From 72f66a97401931382e3d0bc80b50435044268914 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Thu, 29 Jul 2004 04:03:29 +0000 Subject: [PATCH 001/327] Initial revision --- ROMs/M100rom.bin | Bin 0 -> 32768 bytes ROMs/M102rom.bin | Bin 0 -> 32768 bytes ROMs/M200rom.bin | Bin 0 -> 40960 bytes ROMs/N8201rom.bin | Bin 0 -> 32768 bytes ROMs/m100.rom.txt | 2049 +++++++++++++++++++++++++++++++++++++++++++++ ROMs/m102.rom.txt | 2049 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 4098 insertions(+) create mode 100644 ROMs/M100rom.bin create mode 100644 ROMs/M102rom.bin create mode 100644 ROMs/M200rom.bin create mode 100644 ROMs/N8201rom.bin create mode 100644 ROMs/m100.rom.txt create mode 100644 ROMs/m102.rom.txt diff --git a/ROMs/M100rom.bin b/ROMs/M100rom.bin new file mode 100644 index 0000000000000000000000000000000000000000..be7873eec8c27a73df33988c06a454f8cf369594 GIT binary patch literal 32768 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 literal 0 HcmV?d00001 diff --git a/ROMs/M102rom.bin b/ROMs/M102rom.bin new file mode 100644 index 0000000000000000000000000000000000000000..a0b765ee947c894c0ab34480a715dbc533019e61 GIT binary patch literal 32768 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 literal 0 HcmV?d00001 diff --git a/ROMs/M200rom.bin b/ROMs/M200rom.bin new file mode 100644 index 0000000000000000000000000000000000000000..50512ecbc176e7a2b2b63272ae06d0e7c2ad4e2b GIT binary patch literal 40960 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 Date: Thu, 5 Aug 2004 06:45:29 +0000 Subject: [PATCH 002/327] Initial revision --- Darwin.mk | 1 + FreeBSD.mk | 0 GNUmakefile | 31 + Linux.mk | 0 Makefile | 33 + ROM.bin | Bin 0 -> 32768 bytes SunOS.mk | 2 + hex2bin.pl | 30 + src/VirtualT.h | 36 + src/cpu.h | 101 ++ src/disassemble.cpp | 750 ++++++++++++++ src/disassemble.h | 88 ++ src/display.cpp | 1131 +++++++++++++++++++++ src/display.h | 68 ++ src/do_instruct.h | 2327 +++++++++++++++++++++++++++++++++++++++++++ src/doins.c | 85 ++ src/doins.h | 36 + src/io.c | 641 ++++++++++++ src/io.h | 91 ++ src/m100emu.c | 342 +++++++ src/m100emu.h | 52 + src/m100rom.h | 969 ++++++++++++++++++ 22 files changed, 6814 insertions(+) create mode 100644 Darwin.mk create mode 100644 FreeBSD.mk create mode 100644 GNUmakefile create mode 100644 Linux.mk create mode 100644 Makefile create mode 100644 ROM.bin create mode 100644 SunOS.mk create mode 100755 hex2bin.pl create mode 100644 src/VirtualT.h create mode 100644 src/cpu.h create mode 100644 src/disassemble.cpp create mode 100644 src/disassemble.h create mode 100644 src/display.cpp create mode 100644 src/display.h create mode 100644 src/do_instruct.h create mode 100644 src/doins.c create mode 100644 src/doins.h create mode 100644 src/io.c create mode 100644 src/io.h create mode 100644 src/m100emu.c create mode 100644 src/m100emu.h create mode 100644 src/m100rom.h diff --git a/Darwin.mk b/Darwin.mk new file mode 100644 index 0000000..1cb7261 --- /dev/null +++ b/Darwin.mk @@ -0,0 +1 @@ +CFLAGS += -D__unix__ diff --git a/FreeBSD.mk b/FreeBSD.mk new file mode 100644 index 0000000..e69de29 diff --git a/GNUmakefile b/GNUmakefile new file mode 100644 index 0000000..5f4d192 --- /dev/null +++ b/GNUmakefile @@ -0,0 +1,31 @@ +-include $(shell uname).mk +CFLAGS += -O6 +#CFLAGS += -g + +CFLAGS += `fltk-config --cflags --use-images` +LDFLAGS += `fltk-config --ldstaticflags --use-images` + +m100emu: doins.o io.o genwrap.o display.o m100emu.o disassemble.o GNUmakefile + gcc -o m100emu doins.o genwrap.o io.o display.o m100emu.o disassemble.o $(LDFLAGS) + +m100emu.o: m100emu.c cpu.h doins.h display.h genwrap.h do_instruct.h GNUmakefile + gcc $(CFLAGS) -c m100emu.c -o m100emu.o + +doins.o: doins.c doins.h cpu.h io.h m100emu.h GNUmakefile + gcc $(CFLAGS) -c doins.c -o doins.o + +genwrap.o: genwrap.c genwrap.h gen_defs.h GNUmakefile + gcc $(CFLAGS) -c genwrap.c -o genwrap.o + +io.o: cpu.h gen_defs.h io.h io.c GNUmakefile + gcc $(CFLAGS) -c io.c -o io.o + +display.o: display.cpp display.h io.h m100emu.h GNUmakefile + g++ $(CFLAGS) -c display.cpp -o display.o + +disassemble.o: disassemble.cpp m100emu.h disassemble.h m100rom.h io.h GNUmakefile + g++ $(CFLAGS) -c disassemble.cpp -o disassemble.o + +clean: + rm *.o + rm m100emu diff --git a/Linux.mk b/Linux.mk new file mode 100644 index 0000000..e69de29 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..71ed073 --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +#CFLAGS := -O6 -march=pentium -mcpu=pentium +#CFLAGS := -O -pg +#LDFLAGS := -pg +#CFLAGS := -O2 -g +CFLAGS += -O6 + +CFLAGS += `fltk-config --cflags --use-images` +LDFLAGS += `fltk-config --ldstaticflags --use-images` + +m100emu: doins.o io.o genwrap.o display.o m100emu.o disassemble.o Makefile + gcc -o m100emu doins.o genwrap.o io.o display.o m100emu.o disassemble.o $(LDFLAGS) + +m100emu.o: m100emu.c cpu.h doins.h display.h genwrap.h do_instruct.h Makefile + gcc $(CFLAGS) -c m100emu.c -o m100emu.o + +doins.o: doins.c doins.h cpu.h io.h m100emu.h Makefile + gcc $(CFLAGS) -c doins.c -o doins.o + +genwrap.o: genwrap.c genwrap.h gen_defs.h Makefile + gcc $(CFLAGS) -c genwrap.c -o genwrap.o + +io.o: cpu.h gen_defs.h io.h io.c Makefile + gcc $(CFLAGS) -c io.c -o io.o + +display.o: display.cpp display.h io.h m100emu.h Makefile + g++ $(CFLAGS) -c display.cpp -o display.o + +disassemble.o: disassemble.cpp m100emu.h disassemble.h m100rom.h io.h Makefile + g++ $(CFLAGS) -c disassemble.cpp -o disassemble.o + +clean: + rm *.o + rm m100emu diff --git a/ROM.bin b/ROM.bin new file mode 100644 index 0000000000000000000000000000000000000000..be7873eec8c27a73df33988c06a454f8cf369594 GIT binary patch literal 32768 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 literal 0 HcmV?d00001 diff --git a/SunOS.mk b/SunOS.mk new file mode 100644 index 0000000..209d2de --- /dev/null +++ b/SunOS.mk @@ -0,0 +1,2 @@ +CFLAGS += -D__solaris__ +LDFLAGS += -lrt diff --git a/hex2bin.pl b/hex2bin.pl new file mode 100755 index 0000000..2d3128b --- /dev/null +++ b/hex2bin.pl @@ -0,0 +1,30 @@ +#!/usr/bin/perl + +open RAM,"<& RAM.bin"; +open ROM,"<& optROM.bin"; +my $rom=1; +while(<>) { + if(/^:([0-9A-F]{2})([0-9A-F]{4})([0-9A-F]{2})([0-9A-F]*)/) { + my($bytes,$offset,$checkum,$data)=($1,$2,$3,$4); + my $pos=unpack("n",pack("H4",$offset)); + if($pos>=2**15) { + $pos-=2**15; + $rom=0; + } + else { + $rom=1; + } + my $bytes=ord(pack("H2",$bytes)); + my $pack="H".($bytes*2); + my $line=pack($pack,$4); + print "Pos: $pos $pack $bytes\n"; + if($rom) { + sysseek(ROM,$pos,0); + syswrite(ROM,$line); + } + else { + sysseek(RAM,$pos,0); + syswrite(RAM,$line); + } + } +} diff --git a/src/VirtualT.h b/src/VirtualT.h new file mode 100644 index 0000000..ed06c9a --- /dev/null +++ b/src/VirtualT.h @@ -0,0 +1,36 @@ +/* VirtualT.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef _VIRTUALT_H_ +#define _VIRTUALT_H_ + +#define VERSION "0.1" + +#endif diff --git a/src/cpu.h b/src/cpu.h new file mode 100644 index 0000000..7816718 --- /dev/null +++ b/src/cpu.h @@ -0,0 +1,101 @@ +/* cpu.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef _CPU_H_ +#define _CPU_H_ + +#include + +#include "gen_defs.h" + +#define RAMSIZE 32768 +#define ROMSIZE 32768 +#define ADDRESSSPACE 65536 + +extern uchar cpu[14]; +extern uchar memory[ADDRESSSPACE]; +extern uchar sysROM[ROMSIZE]; +extern uchar optROM[ROMSIZE]; + +#define A cpu[0] +#define F cpu[1] +#define B cpu[2] +#define C cpu[3] +#define D cpu[4] +#define E cpu[5] +#define H cpu[6] +#define L cpu[7] +#define PCH cpu[8] +#define PCL cpu[9] +#define SPH cpu[10] +#define SPL cpu[11] + +/* Thoses macros can NOT be set */ +#define AF ((((ushort)A)<<8)|F) +#define BC ((((ushort)B)<<8)|C) +#define DE ((((ushort)D)<<8)|E) +#define HL ((((ushort)H)<<8)|L) +#define PC ((((ushort)PCH)<<8)|PCL) +#define SP ((((ushort)SPH)<<8)|SPL) +#define INCPC {PCL++; if(PCL==0) PCH++;} +#define INCPC2 {PCL+=2; if(PCL<2) PCH++;} +#define INCSP {SPL++; if(SPL==0) SPH++;} +#define INCSP2 {SPL+=2; if(SPL<2) SPH++;} +#define DECPC {PCL--; if(PCL==0xff) PCH--;} +#define DECPC2 {PCL-=2; if(PCL>0xfd) PCH--;} +#define DECSP {SPL--; if(SPL==0xff) SPH--;} +#define DECSP2 {SPL-=2; if(SPL>0xfd) SPH--;} +#define SETPCINS16 {int pc=PC; PCL=memory[pc++]; PCH=memory[pc];} + +#define IM cpu[12] +/* bit 0 is interrupts disabled (1==disabled) */ +#define cpuMISC cpu[13] +#define M memory[HL] +#define INS memory[PC] +#define NXTINS memory[PC+1] +#define INS16 (((int)memory[PC])|(((int)memory[PC+1])<<8)) +#define CF (F&0x01) +#define PF ((F&0x04)>>2) +#define AC ((F&0x10)>>4) +#define ZF ((F&0x40)>>6) +#define SF ((F&0x80)>>7) +#define RST55MASK (IM&0x01) +#define RST65MASK ((IM&0x02)>>1) +#define RST75MASK ((IM&0x04)>>2) +#define INTDIS ((IM&0x08)>>3) +#define RST55PEND ((IM&0x10)>>4) +#define RST65PEND ((IM&0x20)>>5) +#define RST75PEND ((IM&0x40)>>6) +#define SOD ((IM&0x80)>>7) + +#define MEM(x) memory[x] +#define MEM16(x) (((ushort)MEM(x))|((ushort)MEM(x+1))<<8) + +#endif diff --git a/src/disassemble.cpp b/src/disassemble.cpp new file mode 100644 index 0000000..f7a31e3 --- /dev/null +++ b/src/disassemble.cpp @@ -0,0 +1,750 @@ +/* disassemble.cpp */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "m100emu.h" +#include "disassemble.h" +#include "m100rom.h" +#include "io.h" + +Fl_Window *gpDis; + +// Callback routine for the close box of the Disassembler window +void close_cb(Fl_Widget* w, void*) +{ + if (gpDis != NULL) + { + gpDis->hide(); + delete gpDis; + gpDis = 0; + } +} + +// Table of OPCODE +char * VTDis::m_StrTable[256] = { + "NOP", "LXI B,", "STAX B", "INX B", "INR B", "DCR B", "MVI B,", "RLC", + "-", "DAD B", "LDAX B", "DCX B", "INR C", "DCR C", "MVI C,", "RRC", + "-", "LXI D,", "STAX D", "INX D", "INR D", "DCR D", "MVI D,", "RAL", + "-", "DAD D", "LDAX D", "DCX D", "INR E", "DCR E", "MVI E,", "RAR", + "RIM", "LXI H,", "SHLD ", "INX H", "INR H", "DCR H", "MVI H,", "DAA", + "-", "DAD H", "LHLD ", "DCX H", "INR L", "DCR L", "MVI L,", "CMA", + "SIM", "LXI SP,", "STA ", "INX SP", "INR M", "DCR M", "MVI M,", "STC", + "-", "DAD SP", "LDA ", "DCX SP", "INR A", "DCR A", "MVI A,", "CMC", + "MOV B,B", "MOV B,C", "MOV B,D", "MOV B,E", "MOV B,H", "MOV B,L", "MOV B,M", "MOV B,A", + "MOV C,B", "MOV C,C", "MOV C,D", "MOV C,E", "MOV C,H", "MOV C,L", "MOV C,M", "MOV C,A", + "MOV D,B", "MOV D,C", "MOV D,D", "MOV D,E", "MOV D,H", "MOV D,L", "MOV D,M", "MOV D,A", + "MOV E,B", "MOV E,C", "MOV E,D", "MOV E,E", "MOV E,H", "MOV E,L", "MOV E,M", "MOV E,A", + "MOV H,B", "MOV H,C", "MOV H,D", "MOV H,E", "MOV H,H", "MOV H,L", "MOV H,M", "MOV H,A", + "MOV L,B", "MOV L,C", "MOV L,D", "MOV L,E", "MOV L,H", "MOV L,L", "MOV L,M", "MOV L,A", + "MOV M,B", "MOV M,C", "MOV M,D", "MOV M,E", "MOV M,H", "MOV M,L", "HLT", "MOV M,A", + "MOV A,B", "MOV A,C", "MOV A,D", "MOV A,E", "MOV A,H", "MOV A,L", "MOV A,M", "MOV A,A", + "ADD B", "ADD C", "ADD D", "ADD E", "ADD H", "ADD L", "ADD M", "ADD A", + "ADC B", "ADC C", "ADC D", "ADC E", "ADC H", "ADC L", "ADC M", "ADC A", + "SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB M", "SUB A", + "SBB B", "SBB C", "SBB D", "SBB E", "SUB H", "SBB L", "SBB M", "SBB A", + "ANA B", "ANA C", "ANA D", "ANA E", "ANA H", "ANA L", "ANA M", "ANA A", + "XRA B", "XRA C", "XRA D", "XRA E", "XRA H", "XRA L", "XRA M", "XRA A", + "ORA B", "ORA C", "ORA D", "ORA E", "ORA H", "ORA L", "ORA M", "ORA A", + "CMP B", "CMP C", "CMP D", "CMP E", "CMP H", "CMP L", "CMP M", "CMP A", + "RNZ", "POP B", "JNZ ", "JMP ", "CNZ ", "PUSH B", "ADI ", "RST 0", + "RZ", "RET", "JZ ", "-", "CZ ", "CALL ", "ACI ", "RST 1", + "RNC", "POP D", "JNC ", "OUT ", "CNC ", "PUSH D", "SUI ", "RST 2", + "RC", "-", "JC ", "IN ", "CC ", "-", "SBI ", "RST 3", + "RPO", "POP H", "JPO ", "XTHL", "CPO ", "PUSH H", "ANI ", "RST 4", + "RPE", "PCHL", "JPE ", "XCHG", "CPE ", "-", "XRI ", "RST 5", + "RP", "POP PSW", "JP ", "DI", "CP ", "PUSH PSW", "ORI ", "RST 6", + "RM", "SPHL", "JM ", "EI", "CM ", "-", "CPI ", "RST 7" +}; + +// Table indicating length of each opcode +unsigned char VTDis::m_LenTable[256] = { + 0,2,0,0,0,0,1,0, + 0,0,0,0,0,0,1,0, + 0,2,0,0,0,0,1,0, + 0,0,0,0,0,0,1,0, + 0,2,2,0,0,0,1,0, + 0,0,2,0,0,0,1,0, + 0,2,2,0,0,0,1,0, + 0,0,2,0,0,0,1,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,2,2,2,0,1,0, + 0,0,2,0,2,2,1,0, + 0,0,2,1,2,0,1,0, + 0,0,2,1,2,0,1,0, + 0,0,2,0,2,0,1,0, + 0,0,2,0,2,0,1,0, + 0,0,2,0,2,0,1,0, + 0,0,2,0,2,0,1,0 +}; + + +// Menu items for the disassembler +Fl_Menu_Item gDis_menuitems[] = { + { "&File", 0, 0, 0, FL_SUBMENU }, + { "Open...", 0, 0, 0 }, + { "Save...", 0, 0, 0, FL_MENU_DIVIDER }, + { "Close", FL_CTRL + 'q', close_cb, 0 }, + { 0 }, + + { "&Tools", 0, 0, 0, FL_SUBMENU }, + { "CPU Registers", 0, 0 }, + { "Assembler", 0, 0 }, + { "Disassembler", 0, 0 }, + { "Debugger", 0, 0 }, + { "Memory Editor", 0, 0 }, + { "Peripheral Devices", 0, 0 }, + { "Simulation Log Viewer", 0, 0 }, + { "Model T File Viewer", 0, 0 }, + { "BASIC Debugger", 0, 0 }, + { 0 }, + + { 0 } +}; + + + +/* +======================================================= +Menu Item Callbacks +======================================================= +*/ +void disassembler_cb(Fl_Widget* w, void*) { + + if (gpDis == NULL) + { + // Create a new window for the disassembler + gpDis = new Fl_Window(600, 400 , "Disassembler"); + gpDis->callback(close_cb); + + // Create a menu for the new window. + Fl_Menu_Bar *m = new Fl_Menu_Bar(0, 0, 600, MENU_HEIGHT-2); +// gpDisp = new T100_Disp(0, MENU_HEIGHT, 240*MultFact + 90*DisplayMode, 64*MultFact + 50*DisplayMode); + m->menu(gDis_menuitems); + + // Create a Text Editor to show/edit the disassembled text + Fl_Text_Editor* td = new Fl_Text_Editor(0, MENU_HEIGHT, 600, 400-MENU_HEIGHT); + + // Create a Text Buffer for the Text Editor to work with + Fl_Text_Buffer* tb = new Fl_Text_Buffer(); + td->buffer(tb); + + // Show the Disassembling text to indicate activity + tb->append("\n\n\n Disassembling..."); + td->textfont(FL_COURIER); + + // Create a Disassembler + VTDis *pDisassembler = new VTDis(); + + // Assign the RomDescription table for the model being emulated + if (gModel == MODEL_M100) + pDisassembler->m_pRom = &gM100_Desc; + + // Give the disassembler the text editor to dump it's data into + pDisassembler->SetTextViewer(td); + + // Give the disassembler something to disassemble + pDisassembler->CopyIntoMem(memory, 32788); + gpDis->end(); + gpDis->show(); + + // Show the new window + Fl::wait(); + + // Disassemble the code (this should be moved later when dissasembly + // of .CO programs is supported) + pDisassembler->Disassemble(); + } + else + { + } +} + +/* +======================================================= +Disassembler Class Definition +======================================================= +*/ +VTDis::VTDis() +{ + m_StartAddress = 0; + m_EndAddress = 32767; +} + +void VTDis::SetTextViewer(Fl_Text_Editor *pTextViewer) +{ + m_pTextViewer = pTextViewer; +} + +void VTDis::Disassemble() +{ + int c; + int x, i; + int len; + int table; + char line[200]; + char arg[6]; + int addr; + int rst7 = 0; + int rst1 = 0; + unsigned char opcode; + unsigned char op_len; + Fl_Text_Buffer* tb; + + + tb = new Fl_Text_Buffer; + for (c = m_StartAddress; c <= m_EndAddress; c++) + { + // Search for C in the function table + x = 0; + while (m_pRom->pFuns[x].addr != -1) + { + if (m_pRom->pFuns[x].addr == c) + { + strcpy(line, "\n; ======================================================\n; "); + strcat(line, m_pRom->pFuns[x].desc); + strcat(line, "\n; ======================================================\n"); + // Add line to Edit Buffer + tb->append(line); + break; + } + + x++; + } + + // Check if address is a table instead of code + x = 0; + table = 0; + + // Check if last instruction was RST7 (that means this byte is a DB) + if (rst7 == 1) + { + sprintf(line, "%04XH DB %02XH\n", c, m_memory[c]); + tb->append(line); + rst7 = 0; + continue; + } + + // Check if last instruction was RST1 (that means this byte is a DB) + if (rst1 == 1) + { + sprintf(line, "%04XH DB %02XH\n", c, m_memory[c]); + tb->append(line); + rst1 = 0; + continue; + } + + // Loop though the array of table definitions for the current address + while (m_pRom->pTables[x].addr != -1) + { + // Current address found? + if (m_pRom->pTables[x].addr == c) + { + table = 1 ; + // Modified strings are those that start with a 0x80 and ends + // when the next string is found (the next 0x80). All the + // BASIC keywords are stored this way + if (m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING) + { + int next; + int last = c + m_pRom->pTables[x].size; + int str_active = 0; + for (next = c; next < last; next++) + { + if ((m_memory[next] & 0x80) && (str_active)) + { + if ((m_memory[next-1] & 0x80) == 0) + strcat(line, "\""); + strcat(line, "\n"); + tb->append(line); + line[0]=0; + str_active = 0; + } + if (!str_active) + { + sprintf(line, "%04XH DB 80H or '%c'", next, m_memory[next] & 0x7F); + str_active = 1; + if ((m_memory[next+1] & 0x80) == 0) + strcat(line, ",\""); + } + else + { + sprintf(arg, "%c", m_memory[next]); + strcat(line, arg); + } + + if (next + 1 == last) + { + if (m_memory[next-1] & 0x80 == 0) + strcat(line, "\""); + strcat(line, "\n\n"); + tb->append(line); + line[0] = 0; + } + } + } + // A string is one that ends with NULL (0x00) + else if (m_pRom->pTables[x].type == TABLE_TYPE_STRING) + { + int next; + int last = c + m_pRom->pTables[x].size; + int str_active = 0; + int quote_active = 0; + for (next = c; next < last; next++) + { + if ((m_memory[next] == 0) && (str_active)) + { + if (quote_active) + strcat(line, "\""); + strcat(line, ",00H\n"); + tb->append(line); + line[0]=0; + str_active = 0; + quote_active = 0; + } + else if (!str_active) + { + sprintf(line, "%04XH DB \"%c", next, m_memory[next]); + quote_active = 1; + str_active = 1; + } + else + { + if (iscntrl(m_memory[next])) + { + if (quote_active) + { + strcat(line, "\""); + quote_active = 0; + } + sprintf(arg, ",%02XH", m_memory[next]); + } + else + sprintf(arg, "%c", m_memory[next]); + strcat(line, arg); + } + if ((next+1 == last) && (m_memory[next] != 0)) + { + strcat(line, "\n"); + tb->append(line); + line[0]=0; + str_active = 0; + quote_active = 0; + } + } + } + // CTRL_DELIM tables are string that have a non-ASCII byte + // between them + else if (m_pRom->pTables[x].type == TABLE_TYPE_CTRL_DELIM) + { + int next; + int last = c + m_pRom->pTables[x].size; + int str_active = 0; + int quote_active = 0; + for (next = c; next < last; next++) + { + if ((m_memory[next] > 0x7E) && (str_active)) + { + sprintf(arg, "\",%02XH\n", m_memory[next]); + strcat(line, arg); + tb->append(line); + line[0]=0; + str_active = 0; + continue; + } + if (!str_active) + { + if (m_memory[next] > 0x7E) + { + sprintf(line, "%04XH DB %02XH\n", next, m_memory[next]); + tb->append(line); + } + else + { + sprintf(line, "%04XH DB \"%c", next, m_memory[next]); + str_active = 1; + } + } + else + { + sprintf(arg, "%c", m_memory[next]); + strcat(line, arg); + } + } + } + // A JUMP table is one that contains 16 bit address in a table + else if (m_pRom->pTables[x].type == TABLE_TYPE_JUMP) + { + int next; + int last = c + m_pRom->pTables[x].size; + int count = 0; + for (next = c; next < last; next += 2) + { + if (count == 0) + sprintf(line, "%04XH DW ", next); + + sprintf(arg, "%04XH", m_memory[next] | (m_memory[next+1] << 8)); + strcat(line, arg); + if ((next+2 != last) && (count != 3)) + strcat(line, ","); + else + { + strcat(line, "\n"); + if (next+2 == last) + strcat(line, "\n"); + } + + if ((count == 3) || (next+2 == last)) + { + tb->append(line); + count = 0; + } + else + count++; + } + } + // A 2BYTE table is one with entries that are exactly 2 bytes + // This is used for the BASIC error message text + else if (m_pRom->pTables[x].type == TABLE_TYPE_2BYTE) + { + int next; + int last = c + m_pRom->pTables[x].size; + for (next = c; next < last; next += 2) + { + sprintf(line, "%04XH DB \"%c%c\"\n", next, m_memory[next], m_memory[next+1]); + tb->append(line); + } + } + // A 3BYTE table is one with entries that are exactly 3 bytes + // This is used for the Day of week and Month text (Mon, Tue, Jan, Feb) + else if (m_pRom->pTables[x].type == TABLE_TYPE_3BYTE) + { + int next; + int last = c + m_pRom->pTables[x].size; + for (next = c; next < last; next += 3) + { + sprintf(line, "%04XH DB \"%c%c%c\"\n", next, m_memory[next], m_memory[next+1], + m_memory[next+2]); + tb->append(line); + } + } + // A BYTE_LOOKUP is a table that has a single "search" byte with a + // 2 byte address following it + else if (m_pRom->pTables[x].type == TABLE_TYPE_BYTE_LOOKUP) + { + int next; + int last = c + m_pRom->pTables[x].size; + for (next = c; next < last; next += 3) + { + if (iscntrl(m_memory[next])) + sprintf(line, "%04XH DB %02XH\n%04XH DW %04XH\n", next, m_memory[next], + next+1, m_memory[next+1] | (m_memory[next+2] << 8)); + else + sprintf(line, "%04XH DB '%c'\n%04XH DW %04XH\n", next, m_memory[next], + next+1, m_memory[next+1] | (m_memory[next+2] << 8)); + tb->append(line); + } + } + // A 4BYTE_CMD table has 4 ASCII bytes (the command) followed by a + // 2 byte address + else if (m_pRom->pTables[x].type == TABLE_TYPE_4BYTE_CMD) + { + int next; + int last = c + m_pRom->pTables[x].size; + for (next = c; next < last; next += 6) + { + sprintf(line, "%04XH DB \"%c%c%c%c\"\n", next, m_memory[next], + m_memory[next+1], m_memory[next+2], m_memory[next+3]); + tb->append(line); + sprintf(line, "%04XH DW %04XH\n", next+4, m_memory[next+4] | + (m_memory[next+5] << 8)); + tb->append(line); + } + } + // A catalog table is just that. One that contains ROM catalog entries + else if (m_pRom->pTables[x].type == TABLE_TYPE_CATALOG) + { + int next; + int last = c + m_pRom->pTables[x].size; + for (next = c; next < last; next += 11) + { + sprintf(line, "%04XH DB %02XH\n", next, m_memory[next]); + tb->append(line); + sprintf(line, "%04XH DW %04XH\n", next+1, m_memory[next+1] | + (m_memory[next+2] << 8)); + tb->append(line); + + if (m_memory[next+3] == 0) + sprintf(line, "%04XH DB %02XH,\"%c%c%c%c%c%c\",%02XH\n", next+3, m_memory[next+3], + m_memory[next+4], m_memory[next+5], m_memory[next+6], m_memory[next+7], + m_memory[next+8], m_memory[next+9], m_memory[next+10]); + else + sprintf(line, "%04XH DB \"%c%c%c%c%c%c%c\",%02XH\n", next+3, m_memory[next+3], + m_memory[next+4], m_memory[next+5], m_memory[next+6], m_memory[next+7], + m_memory[next+8], m_memory[next+9], m_memory[next+10]); + tb->append(line); + } + } + // A CODE table is one where bytes are simply represented with + // a DB directive. Bytes are split into lines with 8 bytes per line + else if (m_pRom->pTables[x].type == TABLE_TYPE_CODE) + { + int next; + int last = c + m_pRom->pTables[x].size; + int count = 0; + for (next = c; next < last; next++) + { + if (count == 0) + sprintf(line, "%04XH DB ", next); + + sprintf(arg, "%02XH", m_memory[next]); + strcat(line, arg); + if ((next+1 != last) && (count != 7)) + strcat(line, ","); + else + { + strcat(line, "\n"); + if (next+1 == last) + { + strcat(line, "\n"); + tb->append(line); + line[0] = 0; + } + } + + if (count == 7) + { + tb->append(line); + line[0] = 0; + count = 0; + } + else + count++; + } + } + // Add line to Edit Buffer +// tb->append(line); + c += m_pRom->pTables[x].size-1; + break; + } + + x++; + } + + // Was this address identified as a table? If so, don't disassemble it! + if (table) + continue; + + // Get opcode from memory + opcode = m_memory[c]; + + // Determine length of this opcode + op_len = m_LenTable[opcode] & 0x03; + + // Print the address and opcode value to the temporary line buffer + sprintf(line, "%04XH (%02XH) ", c, opcode); + + // Print the opcode text to the temp line buffer + strcat(line, m_StrTable[opcode]); + + // Check if this opcode has a single byte argument + if (op_len == 1) + { + // Single byte argument + sprintf(arg, "%02XH", m_memory[c+1]); + strcat(line, arg); + } + + // Check if this opcode as a 2 byte argument + else if (op_len == 2) + { + // Double byte argument + addr = m_memory[c+1] | (m_memory[c+2] << 8); + sprintf(arg, "%04XH", addr); + strcat(line, arg); + } + + // Calculate # spaces to add for fixed line len (make comments line up) + len = 28 - strlen(line); + + // Add comments for known addresses. Opcodes less that 128 are Variable + // spaces (these opcodes are LXI, LHLD, etc.) + if ((op_len == 2) && (opcode < 128)) + { + x = 0; + while (m_pRom->pVars[x].addr != -1) + { + if (m_pRom->pVars[x].addr == addr) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; "); + strcat(line, m_pRom->pVars[x].desc); + break; + } + + x++; + } + } + // Add comments for known function call addresses. Opcodes 128 and greater + // are CALLs and JMPs + if ((op_len == 2) && (opcode > 128)) + { + x = 0; + while (m_pRom->pFuns[x].addr != -1) + { + if (m_pRom->pFuns[x].addr == addr) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; "); + strcat(line, m_pRom->pFuns[x].desc); + break; + } + + x++; + } + } + + // Handle RST 1 Commenting + if (opcode == 0xCF) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; Compare next byte with M"); + } + // Handle RST 2 Commenting + if (opcode == 0xD7) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; Get next non-white char from M"); + } + // Handle RST 3 Commenting + if (opcode == 0xDF) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; Compare DE and HL"); + } + // Handle RST 4 Commenting + if (opcode == 0xE7) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; Send character in A to screen/printer"); + } + // Handle RST 5 Commenting + if (opcode == 0xEF) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; Determine type of last var used"); + } + // Handle RST 6 Commenting + if (opcode == 0xF7) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; Get sign of FAC1"); + } + // Handle RST 7 Commenting + if (opcode == 0xFF) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; Jump to RST 38H Vector entry of following byte"); + } + + // Increment memory counter by opcode length + c += op_len; + + // Finish off the line + strcat(line, "\n"); + + // Add a blank line for JMP, CALL, and RET to provide routine separation + if (opcode == 195 || opcode == 201 || opcode == 0xE9) + { + strcat(line, "\n"); + } + + // Check if opcode is a rst7 + if (opcode == 0xFF) + rst7 = 1; + + // Check if opcode is a rst1 + if (opcode == 0xCF) + rst1 = 1; + + + // Add line to Edit Buffer + tb->append(line); + } + + // Display the text buffer in the text editor + Fl_Text_Buffer* old_tb = m_pTextViewer->buffer(); + m_pTextViewer->buffer(tb); + delete old_tb; +} + + +void VTDis::CopyIntoMem(unsigned char *ptr, int len) +{ + int c; + + for (c = 0; c < len; c++) + { + m_memory[c] = ptr[c]; + } +} diff --git a/src/disassemble.h b/src/disassemble.h new file mode 100644 index 0000000..427c08d --- /dev/null +++ b/src/disassemble.h @@ -0,0 +1,88 @@ +/* disassemble.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef _DISASSEMBLE_H_ +#define _DISASSEMBLE_H_ + +#include "display.h" + +typedef struct Std_ROM_Addresses { + int addr; + char* desc; +} Std_ROM_Addresses_t; + +typedef struct Std_ROM_Table { + int addr; + int size; + char type; +} Std_ROM_Table_t; + +typedef struct RomDescription { + Std_ROM_Table_t *pTables; + Std_ROM_Addresses_t *pVars; + Std_ROM_Addresses_t *pFuns; +} RomDescription_t; + + +class VTDis +{ +public: + int m_EndAddress; + void CopyIntoMem(unsigned char * ptr, int len); + unsigned char m_memory[65536]; + int m_StartAddress; + class Fl_Text_Editor* m_pTextViewer; + RomDescription_t *m_pRom; + + VTDis(); + + void Disassemble(); + void SetTextViewer(class Fl_Text_Editor* pTextViewer); + +protected: + static char* m_StrTable[256]; + static unsigned char m_LenTable[256]; + +}; + +enum { + TABLE_TYPE_STRING + ,TABLE_TYPE_JUMP + ,TABLE_TYPE_CODE + ,TABLE_TYPE_MODIFIED_STRING + ,TABLE_TYPE_2BYTE + ,TABLE_TYPE_3BYTE + ,TABLE_TYPE_CTRL_DELIM + ,TABLE_TYPE_BYTE_LOOKUP + ,TABLE_TYPE_4BYTE_CMD + ,TABLE_TYPE_CATALOG +}; + +#endif \ No newline at end of file diff --git a/src/display.cpp b/src/display.cpp new file mode 100644 index 0000000..ae0be33 --- /dev/null +++ b/src/display.cpp @@ -0,0 +1,1131 @@ +/* display.cpp */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#include +#include + +#include "VirtualT.h" +#include "display.h" +#include "m100emu.h" +#include "io.h" + +Fl_Window *MainWin; +T100_Disp *gpDisp; +Fl_Box *gpCode, *gpGraph, *gpKey, *gpSpeed, *gpCaps, *gpKeyInfo; +Fl_Menu_Bar *Menu; + +int MultFact = 3; +int DisplayMode = 1; +int SolidChars = 0; + +int gRectsize = 2; +int gXoffset; +int gYoffset; + +char *gSpKeyText[] = { + "SHIFT", + "CTRL", + "GRAPH", + "CODE", + "", + "CAPS", + "", + "PAUSE", + + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + + "SPACE", + "BKSP", + "TAB", + "ESC", + "PASTE", + "LABEL", + "PRINT", + "ENTER", + + "", + "", + "", + "", + "LEFT", + "RIGHT", + "UP", + "DOWN" +}; + + +/* +======================================================= +External Menu Item Callbacks +======================================================= +*/ +void disassembler_cb(Fl_Widget* w, void*); + +void rspeed(Fl_Widget* w, void*) +{ + fullspeed=0; +} +void fspeed(Fl_Widget* w, void*) +{ + fullspeed=1; +} +void close_disp_cb(Fl_Widget* w, void*) +{ + if (gpDisp != NULL) + { + gExitApp = 1; + } +} + +void resize_window() +{ + MainWin->resize(MainWin->x(), MainWin->y(), 240*MultFact + + 90*DisplayMode+2,64*MultFact + 50*DisplayMode + MENU_HEIGHT + 22); + Menu->resize(0, 0, 240*MultFact + 90*DisplayMode+2, MENU_HEIGHT-2); + gpDisp->resize(0, MENU_HEIGHT, 240*MultFact + 90*DisplayMode+2, 64*MultFact + + 50*DisplayMode+2); + gpGraph->resize(0, MENU_HEIGHT+64*MultFact + 50*DisplayMode+2, 60, 20); + gpCode->resize(60, MENU_HEIGHT+64*MultFact + 50*DisplayMode+2, 60, 20); + gpCaps->resize(120, MENU_HEIGHT+64*MultFact + 50*DisplayMode+2, 60, 20); + gpKey->resize(180, MENU_HEIGHT+64*MultFact + 50*DisplayMode+2, 120, 20); + gpSpeed->resize(300, MENU_HEIGHT+64*MultFact + 50*DisplayMode+2, 60, 20); + gpKeyInfo->resize(360, MENU_HEIGHT+64*MultFact + 50*DisplayMode+2, + MainWin->w()-360, 20); + + gRectsize = MultFact - (1 - SolidChars); + if (gRectsize == 0) + gRectsize = 1; + gXoffset = 45*DisplayMode+1; + gYoffset = 25*DisplayMode + MENU_HEIGHT+1; + Fl::check(); + MainWin->redraw(); +} + +/* +======================================================= +Menu Item Callbacks +======================================================= +*/ +void cb_1x(Fl_Widget* w, void*) +{ + MultFact = 1; + resize_window(); +} +void cb_2x(Fl_Widget* w, void*) +{ + MultFact = 2; + resize_window(); +} +void cb_3x(Fl_Widget* w, void*) +{ + MultFact = 3; + resize_window(); +} +void cb_4x(Fl_Widget* w, void*) +{ + MultFact = 4; + resize_window(); +} +void cb_framed(Fl_Widget* w, void*) +{ + DisplayMode ^= 1; + resize_window(); +} +void cb_solidchars (Fl_Widget* w, void*) +{ + SolidChars ^= 1; + resize_window(); +} + +void cb_reset (Fl_Widget* w, void*) +{ + int a=fl_ask("Really Reset ?"); + + if(a==1) + resetcpu(); +} + +void cb_help (Fl_Widget* w, void*) +{ +// Fl_Help_Dialog *HelpWin; + +// HelpWin = new Fl_Help_Dialog(); +// HelpWin->load("./help.htm"); +// HelpWin->show(); + +} + +void cb_about (Fl_Widget* w, void*) +{ + + Fl_Window* o = new Fl_Window(420, 340); + + { Fl_Box* o = new Fl_Box(20, 0, 325, 95, "Virtual T"); + o->labelfont(11); + o->labelsize(80); + } + { Fl_Box* o = new Fl_Box(40, 105, 305, 40, "A Tandy Model 100/102/200 Emulator"); + o->labelfont(8); + o->labelsize(24); + } + { Fl_Box* o = new Fl_Box(20, 150, 335, 35, "written by: "); + o->labelfont(8); + o->labelsize(18); + } + { Fl_Box* o = new Fl_Box(20, 170, 335, 35, "Stephen Hurd"); + o->labelfont(8); + o->labelsize(18); + } + { Fl_Box* o = new Fl_Box(15, 190, 340, 35, "Ken Pettit"); + o->labelfont(8); + o->labelsize(18); + } + { Fl_Box* o = new Fl_Box(15, 210, 340, 35, "Jerome Vernet"); + o->labelfont(8); + o->labelsize(18); + } + { Fl_Box* o = new Fl_Box(85, 255, 195, 25, "V "VERSION); + o->labelfont(8); + o->labelsize(18); + } + { Fl_Box* o = new Fl_Box(25, 295, 320, 25, "This program may be distributed freely "); + o->labelfont(8); + o->labelsize(16); + } + { Fl_Box* o = new Fl_Box(25, 315, 320, 25, "under the terms of the BSD license"); + o->labelfont(8); + o->labelsize(16); + } + { Fl_Box* o = new Fl_Box(10, 75, 320, 20, "in FLTK"); + o->labelfont(8); + o->labelsize(18); + } + o->end(); + o->show(); +} + +void cb_LoadRam (Fl_Widget* w, void*) +{ + Fl_File_Chooser *FileWin; + + FileWin = new Fl_File_Chooser(".","*.bin",1,"Load RAM file"); + FileWin->preview(0); + FileWin->show(); + +} + +void cb_SaveRam (Fl_Widget* w, void*) +{ + Fl_File_Chooser *FileWin; + + FileWin = new Fl_File_Chooser(".","*.bin",1,"Save RAM file"); + FileWin->preview(0); + // FileWin.value(0)="RAM.bin" + FileWin->show(); + +} + + + +void cb_LoadOptRom (Fl_Widget* w, void*) +{ + Fl_File_Chooser *FileWin; + + FileWin = new Fl_File_Chooser(".","*.bin",1,"Load Optional ROM file"); + FileWin->preview(0); + FileWin->show(); +} + + +T100_Disp::T100_Disp(int x, int y, int w, int h) : + Fl_Widget(x, y, w, h) +{ + int driver; + + for (driver = 0; driver < 10; driver++) + { + for (int c = 0; c < 256; c++) + lcd[driver][c] = 0; + } + + m_MyFocus = 0; +} + +// Draw the black pixels on the LCD +void drawpixel(int x, int y, int color) +{ + // fl_color(color); + if (color) + + fl_rectf(x*MultFact + gXoffset,y*MultFact + gYoffset,gRectsize,gRectsize); +} + + +// Redraw the whole LCD +void T100_Disp::draw() +{ + int c; + int width; + int x_pos, inc, start, y_pos; + int xl_start, xl_end, xr_start, xr_end; + + // Draw gray "screen" + fl_color(FL_GRAY); + fl_rectf(x(),y(),w(),h()); + + if (DisplayMode == 1) + { + // Color for outer border + fl_color(FL_WHITE); + + // Draw border along the top + fl_rectf(x(),y(),240*MultFact+92,5); + + // Draw border along the bottom + fl_rectf(x(),y()+64*MultFact+45,240*MultFact+92,5); + + // Draw border along the left + fl_rectf(x(),y()+5,5,64*MultFact+42); + + // Draw border along the right + fl_rectf(x()+240*MultFact+87,y()+5,5,64*MultFact+42); + + + // Color for inner border + fl_color(FL_BLACK); + + // Draw border along the top + fl_rectf(x()+5,y()+5,240*MultFact+42,20); + + // Draw border along the bottom + fl_rectf(x()+5,y()+64*MultFact+27,240*MultFact+82,20); + + // Draw border along the left + fl_rectf(x()+5,y()+5,40,64*MultFact+32); + + // Draw border along the right + fl_rectf(x()+240*MultFact+47,y()+5,40,64*MultFact+32); + + + width = w() - 90; + inc = width/8; + start = 28 + width/16 + (4-MultFact)*2; + fl_color(FL_WHITE); + fl_font(FL_COURIER,12); + char text[3] = "F1"; + y_pos = h()+20; + xl_start = 2*MultFact; + xl_end = 7*MultFact; + + xr_start = 12 + 2*MultFact; + xr_end = 12 + 7*MultFact; + + // Draw function key labels + for (c = 0; c < 8; c++) + { + // Draw text + x_pos = start + inc*c; + text[1] = c + '1'; + fl_draw(text, x_pos, y_pos); + + if (MultFact != 1) + { + // Draw lines to left + fl_line(x_pos - xl_start, y_pos-2, x_pos - xl_end, y_pos-2); + fl_line(x_pos - xl_start, y_pos-7, x_pos - xl_end, y_pos-7); + fl_line(x_pos - xl_end, y_pos-2, x_pos - xl_end, y_pos-7); + + // Draw lines to right + fl_line(x_pos + xr_start, y_pos-2, x_pos + xr_end, y_pos-2); + fl_line(x_pos + xr_start, y_pos-7, x_pos + xr_end, y_pos-7); + fl_line(x_pos + xr_end, y_pos-2, x_pos + xr_end, y_pos-7); + } + } + } + + int x=0; + int y=0; + int driver, col, row; + uchar value; + + for (driver = 0; driver < 10; driver++) + { + for (row = 0; row < 4; row++) + { + for (col = 0; col < 50; col++) + { + if (((driver == 4) || (driver == 9)) && ((col & 0x3F) >= 40)) + continue; + + x=(driver % 5) * 50; + x+=col; + + y = row * 8; + if (driver > 4) + y += 32; + + if (x > 240) + x = x + 1; + value = lcd[driver][row*64+col]; + + // Erase line so it is grey, then fill in with black where needed + fl_color(FL_GRAY); + fl_rectf(x*MultFact + gXoffset,y*MultFact + + gYoffset,gRectsize,8*MultFact); + fl_color(FL_BLACK); + + // Draw the black pixels + drawpixel(x,y++, value&0x01); + drawpixel(x,y++, value&0x02); + drawpixel(x,y++, value&0x04); + drawpixel(x,y++, value&0x08); + drawpixel(x,y++, value&0x10); + drawpixel(x,y++, value&0x20); + drawpixel(x,y++, value&0x40); + drawpixel(x,y++, value&0x80); + } + } + } +} + +void T100_Disp::SetByte(int driver, int col, uchar value) +{ + int x; + int y; + +// if (driver < 10) +// { + // Check if LCD already has the value being requested + if (lcd[driver][col] == value) + return; + + // Load new value into lcd "RAM" + lcd[driver][col] = value; + + // Check if value is an LCD command + if ((col&0x3f) > 49) + return; + + // Check if drawing to unused portion of right-most drivers +// if (((driver == 4) || (driver == 9)) && ((col&0x3F) % 50 >= 40)) +// return; + + // Calculate X position of byte + x=(driver % 5) * 50 + (col&0x3F); + + // Calcluate y position of byte + y = ((col & 0xC0) >> 6) * 8; + if (driver > 4) + y += 32; + + // Set the display + gpDisp->window()->make_current(); + + fl_color(FL_GRAY); + fl_rectf(x*MultFact + gXoffset,y*MultFact + +gYoffset,gRectsize,8*MultFact); + fl_color(FL_BLACK); + + // Draw each pixel of byte + drawpixel(x,y++,value&0x01); + drawpixel(x,y++,(value&0x02)>>1); + drawpixel(x,y++,(value&0x04)>>2); + drawpixel(x,y++,(value&0x08)>>3); + drawpixel(x,y++,(value&0x10)>>4); + drawpixel(x,y++,(value&0x20)>>5); + drawpixel(x,y++,(value&0x40)>>6); + drawpixel(x,y++,(value&0x80)>>7); + + // Update display +// Fl::wait(0); +// } +} + + +Fl_Menu_Item menuitems[] = { + { "&File", 0, 0, 0, FL_SUBMENU }, + { "Load file from HD", 0, 0, 0 }, + { "Save file to HD", 0, 0, 0, FL_MENU_DIVIDER }, + { "Load RAM...", 0, cb_LoadRam, 0 }, + { "Save RAM...", 0, cb_SaveRam, 0, FL_MENU_DIVIDER }, + { "E&xit", FL_CTRL + 'q', close_disp_cb, 0 }, + { 0 }, + + { "&Emulation", 0, 0, 0, FL_SUBMENU }, + { "Reset",0, cb_reset, 0,FL_MENU_DIVIDER }, + { "Model", 0, 0, 0, FL_SUBMENU } , + { "M100", 0, 0, (void *) 1, FL_MENU_RADIO | FL_MENU_VALUE }, + { "M102", 0, 0, (void *) 2, FL_MENU_RADIO }, + { "T200", 0, 0, (void *) 3, FL_MENU_RADIO }, + { 0 }, + { "Speed", 0, 0, 0, FL_SUBMENU }, + { "2.4 MHz", 0, rspeed, (void *) 1, FL_MENU_RADIO | FL_MENU_VALUE }, + { "Max Speed", 0, fspeed, (void *) 1, FL_MENU_RADIO }, + { 0 }, + { "Display", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER}, + { "1x", 0, cb_1x, (void *) 1, FL_MENU_RADIO }, + { "2x", 0, cb_2x, (void *) 2, FL_MENU_RADIO }, + { "3x", 0, cb_3x, (void *) 3, FL_MENU_RADIO | FL_MENU_VALUE}, + { "4x", 0, cb_4x, (void *) 4, FL_MENU_RADIO | FL_MENU_DIVIDER}, + { "Framed", 0, cb_framed, (void *) 1, FL_MENU_TOGGLE|FL_MENU_VALUE }, + { "Solid Chars", 0, cb_solidchars, (void *) 1, FL_MENU_TOGGLE}, + { 0 }, + { "Peripheral Setup...", 0, 0, 0, FL_MENU_DIVIDER }, + { "Load Optional ROM...", 0, cb_LoadOptRom }, + { 0 }, + + { "&Tools", 0, 0, 0, FL_SUBMENU }, + { "CPU Registers", 0, 0 }, + { "Assembler", 0, 0 }, + { "Disassembler", 0, disassembler_cb }, +// { "Disassembler", 0, 0 }, + { "Debugger", 0, 0 }, + { "Memory Editor", 0, 0 }, + { "Peripheral Devices", 0, 0 }, + { "Simulation Log Viewer", 0, 0 }, + { "Model T File Viewer", 0, 0 }, + { "BASIC Debugger", 0, 0 }, + { 0 }, + { "&Help", 0, 0, 0, FL_SUBMENU }, + { "Help", 0, cb_help }, + { "About VirtualT", 0, cb_about }, + { 0 }, + + { 0 } +}; + +// Create the main display window and all children (status, etc.) +void initdisplay(void) +{ + MainWin = new Fl_Window(240*MultFact + 90*DisplayMode+2,64*MultFact + +50*DisplayMode + MENU_HEIGHT + 22, "Virtual T"); + Menu = new Fl_Menu_Bar(0, 0, 240*MultFact + 90*DisplayMode+2, +MENU_HEIGHT-2); + gpDisp = new T100_Disp(0, MENU_HEIGHT, 240*MultFact + 90*DisplayMode+2, +64*MultFact + 50*DisplayMode+2); + MainWin->callback(close_disp_cb); + Menu->menu(menuitems); + gpGraph = new Fl_Box(FL_DOWN_BOX,0, MENU_HEIGHT+64*MultFact + +50*DisplayMode+2, 60, 20,"GRAPH"); + gpGraph->labelsize(10); + gpGraph->deactivate(); + gpCode = new Fl_Box(FL_DOWN_BOX,60, MENU_HEIGHT+64*MultFact + +50*DisplayMode+2, 60, 20,"CODE"); + gpCode->labelsize(10); + gpCode->deactivate(); + gpCaps = new Fl_Box(FL_DOWN_BOX,120, MENU_HEIGHT+64*MultFact + +50*DisplayMode+2, 60, 20,"CAPS"); + gpCaps->labelsize(10); + gpCaps->deactivate(); + gpKey = new Fl_Box(FL_DOWN_BOX,180, MENU_HEIGHT+64*MultFact + +50*DisplayMode+2, 120, 20,""); + gpKey->labelsize(10); + gpSpeed = new Fl_Box(FL_DOWN_BOX,300, MENU_HEIGHT+64*MultFact + +50*DisplayMode+2, 60, 20,""); + gpSpeed->labelsize(10); + gpKeyInfo = new Fl_Box(FL_DOWN_BOX,360, MENU_HEIGHT+64*MultFact + +50*DisplayMode+2, MainWin->w()-360, 20, + "F9:Label F10:Print F11:Paste F12:Pause"); + gpKeyInfo->labelsize(10); + + gXoffset = 45*DisplayMode+1; + gYoffset = 25*DisplayMode + MENU_HEIGHT+1; + + MainWin->end(); + MainWin->show(); + + + Fl::wait(); + + +} + char label[40]; + +void display_cpu_speed(void) +{ + + sprintf(label, "%4.1f Mhz", cpu_speed); + Fl::check(); + gpSpeed->label(label); +} + +void drawbyte(int driver, int column, int value) +{ + gpDisp->SetByte(driver, column, value); + + return; +} + +void power_down() +{ + gpDisp->PowerDown(); + + return; +} + +void process_windows_event() +{ + Fl::wait(0); + + return; +} + +// Called when the Model T shuts its power off +void T100_Disp::PowerDown() +{ + // Clear display + fl_color(FL_GRAY); + if (DisplayMode == 1) + fl_rectf(45,25+30,w()-90,h()-49); + else + fl_rectf(x(),y(),w(),h()); + + Fl::wait(0); + + // Print power down message + char *msg = "System Powered Down"; + char *msg2 = "Press any key to reset"; + int x; + int col; + int driver, column; + for (driver = 0; driver < 10; driver++) + for (col = 0; col < 256; col++) + lcd[driver][col] = 0; + + // Display first line of powerdown message + fl_color(FL_BLACK); + col = 20 - strlen(msg) / 2; + for (x = 0; x < (int) strlen(msg); x++) + { + int mem_index = 0x7711 + (msg[x] - ' ')*5; + column = col++ * 6; + for (int c = 0; c < 6; c++) + { + driver = column / 50; // 50 pixels per driver + if (c == 5) + SetByte(driver, (column % 50) | 0xC0, 0); + else + SetByte(driver, (column % 50) | 0xC0, memory[mem_index++]); + column++; + } + } + + // Display 2nd line of powerdown message + col = 20 - strlen(msg2) / 2; + for (x = 0; x < (int) strlen(msg2); x++) + { + int mem_index = 0x7711 + (msg2[x] - ' ')*5; + column = col++ * 6; + for (int c = 0; c < 6; c++) + { + driver = column / 50 + 5; // 50 pixels per driver + if (c == 5) + SetByte(driver, (column % 50), 0); + else + SetByte(driver, (column % 50), memory[mem_index++]); + column++; + } + } +} + +// Handle mouse events, key events, focus events, etc. +int T100_Disp::handle(int event) +{ + char label[128]; + char keystr[10]; + char isSpecialKey = 1; + int c; + + unsigned int key; + + switch (event) + { + case FL_FOCUS: + m_MyFocus = 1; + break; + + case FL_UNFOCUS: + m_MyFocus = 0; + gSpecialKeys = 0xFFFFFFFF; + gpCode->deactivate(); + gpGraph->deactivate(); + gpKey->label(""); + for (c = 0; c < 128; c++) + gKeyStates[c] = 0; + update_keys(); + break; + + case FL_KEYUP: + if (!m_MyFocus) + return 1; + + // Get the Key that was pressed + key = Fl::event_key(); + //fprintf(stderr,"Touche: %d\n",key); + //fprintf(stderr,"Texte %s\n",Fl::event_text()); + switch (key) + { + case FL_Escape: + gSpecialKeys |= MT_ESC; + break; + case FL_Delete: + if ((Fl::get_key(FL_Shift_L) | Fl::get_key(FL_Shift_R)) == 0) + gSpecialKeys |= MT_SHIFT; + case FL_BackSpace: + gSpecialKeys |= MT_BKSP; + break; + case FL_Tab: + gSpecialKeys |= MT_TAB; + break; + case FL_Enter: + gSpecialKeys |= MT_ENTER; + break; + case FL_Print: + gSpecialKeys |= MT_PRINT; + break; + case FL_F+12: + case FL_Pause: + gSpecialKeys |= MT_PAUSE; + break; + case FL_Left: + gSpecialKeys |= MT_LEFT; + break; + case FL_Up: + gSpecialKeys |= MT_UP; + break; + case FL_Right: + gSpecialKeys |= MT_RIGHT; + break; + case FL_Down: + gSpecialKeys |= MT_DOWN; + break; + case FL_Shift_L: + case FL_Shift_R: + gSpecialKeys |= MT_SHIFT; + break; + case FL_Control_L: + case FL_Control_R: + gSpecialKeys |= MT_CTRL; + break; +// case FL_Caps_Lock: +// gSpecialKeys |= MT_CAP_LOCK; +// break; + case FL_Alt_L: + gSpecialKeys |= MT_GRAPH; + gpGraph->deactivate(); + break; + case FL_Alt_R: + gSpecialKeys |= MT_CODE; + gpCode->deactivate(); + break; + case FL_KP_Enter: + gSpecialKeys |= MT_ENTER; + break; + case FL_Insert: + case FL_Home: + if ((Fl::get_key(FL_Control_L) | Fl::get_key(FL_Control_R)) == 0) + gSpecialKeys |= MT_CTRL; + if (Fl::get_key(FL_Left) == 0) + gSpecialKeys |= MT_LEFT; + break; + case FL_End: + if ((Fl::get_key(FL_Control_L) | Fl::get_key(FL_Control_R)) == 0) + gSpecialKeys |= MT_CTRL; + if (Fl::get_key(FL_Right) == 0) + gSpecialKeys |= MT_RIGHT; + break; + case FL_Page_Up: + if ((Fl::get_key(FL_Shift_L) | Fl::get_key(FL_Shift_R)) == 0) + gSpecialKeys |= MT_SHIFT; + if (Fl::get_key(FL_Up) == 0) + gSpecialKeys |= MT_UP; + break; + case FL_Page_Down: + if ((Fl::get_key(FL_Shift_L) | Fl::get_key(FL_Shift_R)) == 0) + gSpecialKeys |= MT_SHIFT; + if (Fl::get_key(FL_Down) == 0) + gSpecialKeys |= MT_DOWN; + break; + case FL_F+1: + gSpecialKeys |= MT_F1; + break; + case FL_F+2: + gSpecialKeys |= MT_F2; + break; + case FL_F+3: + gSpecialKeys |= MT_F3; + break; + case FL_F+4: + gSpecialKeys |= MT_F4; + break; + case FL_F+5: + gSpecialKeys |= MT_F5; + break; + case FL_F+6: + gSpecialKeys |= MT_F6; + break; + case FL_F+7: + gSpecialKeys |= MT_F7; + break; + case FL_F+8: + gSpecialKeys |= MT_F8; + break; + case FL_F+9: + gSpecialKeys |= MT_LABEL; + break; + case FL_F+10: + gSpecialKeys |= MT_PRINT; + break; + case FL_F+11: + gSpecialKeys |= MT_PASTE; + break; + default: + key &= 0x7F; + // key=(unsigned int)Fl::event_text(); + // fprintf(stderr,"Et aussi %d\n",key); + gKeyStates[key] = 0; + if (key == 0x20) + gSpecialKeys |= MT_SPACE; + if (key == ']') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys |= MT_GRAPH; + gSpecialKeys &= ~MT_SHIFT; + gKeyStates[']'] = 0; + gKeyStates['0'] = 0; + } + else + { + gSpecialKeys |= MT_SHIFT; + gKeyStates['['] = 0; + } + } + if (key == '[') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys |= MT_GRAPH; + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['['] = 0; + gKeyStates['9'] = 0; + } + } + if (key == '`') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys |= MT_GRAPH; + gKeyStates['['] = 0; + } + else + gKeyStates['['] = 0; + + } + if (key == '\\') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys |= MT_GRAPH; + gKeyStates[';'] = 0; + } + else + { + gSpecialKeys |= MT_GRAPH; + gKeyStates['-'] = 0; + } + } + isSpecialKey = 0; + break; + } + update_keys(); + break; + + case FL_KEYDOWN: + if (!m_MyFocus) + return 1; + + if (ioBA & 0x10) + { + resetcpu(); + break; + } + + // Get the Key that was pressed + key = Fl::event_key(); + switch (key) + { + case FL_Escape: + gSpecialKeys &= ~MT_ESC; + break; + case FL_Delete: + gSpecialKeys &= ~MT_SHIFT; + case FL_BackSpace: + gSpecialKeys &= ~MT_BKSP; + break; + case FL_Tab: + gSpecialKeys &= ~MT_TAB; + break; + case FL_Enter: + gSpecialKeys &= ~MT_ENTER; + break; + case FL_Print: + gSpecialKeys &= ~MT_PRINT; + break; + case FL_F+12: + case FL_Pause: + gSpecialKeys &= ~MT_PAUSE; + break; + case FL_Left: + gSpecialKeys &= ~MT_LEFT; + break; + case FL_Up: + gSpecialKeys &= ~MT_UP; + break; + case FL_Right: + + gSpecialKeys &= ~MT_RIGHT; + break; + case FL_Down: + gSpecialKeys &= ~MT_DOWN; + break; + case FL_Shift_L: + case FL_Shift_R: + gSpecialKeys &= ~MT_SHIFT; + break; + case FL_Control_L: + case FL_Control_R: + gSpecialKeys &= ~MT_CTRL; + break; + case FL_Caps_Lock: + gSpecialKeys ^= MT_CAP_LOCK; + if (gSpecialKeys & MT_CAP_LOCK) + gpCaps->deactivate(); + else + gpCaps->activate(); + break; + case FL_Alt_L: + gSpecialKeys &= ~MT_GRAPH; + gpGraph->activate(); + break; + case FL_Alt_R: + gSpecialKeys &= ~MT_CODE; + gpCode->activate(); + break; + case FL_KP_Enter: + gSpecialKeys &= ~MT_ENTER; + break; + case FL_Insert: + case FL_Home: + gSpecialKeys &= ~(MT_CTRL | MT_LEFT); + break; + case FL_End: + gSpecialKeys &= ~(MT_CTRL | MT_RIGHT); + break; + case FL_Page_Up: + gSpecialKeys &= ~(MT_SHIFT | MT_UP); + break; + case FL_Page_Down: + gSpecialKeys &= ~(MT_SHIFT | MT_DOWN); + break; + case FL_F+1: + gSpecialKeys &= ~MT_F1; + break; + case FL_F+2: + gSpecialKeys &= ~MT_F2; + break; + case FL_F+3: + gSpecialKeys &= ~MT_F3; + break; + case FL_F+4: + gSpecialKeys &= ~MT_F4; + break; + case FL_F+5: + gSpecialKeys &= ~MT_F5; + break; + case FL_F+6: + gSpecialKeys &= ~MT_F6; + break; + case FL_F+7: + gSpecialKeys &= ~MT_F7; + break; + case FL_F+8: + gSpecialKeys &= ~MT_F8; + break; + case FL_F+9: + gSpecialKeys &= ~MT_LABEL; + break; + case FL_F+10: + gSpecialKeys &= ~MT_PRINT; + break; + case FL_F+11: + gSpecialKeys &= ~MT_PASTE; + break; + default: + key &= 0x7F; + gKeyStates[key] = 1; + if (key == 0x20) + { + gSpecialKeys &= ~MT_SPACE; + } + if (key == ']') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_GRAPH; + gSpecialKeys |= MT_SHIFT; + gKeyStates[']'] = 0; + gKeyStates['0'] = 1; + } + else + { + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['['] = 1; + gKeyStates[key] = 0; + } + } + if (key == '[') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_GRAPH; + gSpecialKeys |= MT_SHIFT; + gKeyStates['['] = 0; + gKeyStates['9'] = 1; + } + } + if (key == '`') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_GRAPH; + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['`'] = 0; + gKeyStates['['] = 1; + } + else + { + gSpecialKeys &= ~MT_GRAPH; + gKeyStates['`'] = 0; + gKeyStates['['] = 1; + } + } + if (key == '\\') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_GRAPH; + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['\\'] = 0; + gKeyStates[';'] = 1; + } + else + { + gSpecialKeys &= ~MT_GRAPH; + gKeyStates['-'] = 1; + gKeyStates['\\'] = 0; + } + } + + isSpecialKey = 0; + break; + } + update_keys(); + break; + } + + // Display keystroke info on status line of display + if (event == FL_KEYUP || event == FL_KEYDOWN) + { + // Start with empty string + label[0] = 0; + + // Add text for special keys + for (c = 0; c < 32; c++) + { + if ((gSpecialKeys & (0x01 << c)) == 0) + { + if ((c == 2) || (c == 3) || (c==5)) + continue; + if (label[0] != 0) + strcat(label, "+"); + strcat(label, gSpKeyText[c]); + } + } + + // Add text for regular keys + for (c = ' '+1; c < '~'; c++) + { + if (gKeyStates[c]) + { + if (label[0] != 0) + strcat(label, "+"); + sprintf(keystr, "'%c'", c); + + // Space shows up better written instead of ' ' + if (c == 0x20) + strcat(label, "SPACE"); + else + strcat(label, keystr); + } + } + + // For some reason the F1 key causes garbage to print in + // the status box. This check fixed it for some reason -- ???? + Fl::check(); + + // Update the text + gpKey->label(label); + } + + return 1; +} + + + diff --git a/src/display.h b/src/display.h new file mode 100644 index 0000000..011d93a --- /dev/null +++ b/src/display.h @@ -0,0 +1,68 @@ +/* display.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef _DISPLAY_H_ +#define _DISPLAY_H_ + +#define MENU_HEIGHT 32 + +#ifdef __cplusplus +extern "C" { +#endif +extern int gDelayUpdateKeys; +void initdisplay(void); +void drawbyte(int driver, int column, int value); +void power_down(); +void process_windows_event(); +void display_cpu_speed(void); + +#ifdef __cplusplus + +class T100_Disp : public Fl_Widget +{ +public: + int m_MyFocus; + void PowerDown(); + T100_Disp(int x, int y, int w, int h); + + void SetByte(int driver, int col, uchar value); + +protected: + virtual int handle(int event); + void draw(); + + uchar lcd[10][256]; + +}; + +} +#endif + +#endif diff --git a/src/do_instruct.h b/src/do_instruct.h new file mode 100644 index 0000000..8460859 --- /dev/null +++ b/src/do_instruct.h @@ -0,0 +1,2327 @@ +/* do_instruct.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#define LXI(rp,h,l,rps) { \ + INCPC; \ + if(trace) \ + sprintf(p,"LXI "rps",%04x",INS16); \ + l=INS; \ + INCPC; \ + h=INS; \ + INCPC; \ + cpu_delay(10); \ + } + +#define STAX(rp,rps) { \ + INCPC; \ + if(trace) \ + strcat(p,"STAX "rps); \ + MEM(rp)=A; \ + cpu_delay(7); \ + } + +#define INX(rp,h,l,rps) { \ + INCPC; \ + if(trace) \ + strcat(p,"INX "rps); \ + l++; \ + if(!l) \ + h++; \ + cpu_delay(6); \ + } + +#define INR(r,rs) { \ + INCPC; \ + if(trace) \ + strcat(p,"INR "rs); \ + r++; \ + if(r&0x0f==0) /* Low order nybble wrapped */ \ + j=1; \ + else \ + j=0; \ + setflags(r,-1,-1,j,-1,-2); \ + cpu_delay(4); \ + } + +#define DCR(r,rs) { \ + INCPC; \ + if(trace) \ + strcat(p,"DCR "rs); \ + r--; \ + if(r&0x0f==0x0f) /* Low order nybble wrapped */ \ + j=1; \ + else \ + j=0; \ + setflags(r,-1,-1,j,-1,-2); \ + cpu_delay(4); \ + } + +#define MVI(r,rs) { \ + INCPC; \ + if(trace) \ + sprintf(p,"MVI "rs",%02x",INS); \ + r=INS; \ + INCPC; \ + cpu_delay(7); \ + } + +#define DAD(rp,rps) { \ + INCPC; \ + if(trace) \ + strcat(p,"DAD "rps); \ + i=HL; \ + i+=rp; \ + H=(i>>8); \ + L=i; \ + if(i>0xffff) \ + i=1; \ + else \ + i=0; \ + setflags(0,-2,-2,-2,-2,i); \ + cpu_delay(10); \ + } + +#define LDAX(rp,rps) { \ + INCPC; \ + if(trace) \ + strcat(p,"LDAX "rps); \ + A=MEM(rp); \ + cpu_delay(7); \ + } + +#define DCX(rp,h,l,rps) { \ + INCPC; \ + if(trace) \ + strcat(p,"DCX "rps); \ + l--; \ + if(l==0xff) \ + h--; \ + cpu_delay(6); \ + } + +#define MOV(dest,src,ds,ss) { \ + INCPC; \ + if(trace) \ + strcat(p,"MOV "ds","ss); \ + dest=src; \ + cpu_delay(4); \ + } + +#define ADD(r,rs) { \ + INCPC; \ + if(trace) \ + strcat(p,"ADD "rs); \ + i=A; \ + i+=r; \ + j = (((A&0x0F)+(r&0x0F)) &0x10)>>4; \ + A=i; \ + if(i>0xFF) \ + i=1; \ + else \ + i=0; \ + setflags(A,-1,-1,j,-1,i); \ + cpu_delay(4); \ + } + +#define ADC(r,rs) { \ + INCPC; \ + if(trace) \ + strcat(p,"ADC "rs); \ + i=A; \ + i+=r; \ + i+=(CF?1:0); \ + j = (((A&0x0F)+(r&0x0F)+(CF?1:0)) &0x10)>>4; \ + A=i; \ + if(i>0xFF) \ + i=1; \ + else \ + i=0; \ + setflags(A,-1,-1,j,-1,i); \ + cpu_delay(4); \ + } + +#define SUB(r,rs) { \ + INCPC; \ + if(trace) \ + strcat(p,"SUB "rs); \ + i=A; \ + i-=r; \ + j = (((A & 0x0F)-(r & 0x0F)) & 0x10) >> 4; \ + A=i; \ + if(i>0xFF) \ + i=1; \ + else \ + i=0; \ + setflags(A,-1,-1,j,-1,i); \ + cpu_delay(4); \ + } + +#define SBB(r,rs) { \ + INCPC; \ + if(trace) \ + strcat(p,"SCB "rs); \ + i=A; \ + i-=r; \ + i-=(CF?1:0); \ + j = (((A & 0x0F)-(r & 0x0F)-(CF?1:0)) & 0x10) >> 4; \ + A=i; \ + if (i>0xFF) \ + i = 1; \ + else \ + i = 0; \ + setflags(A,-1,-1,j,-1,i); \ + cpu_delay(4); \ + } + +#define ANA(r,rs) { \ + INCPC; \ + if(trace) \ + strcat(p,"ANA "rs); \ + A&=r; \ + setflags(A,-1,-1,1,-1,0); \ + cpu_delay(4); \ + } + +#define XRA(r,rs) { \ + INCPC; \ + if(trace) \ + strcat(p,"XRA "rs); \ + A^=r; \ + setflags(A,-1,-1,0,-1,0); \ + cpu_delay(4); \ + } + +#define ORA(r,rs) { \ + INCPC; \ + if(trace) \ + strcat(p,"ORA "rs); \ + A|=r; \ + setflags(A,-1,-1,0,-1,0); \ + cpu_delay(4); \ + } + +#define CMP(r,rs) { \ + INCPC; \ + if(trace) \ + strcat(p,"CMP "rs); \ + i=A; \ + i-=r; \ + if (i>0xFF) \ + i=1; \ + else \ + i=0; \ + j = (((A & 0x0F)-(r & 0x0F)) & 0x10) >> 4; \ + setflags(A-r,-1,-1,j,-1,i); \ + cpu_delay(4); \ + } + +#define POP(rp,h,l,rps) { \ + INCPC; \ + if(trace) \ + strcat(p,"POP "rps); \ + l=MEM(SP); \ + h=MEM(SP+1); \ + INCSP2; \ + cpu_delay(10); \ + } + +#define PUSH(rp,h,l,rps) { \ + INCPC; \ + if(trace) \ + strcat(p,"PUSH "rps); \ + DECSP2; \ + MEM(SP)=l; \ + MEM(SP+1)=h; \ + cpu_delay(12); \ + } + +#define RST(num) { \ + INCPC; \ + if(trace) \ + sprintf(p,"RST %d",num); \ + DECSP2; \ + MEM(SP)=PCL; MEM(SP+1)=PCH; \ + PCH=0; \ + PCL=8*num; \ + cpu_delay(12); \ + } + +#define DOCALL { \ + DECSP2; \ + MEM(SP)=PCL; MEM(SP+1)=PCH; /* MEM16(SP)=PC; */ \ + DECPC2; \ + SETPCINS16; \ + cpu_delay(9); \ + } + +#define DORET { \ + PCL=MEM(SP); PCH=MEM(SP+1); /* PC=MEM16(SP) */ \ + INCSP2; \ + cpu_delay(6); \ + } + + +{ + if(trace) + p=op+sprintf(op,"%04x (%02x) ",PC,INS); + if(!(INS&0x80)) { + if(!(INS&0x40)) { + if(!(INS&0x20)) { + if(!(INS&0x10)) { + if(!(INS&0x08)) { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x00: /* NOP */ + INCPC; + if(trace) + strcat(p,"NOP"); + cpu_delay(4); + /* return; */ + } + else { + /* case 0x01: /* LXI B */ + LXI(BC,B,C,"B"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x02: /* STAX B */ + STAX(BC,"B"); + } + else { + /* case 0x03: /* INX B */ + INX(BC,B,C,"B"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x04: /* INR B */ + INR(B,"B"); + } + else { + /* case 0x05: /* DCR B */ + DCR(B,"B"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x06: /* MVI B */ + MVI(B,"B"); + } + else { + /* case 0x07: /* RLC */ + INCPC; + if(trace) + strcat(p,"RLC"); + i=A>>7; + A=(A<<1)|i; + setflags(A,-2,-2,-2,-2,i); + cpu_delay(4); + /* return; */ + } + } + } + } + else { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x08: /* INVALID? */ + bail("0x08 is invalid"); + /* return; */ + } + else { + /* case 0x09: /* DAD B */ + DAD(BC,"B"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x0A: /* LDAX B */ + LDAX(BC,"B"); + } + else { + /* case 0x0B: /* DCX B */ + DCX(BC,B,C,"B"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x0C: /* INR C */ + INR(C,"C"); + } + else { + /* case 0x0D: /* DCR C */ + DCR(C,"C"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x0E: /* MVI C */ + MVI(C,"C"); + } + else { + /* case 0x0F: /* RRC */ + INCPC; + if(trace) + strcat(p,"RRC"); + i=A<<7&0x80; + A=(A>>1)|i; + i>>=7; + setflags(A,-2,-2,-2,-2,i); + cpu_delay(4); + /* return; */ + } + } + } + } + } + else { + if(!(INS&0x08)) { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x10: /* INVALID? */ + bail("0x10 is invalid"); + /* return; */ + } + else { + /* case 0x11: /* LXI D */ + LXI(DE,D,E,"D"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x12: /* STAX D */ + STAX(DE,"D"); + } + else { + /* case 0x13: /* INX D */ + INX(DE,D,E,"D"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x14: /* INR D */ + INR(D,"D"); + } + else { + /* case 0x15: /* DCR D */ + DCR(D,"D"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x16: /* MVI D */ + MVI(D,"D"); + } + else { + /* case 0x17: /* RAL */ + INCPC; + if(trace) + strcat(p,"RAL"); + i=A>>7; + A<<=1; + A|=(CF?1:0); + setflags(A,-2,-2,-2,-2,i); + cpu_delay(4); + /* return; */ + } + } + } + } + else { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x18: /* INVALID? */ + bail("0x18 is invalid"); + /* return; */ + } + else { + /* case 0x19: /* DAD D */ + DAD(DE,"D"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x1A: /* LDAX D */ + LDAX(DE,"D"); + } + else { + /* case 0x1B: /* DCX D */ + DCX(DE,D,E,"D"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x1C: /* INR E */ + INR(E,"E"); + } + else { + /* case 0x1D: /* DCR E */ + DCR(E,"E"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x1E: /* MVI E */ + MVI(E,"E"); + } + else { + /* case 0x1F: /* RAR */ + INCPC; + if(trace) + strcat(p,"RAR"); + i=(A&0x01); + A>>=1; + A|=CF?0x80:0; + setflags(A,-2,-2,-2,-2,i); + cpu_delay(4); + /* return; */ + } + } + } + } + } + } + else { + if(!(INS&0x10)) { + if(!(INS&0x08)) { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x20: /* RIM */ + INCPC; + if(trace) + strcat(p,"RIM"); + A=IM; + cpu_delay(4); + /* return; */ + } + else { + /* case 0x21: /* LXI H */ + LXI(HL,H,L,"H"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x22: /* SHLD */ + INCPC; + if(trace) + sprintf(p,"SHLD %x",INS16); + MEM(INS16)=L; + MEM(INS16+1)=H; + /* MEM16(INS16)=HL; */ + INCPC2; + cpu_delay(16); + /* return; */ + } + else { + /* case 0x23: /* INX H */ + INX(HL,H,L,"H"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x24: /* INR H */ + INR(H,"H"); + } + else { + /* case 0x25: /* DCR H */ + DCR(H,"H"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x26: /* MVI H */ + MVI(H,"H"); + } + else { + /* case 0x27: /* DAA */ + INCPC; + if(trace) + strcat(p,"DAA"); + i=j=0; + if(((A&0x0F) > 9)) { + i=6; + j=1; + } + if(AC) + i=6; + if((((A>>4)+j) > 9) || CF) + i|=0x60; + A+=i; + setflags(A,-1,-1,j,-1,i>>4?1:0); + cpu_delay(4); + /* return; */ /* Huh? */ + } + } + } + } + else { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x28: /* INVALID? */ + bail("0x28 is invalid"); + /* return; */ + } + else { + /* case 0x29: /* DAD H */ + DAD(HL,"H"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x2A: /* LHLD */ + INCPC; + if(trace) + sprintf(p,"LHLD %x",INS16); + L=MEM(INS16); + H=MEM(INS16+1); + INCPC2; + cpu_delay(16); + } + else { + /* case 0x2B: /* DCX H */ + DCX(HL,H,L,"H"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x2C: /* INR L */ + INR(L,"L"); + } + else { + /* case 0x2D: /* DCR L */ + DCR(L,"L"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x2E: /* MVI L */ + MVI(L,"L"); + } + else { + /* case 0x2F: /* CMA */ + INCPC; + if(trace) + strcat(p,"CMA"); + A=~A; + cpu_delay(4); + } + } + } + } + } + else { + if(!(INS&0x08)) { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x30: /* SIM */ + INCPC; + if(trace) + strcat(p,"SIM"); + if (A & 0x08) /* Check if Interrupt masking enabled */ + IM=(IM & 0xF8) | (A&0x07); + /* Turn RST 7.5 pending off if bit 4 set */ + if(A&0x10) { + IM&=0xBF; + } + cpu_delay(4); + /* return; */ + } + else { + /* case 0x31: /* LXI SP */ + LXI(SP,SPH,SPL,"SP"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x32: /* STA */ + INCPC; + if(trace) + sprintf(p,"STA %04x",INS16); + MEM(INS16)=A; + INCPC2; + cpu_delay(13); + /* return; */ + } + else { + /* case 0x33: /* INX SP */ + INX(SP,SPH,SPL,"SP"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x34: /* INR M */ + INR(M,"M"); + cpu_delay(6); + } + else { + /* case 0x35: /* DCR M */ + DCR(M,"M"); + cpu_delay(6); + } + } + else { + if(!(INS&0x01)) { + /* case 0x36: /* MVI M */ + MVI(M,"M"); + cpu_delay(3); + } + else { + /* case 0x37: /* STC */ + INCPC; + if(trace) + strcat(p,"STC"); + setflags(0,-2,-2,-2,-2,1); + cpu_delay(4); + /* return; */ + } + } + } + } + else { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x38: /* UNSUPPORTED */ + bail("0x38 is invalid"); + /* return; */ + } + else { + /* case 0x39: /* DAD SP */ + DAD(SP,"SP"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x3A: /* LDA */ + INCPC; + if(trace) + sprintf(p,"LDA %04x",INS16); + A=MEM(INS16); + INCPC2; + cpu_delay(13); + /* return; */ + } + else { + /* case 0x3B: /* DCX SP */ + DCX(SP,SPH,SPL,"SP"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x3C: /* INR A */ + INR(A,"A"); + } + else { + /* case 0x3D: /* DCR A */ + DCR(A,"A"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x3E: /* MVI A */ + MVI(A,"A"); + } + else { + /* case 0x3F: /* CMC */ + INCPC; + if(trace) + strcat(p,"CMC"); + setflags(A,-2,-2,-2,-2,CF?0:1); + cpu_delay(4); + /* return; */ + } + } + } + } + } + } + } + else { + if(!(INS&0x20)) { + if(!(INS&0x10)) { + if(!(INS&0x08)) { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x40: /* MOV B,B */ + MOV(B,B,"B","B"); + } + else { + /* case 0x41: /* MOV B,C */ + MOV(B,C,"B","C"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x42: /* MOV B,D */ + MOV(B,D,"B","D"); + } + else { + /* case 0x43: /* MOV B,E */ + MOV(B,E,"B","E"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x44: /* MOV B,H */ + MOV(B,H,"B","H"); + } + else { + /* case 0x45: /* MOV B,L */ + MOV(B,L,"B","L"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x46: /* MOV B,M */ + MOV(B,M,"B","M"); + cpu_delay(3); + /* return; */ + } + else { + /* case 0x47: /* MOV B,A */ + MOV(B,A,"B","A"); + } + } + } + } + else { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x48: /* MOV C,B */ + MOV(C,B,"C","B"); + } + else { + /* case 0x49: /* MOV C,C */ + MOV(C,C,"C","C"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x4A: /* MOV C,D */ + MOV(C,D,"C","D"); + } + else { + /* case 0x4B: /* MOV C,E */ + MOV(C,E,"C","E"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x4C: /* MOV C,H */ + MOV(C,H,"C","H"); + } + else { + /* case 0x4D: /* MOV C,L */ + MOV(C,L,"C","L"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x4E: /* MOV C,M */ + MOV(C,M,"C","M"); + cpu_delay(3); + } + else { + /* case 0x4F: /* MOV C,A */ + MOV(C,A,"C","A"); + } + } + } + } + } + else { + if(!(INS&0x08)) { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x50: /* MOV D,B */ + MOV(D,B,"D","B"); + } + else { + /* case 0x51: /* MOV D,C */ + MOV(D,C,"D","C"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x52: /* MOV D,D */ + MOV(D,D,"D","D"); + } + else { + /* case 0x53: /* MOV D,E */ + MOV(D,E,"D","E"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x54: /* MOV D,H */ + MOV(D,H,"D","H"); + } + else { + /* case 0x55: /* MOV D,L */ + MOV(D,L,"D","L"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x56: /* MOV D,M */ + MOV(D,M,"D","M"); + cpu_delay(3); + } + else { + /* case 0x57: /* MOV D,A */ + MOV(D,A,"D","A"); + } + } + } + } + else { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x58: /* MOV E,B */ + MOV(E,B,"E","B"); + } + else { + /* case 0x59: /* MOV E,C */ + MOV(E,C,"E","C"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x5A: /* MOV E,D */ + MOV(E,D,"E","D"); + } + else { + /* case 0x5B: /* MOV E,E */ + MOV(E,E,"E","E"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x5C: /* MOV E,H */ + MOV(E,H,"E","H"); + } + else { + /* case 0x5D: /* MOV E,L */ + MOV(E,L,"E","L"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x5E: /* MOV E,M */ + MOV(E,M,"E","M"); + cpu_delay(3); + } + else { + /* case 0x5F: /* MOV E,A */ + MOV(E,A,"E","A"); + } + } + } + } + } + } + else { + if(!(INS&0x10)) { + if(!(INS&0x08)) { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x60: /* MOV H,B */ + MOV(H,B,"H","B"); + } + else { + /* case 0x61: /* MOV H,C */ + MOV(H,C,"H","C"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x62: /* MOV H,D */ + MOV(H,D,"H","D"); + } + else { + /* case 0x63: /* MOV H,E */ + MOV(H,E,"H","E"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x64: /* MOV H,H */ + MOV(H,H,"H","H"); + } + else { + /* case 0x65: /* MOV H,L */ + MOV(H,L,"H","L"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x66: /* MOV H,M */ + MOV(H,M,"H","M"); + } + else { + /* case 0x67: /* MOV H,A */ + MOV(H,A,"H","A"); + } + } + } + } + else { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x68: /* MOV L,B */ + MOV(L,B,"L","B"); + } + else { + /* case 0x69: /* MOV L,C */ + MOV(L,C,"L","C"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x6A: /* MOV L,D */ + MOV(L,D,"L","D"); + } + else { + /* case 0x6B: /* MOV L,E */ + MOV(L,E,"L","E"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x6C: /* MOV L,H */ + MOV(L,H,"L","H"); + } + else { + /* case 0x6D: /* MOV L,L */ + MOV(L,L,"L","L"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x6E: /* MOV L,M */ + MOV(L,M,"L","M"); + cpu_delay(3); + } + else { + /* case 0x6F: /* MOV L,A */ + MOV(L,A,"L","A"); + } + } + } + } + } + else { + if(!(INS&0x08)) { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x70: /* MOV M,B */ + MOV(M,B,"M","B"); + cpu_delay(3); + } + else { + /* case 0x71: /* MOV M,C */ + MOV(M,C,"M","C"); + cpu_delay(3); + } + } + else { + if(!(INS&0x01)) { + /* case 0x72: /* MOV M,D */ + MOV(M,D,"M","D"); + cpu_delay(3); + } + else { + /* case 0x73: /* MOV M,E */ + MOV(M,E,"M","E"); + cpu_delay(3); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x74: /* MOV M,H */ + MOV(M,H,"M","H"); + cpu_delay(3); + } + else { + /* case 0x75: /* MOV M,L */ + MOV(M,L,"M","L"); + cpu_delay(3); + } + } + else { + if(!(INS&0x01)) { + /* case 0x76: /* HLT */ + if(trace) + strcat(p,"HLT"); + cpu_delay(4); + /* return; */ + } + else { + /* case 0x77: /* MOV M,A */ + MOV(M,A,"M","A"); + cpu_delay(3); + } + } + } + } + else { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x78: /* MOV A,B */ + MOV(A,B,"A","B"); + } + else { + /* case 0x79: /* MOV A,C */ + MOV(A,C,"A","C"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x7A: /* MOV A,D */ + MOV(A,D,"A","D"); + } + else { + /* case 0x7B: /* MOV A,E */ + MOV(A,E,"A","E"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x7C: /* MOV A,H */ + MOV(A,H,"A","H"); + } + else { + /* case 0x7D: /* MOV A,L */ + MOV(A,L,"A","L"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x7E: /* MOV A,M */ + MOV(A,M,"A","M"); + cpu_delay(3); + } + else { + /* case 0x7F: /* MOV A,A */ + MOV(A,A,"A","A"); + } + } + } + } + } + } + } + } + else { + if(!(INS&0x40)) { + if(!(INS&0x20)) { + if(!(INS&0x10)) { + if(!(INS&0x08)) { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x80: /* ADD B */ + ADD(B,"B"); + } + else { + /* case 0x81: /* ADD C */ + ADD(C,"C"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x82: /* ADD D */ + ADD(D,"D"); + } + else { + /* case 0x83: /* ADD E */ + ADD(E,"E"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x84: /* ADD H */ + ADD(H,"H"); + } + else { + /* case 0x85: /* ADD L */ + ADD(L,"L"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x86: /* ADD M */ + ADD(M,"M"); + cpu_delay(3); + } + else { + /* case 0x87: /* ADD A */ + ADD(A,"A"); + } + } + } + } + else { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x88: /* ADC B */ + ADC(B,"B"); + } + else { + /* case 0x89: /* ADC C */ + ADC(C,"C"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x8A: /* ADC D */ + ADC(D,"D"); + } + else { + /* case 0x8B: /* ADC E */ + ADC(E,"E"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x8C: /* ADC H */ + ADC(H,"H"); + } + else { + /* case 0x8D: /* ADC L */ + ADC(L,"L"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x8E: /* ADC M */ + ADC(M,"M"); + cpu_delay(3); + } + else { + /* case 0x8F: /* ADC A */ + ADC(A,"A"); + } + } + } + } + } + else { + if(!(INS&0x08)) { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x90: /* SUB B */ + SUB(B,"B"); + } + else { + /* case 0x91: /* SUB C */ + SUB(C,"C"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x92: /* SUB D */ + SUB(D,"D"); + } + else { + /* case 0x93: /* SUB E */ + SUB(E,"E"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x94: /* SUB H */ + SUB(H,"H"); + } + else { + /* case 0x95: /* SUB L */ + SUB(L,"L"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x96: /* SUB M */ + SUB(M,"M"); + cpu_delay(3); + } + else { + /* case 0x97: /* SUB A */ + SUB(A,"A"); + } + } + } + } + else { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x98: /* SBB B */ + SBB(B,"B"); + } + else { + /* case 0x99: /* SBB C */ + SBB(C,"C"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x9A: /* SBB D */ + SBB(D,"D"); + } + else { + /* case 0x9B: /* SBB E */ + SBB(E,"E"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0x9C: /* SBB H */ + SBB(H,"H"); + } + else { + /* case 0x9D: /* SBB L */ + SBB(L,"L"); + } + } + else { + if(!(INS&0x01)) { + /* case 0x9E: /* SBB M */ + SBB(M,"M"); + cpu_delay(3); + } + else { + /* case 0x9F: /* SBB A */ + SBB(A,"A"); + } + } + } + } + } + } + else { + if(!(INS&0x10)) { + if(!(INS&0x08)) { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xA0: /* ANA B */ + ANA(B,"B"); + } + else { + /* case 0xA1: /* ANA C */ + ANA(C,"C"); + } + } + else { + if(!(INS&0x01)) { + /* case 0xA2: /* ANA D */ + ANA(D,"D"); + } + else { + /* case 0xA3: /* ANA E */ + ANA(E,"E"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xA4: /* ANA H */ + ANA(H,"H"); + } + else { + /* case 0xA5: /* ANA L */ + ANA(L,"L"); + } + } + else { + if(!(INS&0x01)) { + /* case 0xA6: /* ANA M */ + ANA(M,"M"); + cpu_delay(3); + } + else { + /* case 0xA7: /* ANA A */ + ANA(A,"A"); + } + } + } + } + else { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xA8: /* XRA B */ + XRA(B,"B"); + } + else { + /* case 0xA9: /* XRA C */ + XRA(C,"C"); + } + } + else { + if(!(INS&0x01)) { + /* case 0xAA: /* XRA D */ + XRA(D,"D"); + } + else { + /* case 0xAB: /* XRA E */ + XRA(E,"E"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xAC: /* XRA H */ + XRA(H,"H"); + } + else { + /* case 0xAD: /* XRA L */ + XRA(L,"L"); + } + } + else { + if(!(INS&0x01)) { + /* case 0xAE: /* XRA M */ + XRA(M,"M"); + cpu_delay(3); + } + else { + /* case 0xAF: /* XRA A */ + XRA(A,"A"); + } + } + } + } + } + else { + if(!(INS&0x08)) { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xB0: /* ORA B */ + ORA(B,"B"); + } + else { + /* case 0xB1: /* ORA C */ + ORA(C,"C"); + } + } + else { + if(!(INS&0x01)) { + /* case 0xB2: /* ORA D */ + ORA(D,"D"); + } + else { + /* case 0xB3: /* ORA E */ + ORA(E,"E"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xB4: /* ORA H */ + ORA(H,"H"); + } + else { + /* case 0xB5: /* ORA L */ + ORA(L,"L"); + } + } + else { + if(!(INS&0x01)) { + /* case 0xB6: /* ORA M */ + ORA(M,"M"); + cpu_delay(3); + } + else { + /* case 0xB7: /* ORA A */ + ORA(A,"A"); + } + } + } + } + else { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xB8: /* CMP B */ + CMP(B,"B"); + } + else { + /* case 0xB9: /* CMP C */ + CMP(C,"C"); + } + } + else { + if(!(INS&0x01)) { + /* case 0xBA: /* CMP D */ + CMP(D,"D"); + } + else { + /* case 0xBB: /* CMP E */ + CMP(E,"E"); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xBC: /* CMP H */ + CMP(H,"H"); + } + else { + /* case 0xBD: /* CMP L */ + CMP(L,"L"); + } + } + else { + if(!(INS&0x01)) { + /* case 0xBE: /* CMP M */ + CMP(M,"M"); + cpu_delay(3); + } + else { + /* case 0xBF: /* CMP A */ + CMP(A,"A"); + } + } + } + } + } + } + } + else { + if(!(INS&0x20)) { + if(!(INS&0x10)) { + if(!(INS&0x08)) { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xC0: /* RNZ */ + INCPC; + if(trace) + strcat(p,"RNZ"); + if(!ZF) { + PCL=MEM(SP); PCH=MEM(SP+1); /* PC=MEM16(SP) */ + INCSP2; + cpu_delay(6); + } + cpu_delay(6); + /* return; */ + } + else { + /* case 0xC1: /* POP B */ + POP(BC,B,C,"B"); + } + } + else { + if(!(INS&0x01)) { + /* case 0xC2: /* JNZ addr */ + INCPC; + if(trace) + sprintf(p,"JNZ %04x",INS16); + if(!ZF) { + SETPCINS16; + cpu_delay(3); + } + else + INCPC2; + cpu_delay(7); + /* return; */ + } + else { + /* case 0xC3: /* JMP addr */ + INCPC; + if(trace) + sprintf(p,"JMP %04x",INS16); + SETPCINS16; + cpu_delay(7); + /* return; */ + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xC4: /* CNZ addr */ + INCPC; + if(trace) + sprintf(p,"CNZ %04x",INS16); + INCPC2; + if(!ZF) { + DOCALL; + } + cpu_delay(9); + /* return; */ + } + else { + /* case 0xC5: /* PUSH B */ + PUSH(BC,B,C,"B"); + } + } + else { + if(!(INS&0x01)) { + /* case 0xC6: /* ADI n */ + INCPC; + if(trace) + sprintf(p,"ADI %02x",INS); + i=A; + i+=INS; + j = (((A&0x0F)+(INS&0x0F)) &0x10)>>4; + A=i; + if(i>0xFF) + i=1; + else + i=0; + setflags(A,-1,-1,j,-1,i); + cpu_delay(7); + INCPC; + /* return; */ + } + else { + /* case 0xC7: /* RST 0 */ + RST(0); + } + } + } + } + else { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xC8: /* RZ */ + if(trace) + strcat(p,"RZ"); + INCPC; + if(ZF) { + DORET; + } + cpu_delay(6); + /* return; */ + } + else { + /* case 0xC9: /* RET */ + if(trace) + strcat(p,"RET"); + DORET; + cpu_delay(4); + /* return; */ + } + } + else { + if(!(INS&0x01)) { + /* case 0xCA: /* JZ addr */ + INCPC; + if(trace) + sprintf(p,"JZ %04x",INS16); + if(ZF) { + SETPCINS16; + cpu_delay(3); + } + else + INCPC2; + cpu_delay(7); + /* return; */ + } + else { + /* case 0xCB: /* INVALID? */ + bail("0xCB is invalid"); + /* return; */ + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xCC: /* CZ addr */ + INCPC; + if(trace) + sprintf(p,"CZ %04x",INS16); + INCPC2; + if(ZF) { + DOCALL; + } + cpu_delay(9); + /* return; */ + } + else { + /* case 0xCD: /* CALL addr */ + INCPC; + if(trace) + sprintf(p,"CALL %04x",INS16); + INCPC2; + DOCALL; + cpu_delay(9); + /* return; */ + } + } + else { + if(!(INS&0x01)) { + /* case 0xCE: /* ACI n */ + INCPC; + if(trace) + sprintf(p,"ACI %02x",INS); + i=A; + i+=INS; + i+=(CF?1:0); + j = (((A&0x0F)+(INS&0x0F)+(CF?1:0)) &0x10)>>4; + A=i; + if(i>0xFF) + i=1; + else + i=0; + INCPC; + setflags(A,-1,-1,j,-1,i); + cpu_delay(7); + /* return; */ + } + else { + /* case 0xCF: /* RST 1 */ + RST(1); + } + } + } + } + } + else { + if(!(INS&0x08)) { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xD0: /* RNC */ + INCPC; + if(trace) + strcat(p,"RNC"); + if(!CF) { + DORET; + } + cpu_delay(6); + /* return; */ + } + else { + /* case 0xD1: /* POP D */ + POP(DE,D,E,"D"); + } + } + else { + if(!(INS&0x01)) { + /* case 0xD2: /* JNC addr */ + INCPC; + if(trace) + sprintf(p,"JNC %04x",INS16); + if(!CF) { + SETPCINS16; + cpu_delay(3); + } + else + INCPC2; + cpu_delay(7); + /* return; */ + } + else { + /* case 0xD3: /* OUT port */ + INCPC; + if(trace) + sprintf(p,"OUT %02x",INS); + out(INS,A); + INCPC; + cpu_delay(10); + /* return; */ + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xD4: /* CNC addr */ + INCPC; + if(trace) + sprintf(p,"CNC %04x",INS); + INCPC2; + if(!CF) { + DOCALL; + } + cpu_delay(9); + /* return; */ + } + else { + /* case 0xD5: /* PUSH D */ + PUSH(DE,D,E,"D"); + } + } + else { + if(!(INS&0x01)) { + /* case 0xD6: /* SUI n */ + INCPC; + if(trace) + sprintf(p,"SUI %02x",INS); + i=A; + i-=INS; + j = (((A&0x0F)-(INS&0x0F)) &0x10)>>4; + A=i; + if (i>0xFF) + i = 1; + else + i = 0; + INCPC; + setflags(A,-1,-1,j,-1,i); + cpu_delay(7); + /* return; */ + } + else { + /* case 0xD7: /* RST 2 */ + RST(2); + } + } + } + } + else { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xD8: /* RC */ + if(trace) + strcat(p,"RC"); + INCPC; + if(CF) { + DORET; + } + cpu_delay(6); + /* return; */ + } + else { + /* case 0xD9: /* INVALID? */ + bail("0xD9 is invalid"); + /* return; */ + } + } + else { + if(!(INS&0x01)) { + /* case 0xDA: /* JC addr */ + INCPC; + if(trace) + sprintf(p,"JC %04x",INS16); + if(CF) { + SETPCINS16; + cpu_delay(3); + } + else + INCPC2; + cpu_delay(7); + } + else { + /* case 0xDB: /* IN port */ + INCPC; + if(trace) + sprintf(p,"IN %x",INS); + A=inport(INS); + INCPC; + cpu_delay(10); + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xDC: /* CC addr */ + INCPC; + if(trace) + sprintf(p,"CC %04x",INS16); + INCPC2; + if(CF) { + DOCALL; + } + cpu_delay(9); + /* return; */ + } + else { + /* case 0xDD: /* INVALID? */ + bail("0xDD is invalid"); + /* return; */ + } + } + else { + if(!(INS&0x01)) { + /* case 0xDE: /* SBI n */ + INCPC; + if(trace) + sprintf(p,"SBI %02x",INS); + i=A; + i-=INS; + i-=(CF?1:0); + j = (((A&0x0F)-(INS&0x0F)-(CF?1:0)) &0x10)>>4; + A=i; + if (i>0xFF) + i = 1; + else + i = 0; + setflags(A,-1,-1,j,-1,i); + INCPC; + cpu_delay(7); + /* return; */ + } + else { + /* case 0xDF: /* RST 3 */ + RST(3); + } + } + } + } + } + } + else { + if(!(INS&0x10)) { + if(!(INS&0x08)) { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xE0: /* RPO */ + INCPC; + if(!PF) { + DORET; + } + cpu_delay(6); + } + else { + /* case 0xE1: /* POP H */ + POP(HL,H,L,"H"); + } + } + else { + if(!(INS&0x01)) { + /* case 0xE2: /* JPO addr */ + INCPC; + if(trace) + sprintf(p,"JPO %04x",INS16); + if(!PF) { + SETPCINS16; + cpu_delay(3); + } + else + INCPC2; + cpu_delay(7); + } + else { + /* case 0xE3: /* XTHL */ + INCPC; + if(trace) + strcat(p,"XTHL"); + i=H; + j=L; + L=MEM(SP); + H=MEM(SP+1); + /* HL=MEM16(SP); */ + MEM(SP)=j; + MEM(SP+1)=i; + /* MEM16(SP)=i; */ + cpu_delay(16); + /* return; */ + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xE4: /* CPO addr */ + INCPC; + INCPC2; + if(!PF) { + DOCALL; + } + cpu_delay(9); + /* return; */ + } + else { + /* case 0xE5: /* PUSH H */ + PUSH(HL,H,L,"H"); + } + } + else { + if(!(INS&0x01)) { + /* case 0xE6: /* ANI n */ + INCPC; + if(trace) + sprintf(p,"ANI %02x",INS); + A=A&INS; + INCPC; + setflags(A,-1,-1,1,-1,0); + cpu_delay(7); + /* return; */ + } + else { + /* case 0xE7: /* RST 4 */ + RST(4); + } + } + } + } + else { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xE8: /* RPE */ + INCPC; + if(trace) + strcat(p,"RPE"); + if(PF) { + DORET; + } + cpu_delay(6); + /* return; */ + } + else { + /* case 0xE9: /* PCHL */ + PCH=H; + PCL=L; + /* PC=HL; */ + cpu_delay(6); + /* return; */ + } + } + else { + if(!(INS&0x01)) { + /* case 0xEA: /* JPE addr */ + INCPC; + if(trace) + sprintf(p,"JPE %04x",INS16); + if(PF) { + SETPCINS16; + cpu_delay(3); + } + else + INCPC2; + cpu_delay(7); + /* return; */ + } + else { + /* case 0xEB: /* XCHG */ + if(trace) + strcat(p,"XCHG"); + INCPC; + i=H; + H=D; + D=i; + i=L; + L=E; + E=i; + /* i=HL; */ + /* HL=DE; */ + /* DE=i; */ + cpu_delay(4); + /* return; */ + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xEC: /* CPE addr */ + INCPC; + if(trace) + sprintf(p,"CPE %04x",INS16); + INCPC2; + if(PF) { + DOCALL; + } + cpu_delay(9); + /* return; */ + } + else { + /* case 0xED: /* INVALID? */ + bail("0xED is invalid"); + /* return; */ + } + } + else { + if(!(INS&0x01)) { + /* case 0xEE: /* XRI n */ + INCPC; + if(trace) + sprintf(p,"XRI %02x",INS); + A=A^INS; + INCPC; + setflags(A,-1,-1,0,-1,0); + cpu_delay(4); + /* return; */ + } + else { + /* case 0xEF: /* RST 5 */ + RST(5); + } + } + } + } + } + else { + if(!(INS&0x08)) { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xF0: /* RP */ + INCPC; + if(trace) + strcat(p,"RP"); + if(!SF) { + DORET; + } + cpu_delay(6); + /* return; */ + } + else { + /* case 0xF1: /* POP PSW */ + POP(AF,A,F,"PSW"); + } + } + else { + if(!(INS&0x01)) { + /* case 0xF2: /* JP addr */ + INCPC; + if(trace) + sprintf(p,"JP %04x",INS16); + if(!SF) { + SETPCINS16; + cpu_delay(3); + } + else + INCPC2; + cpu_delay(7); + /* return; */ + } + else { + /* case 0xF3: /* DI */ + INCPC; + if(trace) + strcat(p,"DI"); + IM|=0x08; + cpu_delay(4); + /* return; */ + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xF4: /* CP addr */ + INCPC; + if(trace) + sprintf(p,"CP %04x",INS16); + INCPC2; + if(!SF) { + DOCALL; + } + cpu_delay(9); + /* return; */ + } + else { + /* case 0xF5: /* PUSH PSW */ + PUSH(AF,A,F,"PSW"); + } + } + else { + if(!(INS&0x01)) { + /* case 0xF6: /* ORI n */ + INCPC; + if(trace) + sprintf(p,"ORI %02x",INS); + A=A|INS; + INCPC; + setflags(A,-1,-1,0,-1,0); + cpu_delay(7); + /* return; */ + } + else { + /* case 0xF7: /* RST 6 */ + RST(6); + } + } + } + } + else { + if(!(INS&0x04)) { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xF8: /* RM */ + INCPC; + if(trace) + strcat(p,"RM"); + if(SF) { + DORET; + } + cpu_delay(6); + /* return; */ + } + else { + /* case 0xF9: /* SPHL */ + INCPC; + if(trace) + strcat(p,"SPHL"); + SPH=H; + SPL=L; + cpu_delay(6); + /* return; */ + } + } + else { + if(!(INS&0x01)) { + /* case 0xFA: /* JM addr */ + INCPC; + if(trace) + sprintf(p,"JM %04x",INS16); + if(SF) { + SETPCINS16; + cpu_delay(3); + } + else + INCPC2; + cpu_delay(7); + /* return; */ + } + else { + /* case 0xFB: /* EI */ + if(trace) + strcat(p,"EI"); + INCPC; + IM&=0xF7; + cpu_delay(4); + /* return; */ + } + } + } + else { + if(!(INS&0x02)) { + if(!(INS&0x01)) { + /* case 0xFC: /* CM addr */ + INCPC; + if(trace) + sprintf(p,"CM %04x",INS16); + INCPC2; + if(SF) { + DOCALL; + } + cpu_delay(9); + /* return; */ + } + else { + /* case 0xFD: /* INVALID? */ + bail("0xFD is invalid"); + /* return; */ + } + } + else { + if(!(INS&0x01)) { + /* case 0xFE: /* CPI n */ + INCPC; + if(trace) + p+=sprintf(p,"CPI %02x",INS); + i=A; + i-=INS; + if(i>0xFF) + i=1; + else + i=0; + j = (((A & 0x0F)-(INS & 0x0F)) & 0x10) >> 4; + setflags(A-INS,-1,-1,j,-1,i); + INCPC; + cpu_delay(7); + /* return; */ + } + else { + /* case 0xFF: /* RST 7 */ + RST(7); + } + } + } + } + } + } + } + } +} diff --git a/src/doins.c b/src/doins.c new file mode 100644 index 0000000..07c9348 --- /dev/null +++ b/src/doins.c @@ -0,0 +1,85 @@ +/* doins.c */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include "cpu.h" +#include "io.h" +#include "m100emu.h" + +static char paritybits[256]={ + 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, + 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00, + 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00, + 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, + 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00, + 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, + 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, + 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00, + 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00, + 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, + 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, + 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00, + 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, + 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00, + 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00, + 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, +}; + +__inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry) +{ + if(sign>=0) + F=(F&0x7F)|(sign?0x80:0); + else if(sign==-1) + F=(F&0x7F)|(regval&0x80); + + if(zero>=0) + F=(F&0xBF)|(sign?0x40:0); + else if(zero==-1) + F=(F&0xBF)|(regval?0:0x40); + + if(auxcarry>=0) + F=(F&0xEF)|(auxcarry?0x10:0); + + if(parity>=0) + F=(F&0xFB)|(parity?0x04:0); + else if(parity==-1) { + /* Table Lookup */ + F=(F&0xFB)|paritybits[regval]; + } + + if(carry>=0) + F=(F&0xFE)|(carry?1:0); +} + +/* inline void do_instruct(void) +#include "do_instruct.h" +*/ diff --git a/src/doins.h b/src/doins.h new file mode 100644 index 0000000..d723013 --- /dev/null +++ b/src/doins.h @@ -0,0 +1,36 @@ +/* doins.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef _DOINS_H_ +#define _DOINS_H_ + +void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry); + +#endif diff --git a/src/io.c b/src/io.c new file mode 100644 index 0000000..069135c --- /dev/null +++ b/src/io.c @@ -0,0 +1,641 @@ +/* io.c */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include "cpu.h" +#include "gen_defs.h" +#include "io.h" +#include + +uchar lcd[10][256]; +uchar lcdpointers[10]={0,0,0,0,0,0,0,0,0,0}; +uchar lcddriver=0; +uchar lcd_fresh_ptr[10] = {1,1,1,1,1,1,1,1,1,1 }; +uchar ioBA; +uchar ioB9; +uchar ioE8; + +uchar keyscan[9] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + +uint lcdbits=0; +time_t clock_time = 0; +time_t last_clock_time = 1; +struct tm *mytime ; + +unsigned long gSpecialKeys = 0; +unsigned char gKeyStates[128]; +int gDelayUpdateKeys = 0; +int gDelayCount = 0; +int gModel = MODEL_M100; + +uchar clock_sr[5]; /* 40 Bit shift register */ +uchar clock_sr_index = 0; +uchar clock_serial_out = 0; + +char keyin[9]; + +void update_keys(void) +{ + int equal = 1; + int buf_index = 0xFF9A; + int c; + uchar key; + + /* Insure keystroke was recgonized by the system */ + for (c = 0; c < 9; c++) + { + key = (uchar) ((~keyscan[c]) & 0xFF); + /* Old keyscan matrix must match buffer in memory */ + if (memory[buf_index] != key) + { + equal = 0; + break; + } + buf_index++; + } + + if (!equal) + { + if (++gDelayCount < 20) + { + gDelayUpdateKeys = 1; + return; + } + } + + gDelayUpdateKeys = 0; + gDelayCount = 0; + + keyscan[0] = ~(gKeyStates['z'] | (gKeyStates['x'] << 1) | + (gKeyStates['c'] << 2) | (gKeyStates['v'] << 3) | + (gKeyStates['b'] << 4) | (gKeyStates['n'] << 5) | + (gKeyStates['m'] << 6) | (gKeyStates['l'] << 7)); + + keyscan[1] = ~(gKeyStates['a'] | (gKeyStates['s'] << 1) | + (gKeyStates['d'] << 2) | (gKeyStates['f'] << 3) | + (gKeyStates['g'] << 4) | (gKeyStates['h'] << 5) | + (gKeyStates['j'] << 6) | (gKeyStates['k'] << 7)); + + keyscan[2] = ~(gKeyStates['q'] | (gKeyStates['w'] << 1) | + (gKeyStates['e'] << 2) | (gKeyStates['r'] << 3) | + (gKeyStates['t'] << 4) | (gKeyStates['y'] << 5) | + (gKeyStates['u'] << 6) | (gKeyStates['i'] << 7)); + + keyscan[3] = ~(gKeyStates['o'] | (gKeyStates['p'] << 1) | + (gKeyStates['['] << 2) | (gKeyStates[';'] << 3) | + (gKeyStates['\''] << 4) | (gKeyStates[','] << 5) | + (gKeyStates['.'] << 6) | (gKeyStates['/'] << 7)); + + keyscan[4] = ~(gKeyStates['1'] | (gKeyStates['2'] << 1) | + (gKeyStates['3'] << 2) | (gKeyStates['4'] << 3) | + (gKeyStates['5'] << 4) | (gKeyStates['6'] << 5) | + (gKeyStates['7'] << 6) | (gKeyStates['8'] << 7)); + + keyscan[5] = ~(gKeyStates['9'] | (gKeyStates['0'] << 1) | + (gKeyStates['-'] << 2) | (gKeyStates['='] << 3)) & + (unsigned char) (gSpecialKeys >> 24); + + keyscan[6] = (unsigned char) ((gSpecialKeys >> 16) & 0xFF); + + keyscan[7] = (unsigned char) ((gSpecialKeys >> 8) & 0xFF); + + keyscan[8] = (unsigned char) (gSpecialKeys & 0xFF); +} +void init_io(void) +{ + int c; + + gSpecialKeys = 0xFFFFFFFF; + + for (c = 0; c < 128; c++) + gKeyStates[c] = 0; + + update_keys(); +} + + +void out(uchar port, uchar val) +{ + static cROM=0; + int c; + + switch(port) { + case 0xA0: /* Modem control port */ + /* + Bit: + 0 - Modem telephone relay (1-Modem connected to phone + line) + 1 - Modem enable (1-Modem chip enabled) */ + return; + + case 0xB0: /* PIO Command/Status Register */ + case 0xB8: + /* + Bit: + 0 - Direction of Port A (0-input, 1-output) + 1 - Direction of Port B (0-input, 1-output) + 2 & 3 - Port C definition (00 - All input, 11 - All output, + 01 - Alt 3, 10 - Alt 4 (see Intel technical sheets + for more information)) + 4 - Enable Port A interrupt (1 - enable) + 5 - Enable Port B interrupt (1 - enable) + 6 & 7 - Timer mode (00 - No effect on counter, 01 - Stop + counter immediately, 10 - Stop counter after TC, 11 + - Start counter) */ + return; + + case 0xB1: /* 8155 PIO Port A */ + case 0xB9: + /* + 8 bit data port for printer output, keyboard column strobe, + and LCD + In addition, the first 5 bits of this port is used to + control the 1990 real time clock chip. The configuration of + these five bits are: + Bit: + 0 - C0 + 1 - C1 + 2 - C2 + 3 - Clock + 4 - Serial data into clock chip */ + lcdbits = (lcdbits & 0x0300) | val; + + /* Check for clock chip serial shift clock */ + if ((val & 0x08) && !(ioB9 & 0x08)) + { + + /* Increment shift register index */ + clock_sr_index++; + + /* Update clock chip output bit based on index */ + clock_serial_out = clock_sr[clock_sr_index / 8] & (0x01 << clock_sr_index % 8) ? 1 : 0; + + } + ioB9 = val; + return; + + case 0xB2: /* 8155 PIO Port B. */ + case 0xBA: + /* + Bit: + 0 - Column 9 select line for keyboard. This line is + also used for the CS-28 line of the LCD. + 1 - CS 29 line of LCD + 2 - Beep toggle (1-Data from bit 5, 0-Data from 8155 + timer) + 3 - Serial toggle (1-Modem, 0-RS232) + 4 - Software on/off switch for computer + 5 - Data to beeper if bit 2 set. Set if bit 2 low. + 6 - DTR (not) line for RS232 + 7 - RTS (not) line for RS232 */ + ioBA = A; + lcdbits = (lcdbits & 0x00FF) | ((A & 0x03) << 8); + + /* Check if software "turned the simulator off" */ + if (A & 0x10) + { + power_down(); + } + return; + + case 0xB3: /* 8155 PIO Port C */ + case 0xBB: + return; + + case 0xB4: /* 8155 Timer register. LSB of timer counter */ + case 0xBC: + return; + + case 0xB5: /* 8155 Timer register. MSB of timer counter */ + case 0xBD: + return; + + case 0xC0: /* Bidirectional data bus for UART (6402) (C0H-CFH same) */ + case 0xC1: + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + return; + + case 0xD0: /* Status control register for UART, modem, and phone (6402) */ + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + case 0xD8: + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDD: + case 0xDE: + case 0xDF: + /* + Bits: + 0 - Stop Bits (1-1.5, 0-2) + 1 - Parity (1-even, 0-odd) + 2 - Parity Enable (1-no parity, 0-parity enabled) + 3 - Data length (00-5 bits, 10-6 bits, 01-7 bits, 11-8 + bits) + 4 - Data length (see bit 3) */ + return; + + case 0xE0: /* Keyboard input and misc. device select (E0H-EFH same) */ + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xED: + case 0xEE: + case 0xEF: + /* + Bits: + 0 - ROM select (0-Standard ROM, 1-Option ROM) + 1 - STROBE (not) signal to printer + 2 - STROBE for Clock chip (1990) + 3 - Remote plug control signal */ + if(val&0x01) { + if(cROM!=1) { + memcpy(memory,optROM,ROMSIZE); + cROM=1; + } + } + else { + if(cROM!=0) { + memcpy(memory,sysROM,ROMSIZE); + cROM=0; + } + } + if ((val & 0x04) && !(ioE8 & 0x04)) + { + /* Clock chip command strobe */ + switch (ioB9 & 0x07) + { + case 0: /* NOP */ + break; + case 1: /* Serial Shift */ + clock_serial_out = clock_sr[0] & 0x01; + clock_sr_index = 0; + break; + case 2: /* Write Clock chip */ + clock_sr_index = 0; + break; + case 3: /* Read clock chip */ + clock_time = time(&clock_time); + if (clock_time == last_clock_time) + break; + + last_clock_time = clock_time; + mytime = localtime(&clock_time); + + /* Update Clock Chip Shift register Seconds */ + clock_sr[0] = mytime->tm_sec % 10; + clock_sr[0] |= (mytime->tm_sec / 10) << 4; + + /* Minutes */ + clock_sr[1] = mytime->tm_min % 10; + clock_sr[1] |= (mytime->tm_min / 10) << 4; + + /* Hours */ + clock_sr[2] = mytime->tm_hour % 10; + clock_sr[2] |= (mytime->tm_hour / 10) << 4; + + /* Day of month */ + clock_sr[3] = mytime->tm_mday % 10; + clock_sr[3] |= (mytime->tm_mday / 10) << 4; + + /* Day of week */ + clock_sr[4] = (mytime->tm_wday) % 10; + + /* Month */ + clock_sr[4] |= (mytime->tm_mon + 1) << 4; + + clock_sr_index = 0; + + if ((memory[0xF92E] == 0) && (memory[0xF92D] == 0)) + { + memory[0xF92D] = mytime->tm_year % 10; + memory[0xF92E] = (mytime->tm_year % 100) / 10; + } + break; + } + } + + ioE8 = val; + + return; + + case 0xF0: /* LCD display data bus (F0H-FFH same) */ + case 0xF1: + case 0xF2: + case 0xF3: + case 0xF4: + case 0xF5: + case 0xF6: + case 0xF7: + case 0xF8: + case 0xF9: + case 0xFA: + case 0xFB: + case 0xFC: + case 0xFD: + case 0xFE: /* Row select */ + for (c = 0; c < 10; c++) + { + if (lcdbits & (1 << c)) + { + /* Save page and column info for later use */ + lcdpointers[c]=A; + + /* New pointer loaded - mark it as "fresh" */ + if ((A & 0x3F) < 50) + lcd_fresh_ptr[c] = 1; + } + } + return; + case 0xFF: /* Data output */ + for (c = 0; c < 10; c++) + { + if (lcdbits & (1 << c)) + { + if ((lcdpointers[c]&0x3f) < 50) + { + /* Save Byte in LCD memory */ + lcd[c][lcdpointers[c]]=A; + + /* Draw the byte on the display */ + drawbyte(c,lcdpointers[c],A); + + /* Update the pointer if */ + lcdpointers[c]++; + if ((lcdpointers[c] & 0x3F) >= 50) + lcdpointers[c] &= 0xC0; + + /* We just changed the pointer so it isn't fresh any more */ + lcd_fresh_ptr[c] = 0; + } + } + } + return; + } +} + +int inport(uchar port) +{ + int c; + unsigned char ret; + + switch(port) { + case 0x82: /* Optional IO thinger? */ + return(0xA2); + + case 0xA0: /* Modem control port */ + return(0xA0); + + case 0xB0: /* PIO Command/Status Register */ + case 0xB8: + /* + Bit: + 0 - Port A interrupt request + 1 - Port A buffer full/empty (input/output) + 2 - Port A interrupt enabled + 3 - Port B interrupt request + 4 - Port B buffer full/empty (input/output) + 5 - Port B interrupt enabled + 6 - Timer interrupt (status of TC pin) + 7 - Not used */ + + /* Force TC high */ + return(0x89); + + case 0xB1: /* 8155 PIO Port A */ + case 0xB9: + return(lcdbits & 0xFF); + + case 0xB2: /* 8155 PIO Port B. */ + case 0xBA: + return(ioBA); + + case 0xB3: /* 8155 PIO Port C */ + case 0xBB: + /* + Bits: + 0 - Serial data input from clock chip + 1 - Busy (not) signal from printer + 2 - Busy signal from printer + 3 - Data from BCR + 4 - CTS (not) line from RS232 + 5 - DSR (not) line from RS232 + 6-7 - Not avaiable on 8155 */ + return(clock_serial_out); + + case 0xB4: /* 8155 Timer register. LSB of timer counter */ + case 0xBC: + return(0); + + case 0xB5: /* 8155 Timer register. MSB of timer counter */ + case 0xBD: + return(0); + + case 0xC0: /* Bidirectional data bus for UART (6402) (C0H-CFH same) */ + case 0xC1: + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + return(0); + + case 0xD0: /* Status control register for UART, modem, and phone (6402) */ + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + case 0xD8: + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDD: + case 0xDE: + case 0xDF: + /* + Bits: + 0 - Data on telephone line (used to detect carrier) + 1 - Overrun error from UART + 2 - Framing error from UART + 3 - Parity error from UART + 4 - Transmit buffer empty from UART + 5 - Ring line on modem connector + 6 - Not used + 7 - Low Power signal from power supply (LPS not) */ + return(0x90); + + case 0xE0: /* Keyboard input and misc. device select (E0H-EFH same) */ + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + ret = 0xFF; + + /* Read keyboard status -- First check bit 0 of output port 0xBA */ + if ((ioBA & 0x01) == 0) + return (unsigned char) (gSpecialKeys & 0xFF); + + if (ioB9 == 0) + { + return keyscan[7] & keyscan[6] & keyscan[5] & keyscan[4] & + keyscan[3] & keyscan[2] & keyscan[1] & keyscan[0]; + } + + /* Check Bit 7 of port B9 */ + if ((ioB9 & 0x80) == 0) + return keyscan[7]; + + /* Check Bit 6 of port B9 */ + if ((ioB9 & 0x40) == 0) + return keyscan[6]; + + /* Check Bit 5 of port B9 */ + if ((ioB9 & 0x20) == 0) + return keyscan[5]; + + /* Check Bit 4 of port B9 */ + if ((ioB9 & 0x10) == 0) + return keyscan[4]; + + /* Check Bit 3 of port B9 */ + if ((ioB9 & 0x08) == 0) + return keyscan[3]; + + /* Check Bit 2 of port B9 */ + if ((ioB9 & 0x04) == 0) + return keyscan[2]; + + /* Check Bit 1 of port B9 */ + if ((ioB9 & 0x02) == 0) + return keyscan[1]; + + /* Check Bit 0 of port B9 */ + if ((ioB9 & 0x01) == 0) + return keyscan[0]; + + return ret; + + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xED: + case 0xEE: + case 0xEF: + /* + 8 bit data row from keyboard strobe */ + return(0x00); + + case 0xF0: /* LCD display data bus (F0H-FFH same) */ + case 0xF1: + case 0xF2: + case 0xF3: + case 0xF4: + case 0xF5: + case 0xF6: + case 0xF7: + case 0xF8: + case 0xF9: + case 0xFA: + case 0xFB: + case 0xFC: + case 0xFD: + case 0xFE: + return(64); + case 0xFF: + /* Loop through all LCD driver modules */ + for (c = 0; c < 10; c++) + { + /* Check if this driver is enabled */ + if (lcdbits & (1 << c)) + { + /* Get the return data from the LCD memory */ + int ret = lcd[c][lcdpointers[c]]; + + /* Update the pointer only if it isn't fresh */ + if (!lcd_fresh_ptr[c]) + lcdpointers[c]++; + + /* We just did a read, so pointer no longer fresh */ + lcd_fresh_ptr[c] = 0; + return ret; + } + } + return(0); + + default: + return(0); + } +} diff --git a/src/io.h b/src/io.h new file mode 100644 index 0000000..f726450 --- /dev/null +++ b/src/io.h @@ -0,0 +1,91 @@ +/* io.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef _IO_H_ +#define _IO_H_ + +#include "gen_defs.h" + +extern unsigned long gSpecialKeys; +extern unsigned char gKeyStates[128]; +extern uchar ioBA; +extern int gModel; + +#ifdef __cplusplus +extern "C" { +#endif +void init_io(void); +void out(uchar port, uchar val); +void update_keys(void); +int inport(uchar port); +#ifdef __cplusplus +} +#endif + + +#define MT_SHIFT 0x00000001 +#define MT_CTRL 0x00000002 +#define MT_GRAPH 0x00000004 +#define MT_CODE 0x00000008 +#define MT_NUM 0x00000010 // Not used +#define MT_CAP_LOCK 0x00000020 +#define MT_PAUSE 0x00000080 + +#define MT_F1 0x00000100 +#define MT_F2 0x00000200 +#define MT_F3 0x00000400 +#define MT_F4 0x00000800 +#define MT_F5 0x00001000 +#define MT_F6 0x00002000 +#define MT_F7 0x00004000 +#define MT_F8 0x00008000 + +#define MT_SPACE 0x00010000 +#define MT_BKSP 0x00020000 +#define MT_TAB 0x00040000 +#define MT_ESC 0x00080000 +#define MT_PASTE 0x00100000 +#define MT_LABEL 0x00200000 // F9 +#define MT_PRINT 0x00400000 +#define MT_ENTER 0x00800000 + + +#define MT_LEFT 0x10000000 +#define MT_RIGHT 0x20000000 +#define MT_UP 0x40000000 +#define MT_DOWN 0x80000000 + +enum { + MODEL_M100 + ,MODEL_M102 + ,MODEL_T200 +}; + +#endif diff --git a/src/m100emu.c b/src/m100emu.c new file mode 100644 index 0000000..c455ed3 --- /dev/null +++ b/src/m100emu.c @@ -0,0 +1,342 @@ +/* m100emu.c */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#ifdef _WIN32 +#include +#endif + +#ifdef __unix__ +#include +#endif + +#include "io.h" +#include "cpu.h" +#include "doins.h" +#include "display.h" +#include "genwrap.h" +#include "filewrap.h" + +int fullspeed=0; + +uchar cpu[14]; +uchar memory[65536]; +uchar sysROM[32768]; +uchar optROM[32768]; +char op[26]; +unsigned long long int cycles=0; +unsigned long long int instructs=0; +unsigned long long int last_isr_cycle=0; +int trace=0; +int starttime; +FILE *tracefile; +DWORD rst7cycles = 9830; +DWORD one_sec_cycle_count; +DWORD one_sec_time; +unsigned long long int one_sec_cycles; +DWORD update_secs = 0; +float cpu_speed; +int gExitApp = 0; + +DWORD last_one_sec_time; + + +#ifdef _WIN32 +__inline double hirestimer(void) +{ + static LARGE_INTEGER pcount, pcfreq; + static int initflag; + + if (!initflag) + { + QueryPerformanceFrequency(&pcfreq); + initflag++; + } + + QueryPerformanceCounter(&pcount); + return (double)pcount.QuadPart / (double)pcfreq.QuadPart; +} +#else +__inline double hirestimer(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (double)tv.tv_sec + (double)tv.tv_usec / 1000000; +} +#endif + +void cpu_delay(int cy) +{ + static double last_instruct=0; + + if(last_instruct==0) + last_instruct=hirestimer(); + if(!fullspeed) { + last_instruct+=cy*0.000000416666666667; + while(hirestimer() (rst7cycles * 0.8)) || (twice_flag == 2)) + { + rst7cycles = new_rst7cycles; + if (rst7cycles < 9830) + rst7cycles = 9830; + cpu_speed = (float) (.000097656 * one_sec_cycle_count); /* 2.4 Mhz / 24576 */ + display_cpu_speed(); + twice_flag = 0; + } + else + twice_flag++; + } + last_one_sec_time = one_sec_time; + one_sec_time = systime; + + } + } + process_windows_event(); +} + +void emulate(void) +{ + unsigned int i; + unsigned int j; + int top=0; + char *p; + FILE *fd; + int currtime; + int nxtmaint=1; + + starttime=msclock(); + while(!gExitApp) { +#include "do_instruct.h" + if(trace && tracefile != NULL) + fprintf(tracefile, "%-22s A:%02X F:%02X B:%02X C:%02X D:%02X E:%02X H:%02X L:%02X PC:%04X SP:%04X IM:%02X *SP:%04X\n" + ,op,A,F,B,C,D,E,H,L,PC,SP,IM,MEM16(SP)); + check_interrupts(); + nxtmaint--; + if(!nxtmaint) { + maint(); + nxtmaint=128; + } + + if (gExitApp) + break; + } + + fd=fopen("RAM.bin", "wb+"); + if(fd!=0) + { + fwrite(memory+ROMSIZE, 1, RAMSIZE, fd); + fclose(fd); + } +} + +#ifdef __unix__ +void handle_sig(int sig) +{ + bail("Kill by signal"); +} +#endif + +int main(int argc, char **argv) +{ + int i; + + for(i=0;i CTRL-C)" }, + { 0x726A, "Enable interrupts as normal" }, + { 0x7270, "Check keyboard queue for pending characters" }, + { 0x7283, "Check for break or wait (CTRL-S)" }, + { 0x729F, "Check if SHIFT-BREAK is being pressed" }, + { 0x72B1, "Scan BREAK,CAPS,NUM,CODE,GRAPH,CTRL,SHIFT & set bits in A" }, + { 0x72C5, "Produce a tone of DE freq and B duration" }, + { 0x7329, "Copy clock chip regs to M" }, + { 0x732A, "Update clock chip regs from M" }, + { 0x7352, "Read next bit from Clock Chip" }, + { 0x7383, "Set clock chip mode" }, + { 0x73A9, "Blink the cursor" }, + { 0x744C, "Plot (set) point (D,E) on the LCD" }, + { 0x73EE, "Character plotting level 7. Plot character in C on LCD at (H,L)" }, + { 0x744D, "Clear (reset) point (D,E) on the LCD" }, + { 0x74A2, "Byte Plot - Send bit pattern to LCD for character" }, + { 0x753B, "Enable LCD drivers after short delay" }, + { 0x7548, "Wait for LCD driver to be available" }, + { 0x7551, "8155 PIO chip bit patterns for LCD drivers" }, + { 0x7643, "8155 PIO chip bit patterns for LCD drivers" }, + { 0x7657, "Delay routine - decrement C until zero" }, + { 0x765C, "Set interrupt to 1DH" }, + { 0x7662, "Beep routine" }, + { 0x7676, "Click sound port" }, + { 0x7682, "Check for optional external controller" }, + { 0x768F, "Optional external controller driver" }, + { 0x7711, "LCD char generator shape table (20H-7FH" }, + { 0x78F1, "LCD char generator shape table (80H-FFH)" }, + { 0x7BF1, "Keyboard conversion matrix" }, + { 0x7D33, "Boot routine" }, + { 0x7DE7, "Cold boot routine" }, + { 0x7EA6, "Display TRS-80 Model number & Free bytes on LCD" }, + { 0x7EAC, "Display number of free bytes on LCD" }, + { 0x7EAC, "Initialize RST 38H RAM vector table" }, + { 0x7EE1, "Calculate physical RAM available" }, + { 0x7F01, "Initial clock chip register values" }, + { 0x7F98, "MENU Text Strings" }, + { 0x7FD6, "RST 38H RAM vector driver routine" }, + { 0xF5F9, "RST 5.5 RAM Vector" }, + { 0xF5FC, "RST 6.5 RAM Vector" }, + { 0xF5FF, "RST 7.5 RAM Vector" }, + { 0xF602, "RAM vector for TRAP interrupt" }, + { 0xF605, "Detect Option ROM" }, + { -1, "" }, +}; + +RomDescription_t gM100_Desc = { + gM100_Tables, + gM100_Vars, + gM100_Funs +}; \ No newline at end of file From 6a4e894a9978bc484a46da3c47f4fa8607d8bbb3 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Thu, 5 Aug 2004 07:19:02 +0000 Subject: [PATCH 003/327] Add wrapper files. --- src/filewrap.h | 149 ++++++++++++++++++ src/gen_defs.h | 253 ++++++++++++++++++++++++++++++ src/genwrap.c | 418 +++++++++++++++++++++++++++++++++++++++++++++++++ src/genwrap.h | 294 ++++++++++++++++++++++++++++++++++ src/wrapdll.h | 64 ++++++++ 5 files changed, 1178 insertions(+) create mode 100644 src/filewrap.h create mode 100644 src/gen_defs.h create mode 100644 src/genwrap.c create mode 100644 src/genwrap.h create mode 100644 src/wrapdll.h diff --git a/src/filewrap.h b/src/filewrap.h new file mode 100644 index 0000000..c9b7b6f --- /dev/null +++ b/src/filewrap.h @@ -0,0 +1,149 @@ +/* filewrap.h */ + +/* File system-call wrappers */ + +/* $Id$ */ + +/**************************************************************************** + * @format.tab-size 4 (Plain Text/Source Code File Header) * + * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * + * * + * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * See the GNU Lesser General Public License for more details: lgpl.txt or * + * http://www.fsf.org/copyleft/lesser.html * + * * + * Anonymous FTP access to the most recent released source is available at * + * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * + * * + * Anonymous CVS access to the development source and modification history * + * is available at cvs.synchro.net:/cvsroot/sbbs, example: * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login * + * (just hit return, no password is necessary) * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src * + * * + * For Synchronet coding style and modification guidelines, see * + * http://www.synchro.net/source.html * + * * + * You are encouraged to submit any modifications (preferably in Unix diff * + * format) via e-mail to mods@synchro.net * + * * + * Note: If this box doesn't appear square, then you need to fix your tabs. * + ****************************************************************************/ + +#ifndef _FILEWRAP_H +#define _FILEWRAP_H + +#include "wrapdll.h" /* DLLEXPORT and DLLCALL */ + +#include /* S_IREAD and S_IWRITE (for use with sopen) */ +#include + +#if defined(__unix__) + #include /* read, write, close, ftruncate, lseek, etc. */ +#endif + +#if defined(_WIN32) || defined(__BORLANDC__) + #include +#endif + +/**********/ +/* Macros */ +/**********/ + +#if defined(_WIN32) + + #include /* O_BINARY */ + #include /* OF_SHARE_ */ + #include /* SH_DENY */ + + #ifndef SH_DENYNO + #define SH_DENYNO OF_SHARE_DENY_NONE + #define SH_DENYWR OF_SHARE_DENY_WRITE + #define SH_DENYRW OF_SHARE_EXCLUSIVE + #endif + +#elif defined(__unix__) + + #include + #ifdef __solaris__ + #define LOCK_NB 1 + #define LOCK_SH 2 + #define LOCK_EX 4 + #endif + + #ifdef __QNX__ + #include + #define L_SET SEEK_SET + #else + #define O_TEXT 0 /* all files in binary mode on Unix */ + #define O_BINARY 0 /* all files in binary mode on Unix */ + #undef O_DENYNONE + #define O_DENYNONE (1<<31) /* req'd for Baja/nopen compatibility */ + + #define SH_DENYNO 2 /* no locks */ + #ifdef F_SANEWRLCKNO + #define SH_DENYRW F_SANEWRLCKNO /* exclusive lock */ + #else + #define SH_DENYRW F_WRLCK /* exclusive lock */ + #endif + + #ifdef F_SANERDLCKNO + #define SH_DENYWR F_SANERDLCKNO /* shareable lock */ + #else + #define SH_DENYWR F_RDLCK /* shareable lock */ + #endif + #endif + #define chsize(fd,size) ftruncate(fd,size) + #define tell(fd) lseek(fd,0,SEEK_CUR) + +#elif defined(__OS2__) + + #include /* SH_DENY */ + +#endif + +/* Standard file descriptors. */ +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 /* Standard input */ +#define STDOUT_FILENO 1 /* Standard output */ +#define STDERR_FILENO 2 /* Standard error output */ +#endif + +#ifndef O_DENYNONE +#define O_DENYNONE SH_DENYNO +#endif + +/**************/ +/* Prototypes */ +/**************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +#if !defined(__BORLANDC__) + DLLEXPORT int DLLCALL lock(int fd, long pos, long len); + DLLEXPORT int DLLCALL unlock(int fd, long pos, long len); +#endif + +#if !defined(__BORLANDC__) && defined(__unix__) + DLLEXPORT int DLLCALL sopen(const char* fn, int access, int share, ...); + DLLEXPORT long DLLCALL filelength(int fd); +#endif + +#if defined(__unix__) + DLLEXPORT FILE * DLLCALL _fsopen(char *pszFilename, char *pszMode, int shmode); +#endif + +DLLEXPORT time_t DLLCALL filetime(int fd); + +#if defined(__cplusplus) +} +#endif + +#endif /* Don't add anything after this line */ diff --git a/src/gen_defs.h b/src/gen_defs.h new file mode 100644 index 0000000..d9c3ba2 --- /dev/null +++ b/src/gen_defs.h @@ -0,0 +1,253 @@ +/* gen_defs.h */ + +/* General(ly useful) constant, macro, and type definitions */ + +/* $Id$ */ + +/**************************************************************************** + * @format.tab-size 4 (Plain Text/Source Code File Header) * + * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * + * * + * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * See the GNU Lesser General Public License for more details: lgpl.txt or * + * http://www.fsf.org/copyleft/lesser.html * + * * + * Anonymous FTP access to the most recent released source is available at * + * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * + * * + * Anonymous CVS access to the development source and modification history * + * is available at cvs.synchro.net:/cvsroot/sbbs, example: * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login * + * (just hit return, no password is necessary) * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src * + * * + * For Synchronet coding style and modification guidelines, see * + * http://www.synchro.net/source.html * + * * + * You are encouraged to submit any modifications (preferably in Unix diff * + * format) via e-mail to mods@synchro.net * + * * + * Note: If this box doesn't appear square, then you need to fix your tabs. * + ****************************************************************************/ + +#ifndef _GEN_DEFS_H +#define _GEN_DEFS_H + +#include + +/* Resolve multi-named errno constants */ +#if defined(EDEADLK) && !defined(EDEADLOCK) + #define EDEADLOCK EDEADLK +#endif + +#if defined(_WIN32) + #define WIN32_LEAN_AND_MEAN /* Don't bring in excess baggage */ + #include +#elif defined(__OS2__) + #define INCL_BASE /* need this for DosSleep prototype */ + #include +#else + #if (defined(__APPLE__) && defined(__MACH__) && defined(__POWERPC__)) || defined (__NetBSD__) + #ifndef __unix__ + #define __unix__ + #endif + #endif +#endif + + +#include + + /* Control characters */ +#define STX 0x02 /* Start of text ^B */ +#define ETX 0x03 /* End of text ^C */ +#define BEL 0x07 /* Bell/beep ^G */ +#define FF 0x0c /* Form feed ^L */ +#define ESC 0x1b /* Escape ^[ */ +#define DEL 0x7f /* Delete ^BS */ +#define BS '\b' /* Back space ^H */ +#define TAB '\t' /* Horizontal tabulation ^I */ +#define LF '\n' /* Line feed ^J */ +#define CR '\r' /* Carriage return ^M */ + +enum { + CTRL_A=1 + ,CTRL_B + ,CTRL_C + ,CTRL_D + ,CTRL_E + ,CTRL_F + ,CTRL_G + ,CTRL_H + ,CTRL_I + ,CTRL_J + ,CTRL_K + ,CTRL_L + ,CTRL_M + ,CTRL_N + ,CTRL_O + ,CTRL_P + ,CTRL_Q + ,CTRL_R + ,CTRL_S + ,CTRL_T + ,CTRL_U + ,CTRL_V + ,CTRL_W + ,CTRL_X + ,CTRL_Y + ,CTRL_Z +}; + +/* Unsigned type short-hands */ +#ifndef uchar + #define uchar unsigned char +#endif +#ifndef __GLIBC__ + #ifndef ushort + #define ushort unsigned short + #define uint unsigned int + #define ulong unsigned long + #endif +#endif + +/* Windows Types */ +#ifndef BYTE +#define BYTE uchar +#endif +#ifndef WORD +#define WORD ushort +#endif +#ifndef DWORD +#define DWORD ulong +#endif +#ifndef BOOL +#define BOOL int +#endif +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif +#ifndef HANDLE +#define HANDLE void* +#endif + +/* Custom Types */ +typedef struct { + char* name; + char* value; +} named_string_t; + +typedef struct { + char* name; + int value; +} named_int_t; + +typedef struct { + char* name; + uint value; +} named_uint_t; + +typedef struct { + char* name; + long value; +} named_long_t; + +typedef struct { + char* name; + ulong value; +} named_ulong_t; + +typedef struct { + char* name; + short value; +} named_short_t; + +typedef struct { + char* name; + ushort value; +} named_ushort_t; + +typedef struct { + char* name; + BOOL value; +} named_bool_t; + +/***********************/ +/* Handy String Macros */ +/***********************/ + +/* This is a bound-safe version of strcpy basically - only works with fixed-length arrays */ +#define SAFECOPY(dst,src) sprintf(dst,"%.*s",(int)sizeof(dst)-1,src) +#define TERMINATE(str) str[sizeof(str)-1]=0 +#define SAFEPRINTF(dst,fmt,arg) snprintf(dst,sizeof(dst),fmt,arg), TERMINATE(dst) +#define SAFEPRINTF2(dst,fmt,a1,a2) snprintf(dst,sizeof(dst),fmt,a1,a2), TERMINATE(dst) +#define SAFEPRINTF3(dst,fmt,a1,a2,a3) snprintf(dst,sizeof(dst),fmt,a1,a2,a3), TERMINATE(dst) + +/* Replace every occurance of c1 in str with c2, using p as a temporary char pointer */ +#define REPLACE_CHARS(str,c1,c2,p) for((p)=(str);*(p);(p)++) if(*(p)==(c1)) *(p)=(c2); + +/* ASCIIZ char* parsing helper macros */ +#define SKIP_WHITESPACE(p) while(*(p) && isspace(*(p))) (p)++; +#define FIND_WHITESPACE(p) while(*(p) && !isspace(*(p))) (p)++; +#define SKIP_CHAR(p,c) while(*(p)==c) (p)++; +#define FIND_CHAR(p,c) while(*(p) && *(p)!=c) (p)++; +#define SKIP_CHARSET(p,s) while(*(p) && strchr(s,*(p))!=NULL) (p)++; +#define FIND_CHARSET(p,s) while(*(p) && strchr(s,*(p))==NULL) (p)++; +#define SKIP_ALPHA(p) while(*(p) && isalpha(*(p))) (p)++; +#define FIND_ALPHA(p) while(*(p) && !isalpha(*(p))) (p)++; +#define SKIP_ALPHANUMERIC(p) while(*(p) && isalnum(*(p))) (p)++; +#define FIND_ALPHANUMERIC(p) while(*(p) && !isalnum(*(p))) (p)++; +#define SKIP_DIGIT(p) while(*(p) && isdigit(*(p))) (p)++; +#define FIND_DIGIT(p) while(*(p) && !isdigit(*(p))) (p)++; +#define SKIP_HEXDIGIT(p) while(*(p) && isxdigit(*(p))) (p)++; +#define FIND_HEXDIGIT(p) while(*(p) && !isxdigit(*(p))) (p)++; + +/****************************************************************************/ +/* MALLOC/FREE Macros for various compilers and environments */ +/* MALLOC is used for allocations of 64k or less */ +/* FREE is used to free buffers allocated with MALLOC */ +/* LMALLOC is used for allocations of possibly larger than 64k */ +/* LFREE is used to free buffers allocated with LMALLOC */ +/* REALLOC is used to re-size a previously MALLOCed or LMALLOCed buffer */ +/* FAR16 is used to create a far (32-bit) pointer in 16-bit compilers */ +/* HUGE16 is used to create a huge (32-bit) pointer in 16-bit compilers */ +/****************************************************************************/ +#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__) + #define HUGE16 huge + #define FAR16 far + #if defined(__TURBOC__) + #define REALLOC(x,y) farrealloc(x,y) + #define LMALLOC(x) farmalloc(x) + #define MALLOC(x) farmalloc(x) + #define LFREE(x) farfree(x) + #define FREE(x) farfree(x) + #elif defined(__WATCOMC__) + #define REALLOC realloc + #define LMALLOC(x) halloc(x,1) /* far heap, but slow */ + #define MALLOC malloc /* far heap, but 64k max */ + #define LFREE hfree + #define FREE free + #else /* Other 16-bit Compiler */ + #define REALLOC realloc + #define LMALLOC malloc + #define MALLOC malloc + #define LFREE free + #define FREE free + #endif +#else /* 32-bit Compiler or Small Memory Model */ + #define HUGE16 + #define FAR16 + #define REALLOC realloc + #define LMALLOC malloc + #define MALLOC malloc + #define LFREE free + #define FREE free +#endif + + +#endif /* Don't add anything after this #endif statement */ diff --git a/src/genwrap.c b/src/genwrap.c new file mode 100644 index 0000000..1299e8e --- /dev/null +++ b/src/genwrap.c @@ -0,0 +1,418 @@ +/* genwrap.c */ + +/* General cross-platform development wrappers */ + +/* $Id$ */ + +/**************************************************************************** + * @format.tab-size 4 (Plain Text/Source Code File Header) * + * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * + * * + * Copyright 2002 Rob Swindell - http://www.synchro.net/copyright.html * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * See the GNU Lesser General Public License for more details: lgpl.txt or * + * http://www.fsf.org/copyleft/lesser.html * + * * + * Anonymous FTP access to the most recent released source is available at * + * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * + * * + * Anonymous CVS access to the development source and modification history * + * is available at cvs.synchro.net:/cvsroot/sbbs, example: * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login * + * (just hit return, no password is necessary) * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src * + * * + * For Synchronet coding style and modification guidelines, see * + * http://www.synchro.net/source.html * + * * + * You are encouraged to submit any modifications (preferably in Unix diff * + * format) via e-mail to mods@synchro.net * + * * + * Note: If this box doesn't appear square, then you need to fix your tabs. * + ****************************************************************************/ + +#include /* strlen() */ +#include /* vsnprintf() */ +#include /* RAND_MAX */ +#include /* O_NOCTTY */ +#include /* clock() */ +#include /* errno */ +#include /* toupper/tolower */ + +#if defined(__unix__) + #include /* ioctl() */ + #include /* uname() */ + /* KIOCSOUND */ + #if defined(__FreeBSD__) + #include + #elif defined(__linux__) + #include + #elif defined(__solaris__) + #include + #include + #endif + #if defined(__OpenBSD__) || defined(__NetBSD__) + #include + #elif defined(__FreeBSD__) + #include + #endif +#endif /* __unix__ */ + +#include "genwrap.h" /* Verify prototypes */ + +/****************************************************************************/ +/* Used to replace snprintf() guarantees to terminate. */ +/****************************************************************************/ +int DLLCALL safe_snprintf(char *dst, size_t size, const char *fmt, ...) +{ + va_list argptr; + int numchars; + + va_start(argptr,fmt); + numchars= vsnprintf(dst,size,fmt,argptr); + va_end(argptr); + dst[size-1]=0; + return(numchars); +} + +/****************************************************************************/ +/* Return last character of string */ +/****************************************************************************/ +char* DLLCALL lastchar(const char* str) +{ + size_t len; + + len = strlen(str); + + if(len) + return((char*)&str[len-1]); + + return((char*)str); +} + +/****************************************************************************/ +/* Return character value of C-escaped (\) character */ +/****************************************************************************/ +char DLLCALL unescape_char(char ch) +{ + switch(ch) { + case '\\': return('\\'); + case '\'': return('\''); + case '"': return('"'); + case '?': return('?'); + case 'a': return('\a'); + case 'b': return('\b'); + case 'f': return('\f'); + case 'n': return('\n'); + case 'r': return('\r'); + case 't': return('\t'); + case 'v': return('\v'); + } + return(ch); +} + +/****************************************************************************/ +/* Return character value of C-escaped (\) character sequence */ +/* (supports \Xhh and \0ooo escape sequences) */ +/* This code currently has problems with sequences like: "\x01blue" */ +/****************************************************************************/ +char DLLCALL unescape_char_ptr(const char* str, char** endptr) +{ + char ch; + + if(toupper(*str)=='X') + ch=(char)strtol(++str,endptr,16); + else if(isdigit(*str)) + ch=(char)strtol(++str,endptr,8); + else { + ch=unescape_char(*(str++)); + if(endptr!=NULL) + *endptr=(char*)str; + } + + return(ch); +} + +/****************************************************************************/ +/* Unescape a C string, in place */ +/****************************************************************************/ +char* DLLCALL unescape_cstr(char* str) +{ + char ch; + char* buf; + char* src; + char* dst; + + if(str==NULL || (buf=strdup(str))==NULL) + return(NULL); + + src=buf; + dst=str; + while((ch=*(src++))!=0) { + if(ch=='\\') /* escape */ + ch=unescape_char_ptr(src,&src); + *(dst++)=ch; + } + *dst=0; + free(buf); + return(str); +} + +/****************************************************************************/ +/* Convert ASCIIZ string to upper case */ +/****************************************************************************/ +#if defined(__unix__) +char* DLLCALL strupr(char* str) +{ + char* p=str; + + while(*p) { + *p=toupper(*p); + p++; + } + return(str); +} +/****************************************************************************/ +/* Convert ASCIIZ string to lower case */ +/****************************************************************************/ +char* DLLCALL strlwr(char* str) +{ + char* p=str; + + while(*p) { + *p=tolower(*p); + p++; + } + return(str); +} +/****************************************************************************/ +/* Reverse characters of a string (provided by amcleod) */ +/****************************************************************************/ +char* strrev(char* str) +{ + char t, *i=str, *j=str+strlen(str); + + while (i /* sprintf */ +#include "gen_defs.h" /* ulong */ +#include "wrapdll.h" /* DLLEXPORT and DLLCALL */ + +#if defined(__unix__) + #include /* sched_yield */ + #include /* clock_t */ + #include /* struct timeval */ + #include /* strcasecmp() */ + #include /* usleep */ + #ifdef _THREAD_SAFE + #include /* Check for GNU PTH libs */ + #ifdef _PTH_PTHREAD_H_ + #include + #endif + #endif +#elif defined(_WIN32) + #include /* getpid() */ +#endif + +/* utime() support */ +#if defined(_MSC_VER) || defined(__WATCOMC__) + #include +#else + #include +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +/*********************/ +/* Compiler-specific */ +/*********************/ + +/* Compiler Description */ +#if defined(__BORLANDC__) + + #define DESCRIBE_COMPILER(str) sprintf(str,"BCC %X.%02X" \ + ,__BORLANDC__>>8,__BORLANDC__&0xff); + +#elif defined(_MSC_VER) + + #define DESCRIBE_COMPILER(str) sprintf(str,"MSC %u", _MSC_VER); + +#elif defined(__GNUC__) + + #define DESCRIBE_COMPILER(str) sprintf(str,"GCC %u.%02u" \ + ,__GNUC__,__GNUC_MINOR__); + +#elif defined(__WATCOMC__) + + #define DESCRIBE_COMPILER(str) sprintf(str,"WATC %d" \ + ,__WATCOMC__); + +#elif defined(__DMC__) /* Digital Mars C/C++ */ + + #define DESCRIBE_COMPILER(str) sprintf(str,"DMC %X.%02X" \ + ,__DMC__>>8,__DMC__&0xff); + +#else /* Unknown compiler */ + + #define DESCRIBE_COMPILER(str) strcpy(str,"UNKNOWN COMPILER"); + +#endif + +/**********/ +/* Macros */ +/**********/ + +/* Target Platform Description */ +#if defined(_WIN64) + #define PLATFORM_DESC "Win64" +#elif defined(_WIN32) + #define PLATFORM_DESC "Win32" +#elif defined(__OS2__) + #define PLATFORM_DESC "OS/2" +#elif defined(__MSDOS__) + #define PLATFORM_DESC "DOS" +#elif defined(__linux__) + #define PLATFORM_DESC "Linux" +#elif defined(__FreeBSD__) + #define PLATFORM_DESC "FreeBSD" +#elif defined(__OpenBSD__) + #define PLATFORM_DESC "OpenBSD" +#elif defined(__NetBSD__) + #define PLATFORM_DESC "NetBSD" +#elif defined(__APPLE__) && defined(__MACH__) && defined(__POWERPC__) + #define PLATFORM_DESC "MacOSX" +#elif defined(BSD) + #define PLATFORM_DESC "BSD" +#elif defined(__solaris__) + #define PLATFORM_DESC "Solaris" +#elif defined(__sun__) + #define PLATFORM_DESC "SunOS" +#elif defined(__gnu__) + #define PLATFORM_DESC "GNU/Hurd" +#elif defined(__QNX__) + #define PLATFORM_DESC "QNX" +#elif defined(__unix__) + #define PLATFORM_DESC "Unix" +#else + #error "Need to describe target platform" +#endif + +/*********************/ +/* String Functionss */ +/*********************/ + +#define snprintf safe_snprintf + +#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__DMC__) + #define vsnprintf _vsnprintf +#endif + +#if defined(__WATCOMC__) + #define vsnprintf(s,l,f,a) vsprintf(s,f,a) +#endif + +#if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__WATCOMC__) + DLLEXPORT char* DLLCALL ultoa(ulong, char*, int radix); +#endif + +#if defined(__unix__) + DLLEXPORT char* DLLCALL strupr(char* str); + DLLEXPORT char* DLLCALL strlwr(char* str); + DLLEXPORT char* DLLCALL strrev(char* str); + #if !defined(stricmp) + #define stricmp(x,y) strcasecmp(x,y) + #define strnicmp(x,y,z) strncasecmp(x,y,z) + #endif +#endif + +#if defined(__unix__) + #define STRERROR(x) strerror(x) +#else + #define STRERROR(x) truncsp(strerror(x)) +#endif + +/**********************************/ +/* Common Utility Macro Functions */ +/**********************************/ + +#if defined(_WIN32) + + #define YIELD() Sleep(1) /* Must sleep at least 1ms to avoid 100% CPU utilization */ + #define MAYBE_YIELD() Sleep(0) + #define SLEEP(x) Sleep(x) + #define BEEP(freq,dur) Beep((DWORD)(freq),(DWORD)(dur)) + #define popen _popen + #define pclose _pclose + #define tzname _tzname + +#elif defined(__OS2__) + + #define YIELD() DosSleep(1) /* Must sleep at least 1ms to avoid 100% CPU utilization */ + #define MAYBE_YIELD() DosSleep(0) + #define SLEEP(x) DosSleep(x) + #define BEEP(freq,dur) DosBeep(freq,dur) + +#elif defined(__unix__) || defined(__APPLE__) + + #if defined(_PTH_PTHREAD_H_) + #define SLEEP(x) ({ int y=x; struct timeval tv; \ + tv.tv_sec=(y/1000); tv.tv_usec=((y%1000)*1000); \ + pth_nap(tv); }) + #else + #define SLEEP(x) ({ int y=x; struct timeval tv; \ + tv.tv_sec=(y/1000); tv.tv_usec=((y%1000)*1000); \ + select(0,NULL,NULL,NULL,&tv); }) + #endif + + #define YIELD() SLEEP(1) + + #if defined(_THREAD_SAFE) + #if defined(__FreeBSD__) + #define MAYBE_YIELD() pthread_yield() + #elif defined(_PTH_PTHREAD_H_) + #define MAYBE_YIELD() pth_yield(NULL) + #elif defined(_POSIX_PRIORITY_SCHEDULING) + #define MAYBE_YIELD() sched_yield() + #else + #define MAYBE_YIELD() YIELD() + #endif + #else + #if defined(_POSIX_PRIORITY_SCHEDULING) + #define MAYBE_YIELD() sched_yield() + #else + #define MAYBE_YIELD() YIELD() + #endif + #endif + + /* + * QNX doesn't support fork() in threaded apps (yet) using vfork() instead + * works, but relies on undefined behaviours not being nasty. On most OSs + * vfork() will share the stack between the parent and child... + */ + #if defined(__QNX__) + #define FORK() vfork() + #else + #define FORK() fork() + #endif + + #define BEEP(freq,dur) unix_beep(freq,dur) + DLLEXPORT void DLLCALL unix_beep(int freq, int dur); + +#else /* Unsupported OS */ + + #error "Unsupported Target: Need some macros and/or function prototypes here." + +#endif + +/* Win32 implementations of recursive (thread-safe) std C time functions on Unix */ + +#if !defined(__unix__) + + #include /* time_t, etc. */ + + DLLEXPORT struct tm* DLLCALL gmtime_r(const time_t* t, struct tm* tm); + DLLEXPORT struct tm* DLLCALL localtime_r(const time_t* t, struct tm* tm); + DLLEXPORT char* DLLCALL ctime_r(const time_t *t, char *buf); + DLLEXPORT char* DLLCALL asctime_r(const struct tm *tm, char *buf); +#endif + +#if defined(__solaris__) + #define CTIME_R(x,y) ctime_r(x,y) + /* #define CTIME_R(x,y) ctime_r(x,y,sizeof y) */ +#else + #define CTIME_R(x,y) ctime_r(x,y) +#endif + +DLLEXPORT int DLLCALL xp_random(int); +DLLEXPORT char* DLLCALL os_version(char *str); +DLLEXPORT char* DLLCALL lastchar(const char* str); +DLLEXPORT int DLLCALL safe_snprintf(char *dst, size_t size, const char *fmt, ...); + +/* C string/char escape-sequence processing */ +DLLEXPORT char* DLLCALL unescape_cstr(char* str); +DLLEXPORT char DLLCALL unescape_char_ptr(const char* str, char** endptr); +DLLEXPORT char DLLCALL unescape_char(char ch); + +#if !defined(__unix__) + #define msclock() clock() + #define MSCLOCKS_PER_SEC CLOCKS_PER_SEC +#else + #define MSCLOCKS_PER_SEC 1000 + clock_t msclock(void); +#endif + +#if defined(__cplusplus) +} +#endif + +#endif /* Don't add anything after this line */ diff --git a/src/wrapdll.h b/src/wrapdll.h new file mode 100644 index 0000000..b4f7c22 --- /dev/null +++ b/src/wrapdll.h @@ -0,0 +1,64 @@ +/* wrapdll.h */ + +/* Defines DLLEXPORT and DLLCALL for cross-platform development wrappers */ + +/* $Id$ */ + +/**************************************************************************** + * @format.tab-size 4 (Plain Text/Source Code File Header) * + * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * + * * + * Copyright 2002 Rob Swindell - http://www.synchro.net/copyright.html * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * See the GNU Lesser General Public License for more details: lgpl.txt or * + * http://www.fsf.org/copyleft/lesser.html * + * * + * Anonymous FTP access to the most recent released source is available at * + * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * + * * + * Anonymous CVS access to the development source and modification history * + * is available at cvs.synchro.net:/cvsroot/sbbs, example: * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login * + * (just hit return, no password is necessary) * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src * + * * + * For Synchronet coding style and modification guidelines, see * + * http://www.synchro.net/source.html * + * * + * You are encouraged to submit any modifications (preferably in Unix diff * + * format) via e-mail to mods@synchro.net * + * * + * Note: If this box doesn't appear square, then you need to fix your tabs. * + ****************************************************************************/ + +#ifndef _WRAPDLL_H +#define _WRAPDLL_H + +#if defined(DLLEXPORT) + #undef DLLEXPORT +#endif +#if defined(DLLCALL) + #undef DLLCALL +#endif + +#if defined(_WIN32) && (defined(WRAPPER_IMPORTS) || defined(WRAPPER_EXPORTS)) + #if defined(WRAPPER_IMPORTS) + #define DLLEXPORT __declspec(dllimport) + #else + #define DLLEXPORT __declspec(dllexport) + #endif + #if defined(__BORLANDC__) + #define DLLCALL __stdcall + #else + #define DLLCALL + #endif +#else /* !_WIN32 || !_DLL*/ + #define DLLEXPORT + #define DLLCALL +#endif + +#endif From 1778df783a0ddacf0d9bcddce6ab55adca089f26 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Thu, 5 Aug 2004 07:19:25 +0000 Subject: [PATCH 004/327] Add JUMP(), RETURN(), and CALL() macros. --- src/do_instruct.h | 294 ++++++++++------------------------------------ 1 file changed, 59 insertions(+), 235 deletions(-) diff --git a/src/do_instruct.h b/src/do_instruct.h index 8460859..0be41ea 100644 --- a/src/do_instruct.h +++ b/src/do_instruct.h @@ -273,20 +273,45 @@ cpu_delay(12); \ } -#define DOCALL { \ - DECSP2; \ - MEM(SP)=PCL; MEM(SP+1)=PCH; /* MEM16(SP)=PC; */ \ - DECPC2; \ - SETPCINS16; \ +#define CALL(cond,ins) { \ + INCPC; \ + if(trace) \ + sprintf(p,ins" %04x",INS16); \ + INCPC2; \ + if(cond) { \ + DECSP2; \ + MEM(SP)=PCL; MEM(SP+1)=PCH; /* MEM16(SP)=PC; */ \ + DECPC2; \ + SETPCINS16; \ + cpu_delay(9); \ + } \ cpu_delay(9); \ } -#define DORET { \ - PCL=MEM(SP); PCH=MEM(SP+1); /* PC=MEM16(SP) */ \ - INCSP2; \ +#define RETURN(cond,ins) { \ + if(trace) \ + strcat(p,ins); \ + INCPC; \ + if(cond) { \ + PCL=MEM(SP); PCH=MEM(SP+1); /* PC=MEM16(SP) */ \ + INCSP2; \ + cpu_delay(6); \ + } \ cpu_delay(6); \ } +#define JUMP(cond,ins) { \ + INCPC; \ + if(trace) \ + sprintf(p,ins" %04x",INS16); \ + if(cond) { \ + SETPCINS16; \ + cpu_delay(3); \ + } \ + else \ + INCPC2; \ + cpu_delay(7); \ + } { if(trace) @@ -1605,26 +1630,11 @@ else { if(!(INS&0x01)) { /* case 0xC2: /* JNZ addr */ - INCPC; - if(trace) - sprintf(p,"JNZ %04x",INS16); - if(!ZF) { - SETPCINS16; - cpu_delay(3); - } - else - INCPC2; - cpu_delay(7); - /* return; */ + JUMP(!ZF,"JNZ"); } else { /* case 0xC3: /* JMP addr */ - INCPC; - if(trace) - sprintf(p,"JMP %04x",INS16); - SETPCINS16; - cpu_delay(7); - /* return; */ + JUMP(1,"JMP"); } } } @@ -1632,15 +1642,7 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0xC4: /* CNZ addr */ - INCPC; - if(trace) - sprintf(p,"CNZ %04x",INS16); - INCPC2; - if(!ZF) { - DOCALL; - } - cpu_delay(9); - /* return; */ + CALL(!ZF,"CNZ"); } else { /* case 0xC5: /* PUSH B */ @@ -1678,38 +1680,17 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0xC8: /* RZ */ - if(trace) - strcat(p,"RZ"); - INCPC; - if(ZF) { - DORET; - } - cpu_delay(6); - /* return; */ + RETURN(ZF,"RZ"); } else { /* case 0xC9: /* RET */ - if(trace) - strcat(p,"RET"); - DORET; - cpu_delay(4); - /* return; */ + RETURN(1,"RET"); } } else { if(!(INS&0x01)) { /* case 0xCA: /* JZ addr */ - INCPC; - if(trace) - sprintf(p,"JZ %04x",INS16); - if(ZF) { - SETPCINS16; - cpu_delay(3); - } - else - INCPC2; - cpu_delay(7); - /* return; */ + JUMP(ZF,"JZ"); } else { /* case 0xCB: /* INVALID? */ @@ -1722,25 +1703,11 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0xCC: /* CZ addr */ - INCPC; - if(trace) - sprintf(p,"CZ %04x",INS16); - INCPC2; - if(ZF) { - DOCALL; - } - cpu_delay(9); - /* return; */ + CALL(ZF,"CZ"); } else { /* case 0xCD: /* CALL addr */ - INCPC; - if(trace) - sprintf(p,"CALL %04x",INS16); - INCPC2; - DOCALL; - cpu_delay(9); - /* return; */ + CALL(1,"CALL"); } } else { @@ -1777,14 +1744,7 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0xD0: /* RNC */ - INCPC; - if(trace) - strcat(p,"RNC"); - if(!CF) { - DORET; - } - cpu_delay(6); - /* return; */ + RETURN(!CF,"RNC"); } else { /* case 0xD1: /* POP D */ @@ -1794,17 +1754,7 @@ else { if(!(INS&0x01)) { /* case 0xD2: /* JNC addr */ - INCPC; - if(trace) - sprintf(p,"JNC %04x",INS16); - if(!CF) { - SETPCINS16; - cpu_delay(3); - } - else - INCPC2; - cpu_delay(7); - /* return; */ + JUMP(!CF,"JNC"); } else { /* case 0xD3: /* OUT port */ @@ -1822,15 +1772,7 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0xD4: /* CNC addr */ - INCPC; - if(trace) - sprintf(p,"CNC %04x",INS); - INCPC2; - if(!CF) { - DOCALL; - } - cpu_delay(9); - /* return; */ + CALL(!CF,"CNC"); } else { /* case 0xD5: /* PUSH D */ @@ -1868,14 +1810,7 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0xD8: /* RC */ - if(trace) - strcat(p,"RC"); - INCPC; - if(CF) { - DORET; - } - cpu_delay(6); - /* return; */ + RETURN(CF,"RC"); } else { /* case 0xD9: /* INVALID? */ @@ -1886,16 +1821,7 @@ else { if(!(INS&0x01)) { /* case 0xDA: /* JC addr */ - INCPC; - if(trace) - sprintf(p,"JC %04x",INS16); - if(CF) { - SETPCINS16; - cpu_delay(3); - } - else - INCPC2; - cpu_delay(7); + JUMP(CF,"JC"); } else { /* case 0xDB: /* IN port */ @@ -1912,15 +1838,7 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0xDC: /* CC addr */ - INCPC; - if(trace) - sprintf(p,"CC %04x",INS16); - INCPC2; - if(CF) { - DOCALL; - } - cpu_delay(9); - /* return; */ + CALL(CF,"CC"); } else { /* case 0xDD: /* INVALID? */ @@ -1964,11 +1882,7 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0xE0: /* RPO */ - INCPC; - if(!PF) { - DORET; - } - cpu_delay(6); + RETURN(!PF,"RPO"); } else { /* case 0xE1: /* POP H */ @@ -1978,16 +1892,7 @@ else { if(!(INS&0x01)) { /* case 0xE2: /* JPO addr */ - INCPC; - if(trace) - sprintf(p,"JPO %04x",INS16); - if(!PF) { - SETPCINS16; - cpu_delay(3); - } - else - INCPC2; - cpu_delay(7); + JUMP(!PF,"JPO"); } else { /* case 0xE3: /* XTHL */ @@ -2011,13 +1916,7 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0xE4: /* CPO addr */ - INCPC; - INCPC2; - if(!PF) { - DOCALL; - } - cpu_delay(9); - /* return; */ + CALL(!PF,"CPO"); } else { /* case 0xE5: /* PUSH H */ @@ -2048,14 +1947,7 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0xE8: /* RPE */ - INCPC; - if(trace) - strcat(p,"RPE"); - if(PF) { - DORET; - } - cpu_delay(6); - /* return; */ + RETURN(PF,"RPE"); } else { /* case 0xE9: /* PCHL */ @@ -2069,17 +1961,7 @@ else { if(!(INS&0x01)) { /* case 0xEA: /* JPE addr */ - INCPC; - if(trace) - sprintf(p,"JPE %04x",INS16); - if(PF) { - SETPCINS16; - cpu_delay(3); - } - else - INCPC2; - cpu_delay(7); - /* return; */ + JUMP(PF,"JPE"); } else { /* case 0xEB: /* XCHG */ @@ -2104,15 +1986,7 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0xEC: /* CPE addr */ - INCPC; - if(trace) - sprintf(p,"CPE %04x",INS16); - INCPC2; - if(PF) { - DOCALL; - } - cpu_delay(9); - /* return; */ + CALL(PF,"CPE"); } else { /* case 0xED: /* INVALID? */ @@ -2146,14 +2020,7 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0xF0: /* RP */ - INCPC; - if(trace) - strcat(p,"RP"); - if(!SF) { - DORET; - } - cpu_delay(6); - /* return; */ + RETURN(!SF,"RP"); } else { /* case 0xF1: /* POP PSW */ @@ -2163,17 +2030,7 @@ else { if(!(INS&0x01)) { /* case 0xF2: /* JP addr */ - INCPC; - if(trace) - sprintf(p,"JP %04x",INS16); - if(!SF) { - SETPCINS16; - cpu_delay(3); - } - else - INCPC2; - cpu_delay(7); - /* return; */ + JUMP(!SF,"JP"); } else { /* case 0xF3: /* DI */ @@ -2190,15 +2047,7 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0xF4: /* CP addr */ - INCPC; - if(trace) - sprintf(p,"CP %04x",INS16); - INCPC2; - if(!SF) { - DOCALL; - } - cpu_delay(9); - /* return; */ + CALL(!SF,"CP"); } else { /* case 0xF5: /* PUSH PSW */ @@ -2229,14 +2078,7 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0xF8: /* RM */ - INCPC; - if(trace) - strcat(p,"RM"); - if(SF) { - DORET; - } - cpu_delay(6); - /* return; */ + RETURN(SF,"RM"); } else { /* case 0xF9: /* SPHL */ @@ -2252,17 +2094,7 @@ else { if(!(INS&0x01)) { /* case 0xFA: /* JM addr */ - INCPC; - if(trace) - sprintf(p,"JM %04x",INS16); - if(SF) { - SETPCINS16; - cpu_delay(3); - } - else - INCPC2; - cpu_delay(7); - /* return; */ + JUMP(SF,"JM"); } else { /* case 0xFB: /* EI */ @@ -2279,15 +2111,7 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0xFC: /* CM addr */ - INCPC; - if(trace) - sprintf(p,"CM %04x",INS16); - INCPC2; - if(SF) { - DOCALL; - } - cpu_delay(9); - /* return; */ + CALL(SF,"CM"); } else { /* case 0xFD: /* INVALID? */ From d95a01534dc02d92d2ab92e5c5f8e7e14eac4d5a Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Fri, 6 Aug 2004 03:31:31 +0000 Subject: [PATCH 005/327] Use FLTKCONFIG variable if defined in the environment or on command-line --- GNUmakefile | 5 +++-- Makefile | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 5f4d192..657a9a2 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -2,8 +2,9 @@ CFLAGS += -O6 #CFLAGS += -g -CFLAGS += `fltk-config --cflags --use-images` -LDFLAGS += `fltk-config --ldstaticflags --use-images` +FLTKCONFIG ?= fltk-config +CFLAGS += `$(FLTKCONFIG) --cflags --use-images` +LDFLAGS += `$(FLTKCONFIG) --ldstaticflags --use-images` m100emu: doins.o io.o genwrap.o display.o m100emu.o disassemble.o GNUmakefile gcc -o m100emu doins.o genwrap.o io.o display.o m100emu.o disassemble.o $(LDFLAGS) diff --git a/Makefile b/Makefile index 71ed073..430b149 100644 --- a/Makefile +++ b/Makefile @@ -4,8 +4,9 @@ #CFLAGS := -O2 -g CFLAGS += -O6 -CFLAGS += `fltk-config --cflags --use-images` -LDFLAGS += `fltk-config --ldstaticflags --use-images` +FLTKCONFIG ?= fltk-config +CFLAGS += `$(FLTKCONFIG) --cflags --use-images` +LDFLAGS += `$(FLTKCONFIG) --ldstaticflags --use-images` m100emu: doins.o io.o genwrap.o display.o m100emu.o disassemble.o Makefile gcc -o m100emu doins.o genwrap.o io.o display.o m100emu.o disassemble.o $(LDFLAGS) From 552100d56aa16b7989f654fe414ca8e31523d51b Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 31 Aug 2004 15:04:49 +0000 Subject: [PATCH 006/327] Added support for X flag (undocumented opcode support) --- src/cpu.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cpu.h b/src/cpu.h index 7816718..f58cd78 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -82,6 +82,8 @@ extern uchar optROM[ROMSIZE]; #define NXTINS memory[PC+1] #define INS16 (((int)memory[PC])|(((int)memory[PC+1])<<8)) #define CF (F&0x01) +#define XF ((F&0x02)>>1) +#define XF_BIT 0x02 #define PF ((F&0x04)>>2) #define AC ((F&0x10)>>4) #define ZF ((F&0x40)>>6) From 21fcb1d6c5aa37670b9d64faec1e318c288156b7 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 31 Aug 2004 15:07:17 +0000 Subject: [PATCH 007/327] Added undocumented opcodes. Made disassembler window resizable. --- src/disassemble.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/disassemble.cpp b/src/disassemble.cpp index f7a31e3..1e3a9d7 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -41,7 +41,6 @@ #include "m100emu.h" #include "disassemble.h" -#include "m100rom.h" #include "io.h" Fl_Window *gpDis; @@ -60,13 +59,13 @@ void close_cb(Fl_Widget* w, void*) // Table of OPCODE char * VTDis::m_StrTable[256] = { "NOP", "LXI B,", "STAX B", "INX B", "INR B", "DCR B", "MVI B,", "RLC", - "-", "DAD B", "LDAX B", "DCX B", "INR C", "DCR C", "MVI C,", "RRC", - "-", "LXI D,", "STAX D", "INX D", "INR D", "DCR D", "MVI D,", "RAL", - "-", "DAD D", "LDAX D", "DCX D", "INR E", "DCR E", "MVI E,", "RAR", + "DSUB", "DAD B", "LDAX B", "DCX B", "INR C", "DCR C", "MVI C,", "RRC", + "ASHR", "LXI D,", "STAX D", "INX D", "INR D", "DCR D", "MVI D,", "RAL", + "RLDE", "DAD D", "LDAX D", "DCX D", "INR E", "DCR E", "MVI E,", "RAR", "RIM", "LXI H,", "SHLD ", "INX H", "INR H", "DCR H", "MVI H,", "DAA", - "-", "DAD H", "LHLD ", "DCX H", "INR L", "DCR L", "MVI L,", "CMA", + "LDEH ", "DAD H", "LHLD ", "DCX H", "INR L", "DCR L", "MVI L,", "CMA", "SIM", "LXI SP,", "STA ", "INX SP", "INR M", "DCR M", "MVI M,", "STC", - "-", "DAD SP", "LDA ", "DCX SP", "INR A", "DCR A", "MVI A,", "CMC", + "LDES ", "DAD SP", "LDA ", "DCX SP", "INR A", "DCR A", "MVI A,", "CMC", "MOV B,B", "MOV B,C", "MOV B,D", "MOV B,E", "MOV B,H", "MOV B,L", "MOV B,M", "MOV B,A", "MOV C,B", "MOV C,C", "MOV C,D", "MOV C,E", "MOV C,H", "MOV C,L", "MOV C,M", "MOV C,A", "MOV D,B", "MOV D,C", "MOV D,D", "MOV D,E", "MOV D,H", "MOV D,L", "MOV D,M", "MOV D,A", @@ -86,11 +85,11 @@ char * VTDis::m_StrTable[256] = { "RNZ", "POP B", "JNZ ", "JMP ", "CNZ ", "PUSH B", "ADI ", "RST 0", "RZ", "RET", "JZ ", "-", "CZ ", "CALL ", "ACI ", "RST 1", "RNC", "POP D", "JNC ", "OUT ", "CNC ", "PUSH D", "SUI ", "RST 2", - "RC", "-", "JC ", "IN ", "CC ", "-", "SBI ", "RST 3", + "RC", "SHLX", "JC ", "IN ", "CC ", "JNX ", "SBI ", "RST 3", "RPO", "POP H", "JPO ", "XTHL", "CPO ", "PUSH H", "ANI ", "RST 4", - "RPE", "PCHL", "JPE ", "XCHG", "CPE ", "-", "XRI ", "RST 5", + "RPE", "PCHL", "JPE ", "XCHG", "CPE ", "LHLX", "XRI ", "RST 5", "RP", "POP PSW", "JP ", "DI", "CP ", "PUSH PSW", "ORI ", "RST 6", - "RM", "SPHL", "JM ", "EI", "CM ", "-", "CPI ", "RST 7" + "RM", "SPHL", "JM ", "EI", "CM ", "JX ", "CPI ", "RST 7" }; // Table indicating length of each opcode @@ -100,9 +99,9 @@ unsigned char VTDis::m_LenTable[256] = { 0,2,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,2,2,0,0,0,1,0, - 0,0,2,0,0,0,1,0, + 1,0,2,0,0,0,1,0, 0,2,2,0,0,0,1,0, - 0,0,2,0,0,0,1,0, + 1,0,2,0,0,0,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, @@ -122,11 +121,11 @@ unsigned char VTDis::m_LenTable[256] = { 0,0,2,2,2,0,1,0, 0,0,2,0,2,2,1,0, 0,0,2,1,2,0,1,0, - 0,0,2,1,2,0,1,0, + 0,0,2,1,2,2,1,0, 0,0,2,0,2,0,1,0, 0,0,2,0,2,0,1,0, 0,0,2,0,2,0,1,0, - 0,0,2,0,2,0,1,0 + 0,0,2,0,2,2,1,0 }; @@ -188,14 +187,17 @@ void disassembler_cb(Fl_Widget* w, void*) { VTDis *pDisassembler = new VTDis(); // Assign the RomDescription table for the model being emulated - if (gModel == MODEL_M100) - pDisassembler->m_pRom = &gM100_Desc; + pDisassembler->m_pRom = gStdRomDesc; // Give the disassembler the text editor to dump it's data into pDisassembler->SetTextViewer(td); // Give the disassembler something to disassemble pDisassembler->CopyIntoMem(memory, 32788); + + gpDis->resizable(m); + gpDis->resizable(td); + gpDis->end(); gpDis->show(); From a8aa6dd9f20e6a874ef2d51d41fdd2d539769276 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 31 Aug 2004 15:07:48 +0000 Subject: [PATCH 008/327] Removed ROM typedefs -- this is now located in rom.h --- src/disassemble.h | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/src/disassemble.h b/src/disassemble.h index 427c08d..ecfc79c 100644 --- a/src/disassemble.h +++ b/src/disassemble.h @@ -33,23 +33,6 @@ #include "display.h" -typedef struct Std_ROM_Addresses { - int addr; - char* desc; -} Std_ROM_Addresses_t; - -typedef struct Std_ROM_Table { - int addr; - int size; - char type; -} Std_ROM_Table_t; - -typedef struct RomDescription { - Std_ROM_Table_t *pTables; - Std_ROM_Addresses_t *pVars; - Std_ROM_Addresses_t *pFuns; -} RomDescription_t; - class VTDis { @@ -72,17 +55,5 @@ class VTDis }; -enum { - TABLE_TYPE_STRING - ,TABLE_TYPE_JUMP - ,TABLE_TYPE_CODE - ,TABLE_TYPE_MODIFIED_STRING - ,TABLE_TYPE_2BYTE - ,TABLE_TYPE_3BYTE - ,TABLE_TYPE_CTRL_DELIM - ,TABLE_TYPE_BYTE_LOOKUP - ,TABLE_TYPE_4BYTE_CMD - ,TABLE_TYPE_CATALOG -}; -#endif \ No newline at end of file +#endif From 7b9dde68b4d1e8af4689fd2df3deb1bfb863771e Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 31 Aug 2004 15:08:56 +0000 Subject: [PATCH 009/327] Added support for host file load/save operations. Addes support for saving & restoring preferences. --- src/display.cpp | 246 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 176 insertions(+), 70 deletions(-) diff --git a/src/display.cpp b/src/display.cpp index ae0be33..74c9cad 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -37,6 +37,9 @@ #include #include #include +//Added by J. VERNET for pref files +// see also cb_xxxxxx +#include @@ -47,11 +50,14 @@ #include "display.h" #include "m100emu.h" #include "io.h" +#include "file.h" Fl_Window *MainWin; T100_Disp *gpDisp; Fl_Box *gpCode, *gpGraph, *gpKey, *gpSpeed, *gpCaps, *gpKeyInfo; Fl_Menu_Bar *Menu; +Fl_Preferences virtualt_prefs(Fl_Preferences::USER, "virtualt.", "virtualt" ); +char gsMenuROM[40]; int MultFact = 3; int DisplayMode = 1; @@ -110,10 +116,13 @@ void disassembler_cb(Fl_Widget* w, void*); void rspeed(Fl_Widget* w, void*) { fullspeed=0; + virtualt_prefs.set("fullspeed",0); } void fspeed(Fl_Widget* w, void*) { fullspeed=1; + virtualt_prefs.set("fullspeed",1); + } void close_disp_cb(Fl_Widget* w, void*) { @@ -155,33 +164,49 @@ Menu Item Callbacks void cb_1x(Fl_Widget* w, void*) { MultFact = 1; + virtualt_prefs.set("MultFact",1); resize_window(); } void cb_2x(Fl_Widget* w, void*) { MultFact = 2; + virtualt_prefs.set("MultFact",2); resize_window(); } void cb_3x(Fl_Widget* w, void*) { MultFact = 3; + virtualt_prefs.set("MultFact",3); resize_window(); } void cb_4x(Fl_Widget* w, void*) { MultFact = 4; + virtualt_prefs.set("MultFact",4); resize_window(); } void cb_framed(Fl_Widget* w, void*) { DisplayMode ^= 1; + virtualt_prefs.set("DisplayMode",DisplayMode); resize_window(); } void cb_solidchars (Fl_Widget* w, void*) { SolidChars ^= 1; + virtualt_prefs.set("SolidChars",SolidChars); resize_window(); } +void cb_save_basic(Fl_Widget* w, void*) +{ + BasicSaveMode ^= 1; + virtualt_prefs.set("BasicSaveMode",BasicSaveMode); +} +void cb_save_co(Fl_Widget* w, void*) +{ + COSaveMode ^= 1; + virtualt_prefs.set("COSaveMode",COSaveMode); +} void cb_reset (Fl_Widget* w, void*) { @@ -191,14 +216,34 @@ void cb_reset (Fl_Widget* w, void*) resetcpu(); } +void cb_UnloadOptRom (Fl_Widget* w, void*) +{ + gsOptRomFile[0] = 0; + + // Update user preferences + virtualt_prefs.set("OptRomFile",gsOptRomFile); + + // Clear menu + strcpy(gsMenuROM, "No ROM loaded"); + + // Clear optROM memory + load_opt_rom(); + + // Reset the CPU + resetcpu(); + +} + + void cb_help (Fl_Widget* w, void*) { -// Fl_Help_Dialog *HelpWin; +#ifndef WIN32 + Fl_Help_Dialog *HelpWin; -// HelpWin = new Fl_Help_Dialog(); -// HelpWin->load("./help.htm"); -// HelpWin->show(); - + HelpWin = new Fl_Help_Dialog(); + HelpWin->load("./help.htm"); + HelpWin->show(); +#endif } void cb_about (Fl_Widget* w, void*) @@ -250,39 +295,6 @@ void cb_about (Fl_Widget* w, void*) o->show(); } -void cb_LoadRam (Fl_Widget* w, void*) -{ - Fl_File_Chooser *FileWin; - - FileWin = new Fl_File_Chooser(".","*.bin",1,"Load RAM file"); - FileWin->preview(0); - FileWin->show(); - -} - -void cb_SaveRam (Fl_Widget* w, void*) -{ - Fl_File_Chooser *FileWin; - - FileWin = new Fl_File_Chooser(".","*.bin",1,"Save RAM file"); - FileWin->preview(0); - // FileWin.value(0)="RAM.bin" - FileWin->show(); - -} - - - -void cb_LoadOptRom (Fl_Widget* w, void*) -{ - Fl_File_Chooser *FileWin; - - FileWin = new Fl_File_Chooser(".","*.bin",1,"Load Optional ROM file"); - FileWin->preview(0); - FileWin->show(); -} - - T100_Disp::T100_Disp(int x, int y, int w, int h) : Fl_Widget(x, y, w, h) { @@ -300,9 +312,7 @@ T100_Disp::T100_Disp(int x, int y, int w, int h) : // Draw the black pixels on the LCD void drawpixel(int x, int y, int color) { - // fl_color(color); if (color) - fl_rectf(x*MultFact + gXoffset,y*MultFact + gYoffset,gRectsize,gRectsize); } @@ -452,10 +462,6 @@ void T100_Disp::SetByte(int driver, int col, uchar value) if ((col&0x3f) > 49) return; - // Check if drawing to unused portion of right-most drivers -// if (((driver == 4) || (driver == 9)) && ((col&0x3F) % 50 >= 40)) -// return; - // Calculate X position of byte x=(driver % 5) * 50 + (col&0x3F); @@ -469,7 +475,7 @@ void T100_Disp::SetByte(int driver, int col, uchar value) fl_color(FL_GRAY); fl_rectf(x*MultFact + gXoffset,y*MultFact + -gYoffset,gRectsize,8*MultFact); + gYoffset,gRectsize,MultFact<<3); fl_color(FL_BLACK); // Draw each pixel of byte @@ -490,16 +496,20 @@ gYoffset,gRectsize,8*MultFact); Fl_Menu_Item menuitems[] = { { "&File", 0, 0, 0, FL_SUBMENU }, - { "Load file from HD", 0, 0, 0 }, - { "Save file to HD", 0, 0, 0, FL_MENU_DIVIDER }, + { "Load file from HD", 0, cb_LoadFromHost, 0 }, + { "Save file to HD", 0, cb_SaveToHost, 0, 0 }, + { "Save Options", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER }, + { "Save Basic as ASCII", 0, cb_save_basic, (void *) 1, FL_MENU_TOGGLE }, + { "Save CO as HEX", 0, cb_save_co, (void *) 2, FL_MENU_TOGGLE }, + { 0 }, { "Load RAM...", 0, cb_LoadRam, 0 }, { "Save RAM...", 0, cb_SaveRam, 0, FL_MENU_DIVIDER }, { "E&xit", FL_CTRL + 'q', close_disp_cb, 0 }, { 0 }, - { "&Emulation", 0, 0, 0, FL_SUBMENU }, - { "Reset",0, cb_reset, 0,FL_MENU_DIVIDER }, - { "Model", 0, 0, 0, FL_SUBMENU } , + { "&Emulation", 0, 0, 0, FL_SUBMENU }, + { "Reset", 0, cb_reset, 0, FL_MENU_DIVIDER }, + { "Model", 0, 0, 0, FL_SUBMENU } , { "M100", 0, 0, (void *) 1, FL_MENU_RADIO | FL_MENU_VALUE }, { "M102", 0, 0, (void *) 2, FL_MENU_RADIO }, { "T200", 0, 0, (void *) 3, FL_MENU_RADIO }, @@ -517,14 +527,17 @@ Fl_Menu_Item menuitems[] = { { "Solid Chars", 0, cb_solidchars, (void *) 1, FL_MENU_TOGGLE}, { 0 }, { "Peripheral Setup...", 0, 0, 0, FL_MENU_DIVIDER }, - { "Load Optional ROM...", 0, cb_LoadOptRom }, + { "Option ROM", 0, 0, 0, FL_SUBMENU }, + { gsMenuROM, 0, 0, 0, FL_MENU_DIVIDER }, + { "Load ROM...", 0, cb_LoadOptRom, 0, 0 }, + { "Unload ROM", 0, cb_UnloadOptRom, 0, 0 }, + { 0 }, { 0 }, { "&Tools", 0, 0, 0, FL_SUBMENU }, { "CPU Registers", 0, 0 }, { "Assembler", 0, 0 }, { "Disassembler", 0, disassembler_cb }, -// { "Disassembler", 0, 0 }, { "Debugger", 0, 0 }, { "Memory Editor", 0, 0 }, { "Peripheral Devices", 0, 0 }, @@ -540,42 +553,139 @@ Fl_Menu_Item menuitems[] = { { 0 } }; +// read Pref File +// J. VERNET + +void initpref(void) +{ + virtualt_prefs.get("fullspeed",fullspeed,0); + virtualt_prefs.get("MultFact",MultFact,3); + virtualt_prefs.get("DisplayMode",DisplayMode,1); + virtualt_prefs.get("SolidChars",SolidChars,0); + virtualt_prefs.get("BasicSaveMode",BasicSaveMode,0); + virtualt_prefs.get("COSaveMode",COSaveMode,0); + virtualt_prefs.get("OptRomFile",gsOptRomFile,"", 256); + + if (strlen(gsOptRomFile) == 0) + { + strcpy(gsMenuROM, "No ROM loaded"); + } + else + { + strcpy(gsMenuROM, fl_filename_name(gsOptRomFile)); + } +} // Create the main display window and all children (status, etc.) void initdisplay(void) { + int mIndex; + MainWin = new Fl_Window(240*MultFact + 90*DisplayMode+2,64*MultFact + -50*DisplayMode + MENU_HEIGHT + 22, "Virtual T"); + 50*DisplayMode + MENU_HEIGHT + 22, "Virtual T"); Menu = new Fl_Menu_Bar(0, 0, 240*MultFact + 90*DisplayMode+2, -MENU_HEIGHT-2); + MENU_HEIGHT-2); gpDisp = new T100_Disp(0, MENU_HEIGHT, 240*MultFact + 90*DisplayMode+2, -64*MultFact + 50*DisplayMode+2); + 64*MultFact + 50*DisplayMode+2); MainWin->callback(close_disp_cb); Menu->menu(menuitems); + + +// Treat Values read in pref files +// J. VERNET +// Be careful, if order or add to Emulation Menu, this code need to be changed. + // Update Speed menu item if not default value + if(fullspeed==1) + { + mIndex = 0; + while (menuitems[mIndex].callback_ != rspeed) + mIndex++; + menuitems[mIndex+1].flags= FL_MENU_RADIO |FL_MENU_VALUE; + menuitems[mIndex].flags= FL_MENU_RADIO; + } + + // Update Display Size from preference + mIndex = 0; + // Find first display size menu item + while (menuitems[mIndex].callback_ != cb_1x) + mIndex++; + mIndex--; + + for(int i=1;i<5;i++) + { + if(i==MultFact) + if(i==4) + menuitems[i+mIndex].flags=FL_MENU_RADIO | FL_MENU_VALUE | FL_MENU_DIVIDER; + else menuitems[i+mIndex].flags=FL_MENU_RADIO | FL_MENU_VALUE; + else + if(i==4) + menuitems[i+mIndex].flags=FL_MENU_RADIO | FL_MENU_DIVIDER; + else menuitems[i+mIndex].flags=FL_MENU_RADIO; + } + + // Update DisplayMode parameter + if(DisplayMode==0) + { + mIndex = 0; + while (menuitems[mIndex].callback_ != cb_framed) + mIndex++; + menuitems[mIndex].flags=FL_MENU_TOGGLE; + } + + // Update SolidChars menu item + if(SolidChars==1) + { + mIndex = 0; + while (menuitems[mIndex].callback_ != cb_solidchars) + mIndex++; + menuitems[mIndex].flags=FL_MENU_TOGGLE|FL_MENU_VALUE; + } + + // Update BasicSaveMode parameter + if(BasicSaveMode==1) + { + mIndex = 0; + while (menuitems[mIndex].callback_ != cb_save_basic) + mIndex++; + menuitems[mIndex].flags=FL_MENU_TOGGLE|FL_MENU_VALUE; + } + + // Update COSaveMode parameter + if(COSaveMode==1) + { + mIndex = 0; + while (menuitems[mIndex].callback_ != cb_save_co) + mIndex++; + menuitems[mIndex].flags=FL_MENU_TOGGLE|FL_MENU_VALUE; + } + gpGraph = new Fl_Box(FL_DOWN_BOX,0, MENU_HEIGHT+64*MultFact + -50*DisplayMode+2, 60, 20,"GRAPH"); + 50*DisplayMode+2, 60, 20,"GRAPH"); gpGraph->labelsize(10); gpGraph->deactivate(); gpCode = new Fl_Box(FL_DOWN_BOX,60, MENU_HEIGHT+64*MultFact + -50*DisplayMode+2, 60, 20,"CODE"); + 50*DisplayMode+2, 60, 20,"CODE"); gpCode->labelsize(10); gpCode->deactivate(); gpCaps = new Fl_Box(FL_DOWN_BOX,120, MENU_HEIGHT+64*MultFact + -50*DisplayMode+2, 60, 20,"CAPS"); + 50*DisplayMode+2, 60, 20,"CAPS"); gpCaps->labelsize(10); gpCaps->deactivate(); gpKey = new Fl_Box(FL_DOWN_BOX,180, MENU_HEIGHT+64*MultFact + -50*DisplayMode+2, 120, 20,""); + 50*DisplayMode+2, 120, 20,""); gpKey->labelsize(10); gpSpeed = new Fl_Box(FL_DOWN_BOX,300, MENU_HEIGHT+64*MultFact + -50*DisplayMode+2, 60, 20,""); + 50*DisplayMode+2, 60, 20,""); gpSpeed->labelsize(10); gpKeyInfo = new Fl_Box(FL_DOWN_BOX,360, MENU_HEIGHT+64*MultFact + -50*DisplayMode+2, MainWin->w()-360, 20, + 50*DisplayMode+2, MainWin->w()-360, 20, "F9:Label F10:Print F11:Paste F12:Pause"); gpKeyInfo->labelsize(10); gXoffset = 45*DisplayMode+1; gYoffset = 25*DisplayMode + MENU_HEIGHT+1; + gRectsize = MultFact - (1 - SolidChars); + if (gRectsize == 0) + gRectsize = 1; MainWin->end(); MainWin->show(); @@ -585,7 +695,8 @@ MENU_HEIGHT-2); } - char label[40]; + +char label[40]; void display_cpu_speed(void) { @@ -859,14 +970,8 @@ int T100_Disp::handle(int event) } if (key == '`') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) - { - gSpecialKeys |= MT_GRAPH; - gKeyStates['['] = 0; - } - else - gKeyStates['['] = 0; - + gSpecialKeys |= MT_GRAPH; + gKeyStates['['] = 0; } if (key == '\\') { @@ -1129,3 +1234,4 @@ int T100_Disp::handle(int event) + From f45b79cc8adecbb50382abb76e1a2d453a7dfbb3 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 31 Aug 2004 15:11:25 +0000 Subject: [PATCH 010/327] Added declarations for loading user preferences. --- src/display.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/display.h b/src/display.h index 011d93a..10f01de 100644 --- a/src/display.h +++ b/src/display.h @@ -37,6 +37,7 @@ extern "C" { #endif extern int gDelayUpdateKeys; +void initpref(void); void initdisplay(void); void drawbyte(int driver, int column, int value); void power_down(); From aff22a22e0757a441a20e5953fec071eb9bebf84 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 31 Aug 2004 15:12:16 +0000 Subject: [PATCH 011/327] Added support for undocumented opcodes. --- src/do_instruct.h | 110 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 86 insertions(+), 24 deletions(-) diff --git a/src/do_instruct.h b/src/do_instruct.h index 0be41ea..7f3a59a 100644 --- a/src/do_instruct.h +++ b/src/do_instruct.h @@ -52,8 +52,11 @@ if(trace) \ strcat(p,"INX "rps); \ l++; \ - if(!l) \ + F &= ~XF_BIT; \ + if(!l) { \ h++; \ + F |= XF_BIT; \ + } \ cpu_delay(6); \ } @@ -121,8 +124,11 @@ if(trace) \ strcat(p,"DCX "rps); \ l--; \ - if(l==0xff) \ + F &= ~XF_BIT; \ + if(l==0xff) { \ + F |= XF_BIT; \ h--; \ + } \ cpu_delay(6); \ } @@ -381,8 +387,16 @@ if(!(INS&0x04)) { if(!(INS&0x02)) { if(!(INS&0x01)) { - /* case 0x08: /* INVALID? */ - bail("0x08 is invalid"); + /* case 0x08: /* DSUB */ + INCPC; + if (trace) + sprintf(p, "DSUB"); + i = HL > BC - (CF?1:0); + j = HL - BC - (CF?1:0); + L=j&0xFF; + H=(j >> 8) & 0xFF; + setflags(H | L,-2,-1,-2,-2,i); + cpu_delay(10); /* return; */ } else { @@ -438,8 +452,16 @@ if(!(INS&0x04)) { if(!(INS&0x02)) { if(!(INS&0x01)) { - /* case 0x10: /* INVALID? */ - bail("0x10 is invalid"); + /* case 0x10: /* ASHR */ + INCPC; + if (trace) + sprintf(p, "ASHR"); + i = L & CF ; + j = HL >> 1; + L = j & 0xFF; + H = (j >> 8) & 0xFF; + setflags(0,-2,-2,-2,-2,i); + cpu_delay(7); /* return; */ } else { @@ -493,8 +515,16 @@ if(!(INS&0x04)) { if(!(INS&0x02)) { if(!(INS&0x01)) { - /* case 0x18: /* INVALID? */ - bail("0x18 is invalid"); + /* case 0x18: /* RLDE */ + INCPC; + if (trace) + sprintf(p, "RLDE"); + i = D & 0x80 ? 1 : 0; + j = DE << 1; + E = j & 0xFF; + D = (j >> 8) & 0xFF; + setflags(0,-2,-2,-2,-2,i); + cpu_delay(10); /* return; */ } else { @@ -606,14 +636,18 @@ if(trace) strcat(p,"DAA"); i=j=0; + /* Check if lower nibble greater than 9 */ if(((A&0x0F) > 9)) { - i=6; - j=1; + i=6; /* Add 6 to lower nibble */ + j=1; /* Aux carry to upper nibble */ } + /* Check for Aux Carry from last operation */ if(AC) - i=6; + i=6; /* Add 6 to lower nibble */ + /* Check if upper nibble will be greater than 9 */ + /* after any carry's are added */ if((((A>>4)+j) > 9) || CF) - i|=0x60; + i|=0x60;/* Add 6 to upper nibble */ A+=i; setflags(A,-1,-1,j,-1,i>>4?1:0); cpu_delay(4); @@ -626,8 +660,15 @@ if(!(INS&0x04)) { if(!(INS&0x02)) { if(!(INS&0x01)) { - /* case 0x28: /* INVALID? */ - bail("0x28 is invalid"); + /* case 0x28: /* LDEH */ + INCPC; + if (trace) + sprintf(p, "LDEH %02x", INS); + j = HL + INS; + INCPC; + E = j & 0xFF; + D = (j >> 8) & 0xFF; + cpu_delay(10); /* return; */ } else { @@ -755,8 +796,15 @@ if(!(INS&0x04)) { if(!(INS&0x02)) { if(!(INS&0x01)) { - /* case 0x38: /* UNSUPPORTED */ - bail("0x38 is invalid"); + /* case 0x38: /* LDES */ + INCPC; + if (trace) + sprintf(p, "LDES %02x", INS); + j = SP + INS; + INCPC; + E = j & 0xFF; + D = (j >> 8) & 0xFF; + cpu_delay(10); /* return; */ } else { @@ -1813,8 +1861,13 @@ RETURN(CF,"RC"); } else { - /* case 0xD9: /* INVALID? */ - bail("0xD9 is invalid"); + /* case 0xD9: /* SHLX */ + INCPC; + if (trace) + sprintf(p, "SHLX"); + MEM(DE)=L; + MEM(DE+1)=H; + cpu_delay(10); /* return; */ } } @@ -1841,8 +1894,8 @@ CALL(CF,"CC"); } else { - /* case 0xDD: /* INVALID? */ - bail("0xDD is invalid"); + /* case 0xDD: /* JNX addr */ + JUMP(!XF,"JNX"); /* return; */ } } @@ -1989,8 +2042,13 @@ CALL(PF,"CPE"); } else { - /* case 0xED: /* INVALID? */ - bail("0xED is invalid"); + /* case 0xED: /* LHLX */ + INCPC; + if (trace) + sprintf(p, "LHLX"); + L=MEM(DE); + H=MEM(DE+1); + cpu_delay(10); /* return; */ } } @@ -2114,8 +2172,8 @@ CALL(SF,"CM"); } else { - /* case 0xFD: /* INVALID? */ - bail("0xFD is invalid"); + /* case 0xFD: /* JX addr */ + JUMP(XF,"JX"); /* return; */ } } @@ -2132,6 +2190,10 @@ else i=0; j = (((A & 0x0F)-(INS & 0x0F)) & 0x10) >> 4; + if (trace == 1) + fprintf(tracefile, "CPI setflags args %02X, %02x, %02x, %02x, %02x %02x\n", + A-INS, -1, -1, j, -1, i) ; + setflags(A-INS,-1,-1,j,-1,i); INCPC; cpu_delay(7); From e1fc6d141d9982951f17defba2c0ec3069ee1e6d Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 31 Aug 2004 15:12:40 +0000 Subject: [PATCH 012/327] Made changes for WIN32 compatibility. --- src/doins.c | 6 +++++- src/gen_defs.h | 7 +++++++ src/genwrap.c | 3 +++ src/io.h | 8 +++++--- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/doins.c b/src/doins.c index 07c9348..337ee6e 100644 --- a/src/doins.c +++ b/src/doins.c @@ -54,7 +54,11 @@ static char paritybits[256]={ 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, }; +#if defined(WIN32) +void setflags(int regval, int sign, int zero, int auxcarry, int parity, int carry) +#else __inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry) +#endif { if(sign>=0) F=(F&0x7F)|(sign?0x80:0); @@ -73,7 +77,7 @@ __inline void setflags(unsigned char regval, char sign, char zero, char auxcarry F=(F&0xFB)|(parity?0x04:0); else if(parity==-1) { /* Table Lookup */ - F=(F&0xFB)|paritybits[regval]; + F=(F&0xFB)|paritybits[regval & 0xFF]; } if(carry>=0) diff --git a/src/gen_defs.h b/src/gen_defs.h index d9c3ba2..d51bf26 100644 --- a/src/gen_defs.h +++ b/src/gen_defs.h @@ -125,6 +125,13 @@ enum { #ifndef DWORD #define DWORD ulong #endif +#ifndef UINT64 +#if defined(WIN32) +#define UINT64 __int64 +#else +#define UINT64 unsigned long long +#endif +#endif #ifndef BOOL #define BOOL int #endif diff --git a/src/genwrap.c b/src/genwrap.c index 1299e8e..7cba246 100644 --- a/src/genwrap.c +++ b/src/genwrap.c @@ -94,6 +94,7 @@ char* DLLCALL lastchar(const char* str) return((char*)str); } +#ifndef WIN32 /****************************************************************************/ /* Return character value of C-escaped (\) character */ /****************************************************************************/ @@ -162,6 +163,8 @@ char* DLLCALL unescape_cstr(char* str) return(str); } +#endif + /****************************************************************************/ /* Convert ASCIIZ string to upper case */ /****************************************************************************/ diff --git a/src/io.h b/src/io.h index f726450..ac3fbed 100644 --- a/src/io.h +++ b/src/io.h @@ -33,14 +33,16 @@ #include "gen_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + extern unsigned long gSpecialKeys; extern unsigned char gKeyStates[128]; extern uchar ioBA; extern int gModel; -#ifdef __cplusplus -extern "C" { -#endif void init_io(void); void out(uchar port, uchar val); void update_keys(void); From 6c98007044763a43a1b2e37c1155523972a63409 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 31 Aug 2004 15:13:58 +0000 Subject: [PATCH 013/327] Made changes to switch back to STD ROM after a reset. --- src/io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/io.c b/src/io.c index 069135c..bcecf92 100644 --- a/src/io.c +++ b/src/io.c @@ -141,9 +141,10 @@ void init_io(void) } +int cROM = 0; + void out(uchar port, uchar val) { - static cROM=0; int c; switch(port) { From 1e78718d065ef351ec9cf04262421bc1ee732fff Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 31 Aug 2004 15:14:40 +0000 Subject: [PATCH 014/327] Added support for loading option ROMS. Added support for loading user preferences. Fixed some WIN32 compile issues. --- src/m100emu.c | 108 +++++++++++++++++++++++++++++++++++--------------- src/m100emu.h | 14 +++++-- 2 files changed, 88 insertions(+), 34 deletions(-) diff --git a/src/m100emu.c b/src/m100emu.c index c455ed3..1c08c2e 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -46,31 +46,38 @@ #include "display.h" #include "genwrap.h" #include "filewrap.h" +#include "roms.h" +#include "intelhex.h" int fullspeed=0; -uchar cpu[14]; -uchar memory[65536]; -uchar sysROM[32768]; -uchar optROM[32768]; -char op[26]; -unsigned long long int cycles=0; -unsigned long long int instructs=0; -unsigned long long int last_isr_cycle=0; -int trace=0; -int starttime; -FILE *tracefile; -DWORD rst7cycles = 9830; +uchar cpu[14]; +uchar memory[65536]; +uchar sysROM[ROMSIZE]; +uchar optROM[ROMSIZE]; +char op[26]; +UINT64 cycles=0; +UINT64 instructs=0; +UINT64 last_isr_cycle=0; +int trace=0; +int starttime; +FILE *tracefile; +DWORD rst7cycles = 9830; DWORD one_sec_cycle_count; DWORD one_sec_time; -unsigned long long int one_sec_cycles; +UINT64 one_sec_cycles; DWORD update_secs = 0; -float cpu_speed; +float cpu_speed; int gExitApp = 0; - +char gsOptRomFile[256]; DWORD last_one_sec_time; +extern RomDescription_t gM100_Desc; +extern int cROM; +RomDescription_t *gStdRomDesc; + + #ifdef _WIN32 __inline double hirestimer(void) { @@ -105,7 +112,7 @@ void cpu_delay(int cy) last_instruct+=cy*0.000000416666666667; while(hirestimer() 32768) || (start_addr != 0)) + return; + // Copy data to optROM + for (c = 0; c < len; c++) + optROM[c] = buf[c]; + } + else + { + // Open BIN file + fd=open(gsOptRomFile,O_RDONLY); + if(fd!=-1) + { + read(fd, optROM, ROMSIZE); + close(fd); + } + } } void initcpu(void) @@ -180,6 +231,8 @@ void initcpu(void) memcpy(memory, sysROM, ROMSIZE); + gStdRomDesc = &gM100_Desc; + for (i = 0; i < RAMSIZE; i++) memory[ROMSIZE + i] = 0; @@ -192,19 +245,14 @@ void initcpu(void) fclose(ram); } - memset(optROM,0,ROMSIZE); - fd=open("optROM.bin",O_RDONLY); - if(fd!=-1) { - read(fd, optROM, ROMSIZE); - close(fd); - return; - } + // Load option ROM if any + load_opt_rom(); } __inline void check_interrupts(void) { - static unsigned long long int last_rst75=0; + static UINT64 last_rst75=0; static DWORD last_rst_ms = 0; if((last_rst75+rst7cycles) Date: Tue, 31 Aug 2004 15:17:57 +0000 Subject: [PATCH 015/327] Initial checkin. --- src/file.cpp | 1139 ++++++++++++++++++++++++++++++++++++++++++++++++ src/file.h | 47 ++ src/intelhex.c | 235 ++++++++++ src/intelhex.h | 40 ++ src/m100rom.c | 991 +++++++++++++++++++++++++++++++++++++++++ src/memory.c | 41 ++ src/memory.h | 21 + src/roms.h | 87 ++++ 8 files changed, 2601 insertions(+) create mode 100644 src/file.cpp create mode 100644 src/file.h create mode 100644 src/intelhex.c create mode 100644 src/intelhex.h create mode 100644 src/m100rom.c create mode 100644 src/memory.c create mode 100644 src/memory.h create mode 100644 src/roms.h diff --git a/src/file.cpp b/src/file.cpp new file mode 100644 index 0000000..56485a5 --- /dev/null +++ b/src/file.cpp @@ -0,0 +1,1139 @@ +/* file.cpp */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include + + +#include +#include +#ifdef _WIN32 +#include +#endif + +extern "C" +{ +#include "memory.h" +#include "roms.h" +#include "intelhex.h" +#include "m100emu.h" +extern RomDescription_t *gStdRomDesc; +void resetcpu(void); +} + + +int BasicSaveMode = 0; +int COSaveMode = 0; +extern Fl_Preferences virtualt_prefs; +extern char gsMenuROM[40]; + +void cb_LoadRam (Fl_Widget* w, void*) +{ + Fl_File_Chooser *FileWin; + + FileWin = new Fl_File_Chooser(".","*.bin",1,"Load RAM file"); + FileWin->preview(0); + FileWin->show(); + +} + +void cb_SaveRam (Fl_Widget* w, void*) +{ + Fl_File_Chooser *FileWin; + + FileWin = new Fl_File_Chooser(".","*.bin",1,"Save RAM file"); + FileWin->preview(0); + // FileWin.value(0)="RAM.bin" + FileWin->show(); + +} + + +void cb_LoadOptRom (Fl_Widget* w, void*) +{ + Fl_File_Chooser *FileWin; + int count, len; + char buffer[65536]; + unsigned short start_addr; + + const char *filename; + + FileWin = new Fl_File_Chooser(".","*.{bin,hex}",1,"Load Optional ROM file"); + FileWin->preview(0); + FileWin->show(); + + while (FileWin->visible()) + Fl::wait(); + + count = FileWin->count(); + if (count == 0) + { + delete FileWin; + return; + } + + // Get Filename + filename = FileWin->value(1); + if (filename == 0) + { + delete FileWin; + return; + } + + // Check for hex file + len = strlen(filename); + if (((filename[len-1] | 0x20) == 'x') && + ((filename[len-2] | 0x20) == 'e') && + ((filename[len=3] | 0x20) == 'h')) + { + // Check if hex file format is valid + len = load_hex_file((char *) filename, buffer, &start_addr); + + if (len == 0) + { + fl_message("HEX file format invalid!"); + return; + } + } + + // Save the selected file in the preferences + virtualt_prefs.set("OptRomFile",filename); + + strcpy(gsOptRomFile, filename); + + // Update menu + strcpy(gsMenuROM, fl_filename_name(gsOptRomFile)); + + load_opt_rom(); + resetcpu(); +} + + +char *gIllformedBasic = "Ill formed BASIC file"; +static char *gTooLargeMsg = "File too large for available memory"; + +#define TYPE_BA 0x80 +#define TYPE_CO 0xA0 +#define TYPE_DO 0xC0 +#define TYPE_HEX 0x40 + + +char *gKeywordTable[] = { + "END", "FOR", "NEXT", "DATA", "INPUT", "DIM", "READ", "LET", + "GOTO", "RUN", "IF", "RESTORE", "GOSUB", "RETURN", "REM", "STOP", + "WIDTH", "ELSE", "LINE", "EDIT", "ERROR", "RESUME", "OUT", "ON", + "DSKO$", "OPEN", "CLOSE", "LOAD", "MERGE", "FILES", "SAVE", "LFILES", + "LPRINT", "DEF", "POKE", "PRINT", "CONT", "LIST", "LLIST", "CLEAR", + "CLOAD", "CSAVE", "TIME$", "DATE$", "DAY$", "COM", "MDM", "KEY", + "CLS", "BEEP", "SOUND", "LCOPY", "PSET", "PRESET", "MOTOR", "MAX", + "POWER", "CALL", "MENU", "IPL", "NAME", "KILL", "SCREEN", "NEW", + +// ========================================== +// Function keyword table TAB to < +// ========================================== + "TAB(", "TO", "USING", "VARPTR", "ERL", "ERR", "STRING$","INSTR", + "DSKI$", "INKEY$","CSRLIN","OFF", "HIMEM", "THEN", "NOT", "STEP", + "+", "-", "*", "/", "^", "AND", "OR", "XOR", + "EQV", "IMP", "MOD", "\\", ">", "=", "<", + +// ========================================== +// Function keyword table SGN to MID$ +// ========================================== + "SGN", "INT", "ABS", "FRE", "INP", "LPOS", "POS", "SQR", + "RND", "LOG", "EXP", "COS", "SIN", "TAN", "ATN", "PEEK", + "EOF", "LOC", "LOF", "CINT", "CSNG", "CDBL", "FIX", "LEN", + "STR$", "VAL", "ASC", "CHR$", "SPACE$","LEFT$", "RIGHT$", "MID$", + +// End of table marker + "" +}; + +int relocate(unsigned char* in, unsigned char* out, unsigned short addr) +{ + int c; + unsigned short next_line; + unsigned short this_line; + int line_number; + int line_len; + unsigned short addr1; + unsigned short base; + + next_line = 1;; + this_line = 0; + c = 0; + line_number = -1; + + // Get pointer to next line + next_line = ((unsigned short) in[c+1] << 8) + (unsigned short) in[c]; + line_len =0; + base = in[0] + (in[1] << 8); + while (next_line != 0) + { + c += 2; // Skip next line pointer + line_len += 2; // Update BASIC line length + + if (in[c] + (in[c+1] << 8) <= line_number) + { + fl_message(gIllformedBasic); + return 0; + } + + line_number = in[c] + (in[c+1] << 8); + + out[c] = in[c]; // Copy low byte of line number + c++; + line_len++; + out[c] = in[c]; // Copy high byte of line number + c++; + line_len++; + + // Copy tokenized line + while (in[c] != 0) + { + out[c] = in[c]; + c++; + line_len++; + } + + out[c] = in[c]; // Copy terminating zero + c++; + line_len++; + + // Update pointer to next line (of line just copied) + out[this_line] = (addr + c) & 0xFF; + out[this_line+1] = (addr + c) >> 8; + + // Validate the line pointers are valid + if (this_line != 0) + { + addr1 = in[this_line] + (in[this_line+1] << 8); + if (addr1 != base + line_len) + { + fl_message(gIllformedBasic); + return 0; + } + } + + // Update location where next pointer will be stored + base = in[this_line] + (in[this_line+1] << 8); + this_line = c; + + // Get pointer to next line + next_line = ((unsigned short) in[c+1] << 8) + (unsigned short) in[c]; + line_len = 0; + } + + // Copy terminating 0x0000 to out + out[c++] = 0; + out[c++] = 0; + + return c; +} + +#define STATE_LINENUM 1 +#define STATE_WHITE 2 +#define STATE_TOKENIZE 3 +#define STATE_CR 4 + +int tokenize(unsigned char* in, unsigned char* out, unsigned short addr) +{ + int state; + int c, x; + unsigned short line_num; + int line_num_len; + unsigned char tok_line[256]; + int line_len; + unsigned char token; + int tok_len; + int out_len; + int last_line_num; + int next_line_offset; + + c = 0; + line_num = 0; + line_num_len = 0; + line_len = 0; + out_len = 0; + last_line_num = -1; + next_line_offset = 0; + state = STATE_LINENUM; + + // Initialize out array with a blank line + out[0] = 0; + out[1] = 0; + + // Parse until end of string + while ((in[c] != 0) && (in[c] != 0x1A)) + { + switch (state) + { + // Read linenumber until non numeric + case STATE_LINENUM: + if ((in[c] < '0') || (in[c] > '9')) + { + // Check for blank lines + if ((in[c] == 0x0d) || (in[c] == 0x0a)) + { + // Skip this character + c++; + } + // Check for characters with no line number + else if (line_num_len == 0) + { + fl_message(gIllformedBasic); + return 0; + } + + // First space not added to output - skip it + if (in[c] == ' ') + c++; + + // Line number found, go to tokenize state + state = STATE_TOKENIZE; + } + else + { + // Add byte to line number + line_num = line_num * 10 + in[c] - '0'; + line_num_len++; + c++; + } + break; + + case STATE_TOKENIZE: + // Check for '?' and assign to PRINT + if (in[c] == '?') + { + tok_line[line_len++] = 0xA3; + c++; + } + // Check for REM tick + else if (in[c] == '\'') + { + tok_line[line_len++] = ':'; + tok_line[line_len++] = 14 | 0x80; + c++; + tok_line[line_len++] = 0xFF; + + // Copy bytes to token line until 0x0D or 0x0A + while ((in[c] != 0x0d) && (in[c] != 0x0a) + && (in[c] != 0)) + { + tok_line[line_len++] = in[c++]; + } + } + // Check for characters greater than 127 and skip + else if ((in[c] > 127) || (in[c] == 0x0d)) + { + c++; + } + // Check for quote + else if (in[c] == '"') + { + tok_line[line_len++] = in[c++]; + // Copy bytes to token line until quote ended + while ((in[c] != '"') && (in[c] != 0x0d) && (in[c] != 0x0a) + && (in[c] != 0)) + { + tok_line[line_len++] = in[c++]; + } + + // Add trailing quote to tok_line + if (in[c] == '"') + tok_line[line_len++] = in[c++]; + } + // Check for end of line + else if (in[c] == 0x0a) + { + // Skip this byte - don't add it to the line + c++; + + if (line_len != 0) + { + // Add line to output + if (line_num > last_line_num) + { + // Add line to end of output + out[next_line_offset] = (addr + next_line_offset + 5 + line_len) & 0xFF; + out[next_line_offset] = (addr + next_line_offset + 5 + line_len) >> 8; + next_line_offset += 2; + + // Add line number + out[next_line_offset++] = line_num & 0xFF; + out[next_line_offset++] = line_num >> 8; + + // Add tokenized line + for (x = 0; x < line_len; x++) + out[next_line_offset++] = tok_line[x]; + + // Add terminating zero + out[next_line_offset++] = 0; + + // Add 0x0000 as next line number offset + out[next_line_offset] = 0; + out[next_line_offset+1] = 0; + + // Update out_len to reflect current length + out_len += line_len + 5; + + // Update last_line_num + last_line_num = line_num; + + } + else + { + // Add line somewhere in the middle + + // NEED TO ADD CODE HERE!!!!! + } + } + state = STATE_LINENUM; + line_len = 0; + line_num = 0; + } + // Add '0' through ';' to tokenized line "as-is" + else if ((in[c] >= '0') && (in[c] <= ';')) + { + tok_line[line_len++] = in[c++]; + } + else + { + // Search token table for match + for (token = 0; strlen(gKeywordTable[token]) != 0; token++) + { + tok_len = strlen(gKeywordTable[token]); + // Compare next Keyword with input + if (strncmp(gKeywordTable[token], (char *) &in[c], + tok_len) == 0) + { + // Add ':' prior to ELSE if not already there + if ((token == 17) && (tok_line[line_len-1] != ':')) + { + tok_line[line_len++] = ':'; + } + tok_line[line_len++] = token + 0x80; + c += tok_len; + + // If REM token, add bytes to end of line + if (token == 14) + { + // Copy bytes to token line until 0x0D or 0x0A + while ((in[c] != 0x0d) && (in[c] != 0x0a) + && (in[c] != 0)) + { + tok_line[line_len++] = in[c++]; + } + } + + // If DATA token, add bytes to EOL or ':' + if (token == 3) + { + // Copy bytes to token line until 0x0D or 0x0A + while ((in[c] != ':') && (in[c] != 0x0d) && (in[c] != 0x0a) + && (in[c] != 0)) + { + tok_line[line_len++] = in[c++]; + } + } + break; + } + } + + // Check if token not found - add byte directly + if (token == 0x7F) + { + tok_line[line_len++] = in[c++]; + } + } + break; + } + } + + return out_len + 2; +} + + +void cb_LoadFromHost(Fl_Widget* w, void*) +{ + int count, i, x; + Fl_File_Chooser *fc; + const char *filename; + const char *filename_name; + char mt_file[8]; + int len; + FILE *fd; + int file_type; + unsigned char data[262144]; + unsigned char conv[32768]; + unsigned short start_addr; + char ch; + unsigned short addr1, addr2, addr3, addr4; + int dir_index; + int move_len; + int need_tokenize; + + fc = new Fl_File_Chooser(".","Model T Files (*.{do,txt,ba,co,hex})",1,"Load file from Host"); + fc->preview(0); + fc->show(); + + while (fc->visible()) + Fl::wait(); + + count = fc->count(); + if (count == 0) + { + delete fc; + return; + } + + // Get Filename + filename = fc->value(1); + if (filename == 0) + { + delete fc; + return; + } + len = strlen(filename); + delete fc; + + // Open file + fd = fopen(filename, "rb"); + if (fd == 0) + { + fl_message("Unable to open file %s", filename); + return; + } + + // Determine type of file + file_type = TYPE_DO; + if (((filename[len-1] | 0x20) == 'o') && + ((filename[len-2] | 0x20) == 'c')) + file_type = TYPE_CO; + if (((filename[len-1] | 0x20) == 'a') && + ((filename[len-2] | 0x20) == 'b')) + file_type = TYPE_BA; + if (((filename[len-1] | 0x20) == 'x') && + ((filename[len-2] | 0x20) == 'e') && + ((filename[len-3] | 0x20) == 'h')) + file_type = TYPE_HEX; + + // Convert filename to Model T name + filename_name = fl_filename_name(filename); + i = 0; + for (x = 0; x < 6; x++) + { + if (filename_name[i] == '.') + mt_file[x] = ' '; + else + mt_file[x] = toupper(filename_name[i++]); + } + if (file_type == TYPE_BA) + { + mt_file[6] = 'B'; + mt_file[7] = 'A'; + } + else if (file_type == TYPE_DO) + { + mt_file[6] = 'D'; + mt_file[7] = 'O'; + } + else if ((file_type == TYPE_CO) || (file_type == TYPE_HEX)) + { + mt_file[6] = 'C'; + mt_file[7] = 'O'; + } + + + // Determine "RAW" length of file (w/o CRLF expansion) + fseek(fd, 0, SEEK_END); + len = ftell(fd); + if (len > 262144) + { + fclose(fd); + fl_message(gTooLargeMsg); + return; + } + + // Read contents to buffer + fseek(fd, 0, SEEK_SET); + fread(data, 1, len, fd); + + // Close the file + fclose(fd); + + // Determine file location + if (file_type == TYPE_BA) + { + addr1 = get_memory16(gStdRomDesc->sFilePtrBA); + } + else if ((file_type == TYPE_CO) || (file_type == TYPE_HEX)) + { + addr1 = get_memory16(gStdRomDesc->sBeginVar); + } + else if (file_type == TYPE_DO) + { + addr1 = get_memory16(gStdRomDesc->sFilePtrDO); + } + + // Determine length of data and expand LF to CRLF + if (file_type == TYPE_DO) + { + i=x=ch=0; + while (i < len) + { + if ((data[i] == 0x0A) && (ch != 0x0D)) + conv[x++] = 0x0D; + ch = data[i++]; + conv[x++] = ch; + if (x >= 32768) + { + fl_message(gTooLargeMsg); + return; + } + } + + if (ch != 0x1A) + { + conv[x++] = 0x1A; + } + + len = x; + } + // For BASIC files, determine if tokenization required + else if (file_type == TYPE_BA) + { + need_tokenize = 1; + + // Check first 10 bytes searching for control characters + for (x = 0; x < 10; x++) + { + if (iscntrl(data[x]) && (data[x] != 0x0d) && (data[x] != 0x0a)) + { + need_tokenize = 0; + break; + } + } + + if (need_tokenize) + { + // Insure file ends with CR + data[len] = 0x0a; + data[len+1] = 0; + + // Tokenize the file & locate at addr1 + len = tokenize(data, conv, addr1); + } + else + { + // Insure tokenized file ends with 0x0000 + data[len] = 0; + data[len+1] = 0; + + // Relocate to new address + len = relocate(data, conv, addr1); + } + } + // For HEX files, load the hex file into conv to get length + else if (file_type == TYPE_HEX) + { + len = load_hex_file((char *) filename, (char *) data, &start_addr); + if (len == 0) + fl_message("Invalid HEX file format"); + } + + if (len == 0) + return; + + // Determine if file will fit in memory + addr3 = get_memory16(gStdRomDesc->sBasicStrings); + addr2 = get_memory16(gStdRomDesc->sBeginVar); + if (addr3 - addr2 < len) + { + fl_message(gTooLargeMsg); + return; + } + + // Determine if file alaready exists in directory + addr2 = gStdRomDesc->sDirectory; + dir_index = 0; + while ((get_memory8(addr2) != 0) && (dir_index < gStdRomDesc->sDirCount)) + { + // Compare this entry to the file being added + for (x = 0; x < 8; x++) + { + if (get_memory8(addr2 + 3 + x) != mt_file[x]) + break; + } + + if (x == 8) + { + fl_message("File %s already exists", filename_name); + return; + } + + addr2 += 11; + dir_index++; + } + + // Determine Directory entry location for new file + addr4 = gStdRomDesc->sDirectory; + dir_index = 0; + while (get_memory8(addr4) != 0) + { + // Point to next directory entry + addr4 += 11; + if (++dir_index >= gStdRomDesc->sDirCount) + { + fl_message("Too many files in directory"); + return; + } + } + + // Move memory to make space for file + move_len = get_memory16(gStdRomDesc->sUnusedMem) - addr1; + for (x = move_len-1; x >= 0; x--) + set_memory8(addr1+len+x, get_memory8(addr1+x)); + + // Update existing Directory entry addresses + addr2 = gStdRomDesc->sDirectory; + dir_index = 0; + while (dir_index < gStdRomDesc->sDirCount) + { + // Check if this entry is active + if (get_memory8(addr2) == 0) + { + addr2 += 11; + dir_index++; + continue; + } + + // Get address of this file + addr3 = get_memory16(addr2+1); + + // Check if file moved + if (addr3 >= addr1) + set_memory16(addr2+1, addr3+len); + + addr2 += 11; + dir_index++; + } + + // Add new Directory entry + if (file_type == TYPE_HEX) + set_memory8(addr4, TYPE_CO); + else + set_memory8(addr4, file_type); + set_memory16(addr4+1, addr1); + for (x = 0; x < 8; x++) + set_memory8(addr4+3+x, mt_file[x]); + + + // If a .BA file was added, renumber the address + // pointers in any "unsaved" BASIC program that + // may exist. + if (file_type == TYPE_BA) + { + addr3 = get_memory16(gStdRomDesc->sFilePtrBA)+len; + + while (get_memory16(addr3) != 0) + { + set_memory16(addr3, get_memory16(addr3)+len); + addr3 = get_memory16(addr3); + } + } + + // Update Other pointers stored in memory + addr3 = get_memory16(gStdRomDesc->sBeginArray); + if (addr3 >= addr1) + set_memory16(gStdRomDesc->sBeginArray, addr3 + len); + + if ((file_type != TYPE_CO) || (file_type == TYPE_HEX)) + { + addr3 = get_memory16(gStdRomDesc->sBeginCO); + if (addr3 > addr1) + set_memory16(gStdRomDesc->sBeginCO, addr3 + len); + } + + if (file_type == TYPE_BA) + { + addr3 = get_memory16(gStdRomDesc->sBeginDO); + if (addr3 > addr1) + set_memory16(gStdRomDesc->sBeginDO, addr3 + len); + } + + addr3 = get_memory16(gStdRomDesc->sBeginVar); + if (addr3 >= addr1) + set_memory16(gStdRomDesc->sBeginVar, addr3 + len); + + addr3 = get_memory16(gStdRomDesc->sUnusedMem); + if (addr3 >= addr1) + set_memory16(gStdRomDesc->sUnusedMem, addr3 + len); + + // Copy the data to the Model T + if (file_type == TYPE_DO) + { + for (x = 0; x < len; x++) + set_memory8(addr1+x, conv[x]); + } + else if ((file_type == TYPE_CO) || (file_type == TYPE_HEX)) + { + for (x = 0; x < len; x++) + set_memory8(addr1+x, data[x]); + } + else if (file_type == TYPE_BA) + { + for (x = 0; x < len; x++) + set_memory8(addr1+x, conv[x]); + } + + + // Reset the system so file will show up + resetcpu(); + +} + + +/* +======================================================================= +Routines to save Model T files to the host +======================================================================= +*/ + +typedef struct model_t_files { + char name[10]; + unsigned short address; + unsigned short dir_address; + unsigned short size; +} model_t_files_t; + +Fl_Window *gSaveToHost; +int gSave; + +void cb_save (Fl_Widget* w, void*) +{ + gSave = 1; + gSaveToHost->hide(); +} + +void cb_cancel (Fl_Widget* w, void*) +{ + gSaveToHost->hide(); +} + +void save_file(model_t_files_t *pFile) +{ + unsigned short addr1, addr2; + unsigned char ch; + unsigned short len; + int c; + unsigned char type; + unsigned short line; + FILE *fd; + Fl_File_Chooser *fc; + char filename[12]; + + if (pFile == 0) + return; + + // Get output filename + strcpy(filename, pFile->name); + len = strlen(filename); + if (filename[len-1] == 'O' && filename[len-2] == 'C') + { + if (COSaveMode == 1) + { + filename[len-3] = 0; + strcat(filename, ".HEX"); + } + } + + fc = new Fl_File_Chooser(filename,"*.*",Fl_File_Chooser::CREATE,"Save file as"); + fc->preview(0); + // FileWin.value(0)="RAM.bin" + fc->show(); + + while (fc->visible()) + Fl::wait(); + + + // Check if a file was selected + if (strlen(fc->value()) == 0) + { + delete fc; + return; + } + + + // Try to open the ouput file + fd = fopen(fc->value(), "rb+"); + if (fd != NULL) + { + // File already exists! Check for overwrite! + fclose(fd); + + c = fl_choice("Overwrite existing file?", "Cancel", "Yes", "No"); + + if ((c == 0) || (c == 2)) + { + delete fc; + return; + } + } + + fd = fopen(fc->value(), "wb+"); + if (fd == NULL) + { + fl_message("Error opening %s for write", fc->value()); + delete fc; + return; + } + + delete fc; + + // Get file type + type = get_memory8(pFile->dir_address); + + // Save base on file type + switch (type) + { + case TYPE_BA: + addr1 = pFile->address; + while ((addr2 = get_memory16(addr1)) != 0) + { + if (BasicSaveMode == 0) + { + // Save line as tokenized data + for (c = addr2-addr1; c > 0; c--) + { + ch = get_memory8(addr1++); + fwrite(&ch, 1, 1, fd); + } + } + else + // Detokenize the line and save as ASCII + { + addr1 += 2; + // Print line number + line = get_memory16(addr1); + addr1 += 2; + fprintf(fd, "%u ", line); + + // Read remaining data & detokenize + while (addr1 < addr2) + { + // Get next byte + ch = get_memory8(addr1++); + + // Check if byte is ':' + if (ch == ':') + { + // Get next character + ch = get_memory8(addr1); + + // Check for REM tick + if (ch == 0x8E) + { + if (get_memory8(addr1+1) == 0xFF) + { + ch = '\''; + fwrite(&ch, 1, 1, fd); + addr1 += 2; + continue; + } + } + + // Check for ELSE + if (ch == 0x91) + continue; + + ch = ':'; + fwrite(&ch, 1, 1, fd); + } + else if (ch > 0x7F) + { + fprintf(fd, "%s", gKeywordTable[ch & 0x7F]); + } + else if (ch == 0) + { + fprintf(fd, "\n"); + } + else + { + fwrite(&ch, 1, 1, fd); + } + + } + } + + } + break; + + case TYPE_DO: + addr1 = pFile->address; + while ((ch = get_memory8(addr1++)) != 0x1a ) + { + fwrite(&ch, 1, 1, fd); + } + + // Write end of file marker (0x1a) to file + fwrite(&ch, 1, 1, fd); + break; + + case TYPE_CO: + // Get length of file to be saved + addr1 = pFile->address; + len = get_memory16(addr1+2) + 6; + if (COSaveMode == 1) + { + save_hex_file(addr1, addr1+len, fd); + } + else + { + for (c = 0; c < len; c++) + { + get_memory8(addr1+c); + fwrite(&ch, 1, 1, fd); + } + } + break; + } + + // Close the output file + fclose(fd); +} + +void cb_SaveToHost(Fl_Widget* w, void*) +{ + Fl_Hold_Browser *fsb; + Fl_Button *fsave; + Fl_Button *fcancel; + unsigned short addr1; + char mt_file[10]; + int dir_index; + unsigned char file_type; + int x, c; + int col_widths[] = {120, 100,100, 0}; + model_t_files_t tFiles[100]; + int tCount; + + // Create the windows + gSaveToHost = new Fl_Window(220,320,"Select file to save to Host"); + fsb = new Fl_Hold_Browser(0, 0, 220,280); + fsave = new Fl_Button(20,288,80,25,"Save"); + fsave->callback(cb_save); + fcancel = new Fl_Button(130, 288, 80, 25, "Cancel"); + fcancel->callback(cb_cancel); + + // Add header & columns for size, address, etc. +// fsb->add("@b@_File\t@b@_Size\t@b@_Address"); +// fsb->column_widths(col_widths); + + // Add Model T files to the browser + addr1 = gStdRomDesc->sDirectory; + dir_index = 0; + tCount = 0; + while (dir_index < gStdRomDesc->sDirCount) + { + file_type = get_memory8(addr1); + if ((file_type != TYPE_BA) && (file_type != TYPE_DO) && + (file_type != TYPE_CO)) + { + dir_index++; + addr1 += 11; + continue; + } + + c = 0; + for (x = 0; x < 6; x++) + { + if (get_memory8(addr1+3+x) != ' ') + mt_file[c++] = get_memory8(addr1+3+x); + } + + mt_file[c++] = '.'; + mt_file[c++] = get_memory8(addr1+3+x++); + mt_file[c++] = get_memory8(addr1+3+x); + mt_file[c] = '\0'; + + // Add filename to tFiles structure + strcpy(tFiles[tCount].name, mt_file); + + // Get address of file + tFiles[tCount].address = get_memory16(addr1+1); + tFiles[tCount++].dir_address = addr1; + + fsb->add(mt_file); + + dir_index++; + addr1 += 11; + } + + // Loop through all tFiles and add to the Browser +/* for (c = 0; c < tCount; c++) + { + // Add filename to Select Browser + sprintf(string, "%s\t%d\t%d", tFiles[c].name, 0, tFiles[c].address); + fsb->add(string); + } +*/ + // Show the window + gSaveToHost->resizable(fsb); + gSaveToHost->show(); + + // Default to No-save and wait for a button + gSave = 0; + while (gSaveToHost->visible()) + Fl::wait(); + + // Check if save button was selected + if (gSave) + { + // Find entry for the file selected + c = fsb->value(); + for (x = 0; x < tCount; x++) + { + // Search array for entry + if (strcmp(fsb->text(c), tFiles[x].name) == 0) + { + save_file(&tFiles[x]); + break; + } + } + } + + // Cleanup the windows stuff + delete fsave; + delete fcancel; + delete fsb; + delete gSaveToHost; +} diff --git a/src/file.h b/src/file.h new file mode 100644 index 0000000..8d445bb --- /dev/null +++ b/src/file.h @@ -0,0 +1,47 @@ +/* file.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef _FILE_H_ +#define _FILE_H_ + +#include "gen_defs.h" + + +void cb_LoadRam (Fl_Widget* w, void*); +void cb_SaveRam (Fl_Widget* w, void*); +void cb_LoadOptRom (Fl_Widget* w, void*); +void cb_UnloadOptRom (Fl_Widget* w, void*); +void cb_LoadFromHost(Fl_Widget* w, void*); +void cb_SaveToHost(Fl_Widget* w, void*); + +extern int BasicSaveMode; +extern int COSaveMode; + +#endif diff --git a/src/intelhex.c b/src/intelhex.c new file mode 100644 index 0000000..a58498d --- /dev/null +++ b/src/intelhex.c @@ -0,0 +1,235 @@ +/* intelhex.c */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + + +/* Intel HEX read/write functions, Paul Stoffregen, paul@ece.orst.edu */ +/* This code is in the public domain. Please retain my name and */ +/* email address in distributed copies, and let me know about any bugs */ + +/* I, Paul Stoffregen, give no warranty, expressed or implied for */ +/* this software and/or documentation provided, including, without */ +/* limitation, warranty of merchantability and fitness for a */ +/* particular purpose. */ + + +#include +#include +#include "intelhex.h" + +/* some ansi prototypes.. maybe ought to make a .h file */ + +/* this is used by load_file to get each line of intex hex */ +int parse_hex_line(char *theline, int bytes[], int *addr, int *num, int *code); + +/* this does the dirty work of writing an intel hex file */ +/* caution, static buffering is used, so it is necessary */ +/* to call it with end=1 when finsihed to flush the buffer */ +/* and close the file */ +void hexout(FILE *fhex, int byte, int memory_location, int end); + + +extern char memory[65536]; /* the memory is global */ + +/* parses a line of intel hex code, stores the data in bytes[] */ +/* and the beginning address in addr, and returns a 1 if the */ +/* line was valid, or a 0 if an error occured. The variable */ +/* num gets the number of bytes that were stored into bytes[] */ + +int parse_hex_line(theline, bytes, addr, num, code) +char *theline; +int *addr, *num, *code, bytes[]; +{ + int sum, len, cksum; + char *ptr; + + *num = 0; + if (theline[0] != ':') return 0; + if (strlen(theline) < 11) return 0; + ptr = theline+1; + if (!sscanf(ptr, "%02x", &len)) return 0; + ptr += 2; + if ( (int)strlen(theline) < (11 + (len * 2)) ) return 0; + if (!sscanf(ptr, "%04x", addr)) return 0; + ptr += 4; + /* printf("Line: length=%d Addr=%d\n", len, *addr); */ + if (!sscanf(ptr, "%02x", code)) return 0; + ptr += 2; + sum = (len & 255) + ((*addr >> 8) & 255) + (*addr & 255) + (*code & 255); + while(*num != len) { + if (!sscanf(ptr, "%02x", &bytes[*num])) return 0; + ptr += 2; + sum += bytes[*num] & 255; + (*num)++; + if (*num >= 256) return 0; + } + if (!sscanf(ptr, "%02x", &cksum)) return 0; + if ( ((sum & 255) + (cksum & 255)) & 255 ) return 0; /* checksum error */ + return 1; +} + +/* loads an intel hex file into the global memory[] array */ +/* filename is a string of the file to be opened */ + +int load_hex_file(char *filename, char *buffer, unsigned short *start_addr) +{ + char line[1000]; + FILE *fin; + int addr, n, status, bytes[256]; + int i, total=0, lineno=1; + int minaddr=65536, maxaddr=0; + char mem[65536]; + + fin = fopen(filename, "r"); + if (fin == NULL) { + return 0; + } + while (!feof(fin) && !ferror(fin)) { + line[0] = '\0'; + i = 0; + while (!feof(fin)) + { + line[i] = fgetc(fin); + if ((line[i] == 0x0d) || line[i] == 0x0a) + { + if (i != 0) + break;; + } + else if (line[i] != -1) + i++; + } + if (i == 0) + break; + line[i] = 0; + if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0'; + if (line[strlen(line)-1] == '\r') line[strlen(line)-1] = '\0'; + if (parse_hex_line(line, bytes, &addr, &n, &status)) { + if (status == 0) { /* data */ + for(i=0; i<=(n-1); i++) { + mem[addr] = bytes[i] & 255; + total++; + if (addr < minaddr) minaddr = addr; + if (addr > maxaddr) maxaddr = addr; + addr++; + } + } + if (status == 1) { /* end of file */ + fclose(fin); + n = 0; + for (i = minaddr; i end) { + return; + } + for (addr=begin; addr <= end; addr++) + hexout(fd, memory[addr], addr, 0); + hexout(fd, 0, 0, 1); +} + + +/* produce intel hex file output... call this routine with */ +/* each byte to output and it's memory location. The file */ +/* pointer fhex must have been opened for writing. After */ +/* all data is written, call with end=1 (normally set to 0) */ +/* so it will flush the data from its static buffer */ + +#define MAXHEXLINE 32 /* the maximum number of bytes to put in one line */ + +void hexout(FILE *fhex, int byte, int memory_location, int end) +{ + static int byte_buffer[MAXHEXLINE]; + static int last_mem, buffer_pos, buffer_addr; + static int writing_in_progress=0; + register int i, sum; + + if (!writing_in_progress) { + /* initial condition setup */ + last_mem = memory_location-1; + buffer_pos = 0; + buffer_addr = memory_location; + writing_in_progress = 1; + } + + if ( (memory_location != (last_mem+1)) || (buffer_pos >= MAXHEXLINE) \ + || ((end) && (buffer_pos > 0)) ) { + /* it's time to dump the buffer to a line in the file */ + fprintf(fhex, ":%02X%04X00", buffer_pos, buffer_addr); + sum = buffer_pos + ((buffer_addr>>8)&255) + (buffer_addr&255); + for (i=0; i < buffer_pos; i++) { + fprintf(fhex, "%02X", byte_buffer[i]&255); + sum += byte_buffer[i]&255; + } + fprintf(fhex, "%02X\n", (-sum)&255); + buffer_addr = memory_location; + buffer_pos = 0; + } + + if (end) { + fprintf(fhex, ":00000001FF\n"); /* end of file marker */ + fclose(fhex); + writing_in_progress = 0; + } + + last_mem = memory_location; + byte_buffer[buffer_pos] = byte & 255; + buffer_pos++; +} + + + diff --git a/src/intelhex.h b/src/intelhex.h new file mode 100644 index 0000000..50b31ae --- /dev/null +++ b/src/intelhex.h @@ -0,0 +1,40 @@ +/* intelhex.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef INTELHEX_H +#define INTELHEX_H + +/* this loads an intel hex file into the memory[] array */ +int load_hex_file(char *filename, char *buffer, unsigned short *start_addr); + +/* this writes a part of memory[] to an intel hex file */ +void save_hex_file(int begin, int end, FILE* fd); + + +#endif diff --git a/src/m100rom.c b/src/m100rom.c new file mode 100644 index 0000000..44df566 --- /dev/null +++ b/src/m100rom.c @@ -0,0 +1,991 @@ +/* m100rom.c */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "roms.h" + + +Std_ROM_Table_t gM100_Tables[] = { + { 0x0003, 5, TABLE_TYPE_STRING }, + { 0x0040, 64, TABLE_TYPE_JUMP }, + { 0x0080, 271, TABLE_TYPE_MODIFIED_STRING }, + { 0x018F, 97, TABLE_TYPE_MODIFIED_STRING }, + { 0x01F0, 112, TABLE_TYPE_MODIFIED_STRING }, + { 0x0262, 140, TABLE_TYPE_JUMP }, + { 0x02EE, 46, TABLE_TYPE_JUMP }, + { 0x031C, 62, TABLE_TYPE_2BYTE }, + { 0x036F, 123, TABLE_TYPE_CODE }, + { 0x03EA, 23, TABLE_TYPE_STRING }, + { 0x0C74, 19, TABLE_TYPE_STRING }, + { 0x0D71, 17, TABLE_TYPE_STRING }, + { 0x14D2, 6, TABLE_TYPE_JUMP }, + { 0x14F2, 6, TABLE_TYPE_JUMP }, + { 0x14FC, 10, TABLE_TYPE_JUMP }, + { 0x167F, 10, TABLE_TYPE_JUMP }, + { 0x1754, 6, TABLE_TYPE_JUMP }, + { 0x1762, 10, TABLE_TYPE_JUMP }, + { 0x17D1, 10, TABLE_TYPE_JUMP }, + { 0x1877, 8, TABLE_TYPE_JUMP }, + { 0x1978, 21, TABLE_TYPE_3BYTE }, + { 0x2481, 16, TABLE_TYPE_STRING }, + { 0x25d5, 18, TABLE_TYPE_STRING }, + { 0x26FE, 14, TABLE_TYPE_STRING }, + { 0x26FE, 14, TABLE_TYPE_STRING }, + { 0x325C, 32, TABLE_TYPE_CODE }, + { 0x327C, 2, TABLE_TYPE_CODE }, + { 0x327E, 88, TABLE_TYPE_CODE }, + { 0x32D6, 1, TABLE_TYPE_CODE }, + { 0x32D7, 32, TABLE_TYPE_CODE }, + { 0x32F7, 1, TABLE_TYPE_CODE }, + { 0x32F8, 24, TABLE_TYPE_CODE }, + { 0x3310, 1, TABLE_TYPE_CODE }, + { 0x3311, 32, TABLE_TYPE_CODE }, + { 0x3331, 1, TABLE_TYPE_CODE }, + { 0x3332, 40, TABLE_TYPE_CODE }, + { 0x335A, 1, TABLE_TYPE_CODE }, + { 0x335B, 64, TABLE_TYPE_CODE }, + { 0x339B, 1, TABLE_TYPE_CODE }, + { 0x339C, 64, TABLE_TYPE_CODE }, + { 0x438A, 24, TABLE_TYPE_BYTE_LOOKUP }, + { 0x43B8, 66, TABLE_TYPE_BYTE_LOOKUP }, + { 0x50F1, 33, TABLE_TYPE_CTRL_DELIM }, + { 0x5113, 16, TABLE_TYPE_JUMP }, + { 0x5185, 30, TABLE_TYPE_4BYTE_CMD }, + { 0x51A3, 1, TABLE_TYPE_CODE }, + { 0x51A4, 28, TABLE_TYPE_CTRL_DELIM }, + { 0x5244, 9, TABLE_TYPE_STRING }, + { 0x5443, 18, TABLE_TYPE_CTRL_DELIM }, + { 0x550D, 16, TABLE_TYPE_JUMP }, + { 0x551D, 1, TABLE_TYPE_CODE }, + { 0x5583, 18, TABLE_TYPE_STRING }, + { 0x5595, 6, TABLE_TYPE_STRING }, + { 0x559B, 2, TABLE_TYPE_STRING }, + { 0x5751, 64, TABLE_TYPE_STRING }, + { 0x5AE9, 36, TABLE_TYPE_3BYTE }, + { 0x5B0D, 17, TABLE_TYPE_STRING }, + { 0x5B1E, 6, TABLE_TYPE_CODE }, + { 0x5B24, 19, TABLE_TYPE_STRING }, + { 0x5B37, 15, TABLE_TYPE_CODE }, + { 0x5B46, 34, TABLE_TYPE_CTRL_DELIM }, + { 0x5CCE, 33, TABLE_TYPE_STRING }, + { 0x5CEF, 18, TABLE_TYPE_4BYTE_CMD }, + { 0x5E15, 13, TABLE_TYPE_STRING }, + { 0x5E22, 8, TABLE_TYPE_CODE }, + { 0x5E2A, 37, TABLE_TYPE_CTRL_DELIM }, + { 0x5F38, 17, TABLE_TYPE_STRING }, + { 0x5F49, 2, TABLE_TYPE_CODE }, + { 0x5F4B, 21, TABLE_TYPE_STRING }, + { 0x5F60, 5, TABLE_TYPE_STRING }, + { 0x6018, 62, TABLE_TYPE_JUMP }, + { 0x6BF1, 88, TABLE_TYPE_CATALOG }, + { 0x6E94, 18, TABLE_TYPE_JUMP }, + { 0x7551, 240, TABLE_TYPE_CODE }, + { 0x7643, 20, TABLE_TYPE_CODE }, + { 0x770B, 6, TABLE_TYPE_CODE }, + { 0x7711, 96*5, TABLE_TYPE_CODE }, + { 0x78F1, 128*6, TABLE_TYPE_CODE }, + { 0x7BF1, 322, TABLE_TYPE_CODE }, + { 0x7F01, 14, TABLE_TYPE_CODE }, + { 0x7F98, 39, TABLE_TYPE_STRING }, + { 0x7FBF, 23, TABLE_TYPE_STRING }, + { -1, 0, 0 } +}; + +Std_ROM_Addresses_t gM100_Vars[] = { + { 0x0040, "Function vector table for SGN to MID$" }, + { 0x0080, "BASIC statement keyword table END to NEW" }, + { 0x018E, "Function keyword table TAB to <" }, + { 0x01F0, "Function keyword table SGN to MID$" }, + { 0x0262, "BASIC statement vector table for END to NEW" }, + { 0x02EE, "Vector table for math operations" }, + { 0x031C, "BASIC error message text" }, + { 0x035A, "Initialization image loaded to F5F0H" }, + { 0x036F, "External ROM detect image loaded at F605H" }, + { 0x03EA, "BASIC message strings" }, + { 0x1F24, "Cassette frequency cycle count" }, + { 0x4349, "Cassette frequency cycle count" }, + { 0x551D, "TERM Mode function key vector table" }, + { 0x5B1E, "Directory file-type display order table" }, + { 0x5E22, "TEXT Function key table - empty" }, + { 0x6BF1, "ROM programs catalog entries" }, + { 0x71F7, "Interrupt exit routine (pop all regs & RET)" }, + { 0x71F8, "Interrupt exit routine (pop all regs & RET)" }, + { 0x7551, "8155 PIO chip bit patterns for Upper LCD drivers" }, + { 0x7551, "8155 PIO chip bit patterns for Lower LCD drivers" }, + { 0x7643, "8155 PIO chip bit patterns for LCD drivers" }, + { 0x7F01, "Initial clock chip register values" }, + { 0x7F98, "MENU Text Strings" }, + { 0x7FA4, "TRS-80 model number string" }, + { 0xF5F0, "Active system signature -- Warm vs Cold boot" }, + { 0xF5F4, "HIMEM" }, + { 0xF5F9, "RST 5.5 RAM Vector" }, + { 0xF5FC, "RST 6.5 RAM Vector" }, + { 0xF5FF, "RST 7.5 RAM Vector" }, + { 0xF602, "RAM vector for TRAP interrupt" }, + { 0xF62A, "Option ROM flag" }, + { 0xF62B, "Dial speed (1=10pps, 2=20pps" }, + { 0xF630, "Function key status table (1 = on)" }, + { 0xF638, "New Console device flag" }, + { 0xF639, "Cursor row (1-8)" }, + { 0xF63A, "Cursor column (1-40)" }, + { 0xF63B, "Active rows count (1-8)" }, + { 0xF63C, "Active columns count (1-40)" }, + { 0xf63d, "Label line protect status" }, + { 0xF63e, "Scroll disable flag" }, + { 0xF63f, "Cursor status (0 = off)" }, + { 0xF640, "Cursor row (1-8)" }, + { 0xF641, "Cursor column (1-40)" }, + { 0xF646, "ESC mode flag for RST 20H" }, + { 0xF648, "Reverse video switch" }, + { 0xF64E, "X coord of last point plotted" }, + { 0xF64F, "Y coord of last point plotted" }, + { 0xF656, "Power off exit condition switch" }, + { 0xF658, "Full/Half duplex switch" }, + { 0xF65A, "RS232 auto linefeed switch" }, + { 0xF65B, "RS232 parameter setting table" }, + { 0xF661, "Address last called" }, + { 0xF667, "OUT statement hook" }, + { 0xF66A, "INP function hook" }, + { 0xF672, "Last Error code" }, + { 0xF674, "Line printer head position" }, + { 0xF675, "Output device for RST 20H (0=screen)" }, + { 0xF678, "BASIC string buffer pointer" }, + { 0xF67A, "Current executing line number" }, + { 0xF67C, "Start of BASIC program pointer" }, + { 0xF680, "End of statement marker" }, + { 0xF685, "Keyboard buffer" }, + { 0xF788, "Horiz. position of cursor (0-39)" }, + { 0xF789, "Function key definition area" }, + { 0xF80A, "Function key definition area (BASIC)" }, + { 0xF88C, "End of RAM for file storage" }, + { 0xF923, "Seconds (ones)" }, + { 0xF924, "Seconds (tens)" }, + { 0xF925, "Minutes (ones)" }, + { 0xF926, "Minutes (tens)" }, + { 0xF927, "Hours (ones)" }, + { 0xF928, "Hours (tens)" }, + { 0xF929, "Date (ones)" }, + { 0xF92A, "Date (tens)" }, + { 0xF92B, "Day code (0=Sun, 1=Mon, etc.)" }, + { 0xF92C, "Month (1-12)" }, + { 0xF92D, "Year (ones)" }, + { 0xF92E, "Year (tens)" }, + { 0xF933, "Seconds (ones)" }, + { 0xF934, "Seconds (tens)" }, + { 0xF935, "Minutes (ones)" }, + { 0xF936, "Minutes (tens)" }, + { 0xF937, "Hours (ones)" }, + { 0xF938, "Hours (tens)" }, + { 0xF939, "Date (ones)" }, + { 0xF93A, "Date (tens)" }, + { 0xF93B, "Day code (0=Sun, 1=Mon, etc.)" }, + { 0xF93D, "Time for ON TIME interrupt (SSHHMM)" }, + { 0xF944, "On Com flag" }, + { 0xF945, "On Com routine address" }, + { 0xF947, "On Time flag" }, + { 0xF948, "On Time routine address" }, + { 0xF94A, "Function key vector table" }, + { 0xF962, "Start of RAM directory" }, + { 0xF99A, "BASIC program not saved pointer" }, + { 0xF9A5, "Start of Paste Buffer" }, + { 0xFAAC, "Last char sent to printer" }, + { 0xFAAD, "Label line enable flag" }, + { 0xFAAE, "Contents of port A8H" }, + { 0xFAAF, "Start of IPL filename" }, + { 0xFABA, "Address where last BASIC list started" }, + { 0xFABE, "SP save area for power up/down" }, + { 0xFAC0, "Lowest RAM address used by system" }, + { 0xFAC9, "Offset of last RST 38H call" }, + { 0xFAD0, "Length of last program loaded/saved to tape" }, + { 0xFADA, "Start of RST 38H vector table" }, + { 0xFAE2, "LCD character output hook" }, + { 0xFAE4, "Printer character output hook" }, + { 0xFB00, "EOF function hook" }, + { 0xFB0C, "Term F6 hook" }, + { 0xFB0E, "Term F7 hook" }, + { 0xFB14, "WIDTH statement hook" }, + { 0xFB1A, "CRT open routine hook" }, + { 0xFB1E, "CRT output file routine hook" }, + { 0xFB20, "WAND Open routine hook" }, + { 0xFB22, "WAND Close routine hook" }, + { 0xFB24, "WAND Get routine hook" }, + { 0xFB26, "WAND Special I/O routine hook" }, + { 0xFB28, "LOF function hook" }, + { 0xFB2A, "LOC function hook" }, + { 0xFB2C, "LFILES statement hook" }, + { 0xFB2E, "DSKI$ routine hook" }, + { 0xFB30, "DSKO$ routine hook" }, + { 0xFB64, "Variable Create/Locate switch" }, + { 0xFB65, "Type of last variable used" }, + { 0xFB67, "File buffer area pointer" }, + { 0xFB94, "Line number of current data statement" }, + { 0xFB96, "FOR/NEXT loop active flag" }, + { 0xFB99, "Address of last variable assigned" }, + { 0xFB9B, "Most recent or currenly running line pointer" }, + { 0xFB9D, "SP used by BASIC to reinitialize the stack" }, + { 0xFB9F, "Line number of last error" }, + { 0xFBA1, "Most recent used or entered line number" }, + { 0xFBA3, "Pointer to occurance of error" }, + { 0xFBA5, "Address of ON ERROR routine" }, + { 0xFBAA, "Line where break, END, or STOP occurred" }, + { 0xFBAC, "Address where program stopped on last break, END, or STOP" }, + { 0xFBAE, "Start of DO files pointer" }, + { 0xFBB0, "Start of CO files pointer" }, + { 0xFBB2, "Start of variable data pointer" }, + { 0xFBB4, "Start of array table pointer" }, + { 0xFBB6, "Unused memory pointer" }, + { 0xFBB8, "Address where DATA search will begin next" }, + { 0xFBBA, "DEF definition table" }, + { 0xFBE7, "8-Byte floating point for double precision math" }, + { 0xFC18, "Start of FAC1 for single and double precision" }, + { 0xFC1A, "Start of FAC1 for integers" }, + { 0xFC60, "8-Byte floating point for double precision math" }, + { 0xFC69, "Start of FAC2 for single and double precision" }, + { 0xFC6B, "Start of FAC2 for integers" }, + { 0xFC82, "Maxfiles" }, + { 0xFC83, "File number description table pointer" }, + { 0xFC93, "Filename of current BASIC program" }, + { 0xFC9C, "Filename of last program loaded from tape" }, + { 0xFCC0, "Start of Alt LCD character buffer" }, + { 0xFDA1, "Map of MENU entry positions to RAM directory positions" }, + { 0xFDED, "Flag to indicate MENU entry location or command entry" }, + { 0xFDEE, "Current MENU directory location" }, + { 0xFDEF, "Maximum MENU directory location" }, + { 0xFE00, "Start of LCD character buffer" }, + { 0xFF40, "XON/XOFF protocol control" }, + { 0xFF41, "XON/XOFF protocol control" }, + { 0xFF42, "XON/XOFF enable flag" }, + { 0xFF43, "RS232 initialization status" }, + { 0xFF44, "Sound flag" }, + { 0xFF45, "Contents of port E8H" }, + { 0xFF46, "RS232 Character buffer" }, + { 0xFF86, "RS232 buffer count" }, + { 0xFF87, "RS232 buffer output position" }, + { 0xFF88, "RS232 buffer input pointer" }, + { 0xFF8A, "Control-S status" }, + { 0xFF8B, "UART baud rate timer value" }, + { 0xFF8D, "RS232 Parity Control byte" }, + { 0xFF8E, "Cassette port pulse control" }, + { 0xFF97, "Special key status storage" }, + { 0xFF98, "Function key status storage" }, + { 0xFF99, "Keyboard scan column storage #1" }, + { 0xFFA2, "Keyboard scan column storage @2" }, + { 0xFFA3, "Shift key status storage" }, + { 0xFFA4, "Key repeat start delay counter" }, + { 0xFFA6, "Key position storage" }, + { 0xFFA8, "Pointer to entry in 2nd Storage Buffer for key" }, + { 0xFFAA, "Keyboard buffer count" }, + { 0xFFAB, "Keyboard typeahead buffer" }, + { 0xFFEC, "Cursor bit pattern storage" }, + { -1, "" } +}; + +Std_ROM_Addresses_t gM100_Funs[] = { + { 0x0000, "Reset Vector" }, + { 0x0008, "Compare next byte with M" }, + { 0x0010, "Get next non-white char from M" }, + { 0x0018, "Compare DE and HL" }, + { 0x001E, "Send a space to screen/printer" }, + { 0x0020, "Send character in A to screen/printer" }, + { 0x0024, "Power down TRAP" }, + { 0x0028, "Determine type of last var used" }, + { 0x002C, "RST 5.5 -- Bar Code Reader" }, + { 0x0030, "Get sign of FAC1" }, + { 0x0034, "RST 6.5 -- RS232 character pending" }, + { 0x0038, "RAM vector table driver" }, + { 0x003C, "RST 7.5 -- Timer background task" }, + { 0x0040, "Function vector table for SGN to MID$" }, + { 0x0080, "BASIC statement keyword table END to NEW" }, + { 0x018F, "Function keyword table TAB to <" }, + { 0x01F0, "Function keyword table SGN to MID$" }, + { 0x0262, "BASIC statement vector table for END to NEW" }, + { 0x02E2, "Math operator priority table" }, + { 0x02EE, "Vector table for math operations" }, + { 0x031C, "BASIC error message text" }, + { 0x035A, "Initialization image loaded to F5F0H" }, + { 0x036F, "External ROM detect image loaded at F605H" }, + { 0x03EA, "BASIC message strings" }, + { 0x0401, "Pop return address for NEXT or RETURN" }, + { 0x0422, "Initialize system and go to BASIC ready" }, + { 0x0446, "Generate Syntax error" }, + { 0x0449, "Generate /0 error" }, + { 0x044C, "Generate NF error" }, + { 0x044F, "Generate DD error" }, + { 0x0452, "Generate RW error" }, + { 0x0455, "Generate OV error" }, + { 0x0458, "Generate MO error" }, + { 0x045B, "Generate TM error" }, + { 0x045D, "Generate error in E" }, + { 0x048D, "Restore stack & runtime and jump to BC" }, + { 0x04C5, "Print BASIC error message - XX error in XXX" }, + { 0x0501, "Pop stack and vector to BASIC ready" }, + { 0x0502, "Vector to BASIC ready - print Ok" }, + { 0x0511, "Silent vector to BASIC ready" }, + { 0x0523, "Perform operation at M and return to ready" }, + { 0x05F0, "Update line addresses for current BASIC program" }, + { 0x05F0, "Update line addresses for current BASIC program" }, + { 0x060A, "Evaluate LIST statement arguments" }, + { 0x0628, "Find line number in DE" }, + { 0x062B, "Find line number in DE starting at HL" }, + { 0x0646, "Perform Token compression" }, + { 0x0726, "FOR statement" }, + { 0x076B, "TO statement" }, + { 0x0783, "STEP statement" }, + { 0x0804, "Execute BASIC program" }, + { 0x083A, "Start executing BASIC program at HL" }, + { 0x0840, "Execute instruction in A, HL points to args" }, + { 0x0858, "RST 10H routine with pre-increment of HL" }, + { 0x0858, "RST 10H routine" }, + { 0x0872, "DEF statement" }, + { 0x0881, "DEFDBL statement" }, + { 0x0886, "DEFINT statement" }, + { 0x0896, "DEFSNG statement" }, + { 0x089F, "DEFSTR statement" }, + { 0x08A1, "Declare variable at M to be type E" }, + { 0x08DB, "Generate FC error" }, + { 0x08E0, "Evaluate line number text at M" }, + { 0x08EB, "Convert ASCII number at M to binary" }, + { 0x08EC, "Convert ASCII number at M+1 to binary" }, + { 0x090F, "RUN statement" }, + { 0x091E, "GOSUB statement" }, + { 0x0936, "GOTO statement" }, + { 0x094D, "Generate UL error" }, + { 0x0966, "RETURN statement" }, + { 0x099E, "DATA statement" }, + { 0x09A0, "REM statement" }, + { 0x09C3, "LET statement" }, + { 0x0A2F, "ON statement" }, + { 0x0A34, "ON ERROR statement" }, + { 0x0A5B, "ON KEY/TIME/COM/MDM GOSUB routine" }, + { 0x0A94, "ON TIME$ handler" }, + { 0x0AB0, "RESUME statement" }, + { 0x0B0F, "ERROR statement" }, + { 0x0B1A, "IF statement" }, + { 0x0B4E, "LPRINT statement" }, + { 0x0B56, "PRINT statement" }, + { 0x0C01, "TAB statement" }, + { 0x0C45, "LINE statement" }, + { 0x0C99, "INPUT # statement" }, + { 0x0CA3, "INPUT statement" }, + { 0x0CD9, "READ statement" }, + { 0x0DAB, "Main BASIC evaluation routine" }, + { 0x0F0D, "Integer Divide FAC1=DE/HL" }, + { 0x0F1C, "Evaluate function at M" }, + { 0x0F47, "ERR function" }, + { 0x0F56, "ERL function" }, + { 0x0F7E, "VARPTR function" }, + { 0x0F86, "VARPTR(#buffer) function" }, + { 0x0F92, "VARPTR(variable) function" }, + { 0x0FDA, "Evaluate variable" }, + { 0x0FE8, "Get char at M and convert to uppercase" }, + { 0x0FE9, "Convert A to uppercase" }, + { 0x1037, "ASCII num conversion - find ASCII or tokenized '+' or '-' in A" }, + { 0x1054, "NOT function" }, + { 0x1069, "RST 28H routine" }, + { 0x108C, "OR function" }, + { 0x1097, "AND function" }, + { 0x10A2, "XOR function" }, + { 0x10AD, "EQV function" }, + { 0x10B5, "IMP function" }, + { 0x10C8, "LPOS function" }, + { 0x10CE, "POS function" }, + { 0x10D1, "Load integer in A into FAC1" }, + { 0x10E6, "Check for running program" }, + { 0x10EF, "Generate ID error" }, + { 0x1100, "INP function" }, + { 0x110C, "OUT statement" }, + { 0x1112, "Evaluate expression at M" }, + { 0x1113, "Evaluate expression at M-1" }, + { 0x112D, "Evaluate expression at M" }, + { 0x112E, "Evaluate expression at M-1" }, + { 0x113B, "LLIST statement" }, + { 0x1140, "LIST statement" }, + { 0x11A2, "Send buffer at M to screen" }, + { 0x1284, "PEEK function" }, + { 0x128B, "POKE function" }, + { 0x1297, "Evaluate expression at M" }, + { 0x12CB, "Wait for key from keyboard" }, + { 0x13A5, "Toggle function key label line" }, + { 0x13DB, "Check keyboard queue for pending characters" }, + { 0x1419, "POWER statement" }, + { 0x1431, "Normal TRAP (low power) interrupt routine" }, + { 0x143F, "Turn off computer" }, + { 0x1459, "POWER CONT statement" }, + { 0x1461, "POWER ON statement" }, + { 0x1470, "Output character to printer" }, + { 0x148A, "Start tape and load tape header" }, + { 0x1494, "Generate I/O error" }, + { 0x1499, "Turn cassette motor on and detect sync header" }, + { 0x14A8, "Turn cassette motor on" }, + { 0x14AA, "Turn cassette motor off" }, + { 0x14B0, "Read byte from tape & update checksum" }, + { 0x14C1, "Write byte to tape & update checksum" }, + { 0x14D2, "LCD Device control block" }, + { 0x14D8, "LCD and PRT file open routine" }, + { 0x14E5, "Output to LCD file" }, + { 0x14ED, "Pop AF, BC, DE, HL from stack" }, + { 0x14F2, "CRT device control block" }, + { 0x14FC, "RAM device control block" }, + { 0x1506, "Open RAM file" }, + { 0x158D, "Close RAM file" }, + { 0x15AC, "Output to RAM file" }, + { 0x15C4, "Input from RAM file" }, + { 0x161B, "Special RAM file I/O" }, + { 0x167F, "CAS device control block" }, + { 0x1689, "Open CAS file" }, + { 0x16AD, "Close CAS file" }, + { 0x16C7, "Output to CAS file" }, + { 0x16D2, "Input from CAS file" }, + { 0x1754, "LPT device control block" }, + { 0x175A, "Output to LPT file" }, + { 0x1762, "COM device control block" }, + { 0x176C, "Open MDM file" }, + { 0x176D, "Open COM file" }, + { 0x179E, "Close COM file" }, + { 0x17A8, "Output to COM/MDM file" }, + { 0x17B0, "Input from COM/MDM file" }, + { 0x17CA, "Special COM/MDM file I/O" }, + { 0x17D1, "MDM Device control block" }, + { 0x17DB, "Close MDM file" }, + { 0x17E6, "Set RS232 parameters from string at M" }, + { 0x1877, "Wand device control block" }, + { 0x1889, "EOF function" }, + { 0x1904, "TIME$ function" }, + { 0x190F, "Read time and store it at M" }, + { 0x192F, "DATE$ function" }, + { 0x1955, "DAY function" }, + { 0x1962, "Read day and store at M" }, + { 0x19A0, "Update in-memory (F923H) clock values" }, + { 0x19AB, "TIME$ statement" }, + { 0x19B3, "Update clock chip from memory F923H" }, + { 0x19BD, "DATE$ statement" }, + { 0x19F1, "DAY$ statement" }, + { 0x1A42, "Get time string from command line" }, + { 0x1A78, "IPL statement" }, + { 0x1A96, "Erase current IPL program" }, + { 0x1A9E, "COM and MDM statements" }, + { 0x1AB2, "KEY() statement" }, + { 0x1AC3, "KEY STOP/ON/OFF statements" }, + { 0x1AEA, "Determine argument (ON/OFF/STOP) for TIME$ statement" }, + { 0x1AFC, "Determine device (KEY/TIME/COM/MDM) for ON GOSUB" }, + { 0x1B0F, "ON TIME$ statement" }, + { 0x1B22, "ON COM handler" }, + { 0x1B32, "RST 7.5 interrupt routine" }, + { 0x1BB1, "Renew automatic power-off counter" }, + { 0x1BB8, "KEY statement" }, + { 0x1BBD, "KEY LIST statement" }, + { 0x1BE0, "Send B characters from M to the screen" }, + { 0x1C57, "PSET statement" }, + { 0x1C66, "PRESET statement" }, + { 0x1C6D, "LINE (graphic) statement" }, + { 0x1CA6, "Draw a filled box on LCD. Coords are on stack" }, + { 0x1CBC, "Draw an unfilled box on LCD. Coords are on stack" }, + { 0x1D2E, "Get (X,Y) coordinate from tokenized string at M" }, + { 0x1D90, "CSRLIN function" }, + { 0x1D9B, "MAX function" }, + { 0x1DA7, "MAXRAM function" }, + { 0x1DB2, "MAXFILES function" }, + { 0x1DB9, "HIMEM function" }, + { 0x1DC3, "WIDTH statement" }, + { 0x1DC5, "SOUND statement" }, + { 0x1DE5, "SOUND OFF statement" }, + { 0x1DE6, "SOUND ON statement" }, + { 0x1DEC, "MOTOR statement" }, + { 0x1DF1, "MOTOR ON statement" }, + { 0x1DF5, "MOTOR OFF statement" }, + { 0x1DFA, "CALL statement" }, + { 0x1E22, "SCREEN statement" }, + { 0x1E5E, "LCOPY statement" }, + { 0x1F3A, "FILES statement" }, + { 0x1F42, "Display Catalog" }, + { 0x1F91, "KILL statement" }, + { 0x1FBE, "Kill a text file" }, + { 0x2037, "NAME statement" }, + { 0x20FE, "NEW statement" }, + { 0x21FA, "Count length of string at M" }, + { 0x2206, "Get .DO filename and locate in RAM directory" }, + { 0x220F, "Open a text file at (FC93H)" }, + { 0x2280, "CSAVE statement" }, + { 0x22B9, "Save buffer at M to tape" }, + { 0x22CC, "SAVEM statement" }, + { 0x22DD, "CSAVEM statement" }, + { 0x2377, "CLOAD statement" }, + { 0x2413, "Load record from tape and store at M" }, + { 0x2478, "Generate Verify Failed error" }, + { 0x2491, "LOADM and RUNM statement" }, + { 0x24A7, "CLOADM statement" }, + { 0x2542, "Move B bytes from M to (DE)" }, + { 0x254B, "Launch .CO files from MENU" }, + { 0x260B, "Open CAS for output of BASIC files" }, + { 0x260E, "Open CAS for output of TEXT files" }, + { 0x2611, "Open CAS for output of CO files" }, + { 0x2650, "Open CAS for input of BASIC files" }, + { 0x2653, "Open CAS for input of TEXT files" }, + { 0x2656, "Open CAS for input of CO files" }, + { 0x273A, "STR$ function" }, + { 0x27B1, "Print buffer at M until NULL or '\"'" }, + { 0x290F, "Move L bytes from (BC) to (DE)" }, + { 0x2943, "LEN function" }, + { 0x294F, "ASC function" }, + { 0x295F, "CHR$ function" }, + { 0x296D, "STRING$ function" }, + { 0x298E, "SPACE$ function" }, + { 0x29AB, "LEFT$ function" }, + { 0x29DC, "RIGHT$ function" }, + { 0x29E6, "MID$ function" }, + { 0x2A07, "VAL function" }, + { 0x2A37, "INSTR function" }, + { 0x2B4C, "FRE function" }, + { 0x2B69, "Double precision subtract (FAC1=FAC1-FAC2)" }, + { 0x2B78, "Double precision addition (FAC1=FAC1+FAC2)" }, + { 0x2C4F, "Add the BCD num in M to the one in (DE)" }, + { 0x2CFF, "Double precision multiply (FAC1=FAC1*FAC2)" }, + { 0x2DC7, "Double precision divide (FAC1=FAC1/FAC2)" }, + { 0x2EE6, "Move C bytes from M to (DE)" }, + { 0x2EEF, "COS function" }, + { 0x2F09, "SIN function" }, + { 0x2F58, "TAN function" }, + { 0x2F71, "ATN function" }, + { 0x2FCF, "LOG function" }, + { 0x305A, "SQR function" }, + { 0x30A4, "EXP function" }, + { 0x313E, "RND function" }, + { 0x31A0, "Double precision Square (FAC1=SQR(FAC1))" }, + { 0x31A3, "Double precision math (FAC1=M * FAC2))" }, + { 0x31B5, "Move FAC1 to FAC2" }, + { 0x31B8, "Move floating point number M to FAC2" }, + { 0x31C1, "Move FAC2 to FAC1" }, + { 0x31C4, "Move floating point number M to FAC1" }, + { 0x31CA, "Move FAC1 to M" }, + { 0x31CA, "Double precision math (FAC1=FAC1*SQR(FAC1))" }, + { 0x31CA, "Swap FAC1 and FAC2" }, + { 0x31EB, "Square FAC1 & do table based math" }, + { 0x31EB, "Square FAC1 & do table based math & muliply times FAC1" }, + { 0x3209, "Table based math (FAC1=(((FAC1*M)+(M+1))*(M+2)+(M+3)..." }, + { 0x322E, "Push FAC2 on stack" }, + { 0x3234, "Push FAC1 on stack" }, + { 0x3245, "Pop FAC2 from stack" }, + { 0x324B, "Pop FAC1 from stack" }, + { 0x325C, "Floating point numbers for math operations " }, + { 0x327C, "Floating point num-shares 6 bytes from next number" }, + { 0x327E, "Floating point numbers for math operations "}, + { 0x32D6, "Count of Floating point numbers to follow for EXP" }, + { 0x32F7, "Count of Floating point numbers to follow for EXP" }, + { 0x3310, "Count of Floating point numbers to follow for LOG" }, + { 0x3331, "Count of Floating point numbers to follow for LOG" }, + { 0x335A, "Count of Floating point numbers to follow for SIN" }, + { 0x339B, "Count of Floating point numbers to follow for ATN" }, + { 0x33DC, "RST 30H routine" }, + { 0x33F2, "ABS function" }, + { 0x3407, "SGN function" }, + { 0x3422, "Push single precision FAC1 on stack" }, + { 0x342F, "Load single precision at M to FAC1" }, + { 0x3432, "Load single precision in BCDE to FAC1" }, + { 0x343D, "Load single precision FAC1 to BCDE" }, + { 0x3447, "Load single precision at M to BCDE" }, + { 0x3450, "Reverse load single precision at M to DEBC" }, + { 0x3459, "Move single precision FAC1 to M" }, + { 0x3461, "Move M to FAC2 using precision at (FB65H)" }, + { 0x3469, "Move B bytes from (DE) to M with increment" }, + { 0x3472, "Move B bytes from (DE) to M with decrement" }, + { 0x3498, "Compare single precision in BCDE with FAC1" }, + { 0x34B0, "Compare single precision in BCDE with M" }, + { 0x34C2, "Compare signed integer in DE with that in HL" }, + { 0x34FA, "Compare double precisoin FAC1 with FAC2" }, + { 0x3501, "CINT function" }, + { 0x3510, "Load signed integer in HL to FAC1" }, + { 0x352A, "CSNG function" }, + { 0x3540, "Convert signed integer in FAC1 to single precision" }, + { 0x3543, "Convert signed integer HL to single precision FAC1" }, + { 0x35BA, "CDBL function" }, + { 0x3645, "FIX function" }, + { 0x3654, "INT function" }, + { 0x35F8, "Signed integer subtract (FAC1=HL-DE)" }, + { 0x3704, "Signed integer addition (FAC1=HL+DE)" }, + { 0x3725, "Signed integer muliply (FAC1=HL*DE)" }, + { 0x377E, "Signed integer divide (FAC1=DE/HL)" }, + { 0x37F4, "Single precision addition (FAC1=FAC1+BCDE)" }, + { 0x37F7, "Single precision addition (FAC1=FAC1+FAC2)" }, + { 0x37FD, "Single precision subtract (FAC1=FAC1-BCDE)" }, + { 0x3803, "Single precision multiply (FAC1=FAC1*BCDE)" }, + { 0x3806, "Single precision multiply (FAC1=FAC2*FAC2)" }, + { 0x380E, "Single precision divide (FAC1=BCDE/FAC1)" }, + { 0x3827, "Single precision load (FAC2=BCDE)" }, + { 0x3840, "Convert ASCII number at M to double precision in FAC1" }, + { 0x3867, "Found 'e' in ASCII number" }, + { 0x388A, "Found 'E' in ASCII number" }, + { 0x3904, "Found '.' in ASCII number" }, + { 0x391A, "Found '%' in ASCII number" }, + { 0x3929, "Found '#' in ASCII number" }, + { 0x3931, "Deal with single & double precision ASCII conversions" }, + { 0x3940, "Convert ASCII number that starts with a Digit" }, + { 0x39CC, "Finish printing BASIC ERROR message \" in \" line #" }, + { 0x39D4, "Print binary number in HL at current position" }, + { 0x39E8, "Convert binary number in FAC1 to ASCII at M" }, + { 0x39EC, "Convert binary number in FAC1 to ASCII at M with format" }, + { 0x3D11, "Initialize FAC1 with 0.0 if it has no value" }, + { 0x3D7F, "Single precision exponential function" }, + { 0x3D8E, "Double precision exponential function" }, + { 0x3DF7, "Integer exponential function" }, + { 0x3FA0, "TIME$ ON statement" }, + { 0x3FD2, "Trigger interrupt. HL points to interrupt table" }, + { 0x3FD2, "Clear interrupt. HL points to interrupt table" }, + { 0x3FB2, "TIME$ OFF statement" }, + { 0x3FB9, "TIME$ STOP statement" }, + { 0x4009, "Clear all COM, TIME, and KEY interrupt definitions" }, + { 0x407F, "RESTORE statement" }, + { 0x409A, "STOP statement" }, + { 0x409F, "END statement" }, + { 0x40DA, "CONT sttement" }, + { 0x40F1, "Check if M is alpha character" }, + { 0x40F2, "Check if A is alpha character" }, + { 0x40F9, "CLEAR statement" }, + { 0x4174, "NEXT statement" }, + { 0x4222, "Send CRLF to screen or printer" }, + { 0x4225, "Send LF to screen or printer" }, + { 0x4229, "BEEP statement" }, + { 0x422D, "Home cursor" }, + { 0x4231, "CLS statement" }, + { 0x4235, "Protect line 8. An ESC T is printed" }, + { 0x423A, "Unprotect line 8. An ESC U is printed" }, + { 0x423F, "Stop automatic scrolling" }, + { 0x4244, "Resume automatic scrolling" }, + { 0x4249, "Turn the cursor on" }, + { 0x424E, "Turn the cursor off" }, + { 0x4253, "Delete current line on screen" }, + { 0x4258, "Insert line a current line" }, + { 0x425D, "Erase from cursor to end of line" }, + { 0x4262, "Send ESC X" }, + { 0x4269, "Start inverse character mode" }, + { 0x426E, "Cancel inverse character mode" }, + { 0x4270, "End escape sequence" }, + { 0x4277, "Send cursor to lower left of CRT" }, + { 0x427C, "Set the current cursor position (H=Row,L=Col)" }, + { 0x428A, "Erase function key display" }, + { 0x42A5, "Set and display function keys (M has key table)" }, + { 0x42A8, "Display function key line" }, + { 0x4313, "Print A to the screen" }, + { 0x4431, "Character plotting level 3. Check new device console flag & call level 4)" }, + { 0x4335, "Character plotting level 4. Turn off background task & call level 5" }, + { 0x434C, "Character plotting level 5. Handle ESC sequences & call level 6" }, + { 0x4373, "LCD output driver" }, + { 0x438A, "RST 20H lookup table" }, + { 0x43AF, "ESC Y routine (Set cursor position)" }, + { 0x43B2, "LCD output Escape routine" }, + { 0x43B8, "LCD Escape sequence lookup table" }, + { 0x43FA, "ESCape sequence driver" }, + { 0x4431, "ESC p routine (start inverse video)" }, + { 0x4432, "ESC q routine (cancel inverse video)" }, + { 0x4437, "ESC U routine (unprotect line 8)" }, + { 0x4439, "ESC T routine (protect line 8)" }, + { 0x443F, "ESC V routine (stop automatic scrolling)" }, + { 0x4440, "ESC W routine (resume automatic scrolling)" }, + { 0x443A, "ESC X routine" }, + { 0x4453, "ESC C routine (move cursor right)" }, + { 0x445C, "ESC D routine (move cursor left)" }, + { 0x4461, "Backspace routine" }, + { 0x4469, "ESC A routine (move cursor up)" }, + { 0x446E, "ESC B routine (move cursor down)" }, + { 0x4480, "Tab routine" }, + { 0x4494, "Linefeed routine" }, + { 0x44A8, "Verticle tab and ESC H routine (home cursor)" }, + { 0x44AA, "CR routine" }, + { 0x44AF, "ESC P routine (turn cursor on)" }, + { 0x44BA, "ESC Q routine (turn cursor off)" }, + { 0x44C4, "ESC M routine" }, + { 0x44D2, "Scroll LCD screen A times at line number in L" }, + { 0x44EA, "ESC L routine (insert line)" }, + { 0x4512, "Get character at (H,L) from LCD RAM)" }, + { 0x4535, "ESC l routine (erase current line)" }, + { 0x4537, "ESC K routine (erase to EOL)" }, + { 0x4548, "Form Feed (0CH), CLS, ESC E, and ESC J routine" }, + { 0x4560, "Character plotting level 6. Save character in C to LCD RAM & call level 7" }, + { 0x454E, "ESC J routine" }, + { 0x463E, "Input and display line and store at (F685H)" }, + { 0x4644, "Input and display (no \"?\") line and store at (F685H)" }, + { 0x4684, "Input routine (463EH) Control-C handler" }, + { 0x4696, "Input routine (463EH) ENTER handler" }, + { 0x46A0, "Input routine (463EH) backspace, left arrow, CTRL-H handler" }, + { 0x46C3, "Input routine (463EH) CTRL-U & X handler" }, + { 0x46CA, "Input routine (463EH) Tab handler" }, + { 0x478B, "DIM statement" }, + { 0x4790, "Find address of variable at M" }, + { 0x4991, "USING function" }, + { 0x4B44, "Send A to screen or printer" }, + { 0x4B55, "Print A to printer, expanding tabs if necessary" }, + { 0x4B92, "Reinitialize output back to LCD" }, + { 0x4BAB, "LCD character output routine" }, + { 0x4BB8, "Move LCD to blank line (send CRLF if needed)" }, + { 0x4BEA, "INKEY$ function" }, + { 0x4C84, "Get file descriptor for file in A" }, + { 0x4CCB, "OPEN statement" }, + { 0x4D59, "LCD, CRT, and LPT file close routine" }, + { 0x4D6E, "RUN statement (with parameters)" }, + { 0x4D70, "LOAD statement" }, + { 0x4D71, "MERGE statement" }, + { 0x4DCF, "SAVE statement" }, + { 0x4E28, "CLOSE statement" }, + { 0x4E8E, "INPUT$ function" }, + { 0x4F0A, "Zero B bytes at M" }, + { 0x4F0B, "Load B bytes at M with A" }, + { 0x4F2E, "PRINT # initialization routine" }, + { 0x4F5B, "LINE INPUT # statement" }, + { 0x504E, "Generate NM error" }, + { 0x5051, "Generate AO error" }, + { 0x5054, "Generate DS error" }, + { 0x5057, "Generate FF error" }, + { 0x505A, "Generate CF error" }, + { 0x505D, "Generate BN error" }, + { 0x5060, "Generate IE error" }, + { 0x5063, "Generate EF error" }, + { 0x5066, "Generate FL error" }, + { 0x506B, "LOF function" }, + { 0x506D, "LOC function" }, + { 0x506F, "LFILES function" }, + { 0x5071, "DSKO$ function" }, + { 0x5073, "DSKI$ function" }, + { 0x50F1, "Device name table" }, + { 0x5113, "Device control block vector addresses table" }, + { 0x5146, "TELCOM Entry point" }, + { 0x515B, "Re-entry point for TELCOM commands" }, + { 0x5185, "TELCOM instruction vector table" }, + { 0x51A4, "TELCOM label line text table" }, + { 0x51C0, "TELCOM STAT instruction routine" }, + { 0x51C7, "Print current STAT settings" }, + { 0x51ED, "Set STAT and return to TELCOM ready" }, + { 0x522F, "TELCOM CALL instruction routine" }, + { 0x524D, "TELCOM FIND instruction routine" }, + { 0x52B4, "Go off-hook" }, + { 0x52BB, "Disconnect phone line and disable modem carrier" }, + { 0x52D0, "Connect phone line and enable modem carrier" }, + { 0x52E4, "Go off-hook and wait for carrier" }, + { 0x5310, "Pause for about 2 seconds" }, + { 0x532D, "Execute logon sequence at M" }, + { 0x5359, "Dialing routine" }, + { 0x539E, "Auto logon sequence" }, + { 0x540A, "Dial the digit in A & print on LCD" }, + { 0x5455, "TELCOM TERM instruction routine" }, + { 0x54FC, "TELCOM \"dispatcher\" routine" }, + { 0x550D, "TERM Mode function key vector table" }, + { 0x5523, "TELCOM PREV function routine" }, + { 0x553E, "TELCOM FULL/HALF function routine" }, + { 0x5550, "TELCOM ECHO function routine" }, + { 0x559D, "TELCOM UP function routine" }, + { 0x567E, "TELCOM DOWN function routine" }, + { 0x571E, "TELCOM BYE function routine" }, + { 0x5791, "Print buffer at M until NULL or \"" }, + { 0x5797, "MENU Program" }, + { 0x57F8, "Display directory entries" }, + { 0x5837, "Handle CTRL-U key from MENU command loop" }, + { 0x585A, "MENU Program command loop" }, + { 0x588E, "Handle Backspace key from MENU command loop" }, + { 0x58F7, "Handle ENTER key from MENU command loop" }, + { 0x596F, "Launch ROM command file from MENU program" }, + { 0x5970, "Display directory entries of type in register C" }, + { 0x59AD, "Convert filename from space padded to '.ext' format" }, + { 0x59C9, "Position cursor for next directory entry" }, + { 0x5A12, "Print time, day and date on first line of screen" }, + { 0x5A15, "Print time,day,date on first line w/o CLS" }, + { 0x5A58, "Print NULL terminated string at M" }, + { 0x5A62, "Copy A bytes from (DE) to M" }, + { 0x5A6D, "Compare string at DE with that at M (max C bytes)" }, + { 0x5A79, "Clear function key definition table" }, + { 0x5A7C, "Set new function key table" }, + { 0x5A9E, "Display function keys on 8th line" }, + { 0x5AA9, "Search directory for filename" }, + { 0x5AE3, "Get start address of file at M" }, + { 0x5B1E, "Directory file-type display order table" }, + { 0x5B68, "ADDRSS Entry point" }, + { 0x5B6B, "ADDRSS entry with (DE) pointing to filename" }, + { 0x5B6F, "SCHEDL Entry point" }, + { 0x5B72, "SCHEDL entry with (DE) pointing to filename" }, + { 0x5BF5, "FIND instruction for ADDRSS/SCHEDL" }, + { 0x5BF7, "LFND instruction for ADDRSS/SCHEDL" }, + { 0x5C3F, "Find text at M in the file at (DE)" }, + { 0x5C6D, "Increment DE past next CRLF in text file at (DE)" }, + { 0x5C74, "Check next byte(s) at (DE) for CRLF" }, + { 0x5CEF, "ADDRSS/SCHEDL instruction vector table" }, + { 0x5D64, "Wait for char from keyboard & convert to uppercase" }, + { 0x5D6A, "Home cursor" }, + { 0x5D70, "Print time on top line until key pressed" }, + { 0x5DEE, "TEXT Entry point" }, + { 0x5E22, "TEXT Function key table - empty" }, + { 0x5E51, "EDIT statement" }, + { 0x5F2F, "Wait for a space to be entered on keyboard" }, + { 0x5F65, "Edit .DO files" }, + { 0x5FDD, "Main TEXT edit loop" }, + { 0x6018, "TEXT control character vector table" }, + { 0x6056, "TEST ESCape routine" }, + { 0x607C, "TEXT control P routine" }, + { 0x608A, "TEXT control I routine" }, + { 0x60BE, "TEXT control M routine" }, + { 0x60DE, "TEXT right arrow and control D routine" }, + { 0x60E2, "TEXT down arrow and control X routine" }, + { 0x610B, "TEXT control H routine" }, + { 0x6151, "TEXT left arrow and control S routine" }, + { 0x6155, "TEXT up arrow and control E routine" }, + { 0x617A, "TEXT control F routine" }, + { 0x618C, "TEXT control A routine" }, + { 0x61C2, "TEXT control T routine" }, + { 0x61D7, "TEXT control B routine" }, + { 0x61FD, "TEXT control R routine" }, + { 0x620B, "TEXT control Q routine" }, + { 0x6210, "TEXT control W routine" }, + { 0x621C, "TEXT control Z routine" }, + { 0x6242, "TEXT control L routine" }, + { 0x628F, "TEXT control C routine" }, + { 0x63E5, "Get next byte for TEXT Program entry" }, + { 0x6431, "TEXT control O routine" }, + { 0x6445, "TEXT control U routine" }, + { 0x6551, "TEXT control N routine" }, + { 0x65C3, "Copy NULL terminated string at M to (DE)" }, + { 0x6691, "TEXT control Y routine" }, + { 0x6713, "TEXT control G routine" }, + { 0x6774, "TEXT control V routine" }, + { 0x6B61, "Insert A into text file at M" }, + { 0x6B6D, "Insert BC spaces at M" }, + { 0x6B9F, "Delete BC characters at M" }, + { 0x6BDB, "Move BC bytes from M to (DE) with increment" }, + { 0x6BE6, "Move BC bytes from M to (DE) with decrement" }, + { 0x6BF1, "ROM programs catalog entries" }, + { 0x6C49, "BASIC Entry point" }, + { 0x6C93, "Copy BASIC Function key table to key definition area" }, + { 0x6C9C, "Copy BASIC Function key table to key definition area" }, + { 0x6CD6, "Re-initialize system without destroying files" }, + { 0x6CE0, "Warm start reset entry" }, + { 0x6D3F, "Send character in A to the printer" }, + { 0x6D6D, "Check RS232 queue for pending characters" }, + { 0x6D7E, "Get a character from RS232 receive queue" }, + { 0x6DAC, "RST 6.5 routine (RS232 receive interrupt)" }, + { 0x6DFC, "Calculate address to save next RS232 character" }, + { 0x6E0B, "Send XON (CTRL-Q) out RS232" }, + { 0x6E1E, "Turn off XON/XOFF protocol" }, + { 0x6E32, "Send character in A to serial port using XON/XOFF" }, + { 0x6E3A, "Send character in C to serial port" }, + { 0x6E4D, "Handle XON/XOFF protocol" }, + { 0x6E75, "Set RS232 baud rate stored in H" }, + { 0x6E94, "RS232 baud rate timer values" }, + { 0x6EA6, "Initialize RS232 or modem" }, + { 0x6ECB, "Deactivate RS232 or modem" }, + { 0x6EE5, "Click sound port if sound enabled" }, + { 0x6EEF, "Check for carrier detect" }, + { 0x6F31, "Enable XON/OFF when CTRL-S / CTRL-Q sent" }, + { 0x6F39, "Initialize serial buffer parameters" }, + { 0x6F46, "Write cassette header and sync byte" }, + { 0x6F5B, "Write char in A to cassette w/o checksum" }, + { 0x6F5B, "Write char in A to cassette w/o checksum or sync bit" }, + { 0x6F6A, "Write bit 0 of A to cassette" }, + { 0x6F85, "Read cassette header and sync byte" }, + { 0x6FDB, "Read Cassette port data bit" }, + { 0x7023, "Count and pack cassette input bits" }, + { 0x702A, "Read character from cassette w/o checksum" }, + { 0x7043, "Cassette REMOTE routine - turn motor on or off" }, + { 0x7055, "Keyboard scanning management routine" }, + { 0x7060, "Key detection -- Determine which keys are pressed" }, + { 0x70B0, "Key repeat detection" }, + { 0x70B0, "Calculate key matrix position and save buffer pointer at FFA8H" }, + { 0x7122, "Key detected - initialize repeat counter and decode" }, + { 0x7122, "Key decoding" }, + { 0x71D5, "Keyboard buffer management - place key in new buffer" }, + { 0x71D5, "Keyboard buffer management - place subsequent key in buffer" }, + { 0x71F7, "Interrupt exit routine (pop all regs & RET)" }, + { 0x720A, "Handle unshifted & non-CTRL key during key decoding" }, + { 0x7222, "Handle Arrow keys during key decoding" }, + { 0x722C, "Handle CAPS LOCK key during key decoding" }, + { 0x7233, "Handle NUM key during key decoding" }, + { 0x7242, "Scan keyboard for character (CTRL-BREAK ==> CTRL-C)" }, + { 0x726A, "Enable interrupts as normal" }, + { 0x7270, "Check keyboard queue for pending characters" }, + { 0x7283, "Check for break or wait (CTRL-S)" }, + { 0x729F, "Check if SHIFT-BREAK is being pressed" }, + { 0x72B1, "Scan BREAK,CAPS,NUM,CODE,GRAPH,CTRL,SHIFT & set bits in A" }, + { 0x72C5, "Produce a tone of DE freq and B duration" }, + { 0x7329, "Copy clock chip regs to M" }, + { 0x732A, "Update clock chip regs from M" }, + { 0x7352, "Read next bit from Clock Chip" }, + { 0x7383, "Set clock chip mode" }, + { 0x73A9, "Blink the cursor" }, + { 0x744C, "Plot (set) point (D,E) on the LCD" }, + { 0x73EE, "Character plotting level 7. Plot character in C on LCD at (H,L)" }, + { 0x744D, "Clear (reset) point (D,E) on the LCD" }, + { 0x74A2, "Byte Plot - Send bit pattern to LCD for character" }, + { 0x753B, "Enable LCD drivers after short delay" }, + { 0x7548, "Wait for LCD driver to be available" }, + { 0x7551, "8155 PIO chip bit patterns for LCD drivers" }, + { 0x7643, "8155 PIO chip bit patterns for LCD drivers" }, + { 0x7657, "Delay routine - decrement C until zero" }, + { 0x765C, "Set interrupt to 1DH" }, + { 0x7662, "Beep routine" }, + { 0x7676, "Click sound port" }, + { 0x7682, "Check for optional external controller" }, + { 0x768F, "Optional external controller driver" }, + { 0x7711, "LCD char generator shape table (20H-7FH" }, + { 0x78F1, "LCD char generator shape table (80H-FFH)" }, + { 0x7BF1, "Keyboard conversion matrix" }, + { 0x7D33, "Boot routine" }, + { 0x7DE7, "Cold boot routine" }, + { 0x7EA6, "Display TRS-80 Model number & Free bytes on LCD" }, + { 0x7EAC, "Display number of free bytes on LCD" }, + { 0x7EAC, "Initialize RST 38H RAM vector table" }, + { 0x7EE1, "Calculate physical RAM available" }, + { 0x7F01, "Initial clock chip register values" }, + { 0x7F98, "MENU Text Strings" }, + { 0x7FD6, "RST 38H RAM vector driver routine" }, + { 0xF5F9, "RST 5.5 RAM Vector" }, + { 0xF5FC, "RST 6.5 RAM Vector" }, + { 0xF5FF, "RST 7.5 RAM Vector" }, + { 0xF602, "RAM vector for TRAP interrupt" }, + { 0xF605, "Detect Option ROM" }, + { -1, "" }, +}; + +RomDescription_t gM100_Desc = { + 0x3C003845, /* Signature */ + 0x7A20, /* Signature address */ + 1, /* StdRom */ + + gM100_Tables, /* Known tables */ + gM100_Vars, /* Known variables */ + gM100_Funs, /* Known functions */ + + 0xF99A, /* Address of unsaved BASIC prgm */ + 0xF9A5, /* Address of next DO file */ + 0xFBAE, /* Start of DO file area */ + 0xFBB0, /* Start of CO file area */ + 0xFBB2, /* Start of Variable space */ + 0xFBB4, /* Start of Array data */ + 0xFBB6, /* Pointer to unused memory */ + 0xF5F4, /* Address where HIMEM is stored */ + 0xF88C, /* End of RAM for file storage */ + 0xFAC0, /* Lowest RAM used by system */ + 0xF962, /* Start of RAM directory */ + 0xF678, /* BASIC string buffer pointer */ + + 24 /* Number of directory entries */ +}; + diff --git a/src/memory.c b/src/memory.c new file mode 100644 index 0000000..819f501 --- /dev/null +++ b/src/memory.c @@ -0,0 +1,41 @@ +/* +============================================================================ +memory.c + + This file is part of the Virtual T Model 100/102/200 Emulator. + + This file is copywrited under the terms of the BSD license. + + Memory management / emulation support +============================================================================ +*/ + +#include "memory.h" +#include "genwrap.h" +#include "filewrap.h" + +extern uchar memory[65536]; +extern uchar sysROM[32768]; +extern uchar optROM[32768]; + + +unsigned char get_memory8(unsigned short address) +{ + return memory[address]; +} + +unsigned short get_memory16(unsigned short address) +{ + return memory[address] + (memory[address+1] << 8); +} + +void set_memory8(unsigned short address, unsigned char data) +{ + memory[address] = data;; +} + +void set_memory16(unsigned short address, unsigned short data) +{ + memory[address] = data & 0xFF; + memory[address+1] = data >> 8; +} diff --git a/src/memory.h b/src/memory.h new file mode 100644 index 0000000..891a4cb --- /dev/null +++ b/src/memory.h @@ -0,0 +1,21 @@ +/* +============================================================================ +memory.h + + This file is part of the Virtual T Model 100/102/200 Emulator. + + This file is copywrited under the terms of the BSD license. + + Memory management / emulation support +============================================================================ +*/ + +#ifndef MEMORY_H +#define MEMORY_H + +unsigned char get_memory8(unsigned short address); +unsigned short get_memory16(unsigned short address); +void set_memory8(unsigned short address, unsigned char data); +void set_memory16(unsigned short address, unsigned short data); + +#endif diff --git a/src/roms.h b/src/roms.h new file mode 100644 index 0000000..c476d0e --- /dev/null +++ b/src/roms.h @@ -0,0 +1,87 @@ +/* roms.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef ROMS_H +#define ROMS_H + +/* Define structure for storing addresses and descriptions for */ +/* known subroutine calls and variable locations within the ROM */ +typedef struct Std_ROM_Addresses { + int addr; + char* desc; +} Std_ROM_Addresses_t; + +/* Define structure for storing known table data stored withing the ROM */ +typedef struct Std_ROM_Table { + int addr; + int size; + char type; +} Std_ROM_Table_t; + +/* Define a structure to contain all information regarding a ROM */ +typedef struct RomDescription { + unsigned long dwSignature; /* Unique 32bit value in ROM */ + unsigned short sSignatureAddr; /* Address of signature */ + unsigned short sStdRom; /* Indicates it this is a standard ROM */ + + Std_ROM_Table_t *pTables; /* Pointer to known tables */ + Std_ROM_Addresses_t *pVars; /* Pointer to known variables */ + Std_ROM_Addresses_t *pFuns; /* Pointer ot known functions */ + + unsigned short sFilePtrBA; /* Address of unsaved BASIC prgm */ + unsigned short sFilePtrDO; /* Address of next DO file */ + unsigned short sBeginDO; /* Start of DO file area */ + unsigned short sBeginCO; /* Start of CO file area */ + unsigned short sBeginVar; /* Start of Variable space */ + unsigned short sBeginArray; /* Start of Array data */ + unsigned short sUnusedMem; /* Pointer to unused memory */ + unsigned short sHimem; /* Address where HIMEM is stored */ + unsigned short sRamEnd; /* End of RAM for file storage */ + unsigned short sLowRam; /* Lowest RAM used by system */ + unsigned short sDirectory; /* Start of RAM directory */ + unsigned short sBasicStrings; /* BASIC string buffer pointer */ + + unsigned short sDirCount; /* Number of entries in Directory */ +} RomDescription_t; + +enum { + TABLE_TYPE_STRING, + TABLE_TYPE_JUMP, + TABLE_TYPE_CODE, + TABLE_TYPE_MODIFIED_STRING, + TABLE_TYPE_2BYTE, + TABLE_TYPE_3BYTE, + TABLE_TYPE_CTRL_DELIM, + TABLE_TYPE_BYTE_LOOKUP, + TABLE_TYPE_4BYTE_CMD, + TABLE_TYPE_CATALOG +}; + +#endif \ No newline at end of file From 2dda3dd4d81f51018c491cf5fa0e4d201dd09b45 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 31 Aug 2004 15:30:28 +0000 Subject: [PATCH 016/327] Added files for file load / save and made changes to --- Makefile | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 430b149..5c3b3f5 100644 --- a/Makefile +++ b/Makefile @@ -1,20 +1,18 @@ #CFLAGS := -O6 -march=pentium -mcpu=pentium #CFLAGS := -O -pg -#LDFLAGS := -pg -#CFLAGS := -O2 -g -CFLAGS += -O6 +CFLAGS := -O -g -FLTKCONFIG ?= fltk-config -CFLAGS += `$(FLTKCONFIG) --cflags --use-images` -LDFLAGS += `$(FLTKCONFIG) --ldstaticflags --use-images` +CFLAGS += -I/usr/local/include +LDFLAGS += -L/usr/local/lib -L/usr/X11R6/lib +LIBS += -lfltk -lXext -lX11 -lm -m100emu: doins.o io.o genwrap.o display.o m100emu.o disassemble.o Makefile - gcc -o m100emu doins.o genwrap.o io.o display.o m100emu.o disassemble.o $(LDFLAGS) +m100emu: doins.o genwrap.o io.o display.o m100emu.o file.o memory.o m100rom.o intelhex.o Makefile + gcc $(LDFLAGS) -o m100emu doins.o genwrap.o io.o display.o m100emu.o $(LIBS) m100emu.o: m100emu.c cpu.h doins.h display.h genwrap.h do_instruct.h Makefile gcc $(CFLAGS) -c m100emu.c -o m100emu.o -doins.o: doins.c doins.h cpu.h io.h m100emu.h Makefile +doins.o: doins.c doins.h cpu.h io.h m100emu.h do_instruct.h Makefile gcc $(CFLAGS) -c doins.c -o doins.o genwrap.o: genwrap.c genwrap.h gen_defs.h Makefile @@ -23,11 +21,21 @@ genwrap.o: genwrap.c genwrap.h gen_defs.h Makefile io.o: cpu.h gen_defs.h io.h io.c Makefile gcc $(CFLAGS) -c io.c -o io.o -display.o: display.cpp display.h io.h m100emu.h Makefile - g++ $(CFLAGS) -c display.cpp -o display.o +display.o: display.cpp display.h Makefile + gcc $(CFLAGS) -c display.cpp -o display.o + +file.o: file.cpp memory.h roms.h intelhex.h m100emu.h Makefile + gcc $(CFLAGS) -c file.cpp -o file.o + +memory.o: memory.c genwrap.h Makefile + gcc $(CFLAGS) -c memory.c -o memory.o + +m100rom.o: m100rom.c roms.h Makefile + gcc $(CFLAGS) -c m100rom.c -o m100rom.o + +intelhex.o: intelhex.c intelhex.h Makefile + gcc $(CFLAGS) -c intelhex.c -o intelhex.o -disassemble.o: disassemble.cpp m100emu.h disassemble.h m100rom.h io.h Makefile - g++ $(CFLAGS) -c disassemble.cpp -o disassemble.o clean: rm *.o From d3f69e6df7ba487f6840c1b48ecdfdfca7a93daf Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 31 Aug 2004 15:31:06 +0000 Subject: [PATCH 017/327] Added support for disassemble.cpp --- Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 5c3b3f5..ab08e68 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ CFLAGS += -I/usr/local/include LDFLAGS += -L/usr/local/lib -L/usr/X11R6/lib LIBS += -lfltk -lXext -lX11 -lm -m100emu: doins.o genwrap.o io.o display.o m100emu.o file.o memory.o m100rom.o intelhex.o Makefile +m100emu: doins.o genwrap.o io.o display.o m100emu.o file.o memory.o m100rom.o intelhex.o disassemble.o Makefile gcc $(LDFLAGS) -o m100emu doins.o genwrap.o io.o display.o m100emu.o $(LIBS) m100emu.o: m100emu.c cpu.h doins.h display.h genwrap.h do_instruct.h Makefile @@ -34,7 +34,10 @@ m100rom.o: m100rom.c roms.h Makefile gcc $(CFLAGS) -c m100rom.c -o m100rom.o intelhex.o: intelhex.c intelhex.h Makefile - gcc $(CFLAGS) -c intelhex.c -o intelhex.o + gcc $(CFLAGS) -c intelhex.c -o intelhex.o + +disassemble.o: disassemble.cpp m100emu.h disassemble.h io.h Makefile + gcc $(CFLAGS) -c disassemble.c -o disassemble.o clean: From 3f1fb601a3a1e63404b5519fab92975d82442b3a Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 31 Aug 2004 15:35:22 +0000 Subject: [PATCH 018/327] Visual C++ 6.0 project/workspace file. --- VirtualT.dsp | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++ VirtualT.dsw | 29 ++++++++ 2 files changed, 226 insertions(+) create mode 100644 VirtualT.dsp create mode 100644 VirtualT.dsw diff --git a/VirtualT.dsp b/VirtualT.dsp new file mode 100644 index 0000000..ea62d4e --- /dev/null +++ b/VirtualT.dsp @@ -0,0 +1,197 @@ +# Microsoft Developer Studio Project File - Name="VirtualT" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=VirtualT - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "VirtualT.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "VirtualT.mak" CFG="VirtualT - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "VirtualT - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "VirtualT - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "VirtualT - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 fltk.lib wsock32.lib comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib:"libc" /libpath:"..\lib" +# SUBTRACT LINK32 /pdb:none /incremental:yes /nodefaultlib + +!ELSEIF "$(CFG)" == "VirtualT - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 fltkd.lib wsock32.lib comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /pdbtype:sept /libpath:"..\lib" +# SUBTRACT LINK32 /pdb:none /incremental:no + +!ENDIF + +# Begin Target + +# Name "VirtualT - Win32 Release" +# Name "VirtualT - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\disassemble.cpp +# End Source File +# Begin Source File + +SOURCE=display.cpp +# End Source File +# Begin Source File + +SOURCE=doins.c +# End Source File +# Begin Source File + +SOURCE=.\file.cpp +# End Source File +# Begin Source File + +SOURCE=genwrap.c +# End Source File +# Begin Source File + +SOURCE=.\intelhex.c +# End Source File +# Begin Source File + +SOURCE=io.c +# End Source File +# Begin Source File + +SOURCE=m100emu.c +# End Source File +# Begin Source File + +SOURCE=.\m100rom.c +# End Source File +# Begin Source File + +SOURCE=.\memory.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=cpu.h +# End Source File +# Begin Source File + +SOURCE=.\disassemble.h +# End Source File +# Begin Source File + +SOURCE=display.h +# End Source File +# Begin Source File + +SOURCE=do_instruct.h +# End Source File +# Begin Source File + +SOURCE=doins.h +# End Source File +# Begin Source File + +SOURCE=gen_defs.h +# End Source File +# Begin Source File + +SOURCE=genwrap.h +# End Source File +# Begin Source File + +SOURCE=.\intelhex.h +# End Source File +# Begin Source File + +SOURCE=io.h +# End Source File +# Begin Source File + +SOURCE=m100emu.h +# End Source File +# Begin Source File + +SOURCE=.\memory.h +# End Source File +# Begin Source File + +SOURCE=.\roms.h +# End Source File +# Begin Source File + +SOURCE=wrapdll.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/VirtualT.dsw b/VirtualT.dsw new file mode 100644 index 0000000..e643330 --- /dev/null +++ b/VirtualT.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "VirtualT"=.\VirtualT.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + From 5ff4b40d15b2cfe655691da07d2ac71e41aa92ca Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 31 Aug 2004 15:41:13 +0000 Subject: [PATCH 019/327] Updated release version number to 0.2 --- src/VirtualT.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VirtualT.h b/src/VirtualT.h index ed06c9a..fac793a 100644 --- a/src/VirtualT.h +++ b/src/VirtualT.h @@ -31,6 +31,6 @@ #ifndef _VIRTUALT_H_ #define _VIRTUALT_H_ -#define VERSION "0.1" +#define VERSION "0.2" #endif From 7722b7d2ab196b0ac9e2afd662bb24f8de98ef3a Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 1 Sep 2004 17:30:48 +0000 Subject: [PATCH 020/327] Added file.c, intelhex.c, m100rom.c and memory.c to the build. --- GNUmakefile | 16 ++++++++++++++-- Makefile | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 657a9a2..9ad8d15 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -6,8 +6,8 @@ FLTKCONFIG ?= fltk-config CFLAGS += `$(FLTKCONFIG) --cflags --use-images` LDFLAGS += `$(FLTKCONFIG) --ldstaticflags --use-images` -m100emu: doins.o io.o genwrap.o display.o m100emu.o disassemble.o GNUmakefile - gcc -o m100emu doins.o genwrap.o io.o display.o m100emu.o disassemble.o $(LDFLAGS) +m100emu: doins.o io.o genwrap.o display.o m100emu.o disassemble.o file.o memory.o m100rom.o intelhex.o GNUmakefile + gcc -o m100emu doins.o genwrap.o io.o display.o m100emu.o disassemble.o file.o memory.o m100rom.o intelhex.o $(LDFLAGS) m100emu.o: m100emu.c cpu.h doins.h display.h genwrap.h do_instruct.h GNUmakefile gcc $(CFLAGS) -c m100emu.c -o m100emu.o @@ -27,6 +27,18 @@ display.o: display.cpp display.h io.h m100emu.h GNUmakefile disassemble.o: disassemble.cpp m100emu.h disassemble.h m100rom.h io.h GNUmakefile g++ $(CFLAGS) -c disassemble.cpp -o disassemble.o +file.o: file.cpp memory.h roms.h intelhex.h m100emu.h GNUmakefile + gcc $(CFLAGS) -c file.cpp -o file.o + +memory.o: memory.c genwrap.h GNUmakefile + gcc $(CFLAGS) -c memory.c -o memory.o + +m100rom.o: m100rom.c roms.h GNUmakefile + gcc $(CFLAGS) -c m100rom.c -o m100rom.o + +intelhex.o: intelhex.c intelhex.h GNUmakefile + gcc $(CFLAGS) -c intelhex.c -o intelhex.o + clean: rm *.o rm m100emu diff --git a/Makefile b/Makefile index ab08e68..234f1dc 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ LDFLAGS += -L/usr/local/lib -L/usr/X11R6/lib LIBS += -lfltk -lXext -lX11 -lm m100emu: doins.o genwrap.o io.o display.o m100emu.o file.o memory.o m100rom.o intelhex.o disassemble.o Makefile - gcc $(LDFLAGS) -o m100emu doins.o genwrap.o io.o display.o m100emu.o $(LIBS) + gcc $(LDFLAGS) -o m100emu doins.o genwrap.o io.o display.o m100emu.o file.o memory.o m100rom.o intelhex.o disassemble.o $(LIBS) m100emu.o: m100emu.c cpu.h doins.h display.h genwrap.h do_instruct.h Makefile gcc $(CFLAGS) -c m100emu.c -o m100emu.o From bdd8f26a4ca7a65587051ae461005bf3b6f04858 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Mon, 6 Sep 2004 19:39:31 +0000 Subject: [PATCH 021/327] *nix compatability stuff... include ctype.h, fix up Makefile (for non-gmake builds) --- Makefile | 43 +++++++++++++++++++++---------------------- src/file.cpp | 13 +++++++------ 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Makefile b/Makefile index 234f1dc..b64b772 100644 --- a/Makefile +++ b/Makefile @@ -1,45 +1,44 @@ -#CFLAGS := -O6 -march=pentium -mcpu=pentium -#CFLAGS := -O -pg -CFLAGS := -O -g +#-include $(shell uname).mk +CFLAGS += -O6 +#CFLAGS += -g -CFLAGS += -I/usr/local/include -LDFLAGS += -L/usr/local/lib -L/usr/X11R6/lib -LIBS += -lfltk -lXext -lX11 -lm +FLTKCONFIG ?= fltk-config +CFLAGS += `$(FLTKCONFIG) --cflags --use-images` +LDFLAGS += `$(FLTKCONFIG) --ldstaticflags --use-images` -m100emu: doins.o genwrap.o io.o display.o m100emu.o file.o memory.o m100rom.o intelhex.o disassemble.o Makefile - gcc $(LDFLAGS) -o m100emu doins.o genwrap.o io.o display.o m100emu.o file.o memory.o m100rom.o intelhex.o disassemble.o $(LIBS) +m100emu: doins.o io.o genwrap.o display.o m100emu.o disassemble.o file.o memory.o m100rom.o intelhex.o GNUmakefile + gcc -o m100emu doins.o genwrap.o io.o display.o m100emu.o disassemble.o file.o memory.o m100rom.o intelhex.o $(LDFLAGS) -m100emu.o: m100emu.c cpu.h doins.h display.h genwrap.h do_instruct.h Makefile +m100emu.o: m100emu.c cpu.h doins.h display.h genwrap.h do_instruct.h GNUmakefile gcc $(CFLAGS) -c m100emu.c -o m100emu.o -doins.o: doins.c doins.h cpu.h io.h m100emu.h do_instruct.h Makefile +doins.o: doins.c doins.h cpu.h io.h m100emu.h GNUmakefile gcc $(CFLAGS) -c doins.c -o doins.o -genwrap.o: genwrap.c genwrap.h gen_defs.h Makefile +genwrap.o: genwrap.c genwrap.h gen_defs.h GNUmakefile gcc $(CFLAGS) -c genwrap.c -o genwrap.o -io.o: cpu.h gen_defs.h io.h io.c Makefile +io.o: cpu.h gen_defs.h io.h io.c GNUmakefile gcc $(CFLAGS) -c io.c -o io.o -display.o: display.cpp display.h Makefile - gcc $(CFLAGS) -c display.cpp -o display.o +display.o: display.cpp display.h io.h m100emu.h GNUmakefile + g++ $(CFLAGS) -c display.cpp -o display.o -file.o: file.cpp memory.h roms.h intelhex.h m100emu.h Makefile +disassemble.o: disassemble.cpp m100emu.h disassemble.h m100rom.h io.h GNUmakefile + g++ $(CFLAGS) -c disassemble.cpp -o disassemble.o + +file.o: file.cpp memory.h roms.h intelhex.h m100emu.h GNUmakefile gcc $(CFLAGS) -c file.cpp -o file.o -memory.o: memory.c genwrap.h Makefile +memory.o: memory.c genwrap.h GNUmakefile gcc $(CFLAGS) -c memory.c -o memory.o -m100rom.o: m100rom.c roms.h Makefile +m100rom.o: m100rom.c roms.h GNUmakefile gcc $(CFLAGS) -c m100rom.c -o m100rom.o -intelhex.o: intelhex.c intelhex.h Makefile +intelhex.o: intelhex.c intelhex.h GNUmakefile gcc $(CFLAGS) -c intelhex.c -o intelhex.o -disassemble.o: disassemble.cpp m100emu.h disassemble.h io.h Makefile - gcc $(CFLAGS) -c disassemble.c -o disassemble.o - - clean: rm *.o rm m100emu diff --git a/src/file.cpp b/src/file.cpp index 56485a5..35857e4 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -28,19 +28,20 @@ */ -#include -#include -#include -#include -#include - #include +#include #include #ifdef _WIN32 #include #endif +#include +#include +#include +#include +#include + extern "C" { #include "memory.h" From 0285125349a01b3d198a635a0a3d639c41e08d29 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 14 Sep 2004 18:27:41 +0000 Subject: [PATCH 022/327] Added support to display for Peripheral Devices window. --- src/disassemble.cpp | 3 ++- src/disassemble.h | 1 + src/display.cpp | 62 +++++++++++++++++++++++++++++++++++---------- src/display.h | 1 + 4 files changed, 52 insertions(+), 15 deletions(-) diff --git a/src/disassemble.cpp b/src/disassemble.cpp index 1e3a9d7..7dad3cf 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -42,6 +42,7 @@ #include "m100emu.h" #include "disassemble.h" #include "io.h" +#include "periph.h" Fl_Window *gpDis; @@ -143,7 +144,7 @@ Fl_Menu_Item gDis_menuitems[] = { { "Disassembler", 0, 0 }, { "Debugger", 0, 0 }, { "Memory Editor", 0, 0 }, - { "Peripheral Devices", 0, 0 }, + { "Peripheral Devices", 0, cb_PeripheralDevices }, { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, 0 }, { "BASIC Debugger", 0, 0 }, diff --git a/src/disassemble.h b/src/disassemble.h index ecfc79c..0512c9e 100644 --- a/src/disassemble.h +++ b/src/disassemble.h @@ -33,6 +33,7 @@ #include "display.h" +void disassembler_cb(Fl_Widget* w, void*); class VTDis { diff --git a/src/display.cpp b/src/display.cpp index 74c9cad..a264253 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -51,13 +51,16 @@ #include "m100emu.h" #include "io.h" #include "file.h" +#include "setup.h" +#include "periph.h" -Fl_Window *MainWin; +Fl_Window *MainWin = NULL; T100_Disp *gpDisp; Fl_Box *gpCode, *gpGraph, *gpKey, *gpSpeed, *gpCaps, *gpKeyInfo; Fl_Menu_Bar *Menu; Fl_Preferences virtualt_prefs(Fl_Preferences::USER, "virtualt.", "virtualt" ); char gsMenuROM[40]; +char gDelayedError[128] = {0}; int MultFact = 3; int DisplayMode = 1; @@ -117,6 +120,7 @@ void rspeed(Fl_Widget* w, void*) { fullspeed=0; virtualt_prefs.set("fullspeed",0); + } void fspeed(Fl_Widget* w, void*) { @@ -124,6 +128,7 @@ void fspeed(Fl_Widget* w, void*) virtualt_prefs.set("fullspeed",1); } + void close_disp_cb(Fl_Widget* w, void*) { if (gpDisp != NULL) @@ -156,6 +161,27 @@ void resize_window() MainWin->redraw(); } +/* use this Function to display a pop up box */ + +void show_error (const char *st) +{ + // Check if MainWin created yet. If not, delay the error + if (MainWin == NULL) + { + strcpy(gDelayedError, st); + return; + } + + fl_alert(st); + +} + +void show_message (const char *st) +{ + fl_message(st); + +} + /* ======================================================= Menu Item Callbacks @@ -237,6 +263,7 @@ void cb_UnloadOptRom (Fl_Widget* w, void*) void cb_help (Fl_Widget* w, void*) { +/* #ifndef WIN32 Fl_Help_Dialog *HelpWin; @@ -244,6 +271,8 @@ void cb_help (Fl_Widget* w, void*) HelpWin->load("./help.htm"); HelpWin->show(); #endif +*/ + } void cb_about (Fl_Widget* w, void*) @@ -271,7 +300,7 @@ void cb_about (Fl_Widget* w, void*) o->labelfont(8); o->labelsize(18); } - { Fl_Box* o = new Fl_Box(15, 210, 340, 35, "Jerome Vernet"); + { Fl_Box* o = new Fl_Box(15, 210, 340, 35, "Jerome Vernet (Mac OsX Port)"); o->labelfont(8); o->labelsize(18); } @@ -310,7 +339,7 @@ T100_Disp::T100_Disp(int x, int y, int w, int h) : } // Draw the black pixels on the LCD -void drawpixel(int x, int y, int color) +__inline void drawpixel(int x, int y, int color) { if (color) fl_rectf(x*MultFact + gXoffset,y*MultFact + gYoffset,gRectsize,gRectsize); @@ -426,7 +455,7 @@ void T100_Disp::draw() // Erase line so it is grey, then fill in with black where needed fl_color(FL_GRAY); - fl_rectf(x*MultFact + gXoffset,y*MultFact + + fl_rectf(x*MultFact + gXoffset,y*MultFact + gYoffset,gRectsize,8*MultFact); fl_color(FL_BLACK); @@ -474,8 +503,8 @@ void T100_Disp::SetByte(int driver, int col, uchar value) gpDisp->window()->make_current(); fl_color(FL_GRAY); - fl_rectf(x*MultFact + gXoffset,y*MultFact + - gYoffset,gRectsize,MultFact<<3); + fl_rectf(x*MultFact + gXoffset, y*MultFact + + gYoffset, gRectsize,MultFact<<3); fl_color(FL_BLACK); // Draw each pixel of byte @@ -526,7 +555,7 @@ Fl_Menu_Item menuitems[] = { { "Framed", 0, cb_framed, (void *) 1, FL_MENU_TOGGLE|FL_MENU_VALUE }, { "Solid Chars", 0, cb_solidchars, (void *) 1, FL_MENU_TOGGLE}, { 0 }, - { "Peripheral Setup...", 0, 0, 0, FL_MENU_DIVIDER }, + { "Peripheral Setup...", 0, cb_PeripheralSetup, 0, FL_MENU_DIVIDER }, { "Option ROM", 0, 0, 0, FL_SUBMENU }, { gsMenuROM, 0, 0, 0, FL_MENU_DIVIDER }, { "Load ROM...", 0, cb_LoadOptRom, 0, 0 }, @@ -540,7 +569,7 @@ Fl_Menu_Item menuitems[] = { { "Disassembler", 0, disassembler_cb }, { "Debugger", 0, 0 }, { "Memory Editor", 0, 0 }, - { "Peripheral Devices", 0, 0 }, + { "Peripheral Devices", 0, cb_PeripheralDevices }, { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, 0 }, { "BASIC Debugger", 0, 0 }, @@ -691,8 +720,11 @@ void initdisplay(void) MainWin->show(); - Fl::wait(); + //Fl::wait(); + Fl::check(); + if (strlen(gDelayedError) != 0) + fl_alert(gDelayedError); } @@ -701,7 +733,7 @@ char label[40]; void display_cpu_speed(void) { - sprintf(label, "%4.1f Mhz", cpu_speed); + sprintf(label, "%4.1f Mhz", cpu_speed + .05); Fl::check(); gpSpeed->label(label); } @@ -722,8 +754,8 @@ void power_down() void process_windows_event() { - Fl::wait(0); - + //Fl::wait(0); + Fl::check(); return; } @@ -737,8 +769,9 @@ void T100_Disp::PowerDown() else fl_rectf(x(),y(),w(),h()); - Fl::wait(0); - + //Fl::wait(0); + Fl::check(); + // Print power down message char *msg = "System Powered Down"; char *msg2 = "Press any key to reset"; @@ -1235,3 +1268,4 @@ int T100_Disp::handle(int event) + diff --git a/src/display.h b/src/display.h index 10f01de..f3586af 100644 --- a/src/display.h +++ b/src/display.h @@ -43,6 +43,7 @@ void drawbyte(int driver, int column, int value); void power_down(); void process_windows_event(); void display_cpu_speed(void); +void show_error(const char*); #ifdef __cplusplus From 7c20f6e2464c06634a02deb2bfe30876c7c705c0 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 14 Sep 2004 18:28:40 +0000 Subject: [PATCH 023/327] Modified file read method to binary to support OSX. --- src/intelhex.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/intelhex.c b/src/intelhex.c index a58498d..a9b3183 100644 --- a/src/intelhex.c +++ b/src/intelhex.c @@ -106,7 +106,7 @@ int load_hex_file(char *filename, char *buffer, unsigned short *start_addr) int minaddr=65536, maxaddr=0; char mem[65536]; - fin = fopen(filename, "r"); + fin = fopen(filename, "rb"); if (fin == NULL) { return 0; } @@ -116,19 +116,23 @@ int load_hex_file(char *filename, char *buffer, unsigned short *start_addr) while (!feof(fin)) { line[i] = fgetc(fin); + // Check for CR/LF if ((line[i] == 0x0d) || line[i] == 0x0a) { if (i != 0) break;; } + // Check for end of file marker + else if (line[i] == 0x1a) + break; else if (line[i] != -1) i++; } if (i == 0) break; line[i] = 0; - if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0'; - if (line[strlen(line)-1] == '\r') line[strlen(line)-1] = '\0'; + if (line[strlen(line)-1] == 0x0a) line[strlen(line)-1] = '\0'; + if (line[strlen(line)-1] == 0x0d) line[strlen(line)-1] = '\0'; if (parse_hex_line(line, bytes, &addr, &n, &status)) { if (status == 0) { /* data */ for(i=0; i<=(n-1); i++) { From aab4f3038885e152b6582ad237b9a9f1f59a568c Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 14 Sep 2004 18:29:04 +0000 Subject: [PATCH 024/327] Added support for COM port emulation. --- src/io.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/io.h | 1 + 2 files changed, 97 insertions(+), 4 deletions(-) diff --git a/src/io.c b/src/io.c index bcecf92..227f495 100644 --- a/src/io.c +++ b/src/io.c @@ -29,10 +29,15 @@ #include +#include + #include "cpu.h" #include "gen_defs.h" #include "io.h" -#include +#include "serial.h" +#include "display.h" +#include "setup.h" +#include "m100emu.h" uchar lcd[10][256]; uchar lcdpointers[10]={0,0,0,0,0,0,0,0,0,0}; @@ -41,6 +46,9 @@ uchar lcd_fresh_ptr[10] = {1,1,1,1,1,1,1,1,1,1 }; uchar ioBA; uchar ioB9; uchar ioE8; +uchar ioBC; /* Low byte of 14-bit timer */ +uchar ioBD; /* High byte of 14-bit timer */ + uchar keyscan[9] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; @@ -128,16 +136,31 @@ void update_keys(void) keyscan[8] = (unsigned char) (gSpecialKeys & 0xFF); } + void init_io(void) { int c; + // Initialize special keys variable gSpecialKeys = 0xFFFFFFFF; for (c = 0; c < 128; c++) gKeyStates[c] = 0; + // Initialize keyscan variables update_keys(); + + // Initialize serial I/O structures + ser_init(); + + // Setup callback for serial I/O + ser_set_callback(cb_int65); +} + +void deinit_io(void) +{ + // Deinitialize the serial port + ser_deinit(); } @@ -146,6 +169,8 @@ int cROM = 0; void out(uchar port, uchar val) { int c; + unsigned char flags; + static int clk_cnt = 20; switch(port) { case 0xA0: /* Modem control port */ @@ -216,7 +241,6 @@ void out(uchar port, uchar val) 5 - Data to beeper if bit 2 set. Set if bit 2 low. 6 - DTR (not) line for RS232 7 - RTS (not) line for RS232 */ - ioBA = A; lcdbits = (lcdbits & 0x00FF) | ((A & 0x03) << 8); /* Check if software "turned the simulator off" */ @@ -224,6 +248,24 @@ void out(uchar port, uchar val) { power_down(); } + + // Update COM settings + if ((val & 0xC8) != (ioBA & 0xC8)) + { + if ((val & 0x08) == 1) + c = 0; + else + { + flags = 0; + if ((val & 0x40) == 0) + flags |= SER_SIGNAL_DTR; + if ((val & 0x80) == 0) + flags |= SER_SIGNAL_RTS; + } + ser_set_signals(flags); + } + + ioBA = A; return; case 0xB3: /* 8155 PIO Port C */ @@ -232,10 +274,16 @@ void out(uchar port, uchar val) case 0xB4: /* 8155 Timer register. LSB of timer counter */ case 0xBC: + ioBC = val; return; case 0xB5: /* 8155 Timer register. MSB of timer counter */ case 0xBD: + ioBD = val; + c = (((int) (ioBD & 0x3F) << 8) | (ioBC)); + if (c != 0) + c = 153600 / c; + ser_set_baud(c); return; case 0xC0: /* Bidirectional data bus for UART (6402) (C0H-CFH same) */ @@ -254,6 +302,7 @@ void out(uchar port, uchar val) case 0xCD: case 0xCE: case 0xCF: + ser_write_byte(val); return; case 0xD0: /* Status control register for UART, modem, and phone (6402) */ @@ -280,6 +329,24 @@ void out(uchar port, uchar val) 3 - Data length (00-5 bits, 10-6 bits, 01-7 bits, 11-8 bits) 4 - Data length (see bit 3) */ + + if ((ioBA & 0x08) == 0) + { + // Set stop bits + c = val & 0x01 ? 2 : 1; + ser_set_stop_bits(c); + + // Set Parity + if (val & 0x04) + c = 'N'; + else + c = val & 0x02 ? 'E' : 'O'; + ser_set_parity((char) c); + + // Set bit size + c = ((val & 0x18) >> 3) + 5; + ser_set_bit_size(c); + } return; case 0xE0: /* Keyboard input and misc. device select (E0H-EFH same) */ @@ -331,6 +398,11 @@ void out(uchar port, uchar val) clock_sr_index = 0; break; case 3: /* Read clock chip */ + if (--clk_cnt > 0) + break; + + clk_cnt = 20; + clock_time = time(&clock_time); if (clock_time == last_clock_time) break; @@ -434,6 +506,7 @@ int inport(uchar port) { int c; unsigned char ret; + unsigned char flags; switch(port) { case 0x82: /* Optional IO thinger? */ @@ -477,7 +550,10 @@ int inport(uchar port) 4 - CTS (not) line from RS232 5 - DSR (not) line from RS232 6-7 - Not avaiable on 8155 */ - return(clock_serial_out); + if (setup.com_mode != SETUP_COM_NONE) + ser_get_flags(&flags); + flags &= SER_FLAG_CTS | SER_FLAG_DSR; + return(clock_serial_out | (flags>>8)); case 0xB4: /* 8155 Timer register. LSB of timer counter */ case 0xBC: @@ -503,7 +579,8 @@ int inport(uchar port) case 0xCD: case 0xCE: case 0xCF: - return(0); + ser_read_byte(&ret); + return ret; case 0xD0: /* Status control register for UART, modem, and phone (6402) */ case 0xD1: @@ -531,6 +608,21 @@ int inport(uchar port) 5 - Ring line on modem connector 6 - Not used 7 - Low Power signal from power supply (LPS not) */ + + // Check if RS-232 is "Muxed in" + if ((ioBA & 0x08) == 0) + { + flags = 0; + if (setup.com_mode != SETUP_COM_NONE) + { + // Get flags from serial routines + ser_get_flags(&flags); + flags = (flags & (SER_FLAG_OVERRUN | SER_FLAG_FRAME_ERR | + SER_FLAG_PARITY_ERR)) | ((flags & SER_FLAG_TX_EMPTY) + << 4) | ((flags & SER_FLAG_RING) >> 1); + } + return flags | 0x80; + } return(0x90); case 0xE0: /* Keyboard input and misc. device select (E0H-EFH same) */ diff --git a/src/io.h b/src/io.h index ac3fbed..ab17a40 100644 --- a/src/io.h +++ b/src/io.h @@ -44,6 +44,7 @@ extern uchar ioBA; extern int gModel; void init_io(void); +void deinit_io(void); void out(uchar port, uchar val); void update_keys(void); int inport(uchar port); From d73293fb182b93b8c714398b5d2f47fdca0c64b4 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 14 Sep 2004 18:30:36 +0000 Subject: [PATCH 025/327] Added support for COM port emulation and added INT6.5 support. Made changes to the maint() function to provide better speed regulation. --- src/m100emu.c | 140 +++++++++++++++++++++++++++++++++++++++----------- src/m100emu.h | 2 + 2 files changed, 113 insertions(+), 29 deletions(-) diff --git a/src/m100emu.c b/src/m100emu.c index 1c08c2e..b56c065 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -38,6 +38,7 @@ #ifdef __unix__ #include +#include #endif #include "io.h" @@ -48,8 +49,9 @@ #include "filewrap.h" #include "roms.h" #include "intelhex.h" +#include "setup.h" -int fullspeed=0; +int fullspeed=0; uchar cpu[14]; uchar memory[65536]; @@ -58,7 +60,7 @@ uchar optROM[ROMSIZE]; char op[26]; UINT64 cycles=0; UINT64 instructs=0; -UINT64 last_isr_cycle=0; +static UINT64 last_isr_cycle=0; int trace=0; int starttime; FILE *tracefile; @@ -72,6 +74,10 @@ int gExitApp = 0; char gsOptRomFile[256]; DWORD last_one_sec_time; +//Added J. VERNET + +char path[255]; +char file[255]; extern RomDescription_t gM100_Desc; extern int cROM; @@ -82,11 +88,11 @@ RomDescription_t *gStdRomDesc; __inline double hirestimer(void) { static LARGE_INTEGER pcount, pcfreq; - static int initflag; + static int initflag = 0; if (!initflag) - { - QueryPerformanceFrequency(&pcfreq); + { + QueryPerformanceFrequency(&pcfreq); initflag++; } @@ -105,12 +111,15 @@ __inline double hirestimer(void) void cpu_delay(int cy) { static double last_instruct=0; + double hires; - if(last_instruct==0) - last_instruct=hirestimer(); if(!fullspeed) { + if(last_instruct==0) + last_instruct=hirestimer(); + last_instruct+=cy*0.000000416666666667; - while(hirestimer() 1) +// last_instruct = hires; } /* #define cpu_delay(x) cycles+=x; instructs++ */ @@ -193,7 +206,9 @@ void load_opt_rom(void) else { // Open BIN file - fd=open(gsOptRomFile,O_RDONLY); + strcpy(file,path); + strcat(file,gsOptRomFile); + fd=open(file,O_RDONLY); if(fd!=-1) { read(fd, optROM, ROMSIZE); @@ -206,6 +221,7 @@ void initcpu(void) { int fd; int i; + FILE *ram; A=0; @@ -221,12 +237,28 @@ void initcpu(void) PCL=0; IM=0x08; cpuMISC=0; - - fd=open("ROM.bin",O_RDONLY | O_BINARY); + + + //J. Vernet : Added to have an absolute path to the ROM.bin + + + strcpy(file,path); + strcat(file,"ROM.bin"); + + + fd=open(file,O_RDONLY | O_BINARY); if(fd<0) + { + show_error("Could not open ROM.bin"); bail("Could not open ROM.bin"); + } + if(read(fd, sysROM, ROMSIZE) last_hires + .05) +// if (systime != (time_t) one_sec_time) { + last_hires = hires; one_sec_cycle_count = (DWORD) (cycles - one_sec_cycles) / 100; one_sec_cycles = cycles; - if (systime != (time_t) one_sec_time) +// if (systime != (time_t) one_sec_time) { /* Update cycle counts only if 2 consecutive seconds - deals with menus */ - if (((time_t)one_sec_time+1 == systime) && ((time_t)last_one_sec_time+2 == systime)) +// if (((time_t)one_sec_time+1 == systime) && ((time_t)last_one_sec_time+2 == systime)) { - new_rst7cycles = (DWORD) (0.39998 * one_sec_cycle_count); /* 0.39998 = 9830 / 24576 */ + new_rst7cycles = (DWORD) (0.39998 * 20 * one_sec_cycle_count); /* 0.39998 = 9830 / 24576 */ if ((new_rst7cycles > (rst7cycles * 0.8)) || (twice_flag == 2)) { rst7cycles = new_rst7cycles; if (rst7cycles < 9830) rst7cycles = 9830; - cpu_speed = (float) (.000097656 * one_sec_cycle_count); /* 2.4 Mhz / 24576 */ - display_cpu_speed(); + time(&systime); + if (systime != (time_t) one_sec_time) + { + cpu_speed = (float) (.000097656 * 20 * one_sec_cycle_count); /* 2.4 Mhz / 24576 */ + display_cpu_speed(); + } twice_flag = 0; } else @@ -334,19 +402,20 @@ void emulate(void) starttime=msclock(); while(!gExitApp) { -#include "do_instruct.h" + #include "do_instruct.h" if(trace && tracefile != NULL) fprintf(tracefile, "%-22s A:%02X F:%02X B:%02X C:%02X D:%02X E:%02X H:%02X L:%02X PC:%04X SP:%04X IM:%02X *SP:%04X\n" ,op,A,F,B,C,D,E,H,L,PC,SP,IM,MEM16(SP)); nxtmaint--; if(!nxtmaint) { - check_interrupts(); maint(); + check_interrupts(); nxtmaint=128; + // 128; } } - fd=fopen("RAM.bin", "wb+"); + fd=fopen("./RAM.bin", "wb+"); if(fd!=0) { fwrite(memory+ROMSIZE, 1, RAMSIZE, fd); @@ -379,10 +448,23 @@ int main(int argc, char **argv) signal(SIGINT,handle_sig); #endif // Added by JV for prefs - initpref(); - initcpu(); - init_io(); - initdisplay(); - emulate(); + initpref(); // load user Menu preferences + load_setup_preferences(); // Load user Peripheral setup preferences + + #ifdef __unix__ + //J. VERNET: Get Absolute Path, as getcwd doesn't return anything when launch from finder + // Beware: if the name (currently m100emu) changes, it will not work + + strncpy(path,argv[0],strlen(argv[0])-7); + # else if + strcpy(path,"./"); + #endif + + initcpu(); // Initialize the CPU + init_io(); // Initialize I/O structures + initdisplay(); // Initialize the Display + emulate(); // Main emulation loop + + // Cleanup + deinit_io(); // Deinitialize I/O } - diff --git a/src/m100emu.h b/src/m100emu.h index 88191ba..4da3813 100644 --- a/src/m100emu.h +++ b/src/m100emu.h @@ -48,11 +48,13 @@ extern uchar memory[65536]; extern RomDescription_t *gStdRomDesc; extern int gModel; extern char gsOptRomFile[256]; +__inline double hirestimer(void); void cpu_delay(int cy); void resetcpu(void); void load_opt_rom(void); +void cb_int65(void); #ifdef __cplusplus } #endif From c944579f25b69d4ec300b2c2bfbdcba47a8cc8ee Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 14 Sep 2004 18:30:55 +0000 Subject: [PATCH 026/327] Updated to version 0.3. --- src/VirtualT.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VirtualT.h b/src/VirtualT.h index fac793a..3d48df2 100644 --- a/src/VirtualT.h +++ b/src/VirtualT.h @@ -31,6 +31,6 @@ #ifndef _VIRTUALT_H_ #define _VIRTUALT_H_ -#define VERSION "0.2" +#define VERSION "0.3" #endif From c193fafc4b491f6ec425f26c64f8895efd6d5a79 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 14 Sep 2004 18:31:26 +0000 Subject: [PATCH 027/327] Added the following files to the build: serial.c setup.cpp periph.cpp --- Makefile | 13 +++++++++++-- VirtualT.dsp | 28 ++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b64b772..78a2b9c 100644 --- a/Makefile +++ b/Makefile @@ -6,8 +6,8 @@ FLTKCONFIG ?= fltk-config CFLAGS += `$(FLTKCONFIG) --cflags --use-images` LDFLAGS += `$(FLTKCONFIG) --ldstaticflags --use-images` -m100emu: doins.o io.o genwrap.o display.o m100emu.o disassemble.o file.o memory.o m100rom.o intelhex.o GNUmakefile - gcc -o m100emu doins.o genwrap.o io.o display.o m100emu.o disassemble.o file.o memory.o m100rom.o intelhex.o $(LDFLAGS) +m100emu: doins.o io.o genwrap.o display.o m100emu.o disassemble.o file.o memory.o m100rom.o intelhex.o setup.o serial.o periph.o GNUmakefile + gcc -o m100emu doins.o genwrap.o io.o display.o m100emu.o disassemble.o file.o memory.o m100rom.o intelhex.o setup.o serial.o periph.o $(LDFLAGS) m100emu.o: m100emu.c cpu.h doins.h display.h genwrap.h do_instruct.h GNUmakefile gcc $(CFLAGS) -c m100emu.c -o m100emu.o @@ -39,6 +39,15 @@ m100rom.o: m100rom.c roms.h GNUmakefile intelhex.o: intelhex.c intelhex.h GNUmakefile gcc $(CFLAGS) -c intelhex.c -o intelhex.o +setup.o: setup.cpp setup.h m100emu.h io.h serial.h GNUmakefile + gcc $(CFLAGS) -c setup.cpp -o setup.o + +serial.o: serial.c serial.h setup.h display.h m100emu.h GNUmakefile + gcc $(CFLAGS) -c serial.c -o serial.o + +periph.o: periph.cpp periph.h serial.h setup.h display.h m100emu.h disassemble.h GNUmakefile + gcc $(CFLAGS) -c periph.cpp -o periph.o + clean: rm *.o rm m100emu diff --git a/VirtualT.dsp b/VirtualT.dsp index ea62d4e..efbe03e 100644 --- a/VirtualT.dsp +++ b/VirtualT.dsp @@ -132,6 +132,18 @@ SOURCE=.\m100rom.c SOURCE=.\memory.c # End Source File +# Begin Source File + +SOURCE=.\periph.cpp +# End Source File +# Begin Source File + +SOURCE=.\serial.c +# End Source File +# Begin Source File + +SOURCE=.\setup.cpp +# End Source File # End Group # Begin Group "Header Files" @@ -182,10 +194,26 @@ SOURCE=.\memory.h # End Source File # Begin Source File +SOURCE=.\periph.h +# End Source File +# Begin Source File + SOURCE=.\roms.h # End Source File # Begin Source File +SOURCE=.\serial.h +# End Source File +# Begin Source File + +SOURCE=.\setup.h +# End Source File +# Begin Source File + +SOURCE=.\VirtualT.h +# End Source File +# Begin Source File + SOURCE=wrapdll.h # End Source File # End Group From 1abbc1661ac0b14ab717c8cb3ab15b9aa5dc26dd Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 14 Sep 2004 18:33:18 +0000 Subject: [PATCH 028/327] Initial check to support COM port emulation including emulation setup, emulation control, and COM traffic monitoring. --- src/periph.cpp | 886 ++++++++++++++++++++++++++++++++ src/periph.h | 102 ++++ src/serial.c | 1308 ++++++++++++++++++++++++++++++++++++++++++++++++ src/serial.h | 154 ++++++ src/setup.cpp | 445 ++++++++++++++++ src/setup.h | 76 +++ 6 files changed, 2971 insertions(+) create mode 100644 src/periph.cpp create mode 100644 src/periph.h create mode 100644 src/serial.c create mode 100644 src/serial.h create mode 100644 src/setup.cpp create mode 100644 src/setup.h diff --git a/src/periph.cpp b/src/periph.cpp new file mode 100644 index 0000000..fc58d1e --- /dev/null +++ b/src/periph.cpp @@ -0,0 +1,886 @@ +/* periph.cpp */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if defined(WIN32) +#include +#endif +#include +#include +#include + +#include "serial.h" +#include "setup.h" +#include "display.h" +#include "m100emu.h" +#include "disassemble.h" +#include "periph.h" + + +typedef struct periph_ctrl_struct +{ + Fl_Menu_Bar* pMenu; + Fl_Tabs* pTabs; + + struct + { + Fl_Group* g; + Fl_Check_Button* pEnable; + Fl_Check_Button* pHex; + T100_ComMon* pLog; + Fl_Scrollbar* pScroll; + Fl_Button* pClear; + Fl_Choice* pFont; + Fl_Box* pPortName; + Fl_Box* pPortStatus; + Fl_Box* pBaud; + Fl_Box* pWordSize; + Fl_Box* pStopBits; + Fl_Box* pParity; + Fl_Box* pDTR; + Fl_Box* pRTS; + Fl_Box* pDSR; + Fl_Box* pCTS; + Fl_Box* pTXD; + Fl_Box* pRXD; + + char sPortName[128]; + char sBaud[10]; + char sPortStatus[40]; + char sWordSize[2]; + char sStopBits[2]; + char sParity[2]; + char sComMdm[10]; + unsigned char cSignal; + } com; + struct + { + Fl_Group* g; + Fl_Box* pText; + } lpt; + struct + { + Fl_Group* g; + Fl_Box* pText; + } mdm; + struct + { + Fl_Group* g; + Fl_Box* pText; + } cas; + struct + { + Fl_Group* g; + Fl_Box* pText; + } bcr; + struct + { + Fl_Group* g; + Fl_Box* pText; + } sound; +} periph_ctrl_t; + +// Menu items for the disassembler +Fl_Menu_Item gPeriph_menuitems[] = { + { "&Tools", 0, 0, 0, FL_SUBMENU }, + { "CPU Registers", 0, 0 }, + { "Assembler", 0, 0 }, + { "Disassembler", 0, disassembler_cb }, + { "Debugger", 0, 0 }, + { "Memory Editor", 0, 0 }, + { "Peripheral Devices", 0, 0 }, + { "Simulation Log Viewer", 0, 0 }, + { "Model T File Viewer", 0, 0 }, + { "BASIC Debugger", 0, 0 }, + { 0 }, + + { 0 } +}; + + +periph_ctrl_t periph_ctrl; +int gComEnableOn = 0; +int gHexOn = 0; +int gFontSize = 12; +Fl_Window *gpdw; + +/* +============================================================================ +Callback routine for the Peripherial Devices window +============================================================================ +*/ +void cb_peripheralwin (Fl_Widget* w, void*) +{ + gpdw->hide(); + ser_set_monitor_callback(NULL); + gComEnableOn = 0; + gHexOn = 0; + delete gpdw; + gpdw = NULL; +} + +/* +============================================================================ +Callback routine for the Com Clear Log button +============================================================================ +*/ +void cb_com_clear (Fl_Widget* w, void*) +{ + periph_ctrl.com.pScroll->maximum(2); + periph_ctrl.com.pScroll->slider_size(1); + periph_ctrl.com.pScroll->value(0, 2, 0, 2); + periph_ctrl.com.pLog->Clear(); +} + +/* +============================================================================ +Callback routine for the Com Font Size choice +============================================================================ +*/ +void cb_com_font_size (Fl_Widget* w, void*) +{ + int size = periph_ctrl.com.pFont->value(); + if (size == 0) + gFontSize = 12; + else if (size == 1) + gFontSize = 14; + else if (size == 2) + gFontSize = 16; + periph_ctrl.com.pLog->CalcLineStarts(); + periph_ctrl.com.pLog->redraw(); +} + +/* +============================================================================ +Callback routine for the Com Enable checkbox +============================================================================ +*/ +void cb_com_enable_box (Fl_Widget* w, void*) +{ + gComEnableOn = periph_ctrl.com.pEnable->value(); + periph_ctrl.com.pLog->redraw(); +} + + +/* +============================================================================ +Callback routine for the Com Enable checkbox +============================================================================ +*/ +void cb_com_hex_box (Fl_Widget* w, void*) +{ + gHexOn = periph_ctrl.com.pHex->value(); + periph_ctrl.com.pLog->CalcLineStarts(); + periph_ctrl.com.pLog->redraw(); +} + +/* +============================================================================ +Callback routine for the Com Scrollbar +============================================================================ +*/ +void cb_ComMonScroll (Fl_Widget* w, void*) +{ + periph_ctrl.com.pLog->m_FirstLine = ((Fl_Scrollbar*) w)->value(); + periph_ctrl.com.pLog->redraw(); +} + +/* +============================================================================ +Callback routine for receiving serial port status updates +============================================================================ +*/ +extern "C" +{ +void ser_com_monitor_cb(int fMonType, unsigned char data) +{ + int baud, size, stop, openState; + char parity; + + switch (fMonType) + { + case SER_MON_COM_PORT_CHANGE: + // Get new settings + ser_get_port_settings(periph_ctrl.com.sPortName, &openState, &baud, &size, + &stop, &parity); + + strcpy(periph_ctrl.com.sPortStatus, openState ? "Open" : "Closed"); + sprintf(periph_ctrl.com.sBaud, "%d", baud); + sprintf(periph_ctrl.com.sWordSize, "%d", size); + sprintf(periph_ctrl.com.sStopBits, "%d", stop); + periph_ctrl.com.sParity[0] = parity; + periph_ctrl.com.sParity[1] = 0; + periph_ctrl.com.sComMdm[0] = 0; + periph_ctrl.com.pBaud->hide(); + periph_ctrl.com.pBaud->show(); + break; + + case SER_MON_COM_SIGNAL: + ser_get_signals(&periph_ctrl.com.cSignal); + + // Update "LEDs" + if (periph_ctrl.com.cSignal & SER_SIGNAL_RTS) + periph_ctrl.com.pRTS->color(FL_YELLOW); + else + periph_ctrl.com.pRTS->color(FL_BLACK); + + if (periph_ctrl.com.cSignal & SER_SIGNAL_DTR) + periph_ctrl.com.pDTR->color(FL_YELLOW); + else + periph_ctrl.com.pDTR->color(FL_BLACK); + + if (periph_ctrl.com.cSignal & SER_SIGNAL_CTS) + periph_ctrl.com.pCTS->color(FL_YELLOW); + else + periph_ctrl.com.pCTS->color(FL_BLACK); + + if (periph_ctrl.com.cSignal & SER_SIGNAL_DSR) + periph_ctrl.com.pDSR->color(FL_YELLOW); + else + periph_ctrl.com.pDSR->color(FL_BLACK); + + periph_ctrl.com.pRTS->redraw(); + periph_ctrl.com.pDTR->redraw(); + periph_ctrl.com.pCTS->redraw(); + periph_ctrl.com.pDSR->redraw(); + break; + + case SER_MON_COM_READ: + if (gComEnableOn) + periph_ctrl.com.pLog->AddByte(0, data, periph_ctrl.com.cSignal); + break; + + case SER_MON_COM_WRITE: + if (gComEnableOn) + periph_ctrl.com.pLog->AddByte(1, data, periph_ctrl.com.cSignal); + break; + + } +} +} + +/* +============================================================================ +Routine to create the PeripheralSetup Window and tabs +============================================================================ +*/ +void update_com_port_settings() +{ + int baud, size, stop, openState; + char parity; + + ser_get_port_settings(periph_ctrl.com.sPortName, &openState, &baud, &size, + &stop, &parity); + + strcpy(periph_ctrl.com.sPortStatus, openState ? "Open" : "Closed"); + sprintf(periph_ctrl.com.sBaud, "%d", baud); + sprintf(periph_ctrl.com.sWordSize, "%d", size); + sprintf(periph_ctrl.com.sStopBits, "%d", stop); + periph_ctrl.com.sParity[0] = parity; + periph_ctrl.com.sParity[1] = 0; + periph_ctrl.com.sComMdm[0] = 0; +} + +/* +============================================================================ +Routine to create the PeripheralSetup Window and tabs +============================================================================ +*/ +void cb_PeripheralDevices (Fl_Widget* w, void*) +{ + Fl_Box* o; + + if (gpdw != NULL) + return; + + // Create Peripheral Setup window + gpdw = new Fl_Window(550, 400, "Peripheral Devices"); + gpdw->callback(cb_peripheralwin); + + // Create Peripheral Tabs + { + // Create a menu for the new window. + periph_ctrl.pMenu = new Fl_Menu_Bar(0, 0, 550, MENU_HEIGHT-2); + periph_ctrl.pMenu->menu(gPeriph_menuitems); + + periph_ctrl.pTabs = new Fl_Tabs(10, MENU_HEIGHT+10, 530, 380-MENU_HEIGHT); + + // COM port Tab + { + periph_ctrl.com.g = new Fl_Group(10, 30+MENU_HEIGHT, 540, 380-MENU_HEIGHT, " COM "); + + // Create static text boxes + o = new Fl_Box(FL_NO_BOX, 20, 45+MENU_HEIGHT, 50, 15, "Port Name:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 20, 70+MENU_HEIGHT, 50, 15, "Port Status:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 20, 95+MENU_HEIGHT, 50, 15, "Baud Rate:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 20, 120+MENU_HEIGHT, 50, 15, "Word Size:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + o = new Fl_Box(FL_NO_BOX, 200, 70+MENU_HEIGHT, 50, 15, "Stop Bits:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 200, 95+MENU_HEIGHT, 50, 15, "Parity:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + o = new Fl_Box(FL_NO_BOX, 450, 45+MENU_HEIGHT, 50, 15, "RTS:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 450, 70+MENU_HEIGHT, 50, 15, "DTR:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 450, 95+MENU_HEIGHT, 50, 15, "CTS:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 450, 120+MENU_HEIGHT, 50, 15, "DSR:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + periph_ctrl.com.pPortName = new Fl_Box(FL_NO_BOX, 100, + 45+MENU_HEIGHT, 400, 15, periph_ctrl.com.sPortName); + periph_ctrl.com.pPortName->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + periph_ctrl.com.pPortStatus = new Fl_Box(FL_NO_BOX, 100, + 70+MENU_HEIGHT, 50, 15, periph_ctrl.com.sPortStatus); + periph_ctrl.com.pPortStatus->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + periph_ctrl.com.pBaud = new Fl_Box(FL_NO_BOX, 100, + 95+MENU_HEIGHT, 50, 15, periph_ctrl.com.sBaud); + periph_ctrl.com.pBaud->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + periph_ctrl.com.pWordSize = new Fl_Box(FL_NO_BOX, 100, + 120+MENU_HEIGHT, 50, 15, periph_ctrl.com.sWordSize); + periph_ctrl.com.pWordSize->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + periph_ctrl.com.pStopBits = new Fl_Box(FL_NO_BOX, 280, + 70+MENU_HEIGHT, 50, 15, periph_ctrl.com.sStopBits); + periph_ctrl.com.pStopBits->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + periph_ctrl.com.pParity = new Fl_Box(FL_NO_BOX, 280, + 95+MENU_HEIGHT, 50, 15, periph_ctrl.com.sParity); + periph_ctrl.com.pParity->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + ser_get_signals(&periph_ctrl.com.cSignal); + + periph_ctrl.com.pRTS = new Fl_Box(FL_OVAL_BOX, 490, 47+MENU_HEIGHT, 12, 12, ""); + periph_ctrl.com.pRTS->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + if (periph_ctrl.com.cSignal & SER_SIGNAL_RTS) + periph_ctrl.com.pRTS->color(FL_YELLOW); + else + periph_ctrl.com.pRTS->color(FL_BLACK); + + periph_ctrl.com.pDTR = new Fl_Box(FL_OVAL_BOX, 490, 72+MENU_HEIGHT, 12, 12, ""); + periph_ctrl.com.pDTR->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + if (periph_ctrl.com.cSignal & SER_SIGNAL_DTR) + periph_ctrl.com.pDTR->color(FL_YELLOW); + else + periph_ctrl.com.pDTR->color(FL_BLACK); + + periph_ctrl.com.pCTS = new Fl_Box(FL_OVAL_BOX, 490, 97+MENU_HEIGHT, 12, 12, ""); + periph_ctrl.com.pCTS->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + if (periph_ctrl.com.cSignal & SER_SIGNAL_CTS) + periph_ctrl.com.pCTS->color(FL_YELLOW); + else + periph_ctrl.com.pCTS->color(FL_BLACK); + + periph_ctrl.com.pDSR = new Fl_Box(FL_OVAL_BOX, 490, 122+MENU_HEIGHT, 12, 12, ""); + periph_ctrl.com.pDSR->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + if (periph_ctrl.com.cSignal & SER_SIGNAL_DSR) + periph_ctrl.com.pDSR->color(FL_YELLOW); + else + periph_ctrl.com.pDSR->color(FL_BLACK); + + periph_ctrl.com.pLog = new T100_ComMon(20, 200, 495, 190-MENU_HEIGHT); +// periph_ctrl.com.pLog->color(FL_WHITE); + + periph_ctrl.com.pScroll = new Fl_Scrollbar(515, 200, 20, 190-MENU_HEIGHT, ""); + periph_ctrl.com.pScroll->type(FL_VERTICAL); + periph_ctrl.com.pScroll->linesize(2); + periph_ctrl.com.pScroll->maximum(2); + periph_ctrl.com.pScroll->callback(cb_ComMonScroll); + periph_ctrl.com.pScroll->slider_size(1); + + // Create items on the Tab + periph_ctrl.com.pEnable = new Fl_Check_Button(20, 362, 130, 20, "Enable Capture"); + periph_ctrl.com.pEnable->callback(cb_com_enable_box); + + // Create items on the Tab + periph_ctrl.com.pHex = new Fl_Check_Button(160, 362, 50, 20, "HEX"); + periph_ctrl.com.pHex->callback(cb_com_hex_box); + + // Create items on the Tab + periph_ctrl.com.pClear = new Fl_Button(330, 360, 80, 25, "Clear Log"); + periph_ctrl.com.pClear->callback(cb_com_clear); + + periph_ctrl.com.pFont = new Fl_Choice(250, 362, 60, 20, "Size"); + periph_ctrl.com.pFont->callback(cb_com_font_size); + periph_ctrl.com.pFont->add("12"); + periph_ctrl.com.pFont->add("14"); + periph_ctrl.com.pFont->add("16"); + periph_ctrl.com.pFont->value(0); + + periph_ctrl.com.g->end(); + + update_com_port_settings(); + + } + + // LPT Port Tab + { + // Create the Group item (the "Tab") + periph_ctrl.lpt.g = new Fl_Group(10, MENU_HEIGHT+30, 500, 380-MENU_HEIGHT, " LPT "); + + // Create controls + periph_ctrl.lpt.pText = new Fl_Box(120, MENU_HEIGHT+60, 60, 80, "Parallel Port not supported yet"); + + // End of control for this tab + periph_ctrl.lpt.g->end(); + } + + // Modem Port Tab + { + // Create the Group item (the "Tab") + periph_ctrl.mdm.g = new Fl_Group(10, MENU_HEIGHT+30, 500, 380-MENU_HEIGHT, " MDM "); + + // Create controls + periph_ctrl.mdm.pText = new Fl_Box(120, MENU_HEIGHT+60, 60, 80, "Modem Port not supported yet"); + + // End of control for this tab + periph_ctrl.mdm.g->end(); + } + + // Cassette Port Tab + { + // Create the Group item (the "Tab") + periph_ctrl.cas.g = new Fl_Group(10, MENU_HEIGHT+30, 500, 380-MENU_HEIGHT, " CAS "); + + // Create controls + periph_ctrl.cas.pText = new Fl_Box(120, MENU_HEIGHT+60, 60, 80, "Cassette Port not supported yet"); + + // End of control for this tab + periph_ctrl.cas.g->end(); + } + + // BCR Port Tab + { + // Create the Group item (the "Tab") + periph_ctrl.bcr.g = new Fl_Group(10, MENU_HEIGHT+30, 500, 380-MENU_HEIGHT, " BCR "); + + // Create controls + periph_ctrl.bcr.pText = new Fl_Box(120, MENU_HEIGHT+60, 60, 80, "BCR Port not supported yet"); + + // End of control for this tab + periph_ctrl.bcr.g->end(); + } + + + periph_ctrl.pTabs->value(periph_ctrl.com.g); + periph_ctrl.pTabs->end(); + + } + + // Make things resizeable + gpdw->resizable(periph_ctrl.pMenu); + gpdw->resizable(periph_ctrl.pTabs); + + // Set COM callback + ser_set_monitor_callback(ser_com_monitor_cb); + + gpdw->show(); +} + +T100_ComMon::T100_ComMon(int x, int y, int w, int h) : + Fl_Widget(x, y, w, h) +{ + // Create first TcomLogBlock + m_log = new TcomLogBlock(); + m_MyFocus = 0; + m_FirstLine = 0; + m_LastLine = 0; + m_LastCol = 0; + m_LastCnt = 0; + m_LineStartCount = 1; + m_LineStarts[0].clb = m_log; + m_LineStarts[0].index = 0; + m_Height = 0; + m_Width = 0; + m_Lines = 0; + m_Cols = 0; + m_pLastEntry = NULL; + +} + +T100_ComMon::~T100_ComMon() +{ + TcomLogBlock *b = m_log; + TcomLogBlock *n; + + // Delete all TcomLogBlock entries + while (b != NULL) + { + // Save pointer to next TcomLogBlock + n = b->next; + + // Delete this block + delete b; + + // Point to next block + b = n; + } +} + +void T100_ComMon::Clear(void) +{ + delete m_log; + m_log = new TcomLogBlock(); + m_FirstLine = 0; + m_LastLine = 0; + m_LastCol = 0; + m_LastCnt = 0; + m_LineStartCount = 1; + m_LineStarts[0].clb = m_log; + m_LineStarts[0].index = 0; + m_Height = 0; + m_Width = 0; + m_Lines = 0; + m_Cols = 0; + m_pLastEntry = NULL; + redraw(); +} + +void T100_ComMon::AddByte(int rx_tx, char byte, char flags) +{ + TcomLogBlock *b = m_log; + int xpos, ypos, adder; + char string[4]; + int line; + + line = m_LastLine; + + // Find last block with room in it + while (b->used == b->max) + { + if (b->next == NULL) + b->next = new TcomLogBlock(); + + b = b->next; + } + + // Add byte to the log + b->entries[b->used].byte = byte; + if (rx_tx) + flags |= 0x80; + b->entries[b->used].flags = flags; + b->entries[b->used].time = hirestimer(); + + // Check if last char was save type as this & advance col if it was + if (m_pLastEntry != NULL) + { + if ((m_pLastEntry->flags & 0x80) == (b->entries[b->used].flags & 0x80) || + (m_LastCnt == 2)) + { + adder = gHexOn ? 3 : 1; + // Add 1 or 3 bytes (2 hex plus space) + m_LastCol += adder; + m_LastCnt = 0; + if (m_LastCol + adder >= m_Cols) + { + m_LastCol = 0; + m_LastLine += 2; + m_LineStarts[m_LineStartCount].clb = b; + m_LineStarts[m_LineStartCount++].index = b->used; + } + } + } + // Increment number of bytes displayed at this col + m_LastCnt++; + + // Determine if byte is on the window + if ((m_LastLine >= m_FirstLine) && (m_LastLine <= m_FirstLine + m_Lines-2)) + { + // Draw byte in window -- first set the display active + window()->make_current(); + + // Select 12 point Courier font + fl_font(FL_COURIER_BOLD,gFontSize); + + // Determine xoffset of text + xpos = (int) (x() + m_LastCol * m_Width); + + // Determine color & yoffset of text + if (b->entries[b->used].flags & 0x80) + { + // Byte is a TX byte + fl_color(FL_RED); + ypos = (int) (y() + (m_LastLine-m_FirstLine+1) * m_Height); + + } + else + { + // Byte is an RX byte + fl_color(FL_BLUE); + ypos = (int) (y() + (m_LastLine-m_FirstLine+2) * m_Height); + } + + + // Draw the text + if (gHexOn) + sprintf(string, "%02X", b->entries[b->used].byte); + else + sprintf(string, "%c", b->entries[b->used].byte); + fl_draw(string, xpos, ypos); + } + + if (line != m_LastLine) + { + periph_ctrl.com.pScroll->maximum((m_LineStartCount<<1)-m_Lines); + periph_ctrl.com.pScroll->slider_size((double) m_Lines / (double) (m_LastLine+2)); + } + + // Save pointer to this entry as last byte added + m_pLastEntry = &b->entries[b->used]; + + b->used++; + +// redraw(); +} + +void T100_ComMon::CalcLineStarts(void) +{ + comLogEntry_t *cle; + TcomLogBlock *clb; + int index; + int col, line, cnt; + int adder; + + // Get pointer/index of first comLogEntry of first line/col + clb = m_log; + index = 0; + adder = gHexOn ? 3 : 1; + line = 0; + col = 0; + cle = NULL; + cnt = 0; + m_LineStartCount = 0; + m_LineStarts[0].clb = clb; + m_LineStarts[0].index = index; + + while (index < clb->used) + { + col = 0; + cle = NULL; + cnt = 0; + m_LineStarts[m_LineStartCount].clb = clb; + m_LineStarts[m_LineStartCount++].index = index; + while (col + adder < m_Cols) + { + if (index >= clb->used) + break; + + // Calculate col/line where data should be drawn + if (cle != NULL) + { + // Check if last char was save type as this & advance if it was + if ((cle->flags & 0x80) == (clb->entries[index].flags & 0x80) || + (cnt == 2)) + { + // Add 1 or 3 bytes (2 hex plus space) + col += adder; + cnt = 0; + if (col + adder >= m_Cols) + { + col = 0; + line += 2; + break; + } + } + } + + // Save pointer to this cle for next comparison + cle = &clb->entries[index]; + + cnt++; + + // Get location of next byte + if (++index == clb->max) + { + // Get pointer to next clb + if (clb->next == NULL) + // No more data -- break loop + break; + + clb = clb->next; + index = 0; + } + + } + } + + if (m_LineStartCount == 0) + m_LineStartCount++; + m_LastLine = line; + m_LastCol = col; + m_LastCnt = cnt; + m_pLastEntry = cle; + periph_ctrl.com.pScroll->maximum((m_LineStartCount<<1)-m_Lines); + periph_ctrl.com.pScroll->slider_size((double) m_Lines / (double) (m_LastLine+2)); +} + +// Redraw the whole LCD +void T100_ComMon::draw() +{ + int line, col, cnt; + comLogEntry_t *cle; + TcomLogBlock *clb; + int index; + int xpos, ypos; + char string[4]; + int adder; + int lines, cols; + + // Select 12 point Courier font + fl_font(FL_COURIER_BOLD,gFontSize); + + // Get character width & height + m_Width = fl_width("W", 1); + m_Height = fl_height(); + + // Calculate max cols and lines + lines = (int) (h() / m_Height); + cols = (int) (w() / m_Width); + + if ((lines != m_Lines) || (cols != m_Cols)) + { + m_Lines = lines; + m_Cols = cols; + CalcLineStarts(); + } + + // Draw white background + fl_color(FL_WHITE); + fl_rectf(x(),y(),w(),h()); + + // Draw GRAY lines between every other line + fl_color(FL_GRAY); + for (line = 2; line < m_Lines; line += 2) + fl_line(x(), y() + (int) (line * m_Height)+2, x()+w(), + y()+(int)(line*m_Height)+2); + + // Get pointer/index of first comLogEntry of first line/col + clb = m_LineStarts[m_FirstLine>>1].clb; + index = m_LineStarts[m_FirstLine>>1].index; + + adder = gHexOn ? 3 : 1; + + line = 0; + while (line + 1 < m_Lines) + { + col = 0; + cle = NULL; + cnt = 0; + while (col + adder < m_Cols) + { + if (index >= clb->used) + break; + + // Calculate col/line where data should be drawn + if (cle != NULL) + { + // Check if last char was also a TX & advance + if ((cle->flags & 0x80) == (clb->entries[index].flags & 0x80) || + (cnt == 2)) + { + // Add 3 bytes (2 hex plus space) + col += adder; + cnt = 0; + if (col + adder >= m_Cols) + { + col = 0; + line += 2; + break; + } + } + } + + // Determine xoffset of text + xpos = (int) (x() + col * m_Width); + + // Determine color & yoffset of text + if (clb->entries[index].flags & 0x80) + { + // Byte is a TX byte + fl_color(FL_RED); + ypos = (int) (y() + (line+1) * m_Height); + + } + else + { + // Byte is an RX byte + fl_color(FL_BLUE); + ypos = (int) (y() + (line+2) * m_Height); + } + + // Draw the text + if (gHexOn) + sprintf(string, "%02X", clb->entries[index].byte); + else + sprintf(string, "%c", clb->entries[index].byte); + fl_draw(string, xpos, ypos); + + // Save pointer to this cle for next comparison + cle = &clb->entries[index]; + + cnt++; + + // Get location of next byte + if (++index == clb->max) + { + // Get pointer to next clb + if (clb->next == NULL) + // No more data -- break loop + break; + + clb = clb->next; + index = 0; + } + + } + + if (index >= clb->used) + break; + } +} diff --git a/src/periph.h b/src/periph.h new file mode 100644 index 0000000..5890fd8 --- /dev/null +++ b/src/periph.h @@ -0,0 +1,102 @@ +/* periph.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef PERIPH_H +#define PERIPH_H + +void cb_PeripheralDevices (Fl_Widget* w, void*); + + +#define MENU_HEIGHT 32 + +typedef struct comLogEntry +{ + double time; + unsigned char byte; + unsigned char flags; +} comLogEntry_t; + + +class TcomLogBlock +{ +public: + TcomLogBlock() { next = NULL; entries = new comLogEntry_t[16384]; + max = 16384; used = 0; }; + ~TcomLogBlock() { delete entries; }; + + TcomLogBlock *next; + struct comLogEntry *entries; + int max; + int used; +}; + +typedef struct lineStart +{ + TcomLogBlock *clb; + int index; +} lineStart_t; + +class T100_ComMon : public Fl_Widget +{ +public: + int m_MyFocus; + T100_ComMon(int x, int y, int w, int h); + ~T100_ComMon(); + + void AddByte(int rx_tx, char byte, char flags); + void CalcLineStarts(void); + int m_FirstLine; + void Clear(void); + +protected: +// virtual int handle(int event); + void draw(); + + + class TcomLogBlock* m_log; + + int m_Cols; + int m_Lines; + double m_Height; + double m_Width; + int m_LastLine; + int m_LastCol; + int m_LastCnt; + comLogEntry_t *m_pLastEntry; + + int m_LineStartCount; + lineStart_t m_LineStarts[20000]; + Fl_Scrollbar* m_pScroll; + +}; + + + +#endif \ No newline at end of file diff --git a/src/serial.c b/src/serial.c new file mode 100644 index 0000000..aad6fec --- /dev/null +++ b/src/serial.c @@ -0,0 +1,1308 @@ +/* serial.c */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(WIN32) +#include +#endif +#include +#include +#include + +#include "serial.h" +#include "setup.h" +#include "display.h" +#include "m100emu.h" + +ser_params_t sp; + +/* +=========================================================================== +ser_init: Initialize serial structures +=========================================================================== +*/ +int ser_init(void) +{ + // Initialize port name + if (setup.com_mode == SETUP_COM_HOST) + strcpy(sp.port_name, setup.com_port); + else if (setup.com_mode == SETUP_COM_OTHER) + strcpy(sp.port_name, setup.com_other); + else if (setup.com_mode == SETUP_COM_SIMULATED) + strcpy(sp.port_name, setup.com_cmd); + + sp.baud_rate = 9600; // Default to 9600 baud rate + sp.open_flag = 0; // Port not open + sp.bit_size = 8; // Default to 8 bits + sp.parity = 'N'; // Initialize to no parity + sp.pCallback = NULL; // No callback funciton + sp.pMonCallback = NULL; // No monitor callback function + sp.stop_bits = 1; // Initialize to 1 stop bit + sp.pCmdFile = NULL; // No open command file + sp.tx_empty = TRUE; // Indicate no active TX + sp.rxIn = 0; // Initialize Read buffer + sp.rxOut = 0; + sp.txIn = 0; // Initialize TX buffer + sp.txOut = 0; + +#ifdef WIN32 + // Create overlapped read event. Must be closed before exiting + // to avoid a handle leak. + sp.osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (sp.osRead.hEvent == NULL) + return SER_IO_ERROR; + + sp.osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (sp.osWrite.hEvent == NULL) + { + CloseHandle(sp.osRead.hEvent); + return SER_IO_ERROR; + } + + // Create events for exiting threads and writing bytes + sp.hThreadExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (sp.hThreadExitEvent == NULL) + return SER_IO_ERROR; + sp.hWriteEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (sp.hWriteEvent == NULL) + return SER_IO_ERROR; + sp.hWriteMutex = CreateMutex(NULL, FALSE, NULL); + if (sp.hWriteMutex == NULL) + return SER_IO_ERROR; + sp.hReadMutex = CreateMutex(NULL, FALSE, NULL); + if (sp.hReadMutex == NULL) + return SER_IO_ERROR; + + sp.fReadThread = FALSE; + sp.fWriteThread = FALSE; + sp.fIntPending = FALSE; + sp.dtrState = DTR_CONTROL_DISABLE; + sp.rtsState = RTS_CONTROL_DISABLE; + + // If Serial port emulation, open the port + if (setup.com_mode != SETUP_COM_NONE) + ser_open_port(); + +#else + + // ============================================ + // Add code here for POSIX initialization + // ============================================ + + +#endif + + return SER_NO_ERROR; +} + +/* +=========================================================================== +ser_deinit: De-Initialize serial structures +=========================================================================== +*/ +int ser_deinit(void) +{ + +#ifdef WIN32 + + // Trigger event to kill worker therads + SetEvent(sp.hThreadExitEvent); + + // Wait for threads to exit + while ((sp.fReadThread == TRUE) && (sp.fWriteThread == TRUE)) + ; + + // Close event handles + if (sp.osRead.hEvent != NULL) + CloseHandle(sp.osRead.hEvent); + if (sp.osWrite.hEvent != NULL) + CloseHandle(sp.osWrite.hEvent); + if (sp.hThreadExitEvent != NULL) + CloseHandle(sp.hThreadExitEvent); + if (sp.hWriteEvent != NULL) + CloseHandle(sp.hWriteEvent); + + // Close port + if (sp.hComm != NULL) + CloseHandle(sp.hComm); +#else + + // =============================================== + // Add code here to deinitialize for POSIX systems + // =============================================== + +#endif + + return SER_NO_ERROR; +} + +/* +=========================================================================== +ser_get_port_list: Get a list of valid COM port names and count. + + This function returns a comma seperated list of serial + port names valid for the host. This list will be + displayed in the Peripheral Setup dialog to allow the + user to select where emulation should be directed. +=========================================================================== +*/ +int ser_get_port_list(char* port_list, int max, int *count) +{ + +#ifdef WIN32 + int c; + HANDLE hComm; + char str[6]; + int list_len = 0; + + *count = 0; + port_list[0] = 0; + + /* Loop through up to 8 serial ports */ + for (c = 1; c <= 8; c++) + { + /* Create string name for each port */ + sprintf(str, "COM%d", c); + + // Test if port is already opened (it needs to be in the list too) + if ((strcmp(str, sp.port_name) == 0) && (sp.open_flag)) + hComm = (void*)1; + + else + { + /* Try to open each port */ + hComm = CreateFile(str, + GENERIC_READ | GENERIC_WRITE, + 0, + 0, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + 0); + + /* Check if COM port exists & not in use */ + if (hComm == INVALID_HANDLE_VALUE) + continue; + + /* Close the port and add to the list */ + CloseHandle(hComm); + } + + /* Check if port name fits in buffer */ + if (strlen(port_list) + strlen(str) + 1 <= (unsigned int) max) + { + // If this isn't the first item in list, append a ',' + if (*count > 0) + strcat(port_list, ","); + + // Append port name to list + strcat(port_list, str); + + *count++; + } + } +#else + *count = 0; + port_list[0] = 0; + + // ============================================ + // Add code here to get port list for POSIX + // ============================================ + +#endif + + return SER_NO_ERROR; +} + + +#ifdef WIN32 +/* +=========================================================================== +initialize_dcb: Configure the WIN32 dcb structure with settings in sp + + This is a WIN32 specific routine +=========================================================================== +*/ +void initialize_dcb(void) +{ + GetCommState(sp.hComm, &sp.dcb); + + // Set Baud Rate + sp.dcb.BaudRate = sp.baud_rate; + + // Set number of bits and stop bits + sp.dcb.ByteSize = sp.bit_size; + if (sp.stop_bits == 1) + sp.dcb.StopBits = ONESTOPBIT; + else + sp.dcb.StopBits = TWOSTOPBITS; + + // Set parity check flag + if (sp.parity == 'I') + sp.dcb.fParity = FALSE; + else + sp.dcb.fParity = TRUE; + if (sp.parity == 'E') + sp.dcb.Parity = EVENPARITY; + else if (sp.parity == 'O') + sp.dcb.Parity = ODDPARITY; + else if (sp.parity == 'N') + sp.dcb.Parity = NOPARITY; + + // Set flow control members + sp.dcb.fOutxCtsFlow = FALSE; + sp.dcb.fOutxDsrFlow = FALSE; + sp.dcb.fInX = FALSE; + sp.dcb.fOutX = FALSE; + sp.dcb.fDsrSensitivity = FALSE; + + // DTR is controlled by the ROM so disable it + sp.dcb.fDtrControl = FALSE;//sp.dtrState; + + // RTS is controlled by the ROM so disable it + sp.dcb.fRtsControl = FALSE;//sp.rtsState;; +} + + +void ErrorReporter(char* text) +{ + show_error(text); +} + +/* +=========================================================================== +process_read_byte: Called when a byte is received by the COM port. This + routine adds the byte to the buffer and calls he callback function. +=========================================================================== +*/ +void process_read_byte(ser_params_t *sp, char byte) +{ + int new_rxIn; + +#ifdef WIN32 + WaitForSingleObject(sp->hReadMutex, 2000); +#endif + + // Add byte to read buffer + sp->rx_buf[sp->rxIn] = byte; + + new_rxIn = sp->rxIn + 1; + if (new_rxIn >= sizeof(sp->rx_buf)) + new_rxIn = 0; + + sp->rxIn = new_rxIn; + +#ifdef WIN32 + ReleaseMutex(sp->hReadMutex); +#endif + + // Check if there is a monitor window open and report the write +// if (sp->pMonCallback != NULL) +// sp->pMonCallback(SER_MON_COM_READ, (unsigned char) byte); + + // Call callback to indicate receipt of data + if (sp->pCallback != NULL) + { + sp->pCallback(); + sp->fIntPending = TRUE; + } +} + +/* +=========================================================================== +stop_threads:: Terminates the Read and Write threads +=========================================================================== +*/ +void stop_threads(void) +{ + time_t start_time, cur_time; + + // Trigger event to exit threads + SetEvent(sp.hThreadExitEvent); + + // Get start time for Wait timeout + time(&start_time); + + // Wait for threads to exit (up to 2 seconds) + while (sp.fReadThread && sp.fWriteThread) + { + time(&cur_time); + if (start_time + 2 <= cur_time) + break; + } + + ResetEvent(sp.hThreadExitEvent); +} + + BOOL fWaitingOnRead = FALSE; +/* +=========================================================================== +ReadProc: Thread to read data from COM port +=========================================================================== +*/ +DWORD ReadProc(LPVOID lpv) +{ + HANDLE hArray[2]; + + DWORD dwStoredFlags = 0xFFFFFFFF; // local copy of event flags + DWORD dwFlags = EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING | EV_RLSD; + DWORD dwRead; // bytes actually read + DWORD dwRes; // result from WaitForSingleObject + COMSTAT comStat; + DWORD dwError; + BOOL fWaitingOnStat = FALSE; + BOOL fThreadDone = FALSE; +// char read_ch; + char buf[128]; + unsigned int c; + ser_params_t *sp; + + + sp = (ser_params_t *) lpv; + + // Detect the following events: + // Read events (from ReadFile) + // Thread exit evetns (from our shutdown functions) + hArray[0] = sp->osRead.hEvent; + hArray[1] = sp->hThreadExitEvent; + + while ( !fThreadDone ) + { + // if no read is outstanding, then issue another one + if (!fWaitingOnRead) + { + if (!ReadFile(sp->hComm, buf, 1, &dwRead, &sp->osRead)) + { + if (GetLastError() != ERROR_IO_PENDING) // read not delayed? + ErrorReporter("ReadFile in ReaderAndStatusProc"); + + fWaitingOnRead = TRUE; + } + else + { + // read completed immediately + if (dwRead) + { + for (c = 0; c < dwRead; c++) + process_read_byte(sp, buf[c]); + } + } + } + + if (dwStoredFlags != dwFlags) { + dwStoredFlags = dwFlags; + if (!SetCommMask(sp->hComm, dwStoredFlags)) + ErrorReporter("SetCommMask"); + } + + // wait for pending operations to complete + if ( fWaitingOnRead ) + { + dwRes = WaitForMultipleObjects(2, hArray, FALSE, INFINITE); + switch(dwRes) + { + // read completed + case WAIT_OBJECT_0: + if (!GetOverlappedResult(sp->hComm, &sp->osRead, &dwRead, FALSE)) + { + ClearCommError(sp->hComm, &dwError, &comStat); + ErrorReporter("GetOverlappedResult (in Reader)"); + } + else + { + // read completed successfully + if (dwRead) + { + for (c = 0; c < dwRead; c++) + process_read_byte(sp, buf[c]); + } + fWaitingOnRead = FALSE; + } + + break; + + case WAIT_TIMEOUT: + break; + + // thread exit event + case WAIT_OBJECT_0 + 1: + fThreadDone = TRUE; + break; + + default: + ErrorReporter("WaitForMultipleObjects(Reader & Status handles)"); + break; + } + } + } + + sp->fReadThread = FALSE; + return 1; +} + +/* +=========================================================================== +WriteProc: Thread to write data to COM port +=========================================================================== +*/ +DWORD WINAPI WriteProc(LPVOID lpv) +{ + HANDLE hArray[2]; + HANDLE hwArray[2]; + DWORD dwRes; + DWORD dwWritten; + BOOL fDone = FALSE; + ser_params_t *sp; + + sp = (ser_params_t*) lpv; + + hArray[0] = sp->hWriteEvent; + hArray[1] = sp->hThreadExitEvent; + + while ( !fDone ) { + dwRes = WaitForMultipleObjects(2, hArray, FALSE, INFINITE); + switch(dwRes) + { + case WAIT_FAILED: + ErrorReporter("WaitForMultipleObjects( writer proc )"); + break; + + // write request event + case WAIT_OBJECT_0: + hwArray[0] = sp->osWrite.hEvent; + hwArray[1] = sp->hThreadExitEvent; + + // Read bytes from sp structure +// c = 0; +#ifdef WIN32 + WaitForSingleObject(sp->hWriteMutex, 2000); +#endif +// while (sp->txIn != sp->txOut) +// { +// buf[c++] = sp->tx_buf[sp->txOut++]; +// if (sp->txOut >= sizeof(sp->tx_buf)) +// sp->txOut = 0; +// } + +#ifdef WIN32 + ReleaseMutex(sp->hWriteMutex); +#endif + // issue write + if (!WriteFile(sp->hComm, sp->tx_buf, 1, &dwWritten, &sp->osWrite)) + { + if (GetLastError() == ERROR_IO_PENDING) + { + // write is delayed + dwRes = WaitForMultipleObjects(2, hwArray, FALSE, INFINITE); + switch(dwRes) + { + // write event set + case WAIT_OBJECT_0: + SetLastError(ERROR_SUCCESS); + if (!GetOverlappedResult(sp->hComm, &sp->osWrite, &dwWritten, FALSE)) { + ErrorReporter("GetOverlappedResult(in Writer)"); + } + + break; + + // thread exit event set + case WAIT_OBJECT_0 + 1: + break; + + // wait timed out + case WAIT_TIMEOUT: + break; + } + + sp->tx_empty = TRUE; + } + } + + break; + + // thread exit event + case WAIT_OBJECT_0 + 1: + fDone = TRUE; + break; + } + } + + sp->fWriteThread = FALSE; + return 1; +} + + +/* +=========================================================================== +start_threads:: Creates the Reader/Status and Writer threads +=========================================================================== +*/ +int start_threads(void) +{ + DWORD dwReadStatId; + DWORD dwWriterId; + + // Create read thread + sp.hReadThread = CreateThread( NULL, 0, + (LPTHREAD_START_ROUTINE) ReadProc, + (LPVOID) &sp, 0, &dwReadStatId); + + if (sp.hReadThread == NULL) + return SER_IO_ERROR; + + sp.fReadThread = TRUE; + + // Create write thread + sp.hWriteThread = CreateThread( NULL, 0, + (LPTHREAD_START_ROUTINE) WriteProc, + (LPVOID) &sp, 0, &dwWriterId ); + + if (sp.hWriteThread == NULL) + return SER_IO_ERROR; + + sp.fWriteThread = TRUE; + + return SER_NO_ERROR; +} + + +#endif + +/* +=========================================================================== +ser_set_baud: Set the baud rate to the numeric value passed. + + The value will be in the range of 75 to 19200 +=========================================================================== +*/ +int ser_set_baud(int baud) +{ + // Update baud rate + sp.baud_rate = baud; + + // If port not open, return -- noting else to do + if (sp.open_flag == 0) + return SER_NO_ERROR; + + if (setup.com_mode == SETUP_COM_HOST) + { + #ifdef WIN32 + // Update DCB settings + initialize_dcb(); + + // Update Port settings with new DCB + if (!SetCommState(sp.hComm, &sp.dcb)) + { + // Error updating port settings + return SER_IO_ERROR; + } + #else + + // ========================================== + // Add code here for POSIX to set baud rate + // ========================================== + + #endif + } + + // Check for a monitor window and report change + if (sp.pMonCallback != NULL) + sp.pMonCallback(SER_MON_COM_PORT_CHANGE, SER_MON_COM_CHANGE_BAUD); + + return SER_NO_ERROR; +} + +/* +=========================================================================== +ser_close_port: Close the opened serial port +=========================================================================== +*/ +int ser_close_port(void) +{ + // Test if port is open + if (sp.open_flag == 0) + return SER_PORT_NOT_OPEN; + + if (setup.com_mode == SETUP_COM_HOST) + { + // =================== + // Close the Host port + // =================== + #ifdef WIN32 + // Insure handle is not NULL + if (sp.hComm != NULL) + { + // Stop all threads + stop_threads(); + + // Close the port + CloseHandle(sp.hComm); + } + sp.hComm = NULL; + #else + + // ============================================ + // Add code here for POSIX to close port + // ============================================ + + #endif + } + else if (setup.com_mode == SETUP_COM_SIMULATED) + { + // ====================== + // Close the command file + // ====================== + if (sp.pCmdFile != NULL) + fclose(sp.pCmdFile); + sp.pCmdFile = NULL; + } + + // Set flag indicating port not open + sp.open_flag = 0; + + // Check for a monitor window and report change + if (sp.pMonCallback != NULL) + sp.pMonCallback(SER_MON_COM_PORT_CHANGE, SER_MON_COM_CHANGE_STATE); + + // Return with no error + return SER_NO_ERROR; +} + + +/* +=========================================================================== +ser_open_port: Open the serial port specified by ser_set_port +=========================================================================== +*/ +int ser_open_port(void) +{ + // Test if port is already opened + if (sp.open_flag == 1) + ser_close_port(); + + // Check if using HOST port emulation + if (setup.com_mode == SETUP_COM_HOST) + { + // ============= + // Open the port + // ============= + #ifdef WIN32 + char msg[50]; + + // Attempt to open the port specified by sp.port_name + sp.hComm = CreateFile( sp.port_name, + GENERIC_READ | GENERIC_WRITE, + 0, + 0, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + //FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + 0); + // Check for error opening port + if (sp.hComm == INVALID_HANDLE_VALUE) + { + sprintf(msg, "Error opening port %s", sp.port_name); + show_error(msg); + return SER_IO_ERROR; + } + #else + + // ============================================ + // Add code here for POSIX to open the port + // ============================================ + + #endif + + // ========================================== + // Configure port's baud rate, bit_size, etc. + // ========================================== + #ifdef WIN32 + FillMemory(&sp.dcb, sizeof(sp.dcb), 0); + sp.dcb.DCBlength = sizeof(DCB); + if (!GetCommState(sp.hComm, &sp.dcb)) + { + DWORD err = GetLastError(); + + sprintf(msg,"I/O Error on %s", sp.port_name); + show_error(msg); + // Error reading port state + return SER_IO_ERROR; + } + + // Initialize the DCB to set baud rate, etc. + initialize_dcb(); + + // Update DCB settings + if (!SetCommState(sp.hComm, &sp.dcb)) + { + // Error updating port settings + CloseHandle(sp.hComm); + sp.hComm = 0; + return SER_IO_ERROR; + } + + // Start Read an Write Threads + start_threads(); + + // Update flag indicating port open + sp.open_flag = TRUE; + #else + + // ============================================ + // Add code here for POSIX to configure port + // ============================================ + + #endif + } + else if (setup.com_mode == SETUP_COM_SIMULATED) + { + // Open Simulation Command file + if ((sp.pCmdFile = fopen(setup.com_cmd, "r")) == NULL) + return SER_IO_ERROR; + + // Update flag indicating port open + sp.open_flag = TRUE; + } + else if (setup.com_mode == SETUP_COM_OTHER) + { + // ============================================ + // Add code here to support other Host ports + // ============================================ + } + + // Check for a monitor window and report change + if (sp.pMonCallback != NULL) + sp.pMonCallback(SER_MON_COM_PORT_CHANGE, SER_MON_COM_CHANGE_STATE); + + // Return with no error + return SER_NO_ERROR; +} + +/* +=========================================================================== +ser_set_port: Set the active serial port for subsequent calls + + Port is an OS specific string indicating the name of the + host serial port where all traffic will be directed. +=========================================================================== +*/ +int ser_set_port(char* port) +{ + // Save name of port for later use + strcpy(sp.port_name, port); + + // Check for a monitor window and report change + if (sp.pMonCallback != NULL) + sp.pMonCallback(SER_MON_COM_PORT_CHANGE, SER_MON_COM_CHANGE_NAME); + +return SER_NO_ERROR; +} + +/* +=========================================================================== +ser_get_port_settings: Provides current port emulation settings for + reporting in the PeripheralDevices window. +=========================================================================== +*/ +int ser_get_port_settings(char* port, int* open_state, int* baud, int* size, + int* stop_bits, char* parity) +{ + // Save name of port for later use + strcpy(port, sp.port_name); + *open_state = sp.open_flag; + *baud = sp.baud_rate; + *size = sp.bit_size; + *stop_bits = sp.stop_bits; + *parity = sp.parity; + + return SER_NO_ERROR; +} + +/* +=========================================================================== +ser_set_parity: Set parity for the emulated port + + Valid values for parity are 'O', 'E', 'N', or 'I' +=========================================================================== +*/ +int ser_set_parity(char parity) +{ + // Check if parity changed + if (parity == sp.parity) + return SER_NO_ERROR; + + // Save new parity + sp.parity = parity; + + // If port not open, return -- noting else to do + if (sp.open_flag == 0) + return SER_NO_ERROR; + + if (setup.com_mode == SETUP_COM_HOST) + { + #ifdef WIN32 + // Update DCB settings + initialize_dcb(); + + // Update Port settings with new DCB + if (!SetCommState(sp.hComm, &sp.dcb)) + { + // Error updating port settings + return SER_IO_ERROR; + } + #else + + // ============================================ + // Add code here for POSIX to set parity + // ============================================ + + #endif + } + + // Check for a monitor window and report change + if (sp.pMonCallback != NULL) + sp.pMonCallback(SER_MON_COM_PORT_CHANGE, SER_MON_COM_CHANGE_PARITY); + + return SER_NO_ERROR; +} + +/* +=========================================================================== +ser_set_bit_size: Set the serial port's bit size + + Valid values for bit_size are 6, 7, or 8 +=========================================================================== +*/ +int ser_set_bit_size(int bit_size) +{ + // Check if bit size changed + if (bit_size == sp.bit_size) + return SER_NO_ERROR; + + // Save bit size + sp.bit_size = bit_size; + + // If port not open, return -- noting else to do + if (sp.open_flag == 0) + return SER_NO_ERROR; + + if (setup.com_mode == SETUP_COM_HOST) + { + #ifdef WIN32 + // Update DCB settings + initialize_dcb(); + + // Update Port settings with new DCB + if (!SetCommState(sp.hComm, &sp.dcb)) + { + // Error updating port settings + return SER_IO_ERROR; + } + #else + + // ============================================ + // Add code here for POSIX to set #bits + // ============================================ + + #endif + } + + // Check for a monitor window and report change + if (sp.pMonCallback != NULL) + sp.pMonCallback(SER_MON_COM_PORT_CHANGE, SER_MON_COM_CHANGE_BITS); + +return SER_NO_ERROR; +} + +/* +=========================================================================== +ser_set_stop_bits: Set the serial port's stop bits + + Valid values for stop_bits are 1 or 2 +=========================================================================== +*/ +int ser_set_stop_bits(int stop_bits) +{ + // Check if stop bits changed + if (stop_bits == sp.stop_bits) + return SER_NO_ERROR; + + // Save stop bits + sp.stop_bits = stop_bits; + + // If port not open, return -- noting else to do + if (sp.open_flag == 0) + return SER_NO_ERROR; + + if (setup.com_mode == SETUP_COM_HOST) + { + #ifdef WIN32 + // Update DCB settings + initialize_dcb(); + + // Update Port settings with new DCB + if (!SetCommState(sp.hComm, &sp.dcb)) + { + // Error updating port settings + return SER_IO_ERROR; + } + #else + + // ============================================ + // Add code here for POSIX to set #stop bits + // ============================================ + + #endif + } + + // Check for a monitor window and report change + if (sp.pMonCallback != NULL) + sp.pMonCallback(SER_MON_COM_PORT_CHANGE, SER_MON_COM_CHANGE_STOP); + + return SER_NO_ERROR; +} + +/* +=========================================================================== +ser_set_callback: Set the callback routine for processing incomming data. +=========================================================================== +*/ +int ser_set_callback(ser_callback pCallback) +{ + // Save callback address + sp.pCallback = pCallback; + + return SER_NO_ERROR; +} + +/* +=========================================================================== +ser_set_monitor_callback: Set the callback routine for reporting traffic + to a monitor window. +=========================================================================== +*/ +int ser_set_monitor_callback(ser_monitor_cb pCallback) +{ + // Save callback address + sp.pMonCallback = pCallback; + + return SER_NO_ERROR; +} + +/* +=========================================================================== +ser_set_flags: Set the serial port's RTS and DTR flags + +=========================================================================== +*/ +int ser_set_signals(unsigned char flags) +{ + if (setup.com_mode == SETUP_COM_HOST) + { + #ifdef WIN32 + // Update DTR flag + if (flags & SER_SIGNAL_DTR) + { + sp.dtrState = DTR_CONTROL_ENABLE; + EscapeCommFunction(sp.hComm, SETDTR); + } + else + { + sp.dtrState = DTR_CONTROL_DISABLE; + EscapeCommFunction(sp.hComm, CLRDTR); + } + + // Update RTS flag + if (flags & SER_SIGNAL_RTS) + { + sp.rtsState = RTS_CONTROL_ENABLE; + EscapeCommFunction(sp.hComm, SETRTS); + } + else + { + sp.rtsState = RTS_CONTROL_DISABLE; + EscapeCommFunction(sp.hComm, CLRRTS); + } + + #else + + // ============================================ + // Add code here for POSIX to set DTR/RTS + // ============================================ + + #endif + } + + // Check for a monitor window and report change + if (sp.pMonCallback != NULL) + sp.pMonCallback(SER_MON_COM_SIGNAL, (char)((flags>>8) | + (flags & (SER_FLAG_DSR | SER_FLAG_CTS)))); + + return SER_NO_ERROR; +} + +/* +=========================================================================== +ser_get_flags: Get serial port's flags + +=========================================================================== +*/ +int ser_get_flags(unsigned char *flags) +{ + long modem_status; + + if (setup.com_mode == SETUP_COM_HOST) + { + if (sp.open_flag == 0) + { + *flags = 0; + return SER_NO_ERROR; + } + + #ifdef WIN32 + if (!GetCommModemStatus(sp.hComm, &modem_status)) + { + *flags = 0; + if (sp.tx_empty) + *flags |= SER_FLAG_TX_EMPTY; + return SER_IO_ERROR; + } + + *flags = 0; + + // Set CTS flag + if ((modem_status & MS_CTS_ON) == 0) + *flags |= SER_FLAG_CTS; + + // Set DSR flag + if ((modem_status & MS_DSR_ON) == 0) + *flags |= SER_FLAG_DSR; + + // RING flag + if (modem_status & MS_RING_ON) + *flags |= SER_FLAG_RING + ; + // TX_EMPTY flag + if (sp.tx_empty) + *flags |= SER_FLAG_TX_EMPTY; + + // OVERRUN flag + + // FRAMING Error flag + + if ((sp.rxIn != sp.rxOut) && (sp.fIntPending == 0)) + { + if (sp.pCallback != NULL) + { + sp.pCallback(); + sp.fIntPending = TRUE; + } + } + #else + + // ============================================ + // Add code here for POSIX to read flags + // ============================================ + + #endif + } + + return SER_NO_ERROR; +} + +/* +=========================================================================== +ser_get_signals: Get serial port's CTS, RTS, DTR, and DSR signals + +=========================================================================== +*/ +int ser_get_signals(unsigned char *flags) +{ + long modem_status; + + if (setup.com_mode == SETUP_COM_HOST) + { + if (sp.open_flag == 0) + { + *flags = 0; + return SER_NO_ERROR; + } + + #ifdef WIN32 + if (!GetCommModemStatus(sp.hComm, &modem_status)) + { + *flags = 0; + return SER_IO_ERROR; + } + + *flags = 0; + + // Set CTS flag + if ((modem_status & MS_CTS_ON) == 1) + *flags |= SER_SIGNAL_CTS; + + // Set DSR flag + if ((modem_status & MS_DSR_ON) == 1) + *flags |= SER_SIGNAL_DSR; + + // Set RTS flag + if (sp.rtsState == RTS_CONTROL_ENABLE) + *flags |= SER_SIGNAL_RTS; + + // Set DTR flag + if (sp.dtrState == DTR_CONTROL_ENABLE) + *flags |= SER_SIGNAL_DTR; + + #else + + // ============================================ + // Add code here for POSIX to read flags + // ============================================ + + #endif + } + + return SER_NO_ERROR; +} + +/* +=========================================================================== +ser_read_byte: Read byte from the serial port + +=========================================================================== +*/ +int ser_read_byte(char* data) +{ + // Check if a port is open, return if not + if (sp.open_flag == FALSE) + { + *data = 0; + return SER_NO_ERROR; + } + + // Check if COM emulation type is Host port + if (setup.com_mode == SETUP_COM_HOST) + { + #ifdef WIN32 + int new_rxOut; + +#ifdef WIN32 + WaitForSingleObject(sp.hReadMutex, 2000); +#endif + // Check if any bytes in RX buffer + if (sp.rxIn == sp.rxOut) + { +#ifdef WIN32 + ReleaseMutex(sp.hReadMutex); +#endif + // No data in buffer! + *data = 0; + // Check if there is a monitor window open and report the write + if (sp.pMonCallback != NULL) + sp.pMonCallback(SER_MON_COM_READ, *data); + return SER_NO_DATA; + } + + *data = sp.rx_buf[sp.rxOut]; + + new_rxOut = sp.rxOut + 1; + if (new_rxOut >= sizeof(sp.rx_buf)) + new_rxOut = 0; + sp.rxOut = new_rxOut; + +#ifdef WIN32 + ReleaseMutex(sp.hReadMutex); +#endif + sp.fIntPending = FALSE; + + #else + + // ============================================ + // Add code here for POSIX to write data + // ============================================ + + #endif + } + + // Check if there is a monitor window open and report the write + if (sp.pMonCallback != NULL) + sp.pMonCallback(SER_MON_COM_READ, *data); + + return SER_NO_ERROR; +} + +/* +=========================================================================== +ser_write_byte: Write a byte to the serial port + +=========================================================================== +*/ +int ser_write_byte(char data) +{ + // Check if a port is open, return if not + if (sp.open_flag == FALSE) + return SER_NO_ERROR; + + // Check if COM port emulation configured for HOST port + if (setup.com_mode == SETUP_COM_HOST) + { + #ifdef WIN32 + // Store data in structure +#ifdef WIN32 + WaitForSingleObject(sp.hWriteMutex, 2000); +#endif + sp.tx_buf[0] = data; +// sp.tx_buf[sp.txIn++] = data; +// if (sp.txIn >= sizeof(sp.tx_buf)) +// sp.txIn = 0; + + // Update tx_empy flag indicating byte to write + sp.tx_empty = FALSE; + +#ifdef WIN32 + ReleaseMutex(sp.hWriteMutex); +#endif + + // Trigger the thread to write the byte + SetEvent(sp.hWriteEvent); + + #else + + // ================================================= + // Add code here for POSIX to write data (Host Mode) + // ================================================= + + #endif + } + + // Check if there is a monitor window open and report the write + if (sp.pMonCallback != NULL) + sp.pMonCallback(SER_MON_COM_WRITE, data); + + return SER_NO_ERROR; +} + diff --git a/src/serial.h b/src/serial.h new file mode 100644 index 0000000..e4c1bf4 --- /dev/null +++ b/src/serial.h @@ -0,0 +1,154 @@ +/* serial.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#ifndef MT_SERIAL_H +#define MT_SERIAL_H + +enum { + SER_NO_ERROR, + SER_IO_ERROR, + SER_INVALID_PORT, + SER_PORT_NOT_SELECTED, + SER_TIMEOUT, + SER_NO_DATA, + SER_PORT_NOT_OPEN +}; + +enum { + SER_MON_COM_READ, + SER_MON_COM_WRITE, + SER_MON_COM_PORT_CHANGE, + SER_MON_COM_SIGNAL +}; + +enum { + SER_MON_COM_CHANGE_ALL, + SER_MON_COM_CHANGE_NAME, + SER_MON_COM_CHANGE_STATE, + SER_MON_COM_CHANGE_BAUD, + SER_MON_COM_CHANGE_BITS, + SER_MON_COM_CHANGE_STOP, + SER_MON_COM_CHANGE_PARITY +}; + +#define SER_FLAG_TX_EMPTY 0x001 +#define SER_FLAG_OVERRUN 0x002 +#define SER_FLAG_FRAME_ERR 0x004 +#define SER_FLAG_PARITY_ERR 0x008 +#define SER_FLAG_CTS 0x010 +#define SER_FLAG_DSR 0x020 +#define SER_FLAG_RING 0x040 + +#define SER_SIGNAL_CTS 0x01 +#define SER_SIGNAL_DSR 0x02 +#define SER_SIGNAL_DTR 0x04 +#define SER_SIGNAL_RTS 0x08 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*ser_callback)(); +typedef void (*ser_monitor_cb)(int fMonType, unsigned char data); + +/* Configuration functions */ +int ser_init(void); +int ser_deinit(void); +int ser_get_port_list(char* port_list, int max, int *count); +int ser_set_baud(int baud_rate); +int ser_set_parity(char parity); +int ser_set_bit_size(int bit_size); +int ser_set_stop_bits(int stop_bits); +int ser_set_callback(ser_callback pCallback); +int ser_set_monitor_callback(ser_monitor_cb pCallback); +int ser_set_port(char* port); +int ser_get_port_settings(char* port, int* open_state, int* baud, int* size, + int* stop_bits, char* parity); + +int ser_open_port(void); +int ser_close_port(void); + +/* Communication functions */ +int ser_get_flags(unsigned char *flags); +int ser_set_signals(unsigned char flags); +int ser_get_signals(unsigned char *signals); +int ser_read_byte(char* data); +int ser_write_byte(char data); + +#ifdef __cplusplus +} +#endif + + +typedef struct ser_params +{ + char port_name[256]; // Host port name for emulation + char parity; // Current parity setting + int baud_rate; // Current baud rate + int bit_size; // Bit size for theport + int stop_bits; // Number of stop bits + int open_flag; // Set to 1 when the port is open + char rx_buf[128]; // Read buffer + int rxIn; // Read buffer input location + int rxOut; // Read buffer output location + char tx_buf[32]; // Read buffer + int txIn; // Read buffer input location + int txOut; // Read buffer output location + int tx_empty; // Flag to indicate when TX is done + + ser_callback pCallback; // Callback function for RX data + ser_monitor_cb pMonCallback; + + FILE* pCmdFile; // Command file for Simulated I/O + + // Host COM port control structures + +#ifdef WIN32 + HANDLE hComm; // Handle to the serial port + OVERLAPPED osRead; // Overlapped I/O structure for reading + OVERLAPPED osWrite; // Overlapped I/O structure for writing + DCB dcb; // Device control block + HANDLE hReadThread; // Read COM thread + HANDLE hWriteThread; // Write COM thread + HANDLE hThreadExitEvent; // Event to trigger thread exiting + HANDLE hWriteEvent; // Event to trigger a write operation + HANDLE hWriteMutex; + HANDLE hReadMutex; + int fReadThread; // Flag indicating if Read Thread active + int fWriteThread; // Flag indicating if Write Tread active + int fIntPending; + int dtrState; // Current state of DTR + int rtsState; // Current state of RTS +#endif + +} ser_params_t; + +#endif diff --git a/src/setup.cpp b/src/setup.cpp new file mode 100644 index 0000000..9f47b0d --- /dev/null +++ b/src/setup.cpp @@ -0,0 +1,445 @@ +/* setup.cpp */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "m100emu.h" +#include "io.h" +#include "serial.h" +#include "setup.h" + +extern Fl_Preferences virtualt_prefs; + + +typedef struct setup_ctrl_struct +{ + Fl_Tabs* pTabs; + + struct + { + Fl_Group* g; + Fl_Round_Button* pNone; + Fl_Round_Button* pSim; + Fl_Input* pCmd; + Fl_Round_Button* pHost; + Fl_Choice* pPort; + Fl_Round_Button* pOther; + Fl_Input* pOtherName; + } com; + struct + { + Fl_Group* g; + } lpt; + struct + { + Fl_Group* g; + Fl_Box* pText; + } mdm; + struct + { + Fl_Group* g; + Fl_Box* pText; + } cas; + struct + { + Fl_Group* g; + Fl_Box* pText; + } bcr; + struct + { + Fl_Group* g; + Fl_Box* pText; + } sound; +} setup_ctrl_t; + + +Fl_Window *gpsw; // Peripheral Setup Window + +setup_ctrl_t setup_ctrl; // Setup window controls +peripheral_setup_t setup; // Setup options + +/* +============================================================================ +Routines to load and save setup structure to the user preferences +============================================================================ +*/ +void save_setup_preferences(void) +{ + // Save COM emulation settings + virtualt_prefs.set("ComMode", setup.com_mode); + virtualt_prefs.set("ComCmd", setup.com_cmd); + virtualt_prefs.set("ComPort", setup.com_port); + virtualt_prefs.set("ComOther", setup.com_other); + + // Save LPT emulation settings + + // Save MDM emulation settings + + // Save CAS emulation settings + + // Save BCR emulation settings + + // Save Sound emulation settings +} + +void load_setup_preferences(void) +{ + // Load COM emulation settings + virtualt_prefs.get("ComMode", setup.com_mode,0); + virtualt_prefs.get("ComCmd", setup.com_cmd,"", 128); + virtualt_prefs.get("ComPort", setup.com_port,"", 128); + virtualt_prefs.get("ComOther", setup.com_other,"", 128); + + // Load LPT emulation settings + + // Load MDM emulation settings + + // Load CAS emulation settings + + // Load BCR emulation settings + + // Load Sound emulation settings +} + +/* +============================================================================ +Callback routines for the Setup Window +============================================================================ +*/ +void cb_setup_cancel (Fl_Widget* w, void*) +{ + gpsw->hide(); + delete gpsw; +} + +void cb_setup_OK(Fl_Widget* w, void*) +{ + // First check if Host port needs to be closed + if (setup.com_mode == SETUP_COM_HOST) + { + // Check if we are turning Host port emulation off + if (setup_ctrl.com.pHost->value() != 1) + ser_close_port(); + + // Check if we are changing ports + if (strcmp(setup_ctrl.com.pPort->text(), setup.com_port) != 0) + ser_close_port(); + } + + if (setup.com_mode == SETUP_COM_OTHER) + { + // Check if we are turning Host port emulation off + if (setup_ctrl.com.pOther->value() != 1) + ser_close_port(); + + // Check if we are changing ports + if (strcmp(setup_ctrl.com.pOtherName->value(), setup.com_other) != 0) + ser_close_port(); + } + + // =========================== + // Get COM options + // =========================== + strcpy(setup.com_cmd, setup_ctrl.com.pCmd->value()); + strcpy(setup.com_port, setup_ctrl.com.pPort->text()); + strcpy(setup.com_other, setup_ctrl.com.pOtherName->value()); + + if (setup_ctrl.com.pNone->value() == 1) + { + ser_set_port("No Emulation"); + setup.com_mode = SETUP_COM_NONE; + } + else if (setup_ctrl.com.pSim->value() == 1) + { + // Open the Script file + ser_set_port(setup.com_cmd); + setup.com_mode = SETUP_COM_SIMULATED; + ser_open_port(); + } + else if (setup_ctrl.com.pHost->value() == 1) + { + // Set preference in structure + setup.com_mode = SETUP_COM_HOST; + + // Open the Host port + ser_set_port(setup.com_port); + ser_open_port(); + } + else if (setup_ctrl.com.pOther->value() == 1) + { + // Set preference in structure + setup.com_mode = SETUP_COM_OTHER; + + // Open the Host port + ser_set_port(setup.com_other); + ser_open_port(); + } + + // =========================== + // Get LPT options + // =========================== + + // =========================== + // Get MDM options + // =========================== + + // =========================== + // Get CAS options + // =========================== + + // =========================== + // Get BCR options + // =========================== + + // =========================== + // Get Sound options + // =========================== + + // Save setup preferences to file + save_setup_preferences(); + + // Destroy the window + gpsw->hide(); + delete gpsw; +} + +void cb_setupwin (Fl_Widget* w, void*) +{ + gpsw->hide(); + delete gpsw; +} + +/* +============================================================================ +Callback routines for the COM Tab +============================================================================ +*/ +void cb_com_radio_none (Fl_Widget* w, void*) +{ + setup_ctrl.com.pCmd->deactivate(); + setup_ctrl.com.pPort->deactivate(); + setup_ctrl.com.pOtherName->deactivate(); +} + +void cb_com_radio_sim (Fl_Widget* w, void*) +{ + setup_ctrl.com.pCmd->activate(); + setup_ctrl.com.pPort->deactivate(); + setup_ctrl.com.pOtherName->deactivate(); +} + +void cb_com_radio_host (Fl_Widget* w, void*) +{ + setup_ctrl.com.pCmd->deactivate(); + setup_ctrl.com.pPort->activate(); + setup_ctrl.com.pOtherName->deactivate(); +} + +void cb_com_radio_other (Fl_Widget* w, void*) +{ + setup_ctrl.com.pCmd->deactivate(); + setup_ctrl.com.pPort->deactivate(); + setup_ctrl.com.pOtherName->activate(); +} + +/* +============================================================================ +Routine to create the PeripheralSetup Window and tabs +============================================================================ +*/ +void cb_PeripheralSetup (Fl_Widget* w, void*) +{ + char com_port_list[256]; + int count; + char *token; + int index; + + // Create Peripheral Setup window + gpsw = new Fl_Window(350, 300, "Peripheral Setup"); + gpsw->callback(cb_setupwin); + + // Create Peripheral Tabs + { + setup_ctrl.pTabs = new Fl_Tabs(10, 10, 330, 240); + + // COM port Tab + { + setup_ctrl.com.g = new Fl_Group(10, 30, 350, 260, " COM "); + + // Create items on the Tab + setup_ctrl.com.pNone = new Fl_Round_Button(20, 40, 180, 20, "No emulation"); + setup_ctrl.com.pNone->type(FL_RADIO_BUTTON); + setup_ctrl.com.pNone->callback(cb_com_radio_none); + + setup_ctrl.com.pSim = new Fl_Round_Button(20, 65, 180, 20, "Use Simulated Port (not supported yet)"); + setup_ctrl.com.pSim->type(FL_RADIO_BUTTON); + setup_ctrl.com.pSim->callback(cb_com_radio_sim); + + setup_ctrl.com.pCmd = new Fl_Input(105, 90, 200, 20, "Cmd File:"); + if (setup.com_mode != SETUP_COM_SIMULATED) + setup_ctrl.com.pCmd->deactivate(); + setup_ctrl.com.pCmd->value(setup.com_cmd); + + setup_ctrl.com.pHost = new Fl_Round_Button(20, 115, 180, 20, "Use Host Port"); + setup_ctrl.com.pHost->type(FL_RADIO_BUTTON); + setup_ctrl.com.pHost->callback(cb_com_radio_host); + + setup_ctrl.com.pPort = new Fl_Choice(50, 140, 240, 20, ""); + if (setup.com_mode != SETUP_COM_HOST) + setup_ctrl.com.pPort->deactivate(); + + setup_ctrl.com.pOther = new Fl_Round_Button(20, 170, 180, 20, "Other Host Port"); + setup_ctrl.com.pOther->type(FL_RADIO_BUTTON); + setup_ctrl.com.pOther->callback(cb_com_radio_other); + + setup_ctrl.com.pOtherName = new Fl_Input(50, 195, 240, 20, ""); + if (setup.com_mode != SETUP_COM_OTHER) + setup_ctrl.com.pOtherName->deactivate(); + setup_ctrl.com.pOtherName->value(setup.com_other); + + + // Get list of COM ports on the host + ser_get_port_list(com_port_list, 256, &count); + token = strtok(com_port_list, ","); + while (token != 0) + { + index = setup_ctrl.com.pPort->add(token); + + if (strcmp(token, setup.com_port) == 0) + setup_ctrl.com.pPort->value(index); + + + // Get next item from list + token = strtok(NULL, ","); + } + + if (setup.com_mode == SETUP_COM_NONE) + setup_ctrl.com.pNone->value(1); + else if (setup.com_mode == SETUP_COM_HOST) + setup_ctrl.com.pHost->value(1); + else if (setup.com_mode == SETUP_COM_SIMULATED) + setup_ctrl.com.pSim->value(1); + else if (setup.com_mode == SETUP_COM_OTHER) + setup_ctrl.com.pOther->value(1); + + // End of Controls for this tab + setup_ctrl.com.g->end(); + } + + // LPT Port Tab + { + // Create the Group item (the "Tab") + setup_ctrl.lpt.g = new Fl_Group(10, 30, 350, 260, " LPT "); + + // Create controls + setup_ctrl.mdm.pText = new Fl_Box(120, 60, 60, 80, "Parallel Port not supported yet"); + + // End of control for this tab + setup_ctrl.lpt.g->end(); + } + + // Modem Port Tab + { + // Create the Group item (the "Tab") + setup_ctrl.mdm.g = new Fl_Group(10, 30, 350, 260, " MDM "); + + // Create controls + setup_ctrl.mdm.pText = new Fl_Box(120, 60, 60, 80, "Modem Port not supported yet"); + + // End of control for this tab + setup_ctrl.mdm.g->end(); + } + + // Cassette Port Tab + { + // Create the Group item (the "Tab") + setup_ctrl.cas.g = new Fl_Group(10, 30, 300, 260, " CAS "); + + // Create controls + setup_ctrl.cas.pText = new Fl_Box(120, 60, 60, 80, "Cassette Port not supported yet"); + + // End of control for this tab + setup_ctrl.cas.g->end(); + } + + // BCR Port Tab + { + // Create the Group item (the "Tab") + setup_ctrl.bcr.g = new Fl_Group(10, 30, 300, 260, " BCR "); + + // Create controls + setup_ctrl.bcr.pText = new Fl_Box(120, 60, 60, 80, "BCR Port not supported yet"); + + // End of control for this tab + setup_ctrl.bcr.g->end(); + } + + // Speaker Port Tab + { + // Create the Group item (the "Tab") + setup_ctrl.sound.g = new Fl_Group(10, 30, 300, 260, " Sound "); + + // Create controls + setup_ctrl.sound.pText = new Fl_Box(120, 60, 60, 80, "Sound not supported yet"); + + // End of control for this tab + setup_ctrl.sound.g->end(); + } + + setup_ctrl.pTabs->value(setup_ctrl.com.g); + setup_ctrl.pTabs->end(); + + } + + // OK button + { Fl_Button* o = new Fl_Button(180, 260, 60, 30, "Cancel"); + o->callback((Fl_Callback*)cb_setup_cancel); + } + { Fl_Return_Button* o = new Fl_Return_Button(250, 260, 60, 30, "OK"); + o->callback((Fl_Callback*)cb_setup_OK); + } + + gpsw->show(); +} + diff --git a/src/setup.h b/src/setup.h new file mode 100644 index 0000000..4d8c12f --- /dev/null +++ b/src/setup.h @@ -0,0 +1,76 @@ +/* setup.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef SETUP_H +#define SETUP_H + + +#ifdef __cplusplus +void cb_PeripheralSetup (Fl_Widget* w, void*); +extern "C" { +#endif + +void load_setup_preferences(void); + + +typedef struct peripheral_setup +{ + // COM port emulation settings + int com_mode; // Mode for COM emulation + char com_port[128]; // Port name of Host + char com_cmd[128]; // Command file for simulation + char com_other[128]; // Command file for simulation + int com_throttle; // Flag if serial I/O should be throttled + + // LPT port emulation settings + + // MDM port emulation settings + + // CAS port emulation settings + + // BCR port emulation settings + + // Sound emulation settings + +} peripheral_setup_t; + +extern peripheral_setup_t setup; + +enum { + SETUP_COM_NONE, + SETUP_COM_SIMULATED, + SETUP_COM_HOST, + SETUP_COM_OTHER +}; + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file From b7ec4feac0337105ce383dccb728a642d778c91a Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 14 Sep 2004 20:20:24 +0000 Subject: [PATCH 029/327] Cleaned up some #ifdefs for WIN32 --- src/serial.c | 41 ++++------------------------------------- 1 file changed, 4 insertions(+), 37 deletions(-) diff --git a/src/serial.c b/src/serial.c index aad6fec..e963fff 100644 --- a/src/serial.c +++ b/src/serial.c @@ -303,9 +303,7 @@ void process_read_byte(ser_params_t *sp, char byte) { int new_rxIn; -#ifdef WIN32 WaitForSingleObject(sp->hReadMutex, 2000); -#endif // Add byte to read buffer sp->rx_buf[sp->rxIn] = byte; @@ -316,13 +314,7 @@ void process_read_byte(ser_params_t *sp, char byte) sp->rxIn = new_rxIn; -#ifdef WIN32 ReleaseMutex(sp->hReadMutex); -#endif - - // Check if there is a monitor window open and report the write -// if (sp->pMonCallback != NULL) -// sp->pMonCallback(SER_MON_COM_READ, (unsigned char) byte); // Call callback to indicate receipt of data if (sp->pCallback != NULL) @@ -358,7 +350,7 @@ void stop_threads(void) ResetEvent(sp.hThreadExitEvent); } - BOOL fWaitingOnRead = FALSE; +BOOL fWaitingOnRead = FALSE; /* =========================================================================== ReadProc: Thread to read data from COM port @@ -376,7 +368,6 @@ DWORD ReadProc(LPVOID lpv) DWORD dwError; BOOL fWaitingOnStat = FALSE; BOOL fThreadDone = FALSE; -// char read_ch; char buf[128]; unsigned int c; ser_params_t *sp; @@ -497,20 +488,9 @@ DWORD WINAPI WriteProc(LPVOID lpv) hwArray[1] = sp->hThreadExitEvent; // Read bytes from sp structure -// c = 0; -#ifdef WIN32 WaitForSingleObject(sp->hWriteMutex, 2000); -#endif -// while (sp->txIn != sp->txOut) -// { -// buf[c++] = sp->tx_buf[sp->txOut++]; -// if (sp->txOut >= sizeof(sp->tx_buf)) -// sp->txOut = 0; -// } -#ifdef WIN32 ReleaseMutex(sp->hWriteMutex); -#endif // issue write if (!WriteFile(sp->hComm, sp->tx_buf, 1, &dwWritten, &sp->osWrite)) { @@ -589,9 +569,9 @@ int start_threads(void) return SER_NO_ERROR; } - #endif + /* =========================================================================== ser_set_baud: Set the baud rate to the numeric value passed. @@ -819,7 +799,7 @@ int ser_set_port(char* port) if (sp.pMonCallback != NULL) sp.pMonCallback(SER_MON_COM_PORT_CHANGE, SER_MON_COM_CHANGE_NAME); -return SER_NO_ERROR; + return SER_NO_ERROR; } /* @@ -935,7 +915,7 @@ int ser_set_bit_size(int bit_size) if (sp.pMonCallback != NULL) sp.pMonCallback(SER_MON_COM_PORT_CHANGE, SER_MON_COM_CHANGE_BITS); -return SER_NO_ERROR; + return SER_NO_ERROR; } /* @@ -1210,15 +1190,11 @@ int ser_read_byte(char* data) #ifdef WIN32 int new_rxOut; -#ifdef WIN32 WaitForSingleObject(sp.hReadMutex, 2000); -#endif // Check if any bytes in RX buffer if (sp.rxIn == sp.rxOut) { -#ifdef WIN32 ReleaseMutex(sp.hReadMutex); -#endif // No data in buffer! *data = 0; // Check if there is a monitor window open and report the write @@ -1234,9 +1210,7 @@ int ser_read_byte(char* data) new_rxOut = 0; sp.rxOut = new_rxOut; -#ifdef WIN32 ReleaseMutex(sp.hReadMutex); -#endif sp.fIntPending = FALSE; #else @@ -1272,20 +1246,13 @@ int ser_write_byte(char data) { #ifdef WIN32 // Store data in structure -#ifdef WIN32 WaitForSingleObject(sp.hWriteMutex, 2000); -#endif sp.tx_buf[0] = data; -// sp.tx_buf[sp.txIn++] = data; -// if (sp.txIn >= sizeof(sp.tx_buf)) -// sp.txIn = 0; // Update tx_empy flag indicating byte to write sp.tx_empty = FALSE; -#ifdef WIN32 ReleaseMutex(sp.hWriteMutex); -#endif // Trigger the thread to write the byte SetEvent(sp.hWriteEvent); From 1db076468f1569b9cd348a78d5dae8ee6170d241 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 1 Oct 2004 21:05:34 +0000 Subject: [PATCH 030/327] Added support for detecting changes in CTS & DSR. --- src/serial.c | 104 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 74 insertions(+), 30 deletions(-) diff --git a/src/serial.c b/src/serial.c index e963fff..3ff0edc 100644 --- a/src/serial.c +++ b/src/serial.c @@ -290,7 +290,7 @@ void initialize_dcb(void) void ErrorReporter(char* text) { - show_error(text); +// show_error(text); } /* @@ -358,12 +358,15 @@ ReadProc: Thread to read data from COM port */ DWORD ReadProc(LPVOID lpv) { - HANDLE hArray[2]; + HANDLE hArray[3]; + OVERLAPPED osStatus; DWORD dwStoredFlags = 0xFFFFFFFF; // local copy of event flags - DWORD dwFlags = EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING | EV_RLSD; + DWORD dwFlags = EV_CTS | EV_DSR; DWORD dwRead; // bytes actually read DWORD dwRes; // result from WaitForSingleObject + DWORD dwOvRes; + DWORD dwCommEvent; COMSTAT comStat; DWORD dwError; BOOL fWaitingOnStat = FALSE; @@ -375,11 +378,16 @@ DWORD ReadProc(LPVOID lpv) sp = (ser_params_t *) lpv; + osStatus.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + ResetEvent(sp->osRead.hEvent); + ResetEvent(sp->osWrite.hEvent); + // Detect the following events: // Read events (from ReadFile) // Thread exit evetns (from our shutdown functions) hArray[0] = sp->osRead.hEvent; hArray[1] = sp->hThreadExitEvent; + hArray[2] = osStatus.hEvent; while ( !fThreadDone ) { @@ -404,16 +412,33 @@ DWORD ReadProc(LPVOID lpv) } } - if (dwStoredFlags != dwFlags) { + if (dwStoredFlags != dwFlags) + { dwStoredFlags = dwFlags; if (!SetCommMask(sp->hComm, dwStoredFlags)) ErrorReporter("SetCommMask"); } + if (!fWaitingOnStat) { + if (!WaitCommEvent(sp->hComm, &dwCommEvent, &osStatus)) + { + if (GetLastError() == ERROR_IO_PENDING) + fWaitingOnStat = TRUE; + else + // error in WaitCommEvent; abort + break; + } + else + // Check for a monitor window and report change + if (sp->pMonCallback != NULL) + sp->pMonCallback(SER_MON_COM_SIGNAL, 0); + } + + // wait for pending operations to complete - if ( fWaitingOnRead ) + if ( fWaitingOnRead || fWaitingOnStat ) { - dwRes = WaitForMultipleObjects(2, hArray, FALSE, INFINITE); + dwRes = WaitForMultipleObjects(3, hArray, FALSE, INFINITE); switch(dwRes) { // read completed @@ -422,6 +447,7 @@ DWORD ReadProc(LPVOID lpv) { ClearCommError(sp->hComm, &dwError, &comStat); ErrorReporter("GetOverlappedResult (in Reader)"); + dwError = GetLastError(); } else { @@ -444,6 +470,19 @@ DWORD ReadProc(LPVOID lpv) fThreadDone = TRUE; break; + case WAIT_OBJECT_0 + 2: + if (!GetOverlappedResult(sp->hComm, &osStatus, &dwOvRes, FALSE)) + ErrorReporter("GetOverlappedResult Error (status read)"); + else + // Check for a monitor window and report change + if (sp->pMonCallback != NULL) + sp->pMonCallback(SER_MON_COM_SIGNAL, 0); + + // Set fWaitingOnStat flag to indicate that a new + // WaitCommEvent is to be issued. + fWaitingOnStat = FALSE; + break; + default: ErrorReporter("WaitForMultipleObjects(Reader & Status handles)"); break; @@ -473,6 +512,9 @@ DWORD WINAPI WriteProc(LPVOID lpv) hArray[0] = sp->hWriteEvent; hArray[1] = sp->hThreadExitEvent; + + hwArray[0] = sp->osWrite.hEvent; + hwArray[1] = sp->hThreadExitEvent; while ( !fDone ) { dwRes = WaitForMultipleObjects(2, hArray, FALSE, INFINITE); @@ -484,13 +526,10 @@ DWORD WINAPI WriteProc(LPVOID lpv) // write request event case WAIT_OBJECT_0: - hwArray[0] = sp->osWrite.hEvent; - hwArray[1] = sp->hThreadExitEvent; - // Read bytes from sp structure - WaitForSingleObject(sp->hWriteMutex, 2000); +// WaitForSingleObject(sp->hWriteMutex, 2000); - ReleaseMutex(sp->hWriteMutex); +// ReleaseMutex(sp->hWriteMutex); // issue write if (!WriteFile(sp->hComm, sp->tx_buf, 1, &dwWritten, &sp->osWrite)) { @@ -588,7 +627,8 @@ int ser_set_baud(int baud) if (sp.open_flag == 0) return SER_NO_ERROR; - if (setup.com_mode == SETUP_COM_HOST) + if ((setup.com_mode == SETUP_COM_HOST) || + (setup.com_mode == SETUP_COM_OTHER)) { #ifdef WIN32 // Update DCB settings @@ -627,7 +667,8 @@ int ser_close_port(void) if (sp.open_flag == 0) return SER_PORT_NOT_OPEN; - if (setup.com_mode == SETUP_COM_HOST) + if ((setup.com_mode == SETUP_COM_HOST) || + (setup.com_mode == SETUP_COM_OTHER)) { // =================== // Close the Host port @@ -685,7 +726,8 @@ int ser_open_port(void) ser_close_port(); // Check if using HOST port emulation - if (setup.com_mode == SETUP_COM_HOST) + if ((setup.com_mode == SETUP_COM_HOST) || + (setup.com_mode == SETUP_COM_OTHER)) { // ============= // Open the port @@ -767,12 +809,6 @@ int ser_open_port(void) // Update flag indicating port open sp.open_flag = TRUE; } - else if (setup.com_mode == SETUP_COM_OTHER) - { - // ============================================ - // Add code here to support other Host ports - // ============================================ - } // Check for a monitor window and report change if (sp.pMonCallback != NULL) @@ -842,7 +878,8 @@ int ser_set_parity(char parity) if (sp.open_flag == 0) return SER_NO_ERROR; - if (setup.com_mode == SETUP_COM_HOST) + if ((setup.com_mode == SETUP_COM_HOST) || + (setup.com_mode == SETUP_COM_OTHER)) { #ifdef WIN32 // Update DCB settings @@ -890,7 +927,8 @@ int ser_set_bit_size(int bit_size) if (sp.open_flag == 0) return SER_NO_ERROR; - if (setup.com_mode == SETUP_COM_HOST) + if ((setup.com_mode == SETUP_COM_HOST) || + (setup.com_mode == SETUP_COM_OTHER)) { #ifdef WIN32 // Update DCB settings @@ -938,7 +976,8 @@ int ser_set_stop_bits(int stop_bits) if (sp.open_flag == 0) return SER_NO_ERROR; - if (setup.com_mode == SETUP_COM_HOST) + if ((setup.com_mode == SETUP_COM_HOST) || + (setup.com_mode == SETUP_COM_OTHER)) { #ifdef WIN32 // Update DCB settings @@ -1001,7 +1040,8 @@ ser_set_flags: Set the serial port's RTS and DTR flags */ int ser_set_signals(unsigned char flags) { - if (setup.com_mode == SETUP_COM_HOST) + if ((setup.com_mode == SETUP_COM_HOST) || + (setup.com_mode == SETUP_COM_OTHER)) { #ifdef WIN32 // Update DTR flag @@ -1055,7 +1095,8 @@ int ser_get_flags(unsigned char *flags) { long modem_status; - if (setup.com_mode == SETUP_COM_HOST) + if ((setup.com_mode == SETUP_COM_HOST) || + (setup.com_mode == SETUP_COM_OTHER)) { if (sp.open_flag == 0) { @@ -1124,7 +1165,8 @@ int ser_get_signals(unsigned char *flags) { long modem_status; - if (setup.com_mode == SETUP_COM_HOST) + if ((setup.com_mode == SETUP_COM_HOST) || + (setup.com_mode == SETUP_COM_OTHER)) { if (sp.open_flag == 0) { @@ -1142,11 +1184,11 @@ int ser_get_signals(unsigned char *flags) *flags = 0; // Set CTS flag - if ((modem_status & MS_CTS_ON) == 1) + if (modem_status & MS_CTS_ON) *flags |= SER_SIGNAL_CTS; // Set DSR flag - if ((modem_status & MS_DSR_ON) == 1) + if (modem_status & MS_DSR_ON) *flags |= SER_SIGNAL_DSR; // Set RTS flag @@ -1185,7 +1227,8 @@ int ser_read_byte(char* data) } // Check if COM emulation type is Host port - if (setup.com_mode == SETUP_COM_HOST) + if ((setup.com_mode == SETUP_COM_HOST) || + (setup.com_mode == SETUP_COM_OTHER)) { #ifdef WIN32 int new_rxOut; @@ -1242,7 +1285,8 @@ int ser_write_byte(char data) return SER_NO_ERROR; // Check if COM port emulation configured for HOST port - if (setup.com_mode == SETUP_COM_HOST) + if ((setup.com_mode == SETUP_COM_HOST) || + (setup.com_mode == SETUP_COM_OTHER)) { #ifdef WIN32 // Store data in structure From 7b02450cc406a0f67aac14f03eb8c1c6bf6f0e49 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 1 Oct 2004 21:06:32 +0000 Subject: [PATCH 031/327] Changes defines to 1-byte values instead of 2-byte values. --- src/serial.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/serial.h b/src/serial.h index e4c1bf4..4c8806b 100644 --- a/src/serial.h +++ b/src/serial.h @@ -59,13 +59,13 @@ enum { SER_MON_COM_CHANGE_PARITY }; -#define SER_FLAG_TX_EMPTY 0x001 -#define SER_FLAG_OVERRUN 0x002 -#define SER_FLAG_FRAME_ERR 0x004 -#define SER_FLAG_PARITY_ERR 0x008 -#define SER_FLAG_CTS 0x010 -#define SER_FLAG_DSR 0x020 -#define SER_FLAG_RING 0x040 +#define SER_FLAG_TX_EMPTY 0x01 +#define SER_FLAG_OVERRUN 0x02 +#define SER_FLAG_FRAME_ERR 0x04 +#define SER_FLAG_PARITY_ERR 0x08 +#define SER_FLAG_CTS 0x10 +#define SER_FLAG_DSR 0x20 +#define SER_FLAG_RING 0x40 #define SER_SIGNAL_CTS 0x01 #define SER_SIGNAL_DSR 0x02 From 7fe50ebb7db70c69a96613c36d4cff656cc2e1ad Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 1 Oct 2004 21:07:17 +0000 Subject: [PATCH 032/327] Made changes to accomodate difference in #define size of serial constants. --- src/io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io.c b/src/io.c index 227f495..4b8d8fe 100644 --- a/src/io.c +++ b/src/io.c @@ -553,7 +553,7 @@ int inport(uchar port) if (setup.com_mode != SETUP_COM_NONE) ser_get_flags(&flags); flags &= SER_FLAG_CTS | SER_FLAG_DSR; - return(clock_serial_out | (flags>>8)); + return clock_serial_out | flags; case 0xB4: /* 8155 Timer register. LSB of timer counter */ case 0xBC: From 53ed1588ec90918830e4b1c8d8b2959d68152bcb Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 1 Oct 2004 21:08:21 +0000 Subject: [PATCH 033/327] Added support for selecting start & stop characters & displaying delta time. --- src/periph.cpp | 403 +++++++++++++++++++++++++++++++++++++++++++++---- src/periph.h | 20 ++- 2 files changed, 387 insertions(+), 36 deletions(-) diff --git a/src/periph.cpp b/src/periph.cpp index fc58d1e..f9de457 100644 --- a/src/periph.cpp +++ b/src/periph.cpp @@ -74,6 +74,9 @@ typedef struct periph_ctrl_struct Fl_Box* pWordSize; Fl_Box* pStopBits; Fl_Box* pParity; + Fl_Box* pStartChar; + Fl_Box* pStopChar; + Fl_Box* pDeltaTime; Fl_Box* pDTR; Fl_Box* pRTS; Fl_Box* pDSR; @@ -88,6 +91,9 @@ typedef struct periph_ctrl_struct char sStopBits[2]; char sParity[2]; char sComMdm[10]; + char sStartChar[40]; + char sStopChar[40]; + char sDeltaTime[40]; unsigned char cSignal; } com; struct @@ -353,12 +359,17 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); o = new Fl_Box(FL_NO_BOX, 20, 95+MENU_HEIGHT, 50, 15, "Baud Rate:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - o = new Fl_Box(FL_NO_BOX, 20, 120+MENU_HEIGHT, 50, 15, "Word Size:"); + o = new Fl_Box(FL_NO_BOX, 20, 120+MENU_HEIGHT, 50, 15, "Start Char:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - - o = new Fl_Box(FL_NO_BOX, 200, 70+MENU_HEIGHT, 50, 15, "Stop Bits:"); + + o = new Fl_Box(FL_NO_BOX, 180, 70+MENU_HEIGHT, 50, 15, "Word Size:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 180, 95+MENU_HEIGHT, 50, 15, "Parity:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 180, 120+MENU_HEIGHT, 50, 15, "End Char:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - o = new Fl_Box(FL_NO_BOX, 200, 95+MENU_HEIGHT, 50, 15, "Parity:"); + + o = new Fl_Box(FL_NO_BOX, 320, 70+MENU_HEIGHT, 50, 15, "Stop Bits:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); o = new Fl_Box(FL_NO_BOX, 450, 45+MENU_HEIGHT, 50, 15, "RTS:"); @@ -382,17 +393,32 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) 95+MENU_HEIGHT, 50, 15, periph_ctrl.com.sBaud); periph_ctrl.com.pBaud->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - periph_ctrl.com.pWordSize = new Fl_Box(FL_NO_BOX, 100, - 120+MENU_HEIGHT, 50, 15, periph_ctrl.com.sWordSize); + periph_ctrl.com.pStartChar = new Fl_Box(FL_NO_BOX, 100, + 120+MENU_HEIGHT, 60, 15, periph_ctrl.com.sStartChar); + periph_ctrl.com.pStartChar->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + strcpy(periph_ctrl.com.sStartChar, "(Click)"); + + periph_ctrl.com.pWordSize = new Fl_Box(FL_NO_BOX, 260, + 70+MENU_HEIGHT, 50, 15, periph_ctrl.com.sWordSize); periph_ctrl.com.pWordSize->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - periph_ctrl.com.pStopBits = new Fl_Box(FL_NO_BOX, 280, + periph_ctrl.com.pParity = new Fl_Box(FL_NO_BOX, 260, + 95+MENU_HEIGHT, 50, 15, periph_ctrl.com.sParity); + periph_ctrl.com.pParity->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + periph_ctrl.com.pStopChar = new Fl_Box(FL_NO_BOX, 260, + 120+MENU_HEIGHT, 120, 15, periph_ctrl.com.sStopChar); + periph_ctrl.com.pStopChar->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + strcpy(periph_ctrl.com.sStopChar, "(Shift/Right Click)"); + + periph_ctrl.com.pStopBits = new Fl_Box(FL_NO_BOX, 380, 70+MENU_HEIGHT, 50, 15, periph_ctrl.com.sStopBits); periph_ctrl.com.pStopBits->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - periph_ctrl.com.pParity = new Fl_Box(FL_NO_BOX, 280, - 95+MENU_HEIGHT, 50, 15, periph_ctrl.com.sParity); - periph_ctrl.com.pParity->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + periph_ctrl.com.pDeltaTime = new Fl_Box(FL_NO_BOX, 20, + 145+MENU_HEIGHT, 190, 15, periph_ctrl.com.sDeltaTime); + periph_ctrl.com.pDeltaTime->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + strcpy(periph_ctrl.com.sDeltaTime, ""); ser_get_signals(&periph_ctrl.com.cSignal); @@ -541,26 +567,13 @@ T100_ComMon::T100_ComMon(int x, int y, int w, int h) : m_Lines = 0; m_Cols = 0; m_pLastEntry = NULL; - + m_pStartTime = NULL; + m_pStopTime = NULL; } T100_ComMon::~T100_ComMon() { - TcomLogBlock *b = m_log; - TcomLogBlock *n; - - // Delete all TcomLogBlock entries - while (b != NULL) - { - // Save pointer to next TcomLogBlock - n = b->next; - - // Delete this block - delete b; - - // Point to next block - b = n; - } + delete m_log; } void T100_ComMon::Clear(void) @@ -579,6 +592,14 @@ void T100_ComMon::Clear(void) m_Lines = 0; m_Cols = 0; m_pLastEntry = NULL; + m_pStartTime = NULL; + m_pStopTime = NULL; + periph_ctrl.com.sDeltaTime[0] = 0; + periph_ctrl.com.pDeltaTime->label(periph_ctrl.com.sDeltaTime); + strcpy(periph_ctrl.com.sStartChar, "(Click)"); + periph_ctrl.com.pStartChar->label(periph_ctrl.com.sStartChar); + strcpy(periph_ctrl.com.sStopChar, "(Shift/Right Click)"); + periph_ctrl.com.pStopChar->label(periph_ctrl.com.sStopChar); redraw(); } @@ -662,7 +683,7 @@ void T100_ComMon::AddByte(int rx_tx, char byte, char flags) sprintf(string, "%02X", b->entries[b->used].byte); else sprintf(string, "%c", b->entries[b->used].byte); - fl_draw(string, xpos, ypos); + fl_draw(string, xpos, ypos-2); } if (line != m_LastLine) @@ -854,12 +875,32 @@ void T100_ComMon::draw() ypos = (int) (y() + (line+2) * m_Height); } + if (&clb->entries[index] == m_pStartTime) + { + fl_color(FL_GREEN); + fl_rectf(xpos, ypos-(int) m_Height+3, (int) (adder * m_Width), (int) m_Height-1); + fl_color(FL_BLACK); + m_StartTimeLine = line; + if ((clb->entries[index].flags & 0x80) == 0) + m_StartTimeLine++; + m_StartTimeCol = col; + } + else if (&clb->entries[index] == m_pStopTime) + { + fl_color(FL_RED); + fl_rectf(xpos, ypos-(int)m_Height+3, (int) (adder * m_Width), (int) m_Height-1); + fl_color(FL_WHITE); + m_StopTimeLine = line; + if ((clb->entries[index].flags & 0x80) == 0) + m_StopTimeLine++; + m_StopTimeCol = col; + } // Draw the text if (gHexOn) sprintf(string, "%02X", clb->entries[index].byte); else sprintf(string, "%c", clb->entries[index].byte); - fl_draw(string, xpos, ypos); + fl_draw(string, xpos, ypos-2); // Save pointer to this cle for next comparison cle = &clb->entries[index]; @@ -884,3 +925,309 @@ void T100_ComMon::draw() break; } } + +// Handle mouse events, key events, focus events, etc. +int T100_ComMon::handle(int event) +{ + int c, xp, yp, shift; + int line_click, col_click, cnt; + int col, line, adder; + int index, lineIndex; + int xpos, ypos; + char string[4]; + TcomLogBlock *clb; + comLogEntry_t *cle, *prev_cle; + comLogEntry_t *cle_sel; + double delta; + + switch (event) + { + case FL_FOCUS: + m_MyFocus = 1; + break; + + case FL_UNFOCUS: + m_MyFocus = 0; + break; + + case FL_PUSH: + // Get id of mouse button pressed + c = Fl::event_button(); + + // Check if it was the Left Mouse button + if ((c == FL_LEFT_MOUSE) || (c == FL_RIGHT_MOUSE)) + { + // Get X,Y position of button press + xp = Fl::event_x(); + yp = Fl::event_y(); + + // Check if Shift was depressed during the Mouse Button event + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + shift = 1; + else + shift = 0; + + + if (c == FL_RIGHT_MOUSE) + shift = 1; + + // Determine line & col of mouse click + col_click = (int) ((xp - x()) / m_Width); + line_click = (int) ((yp - y()) / m_Height); + + // Get LineStart index + lineIndex = (m_FirstLine + line_click) >> 1; + + // Get comLogEntry of first item on this line + if (lineIndex < m_LineStartCount) + { + clb = m_LineStarts[lineIndex].clb; + index = m_LineStarts[lineIndex].index; + } + else + clb = NULL; + + // Check if mouse was clicked below existing data + if (clb == NULL) + cle_sel = NULL; + + cnt = 0; + col = 0; + cle = NULL; + cle_sel = NULL; + line = lineIndex << 1; + adder = gHexOn ? 3 : 1; + + // Scan through comLogEntries to find this entry + while (clb != NULL) + { + if (index >= clb->used) + break; + + if (col > col_click) + break; + + // Calculate col/line where data should be drawn + if (cle != NULL) + { + // Check if last char was save type as this & advance if it was + if ((cle->flags & 0x80) == (clb->entries[index].flags & 0x80) || + (cnt == 2)) + { + // Add 1 or 3 bytes (2 hex plus space) + col += adder; + cnt = 0; + if (col + adder >= m_Cols) + { + col = 0; + line += 2; + break; + } + } + } + + // Save pointer to this cle for next comparison + cle = &clb->entries[index]; + + // Check if we are on the correct column + if ((col_click >= col) && (col_click < col + adder)) + { + // Check for correct line number + if (cle->flags & 0x80) + { + if (line == line_click) + { + cle_sel = &clb->entries[index]; + break; + } + } + else + { + if (line + 1 == line_click) + { + cle_sel = &clb->entries[index]; + break; + } + } + } + + cnt++; + + // Get location of next byte + if (++index == clb->max) + { + // Get pointer to next clb + if (clb->next == NULL) + // No more data -- break loop + break; + + clb = clb->next; + index = 0; + } + } + + // Check for existing start or stop character + prev_cle = NULL; + if (shift) + { + // Check if for pre-existing stop selection + if (m_pStopTime != NULL) + { + // Check if char is currently displayed + if ((m_StopTimeLine >= m_FirstLine) && + (m_StopTimeLine < m_FirstLine + m_Lines)) + { + xpos = (int) (x() + m_StopTimeCol * m_Width); + ypos = (int) (y() + m_StopTimeLine * m_Height); + prev_cle = m_pStopTime; + line = m_StopTimeLine; + } + } + } + else + { + // Check if for pre-existing stop selection + if (m_pStartTime != NULL) + { + // Check if char is currently displayed + if ((m_StartTimeLine >= m_FirstLine) && + (m_StartTimeLine < m_FirstLine + m_Lines)) + { + xpos = (int) (x() + m_StartTimeCol * m_Width); + ypos = (int) (y() + m_StartTimeLine * m_Height); + prev_cle = m_pStartTime; + line = m_StartTimeLine; + } + } + } + + // "Unselect" previous start or stop char + window()->make_current(); + // Select 12 point Courier font + fl_font(FL_COURIER_BOLD,gFontSize); + if (prev_cle != NULL) + { + // Draw background + fl_color(FL_WHITE); + fl_rectf(xpos, ypos+3, (int) (adder * m_Width), (int) m_Height-1); + + if (line & 0x01) + fl_color(FL_BLUE); + else + fl_color(FL_RED); + + // Draw the text + if (gHexOn) + sprintf(string, "%02X", prev_cle->byte); + else + sprintf(string, "%c", prev_cle->byte); + fl_draw(string, xpos, ypos+(int) m_Height-2); + + // Restore line number of current selection + line = line_click; + } + + // Check if cursor was clicked on valid data + if (cle_sel != NULL) + { + // Check if shift key was pressed during mouse click + if (shift) + { + m_pStopTime = cle_sel; + sprintf(periph_ctrl.com.sStopChar, "%c (%02xh)", cle_sel->byte, cle_sel->byte); + periph_ctrl.com.pStopChar->label(periph_ctrl.com.sStopChar); + m_pStopTime = cle_sel; + m_StopTimeLine = line_click; + m_StopTimeCol = col; + fl_color(FL_RED); + } + else + { + m_pStartTime = cle_sel; + sprintf(periph_ctrl.com.sStartChar, "%c (%02xh)", cle_sel->byte, cle_sel->byte); + periph_ctrl.com.pStartChar->label(periph_ctrl.com.sStartChar); + m_pStartTime = cle_sel; + m_StartTimeLine = line_click; + m_StartTimeCol = col; + } + + if (m_pStartTime != NULL) + { + // Draw the Start selecton box + fl_color(FL_GREEN); + xpos = (int) (x() + m_StartTimeCol * m_Width); + ypos = (int) (y() + m_StartTimeLine * m_Height); + fl_rectf(xpos, ypos+3, (int) (adder * m_Width), (int) m_Height-1); + + // Draw the StartTime text + fl_color(FL_BLACK); + if (gHexOn) + sprintf(string, "%02X", m_pStartTime->byte); + else + sprintf(string, "%c", m_pStartTime->byte); + fl_draw(string, xpos, ypos + (int)m_Height-2); + } + + if (m_pStopTime != NULL) + { + // Draw the Start selecton box + if (m_pStartTime == m_pStopTime) + fl_color(FL_YELLOW); + else + fl_color(FL_RED); + xpos = (int) (x() + m_StopTimeCol * m_Width); + ypos = (int) (y() + m_StopTimeLine * m_Height); + fl_rectf(xpos, ypos+3, (int) (adder * m_Width), (int) m_Height-1); + + // Draw the StartTime text + if (m_pStartTime == m_pStopTime) + fl_color(FL_BLACK); + else + fl_color(FL_WHITE); + if (gHexOn) + sprintf(string, "%02X", m_pStopTime->byte); + else + sprintf(string, "%c", m_pStopTime->byte); + fl_draw(string, xpos, ypos + (int)m_Height-2); + } + } + else + { + if (shift) + { + m_pStopTime = NULL; + strcpy(periph_ctrl.com.sStopChar, "No Data"); + periph_ctrl.com.pStopChar->label(periph_ctrl.com.sStopChar); + } + else + { + m_pStartTime = NULL; + strcpy(periph_ctrl.com.sStartChar, "No Data"); + periph_ctrl.com.pStartChar->label(periph_ctrl.com.sStartChar); + } + } + + // Check if user has selected both the start & stop bytes + if ((m_pStopTime != NULL) && (m_pStartTime != NULL)) + { + delta = (m_pStopTime->time - m_pStartTime->time) * 1000.0; + if ((delta > 1000.0) || (delta < -1000.0)) + sprintf(periph_ctrl.com.sDeltaTime, "Time = %.3f s", delta/1000.0); + else + sprintf(periph_ctrl.com.sDeltaTime, "Time = %.1f ms", delta); + } + else + strcpy(periph_ctrl.com.sDeltaTime, ""); + + periph_ctrl.com.pDeltaTime->label(periph_ctrl.com.sDeltaTime); + } + break; + + default: + Fl_Widget::handle(event); + break; + + } + + return 1; +} diff --git a/src/periph.h b/src/periph.h index 5890fd8..24d7a3e 100644 --- a/src/periph.h +++ b/src/periph.h @@ -49,7 +49,7 @@ class TcomLogBlock public: TcomLogBlock() { next = NULL; entries = new comLogEntry_t[16384]; max = 16384; used = 0; }; - ~TcomLogBlock() { delete entries; }; + ~TcomLogBlock() { if (next != NULL) delete next; delete entries; }; TcomLogBlock *next; struct comLogEntry *entries; @@ -66,22 +66,20 @@ typedef struct lineStart class T100_ComMon : public Fl_Widget { public: - int m_MyFocus; T100_ComMon(int x, int y, int w, int h); ~T100_ComMon(); void AddByte(int rx_tx, char byte, char flags); void CalcLineStarts(void); - int m_FirstLine; void Clear(void); + int m_FirstLine; protected: // virtual int handle(int event); void draw(); + virtual int handle(int event); - - class TcomLogBlock* m_log; - + int m_MyFocus; int m_Cols; int m_Lines; double m_Height; @@ -89,8 +87,14 @@ class T100_ComMon : public Fl_Widget int m_LastLine; int m_LastCol; int m_LastCnt; - comLogEntry_t *m_pLastEntry; - + comLogEntry_t* m_pLastEntry; + comLogEntry_t* m_pStartTime; + comLogEntry_t* m_pStopTime; + int m_StartTimeCol; + int m_StartTimeLine; + int m_StopTimeCol; + int m_StopTimeLine; + TcomLogBlock* m_log; int m_LineStartCount; lineStart_t m_LineStarts[20000]; Fl_Scrollbar* m_pScroll; From 2aae3b9115f5689294fa92d812fe973506a4cae8 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 1 Oct 2004 21:09:12 +0000 Subject: [PATCH 034/327] Fixed bug - error occured when no Host COM port was selected. --- src/setup.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/setup.cpp b/src/setup.cpp index 9f47b0d..2274b57 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -182,7 +182,10 @@ void cb_setup_OK(Fl_Widget* w, void*) // Get COM options // =========================== strcpy(setup.com_cmd, setup_ctrl.com.pCmd->value()); - strcpy(setup.com_port, setup_ctrl.com.pPort->text()); + if (setup_ctrl.com.pPort->text() != NULL) + strcpy(setup.com_port, setup_ctrl.com.pPort->text()); + else + strcpy(setup.com_port, ""); strcpy(setup.com_other, setup_ctrl.com.pOtherName->value()); if (setup_ctrl.com.pNone->value() == 1) From 59564ebe26a754d7b0e5df5256260a58ba4ecdb2 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Mon, 27 Mar 2006 08:13:16 +0000 Subject: [PATCH 035/327] Project sync for version 0.5. Lot's of changes - too many to list. --- GNUmakefile | 93 +- ROMs/{M200rom.bin => T200rom.bin} | Bin 40960 -> 73728 bytes VirtualT.dsp | 100 +- src/VirtualT.h | 11 +- src/cpu.h | 16 +- src/disassemble.cpp | 127 ++- src/display.cpp | 1283 +++++++++++++++++---- src/display.h | 68 +- src/do_instruct.h | 201 ++-- src/doins.c | 11 +- src/doins.h | 6 +- src/file.cpp | 17 +- src/genwrap.h | 20 +- src/intelhex.c | 2 +- src/io.c | 751 +++++++++--- src/io.h | 9 +- src/m100emu.c | 385 ++++--- src/m100emu.h | 18 +- src/m100rom.c | 1710 ++++++++++++++-------------- src/m200rom.c | 990 ++++++++++++++++ src/memedit.cpp | 1758 +++++++++++++++++++++++++++++ src/memedit.h | 90 ++ src/memory.c | 1565 ++++++++++++++++++++++++- src/memory.h | 84 +- src/n8201rom.c | 916 +++++++++++++++ src/periph.cpp | 2 +- src/periph.h | 2 +- src/roms.h | 14 +- src/romstrings.c | 875 ++++++++++++++ src/romstrings.h | 882 +++++++++++++++ src/serial.c | 16 +- src/setup.cpp | 460 +++++++- src/setup.h | 20 +- src/sound.c | 440 ++++++++ src/sound.h | 40 + 35 files changed, 11395 insertions(+), 1587 deletions(-) rename ROMs/{M200rom.bin => T200rom.bin} (55%) create mode 100644 src/m200rom.c create mode 100644 src/memedit.cpp create mode 100644 src/memedit.h create mode 100644 src/n8201rom.c create mode 100644 src/romstrings.c create mode 100644 src/romstrings.h create mode 100644 src/sound.c create mode 100644 src/sound.h diff --git a/GNUmakefile b/GNUmakefile index 9ad8d15..f89b45c 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,44 +1,77 @@ -include $(shell uname).mk -CFLAGS += -O6 -#CFLAGS += -g +CFLAGS += -I $(FLTKDIR) -O6 +CPPFLAGS += -I $(FLTKDIR) +EXECUTABLE = virtualt -FLTKCONFIG ?= fltk-config -CFLAGS += `$(FLTKCONFIG) --cflags --use-images` -LDFLAGS += `$(FLTKCONFIG) --ldstaticflags --use-images` +FLTKCONFIG = $(FLTKDIR)/fltk-config +VPATH = src:obj -m100emu: doins.o io.o genwrap.o display.o m100emu.o disassemble.o file.o memory.o m100rom.o intelhex.o GNUmakefile - gcc -o m100emu doins.o genwrap.o io.o display.o m100emu.o disassemble.o file.o memory.o m100rom.o intelhex.o $(LDFLAGS) +CFLAGS += `$(FLTKCONFIG) --cflags --use-images` +LDFLAGS += `$(FLTKCONFIG) --ldstaticflags --use-images` -m100emu.o: m100emu.c cpu.h doins.h display.h genwrap.h do_instruct.h GNUmakefile - gcc $(CFLAGS) -c m100emu.c -o m100emu.o - -doins.o: doins.c doins.h cpu.h io.h m100emu.h GNUmakefile - gcc $(CFLAGS) -c doins.c -o doins.o +OBJECTS = $(SOURCES:.c=.o) +OBJECTSCPP = $(SOURCESCPP:.cpp=.o) +LIBFILES = $(FLTKDIR)/lib/libfltk.a $(FLTKDIR)/lib/libfltk_images.a -genwrap.o: genwrap.c genwrap.h gen_defs.h GNUmakefile - gcc $(CFLAGS) -c genwrap.c -o genwrap.o -io.o: cpu.h gen_defs.h io.h io.c GNUmakefile - gcc $(CFLAGS) -c io.c -o io.o +# ============================= +# Define all source files below +# ============================= +SOURCES = m100emu.c doins.c genwrap.c serial.c intelhex.c memory.c m100rom.c \ + m200rom.c n8201rom.c romstrings.c sound.c +SOURCESCPP = display.cpp setup.cpp periph.cpp disassemble.cpp file.cpp memedit.cpp -display.o: display.cpp display.h io.h m100emu.h GNUmakefile - g++ $(CFLAGS) -c display.cpp -o display.o -disassemble.o: disassemble.cpp m100emu.h disassemble.h m100rom.h io.h GNUmakefile - g++ $(CFLAGS) -c disassemble.cpp -o disassemble.o +# ======================== +# Rule for all files below +# ======================== +all: $(SOURCES) $(SOURCESCPP) $(EXECUTABLE) -file.o: file.cpp memory.h roms.h intelhex.h m100emu.h GNUmakefile - gcc $(CFLAGS) -c file.cpp -o file.o +$(EXECUTABLE): $(OBJECTS) $(OBJECTSCPP) +ifndef FLTKDIR + @echo "FLTKDIR environment variable must be set first!" +else + cd obj; gcc $(LDFLAGS) $(OBJECTS) $(OBJECTSCPP) $(LIBFILES) -o ../$@ + cd .. +endif -memory.o: memory.c genwrap.h GNUmakefile - gcc $(CFLAGS) -c memory.c -o memory.o -m100rom.o: m100rom.c roms.h GNUmakefile - gcc $(CFLAGS) -c m100rom.c -o m100rom.o +# =============================== +# Rule for compiling source files +# =============================== +.cpp.o: + -mkdir -p obj; g++ $(CPPFLAGS) -c $< -o obj/$@ -intelhex.o: intelhex.c intelhex.h GNUmakefile - gcc $(CFLAGS) -c intelhex.c -o intelhex.o +.c.o: + -mkdir -p obj; gcc $(CFLAGS) -c $< -o obj/$@ + +# ========================================== +# Declare dependencies on header files below +# ========================================== +$(OBJECTS) $(OBJECTSCPP): m100emu.h GNUmakefile VirtualT.h + +disassemble.o: disassemble.h io.h cpu.h periph.h memedit.h romstrings.h +display.o: display.h io.h file.h setup.h periph.h memory.h memedit.h +doins.o: cpu.h io.h +file.o: memory.h roms.h intelhex.h +io.o: cpu.h gen_defs.h io.h serial.h display.h setup.h memory.h +intelhex.o: intelhex.h +m100emu.o: io.h cpu.h soins.h display.h genwrap.h filewrap.h roms.h \ + intelhex.h setup.h memory.h +memedit.o: memedit.h disassemble.h memory.h cpu.h +memory.o: memory.h cpu.h io.h intelhex.h setup.h +periph.o: periph.h serial.h setup.h display.h disassemble.h +serial.o: serial.h setup.h display.h +setup.o: setup.h io.h serial.h memory.h memedit.h +sound.c: sound.h +m100rom.o m102rom.o m200rom.o n8201rom.o romstrings.o: roms.h romstrings.h + + +# ============================= +# Rule to clean all build files +# ============================= clean: - rm *.o - rm m100emu + cd obj; rm *.o; cd .. + rm virtualt + diff --git a/ROMs/M200rom.bin b/ROMs/T200rom.bin similarity index 55% rename from ROMs/M200rom.bin rename to ROMs/T200rom.bin index 50512ecbc176e7a2b2b63272ae06d0e7c2ad4e2b..9f4eccfc1fb91fa6a923d062da104ddf4d5a6aab 100644 GIT binary patch delta 33046 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%0D_kX+b4xc90j4 zgK`o)Ao%KF(*f4)Aa6Xro5smQmuTwP!+^-|(No8WeBlsDOoTf`fwsJp)aTzh9pR{D|S1``|LhTk2FHT4T3}T;yuNHFKX#hPc%nd`T z_!^hNYJ2OTimT^{#~f@<)$VGxyvCh%ijkg{*D}&KYbg4(d^1JAStX^9E87&T3NG%z zv6f@atAngUP{Bo>{9-PRHLnd)CaxOH1egTipW}h~r@+KK#+JWPv760#qY_vXUT8O1 zm%VjR152-`5$XWETSRyS*Z@sPBfJ@;_c&KYfJaY!QNg;aNVth4zo?|yypO9`4J^`& zxx~d>lKvR(4KXzb@jsBs`gU`86S$GmMNsI&_Ht_v-^gL-dc?~6_DEn!_B0as-Y>vw z7aN>uiy$_BX0>_Q3?Br!4o@Joz?^hImKcB=6!JyzEweh(;WmH?XgH$Dj=ORpd}j-> zSx1r}GcY%&$DhmIb2y3|sAMw$(o7zdvoo<~I}SS>Z+EG|%^C1lJ|WCuGoEhwj_e_t zf@-zB(x3uI$y5cbWrUsu##+7?Inr{K@6gO(2Vu2!<%UG?5MZPofE?K-7t-5ld;rGP z*z%o-Ef-NGLaGS3Wvv0(vWwgAfwA>8a^i-O!cR!T0RX^1#05p9Gi@qy+^{`O480|U z6VyH*?*+}z>mc!>OXEjzX(I=>9KP;c{AwPD?Yrv!m}xcz7<*7+nt{FPWK!@qopcbH zg?s|{s%wxa)QP@@sv;#|{SY0kfDbt}D24NC3B{=8Iuc^?m|UVk6sR0i%nsq9gb*B{ zL(-5kM22X%A5z0HnjDH78Wc=JUxyNhRI9ix+*WQo);5J`(_{Hr-cS`GrnGNhD?L>m zkU%&I%YRUa8K`1SAS=2Wf^TQ5=qz7P$VsQ{Olct6?&Gn87GX{mc>{M-R2Qw)xKwK^ zU9$TsDehb&#hux9GO1MQ%AgtF7S+ZM@(*Μn(SML=etVJfW->=sHPPc-4{+ZnNe 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 #define XF_BIT 0x02 +#define OV ((F&0x02)>>1) +#define OV_BIT 0x02 #define PF ((F&0x04)>>2) #define AC ((F&0x10)>>4) +#define TS ((F&0x20)>>5) +#define TS_BIT 0x20 #define ZF ((F&0x40)>>6) #define SF ((F&0x80)>>7) #define RST55MASK (IM&0x01) @@ -99,5 +106,6 @@ extern uchar optROM[ROMSIZE]; #define MEM(x) memory[x] #define MEM16(x) (((ushort)MEM(x))|((ushort)MEM(x+1))<<8) +#define MEMSET(a,v) {if (gReMem) remem_set8(a, v); else if(a>=ROMSIZE) memory[a]=v; } #endif diff --git a/src/disassemble.cpp b/src/disassemble.cpp index 7dad3cf..d34dfbe 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -39,10 +39,14 @@ #include #include +#include "VirtualT.h" #include "m100emu.h" #include "disassemble.h" #include "io.h" +#include "cpu.h" #include "periph.h" +#include "memedit.h" +#include "romstrings.h" Fl_Window *gpDis; @@ -61,34 +65,49 @@ void close_cb(Fl_Widget* w, void*) char * VTDis::m_StrTable[256] = { "NOP", "LXI B,", "STAX B", "INX B", "INR B", "DCR B", "MVI B,", "RLC", "DSUB", "DAD B", "LDAX B", "DCX B", "INR C", "DCR C", "MVI C,", "RRC", + "ASHR", "LXI D,", "STAX D", "INX D", "INR D", "DCR D", "MVI D,", "RAL", "RLDE", "DAD D", "LDAX D", "DCX D", "INR E", "DCR E", "MVI E,", "RAR", + "RIM", "LXI H,", "SHLD ", "INX H", "INR H", "DCR H", "MVI H,", "DAA", "LDEH ", "DAD H", "LHLD ", "DCX H", "INR L", "DCR L", "MVI L,", "CMA", + "SIM", "LXI SP,", "STA ", "INX SP", "INR M", "DCR M", "MVI M,", "STC", "LDES ", "DAD SP", "LDA ", "DCX SP", "INR A", "DCR A", "MVI A,", "CMC", + "MOV B,B", "MOV B,C", "MOV B,D", "MOV B,E", "MOV B,H", "MOV B,L", "MOV B,M", "MOV B,A", "MOV C,B", "MOV C,C", "MOV C,D", "MOV C,E", "MOV C,H", "MOV C,L", "MOV C,M", "MOV C,A", + "MOV D,B", "MOV D,C", "MOV D,D", "MOV D,E", "MOV D,H", "MOV D,L", "MOV D,M", "MOV D,A", "MOV E,B", "MOV E,C", "MOV E,D", "MOV E,E", "MOV E,H", "MOV E,L", "MOV E,M", "MOV E,A", + "MOV H,B", "MOV H,C", "MOV H,D", "MOV H,E", "MOV H,H", "MOV H,L", "MOV H,M", "MOV H,A", "MOV L,B", "MOV L,C", "MOV L,D", "MOV L,E", "MOV L,H", "MOV L,L", "MOV L,M", "MOV L,A", + "MOV M,B", "MOV M,C", "MOV M,D", "MOV M,E", "MOV M,H", "MOV M,L", "HLT", "MOV M,A", "MOV A,B", "MOV A,C", "MOV A,D", "MOV A,E", "MOV A,H", "MOV A,L", "MOV A,M", "MOV A,A", + "ADD B", "ADD C", "ADD D", "ADD E", "ADD H", "ADD L", "ADD M", "ADD A", "ADC B", "ADC C", "ADC D", "ADC E", "ADC H", "ADC L", "ADC M", "ADC A", + "SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB M", "SUB A", "SBB B", "SBB C", "SBB D", "SBB E", "SUB H", "SBB L", "SBB M", "SBB A", + "ANA B", "ANA C", "ANA D", "ANA E", "ANA H", "ANA L", "ANA M", "ANA A", "XRA B", "XRA C", "XRA D", "XRA E", "XRA H", "XRA L", "XRA M", "XRA A", + "ORA B", "ORA C", "ORA D", "ORA E", "ORA H", "ORA L", "ORA M", "ORA A", "CMP B", "CMP C", "CMP D", "CMP E", "CMP H", "CMP L", "CMP M", "CMP A", + "RNZ", "POP B", "JNZ ", "JMP ", "CNZ ", "PUSH B", "ADI ", "RST 0", "RZ", "RET", "JZ ", "-", "CZ ", "CALL ", "ACI ", "RST 1", + "RNC", "POP D", "JNC ", "OUT ", "CNC ", "PUSH D", "SUI ", "RST 2", "RC", "SHLX", "JC ", "IN ", "CC ", "JNX ", "SBI ", "RST 3", + "RPO", "POP H", "JPO ", "XTHL", "CPO ", "PUSH H", "ANI ", "RST 4", "RPE", "PCHL", "JPE ", "XCHG", "CPE ", "LHLX", "XRI ", "RST 5", + "RP", "POP PSW", "JP ", "DI", "CP ", "PUSH PSW", "ORI ", "RST 6", "RM", "SPHL", "JM ", "EI", "CM ", "JX ", "CPI ", "RST 7" }; @@ -143,7 +162,7 @@ Fl_Menu_Item gDis_menuitems[] = { { "Assembler", 0, 0 }, { "Disassembler", 0, 0 }, { "Debugger", 0, 0 }, - { "Memory Editor", 0, 0 }, + { "Memory Editor", 0, cb_MemoryEditor }, { "Peripheral Devices", 0, cb_PeripheralDevices }, { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, 0 }, @@ -194,7 +213,7 @@ void disassembler_cb(Fl_Widget* w, void*) { pDisassembler->SetTextViewer(td); // Give the disassembler something to disassemble - pDisassembler->CopyIntoMem(memory, 32788); + pDisassembler->CopyIntoMem(memory, ROMSIZE); gpDis->resizable(m); gpDis->resizable(td); @@ -222,7 +241,7 @@ Disassembler Class Definition VTDis::VTDis() { m_StartAddress = 0; - m_EndAddress = 32767; + m_EndAddress = ROMSIZE-1; } void VTDis::SetTextViewer(Fl_Text_Editor *pTextViewer) @@ -237,7 +256,7 @@ void VTDis::Disassemble() int len; int table; char line[200]; - char arg[6]; + char arg[60]; int addr; int rst7 = 0; int rst1 = 0; @@ -256,7 +275,7 @@ void VTDis::Disassemble() if (m_pRom->pFuns[x].addr == c) { strcpy(line, "\n; ======================================================\n; "); - strcat(line, m_pRom->pFuns[x].desc); + strcat(line, gDisStrings[m_pRom->pFuns[x].strnum].desc); strcat(line, "\n; ======================================================\n"); // Add line to Edit Buffer tb->append(line); @@ -337,6 +356,73 @@ void VTDis::Disassemble() } } } + // Modified strings are those that start with a 0x80 and ends + // when the next string is found (the next 0x80). All the + // BASIC keywords are stored this way + else if (m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING2) + { + int next; + int last = c + m_pRom->pTables[x].size; + int str_active = 0; + for (next = c; next < last; next++) + { + if (m_memory[next] == 0) + { + sprintf(line, "%04XH DB 00H\n", next); + tb->append(line); + line[0] = 0; + continue; + } + if ((m_memory[next] & 0x80) && (str_active)) + { + sprintf(arg, "\",'%c' or 80H", m_memory[next] & 0x7F); + strcat(line, arg); + sprintf(arg, ", %02XH\n", m_memory[next+1]); + strcat(line, arg); +// if ((m_memory[next-1] & 0x80) == 0) +// strcat(line, "\""); +// strcat(line, "\n"); + tb->append(line); + line[0]=0; + str_active = 0; + next++; + continue; + } + if (!str_active) + { + if (m_memory[next] & 0x80) + { + sprintf(line, "%04XH DB '%c' OR 80H", next, m_memory[next] & 0x7F); + sprintf(arg, ", %02XH\n", m_memory[next+1]); + strcat(line, arg); + tb->append(line); + line[0]=0; + str_active = 0; + next++; + continue; + } + else + { + sprintf(line, "%04XH DB \"%c", next, m_memory[next]); + str_active = 1; + } + } + else + { + sprintf(arg, "%c", m_memory[next]); + strcat(line, arg); + } + + if (next + 1 == last) + { + if (m_memory[next-1] & 0x80 == 0) + strcat(line, "\""); + strcat(line, "\n\n"); + tb->append(line); + line[0] = 0; + } + } + } // A string is one that ends with NULL (0x00) else if (m_pRom->pTables[x].type == TABLE_TYPE_STRING) { @@ -358,9 +444,18 @@ void VTDis::Disassemble() } else if (!str_active) { - sprintf(line, "%04XH DB \"%c", next, m_memory[next]); - quote_active = 1; - str_active = 1; + if (m_memory[next] == 0) + { + sprintf(line, "%04XH DB 00H\n", next); + tb->append(line); + line[0]=0; + } + else + { + sprintf(line, "%04XH DB \"%c", next, m_memory[next]); + quote_active = 1; + str_active = 1; + } } else { @@ -374,11 +469,21 @@ void VTDis::Disassemble() sprintf(arg, ",%02XH", m_memory[next]); } else - sprintf(arg, "%c", m_memory[next]); + { + if (!quote_active) + sprintf(arg, ",\"%c", m_memory[next]); + else if (m_memory[next] == '"') + sprintf(arg, "\\%c", m_memory[next]); + else + sprintf(arg, "%c", m_memory[next]); + quote_active = 1; + } strcat(line, arg); } if ((next+1 == last) && (m_memory[next] != 0)) { + if (quote_active) + strcat(line, "\""); strcat(line, "\n"); tb->append(line); line[0]=0; @@ -633,7 +738,7 @@ void VTDis::Disassemble() for (i = 0; i < len; i++) strcat(line, " "); strcat(line, "; "); - strcat(line, m_pRom->pVars[x].desc); + strcat(line, gDisStrings[m_pRom->pVars[x].strnum].desc); break; } @@ -652,7 +757,7 @@ void VTDis::Disassemble() for (i = 0; i < len; i++) strcat(line, " "); strcat(line, "; "); - strcat(line, m_pRom->pFuns[x].desc); + strcat(line, gDisStrings[m_pRom->pFuns[x].strnum].desc); break; } diff --git a/src/display.cpp b/src/display.cpp index a264253..234ef60 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -34,12 +34,12 @@ #include #include #include -#include +#include #include #include //Added by J. VERNET for pref files // see also cb_xxxxxx -#include +#include @@ -53,22 +53,33 @@ #include "file.h" #include "setup.h" #include "periph.h" +#include "memory.h" +#include "memedit.h" + +extern "C" { +extern RomDescription_t gM100_Desc; +extern RomDescription_t gM200_Desc; +extern RomDescription_t gN8201_Desc; +extern RomDescription_t *gStdRomDesc; +} -Fl_Window *MainWin = NULL; -T100_Disp *gpDisp; -Fl_Box *gpCode, *gpGraph, *gpKey, *gpSpeed, *gpCaps, *gpKeyInfo; -Fl_Menu_Bar *Menu; -Fl_Preferences virtualt_prefs(Fl_Preferences::USER, "virtualt.", "virtualt" ); -char gsMenuROM[40]; -char gDelayedError[128] = {0}; +Fl_Window *MainWin = NULL; +T100_Disp *gpDisp; +Fl_Box *gpCode, *gpGraph, *gpKey, *gpSpeed, *gpCaps, *gpKeyInfo; +Fl_Menu_Bar *Menu; +Fl_Preferences virtualt_prefs(Fl_Preferences::USER, "virtualt.", "virtualt" ); +char gsMenuROM[40]; +char gDelayedError[128] = {0}; -int MultFact = 3; -int DisplayMode = 1; -int SolidChars = 0; +int MultFact = 3; +int DisplayMode = 1; +int SolidChars = 0; +int DispHeight = 64; -int gRectsize = 2; -int gXoffset; -int gYoffset; +int gRectsize = 2; +int gXoffset; +int gYoffset; +void switch_model(int model); char *gSpKeyText[] = { "SHIFT", @@ -137,19 +148,32 @@ void close_disp_cb(Fl_Widget* w, void*) } } +/* +===================================================================== +resize_window: This function resizes the main window and repositions + all of the status windows. The new size of the + window is determined by the following values: + + gModel, MultFact, DisplayMode +===================================================================== +*/ void resize_window() { + if (gModel == MODEL_T200) + DispHeight = 128; + else + DispHeight = 64; MainWin->resize(MainWin->x(), MainWin->y(), 240*MultFact + - 90*DisplayMode+2,64*MultFact + 50*DisplayMode + MENU_HEIGHT + 22); + 90*DisplayMode+2,DispHeight*MultFact + 50*DisplayMode + MENU_HEIGHT + 22); Menu->resize(0, 0, 240*MultFact + 90*DisplayMode+2, MENU_HEIGHT-2); - gpDisp->resize(0, MENU_HEIGHT, 240*MultFact + 90*DisplayMode+2, 64*MultFact + gpDisp->resize(0, MENU_HEIGHT, 240*MultFact + 90*DisplayMode+2, DispHeight*MultFact + 50*DisplayMode+2); - gpGraph->resize(0, MENU_HEIGHT+64*MultFact + 50*DisplayMode+2, 60, 20); - gpCode->resize(60, MENU_HEIGHT+64*MultFact + 50*DisplayMode+2, 60, 20); - gpCaps->resize(120, MENU_HEIGHT+64*MultFact + 50*DisplayMode+2, 60, 20); - gpKey->resize(180, MENU_HEIGHT+64*MultFact + 50*DisplayMode+2, 120, 20); - gpSpeed->resize(300, MENU_HEIGHT+64*MultFact + 50*DisplayMode+2, 60, 20); - gpKeyInfo->resize(360, MENU_HEIGHT+64*MultFact + 50*DisplayMode+2, + gpGraph->resize(0, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 60, 20); + gpCode->resize(60, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 60, 20); + gpCaps->resize(120, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 60, 20); + gpKey->resize(180, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 120, 20); + gpSpeed->resize(300, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 60, 20); + gpKeyInfo->resize(360, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, MainWin->w()-360, 20); gRectsize = MultFact - (1 - SolidChars); @@ -244,10 +268,14 @@ void cb_reset (Fl_Widget* w, void*) void cb_UnloadOptRom (Fl_Widget* w, void*) { + char option_name[32]; + gsOptRomFile[0] = 0; // Update user preferences - virtualt_prefs.set("OptRomFile",gsOptRomFile); + get_model_string(option_name, gModel); + strcat(option_name, "_OptRomFile"); + virtualt_prefs.set(option_name, gsOptRomFile); // Clear menu strcpy(gsMenuROM, "No ROM loaded"); @@ -260,21 +288,58 @@ void cb_UnloadOptRom (Fl_Widget* w, void*) } +void cb_M100(Fl_Widget* w, void*) +{ + /* Switch to new model */ + switch_model(MODEL_M100); +} +void cb_M102(Fl_Widget* w, void*) +{ + /* Switch to new model */ + switch_model(MODEL_M102); +} +void cb_M200(Fl_Widget* w, void*) +{ + /* Switch to new model */ + switch_model(MODEL_T200); +} +//void cb_M10(Fl_Widget* w, void*) +//{ + /* Switch to new model */ +// switch_model(MODEL_M10); +//} +void cb_PC8201(Fl_Widget* w, void*) +{ + /* Switch to new model */ + switch_model(MODEL_PC8201); +} +void cb_PC8300(Fl_Widget* w, void*) +{ + /* Switch to new model */ + switch_model(MODEL_PC8300); +} +/* +======================================================= +cb_help: This routine displays the Help Subsystem +======================================================= +*/ void cb_help (Fl_Widget* w, void*) { -/* -#ifndef WIN32 + Fl_Help_Dialog *HelpWin; HelpWin = new Fl_Help_Dialog(); - HelpWin->load("./help.htm"); + HelpWin->load("help.htm"); HelpWin->show(); -#endif -*/ } +/* +========================================================== +cb_about: This callback routine displays the about box +========================================================== +*/ void cb_about (Fl_Widget* w, void*) { @@ -292,11 +357,11 @@ void cb_about (Fl_Widget* w, void*) o->labelfont(8); o->labelsize(18); } - { Fl_Box* o = new Fl_Box(20, 170, 335, 35, "Stephen Hurd"); + { Fl_Box* o = new Fl_Box(20, 170, 335, 35, "Ken Pettit"); o->labelfont(8); o->labelsize(18); } - { Fl_Box* o = new Fl_Box(15, 190, 340, 35, "Ken Pettit"); + { Fl_Box* o = new Fl_Box(15, 190, 340, 35, "Stephen Hurd"); o->labelfont(8); o->labelsize(18); } @@ -324,6 +389,124 @@ void cb_about (Fl_Widget* w, void*) o->show(); } + + +Fl_Menu_Item menuitems[] = { + { "&File", 0, 0, 0, FL_SUBMENU }, + { "Load file from HD", 0, cb_LoadFromHost, 0 }, + { "Save file to HD", 0, cb_SaveToHost, 0, 0 }, + { "Save Options", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER }, + { "Save Basic as ASCII", 0, cb_save_basic, (void *) 1, FL_MENU_TOGGLE }, + { "Save CO as HEX", 0, cb_save_co, (void *) 2, FL_MENU_TOGGLE }, + { 0 }, + { "Load RAM...", 0, cb_LoadRam, 0 }, + { "Save RAM...", 0, cb_SaveRam, 0, FL_MENU_DIVIDER }, + { "E&xit", FL_CTRL + 'q', close_disp_cb, 0 }, + { 0 }, + + { "&Emulation", 0, 0, 0, FL_SUBMENU }, + { "Reset", 0, cb_reset, 0, FL_MENU_DIVIDER }, + { "Model", 0, 0, 0, FL_SUBMENU } , + { "M100", 0, cb_M100, (void *) 1, FL_MENU_RADIO | FL_MENU_VALUE }, + { "M102", 0, cb_M102, (void *) 2, FL_MENU_RADIO }, + { "T200", 0, cb_M200, (void *) 3, FL_MENU_RADIO }, + { "PC-8201", 0, cb_PC8201, (void *) 4, FL_MENU_RADIO }, +// { "8300", 0, cb_PC8300, (void *) 5, FL_MENU_RADIO }, + { 0 }, + { "Speed", 0, 0, 0, FL_SUBMENU }, + { "2.4 MHz", 0, rspeed, (void *) 1, FL_MENU_RADIO | FL_MENU_VALUE }, + { "Max Speed", 0, fspeed, (void *) 1, FL_MENU_RADIO }, + { 0 }, + { "Display", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER}, + { "1x", 0, cb_1x, (void *) 1, FL_MENU_RADIO }, + { "2x", 0, cb_2x, (void *) 2, FL_MENU_RADIO }, + { "3x", 0, cb_3x, (void *) 3, FL_MENU_RADIO | FL_MENU_VALUE}, + { "4x", 0, cb_4x, (void *) 4, FL_MENU_RADIO | FL_MENU_DIVIDER}, + { "Framed", 0, cb_framed, (void *) 1, FL_MENU_TOGGLE|FL_MENU_VALUE }, + { "Solid Chars", 0, cb_solidchars, (void *) 1, FL_MENU_TOGGLE}, + { 0 }, + { "Peripheral Setup...", 0, cb_PeripheralSetup, 0, 0 }, + { "Memory Options...", 0, cb_MemorySetup, 0, FL_MENU_DIVIDER }, + { "Option ROM", 0, 0, 0, FL_SUBMENU }, + { gsMenuROM, 0, 0, 0, FL_MENU_DIVIDER }, + { "Load ROM...", 0, cb_LoadOptRom, 0, 0 }, + { "Unload ROM", 0, cb_UnloadOptRom, 0, 0 }, + { 0 }, + { 0 }, + + { "&Tools", 0, 0, 0, FL_SUBMENU }, + { "CPU Registers", 0, 0 }, + { "Assembler", 0, 0 }, + { "Disassembler", 0, disassembler_cb }, + { "Debugger", 0, 0 }, + { "Memory Editor", 0, cb_MemoryEditor }, + { "Peripheral Devices", 0, cb_PeripheralDevices }, + { "Simulation Log Viewer", 0, 0 }, + { "Model T File Viewer", 0, 0 }, + { "BASIC Debugger", 0, 0 }, + { 0 }, + { "&Help", 0, 0, 0, FL_SUBMENU }, + { "Help", 0, cb_help }, + { "About VirtualT", 0, cb_about }, + { 0 }, + + { 0 } +}; + +/* +============================================================================ +switch_model: This function is called by the menu callback routines that + manage selection of the current model being emulated. It + saves the RAM for the current model, changes the to new + model, resizes the display, then reinitializes the system. +============================================================================ +*/ +void switch_model(int model) +{ + /* Save RAM for current emulation */ + save_ram(); + + /* Switch to new model */ + gModel = model; + virtualt_prefs.set("Model",gModel); + + init_pref(); + + /* Load Memory preferences */ + load_memory_preferences(); + init_mem(); + + /* Set pointer to ROM Description */ + if (gModel == MODEL_T200) + gStdRomDesc = &gM200_Desc; + else if (gModel == MODEL_PC8201) + gStdRomDesc = &gN8201_Desc; + else + gStdRomDesc = &gM100_Desc; + + /* Clear the LCD */ + gpDisp->Clear(); + + delete MainWin; + init_display(); + + /* Resize the window in case of size difference */ + resize_window(); + + /* Re-initialize the CPU */ + init_cpu(); + + /* Update Memory Editor window if any */ + cb_MemoryEditorUpdate(); +} + + + +/* +======================================================= +T100:Disp: This is the class construcor +======================================================= +*/ T100_Disp::T100_Disp(int x, int y, int w, int h) : Fl_Widget(x, y, w, h) { @@ -338,26 +521,66 @@ T100_Disp::T100_Disp(int x, int y, int w, int h) : m_MyFocus = 0; } +/* +========================================================== +Command: This function processes commands sent to + Model 100 LCD subsystem. +========================================================== +*/ +void T100_Disp::Command(int instruction, uchar data) +{ +} + +/* +================================================================= +Clear: This routine clears the "LCD" +================================================================= +*/ +void T100_Disp::Clear(void) +{ + int driver; + + for (driver = 0; driver < 10; driver++) + { + for (int c = 0; c < 256; c++) + lcd[driver][c] = 0; + } +} + +/* +================================================================= +drawpixel: This routine is called by the system to draw a single + black pixel on the "LCD". +================================================================= +*/ // Draw the black pixels on the LCD __inline void drawpixel(int x, int y, int color) { + // Check if the pixel color is black and draw if it is if (color) fl_rectf(x*MultFact + gXoffset,y*MultFact + gYoffset,gRectsize,gRectsize); } - -// Redraw the whole LCD -void T100_Disp::draw() +/* +================================================================= +draw_static: This routine draws the static portions of the LCD, + such as erasing the background, drawing function + key labls, etc. +================================================================= +*/ +void T100_Disp::draw_static() { int c; int width; int x_pos, inc, start, y_pos; int xl_start, xl_end, xr_start, xr_end; + int num_labels; // Draw gray "screen" fl_color(FL_GRAY); fl_rectf(x(),y(),w(),h()); + /* Check if the user wants the display "framed" */ if (DisplayMode == 1) { // Color for outer border @@ -367,33 +590,34 @@ void T100_Disp::draw() fl_rectf(x(),y(),240*MultFact+92,5); // Draw border along the bottom - fl_rectf(x(),y()+64*MultFact+45,240*MultFact+92,5); + fl_rectf(x(),y()+DispHeight*MultFact+45,240*MultFact+92,5); // Draw border along the left - fl_rectf(x(),y()+5,5,64*MultFact+42); + fl_rectf(x(),y()+5,5,DispHeight*MultFact+42); // Draw border along the right - fl_rectf(x()+240*MultFact+87,y()+5,5,64*MultFact+42); + fl_rectf(x()+240*MultFact+87,y()+5,5,DispHeight*MultFact+42); // Color for inner border fl_color(FL_BLACK); - + // Draw border along the top fl_rectf(x()+5,y()+5,240*MultFact+42,20); // Draw border along the bottom - fl_rectf(x()+5,y()+64*MultFact+27,240*MultFact+82,20); + fl_rectf(x()+5,y()+DispHeight*MultFact+27,240*MultFact+82,20); // Draw border along the left - fl_rectf(x()+5,y()+5,40,64*MultFact+32); + fl_rectf(x()+5,y()+5,40,DispHeight*MultFact+32); // Draw border along the right - fl_rectf(x()+240*MultFact+47,y()+5,40,64*MultFact+32); + fl_rectf(x()+240*MultFact+47,y()+5,40,DispHeight*MultFact+32); width = w() - 90; - inc = width/8; + num_labels = gModel == MODEL_PC8201 ? 5 : 8; + inc = width / num_labels; start = 28 + width/16 + (4-MultFact)*2; fl_color(FL_WHITE); fl_font(FL_COURIER,12); @@ -406,7 +630,7 @@ void T100_Disp::draw() xr_end = 12 + 7*MultFact; // Draw function key labels - for (c = 0; c < 8; c++) + for (c = 0; c < num_labels; c++) { // Draw text x_pos = start + inc*c; @@ -427,12 +651,24 @@ void T100_Disp::draw() } } } +} +/* +================================================================= +draw: This routine draws the entire LCD. This is a member + function of Fl_Window. +================================================================= +*/ +void T100_Disp::draw() +{ int x=0; int y=0; int driver, col, row; uchar value; + /* Draw static background stuff */ + draw_static(); + for (driver = 0; driver < 10; driver++) { for (row = 0; row < 4; row++) @@ -521,79 +757,24 @@ void T100_Disp::SetByte(int driver, int col, uchar value) // Fl::wait(0); // } } - - -Fl_Menu_Item menuitems[] = { - { "&File", 0, 0, 0, FL_SUBMENU }, - { "Load file from HD", 0, cb_LoadFromHost, 0 }, - { "Save file to HD", 0, cb_SaveToHost, 0, 0 }, - { "Save Options", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER }, - { "Save Basic as ASCII", 0, cb_save_basic, (void *) 1, FL_MENU_TOGGLE }, - { "Save CO as HEX", 0, cb_save_co, (void *) 2, FL_MENU_TOGGLE }, - { 0 }, - { "Load RAM...", 0, cb_LoadRam, 0 }, - { "Save RAM...", 0, cb_SaveRam, 0, FL_MENU_DIVIDER }, - { "E&xit", FL_CTRL + 'q', close_disp_cb, 0 }, - { 0 }, - - { "&Emulation", 0, 0, 0, FL_SUBMENU }, - { "Reset", 0, cb_reset, 0, FL_MENU_DIVIDER }, - { "Model", 0, 0, 0, FL_SUBMENU } , - { "M100", 0, 0, (void *) 1, FL_MENU_RADIO | FL_MENU_VALUE }, - { "M102", 0, 0, (void *) 2, FL_MENU_RADIO }, - { "T200", 0, 0, (void *) 3, FL_MENU_RADIO }, - { 0 }, - { "Speed", 0, 0, 0, FL_SUBMENU }, - { "2.4 MHz", 0, rspeed, (void *) 1, FL_MENU_RADIO | FL_MENU_VALUE }, - { "Max Speed", 0, fspeed, (void *) 1, FL_MENU_RADIO }, - { 0 }, - { "Display", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER}, - { "1x", 0, cb_1x, (void *) 1, FL_MENU_RADIO }, - { "2x", 0, cb_2x, (void *) 2, FL_MENU_RADIO }, - { "3x", 0, cb_3x, (void *) 3, FL_MENU_RADIO | FL_MENU_VALUE}, - { "4x", 0, cb_4x, (void *) 4, FL_MENU_RADIO | FL_MENU_DIVIDER}, - { "Framed", 0, cb_framed, (void *) 1, FL_MENU_TOGGLE|FL_MENU_VALUE }, - { "Solid Chars", 0, cb_solidchars, (void *) 1, FL_MENU_TOGGLE}, - { 0 }, - { "Peripheral Setup...", 0, cb_PeripheralSetup, 0, FL_MENU_DIVIDER }, - { "Option ROM", 0, 0, 0, FL_SUBMENU }, - { gsMenuROM, 0, 0, 0, FL_MENU_DIVIDER }, - { "Load ROM...", 0, cb_LoadOptRom, 0, 0 }, - { "Unload ROM", 0, cb_UnloadOptRom, 0, 0 }, - { 0 }, - { 0 }, - - { "&Tools", 0, 0, 0, FL_SUBMENU }, - { "CPU Registers", 0, 0 }, - { "Assembler", 0, 0 }, - { "Disassembler", 0, disassembler_cb }, - { "Debugger", 0, 0 }, - { "Memory Editor", 0, 0 }, - { "Peripheral Devices", 0, cb_PeripheralDevices }, - { "Simulation Log Viewer", 0, 0 }, - { "Model T File Viewer", 0, 0 }, - { "BASIC Debugger", 0, 0 }, - { 0 }, - { "&Help", 0, 0, 0, FL_SUBMENU }, - { "Help", 0, cb_help }, - { "About VirtualT", 0, cb_about }, - { 0 }, - - { 0 } -}; - // read Pref File // J. VERNET -void initpref(void) +void init_pref(void) { + char option_name[32]; + virtualt_prefs.get("fullspeed",fullspeed,0); virtualt_prefs.get("MultFact",MultFact,3); virtualt_prefs.get("DisplayMode",DisplayMode,1); virtualt_prefs.get("SolidChars",SolidChars,0); virtualt_prefs.get("BasicSaveMode",BasicSaveMode,0); virtualt_prefs.get("COSaveMode",COSaveMode,0); - virtualt_prefs.get("OptRomFile",gsOptRomFile,"", 256); + virtualt_prefs.get("Model",gModel, MODEL_M100); + + get_model_string(option_name, gModel); + strcat(option_name, "_OptRomFile"); + virtualt_prefs.get(option_name,gsOptRomFile,"", 256); if (strlen(gsOptRomFile) == 0) { @@ -605,24 +786,34 @@ void initpref(void) } } // Create the main display window and all children (status, etc.) -void initdisplay(void) +void init_display(void) { int mIndex; + int i; - MainWin = new Fl_Window(240*MultFact + 90*DisplayMode+2,64*MultFact + + if (gModel == MODEL_T200) + DispHeight = 128; + else + DispHeight = 64; + MainWin = new Fl_Window(240*MultFact + 90*DisplayMode+2,DispHeight*MultFact + 50*DisplayMode + MENU_HEIGHT + 22, "Virtual T"); Menu = new Fl_Menu_Bar(0, 0, 240*MultFact + 90*DisplayMode+2, MENU_HEIGHT-2); - gpDisp = new T100_Disp(0, MENU_HEIGHT, 240*MultFact + 90*DisplayMode+2, - 64*MultFact + 50*DisplayMode+2); + if (gModel == MODEL_T200) + gpDisp = new T200_Disp(0, MENU_HEIGHT, 240*MultFact + 90*DisplayMode+2, + DispHeight*MultFact + 50*DisplayMode+2); + else + gpDisp = new T100_Disp(0, MENU_HEIGHT, 240*MultFact + 90*DisplayMode+2, + DispHeight*MultFact + 50*DisplayMode+2); MainWin->callback(close_disp_cb); Menu->menu(menuitems); // Treat Values read in pref files // J. VERNET -// Be careful, if order or add to Emulation Menu, this code need to be changed. + //================================================== // Update Speed menu item if not default value + //================================================== if(fullspeed==1) { mIndex = 0; @@ -632,14 +823,16 @@ void initdisplay(void) menuitems[mIndex].flags= FL_MENU_RADIO; } + //================================================== // Update Display Size from preference + //================================================== mIndex = 0; // Find first display size menu item while (menuitems[mIndex].callback_ != cb_1x) mIndex++; mIndex--; - for(int i=1;i<5;i++) + for(i=1;i<5;i++) { if(i==MultFact) if(i==4) @@ -651,7 +844,29 @@ void initdisplay(void) else menuitems[i+mIndex].flags=FL_MENU_RADIO; } + //================================================== + // Update Model selection + //================================================== + mIndex = 0; + // Find first display size menu item + while (menuitems[mIndex].callback_ != cb_M100) + mIndex++; + + for(i=MODEL_M100;i<=MODEL_PC8201;i++) + { + if(i==gModel) + if(i==MODEL_PC8300) + menuitems[i+mIndex].flags=FL_MENU_RADIO | FL_MENU_VALUE | FL_MENU_DIVIDER; + else menuitems[i+mIndex].flags=FL_MENU_RADIO | FL_MENU_VALUE; + else + if(i==MODEL_PC8300) + menuitems[i+mIndex].flags=FL_MENU_RADIO | FL_MENU_DIVIDER; + else menuitems[i+mIndex].flags=FL_MENU_RADIO; + } + + //================================================== // Update DisplayMode parameter + //================================================== if(DisplayMode==0) { mIndex = 0; @@ -660,7 +875,11 @@ void initdisplay(void) menuitems[mIndex].flags=FL_MENU_TOGGLE; } - // Update SolidChars menu item + /* + ================================================== + Update SolidChars menu item + ================================================== + */ if(SolidChars==1) { mIndex = 0; @@ -669,7 +888,11 @@ void initdisplay(void) menuitems[mIndex].flags=FL_MENU_TOGGLE|FL_MENU_VALUE; } - // Update BasicSaveMode parameter + /* + ================================================== + Update BasicSaveMode parameter + ================================================== + */ if(BasicSaveMode==1) { mIndex = 0; @@ -678,7 +901,11 @@ void initdisplay(void) menuitems[mIndex].flags=FL_MENU_TOGGLE|FL_MENU_VALUE; } - // Update COSaveMode parameter + /* + ================================================== + Update COSaveMode parameter + ================================================== + */ if(COSaveMode==1) { mIndex = 0; @@ -687,25 +914,30 @@ void initdisplay(void) menuitems[mIndex].flags=FL_MENU_TOGGLE|FL_MENU_VALUE; } - gpGraph = new Fl_Box(FL_DOWN_BOX,0, MENU_HEIGHT+64*MultFact + + /* + ======================================== + Create Status boxes for various things + ======================================== + */ + gpGraph = new Fl_Box(FL_DOWN_BOX,0, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 60, 20,"GRAPH"); gpGraph->labelsize(10); gpGraph->deactivate(); - gpCode = new Fl_Box(FL_DOWN_BOX,60, MENU_HEIGHT+64*MultFact + + gpCode = new Fl_Box(FL_DOWN_BOX,60, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 60, 20,"CODE"); gpCode->labelsize(10); gpCode->deactivate(); - gpCaps = new Fl_Box(FL_DOWN_BOX,120, MENU_HEIGHT+64*MultFact + + gpCaps = new Fl_Box(FL_DOWN_BOX,120, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 60, 20,"CAPS"); gpCaps->labelsize(10); gpCaps->deactivate(); - gpKey = new Fl_Box(FL_DOWN_BOX,180, MENU_HEIGHT+64*MultFact + + gpKey = new Fl_Box(FL_DOWN_BOX,180, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 120, 20,""); gpKey->labelsize(10); - gpSpeed = new Fl_Box(FL_DOWN_BOX,300, MENU_HEIGHT+64*MultFact + + gpSpeed = new Fl_Box(FL_DOWN_BOX,300, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 60, 20,""); gpSpeed->labelsize(10); - gpKeyInfo = new Fl_Box(FL_DOWN_BOX,360, MENU_HEIGHT+64*MultFact + + gpKeyInfo = new Fl_Box(FL_DOWN_BOX,360, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, MainWin->w()-360, 20, "F9:Label F10:Print F11:Paste F12:Pause"); gpKeyInfo->labelsize(10); @@ -716,23 +948,27 @@ void initdisplay(void) if (gRectsize == 0) gRectsize = 1; + /* End the Window and show it */ MainWin->end(); MainWin->show(); - //Fl::wait(); - Fl::check(); + /* Check for Fl_Window event */ + Fl::check(); + /* Check if an error occured prior to Window generation ... */ + /* ...and display it now if any */ if (strlen(gDelayedError) != 0) + { fl_alert(gDelayedError); - + gDelayedError[0] = '\0'; + } } char label[40]; void display_cpu_speed(void) { - sprintf(label, "%4.1f Mhz", cpu_speed + .05); Fl::check(); gpSpeed->label(label); @@ -778,6 +1014,12 @@ void T100_Disp::PowerDown() int x; int col; int driver, column; + int addr; + + addr = 0x7711; + if (gModel == MODEL_PC8201) + addr = 0x78B7; + for (driver = 0; driver < 10; driver++) for (col = 0; col < 256; col++) lcd[driver][col] = 0; @@ -787,7 +1029,7 @@ void T100_Disp::PowerDown() col = 20 - strlen(msg) / 2; for (x = 0; x < (int) strlen(msg); x++) { - int mem_index = 0x7711 + (msg[x] - ' ')*5; + int mem_index = addr + (msg[x] - ' ')*5; column = col++ * 6; for (int c = 0; c < 6; c++) { @@ -804,7 +1046,7 @@ void T100_Disp::PowerDown() col = 20 - strlen(msg2) / 2; for (x = 0; x < (int) strlen(msg2); x++) { - int mem_index = 0x7711 + (msg2[x] - ' ')*5; + int mem_index = addr + (msg2[x] - ' ')*5; column = col++ * 6; for (int c = 0; c < 6; c++) { @@ -819,9 +1061,9 @@ void T100_Disp::PowerDown() } // Handle mouse events, key events, focus events, etc. +char keylabel[128]; int T100_Disp::handle(int event) { - char label[128]; char keystr[10]; char isSpecialKey = 1; int c; @@ -976,49 +1218,179 @@ int T100_Disp::handle(int event) gKeyStates[key] = 0; if (key == 0x20) gSpecialKeys |= MT_SPACE; - if (key == ']') + + /* + ========================================= + ========================================= + */ + if (gModel != MODEL_PC8201) { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (key == ']') { - gSpecialKeys |= MT_GRAPH; - gSpecialKeys &= ~MT_SHIFT; - gKeyStates[']'] = 0; - gKeyStates['0'] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys |= MT_GRAPH; + gSpecialKeys &= ~MT_SHIFT; + gKeyStates[']'] = 0; + gKeyStates['0'] = 0; + } + else + { + gSpecialKeys |= MT_SHIFT; + gKeyStates['['] = 0; + } } - else + if (key == '[') { - gSpecialKeys |= MT_SHIFT; - gKeyStates['['] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys |= MT_GRAPH; + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['['] = 0; + gKeyStates['9'] = 0; + } } - } - if (key == '[') - { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (key == '`') { gSpecialKeys |= MT_GRAPH; - gSpecialKeys &= ~MT_SHIFT; gKeyStates['['] = 0; - gKeyStates['9'] = 0; + } + if (key == '\\') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys |= MT_GRAPH; + gKeyStates[';'] = 0; + } + else + { + gSpecialKeys |= MT_GRAPH; + gKeyStates['-'] = 0; + } } } - if (key == '`') - { - gSpecialKeys |= MT_GRAPH; - gKeyStates['['] = 0; - } - if (key == '\\') + else { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + // Handle the '^' key (Shift 6) + if (key == '6') { - gSpecialKeys |= MT_GRAPH; - gKeyStates[';'] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['6'] = 0; + gKeyStates['@'] = 0; + } + else + { + gSpecialKeys |= MT_SHIFT; + gKeyStates['@'] = 0; + } } - else + // Handle the '"' key (shift ') + if (key == '\'') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['\''] = 0; + gKeyStates['2'] = 0; + gKeyStates['7'] = 0; + } + else + { + gSpecialKeys |= MT_SHIFT; + gKeyStates['2'] = 0; + gKeyStates['7'] = 0; + } + } + // Handle the '+' and '=' keys + if (key == '=') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_SHIFT; + gKeyStates[';'] = 0; + gKeyStates['-'] = 0; + } + else + { + gSpecialKeys |= MT_SHIFT; + gKeyStates['-'] = 0; + gKeyStates[';'] = 0; + } + } + // Handle the '(' key + if (key == '9') + { + gKeyStates['8'] = 0; + gKeyStates['9'] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + gSpecialKeys &= ~MT_SHIFT; + else + gSpecialKeys |= MT_SHIFT; + } + // Handle the ')' key + if (key == '0') + { + gKeyStates['9'] = 0; + gKeyStates['0'] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + gSpecialKeys &= ~MT_SHIFT; + else + gSpecialKeys |= MT_SHIFT; + } + // Handle the '_' key + if (key == '-') { - gSpecialKeys |= MT_GRAPH; gKeyStates['-'] = 0; + gKeyStates['0'] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + gSpecialKeys &= ~MT_SHIFT; + else + gSpecialKeys |= MT_SHIFT; + } + // Handle the '_' key + if (key == ';') + { + gKeyStates[';'] = 0; + gKeyStates[':'] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + gSpecialKeys &= ~MT_SHIFT; + else + gSpecialKeys |= MT_SHIFT; + } + // Handle the '*' key + if (key == '8') + { + gKeyStates['8'] = 0; + gKeyStates[':'] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + gSpecialKeys &= ~MT_SHIFT; + else + gSpecialKeys |= MT_SHIFT; + } + // Handle the '&' key + if (key == '7') + { + gKeyStates['7'] = 0; + gKeyStates['6'] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + gSpecialKeys &= ~MT_SHIFT; + else + gSpecialKeys |= MT_SHIFT; + } + // Handle the '@' key + if (key == '2') + { + gKeyStates['2'] = 0; + gKeyStates['@'] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + gSpecialKeys &= ~MT_SHIFT; + else + gSpecialKeys |= MT_SHIFT; } } + isSpecialKey = 0; break; } @@ -1152,65 +1524,181 @@ int T100_Disp::handle(int event) { gSpecialKeys &= ~MT_SPACE; } - if (key == ']') + if (gModel != MODEL_PC8201) { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (key == ']') { - gSpecialKeys &= ~MT_GRAPH; - gSpecialKeys |= MT_SHIFT; - gKeyStates[']'] = 0; - gKeyStates['0'] = 1; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_GRAPH; + gSpecialKeys |= MT_SHIFT; + gKeyStates[']'] = 0; + gKeyStates['0'] = 1; + } + else + { + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['['] = 1; + gKeyStates[key] = 0; + } } - else + if (key == '[') { - gSpecialKeys &= ~MT_SHIFT; - gKeyStates['['] = 1; - gKeyStates[key] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_GRAPH; + gSpecialKeys |= MT_SHIFT; + gKeyStates['['] = 0; + gKeyStates['9'] = 1; + } } - } - if (key == '[') - { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (key == '`') { - gSpecialKeys &= ~MT_GRAPH; - gSpecialKeys |= MT_SHIFT; - gKeyStates['['] = 0; - gKeyStates['9'] = 1; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_GRAPH; + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['`'] = 0; + gKeyStates['['] = 1; + } + else + { + gSpecialKeys &= ~MT_GRAPH; + gKeyStates['`'] = 0; + gKeyStates['['] = 1; + } + } + if (key == '\\') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_GRAPH; + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['\\'] = 0; + gKeyStates[';'] = 1; + } + else + { + gSpecialKeys &= ~MT_GRAPH; + gKeyStates['-'] = 1; + gKeyStates['\\'] = 0; + } } } - if (key == '`') + else { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + // Deal with special keys for the PC-8201 + + // Handle the '^' key (Shift 6) + if (key == '6') { - gSpecialKeys &= ~MT_GRAPH; - gSpecialKeys &= ~MT_SHIFT; - gKeyStates['`'] = 0; - gKeyStates['['] = 1; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gKeyStates['6'] = 0; + gKeyStates['@'] = 1; + } + else + { + gSpecialKeys |= MT_SHIFT; + gKeyStates['@'] = 0; + } } - else + // Handle the '"' key (Shift ') + if (key == '\'') { - gSpecialKeys &= ~MT_GRAPH; - gKeyStates['`'] = 0; - gKeyStates['['] = 1; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gKeyStates['\''] = 0; + gKeyStates['2'] = 1; + } + else + { + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['2'] = 0; + gKeyStates['7'] = 1; + } } - } - if (key == '\\') - { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + // Handle the '+' and '=' keys + if (key == '=') { - gSpecialKeys &= ~MT_GRAPH; - gSpecialKeys &= ~MT_SHIFT; - gKeyStates['\\'] = 0; - gKeyStates[';'] = 1; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gKeyStates['='] = 0; + gKeyStates[';'] = 1; + } + else + { + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['-'] = 1; + gKeyStates['='] = 0; + } } - else + // Handle the '(' key + if (key == '9') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gKeyStates['9'] = 0; + gKeyStates['8'] = 1; + } + } + // Handle the '(' key + if (key == '0') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gKeyStates['0'] = 0; + gKeyStates['9'] = 1; + } + } + // Handle the '_' key + if (key == '-') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gKeyStates['-'] = 0; + gKeyStates['0'] = 1; + } + } + // Handle the ':' key + if (key == ';') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys |= MT_SHIFT; + gKeyStates[';'] = 0; + gKeyStates[':'] = 1; + } + } + // Handle the '*' key + if (key == '8') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gKeyStates['8'] = 0; + gKeyStates[':'] = 1; + } + } + // Handle the '&' key + if (key == '7') { - gSpecialKeys &= ~MT_GRAPH; - gKeyStates['-'] = 1; - gKeyStates['\\'] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gKeyStates['7'] = 0; + gKeyStates['6'] = 1; + } + } + // Handle the '@' key + if (key == '2') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys |= MT_SHIFT; + gKeyStates['2'] = 0; + gKeyStates['@'] = 1; + } } } - isSpecialKey = 0; break; } @@ -1222,7 +1710,7 @@ int T100_Disp::handle(int event) if (event == FL_KEYUP || event == FL_KEYDOWN) { // Start with empty string - label[0] = 0; + keylabel[0] = 0; // Add text for special keys for (c = 0; c < 32; c++) @@ -1231,9 +1719,9 @@ int T100_Disp::handle(int event) { if ((c == 2) || (c == 3) || (c==5)) continue; - if (label[0] != 0) - strcat(label, "+"); - strcat(label, gSpKeyText[c]); + if (keylabel[0] != 0) + strcat(keylabel, "+"); + strcat(keylabel, gSpKeyText[c]); } } @@ -1242,15 +1730,15 @@ int T100_Disp::handle(int event) { if (gKeyStates[c]) { - if (label[0] != 0) - strcat(label, "+"); + if (keylabel[0] != 0) + strcat(keylabel, "+"); sprintf(keystr, "'%c'", c); // Space shows up better written instead of ' ' if (c == 0x20) - strcat(label, "SPACE"); + strcat(keylabel, "SPACE"); else - strcat(label, keystr); + strcat(keylabel, keystr); } } @@ -1259,13 +1747,400 @@ int T100_Disp::handle(int event) Fl::check(); // Update the text - gpKey->label(label); + gpKey->label(keylabel); } return 1; } +/* +========================================================== +t200_command: This function processes commands sent to + Model 200 LCD subsystem. +========================================================== +*/ +void t200_command(unsigned char ir, unsigned char data) +{ + gpDisp->Command(ir, data); +} + +/* +========================================================== +t200_readport: This function returns the I/O port data + for the port specified. +========================================================== +*/ +unsigned char t200_readport(unsigned char port) +{ + return ((T200_Disp*)gpDisp)->ReadPort(port); +} + +/* +======================================================= +T200:Disp: This is the class construcor +======================================================= +*/ +T200_Disp::T200_Disp(int x, int y, int w, int h) : + T100_Disp(x, y, w, h) +{ + int c; + + /* Clear the display RAM */ + for (c = 0; c < 8192; c++) + m_ram[c] = 0; + + m_MyFocus = 0; + m_dstarth = 0; + m_dstartl = 0; + m_mcr = 0; + m_hpitch = 0; + m_hcnt = 0; + m_curspos = 0; + m_cursaddrh = 0; + m_cursaddrl = 0; + m_ramrd = 0; + m_ramrd_dummy = 0; + m_redraw_count = 0; +} + +/* +========================================================== +Command: This function processes commands sent to + Model 200 LCD subsystem. +========================================================== +*/ +void T200_Disp::Command(int instruction, uchar data) +{ + int cursaddr, dstart; + char mask; + int c; + + /* Calculate cursaddr just in case */ + cursaddr = (m_cursaddrh << 8) | m_cursaddrl; + + switch (instruction) + { + case SET_MCR: + m_mcr = data; + break; + + case SET_HPITCH: + m_hpitch = data; + break; + + case SET_HCNT: + m_hcnt = data; + break; + + case SET_TDIV: + m_tdiv = data; + break; + + case SET_CURSPOS: + m_curspos = data; + break; + + case SET_DSTARTL: + /* Save new value for m_dstartl */ + m_dstartl = data; + + break; + + case SET_DSTARTH: + /* Save new value of m_dstarth */ + m_dstarth = data; + + + /* Calculate location of new page start */ + dstart = (m_dstarth << 8) | m_dstartl; + + /* Test if changing to a totally new page */ + c = abs(dstart - m_last_dstart); + if (c != 0x140) + c = dstart - m_last_dstart + 0x2000; + if (c != 0x140) + c = m_last_dstart - dstart + 0x2000; + + m_last_dstart = dstart; + + if (c != 0x140) + { + /* Clear all of memory to prevent screen "jump" */ + for (c = 0; c < 0x2000; c++) + m_ram[c] = 0; + } + else + { + /* Clear RAM "above" display area */ + dstart -= 640; + if (dstart < 0) + dstart += 8192; + for (c = 0; c < 640; c++) + { + m_ram[dstart++] = 0; + if (dstart >= 8192) + dstart = 0; + } + } + + m_redraw_count = 40 * 8; +// printf("T200:IR=0x%04X DATA=0x%02X\n", instruction, dstart); + + break; + + case SET_CURSADDRL: + /* Test for increment of m_dstarth */ + if ((m_cursaddrl & 0x80) && !(data & 0x80)) + { + m_cursaddrh++; + + /* Test if address >= 8192 */ + if (m_cursaddrh >= 0x20) + m_cursaddrh = 0; + } + + /* Save new value of cursor address */ + m_cursaddrl = data; + break; + + case SET_CURSADDRH: + /* Save new value of m_cursaddrh */ + m_cursaddrh = data; + break; + + case RAM_WR: + /* Draw new data on the LCD */ + SetByte(cursaddr, 0, data); + + /* Increment cursor address */ + if (++m_cursaddrl == 0) + m_cursaddrh++; + + /* Test if address >= 8192 */ + if (m_cursaddrh >= 0x20) + m_cursaddrh = 0; + + if (m_redraw_count > 0) + { + if (--m_redraw_count == 0) + redraw_active(); + } + break; + + case RAM_RD: + /* Load m_ramrd register from the dummy register */ + m_ramrd_addr = cursaddr; + + break; + + case RAM_BIT_CLR: /* Clear the bit specified by data at cursaddr */ + /* First calculate the AND mask */ + mask = 0xFE << data; + + /* Draw new data on the LCD */ + SetByte(cursaddr, 0, m_ram[cursaddr] & mask); + + /* Now increment the address */ + if (++m_cursaddrl == 0) + m_cursaddrh++; + /* Test if address >= 8192 */ + + if (m_cursaddrh >= 0x20) + m_cursaddrh = 0; + + break; + + case RAM_BIT_SET: /* Set the bit specified by data at cursaddr */ + /* First calculate the OR mask */ + mask = 0x01 << data; + + /* Draw new data on the LCD */ + SetByte(cursaddr, 0, m_ram[cursaddr] | mask); + + /* Now increment the address */ + if (++m_cursaddrl == 0) + m_cursaddrh++; + + /* Test if address >= 8192 */ + if (m_cursaddrh >= 0x20) + m_cursaddrh = 0; + + break; + + } +} + +/* +================================================================= +draw: This routine draws the entire LCD. This is a member + function of Fl_Window. +================================================================= +*/ +void T200_Disp::draw() +{ + + int x=0; + int y=0; + int addr, col, row; + uchar value; + + /* Draw the static portions of the LCD / screen */ + draw_static(); + + /* Get RAM address where display should start */ + addr = (m_dstarth << 8) | m_dstartl; + + fl_color(FL_BLACK); + + /* Check if the driver is in "graphics" mode */ + if (m_mcr & 0x02) + { + /* Loop through all 128 display pixel rows */ + for (row = 0; row < 128; row++) + { + y = row; + + /* Loop through all 40 LCD columns */ + for (col = 0; col < 40; col++) + { + /* Calculate x coordinate (Characters are 6 pixels wide) */ + x= col * 6; + + + /* Get data to be displayed on "LCD" */ + value = m_ram[addr++]; + if (addr >= 8192) + addr = 0; + + // Erase line so it is grey, then fill in with black where needed +// fl_color(FL_GRAY); +// fl_rectf(x*MultFact + gXoffset,y*MultFact + +// gYoffset,8*MultFact,gRectsize); +// fl_color(FL_BLACK); + + // Draw the black pixels + drawpixel(x++,y, value&0x01); + drawpixel(x++,y, value&0x02); + drawpixel(x++,y, value&0x04); + drawpixel(x++,y, value&0x08); + drawpixel(x++,y, value&0x10); + drawpixel(x++,y, value&0x20); + } + } + } +} + +void T200_Disp::SetByte(int driver, int col, uchar value) +{ + int x; + int y; + int addr = driver; + int diff = addr - ((m_dstarth << 8) | m_dstartl); + if (diff < 0) + diff += 8192; + + // Check if LCD already has the value being requested + if (m_ram[addr] == value) + return; + + // Load new value into lcd "RAM" + m_ram[addr] = value; + // Calculate X position of byte */ + x = (diff % 40) * 6; + // Calcluate y position of byte + y = (diff / 40); + if (y >= 128) + return; + + // Set the display + gpDisp->window()->make_current(); + + fl_color(FL_GRAY); + fl_rectf(x*MultFact + gXoffset, y*MultFact + + gYoffset, MultFact*6, gRectsize); + fl_color(FL_BLACK); + + // Draw each pixel of byte + drawpixel(x++,y,value&0x01); + drawpixel(x++,y,(value&0x02)>>1); + drawpixel(x++,y,(value&0x04)>>2); + drawpixel(x++,y,(value&0x08)>>3); + drawpixel(x++,y,(value&0x10)>>4); + drawpixel(x++,y,(value&0x20)>>5); +} + +unsigned char T200_Disp::ReadPort(unsigned char port) +{ + /* Read RAM data through dummy register */ + m_ramrd = m_ramrd_dummy; + + /* Do a dummy read */ + m_ramrd_dummy = m_ram[m_ramrd_addr++]; + if (m_ramrd_addr >= 8192) + m_ramrd_addr = 0; + + return m_ramrd; +} + +/* +================================================================= +redraw_active: This routine redraws only the active LCD pixel + portion of the screen. This prevents screen + "flicker" that would be caused by erasing the + entire background and redrawing the static data + every time the screen scrolls. +================================================================= +*/ +void T200_Disp::redraw_active() +{ + + int x=0; + int y=0; + int addr, col, row; + uchar value; + + // Set the display + gpDisp->window()->make_current(); + + /* Get RAM address where display should start */ + addr = (m_dstarth << 8) | m_dstartl; + + /* Check if the driver is in "graphics" mode */ + if (m_mcr & 0x02) + { + /* Loop through all 128 display pixel rows */ + for (row = 0; row < 128; row++) + { + // Erase line so it is grey, then fill in with black where needed + y = row; + fl_color(FL_GRAY); + fl_rectf(gXoffset,y*MultFact + + gYoffset,240*MultFact,gRectsize); + fl_color(FL_BLACK); + + /* Loop through all 40 LCD columns */ + for (col = 0; col < 40; col++) + { + /* Calculate x coordinate (Characters are 6 pixels wide) */ + x= col * 6; + + /* Get data to be displayed on "LCD" */ + value = m_ram[addr++]; + if (addr >= 8192) + addr = 0; + + // Draw the black pixels + drawpixel(x++,y, value&0x01); + drawpixel(x++,y, value&0x02); + drawpixel(x++,y, value&0x04); + drawpixel(x++,y, value&0x08); + drawpixel(x++,y, value&0x10); + drawpixel(x++,y, value&0x20); + } + } + } +} diff --git a/src/display.h b/src/display.h index f3586af..340c3a8 100644 --- a/src/display.h +++ b/src/display.h @@ -37,33 +37,85 @@ extern "C" { #endif extern int gDelayUpdateKeys; -void initpref(void); -void initdisplay(void); +void init_pref(void); +void init_display(void); void drawbyte(int driver, int column, int value); void power_down(); void process_windows_event(); void display_cpu_speed(void); void show_error(const char*); +void t200_command(unsigned char ir, unsigned char data); +unsigned char t200_readport(unsigned char port); #ifdef __cplusplus class T100_Disp : public Fl_Widget { public: - int m_MyFocus; - void PowerDown(); T100_Disp(int x, int y, int w, int h); - void SetByte(int driver, int col, uchar value); + virtual void PowerDown(); + virtual void SetByte(int driver, int col, uchar value); + virtual void Command(int instruction, uchar data); + virtual void Clear(void); protected: - virtual int handle(int event); - void draw(); + virtual int handle(int event); + virtual void draw(); + virtual void draw_static(); - uchar lcd[10][256]; + int m_MyFocus; + uchar lcd[10][256]; }; + +class T200_Disp : public T100_Disp +{ +public: + T200_Disp(int x, int y, int w, int h); + virtual void Command(int instruction , uchar data); + virtual void SetByte(int driver, int col, uchar value); + unsigned char ReadPort(unsigned char port); + +protected: + virtual void draw(); + virtual void redraw_active(); + + uchar m_ram[8192]; /* T200 Display RAM storage */ + uchar m_mcr; /* Mode Control Register */ + uchar m_hpitch; /* Horizontal Character pitch */ + uchar m_hcnt; /* Horizontal character count */ + uchar m_tdiv; /* Time divisions */ + uchar m_curspos; /* Cursor position */ + uchar m_dstartl; /* Display start Low */ + uchar m_dstarth; /* Display start High */ + int m_last_dstart; /* Last dstart for clear operations */ + uchar m_cursaddrl; /* Cursor address Low */ + uchar m_cursaddrh; /* Cursor address High */ + uchar m_ramwr; /* Data to be written to the RAM */ + uchar m_ramrd; /* Data read from the RAM */ + uchar m_ramrd_dummy; /* Dummy read register */ + int m_ramrd_addr; /* Address for RAM reads */ + int m_redraw_count; + + enum { + SET_MCR, + SET_HPITCH, + SET_HCNT, + SET_TDIV, + SET_CURSPOS, + SET_DSTARTL = 8, + SET_DSTARTH, + SET_CURSADDRL, + SET_CURSADDRH, + RAM_WR, + RAM_RD, + RAM_BIT_CLR, + RAM_BIT_SET + }; +}; + } #endif diff --git a/src/do_instruct.h b/src/do_instruct.h index 7f3a59a..e3209fd 100644 --- a/src/do_instruct.h +++ b/src/do_instruct.h @@ -43,7 +43,7 @@ INCPC; \ if(trace) \ strcat(p,"STAX "rps); \ - MEM(rp)=A; \ + MEMSET(rp,A); \ cpu_delay(7); \ } @@ -69,7 +69,7 @@ j=1; \ else \ j=0; \ - setflags(r,-1,-1,j,-1,-2); \ + setflags(r,-1,-1,j,-1,-2, (r==0x80) || (r==0), -2); \ cpu_delay(4); \ } @@ -82,7 +82,7 @@ j=1; \ else \ j=0; \ - setflags(r,-1,-1,j,-1,-2); \ + setflags(r,-1,-1,j,-1,-2, (r==0xFF) || (r==0x7F), -2); \ cpu_delay(4); \ } @@ -101,13 +101,16 @@ strcat(p,"DAD "rps); \ i=HL; \ i+=rp; \ + j=(HL&0x8000)==(rp&0x8000); \ H=(i>>8); \ L=i; \ if(i>0xffff) \ i=1; \ else \ i=0; \ - setflags(0,-2,-2,-2,-2,i); \ + if (j) \ + j = (HL&0x8000) != (rp&0x8000); \ + setflags(0,-2,-2,-2,-2,i,j,-2 ); \ cpu_delay(10); \ } @@ -140,19 +143,30 @@ cpu_delay(4); \ } +#define MOVM(src,ss) { \ + INCPC; \ + if(trace) \ + strcat(p,"MOV M,"ss); \ + MEMSET(HL, src); \ + cpu_delay(7); \ + } + #define ADD(r,rs) { \ INCPC; \ if(trace) \ strcat(p,"ADD "rs); \ i=A; \ i+=r; \ + v=(A&0x80) == (r&0x80); \ j = (((A&0x0F)+(r&0x0F)) &0x10)>>4; \ A=i; \ if(i>0xFF) \ i=1; \ else \ i=0; \ - setflags(A,-1,-1,j,-1,i); \ + if (v) \ + v = (A&0x80) != (r&0x80); \ + setflags(A,-1,-1,j,-1,i,v,-2); \ cpu_delay(4); \ } @@ -163,13 +177,16 @@ i=A; \ i+=r; \ i+=(CF?1:0); \ + v=(A&0x80) == (r&0x80); \ j = (((A&0x0F)+(r&0x0F)+(CF?1:0)) &0x10)>>4; \ A=i; \ if(i>0xFF) \ i=1; \ else \ i=0; \ - setflags(A,-1,-1,j,-1,i); \ + if (v) \ + v = (A&0x80) != (r&0x80); \ + setflags(A,-1,-1,j,-1,i,v,-2); \ cpu_delay(4); \ } @@ -180,12 +197,15 @@ i=A; \ i-=r; \ j = (((A & 0x0F)-(r & 0x0F)) & 0x10) >> 4; \ + v=(A&0x80) == (r&0x80); \ A=i; \ if(i>0xFF) \ i=1; \ else \ i=0; \ - setflags(A,-1,-1,j,-1,i); \ + if (v) \ + v = (A&0x80) != (r&0x80); \ + setflags(A,-1,-1,j,-1,i,v,-2); \ cpu_delay(4); \ } @@ -197,12 +217,15 @@ i-=r; \ i-=(CF?1:0); \ j = (((A & 0x0F)-(r & 0x0F)-(CF?1:0)) & 0x10) >> 4; \ + v=(A&0x80) == (r&0x80); \ A=i; \ if (i>0xFF) \ i = 1; \ else \ i = 0; \ - setflags(A,-1,-1,j,-1,i); \ + if (v) \ + v = (A&0x80) != (r&0x80); \ + setflags(A,-1,-1,j,-1,i,v,-2); \ cpu_delay(4); \ } @@ -211,7 +234,7 @@ if(trace) \ strcat(p,"ANA "rs); \ A&=r; \ - setflags(A,-1,-1,1,-1,0); \ + setflags(A,-1,-1,1,-1,0,-2,-2); \ cpu_delay(4); \ } @@ -220,7 +243,7 @@ if(trace) \ strcat(p,"XRA "rs); \ A^=r; \ - setflags(A,-1,-1,0,-1,0); \ + setflags(A,-1,-1,0,-1,0,-2,-2); \ cpu_delay(4); \ } @@ -229,7 +252,7 @@ if(trace) \ strcat(p,"ORA "rs); \ A|=r; \ - setflags(A,-1,-1,0,-1,0); \ + setflags(A,-1,-1,0,-1,0,-2,-2); \ cpu_delay(4); \ } @@ -244,7 +267,11 @@ else \ i=0; \ j = (((A & 0x0F)-(r & 0x0F)) & 0x10) >> 4; \ - setflags(A-r,-1,-1,j,-1,i); \ + if ((A&0x80) == (r&0x80)) \ + v = (A&0x80) != (r&0x80); \ + else \ + v = 0; \ + setflags(A-r,-1,-1,j,-1,i,v,-2); \ cpu_delay(4); \ } @@ -263,8 +290,8 @@ if(trace) \ strcat(p,"PUSH "rps); \ DECSP2; \ - MEM(SP)=l; \ - MEM(SP+1)=h; \ + MEMSET(SP,l); \ + MEMSET(SP+1,h); \ cpu_delay(12); \ } @@ -273,7 +300,7 @@ if(trace) \ sprintf(p,"RST %d",num); \ DECSP2; \ - MEM(SP)=PCL; MEM(SP+1)=PCH; \ + MEMSET(SP,PCL); MEMSET(SP+1,PCH); \ PCH=0; \ PCL=8*num; \ cpu_delay(12); \ @@ -286,7 +313,7 @@ INCPC2; \ if(cond) { \ DECSP2; \ - MEM(SP)=PCL; MEM(SP+1)=PCH; /* MEM16(SP)=PC; */ \ + MEMSET(SP,PCL); MEMSET(SP+1,PCH); /* MEM16(SP)=PC; */ \ DECPC2; \ SETPCINS16; \ cpu_delay(9); \ @@ -376,7 +403,7 @@ strcat(p,"RLC"); i=A>>7; A=(A<<1)|i; - setflags(A,-2,-2,-2,-2,i); + setflags(A,-2,-2,-2,-2,i,-2,-2); cpu_delay(4); /* return; */ } @@ -391,11 +418,14 @@ INCPC; if (trace) sprintf(p, "DSUB"); - i = HL > BC - (CF?1:0); - j = HL - BC - (CF?1:0); + i = HL < BC;// - (CF?1:0); + j = HL - BC;// - (CF?1:0); + v = (HL&0x8000) == (BC&0x8000); L=j&0xFF; H=(j >> 8) & 0xFF; - setflags(H | L,-2,-1,-2,-2,i); + if (v) + v = (HL&0x8000) != (BC&0x8000); + setflags(H | L,-2,-1,-2,-2,i,v,-2); cpu_delay(10); /* return; */ } @@ -439,7 +469,7 @@ i=A<<7&0x80; A=(A>>1)|i; i>>=7; - setflags(A,-2,-2,-2,-2,i); + setflags(A,-2,-2,-2,-2,i,-2,-2); cpu_delay(4); /* return; */ } @@ -459,8 +489,8 @@ i = L & CF ; j = HL >> 1; L = j & 0xFF; - H = (j >> 8) & 0xFF; - setflags(0,-2,-2,-2,-2,i); + H = (H & 0x80) | ((j >> 8) & 0xFF); + setflags(0,-2,-2,-2,-2,i,-2,-2); cpu_delay(7); /* return; */ } @@ -504,7 +534,7 @@ i=A>>7; A<<=1; A|=(CF?1:0); - setflags(A,-2,-2,-2,-2,i); + setflags(A,-2,-2,-2,-2,i,-2,-2); cpu_delay(4); /* return; */ } @@ -521,9 +551,9 @@ sprintf(p, "RLDE"); i = D & 0x80 ? 1 : 0; j = DE << 1; - E = j & 0xFF; + E = (j & 0xFF) | (CF ? 1 : 0); D = (j >> 8) & 0xFF; - setflags(0,-2,-2,-2,-2,i); + setflags(0,-2,-2,-2,-2,i,-2,-2); cpu_delay(10); /* return; */ } @@ -567,7 +597,7 @@ i=(A&0x01); A>>=1; A|=CF?0x80:0; - setflags(A,-2,-2,-2,-2,i); + setflags(A,-2,-2,-2,-2,i,-2,-2); cpu_delay(4); /* return; */ } @@ -601,8 +631,8 @@ INCPC; if(trace) sprintf(p,"SHLD %x",INS16); - MEM(INS16)=L; - MEM(INS16+1)=H; + MEMSET(INS16,L); + MEMSET(INS16+1,H); /* MEM16(INS16)=HL; */ INCPC2; cpu_delay(16); @@ -649,7 +679,7 @@ if((((A>>4)+j) > 9) || CF) i|=0x60;/* Add 6 to upper nibble */ A+=i; - setflags(A,-1,-1,j,-1,i>>4?1:0); + setflags(A,-1,-1,j,-1,i>>4?1:0,-2,-2); cpu_delay(4); /* return; */ /* Huh? */ } @@ -750,7 +780,7 @@ INCPC; if(trace) sprintf(p,"STA %04x",INS16); - MEM(INS16)=A; + MEMSET(INS16,A); INCPC2; cpu_delay(13); /* return; */ @@ -765,27 +795,47 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0x34: /* INR M */ - INR(M,"M"); - cpu_delay(6); + INCPC; + if(trace) + strcat(p,"INR M"); + MEMSET(HL,(uchar) (M+1)); + if(M&0x0f==0) /* Low order nybble wrapped */ + j=1; + else + j=0; + setflags(M,-1,-1,j,-1,-2, (M==0x80) || (M==0), -2); + cpu_delay(10); } else { /* case 0x35: /* DCR M */ - DCR(M,"M"); - cpu_delay(6); + INCPC; + if(trace) + strcat(p,"DCR M"); + MEMSET(HL, (uchar)(M-1)); + if(M&0x0f==0x0f) /* Low order nybble wrapped */ + j=1; + else + j=0; + setflags(M,-1,-1,j,-1,-2, (M==0xFF) || (M==0x7F), -2); + cpu_delay(10); } } else { if(!(INS&0x01)) { /* case 0x36: /* MVI M */ - MVI(M,"M"); - cpu_delay(3); + INCPC; + if(trace) + sprintf(p,"MVI M,%02x",INS); + MEMSET((int)HL,INS); + INCPC; + cpu_delay(10); } else { /* case 0x37: /* STC */ INCPC; if(trace) strcat(p,"STC"); - setflags(0,-2,-2,-2,-2,1); + setflags(0,-2,-2,-2,-2,1,-2,-2); cpu_delay(4); /* return; */ } @@ -850,7 +900,7 @@ INCPC; if(trace) strcat(p,"CMC"); - setflags(A,-2,-2,-2,-2,CF?0:1); + setflags(A,-2,-2,-2,-2,CF?0:1,-2,-2); cpu_delay(4); /* return; */ } @@ -1158,25 +1208,21 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0x70: /* MOV M,B */ - MOV(M,B,"M","B"); - cpu_delay(3); + MOVM(B,"B"); } else { /* case 0x71: /* MOV M,C */ - MOV(M,C,"M","C"); - cpu_delay(3); + MOVM(C,"C"); } } else { if(!(INS&0x01)) { /* case 0x72: /* MOV M,D */ - MOV(M,D,"M","D"); - cpu_delay(3); + MOVM(D,"D"); } else { /* case 0x73: /* MOV M,E */ - MOV(M,E,"M","E"); - cpu_delay(3); + MOVM(E,"E"); } } } @@ -1184,13 +1230,11 @@ if(!(INS&0x02)) { if(!(INS&0x01)) { /* case 0x74: /* MOV M,H */ - MOV(M,H,"M","H"); - cpu_delay(3); + MOVM(H,"H"); } else { /* case 0x75: /* MOV M,L */ - MOV(M,L,"M","L"); - cpu_delay(3); + MOVM(L,"L"); } } else { @@ -1203,8 +1247,7 @@ } else { /* case 0x77: /* MOV M,A */ - MOV(M,A,"M","A"); - cpu_delay(3); + MOVM(A,"A"); } } } @@ -1706,12 +1749,15 @@ i=A; i+=INS; j = (((A&0x0F)+(INS&0x0F)) &0x10)>>4; + v = (A&0x80) == (INS&0x80); A=i; if(i>0xFF) i=1; else i=0; - setflags(A,-1,-1,j,-1,i); + if (v) + v = (A&0x80) != (INS&0x80); + setflags(A,-1,-1,j,-1,i,v,-2); cpu_delay(7); INCPC; /* return; */ @@ -1768,14 +1814,17 @@ i+=INS; i+=(CF?1:0); j = (((A&0x0F)+(INS&0x0F)+(CF?1:0)) &0x10)>>4; + v = (A&0x80) == (INS&0x80); A=i; if(i>0xFF) i=1; else i=0; - INCPC; - setflags(A,-1,-1,j,-1,i); + if (v) + v = (A&0x80) != (INS&0x80); + setflags(A,-1,-1,j,-1,i,v,-2); cpu_delay(7); + INCPC; /* return; */ } else { @@ -1836,14 +1885,17 @@ i=A; i-=INS; j = (((A&0x0F)-(INS&0x0F)) &0x10)>>4; + v = (A&0x80) == (INS&0x80); A=i; if (i>0xFF) i = 1; else i = 0; - INCPC; - setflags(A,-1,-1,j,-1,i); + if (v) + v = (A&0x80) != (INS&0x80); + setflags(A,-1,-1,j,-1,i,v,-2); cpu_delay(7); + INCPC; /* return; */ } else { @@ -1865,8 +1917,8 @@ INCPC; if (trace) sprintf(p, "SHLX"); - MEM(DE)=L; - MEM(DE+1)=H; + MEMSET(DE, L); + MEMSET(DE+1, H); cpu_delay(10); /* return; */ } @@ -1895,7 +1947,7 @@ } else { /* case 0xDD: /* JNX addr */ - JUMP(!XF,"JNX"); + JUMP(!OV,"JND"); /* return; */ } } @@ -1909,12 +1961,15 @@ i-=INS; i-=(CF?1:0); j = (((A&0x0F)-(INS&0x0F)-(CF?1:0)) &0x10)>>4; + v = (A&0x80) == (INS&0x80); A=i; if (i>0xFF) i = 1; else i = 0; - setflags(A,-1,-1,j,-1,i); + if (v) + v = (A&0x80) != (INS&0x80); + setflags(A,-1,-1,j,-1,i,v,-2); INCPC; cpu_delay(7); /* return; */ @@ -1957,8 +2012,8 @@ L=MEM(SP); H=MEM(SP+1); /* HL=MEM16(SP); */ - MEM(SP)=j; - MEM(SP+1)=i; + MEMSET(SP, (uchar) j); + MEMSET(SP+1, (uchar) i); /* MEM16(SP)=i; */ cpu_delay(16); /* return; */ @@ -1984,7 +2039,7 @@ sprintf(p,"ANI %02x",INS); A=A&INS; INCPC; - setflags(A,-1,-1,1,-1,0); + setflags(A,-1,-1,1,-1,0,-2,-2); cpu_delay(7); /* return; */ } @@ -2060,7 +2115,7 @@ sprintf(p,"XRI %02x",INS); A=A^INS; INCPC; - setflags(A,-1,-1,0,-1,0); + setflags(A,-1,-1,0,-1,0,-2,-2); cpu_delay(4); /* return; */ } @@ -2120,7 +2175,7 @@ sprintf(p,"ORI %02x",INS); A=A|INS; INCPC; - setflags(A,-1,-1,0,-1,0); + setflags(A,-1,-1,0,-1,0,-2,-2); cpu_delay(7); /* return; */ } @@ -2173,7 +2228,7 @@ } else { /* case 0xFD: /* JX addr */ - JUMP(XF,"JX"); + JUMP(OV,"JD"); /* return; */ } } @@ -2190,11 +2245,11 @@ else i=0; j = (((A & 0x0F)-(INS & 0x0F)) & 0x10) >> 4; - if (trace == 1) - fprintf(tracefile, "CPI setflags args %02X, %02x, %02x, %02x, %02x %02x\n", - A-INS, -1, -1, j, -1, i) ; - - setflags(A-INS,-1,-1,j,-1,i); + if ((A&0x80) == (INS&0x80)) + v = (A&0x80) != (INS&0x80); + else + v = 0; + setflags(A-INS,-1,-1,j,-1,i,v,-2); INCPC; cpu_delay(7); /* return; */ diff --git a/src/doins.c b/src/doins.c index 337ee6e..3b4479b 100644 --- a/src/doins.c +++ b/src/doins.c @@ -55,9 +55,9 @@ static char paritybits[256]={ }; #if defined(WIN32) -void setflags(int regval, int sign, int zero, int auxcarry, int parity, int carry) +void setflags(int regval, int sign, int zero, int auxcarry, int parity, int carry, int ov, int ts) #else -__inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry) +__inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry, char ov, char ts) #endif { if(sign>=0) @@ -66,7 +66,7 @@ __inline void setflags(unsigned char regval, char sign, char zero, char auxcarry F=(F&0x7F)|(regval&0x80); if(zero>=0) - F=(F&0xBF)|(sign?0x40:0); + F=(F&0xBF)|(zero?0x40:0); else if(zero==-1) F=(F&0xBF)|(regval?0:0x40); @@ -82,6 +82,11 @@ __inline void setflags(unsigned char regval, char sign, char zero, char auxcarry if(carry>=0) F=(F&0xFE)|(carry?1:0); + + if (ov >= 0) + F=(F&~OV_BIT)|(ov?OV_BIT:0); + if (ts >= 0) + F=(F&~TS_BIT)|(ts?TS_BIT:0); } /* inline void do_instruct(void) diff --git a/src/doins.h b/src/doins.h index d723013..1fbfd99 100644 --- a/src/doins.h +++ b/src/doins.h @@ -31,6 +31,10 @@ #ifndef _DOINS_H_ #define _DOINS_H_ -void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry); +#if defined(WIN32) +void setflags(int regval, int sign, int zero, int auxcarry, int parity, int carry, int ov, int ts); +#else +__inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry, char ov, char ts); +#endif #endif diff --git a/src/file.cpp b/src/file.cpp index 35857e4..d294f49 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -28,7 +28,6 @@ */ - #include #include #include @@ -37,7 +36,7 @@ #endif #include -#include +#include #include #include #include @@ -85,6 +84,7 @@ void cb_LoadOptRom (Fl_Widget* w, void*) Fl_File_Chooser *FileWin; int count, len; char buffer[65536]; + char option_name[32]; unsigned short start_addr; const char *filename; @@ -128,7 +128,9 @@ void cb_LoadOptRom (Fl_Widget* w, void*) } // Save the selected file in the preferences - virtualt_prefs.set("OptRomFile",filename); + get_model_string(option_name, gModel); + strcat(option_name, "_OptRomFile"); + virtualt_prefs.set(option_name, filename); strcpy(gsOptRomFile, filename); @@ -707,7 +709,7 @@ void cb_LoadFromHost(Fl_Widget* w, void*) } // Determine Directory entry location for new file - addr4 = gStdRomDesc->sDirectory; + addr4 = gStdRomDesc->sDirectory + 11 * gStdRomDesc->sFirstDirEntry; dir_index = 0; while (get_memory8(addr4) != 0) { @@ -787,9 +789,14 @@ void cb_LoadFromHost(Fl_Widget* w, void*) if (file_type == TYPE_BA) { + /* Update beginning of .DO file pointer */ addr3 = get_memory16(gStdRomDesc->sBeginDO); if (addr3 > addr1) set_memory16(gStdRomDesc->sBeginDO, addr3 + len); + + /* Update BASIC size variable */ + addr3 = get_memory16(gStdRomDesc->sBasicSize); + set_memory16(gStdRomDesc->sBasicSize, addr3 + len-2); } addr3 = get_memory16(gStdRomDesc->sBeginVar); @@ -1022,7 +1029,7 @@ void save_file(model_t_files_t *pFile) { for (c = 0; c < len; c++) { - get_memory8(addr1+c); + ch = get_memory8(addr1+c); fwrite(&ch, 1, 1, fd); } } diff --git a/src/genwrap.h b/src/genwrap.h index 31ce7a1..d478dea 100644 --- a/src/genwrap.h +++ b/src/genwrap.h @@ -76,8 +76,7 @@ extern "C" { /* Compiler Description */ #if defined(__BORLANDC__) - #define DESCRIBE_COMPILER(str) sprintf(str,"BCC %X.%02X" \ - ,__BORLANDC__>>8,__BORLANDC__&0xff); + #define DESCRIBE_COMPILER(str) sprintf(str,"BCC %X.%02X",__BORLANDC__>>8,__BORLANDC__&0xff); #elif defined(_MSC_VER) @@ -85,18 +84,15 @@ extern "C" { #elif defined(__GNUC__) - #define DESCRIBE_COMPILER(str) sprintf(str,"GCC %u.%02u" \ - ,__GNUC__,__GNUC_MINOR__); + #define DESCRIBE_COMPILER(str) sprintf(str,"GCC %u.%02u",__GNUC__,__GNUC_MINOR__); #elif defined(__WATCOMC__) - #define DESCRIBE_COMPILER(str) sprintf(str,"WATC %d" \ - ,__WATCOMC__); + #define DESCRIBE_COMPILER(str) sprintf(str,"WATC %d",__WATCOMC__); #elif defined(__DMC__) /* Digital Mars C/C++ */ - #define DESCRIBE_COMPILER(str) sprintf(str,"DMC %X.%02X" \ - ,__DMC__>>8,__DMC__&0xff); + #define DESCRIBE_COMPILER(str) sprintf(str,"DMC %X.%02X",__DMC__>>8,__DMC__&0xff); #else /* Unknown compiler */ @@ -201,13 +197,9 @@ extern "C" { #elif defined(__unix__) || defined(__APPLE__) #if defined(_PTH_PTHREAD_H_) - #define SLEEP(x) ({ int y=x; struct timeval tv; \ - tv.tv_sec=(y/1000); tv.tv_usec=((y%1000)*1000); \ - pth_nap(tv); }) + #define SLEEP(x) ({ int y=x; struct timeval tv; tv.tv_sec=(y/1000); tv.tv_usec=((y%1000)*1000); pth_nap(tv); }) #else - #define SLEEP(x) ({ int y=x; struct timeval tv; \ - tv.tv_sec=(y/1000); tv.tv_usec=((y%1000)*1000); \ - select(0,NULL,NULL,NULL,&tv); }) + #define SLEEP(x) ({ int y=x; struct timeval tv; tv.tv_sec=(y/1000); tv.tv_usec=((y%1000)*1000); select(0,NULL,NULL,NULL,&tv); }) #endif #define YIELD() SLEEP(1) diff --git a/src/intelhex.c b/src/intelhex.c index a9b3183..b8bc1c1 100644 --- a/src/intelhex.c +++ b/src/intelhex.c @@ -210,7 +210,7 @@ void hexout(FILE *fhex, int byte, int memory_location, int end) writing_in_progress = 1; } - if ( (memory_location != (last_mem+1)) || (buffer_pos >= MAXHEXLINE) \ + if ( (memory_location != (last_mem+1)) || (buffer_pos >= MAXHEXLINE) || ((end) && (buffer_pos > 0)) ) { /* it's time to dump the buffer to a line in the file */ fprintf(fhex, ":%02X%04X00", buffer_pos, buffer_addr); diff --git a/src/io.c b/src/io.c index 4b8d8fe..523b412 100644 --- a/src/io.c +++ b/src/io.c @@ -31,6 +31,7 @@ #include #include +#include "VirtualT.h" #include "cpu.h" #include "gen_defs.h" #include "io.h" @@ -38,36 +39,41 @@ #include "display.h" #include "setup.h" #include "m100emu.h" +#include "memory.h" +#include "sound.h" uchar lcd[10][256]; uchar lcdpointers[10]={0,0,0,0,0,0,0,0,0,0}; uchar lcddriver=0; uchar lcd_fresh_ptr[10] = {1,1,1,1,1,1,1,1,1,1 }; +uchar io90; +uchar ioA1; uchar ioBA; uchar ioB9; uchar ioE8; uchar ioBC; /* Low byte of 14-bit timer */ uchar ioBD; /* High byte of 14-bit timer */ - - +uchar ioD0; /* D0-DF io for T200 */ +uchar t200_ir; /* Instruction register */ +uchar t200_mcr; /* Mode Control Register */ +uchar t200_uart_state = 0; +uchar gRp5c01_mode; +uchar gRp5c01_data[4][13]; uchar keyscan[9] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +char keyin[9]; -uint lcdbits=0; -time_t clock_time = 0; -time_t last_clock_time = 1; -struct tm *mytime ; - +uint lcdbits=0; +time_t clock_time = 0; +time_t last_clock_time = 1; +struct tm *mytime ; unsigned long gSpecialKeys = 0; -unsigned char gKeyStates[128]; +unsigned char gKeyStates[128]; int gDelayUpdateKeys = 0; int gDelayCount = 0; -int gModel = MODEL_M100; +uchar clock_sr[5]; /* 40 Bit shift register */ +uchar clock_sr_index = 0; +uchar clock_serial_out = 0; -uchar clock_sr[5]; /* 40 Bit shift register */ -uchar clock_sr_index = 0; -uchar clock_serial_out = 0; - -char keyin[9]; void update_keys(void) { @@ -76,6 +82,13 @@ void update_keys(void) int c; uchar key; + if (gModel == MODEL_T200) + buf_index = 0xFD0E; + else if (gModel == MODEL_PC8201) + buf_index = 0xFE58; + + + /* Insure keystroke was recgonized by the system */ for (c = 0; c < 9; c++) { @@ -116,63 +129,218 @@ void update_keys(void) (gKeyStates['t'] << 4) | (gKeyStates['y'] << 5) | (gKeyStates['u'] << 6) | (gKeyStates['i'] << 7)); - keyscan[3] = ~(gKeyStates['o'] | (gKeyStates['p'] << 1) | - (gKeyStates['['] << 2) | (gKeyStates[';'] << 3) | - (gKeyStates['\''] << 4) | (gKeyStates[','] << 5) | - (gKeyStates['.'] << 6) | (gKeyStates['/'] << 7)); - keyscan[4] = ~(gKeyStates['1'] | (gKeyStates['2'] << 1) | (gKeyStates['3'] << 2) | (gKeyStates['4'] << 3) | (gKeyStates['5'] << 4) | (gKeyStates['6'] << 5) | (gKeyStates['7'] << 6) | (gKeyStates['8'] << 7)); - keyscan[5] = ~(gKeyStates['9'] | (gKeyStates['0'] << 1) | - (gKeyStates['-'] << 2) | (gKeyStates['='] << 3)) & - (unsigned char) (gSpecialKeys >> 24); + if (gModel != MODEL_PC8201) + { + keyscan[3] = ~(gKeyStates['o'] | (gKeyStates['p'] << 1) | + (gKeyStates['['] << 2) | (gKeyStates[';'] << 3) | + (gKeyStates['\''] << 4) | (gKeyStates[','] << 5) | + (gKeyStates['.'] << 6) | (gKeyStates['/'] << 7)); + + keyscan[5] = ~(gKeyStates['9'] | (gKeyStates['0'] << 1) | + (gKeyStates['-'] << 2) | (gKeyStates['='] << 3)) & + (unsigned char) (gSpecialKeys >> 24); - keyscan[6] = (unsigned char) ((gSpecialKeys >> 16) & 0xFF); + keyscan[6] = (unsigned char) ((gSpecialKeys >> 16) & 0xFF); - keyscan[7] = (unsigned char) ((gSpecialKeys >> 8) & 0xFF); + keyscan[7] = (unsigned char) ((gSpecialKeys >> 8) & 0xFF); - keyscan[8] = (unsigned char) (gSpecialKeys & 0xFF); + keyscan[8] = (unsigned char) (gSpecialKeys & 0xFF); + } + else + { + keyscan[3] = ~(gKeyStates['o'] | (gKeyStates['p'] << 1) | + (gKeyStates['@'] << 2) | (gKeyStates['\\'] << 3) | + (gKeyStates[','] << 4) | (gKeyStates['.'] << 5) | + (gKeyStates['/'] << 6) | (gKeyStates[']'] << 7)); + + keyscan[5] = ~(gKeyStates['9'] | (gKeyStates['0'] << 1) | + (gKeyStates[';'] << 2) | (gKeyStates[':'] << 3) | + (gKeyStates['-'] << 4) | (gKeyStates['['] << 5)) & + (unsigned char) (((gSpecialKeys & MT_SPACE) | ~MT_SPACE) >> 10) & + (unsigned char) (((gSpecialKeys & MT_INS) | ~MT_INS) >> 17); + + keyscan[6] = (unsigned char) (((gSpecialKeys & MT_BKSP) >> 17) | ~(MT_BKSP >> 17)) & + (unsigned char) (((gSpecialKeys & MT_UP) >> 29) | ~(MT_UP >> 29)) & + (unsigned char) (((gSpecialKeys & MT_DOWN) >> 29) | ~(MT_DOWN >> 29)) & + (unsigned char) (((gSpecialKeys & MT_LEFT) >> 25) | ~(MT_LEFT >> 25)) & + (unsigned char) (((gSpecialKeys & MT_RIGHT) >> 25) | ~(MT_RIGHT >> 25)) & + (unsigned char) (((gSpecialKeys & MT_TAB) >> 13) | ~(MT_TAB >> 13)) & + (unsigned char) (((gSpecialKeys & MT_ESC) >> 13) | ~(MT_ESC >> 13)) & + (unsigned char) (((gSpecialKeys & MT_ENTER) >> 16) | ~(MT_ENTER >> 16)); + + keyscan[7] = (unsigned char) ((gSpecialKeys >> 8) & 0x1F); + + keyscan[8] = (unsigned char) ((gSpecialKeys & 0x07) | 0xF8) & + (unsigned char) (((gSpecialKeys & MT_CAP_LOCK) | ~MT_CAP_LOCK) >> 1); + } } void init_io(void) { int c; - // Initialize special keys variable + /* Initialize special keys variable */ gSpecialKeys = 0xFFFFFFFF; for (c = 0; c < 128; c++) gKeyStates[c] = 0; - // Initialize keyscan variables + /* Initialize keyscan variables */ update_keys(); - // Initialize serial I/O structures + /* Initialize serial I/O structures */ + t200_uart_state = 0; /* Confiture 8152 to Mode state */ ser_init(); - // Setup callback for serial I/O + /* Setup callback for serial I/O */ ser_set_callback(cb_int65); + + ioA1 = 0; + io90 = 0; + ioA1 = 0; + ioBA = 0; + ioB9 = 0; + ioE8 = 0; + ioBC = 0; /* Low byte of 14-bit timer */ + ioBD = 0; /* High byte of 14-bit timer */ + ioD0 = 0; /* D0-DF io for T200 */ } void deinit_io(void) { - // Deinitialize the serial port + /* Deinitialize the serial port */ ser_deinit(); } int cROM = 0; +void clock_chip_cmd(void) +{ + static int clk_cnt = 1; + + /* Clock chip command strobe */ + switch (ioB9 & 0x07) + { + case 0: /* NOP */ + break; + case 1: /* Serial Shift */ + clock_serial_out = clock_sr[0] & 0x01; + clock_sr_index = 0; + break; + case 2: /* Write Clock chip */ + clock_sr_index = 0; + break; + case 3: /* Read clock chip */ + if (--clk_cnt > 0) + break; + + clk_cnt = 20; + + clock_time = time(&clock_time); + if (clock_time == last_clock_time) + break; + + last_clock_time = clock_time; + mytime = localtime(&clock_time); + + /* Update Clock Chip Shift register Seconds */ + clock_sr[0] = mytime->tm_sec % 10; + clock_sr[0] |= (mytime->tm_sec / 10) << 4; + + /* Minutes */ + clock_sr[1] = mytime->tm_min % 10; + clock_sr[1] |= (mytime->tm_min / 10) << 4; + + /* Hours */ + clock_sr[2] = mytime->tm_hour % 10; + clock_sr[2] |= (mytime->tm_hour / 10) << 4; + + /* Day of month */ + clock_sr[3] = mytime->tm_mday % 10; + clock_sr[3] |= (mytime->tm_mday / 10) << 4; + + /* Day of week */ + clock_sr[4] = (mytime->tm_wday) % 10; + + /* Month */ + clock_sr[4] |= (mytime->tm_mon + 1) << 4; + + clock_sr_index = 0; + + if ((memory[0xF92E] == 0) && (memory[0xF92D] == 0)) + { + memory[0xF92D] = mytime->tm_year % 10; + memory[0xF92E] = (mytime->tm_year % 100) / 10; + } + } +} void out(uchar port, uchar val) { int c; unsigned char flags; - static int clk_cnt = 20; switch(port) { + case 0x70: /* ReMem Mode port */ + case 0x81: /* ReMem RAMPAC emulation port */ + case 0x83: /* ReMem RAMPAC emulation port */ + remem_out(port, val); + break; + + case 0x90: /* T200 Clock/Timer chip */ + if (gModel == MODEL_PC8201) + { + if ((val & 0x10) && !(io90 & 0x10)) + { + clock_chip_cmd(); + break; + } + + io90 = val; + break; + } + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9A: + case 0x9B: + case 0x9C: + if (gModel == MODEL_T200) + { + gRp5c01_data[gRp5c01_mode & 0x03][port & 0x0F] = val; + + /* Check if the time is being set */ + if (gRp5c01_mode == 0) + { + /* Add code here to update the system time */ + } + /* Check if the alarm is being set */ + else if (gRp5c01_mode == 1) + { + } + } + break; + + case 0x9D: /* Clock chip Mode Register */ + if (gModel == MODEL_T200) + gRp5c01_mode = val & 0x03; + break; + + case 0x9E: + case 0x9F: + break; + case 0xA0: /* Modem control port */ /* Bit: @@ -181,6 +349,31 @@ void out(uchar port, uchar val) 1 - Modem enable (1-Modem chip enabled) */ return; + case 0xA1: /* RAM bank port on PC-8201A */ + /* Test for a change to the ROM bank (0x0000 - 0x7FFF) */ + if ((val & 0x0F) == ioA1) + break; + + if ((val & 0x03) != (ioA1 & 0x03)) + { + set_rom_bank((unsigned char) (val & 0x03)); + } + + /* Test for a change to the RAM bank (0x8000 - 0xFFFF) */ + if ((val & 0x0C) != (ioA1 & 0x0C)) + { + /* Convert HW select to bank number */ + c = (val & 0x0C) >> 2; + if (c > 0) + c--; + + /* Set bank number */ + set_ram_bank((unsigned char) c); + } + + ioA1 = val & 0x0F; + break; + case 0xB0: /* PIO Command/Status Register */ case 0xB8: /* @@ -249,20 +442,43 @@ void out(uchar port, uchar val) power_down(); } - // Update COM settings - if ((val & 0xC8) != (ioBA & 0xC8)) + /* Update COM settings */ + if (gModel != MODEL_T200) { - if ((val & 0x08) == 1) - c = 0; + if ((val & 0xC8) != (ioBA & 0xC8)) + { + if ((val & 0x08) == 1) + c = 0; + else + { + flags = 0; + if ((val & 0x40) == 0) + flags |= SER_SIGNAL_DTR; + if ((val & 0x80) == 0) + flags |= SER_SIGNAL_RTS; + } + ser_set_signals(flags); + } + } + + if ((ioBA & 0x04) != (A & 0x04)) + { + if (A & 0x04) + sound_stop_tone(); else { - flags = 0; - if ((val & 0x40) == 0) - flags |= SER_SIGNAL_DTR; - if ((val & 0x80) == 0) - flags |= SER_SIGNAL_RTS; + unsigned short div, freq; + div = ((ioBD & 0x3F) << 8) | ioBC; + if (div != 0) + freq = (unsigned short) (2457600L / div); + else + freq = 500; + sound_start_tone(freq); } - ser_set_signals(flags); + } + if ((ioBA & 0x20) != (A & 0x20)) + { + sound_toggle_speaker((A & 0x20) >> 5); } ioBA = A; @@ -287,7 +503,7 @@ void out(uchar port, uchar val) return; case 0xC0: /* Bidirectional data bus for UART (6402) (C0H-CFH same) */ - case 0xC1: + case 0xC1: /* Status/Control bus for T200 */ case 0xC2: case 0xC3: case 0xC4: @@ -301,8 +517,58 @@ void out(uchar port, uchar val) case 0xCC: case 0xCD: case 0xCE: + if (gModel == MODEL_T200) + { + ser_write_byte(val); + return; + } case 0xCF: - ser_write_byte(val); + if (gModel == MODEL_T200) + { + if (t200_uart_state == 0) + { + /* Set Mode state - first check data bits*/ + c = ((val & 0x0C) >> 2) + 5; + ser_set_bit_size(c); + + /* Set stop bits */ + c = val & 0x80 ? 2 : 1; + ser_set_stop_bits(c); + + /* Set Parity */ + if (val & 0x10) + c = val & 0x20 ? 'E' : 'O'; + else + c = 'N'; + ser_set_parity((char) c); + + t200_uart_state = 1; + } + else + { + /* Command state - first checkf for reset operation */ + if (val & 0x40) + { + /* Reset the UART */ + t200_uart_state = 0; + return; + } + + /* Set UART state based on command */ + flags = 0; + /* Test for DTR */ + if (val & 0x02) + flags |= SER_SIGNAL_DTR; + + /* Test for RTS */ + if (val & 0x20) + flags |= SER_SIGNAL_RTS; + + ser_set_signals(flags); + } + } + else + ser_write_byte(val); return; case 0xD0: /* Status control register for UART, modem, and phone (6402) */ @@ -321,31 +587,51 @@ void out(uchar port, uchar val) case 0xDD: case 0xDE: case 0xDF: - /* - Bits: - 0 - Stop Bits (1-1.5, 0-2) - 1 - Parity (1-even, 0-odd) - 2 - Parity Enable (1-no parity, 0-parity enabled) - 3 - Data length (00-5 bits, 10-6 bits, 01-7 bits, 11-8 - bits) - 4 - Data length (see bit 3) */ - - if ((ioBA & 0x08) == 0) + if (gModel != MODEL_T200) { - // Set stop bits - c = val & 0x01 ? 2 : 1; - ser_set_stop_bits(c); + /* + Bits: + 0 - Stop Bits (1-1.5, 0-2) + 1 - Parity (1-even, 0-odd) + 2 - Parity Enable (1-no parity, 0-parity enabled) + 3 - Data length (00-5 bits, 10-6 bits, 01-7 bits, 11-8 + bits) + 4 - Data length (see bit 3) */ + + if ((ioBA & 0x08) == 0) + { + /* Set stop bits */ + c = val & 0x01 ? 2 : 1; + ser_set_stop_bits(c); - // Set Parity - if (val & 0x04) - c = 'N'; - else - c = val & 0x02 ? 'E' : 'O'; - ser_set_parity((char) c); + /* Set Parity */ + if (val & 0x04) + c = 'N'; + else + c = val & 0x02 ? 'E' : 'O'; + ser_set_parity((char) c); + + /* Set bit size */ + c = ((val & 0x18) >> 3) + 5; + ser_set_bit_size(c); + } + } + else + { + /* ROM and RAM bank seleciton bits */ + /* Check for a change in the current RAM bank */ + if ((ioD0 & 0x0C) != (val & 0x0C)) + { + set_ram_bank((unsigned char)((val >> 2) & 0x03)); + } + + /* Check for a change in the current ROM bank */ + if ((ioD0 & 0x03) != (val & 0x03)) + { + set_rom_bank((uchar) (val & 0x03)); + } - // Set bit size - c = ((val & 0x18) >> 3) + 5; - ser_set_bit_size(c); + ioD0 = val; } return; @@ -371,74 +657,16 @@ void out(uchar port, uchar val) 1 - STROBE (not) signal to printer 2 - STROBE for Clock chip (1990) 3 - Remote plug control signal */ - if(val&0x01) { - if(cROM!=1) { - memcpy(memory,optROM,ROMSIZE); - cROM=1; - } - } - else { - if(cROM!=0) { - memcpy(memory,sysROM,ROMSIZE); - cROM=0; - } - } - if ((val & 0x04) && !(ioE8 & 0x04)) + if (gModel != MODEL_T200) { - /* Clock chip command strobe */ - switch (ioB9 & 0x07) - { - case 0: /* NOP */ - break; - case 1: /* Serial Shift */ - clock_serial_out = clock_sr[0] & 0x01; - clock_sr_index = 0; - break; - case 2: /* Write Clock chip */ - clock_sr_index = 0; - break; - case 3: /* Read clock chip */ - if (--clk_cnt > 0) - break; - - clk_cnt = 20; - - clock_time = time(&clock_time); - if (clock_time == last_clock_time) - break; - - last_clock_time = clock_time; - mytime = localtime(&clock_time); - - /* Update Clock Chip Shift register Seconds */ - clock_sr[0] = mytime->tm_sec % 10; - clock_sr[0] |= (mytime->tm_sec / 10) << 4; - - /* Minutes */ - clock_sr[1] = mytime->tm_min % 10; - clock_sr[1] |= (mytime->tm_min / 10) << 4; - - /* Hours */ - clock_sr[2] = mytime->tm_hour % 10; - clock_sr[2] |= (mytime->tm_hour / 10) << 4; - - /* Day of month */ - clock_sr[3] = mytime->tm_mday % 10; - clock_sr[3] |= (mytime->tm_mday / 10) << 4; - - /* Day of week */ - clock_sr[4] = (mytime->tm_wday) % 10; - - /* Month */ - clock_sr[4] |= (mytime->tm_mon + 1) << 4; - - clock_sr_index = 0; + /* Check for change in ROM selection */ + if ((val & 0x01) != cROM) + set_rom_bank((uchar) (val & 0x01)); - if ((memory[0xF92E] == 0) && (memory[0xF92D] == 0)) - { - memory[0xF92D] = mytime->tm_year % 10; - memory[0xF92E] = (mytime->tm_year % 100) / 10; - } + /* Check for Clock Chip strobe */ + if ((val & 0x04) && !(ioE8 & 0x04)) + { + clock_chip_cmd(); break; } } @@ -462,42 +690,61 @@ void out(uchar port, uchar val) case 0xFC: case 0xFD: case 0xFE: /* Row select */ - for (c = 0; c < 10; c++) + if (gModel != MODEL_T200) { - if (lcdbits & (1 << c)) + for (c = 0; c < 10; c++) { - /* Save page and column info for later use */ - lcdpointers[c]=A; + if (lcdbits & (1 << c)) + { + /* Save page and column info for later use */ + lcdpointers[c]=A; - /* New pointer loaded - mark it as "fresh" */ - if ((A & 0x3F) < 50) - lcd_fresh_ptr[c] = 1; + /* New pointer loaded - mark it as "fresh" */ + if ((A & 0x3F) < 50) + lcd_fresh_ptr[c] = 1; + } } + } + else + { + /* Execute the command using the value supplied */ + t200_command(t200_ir, val); } return; case 0xFF: /* Data output */ - for (c = 0; c < 10; c++) + if (gModel != MODEL_T200) { - if (lcdbits & (1 << c)) + for (c = 0; c < 10; c++) { - if ((lcdpointers[c]&0x3f) < 50) + if (lcdbits & (1 << c)) { - /* Save Byte in LCD memory */ - lcd[c][lcdpointers[c]]=A; - - /* Draw the byte on the display */ - drawbyte(c,lcdpointers[c],A); - - /* Update the pointer if */ - lcdpointers[c]++; - if ((lcdpointers[c] & 0x3F) >= 50) - lcdpointers[c] &= 0xC0; - - /* We just changed the pointer so it isn't fresh any more */ - lcd_fresh_ptr[c] = 0; + if ((lcdpointers[c]&0x3f) < 50) + { + /* Save Byte in LCD memory */ + lcd[c][lcdpointers[c]]=A; + + /* Draw the byte on the display */ + drawbyte(c,lcdpointers[c],A); + + /* Update the pointer if */ + lcdpointers[c]++; + if ((lcdpointers[c] & 0x3F) >= 50) + lcdpointers[c] &= 0xC0; + + /* We just changed the pointer so it isn't fresh any more */ + lcd_fresh_ptr[c] = 0; + } } } } + else + { + /* Save the T200 LCD controller Instruction Register */ + if (val == 0x0D) + t200_command(val, 0); + else + t200_ir = val; + } return; } } @@ -512,8 +759,99 @@ int inport(uchar port) case 0x82: /* Optional IO thinger? */ return(0xA2); + case 0x90: /* T200 Clock/Timer chip */ + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9A: + case 0x9B: + case 0x9C: + if (gModel == MODEL_T200) + { + /* Check if the time is being set */ + if (gRp5c01_mode == 0) + { + /* Read system clock and update "chip" */ + if (port == 0x90) + { + clock_time = time(&clock_time); + if (clock_time != last_clock_time) + { + last_clock_time = clock_time; + mytime = localtime(&clock_time); + + /* Update Clock Chip Shift register Seconds */ + gRp5c01_data[0][0] = mytime->tm_sec % 10; + gRp5c01_data[0][1] = mytime->tm_sec / 10; + + /* Minutes */ + gRp5c01_data[0][2] = mytime->tm_min % 10; + gRp5c01_data[0][3] = mytime->tm_min / 10; + + /* Hours */ + /* Test if we are in 12 or 24 hour mode */ + if (gRp5c01_data[1][10] == 1) + { + gRp5c01_data[0][4] = mytime->tm_hour % 10; + gRp5c01_data[0][5] = mytime->tm_hour / 10; + } + else + { + gRp5c01_data[0][4] = (mytime->tm_hour % 12) % 10; + gRp5c01_data[0][5] = (mytime->tm_hour % 12) / 10; + if (mytime->tm_hour >=12) + gRp5c01_data[0][5] |= 2; + } + + /* Day of week */ + gRp5c01_data[0][6] = mytime->tm_wday; + + /* Day of month */ + gRp5c01_data[0][7] = mytime->tm_mday % 10; + gRp5c01_data[0][8] = mytime->tm_mday / 10; + + /* Month */ + gRp5c01_data[0][9] = (mytime->tm_mon+1) % 10; + gRp5c01_data[0][10] = (mytime->tm_mon+1) / 10; + + /* Year */ + gRp5c01_data[0][11] = mytime->tm_year % 10; + gRp5c01_data[0][12] = (mytime->tm_year % 100) / 10; + } + } + } + /* Check if the alarm is being set */ + else if (gRp5c01_mode == 1) + { + } + + /* Return data stored in the RP5C01 "chip" */ + ret = gRp5c01_data[gRp5c01_mode & 0x03][port & 0x0F]; + return ret; + } + return 0;; + + case 0x9D: /* Clock chip Mode Register */ + return gRp5c01_mode; + + case 0x9E: + case 0x9F: + return 0;; + case 0xA0: /* Modem control port */ - return(0xA0); + if ((gModel == MODEL_PC8201) || (gModel == MODEL_PC8300)) + return ioA1; + else + return 0xA0; + + case 0xA1: /* Bank control port on NEC laptops */ + return ioA1; case 0xB0: /* PIO Command/Status Register */ case 0xB8: @@ -553,7 +891,11 @@ int inport(uchar port) if (setup.com_mode != SETUP_COM_NONE) ser_get_flags(&flags); flags &= SER_FLAG_CTS | SER_FLAG_DSR; - return clock_serial_out | flags; + if (gModel == MODEL_T200) + flags |= 0x01; /* Low Power Sense (not) */ + else + flags |= clock_serial_out; + return flags; case 0xB4: /* 8155 Timer register. LSB of timer counter */ case 0xBC: @@ -578,8 +920,29 @@ int inport(uchar port) case 0xCC: case 0xCD: case 0xCE: + if (gModel == MODEL_T200) + { + ser_read_byte(&ret); + return ret; + } case 0xCF: - ser_read_byte(&ret); + if (gModel == MODEL_T200) + { + ret = 1; + if (ser_get_flags(&flags) == SER_PORT_NOT_OPEN) + { + ret = SER_FLAG_TX_EMPTY << 2; + } + else + { + ret |= (flags & (SER_FLAG_OVERRUN | SER_FLAG_FRAME_ERR)) << 3; + ret |= flags & SER_FLAG_PARITY_ERR; + ret |= (flags & SER_FLAG_TX_EMPTY) << 2; + ret |= (flags & SER_FLAG_DSR) << 1; + } + } + else + ser_read_byte(&ret); return ret; case 0xD0: /* Status control register for UART, modem, and phone (6402) */ @@ -598,32 +961,39 @@ int inport(uchar port) case 0xDD: case 0xDE: case 0xDF: - /* - Bits: - 0 - Data on telephone line (used to detect carrier) - 1 - Overrun error from UART - 2 - Framing error from UART - 3 - Parity error from UART - 4 - Transmit buffer empty from UART - 5 - Ring line on modem connector - 6 - Not used - 7 - Low Power signal from power supply (LPS not) */ - - // Check if RS-232 is "Muxed in" - if ((ioBA & 0x08) == 0) + if (gModel != MODEL_T200) { - flags = 0; - if (setup.com_mode != SETUP_COM_NONE) + /* + Bits: + 0 - Data on telephone line (used to detect carrier) + 1 - Overrun error from UART + 2 - Framing error from UART + 3 - Parity error from UART + 4 - Transmit buffer empty from UART + 5 - Ring line on modem connector + 6 - Not used + 7 - Low Power signal from power supply (LPS not) */ + + /* Check if RS-232 is "Muxed in" */ + if ((ioBA & 0x08) == 0) { - // Get flags from serial routines - ser_get_flags(&flags); - flags = (flags & (SER_FLAG_OVERRUN | SER_FLAG_FRAME_ERR | - SER_FLAG_PARITY_ERR)) | ((flags & SER_FLAG_TX_EMPTY) - << 4) | ((flags & SER_FLAG_RING) >> 1); + flags = 0; + if (setup.com_mode != SETUP_COM_NONE) + { + /* Get flags from serial routines */ + ser_get_flags(&flags); + flags = (flags & (SER_FLAG_OVERRUN | SER_FLAG_FRAME_ERR | + SER_FLAG_PARITY_ERR)) | ((flags & SER_FLAG_TX_EMPTY) + << 4) | ((flags & SER_FLAG_RING) >> 1); + } + return flags | 0x80; } - return flags | 0x80; + return(0x90); + } + else + { + return ioD0; } - return(0x90); case 0xE0: /* Keyboard input and misc. device select (E0H-EFH same) */ case 0xE1: @@ -706,7 +1076,10 @@ int inport(uchar port) case 0xFC: case 0xFD: case 0xFE: - return(64); + if (gModel == MODEL_T200) + return t200_readport(0xFE); + else + return(64); case 0xFF: /* Loop through all LCD driver modules */ for (c = 0; c < 10; c++) @@ -732,3 +1105,21 @@ int inport(uchar port) return(0); } } + +void io_set_ram_bank(unsigned char bank) +{ + if (gModel == MODEL_T200) + { + /* Update ioD0 port with bank bits */ + ioD0 = (ioD0 & 3) | ((bank & 3) << 2); + } + else if ((gModel == MODEL_PC8201) || (gModel == MODEL_PC8300)) + { + /* Convert bank number to HW select. Bank 1 not used in HW */ + if (bank > 0) + bank++; + + /* Update I/O port with RAM bank info (High address bits) */ + ioA1 = (ioA1 & 3) | ((bank & 3) << 2); + } +} diff --git a/src/io.h b/src/io.h index ab17a40..56057f1 100644 --- a/src/io.h +++ b/src/io.h @@ -47,6 +47,7 @@ void init_io(void); void deinit_io(void); void out(uchar port, uchar val); void update_keys(void); +void io_set_ram_bank(unsigned char bank); int inport(uchar port); #ifdef __cplusplus } @@ -78,6 +79,8 @@ int inport(uchar port); #define MT_LABEL 0x00200000 // F9 #define MT_PRINT 0x00400000 #define MT_ENTER 0x00800000 +#define MT_INS 0x01000000 +#define MT_DEL 0x02000000 #define MT_LEFT 0x10000000 @@ -85,10 +88,4 @@ int inport(uchar port); #define MT_UP 0x40000000 #define MT_DOWN 0x80000000 -enum { - MODEL_M100 - ,MODEL_M102 - ,MODEL_T200 -}; - #endif diff --git a/src/m100emu.c b/src/m100emu.c index b56c065..7f5d8a9 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -41,6 +41,7 @@ #include #endif +#include "VirtualT.h" #include "io.h" #include "cpu.h" #include "doins.h" @@ -50,13 +51,18 @@ #include "roms.h" #include "intelhex.h" #include "setup.h" +#include "memory.h" +#include "m100emu.h" +#include "sound.h" int fullspeed=0; +int gModel = MODEL_M100; uchar cpu[14]; uchar memory[65536]; -uchar sysROM[ROMSIZE]; -uchar optROM[ROMSIZE]; +uchar sysROM[65536]; +uchar msplanROM[32768]; +uchar optROM[32768]; char op[26]; UINT64 cycles=0; UINT64 instructs=0; @@ -80,10 +86,19 @@ char path[255]; char file[255]; extern RomDescription_t gM100_Desc; +extern RomDescription_t gM200_Desc; +extern RomDescription_t gN8201_Desc; +extern uchar gReMem; extern int cROM; -RomDescription_t *gStdRomDesc; +extern unsigned char ioD0; +RomDescription_t *gStdRomDesc; +/* Define Debug global variables */ +char gDebugActive = 0; +char gStopped = 0; +char gSingleStep = 0; + #ifdef _WIN32 __inline double hirestimer(void) { @@ -108,9 +123,9 @@ __inline double hirestimer(void) } #endif +double last_instruct=0; void cpu_delay(int cy) { - static double last_instruct=0; double hires; if(!fullspeed) { @@ -173,118 +188,190 @@ void resetcpu(void) } -void load_opt_rom(void) +/* +============================================================================= +get_model_string: This function returns the sring name of the specified + emulation model. +============================================================================= +*/ +void get_model_string(char* str, int model) { - int len, c; - int fd; - unsigned short start_addr; - char buf[65536]; - - // Clear the option ROM memory - memset(optROM,0,ROMSIZE); - - // Check if an option ROM is loaded - if ((len = strlen(gsOptRomFile)) == 0) - return; - - // Check type of option ROM - if (((gsOptRomFile[len-1] | 0x20) == 'x') && - ((gsOptRomFile[len-2] | 0x20) == 'e') && - ((gsOptRomFile[len-3] | 0x20) == 'h')) + switch (model) { - // Load Intel HEX file - len = load_hex_file(gsOptRomFile, buf, &start_addr); - - // Check for invalid HEX file - if ((len > 32768) || (start_addr != 0)) - return; + case MODEL_M100: + strcpy(str, "m100"); + break; + case MODEL_M102: + strcpy(str, "m102"); + break; + case MODEL_T200: + strcpy(str, "t200"); + break; +// case MODEL_M10: +// strcpy(str, "m10"); +// break; + case MODEL_PC8201: + strcpy(str, "pc8201"); + break; + case MODEL_PC8300: + strcpy(str, "pc8300"); + break; + } +} - // Copy data to optROM - for (c = 0; c < len; c++) - optROM[c] = buf[c]; +/* +============================================================================= +get_emulation_path: This function returns the path of the emulation directory + based on the supplied model. +============================================================================= +*/ +void get_emulation_path(char* emu, int model) +{ + strcpy(emu, path); /* Copy VirtualT path */ + switch (model) + { + case MODEL_M100: + strcat(emu, "M100/"); + break; + case MODEL_M102: + strcat(emu, "M102/"); + break; + case MODEL_T200: + strcat(emu, "T200/"); + break; +// case MODEL_M10: +// strcat(emu, "m10/"); +// break; + case MODEL_PC8201: + strcat(emu, "PC8201/"); + break; + case MODEL_PC8300: + strcat(emu, "PC8300/"); + break; } - else +} + +/* +============================================================================= +get_rom_path: This function returns the path of the ROM file for the + model specified. The path is strcpy(ed) into the string + supplied. +============================================================================= +*/ +void get_rom_path(char* file, int model) +{ + strcpy(file, path); /* Copy VirtualT path */ + switch (model) { - // Open BIN file - strcpy(file,path); - strcat(file,gsOptRomFile); - fd=open(file,O_RDONLY); - if(fd!=-1) - { - read(fd, optROM, ROMSIZE); - close(fd); - } + case MODEL_M100: + strcpy(file, "M100/M100rom.bin"); + break; + case MODEL_M102: + strcpy(file, "M102/M102rom.bin"); + break; + case MODEL_T200: + strcpy(file, "T200/T200rom.bin"); + break; +// case MODEL_M10: +// strcpy(file, "m10/m10rom.bin"); +// break; + case MODEL_PC8201: + strcpy(file, "PC8201/PC8201rom.bin"); + break; + case MODEL_PC8300: + strcpy(file, "PC8300/PC8300rom.bin"); + break; } } -void initcpu(void) +/* +============================================================================= +check_model_support: This function checks for support for the specified + Model and returns TRUE if that model is supported. + + Model Support is determined by checking for the + appropriate directory structure with the correct ROM + file. +============================================================================= +*/ +int check_model_support(int model) { - int fd; - int i; - - FILE *ram; + char file[256]; + int fd; - A=0; - F=0; - B=0; - C=0; - E=0; - H=0; - L=0; - SPH=0; - SPL=0; - PCH=0; - PCL=0; + + /* Get the path for the model supplied */ + get_rom_path(file, model); + + /* Attempt to open the ROM file */ + if ((fd = open(file, O_RDONLY)) == -1) + return FALSE; + + /* Open successful, close the file and return */ + close(fd); + return TRUE; +} + +/* +====================================================================== +initcpu: This function initializes the CPU and the system memories + including loading the ROM and RAM files. +====================================================================== +*/ +void init_cpu(void) +{ + int fd; + int i; + + /* Initialize CPU registers */ + A = F = B = C = D = E = H = L = 0; + SPH = SPL = 0; + PCH = PCL = 0; IM=0x08; cpuMISC=0; - - //J. Vernet : Added to have an absolute path to the ROM.bin - - - strcpy(file,path); - strcat(file,"ROM.bin"); - - - fd=open(file,O_RDONLY | O_BINARY); - if(fd<0) + /* Get Path to ROM based on current Model selection */ + get_rom_path(file, gModel); + + /* Open the ROM file */ + fd = open(file,O_RDONLY | O_BINARY); + if (fd < 0) { - show_error("Could not open ROM.bin"); - bail("Could not open ROM.bin"); + show_error("Could not open ROM file"); } - - if(read(fd, sysROM, ROMSIZE) 0)) + i--; + strncpy(path,argv[0], i+1); +# else + strcpy(path,"./"); #endif + // Added by JV for prefs - initpref(); // load user Menu preferences + init_pref(); // load user Menu preferences load_setup_preferences(); // Load user Peripheral setup preferences + load_memory_preferences(); // Load user Memory setup preferences - #ifdef __unix__ - //J. VERNET: Get Absolute Path, as getcwd doesn't return anything when launch from finder - // Beware: if the name (currently m100emu) changes, it will not work - - strncpy(path,argv[0],strlen(argv[0])-7); - # else if - strcpy(path,"./"); - #endif - - initcpu(); // Initialize the CPU - init_io(); // Initialize I/O structures - initdisplay(); // Initialize the Display - emulate(); // Main emulation loop - - // Cleanup - deinit_io(); // Deinitialize I/O + /* Perform initialization */ + init_mem(); /* Initialize Memory */ + init_io(); /* Initialize I/O structures */ + init_sound(); /* Initialize Sound system */ + init_display(); /* Initialize the Display */ + init_cpu(); /* Initialize the CPU */ + + /* Perform Emulation */ + emulate(); /* Main emulation loop */ + + /* Save RAM comtents after emulation */ + save_ram(); + + /* Cleanup */ + deinit_io(); /* Deinitialize I/O */ + deinit_sound(); /* Deinitialize sound */ + free_mem(); /* Free memory used by ReMem and/or Rampac */ } diff --git a/src/m100emu.h b/src/m100emu.h index 4da3813..0bc88d2 100644 --- a/src/m100emu.h +++ b/src/m100emu.h @@ -39,7 +39,7 @@ extern "C" { #endif -extern char op[16]; +extern char op[26]; extern int trace; extern int fullspeed; extern int gExitApp; @@ -49,14 +49,22 @@ extern RomDescription_t *gStdRomDesc; extern int gModel; extern char gsOptRomFile[256]; __inline double hirestimer(void); +typedef void (*mem_monitor_cb)(void); +void mem_set_monitor_callback(mem_monitor_cb cb); -void cpu_delay(int cy); -void resetcpu(void); -void load_opt_rom(void); -void cb_int65(void); +int check_model_support(int model); +void get_emulation_path(char* emu, int model); +void get_model_string(char* str, int model); +void get_rom_path(char* file, int model); +void init_cpu(void); +void cpu_delay(int cy); +void resetcpu(void); +void cb_int65(void); + #ifdef __cplusplus } #endif + #endif diff --git a/src/m100rom.c b/src/m100rom.c index 44df566..b66cfe7 100644 --- a/src/m100rom.c +++ b/src/m100rom.c @@ -28,6 +28,7 @@ */ #include "roms.h" +#include "romstrings.h" Std_ROM_Table_t gM100_Tables[] = { @@ -50,12 +51,11 @@ Std_ROM_Table_t gM100_Tables[] = { { 0x1754, 6, TABLE_TYPE_JUMP }, { 0x1762, 10, TABLE_TYPE_JUMP }, { 0x17D1, 10, TABLE_TYPE_JUMP }, - { 0x1877, 8, TABLE_TYPE_JUMP }, + { 0x1877, 10, TABLE_TYPE_JUMP }, { 0x1978, 21, TABLE_TYPE_3BYTE }, { 0x2481, 16, TABLE_TYPE_STRING }, { 0x25d5, 18, TABLE_TYPE_STRING }, { 0x26FE, 14, TABLE_TYPE_STRING }, - { 0x26FE, 14, TABLE_TYPE_STRING }, { 0x325C, 32, TABLE_TYPE_CODE }, { 0x327C, 2, TABLE_TYPE_CODE }, { 0x327E, 88, TABLE_TYPE_CODE }, @@ -73,35 +73,46 @@ Std_ROM_Table_t gM100_Tables[] = { { 0x339C, 64, TABLE_TYPE_CODE }, { 0x438A, 24, TABLE_TYPE_BYTE_LOOKUP }, { 0x43B8, 66, TABLE_TYPE_BYTE_LOOKUP }, + { 0x466F, 21, TABLE_TYPE_BYTE_LOOKUP }, { 0x50F1, 33, TABLE_TYPE_CTRL_DELIM }, { 0x5113, 16, TABLE_TYPE_JUMP }, + { 0x517C, 9, TABLE_TYPE_STRING }, { 0x5185, 30, TABLE_TYPE_4BYTE_CMD }, { 0x51A3, 1, TABLE_TYPE_CODE }, { 0x51A4, 28, TABLE_TYPE_CTRL_DELIM }, + { 0x51E7, 6, TABLE_TYPE_STRING }, { 0x5244, 9, TABLE_TYPE_STRING }, { 0x5443, 18, TABLE_TYPE_CTRL_DELIM }, { 0x550D, 16, TABLE_TYPE_JUMP }, { 0x551D, 1, TABLE_TYPE_CODE }, { 0x5583, 18, TABLE_TYPE_STRING }, { 0x5595, 6, TABLE_TYPE_STRING }, - { 0x559B, 2, TABLE_TYPE_STRING }, - { 0x5751, 64, TABLE_TYPE_STRING }, + { 0x559B, 2, TABLE_TYPE_CODE }, + { 0x5751, 80, TABLE_TYPE_STRING }, { 0x5AE9, 36, TABLE_TYPE_3BYTE }, { 0x5B0D, 17, TABLE_TYPE_STRING }, { 0x5B1E, 6, TABLE_TYPE_CODE }, { 0x5B24, 19, TABLE_TYPE_STRING }, { 0x5B37, 15, TABLE_TYPE_CODE }, { 0x5B46, 34, TABLE_TYPE_CTRL_DELIM }, + { 0x5D01, 1, TABLE_TYPE_CODE }, + { 0x5D02, 8, TABLE_TYPE_STRING }, + { 0x5D0A, 51, TABLE_TYPE_CTRL_DELIM }, { 0x5CCE, 33, TABLE_TYPE_STRING }, { 0x5CEF, 18, TABLE_TYPE_4BYTE_CMD }, { 0x5E15, 13, TABLE_TYPE_STRING }, { 0x5E22, 8, TABLE_TYPE_CODE }, - { 0x5E2A, 37, TABLE_TYPE_CTRL_DELIM }, + { 0x5E2A, 36, TABLE_TYPE_CTRL_DELIM }, { 0x5F38, 17, TABLE_TYPE_STRING }, { 0x5F49, 2, TABLE_TYPE_CODE }, { 0x5F4B, 21, TABLE_TYPE_STRING }, { 0x5F60, 5, TABLE_TYPE_STRING }, { 0x6018, 62, TABLE_TYPE_JUMP }, + { 0x60B1, 13, TABLE_TYPE_STRING }, + { 0x65CE, 17, TABLE_TYPE_STRING }, + { 0x665D, 21, TABLE_TYPE_BYTE_LOOKUP }, + { 0x670C, 7, TABLE_TYPE_STRING }, + { 0x6735, 9, TABLE_TYPE_STRING }, { 0x6BF1, 88, TABLE_TYPE_CATALOG }, { 0x6E94, 18, TABLE_TYPE_JUMP }, { 0x7551, 240, TABLE_TYPE_CODE }, @@ -117,851 +128,852 @@ Std_ROM_Table_t gM100_Tables[] = { }; Std_ROM_Addresses_t gM100_Vars[] = { - { 0x0040, "Function vector table for SGN to MID$" }, - { 0x0080, "BASIC statement keyword table END to NEW" }, - { 0x018E, "Function keyword table TAB to <" }, - { 0x01F0, "Function keyword table SGN to MID$" }, - { 0x0262, "BASIC statement vector table for END to NEW" }, - { 0x02EE, "Vector table for math operations" }, - { 0x031C, "BASIC error message text" }, - { 0x035A, "Initialization image loaded to F5F0H" }, - { 0x036F, "External ROM detect image loaded at F605H" }, - { 0x03EA, "BASIC message strings" }, - { 0x1F24, "Cassette frequency cycle count" }, - { 0x4349, "Cassette frequency cycle count" }, - { 0x551D, "TERM Mode function key vector table" }, - { 0x5B1E, "Directory file-type display order table" }, - { 0x5E22, "TEXT Function key table - empty" }, - { 0x6BF1, "ROM programs catalog entries" }, - { 0x71F7, "Interrupt exit routine (pop all regs & RET)" }, - { 0x71F8, "Interrupt exit routine (pop all regs & RET)" }, - { 0x7551, "8155 PIO chip bit patterns for Upper LCD drivers" }, - { 0x7551, "8155 PIO chip bit patterns for Lower LCD drivers" }, - { 0x7643, "8155 PIO chip bit patterns for LCD drivers" }, - { 0x7F01, "Initial clock chip register values" }, - { 0x7F98, "MENU Text Strings" }, - { 0x7FA4, "TRS-80 model number string" }, - { 0xF5F0, "Active system signature -- Warm vs Cold boot" }, - { 0xF5F4, "HIMEM" }, - { 0xF5F9, "RST 5.5 RAM Vector" }, - { 0xF5FC, "RST 6.5 RAM Vector" }, - { 0xF5FF, "RST 7.5 RAM Vector" }, - { 0xF602, "RAM vector for TRAP interrupt" }, - { 0xF62A, "Option ROM flag" }, - { 0xF62B, "Dial speed (1=10pps, 2=20pps" }, - { 0xF630, "Function key status table (1 = on)" }, - { 0xF638, "New Console device flag" }, - { 0xF639, "Cursor row (1-8)" }, - { 0xF63A, "Cursor column (1-40)" }, - { 0xF63B, "Active rows count (1-8)" }, - { 0xF63C, "Active columns count (1-40)" }, - { 0xf63d, "Label line protect status" }, - { 0xF63e, "Scroll disable flag" }, - { 0xF63f, "Cursor status (0 = off)" }, - { 0xF640, "Cursor row (1-8)" }, - { 0xF641, "Cursor column (1-40)" }, - { 0xF646, "ESC mode flag for RST 20H" }, - { 0xF648, "Reverse video switch" }, - { 0xF64E, "X coord of last point plotted" }, - { 0xF64F, "Y coord of last point plotted" }, - { 0xF656, "Power off exit condition switch" }, - { 0xF658, "Full/Half duplex switch" }, - { 0xF65A, "RS232 auto linefeed switch" }, - { 0xF65B, "RS232 parameter setting table" }, - { 0xF661, "Address last called" }, - { 0xF667, "OUT statement hook" }, - { 0xF66A, "INP function hook" }, - { 0xF672, "Last Error code" }, - { 0xF674, "Line printer head position" }, - { 0xF675, "Output device for RST 20H (0=screen)" }, - { 0xF678, "BASIC string buffer pointer" }, - { 0xF67A, "Current executing line number" }, - { 0xF67C, "Start of BASIC program pointer" }, - { 0xF680, "End of statement marker" }, - { 0xF685, "Keyboard buffer" }, - { 0xF788, "Horiz. position of cursor (0-39)" }, - { 0xF789, "Function key definition area" }, - { 0xF80A, "Function key definition area (BASIC)" }, - { 0xF88C, "End of RAM for file storage" }, - { 0xF923, "Seconds (ones)" }, - { 0xF924, "Seconds (tens)" }, - { 0xF925, "Minutes (ones)" }, - { 0xF926, "Minutes (tens)" }, - { 0xF927, "Hours (ones)" }, - { 0xF928, "Hours (tens)" }, - { 0xF929, "Date (ones)" }, - { 0xF92A, "Date (tens)" }, - { 0xF92B, "Day code (0=Sun, 1=Mon, etc.)" }, - { 0xF92C, "Month (1-12)" }, - { 0xF92D, "Year (ones)" }, - { 0xF92E, "Year (tens)" }, - { 0xF933, "Seconds (ones)" }, - { 0xF934, "Seconds (tens)" }, - { 0xF935, "Minutes (ones)" }, - { 0xF936, "Minutes (tens)" }, - { 0xF937, "Hours (ones)" }, - { 0xF938, "Hours (tens)" }, - { 0xF939, "Date (ones)" }, - { 0xF93A, "Date (tens)" }, - { 0xF93B, "Day code (0=Sun, 1=Mon, etc.)" }, - { 0xF93D, "Time for ON TIME interrupt (SSHHMM)" }, - { 0xF944, "On Com flag" }, - { 0xF945, "On Com routine address" }, - { 0xF947, "On Time flag" }, - { 0xF948, "On Time routine address" }, - { 0xF94A, "Function key vector table" }, - { 0xF962, "Start of RAM directory" }, - { 0xF99A, "BASIC program not saved pointer" }, - { 0xF9A5, "Start of Paste Buffer" }, - { 0xFAAC, "Last char sent to printer" }, - { 0xFAAD, "Label line enable flag" }, - { 0xFAAE, "Contents of port A8H" }, - { 0xFAAF, "Start of IPL filename" }, - { 0xFABA, "Address where last BASIC list started" }, - { 0xFABE, "SP save area for power up/down" }, - { 0xFAC0, "Lowest RAM address used by system" }, - { 0xFAC9, "Offset of last RST 38H call" }, - { 0xFAD0, "Length of last program loaded/saved to tape" }, - { 0xFADA, "Start of RST 38H vector table" }, - { 0xFAE2, "LCD character output hook" }, - { 0xFAE4, "Printer character output hook" }, - { 0xFB00, "EOF function hook" }, - { 0xFB0C, "Term F6 hook" }, - { 0xFB0E, "Term F7 hook" }, - { 0xFB14, "WIDTH statement hook" }, - { 0xFB1A, "CRT open routine hook" }, - { 0xFB1E, "CRT output file routine hook" }, - { 0xFB20, "WAND Open routine hook" }, - { 0xFB22, "WAND Close routine hook" }, - { 0xFB24, "WAND Get routine hook" }, - { 0xFB26, "WAND Special I/O routine hook" }, - { 0xFB28, "LOF function hook" }, - { 0xFB2A, "LOC function hook" }, - { 0xFB2C, "LFILES statement hook" }, - { 0xFB2E, "DSKI$ routine hook" }, - { 0xFB30, "DSKO$ routine hook" }, - { 0xFB64, "Variable Create/Locate switch" }, - { 0xFB65, "Type of last variable used" }, - { 0xFB67, "File buffer area pointer" }, - { 0xFB94, "Line number of current data statement" }, - { 0xFB96, "FOR/NEXT loop active flag" }, - { 0xFB99, "Address of last variable assigned" }, - { 0xFB9B, "Most recent or currenly running line pointer" }, - { 0xFB9D, "SP used by BASIC to reinitialize the stack" }, - { 0xFB9F, "Line number of last error" }, - { 0xFBA1, "Most recent used or entered line number" }, - { 0xFBA3, "Pointer to occurance of error" }, - { 0xFBA5, "Address of ON ERROR routine" }, - { 0xFBAA, "Line where break, END, or STOP occurred" }, - { 0xFBAC, "Address where program stopped on last break, END, or STOP" }, - { 0xFBAE, "Start of DO files pointer" }, - { 0xFBB0, "Start of CO files pointer" }, - { 0xFBB2, "Start of variable data pointer" }, - { 0xFBB4, "Start of array table pointer" }, - { 0xFBB6, "Unused memory pointer" }, - { 0xFBB8, "Address where DATA search will begin next" }, - { 0xFBBA, "DEF definition table" }, - { 0xFBE7, "8-Byte floating point for double precision math" }, - { 0xFC18, "Start of FAC1 for single and double precision" }, - { 0xFC1A, "Start of FAC1 for integers" }, - { 0xFC60, "8-Byte floating point for double precision math" }, - { 0xFC69, "Start of FAC2 for single and double precision" }, - { 0xFC6B, "Start of FAC2 for integers" }, - { 0xFC82, "Maxfiles" }, - { 0xFC83, "File number description table pointer" }, - { 0xFC93, "Filename of current BASIC program" }, - { 0xFC9C, "Filename of last program loaded from tape" }, - { 0xFCC0, "Start of Alt LCD character buffer" }, - { 0xFDA1, "Map of MENU entry positions to RAM directory positions" }, - { 0xFDED, "Flag to indicate MENU entry location or command entry" }, - { 0xFDEE, "Current MENU directory location" }, - { 0xFDEF, "Maximum MENU directory location" }, - { 0xFE00, "Start of LCD character buffer" }, - { 0xFF40, "XON/XOFF protocol control" }, - { 0xFF41, "XON/XOFF protocol control" }, - { 0xFF42, "XON/XOFF enable flag" }, - { 0xFF43, "RS232 initialization status" }, - { 0xFF44, "Sound flag" }, - { 0xFF45, "Contents of port E8H" }, - { 0xFF46, "RS232 Character buffer" }, - { 0xFF86, "RS232 buffer count" }, - { 0xFF87, "RS232 buffer output position" }, - { 0xFF88, "RS232 buffer input pointer" }, - { 0xFF8A, "Control-S status" }, - { 0xFF8B, "UART baud rate timer value" }, - { 0xFF8D, "RS232 Parity Control byte" }, - { 0xFF8E, "Cassette port pulse control" }, - { 0xFF97, "Special key status storage" }, - { 0xFF98, "Function key status storage" }, - { 0xFF99, "Keyboard scan column storage #1" }, - { 0xFFA2, "Keyboard scan column storage @2" }, - { 0xFFA3, "Shift key status storage" }, - { 0xFFA4, "Key repeat start delay counter" }, - { 0xFFA6, "Key position storage" }, - { 0xFFA8, "Pointer to entry in 2nd Storage Buffer for key" }, - { 0xFFAA, "Keyboard buffer count" }, - { 0xFFAB, "Keyboard typeahead buffer" }, - { 0xFFEC, "Cursor bit pattern storage" }, - { -1, "" } + { 0x0040, R_FUN_VCTR_TBL }, + { 0x0080, R_BASIC_TBL }, + { 0x018E, R_FUN_TBL_TAB }, + { 0x01F0, R_FUN_TBL_SGN }, + { 0x0262, R_BASIC_VCTR_TBL }, + { 0x02EE, R_MATH_VCTR_TBL }, + { 0x031A, R_BASIC_ERR_TXT }, + { 0x035A, R_INIT_IMAGE }, + { 0x036F, R_XROM_DET_IMAGE }, + { 0x03EA, R_BASIC_STRINGS }, + { 0x1F24, R_CAS_FREQ_CNT }, + { 0x4349, R_CAS_FREQ_CNT }, + { 0x551D, R_TERM_FKEY_VCTR_TBL }, + { 0x5B1E, R_DIR_DISP_ORDER_TBL }, + { 0x5E22, R_TEXT_FKEY_VCTR_TBL }, + { 0x6BF1, R_ROM_CAT_ENTRIES }, + { 0x71F7, R_INT_EXIT_FUN }, + { 0x71F8, R_INT_EXIT_FUN }, + { 0x7551, R_8155_PIO_PAT1 }, + { 0x7643, R_8155_PIO_PAT2 }, + { 0x7F01, R_INIT_CLK_VALUES }, + { 0x7F98, R_MENU_STRINGS }, + { 0x7FA4, R_MODEL_NUM_STRING }, + { 0xF5F0, R_ACTIVE_SIGNATURE }, + { 0xF5F4, R_HIMEM }, + { 0xF5F9, R_RST_5_5_VCTR }, + { 0xF5FC, R_RST_6_5_VCTR }, + { 0xF5FF, R_RST_7_5_VCTR }, + { 0xF602, R_TRAP_VCTR }, + { 0xF62A, R_OPTION_ROM_FLAG }, + { 0xF62B, R_DIAL_SPEED }, + { 0xF630, R_FKEY_STAT_TBL }, + { 0xF638, R_NEW_CONSOLE_FLAG }, + { 0xF639, R_CURSOR_ROW }, + { 0xF63A, R_CURSOR_COL }, + { 0xF63B, R_ACTIVE_ROW_CNT }, + { 0xF63C, R_ACTIVE_COL_CNT }, + { 0xf63d, R_LABEL_LINE_PROT }, + { 0xF63e, R_SCROLL_DISABLE }, + { 0xF63f, R_CURSOR_STAT }, + { 0xF640, R_CURSOR_ROW2 }, + { 0xF641, R_CURSOR_COL2 }, + { 0xF646, R_ESC_MODE_FLAG }, + { 0xF648, R_REV_VID_SWITCH }, + { 0xF64E, R_LAST_PLOT_X }, + { 0xF64F, R_LAST_PLOT_Y }, + { 0xF656, R_PWR_OFF_STAT }, + { 0xF658, R_DUPLEX_SWITCH }, + { 0xF65A, R_RS232_LF_SWITCH }, + { 0xF65B, R_RS232_PARAM_TBL }, + { 0xF661, R_ADDRESS_LAST_CALLED }, + { 0xF667, R_OUT_STMT_HOOK }, + { 0xF66A, R_INP_STMT_HOOK }, + { 0xF672, R_LAST_ERROR_CODE }, + { 0xF674, R_LPT_HEAD_POS }, + { 0xF675, R_OUTPUT_DEVICE }, + { 0xF678, R_BASIC_STR_BUF_PTR }, + { 0xF67A, R_CUR_BASIC_LINE_NUM }, + { 0xF67C, R_START_BASIC_PGM_PTR }, + { 0xF680, R_END_OF_STMT_MARKER }, + { 0xF685, R_KEYBOARD_BUF }, + { 0xF788, R_CURSOR_H_POS }, + { 0xF789, R_FKEY_DEF_BUF }, + { 0xF80A, R_BASIC_FKEY_DEF_BUF }, + { 0xF88C, R_FILE_RAM_END }, + { 0xF923, R_SEC_ONES }, + { 0xF924, R_SEC_TENS }, + { 0xF925, R_MIN_ONES }, + { 0xF926, R_MIN_TENS }, + { 0xF927, R_HR_ONES }, + { 0xF928, R_HR_TENS }, + { 0xF929, R_DATE_ONES }, + { 0xF92A, R_DATE_TENS }, + { 0xF92B, R_DAY_CODE }, + { 0xF92C, R_MONTH }, + { 0xF92D, R_YEAR_ONES }, + { 0xF92E, R_YEAR_TENS }, + { 0xF933, R_SEC_ONES2 }, + { 0xF934, R_SEC_TENS2 }, + { 0xF935, R_MIN_ONES2 }, + { 0xF936, R_MIN_TENS2 }, + { 0xF937, R_HR_ONES2 }, + { 0xF938, R_HR_TENS2 }, + { 0xF939, R_DATE_ONES2 }, + { 0xF93A, R_DATE_TENS2 }, + { 0xF93B, R_DAY_CODE2 }, + { 0xF93D, R_ONTIME_TIME }, + { 0xF944, R_ONCOM_FLAG }, + { 0xF945, R_ONCOM_ADDRESS }, + { 0xF947, R_ONTIME_FLAG }, + { 0xF948, R_ONTIME_ADDRESS }, + { 0xF94A, R_FKEY_VCTR_TBL }, + { 0xF962, R_DIR_RAM_START }, + { 0xF99A, R_UNSAVED_BASIC_PTR }, + { 0xF9A5, R_PASTE_RAM_START }, + { 0xFAAC, R_LAST_CHAR_PRINTED }, + { 0xFAAD, R_LABEL_ENABLE_FLAG }, + { 0xFAAE, R_PORT_A8H }, + { 0xFAAF, R_IPL_FILENAME_START }, + { 0xFABA, R_BASIC_LIST_START }, + { 0xFABE, R_SP_SAVE_BUF }, + { 0xFAC0, R_LOWEST_RAM }, + { 0xFAC9, R_RST_38H_OFFSET }, + { 0xFAD0, R_LAST_PGRM_LEN }, + { 0xFADA, R_RST_38H_VCTR_TBL }, + { 0xFAE2, R_LCD_OUTPUT_HOOK }, + { 0xFAE4, R_LPT_OUTPUT_HOOK }, + { 0xFB00, R_EOF_FUN_HOOK }, + { 0xFB0C, R_TERM_F6_HOOK }, + { 0xFB0E, R_TERM_F7_HOOK }, + { 0xFB14, R_WIDTH_STMT_HOOK }, + { 0xFB1A, R_CRT_OPEN_HOOK }, + { 0xFB1E, R_CRT_OUTPUT_HOOK }, + { 0xFB20, R_WAND_OPEN_HOOK }, + { 0xFB22, R_WAND_CLOSE_HOOK }, + { 0xFB24, R_WAND_GET_HOOK }, + { 0xFB26, R_WAND_IO_HOOK }, + { 0xFB28, R_LOF_HOOK }, + { 0xFB2A, R_LOC_HOOK }, + { 0xFB2C, R_LFILES_HOOK }, + { 0xFB2E, R_DSKI_HOOK }, + { 0xFB30, R_DSKO_HOOK }, + { 0xFB64, R_VAR_CREATE_LOC_FLAG }, + { 0xFB65, R_LAST_VAR_TYPE }, + { 0xFB67, R_FILE_BUF_PTR }, + { 0xFB94, R_DATA_STMT_LINE_NUM }, + { 0xFB96, R_FOR_NEXT_ACTIVE_FLAG }, + { 0xFB99, R_LAST_VAR_ASSIGNED_ADDR }, + { 0xFB9B, R_RUNNING_LINE_NUM_ADDR }, + { 0xFB9D, R_BASIC_SP_BUF }, + { 0xFB9F, R_LAST_ERR_LINE_NUM }, + { 0xFBA1, R_LAST_ENTERED_LINE_NUM }, + { 0xFBA3, R_ERR_PTR }, + { 0xFBA5, R_ONERROR_ADDRESS }, + { 0xFBA7, R_BASIC_RUNNING }, + { 0xFBAA, R_BREAK_LINE_NUM }, + { 0xFBAC, R_BREAK_ADDRESS }, + { 0xFBAE, R_DO_FILES_PTR }, + { 0xFBB0, R_CO_FILES_PTR }, + { 0xFBB2, R_VAR_PTR }, + { 0xFBB4, R_ARRAY_TBL_PTR }, + { 0xFBB6, R_UNUSED_MEM_PTR }, + { 0xFBB8, R_DATA_SEARCH_ADDR }, + { 0xFBBA, R_DEF_TBL }, + { 0xFBE7, R_FP_TEMP1 }, + { 0xFC18, R_FP_FAC1 }, + { 0xFC1A, R_INT_FAC1 }, + { 0xFC60, R_FP_TEMP2 }, + { 0xFC69, R_FP_FAC2 }, + { 0xFC6B, R_INT_FAC2 }, + { 0xFC79, R_FP_TEMP3 }, + { 0xFC82, R_MAXFILES }, + { 0xFC83, R_FILE_NUM_TBL_PTR }, + { 0xFC93, R_BASIC_FILENAME }, + { 0xFC9C, R_LAST_LOAD_FILENAME }, + { 0xFCC0, R_ALT_LCD_CHAR_BUF }, + { 0xFDA1, R_MENU_TO_RAM_MAP }, + { 0xFDED, R_MENU_OR_CMD_FLAG }, + { 0xFDEE, R_CUR_MENU_DIR_LOC }, + { 0xFDEF, R_MAX_MENU_DIR_LOC }, + { 0xFE00, R_LCD_CHAR_BUF }, + { 0xFF40, R_XON_XOFF_CTRL }, + { 0xFF41, R_XON_XOFF_CTRL }, + { 0xFF42, R_XON_XOFF_ENABLE }, + { 0xFF43, R_RS232_INIT_STAT }, + { 0xFF44, R_SOUND_FLAG }, + { 0xFF45, R_PORT_E8H }, + { 0xFF46, R_RS232_CHAR_BUF }, + { 0xFF86, R_RS232_BUF_CNT }, + { 0xFF87, R_RS232_BUF_OUT }, + { 0xFF88, R_RS232_BUF_IN }, + { 0xFF8A, R_CTRL_S_STAT }, + { 0xFF8B, R_UART_BAUD_TIMER_VAL }, + { 0xFF8D, R_RS232_PARITY_CTRL }, + { 0xFF8E, R_CAS_PULSE_CTRL }, + { 0xFF97, R_SPEC_KEY_STAT }, + { 0xFF98, R_FKEY_STAT }, + { 0xFF99, R_KEY_SCAN_STORAGE1 }, + { 0xFFA2, R_KEY_SCAN_STORAGE2 }, + { 0xFFA3, R_SHIFT_KEY_STAT }, + { 0xFFA4, R_KEY_REPT_START }, + { 0xFFA6, R_KEY_POSITION }, + { 0xFFA8, R_2ND_KEY_BUF_PTR }, + { 0xFFAA, R_KEY_BUF_CNT }, + { 0xFFAB, R_KEY_TYPEAHEAD_BUF }, + { 0xFFEC, R_CURSOR_BIT_PAT_BUF }, + { -1, -1 } }; Std_ROM_Addresses_t gM100_Funs[] = { - { 0x0000, "Reset Vector" }, - { 0x0008, "Compare next byte with M" }, - { 0x0010, "Get next non-white char from M" }, - { 0x0018, "Compare DE and HL" }, - { 0x001E, "Send a space to screen/printer" }, - { 0x0020, "Send character in A to screen/printer" }, - { 0x0024, "Power down TRAP" }, - { 0x0028, "Determine type of last var used" }, - { 0x002C, "RST 5.5 -- Bar Code Reader" }, - { 0x0030, "Get sign of FAC1" }, - { 0x0034, "RST 6.5 -- RS232 character pending" }, - { 0x0038, "RAM vector table driver" }, - { 0x003C, "RST 7.5 -- Timer background task" }, - { 0x0040, "Function vector table for SGN to MID$" }, - { 0x0080, "BASIC statement keyword table END to NEW" }, - { 0x018F, "Function keyword table TAB to <" }, - { 0x01F0, "Function keyword table SGN to MID$" }, - { 0x0262, "BASIC statement vector table for END to NEW" }, - { 0x02E2, "Math operator priority table" }, - { 0x02EE, "Vector table for math operations" }, - { 0x031C, "BASIC error message text" }, - { 0x035A, "Initialization image loaded to F5F0H" }, - { 0x036F, "External ROM detect image loaded at F605H" }, - { 0x03EA, "BASIC message strings" }, - { 0x0401, "Pop return address for NEXT or RETURN" }, - { 0x0422, "Initialize system and go to BASIC ready" }, - { 0x0446, "Generate Syntax error" }, - { 0x0449, "Generate /0 error" }, - { 0x044C, "Generate NF error" }, - { 0x044F, "Generate DD error" }, - { 0x0452, "Generate RW error" }, - { 0x0455, "Generate OV error" }, - { 0x0458, "Generate MO error" }, - { 0x045B, "Generate TM error" }, - { 0x045D, "Generate error in E" }, - { 0x048D, "Restore stack & runtime and jump to BC" }, - { 0x04C5, "Print BASIC error message - XX error in XXX" }, - { 0x0501, "Pop stack and vector to BASIC ready" }, - { 0x0502, "Vector to BASIC ready - print Ok" }, - { 0x0511, "Silent vector to BASIC ready" }, - { 0x0523, "Perform operation at M and return to ready" }, - { 0x05F0, "Update line addresses for current BASIC program" }, - { 0x05F0, "Update line addresses for current BASIC program" }, - { 0x060A, "Evaluate LIST statement arguments" }, - { 0x0628, "Find line number in DE" }, - { 0x062B, "Find line number in DE starting at HL" }, - { 0x0646, "Perform Token compression" }, - { 0x0726, "FOR statement" }, - { 0x076B, "TO statement" }, - { 0x0783, "STEP statement" }, - { 0x0804, "Execute BASIC program" }, - { 0x083A, "Start executing BASIC program at HL" }, - { 0x0840, "Execute instruction in A, HL points to args" }, - { 0x0858, "RST 10H routine with pre-increment of HL" }, - { 0x0858, "RST 10H routine" }, - { 0x0872, "DEF statement" }, - { 0x0881, "DEFDBL statement" }, - { 0x0886, "DEFINT statement" }, - { 0x0896, "DEFSNG statement" }, - { 0x089F, "DEFSTR statement" }, - { 0x08A1, "Declare variable at M to be type E" }, - { 0x08DB, "Generate FC error" }, - { 0x08E0, "Evaluate line number text at M" }, - { 0x08EB, "Convert ASCII number at M to binary" }, - { 0x08EC, "Convert ASCII number at M+1 to binary" }, - { 0x090F, "RUN statement" }, - { 0x091E, "GOSUB statement" }, - { 0x0936, "GOTO statement" }, - { 0x094D, "Generate UL error" }, - { 0x0966, "RETURN statement" }, - { 0x099E, "DATA statement" }, - { 0x09A0, "REM statement" }, - { 0x09C3, "LET statement" }, - { 0x0A2F, "ON statement" }, - { 0x0A34, "ON ERROR statement" }, - { 0x0A5B, "ON KEY/TIME/COM/MDM GOSUB routine" }, - { 0x0A94, "ON TIME$ handler" }, - { 0x0AB0, "RESUME statement" }, - { 0x0B0F, "ERROR statement" }, - { 0x0B1A, "IF statement" }, - { 0x0B4E, "LPRINT statement" }, - { 0x0B56, "PRINT statement" }, - { 0x0C01, "TAB statement" }, - { 0x0C45, "LINE statement" }, - { 0x0C99, "INPUT # statement" }, - { 0x0CA3, "INPUT statement" }, - { 0x0CD9, "READ statement" }, - { 0x0DAB, "Main BASIC evaluation routine" }, - { 0x0F0D, "Integer Divide FAC1=DE/HL" }, - { 0x0F1C, "Evaluate function at M" }, - { 0x0F47, "ERR function" }, - { 0x0F56, "ERL function" }, - { 0x0F7E, "VARPTR function" }, - { 0x0F86, "VARPTR(#buffer) function" }, - { 0x0F92, "VARPTR(variable) function" }, - { 0x0FDA, "Evaluate variable" }, - { 0x0FE8, "Get char at M and convert to uppercase" }, - { 0x0FE9, "Convert A to uppercase" }, - { 0x1037, "ASCII num conversion - find ASCII or tokenized '+' or '-' in A" }, - { 0x1054, "NOT function" }, - { 0x1069, "RST 28H routine" }, - { 0x108C, "OR function" }, - { 0x1097, "AND function" }, - { 0x10A2, "XOR function" }, - { 0x10AD, "EQV function" }, - { 0x10B5, "IMP function" }, - { 0x10C8, "LPOS function" }, - { 0x10CE, "POS function" }, - { 0x10D1, "Load integer in A into FAC1" }, - { 0x10E6, "Check for running program" }, - { 0x10EF, "Generate ID error" }, - { 0x1100, "INP function" }, - { 0x110C, "OUT statement" }, - { 0x1112, "Evaluate expression at M" }, - { 0x1113, "Evaluate expression at M-1" }, - { 0x112D, "Evaluate expression at M" }, - { 0x112E, "Evaluate expression at M-1" }, - { 0x113B, "LLIST statement" }, - { 0x1140, "LIST statement" }, - { 0x11A2, "Send buffer at M to screen" }, - { 0x1284, "PEEK function" }, - { 0x128B, "POKE function" }, - { 0x1297, "Evaluate expression at M" }, - { 0x12CB, "Wait for key from keyboard" }, - { 0x13A5, "Toggle function key label line" }, - { 0x13DB, "Check keyboard queue for pending characters" }, - { 0x1419, "POWER statement" }, - { 0x1431, "Normal TRAP (low power) interrupt routine" }, - { 0x143F, "Turn off computer" }, - { 0x1459, "POWER CONT statement" }, - { 0x1461, "POWER ON statement" }, - { 0x1470, "Output character to printer" }, - { 0x148A, "Start tape and load tape header" }, - { 0x1494, "Generate I/O error" }, - { 0x1499, "Turn cassette motor on and detect sync header" }, - { 0x14A8, "Turn cassette motor on" }, - { 0x14AA, "Turn cassette motor off" }, - { 0x14B0, "Read byte from tape & update checksum" }, - { 0x14C1, "Write byte to tape & update checksum" }, - { 0x14D2, "LCD Device control block" }, - { 0x14D8, "LCD and PRT file open routine" }, - { 0x14E5, "Output to LCD file" }, - { 0x14ED, "Pop AF, BC, DE, HL from stack" }, - { 0x14F2, "CRT device control block" }, - { 0x14FC, "RAM device control block" }, - { 0x1506, "Open RAM file" }, - { 0x158D, "Close RAM file" }, - { 0x15AC, "Output to RAM file" }, - { 0x15C4, "Input from RAM file" }, - { 0x161B, "Special RAM file I/O" }, - { 0x167F, "CAS device control block" }, - { 0x1689, "Open CAS file" }, - { 0x16AD, "Close CAS file" }, - { 0x16C7, "Output to CAS file" }, - { 0x16D2, "Input from CAS file" }, - { 0x1754, "LPT device control block" }, - { 0x175A, "Output to LPT file" }, - { 0x1762, "COM device control block" }, - { 0x176C, "Open MDM file" }, - { 0x176D, "Open COM file" }, - { 0x179E, "Close COM file" }, - { 0x17A8, "Output to COM/MDM file" }, - { 0x17B0, "Input from COM/MDM file" }, - { 0x17CA, "Special COM/MDM file I/O" }, - { 0x17D1, "MDM Device control block" }, - { 0x17DB, "Close MDM file" }, - { 0x17E6, "Set RS232 parameters from string at M" }, - { 0x1877, "Wand device control block" }, - { 0x1889, "EOF function" }, - { 0x1904, "TIME$ function" }, - { 0x190F, "Read time and store it at M" }, - { 0x192F, "DATE$ function" }, - { 0x1955, "DAY function" }, - { 0x1962, "Read day and store at M" }, - { 0x19A0, "Update in-memory (F923H) clock values" }, - { 0x19AB, "TIME$ statement" }, - { 0x19B3, "Update clock chip from memory F923H" }, - { 0x19BD, "DATE$ statement" }, - { 0x19F1, "DAY$ statement" }, - { 0x1A42, "Get time string from command line" }, - { 0x1A78, "IPL statement" }, - { 0x1A96, "Erase current IPL program" }, - { 0x1A9E, "COM and MDM statements" }, - { 0x1AB2, "KEY() statement" }, - { 0x1AC3, "KEY STOP/ON/OFF statements" }, - { 0x1AEA, "Determine argument (ON/OFF/STOP) for TIME$ statement" }, - { 0x1AFC, "Determine device (KEY/TIME/COM/MDM) for ON GOSUB" }, - { 0x1B0F, "ON TIME$ statement" }, - { 0x1B22, "ON COM handler" }, - { 0x1B32, "RST 7.5 interrupt routine" }, - { 0x1BB1, "Renew automatic power-off counter" }, - { 0x1BB8, "KEY statement" }, - { 0x1BBD, "KEY LIST statement" }, - { 0x1BE0, "Send B characters from M to the screen" }, - { 0x1C57, "PSET statement" }, - { 0x1C66, "PRESET statement" }, - { 0x1C6D, "LINE (graphic) statement" }, - { 0x1CA6, "Draw a filled box on LCD. Coords are on stack" }, - { 0x1CBC, "Draw an unfilled box on LCD. Coords are on stack" }, - { 0x1D2E, "Get (X,Y) coordinate from tokenized string at M" }, - { 0x1D90, "CSRLIN function" }, - { 0x1D9B, "MAX function" }, - { 0x1DA7, "MAXRAM function" }, - { 0x1DB2, "MAXFILES function" }, - { 0x1DB9, "HIMEM function" }, - { 0x1DC3, "WIDTH statement" }, - { 0x1DC5, "SOUND statement" }, - { 0x1DE5, "SOUND OFF statement" }, - { 0x1DE6, "SOUND ON statement" }, - { 0x1DEC, "MOTOR statement" }, - { 0x1DF1, "MOTOR ON statement" }, - { 0x1DF5, "MOTOR OFF statement" }, - { 0x1DFA, "CALL statement" }, - { 0x1E22, "SCREEN statement" }, - { 0x1E5E, "LCOPY statement" }, - { 0x1F3A, "FILES statement" }, - { 0x1F42, "Display Catalog" }, - { 0x1F91, "KILL statement" }, - { 0x1FBE, "Kill a text file" }, - { 0x2037, "NAME statement" }, - { 0x20FE, "NEW statement" }, - { 0x21FA, "Count length of string at M" }, - { 0x2206, "Get .DO filename and locate in RAM directory" }, - { 0x220F, "Open a text file at (FC93H)" }, - { 0x2280, "CSAVE statement" }, - { 0x22B9, "Save buffer at M to tape" }, - { 0x22CC, "SAVEM statement" }, - { 0x22DD, "CSAVEM statement" }, - { 0x2377, "CLOAD statement" }, - { 0x2413, "Load record from tape and store at M" }, - { 0x2478, "Generate Verify Failed error" }, - { 0x2491, "LOADM and RUNM statement" }, - { 0x24A7, "CLOADM statement" }, - { 0x2542, "Move B bytes from M to (DE)" }, - { 0x254B, "Launch .CO files from MENU" }, - { 0x260B, "Open CAS for output of BASIC files" }, - { 0x260E, "Open CAS for output of TEXT files" }, - { 0x2611, "Open CAS for output of CO files" }, - { 0x2650, "Open CAS for input of BASIC files" }, - { 0x2653, "Open CAS for input of TEXT files" }, - { 0x2656, "Open CAS for input of CO files" }, - { 0x273A, "STR$ function" }, - { 0x27B1, "Print buffer at M until NULL or '\"'" }, - { 0x290F, "Move L bytes from (BC) to (DE)" }, - { 0x2943, "LEN function" }, - { 0x294F, "ASC function" }, - { 0x295F, "CHR$ function" }, - { 0x296D, "STRING$ function" }, - { 0x298E, "SPACE$ function" }, - { 0x29AB, "LEFT$ function" }, - { 0x29DC, "RIGHT$ function" }, - { 0x29E6, "MID$ function" }, - { 0x2A07, "VAL function" }, - { 0x2A37, "INSTR function" }, - { 0x2B4C, "FRE function" }, - { 0x2B69, "Double precision subtract (FAC1=FAC1-FAC2)" }, - { 0x2B78, "Double precision addition (FAC1=FAC1+FAC2)" }, - { 0x2C4F, "Add the BCD num in M to the one in (DE)" }, - { 0x2CFF, "Double precision multiply (FAC1=FAC1*FAC2)" }, - { 0x2DC7, "Double precision divide (FAC1=FAC1/FAC2)" }, - { 0x2EE6, "Move C bytes from M to (DE)" }, - { 0x2EEF, "COS function" }, - { 0x2F09, "SIN function" }, - { 0x2F58, "TAN function" }, - { 0x2F71, "ATN function" }, - { 0x2FCF, "LOG function" }, - { 0x305A, "SQR function" }, - { 0x30A4, "EXP function" }, - { 0x313E, "RND function" }, - { 0x31A0, "Double precision Square (FAC1=SQR(FAC1))" }, - { 0x31A3, "Double precision math (FAC1=M * FAC2))" }, - { 0x31B5, "Move FAC1 to FAC2" }, - { 0x31B8, "Move floating point number M to FAC2" }, - { 0x31C1, "Move FAC2 to FAC1" }, - { 0x31C4, "Move floating point number M to FAC1" }, - { 0x31CA, "Move FAC1 to M" }, - { 0x31CA, "Double precision math (FAC1=FAC1*SQR(FAC1))" }, - { 0x31CA, "Swap FAC1 and FAC2" }, - { 0x31EB, "Square FAC1 & do table based math" }, - { 0x31EB, "Square FAC1 & do table based math & muliply times FAC1" }, - { 0x3209, "Table based math (FAC1=(((FAC1*M)+(M+1))*(M+2)+(M+3)..." }, - { 0x322E, "Push FAC2 on stack" }, - { 0x3234, "Push FAC1 on stack" }, - { 0x3245, "Pop FAC2 from stack" }, - { 0x324B, "Pop FAC1 from stack" }, - { 0x325C, "Floating point numbers for math operations " }, - { 0x327C, "Floating point num-shares 6 bytes from next number" }, - { 0x327E, "Floating point numbers for math operations "}, - { 0x32D6, "Count of Floating point numbers to follow for EXP" }, - { 0x32F7, "Count of Floating point numbers to follow for EXP" }, - { 0x3310, "Count of Floating point numbers to follow for LOG" }, - { 0x3331, "Count of Floating point numbers to follow for LOG" }, - { 0x335A, "Count of Floating point numbers to follow for SIN" }, - { 0x339B, "Count of Floating point numbers to follow for ATN" }, - { 0x33DC, "RST 30H routine" }, - { 0x33F2, "ABS function" }, - { 0x3407, "SGN function" }, - { 0x3422, "Push single precision FAC1 on stack" }, - { 0x342F, "Load single precision at M to FAC1" }, - { 0x3432, "Load single precision in BCDE to FAC1" }, - { 0x343D, "Load single precision FAC1 to BCDE" }, - { 0x3447, "Load single precision at M to BCDE" }, - { 0x3450, "Reverse load single precision at M to DEBC" }, - { 0x3459, "Move single precision FAC1 to M" }, - { 0x3461, "Move M to FAC2 using precision at (FB65H)" }, - { 0x3469, "Move B bytes from (DE) to M with increment" }, - { 0x3472, "Move B bytes from (DE) to M with decrement" }, - { 0x3498, "Compare single precision in BCDE with FAC1" }, - { 0x34B0, "Compare single precision in BCDE with M" }, - { 0x34C2, "Compare signed integer in DE with that in HL" }, - { 0x34FA, "Compare double precisoin FAC1 with FAC2" }, - { 0x3501, "CINT function" }, - { 0x3510, "Load signed integer in HL to FAC1" }, - { 0x352A, "CSNG function" }, - { 0x3540, "Convert signed integer in FAC1 to single precision" }, - { 0x3543, "Convert signed integer HL to single precision FAC1" }, - { 0x35BA, "CDBL function" }, - { 0x3645, "FIX function" }, - { 0x3654, "INT function" }, - { 0x35F8, "Signed integer subtract (FAC1=HL-DE)" }, - { 0x3704, "Signed integer addition (FAC1=HL+DE)" }, - { 0x3725, "Signed integer muliply (FAC1=HL*DE)" }, - { 0x377E, "Signed integer divide (FAC1=DE/HL)" }, - { 0x37F4, "Single precision addition (FAC1=FAC1+BCDE)" }, - { 0x37F7, "Single precision addition (FAC1=FAC1+FAC2)" }, - { 0x37FD, "Single precision subtract (FAC1=FAC1-BCDE)" }, - { 0x3803, "Single precision multiply (FAC1=FAC1*BCDE)" }, - { 0x3806, "Single precision multiply (FAC1=FAC2*FAC2)" }, - { 0x380E, "Single precision divide (FAC1=BCDE/FAC1)" }, - { 0x3827, "Single precision load (FAC2=BCDE)" }, - { 0x3840, "Convert ASCII number at M to double precision in FAC1" }, - { 0x3867, "Found 'e' in ASCII number" }, - { 0x388A, "Found 'E' in ASCII number" }, - { 0x3904, "Found '.' in ASCII number" }, - { 0x391A, "Found '%' in ASCII number" }, - { 0x3929, "Found '#' in ASCII number" }, - { 0x3931, "Deal with single & double precision ASCII conversions" }, - { 0x3940, "Convert ASCII number that starts with a Digit" }, - { 0x39CC, "Finish printing BASIC ERROR message \" in \" line #" }, - { 0x39D4, "Print binary number in HL at current position" }, - { 0x39E8, "Convert binary number in FAC1 to ASCII at M" }, - { 0x39EC, "Convert binary number in FAC1 to ASCII at M with format" }, - { 0x3D11, "Initialize FAC1 with 0.0 if it has no value" }, - { 0x3D7F, "Single precision exponential function" }, - { 0x3D8E, "Double precision exponential function" }, - { 0x3DF7, "Integer exponential function" }, - { 0x3FA0, "TIME$ ON statement" }, - { 0x3FD2, "Trigger interrupt. HL points to interrupt table" }, - { 0x3FD2, "Clear interrupt. HL points to interrupt table" }, - { 0x3FB2, "TIME$ OFF statement" }, - { 0x3FB9, "TIME$ STOP statement" }, - { 0x4009, "Clear all COM, TIME, and KEY interrupt definitions" }, - { 0x407F, "RESTORE statement" }, - { 0x409A, "STOP statement" }, - { 0x409F, "END statement" }, - { 0x40DA, "CONT sttement" }, - { 0x40F1, "Check if M is alpha character" }, - { 0x40F2, "Check if A is alpha character" }, - { 0x40F9, "CLEAR statement" }, - { 0x4174, "NEXT statement" }, - { 0x4222, "Send CRLF to screen or printer" }, - { 0x4225, "Send LF to screen or printer" }, - { 0x4229, "BEEP statement" }, - { 0x422D, "Home cursor" }, - { 0x4231, "CLS statement" }, - { 0x4235, "Protect line 8. An ESC T is printed" }, - { 0x423A, "Unprotect line 8. An ESC U is printed" }, - { 0x423F, "Stop automatic scrolling" }, - { 0x4244, "Resume automatic scrolling" }, - { 0x4249, "Turn the cursor on" }, - { 0x424E, "Turn the cursor off" }, - { 0x4253, "Delete current line on screen" }, - { 0x4258, "Insert line a current line" }, - { 0x425D, "Erase from cursor to end of line" }, - { 0x4262, "Send ESC X" }, - { 0x4269, "Start inverse character mode" }, - { 0x426E, "Cancel inverse character mode" }, - { 0x4270, "End escape sequence" }, - { 0x4277, "Send cursor to lower left of CRT" }, - { 0x427C, "Set the current cursor position (H=Row,L=Col)" }, - { 0x428A, "Erase function key display" }, - { 0x42A5, "Set and display function keys (M has key table)" }, - { 0x42A8, "Display function key line" }, - { 0x4313, "Print A to the screen" }, - { 0x4431, "Character plotting level 3. Check new device console flag & call level 4)" }, - { 0x4335, "Character plotting level 4. Turn off background task & call level 5" }, - { 0x434C, "Character plotting level 5. Handle ESC sequences & call level 6" }, - { 0x4373, "LCD output driver" }, - { 0x438A, "RST 20H lookup table" }, - { 0x43AF, "ESC Y routine (Set cursor position)" }, - { 0x43B2, "LCD output Escape routine" }, - { 0x43B8, "LCD Escape sequence lookup table" }, - { 0x43FA, "ESCape sequence driver" }, - { 0x4431, "ESC p routine (start inverse video)" }, - { 0x4432, "ESC q routine (cancel inverse video)" }, - { 0x4437, "ESC U routine (unprotect line 8)" }, - { 0x4439, "ESC T routine (protect line 8)" }, - { 0x443F, "ESC V routine (stop automatic scrolling)" }, - { 0x4440, "ESC W routine (resume automatic scrolling)" }, - { 0x443A, "ESC X routine" }, - { 0x4453, "ESC C routine (move cursor right)" }, - { 0x445C, "ESC D routine (move cursor left)" }, - { 0x4461, "Backspace routine" }, - { 0x4469, "ESC A routine (move cursor up)" }, - { 0x446E, "ESC B routine (move cursor down)" }, - { 0x4480, "Tab routine" }, - { 0x4494, "Linefeed routine" }, - { 0x44A8, "Verticle tab and ESC H routine (home cursor)" }, - { 0x44AA, "CR routine" }, - { 0x44AF, "ESC P routine (turn cursor on)" }, - { 0x44BA, "ESC Q routine (turn cursor off)" }, - { 0x44C4, "ESC M routine" }, - { 0x44D2, "Scroll LCD screen A times at line number in L" }, - { 0x44EA, "ESC L routine (insert line)" }, - { 0x4512, "Get character at (H,L) from LCD RAM)" }, - { 0x4535, "ESC l routine (erase current line)" }, - { 0x4537, "ESC K routine (erase to EOL)" }, - { 0x4548, "Form Feed (0CH), CLS, ESC E, and ESC J routine" }, - { 0x4560, "Character plotting level 6. Save character in C to LCD RAM & call level 7" }, - { 0x454E, "ESC J routine" }, - { 0x463E, "Input and display line and store at (F685H)" }, - { 0x4644, "Input and display (no \"?\") line and store at (F685H)" }, - { 0x4684, "Input routine (463EH) Control-C handler" }, - { 0x4696, "Input routine (463EH) ENTER handler" }, - { 0x46A0, "Input routine (463EH) backspace, left arrow, CTRL-H handler" }, - { 0x46C3, "Input routine (463EH) CTRL-U & X handler" }, - { 0x46CA, "Input routine (463EH) Tab handler" }, - { 0x478B, "DIM statement" }, - { 0x4790, "Find address of variable at M" }, - { 0x4991, "USING function" }, - { 0x4B44, "Send A to screen or printer" }, - { 0x4B55, "Print A to printer, expanding tabs if necessary" }, - { 0x4B92, "Reinitialize output back to LCD" }, - { 0x4BAB, "LCD character output routine" }, - { 0x4BB8, "Move LCD to blank line (send CRLF if needed)" }, - { 0x4BEA, "INKEY$ function" }, - { 0x4C84, "Get file descriptor for file in A" }, - { 0x4CCB, "OPEN statement" }, - { 0x4D59, "LCD, CRT, and LPT file close routine" }, - { 0x4D6E, "RUN statement (with parameters)" }, - { 0x4D70, "LOAD statement" }, - { 0x4D71, "MERGE statement" }, - { 0x4DCF, "SAVE statement" }, - { 0x4E28, "CLOSE statement" }, - { 0x4E8E, "INPUT$ function" }, - { 0x4F0A, "Zero B bytes at M" }, - { 0x4F0B, "Load B bytes at M with A" }, - { 0x4F2E, "PRINT # initialization routine" }, - { 0x4F5B, "LINE INPUT # statement" }, - { 0x504E, "Generate NM error" }, - { 0x5051, "Generate AO error" }, - { 0x5054, "Generate DS error" }, - { 0x5057, "Generate FF error" }, - { 0x505A, "Generate CF error" }, - { 0x505D, "Generate BN error" }, - { 0x5060, "Generate IE error" }, - { 0x5063, "Generate EF error" }, - { 0x5066, "Generate FL error" }, - { 0x506B, "LOF function" }, - { 0x506D, "LOC function" }, - { 0x506F, "LFILES function" }, - { 0x5071, "DSKO$ function" }, - { 0x5073, "DSKI$ function" }, - { 0x50F1, "Device name table" }, - { 0x5113, "Device control block vector addresses table" }, - { 0x5146, "TELCOM Entry point" }, - { 0x515B, "Re-entry point for TELCOM commands" }, - { 0x5185, "TELCOM instruction vector table" }, - { 0x51A4, "TELCOM label line text table" }, - { 0x51C0, "TELCOM STAT instruction routine" }, - { 0x51C7, "Print current STAT settings" }, - { 0x51ED, "Set STAT and return to TELCOM ready" }, - { 0x522F, "TELCOM CALL instruction routine" }, - { 0x524D, "TELCOM FIND instruction routine" }, - { 0x52B4, "Go off-hook" }, - { 0x52BB, "Disconnect phone line and disable modem carrier" }, - { 0x52D0, "Connect phone line and enable modem carrier" }, - { 0x52E4, "Go off-hook and wait for carrier" }, - { 0x5310, "Pause for about 2 seconds" }, - { 0x532D, "Execute logon sequence at M" }, - { 0x5359, "Dialing routine" }, - { 0x539E, "Auto logon sequence" }, - { 0x540A, "Dial the digit in A & print on LCD" }, - { 0x5455, "TELCOM TERM instruction routine" }, - { 0x54FC, "TELCOM \"dispatcher\" routine" }, - { 0x550D, "TERM Mode function key vector table" }, - { 0x5523, "TELCOM PREV function routine" }, - { 0x553E, "TELCOM FULL/HALF function routine" }, - { 0x5550, "TELCOM ECHO function routine" }, - { 0x559D, "TELCOM UP function routine" }, - { 0x567E, "TELCOM DOWN function routine" }, - { 0x571E, "TELCOM BYE function routine" }, - { 0x5791, "Print buffer at M until NULL or \"" }, - { 0x5797, "MENU Program" }, - { 0x57F8, "Display directory entries" }, - { 0x5837, "Handle CTRL-U key from MENU command loop" }, - { 0x585A, "MENU Program command loop" }, - { 0x588E, "Handle Backspace key from MENU command loop" }, - { 0x58F7, "Handle ENTER key from MENU command loop" }, - { 0x596F, "Launch ROM command file from MENU program" }, - { 0x5970, "Display directory entries of type in register C" }, - { 0x59AD, "Convert filename from space padded to '.ext' format" }, - { 0x59C9, "Position cursor for next directory entry" }, - { 0x5A12, "Print time, day and date on first line of screen" }, - { 0x5A15, "Print time,day,date on first line w/o CLS" }, - { 0x5A58, "Print NULL terminated string at M" }, - { 0x5A62, "Copy A bytes from (DE) to M" }, - { 0x5A6D, "Compare string at DE with that at M (max C bytes)" }, - { 0x5A79, "Clear function key definition table" }, - { 0x5A7C, "Set new function key table" }, - { 0x5A9E, "Display function keys on 8th line" }, - { 0x5AA9, "Search directory for filename" }, - { 0x5AE3, "Get start address of file at M" }, - { 0x5B1E, "Directory file-type display order table" }, - { 0x5B68, "ADDRSS Entry point" }, - { 0x5B6B, "ADDRSS entry with (DE) pointing to filename" }, - { 0x5B6F, "SCHEDL Entry point" }, - { 0x5B72, "SCHEDL entry with (DE) pointing to filename" }, - { 0x5BF5, "FIND instruction for ADDRSS/SCHEDL" }, - { 0x5BF7, "LFND instruction for ADDRSS/SCHEDL" }, - { 0x5C3F, "Find text at M in the file at (DE)" }, - { 0x5C6D, "Increment DE past next CRLF in text file at (DE)" }, - { 0x5C74, "Check next byte(s) at (DE) for CRLF" }, - { 0x5CEF, "ADDRSS/SCHEDL instruction vector table" }, - { 0x5D64, "Wait for char from keyboard & convert to uppercase" }, - { 0x5D6A, "Home cursor" }, - { 0x5D70, "Print time on top line until key pressed" }, - { 0x5DEE, "TEXT Entry point" }, - { 0x5E22, "TEXT Function key table - empty" }, - { 0x5E51, "EDIT statement" }, - { 0x5F2F, "Wait for a space to be entered on keyboard" }, - { 0x5F65, "Edit .DO files" }, - { 0x5FDD, "Main TEXT edit loop" }, - { 0x6018, "TEXT control character vector table" }, - { 0x6056, "TEST ESCape routine" }, - { 0x607C, "TEXT control P routine" }, - { 0x608A, "TEXT control I routine" }, - { 0x60BE, "TEXT control M routine" }, - { 0x60DE, "TEXT right arrow and control D routine" }, - { 0x60E2, "TEXT down arrow and control X routine" }, - { 0x610B, "TEXT control H routine" }, - { 0x6151, "TEXT left arrow and control S routine" }, - { 0x6155, "TEXT up arrow and control E routine" }, - { 0x617A, "TEXT control F routine" }, - { 0x618C, "TEXT control A routine" }, - { 0x61C2, "TEXT control T routine" }, - { 0x61D7, "TEXT control B routine" }, - { 0x61FD, "TEXT control R routine" }, - { 0x620B, "TEXT control Q routine" }, - { 0x6210, "TEXT control W routine" }, - { 0x621C, "TEXT control Z routine" }, - { 0x6242, "TEXT control L routine" }, - { 0x628F, "TEXT control C routine" }, - { 0x63E5, "Get next byte for TEXT Program entry" }, - { 0x6431, "TEXT control O routine" }, - { 0x6445, "TEXT control U routine" }, - { 0x6551, "TEXT control N routine" }, - { 0x65C3, "Copy NULL terminated string at M to (DE)" }, - { 0x6691, "TEXT control Y routine" }, - { 0x6713, "TEXT control G routine" }, - { 0x6774, "TEXT control V routine" }, - { 0x6B61, "Insert A into text file at M" }, - { 0x6B6D, "Insert BC spaces at M" }, - { 0x6B9F, "Delete BC characters at M" }, - { 0x6BDB, "Move BC bytes from M to (DE) with increment" }, - { 0x6BE6, "Move BC bytes from M to (DE) with decrement" }, - { 0x6BF1, "ROM programs catalog entries" }, - { 0x6C49, "BASIC Entry point" }, - { 0x6C93, "Copy BASIC Function key table to key definition area" }, - { 0x6C9C, "Copy BASIC Function key table to key definition area" }, - { 0x6CD6, "Re-initialize system without destroying files" }, - { 0x6CE0, "Warm start reset entry" }, - { 0x6D3F, "Send character in A to the printer" }, - { 0x6D6D, "Check RS232 queue for pending characters" }, - { 0x6D7E, "Get a character from RS232 receive queue" }, - { 0x6DAC, "RST 6.5 routine (RS232 receive interrupt)" }, - { 0x6DFC, "Calculate address to save next RS232 character" }, - { 0x6E0B, "Send XON (CTRL-Q) out RS232" }, - { 0x6E1E, "Turn off XON/XOFF protocol" }, - { 0x6E32, "Send character in A to serial port using XON/XOFF" }, - { 0x6E3A, "Send character in C to serial port" }, - { 0x6E4D, "Handle XON/XOFF protocol" }, - { 0x6E75, "Set RS232 baud rate stored in H" }, - { 0x6E94, "RS232 baud rate timer values" }, - { 0x6EA6, "Initialize RS232 or modem" }, - { 0x6ECB, "Deactivate RS232 or modem" }, - { 0x6EE5, "Click sound port if sound enabled" }, - { 0x6EEF, "Check for carrier detect" }, - { 0x6F31, "Enable XON/OFF when CTRL-S / CTRL-Q sent" }, - { 0x6F39, "Initialize serial buffer parameters" }, - { 0x6F46, "Write cassette header and sync byte" }, - { 0x6F5B, "Write char in A to cassette w/o checksum" }, - { 0x6F5B, "Write char in A to cassette w/o checksum or sync bit" }, - { 0x6F6A, "Write bit 0 of A to cassette" }, - { 0x6F85, "Read cassette header and sync byte" }, - { 0x6FDB, "Read Cassette port data bit" }, - { 0x7023, "Count and pack cassette input bits" }, - { 0x702A, "Read character from cassette w/o checksum" }, - { 0x7043, "Cassette REMOTE routine - turn motor on or off" }, - { 0x7055, "Keyboard scanning management routine" }, - { 0x7060, "Key detection -- Determine which keys are pressed" }, - { 0x70B0, "Key repeat detection" }, - { 0x70B0, "Calculate key matrix position and save buffer pointer at FFA8H" }, - { 0x7122, "Key detected - initialize repeat counter and decode" }, - { 0x7122, "Key decoding" }, - { 0x71D5, "Keyboard buffer management - place key in new buffer" }, - { 0x71D5, "Keyboard buffer management - place subsequent key in buffer" }, - { 0x71F7, "Interrupt exit routine (pop all regs & RET)" }, - { 0x720A, "Handle unshifted & non-CTRL key during key decoding" }, - { 0x7222, "Handle Arrow keys during key decoding" }, - { 0x722C, "Handle CAPS LOCK key during key decoding" }, - { 0x7233, "Handle NUM key during key decoding" }, - { 0x7242, "Scan keyboard for character (CTRL-BREAK ==> CTRL-C)" }, - { 0x726A, "Enable interrupts as normal" }, - { 0x7270, "Check keyboard queue for pending characters" }, - { 0x7283, "Check for break or wait (CTRL-S)" }, - { 0x729F, "Check if SHIFT-BREAK is being pressed" }, - { 0x72B1, "Scan BREAK,CAPS,NUM,CODE,GRAPH,CTRL,SHIFT & set bits in A" }, - { 0x72C5, "Produce a tone of DE freq and B duration" }, - { 0x7329, "Copy clock chip regs to M" }, - { 0x732A, "Update clock chip regs from M" }, - { 0x7352, "Read next bit from Clock Chip" }, - { 0x7383, "Set clock chip mode" }, - { 0x73A9, "Blink the cursor" }, - { 0x744C, "Plot (set) point (D,E) on the LCD" }, - { 0x73EE, "Character plotting level 7. Plot character in C on LCD at (H,L)" }, - { 0x744D, "Clear (reset) point (D,E) on the LCD" }, - { 0x74A2, "Byte Plot - Send bit pattern to LCD for character" }, - { 0x753B, "Enable LCD drivers after short delay" }, - { 0x7548, "Wait for LCD driver to be available" }, - { 0x7551, "8155 PIO chip bit patterns for LCD drivers" }, - { 0x7643, "8155 PIO chip bit patterns for LCD drivers" }, - { 0x7657, "Delay routine - decrement C until zero" }, - { 0x765C, "Set interrupt to 1DH" }, - { 0x7662, "Beep routine" }, - { 0x7676, "Click sound port" }, - { 0x7682, "Check for optional external controller" }, - { 0x768F, "Optional external controller driver" }, - { 0x7711, "LCD char generator shape table (20H-7FH" }, - { 0x78F1, "LCD char generator shape table (80H-FFH)" }, - { 0x7BF1, "Keyboard conversion matrix" }, - { 0x7D33, "Boot routine" }, - { 0x7DE7, "Cold boot routine" }, - { 0x7EA6, "Display TRS-80 Model number & Free bytes on LCD" }, - { 0x7EAC, "Display number of free bytes on LCD" }, - { 0x7EAC, "Initialize RST 38H RAM vector table" }, - { 0x7EE1, "Calculate physical RAM available" }, - { 0x7F01, "Initial clock chip register values" }, - { 0x7F98, "MENU Text Strings" }, - { 0x7FD6, "RST 38H RAM vector driver routine" }, - { 0xF5F9, "RST 5.5 RAM Vector" }, - { 0xF5FC, "RST 6.5 RAM Vector" }, - { 0xF5FF, "RST 7.5 RAM Vector" }, - { 0xF602, "RAM vector for TRAP interrupt" }, - { 0xF605, "Detect Option ROM" }, - { -1, "" }, + { 0x0000, R_RESET_VECTOR }, + { 0x0008, R_COMP_BYTE_M }, + { 0x0010, R_GET_NONWHITE }, + { 0x0018, R_COMP_DE_HL }, + { 0x001E, R_PRINT_SPACE }, + { 0x0020, R_PRINT_CHAR }, + { 0x0024, R_PWR_DOWN_TRAP }, + { 0x0028, R_DET_LAST_VAR_TYPE }, + { 0x002C, R_RST_5_5 }, + { 0x0030, R_GET_FAC1_SIGN }, + { 0x0034, R_RST_6_5 }, + { 0x0038, R_RAM_VCTR_TBL_DRIVER }, + { 0x003C, R_RST_7_5 }, + { 0x0040, R_FUN_VCTR_TBL }, + { 0x0080, R_BASIC_KEYWORD_TBL }, + { 0x018F, R_FUN_KEYWORD_TBL1 }, + { 0x01F0, R_FUN_KEYWORD_TBL2 }, + { 0x0262, R_BASIC_VECTOR_TBL }, + { 0x02E2, R_MATH_PRIORITY_TBL }, + { 0x02EE, R_MATH_VCTR_TBL }, + { 0x031C, R_BASIC_ERR_MSG_TXT }, + { 0x035A, R_FUN_INIT_IMAGE }, + { 0x036F, R_FUN_XROM_IMAGE }, + { 0x03EA, R_FUN_BASIC_STRINGS }, + { 0x0401, R_POP_FOR_NEXT }, + { 0x0422, R_INIT_AND_READY }, + { 0x0446, R_GEN_SN_ERROR }, + { 0x0449, R_GEN_d0_ERROR }, + { 0x044C, R_GEN_NF_ERROR }, + { 0x044F, R_GEN_DD_ERROR }, + { 0x0452, R_GEN_RW_ERROR }, + { 0x0455, R_GEN_OV_ERROR }, + { 0x0458, R_GEN_MO_ERROR }, + { 0x045B, R_GEN_TM_ERROR }, + { 0x045D, R_GEN_ERR_IN_E }, + { 0x048D, R_RESTORE_JMP_BC }, + { 0x04C5, R_PRINT_BASIC_ERR }, + { 0x0501, R_POP_GO_BASIC_RDY }, + { 0x0502, R_GO_BASIC_RDY_OK }, + { 0x0511, R_GO_BASIC_RDY }, + { 0x0523, R_PERFORM_M_GO_RDY }, + { 0x05F0, R_UPDATE_LINE_ADDR }, + { 0x060A, R_EVAL_LIST_ARGS }, + { 0x0628, R_FIND_LINE_IN_DE }, + { 0x062B, R_FIND_LINE_DE_AT_HL }, + { 0x0646, R_TOKEN_COMPRESS }, + { 0x0726, R_FOR_STMT }, + { 0x076B, R_TO_STMT }, + { 0x0783, R_STEP_STMT }, + { 0x0804, R_RUN_BASIC_PGRM }, + { 0x083A, R_RUN_BASIC_AT_HL }, + { 0x0840, R_EXEC_INST_IN_A }, + { 0x0858, R_RST_10H_INC_HL }, + { 0x0859, R_RST_10H }, + { 0x0872, R_DEF_STMT }, + { 0x0881, R_DEFDBL_STMT }, + { 0x0886, R_DEFINT_STMT }, + { 0x0896, R_DEFSNG_STMT }, + { 0x089F, R_DEFSTR_STMT }, + { 0x08A1, R_DECL_VAR_TYPE_E }, + { 0x08DB, R_GEN_FC_ERROR }, + { 0x08E0, R_EVAL_LINE_NUM }, + { 0x08EB, R_ASCII_TO_BIN }, + { 0x08EC, R_ASCII_TO_BIN_PREINC }, + { 0x090F, R_RUN_STMT }, + { 0x091E, R_GOSUB_STMT }, + { 0x0936, R_GOTO_STMT }, + { 0x094D, R_GEN_UL_ERROR }, + { 0x0966, R_RETURN_STMT }, + { 0x099E, R_DATA_STMT }, + { 0x09A0, R_REM_STMT }, + { 0x09C3, R_LET_STMT }, + { 0x0A2F, R_ON_STMT }, + { 0x0A34, R_ON_ERROR_STMT }, + { 0x0A5B, R_ON_KEY_STMT }, + { 0x0A94, R_ON_TIME_STMT }, + { 0x0AB0, R_RESUME_STMT }, + { 0x0B0F, R_ERROR_STMT }, + { 0x0B1A, R_IF_STMT }, + { 0x0B4E, R_LPRINT_STMT }, + { 0x0B56, R_PRINT_STMT }, + { 0x0C01, R_TAB_STMT }, + { 0x0C45, R_LINE_STMT }, + { 0x0C99, R_INPUT_NO_STMT }, + { 0x0CA3, R_INPUT_STMT }, + { 0x0CD9, R_READ_STMT }, + { 0x0DAB, R_EVAL_BASIC_INST }, + { 0x0F0D, R_INT16_DIV }, + { 0x0F1C, R_EVAL_FUN }, + { 0x0F47, R_ERR_FUN }, + { 0x0F56, R_ERL_FUN }, + { 0x0F7E, R_VARPTR_FUN }, + { 0x0F86, R_VARPTR_BUF_FUN }, + { 0x0F92, R_VARPTR_VAR_FUN }, + { 0x0FDA, R_EVAL_VAR }, + { 0x0FE8, R_CONV_M_TOUPPER }, + { 0x0FE9, R_CONV_A_TOUPPER }, + { 0x1037, R_ASCII_NUM_CONV }, + { 0x1054, R_NOT_FUN }, + { 0x1069, R_RST_28H }, + { 0x108C, R_OR_FUN }, + { 0x1097, R_AND_FUN }, + { 0x10A2, R_XOR_FUN }, + { 0x10AD, R_EQV_FUN }, + { 0x10B5, R_IMP_FUN }, + { 0x10C8, R_LPOS_FUN }, + { 0x10CE, R_POS_FUN }, + { 0x10D1, R_LD_FAC1_INT }, + { 0x10E6, R_CHK_RUNNING_PGRM }, + { 0x10EF, R_GEN_ID_ERROR }, + { 0x1100, R_INP_FUN }, + { 0x110C, R_OUT_STMT }, + { 0x1112, R_EVAL_EXPR }, + { 0x1113, R_EVAL_EXPR_PREDEC }, + { 0x112D, R_EVAL_EXPR }, + { 0x112E, R_EVAL_EXPR_PREDEC }, + { 0x113B, R_LLIST_STMT }, + { 0x1140, R_LIST_STMT }, + { 0x11A2, R_BUF_TO_LCD }, + { 0x1284, R_PEEK_FUN }, + { 0x128B, R_POKE_FUN }, + { 0x1297, R_EVAL_EXPR }, + { 0x12CB, R_WAIT_KEY }, + { 0x13A5, R_TOGGLE_LABEL }, + { 0x13DB, R_CHK_KEY_QUEUE }, + { 0x1419, R_POWER_STMT }, + { 0x1431, R_LOW_PWR_TRAP }, + { 0x143F, R_POWER_DOWN }, + { 0x1459, R_POWER_CONT_STMT }, + { 0x1461, R_POWER_ON_STMT }, + { 0x1470, R_OUT_CH_TO_LPT }, + { 0x148A, R_LOAD_CAS_HDR }, + { 0x1494, R_GEN_IO_ERROR }, + { 0x1499, R_DET_CAS_SYNC_HDR }, + { 0x14A8, R_CAS_MOTOR_ON }, + { 0x14AA, R_CAS_MOTOR_OFF }, + { 0x14B0, R_CAS_READ_BYTE }, + { 0x14C1, R_CAS_WRITE_BYTE }, + { 0x14D2, R_LCD_DCB }, + { 0x14D8, R_LCD_OPEN }, + { 0x14E5, R_LCD_OUT }, + { 0x14ED, R_POP_ALL_REGS }, + { 0x14F2, R_CRT_DCB }, + { 0x14FC, R_RAM_DCB }, + { 0x1506, R_RAM_OPEN }, + { 0x158D, R_RAM_CLOSE }, + { 0x15AC, R_RAM_OUT }, + { 0x15C4, R_RAM_IN }, + { 0x161B, R_RAM_IO }, + { 0x167F, R_CAS_DCB }, + { 0x1689, R_CAS_OPEN }, + { 0x16AD, R_CAS_CLOSE }, + { 0x16C7, R_CAS_OUT }, + { 0x16D2, R_CAS_IN }, + { 0x1754, R_LPT_DCB }, + { 0x175A, R_LPT_OUT }, + { 0x1762, R_COM_DCB }, + { 0x176C, R_MDM_OPEN }, + { 0x176D, R_COM_OPEN }, + { 0x179E, R_COM_CLOSE }, + { 0x17A8, R_COM_OUT }, + { 0x17B0, R_COM_IN }, + { 0x17CA, R_COM_IO }, + { 0x17D1, R_MDM_DCB }, + { 0x17DB, R_MDM_CLOSE }, + { 0x17E6, R_SET_RS232_PARAMS }, + { 0x1877, R_BCR_DCB }, + { 0x1889, R_EOF_FUN }, + { 0x1904, R_TIME_FUN }, + { 0x190F, R_READ_TIME }, + { 0x192F, R_DATE_FUN }, + { 0x1955, R_DAY_FUN }, + { 0x1962, R_READ_DAY }, + { 0x19A0, R_UPDATE_CLK_VALUES }, + { 0x19AB, R_TIME_STMT }, + { 0x19B3, R_UPDATE_CLK_CHIP }, + { 0x19BD, R_DATE_STMT }, + { 0x19F1, R_DAY_STMT }, + { 0x1A42, R_GET_TIME_STRING }, + { 0x1A78, R_IPL_STMT }, + { 0x1A96, R_ERASE_IPL_PRGM }, + { 0x1A9E, R_COM_MDM_STMT }, + { 0x1AB2, R_KEY_FUN }, + { 0x1AC3, R_KEY_ON_OFF_STMT }, + { 0x1AEA, R_DET_TIME_ARG }, + { 0x1AFC, R_DET_DEVICE_ARG }, + { 0x1B0F, R_ONTIME_STMT }, + { 0x1B22, R_ONCOM_STMT }, + { 0x1B32, R_RST7_5_ISR }, + { 0x1BB1, R_KICK_PWR_OFF_WDT }, + { 0x1BB8, R_KEY_STMT }, + { 0x1BBD, R_KEY_LIST_STMT }, + { 0x1BE0, R_SEND_CHARS_TO_LCD }, + { 0x1C57, R_PSET_STMT }, + { 0x1C66, R_PRESET_STMT }, + { 0x1C6D, R_LINE_STMT }, + { 0x1CA6, R_DRAW_FBOX }, + { 0x1CBC, R_DRAW_BOX }, + { 0x1D2E, R_TOKENIZE_XY }, + { 0x1D90, R_CSRLIN_FUN }, + { 0x1D9B, R_MAX_FUN }, + { 0x1DA7, R_MAXRAM_FUN }, + { 0x1DB2, R_MAXFILES_FUN }, + { 0x1DB9, R_HIMEM_FUN }, + { 0x1DC3, R_WIDTH_STMT }, + { 0x1DC5, R_SOUND_STMT }, + { 0x1DE5, R_SOUND_OFF_STMT }, + { 0x1DE6, R_SOUND_ON_STMT }, + { 0x1DEC, R_MOTOR_STMT }, + { 0x1DF1, R_MOTOR_ON_STMT }, + { 0x1DF5, R_MOTOR_OFF_STMT }, + { 0x1DFA, R_CALL_STMT }, + { 0x1E22, R_SCREEN_STMT }, + { 0x1E5E, R_LCOPY_STMT }, + { 0x1F3A, R_FILES_STMT }, + { 0x1F42, R_DISPLAY_CAT }, + { 0x1F91, R_KILL_STMT }, + { 0x1FBE, R_KILL_TEXT_FILE }, + { 0x2037, R_NAME_STMT }, + { 0x20FE, R_NEW_STMT }, + { 0x21FA, R_STRLEN }, + { 0x2206, R_GET_FIND_DO_FILE }, + { 0x220F, R_OPEN_TEXT_FILE }, + { 0x2280, R_CSAVE_STMT }, + { 0x22B9, R_CAS_WRITE_BUF }, + { 0x22CC, R_SAVEM_STMT }, + { 0x22DD, R_CSAVEM_STMT }, + { 0x2377, R_CLOAD_STMT }, + { 0x2413, R_CAS_READ_REC }, + { 0x2478, R_GEN_VERIFY_FAIL_ERR }, + { 0x2491, R_LOADM_STMT }, + { 0x24A7, R_CLOADM_STMT }, + { 0x2542, R_MOVE_B_BYTES }, + { 0x254B, R_EXEC_CO_FILE }, + { 0x260B, R_CAS_OPEN_OUT_BA }, + { 0x260E, R_CAS_OPEN_OUT_DO }, + { 0x2611, R_CAS_OPEN_OUT_CO }, + { 0x2650, R_CAS_OPEN_IN_BA }, + { 0x2653, R_CAS_OPEN_IN_DO }, + { 0x2656, R_CAS_OPEN_IN_CO }, + { 0x273A, R_STR_FUN }, + { 0x27B1, R_PRINT_STRING }, + { 0x290F, R_MOVE_L_BYTES }, + { 0x2943, R_LEN_FUN }, + { 0x294F, R_ASC_FUN }, + { 0x295F, R_CHR_FUN }, + { 0x296D, R_STRING_FUN }, + { 0x298E, R_SPACE_FUN }, + { 0x29AB, R_LEFT_FUN }, + { 0x29DC, R_RIGHT_FUN }, + { 0x29E6, R_MID_FUN }, + { 0x2A07, R_VAL_FUN }, + { 0x2A37, R_INSTR_FUN }, + { 0x2B4C, R_FRE_FUN }, + { 0x2B69, R_DBL_SUB }, + { 0x2B78, R_DBL_ADD }, + { 0x2C4F, R_BCD_ADD }, + { 0x2CFF, R_DBL_MULT }, + { 0x2DC7, R_DBL_DIV }, + { 0x2EE6, R_MOVE_C_BYTES }, + { 0x2EEF, R_COS_FUN }, + { 0x2F09, R_SIN_FUN }, + { 0x2F58, R_TAN_FUN }, + { 0x2F71, R_ATN_FUN }, + { 0x2FCF, R_LOG_FUN }, + { 0x305A, R_SQR_FUN }, + { 0x30A4, R_EXP_FUN }, + { 0x313E, R_RND_FUN }, + { 0x3182, R_INIT_TEMP3 }, + { 0x31A0, R_DBL_SQR }, + { 0x31A3, R_MULT_M_FAC2 }, + { 0x31B5, R_FAC2_EQ_FAC1 }, + { 0x31B8, R_FAC2_EQ_FP }, + { 0x31C1, R_FAC1_EQ_FAC2 }, + { 0x31C4, R_FAC1_EQ_FP }, + { 0x31CA, R_M_EQ_FAC1 }, + { 0x31CA, R_MULT_FAC1_SQR_FAC1 }, + { 0x31CA, R_SWAP_FAC1_FAC2 }, + { 0x31EB, R_SQR_FAC1_MULT_TBL }, + { 0x3209, R_TBL_BASED_MATH }, + { 0x322E, R_PUSH_FAC2 }, + { 0x3234, R_PUSH_FAC1 }, + { 0x3245, R_POP_FAC2 }, + { 0x324B, R_POP_FAC1 }, + { 0x325C, R_FP_NUMBERS }, + { 0x327C, R_FP_SHARED_NUMBERS }, + { 0x327E, R_FP_NUMBERS }, + { 0x32D6, R_EXP_MATH_TBL }, + { 0x32F7, R_EXP_MATH_TBL }, + { 0x3310, R_LOG_MATH_TBL }, + { 0x3331, R_LOG_MATH_TBL }, + { 0x335A, R_SIN_MATH_TBL }, + { 0x339B, R_ATN_MATH_TBL }, + { 0x33DC, R_RST_30H_FUN }, + { 0x33F2, R_ABS_FUN }, + { 0x3407, R_SGN_FUN }, + { 0x3422, R_PUSH_SNGL_FAC1 }, + { 0x342F, R_SNGL_FAC1_EQ_M }, + { 0x3432, R_SNGL_FAC1_EQ_BCDE }, + { 0x343D, R_SNGL_BCDE_EQ_FAC1 }, + { 0x3447, R_SNGL_BCDE_EQ_M }, + { 0x3450, R_SNGL_DECB_EQ_M }, + { 0x3459, R_SNGL_M_EQ_FAC1 }, + { 0x3461, R_LOAD_FAC2_FROM_M }, + { 0x3469, R_MOVE_B_BYTES_INC }, + { 0x3472, R_MOVE_B_BYTES_DEC }, + { 0x3498, R_SNGL_CMP_BCDE_FAC1 }, + { 0x34B0, R_SNGL_CMP_BCDE_M }, + { 0x34C2, R_SINT_CMP }, + { 0x34FA, R_CMP_FAC1_FAC2 }, + { 0x3501, R_CINT_FUN }, + { 0x3510, R_FAC1_EQ_SINT_HL }, + { 0x352A, R_CSNG_FUN }, + { 0x3540, R_CONV_SINT_SNGL }, + { 0x3543, R_CONV_SINT_HL_SNGL }, + { 0x35BA, R_CDBL_FUN }, + { 0x35F8, R_SINT_SUB }, + { 0x3645, R_FIX_FUN }, + { 0x3654, R_INT_FUN }, + { 0x3704, R_SINT_ADD }, + { 0x3725, R_SINT_MULT }, + { 0x377E, R_SINT_DIV }, + { 0x37F4, R_SNGL_ADD_BCDE }, + { 0x37F7, R_SNGL_ADD_FAC2 }, + { 0x37FD, R_SNGL_SUB }, + { 0x3803, R_SNGL_MULT_BCDE }, + { 0x3806, R_SNGL_MULT_FAC2 }, + { 0x380E, R_SNGL_DIV }, + { 0x3827, R_SNGL_LOAD }, + { 0x3840, R_ASCII_TO_DBL }, + { 0x3867, R_ASCII_FND_e }, + { 0x388A, R_ASCII_FND_E }, + { 0x3904, R_ASCII_FND_DOT }, + { 0x391A, R_ASCII_FND_PERC }, + { 0x3929, R_ASCII_FND_LB }, + { 0x3931, R_ASCII_CONV_HELPER }, + { 0x3940, R_ASCII_CONV_HELPER2 }, + { 0x39CC, R_PRNT_BASIC_ERR_TERM }, + { 0x39D4, R_PRINT_HL_ON_LCD }, + { 0x39E8, R_PRINT_FAC1 }, + { 0x39EC, R_PRINT_FAC1_FORMAT }, + { 0x3D11, R_FAC1_EQ_ZERO }, + { 0x3D7F, R_SNGL_EXP }, + { 0x3D8E, R_DBL_EXP }, + { 0x3DF7, R_INT_EXP }, + { 0x3F28, R_INIT_BASIC_VARS }, + { 0x3FA0, R_TIME_ON_STMT }, + { 0x3FB2, R_TIME_OFF_STMT }, + { 0x3FB9, R_TIME_STOP_STMT }, + { 0x3FD2, R_TRIG_INTR }, + { 0x3FF1, R_CLEAR_INTR }, + { 0x4009, R_CLEAR_COM_INT_DEF }, + { 0x407F, R_RESTORE_STMT }, + { 0x409A, R_STOP_STMT }, + { 0x409F, R_END_STMT }, + { 0x40DA, R_CONT_STMT }, + { 0x40F1, R_ISALPHA_M }, + { 0x40F2, R_ISALPHA_A }, + { 0x40F9, R_CLEAR_STMT }, + { 0x4174, R_NEXT_STMT }, + { 0x4222, R_SEND_CRLF }, + { 0x4225, R_SEND_LF }, + { 0x4229, R_BEEP_STMT }, + { 0x422D, R_HOME_CURSOR }, + { 0x4231, R_CLS_STMT }, + { 0x4235, R_PROTECT_LABEL }, + { 0x423A, R_UNPROT_LABEL }, + { 0x423F, R_STOP_AUTO_SCROLL }, + { 0x4244, R_RESUME_AUTO_SCROLL }, + { 0x4249, R_TURN_CURSOR_ON }, + { 0x424E, R_TURN_CURSOR_OFF }, + { 0x4253, R_DEL_CUR_LINE }, + { 0x4258, R_INSERT_LINE }, + { 0x425D, R_ERASE_TO_EOL }, + { 0x4262, R_SEND_ESC_X }, + { 0x4269, R_INV_CHAR_ENABLE }, + { 0x426E, R_INV_CHAR_DISABLE }, + { 0x4270, R_END_ESC_SEQ }, + { 0x4277, R_CURSOR_TO_LOW_LEFT }, + { 0x427C, R_SET_CURSOR_POS }, + { 0x428A, R_ERASE_FKEY_DISP }, + { 0x42A5, R_SET_DISP_FKEY }, + { 0x42A8, R_DISP_FKEY_LINE }, + { 0x4313, R_PRINT_A_TO_LCD }, +// { 0x4431, R_CHAR_PLOT_3 }, + { 0x4335, R_CHAR_PLOT_4 }, + { 0x434C, R_CHAR_PLOT_5 }, + { 0x4373, R_LCD_OUT_DRIVER }, + { 0x438A, R_RST_20H_LKUP_TBL }, + { 0x43AF, R_ESC_Y }, + { 0x43B2, R_LCD_OUT_ESC_FUN }, + { 0x43B8, R_LCD_ESC_LKUP_TBL }, + { 0x43FA, R_ESC_SEQ_DRIVER }, + { 0x4431, R_ESC_p_FUN }, + { 0x4432, R_ESC_q_FUN }, + { 0x4437, R_ESC_U_FUN }, + { 0x4439, R_ESC_T_FUN }, + { 0x443A, R_ESC_X_FUN }, + { 0x443F, R_ESC_V_FUN }, + { 0x4440, R_ESC_W_FUN }, + { 0x4453, R_ESC_C_FUN }, + { 0x445C, R_ESC_D_FUN }, + { 0x4461, R_BKSPACE_FUN }, + { 0x4469, R_ESC_A_FUN }, + { 0x446E, R_ESC_B_FUN }, + { 0x4480, R_TAB_FUN }, + { 0x4494, R_LF_FUN }, + { 0x44A8, R_ESC_H_FUN }, + { 0x44AA, R_CR_FUN }, + { 0x44AF, R_ESC_P_FUN }, + { 0x44BA, R_ESC_Q_FUN }, + { 0x44C4, R_ESC_M_FUN }, + { 0x44D2, R_LCD_SCROLL }, + { 0x44EA, R_ESC_L_FUN }, + { 0x4512, R_GET_LCD_CHAR }, + { 0x4535, R_ESC_l_FUN }, + { 0x4537, R_ESC_K_FUN }, + { 0x4548, R_CLS_FUN }, + { 0x454E, R_ESC_J_FUN }, + { 0x4560, R_CHAR_PLOT_6 }, + { 0x463E, R_INP_DISP_LINE }, + { 0x4644, R_INP_DISP_LINE_NO_Q }, + { 0x4684, R_INP_CTRL_C_HANDLER }, + { 0x4696, R_INP_ENTER_HANDLER }, + { 0x46A0, R_INP_BKSP_HANDLER }, + { 0x46C3, R_INP_CTRL_U_HANDLER }, + { 0x46CA, R_INP_TAB_HANDLER }, + { 0x478B, R_DIM_STMT }, + { 0x4790, R_FIND_VAR_ADDR }, + { 0x4991, R_USING_FUN }, + { 0x4B44, R_SEND_A_LCD_LPT }, + { 0x4B55, R_PRINT_A_EXPAND }, + { 0x4B92, R_SET_OUT_DEV_LCD }, + { 0x4BAB, R_LCD_CHAR_OUT_FUN }, + { 0x4BB8, R_LCD_NEW_LINE }, + { 0x4BEA, R_INKEY_FUN }, + { 0x4C84, R_GET_FILE_DESC }, + { 0x4CCB, R_OPEN_STMT }, + { 0x4D59, R_LCD_CLOSE_FUN }, + { 0x4D6E, R_RUN_STMT }, + { 0x4D70, R_LOAD_STMT }, + { 0x4D71, R_MERGE_STMT }, + { 0x4DCF, R_SAVE_STMT }, + { 0x4E28, R_CLOSE_STMT }, + { 0x4E8E, R_INPUT_STMT }, + { 0x4F0A, R_CLEAR_MEM }, + { 0x4F0B, R_LOAD_MEM }, + { 0x4F2E, R_PRINT_LB_INIT_FUN }, + { 0x4F5B, R_LINE_INPUT_STMT }, + { 0x504E, R_GEN_NM_ERR_FUN }, + { 0x5051, R_GEN_AO_ERR_FUN }, + { 0x5054, R_GEN_DS_ERR_FUN }, + { 0x5057, R_GEN_FF_ERR_FUN }, + { 0x505A, R_GEN_CF_ERR_FUN }, + { 0x505D, R_GEN_BN_ERR_FUN }, + { 0x5060, R_GEN_IE_ERR_FUN }, + { 0x5063, R_GEN_EF_ERR_FUN }, + { 0x5066, R_GEN_FL_ERR_FUN }, + { 0x506B, R_LOF_FUN }, + { 0x506D, R_LOC_FUN }, + { 0x506F, R_LFILES_FUN }, + { 0x5071, R_DSKO_FUN }, + { 0x5073, R_DSKI_FUN }, + { 0x50F1, R_DEV_NAME_TBL }, + { 0x5113, R_DCB_VCTR_TBL }, + { 0x5146, R_TELCOM_ENTRY }, + { 0x515B, R_TELCOM_RE_ENTRY }, + { 0x5185, R_TELCOM_INST_VCTR_TBL }, + { 0x51A4, R_TELCOM_LABEL_TXT }, + { 0x51C0, R_TELCOM_STAT_FUN }, + { 0x51C7, R_PRINT_TELCOM_STAT }, + { 0x51ED, R_SET_TELCOM_STAT }, + { 0x522F, R_TELCOM_CALL_FUN }, + { 0x524D, R_TELCOM_FIND_FUN }, + { 0x52B4, R_GO_OFFHOOK }, + { 0x52BB, R_DISCONNECT_PHONE }, + { 0x52D0, R_CONNECT_PHONE }, + { 0x52E4, R_GO_OFFHOOK_WAIT }, + { 0x5310, R_TELCOM_PAUSE }, + { 0x532D, R_EXEC_LOGON_SEQ }, + { 0x5359, R_DIALING_FUN }, + { 0x539E, R_AUTO_LOGIN_SEQ }, + { 0x540A, R_DIAL_DIGIT }, + { 0x5455, R_TELCOM_TERM_FUN }, + { 0x54FC, R_TELCOM_DISPATCH }, + { 0x550D, R_TERM_FKEY_VCTR_TBL }, + { 0x5523, R_TELCOM_PREV_FUN }, + { 0x553E, R_TELCOM_FULL_FUN }, + { 0x5550, R_TELCOM_ECHO_FUN }, + { 0x559D, R_TELCOM_UP_FUN }, + { 0x567E, R_TELCOM_DOWN_FUN }, + { 0x571E, R_TELCOM_BYE_FUN }, + { 0x5791, R_PRINT_STRING }, + { 0x5797, R_MENU_ENTRY }, + { 0x57F8, R_DISP_DIR }, + { 0x5837, R_MENU_CTRL_U_HANDLER }, + { 0x585A, R_MENU_CMD_LOOP }, + { 0x588E, R_MENU_BKSP_HANDLER }, + { 0x58F7, R_MENU_ENTER_HANDLER }, + { 0x596F, R_EXEC_ROM_FILE }, + { 0x5970, R_DISP_DIR_TYPE_C }, + { 0x59AD, R_CONV_FILENAME }, + { 0x59C9, R_NEXT_DIR_ENTRY }, + { 0x5A12, R_CLS_PRINT_TIME_DAY }, + { 0x5A15, R_PRINT_TIME_DAY }, + { 0x5A58, R_PRINT_STRING2 }, + { 0x5A62, R_COPY_MEM_DE_M }, + { 0x5A6D, R_CMP_MEM_DE_M }, + { 0x5A79, R_CLEAR_FKEY_TBL }, + { 0x5A7C, R_SET_FKEYS }, + { 0x5A9E, R_DISP_FKEYS }, + { 0x5AA9, R_SEARCH_DIR }, + { 0x5AE3, R_GET_FILE_ADDR }, + { 0x5B1E, R_DIR_DISP_ORDER_TBL }, + { 0x5B68, R_ADDRSS_ENTRY }, + { 0x5B6B, R_ADDRSS_ENTRY_W_FILE }, + { 0x5B6F, R_SCHEDL_ENTRY }, + { 0x5B72, R_SCHEDL_ENTRY_W_FILE }, + { 0x5BF5, R_ADDRSS_FIND_FUN }, + { 0x5BF7, R_ADDRSS_LFND_FUN }, + { 0x5C3F, R_FIND_TEXT_IN_FILE }, + { 0x5C6D, R_FIND_NEXT_LINE_IN_FILE }, + { 0x5C74, R_CHECK_FOR_CRLF }, + { 0x5CEF, R_ADDRSS_INST_VCTR_TBL }, + { 0x5D64, R_GET_KEY_CONV_TOUPPER }, + { 0x5D6A, R_SEND_CURSOR_HOME }, + { 0x5D70, R_PRINT_TIME_LOOP }, + { 0x5DEE, R_TEXT_ENTRY }, + { 0x5E22, R_TEXT_FKEY_TBL }, + { 0x5E51, R_EDIT_STMT }, + { 0x5F2F, R_WAIT_FOR_SPACE_KEY }, + { 0x5F65, R_EDIT_DO_FILE_FUN }, + { 0x5FDD, R_TEXT_EDIT_LOOP }, + { 0x6018, R_TEXT_CTRL_VCTR_TBL }, + { 0x6056, R_TEXT_ESC_FUN }, + { 0x607C, R_TEXT_CTRL_P_FUN }, + { 0x608A, R_TEXT_CTRL_I_FUN }, + { 0x60BE, R_TEXT_CTRL_M_FUN }, + { 0x60DE, R_TEXT_CTRL_D_FUN }, + { 0x60E2, R_TEXT_CTRL_X_FUN }, + { 0x610B, R_TEXT_CTRL_H_FUN }, + { 0x6151, R_TEXT_CTRL_S_FUN }, + { 0x6155, R_TEXT_CTRL_E_FUN }, + { 0x617A, R_TEXT_CTRL_F_FUN }, + { 0x618C, R_TEXT_CTRL_A_FUN }, + { 0x61C2, R_TEXT_CTRL_T_FUN }, + { 0x61D7, R_TEXT_CTRL_B_FUN }, + { 0x61FD, R_TEXT_CTRL_R_FUN }, + { 0x620B, R_TEXT_CTRL_Q_FUN }, + { 0x6210, R_TEXT_CTRL_W_FUN }, + { 0x621C, R_TEXT_CTRL_Z_FUN }, + { 0x6242, R_TEXT_CTRL_L_FUN }, + { 0x628F, R_TEXT_CTRL_C_FUN }, + { 0x63E5, R_TEXT_GET_NEXT_BYTE }, + { 0x6431, R_TEXT_CTRL_O_FUN }, + { 0x6445, R_TEXT_CTRL_U_FUN }, + { 0x6551, R_TEXT_CTRL_N_FUN }, + { 0x65C3, R_COPY_NULL_STRING }, + { 0x6691, R_TEXT_CTRL_Y_FUN }, + { 0x6713, R_TEXT_CTRL_G_FUN }, + { 0x6774, R_TEXT_CTRL_V_FUN }, + { 0x6B61, R_INSERT_A_INTO_FILE }, + { 0x6B6D, R_INSERT_SPACES }, + { 0x6B9F, R_DELETE_CHARS }, + { 0x6BDB, R_MOVE_BC_BYTES_INC }, + { 0x6BE6, R_MOVE_BC_BYTES_DEC }, + { 0x6BF1, R_ROM_CAT_ENTRIES }, + { 0x6C49, R_BASIC_ENTRY }, + { 0x6C93, R_LOAD_BASIC_FKEYS }, + { 0x6C9C, R_LOAD_BASIC_FKEYS }, + { 0x6CD6, R_RE_INIT_SYSTEM }, + { 0x6CE0, R_WARM_RESET }, + { 0x6D3F, R_SEND_A_TO_LPT }, + { 0x6D6D, R_CHECK_RS232_QUEUE }, + { 0x6D7E, R_READ_RS232_QUEUE }, + { 0x6DAC, R_RST_6_5_FUN }, + { 0x6DFC, R_INC_RS232_QUEUE_IN }, + { 0x6E0B, R_SEND_XON }, + { 0x6E1E, R_DISABLE_XON_XOFF }, + { 0x6E32, R_SEND_A_USING_XON }, + { 0x6E3A, R_SEND_C_TO_RS232 }, + { 0x6E4D, R_XON_XOFF_HANDLER }, + { 0x6E75, R_SET_RS232_BAUD_RATE }, + { 0x6E94, R_RS232_BAUD_TIMER_VALS }, + { 0x6EA6, R_INIT_RS232_MDM }, + { 0x6ECB, R_UNINIT_RS232_MDM }, + { 0x6EE5, R_CLICK_SND_PORT }, + { 0x6EEF, R_CHECK_CD }, + { 0x6F31, R_ENABLE_XON_XOFF }, + { 0x6F39, R_INIT_SER_BUF_PARAMS }, + { 0x6F46, R_CAS_WRITE_HEADER }, + { 0x6F5B, R_CAS_WRITE_NO_CHKSUM }, + { 0x6F5B, R_CAS_WRITE_NO_SYNC }, + { 0x6F6A, R_CAS_WRITE_BIT }, + { 0x6F85, R_CAS_READ_HEADER }, + { 0x6FDB, R_CAS_READ_BIT }, + { 0x7023, R_CAS_COUNT_BITS }, + { 0x702A, R_CAS_READ_NO_CHKSUM }, + { 0x7043, R_CAS_REMOTE_FUN }, + { 0x7055, R_KEYSCAN_MGT_FUN }, + { 0x7060, R_KEY_DETECTION }, + { 0x70B0, R_KEY_REPEAT_DET }, +// { 0x70B0, R_GET_KEY_MATRIX }, +// { 0x7122, R_INIT_KEY_RPT_CNT }, + { 0x7122, R_KEY_DECODE }, + { 0x71D5, R_KEY_FIRST_IN_BUF }, + { 0x71E4, R_KEY_ADD_TO_BUF }, + { 0x71F7, R_ISR_EXIT_FUN }, + { 0x720A, R_UNSHIFTED_KEY }, + { 0x7222, R_ARROW_KEY }, + { 0x722C, R_CAPS_LOCK_KEY }, + { 0x7233, R_NUM_KEY }, + { 0x7242, R_SCAN_KEYBOARD }, + { 0x726A, R_ENABLE_INTERRUPTS }, + { 0x7270, R_CHK_PENDING_KEYS }, + { 0x7283, R_CHK_BREAK }, + { 0x729F, R_CHK_SHIFT_BREAK }, + { 0x72B1, R_SCAN_SPECIAL_KEYS }, + { 0x72C5, R_GEN_TONE }, + { 0x7329, R_GET_CLK_CHIP_REGS }, + { 0x732A, R_PUT_CLK_CHIP_REGS }, + { 0x7352, R_READ_CLK_CHIP_BIT }, + { 0x7383, R_SET_CLK_CHIP_MODE }, + { 0x73A9, R_BLINK_CURSOR }, + { 0x73EE, R_CHAR_PLOT_7 }, + { 0x744C, R_PLOT_POINT }, + { 0x744D, R_CLEAR_POINT }, + { 0x74A2, R_LCD_BYTE_PLOT }, + { 0x753B, R_ENABLE_LCD_DRIVER }, + { 0x7548, R_WAIT_LCD_DRIVER }, + { 0x7551, R_LCD_BIT_PATTERNS }, + { 0x7643, R_LCD_BIT_PATTERNS }, + { 0x7657, R_DELAY_FUN }, + { 0x765C, R_SET_INTR_1DH }, + { 0x7662, R_BEEP_FUN }, + { 0x7676, R_CLICK_SOUND_PORT }, + { 0x7682, R_CHK_XTRNL_CNTRLER }, + { 0x768F, R_XTRNL_CNTRLER_DRIVER }, + { 0x7711, R_LCD_CHAR_SHAPE_TBL1 }, + { 0x78F1, R_LCD_CHAR_SHAPE_TBL2 }, + { 0x7BF1, R_KEYBOARD_CONV_MATRIX }, + { 0x7D33, R_BOOT_ROUTINE }, + { 0x7DE7, R_COLD_BOOT }, + { 0x7EA6, R_DISP_MODEL }, + { 0x7EAC, R_DISP_FREE_BYTES }, + { 0x7EC6, R_INIT_RST_38H_TBL }, + { 0x7EE1, R_CALC_FREE_RAM }, + { 0x7F01, R_INIT_CLK_CHIP_REGS }, + { 0x7F98, R_MENU_TEXT_STRINGS }, + { 0x7FD6, R_RST_38H_DRIVER }, + { 0xF5F9, R_RST_5_5_VECTOR }, + { 0xF5FC, R_RST_6_5_VECTOR }, + { 0xF5FF, R_RST_7_5_VECTOR }, + { 0xF602, R_TRAP_VECTOR }, + { 0xF605, R_DETECT_OPTION_ROM }, + { -1, -1 } }; RomDescription_t gM100_Desc = { @@ -985,7 +997,9 @@ RomDescription_t gM100_Desc = { 0xFAC0, /* Lowest RAM used by system */ 0xF962, /* Start of RAM directory */ 0xF678, /* BASIC string buffer pointer */ + 0xFAD8, /* BASIC Size */ - 24 /* Number of directory entries */ + 24, /* Number of directory entries */ + 8 /* Index of first Dir entry */ }; diff --git a/src/m200rom.c b/src/m200rom.c new file mode 100644 index 0000000..17b48aa --- /dev/null +++ b/src/m200rom.c @@ -0,0 +1,990 @@ +/* m100rom.c */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "roms.h" +#include "romstrings.h" + + +Std_ROM_Table_t gM200_Tables[] = { + { 0x0003, 5, TABLE_TYPE_STRING }, + { 0x0040, 64, TABLE_TYPE_JUMP }, + { 0x0080, 271, TABLE_TYPE_MODIFIED_STRING }, + { 0x018F, 97, TABLE_TYPE_MODIFIED_STRING }, + { 0x01F0, 112, TABLE_TYPE_MODIFIED_STRING }, + { 0x0262, 140, TABLE_TYPE_JUMP }, + { 0x02EE, 46, TABLE_TYPE_JUMP }, + { 0x031C, 62, TABLE_TYPE_2BYTE }, + { 0x0372, 163, TABLE_TYPE_CODE }, + { 0x0415, 23, TABLE_TYPE_STRING }, + { 0x0C9F, 19, TABLE_TYPE_STRING }, + { 0x0D9C, 17, TABLE_TYPE_STRING }, + { 0x15E9, 6, TABLE_TYPE_JUMP }, + { 0x1609, 6, TABLE_TYPE_JUMP }, + { 0x1613, 10, TABLE_TYPE_JUMP }, + { 0x17AD, 10, TABLE_TYPE_JUMP }, + { 0x1882, 6, TABLE_TYPE_JUMP }, + { 0x1890, 10, TABLE_TYPE_JUMP }, + { 0x1908, 10, TABLE_TYPE_JUMP }, + { 0x19E6, 8, TABLE_TYPE_JUMP }, + { 0x1ADB, 21, TABLE_TYPE_3BYTE }, + { 0x21AF, 16, TABLE_TYPE_STRING }, + { 0x2D6B, 8, TABLE_TYPE_STRING }, + { 0x31F1, 16, TABLE_TYPE_STRING }, + { 0x333A, 18, TABLE_TYPE_STRING }, + { 0x3464, 14, TABLE_TYPE_STRING }, + { 0x3FAD, 32, TABLE_TYPE_CODE }, + { 0x3FCD, 2, TABLE_TYPE_CODE }, + { 0x3FCF, 88, TABLE_TYPE_CODE }, + { 0x4027, 1, TABLE_TYPE_CODE }, + { 0x4028, 32, TABLE_TYPE_CODE }, + { 0x4048, 1, TABLE_TYPE_CODE }, + { 0x4049, 24, TABLE_TYPE_CODE }, + { 0x4061, 1, TABLE_TYPE_CODE }, + { 0x4062, 32, TABLE_TYPE_CODE }, + { 0x4082, 1, TABLE_TYPE_CODE }, + { 0x4083, 40, TABLE_TYPE_CODE }, + { 0x40AB, 1, TABLE_TYPE_CODE }, + { 0x40AC, 64, TABLE_TYPE_CODE }, + { 0x40EC, 1, TABLE_TYPE_CODE }, + { 0x40ED, 64, TABLE_TYPE_CODE }, + { 0x50AD, 24, TABLE_TYPE_BYTE_LOOKUP }, + { 0x50DB, 80, TABLE_TYPE_BYTE_LOOKUP }, + { 0x5521, 21, TABLE_TYPE_BYTE_LOOKUP }, + { 0x5FA8, 33, TABLE_TYPE_CTRL_DELIM }, + { 0x5FCA, 16, TABLE_TYPE_JUMP }, + { 0x6033, 9, TABLE_TYPE_STRING }, + { 0x603C, 30, TABLE_TYPE_4BYTE_CMD }, + { 0x605A, 1, TABLE_TYPE_CODE }, + { 0x605B, 28, TABLE_TYPE_CTRL_DELIM }, + { 0x6142, 9, TABLE_TYPE_STRING }, + { 0x6363, 18, TABLE_TYPE_CTRL_DELIM }, + { 0x648A, 16, TABLE_TYPE_JUMP }, + { 0x649A, 1, TABLE_TYPE_CODE }, + { 0x64FD, 18, TABLE_TYPE_STRING }, + { 0x650F, 6, TABLE_TYPE_STRING }, + { 0x6515, 2, TABLE_TYPE_CODE }, + { 0x674F, 79, TABLE_TYPE_STRING }, + { 0x6802, 14, TABLE_TYPE_STRING }, + { 0x6869, 17, TABLE_TYPE_STRING }, + { 0x6903, 18, TABLE_TYPE_STRING }, + { 0x696B, 97, TABLE_TYPE_STRING }, + { 0x69F1, 21, TABLE_TYPE_STRING }, + { 0x6AD1, 9, TABLE_TYPE_STRING }, + { 0x6AE0, 6, TABLE_TYPE_STRING }, + { 0x6CA9, 8, TABLE_TYPE_STRING }, + { 0x6E92, 36, TABLE_TYPE_3BYTE }, + { 0x6EB6, 6, TABLE_TYPE_CODE }, + { 0x6EBC, 9, TABLE_TYPE_CODE }, + { 0x6EC5, 34, TABLE_TYPE_CTRL_DELIM }, + { 0x6F16, 11, TABLE_TYPE_STRING }, + { 0x7030, 18, TABLE_TYPE_STRING }, + { 0x70D7, 22, TABLE_TYPE_STRING }, + { 0x70ED, 18, TABLE_TYPE_4BYTE_CMD }, + { 0x7106, 8, TABLE_TYPE_STRING }, + { 0x710E, 55, TABLE_TYPE_CTRL_DELIM }, + { 0x71C5, 15, TABLE_TYPE_STRING }, + { 0x71D4, 8, TABLE_TYPE_CODE }, + { 0x71DC, 36, TABLE_TYPE_CTRL_DELIM }, + { 0x72EE, 17, TABLE_TYPE_STRING }, + { 0x72FF, 2, TABLE_TYPE_CODE }, + { 0x7301, 21, TABLE_TYPE_STRING }, + { 0x7316, 5, TABLE_TYPE_STRING }, + { 0x73CF, 64, TABLE_TYPE_JUMP }, + { 0x7492, 13, TABLE_TYPE_STRING }, + { 0x79C3, 17, TABLE_TYPE_STRING }, + { 0x7D04, 28, TABLE_TYPE_STRING }, + { 0x7D2C, 84, TABLE_TYPE_STRING }, + { 0x7DFF, 9, TABLE_TYPE_STRING }, + { 0x7316, 5, TABLE_TYPE_STRING }, + { 0x7E9E, 11, TABLE_TYPE_STRING }, + { 0x832C, 66, TABLE_TYPE_CATALOG }, + { 0x836E, 4, TABLE_TYPE_CODE }, + { 0x86CC, 18, TABLE_TYPE_JUMP }, +// { 0x7551, 240, TABLE_TYPE_CODE }, +// { 0x7643, 20, TABLE_TYPE_CODE }, + { 0x905E, 5, TABLE_TYPE_CODE }, + { 0x9063, 96*8, TABLE_TYPE_CODE }, + { 0x9363, 128*8, TABLE_TYPE_CODE }, + { 0x9763, 322, TABLE_TYPE_CODE }, + { 0x9B54, 14, TABLE_TYPE_CODE }, + { 0x9C4E, 31, TABLE_TYPE_STRING }, + { 0x9C6E, 23, TABLE_TYPE_STRING }, + { 0x9F76, 12, TABLE_TYPE_STRING }, + { -1, 0, 0 } +}; + +Std_ROM_Addresses_t gM200_Vars[] = { + { 0x0040, R_FUN_VCTR_TBL }, + { 0x0080, R_BASIC_TBL }, + { 0x018F, R_FUN_TBL_TAB }, + { 0x01F0, R_FUN_TBL_SGN }, + { 0x0262, R_BASIC_VCTR_TBL }, + { 0x02EE, R_MATH_VCTR_TBL }, + { 0x031A, R_BASIC_ERR_TXT }, + { 0x035A, R_INIT_IMAGE }, + { 0x0372, R_XROM_DET_IMAGE }, + { 0x0415, R_BASIC_STRINGS }, + { 0x1F24, R_CAS_FREQ_CNT }, + { 0x4349, R_CAS_FREQ_CNT }, + { 0x649A, R_TERM_FKEY_VCTR_TBL }, + { 0x5B1E, R_DIR_DISP_ORDER_TBL }, + { 0x6EB6, R_TEXT_FKEY_VCTR_TBL }, + { 0x6BF1, R_ROM_CAT_ENTRIES }, + { 0x832C, R_INT_EXIT_FUN }, + { 0x8AB9, R_INT_EXIT_FUN }, + { 0x9B54, R_INIT_CLK_VALUES }, + { 0x7F98, R_MENU_STRINGS }, + { 0x9C4E, R_MODEL_NUM_STRING }, + { 0xEEB0, R_ACTIVE_SIGNATURE }, + { 0xF5F4, R_HIMEM }, + { 0xEEB4, R_RST_5_5_VCTR }, + { 0xEEBF, R_RST_6_5_VCTR }, + { 0xEEC2, R_RST_7_5_VCTR }, + { 0xEEC5, R_TRAP_VCTR }, + { 0xEEF3, R_OPTION_ROM_FLAG }, + { 0xEF44, R_DIAL_SPEED }, + { 0xEEFD, R_FKEY_STAT_TBL }, + { 0xEF05, R_NEW_CONSOLE_FLAG }, + { 0xEF06, R_CURSOR_ROW }, + { 0xEF07, R_CURSOR_COL }, + { 0xEF08, R_ACTIVE_ROW_CNT }, + { 0xEF09, R_ACTIVE_COL_CNT }, + { 0xEF0A, R_LABEL_LINE_PROT }, + { 0xEF0B, R_SCROLL_DISABLE }, + { 0xEF0C, R_CURSOR_STAT }, + { 0xEF0D, R_CURSOR_ROW2 }, + { 0xEF13, R_ESC_MODE_FLAG }, + { 0xEF15, R_REV_VID_SWITCH }, + { 0xEF30, R_LAST_PLOT_X }, + { 0xEF31, R_LAST_PLOT_Y }, + { 0xEF37, R_PWR_OFF_STAT }, + { 0xEF39, R_DUPLEX_SWITCH }, + { 0xEF3B, R_RS232_LF_SWITCH }, + { 0xEF3C, R_RS232_PARAM_TBL }, + { 0xEF49, R_ADDRESS_LAST_CALLED }, + { 0xEF52, R_OUT_STMT_HOOK }, + { 0xEF55, R_INP_STMT_HOOK }, + { 0xEF5D, R_LAST_ERROR_CODE }, + { 0xEF5F, R_LPT_HEAD_POS }, + { 0xEF60, R_OUTPUT_DEVICE }, + { 0xEF63, R_BASIC_STR_BUF_PTR }, + { 0xEF65, R_CUR_BASIC_LINE_NUM }, + { 0xEF67, R_START_BASIC_PGM_PTR }, + { 0xEF6B, R_END_OF_STMT_MARKER }, + { 0xEF70, R_KEYBOARD_BUF }, + { 0xF073, R_CURSOR_H_POS }, + { 0xF074, R_FKEY_DEF_BUF }, + { 0xF0F5, R_BASIC_FKEY_DEF_BUF }, + { 0xF177, R_FILE_RAM_END }, + { 0xF212, R_SEC_ONES }, + { 0xF213, R_SEC_TENS }, + { 0xF214, R_MIN_ONES }, + { 0xF215, R_MIN_TENS }, + { 0xF216, R_HR_ONES }, + { 0xF217, R_HR_TENS }, + { 0xF218, R_DATE_ONES }, + { 0xF219, R_DATE_TENS }, + { 0xF21A, R_DAY_CODE }, + { 0xF21B, R_MONTH }, + { 0xF21C, R_YEAR_ONES }, + { 0xF21D, R_YEAR_TENS }, + { 0xF764, R_SEC_ONES2 }, + { 0xF765, R_SEC_TENS2 }, + { 0xF766, R_MIN_ONES2 }, + { 0xF767, R_MIN_TENS2 }, + { 0xF768, R_HR_ONES2 }, + { 0xF769, R_HR_TENS2 }, + { 0xF76A, R_DATE_ONES2 }, + { 0xF76B, R_DATE_TENS2 }, + { 0xF76C, R_DAY_CODE2 }, + { 0xF22D, R_ONTIME_TIME }, + { 0xF234, R_ONCOM_FLAG }, + { 0xF235, R_ONCOM_ADDRESS }, + { 0xF237, R_ONTIME_FLAG }, + { 0xF252, R_DIR_RAM_START }, + { 0xF295, R_UNSAVED_BASIC_PTR }, + { 0xF2A0, R_PASTE_RAM_START }, + { 0xF4DB, R_LAST_CHAR_PRINTED }, + { 0xF4DC, R_LABEL_ENABLE_FLAG }, + { 0xFCFF, R_PORT_A8H }, + { 0xF4DD, R_IPL_FILENAME_START }, + { 0xF4E8, R_BASIC_LIST_START }, + { 0xF4EC, R_SP_SAVE_BUF }, + { 0xF4EE, R_LOWEST_RAM }, + { 0xF4F7, R_RST_38H_OFFSET }, + { 0xF4FD, R_LAST_PGRM_LEN }, + { 0xF507, R_RST_38H_VCTR_TBL }, + { 0xF617, R_VAR_CREATE_LOC_FLAG }, + { 0xF618, R_LAST_VAR_TYPE }, + { 0xF61A, R_FILE_BUF_PTR }, + { 0xF647, R_DATA_STMT_LINE_NUM }, + { 0xF649, R_FOR_NEXT_ACTIVE_FLAG }, + { 0xF64C, R_LAST_VAR_ASSIGNED_ADDR }, + { 0xF64E, R_RUNNING_LINE_NUM_ADDR }, + { 0xF650, R_BASIC_SP_BUF }, + { 0xF652, R_LAST_ERR_LINE_NUM }, + { 0xF654, R_LAST_ENTERED_LINE_NUM }, + { 0xF656, R_ERR_PTR }, + { 0xF658, R_ONERROR_ADDRESS }, + { 0xF65A, R_BASIC_RUNNING}, + { 0xF65D, R_BREAK_LINE_NUM }, + { 0xF65F, R_BREAK_ADDRESS }, + { 0xF661, R_DO_FILES_PTR }, + { 0xF663, R_CO_FILES_PTR }, + { 0xF665, R_VAR_PTR }, + { 0xF667, R_ARRAY_TBL_PTR }, + { 0xF669, R_UNUSED_MEM_PTR }, + { 0xF66B, R_DATA_SEARCH_ADDR }, + { 0xF66D, R_DEF_TBL }, + { 0xF69A, R_FP_TEMP1 }, + { 0xF6CB, R_FP_FAC1 }, + { 0xF6CD, R_INT_FAC1 }, + { 0xF713, R_FP_TEMP2 }, + { 0xF71C, R_FP_FAC2 }, + { 0xF71E, R_INT_FAC2 }, + { 0xF72C, R_FP_TEMP3 }, + { 0xF735, R_MAXFILES }, + { 0xF736, R_FILE_NUM_TBL_PTR }, + { 0xF746, R_BASIC_FILENAME }, + { 0xF74F, R_LAST_LOAD_FILENAME }, + { 0xF7B0, R_ALT_LCD_CHAR_BUF }, + { 0xF7C9, R_MENU_TO_RAM_MAP }, + { 0xF848, R_CUR_MENU_DIR_LOC }, + { 0xF849, R_MAX_MENU_DIR_LOC }, + { 0xFCF0, R_XON_XOFF_CTRL }, + { 0xFCF1, R_XON_XOFF_CTRL }, + { 0xFCF2, R_XON_XOFF_ENABLE }, + { 0xFCF3, R_RS232_INIT_STAT }, + { 0xFCF4, R_SOUND_FLAG }, + { 0xFCFF, R_PORT_E8H }, + { 0xFFBB, R_RS232_CHAR_BUF }, + { 0xFCF5, R_RS232_BUF_CNT }, + { 0xFCF6, R_RS232_BUF_OUT }, + { 0xFCF7, R_RS232_BUF_IN }, + { 0xFCF9, R_CTRL_S_STAT }, + { 0xFCFA, R_UART_BAUD_TIMER_VAL }, + { 0xFCFC, R_RS232_PARITY_CTRL }, + { 0xFCFD, R_CAS_PULSE_CTRL }, + { 0xFD0D, R_KEY_SCAN_STORAGE1 }, + { 0xFD16, R_KEY_SCAN_STORAGE2 }, + { 0xFD17, R_SHIFT_KEY_STAT }, + { 0xFD18, R_KEY_REPT_START }, + { 0xFD1A, R_KEY_POSITION }, + { 0xFD1C, R_2ND_KEY_BUF_PTR }, + { 0xFD1E, R_KEY_BUF_CNT }, + { 0xFD60, R_CURSOR_BIT_PAT_BUF }, + { -1, -1 } +}; + +Std_ROM_Addresses_t gM200_Funs[] = { + { 0x0000, R_RESET_VECTOR }, + { 0x0008, R_COMP_BYTE_M }, + { 0x0010, R_GET_NONWHITE }, + { 0x0018, R_COMP_DE_HL }, + { 0x001E, R_PRINT_SPACE }, + { 0x0020, R_PRINT_CHAR }, + { 0x0024, R_PWR_DOWN_TRAP }, + { 0x0028, R_DET_LAST_VAR_TYPE }, + { 0x002C, R_RST_5_5 }, + { 0x0030, R_GET_FAC1_SIGN }, + { 0x0034, R_RST_6_5 }, + { 0x0038, R_RAM_VCTR_TBL_DRIVER }, + { 0x003C, R_RST_7_5 }, + { 0x0040, R_FUN_VCTR_TBL }, + { 0x0080, R_BASIC_KEYWORD_TBL }, + { 0x018F, R_FUN_KEYWORD_TBL1 }, + { 0x01F0, R_FUN_KEYWORD_TBL2 }, + { 0x0262, R_BASIC_VECTOR_TBL }, + { 0x02E2, R_MATH_PRIORITY_TBL }, + { 0x02EE, R_MATH_VCTR_TBL }, + { 0x031C, R_BASIC_ERR_MSG_TXT }, + { 0x035A, R_FUN_INIT_IMAGE }, + { 0x0372, R_FUN_XROM_IMAGE }, + { 0x0415, R_FUN_BASIC_STRINGS }, + { 0x042C, R_POP_FOR_NEXT }, + { 0x044D, R_INIT_AND_READY }, + { 0x0471, R_GEN_SN_ERROR }, + { 0x0474, R_GEN_d0_ERROR }, + { 0x0477, R_GEN_NF_ERROR }, + { 0x047A, R_GEN_DD_ERROR }, + { 0x047D, R_GEN_RW_ERROR }, + { 0x0480, R_GEN_OV_ERROR }, + { 0x0483, R_GEN_MO_ERROR }, + { 0x0486, R_GEN_TM_ERROR }, + { 0x0488, R_GEN_ERR_IN_E }, + { 0x04B8, R_RESTORE_JMP_BC }, + { 0x04F0, R_PRINT_BASIC_ERR }, + { 0x052C, R_POP_GO_BASIC_RDY }, + { 0x052D, R_GO_BASIC_RDY_OK }, + { 0x053C, R_GO_BASIC_RDY }, + { 0x054E, R_PERFORM_M_GO_RDY }, + { 0x061B, R_UPDATE_LINE_ADDR }, + { 0x0635, R_EVAL_LIST_ARGS }, + { 0x0653, R_FIND_LINE_IN_DE }, + { 0x0656, R_FIND_LINE_DE_AT_HL }, + { 0x0671, R_TOKEN_COMPRESS }, + { 0x0751, R_FOR_STMT }, + { 0x0796, R_TO_STMT }, + { 0x07AE, R_STEP_STMT }, + { 0x082F, R_RUN_BASIC_PGRM }, + { 0x0865, R_RUN_BASIC_AT_HL }, + { 0x086B, R_EXEC_INST_IN_A }, + { 0x0883, R_RST_10H_INC_HL }, + { 0x0884, R_RST_10H }, + { 0x089D, R_DEF_STMT }, + { 0x08AC, R_DEFDBL_STMT }, + { 0x08B1, R_DEFINT_STMT }, + { 0x08C1, R_DEFSNG_STMT }, + { 0x08CA, R_DEFSTR_STMT }, + { 0x08CC, R_DECL_VAR_TYPE_E }, + { 0x0906, R_GEN_FC_ERROR }, + { 0x090B, R_EVAL_LINE_NUM }, + { 0x0916, R_ASCII_TO_BIN }, + { 0x0917, R_ASCII_TO_BIN_PREINC }, + { 0x093A, R_RUN_STMT }, + { 0x0949, R_GOSUB_STMT }, + { 0x0961, R_GOTO_STMT }, + { 0x0978, R_GEN_UL_ERROR }, + { 0x0991, R_RETURN_STMT }, + { 0x09C9, R_DATA_STMT }, + { 0x09CB, R_REM_STMT }, + { 0x09EE, R_LET_STMT }, + { 0x0A5A, R_ON_STMT }, + { 0x0A5F, R_ON_ERROR_STMT }, + { 0x0A86, R_ON_KEY_STMT }, + { 0x0ABF, R_ON_TIME_STMT }, + { 0x0ADB, R_RESUME_STMT }, + { 0x0B3A, R_ERROR_STMT }, + { 0x0B45, R_IF_STMT }, + { 0x0B79, R_LPRINT_STMT }, + { 0x0B81, R_PRINT_STMT }, + { 0x0C2C, R_TAB_STMT }, + { 0x0C70, R_LINE_STMT }, + { 0x0CC4, R_INPUT_NO_STMT }, + { 0x0CCE, R_INPUT_STMT }, + { 0x0D04, R_READ_STMT }, + { 0x0DD6, R_EVAL_BASIC_INST }, + { 0x0F38, R_INT16_DIV }, + { 0x0F47, R_EVAL_FUN }, + { 0x0F72, R_ERR_FUN }, + { 0x0F81, R_ERL_FUN }, + { 0x0FA9, R_VARPTR_FUN }, + { 0x0FB1, R_VARPTR_BUF_FUN }, + { 0x0FBD, R_VARPTR_VAR_FUN }, + { 0x1005, R_EVAL_VAR }, + { 0x1013, R_CONV_M_TOUPPER }, + { 0x1014, R_CONV_A_TOUPPER }, + { 0x1062, R_ASCII_NUM_CONV }, + { 0x107E, R_NOT_FUN }, + { 0x1093, R_RST_28H }, + { 0x10B6, R_OR_FUN }, + { 0x10C1, R_AND_FUN }, + { 0x10CC, R_XOR_FUN }, + { 0x10D7, R_EQV_FUN }, + { 0x10DF, R_IMP_FUN }, + { 0x10F2, R_LPOS_FUN }, + { 0x10F8, R_POS_FUN }, + { 0x10FB, R_LD_FAC1_INT }, + { 0x1110, R_CHK_RUNNING_PGRM }, + { 0x1119, R_GEN_ID_ERROR }, + { 0x112A, R_INP_FUN }, + { 0x1136, R_OUT_STMT }, + { 0x113C, R_EVAL_EXPR }, + { 0x113D, R_EVAL_EXPR_PREDEC }, + { 0x1157, R_EVAL_EXPR }, + { 0x1158, R_EVAL_EXPR_PREDEC }, + { 0x1165, R_LLIST_STMT }, + { 0x116A, R_LIST_STMT }, + { 0x11CC, R_BUF_TO_LCD }, + { 0x12B0, R_PEEK_FUN }, + { 0x12B7, R_POKE_FUN }, + { 0x12C3, R_EVAL_EXPR }, + { 0x12F7, R_WAIT_KEY }, + { 0x13CE, R_TOGGLE_LABEL }, + { 0x140A, R_CHK_KEY_QUEUE }, + { 0x146A, R_POWER_STMT }, + { 0x14B2, R_LOW_PWR_TRAP }, //???? + { 0x1549, R_POWER_DOWN }, + { 0x1572, R_POWER_CONT_STMT }, + { 0x157A, R_POWER_ON_STMT }, + { 0x1590, R_OUT_CH_TO_LPT }, + { 0x15A2, R_LOAD_CAS_HDR }, + { 0x15AC, R_GEN_IO_ERROR }, + { 0x15B1, R_DET_CAS_SYNC_HDR }, + { 0x15C0, R_CAS_MOTOR_ON }, + { 0x15C2, R_CAS_MOTOR_OFF }, + { 0x15C8, R_CAS_READ_BYTE }, + { 0x15D9, R_CAS_WRITE_BYTE }, + { 0x15E9, R_LCD_DCB }, + { 0x15EF, R_LCD_OPEN }, + { 0x15FC, R_LCD_OUT }, + { 0x1604, R_POP_ALL_REGS }, + { 0x1609, R_CRT_DCB }, + { 0x1613, R_RAM_DCB }, + { 0x161D, R_RAM_OPEN }, + { 0x16A4, R_RAM_CLOSE }, + { 0x16D0, R_RAM_OUT }, + { 0x16F2, R_RAM_IN }, + { 0x1749, R_RAM_IO }, + { 0x17AD, R_CAS_DCB }, + { 0x17B7, R_CAS_OPEN }, + { 0x17DB, R_CAS_CLOSE }, + { 0x17F5, R_CAS_OUT }, + { 0x1800, R_CAS_IN }, + { 0x1882, R_LPT_DCB }, + { 0x1888, R_LPT_OUT }, + { 0x1890, R_COM_DCB }, + { 0x189A, R_MDM_OPEN }, + { 0x189B, R_COM_OPEN }, + { 0x18D2, R_COM_CLOSE }, + { 0x18DC, R_COM_OUT }, + { 0x18E7, R_COM_IN }, + { 0x1901, R_COM_IO }, + { 0x1908, R_MDM_DCB }, + { 0x1912, R_MDM_CLOSE }, + { 0x191D, R_SET_RS232_PARAMS }, + { 0x19E6, R_BCR_DCB }, + { 0x19F8, R_EOF_FUN }, + { 0x1A73, R_TIME_FUN }, + { 0x1A7E, R_READ_TIME }, + { 0x1A9E, R_DATE_FUN }, + { 0x1AB8, R_DAY_FUN }, + { 0x1AC5, R_READ_DAY }, + { 0x1B03, R_UPDATE_CLK_VALUES }, + { 0x1B0E, R_TIME_STMT }, + { 0x1B16, R_UPDATE_CLK_CHIP }, + { 0x1B23, R_DATE_STMT }, + { 0x1B67, R_DAY_STMT }, + { 0x1BB6, R_GET_TIME_STRING }, + { 0x1BFC, R_IPL_STMT }, + { 0x1C1A, R_ERASE_IPL_PRGM }, + { 0x1C22, R_COM_MDM_STMT }, + { 0x1C36, R_KEY_FUN }, + { 0x1C47, R_KEY_ON_OFF_STMT }, + { 0x1C6E, R_DET_TIME_ARG }, + { 0x1C80, R_DET_DEVICE_ARG }, + { 0x1C93, R_ONTIME_STMT }, + { 0x1CA6, R_ONCOM_STMT }, + { 0x1CB6, R_RST7_5_ISR }, + { 0x2697, R_KICK_PWR_OFF_WDT }, + { 0x269E, R_KEY_STMT }, + { 0x26A3, R_KEY_LIST_STMT }, + { 0x26C6, R_SEND_CHARS_TO_LCD }, + { 0x273D, R_PSET_STMT }, + { 0x274C, R_PRESET_STMT }, + { 0x2753, R_LINE_STMT }, + { 0x278C, R_DRAW_FBOX }, + { 0x27A2, R_DRAW_BOX }, + { 0x2814, R_TOKENIZE_XY }, + { 0x2876, R_CSRLIN_FUN }, + { 0x2881, R_MAX_FUN }, + { 0x288D, R_MAXRAM_FUN }, + { 0x2898, R_MAXFILES_FUN }, + { 0x289F, R_HIMEM_FUN }, + { 0x28A9, R_WIDTH_STMT }, + { 0x28AB, R_SOUND_STMT }, + { 0x28CB, R_SOUND_OFF_STMT }, + { 0x28CC, R_SOUND_ON_STMT }, + { 0x28D2, R_MOTOR_STMT }, + { 0x28D7, R_MOTOR_ON_STMT }, + { 0x28DB, R_MOTOR_OFF_STMT }, + { 0x28E0, R_CALL_STMT }, + { 0x2908, R_SCREEN_STMT }, + { 0x2946, R_LCOPY_STMT }, + { 0x2A2C, R_FILES_STMT }, + { 0x2A34, R_DISPLAY_CAT }, + { 0x2A88, R_KILL_STMT }, + { 0x2AB4, R_KILL_TEXT_FILE }, + { 0x2B40, R_NAME_STMT }, + { 0x2C1B, R_NEW_STMT }, + { 0x2D43, R_STRLEN }, + { 0x2D73, R_GET_FIND_DO_FILE }, + { 0x2D7C, R_OPEN_TEXT_FILE }, + { 0x2FDB, R_CSAVE_STMT }, + { 0x3014, R_CAS_WRITE_BUF }, + { 0x3027, R_SAVEM_STMT }, + { 0x3038, R_CSAVEM_STMT }, + { 0x30E7, R_CLOAD_STMT }, + { 0x3183, R_CAS_READ_REC }, + { 0x31E8, R_GEN_VERIFY_FAIL_ERR }, + { 0x3201, R_LOADM_STMT }, + { 0x3217, R_CLOADM_STMT }, + { 0x32A7, R_MOVE_B_BYTES }, + { 0x32B0, R_EXEC_CO_FILE }, + { 0x3370, R_CAS_OPEN_OUT_BA }, + { 0x3373, R_CAS_OPEN_OUT_DO }, + { 0x3376, R_CAS_OPEN_OUT_CO }, + { 0x33B5, R_CAS_OPEN_IN_BA }, + { 0x33B8, R_CAS_OPEN_IN_DO }, + { 0x33BB, R_CAS_OPEN_IN_CO }, + { 0x34A0, R_STR_FUN }, + { 0x3517, R_PRINT_STRING }, + { 0x3675, R_MOVE_L_BYTES }, + { 0x36A9, R_LEN_FUN }, + { 0x36B5, R_ASC_FUN }, + { 0x36C5, R_CHR_FUN }, + { 0x36D3, R_STRING_FUN }, + { 0x36F4, R_SPACE_FUN }, + { 0x3711, R_LEFT_FUN }, + { 0x3742, R_RIGHT_FUN }, + { 0x374C, R_MID_FUN }, + { 0x376D, R_VAL_FUN }, + { 0x379D, R_INSTR_FUN }, + { 0x38B2, R_FRE_FUN }, + { 0x38CF, R_DBL_SUB }, + { 0x38E7, R_DBL_ADD }, + { 0x39BE, R_BCD_ADD }, + { 0x3A74, R_DBL_MULT }, + { 0x3B3C, R_DBL_DIV }, + { 0x3C5E, R_MOVE_C_BYTES }, + { 0x3C67, R_COS_FUN }, + { 0x3C81, R_SIN_FUN }, + { 0x3CD0, R_TAN_FUN }, + { 0x3CE9, R_ATN_FUN }, + { 0x3D47, R_LOG_FUN }, + { 0x3DD2, R_SQR_FUN }, + { 0x3E1C, R_EXP_FUN }, + { 0x3EB6, R_RND_FUN }, + { 0x3EFA, R_INIT_TEMP3 }, +// { 0x3F18, R_DBL_SQR }, +// { 0x3F1B, R_MULT_M_FAC2 }, + { 0x3F03, R_FAC2_EQ_FAC1 }, + { 0x3F06, R_FAC2_EQ_FP }, + { 0x3F0F, R_FAC1_EQ_FAC2 }, + { 0x3F12, R_FAC1_EQ_FP }, + { 0x3F1E, R_M_EQ_FAC1 }, + { 0x3F1E, R_MULT_FAC1_SQR_FAC1 }, + { 0x3F1E, R_SWAP_FAC1_FAC2 }, + { 0x3F3F, R_SQR_FAC1_MULT_TBL }, + { 0x3F5A, R_TBL_BASED_MATH }, + { 0x3F7F, R_PUSH_FAC2 }, + { 0x3F85, R_PUSH_FAC1 }, + { 0x3F96, R_POP_FAC2 }, + { 0x3F9C, R_POP_FAC1 }, + { 0x3FAD, R_FP_NUMBERS }, + { 0x3FCD, R_FP_SHARED_NUMBERS }, + { 0x3FCF, R_FP_NUMBERS }, + { 0x4027, R_EXP_MATH_TBL }, + { 0x4048, R_EXP_MATH_TBL }, + { 0x4061, R_LOG_MATH_TBL }, + { 0x4082, R_LOG_MATH_TBL }, + { 0x40AB, R_SIN_MATH_TBL }, + { 0x40EC, R_ATN_MATH_TBL }, + { 0x412D, R_RST_30H_FUN }, + { 0x4143, R_ABS_FUN }, + { 0x4158, R_SGN_FUN }, + { 0x4173, R_PUSH_SNGL_FAC1 }, + { 0x4180, R_SNGL_FAC1_EQ_M }, + { 0x4183, R_SNGL_FAC1_EQ_BCDE }, + { 0x418E, R_SNGL_BCDE_EQ_FAC1 }, + { 0x4198, R_SNGL_BCDE_EQ_M }, + { 0x41A1, R_SNGL_DECB_EQ_M }, + { 0x41AA, R_SNGL_M_EQ_FAC1 }, + { 0x41B2, R_LOAD_FAC2_FROM_M }, + { 0x41BA, R_MOVE_B_BYTES_INC }, + { 0x41C3, R_MOVE_B_BYTES_DEC }, + { 0x41E9, R_SNGL_CMP_BCDE_FAC1 }, + { 0x4201, R_SNGL_CMP_BCDE_M }, + { 0x4213, R_SINT_CMP }, + { 0x424E, R_CMP_FAC1_FAC2 }, + { 0x4255, R_CINT_FUN }, + { 0x4264, R_FAC1_EQ_SINT_HL }, + { 0x427E, R_CSNG_FUN }, + { 0x4294, R_CONV_SINT_SNGL }, + { 0x4297, R_CONV_SINT_HL_SNGL }, + { 0x430E, R_CDBL_FUN }, + { 0x434C, R_SINT_SUB }, + { 0x4399, R_FIX_FUN }, + { 0x43A8, R_INT_FUN }, + { 0x4458, R_SINT_ADD }, + { 0x4479, R_SINT_MULT }, + { 0x44D2, R_SINT_DIV }, + { 0x4548, R_SNGL_ADD_BCDE }, + { 0x454B, R_SNGL_ADD_FAC2 }, + { 0x4551, R_SNGL_SUB }, + { 0x4557, R_SNGL_MULT_BCDE }, + { 0x455A, R_SNGL_MULT_FAC2 }, + { 0x4562, R_SNGL_DIV }, + { 0x457B, R_SNGL_LOAD }, + { 0x4594, R_ASCII_TO_DBL }, + { 0x45B9, R_ASCII_FND_e }, + { 0x45D1, R_ASCII_FND_E }, + { 0x4643, R_ASCII_FND_DOT }, + { 0x4659, R_ASCII_FND_PERC }, + { 0x4668, R_ASCII_FND_LB }, + { 0x4670, R_ASCII_CONV_HELPER }, + { 0x467F, R_ASCII_CONV_HELPER2 }, + { 0x4703, R_PRNT_BASIC_ERR_TERM }, + { 0x470B, R_PRINT_HL_ON_LCD }, + { 0x471F, R_PRINT_FAC1 }, + { 0x472F, R_PRINT_FAC1_FORMAT }, +// { 0x4A54, R_FAC1_EQ_ZERO }, + { 0x4AA2, R_SNGL_EXP }, + { 0x4AB1, R_DBL_EXP }, + { 0x4B1A, R_INT_EXP }, + { 0x4C43, R_INIT_BASIC_VARS }, + { 0x4CBB, R_TIME_ON_STMT }, + { 0x4CCD, R_TIME_OFF_STMT }, + { 0x4CD4, R_TIME_STOP_STMT }, + { 0x4CED, R_TRIG_INTR }, + { 0x4D0C, R_CLEAR_INTR }, + { 0x4D24, R_CLEAR_COM_INT_DEF }, + { 0x4D9A, R_RESTORE_STMT }, + { 0x4DB5, R_STOP_STMT }, + { 0x4DBA, R_END_STMT }, + { 0x4DF5, R_CONT_STMT }, + { 0x4E0C, R_ISALPHA_M }, + { 0x4E0D, R_ISALPHA_A }, + { 0x4E14, R_CLEAR_STMT }, + { 0x4E90, R_NEXT_STMT }, + { 0x4F3E, R_SEND_CRLF }, + { 0x4F41, R_SEND_LF }, + { 0x4F45, R_BEEP_STMT }, + { 0x4F49, R_HOME_CURSOR }, + { 0x4F4D, R_CLS_STMT }, + { 0x4F54, R_PROTECT_LABEL }, + { 0x4F59, R_UNPROT_LABEL }, + { 0x4F5E, R_STOP_AUTO_SCROLL }, + { 0x4F63, R_RESUME_AUTO_SCROLL }, + { 0x4F68, R_TURN_CURSOR_ON }, + { 0x4F6D, R_TURN_CURSOR_OFF }, + { 0x4F72, R_DEL_CUR_LINE }, + { 0x4F77, R_INSERT_LINE }, + { 0x4F7C, R_ERASE_TO_EOL }, + { 0x4F81, R_SEND_ESC_X }, + { 0x4F88, R_INV_CHAR_ENABLE }, + { 0x4F8D, R_INV_CHAR_DISABLE }, + { 0x4F8F, R_END_ESC_SEQ }, + { 0x4F96, R_CURSOR_TO_LOW_LEFT }, + { 0x4F9B, R_SET_CURSOR_POS }, + { 0x4FA9, R_ERASE_FKEY_DISP }, + { 0x4FC4, R_SET_DISP_FKEY }, + { 0x4FC7, R_DISP_FKEY_LINE }, + { 0x5030, R_PRINT_A_TO_LCD }, +// { 0x4431, R_CHAR_PLOT_3 }, + { 0x504D, R_CHAR_PLOT_4 }, + { 0x5062, R_CHAR_PLOT_5 }, + { 0x5082, R_LF_FUN }, + { 0x5096, R_LCD_OUT_DRIVER }, + { 0x50AD, R_RST_20H_LKUP_TBL }, + { 0x50D2, R_ESC_Y }, + { 0x50D5, R_LCD_OUT_ESC_FUN }, + { 0x50DB, R_LCD_ESC_LKUP_TBL }, + { 0x5129, R_ESC_SEQ_DRIVER }, + { 0x5160, R_ESC_p_FUN }, + { 0x5161, R_ESC_q_FUN }, + { 0x5166, R_ESC_U_FUN }, + { 0x5168, R_ESC_T_FUN }, + { 0x5169, R_ESC_X_FUN }, + { 0x516E, R_ESC_V_FUN }, + { 0x516F, R_ESC_W_FUN }, + { 0x5182, R_ESC_C_FUN }, + { 0x518B, R_ESC_D_FUN }, + { 0x5190, R_BKSPACE_FUN }, + { 0x5198, R_ESC_A_FUN }, + { 0x519D, R_ESC_B_FUN }, + { 0x51AF, R_TAB_FUN }, + { 0x51C5, R_ESC_H_FUN }, + { 0x51C7, R_CR_FUN }, + { 0x51CC, R_ESC_P_FUN }, + { 0x51CD, R_ESC_Q_FUN }, + { 0x51DD, R_ESC_M_FUN }, + { 0x51F0, R_LCD_SCROLL }, + { 0x5240, R_ESC_L_FUN }, + { 0x52FB, R_GET_LCD_CHAR }, + { 0x5314, R_ESC_l_FUN }, + { 0x5316, R_ESC_K_FUN }, + { 0x532D, R_CLS_FUN }, + { 0x5333, R_ESC_J_FUN }, + { 0x5345, R_CHAR_PLOT_6 }, + { 0x54F0, R_INP_DISP_LINE }, + { 0x54F6, R_INP_DISP_LINE_NO_Q }, + { 0x5536, R_INP_CTRL_C_HANDLER }, + { 0x5549, R_INP_ENTER_HANDLER }, + { 0x5555, R_INP_BKSP_HANDLER }, + { 0x5578, R_INP_CTRL_U_HANDLER }, + { 0x557F, R_INP_TAB_HANDLER }, + { 0x563F, R_DIM_STMT }, + { 0x5644, R_FIND_VAR_ADDR }, + { 0x5845, R_USING_FUN }, + { 0x5A05, R_SEND_A_LCD_LPT }, + { 0x5A14, R_PRINT_A_EXPAND }, + { 0x5A56, R_SET_OUT_DEV_LCD }, + { 0x5A6A, R_LCD_CHAR_OUT_FUN }, + { 0x5A77, R_LCD_NEW_LINE }, + { 0x5AA9, R_INKEY_FUN }, + { 0x5B43, R_GET_FILE_DESC }, + { 0x5B8A, R_OPEN_STMT }, + { 0x5C18, R_LCD_CLOSE_FUN }, + { 0x5C2D, R_RUN_STMT }, + { 0x5C2F, R_LOAD_STMT }, + { 0x5C30, R_MERGE_STMT }, + { 0x5C8E, R_SAVE_STMT }, + { 0x5CE7, R_CLOSE_STMT }, + { 0x5D4A, R_INPUT_STMT }, + { 0x5DC1, R_CLEAR_MEM }, + { 0x5DC2, R_LOAD_MEM }, + { 0x5DE5, R_PRINT_LB_INIT_FUN }, + { 0x5E12, R_LINE_INPUT_STMT }, + { 0x5F05, R_GEN_NM_ERR_FUN }, + { 0x5F08, R_GEN_AO_ERR_FUN }, + { 0x5F0B, R_GEN_DS_ERR_FUN }, + { 0x5F0E, R_GEN_FF_ERR_FUN }, + { 0x5F11, R_GEN_CF_ERR_FUN }, + { 0x5F14, R_GEN_BN_ERR_FUN }, + { 0x5F17, R_GEN_IE_ERR_FUN }, + { 0x5F1A, R_GEN_EF_ERR_FUN }, + { 0x5F1D, R_GEN_FL_ERR_FUN }, + { 0x5F22, R_LOF_FUN }, + { 0x5F24, R_LOC_FUN }, + { 0x5F26, R_LFILES_FUN }, + { 0x5F28, R_DSKO_FUN }, + { 0x5F2A, R_DSKI_FUN }, + { 0x5FA8, R_DEV_NAME_TBL }, + { 0x5FCA, R_DCB_VCTR_TBL }, + { 0x5FFD, R_TELCOM_ENTRY }, + { 0x6012, R_TELCOM_RE_ENTRY }, + { 0x603C, R_TELCOM_INST_VCTR_TBL }, + { 0x605B, R_TELCOM_LABEL_TXT }, + { 0x6077, R_TELCOM_STAT_FUN }, + { 0x607E, R_PRINT_TELCOM_STAT }, + { 0x60A4, R_SET_TELCOM_STAT }, + { 0x612D, R_TELCOM_CALL_FUN }, + { 0x614B, R_TELCOM_FIND_FUN }, + { 0x61B2, R_GO_OFFHOOK }, + { 0x61BA, R_DISCONNECT_PHONE }, + { 0x61D0, R_CONNECT_PHONE }, + { 0x61E7, R_GO_OFFHOOK_WAIT }, + { 0x620E, R_TELCOM_PAUSE }, + { 0x622B, R_EXEC_LOGON_SEQ }, + { 0x6261, R_DIALING_FUN }, + { 0x62B0, R_AUTO_LOGIN_SEQ }, + { 0x632A, R_DIAL_DIGIT }, + { 0x6378, R_TELCOM_TERM_FUN }, + { 0x6479, R_TELCOM_DISPATCH }, + { 0x648A, R_TERM_FKEY_VCTR_TBL }, + { 0x649D, R_TELCOM_PREV_FUN }, + { 0x64B8, R_TELCOM_FULL_FUN }, + { 0x64CA, R_TELCOM_ECHO_FUN }, + { 0x6517, R_TELCOM_UP_FUN }, + { 0x6608, R_TELCOM_DOWN_FUN }, + { 0x66DB, R_TELCOM_BYE_FUN }, + { 0x679E, R_PRINT_STRING }, + { 0x67A4, R_MENU_ENTRY }, + { 0x6828, R_DISP_DIR }, + { 0x6860, R_MENU_CTRL_U_HANDLER }, + { 0x6A08, R_MENU_CMD_LOOP }, +// { 0x588E, R_MENU_BKSP_HANDLER }, +// { 0x58F7, R_MENU_ENTER_HANDLER }, + { 0x6AEF, R_EXEC_ROM_FILE }, + { 0x6CB1, R_DISP_DIR_TYPE_C }, + { 0x6D31, R_CONV_FILENAME }, + { 0x6D51, R_NEXT_DIR_ENTRY }, + { 0x6D97, R_CLS_PRINT_TIME_DAY }, + { 0x6D9E, R_PRINT_TIME_DAY }, + { 0x6DF6, R_PRINT_STRING2 }, + { 0x6E06, R_COPY_MEM_DE_M }, + { 0x6E11, R_CMP_MEM_DE_M }, + { 0x6E1D, R_CLEAR_FKEY_TBL }, + { 0x6E20, R_SET_FKEYS }, + { 0x6E42, R_DISP_FKEYS }, + { 0x6E4D, R_SEARCH_DIR }, + { 0x6E8C, R_GET_FILE_ADDR }, + { 0x6EB6, R_DIR_DISP_ORDER_TBL }, + { 0x6EE7, R_ADDRSS_ENTRY }, +// { 0x5B6B, R_ADDRSS_ENTRY_W_FILE }, + { 0x6EED, R_SCHEDL_ENTRY }, +// { 0x5B72, R_SCHEDL_ENTRY_W_FILE }, + { 0x6F9E, R_ADDRSS_FIND_FUN }, + { 0x6FA0, R_ADDRSS_LFND_FUN }, + { 0x7042, R_FIND_TEXT_IN_FILE }, + { 0x7076, R_FIND_NEXT_LINE_IN_FILE }, + { 0x707D, R_CHECK_FOR_CRLF }, + { 0x70ED, R_ADDRSS_INST_VCTR_TBL }, +// { 0x5D64, R_GET_KEY_CONV_TOUPPER }, +// { 0x5D6A, R_SEND_CURSOR_HOME }, +// { 0x5D70, R_PRINT_TIME_LOOP }, + { 0x719D, R_TEXT_ENTRY }, + { 0x71D4, R_TEXT_FKEY_TBL }, + { 0x7207, R_EDIT_STMT }, + { 0x72E5, R_WAIT_FOR_SPACE_KEY }, + { 0x731B, R_EDIT_DO_FILE_FUN }, + { 0x7396, R_TEXT_EDIT_LOOP }, + { 0x73CF, R_TEXT_CTRL_VCTR_TBL }, + { 0x740F, R_TEXT_ESC_FUN }, + { 0x745D, R_TEXT_CTRL_P_FUN }, + { 0x746B, R_TEXT_CTRL_I_FUN }, + { 0x749F, R_TEXT_CTRL_M_FUN }, + { 0x74BF, R_TEXT_CTRL_D_FUN }, + { 0x74C4, R_TEXT_CTRL_X_FUN }, + { 0x74EC, R_TEXT_CTRL_H_FUN }, + { 0x7532, R_TEXT_CTRL_S_FUN }, + { 0x7536, R_TEXT_CTRL_E_FUN }, + { 0x755B, R_TEXT_CTRL_F_FUN }, + { 0x756D, R_TEXT_CTRL_A_FUN }, + { 0x75A3, R_TEXT_CTRL_T_FUN }, + { 0x75b8, R_TEXT_CTRL_B_FUN }, + { 0x75DE, R_TEXT_CTRL_R_FUN }, + { 0x75EC, R_TEXT_CTRL_Q_FUN }, + { 0x75F1, R_TEXT_CTRL_W_FUN }, + { 0x75FD, R_TEXT_CTRL_Z_FUN }, + { 0x7623, R_TEXT_CTRL_L_FUN }, + { 0x7670, R_TEXT_CTRL_C_FUN }, + { 0x77C6, R_TEXT_GET_NEXT_BYTE }, + { 0x7812, R_TEXT_CTRL_O_FUN }, + { 0x7826, R_TEXT_CTRL_U_FUN }, + { 0x792C, R_TEXT_CTRL_N_FUN }, + { 0x79B7, R_COPY_NULL_STRING }, + { 0x7A83, R_TEXT_CTRL_Y_FUN }, + { 0x7DDD, R_TEXT_CTRL_G_FUN }, + { 0x7E3E, R_TEXT_CTRL_V_FUN }, + { 0x829C, R_INSERT_A_INTO_FILE }, + { 0x82A8, R_INSERT_SPACES }, + { 0x82DA, R_DELETE_CHARS }, + { 0x8316, R_MOVE_BC_BYTES_INC }, + { 0x8321, R_MOVE_BC_BYTES_DEC }, + { 0x832C, R_ROM_CAT_ENTRIES }, + { 0x838F, R_BASIC_ENTRY }, + { 0x83D3, R_LOAD_BASIC_FKEYS }, + { 0x83DC, R_LOAD_BASIC_FKEYS }, + { 0x841C, R_RE_INIT_SYSTEM }, + { 0x8439, R_WARM_RESET }, + { 0x84C9, R_SEND_A_TO_LPT }, + { 0x8508, R_CHECK_RS232_QUEUE }, + { 0x8519, R_READ_RS232_QUEUE }, + { 0x8547, R_RST_6_5_FUN }, + { 0x85F9, R_INC_RS232_QUEUE_IN }, + { 0x8608, R_SEND_XON }, + { 0x8617, R_DISABLE_XON_XOFF }, + { 0x8629, R_SEND_C_TO_RS232 }, + { 0x864F, R_SEND_A_USING_XON }, + { 0x8681, R_XON_XOFF_HANDLER }, + { 0x86AD, R_SET_RS232_BAUD_RATE }, + { 0x86CC, R_RS232_BAUD_TIMER_VALS }, + { 0x86DE, R_INIT_RS232_MDM }, +// { 0x8740, R_UNINIT_RS232_MDM }, + { 0x8740, R_CLICK_SND_PORT }, + { 0x874A, R_CHECK_CD }, + { 0x879D, R_ENABLE_XON_XOFF }, + { 0x87A5, R_INIT_SER_BUF_PARAMS }, + { 0x87D1, R_CAS_WRITE_HEADER }, + { 0x87E6, R_CAS_WRITE_NO_CHKSUM }, +// { 0x6F5B, R_CAS_WRITE_NO_SYNC }, + { 0x87F5, R_CAS_WRITE_BIT }, + { 0x8810, R_CAS_READ_HEADER }, + { 0x8866, R_CAS_READ_BIT }, + { 0x88AC, R_CAS_COUNT_BITS }, + { 0x88B3, R_CAS_READ_NO_CHKSUM }, + { 0x88CC, R_CAS_REMOTE_FUN }, + { 0x88E4, R_KEYSCAN_MGT_FUN }, + { 0x88EF, R_KEY_DETECTION }, + { 0x893F, R_KEY_REPEAT_DET }, +// { 0x70B0, R_GET_KEY_MATRIX }, +// { 0x7122, R_INIT_KEY_RPT_CNT }, + { 0x89D8, R_KEY_DECODE }, + { 0x8A96, R_KEY_FIRST_IN_BUF }, + { 0x8AA5, R_KEY_ADD_TO_BUF }, + { 0x8AB8, R_ISR_EXIT_FUN }, + { 0x8ACB, R_UNSHIFTED_KEY }, + { 0x8AE3, R_ARROW_KEY }, + { 0x8AED, R_CAPS_LOCK_KEY }, + { 0x8AF4, R_NUM_KEY }, + { 0x8B03, R_SCAN_KEYBOARD }, + { 0x8B2B, R_ENABLE_INTERRUPTS }, + { 0x8B31, R_CHK_PENDING_KEYS }, + { 0x8B4D, R_CHK_BREAK }, + { 0x8B69, R_CHK_SHIFT_BREAK }, + { 0x8B7B, R_SCAN_SPECIAL_KEYS }, + { 0x8B8F, R_GEN_TONE }, +// { 0x7329, R_GET_CLK_CHIP_REGS }, +// { 0x732A, R_PUT_CLK_CHIP_REGS }, +// { 0x7352, R_READ_CLK_CHIP_BIT }, + { 0x8CD6, R_SET_CLK_CHIP_MODE }, + { 0x8CF5, R_BLINK_CURSOR }, + { 0x8D3A, R_CHAR_PLOT_7 }, + { 0x8D76, R_PLOT_POINT }, + { 0x8D77, R_CLEAR_POINT }, + { 0x8DA4, R_LCD_BYTE_PLOT }, + { 0x8E9D, R_ENABLE_LCD_DRIVER }, //??? + { 0x8EAA, R_WAIT_LCD_DRIVER }, +// { 0x7551, R_LCD_BIT_PATTERNS }, +// { 0x7643, R_LCD_BIT_PATTERNS }, + { 0x8F9B, R_DELAY_FUN }, + { 0x8FA0, R_SET_INTR_1DH }, + { 0x8FA6, R_BEEP_FUN }, + { 0x8FC9, R_CLICK_SOUND_PORT }, + { 0x8FD4, R_CHK_XTRNL_CNTRLER }, + { 0x8FE2, R_XTRNL_CNTRLER_DRIVER }, + { 0x9063, R_LCD_CHAR_SHAPE_TBL1 }, + { 0x9363, R_LCD_CHAR_SHAPE_TBL2 }, //??? + { 0x9763, R_KEYBOARD_CONV_MATRIX }, + { 0x98AB, R_BOOT_ROUTINE }, + { 0x9A16, R_COLD_BOOT }, + { 0x9AF7, R_DISP_MODEL }, + { 0x9AFD, R_DISP_FREE_BYTES }, + { 0x9B17, R_INIT_RST_38H_TBL }, + { 0x9B32, R_CALC_FREE_RAM }, + { 0x9B54, R_INIT_CLK_CHIP_REGS }, + { 0x9C4E, R_MENU_TEXT_STRINGS }, + { 0x9C85, R_RST_38H_DRIVER }, +// { 0xF5F9, R_RST_5_5_VECTOR }, +// { 0xF5FC, R_RST_6_5_VECTOR }, +// { 0xF5FF, R_RST_7_5_VECTOR }, +// { 0xF602, R_TRAP_VECTOR }, +// { 0xF605, R_DETECT_OPTION_ROM }, + { -1, -1 } +}; + +RomDescription_t gM200_Desc = { + 0x7A27C3A7, /* Signature */ + 0x7A20, /* Signature address */ + 1, /* StdRom */ + + gM200_Tables, /* Known tables */ + gM200_Vars, /* Known variables */ + gM200_Funs, /* Known functions */ + + 0xF295, /* Address of unsaved BASIC prgm */ + 0xF2A0, /* Address of next DO file */ + 0xF661, /* Start of DO file area */ + 0xF663, /* Start of CO file area */ + 0xF665, /* Start of Variable space */ + 0xF667, /* Start of Array data */ + 0xF669, /* Pointer to unused memory */ + 0xEEB4, /* Address where HIMEM is stored */ + 0xF177, /* End of RAM for file storage */ + 0xF4EE, /* Lowest RAM used by system */ + 0xF252, /* Start of RAM directory */ + 0xEF63, /* BASIC string buffer pointer */ + 0xF505, /* BASIC size */ + + 52, /* Number of directory entries */ + 9 /* Index of first dir entry */ +}; + diff --git a/src/memedit.cpp b/src/memedit.cpp new file mode 100644 index 0000000..2b7428b --- /dev/null +++ b/src/memedit.cpp @@ -0,0 +1,1758 @@ +/* memedit.cpp */ + +/* $Id$ */ + +/* + * Copyright 2004 Ken Pettit and Stephen Hurd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(WIN32) +#include +#endif +#include +#include +#include + +#include "VirtualT.h" +#include "m100emu.h" +#include "disassemble.h" +#include "memedit.h" +#include "memory.h" +#include "cpu.h" +extern "C" +#include "intelhex.h" + + +typedef struct memedit_ctrl_struct +{ + Fl_Menu_Bar* pMenu; + + T100_MemEditor* pMemEdit; + Fl_Scrollbar* pScroll; + Fl_Input* pMemRange; + Fl_Box* pRegionText; + Fl_Box* pAddressText; + Fl_Choice* pRegion; + + char sFilename[256]; + int sAddrStart; + int sAddrEnd; + int sAddrTop; +} memedit_ctrl_t; + +typedef struct memedit_dialog +{ + Fl_Window* pWin; // Dialog box window + Fl_Input* pFilename; + Fl_Input* pStartAddr; + Fl_Box* pEndAddr; + Fl_Button* pBrowse; + Fl_Box* pBytes; + char sBytes[20]; + int iOk; +} memedit_dialog_t; + +void cb_PeripheralDevices (Fl_Widget* w, void*); +void cb_load(Fl_Widget* w, void*); +void cb_save_bin(Fl_Widget* w, void*); +void cb_save_hex(Fl_Widget* w, void*); + +extern "C" +{ +extern uchar gReMem; /* Flag indicating if ReMem emulation enabled */ +extern uchar gRampac; +} + + +// Menu items for the disassembler +Fl_Menu_Item gMemEdit_menuitems[] = { + { "&File", 0, 0, 0, FL_SUBMENU }, + { "Load from File...", 0, cb_load, 0 }, + { "Save to BIN...", 0, cb_save_bin, 0 }, + { "Save to HEX...", 0, cb_save_hex, 0 }, + { 0 }, + + { "&Tools", 0, 0, 0, FL_SUBMENU }, + { "CPU Registers", 0, 0 }, + { "Assembler", 0, 0 }, + { "Disassembler", 0, disassembler_cb }, + { "Debugger", 0, 0 }, + { "Memory Editor", 0, 0 }, + { "Peripheral Devices", 0, cb_PeripheralDevices }, + { "Simulation Log Viewer", 0, 0 }, + { "Model T File Viewer", 0, 0 }, + { "BASIC Debugger", 0, 0 }, + { 0 }, + + { 0 } +}; + + +memedit_ctrl_t memedit_ctrl; +memedit_dialog_t gDialog; +Fl_Window *gmew; // Global Memory Edit Window +unsigned char gDispMemory[8192]; + +/* +============================================================================ +Callback routine for the Peripherial Devices window +============================================================================ +*/ +void cb_memeditwin (Fl_Widget* w, void*) +{ + gmew->hide(); + mem_set_monitor_callback(NULL); + delete gmew; + gmew = NULL; +} + +/* +============================================================================ +Callback routine for the Memory Dialog window +============================================================================ +*/ +void cb_dialogwin (Fl_Widget* w, void*) +{ + gDialog.pWin->hide(); +} + +/* +============================================================================ +Callback routine for the Region choice box +============================================================================ +*/ +void cb_region(Fl_Widget* w, void*) +{ + int size = memedit_ctrl.pRegion->value(); + + // Set new region here + memedit_ctrl.pMemEdit->SetScrollSize(); + + memedit_ctrl.pMemEdit->redraw(); + + memedit_ctrl.pMemEdit->UpdateAddressText(); +} + +void load_okButton_cb(Fl_Widget* w, void*) +{ + + // Test for valid filename + if (strlen(gDialog.pFilename->value()) == 0) + { + fl_alert("Please supply filename"); + gDialog.pFilename->take_focus(); + return; + } + + // Test if Start address supplied + if (strlen(gDialog.pStartAddr->value()) == 0) + { + fl_alert("Please supply start address"); + gDialog.pStartAddr->take_focus(); + return; + } + + // Indicate OK button pressed + gDialog.iOk = 1; + + gDialog.pWin->hide(); +} + +void load_cancelButton_cb(Fl_Widget* w, void*) +{ + gDialog.iOk = 0; + gDialog.pWin->hide(); +} + +void update_length_field(const char *filename) +{ + int len; + char buffer[65536]; + unsigned short start_addr; + + // Check for hex file + len = strlen(filename); + if (((filename[len-1] | 0x20) == 'x') && + ((filename[len-2] | 0x20) == 'e') && + ((filename[len-3] | 0x20) == 'h')) + { + // Check if hex file format is valid + len = load_hex_file((char *) filename, buffer, &start_addr); + + if (len == 0) + { + strcpy(gDialog.sBytes, "Error in HEX"); + gDialog.pBytes->redraw_label(); + return; + } + else + { + // Update Length field and End address fields + sprintf(gDialog.sBytes, "%d", len); + gDialog.pBytes->redraw_label(); + } + } + else + { + // Open file as binary + FILE* fd; + if ((fd = fopen(filename, "r")) == NULL) + { + strcpy(gDialog.sBytes, "Error opening file"); + gDialog.pBytes->redraw_label(); + } + else + { + // Determine file length + fseek(fd, 0, SEEK_END); + len = ftell(fd); + fclose(fd); + sprintf(gDialog.sBytes, "%d", len); + gDialog.pBytes->redraw_label(); + } + + } +} + +void load_browseButton_cb(Fl_Widget* w, void*) +{ + int count; + const char * filename; + + Fl_File_Chooser file(".","*.{bin,hex}",1,"Load Optional ROM file"); + file.show(); + + while (file.visible()) + Fl::wait(); + + // Get filename + count = file.count(); + if (count != 1) + return; + filename = file.value(1); + if (filename == 0) + return; + + // Update filename field + gDialog.pFilename->value(filename); + + update_length_field(filename); +} + +void load_filename_cb(Fl_Widget* w, void*) +{ + const char *filename = gDialog.pFilename->value(); + + update_length_field(filename); +} + +/* +============================================================================ +Callback routine for the Load Menu Item +============================================================================ +*/ +void cb_load(Fl_Widget* w, void*) +{ + + Fl_Box *o; + Fl_Return_Button *rb; + Fl_Button *b; + + // Build dialog box for selecting file and Memory Range + gDialog.pWin = new Fl_Window(400, 200, "Load Memory Dialog"); + gDialog.pWin->callback(cb_dialogwin); + + // Create edit field for filename + o = new Fl_Box(FL_NO_BOX, 10, 10, 50, 15, "Filename"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + gDialog.pFilename = new Fl_Input(10, 30, 300, 20, ""); + gDialog.pFilename->callback(load_filename_cb); + + // Create browse button + gDialog.pBrowse = new Fl_Button(320, 30, 70, 20, "Browse"); + gDialog.pBrowse->callback(load_browseButton_cb); + + + // Create report field for # bytes being loaded + o = new Fl_Box(FL_NO_BOX, 25, 55, 100, 15, "Filesize (bytes):"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + gDialog.sBytes[0] = 0; + gDialog.pBytes = new Fl_Box(FL_NO_BOX, 135, 55, 150, 15, gDialog.sBytes); + gDialog.pBytes->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + // Create Edit fields for memory range + o = new Fl_Box(FL_NO_BOX, 10, 90, 110, 15, "Start Address"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + gDialog.pStartAddr = new Fl_Input(120, 90, 90, 20, ""); + gDialog.pStartAddr->value(memedit_ctrl.pMemRange->value()); + + o = new Fl_Box(FL_NO_BOX, 10, 120, 110, 15, "End Address"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + gDialog.pEndAddr = new Fl_Box(FL_NO_BOX, 120, 120, 90, 15, ""); + gDialog.pEndAddr->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + + // Create OK and Cancel buttons + rb = new Fl_Return_Button(90, 160, 75, 25, "OK"); + rb->callback(load_okButton_cb); + + b = new Fl_Button(210, 160, 75, 25, "Cancel"); + b->callback(load_cancelButton_cb); + + gDialog.pWin->set_modal(); + + // Show the dialog box + gDialog.pWin->show(); + + while (gDialog.pWin->visible()) + Fl::wait(); + + // Check if OK button was pressed + if (gDialog.iOk) + { + // Try to open filename supplied + + } + + delete gDialog.pWin; +} + + +/* +============================================================================ +Callback routine for the save BIN Menu Item +============================================================================ +*/ +void cb_save_bin(Fl_Widget* w, void*) +{ +} + +/* +============================================================================ +Callback routine for the save HEX Menu Item +============================================================================ +*/ +void cb_save_hex(Fl_Widget* w, void*) +{ +} + +/* +============================================================================ +Callback routine for processing memory changes during debug +============================================================================ +*/ +extern "C" +{ + +void memory_monitor_cb(void) +{ + // Test if any currently displayed memory changed from last time + memedit_ctrl.pMemEdit->UpdateDispMem(); +} +} + +/* +============================================================================ +Routine to manages changes to emulation mode -- different Model type, + or different memory emulation. +============================================================================ +*/ +void update_memory_emulation() +{ +} + +/* +============================================================================ +Callback routine for the Com Scrollbar +============================================================================ +*/ +void cb_MemEditScroll (Fl_Widget* w, void*) +{ + memedit_ctrl.pMemEdit->m_FirstLine = ((Fl_Scrollbar*) w)->value(); + memedit_ctrl.pMemEdit->redraw(); + memedit_ctrl.pMemEdit->UpdateAddressText(); +} + + +/* +============================================================================ +Routine to create the MemoryEditor Window +============================================================================ +*/ +void cb_MemoryEditor (Fl_Widget* w, void*) +{ + Fl_Box* o; + + if (gmew != NULL) + return; + + // Create Peripheral Setup window + gmew = new Fl_Window(585, 400, "Memory Editor"); + gmew->callback(cb_memeditwin); + + // Create a menu for the new window. + memedit_ctrl.pMenu = new Fl_Menu_Bar(0, 0, 585, MENU_HEIGHT-2); + memedit_ctrl.pMenu->menu(gMemEdit_menuitems); + + // Create static text boxes + o = new Fl_Box(FL_NO_BOX, 10, 10+MENU_HEIGHT, 50, 15, "Region"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 175, 10+MENU_HEIGHT, 50, 15, "Address"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + // Create Region choice box + memedit_ctrl.pRegion = new Fl_Choice(70, 8+MENU_HEIGHT, 100, 20, ""); + memedit_ctrl.pRegion->callback(cb_region); + + // Create Filename edit field + memedit_ctrl.pMemRange = new Fl_Input(235, 8+MENU_HEIGHT, 210, 20, ""); +// memedit_ctrl.pMemRange->deactivate(); + + memedit_ctrl.pMemEdit = new T100_MemEditor(10, 40+MENU_HEIGHT, 545, 350-MENU_HEIGHT); + + memedit_ctrl.pScroll = new Fl_Scrollbar(555, 40+MENU_HEIGHT, 15, 350-MENU_HEIGHT, ""); + memedit_ctrl.pScroll->type(FL_VERTICAL); + memedit_ctrl.pScroll->linesize(2); + memedit_ctrl.pScroll->maximum(2); + memedit_ctrl.pScroll->callback(cb_MemEditScroll); + memedit_ctrl.pScroll->slider_size(1); + + + // Make things resizeable + gmew->resizable(memedit_ctrl.pMenu); + gmew->resizable(memedit_ctrl.pMemEdit); + + memedit_ctrl.pMemEdit->SetScrollSize(); + + // Set Memory Monitor callback + mem_set_monitor_callback(memory_monitor_cb); + + gmew->show(); +} + +/* +================================================================ +cb_MemoryEditorUpdate: This function updates the Memory Editor + window controls when the model or memory + emulation is changed. +================================================================ +*/ +void cb_MemoryEditorUpdate(void) +{ + // First validate that the memory editor window is open + if (gmew == NULL) + return; + + // Update the Region choice box + memedit_ctrl.pMemEdit->SetRegionOptions(); + + // Update the Scroll Sizes + memedit_ctrl.pMemEdit->SetScrollSize(); + + // Update Region ENUM + memedit_ctrl.pMemEdit->GetRegionEnum(); + + // Redraw the memory editor + memedit_ctrl.pMemEdit->redraw(); +} + +T100_MemEditor::T100_MemEditor(int x, int y, int w, int h) : + Fl_Widget(x, y, w, h) +{ + m_MyFocus = 0; + m_FirstLine = 0; + m_Cols = 0; + m_Lines = 0; + m_FirstAddress = 0; + m_Height = 0; + m_Width = 0; + m_CursorAddress = 0; + m_CursorCol = -1; + m_CursorRow = -1; + m_CursorField = 0; + m_pScroll = NULL; + m_SelActive = 0; + m_SelEndRow = 0; + m_SelEndCol = 0; + SetRegionOptions(); +} + +T100_MemEditor::~T100_MemEditor() +{ +} + +void T100_MemEditor::SetRegionOptions(void) +{ + memedit_ctrl.pRegion->clear(); + + // Update the Regions control with appropriate options + if (gReMem) + { + memedit_ctrl.pRegion->add("RAM"); + memedit_ctrl.pRegion->add("Flash 1"); + memedit_ctrl.pRegion->add("Flash 2"); + memedit_ctrl.pRegion->value(0); + } + else + { + switch (gModel) + { + case MODEL_M100: + case MODEL_M102: + memedit_ctrl.pRegion->add("RAM"); + memedit_ctrl.pRegion->add("ROM"); + memedit_ctrl.pRegion->add("Opt ROM"); + memedit_ctrl.pRegion->value(0); + break; + + case MODEL_T200: + memedit_ctrl.pRegion->add("RAM 1"); + memedit_ctrl.pRegion->add("RAM 2"); + memedit_ctrl.pRegion->add("RAM 3"); + memedit_ctrl.pRegion->add("ROM"); + memedit_ctrl.pRegion->add("ROM 2"); + memedit_ctrl.pRegion->add("Opt ROM"); + memedit_ctrl.pRegion->value(0); + break; + + case MODEL_PC8201: + memedit_ctrl.pRegion->add("RAM 1"); + memedit_ctrl.pRegion->add("RAM 2"); + memedit_ctrl.pRegion->add("RAM 3"); + memedit_ctrl.pRegion->add("ROM"); + memedit_ctrl.pRegion->add("Opt ROM"); + memedit_ctrl.pRegion->value(0); + break; + } + } + if (gRampac) + memedit_ctrl.pRegion->add("RamPac"); +} + +void T100_MemEditor::SetScrollSize(void) +{ + double size; + int height; + int region; + + // Test for ReMem emulation mode + if (gReMem) + { + // All ReMem blocks are 2Meg = 128K lines * 16 bytes + m_Max = 1024 * 2048 / 16; + } + else + { + // Check if RAM or ROM region selected + region = memedit_ctrl.pRegion->value(); + switch (gModel) + { + case MODEL_M100: + case MODEL_M102: + case MODEL_PC8201: + if (region == 0) + m_Max = RAMSIZE / 16; + else + m_Max = ROMSIZE / 16; + break; + + case MODEL_T200: + if (region < 3) + m_Max = RAMSIZE / 16; + else + m_Max = ROMSIZE / 16; + break; + } + } + // Check if RamPac RAM is selected + if (strcmp(memedit_ctrl.pRegion->text(), "RamPac") == 0) + m_Max = 1024 * 256 / 16; + + // Select 12 point Courier font + fl_font(FL_COURIER, 12); + + // Get character width & height + m_Height = fl_height(); + height = memedit_ctrl.pScroll->h(); + size = (int) (height / m_Height); + + // Set maximum value of scroll + if (memedit_ctrl.pScroll->value() >= m_Max) + memedit_ctrl.pScroll->value((int) (m_Max-size), 1, 0, (int) m_Max); + memedit_ctrl.pScroll->maximum(m_Max-size); + memedit_ctrl.pScroll->step(size / m_Max); + memedit_ctrl.pScroll->slider_size(size/m_Max); + memedit_ctrl.pScroll->linesize(1); +} + +int T100_MemEditor::GetRegionEnum(void) +{ + char reg_text[16]; + + // Get region text from control + strcpy(reg_text, memedit_ctrl.pRegion->text()); + + // Test if RAM region is selected + if (strcmp(reg_text, "RAM") == 0) + { + if (gReMem) + m_Region = REGION_REMEM_RAM; + else + m_Region = REGION_RAM; + } + + // Test if RAM 1 region is selecte + if (strcmp(reg_text, "RAM 1") == 0) + m_Region = REGION_RAM1; + + // Test if RAM 2 region is selecte + if (strcmp(reg_text, "RAM 2") == 0) + m_Region = REGION_RAM2; + + // Test if RAM 3 region is selecte + if (strcmp(reg_text, "RAM 3") == 0) + m_Region = REGION_RAM3; + + // Test if ROM region is selected + if (strcmp(reg_text, "ROM") == 0) + m_Region = REGION_ROM; + + // Test if OptROM region is selected + if (strcmp(reg_text, "Opt ROM") == 0) + m_Region = REGION_OPTROM; + + // Test if ROM2 region is selected + if (strcmp(reg_text, "ROM 2") == 0) + m_Region = REGION_ROM2; + + // Test if RAMPAC region is selected + if (strcmp(reg_text, "RamPac") == 0) + m_Region = REGION_RAMPAC; + + // Test if Flash 1 region is selected + if (strcmp(reg_text, "Flash 1") == 0) + m_Region = REGION_FLASH1; + + // Test if Flash 2 region is selected + if (strcmp(reg_text, "Flash 2") == 0) + m_Region = REGION_FLASH2; + + return m_Region; + +} + +void T100_MemEditor::UpdateDispMem(void) +{ + int count, c; + unsigned char mem[8192]; + int xpos, ypos; + char string[6]; + int modified = 0; + + // Calculate # bytes to read + count = m_Lines * 16; + + // Read memory + get_memory8_ext(m_Region, m_FirstAddress, count, mem); + + // Set the display + window()->make_current(); + + // Select 12 point Courier font + fl_font(FL_COURIER, 12); + + // Check for changes + for (c = 0; c < count; c++) + if (mem[c] != gDispMemory[c]) + { + gDispMemory[c] = mem[c]; + + // Display new text + sprintf(string, "%02X", mem[c]); + + // Calculate xpos and ypos of the text + xpos = (int) (x() + ((c&0x0F)*3+9+((c&0x0F)>7)) * m_Width); + ypos = (int) (y() + ((c>>4)+1) * m_Height); + + // Draw Address text for line + fl_color(FL_WHITE); + fl_rectf(xpos, ypos - (int) m_Height, (int) m_Width*2, (int) m_Height); + fl_color(FL_BLACK); + fl_draw(string, xpos, ypos-2); + + // Draw the new ASCII value + if ((mem[c] >= ' ') && (mem[c] <= '~')) + sprintf(string, "%c", mem[c]); + else + strcpy(string, "."); + xpos = (int) (x() + (59 + (c&0x0F)) * m_Width); + fl_color(FL_WHITE); + fl_rectf(xpos, ypos - (int) m_Height, (int) m_Width, (int) m_Height); + fl_color(FL_BLACK); + fl_draw(string, xpos, ypos-2); + + // Set modified flag + modified = 1; + } + + if (modified) + DrawCursor(); +} + + +// Redraw the whole LCD +void T100_MemEditor::draw() +{ + int lines, cols; + int line; + unsigned char line_bytes[16]; // Bytes for line being displayed + int addr; + char string[10]; + int xpos, ypos; + int c, max; + int region; // Region where memory is being drawn from + + // Select 12 point Courier font + fl_font(FL_COURIER, 12); + + // Get character width & height + m_Width = fl_width("W", 1); + m_Height = fl_height(); + + // Calculate max cols and lines + lines = (int) (h() / m_Height); + cols = (int) (w() / m_Width); + + if ((lines != m_Lines) || (cols != m_Cols)) + { + m_Lines = lines; + m_Cols = cols; + SetScrollSize(); + } + + // Draw white background + fl_color(FL_WHITE); + fl_rectf(x(),y(),w(),h()); + + fl_color(FL_BLACK); + line = 0; + max = (int) m_Max * 16; // Calc maximum address + + m_FirstAddress = memedit_ctrl.pScroll->value() * 16; + + // Calculate region where memory is read from + region = GetRegionEnum(); + + // Read memory + get_memory8_ext(region, m_FirstAddress, m_Lines*16, gDispMemory); + + // Loop through all lines on display + while (line < m_Lines) + { + // Calculate address to be displayed + addr = m_FirstAddress + line * 16; + if (addr >= max) + break; + if ((region == REGION_RAM) || (region == REGION_RAM2) || + (region == REGION_RAM3) || region == REGION_RAM1) + sprintf(string, "%06X ", addr + RAMSTART); + else + sprintf(string, "%06X ", addr); + + // Calculate xpos and ypos of the text + xpos = (int) (x() + m_Width); + ypos = (int) (y() + (line+1) * m_Height); + + // Draw Address text for line + fl_draw(string, xpos, ypos-2); + + // Read memory for this line + get_memory8_ext(region, addr, 16, line_bytes); + + // Loop through 16 bytes and display in HEX + for (c = 0; c < 16; c++) + { + // Calculate xpos for this byte + if (c < 8) + xpos = (int) (x() + (c*3 + 9) * m_Width); + else + xpos = (int) (x() + (c*3 + 10) * m_Width); + + sprintf(string, "%02X", line_bytes[c]); + + if (xpos + m_Width < w()) + fl_draw(string, xpos, ypos-2); + } + + // Calculate xpos for first byte + xpos = (int) (x() + (16*3 + 11) * m_Width); + + string[1] = 0; + + // Loop through 16 bytes and display as text + for (c = 0; c < 16; c++) + { + // Determine character to display + if ((line_bytes[c] < 0x20) || (line_bytes[c] > '~')) + string[0] = '.'; + else + string[0] = line_bytes[c]; + + // Print the character + if (xpos < w()) + fl_draw(string, xpos, ypos-2); + + // Calculate xpos of next byte + xpos += (int) m_Width; + } + + // Increment Line number + line++; + } + + if (m_MyFocus) + DrawCursor(); +} + +// Handle mouse events, key events, focus events, etc. +int T100_MemEditor::handle(int event) +{ + int c, xp, yp, shift; + int line_click, col_click, cnt; + int col, line; + int lineIndex; + int height, size; + int value; + unsigned int key; + int first, address; + unsigned char data; + int xpos, ypos; + char string[6]; + + switch (event) + { + case FL_FOCUS: + m_MyFocus = 1; + break; + + case FL_UNFOCUS: + m_MyFocus = 0; + + // Make our window the current window for drawing + window()->make_current(); + + // "Unselect" previous start or stop char + EraseCursor(); + break; + + case FL_PUSH: + // Get id of mouse button pressed + c = Fl::event_button(); + + // We must take the focus so keystrokes work properly + take_focus(); + + // Make our window the current window for drawing + window()->make_current(); + + // Check if it was the Left Mouse button + if ((c == FL_LEFT_MOUSE) || (c == FL_RIGHT_MOUSE)) + { + // Get X,Y position of button press + xp = Fl::event_x(); + yp = Fl::event_y(); + + // Check if Shift was depressed during the Mouse Button event + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + shift = 1; + else + shift = 0; + + + if (c == FL_RIGHT_MOUSE) + shift = 1; + + // Determine line & col of mouse click + col_click = (int) ((xp - x()) / m_Width); + line_click = (int) ((yp - y()) / m_Height); + + // Constrain Column base on geometry + if (col_click < 9) + col_click = 9; + + // Constrain click to 1st column in of value in first field + if (col_click < 24+9) + col_click = (int) ((col_click-9) / 3) * 3 + 9; + else if (col_click < 59) + col_click = (int) ((col_click-25-9) / 3) * 3 + 25+9; + else if (col_click > 74) + col_click = 74; + + // Get LineStart index + lineIndex = (m_FirstLine + line_click) >> 1; + + cnt = 0; + col = 0; + line = lineIndex << 1; + + // "Unselect" previous start or stop char + window()->make_current(); + + // Select 12 point Courier font + fl_font(FL_COURIER, 12); + + // Erase current cursor + EraseCursor(); + + // Save new cursor position + m_CursorCol = col_click; + m_CursorRow = line_click; + if (col_click >= 59) + m_CursorField = 2; + else + m_CursorField = 1; + + // Draw new cursor + DrawCursor(); + } + break; + + case FL_KEYDOWN: + if (!m_MyFocus) + return 1; + + // Get the Key that was pressed + key = Fl::event_key(); + + // Check if Shift was depressed during the Mouse Button event + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + shift = 1; + else + shift = 0; + + // Make our window the current window for drawing + window()->make_current(); + + switch (key) + { + case FL_Left: + // First test if selection active. If active, dactivate the selection + // and place cursor at m_CursorRow,m_CursorCol + if (m_SelActive) + { + // Call routine to "unhilight" the selection + + // Deactivate the selection + m_SelActive = 0; + + // Draw the cursor at the m_Cursor position + DrawCursor(); + } + else + { + // Call routine to hide current cursor + EraseCursor(); + + // Move cursor left 1 position in current field + if (m_CursorField == 1) + { + col = m_CursorCol-1; + + // Test if cursor on leftmost entry + if (col < 9) + { + if (m_CursorRow != 0) + { + m_CursorRow--; + col = 10 + 15 * 3; + } + else + { + // Test if we can scroll up one line + if (memedit_ctrl.pScroll->value() != 0) + { + col = 10 + 15 * 3; + ScrollUp(1); + } + else + col = m_CursorCol; + } + } else if (col < 25+9) + col = (int) ((col-10) / 3) * 3 + 9; + else + col = (int) ((col-25-9) / 3) * 3 + 25+9; + + m_CursorCol = col; + } + else + { + // Subtract 1 from cursor position & test if out of field + if (--m_CursorCol < 59) + { + if (m_CursorRow != 0) + { + m_CursorRow--; + m_CursorCol = 74; + } + else + { + // Test if we can scroll up one line + if (memedit_ctrl.pScroll->value() != 0) + { + m_CursorCol = 74; + ScrollUp(1); + } + else + m_CursorCol++; + } + + } + } + + DrawCursor(); + } + break; + case FL_Right: + // First test if selection active. If active, dactivate the selection + // and place cursor at m_CursorRow,m_CursorCol + if (m_SelActive) + { + // Call routine to "unhilight" the selection + + // Deactivate the selection + m_SelActive = 0; + + // Make SelEnd the Cursor position + m_CursorRow = m_SelEndRow; + m_CursorCol = m_SelEndCol; + + // Draw the cursor at the m_Cursor position + DrawCursor(); + } + else + { + // Call routine to hide current cursor + EraseCursor(); + + // Move cursor left 1 position in current field + if (m_CursorField == 1) + { + col = m_CursorCol+3; + + // Test if cursor on leftmost entry + if (col > 9+16*3) + { + if (m_CursorRow != m_Lines-1) + { + m_CursorRow++; + col = 9; + } + else + { + // Select 12 point Courier font + fl_font(FL_COURIER, 12); + + // Get character width & height + m_Height = fl_height(); + height = memedit_ctrl.pScroll->h(); + size = (int) (height / m_Height); + if (memedit_ctrl.pScroll->value() != m_Max - size) + { + col = 9; + ScrollUp(-1); + } + else + col = m_CursorCol; + } + } else if (col > 8+8*3) + col = (int) ((col-25-9) / 3) * 3 + 25+9; + else + col = (int) ((col-9) / 3) * 3 + 9; + + m_CursorCol = col; + } + else + { + // Subtract 1 from cursor position & test if out of field + if (++m_CursorCol > 74) + { + if (m_CursorRow != m_Lines-1) + { + m_CursorRow++; + m_CursorCol = 59; + } + else + { + // Select 12 point Courier font + fl_font(FL_COURIER, 12); + + // Get character width & height + m_Height = fl_height(); + height = memedit_ctrl.pScroll->h(); + size = (int) (height / m_Height); + if (memedit_ctrl.pScroll->value() != m_Max - size) + { + m_CursorCol = 59; + ScrollUp(-1); + } + else + m_CursorCol--; + } + + } + } + + // Draw the cursor at the m_Cursor position + DrawCursor(); + } + break; + case FL_Up: + // First test if selection active. If active, dactivate the selection + // and place cursor at m_CursorRow,m_CursorCol + if (m_SelActive) + { + // Call routine to "unhilight" the selection + + // Deactivate the selection + m_SelActive = 0; + + // Make SelEnd the Cursor position + m_CursorRow = m_SelEndRow; + m_CursorCol = m_SelEndCol; + + // Draw the cursor at the m_Cursor position + DrawCursor(); + } + else + { + // Call routine to hide current cursor + EraseCursor(); + + // Update row + if (m_CursorRow != 0) + m_CursorRow--; + else + { + ScrollUp(1); + DrawCursor(); + break; + } + + // Update Col so it is on 1st byte of field + if (m_CursorField == 1) + { + col = m_CursorCol; + + if (col > 8+8*3) + col = (int) ((col-25-9) / 3) * 3 + 25+9; + else + col = (int) ((col-9) / 3) * 3 + 9; + + m_CursorCol = col; + } + + // Draw the cursor at the m_Cursor position + DrawCursor(); + } + + break; + case FL_Down: + // First test if selection active. If active, dactivate the selection + // and place cursor at m_CursorRow,m_CursorCol + if (m_SelActive) + { + // Call routine to "unhilight" the selection + + // Deactivate the selection + m_SelActive = 0; + + // Draw the cursor at the m_Cursor position + DrawCursor(); + } + else + { + // Call routine to hide current cursor + EraseCursor(); + + // Update row + if (m_CursorRow != m_Lines - 1) + m_CursorRow++; + else + { + ScrollUp(-1); + DrawCursor(); + break; + } + + // Update Col so it is on 1st byte of field + if (m_CursorField == 1) + { + col = m_CursorCol; + + if (col > 8+8*3) + col = (int) ((col-25-9) / 3) * 3 + 25+9; + else + col = (int) ((col-9) / 3) * 3 + 9; + + m_CursorCol = col; + } + + // Draw the cursor at the m_Cursor position + DrawCursor(); + } + + break; + + case FL_Home: + // Erase current cursor + EraseCursor(); + + // Test if CTRL key is pressed + if ((Fl::get_key(FL_Control_L) | Fl::get_key(FL_Control_R)) != 0) + { + // Ctrl key pressed go to very top + ScrollUp((int) m_Max); + m_CursorRow = 0; + } + + // Move cursor to beginning of field + m_CursorCol = m_CursorField == 1 ? 9 : 59; + + // Draw the cursor at the m_Cursor position + DrawCursor(); + break; + + case FL_End: + // Erase current cursor + EraseCursor(); + + if ((Fl::get_key(FL_Control_L) | Fl::get_key(FL_Control_R)) != 0) + { + // Calculate scroll distance to end + value = memedit_ctrl.pScroll->value(); + height = memedit_ctrl.pScroll->h(); + size = (int) (height / m_Height); + m_CursorRow = size-1; + size = (int) m_Max - size - value; + + ScrollUp(-size); + } + + // Move cursor to end of row + m_CursorCol = m_CursorField == 1 ? 55 : 74; + + // Draw the cursor at the m_Cursor position + DrawCursor(); + break; + + case FL_Page_Up: + // Erase current cursor + EraseCursor(); + + // Test if already at top of memory + if ((value = memedit_ctrl.pScroll->value()) == 0) + { + m_CursorRow = 0; + + // Move cursor to beginning of field + m_CursorCol = m_CursorField == 1 ? 9 : 59; + } + + height = memedit_ctrl.pScroll->h(); + size = (int) (height / m_Height); + + if ((value < size) && (value != 0)) + m_CursorRow -= size - value; + + ScrollUp(size); + + // Draw the cursor + DrawCursor(); + break; + + case FL_Page_Down: + // Erase current cursor + EraseCursor(); + + // Calculate distance of scroll + height = memedit_ctrl.pScroll->h(); + size = (int) (height / m_Height); + + // Test if on last page already + value = memedit_ctrl.pScroll->value(); + if (value == (int) m_Max - size) + { + // Move cursor to beginning of field + m_CursorCol = m_CursorField == 1 ? 9 : 59; + m_CursorRow = size-1; + } + + // Test scroll size for bounds + if (value + size > m_Max - size) + size = (int) m_Max - size - value; + + ScrollUp(-size); + + // Draw the cursor + DrawCursor(); + + break; + + case FL_Tab: + // Erase current cursor + EraseCursor(); + + // Change to other field + if (m_CursorField == 1) + { + // Change to ASCII field + m_CursorField = 2; + + // Calculate absolute position (0 to 15) + if (m_CursorCol > 8+8*3) + col = (int) ((m_CursorCol-10) / 3); + else + col = (int) ((m_CursorCol-9) / 3); + + // Position cursor in new field + m_CursorCol = 59 + col; + } + else + { + // Change to HEX field + m_CursorField = 1; + + // Calculate absolution position (0 to 15) + col = m_CursorCol - 59; + + // Position cursor in new field + if (col > 7) + m_CursorCol = col * 3 + 10; + else + m_CursorCol = col * 3 + 9; + } + // Draw the cursor + DrawCursor(); + + break; + + default: + // Handle changes to the memory + if (m_CursorField == 1) + { + // Check for ASCII keystrokes + if (((key >= '0') && (key <= '9')) || ((key >= 'a') && (key <= 'f')) || + ((key >= 'A') && (key <= 'F'))) + { + // Erase current cursor + EraseCursor(); + + // Process keystroke -- first determine address being modified + if (m_CursorCol > 8+8*3) + { + // Calculate index of byte + col = (int) ((m_CursorCol-10) / 3); + + // Test if cursor at beginning of byte or in middle + if ((int)((m_CursorCol - 25 - 9) / 3) * 3 == m_CursorCol-25-9) + first = 1; + else + first = 0; + } + else + { + // Calculate index of byte + col = (int) ((m_CursorCol-9) / 3); + + // Test if cursor at beginning of byte or in middle + if ((int)((m_CursorCol - 9) / 3) * 3 == m_CursorCol-9) + first = 1; + else + first = 0; + } + + // Get address of first item on screen + address = memedit_ctrl.pScroll->value() * 16; + address += m_CursorRow * 16; + address += col; + + // Determine if this is the first keystroke at this address + if (first) + { + data = 0; + set_memory8_ext(m_Region, address, 1, &data); + } + + // Determine value of keystroke (convert from HEX) + if (key <= '9') + value = key - '0'; + else if (key <= 'F') + value = key - 'A' + 10; + else + value = key - 'a' + 10; + + // Get current memory value + get_memory8_ext(m_Region, address, 1, &data); + data = data * 16 + value; + + // Write new value to memory + set_memory8_ext(m_Region, address, 1, &data); + + // Display new text + // Select 12 point Courier font + fl_font(FL_COURIER, 12); + + sprintf(string, "%02X", data); + + // Calculate xpos and ypos of the text + xpos = (int) (x() + (col*3+9+(col>7)) * m_Width); + ypos = (int) (y() + (m_CursorRow+1) * m_Height); + + // Set the display + window()->make_current(); + + // Draw Address text for line + fl_color(FL_WHITE); + fl_rectf(xpos, ypos - (int) m_Height, (int) m_Width*2, (int) m_Height); + fl_color(FL_BLACK); + fl_draw(string, xpos, ypos-2); + + // Draw the new ASCII value + if ((data >= ' ') && (data <= '~')) + sprintf(string, "%c", data); + else + strcpy(string, "."); + xpos = (int) (x() + (59 + col) * m_Width); + fl_color(FL_WHITE); + fl_rectf(xpos, ypos - (int) m_Height, (int) m_Width, (int) m_Height); + fl_color(FL_BLACK); + fl_draw(string, xpos, ypos-2); + + + // Update cursor position + m_CursorCol++; + if (!first) + { + // Skip the white space between bytes + m_CursorCol++; + + if (m_CursorCol == 9+8*3) + m_CursorCol = 10+8*3; + + // Test if cursor on leftmost entry + else if (m_CursorCol > 9+16*3) + { + // Test if cursor at bottom of screen + if (m_CursorRow != m_Lines-1) + { + // Not at bottom, simply increment to next line + m_CursorRow++; + m_CursorCol = 9; + } + else + { + // Cursor at bottom of screen. Need to scroll + + // Select 12 point Courier font + fl_font(FL_COURIER, 12); + + // Get character width & height + m_Height = fl_height(); + height = memedit_ctrl.pScroll->h(); + size = (int) (height / m_Height); + + // Test if scroll at bottom + if (memedit_ctrl.pScroll->value() != m_Max - size) + { + // Not at bottom. Scroll 1 line + m_CursorCol = 9; + ScrollUp(-1); + } + else + m_CursorCol = 55; + } + } + } + + // Draw new cursor + DrawCursor(); + + } + } + else + { + key = *(Fl::event_text()); + + // In ASCII field. Test for valid keystorke + if ((key >= ' ') && (key <= '~')) + { + // Erase current cursor + EraseCursor(); + + // Calculate index of byte + col = (int) m_CursorCol-59; + + // Get address of first item on screen + address = memedit_ctrl.pScroll->value() * 16; + address += m_CursorRow * 16; + address += col; + + // Write new value to memory + data = key; + set_memory8_ext(m_Region, address, 1, &data); + + // Display new text + // Select 12 point Courier font + fl_font(FL_COURIER, 12); + + sprintf(string, "%02X", data); + + // Calculate xpos and ypos of the text + xpos = (int) (x() + (col*3+9+(col>7)) * m_Width); + ypos = (int) (y() + (m_CursorRow+1) * m_Height); + + // Set the display + window()->make_current(); + + // Draw Address text for line + fl_color(FL_WHITE); + fl_rectf(xpos, ypos - (int) m_Height, (int) m_Width*2, (int) m_Height); + fl_color(FL_BLACK); + fl_draw(string, xpos, ypos-2); + + // Draw the new ASCII value + if ((data >= ' ') && (data <= '~')) + sprintf(string, "%c", data); + else + strcpy(string, "."); + xpos = (int) (x() + (59 + col) * m_Width); + fl_color(FL_WHITE); + fl_rectf(xpos, ypos - (int) m_Height, (int) m_Width, (int) m_Height); + fl_color(FL_BLACK); + fl_draw(string, xpos, ypos-2); + + + // Update cursor position + m_CursorCol++; + + // Test if cursor on leftmost entry + if (m_CursorCol > 74) + { + // Test if cursor at bottom of screen + if (m_CursorRow != m_Lines-1) + { + // Not at bottom, simply increment to next line + m_CursorRow++; + m_CursorCol = 59; + } + else + { + // Cursor at bottom of screen. Need to scroll + + // Select 12 point Courier font + fl_font(FL_COURIER, 12); + + // Get character width & height + m_Height = fl_height(); + height = memedit_ctrl.pScroll->h(); + size = (int) (height / m_Height); + + // Test if scroll at bottom + if (memedit_ctrl.pScroll->value() != m_Max - size) + { + // Not at bottom. Scroll 1 line + m_CursorCol = 59; + ScrollUp(-1); + } + else + m_CursorCol = 73; + } + } + + // Draw new cursor + DrawCursor(); + + } + } + + break; + + } + break; + + default: + Fl_Widget::handle(event); + break; + + } + + return 1; +} + + +/* +================================================================ +ScrollUp: This function scrolls the window up the specified + number of lines +================================================================ +*/ +void T100_MemEditor::ScrollUp(int lines) +{ + int height, size, value; + + // Get current scroll value + value = memedit_ctrl.pScroll->value(); + + // Test if at top already + if ((value == 0) && (lines > 0)) + return; + + + // Select 12 point Courier font + fl_font(FL_COURIER, 12); + + // Get height of screen in lines + m_Height = fl_height(); + height = memedit_ctrl.pScroll->h(); + size = (int) (height / m_Height); + + // Test if at bottom and scrolling down + if ((value == m_Max - size) && (lines < 0)) + return; + + // Update new value base on scroll distance requested + value -= lines; + if (value < 0) + value = 0; + + // Update scroll bar + memedit_ctrl.pScroll->value(value, 1, 0, (int) m_Max); + memedit_ctrl.pScroll->maximum(m_Max-size); + memedit_ctrl.pScroll->step(size / m_Max); + memedit_ctrl.pScroll->slider_size(size/m_Max); + memedit_ctrl.pScroll->linesize(1); + redraw(); +} + +// Erase the cursor at its current position +void T100_MemEditor::EraseCursor() +{ + int x_pos, y_pos; + + // Erase current cursor + fl_color(FL_WHITE); + if (m_CursorRow != -1) + { + x_pos = (int) (m_CursorCol * m_Width + x()); + y_pos = (int) (m_CursorRow * m_Height + y()); + fl_line(x_pos-1, y_pos, x_pos-1, y_pos + (int) m_Height); + fl_line(x_pos, y_pos, x_pos, y_pos + (int) m_Height); + } + +} + +// Erase the cursor at its current position +void T100_MemEditor::DrawCursor() +{ + int x_pos, y_pos; + + if (!m_MyFocus) + return; + + // Draw new cursor + fl_color(FL_BLACK); + if (m_CursorRow != -1) + { + x_pos = (int) (m_CursorCol * m_Width + x()); + y_pos = (int) (m_CursorRow * m_Height + y()); + fl_line(x_pos-1, y_pos, x_pos-1, y_pos + (int) m_Height-2); + fl_line(x_pos, y_pos, x_pos, y_pos + (int) m_Height-2); + } + + UpdateAddressText(); +} + +// Update the Address edit box base on the position of the cursor +void T100_MemEditor::UpdateAddressText() +{ + char string[10]; + long address; + int col, region; + + if (!m_MyFocus) + return; + + // Determine column of cursor + if (m_CursorField == 1) + { + // Process keystroke -- first determine address being modified + if (m_CursorCol > 8+8*3) + col = (int) ((m_CursorCol-10) / 3); + else + col = (int) ((m_CursorCol-9) / 3); + } + else + col = (int) m_CursorCol-59; + + + // Get address of first item on screen + address = memedit_ctrl.pScroll->value() * 16; + address += m_CursorRow * 16; + address += col; + + // Now create text + // Calculate region where memory is read from + region = GetRegionEnum(); + + if ((region == REGION_RAM) || (region == REGION_RAM2) || + (region == REGION_RAM3) || region == REGION_RAM1) + { + if (gReMem) + sprintf(string, "0x%06X", address + RAMSTART); + else + sprintf(string, "0x%04X", address + RAMSTART); + } + else + { + if (gReMem) + sprintf(string, "0x%06X", address); + else + sprintf(string, "0x%04X", address); + } + memedit_ctrl.pMemRange->value(string); +} + + diff --git a/src/memedit.h b/src/memedit.h new file mode 100644 index 0000000..b88e6c5 --- /dev/null +++ b/src/memedit.h @@ -0,0 +1,90 @@ +/* memedit.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Ken Pettit and Stephen Hurd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef MEMEDIT_H +#define MEMEDIT_H + + +#include "FL/Fl_File_Chooser.H" + +void cb_MemoryEditor (Fl_Widget* w, void*); +void cb_MemoryEditorUpdate(void); + + +#define MENU_HEIGHT 32 + +class T100_MemEditor : public Fl_Widget +{ +public: + T100_MemEditor(int x, int y, int w, int h); + ~T100_MemEditor(); + + void SetMemRegion(int region); + void SetMemAddress(int address); + void SetScrollSize(void); + void SetRegionOptions(void); + int GetRegionEnum(void); + void UpdateAddressText(void); + void UpdateDispMem(void); + int m_FirstLine; + +protected: +// virtual int handle(int event); + void draw(); + virtual int handle(int event); + void DrawCursor(void); + void EraseCursor(void); + void ScrollUp(int lines); + void ScrollDown(int lines); + + int m_MyFocus; + int m_Region; + int m_Cols; + int m_Lines; + double m_Max; + double m_Height; + double m_Width; + int m_FirstAddress; + + int m_CursorAddress; + int m_CursorCol; + int m_CursorRow; + int m_CursorField; + + // Current selection control -- active & start / end addresses + int m_SelActive; + long m_SelEndRow; + long m_SelEndCol; + + Fl_Scrollbar* m_pScroll; + +}; + +#endif diff --git a/src/memory.c b/src/memory.c index 819f501..e26873c 100644 --- a/src/memory.c +++ b/src/memory.c @@ -10,13 +10,44 @@ memory.c ============================================================================ */ +#include +#include + +#include "VirtualT.h" +#include "m100emu.h" #include "memory.h" -#include "genwrap.h" -#include "filewrap.h" +#include "cpu.h" +#include "io.h" +#include "intelhex.h" +#include "setup.h" + +extern uchar memory[65536]; /* System Memory */ +extern uchar sysROM[65536]; /* System ROM */ +extern uchar optROM[32768]; /* Option ROM */ +extern uchar msplanROM[32768]; /* MSPLAN ROM T200 Only */ +extern char path[255]; +extern char file[255]; +extern int cROM; /* Model 100/102 Option ROM flag */ + +unsigned char rambanks[3*32768]; /* Model T200 & NEC RAM banks */ +uchar gRamBank = 0; /* Currently enabled bank */ +uchar gRomBank = 0; /* Current ROM Bank selection */ -extern uchar memory[65536]; -extern uchar sysROM[32768]; -extern uchar optROM[32768]; +uchar gReMem = 0; /* Flag indicating if ReMem emulation enabled */ +uchar gReMemBoot = 0; /* ALT boot flag */ +uchar gReMemMode = 0; /* Current ReMem emulation mode */ +uchar gReMemSector = 0; /* Current Vector access sector */ +uchar gReMemCounter = 0; /* Current Vector access counter */ +unsigned char *gReMemSectPtr = 0; /* Pointer to current Sector memory */ +unsigned short gReMemMap[64]; /* Map of 1K blocks - 64 total */ +uchar *gReMemRam = 0; /* Pointer to ReMem RAM space */ +uchar *gReMemFlash1 = 0; /* Pointer to ReMem Flash1 space */ +uchar *gReMemFlash2 = 0; /* Pointer to ReMem Flash2 space */ + +int gRampac = 0; /* Rampac Enable flag */ +unsigned char *gRampacRam = 0; /* Rampac RAM pointer */ +int gRampacSector = 0; /* Rampac emulation Sector number */ +int gRampacCounter = 0; /* Rampac emulation Counter */ unsigned char get_memory8(unsigned short address) @@ -39,3 +70,1527 @@ void set_memory16(unsigned short address, unsigned short data) memory[address] = data & 0xFF; memory[address+1] = data >> 8; } + +/* +======================================================================== +get_memory8_ext: This routine reads the specified number of bytes + from the address given for the region identified. +======================================================================== +*/ +void get_memory8_ext(int region, long address, int count, unsigned char *data) +{ + int addr; + int c, x; + int start_1k, end_1k; // 1K Block address for start & end of copy + unsigned short map; + int mapped; + int cp_ptr; + unsigned char *ptr; + int limit; + + switch (region) + { + case REGION_RAM: + addr = RAMSTART + address; + for (c = 0; c < count; c++) + data[c] = memory[addr++]; + break; + + case REGION_ROM: + addr = address; + for (c = 0; c < count; c++) + data[c] = memory[addr++]; + break; + + case REGION_ROM2: + addr = address; + for (c = 0; c < count; c++) + data[c] = msplanROM[addr++]; + break; + + case REGION_OPTROM: + addr = address; + for (c = 0; c < count; c++) + data[c] = optROM[addr++]; + break; + + case REGION_RAM1: + // Check if RAM Bank 1 is active & copy from system memory if it is + if (gRamBank == 0) + { + addr = address + RAMSTART; + for (c = 0; c < count; c++) + data[c] = memory[addr++]; + } + else + { + addr = address; + for (c = 0; c < count; c++) + data[c] = rambanks[addr++]; + } + break; + + case REGION_RAM2: + // Check if RAM Bank 2 is active & copy from system memory if it is + if (gRamBank == 1) + { + addr = address + RAMSTART; + for (c = 0; c < count; c++) + data[c] = memory[addr++]; + } + else + { + if (gModel == MODEL_T200) + addr = 24576 + address; + else + addr = 32768 + address; + for (c = 0; c < count; c++) + data[c] = rambanks[addr++]; + } + break; + + case REGION_RAM3: + // Check if RAM Bank 2 is active & copy from system memory if it is + if (gRamBank == 2) + { + addr = address + RAMSTART; + for (c = 0; c < count; c++) + data[c] = memory[addr++]; + } + else + { + if (gModel == MODEL_T200) + addr = 24576*2 + address; + else + addr = 32768*2 + address; + for (c = 0; c < count; c++) + data[c] = rambanks[addr++]; + } + break; + + case REGION_RAMPAC: + // Check if RamPack memory is valid + if (gRampacRam == NULL) + break; + + // Load data from RamPac RAM + addr = address; + for (c = 0; c < count; c++) + data[c] = gRampacRam[addr++]; + break; + + /* + ================================================================ + The following cases deal with ReMem emulation of RAM and FLASH. + For these cases, the MMU settings must be queried to determine + if memory should be copied from the 2Meg region or from the + system memory where 1K blocks are copied to/from. + ================================================================ + */ + case REGION_REMEM_RAM: + case REGION_FLASH1: + case REGION_FLASH2: + // First check that the ReMem RAM has been allocated + if ((gReMemRam == NULL) || (gReMemFlash1 == NULL) || (gReMemFlash2 == NULL)) + break; + + // Check ReMem emulation mode + if (gReMemMode & REMEM_MODE_NORMAL) + { + // Check if copy crosses 1K block boundries + start_1k = address / 1024; + end_1k = (address + count) / 1024; + + // Indicate zero bytes copied so far + cp_ptr = 0; + + // Loop for each 1K block & copy data + for (x = start_1k; x <= end_1k; x++) + { + // Calculate ReMemMap value to search for to test if + // this block is mapped to system memory + if (region == REGION_REMEM_RAM) + { + map = REMEM_VCTR_FLASH1_CS | REMEM_VCTR_FLASH2_CS; + ptr = gReMemRam; + } + else if (region == REGION_FLASH1) + { + map = REMEM_VCTR_RAM_CS | REMEM_VCTR_FLASH2_CS; + ptr = gReMemFlash1; + } + else + { + map = REMEM_VCTR_RAM_CS | REMEM_VCTR_FLASH1_CS; + ptr = gReMemFlash2; + } + map |= x; + + // Loop through all maps and test if this block mapped + mapped = FALSE; + for (c = 0; c < 64; c++) + { + if ((gReMemMap[c] & ~(REMEM_VCTR_READ_ONLY | REMEM_VCTR_MMU_ACTIVE)) == map) + { + mapped = TRUE; + break; + } + } + + // Check if copy is from System Memory or ReMem memory + if (mapped) + { + // Block is mapped -- copy from system memory + addr = (address - x*1024) + c * 1024; + for (; (cp_ptr < count) && (addr < (c+1)*1024); cp_ptr++) + data[cp_ptr] = memory[addr++]; + } + else + { + // Block is not mapped -- copy from appropriate allocation + addr = address + cp_ptr; + for (;(cp_ptr < count) & (addr < (x+1)*1024); cp_ptr++) + data[cp_ptr] = ptr[addr++]; + } + } + } + else + { + // Get pointer to correct memory space + if (region == REGION_REMEM_RAM) + ptr = gReMemRam; + else if (region == REGION_FLASH1) + ptr = gReMemFlash1; + else if (region == REGION_FLASH2) + ptr = gReMemFlash2; + + addr = address; + cp_ptr = 0; + + // ReMem Normal mode enabled + if (gModel == MODEL_T200) + limit = 40960; + else + limit = 32768; + + // Test if reading from "ROM" space + if (addr < limit) + { + // If reading from Flash1 space, read system memory instead + if (region == REGION_FLASH1) + { + // Copy bytes from the system memory + for (; (cp_ptr < count) && (addr < limit); cp_ptr++) + data[cp_ptr] = memory[addr++]; + } + // Test if copying to RAM below the "Normal" region + else + { + // Copy bytes up to the limit from allocation + for (; (cp_ptr < count) && (addr < limit); cp_ptr++) + data[cp_ptr] = ptr[addr++]; + } + } + + // Test if reading from "RAM" space + if ((addr >= limit) && (addr < 65536)) + { + if (region == REGION_REMEM_RAM) + { + // Copy bytes from the System RAM between limit and 64K + for (; (cp_ptr < count) && (addr < 65536) ; cp_ptr++) + data[cp_ptr] = memory[addr++]; + } + else + { + // Copy remainder of bytes above 64K from allocation + for (; cp_ptr < count; cp_ptr++) + data[cp_ptr] = ptr[addr++]; + } + } + + // Copy bytes that are above Normal "RAM" locations + if (addr >= 65536) + { + // Copy all bytes directly if Flash2 + for (; cp_ptr < count; cp_ptr++) + data[cp_ptr] = ptr[addr++]; + } + } + break; + } +} + +/* +======================================================================== +set_memory8_ext: This routine writes the specified number of bytes + from the address given to the region identified. +======================================================================== +*/ +void set_memory8_ext(int region, long address, int count, unsigned char *data) +{ + int addr; + int c, x; + int start_1k, end_1k; // 1K Block address for start & end of copy + unsigned short map; + int mapped; + int cp_ptr; + unsigned char *ptr; + int limit; + + switch (region) + { + case REGION_RAM: + addr = RAMSTART + address; + for (c = 0; c < count; c++) + memory[addr++] = data[c]; + break; + + case REGION_ROM: + addr = address; + for (c = 0; c < count; c++) + memory[addr++] = data[c]; + break; + + case REGION_ROM2: + addr = address; + for (c = 0; c < count; c++) + msplanROM[addr++] = data[c]; + break; + + case REGION_OPTROM: + addr = address; + for (c = 0; c < count; c++) + optROM[addr++] = data[c]; + break; + + case REGION_RAM1: + // Check if RAM Bank 1 is active & copy from system memory if it is + if (gRamBank == 0) + { + addr = address + RAMSTART; + for (c = 0; c < count; c++) + memory[addr++] = data[c]; + } + else + { + addr = address; + for (c = 0; c < count; c++) + rambanks[addr++] = data[c]; + } + break; + + case REGION_RAM2: + // Check if RAM Bank 2 is active & copy from system memory if it is + if (gRamBank == 1) + { + addr = address + RAMSTART; + for (c = 0; c < count; c++) + memory[addr++] = data[c]; + } + else + { + if (gModel == MODEL_T200) + addr = 24576 + address; + else + addr = 32768 + address; + for (c = 0; c < count; c++) + rambanks[addr++] = data[c]; + } + break; + + case REGION_RAM3: + // Check if RAM Bank 2 is active & copy from system memory if it is + if (gRamBank == 2) + { + addr = address + RAMSTART; + for (c = 0; c < count; c++) + memory[addr++] = data[c]; + } + else + { + if (gModel == MODEL_T200) + addr = 24576*2 + address; + else + addr = 32768*2 + address; + for (c = 0; c < count; c++) + rambanks[addr++] = data[c]; + } + break; + + case REGION_RAMPAC: + // Check if RamPack memory is valid + if (gRampacRam == NULL) + break; + + // Load data from RamPac RAM + addr = address; + for (c = 0; c < count; c++) + gRampacRam[addr++] = data[c]; + break; + + /* + ================================================================ + The following cases deal with ReMem emulation of RAM and FLASH. + For these cases, the MMU settings must be queried to determine + if memory should be copied from the 2Meg region or from the + system memory where 1K blocks are copied to/from. + ================================================================ + */ + case REGION_REMEM_RAM: + case REGION_FLASH1: + case REGION_FLASH2: + // First check that the ReMem RAM has been allocated + if ((gReMemRam == NULL) || (gReMemFlash1 == NULL) || (gReMemFlash2 == NULL)) + break; + + // Check ReMem emulation mode + if (gReMemMode & REMEM_MODE_NORMAL) + { + // Check if copy crosses 1K block boundries + start_1k = address / 1024; + end_1k = (address + count) / 1024; + + // Indicate zero bytes copied so far + cp_ptr = 0; + + // Loop for each 1K block & copy data + for (x = start_1k; x <= end_1k; x++) + { + // Calculate ReMemMap value to search for to test if + // this block is mapped to system memory + if (region == REGION_REMEM_RAM) + { + map = REMEM_VCTR_FLASH1_CS | REMEM_VCTR_FLASH2_CS; + ptr = gReMemRam; + } + else if (region == REGION_FLASH1) + { + map = REMEM_VCTR_RAM_CS | REMEM_VCTR_FLASH2_CS; + ptr = gReMemFlash1; + } + else + { + map = REMEM_VCTR_RAM_CS | REMEM_VCTR_FLASH1_CS; + ptr = gReMemFlash2; + } + map |= x; + + // Loop through all maps and test if this block mapped + mapped = FALSE; + for (c = 0; c < 64; c++) + { + if ((gReMemMap[c] & ~(REMEM_VCTR_READ_ONLY | REMEM_VCTR_MMU_ACTIVE)) == map) + { + mapped = TRUE; + break; + } + } + + // Check if copy is from System Memory or ReMem memory + if (mapped) + { + // Block is mapped -- copy from system memory + addr = (address - x*1024) + c * 1024; + for (; (cp_ptr < count) && (addr < (c+1)*1024); cp_ptr++) + memory[addr++] = data[cp_ptr]; + } + else + { + // Block is not mapped -- copy from appropriate allocation + addr = address + cp_ptr; + for (;(cp_ptr < count) & (addr < (x+1)*1024); cp_ptr++) + ptr[addr++] = data[cp_ptr]; + } + } + } + else + { + // Get pointer to correct memory space + if (region == REGION_REMEM_RAM) + ptr = gReMemRam; + else if (region == REGION_FLASH1) + ptr = gReMemFlash1; + else if (region == REGION_FLASH2) + ptr = gReMemFlash2; + + addr = address; + cp_ptr = 0; + + // ReMem Normal mode enabled + if (gModel == MODEL_T200) + limit = 40960; + else + limit = 32768; + + // Test if reading from "ROM" space + if (addr < limit) + { + // If reading from Flash1 space, read system memory instead + if (region == REGION_FLASH1) + { + // Copy bytes from the system memory + for (; (cp_ptr < count) && (addr < limit); cp_ptr++) + memory[addr++] = data[cp_ptr]; + } + // Test if copying to RAM below the "Normal" region + else + { + // Copy bytes up to the limit from allocation + for (; (cp_ptr < count) && (addr < limit); cp_ptr++) + ptr[addr++] = data[cp_ptr]; + } + } + + // Test if reading from "RAM" space + if ((addr >= limit) && (addr < 65536)) + { + if (region == REGION_REMEM_RAM) + { + // Copy bytes from the System RAM between limit and 64K + for (; (cp_ptr < count) && (addr < 65536) ; cp_ptr++) + memory[addr++] = data[cp_ptr]; + } + else + { + // Copy remainder of bytes above 64K from allocation + for (; cp_ptr < count; cp_ptr++) + ptr[addr++] = data[cp_ptr]; + } + } + + // Copy bytes that are above Normal "RAM" locations + if (addr >= 65536) + { + // Copy all bytes directly if Flash2 + for (; cp_ptr < count; cp_ptr++) + ptr[addr++] = data[cp_ptr]; + } + } + break; + } +} + +/* +======================================================================== +init_mem: This routine initialized the Memory subsystem. It takes + care of allocation of ReMem memory, Rampac memory, etc. +======================================================================== +*/ +void init_mem(void) +{ + int c, size; + + /* Set gReMem and gRampac based on preferences */ + gReMem = (mem_setup.mem_mode == SETUP_MEM_REMEM) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC); + gRampac = (mem_setup.mem_mode == SETUP_MEM_RAMPAC) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC); + + /* Test if ReMem emulation enabled */ + if (gReMem) + { + /* Allocate memory only if not already allocated */ + if (gReMemRam == 0) + { + /* Size of allocation for RAM and FLASH */ + size = 1024 * 2048; + + /* Allocate space for RAM and FLASH */ + gReMemRam = malloc(size); + gReMemFlash1 = malloc(size); + gReMemFlash2 = malloc(size); + + /* Initialize memory to zero */ + for (c = 0; c < size; c++) + { + gReMemRam[c] = 0; + gReMemFlash1[c] = 0; + gReMemFlash2[c] = 0; + } + } + } + + /* Test if Rampac emulation enabled */ + if (gRampac) + { + /* Allocate memory only if not already allocated */ + if (gRampacRam == 0) + { + /* Size of allocation for RAM and FLASH */ + size = 1024 * 256; + + /* Allocate space for Rampac RAM */ + gRampacRam = malloc(size); + + /* Initialize memory to zero */ + for (c = 0; c < size; c++) + gRampacRam[c] = 0; + } + } +} + +/* +======================================================================== +free_remem_mem: This routine frees the memory used by the ReMem + emulation and resets the pointers to zero. +======================================================================== +*/ +void free_remem_mem(void) +{ + /* Delete memory allocated for RAM and FLASH */ + free(gReMemRam); + free(gReMemFlash1); + free(gReMemFlash2); + + /* Set memory pointers to NULL */ + gReMemRam = 0; + gReMemFlash1 = 0; + gReMemFlash2 = 0; +} + +/* +======================================================================== +free_rampac_mem: This routine frees the memory used by the Rampac + emulation and resets the pointers to zero. +======================================================================== +*/ +void free_rampac_mem(void) +{ + /* Delete memory allocated for RAM and FLASH */ + free(gRampacRam); + + /* Set memory pointers to NULL */ + gRampacRam = 0; +} + +/* +======================================================================== +free_mem: This routine frees ReMem and/or Rampac memory allocated + during the emulation session. +======================================================================== +*/ +void free_mem(void) +{ + /* Test if ReMem RAM currently allocated */ + if (gReMemRam != 0) + free_remem_mem(); + + /* Test if Rampac RAM currently allocated */ + if (gRampacRam != 0) + free_rampac_mem(); +} + +/* +======================================================================== +save_remem_ram: This routine saves the ReMem emulation RAM to the ReMem + file. +======================================================================== +*/ +void save_remem_ram(void) +{ + FILE *fd; + int size; + + /* Open ReMem file */ + fd = fopen(mem_setup.remem_file, "wb+"); + + /* Check if file opened successfully */ + if (fd != 0) + { + size = 1024 * 2048; /* Copy 2 meg of RAM & FLASH + + /* Write ReMem RAM first */ + fwrite(gReMemRam, 1, size, fd); + + /* Now write Flash */ + fwrite(gReMemFlash1, 1, size, fd); + fwrite(gReMemFlash2, 1, size, fd); + + /* Close the file */ + fclose(fd); + } +} + +/* +======================================================================== +save_rampac_ram: This routine saves the Rampac emulation RAM to the + Rampac file. +======================================================================== +*/ +void save_rampac_ram(void) +{ + FILE *fd; + int size; + + /* Open Rampac file */ + fd = fopen(mem_setup.rampac_file, "wb+"); + + /* Check if file opened successfully */ + if (fd != 0) + { + size = 1024 * 256; /* Copy 256 K of RAM + + /* Write ReMem RAM first */ + fwrite(gRampacRam, 1, size, fd); + + /* Close the file */ + fclose(fd); + } +} + +/* +======================================================================== +save_ram: This routine saves the contens of the RAM after + emulation has completed (or anytime it is called). + + This routine currently does not support any external + hardware memory additions. Current support is as follows: + + M100, M102: 32K RAM + T200: 72K RAM + PC8201, PC8300: 64K RAM +======================================================================== +*/ +void save_ram(void) +{ + char file[256]; + FILE *fd; + + /* Check if ReMem emulation enabled or Base Memory emulation */ + if (gReMem) + { + save_remem_ram(); /* Save ReMem data to file */ + } + else + { + /* Base memory -- First get the emulation path */ + get_emulation_path(file, gModel); + + /* Append the RAM filename for Base Memory emulation */ + strcat(file, "RAM.bin"); + + /* Open the RAM file */ + fd=fopen(file, "wb+"); + if(fd != 0) + { + /* Save based on which model is being emulated */ + switch (gModel) + { + case MODEL_M100: /* M100 & M102 have single bank */ + case MODEL_M102: + fwrite(memory+RAMSTART, 1, RAMSIZE, fd); + break; + + case MODEL_T200: + /* Update rambanks array with current memory bank */ + memcpy(&rambanks[gRamBank*24576], &memory[RAMSTART], RAMSIZE); + + /* Save RAM */ + fwrite(rambanks, 1, 3*RAMSIZE, fd); + + /* Write bank number to file */ + fwrite(&gRamBank, 1, 1, fd); + + break; + + case MODEL_PC8201: + case MODEL_PC8300: + /* Update rambanks array with current memory bank */ + memcpy(&rambanks[gRamBank*RAMSIZE], &memory[RAMSTART], RAMSIZE); + + /* Save RAM */ + fwrite(rambanks, 1, 3*RAMSIZE, fd); + + /* Write bank number to file */ + fwrite(&gRamBank, 1, 1, fd); + fwrite(&gRomBank, 1, 1, fd); + + break; + } + + /* Close the file */ + fclose(fd); + } + } + + /* + =========================================== + Save Rampac RAM if enabled + =========================================== + */ + if (gRampac) + { + save_rampac_ram(); /* Save Rampac RAM to file */ + } +} + +/* +======================================================================== +load_remem_ram: This routine loads the ReMem emulation RAM from the + ReMem file. +======================================================================== +*/ +void load_remem_ram(void) +{ + FILE *fd; + int size; + + /* Open ReMem file */ + fd = fopen(mem_setup.remem_file, "rb+"); + + /* Check if file opened successfully */ + if (fd != 0) + { + size = 1024 * 2048; /* Copy 2 meg of RAM & FLASH + + /* Write ReMem RAM first */ + fread(gReMemRam, 1, size, fd); + + /* Now write Flash */ + fread(gReMemFlash1, 1, size, fd); + fread(gReMemFlash2, 1, size, fd); + + /* Close the file */ + fclose(fd); + } +} + +/* +======================================================================== +load_rampac_ram: This routine loads the Rampac emulation RAM from the + Rampac file. +======================================================================== +*/ +void load_rampac_ram(void) +{ + FILE *fd; + int size; + + /* Open Rampac file */ + fd = fopen(mem_setup.rampac_file, "wb+"); + + /* Check if file opened successfully */ + if (fd != 0) + { + size = 1024 * 256; /* Copy 256 K of RAM + + /* Write ReMem RAM first */ + fread(gRampacRam, 1, size, fd); + + /* Close the file */ + fclose(fd); + } +} + +/* +======================================================================== +load_ram: This routine loads the contens of the RAM in preparation + for emulation (or anytime it is called). + + This routine currently does not support any external + hardware memory additions. Current support is as follows: + + M100, M102: 32K RAM + T200: 72K RAM + PC8201, PC8300: 64K RAM +======================================================================== +*/ +void load_ram(void) +{ + char file[256]; + FILE *fd; + + /* Check if ReMem emulation enabled or Base Memory emulation */ + if (gReMem) + { + load_remem_ram(); /* Call routine to load ReMem */ + } + else + { + /* First get the emulation path */ + get_emulation_path(file, gModel); + + /* Append the RAM filename */ + strcat(file, "RAM.bin"); + + /* Open the RAM file */ + fd = fopen(file, "rb+"); + if(fd == 0) + return; + + /* Save based on which model is being emulated */ + switch (gModel) + { + case MODEL_M100: /* M100 & M102 have single bank */ + case MODEL_M102: + fread(memory+RAMSTART, 1, RAMSIZE, fd); + break; + + case MODEL_T200: + /* Read all ram into rambanks array */ + fread(rambanks, 1, 3*RAMSIZE, fd); + + /* Read bank number to file */ + fread(&gRamBank, 1, 1, fd); + + /* Test bank number for bounds */ + if (gRamBank > 2) + gRamBank = 0; + + /* Seek to the correct location for this bank */ + memcpy(&memory[RAMSTART], &rambanks[gRamBank*24576], RAMSIZE); + + /* Update Hardware with Bank */ + io_set_ram_bank(gRamBank); + + break; + + case MODEL_PC8201: + case MODEL_PC8300: + /* Read all ram into rambanks array */ + fread(rambanks, 1, 3*RAMSIZE, fd); + + /* Read bank number to file */ + fread(&gRamBank, 1, 1, fd); + fread(&gRomBank, 1, 1, fd); + + /* Test bank number for bounds */ + if (gRamBank > 2) + gRamBank = 0; + + /* Seek to the correct location for this bank */ + memcpy(&memory[RAMSTART], &rambanks[gRamBank*RAMSIZE], RAMSIZE); + + /* Update Hardware with RAM Bank */ + io_set_ram_bank(gRamBank); + + /* Update Hardware with ROM Bank */ + + break; + } + + /* Close the file */ + fclose(fd); + } + + /* + =========================================== + Load Rampac RAM if enabled + =========================================== + */ + if (gRampac) + { + load_rampac_ram(); /* Call routine to load Rampac */ + } +} + +/* +============================================================================= +load_opt_rom: This function loads option ROMS as specified by user settings. +============================================================================= +*/ +void load_opt_rom(void) +{ + int len, c; + FILE *fd; + unsigned short start_addr; + char buf[65536]; + + // Clear the option ROM memory + memset(optROM,0,OPTROMSIZE); + + // Check if an option ROM is loaded + if ((len = strlen(gsOptRomFile)) == 0) + return; + + // Check type of option ROM + if (((gsOptRomFile[len-1] | 0x20) == 'x') && + ((gsOptRomFile[len-2] | 0x20) == 'e') && + ((gsOptRomFile[len-3] | 0x20) == 'h')) + { + // Load Intel HEX file + len = load_hex_file(gsOptRomFile, buf, &start_addr); + + // Check for invalid HEX file + if ((len > 32768) || (start_addr != 0)) + return; + + // Copy data to optROM + for (c = 0; c < len; c++) + optROM[c] = buf[c]; + + } + else + { + // Open BIN file + fd=fopen(gsOptRomFile,"rb"); + if(fd!=0) + { + fread(optROM,1, OPTROMSIZE, fd); + fclose(fd); + } + } +} + +/* +============================================================================= +set_ram_bank: This function sets the current RAM bank for Model T200 and + NEC PCs. It checks for ReMem emulation and properly swaps + out the memory space in the 2Meg Memory space. +============================================================================= +*/ +void set_ram_bank(unsigned char bank) +{ + int block; + + if (!gReMem) + { + /* Deal with Non-Remem Banks */ + switch (gModel) + { + case MODEL_T200: /* Model T200 RAM banks */ + case MODEL_PC8201: /* NEC Laptop banks */ + case MODEL_PC8300: + memcpy(&rambanks[gRamBank*RAMSIZE], &memory[RAMSTART], RAMSIZE); + gRamBank = bank; + memcpy(&memory[RAMSTART], &rambanks[gRamBank*RAMSIZE], RAMSIZE); + } + } + else + { + /* Deal with ReMem emulation mode */ + if (gModel == MODEL_T200) + { + /* Write all RAM bank blocks back to ReMem memory */ + if (!(gReMemMode & REMEM_MODE_NORMAL)) + { + /* Copy system to normal mode ReMem RAM */ + remem_copy_system_to_normal(); + } + else + { + /* Loop through 24 1K RAM Blocks */ + for (block = 40; block < 64; block++) + remem_copy_block_to_mmu(block); + + /* Now set the new RAM bank */ + gRamBank = bank; + remem_update_vectors(gReMemMode); + + /* Loop through 24 1K RAM Blocks */ + for (block = 40; block < 64; block++) + remem_copy_mmu_to_block(block); + } + } + } +} + +/* +============================================================================= +set_rom_bank: This function sets the current ROM bank for all models. It + checks for ReMem emulation and properly swaps out the memory + space to one of the 2Meg FLASH Memory spaces. +============================================================================= +*/ +void set_rom_bank(unsigned char bank) +{ + int block, blocks; + + if (!gReMem) + { + /* Deal with non-ReMem emulation */ + switch (gModel) + { + case MODEL_M100: /* Model 100 / 102 emulation */ + case MODEL_M102: + if (bank & 0x01) + { + memcpy(memory,optROM,ROMSIZE); + cROM=1; + } + else + { + memcpy(memory,sysROM,ROMSIZE); + cROM=0; + } + break; + + case MODEL_T200: /* Model 200 emulation */ + gRomBank = bank; + switch (bank) { + case 0: + memcpy(memory,sysROM,ROMSIZE); + break; + case 1: + memcpy(memory, msplanROM, sizeof(msplanROM)); + break; + case 2: + memcpy(memory,optROM,sizeof(optROM)); + break; + } + break; + + case MODEL_PC8201: /* NEC laptops */ + case MODEL_PC8300: + gRomBank = bank; /* Update global ROM bank var */ + + switch (bank) + { + case 0: /* System ROM bank */ + memcpy(memory,sysROM,ROMSIZE); + break; + + case 1: /* Option ROM bank */ + memcpy(memory,optROM,ROMSIZE); + break; + + case 2: /* RAM banks */ + case 3: + memcpy(memory,&rambanks[(bank-1)*RAMSIZE],RAMSIZE); + break; + } + break; + } + } + else + { + /* Write all ROM bank blocks back to ReMem memory */ + if (gReMemMode & REMEM_MODE_NORMAL) + { + /* Calculate number of ROM blocks base on model */ + blocks = gModel == MODEL_T200 ? 40 : 32; + + /* Loop through all 1K ROM Blocks & copy from system to MMU */ + for (block = 0; block < blocks; block++) + remem_copy_block_to_mmu(block); + + /* Now set the new RAM bank */ + if (gModel == MODEL_T200) + gRomBank = bank; + else + cROM = bank & 0x01; + remem_update_vectors(gReMemMode); + + /* Loop through all 1K ROM Blocks & copy to system memory */ + for (block = 0; block < blocks; block++) + remem_copy_mmu_to_block(block); + } + } +} + +/* +============================================================================= +remem_set8: This function services memory writes while in ReMem emulation + mode. It validates if the 1K block of memory being accessed + is set to Read-Only and traps writes to the MMU section of + memory to copy ReMem memory to/from system memory when writes + to the active map are made. +============================================================================= +*/ +void remem_set8(unsigned int address, unsigned char data) +{ + int block; /* Which 1K block is being accessed */ + + /* Calculate which block is being accessed */ + block = address >> 11; + + /* Test if ReMem memory block is read-only */ + if (gReMemMap[block] & REMEM_VCTR_READ_ONLY) + return; + + /* Test if accessing MMU vector for current map */ + if (gReMemMap[block] & REMEM_VCTR_MMU_ACTIVE) + { + /* Need to validate that address is accssing active portion of MMU page */ + } + + /* Update memory with data */ + memory[address] = data; +} + + +/* +============================================================================= +remem_out: This function services out operations to the ReMem emulation. + ReMem uses port I/O for configuration of memory maps, etc. +============================================================================= +*/ +int remem_out(unsigned char port, unsigned char data) +{ + int ret = 0; /* Indicate if port serviced or not */ + int romSector, ramSector; + int bank; + + /* Test if ReMem emulation is enabled */ + if (!gReMem || (gReMemRam == 0)) + return 0; + + /* Process port number being accessed */ + switch (port) + { + + case REMEM_MODE_PORT: /* ReMem mode port */ + ret = 1; /* Indicate port processed */ + + /* Test if old mode = new mode and do nothing if equal */ + if (data == gReMemMode) + break; + + /* + ====================================================================== + First copy existing system memory to ReMem memory + ====================================================================== + */ + + /* Test if changing from normal mode to ReMem mode */ + if ((data & REMEM_MODE_NORMAL) != (gReMemMode & REMEM_MODE_NORMAL)) + { + /* Save system memory to ReMem "Normal mode" memory */ + if (!(gReMemMode & REMEM_MODE_NORMAL)) + remem_copy_system_to_normal(); + } + + /* Test if the MAP selection is being changed */ + else if ((data & REMEM_MODE_MAP_BITS) != (gReMemMode & REMEM_MODE_MAP_BITS)) + { + /* Copy system memory blocks to ReMem blocks */ + if (gReMemMode & REMEM_MODE_NORMAL) + remem_copy_system_to_mmu(); + } + + /* Calculate ReMem Map vector pointer */ + remem_update_vectors(data); + + /* + ====================================================================== + Now copy ReMem memory to system memory + ====================================================================== + */ + /* Test if new mode is "Normal" mode */ + if (!(data & REMEM_MODE_NORMAL)) + { + /* Copy "Normal" ReMem memory space to sysem memory */ + remem_copy_normal_to_system(); + } + else if ((data & REMEM_MODE_MAP_BITS) != (gReMemMode & REMEM_MODE_MAP_BITS)) + { + /* Copy MMU data to system RAM */ + remem_copy_mmu_to_system(); + } + + /* Update ReMem mode */ + gReMemMode = data; + break; + + + /* ReMem port for setting the vector access sector */ + case REMEM_SECTOR_PORT: + /* Test if ReMem emulation enabled */ + if (!gReMem) + break; + + gReMemSector = data; /* Update Sector number */ + gReMemCounter = 0; /* Clear the ReMem counter */ + gReMemSectPtr = (unsigned char *) (gReMemRam + gReMemSector * REMEM_BANK_SIZE); + ret = 1; /* Indicate Port I/O processed */ + break; + + /* ReMem port for writing vector data */ + case REMEM_VCTR_PORT: + /* Insure ReMem enabled */ + if (!gReMem) + break; + + /* Calculate current MMU ROM bank */ + bank = gModel == MODEL_T200 ? gRomBank : cROM; + + /* Convert current MMU map / ROM bank to sector format */ + romSector = ((gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT) * + REMEM_BANKS_PER_MAP + bank; + + /* Calculate current MMU RAM bank */ + bank = gModel == MODEL_T200 ? gRamBank : 1; + + /* Convert current MMU map / ROM bank to sector format */ + ramSector = ((gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT) * + REMEM_BANKS_PER_MAP + bank; + + /* Test if Current ReMem Sector same as current ReMem Map/Bank selection */ + if ((gReMemSector == romSector) || (gReMemSector == ramSector)) + { + /* Copy system memory to ReMem memory */ + remem_copy_block_to_mmu(gReMemCounter >> 1); + + /* Update ReMem MMU */ + *gReMemSectPtr = data; + + /* Copy new MMU data to system */ + remem_copy_mmu_to_block(gReMemCounter >> 1); + } + + /* Write vector data to ReMem RAM */ + *gReMemSectPtr++ = data; + gReMemCounter++; /* Increment Sector Counter */ + if (gReMemCounter >= REMEM_BANK_SIZE) + { + gReMemSector++; /* Increment to next sector */ + gReMemCounter = 0; /* Clear sector counter */ + gReMemSectPtr = (unsigned char *) (gReMemRam + gReMemSector * REMEM_BANK_SIZE); + } + ret = 1; /* Indicate Port I/O processed */ + break; + + /* RamPac Set Vector port */ + case RAMPAC_SECTOR_PORT: + ret = 1; + break; + + /* RamPac Write Byte port */ + case RAMPAC_DATA_PORT: + ret = 1; + break; + + /* Other Ports not supported */ + default: + ret = 0; + break; + } + + return ret; +} + + +/* +============================================================================= +remem_update_vectors: This function updates the gReMemMap with memory + vectors for the targetMode mode. +============================================================================= +*/ +void remem_update_vectors(unsigned char targetMode) +{ + int map; /* ReMem map selection */ + int c; /* Map vector counter */ + int x; + int block; /* Block being updated */ + int bank; /* ReMem vector bank being used based on optRom, etc. */ + int offset; /* Offset of RAM vectors within page */ + unsigned short mmuBlock; /* Start address of active MMU Map region */ + unsigned short *pMapPtr; /* Pointer to ReMem map vectors */ + int romBlocks; /* Number of ROM blocks that need to be updated */ + int ramBlocks; /* Number of RAM blocks that need to be updated */ + + /* Calculate number of ROM blocks vs. RAM blocks */ + romBlocks = (gModel == MODEL_T200 ? 40 : 32); + ramBlocks = 64 - romBlocks; + block = 0; + map = (targetMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT; + + /* Update block vectors for both ROM and RAM banks */ + for (x = 0; x < 2; x++) + { + /* Calculate location of vectors in ROM map based on Bank selection */ + if (x == 0) + bank = gModel == MODEL_T200 ? gRomBank : cROM << 1; + else + bank = gModel == MODEL_T200 ? gRamBank : 1; + offset = x ? REMEM_RAM_BANK_OFFSET : 0; + mmuBlock = (unsigned short) ((REMEM_MAP_OFFSET + map * REMEM_MAP_SIZE + + bank * REMEM_BANK_SIZE + offset) >> 11); + pMapPtr = (unsigned short *) (gReMemRam + REMEM_MAP_OFFSET + map * REMEM_MAP_SIZE + + bank * REMEM_BANK_SIZE + offset); + + /* Update ReMem ROM/RAM blocks */ + for (c = 0; c < !x ? romBlocks : ramBlocks; c++) + { + gReMemMap[block] = pMapPtr[c]; /* Copy map vector from ReMem RAM */ + + /* Test for Global R/O bit in ReMemMode for FLASH1 */ + if ((gReMemMap[block] & REMEM_VCTR_FLASH1_CS) == 0) + { + if (gReMemMode & REMEM_MODE_FLASH1_RO) + gReMemMap[block] |= REMEM_VCTR_READ_ONLY; + } + + /* Test for Global R/O bit in ReMemMode for FLASH2 */ + if ((gReMemMap[block] & REMEM_VCTR_FLASH2_CS) == 0) + { + if (gReMemMode & REMEM_MODE_FLASH2_RO) + gReMemMap[block] |= REMEM_VCTR_READ_ONLY; + } + + /* Test if Block being mapped is active MMU Map space */ + if ((gReMemMap[block] & REMEM_VCTR_ADDRESS) == mmuBlock) + gReMemMap[block] |= REMEM_VCTR_MMU_ACTIVE; + + /* Increment to next block */ + block++; + } + } +} + +/* +============================================================================= +remem_copy_normal_to_system: This function copies memory from "Normal" + mode space to system memory space. +============================================================================= +*/ +void remem_copy_normal_to_system(void) +{ + int bytes; /* Number of bytes to copy */ + int c; /* Byte counter */ + int dest; /* Destination location */ + uchar *pSrc; /* Source address */ + + /* First copy ROM to system memory */ + bytes = gModel == MODEL_T200 ? gRomBank ? 32768 : 40960 : 32768; + pSrc = (gReMemBoot ? gReMemFlash2 : gReMemFlash1) + + 0x10000 * (gModel == MODEL_T200 ? gRomBank : cROM); + dest = 0; + + /* Copy the ROM bytes */ + for (c = 0; c < bytes; c++) + memory[dest++] = *pSrc++; + + /* Now prepare to copy the RAM bytes */ + bytes = gModel == MODEL_T200 ? 24576 : 32768; + pSrc = gReMemRam + 0x10000 * (gModel == MODEL_T200 ? gRamBank : cROM) + + (gModel == MODEL_T200 ? 40960 : 32768); + + /* Copy the RAM bytes */ + for (c = 0; c < bytes; c++) + memory[dest++] = *pSrc++; +} + +/* +============================================================================= +remem_copy_mmu_to_system: This function copies memory from MMU mode space + to system memory space. +============================================================================= +*/ +void remem_copy_mmu_to_system(void) +{ + int block; /* Block being copied */ + + /* Loop through all blocks */ + for (block = 0; block < 64; block++) + { + remem_copy_mmu_to_block(block); + } +} + +/* +============================================================================= +remem_copy_mmu_to_block: This function copies a 1K block from MMU mode + space to system memory space. +============================================================================= +*/ +void remem_copy_mmu_to_block(int block) +{ + int c; /* Byte counter */ + uchar *pSrc; /* Source pointer */ + int dest; /* Destination pointer */ + + /* Calculate source pointer based on block vector */ + if ((gReMemMap[block] & REMEM_VCTR_RAM_CS) == 0) + pSrc = gReMemRam; + else if ((gReMemMap[block] & REMEM_VCTR_FLASH1_CS) == 0) + pSrc = gReMemFlash1; + else if ((gReMemMap[block] & REMEM_VCTR_FLASH1_CS) == 0) + pSrc = gReMemFlash2; + else + return; + + /* Calculate offset of 1K block */ + pSrc += (gReMemMap[block] & REMEM_VCTR_ADDRESS) << 11; + dest = block * 1024; + + /* Copy bytes */ + for (c = 0; c < 1024; c++) + memory[dest++] = *pSrc++; +} + +/* +============================================================================= +remem_copy_system_to_normal: This function copies memory from System + memory space to "Normal" mode space. +============================================================================= +*/ +void remem_copy_system_to_normal(void) +{ + int bytes; /* Number of bytes to copy */ + int c; /* Byte counter */ + int src; /* Destination location */ + uchar *pDest; /* Source address */ + + /* Copy only the RAM bytes */ + if (gModel == MODEL_T200) + { + bytes = 24576; + pDest = gReMemRam + 0x10000 * gRamBank + 40960; + src = 40960; + } + else + { + bytes = 32768; + pDest = gReMemRam + 0x10000 * cROM + 32768; + src = 32768; + } + + /* Copy the RAM bytes */ + for (c = 0; c < bytes; c++) + *pDest++ = memory[src++]; +} + +/* +============================================================================= +remem_copy_system_to_mmu: This function copies memory from System + memory space to MMU mode space. +============================================================================= +*/ +void remem_copy_system_to_mmu(void) +{ + int block; /* Block being copied */ + + /* Loop through all blocks */ + for (block = 0; block < 64; block++) + { + remem_copy_block_to_mmu(block); + } +} + +/* +============================================================================= +remem_copy_block_to_mmu: This function copies a 1K block of RAM from + system space to ReMem space base on the current + ReMem mode settings. The spcified 1K block of + system RAM is copied. +============================================================================= +*/ +void remem_copy_block_to_mmu(int block) +{ + int c; /* Byte counter */ + uchar *pDest; /* Destination pointer */ + int src; /* Source pointer */ + + /* Check if block is read-only, skip copy if read-only*/ + if (gReMemMap[block] & REMEM_VCTR_READ_ONLY) + return; + + /* Calculate source pointer base on block vector */ + if ((gReMemMap[block] & REMEM_VCTR_RAM_CS) == 0) + pDest = gReMemRam; + else if ((gReMemMap[block] & REMEM_VCTR_FLASH1_CS) == 0) + pDest = gReMemFlash1; + else if ((gReMemMap[block] & REMEM_VCTR_FLASH1_CS) == 0) + pDest = gReMemFlash2; + else + return; + + /* Calculate offset of 1K block */ + pDest += (gReMemMap[block] & REMEM_VCTR_ADDRESS) << 11; + src = block * 1024; + + /* Copy bytes */ + for (c = 0; c < 1024; c++) + *pDest++ = memory[src++]; +} + diff --git a/src/memory.h b/src/memory.h index 891a4cb..e2b5e5b 100644 --- a/src/memory.h +++ b/src/memory.h @@ -13,9 +13,85 @@ memory.h #ifndef MEMORY_H #define MEMORY_H -unsigned char get_memory8(unsigned short address); -unsigned short get_memory16(unsigned short address); -void set_memory8(unsigned short address, unsigned char data); -void set_memory16(unsigned short address, unsigned short data); +#ifdef __cplusplus +extern "C" { +#endif + +#define REMEM_MODE_NORMAL 0x01 +#define REMEM_MODE_RAMPAC 0x02 +#define REMEM_MODE_MAP_BITS 0x1C +#define REMEM_MODE_MAP_SHIFT 2 +#define REMEM_MODE_FLASH1_RO 0x20 +#define REMEM_MODE_FLASH2_RO 0x40 + +#define REMEM_MODE_PORT 0x70 +#define REMEM_SECTOR_PORT 0x71 +#define REMEM_VCTR_PORT 0x73 +#define RAMPAC_SECTOR_PORT 0x81 +#define RAMPAC_DATA_PORT 0x83 + +#define REMEM_VCTR_RAM_CS 0x2000 +#define REMEM_VCTR_FLASH1_CS 0x1000 +#define REMEM_VCTR_FLASH2_CS 0x0800 +#define REMEM_VCTR_READ_ONLY 0x4000 +#define REMEM_VCTR_MMU_ACTIVE 0x8000 +#define REMEM_VCTR_ADDRESS 0x07FF + +#define REMEM_MAP_OFFSET 0x00100000000 +#define REMEM_MAP_SIZE (gModel == MODEL_T200 ? 1024 : 512) +#define REMEM_BANK_SIZE (gModel == MODEL_T200 ? 256 : 128) +#define REMEM_BANKS_PER_MAP (gModel == MODEL_T200 ? 8 : 4) +#define REMEM_RAM_BANK_OFFSET 0xA0 + +#define REGION_RAM 0 +#define REGION_ROM 1 +#define REGION_ROM2 2 +#define REGION_OPTROM 3 +#define REGION_RAM1 4 +#define REGION_RAM2 5 +#define REGION_RAM3 6 +#define REGION_REMEM_RAM 7 +#define REGION_FLASH1 8 +#define REGION_FLASH2 9 +#define REGION_RAMPAC 10 + +void init_mem(void); +void free_mem(void); +void free_remem_mem(void); +void free_rampac_mem(void); +void load_rampac_ram(void); +void load_remem_ram(void); +void save_rampac_ram(void); +void save_remem_ram(void); + +unsigned char get_memory8(unsigned short address); +unsigned short get_memory16(unsigned short address); +void set_memory8(unsigned short address, unsigned char data); +void set_memory16(unsigned short address, unsigned short data); + +void get_memory8_ext(int region, long address, int count, unsigned char *data); +void set_memory8_ext(int region, long address, int count, unsigned char *data); + +void remem_set8(unsigned int address, unsigned char data); +int remem_out(unsigned char port, unsigned char data); +int remem_in(unsigned char port, unsigned char *data); +void remem_update_vectors(unsigned char targetMode); +void remem_copy_normal_to_system(void); +void remem_copy_mmu_to_system(void); +void remem_copy_system_to_normal(void); +void remem_copy_system_to_mmu(void); +void remem_copy_mmu_to_block(int block); +void remem_copy_block_to_mmu(int block); + +void save_ram(void); +void load_ram(void); +void load_opt_rom(void); +void set_ram_bank(unsigned char page); +void set_rom_bank(unsigned char bank); + + +#ifdef __cplusplus +} +#endif #endif diff --git a/src/n8201rom.c b/src/n8201rom.c new file mode 100644 index 0000000..2508a34 --- /dev/null +++ b/src/n8201rom.c @@ -0,0 +1,916 @@ +/* n8201rom.c */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "roms.h" +#include "romstrings.h" + + +Std_ROM_Table_t gN8201_Tables[] = { + { 0x0003, 5, TABLE_TYPE_STRING }, + { 0x0040, 266, TABLE_TYPE_JUMP }, + { 0x014A, 26*2,TABLE_TYPE_JUMP }, + { 0x017E, 542, TABLE_TYPE_MODIFIED_STRING2 }, + { 0x03BD, 40, TABLE_TYPE_JUMP }, + { 0x03E5, 70, TABLE_TYPE_2BYTE }, + { 0x042B, 225, TABLE_TYPE_CODE }, + { 0x050C, 23, TABLE_TYPE_STRING }, + { 0x0F5D, 19, TABLE_TYPE_STRING }, + { 0x1057, 17, TABLE_TYPE_STRING }, + { 0x1712, 16, TABLE_TYPE_STRING }, + { 0x1962, 10, TABLE_TYPE_JUMP }, + { 0x1974, 10, TABLE_TYPE_JUMP }, + { 0x1AF7, 10, TABLE_TYPE_JUMP }, + { 0x1BCC, 6, TABLE_TYPE_JUMP }, + { 0x1BDA, 10, TABLE_TYPE_JUMP }, + { 0x1CEC, 10, TABLE_TYPE_JUMP }, + { 0x287B, 6, TABLE_TYPE_STRING }, + { 0x2ABF, 12, TABLE_TYPE_STRING }, + { 0x2FDA, 1, TABLE_TYPE_CODE }, + { 0x2FEB, 4*4, TABLE_TYPE_CODE }, + { 0x3CE2, 12, TABLE_TYPE_CODE }, + { 0x3DFD, 1, TABLE_TYPE_CODE }, + { 0x3DFE, 7*4, TABLE_TYPE_CODE }, + { 0x3F49, 1, TABLE_TYPE_CODE }, + { 0x3F4A, 5*4, TABLE_TYPE_CODE }, + { 0x3F98, 1, TABLE_TYPE_CODE }, + { 0x3F99, 9*4, TABLE_TYPE_CODE }, + { 0x43EF, 36, TABLE_TYPE_BYTE_LOOKUP }, + { 0x4429, 72, TABLE_TYPE_BYTE_LOOKUP }, + { 0x47FC, 8*3, TABLE_TYPE_BYTE_LOOKUP }, + { 0x528D, 29, TABLE_TYPE_CTRL_DELIM }, + { 0x52AA, 1, TABLE_TYPE_CODE }, + { 0x52AB, 16, TABLE_TYPE_JUMP }, + { 0x5318, 9, TABLE_TYPE_STRING }, + { 0x5321, 18, TABLE_TYPE_4BYTE_CMD }, + { 0x5333, 1, TABLE_TYPE_CODE }, + { 0x5334, 25, TABLE_TYPE_STRING }, + { 0x536B, 29, TABLE_TYPE_STRING }, + { 0x5445, 20, TABLE_TYPE_JUMP }, + { 0x54AD, 17, TABLE_TYPE_STRING }, + { 0x54BE, 7, TABLE_TYPE_STRING }, + { 0x560A, 53, TABLE_TYPE_STRING }, + { 0x5E61, 5, TABLE_TYPE_CODE }, + { 0x5E66, 4, TABLE_TYPE_STRING }, + { 0x5E6A, 2, TABLE_TYPE_CODE }, + { 0x5E6C, 4, TABLE_TYPE_STRING }, + { 0x5E70, 2, TABLE_TYPE_CODE }, + { 0x5E72, 4, TABLE_TYPE_STRING }, + { 0x5E76, 2, TABLE_TYPE_CODE }, + { 0x5E78, 1, TABLE_TYPE_CODE }, + { 0x5E79, 57, TABLE_TYPE_STRING }, + { 0x5EB2, 150, TABLE_TYPE_STRING }, + { 0x5FEB, 13, TABLE_TYPE_STRING }, + { 0x5FFC, 8, TABLE_TYPE_CODE }, + { 0x551D, 1, TABLE_TYPE_CODE }, + { 0x6002, 22, TABLE_TYPE_STRING }, + { 0x6105, 17, TABLE_TYPE_STRING }, + { 0x61EF, 64, TABLE_TYPE_JUMP }, + { 0x6845, 21, TABLE_TYPE_BYTE_LOOKUP }, + { 0x6C8E, 66, TABLE_TYPE_CATALOG }, + { 0x6F40, 18, TABLE_TYPE_JUMP }, + { 0x75DA, 240, TABLE_TYPE_CODE }, + { 0x76CC, 20, TABLE_TYPE_CODE }, + { 0x78B7, 96*5, TABLE_TYPE_CODE }, + { 0x7A97, 85*6-1, TABLE_TYPE_CODE }, +/* { 0x7BF1, 322, TABLE_TYPE_CODE }, +*/ { 0x7EA1, 14, TABLE_TYPE_CODE }, + { 0x7F89, 12, TABLE_TYPE_STRING }, + { 0x7F95, 12, TABLE_TYPE_STRING }, + { 0x7FA1, 14, TABLE_TYPE_STRING }, + { 0x7FAF, 15, TABLE_TYPE_STRING }, + { -1, 0, 0 } +}; + +Std_ROM_Addresses_t gN8201_Vars[] = { + { 0x0040, R_FUN_VCTR_TBL }, + { 0x0080, R_BASIC_TBL }, + { 0x02EE, R_MATH_VCTR_TBL }, + { 0x03E5, R_BASIC_ERR_TXT }, + { 0x042B, R_INIT_IMAGE }, + { 0x036F, R_XROM_DET_IMAGE }, + { 0x050C, R_BASIC_STRINGS }, +// { 0x1F24, R_CAS_FREQ_CNT }, +// { 0x4349, R_CAS_FREQ_CNT }, + { 0xF3C2, R_TERM_FKEY_VCTR_TBL }, + { 0x5E61, R_DIR_DISP_ORDER_TBL }, + { 0x5FF7, R_TEXT_FKEY_VCTR_TBL }, + { 0x5C8E, R_ROM_CAT_ENTRIES }, + { 0x7266, R_INT_EXIT_FUN }, + { 0x7267, R_INT_EXIT_FUN }, + { 0x75DA, R_8155_PIO_PAT1 }, + { 0x76CC, R_8155_PIO_PAT2 }, + { 0x7EA1, R_INIT_CLK_VALUES }, + { 0x7F89, R_MENU_STRINGS }, + { 0x7F95, R_MODEL_NUM_STRING }, + { 0xF380, R_ACTIVE_SIGNATURE }, + { 0xF384, R_HIMEM }, + { 0xF386, R_RST0_HOOK }, + { 0xF389, R_RST_5_5_VCTR }, + { 0xF38C, R_RST_6_5_VCTR }, + { 0xF38F, R_RST_7_5_VCTR }, + { 0xF392, R_TRAP_VCTR }, + { 0xF3B9, R_EXEC_2ND_ROM }, + { 0xF3C0, R_TELCOM_FKEY_VCTR }, + { 0xF3BF, R_OPTION_ROM_FLAG }, + { 0xF3C0, R_FKEY_STAT_TBL }, + { 0xF3E8, R_NEW_CONSOLE_FLAG }, + { 0xF3E5, R_CURSOR_ROW }, + { 0xF3E6, R_CURSOR_COL }, + { 0xF3E7, R_ACTIVE_ROW_CNT }, + { 0xF3E8, R_ACTIVE_COL_CNT }, + { 0xF3E9, R_LABEL_LINE_PROT }, + { 0xF3EA, R_SCROLL_DISABLE }, + { 0xF3EB, R_CURSOR_STAT }, + { 0xF3EC, R_CURSOR_ROW2 }, + { 0xF3ED, R_CURSOR_COL2 }, + { 0xF3F2, R_ESC_MODE_FLAG }, + { 0xF3F4, R_REV_VID_SWITCH }, + { 0xF3FA, R_LAST_PLOT_X }, + { 0xF3FB, R_LAST_PLOT_Y }, + { 0xF401, R_PWR_OFF_STAT }, + { 0xF403, R_DUPLEX_SWITCH }, + { 0xF404, R_RS232_LF_SWITCH }, + { 0xF406, R_RS232_PARAM_TBL }, + { 0xF40C, R_ADDRESS_LAST_CALLED }, + { 0xF413, R_OUT_STMT_HOOK }, + { 0xF44B, R_INP_STMT_HOOK }, + { 0xF453, R_LAST_ERROR_CODE }, + { 0xF455, R_LPT_HEAD_POS }, + { 0xF456, R_OUTPUT_DEVICE }, + { 0xF459, R_BASIC_STR_BUF_PTR }, + { 0xF45B, R_CUR_BASIC_LINE_NUM }, + { 0xF45D, R_START_BASIC_PGM_PTR }, + { 0xF461, R_END_OF_STMT_MARKER }, + { 0xF5A1, R_KEYBOARD_BUF }, + { 0xF6A4, R_CURSOR_H_POS }, + { 0xF6A5, R_FKEY_DEF_BUF }, + { 0xF746, R_BASIC_FKEY_DEF_BUF }, + { 0xF462, R_FILE_RAM_END }, + { 0xF832, R_SEC_ONES }, + { 0xF833, R_SEC_TENS }, + { 0xF834, R_MIN_ONES }, + { 0xF835, R_MIN_TENS }, + { 0xF836, R_HR_ONES }, + { 0xF837, R_HR_TENS }, + { 0xF838, R_DATE_ONES }, + { 0xF839, R_DATE_TENS }, + { 0xF83A, R_DAY_CODE }, + { 0xF83B, R_MONTH }, + { 0xF83C, R_YEAR_ONES }, + { 0xF83D, R_YEAR_TENS }, + { 0xF840, R_ONTIME_TIME }, +// { 0xF841, R_ONCOM_FLAG }, +// { 0xF945, R_ONCOM_ADDRESS }, + { 0xF841, R_ONTIME_FLAG }, +// { 0xF948, R_ONTIME_ADDRESS }, +// { 0xF94A, R_FKEY_VCTR_TBL }, + { 0xF84F, R_DIR_RAM_START }, + { 0xF979, R_UNSAVED_BASIC_PTR }, + { 0xF87C, R_PASTE_RAM_START }, +// { 0xFAAD, R_LABEL_ENABLE_FLAG }, + { 0xF9BC, R_BASIC_LIST_START }, + { 0xF9AE, R_SP_SAVE_BUF }, + { 0xF9B0, R_LOWEST_RAM }, + { 0xFAC9, R_RST_38H_OFFSET }, + { 0xF9C2, R_LAST_PGRM_LEN }, + { 0xF9CC, R_RST_38H_VCTR_TBL }, + { 0xFA8A, R_VAR_CREATE_LOC_FLAG }, + { 0xFA8B, R_LAST_VAR_TYPE }, + { 0xFA9A, R_FILE_BUF_PTR }, + { 0xFAC7, R_DATA_STMT_LINE_NUM }, + { 0xFAC9, R_FOR_NEXT_ACTIVE_FLAG }, + { 0xFACB, R_LAST_VAR_ASSIGNED_ADDR }, + { 0xFACE, R_RUNNING_LINE_NUM_ADDR }, + { 0xFAD0, R_BASIC_SP_BUF }, + { 0xFAD2, R_LAST_ERR_LINE_NUM }, + { 0xFAD4, R_LAST_ENTERED_LINE_NUM }, + { 0xFAD6, R_ERR_PTR }, + { 0xFAD8, R_ONERROR_ADDRESS }, + { 0xFADA, R_BASIC_RUNNING }, + { 0xFADD, R_BREAK_LINE_NUM }, + { 0xFADF, R_BREAK_ADDRESS }, + { 0xFAE1, R_DO_FILES_PTR }, + { 0xFAE3, R_CO_FILES_PTR }, + { 0xFAE5, R_VAR_PTR }, + { 0xFAE7, R_ARRAY_TBL_PTR }, + { 0xFAE9, R_UNUSED_MEM_PTR }, + { 0xFAEB, R_DATA_SEARCH_ADDR }, + { 0xFAED, R_DEF_TBL }, +// { 0xFBE7, R_FP_TEMP1 }, + { 0xFB28, R_FP_FAC1 }, + { 0xFB24, R_INT_FAC1 }, +// { 0xFC60, R_FP_TEMP2 }, + { 0xFB2E, R_FP_FAC2 }, + { 0xFB62, R_MAXFILES }, + { 0xFB63, R_FILE_NUM_TBL_PTR }, + { 0xFB78, R_BASIC_FILENAME }, + { 0xFB81, R_LAST_LOAD_FILENAME }, + { 0xFBC0, R_ALT_LCD_CHAR_BUF }, +// { 0xFDEF, R_MAX_MENU_DIR_LOC }, + { 0xFE40, R_XON_XOFF_CTRL }, + { 0xFE41, R_XON_XOFF_CTRL }, + { 0xFE42, R_XON_XOFF_ENABLE }, + { 0xFE43, R_RS232_INIT_STAT }, + { 0xFE44, R_PORT_90H }, + { 0xFEC4, R_RS232_CHAR_BUF }, + { 0xFE45, R_RS232_BUF_CNT }, + { 0xFE46, R_RS232_BUF_OUT }, + { 0xFE47, R_RS232_BUF_IN }, + { 0xFE49, R_CTRL_S_STAT }, + { 0xFE4A, R_UART_BAUD_TIMER_VAL }, + { 0xFE4C, R_RS232_PARITY_CTRL }, + { 0xFE57, R_KEY_SCAN_STORAGE1 }, + { 0xFE60, R_KEY_SCAN_STORAGE2 }, + { 0xFE62, R_KEY_REPT_START }, + { 0xFE66, R_2ND_KEY_BUF_PTR }, + { 0xFE68, R_KEY_BUF_CNT }, + { 0xFE69, R_KEY_TYPEAHEAD_BUF }, + { 0xFEAB, R_CURSOR_BIT_PAT_BUF }, + { -1, -1 } +}; + +Std_ROM_Addresses_t gN8201_Funs[] = { + { 0x0000, R_RESET_VECTOR }, + { 0x0008, R_COMP_BYTE_M }, + { 0x0010, R_GET_NONWHITE }, + { 0x0018, R_COMP_DE_HL }, + { 0x001E, R_PRINT_SPACE }, + { 0x0020, R_PRINT_CHAR }, +// { 0x0024, R_PWR_DOWN_TRAP }, + { 0x0028, R_DET_LAST_VAR_TYPE }, + { 0x002C, R_RST_5_5 }, +// { 0x0030, R_GET_FAC1_SIGN }, + { 0x0034, R_RST_6_5 }, +// { 0x0038, R_RAM_VCTR_TBL_DRIVER }, + { 0x003C, R_RST_7_5 }, + { 0x0040, R_FUN_VCTR_TBL }, + { 0x017E, R_BASIC_KEYWORD_TBL }, +// { 0x018F, R_FUN_KEYWORD_TBL1 }, +// { 0x01F0, R_FUN_KEYWORD_TBL2 }, +// { 0x0262, R_BASIC_VECTOR_TBL }, +// { 0x02E2, R_MATH_PRIORITY_TBL }, + { 0x03BD, R_MATH_VCTR_TBL }, + { 0x03E5, R_BASIC_ERR_MSG_TXT }, + { 0x042B, R_FUN_INIT_IMAGE }, + { 0x050C, R_FUN_BASIC_STRINGS }, + { 0x0523, R_POP_FOR_NEXT }, + { 0x0544, R_INIT_AND_READY }, + { 0x0568, R_GEN_SN_ERROR }, + { 0x056B, R_GEN_d0_ERROR }, + { 0x056E, R_GEN_NF_ERROR }, + { 0x0571, R_GEN_DD_ERROR }, + { 0x0574, R_GEN_RW_ERROR }, + { 0x0577, R_GEN_OV_ERROR }, + { 0x057A, R_GEN_MO_ERROR }, + { 0x057D, R_GEN_TM_ERROR }, + { 0x0585, R_GEN_ERR_IN_E }, + { 0x05B5, R_RESTORE_JMP_BC }, + { 0x05ED, R_PRINT_BASIC_ERR }, + { 0x0501, R_POP_GO_BASIC_RDY }, + { 0x062D, R_GO_BASIC_RDY_OK }, + { 0x063C, R_GO_BASIC_RDY }, + { 0x064E, R_PERFORM_M_GO_RDY }, + { 0x0714, R_UPDATE_LINE_ADDR }, + { 0x073A, R_EVAL_LIST_ARGS }, + { 0x075D, R_FIND_LINE_IN_DE }, + { 0x0760, R_FIND_LINE_DE_AT_HL }, + { 0x077B, R_TOKEN_COMPRESS }, + { 0x097B, R_FOR_STMT }, + { 0x09C0, R_TO_STMT }, + { 0x09D8, R_STEP_STMT }, + { 0x0A1D, R_RUN_BASIC_PGRM }, + { 0x0A4F, R_RUN_BASIC_AT_HL }, + { 0x0A55, R_EXEC_INST_IN_A }, + { 0x0A77, R_RST_10H_INC_HL }, + { 0x0B4B, R_DEFDBL_STMT }, + { 0x0B45, R_DEFINT_STMT }, + { 0x0B48, R_DEFSNG_STMT }, + { 0x0B42, R_DEFSTR_STMT }, + { 0x0B4D, R_DECL_VAR_TYPE_E }, + { 0x0B87, R_GEN_FC_ERROR }, + { 0x0B8C, R_EVAL_LINE_NUM }, + { 0x0BAC, R_ASCII_TO_BIN_PREINC }, + { 0x0BD0, R_RUN_STMT }, + { 0x0BE6, R_GOSUB_STMT }, + { 0x0C19, R_GOTO_STMT }, + { 0x0C4E, R_GEN_UL_ERROR }, + { 0x0C53, R_RETURN_STMT }, + { 0x0C8C, R_DATA_STMT }, + { 0x0C8D, R_REM_STMT }, + { 0x0CB6, R_LET_STMT }, + { 0x0D22, R_ON_STMT }, + { 0x0D27, R_ON_ERROR_STMT }, + { 0x0D4E, R_ON_KEY_STMT }, + { 0x0D87, R_ON_TIME_STMT }, + { 0x0DA3, R_RESUME_STMT }, + { 0x0DF5, R_ERROR_STMT }, + { 0x0E00, R_IF_STMT }, + { 0x0E3D, R_LPRINT_STMT }, + { 0x0E45, R_PRINT_STMT }, + { 0x0EEB, R_TAB_STMT }, + { 0x0F32, R_LINE_STMT }, + { 0x0F82, R_INPUT_NO_STMT }, + { 0x0F8C, R_INPUT_STMT }, + { 0x0FBA, R_READ_STMT }, + { 0x1091, R_EVAL_BASIC_INST }, + { 0x120B, R_INT16_DIV }, + { 0x121A, R_EVAL_FUN }, + { 0x124D, R_ERR_FUN }, + { 0x125C, R_ERL_FUN }, + { 0x12A7, R_EVAL_VAR }, + { 0x12B5, R_CONV_M_TOUPPER }, + { 0x12B6, R_CONV_A_TOUPPER }, + { 0x1306, R_ASCII_NUM_CONV }, + { 0x1323, R_NOT_FUN }, + { 0x1338, R_RST_28H }, + { 0x1366, R_OR_FUN }, + { 0x1371, R_AND_FUN }, + { 0x137C, R_XOR_FUN }, + { 0x1384, R_IMP_FUN }, + { 0x1397, R_LPOS_FUN }, + { 0x139D, R_POS_FUN }, + { 0x13A0, R_LD_FAC1_INT }, +// { 0x10E6, R_CHK_RUNNING_PGRM }, +// { 0x10EF, R_GEN_ID_ERROR }, + { 0x13B5, R_INP_FUN }, + { 0x13C1, R_OUT_STMT }, + { 0x13C7, R_EVAL_EXPR }, + { 0x13C8, R_EVAL_EXPR_PREDEC }, + { 0x13E2, R_EVAL_EXPR }, + { 0x13E3, R_EVAL_EXPR_PREDEC }, + { 0x13F0, R_LLIST_STMT }, + { 0x13F5, R_LIST_STMT }, + { 0x1462, R_BUF_TO_LCD }, + { 0x15E0, R_PEEK_FUN }, + { 0x15E7, R_POKE_FUN }, + { 0x15F3, R_EVAL_EXPR }, + { 0x1617, R_RENUM_STMT }, + { 0x174D, R_WAIT_KEY }, +// { 0x13A5, R_TOGGLE_LABEL }, + { 0x183D, R_CHK_KEY_QUEUE }, + { 0x187B, R_POWER_STMT }, + { 0x1895, R_LOW_PWR_TRAP }, + { 0x18A9, R_POWER_DOWN }, + { 0x18C6, R_POWER_CONT_STMT }, + { 0x18CE, R_POWER_ON_STMT }, + { 0x18DD, R_OUT_CH_TO_LPT }, + { 0x18EF, R_LOAD_CAS_HDR }, + { 0x18FC, R_GEN_IO_ERROR }, + { 0x1901, R_DET_CAS_SYNC_HDR }, + { 0x1913, R_CAS_MOTOR_ON }, + { 0x1915, R_CAS_MOTOR_OFF }, + { 0x191B, R_CAS_READ_BYTE }, + { 0x192F, R_CAS_WRITE_BYTE }, +// { 0x14D2, R_LCD_DCB }, +// { 0x14D8, R_LCD_OPEN }, + { 0x1955, R_LCD_OUT }, + { 0x195D, R_POP_ALL_REGS }, + { 0x1962, R_CRT_DCB }, + { 0x1974, R_RAM_DCB }, + { 0x197E, R_RAM_OPEN }, + { 0x1A05, R_RAM_CLOSE }, + { 0x1A24, R_RAM_OUT }, + { 0x1A3C, R_RAM_IN }, + { 0x1A93, R_RAM_IO }, + { 0x1AF7, R_CAS_DCB }, + { 0x1B01, R_CAS_OPEN }, + { 0x1B25, R_CAS_CLOSE }, + { 0x1B3F, R_CAS_OUT }, + { 0x1B4A, R_CAS_IN }, + { 0x1BCC, R_LPT_DCB }, + { 0x1BD2, R_LPT_OUT }, + { 0x1BDA, R_COM_DCB }, + { 0x1BE4, R_MDM_OPEN }, + { 0x1BE5, R_COM_OPEN }, + { 0x1C01, R_COM_CLOSE }, + { 0x1C1D, R_COM_OUT }, + { 0x1C28, R_COM_IN }, + { 0x1C47, R_COM_IO }, +// { 0x1C4E, R_MDM_DCB }, +// { 0x17DB, R_MDM_CLOSE }, + { 0x1C4E, R_SET_RS232_PARAMS }, + { 0x1CEC, R_BCR_DCB }, + { 0x1CFE, R_EOF_FUN }, + { 0x1D74, R_TIME_FUN }, + { 0x1D7F, R_READ_TIME }, + { 0x1D9F, R_DATE_FUN }, + { 0x1DEE, R_UPDATE_CLK_VALUES }, + { 0x1DF9, R_TIME_STMT }, +// { 0x1DF9, R_UPDATE_CLK_CHIP }, + { 0x1E07, R_DATE_STMT }, + { 0x1E5B, R_GET_TIME_STRING }, + { 0x1E91, R_COM_MDM_STMT }, + { 0x1E9E, R_DET_TIME_ARG }, + { 0x1EB0, R_TEST_COM_TOKEN }, +// { 0x1AB2, R_KEY_FUN }, +// { 0x1AC3, R_KEY_ON_OFF_STMT }, +// { 0x1AFC, R_DET_DEVICE_ARG }, +// { 0x1B0F, R_ONTIME_STMT }, +// { 0x1B22, R_ONCOM_STMT }, + { 0x1EBE, R_RST7_5_ISR }, + { 0x1EF4, R_KICK_PWR_OFF_WDT }, +// { 0x1BB8, R_KEY_STMT }, +// { 0x1BBD, R_KEY_LIST_STMT }, + { 0x1EFB, R_SEND_CHARS_TO_LCD }, + { 0x1F11, R_KEY_STMT }, + { 0x1F5E, R_PSET_STMT }, + { 0x1F6D, R_PRESET_STMT }, +// { 0x1F74, R_LINE_STMT }, +// { 0x1CA6, R_DRAW_FBOX }, +// { 0x1CBC, R_DRAW_BOX }, + { 0x1F74, R_TOKENIZE_XY }, + { 0x1FD4, R_CSRLIN_FUN }, +// { 0x1D9B, R_MAX_FUN }, +// { 0x1DA7, R_MAXRAM_FUN }, +// { 0x1DB2, R_MAXFILES_FUN }, +// { 0x1DB9, R_HIMEM_FUN }, + { 0x1FDF, R_WIDTH_STMT }, + { 0x1FE1, R_CMD_STMT }, + { 0x1FE3, R_COLOR_STMT }, + { 0x1FE5, R_PRINT_STMT }, + { 0x1FE7, R_SOUND_STMT }, +// { 0x1DE5, R_SOUND_OFF_STMT }, +// { 0x1DE6, R_SOUND_ON_STMT }, + { 0x1FFD, R_MOTOR_STMT }, + { 0x2003, R_EXEC_STMT }, + { 0x201A, R_SCREEN_STMT }, + { 0x211D, R_FILES_STMT }, + { 0x2127, R_DISPLAY_CAT }, + { 0x217B, R_KILL_STMT }, + { 0x219B, R_KILL_TEXT_FILE }, + { 0x2220, R_NAME_STMT }, + { 0x22ED, R_NEW_STMT }, + { 0x23F6, R_STRLEN }, + { 0x2402, R_GET_FIND_DO_FILE }, + { 0x240B, R_OPEN_TEXT_FILE }, + { 0x25D2, R_CSAVE_STMT }, + { 0x264D, R_BSAVE_STMT }, + { 0x2703, R_BLOAD_STMT }, + { 0x27D1, R_CAS_READ_REC }, +/* { 0x22CC, R_SAVEM_STMT }, + { 0x22DD, R_CSAVEM_STMT }, + { 0x2377, R_CLOAD_STMT }, + { 0x2413, R_CAS_READ_REC }, + { 0x2478, R_GEN_VERIFY_FAIL_ERR }, +*/ { 0x28FD, R_MOVE_B_BYTES }, + { 0x2906, R_EXEC_CO_FILE }, +/* { 0x260B, R_CAS_OPEN_OUT_BA }, + { 0x260E, R_CAS_OPEN_OUT_DO }, + { 0x2611, R_CAS_OPEN_OUT_CO }, + { 0x2650, R_CAS_OPEN_IN_BA }, + { 0x2653, R_CAS_OPEN_IN_DO }, + { 0x2656, R_CAS_OPEN_IN_CO }, +*/ { 0x2AFB, R_STR_FUN }, + { 0x2B72, R_PRINT_STRING }, + { 0x2CD0, R_MOVE_L_BYTES }, + { 0x2D04, R_LEN_FUN }, + { 0x2D10, R_ASC_FUN }, + { 0x2D20, R_CHR_FUN }, + { 0x2D2E, R_STRING_FUN }, + { 0x2D48, R_SPACE_FUN }, + { 0x2D6C, R_LEFT_FUN }, + { 0x2D9D, R_RIGHT_FUN }, + { 0x2DA7, R_MID_FUN }, + { 0x2DD3, R_VAL_FUN }, + { 0x2E03, R_INSTR_FUN }, + { 0x2E8E, R_FRE_FUN }, + { 0x34F1, R_DBL_SUB }, + { 0x34FA, R_DBL_ADD }, + { 0x2C4F, R_BCD_ADD }, + { 0x3639, R_DBL_MULT }, + { 0x3691, R_DBL_DIV }, + { 0x3EBD, R_COS_FUN }, + { 0x3EC3, R_SIN_FUN }, + { 0x3F5E, R_TAN_FUN }, + { 0x3F73, R_ATN_FUN }, + { 0x2FFC, R_LOG_FUN }, + { 0x3D4D, R_SQR_FUN }, + { 0x3DAD, R_EXP_FUN }, + { 0x3E4A, R_RND_FUN }, +/* { 0x3182, R_INIT_TEMP3 }, + { 0x31A0, R_DBL_SQR }, + { 0x31A3, R_MULT_M_FAC2 }, + { 0x31B5, R_FAC2_EQ_FAC1 }, + { 0x31B8, R_FAC2_EQ_FP }, + { 0x31C1, R_FAC1_EQ_FAC2 }, + { 0x31C4, R_FAC1_EQ_FP }, + { 0x31CA, R_M_EQ_FAC1 }, + { 0x31CA, R_MULT_FAC1_SQR_FAC1 }, + { 0x31CA, R_SWAP_FAC1_FAC2 }, + { 0x31EB, R_SQR_FAC1_MULT_TBL }, +*/ { 0x3E29, R_TBL_BASED_MATH }, +/* { 0x322E, R_PUSH_FAC2 }, + { 0x3234, R_PUSH_FAC1 }, + { 0x3245, R_POP_FAC2 }, + { 0x324B, R_POP_FAC1 }, + { 0x325C, R_FP_NUMBERS }, + { 0x327C, R_FP_SHARED_NUMBERS }, + { 0x327E, R_FP_NUMBERS }, +*/ { 0x3DFD, R_EXP_MATH_TBL }, + { 0x32F7, R_EXP_MATH_TBL }, + { 0x2FDA, R_LOG_MATH_TBL }, + { 0x2FEB, R_LOG_MATH_TBL }, + { 0x3F49, R_SIN_MATH_TBL }, + { 0x3F98, R_ATN_MATH_TBL }, + { 0x3173, R_RST_30H_FUN }, + { 0x3195, R_ABS_FUN }, + { 0x31A8, R_SGN_FUN }, + { 0x31C3, R_PUSH_SNGL_FAC1 }, + { 0x31D0, R_SNGL_FAC1_EQ_M }, + { 0x31D3, R_SNGL_FAC1_EQ_BCDE }, + { 0x31DE, R_SNGL_BCDE_EQ_FAC1 }, + { 0x31E1, R_SNGL_BCDE_EQ_M }, + { 0x31E1, R_SNGL_DECB_EQ_M }, + { 0x31EA, R_SNGL_M_EQ_FAC1 }, + { 0x31F2, R_LOAD_FAC2_FROM_M }, + { 0x31F7, R_MOVE_B_BYTES_INC }, +/* { 0x3472, R_MOVE_B_BYTES_DEC }, +*/ { 0x322E, R_SNGL_CMP_BCDE_FAC1 }, + { 0x3246, R_SNGL_CMP_BCDE_M }, + { 0x3259, R_SINT_CMP }, + { 0x3297, R_CMP_FAC1_FAC2 }, + { 0x329E, R_CINT_FUN }, + { 0x32BA, R_FAC1_EQ_SINT_HL }, + { 0x32D2, R_CSNG_FUN }, + { 0x32ED, R_CONV_SINT_SNGL }, + { 0x32F0, R_CONV_SINT_HL_SNGL }, + { 0x32FC, R_CDBL_FUN }, +/* { 0x35F8, R_SINT_SUB }, +*/ { 0x3345, R_FIX_FUN }, + { 0x3354, R_INT_FUN }, + { 0x3403, R_SINT_ADD }, + { 0x3423, R_SINT_MULT }, + { 0x347A, R_SINT_DIV }, + { 0x2EBB, R_SNGL_ADD_BCDE }, +/* { 0x37F7, R_SNGL_ADD_FAC2 }, +*/ { 0x2EC1, R_SNGL_SUB }, +/* { 0x3803, R_SNGL_MULT_BCDE }, + { 0x3806, R_SNGL_MULT_FAC2 }, + { 0x380E, R_SNGL_DIV }, + { 0x3827, R_SNGL_LOAD }, +*/ { 0x371F, R_ASCII_TO_DBL }, + { 0x374E, R_ASCII_FND_e }, + { 0x3776, R_ASCII_FND_E }, + { 0x37C1, R_ASCII_FND_DOT }, + { 0x37CC, R_ASCII_FND_PERC }, + { 0x37D7, R_ASCII_FND_LB }, + { 0x37DF, R_ASCII_CONV_HELPER }, + { 0x380D, R_ASCII_CONV_HELPER2 }, + { 0x3890, R_PRNT_BASIC_ERR_TERM }, + { 0x3898, R_PRINT_HL_ON_LCD }, + { 0x38A7, R_PRINT_FAC1 }, + { 0x38AB, R_PRINT_FAC1_FORMAT }, +/* { 0x3D11, R_FAC1_EQ_ZERO }, + { 0x3D7F, R_SNGL_EXP }, + { 0x3D8E, R_DBL_EXP }, + { 0x3DF7, R_INT_EXP }, + { 0x3F28, R_INIT_BASIC_VARS }, +*/ { 0x406A, R_TIME_ON_STMT }, + { 0x4073, R_TIME_OFF_STMT }, + { 0x4078, R_TIME_STOP_STMT }, +/* { 0x3FD2, R_TRIG_INTR }, + { 0x3FF1, R_CLEAR_INTR }, +*/ { 0x408D, R_CLEAR_COM_INT_DEF }, + { 0x40CF, R_RESTORE_STMT }, + { 0x40EA, R_STOP_STMT }, + { 0x40EF, R_END_STMT }, + { 0x412A, R_CONT_STMT }, + { 0x4141, R_ISALPHA_M }, + { 0x4142, R_ISALPHA_A }, + { 0x4149, R_CLEAR_STMT }, + { 0x41CA, R_NEXT_STMT }, + { 0x4251, R_SEND_CRLF }, + { 0x4254, R_SEND_LF }, + { 0x4258, R_BEEP_STMT }, + { 0x425C, R_HOME_CURSOR }, + { 0x4260, R_CLS_STMT }, + { 0x4264, R_PROTECT_LABEL }, + { 0x4269, R_UNPROT_LABEL }, + { 0x426E, R_STOP_AUTO_SCROLL }, + { 0x4273, R_RESUME_AUTO_SCROLL }, + { 0x4278, R_TURN_CURSOR_ON }, + { 0x427D, R_TURN_CURSOR_OFF }, + { 0x4282, R_DEL_CUR_LINE }, + { 0x4287, R_INSERT_LINE }, + { 0x428C, R_ERASE_TO_EOL }, + { 0x4291, R_SEND_ESC_X }, + { 0x42A2, R_INV_CHAR_ENABLE }, + { 0x42A7, R_INV_CHAR_DISABLE }, + { 0x42A9, R_END_ESC_SEQ }, + { 0x42B0, R_CURSOR_TO_LOW_LEFT }, + { 0x42B5, R_SET_CURSOR_POS }, + { 0x42C3, R_ERASE_FKEY_DISP }, + { 0x42E1, R_SET_DISP_FKEY }, + { 0x42E4, R_DISP_FKEY_LINE }, + { 0x4363, R_PRINT_A_TO_LCD }, +// { 0x44AA, R_CHAR_PLOT_3 }, + { 0x4380, R_CHAR_PLOT_4 }, + { 0x4395, R_CHAR_PLOT_5 }, + { 0x43D2, R_LCD_OUT_DRIVER }, + { 0x43EF, R_RST_20H_LKUP_TBL }, + { 0x4420, R_ESC_Y }, +// { 0x4429, R_LCD_OUT_ESC_FUN }, + { 0x4429, R_LCD_ESC_LKUP_TBL }, + { 0x4471, R_ESC_SEQ_DRIVER }, + { 0x44AA, R_ESC_p_FUN }, + { 0x44AB, R_ESC_q_FUN }, + { 0x44B0, R_ESC_U_FUN }, + { 0x44B2, R_ESC_T_FUN }, + { 0x44B3, R_ESC_X_FUN }, + { 0x44BE, R_ESC_V_FUN }, + { 0x44BF, R_ESC_W_FUN }, + { 0x44D2, R_ESC_C_FUN }, + { 0x44DB, R_ESC_D_FUN }, + { 0x44E0, R_BKSPACE_FUN }, + { 0x44E8, R_ESC_A_FUN }, + { 0x44ED, R_ESC_B_FUN }, + { 0x4505, R_TAB_FUN }, +/* { 0x4494, R_LF_FUN }, +*/ { 0x451B, R_ESC_H_FUN }, + { 0x451D, R_CR_FUN }, +/* { 0x44AF, R_ESC_P_FUN }, + { 0x44BA, R_ESC_Q_FUN }, +*/ { 0x4530, R_ESC_M_FUN }, + { 0x4550, R_LCD_SCROLL }, + { 0x44EA, R_ESC_L_FUN }, + { 0x4568, R_GET_LCD_CHAR }, + { 0x45B9, R_ESC_l_FUN }, + { 0x45BB, R_ESC_K_FUN }, + { 0x45CC, R_CLS_FUN }, + { 0x45D2, R_ESC_J_FUN }, + { 0x45E4, R_CHAR_PLOT_6 }, + { 0x47A4, R_INP_DISP_LINE }, + { 0x4798, R_INP_DISP_LINE_NO_Q }, + { 0x485D, R_INP_CTRL_C_HANDLER }, + { 0x4814, R_INP_ENTER_HANDLER }, + { 0x4909, R_INP_BKSP_HANDLER }, + { 0x4952, R_INP_CTRL_U_HANDLER }, +/* { 0x46CA, R_INP_TAB_HANDLER }, +*/ { 0x49AA, R_DIM_STMT }, + { 0x4BA0, R_FIND_VAR_ADDR }, + { 0x4BA1, R_USING_FUN }, + { 0x4CFA, R_SEND_A_LCD_LPT }, + { 0x4D0B, R_PRINT_A_EXPAND }, + { 0x4D3B, R_SET_OUT_DEV_LCD }, + { 0x4D54, R_LCD_CHAR_OUT_FUN }, + { 0x4D61, R_LCD_NEW_LINE }, + { 0x4D93, R_INKEY_FUN }, + { 0x4E30, R_GET_FILE_DESC }, + { 0x4E77, R_OPEN_STMT }, + { 0x4F05, R_LCD_CLOSE_FUN }, + { 0x4F1A, R_RUN_STMT }, + { 0x4F1C, R_LOAD_STMT }, + { 0x4F1D, R_MERGE_STMT }, + { 0x4F74, R_SAVE_STMT }, + { 0x4FC5, R_CLOSE_STMT }, + { 0x5029, R_INPUT_STMT }, + { 0x50A0, R_CLEAR_MEM }, + { 0x50A1, R_LOAD_MEM }, + { 0x50C4, R_PRINT_LB_INIT_FUN }, + { 0x50F1, R_LINE_INPUT_STMT }, + { 0x51E4, R_GEN_NM_ERR_FUN }, + { 0x51E7, R_GEN_AO_ERR_FUN }, + { 0x51EA, R_GEN_DS_ERR_FUN }, + { 0x51ED, R_GEN_FF_ERR_FUN }, + { 0x51F0, R_GEN_CF_ERR_FUN }, + { 0x51F3, R_GEN_BN_ERR_FUN }, + { 0x51F6, R_GEN_IE_ERR_FUN }, + { 0x51F9, R_GEN_EF_ERR_FUN }, + { 0x51FC, R_GEN_FL_ERR_FUN }, + { 0x5201, R_LOF_FUN }, + { 0x5203, R_LOC_FUN }, + { 0x5205, R_LFILES_FUN }, + { 0x5207, R_DSKO_FUN }, + { 0x5209, R_DSKI_FUN }, + { 0x520B, R_DSKF_FUN }, + { 0x520F, R_FORMAT_FUN }, + { 0x528D, R_DEV_NAME_TBL }, + { 0x52AB, R_DCB_VCTR_TBL }, + { 0x52DC, R_TELCOM_ENTRY }, + { 0x52F5, R_TELCOM_RE_ENTRY }, + { 0x5321, R_TELCOM_INST_VCTR_TBL }, + { 0x5334, R_TELCOM_LABEL_TXT }, + { 0x534D, R_TELCOM_STAT_FUN }, + { 0x5353, R_PRINT_TELCOM_STAT }, +/* { 0x51ED, R_SET_TELCOM_STAT }, + { 0x522F, R_TELCOM_CALL_FUN }, + { 0x524D, R_TELCOM_FIND_FUN }, + { 0x52B4, R_GO_OFFHOOK }, + { 0x52BB, R_DISCONNECT_PHONE }, + { 0x52D0, R_CONNECT_PHONE }, + { 0x52E4, R_GO_OFFHOOK_WAIT }, + { 0x5310, R_TELCOM_PAUSE }, + { 0x532D, R_EXEC_LOGON_SEQ }, + { 0x5359, R_DIALING_FUN }, + { 0x539E, R_AUTO_LOGIN_SEQ }, + { 0x540A, R_DIAL_DIGIT }, +*/ { 0x5388, R_TELCOM_TERM_FUN }, + { 0x5434, R_TELCOM_DISPATCH }, + { 0x5445, R_TERM_FKEY_VCTR_TBL }, + { 0x5459, R_TELCOM_PREV_FUN }, + { 0x5474, R_TELCOM_FULL_FUN }, + { 0x5486, R_TELCOM_ECHO_FUN }, + { 0x54C5, R_TELCOM_UP_FUN }, + { 0x5550, R_TELCOM_DOWN_FUN }, + { 0x55F0, R_TELCOM_BYE_FUN }, + { 0x563F, R_PRINT_STRING }, + { 0x5645, R_MENU_ENTRY }, +/* { 0x57F8, R_DISP_DIR }, + { 0x5837, R_MENU_CTRL_U_HANDLER }, + { 0x585A, R_MENU_CMD_LOOP }, + { 0x588E, R_MENU_BKSP_HANDLER }, +*/ { 0x5822, R_MENU_ENTER_HANDLER }, + { 0x5888, R_EXEC_ROM_FILE }, + { 0x5D08, R_DISP_DIR_TYPE_C }, + { 0x5D3F, R_CONV_FILENAME }, + { 0x5D67, R_NEXT_DIR_ENTRY }, + { 0x5D83, R_CLS_PRINT_TIME_DAY }, + { 0x5D86, R_PRINT_TIME_DAY }, + { 0x5DA2, R_PRINT_STRING2 }, + { 0x5DAC, R_COPY_MEM_DE_M }, + { 0x5DCD, R_CMP_MEM_DE_M }, +// { 0x5A79, R_CLEAR_FKEY_TBL }, + { 0x5DDC, R_SET_FKEYS }, + { 0x5DFB, R_DISP_FKEYS }, + { 0x5E5B, R_GET_FILE_ADDR }, + { 0x5E61, R_DIR_DISP_ORDER_TBL }, + { 0x5F48, R_FIND_TEXT_IN_FILE }, + { 0x5F76, R_CHECK_FOR_CRLF }, + { 0x5FA0, R_GET_KEY_CONV_TOUPPER }, + { 0x5FA6, R_PRINT_TIME_LOOP }, + { 0x5FC4, R_TEXT_ENTRY }, + { 0x5FF7, R_TEXT_FKEY_TBL }, + { 0x6030, R_EDIT_STMT }, + { 0x612A, R_EDIT_DO_FILE_FUN }, + { 0x61B6, R_TEXT_EDIT_LOOP }, + { 0x61EF, R_TEXT_CTRL_VCTR_TBL }, + { 0x622F, R_TEXT_ESC_FUN }, + { 0x6258, R_TEXT_CTRL_I_FUN }, + { 0x628C, R_TEXT_CTRL_M_FUN }, + { 0x62AC, R_TEXT_CTRL_D_FUN }, + { 0x62B0, R_TEXT_CTRL_X_FUN }, + { 0x62D9, R_TEXT_CTRL_H_FUN }, + { 0x631F, R_TEXT_CTRL_S_FUN }, + { 0x6323, R_TEXT_CTRL_E_FUN }, + { 0x6348, R_TEXT_CTRL_F_FUN }, + { 0x635A, R_TEXT_CTRL_A_FUN }, + { 0x6390, R_TEXT_CTRL_T_FUN }, + { 0x63A5, R_TEXT_CTRL_B_FUN }, + { 0x63CB, R_TEXT_CTRL_R_FUN }, + { 0x63D9, R_TEXT_CTRL_Q_FUN }, + { 0x63DE, R_TEXT_CTRL_W_FUN }, + { 0x63EA, R_TEXT_CTRL_Z_FUN }, + { 0x6410, R_TEXT_CTRL_L_FUN }, + { 0x645D, R_TEXT_CTRL_C_FUN }, + { 0x65BF, R_TEXT_GET_NEXT_BYTE }, + { 0x6606, R_TEXT_CTRL_O_FUN }, + { 0x661A, R_TEXT_CTRL_U_FUN }, + { 0x6736, R_TEXT_CTRL_N_FUN }, + { 0x67A8, R_COPY_NULL_STRING }, + { 0x6BFE, R_INSERT_A_INTO_FILE }, + { 0x6C0A, R_INSERT_SPACES }, + { 0x6C3C, R_DELETE_CHARS }, + { 0x6C78, R_MOVE_BC_BYTES_INC }, + { 0x6C83, R_MOVE_BC_BYTES_DEC }, + { 0x6C8E, R_ROM_CAT_ENTRIES }, + { 0x6CD0, R_BASIC_ENTRY }, + { 0x6CF7, R_LOAD_BASIC_FKEYS }, + { 0x6D00, R_LOAD_BASIC_FKEYS }, + { 0x6D3A, R_RE_INIT_SYSTEM }, + { 0x6D44, R_WARM_RESET }, + { 0x6D92, R_SEND_A_TO_LPT }, + { 0x6DC2, R_CHECK_RS232_QUEUE }, + { 0x6DD3, R_READ_RS232_QUEUE }, + { 0x6E00, R_RST_6_5_FUN }, + { 0x6E84, R_INC_RS232_QUEUE_IN }, + { 0x6E97, R_SEND_XON }, + { 0x6EAA, R_DISABLE_XON_XOFF }, + { 0x6EBE, R_SEND_A_USING_XON }, + { 0x6EDC, R_SEND_C_TO_RS232 }, + { 0x6EF9, R_XON_XOFF_HANDLER }, + { 0x6F21, R_SET_RS232_BAUD_RATE }, + { 0x6F40, R_RS232_BAUD_TIMER_VALS }, + { 0x6F52, R_INIT_RS232_MDM }, + { 0x6FA8, R_UNINIT_RS232_MDM }, +// { 0x6EE5, R_CLICK_SND_PORT }, +// { 0x6EEF, R_CHECK_CD }, + { 0x6F8D, R_ENABLE_XON_XOFF }, + { 0x6F95, R_INIT_SER_BUF_PARAMS }, + { 0x6FD9, R_CAS_MOTOR_ON }, + { 0x7047, R_CAS_WRITE_HEADER }, + { 0x6FEB, R_CAS_WRITE_NO_CHKSUM }, + { 0x6FF8, R_CAS_WRITE_BIT }, + { 0x7059, R_CAS_READ_HEADER }, + { 0x70AF, R_CAS_READ_BIT }, +// { 0x7023, R_CAS_COUNT_BITS }, + { 0x708E, R_CAS_READ_NO_CHKSUM }, + { 0x70CD, R_KEYSCAN_MGT_FUN }, + { 0x70D8, R_KEY_DETECTION }, + { 0x713C, R_KEY_REPEAT_DET }, + { 0x7195, R_KEY_DECODE }, + { 0x7230, R_KEY_FIRST_IN_BUF }, + { 0x7253, R_KEY_ADD_TO_BUF }, + { 0x7266, R_ISR_EXIT_FUN }, +/* { 0x720A, R_UNSHIFTED_KEY }, + { 0x7222, R_ARROW_KEY }, + { 0x722C, R_CAPS_LOCK_KEY }, + { 0x7233, R_NUM_KEY }, +*/ { 0x7279, R_SCAN_KEYBOARD }, + { 0x72A0, R_ENABLE_INTERRUPTS }, + { 0x72A6, R_CHK_PENDING_KEYS }, + { 0x72B9, R_CHK_BREAK }, + { 0x72DF, R_CHK_SHIFT_BREAK }, +// { 0x72B1, R_SCAN_SPECIAL_KEYS }, + { 0x730D, R_GEN_TONE }, + { 0x7359, R_GET_CLK_CHIP_REGS }, + { 0x735A, R_PUT_CLK_CHIP_REGS }, + { 0x7382, R_READ_CLK_CHIP_BIT }, + { 0x73B3, R_SET_CLK_CHIP_MODE }, + { 0x7409, R_BLINK_CURSOR }, + { 0x744D, R_CHAR_PLOT_7 }, + { 0x74D0, R_PLOT_POINT }, + { 0x74D1, R_CLEAR_POINT }, + { 0x7526, R_LCD_BYTE_PLOT }, + { 0x75BC, R_ENABLE_LCD_DRIVER }, + { 0x75D1, R_WAIT_LCD_DRIVER }, + { 0x75DA, R_LCD_BIT_PATTERNS }, + { 0x76CC, R_LCD_BIT_PATTERNS }, + { 0x76E0, R_DELAY_FUN }, + { 0x76E5, R_SET_INTR_1DH }, + { 0x76EB, R_BEEP_FUN }, + { 0x76FF, R_CLICK_SOUND_PORT }, +// { 0x7682, R_CHK_XTRNL_CNTRLER }, +// { 0x768F, R_XTRNL_CNTRLER_DRIVER }, + { 0x78B7, R_LCD_CHAR_SHAPE_TBL1 }, + { 0x7A97, R_LCD_CHAR_SHAPE_TBL2 }, +/* { 0x7BF1, R_KEYBOARD_CONV_MATRIX }, +*/ { 0x7C94, R_BOOT_ROUTINE }, + { 0x7D83, R_COLD_BOOT }, + { 0x7E3E, R_DISP_MODEL }, + { 0x7E52, R_DISP_FREE_BYTES }, + { 0x7E66, R_INIT_RST_38H_TBL }, + { 0x7E81, R_CALC_FREE_RAM }, + { 0x7EA1, R_INIT_CLK_CHIP_REGS }, + { 0x7F98, R_MENU_TEXT_STRINGS }, + { 0x7FBE, R_RST_38H_DRIVER }, +/* { 0xF5F9, R_RST_5_5_VECTOR }, + { 0xF5FC, R_RST_6_5_VECTOR }, + { 0xF5FF, R_RST_7_5_VECTOR }, + { 0xF602, R_TRAP_VECTOR }, + { 0xF605, R_DETECT_OPTION_ROM }, +*/ { -1, -1 } +}; + +RomDescription_t gN8201_Desc = { + 0x31303238, /* Signature */ + 0x7F9C, /* Signature address */ + 1, /* StdRom */ + + gN8201_Tables, /* Known tables */ + gN8201_Vars, /* Known variables */ + gN8201_Funs, /* Known functions */ + + 0xF979, /* Address of unsaved BASIC prgm */ + 0xF87C, /* Address of next DO file */ + 0xFAE1, /* Start of DO file area */ + 0xFAE3, /* Start of CO file area */ + 0xFAE5, /* Start of Variable space */ + 0xFAE7, /* Start of Array data */ + 0xFAE9, /* Pointer to unused memory */ + 0xF384, /* Address where HIMEM is stored */ + 0xF462, /* End of RAM for file storage */ + 0xF9B0, /* Lowest RAM used by system */ + 0xF84F, /* Start of RAM directory */ + 0xF459, /* BASIC string buffer pointer */ + 0xF9CA, /* BASIC Size */ + + 24, /* Number of directory entries */ + 8 /* Index of first Dir entry */ +}; + diff --git a/src/periph.cpp b/src/periph.cpp index f9de457..4f6dde9 100644 --- a/src/periph.cpp +++ b/src/periph.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/periph.h b/src/periph.h index 24d7a3e..58a1175 100644 --- a/src/periph.h +++ b/src/periph.h @@ -103,4 +103,4 @@ class T100_ComMon : public Fl_Widget -#endif \ No newline at end of file +#endif diff --git a/src/roms.h b/src/roms.h index c476d0e..e5640b3 100644 --- a/src/roms.h +++ b/src/roms.h @@ -35,7 +35,7 @@ /* known subroutine calls and variable locations within the ROM */ typedef struct Std_ROM_Addresses { int addr; - char* desc; + int strnum; } Std_ROM_Addresses_t; /* Define structure for storing known table data stored withing the ROM */ @@ -45,6 +45,13 @@ typedef struct Std_ROM_Table { char type; } Std_ROM_Table_t; +/* Define structure for storing addresses and descriptions for */ +/* known subroutine calls and variable locations within the ROM */ +typedef struct Std_ROM_Strings { + int addr; + char* desc; +} Std_ROM_Strings_t; + /* Define a structure to contain all information regarding a ROM */ typedef struct RomDescription { unsigned long dwSignature; /* Unique 32bit value in ROM */ @@ -67,8 +74,10 @@ typedef struct RomDescription { unsigned short sLowRam; /* Lowest RAM used by system */ unsigned short sDirectory; /* Start of RAM directory */ unsigned short sBasicStrings; /* BASIC string buffer pointer */ + unsigned short sBasicSize; /* Size of all BASIC programs */ unsigned short sDirCount; /* Number of entries in Directory */ + unsigned short sFirstDirEntry; /* Index of first available enry */ } RomDescription_t; enum { @@ -76,6 +85,7 @@ enum { TABLE_TYPE_JUMP, TABLE_TYPE_CODE, TABLE_TYPE_MODIFIED_STRING, + TABLE_TYPE_MODIFIED_STRING2, TABLE_TYPE_2BYTE, TABLE_TYPE_3BYTE, TABLE_TYPE_CTRL_DELIM, @@ -84,4 +94,4 @@ enum { TABLE_TYPE_CATALOG }; -#endif \ No newline at end of file +#endif diff --git a/src/romstrings.c b/src/romstrings.c new file mode 100644 index 0000000..e82ac8b --- /dev/null +++ b/src/romstrings.c @@ -0,0 +1,875 @@ +/* m100rom.c */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "roms.h" +#include "romstrings.h" + +Std_ROM_Strings_t gDisStrings[] = { + { R_FUN_VCTR_TBL, "Function vector table for SGN to MID$" }, + { R_BASIC_TBL, "BASIC statement keyword table END to NEW" }, + { R_FUN_TBL_TAB, "Function keyword table TAB to <" }, + { R_FUN_TBL_SGN, "Function keyword table SGN to MID$" }, + { R_BASIC_VCTR_TBL, "BASIC statement vector table for END to NEW" }, + { R_MATH_VCTR_TBL, "Vector table for math operations" }, + { R_BASIC_ERR_TXT, "BASIC error message text" }, + { R_INIT_IMAGE, "Initialization image loaded to F5F0H" }, + { R_XROM_DET_IMAGE, "External ROM detect image loaded at F605H" }, + { R_BASIC_STRINGS, "BASIC message strings" }, + { R_CAS_FREQ_CNT, "Cassette frequency cycle count" }, + { R_TERM_FKEY_VCTR_TBL, "TERM Mode function key vector table" }, + { R_DIR_DISP_ORDER_TBL, "Directory file-type display order table" }, + { R_TEXT_FKEY_VCTR_TBL, "TEXT Function key table - empty" }, + { R_ROM_CAT_ENTRIES, "ROM programs catalog entries" }, + { R_INT_EXIT_FUN, "Interrupt exit routine (pop all regs & RET)" }, + { R_8155_PIO_PAT1, "8155 PIO chip bit patterns for Upper LCD drivers" }, + { R_8155_PIO_PAT2, "8155 PIO chip bit patterns for Lower LCD drivers" }, + { R_INIT_CLK_VALUES, "Initial clock chip register values" }, + { R_MENU_STRINGS, "MENU Text Strings" }, + { R_MODEL_NUM_STRING, "TRS-80 model number string" }, + { R_ACTIVE_SIGNATURE, "Active system signature -- Warm vs Cold boot" }, + { R_HIMEM, "HIMEM" }, + { R_RST_5_5_VCTR, "RST 5.5 RAM Vector" }, + { R_RST_6_5_VCTR, "RST 6.5 RAM Vector" }, + { R_RST_7_5_VCTR, "RST 7.5 RAM Vector" }, + { R_TRAP_VCTR, "RAM vector for TRAP interrupt" }, + { R_OPTION_ROM_FLAG, "Option ROM flag" }, + { R_DIAL_SPEED, "Dial speed (1=10pps, 2=20pps" }, + { R_FKEY_STAT_TBL, "Function key status table (1 = on)" }, + { R_NEW_CONSOLE_FLAG, "New Console device flag" }, + { R_CURSOR_ROW, "Cursor row (1-8)" }, + { R_CURSOR_COL, "Cursor column (1-40)" }, + { R_ACTIVE_ROW_CNT, "Active rows count (1-8)" }, + { R_ACTIVE_COL_CNT, "Active columns count (1-40)" }, + { R_LABEL_LINE_PROT, "Label line protect status" }, + { R_SCROLL_DISABLE, "Scroll disable flag" }, + { R_CURSOR_STAT, "Cursor status (0 = off)" }, + { R_CURSOR_ROW2, "Cursor row (1-8)" }, + { R_CURSOR_COL2, "Cursor column (1-40)" }, + { R_ESC_MODE_FLAG, "ESC mode flag for RST 20H" }, + { R_REV_VID_SWITCH, "Reverse video switch" }, + { R_LAST_PLOT_X, "X coord of last point plotted" }, + { R_LAST_PLOT_Y, "Y coord of last point plotted" }, + { R_PWR_OFF_STAT, "Power off exit condition switch" }, + { R_DUPLEX_SWITCH, "Full/Half duplex switch" }, + { R_RS232_LF_SWITCH, "RS232 auto linefeed switch" }, + { R_RS232_PARAM_TBL, "RS232 parameter setting table" }, + { R_ADDRESS_LAST_CALLED, "Address last called" }, + { R_OUT_STMT_HOOK, "OUT statement hook" }, + { R_INP_STMT_HOOK, "INP function hook" }, + { R_LAST_ERROR_CODE, "Last Error code" }, + { R_LPT_HEAD_POS, "Line printer head position" }, + { R_OUTPUT_DEVICE, "Output device for RST 20H (0=screen)" }, + { R_BASIC_STR_BUF_PTR, "BASIC string buffer pointer" }, + { R_CUR_BASIC_LINE_NUM, "Current executing line number" }, + { R_START_BASIC_PGM_PTR, "Start of BASIC program pointer" }, + { R_END_OF_STMT_MARKER, "End of statement marker" }, + { R_KEYBOARD_BUF, "Keyboard buffer" }, + { R_CURSOR_H_POS, "Horiz. position of cursor (0-39)" }, + { R_FKEY_DEF_BUF, "Function key definition area" }, + { R_BASIC_FKEY_DEF_BUF, "Function key definition area (BASIC)" }, + { R_FILE_RAM_END, "End of RAM for file storage" }, + { R_SEC_ONES, "Seconds (ones)" }, + { R_SEC_TENS, "Seconds (tens)" }, + { R_MIN_ONES, "Minutes (ones)" }, + { R_MIN_TENS, "Minutes (tens)" }, + { R_HR_ONES, "Hours (ones)" }, + { R_HR_TENS, "Hours (tens)" }, + { R_DATE_ONES, "Date (ones)" }, + { R_DATE_TENS, "Date (tens)" }, + { R_DAY_CODE, "Day code (0=Sun, 1=Mon, etc.)" }, + { R_MONTH, "Month (1-12)" }, + { R_YEAR_ONES, "Year (ones)" }, + { R_YEAR_TENS, "Year (tens)" }, + { R_SEC_ONES2, "Seconds (ones)" }, + { R_SEC_TENS2, "Seconds (tens)" }, + { R_MIN_ONES2, "Minutes (ones)" }, + { R_MIN_TENS2, "Minutes (tens)" }, + { R_HR_ONES2, "Hours (ones)" }, + { R_HR_TENS2, "Hours (tens)" }, + { R_DATE_ONES2, "Date (ones)" }, + { R_DATE_TENS2, "Date (tens)" }, + { R_DAY_CODE2, "Day code (0=Sun, 1=Mon, etc.)" }, + { R_ONTIME_TIME, "Time for ON TIME interrupt (SSHHMM)" }, + { R_ONCOM_FLAG, "On Com flag" }, + { R_ONCOM_ADDRESS, "On Com routine address" }, + { R_ONTIME_FLAG, "On Time flag" }, + { R_ONTIME_ADDRESS, "On Time routine address" }, + { R_FKEY_VCTR_TBL, "Function key vector table" }, + { R_DIR_RAM_START, "Start of RAM directory" }, + { R_UNSAVED_BASIC_PTR, "BASIC program not saved pointer" }, + { R_PASTE_RAM_START, "Start of Paste Buffer" }, + { R_LAST_CHAR_PRINTED, "Last char sent to printer" }, + { R_LABEL_ENABLE_FLAG, "Label line enable flag" }, + { R_PORT_A8H, "Contents of port A8H" }, + { R_IPL_FILENAME_START, "Start of IPL filename" }, + { R_BASIC_LIST_START, "Address where last BASIC list started" }, + { R_SP_SAVE_BUF, "SP save area for power up/down" }, + { R_LOWEST_RAM, "Lowest RAM address used by system" }, + { R_RST_38H_OFFSET, "Offset of last RST 38H call" }, + { R_LAST_PGRM_LEN, "Length of last program loaded/saved to tape" }, + { R_RST_38H_VCTR_TBL, "Start of RST 38H vector table" }, + { R_LCD_OUTPUT_HOOK, "LCD character output hook" }, + { R_LPT_OUTPUT_HOOK, "Printer character output hook" }, + { R_EOF_FUN_HOOK, "EOF function hook" }, + { R_TERM_F6_HOOK, "Term F6 hook" }, + { R_TERM_F7_HOOK, "Term F7 hook" }, + { R_WIDTH_STMT_HOOK, "WIDTH statement hook" }, + { R_CRT_OPEN_HOOK, "CRT open routine hook" }, + { R_CRT_OUTPUT_HOOK, "CRT output file routine hook" }, + { R_WAND_OPEN_HOOK, "WAND Open routine hook" }, + { R_WAND_CLOSE_HOOK, "WAND Close routine hook" }, + { R_WAND_GET_HOOK, "WAND Get routine hook" }, + { R_WAND_IO_HOOK, "WAND Special I/O routine hook" }, + { R_LOF_HOOK, "LOF function hook" }, + { R_LOC_HOOK, "LOC function hook" }, + { R_LFILES_HOOK, "LFILES statement hook" }, + { R_DSKI_HOOK, "DSKI$ routine hook" }, + { R_DSKO_HOOK, "DSKO$ routine hook" }, + { R_VAR_CREATE_LOC_FLAG, "Variable Create/Locate switch" }, + { R_LAST_VAR_TYPE, "Type of last variable used" }, + { R_FILE_BUF_PTR, "File buffer area pointer" }, + { R_DATA_STMT_LINE_NUM, "Line number of current data statement" }, + { R_FOR_NEXT_ACTIVE_FLAG, "FOR/NEXT loop active flag" }, + { R_LAST_VAR_ASSIGNED_ADDR, "Address of last variable assigned" }, + { R_RUNNING_LINE_NUM_ADDR, "Most recent or currenly running line pointer" }, + { R_BASIC_SP_BUF, "SP used by BASIC to reinitialize the stack" }, + { R_LAST_ERR_LINE_NUM, "Line number of last error" }, + { R_LAST_ENTERED_LINE_NUM, "Most recent used or entered line number" }, + { R_ERR_PTR, "Pointer to occurance of error" }, + { R_ONERROR_ADDRESS, "Address of ON ERROR routine" }, + { R_BREAK_LINE_NUM, "Line where break, END, or STOP occurred" }, + { R_BREAK_ADDRESS, "Address where program stopped on last break, END, or STOP" }, + { R_DO_FILES_PTR, "Start of DO files pointer" }, + { R_CO_FILES_PTR, "Start of CO files pointer" }, + { R_VAR_PTR, "Start of variable data pointer" }, + { R_ARRAY_TBL_PTR, "Start of array table pointer" }, + { R_UNUSED_MEM_PTR, "Unused memory pointer" }, + { R_DATA_SEARCH_ADDR, "Address where DATA search will begin next" }, + { R_DEF_TBL, "DEF definition table" }, + { R_FP_TEMP1, "Floating Point Temp 1" }, + { R_FP_TEMP2, "Floating Point Temp 2" }, + { R_FP_TEMP3, "Floating Point Temp 3" }, + { R_FP_FAC1, "Start of FAC1 for single and double precision" }, + { R_INT_FAC1, "Start of FAC1 for integers" }, + { R_FP_FAC2, "Start of FAC2 for single and double precision" }, + { R_INT_FAC2, "Start of FAC2 for integers" }, + { R_MAXFILES, "Maxfiles" }, + { R_FILE_NUM_TBL_PTR, "File number description table pointer" }, + { R_BASIC_FILENAME, "Filename of current BASIC program" }, + { R_LAST_LOAD_FILENAME, "Filename of last program loaded from tape" }, + { R_ALT_LCD_CHAR_BUF, "Start of Alt LCD character buffer" }, + { R_MENU_TO_RAM_MAP, "Map of MENU entry positions to RAM directory positions" }, + { R_MENU_OR_CMD_FLAG, "Flag to indicate MENU entry location or command entry" }, + { R_CUR_MENU_DIR_LOC, "Current MENU directory location" }, + { R_MAX_MENU_DIR_LOC, "Maximum MENU directory location" }, + { R_LCD_CHAR_BUF, "Start of LCD character buffer" }, + { R_XON_XOFF_CTRL, "XON/XOFF protocol control" }, + { R_XON_XOFF_ENABLE, "XON/XOFF enable flag" }, + { R_RS232_INIT_STAT, "RS232 initialization status" }, + { R_SOUND_FLAG, "Sound flag" }, + { R_PORT_E8H, "Contents of port E8H" }, + { R_RS232_CHAR_BUF, "RS232 Character buffer" }, + { R_RS232_BUF_CNT, "RS232 buffer count" }, + { R_RS232_BUF_OUT, "RS232 buffer output position" }, + { R_RS232_BUF_IN, "RS232 buffer input pointer" }, + { R_CTRL_S_STAT, "Control-S status" }, + { R_UART_BAUD_TIMER_VAL, "UART baud rate timer value" }, + { R_RS232_PARITY_CTRL, "RS232 Parity Control byte" }, + { R_CAS_PULSE_CTRL, "Cassette port pulse control" }, + { R_SPEC_KEY_STAT, "Special key status storage" }, + { R_FKEY_STAT, "Function key status storage" }, + { R_KEY_SCAN_STORAGE1, "Keyboard scan column storage #1" }, + { R_KEY_SCAN_STORAGE2, "Keyboard scan column storage @2" }, + { R_SHIFT_KEY_STAT, "Shift key status storage" }, + { R_KEY_REPT_START, "Key repeat start delay counter" }, + { R_KEY_POSITION, "Key position storage" }, + { R_2ND_KEY_BUF_PTR, "Pointer to entry in 2nd Storage Buffer for key" }, + { R_KEY_BUF_CNT, "Keyboard buffer count" }, + { R_KEY_TYPEAHEAD_BUF, "Keyboard typeahead buffer" }, + { R_CURSOR_BIT_PAT_BUF, "Cursor bit pattern storage" }, + + /* ROM Functions */ + + { R_RESET_VECTOR, "Reset Vector" }, + { R_COMP_BYTE_M, "Compare next byte with M" }, + { R_GET_NONWHITE, "Get next non-white char from M" }, + { R_COMP_DE_HL, "Compare DE and HL" }, + { R_PRINT_SPACE, "Send a space to screen/printer" }, + { R_PRINT_CHAR, "Send character in A to screen/printer" }, + { R_PWR_DOWN_TRAP, "Power down TRAP" }, + { R_DET_LAST_VAR_TYPE, "Determine type of last var used" }, + { R_RST_5_5, "RST 5.5 -- Bar Code Reader" }, + { R_GET_FAC1_SIGN, "Get sign of FAC1" }, + { R_RST_6_5, "RST 6.5 -- RS232 character pending" }, + { R_RAM_VCTR_TBL_DRIVER, "RAM vector table driver" }, + { R_RST_7_5, "RST 7.5 -- Timer background task" }, + { R_BASIC_KEYWORD_TBL, "BASIC statement keyword table END to NEW" }, + { R_FUN_KEYWORD_TBL1, "Function keyword table TAB to <" }, + { R_FUN_KEYWORD_TBL2, "Function keyword table SGN to MID$" }, + { R_BASIC_VECTOR_TBL, "BASIC statement vector table for END to NEW" }, + { R_MATH_PRIORITY_TBL, "Math operator priority table" }, + { R_BASIC_ERR_MSG_TXT, "BASIC error message text" }, + { R_FUN_INIT_IMAGE, "Initialization image loaded to F5F0H" }, + { R_FUN_XROM_IMAGE, "External ROM detect image loaded at F605H" }, + { R_FUN_BASIC_STRINGS, "BASIC message strings" }, + { R_POP_FOR_NEXT, "Pop return address for NEXT or RETURN" }, + { R_INIT_AND_READY, "Initialize system and go to BASIC ready" }, + { R_GEN_SN_ERROR, "Generate Syntax error" }, + { R_GEN_d0_ERROR, "Generate /0 error" }, + { R_GEN_NF_ERROR, "Generate NF error" }, + { R_GEN_DD_ERROR, "Generate DD error" }, + { R_GEN_RW_ERROR, "Generate RW error" }, + { R_GEN_OV_ERROR, "Generate OV error" }, + { R_GEN_MO_ERROR, "Generate MO error" }, + { R_GEN_TM_ERROR, "Generate TM error" }, + { R_GEN_ERR_IN_E, "Generate error in E" }, + { R_RESTORE_JMP_BC, "Restore stack & runtime and jump to BC" }, + { R_PRINT_BASIC_ERR, "Print BASIC error message - XX error in XXX" }, + { R_POP_GO_BASIC_RDY, "Pop stack and vector to BASIC ready" }, + { R_GO_BASIC_RDY_OK, "Vector to BASIC ready - print Ok" }, + { R_GO_BASIC_RDY, "Silent vector to BASIC ready" }, + { R_PERFORM_M_GO_RDY, "Perform operation at M and return to ready" }, + { R_UPDATE_LINE_ADDR, "Update line addresses for current BASIC program" }, + { R_EVAL_LIST_ARGS, "Evaluate LIST statement arguments" }, + { R_FIND_LINE_IN_DE, "Find line number in DE" }, + { R_FIND_LINE_DE_AT_HL, "Find line number in DE starting at HL" }, + { R_TOKEN_COMPRESS, "Perform Token compression" }, + { R_FOR_STMT, "FOR statement" }, + { R_TO_STMT, "TO statement" }, + { R_STEP_STMT, "STEP statement" }, + { R_RUN_BASIC_PGRM, "Execute BASIC program" }, + { R_RUN_BASIC_AT_HL, "Start executing BASIC program at HL" }, + { R_EXEC_INST_IN_A, "Execute instruction in A, HL points to args" }, + { R_RST_10H_INC_HL, "RST 10H routine with pre-increment of HL" }, + { R_RST_10H, "RST 10H routine" }, + { R_DEF_STMT, "DEF statement" }, + { R_DEFDBL_STMT, "DEFDBL statement" }, + { R_DEFINT_STMT, "DEFINT statement" }, + { R_DEFSNG_STMT, "DEFSNG statement" }, + { R_DEFSTR_STMT, "DEFSTR statement" }, + { R_DECL_VAR_TYPE_E, "Declare variable at M to be type E" }, + { R_GEN_FC_ERROR, "Generate FC error" }, + { R_EVAL_LINE_NUM, "Evaluate line number text at M" }, + { R_ASCII_TO_BIN, "Convert ASCII number at M to binary" }, + { R_ASCII_TO_BIN_PREINC, "Convert ASCII number at M+1 to binary" }, + { R_RUN_STMT, "RUN statement" }, + { R_GOSUB_STMT, "GOSUB statement" }, + { R_GOTO_STMT, "GOTO statement" }, + { R_GEN_UL_ERROR, "Generate UL error" }, + { R_RETURN_STMT, "RETURN statement" }, + { R_DATA_STMT, "DATA statement" }, + { R_REM_STMT, "REM statement" }, + { R_LET_STMT, "LET statement" }, + { R_ON_STMT, "ON statement" }, + { R_ON_ERROR_STMT, "ON ERROR statement" }, + { R_ON_KEY_STMT, "ON KEY/TIME/COM/MDM GOSUB routine" }, + { R_ON_TIME_STMT, "ON TIME$ handler" }, + { R_RESUME_STMT, "RESUME statement" }, + { R_ERROR_STMT, "ERROR statement" }, + { R_IF_STMT, "IF statement" }, + { R_LPRINT_STMT, "LPRINT statement" }, + { R_PRINT_STMT, "PRINT statement" }, + { R_TAB_STMT, "TAB statement" }, + { R_LINE_STMT, "LINE statement" }, + { R_INPUT_NO_STMT, "INPUT # statement" }, + { R_INPUT_STMT, "INPUT statement" }, + { R_READ_STMT, "READ statement" }, + { R_EVAL_BASIC_INST, "Main BASIC evaluation routine" }, + { R_INT16_DIV, "Integer Divide FAC1=DE/HL" }, + { R_EVAL_FUN, "Evaluate function at M" }, + { R_ERR_FUN, "ERR function" }, + { R_ERL_FUN, "ERL function" }, + { R_VARPTR_FUN, "VARPTR function" }, + { R_VARPTR_BUF_FUN, "VARPTR(#buffer) function" }, + { R_VARPTR_VAR_FUN, "VARPTR(variable) function" }, + { R_EVAL_VAR, "Evaluate variable" }, + { R_CONV_M_TOUPPER, "Get char at M and convert to uppercase" }, + { R_CONV_A_TOUPPER, "Convert A to uppercase" }, + { R_ASCII_NUM_CONV, "ASCII num conversion - find ASCII or tokenized '+' or '-' in A" }, + { R_NOT_FUN, "NOT function" }, + { R_RST_28H, "RST 28H routine" }, + { R_OR_FUN, "OR function" }, + { R_AND_FUN, "AND function" }, + { R_XOR_FUN, "XOR function" }, + { R_EQV_FUN, "EQV function" }, + { R_IMP_FUN, "IMP function" }, + { R_LPOS_FUN, "LPOS function" }, + { R_POS_FUN, "POS function" }, + { R_LD_FAC1_INT, "Load integer in A into FAC1" }, + { R_CHK_RUNNING_PGRM, "Check for running program" }, + { R_GEN_ID_ERROR, "Generate ID error" }, + { R_INP_FUN, "INP function" }, + { R_OUT_STMT, "OUT statement" }, + { R_EVAL_EXPR, "Evaluate expression at M" }, + { R_EVAL_EXPR_PREDEC, "Evaluate expression at M-1" }, + { R_LLIST_STMT, "LLIST statement" }, + { R_LIST_STMT, "LIST statement" }, + { R_BUF_TO_LCD, "Send buffer at M to screen" }, + { R_PEEK_FUN, "PEEK function" }, + { R_POKE_FUN, "POKE function" }, + { R_WAIT_KEY, "Wait for key from keyboard" }, + { R_TOGGLE_LABEL, "Toggle function key label line" }, + { R_CHK_KEY_QUEUE, "Check keyboard queue for pending characters" }, + { R_POWER_STMT, "POWER statement" }, + { R_LOW_PWR_TRAP, "Normal TRAP (low power) interrupt routine" }, + { R_POWER_DOWN, "Turn off computer" }, + { R_POWER_CONT_STMT, "POWER CONT statement" }, + { R_POWER_ON_STMT, "POWER ON statement" }, + { R_OUT_CH_TO_LPT, "Output character to printer" }, + { R_LOAD_CAS_HDR, "Start tape and load tape header" }, + { R_GEN_IO_ERROR, "Generate I/O error" }, + { R_DET_CAS_SYNC_HDR, "Turn cassette motor on and detect sync header" }, + { R_CAS_MOTOR_ON, "Turn cassette motor on" }, + { R_CAS_MOTOR_OFF, "Turn cassette motor off" }, + { R_CAS_READ_BYTE, "Read byte from tape & update checksum" }, + { R_CAS_WRITE_BYTE, "Write byte to tape & update checksum" }, + { R_LCD_DCB, "LCD Device control block" }, + { R_LCD_OPEN, "LCD and PRT file open routine" }, + { R_LCD_OUT, "Output to LCD file" }, + { R_POP_ALL_REGS, "Pop AF, BC, DE, HL from stack" }, + { R_CRT_DCB, "CRT device control block" }, + { R_RAM_DCB, "RAM device control block" }, + { R_RAM_OPEN, "Open RAM file" }, + { R_RAM_CLOSE, "Close RAM file" }, + { R_RAM_OUT, "Output to RAM file" }, + { R_RAM_IN, "Input from RAM file" }, + { R_RAM_IO, "Special RAM file I/O" }, + { R_CAS_DCB, "CAS device control block" }, + { R_CAS_OPEN, "Open CAS file" }, + { R_CAS_CLOSE, "Close CAS file" }, + { R_CAS_OUT, "Output to CAS file" }, + { R_CAS_IN, "Input from CAS file" }, + { R_LPT_DCB, "LPT device control block" }, + { R_LPT_OUT, "Output to LPT file" }, + { R_COM_DCB, "COM device control block" }, + { R_MDM_OPEN, "Open MDM file" }, + { R_COM_OPEN, "Open COM file" }, + { R_COM_CLOSE, "Close COM file" }, + { R_COM_OUT, "Output to COM/MDM file" }, + { R_COM_IN, "Input from COM/MDM file" }, + { R_COM_IO, "Special COM/MDM file I/O" }, + { R_MDM_DCB, "MDM Device control block" }, + { R_MDM_CLOSE, "Close MDM file" }, + { R_SET_RS232_PARAMS, "Set RS232 parameters from string at M" }, + { R_BCR_DCB, "Wand device control block" }, + { R_EOF_FUN, "EOF function" }, + { R_TIME_FUN, "TIME$ function" }, + { R_READ_TIME, "Read time and store it at M" }, + { R_DATE_FUN, "DATE$ function" }, + { R_DAY_FUN, "DAY function" }, + { R_READ_DAY, "Read day and store at M" }, + { R_UPDATE_CLK_VALUES, "Update in-memory (F923H) clock values" }, + { R_TIME_STMT, "TIME$ statement" }, + { R_UPDATE_CLK_CHIP, "Update clock chip from memory F923H" }, + { R_DATE_STMT, "DATE$ statement" }, + { R_DAY_STMT, "DAY$ statement" }, + { R_GET_TIME_STRING, "Get time string from command line" }, + { R_IPL_STMT, "IPL statement" }, + { R_ERASE_IPL_PRGM, "Erase current IPL program" }, + { R_COM_MDM_STMT, "COM and MDM statements" }, + { R_KEY_FUN, "KEY() statement" }, + { R_KEY_ON_OFF_STMT, "KEY STOP/ON/OFF statements" }, + { R_DET_TIME_ARG, "Determine argument (ON/OFF/STOP) for TIME$ statement" }, + { R_DET_DEVICE_ARG, "Determine device (KEY/TIME/COM/MDM) for ON GOSUB" }, + { R_ONTIME_STMT, "ON TIME$ statement" }, + { R_ONCOM_STMT, "ON COM handler" }, + { R_RST7_5_ISR, "RST 7.5 interrupt routine" }, + { R_KICK_PWR_OFF_WDT, "Renew automatic power-off counter" }, + { R_KEY_STMT, "KEY statement" }, + { R_KEY_LIST_STMT, "KEY LIST statement" }, + { R_SEND_CHARS_TO_LCD, "Send B characters from M to the screen" }, + { R_PSET_STMT, "PSET statement" }, + { R_PRESET_STMT, "PRESET statement" }, + { R_DRAW_FBOX, "Draw a filled box on LCD. Coords are on stack" }, + { R_DRAW_BOX, "Draw an unfilled box on LCD. Coords are on stack" }, + { R_TOKENIZE_XY, "Get (X,Y) coordinate from tokenized string at M" }, + { R_CSRLIN_FUN, "CSRLIN function" }, + { R_MAX_FUN, "MAX function" }, + { R_MAXRAM_FUN, "MAXRAM function" }, + { R_MAXFILES_FUN, "MAXFILES function" }, + { R_HIMEM_FUN, "HIMEM function" }, + { R_WIDTH_STMT, "WIDTH statement" }, + { R_SOUND_STMT, "SOUND statement" }, + { R_SOUND_OFF_STMT, "SOUND OFF statement" }, + { R_SOUND_ON_STMT, "SOUND ON statement" }, + { R_MOTOR_STMT, "MOTOR statement" }, + { R_MOTOR_ON_STMT, "MOTOR ON statement" }, + { R_MOTOR_OFF_STMT, "MOTOR OFF statement" }, + { R_CALL_STMT, "CALL statement" }, + { R_SCREEN_STMT, "SCREEN statement" }, + { R_LCOPY_STMT, "LCOPY statement" }, + { R_FILES_STMT, "FILES statement" }, + { R_DISPLAY_CAT, "Display Catalog" }, + { R_KILL_STMT, "KILL statement" }, + { R_KILL_TEXT_FILE, "Kill a text file" }, + { R_NAME_STMT, "NAME statement" }, + { R_NEW_STMT, "NEW statement" }, + { R_STRLEN, "Count length of string at M" }, + { R_GET_FIND_DO_FILE, "Get .DO filename and locate in RAM directory" }, + { R_OPEN_TEXT_FILE, "Open a text file at (FC93H)" }, + { R_CSAVE_STMT, "CSAVE statement" }, + { R_CAS_WRITE_BUF, "Save buffer at M to tape" }, + { R_SAVEM_STMT, "SAVEM statement" }, + { R_CSAVEM_STMT, "CSAVEM statement" }, + { R_CLOAD_STMT, "CLOAD statement" }, + { R_CAS_READ_REC, "Load record from tape and store at M" }, + { R_GEN_VERIFY_FAIL_ERR, "Generate Verify Failed error" }, + { R_LOADM_STMT, "LOADM and RUNM statement" }, + { R_CLOADM_STMT, "CLOADM statement" }, + { R_MOVE_B_BYTES, "Move B bytes from M to (DE)" }, + { R_EXEC_CO_FILE, "Launch .CO files from MENU" }, + { R_CAS_OPEN_OUT_BA, "Open CAS for output of BASIC files" }, + { R_CAS_OPEN_OUT_DO, "Open CAS for output of TEXT files" }, + { R_CAS_OPEN_OUT_CO, "Open CAS for output of CO files" }, + { R_CAS_OPEN_IN_BA, "Open CAS for input of BASIC files" }, + { R_CAS_OPEN_IN_DO, "Open CAS for input of TEXT files" }, + { R_CAS_OPEN_IN_CO, "Open CAS for input of CO files" }, + { R_STR_FUN, "STR$ function" }, + { R_PRINT_STRING, "Print buffer at M until NULL or '\"'" }, + { R_MOVE_L_BYTES, "Move L bytes from (BC) to (DE)" }, + { R_LEN_FUN, "LEN function" }, + { R_ASC_FUN, "ASC function" }, + { R_CHR_FUN, "CHR$ function" }, + { R_STRING_FUN, "STRING$ function" }, + { R_SPACE_FUN, "SPACE$ function" }, + { R_LEFT_FUN, "LEFT$ function" }, + { R_RIGHT_FUN, "RIGHT$ function" }, + { R_MID_FUN, "MID$ function" }, + { R_VAL_FUN, "VAL function" }, + { R_INSTR_FUN, "INSTR function" }, + { R_FRE_FUN, "FRE function" }, + { R_DBL_SUB, "Double precision subtract (FAC1=FAC1-FAC2)" }, + { R_DBL_ADD, "Double precision addition (FAC1=FAC1+FAC2)" }, + { R_BCD_ADD, "Add the BCD num in M to the one in (DE)" }, + { R_DBL_MULT, "Double precision multiply (FAC1=FAC1*FAC2)" }, + { R_DBL_DIV, "Double precision divide (FAC1=FAC1/FAC2)" }, + { R_MOVE_C_BYTES, "Move C bytes from M to (DE)" }, + { R_COS_FUN, "COS function" }, + { R_SIN_FUN, "SIN function" }, + { R_TAN_FUN, "TAN function" }, + { R_ATN_FUN, "ATN function" }, + { R_LOG_FUN, "LOG function" }, + { R_SQR_FUN, "SQR function" }, + { R_EXP_FUN, "EXP function" }, + { R_RND_FUN, "RND function" }, + { R_DBL_SQR, "Double precision Square (FAC1=SQR(FAC1))" }, + { R_MULT_M_FAC2, "Double precision math (FAC1=M * FAC2))" }, + { R_FAC2_EQ_FAC1, "Move FAC1 to FAC2" }, + { R_FAC2_EQ_FP, "Move floating point number M to FAC2" }, + { R_FAC1_EQ_FAC2, "Move FAC2 to FAC1" }, + { R_FAC1_EQ_FP, "Move floating point number M to FAC1" }, + { R_M_EQ_FAC1, "Move FAC1 to M" }, + { R_MULT_FAC1_SQR_FAC1, "Double precision math (FAC1=FAC1*SQR(FAC1))" }, + { R_SWAP_FAC1_FAC2, "Swap FAC1 and FAC2" }, + { R_SQR_FAC1_MULT_TBL, "Square FAC1 & do table based math" }, + { R_TBL_BASED_MATH, "Table based math (FAC1=(((FAC1*M)+(M+1))*(M+2)+(M+3)..." }, + { R_PUSH_FAC2, "Push FAC2 on stack" }, + { R_PUSH_FAC1, "Push FAC1 on stack" }, + { R_POP_FAC2, "Pop FAC2 from stack" }, + { R_POP_FAC1, "Pop FAC1 from stack" }, + { R_FP_NUMBERS, "Floating point numbers for math operations " }, + { R_FP_SHARED_NUMBERS, "Floating point num-shares 6 bytes from next number" }, + { R_EXP_MATH_TBL, "Count of Floating point numbers to follow for EXP" }, + { R_LOG_MATH_TBL, "Count of Floating point numbers to follow for LOG" }, + { R_SIN_MATH_TBL, "Count of Floating point numbers to follow for SIN" }, + { R_ATN_MATH_TBL, "Count of Floating point numbers to follow for ATN" }, + { R_RST_30H_FUN, "RST 30H routine" }, + { R_ABS_FUN, "ABS function" }, + { R_SGN_FUN, "SGN function" }, + { R_PUSH_SNGL_FAC1, "Push single precision FAC1 on stack" }, + { R_SNGL_FAC1_EQ_M, "Load single precision at M to FAC1" }, + { R_SNGL_FAC1_EQ_BCDE, "Load single precision in BCDE to FAC1" }, + { R_SNGL_BCDE_EQ_FAC1, "Load single precision FAC1 to BCDE" }, + { R_SNGL_BCDE_EQ_M, "Load single precision at M to BCDE" }, + { R_SNGL_DECB_EQ_M, "Reverse load single precision at M to DEBC" }, + { R_SNGL_M_EQ_FAC1, "Move single precision FAC1 to M" }, + { R_LOAD_FAC2_FROM_M, "Move M to FAC2 using precision at (FB65H)" }, + { R_MOVE_B_BYTES_INC, "Move B bytes from (DE) to M with increment" }, + { R_MOVE_B_BYTES_DEC, "Move B bytes from (DE) to M with decrement" }, + { R_SNGL_CMP_BCDE_FAC1, "Compare single precision in BCDE with FAC1" }, + { R_SNGL_CMP_BCDE_M, "Compare single precision in BCDE with M" }, + { R_SINT_CMP, "Compare signed integer in DE with that in HL" }, + { R_CMP_FAC1_FAC2, "Compare double precision FAC1 with FAC2" }, + { R_CINT_FUN, "CINT function" }, + { R_FAC1_EQ_SINT_HL, "Load signed integer in HL to FAC1" }, + { R_CSNG_FUN, "CSNG function" }, + { R_CONV_SINT_SNGL, "Convert signed integer in FAC1 to single precision" }, + { R_CONV_SINT_HL_SNGL, "Convert signed integer HL to single precision FAC1" }, + { R_CDBL_FUN, "CDBL function" }, + { R_FIX_FUN, "FIX function" }, + { R_INT_FUN, "INT function" }, + { R_SINT_SUB, "Signed integer subtract (FAC1=HL-DE)" }, + { R_SINT_ADD, "Signed integer addition (FAC1=HL+DE)" }, + { R_SINT_MULT, "Signed integer muliply (FAC1=HL*DE)" }, + { R_SINT_DIV, "Signed integer divide (FAC1=DE/HL)" }, + { R_SNGL_ADD_BCDE, "Single precision addition (FAC1=FAC1+BCDE)" }, + { R_SNGL_ADD_FAC2, "Single precision addition (FAC1=FAC1+FAC2)" }, + { R_SNGL_SUB, "Single precision subtract (FAC1=FAC1-BCDE)" }, + { R_SNGL_MULT_BCDE, "Single precision multiply (FAC1=FAC1*BCDE)" }, + { R_SNGL_MULT_FAC2, "Single precision multiply (FAC1=FAC2*FAC2)" }, + { R_SNGL_DIV, "Single precision divide (FAC1=BCDE/FAC1)" }, + { R_SNGL_LOAD, "Single precision load (FAC2=BCDE)" }, + { R_ASCII_TO_DBL, "Convert ASCII number at M to double precision in FAC1" }, + { R_ASCII_FND_e, "Found 'e' in ASCII number" }, + { R_ASCII_FND_E, "Found 'E' in ASCII number" }, + { R_ASCII_FND_DOT, "Found '.' in ASCII number" }, + { R_ASCII_FND_PERC, "Found '%' in ASCII number" }, + { R_ASCII_FND_LB, "Found '#' in ASCII number" }, + { R_ASCII_CONV_HELPER, "Deal with single & double precision ASCII conversions" }, + { R_ASCII_CONV_HELPER2, "Convert ASCII number that starts with a Digit" }, + { R_PRNT_BASIC_ERR_TERM, "Finish printing BASIC ERROR message \" in \" line #" }, + { R_PRINT_HL_ON_LCD, "Print binary number in HL at current position" }, + { R_PRINT_FAC1, "Convert binary number in FAC1 to ASCII at M" }, + { R_PRINT_FAC1_FORMAT, "Convert binary number in FAC1 to ASCII at M with format" }, + { R_FAC1_EQ_ZERO, "Initialize FAC1 with 0.0 if it has no value" }, + { R_SNGL_EXP, "Single precision exponential function" }, + { R_DBL_EXP, "Double precision exponential function" }, + { R_INT_EXP, "Integer exponential function" }, + { R_TIME_ON_STMT, "TIME$ ON statement" }, + { R_TRIG_INTR, "Trigger interrupt. HL points to interrupt table" }, + { R_CLEAR_INTR, "Clear interrupt. HL points to interrupt table" }, + { R_TIME_OFF_STMT, "TIME$ OFF statement" }, + { R_TIME_STOP_STMT, "TIME$ STOP statement" }, + { R_CLEAR_COM_INT_DEF, "Clear all COM, TIME, and KEY interrupt definitions" }, + { R_RESTORE_STMT, "RESTORE statement" }, + { R_STOP_STMT, "STOP statement" }, + { R_END_STMT, "END statement" }, + { R_CONT_STMT, "CONT sttement" }, + { R_ISALPHA_M, "Check if M is alpha character" }, + { R_ISALPHA_A, "Check if A is alpha character" }, + { R_CLEAR_STMT, "CLEAR statement" }, + { R_NEXT_STMT, "NEXT statement" }, + { R_SEND_CRLF, "Send CRLF to screen or printer" }, + { R_SEND_LF, "Send LF to screen or printer" }, + { R_BEEP_STMT, "BEEP statement" }, + { R_HOME_CURSOR, "Home cursor" }, + { R_CLS_STMT, "CLS statement" }, + { R_PROTECT_LABEL, "Protect line 8. An ESC T is printed" }, + { R_UNPROT_LABEL, "Unprotect line 8. An ESC U is printed" }, + { R_STOP_AUTO_SCROLL, "Stop automatic scrolling" }, + { R_RESUME_AUTO_SCROLL, "Resume automatic scrolling" }, + { R_TURN_CURSOR_ON, "Turn the cursor on" }, + { R_TURN_CURSOR_OFF, "Turn the cursor off" }, + { R_DEL_CUR_LINE, "Delete current line on screen" }, + { R_INSERT_LINE, "Insert line a current line" }, + { R_ERASE_TO_EOL, "Erase from cursor to end of line" }, + { R_SEND_ESC_X, "Send ESC X" }, + { R_INV_CHAR_ENABLE, "Start inverse character mode" }, + { R_INV_CHAR_DISABLE, "Cancel inverse character mode" }, + { R_END_ESC_SEQ, "End escape sequence" }, + { R_CURSOR_TO_LOW_LEFT, "Send cursor to lower left of CRT" }, + { R_SET_CURSOR_POS, "Set the current cursor position (H=Row,L=Col)" }, + { R_ERASE_FKEY_DISP, "Erase function key display" }, + { R_SET_DISP_FKEY, "Set and display function keys (M has key table)" }, + { R_DISP_FKEY_LINE, "Display function key line" }, + { R_PRINT_A_TO_LCD, "Print A to the screen" }, + { R_CHAR_PLOT_3, "Character plotting level 3. Check new device console flag & call level 4)" }, + { R_CHAR_PLOT_4, "Character plotting level 4. Turn off background task & call level 5" }, + { R_CHAR_PLOT_5, "Character plotting level 5. Handle ESC sequences & call level 6" }, + { R_LCD_OUT_DRIVER, "LCD output driver" }, + { R_RST_20H_LKUP_TBL, "RST 20H lookup table" }, + { R_ESC_Y, "ESC Y routine (Set cursor position)" }, + { R_LCD_OUT_ESC_FUN, "LCD output Escape routine" }, + { R_LCD_ESC_LKUP_TBL, "LCD Escape sequence lookup table" }, + { R_ESC_SEQ_DRIVER, "ESCape sequence driver" }, + { R_ESC_p_FUN, "ESC p routine (start inverse video)" }, + { R_ESC_q_FUN, "ESC q routine (cancel inverse video)" }, + { R_ESC_U_FUN, "ESC U routine (unprotect line 8)" }, + { R_ESC_T_FUN, "ESC T routine (protect line 8)" }, + { R_ESC_V_FUN, "ESC V routine (stop automatic scrolling)" }, + { R_ESC_W_FUN, "ESC W routine (resume automatic scrolling)" }, + { R_ESC_X_FUN, "ESC X routine" }, + { R_ESC_C_FUN, "ESC C routine (move cursor right)" }, + { R_ESC_D_FUN, "ESC D routine (move cursor left)" }, + { R_BKSPACE_FUN, "Backspace routine" }, + { R_ESC_A_FUN, "ESC A routine (move cursor up)" }, + { R_ESC_B_FUN, "ESC B routine (move cursor down)" }, + { R_TAB_FUN, "Tab routine" }, + { R_LF_FUN, "Linefeed routine" }, + { R_ESC_H_FUN, "Verticle tab and ESC H routine (home cursor)" }, + { R_CR_FUN, "CR routine" }, + { R_ESC_P_FUN, "ESC P routine (turn cursor on)" }, + { R_ESC_Q_FUN, "ESC Q routine (turn cursor off)" }, + { R_ESC_M_FUN, "ESC M routine" }, + { R_LCD_SCROLL, "Scroll LCD screen A times at line number in L" }, + { R_ESC_L_FUN, "ESC L routine (insert line)" }, + { R_GET_LCD_CHAR, "Get character at (H,L) from LCD RAM)" }, + { R_ESC_l_FUN, "ESC l routine (erase current line)" }, + { R_ESC_K_FUN, "ESC K routine (erase to EOL)" }, + { R_CLS_FUN, "Form Feed (0CH), CLS, ESC E, and ESC J routine" }, + { R_CHAR_PLOT_6, "Character plotting level 6. Save character in C to LCD RAM & call level 7" }, + { R_ESC_J_FUN, "ESC J routine" }, + { R_INP_DISP_LINE, "Input and display line and store" }, + { R_INP_DISP_LINE_NO_Q, "Input and display (no \"?\") line and store" }, + { R_INP_CTRL_C_HANDLER, "Input routine Control-C handler" }, + { R_INP_ENTER_HANDLER, "Input routine ENTER handler" }, + { R_INP_BKSP_HANDLER, "Input routine backspace, left arrow, CTRL-H handler" }, + { R_INP_CTRL_U_HANDLER, "Input routine CTRL-U & X handler" }, + { R_INP_TAB_HANDLER, "Input routine Tab handler" }, + { R_DIM_STMT, "DIM statement" }, + { R_FIND_VAR_ADDR, "Find address of variable at M" }, + { R_USING_FUN, "USING function" }, + { R_SEND_A_LCD_LPT, "Send A to screen or printer" }, + { R_PRINT_A_EXPAND, "Print A to printer, expanding tabs if necessary" }, + { R_SET_OUT_DEV_LCD, "Reinitialize output back to LCD" }, + { R_LCD_CHAR_OUT_FUN, "LCD character output routine" }, + { R_LCD_NEW_LINE, "Move LCD to blank line (send CRLF if needed)" }, + { R_INKEY_FUN, "INKEY$ function" }, + { R_GET_FILE_DESC, "Get file descriptor for file in A" }, + { R_OPEN_STMT, "OPEN statement" }, + { R_LCD_CLOSE_FUN, "LCD, CRT, and LPT file close routine" }, + { R_RUN_STMT_PARAM, "RUN statement (with parameters)" }, + { R_LOAD_STMT, "LOAD statement" }, + { R_MERGE_STMT, "MERGE statement" }, + { R_SAVE_STMT, "SAVE statement" }, + { R_CLOSE_STMT, "CLOSE statement" }, + { R_INPUT_FUN, "INPUT$ function" }, + { R_CLEAR_MEM, "Zero B bytes at M" }, + { R_LOAD_MEM, "Load B bytes at M with A" }, + { R_PRINT_LB_INIT_FUN, "PRINT # initialization routine" }, + { R_LINE_INPUT_STMT, "LINE INPUT # statement" }, + { R_GEN_NM_ERR_FUN, "Generate NM error" }, + { R_GEN_AO_ERR_FUN, "Generate AO error" }, + { R_GEN_DS_ERR_FUN, "Generate DS error" }, + { R_GEN_FF_ERR_FUN, "Generate FF error" }, + { R_GEN_CF_ERR_FUN, "Generate CF error" }, + { R_GEN_BN_ERR_FUN, "Generate BN error" }, + { R_GEN_IE_ERR_FUN, "Generate IE error" }, + { R_GEN_EF_ERR_FUN, "Generate EF error" }, + { R_GEN_FL_ERR_FUN, "Generate FL error" }, + { R_LOF_FUN, "LOF function" }, + { R_LOC_FUN, "LOC function" }, + { R_LFILES_FUN, "LFILES function" }, + { R_DSKO_FUN, "DSKO$ function" }, + { R_DSKI_FUN, "DSKI$ function" }, + { R_DEV_NAME_TBL, "Device name table" }, + { R_DCB_VCTR_TBL, "Device control block vector addresses table" }, + { R_TELCOM_ENTRY, "TELCOM Entry point" }, + { R_TELCOM_RE_ENTRY, "Re-entry point for TELCOM commands" }, + { R_TELCOM_INST_VCTR_TBL, "TELCOM instruction vector table" }, + { R_TELCOM_LABEL_TXT, "TELCOM label line text table" }, + { R_TELCOM_STAT_FUN, "TELCOM STAT instruction routine" }, + { R_PRINT_TELCOM_STAT, "Print current STAT settings" }, + { R_SET_TELCOM_STAT, "Set STAT and return to TELCOM ready" }, + { R_TELCOM_CALL_FUN, "TELCOM CALL instruction routine" }, + { R_TELCOM_FIND_FUN, "TELCOM FIND instruction routine" }, + { R_GO_OFFHOOK, "Go off-hook" }, + { R_DISCONNECT_PHONE, "Disconnect phone line and disable modem carrier" }, + { R_CONNECT_PHONE, "Connect phone line and enable modem carrier" }, + { R_GO_OFFHOOK_WAIT, "Go off-hook and wait for carrier" }, + { R_TELCOM_PAUSE, "Pause for about 2 seconds" }, + { R_EXEC_LOGON_SEQ, "Execute logon sequence at M" }, + { R_DIALING_FUN, "Dialing routine" }, + { R_AUTO_LOGIN_SEQ, "Auto logon sequence" }, + { R_DIAL_DIGIT, "Dial the digit in A & print on LCD" }, + { R_TELCOM_TERM_FUN, "TELCOM TERM instruction routine" }, + { R_TELCOM_DISPATCH, "TELCOM \"dispatcher\" routine" }, + { R_TELCOM_PREV_FUN, "TELCOM PREV function routine" }, + { R_TELCOM_FULL_FUN, "TELCOM FULL/HALF function routine" }, + { R_TELCOM_ECHO_FUN, "TELCOM ECHO function routine" }, + { R_TELCOM_UP_FUN, "TELCOM UP function routine" }, + { R_TELCOM_DOWN_FUN, "TELCOM DOWN function routine" }, + { R_TELCOM_BYE_FUN, "TELCOM BYE function routine" }, + { R_MENU_ENTRY, "MENU Program" }, + { R_DISP_DIR, "Display directory entries" }, + { R_MENU_CTRL_U_HANDLER, "Handle CTRL-U key from MENU command loop" }, + { R_MENU_CMD_LOOP, "MENU Program command loop" }, + { R_MENU_BKSP_HANDLER, "Handle Backspace key from MENU command loop" }, + { R_MENU_ENTER_HANDLER, "Handle ENTER key from MENU command loop" }, + { R_EXEC_ROM_FILE, "Launch ROM command file from MENU program" }, + { R_DISP_DIR_TYPE_C, "Display directory entries of type in register C" }, + { R_CONV_FILENAME, "Convert filename from space padded to '.ext' format" }, + { R_NEXT_DIR_ENTRY, "Position cursor for next directory entry" }, + { R_CLS_PRINT_TIME_DAY, "Print time, day and date on first line of screen" }, + { R_PRINT_TIME_DAY, "Print time,day,date on first line w/o CLS" }, + { R_PRINT_STRING2, "Print NULL terminated string at M" }, + { R_COPY_MEM_DE_M, "Copy A bytes from (DE) to M" }, + { R_CMP_MEM_DE_M, "Compare string at DE with that at M (max C bytes)" }, + { R_CLEAR_FKEY_TBL, "Clear function key definition table" }, + { R_SET_FKEYS, "Set new function key table" }, + { R_DISP_FKEYS, "Display function keys on 8th line" }, + { R_SEARCH_DIR, "Search directory for filename" }, + { R_GET_FILE_ADDR, "Get start address of file at M" }, + { R_ADDRSS_ENTRY, "ADDRSS Entry point" }, + { R_ADDRSS_ENTRY_W_FILE, "ADDRSS entry with (DE) pointing to filename" }, + { R_SCHEDL_ENTRY, "SCHEDL Entry point" }, + { R_SCHEDL_ENTRY_W_FILE, "SCHEDL entry with (DE) pointing to filename" }, + { R_ADDRSS_FIND_FUN, "FIND instruction for ADDRSS/SCHEDL" }, + { R_ADDRSS_LFND_FUN, "LFND instruction for ADDRSS/SCHEDL" }, + { R_FIND_TEXT_IN_FILE, "Find text at M in the file at (DE)" }, + { R_FIND_NEXT_LINE_IN_FILE, "Increment DE past next CRLF in text file at (DE)" }, + { R_CHECK_FOR_CRLF, "Check next byte(s) at (DE) for CRLF" }, + { R_ADDRSS_INST_VCTR_TBL, "ADDRSS/SCHEDL instruction vector table" }, + { R_GET_KEY_CONV_TOUPPER, "Wait for char from keyboard & convert to uppercase" }, + { R_SEND_CURSOR_HOME, "Home cursor" }, + { R_PRINT_TIME_LOOP, "Print time on top line until key pressed" }, + { R_TEXT_ENTRY, "TEXT Entry point" }, + { R_TEXT_FKEY_TBL, "TEXT Function key table - empty" }, + { R_EDIT_STMT, "EDIT statement" }, + { R_WAIT_FOR_SPACE_KEY, "Wait for a space to be entered on keyboard" }, + { R_EDIT_DO_FILE_FUN, "Edit .DO files" }, + { R_TEXT_EDIT_LOOP, "Main TEXT edit loop" }, + { R_TEXT_CTRL_VCTR_TBL, "TEXT control character vector table" }, + { R_TEXT_ESC_FUN, "TEXT ESCape routine" }, + { R_TEXT_CTRL_P_FUN, "TEXT control P routine" }, + { R_TEXT_CTRL_I_FUN, "TEXT control I routine" }, + { R_TEXT_CTRL_M_FUN, "TEXT control M routine" }, + { R_TEXT_CTRL_D_FUN, "TEXT right arrow and control D routine" }, + { R_TEXT_CTRL_X_FUN, "TEXT down arrow and control X routine" }, + { R_TEXT_CTRL_H_FUN, "TEXT control H routine" }, + { R_TEXT_CTRL_S_FUN, "TEXT left arrow and control S routine" }, + { R_TEXT_CTRL_E_FUN, "TEXT up arrow and control E routine" }, + { R_TEXT_CTRL_F_FUN, "TEXT control F routine" }, + { R_TEXT_CTRL_A_FUN, "TEXT control A routine" }, + { R_TEXT_CTRL_T_FUN, "TEXT control T routine" }, + { R_TEXT_CTRL_B_FUN, "TEXT control B routine" }, + { R_TEXT_CTRL_R_FUN, "TEXT control R routine" }, + { R_TEXT_CTRL_Q_FUN, "TEXT control Q routine" }, + { R_TEXT_CTRL_W_FUN, "TEXT control W routine" }, + { R_TEXT_CTRL_Z_FUN, "TEXT control Z routine" }, + { R_TEXT_CTRL_L_FUN, "TEXT control L routine" }, + { R_TEXT_CTRL_C_FUN, "TEXT control C routine" }, + { R_TEXT_GET_NEXT_BYTE, "Get next byte for TEXT Program entry" }, + { R_TEXT_CTRL_O_FUN, "TEXT control O routine" }, + { R_TEXT_CTRL_U_FUN, "TEXT control U routine" }, + { R_TEXT_CTRL_N_FUN, "TEXT control N routine" }, + { R_COPY_NULL_STRING, "Copy NULL terminated string at M to (DE)" }, + { R_TEXT_CTRL_Y_FUN, "TEXT control Y routine" }, + { R_TEXT_CTRL_G_FUN, "TEXT control G routine" }, + { R_TEXT_CTRL_V_FUN, "TEXT control V routine" }, + { R_INSERT_A_INTO_FILE, "Insert A into text file at M" }, + { R_INSERT_SPACES, "Insert BC spaces at M" }, + { R_DELETE_CHARS, "Delete BC characters at M" }, + { R_MOVE_BC_BYTES_INC, "Move BC bytes from M to (DE) with increment" }, + { R_MOVE_BC_BYTES_DEC, "Move BC bytes from M to (DE) with decrement" }, + { R_BASIC_ENTRY, "BASIC Entry point" }, + { R_LOAD_BASIC_FKEYS, "Copy BASIC Function key table to key definition area" }, + { R_RE_INIT_SYSTEM, "Re-initialize system without destroying files" }, + { R_WARM_RESET, "Warm start reset entry" }, + { R_SEND_A_TO_LPT, "Send character in A to the printer" }, + { R_CHECK_RS232_QUEUE, "Check RS232 queue for pending characters" }, + { R_READ_RS232_QUEUE, "Get a character from RS232 receive queue" }, + { R_RST_6_5_FUN, "RST 6.5 routine (RS232 receive interrupt)" }, + { R_INC_RS232_QUEUE_IN, "Calculate address to save next RS232 character" }, + { R_SEND_XON, "Send XON (CTRL-Q) out RS232" }, + { R_DISABLE_XON_XOFF, "Turn off XON/XOFF protocol" }, + { R_SEND_A_USING_XON, "Send character in A to serial port using XON/XOFF" }, + { R_SEND_C_TO_RS232, "Send character in C to serial port" }, + { R_XON_XOFF_HANDLER, "Handle XON/XOFF protocol" }, + { R_SET_RS232_BAUD_RATE, "Set RS232 baud rate stored in H" }, + { R_RS232_BAUD_TIMER_VALS, "RS232 baud rate timer values" }, + { R_INIT_RS232_MDM, "Initialize RS232 or modem" }, + { R_UNINIT_RS232_MDM, "Deactivate RS232 or modem" }, + { R_CLICK_SND_PORT, "Click sound port if sound enabled" }, + { R_CHECK_CD, "Check for carrier detect" }, + { R_ENABLE_XON_XOFF, "Enable XON/OFF when CTRL-S / CTRL-Q sent" }, + { R_INIT_SER_BUF_PARAMS, "Initialize serial buffer parameters" }, + { R_CAS_WRITE_HEADER, "Write cassette header and sync byte" }, + { R_CAS_WRITE_NO_CHKSUM, "Write char in A to cassette w/o checksum" }, + { R_CAS_WRITE_NO_SYNC, "Write char in A to cassette w/o checksum or sync bit" }, + { R_CAS_WRITE_BIT, "Write bit 0 of A to cassette" }, + { R_CAS_READ_HEADER, "Read cassette header and sync byte" }, + { R_CAS_READ_BIT, "Read Cassette port data bit" }, + { R_CAS_COUNT_BITS, "Count and pack cassette input bits" }, + { R_CAS_READ_NO_CHKSUM, "Read character from cassette w/o checksum" }, + { R_CAS_REMOTE_FUN, "Cassette REMOTE routine - turn motor on or off" }, + { R_KEYSCAN_MGT_FUN, "Keyboard scanning management routine" }, + { R_KEY_DETECTION, "Key detection -- Determine which keys are pressed" }, + { R_KEY_REPEAT_DET, "Key repeat detection" }, + { R_GET_KEY_MATRIX, "Calculate key matrix position and save buffer pointer at FFA8H" }, + { R_INIT_KEY_RPT_CNT, "Key detected - initialize repeat counter and decode" }, + { R_KEY_DECODE, "Key decoding" }, + { R_KEY_FIRST_IN_BUF, "Keyboard buffer management - place key in new buffer" }, + { R_KEY_ADD_TO_BUF, "Keyboard buffer management - place subsequent key in buffer" }, + { R_ISR_EXIT_FUN, "Interrupt exit routine (pop all regs & RET)" }, + { R_UNSHIFTED_KEY, "Handle unshifted & non-CTRL key during key decoding" }, + { R_ARROW_KEY, "Handle Arrow keys during key decoding" }, + { R_CAPS_LOCK_KEY, "Handle CAPS LOCK key during key decoding" }, + { R_NUM_KEY, "Handle NUM key during key decoding" }, + { R_SCAN_KEYBOARD, "Scan keyboard for character (CTRL-BREAK ==> CTRL-C)" }, + { R_ENABLE_INTERRUPTS, "Enable interrupts as normal" }, + { R_CHK_PENDING_KEYS, "Check keyboard queue for pending characters" }, + { R_CHK_BREAK, "Check for break or wait (CTRL-S)" }, + { R_CHK_SHIFT_BREAK, "Check if SHIFT-BREAK is being pressed" }, + { R_SCAN_SPECIAL_KEYS, "Scan BREAK,CAPS,NUM,CODE,GRAPH,CTRL,SHIFT & set bits in A" }, + { R_GEN_TONE, "Produce a tone of DE freq and B duration" }, + { R_GET_CLK_CHIP_REGS, "Copy clock chip regs to M" }, + { R_PUT_CLK_CHIP_REGS, "Update clock chip regs from M" }, + { R_READ_CLK_CHIP_BIT, "Read next bit from Clock Chip" }, + { R_SET_CLK_CHIP_MODE, "Set clock chip mode" }, + { R_BLINK_CURSOR, "Blink the cursor" }, + { R_PLOT_POINT, "Plot (set) point (D,E) on the LCD" }, + { R_CHAR_PLOT_7, "Character plotting level 7. Plot character in C on LCD at (H,L)" }, + { R_CLEAR_POINT, "Clear (reset) point (D,E) on the LCD" }, + { R_LCD_BYTE_PLOT, "Byte Plot - Send bit pattern to LCD for character" }, + { R_ENABLE_LCD_DRIVER, "Enable LCD drivers after short delay" }, + { R_WAIT_LCD_DRIVER, "Wait for LCD driver to be available" }, + { R_LCD_BIT_PATTERNS, "8155 PIO chip bit patterns for LCD drivers" }, + { R_DELAY_FUN, "Delay routine - decrement C until zero" }, + { R_SET_INTR_1DH, "Set interrupt to 1DH" }, + { R_BEEP_FUN, "Beep routine" }, + { R_CLICK_SOUND_PORT, "Click sound port" }, + { R_CHK_XTRNL_CNTRLER, "Check for optional external controller" }, + { R_XTRNL_CNTRLER_DRIVER, "Optional external controller driver" }, + { R_LCD_CHAR_SHAPE_TBL1, "LCD char generator shape table (20H-7FH" }, + { R_LCD_CHAR_SHAPE_TBL2, "LCD char generator shape table (80H-FFH)" }, + { R_KEYBOARD_CONV_MATRIX, "Keyboard conversion matrix" }, + { R_BOOT_ROUTINE, "Boot routine" }, + { R_COLD_BOOT, "Cold boot routine" }, + { R_DISP_MODEL, "Display TRS-80 Model number & Free bytes on LCD" }, + { R_DISP_FREE_BYTES, "Display number of free bytes on LCD" }, + { R_INIT_RST_38H_TBL, "Initialize RST 38H RAM vector table" }, + { R_CALC_FREE_RAM, "Calculate physical RAM available" }, + { R_INIT_CLK_CHIP_REGS, "Initial clock chip register values" }, + { R_MENU_TEXT_STRINGS, "MENU Text Strings" }, + { R_RST_38H_DRIVER, "RST 38H RAM vector driver routine" }, + { R_RST_5_5_VECTOR, "RST 5.5 RAM Vector" }, + { R_RST_6_5_VECTOR, "RST 6.5 RAM Vector" }, + { R_RST_7_5_VECTOR, "RST 7.5 RAM Vector" }, + { R_TRAP_VECTOR, "RAM vector for TRAP interrupt" }, + { R_DETECT_OPTION_ROM, "Detect Option ROM" }, + { R_BASIC_RUNNING, "BASIC Program Running Flag" }, + { R_INIT_BASIC_VARS, "Initialize BASIC Variables for new execution" }, + { R_INIT_TEMP3, "Initialize FP_TEMP3 for new program" }, + { R_RENUM_STMT, "RENUM Statement" }, + { R_TEST_COM_TOKEN, "Test for COM token (ON COM Statement)" }, + { R_CMD_STMT, "CMD Statement" }, + { R_LOCATE_STMT, "LOCATE Statement" }, + { R_COLOR_STMT, "COLOR Statement" }, + { R_EXEC_STMT, "EXEC Statement" }, + { R_BSAVE_STMT, "BSAVE Statement" }, + { R_BLOAD_STMT, "BLOAD Statement" }, + { R_DSKF_FUN, "DSKF Function" }, + { R_FORMAT_FUN, "FORMAT Function" }, + { R_PORT_90H, "Current value of OUT port 90H" }, + { R_RST0_HOOK, "RST 0 Hook" }, + { R_EXEC_2ND_ROM, "Hook to execute Option ROM" }, + { R_TELCOM_FKEY_VCTR, "Main TELCOM Funciton Key Vector Table" }, + { -1, "" }, +}; diff --git a/src/romstrings.h b/src/romstrings.h new file mode 100644 index 0000000..83deee3 --- /dev/null +++ b/src/romstrings.h @@ -0,0 +1,882 @@ +/* romstrings.c */ + +/* $Id$ */ + +/* + * Copyright 2004 Stephen Hurd and Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +enum { + /* Variables */ + R_FUN_VCTR_TBL, + R_BASIC_TBL, + R_FUN_TBL_TAB, + R_FUN_TBL_SGN, + R_BASIC_VCTR_TBL, + R_MATH_VCTR_TBL, + R_BASIC_ERR_TXT, + R_INIT_IMAGE, + R_XROM_DET_IMAGE, + R_BASIC_STRINGS, + R_CAS_FREQ_CNT, + R_TERM_FKEY_VCTR_TBL, + R_DIR_DISP_ORDER_TBL, + R_TEXT_FKEY_VCTR_TBL, + R_ROM_CAT_ENTRIES, + R_INT_EXIT_FUN, + R_8155_PIO_PAT1, + R_8155_PIO_PAT2, + R_INIT_CLK_VALUES, + R_MENU_STRINGS, + R_MODEL_NUM_STRING, + R_ACTIVE_SIGNATURE, + R_HIMEM, + R_RST_5_5_VCTR, + R_RST_6_5_VCTR, + R_RST_7_5_VCTR, + R_TRAP_VCTR, + R_OPTION_ROM_FLAG, + R_DIAL_SPEED, + R_FKEY_STAT_TBL, + R_NEW_CONSOLE_FLAG, + R_CURSOR_ROW, + R_CURSOR_COL, + R_ACTIVE_ROW_CNT, + R_ACTIVE_COL_CNT, + R_LABEL_LINE_PROT, + R_SCROLL_DISABLE, + R_CURSOR_STAT, + R_CURSOR_ROW2, + R_CURSOR_COL2, + R_ESC_MODE_FLAG, + R_REV_VID_SWITCH, + R_LAST_PLOT_X, + R_LAST_PLOT_Y, + R_PWR_OFF_STAT, + R_DUPLEX_SWITCH, + R_RS232_LF_SWITCH, + R_RS232_PARAM_TBL, + R_ADDRESS_LAST_CALLED, + R_OUT_STMT_HOOK, + R_INP_STMT_HOOK, + R_LAST_ERROR_CODE, + R_LPT_HEAD_POS, + R_OUTPUT_DEVICE, + R_BASIC_STR_BUF_PTR, + R_CUR_BASIC_LINE_NUM, + R_START_BASIC_PGM_PTR, + R_END_OF_STMT_MARKER, + R_KEYBOARD_BUF, + R_CURSOR_H_POS, + R_FKEY_DEF_BUF, + R_BASIC_FKEY_DEF_BUF, + R_FILE_RAM_END, + R_SEC_ONES, + R_SEC_TENS, + R_MIN_ONES, + R_MIN_TENS, + R_HR_ONES, + R_HR_TENS, + R_DATE_ONES, + R_DATE_TENS, + R_DAY_CODE, + R_MONTH, + R_YEAR_ONES, + R_YEAR_TENS, + R_SEC_ONES2, + R_SEC_TENS2, + R_MIN_ONES2, + R_MIN_TENS2, + R_HR_ONES2, + R_HR_TENS2, + R_DATE_ONES2, + R_DATE_TENS2, + R_DAY_CODE2, + R_ONTIME_TIME, + R_ONCOM_FLAG, + R_ONCOM_ADDRESS, + R_ONTIME_FLAG, + R_ONTIME_ADDRESS, + R_FKEY_VCTR_TBL, + R_DIR_RAM_START, + R_UNSAVED_BASIC_PTR, + R_PASTE_RAM_START, + R_LAST_CHAR_PRINTED, + R_LABEL_ENABLE_FLAG, + R_PORT_A8H, + R_IPL_FILENAME_START, + R_BASIC_LIST_START, + R_SP_SAVE_BUF, + R_LOWEST_RAM, + R_RST_38H_OFFSET, + R_LAST_PGRM_LEN, + R_RST_38H_VCTR_TBL, + R_LCD_OUTPUT_HOOK, + R_LPT_OUTPUT_HOOK, + R_EOF_FUN_HOOK, + R_TERM_F6_HOOK, + R_TERM_F7_HOOK, + R_WIDTH_STMT_HOOK, + R_CRT_OPEN_HOOK, + R_CRT_OUTPUT_HOOK, + R_WAND_OPEN_HOOK, + R_WAND_CLOSE_HOOK, + R_WAND_GET_HOOK, + R_WAND_IO_HOOK, + R_LOF_HOOK, + R_LOC_HOOK, + R_LFILES_HOOK, + R_DSKI_HOOK, + R_DSKO_HOOK, + R_VAR_CREATE_LOC_FLAG, + R_LAST_VAR_TYPE, + R_FILE_BUF_PTR, + R_DATA_STMT_LINE_NUM, + R_FOR_NEXT_ACTIVE_FLAG, + R_LAST_VAR_ASSIGNED_ADDR, + R_RUNNING_LINE_NUM_ADDR, + R_BASIC_SP_BUF, + R_LAST_ERR_LINE_NUM, + R_LAST_ENTERED_LINE_NUM, + R_ERR_PTR, + R_ONERROR_ADDRESS, + R_BREAK_LINE_NUM, + R_BREAK_ADDRESS, + R_DO_FILES_PTR, + R_CO_FILES_PTR, + R_VAR_PTR, + R_ARRAY_TBL_PTR, + R_UNUSED_MEM_PTR, + R_DATA_SEARCH_ADDR, + R_DEF_TBL, + R_FP_TEMP1, + R_FP_TEMP2, + R_FP_TEMP3, + R_FP_FAC1, + R_INT_FAC1, + R_FP_FAC2, + R_INT_FAC2, + R_MAXFILES, + R_FILE_NUM_TBL_PTR, + R_BASIC_FILENAME, + R_LAST_LOAD_FILENAME, + R_ALT_LCD_CHAR_BUF, + R_MENU_TO_RAM_MAP, + R_MENU_OR_CMD_FLAG, + R_CUR_MENU_DIR_LOC, + R_MAX_MENU_DIR_LOC, + R_LCD_CHAR_BUF, + R_XON_XOFF_CTRL, + R_XON_XOFF_ENABLE, + R_RS232_INIT_STAT, + R_SOUND_FLAG, + R_PORT_E8H, + R_RS232_CHAR_BUF, + R_RS232_BUF_CNT, + R_RS232_BUF_OUT, + R_RS232_BUF_IN, + R_CTRL_S_STAT, + R_UART_BAUD_TIMER_VAL, + R_RS232_PARITY_CTRL, + R_CAS_PULSE_CTRL, + R_SPEC_KEY_STAT, + R_FKEY_STAT, + R_KEY_SCAN_STORAGE1, + R_KEY_SCAN_STORAGE2, + R_SHIFT_KEY_STAT, + R_KEY_REPT_START, + R_KEY_POSITION, + R_2ND_KEY_BUF_PTR, + R_KEY_BUF_CNT, + R_KEY_TYPEAHEAD_BUF, + R_CURSOR_BIT_PAT_BUF, + + /* ROM Functions */ + + R_RESET_VECTOR, + R_COMP_BYTE_M, + R_GET_NONWHITE, + R_COMP_DE_HL, + R_PRINT_SPACE, + R_PRINT_CHAR, + R_PWR_DOWN_TRAP, + R_DET_LAST_VAR_TYPE, + R_RST_5_5, + R_GET_FAC1_SIGN, + R_RST_6_5, + R_RAM_VCTR_TBL_DRIVER, + R_RST_7_5, + R_BASIC_KEYWORD_TBL, + R_FUN_KEYWORD_TBL1, + R_FUN_KEYWORD_TBL2, + R_BASIC_VECTOR_TBL, + R_MATH_PRIORITY_TBL, + R_BASIC_ERR_MSG_TXT, + R_FUN_INIT_IMAGE, + R_FUN_XROM_IMAGE, + R_FUN_BASIC_STRINGS, + R_POP_FOR_NEXT, + R_INIT_AND_READY, + R_GEN_SN_ERROR, + R_GEN_d0_ERROR, + R_GEN_NF_ERROR, + R_GEN_DD_ERROR, + R_GEN_RW_ERROR, + R_GEN_OV_ERROR, + R_GEN_MO_ERROR, + R_GEN_TM_ERROR, + R_GEN_ERR_IN_E, + R_RESTORE_JMP_BC, + R_PRINT_BASIC_ERR, + R_POP_GO_BASIC_RDY, + R_GO_BASIC_RDY_OK, + R_GO_BASIC_RDY, + R_PERFORM_M_GO_RDY, + R_UPDATE_LINE_ADDR, + R_EVAL_LIST_ARGS, + R_FIND_LINE_IN_DE, + R_FIND_LINE_DE_AT_HL, + R_TOKEN_COMPRESS, + R_FOR_STMT, + R_TO_STMT, + R_STEP_STMT, + R_RUN_BASIC_PGRM, + R_RUN_BASIC_AT_HL, + R_EXEC_INST_IN_A, + R_RST_10H_INC_HL, + R_RST_10H, + R_DEF_STMT, + R_DEFDBL_STMT, + R_DEFINT_STMT, + R_DEFSNG_STMT, + R_DEFSTR_STMT, + R_DECL_VAR_TYPE_E, + R_GEN_FC_ERROR, + R_EVAL_LINE_NUM, + R_ASCII_TO_BIN, + R_ASCII_TO_BIN_PREINC, + R_RUN_STMT, + R_GOSUB_STMT, + R_GOTO_STMT, + R_GEN_UL_ERROR, + R_RETURN_STMT, + R_DATA_STMT, + R_REM_STMT, + R_LET_STMT, + R_ON_STMT, + R_ON_ERROR_STMT, + R_ON_KEY_STMT, + R_ON_TIME_STMT, + R_RESUME_STMT, + R_ERROR_STMT, + R_IF_STMT, + R_LPRINT_STMT, + R_PRINT_STMT, + R_TAB_STMT, + R_LINE_STMT, + R_INPUT_NO_STMT, + R_INPUT_STMT, + R_READ_STMT, + R_EVAL_BASIC_INST, + R_INT16_DIV, + R_EVAL_FUN, + R_ERR_FUN, + R_ERL_FUN, + R_VARPTR_FUN, + R_VARPTR_BUF_FUN, + R_VARPTR_VAR_FUN, + R_EVAL_VAR, + R_CONV_M_TOUPPER, + R_CONV_A_TOUPPER, + R_ASCII_NUM_CONV, + R_NOT_FUN, + R_RST_28H, + R_OR_FUN, + R_AND_FUN, + R_XOR_FUN, + R_EQV_FUN, + R_IMP_FUN, + R_LPOS_FUN, + R_POS_FUN, + R_LD_FAC1_INT, + R_CHK_RUNNING_PGRM, + R_GEN_ID_ERROR, + R_INP_FUN, + R_OUT_STMT, + R_EVAL_EXPR, + R_EVAL_EXPR_PREDEC, + R_LLIST_STMT, + R_LIST_STMT, + R_BUF_TO_LCD, + R_PEEK_FUN, + R_POKE_FUN, + R_WAIT_KEY, + R_TOGGLE_LABEL, + R_CHK_KEY_QUEUE, + R_POWER_STMT, + R_LOW_PWR_TRAP, + R_POWER_DOWN, + R_POWER_CONT_STMT, + R_POWER_ON_STMT, + R_OUT_CH_TO_LPT, + R_LOAD_CAS_HDR, + R_GEN_IO_ERROR, + R_DET_CAS_SYNC_HDR, + R_CAS_MOTOR_ON, + R_CAS_MOTOR_OFF, + R_CAS_READ_BYTE, + R_CAS_WRITE_BYTE, + R_LCD_DCB, + R_LCD_OPEN, + R_LCD_OUT, + R_POP_ALL_REGS, + R_CRT_DCB, + R_RAM_DCB, + R_RAM_OPEN, + R_RAM_CLOSE, + R_RAM_OUT, + R_RAM_IN, + R_RAM_IO, + R_CAS_DCB, + R_CAS_OPEN, + R_CAS_CLOSE, + R_CAS_OUT, + R_CAS_IN, + R_LPT_DCB, + R_LPT_OUT, + R_COM_DCB, + R_MDM_OPEN, + R_COM_OPEN, + R_COM_CLOSE, + R_COM_OUT, + R_COM_IN, + R_COM_IO, + R_MDM_DCB, + R_MDM_CLOSE, + R_SET_RS232_PARAMS, + R_BCR_DCB, + R_EOF_FUN, + R_TIME_FUN, + R_READ_TIME, + R_DATE_FUN, + R_DAY_FUN, + R_READ_DAY, + R_UPDATE_CLK_VALUES, + R_TIME_STMT, + R_UPDATE_CLK_CHIP, + R_DATE_STMT, + R_DAY_STMT, + R_GET_TIME_STRING, + R_IPL_STMT, + R_ERASE_IPL_PRGM, + R_COM_MDM_STMT, + R_KEY_FUN, + R_KEY_ON_OFF_STMT, + R_DET_TIME_ARG, + R_DET_DEVICE_ARG, + R_ONTIME_STMT, + R_ONCOM_STMT, + R_RST7_5_ISR, + R_KICK_PWR_OFF_WDT, + R_KEY_STMT, + R_KEY_LIST_STMT, + R_SEND_CHARS_TO_LCD, + R_PSET_STMT, + R_PRESET_STMT, + R_DRAW_FBOX, + R_DRAW_BOX, + R_TOKENIZE_XY, + R_CSRLIN_FUN, + R_MAX_FUN, + R_MAXRAM_FUN, + R_MAXFILES_FUN, + R_HIMEM_FUN, + R_WIDTH_STMT, + R_SOUND_STMT, + R_SOUND_OFF_STMT, + R_SOUND_ON_STMT, + R_MOTOR_STMT, + R_MOTOR_ON_STMT, + R_MOTOR_OFF_STMT, + R_CALL_STMT, + R_SCREEN_STMT, + R_LCOPY_STMT, + R_FILES_STMT, + R_DISPLAY_CAT, + R_KILL_STMT, + R_KILL_TEXT_FILE, + R_NAME_STMT, + R_NEW_STMT, + R_STRLEN, + R_GET_FIND_DO_FILE, + R_OPEN_TEXT_FILE, + R_CSAVE_STMT, + R_CAS_WRITE_BUF, + R_SAVEM_STMT, + R_CSAVEM_STMT, + R_CLOAD_STMT, + R_CAS_READ_REC, + R_GEN_VERIFY_FAIL_ERR, + R_LOADM_STMT, + R_CLOADM_STMT, + R_MOVE_B_BYTES, + R_EXEC_CO_FILE, + R_CAS_OPEN_OUT_BA, + R_CAS_OPEN_OUT_DO, + R_CAS_OPEN_OUT_CO, + R_CAS_OPEN_IN_BA, + R_CAS_OPEN_IN_DO, + R_CAS_OPEN_IN_CO, + R_STR_FUN, + R_PRINT_STRING, + R_MOVE_L_BYTES, + R_LEN_FUN, + R_ASC_FUN, + R_CHR_FUN, + R_STRING_FUN, + R_SPACE_FUN, + R_LEFT_FUN, + R_RIGHT_FUN, + R_MID_FUN, + R_VAL_FUN, + R_INSTR_FUN, + R_FRE_FUN, + R_DBL_SUB, + R_DBL_ADD, + R_BCD_ADD, + R_DBL_MULT, + R_DBL_DIV, + R_MOVE_C_BYTES, + R_COS_FUN, + R_SIN_FUN, + R_TAN_FUN, + R_ATN_FUN, + R_LOG_FUN, + R_SQR_FUN, + R_EXP_FUN, + R_RND_FUN, + R_DBL_SQR, + R_MULT_M_FAC2, + R_FAC2_EQ_FAC1, + R_FAC2_EQ_FP, + R_FAC1_EQ_FAC2, + R_FAC1_EQ_FP, + R_M_EQ_FAC1, + R_MULT_FAC1_SQR_FAC1, + R_SWAP_FAC1_FAC2, + R_SQR_FAC1_MULT_TBL, + R_TBL_BASED_MATH, + R_PUSH_FAC2, + R_PUSH_FAC1, + R_POP_FAC2, + R_POP_FAC1, + R_FP_NUMBERS, + R_FP_SHARED_NUMBERS, + R_EXP_MATH_TBL, + R_LOG_MATH_TBL, + R_SIN_MATH_TBL, + R_ATN_MATH_TBL, + R_RST_30H_FUN, + R_ABS_FUN, + R_SGN_FUN, + R_PUSH_SNGL_FAC1, + R_SNGL_FAC1_EQ_M, + R_SNGL_FAC1_EQ_BCDE, + R_SNGL_BCDE_EQ_FAC1, + R_SNGL_BCDE_EQ_M, + R_SNGL_DECB_EQ_M, + R_SNGL_M_EQ_FAC1, + R_LOAD_FAC2_FROM_M, + R_MOVE_B_BYTES_INC, + R_MOVE_B_BYTES_DEC, + R_SNGL_CMP_BCDE_FAC1, + R_SNGL_CMP_BCDE_M, + R_SINT_CMP, + R_CMP_FAC1_FAC2, + R_CINT_FUN, + R_FAC1_EQ_SINT_HL, + R_CSNG_FUN, + R_CONV_SINT_SNGL, + R_CONV_SINT_HL_SNGL, + R_CDBL_FUN, + R_FIX_FUN, + R_INT_FUN, + R_SINT_SUB, + R_SINT_ADD, + R_SINT_MULT, + R_SINT_DIV, + R_SNGL_ADD_BCDE, + R_SNGL_ADD_FAC2, + R_SNGL_SUB, + R_SNGL_MULT_BCDE, + R_SNGL_MULT_FAC2, + R_SNGL_DIV, + R_SNGL_LOAD, + R_ASCII_TO_DBL, + R_ASCII_FND_e, + R_ASCII_FND_E, + R_ASCII_FND_DOT, + R_ASCII_FND_PERC, + R_ASCII_FND_LB, + R_ASCII_CONV_HELPER, + R_ASCII_CONV_HELPER2, + R_PRNT_BASIC_ERR_TERM, + R_PRINT_HL_ON_LCD, + R_PRINT_FAC1, + R_PRINT_FAC1_FORMAT, + R_FAC1_EQ_ZERO, + R_SNGL_EXP, + R_DBL_EXP, + R_INT_EXP, + R_TIME_ON_STMT, + R_TRIG_INTR, + R_CLEAR_INTR, + R_TIME_OFF_STMT, + R_TIME_STOP_STMT, + R_CLEAR_COM_INT_DEF, + R_RESTORE_STMT, + R_STOP_STMT, + R_END_STMT, + R_CONT_STMT, + R_ISALPHA_M, + R_ISALPHA_A, + R_CLEAR_STMT, + R_NEXT_STMT, + R_SEND_CRLF, + R_SEND_LF, + R_BEEP_STMT, + R_HOME_CURSOR, + R_CLS_STMT, + R_PROTECT_LABEL, + R_UNPROT_LABEL, + R_STOP_AUTO_SCROLL, + R_RESUME_AUTO_SCROLL, + R_TURN_CURSOR_ON, + R_TURN_CURSOR_OFF, + R_DEL_CUR_LINE, + R_INSERT_LINE, + R_ERASE_TO_EOL, + R_SEND_ESC_X, + R_INV_CHAR_ENABLE, + R_INV_CHAR_DISABLE, + R_END_ESC_SEQ, + R_CURSOR_TO_LOW_LEFT, + R_SET_CURSOR_POS, + R_ERASE_FKEY_DISP, + R_SET_DISP_FKEY, + R_DISP_FKEY_LINE, + R_PRINT_A_TO_LCD, + R_CHAR_PLOT_3, + R_CHAR_PLOT_4, + R_CHAR_PLOT_5, + R_LCD_OUT_DRIVER, + R_RST_20H_LKUP_TBL, + R_ESC_Y, + R_LCD_OUT_ESC_FUN, + R_LCD_ESC_LKUP_TBL, + R_ESC_SEQ_DRIVER, + R_ESC_p_FUN, + R_ESC_q_FUN, + R_ESC_U_FUN, + R_ESC_T_FUN, + R_ESC_V_FUN, + R_ESC_W_FUN, + R_ESC_X_FUN, + R_ESC_C_FUN, + R_ESC_D_FUN, + R_BKSPACE_FUN, + R_ESC_A_FUN, + R_ESC_B_FUN, + R_TAB_FUN, + R_LF_FUN, + R_ESC_H_FUN, + R_CR_FUN, + R_ESC_P_FUN, + R_ESC_Q_FUN, + R_ESC_M_FUN, + R_LCD_SCROLL, + R_ESC_L_FUN, + R_GET_LCD_CHAR, + R_ESC_l_FUN, + R_ESC_K_FUN, + R_CLS_FUN, + R_CHAR_PLOT_6, + R_ESC_J_FUN, + R_INP_DISP_LINE, + R_INP_DISP_LINE_NO_Q, + R_INP_CTRL_C_HANDLER, + R_INP_ENTER_HANDLER, + R_INP_BKSP_HANDLER, + R_INP_CTRL_U_HANDLER, + R_INP_TAB_HANDLER, + R_DIM_STMT, + R_FIND_VAR_ADDR, + R_USING_FUN, + R_SEND_A_LCD_LPT, + R_PRINT_A_EXPAND, + R_SET_OUT_DEV_LCD, + R_LCD_CHAR_OUT_FUN, + R_LCD_NEW_LINE, + R_INKEY_FUN, + R_GET_FILE_DESC, + R_OPEN_STMT, + R_LCD_CLOSE_FUN, + R_RUN_STMT_PARAM, + R_LOAD_STMT, + R_MERGE_STMT, + R_SAVE_STMT, + R_CLOSE_STMT, + R_INPUT_FUN, + R_CLEAR_MEM, + R_LOAD_MEM, + R_PRINT_LB_INIT_FUN, + R_LINE_INPUT_STMT, + R_GEN_NM_ERR_FUN, + R_GEN_AO_ERR_FUN, + R_GEN_DS_ERR_FUN, + R_GEN_FF_ERR_FUN, + R_GEN_CF_ERR_FUN, + R_GEN_BN_ERR_FUN, + R_GEN_IE_ERR_FUN, + R_GEN_EF_ERR_FUN, + R_GEN_FL_ERR_FUN, + R_LOF_FUN, + R_LOC_FUN, + R_LFILES_FUN, + R_DSKO_FUN, + R_DSKI_FUN, + R_DEV_NAME_TBL, + R_DCB_VCTR_TBL, + R_TELCOM_ENTRY, + R_TELCOM_RE_ENTRY, + R_TELCOM_INST_VCTR_TBL, + R_TELCOM_LABEL_TXT, + R_TELCOM_STAT_FUN, + R_PRINT_TELCOM_STAT, + R_SET_TELCOM_STAT, + R_TELCOM_CALL_FUN, + R_TELCOM_FIND_FUN, + R_GO_OFFHOOK, + R_DISCONNECT_PHONE, + R_CONNECT_PHONE, + R_GO_OFFHOOK_WAIT, + R_TELCOM_PAUSE, + R_EXEC_LOGON_SEQ, + R_DIALING_FUN, + R_AUTO_LOGIN_SEQ, + R_DIAL_DIGIT, + R_TELCOM_TERM_FUN, + R_TELCOM_DISPATCH, + R_TELCOM_PREV_FUN, + R_TELCOM_FULL_FUN, + R_TELCOM_ECHO_FUN, + R_TELCOM_UP_FUN, + R_TELCOM_DOWN_FUN, + R_TELCOM_BYE_FUN, + R_MENU_ENTRY, + R_DISP_DIR, + R_MENU_CTRL_U_HANDLER, + R_MENU_CMD_LOOP, + R_MENU_BKSP_HANDLER, + R_MENU_ENTER_HANDLER, + R_EXEC_ROM_FILE, + R_DISP_DIR_TYPE_C, + R_CONV_FILENAME, + R_NEXT_DIR_ENTRY, + R_CLS_PRINT_TIME_DAY, + R_PRINT_TIME_DAY, + R_PRINT_STRING2, + R_COPY_MEM_DE_M, + R_CMP_MEM_DE_M, + R_CLEAR_FKEY_TBL, + R_SET_FKEYS, + R_DISP_FKEYS, + R_SEARCH_DIR, + R_GET_FILE_ADDR, + R_ADDRSS_ENTRY, + R_ADDRSS_ENTRY_W_FILE, + R_SCHEDL_ENTRY, + R_SCHEDL_ENTRY_W_FILE, + R_ADDRSS_FIND_FUN, + R_ADDRSS_LFND_FUN, + R_FIND_TEXT_IN_FILE, + R_FIND_NEXT_LINE_IN_FILE, + R_CHECK_FOR_CRLF, + R_ADDRSS_INST_VCTR_TBL, + R_GET_KEY_CONV_TOUPPER, + R_SEND_CURSOR_HOME, + R_PRINT_TIME_LOOP, + R_TEXT_ENTRY, + R_TEXT_FKEY_TBL, + R_EDIT_STMT, + R_WAIT_FOR_SPACE_KEY, + R_EDIT_DO_FILE_FUN, + R_TEXT_EDIT_LOOP, + R_TEXT_CTRL_VCTR_TBL, + R_TEXT_ESC_FUN, + R_TEXT_CTRL_P_FUN, + R_TEXT_CTRL_I_FUN, + R_TEXT_CTRL_M_FUN, + R_TEXT_CTRL_D_FUN, + R_TEXT_CTRL_X_FUN, + R_TEXT_CTRL_H_FUN, + R_TEXT_CTRL_S_FUN, + R_TEXT_CTRL_E_FUN, + R_TEXT_CTRL_F_FUN, + R_TEXT_CTRL_A_FUN, + R_TEXT_CTRL_T_FUN, + R_TEXT_CTRL_B_FUN, + R_TEXT_CTRL_R_FUN, + R_TEXT_CTRL_Q_FUN, + R_TEXT_CTRL_W_FUN, + R_TEXT_CTRL_Z_FUN, + R_TEXT_CTRL_L_FUN, + R_TEXT_CTRL_C_FUN, + R_TEXT_GET_NEXT_BYTE, + R_TEXT_CTRL_O_FUN, + R_TEXT_CTRL_U_FUN, + R_TEXT_CTRL_N_FUN, + R_COPY_NULL_STRING, + R_TEXT_CTRL_Y_FUN, + R_TEXT_CTRL_G_FUN, + R_TEXT_CTRL_V_FUN, + R_INSERT_A_INTO_FILE, + R_INSERT_SPACES, + R_DELETE_CHARS, + R_MOVE_BC_BYTES_INC, + R_MOVE_BC_BYTES_DEC, + R_BASIC_ENTRY, + R_LOAD_BASIC_FKEYS, + R_RE_INIT_SYSTEM, + R_WARM_RESET, + R_SEND_A_TO_LPT, + R_CHECK_RS232_QUEUE, + R_READ_RS232_QUEUE, + R_RST_6_5_FUN, + R_INC_RS232_QUEUE_IN, + R_SEND_XON, + R_DISABLE_XON_XOFF, + R_SEND_A_USING_XON, + R_SEND_C_TO_RS232, + R_XON_XOFF_HANDLER, + R_SET_RS232_BAUD_RATE, + R_RS232_BAUD_TIMER_VALS, + R_INIT_RS232_MDM, + R_UNINIT_RS232_MDM, + R_CLICK_SND_PORT, + R_CHECK_CD, + R_ENABLE_XON_XOFF, + R_INIT_SER_BUF_PARAMS, + R_CAS_WRITE_HEADER, + R_CAS_WRITE_NO_CHKSUM, + R_CAS_WRITE_NO_SYNC, + R_CAS_WRITE_BIT, + R_CAS_READ_HEADER, + R_CAS_READ_BIT, + R_CAS_COUNT_BITS, + R_CAS_READ_NO_CHKSUM, + R_CAS_REMOTE_FUN, + R_KEYSCAN_MGT_FUN, + R_KEY_DETECTION, + R_KEY_REPEAT_DET, + R_GET_KEY_MATRIX, + R_INIT_KEY_RPT_CNT, + R_KEY_DECODE, + R_KEY_FIRST_IN_BUF, + R_KEY_ADD_TO_BUF, + R_ISR_EXIT_FUN, + R_UNSHIFTED_KEY, + R_ARROW_KEY, + R_CAPS_LOCK_KEY, + R_NUM_KEY, + R_SCAN_KEYBOARD, + R_ENABLE_INTERRUPTS, + R_CHK_PENDING_KEYS, + R_CHK_BREAK, + R_CHK_SHIFT_BREAK, + R_SCAN_SPECIAL_KEYS, + R_GEN_TONE, + R_GET_CLK_CHIP_REGS, + R_PUT_CLK_CHIP_REGS, + R_READ_CLK_CHIP_BIT, + R_SET_CLK_CHIP_MODE, + R_BLINK_CURSOR, + R_PLOT_POINT, + R_CHAR_PLOT_7, + R_CLEAR_POINT, + R_LCD_BYTE_PLOT, + R_ENABLE_LCD_DRIVER, + R_WAIT_LCD_DRIVER, + R_LCD_BIT_PATTERNS, + R_DELAY_FUN, + R_SET_INTR_1DH, + R_BEEP_FUN, + R_CLICK_SOUND_PORT, + R_CHK_XTRNL_CNTRLER, + R_XTRNL_CNTRLER_DRIVER, + R_LCD_CHAR_SHAPE_TBL1, + R_LCD_CHAR_SHAPE_TBL2, + R_KEYBOARD_CONV_MATRIX, + R_BOOT_ROUTINE, + R_COLD_BOOT, + R_DISP_MODEL, + R_DISP_FREE_BYTES, + R_INIT_RST_38H_TBL, + R_CALC_FREE_RAM, + R_INIT_CLK_CHIP_REGS, + R_MENU_TEXT_STRINGS, + R_RST_38H_DRIVER, + R_RST_5_5_VECTOR, + R_RST_6_5_VECTOR, + R_RST_7_5_VECTOR, + R_TRAP_VECTOR, + R_DETECT_OPTION_ROM, + R_BASIC_RUNNING, + R_INIT_BASIC_VARS, + R_INIT_TEMP3, + R_RENUM_STMT, + R_TEST_COM_TOKEN, + R_CMD_STMT, + R_LOCATE_STMT, + R_COLOR_STMT, + R_EXEC_STMT, + R_BSAVE_STMT, + R_BLOAD_STMT, + R_DSKF_FUN, + R_FORMAT_FUN, + R_PORT_90H, + R_RST0_HOOK, + R_EXEC_2ND_ROM, + R_TELCOM_FKEY_VCTR +}; + +#ifdef __cplusplus +extern "C" { +#endif + +extern Std_ROM_Strings_t gDisStrings[]; + +#ifdef __cplusplus +} +#endif diff --git a/src/serial.c b/src/serial.c index 3ff0edc..dcad761 100644 --- a/src/serial.c +++ b/src/serial.c @@ -372,7 +372,6 @@ DWORD ReadProc(LPVOID lpv) BOOL fWaitingOnStat = FALSE; BOOL fThreadDone = FALSE; char buf[128]; - unsigned int c; ser_params_t *sp; @@ -406,8 +405,7 @@ DWORD ReadProc(LPVOID lpv) // read completed immediately if (dwRead) { - for (c = 0; c < dwRead; c++) - process_read_byte(sp, buf[c]); + process_read_byte(sp, buf[0]); } } } @@ -429,14 +427,18 @@ DWORD ReadProc(LPVOID lpv) break; } else + { // Check for a monitor window and report change if (sp->pMonCallback != NULL) sp->pMonCallback(SER_MON_COM_SIGNAL, 0); + ResetEvent(osStatus.hEvent); + } } // wait for pending operations to complete if ( fWaitingOnRead || fWaitingOnStat ) +// if ( fWaitingOnRead) { dwRes = WaitForMultipleObjects(3, hArray, FALSE, INFINITE); switch(dwRes) @@ -454,8 +456,8 @@ DWORD ReadProc(LPVOID lpv) // read completed successfully if (dwRead) { - for (c = 0; c < dwRead; c++) - process_read_byte(sp, buf[c]); + if (fWaitingOnRead) + process_read_byte(sp, buf[0]); } fWaitingOnRead = FALSE; } @@ -1101,7 +1103,7 @@ int ser_get_flags(unsigned char *flags) if (sp.open_flag == 0) { *flags = 0; - return SER_NO_ERROR; + return SER_PORT_NOT_OPEN; } #ifdef WIN32 @@ -1151,6 +1153,8 @@ int ser_get_flags(unsigned char *flags) #endif } + else if (setup.com_mode == SETUP_COM_NONE) + return SER_PORT_NOT_OPEN; return SER_NO_ERROR; } diff --git a/src/setup.cpp b/src/setup.cpp index 2274b57..90162b8 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -31,15 +31,18 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -48,10 +51,11 @@ #include "io.h" #include "serial.h" #include "setup.h" +#include "memory.h" +#include "memedit.h" extern Fl_Preferences virtualt_prefs; - typedef struct setup_ctrl_struct { Fl_Tabs* pTabs; @@ -94,10 +98,27 @@ typedef struct setup_ctrl_struct } setup_ctrl_t; +typedef struct memory_ctrl_struct +{ + Fl_Round_Button* pNone; + Fl_Round_Button* pReMem; + Fl_Round_Button* pRampac; + Fl_Round_Button* pReMem_Rampac; + Fl_Input* pReMemFile; + Fl_Input* pRampacFile; + Fl_Button* pReMemBrowse; + Fl_Button* pRampacBrowse; + Fl_Box* pReMemText; +} memory_ctrl_t; + + Fl_Window *gpsw; // Peripheral Setup Window +Fl_Window *gmsw; // Memory Setup Window setup_ctrl_t setup_ctrl; // Setup window controls +memory_ctrl_t mem_ctrl; // Memory setup window peripheral_setup_t setup; // Setup options +memory_setup_t mem_setup; // Memory setup options /* ============================================================================ @@ -253,6 +274,12 @@ void cb_setupwin (Fl_Widget* w, void*) delete gpsw; } +void cb_memorywin (Fl_Widget* w, void*) +{ + gmsw->hide(); + delete gmsw; +} + /* ============================================================================ Callback routines for the COM Tab @@ -432,7 +459,7 @@ void cb_PeripheralSetup (Fl_Widget* w, void*) setup_ctrl.pTabs->value(setup_ctrl.com.g); setup_ctrl.pTabs->end(); - + } // OK button @@ -446,3 +473,414 @@ void cb_PeripheralSetup (Fl_Widget* w, void*) gpsw->show(); } +/* +============================================================================ +Routines to load and save setup structure to the user preferences +============================================================================ +*/ +void save_memory_preferences(void) +{ + char str[16]; + char pref[64]; + + get_model_string(str, gModel); + + // Save COM emulation settings + strcpy(pref, str); + strcat(pref, "_MemMode"); + virtualt_prefs.set(pref, mem_setup.mem_mode); + + strcpy(pref, str); + strcat(pref, "_ReMemFile"); + virtualt_prefs.set(pref, mem_setup.remem_file); + + + strcpy(pref, str); + strcat(pref, "_RampacFile"); + virtualt_prefs.set(pref, mem_setup.rampac_file); +} + +void load_memory_preferences(void) +{ + char str[16]; + char pref[64]; + char path[256]; + + get_model_string(str, gModel); + + // Load mem emulation mode base on Model + strcpy(pref, str); + strcat(pref, "_MemMode"); + virtualt_prefs.get(pref, mem_setup.mem_mode,0); + + // Load ReMem filename base on Model + strcpy(pref, str); + strcat(pref, "_ReMemFile"); + get_emulation_path(path, gModel); + strcat(path, "remem.bin"); + virtualt_prefs.get(pref, mem_setup.remem_file, path, 256); + if (strlen(mem_setup.remem_file) == 0) + strcpy(mem_setup.remem_file, path); + + // Load Rampac filename base on Model + strcpy(pref, str); + strcat(pref, "_RampacFile"); + get_emulation_path(path, gModel); + strcat(path, "rampac.bin"); + virtualt_prefs.get(pref, mem_setup.rampac_file, path, 256); + if (strlen(mem_setup.rampac_file) == 0) + strcpy(mem_setup.rampac_file, path); +} + +/* +============================================================================ +Callback routines for the Memory options window +============================================================================ +*/ +void cb_memory_OK(Fl_Widget* w, void*) +{ + int old_mode; + + /* + =================================================== + First check if ReMem memory needs to be deallocated + =================================================== + */ + if ((mem_setup.mem_mode == SETUP_MEM_REMEM) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC)) + { + // Check if we are turning ReMem emulation off + if ((mem_ctrl.pReMem->value() != 1) && (mem_ctrl.pReMem_Rampac->value() != 1)) + { + save_remem_ram(); // Write ReMem memory to file + free_remem_mem(); // Deallocate ReMem memory + } + } + + /* + =================================================== + Next check if Rampac memory needs to be deallocated + =================================================== + */ + if ((mem_setup.mem_mode == SETUP_MEM_RAMPAC) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC)) + { + // Check if we are turning Host port emulation off + if (mem_ctrl.pRampac->value() != 1) + { + save_rampac_ram(); // Write Rampac memory to file + free_rampac_mem(); // Deallocate Rampac memory + } + } + + // Save old mem_mode so we know when to load data from file + old_mode = mem_setup.mem_mode; + + // =========================== + // Get memory options + // =========================== + if (mem_ctrl.pNone->value() == 1) + mem_setup.mem_mode = SETUP_MEM_BASE; + else if (mem_ctrl.pRampac->value() == 1) + mem_setup.mem_mode = SETUP_MEM_RAMPAC; + else if (mem_ctrl.pReMem->value() == 1) + mem_setup.mem_mode = SETUP_MEM_REMEM; + else if (mem_ctrl.pReMem_Rampac->value() == 1) + mem_setup.mem_mode = SETUP_MEM_REMEM_RAMPAC; + + // Allocate ReMem and / or Rampac memory if not already + init_mem(); + + // If we are in ReMem or ReMem_Rampac mode, check if ReMem filename changed + if ((mem_setup.mem_mode == SETUP_MEM_REMEM) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC)) + { + // Check if we are changing ReMem filename + if (strcmp(mem_ctrl.pReMemFile->value(), mem_setup.remem_file) != 0) + { + // Save memory to old file + save_remem_ram(); + + // Copy new filename to preferences + strcpy(mem_setup.remem_file, mem_ctrl.pReMemFile->value()); + + // Load ReMem data from new file + load_remem_ram(); + } + else if ((old_mode != SETUP_MEM_REMEM) && (old_mode != SETUP_MEM_REMEM_RAMPAC)) + { + // Load ReMem data from file + load_remem_ram(); + } + } + + // If we are in Rampac or ReMem_Rampac mode, check if Rampac filename changed + if ((mem_setup.mem_mode == SETUP_MEM_RAMPAC) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC)) + { + // Check if we are changing Rampac filename + if (strcmp(mem_ctrl.pRampacFile->value(), mem_setup.rampac_file) != 0) + { + // Save memory to old file + save_rampac_ram(); + + // Copy new filename to preferences + strcpy(mem_setup.rampac_file, mem_ctrl.pRampacFile->value()); + + // Load Rampac data from new file + load_rampac_ram(); + } + else if ((old_mode != SETUP_MEM_RAMPAC) && (old_mode != SETUP_MEM_REMEM_RAMPAC)) + { + // Load Rampac data from file + load_rampac_ram(); + } + } + + // Copy new ReMem filename and Rampac filename to preferences + strcpy(mem_setup.remem_file, mem_ctrl.pReMemFile->value()); + strcpy(mem_setup.rampac_file, mem_ctrl.pRampacFile->value()); + + // Save memory preferences to file + save_memory_preferences(); + + // Update Memory Editor + cb_MemoryEditorUpdate(); + + // Destroy the window + gmsw->hide(); + delete gmsw; +} + +void cb_remem_browse(Fl_Widget* w, void*) +{ + int count; + Fl_File_Chooser *fc; + const char *filename; + const char *filename_name; + int len; + char mstr[16]; + char mstr_upper[16]; + char path[256]; + int c; + + // Create chooser window to pick file + strcpy(path, mem_ctrl.pReMemFile->value()); + fc = new Fl_File_Chooser(path,"Binary Files (*.bin)",2,"Choose ReMem File"); + fc->preview(0); + fc->show(); + + // Show Chooser window + while (fc->visible()) + Fl::wait(); + + count = fc->count(); + if (count == 0) + { + delete fc; + return; + } + + // Get Filename + filename = fc->value(1); + if (filename == 0) + { + delete fc; + return; + } + len = strlen(filename); + + // Copy filename to edit field + filename_name = fl_filename_name(filename); + + get_model_string(mstr, gModel); + strcpy(mstr_upper, mstr); + for (c = strlen(mstr_upper)-1; c >= 0; c--) + mstr_upper[c] = toupper(mstr_upper[c]); + if (strstr(filename, mstr) || strstr(filename, mstr_upper)) + { + get_emulation_path(path, gModel); + strcat(path, filename_name); + mem_ctrl.pReMemFile->value(path); + } + else + mem_ctrl.pReMemFile->value(filename); + + delete fc; +} + +void cb_radio_base_memory (Fl_Widget* w, void*) +{ + mem_ctrl.pRampacFile->deactivate(); + mem_ctrl.pRampacBrowse->deactivate(); + mem_ctrl.pReMemFile->deactivate(); + mem_ctrl.pReMemBrowse->deactivate(); + mem_ctrl.pReMemText->hide(); +} + +void cb_radio_remem (Fl_Widget* w, void*) +{ + mem_ctrl.pReMemFile->activate(); + mem_ctrl.pReMemBrowse->activate(); + mem_ctrl.pRampacFile->deactivate(); + mem_ctrl.pRampacBrowse->deactivate(); + mem_ctrl.pReMemText->show(); +} + +void cb_radio_rampac (Fl_Widget* w, void*) +{ + mem_ctrl.pRampacFile->activate(); + mem_ctrl.pRampacBrowse->activate(); + mem_ctrl.pReMemFile->deactivate(); + mem_ctrl.pReMemBrowse->deactivate(); + mem_ctrl.pReMemText->hide(); +} + +void cb_radio_remem_and_rampac (Fl_Widget* w, void*) +{ + mem_ctrl.pReMemFile->activate(); + mem_ctrl.pReMemBrowse->activate(); + mem_ctrl.pRampacFile->activate(); + mem_ctrl.pRampacBrowse->activate(); + mem_ctrl.pReMemText->show(); +} + +void cb_memory_cancel (Fl_Widget* w, void*) +{ + gmsw->hide(); + delete gpsw; +} + +void cb_rampac_browse (Fl_Widget* w, void*) +{ + int count; + Fl_File_Chooser *fc; + const char *filename; + const char *filename_name; + int len; + char mstr[16]; + char mstr_upper[16]; + char path[256]; + int c; + + // Create chooser window to pick file + strcpy(path, mem_ctrl.pRampacFile->value()); + fc = new Fl_File_Chooser(path,"Binary Files (*.bin)",2,"Choose Rampac File"); + fc->preview(0); + fc->show(); + + // Show Chooser window + while (fc->visible()) + Fl::wait(); + + count = fc->count(); + if (count == 0) + { + delete fc; + return; + } + + // Get Filename + filename = fc->value(1); + if (filename == 0) + { + delete fc; + return; + } + len = strlen(filename); + + // Copy filename to edit field + filename_name = fl_filename_name(filename); + + get_model_string(mstr, gModel); + strcpy(mstr_upper, mstr); + for (c = strlen(mstr_upper)-1; c >= 0; c--) + mstr_upper[c] = toupper(mstr_upper[c]); + if (strstr(filename, mstr) || strstr(filename, mstr_upper)) + { + get_emulation_path(path, gModel); + strcat(path, filename_name); + mem_ctrl.pRampacFile->value(path); + } + else + mem_ctrl.pRampacFile->value(filename); + + delete fc; +} + +/* +============================================================================ +Routine to create the PeripheralSetup Window and tabs +============================================================================ +*/ +void cb_MemorySetup (Fl_Widget* w, void*) +{ + // Create Peripheral Setup window + gmsw = new Fl_Window(420, 260, "Memory Emulation Options"); + gmsw->callback(cb_memorywin); + + // Create items on the Tab + mem_ctrl.pNone = new Fl_Round_Button(20, 20, 180, 20, "Base Memory"); + mem_ctrl.pNone->type(FL_RADIO_BUTTON); + mem_ctrl.pNone->callback(cb_radio_base_memory); + if (mem_setup.mem_mode == SETUP_MEM_BASE) + mem_ctrl.pNone->value(1); + + mem_ctrl.pRampac = new Fl_Round_Button(20, 45, 180, 20, "RamPac (256K RAM)"); + mem_ctrl.pRampac->type(FL_RADIO_BUTTON); + mem_ctrl.pRampac->callback(cb_radio_rampac); + if (mem_setup.mem_mode == SETUP_MEM_RAMPAC) + mem_ctrl.pRampac->value(1); + + mem_ctrl.pReMem = new Fl_Round_Button(20, 70, 220, 20, "ReMem (2M RAM, 4M FLASH)"); + mem_ctrl.pReMem->type(FL_RADIO_BUTTON); + mem_ctrl.pReMem->callback(cb_radio_remem); + if (mem_setup.mem_mode == SETUP_MEM_REMEM) + mem_ctrl.pReMem->value(1); + + mem_ctrl.pReMem_Rampac = new Fl_Round_Button(20, 95, 180, 20, "ReMem + RamPac"); + mem_ctrl.pReMem_Rampac->type(FL_RADIO_BUTTON); + mem_ctrl.pReMem_Rampac->callback(cb_radio_remem_and_rampac); + if (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC) + mem_ctrl.pReMem_Rampac->value(1); + + // =============================================== + // Setup Rampac File Edit field and Browser button + // =============================================== + mem_ctrl.pRampacFile = new Fl_Input(105, 120, 210, 20, "RamPac File"); + mem_ctrl.pRampacFile->value(mem_setup.rampac_file); + + mem_ctrl.pRampacBrowse = new Fl_Button(330, 115, 60, 30, "Browse"); + mem_ctrl.pRampacBrowse->callback((Fl_Callback*)cb_rampac_browse); + + if ((mem_setup.mem_mode != SETUP_MEM_RAMPAC) && (mem_setup.mem_mode != SETUP_MEM_REMEM_RAMPAC)) + { + mem_ctrl.pRampacFile->deactivate(); + mem_ctrl.pRampacBrowse->deactivate(); + } + + // =============================================== + // Setup ReMem File edit field and Browser button + // =============================================== + mem_ctrl.pReMemFile = new Fl_Input(105, 160, 210, 20, "ReMem File"); + mem_ctrl.pReMemFile->value(mem_setup.remem_file); + mem_ctrl.pReMemText = new Fl_Box(45, 180, 325, 20, "(Use Memory Editor to load FLASH)"); + mem_ctrl.pReMemText->labelsize(12); + + mem_ctrl.pReMemBrowse = new Fl_Button(330, 155, 60, 30, "Browse"); + mem_ctrl.pReMemBrowse->callback((Fl_Callback*)cb_remem_browse); + + if ((mem_setup.mem_mode != SETUP_MEM_REMEM) && (mem_setup.mem_mode != SETUP_MEM_REMEM_RAMPAC)) + { + mem_ctrl.pReMemFile->deactivate(); + mem_ctrl.pReMemBrowse->deactivate(); + mem_ctrl.pReMemText->hide(); + } + + // OK button + { Fl_Button* o = new Fl_Button(160, 220, 60, 30, "Cancel"); + o->callback((Fl_Callback*)cb_memory_cancel); + } + { Fl_Return_Button* o = new Fl_Return_Button(230, 220, 60, 30, "OK"); + o->callback((Fl_Callback*)cb_memory_OK); + } + + gmsw->show(); +} + diff --git a/src/setup.h b/src/setup.h index 4d8c12f..ca49da7 100644 --- a/src/setup.h +++ b/src/setup.h @@ -33,10 +33,12 @@ #ifdef __cplusplus void cb_PeripheralSetup (Fl_Widget* w, void*); +void cb_MemorySetup (Fl_Widget* w, void*); extern "C" { #endif void load_setup_preferences(void); +void load_memory_preferences(void); typedef struct peripheral_setup @@ -62,6 +64,15 @@ typedef struct peripheral_setup extern peripheral_setup_t setup; +typedef struct memory_setup +{ + int mem_mode; // Mode for Memory emulation + char remem_file[256]; // Filename for ReMem storage + char rampac_file[256]; // Filename for RamPac storage +} memory_setup_t; + +extern memory_setup_t mem_setup; + enum { SETUP_COM_NONE, SETUP_COM_SIMULATED, @@ -69,8 +80,15 @@ enum { SETUP_COM_OTHER }; +enum { + SETUP_MEM_BASE, + SETUP_MEM_RAMPAC, + SETUP_MEM_REMEM, + SETUP_MEM_REMEM_RAMPAC +}; + #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif diff --git a/src/sound.c b/src/sound.c new file mode 100644 index 0000000..70d873d --- /dev/null +++ b/src/sound.c @@ -0,0 +1,440 @@ +/* sound.c */ + +/* $Id$ */ + +/* + * Copyright 2005 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define _MT +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#endif + +#ifdef __unix__ +#include +#include +#endif + +#include "VirtualT.h" +#include "sound.h" +#include "m100emu.h" + +#pragma comment(lib, "winmm.lib") + +#define snd_Buffers 2 +#define cwSizel 96 + +/* + * module static data + */ +unsigned int g_FrameSize ; +unsigned int g_Blocks ; +unsigned int g_BufSize ; +const unsigned int g_Buffers = 2 ; + +unsigned int NextBuf, fDone [snd_Buffers] ; +unsigned int Index ; +unsigned short readbuf [2 * cwSizel] ; /* input buffer */ +short int tmpbuf [2 * cwSizel] ; +int m_Channels = 2 , + m_SamplingRate = 22050, + SamplesPerFrame = cwSizel; +short *pcmbuf; +short *tmppcmbuf; +int frameCount=0; +int cwSize = 2*cwSizel; +int gPlayTone = 0; +int gToneFreq = 0; +int gFlushBuffers = 0; +int gExit = 0; +extern double last_instruct; +static double spkr_cycle = 0; +int gBeepOn = 0; + +#ifdef _WIN32 +HANDLE g_hEquThread; +DWORD dwThreadID; +WAVEFORMATEX wf ; +HWAVEOUT hOutput ; +WAVEHDR wh [snd_Buffers] ; +#endif + + +#ifdef _WIN32 + +void APIENTRY sndCallback (HWAVEOUT hWaveOut, UINT wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) +{ + if (wMsg == WOM_DONE) + fDone [((LPWAVEHDR) dwParam1)->dwUser] = TRUE ; +} + +BOOL sndOpenOutput (unsigned int chan, unsigned int freq, unsigned int framesize) +{ + UINT i; + UINT n; + UINT id = WAVE_MAPPER; + UINT devs = waveOutGetNumDevs (); + WAVEOUTCAPS caps ; + MMRESULT err; + + // we're not using wavemapper, since soundblaster probably is + // preferred device --> look for the multichannel card + if (chan > 2) + { + /* Loop through all devices looking for multi-channel support */ + for (id = 0 ; id < devs ; id++) + { + err = waveOutGetDevCaps (id, &caps, sizeof (WAVEOUTCAPS)) ; + if ((err == MMSYSERR_NOERROR) && (caps.wChannels >= chan)) + break ; + } + + /* Check if no output devices found */ + if (id == devs) + return FALSE ; + + g_FrameSize = 8 * framesize ; + g_Blocks = 10 ; + } + else + { + /* Configure for up to 2 channel support */ + g_FrameSize = chan * framesize ; + g_Blocks = 22 ; + } + + /* Calculate buffer size */ + g_BufSize = 2 * g_Blocks * g_FrameSize ; + + /* Prepare to open the Wave Device */ + wf.nSamplesPerSec = freq ; + wf.wFormatTag = WAVE_FORMAT_PCM ; + wf.nChannels = chan ; + wf.nBlockAlign = 2 * wf.nChannels ; + wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign ; + wf.wBitsPerSample = 16 ; + + /* Try to open the Wave output device */ + waveOutOpen (&hOutput, id, &wf, (DWORD) sndCallback, 0, /* WAVE_FORMAT_DIRECT | */ CALLBACK_FUNCTION) ; + if (hOutput == NULL) + return FALSE ; + + /* Initialize buffers for the device */ + for ( i = 0 ; i < g_Buffers ; i++) + { + ZeroMemory (&wh [i], sizeof (WAVEHDR)) ; + + wh [i].dwBufferLength = g_BufSize ; + wh [i].lpData = (LPSTR) VirtualAlloc (NULL, g_BufSize, MEM_COMMIT, PAGE_READWRITE) ; + if (wh [i].lpData == NULL) + { + for (n = 0 ; n < i ; n++) + VirtualFree (wh [n].lpData, 0, MEM_RELEASE) ; + waveOutClose (hOutput) ; + return FALSE ; + } + + ZeroMemory (wh [i].lpData, g_BufSize) ; + + wh [i].dwUser = i ; + fDone [i] = TRUE ; + NextBuf = 0 ; + } + + Index = 0 ; + + return TRUE ; +} + + + +BOOL sndCloseOutput (void) +{ + UINT i; + + if (hOutput == NULL) + return FALSE ; + + waveOutReset (hOutput) ; + + for (i = 0 ; i < g_Buffers ; i++) + { + if (wh [i].dwFlags & WHDR_PREPARED) + waveOutUnprepareHeader (hOutput, &wh [i], sizeof (WAVEHDR)) ; + VirtualFree (wh [i].lpData, 0, MEM_RELEASE) ; + } + + waveOutClose (hOutput) ; + hOutput = NULL ; + + return TRUE ; +} + +short *sndGetBuffer (void) +{ + short *wbuf; + + if (hOutput == NULL) + return NULL ; + + /* printf ("%i %i\t", NextBuf, Index) ; */ + + wbuf = (short *) wh [NextBuf].lpData ; + wbuf = &wbuf [g_FrameSize * Index++] ; + + if (Index <= g_Blocks) + return wbuf ; + + Index = 1 ; /* i.e. Index = 0++ */ + + fDone [NextBuf] = FALSE ; + waveOutPrepareHeader (hOutput, &wh [NextBuf], sizeof (WAVEHDR)) ; + waveOutWrite (hOutput, &wh [NextBuf], sizeof (WAVEHDR)) ; + + NextBuf = ++NextBuf % g_Buffers ; + + while (fDone [NextBuf] == FALSE) + Sleep (60) ; + /* if (WaitForSingleObject (hStopNow, 40) == WAIT_OBJECT_0) return FALSE ; */ + + if (wh [NextBuf].dwFlags & WHDR_PREPARED) + waveOutUnprepareHeader (hOutput, &wh [NextBuf], sizeof (WAVEHDR)) ; + + /* printf ("** **\t%i %i\t", NextBuf, 0) ; */ + + return (short *) wh [NextBuf].lpData ; +} + +void sndFlushBuffers (void) +{ + UINT i; + + /* Zero the memory in all buffers */ + for (i = Index ; i <= g_Blocks ; i++) + { + PBYTE buf; + buf = (PBYTE) sndGetBuffer () ; + if (!buf) + return ; + + ZeroMemory (buf, g_FrameSize * sizeof (short)) ; + } + + /* Wait for all buffers to be done */ + for (i = 0 ; i < g_Buffers ; i++) + { + while (fDone [i] == FALSE) + Sleep (20) ; + } +} + +//;============================================================= +void playback() +{ + int i; + BOOL fWantPlayback; + double inc, sval; + static double mult = 1; + static double mult_add = 0; + static double val = 0.0; + + + if (gToneFreq != 0.0) + mult = (double) m_SamplingRate / (double) gToneFreq; + if (mult <= 10) + mult_add = .5; + if (mult >= 50) + mult_add = -.5; + +// mult += mult_add; + inc = 1.0 / (double) cwSize; + for (i = 0; i < cwSize; i++) + { + val += inc; + sval = sin(val * 6.283*mult) * 32700; + readbuf[i] = (unsigned short) sval; + } + fWantPlayback = TRUE; + + /* get an output buffer and do decoding work */ + pcmbuf = (fWantPlayback && frameCount) ? sndGetBuffer () : tmpbuf ; + tmppcmbuf = pcmbuf; + + for (i=0;i 0.001) + { + gPlayTone = 0; + gBeepOn = 0; + sndFlushBuffers(); + } + } + if (gExit) + break; + } + + sndCloseOutput (); + _endthreadex(0); + + return 0; +} + +#endif + + +/* +================================================================== +init_sound: This routine initializes the sound output device(s) + for tone generations. +================================================================== +*/ +void init_sound(void) +{ + gExit = 0; + return; + +#ifdef _WIN32 + g_hEquThread = (HANDLE)_beginthreadex(0,0,EquProc,0,0,&dwThreadID); +#endif +} + + +/* +================================================================== +init_sound: This routine deinitializes the sound output device(s) + for tone generations. +================================================================== +*/ +void deinit_sound(void) +{ + gExit = 1; + +#ifdef _WIN32 +// sndCloseOutput(); +#endif +} + + +/* +================================================================== +start_tone: This routine starts a tone of specified frequency +================================================================== +*/ +void sound_start_tone(int freq) +{ + gToneFreq = freq; + gPlayTone = 1; +} + +/* +================================================================== +stop_tone: This routine stops playing of tones +================================================================== +*/ +void sound_stop_tone(void) +{ + +#ifdef _WIN32 +// waveOutReset (hOutput) ; +#endif + gPlayTone = 0; +// gFlushBuffers = 1; +} + + +/* +================================================================== +toggle_speaker: This routine handles toggling of the I/O bit that + is connected directly to the speaker. The routine + calculates the frequency of toggle and generates + a beep during the toggle period. +================================================================== +*/ +void sound_toggle_speaker(int bitVal) +{ + double delta; + + /* Calculate delta between current cycle and last cycle */ + delta = last_instruct - spkr_cycle; + spkr_cycle = last_instruct; + + /* Test if delta is within a valid range */ + if ((delta < 5000) && (delta != 0.0)) + { + gBeepOn = 1; + sound_start_tone((int) (1.0 / delta)); + } + +} + + diff --git a/src/sound.h b/src/sound.h new file mode 100644 index 0000000..385c0b6 --- /dev/null +++ b/src/sound.h @@ -0,0 +1,40 @@ +/* sound.h */ + +/* $Id$ */ + +/* + * Copyright 2005 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef SOUND_H +#define SOUND_H + +void init_sound (void); +void deinit_sound (void); +void sound_start_tone (int freq); +void sound_stop_tone (void); +void sound_toggle_speaker (int bitVal); + +#endif From ba2314e9f8d761273f8de6846b980a207ffa68b3 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 18 Apr 2006 23:49:09 +0000 Subject: [PATCH 036/327] Completed support for ReMem, added Memory Editor Window Load/Save options. --- src/VirtualT.h | 2 +- src/cpu.h | 97 ++-- src/disassemble.cpp | 45 +- src/disassemble.h | 1 + src/display.cpp | 46 +- src/do_instruct.h | 140 +----- src/file.cpp | 32 +- src/file.h | 12 + src/io.c | 35 +- src/m100emu.c | 237 +++++++--- src/m100emu.h | 10 +- src/memedit.h | 1 + src/memory.c | 1027 +++++++++++++++++++++++-------------------- src/memory.h | 49 ++- src/periph.cpp | 7 +- src/periph.h | 2 + src/serial.c | 1 - src/setup.cpp | 36 +- src/sound.c | 63 +-- 19 files changed, 1067 insertions(+), 776 deletions(-) diff --git a/src/VirtualT.h b/src/VirtualT.h index 5907a5f..0f311a2 100644 --- a/src/VirtualT.h +++ b/src/VirtualT.h @@ -31,7 +31,7 @@ #ifndef _VIRTUALT_H_ #define _VIRTUALT_H_ -#define VERSION "0.5" +#define VERSION "0.6" enum { MODEL_M100 diff --git a/src/cpu.h b/src/cpu.h index f527e6f..8340e35 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -35,6 +35,10 @@ #include "gen_defs.h" +#ifdef __cplusplus +extern "C" { +#endif + #define RAMSIZE (gModel==MODEL_T200?24576:32768) #define ROMSIZE (gModel==MODEL_T200?40960:32768) #define RAMSTART (gModel==MODEL_T200?40960:32768) @@ -42,9 +46,9 @@ #define ADDRESSSPACE 65536 extern uchar cpu[14]; -extern uchar memory[ADDRESSSPACE]; -extern uchar sysROM[65536]; -extern uchar optROM[32768]; +extern uchar *gMemory[64]; +//extern uchar gSysROM[65536]; +//extern uchar gOptROM[32768]; #define A cpu[0] #define F cpu[1] @@ -74,27 +78,21 @@ extern uchar optROM[32768]; #define DECPC2 {PCL-=2; if(PCL>0xfd) PCH--;} #define DECSP {SPL--; if(SPL==0xff) SPH--;} #define DECSP2 {SPL-=2; if(SPL>0xfd) SPH--;} -#define SETPCINS16 {int pc=PC; PCL=memory[pc++]; PCH=memory[pc];} - -#define IM cpu[12] -/* bit 0 is interrupts disabled (1==disabled) */ -#define cpuMISC cpu[13] -#define M memory[HL] -#define INS memory[PC] -//#define INS (uchar) (gReMem ? 0 : memory[PC]) -#define NXTINS memory[PC+1] -#define INS16 (((int)memory[PC])|(((int)memory[PC+1])<<8)) -#define CF (F&0x01) -#define XF ((F&0x02)>>1) -#define XF_BIT 0x02 -#define OV ((F&0x02)>>1) -#define OV_BIT 0x02 -#define PF ((F&0x04)>>2) -#define AC ((F&0x10)>>4) -#define TS ((F&0x20)>>5) -#define TS_BIT 0x20 -#define ZF ((F&0x40)>>6) -#define SF ((F&0x80)>>7) + +extern int gIndex[65536]; + +#define cpuMISC cpu[13] +#define CF (F&0x01) +#define XF ((F&0x02)>>1) +#define XF_BIT 0x02 +#define OV ((F&0x02)>>1) +#define OV_BIT 0x02 +#define PF ((F&0x04)>>2) +#define AC ((F&0x10)>>4) +#define TS ((F&0x20)>>5) +#define TS_BIT 0x20 +#define ZF ((F&0x40)>>6) +#define SF ((F&0x80)>>7) #define RST55MASK (IM&0x01) #define RST65MASK ((IM&0x02)>>1) #define RST75MASK ((IM&0x04)>>2) @@ -102,10 +100,55 @@ extern uchar optROM[32768]; #define RST55PEND ((IM&0x10)>>4) #define RST65PEND ((IM&0x20)>>5) #define RST75PEND ((IM&0x40)>>6) -#define SOD ((IM&0x80)>>7) +#define SOD ((IM&0x80)>>7) +#define IM cpu[12] + +#ifdef __cplusplus +} +#endif + +#endif -#define MEM(x) memory[x] + +/* +===================================================================== +The following defines allow compiling the instruction decoding either +with or without ReMem support. ReMem support slows down the +emulation so the main emulatin routine has 2 loops - one with ReMem +support and one without. The appropriate loop is executed based on +the settings for ReMem support. +===================================================================== +*/ +#undef SETPCINS16 +#undef M +#undef INS +#undef NXTINS +#undef INS16 +#undef MEM +#undef MDM16 +#undef MEMSET + +#ifdef NO_REMEM + +#define SETPCINS16 {int pc=PC; PCL=gBaseMemory[pc++]; PCH=gBaseMemory[pc];} +#define M gBaseMemory[HL] +#define INS gBaseMemory[PC] +#define NXTINS gBaseMemory[PC+1] +#define INS16 (((int)gBaseMemory[PC])|((int)gBaseMemory[PC+1]<<8)) +#define MEM(x) gBaseMemory[x] #define MEM16(x) (((ushort)MEM(x))|((ushort)MEM(x+1))<<8) -#define MEMSET(a,v) {if (gReMem) remem_set8(a, v); else if(a>=ROMSIZE) memory[a]=v; } +#define MEMSET(a,v) {if(a>=ROMSIZE) gBaseMemory[a] = v; } + +#else + +#define SETPCINS16 {int pc=PC; PCL=get_memory8((unsigned short) pc++); PCH=get_memory8((unsigned short) pc);} +#define M (gMemory[gIndex[HL]][HL & 0x3FF]) +#define INS (gMemory[gIndex[PC]][PC & 0x3FF]) +#define NXTINS (get_memory8((unsigned short) (PC+1))) +#define INS16 (((int)get_memory8((unsigned short) (PC)))|(((int)get_memory8((unsigned short) (PC+1)))<<8)) +#define MEM(x) (gMemory[gIndex[x]][x & 0x3FF]) +#define MEM16(x) (((ushort)MEM(x))|((ushort)MEM(x+1))<<8) +#define MEMSET(a,v) {remem_set8((unsigned short) (a), v); } #endif + diff --git a/src/disassemble.cpp b/src/disassemble.cpp index d34dfbe..0689b23 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -47,6 +47,8 @@ #include "periph.h" #include "memedit.h" #include "romstrings.h" +#include "cpuregs.h" +#include "memory.h" Fl_Window *gpDis; @@ -158,7 +160,7 @@ Fl_Menu_Item gDis_menuitems[] = { { 0 }, { "&Tools", 0, 0, 0, FL_SUBMENU }, - { "CPU Registers", 0, 0 }, + { "CPU Registers", 0, cb_CpuRegs }, { "Assembler", 0, 0 }, { "Disassembler", 0, 0 }, { "Debugger", 0, 0 }, @@ -213,7 +215,7 @@ void disassembler_cb(Fl_Widget* w, void*) { pDisassembler->SetTextViewer(td); // Give the disassembler something to disassemble - pDisassembler->CopyIntoMem(memory, ROMSIZE); + pDisassembler->CopyIntoMem(gSysROM, ROMSIZE); gpDis->resizable(m); gpDis->resizable(td); @@ -856,3 +858,42 @@ void VTDis::CopyIntoMem(unsigned char *ptr, int len) m_memory[c] = ptr[c]; } } + +int VTDis::DisassembleLine(int address, char* line) +{ + char arg[60]; + int addr; + unsigned char opcode; + unsigned char op_len; + + // Get opcode from memory + opcode = gMemory[address>>10][address&0x3FF]; + + // Determine length of this opcode + op_len = m_LenTable[opcode] & 0x03; + + // Print the address and opcode value to the temporary line buffer + sprintf(line, "%04XH ", address); + + // Print the opcode text to the temp line buffer + strcat(line, m_StrTable[opcode]); + + // Check if this opcode has a single byte argument + if (op_len == 1) + { + // Single byte argument + sprintf(arg, "%02XH", gMemory[(address+1)>>10][(address+1)&0x3FF]); + strcat(line, arg); + } + + // Check if this opcode as a 2 byte argument + else if (op_len == 2) + { + // Double byte argument + addr = get_memory8(address+1) | (get_memory8(address+2) << 8); + sprintf(arg, "%04XH", addr); + strcat(line, arg); + } + + return 1; +} diff --git a/src/disassemble.h b/src/disassemble.h index 0512c9e..9c6367c 100644 --- a/src/disassemble.h +++ b/src/disassemble.h @@ -50,6 +50,7 @@ class VTDis void Disassemble(); void SetTextViewer(class Fl_Text_Editor* pTextViewer); + static int DisassembleLine(int address, char* line); protected: static char* m_StrTable[256]; static unsigned char m_LenTable[256]; diff --git a/src/display.cpp b/src/display.cpp index 234ef60..bb318a3 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -55,6 +55,7 @@ #include "periph.h" #include "memory.h" #include "memedit.h" +#include "cpuregs.h" extern "C" { extern RomDescription_t gM100_Desc; @@ -145,6 +146,7 @@ void close_disp_cb(Fl_Widget* w, void*) if (gpDisp != NULL) { gExitApp = 1; + gExitLoop = 1; } } @@ -319,6 +321,31 @@ void cb_PC8300(Fl_Widget* w, void*) switch_model(MODEL_PC8300); } +#ifdef __APPLE__ +//JV 08/10/05: add an action to choose the working directory +void cb_choosewkdir(Fl_Widget* w, void*) +{ + /* Choose the working directory (ROM, RAM Files... */ + char *ret; + + + ret=ChooseWorkDir(); + if(ret==NULL) exit(-1); + else + { + strcpy(path,ret); + #ifdef __unix__ + strcat(path,"/"); + #else + strcat(path,"\\"); + #endif + virtualt_prefs.set("Path",path); + } + +} +//--JV +#endif + /* ======================================================= cb_help: This routine displays the Help Subsystem @@ -426,6 +453,9 @@ Fl_Menu_Item menuitems[] = { { "Solid Chars", 0, cb_solidchars, (void *) 1, FL_MENU_TOGGLE}, { 0 }, { "Peripheral Setup...", 0, cb_PeripheralSetup, 0, 0 }, +#ifdef __APPLE__ + { "Directory...", 0, cb_choosewkdir, 0, 0 }, // JV 08/10/05 menu Directory added +#endif { "Memory Options...", 0, cb_MemorySetup, 0, FL_MENU_DIVIDER }, { "Option ROM", 0, 0, 0, FL_SUBMENU }, { gsMenuROM, 0, 0, 0, FL_MENU_DIVIDER }, @@ -435,7 +465,7 @@ Fl_Menu_Item menuitems[] = { { 0 }, { "&Tools", 0, 0, 0, FL_SUBMENU }, - { "CPU Registers", 0, 0 }, + { "CPU Registers", 0, cb_CpuRegs }, { "Assembler", 0, 0 }, { "Disassembler", 0, disassembler_cb }, { "Debugger", 0, 0 }, @@ -681,7 +711,7 @@ void T100_Disp::draw() x=(driver % 5) * 50; x+=col; - y = row * 8; + y = row << 3; if (driver > 4) y += 32; @@ -752,10 +782,6 @@ void T100_Disp::SetByte(int driver, int col, uchar value) drawpixel(x,y++,(value&0x20)>>5); drawpixel(x,y++,(value&0x40)>>6); drawpixel(x,y++,(value&0x80)>>7); - - // Update display -// Fl::wait(0); -// } } // read Pref File // J. VERNET @@ -1037,7 +1063,7 @@ void T100_Disp::PowerDown() if (c == 5) SetByte(driver, (column % 50) | 0xC0, 0); else - SetByte(driver, (column % 50) | 0xC0, memory[mem_index++]); + SetByte(driver, (column % 50) | 0xC0, gSysROM[mem_index++]); column++; } } @@ -1054,7 +1080,7 @@ void T100_Disp::PowerDown() if (c == 5) SetByte(driver, (column % 50), 0); else - SetByte(driver, (column % 50), memory[mem_index++]); + SetByte(driver, (column % 50), gSysROM[mem_index++]); column++; } } @@ -1988,7 +2014,7 @@ void T200_Disp::draw() draw_static(); /* Get RAM address where display should start */ - addr = (m_dstarth << 8) | m_dstartl; + addr = ((m_dstarth << 8) | m_dstartl) & (8192-1); fl_color(FL_BLACK); @@ -2106,7 +2132,7 @@ void T200_Disp::redraw_active() gpDisp->window()->make_current(); /* Get RAM address where display should start */ - addr = (m_dstarth << 8) | m_dstartl; + addr =( (m_dstarth << 8) | m_dstartl) &(8192-1); /* Check if the driver is in "graphics" mode */ if (m_mcr & 0x02) diff --git a/src/do_instruct.h b/src/do_instruct.h index e3209fd..06f2b2c 100644 --- a/src/do_instruct.h +++ b/src/do_instruct.h @@ -30,8 +30,6 @@ #define LXI(rp,h,l,rps) { \ INCPC; \ - if(trace) \ - sprintf(p,"LXI "rps",%04x",INS16); \ l=INS; \ INCPC; \ h=INS; \ @@ -41,16 +39,12 @@ #define STAX(rp,rps) { \ INCPC; \ - if(trace) \ - strcat(p,"STAX "rps); \ MEMSET(rp,A); \ cpu_delay(7); \ } #define INX(rp,h,l,rps) { \ INCPC; \ - if(trace) \ - strcat(p,"INX "rps); \ l++; \ F &= ~XF_BIT; \ if(!l) { \ @@ -62,8 +56,6 @@ #define INR(r,rs) { \ INCPC; \ - if(trace) \ - strcat(p,"INR "rs); \ r++; \ if(r&0x0f==0) /* Low order nybble wrapped */ \ j=1; \ @@ -75,8 +67,6 @@ #define DCR(r,rs) { \ INCPC; \ - if(trace) \ - strcat(p,"DCR "rs); \ r--; \ if(r&0x0f==0x0f) /* Low order nybble wrapped */ \ j=1; \ @@ -88,8 +78,6 @@ #define MVI(r,rs) { \ INCPC; \ - if(trace) \ - sprintf(p,"MVI "rs",%02x",INS); \ r=INS; \ INCPC; \ cpu_delay(7); \ @@ -97,8 +85,6 @@ #define DAD(rp,rps) { \ INCPC; \ - if(trace) \ - strcat(p,"DAD "rps); \ i=HL; \ i+=rp; \ j=(HL&0x8000)==(rp&0x8000); \ @@ -116,16 +102,12 @@ #define LDAX(rp,rps) { \ INCPC; \ - if(trace) \ - strcat(p,"LDAX "rps); \ A=MEM(rp); \ cpu_delay(7); \ } #define DCX(rp,h,l,rps) { \ INCPC; \ - if(trace) \ - strcat(p,"DCX "rps); \ l--; \ F &= ~XF_BIT; \ if(l==0xff) { \ @@ -137,24 +119,18 @@ #define MOV(dest,src,ds,ss) { \ INCPC; \ - if(trace) \ - strcat(p,"MOV "ds","ss); \ dest=src; \ cpu_delay(4); \ } #define MOVM(src,ss) { \ INCPC; \ - if(trace) \ - strcat(p,"MOV M,"ss); \ MEMSET(HL, src); \ cpu_delay(7); \ } #define ADD(r,rs) { \ INCPC; \ - if(trace) \ - strcat(p,"ADD "rs); \ i=A; \ i+=r; \ v=(A&0x80) == (r&0x80); \ @@ -172,8 +148,6 @@ #define ADC(r,rs) { \ INCPC; \ - if(trace) \ - strcat(p,"ADC "rs); \ i=A; \ i+=r; \ i+=(CF?1:0); \ @@ -192,8 +166,6 @@ #define SUB(r,rs) { \ INCPC; \ - if(trace) \ - strcat(p,"SUB "rs); \ i=A; \ i-=r; \ j = (((A & 0x0F)-(r & 0x0F)) & 0x10) >> 4; \ @@ -211,8 +183,6 @@ #define SBB(r,rs) { \ INCPC; \ - if(trace) \ - strcat(p,"SCB "rs); \ i=A; \ i-=r; \ i-=(CF?1:0); \ @@ -231,8 +201,6 @@ #define ANA(r,rs) { \ INCPC; \ - if(trace) \ - strcat(p,"ANA "rs); \ A&=r; \ setflags(A,-1,-1,1,-1,0,-2,-2); \ cpu_delay(4); \ @@ -240,8 +208,6 @@ #define XRA(r,rs) { \ INCPC; \ - if(trace) \ - strcat(p,"XRA "rs); \ A^=r; \ setflags(A,-1,-1,0,-1,0,-2,-2); \ cpu_delay(4); \ @@ -249,8 +215,6 @@ #define ORA(r,rs) { \ INCPC; \ - if(trace) \ - strcat(p,"ORA "rs); \ A|=r; \ setflags(A,-1,-1,0,-1,0,-2,-2); \ cpu_delay(4); \ @@ -258,8 +222,6 @@ #define CMP(r,rs) { \ INCPC; \ - if(trace) \ - strcat(p,"CMP "rs); \ i=A; \ i-=r; \ if (i>0xFF) \ @@ -277,8 +239,6 @@ #define POP(rp,h,l,rps) { \ INCPC; \ - if(trace) \ - strcat(p,"POP "rps); \ l=MEM(SP); \ h=MEM(SP+1); \ INCSP2; \ @@ -287,8 +247,6 @@ #define PUSH(rp,h,l,rps) { \ INCPC; \ - if(trace) \ - strcat(p,"PUSH "rps); \ DECSP2; \ MEMSET(SP,l); \ MEMSET(SP+1,h); \ @@ -297,8 +255,6 @@ #define RST(num) { \ INCPC; \ - if(trace) \ - sprintf(p,"RST %d",num); \ DECSP2; \ MEMSET(SP,PCL); MEMSET(SP+1,PCH); \ PCH=0; \ @@ -308,8 +264,6 @@ #define CALL(cond,ins) { \ INCPC; \ - if(trace) \ - sprintf(p,ins" %04x",INS16); \ INCPC2; \ if(cond) { \ DECSP2; \ @@ -322,8 +276,6 @@ } #define RETURN(cond,ins) { \ - if(trace) \ - strcat(p,ins); \ INCPC; \ if(cond) { \ PCL=MEM(SP); PCH=MEM(SP+1); /* PC=MEM16(SP) */ \ @@ -335,8 +287,6 @@ #define JUMP(cond,ins) { \ INCPC; \ - if(trace) \ - sprintf(p,ins" %04x",INS16); \ if(cond) { \ SETPCINS16; \ cpu_delay(3); \ @@ -347,8 +297,8 @@ } { - if(trace) - p=op+sprintf(op,"%04x (%02x) ",PC,INS); +// if(trace) +// p=op+sprintf(op,"%04x (%02x) ",PC,INS); if(!(INS&0x80)) { if(!(INS&0x40)) { if(!(INS&0x20)) { @@ -359,8 +309,6 @@ if(!(INS&0x01)) { /* case 0x00: /* NOP */ INCPC; - if(trace) - strcat(p,"NOP"); cpu_delay(4); /* return; */ } @@ -399,8 +347,6 @@ else { /* case 0x07: /* RLC */ INCPC; - if(trace) - strcat(p,"RLC"); i=A>>7; A=(A<<1)|i; setflags(A,-2,-2,-2,-2,i,-2,-2); @@ -416,8 +362,6 @@ if(!(INS&0x01)) { /* case 0x08: /* DSUB */ INCPC; - if (trace) - sprintf(p, "DSUB"); i = HL < BC;// - (CF?1:0); j = HL - BC;// - (CF?1:0); v = (HL&0x8000) == (BC&0x8000); @@ -464,8 +408,6 @@ else { /* case 0x0F: /* RRC */ INCPC; - if(trace) - strcat(p,"RRC"); i=A<<7&0x80; A=(A>>1)|i; i>>=7; @@ -484,8 +426,6 @@ if(!(INS&0x01)) { /* case 0x10: /* ASHR */ INCPC; - if (trace) - sprintf(p, "ASHR"); i = L & CF ; j = HL >> 1; L = j & 0xFF; @@ -529,8 +469,6 @@ else { /* case 0x17: /* RAL */ INCPC; - if(trace) - strcat(p,"RAL"); i=A>>7; A<<=1; A|=(CF?1:0); @@ -547,8 +485,6 @@ if(!(INS&0x01)) { /* case 0x18: /* RLDE */ INCPC; - if (trace) - sprintf(p, "RLDE"); i = D & 0x80 ? 1 : 0; j = DE << 1; E = (j & 0xFF) | (CF ? 1 : 0); @@ -592,8 +528,6 @@ else { /* case 0x1F: /* RAR */ INCPC; - if(trace) - strcat(p,"RAR"); i=(A&0x01); A>>=1; A|=CF?0x80:0; @@ -614,8 +548,6 @@ if(!(INS&0x01)) { /* case 0x20: /* RIM */ INCPC; - if(trace) - strcat(p,"RIM"); A=IM; cpu_delay(4); /* return; */ @@ -629,8 +561,6 @@ if(!(INS&0x01)) { /* case 0x22: /* SHLD */ INCPC; - if(trace) - sprintf(p,"SHLD %x",INS16); MEMSET(INS16,L); MEMSET(INS16+1,H); /* MEM16(INS16)=HL; */ @@ -663,8 +593,6 @@ else { /* case 0x27: /* DAA */ INCPC; - if(trace) - strcat(p,"DAA"); i=j=0; /* Check if lower nibble greater than 9 */ if(((A&0x0F) > 9)) { @@ -692,8 +620,6 @@ if(!(INS&0x01)) { /* case 0x28: /* LDEH */ INCPC; - if (trace) - sprintf(p, "LDEH %02x", INS); j = HL + INS; INCPC; E = j & 0xFF; @@ -710,8 +636,6 @@ if(!(INS&0x01)) { /* case 0x2A: /* LHLD */ INCPC; - if(trace) - sprintf(p,"LHLD %x",INS16); L=MEM(INS16); H=MEM(INS16+1); INCPC2; @@ -742,8 +666,6 @@ else { /* case 0x2F: /* CMA */ INCPC; - if(trace) - strcat(p,"CMA"); A=~A; cpu_delay(4); } @@ -758,8 +680,6 @@ if(!(INS&0x01)) { /* case 0x30: /* SIM */ INCPC; - if(trace) - strcat(p,"SIM"); if (A & 0x08) /* Check if Interrupt masking enabled */ IM=(IM & 0xF8) | (A&0x07); /* Turn RST 7.5 pending off if bit 4 set */ @@ -778,8 +698,6 @@ if(!(INS&0x01)) { /* case 0x32: /* STA */ INCPC; - if(trace) - sprintf(p,"STA %04x",INS16); MEMSET(INS16,A); INCPC2; cpu_delay(13); @@ -796,8 +714,6 @@ if(!(INS&0x01)) { /* case 0x34: /* INR M */ INCPC; - if(trace) - strcat(p,"INR M"); MEMSET(HL,(uchar) (M+1)); if(M&0x0f==0) /* Low order nybble wrapped */ j=1; @@ -809,8 +725,6 @@ else { /* case 0x35: /* DCR M */ INCPC; - if(trace) - strcat(p,"DCR M"); MEMSET(HL, (uchar)(M-1)); if(M&0x0f==0x0f) /* Low order nybble wrapped */ j=1; @@ -824,17 +738,13 @@ if(!(INS&0x01)) { /* case 0x36: /* MVI M */ INCPC; - if(trace) - sprintf(p,"MVI M,%02x",INS); - MEMSET((int)HL,INS); + MEMSET(HL,INS); INCPC; cpu_delay(10); } else { /* case 0x37: /* STC */ INCPC; - if(trace) - strcat(p,"STC"); setflags(0,-2,-2,-2,-2,1,-2,-2); cpu_delay(4); /* return; */ @@ -848,8 +758,6 @@ if(!(INS&0x01)) { /* case 0x38: /* LDES */ INCPC; - if (trace) - sprintf(p, "LDES %02x", INS); j = SP + INS; INCPC; E = j & 0xFF; @@ -866,8 +774,6 @@ if(!(INS&0x01)) { /* case 0x3A: /* LDA */ INCPC; - if(trace) - sprintf(p,"LDA %04x",INS16); A=MEM(INS16); INCPC2; cpu_delay(13); @@ -898,8 +804,6 @@ else { /* case 0x3F: /* CMC */ INCPC; - if(trace) - strcat(p,"CMC"); setflags(A,-2,-2,-2,-2,CF?0:1,-2,-2); cpu_delay(4); /* return; */ @@ -1240,8 +1144,6 @@ else { if(!(INS&0x01)) { /* case 0x76: /* HLT */ - if(trace) - strcat(p,"HLT"); cpu_delay(4); /* return; */ } @@ -1703,8 +1605,6 @@ if(!(INS&0x01)) { /* case 0xC0: /* RNZ */ INCPC; - if(trace) - strcat(p,"RNZ"); if(!ZF) { PCL=MEM(SP); PCH=MEM(SP+1); /* PC=MEM16(SP) */ INCSP2; @@ -1744,8 +1644,6 @@ if(!(INS&0x01)) { /* case 0xC6: /* ADI n */ INCPC; - if(trace) - sprintf(p,"ADI %02x",INS); i=A; i+=INS; j = (((A&0x0F)+(INS&0x0F)) &0x10)>>4; @@ -1808,8 +1706,6 @@ if(!(INS&0x01)) { /* case 0xCE: /* ACI n */ INCPC; - if(trace) - sprintf(p,"ACI %02x",INS); i=A; i+=INS; i+=(CF?1:0); @@ -1856,8 +1752,6 @@ else { /* case 0xD3: /* OUT port */ INCPC; - if(trace) - sprintf(p,"OUT %02x",INS); out(INS,A); INCPC; cpu_delay(10); @@ -1880,8 +1774,6 @@ if(!(INS&0x01)) { /* case 0xD6: /* SUI n */ INCPC; - if(trace) - sprintf(p,"SUI %02x",INS); i=A; i-=INS; j = (((A&0x0F)-(INS&0x0F)) &0x10)>>4; @@ -1915,8 +1807,6 @@ else { /* case 0xD9: /* SHLX */ INCPC; - if (trace) - sprintf(p, "SHLX"); MEMSET(DE, L); MEMSET(DE+1, H); cpu_delay(10); @@ -1931,8 +1821,6 @@ else { /* case 0xDB: /* IN port */ INCPC; - if(trace) - sprintf(p,"IN %x",INS); A=inport(INS); INCPC; cpu_delay(10); @@ -1955,8 +1843,6 @@ if(!(INS&0x01)) { /* case 0xDE: /* SBI n */ INCPC; - if(trace) - sprintf(p,"SBI %02x",INS); i=A; i-=INS; i-=(CF?1:0); @@ -2005,8 +1891,6 @@ else { /* case 0xE3: /* XTHL */ INCPC; - if(trace) - strcat(p,"XTHL"); i=H; j=L; L=MEM(SP); @@ -2035,8 +1919,6 @@ if(!(INS&0x01)) { /* case 0xE6: /* ANI n */ INCPC; - if(trace) - sprintf(p,"ANI %02x",INS); A=A&INS; INCPC; setflags(A,-1,-1,1,-1,0,-2,-2); @@ -2073,8 +1955,6 @@ } else { /* case 0xEB: /* XCHG */ - if(trace) - strcat(p,"XCHG"); INCPC; i=H; H=D; @@ -2099,8 +1979,6 @@ else { /* case 0xED: /* LHLX */ INCPC; - if (trace) - sprintf(p, "LHLX"); L=MEM(DE); H=MEM(DE+1); cpu_delay(10); @@ -2111,8 +1989,6 @@ if(!(INS&0x01)) { /* case 0xEE: /* XRI n */ INCPC; - if(trace) - sprintf(p,"XRI %02x",INS); A=A^INS; INCPC; setflags(A,-1,-1,0,-1,0,-2,-2); @@ -2148,8 +2024,6 @@ else { /* case 0xF3: /* DI */ INCPC; - if(trace) - strcat(p,"DI"); IM|=0x08; cpu_delay(4); /* return; */ @@ -2171,8 +2045,6 @@ if(!(INS&0x01)) { /* case 0xF6: /* ORI n */ INCPC; - if(trace) - sprintf(p,"ORI %02x",INS); A=A|INS; INCPC; setflags(A,-1,-1,0,-1,0,-2,-2); @@ -2196,8 +2068,6 @@ else { /* case 0xF9: /* SPHL */ INCPC; - if(trace) - strcat(p,"SPHL"); SPH=H; SPL=L; cpu_delay(6); @@ -2211,8 +2081,6 @@ } else { /* case 0xFB: /* EI */ - if(trace) - strcat(p,"EI"); INCPC; IM&=0xF7; cpu_delay(4); @@ -2236,8 +2104,6 @@ if(!(INS&0x01)) { /* case 0xFE: /* CPI n */ INCPC; - if(trace) - p+=sprintf(p,"CPI %02x",INS); i=A; i-=INS; if(i>0xFF) diff --git a/src/file.cpp b/src/file.cpp index d294f49..1454c00 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -48,7 +48,7 @@ extern "C" #include "intelhex.h" #include "m100emu.h" extern RomDescription_t *gStdRomDesc; -void resetcpu(void); +void jump_to_zero(void); } @@ -138,7 +138,7 @@ void cb_LoadOptRom (Fl_Widget* w, void*) strcpy(gsMenuROM, fl_filename_name(gsOptRomFile)); load_opt_rom(); - resetcpu(); + jump_to_zero(); } @@ -826,7 +826,7 @@ void cb_LoadFromHost(Fl_Widget* w, void*) // Reset the system so file will show up - resetcpu(); + jump_to_zero(); } @@ -1128,13 +1128,16 @@ void cb_SaveToHost(Fl_Widget* w, void*) { // Find entry for the file selected c = fsb->value(); - for (x = 0; x < tCount; x++) + if (c) { - // Search array for entry - if (strcmp(fsb->text(c), tFiles[x].name) == 0) + for (x = 0; x < tCount; x++) { - save_file(&tFiles[x]); - break; + // Search array for entry + if (strcmp(fsb->text(c), tFiles[x].name) == 0) + { + save_file(&tFiles[x]); + break; + } } } } @@ -1145,3 +1148,16 @@ void cb_SaveToHost(Fl_Widget* w, void*) delete fsb; delete gSaveToHost; } + +#ifdef __APPLE__ +//JV 08/10/05: add a function to choose the working directory (where are the ROMs files) +char* ChooseWorkDir() +{ + char *ret=NULL; + + ret = fl_dir_chooser("Choose Working Directory",".",0); + + return ret; +} +//JV +#endif diff --git a/src/file.h b/src/file.h index 8d445bb..d7ddf5e 100644 --- a/src/file.h +++ b/src/file.h @@ -44,4 +44,16 @@ void cb_SaveToHost(Fl_Widget* w, void*); extern int BasicSaveMode; extern int COSaveMode; +#ifdef __APPLE__ +//JV 10/08/05 +char* ChooseWorkDir(); + +#ifdef __cplusplus +extern "C" +#endif +extern char path[255]; + +//JV +#endif + #endif diff --git a/src/io.c b/src/io.c index 523b412..b7d94d3 100644 --- a/src/io.c +++ b/src/io.c @@ -73,6 +73,7 @@ int gDelayCount = 0; uchar clock_sr[5]; /* 40 Bit shift register */ uchar clock_sr_index = 0; uchar clock_serial_out = 0; +extern int gRomBank; void update_keys(void) @@ -80,7 +81,7 @@ void update_keys(void) int equal = 1; int buf_index = 0xFF9A; int c; - uchar key; + unsigned char key; if (gModel == MODEL_T200) buf_index = 0xFD0E; @@ -94,7 +95,7 @@ void update_keys(void) { key = (uchar) ((~keyscan[c]) & 0xFF); /* Old keyscan matrix must match buffer in memory */ - if (memory[buf_index] != key) + if (get_memory8((unsigned short) buf_index) != key) { equal = 0; break; @@ -217,9 +218,6 @@ void deinit_io(void) ser_deinit(); } - -int cROM = 0; - void clock_chip_cmd(void) { static int clk_cnt = 1; @@ -273,10 +271,10 @@ void clock_chip_cmd(void) clock_sr_index = 0; - if ((memory[0xF92E] == 0) && (memory[0xF92D] == 0)) + if ((get_memory8(0xF92E) == 0) && (get_memory8(0xF92D) == 0)) { - memory[0xF92D] = mytime->tm_year % 10; - memory[0xF92E] = (mytime->tm_year % 100) / 10; + set_memory8(0xF92D, (unsigned char) (mytime->tm_year % 10)); + set_memory8(0xF92E, (unsigned char) ((mytime->tm_year % 100) / 10)); } } } @@ -286,9 +284,11 @@ void out(uchar port, uchar val) unsigned char flags; switch(port) { - case 0x70: /* ReMem Mode port */ - case 0x81: /* ReMem RAMPAC emulation port */ - case 0x83: /* ReMem RAMPAC emulation port */ + case REMEM_SECTOR_PORT: /* ReMem Sector access port */ + case REMEM_DATA_PORT: /* ReMem Data Port */ + case REMEM_MODE_PORT: /* ReMem Mode port */ + case RAMPAC_SECTOR_PORT: /* ReMem/RAMPAC emulation port */ + case RAMPAC_DATA_PORT: /* ReMem RAMPAC emulation port */ remem_out(port, val); break; @@ -660,7 +660,7 @@ void out(uchar port, uchar val) if (gModel != MODEL_T200) { /* Check for change in ROM selection */ - if ((val & 0x01) != cROM) + if ((val & 0x01) != gRomBank) set_rom_bank((uchar) (val & 0x01)); /* Check for Clock Chip strobe */ @@ -756,6 +756,17 @@ int inport(uchar port) unsigned char flags; switch(port) { + case REMEM_SECTOR_PORT: /* ReMem Sector access port */ + case REMEM_DATA_PORT: /* ReMem Data Port */ + case REMEM_MODE_PORT: /* ReMem Mode port */ + case REMEM_REVID_PORT: /* ReMem Rev ID */ + case RAMPAC_SECTOR_PORT: /* ReMem/RAMPAC emulation port */ + case RAMPAC_DATA_PORT: /* ReMem RAMPAC emulation port */ + if (remem_in(port, &ret)) + return ret; + else + return 0; + case 0x82: /* Optional IO thinger? */ return(0xA2); diff --git a/src/m100emu.c b/src/m100emu.c index 7f5d8a9..5f086f3 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -59,10 +59,14 @@ int fullspeed=0; int gModel = MODEL_M100; uchar cpu[14]; -uchar memory[65536]; -uchar sysROM[65536]; -uchar msplanROM[32768]; -uchar optROM[32768]; +extern uchar *gMemory[64]; +extern uchar gBaseMemory[65536]; +extern uchar gSysROM[65536]; +extern uchar gMsplanROM[32768]; +extern uchar gOptROM[32768]; + +mem_monitor_cb gMemMonitor = NULL; + char op[26]; UINT64 cycles=0; UINT64 instructs=0; @@ -77,6 +81,7 @@ UINT64 one_sec_cycles; DWORD update_secs = 0; float cpu_speed; int gExitApp = 0; +int gExitLoop = 0; char gsOptRomFile[256]; DWORD last_one_sec_time; @@ -95,9 +100,11 @@ RomDescription_t *gStdRomDesc; /* Define Debug global variables */ -char gDebugActive = 0; -char gStopped = 0; -char gSingleStep = 0; +char gDebugActive = 0; +char gStopped = 0; +char gSingleStep = 0; +debug_monitor_callback gpDebugMonitors[3] = { NULL, NULL, NULL }; + #ifdef _WIN32 __inline double hirestimer(void) @@ -168,24 +175,82 @@ void bail(char *msg) exit(1); } +void jump_to_zero(void) +{ + int i; + + /* Clear all CPU registers */ + for (i = 0; i < sizeof(cpu); i++) + cpu[i] = 0; +} + void resetcpu(void) { - A=0; - F=0; - B=0; - C=0; - E=0; - H=0; - L=0; - SPH=0; - SPL=0; - PCH=0; - PCL=0; + int i; + + /* Clear all CPU registers */ + for (i = 0; i < sizeof(cpu); i++) + cpu[i] = 0; + + /* Set interrupt mask */ IM=0x08; cpuMISC=0; - memcpy(memory,sysROM,ROMSIZE); - cROM = 0; + /* Re-initialize memory */ + reinit_mem(); + + /* Check if debug monitor active and updae if there are */ + if (gDebugActive) + { + /* Call all debug monitor callback routines */ + for (i = 0; i < 3; i++) + { + if (gpDebugMonitors[i] != NULL) + gpDebugMonitors[i](); + } + } +} + + +/* +============================================================================= +debug_set_monitor_callback: This function adds a new debug monitor process. +============================================================================= +*/ +int debug_set_monitor_callback(debug_monitor_callback pCallback) +{ + int x; + + for (x = 0; x < 3; x++) + { + if (gpDebugMonitors[x] == NULL) + { + gpDebugMonitors[x] = pCallback; + return x; + } + } + + return -1; +} + +/* +============================================================================= +debug_clear_monitor_callback: This function deletes the specified callback + from the debug monitor list. +============================================================================= +*/ +void debug_clear_monitor_callback(debug_monitor_callback pCallback) +{ + int x; + + for (x = 0; x < 3; x++) + { + if (gpDebugMonitors[x] == pCallback) + { + gpDebugMonitors[x] = NULL; + return; + } + } } /* @@ -341,20 +406,20 @@ void init_cpu(void) } /* Read data from the ROM file */ - if (read(fd, sysROM, ROMSIZE) 0)) + while ((argv[0][i] != '/') && (i > 0)) i--; strncpy(path,argv[0], i+1); # else @@ -575,9 +706,9 @@ int main(int argc, char **argv) #endif // Added by JV for prefs - init_pref(); // load user Menu preferences - load_setup_preferences(); // Load user Peripheral setup preferences - load_memory_preferences(); // Load user Memory setup preferences + init_pref(); /* load user Menu preferences */ + load_setup_preferences(); /* Load user Peripheral setup preferences */ + load_memory_preferences(); /* Load user Memory setup preferences */ /* Perform initialization */ init_mem(); /* Initialize Memory */ diff --git a/src/m100emu.h b/src/m100emu.h index 0bc88d2..c89ca4b 100644 --- a/src/m100emu.h +++ b/src/m100emu.h @@ -43,14 +43,22 @@ extern char op[26]; extern int trace; extern int fullspeed; extern int gExitApp; +extern int gExitLoop; extern float cpu_speed; -extern uchar memory[65536]; +extern uchar *gMemory[64]; extern RomDescription_t *gStdRomDesc; extern int gModel; extern char gsOptRomFile[256]; __inline double hirestimer(void); typedef void (*mem_monitor_cb)(void); +typedef void (*debug_monitor_callback)(); void mem_set_monitor_callback(mem_monitor_cb cb); +int debug_set_monitor_callback(debug_monitor_callback pCallback); +void debug_clear_monitor_callback(debug_monitor_callback pCallback); +extern char gDebugActive; +extern char gStopped; +extern char gSingleStep; +extern int gDebugMonitorFreq; int check_model_support(int model); diff --git a/src/memedit.h b/src/memedit.h index b88e6c5..b542180 100644 --- a/src/memedit.h +++ b/src/memedit.h @@ -53,6 +53,7 @@ class T100_MemEditor : public Fl_Widget int GetRegionEnum(void); void UpdateAddressText(void); void UpdateDispMem(void); + void MoveTo(int value); int m_FirstLine; protected: diff --git a/src/memory.c b/src/memory.c index e26873c..3c05d56 100644 --- a/src/memory.c +++ b/src/memory.c @@ -21,17 +21,17 @@ memory.c #include "intelhex.h" #include "setup.h" -extern uchar memory[65536]; /* System Memory */ -extern uchar sysROM[65536]; /* System ROM */ -extern uchar optROM[32768]; /* Option ROM */ -extern uchar msplanROM[32768]; /* MSPLAN ROM T200 Only */ +uchar *gMemory[64]; /* CPU Memory space */ +uchar gBaseMemory[65536]; /* System Memory */ +uchar gSysROM[65536]; /* System ROM */ +uchar gOptROM[32768]; /* Option ROM */ +uchar gMsplanROM[32768]; /* MSPLAN ROM T200 Only */ extern char path[255]; extern char file[255]; -extern int cROM; /* Model 100/102 Option ROM flag */ unsigned char rambanks[3*32768]; /* Model T200 & NEC RAM banks */ uchar gRamBank = 0; /* Currently enabled bank */ -uchar gRomBank = 0; /* Current ROM Bank selection */ +int gRomBank = 0; /* Current ROM Bank selection */ uchar gReMem = 0; /* Flag indicating if ReMem emulation enabled */ uchar gReMemBoot = 0; /* ALT boot flag */ @@ -40,6 +40,9 @@ uchar gReMemSector = 0; /* Current Vector access sector */ uchar gReMemCounter = 0; /* Current Vector access counter */ unsigned char *gReMemSectPtr = 0; /* Pointer to current Sector memory */ unsigned short gReMemMap[64]; /* Map of 1K blocks - 64 total */ +unsigned int gReMemMapLower = 0; /* Lower address of actively mapped MMU Map */ +unsigned int gReMemMapUpper = 0; /* Upper address of actively mapped MMU Map */ + uchar *gReMemRam = 0; /* Pointer to ReMem RAM space */ uchar *gReMemFlash1 = 0; /* Pointer to ReMem Flash1 space */ uchar *gReMemFlash2 = 0; /* Pointer to ReMem Flash2 space */ @@ -48,27 +51,39 @@ int gRampac = 0; /* Rampac Enable flag */ unsigned char *gRampacRam = 0; /* Rampac RAM pointer */ int gRampacSector = 0; /* Rampac emulation Sector number */ int gRampacCounter = 0; /* Rampac emulation Counter */ +unsigned char *gRampacSectPtr = 0;/* Pointer to current Sector memory */ +int gRampacSaveSector = 0; /* Rampac emulation Sector number */ +int gRampacSaveCounter = 0; /* Rampac emulation Counter */ +unsigned char *gRampacSaveSectPtr = 0;/* Pointer to current Sector memory */ + +int gIndex[65536]; unsigned char get_memory8(unsigned short address) { - return memory[address]; + if (gReMem) + return gMemory[address >> 10][address & 0x3FF]; + else + return gBaseMemory[address]; } unsigned short get_memory16(unsigned short address) { - return memory[address] + (memory[address+1] << 8); + if (gReMem) + return gMemory[address>>10][address&0x3FF] + (gMemory[(address+1)>>10][(address+1)&0x3FF] << 8); + else + return gBaseMemory[address] + (gBaseMemory[address+1] << 8); } void set_memory8(unsigned short address, unsigned char data) { - memory[address] = data;; + remem_set8(address, data); } void set_memory16(unsigned short address, unsigned short data) { - memory[address] = data & 0xFF; - memory[address+1] = data >> 8; + remem_set8(address, (unsigned char) (data & 0xFF)); + remem_set8(address+1, (unsigned char) (data >> 8)); } /* @@ -80,38 +95,40 @@ get_memory8_ext: This routine reads the specified number of bytes void get_memory8_ext(int region, long address, int count, unsigned char *data) { int addr; - int c, x; - int start_1k, end_1k; // 1K Block address for start & end of copy - unsigned short map; - int mapped; + int c; int cp_ptr; unsigned char *ptr; - int limit; switch (region) { case REGION_RAM: addr = RAMSTART + address; for (c = 0; c < count; c++) - data[c] = memory[addr++]; + { + data[c] = gMemory[addr>>10][addr&0x3FF]; + addr++; + } break; case REGION_ROM: addr = address; for (c = 0; c < count; c++) - data[c] = memory[addr++]; + { + data[c] = gMemory[addr>>10][addr&0x3FF]; + addr++; + } break; case REGION_ROM2: addr = address; for (c = 0; c < count; c++) - data[c] = msplanROM[addr++]; + data[c] = gMsplanROM[addr++]; break; case REGION_OPTROM: addr = address; for (c = 0; c < count; c++) - data[c] = optROM[addr++]; + data[c] = gOptROM[addr++]; break; case REGION_RAM1: @@ -120,7 +137,10 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) { addr = address + RAMSTART; for (c = 0; c < count; c++) - data[c] = memory[addr++]; + { + data[c] = gMemory[addr>>10][addr&0x3FF]; + addr++; + } } else { @@ -136,7 +156,10 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) { addr = address + RAMSTART; for (c = 0; c < count; c++) - data[c] = memory[addr++]; + { + data[c] = gMemory[addr>>10][addr&0x3FF]; + addr++; + } } else { @@ -155,7 +178,10 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) { addr = address + RAMSTART; for (c = 0; c < count; c++) - data[c] = memory[addr++]; + { + data[c] = gMemory[addr>>10][addr&0x3FF]; + addr++; + } } else { @@ -194,129 +220,21 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) if ((gReMemRam == NULL) || (gReMemFlash1 == NULL) || (gReMemFlash2 == NULL)) break; - // Check ReMem emulation mode - if (gReMemMode & REMEM_MODE_NORMAL) - { - // Check if copy crosses 1K block boundries - start_1k = address / 1024; - end_1k = (address + count) / 1024; - - // Indicate zero bytes copied so far - cp_ptr = 0; - - // Loop for each 1K block & copy data - for (x = start_1k; x <= end_1k; x++) - { - // Calculate ReMemMap value to search for to test if - // this block is mapped to system memory - if (region == REGION_REMEM_RAM) - { - map = REMEM_VCTR_FLASH1_CS | REMEM_VCTR_FLASH2_CS; - ptr = gReMemRam; - } - else if (region == REGION_FLASH1) - { - map = REMEM_VCTR_RAM_CS | REMEM_VCTR_FLASH2_CS; - ptr = gReMemFlash1; - } - else - { - map = REMEM_VCTR_RAM_CS | REMEM_VCTR_FLASH1_CS; - ptr = gReMemFlash2; - } - map |= x; + // Indicate zero bytes copied so far + cp_ptr = 0; - // Loop through all maps and test if this block mapped - mapped = FALSE; - for (c = 0; c < 64; c++) - { - if ((gReMemMap[c] & ~(REMEM_VCTR_READ_ONLY | REMEM_VCTR_MMU_ACTIVE)) == map) - { - mapped = TRUE; - break; - } - } + // Determine which location to copy memory from + if (region == REGION_REMEM_RAM) + ptr = gReMemRam; + else if (region == REGION_FLASH1) + ptr = gReMemFlash1; + else + ptr = gReMemFlash2; - // Check if copy is from System Memory or ReMem memory - if (mapped) - { - // Block is mapped -- copy from system memory - addr = (address - x*1024) + c * 1024; - for (; (cp_ptr < count) && (addr < (c+1)*1024); cp_ptr++) - data[cp_ptr] = memory[addr++]; - } - else - { - // Block is not mapped -- copy from appropriate allocation - addr = address + cp_ptr; - for (;(cp_ptr < count) & (addr < (x+1)*1024); cp_ptr++) - data[cp_ptr] = ptr[addr++]; - } - } - } - else - { - // Get pointer to correct memory space - if (region == REGION_REMEM_RAM) - ptr = gReMemRam; - else if (region == REGION_FLASH1) - ptr = gReMemFlash1; - else if (region == REGION_FLASH2) - ptr = gReMemFlash2; - - addr = address; - cp_ptr = 0; - - // ReMem Normal mode enabled - if (gModel == MODEL_T200) - limit = 40960; - else - limit = 32768; - - // Test if reading from "ROM" space - if (addr < limit) - { - // If reading from Flash1 space, read system memory instead - if (region == REGION_FLASH1) - { - // Copy bytes from the system memory - for (; (cp_ptr < count) && (addr < limit); cp_ptr++) - data[cp_ptr] = memory[addr++]; - } - // Test if copying to RAM below the "Normal" region - else - { - // Copy bytes up to the limit from allocation - for (; (cp_ptr < count) && (addr < limit); cp_ptr++) - data[cp_ptr] = ptr[addr++]; - } - } - - // Test if reading from "RAM" space - if ((addr >= limit) && (addr < 65536)) - { - if (region == REGION_REMEM_RAM) - { - // Copy bytes from the System RAM between limit and 64K - for (; (cp_ptr < count) && (addr < 65536) ; cp_ptr++) - data[cp_ptr] = memory[addr++]; - } - else - { - // Copy remainder of bytes above 64K from allocation - for (; cp_ptr < count; cp_ptr++) - data[cp_ptr] = ptr[addr++]; - } - } - - // Copy bytes that are above Normal "RAM" locations - if (addr >= 65536) - { - // Copy all bytes directly if Flash2 - for (; cp_ptr < count; cp_ptr++) - data[cp_ptr] = ptr[addr++]; - } - } + // Block is not mapped -- copy from 2Meg Region (RAM or FLASH) + addr = address; + for (;(cp_ptr < count); cp_ptr++) + data[cp_ptr] = ptr[addr++]; break; } } @@ -330,38 +248,42 @@ set_memory8_ext: This routine writes the specified number of bytes void set_memory8_ext(int region, long address, int count, unsigned char *data) { int addr; - int c, x; - int start_1k, end_1k; // 1K Block address for start & end of copy + int c; unsigned short map; - int mapped; int cp_ptr; unsigned char *ptr; - int limit; + int map_changed = 0; switch (region) { case REGION_RAM: addr = RAMSTART + address; for (c = 0; c < count; c++) - memory[addr++] = data[c]; + { + gMemory[addr>>10][addr&0x3FF] = data[c]; + addr++; + } break; case REGION_ROM: addr = address; for (c = 0; c < count; c++) - memory[addr++] = data[c]; + { + gMemory[addr>>10][addr&0x3FF] = data[c]; + addr++; + } break; case REGION_ROM2: addr = address; for (c = 0; c < count; c++) - msplanROM[addr++] = data[c]; + gMsplanROM[addr++] = data[c]; break; case REGION_OPTROM: addr = address; for (c = 0; c < count; c++) - optROM[addr++] = data[c]; + gOptROM[addr++] = data[c]; break; case REGION_RAM1: @@ -370,7 +292,10 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) { addr = address + RAMSTART; for (c = 0; c < count; c++) - memory[addr++] = data[c]; + { + gMemory[addr>>10][addr&0x3FF] = data[c]; + addr++; + } } else { @@ -386,7 +311,10 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) { addr = address + RAMSTART; for (c = 0; c < count; c++) - memory[addr++] = data[c]; + { + gMemory[addr>>10][addr&0x3FF] = data[c]; + addr++; + } } else { @@ -405,7 +333,10 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) { addr = address + RAMSTART; for (c = 0; c < count; c++) - memory[addr++] = data[c]; + { + gMemory[addr>>10][addr&0x3FF] = data[c]; + addr++; + } } else { @@ -445,63 +376,36 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) break; // Check ReMem emulation mode - if (gReMemMode & REMEM_MODE_NORMAL) + // If REMEM_MODE_NORMAL bit is set then ReMem is mapping 1K + // blocks of memory to the 64K address space + if ((gReMemMode & REMEM_MODE_NORMAL) && (region == REGION_REMEM_RAM)) { - // Check if copy crosses 1K block boundries - start_1k = address / 1024; - end_1k = (address + count) / 1024; - // Indicate zero bytes copied so far cp_ptr = 0; + addr = address; + + // Calculate ReMemMap value to search for to test if + map = REMEM_VCTR_FLASH1_CS | REMEM_VCTR_FLASH2_CS; + ptr = gReMemRam; - // Loop for each 1K block & copy data - for (x = start_1k; x <= end_1k; x++) + /* Loop for each byte and copy to RAM. If byte is in MMU space */ + /* we must update the mapping tables */ + for (cp_ptr = 0; cp_ptr < count; cp_ptr++) { - // Calculate ReMemMap value to search for to test if - // this block is mapped to system memory - if (region == REGION_REMEM_RAM) - { - map = REMEM_VCTR_FLASH1_CS | REMEM_VCTR_FLASH2_CS; - ptr = gReMemRam; - } - else if (region == REGION_FLASH1) - { - map = REMEM_VCTR_RAM_CS | REMEM_VCTR_FLASH2_CS; - ptr = gReMemFlash1; - } - else - { - map = REMEM_VCTR_RAM_CS | REMEM_VCTR_FLASH1_CS; - ptr = gReMemFlash2; - } - map |= x; + /* Determine if address is part of MMU */ + if ((addr >= REMEM_MAP_OFFSET) && (addr <= (REMEM_MAP_OFFSET + REMEM_MAP_SIZE * 8))) + /* Indiacte possible map chage */ + map_changed = 1; - // Loop through all maps and test if this block mapped - mapped = FALSE; - for (c = 0; c < 64; c++) - { - if ((gReMemMap[c] & ~(REMEM_VCTR_READ_ONLY | REMEM_VCTR_MMU_ACTIVE)) == map) - { - mapped = TRUE; - break; - } - } + /* Copy the data to RAM */ + ptr[addr++] = data[cp_ptr]; + } - // Check if copy is from System Memory or ReMem memory - if (mapped) - { - // Block is mapped -- copy from system memory - addr = (address - x*1024) + c * 1024; - for (; (cp_ptr < count) && (addr < (c+1)*1024); cp_ptr++) - memory[addr++] = data[cp_ptr]; - } - else - { - // Block is not mapped -- copy from appropriate allocation - addr = address + cp_ptr; - for (;(cp_ptr < count) & (addr < (x+1)*1024); cp_ptr++) - ptr[addr++] = data[cp_ptr]; - } + /* Check if map changed above and update vectors if it did */ + if (map_changed) + { + remem_update_vectors(gReMemMode); + remem_copy_mmu_to_system(); } } else @@ -515,57 +419,10 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) ptr = gReMemFlash2; addr = address; - cp_ptr = 0; - - // ReMem Normal mode enabled - if (gModel == MODEL_T200) - limit = 40960; - else - limit = 32768; - - // Test if reading from "ROM" space - if (addr < limit) - { - // If reading from Flash1 space, read system memory instead - if (region == REGION_FLASH1) - { - // Copy bytes from the system memory - for (; (cp_ptr < count) && (addr < limit); cp_ptr++) - memory[addr++] = data[cp_ptr]; - } - // Test if copying to RAM below the "Normal" region - else - { - // Copy bytes up to the limit from allocation - for (; (cp_ptr < count) && (addr < limit); cp_ptr++) - ptr[addr++] = data[cp_ptr]; - } - } - - // Test if reading from "RAM" space - if ((addr >= limit) && (addr < 65536)) - { - if (region == REGION_REMEM_RAM) - { - // Copy bytes from the System RAM between limit and 64K - for (; (cp_ptr < count) && (addr < 65536) ; cp_ptr++) - memory[addr++] = data[cp_ptr]; - } - else - { - // Copy remainder of bytes above 64K from allocation - for (; cp_ptr < count; cp_ptr++) - ptr[addr++] = data[cp_ptr]; - } - } - // Copy bytes that are above Normal "RAM" locations - if (addr >= 65536) - { - // Copy all bytes directly if Flash2 - for (; cp_ptr < count; cp_ptr++) - ptr[addr++] = data[cp_ptr]; - } + // Copy bytes up to the limit to allocation + for (cp_ptr = 0; cp_ptr < count; cp_ptr++) + ptr[addr++] = data[cp_ptr]; } break; } @@ -580,11 +437,15 @@ init_mem: This routine initialized the Memory subsystem. It takes void init_mem(void) { int c, size; + int next = 32; /* Set gReMem and gRampac based on preferences */ gReMem = (mem_setup.mem_mode == SETUP_MEM_REMEM) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC); gRampac = (mem_setup.mem_mode == SETUP_MEM_RAMPAC) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC); + for (c = 0; c < 65536; c++) + gIndex[c] = c >> 10; + /* Test if ReMem emulation enabled */ if (gReMem) { @@ -607,6 +468,22 @@ void init_mem(void) gReMemFlash2[c] = 0; } } + + remem_copy_normal_to_system(); + + /* Initialize Rampac I/O mode access variables */ + gReMemMode = 0; + gReMemSector = 0; + gReMemCounter = 0; + gReMemSectPtr = (unsigned char *) (gReMemRam + REMEM_MAP_OFFSET); + } + else + { + for (c = 0; c < ROMSIZE/1024; c++) + gMemory[c] = &gSysROM[c*1024]; + + for (; c < 64; c++) + gMemory[c] = &gBaseMemory[next++ * 1024]; } /* Test if Rampac emulation enabled */ @@ -625,9 +502,38 @@ void init_mem(void) for (c = 0; c < size; c++) gRampacRam[c] = 0; } + + /* Initialize Rampac mode access variables */ + gRampacSector = 0; + gRampacCounter = 0; + gRampacSectPtr = gRampacRam; + + } +} + +void reinit_mem(void) +{ + /* Check if ReMem emulation on */ + if (gReMem) + { + gReMemMode = 0; + gReMemSector = 0; + gReMemCounter = 0; + gReMemSectPtr = (unsigned char *) (gReMemRam + REMEM_MAP_OFFSET); + + remem_copy_normal_to_system(); } + else + { + memcpy(gBaseMemory,gSysROM,ROMSIZE); + } + + gRamBank = 0; + gRomBank = 0; + } + /* ======================================================================== free_remem_mem: This routine frees the memory used by the ReMem @@ -645,6 +551,9 @@ void free_remem_mem(void) gReMemRam = 0; gReMemFlash1 = 0; gReMemFlash2 = 0; + + gReMemMapLower = 0; + gReMemMapLower = 0; } /* @@ -777,13 +686,10 @@ void save_ram(void) { case MODEL_M100: /* M100 & M102 have single bank */ case MODEL_M102: - fwrite(memory+RAMSTART, 1, RAMSIZE, fd); + fwrite(gBaseMemory+RAMSTART, 1, RAMSIZE, fd); break; case MODEL_T200: - /* Update rambanks array with current memory bank */ - memcpy(&rambanks[gRamBank*24576], &memory[RAMSTART], RAMSIZE); - /* Save RAM */ fwrite(rambanks, 1, 3*RAMSIZE, fd); @@ -794,9 +700,6 @@ void save_ram(void) case MODEL_PC8201: case MODEL_PC8300: - /* Update rambanks array with current memory bank */ - memcpy(&rambanks[gRamBank*RAMSIZE], &memory[RAMSTART], RAMSIZE); - /* Save RAM */ fwrite(rambanks, 1, 3*RAMSIZE, fd); @@ -832,7 +735,8 @@ load_remem_ram: This routine loads the ReMem emulation RAM from the void load_remem_ram(void) { FILE *fd; - int size; + int size, x; + int empty = 1; /* Open ReMem file */ fd = fopen(mem_setup.remem_file, "rb+"); @@ -852,6 +756,25 @@ void load_remem_ram(void) /* Close the file */ fclose(fd); } + + /* Test if ReMem FLASH "Normal" region is empty */ + for (x = 0; x < 10; x++) + { + /* Check for any non-zero bytes in normal ROM area */ + if (gReMemFlash1[x] != 0) + empty = 0; + } + + if (empty) + { + /* Rom area is empty - initialize with SYSROM */ + for (x = 0; x < ROMSIZE; x++) + gReMemFlash1[x] = gSysROM[x]; + } + + /* Initalize MsplanROM area */ + for (x = 0; x < sizeof(gMsplanROM); x++) + gReMemFlash1[0x10000 + x] = gMsplanROM[x]; } /* @@ -898,14 +821,19 @@ void load_ram(void) { char file[256]; FILE *fd; + int x; /* Check if ReMem emulation enabled or Base Memory emulation */ if (gReMem) { load_remem_ram(); /* Call routine to load ReMem */ + remem_copy_normal_to_system(); } else { + for (x = 0; x < 64; x++) + gMemory[x] = 0; + /* First get the emulation path */ get_emulation_path(file, gModel); @@ -922,7 +850,7 @@ void load_ram(void) { case MODEL_M100: /* M100 & M102 have single bank */ case MODEL_M102: - fread(memory+RAMSTART, 1, RAMSIZE, fd); + fread(gBaseMemory+RAMSTART, 1, RAMSIZE, fd); break; case MODEL_T200: @@ -937,7 +865,7 @@ void load_ram(void) gRamBank = 0; /* Seek to the correct location for this bank */ - memcpy(&memory[RAMSTART], &rambanks[gRamBank*24576], RAMSIZE); + memcpy(&gBaseMemory[RAMSTART], &rambanks[gRamBank*24576], RAMSIZE); /* Update Hardware with Bank */ io_set_ram_bank(gRamBank); @@ -958,7 +886,7 @@ void load_ram(void) gRamBank = 0; /* Seek to the correct location for this bank */ - memcpy(&memory[RAMSTART], &rambanks[gRamBank*RAMSIZE], RAMSIZE); + memcpy(&gBaseMemory[RAMSTART], &rambanks[gRamBank*RAMSIZE], RAMSIZE); /* Update Hardware with RAM Bank */ io_set_ram_bank(gRamBank); @@ -996,7 +924,7 @@ void load_opt_rom(void) char buf[65536]; // Clear the option ROM memory - memset(optROM,0,OPTROMSIZE); + memset(gOptROM,0,OPTROMSIZE); // Check if an option ROM is loaded if ((len = strlen(gsOptRomFile)) == 0) @@ -1016,7 +944,17 @@ void load_opt_rom(void) // Copy data to optROM for (c = 0; c < len; c++) - optROM[c] = buf[c]; + gOptROM[c] = buf[c]; + + if (gReMem) + { + if (gModel == MODEL_T200) + for (c = 0; c < len; c++) + gReMemFlash1[0x20000 + c] = buf[c]; + else + for (c = 0; c < len; c++) + gReMemFlash1[0x10000 + c] = buf[c]; + } } else @@ -1025,7 +963,7 @@ void load_opt_rom(void) fd=fopen(gsOptRomFile,"rb"); if(fd!=0) { - fread(optROM,1, OPTROMSIZE, fd); + fread(gOptROM,1, OPTROMSIZE, fd); fclose(fd); } } @@ -1050,9 +988,9 @@ void set_ram_bank(unsigned char bank) case MODEL_T200: /* Model T200 RAM banks */ case MODEL_PC8201: /* NEC Laptop banks */ case MODEL_PC8300: - memcpy(&rambanks[gRamBank*RAMSIZE], &memory[RAMSTART], RAMSIZE); + memcpy(&rambanks[gRamBank*RAMSIZE], &gBaseMemory[RAMSTART], RAMSIZE); gRamBank = bank; - memcpy(&memory[RAMSTART], &rambanks[gRamBank*RAMSIZE], RAMSIZE); + memcpy(&gBaseMemory[RAMSTART], &rambanks[gRamBank*RAMSIZE], RAMSIZE); } } else @@ -1061,18 +999,9 @@ void set_ram_bank(unsigned char bank) if (gModel == MODEL_T200) { /* Write all RAM bank blocks back to ReMem memory */ - if (!(gReMemMode & REMEM_MODE_NORMAL)) - { - /* Copy system to normal mode ReMem RAM */ - remem_copy_system_to_normal(); - } - else + if (gReMemMode & REMEM_MODE_NORMAL) { - /* Loop through 24 1K RAM Blocks */ - for (block = 40; block < 64; block++) - remem_copy_block_to_mmu(block); - - /* Now set the new RAM bank */ + /* Set the new RAM bank */ gRamBank = bank; remem_update_vectors(gReMemMode); @@ -1102,29 +1031,24 @@ void set_rom_bank(unsigned char bank) { case MODEL_M100: /* Model 100 / 102 emulation */ case MODEL_M102: + gRomBank = bank; if (bank & 0x01) - { - memcpy(memory,optROM,ROMSIZE); - cROM=1; - } + memcpy(gBaseMemory,gOptROM,ROMSIZE); else - { - memcpy(memory,sysROM,ROMSIZE); - cROM=0; - } + memcpy(gBaseMemory,gSysROM,ROMSIZE); break; case MODEL_T200: /* Model 200 emulation */ gRomBank = bank; switch (bank) { case 0: - memcpy(memory,sysROM,ROMSIZE); + memcpy(gBaseMemory,gSysROM,ROMSIZE); break; case 1: - memcpy(memory, msplanROM, sizeof(msplanROM)); + memcpy(gBaseMemory, gMsplanROM, sizeof(gMsplanROM)); break; case 2: - memcpy(memory,optROM,sizeof(optROM)); + memcpy(gBaseMemory,gOptROM,sizeof(gOptROM)); break; } break; @@ -1136,16 +1060,16 @@ void set_rom_bank(unsigned char bank) switch (bank) { case 0: /* System ROM bank */ - memcpy(memory,sysROM,ROMSIZE); + memcpy(gBaseMemory,gSysROM,ROMSIZE); break; case 1: /* Option ROM bank */ - memcpy(memory,optROM,ROMSIZE); + memcpy(gBaseMemory,gOptROM,ROMSIZE); break; case 2: /* RAM banks */ case 3: - memcpy(memory,&rambanks[(bank-1)*RAMSIZE],RAMSIZE); + memcpy(gBaseMemory,&rambanks[(bank-1)*RAMSIZE],RAMSIZE); break; } break; @@ -1153,27 +1077,29 @@ void set_rom_bank(unsigned char bank) } else { + gRomBank = bank; + /* Write all ROM bank blocks back to ReMem memory */ if (gReMemMode & REMEM_MODE_NORMAL) { /* Calculate number of ROM blocks base on model */ blocks = gModel == MODEL_T200 ? 40 : 32; - /* Loop through all 1K ROM Blocks & copy from system to MMU */ - for (block = 0; block < blocks; block++) - remem_copy_block_to_mmu(block); - /* Now set the new RAM bank */ if (gModel == MODEL_T200) gRomBank = bank; else - cROM = bank & 0x01; + gRomBank = bank & 0x01; remem_update_vectors(gReMemMode); /* Loop through all 1K ROM Blocks & copy to system memory */ for (block = 0; block < blocks; block++) remem_copy_mmu_to_block(block); } + else + { + remem_copy_normal_to_system(); + } } } @@ -1189,25 +1115,156 @@ remem_set8: This function services memory writes while in ReMem emulation void remem_set8(unsigned int address, unsigned char data) { int block; /* Which 1K block is being accessed */ + int mmuBlock; /* Block with MMU that is being modified */ + int bank; /* Bank with map that is being modified */ + int romBank; /* The currently mapped romBank within the Map */ + int ramBank; /* The currently mapped ramBank within the Map */ /* Calculate which block is being accessed */ - block = address >> 11; +// block = address >> 10; + block = gIndex[address]; /* Test if ReMem memory block is read-only */ - if (gReMemMap[block] & REMEM_VCTR_READ_ONLY) + if ((gReMemMode & REMEM_MODE_NORMAL) && (gReMemMap[block] & REMEM_VCTR_READ_ONLY)) return; /* Test if accessing MMU vector for current map */ if (gReMemMap[block] & REMEM_VCTR_MMU_ACTIVE) { /* Need to validate that address is accssing active portion of MMU page */ + if (((address & 0x3FF) >= gReMemMapLower) && ((address & 0x3FF) < gReMemMapUpper)) + { + /* System is making a change to the active MAP!! Now we need to determine if */ + /* The portion of the map being modified is selected by the current ROM/RAM */ + /* bank settings */ + bank = block / REMEM_BANK_SIZE; + romBank = gModel == MODEL_T200 ? gRomBank : gRomBank << 1; + ramBank = gModel == MODEL_T200 ? gRamBank : 1; + + /* First validate that the data is actually changing */ + if (gMemory[block][address&0x3FF] == data) + return; + + /* Okay, data is really changing first update system memory */ + gMemory[block][address&0x3FF] = data; + + /* Determine if the change was made in a mapped bank ROM or RAM */ + if ((bank != romBank) && (bank != ramBank)) + return; + + /* Determine which map entry was modified */ + mmuBlock = ((address & 0x3FF) - gReMemMapLower - (bank * REMEM_BANK_SIZE)) >> 1; + + /* Update the gReMemMap vector table for this block */ + if (address & 0x01) + gReMemMap[mmuBlock] = (gReMemMap[mmuBlock] & 0x00FF) | (data << 8); + else + gReMemMap[mmuBlock] = (gReMemMap[mmuBlock] & 0xFF00) | data; + + /* Now copy new block to system memory */ + remem_copy_mmu_to_block(mmuBlock); + + return; + } } /* Update memory with data */ - memory[address] = data; + gMemory[block][address & 0x3FF] = data; } +/* +============================================================================= +remem_in: This function services in operations to the ReMem emulation. + ReMem uses port I/O for configuration of memory maps, etc. +============================================================================= +*/ +int remem_in(unsigned char port, unsigned char *data) +{ + int ret = 0; /* Indicate if port serviced or not */ + int map; + + /* Test if ReMem emulation is enabled */ + if (!(gReMem | gRampac) || (gReMemRam == 0)) + return 0; + + /* Process port number being accessed */ + switch (port) + { + + case REMEM_MODE_PORT: /* ReMem mode port */ + *data = gReMemMode; /* Return the current ReMem mode */ + ret = 1; /* Indicate port processed */ + break; + + case REMEM_REVID_PORT: /* ReMem Firmware Rev being emulated */ + *data = (unsigned char) REMEM_REV; /* Provide emulation level */ + ret = 1; /* Indicate port processed */ + break; + + case REMEM_SECTOR_PORT: /* ReMem I/O Sector number */ + *data = gReMemSector; /* Provide current sector number */ + ret = 1; /* Indicate port processed */ + break; + + case REMEM_DATA_PORT: /* ReMem Data Port */ + if (gReMemSectPtr != NULL) + { + *data = *gReMemSectPtr++; /* Get data at current Sector Pointer */ + /* Update the ReMem Counter and Sector */ + gReMemCounter++; /* Increment Sector Counter */ + if (gReMemCounter >= REMEM_BANK_SIZE) + { + /* Get the map number */ + map = (gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT; + + gReMemSector++; /* Increment to next sector */ + gReMemCounter = 0; /* Clear sector counter */ + gReMemSectPtr = (unsigned char *) (gReMemRam + REMEM_MAP_OFFSET + + map * REMEM_MAP_SIZE + gReMemSector * REMEM_BANK_SIZE); + } + } + else + *data = 0xCC; /* Code to indicate unallocated memory */ + ret = 1; /* Indicate port processed */ + break; + + case RAMPAC_SECTOR_PORT: /* RamPac I/O Sector number */ + *data = gRampacSector; /* Provide current Rampac Sector */ + ret = 1; /* Indicate port processed */ + break; + + case RAMPAC_DATA_PORT: /* Rampac I/O Data port */ + if (gRampacSectPtr != NULL) + { + *data = *gRampacSectPtr++;/* Proivde data at current sector/counter */ + + /* Update Counter */ + if (++gRampacCounter >= RAMPAC_SECTOR_SIZE) + { + /* Clear counter and move to next sector */ + gRampacCounter = 0; + if (++gRampacSector >= RAMPAC_SECTOR_COUNT) + { + /* Past end of RAM, reset to start */ + gRampacSector = 0; + if (gReMem && (gReMemMode & REMEM_MODE_RAMPAC)) + gRampacSectPtr = gReMemRam + REMEM_RAMPAC_OFFSET; + else + gRampacSectPtr = gRampacRam; + } + } + } + else + *data = 0xCC; /* Code to indicate unallocated memory */ + ret = 1; /* Indicate port processed */ + break; + + } + + return ret; +} + /* ============================================================================= remem_out: This function services out operations to the ReMem emulation. @@ -1218,10 +1275,11 @@ int remem_out(unsigned char port, unsigned char data) { int ret = 0; /* Indicate if port serviced or not */ int romSector, ramSector; - int bank; + int bank, block, mmuBlock; + int map; /* Test if ReMem emulation is enabled */ - if (!gReMem || (gReMemRam == 0)) + if (!(gReMem | gRampac) || (gReMemRam == 0)) return 0; /* Process port number being accessed */ @@ -1237,115 +1295,221 @@ int remem_out(unsigned char port, unsigned char data) /* ====================================================================== - First copy existing system memory to ReMem memory + First check to see if we are enabling MMU mode ====================================================================== */ - - /* Test if changing from normal mode to ReMem mode */ - if ((data & REMEM_MODE_NORMAL) != (gReMemMode & REMEM_MODE_NORMAL)) + if (data & REMEM_MODE_NORMAL) { - /* Save system memory to ReMem "Normal mode" memory */ - if (!(gReMemMode & REMEM_MODE_NORMAL)) - remem_copy_system_to_normal(); - } - /* Test if the MAP selection is being changed */ - else if ((data & REMEM_MODE_MAP_BITS) != (gReMemMode & REMEM_MODE_MAP_BITS)) - { - /* Copy system memory blocks to ReMem blocks */ - if (gReMemMode & REMEM_MODE_NORMAL) - remem_copy_system_to_mmu(); + /* Calculate ReMem Map vector pointer */ + remem_update_vectors(data); } - /* Calculate ReMem Map vector pointer */ - remem_update_vectors(data); - /* ====================================================================== Now copy ReMem memory to system memory ====================================================================== */ /* Test if new mode is "Normal" mode */ - if (!(data & REMEM_MODE_NORMAL)) + if (!(data & REMEM_MODE_NORMAL) && (gReMemMode & REMEM_MODE_NORMAL)) { /* Copy "Normal" ReMem memory space to sysem memory */ remem_copy_normal_to_system(); } - else if ((data & REMEM_MODE_MAP_BITS) != (gReMemMode & REMEM_MODE_MAP_BITS)) + /* Test if changing to MMU mode or MAP changed */ + else if (((data & REMEM_MODE_NORMAL) && !(gReMemMode & REMEM_MODE_NORMAL)) || + ((data & REMEM_MODE_MAP_BITS) != (gReMemMode & REMEM_MODE_MAP_BITS) && + (data & REMEM_MODE_NORMAL))) { /* Copy MMU data to system RAM */ remem_copy_mmu_to_system(); } + /* + ====================================================================== + Check if we are enabling RamPac emulation + ====================================================================== + */ + if ((data & REMEM_MODE_RAMPAC) && ((gReMemMode & REMEM_MODE_RAMPAC) == 0)) + { + /* If Rampac is present, save global variables to restore later */ + if (gRampac) + { + gRampacSaveSector = gRampacSector; + gRampacSaveCounter = gRampacCounter; + gRampacSaveSectPtr = gRampacSectPtr; + } + + gRampacSector = 0; /* Initialize sector number */ + gRampacCounter = 0; /* Initialize counter number */ + gRampacSectPtr = gReMemRam + REMEM_RAMPAC_OFFSET; + } + /* Check if we are disabling Rampac emulation */ + else if (((data & REMEM_MODE_RAMPAC) == 0) && (gReMemMode & REMEM_MODE_RAMPAC)) + { + /* If Rampac is present, restore registers from save variables */ + if (gRampac) + { + gRampacSector = gRampacSaveSector; + gRampacCounter = gRampacSaveCounter; + gRampacSectPtr = gRampacSaveSectPtr; + } + else + { + /* Clear all rampac variables */ + gRampacSector = 0; /* Initialize sector number */ + gRampacCounter = 0; /* Initialize counter number */ + gRampacSectPtr = 0; + } + } + /* Update ReMem mode */ gReMemMode = data; break; /* ReMem port for setting the vector access sector */ + case REMEM_REVID_PORT: + ret = 1; + break; + case REMEM_SECTOR_PORT: - /* Test if ReMem emulation enabled */ - if (!gReMem) - break; + /* Test if MMU I/O Enable mode is set */ + if (gReMemMode & REMEM_MODE_IOENABLE) + { + /* Store new value for ReMemSector & Clear counter */ + gReMemSector = data; /* Update Sector number */ + gReMemCounter = 0; /* Clear the ReMem counter */ - gReMemSector = data; /* Update Sector number */ - gReMemCounter = 0; /* Clear the ReMem counter */ - gReMemSectPtr = (unsigned char *) (gReMemRam + gReMemSector * REMEM_BANK_SIZE); - ret = 1; /* Indicate Port I/O processed */ + /* Get the map number */ + map = (gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT; + + /* Calculate pointer to actual RAM storage for this sector */ + gReMemSectPtr = (unsigned char *) (gReMemRam + REMEM_MAP_OFFSET + + map * REMEM_MAP_SIZE + gReMemSector * REMEM_BANK_SIZE); + } + ret = 1; break; /* ReMem port for writing vector data */ - case REMEM_VCTR_PORT: - /* Insure ReMem enabled */ - if (!gReMem) - break; + case REMEM_DATA_PORT: + /* First check if RamPac Mode enabled */ + if (gReMemMode & REMEM_MODE_IOENABLE) + { + /* Calculate ReMem Vector block based on current ReMemCounter */ + block = (gReMemCounter >> 1) + gReMemSector * REMEM_BLOCKS_PER_BANK; + + /* Check if MMU mode is enabled. If it is, we may need to dynamically */ + /* load and unload blocks from system memory to ReMem Memory as a */ + /* Result of the I/O update */ + if (gReMemMode & REMEM_MODE_NORMAL) + { + /* MMU mode is enabled - Test if update changes mapped block */ - /* Calculate current MMU ROM bank */ - bank = gModel == MODEL_T200 ? gRomBank : cROM; + /* Calculate current MMU ROM bank */ + bank = gModel == MODEL_T200 ? gRomBank : gRomBank << 1; - /* Convert current MMU map / ROM bank to sector format */ - romSector = ((gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT) * - REMEM_BANKS_PER_MAP + bank; + /* Convert current MMU map / ROM bank to sector format */ + romSector = ((gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT) * + REMEM_BANKS_PER_MAP + bank; - /* Calculate current MMU RAM bank */ - bank = gModel == MODEL_T200 ? gRamBank : 1; + /* Calculate current MMU RAM bank */ + bank = gModel == MODEL_T200 ? gRamBank : 1; - /* Convert current MMU map / ROM bank to sector format */ - ramSector = ((gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT) * - REMEM_BANKS_PER_MAP + bank; + /* Convert current MMU map / ROM bank to sector format */ + ramSector = ((gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT) * + REMEM_BANKS_PER_MAP + bank; - /* Test if Current ReMem Sector same as current ReMem Map/Bank selection */ - if ((gReMemSector == romSector) || (gReMemSector == ramSector)) - { - /* Copy system memory to ReMem memory */ - remem_copy_block_to_mmu(gReMemCounter >> 1); + /* Test if Current ReMem Sector same as current ReMem Map/Bank selection */ + /* If it is, this means we are writing to an actively mapped bank and */ + /* Need to swap the memory to/from system RAM */ + if ((gReMemSector == romSector) || (gReMemSector == ramSector)) + { + /* Swap memory in/out only if data actually changes */ + if (*gReMemSectPtr != data) + { + /* Update ReMem Vector table */ + if (gReMemCounter & 0x01) + gReMemMap[block] = (gReMemMap[block] & 0x00FF) | (data << 8); + else + gReMemMap[block] = (gReMemMap[block] & 0xFF00) | data; + + /* Check if new assignment maps the MMU bank to system memory */ + map = (gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT; + mmuBlock = (unsigned short) ((REMEM_MAP_OFFSET + map * REMEM_MAP_SIZE) >> 10); + + if ((gReMemMap[block] & REMEM_VCTR_ADDRESS) == mmuBlock) + { + gReMemMap[block] |= REMEM_VCTR_MMU_ACTIVE; + gReMemMapLower = (map & 0x02) * REMEM_MAP_SIZE; + gReMemMapUpper = ((map & 0x02) + 1) * REMEM_MAP_SIZE; + } + + /* Copy new MMU data to system based on new vector */ + remem_copy_mmu_to_block(block); + } + } + } - /* Update ReMem MMU */ - *gReMemSectPtr = data; + /* Update ReMem MAP RAM with new value */ + *gReMemSectPtr++ = data; - /* Copy new MMU data to system */ - remem_copy_mmu_to_block(gReMemCounter >> 1); - } + /* Update the ReMem Counter and Sector */ + gReMemCounter++; /* Increment Sector Counter */ + if (gReMemCounter >= REMEM_BANK_SIZE) + { + /* Get the map number */ + map = (gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT; - /* Write vector data to ReMem RAM */ - *gReMemSectPtr++ = data; - gReMemCounter++; /* Increment Sector Counter */ - if (gReMemCounter >= REMEM_BANK_SIZE) - { - gReMemSector++; /* Increment to next sector */ - gReMemCounter = 0; /* Clear sector counter */ - gReMemSectPtr = (unsigned char *) (gReMemRam + gReMemSector * REMEM_BANK_SIZE); + gReMemSector++; /* Increment to next sector */ + gReMemCounter = 0; /* Clear sector counter */ + gReMemSectPtr = (unsigned char *) (gReMemRam + REMEM_MAP_OFFSET + + map * REMEM_MAP_SIZE + gReMemSector * REMEM_BANK_SIZE); + } } ret = 1; /* Indicate Port I/O processed */ break; - /* RamPac Set Vector port */ + /* RamPac Write Byte port */ case RAMPAC_SECTOR_PORT: - ret = 1; + /* Store new value for RampacSector & Clear counter */ + gRampacSector = data; /* Update Sector for Rampac */ + gRampacCounter = 0; /* Clear Rampac counter */ + + /* Initialize pointer to memory based on emulation mode */ + if (gReMem && (gReMemMode & REMEM_MODE_RAMPAC)) + gRampacSectPtr = gReMemRam + REMEM_RAMPAC_OFFSET + + gRampacSector * RAMPAC_SECTOR_SIZE; + else if (gRampac) + gRampacSectPtr = gRampacRam + gRampacSector * RAMPAC_SECTOR_SIZE; + + ret = 1; /* Indicate Port I/O processed */ break; /* RamPac Write Byte port */ case RAMPAC_DATA_PORT: + if (gRampacSectPtr != NULL) + { + /* Save data in Ram */ + *gRampacSectPtr++ = data; + + /* Update Counter */ + if (++gRampacCounter >= RAMPAC_SECTOR_SIZE) + { + /* Clear counter and move to next sector */ + gRampacCounter = 0; + if (++gRampacSector >= RAMPAC_SECTOR_COUNT) + { + /* Past end of RAM, reset to start */ + gRampacSector = 0; + if (gReMem && (gReMemMode & REMEM_MODE_RAMPAC)) + gRampacSectPtr = gReMemRam + REMEM_RAMPAC_OFFSET; + else + gRampacSectPtr = gRampacRam; + } + } + } + ret = 1; break; @@ -1372,7 +1536,6 @@ void remem_update_vectors(unsigned char targetMode) int x; int block; /* Block being updated */ int bank; /* ReMem vector bank being used based on optRom, etc. */ - int offset; /* Offset of RAM vectors within page */ unsigned short mmuBlock; /* Start address of active MMU Map region */ unsigned short *pMapPtr; /* Pointer to ReMem map vectors */ int romBlocks; /* Number of ROM blocks that need to be updated */ @@ -1389,17 +1552,16 @@ void remem_update_vectors(unsigned char targetMode) { /* Calculate location of vectors in ROM map based on Bank selection */ if (x == 0) - bank = gModel == MODEL_T200 ? gRomBank : cROM << 1; + bank = gModel == MODEL_T200 ? gRomBank : gRomBank << 1; else bank = gModel == MODEL_T200 ? gRamBank : 1; - offset = x ? REMEM_RAM_BANK_OFFSET : 0; mmuBlock = (unsigned short) ((REMEM_MAP_OFFSET + map * REMEM_MAP_SIZE + - bank * REMEM_BANK_SIZE + offset) >> 11); + bank * REMEM_BANK_SIZE) >> 10); pMapPtr = (unsigned short *) (gReMemRam + REMEM_MAP_OFFSET + map * REMEM_MAP_SIZE + - bank * REMEM_BANK_SIZE + offset); + bank * REMEM_BANK_SIZE + (x ? REMEM_RAM_MAP_OFFSET : 0)); /* Update ReMem ROM/RAM blocks */ - for (c = 0; c < !x ? romBlocks : ramBlocks; c++) + for (c = 0; c < (!x ? romBlocks : ramBlocks); c++) { gReMemMap[block] = pMapPtr[c]; /* Copy map vector from ReMem RAM */ @@ -1418,8 +1580,12 @@ void remem_update_vectors(unsigned char targetMode) } /* Test if Block being mapped is active MMU Map space */ - if ((gReMemMap[block] & REMEM_VCTR_ADDRESS) == mmuBlock) + if (x && ((gReMemMap[block] & REMEM_VCTR_ADDRESS) == mmuBlock)) + { gReMemMap[block] |= REMEM_VCTR_MMU_ACTIVE; + gReMemMapLower = (map & 0x02) * REMEM_MAP_SIZE; + gReMemMapUpper = ((map & 0x02) + 1) * REMEM_MAP_SIZE; + } /* Increment to next block */ block++; @@ -1435,29 +1601,28 @@ remem_copy_normal_to_system: This function copies memory from "Normal" */ void remem_copy_normal_to_system(void) { - int bytes; /* Number of bytes to copy */ + int blocks; /* Number of blocks to copy */ int c; /* Byte counter */ int dest; /* Destination location */ uchar *pSrc; /* Source address */ /* First copy ROM to system memory */ - bytes = gModel == MODEL_T200 ? gRomBank ? 32768 : 40960 : 32768; + blocks = gModel == MODEL_T200 ? 40 : 32; pSrc = (gReMemBoot ? gReMemFlash2 : gReMemFlash1) + - 0x10000 * (gModel == MODEL_T200 ? gRomBank : cROM); + 0x10000 * gRomBank; dest = 0; /* Copy the ROM bytes */ - for (c = 0; c < bytes; c++) - memory[dest++] = *pSrc++; + for (c = 0; c < blocks; c++) + gMemory[dest++] = &pSrc[c*1024]; /* Now prepare to copy the RAM bytes */ - bytes = gModel == MODEL_T200 ? 24576 : 32768; - pSrc = gReMemRam + 0x10000 * (gModel == MODEL_T200 ? gRamBank : cROM) + - (gModel == MODEL_T200 ? 40960 : 32768); + blocks = gModel == MODEL_T200 ? 24 : 32; + pSrc = gReMemRam + 0x10000 * gRamBank + (gModel == MODEL_T200 ? 40960 : 32768); /* Copy the RAM bytes */ - for (c = 0; c < bytes; c++) - memory[dest++] = *pSrc++; + for (c = 0; c < blocks; c++) + gMemory[dest++] = &pSrc[c*1024]; } /* @@ -1485,112 +1650,22 @@ remem_copy_mmu_to_block: This function copies a 1K block from MMU mode */ void remem_copy_mmu_to_block(int block) { - int c; /* Byte counter */ uchar *pSrc; /* Source pointer */ - int dest; /* Destination pointer */ /* Calculate source pointer based on block vector */ if ((gReMemMap[block] & REMEM_VCTR_RAM_CS) == 0) pSrc = gReMemRam; else if ((gReMemMap[block] & REMEM_VCTR_FLASH1_CS) == 0) pSrc = gReMemFlash1; - else if ((gReMemMap[block] & REMEM_VCTR_FLASH1_CS) == 0) + else if ((gReMemMap[block] & REMEM_VCTR_FLASH2_CS) == 0) pSrc = gReMemFlash2; else return; /* Calculate offset of 1K block */ - pSrc += (gReMemMap[block] & REMEM_VCTR_ADDRESS) << 11; - dest = block * 1024; - - /* Copy bytes */ - for (c = 0; c < 1024; c++) - memory[dest++] = *pSrc++; -} - -/* -============================================================================= -remem_copy_system_to_normal: This function copies memory from System - memory space to "Normal" mode space. -============================================================================= -*/ -void remem_copy_system_to_normal(void) -{ - int bytes; /* Number of bytes to copy */ - int c; /* Byte counter */ - int src; /* Destination location */ - uchar *pDest; /* Source address */ - - /* Copy only the RAM bytes */ - if (gModel == MODEL_T200) - { - bytes = 24576; - pDest = gReMemRam + 0x10000 * gRamBank + 40960; - src = 40960; - } - else - { - bytes = 32768; - pDest = gReMemRam + 0x10000 * cROM + 32768; - src = 32768; - } - - /* Copy the RAM bytes */ - for (c = 0; c < bytes; c++) - *pDest++ = memory[src++]; -} - -/* -============================================================================= -remem_copy_system_to_mmu: This function copies memory from System - memory space to MMU mode space. -============================================================================= -*/ -void remem_copy_system_to_mmu(void) -{ - int block; /* Block being copied */ - - /* Loop through all blocks */ - for (block = 0; block < 64; block++) - { - remem_copy_block_to_mmu(block); - } -} - -/* -============================================================================= -remem_copy_block_to_mmu: This function copies a 1K block of RAM from - system space to ReMem space base on the current - ReMem mode settings. The spcified 1K block of - system RAM is copied. -============================================================================= -*/ -void remem_copy_block_to_mmu(int block) -{ - int c; /* Byte counter */ - uchar *pDest; /* Destination pointer */ - int src; /* Source pointer */ - - /* Check if block is read-only, skip copy if read-only*/ - if (gReMemMap[block] & REMEM_VCTR_READ_ONLY) - return; - - /* Calculate source pointer base on block vector */ - if ((gReMemMap[block] & REMEM_VCTR_RAM_CS) == 0) - pDest = gReMemRam; - else if ((gReMemMap[block] & REMEM_VCTR_FLASH1_CS) == 0) - pDest = gReMemFlash1; - else if ((gReMemMap[block] & REMEM_VCTR_FLASH1_CS) == 0) - pDest = gReMemFlash2; - else - return; - - /* Calculate offset of 1K block */ - pDest += (gReMemMap[block] & REMEM_VCTR_ADDRESS) << 11; - src = block * 1024; + pSrc += (gReMemMap[block] & REMEM_VCTR_ADDRESS) << 10; /* Copy bytes */ - for (c = 0; c < 1024; c++) - *pDest++ = memory[src++]; + gMemory[block] = pSrc; } diff --git a/src/memory.h b/src/memory.h index e2b5e5b..b6cacc9 100644 --- a/src/memory.h +++ b/src/memory.h @@ -17,31 +17,45 @@ memory.h extern "C" { #endif +#define REMEM_REV_MAJOR 4 + +#define REMEM_REV_M100 (REMEM_REV_MAJOR << 4) +#define REMEM_REV_M102 ((REMEM_REV_MAJOR << 4) | 0x01) +#define REMEM_REV_T200 ((REMEM_REV_MAJOR << 4) | 0x02) + +#define REMEM_REV (gModel == MODEL_M100 ? REMEM_REV_M100 : gModel == MODEL_M102 ? REMEM_REV_M102 : REMEM_REV_T200) + #define REMEM_MODE_NORMAL 0x01 #define REMEM_MODE_RAMPAC 0x02 -#define REMEM_MODE_MAP_BITS 0x1C -#define REMEM_MODE_MAP_SHIFT 2 -#define REMEM_MODE_FLASH1_RO 0x20 -#define REMEM_MODE_FLASH2_RO 0x40 - +#define REMEM_MODE_IOENABLE 0x04 +#define REMEM_MODE_MAP_BITS 0x38 +#define REMEM_MODE_MAP_SHIFT 3 +#define REMEM_MODE_FLASH1_RO 0x40 +#define REMEM_MODE_FLASH2_RO 0x80 + +#define REMEM_SECTOR_PORT 0x61 +#define REMEM_DATA_PORT 0x63 #define REMEM_MODE_PORT 0x70 -#define REMEM_SECTOR_PORT 0x71 -#define REMEM_VCTR_PORT 0x73 +#define REMEM_REVID_PORT 0x71 #define RAMPAC_SECTOR_PORT 0x81 #define RAMPAC_DATA_PORT 0x83 #define REMEM_VCTR_RAM_CS 0x2000 -#define REMEM_VCTR_FLASH1_CS 0x1000 -#define REMEM_VCTR_FLASH2_CS 0x0800 +#define REMEM_VCTR_FLASH2_CS 0x1000 +#define REMEM_VCTR_FLASH1_CS 0x0800 #define REMEM_VCTR_READ_ONLY 0x4000 #define REMEM_VCTR_MMU_ACTIVE 0x8000 #define REMEM_VCTR_ADDRESS 0x07FF -#define REMEM_MAP_OFFSET 0x00100000000 -#define REMEM_MAP_SIZE (gModel == MODEL_T200 ? 1024 : 512) -#define REMEM_BANK_SIZE (gModel == MODEL_T200 ? 256 : 128) -#define REMEM_BANKS_PER_MAP (gModel == MODEL_T200 ? 8 : 4) -#define REMEM_RAM_BANK_OFFSET 0xA0 +#define REMEM_MAP_OFFSET 0x1BF000 +#define REMEM_MAP_SIZE 512 +#define REMEM_BANK_SIZE 128 +#define REMEM_BANKS_PER_MAP 4 +#define REMEM_BLOCKS_PER_BANK 32 +#define REMEM_RAM_MAP_OFFSET (gModel == MODEL_T200 ? 0x50 : 0) +#define REMEM_RAMPAC_OFFSET 0x1C0000 +#define RAMPAC_SECTOR_SIZE 1024 +#define RAMPAC_SECTOR_COUNT 256 #define REGION_RAM 0 #define REGION_ROM 1 @@ -55,7 +69,14 @@ extern "C" { #define REGION_FLASH2 9 #define REGION_RAMPAC 10 + +extern unsigned char *gMemory[64]; +extern unsigned char gSysROM[65536]; +extern unsigned char gBaseMemory[65536]; +extern unsigned char gReMem; + void init_mem(void); +void reinit_mem(void); void free_mem(void); void free_remem_mem(void); void free_rampac_mem(void); diff --git a/src/periph.cpp b/src/periph.cpp index 4f6dde9..9b0d20f 100644 --- a/src/periph.cpp +++ b/src/periph.cpp @@ -47,11 +47,12 @@ #include #include "serial.h" -#include "setup.h" #include "display.h" #include "m100emu.h" #include "disassemble.h" #include "periph.h" +#include "memedit.h" +#include "cpuregs.h" typedef struct periph_ctrl_struct @@ -126,11 +127,11 @@ typedef struct periph_ctrl_struct // Menu items for the disassembler Fl_Menu_Item gPeriph_menuitems[] = { { "&Tools", 0, 0, 0, FL_SUBMENU }, - { "CPU Registers", 0, 0 }, + { "CPU Registers", 0, cb_CpuRegs }, { "Assembler", 0, 0 }, { "Disassembler", 0, disassembler_cb }, { "Debugger", 0, 0 }, - { "Memory Editor", 0, 0 }, + { "Memory Editor", 0, cb_MemoryEditor }, { "Peripheral Devices", 0, 0 }, { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, 0 }, diff --git a/src/periph.h b/src/periph.h index 58a1175..54a0d34 100644 --- a/src/periph.h +++ b/src/periph.h @@ -31,6 +31,8 @@ #ifndef PERIPH_H #define PERIPH_H +#include + void cb_PeripheralDevices (Fl_Widget* w, void*); diff --git a/src/serial.c b/src/serial.c index dcad761..47e3a9d 100644 --- a/src/serial.c +++ b/src/serial.c @@ -37,7 +37,6 @@ #include "serial.h" #include "setup.h" #include "display.h" -#include "m100emu.h" ser_params_t sp; diff --git a/src/setup.cpp b/src/setup.cpp index 90162b8..64b9b13 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -48,11 +48,11 @@ #include #include "m100emu.h" -#include "io.h" #include "serial.h" #include "setup.h" #include "memory.h" #include "memedit.h" +#include "file.h" extern Fl_Preferences virtualt_prefs; @@ -146,6 +146,13 @@ void save_setup_preferences(void) void load_setup_preferences(void) { + #ifdef __APPLE__ + //JV 10/08/05 + int ex; + char *ret; + //---------JV + #endif + // Load COM emulation settings virtualt_prefs.get("ComMode", setup.com_mode,0); virtualt_prefs.get("ComCmd", setup.com_cmd,"", 128); @@ -161,6 +168,29 @@ void load_setup_preferences(void) // Load BCR emulation settings // Load Sound emulation settings + +#ifdef __APPLE__ + //JV 08/10/05 + // Load Path Preferences + ex=virtualt_prefs.get("Path",path,".",256); + if(ex==0) // no path in the pref file or pref file nonexistent + { + ret=ChooseWorkDir(); // return the directory + if(ret==NULL) + exit(-1); //nothing choose: do nothing.... + else + { + strcpy(path,ret); + #ifdef __unix__ + strcat(path,"/"); + #else + strcat(path,"\\"); + #endif + virtualt_prefs.set("Path",path); // set pref path + } + } + //JV +#endif } /* @@ -643,6 +673,10 @@ void cb_memory_OK(Fl_Widget* w, void*) // Update Memory Editor cb_MemoryEditorUpdate(); + /* Reset the CPU */ + resetcpu(); + gExitLoop = 1; + // Destroy the window gmsw->hide(); delete gmsw; diff --git a/src/sound.c b/src/sound.c index 70d873d..257717e 100644 --- a/src/sound.c +++ b/src/sound.c @@ -33,12 +33,12 @@ #include #include #include -#include -#include #ifdef _WIN32 #include #include +#include +#include #endif #ifdef __unix__ @@ -53,7 +53,7 @@ #pragma comment(lib, "winmm.lib") #define snd_Buffers 2 -#define cwSizel 96 +#define cwSizel 32 /* * module static data @@ -67,6 +67,7 @@ unsigned int NextBuf, fDone [snd_Buffers] ; unsigned int Index ; unsigned short readbuf [2 * cwSizel] ; /* input buffer */ short int tmpbuf [2 * cwSizel] ; +unsigned short *gpOneHertz = NULL; int m_Channels = 2 , m_SamplingRate = 22050, SamplesPerFrame = cwSizel; @@ -74,13 +75,15 @@ short *pcmbuf; short *tmppcmbuf; int frameCount=0; int cwSize = 2*cwSizel; + int gPlayTone = 0; int gToneFreq = 0; int gFlushBuffers = 0; int gExit = 0; +int gBeepOn = 0; +int gOneHzPtr = 0; extern double last_instruct; static double spkr_cycle = 0; -int gBeepOn = 0; #ifdef _WIN32 HANDLE g_hEquThread; @@ -208,8 +211,6 @@ short *sndGetBuffer (void) if (hOutput == NULL) return NULL ; - /* printf ("%i %i\t", NextBuf, Index) ; */ - wbuf = (short *) wh [NextBuf].lpData ; wbuf = &wbuf [g_FrameSize * Index++] ; @@ -231,8 +232,6 @@ short *sndGetBuffer (void) if (wh [NextBuf].dwFlags & WHDR_PREPARED) waveOutUnprepareHeader (hOutput, &wh [NextBuf], sizeof (WAVEHDR)) ; - /* printf ("** **\t%i %i\t", NextBuf, 0) ; */ - return (short *) wh [NextBuf].lpData ; } @@ -264,26 +263,14 @@ void playback() { int i; BOOL fWantPlayback; - double inc, sval; - static double mult = 1; - static double mult_add = 0; - static double val = 0.0; - if (gToneFreq != 0.0) - mult = (double) m_SamplingRate / (double) gToneFreq; - if (mult <= 10) - mult_add = .5; - if (mult >= 50) - mult_add = -.5; - -// mult += mult_add; - inc = 1.0 / (double) cwSize; for (i = 0; i < cwSize; i++) { - val += inc; - sval = sin(val * 6.283*mult) * 32700; - readbuf[i] = (unsigned short) sval; + readbuf[i] = gpOneHertz[gOneHzPtr]; + gOneHzPtr += gToneFreq; + if (gOneHzPtr >= m_SamplingRate) + gOneHzPtr -= m_SamplingRate; } fWantPlayback = TRUE; @@ -311,7 +298,6 @@ DWORD WINAPI EquProc(LPVOID lpParam) { static creatflag; - while (1) { // If no active tone being played, wait for event so we don't @@ -360,10 +346,23 @@ init_sound: This routine initializes the sound output device(s) */ void init_sound(void) { + int x; + double w; + gExit = 0; + + // Create sin table + gpOneHertz = malloc(m_SamplingRate * sizeof(unsigned short)); + w = 2.0 * 3.14159 / (double) m_SamplingRate; + for (x = 0; x < m_SamplingRate; x++) + { + gpOneHertz[x] = (unsigned short) (sin(w * (double) x) * 32767.0); + } + return; #ifdef _WIN32 + // Start thread to handle Sound I/O g_hEquThread = (HANDLE)_beginthreadex(0,0,EquProc,0,0,&dwThreadID); #endif } @@ -371,13 +370,14 @@ void init_sound(void) /* ================================================================== -init_sound: This routine deinitializes the sound output device(s) - for tone generations. +deinit_sound: This routine deinitializes the sound output device(s) + for tone generations. ================================================================== */ void deinit_sound(void) { gExit = 1; + free(gpOneHertz); #ifdef _WIN32 // sndCloseOutput(); @@ -392,8 +392,11 @@ start_tone: This routine starts a tone of specified frequency */ void sound_start_tone(int freq) { - gToneFreq = freq; - gPlayTone = 1; + if (freq < m_SamplingRate / 2.0) + { + gToneFreq = freq; + gPlayTone = 1; + } } /* @@ -432,7 +435,7 @@ void sound_toggle_speaker(int bitVal) if ((delta < 5000) && (delta != 0.0)) { gBeepOn = 1; - sound_start_tone((int) (1.0 / delta)); + sound_start_tone((int) (60000.0 / delta)); } } From e111bb96aaa87db40ff94fa3447ea94504e5a359 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 18 Apr 2006 23:50:26 +0000 Subject: [PATCH 037/327] New Tool addition - CPU Register's window with Stop / Stingle Step / Run capability. --- src/cpuregs.cpp | 1769 +++++++++++++++++++++++++++++++++++++++++++++++ src/cpuregs.h | 130 ++++ 2 files changed, 1899 insertions(+) create mode 100644 src/cpuregs.cpp create mode 100644 src/cpuregs.h diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp new file mode 100644 index 0000000..1dd630a --- /dev/null +++ b/src/cpuregs.cpp @@ -0,0 +1,1769 @@ +/* cpuregs.cpp */ + +/* $Id$ */ + +/* + * Copyright 2006 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#if defined(WIN32) +#include +#endif +#include +#include +#include + +#include "cpuregs.h" +#include "m100emu.h" +#include "disassemble.h" +#include "periph.h" +#include "memedit.h" +#include "cpu.h" +#include "memory.h" + +#define MENU_HEIGHT 32 + +/* +============================================================================ +Global variables +============================================================================ +*/ +cpuregs_ctrl_t cpuregs_ctrl; +Fl_Window *gcpuw; +int gStopCountdown = 0; +int gSaveFreq = 0; +int gDisableRealtimeTrace = 0; +int gDebugCount = 0;; +int gDebugMonitorFreq = 8192; + +// Menu items for the disassembler +Fl_Menu_Item gCpuRegs_menuitems[] = { + { "&Tools", 0, 0, 0, FL_SUBMENU }, + { "CPU Registers", 0, 0 }, + { "Assembler", 0, 0 }, + { "Disassembler", 0, disassembler_cb }, + { "Debugger", 0, 0 }, + { "Memory Editor", 0, cb_MemoryEditor }, + { "Peripheral Devices", 0, cb_PeripheralDevices }, + { "Simulation Log Viewer", 0, 0 }, + { "Model T File Viewer", 0, 0 }, + { "BASIC Debugger", 0, 0 }, + { 0 }, + { 0 } +}; + +void debug_cpuregs_cb (void); + +/* +============================================================================ +Callback routine for the CPU Regs window +============================================================================ +*/ +void cb_cpuregswin (Fl_Widget* w, void*) +{ + // Hide the window + gcpuw->hide(); + + // Disable debug processes + gDebugActive--; + + if (gDebugActive == 0) + { + gStopped = 0; + gSingleStep = 0; + } + + // Remove ourselves as a debug monitor + debug_clear_monitor_callback(debug_cpuregs_cb); + + // Delete the window and set to NULL + delete gcpuw; + gcpuw = NULL; +} + + +/* +============================================================================ +str_to_i: This routine converts a hex or decimal string to an integer. + Hex values are indentified by a leading "0x". +============================================================================ +*/ +int str_to_i(const char *pStr) +{ + int x; + int val, digit; + + // Test for Hex number + if (strncmp("0x", pStr, 2) == 0) + { + x = 2; val = 0; + while (pStr[x] != '\0') + { + digit = pStr[x] > '9' ? (pStr[x] | 0x60) - 'a' + 10 : pStr[x] - '0'; + val = val * 16 + digit; + x++; + } + } + else + val = atoi(pStr); + + // Return value to caller + return val; +} + +/* +============================================================================ +get_reg_edits: This routine reads all register input fields and updates the + CPU registers accordingly. +============================================================================ +*/ +void get_reg_edits(void) +{ + const char* pStr; + int val, flags; + + // Get value of PC + pStr = cpuregs_ctrl.pRegPC->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + PCL = val & 0xFF; PCH = val >> 8; + } + + // Get value of SP + pStr = cpuregs_ctrl.pRegSP->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + SPL = val & 0xFF; SPH = val >> 8; + } + + // Get value of A + pStr = cpuregs_ctrl.pRegA->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + A = val & 0xFF; + } + + // Get value of M + pStr = cpuregs_ctrl.pRegM->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + set_memory8(HL, val & 0xFF); + } + + // Get value of BC + pStr = cpuregs_ctrl.pRegBC->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + if (val != BC) + { + // Update the values of B and C from the BC edit field + B = val >> 8; + C = val & 0xFF; + } + else + { + // BC didn't change - test B and C individually + pStr = cpuregs_ctrl.pRegB->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + B = val; + } + // Now get new value for C + pStr = cpuregs_ctrl.pRegC->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + C = val; + } + } + } + + // Get value of DE + pStr = cpuregs_ctrl.pRegDE->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + if (val != DE) + { + // Update the values of D and E from the DE edit field + D = val >> 8; + E = val & 0xFF; + } + else + { + // DE didn't change - test D and E individually + pStr = cpuregs_ctrl.pRegD->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + D = val; + } + // Now get new value for E + pStr = cpuregs_ctrl.pRegE->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + E = val; + } + } + } + + // Get value of HL + pStr = cpuregs_ctrl.pRegHL->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + if (val != HL) + { + // Update the values of H and L from the HL edit field + H = val >> 8; + L = val & 0xFF; + } + else + { + // HL didn't change - test H and L individually + pStr = cpuregs_ctrl.pRegH->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + H = val; + } + // Now get new value for L + pStr = cpuregs_ctrl.pRegL->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + L = val; + } + } + } + + // Finally get updates to the flags + flags = 0; + if (cpuregs_ctrl.pSFlag->value()) + flags |= 0x80; + if (cpuregs_ctrl.pZFlag->value()) + flags |= 0x40; + if (cpuregs_ctrl.pTSFlag->value()) + flags |= 0x20; + if (cpuregs_ctrl.pACFlag->value()) + flags |= 0x10; + if (cpuregs_ctrl.pPFlag->value()) + flags |= 0x04; + if (cpuregs_ctrl.pOVFlag->value()) + flags |= 0x02; + if (cpuregs_ctrl.pCFlag->value()) + flags |= 0x01; + + F = flags; +} + +/* +============================================================================ +Callback routine to redraw the trace and stack areas +============================================================================ +*/ +void cb_redraw_trace(Fl_Widget* w, void*) +{ + int x, draw; + char str[10]; + + gcpuw->make_current(); + + // Clear rectangle + fl_color(FL_GRAY); + fl_rectf(25, 205+MENU_HEIGHT, 510, 115); + fl_rectf(555, 205+MENU_HEIGHT, 54, 115); + + // Select 11 point Courier font + fl_font(FL_COURIER,11); + fl_color(FL_BLACK); + + // Determine first trace to draw + draw = cpuregs_ctrl.iInstTraceHead; + for (x = 0; x < 8; x++) + { + // Draw the Stack + sprintf(str, "0x%02X", get_memory8(SP+x)); + fl_draw(str, 560, 212+MENU_HEIGHT+x*15); + + // Now draw the Instruction Trace + if (x == 7) + fl_font(FL_COURIER_BOLD, 11); + fl_draw(cpuregs_ctrl.sInstTrace[draw], 25, 212+MENU_HEIGHT+x*15); + if (++draw >= 8) + draw = 0; + + } +} + +/* +============================================================================ +Callback routine for receiving serial port status updates +============================================================================ +*/ +extern "C" +{ +void debug_monitor_cb(int fMonType, unsigned char data) +{ +} +} + +/* +============================================================================ +debug_cpuregs_cb: This routine is the callback for the CPURegs Monitor + window. This routine handles updating of Register + values while the CPU is running. +============================================================================ +*/ +void debug_cpuregs_cb (void) +{ + char str[100]; + char flags[10]; + int x, len; + + if (!gStopped) + if (++gDebugCount < gDebugMonitorFreq) + return; + + gDebugCount = 0; + + // Update PC edit box + sprintf(str, cpuregs_ctrl.sPCfmt, PC); + cpuregs_ctrl.pRegPC->value(str); + + // Update SP edit box + sprintf(str, cpuregs_ctrl.sSPfmt, SP); + cpuregs_ctrl.pRegSP->value(str); + + // Update A edit box + sprintf(str, cpuregs_ctrl.sAfmt, A); + cpuregs_ctrl.pRegA->value(str); + + // Update B edit box + sprintf(str, cpuregs_ctrl.sBfmt, B); + cpuregs_ctrl.pRegB->value(str); + + // Update C edit box + sprintf(str, cpuregs_ctrl.sCfmt, C); + cpuregs_ctrl.pRegC->value(str); + + // Update D edit box + sprintf(str, cpuregs_ctrl.sDfmt, D); + cpuregs_ctrl.pRegD->value(str); + + // Update E edit box + sprintf(str, cpuregs_ctrl.sEfmt, E); + cpuregs_ctrl.pRegE->value(str); + + // Update H edit box + sprintf(str, cpuregs_ctrl.sHfmt, H); + cpuregs_ctrl.pRegH->value(str); + + // Update L edit box + sprintf(str, cpuregs_ctrl.sLfmt, L); + cpuregs_ctrl.pRegL->value(str); + + // Update BC edit box + sprintf(str, cpuregs_ctrl.sBCfmt, BC); + cpuregs_ctrl.pRegBC->value(str); + + // Update DE edit box + sprintf(str, cpuregs_ctrl.sDEfmt, DE); + cpuregs_ctrl.pRegDE->value(str); + + // Update HL edit box + sprintf(str, cpuregs_ctrl.sHLfmt, HL); + cpuregs_ctrl.pRegHL->value(str); + + // Update M edit box + sprintf(str, cpuregs_ctrl.sMfmt, M); + cpuregs_ctrl.pRegM->value(str); + + // Update flags + cpuregs_ctrl.pSFlag->value(SF); + cpuregs_ctrl.pZFlag->value(ZF); + cpuregs_ctrl.pTSFlag->value(TS); + cpuregs_ctrl.pACFlag->value(AC); + cpuregs_ctrl.pPFlag->value(PF); + cpuregs_ctrl.pOVFlag->value(OV); + cpuregs_ctrl.pXFlag->value(XF); + cpuregs_ctrl.pCFlag->value(CF); + + if (!gDisableRealtimeTrace || (gStopCountdown != 0) || gStopped) + { + // Disassemble 1 instruction + VTDis::DisassembleLine(PC, cpuregs_ctrl.sInstTrace[cpuregs_ctrl.iInstTraceHead]); + + // Append spaces after opcode + len = 20 - strlen(cpuregs_ctrl.sInstTrace[cpuregs_ctrl.iInstTraceHead]); + for (x = 0; x < len; x++) + strcat(cpuregs_ctrl.sInstTrace[cpuregs_ctrl.iInstTraceHead], " "); + + // Format flags string + sprintf(flags, "%c%c%c%c%c%c%c%c", SF?'S':' ', ZF?'Z':' ', TS?'T':' ',AC?'A':' ', + PF?'P':' ',OV?'O':' ',XF?'X':' ', CF?'C':' '); + + // Append regs after opcode + sprintf(str, "A:%02X %s B:%02X C:%02X D:%02X E:%02X H:%02X L:%02X SP:%02X", + A, flags, B, C, D, E, H, L, SP); + strcat(cpuregs_ctrl.sInstTrace[cpuregs_ctrl.iInstTraceHead++], str); + + if (cpuregs_ctrl.iInstTraceHead >= 8) + cpuregs_ctrl.iInstTraceHead= 0; + + // Update Trace data on window + cb_redraw_trace(NULL, NULL); + } + + // Check if processor stop requested + if (gStopCountdown > 0) + { + // We countdown to a stop so the last 8 trace steps make sense + if (--gStopCountdown == 0) + { + gStopped = 1; + gDebugMonitorFreq = gSaveFreq; + } + } +} + +/* +============================================================================ +Routine to handle Stop button +============================================================================ +*/ +void cb_debug_stop(Fl_Widget* w, void*) +{ + // Change activation state of processor controls + cpuregs_ctrl.pStop->deactivate(); + cpuregs_ctrl.pStep->activate(); + cpuregs_ctrl.pRun->activate(); + cpuregs_ctrl.pRedraw->activate(); + + // Activate the edit fields to allow register updates + cpuregs_ctrl.pRegA->activate(); + cpuregs_ctrl.pRegB->activate(); + cpuregs_ctrl.pRegC->activate(); + cpuregs_ctrl.pRegD->activate(); + cpuregs_ctrl.pRegE->activate(); + cpuregs_ctrl.pRegH->activate(); + cpuregs_ctrl.pRegL->activate(); + cpuregs_ctrl.pRegPC->activate(); + cpuregs_ctrl.pRegSP->activate(); + cpuregs_ctrl.pRegBC->activate(); + cpuregs_ctrl.pRegDE->activate(); + cpuregs_ctrl.pRegHL->activate(); + cpuregs_ctrl.pRegM->activate(); + + // Activate Flags + cpuregs_ctrl.pSFlag->activate(); + cpuregs_ctrl.pZFlag->activate(); + cpuregs_ctrl.pCFlag->activate(); + cpuregs_ctrl.pTSFlag->activate(); + cpuregs_ctrl.pACFlag->activate(); + cpuregs_ctrl.pPFlag->activate(); + cpuregs_ctrl.pOVFlag->activate(); + cpuregs_ctrl.pXFlag->activate(); + + // Stop the processor + gStopCountdown = 8; + gSaveFreq = gDebugMonitorFreq; + gDebugMonitorFreq = 1; +} + +/* +============================================================================ +Routine to handle Step button +============================================================================ +*/ +void cb_debug_step(Fl_Widget* w, void*) +{ + // Get Register updates + get_reg_edits(); + + // Single step the processor + gSingleStep = 1; +} + +/* +============================================================================ +Routine to handle Run button +============================================================================ +*/ +void cb_debug_run(Fl_Widget* w, void*) +{ + // Change activation state of processor controls + cpuregs_ctrl.pStop->activate(); + cpuregs_ctrl.pStep->deactivate(); + cpuregs_ctrl.pRun->deactivate(); + cpuregs_ctrl.pRedraw->deactivate(); + + // Deactivate the edit fields to allow register updates + cpuregs_ctrl.pRegA->deactivate(); + cpuregs_ctrl.pRegB->deactivate(); + cpuregs_ctrl.pRegC->deactivate(); + cpuregs_ctrl.pRegD->deactivate(); + cpuregs_ctrl.pRegE->deactivate(); + cpuregs_ctrl.pRegH->deactivate(); + cpuregs_ctrl.pRegL->deactivate(); + cpuregs_ctrl.pRegPC->deactivate(); + cpuregs_ctrl.pRegSP->deactivate(); + cpuregs_ctrl.pRegBC->deactivate(); + cpuregs_ctrl.pRegDE->deactivate(); + cpuregs_ctrl.pRegHL->deactivate(); + cpuregs_ctrl.pRegM->deactivate(); + + // Deactivate Flags + cpuregs_ctrl.pSFlag->deactivate(); + cpuregs_ctrl.pZFlag->deactivate(); + cpuregs_ctrl.pCFlag->deactivate(); + cpuregs_ctrl.pTSFlag->deactivate(); + cpuregs_ctrl.pACFlag->deactivate(); + cpuregs_ctrl.pPFlag->deactivate(); + cpuregs_ctrl.pOVFlag->deactivate(); + cpuregs_ctrl.pXFlag->deactivate(); + + // Get Register updates + get_reg_edits(); + + // Start the processor + gStopped = 0; +} + +/* +============================================================================ +Routine to handle Change to PC edit field +============================================================================ +*/ +void cb_reg_pc_changed(Fl_Widget* w, void*) +{ + int new_pc; + const char *pStr; + int trace_tail; + char str[120], flags[20]; + int len, x; + + pStr = cpuregs_ctrl.pRegPC->value(); + new_pc = str_to_i(pStr); + trace_tail = cpuregs_ctrl.iInstTraceHead - 1; + if (trace_tail < 0) + trace_tail = 7; + + // Disassemble 1 instruction + VTDis::DisassembleLine(new_pc, cpuregs_ctrl.sInstTrace[trace_tail]); + + // Append spaces after opcode + len = 20 - strlen(cpuregs_ctrl.sInstTrace[trace_tail]); + for (x = 0; x < len; x++) + strcat(cpuregs_ctrl.sInstTrace[trace_tail], " "); + + // Format flags string + sprintf(flags, "%c%c%c%c%c%c%c%c", SF?'S':' ', ZF?'Z':' ', TS?'T':' ',AC?'A':' ', + PF?'P':' ',OV?'O':' ',XF?'X':' ', CF?'C':' '); + + // Append regs after opcode + sprintf(str, "A:%02X %s B:%02X C:%02X D:%02X E:%02X H:%02X L:%02X SP:%02X", + A, flags, B, C, D, E, H, L, SP); + strcat(cpuregs_ctrl.sInstTrace[trace_tail], str); + + // Update Trace data on window + cb_redraw_trace(NULL, NULL); +} + +/* +============================================================================ +Routine to handle Change to HL edit field +============================================================================ +*/ +void cb_reg_hl_changed(Fl_Widget* w, void*) +{ + int new_hl; + const char *pStr; + char str[20]; + + pStr = cpuregs_ctrl.pRegHL->value(); + new_hl = str_to_i(pStr); + + H = (new_hl >> 8) & 0xFF; + L = new_hl & 0xFF; + + // Update H edit box + sprintf(str, cpuregs_ctrl.sHfmt, H); + cpuregs_ctrl.pRegH->value(str); + + // Update L edit box + sprintf(str, cpuregs_ctrl.sLfmt, L); + cpuregs_ctrl.pRegL->value(str); + + // Update M edit box + sprintf(str, cpuregs_ctrl.sMfmt, M); + cpuregs_ctrl.pRegM->value(str); + +} + +/* +============================================================================ +Routine to handle Change to H edit field +============================================================================ +*/ +void cb_reg_h_changed(Fl_Widget* w, void*) +{ + const char *pStr; + char str[20]; + + pStr = cpuregs_ctrl.pRegH->value(); + H = str_to_i(pStr); + + // Update H edit box + sprintf(str, cpuregs_ctrl.sHfmt, H); + cpuregs_ctrl.pRegH->value(str); + + // Update HL edit box + sprintf(str, cpuregs_ctrl.sHLfmt, HL); + cpuregs_ctrl.pRegHL->value(str); + + // Update M edit box + sprintf(str, cpuregs_ctrl.sMfmt, M); + cpuregs_ctrl.pRegM->value(str); + +} + +/* +============================================================================ +Routine to handle Change to L edit field +============================================================================ +*/ +void cb_reg_l_changed(Fl_Widget* w, void*) +{ + const char *pStr; + char str[20]; + + pStr = cpuregs_ctrl.pRegL->value(); + L = str_to_i(pStr); + + // Update H edit box + sprintf(str, cpuregs_ctrl.sLfmt, L); + cpuregs_ctrl.pRegL->value(str); + + // Update HL edit box + sprintf(str, cpuregs_ctrl.sHLfmt, HL); + cpuregs_ctrl.pRegHL->value(str); + + // Update M edit box + sprintf(str, cpuregs_ctrl.sMfmt, M); + cpuregs_ctrl.pRegM->value(str); + +} + +/* +============================================================================ +Routine to handle Change to SP edit field +============================================================================ +*/ +void cb_reg_sp_changed(Fl_Widget* w, void*) +{ + const char *pStr; + int val; + + // Get value of SP + pStr = cpuregs_ctrl.pRegSP->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + SPL = val & 0xFF; SPH = val >> 8; + } + + // Update Trace data on window + cb_redraw_trace(NULL, NULL); +} + +/* +============================================================================ +Routine to handle disabling realtime trace +============================================================================ +*/ +void cb_disable_realtime_trace(Fl_Widget* w, void*) +{ + gDisableRealtimeTrace = cpuregs_ctrl.pDisableTrace->value(); + + if (gDisableRealtimeTrace) + { + gcpuw->make_current(); + + // Clear rectangle + fl_color(FL_GRAY); + fl_rectf(25, 205+MENU_HEIGHT, 510, 115); + fl_rectf(555, 205+MENU_HEIGHT, 54, 115); + } +} + +/* +============================================================================ +Routine to handle Reg A Hex display mode +============================================================================ +*/ +void cb_reg_a_hex(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sAfmt, "0x%02X"); + sprintf(str, cpuregs_ctrl.sAfmt, A); + cpuregs_ctrl.pRegA->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg A Dec display mode +============================================================================ +*/ +void cb_reg_a_dec(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sAfmt, "%d"); + sprintf(str, cpuregs_ctrl.sAfmt, A); + cpuregs_ctrl.pRegA->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg B Hex display mode +============================================================================ +*/ +void cb_reg_b_hex(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sBfmt, "0x%02X"); + sprintf(str, cpuregs_ctrl.sBfmt, B); + cpuregs_ctrl.pRegB->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +========================================================================== +Routine to handle Reg B Dec display mode +============================================================================ +*/ +void cb_reg_b_dec(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sBfmt, "%d"); + sprintf(str, cpuregs_ctrl.sBfmt, B); + cpuregs_ctrl.pRegB->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg C Hex display mode +============================================================================ +*/ +void cb_reg_c_hex(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sCfmt, "0x%02X"); + sprintf(str, cpuregs_ctrl.sCfmt, C); + cpuregs_ctrl.pRegC->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg C Dec display mode +============================================================================ +*/ +void cb_reg_c_dec(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sCfmt, "%d"); + sprintf(str, cpuregs_ctrl.sCfmt, C); + cpuregs_ctrl.pRegC->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg D Hex display mode +============================================================================ +*/ +void cb_reg_d_hex(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sDfmt, "0x%02X"); + sprintf(str, cpuregs_ctrl.sDfmt, D); + cpuregs_ctrl.pRegD->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg D Dec display mode +============================================================================ +*/ +void cb_reg_d_dec(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sDfmt, "%d"); + sprintf(str, cpuregs_ctrl.sDfmt, D); + cpuregs_ctrl.pRegD->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg E Hex display mode +============================================================================ +*/ +void cb_reg_e_hex(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sEfmt, "0x%02X"); + sprintf(str, cpuregs_ctrl.sEfmt, E); + cpuregs_ctrl.pRegE->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg E Dec display mode +============================================================================ +*/ +void cb_reg_e_dec(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sEfmt, "%d"); + sprintf(str, cpuregs_ctrl.sEfmt, E); + cpuregs_ctrl.pRegE->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg H Hex display mode +============================================================================ +*/ +void cb_reg_h_hex(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sHfmt, "0x%02X"); + sprintf(str, cpuregs_ctrl.sHfmt, H); + cpuregs_ctrl.pRegH->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg H Dec display mode +============================================================================ +*/ +void cb_reg_h_dec(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sHfmt, "%d"); + sprintf(str, cpuregs_ctrl.sHfmt, H); + cpuregs_ctrl.pRegH->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg L Hex display mode +============================================================================ +*/ +void cb_reg_l_hex(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sLfmt, "0x%02X"); + sprintf(str, cpuregs_ctrl.sLfmt, L); + cpuregs_ctrl.pRegL->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg L Dec display mode +============================================================================ +*/ +void cb_reg_l_dec(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sLfmt, "%d"); + sprintf(str, cpuregs_ctrl.sLfmt, L); + cpuregs_ctrl.pRegL->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg PC Hex display mode +============================================================================ +*/ +void cb_reg_pc_hex(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sPCfmt, "0x%04X"); + sprintf(str, cpuregs_ctrl.sPCfmt, PC); + cpuregs_ctrl.pRegPC->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg PC Dec display mode +============================================================================ +*/ +void cb_reg_pc_dec(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sPCfmt, "%d"); + sprintf(str, cpuregs_ctrl.sPCfmt, PC); + cpuregs_ctrl.pRegPC->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg SP Hex display mode +============================================================================ +*/ +void cb_reg_sp_hex(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sSPfmt, "0x%04X"); + sprintf(str, cpuregs_ctrl.sSPfmt, SP); + cpuregs_ctrl.pRegSP->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg SP Dec display mode +============================================================================ +*/ +void cb_reg_sp_dec(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sSPfmt, "%d"); + sprintf(str, cpuregs_ctrl.sSPfmt, SP); + cpuregs_ctrl.pRegSP->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg BC Hex display mode +============================================================================ +*/ +void cb_reg_bc_hex(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sBCfmt, "0x%04X"); + sprintf(str, cpuregs_ctrl.sBCfmt, BC); + cpuregs_ctrl.pRegBC->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg BC Dec display mode +============================================================================ +*/ +void cb_reg_bc_dec(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sBCfmt, "%d"); + sprintf(str, cpuregs_ctrl.sBCfmt, BC); + cpuregs_ctrl.pRegBC->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg DE Hex display mode +============================================================================ +*/ +void cb_reg_de_hex(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sDEfmt, "0x%04X"); + sprintf(str, cpuregs_ctrl.sDEfmt, DE); + cpuregs_ctrl.pRegDE->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg DE Dec display mode +============================================================================ +*/ +void cb_reg_de_dec(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sDEfmt, "%d"); + sprintf(str, cpuregs_ctrl.sDEfmt, DE); + cpuregs_ctrl.pRegDE->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg HL Hex display mode +============================================================================ +*/ +void cb_reg_hl_hex(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sHLfmt, "0x%04X"); + sprintf(str, cpuregs_ctrl.sHLfmt, HL); + cpuregs_ctrl.pRegHL->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg HL Dec display mode +============================================================================ +*/ +void cb_reg_hl_dec(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sHLfmt, "%d"); + sprintf(str, cpuregs_ctrl.sHLfmt, HL); + cpuregs_ctrl.pRegHL->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg M Hex display mode +============================================================================ +*/ +void cb_reg_m_hex(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sMfmt, "0x%02X"); + sprintf(str, cpuregs_ctrl.sMfmt, M); + cpuregs_ctrl.pRegM->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg M Dec display mode +============================================================================ +*/ +void cb_reg_m_dec(Fl_Widget* w, void*) +{ + char str[8]; + + strcpy(cpuregs_ctrl.sMfmt, "%d"); + sprintf(str, cpuregs_ctrl.sMfmt, M); + cpuregs_ctrl.pRegM->value(str); + + cpuregs_ctrl.pAllHex->value(0); + cpuregs_ctrl.pAllDec->value(0); +} + +/* +============================================================================ +Routine to handle Reg All Hex display mode +============================================================================ +*/ +void cb_reg_all_hex(Fl_Widget* w, void*) +{ + // Change format to "Hex" for all + cb_reg_a_hex(w, NULL); + cb_reg_b_hex(w, NULL); + cb_reg_c_hex(w, NULL); + cb_reg_d_hex(w, NULL); + cb_reg_e_hex(w, NULL); + cb_reg_h_hex(w, NULL); + cb_reg_l_hex(w, NULL); + cb_reg_pc_hex(w, NULL); + cb_reg_sp_hex(w, NULL); + cb_reg_bc_hex(w, NULL); + cb_reg_de_hex(w, NULL); + cb_reg_hl_hex(w, NULL); + cb_reg_m_hex(w, NULL); + + // Deselect all "Dec" buttons + cpuregs_ctrl.pADec->value(0); + cpuregs_ctrl.pBDec->value(0); + cpuregs_ctrl.pCDec->value(0); + cpuregs_ctrl.pDDec->value(0); + cpuregs_ctrl.pEDec->value(0); + cpuregs_ctrl.pHDec->value(0); + cpuregs_ctrl.pLDec->value(0); + cpuregs_ctrl.pPCDec->value(0); + cpuregs_ctrl.pSPDec->value(0); + cpuregs_ctrl.pBCDec->value(0); + cpuregs_ctrl.pDEDec->value(0); + cpuregs_ctrl.pHLDec->value(0); + cpuregs_ctrl.pMDec->value(0); + + // Select all "Hex" buttons + cpuregs_ctrl.pAHex->value(1); + cpuregs_ctrl.pBHex->value(1); + cpuregs_ctrl.pCHex->value(1); + cpuregs_ctrl.pDHex->value(1); + cpuregs_ctrl.pEHex->value(1); + cpuregs_ctrl.pHHex->value(1); + cpuregs_ctrl.pLHex->value(1); + cpuregs_ctrl.pPCHex->value(1); + cpuregs_ctrl.pSPHex->value(1); + cpuregs_ctrl.pBCHex->value(1); + cpuregs_ctrl.pDEHex->value(1); + cpuregs_ctrl.pHLHex->value(1); + cpuregs_ctrl.pMHex->value(1); + + // reselect the "All Hex" button + cpuregs_ctrl.pAllHex->value(1); +} + +/* +============================================================================ +Routine to handle Reg All Dec display mode +============================================================================ +*/ +void cb_reg_all_dec(Fl_Widget* w, void*) +{ + // Change format of all items to Dec + cb_reg_a_dec(w, NULL); + cb_reg_b_dec(w, NULL); + cb_reg_c_dec(w, NULL); + cb_reg_d_dec(w, NULL); + cb_reg_e_dec(w, NULL); + cb_reg_h_dec(w, NULL); + cb_reg_l_dec(w, NULL); + cb_reg_pc_dec(w, NULL); + cb_reg_sp_dec(w, NULL); + cb_reg_bc_dec(w, NULL); + cb_reg_de_dec(w, NULL); + cb_reg_hl_dec(w, NULL); + cb_reg_m_dec(w, NULL); + + // Deselect all "Hex" buttons + cpuregs_ctrl.pAHex->value(0); + cpuregs_ctrl.pBHex->value(0); + cpuregs_ctrl.pCHex->value(0); + cpuregs_ctrl.pDHex->value(0); + cpuregs_ctrl.pEHex->value(0); + cpuregs_ctrl.pHHex->value(0); + cpuregs_ctrl.pLHex->value(0); + cpuregs_ctrl.pPCHex->value(0); + cpuregs_ctrl.pSPHex->value(0); + cpuregs_ctrl.pBCHex->value(0); + cpuregs_ctrl.pDEHex->value(0); + cpuregs_ctrl.pHLHex->value(0); + cpuregs_ctrl.pMHex->value(0); + + // Select all "Dec" buttons + cpuregs_ctrl.pADec->value(1); + cpuregs_ctrl.pBDec->value(1); + cpuregs_ctrl.pCDec->value(1); + cpuregs_ctrl.pDDec->value(1); + cpuregs_ctrl.pEDec->value(1); + cpuregs_ctrl.pHDec->value(1); + cpuregs_ctrl.pLDec->value(1); + cpuregs_ctrl.pPCDec->value(1); + cpuregs_ctrl.pSPDec->value(1); + cpuregs_ctrl.pBCDec->value(1); + cpuregs_ctrl.pDEDec->value(1); + cpuregs_ctrl.pHLDec->value(1); + cpuregs_ctrl.pMDec->value(1); + + // Reselect "All" Dec button + cpuregs_ctrl.pAllDec->value(1); +} + +/* +============================================================================ +Routine to create the PeripheralSetup Window and tabs +============================================================================ +*/ +void cb_CpuRegs (Fl_Widget* w, void*) +{ + Fl_Box* o; + + if (gcpuw != NULL) + return; + + // Create Peripheral Setup window + gcpuw = new Fl_Window(630, 400, "CPU Registers"); + gcpuw->callback(cb_cpuregswin); + + // Create a menu for the new window. + cpuregs_ctrl.pMenu = new Fl_Menu_Bar(0, 0, 630, MENU_HEIGHT-2); + cpuregs_ctrl.pMenu->menu(gCpuRegs_menuitems); + + // Create static text boxes + o = new Fl_Box(FL_NO_BOX, 20, 20+MENU_HEIGHT, 50, 15, "PC"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 20, 45+MENU_HEIGHT, 50, 15, "SP"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 20, 70+MENU_HEIGHT, 50, 15, "B"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 20, 95+MENU_HEIGHT, 50, 15, "D"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 20, 120+MENU_HEIGHT, 50, 15, "H"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + o = new Fl_Box(FL_NO_BOX, 120, 20+MENU_HEIGHT, 50, 15, "A"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 120, 70+MENU_HEIGHT, 50, 15, "C"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 120, 95+MENU_HEIGHT, 50, 15, "E"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 120, 120+MENU_HEIGHT, 50, 15, "L"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + o = new Fl_Box(FL_NO_BOX, 220, 70+MENU_HEIGHT, 50, 15, "BC"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 220, 95+MENU_HEIGHT, 50, 15, "DE"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 220, 120+MENU_HEIGHT, 50, 15, "HL"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 220, 145+MENU_HEIGHT, 50, 15, "M"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + + // Program Counter edit box + cpuregs_ctrl.pRegPC = new Fl_Input(50, 19+MENU_HEIGHT, 60, 20, ""); + cpuregs_ctrl.pRegPC->deactivate(); + cpuregs_ctrl.pRegPC->callback(cb_reg_pc_changed); + cpuregs_ctrl.pRegPC->value("0x0000"); + + // Accumulator Edit Box + cpuregs_ctrl.pRegA = new Fl_Input(150, 19+MENU_HEIGHT, 60, 20, ""); + cpuregs_ctrl.pRegA->deactivate(); + cpuregs_ctrl.pRegA->value("0x00"); + + // Stack Pointer edit box + cpuregs_ctrl.pRegSP = new Fl_Input(50, 44+MENU_HEIGHT, 60, 20, ""); + cpuregs_ctrl.pRegSP->deactivate(); + cpuregs_ctrl.pRegSP->callback(cb_reg_sp_changed); + cpuregs_ctrl.pRegSP->value("0x0000"); + + // Create Flag checkboxes + // Sign flag + cpuregs_ctrl.pSFlag = new Fl_Check_Button(223, 19+MENU_HEIGHT, 30, 20, "S"); + cpuregs_ctrl.pSFlag->deactivate(); + + // Zero flag + cpuregs_ctrl.pZFlag = new Fl_Check_Button(253, 19+MENU_HEIGHT, 30, 20, "Z"); + cpuregs_ctrl.pZFlag->deactivate(); + + // Carry flag + cpuregs_ctrl.pCFlag = new Fl_Check_Button(290, 19+MENU_HEIGHT, 30, 20, "C"); + cpuregs_ctrl.pCFlag->deactivate(); + + // TS flag + cpuregs_ctrl.pTSFlag = new Fl_Check_Button(148, 44+MENU_HEIGHT, 40, 20, "TS"); + cpuregs_ctrl.pTSFlag->deactivate(); + + // AC flag + cpuregs_ctrl.pACFlag = new Fl_Check_Button(185, 44+MENU_HEIGHT, 40, 20, "AC"); + cpuregs_ctrl.pACFlag->deactivate(); + + // Parity flag + cpuregs_ctrl.pPFlag = new Fl_Check_Button(223, 44+MENU_HEIGHT, 30, 20, "P"); + cpuregs_ctrl.pPFlag->deactivate(); + + // Overflow flag + cpuregs_ctrl.pOVFlag = new Fl_Check_Button(253, 44+MENU_HEIGHT, 40, 20, "OV"); + cpuregs_ctrl.pOVFlag->deactivate(); + + // X flag + cpuregs_ctrl.pXFlag = new Fl_Check_Button(290, 44+MENU_HEIGHT, 30, 20, "X"); + cpuregs_ctrl.pXFlag->deactivate(); + + // Register B Edit Box + cpuregs_ctrl.pRegB = new Fl_Input(50, 69+MENU_HEIGHT, 60, 20, ""); + cpuregs_ctrl.pRegB->deactivate(); + cpuregs_ctrl.pRegB->value("0x00"); + + // Register C Edit Box + cpuregs_ctrl.pRegC = new Fl_Input(150, 69+MENU_HEIGHT, 60, 20, ""); + cpuregs_ctrl.pRegC->deactivate(); + cpuregs_ctrl.pRegC->value("0x00"); + + // Register BC Edit Box + cpuregs_ctrl.pRegBC = new Fl_Input(250, 69+MENU_HEIGHT, 60, 20, ""); + cpuregs_ctrl.pRegBC->deactivate(); + cpuregs_ctrl.pRegBC->value("0x0000"); + + // Register D Edit Box + cpuregs_ctrl.pRegD = new Fl_Input(50, 94+MENU_HEIGHT, 60, 20, ""); + cpuregs_ctrl.pRegD->deactivate(); + cpuregs_ctrl.pRegD->value("0x00"); + + // Register E Edit Box + cpuregs_ctrl.pRegE = new Fl_Input(150, 94+MENU_HEIGHT, 60, 20, ""); + cpuregs_ctrl.pRegE->deactivate(); + cpuregs_ctrl.pRegE->value("0x00"); + + // Register DE Edit Box + cpuregs_ctrl.pRegDE = new Fl_Input(250, 94+MENU_HEIGHT, 60, 20, ""); + cpuregs_ctrl.pRegDE->deactivate(); + cpuregs_ctrl.pRegDE->value("0x0000"); + + // Register H Edit Box + cpuregs_ctrl.pRegH = new Fl_Input(50, 119+MENU_HEIGHT, 60, 20, ""); + cpuregs_ctrl.pRegH->deactivate(); + cpuregs_ctrl.pRegH->callback(cb_reg_h_changed); + cpuregs_ctrl.pRegH->value("0x00"); + + // Register L Edit Box + cpuregs_ctrl.pRegL = new Fl_Input(150, 119+MENU_HEIGHT, 60, 20, ""); + cpuregs_ctrl.pRegL->deactivate(); + cpuregs_ctrl.pRegL->callback(cb_reg_l_changed); + cpuregs_ctrl.pRegL->value("0x00"); + + // Register HL Edit Box + cpuregs_ctrl.pRegHL = new Fl_Input(250, 119+MENU_HEIGHT, 60, 20, ""); + cpuregs_ctrl.pRegHL->deactivate(); + cpuregs_ctrl.pRegHL->callback(cb_reg_hl_changed); + cpuregs_ctrl.pRegHL->value("0x0000"); + + // Register M Edit Box + cpuregs_ctrl.pRegM = new Fl_Input(250, 144+MENU_HEIGHT, 60, 20, ""); + cpuregs_ctrl.pRegM->deactivate(); + cpuregs_ctrl.pRegM->value("0x00"); + + + strcpy(cpuregs_ctrl.sPCfmt, "0x%04X"); + strcpy(cpuregs_ctrl.sSPfmt, "0x%04X"); + strcpy(cpuregs_ctrl.sBCfmt, "0x%04X"); + strcpy(cpuregs_ctrl.sDEfmt, "0x%04X"); + strcpy(cpuregs_ctrl.sHLfmt, "0x%04X"); + strcpy(cpuregs_ctrl.sAfmt, "0x%02X"); + strcpy(cpuregs_ctrl.sBfmt, "0x%02X"); + strcpy(cpuregs_ctrl.sCfmt, "0x%02X"); + strcpy(cpuregs_ctrl.sDfmt, "0x%02X"); + strcpy(cpuregs_ctrl.sEfmt, "0x%02X"); + strcpy(cpuregs_ctrl.sHfmt, "0x%02X"); + strcpy(cpuregs_ctrl.sLfmt, "0x%02X"); + strcpy(cpuregs_ctrl.sMfmt, "0x%02X"); + + // Group the Reg "All" radio buttons together + { + cpuregs_ctrl.g = new Fl_Group(440, 10 + MENU_HEIGHT, 100, 20, ""); + + // Display format for Reg A + o = new Fl_Box(FL_NO_BOX, 410, 11+MENU_HEIGHT, 50, 15, "All"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + cpuregs_ctrl.pAllHex = new Fl_Round_Button(440, 10 + MENU_HEIGHT, 50, 20, "Hex"); + cpuregs_ctrl.pAllHex->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pAllHex->callback(cb_reg_all_hex); + cpuregs_ctrl.pAllHex->value(1); + + cpuregs_ctrl.pAllDec = new Fl_Round_Button(490, 10 + MENU_HEIGHT, 50, 20, "Dec"); + cpuregs_ctrl.pAllDec->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pAllDec->callback(cb_reg_all_dec); + cpuregs_ctrl.g->end(); + } + + // Group the Reg A radio buttons together + { + cpuregs_ctrl.g = new Fl_Group(370, 30 + MENU_HEIGHT, 100, 20, ""); + + // Display format for Reg A + o = new Fl_Box(FL_NO_BOX, 340, 31+MENU_HEIGHT, 50, 15, "A"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + cpuregs_ctrl.pAHex = new Fl_Round_Button(370, 30 + MENU_HEIGHT, 50, 20, "Hex"); + cpuregs_ctrl.pAHex->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pAHex->callback(cb_reg_a_hex); + cpuregs_ctrl.pAHex->value(1); + + cpuregs_ctrl.pADec = new Fl_Round_Button(420, 30 + MENU_HEIGHT, 50, 20, "Dec"); + cpuregs_ctrl.pADec->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pADec->callback(cb_reg_a_dec); + cpuregs_ctrl.g->end(); + } + + // Group the Reg B radio buttons togther + { + cpuregs_ctrl.g = new Fl_Group(370, 50 + MENU_HEIGHT, 100, 20, ""); + + // Display format for Reg B + o = new Fl_Box(FL_NO_BOX, 340, 51+MENU_HEIGHT, 50, 15, "B"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + cpuregs_ctrl.pBHex = new Fl_Round_Button(370, 50 + MENU_HEIGHT, 50, 20, "Hex"); + cpuregs_ctrl.pBHex->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pBHex->callback(cb_reg_b_hex); + cpuregs_ctrl.pBHex->value(1); + + cpuregs_ctrl.pBDec = new Fl_Round_Button(420, 50 + MENU_HEIGHT, 50, 20, "Dec"); + cpuregs_ctrl.pBDec->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pBDec->callback(cb_reg_b_dec); + cpuregs_ctrl.g->end(); + } + + // Group the Reg C radio buttons togther + { + cpuregs_ctrl.g = new Fl_Group(370, 70 + MENU_HEIGHT, 100, 20, ""); + + // Display format for Reg C + o = new Fl_Box(FL_NO_BOX, 340, 71+MENU_HEIGHT, 50, 15, "C"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + cpuregs_ctrl.pCHex = new Fl_Round_Button(370, 70 + MENU_HEIGHT, 50, 20, "Hex"); + cpuregs_ctrl.pCHex->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pCHex->callback(cb_reg_c_hex); + cpuregs_ctrl.pCHex->value(1); + + cpuregs_ctrl.pCDec = new Fl_Round_Button(420, 70 + MENU_HEIGHT, 50, 20, "Dec"); + cpuregs_ctrl.pCDec->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pCDec->callback(cb_reg_c_dec); + cpuregs_ctrl.g->end(); + } + + // Group the Reg D radio buttons togther + { + cpuregs_ctrl.g = new Fl_Group(370, 90 + MENU_HEIGHT, 100, 20, ""); + + // Display format for Reg D + o = new Fl_Box(FL_NO_BOX, 340, 91+MENU_HEIGHT, 50, 15, "D"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + cpuregs_ctrl.pDHex = new Fl_Round_Button(370, 90 + MENU_HEIGHT, 50, 20, "Hex"); + cpuregs_ctrl.pDHex->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pDHex->callback(cb_reg_d_hex); + cpuregs_ctrl.pDHex->value(1); + + cpuregs_ctrl.pDDec = new Fl_Round_Button(420, 90 + MENU_HEIGHT, 50, 20, "Dec"); + cpuregs_ctrl.pDDec->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pDDec->callback(cb_reg_d_dec); + cpuregs_ctrl.g->end(); + } + + // Group the Reg E radio buttons togther + { + cpuregs_ctrl.g = new Fl_Group(370, 110 + MENU_HEIGHT, 100, 20, ""); + + // Display format for Reg E + o = new Fl_Box(FL_NO_BOX, 340, 111+MENU_HEIGHT, 50, 15, "E"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + cpuregs_ctrl.pEHex = new Fl_Round_Button(370, 110 + MENU_HEIGHT, 50, 20, "Hex"); + cpuregs_ctrl.pEHex->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pEHex->callback(cb_reg_e_hex); + cpuregs_ctrl.pEHex->value(1); + + cpuregs_ctrl.pEDec = new Fl_Round_Button(420, 110 + MENU_HEIGHT, 50, 20, "Dec"); + cpuregs_ctrl.pEDec->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pEDec->callback(cb_reg_e_dec); + cpuregs_ctrl.g->end(); + } + + // Group the Reg H radio buttons togther + { + cpuregs_ctrl.g = new Fl_Group(370, 130 + MENU_HEIGHT, 100, 20, ""); + + // Display format for Reg H + o = new Fl_Box(FL_NO_BOX, 340, 131+MENU_HEIGHT, 50, 15, "H"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + cpuregs_ctrl.pHHex = new Fl_Round_Button(370, 130 + MENU_HEIGHT, 50, 20, "Hex"); + cpuregs_ctrl.pHHex->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pHHex->callback(cb_reg_h_hex); + cpuregs_ctrl.pHHex->value(1); + + cpuregs_ctrl.pHDec = new Fl_Round_Button(420, 130 + MENU_HEIGHT, 50, 20, "Dec"); + cpuregs_ctrl.pHDec->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pHDec->callback(cb_reg_h_dec); + cpuregs_ctrl.g->end(); + } + + // Group the Reg L radio buttons togther + { + cpuregs_ctrl.g = new Fl_Group(370, 150 + MENU_HEIGHT, 100, 20, ""); + + // Display format for Reg L + o = new Fl_Box(FL_NO_BOX, 340, 151+MENU_HEIGHT, 50, 15, "L"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + cpuregs_ctrl.pLHex = new Fl_Round_Button(370, 150 + MENU_HEIGHT, 50, 20, "Hex"); + cpuregs_ctrl.pLHex->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pLHex->callback(cb_reg_l_hex); + cpuregs_ctrl.pLHex->value(1); + + cpuregs_ctrl.pLDec = new Fl_Round_Button(420, 150 + MENU_HEIGHT, 50, 20, "Dec"); + cpuregs_ctrl.pLDec->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pLDec->callback(cb_reg_l_dec); + cpuregs_ctrl.g->end(); + } + + + // Group the Reg PC radio buttons togther + { + cpuregs_ctrl.g = new Fl_Group(520, 30 + MENU_HEIGHT, 100, 20, ""); + + // Display format for Reg L + o = new Fl_Box(FL_NO_BOX, 490, 31+MENU_HEIGHT, 50, 15, "PC"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + cpuregs_ctrl.pPCHex = new Fl_Round_Button(520, 30 + MENU_HEIGHT, 50, 20, "Hex"); + cpuregs_ctrl.pPCHex->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pPCHex->callback(cb_reg_pc_hex); + cpuregs_ctrl.pPCHex->value(1); + + cpuregs_ctrl.pPCDec = new Fl_Round_Button(570, 30 + MENU_HEIGHT, 50, 20, "Dec"); + cpuregs_ctrl.pPCDec->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pPCDec->callback(cb_reg_pc_dec); + cpuregs_ctrl.g->end(); + } + + // Group the Reg SP radio buttons togther + { + cpuregs_ctrl.g = new Fl_Group(520, 50 + MENU_HEIGHT, 100, 20, ""); + + // Display format for Reg L + o = new Fl_Box(FL_NO_BOX, 490, 51+MENU_HEIGHT, 50, 15, "SP"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + cpuregs_ctrl.pSPHex = new Fl_Round_Button(520, 50 + MENU_HEIGHT, 50, 20, "Hex"); + cpuregs_ctrl.pSPHex->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pSPHex->callback(cb_reg_sp_hex); + cpuregs_ctrl.pSPHex->value(1); + + cpuregs_ctrl.pSPDec = new Fl_Round_Button(570, 50 + MENU_HEIGHT, 50, 20, "Dec"); + cpuregs_ctrl.pSPDec->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pSPDec->callback(cb_reg_sp_dec); + cpuregs_ctrl.g->end(); + } + + // Group the Reg BC radio buttons togther + { + cpuregs_ctrl.g = new Fl_Group(520, 70 + MENU_HEIGHT, 100, 20, ""); + + // Display format for Reg L + o = new Fl_Box(FL_NO_BOX, 490, 71+MENU_HEIGHT, 50, 15, "BC"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + cpuregs_ctrl.pBCHex = new Fl_Round_Button(520, 70 + MENU_HEIGHT, 50, 20, "Hex"); + cpuregs_ctrl.pBCHex->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pBCHex->callback(cb_reg_bc_hex); + cpuregs_ctrl.pBCHex->value(1); + + cpuregs_ctrl.pBCDec = new Fl_Round_Button(570, 70 + MENU_HEIGHT, 50, 20, "Dec"); + cpuregs_ctrl.pBCDec->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pBCDec->callback(cb_reg_bc_dec); + cpuregs_ctrl.g->end(); + } + + // Group the Reg DE radio buttons togther + { + cpuregs_ctrl.g = new Fl_Group(520, 90 + MENU_HEIGHT, 100, 20, ""); + + // Display format for Reg L + o = new Fl_Box(FL_NO_BOX, 490, 91+MENU_HEIGHT, 50, 15, "DE"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + cpuregs_ctrl.pDEHex = new Fl_Round_Button(520, 90 + MENU_HEIGHT, 50, 20, "Hex"); + cpuregs_ctrl.pDEHex->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pDEHex->callback(cb_reg_de_hex); + cpuregs_ctrl.pDEHex->value(1); + + cpuregs_ctrl.pDEDec = new Fl_Round_Button(570, 90 + MENU_HEIGHT, 50, 20, "Dec"); + cpuregs_ctrl.pDEDec->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pDEDec->callback(cb_reg_de_dec); + cpuregs_ctrl.g->end(); + } + + // Group the Reg HL radio buttons togther + { + cpuregs_ctrl.g = new Fl_Group(520, 110 + MENU_HEIGHT, 100, 20, ""); + + // Display format for Reg HL + o = new Fl_Box(FL_NO_BOX, 490, 111+MENU_HEIGHT, 50, 15, "HL"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + cpuregs_ctrl.pHLHex = new Fl_Round_Button(520, 110 + MENU_HEIGHT, 50, 20, "Hex"); + cpuregs_ctrl.pHLHex->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pHLHex->callback(cb_reg_hl_hex); + cpuregs_ctrl.pHLHex->value(1); + + cpuregs_ctrl.pHLDec = new Fl_Round_Button(570, 110 + MENU_HEIGHT, 50, 20, "Dec"); + cpuregs_ctrl.pHLDec->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pHLDec->callback(cb_reg_hl_dec); + cpuregs_ctrl.g->end(); + } + + // Group the Reg M radio buttons togther + { + cpuregs_ctrl.g = new Fl_Group(520, 130 + MENU_HEIGHT, 100, 20, ""); + + // Display format for Reg HL + o = new Fl_Box(FL_NO_BOX, 490, 131+MENU_HEIGHT, 50, 15, "M"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + cpuregs_ctrl.pMHex = new Fl_Round_Button(520, 130 + MENU_HEIGHT, 50, 20, "Hex"); + cpuregs_ctrl.pMHex->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pMHex->callback(cb_reg_m_hex); + cpuregs_ctrl.pMHex->value(1); + + cpuregs_ctrl.pMDec = new Fl_Round_Button(570, 130 + MENU_HEIGHT, 50, 20, "Dec"); + cpuregs_ctrl.pMDec->type(FL_RADIO_BUTTON); + cpuregs_ctrl.pMDec->callback(cb_reg_m_dec); + cpuregs_ctrl.g->end(); + } + + // Create Instruction Trace Text Boxes + o = new Fl_Box(FL_NO_BOX, 20, 180+MENU_HEIGHT, 50, 15, "Instruction Trace"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_DOWN_BOX, 20, 200+MENU_HEIGHT, 520, 124, ""); + cpuregs_ctrl.iInstTraceHead = 0; + + // Create checkbox to disable realtime trace + cpuregs_ctrl.pDisableTrace = new Fl_Check_Button(200, 180+MENU_HEIGHT, 180, 20, "Disable Real-time Trace"); + cpuregs_ctrl.pDisableTrace->callback(cb_disable_realtime_trace); + + + // Create Stack Box + o = new Fl_Box(FL_NO_BOX, 550, 180+MENU_HEIGHT, 50, 15, "Stack"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_DOWN_BOX, 550, 200+MENU_HEIGHT, 60, 124, ""); + + // Create Stop button + cpuregs_ctrl.pStop = new Fl_Button(30, 365, 80, 25, "Stop"); + cpuregs_ctrl.pStop->callback(cb_debug_stop); + + // Create Step button + cpuregs_ctrl.pStep = new Fl_Button(130, 365, 80, 25, "Step"); + cpuregs_ctrl.pStep->deactivate(); + cpuregs_ctrl.pStep->callback(cb_debug_step); + + // Create Run button + cpuregs_ctrl.pRun = new Fl_Button(230, 365, 80, 25, "Run"); + cpuregs_ctrl.pRun->deactivate(); + cpuregs_ctrl.pRun->callback(cb_debug_run); + + // Create Redraw button + cpuregs_ctrl.pRedraw = new Fl_Button(330, 365, 80, 25, "Redraw"); + cpuregs_ctrl.pRedraw->deactivate(); + cpuregs_ctrl.pRedraw->callback(cb_redraw_trace); + + // Set Debug callback + debug_set_monitor_callback(debug_cpuregs_cb); + + // Show the new window + gcpuw->show(); + + // Indicate an active debug window + gDebugActive++; +} + + diff --git a/src/cpuregs.h b/src/cpuregs.h new file mode 100644 index 0000000..5da1f1e --- /dev/null +++ b/src/cpuregs.h @@ -0,0 +1,130 @@ +/* cpuregs.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef CPUREGS_H +#define CPUREGS_H + +#include +#include +#include +#include +#include + +void cb_CpuRegs(Fl_Widget* w, void*); + +typedef struct cpuregs_ctrl_struct +{ + Fl_Menu_Bar* pMenu; + + Fl_Check_Button* pEnable; + + Fl_Input* pRegA; + Fl_Input* pRegF; + Fl_Input* pRegB; + Fl_Input* pRegC; + Fl_Input* pRegD; + Fl_Input* pRegE; + Fl_Input* pRegH; + Fl_Input* pRegL; + Fl_Input* pRegBC; + Fl_Input* pRegDE; + Fl_Input* pRegHL; + Fl_Input* pRegPC; + Fl_Input* pRegSP; + Fl_Input* pRegM; + + Fl_Check_Button* pSFlag; + Fl_Check_Button* pZFlag; + Fl_Check_Button* pTSFlag; + Fl_Check_Button* pACFlag; + Fl_Check_Button* pPFlag; + Fl_Check_Button* pOVFlag; + Fl_Check_Button* pXFlag; + Fl_Check_Button* pCFlag; + + Fl_Round_Button* pAllHex; + Fl_Round_Button* pAllDec; + Fl_Round_Button* pAHex; + Fl_Round_Button* pADec; + Fl_Round_Button* pBHex; + Fl_Round_Button* pBDec; + Fl_Round_Button* pCHex; + Fl_Round_Button* pCDec; + Fl_Round_Button* pDHex; + Fl_Round_Button* pDDec; + Fl_Round_Button* pEHex; + Fl_Round_Button* pEDec; + Fl_Round_Button* pHHex; + Fl_Round_Button* pHDec; + Fl_Round_Button* pLHex; + Fl_Round_Button* pLDec; + Fl_Round_Button* pPCHex; + Fl_Round_Button* pPCDec; + Fl_Round_Button* pSPHex; + Fl_Round_Button* pSPDec; + Fl_Round_Button* pBCHex; + Fl_Round_Button* pBCDec; + Fl_Round_Button* pDEHex; + Fl_Round_Button* pDEDec; + Fl_Round_Button* pHLHex; + Fl_Round_Button* pHLDec; + Fl_Round_Button* pMHex; + Fl_Round_Button* pMDec; + + Fl_Box* pInstTrace[8]; + char sInstTrace[8][120]; + int iInstTraceHead; + Fl_Check_Button* pDisableTrace; + + Fl_Button* pStop; + Fl_Button* pStep; + Fl_Button* pRun; + Fl_Button* pRedraw; + + char sPCfmt[8]; + char sSPfmt[8]; + char sAfmt[8]; + char sBfmt[8]; + char sCfmt[8]; + char sDfmt[8]; + char sEfmt[8]; + char sHfmt[8]; + char sLfmt[8]; + char sBCfmt[8]; + char sDEfmt[8]; + char sHLfmt[8]; + char sMfmt[8]; + + Fl_Group* g; + +} cpuregs_ctrl_t; + + +#endif From 72ff8450a28a19f722dbb403e8e45cd020ad4ce8 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 18 Apr 2006 23:51:44 +0000 Subject: [PATCH 038/327] Added memory save and load functions --- src/intelhex.c | 44 +++++- src/intelhex.h | 1 + src/memedit.cpp | 408 ++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 441 insertions(+), 12 deletions(-) diff --git a/src/intelhex.c b/src/intelhex.c index b8bc1c1..91c5f82 100644 --- a/src/intelhex.c +++ b/src/intelhex.c @@ -42,6 +42,7 @@ #include #include #include "intelhex.h" +#include "memory.h" /* some ansi prototypes.. maybe ought to make a .h file */ @@ -55,7 +56,7 @@ int parse_hex_line(char *theline, int bytes[], int *addr, int *num, int *code); void hexout(FILE *fhex, int byte, int memory_location, int end); -extern char memory[65536]; /* the memory is global */ +//extern char memory[65536]; /* the memory is global */ /* parses a line of intel hex code, stores the data in bytes[] */ /* and the beginning address in addr, and returns a 1 if the */ @@ -169,6 +170,45 @@ int load_hex_file(char *filename, char *buffer, unsigned short *start_addr) return n; } +/* the command string format is "S begin end filename" where */ +/* "begin" and "end" are the locations to dump to the intel */ +/* hex file, specified in hexidecimal. */ + +void save_hex_file_ext(int begin, int end, int region, FILE* fd) +{ + int addr; + char buffer[16384]; + int count, len, x; + + if (begin > end) { + return; + } + + // Calculate length of memory region + count = end - begin + 1; + addr = begin; + len = count > sizeof(buffer) ? sizeof(buffer) : count; + + // Copy data out 1 buffer at a time + while (count > 0) + { + // Read next buffer from memory + get_memory8_ext(region, addr, len, buffer); + + // Output all bytes in the buffer + for (x = 0; x < len; x++) + hexout(fd, buffer[x], addr + x - begin, 0); + + // Update count + count -= len; + addr += len; + + // Update len for next loop + len = count > sizeof(buffer) ? sizeof(buffer) : count; + } + hexout(fd, 0, 0, 1); +} + /* the command string format is "S begin end filename" where */ /* "begin" and "end" are the locations to dump to the intel */ @@ -182,7 +222,7 @@ void save_hex_file(int begin, int end, FILE* fd) return; } for (addr=begin; addr <= end; addr++) - hexout(fd, memory[addr], addr, 0); + hexout(fd, get_memory8((unsigned short) addr), addr, 0); hexout(fd, 0, 0, 1); } diff --git a/src/intelhex.h b/src/intelhex.h index 50b31ae..bf15e86 100644 --- a/src/intelhex.h +++ b/src/intelhex.h @@ -35,6 +35,7 @@ int load_hex_file(char *filename, char *buffer, unsigned short *start_addr); /* this writes a part of memory[] to an intel hex file */ void save_hex_file(int begin, int end, FILE* fd); +void save_hex_file_ext(int begin, int end, int region, FILE* fd); #endif diff --git a/src/memedit.cpp b/src/memedit.cpp index 2b7428b..a5f38f2 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -52,9 +53,11 @@ #include "memedit.h" #include "memory.h" #include "cpu.h" +#include "cpuregs.h" extern "C" +{ #include "intelhex.h" - +} typedef struct memedit_ctrl_struct { @@ -78,9 +81,13 @@ typedef struct memedit_dialog Fl_Window* pWin; // Dialog box window Fl_Input* pFilename; Fl_Input* pStartAddr; + Fl_Input* pEndSaveAddr; + Fl_Input* pSaveLen; Fl_Box* pEndAddr; Fl_Button* pBrowse; Fl_Box* pBytes; + Fl_Button* pHex; + Fl_Button* pBin; char sBytes[20]; int iOk; } memedit_dialog_t; @@ -89,6 +96,8 @@ void cb_PeripheralDevices (Fl_Widget* w, void*); void cb_load(Fl_Widget* w, void*); void cb_save_bin(Fl_Widget* w, void*); void cb_save_hex(Fl_Widget* w, void*); +void cb_save_memory(Fl_Widget* w, void*); +int str_to_i(const char *pStr); extern "C" { @@ -101,12 +110,11 @@ extern uchar gRampac; Fl_Menu_Item gMemEdit_menuitems[] = { { "&File", 0, 0, 0, FL_SUBMENU }, { "Load from File...", 0, cb_load, 0 }, - { "Save to BIN...", 0, cb_save_bin, 0 }, - { "Save to HEX...", 0, cb_save_hex, 0 }, + { "Save to File...", 0, cb_save_memory, 0 }, { 0 }, { "&Tools", 0, 0, 0, FL_SUBMENU }, - { "CPU Registers", 0, 0 }, + { "CPU Registers", 0, cb_CpuRegs }, { "Assembler", 0, 0 }, { "Disassembler", 0, disassembler_cb }, { "Debugger", 0, 0 }, @@ -160,12 +168,28 @@ void cb_region(Fl_Widget* w, void*) // Set new region here memedit_ctrl.pMemEdit->SetScrollSize(); - memedit_ctrl.pMemEdit->redraw(); - memedit_ctrl.pMemEdit->UpdateAddressText(); } +/* +============================================================================ +Callback routine for the Memory Range edit box +============================================================================ +*/ +void cb_memory_range(Fl_Widget* w, void*) +{ + const char *pStr; + int address; + + pStr = memedit_ctrl.pMemRange->value(); + address = str_to_i(pStr); + + // Set new region here + memedit_ctrl.pMemEdit->MoveTo(address); +} + + void load_okButton_cb(Fl_Widget* w, void*) { @@ -185,6 +209,18 @@ void load_okButton_cb(Fl_Widget* w, void*) return; } + // Test if writing - need end address or length if so + if (gDialog.pHex != NULL) + { + if ((strlen(gDialog.pEndSaveAddr->value()) == 0) && + (strlen(gDialog.pSaveLen->value()) == 0)) + { + fl_alert("Please supply end address or length"); + gDialog.pEndSaveAddr->take_focus(); + return; + } + } + // Indicate OK button pressed gDialog.iOk = 1; @@ -247,12 +283,96 @@ void update_length_field(const char *filename) } } +void load_file_to_mem(const char *filename, int address) +{ + int len; + unsigned char *buffer; + unsigned short start_addr; + + // Check for hex file + len = strlen(filename); + if (((filename[len-1] | 0x20) == 'x') && + ((filename[len-2] | 0x20) == 'e') && + ((filename[len-3] | 0x20) == 'h')) + { + buffer = new unsigned char[65536]; + + // Check if hex file format is valid + len = load_hex_file((char *) filename, (char *) buffer, &start_addr); + + if (len == 0) + return; + else + { + // Write data to the selected region + set_memory8_ext(memedit_ctrl.pMemEdit->GetRegionEnum(), address, len, buffer); + } + + // Free the memory + delete buffer; + } + else + { + // Open file as binary + FILE* fd; + if ((fd = fopen(filename, "r")) != NULL) + { + // Determine file length + fseek(fd, 0, SEEK_END); + len = ftell(fd); + buffer = new unsigned char[len]; + fseek(fd, 0, SEEK_SET); + fread(buffer, 1, len, fd); + set_memory8_ext(memedit_ctrl.pMemEdit->GetRegionEnum(), address, len, buffer); + fclose(fd); + + delete buffer; + } + + } +} + +void save_mem_to_file(const char *filename, int address, int count, int save_as_hex) +{ + unsigned char *buffer; + FILE *fd; + + + // Check for hex file + if (save_as_hex) + { + // Try to open the file for write + fd = fopen(filename, "w+"); + if (fd == NULL) + return; + + save_hex_file_ext(address, address+count-1, memedit_ctrl.pMemEdit->GetRegionEnum(), fd); + + fclose(fd); + } + else + { + // Open file as binary + FILE* fd; + if ((fd = fopen(filename, "wb+")) != NULL) + { + buffer = new unsigned char[count]; + get_memory8_ext(memedit_ctrl.pMemEdit->GetRegionEnum(), address, count, buffer); + fwrite(buffer, count, 1, fd); + fclose(fd); + + delete buffer; + } + + } +} + void load_browseButton_cb(Fl_Widget* w, void*) { int count; const char * filename; - Fl_File_Chooser file(".","*.{bin,hex}",1,"Load Optional ROM file"); + Fl_File_Chooser file(".","*.{bin,hex}",1,"Select File to Open"); file.show(); while (file.visible()) @@ -272,6 +392,73 @@ void load_browseButton_cb(Fl_Widget* w, void*) update_length_field(filename); } +void save_browseButton_cb(Fl_Widget* w, void*) +{ + int count, len; + const char * filename; + char filespec[10]; + char filepath[256]; + FILE *fd; + int c; + + if (gDialog.pHex->value()) + strcpy(filespec, "*.hex"); + else + strcpy(filespec, "*.bin"); + Fl_File_Chooser file(".", filespec, Fl_File_Chooser::CREATE, "Select File to Open"); + + while (1) + { + file.show(); + while (file.visible()) + Fl::wait(); + + // Get filename + count = file.count(); + if (count != 1) + return; + filename = file.value(1); + if (filename == 0) + return; + + // Try to open the ouput file + fd = fopen(filename, "rb+"); + if (fd != NULL) + { + // File already exists! Check for overwrite! + fclose(fd); + + c = fl_choice("Overwrite existing file?", "Cancel", "Yes", "No"); + + // Test if Cancel selected + if (c == 0) + return; + + if (c == 1) + break; + } + } + + // Check if filename ends with ".hex" + len = strlen(filename); + if (((filename[len-1] | 0x20) == filespec[4]) && + ((filename[len-2] | 0x20) == filespec[3]) && + ((filename[len-3] | 0x20) == filespec[2]) && + ((filename[len-4] == '.'))) + { + // Update filename field + gDialog.pFilename->value(filename); + } + else + { + strcpy(filepath, filename); + strcat(filepath, &filespec[1]); + + // Update filename field + gDialog.pFilename->value(filepath); + } +} + void load_filename_cb(Fl_Widget* w, void*) { const char *filename = gDialog.pFilename->value(); @@ -286,10 +473,11 @@ Callback routine for the Load Menu Item */ void cb_load(Fl_Widget* w, void*) { - Fl_Box *o; Fl_Return_Button *rb; Fl_Button *b; + const char * pStr; + int address; // Build dialog box for selecting file and Memory Range gDialog.pWin = new Fl_Window(400, 200, "Load Memory Dialog"); @@ -324,6 +512,9 @@ void cb_load(Fl_Widget* w, void*) gDialog.pEndAddr = new Fl_Box(FL_NO_BOX, 120, 120, 90, 15, ""); gDialog.pEndAddr->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + // NULL out controls for Hex and Bin + gDialog.pHex = NULL; + gDialog.pBin = NULL; // Create OK and Cancel buttons rb = new Fl_Return_Button(90, 160, 75, 25, "OK"); @@ -343,14 +534,19 @@ void cb_load(Fl_Widget* w, void*) // Check if OK button was pressed if (gDialog.iOk) { - // Try to open filename supplied + // Get Address where data should be written + pStr = gDialog.pStartAddr->value(); + address = str_to_i(pStr); + pStr = gDialog.pFilename->value(); + load_file_to_mem(pStr, address); + } delete gDialog.pWin; + gmew->take_focus(); } - /* ============================================================================ Callback routine for the save BIN Menu Item @@ -358,6 +554,25 @@ Callback routine for the save BIN Menu Item */ void cb_save_bin(Fl_Widget* w, void*) { + char filepath[256]; + const char *pStr; + int len; + + // Get current filepath + pStr = gDialog.pFilename->value(); + + len = strlen(pStr); + if (len != 0) + { + strcpy(filepath, pStr); + if (filepath[len-4] == '.') + filepath[len-4] = '\0'; + + strcat(filepath, ".bin"); + + gDialog.pFilename->value(filepath); + } + } /* @@ -367,8 +582,128 @@ Callback routine for the save HEX Menu Item */ void cb_save_hex(Fl_Widget* w, void*) { + char filepath[256]; + const char *pStr; + int len; + + // Get current filepath + pStr = gDialog.pFilename->value(); + + len = strlen(pStr); + if (len != 0) + { + strcpy(filepath, pStr); + if (filepath[len-4] == '.') + filepath[len-4] = '\0'; + + strcat(filepath, ".hex"); + + gDialog.pFilename->value(filepath); + } +} + +/* +============================================================================ +Callback routine for the Save Menu Item +============================================================================ +*/ +void cb_save_memory(Fl_Widget* w, void*) +{ + Fl_Box *o; + Fl_Return_Button *rb; + Fl_Button *b; + const char * pStr; + int address, end_addr, count; + int save_as_hex; + + // Build dialog box for selecting file and Memory Range + gDialog.pWin = new Fl_Window(400, 230, "Save Memory Dialog"); + gDialog.pWin->callback(cb_dialogwin); + + // Create radio buttons to select save type + gDialog.pHex = new Fl_Round_Button(10, 10, 110, 20, "Save as HEX"); + gDialog.pHex->type(FL_RADIO_BUTTON); + gDialog.pHex->callback(cb_save_hex); + gDialog.pHex->value(1); + + gDialog.pBin = new Fl_Round_Button(140, 10, 110, 20, "Save as BIN"); + gDialog.pBin->type(FL_RADIO_BUTTON); + gDialog.pBin->callback(cb_save_bin); + + // Create edit field for filename + o = new Fl_Box(FL_NO_BOX, 10, 40, 50, 15, "Filename"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + gDialog.pFilename = new Fl_Input(10, 60, 300, 20, ""); + gDialog.pFilename->callback(load_filename_cb); + + // Create browse button + gDialog.pBrowse = new Fl_Button(320, 60, 70, 20, "Browse"); + gDialog.pBrowse->callback(save_browseButton_cb); + + // Create Edit fields for memory range + o = new Fl_Box(FL_NO_BOX, 10, 90, 110, 15, "Start Address"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + gDialog.pStartAddr = new Fl_Input(120, 90, 90, 20, ""); + gDialog.pStartAddr->value(memedit_ctrl.pMemRange->value()); + + o = new Fl_Box(FL_NO_BOX, 10, 120, 110, 15, "End Address"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + gDialog.pEndSaveAddr = new Fl_Input(120, 120, 90, 20, ""); + + // Create edit field for length + o = new Fl_Box(FL_NO_BOX, 10, 150, 110, 15, "Length"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + gDialog.pSaveLen = new Fl_Input(120, 150, 90, 20, ""); + + // Create OK and Cancel buttons + rb = new Fl_Return_Button(90, 190, 75, 25, "OK"); + rb->callback(load_okButton_cb); + + b = new Fl_Button(210, 190, 75, 25, "Cancel"); + b->callback(load_cancelButton_cb); + + gDialog.pWin->set_modal(); + + // Show the dialog box + gDialog.pWin->show(); + + while (gDialog.pWin->visible()) + Fl::wait(); + + // Check if OK button was pressed + if (gDialog.iOk) + { + // Get Address where data should be written + pStr = gDialog.pStartAddr->value(); + address = str_to_i(pStr); + + // Get End address + pStr = gDialog.pEndSaveAddr->value(); + if (strlen(pStr) != 0) + { + end_addr = str_to_i(pStr); + count = end_addr - address + 1; + } + else + { + pStr = gDialog.pSaveLen->value(); + count = str_to_i(pStr); + } + + // Get save mode selection + save_as_hex = gDialog.pHex->value(); + + // Get filename selection + pStr = gDialog.pFilename->value(); + save_mem_to_file(pStr, address, count, save_as_hex); + + } + + delete gDialog.pWin; + gmew->take_focus(); } + /* ============================================================================ Callback routine for processing memory changes during debug @@ -439,6 +774,7 @@ void cb_MemoryEditor (Fl_Widget* w, void*) // Create Filename edit field memedit_ctrl.pMemRange = new Fl_Input(235, 8+MENU_HEIGHT, 210, 20, ""); + memedit_ctrl.pMemRange->callback(cb_memory_range); // memedit_ctrl.pMemRange->deactivate(); memedit_ctrl.pMemEdit = new T100_MemEditor(10, 40+MENU_HEIGHT, 545, 350-MENU_HEIGHT); @@ -1667,6 +2003,58 @@ void T100_MemEditor::ScrollUp(int lines) redraw(); } +/* +================================================================ +MoveTo: This function moves to the specified line +================================================================ +*/ +void T100_MemEditor::MoveTo(int address) +{ + int height, size, value, col; + + /* Calculate line value */ + value = address / 16; + col = address % 16; + + // Erase the cursor, if any */ + EraseCursor(); + + // Select 12 point Courier font + fl_font(FL_COURIER, 12); + + // Get height of screen in lines + m_Height = fl_height(); + height = memedit_ctrl.pScroll->h(); + size = (int) (height / m_Height); + + // Test if at bottom and scrolling down + if (value > m_Max - size) + value = (int) (m_Max - size); + + // Update new value base on scroll distance requested + if (value < 0) + value = 0; + + // Update scroll bar + memedit_ctrl.pScroll->value(value, 1, 0, (int) m_Max); + memedit_ctrl.pScroll->maximum(m_Max-size); + memedit_ctrl.pScroll->step(size / m_Max); + memedit_ctrl.pScroll->slider_size(size/m_Max); + memedit_ctrl.pScroll->linesize(1); + redraw(); + + /* Set cursor row and column */ + m_CursorRow = address / 16 - value; + if (m_CursorField == 0) + m_CursorField = 1; + if (m_CursorField == 2) + m_CursorCol = 59 + col; + else + m_CursorCol = 9 + col * 3 + (col > 8 ? 1 : 0); + + DrawCursor(); +} + // Erase the cursor at its current position void T100_MemEditor::EraseCursor() { From 2e8d3a8275474f8996b01467468a632596008156 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 18 Apr 2006 23:52:31 +0000 Subject: [PATCH 039/327] Added cpuregs.cpp and cpuregs.h to project to support CPU Registers Tool window --- VirtualT.dsp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/VirtualT.dsp b/VirtualT.dsp index 3e8c62d..35d51ab 100644 --- a/VirtualT.dsp +++ b/VirtualT.dsp @@ -94,6 +94,10 @@ LINK32=link.exe # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File +SOURCE=.\src\cpuregs.cpp +# End Source File +# Begin Source File + SOURCE=.\src\disassemble.cpp # End Source File # Begin Source File @@ -174,6 +178,10 @@ SOURCE=.\src\cpu.h # End Source File # Begin Source File +SOURCE=.\src\cpuregs.h +# End Source File +# Begin Source File + SOURCE=.\src\disassemble.h # End Source File # Begin Source File From 39a82bb90e14ea098ddaadda1b65c085e3542240 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 18 Apr 2006 23:54:04 +0000 Subject: [PATCH 040/327] Added cpuregs.cpp to project to support CPU Registers Tools window --- GNUmakefile | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index f89b45c..80ffad2 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -7,19 +7,20 @@ FLTKCONFIG = $(FLTKDIR)/fltk-config VPATH = src:obj CFLAGS += `$(FLTKCONFIG) --cflags --use-images` -LDFLAGS += `$(FLTKCONFIG) --ldstaticflags --use-images` +LDFLAGS += `$(FLTKCONFIG) --ldstaticflags --use-images` -L /usr/X11R6/lib -L $(FLTKDIR)/lib OBJECTS = $(SOURCES:.c=.o) OBJECTSCPP = $(SOURCESCPP:.cpp=.o) -LIBFILES = $(FLTKDIR)/lib/libfltk.a $(FLTKDIR)/lib/libfltk_images.a +LIBFILES = -lfltk -lfltk_images -lfltk_jpeg -lfltk_png -lfltk_z -lm -lc -lX11 +OBJDIR = obj # ============================= # Define all source files below # ============================= SOURCES = m100emu.c doins.c genwrap.c serial.c intelhex.c memory.c m100rom.c \ - m200rom.c n8201rom.c romstrings.c sound.c -SOURCESCPP = display.cpp setup.cpp periph.cpp disassemble.cpp file.cpp memedit.cpp + m200rom.c n8201rom.c romstrings.c sound.c io.c +SOURCESCPP = display.cpp setup.cpp periph.cpp disassemble.cpp file.cpp memedit.cpp cpuregs.cpp # ======================== @@ -57,14 +58,15 @@ doins.o: cpu.h io.h file.o: memory.h roms.h intelhex.h io.o: cpu.h gen_defs.h io.h serial.h display.h setup.h memory.h intelhex.o: intelhex.h -m100emu.o: io.h cpu.h soins.h display.h genwrap.h filewrap.h roms.h \ +m100emu.o: io.h cpu.h doins.h display.h genwrap.h filewrap.h roms.h \ intelhex.h setup.h memory.h memedit.o: memedit.h disassemble.h memory.h cpu.h memory.o: memory.h cpu.h io.h intelhex.h setup.h -periph.o: periph.h serial.h setup.h display.h disassemble.h +periph.o: periph.h serial.h setup.h display.h disassemble.h cpuregs.h serial.o: serial.h setup.h display.h setup.o: setup.h io.h serial.h memory.h memedit.h sound.c: sound.h +cpuregs.c: cpuregs.h disassemble.h periph.h memedit.h cpu.h m100rom.o m102rom.o m200rom.o n8201rom.o romstrings.o: roms.h romstrings.h From 28ee092ed49e8c408ea8fedacd32363021f8893f Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 19 Apr 2006 04:01:11 +0000 Subject: [PATCH 041/327] Updated edit fields for BC and DE changes --- src/cpuregs.cpp | 146 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index 1dd630a..968671a 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -604,6 +604,146 @@ void cb_reg_pc_changed(Fl_Widget* w, void*) cb_redraw_trace(NULL, NULL); } +/* +============================================================================ +Routine to handle Change to BC edit field +============================================================================ +*/ +void cb_reg_bc_changed(Fl_Widget* w, void*) +{ + int new_bc; + const char *pStr; + char str[20]; + + pStr = cpuregs_ctrl.pRegBC->value(); + new_bc = str_to_i(pStr); + + B = (new_bc >> 8) & 0xFF; + C = new_bc & 0xFF; + + // Update B edit box + sprintf(str, cpuregs_ctrl.sBfmt, B); + cpuregs_ctrl.pRegB->value(str); + + // Update C edit box + sprintf(str, cpuregs_ctrl.sCfmt, C); + cpuregs_ctrl.pRegC->value(str); +} + +/* +============================================================================ +Routine to handle Change to B edit field +============================================================================ +*/ +void cb_reg_b_changed(Fl_Widget* w, void*) +{ + const char *pStr; + char str[20]; + + pStr = cpuregs_ctrl.pRegB->value(); + B = str_to_i(pStr); + + // Update B edit box + sprintf(str, cpuregs_ctrl.sBfmt, B); + cpuregs_ctrl.pRegB->value(str); + + // Update BC edit box + sprintf(str, cpuregs_ctrl.sBCfmt, BC); + cpuregs_ctrl.pRegBC->value(str); +} + +/* +============================================================================ +Routine to handle Change to C edit field +============================================================================ +*/ +void cb_reg_c_changed(Fl_Widget* w, void*) +{ + const char *pStr; + char str[20]; + + pStr = cpuregs_ctrl.pRegC->value(); + C = str_to_i(pStr); + + // Update C edit box + sprintf(str, cpuregs_ctrl.sCfmt, C); + cpuregs_ctrl.pRegC->value(str); + + // Update BC edit box + sprintf(str, cpuregs_ctrl.sBCfmt, BC); + cpuregs_ctrl.pRegBC->value(str); +} + +/* +============================================================================ +Routine to handle Change to DE edit field +============================================================================ +*/ +void cb_reg_de_changed(Fl_Widget* w, void*) +{ + int new_de; + const char *pStr; + char str[20]; + + pStr = cpuregs_ctrl.pRegDE->value(); + new_de = str_to_i(pStr); + + D = (new_de >> 8) & 0xFF; + E = new_de & 0xFF; + + // Update D edit box + sprintf(str, cpuregs_ctrl.sDfmt, D); + cpuregs_ctrl.pRegD->value(str); + + // Update E edit box + sprintf(str, cpuregs_ctrl.sEfmt, E); + cpuregs_ctrl.pRegE->value(str); +} + +/* +============================================================================ +Routine to handle Change to D edit field +============================================================================ +*/ +void cb_reg_d_changed(Fl_Widget* w, void*) +{ + const char *pStr; + char str[20]; + + pStr = cpuregs_ctrl.pRegD->value(); + D = str_to_i(pStr); + + // Update B edit box + sprintf(str, cpuregs_ctrl.sDfmt, D); + cpuregs_ctrl.pRegD->value(str); + + // Update BC edit box + sprintf(str, cpuregs_ctrl.sDEfmt, DE); + cpuregs_ctrl.pRegDE->value(str); +} + +/* +============================================================================ +Routine to handle Change to E edit field +============================================================================ +*/ +void cb_reg_e_changed(Fl_Widget* w, void*) +{ + const char *pStr; + char str[20]; + + pStr = cpuregs_ctrl.pRegE->value(); + E = str_to_i(pStr); + + // Update C edit box + sprintf(str, cpuregs_ctrl.sEfmt, E); + cpuregs_ctrl.pRegE->value(str); + + // Update DE edit box + sprintf(str, cpuregs_ctrl.sDEfmt, DE); + cpuregs_ctrl.pRegDE->value(str); +} + /* ============================================================================ Routine to handle Change to HL edit field @@ -1389,31 +1529,37 @@ void cb_CpuRegs (Fl_Widget* w, void*) // Register B Edit Box cpuregs_ctrl.pRegB = new Fl_Input(50, 69+MENU_HEIGHT, 60, 20, ""); cpuregs_ctrl.pRegB->deactivate(); + cpuregs_ctrl.pRegB->callback(cb_reg_b_changed); cpuregs_ctrl.pRegB->value("0x00"); // Register C Edit Box cpuregs_ctrl.pRegC = new Fl_Input(150, 69+MENU_HEIGHT, 60, 20, ""); cpuregs_ctrl.pRegC->deactivate(); + cpuregs_ctrl.pRegC->callback(cb_reg_c_changed); cpuregs_ctrl.pRegC->value("0x00"); // Register BC Edit Box cpuregs_ctrl.pRegBC = new Fl_Input(250, 69+MENU_HEIGHT, 60, 20, ""); cpuregs_ctrl.pRegBC->deactivate(); + cpuregs_ctrl.pRegBC->callback(cb_reg_bc_changed); cpuregs_ctrl.pRegBC->value("0x0000"); // Register D Edit Box cpuregs_ctrl.pRegD = new Fl_Input(50, 94+MENU_HEIGHT, 60, 20, ""); cpuregs_ctrl.pRegD->deactivate(); + cpuregs_ctrl.pRegD->callback(cb_reg_d_changed); cpuregs_ctrl.pRegD->value("0x00"); // Register E Edit Box cpuregs_ctrl.pRegE = new Fl_Input(150, 94+MENU_HEIGHT, 60, 20, ""); cpuregs_ctrl.pRegE->deactivate(); + cpuregs_ctrl.pRegE->callback(cb_reg_e_changed); cpuregs_ctrl.pRegE->value("0x00"); // Register DE Edit Box cpuregs_ctrl.pRegDE = new Fl_Input(250, 94+MENU_HEIGHT, 60, 20, ""); cpuregs_ctrl.pRegDE->deactivate(); + cpuregs_ctrl.pRegDE->callback(cb_reg_de_changed); cpuregs_ctrl.pRegDE->value("0x0000"); // Register H Edit Box From 8356e7c26189dc20b97bd9109b5fa4b35fe28fec Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 19 Apr 2006 04:01:44 +0000 Subject: [PATCH 042/327] Fixed a bug with ReMem emulation in T200 mode --- src/memory.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/memory.c b/src/memory.c index 3c05d56..836cf92 100644 --- a/src/memory.c +++ b/src/memory.c @@ -966,6 +966,16 @@ void load_opt_rom(void) fread(gOptROM,1, OPTROMSIZE, fd); fclose(fd); } + + if (gReMem) + { + if (gModel == MODEL_T200) + for (c = 0; c < OPTROMSIZE; c++) + gReMemFlash1[0x20000 + c] = gOptROM[c]; + else + for (c = 0; c < OPTROMSIZE; c++) + gReMemFlash1[0x10000 + c] = gOptROM[c]; + } } } @@ -1009,6 +1019,12 @@ void set_ram_bank(unsigned char bank) for (block = 40; block < 64; block++) remem_copy_mmu_to_block(block); } + else + { + // ReMem Normal mode not enabled - use system model + gRamBank = bank; + remem_copy_normal_to_system(); + } } } } @@ -1219,6 +1235,8 @@ int remem_in(unsigned char port, unsigned char *data) map = (gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT; gReMemSector++; /* Increment to next sector */ + if (gReMemSector >= REMEM_BLOCKS_PER_BANK) + gReMemSector = 0; gReMemCounter = 0; /* Clear sector counter */ gReMemSectPtr = (unsigned char *) (gReMemRam + REMEM_MAP_OFFSET + map * REMEM_MAP_SIZE + gReMemSector * REMEM_BANK_SIZE); @@ -1462,6 +1480,8 @@ int remem_out(unsigned char port, unsigned char data) map = (gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT; gReMemSector++; /* Increment to next sector */ + if (gReMemSector >= REMEM_BLOCKS_PER_BANK) + gReMemSector = 0; gReMemCounter = 0; /* Clear sector counter */ gReMemSectPtr = (unsigned char *) (gReMemRam + REMEM_MAP_OFFSET + map * REMEM_MAP_SIZE + gReMemSector * REMEM_BANK_SIZE); From c0a6cc4314c2b6e8f1cec50d8426e149c7ee2254 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 21 Apr 2006 05:05:05 +0000 Subject: [PATCH 043/327] Fixed memory access issue whne not in ReMem emulation mode --- src/VirtualT.h | 2 +- src/memory.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/VirtualT.h b/src/VirtualT.h index 0f311a2..4d769a4 100644 --- a/src/VirtualT.h +++ b/src/VirtualT.h @@ -31,7 +31,7 @@ #ifndef _VIRTUALT_H_ #define _VIRTUALT_H_ -#define VERSION "0.6" +#define VERSION "0.7" enum { MODEL_M100 diff --git a/src/memory.c b/src/memory.c index 836cf92..22c57c1 100644 --- a/src/memory.c +++ b/src/memory.c @@ -77,7 +77,10 @@ unsigned short get_memory16(unsigned short address) void set_memory8(unsigned short address, unsigned char data) { - remem_set8(address, data); + if (gReMem) + remem_set8(address, data); + else + gBaseMemory[address] = data; } void set_memory16(unsigned short address, unsigned short data) From 2e829503990a33c3219bad1c0fdb2ff1637ff498 Mon Sep 17 00:00:00 2001 From: "John R. Hogerhuis" Date: Tue, 13 Jun 2006 04:36:30 +0000 Subject: [PATCH 044/327] Changes necessary to compile under Debian Linux --- GNUmakefile | 4 ++-- src/serial.c | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 80ffad2..b085170 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -32,7 +32,7 @@ $(EXECUTABLE): $(OBJECTS) $(OBJECTSCPP) ifndef FLTKDIR @echo "FLTKDIR environment variable must be set first!" else - cd obj; gcc $(LDFLAGS) $(OBJECTS) $(OBJECTSCPP) $(LIBFILES) -o ../$@ + cd obj; g++ $(LDFLAGS) $(OBJECTS) $(OBJECTSCPP) $(FLTKDIR)/src/Fl_Help_Dialog.o $(LIBFILES) -o ../$@ cd .. endif @@ -66,7 +66,7 @@ periph.o: periph.h serial.h setup.h display.h disassemble.h cpuregs.h serial.o: serial.h setup.h display.h setup.o: setup.h io.h serial.h memory.h memedit.h sound.c: sound.h -cpuregs.c: cpuregs.h disassemble.h periph.h memedit.h cpu.h +cpuregs.cpp: cpuregs.h disassemble.h periph.h memedit.h cpu.h m100rom.o m102rom.o m200rom.o n8201rom.o romstrings.o: roms.h romstrings.h diff --git a/src/serial.c b/src/serial.c index 47e3a9d..23247fe 100644 --- a/src/serial.c +++ b/src/serial.c @@ -29,6 +29,9 @@ #if defined(WIN32) #include +#else +#define TRUE (!0) +#define FALSE (0) #endif #include #include From 5179c17dca98a6d169f02ddf0d89f061a4af0dd3 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Fri, 4 Aug 2006 18:21:48 +0000 Subject: [PATCH 045/327] stdlib.h replaced malloc.h many many moons ago. --- src/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memory.c b/src/memory.c index 22c57c1..934ac16 100644 --- a/src/memory.c +++ b/src/memory.c @@ -11,7 +11,7 @@ memory.c */ #include -#include +#include #include "VirtualT.h" #include "m100emu.h" From 39b0f4e82ec84202e1d8ae84d72fb7b6d470bfb9 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Fri, 4 Aug 2006 18:41:21 +0000 Subject: [PATCH 046/327] Remove broken FLTKDIR usage. fltk-config is *all* you need or you're doing something wrong. --- GNUmakefile | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index b085170..a1a940c 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,17 +1,13 @@ -include $(shell uname).mk -CFLAGS += -I $(FLTKDIR) -O6 -CPPFLAGS += -I $(FLTKDIR) -EXECUTABLE = virtualt +EXECUTABLE := virtualt +VPATH := src:obj -FLTKCONFIG = $(FLTKDIR)/fltk-config -VPATH = src:obj +FLTKCONFIG ?= fltk-config CFLAGS += `$(FLTKCONFIG) --cflags --use-images` -LDFLAGS += `$(FLTKCONFIG) --ldstaticflags --use-images` -L /usr/X11R6/lib -L $(FLTKDIR)/lib +CPPFLAGS += `$(FLTKCONFIG) --cflags --use-images` -OBJECTS = $(SOURCES:.c=.o) -OBJECTSCPP = $(SOURCESCPP:.cpp=.o) -LIBFILES = -lfltk -lfltk_images -lfltk_jpeg -lfltk_png -lfltk_z -lm -lc -lX11 +LIBFILES = -lm -lc -lX11 OBJDIR = obj @@ -21,6 +17,8 @@ OBJDIR = obj SOURCES = m100emu.c doins.c genwrap.c serial.c intelhex.c memory.c m100rom.c \ m200rom.c n8201rom.c romstrings.c sound.c io.c SOURCESCPP = display.cpp setup.cpp periph.cpp disassemble.cpp file.cpp memedit.cpp cpuregs.cpp +OBJECTS = $(SOURCES:.c=.o) +OBJECTSCPP = $(SOURCESCPP:.cpp=.o) # ======================== @@ -29,12 +27,8 @@ SOURCESCPP = display.cpp setup.cpp periph.cpp disassemble.cpp file.cpp memedit.c all: $(SOURCES) $(SOURCESCPP) $(EXECUTABLE) $(EXECUTABLE): $(OBJECTS) $(OBJECTSCPP) -ifndef FLTKDIR - @echo "FLTKDIR environment variable must be set first!" -else - cd obj; g++ $(LDFLAGS) $(OBJECTS) $(OBJECTSCPP) $(FLTKDIR)/src/Fl_Help_Dialog.o $(LIBFILES) -o ../$@ + cd obj; g++ $(LDFLAGS) $(OBJECTS) $(OBJECTSCPP) `$(FLTKCONFIG) --ldstaticflags --use-images` $(LIBFILES) -o ../$@ cd .. -endif # =============================== From 510b7641636e414daf02301284019c8001a7ea33 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Fri, 4 Aug 2006 18:42:09 +0000 Subject: [PATCH 047/327] Include stdlib.h where required for exit() prototype. Include gen_wrap.h in serial.c directly for TRUE/FALSE defines. --- src/display.cpp | 1 + src/m100emu.c | 1 + src/serial.c | 1 + src/setup.cpp | 1 + src/sound.c | 1 + 5 files changed, 5 insertions(+) diff --git a/src/display.cpp b/src/display.cpp index bb318a3..895c7f0 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -27,6 +27,7 @@ * SUCH DAMAGE. */ +#include #include #include diff --git a/src/m100emu.c b/src/m100emu.c index 5f086f3..7e89563 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #ifdef _WIN32 #include diff --git a/src/serial.c b/src/serial.c index 23247fe..970f909 100644 --- a/src/serial.c +++ b/src/serial.c @@ -40,6 +40,7 @@ #include "serial.h" #include "setup.h" #include "display.h" +#include "gen_defs.h" ser_params_t sp; diff --git a/src/setup.cpp b/src/setup.cpp index 64b9b13..03b3be5 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -27,6 +27,7 @@ * SUCH DAMAGE. */ +#include #include #include diff --git a/src/sound.c b/src/sound.c index 257717e..6883d2d 100644 --- a/src/sound.c +++ b/src/sound.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include From d2af164dced4731c549d30ae27f11d6a0bc28992 Mon Sep 17 00:00:00 2001 From: "John R. Hogerhuis" Date: Sun, 5 Nov 2006 00:04:12 +0000 Subject: [PATCH 048/327] ROMs are now looked for in the same place as they exist in the build tree --- src/m100emu.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/m100emu.c b/src/m100emu.c index 7e89563..62bcfce 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -330,22 +330,22 @@ void get_rom_path(char* file, int model) switch (model) { case MODEL_M100: - strcpy(file, "M100/M100rom.bin"); + strcpy(file, "ROMs/M100rom.bin"); break; case MODEL_M102: - strcpy(file, "M102/M102rom.bin"); + strcpy(file, "ROMs/M102rom.bin"); break; case MODEL_T200: - strcpy(file, "T200/T200rom.bin"); + strcpy(file, "ROMs/T200rom.bin"); break; // case MODEL_M10: -// strcpy(file, "m10/m10rom.bin"); +// strcpy(file, "ROMs/m10rom.bin"); // break; case MODEL_PC8201: - strcpy(file, "PC8201/PC8201rom.bin"); + strcpy(file, "ROMs/N8201rom.bin"); break; case MODEL_PC8300: - strcpy(file, "PC8300/PC8300rom.bin"); + strcpy(file, "ROMs/PC8300rom.bin"); break; } } From aa2c6fdd3f896eeb04e5651f2d17ac2f9fe48100 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 31 Mar 2007 22:09:15 +0000 Subject: [PATCH 049/327] Fixed issue with Read from HD in normal memory mode. Added many files for IDE & Assember. This is a work in progress and not complete yet. --- GNUmakefile | 52 +- VirtualT.dsp | 138 +- src/FLU/FluSimpleString.h | 147 + src/FLU/Flu_DND.h | 206 ++ src/FLU/Flu_Enumerations.h | 99 + src/FLU/Flu_Tree_Browser.h | 1081 ++++++ src/FLU/flu_export.h | 27 + src/FLU/flu_pixmaps.h | 54 + src/FLU_LICENSE | 569 +++ src/FluSimpleString.cpp | 146 + src/Flu_DND.cpp | 264 ++ src/Flu_Tree_Browser.cpp | 3420 ++++++++++++++++++ src/LICENSE | 569 +++ src/MString.cpp | 2241 ++++++++++++ src/MString.h | 380 ++ src/MStringArray.cpp | 481 +++ src/MStringArray.h | 83 + src/VirtualT.h | 6 +- src/a85parse.cpp | 6751 ++++++++++++++++++++++++++++++++++++ src/a85parse.h | 87 + src/a85parse.syn | 705 ++++ src/assemble.cpp | 3034 ++++++++++++++++ src/assemble.h | 373 ++ src/cpu.h | 62 +- src/cpuregs.cpp | 32 +- src/disassemble.cpp | 11 +- src/display.cpp | 258 +- src/display.h | 18 + src/do_instruct.h | 806 ++--- src/doins.c | 34 +- src/elf.h | 237 ++ src/flu_pixmaps.cpp | 1629 +++++++++ src/ide.cpp | 1345 +++++++ src/ide.h | 125 + src/io.c | 4 +- src/m100emu.c | 37 +- src/m100emu.h | 2 +- src/m100rom.c | 2 +- src/memedit.cpp | 7 +- src/memory.c | 84 +- src/multiwin.cpp | 637 ++++ src/multiwin.h | 86 + src/multiwin_icons.cpp | 389 +++ src/multiwin_icons.h | 54 + src/periph.cpp | 9 +- src/rpn_eqn.cpp | 50 + src/rpn_eqn.h | 68 + src/serial.c | 5 +- src/setup.cpp | 29 +- src/sound.c | 4 +- src/vtobj.cpp | 359 ++ src/vtobj.h | 184 + 52 files changed, 26896 insertions(+), 584 deletions(-) create mode 100644 src/FLU/FluSimpleString.h create mode 100644 src/FLU/Flu_DND.h create mode 100644 src/FLU/Flu_Enumerations.h create mode 100644 src/FLU/Flu_Tree_Browser.h create mode 100644 src/FLU/flu_export.h create mode 100644 src/FLU/flu_pixmaps.h create mode 100644 src/FLU_LICENSE create mode 100644 src/FluSimpleString.cpp create mode 100644 src/Flu_DND.cpp create mode 100644 src/Flu_Tree_Browser.cpp create mode 100644 src/LICENSE create mode 100644 src/MString.cpp create mode 100644 src/MString.h create mode 100644 src/MStringArray.cpp create mode 100644 src/MStringArray.h create mode 100644 src/a85parse.cpp create mode 100644 src/a85parse.h create mode 100644 src/a85parse.syn create mode 100644 src/assemble.cpp create mode 100644 src/assemble.h create mode 100644 src/elf.h create mode 100644 src/flu_pixmaps.cpp create mode 100644 src/ide.cpp create mode 100644 src/ide.h create mode 100644 src/multiwin.cpp create mode 100644 src/multiwin.h create mode 100644 src/multiwin_icons.cpp create mode 100644 src/multiwin_icons.h create mode 100644 src/rpn_eqn.cpp create mode 100644 src/rpn_eqn.h create mode 100644 src/vtobj.cpp create mode 100644 src/vtobj.h diff --git a/GNUmakefile b/GNUmakefile index a1a940c..e929c2b 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,13 +1,19 @@ -include $(shell uname).mk -EXECUTABLE := virtualt -VPATH := src:obj +CFLAGS += -I $(FLTKDIR) -I src/FLU +CPPFLAGS += -I $(FLTKDIR) +EXECUTABLE = virtualt -FLTKCONFIG ?= fltk-config +FLTKCONFIG = $(FLTKDIR)/fltk-config +VPATH = src:obj CFLAGS += `$(FLTKCONFIG) --cflags --use-images` -CPPFLAGS += `$(FLTKCONFIG) --cflags --use-images` +LDFLAGS += `$(FLTKCONFIG) --ldstaticflags --use-images` -L /usr/X11R6/lib -L $(FLTKDIR)/lib -LIBFILES = -lm -lc -lX11 +OBJECTS = $(SOURCES:.c=.o) +OBJECTSCPP = $(SOURCESCPP:.cpp=.o) +LIBFILES = -lstdc++ -lfltk -lfltk_images -lfltk_jpeg -lfltk_png -lfltk_z -lm -lc -lX11 +#LIBFILES = /$(FLTKDIR)/lib/libfltk.a ../$(FLTKDIR)/lib/libfltk_images.a ../$(FLTKDIR)/lib/libfltk_jpeg.a ../$(FLTKDIR)/lib/libfltk_png.a \ +# /$(FLTKDIR)/lib/libfltk_z.a -lm -lc -lX11 OBJDIR = obj @@ -16,9 +22,10 @@ OBJDIR = obj # ============================= SOURCES = m100emu.c doins.c genwrap.c serial.c intelhex.c memory.c m100rom.c \ m200rom.c n8201rom.c romstrings.c sound.c io.c -SOURCESCPP = display.cpp setup.cpp periph.cpp disassemble.cpp file.cpp memedit.cpp cpuregs.cpp -OBJECTS = $(SOURCES:.c=.o) -OBJECTSCPP = $(SOURCESCPP:.cpp=.o) +SOURCESCPP = display.cpp setup.cpp periph.cpp disassemble.cpp file.cpp memedit.cpp cpuregs.cpp \ + a85parse.cpp assemble.cpp MString.cpp MStringArray.cpp rpn_eqn.cpp vtobj.cpp \ + Flu_DND.cpp flu_pixmaps.cpp Flu_Tree_Browser.cpp FluSimpleString.cpp ide.cpp \ + multiwin.cpp multiwin_icons.cpp # ======================== @@ -27,8 +34,12 @@ OBJECTSCPP = $(SOURCESCPP:.cpp=.o) all: $(SOURCES) $(SOURCESCPP) $(EXECUTABLE) $(EXECUTABLE): $(OBJECTS) $(OBJECTSCPP) - cd obj; g++ $(LDFLAGS) $(OBJECTS) $(OBJECTSCPP) `$(FLTKCONFIG) --ldstaticflags --use-images` $(LIBFILES) -o ../$@ +ifndef FLTKDIR + @echo "FLTKDIR environment variable must be set first!" +else + cd obj; gcc $(LDFLAGS) $(OBJECTS) $(OBJECTSCPP) $(LIBFILES) -o ../$@ cd .. +endif # =============================== @@ -56,13 +67,32 @@ m100emu.o: io.h cpu.h doins.h display.h genwrap.h filewrap.h roms.h \ intelhex.h setup.h memory.h memedit.o: memedit.h disassemble.h memory.h cpu.h memory.o: memory.h cpu.h io.h intelhex.h setup.h -periph.o: periph.h serial.h setup.h display.h disassemble.h cpuregs.h +periph.o: periph.h serial.h setup.h display.h disassemble.h serial.o: serial.h setup.h display.h setup.o: setup.h io.h serial.h memory.h memedit.h sound.c: sound.h -cpuregs.cpp: cpuregs.h disassemble.h periph.h memedit.h cpu.h m100rom.o m102rom.o m200rom.o n8201rom.o romstrings.o: roms.h romstrings.h +# ========== +# asm files +# ========== +a85parse.o: a85parse.h assemble.h +assemble.o: assemble.h +MString.o: MString.h +MStringArray.o: MStringArray.h MString.h +rpn_eqn.o: rpn_eqn.h +vtobj.o: vtobj.h + +# ========== +# ide files +# ========== +Flu_DND.o: FLU/Flu_DND.h +flu_pixmaps.o: FLU/flu_pixmaps.h +Flu_Tree_Browser.o: FLU/Flu_Tree_Browser.h +FluSimpleString.o: FLU/FluSimpleString.h +ide.o: ide.h +multiwin.o: multiwin.h +multiwin_icons.o: multiwin_icons.h # ============================= # Rule to clean all build files diff --git a/VirtualT.dsp b/VirtualT.dsp index 35d51ab..31bd04b 100644 --- a/VirtualT.dsp +++ b/VirtualT.dsp @@ -70,7 +70,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "$(FLTKDIR)" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "$(FLTKDIR)" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" @@ -80,8 +80,8 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept -# ADD LINK32 $(FLTKDIR)/lib/fltkd.lib $(FLTKDIR)/lib/fltkimagesd.lib wsock32.lib comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /pdbtype:sept /libpath:"..\lib" -# SUBTRACT LINK32 /pdb:none /incremental:no +# ADD LINK32 $(FLTKDIR)/lib/fltkd.lib $(FLTKDIR)/lib/fltkimagesd.lib wsock32.lib comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib:"libcd" /libpath:"..\lib" +# SUBTRACT LINK32 /pdb:none /incremental:no /debug /pdbtype: !ENDIF @@ -92,6 +92,66 @@ LINK32=link.exe # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "asm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\a85parse.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\assemble.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\MString.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\MStringArray.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\rpn_eqn.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\vtobj.cpp +# End Source File +# End Group +# Begin Group "ide" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\Flu_DND.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\flu_pixmaps.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\Flu_Tree_Browser.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\FluSimpleString.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\ide.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\multiwin.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\multiwin_icons.cpp +# End Source File +# End Group # Begin Source File SOURCE=.\src\cpuregs.cpp @@ -172,6 +232,78 @@ SOURCE=.\src\sound.c # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Group "asm.h" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\a85parse.h +# End Source File +# Begin Source File + +SOURCE=.\src\assemble.h +# End Source File +# Begin Source File + +SOURCE=.\src\elf.h +# End Source File +# Begin Source File + +SOURCE=.\src\MString.h +# End Source File +# Begin Source File + +SOURCE=.\src\MStringArray.h +# End Source File +# Begin Source File + +SOURCE=.\src\rpn_eqn.h +# End Source File +# Begin Source File + +SOURCE=.\src\vtobj.h +# End Source File +# End Group +# Begin Group "ide.h" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\FLU\Flu_DND.h +# End Source File +# Begin Source File + +SOURCE=.\src\FLU\Flu_Enumerations.h +# End Source File +# Begin Source File + +SOURCE=.\src\FLU\flu_export.h +# End Source File +# Begin Source File + +SOURCE=.\src\FLU\flu_pixmaps.h +# End Source File +# Begin Source File + +SOURCE=.\src\FLU\Flu_Tree_Browser.h +# End Source File +# Begin Source File + +SOURCE=.\src\FLU\FluSimpleString.h +# End Source File +# Begin Source File + +SOURCE=.\src\ide.h +# End Source File +# Begin Source File + +SOURCE=.\src\multiwin.h +# End Source File +# Begin Source File + +SOURCE=.\src\multiwin_icons.h +# End Source File +# End Group # Begin Source File SOURCE=.\src\cpu.h diff --git a/src/FLU/FluSimpleString.h b/src/FLU/FluSimpleString.h new file mode 100644 index 0000000..1863fd7 --- /dev/null +++ b/src/FLU/FluSimpleString.h @@ -0,0 +1,147 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#ifndef _FLU_SIMPLE_STRING_H +#define _FLU_SIMPLE_STRING_H + +#include +#include +#include +#include + +#include "Flu_Enumerations.h" + +//! A simple string object that works a lot like the STL string object +class FLU_EXPORT FluSimpleString +{ + + public: + + //! Default constructor: sets to empty string ("") + FluSimpleString(); + + //! Allocates the string to be of length \b len. Does not set the buffer to any initial value + FluSimpleString( unsigned int len ); + + //! String copy constructor + FluSimpleString( const char *s ); + + //! Copy constructor + FluSimpleString( const FluSimpleString& s ); + + //! Default destructor + ~FluSimpleString(); + + //! \return a c-style nul terminated pointer to the string + inline const char* c_str() const { return str; } + + //! \return how long the string is + inline int size() const { return strlen(str); } + + //! Array operator + inline char& operator [](int i) { return str[i]; } + + //! Array operator + inline char operator [](int i) const { return str[i]; } + + //! \return the indicated substring of this string + FluSimpleString substr( int pos, int len ) const; + + //! Convert this string to uppercase + void upcase(); + + //! Convert this string to lowercase + void downcase(); + + //! \return the first index of character \b c in this string, or -1 if \c is not in this string + int find( char c ) const; + + //! \return the last index of character \b c in this string, or -1 if \c is not in this string + int rfind( char c ) const; + + //! \return 0 if this string is equal to \b s, -1 if this string is lexigraphically less than \b s, 1 if this string is lexigraphically greater than \b s (uses c-std function \b strcmp ) + int compare( const FluSimpleString &s ) const; + + //! Same as compare(), except ignores the case of the string + int casecompare( const FluSimpleString &s ) const; + + //! \return 0 if this string is equal to \b s, -1 if this string is lexigraphically less than \b s, 1 if this string is lexigraphically greater than \b s (uses c-std function \b strcmp ) + inline friend int compare( const FluSimpleString &s1, const FluSimpleString &s2 ) + { return s1.compare( s2 ); } + + //! Same as compare(), except ignores the case of the string + inline friend int casecompare( const FluSimpleString &s1, const FluSimpleString &s2 ) + { return s1.casecompare( s2 ); } + + //! Add character \b c to the end of the string + inline void push_back( char c ) + { char s[2] = { c, '\0' }; *this += s; } + + //! Alias for the \c = operator + inline void copy( const FluSimpleString& s ) + { *this = s; } + + //! Alias for the \c = operator + inline void copy( const char *s ) + { *this = s; } + + //! Copy the substring of \b s to this string + inline void copy( const FluSimpleString& s, unsigned int start, unsigned int len ) + { copy( s.c_str(), start, len ); } + + //! Copy the substring of \b s to this string + void copy( const char *s, unsigned int start, unsigned int len ); + + //! Copy operator + FluSimpleString& operator =( const char *s ); + + //! Copy operator + inline FluSimpleString& operator =( FluSimpleString s ) { return( *this = s.str ); } + + //! Less-than operator + inline bool operator <( const FluSimpleString& s ) const { return( strcmp( str, s.str ) < 0 ); } + + //! Greater-than operator + inline bool operator >( const FluSimpleString& s ) const { return( strcmp( str, s.str ) > 0 ); } + + //! Equality operator + inline bool operator ==( const FluSimpleString& s ) const { return( strcmp( str, s.str ) == 0 ); } + + //! Inequality operator + inline bool operator !=( const FluSimpleString& s ) const { return( strcmp( str, s.str ) != 0 ); } + + //! Concatenate operator + inline friend FluSimpleString operator +( const char *s1, FluSimpleString s2 ) { FluSimpleString s = s1; s += s2; return s; } + + //! Concatenate operator + inline friend FluSimpleString operator +( FluSimpleString s1, const char *s2 ) { FluSimpleString s = s1; s += s2; return s; } + + //! Concatenate operator + inline friend FluSimpleString operator +( FluSimpleString s1, FluSimpleString s2 ) { FluSimpleString s = s1; s += s2; return s; } + + //! Concatenate assignment operator + inline FluSimpleString& operator +=( const FluSimpleString& s ) { *this += s.str; return *this; } + + //! Concatenate assignment operator + FluSimpleString& operator +=( const char *s ); + + private: + + char *str; + +}; + +#endif + diff --git a/src/FLU/Flu_DND.h b/src/FLU/Flu_DND.h new file mode 100644 index 0000000..543ad24 --- /dev/null +++ b/src/FLU/Flu_DND.h @@ -0,0 +1,206 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#ifndef _FLU_DND_H +#define _FLU_DND_H + +#include +#include + +#include +#include + +#include "Flu_Enumerations.h" + +#define FLU_DND_MAX_TYPES 32 + +//! This class encapsulates the event state for a single dragged object, and is designed to work exclusively with Flu_DND +class FLU_EXPORT Flu_DND_Event +{ + friend class Flu_DND; + + public: + + //! Default constructor + Flu_DND_Event(); + + //! Default destructor + ~Flu_DND_Event(); + + //! \return \c true if currently dragging an object, \c false otherwise + inline bool event_is_valid() const + { return dragging; } + + //! \return \c true if the dragged object is normal FLTK text (see Fl::copy() ), else \c false if it is an object derived from Flu_DND + inline bool event_is_text() const + { return( _text != 0 ); } + + //! \return \c true if the dragged object is an object derived from Flu_DND, else \c false if it is normal FLTK text (see Fl::copy() ) + inline bool event_is_other() const + { return( _text == 0 ); } + + //! \return the text from Fl::copy() if this event is a text event (see event_is_text() ) + /*! \note This is valid only after the object has been dropped (i.e. in Flu_DND::on_dnd_drop() )*/ + inline const char* text() const + { return _text; } + + //! \return the dragged object data as added in Flu_DND::dnd_grab() if this event is an "other" event (see event_is_other() ) + /*! \note This is valid only after the object has been dropped (i.e. in Flu_DND::on_dnd_drop() )*/ + inline void* data() const + { return _data; } + + //! \return the type of the data object that was dropped. This is \c NULL for FLTK text events + /*! \note This is valid only after the object has been dropped (i.e. in Flu_DND::on_dnd_drop() )*/ + inline const char* data_type() const + { return _dataType; } + + //! \return \c true if the type of the data object that was dropped is equal to \b t, \c false otherwise + inline bool is_data_type( const char *t ) const + { if( !_dataType ) return 0; else return( strcmp( _dataType, t ) == 0 ); } + + //! \return the x coordinate (from Fl::event_x() ) of when the object was grabbed + inline int grab_x() const + { return _grab_x; } + + //! \return the y coordinate (from Fl::event_y() ) of when the object was grabbed + inline int grab_y() const + { return _grab_y; } + + //! \return the x coordinate (from Fl::event_x() ) of when the object was dropped + inline int drop_x() const + { return _drop_x; } + + //! \return the y coordinate (from Fl::event_y() ) of when the object was dropped + inline int drop_y() const + { return _drop_y; } + + private: + + bool dragging; + void *objUnderMouse; + char *_text, *_dataType; + void *_data; + int _grab_x, _grab_y, _drop_x, _drop_y; + bool exit; + + void clear(); +}; + +//! This class augments the existing FLTK drag-n-drop feature, working with Flu_DND_Event to achieve new functionality +/*! It adds the ability to create specific DND objects, allowing classes that handle + DND to discriminate between which objects are "allowed" to be dropped on them. + + Almost all functions are protected, since only a derived class should be in charge of what kinds of events + to handle and what kinds of objects to support. +*/ +class FLU_EXPORT Flu_DND +{ + public: + + //! Set the function that is called when the dragged object is dropped. This is called in addition to the member function on_dnd_drop() + inline void dnd_callback( void (*cb)(const Flu_DND_Event*,void*), void *cbd = 0 ) + { dndCallback = cb; dndCallbackData = cbd; } + + protected: + + //! Default constructor + Flu_DND( const char *thisType ); + + //! Default destructor + virtual ~Flu_DND(); + + //! See Flu_DND_Event::event_is_text() + inline bool dnd_event_is_text() const + { return( dndEvent.dragging && !dndEvent._data ); } + + //! See Flu_DND_Event::event_is_other() + inline bool dnd_event_is_other() const + { return( dndEvent.dragging && dndEvent._data ); } + + //! See Flu_DND_Event::event_is_valid() + inline bool dnd_is_dragging() const + { return dndEvent.dragging; } + + //! See Flu_DND_Event::is_data_type() + inline bool dnd_is_data_type( const char *t ) const + { return dndEvent.is_data_type( t ); } + + //! Set whether standard FLTK text events can be dropped on this object + inline void dnd_allow_text( bool b ) + { allowTextEvents = b; } + + //! Get whether standard FLTK text events can be dropped on this object + inline bool dnd_allow_text() const + { return allowTextEvents; } + + //! Set whether this object can be dragged to another object + inline void dnd_allow_dragging( bool b ) + { allowDragging = b; } + + //! Get whether this object can be dragged to another object + inline bool dnd_allow_dragging() const + { return allowDragging; } + + //! Set whether this object can have other objects dropped on it + inline void dnd_allow_dropping( bool b ) + { allowDropping = b; } + + //! Get whether this object can have other objects dropped on it + inline bool dnd_allow_dropping() const + { return allowDropping; } + + //! Add type \b t to the list of types that are allowed to be dropped on this object (up to a compiled maximum of \c \b FLU_DND_MAX_TYPES) + void dnd_allow_type( const char *t ); + + //! \return \c true if type \b t is allowed to be dropped on this object, \c false otherwise + bool dnd_type_allowed( const char *t ) const; + + //! Descendents should call this when they detect themselves being grabbed for a drag-n-drop + void dnd_grab( void *data, const char *type ); + + //! Descendents should call this at the start of their handle() method to handle DND processing + int dnd_handle( int event ); + + //! Descendents can override this to respond to when the mouse is let go during a drag-n-drop (regardless of whether the item was dropped on you) + virtual void on_dnd_release(); + + //! Descendents can override this to respond to when the mouse has entered you during a drag-n-drop + virtual void on_dnd_enter(); + + //! Descendents can override this to respond to when the mouse has left you during a drag-n-drop + virtual void on_dnd_leave(); + + //! Descendents should override this to respond to when the dragged object has been dropped on you + virtual void on_dnd_drop( const Flu_DND_Event *e ); + + //! Descendents should override this to indicate whether the currently dragged item is allowed to be dropped on you (for example, if the item can only be dropped at certain locations) + virtual bool on_dnd_drag( int X, int Y ); + + private: + + bool ok2drop(); + + static Flu_DND_Event dndEvent; + bool allowTextEvents, allowDragging, allowDropping; + char* _thisType; + char* allowedTypes[FLU_DND_MAX_TYPES]; + int nTypes; + + void (*dndCallback)(const Flu_DND_Event*,void*); + void *dndCallbackData; + +}; + +#endif diff --git a/src/FLU/Flu_Enumerations.h b/src/FLU/Flu_Enumerations.h new file mode 100644 index 0000000..89b7586 --- /dev/null +++ b/src/FLU/Flu_Enumerations.h @@ -0,0 +1,99 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + +#ifndef _FLU_ENUMERATIONS_H +#define _FLU_ENUMERATIONS_H + +#include "flu_export.h" + +/* these enums are all global to conform to the fltk standard */ + +/*! Selection modes for FLU widgets that select stuff. + Used by: + Flu_Tree_Browser +*/ +enum { + FLU_NO_SELECT, + FLU_SINGLE_SELECT, + FLU_MULTI_SELECT +}; + +/*! Data insertion modes for FLU widgets that insert stuff. + Used by: + Flu_Tree_Browser +*/ +enum { + FLU_INSERT_FRONT, + FLU_INSERT_BACK, + FLU_INSERT_SORTED, + FLU_INSERT_SORTED_REVERSE +}; + +/*! Selection drag modes for FLU widgets that select stuff (used while the mouse is being dragged). + Used by: + Flu_Tree_Browser +*/ +enum { + FLU_DRAG_IGNORE, + FLU_DRAG_TO_SELECT, + FLU_DRAG_TO_MOVE +}; + +/*! Callback reasons for FLU widgets that select stuff. + Used by: + Flu_Tree_Browser +*/ +enum { + FLU_HILIGHTED, + FLU_UNHILIGHTED, + FLU_SELECTED, + FLU_UNSELECTED, + FLU_OPENED, + FLU_CLOSED, + FLU_DOUBLE_CLICK, + FLU_RIGHT_CLICK, + FLU_WIDGET_CALLBACK, + FLU_MOVED_NODE, + FLU_NEW_NODE +}; + +/* not done */ +#if 0 + +/*! Enumerations for Flu_Container */ +typedef enum +{ + FLU_PACK_HORIZONTAL, + FLU_PACK_VERTICAL +} FluPackType; + +/*! Enumerations for Flu_Container */ +typedef enum +{ + FLU_RESIZE_NONE, + FLU_RESIZE_RELATIVE, + FLU_RESIZE_EXPAND_RELATIVE, + FLU_RESIZE_EQUAL, +} FluResizeType; + +/*! Enumerations for Flu_Container */ +typedef enum +{ + FLU_FILL_NONE, + FLU_FILL_FULL +} FluFillType; + +#endif + +#endif diff --git a/src/FLU/Flu_Tree_Browser.h b/src/FLU/Flu_Tree_Browser.h new file mode 100644 index 0000000..d04b79d --- /dev/null +++ b/src/FLU/Flu_Tree_Browser.h @@ -0,0 +1,1081 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#ifndef _FLU_TREE_BROWSER_H +#define _FLU_TREE_BROWSER_H + +#include +#include +#include + +#define USE_FLU_DND + +/* fltk includes */ +#include +#include +#include +#include +#include +#include +#include + +/* flu includes */ +#include "Flu_Enumerations.h" +#include "FluSimpleString.h" +#ifdef USE_FLU_DND +#include "Flu_DND.h" +#else +typedef struct { bool dummy; } Flu_DND_Event; // for compatibilty when not compiling DND support +#endif + +//! This class provides a browser for hierarchical data representation (i.e. a "tree") +#ifdef USE_FLU_DND +class FLU_EXPORT Flu_Tree_Browser : public Fl_Group, public Flu_DND +#else +class FLU_EXPORT Flu_Tree_Browser : public Fl_Group +#endif +{ + + public: + + class Node; + friend class Node; + + //! Normal FLTK widget constructor + Flu_Tree_Browser( int x, int y, int w, int h, const char *label = 0 ); + + //! Default destructor + virtual ~Flu_Tree_Browser(); + + //! Add the entry specified by \b fullpath to the tree. If \b w is not \c NULL then that widget is the entry and its label is visible depending on the value of \b showLabel. Note that the widget is destroyed by the tree/node on clear() or the destructor + /*! If \b fullpath ends in a slash ("/"), then the entry is added as a branch, else it is added as a leaf + \return a pointer to the Node of the added entry or NULL if the add failed */ + Node* add( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true ); + + //! Add entry \b name in path \b path to the tree. If \b w is not \c NULL then that widget is the entry and its label is visible depending on the value of \b showLabel. Note that the widget is destroyed by the tree/node on clear() or the destructor + /*! If \b name ends in a slash ("/"), then the entry is added as a branch, else it is added as a leaf + \return a pointer to the Node of the added entry or NULL if the add failed */ + Node* add( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true ); + + Node* insert_at(Node* p, Node* i, const char* name, Fl_Widget *w = 0, bool showLabel = true ); + + //! Add entry \b name to node \b n. If \b w is not \c NULL then that widget is the entry and its label is visible depending on the value of \b showLabel. Note that the widget is destroyed by the tree/node on clear() or the destructor + /*! If \b name ends in a slash ("/"), then the entry is added as a branch, else it is added as a leaf + \return a pointer to the Node of the added entry or NULL if the add failed */ + inline Node* add( Node* n, const char* name, Fl_Widget *w = 0, bool showLabel = true ) + { return n->add( name, w, showLabel ); } + + //! Set whether all branches are always open. Default value is \c false + inline void all_branches_always_open( bool b ) + { rdata.allBranchesAlwaysOpen = b; } + + //! Get whether all branches are always open. Default value is \c false + inline bool all_branches_always_open() + { return rdata.allBranchesAlwaysOpen; } + + //! Set whether multiple leaves with the same path are allowed. Default value is \c true + inline void allow_leaf_duplication( bool b ) + { rdata.allowDuplication = b; } + + //! Get whether multiple leaves with the same path are allowed. + inline bool allow_leaf_duplication() + { return rdata.allowDuplication; } + + //! \return \c true if drag and drop support has been compiled in, \c false otherwise + inline bool have_dnd() + { +#ifdef USE_FLU_DND + return true; +#else + return false; +#endif + } + + //! Set whether drag and drop processing is enabled for the browser. Default is \c false + /*! If DND is enabled, either text or instances of Flu_Tree_Browser::DND_Object from outside the tree can be dragged and dropped + onto the tree to create a new node. Nodes within the tree can be dragged and dropped (only within the same tree) according to + the value of selection_drag_mode(). */ + inline void allow_dnd( bool b ) + { rdata.dnd = b; } + + //! Get whether drag and drop processing is enabled for the browser. + inline bool allow_dnd() + { return rdata.dnd; } + + //! Set whether the root node is always open. Shortcut for \c get_root()->always_open(b). Default is \c false + inline void always_open( bool b ) + { root.always_open( b ); } + + //! Get whether the root node is always open + inline bool always_open() + { return root.always_open(); } + + //! Set whether animations of opening/closing branches are enabled. Default is \c false + inline void animate( bool b ) + { rdata.animate = b; } + + //! Get whether animations of opening/closing branches are enabled + inline bool animate() + { return rdata.animate; } + + //! Get the default branch text color + inline Fl_Color branch_color() const + { return rdata.defBranchColor; } + + //! Get the default branch text font + inline Fl_Font branch_font() const + { return rdata.defBranchFont; } + + //! Get the default branch text size + inline int branch_size() const + { return rdata.defBranchSize; } + + //! Set the default color, font and size to use for the text of all subsequent branches added to the tree + inline void branch_text( Fl_Color color, Fl_Font font, int size ) + { rdata.defBranchColor = color; rdata.defBranchFont = font; rdata.defBranchSize = size; } + + //! Set the default branch icons to use for all subsequent branches added to the tree + void branch_icons( Fl_Image *closed, Fl_Image *open ); + + //! Get the type of box to draw the browser in + inline Fl_Boxtype box() const + { return _box->box(); } + + //! Set the type of box to draw the browser in. Default is FL_NO_BOX + inline void box( Fl_Boxtype b ) + { _box->box( b ); } + + //! Override of Fl_Widget::callback + inline void callback( Fl_Callback *c, void *user_data = 0 ) + { rdata.cb = c; rdata.cbd = user_data; } + + //! Get the reason why the last callback happened. This can be one of FLU_UNHILIGHTED, FLU_HILIGHTED, FLU_SELECTED, FLU_UNSELECTED, FLU_OPENED, FLU_CLOSED, FLU_DOUBLE_CLICK, FLU_WIDGET_CALLBACK, FLU_MOVED_CALLBACK, FLU_NEW_NODE_CALLBACK + inline int callback_reason() const + { return rdata.cbReason; } + + //! Get the node on which the last callback happened. + inline Node* callback_node() const + { return rdata.cbNode; } + + //! Clear all entries from the tree + void clear(); + + //! Set the default collapse icons to use for all subsequent branches added to the tree + void collapse_icons( Fl_Image *closed, Fl_Image *open ); + + //! Get the amount of time to take when animating an open/close. Use in conjunction with frame_rate() + inline float collapse_time() const + { return rdata.collapseTime; } + + //! Set the amount of time to take when animating an open/close. Use in conjunction with frame_rate(). Default is 0.1 seconds + inline void collapse_time( float t ) + { rdata.collapseTime = t; } + + //! Get the background color of the browser + inline Fl_Color color() const + { return _box->color(); } + + //! Set the background color of the browser. Default is FL_WHITE + inline void color( Fl_Color c ) + { _box->color( c ); } + + //! Set the background color of the browser. Default is FL_WHITE + inline void color( unsigned c ) + { _box->color( (Fl_Color)c ); } + + //! Set the color, style, and width of the connector lines. Default is FL_DARK2, FL_DOT, 1 + inline void connector_style( Fl_Color color, int style, int width = 1 ) + { rdata.defLineColor = color; rdata.lineStyle = style; rdata.lineWidth = width; } + + //! Get the color of the connector lines + inline Fl_Color connector_color() const + { return rdata.defLineColor; } + + //! Get the style of the connector lines + inline int connector_style() const + { return rdata.lineStyle; } + + //! Get the width of the connector lines + inline int connector_width() const + { return rdata.lineWidth; } + + //! Set whether double-clicking a branch opens/closes it + inline void double_click_opens( bool b ) + { rdata.doubleClickToOpen = b; } + + //! Get whether double-clicking a branch opens/closes it + inline bool double_click_opens() + { return rdata.doubleClickToOpen; } + + //! Get the color to use for shading even entries + inline Fl_Color even_shaded_entry_color() const + { return rdata.shadedColors[0]; } + + //! Find the entry identified by \b fullpath + /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */ + inline Node* find( const char *fullpath ) + { return find_next( fullpath ); } + + //! Find entry \b name in path \b path + /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */ + Node* find( const char *path, const char *name ); + + //! Find the entry identified by unique id \b id + /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */ + Node* find( unsigned int id ); + + //! Search for Node \b n in the tree + /*! \return a pointer to \b n if it is found, or NULL if it is not in the tree */ + inline Node* find( Node *n ) + { if( !n ) return NULL; else return find( n->id() ); } + + //! Find the entry containing the widget \b w + /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */ + Node* find( Fl_Widget *w ); + + //! Find the next entry identified by \b fullpath after \b startNode + /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */ + Node* find_next( const char *fullpath, Node* startNode = NULL ); + + //! Find the next entry \b name in path \b path after \b startNode + /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */ + Node* find_next( const char *path, const char *name ); + + //! \return the number of discovered nodes matching path \b fullpath + int find_number( const char *fullpath ); + + //! \return the number of discovered nodes with name \b name in path \b path + int find_number( const char *path, const char *name ); + + //! \return the full path of the entry identified by unique id \b id, or the empty string if no matching entry was found + /*! \note the returned value is only valid until the next time find_path() is called */ + const char* find_path( unsigned int id ); + + //! \return the full path of the entry containing the widget \b w, or the empty string if no matching entry was found + /*! \note the returned value is only valid until the next time find_path() is called */ + const char* find_path( Fl_Widget *w ); + + //! \return the full path of Node \b n, or the empty string if \b n is not in the tree + /*! \note the returned value is only valid until the next time find_path() is called */ + inline const char* find_path( Node *n ) + { if( !n ) return ""; else return find_path( n->id() ); } + + //! \return the first node in the tree (i.e. the root) + inline Node* first() { return root.first(); } + + //! \return the first branch encountered in a depth-first traversal of the tree. NULL means there are no branches + inline Node* first_branch() { return root.first_branch(); } + + //! \return the first leaf encountered in a depth-first traversal of the tree. NULL means there are no leaves + inline Node* first_leaf() { return root.first_leaf(); } + + //! Get the frame rate to use during the open/close animation. Use in conjunction with collapse_time() + inline float frame_rate() const + { return rdata.fps; } + + //! Set the frame rate to use during the open/close animation. Use in conjunction with collapse_time(). Default is 100 frames per second + inline void frame_rate( float f ) + { if( f <= 0.0f ) rdata.fps = 0.001f; else rdata.fps = f; } + + //! \return a pointer to the root node of the tree + inline Node *get_root() { return &root; } + + //! \return the selected Node that is at \b index among all selected nodes, or \c NULL if no Node is selected + /*! For example, \c get_selected(1) will return the first selected node. */ + Node* get_selected( int index ); + + //! Override of Fl_Widget::handle + int handle( int event ); + + //! Set the horizontal icon gap for each entry. Default is 2 + inline void horizontal_gap( int g ) + { rdata.hGap = g; rdata.forceResize = true; } + + //! Get the horizontal icon gap for each entry + inline int horizontal_gap() const + { return rdata.hGap; } + + //! Set how entries are inserted into the tree. This can be one of FLU_INSERT_FRONT, FLU_INSERT_BACK, FLU_INSERT_SORTED, FLU_INSERT_SORTED_REVERSE. Default is FLU_INSERT_SORTED + void insertion_mode( int m ); + + //! Get how entries are inserted into the tree. + inline int insertion_mode() + { return rdata.insertionMode; } + + //! Set the title of the Tree (also the label for the root entry) + inline void label( const char *l ) + { root.text = l; } + + //! Get the title of the Tree (also the label for the root entry) + inline const char* label() const + { return root.text.c_str(); } + + //! \return the last node in the tree + inline Node* last() { return root.last(); } + + //! \return the last branch encountered in a depth-first traversal of the tree. NULL means there are no branches + inline Node* last_branch() { return root.last_branch(); } + + //! \return the last leaf encountered in a depth-first traversal of the tree. NULL means there are no leaves + inline Node* last_leaf() { return root.last_leaf(); } + + //! Get the default leaf text color + inline Fl_Color leaf_color() const + { return rdata.defLeafColor; } + + //! Get the default leaf text font + inline Fl_Font leaf_font() const + { return rdata.defLeafFont; } + + //! Get the default leaf text size + inline int leaf_size() const + { return rdata.defLeafSize; } + + //! Set the default leaf icon to use for all subsequent leaves added to the tree + void leaf_icon( Fl_Image *icon ); + + //! Set the default color, font and size to use for the text of all subsequent leaves added to the tree, Default is FL_BLACK, FL_HELVETICA, 12 + inline void leaf_text( Fl_Color color, Fl_Font font, int size ) + { rdata.defLeafColor = color; rdata.defLeafFont = font; rdata.defLeafSize = size; } + + //! Set whether items can be moved only within their group ( \c true ) or can be moved anywhere in the tree ( \c false ). Default is \c false. Used only when selection_drag_mode() is FLU_DRAG_TO_MOVE. + inline void move_only_same_group( bool b ) + { rdata.moveOnlySameGroup = b; } + + //! Get whether items can be moved only within their group ( \c true ) or can be moved anywhere in the tree ( \c false ). Used only when selection_drag_mode() is FLU_DRAG_TO_MOVE. + inline bool move_only_same_group() + { return rdata.moveOnlySameGroup; } + + //! \return the number of selected entries + int num_selected(); + + //! Get the color to use for shading odd entries + inline Fl_Color odd_shaded_entry_color() const + { return rdata.shadedColors[1]; } + + //! Set whether only a single branch (except the root branch) is allowed open at a time. Default is \c false + inline void only_one_open_branch( bool b ) + { rdata.singleBranchOpen = b; } + + //! Get whether only a single branch (except the root branch) is allowed open at a time + inline bool only_one_open_branch() + { return rdata.singleBranchOpen; } + + //! Open or close the root node + inline void open( bool b ) + { root.open( b ); } + + //! Is the root node open or closed? + inline bool open() const + { return root.open(); } + + //! Set whether selecting a branch also opens it. Default is \c false + inline void open_on_select( bool b ) + { rdata.openOnSelect = b; } + + //! Get whether selecting a branch also opens it + inline bool open_on_select() const + { return rdata.openOnSelect; } + + //! Print the tree to stdout + void print(); + + //! Remove the entry identified by path \b fullpath from the tree + /*! \return the unique id of the removed entry, or \c 0 if no matching entry was found */ + unsigned int remove( const char *fullpath ); + + //! Remove entry \b name in path \b path from the tree + /*! \return the unique id of the removed entry, or \c 0 if no matching entry was found */ + unsigned int remove( const char *path, const char *name ); + + //! Remove the entry identified by unique id \b id from the tree + /*! \return the unique id of the removed entry, or \c 0 if no matching entry was found */ + unsigned int remove( unsigned int id ); + + //! Remove the entry containing the widget \b w from the tree. Note that the widget is automatically destroyed + /*! \return the unique id of the removed entry, or \c 0 if no matching entry was found */ + unsigned int remove( Fl_Widget *w ); + + //! Remove Node \b n from the tree + /*! \return the id of \b n on successful removal, or \c 0 if \b n is not in the tree */ + inline unsigned int remove( Node* n ) + { if( !n ) return 0; else return remove( n->id() ); } + + //! Override of Fl_Widget::resize + void resize( int X, int Y, int W, int H ); + + //! Convenience routine to set the root label color. See Flu_Tree_Browser::Node::label_color() + inline void root_color( Fl_Color c ) + { get_root()->label_color( c ); } + + //! Convenience routine to set the root label color. See Flu_Tree_Browser::Node::label_color() + inline Fl_Color root_color() + { return get_root()->label_color(); } + + //! Convenience routine to set the root label font. See Flu_Tree_Browser::Node::label_font() + inline void root_font( Fl_Font f ) + { get_root()->label_font( f ); } + + //! Convenience routine to set the root label font. See Flu_Tree_Browser::Node::label_font() + inline Fl_Font root_font() + { return get_root()->label_font(); } + + //! Convenience routine to set the root label size. See Flu_Tree_Browser::Node::label_size() + inline void root_size( unsigned char s ) + { get_root()->label_size( s ); } + + //! Convenience routine to set the root label size. See Flu_Tree_Browser::Node::label_size() + inline unsigned char root_size() + { return get_root()->label_size(); } + + //! Select all entries in the tree + inline void select_all() + { root.select_all(); } + + //! Get the color to use when hilighting selected entries + inline Fl_Color selection_color() const + { return rdata.defSelectionColor; } + + //! Set the color to use when hilighting selected entries. Default is FL_SELECTION_COLOR + inline void selection_color( Fl_Color c ) + { rdata.defSelectionColor = c; } + + //! Set the color to use when hilighting selected entries. Default is FL_SELECTION_COLOR + inline void selection_color( unsigned c ) + { selection_color( (Fl_Color)c ); } + + //! Set how selection is affected when the mouse is dragged. This can be one of FLU_DRAG_IGNORE, FLU_DRAG_TO_SELECT, FLU_DRAG_TO_MOVE. Default is FLU_DRAG_TO_SELECT. + inline void selection_drag_mode( int m ) + { rdata.selectionDragMode = m; } + + //! Get how selection is affected when the mouse is dragged + inline int selection_drag_mode() const + { return rdata.selectionDragMode; } + + //! Set how individual entries are selected using the mouse. This can be one of FLU_NO_SELECT, FLU_SINGLE_SELECT, FLU_MULTI_SELECT. Default is FLU_MULTI_SELECT + inline void selection_mode( int m ) + { rdata.selectionMode = m; root.unselect_all(); } + + //! Get how individual entries are selected using the mouse + inline int selection_mode() const + { return rdata.selectionMode; } + + //! Set which node is hilighted and ready to be selected or unselected. This also scrolls the browser so \b n is visible. + void set_hilighted( Node* n ); + + //! Set the title of the root of the tree to \b label. If \b w is not \c NULL then that widget is the entry and its label is visible depending on the value of \b showLabel. Note that the widget is destroyed by the tree/node on clear() or the destructor + /*! The root icons, color, font and size are set to the current branch icons and text color, font and size */ + Node* set_root( const char *label, Fl_Widget *w = 0, bool showLabel = true ); + + //! Set the colors to use for shading every other entry. Default is FL_WHITE, FL_WHITE + inline void shaded_entry_colors( Fl_Color even, Fl_Color odd ) + { rdata.shadedColors[0] = even; rdata.shadedColors[1] = odd; } + + //! Set whether branch entries are visible. Default is \c true + inline void show_branches( bool b ) + { rdata.showBranches = b; rdata.forceResize = true; } + + //! Get whether branch entries are visible + inline bool show_branches() const + { return rdata.showBranches; } + + //! Set whether the connectors between entries are visible. Default is \c true + inline void show_connectors( bool b ) + { rdata.showConnectors = b; } + + //! Get whether the connectors between entries are visible + inline bool show_connectors() const + { return rdata.showConnectors; } + + //! Set whether the root branch (i.e. the name of the tree) is visible. Default is \c true + inline void show_root( bool b ) + { rdata.showRoot = b; rdata.forceResize = true; } + + //! Get whether the root branch (i.e. the name of the tree) is visible + inline bool show_root() const + { return rdata.showRoot; } + + //! Set whether leaf entries are visible. Default is \c true + inline void show_leaves( bool b ) + { rdata.showLeaves = b; rdata.forceResize = true; } + + //! Get whether leaf entries are visible + inline bool show_leaves() const + { return rdata.showLeaves; } + + //! Unselect all entries in the tree + inline void unselect_all() + { root.unselect_all(); } + + //! Set the vertical gap between tree entries. Default is 0 + inline void vertical_gap( int g ) + { rdata.vGap = g; rdata.forceResize = true; } + + //! Get the vertical gap between tree entries + inline int vertical_gap() const + { return rdata.vGap; } + + //! Override of Fl_Widget::when. Currently only FL_WHEN_NEVER, FL_WHEN_CHANGED, and FL_WHEN_NOT_CHANGED are supported. Default value is FL_WHEN_CHANGED + /*! When the callback occurs, you can use callback_reason() to determine exactly what cause the callback and callback_node() + to get the node that was affected. */ + inline void when( unsigned int w ) + { rdata.when = w; } + + //! Override of Fl_Widget::when + inline unsigned int when() const + { return rdata.when; } + + //! Set the gap between the widget and the icon that precedes it. Default is 2 + inline void widget_gap( int g ) + { rdata.wGap = g; rdata.forceResize = true; } + + //! Get the gap between the widget and the icon that precedes it + inline int widget_gap() const + { return rdata.wGap; } + + protected: + + class RData; + + //! Internal class holding an (alphabetically) ordered list of nodes + class FLU_EXPORT NodeList + { + public: + NodeList(); + ~NodeList(); + void add( Node* n, int position = -1 ); + void insert_at( Node* i, Node* n ); + inline Node* child( int n ) const { return _nodes[n]; } + int erase( Node* n ); + int erase( const char* n ); + void erase( int n ); + void clear(); + int findNum( const char *n ); // find the number of nodes in the list with name n + Node* find( const char* n, int which = 1 ); // find the which'th node in the list with name n + inline int size() const { return _nNodes; }; + void sort(); + static bool move( Node* n1, int where, Node* n2 ); + private: + friend class Node; + static int compareNodes( const void *arg1, const void* arg2 ); + static int reverseCompareNodes( const void *arg1, const void* arg2 ); + bool search( Node *n, int &index ); + bool search( const char *n, int &index ); + bool linSearch( Node *n, int &index ); + bool linSearch( const char *n, int &index ); + bool binSearch( Node *n, int &index ); + bool binSearch( const char *n, int &index ); + Node **_nodes; + int _nNodes, _size; + }; + + //! Internal class holding a stack of integers + class FLU_EXPORT IntStack + { + public: + IntStack(); + IntStack( const IntStack& s ); + ~IntStack(); + void push( int i ); + int pop(); + void clear(); + inline int operator [](int i) { return _list[i]; } + inline int size() { return _size; } + IntStack& operator =( const IntStack& s ); + private: + int *_list; + int _size, _bufferSize; + }; + + public: + enum { MOVE_BEFORE, MOVE_INSIDE, MOVE_AFTER }; // where to move a dragged node? + protected: + + //! Recursive data structure passed down through the node tree + class FLU_EXPORT RData { + public: + // volatile objects (from the perspective of each node during a recursive descent) + int x, y, totalW, totalH; + bool first, last, dragging, shiftSelect, shiftSelectAll, visibilityChanged; + Node *hilighted, *lastHilighted, *previous, *grabbed, *dragNode, *animatedNode; + int delta, shadedIndex, counter, searchIndex, branchIconW, dragPos, dragWhere; + Fl_Color lineColor, bgColor, selectionColor; + bool forceResize; // force the browser to resize on the next draw (which forces a recalculation of the tree layout) + unsigned int nextId; // monotonically increasing id of each entry + FluSimpleString path; // used to construct the full path during a findPath() operation + IntStack branchConnectors; + + // static objects (from the perspective of each node during a recursive descent) + int insertionMode; + Fl_Image *defaultCollapseIcons[2], *defaultBranchIcons[2]; + Fl_Image *collapseIcons[2], *branchIcons[2], *leafIcon; + int hGap, vGap, wGap; + int lineStyle, lineWidth, selectionMode, selectionDragMode; + bool showRoot, showConnectors, showLeaves, showBranches, openOnSelect, + allowDuplication, animate, animating, singleBranchOpen, moveOnlySameGroup, justOpenedClosed, + isMoveValid, doubleClickToOpen, dnd, allBranchesAlwaysOpen; + float collapseTime, fps, animationDelta, animationOffset; + Fl_Color defLineColor, defSelectionColor, shadedColors[2]; + Fl_Color defLeafColor, defBranchColor; + Fl_Font defLeafFont, defBranchFont; + int defLeafSize, defBranchSize; + int browserX, browserY, browserW, browserH; + Node *root; + Flu_Tree_Browser *tree; + Fl_Callback *cb; + void *cbd; + unsigned int when, cbReason; + Node *cbNode, *lastOpenBranch; + //int (*sortCB)(Node*,Node*); + }; + + public: + +#ifdef USE_FLU_DND + //! This class can be subclassed to make an object which can be dropped on a tree to make a new node + /*! When the object is dropped, the tree will name the object according to what the function + \b name() returns */ + class FLU_EXPORT DND_Object : public Flu_DND + { + public: + + //! Default constructor + DND_Object(); + + //! The descendent should call this when the user grabs the object to start dragging it (e.g. on the FL_PUSH event) + inline void grab() + { dnd_grab( this, "DND_Object" ); } + + //! Descendents MUST implement this function to return the name of the dropped object + virtual const char* name() = 0; + + }; +#endif + + //! This class holds a single entry in the tree + class FLU_EXPORT Node + { + + protected: + + enum { ADD, REMOVE, FIND, FIND_NUMBER, GET_SELECTED }; // parameters for modify() + enum { DRAW, MEASURE, MEASURE_THIS_OPEN, HANDLE, COUNT_SELECTED }; // parameters for recurse() + + // flags + enum { SELECTED = 0x0001, COLLAPSED = 0x0002, LEAF = 0x0004, SHOW_LABEL = 0x0008, + ACTIVE = 0x0010, EXPAND_TO_WIDTH = 0x0020, ALWAYS_OPEN = 0x0040, + SOME_VISIBLE_CHILDREN = 0x0080, MOVABLE = 0x0100, DROPPABLE = 0x0200 }; + + // flag manipulator functions + inline bool CHECK( unsigned short flag ) const { return (flags & flag) != 0; } + inline void SET( unsigned short flag ) { flags |= flag; } + inline void SET( unsigned short flag, bool b ) { if(b) SET(flag); else CLEAR(flag); } + inline void CLEAR( unsigned short flag ) { flags &= ~flag; } + + public: + + //! Is this node currently active? + inline bool active() const + { return CHECK(ACTIVE); } + + //! Activate or deactivate this node + void active( bool b ); + + //! Activate this node + inline void activate() + { active(true); } + + Node* insert_at( Node* p, Node* i, const char* path, RData &rdata, Fl_Widget *w, bool showLabel ); + + //! Add the entry specified by \b fullpath to this node. If \b w is not \c NULL then that widget is the entry and the label (as specified in \b fullPath) is visible depending on the value of \b showLabel. Note that the widget is destroyed by the tree/node on clear() or the destructor + /*! \return a pointer to the Node of the added entry or NULL if the add failed */ + inline Node* add( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true ) + { return( modify( fullpath, ADD, tree->rdata, w, showLabel ) ); } + + //! Set whether a branch node is always open (only for branch nodes). Default is \c false + inline void always_open( bool b ) + { if( b ) open(true); SET(ALWAYS_OPEN,b); tree->rdata.forceResize = true; } + + //! Get whether a branch node is always open (only for branches) + inline bool always_open() const + { return CHECK(ALWAYS_OPEN); } + + //! Set the branch icons to use for this node (only for branch nodes) + /*! \note if a NULL icon is passed, the default folder icons are chosen */ + void branch_icons( Fl_Image *closed, Fl_Image *open ); + + //! Convenience routine to set both branch icons at once + inline void branch_icon( Fl_Image *icon ) + { branch_icons( icon, icon ); } + + //! \return child \b i of this node. Bounds checking is performed and NULL is returned if the child cannot be found + Node* child( int i ) const; + + //! \return the number of child nodes beneath this node + inline int children() const + { return _children.size(); } + + //! Clear all child entries from this node (does not change the entry of this node) + void clear(); + + //! Close this node (only for branches) + inline void close() + { open( false ); } + + //! Is this node closed? (only for branches) + inline bool closed() + { return !open(); } + + //! Set the collapse icons to use for this node (only for branch nodes) + /*! \note if a NULL icon is passed, the default plus/minus icons are chosen */ + void collapse_icons( Fl_Image *closed, Fl_Image *open ); + + //! Deactivate this node + inline void deactivate() + { active(false); } + + //! Get the depth of this node in the tree + unsigned short depth() const; + + //! Do the tree browser callback. \b reason should be one of FLU_HILIGHTED, FLU_UNHILIGHTED, FLU_SELECTED, FLU_UNSELECTED, FLU_OPENED, FLU_CLOSED, FLU_DOUBLE_CLICK, FLU_WIDGET_CALLBACK + void do_callback( int reason ); + + //! Set whether this node can receive new nodes as a result of dragging-and-dropping (only for branch nodes). Default is \c true + inline void droppable( bool b ) + { SET(DROPPABLE,b); } + + //! Get whether this node can receive new nodes as a result of dragging-and-dropping (only for branch nodes). + inline bool droppable() + { return CHECK(DROPPABLE); } + + //! Set whether to force the size of the widget to expand to fill the visible width of the browser. Default is \c false + inline void expand_to_width( bool b ) + { SET(EXPAND_TO_WIDTH,b); tree->rdata.forceResize = true; } + + //! Get whether to force the size of the widget to expand to fill the visible width of the browser + inline bool expand_to_width() const + { return CHECK(EXPAND_TO_WIDTH); } + + //! Find the entry identified by \b fullpath + /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */ + inline Node* find( const char *fullpath ) + { return( modify( fullpath, FIND, tree->rdata ) ); } + + //! Find the entry identified by unique id \b id + /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */ + Node* find( unsigned int id ); + + //! Find the entry containing the widget \b w + /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */ + Node* find( Fl_Widget *w ); + + //! Search for Node \b n + /*! \return a pointer to \b n if it is found, or NULL if it is not present */ + inline Node* find( Node *n ) + { if( !n ) return NULL; else return find( n->id() ); } + + //! \return the full path of this node + /*! \note the returned value is only valid until the next time find_path() is called */ + inline const char* find_path() + { return tree->find_path( this ); } + + //! \return the first node in this hierarchy (i.e. this node) + Node* first(); + + //! \return the first branch encountered in a depth-first traversal (or this node if it is a branch). NULL means there are no branches + Node* first_branch(); + + //! \return the first leaf encountered in a depth-first traversal (or this node if it is a leaf). NULL means there are no leaves + Node* first_leaf(); + + //! Get the unique ID of this node + inline unsigned int id() const + { return _id; } + + //! Get the index this node is (as a child) in its parent's list + /*! \return -1 if this node has no parent, else its index in its parent's list of children */ + int index() const; + + //! Is node \b n an ancestor of this node? + bool is_ancestor( Node* n ); + + //! Is this node a branch node? + inline bool is_branch() const + { return !CHECK(LEAF); } + + //! Is node \b n a descendent of this node? + bool is_descendent( Node* n ); + + //! Is this node a leaf node? + inline bool is_leaf() const + { return CHECK(LEAF); } + + //! Is this node the root node? + inline bool is_root() const + { return( _parent == 0 ); } + + //! Get the label for this node + inline const char* label() const + { return text.c_str(); } + + //! Set the label color for this node + inline void label_color( Fl_Color c ) + { textColor = c; } + + //! Get the label color for this node + inline Fl_Color label_color() const + { return textColor; } + + //! Set the label font for this node + inline void label_font( Fl_Font f ) + { textFont = f; tree->rdata.forceResize = true; } + + //! Get the label font for this node + inline Fl_Font label_font() const + { return textFont; } + + //! Set the label size for this node + inline void label_size( unsigned char s ) + { textSize = s; tree->rdata.forceResize = true; } + + //! Get the label size for this node + inline unsigned char label_size() const + { return textSize; } + + //! Is the label for this node visible? + inline bool label_visible() const + { return CHECK(SHOW_LABEL); } + + //! Set whether the label for this node is visible + inline void label_visible( bool b ) + { SET(SHOW_LABEL,b); tree->rdata.forceResize = true; } + + //! \return the last node in this hierarchy + Node* last(); + + //! \return the last branch encountered in a depth-first traversal (or this node if it is a branch and has no children). NULL means there are no branches + Node* last_branch(); + + //! \return the last leaf encountered in a depth-first traversal (or this node if it is a leaf). NULL means there are no leaves + Node* last_leaf(); + + //! Set the leaf icon to use for this node (only for leaf nodes) + void leaf_icon( Fl_Image *icon ); + + //! Set whether this node can be moved (either via move() or by dragging with the mouse). Default is \c true + inline void movable( bool b ) + { SET(MOVABLE,b); } + + //! Get whether this node can be moved (either via move() or by dragging with the mouse) + inline bool movable() + { return CHECK(MOVABLE); } + + //! Move this node to a position before, after, or inside node \b n + /*! \param where can be one of MOVE_BEFORE, MOVE_AFTER, or MOVE_INSIDE + \return \c true if the move was successful, or \c false if the move is not allowed + */ + inline bool move( int where, Node* n ) + { return( move( this, where, n ) ); } + + //! Move node \b n1 to a position before, after, or inside node \b n2 + /*! \param where can be one of MOVE_BEFORE, MOVE_AFTER, or MOVE_INSIDE + \return \c true if the move was successful, or \c false if the move is not allowed + */ + static bool move( Node* n1, int where, Node* n2 ); + + //! \return the next node (after this node) in this hierarchy (depth-first traversal) + Node* next(); + + //! \return the next branch (after this node) encountered in a depth-first traversal. NULL means there are no more branches + Node* next_branch(); + + //! \return the next leaf (after this node) encountered in a depth-first traversal. NULL means there are no more leaves + Node* next_leaf(); + + //! \return the next sibling (after this node) encountered in a depth-first traversal. NULL means this node is the last child w.r.t. its parent + Node* next_sibling(); + + //! Is this node currently open? (only for branch nodes) + inline bool open() const + { return( !CHECK(COLLAPSED) || tree->rdata.allBranchesAlwaysOpen ); } + + //! Open or close this node (only for branch nodes) + void open( bool b ); + + //! Get the node that is the parent of this node, or NULL if there is no parent + inline Node* parent() const + { return _parent; } + + //! \return the previous node (before this node) in this hierarchy (depth-first traversal) + Node* previous(); + + //! \return the previous branch (before this node) encountered in a depth-first traversal. NULL means there are no more branches + Node* previous_branch(); + + //! \return the previous leaf (before this node) encountered in a depth-first traversal. NULL means there are no more leaves + Node* previous_leaf(); + + //! \return the previous sibling (before this node) encountered in a depth-first traversal. NULL means this node is the first child w.r.t. its parent + Node* previous_sibling(); + + //! Print this node and its children to stdout + void print( int spaces = 0 ); + + //! Remove the entry identified by path \b fullpath from this node + /*! \return the unique id of the removed entry, or \c 0 if no matching entry was found */ + inline unsigned int remove( const char *fullpath ) + { return( (unsigned int)modify( fullpath, REMOVE, tree->rdata ) ); } + + //! Remove the entry identified by unique id \b id from this node + /*! \return the unique id of the removed entry, or \c 0 if no matching entry was found */ + unsigned int remove( unsigned int id ); + + //! Remove the entry containing the widget \b w from this node. Note that the widget is automatically destroyed + /*! \return the unique id of the removed entry, or \c 0 if no matching entry was found */ + unsigned int remove( Fl_Widget *w ); + + //! Remove Node \b n + /*! \return the id of \b n on successful removal, or \c 0 if \b n is present */ + inline unsigned int remove( Node* n ) + { if( !n ) return 0; else return remove( n->id() ); } + + //! Select this entry and all child entries + void select_all(); + + //! Is this node currently selected? + inline bool selected() const + { return CHECK(SELECTED); } + + //! Select or unselect this node + void select( bool b ); + + //! Unselect this entry and all child entries (except for Node \b except ) + void unselect_all( Node* except = NULL ); + + //! Get the user-specific data stored in this node + inline void* user_data() + { return userData; } + + //! Set the user-specific data stored in this node + inline void user_data( void *d ) + { userData = d; } + + //! Get the widget in this node, or NULL if there is no widget. Note that the widget is destroyed by the tree/node on clear() or the destructor + inline Fl_Widget* widget() const + { return( _widget ? _widget->w : NULL ); } + + //! Set the widget in this node. Note that the widget is destroyed by the tree/node on clear() or the destructor + void widget( Fl_Widget *w ); + + protected: + + friend class Flu_Tree_Browser; + friend class NodeList; + + // Root node constructor + Node( const char *lbl = 0 ); + + // Non-root constructor + Node( bool l, const char* n, Node *p, RData &rdata, Fl_Widget *w, bool showLabel ); + + ~Node(); + + // add/remove/find/get + Node* modify( const char* path, int what, RData &rdata, Fl_Widget *w = 0, bool showLabel = true ); + + void sort(); + + void determineVisibility( bool parentVisible = true ); + + static bool isMoveValid( Node* &n1, int &where, Node* &n2 ); + + // handle/draw/measure/count + int recurse( RData &rdata, int type, int event = 0 ); + + void draw( RData &rdata, bool measure ); + + // recursively finding the full path of the node identified by id + bool findPath( unsigned int id, RData &rdata ); + + // recursively finding the full path of the node containing w + bool findPath( Fl_Widget *w, RData &rdata ); + + class FLU_EXPORT WidgetInfo + { + public: + Fl_Widget *w; + int defaultW; // the initial width of the widget + void (*CB)(Fl_Widget*,void*); + void *CBData; + }; + + unsigned int _id; // the unique id of this node + unsigned short flags; + NodeList _children; + Node *_parent; + Flu_Tree_Browser *tree; + FluSimpleString text; + WidgetInfo *_widget; // memory overhead deferred to WidgetInfo. present only if widget is + void *userData; + int totalChildH; // needed for animation + Fl_Image *cIcon[2], *bIcon[2], *lIcon; + Fl_Color textColor; + Fl_Font textFont; + unsigned char textSize; // the font size of the entry label text + unsigned short textW, textH; // how big the entry label actually is (stored within the node for performance reasons) + int currentY; // needed for animation + unsigned short currentH; + + inline static void _widgetCB( Fl_Widget* w, void* arg ) + { ((Node*)arg)->widgetCB(); } + void widgetCB(); + }; + + protected: + + inline static void _scrollCB( Fl_Widget* w, void* arg ) + { ((Flu_Tree_Browser*)arg)->redraw(); } + + inline static void _timerRedrawCB( void *arg ) + { ((Flu_Tree_Browser*)arg)->timerRedrawCB(); } + void timerRedrawCB(); + + inline static void _timerScrollCB( void *arg ) + { ((Flu_Tree_Browser*)arg)->timerScrollCB(); } + void timerScrollCB(); + + void on_dnd_leave(); + + void on_dnd_release(); + + bool on_dnd_drag( int X, int Y ); + + void on_dnd_drop( const Flu_DND_Event *e ); + + /* override of Fl_Double_Window::draw() */ + void draw(); + + Fl_Group *scrollBox; + Fl_Scrollbar *scrollH, *scrollV; + Fl_Group *_box; + Node root; + RData rdata; + int lastEvent; + float autoScrollX, autoScrollY; + bool scrolledTimerOn; + +}; + +#endif diff --git a/src/FLU/flu_export.h b/src/FLU/flu_export.h new file mode 100644 index 0000000..c73d922 --- /dev/null +++ b/src/FLU/flu_export.h @@ -0,0 +1,27 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + +#ifndef _FLU_EXPORT_H +#define _FLU_EXPORT_H + +#ifdef FLU_DLL + #ifdef FLU_LIBRARY + #define FLU_EXPORT __declspec(dllexport) + #else + #define FLU_EXPORT __declspec(dllimport) + #endif +#else + #define FLU_EXPORT +#endif + +#endif diff --git a/src/FLU/flu_pixmaps.h b/src/FLU/flu_pixmaps.h new file mode 100644 index 0000000..716c630 --- /dev/null +++ b/src/FLU/flu_pixmaps.h @@ -0,0 +1,54 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#ifndef _FLU_PIXMAPS_H +#define _FLU_PIXMAPS_H + +#include "flu_export.h" + +FLU_EXPORT extern char* plus_xpm[]; +FLU_EXPORT extern char* minus_xpm[]; +FLU_EXPORT extern char* arrow_closed_xpm[]; +FLU_EXPORT extern char* arrow_open_xpm[]; +FLU_EXPORT extern char* bluedot_xpm[]; +FLU_EXPORT extern char* book_xpm[]; +FLU_EXPORT extern char* floppy_drive_xpm[]; +FLU_EXPORT extern char* network_drive_xpm[]; +FLU_EXPORT extern char* ram_drive_xpm[]; +FLU_EXPORT extern char* removable_drive_xpm[]; +FLU_EXPORT extern char* cd_drive_xpm[]; +FLU_EXPORT extern char* computer_xpm[]; +FLU_EXPORT extern char* disk_drive_xpm[]; +FLU_EXPORT extern char* filled_folder_xpm[]; +FLU_EXPORT extern char* folder_closed_xpm[]; +FLU_EXPORT extern char* folder_open_xpm[]; +FLU_EXPORT extern char* folder_up_xpm[]; +FLU_EXPORT extern char* folder_load_xpm[]; +FLU_EXPORT extern char* folder_save_xpm[]; +FLU_EXPORT extern char* big_folder_up_xpm[]; +FLU_EXPORT extern char* big_folder_new_xpm[]; +FLU_EXPORT extern char* greendot_xpm[]; +FLU_EXPORT extern char* purpledot_xpm[]; +FLU_EXPORT extern char* question_book_xpm[]; +FLU_EXPORT extern char* reddot_xpm[]; +FLU_EXPORT extern char* tealdot_xpm[]; +FLU_EXPORT extern char* textdoc_xpm[]; +FLU_EXPORT extern char* yellowdot_xpm[]; +FLU_EXPORT extern char* cdrom_xpm[]; +FLU_EXPORT extern char* trash_xpm[]; +FLU_EXPORT extern char* home_xpm[]; +FLU_EXPORT extern char* reload_xpm[]; + +#endif diff --git a/src/FLU_LICENSE b/src/FLU_LICENSE new file mode 100644 index 0000000..273fc09 --- /dev/null +++ b/src/FLU_LICENSE @@ -0,0 +1,569 @@ +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Jason Bryan, Ohio Supercomputer Center, Ohio State University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * To contribute, advise, suggest, berate, recommend, criticise, + * or otherwise communicate with me: jbryan@osc.edu + * Ohio Supercomputer Center + * 1224 Kinnear Rd + * Columbus, Ohio 43212 + ***************************************************************/ + + +----------------------------------------------------------------------- + + This library depends on the following GPL free libraries: + FLTK + + This library also uses OpenGL, which is a registered trademark of Silicon + Graphics, Inc. (SGI), and Doxygen, a free HTML page generator for documentation + of C++ classes. + + + This library is hereby distributed under the same LGPL license as FLTK. + Have fun with it! + +----------------------------------------------------------------------- + + FLTK License + December 11, 2001 + +The FLTK library and included programs are provided under the terms +of the GNU Library General Public License (LGPL) with the following +exceptions: + + 1. Modifications to the FLTK configure script, config + header file, and makefiles by themselves to support + a specific platform do not constitute a modified or + derivative work. + + The authors do request that such modifications be + contributed to the FLTK project - send all + contributions to "fltk-bugs@fltk.org". + + 2. Widgets that are subclassed from FLTK widgets do not + constitute a derivative work. + + 3. Static linking of applications and widgets to the + FLTK library does not constitute a derivative work + and does not require the author to provide source + code for the application or widget, use the shared + FLTK libraries, or link their applications or + widgets against a user-supplied version of FLTK. + + If you link the application or widget to a modified + version of FLTK, then the changes to FLTK must be + provided under the terms of the LGPL in sections + 1, 2, and 4. + + 4. You do not have to provide a copy of the FLTK license + with programs that are linked to the FLTK library, nor + do you have to identify the FLTK license in your + program or documentation as required by section 6 + of the LGPL. + + However, programs must still identify their use of FLTK. + The following example statement can be included in user + documentation to satisfy this requirement: + + [program/widget] is based in part on the work of + the FLTK project (http://www.fltk.org). + +----------------------------------------------------------------------- + + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + [This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/src/FluSimpleString.cpp b/src/FluSimpleString.cpp new file mode 100644 index 0000000..32eae93 --- /dev/null +++ b/src/FluSimpleString.cpp @@ -0,0 +1,146 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#include "FLU/FluSimpleString.h" + +FluSimpleString :: FluSimpleString() +{ + str = strdup(""); +} + +FluSimpleString :: FluSimpleString( unsigned int len ) +{ + if( len > 0 ) + str = (char*)malloc( len ); + else + str = strdup(""); +} + +FluSimpleString :: FluSimpleString( const char *s ) +{ + str = strdup(""); + *this = s; +} + +FluSimpleString :: FluSimpleString( const FluSimpleString& s ) +{ + str = strdup(""); + *this = s.str; +} + +FluSimpleString :: ~FluSimpleString() +{ + if(str) + free(str); +} + +void FluSimpleString :: copy( const char *s, unsigned int start, unsigned int len ) +{ + if( len == 0 ) return; + if( s == 0 ) return; + if( start+len > strlen(s) ) return; + if(str) free(str); + str = (char*)malloc( len+1 ); + strncpy( str, s+start, len ); + str[len] = '\0'; +} + +int FluSimpleString :: compare( const FluSimpleString &s ) const +{ + return strcmp( str, s.str ); +} + +int FluSimpleString :: casecompare( const FluSimpleString &s ) const +{ + FluSimpleString s1(str), s2(s); + s1.upcase(); + s2.upcase(); + return strcmp( s1.str, s2.str ); +} + +void FluSimpleString :: upcase() +{ + unsigned int l = strlen(str); + for( unsigned int i = 0; i < l; i++ ) + str[i] = toupper( str[i] ); +} + +void FluSimpleString :: downcase() +{ + unsigned int l = strlen(str); + for( unsigned int i = 0; i < l; i++ ) + str[i] = tolower( str[i] ); +} + +int FluSimpleString :: find( char c ) const +{ + const char *i = strchr( str, c ); + if( !i ) + return -1; + else + return i-str; +} + +int FluSimpleString :: rfind( char c ) const +{ + const char *i = strrchr( str, c ); + if( !i ) + return -1; + else + return i-str; +} + +FluSimpleString FluSimpleString :: substr( int pos, int len ) const +{ + if( (pos+len) <= 0 || (pos+len) > size() ) + return FluSimpleString(""); + else + { + char *buf = (char*)malloc( len+1 ); + strncpy( buf, str+pos, len ); + buf[len] = '\0'; + FluSimpleString s = buf; + free( buf ); + return s; + } +} + +FluSimpleString& FluSimpleString :: operator =( const char *s ) +{ + char* tmp; + if(s==0) + tmp = strdup(""); + else + tmp = strdup(s); + if(str) + free(str); + str = tmp; + return *this; +} + +FluSimpleString& FluSimpleString :: operator +=( const char *s ) +{ + if( s==0 ) + s = ""; + char *old = strdup(str); + int lold = strlen(old), ls = strlen(s); + free(str); + str = (char*)malloc( lold + ls + 1 ); + memcpy( str, old, lold ); + memcpy( str+lold, s, ls ); + str[lold+ls] = '\0'; + free(old); + return *this; +} diff --git a/src/Flu_DND.cpp b/src/Flu_DND.cpp new file mode 100644 index 0000000..98b853f --- /dev/null +++ b/src/Flu_DND.cpp @@ -0,0 +1,264 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#include +#include "FLU/Flu_DND.h" + +Flu_DND_Event :: Flu_DND_Event() +{ + _text = _dataType = 0; + clear(); +} + +Flu_DND_Event :: ~Flu_DND_Event() +{ + clear(); +} + +void Flu_DND_Event :: clear() +{ + // reset everything + objUnderMouse = false; + dragging = false; + exit = false; + if(_text) free(_text); _text = 0; + if(_dataType) free(_dataType); _dataType = 0; + _data = 0; + _grab_x = _grab_y = _drop_x = _drop_y = 0; +} + +Flu_DND_Event Flu_DND::dndEvent; + +Flu_DND :: Flu_DND( const char *thisType ) +{ + // initialize everything + nTypes = 0; + _thisType = strdup( thisType ); + dnd_allow_text( false ); + dnd_callback( 0 ); + allowDragging = allowDropping = true; +} + +Flu_DND :: ~Flu_DND() +{ + // free all the stored types + if( _thisType ) + free( _thisType ); + for( int i = 0; i < nTypes; i++ ) + free( allowedTypes[i] ); +} + +void Flu_DND :: dnd_allow_type( const char *t ) +{ + if( nTypes >= FLU_DND_MAX_TYPES ) + return; + allowedTypes[nTypes++] = strdup( t ); +} + +bool Flu_DND :: dnd_type_allowed( const char *t ) const +{ + for( int i = 0; i < nTypes; i++ ) + if( strcmp( allowedTypes[i], t ) == 0 ) + return true; + return false; +} + +void Flu_DND :: dnd_grab( void *data, const char *type ) +{ + dndEvent.clear(); + if( !allowDragging || !data ) + return; + // remember the event + //printf( "dnd_grab %s %X\n", _thisType, this ); + dndEvent.dragging = true; + dndEvent.exit = false; + dndEvent.objUnderMouse = this; + dndEvent._data = data; + dndEvent._dataType = strdup( type ); + dndEvent._grab_x = Fl::event_x(); + dndEvent._grab_y = Fl::event_y(); + + // start the fltk system-wide DND + Fl::copy( " ", 1, 0 ); + Fl::dnd(); +} + +void Flu_DND :: on_dnd_enter() +{ +} + +void Flu_DND :: on_dnd_leave() +{ +} + +void Flu_DND :: on_dnd_drop( const Flu_DND_Event *e ) +{ +} + +void Flu_DND :: on_dnd_release() +{ +} + +bool Flu_DND :: on_dnd_drag( int X, int Y ) +{ + return true; +} + +int Flu_DND :: dnd_handle( int event ) +{ + // if dnd is on, then only DND events are generated + // but, there appears to be a bug in fltk where an FL_NO_EVENT is generated if the mouse + // is released when outside of any fltk widget. so, if we detect the NO_EVENT, and we are still + // dragging, then we need to process it as a release + if( dndEvent.dragging && event == FL_NO_EVENT ) + { + if( dndEvent.exit ) // not in any widget + { + // trash the event and return + //printf( "exit %s %X\n", _thisType, this ); + dndEvent.clear(); + return 1; + } + // otherwise the NO_EVENT is inside a widget. i don't know why a NO_EVENT is generated + // since the event is inside a widget. but, whatever. at any rate, this object should process + // it as a paste, only if it is the object the mouse is over (as tracked by dndEvent.objUnderMouse) + if( dndEvent.objUnderMouse == this ) + { + //printf( "FL_NO_EVENT %s %X\n", _thisType, this ); + event = FL_PASTE; + } + } + + //printf( "event %d %s %X\n", event, _thisType, this ); + + switch( event ) + { + case FL_DND_DRAG: + { + //printf( "FL_DND_DRAG %s %X\n", _thisType, this ); + + // if we receive a drag event and we are not holding data, then it must be + // from an fltk text widget + + // remember where the dragging occurs and check if it's ok for us + // to drop the item here + dndEvent.dragging = true; + dndEvent.objUnderMouse = this; + dndEvent._drop_x = Fl::event_x(); + dndEvent._drop_y = Fl::event_y(); + + return ok2drop(); + } + + case FL_DND_RELEASE: + //printf( "FL_DND_RELEASE %s %X\n", _thisType, this ); + on_dnd_release(); + return ok2drop(); + + case FL_UNFOCUS: + //printf( "FL_UNFOCUS %s %X\n", _thisType, this ); + return 1; + + case FL_FOCUS: + //printf( "FL_FOCUS %s %X\n", _thisType, this ); + return 1; + + case FL_DND_ENTER: + //printf( "FL_DND_ENTER %s %X\n", _thisType, this ); + dndEvent.exit = false; + dndEvent.objUnderMouse = this; + dndEvent._drop_x = Fl::event_x(); + dndEvent._drop_y = Fl::event_y(); + if( ok2drop() ) // if it's ok to drop, then it's ok to enter + { + on_dnd_enter(); + return 1; + } + else + return 0; + + case FL_DND_LEAVE: + //printf( "FL_DND_LEAVE %s %X\n", _thisType, this ); + dndEvent.exit = true; + dndEvent.objUnderMouse = NULL; + on_dnd_leave(); + return 1; + + case FL_PASTE: + //printf( "FL_PASTE %s %X\n", _thisType, this ); + on_dnd_release(); + // if the mouse is not inside a DND widget, then there's nothing to do + if( dndEvent.exit ) + { + dndEvent.clear(); + return 0; + } + + //if( dndEvent.objUnderMouse != this ) + //return 0; + + // if there's no data, then this paste is generated from an FLTK text DND event + if( !dndEvent.data() ) + { + dndEvent.clear(); + dndEvent._text = strdup( Fl::event_text() ); + } + dndEvent._drop_x = Fl::event_x(); + dndEvent._drop_y = Fl::event_y(); + + // if it's ok to drop, then call the drop processing members + if( true ) + { + if( dndCallback ) + dndCallback( &dndEvent, dndCallbackData ); + on_dnd_drop(&dndEvent); + dndEvent.clear(); + return 1; + } + else + { + dndEvent.clear(); + return 0; + } + + default: + // just in case + //printf( "event: %d\n", event ); + if( dndEvent.exit ) + { + on_dnd_release(); + dndEvent.clear(); + } + break; + } + return 0; +} + +bool Flu_DND :: ok2drop() +{ + if( !allowDropping ) + return false; + + if( dndEvent.data() ) // see if the dnd event is valid + { + // check if the source type is allowed by this class + if( !dnd_type_allowed( dndEvent.data_type() ) ) + return false; + } + else if( !allowTextEvents ) // event is a normal FLTK text dnd event + return false; + + return on_dnd_drag( Fl::event_x(), Fl::event_y() ); +} diff --git a/src/Flu_Tree_Browser.cpp b/src/Flu_Tree_Browser.cpp new file mode 100644 index 0000000..6813162 --- /dev/null +++ b/src/Flu_Tree_Browser.cpp @@ -0,0 +1,3420 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#include +#include +#include +#include + +#include "FLU/Flu_Tree_Browser.h" +#include "FLU/flu_pixmaps.h" + +#define MAX( x, y ) ( (x)>(y) ? (x) : (y) ) +#define MIN( x, y ) ( (x)<(y) ? (x) : (y) ) +#define ABS( x ) ( (x)>0 ? (x) : -(x) ) +#define LERP( t, x0, x1 ) ( (x0) + (t)*( (x1) - (x0) ) ) + +#ifdef USE_FLU_DND +Flu_Tree_Browser :: DND_Object :: DND_Object() : Flu_DND( "DND_Object" ) +{ +} +#endif + +Flu_Tree_Browser :: IntStack :: IntStack() +{ + _list = NULL; + _size = _bufferSize = 0; +} + +Flu_Tree_Browser :: IntStack :: IntStack( const Flu_Tree_Browser::IntStack& s ) +{ + _list = NULL; + _size = _bufferSize = 0; + *this = s; +} + +Flu_Tree_Browser :: IntStack :: ~IntStack() +{ + clear(); +} + +Flu_Tree_Browser::IntStack& Flu_Tree_Browser :: IntStack :: operator =( const Flu_Tree_Browser::IntStack& s ) +{ + clear(); + if( s._size ) + { + _list = (int*)malloc( s._size*sizeof(int) ); + memcpy( _list, s._list, s._size*sizeof(int) ); + _size = _bufferSize = s._size; + } + return *this; +} + +void Flu_Tree_Browser :: IntStack :: push( int i ) +{ + if( _size == _bufferSize ) + { + // allocate a new list + _bufferSize += 4; + int *newList = (int*)malloc( _bufferSize*sizeof(int) ); + // copy the old list + if( _size > 0 ) + memcpy( newList, _list, _size*sizeof(int) ); + if( _list ) + free( _list ); + _list = newList; + } + // add the new item + _list[_size] = i; + _size++; +} + +int Flu_Tree_Browser :: IntStack :: pop() +{ + if( _size == 0 ) + return 0; + int val = _list[_size]; + _size--; + return val; +} + +void Flu_Tree_Browser :: IntStack :: clear() +{ + if( _list ) + free( _list ); + _list = NULL; + _size = _bufferSize = 0; +} + +Flu_Tree_Browser :: NodeList :: NodeList() +{ + _nodes = NULL; + _nNodes = _size = 0; +} + +Flu_Tree_Browser :: NodeList :: ~NodeList() +{ + clear(); +} + +typedef Flu_Tree_Browser::Node* NodeP; + +bool Flu_Tree_Browser :: NodeList :: search( const char *n, int &index ) +{ + index = _nNodes; + if( _nNodes == 0 ) + return false; + + // we know we have at least one node. so use it to get the RData struct to find out what + // the insertion mode is + int iMode = _nodes[0]->tree->insertion_mode(); + + if( iMode == FLU_INSERT_SORTED || iMode == FLU_INSERT_SORTED_REVERSE ) + return( binSearch( n, index ) ); + else + return( linSearch( n, index ) ); +} + +bool Flu_Tree_Browser :: NodeList :: search( Node *n, int &index ) +{ + index = _nNodes; + if( _nNodes == 0 ) + return false; + + // we know we have at least one node. so use it to get the RData struct to find out what + // the insertion mode is + int iMode = _nodes[0]->tree->insertion_mode(); + + if( iMode == FLU_INSERT_SORTED || iMode == FLU_INSERT_SORTED_REVERSE ) + return( binSearch( n, index ) ); + else + return( linSearch( n, index ) ); +} + +bool Flu_Tree_Browser :: NodeList :: linSearch( const char *n, int &index ) +{ + index = _nNodes; + for( int i = 0; i < _nNodes; i++ ) + { + if( strcmp( n, _nodes[i]->label() ) == 0 ) + { + index = i; + return true; + } + } + return false; +} + +bool Flu_Tree_Browser :: NodeList :: linSearch( Node *n, int &index ) +{ + index = _nNodes; + for( int i = 0; i < _nNodes; i++ ) + { + if( n == _nodes[i] ) + { + index = i; + return true; + } + } + return false; +} + +bool Flu_Tree_Browser :: NodeList :: binSearch( Node *n, int &index ) +{ + if( binSearch( n->label(), index ) ) + { + // the search found the first node with the label. since there are identical entries + // allowed, it may not be the actual node we want. therefore search forward until we find it + for( ; index < _nNodes; index++ ) + if( _nodes[index] == n ) + return true; + return false; + } + else + return false; +} + +bool Flu_Tree_Browser :: NodeList :: binSearch( const char *n, int &index ) +{ + // do a binary search for a child with name == "n" + // return true if the child is found, and store its index in "index" + // return false if the child is not found, and store the index it would + // be in in "index" + + // special case: no nodes + if( _nNodes == 0 ) + { + index = 0; + return false; + } + + // we know we have at least one node. so use it to get the RData struct to find out what + // the insertion mode is + int iMode = _nodes[0]->tree->insertion_mode(); + + // special case: 1 node + if( _nNodes == 1 ) + { + int val = strcmp( n, _nodes[0]->label() ); + if( iMode == FLU_INSERT_SORTED_REVERSE ) + val *= -1; + if( val == 0 ) + { + index = 0; + return true; + } + else if( val < 0 ) + index = 0; + else + index = 1; + return false; + } + + int first = 0, last = _nNodes - 1; + int val1, val2, mVal; + for(;;) + { + // the range is down to 2 nodes + if( last == first + 1 ) + { + val1 = strcmp( n, _nodes[first]->label() ); + if( iMode == FLU_INSERT_SORTED_REVERSE ) + val1 = -val1; + if( val1 < 0 ) + { + index = first; + return false; + } + else if( val1 == 0 ) + { + index = first; + break; + } + val2 = strcmp( n, _nodes[last]->label() ); + if( iMode == FLU_INSERT_SORTED_REVERSE ) + val2 = -val2; + if( val2 < 0 ) + { + index = last; + return false; + } + else if( val2 == 0 ) + { + index = last; + break; + } + else + { + index = last+1; + return false; + } + } + + // pick which half of the array to search next + int midpoint = first + ((last-first)>>1); + mVal = strcmp( n, _nodes[midpoint]->label() ); + if( iMode == FLU_INSERT_SORTED_REVERSE ) + mVal = -mVal; + if( mVal < 0 ) + last = midpoint; + else if( mVal > 0 ) + first = midpoint; + else + { + index = midpoint; + break; + } + } + + // we found *a* node equal to "n", now find the first node equal to "n" + // by searching until we hit a node not equal to "n" + for( first = index; first > 0; first-- ) + if( strcmp( n, _nodes[first-1]->label() ) != 0 ) + break; + index = first; + + return true; +} + +int Flu_Tree_Browser :: NodeList :: compareNodes( const void *arg1, const void* arg2 ) +{ + Flu_Tree_Browser::Node *n1 = *((Flu_Tree_Browser::Node**)arg1), *n2 = *((Flu_Tree_Browser::Node**)arg2); + return strcmp( n1->text.c_str(), n2->text.c_str() ); +} + +int Flu_Tree_Browser :: NodeList :: reverseCompareNodes( const void *arg1, const void* arg2 ) +{ + Flu_Tree_Browser::Node *n1 = *((Flu_Tree_Browser::Node**)arg1), *n2 = *((Flu_Tree_Browser::Node**)arg2); + return( -strcmp( n1->text.c_str(), n2->text.c_str() ) ); +} + +void Flu_Tree_Browser :: NodeList :: sort() +{ + if( _nNodes ) + { + // we know we have at least one node. so use it to get the RData struct to find out what + // the insertion mode is + int iMode = _nodes[0]->tree->insertion_mode(); + if( iMode == FLU_INSERT_SORTED ) + qsort( _nodes, _nNodes, sizeof(Node*), compareNodes ); + else if( iMode == FLU_INSERT_SORTED_REVERSE ) + qsort( _nodes, _nNodes, sizeof(Node*), reverseCompareNodes ); + } +} + +bool Flu_Tree_Browser :: Node :: move( Node* n1, int where, Node* n2 ) +{ + if( isMoveValid( n1, where, n2 ) ) + return( NodeList::move( n1, where, n2 ) ); + else + return false; +} + +void Flu_Tree_Browser :: Node :: sort() +{ + _children.sort(); + for( int i = 0; i < _children.size(); i++ ) + _children.child(i)->sort(); +} + +bool Flu_Tree_Browser :: Node :: is_ancestor( Node* n ) +{ + Node *p = parent(); + while( p ) + { + if( p == n ) + return true; + else + p = p->parent(); + } + return false; +} + +bool Flu_Tree_Browser :: Node :: is_descendent( Node* n ) +{ + return n->is_ancestor( this ); +} + +bool Flu_Tree_Browser :: NodeList :: move( Node* n1, int where, Node* n2 ) +{ + if( !n1 || !n2 ) + return false; + + if( n1->tree ) + n1->tree->redraw(); + if( n2->tree ) + n2->tree->redraw(); + + // try to move n1 to the first child position of n2 + if( where == MOVE_INSIDE ) + { + if( !n2->is_branch() ) + return false; + // get the parent of n1 + Node* p1 = n1->parent(); + if( p1 ) + // remove n1 from its parent's list + p1->_children.erase( n1 ); + // insert into n2 + int iMode = n1->tree->insertion_mode(); + if( iMode == FLU_INSERT_SORTED || iMode == FLU_INSERT_SORTED_REVERSE ) + n2->_children.add( n1 ); + else + n2->_children.add( n1, 0 ); + // update the parent of n1 + n1->_parent = n2; + return true; + } + + // find the position of n2 in its parent's list + Node* p2 = n2->parent(); + if( !p2 ) + return false; + int index = 0, removed = -1; + if( p2->_children.search( n2, index ) ) + { + // get the parent of n1 + Node* p1 = n1->parent(); + if( p1 ) + // remove n1 from its parent's list. remember the position it was removed from + removed = p1->_children.erase( n1 ); + + // if n1 and n2 have the same parent, and if n1 came before the spot where + // n2 will be inserted, then our indexing is off by one because n1 has been removed + if( p1 == p2 && removed <= index ) + index--; + + if( where == MOVE_AFTER ) + index++; + + // insert n1 at the proper position + p2->_children.add( n1, index ); + + // update the parent of n1 + n1->_parent = p2; + } + + return true; +} + +void Flu_Tree_Browser :: NodeList :: insert_at(Flu_Tree_Browser::Node* i, Flu_Tree_Browser::Node* n) +{ + int c; + + if (i == 0) + add(n, -1); + else + { + // Find index of i within the list + for( c = 0; c < _nNodes; c++ ) + if (_nodes[c] == i) + { + add( n, c); + break; + } + } +} + +void Flu_Tree_Browser :: NodeList :: add( Node* n, int position ) +{ + int i, index; + int mode = n->tree->insertion_mode(); + + // if the list is out of room, allocate a new one that's bigger + if( _nNodes == _size ) + { + int newSize = ( _size == 0 ) ? 1 : _size*2; // double the size of the old list (same behavior as STL vector) + // allocate the new list + Node** newNodes = new NodeP[ newSize ]; + // copy the old list to the new list + memcpy( newNodes, _nodes, _nNodes*sizeof(Node*) ); + // delete the old list and replace it with the new list + delete[] _nodes; + _nodes = newNodes; + _size = newSize; + } + + if( position >= 0 ) + { + if( position > _nNodes ) + index = _nNodes; + else + index = position; + } + else if( mode == FLU_INSERT_SORTED || mode == FLU_INSERT_SORTED_REVERSE ) + { + // search through the list until we find where to insert the node + binSearch( n->label(), index ); + } + else if( mode == FLU_INSERT_FRONT ) + { + index = 0; + } + else if( mode == FLU_INSERT_BACK ) + { + index = _nNodes; + } + else + return; + + // shift all entries from the new insertion point down one spot + // to make room for the new node + for( i = _nNodes - 1; i >= index; i-- ) + _nodes[i+1] = _nodes[i]; + + // add the new node + _nodes[index] = n; + + _nNodes++; +} + +int Flu_Tree_Browser :: NodeList :: erase( Node *n ) +{ + if( n == NULL ) + return -1; + + int index; + if( search( n, index ) ) + { + // move all the others down one spot to remove the node + for( int i = index; i < _nNodes-1; i++ ) + _nodes[i] = _nodes[i+1]; + _nNodes--; + + return index; + } + return -1; +} + +int Flu_Tree_Browser :: NodeList :: erase( const char* n ) +{ + if( _nNodes == 0 ) + return -1; + + int index; + if( search( n, index ) ) + { + // move all the others down one spot to remove the node + for( int i = index; i < _nNodes-1; i++ ) + _nodes[i] = _nodes[i+1]; + _nNodes--; + return index; + } + return -1; +} + +void Flu_Tree_Browser :: NodeList :: erase( int n ) +{ + // make sure n is in range + if( ( n < 0 ) || ( n >= _nNodes ) ) + return; + + // move all the others down one spot to remove the node + for( int i = n; i < _nNodes-1; i++ ) + _nodes[i] = _nodes[i+1]; + + _nNodes--; +} + +void Flu_Tree_Browser :: NodeList :: clear() +{ + if( _nodes ) + delete[] _nodes; + _nodes = NULL; + _nNodes = _size = 0; +} + +int Flu_Tree_Browser :: NodeList :: findNum( const char *n ) +{ + if( ( _nNodes == 0 ) || ( n == 0 ) ) + return 0; + + // see if there is a first node equal to "n" + int index, last; + if( !search( n, index ) ) + return 0; + + // now search forward until we hit a node not equal to "n" + for( last = index; last < _nNodes-1; last++ ) + if( strcmp( n, _nodes[last+1]->label() ) != 0 ) + break; + + return last - index + 1; +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: NodeList :: find( const char* n, int which ) +{ + if( ( _nNodes == 0 ) || ( n == 0 ) || ( which == 0 ) ) + return NULL; + + // see if there is a first node equal to "n" + int index, first; + if( !search( n, first ) ) + return NULL; + + // now search forward and try to find the which'th node named "n" + int total = 0; + for( index = first; index < _nNodes; index++ ) + { + if( strcmp( n, _nodes[index]->label() ) == 0 ) + { + total++; + if( total == which ) + break; + } + else + break; + } + if( total != which ) + return NULL; + + return _nodes[index]; +} + +#define SCROLL_SIZE 15 + +Flu_Tree_Browser :: Flu_Tree_Browser( int x, int y, int w, int h, const char *l ) + : Fl_Group( x, y, w, h ) +#ifdef USE_FLU_DND + , Flu_DND( "Flu_Tree_Browser" ) +#endif +{ + lastEvent = -1; + autoScrollX = autoScrollY = 0.0f; +#ifdef USE_FLU_DND + dnd_allow_type( "Flu_Tree_Browser" ); + dnd_allow_type( "DND_Object" ); + dnd_allow_text( true ); +#endif + + // add some widgets + _box = new Fl_Group( x, y, w-SCROLL_SIZE, h-SCROLL_SIZE ); + _box->resizable( NULL ); + _box->end(); + scrollV = new Fl_Scrollbar( x+w-SCROLL_SIZE, y, SCROLL_SIZE, h-SCROLL_SIZE ); + scrollV->type( FL_VERTICAL ); + scrollV->callback( _scrollCB, this ); + scrollV->value( 0, 1, 0, 0 ); + scrollH = new Fl_Scrollbar( x, y+h-SCROLL_SIZE, w-SCROLL_SIZE, SCROLL_SIZE ); + scrollH->type( FL_HORIZONTAL ); + scrollH->callback( _scrollCB, this ); + scrollH->value( 0, 1, 0, 0 ); + scrollBox = new Fl_Group( x+w-SCROLL_SIZE, y+h-SCROLL_SIZE, SCROLL_SIZE, SCROLL_SIZE ); + scrollBox->box( FL_UP_BOX ); + scrollBox->end(); + resizable( _box ); + + // set up the recursive data structure + memset( &rdata, 0, sizeof(rdata) ); + rdata.root = &root; + root.tree = this; + rdata.tree = this; + rdata.dragging = false; + rdata.forceResize = true; + rdata.shiftSelect = false; + rdata.shiftSelectAll = false; + rdata.nextId = 1; + rdata.searchIndex = 1; + rdata.defaultCollapseIcons[0] = new Fl_Pixmap( plus_xpm ); + rdata.defaultCollapseIcons[1] = new Fl_Pixmap( minus_xpm ); + rdata.defaultBranchIcons[0] = new Fl_Pixmap( folder_closed_xpm ); + rdata.defaultBranchIcons[1] = new Fl_Pixmap( folder_open_xpm ); + + end(); + + // set the default values for the tree + animate( false ); + collapse_time( 0.1f ); + double_click_opens( true ); + move_only_same_group( false ); + frame_rate( 100.0f ); + allow_leaf_duplication( true ); + shaded_entry_colors( FL_WHITE, FL_WHITE ); + collapse_icons( NULL, NULL ); + branch_icons( NULL, NULL ); + leaf_icon( NULL ); + branch_text( FL_BLACK, FL_HELVETICA_BOLD, 12 ); + leaf_text( FL_BLACK, FL_HELVETICA, 12 ); + callback( NULL ); + when( FL_WHEN_CHANGED ); + color( FL_WHITE ); + selection_color( FL_SELECTION_COLOR ); + box( FL_NO_BOX ); + connector_style( FL_DARK2, FL_DOT ); + selection_mode( FLU_MULTI_SELECT ); + selection_drag_mode( FLU_DRAG_TO_SELECT ); + insertion_mode( FLU_INSERT_SORTED ); + show_connectors( true ); + show_root( true ); + show_leaves( true ); + show_branches( true ); + open_on_select( false ); + //root_always_open( false ); + horizontal_gap( 2 ); + vertical_gap( 0 ); + widget_gap( 2 ); + set_root( l ); +} + +Flu_Tree_Browser :: ~Flu_Tree_Browser() +{ + Fl::remove_timeout( _timerRedrawCB, this ); + Fl::remove_timeout( _timerScrollCB, this ); + + delete rdata.defaultCollapseIcons[0]; + delete rdata.defaultCollapseIcons[1]; + + delete rdata.defaultBranchIcons[0]; + delete rdata.defaultBranchIcons[1]; +} + +void Flu_Tree_Browser :: collapse_icons( Fl_Image *closed, Fl_Image *open ) +{ + if( closed ) + rdata.collapseIcons[0] = closed; + else + rdata.collapseIcons[0] = rdata.defaultCollapseIcons[0]; + + if( open ) + rdata.collapseIcons[1] = open; + else + rdata.collapseIcons[1] = rdata.defaultCollapseIcons[1]; +} + +void Flu_Tree_Browser :: branch_icons( Fl_Image *closed, Fl_Image *open ) +{ + if( closed ) + rdata.branchIcons[0] = closed; + else + rdata.branchIcons[0] = rdata.defaultBranchIcons[0]; + + if( open ) + rdata.branchIcons[1] = open; + else + rdata.branchIcons[1] = rdata.defaultBranchIcons[1]; +} + +void Flu_Tree_Browser :: leaf_icon( Fl_Image *icon ) +{ + rdata.leafIcon = icon; +} + +void Flu_Tree_Browser :: resize( int X, int Y, int W, int H ) +{ + Fl_Group::resize( X, Y, W, H ); + + int dx = Fl::box_dx(box()), dy = Fl::box_dy(box()), dw = Fl::box_dw(box()), dh = Fl::box_dh(box()); + + rdata.x = X+dx; rdata.y = Y+dy; rdata.totalW = rdata.x; + root.recurse( rdata, Node::MEASURE ); + rdata.totalW -= X-dx; + rdata.totalH = rdata.y - Y-dy; + + // if the size of the tree is bigger than the window, turn on the scrollbars + bool hOn = false, vOn = false; + if( rdata.totalW > W-dw ) + hOn = true; + if( rdata.totalH > H-dh ) + vOn = true; + + // check if turning on one scrollbar actually forces the other to turn on + if( hOn && ( rdata.totalH > H-SCROLL_SIZE ) ) + vOn = true; + if( vOn && ( rdata.totalW > W-SCROLL_SIZE ) ) + hOn = true; + + // now resize the other kids depending on the state of the scrollbars + + _box->resize( X, Y, W, H ); + if( hOn && vOn ) // both scrollbars on + { + scrollH->resize( X+dx, Y+H-SCROLL_SIZE-dy, W-SCROLL_SIZE-dw, SCROLL_SIZE ); + scrollH->show(); + scrollV->resize( X+W-SCROLL_SIZE-dx, Y+dy, SCROLL_SIZE, H-SCROLL_SIZE-dh ); + scrollV->show(); + scrollBox->resize( X+W-SCROLL_SIZE-dx, Y+H-SCROLL_SIZE-dy, SCROLL_SIZE, SCROLL_SIZE ); + scrollBox->show(); + + // set the scrollbar sizes and values + int hDelta = rdata.totalW - W+dw + SCROLL_SIZE, scrollHW = scrollH->w()-SCROLL_SIZE-SCROLL_SIZE; + hDelta = MAX( hDelta, 0 ); + scrollH->value( MIN( scrollH->value(), hDelta ), 1, 0, hDelta ); + scrollH->slider_size( MAX( (float)SCROLL_SIZE/float(scrollHW), float(scrollHW-hDelta)/float(scrollHW) ) ); + + int vDelta = rdata.totalH - H+dh + SCROLL_SIZE, scrollVH = scrollV->h()-SCROLL_SIZE-SCROLL_SIZE; + vDelta = MAX( vDelta, 0 ); + scrollV->value( MIN( scrollV->value(), vDelta ), 1, 0, vDelta ); + scrollV->slider_size( MAX( (float)SCROLL_SIZE/float(scrollVH), float(scrollVH-vDelta)/float(scrollVH) ) ); + } + else if( !hOn && !vOn ) // neither on + { + scrollH->hide(); + scrollV->hide(); + scrollBox->hide(); + } + else if( hOn ) // just horizontal on + { + scrollH->resize( X+dx, Y+H-SCROLL_SIZE-dy, W-dw, SCROLL_SIZE ); + scrollH->show(); + scrollV->hide(); + scrollBox->hide(); + + // set the scrollbar size and value + int hDelta = rdata.totalW - W+dw, scrollHW = scrollH->w()-SCROLL_SIZE-SCROLL_SIZE; + hDelta = MAX( hDelta, 0 ); + scrollH->value( MIN( scrollH->value(), hDelta ), 1, 0, hDelta ); + scrollH->slider_size( MAX( (float)SCROLL_SIZE/float(scrollHW), float(scrollHW-hDelta)/float(scrollHW) ) ); + } + else if( vOn ) // just vertical on + { + scrollH->hide(); + scrollV->resize( X+W-SCROLL_SIZE-dx, Y+dy, SCROLL_SIZE, H-dh ); + scrollV->show(); + scrollBox->hide(); + + // set the scrollbar size and value + int vDelta = rdata.totalH - H+dh, scrollVH = scrollV->h()-SCROLL_SIZE-SCROLL_SIZE; + vDelta = MAX( vDelta, 0 ); + scrollV->value( MIN( scrollV->value(), vDelta ), 1, 0, vDelta ); + scrollV->slider_size( MAX( (float)SCROLL_SIZE/float(scrollVH), float(scrollVH-vDelta)/float(scrollVH) ) ); + } + + rdata.browserX = _box->x() + dx; + rdata.browserY = _box->y() + dy; + rdata.browserW = _box->w() - dw; + rdata.browserH = _box->h() - dh; + + redraw(); + + rdata.forceResize = true; // weird hack to get the scrollbars to turn on right the first time +} + +void Flu_Tree_Browser :: on_dnd_leave() +{ +#ifdef USE_FLU_DND + rdata.isMoveValid = false; + redraw(); + + // X + if( scrollH->visible() ) + { + float max = (float) (0.01f * (scrollH->maximum() - scrollH->minimum())); + if( max < 10.0f ) max = 10.0f; + if( autoScrollX > 0.0f ) + autoScrollX = max; + else + autoScrollX = -max; + } + + // Y + if( scrollV->visible() ) + { + float max = (float) (0.01f * (scrollV->maximum() - scrollV->minimum())); + if( max < 10.0f ) max = 10.0f; + if( autoScrollY > 0.0f ) + autoScrollY = max; + else + autoScrollY = -max; + } +#endif +} + +bool Flu_Tree_Browser :: on_dnd_drag( int X, int Y ) +{ +#ifdef USE_FLU_DND + rdata.dragging = true; + + autoScrollX = autoScrollY = 0.0f; + + if( scrollH->visible() ) + { + // auto-scroll the horizontal scrollbars based on how close to the left or right of the browser the mouse is + float min = 1.0f, max = (float) (0.01f * (scrollH->maximum() - scrollH->minimum())); + if( max < 10.0f ) max = 10.0f; + if( X < (x()+30) ) // left + { + float t = float((x()+30) - X) / 30.0f; + autoScrollX = -LERP( t*t, min, max ); + if( !scrolledTimerOn ) + Fl::add_timeout( 0.0, _timerScrollCB, this ); + } + else if( X > (x()+w()-30) ) // right + { + float t = float(X - (x()+w()-30)) / 30.0f; + autoScrollX = LERP( t*t, min, max ); + if( !scrolledTimerOn ) + Fl::add_timeout( 0.0, _timerScrollCB, this ); + } + } + + if( scrollV->visible() ) + { + // auto-scroll the vertical scrollbars based on how close to the top or bottom of the browser the mouse is + float min = 1.0f, max = (float) (0.01f * (scrollV->maximum() - scrollV->minimum())); + if( max < 10.0f ) max = 10.0f; + if( Y < (y()+30) ) // top + { + float t = float((y()+30) - Y) / 30.0f; + autoScrollY = -LERP( t*t, min, max ); + if( !scrolledTimerOn ) + Fl::add_timeout( 0.0, _timerScrollCB, this ); + } + else if( Y > (y()+h()-30) ) // bottom + { + float t = float(Y - (y()+h()-30)) / 30.0f; + autoScrollY = LERP( t*t, min, max ); + if( !scrolledTimerOn ) + Fl::add_timeout( 0.0, _timerScrollCB, this ); + } + } + + if( autoScrollX == 0.0f && autoScrollY == 0.0f ) + { + Fl::remove_timeout( _timerScrollCB, this ); + scrolledTimerOn = false; + } + + int dx = Fl::box_dx(box()), dy = Fl::box_dy(box()); + rdata.x = x()+dx; rdata.y = y()+dy; + if( scrollH->visible() ) + rdata.x -= scrollH->value(); + if( scrollV->visible() ) + rdata.y -= scrollV->value(); + rdata.delta = 0; + root.recurse( rdata, Node::HANDLE, FL_DND_DRAG ); + rdata.isMoveValid = Fl::event_inside( this ) && Node::isMoveValid( rdata.grabbed, rdata.dragWhere, rdata.dragNode ); + + redraw(); + Fl::flush(); + + if( rdata.isMoveValid ) + return true; + else +#endif + return false; +} + +void Flu_Tree_Browser :: on_dnd_release() +{ +#ifdef USE_FLU_DND + Fl::remove_timeout( _timerScrollCB, this ); + scrolledTimerOn = false; + redraw(); + Fl::flush(); +#endif +} + +void Flu_Tree_Browser :: on_dnd_drop( const Flu_DND_Event *e ) +{ +#ifdef USE_FLU_DND + bool newNode = false; + + if( !rdata.isMoveValid ) + rdata.grabbed = 0; + + else if( e->event_is_text() && rdata.dnd ) + { + // create a new node with the text as the name and make it the grabbed node + rdata.grabbed = new Node( true, e->text(), NULL, rdata, NULL, true ); + if( rdata.grabbed ) + newNode = true; + } + + else + { + if( e->is_data_type( "Flu_Tree_Browser" ) ) + { + if( rdata.moveOnlySameGroup && ( rdata.grabbed->parent() != rdata.dragNode->parent() ) ) + rdata.grabbed = NULL; + } + else if( e->is_data_type( "DND_Object" ) && rdata.dnd ) + { + // create a new node with the text as the name and make it the grabbed node + DND_Object *o = (DND_Object*)e->data(); + rdata.grabbed = new Node( true, o->name(), NULL, rdata, NULL, true ); + if( rdata.grabbed ) + { + rdata.grabbed->user_data( e->data() ); + newNode = true; + } + } + else + rdata.grabbed = NULL; + } + + // select only the new/moved node + root.unselect_all( rdata.grabbed ); + set_hilighted( rdata.grabbed ); + if( rdata.grabbed ) + { + rdata.grabbed->select( true ); + + // move the node + if( NodeList::move( rdata.grabbed, rdata.dragWhere, rdata.dragNode ) ) + { + if( newNode ) + rdata.grabbed->do_callback( FLU_NEW_NODE ); + else + rdata.grabbed->do_callback( FLU_MOVED_NODE ); + } + rdata.forceResize = true; + } + Fl::focus(this); + + rdata.dragging = false; + rdata.grabbed = 0; + rdata.dragNode = 0; + Fl::remove_timeout( _timerScrollCB, this ); + scrolledTimerOn = false; + + redraw(); +#endif +} + +int Flu_Tree_Browser :: handle( int event ) +{ +#ifdef USE_FLU_DND + if( dnd_handle( event ) ) + return 1; +#endif + + if( event == FL_NO_EVENT || event == FL_MOVE ) + return 0; + + if( event == FL_FOCUS && rdata.lastHilighted ) + { + set_hilighted( rdata.lastHilighted ); + lastEvent = event; + Fl_Group::handle( event ); + redraw(); + return 1; + } + + if( event == FL_UNFOCUS ) + { + if( lastEvent != FL_LEAVE ) + { + rdata.lastHilighted = rdata.hilighted; + } + set_hilighted( NULL ); + lastEvent = event; + Fl_Group::handle( event ); + redraw(); + return 1; + } + + if( !rdata.dragging ) + { + if( ! (event == FL_MOVE || event == FL_ENTER || event == FL_LEAVE ) ) + _box->redraw(); + if( Fl_Group::handle( event ) ) + { + //if( event == FL_KEYDOWN || event == FL_KEYUP ) + // redraw(); + return 1; + } + } + + if( event == FL_RELEASE ) + { + Fl::focus(this); + rdata.dragging = false; + rdata.grabbed = 0; + rdata.dragNode = 0; + redraw(); + } + + int dx = Fl::box_dx(box()), dy = Fl::box_dy(box()); + + // set some initial values for the recursive data structure + // account for the scrollbar positions + rdata.x = x()+dx; rdata.y = y()+dy; + if( scrollH->visible() ) + rdata.x -= scrollH->value(); + if( scrollV->visible() ) + rdata.y -= scrollV->value(); + + rdata.previous = NULL; + rdata.delta = 0; + rdata.visibilityChanged = false; + + // catch cursor keys for moving the hilighted entry or selecting all entries + if( event == FL_KEYDOWN ) + { + // move hilighted entry up + if( Fl::event_key() == FL_Up ) + { + rdata.delta = -1; + Fl::focus(this); + redraw(); + } + + // move hilighted entry down + else if( Fl::event_key() == FL_Down ) + { + rdata.delta = 1; + Fl::focus(this); + redraw(); + } + + // select all + else if( Fl::event_state(FL_CTRL) && Fl::event_key() == 'a' ) + { + select_all(); + Fl::focus(this); + redraw(); + return 1; + } + + // check for the Home key + else if( Fl::event_key() == FL_Home ) + { + // set the hilighted entry to be the first entry + if( rdata.showRoot || ( rdata.root->_children.size() == 0 ) ) + set_hilighted( rdata.root ); + else if( rdata.root->_children.size() > 0 ) + set_hilighted( rdata.root->_children.child(0) ); + redraw(); + } + + // check for the End key + else if( Fl::event_key() == FL_End ) + { + // set the hilighted entry to be the last visible entry + if( rdata.showRoot && ( rdata.root->_children.size() == 0 ) ) + set_hilighted( rdata.root ); + else + { + // find the last node by repeatedly looking for the last child until there are no more branches + Node *n = &root; + while( n->_children.size() && n->open() ) + n = n->_children.child( n->_children.size()-1 ); + set_hilighted( n ); + } + redraw(); + } + } + + // pass the event down the tree + int val = root.recurse( rdata, Node::HANDLE, event ); + if( val ) + { + redraw(); + if( rdata.visibilityChanged ) + root.determineVisibility(); + if( val == 1 ) + return 1; + } + // special case: if multi-select or single-select and user clicks on no items, unselect all items + else if( (rdata.selectionMode != FLU_NO_SELECT) && (event == FL_PUSH) && (!Fl::event_state(FL_CTRL)) ) + { + unselect_all(); + set_hilighted( NULL ); + rdata.forceResize = true; + redraw(); + + return 1; + } + + if( event == FL_SHOW || event == FL_HIDE ) + root.determineVisibility(); + + return 0; +} + +void Flu_Tree_Browser :: insertion_mode( int m ) +{ + rdata.insertionMode = m; + root.sort(); +} + +void Flu_Tree_Browser :: set_hilighted( Flu_Tree_Browser::Node* n ) +{ + if( rdata.hilighted == n && rdata.when != FL_WHEN_NOT_CHANGED ) + return; + + if( rdata.hilighted ) + rdata.hilighted->do_callback( FLU_UNHILIGHTED ); + rdata.hilighted = n; + if( rdata.hilighted ) + rdata.hilighted->do_callback( FLU_HILIGHTED ); + + if( rdata.hilighted ) + { + int extraH = scrollH->visible() ? scrollH->h() : 0; + + // if the hilighted entry is below the visible bounds of the browser, move the vertical scrollbar + // so the hilighted entry is the last visible entry + if( rdata.hilighted->currentY-y()+rdata.hilighted->currentH > scrollV->value()+h()-extraH ) + ((Fl_Valuator*)scrollV)->value( rdata.hilighted->currentY-y() - h()+extraH + rdata.hilighted->currentH ); + + // if the hilighted entry is above the visible bounds of the browser, move the vertical scrollbar + // so the hilighted entry is the first visible entry + if( rdata.hilighted->currentY-y() < scrollV->value() ) + ((Fl_Valuator*)scrollV)->value( rdata.hilighted->currentY-y() ); + } + redraw(); +} + +int Flu_Tree_Browser :: num_selected() +{ + return root.recurse( rdata, Node::COUNT_SELECTED ); +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: get_selected( int index ) +{ + rdata.counter = 0; + rdata.searchIndex = index; + Node *n = root.modify( 0, Node::GET_SELECTED, rdata ); + rdata.searchIndex = 1; + return n; +} + +Flu_Tree_Browser :: Node :: Node( const char *lbl ) +{ + flags = 0; + userData = 0; + _parent = 0; + _widget = 0; + SET(ACTIVE); + CLEAR(LEAF); + _id = 0; + CLEAR(ALWAYS_OPEN); + SET(COLLAPSED); + SET(MOVABLE); + SET(DROPPABLE); + currentY = currentH = 0; + totalChildH = 0; + CLEAR(SELECTED); + CLEAR(EXPAND_TO_WIDTH); + SET(SHOW_LABEL); + if( lbl == 0 ) + text = ""; + else + text = lbl; + + cIcon[0] = cIcon[1] = bIcon[0] = bIcon[1] = lIcon = 0; +} + +Flu_Tree_Browser :: Node :: Node( bool l, const char* n, Node *p, RData &rdata, Fl_Widget *w, bool showLbl ) +{ + flags = 0; + userData = 0; + SET(LEAF,l); + text = n; + _id = 0; + SET(ACTIVE); + _parent = p; + CLEAR(ALWAYS_OPEN); + SET(COLLAPSED); + CLEAR(SELECTED); + CLEAR(EXPAND_TO_WIDTH); + SET(MOVABLE); + SET(DROPPABLE); + _widget = 0; + totalChildH = 0; + currentY = currentH = 0; + cIcon[0] = cIcon[1] = bIcon[0] = bIcon[1] = lIcon = 0; + SET( SHOW_LABEL, showLbl ); + + if( is_leaf() ) + { + lIcon = rdata.leafIcon; + textColor = rdata.defLeafColor; + textFont = rdata.defLeafFont; + textSize = rdata.defLeafSize; + } + else + { + cIcon[0] = rdata.collapseIcons[0]; + cIcon[1] = rdata.collapseIcons[1]; + bIcon[0] = rdata.branchIcons[0]; + bIcon[1] = rdata.branchIcons[1]; + textColor = rdata.defBranchColor; + textFont = rdata.defBranchFont; + textSize = rdata.defBranchSize; + } + + _id = rdata.nextId++; + tree = rdata.tree; + widget( w ); +} + +Flu_Tree_Browser :: Node :: ~Node() +{ + // if this node is in a tree, make sure it isn't holding a reference to us + if( tree ) + { + if( tree->rdata.hilighted == this ) tree->rdata.hilighted = NULL; + if( tree->rdata.lastHilighted == this ) tree->rdata.lastHilighted = NULL; + if( tree->rdata.grabbed == this ) tree->rdata.grabbed = NULL; + if( tree->rdata.dragNode == this ) tree->rdata.dragNode = NULL; + } + clear(); +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: first() +{ + return this; +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: first_branch() +{ + Node *n = first(); + while( n ) + { + if( n->is_branch() ) + return n; + else + n = n->next(); + } + return NULL; +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: first_leaf() +{ + Node *n = first(); + while( n ) + { + if( n->is_leaf() ) + return n; + else + n = n->next(); + } + return NULL; +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: last() +{ + if( children() == 0 ) + return this; + else + return( child( children() - 1 )->last() ); +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: last_branch() +{ + Node *n = last(); + while( n ) + { + if( n->is_branch() ) + return n; + else + n = n->previous(); + } + return NULL; +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: last_leaf() +{ + Node *n = last(); + while( n ) + { + if( n->is_leaf() ) + return n; + else + n = n->previous(); + } + return NULL; +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: next_sibling() +{ + if( is_root() ) + return NULL; + int index; + for( index = 0; index < _parent->children(); index++ ) + if( _parent->child(index) == this ) + break; + // if we are the last child of our parent, then we have no next sibling + if( index == _parent->children()-1 ) + return NULL; + // otherwise return our next sibling + else + return( _parent->child(index+1) ); +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: previous_sibling() +{ + if( is_root() ) + return NULL; + int index; + for( index = 0; index < _parent->children(); index++ ) + if( _parent->child(index) == this ) + break; + // if we are the first child of our parent, then we have no previous sibling + if( index == 0 ) + return NULL; + // otherwise return our previous sibling + else + return( _parent->child(index-1) ); +} + +int Flu_Tree_Browser :: Node :: index() const +{ + if( is_root() ) + return -1; + int index; + for( index = 0; index < _parent->children(); index++ ) + if( _parent->child(index) == this ) + return index; + return -1; +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: next() +{ + // take care of the root node as a special case + if( is_root() ) + { + if( children() ) + return child(0); + else + return NULL; + } + + // if we are a branch, then the next node is our first child, unless we don't have any children + if( is_branch() && _children.size() ) + return _children.child(0); + else + { + // otherwise, the next node is our next sibling. if there is no next sibling (because we + // are the last child of our parent), then the next node is the next sibling of our parent (and so on...) + Node *p = parent(), *n = next_sibling(); + while( p ) + { + if( n ) + return n; + else + { + n = p->next_sibling(); + p = p->parent(); + } + } + return NULL; + } +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: next_branch() +{ + Node *n = next(); + while( n ) + { + if( n->is_branch() ) + return n; + else + n = n->next(); + } + return NULL; +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: next_leaf() +{ + Node *n = next(); + while( n ) + { + if( n->is_leaf() ) + return n; + else + n = n->next(); + } + return NULL; +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: previous() +{ + // take care of the root node as a special case + if( is_root() ) + return NULL; + + // the previous node is either our parent's + // previous sibling (if that sibling exists and is a leaf or a branch with no children), + // or the last child of our parent's previous sibling (if that sibling exists and is + // a branch with children). if there is no previous sibling, then the previous node + // is our parent + Node *n = previous_sibling(); + if( !n ) + return _parent; + else + { + if( n->is_leaf() ) // is leaf, so that is the previous node + return n; + else if( n->children() ) // is branch with some children, so previous node is last child + return( n->last() ); + else // is branch with no children, so that is the previous node + return n; + } +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: previous_branch() +{ + Node *n = previous(); + while( n ) + { + if( n->is_branch() ) + return n; + else + n = n->previous(); + } + return NULL; +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: previous_leaf() +{ + Node *n = previous(); + while( n ) + { + if( n->is_leaf() ) + return n; + else + n = n->previous(); + } + return NULL; +} + +void Flu_Tree_Browser :: Node :: determineVisibility( bool parentVisible ) +{ + if( _widget ) + { + if( parentVisible ) + _widget->w->show(); + else + _widget->w->hide(); + } + for( int i = 0; i < _children.size(); i++ ) + _children.child(i)->determineVisibility( parentVisible && open() ); +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: child( int i ) const +{ + if( i < 0 || i >= _children.size() ) + return 0; + else + return _children.child(i); +} + +void Flu_Tree_Browser :: Node :: clear() +{ + widget(NULL); + for( int i = 0; i < _children.size(); i++ ) + delete _children.child(i); + _children.clear(); +} + +void Flu_Tree_Browser :: Node :: print( int spaces ) +{ + for( int s = 0; s < spaces; s++ ) + printf( " " ); + if( is_leaf() ) + printf( " %s\n", text.c_str() ); + else + printf( "[%s]\n", text.c_str() ); + + for( int i = 0; i < _children.size(); i++ ) + _children.child(i)->print( spaces+2 ); +} + +void Flu_Tree_Browser :: draw() +{ + if( rdata.forceResize ) + { + resize( x(), y(), w(), h() ); + rdata.forceResize = false; + } + + // draw the background color + fl_draw_box( FL_FLAT_BOX, _box->x(), _box->y(), _box->w(), _box->h(), _box->color() ); + + int dx = Fl::box_dx(box()), dy = Fl::box_dy(box()); + + // set up the recursive data structure + rdata.x = x()+dx; rdata.y = y()+dy; + // account for the positions of the scrollbars + if( scrollH->visible() ) + rdata.x -= scrollH->value(); + if( scrollV->visible() ) + rdata.y -= scrollV->value(); + rdata.first = true; + rdata.last = true; + rdata.bgColor = _box->color(); + rdata.shadedIndex = 0; + + // pick the connector line and selection colors depending on the active state + if( active() ) + { + rdata.lineColor = rdata.defLineColor; + rdata.selectionColor = rdata.defSelectionColor; + } + else + { + rdata.lineColor = fl_inactive( rdata.defLineColor ); + rdata.selectionColor = fl_inactive( rdata.defSelectionColor ); + } + + // draw the tree + fl_push_clip( _box->x(), _box->y(), _box->w(), _box->h() ); + root.recurse( rdata, Node::DRAW ); + + // if dragging to move, draw a bar showing where the dragged node will be inserted +#ifdef USE_FLU_DND + if( dnd_is_dragging() && rdata.isMoveValid && rdata.dragging ) + { + bool drawLine = false; + if( dnd_event_is_text() ) + drawLine = true; + else if( dnd_is_data_type( "Flu_Tree_Browser" ) ) + { + if( !rdata.moveOnlySameGroup || ( rdata.grabbed->parent() == rdata.dragNode->parent() ) ) + drawLine = true; + } + else if( dnd_is_data_type( "DND_Object" ) ) + drawLine = true; + if( drawLine && rdata.dragWhere != MOVE_INSIDE ) + { + fl_color( FL_RED ); + fl_line_style( FL_SOLID, 2 ); + fl_line( _box->x(), rdata.dragPos, _box->x()+_box->w(), rdata.dragPos ); + fl_line_style( 0 ); + } + } +#endif + + fl_pop_clip(); + + // draw the kids + draw_child( *scrollBox ); + draw_child( *scrollH ); + draw_child( *scrollV ); + + // draw the box last so it's on top + fl_draw_box( _box->box(), _box->x(), _box->y(), _box->w(), _box->h(), _box->color() ); +} + +inline void draw_T( int x, int y, int w, int h ) +{ + int w2 = w >> 1; + int h2 = h >> 1; + fl_line( x+w2, y, x+w2, y+h ); + fl_line( x+w2, y+h2, x+w, y+h2 ); +} + +inline void draw_L( int x, int y, int w, int h ) +{ + int w2 = w >> 1; + int h2 = h >> 1; + fl_line( x+w2, y, x+w2, y+h2 ); + fl_line( x+w2, y+h2, x+w, y+h2 ); +} + +inline void draw_Lflip( int x, int y, int w, int h ) +{ + int w2 = w >> 1; + int h2 = h >> 1; + fl_line( x+w2, y+h, x+w2, y+h2 ); + fl_line( x+w2, y+h2, x, y+h2 ); +} + +inline void draw_Ldash( int x, int y, int w, int h ) +{ + w = w >> 1; + h = h >> 1; + fl_line( x, y+h, x+w, y+h ); +} + +inline void draw_vert_dash( int x, int y, int w, int h ) +{ + w = w >> 1; + fl_line( x+w, y+(h>>1), x+w, y+h ); +} + +inline void draw_Rdash( int x, int y, int w, int h ) +{ + h = h >> 1; + fl_line( x+w, y+h, x+(w>>1), y+h ); +} + +void Flu_Tree_Browser :: Node :: draw( RData &rdata, bool measure ) +{ + int which = open(); // i.e. which icon: open or closed? + bool skipCollapser = is_root() && rdata.showRoot && ( CHECK(ALWAYS_OPEN) || rdata.allBranchesAlwaysOpen ); + int halfHGap = rdata.hGap >> 1, halfVGap = rdata.vGap >> 1; + bool doDraw = !measure; + + int X = rdata.x; + int Y = rdata.y; + + Fl_Color bgColor = rdata.shadedColors[rdata.shadedIndex], tColor = textColor, hilightColor = rdata.selectionColor; + + // pick the text color depending on the active state + if( !rdata.tree->active() || !CHECK(ACTIVE)) + tColor = fl_inactive( tColor ); + + if( doDraw ) + { + // draw the background for the entry using the entry background color + fl_draw_box( FL_FLAT_BOX, rdata.browserX, Y, rdata.browserW, currentH, bgColor ); + + // if dragging to the inside of a branch, hilight that branch +#ifdef USE_FLU_DND + if( tree->dnd_is_dragging() && rdata.isMoveValid && rdata.dragWhere == MOVE_INSIDE && rdata.dragNode == this ) + { + bgColor = FL_RED; + tColor = fl_contrast( tColor, bgColor ); + hilightColor = rdata.bgColor; + fl_draw_box( FL_FLAT_BOX, rdata.browserX, Y, rdata.browserW, currentH, bgColor ); + } + // if selected, draw a filled selection box and reverse the normal draw colors + else if( CHECK(SELECTED) ) +#else + if( CHECK(SELECTED) ) +#endif + { + bgColor = rdata.selectionColor; + tColor = fl_contrast( tColor, bgColor ); + hilightColor = rdata.bgColor; + fl_draw_box( FL_FLAT_BOX, rdata.browserX, Y, rdata.browserW, currentH, bgColor ); + } + + fl_color( rdata.lineColor ); + fl_line_style( rdata.lineStyle, rdata.lineWidth ); + } + + if( is_leaf() ) // draw leaves one way... + { + // draw the connectors + if( doDraw && rdata.showConnectors && rdata.showBranches ) + { + if( rdata.last ) + draw_L( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap ); + else + draw_T( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap ); + } + + // account for leaf icon spacing + if( rdata.showBranches ) + { + if( lIcon ) + X += rdata.collapseIcons[which]->w() + rdata.hGap; + else + X += rdata.collapseIcons[which]->w() + rdata.wGap; + } + else + X += rdata.wGap; + + // draw some more connectors + if( doDraw && rdata.showConnectors && lIcon && rdata.showBranches ) + draw_Ldash( X-halfHGap, Y-halfVGap, lIcon->w()+rdata.hGap, currentH+rdata.vGap ); + + // draw the leaf icon + if( lIcon ) + { + if( doDraw ) + lIcon->draw( X, Y+(currentH>>1)-(lIcon->h()>>1) ); + X += lIcon->w() + rdata.wGap; + } + } + else // ...and branches another + { + // force the root to the left if it has no visible children + if( _parent == 0 && !CHECK(SOME_VISIBLE_CHILDREN) ) + skipCollapser = true; + + if( !CHECK(SOME_VISIBLE_CHILDREN) && !rdata.showLeaves ) + which = 0; + + // draw the connectors + if( doDraw && !skipCollapser && rdata.showConnectors && rdata.showBranches ) + { + if( _parent==0 ) + { + if( CHECK(SOME_VISIBLE_CHILDREN) ) + draw_Rdash( X-halfHGap, Y-halfVGap, rdata.collapseIcons[which]->w()+4+rdata.hGap, currentH+rdata.vGap ); + } + else if( rdata.last ) + draw_L( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap ); + else + draw_T( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap ); + } + + // draw the collapsed icons + if( doDraw && !skipCollapser && !CHECK(ALWAYS_OPEN) && !rdata.allBranchesAlwaysOpen ) + { + if( CHECK(SOME_VISIBLE_CHILDREN) || rdata.showLeaves ) + { + if( _parent==0 ) + cIcon[which]->draw( X, Y+(currentH>>1)-(cIcon[which]->h()>>1) ); + else + cIcon[which]->draw( X+(rdata.branchIconW>>1)-(cIcon[which]->w()>>1), Y+(currentH>>1)-(cIcon[which]->h()>>1) ); + } + } + + if( !skipCollapser ) + { + X += cIcon[which]->w(); + if( bIcon[which] ) + X += rdata.hGap; + else + X += rdata.wGap; + } + + // draw some more connectors + if( doDraw && rdata.showConnectors && rdata.showBranches ) + { + int hGap = rdata.hGap; + if( bIcon[which] ) + hGap += bIcon[which]->w(); + if( skipCollapser ) + draw_vert_dash( X-halfHGap, Y-halfVGap, hGap, currentH+rdata.vGap ); + else if( !which || !CHECK(SOME_VISIBLE_CHILDREN) ) + draw_Ldash( X-halfHGap, Y-halfVGap, hGap, currentH+rdata.vGap ); + else + draw_Lflip( X-halfHGap, Y-halfVGap, hGap, currentH+rdata.vGap ); + } + + // draw the branch icon + if( bIcon[which] ) + { + if( doDraw ) + bIcon[which]->draw( X, Y+(currentH>>1)-(bIcon[which]->h()>>1) ); + X += bIcon[which]->w() + rdata.wGap; + } + } + + if( doDraw ) + fl_line_style( 0 ); + + // draw the entry + if( CHECK(SHOW_LABEL) ) + { + if( doDraw ) + { + fl_draw_box( FL_FLAT_BOX, X, Y+(currentH>>1)-(textH>>1), textW, textH, bgColor ); + fl_color( tColor ); + fl_font( textFont, textSize ); + fl_draw( text.c_str(), X, Y+(currentH>>1)-(textH>>1), textW, textH, FL_ALIGN_LEFT ); + } + X += textW; + } + if( _widget ) + { + int widgetW = _widget->w->w(); + int widgetH = _widget->w->h(); + if( doDraw ) + { + _widget->w->redraw(); + _widget->w->position( X, Y+(currentH>>1)-(widgetH>>1) ); + if( CHECK(EXPAND_TO_WIDTH) ) + _widget->w->size( MAX( _widget->defaultW, rdata.browserW - (X-rdata.browserX) ), _widget->w->h() ); + _widget->w->draw(); + } + if( CHECK(EXPAND_TO_WIDTH) ) + { + if( _widget->w->w() == _widget->defaultW ) + X += _widget->defaultW; + } + else + X += widgetW; + } + + // if hilighted, draw a box outlining the entry + if( rdata.hilighted == this && doDraw ) + { + fl_color( hilightColor ); + fl_line_style( FL_DOT, 1 ); + fl_rect( rdata.browserX, Y, rdata.browserW, currentH, hilightColor ); + fl_line_style( 0 ); + } + + rdata.totalW = MAX( rdata.totalW, X ); +} + +void Flu_Tree_Browser :: Node :: select( bool b ) +{ + if( (CHECK(SELECTED)==b) && (tree->rdata.when != FL_WHEN_NOT_CHANGED) ) + return; + SET(SELECTED,b); + tree->redraw(); + if( tree->rdata.when == FL_WHEN_RELEASE ) + return; + if( b ) + do_callback( FLU_SELECTED ); + else + do_callback( FLU_UNSELECTED ); +} + +void Flu_Tree_Browser :: timerScrollCB() +{ + bool doRedraw = false; + + float val = scrollV->value() + autoScrollY; + if( val < 0.0f ) + val = 0.0f; + if( val > scrollV->maximum() ) + val = (float) scrollV->maximum(); + doRedraw |= ( val != scrollV->value() ); + ((Fl_Valuator*)scrollV)->value( val ); + + val = scrollH->value() + autoScrollX; + if( val < 0.0f ) + val = 0.0f; + if( val > scrollH->maximum() ) + val = (float) scrollH->maximum(); + doRedraw |= ( val != scrollH->value() ); + ((Fl_Valuator*)scrollH)->value( val ); + + Fl::repeat_timeout( 0.02, _timerScrollCB, this ); + scrolledTimerOn = true; + if( doRedraw ) + redraw(); +} + +void Flu_Tree_Browser :: timerRedrawCB() +{ + if( rdata.animating ) + Fl::repeat_timeout( 1.0f/rdata.fps, _timerRedrawCB, this ); + redraw(); +} + +void Flu_Tree_Browser :: Node :: open( bool b ) +{ + if( is_leaf() ) + return; + + if( CHECK(ALWAYS_OPEN) || tree->rdata.allBranchesAlwaysOpen ) + return; + + if( (open() == b) && (tree->rdata.when != FL_WHEN_NOT_CHANGED) ) + return; + + tree->rdata.justOpenedClosed = true; + + SET(COLLAPSED,!b); + + if( tree->rdata.animate ) + { + // if we aren't yet animating a node, animate it! + if( !tree->rdata.animating && !tree->rdata.animatedNode ) + { + // if we don't know how high all the children are, find out + // (this only happens once per node, the first time it is opened) + if( totalChildH == 0 ) + { + RData r = tree->rdata; + r.x = r.y = r.totalW = 0; + recurse( r, Node::MEASURE_THIS_OPEN ); + } + // set the initial offset based on whether the branch is open or closed + tree->rdata.animationOffset = (float) (b ? -totalChildH : -1); + // the delta is how much to change the offset each frame + tree->rdata.animationDelta = totalChildH / ( tree->rdata.collapseTime * tree->rdata.fps ); + tree->rdata.animationDelta = b ? tree->rdata.animationDelta : -tree->rdata.animationDelta; + tree->rdata.animating = true; + tree->rdata.animatedNode = this; + Fl::add_timeout( 1.0f/tree->rdata.fps, _timerRedrawCB, tree ); + } + // otherwise reverse the direction of the animation, only if we are animating this node + else if( tree->rdata.animating && tree->rdata.animatedNode==this ) + { + if( b ^ (tree->rdata.animationDelta>0) ) + tree->rdata.animationDelta = -tree->rdata.animationDelta; + } + } + + if( open() && (_parent != 0) ) // root node doesn't count as a single open branch + { + if( ( tree->rdata.lastOpenBranch != this ) && tree->rdata.singleBranchOpen ) + tree->rdata.lastOpenBranch->close(); + tree->rdata.lastOpenBranch = this; + } + + tree->rdata.forceResize = true; + tree->rdata.visibilityChanged = true; + if( b ) + do_callback( FLU_OPENED ); + else + do_callback( FLU_CLOSED ); +} + +void Flu_Tree_Browser :: Node :: active( bool b ) +{ + if( CHECK(ACTIVE) == b && tree->rdata.when != FL_WHEN_NOT_CHANGED ) + return; + SET( ACTIVE, b ); + if( _widget ) + { + if( b ) + _widget->w->activate(); + else + _widget->w->deactivate(); + } + if( !CHECK(ACTIVE) ) + { + if( tree->rdata.hilighted == this ) + tree->set_hilighted( NULL ); + select( false ); + open( false ); + } +} + +void Flu_Tree_Browser :: Node :: unselect_all( Node* except ) +{ + if( this != except ) + select( false ); + for( int i = 0; i < _children.size(); i++ ) + _children.child(i)->unselect_all( except ); +} + +void Flu_Tree_Browser :: Node :: select_all() +{ + select( true ); + for( int i = 0; i < _children.size(); i++ ) + _children.child(i)->select_all(); +} + +bool Flu_Tree_Browser :: Node :: isMoveValid( Node* &n1, int &where, Node* &n2 ) +{ + // if n1 is NULL, then check it as if it were a node being moved from another tree + + if( n2 == NULL ) + return false; + + // check the validity of the move: + // 1) the source and destination nodes can't be the same + // 2) you can't move before the root node + // 3) you can't move an unmovable node or move a branch node such that it would become a descendent of itself + // 4) if moving only within the same group, check that the parents are the same + // 5) if moving into a sorted tree, the destination node MUST be a branch + // 6) a move AFTER an OPEN branch is a move BEFORE its first child + // 7) you can't move a node into a non-droppable branch node + + if( n1 == n2 ) + return false; + + if( where==MOVE_BEFORE && n2->is_root() ) + return false; + + if( n1 ) + { + if( !n1->movable() ) + return false; + if( n1->is_branch() ) + if( n1->is_descendent( n2 ) ) + return false; + } + + bool sameGroup = n2->tree->move_only_same_group(); + if( sameGroup && n1 ) + { + if( n1->parent() != n2->parent() || where==MOVE_INSIDE ) + return false; + } + + int iMode = n2->tree->insertion_mode(); + if( iMode == FLU_INSERT_SORTED || iMode == FLU_INSERT_SORTED_REVERSE ) + { + if( n2->is_branch() ) + { + where = MOVE_INSIDE; + return true; + } + else + return false; + } + + if( where==MOVE_AFTER && n2->is_branch() && n2->open() ) + { + // can't move inside a branch if within the same group, unless the first node is dragged + // from outside the tree (in which case n1 is NULL) + if( sameGroup && n1 ) + { + if( n2->_children.size() > 0 ) + return false; + } + else if( n2->_children.size() > 0 ) + { + where = MOVE_BEFORE; + n2 = n2->_children.child(0); + } + else + where = MOVE_INSIDE; + } + + if( where==MOVE_INSIDE ) + { + if( !n2->droppable() ) + return false; + } + else if( n2->parent() ) + if( !n2->parent()->droppable() ) + return false; + + return true; +} + +int Flu_Tree_Browser :: Node :: recurse( RData &rdata, int type, int event ) +{ + int i; + + if( type == COUNT_SELECTED ) + { + if( is_leaf() ) + return (int)CHECK(SELECTED); + else + { + int total = (int)CHECK(SELECTED); + for( i = 0; i < _children.size(); i++ ) + total += _children.child(i)->recurse( rdata, type, event ); + return total; + } + } + + // see if this entry is even visible + if( rdata.y > rdata.browserY+rdata.browserH ) + { + if( type == DRAW ) + return 1; + else if( type == HANDLE ) + return 0; + } + + int which = open(); + bool skipEntry = ( is_root() && !rdata.showRoot ) || ( is_leaf() && !rdata.showLeaves ) || ( is_branch() && !rdata.showBranches ); + bool skipCollapser = is_root() && rdata.showRoot && ( CHECK(ALWAYS_OPEN) || rdata.allBranchesAlwaysOpen ); + + // find the size of the entry label + if( (type == MEASURE) || (type == MEASURE_THIS_OPEN) ) + { + if( CHECK(SHOW_LABEL) ) + { + int W = 0, H; + fl_font( textFont, textSize ); + fl_measure( text.c_str(), W, H ); + W += 4; H += 4; // hack - it looks better + textW = W; + textH = H; + } + else + { + textW = textH = 0; + } + + // remember vertically where this node is w.r.t the browser + currentY = rdata.y; + + currentH = textH; + + // find the total size of the entry, depending on if there's a widget + if( _widget ) + currentH = MAX( _widget->w->h(), currentH ); + + // find the total height of this entry by taking the max height of the entry and icons + if( is_leaf() ) + { + if( lIcon ) + currentH = MAX( currentH, lIcon->h() ); + } + else + { + currentH = MAX( currentH, cIcon[which]->h() ); + if( bIcon[which] ) + currentH = MAX( currentH, bIcon[which]->h() ); + } + } + + bool skipAhead = (rdata.y + currentH) < rdata.browserY; + + // process the entry + switch( type ) + { + case DRAW: + { + if( skipEntry || skipAhead ) break; + + draw( rdata, false ); + + // draw any vertical connectors connecting our aunts, great aunts, etc., + if( rdata.showBranches ) + { + int d = depth()-1; + for( i = 0; i < rdata.branchConnectors.size(); i++ ) + { + if( i != d ) + { + fl_color( rdata.lineColor ); + fl_line_style( rdata.lineStyle, rdata.lineWidth ); + fl_line( rdata.branchConnectors[i], rdata.y, rdata.branchConnectors[i], rdata.y+currentH ); + fl_line_style( 0 ); + } + } + } + + rdata.shadedIndex = 1 - rdata.shadedIndex; // toggle the even/odd entry for shading + } + break; + + case MEASURE: + if( is_leaf() ) + CLEAR( SOME_VISIBLE_CHILDREN ); + else + { + // find out whether the branch has any children that could be visible + bool someVisibleChildren = rdata.showLeaves && ( _children.size() > 0 ); + for( i = 0; i < _children.size(); i++ ) + { + if( _children.child(i)->is_branch() ) + { + someVisibleChildren = true; + break; + } + } + SET( SOME_VISIBLE_CHILDREN, someVisibleChildren ); + } + case MEASURE_THIS_OPEN: + if( skipEntry ) break; + draw( rdata, true ); + break; + + case HANDLE: + { + if( skipEntry || skipAhead || !CHECK(ACTIVE) ) break; + + if( event != FL_DRAG && event != FL_NO_EVENT ) + rdata.justOpenedClosed = false; + + // if we are trying to select all entries between 2 widgets due to a shift-select... + if( rdata.shiftSelect ) + { + if( (rdata.hilighted == this) || (rdata.grabbed == this) ) + { + if( !rdata.shiftSelectAll ) + { + rdata.shiftSelectAll = true; + select( true ); + if( is_branch() && rdata.openOnSelect ) + { + open( true ); + } + } + else + { + rdata.shiftSelect = false; + rdata.shiftSelectAll = false; + rdata.grabbed = 0; + select( true ); + if( is_branch() && rdata.openOnSelect ) + { + open( true ); + } + } + } + else if( rdata.shiftSelectAll ) + { + select( true ); + if( is_branch() && rdata.openOnSelect ) + { + open( true ); + } + } + break; + } + + // check for the keyboard event + if( event == FL_KEYDOWN ) + { + // check for the spacebar selecting this entry + if( Fl::event_key() == ' ' && rdata.hilighted == this ) + { + if( Fl::event_state(FL_CTRL) ) + select( !CHECK(SELECTED) ); + else + { + rdata.root->unselect_all( this ); + select( true ); + } + if( is_branch() && rdata.openOnSelect ) + { + open( true ); + } + return 1; + } + + // check for the enter key opening/closing this entry + else if( (Fl::event_key() == FL_Enter) && (rdata.hilighted == this) ) + { + open( !open() ); + return 1; + } + + // check for the left/right cursor keys opening/closing this entry + else if( (Fl::event_key() == FL_Left) && (rdata.hilighted == this) ) + { + open( false ); + return 1; + } + else if( (Fl::event_key() == FL_Right) && (rdata.hilighted == this) ) + { + open( true ); + do_callback(FLU_RIGHT_CLICK); + return 1; + } + } + + // check for the "up" cursor key moving the hilighted entry + if( rdata.delta == -1 && rdata.hilighted == this && rdata.previous != NULL ) + { + tree->set_hilighted( rdata.previous ); + rdata.delta = 0; + return 1; + } + + // check for the "down" cursor key moving the hilighted entry + if( rdata.delta == 1 && rdata.hilighted == rdata.previous ) + { + tree->set_hilighted( this ); + rdata.delta = 0; + return 1; + } + + rdata.previous = this; + + // the event is not ours to use + //if( _widget && !rdata.dragging ) + //if( Fl::event_inside( _widget->w ) ) + // return 2; + + bool inExpander = false; + if( is_branch() ) + { + int which = open(); + if( _parent==0 ) + inExpander = Fl::event_inside( rdata.x, rdata.y+(currentH>>1)-(cIcon[which]->h()>>1), + cIcon[which]->w(), cIcon[which]->h() ); + else + inExpander = Fl::event_inside( rdata.x+(rdata.branchIconW>>1)-(cIcon[which]->w()>>1), + rdata.y+(currentH>>1)-(cIcon[which]->h()>>1), + cIcon[which]->w(), cIcon[which]->h() ); + } + + if( event == FL_PUSH ) + { + // check for expand/collapse + if( Fl::event_button() == FL_LEFT_MOUSE && inExpander ) + { + /* + if( is_branch() ) + { + bool c = false; + int which = open(); + if( _parent==0 ) + { + c = Fl::event_inside( rdata.x, rdata.y+(currentH>>1)-(cIcon[which]->h()>>1), + cIcon[which]->w(), cIcon[which]->h() ); + } + else + c = Fl::event_inside( rdata.x+(rdata.branchIconW>>1)-(cIcon[which]->w()>>1), + rdata.y+(currentH>>1)-(cIcon[which]->h()>>1), + cIcon[which]->w(), cIcon[which]->h() ); + if( inExpander ) + {*/ + open( !open() ); + rdata.dragging = false; + rdata.dragNode = 0; + return 1; + //} + //} + } + } + + if( event == FL_DRAG && rdata.justOpenedClosed ) + return 0; + + // if no selections, return + if( rdata.selectionMode == FLU_NO_SELECT ) + break; + + // if the event is not inside us, return + if( !Fl::event_inside( rdata.browserX, rdata.y, rdata.browserW, currentH ) ) + break; + +#ifdef USE_FLU_DND + // check for grabbing of a node for DND + if( event == FL_DRAG && rdata.selectionDragMode == FLU_DRAG_TO_MOVE && !is_root() && rdata.grabbed && + //rdata.insertionMode!=FLU_INSERT_SORTED && rdata.insertionMode!=FLU_INSERT_SORTED_REVERSE && + !tree->dnd_is_dragging() && !rdata.justOpenedClosed && CHECK(MOVABLE) ) + { + tree->dnd_grab( this, "Flu_Tree_Browser" ); + return 1; + } + + // dragging to move a node + if( event == FL_DND_DRAG ) + { + rdata.dragNode = this; // remember which node to move the grabbed node before/after + if( is_root() ) + { + rdata.dragWhere = MOVE_AFTER; + rdata.dragPos = rdata.y + currentH; + } + else + { + // if this is a leaf or an open branch, then can only move before or after + // otherwise can move inside + if( is_branch() && !open() ) + { + int t = MAX( currentH / 3, 1 ); + if( (Fl::event_y()-rdata.y) <= t ) + rdata.dragWhere = MOVE_BEFORE; + else if( (Fl::event_y()-rdata.y) <= (t<<1) ) + rdata.dragWhere = MOVE_INSIDE; + else + rdata.dragWhere = MOVE_AFTER; + } + else + { + if( (Fl::event_y()-rdata.y) <= (currentH>>1) ) + rdata.dragWhere = MOVE_BEFORE; + else + rdata.dragWhere = MOVE_AFTER; + } + + // where to draw the insertion position? + if( rdata.dragWhere == MOVE_BEFORE || rdata.dragWhere == MOVE_INSIDE ) + rdata.dragPos = rdata.y; + else + rdata.dragPos = rdata.y + currentH; + } + return 1; + } +#endif + + // single selection + if( rdata.selectionMode == FLU_SINGLE_SELECT ) + { + if( event == FL_PUSH ) + { + //rdata.dragging = true; + rdata.grabbed = this; + + rdata.root->unselect_all( this ); + tree->set_hilighted( this ); + if( Fl::event_state(FL_CTRL) ) + select( !CHECK(SELECTED) ); + else + select( true ); + + if( Fl::event_button() == FL_RIGHT_MOUSE) + { + do_callback( FLU_RIGHT_CLICK ); + } + if( is_leaf() ) + { + if( Fl::event_clicks() > 0 ) + { + Fl::event_clicks(0); + do_callback( FLU_DOUBLE_CLICK ); + } + } + else + { + if( Fl::event_clicks() > 0 ) + { + Fl::event_clicks(0); + if( rdata.doubleClickToOpen ) + open( !open() ); + else + do_callback( FLU_DOUBLE_CLICK ); + } + else if( rdata.openOnSelect ) + { + open( true ); + } + } + return 1; + } + else if( event == FL_DRAG ) + { + rdata.dragging = true; + //if( ( rdata.selectionDragMode == FLU_DRAG_IGNORE || rdata.selectionDragMode == FLU_DRAG_TO_MOVE) && ( tree->insertion_mode() == FLU_INSERT_FRONT || tree->insertion_mode() == FLU_INSERT_BACK ) ) + //return 1; + rdata.root->unselect_all( this ); + tree->set_hilighted( this ); + select( true ); + return 1; + } + else if( event == FL_RELEASE && rdata.when == FL_WHEN_RELEASE && selected() && !inExpander ) + { + do_callback( FLU_SELECTED ); + return 1; + } + } + + // multiple selection + else if( rdata.selectionMode == FLU_MULTI_SELECT ) + { + if( event == FL_PUSH ) + { + //rdata.dragging = true; + rdata.grabbed = this; + + if( Fl::event_state(FL_CTRL) ) + { + select( !CHECK(SELECTED) ); + tree->set_hilighted( this ); + } + else if( Fl::event_state(FL_SHIFT) ) + { + // select everything from the last selected entry to this one + if( rdata.hilighted == this ) + { + select( true ); + if( is_branch() ) + { + if( Fl::event_clicks() > 0 ) + { + Fl::event_clicks(0); + if( rdata.doubleClickToOpen ) + open( !open() ); + else + do_callback( FLU_DOUBLE_CLICK ); + } + else if( rdata.openOnSelect ) + { + open( !open() ); + } + } + } + else + { + rdata.shiftSelectAll = false; + rdata.shiftSelect = true; + rdata.grabbed = this; + rdata.root->recurse( rdata, HANDLE, 0 ); + tree->set_hilighted( this ); + } + } + else + { + rdata.root->unselect_all( this ); + select( true ); + if( is_leaf() ) + { + if( Fl::event_clicks() > 0 ) + { + Fl::event_clicks(0); + do_callback( FLU_DOUBLE_CLICK ); + } + } + else + { + if( Fl::event_clicks() > 0 ) + { + Fl::event_clicks(0); + if( rdata.doubleClickToOpen ) + open( !open() ); + else + do_callback( FLU_DOUBLE_CLICK ); + } + else if( rdata.openOnSelect ) + { + open( true ); + } + } + tree->set_hilighted( this ); + if( Fl::event_button() == FL_RIGHT_MOUSE) + { + do_callback( FLU_RIGHT_CLICK ); + } + } + return 1; + } + else if( event == FL_DRAG ) + { + rdata.dragging = true; + //if( ( rdata.selectionDragMode == FLU_DRAG_IGNORE || rdata.selectionDragMode == FLU_DRAG_TO_MOVE) && ( tree->insertion_mode() == FLU_INSERT_FRONT || tree->insertion_mode() == FLU_INSERT_BACK ) ) + //return 1; + select( true ); + tree->set_hilighted( this ); + return 1; + } + else if( event == FL_RELEASE && rdata.when == FL_WHEN_RELEASE && selected() && !inExpander ) + { + do_callback( FLU_SELECTED ); + return 1; + } + } + } + break; + } + + // advance the counters vertically to the next entry + if( !skipEntry ) + rdata.y += currentH + rdata.vGap; + + // if we're a leaf, no need to process further + if( is_leaf() ) + return 0; + + // should we bail out already if we're done processing? + if( closed() && !skipEntry && !skipCollapser && tree->rdata.animatedNode!=this && ( type != MEASURE_THIS_OPEN ) ) + return 0; + + if( !CHECK(SOME_VISIBLE_CHILDREN) ) + return 0; + + // advance the counters horizontally to the next entry + if( rdata.showBranches ) + { + if( !skipEntry && !skipCollapser ) + rdata.x += cIcon[which]->w() + rdata.hGap; + } + rdata.totalW = MAX( rdata.totalW, rdata.x ); + + // the branchIconW is the width of the branch icon at this level + // it is used to center all children icons under the branch icon + int lastBranchIconW = rdata.branchIconW; + if( rdata.showBranches ) + { + if( bIcon[which] ) + rdata.branchIconW = bIcon[which]->w(); + else + rdata.branchIconW = cIcon[which]->w(); + } + else + rdata.branchIconW = 0; + + // update the animation + if( tree->rdata.animatedNode==this && ( type == DRAW ) ) + { + // check for termination (if opening) + if( (rdata.animationOffset+rdata.animationDelta) >= 0.0f ) + { + tree->rdata.animatedNode = NULL; + rdata.animating = false; + tree->rdata.forceResize = true; + Fl::remove_timeout( _timerRedrawCB, tree ); + } + else + { + // update the offset + rdata.animationOffset += rdata.animationDelta; + fl_push_clip( rdata.browserX, rdata.y, rdata.browserW, rdata.browserH ); + rdata.y += (int)rdata.animationOffset; + } + } + + if( ( type == MEASURE ) || ( type == MEASURE_THIS_OPEN ) ) + totalChildH = rdata.y; + + // process all children + int val; + int tempW = rdata.branchIconW >> 1; + for( i = 0; i < _children.size(); i++ ) + { + // prepare the recursive data structure for the next level + if( !skipEntry ) + rdata.first = false; + rdata.last = (i == _children.size()-1 ); + + // if child "i" is not the last child, + // then there is a long connector that needs drawn between this node and the last child. + // push the horizontal position of the connector onto the stack + if( (type == DRAW) && rdata.showConnectors && ( i < _children.size()-1 ) ) + { + rdata.branchConnectors.push( rdata.x+tempW ); + val = _children.child(i)->recurse( rdata, type, event ); + rdata.branchConnectors.pop(); + } + else + val = _children.child(i)->recurse( rdata, type, event ); + + if( val ) + return val; + } + + // set the branch icon width back to what it was before we changed it + rdata.branchIconW = lastBranchIconW; + + if( ( type == MEASURE ) || ( type == MEASURE_THIS_OPEN ) ) + totalChildH = rdata.y - totalChildH; + + // update the animation + if( tree->rdata.animatedNode==this && ( type == DRAW ) ) + { + fl_pop_clip(); + // check for termination (if closing) + if( rdata.animationOffset <= (float)(-totalChildH) ) + { + tree->rdata.animatedNode = NULL; + rdata.animating = false; + tree->rdata.forceResize = true; + Fl::remove_timeout( _timerRedrawCB, tree ); + } + } + + // move back horizontally from the last entry + if( rdata.showBranches ) + { + if( !skipEntry && !skipCollapser ) + rdata.x -= cIcon[which]->w() + rdata.hGap; + } + + return 0; +} + +void Flu_Tree_Browser :: print() +{ + root.print(); +} + +void Flu_Tree_Browser :: clear() +{ + root.clear(); + root.text = ""; + + rdata.hilighted = NULL; + rdata.dragging = false; + rdata.forceResize = true; + rdata.lastOpenBranch = NULL; + rdata.shiftSelect = false; + rdata.shiftSelectAll = false; + rdata.nextId = 1; + rdata.searchIndex = 1; +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: set_root( const char *label, Fl_Widget *w, bool showLabel ) +{ + if( label == 0 ) + label = ""; + root.text = label; + root.widget( w ); + root.SET(Node::SHOW_LABEL,showLabel); + root.cIcon[0] = rdata.collapseIcons[0]; + root.cIcon[1] = rdata.collapseIcons[1]; + root.bIcon[0] = rdata.branchIcons[0]; + root.bIcon[1] = rdata.branchIcons[1]; + root.textColor = rdata.defBranchColor; + root.textFont = rdata.defBranchFont; + root.textSize = rdata.defBranchSize; + rdata.forceResize = true; + + return &root; +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: add( const char* fullpath, Fl_Widget *w, bool showLabel ) +{ + return( root.modify( fullpath, Node::ADD, rdata, w, showLabel ) ); +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser::insert_at(Flu_Tree_Browser::Node* p, Flu_Tree_Browser::Node* i, + const char *name, Fl_Widget* w, bool showLabel) +{ + if (p) + return p->insert_at(p, i, name, rdata, w, showLabel); + return 0; +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: add( const char* path, const char* text, Fl_Widget *w, bool showLabel ) +{ + // if the path does not end in '/', add it + FluSimpleString s = path; + if( path[strlen(path)-1] != '/' ) + s += "/"; + s += text; + + return add( s.c_str(), w, showLabel ); +} + +unsigned int Flu_Tree_Browser :: remove( const char *fullpath ) +{ + return( (unsigned int)root.modify( fullpath, Node::REMOVE, rdata ) ); +} + +unsigned int Flu_Tree_Browser :: remove( const char *path, const char *text ) +{ + // if the path does not end in '/', add it + FluSimpleString s = path; + if( path[strlen(path)-1] != '/' ) + s += "/"; + s += text; + return remove( s.c_str() ); +} + +unsigned int Flu_Tree_Browser :: remove( unsigned int id ) +{ + return root.remove( id ); +} + +unsigned int Flu_Tree_Browser :: Node :: remove( unsigned int id ) +{ + if( id == 0 ) + return 0; + + for( int i = 0; i < _children.size(); i++ ) + { + Node *n = _children.child(i); + if( n->id() == id ) + { + _children.erase( i ); + tree->rdata.forceResize = true; + delete n; + return id; + } + else if( n->remove( id ) ) + return id; + } + + return 0; +} + +unsigned int Flu_Tree_Browser :: remove( Fl_Widget *w ) +{ + return root.remove( w ); +} + +unsigned int Flu_Tree_Browser :: Node :: remove( Fl_Widget *w ) +{ + for( int i = 0; i < _children.size(); i++ ) + { + Node *n = _children.child(i); + if( n->_widget ) + { + if( n->_widget->w == w ) + { + int id = n->id(); + _children.erase( i ); + tree->rdata.forceResize = true; + delete n; + return id; + } + } + + int id = n->remove( w ); + if( id ) + return id; + } + + return 0; +} + +int Flu_Tree_Browser :: find_number( const char *fullpath ) +{ + rdata.counter = 0; + root.modify( fullpath, Node::FIND_NUMBER, rdata ); + return rdata.counter; +} + +int Flu_Tree_Browser :: find_number( const char *path, const char *text ) +{ + // if the path does not end in '/', add it + FluSimpleString s = path; + if( path[strlen(path)-1] != '/' ) + s += "/"; + s += text; + return find_number( s.c_str() ); +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: find_next( const char *fullpath, Node* startNode ) +{ + // degenerate case: root node + if( strcmp( fullpath, "/" ) == 0 ) + return &root; + rdata.previous = startNode; + return( root.modify( fullpath, Node::FIND, rdata ) ); +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: find_next( const char *path, const char *text ) +{ + // if the path does not end in '/', add it + FluSimpleString s = path; + if( path[strlen(path)-1] != '/' ) + s += "/"; + s += text; + return find_next( s.c_str() ); +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: find( const char *path, const char *text ) +{ + // if the path does not end in '/', add it + FluSimpleString s = path; + if( path[strlen(path)-1] != '/' ) + s += "/"; + s += text; + return find( s.c_str() ); +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: find( unsigned int id ) +{ + return root.find( id ); +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: find( unsigned int id ) +{ + if( id == 0 ) + return NULL; + + if( _id == id ) + return this; + + for( int i = 0; i < _children.size(); i++ ) + { + Node *n = _children.child(i)->find( id ); + if( n ) + return n; + } + + return NULL; +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: find( Fl_Widget *w ) +{ + return root.find( w ); +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: find( Fl_Widget *w ) +{ + if( _widget ) + if( _widget->w == w ) + return this; + + for( int i = 0; i < _children.size(); i++ ) + { + Node *n = _children.child(i)->find( w ); + if( n ) + return n; + } + + return NULL; +} + + +bool Flu_Tree_Browser :: Node :: findPath( unsigned int id, RData &rdata ) +{ + if( _id == id ) + { + if( is_leaf() ) + rdata.path += text; + else + { + rdata.path += text; + rdata.path += "/"; + } + return true; + } + + if( is_leaf() ) + return false; + + char *oldPath = strdup( rdata.path.c_str() ); + if( _parent != 0 ) + { + rdata.path += text; + rdata.path += "/"; + } + + for( int i = 0; i < _children.size(); i++ ) + { + if( _children.child(i)->findPath( id, rdata ) ) + { + free( oldPath ); + return true; + } + } + + rdata.path = oldPath; + free( oldPath ); + + return false; +} + +bool Flu_Tree_Browser :: Node :: findPath( Fl_Widget *w, RData &rdata ) +{ + if( _widget ) + if( _widget->w == w ) + { + if( is_leaf() ) + rdata.path += text; + else + { + rdata.path += text; + rdata.path += "/"; + } + return true; + } + + if( is_leaf() ) + return false; + + char *oldPath = strdup( rdata.path.c_str() ); + if( _parent != 0 ) + { + rdata.path += text; + rdata.path += "/"; + } + + for( int i = 0; i < _children.size(); i++ ) + { + if( _children.child(i)->findPath( w, rdata ) ) + { + free( oldPath ); + return true; + } + } + + rdata.path = oldPath; + free( oldPath ); + + return false; +} + +const char* Flu_Tree_Browser :: find_path( unsigned int id ) +{ + // degenerate case: the root is always id==0 + if( id == 0 ) + return "/"; + rdata.path = "/"; + if( root.findPath( id, rdata ) ) + return rdata.path.c_str(); + else + return ""; +} + +const char* Flu_Tree_Browser :: find_path( Fl_Widget *w ) +{ + rdata.path = "/"; + if( root.findPath( w, rdata ) ) + return rdata.path.c_str(); + else + return ""; +} + +char* remove_escape_chars( const char *str ) +{ + // remove any escape characters + char *text = strdup( str ); + int tIndex = 0; + for( int pIndex = 0; pIndex < (int)strlen( str ); pIndex++ ) + { + if( str[pIndex] != '\\' ) + text[tIndex++] = str[pIndex]; + } + text[tIndex] = '\0'; + + return text; +} + +void Flu_Tree_Browser :: Node :: do_callback( int reason ) +{ + if( tree->rdata.when == FL_WHEN_NEVER ) + return; + if( tree->rdata.cb ) + { + tree->rdata.cbReason = reason; + tree->rdata.cbNode = this; + tree->rdata.cb( tree, tree->rdata.cbd ); + } +} + +unsigned short Flu_Tree_Browser :: Node :: depth() const +{ + int d = 0; + Node *p = _parent; + while( p ) + { + d++; + p = p->_parent; + } + return d; +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: modify( const char* path, int what, RData &rdata, Fl_Widget *w, bool showLabel ) +{ + // find the w'th selected entry + if( what == GET_SELECTED ) + { + if( CHECK(SELECTED) ) + { + rdata.counter++; + if( rdata.counter == rdata.searchIndex ) + return this; + } + for( int i = 0; i < _children.size(); i++ ) + { + Node *n = _children.child(i)->modify( path, what, rdata, w ); + if( n ) + return n; + } + return NULL; + } + + // trivial test for a bogus empty path + if( path == 0 ) + return NULL; + + // if the path starts with '/', skip the '/' + if( path[0] == '/' ) + path++; + + // trivial test for a bogus empty path + if( path[0] == '\0' ) + return NULL; + + const char *remainingPath; + char *nodeName; + bool lastNode, branchNode; + Node *retNode = NULL; + + ///////////// extract the next node name from the path /////////////////// + + // find the next '/' that is not preceded by the escape character '\' + const char *slash = strchr( path, '/' ); + for(;;) + { + // find the next '/' + if( slash == NULL ) // there isn't one, so we're done + break; + // test for escape character + else if( slash[-1] == '\\' ) // path[0] can never be '/', so this is a safe test + slash = strchr( slash+1, '/' ); + // we have it + else + break; + } + + // if there is no slash, then the node name is the path and it is a leaf and the last node in the path + if( slash == NULL ) + { + branchNode = false; + char *name = strdup( path ); // copy the path + nodeName = remove_escape_chars( name ); // remove the escape characters + free( name ); + lastNode = true; + remainingPath = NULL; + } + // otherwise the node name is the path up to the slash, it is also a branch and may not be the last node in the path + else + { + branchNode = true; + char *name = (char*)malloc( slash-path+1 ); + strncpy( name, path, slash-path ); + name[slash-path] = '\0'; + nodeName = remove_escape_chars( name ); // remove the escape characters + free( name ); + lastNode = ( slash[1] == '\0' ); // this is the last node if there is nothing after the slash + if( lastNode ) + remainingPath = NULL; + else + remainingPath = slash+1; + } + + ///////////// process the node /////////////////// + + switch( what ) + { + case ADD: + { + // if the new node is a leaf node, add the string as a leaf and return + if( !branchNode ) + { + // is there already a node with this name? + Node *n = _children.find( nodeName ); + if( n ) + { + // if that node is a branch node, we can't add a new one with the same name + if( n->is_branch() ) + break; + + // if we are not allowed to add multiple nodes with the same name, + // then just return + if( !rdata.allowDuplication ) + break; + } + + // add a new node + retNode = new Node( true, nodeName, this, rdata, w, showLabel ); + _children.add( retNode ); + rdata.forceResize = true; + rdata.visibilityChanged = true; + } + // otherwise make sure the node name exists as a branch and recurse on it + else + { + // if there is already a node with this name, just use it + Node *n = NULL; + n = _children.find( nodeName ); + if( n ) + { + // make sure it is a branch + if( n->is_leaf() ) + break; + } + + // else add a new node + if( n == NULL ) + { + // only add the widget for the last node + n = new Node( false, nodeName, this, rdata, lastNode?w:NULL, lastNode?showLabel:true ); + _children.add( n ); + rdata.forceResize = true; + rdata.visibilityChanged = true; + } + + // recurse on the remainder of the path, if not the last node + if( lastNode ) + retNode = n; + else + retNode = n->modify( remainingPath, what, rdata, w, showLabel ); + } + } + break; + + case REMOVE: + { + // try to find the indicated node. if we can't find it, just return + Node *n = _children.find( nodeName ); + if( !n ) + break; + + // if this is the last node, remove it. + if( lastNode ) + { + int ID = n->id(); + _children.erase( n ); + delete n; + retNode = (Node*)ID; // non-null return value means remove was successful + rdata.forceResize = true; + rdata.visibilityChanged = true; + } + // otherwise recurse on the remainder of the path + else + retNode = n->modify( remainingPath, what, rdata, w, showLabel ); + } + break; + + case FIND: + { + // if this node equals the starting node for a find_next, + // then by clearing rdata.previous we flag that we are allowed to return the next match + if( rdata.previous == this ) + rdata.previous = NULL; + + Node *n = NULL; + + if( !lastNode ) + { + // if, according to the path, this is not the last node, then just recursively + // search for the named node + n = _children.find( nodeName ); + if( !n ) + break; + retNode = n->modify( remainingPath, what, rdata, w, showLabel ); + } + else + { + // otherwise, according to the path, this is the last node (i.e. a leaf). + // since only leaves can have multiple identical entries, + // try to find the indicated node, accounting for the possibility + // that it may not be the one we're after + int next = 1; + for(;;) + { + // look for the named node + n = _children.find( nodeName, next++ ); + + // if we can't find it, just return, because it's not here + if( !n ) + break; + + // we are only allowed to return a match if the previous node is NULL, + // indicating we have passed the starting node for a find_next + if( rdata.previous == NULL ) + { + retNode = n; + break; + } + + // if the found node equals the starting node for a find_next, + // then by clearing rdata.previous we flag that we are allowed to return the next match + if( rdata.previous == n ) + rdata.previous = NULL; + } + } + } + break; + + case FIND_NUMBER: + { + if( lastNode ) // can only match multiple leaves if the path says this is the last node + { + rdata.counter += _children.findNum( nodeName ); + } + else // otherwise recurse down the remaining path + { + Node *n = _children.find( nodeName ); + n->modify( remainingPath, what, rdata, w, showLabel ); + } + } + break; + } + + free( nodeName ); + + return retNode; +} + +Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: insert_at( Node* p, Node* i, const char* path, + RData &rdata, Fl_Widget *w, bool showLabel ) +{ + + const char *remainingPath; + char *nodeName; + bool lastNode, branchNode; + Node *retNode = NULL; + + ///////////// extract the next node name from the path /////////////////// + + // find the next '/' that is not preceded by the escape character '\' + const char *slash = strchr( path, '/' ); + for(;;) + { + // find the next '/' + if( slash == NULL ) // there isn't one, so we're done + break; + // test for escape character + else if( slash[-1] == '\\' ) // path[0] can never be '/', so this is a safe test + slash = strchr( slash+1, '/' ); + // we have it + else + break; + } + + // if there is no slash, then the node name is the path and it is a leaf and the last node in the path + if( slash == NULL ) + { + branchNode = false; + char *name = strdup( path ); // copy the path + nodeName = remove_escape_chars( name ); // remove the escape characters + free( name ); + lastNode = true; + remainingPath = NULL; + } + // otherwise the node name is the path up to the slash, it is also a branch and may not be the last node in the path + else + { + branchNode = true; + char *name = (char*)malloc( slash-path+1 ); + strncpy( name, path, slash-path ); + name[slash-path] = '\0'; + nodeName = remove_escape_chars( name ); // remove the escape characters + free( name ); + lastNode = ( slash[1] == '\0' ); // this is the last node if there is nothing after the slash + if( lastNode ) + remainingPath = NULL; + else + remainingPath = slash+1; + } + + ///////////// process the node /////////////////// + + // if the new node is a leaf node, add the string as a leaf and return + if( !branchNode ) + retNode = new Node( true, nodeName, this, rdata, w, showLabel ); + else + retNode = new Node( false, nodeName, this, rdata, w, showLabel ); + + // Find number of the given insert node + _children.insert_at(i, retNode); + rdata.forceResize = true; + rdata.visibilityChanged = true; + + free( nodeName ); + + return retNode; +} + +void Flu_Tree_Browser :: Node :: widgetCB() +{ + if( _widget ) + { + if( _widget->CB ) + _widget->CB( _widget->w, _widget->CBData ); + } + do_callback( FLU_WIDGET_CALLBACK ); +} + +void Flu_Tree_Browser :: Node :: widget( Fl_Widget *w ) +{ + tree->rdata.forceResize = true; + + if( _widget ) + { + Fl_Group *p = _widget->w->parent(); + if( p ) + p->remove( *(_widget->w) ); + delete _widget->w; + delete _widget; + _widget = NULL; + } + + if( !w ) + return; + + _widget = new WidgetInfo; + _widget->w = w; + _widget->defaultW = _widget->w->w(); + _widget->CB = _widget->w->callback(); + _widget->CBData = _widget->w->user_data(); + _widget->w->callback( _widgetCB, this ); + + Fl_Group *parent = w->parent(); + if( parent ) + parent->remove( *w ); + tree->_box->add( w ); +} + +void Flu_Tree_Browser :: Node :: branch_icons( Fl_Image *closed, Fl_Image *open ) +{ + if( is_branch() ) + { + bIcon[0] = closed; + bIcon[1] = open; + tree->rdata.forceResize = true; + } +} + +void Flu_Tree_Browser :: Node :: collapse_icons( Fl_Image *closed, Fl_Image *open ) +{ + if( is_branch() ) + { + if( !closed || !open ) + { + cIcon[0] = tree->rdata.defaultCollapseIcons[0]; + cIcon[1] = tree->rdata.defaultCollapseIcons[1]; + } + else + { + cIcon[0] = closed; + cIcon[1] = open; + } + tree->rdata.forceResize = true; + } +} + +void Flu_Tree_Browser :: Node :: leaf_icon( Fl_Image *icon ) +{ + if( is_leaf() ) + { + lIcon = icon; + tree->rdata.forceResize = true; + } +} diff --git a/src/LICENSE b/src/LICENSE new file mode 100644 index 0000000..273fc09 --- /dev/null +++ b/src/LICENSE @@ -0,0 +1,569 @@ +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Jason Bryan, Ohio Supercomputer Center, Ohio State University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * To contribute, advise, suggest, berate, recommend, criticise, + * or otherwise communicate with me: jbryan@osc.edu + * Ohio Supercomputer Center + * 1224 Kinnear Rd + * Columbus, Ohio 43212 + ***************************************************************/ + + +----------------------------------------------------------------------- + + This library depends on the following GPL free libraries: + FLTK + + This library also uses OpenGL, which is a registered trademark of Silicon + Graphics, Inc. (SGI), and Doxygen, a free HTML page generator for documentation + of C++ classes. + + + This library is hereby distributed under the same LGPL license as FLTK. + Have fun with it! + +----------------------------------------------------------------------- + + FLTK License + December 11, 2001 + +The FLTK library and included programs are provided under the terms +of the GNU Library General Public License (LGPL) with the following +exceptions: + + 1. Modifications to the FLTK configure script, config + header file, and makefiles by themselves to support + a specific platform do not constitute a modified or + derivative work. + + The authors do request that such modifications be + contributed to the FLTK project - send all + contributions to "fltk-bugs@fltk.org". + + 2. Widgets that are subclassed from FLTK widgets do not + constitute a derivative work. + + 3. Static linking of applications and widgets to the + FLTK library does not constitute a derivative work + and does not require the author to provide source + code for the application or widget, use the shared + FLTK libraries, or link their applications or + widgets against a user-supplied version of FLTK. + + If you link the application or widget to a modified + version of FLTK, then the changes to FLTK must be + provided under the terms of the LGPL in sections + 1, 2, and 4. + + 4. You do not have to provide a copy of the FLTK license + with programs that are linked to the FLTK library, nor + do you have to identify the FLTK license in your + program or documentation as required by section 6 + of the LGPL. + + However, programs must still identify their use of FLTK. + The following example statement can be included in user + documentation to satisfy this requirement: + + [program/widget] is based in part on the work of + the FLTK project (http://www.fltk.org). + +----------------------------------------------------------------------- + + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + [This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/src/MString.cpp b/src/MString.cpp new file mode 100644 index 0000000..0c4cee0 --- /dev/null +++ b/src/MString.cpp @@ -0,0 +1,2241 @@ +/* + $Id$ + + MString - Dynamic string data type library + Copyright (C) 2001-2005 Jesse L. Lovelace (jesse at aslogicsys dot com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ----- + $Log$ + Revision 1.1 2007/03/31 22:09:17 kpettit1 + Fixed issue with Read from HD in normal memory mode. Added many files for IDE & Assember. This is a work in progress and not complete yet. + + Revision 1.9 2005/04/11 15:33:53 pez4brian + Update for 0.70 release + + Revision 1.8 2005/04/11 01:29:30 thementat + Changing the license to LGPL. + + Revision 1.7 2005/03/28 15:37:06 pez4brian + Fix Delete + Optimize (const char*) operator + Clean up + + Revision 1.6 2004/12/15 14:57:46 pez4brian + Fixed bug in Find + + Revision 1.5 2004/12/01 21:04:10 thementat + Updating contact info. + + Revision 1.4 2004/12/01 19:41:42 pez4brian + Various changes and bug-fixes + + Revision 1.3 2001/10/17 13:23:53 thementat + Added new code by Balint Toth and revised headers. + +*/ + +//#include +//#include +#include +#include +#include "MString.h" + +#define MIN(a,b) ((a)<(b) ? (a) : (b)) + +//using std::cout; +//using std::endl; + +class MNode { +public: + MNode(char ch, MNode* link = NULL) {MLink_Forward = link; MInfo = ch; } + MNode *MLink_Forward; + char MInfo; +}; + +//Begin Static Functions --------------------------------- + +static void reverse_loop( MNode * & previous, MNode * & p ) +{ + + if ( p ) { + MNode * next = p->MLink_Forward; + p->MLink_Forward = previous; + previous = p; + p = next; + reverse_loop( previous, p ); + } +} + +static void reverse_driver( MNode * & p ) +{ + MNode * previous = 0; + reverse_loop( previous, p ); + p = previous; +} + +static MNode* copy(MNode* p, MNode*& tailNode) +{ + MNode* head = 0; + MNode* tail = 0; + + + while(p) { + if (!head) + head = tail = new MNode(p->MInfo); + else { + tail->MLink_Forward = new MNode(p->MInfo); + tail = tail->MLink_Forward; + } + p = p->MLink_Forward; + } + tailNode = tail; + return head; +} + +/* +// Added by Bruce Riggins +// copy a char array to a node structure +static int copy(MNode* fromNode, char * toPC) +{ + MNode* head = GetPointerAt; + MNode* tail = 0; + + + while(p) { + if (!head) + head = tail = new MNode(p->MInfo); + else { + tail->MLink_Forward = new MNode(p->MInfo); + tail = tail->MLink_Forward; + } + p = p->MLink_Forward; + } + tailNode = tail; + return head; +} +// End added by Bruce Riggins +*/ + +// Moved to internal private method +// Bruce Riggins +//static void deallocate(MNode* p) +void MString::deallocate(MNode* p) +{ + MNode* tmp; + while (p) { + tmp = p; + p = p->MLink_Forward; + delete tmp; + tmp = NULL; + } + if (pcStr) { + delete pcStr; + pcStr = NULL; + bModified = true; +// iBufferInUse = 0; + } +} + +static int string_length(char* string) +{ + int count = 0; + if (string == NULL) + return count; + while( string[count] != '\0') { + count++; + } + return count; +} + +static void MakeLetterLower(char& ch) { + + if ((ch >= 65) && (ch <= 90)) + ch = char(ch + 32); +} + +static void MakeLetterUpper(char& ch) { + + if ((ch >= 97) && (ch <= 122)) + ch = char(ch - 32); +} + +static MNode* TravelList(MNode * startPointer, int nCount) { + + MNode * tmp = startPointer; + for (int i = 0; i < nCount; i++) { + if (!tmp) + return 0; + tmp = tmp->MLink_Forward; + } + return tmp; +} + +static MNode* findTail(MNode * startPointer) { + MNode * tmp=startPointer; + while (tmp) { + if (!tmp->MLink_Forward) + return tmp; + tmp = tmp->MLink_Forward; + } + return startPointer; +} + +MNode* MString::GetPointerAt(int nIndex) { + + MNode* tmp = headMNode; + + for (int i = 0; (i < nIndex); i++) { + + if (NULL == tmp) + return NULL; + + tmp = tmp->MLink_Forward; + } + return tmp; +} + +static MNode * MakeRightChain(const MNode *node, int nStart, MNode*& finalNode) +{ + static int count = nStart; + + MNode * tmp = NULL; +// cout << "hi\n"; + if (!node) { +// cout << "after ! " << count << endl; + //finalNode = NULL; + count --; + return NULL; + } + else { + while (node) + { +// cout << "yo\n"; + tmp = MakeRightChain(node->MLink_Forward, nStart, finalNode); +// cout << "before && " << tmp->MInfo << endl; +// cout << "next " << tmp << endl; + if ((count >= 0) && (tmp)) { + finalNode = new MNode(tmp->MInfo, finalNode); + count--; + return tmp; + } + } + } +// cout << "bye\n"; + return NULL; +} + + +//End Static Functions ------------------------------------ + +//Begin Constructors -------------------------------------- + +MString::~MString() { + deallocate(headMNode); + headMNode = NULL; + tailMNode = NULL; + if (pcStr) + { + delete pcStr; + pcStr = NULL; + } +} + +MString::MString() { //100% + bModified = true; + + headMNode = NULL; + tailMNode = NULL; + precision = 3; + pcStr = NULL; +// iBufferInUse = 0; + iBufLen = -1; +} + +MString::MString(const MString &stringSrc) { //100% + bModified = true; + + headMNode = copy(stringSrc.headMNode, tailMNode); + precision = 3; + pcStr = NULL; +// iBufferInUse = 0; + iBufLen = -1; +} + +MString::MString(const char ch, int nRepeat) { //100% + bModified = true; + + if (nRepeat < 1) + return; + + headMNode = new MNode(ch); + nRepeat--; + MNode *tmp = headMNode; + + for (int i=0; i < nRepeat; i++) { + tmp->MLink_Forward = new MNode(ch); + tmp = tmp->MLink_Forward; + } + tailMNode = tmp; + precision = 3; + pcStr = NULL; +// iBufferInUse = 0; + iBufLen = -1; +} + +MString::MString(const char* string) { //100% + bModified = true; + + headMNode = NULL; + tailMNode = NULL; + pcStr = NULL; + precision = 3; + + int i = 0; + if ( string == NULL || + string[0] == '\0' ) + { + return; + } + + headMNode = new MNode(string[0]); + MNode *tmp = headMNode; + + for (i = 1; string[i] != '\0'; i++) + { + tmp->MLink_Forward = new MNode(string[i]); + tmp=tmp->MLink_Forward; + } + + tailMNode = tmp; + + precision = 3; + pcStr = NULL; +// iBufferInUse = 0; + iBufLen = -1; +} + +MString::MString(const char* string, int maxlen) { //100% + bModified = true; + + headMNode = NULL; + tailMNode = NULL; + pcStr = NULL; + precision = 3; + + int i = 0; + if ( string == NULL || + string[0] == '\0' ) + { + return; + } + + headMNode = new MNode(string[i]); + MNode *tmp = headMNode; + + for (i = 1; (i < maxlen) && (string[i] != '\0'); i++) + { + tmp->MLink_Forward = new MNode(string[i]); + tmp=tmp->MLink_Forward; + } + + tailMNode = tmp; + + pcStr = NULL; +// iBufferInUse = 0; + iBufLen = -1; +} + +MString::MString(int num) { + bModified = true; + + headMNode = NULL; + tailMNode = NULL; + + precision = 3; + + //deallocate(headMNode); + + int k = 1, + single = 0; + MString tmp; + + if( num == 0 ) + { + tmp = '0'; + } + + while ((num % (k)) < num) { + single = (num % (10 * k))/k; + tmp += char(single + '0'); //Thanks to botch for reminding me about '0' + k = k * 10; + + } + tmp.MakeReverse(); + headMNode = copy(tmp.headMNode, tailMNode); + + pcStr = NULL; +// iBufferInUse = 0; + iBufLen = -1; +} + +MString::MString(double num) { + bModified = true; + + headMNode = NULL; + tailMNode = NULL; + precision = 3; + + //deallocate(headMNode); + + MString tmp; + tmp.SetPrecision(GetPrecision()); + tmp += num; + headMNode = copy(tmp.headMNode, tailMNode); + pcStr = NULL; + +// iBufferInUse = 0; + + iBufLen = -1; +} + + + +//End Constructors ---------------------------------------- + +//Begin Test Functions ------------------------------------ + +void MString::testG() { //100% + + MNode *tmp = headMNode; + +// cout << "Head = " << headMNode << endl; + while (tmp) + { +// cout << tmp->MInfo << " " << tmp->MLink_Forward << endl; + tmp = tmp->MLink_Forward; + } +// cout << "Tail = " << tailMNode << endl; + +} + +MString MString::GetGVersion() { //100% + + MString tmp; + + for (int i = 0; MString_VERSION[i] != '\0'; i++) + tmp += MString_VERSION[i]; + return tmp; +} + + +//End Test Functions -------------------------------------- + +//Begin Precision Functions ------------------------------- + +void MString::SetPrecision(int num){ //100% + bModified = true; + + if (num > MAX_PRECISION) // + return; + precision = num; +} + +int MString::GetPrecision() const { //100% + + return precision; +} + +MString MString::ReturnLicense() { //100% + MString license; + license = "MString - Dynamic string data type library\nCopyright (C) 2000-2004 Jesse L. Lovelace\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"; + + return license; +} + +//End Precision Functions --------------------------------- + +//Begin String as Array Functions ------------------------- + +int MString::GetLength() const { //100% + + int length = 0; + + if (headMNode) { + + MNode* tmp = headMNode; + while (tmp) { //while pointer is not null, count characters. + length++; + tmp=tmp->MLink_Forward; //next node. + } + } + return length; +} + +bool MString::IsEmpty() const { //100% + + if (headMNode) + return false; + else + return true; +} + +void MString::Empty() { //100% + bModified = true; + + deallocate(headMNode); + headMNode = tailMNode = NULL; +} + +char MString::GetAt(int nIndex) const { //100% + + // 1/31/2005 EMW - GetAt calling GetLength which walks through + // the list to find length. Then walking through the list to + // the position we desired. Changed so walk to nIndex or end of + // MString and then stop. + + if ((nIndex < 0) || (IsEmpty())) + return 0; //return's null if MString is empty or to small. + + MNode* tmp = headMNode; + + int i = 0; + while( tmp && i < nIndex ) // while have node and less than nIndex + { + tmp=tmp->MLink_Forward; + ++i; + } + + if( !tmp ) + { + return 0; // index too large return 0 + } + else + { + return tmp->MInfo;// if last node is valid return MInfo + } +} + +char MString::operator [](int nIndex) const { //100% + + return GetAt(nIndex); +} + +char& MString::operator [](int nIndex) { + + char * nullChar = NULL; + + if ((nIndex < 0) || (IsEmpty())) + return *nullChar; //return's null if MString is empty or to small + + MNode* tmp = headMNode; + + int i = 0; + while( tmp && i < nIndex ) // while have node and less than nIndex + { + tmp=tmp->MLink_Forward; + ++i; + } + + if( !tmp ) // if last node is valid return MInfo + { + return *nullChar; // index too large return 0 + } + else + { + return tmp->MInfo;// if last node is valid return MInf + } +} + +void MString::SetAt(int nIndex, char ch) { //100% + bModified = true; + + if ((nIndex < 0) || (IsEmpty())) + return; + + MNode* tmp = headMNode; + + int i = 0; + while( tmp && i < nIndex ) // while have node and less than nIndex + { + tmp=tmp->MLink_Forward; + ++i; + } + + if(tmp) + { + tmp->MInfo = ch; + } +} + +//End String as Array Functions --------------------------- + + +//Begin overloaded stream functions ----------------------- + +/*std::ostream& operator<< (std::ostream& out, const MString& string) { //100% + + if (string.IsEmpty()) + return out; + + MNode* tmp = string.headMNode; //because friend, access via dot + while (tmp) { //while tmp not null go on + out << tmp->MInfo; + tmp = tmp->MLink_Forward; + } + return out; +} + +std::istream& operator>> (std::istream& in, MString& string) { //100% + + char ch; + while (in) { + + in.get(ch); + string += ch; + } + + return in; +} + +std::istream& getline(std::istream& in, MString& string) { //100% + //Idea from APString + + char ch = 0; + + while(in && ('\n' != ch)) { + + in.get(ch); + string += ch; + } + + if ('\n' == ch) + string += ch; + + return in; +} +*/ + +//End overloaded stream functions ------------------------- + +//Begin Assignment/Concatination operators ---------------- + +const MString& MString::operator=(const MString& stringSrc) { //100% + + if (this != &stringSrc) { + bModified = true; + deallocate(headMNode); + headMNode = copy(stringSrc.headMNode,tailMNode); + } + return *this; +} + +const MString& MString::operator=(char ch) { //100% + bModified = true; + + deallocate(headMNode); + headMNode = tailMNode = new MNode(ch); + return *this; +} + +const MString& MString::operator=(const char* string) { //100% + bModified = true; + + deallocate(headMNode); + + int i = 0; + if ( string == NULL || string[0] == '\0' ) { + headMNode=NULL; + tailMNode=NULL; + precision=3; + return *this; + } + + headMNode = new MNode(string[0]); + MNode *tmp = headMNode; + + for (i = 1; string[i] != '\0'; i++) { + tmp->MLink_Forward = new MNode(string[i]); + + tmp=tmp->MLink_Forward; + } + tailMNode = tmp; + + return *this; +} + +const MString& MString::operator =(int num) { //100% + bModified = true; + //Original MString + + //Thanks to Rask for the math! + deallocate(headMNode); + + int k = 1, + single = 0; + MString tmp; + + if( num == 0 ) + { + tmp = '0'; + } + + while ((num % (k)) < num) { + single = (num % (10 * k))/k; + tmp += char(single + '0'); //Thanks to botch for reminding me about '0' + k = k * 10; + } + tmp.MakeReverse(); + headMNode = copy(tmp.headMNode, tailMNode); + return *this; +} + +const MString& MString::operator =(double num) { //100% + bModified = true; + //Original MString + + deallocate(headMNode); + + MString tmp; + tmp.SetPrecision(GetPrecision()); + tmp += num; + + headMNode = copy(tmp.headMNode, tailMNode); + return *this; +} + +const MString& MString::operator =(float num) { //100% + bModified = true; + //Original MString + + deallocate(headMNode); + + MString tmp; + tmp.SetPrecision(GetPrecision()); + tmp += num; + + headMNode = copy(tmp.headMNode, tailMNode); + return *this; + +} + +//Begin added operators by Bruce Riggins --------------- +//MString::operator char * () const +MString::operator const char * () const +{ + MString * m = (MString *) this; // BAD BAD BAD Using pointer to get + return m->GetBuffer(); // around const. Is there a fix for this? +} +//End added operators by Bruce Riggins ----------------- + +MString operator +(const MString& string1, const MString& string2) { //100% + + MString tmpStr; + tmpStr = string1; + tmpStr += string2; + + return tmpStr; +} + +MString operator +(const MString& string, char ch) { //100% + + MString tmpStr; + tmpStr = string; + tmpStr += ch; + + return tmpStr; +} + +MString operator +(char ch, const MString& string) { //100% + + MString tmpStr; + tmpStr = ch; + tmpStr += string; + + return tmpStr; +} + +MString operator +(const MString& string, char* ch) { //100% + + MString tmpStr; + tmpStr = string; + tmpStr += ch; + + return tmpStr; +} + +MString operator +(char* ch, const MString& string) { //100% + + MString tmpStr; + tmpStr = ch; + tmpStr += string; + + return tmpStr; +} + +MString operator +(int num, const MString& string) { + + MString tmpStr; + tmpStr = num; + tmpStr += string; + + return tmpStr; +} + +MString operator +(const MString& string, int num) { + + MString tmpStr; + tmpStr = string; + tmpStr += num; + + return tmpStr; +} + +const MString& MString::operator +=(const MString& string) { //100% + + if (!(string.headMNode)) { //if string is empty do nothing. + return *this; + } + + bModified = true; + MNode* toAdd = string.headMNode; + + // EMW - moved out of loop, only need to check the first time + if (!headMNode) { + headMNode = tailMNode = new MNode(toAdd->MInfo); + toAdd = toAdd->MLink_Forward; + } + + while (toAdd) + { + tailMNode->MLink_Forward = new MNode(toAdd->MInfo); + tailMNode = tailMNode->MLink_Forward; + toAdd = toAdd->MLink_Forward; + } + return *this; +} + +const MString& MString::operator +=(char ch) { //100% + + if (ch == '\0') + return *this; + + bModified = true; + if (!headMNode) { + headMNode = tailMNode = new MNode(ch); + return *this; + } + else { + tailMNode->MLink_Forward = new MNode(ch); + tailMNode = tailMNode->MLink_Forward; + } + + return *this; +} + +const MString& MString::operator +=(char string[]) { //100% + bModified = true; + + for (int i = 0; string[i] != '\0'; i++) { + + if (!headMNode) { + headMNode = tailMNode = new MNode(string[i]); + } + else { + tailMNode->MLink_Forward = new MNode(string[i]); + tailMNode = tailMNode->MLink_Forward; + } + } + + return *this; +} + +const MString& MString::operator +=(int num) { + bModified = true; + + //Original MString function + //Concatinates a integer to a string (woohoo!) + + MString tmpStr; + int k = 1, + single = 0; + + + while ((num % (k)) < num) { + single = (num % (10 * k))/k; + tmpStr += char(single + '0'); + //Thanks to botch for reminding me about '0' + k = k * 10; + + } + tmpStr.MakeReverse(); + //numbers are in reverse order, need to straighten + + if (!headMNode) { + // if string is empty use static copy function + headMNode = copy(tmpStr.headMNode, tailMNode); + } + else { + MNode *otherTmp = tmpStr.headMNode; + + for (int i = 0; (otherTmp); i++) { + + + tailMNode->MLink_Forward = new MNode(otherTmp->MInfo); + tailMNode = tailMNode->MLink_Forward; + otherTmp = otherTmp->MLink_Forward; + + } + } + + return *this; +} + +const MString& MString::operator +=(double num) { + bModified = true; + //Original MString + + MString tmpStr, tmpStr2; + + int k = 1, + single = 0; + + long int num1 = int(num), + power = 1; + + + //THIS IS NOT A GOOD IMPLIMENTATION + //Ideas would be helpful + + // Thanks to Danny Horswell for fixing the float bug + while ((num1 % (k)) < num1) { + single = (num1 % (10 * k))/k; + tmpStr += char(single + '0'); + //Thanks to botch for reminding me about '0' + k = k * 10; + + } + + tmpStr.MakeReverse(); + //numbers are in reverse order, need to straighten + + + for (int i = 0; i < precision; i++) { + power = power * 10; + } + + num1 = int((num - num1) * power); + single = 0; + k = 1; + + while (k != power) { + single = (num1 % (10 * k))/k; + tmpStr2 += char(single + '0'); + //Thanks to botch for reminding me about '0' + k = k * 10; + + } + + tmpStr2.MakeReverse(); + + if (tmpStr2.headMNode) + tmpStr = tmpStr + '.' + tmpStr2; + + + MNode* toAdd = tmpStr.headMNode; + + while (toAdd) { + if (!headMNode) { + headMNode = tailMNode = new MNode(toAdd->MInfo); + toAdd = toAdd->MLink_Forward; + } + else { + tailMNode->MLink_Forward = new MNode(toAdd->MInfo); + tailMNode = tailMNode->MLink_Forward; + toAdd = toAdd->MLink_Forward; + } + } + return *this; +} + +const MString& MString::operator +=(float num) { + bModified = true; + //Original MString + + MString tmpStr; + tmpStr+=double(num); + + MNode* toAdd = tmpStr.headMNode; + + while (toAdd) { + if (!headMNode) { + headMNode = tailMNode = new MNode(toAdd->MInfo); + toAdd = toAdd->MLink_Forward; + } + else { + tailMNode->MLink_Forward = new MNode(toAdd->MInfo); + tailMNode = tailMNode->MLink_Forward; + toAdd = toAdd->MLink_Forward; + } + } + return *this; +} + + +//End Assignment/Concatination operators ------------------ + +//Begin Comparison operators ------------------------------ + +bool operator==(const MString& s1, const MString& s2) { //tested 90% + //Idea from CString + + if (s1.Compare(s2) != 0) + return false; + return true; +} + +bool operator==(const MString& s1, const char* s2) {//tested 90% + + if (s1.Compare(s2) != 0) + return false; + return true; +} + +bool operator==(const char* s1, const MString& s2) {//tested 90% + if (s2.Compare(s1) != 0) + return false; + return true; +} + +bool operator!=(const MString& s1, const MString& s2) { //tested 90% + //Idea from CString + + if (s1 == s2) + return false; + else + return true; +} + +bool operator!=(const MString& s1, char* s2) {//tested 90% + + if (s1 == s2) + return false; + else + return true; +} + +bool operator!=(char* s1, const MString& s2) {//tested 90% + + if (s1 == s2) + return false; + else + return true; +} + +bool operator!=(const MString& s1, const char* s2) { + + if (s1 == s2) + return false; + else + return true; +} + +bool operator <(const MString& s1, const MString& s2) { //tested 90% + //Idea from CString + + if (s1.Compare(s2) < 0) + return true; + else + return false; +} + +bool operator <(const MString& s1, char* s2) {//tested 90% + + if (s1.Compare(s2) < 0) + return true; + else + return false; +} + +bool operator <(char* s1, const MString& s2) {//tested 90% + + MString tmpStr(s1); + + if (tmpStr.Compare(s2) < 0) + return true; + + + return false; +} + +bool operator >(const MString& s1, const MString& s2) { //tested 90% + //Idea from CString + + if (s1.Compare(s2) > 0) + return true; + else + return false; +} + +bool operator >(const MString& s1, char* s2) {//tested 90% + + if (s1.Compare(s2) > 0) + return true; + else + return false; +} + +bool operator >(char* s1, const MString& s2) {//tested 90% + + if (s2.Compare(s1) < 0) + return true; + else + return false; +} + +bool operator <=(const MString& s1, const MString& s2) { //tested 90% + //Idea from CString + + if (s1.Compare(s2) <= 0) + return true; + else + return false; +} + +bool operator <=(const MString& s1, char* s2){//tested 90% + + if (s1.Compare(s2) <= 0) + return true; + else + return false; +} + +bool operator <=(char* s1, const MString& s2) {//tested 90% + + if (s2.Compare(s1) >= 0) + return true; + else + return false; +} + +bool operator >=(const MString& s1, const MString& s2) { //tested 90% + //Idea from CString + + if (s1.Compare(s2) >= 0) + return true; + else + return false; +} + +bool operator >=(const MString& s1, char* s2) {//tested 90% + + if (s1.Compare(s2) >= 0) + return true; + else + return false; +} + +bool operator >=(char* s1, const MString& s2){//tested 90% + + if (s2.Compare(s1) <= 0) + return true; + else + return false; +} + +int MString::Compare(const char* string) const { //not fully tested + //Idea from CString + + //This function is pretty well optimized + //because i didn't use [] but traversed list + + MNode *tmp = headMNode; + int error = 1; + /// ----- ADDED BY JPI 1/7/2004 ----------------- + int i = 0; + while( tmp ) + { + if( string[i] == '\0' ) + return ((i + 1) * 1); + + if( tmp->MInfo > string[i] ) + return (i + 1); + + if( tmp->MInfo < string[i] ) + return ((i + 1) * -1); + + i++; + tmp = tmp->MLink_Forward; + } + + if( string[i] == '\0' ) + error = 0; + + return error; + /// ----- ADDED BY JPI 1/7/2004 ----------------- + + //for (int i = 0; string[i] != '\0'; i++) { + // error = 0; + // if (!tmp) { + // return ((i + 1) * -1); + // } + // if (tmp->MInfo > string[i]) + // return (i + 1); + // //because what if we are at index 0? + + // if (tmp->MInfo < string[i]) + // return ((i + 1) * -1); + // tmp=tmp->MLink_Forward; + //} + //return error; + +} + +int MString::Compare(const MString& string) const { + + MNode *tmpString = string.headMNode; + MNode *tmp = headMNode; + int error = 1; + + /// ----- ADDED BY EMW 1/25/2005 ----------------- + int count = 0; + while( tmpString ) + { + error = 0; + + // check if tmp == NULL ( tmp is shorter than tmpString ) + if (!tmp) { + return ((count+1) * -1); + } + + // compare the letters + if (tmp->MInfo > tmpString->MInfo) + return (count+1); + if (tmp->MInfo < tmpString->MInfo) + return ((count+1) * -1); + + // get the next letter + tmp=tmp->MLink_Forward; + tmpString = tmpString->MLink_Forward; + + count++; + } + + // check if tmp is valid ( tmp is longer than tmpString ) + if(tmp) + { + return count; + } + /// ----- ADDED BY EMW 1/25/2005 ----------------- + + /*for (int i = 0; (tmpString); i++) { + error = 0; + if (!tmp) { + return ((i+1) * -1); + } + if (tmp->MInfo > tmpString->MInfo) + return (i+1); + if (tmp->MInfo < tmpString->MInfo) + return ((i+1) * -1); + tmp=tmp->MLink_Forward; + tmpString = tmpString->MLink_Forward; + }*/ + + // the next 4 lines need to be re-written + //if (GetLength() > string.GetLength()) + // return GetLength(); + //if (GetLength() < string.GetLength()) + // return (string.GetLength() * -1); + + return error; +} + +int MString::CompareNoCase(const char * string) const { //not fully tested + //Idea from CString +/* + MString tmpStr1(string); + MString tmpStr2; //make local copy of string, bad code, uses to much room. + tmpStr2.headMNode = copy(headMNode, tmpStr2.tailMNode); + + tmpStr1.MakeLower(); + tmpStr2.MakeLower(); + + + MNode *tmpString = tmpStr1.headMNode; + MNode *tmp = tmpStr2.headMNode; + + for (int i = 0; ((tmp) && (tmpString)); i++) { + + if (tmp->MInfo > tmpString->MInfo) + return i; + if (tmp->MInfo < tmpString->MInfo) + return (i * -1); + tmp=tmp->MLink_Forward; + tmpString = tmpString->MLink_Forward; + } + return 0; + */ + + MNode * tmp = headMNode; + char c1 = 0, + c2 = 0; + int error = 1; + for (int i = 0; (string[i] != '\0'); i++) { + error = 0; + if (!tmp) { + return ((i+1) * -1); + } + c1 = tmp->MInfo; + c2 = string[i]; + MakeLetterLower(c1); + MakeLetterLower(c2); + if (c1 > c2) + return (i+1); + if (c1 < c2) + return ((i+1) * -1); + tmp = tmp->MLink_Forward; + } + return error; +} + +int MString::Collate(char* string) const{ + //Idea from CString + + //WARNING, COLLATE CURRENTLY IS THE SAME AS COMPARE + //BECAUSE I DON'T KNOW HOW TO IMPLIMENT IT. + + return Compare(string); +} + +int MString::CollateNoCase(char* string) const{ + //Idea from CString + + //WARNING, COLLATE CURRENTLY IS THE SAME AS COMPARE + //BECAUSE I DON'T KNOW HOW TO IMPLIMENT IT. + + return CompareNoCase(string); +} + +bool MString::CompareGlob(const MString& glob) const{ + //Match strings against globs. + //In a glob string a question sign matches any character + //and an asterisk matches any string. + return Gmatch( glob.headMNode, headMNode ); +} + +bool MString::Gmatch( MNode* g, MNode* s ) const +{ + char t; + + while ( g != NULL ) + { + if ( s == NULL && g->MInfo != '*' ) + { + return false; + } + + t = g->MInfo; + g = g->MLink_Forward; + + switch ( t ) + { + case '*': + if ( g == NULL ) + { + return true; + } + + while ( s != NULL ) + { + if ( Gmatch( g, s ) == true ) + { + return true; + } + s = s->MLink_Forward; + } + return false; + + case '?': + break; + + default: + if ( t != s->MInfo ) + { + return false; + } + break; + } + + s = s->MLink_Forward; + } + + if( s == NULL ) + { + return true; + } + + return false; +} + + +//End Comparison operators -------------------------------- + +//Begin Extraction operators ------------------------------ + +MString MString::Mid(int nFirst) const { //100% + //Idea from CString + + MString tmp; + +// int length = GetLength(); + + if (!headMNode) //checks to see if the head pointer is null + return tmp; + + MNode* travel = TravelList(headMNode, nFirst); + + while (travel) { + + tmp += travel->MInfo; + travel = travel->MLink_Forward; + } + + return tmp; +} + +MString MString::Mid(int nFirst, int nCount) const { //100% + //Idea from CString + + MString tmp; + + if (!headMNode) + return tmp; + + MNode* travel = TravelList(headMNode, nFirst); + while ((travel) && (nCount > 0) ) { + nCount--; + tmp += travel->MInfo; + travel = travel->MLink_Forward; + } + return tmp; +} + +MString MString::Left(int nCount) const { //100% + //Idea from CString + + MString tmp; + + if (!headMNode) + return tmp; + + MNode* travel = headMNode; + while ((travel) && (nCount > 0)) { + nCount--; + tmp += travel->MInfo; + travel = travel->MLink_Forward; + } + return tmp; +} + +MString MString::Right(int nCount) const { //100% + + MString tmp; + + if (!headMNode) + return tmp; + + int bound = 0, + length = GetLength(); + + if (nCount > length) + bound = length; + else + bound = nCount; + + MNode* travel = TravelList(headMNode, (length - bound)); + + for (int i = (length - bound); i < length; i++) { + + tmp += travel->MInfo; + travel = travel->MLink_Forward; + } + return tmp; + +// MString tmp; +// MakeRightChain(headMNode, nCount, tmp.headMNode); + +} + +MString MString::SpanIncluding(char* string) const { + + MString tmpStr; + + if ((!headMNode) || (string_length(string) < 1)) + return tmpStr; + + MNode *tmp = headMNode; + + while (tmp) { + + int strCount = 0; + while (string[strCount] != '\0') { + + if (tmp->MInfo == string[strCount]) + tmpStr += tmp->MInfo; + strCount++; + } + tmp = tmp->MLink_Forward; + + // because MFC exits if first character doesn't + // contain one of the desired characters. + if (tmpStr.IsEmpty()) + return tmpStr; + } + return tmpStr; +} + +MString MString::SpanExcluding(char* string) const { + + MString tmpStr; + + if ((!headMNode) || (string_length(string) < 1)) + return tmpStr; + + bool isIn = false; + MNode *tmp = headMNode; + + while (tmp) { + + int strCount = 0; + while (string[strCount] != '\0') { + + if (tmp->MInfo == string[strCount]) + isIn = true; + strCount++; + } + if (isIn == false) + tmpStr += tmp->MInfo; + isIn = false; + tmp = tmp->MLink_Forward; + } + return tmpStr; +} + +char* MString::ToChar(int nStart,int nCount) { + + int length = GetLength(), + count = 0; + + char* myChar = NULL; + + if ((nStart < 0) || (nStart >= length) || nCount==0) + return myChar; + + if (nCount > 0) + { + //a new char string, +1 is for null + myChar = new char[(MIN(nCount+nStart,length) - nStart) + 1]; + MNode* tmp = TravelList(headMNode, nStart); + + for (int i = 0; i < MIN((length-nStart),nCount); i++) + { + myChar[count++] = tmp->MInfo; + tmp = tmp->MLink_Forward; + } + } + else + { + //a new char string, +1 is for null + myChar = new char[(length - nStart) + 1]; + MNode* tmp = TravelList(headMNode, nStart); + + for (int i = nStart; i < length; i++) + { + myChar[count++] = tmp->MInfo; + tmp = tmp->MLink_Forward; + } + } + + + myChar[count] = '\0'; //add ending null; + return myChar; + +} + +int MString::ToInt(int nStart) { + + MNode* tmp; + if( nStart != 0 ) + { + if ((nStart < 0) || (nStart > GetLength())) + return 0; + + tmp = TravelList(headMNode, nStart); + } + else + { + tmp = headMNode; + } + + MString tmpStr; + int power = 1, + tmpInt = 0, + tmpMul = 1; + + if( (tmp) && (tmp->MInfo == '-') ) + { + tmpMul = -1; + tmp = tmp->MLink_Forward; + } + + while((tmp) && (tmp->MInfo >= '0') && (tmp->MInfo <='9')) { + tmpStr+= tmp->MInfo; + tmp = tmp->MLink_Forward; + } + + tmpStr.MakeReverse(); + + tmp = tmpStr.headMNode; + + while(tmp) { + tmpInt = tmpInt + ((tmp->MInfo - '0') * power); + power = power * 10; + tmp = tmp->MLink_Forward; + } + return tmpInt * tmpMul; +} + +double MString::ToDouble(int nStart) { + + MNode* tmp; + if( nStart != 0 ) + { + if ((nStart < 0) || (nStart > GetLength())) + return 0.0; + + tmp = TravelList(headMNode, nStart); + } + else + { + tmp = headMNode; + } + + MString tmpStr; + + double power; + double tmpMul = 1.0; + double tmpDouble = 0.0; + + if( (tmp) && (tmp->MInfo == '-') ) + { + tmpMul = -1.0; + tmp = tmp->MLink_Forward; + } + + while((tmp) && (tmp->MInfo >= '0') && (tmp->MInfo <='9')) + { + tmpStr+= tmp->MInfo; + tmp = tmp->MLink_Forward; + } + + if( (tmp) && (tmp->MInfo == '.') ) + { + //parse for decimal places + tmp = tmp->MLink_Forward; + + power = 10.0; + + while((tmp) && (tmp->MInfo >= '0') && (tmp->MInfo <='9')) + { + tmpDouble = tmpDouble + ((tmp->MInfo - '0') / power); + tmp = tmp->MLink_Forward; + power = power * 10.0; + } + } + + tmpStr.MakeReverse(); + + tmp = tmpStr.headMNode; + + power = 1.0; + + while(tmp) + { + tmpDouble = tmpDouble + ((tmp->MInfo - '0') * power); + power = power * 10.0; + tmp = tmp->MLink_Forward; + } + + return tmpDouble * tmpMul; +} + +//End Extraction operators -------------------------------- + +//Begin Other Conversions --------------------------------- + +void MString::MakeUpper() { + bModified = true; + + MNode * tmp = headMNode; + while(tmp) { + MakeLetterUpper(tmp->MInfo); + tmp = tmp->MLink_Forward; + } +} + +void MString::MakeLower() { + bModified = true; + + MNode * tmp = headMNode; + while(tmp) { + MakeLetterLower(tmp->MInfo); + tmp = tmp->MLink_Forward; + } +} + +void MString::MakeReverse() { + bModified = true; + + if (!headMNode) + return; + + reverse_driver( headMNode ); + tailMNode = findTail(headMNode); +} + +int MString::Replace(char chOld, char chNew) { + bModified = true; + + if (!headMNode) + return 0; + + int timesReplaced = 0; + MNode* tmp = headMNode; + + while (tmp) { + + if (tmp->MInfo == chOld) { + tmp->MInfo = chNew; + timesReplaced++; + } + + tmp = tmp->MLink_Forward; + + //Thanks to Michael Scheuner for pointing out the missing line (above) + + + } + return timesReplaced; +} + +int MString::Replace(char* stringOld, char* stringNew) { + bModified = true; + //Idea from CString + + int size1 = string_length(stringOld), + size2 = string_length(stringNew), + length = GetLength(), + count = 0, + place = 0; + + if ( (length == 0) || (size1 < 1) || (size2 < 1) ) { + return 0; + } + + while (Find(stringOld, place) >= 0 ) { + place = Find(stringOld, place); + Delete(place, size1); + Insert(place, stringNew); + place+=size2; + count++; + } + + return count; +} + +int MString::Remove(char ch){ + bModified = true; + //Idea from CString + //TO DO: add string remove. + + int count = 0; + while (Find(ch) >= 0) { + Delete(Find(ch)); + count++; + } + + return count; +} + +int MString::Insert(int nIndex, char ch) { + bModified = true; + //Idea from CString + + int length = GetLength(); + + if (nIndex < 0) + return -1; + + if (nIndex >= length) //i don't know if I should pad the string or not + nIndex = length; + + if (0 == nIndex) { + headMNode = tailMNode = new MNode(ch, headMNode); + return 1; + } + + if (nIndex == length) { + tailMNode->MLink_Forward = new MNode(ch); + tailMNode = tailMNode->MLink_Forward; + return (length+1); + } + else + { + GetPointerAt(nIndex - 1)->MLink_Forward = + new MNode(ch, GetPointerAt(nIndex - 1)->MLink_Forward); + } + return (length + 1); +} + +int MString::Insert(int nIndex, char* string) { + bModified = true; + //Idea from CString + + int length = GetLength(); + + if (nIndex < 0) + return -1; + + if (nIndex >= length) + nIndex = length; + + for (int i = 0; string[i] != '\0'; i++) { + Insert(nIndex++, string[i]); + } + + return GetLength(); +} + +int MString::Delete(int nIndex, int nCount) { + bModified = true; + //Idea from CString + + int length = GetLength(); + + if ((!headMNode) || (nIndex < 0) || (nIndex > length) || (nCount < 1)) + return length; + + if (nCount > (length - nIndex)) + nCount = (length - nIndex); + + if (0 == nIndex) { + MNode* first = headMNode; + MNode* last = GetPointerAt((nIndex + nCount)-1); + + if (last->MLink_Forward) { + headMNode = last->MLink_Forward; + last->MLink_Forward = NULL; + deallocate(first); + } + else { + headMNode = 0; + deallocate(first); + } + + } + else { + MNode* toHead = GetPointerAt(nIndex - 1); + MNode* first = GetPointerAt(nIndex); + + MNode* last = GetPointerAt((nCount + nIndex) - 1); + + if (last->MLink_Forward) { + toHead->MLink_Forward = last->MLink_Forward; + last->MLink_Forward = NULL; + deallocate(first); + } + else { + toHead->MLink_Forward = NULL; + deallocate(first); + } + } + tailMNode = findTail(headMNode); + + return GetLength(); +} + +//Additions by Bruce Riggins 11/14/00 +// Use the given data to build a string. +#ifdef WIN32 +#define vsnprintf _vsnprintf +#endif +// +void MString::Format( const char * sFormat, ...) +{ + bModified = true; + + char * s = new char[2000]; + va_list arglist; + va_start(arglist, sFormat); + vsnprintf(s, 2000, sFormat, arglist); + va_end(arglist); + *this = s; + delete s; + s = NULL; +} +// End additions by Bruce Riggins 11/14/00 + +void MString::Trim() { + //Original MString + + if (!headMNode) + return; + + TrimLeft(); + TrimRight(); +} + +void MString::Trim(char ch) { + //Original MString + + if (!headMNode) + return; + + TrimLeft(ch); + TrimRight(ch); +} +void MString::Trim(char* string){ + + if (!headMNode) + return; + + TrimLeft(string); + TrimRight(string); +} + +void MString::TrimLeft() { + //Idea from CString + if (!headMNode) + return; + + TrimLeft(' '); + TrimLeft('\t'); + TrimLeft('\n'); +} + +void MString::TrimLeft(char ch) { + if (!headMNode) + return; + + // not using a "int length" because it will change constantly. + while(Find(ch) == 0) + { + Delete(Find(ch)); + } +} + +void MString::TrimLeft(char* string) { + + if (!headMNode) + return; + + int strLen = string_length(string); + + while(Find(string) == 0) { + Delete(0, strLen); + } +} + +void MString::TrimRight() { + //Idea from CString + if (!headMNode) + return; + + TrimRight(' '); + TrimRight('\t'); + TrimRight('\n'); +} + +void MString::TrimRight(char ch) { + + if (!headMNode) + return; + + // not using a "int length" because it will change constantly. + while ( ReverseFind(ch) == (GetLength() - 1)) + { + Delete(ReverseFind(ch)); + } +} + + +void MString::TrimRight(char* string) { + + if (!headMNode) + return; + + int strLen = string_length(string); + + if (strLen > GetLength()) + return; + + while ( ReverseFind(string) == ( GetLength() - strLen ) ) { + Delete(ReverseFind(string), strLen); + } +} + +//End Other Conversions ----------------------------------- + +//Begin Searching ----------------------------------------- + +int MString::Find(char ch, int nStart) const { + //Idea from CString + + if (!headMNode) + return -1; + + MNode *tmp = TravelList(headMNode, nStart); + + for (int i = nStart; (tmp) ; i++) { + + if (tmp->MInfo == ch) { + return i; + } + tmp = tmp->MLink_Forward; + } + return -1; +} + +int MString::Find(char* string, int nStart) const { + //Idea from CString + + int strLength = string_length(string); + + if ((!headMNode) || (strLength == 0)) + //if bigger than MString or not a string. + return -1; + + bool found = false; + MNode *tmp = TravelList(headMNode, nStart); + + while (tmp) { + + if (tmp->MInfo == string[0]) { + + int strPos = 0; + MNode* subTmp = tmp; + + while ( (subTmp) && (string[strPos] != '\0') ) { + if (subTmp->MInfo == string[strPos++]) + found = true; + else { + found = false; + break; + } + subTmp = subTmp ->MLink_Forward; + } + if( (found == true) && (strPos == strLength) ) + return nStart; + } + tmp = tmp->MLink_Forward; + nStart++; + } + return -1; +} + +int MString::ReverseFind(char ch) const { //Idea from CString + + + if (!headMNode) + return -1; + + int length = GetLength(); + + for (int i = (length - 1); i >= 0; i--) { + + if (GetAt(i) == ch) { + return i; + } + + } + + return -1; +} + +int MString::ReverseFind(char* string) const { + + if (!headMNode) + return -1; + + int length = GetLength(), + strLen = string_length(string); + + bool found = false; + + if (strLen < 1) + return -1; + + for (int i = (length - strLen); i >= 0; i--) { + if (GetAt(i) == string[0]) { + + int strPos = 0; + + for (int k = i; k < (i + strLen); k++) { + if (GetAt(k) == string[strPos++]) + found = true; + else { + found = false; + break; + } + } + if (found == true) + return i; + } + } + return -1; +} + + +int MString::FindOneOf(char* string) const { + //Idea from CString + if (!headMNode) + return -1; + + int strLen = string_length(string); + + for (int i = 0; i < strLen; i++) { + if (Find(string[i]) >= 0) + return i; + } + + return -1; +} + + +//End Searching ------------------------------------------- + +//Begin Buffer Access ------------------------------------- + // Additions by Bruce Riggins 11/7/00 + // Access to string implementation buffer as "C" character array +char * MString::GetBuffer(int nMinBufLength) { + //Idea from CString + + if( bModified == true ) + { + if (pcStr) { + // if buffer is in existence already, simply delete it and start over + delete pcStr; + pcStr = NULL; + } + + // create a buffer and copy list to it + int iLen = GetLength(); + + iLen = iLen < nMinBufLength ? nMinBufLength : // true + iLen; // false + + pcStr = new char[iLen + 1]; // room for trailing zero + if (pcStr) { + char * tmppc = pcStr; + MNode * pn = headMNode; + iBufLen = iLen; + while (pn) { + *tmppc++ = pn->MInfo; + pn = pn->MLink_Forward; + } + *tmppc = '\0'; + } + + bModified = false; + } + + return pcStr; +} + +void MString::ReleaseBuffer(int nNewLength) { + + // empty the current MString to prepare + // for getting the new string + MNode* tmp = headMNode; + MNode* tmp2; + while (tmp) { + tmp2 = tmp; + tmp = tmp->MLink_Forward; + delete tmp2; + tmp2 = NULL; + } + // done emptying MString + + headMNode = new MNode( pcStr[0] ); + tmp = headMNode; + int i = 1; + char ch; + + if( nNewLength == -1 ) // if no length entered go through string until NULL + { + ch = pcStr[i]; + while( ch != '\0' && i < iBufLen ) + { + tmp->MLink_Forward = new MNode(ch); + tmp=tmp->MLink_Forward; + + ++i; + ch = pcStr[i]; + } + } + else + { + bModified = true; + + // Don't let the new length be longer than the + // current length. Shorter is okay. + if( nNewLength > iBufLen ) { + nNewLength = iBufLen; } + + while( i < nNewLength ) + { + ch = pcStr[i]; + tmp->MLink_Forward = new MNode(ch); + tmp=tmp->MLink_Forward; + ++i; + } + } + + tailMNode = tmp; +} + +// LPTSTR GetBufferSetLength(int nNewLength); //Idea from CString +// void FreeExtra(); //Idea from CString + +// Use LockBuffer/UnlockBuffer to turn refcounting off +char * MString::LockBuffer() { + //Idea from CString + + // Simple, non-functional implementation + return pcStr; +} + +void MString::UnlockBuffer() { + //Idea from CString + + // Simple, non-functional implementation + return; +} + + // End of BR additions + +//End Buffer Access --------------------------------------- + diff --git a/src/MString.h b/src/MString.h new file mode 100644 index 0000000..cbb38e0 --- /dev/null +++ b/src/MString.h @@ -0,0 +1,380 @@ +/* MString - Dynamic string data type library + Copyright (C) 2001-2005 Jesse L. Lovelace + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef MSTRING_H +#define MSTRING_H + +#ifdef __cplusplus // we only want this for C++ code + +/* MString by Jesse Lovelace (mentat) + jesse at aslogicsys dot com + + (MString began as GString but was changed to remain compatible with + gtk+'s GString data type.) + + http://mstring.sourceforge.net + + MString is a string library that uses dynamically sizable character + strings. To do this I used linked lists instead of dynamic arrays for + various reasons (one being the problems that arrays of dynamic arrays + cause). + + MString is designed to maintain compatibility with the MFC CString + library. MString should be 99% compatible if you exclude the windoze + specific operations (including buffer access) and the .Format commands. + + For the full documentation see functions.txt + + MString also includes the MStringArray class. MStringArray follows the + same scheme as CStringArray from MFC. CStringArrays are also linked + lists for now (I may change them to dynamically allocated arrays in the + future). + + Please submit any suggestions/bugs/comments to jllovela@eos.ncsu.edu + + Enjoy. + + Thanks to: + Brian Matherly - Project manager and developer. + Balint Toth - Fixed insert bug and new features, + Bruce Riggins - New char * code, + Dingo - pointer debugging, + Rask - math and Trim(char ch), + Botch - debugging and advice, + Antiloop - for phat grooves. + + (Last modified April 10, 2005) +*/ + +const int MAX_PRECISION = 9; //due to bad double to string code. +const char MString_VERSION[8] = "0.70"; +//typedef const char * LPCSTR; + +//#include + +class MNode; + +struct MStringData { + char * pcStr; + int precision; + int iBufLen; // length of buffer minus 1 for null terminator + int iBufferInUse; +}; + +class MString { + +//Begin overloaded stream functions ----------------------- + +// friend std::ostream& operator<< (std::ostream& out, const MString& string); + // PRE: out is a valid output stream, string is a valid MString + // POST: contents of string are sent to stream out. + +// friend std::istream& operator>> (std::istream& in, MString& string); + // PRE: in is a valid input stream, string is a valid MString + // POST: characters in input stream are stored in string. + +// friend std::istream& getline(std::istream& in, MString& string); + // PRE: in is valid input stream, sting is a valid MString + // POST: characters up to (and including) the newline are stored + // in string. + // EX: getline(in, string); + +//End overloaded stream functions ------------------------- + +public: + +//Begin Constructors -------------------------------------- + + MString(); + // Info: construct empty MString + + MString(const MString& stringSrc); + // Info: copy constructor + // PRE: stringSrc is a valid MString object. + // POST: new object is a deep copy of stringSrc. + + MString(const char ch, int nRepeat = 1); + // Info: construct with single character repeated nRepeat times + // PRE: ch is a valid ascii character and non null. + // POST: new object contains ch repeated nRepeat times. + + MString(const char* string); + // PRE: string is a valid null-terminated string. + // POST: new object contains the data from string minues null. + +// Added by Bruce Riggins + MString(const char * string, int nLength); + // Info: copy with maximum length + // PRE: string is a valid null-terminated string, nLength>0 + // POST: new object contains the data from string minues null +// End addition + + MString(const int num); + // NEW CODE, PLEASE HELP DEBUG (v. 60) + MString(double num); + + ~MString(); + // Info: destructor + +//End Constructors ---------------------------------------- + +//Begin Test Functions ------------------------------------ + + void testG(); + // Info: uses cout to display the data and pointer of each + // Node. + + MString GetGVersion(); + // Info: returns the current version of MString. + // POST: returns an object of type MString containing version info + + MString ReturnLicense(); + // Info: returns license info + // POST: returns an object of type MString containing license info + + +//End Test Functions -------------------------------------- + +//Begin Precision Functions ------------------------------- + + void SetPrecision(int num); + // PRE: num <= MAX_PRECISION + // POST: double conversion precision changed to num. + + int GetPrecision() const; + // POST: returns an int type equal to the current double precision. + +//End Precision Functions --------------------------------- + +//Begin String as Array Functions ------------------------- + + int GetLength() const; + // Info: returns the length of the string excluding null + + bool IsEmpty() const; + // Info: nonzero if string has 0 length + + void Empty(); + // Info: empty's the string and free's memory + + char GetAt(int nIndex) const; + // Info: returns char at index + + char operator [](int nIndex) const; + // Info: operator overload of GetAt(int nIndex) + + char& operator [](int nIndex); + // Info: use like SetAt, myString[0] = 'M'; + + void SetAt(int nIndex, char ch); + // Info: sets the character at nIndex + +//End String as Array Functions --------------------------- + +//Begin added operators by Bruce Riggins --------------- + operator const char * () const; +//End added operators by Bruce Riggins ----------------- + +//Begin Assignment/Concatination operators ---------------- + + const MString& operator =(const MString& stringSrc); //Idea from CString + const MString& operator =(char ch); + const MString& operator =(const char* string); + const MString& operator =(int num); //Original MString + const MString& operator =(double num); //Original MString + const MString& operator =(float num); //Original MString + + const MString& operator +=(const MString& string); //Idea from CString + const MString& operator +=(char ch); + const MString& operator +=(char* string); + const MString& operator +=(int num); //Original MString + const MString& operator +=(double num); //Original MString + const MString& operator +=(float num); //Original MString + + void Cat(char ch); //Not implimented yet. + void Cat(char* string); + void Cat(MString& string); + + + + friend MString operator +(const MString& string1, const MString& string2); + friend MString operator +(const MString& string, char ch); + friend MString operator +(char ch, const MString& string); + friend MString operator +(const MString& string1, char* string2); + friend MString operator +(char* string1, const MString& string2); + friend MString operator +(int num, const MString& string); + friend MString operator +(const MString& string, int num); + + +//End Assignment/Concatination operators ------------------ + +//Begin Comparison operators ------------------------------ + + friend bool operator==(const MString& s1, const MString& s2); //Idea from CString + friend bool operator==(const MString& s1, const char* s2); + friend bool operator==(const char* s1, const MString& s2); + + friend bool operator!=(const MString& s1, const MString& s2); //Idea from CString + friend bool operator!=(const MString& s1, char* s2); + friend bool operator!=(char* s1, const MString& s2); + friend bool operator!=(const MString& s1, const char* s2); + + friend bool operator <(const MString& s1, const MString& s2); //Idea from CString + friend bool operator <(const MString& s1, char* s2); + friend bool operator <(char* s1, const MString& s2); + + friend bool operator >(const MString& s1, const MString& s2); //Idea from CString + friend bool operator >(const MString& s1, char* s2); + friend bool operator >(char* s1, const MString& s2); + + friend bool operator <=(const MString& s1, const MString& s2); //Idea from CString + friend bool operator <=(const MString& s1, char* s2); + friend bool operator <=(char* s1, const MString& s2); + + friend bool operator >=(const MString& s1, const MString& s2); //Idea from CString + friend bool operator >=(const MString& s1, char* s2); + friend bool operator >=(char* s1, const MString& s2); + + int Compare(const char* string) const; //Idea from CString + int Compare(const MString& string) const; //MString original + int CompareNoCase(const char* string) const; //Idea from CString + int Collate(char* string) const; //Idea from CString + int CollateNoCase(char* string) const; //Idea from CString + + bool CompareGlob(const MString& glob) const; + +//End Comparison operators -------------------------------- + +//Begin Extraction operators ------------------------------ + + MString Mid(int nFirst) const; //Idea from CString + MString Mid(int nFirst, int nCount) const; //Idea from CString + MString Left(int nCount) const; //Idea from CString + MString Right(int nCount) const; //Idea from CString + MString SpanIncluding(char* string) const; //Idea from CString + MString SpanExcluding(char* string) const; //Idea from CString + char* ToChar(int nStart = 0,int nCount = -1); + // PRE: nStart is >0 and < GetLength(). + // POST: returns a pointer to a new null-terminated character array + // that is a copy of the infomation in the MString. + + int ToInt(int nStart = 0); + // PRE: nStart is > 0 and < GetLength(). + // POST: returns an integer created from the numbers starting at nStart + // Other: ToInt does not check to see if the string of numbers contained + // in the MString object is to long for type int. ToInt converts + // a sequence of ASCII values 48 thru 57 ('0' to '9') non-number + // values result in a return from the function. + // EX: if myString is of type MString containing "12345C1232" + // myString.ToInt(0) returns 12345 + // myString.ToInt(1) returns 2345 + + double ToDouble( int nStart = 0 ); + +//End Extraction operators -------------------------------- + +//Begin Other Conversions --------------------------------- + + void MakeUpper(); //Idea from CString + void MakeLower(); //Idea from CString + void MakeReverse(); //Idea from CString + + int Replace(char chOld, char chNew); //Idea from CString + int Replace(char* stringOld, char* stringNew); //Idea from CString + int Remove(char ch); //Idea from CString + int Insert(int nIndex, char ch); //Idea from CString + int Insert(int nIndex, char* string); //Idea from CString + int Delete(int nIndex, int nCount = 1); //Idea from CString + + //Research Format +// Additions by Bruce Riggins 11/14/00 + void Format(const char * sFormat, ...); +// End additions by Bruce Riggins 11/14/00 + + void Trim(); //Original MString + void Trim(char ch); //Original MString + void Trim(char* string); + + void TrimLeft(); //Idea from CString + void TrimLeft(char ch); + void TrimLeft(char* string); + + + void TrimRight(); //Idea from CString + void TrimRight(char ch); + void TrimRight(char* string); + +//End Other Conversions ----------------------------------- + + //Research FormatMessage + +//Begin Searching ----------------------------------------- + + int Find(char ch, int nStart = 0) const; //Idea from CString + int Find(char* string, int nStart = 0) const; //Idea from CString + + + int ReverseFind(char ch) const; //Idea from CString + int ReverseFind(char* string) const; //MString original + int FindOneOf(char* string) const; //Idea from CStrin + + +//End Searching ------------------------------------------- + + //Buffer Access and Windows-Specific items not included. + +//Begin Buffer Access ------------------------------------- + // Additions by Bruce Riggins 11/7/00 + // Access to string implementation buffer as "C" character array + char * GetBuffer(int nMinBufLength = -1); //Idea from CString + void ReleaseBuffer(int nNewLength = -1); //Idea from CString +// char * GetBufferSetLength(int nNewLength); //Idea from CString +// void FreeExtra(); //Idea from CString + + // Use LockBuffer/UnlockBuffer to turn refcounting off + char * LockBuffer(); //Idea from CString + void UnlockBuffer(); //Idea from CString + + // End of BR additions + +//End Buffer Access --------------------------------------- + +private: + + MNode* GetPointerAt(int nIndex); + void deallocate(MNode *p); // added by Bruce Riggins + + bool Gmatch( MNode* g, MNode* s ) const; + + char * pcStr; + MNode *headMNode; + MNode *tailMNode; //New for .3b + + int precision; + int iBufLen; // length of buffer minus 1 for null terminator + int iBufferInUse; + + // flag to indicate that the MString has been modified since the + // last time char* GetBuffer() was called + bool bModified; + +}; + +#endif // __cplusplus + +#endif diff --git a/src/MStringArray.cpp b/src/MStringArray.cpp new file mode 100644 index 0000000..63f73f5 --- /dev/null +++ b/src/MStringArray.cpp @@ -0,0 +1,481 @@ +/* MStringArray - Dynamic Array of MString objects + Copyright (C) 2001-2005 Jesse L. Lovelace (jesse at aslogicsys dot com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +//#include +//#include +#include "MStringArray.h" +#include "MString.h" + + +#ifndef NULL +#define NULL 0 +#endif +//using namespace std; + +class MArrayNode { +public: + MArrayNode(MString string, MArrayNode* link = 0) {MLink_Forward = link; MInfo = string;} + MArrayNode *MLink_Forward; + MString MInfo; +}; + +static void deallocate(MArrayNode* p) +{ + MArrayNode* tmp; + while (p) { + tmp = p; + p = p->MLink_Forward; + delete tmp; + } +} + +static MArrayNode* findTail(MArrayNode * startPointer) { + MArrayNode * tmp=startPointer; + while (tmp) { + if (!tmp->MLink_Forward) + return tmp; + tmp = tmp->MLink_Forward; + } + return startPointer; +} + +static MArrayNode* copy(MArrayNode* p, MArrayNode*& tailNode) +{ + MArrayNode* head = 0; + MArrayNode* tail = 0; + + + while(p) { + if (!head) + head = tail = new MArrayNode(p->MInfo); + else { + tail->MLink_Forward = new MArrayNode(p->MInfo); + tail = tail->MLink_Forward; + } + p = p->MLink_Forward; + } + tailNode = tail; + return head; +} + +MArrayNode* MStringArray::GetPointerAt(int nIndex) { + + MArrayNode* tmp = headMNode; + + for (int i = 0; (i < nIndex); i++) { + + if (0 == tmp) + return 0; + + tmp = tmp->MLink_Forward; + } + return tmp; +} + + +MStringArray::~MStringArray() { + deallocate(headMNode); + headMNode = tailMNode = NULL; +} + +MStringArray::MStringArray() { + + headMNode = tailMNode = NULL; +} + +MStringArray::MStringArray(const MStringArray& arraySrc) { + + headMNode = copy(arraySrc.headMNode, tailMNode); +} + +MStringArray::MStringArray(const MString& stringSrc) { + + headMNode = tailMNode = new MArrayNode(stringSrc); +} + +const MStringArray& MStringArray::operator = (const MStringArray& arraySrc) { + + if (this != &arraySrc) { + deallocate(headMNode); + headMNode = tailMNode = NULL; + headMNode = copy(arraySrc.headMNode, tailMNode); + } + return *this; +} + + +int MStringArray::GetSize() const { + + int count = 0; + + if (headMNode==NULL) + return count; + + MArrayNode *tmp = headMNode; + + while(tmp) { + count++; + tmp = tmp->MLink_Forward; + } + return count; + +} + +int MStringArray::GetUpperBound() const { + + return (GetSize() - 1); +} + +void MStringArray::SetSize(int nNewSize, int nGrowBy) { + + if (nNewSize < 0) + return; + //UNFINISHED FUNCTION + //nGrowBy unreferenced formal param + +} + + +void MStringArray::FreeExtra() { + + //UNFINISHED FUNCTION + +} + +void MStringArray::RemoveAll() { + + deallocate(headMNode); + headMNode = tailMNode = NULL; + +} + +void MStringArray::test() { + + MArrayNode *tmp = headMNode; + + int count = 0; +// cout << "Head = " << headMNode << endl; + while (tmp) + { +// cout << "Index(" << count++ << ") " << tmp->MInfo << " " << tmp->MLink_Forward << endl; + tmp = tmp->MLink_Forward; + } +// cout << "Tail = " << tailMNode << endl; +// cout << "GetSize = " << GetSize() << endl; +} + + + +MString MStringArray::GetAt(int nIndex) const { + + MString tmpStr; + if ((nIndex < 0) || (nIndex > GetUpperBound())) + return tmpStr; //return's null MString if the nIndex is to big or small. + + MArrayNode* tmp = headMNode; + + for (int i = 0; i < nIndex; i++) + tmp=tmp->MLink_Forward; + + return tmp->MInfo; +} + +void MStringArray::SetAt(int nIndex, const MString &newElement) { + + if ((nIndex < 0) || (nIndex > GetUpperBound())) + return; //return's null MString if the nIndex is to big or small. + + MArrayNode* tmp = headMNode; + + for (int i = 0; i < nIndex; i++) + tmp=tmp->MLink_Forward; + + tmp->MInfo = newElement; +} + +void MStringArray::SetAt(int nIndex, char newString[]) { + + if ((nIndex < 0) || (nIndex > GetUpperBound())) + return; //return's null MString if the nIndex is to big or small. + + MArrayNode* tmp = headMNode; + + for (int i = 0; i < nIndex; i++) + tmp=tmp->MLink_Forward; + + tmp->MInfo = newString; +} + + +MString& MStringArray::ElementAt(int nIndex) { + + MString* tmpStr = NULL; + if ((nIndex < 0) || (nIndex > GetUpperBound())) + return *tmpStr; //return's null MString if the nIndex is to big or small. + + MArrayNode* tmp = headMNode; + + for (int i = 0; i < nIndex; i++) + tmp=tmp->MLink_Forward; + + return tmp->MInfo; +} + +// const MString* MStringArray::GetData() const; +// MString* MStringArray::GetData(); + + +void MStringArray::SetAtGrow(int nIndex, const MString &newElement) { + + //Not written yet +} + +void MStringArray::SetAtGrow(int nIndex, char newString[]) { + //Not written yet + +} + +int MStringArray::Add(const MString &newElement) { + + InsertAt(GetSize(), newElement); + + return GetUpperBound(); +} + +int MStringArray::Add(char newString[]) { //works + + InsertAt(GetSize(), newString); + + return GetUpperBound(); +} + + +int MStringArray::Append(const MStringArray &src) { //works + + InsertAt(GetSize(), src); + + return GetSize(); +} + +void MStringArray::Copy(const MStringArray &src) { + + headMNode = copy(src.headMNode, tailMNode); + +} +void MStringArray::InsertAt(int nIndex, const MString &newElement, int nCount) { //works + //MFC Uses pointer to MString, + + int length = GetSize(); + + if ((nCount == 0) || (nIndex < 0)) + return; + + if (length == 0) { //if size is zero + headMNode = tailMNode = new MArrayNode(newElement); + return; + } + + + if (nIndex == length) {//if just adding to end, use tailMNode + for (int a = 0; a < nCount; a++) { + tailMNode->MLink_Forward = new MArrayNode(newElement); + tailMNode = tailMNode->MLink_Forward; + } + return; + } + + if (nIndex == 0) { + headMNode = new MArrayNode(newElement, headMNode); + MArrayNode* tmp = headMNode; + + for (int i = 1; i < nCount; i++) { + tmp->MLink_Forward = new MArrayNode(newElement, tmp->MLink_Forward); + tmp = tmp->MLink_Forward; + } + return; + + } + + + if (nIndex > (length - 1)) {//if space between new element and old ones, + // pad with null MStrings + + for (int adds = nIndex; nIndex > GetSize(); adds++) { + MString tmpStr; + Add(tmpStr); + } + + for (int other = 0; other < nCount; other++) { + Add(newElement); + } + return; + } + + // if inserting in the middle somewhere + MArrayNode * tmp = headMNode; + for (int k = 0; k < (nIndex - 1); k++) { //go to index you want to insert infront of. + tmp = tmp->MLink_Forward; + } + for (int w = 0; w < nCount; w++) { + tmp->MLink_Forward = new MArrayNode(newElement, tmp->MLink_Forward); + tmp = tmp->MLink_Forward; + } + return; + +} + + +void MStringArray::InsertAt(int nStartIndex, MStringArray pNewArray){ //works + + int size = pNewArray.GetSize(); + + for (int i = 0; i < size; i++) + InsertAt(nStartIndex++, pNewArray.GetAt(i)); //sloppy jesse, don't use GetAt +} + + +void MStringArray::InsertAt(int nIndex, char newString[], int nCount) { + + + MString tmp(newString); + InsertAt(nIndex, tmp, nCount); + + return; + +} + +void MStringArray::RemoveAt(int nIndex, int nCount) { + + int length = GetSize(); + + if ((length < 1) || (nIndex > length) || (nCount < 1)) + return; + + if (nCount > (length - nIndex)) + nCount = (length - nIndex); + + if (0 == nIndex) { + MArrayNode* first = headMNode; + MArrayNode* last = GetPointerAt((nIndex + nCount)-1); + + if (last->MLink_Forward) { + headMNode = last->MLink_Forward; + last->MLink_Forward = NULL; + deallocate(first); + } + else { + headMNode = NULL; + deallocate(first); + } + + } + else { + MArrayNode* toHead = GetPointerAt(nIndex - 1); + MArrayNode* first = GetPointerAt(nIndex); + + MArrayNode* last = GetPointerAt((nCount + nIndex) - 1); + + if (last->MLink_Forward) { + if (last->MLink_Forward->MLink_Forward) { + toHead->MLink_Forward = last->MLink_Forward; + last->MLink_Forward = NULL; + deallocate(first); + } + else { + toHead->MLink_Forward=last->MLink_Forward; + last->MLink_Forward = NULL; + deallocate(first); + } + } + else { + toHead->MLink_Forward = NULL; + deallocate(first); + } + } + tailMNode = findTail(headMNode); + +} + +MString& MStringArray::operator[](int nIndex) { + + MString* tmpStr = NULL; + if ((nIndex < 0) || (nIndex > GetUpperBound())) + return *tmpStr; //return's null MString if the nIndex is to big or small. + + MArrayNode* tmp = headMNode; + + for (int i = 0; i < nIndex; i++) + tmp=tmp->MLink_Forward; + + return tmp->MInfo; +} + +MString MStringArray::operator[](int nIndex) const { + + MString tmpStr; + if ((nIndex < 0) || (nIndex > GetUpperBound())) + return tmpStr; //return's null MString if the nIndex is to big or small. + + MArrayNode* tmp = headMNode; + + for (int i = 0; i < nIndex; i++) + tmp=tmp->MLink_Forward; + + return tmp->MInfo; +} + + //New functions: + +void MStringArray::Split(MString stringToSplit, char ch, int nStartIndex, int insertAt){ + + MStringArray tmpArray; + + MString tmpString; + + int place = nStartIndex, + nextFind = stringToSplit.Find(ch, place); + + while (nextFind >= 0) { + + tmpString = stringToSplit.Mid(place, nextFind - place); + + tmpString.Trim(ch); + +// cout << tmpString << endl; +// cout << "place = " << place << endl; + + tmpArray.Add(tmpString); + + tmpString.Empty(); + + place = nextFind + 1; + nextFind = stringToSplit.Find(ch, place); + +// cout << "place = " << place << endl; + } + tmpString = stringToSplit.Right(stringToSplit.GetLength() - place); + //get the last word and add + // it + tmpString.Trim(ch); + if (!tmpString.IsEmpty()) { + tmpArray.Add(tmpString); + tmpString.Empty(); + } + + InsertAt(insertAt, tmpArray); +} diff --git a/src/MStringArray.h b/src/MStringArray.h new file mode 100644 index 0000000..186d8b1 --- /dev/null +++ b/src/MStringArray.h @@ -0,0 +1,83 @@ +/* MStringArray - Dynamic Array of MString objects + Copyright (C) 2001-2005 Jesse L. Lovelace + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef MSTRINGARRAY_H +#define MSTRINGARRAY_H + +#include "MString.h" + +const char MStringArray_VERSION[8] = "BETA 1"; + +class MArrayNode; + + +class MStringArray { +public: + MStringArray(); + MStringArray(const MStringArray& arraySrc); + MStringArray(const MString& stringSrc); + ~MStringArray(); + + const MStringArray& operator =(const MStringArray& arraySrc); + int GetSize() const; + int GetUpperBound() const; + void SetSize(int nNewSize, int nGrowBy = -1); + + void FreeExtra(); + void RemoveAll(); + MString GetAt(int nIndex) const; + void SetAt(int nIndex, const MString &newElement); + void SetAt(int nIndex, char newString[]); + MString& ElementAt(int nIndex); + +// const MString* GetData() const; +// MString* GetData(); + + + void SetAtGrow(int nIndex, const MString &newElement); + void SetAtGrow(int nIndex, char newString[]); + int Add(const MString &newElement); + int Add(char newString[]); + MString Pop(); + int Append(const MStringArray &src); + void Copy(const MStringArray &src); + + void InsertAt(int nIndex, const MString &newElement, int nCount = 1); + void InsertAt(int nStartIndex, MStringArray pNewArray); + void InsertAt(int nIndex, char newString[], int nCount = 1); + + void RemoveAt(int nIndex, int nCount = 1); + + MString& operator[](int nIndex); + MString operator[](int nIndex) const; + + //New functions: + + void Split(MString stringToSplit, char ch = ' ', int nStartIndex = 0, int insertAt = 0); + + void test(); + +private: + MArrayNode* GetPointerAt(int nIndex); + + MArrayNode *headMNode; + MArrayNode *tailMNode; + +}; + +#endif diff --git a/src/VirtualT.h b/src/VirtualT.h index 4d769a4..bc067d6 100644 --- a/src/VirtualT.h +++ b/src/VirtualT.h @@ -31,7 +31,7 @@ #ifndef _VIRTUALT_H_ #define _VIRTUALT_H_ -#define VERSION "0.7" +#define VERSION "0.9" enum { MODEL_M100 @@ -41,5 +41,9 @@ enum { ,MODEL_PC8300 }; +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif #endif diff --git a/src/a85parse.cpp b/src/a85parse.cpp new file mode 100644 index 0000000..b07a8eb --- /dev/null +++ b/src/a85parse.cpp @@ -0,0 +1,6751 @@ +// 8085 Assembler Parser Syntax + +// Written by Kenneth D. Pettit +// This is an input syntax grammer for the Anagram LARL Parser Generator + + +/* + + AnaGram Parsing Engine + Copyright (c) 1993-2000, Parsifal Software. + All Rights Reserved. + + Serial number 2P18859U + Registered to: + Kenneth D. Pettit + Conexant Systems, Inc. + +*/ + +#ifndef A85PARSE_H_1147178743 +#include "a85parse.h" +#endif + +#ifndef A85PARSE_H_1147178743 +#error Mismatched header file +#endif + +#include +#include +#include +#include + +#define RULE_CONTEXT (&((PCB).cs[(PCB).ssx])) +#define ERROR_CONTEXT ((PCB).cs[(PCB).error_frame_ssx]) +#define CONTEXT ((PCB).cs[(PCB).ssx]) + + + +a85parse_pcb_type a85parse_pcb; +#define PCB a85parse_pcb + +/* Line 483, C:/Projects/VirtualT/src/asm/a85parse.syn */ + // Embedded C + +#include "MString.h" // Include MString header +#include "MStringArray.h" // Include MStringArray header +#include "assemble.h" // Include VTAssembler header + +#ifndef BOOL +typedef int BOOL; +#endif + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +VTAssembler* gAsm = 0; // Pointer to the assembler +CRpnEquation* gEq = 0; // Pointer to active equation +VTObArray* gExpList = 0; // Pointer to active expression list +MStringArray* gNameList = 0; // Pointer to active name list +CCondition* gCond = 0; // Pointer to active condition +char ss[32][256]; // String Stack; +char integer[64]; // Integer storage space +char int_len = 0; // Integer string length +int ss_idx = 0; // String Stack Index +int ss_len = 0; // SS string length +double gDivisor = 1.0; // Current divisor for float converwions +int gTabSize = 4; +char reg[10]; // Register arguments +int reg_cnt = 0; // Register Arg count +int label = 0; // Number of labels on string stack +int name_list_cnt = 0; // Number of strings in name list +int ex_cnt = 0; // Number of expressions in expression list + +void a85parse(void); + +// This function checks the string accumulator for errors +// parsing the file. If there are no errors, check the string +// accumulator to insure it is empty. If anything is left in the +// accumulator, then there is an error with our parser. +void check_string_stack(void) +{ + // If we have no errors... + if (gAsm->m_Errors.GetSize() == 0) + { + // Check string accumulator size + int stringCount; + if ((stringCount = ss_idx) != 0) + { + MString string; + string.Format("Internal Design Parse Error - %d string(s) left on stack!", + stringCount); + gAsm->m_Errors.Add(string); + } + } +} + +// ParseDesignFile is the entry point for parsing design files. The full path of +// the design file should be passed as the only parameter. If the design file is +// parsed successfully, the routine will return TRUE, otherwise it will return +// FALSE. +BOOL ParseASMFile(const char* filename, VTAssembler* pAsm) +{ + if (pAsm == NULL) + return FALSE; + + gAsm = pAsm; + + // Clear old design from the CDesign object + gAsm->ResetContent(); + + // Insure no active equation left over from a previous run + if (gEq != 0) + delete gEq; + if (gExpList != 0) + delete gExpList; + if (gNameList != 0) + delete gNameList; + if (gCond != 0) + delete gCond; + + // Allocate an active equation to be used during parsing + gEq = new CRpnEquation; + gExpList = new VTObArray; + gNameList = new MStringArray; + gCond = new CCondition; + gAsm->m_FileIndex = gAsm->m_Filenames.Add(filename); + + // Try to open the file + if ((gAsm->m_fd = fopen(gAsm->m_Filenames[gAsm->m_FileIndex], "r")) == 0) + return FALSE; + + // Reset the string stack + ss_idx = 0; + ss_len = 0; + int_len = 0; + + // Reset the Register, name, expression, and label counters + reg_cnt = label = ex_cnt = name_list_cnt = 0; + + // Parse the file. + a85parse(); + + fclose(gAsm->m_fd); + + // Check for parser errors + check_string_stack(); + + // Check if errors occured + int count = gAsm->m_Errors.GetSize(); + if (count != 0) + return FALSE; + + // No errors! + return TRUE; +} + +// Define macros to handle input and errors + +#define TAB_SPACING gTabSize + +#define GET_INPUT ((PCB).input_code = gAsm->m_fd != 0 ? \ + fgetc(gAsm->m_fd) : 0) + +#define SYNTAX_ERROR {MString string; string.Format("%s, line %d, column %d", \ + (PCB).error_message, (PCB).line, (PCB).column); gAsm->m_Errors.Add(string); } + +#define PARSER_STACK_OVERFLOW {MString string; string.Format(\ + "\nParser stack overflow, line %d, column %d",\ + (PCB).line, (PCB).column); gAsm->m_Errors.Add(string);} + +#define REDUCTION_TOKEN_ERROR {MString string; string.Format(\ + "\nReduction token error, line %d, column %d", \ + (PCB).line, (PCB).column); gAsm->m_Errors.Add(string);} + +int do_hex(int h, int n) +{ + int temp1, temp2; + + temp2 = h * 16; + temp1 = (n <='9' ? n-'0' : (n | 0x60) - 'a' + 10); + temp1 += temp2; + return temp1; +} + +void expression_list_literal() +{ + CExpression *pExp = new CExpression; + + pExp->m_Literal = ss[ss_idx--]; + gExpList->Add(pExp); +} + +void expression_list_equation() +{ + CExpression *pExp = new CExpression; + + pExp->m_Equation = gEq; + gEq = new CRpnEquation; + + gExpList->Add(pExp); +} + +void condition(int condition) +{ + if (condition == -1) + { + // Get Right hand side equation + gCond->m_EqRight = gEq; + } + else + { + // Save conditional + gCond->m_Condition = condition; + gCond->m_EqLeft = gEq; + } + + // Assign new equation for parser + gEq = new CRpnEquation; +} + +int conv_to_hex() +{ + int temp1; + + sscanf(integer, "%x", &temp1); + + return temp1; +} + +int conv_to_dec() +{ + int temp1; + + sscanf(integer, "%d", &temp1); + + return temp1; +} + +int conv_to_oct() +{ + int temp1; + + sscanf(integer, "%o", &temp1); + + return temp1; +} + +int conv_to_bin() +{ + int temp1, x; + + temp1 = 0; + x = 0; + + while (integer[x] != 0) + temp1 = (temp1 << 1) + integer[x++] - '0'; + + return temp1; +} + + +#ifndef CONVERT_CASE + +static const char agCaseTable[31] = { + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 +}; + +static int agConvertCase(int c) { + if (c >= 'a' && c <= 'z') return c ^= 0x20; + if (c >= 0xe0 && c < 0xff) c ^= agCaseTable[c-0xe0]; + return c; +} + +#define CONVERT_CASE(c) agConvertCase(c) + +#endif + + +#ifndef TAB_SPACING +#define TAB_SPACING 8 +#endif + +#define ag_rp_1() (gAsm->include(ss[ss_idx--])) + +#define ag_rp_6() (gAsm->pragma_list()) + +#define ag_rp_7() (gAsm->pragma_hex()) + +#define ag_rp_8() (gAsm->preproc_ifdef(ss[ss_idx--])) + +#define ag_rp_9() (gAsm->preproc_ifndef(ss[ss_idx--])) + +#define ag_rp_10() (gAsm->preproc_else()) + +#define ag_rp_11() (gAsm->preproc_endif()) + +#define ag_rp_12() (gAsm->preproc_define(ss[ss_idx--])) + +#define ag_rp_13() (gAsm->preproc_undef(ss[ss_idx--])) + +#define ag_rp_14() (gAsm->equate(ss[ss_idx--])) + +#define ag_rp_15() (gAsm->directive_set(ss[ss_idx--])) + +#define ag_rp_16() (gAsm->equate((const char *) -1)) + +#define ag_rp_17() (gAsm->directive_set((const char *) -1)) + +#define ag_rp_18() (gAsm->directive_org()) + +#define ag_rp_19() (gAsm->directive_aseg()) + +#define ag_rp_20() (gAsm->directive_cseg(0)) + +#define ag_rp_21() (gAsm->directive_dseg(0)) + +static void ag_rp_22(void) { +/* Line 100, C:/Projects/VirtualT/src/asm/a85parse.syn */ + gAsm->label(ss[ss_idx--]); gAsm->directive_ds(); +} + +#define ag_rp_23() (gAsm->directive_ds()) + +static void ag_rp_24(void) { +/* Line 102, C:/Projects/VirtualT/src/asm/a85parse.syn */ + gAsm->label(ss[ss_idx--]); gAsm->directive_db(); +} + +#define ag_rp_25() (gAsm->directive_db()) + +static void ag_rp_26(void) { +/* Line 104, C:/Projects/VirtualT/src/asm/a85parse.syn */ + gAsm->label(ss[ss_idx--]); gAsm->directive_dw(); +} + +#define ag_rp_27() (gAsm->directive_dw()) + +#define ag_rp_28() (gAsm->directive_extern()) + +#define ag_rp_29() (gAsm->directive_extern()) + +#define ag_rp_30() (gAsm->directive_public()) + +#define ag_rp_31() (gAsm->directive_name(ss[ss_idx--])) + +#define ag_rp_32() (gAsm->directive_stkln()) + +#define ag_rp_33() (gAsm->directive_end("")) + +#define ag_rp_34() (gAsm->directive_end(ss[ss_idx--])) + +#define ag_rp_35() (gAsm->directive_if()) + +#define ag_rp_36() (gAsm->directive_else()) + +#define ag_rp_37() (gAsm->directive_endif()) + +#define ag_rp_38() (gAsm->directive_title(ss[ss_idx--])) + +#define ag_rp_39() (gAsm->directive_title(ss[ss_idx--])) + +#define ag_rp_40(n) (gAsm->directive_page(n)) + +#define ag_rp_41() (gAsm->directive_page(-1)) + +#define ag_rp_42() (gAsm->directive_sym()) + +#define ag_rp_43() (gAsm->directive_link(ss[ss_idx--])) + +#define ag_rp_44() (gAsm->directive_maclib(ss[ss_idx--])) + +#define ag_rp_45() (expression_list_literal()) + +#define ag_rp_46() (expression_list_equation()) + +#define ag_rp_47() (expression_list_equation()) + +#define ag_rp_48() (expression_list_literal()) + +#define ag_rp_49() (expression_list_literal()) + +#define ag_rp_50() (gNameList->Add(ss[ss_idx--])) + +#define ag_rp_51() (gNameList->Add(ss[ss_idx--])) + +static void ag_rp_52(void) { +/* Line 147, C:/Projects/VirtualT/src/asm/a85parse.syn */ + strcpy(ss[++ss_idx], "$"); ss_len = 1; +} + +static void ag_rp_53(int c) { +/* Line 150, C:/Projects/VirtualT/src/asm/a85parse.syn */ + ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; +} + +static void ag_rp_54(int c) { +/* Line 151, C:/Projects/VirtualT/src/asm/a85parse.syn */ + ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; +} + +static void ag_rp_55(int c) { +/* Line 152, C:/Projects/VirtualT/src/asm/a85parse.syn */ + ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; +} + +static void ag_rp_56(int c) { +/* Line 155, C:/Projects/VirtualT/src/asm/a85parse.syn */ + ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; +} + +static void ag_rp_57(int c) { +/* Line 156, C:/Projects/VirtualT/src/asm/a85parse.syn */ + ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; +} + +static void ag_rp_58(int ch1, int ch2) { +/* Line 162, C:/Projects/VirtualT/src/asm/a85parse.syn */ + ss_idx++; ss_len = 2; sprintf(ss[ss_idx], "%c%c", ch1, ch2); +} + +static void ag_rp_59(int c) { +/* Line 163, C:/Projects/VirtualT/src/asm/a85parse.syn */ + ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; +} + +static void ag_rp_60(void) { +/* Line 169, C:/Projects/VirtualT/src/asm/a85parse.syn */ + ss_idx++; ss_len = 0; +} + +static void ag_rp_61(int c) { +/* Line 170, C:/Projects/VirtualT/src/asm/a85parse.syn */ + ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; +} + +static void ag_rp_62(int c) { +/* Line 171, C:/Projects/VirtualT/src/asm/a85parse.syn */ + ss[ss_idx][ss_len++] = '\\'; ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; +} + +static void ag_rp_63(void) { +/* Line 175, C:/Projects/VirtualT/src/asm/a85parse.syn */ + ss[ss_idx][ss_len++] = '>'; ss[ss_idx][ss_len] = 0; +} + +static void ag_rp_64(void) { +/* Line 178, C:/Projects/VirtualT/src/asm/a85parse.syn */ + ss[++ss_idx][0] = '<'; ss[ss_idx][1] = 0; ss_len = 1; +} + +static void ag_rp_65(int c) { +/* Line 179, C:/Projects/VirtualT/src/asm/a85parse.syn */ + ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; +} + +static void ag_rp_66(int c) { +/* Line 180, C:/Projects/VirtualT/src/asm/a85parse.syn */ + ss[ss_idx][ss_len++] = '\\'; ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; +} + +#define ag_rp_67() (gAsm->label(ss[ss_idx--])) + +#define ag_rp_68() (condition(-1)) + +#define ag_rp_69() (condition(COND_NOCMP)) + +#define ag_rp_70() (condition(COND_EQ)) + +#define ag_rp_71() (condition(COND_NE)) + +#define ag_rp_72() (condition(COND_GE)) + +#define ag_rp_73() (condition(COND_LE)) + +#define ag_rp_74() (condition(COND_GT)) + +#define ag_rp_75() (condition(COND_LT)) + +#define ag_rp_76() (gEq->Add(RPN_BITOR)) + +#define ag_rp_77() (gEq->Add(RPN_BITOR)) + +#define ag_rp_78() (gEq->Add(RPN_BITXOR)) + +#define ag_rp_79() (gEq->Add(RPN_BITXOR)) + +#define ag_rp_80() (gEq->Add(RPN_BITAND)) + +#define ag_rp_81() (gEq->Add(RPN_BITAND)) + +#define ag_rp_82() (gEq->Add(RPN_LEFTSHIFT)) + +#define ag_rp_83() (gEq->Add(RPN_LEFTSHIFT)) + +#define ag_rp_84() (gEq->Add(RPN_RIGHTSHIFT)) + +#define ag_rp_85() (gEq->Add(RPN_RIGHTSHIFT)) + +#define ag_rp_86() (gEq->Add(RPN_ADD)) + +#define ag_rp_87() (gEq->Add(RPN_SUBTRACT)) + +#define ag_rp_88() (gEq->Add(RPN_MULTIPLY)) + +#define ag_rp_89() (gEq->Add(RPN_DIVIDE)) + +#define ag_rp_90() (gEq->Add(RPN_MODULUS)) + +#define ag_rp_91() (gEq->Add(RPN_MODULUS)) + +#define ag_rp_92() (gEq->Add(RPN_EXPONENT)) + +#define ag_rp_93() (gEq->Add(RPN_NOT)) + +#define ag_rp_94() (gEq->Add(RPN_NOT)) + +#define ag_rp_95() (gEq->Add(RPN_BITNOT)) + +#define ag_rp_96(n) (gEq->Add((double) n)) + +#define ag_rp_97() (gEq->Add(ss[ss_idx--])) + +#define ag_rp_98() (gEq->Add(RPN_FLOOR)) + +#define ag_rp_99() (gEq->Add(RPN_CEIL)) + +#define ag_rp_100() (gEq->Add(RPN_LN)) + +#define ag_rp_101() (gEq->Add(RPN_LOG)) + +#define ag_rp_102() (gEq->Add(RPN_SQRT)) + +#define ag_rp_103() (gEq->Add(RPN_IP)) + +#define ag_rp_104() (gEq->Add(RPN_FP)) + +#define ag_rp_105(n) (n) + +#define ag_rp_106(r) (r) + +#define ag_rp_107(n) (n) + +#define ag_rp_108() (conv_to_dec()) + +#define ag_rp_109() (conv_to_hex()) + +#define ag_rp_110() (conv_to_hex()) + +#define ag_rp_111() (conv_to_hex()) + +#define ag_rp_112() (conv_to_bin()) + +#define ag_rp_113() (conv_to_oct()) + +#define ag_rp_114() (conv_to_dec()) + +static void ag_rp_115(int n) { +/* Line 304, C:/Projects/VirtualT/src/asm/a85parse.syn */ + int_len = 1; integer[0] = n; integer[1] = 0; +} + +static void ag_rp_116(int n) { +/* Line 305, C:/Projects/VirtualT/src/asm/a85parse.syn */ + int_len = 2; integer[0] = '-', integer[1] = n; integer[2] = 0; +} + +static void ag_rp_117(int n) { +/* Line 306, C:/Projects/VirtualT/src/asm/a85parse.syn */ + int_len = 1; integer[0] = n; integer[1] = 0; +} + +static void ag_rp_118(int n) { +/* Line 307, C:/Projects/VirtualT/src/asm/a85parse.syn */ + integer[int_len++] = n; integer[int_len] = 0; +} + +static void ag_rp_119(int n) { +/* Line 312, C:/Projects/VirtualT/src/asm/a85parse.syn */ + int_len = 1; integer[0] = n; integer[1] = 0; +} + +static void ag_rp_120(int n) { +/* Line 313, C:/Projects/VirtualT/src/asm/a85parse.syn */ + integer[int_len++] = n; integer[int_len] = 0; +} + +static void ag_rp_121(int n) { +/* Line 316, C:/Projects/VirtualT/src/asm/a85parse.syn */ + integer[int_len++] = n; integer[int_len] = 0; +} + +static void ag_rp_122(int n) { +/* Line 317, C:/Projects/VirtualT/src/asm/a85parse.syn */ + integer[int_len++] = n; integer[int_len] = 0; +} + +#define ag_rp_123(n) (n) + +#define ag_rp_124() ('\\') + +#define ag_rp_125(n) (n) + +#define ag_rp_126() ('\\') + +#define ag_rp_127() ('\n') + +#define ag_rp_128() ('\t') + +#define ag_rp_129() ('\r') + +#define ag_rp_130() ('\0') + +#define ag_rp_131() ('\'') + +#define ag_rp_132() ('\'') + +static double ag_rp_133(void) { +/* Line 337, C:/Projects/VirtualT/src/asm/a85parse.syn */ + gDivisor = 1.0; return (double) conv_to_dec(); +} + +static double ag_rp_134(int d) { +/* Line 338, C:/Projects/VirtualT/src/asm/a85parse.syn */ + gDivisor = 10.0; return ((double) (d - '0') / gDivisor); +} + +static double ag_rp_135(double r, int d) { +/* Line 339, C:/Projects/VirtualT/src/asm/a85parse.syn */ + gDivisor *= 10.0; return (r + (double) (d - '0') / gDivisor); +} + +#define ag_rp_136() (reg[reg_cnt++] = '0') + +#define ag_rp_137() (reg[reg_cnt++] = '1') + +#define ag_rp_138() (reg[reg_cnt++] = '2') + +#define ag_rp_139() (reg[reg_cnt++] = '3') + +#define ag_rp_140() (reg[reg_cnt++] = '4') + +#define ag_rp_141() (reg[reg_cnt++] = '5') + +#define ag_rp_142() (reg[reg_cnt++] = '6') + +#define ag_rp_143() (reg[reg_cnt++] = '7') + +#define ag_rp_144() (reg[reg_cnt++] = '0') + +#define ag_rp_145() (reg[reg_cnt++] = '1') + +#define ag_rp_146() (reg[reg_cnt++] = '2') + +#define ag_rp_147() (reg[reg_cnt++] = '3') + +#define ag_rp_148() (reg[reg_cnt++] = '0') + +#define ag_rp_149() (reg[reg_cnt++] = '1') + +#define ag_rp_150() (reg[reg_cnt++] = '2') + +#define ag_rp_151() (reg[reg_cnt++] = '3') + +#define ag_rp_152() (reg[reg_cnt++] = '3') + +#define ag_rp_153() (reg[reg_cnt++] = '0') + +#define ag_rp_154() (reg[reg_cnt++] = '1') + +#define ag_rp_155() (gAsm->opcode_arg_equ8 (OPCODE_ACI)) + +#define ag_rp_156() (gAsm->opcode_arg_1reg (OPCODE_ADC)) + +#define ag_rp_157() (gAsm->opcode_arg_1reg (OPCODE_ADD)) + +#define ag_rp_158() (gAsm->opcode_arg_equ8 (OPCODE_ADI)) + +#define ag_rp_159() (gAsm->opcode_arg_1reg (OPCODE_ANA)) + +#define ag_rp_160() (gAsm->opcode_arg_equ8 (OPCODE_ANI)) + +#define ag_rp_161() (gAsm->opcode_arg_0 (OPCODE_ASHR)) + +#define ag_rp_162() (gAsm->opcode_arg_equ16 (OPCODE_CALL)) + +#define ag_rp_163() (gAsm->opcode_arg_equ16 (OPCODE_CC)) + +#define ag_rp_164() (gAsm->opcode_arg_equ16 (OPCODE_CM)) + +#define ag_rp_165() (gAsm->opcode_arg_0 (OPCODE_CMA)) + +#define ag_rp_166() (gAsm->opcode_arg_0 (OPCODE_CMC)) + +#define ag_rp_167() (gAsm->opcode_arg_1reg (OPCODE_CMP)) + +#define ag_rp_168() (gAsm->opcode_arg_equ16 (OPCODE_CNC)) + +#define ag_rp_169() (gAsm->opcode_arg_equ16 (OPCODE_CNZ)) + +#define ag_rp_170() (gAsm->opcode_arg_equ16 (OPCODE_CP)) + +#define ag_rp_171() (gAsm->opcode_arg_equ16 (OPCODE_CPE)) + +#define ag_rp_172() (gAsm->opcode_arg_equ8 (OPCODE_CPI)) + +#define ag_rp_173() (gAsm->opcode_arg_equ16 (OPCODE_CPO)) + +#define ag_rp_174() (gAsm->opcode_arg_equ16 (OPCODE_CZ)) + +#define ag_rp_175() (gAsm->opcode_arg_0 (OPCODE_DAA)) + +#define ag_rp_176() (gAsm->opcode_arg_1reg (OPCODE_DAD)) + +#define ag_rp_177() (gAsm->opcode_arg_1reg (OPCODE_DCR)) + +#define ag_rp_178() (gAsm->opcode_arg_1reg (OPCODE_DCX)) + +#define ag_rp_179() (gAsm->opcode_arg_0 (OPCODE_DI)) + +#define ag_rp_180() (gAsm->opcode_arg_0 (OPCODE_DSUB)) + +#define ag_rp_181() (gAsm->opcode_arg_0 (OPCODE_EI)) + +#define ag_rp_182() (gAsm->opcode_arg_0 (OPCODE_HLT)) + +#define ag_rp_183() (gAsm->opcode_arg_equ8 (OPCODE_IN)) + +#define ag_rp_184() (gAsm->opcode_arg_1reg (OPCODE_INR)) + +#define ag_rp_185() (gAsm->opcode_arg_1reg (OPCODE_INX)) + +#define ag_rp_186() (gAsm->opcode_arg_equ16 (OPCODE_JC)) + +#define ag_rp_187() (gAsm->opcode_arg_equ16 (OPCODE_JD)) + +#define ag_rp_188() (gAsm->opcode_arg_equ16 (OPCODE_JD)) + +#define ag_rp_189() (gAsm->opcode_arg_equ16 (OPCODE_JM)) + +#define ag_rp_190() (gAsm->opcode_arg_equ16 (OPCODE_JMP)) + +#define ag_rp_191() (gAsm->opcode_arg_equ16 (OPCODE_JNC)) + +#define ag_rp_192() (gAsm->opcode_arg_equ16 (OPCODE_JND)) + +#define ag_rp_193() (gAsm->opcode_arg_equ16 (OPCODE_JND)) + +#define ag_rp_194() (gAsm->opcode_arg_equ16 (OPCODE_JNZ)) + +#define ag_rp_195() (gAsm->opcode_arg_equ16 (OPCODE_JP)) + +#define ag_rp_196() (gAsm->opcode_arg_equ16 (OPCODE_JPE)) + +#define ag_rp_197() (gAsm->opcode_arg_equ16 (OPCODE_JPO)) + +#define ag_rp_198() (gAsm->opcode_arg_equ16 (OPCODE_JZ)) + +#define ag_rp_199() (gAsm->opcode_arg_equ16 (OPCODE_LDA)) + +#define ag_rp_200() (gAsm->opcode_arg_1reg (OPCODE_LDAX)) + +#define ag_rp_201() (gAsm->opcode_arg_equ8 (OPCODE_LDEH)) + +#define ag_rp_202() (gAsm->opcode_arg_equ8 (OPCODE_LDES)) + +#define ag_rp_203() (gAsm->opcode_arg_equ16 (OPCODE_LHLD)) + +#define ag_rp_204() (gAsm->opcode_arg_0 (OPCODE_LHLX)) + +#define ag_rp_205() (gAsm->opcode_arg_1reg_equ8(OPCODE_LXI)) + +#define ag_rp_206() (gAsm->opcode_arg_2reg (OPCODE_MOV)) + +#define ag_rp_207() (gAsm->opcode_arg_1reg_equ8(OPCODE_MVI)) + +#define ag_rp_208() (gAsm->opcode_arg_0 (OPCODE_NOP)) + +#define ag_rp_209() (gAsm->opcode_arg_1reg (OPCODE_ORA)) + +#define ag_rp_210() (gAsm->opcode_arg_equ8 (OPCODE_ORI)) + +#define ag_rp_211() (gAsm->opcode_arg_equ8 (OPCODE_OUT)) + +#define ag_rp_212() (gAsm->opcode_arg_0 (OPCODE_PCHL)) + +#define ag_rp_213() (gAsm->opcode_arg_1reg (OPCODE_POP)) + +#define ag_rp_214() (gAsm->opcode_arg_1reg (OPCODE_PUSH)) + +#define ag_rp_215() (gAsm->opcode_arg_0 (OPCODE_RAL)) + +#define ag_rp_216() (gAsm->opcode_arg_0 (OPCODE_RAR)) + +#define ag_rp_217() (gAsm->opcode_arg_0 (OPCODE_RC)) + +#define ag_rp_218() (gAsm->opcode_arg_0 (OPCODE_RET)) + +#define ag_rp_219() (gAsm->opcode_arg_0 (OPCODE_RIM)) + +#define ag_rp_220() (gAsm->opcode_arg_0 (OPCODE_RLC)) + +#define ag_rp_221() (gAsm->opcode_arg_0 (OPCODE_RLDE)) + +#define ag_rp_222() (gAsm->opcode_arg_0 (OPCODE_RM)) + +#define ag_rp_223() (gAsm->opcode_arg_0 (OPCODE_RNC)) + +#define ag_rp_224() (gAsm->opcode_arg_0 (OPCODE_RNZ)) + +#define ag_rp_225() (gAsm->opcode_arg_0 (OPCODE_RP)) + +#define ag_rp_226() (gAsm->opcode_arg_0 (OPCODE_RPE)) + +#define ag_rp_227() (gAsm->opcode_arg_0 (OPCODE_RPO)) + +#define ag_rp_228() (gAsm->opcode_arg_0 (OPCODE_RRC)) + +#define ag_rp_229(c) (gAsm->opcode_arg_imm (OPCODE_RST, c)) + +#define ag_rp_230() (gAsm->opcode_arg_0 (OPCODE_RZ)) + +#define ag_rp_231() (gAsm->opcode_arg_1reg (OPCODE_SBB)) + +#define ag_rp_232() (gAsm->opcode_arg_equ8 (OPCODE_SBI)) + +#define ag_rp_233() (gAsm->opcode_arg_equ16 (OPCODE_SHLD)) + +#define ag_rp_234() (gAsm->opcode_arg_0 (OPCODE_SHLX)) + +#define ag_rp_235() (gAsm->opcode_arg_0 (OPCODE_SIM)) + +#define ag_rp_236() (gAsm->opcode_arg_0 (OPCODE_SPHL)) + +#define ag_rp_237() (gAsm->opcode_arg_equ16 (OPCODE_STA)) + +#define ag_rp_238() (gAsm->opcode_arg_1reg (OPCODE_STAX)) + +#define ag_rp_239() (gAsm->opcode_arg_0 (OPCODE_STC)) + +#define ag_rp_240() (gAsm->opcode_arg_1reg (OPCODE_SUB)) + +#define ag_rp_241() (gAsm->opcode_arg_equ8 (OPCODE_SUI)) + +#define ag_rp_242() (gAsm->opcode_arg_0 (OPCODE_XCHG)) + +#define ag_rp_243() (gAsm->opcode_arg_1reg (OPCODE_XRA)) + +#define ag_rp_244() (gAsm->opcode_arg_equ8 (OPCODE_XRI)) + +#define ag_rp_245() (gAsm->opcode_arg_0 (OPCODE_XTHL)) + + +#define READ_COUNTS +#define WRITE_COUNTS +#undef V +#define V(i,t) (*(t *) (&(PCB).vs[(PCB).ssx + i])) +#undef VS +#define VS(i) (PCB).vs[(PCB).ssx + i] + +#ifndef GET_CONTEXT +#define GET_CONTEXT CONTEXT = (PCB).input_context +#endif + +typedef enum { + ag_action_1, + ag_action_2, + ag_action_3, + ag_action_4, + ag_action_5, + ag_action_6, + ag_action_7, + ag_action_8, + ag_action_9, + ag_action_10, + ag_action_11, + ag_action_12 +} ag_parser_action; + +#ifndef NULL_VALUE_INITIALIZER +#define NULL_VALUE_INITIALIZER = { 0 } +#endif + + +static a85parse_vs_type const ag_null_value NULL_VALUE_INITIALIZER; + +static const unsigned char ag_rpx[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 0, 0, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, + 41, 0, 42, 43, 44, 45, 46, 47, 0, 48, 49, 50, 51, 52, 53, 0, 54, 55, + 0, 56, 57, 58, 0, 59, 60, 61, 62, 0, 63, 64, 65, 0, 0, 0, 66, 0, + 0, 67, 0, 0, 68, 0, 0, 69, 0, 0, 70, 0, 0, 71, 0, 0, 72, 73, + 0, 74, 75, 0, 76, 77, 0, 78, 79, 80, 81, 0, 82, 83, 0, 84, 85, 86, + 87, 88, 0, 89, 90, 91, 92, 93, 0, 0, 94, 95, 96, 97, 98, 99,100,101, + 102,103,104,105,106,107,108,109,110,111,112,113,114, 0, 0,115,116,117, + 118,119,120,121,122,123,124,125,126,127,128, 0,129,130,131,132,133,134, + 135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150, 0, 0, + 0,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167, + 168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185, + 186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203, + 204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221, + 222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241 +}; + +static const unsigned char ag_key_itt[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0 +}; + +static const unsigned short ag_key_pt[] = { + 1,291, 1,295, 1,297, 1,305, 1,306, 1,307, 1,308, 1,309, + 1,310, 1,311, 1,312, 1,313, 1,314, 1,315, 1,316, 1,317, + 1,318, 1,319, 1,320, 1,321, 1,322, 1,324, 1,326, 1,327, + 1,328, 1,329, 1, 85, 1,331, 1,334, 1,336, 1,338, 1,340, + 1,342, 1,345, 1,347, 1,349, 1,351, 1,353, 1,359, 1,362, + 1,366, 1,367, 1,368, 1,369, 1,370, 1,371, 1,372, 1,376, + 1,374, 1,159, 1,375, 1,175, 1,176, 1,177, 1,178, 1,378, + 1,180, 1,377, 1,379, 1,381, 1,382, 1,383, 1,384, 1,385, + 1,386, 1,387, 1,388, 1,389, 1,390, 1,391, 1,392, 1,393, + 1,394, 1,395, 1,396, 1,397, 1,398, 1,399, 1,400, 1,402, + 1,403, 1,404, 1,405, 1,406, 1,407, 1,408, 1,409, 1,410, + 1,411, 1,412, 1,413, 1,414, 1,415, 1,416, 1,417, 1,418, + 1,419, 1,420, 1,421, 1,422, 1,423, 1,424, 1,425, 1,426, + 1,427, 1,428, 1,429, 1,430, 1,431, 1,432, 1,433, 1,434, + 1,435, 1,436, 1,437, 1,438, 1,439, 1,440, 1,441, 1,442, + 1,443, 1,444, 1,445, 1,446, 1,447, 1,448, 1,449, 1,450, + 1,451, 1,452, 1,453, 1,454, 1,455, 1,456, 1,457, 1,458, + 1,459, 1,460, 1,461, 1,462, 1,463, 1,464, 1,465, 1,466, + 1,467, 1,468, 1,469, 1,470, 1,471,0 +}; + +static const unsigned char ag_key_ch[] = { + 0, 76, 78,255, 68, 78,255, 70, 78,255, 68, 69, 73, 80, 85,255, 42, 47, + 255, 67, 68, 73,255, 65, 73,255, 69, 72,255, 67, 68, 78, 83,255, 65, 67, + 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 83, 90,255, 65, + 68,255, 82, 88,255, 69, 85,255, 65, 66, 67, 73, 83, 87,255, 73,255, 68, + 255, 69, 82,255, 84,255, 73, 76, 78, 88,255, 67, 82, 88,255, 70, 78,255, + 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, + 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 72, 73, 88,255, + 65, 79, 86,255, 65, 79,255, 65, 71, 73,255, 82, 85,255, 66, 83,255, 65, + 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, 79,255, 65, 67, + 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, 68, 88,255, 76,255, + 88,255, 65, 67, 75,255, 66, 73,255, 66, 72, 73, 80, 84, 85, 89,255, 65, + 73,255, 67, 82, 84,255, 35, 36, 47, 65, 67, 68, 69, 72, 73, 74, 76, 77, + 78, 79, 80, 82, 83, 84, 88,255, 76, 78,255, 68, 78,255, 70, 78,255, 68, + 69, 73, 80, 85,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 67, 68, + 73,255, 65, 68, 73,255, 69, 72,255, 67, 68, 78, 83,255, 65, 67, 80,255, + 67, 90,255, 69, 73, 79,255, 65, 67, 69, 77, 78, 80, 83, 90,255, 65, 68, + 255, 82, 88,255, 69, 85,255, 65, 66, 67, 73, 83, 87,255, 73,255, 68,255, + 85,255, 69, 82,255, 84,255, 73, 76, 78, 81, 88,255, 76, 80,255, 69, 84, + 255, 69, 76,255, 67, 82, 88,255, 70, 78, 80,255, 80,255, 67, 68, 88, 90, + 255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, 88,255, 72, 83,255, 65, + 69,255, 68, 88,255, 76,255, 78, 83,255, 68, 69, 72, 73, 78, 79, 84, 88, + 255, 68, 86,255, 65, 79, 86,255, 80, 84,255, 65, 69, 79,255, 65, 71, 73, + 255, 82, 85,255, 66, 83,255, 65, 67, 79, 83, 85,255, 76, 82,255, 67, 68, + 255, 67, 90,255, 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90, + 255, 66, 73,255, 68, 88,255, 76, 82,255, 72,255, 88,255, 65, 67, 75,255, + 66, 73,255, 66, 69, 72, 73, 80, 81, 84, 85, 89,255, 65, 73,255, 67, 79, + 82, 84,255, 33, 35, 36, 39, 42, 44, 47, 60, 61, 62, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, 88,255, 42,255, 76, + 78,255, 68, 78,255, 70, 78,255, 68, 69, 73, 80, 85,255, 42, 47,255, 60, + 61,255, 61,255, 61, 62,255, 67, 68, 73,255, 65, 68, 73,255, 69, 72,255, + 67, 68, 78, 83,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, + 69, 77, 78, 80, 83, 90,255, 65, 68,255, 82, 88,255, 69, 85,255, 65, 66, + 67, 73, 83, 87,255, 73,255, 68,255, 69, 82,255, 84,255, 73, 76, 78, 81, + 88,255, 76, 80,255, 69, 84,255, 76,255, 67, 82, 88,255, 70, 78, 80,255, + 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, + 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 69, 72, 73, 78, + 79, 84, 88,255, 68, 86,255, 65, 79, 86,255, 80, 84,255, 65, 69, 79,255, + 65, 71, 73,255, 82, 85,255, 66, 83,255, 65, 67, 79, 83, 85,255, 76, 82, + 255, 67, 68,255, 67, 90,255, 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, + 82, 83, 90,255, 66, 73,255, 68, 88,255, 76, 82,255, 72,255, 88,255, 65, + 67, 75,255, 66, 73,255, 66, 72, 73, 80, 81, 84, 85, 89,255, 65, 73,255, + 67, 79, 82, 84,255, 33, 35, 36, 39, 42, 44, 47, 60, 61, 62, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, 88,255, 76, + 80,255, 78, 79,255, 36, 39, 47, 67, 70, 73, 76, 78, 83,255, 47,255, 47, + 58,255, 36, 47,255, 42, 47,255, 47,255, 47, 72, 76,255, 42, 47,255, 67, + 68, 73,255, 65, 73,255, 69, 72,255, 67, 68, 78, 83,255, 65, 67, 80,255, + 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 83, 90,255, 65, 68,255, + 82, 88,255, 69, 85,255, 65, 66, 67, 73, 83, 87,255, 73,255, 68,255, 69, + 82,255, 84,255, 73, 76, 78, 81, 88,255, 82, 88,255, 70, 78,255, 80,255, + 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, 88,255, + 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 72, 73, 88,255, 65, 79, + 86,255, 65, 79,255, 65, 71, 73,255, 82, 85,255, 66, 83,255, 65, 67, 79, + 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, 79,255, 65, 67, 69, 73, + 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, 68, 88,255, 76,255, 88,255, + 65, 67, 75,255, 66, 73,255, 66, 69, 72, 73, 80, 84, 85, 89,255, 65, 73, + 255, 67, 82, 84,255, 47, 65, 67, 68, 69, 72, 73, 74, 76, 77, 78, 79, 80, + 82, 83, 84, 88,255, 67, 68, 73,255, 65, 73,255, 69, 72,255, 67, 68, 78, + 83,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, + 83, 90,255, 65, 68,255, 82, 88,255, 69, 85,255, 65, 66, 67, 73, 83, 87, + 255, 73,255, 68,255, 69, 82,255, 84,255, 73, 76, 78, 88,255, 82, 88,255, + 70, 78,255, 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, + 88, 90,255, 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 72, + 73, 88,255, 65, 79, 86,255, 65, 79,255, 65, 71, 73,255, 82, 85,255, 66, + 83,255, 65, 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, 79, + 255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, 68, 88, + 255, 76,255, 88,255, 65, 67, 75,255, 66, 73,255, 66, 72, 73, 80, 84, 85, + 89,255, 65, 73,255, 67, 82, 84,255, 65, 67, 68, 69, 72, 73, 74, 76, 77, + 78, 79, 80, 82, 83, 84, 88,255, 66, 83, 87,255, 68, 69, 83,255, 36,255, + 72, 76,255, 67, 68, 73,255, 65, 73,255, 69, 72,255, 67, 68, 78, 83,255, + 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 83, 90, + 255, 65, 68,255, 82, 88,255, 69, 85,255, 65, 66, 67, 73, 83, 87,255, 73, + 255, 68,255, 69, 82,255, 84,255, 73, 76, 78, 81, 88,255, 82, 88,255, 70, + 78,255, 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, + 90,255, 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 72, 73, + 88,255, 65, 79, 86,255, 65, 79,255, 65, 71, 73,255, 82, 85,255, 66, 83, + 255, 65, 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, 79,255, + 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, 68, 88,255, + 76,255, 88,255, 65, 67, 75,255, 66, 73,255, 66, 69, 72, 73, 80, 84, 85, + 89,255, 65, 73,255, 67, 82, 84,255, 47, 65, 67, 68, 69, 72, 73, 74, 76, + 77, 78, 79, 80, 82, 83, 84, 88,255, 47,255, 76, 80,255, 78, 79,255, 36, + 39, 47, 67, 70, 73, 76, 83,255, 42, 47,255, 67, 68, 73,255, 65, 73,255, + 67, 68, 78, 83,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, + 77, 78, 80, 90,255, 65, 68,255, 82, 88,255, 65, 67, 73, 83,255, 82, 88, + 255, 78,255, 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, + 88, 90,255, 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 72, + 88,255, 79, 86,255, 65, 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, + 67, 68,255, 67, 90,255, 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, + 83, 90,255, 66, 73,255, 68, 88,255, 76,255, 88,255, 65, 67,255, 66, 73, + 255, 66, 72, 73, 80, 84, 85,255, 65, 73,255, 67, 82, 84,255, 47, 65, 67, + 68, 69, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 42, 47,255, 60, + 61,255, 61,255, 61, 62,255, 67, 68, 73,255, 65, 68, 73,255, 67, 68, 78, + 83,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, + 90,255, 65, 68,255, 82, 88,255, 65, 67, 73, 83,255, 73, 81,255, 69, 84, + 255, 82, 88,255, 78,255, 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, + 77, 78, 80, 88, 90,255, 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76, + 255, 68, 69, 72, 84, 88,255, 68, 86,255, 79, 86,255, 69, 79,255, 65, 73, + 255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, + 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, 68, + 88,255, 76, 82,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, 73, 80, 84, + 85,255, 65, 73,255, 67, 79, 82, 84,255, 33, 42, 44, 47, 60, 61, 62, 65, + 67, 68, 69, 71, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 42, 47, + 255, 67, 68, 73,255, 65, 73,255, 67, 68, 78, 83,255, 65, 67, 80,255, 67, + 90,255, 69, 73, 79,255, 65, 67, 69, 77, 78, 80, 90,255, 65, 68,255, 82, + 88,255, 65, 67, 73, 83,255, 76, 80,255, 82, 88,255, 78, 80,255, 80,255, + 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, 88,255, + 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 72, 78, 79, 88,255, 79, + 86,255, 65, 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 67, 68,255, + 67, 90,255, 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, + 66, 73,255, 68, 88,255, 76,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, + 73, 80, 81, 84, 85,255, 65, 73,255, 67, 82, 84,255, 36, 39, 47, 65, 67, + 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 47, 65, 66, + 67, 68, 69, 72, 76, 77,255, 47, 66, 68,255, 47, 65, 66, 68, 72, 80,255, + 47, 66, 68, 72, 83,255, 76, 80,255, 78, 79,255, 36, 39, 67, 70, 73, 76, + 78, 83,255, 65, 66, 67, 68, 69, 72, 76, 77,255, 66, 68,255, 65, 66, 68, + 72, 80,255, 66, 68, 72, 83,255, 67, 68, 73,255, 65, 73,255, 67, 68, 78, + 83,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, + 90,255, 65, 68,255, 82, 88,255, 65, 67, 73, 83,255, 82, 88,255, 78,255, + 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, + 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 72, 88,255, 79, + 86,255, 65, 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 67, 68,255, + 67, 90,255, 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, + 66, 73,255, 68, 88,255, 76,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, + 73, 80, 84, 85,255, 65, 73,255, 67, 82, 84,255, 47, 65, 67, 68, 69, 72, + 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 42, 47,255, 36, 47,255, 36, + 47,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 33, 42, 44, 47, 60, + 61, 62,255, 42, 47,255, 44, 47,255, 39,255, 39,255, 42, 47,255, 60, 61, + 255, 61,255, 61, 62,255, 67, 68, 73,255, 65, 68, 73,255, 67, 68, 78, 83, + 255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 90, + 255, 65, 68,255, 82, 88,255, 65, 67, 73, 83,255, 73, 81,255, 69, 84,255, + 76,255, 82, 88,255, 78,255, 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, + 68, 77, 78, 80, 88, 90,255, 88,255, 72, 83,255, 65, 69,255, 68, 88,255, + 76,255, 68, 69, 72, 84, 88,255, 68, 86,255, 79, 86,255, 69, 79,255, 65, + 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, + 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, + 68, 88,255, 76, 82,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, 73, 80, + 84, 85,255, 65, 73,255, 67, 79, 82, 84,255, 33, 42, 44, 47, 60, 61, 62, + 65, 66, 67, 68, 69, 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 83, 88, + 255, 72,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 76, + 255, 82, 88,255, 78,255, 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, + 77, 78, 80, 88, 90,255, 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76, + 255, 68, 69, 72, 84, 88,255, 68, 86,255, 79, 86,255, 69, 79,255, 65, 73, + 255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, + 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, 68, + 88,255, 76, 82,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, 73, 80, 84, + 85,255, 65, 73,255, 67, 79, 82, 84,255, 33, 42, 44, 47, 60, 61, 62, 66, + 68, 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 83, 88,255, 76, 80,255, + 78, 79,255, 36, 39, 67, 70, 73, 76, 83,255, 60, 61,255, 61,255, 61, 62, + 255, 67, 68, 73,255, 65, 68, 73,255, 67, 68, 78, 83,255, 65, 67, 80,255, + 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 90,255, 65, 68,255, 82, + 88,255, 65, 67, 73, 83,255, 73, 81,255, 69, 84,255, 82, 88,255, 78,255, + 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, + 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 69, 72, 84, 88, + 255, 68, 86,255, 79, 86,255, 69, 79,255, 65, 73,255, 82, 85,255, 67, 79, + 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, 79,255, 65, 67, 69, 73, + 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, 68, 88,255, 76, 82,255, 88, + 255, 65, 67,255, 66, 73,255, 66, 72, 73, 80, 84, 85,255, 65, 73,255, 67, + 79, 82, 84,255, 33, 42, 44, 47, 60, 61, 62, 65, 67, 68, 69, 71, 72, 73, + 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 60, 61,255, 61,255, 61, 62,255, + 67, 68, 73,255, 65, 68, 73,255, 67, 68, 78, 83,255, 65, 67, 80,255, 67, + 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 90,255, 65, 68,255, 82, 88, + 255, 65, 67, 73, 83,255, 73, 81,255, 69, 84,255, 82, 88,255, 78,255, 80, + 255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, 88, + 255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 69, 72, 84, 88,255, + 79, 86,255, 69, 79,255, 65, 73,255, 82, 85,255, 67, 79, 85,255, 76, 82, + 255, 67, 68,255, 67, 90,255, 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, + 82, 83, 90,255, 66, 73,255, 68, 88,255, 76, 82,255, 88,255, 65, 67,255, + 66, 73,255, 66, 72, 73, 80, 84, 85,255, 65, 73,255, 67, 79, 82, 84,255, + 33, 44, 47, 60, 61, 62, 65, 67, 68, 69, 71, 72, 73, 74, 76, 77, 78, 79, + 80, 82, 83, 88,255, 61,255, 61,255, 61,255, 67, 68, 73,255, 65, 68, 73, + 255, 67, 68, 78, 83,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, + 67, 77, 78, 80, 90,255, 65, 68,255, 82, 88,255, 65, 67, 73, 83,255, 73, + 81,255, 69, 84,255, 82, 88,255, 78,255, 80,255, 67, 68, 88, 90,255, 69, + 79,255, 67, 68, 77, 78, 80, 88, 90,255, 88,255, 72, 83,255, 65, 69,255, + 68, 88,255, 76,255, 68, 69, 72, 84, 88,255, 79, 86,255, 69, 79,255, 65, + 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, + 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, + 68, 88,255, 76,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, 73, 80, 84, + 85,255, 65, 73,255, 67, 79, 82, 84,255, 33, 44, 47, 60, 61, 62, 65, 67, + 68, 69, 71, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 61,255, 61, + 255, 61,255, 67, 68, 73,255, 65, 73,255, 67, 68, 78, 83,255, 65, 67, 80, + 255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 90,255, 65, 68,255, + 82, 88,255, 65, 67, 73, 83,255, 73, 81,255, 69, 84,255, 82, 88,255, 78, + 255, 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90, + 255, 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 69, 72, 84, + 88,255, 79, 86,255, 69, 79,255, 65, 73,255, 82, 85,255, 67, 79, 85,255, + 76, 82,255, 67, 68,255, 67, 90,255, 69, 79,255, 65, 67, 69, 73, 76, 77, + 78, 80, 82, 83, 90,255, 66, 73,255, 68, 88,255, 76,255, 88,255, 65, 67, + 255, 66, 73,255, 66, 72, 73, 80, 84, 85,255, 65, 73,255, 67, 79, 82, 84, + 255, 33, 44, 47, 60, 61, 62, 65, 67, 68, 69, 71, 72, 73, 74, 76, 77, 78, + 79, 80, 82, 83, 88,255, 61,255, 61,255, 61,255, 67, 68, 73,255, 65, 73, + 255, 67, 68, 78, 83,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, + 67, 77, 78, 80, 90,255, 65, 68,255, 82, 88,255, 65, 67, 73, 83,255, 73, + 81,255, 69, 84,255, 82, 88,255, 78,255, 80,255, 67, 68, 88, 90,255, 69, + 79,255, 67, 68, 77, 78, 80, 88, 90,255, 88,255, 72, 83,255, 65, 69,255, + 68, 88,255, 76,255, 68, 69, 72, 84, 88,255, 79, 86,255, 69, 79,255, 65, + 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, + 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, + 68, 88,255, 76,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, 73, 80, 84, + 85,255, 65, 73,255, 67, 82, 84,255, 33, 44, 47, 60, 61, 62, 65, 67, 68, + 69, 71, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 61,255, 61,255, + 61,255, 69, 84,255, 69, 84,255, 33, 47, 60, 61, 62, 69, 71, 76, 78,255, + 44, 47,255, 42, 47,255, 67, 68, 73,255, 65, 73,255, 67, 68, 78, 83,255, + 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 90,255, + 65, 68,255, 82, 88,255, 65, 67, 73, 83,255, 82, 88,255, 78,255, 80,255, + 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, 88,255, + 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 72, 88,255, 79, 86,255, + 65, 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90, + 255, 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73, + 255, 68, 88,255, 76,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, 73, 80, + 84, 85,255, 65, 73,255, 67, 82, 84,255, 44, 47, 65, 67, 68, 69, 72, 73, + 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 44,255, 42, 47,255, 47, 66, 68, + 72, 81,255, 69,255, 76, 80,255, 78, 79,255, 36, 39, 47, 65, 66, 67, 68, + 69, 70, 72, 73, 76, 77, 78, 83,255 +}; + +static const unsigned char ag_key_act[] = { + 0,3,3,4,3,3,4,2,3,4,3,2,2,3,3,4,0,0,4,5,5,5,4,5,5,4,7,7,4,7,2,2,2,4,5, + 5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5,4,5,5,4,5,5,4,7,7,4,2,5,2,5,6,5,4,7, + 4,6,4,7,7,4,2,4,5,7,2,2,4,7,5,5,4,5,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6, + 5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,2,7,7,4,7,7,7,4,7,7,4,5,5,5,4,2,7,4, + 7,7,4,7,7,7,2,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4, + 5,5,4,2,4,5,4,6,5,7,4,5,5,4,2,2,7,7,2,2,7,4,5,5,4,7,2,7,4,2,5,2,2,2,2, + 2,7,2,2,2,2,2,2,2,2,2,7,2,4,3,3,4,3,3,4,2,3,4,3,2,2,3,3,4,0,0,4,0,0,4, + 0,4,0,0,4,5,5,5,4,5,5,5,4,7,7,4,7,2,2,2,4,5,5,5,4,5,5,4,5,5,5,4,7,5,7, + 6,2,6,7,5,4,5,5,4,5,5,4,7,7,4,2,5,2,5,6,5,4,7,4,6,4,5,4,7,7,4,2,4,5,7, + 2,6,2,4,7,5,4,5,5,4,7,7,4,7,5,5,4,5,6,5,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2, + 6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,7,7,4,2,5,2,2,5,7,5,7,4,5,5,4,7,2,7, + 4,5,5,4,7,5,2,4,5,5,5,4,6,7,4,7,7,4,7,7,7,7,2,4,5,5,4,5,7,4,5,5,4,5,5, + 4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,6,5,4,7,4,5,4,6,5,7,4,5,5,4,2,7, + 2,7,6,7,2,2,7,4,5,5,4,7,7,2,7,4,3,2,5,3,3,0,2,1,1,1,6,5,6,6,6,2,2,6,2, + 2,6,6,2,2,2,2,2,7,2,4,3,4,3,3,4,3,3,4,2,3,4,3,2,2,3,3,4,0,0,4,0,0,4,0, + 4,0,0,4,5,5,5,4,5,5,5,4,7,7,4,7,2,2,2,4,5,5,5,4,5,5,4,5,5,5,4,7,5,7,6, + 2,6,7,5,4,5,5,4,5,5,4,7,7,4,2,5,2,5,6,5,4,7,4,6,4,7,7,4,2,4,5,7,2,5,2, + 4,7,5,4,5,5,4,7,4,7,5,5,4,5,6,5,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4, + 5,4,5,5,4,6,2,4,5,5,4,2,4,2,5,2,7,5,7,5,7,4,5,5,4,7,2,7,4,5,5,4,7,5,2, + 4,5,5,5,4,6,7,4,7,7,4,7,7,7,7,2,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7,2,5, + 2,6,7,7,5,4,5,5,4,5,5,4,6,5,4,7,4,5,4,6,5,7,4,5,5,4,2,2,7,6,7,2,2,7,4, + 5,5,4,7,7,2,7,4,3,2,5,3,3,0,2,1,1,1,6,5,6,6,6,2,2,6,2,2,6,6,2,2,2,2,2, + 7,2,4,7,5,4,5,7,4,5,3,3,7,2,7,2,7,7,4,3,4,3,0,4,5,3,4,0,0,4,2,4,3,7,7, + 4,0,0,4,5,5,5,4,5,5,4,7,7,4,7,2,2,2,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6, + 7,5,4,5,5,4,5,5,4,7,7,4,2,5,2,5,6,5,4,7,4,6,4,7,7,4,2,4,5,7,2,7,2,4,5, + 5,4,5,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2, + 4,2,2,7,7,4,7,7,7,4,7,7,4,5,5,5,4,2,7,4,7,7,4,7,7,7,2,4,5,5,4,5,7,4,5, + 5,4,5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,2,4,5,4,6,5,7,4,5,5,4,2, + 7,2,7,7,2,2,7,4,5,5,4,7,2,7,4,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,7,2,4,5,5, + 5,4,5,5,4,7,7,4,7,2,2,2,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5,4,5,5,4, + 5,5,4,7,7,4,2,5,2,5,6,5,4,7,4,6,4,7,7,4,2,4,5,7,2,2,4,5,5,4,5,6,4,5,4, + 5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,2,7,7,4,7, + 7,7,4,7,7,4,5,5,5,4,2,7,4,7,7,4,7,7,7,2,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5, + 7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,2,4,5,4,6,5,7,4,5,5,4,2,2,7,7,2,2,7,4, + 5,5,4,7,2,7,4,2,2,2,2,7,2,2,2,2,2,2,2,2,2,7,2,4,5,5,5,4,2,7,7,4,5,4,7, + 7,4,5,5,5,4,5,5,4,7,7,4,7,2,2,2,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5, + 4,5,5,4,5,5,4,7,7,4,2,5,2,5,6,5,4,7,4,6,4,7,7,4,2,4,5,7,2,7,2,4,5,5,4, + 5,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2, + 2,7,7,4,7,7,7,4,7,7,4,5,5,5,4,2,7,4,7,7,4,7,7,7,2,4,5,5,4,5,7,4,5,5,4, + 5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,2,4,5,4,6,5,7,4,5,5,4,2,7,2, + 7,7,2,2,7,4,5,5,4,7,2,7,4,3,2,2,2,2,7,2,2,2,2,2,2,2,2,2,7,2,4,3,4,7,5, + 4,5,7,4,5,3,3,7,2,7,2,7,4,0,0,4,5,5,5,4,5,5,4,7,2,2,7,4,5,5,5,4,5,5,4, + 5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,2,2,5,7,4,5,5,4,6,4,5,4,5,5,5,5,4,5, + 5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,2,7,4,7,7,4,5,5,4,2,7, + 4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4, + 2,4,5,4,6,5,4,5,5,4,2,2,7,7,2,2,4,5,5,4,7,2,7,4,2,2,2,2,7,7,2,2,2,2,7, + 2,2,2,2,2,4,0,0,4,0,0,4,0,4,0,0,4,5,5,5,4,5,5,5,4,7,2,2,7,4,5,5,5,4,5, + 5,4,5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,2,2,5,7,4,5,5,4,5,5,4,5,5,4,6,4, + 5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,5,2,5, + 7,4,5,5,4,2,7,4,5,7,4,5,5,4,6,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5, + 7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,6,5,4,5,4,6,5,4,5,5,4,2,2,7,7,2,2,4,5, + 5,4,7,7,2,7,4,3,3,0,2,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,4,0,0,4,5, + 5,5,4,5,5,4,7,2,2,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5,7,6,2,6,5,4,5,5,4,5,5, + 4,2,2,5,7,4,7,5,4,5,5,4,6,5,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4, + 5,5,4,6,2,4,5,5,4,2,4,2,2,5,7,7,4,7,7,4,5,5,4,2,7,4,7,7,7,4,5,5,4,5,7, + 4,5,5,4,5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,2,4,5,4,6,5,4,5,5,4, + 2,2,7,7,7,2,2,4,5,5,4,7,2,7,4,5,3,2,2,2,2,7,2,7,2,2,2,2,7,2,2,2,2,2,4, + 3,5,5,5,5,5,5,5,5,4,3,5,5,4,3,5,5,5,5,7,4,3,5,5,5,7,4,7,5,4,5,7,4,5,3, + 7,2,7,2,7,7,4,5,5,5,5,5,5,5,5,4,5,5,4,5,5,5,5,7,4,5,5,5,7,4,5,5,5,4,5, + 5,4,7,2,2,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,2,2,5,7, + 4,5,5,4,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4, + 2,4,2,2,7,4,7,7,4,5,5,4,2,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7, + 2,5,2,6,7,7,5,4,5,5,4,5,5,4,2,4,5,4,6,5,4,5,5,4,2,2,7,7,2,2,4,5,5,4,7, + 2,7,4,3,2,2,2,7,7,2,2,2,2,7,2,2,2,2,2,4,0,0,4,5,2,4,5,3,4,0,0,4,0,0,4, + 0,4,0,0,4,3,3,0,2,1,1,1,4,0,0,4,0,2,4,3,4,3,4,0,0,4,0,0,4,0,4,0,0,4,5, + 5,5,4,5,5,5,4,7,2,2,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5, + 4,2,2,5,7,4,5,5,4,5,5,4,7,4,5,5,4,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5, + 5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,5,2,5,7,4,5,5,4,2,7,4,5,7,4,5,5,4,6,7, + 4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4, + 6,5,4,5,4,6,5,4,5,5,4,2,2,7,7,2,2,4,5,5,4,7,7,2,7,4,3,3,0,2,1,1,1,2,5, + 2,6,2,2,6,2,2,2,2,2,2,2,5,2,2,2,4,5,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,7,4, + 5,5,4,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2, + 4,2,5,2,5,7,4,5,5,4,2,7,4,5,7,4,5,5,4,6,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4, + 5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,6,5,4,5,4,6,5,4,5,5,4,2,2,7, + 7,2,2,4,5,5,4,7,7,2,7,4,3,3,0,2,1,1,1,5,5,2,6,2,2,2,2,2,2,2,5,2,2,2,4, + 7,5,4,5,7,4,5,3,7,2,7,2,7,4,0,0,4,0,4,0,0,4,5,5,5,4,5,5,5,4,7,2,2,7,4, + 5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,2,2,5,7,4,5,5,4,5,5,4, + 5,5,4,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2, + 4,2,5,2,5,7,4,5,5,4,2,7,4,5,7,4,5,5,4,6,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4, + 5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,6,5,4,5,4,6,5,4,5,5,4,2,2,7, + 7,2,2,4,5,5,4,7,7,2,7,4,3,3,0,3,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2, + 4,0,0,4,0,4,0,0,4,5,5,5,4,5,5,5,4,7,2,2,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5, + 6,2,6,5,4,5,5,4,5,5,4,2,2,5,7,4,5,5,4,5,5,4,5,5,4,6,4,5,4,5,5,5,5,4,5, + 5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,5,2,5,7,4,7,7,4,5,7,4, + 5,5,4,6,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5, + 5,4,5,5,4,6,5,4,5,4,6,5,4,5,5,4,2,2,7,7,2,2,4,5,5,4,7,7,2,7,4,3,0,3,1, + 1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,4,0,4,0,4,0,4,5,5,5,4,5,5,5,4,7,2, + 2,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,2,2,5,7,4,5,5,4, + 5,5,4,5,5,4,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5, + 5,4,2,4,2,5,2,5,7,4,7,7,4,5,7,4,5,5,4,6,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4, + 5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,2,4,5,4,6,5,4,5,5,4,2,2,7,7, + 2,2,4,5,5,4,7,7,2,7,4,3,0,3,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,4,0, + 4,0,4,0,4,5,5,5,4,5,5,4,7,2,2,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,5,4, + 5,5,4,5,5,4,2,2,5,7,4,5,5,4,5,5,4,5,5,4,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6, + 2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,5,2,5,7,4,7,7,4,5,7,4,5,5,4,6,7, + 4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4, + 2,4,5,4,6,5,4,5,5,4,2,2,7,7,2,2,4,5,5,4,7,7,2,7,4,3,0,3,1,1,1,2,2,2,2, + 2,7,2,2,2,2,2,2,2,2,2,2,4,0,4,0,4,0,4,5,5,5,4,5,5,4,7,2,2,7,4,5,5,5,4, + 5,5,4,5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,2,2,5,7,4,5,5,4,5,5,4,5,5,4,6, + 4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,5,2, + 5,7,4,7,7,4,5,7,4,5,5,4,6,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7, + 2,5,2,6,7,7,5,4,5,5,4,5,5,4,2,4,5,4,6,5,4,5,5,4,2,2,7,7,2,2,4,5,5,4,7, + 2,7,4,3,0,3,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,4,0,4,0,4,0,4,5,5,4, + 5,5,4,3,3,1,1,1,7,2,2,7,4,0,3,4,0,0,4,5,5,5,4,5,5,4,7,2,2,7,4,5,5,5,4, + 5,5,4,5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,2,2,5,7,4,5,5,4,6,4,5,4,5,5,5, + 5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,2,7,4,7,7,4,5,5, + 4,2,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4, + 5,5,4,2,4,5,4,6,5,4,5,5,4,2,2,7,7,2,2,4,5,5,4,7,2,7,4,0,2,2,2,2,7,7,2, + 2,2,2,7,2,2,2,2,2,4,0,4,0,0,4,2,5,5,5,5,4,7,4,7,5,4,5,7,4,5,3,3,5,5,6, + 5,5,2,5,7,6,5,7,7,4 +}; + +static const unsigned short ag_key_parm[] = { + 0,301,302, 0,299,300, 0, 0,294, 0,303, 0, 0,296,304, 0, 35,285, + 0,118,120,122, 0,124,126, 0, 12,128, 0,116, 0, 0, 0, 0,136,138, + 140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146, 14,154, 0,156, + 158, 0,160,162, 0, 16,166, 0, 0, 20, 0,164, 18, 22, 0, 40, 0, 34, + 0, 26, 24, 0, 0, 0,168, 38, 0, 0, 0, 0,174,176, 0, 36,172, 0, + 186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0, + 206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 0, 48,216, 0, + 50,218,220, 0, 30,222, 0,224, 10,226, 0, 0,228, 0, 28,234, 0, 44, + 230,232, 0, 0,236,238, 0,246,248, 0,252,254, 0,258,260, 0, 0,240, + 242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272,274, 0, 0, 0, + 282, 0,280,284, 32, 0,286,288, 0, 0, 0,276,278, 0, 0, 46, 0,292, + 294, 0,290, 0,296, 0, 0, 52, 0, 0, 0, 0, 0,170, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 42, 0, 0,301,302, 0,299,300, 0, 0,294, 0,303, + 0, 0,296,304, 0, 35,285, 0,350,339, 0,332, 0,337,352, 0,118,120, + 122, 0,124, 70,126, 0, 12,128, 0,116, 0, 0, 0, 0,136,138,140, 0, + 142,144, 0,148,150,152, 0,130,132, 82,134, 0,146, 14,154, 0,156,158, + 0,160,162, 0, 16,166, 0, 0, 20, 0,164, 18, 22, 0, 40, 0, 34, 0, + 6, 0, 26, 24, 0, 0, 0,168, 38, 0, 54, 0, 0, 80, 92, 0, 58, 62, + 0, 4,170, 0, 0,174,176, 0, 36,172, 90, 0,186, 0,188,190,192,194, + 0,198,200, 0,178,180,184, 0,196,182,202, 0,206, 0,208,210, 0,204, + 0, 0,212,214, 0, 0, 0, 48, 2, 0, 0, 60, 0, 0, 84, 86, 64,216, + 0, 76,218, 0, 50, 0,220, 0,222, 78, 0, 30, 56, 0, 0,224, 10,226, + 0, 66,228, 0, 28,234, 0, 44,230,232,114, 0, 0,236,238, 0,246,248, + 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, + 0,268,270, 0,272,274, 0, 72, 74, 0,278, 0,282, 0,280,284, 32, 0, + 286,288, 0, 0, 8, 0,276,112, 88, 0, 0, 46, 0,292,294, 0,290, 68, + 0,296, 0,335, 0, 52,168,360,330, 0,343,333,341,110, 96,102,100,104, + 0, 0, 94, 0, 0,106,108, 0, 0, 0, 0, 0, 42, 0, 0, 38, 0,301, + 302, 0,299,300, 0, 0,294, 0,303, 0, 0,296,304, 0, 35,285, 0,350, + 339, 0,332, 0,337,352, 0,118,120,122, 0,124, 70,126, 0, 12,128, 0, + 116, 0, 0, 0, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132, + 82,134, 0,146, 14,154, 0,156,158, 0,160,162, 0, 16,166, 0, 0, 20, + 0,164, 18, 22, 0, 40, 0, 34, 0, 26, 24, 0, 0, 0,168, 38, 0, 54, + 0, 0, 80, 92, 0, 58, 62, 0,170, 0, 0,174,176, 0, 36,172, 90, 0, + 186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0, + 206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 60, 0, 48, 84, + 86, 64,216, 0, 76,218, 0, 50, 0,220, 0,222, 78, 0, 30, 56, 0, 0, + 224, 10,226, 0, 66,228, 0, 28,234, 0, 44,230,232,114, 0, 0,236,238, + 0,246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256, + 262,264,266, 0,268,270, 0,272,274, 0, 72, 74, 0,278, 0,282, 0,280, + 284, 32, 0,286,288, 0, 0, 0,276,112, 88, 0, 0, 46, 0,292,294, 0, + 290, 68, 0,296, 0,335, 0, 52,168,360,330, 0,343,333,341,110, 96,102, + 100,104, 0, 0, 94, 0, 0,106,108, 0, 0, 0, 0, 0, 42, 0, 0, 80, + 92, 0, 84, 86, 0, 52,168, 35, 82, 0, 90, 0, 78, 88, 0, 35, 0, 35, + 97, 0, 52, 35, 0, 35,285, 0, 0, 0, 35, 4, 2, 0, 35,285, 0,118, + 120,122, 0,124,126, 0, 12,128, 0,116, 0, 0, 0, 0,136,138,140, 0, + 142,144, 0,148,150,152, 0,130,132,134, 0,146, 14,154, 0,156,158, 0, + 160,162, 0, 16,166, 0, 0, 20, 0,164, 18, 22, 0, 40, 0, 34, 0, 26, + 24, 0, 0, 0,168, 38, 0, 6, 0, 0,174,176, 0, 36,172, 0,186, 0, + 188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0,206, 0, + 208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 0, 48,216, 0, 50,218, + 220, 0, 30,222, 0,224, 10,226, 0, 0,228, 0, 28,234, 0, 44,230,232, + 0, 0,236,238, 0,246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, + 0,250, 0,256,262,264,266, 0,268,270, 0,272,274, 0, 0, 0,282, 0, + 280,284, 32, 0,286,288, 0, 0, 8, 0,276,278, 0, 0, 46, 0,292,294, + 0,290, 0,296, 0, 0, 0, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 42, 0, 0,118,120,122, 0,124,126, 0, 12,128, 0,116, 0, 0, + 0, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146, + 14,154, 0,156,158, 0,160,162, 0, 16,166, 0, 0, 20, 0,164, 18, 22, + 0, 40, 0, 34, 0, 26, 24, 0, 0, 0,168, 38, 0, 0, 0,174,176, 0, + 36,172, 0,186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196, + 182,202, 0,206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 0, + 48,216, 0, 50,218,220, 0, 30,222, 0,224, 10,226, 0, 0,228, 0, 28, + 234, 0, 44,230,232, 0, 0,236,238, 0,246,248, 0,252,254, 0,258,260, + 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272,274, + 0, 0, 0,282, 0,280,284, 32, 0,286,288, 0, 0, 0,276,278, 0, 0, + 46, 0,292,294, 0,290, 0,296, 0, 0, 0, 0, 0,170, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 42, 0, 0, 20, 18, 22, 0, 0, 6, 8, 0, 52, 0, + 4, 2, 0,118,120,122, 0,124,126, 0, 12,128, 0,116, 0, 0, 0, 0, + 136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146, 14,154, + 0,156,158, 0,160,162, 0, 16,166, 0, 0, 20, 0,164, 18, 22, 0, 40, + 0, 34, 0, 26, 24, 0, 0, 0,168, 38, 0, 6, 0, 0,174,176, 0, 36, + 172, 0,186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182, + 202, 0,206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 0, 48, + 216, 0, 50,218,220, 0, 30,222, 0,224, 10,226, 0, 0,228, 0, 28,234, + 0, 44,230,232, 0, 0,236,238, 0,246,248, 0,252,254, 0,258,260, 0, + 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272,274, 0, + 0, 0,282, 0,280,284, 32, 0,286,288, 0, 0, 8, 0,276,278, 0, 0, + 46, 0,292,294, 0,290, 0,296, 0,285, 0, 0, 0, 0,170, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 42, 0, 0,285, 0, 80, 92, 0, 84, 86, 0, 52, + 168, 35, 82, 0, 90, 0, 88, 0, 35,285, 0,118,120,122, 0,124,126, 0, + 116, 0, 0,128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132, + 134, 0,146,154, 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,174,176, + 0,172, 0,186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196, + 182,202, 0,206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 0, + 216, 0,218,220, 0,224,226, 0, 0,228, 0,230,232,234, 0,236,238, 0, + 246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262, + 264,266, 0,268,270, 0,272,274, 0, 0, 0,282, 0,280,284, 0,286,288, + 0, 0, 0,276,278, 0, 0, 0,292,294, 0,290, 0,296, 0, 0, 0, 0, + 0,168,170, 0, 0, 0, 0,222, 0, 0, 0, 0, 0, 0, 35,285, 0,350, + 339, 0,332, 0,337,352, 0,118,120,122, 0,124, 70,126, 0,116, 0, 0, + 128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146, + 154, 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, + 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198,200, 0,178,180, + 184, 0,196,182,202, 0,206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, + 0, 0, 60, 0, 64,216, 0, 76,218, 0, 0,220, 0, 56,222, 0,224,226, + 0, 66,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, 0,258, + 260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272, + 274, 0, 72, 74, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, + 0, 0,292,294, 0,290, 68, 0,296, 0,335,360,330, 0,343,333,341, 0, + 0, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35,285, + 0,118,120,122, 0,124,126, 0,116, 0, 0,128, 0,136,138,140, 0,142, + 144, 0,148,150,152, 0,130,132, 82,134, 0,146,154, 0,156,158, 0,160, + 162, 0, 0, 0,164,166, 0, 80, 92, 0,174,176, 0,172, 90, 0,186, 0, + 188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0,206, 0, + 208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 0, 84, 86,216, 0,218, + 220, 0,224,226, 0, 0,228, 0,230,232,234, 0,236,238, 0,246,248, 0, + 252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0, + 268,270, 0,272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0, + 276,278, 88, 0, 0, 0,292,294, 0,290, 0,296, 0, 52,168, 0, 0, 0, + 0,168, 0,170, 0, 0, 0, 0,222, 0, 0, 0, 0, 0, 0, 35,110, 96, + 102,100,104, 94,106,108, 0, 35, 96,100, 0, 35,110, 96,100, 94,114, 0, + 35, 96,100, 94,112, 0, 80, 92, 0, 84, 86, 0, 52,168, 82, 0, 90, 0, + 78, 88, 0,110, 96,102,100,104, 94,106,108, 0, 96,100, 0,110, 96,100, + 94,114, 0, 96,100, 94,112, 0,118,120,122, 0,124,126, 0,116, 0, 0, + 128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146, + 154, 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,174,176, 0,172, 0, + 186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0, + 206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 0,216, 0,218, + 220, 0,224,226, 0, 0,228, 0,230,232,234, 0,236,238, 0,246,248, 0, + 252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0, + 268,270, 0,272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0, + 276,278, 0, 0, 0,292,294, 0,290, 0,296, 0,285, 0, 0, 0,168,170, + 0, 0, 0, 0,222, 0, 0, 0, 0, 0, 0, 35,285, 0, 52, 0, 0, 52, + 285, 0, 35,285, 0,350,339, 0,332, 0,337,352, 0,335,360,330, 0,343, + 333,341, 0, 35,285, 0,330, 0, 0,168, 0,173, 0, 35,285, 0,350,339, + 0,332, 0,337,352, 0,118,120,122, 0,124, 70,126, 0,116, 0, 0,128, + 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146,154, + 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, 0, + 170, 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198,200, 0,178, + 180,184, 0,196,182,202, 0,206, 0,208,210, 0,204, 0, 0,212,214, 0, + 0, 0, 0, 60, 0, 64,216, 0, 76,218, 0, 0,220, 0, 56,222, 0,224, + 226, 0, 66,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, 0, + 258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0, + 272,274, 0, 72, 74, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, + 0, 0, 0,292,294, 0,290, 68, 0,296, 0,335,360,330, 0,343,333,341, + 0, 96, 0,100, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, + 0, 94, 0, 35,285, 0,350,339, 0,332, 0,337,352, 0, 58, 62, 0,170, + 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198,200, 0,178,180, + 184, 0,196,182,202, 0,206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, + 0, 0, 60, 0, 64,216, 0, 76,218, 0, 0,220, 0, 56,222, 0,224,226, + 0, 66,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, 0,258, + 260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272, + 274, 0, 72, 74, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, + 0, 0,292,294, 0,290, 68, 0,296, 0,335,360,330, 0,343,333,341, 96, + 100, 0, 94, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 80, 92, 0, + 84, 86, 0, 52,168, 82, 0, 90, 0, 88, 0,350,339, 0,332, 0,337,352, + 0,118,120,122, 0,124, 70,126, 0,116, 0, 0,128, 0,136,138,140, 0, + 142,144, 0,148,150,152, 0,130,132,134, 0,146,154, 0,156,158, 0,160, + 162, 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, 0,174,176, 0,172, 0, + 186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0, + 206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 60, 0, 64,216, + 0, 76,218, 0, 0,220, 0, 56,222, 0,224,226, 0, 66,228, 0,230,232, + 234, 0,236,238, 0,246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, + 0,250, 0,256,262,264,266, 0,268,270, 0,272,274, 0, 72, 74, 0,282, + 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, 0, 0,292,294, 0,290, + 68, 0,296, 0,335,360,330,285,343,333,341, 0, 0, 0, 0, 0,170, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,350,339, 0,332, 0,337,352, 0, + 118,120,122, 0,124, 70,126, 0,116, 0, 0,128, 0,136,138,140, 0,142, + 144, 0,148,150,152, 0,130,132,134, 0,146,154, 0,156,158, 0,160,162, + 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, 0,174,176, 0,172, 0,186, + 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0,206, + 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 60, 0, 64,216, 0, + 218,220, 0, 56,222, 0,224,226, 0, 66,228, 0,230,232,234, 0,236,238, + 0,246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256, + 262,264,266, 0,268,270, 0,272,274, 0, 72, 74, 0,282, 0,280,284, 0, + 286,288, 0, 0, 0,276,278, 0, 0, 0,292,294, 0,290, 68, 0,296, 0, + 335,330,285,343,333,341, 0, 0, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,339, 0,332, 0,337, 0,118,120,122, 0,124, 70,126, + 0,116, 0, 0,128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130, + 132,134, 0,146,154, 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,168, + 54, 0, 58, 62, 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198, + 200, 0,178,180,184, 0,196,182,202, 0,206, 0,208,210, 0,204, 0, 0, + 212,214, 0, 0, 0, 0, 60, 0, 64,216, 0,218,220, 0, 56,222, 0,224, + 226, 0, 66,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, 0, + 258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0, + 272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, + 0, 0,292,294, 0,290, 68, 0,296, 0,335,330,285,343,333,341, 0, 0, + 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,339, 0,332, + 0,337, 0,118,120,122, 0,124,126, 0,116, 0, 0,128, 0,136,138,140, + 0,142,144, 0,148,150,152, 0,130,132,134, 0,146,154, 0,156,158, 0, + 160,162, 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, 0,174,176, 0,172, + 0,186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, + 0,206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 60, 0, 64, + 216, 0,218,220, 0, 56,222, 0,224,226, 0, 66,228, 0,230,232,234, 0, + 236,238, 0,246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, + 0,256,262,264,266, 0,268,270, 0,272,274, 0, 0, 0,282, 0,280,284, + 0,286,288, 0, 0, 0,276,278, 0, 0, 0,292,294, 0,290, 68, 0,296, + 0,335,330,285,343,333,341, 0, 0, 0, 0, 0,170, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,339, 0,332, 0,337, 0,118,120,122, 0,124,126, + 0,116, 0, 0,128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130, + 132,134, 0,146,154, 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,168, + 54, 0, 58, 62, 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198, + 200, 0,178,180,184, 0,196,182,202, 0,206, 0,208,210, 0,204, 0, 0, + 212,214, 0, 0, 0, 0, 60, 0, 64,216, 0,218,220, 0, 56,222, 0,224, + 226, 0, 66,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, 0, + 258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0, + 272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, + 0, 0,292,294, 0,290, 0,296, 0,335,330,285,343,333,341, 0, 0, 0, + 0, 0,170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,339, 0,332, 0, + 337, 0, 58, 62, 0, 60, 64, 0,335,285,343,333,341, 54, 0, 0, 56, 0, + 330,285, 0, 35,285, 0,118,120,122, 0,124,126, 0,116, 0, 0,128, 0, + 136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146,154, 0, + 156,158, 0,160,162, 0, 0, 0,164,166, 0,174,176, 0,172, 0,186, 0, + 188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0,206, 0, + 208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 0,216, 0,218,220, 0, + 224,226, 0, 0,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, + 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, + 0,272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, + 0, 0, 0,292,294, 0,290, 0,296, 0,330, 0, 0, 0, 0,168,170, 0, + 0, 0, 0,222, 0, 0, 0, 0, 0, 0,330, 0, 35,285, 0, 0, 96,100, + 94, 98, 0, 82, 0, 80, 92, 0, 84, 86, 0, 52,168, 35,110, 96,102,100, + 104, 0, 94, 90,106,108, 78, 88, 0 +}; + +static const unsigned short ag_key_jmp[] = { + 0, 6, 9, 0, 13, 16, 0, 4, 20, 0, 0, 1, 7, 26, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 39, 41, 0, 37, 19, 23, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 0, 34, 38, 41, 46, 0, 0, 0, + 0, 0, 0, 0, 0, 49, 51, 0, 53, 0, 56, 0, 59, 0, 0, 56, 0, 69, + 0, 58, 61, 0, 73, 0, 0, 53, 71, 76, 0, 66, 0, 0, 0, 0, 83, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 92, 97, 0, 0, 0, + 0, 0, 0, 0, 0,108,110, 0, 0, 0, 0,116, 0,113,119, 71, 74, 0, + 76, 81, 83, 0, 85, 88, 0, 0, 0, 0, 0,133, 90, 0,100,104, 0, 92, + 95, 98,140, 0, 0, 0, 0, 0,110, 0, 0, 0, 0, 0, 0, 0,148, 0, + 106,108,151, 0,154,157,112,114, 0, 0, 0, 0, 0, 0, 0, 0,175, 0, + 0, 0,180, 0,121, 0, 0, 0, 0,172,178,116,118,182,186,124, 0, 0, + 0, 0,131,197,134, 0, 10, 0, 16, 29, 45, 62, 78, 63, 87,100,121,126, + 130,137,143,160,189,126,200, 0,145,148, 0,152,155, 0,227,159, 0,139, + 224,230,165,171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,183,185, 0,181,250,254,258, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,187, 0,190,266,270,273,193, 0, 0, 0, 0, + 0, 0, 0, 0,196,198, 0,286, 0,289, 0,292, 0, 0,203, 0,302, 0, + 0, 0,205,208, 0,308, 0, 0,200,304,306,311, 0,210, 0, 0, 0, 0, + 0,214,216, 0,218, 0, 0, 0, 0,328, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,336,338,343, 0, 0, 0, 0, 0, 0, 0, 0,354, + 356, 0, 0, 0, 0,362, 0,223,225, 0,359, 0,365,367, 0,227, 0,229, + 0, 0, 0, 0,231,379,236, 0, 0, 0, 0,238, 0,386, 0, 0, 0, 0, + 0,393,241, 0,253,257, 0,243,246,249,251,400, 0, 0, 0, 0, 0,263, + 0, 0, 0, 0, 0, 0, 0,409, 0,259,261,412, 0,415,418,265,267, 0, + 0, 0, 0, 0, 0, 0, 0,436, 0, 0,273, 0, 0, 0,444, 0,278, 0, + 0, 0, 0,433,269,439,271,442,275,446,450,281, 0, 0, 0, 0,288,291, + 463,293, 0,137,233, 0,176,179, 0,239,242,245,247,261, 0,277,295,313, + 319,322,325,332,346,370,382,389,397,403,421,453,283,466, 0,296, 0,306, + 309, 0,313,316, 0,506,320, 0,300,503,509,326,332, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,344,346, 0, + 342,529,533,537, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,348, 0, + 351,545,549,552,354, 0, 0, 0, 0, 0, 0, 0, 0,357,359, 0,565, 0, + 568, 0,571, 0, 0,364, 0,581, 0,366,369, 0,585, 0, 0,361,583, 0, + 588, 0,371, 0, 0, 0, 0, 0,375, 0,377, 0, 0, 0, 0,604, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,612,614,619, 0, 0, 0, + 0, 0, 0, 0, 0,630,632, 0, 0, 0, 0,638, 0,635, 0,641,382, 0, + 385, 0,387, 0, 0, 0, 0,389,652,394, 0, 0, 0, 0,396, 0,659, 0, + 0, 0, 0, 0,666,399, 0,411,415, 0,401,404,407,409,673, 0, 0, 0, + 0, 0,421, 0, 0, 0, 0, 0, 0, 0,682, 0,417,419,685, 0,688,691, + 423,425, 0, 0, 0, 0, 0, 0, 0, 0,709, 0, 0,429, 0, 0, 0,717, + 0,434, 0, 0, 0, 0,706,712,427,715,431,719,723,437, 0, 0, 0, 0, + 444,447,735,449, 0,298,512, 0,337,340, 0,518,521,524,526,540, 0,556, + 574,590,596,599,602,608,622,643,655,662,670,676,694,726,439,738, 0,461, + 0, 0, 0,467, 0, 0,452,455,457,773,465,776,469,472, 0,476, 0,478, + 0, 0, 0,480, 0, 0, 0, 0,797, 0,482,484,487, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,493,495, 0,491,809,813,816, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,497, 0,824,828,831,500, 0, 0, 0, 0, 0, + 0, 0, 0,503,505, 0,843, 0,846, 0,849, 0, 0,510, 0,859, 0,514, + 517, 0,863, 0, 0,507,861,512,866, 0, 0, 0, 0, 0,874, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,880,882,887, 0, 0, 0, 0, 0, + 0, 0, 0,898,900, 0, 0, 0, 0,906, 0,903,909,522,525, 0,527,532, + 534, 0,536,539, 0, 0, 0, 0, 0,923,541, 0,551,555, 0,543,546,549, + 930, 0, 0, 0, 0, 0,561, 0, 0, 0, 0, 0, 0, 0,938, 0,557,559, + 941, 0,944,947,563,565, 0, 0, 0, 0, 0, 0, 0, 0,965, 0, 0, 0, + 970, 0,574, 0, 0, 0, 0,962,567,968,569,571,972,976,577, 0, 0, 0, + 0,584,988,587, 0,806,819,835,852,868,519,877,890,911,916,920,927,933, + 950,979,579,991, 0, 0, 0, 0, 0, 0, 0, 0,592,594, 0,590,1013,1017, + 1020, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,596, 0,1028,1032, + 1035,599, 0, 0, 0, 0, 0, 0, 0, 0,602,604, 0,1047, 0,1050, 0, + 1053, 0, 0,609, 0,1063, 0,611,614, 0,1067, 0, 0,606,1065,1070, 0, + 0, 0, 0, 0,1077, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1083,1085,1090, 0, 0, 0, 0, 0, 0, 0, 0,1101,1103, 0, 0, 0, 0, + 1109, 0,1106,1112,619,622, 0,624,629,631, 0,633,636, 0, 0, 0, 0, + 0,1126,638, 0,648,652, 0,640,643,646,1133, 0, 0, 0, 0, 0,658, + 0, 0, 0, 0, 0, 0, 0,1141, 0,654,656,1144, 0,1147,1150,660,662, + 0, 0, 0, 0, 0, 0, 0, 0,1168, 0, 0, 0,1173, 0,669, 0, 0, + 0, 0,1165,1171,664,666,1175,1179,672, 0, 0, 0, 0,679,1190,682, 0, + 1023,1039,1056,1072,616,1080,1093,1114,1119,1123,1130,1136,1153,1182,674, + 1193, 0, 0, 0, 0, 0,1214,685,688, 0, 0, 0,691,694, 0, 0, 0, + 0, 0, 0, 0, 0,702,704, 0,700,1227,1231,1234, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,706, 0,1242,1246,1249,709, 0, 0, 0, 0, + 0, 0, 0, 0,712,714, 0,1261, 0,1264, 0,1267, 0, 0,719, 0,1277, + 0,723,726, 0,1281, 0, 0,716,1279,721,1284, 0, 0, 0, 0, 0,1292, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1298,1300,1305, 0, + 0, 0, 0, 0, 0, 0, 0,1316,1318, 0, 0, 0, 0,1324, 0,1321,1327, + 731,734, 0,736,741,743, 0,745,748, 0, 0, 0, 0, 0,1341,750, 0,760, + 764, 0,752,755,758,1348, 0, 0, 0, 0, 0,770, 0, 0, 0, 0, 0, 0, + 0,1356, 0,766,768,1359, 0,1362,1365,772,774, 0, 0, 0, 0, 0, 0, + 0, 0,1383, 0, 0, 0,1388, 0,783, 0, 0, 0, 0,1380,776,1386,778, + 780,1390,1394,786, 0, 0, 0, 0,793,1406,796, 0,698,1237,1253,1270, + 1286,728,1295,1308,1329,1334,1338,1345,1351,1368,1397,788,1409, 0,799, + 0,810, 0, 0, 0,816, 0, 0,801,804,806,1433,814,1436,818, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,822,1451,1455,824, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,827, 0,1463,1467,1470, 0, 0, 0, 0, + 0, 0, 0, 0,1481,1484, 0,830, 0, 0, 0, 0,1492, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1497,1499,1504, 0, 0, 0, 0, 0, + 0, 0, 0,1515,1517, 0, 0, 0, 0,1523, 0,1520,1526,838, 0,840,842, + 0, 0, 0, 0,1535,847, 0,849,852,854, 0, 0, 0, 0, 0,861, 0, 0, + 0, 0, 0, 0, 0,1545, 0,857,859,1548, 0,1551,1554,863,865, 0, 0, + 0, 0, 0, 0, 0, 0,1572, 0, 0, 0,1577, 0, 0, 0, 0, 0,1569, + 1575,867,869,1579,1582, 0, 0, 0, 0,872,1592,875, 0,1448,1458,1474, + 1487,833,835,1495,1507,1528,1532,844,1538,1541,1557,1585,1595, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 882,1627,1631,884, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,887, + 0,1640,1644,1647, 0, 0, 0, 0, 0, 0, 0, 0,1658,1661, 0,890, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1675, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,1680,1682,1687, 0, 0, 0, 0, 0, 0, 0, 0,1698, + 1700, 0, 0, 0, 0,1706, 0,1703, 0,1709, 0,896, 0, 0, 0, 0,1717, + 898, 0, 0,900, 0, 0, 0, 0,1726,902, 0,904,907,909, 0, 0, 0, 0, + 0,916, 0, 0, 0, 0, 0, 0, 0,1736, 0,912,914,1739, 0,1742,1745, + 918,920, 0, 0, 0, 0, 0, 0, 0, 0,1763, 0, 0, 0, 0,1769, 0, + 0, 0, 0, 0,1760,1766,922,924,1771,1774, 0, 0, 0, 0,927,930,1784, + 932, 0,878,880, 0,1616,1619,1622,1624,1635,1651,1664,1669,1672,893,1678, + 1690,1711,1720,1723,1729,1732,1748,1777,1787, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,938,1819,1823,940, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,943, 0,946,1831,1835,1838, 0, 0, 0, 0, 0, 0, 0, 0, + 1850,1853, 0,949, 0,954, 0, 0, 0, 0, 0,1864, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1870,1872,1877, 0, 0, 0, 0, 0, + 0, 0, 0,1888,1890, 0, 0, 0, 0,1896, 0,1893,1899, 0,961,963, 0, + 965,967, 0, 0, 0, 0,1910,972, 0,974,977,979, 0, 0, 0, 0, 0,986, + 0, 0, 0, 0, 0, 0, 0,1920, 0,982,984,1923, 0,1926,1929,988,990, + 0, 0, 0, 0, 0, 0, 0, 0,1947, 0, 0, 0,1952, 0, 0, 0, 0, + 0,1944,1950,992,994,997,1954,1957, 0, 0, 0, 0,1000,1968,1003, 0, + 0,935,1816,1826,1842,1856,952,1861,958,1867,1880,1901,1907,969,1913, + 1916,1932,1960,1971, 0,1006, 0, 0, 0, 0, 0, 0, 0, 0, 0,1008, + 0, 0, 0,1010, 0, 0, 0, 0,1012, 0,1015, 0, 0, 0,1017, 0,1026, + 0, 0, 0,1032, 0, 0,1019,1022,2022,1030,2025,1034,1037, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1041, 0, 0, 0, + 0,1044, 0, 0, 0, 0, 0, 0, 0, 0,1048,2060,2064,1050, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1053, 0,2072,2076,2079, 0, 0, 0, + 0, 0, 0, 0, 0,2090,2093, 0,1056, 0, 0, 0, 0,2101, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2106,2108,2113, 0, 0, 0, 0, + 0, 0, 0, 0,2124,2126, 0, 0, 0, 0,2132, 0,2129,2135,1064, 0, + 1066,1068, 0, 0, 0, 0,2144,1073, 0,1075,1078,1080, 0, 0, 0, 0, + 0,1087, 0, 0, 0, 0, 0, 0, 0,2154, 0,1083,1085,2157, 0,2160, + 2163,1089,1091, 0, 0, 0, 0, 0, 0, 0, 0,2181, 0, 0, 0,2186, 0, + 0, 0, 0, 0,2178,2184,1093,1095,2188,2191, 0, 0, 0, 0,1098,2201, + 1101, 0,1046,2067,2083,2096,1059,1061,2104,2116,2137,2141,1070,2147,2150, + 2166,2194,2204, 0, 0, 0, 0, 0,2225, 0, 0,1104, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,1106,1108, 0,2234,2237,2240,2242, 0, 0, + 0, 0, 0,2253, 0,1110, 0,1113, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1119,2274,2278,1121, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1124, 0,2287,2291,2294, 0, 0, + 0, 0, 0, 0, 0, 0,2305,2308, 0,1127, 0, 0, 0, 0, 0, 0, 0, + 1130, 0, 0, 0, 0,2324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,2329,2331,2336, 0, 0, 0, 0, 0, 0, 0, 0,2347,2349, 0, 0, + 0, 0,2355, 0,2352, 0,2358, 0,1132, 0, 0, 0, 0,2366,1134, 0, + 0,1136, 0, 0, 0, 0,2375,1138, 0,1140,1143,1145, 0, 0, 0, 0, + 0,1152, 0, 0, 0, 0, 0, 0, 0,2385, 0,1148,1150,2388, 0,2391, + 2394,1154,1156, 0, 0, 0, 0, 0, 0, 0, 0,2412, 0, 0, 0, 0,2418, + 0, 0, 0, 0, 0,2409,2415,1158,1160,2420,2423, 0, 0, 0, 0,1163, + 1166,2433,1168, 0,1115,1117, 0,2263,2266,2269,2271,2282, 0,2298,2311, + 2316,2319,2322,2327,2339,2360,2369,2372,2378,2381, 0,2397,2426,2436, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1175, 0, + 0, 0, 0,2485, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2490, + 2492,2497, 0, 0, 0, 0, 0, 0, 0, 0,2508,2510, 0, 0, 0, 0,2516, + 0,2513, 0,2519, 0,1177, 0, 0, 0, 0,2527,1179, 0, 0,1181, 0, + 0, 0, 0,2536,1183, 0,1185,1188,1190, 0, 0, 0, 0, 0,1197, 0, + 0, 0, 0, 0, 0, 0,2546, 0,1193,1195,2549, 0,2552,2555,1199,1201, + 0, 0, 0, 0, 0, 0, 0, 0,2573, 0, 0, 0, 0,2579, 0, 0, 0, + 0, 0,2570,2576,1203,1205,2581,2584, 0, 0, 0, 0,1208,1211,2594,1213, + 0,1171,1173, 0,2469,2472,2475,2477, 0, 0,2480,2483,2488,2500,2521, + 2530,2533,2539,2542, 0,2558,2587,2597, 0,1223, 0, 0, 0,1229, 0, 0, + 1216,1219,2625,1227,2628,1231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,1241,2647,2651,1243, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1246, 0,2660,2664,2667, 0, 0, 0, 0, 0, 0, + 0, 0,2678,2681, 0,1249, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2695, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2700,2702,2707, 0, + 0, 0, 0, 0, 0, 0, 0,2718,2720, 0, 0, 0, 0,2726, 0,2723, 0, + 2729, 0,1255, 0, 0, 0, 0,2737,1257, 0, 0,1259, 0, 0, 0, 0,2746, + 1261, 0,1263,1266,1268, 0, 0, 0, 0, 0,1275, 0, 0, 0, 0, 0, 0, + 0,2756, 0,1271,1273,2759, 0,2762,2765,1277,1279, 0, 0, 0, 0, 0, + 0, 0, 0,2783, 0, 0, 0, 0,2789, 0, 0, 0, 0, 0,2780,2786,1281, + 1283,2791,2794, 0, 0, 0, 0,1286,1289,2804,1291, 0,1235,1237, 0,1239, + 2639,2642,2644,2655,2671,2684,2689,2692,1252,2698,2710,2731,2740,2743, + 2749,2752,2768,2797,2807, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,1298,2844,2848,1300, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,1303, 0,2857,2861,2864, 0, 0, 0, 0, 0, 0, 0, 0, + 2875,2878, 0,1306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2892, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2897,2899,2904, 0, 0, 0, + 0, 0, 0, 0, 0,2915,2917, 0, 0, 0, 0,2923, 0,2920, 0,2926, 0, + 1312, 0,1314,1316, 0, 0,1318, 0, 0, 0, 0,2940,1320, 0,1322,1325, + 1327, 0, 0, 0, 0, 0,1334, 0, 0, 0, 0, 0, 0, 0,2950, 0,1330, + 1332,2953, 0,2956,2959,1336,1338, 0, 0, 0, 0, 0, 0, 0, 0,2977, + 0, 0, 0, 0,2983, 0, 0, 0, 0, 0,2974,2980,1340,1342,2985,2988, + 0, 0, 0, 0,1345,1348,2998,1350, 0,1294, 0,1296,2836,2839,2841,2852, + 2868,2881,2886,2889,1309,2895,2907,2928,2934,2937,2943,2946,2962,2991, + 3001, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1357, + 3035,3039,1359, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1362, 0, + 3048,3052,3055, 0, 0, 0, 0, 0, 0, 0, 0,3066,3069, 0,1365, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,3083, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,3088,3090,3095, 0, 0, 0, 0, 0, 0, 0, 0,3106, + 3108, 0, 0, 0, 0,3114, 0,3111, 0,3117, 0,1371, 0,1373,1375, 0, + 0,1377, 0, 0, 0, 0,3131,1379, 0,1381,1384,1386, 0, 0, 0, 0, + 0,1393, 0, 0, 0, 0, 0, 0, 0,3141, 0,1389,1391,3144, 0,3147, + 3150,1395,1397, 0, 0, 0, 0, 0, 0, 0, 0,3168, 0, 0, 0,3173, 0, + 0, 0, 0, 0,3165,3171,1399,1401,3175,3178, 0, 0, 0, 0,1404,1407, + 3188,1409, 0,1353, 0,1355,3029,3031,3033,3043,3059,3072,3077,3080,1368, + 3086,3098,3119,3125,3128,3134,3137,3153,3181,3191, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1416,3225,3229,1418, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1421, 0,3237,3241,3244, 0, 0, 0, 0, + 0, 0, 0, 0,3255,3258, 0,1424, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,3272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,3277,3279, + 3284, 0, 0, 0, 0, 0, 0, 0, 0,3295,3297, 0, 0, 0, 0,3303, 0, + 3300, 0,3306, 0,1430, 0,1432,1434, 0, 0,1436, 0, 0, 0, 0,3320, + 1438, 0,1440,1443,1445, 0, 0, 0, 0, 0,1452, 0, 0, 0, 0, 0, 0, + 0,3330, 0,1448,1450,3333, 0,3336,3339,1454,1456, 0, 0, 0, 0, 0, + 0, 0, 0,3357, 0, 0, 0,3362, 0, 0, 0, 0, 0,3354,3360,1458,1460, + 3364,3367, 0, 0, 0, 0,1463,1466,3377,1468, 0,1412, 0,1414,3219,3221, + 3223,3232,3248,3261,3266,3269,1427,3275,3287,3308,3314,3317,3323,3326, + 3342,3370,3380, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1475,3414,3418,1477, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1480, + 0,3426,3430,3433, 0, 0, 0, 0, 0, 0, 0, 0,3444,3447, 0,1483, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,3461, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,3466,3468,3473, 0, 0, 0, 0, 0, 0, 0, 0, + 3484,3486, 0, 0, 0, 0,3492, 0,3489, 0,3495, 0,1489, 0,1491,1493, + 0, 0,1495, 0, 0, 0, 0,3509,1497, 0,1499,1502,1504, 0, 0, 0, + 0, 0,1511, 0, 0, 0, 0, 0, 0, 0,3519, 0,1507,1509,3522, 0,3525, + 3528,1513,1515, 0, 0, 0, 0, 0, 0, 0, 0,3546, 0, 0, 0,3551, 0, + 0, 0, 0, 0,3543,3549,1517,1519,3553,3556, 0, 0, 0, 0,1522,3566, + 1525, 0,1471, 0,1473,3408,3410,3412,3421,3437,3450,3455,3458,1486,3464, + 3476,3497,3503,3506,3512,3515,3531,3559,3569, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1528,1530,3596,3598,3600,1532,3602,3605,1534, 0, + 0,1536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1538,3624,3628,1540, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1543, 0,3636,3640,3643, + 0, 0, 0, 0, 0, 0, 0, 0,3654,3657, 0,1546, 0, 0, 0, 0,3665, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,3670,3672,3677, 0, + 0, 0, 0, 0, 0, 0, 0,3688,3690, 0, 0, 0, 0,3696, 0,3693,3699, + 1554, 0,1556,1558, 0, 0, 0, 0,3708,1563, 0,1565,1568,1570, 0, 0, + 0, 0, 0,1577, 0, 0, 0, 0, 0, 0, 0,3718, 0,1573,1575,3721, 0, + 3724,3727,1579,1581, 0, 0, 0, 0, 0, 0, 0, 0,3745, 0, 0, 0,3750, + 0, 0, 0, 0, 0,3742,3748,1583,1585,3752,3755, 0, 0, 0, 0,1588, + 3765,1591, 0, 0,3621,3631,3647,3660,1549,1551,3668,3680,3701,3705,1560, + 3711,3714,3730,3758,3768, 0, 0, 0, 0, 0, 0,3792, 0, 0, 0, 0, + 0,1599, 0,1602, 0, 0, 0,1608, 0, 0,1594,1597, 0, 0,3801, 0, + 0,3803, 0,1606,3806, 0,1610,1613, 0 +}; + +static const unsigned short ag_key_index[] = { + 204, 0,471,204,501,743,204,204,779,789,789, 0, 0, 0,791,794,794,800, + 800,794,794,802,789,789,995,1197,1218,1222,1222,1222,1222,1224, 0, 0, + 1413,1431,789,1439,779,789,779,789,789,789,789,789,789,789,789,789,789, + 1599,1599,1439,789,779,779,1439,1792,779,789,779,1439,789,789,1975,789, + 0, 0, 0, 0,1599,779,1995,1599,779,1995,1599,2005,779,1599,1599,1599, + 779,779,1995,1599,789,1599,1599,1599,1599,1599,1599,1599,1599,1599,1599, + 1599,1599,1599,1599,2009,2009,1599,779,779,1995,1599,1995,1995,2016,1599, + 779,779,779,2005,779,779,779,779,779,779,779,779,779,779,779,779,779,779, + 2016,1995,779,1599,1599,1599,1599,2016,1995,2016,1599,779,779,779,779, + 779,779,779,1995,1599,1599,779,779,779,1599,779,1995,779,1995,1995,779, + 2028,2037,2028,2037,2046,2028,2028,2028,2037, 0,2049,2049,2028,2028,2037, + 2037,2037,2055,2028,2028,2028,2046,2028,2028,2028,2028,2028,2028,2028, + 2028,2028,2028,2028,2028,2028,2028,2055,2037,2028,2055,2037,2055,2028, + 2028,2028,2028,2028,2028,2028,2037,2028,2028,2028,2028,2037,2028,2037, + 2037,2028,2208,794,1222,789, 0,800,800,1431,789, 0,800,800,779,2028, + 2228,2231,779,2028,794,1222,794,1222,794,1222,794,1222,779,2028,779,2028, + 779,2028,800,800,800,779,2028,2028,2028,2028,779,2028,779,2028,2245,800, + 800, 0,800, 0,2256,789,2028,2028,204,2028,2037,2028,2037,2046,2028,2028, + 2028,2037, 0,2049,2049,2028,2028,2037,2037,2037,2055,2028,2028,2028,2046, + 2028,2028,2028,2028,2028,2028,2028,2028,2028,2028,2028,2028,2028,2028, + 2055,2037,2028,2055,2037,2055,2028,2028,2028,2028,2028,2028,2028,2037, + 2028,2028,2028,2028,2037,2028,2037,2037,2028,2208,2259,2261,2261,2256, + 0,2441, 0, 0,2261,1792,2467,1792,2602,789,789,789,789,789,789,789, + 1792,1792, 0, 0, 0, 0, 0, 0, 0,1439,2028,2631,2631,2631,2812,3006, + 3006,3196,3385,3573,3608,2028,1431,3618,3618,3618,2261,3618,3618,3618, + 3618, 0, 0,3772,1599,1599,1599,1599,1599,3790,3790,1599, 0,3795, 0, + 2261, 0, 0,2028,2028,2028,2028,2028,2028,2028, 0,1439,2631,1439,2631, + 2631,2631,2631,2028,2028,779,2028,779,2028,779,2028,779,2028,779,2028, + 2028,779,2028,2028,779,2028,2028,779,779,779,779,779,779,779,779,779,779, + 779,779,779,3790,2261,3618,3618,3618,3618,3790,3790, 0, 0, 0, 0, 0, + 0, 0, 0,2812,2631,2631,2631,2631,2631,2028,2028,2028,2028,2028,2028, + 2028,2028,2028,2028,2028,2028,3809,1222,2028,2028,2037,2028,2812,2812, + 3006,3006,3006,3006,3006,3006,3196,3196,3385,3385,1222,2028,2028,2037, + 2028 +}; + +static const unsigned char ag_key_ends[] = { +69,70,73,78,69,0, 83,69,0, 68,73,70,0, 69,70,0, 68,69,70,0, +67,76,85,68,69,0, 82,65,71,77,65,0, 78,68,69,70,0, 73,0, 71,0, +82,0, 76,76,0, 69,71,0, 71,0, 66,0, 83,69,0, 70,0, 82,78,0, +78,0, 76,84,0, 76,85,68,69,0, 78,75,0, 73,0, 67,76,73,66,0, +86,0, 73,0, 77,69,0, 80,0, 84,0, 71,69,0, 72,76,0, 80,0, +76,73,67,0, 72,0, 84,0, 77,0, 69,0, 67,0, 84,0, 77,0, +72,76,0, 76,78,0, 77,0, 73,84,76,69,0, 72,71,0, 72,76,0, 61,0, +69,70,73,78,69,0, 83,69,0, 68,73,70,0, 69,70,0, 68,69,70,0, +67,76,85,68,69,0, 82,65,71,77,65,0, 78,68,69,70,0, 92,39,0, 42,0, +73,0, 71,0, 82,0, 76,76,0, 73,76,0, 69,71,0, 71,0, 66,0, +83,69,0, 70,0, 82,78,0, 78,0, 79,79,82,0, 88,0, 84,0, +76,85,68,69,0, 75,0, 84,0, 71,0, 73,0, 67,76,73,66,0, 73,0, +77,69,0, 84,0, 71,69,0, 72,76,0, 80,0, 87,0, 76,73,67,0, 72,0, +84,0, 77,0, 69,0, 67,0, 84,0, 84,0, 77,0, 76,0, 82,84,0, +76,78,0, 77,0, 73,84,76,69,0, 72,71,0, 82,0, 72,76,0, 47,0, +61,0, 69,70,73,78,69,0, 83,69,0, 68,73,70,0, 69,70,0, +68,69,70,0, 67,76,85,68,69,0, 82,65,71,77,65,0, 78,68,69,70,0, +92,39,0, 42,0, 73,0, 71,0, 82,0, 76,76,0, 73,76,0, 69,71,0, +71,0, 66,0, 83,69,0, 70,0, 82,78,0, 78,0, 79,79,82,0, 84,0, +76,85,68,69,0, 78,75,0, 71,0, 73,0, 67,76,73,66,0, 73,0, +77,69,0, 84,0, 71,69,0, 72,76,0, 80,0, 87,0, 76,73,67,0, 72,0, +84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 76,0, 82,84,0, 76,78,0, +77,0, 73,84,76,69,0, 72,71,0, 82,0, 72,76,0, 92,39,0, 42,0, +69,73,76,0, 79,79,82,0, 80,0, 71,0, 79,84,0, 81,82,84,0, 42,0, +42,0, 42,0, 42,0, 69,88,0, 73,83,84,0, 73,0, 71,0, 82,0, +76,76,0, 69,71,0, 71,0, 66,0, 83,69,0, 70,0, 85,0, 82,78,0, +78,0, 76,84,0, 78,75,0, 73,0, 67,76,73,66,0, 86,0, 73,0, +77,69,0, 80,0, 84,0, 71,69,0, 72,76,0, 80,0, 76,73,67,0, 72,0, +84,0, 77,0, 69,0, 67,0, 84,0, 84,0, 77,0, 72,76,0, 76,78,0, +77,0, 73,84,76,69,0, 72,71,0, 72,76,0, 73,0, 71,0, 82,0, +76,76,0, 69,71,0, 71,0, 66,0, 83,69,0, 70,0, 82,78,0, 78,0, +76,84,0, 78,75,0, 73,0, 67,76,73,66,0, 86,0, 73,0, 77,69,0, +80,0, 84,0, 71,69,0, 72,76,0, 80,0, 76,73,67,0, 72,0, 84,0, +77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, 76,78,0, 77,0, +73,84,76,69,0, 72,71,0, 72,76,0, 81,85,0, 69,84,0, 69,88,0, +73,83,84,0, 47,0, 73,0, 71,0, 82,0, 76,76,0, 69,71,0, 71,0, +66,0, 83,69,0, 70,0, 85,0, 82,78,0, 78,0, 76,84,0, 78,75,0, +73,0, 67,76,73,66,0, 86,0, 73,0, 77,69,0, 80,0, 84,0, 71,69,0, +72,76,0, 80,0, 76,73,67,0, 72,0, 84,0, 77,0, 69,0, 67,0, +84,0, 84,0, 77,0, 72,76,0, 76,78,0, 77,0, 73,84,76,69,0, +72,71,0, 72,76,0, 47,0, 92,39,0, 42,0, 69,73,76,0, 79,79,82,0, +80,0, 71,0, 81,82,84,0, 73,0, 72,82,0, 76,76,0, 85,66,0, 73,0, +76,84,0, 73,0, 86,0, 73,0, 79,80,0, 84,0, 72,76,0, 80,0, +83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, +72,71,0, 72,76,0, 61,0, 42,0, 73,0, 72,82,0, 76,76,0, 85,66,0, +76,84,0, 73,0, 73,0, 80,0, 84,0, 72,76,0, 80,0, 83,72,0, +84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, 72,71,0, 82,0, +72,76,0, 92,39,0, 73,0, 72,82,0, 76,76,0, 73,76,0, 85,66,0, +73,0, 79,79,82,0, 76,84,0, 71,0, 73,0, 86,0, 73,0, 79,80,0, +84,0, 72,76,0, 80,0, 83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, +77,0, 72,76,0, 82,84,0, 72,71,0, 72,76,0, 42,0, 42,0, 42,0, +83,87,0, 42,0, 80,0, 92,39,0, 69,73,76,0, 79,79,82,0, 80,0, +71,0, 79,84,0, 81,82,84,0, 83,87,0, 80,0, 47,0, 73,0, 72,82,0, +76,76,0, 85,66,0, 73,0, 76,84,0, 73,0, 86,0, 73,0, 79,80,0, +84,0, 72,76,0, 80,0, 83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, +77,0, 72,76,0, 72,71,0, 72,76,0, 47,0, 61,0, 42,0, 92,39,0, +39,0, 61,0, 42,0, 73,0, 72,82,0, 76,76,0, 85,66,0, 84,0, +73,0, 73,0, 80,0, 84,0, 72,76,0, 80,0, 83,72,0, 84,0, 77,0, +69,0, 67,0, 84,0, 77,0, 72,76,0, 72,71,0, 82,0, 72,76,0, +61,0, 42,0, 84,0, 73,0, 73,0, 80,0, 84,0, 72,76,0, 80,0, +83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, +72,71,0, 82,0, 72,76,0, 92,39,0, 69,73,76,0, 79,79,82,0, 80,0, +71,0, 81,82,84,0, 61,0, 42,0, 47,0, 73,0, 72,82,0, 76,76,0, +85,66,0, 76,84,0, 73,0, 73,0, 80,0, 84,0, 72,76,0, 80,0, +83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, +72,71,0, 82,0, 72,76,0, 61,0, 47,0, 73,0, 72,82,0, 76,76,0, +85,66,0, 76,84,0, 73,0, 86,0, 73,0, 80,0, 84,0, 72,76,0, +80,0, 83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, +72,71,0, 82,0, 72,76,0, 61,0, 47,0, 73,0, 72,82,0, 76,76,0, +85,66,0, 76,84,0, 73,0, 86,0, 73,0, 80,0, 84,0, 72,76,0, +80,0, 83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, +72,71,0, 82,0, 72,76,0, 61,0, 47,0, 73,0, 72,82,0, 76,76,0, +85,66,0, 76,84,0, 73,0, 86,0, 73,0, 80,0, 84,0, 72,76,0, +80,0, 83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, +72,71,0, 82,0, 72,76,0, 61,0, 47,0, 73,0, 72,82,0, 76,76,0, +85,66,0, 76,84,0, 73,0, 86,0, 73,0, 80,0, 84,0, 72,76,0, +80,0, 83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, +72,71,0, 72,76,0, 61,0, 47,0, 81,0, 69,0, 47,0, 73,0, +72,82,0, 76,76,0, 85,66,0, 73,0, 76,84,0, 73,0, 86,0, 73,0, +79,80,0, 84,0, 72,76,0, 80,0, 83,72,0, 84,0, 77,0, 69,0, +67,0, 84,0, 77,0, 72,76,0, 72,71,0, 72,76,0, 92,39,0, 42,0, +73,76,0, 79,79,82,0, 80,0, 71,0, 79,84,0, 81,82,84,0, +}; +#define AG_TCV(x) (((int)(x) >= -1 && (int)(x) <= 255) ? ag_tcv[(x) + 1] : 0) + +static const unsigned short ag_tcv[] = { + 26, 26,472,472,472,472,472,472,472,472, 1,288,472,472,472,472,472,472, + 472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, 1,361,473, + 472,474,358,348,475,365,364,356,354,287,355,476,357,477,478,478,478,478, + 478,478,478,479,479,472,286,480,472,481,472,472,482,482,482,482,482,482, + 483,483,483,483,483,483,483,484,483,483,483,485,483,486,483,483,483,487, + 483,483,472,488,472,346,489,472,482,482,482,482,482,482,483,483,483,483, + 483,483,483,484,483,483,483,485,483,486,483,483,483,487,483,483,472,344, + 472,363,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490, + 490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490, + 490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490, + 490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490, + 490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490, + 490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490, + 490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490, + 490,490,490,490,490 +}; + +#ifndef SYNTAX_ERROR +#define SYNTAX_ERROR fprintf(stderr,"%s, line %d, column %d\n", \ + (PCB).error_message, (PCB).line, (PCB).column) +#endif + +#ifndef FIRST_LINE +#define FIRST_LINE 1 +#endif + +#ifndef FIRST_COLUMN +#define FIRST_COLUMN 1 +#endif + +#ifndef PARSER_STACK_OVERFLOW +#define PARSER_STACK_OVERFLOW {fprintf(stderr, \ + "\nParser stack overflow, line %d, column %d\n",\ + (PCB).line, (PCB).column);} +#endif + +#ifndef REDUCTION_TOKEN_ERROR +#define REDUCTION_TOKEN_ERROR {fprintf(stderr, \ + "\nReduction token error, line %d, column %d\n", \ + (PCB).line, (PCB).column);} +#endif + + +typedef enum + {ag_accept_key, ag_set_key, ag_jmp_key, ag_end_key, ag_no_match_key, + ag_cf_accept_key, ag_cf_set_key, ag_cf_end_key} key_words; + +#ifndef GET_INPUT +#define GET_INPUT ((PCB).input_code = getchar()) +#endif + + +static int ag_look_ahead(void) { + if ((PCB).rx < (PCB).fx) { + return CONVERT_CASE((PCB).lab[(PCB).rx++]); + } + GET_INPUT; + (PCB).fx++; + return CONVERT_CASE((PCB).lab[(PCB).rx++] = (PCB).input_code); +} + +static void ag_get_key_word(int ag_k) { + int save_index = (PCB).rx; + const unsigned char *sp; + int ag_ch; + while (1) { + switch (ag_key_act[ag_k]) { + case ag_cf_end_key: + sp = ag_key_ends + ag_key_jmp[ag_k]; + do { + if ((ag_ch = *sp++) == 0) { + int ag_k1 = ag_key_parm[ag_k]; + int ag_k2 = ag_key_pt[ag_k1]; + if (ag_key_itt[ag_k2 + ag_look_ahead()]) goto ag_fail; + (PCB).rx--; + (PCB).token_number = (a85parse_token_type) ag_key_pt[ag_k1 + 1]; + return; + } + } while (ag_look_ahead() == ag_ch); + goto ag_fail; + case ag_end_key: + sp = ag_key_ends + ag_key_jmp[ag_k]; + do { + if ((ag_ch = *sp++) == 0) { + (PCB).token_number = (a85parse_token_type) ag_key_parm[ag_k]; + return; + } + } while (ag_look_ahead() == ag_ch); + case ag_no_match_key: +ag_fail: + (PCB).rx = save_index; + return; + case ag_cf_set_key: { + int ag_k1 = ag_key_parm[ag_k]; + int ag_k2 = ag_key_pt[ag_k1]; + ag_k = ag_key_jmp[ag_k]; + if (ag_key_itt[ag_k2 + (ag_ch = ag_look_ahead())]) break; + save_index = --(PCB).rx; + (PCB).token_number = (a85parse_token_type) ag_key_pt[ag_k1+1]; + break; + } + case ag_set_key: + save_index = (PCB).rx; + (PCB).token_number = (a85parse_token_type) ag_key_parm[ag_k]; + case ag_jmp_key: + ag_k = ag_key_jmp[ag_k]; + ag_ch = ag_look_ahead(); + break; + case ag_accept_key: + (PCB).token_number = (a85parse_token_type) ag_key_parm[ag_k]; + return; + case ag_cf_accept_key: { + int ag_k1 = ag_key_parm[ag_k]; + int ag_k2 = ag_key_pt[ag_k1]; + if (ag_key_itt[ag_k2 + ag_look_ahead()]) (PCB).rx = save_index; + else { + (PCB).rx--; + (PCB).token_number = (a85parse_token_type) ag_key_pt[ag_k1+1]; + } + return; + } + } + while (ag_key_ch[ag_k] < ag_ch) ag_k++; + if (ag_key_ch[ag_k] != ag_ch) { + (PCB).rx = save_index; + return; + } + } +} + + +#ifndef AG_NEWLINE +#define AG_NEWLINE 10 +#endif + +#ifndef AG_RETURN +#define AG_RETURN 13 +#endif + +#ifndef AG_FORMFEED +#define AG_FORMFEED 12 +#endif + +#ifndef AG_TABCHAR +#define AG_TABCHAR 9 +#endif + +static void ag_track(void) { + int ag_k = 0; + while (ag_k < (PCB).rx) { + int ag_ch = (PCB).lab[ag_k++]; + switch (ag_ch) { + case AG_NEWLINE: + (PCB).column = 1, (PCB).line++; + case AG_RETURN: + case AG_FORMFEED: + break; + case AG_TABCHAR: + (PCB).column += (TAB_SPACING) - ((PCB).column - 1) % (TAB_SPACING); + break; + default: + (PCB).column++; + } + } + ag_k = 0; + while ((PCB).rx < (PCB).fx) (PCB).lab[ag_k++] = (PCB).lab[(PCB).rx++]; + (PCB).fx = ag_k; + (PCB).rx = 0; +} + + +static void ag_prot(void) { + int ag_k = 128 - ++(PCB).btsx; + if (ag_k <= (PCB).ssx) { + (PCB).exit_flag = AG_STACK_ERROR_CODE; + PARSER_STACK_OVERFLOW; + return; + } + (PCB).bts[(PCB).btsx] = (PCB).sn; + (PCB).bts[ag_k] = (PCB).ssx; + (PCB).vs[ag_k] = (PCB).vs[(PCB).ssx]; + (PCB).ss[ag_k] = (PCB).ss[(PCB).ssx]; +} + +static void ag_undo(void) { + if ((PCB).drt == -1) return; + while ((PCB).btsx) { + int ag_k = 128 - (PCB).btsx; + (PCB).sn = (PCB).bts[(PCB).btsx--]; + (PCB).ssx = (PCB).bts[ag_k]; + (PCB).vs[(PCB).ssx] = (PCB).vs[ag_k]; + (PCB).ss[(PCB).ssx] = (PCB).ss[ag_k]; + } + (PCB).token_number = (a85parse_token_type) (PCB).drt; + (PCB).ssx = (PCB).dssx; + (PCB).sn = (PCB).dsn; + (PCB).drt = -1; +} + + +static const unsigned short ag_tstt[] = { +489,487,486,485,484,483,482,474,471,470,469,468,467,466,465,464,463,462,461, + 460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444,443, + 442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426,425, + 424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408,407, + 406,405,404,403,402,400,399,398,397,396,395,394,393,392,391,390,389,388, + 387,386,385,384,383,382,381,379,329,328,327,326,324,322,321,320,319,318, + 317,316,315,314,313,312,311,310,309,308,307,304,303,302,301,300,299,296, + 294,291,288,287,286,285,85,35,1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,1,0,37, +35,1,0,2,282, +489,487,486,485,484,483,482,474,471,470,469,468,467,466,465,464,463,462,461, + 460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444,443, + 442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426,425, + 424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408,407, + 406,405,404,403,402,400,399,398,397,396,395,394,393,392,391,390,389,388, + 387,386,385,384,383,382,381,379,329,328,327,326,324,322,321,320,319,318, + 317,316,315,314,313,312,311,310,309,308,307,304,303,302,301,300,299,296, + 294,291,288,287,286,285,85,35,1,0,22,23,24,25,39,40, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,38,1,0, +1,0, +489,487,486,485,484,483,482,474,471,470,469,468,467,466,465,464,463,462,461, + 460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444,443, + 442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426,425, + 424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408,407, + 406,405,404,403,402,400,399,398,397,396,395,394,393,392,391,390,389,388, + 387,386,385,384,383,382,381,379,329,328,327,326,324,322,321,320,319,318, + 317,316,315,314,313,312,311,310,309,308,307,304,303,302,301,300,299,296, + 294,291,288,287,286,285,85,35,0,2,4,12,27,28,32,33,34,41,43,44,45,48,49, + 50,51,52,53,57,84,289,298, +489,487,486,485,484,483,482,474,471,470,469,468,467,466,465,464,463,462,461, + 460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444,443, + 442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426,425, + 424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408,407, + 406,405,404,403,402,400,399,398,397,396,395,394,393,392,391,390,389,388, + 387,386,385,384,383,382,381,379,329,328,327,326,324,322,321,320,319,318, + 317,316,315,314,313,312,311,310,309,308,307,304,303,302,301,300,299,296, + 294,291,288,287,286,285,85,35,26,1,0,23,24,39,40, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 372,371,370,369,368,367,366,365,364,363,362,361,358,357,356,355,354,348, + 346,344,288,287,286,168,85,35,1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,1,0,30,31, + 33,34,89,90,92,94,95,120,123,126,134,135,137,139,140,143,145,148,149, + 162,163,164,165,167,170,171,172,174,277,278,279,280,281, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,1,0,30,31, + 33,34,89,90,92,94,95,120,123,126,134,135,137,139,140,143,145,148,149, + 162,163,164,165,167,170,171,172,174,277,278,279,280,281, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,1,0,30,31, + 33,34,89,90,92,94,95,120,123,126,134,135,137,139,140,143,145,148,149, + 162,163,164,165,167,170,171,172,174,277,278,279,280,281, +489,487,486,485,484,483,482,479,478,477,474,97,35,1,0,2,87,282,283,284, +489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, +288,287,286,285,35,1,0,2,282,283,284, +288,287,286,285,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, +297,295,35,1,0,2,282,283,284, +480,473,35,1,0,2,282,283,284, +489,488,487,486,485,484,483,482,480,479,478,477,476,473,357,35,1,0,2,282, + 283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 329,328,327,326,324,322,321,320,319,318,317,316,315,314,313,312,311,310, + 309,308,307,306,305,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 329,328,327,326,324,322,321,320,319,318,317,316,315,314,313,312,311,310, + 309,308,307,0,58,59,60,61,62,63,65,66,68,69,70,71,72,73,75,76,77,78,79, + 80,81,82,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198, + 199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234, + 235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252, + 253,254,255,256,257,258,259,261,262,263,264,265,266,267,268,269,270,271, + 272,273,274,275,276, +313,312,311,306,305,0,54,56,62,63,65, +489,487,486,485,484,483,482,474,85,0,4,84,298, +489,487,486,485,484,483,482,474,85,0,4,84,298, +489,487,486,485,484,483,482,474,85,0,4,84,298, +489,487,486,485,484,483,482,474,85,0,4,84,298, +297,295,0,46,47, +480,473,0,11,13,14,15,290,292, +489,488,487,486,485,484,483,482,480,479,478,477,476,473,357,0,11,13,14,15, + 20,290,292,293, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 329,328,327,326,324,322,321,320,319,318,317,316,315,314,313,312,311,310, + 309,308,307,306,305,288,287,286,285,0,54,56, +288,287,286,285,0,27,28,33,34,42, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 372,371,370,369,368,367,366,365,364,363,361,358,357,356,355,354,348,346, + 344,288,287,286,168,85,35,1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 372,371,370,369,368,367,366,365,364,363,362,361,358,357,356,355,354,348, + 346,344,288,287,286,168,85,35,1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 372,371,370,369,368,367,366,365,364,363,362,361,358,357,356,355,354,348, + 346,344,288,287,286,168,85,35,1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381, + 379,365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,285,35, + 1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381, + 379,365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,285,35, + 1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 372,371,370,369,368,367,366,365,364,363,361,358,357,356,355,354,348,346, + 344,288,287,286,168,85,35,1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 372,371,370,369,368,367,366,365,364,363,362,361,358,357,356,355,354,348, + 346,344,288,287,286,168,85,35,1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 372,371,370,369,368,367,366,365,364,363,362,361,358,357,356,355,354,348, + 346,344,288,287,286,168,85,35,1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 372,371,370,369,368,367,366,365,364,363,361,358,357,356,355,354,348,346, + 344,288,287,286,168,85,35,1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381, + 379,365,364,363,361,360,359,358,357,356,355,354,353,352,351,350,349,348, + 347,346,345,344,343,342,341,340,339,338,337,336,335,334,333,332,331,330, + 288,287,286,285,35,1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 372,371,370,369,368,367,366,365,364,363,362,361,358,357,356,355,354,348, + 346,344,288,287,286,168,85,35,1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 372,371,370,369,368,367,366,365,364,363,362,361,358,357,356,355,354,348, + 346,344,288,287,286,168,85,35,1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 372,371,370,369,368,367,366,365,364,363,361,358,357,356,355,354,348,346, + 344,288,287,286,168,85,35,1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381, + 379,372,371,370,369,368,367,366,365,364,363,361,358,357,356,355,354,348, + 346,344,288,287,286,285,168,85,35,1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, + 282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,287,286,1,0,33,34,89,90, + 92,94,95,120,123,126,134,135,137,139,140,143,145,148,149,162,163,164, + 165,167,170,171,172,174,277,278,279,280,281, +288,0,32, +288,0,32, +288,0,32, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +375,374,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +478,477,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +378,377,376,375,374,35,1,0,2,282,283,284, +378,377,376,375,374,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, +378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, +376,375,374,180,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +375,374,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +376,375,374,180,35,1,0,2,282,283,284, +378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +376,375,374,180,35,1,0,2,282,283,284, +378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, +376,375,374,180,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, +378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +378,376,375,374,178,177,176,175,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +378,376,375,374,178,177,176,175,1,0,39,40, +375,374,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +378,376,375,374,178,177,176,175,1,0,39,40, +478,477,1,0,39,40, +378,377,376,375,374,1,0,39,40, +378,377,376,375,374,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +378,376,375,374,178,177,176,175,1,0,39,40, +378,376,375,374,178,177,176,175,1,0,39,40, +378,376,375,374,178,177,176,175,1,0,39,40, +376,375,374,180,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +375,374,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +376,375,374,180,1,0,39,40, +378,376,375,374,178,177,176,175,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +376,375,374,180,1,0,39,40, +378,376,375,374,178,177,176,175,1,0,39,40, +376,375,374,180,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +378,376,375,374,178,177,176,175,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +378,376,375,374,178,177,176,175,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +378,376,375,374,178,177,176,175,1,0,39,40, +378,376,375,374,178,177,176,175,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,1,0,39,40, +489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,474,85,0,4,84,298, +489,488,487,486,485,484,483,482,479,478,477,476,357,35,1,0,2,282,283,284, +489,488,487,486,485,484,483,482,479,478,477,476,357,0,20,293, +288,287,286,285,35,1,0,2,282,283,284, +288,287,286,285,35,1,0,2,282,283,284, +1,0,39, +475,473,35,1,0,2,282,283,284, +475,473,0,11,13,19,21,290,323, +288,287,286,285,35,1,0,2,282,283,284, +288,287,286,285,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,74,84,98,118, + 119,122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154, + 155,156,298,325,373, +489,487,486,485,484,483,482,474,288,287,286,285,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,474,85,0,4,84,298, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,474,85,0,4,84,298, +489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,474,85,0,4,67,84,298, +489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,474,85,0,4,67,84,298, +489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,474,85,0,4,67,84,298, +489,487,486,485,484,483,482,479,478,477,476,475,474,473,372,371,370,369,368, + 367,366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,473,372,371,370,369,368, + 367,366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,11,13,16,18,19,21, + 55,64,84,118,119,122,125,128,133,136,138,143,144,145,146,147,148,150, + 151,152,153,154,155,156,290,298,323,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,473,372,371,370,369,368, + 367,366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,473,372,371,370,369,368, + 367,366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,11,13,16,18,19,21, + 55,64,84,118,119,122,125,128,133,136,138,143,144,145,146,147,148,150, + 151,152,153,154,155,156,290,298,323,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +288,287,286,285,35,1,0,2,282,283,284, +288,287,286,285,35,1,0,2,282,283,284, +288,287,286,285,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,473,372,371,370,369,368, + 367,366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,11,13,16,18,19,21, + 55,64,84,118,119,122,125,128,133,136,138,143,144,145,146,147,148,150, + 151,152,153,154,155,156,290,298,323,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,473,372,371,370,369,368, + 367,366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,11,13,16,18,19,21, + 55,64,84,118,119,122,125,128,133,136,138,143,144,145,146,147,148,150, + 151,152,153,154,155,156,290,298,323,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,474,364,361,360,358,357,356,355,354, + 352,350,348,346,344,343,341,339,337,335,333,332,330,288,287,286,285,35, + 1,0,2,87,282,283,284, +288,287,286,285,35,1,0,2,282,283,284, +288,287,286,285,35,1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,472,365, + 364,363,361,358,357,356,355,354,348,346,344,287,286,1,0, +288,287,286,285,35,1,0,2,282,283,284, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,287,286,1,0, +330,288,287,286,285,35,1,0,2,282,283,284, +489,488,487,486,485,484,483,482,479,478,477,476,357,288,287,286,35,1,0,2, + 282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,474,471,470,469,468,467,466,465,464,463,462,461, + 460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444,443, + 442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426,425, + 424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408,407, + 406,405,404,403,402,400,399,398,397,396,395,394,393,392,391,390,389,388, + 387,386,385,384,383,382,381,379,329,328,327,326,324,322,321,320,319,318, + 317,316,315,314,313,312,311,310,309,308,307,304,303,302,301,300,299,296, + 294,291,288,287,286,285,85,35,26,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +378,376,375,374,178,177,176,175,0,5,380, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +378,376,375,374,178,177,176,175,0,5,380, +375,374,0,158,160,183, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +378,376,375,374,178,177,176,175,0,5,380, +478,477,0,164,278, +378,377,376,375,374,0,157,158,160,179,181,182, +378,377,376,375,374,0,157,158,160,179,181,182, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +378,376,375,374,178,177,176,175,0,5,380, +378,376,375,374,178,177,176,175,0,5,380, +378,376,375,374,178,177,176,175,0,5,380, +376,375,374,180,0,6,401, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +375,374,0,158,160,183, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +376,375,374,180,0,6,401, +378,376,375,374,178,177,176,175,0,5,380, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +376,375,374,180,0,6,401, +378,376,375,374,178,177,176,175,0,5,380, +376,375,374,180,0,6,401, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +378,376,375,374,178,177,176,175,0,5,380, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +378,376,375,374,178,177,176,175,0,5,380, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +378,376,375,374,178,177,176,175,0,5,380, +378,376,375,374,178,177,176,175,0,5,380, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,0,143,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198, + 199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234, + 235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252, + 253,254,255,256,257,258,259,261,262,263,264,265,266,267,268,269,270,271, + 272,273,274,275,276, +479,478,477,475,355,354,168,1,0,3,7,8,16,18,325, +489,488,487,486,485,484,483,482,481,480,479,478,477,476,474,473,472,365,364, + 363,361,358,357,356,355,354,348,346,344,288,287,286,173,1,0,17, +489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472,365, + 364,363,361,358,357,356,355,354,348,346,344,288,287,286,173,1,0,17, +330,288,287,286,285,35,1,0,2,282,283,284, +479,478,477,0, +487,0, +479,478,477,0, +479,478,477,0, +489,488,487,486,485,484,483,482,481,480,479,478,477,476,474,473,472,365,364, + 363,361,358,357,356,355,354,348,346,344,288,287,286,173,1,0,17, +479,478,477,0, +482,479,478,477,376,0, +482,479,478,477,0, +489,482,479,478,477,476,474,376,375,374,159,0, +365,35,1,0,2,282,283,284, +365,35,1,0,2,282,283,284, +365,35,1,0,2,282,283,284, +365,35,1,0,2,282,283,284, +365,35,1,0,2,282,283,284, +365,35,1,0,2,282,283,284, +365,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 364,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346,345, + 344,343,342,341,340,339,338,337,336,335,334,333,332,331,330,288,287,286, + 285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 364,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346,345, + 344,343,342,341,340,339,338,337,336,335,334,333,332,331,330,288,287,286, + 285,35,1,0,2,282,283,284, +365,0,148, +365,0,148, +365,0,148, +365,0,148, +365,0,148, +365,0,148, +365,0,148, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,355,354,168,85,0,3,4,7,8,9,10,16,18,84,138,146,147,148,150,151, + 152,153,154,155,156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,355,354,168,85,0,3,4,7,8,9,10,16,18,84,138,146,147,148,150,151, + 152,153,154,155,156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,355,354,168,85,0,3,4,7,8,9,10,16,18,84,138,146,147,148,150,151, + 152,153,154,155,156,298,325,373, +360,359,358,357,356,0,137,139,140,141,142, +355,354,0,134,135, +353,352,351,350,0,129,130,131,132, +349,348,0,126,127, +347,346,0,123,124, +345,344,0,120,121, +343,342,341,340,339,338,337,336,335,334,333,332,331,0,99,100,101,102,103, + 104,105,106,107,108,109,110,111,112,113,114,115,116,117, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +288,287,286,285,1,0,39,40, +330,288,287,286,285,1,0,39,40, +330,288,287,286,285,1,0,39,40, +330,288,287,286,285,1,0,39,40, +489,488,487,486,485,484,483,482,481,480,479,478,477,476,474,473,472,365,364, + 363,361,358,357,356,355,354,348,346,344,288,287,286,173,1,0,17, +330,288,287,286,285,1,0,39,40, +330,288,287,286,285,1,0,39,40, +330,288,287,286,285,1,0,39,40, +330,288,287,286,285,1,0,39,40, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,1,0, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,1,0, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,330,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +330,1,0,39,40, +330,1,0,39,40, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 361,288,287,286,285,35,1,0,2,282,283,284, +287,1,0,39,40, +489,482,479,478,477,474,376,375,374,159,0, +488,486,485,484,477,475,0, +489,488,487,486,485,484,483,482,481,480,479,478,477,476,474,473,472,365,364, + 363,361,358,357,356,355,354,348,346,344,288,287,286,173,1,0,17, +482,479,478,477,0, +475,0, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +364,0,149, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, +330,0,83, +489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472,365, + 364,363,361,358,357,356,355,354,348,346,344,288,287,286,173,1,0,17, +330,0,83, +330,0,83, +330,0,83, +330,0,83, +330,0,83, +330,0,83, +287,0,34, +364,0,149, +364,0,149, +364,0,149, +364,0,149, +364,0,149, +364,0,149, +364,0,149, +471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, + 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, + 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, + 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, + 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, + 364,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346,345, + 344,343,342,341,340,339,338,337,336,335,334,333,332,331,330,288,287,286, + 285,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,355,354,168,85,0,3,4,7,8,9,10,16,18,84,138,146,147,148,150,151, + 152,153,154,155,156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,355,354,168,85,0,3,4,7,8,9,10,16,18,84,138,146,147,148,150,151, + 152,153,154,155,156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,355,354,168,85,0,3,4,7,8,9,10,16,18,84,138,146,147,148,150,151, + 152,153,154,155,156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,355,354,168,85,0,3,4,7,8,9,10,16,18,84,138,146,147,148,150,151, + 152,153,154,155,156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,355,354,168,85,0,3,4,7,8,9,10,16,18,84,138,146,147,148,150,151, + 152,153,154,155,156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,133,136,138, + 143,144,145,146,147,148,150,151,152,153,154,155,156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,133,136,138, + 143,144,145,146,147,148,150,151,152,153,154,155,156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,128,133,136, + 138,143,144,145,146,147,148,150,151,152,153,154,155,156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,128,133,136, + 138,143,144,145,146,147,148,150,151,152,153,154,155,156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,128,133,136, + 138,143,144,145,146,147,148,150,151,152,153,154,155,156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,128,133,136, + 138,143,144,145,146,147,148,150,151,152,153,154,155,156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,125,128,133, + 136,138,143,144,145,146,147,148,150,151,152,153,154,155,156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,125,128,133, + 136,138,143,144,145,146,147,148,150,151,152,153,154,155,156,298,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,122,125,128, + 133,136,138,143,144,145,146,147,148,150,151,152,153,154,155,156,298,325, + 373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,122,125,128, + 133,136,138,143,144,145,146,147,148,150,151,152,153,154,155,156,298,325, + 373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,119,122,125, + 128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155,156,298, + 325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,119,122,125, + 128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155,156,298, + 325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,473,378,376,375,374,372, + 371,370,369,368,367,366,365,363,362,361,355,354,178,177,176,175,168,85, + 35,1,0,2,282,283,284, +489,487,486,485,484,483,482,474,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,473,372,371,370,369,368, + 367,366,365,363,362,361,355,354,168,85,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +378,376,375,374,178,177,176,175,1,0,39,40, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,1,0,39,40, +360,359,358,357,356,0,137,139,140,141,142, +360,359,358,357,356,0,137,139,140,141,142, +355,354,0,134,135, +355,354,0,134,135, +355,354,0,134,135, +355,354,0,134,135, +353,352,351,350,0,129,130,131,132, +353,352,351,350,0,129,130,131,132, +349,348,0,126,127, +349,348,0,126,127, +347,346,0,123,124, +347,346,0,123,124, +489,487,486,485,484,483,482,474,85,0,4,84,298, +489,487,486,485,484,483,482,479,478,477,476,475,474,473,372,371,370,369,368, + 367,366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,11,13,16,18,19,21, + 55,84,118,119,122,125,128,133,136,138,143,144,145,146,147,148,150,151, + 152,153,154,155,156,290,298,323,325,373, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, +378,376,375,374,178,177,176,175,0,5,380, +489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, + 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, + 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, + 156,298,325,373, + +}; + + +static unsigned const char ag_astt[19815] = { + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,8,7,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,9,5,3,3,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,0,1,1,1,1,1,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,3,9,7,9,5,2,2,2,2,2, + 2,2,2,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,1,1,1,1,1,1,1,1,1,3,1,1,1,2,1,7,3,1,1,3,1,3,1,1,1,1,1,1,1,1,2,2,1, + 1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,3,1,7,3,3,1,1,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,8,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,8,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,7,1,2,1,1,3,5,5,5,5,5, + 5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1,1,7,1,1,1, + 3,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5, + 1,1,7,1,1,1,3,5,5,1,1,7,1,1,1,3,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,2,2,2,1,1,1,1,1,1,1, + 1,1,1,2,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,2, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,2,1,1,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,1,1,2,2,2,1,1,2,1,1,2,1,1,2,1,1,1,1,1,7,1,1, + 1,1,1,2,2,2,2,2,2,2,2,2,7,2,1,1,2,2,2,2,2,2,2,2,2,7,2,1,1,2,2,2,2,2,2,2,2, + 2,7,2,1,1,2,2,2,2,2,2,2,2,2,7,2,1,1,1,1,7,2,2,2,2,7,2,1,2,1,1,1,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,7,2,1,2,1,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,5,5,5,5,7,1,1,1,1,1,1,7,3,1,1, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, + 5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5, + 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7, + 1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,5,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,7,3,3,7,3,3,7,3,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1, + 5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5, + 1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5, + 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, + 5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1, + 1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,1,5,7, + 1,1,1,3,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, + 5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7, + 1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7, + 1,1,1,3,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5, + 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1, + 1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1, + 3,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, + 5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7, + 1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5, + 5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, + 5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, + 5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1, + 1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7, + 1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, + 5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,1,7,1,1,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,1,7,1,1,8, + 8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, + 8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8, + 8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, + 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8, + 8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1, + 7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,5,5,5,5,1,7,1,1,5,5,5,5,5,5,5,5,5,1,1,7,1, + 1,1,3,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2, + 2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1,5,7,1,1,1,3, + 1,4,1,5,5,1,1,7,1,1,1,3,1,2,7,2,1,1,2,1,1,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1, + 1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7, + 1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1, + 2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5, + 5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,4,2,1,1,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2, + 2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,7,2,1,1,1, + 5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5, + 5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1,1,7,1,1,1,3,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2, + 2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1, + 1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2, + 1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,2,1,1,3,5,5,5,5,1,1,7,1,1,1,3,5,5,5, + 5,1,1,7,1,1,1,3,10,10,1,10,10,10,10,10,10,2,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,7,5,5,5,5,1,1,7,1,1,1,3,10,10,1,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,3,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,7,5,5,5,5,5,1,5,7,1,1,1,3,10,10,10,10,10,10,10,10,10,10,10, + 10,10,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1, + 2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,5,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,1,1,7,2,2,2,2,2,2,2,2,2,2,2,2, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2, + 1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 2,2,2,7,2,1,1,1,7,2,2,1,1,1,1,1,7,2,2,2,2,2,2,1,1,1,1,1,7,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,7,1,1,2,2, + 2,2,2,2,2,2,7,1,1,2,2,2,2,7,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1, + 1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,2,2,2,2,2,2,2,2,2,2,2,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1, + 2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, + 2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7, + 2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1, + 1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,7,2, + 1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,7,2,1,2,2,2, + 2,2,2,2,2,7,2,1,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1, + 2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, + 2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7, + 2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,7,2, + 1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,5,3,3,1,1,1,1,1,1,2,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,2,2, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,2,1,1,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,1,2,1,1,1,2,2,2,1,1,2,1,1,2,1,1,2,2,2,1,1,1,1,2,9,7, + 2,1,1,2,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,7,2,5,5,5,5,5,1,5,7,1,1,1,3,2,2,2,7,1,4,2,2,2,7,2,2,2,7,2,1,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,10,10,10,5,10, + 10,10,10,2,7,10,10,10,10,4,9,2,10,10,10,2,9,2,2,2,2,4,5,1,1,7,1,1,1,3,5,1, + 1,7,1,1,1,3,5,1,1,7,1,1,1,3,5,1,1,7,1,1,1,3,5,1,1,7,1,1,1,3,5,1,1,7,1,1,1, + 3,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7, + 1,1,7,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2, + 2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1, + 2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2, + 2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2, + 7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1, + 5,1,1,1,1,1,1,5,1,1,1,1,1,1,5,1,1,1,1,5,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,1,7,1,2,8,4,4,4,4,1,7,1,1,8,4,4,4,4,1,7,1, + 1,8,4,4,4,4,1,7,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,7,1,8,5,5,5,5,1,7,1,1,8,5,5,5,5,1,7,1,1,8,5,5,5,5,1,7,1,1,8, + 5,5,5,5,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,3,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,3,2,2,2,7,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7, + 1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,1,7,1, + 1,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,1, + 7,1,1,9,2,10,10,10,9,2,2,2,2,4,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,7,2,7,2,2,2,2,2,2,2,2,2, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2, + 1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, + 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1, + 1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, + 1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1, + 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1, + 1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,1,7,1,2,1,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,4,1,1,4,1,1,4, + 1,1,4,1,1,7,1,1,7,1,1,7,1,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, + 2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1, + 2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1, + 2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2, + 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1, + 2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,1,1,1,1,1,4,1,1,1,1,1,1, + 1,1,1,1,4,1,1,1,1,1,1,1,4,1,1,1,1,4,1,1,1,1,4,1,1,1,1,4,1,1,1,1,1,1,4,1,1, + 1,1,1,1,1,1,4,1,1,1,1,1,1,4,1,1,1,1,4,1,1,1,1,4,1,1,1,1,4,1,1,2,2,2,2,2,2, + 2,2,2,7,2,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7, + 2,2,1,1,2,1,2,1,2,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2, + 1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 7,2,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2, + 1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1 +}; + + +static const unsigned short ag_pstt[] = { +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,0,2,2,2,3, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,4, +1,541,543,541,541, +6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,5,3,0,7,7,7,5,6, +13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,14,13,4, +16,18, +82,82,82,82,82,82,82,82,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25, + 25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25, + 25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25, + 25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25, + 25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,15, + 16,17,18,19,20,21,22,23,22,8,9,10,81,1,6,23,26,34,21,13,22,12,11,35,33, + 32,31,30,29,34,35,28,27,25,14,24,14, +6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,4,5,7,3,3,5,6, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,1,542,8,2,2,2,546, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,9,2,2, + 2,545, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,10,2, + 2,2,544, +36,39,41,42,43,44,45,46,47,48,49,50,51,52,54,60,63,64,66,59,58,37,65,62,53, + 57,55,56,61,40,38,68,8,9,67,11,67,68,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, +36,39,41,42,43,44,45,46,47,48,49,50,51,52,54,60,63,64,66,59,58,37,65,62,53, + 57,55,56,61,40,38,69,8,9,67,12,67,69,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, +36,39,41,42,43,44,45,46,47,48,49,50,51,52,54,60,63,64,66,59,58,37,65,62,53, + 57,55,56,61,40,38,70,8,9,67,13,67,70,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, +83,83,83,83,83,83,83,84,84,84,83,100,1,2,14,2,84,2,2,557, +542,542,542,542,542,542,542,542,542,1,2,15,2,2,2,563, +542,542,542,542,542,542,542,542,542,1,2,16,2,2,2,562, +542,542,542,542,1,2,17,2,2,2,561, +542,542,542,542,1,2,18,2,2,2,560, +542,542,542,542,542,542,542,542,542,1,2,19,2,2,2,559, +542,542,542,542,542,542,542,542,542,1,2,20,2,2,2,558, +542,542,1,2,21,2,2,2,555, +542,542,1,2,22,2,2,2,553, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,2,23,2,2,2, + 550, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,24,2,2,2,548, +71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, + 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114, + 115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132, + 133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150, + 151,152,153,154,155,156,157,158,159,160,161,222,224,226,227,229,231,232, + 233,235,237,239,241,243,245,247,249,251,253,254,255,256,25,257,45,46,47, + 252,250,248,246,244,242,240,238,236,234,62,63,230,228,68,225,223,221, + 221,220,219,218,217,216,215,223,214,213,212,227,228,211,210,209,208,207, + 206,205,204,237,203,202,201,241,242,243,244,200,199,198,197,196,195,194, + 193,192,191,190,189,188,187,186,185,184,183,182,181,180,266,179,178,177, + 270,176,175,174,274,173,172,277,278,279,280,281,282,283,284,285,286,287, + 288,289,290,171,292,170,169,168,296,297,298,167,166,301,165,164,304,163, + 162,307, +247,249,251,261,263,26,264,262,260,259,258, +82,82,82,82,82,82,82,82,81,27,37,265,265, +82,82,82,82,82,82,82,82,81,28,36,265,265, +82,82,82,82,82,82,82,82,81,29,33,265,265, +82,82,82,82,82,82,82,82,81,30,32,265,265, +266,267,31,30,31, +96,91,32,28,270,29,268,271,269, +85,85,85,85,85,85,85,85,96,85,85,85,85,91,85,33,25,270,26,268,27,271,269, + 272, +43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,261,263,24,24,24,24,34,274, + 273, +275,8,9,10,35,20,13,12,11,19, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,36,2, + 2,2,749, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,1,542,37,2,2,2,622, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,1,542,38,2,2,2,603, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,39,2, + 2,2,748, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,1,542,40,2,2,2,605, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,41,2, + 2,2,747, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,42,2, + 2,2,746, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,43,2, + 2,2,745, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,44,2, + 2,2,744, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,45,2, + 2,2,743, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,46,2, + 2,2,742, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,47,2, + 2,2,741, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,48,2, + 2,2,740, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,49,2, + 2,2,739, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,50,2, + 2,2,738, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1, + 542,51,2,2,2,737, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1, + 542,52,2,2,2,736, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,1,542,53,2,2,2,616, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,54,2, + 2,2,735, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,1,542,55,2,2,2,614, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,1,542,56,2,2,2,613, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,1,542,57,2,2,2,615, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,1,542,58,2,2,2,623, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,1,542,59,2,2,2,624, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,60,2, + 2,2,734, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,1,542,61,2,2,2,607, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,1,542,62,2,2,2,617, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,63,2, + 2,2,733, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,64,2, + 2,2,732, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,1,542,65,2,2,2,620, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,66,2, + 2,2,731, +36,39,41,42,43,44,45,46,47,48,49,50,51,52,54,60,63,64,66,59,58,37,65,62,53, + 57,55,56,61,40,38,8,9,6,8,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6, +11,68,11, +10,69,10, +9,70,9, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,71,2,2,2,730, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,72,2,2,2,729, +542,542,542,542,542,542,542,542,1,542,73,2,2,2,728, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,74,2,2,2,727, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,75,2,2,2,726, +542,542,542,542,542,542,542,542,1,542,76,2,2,2,725, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,77,2,2,2,724, +542,542,1,542,78,2,2,2,723, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,79,2,2,2,722, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,80,2,2,2,721, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,81,2,2,2,720, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,82,2,2,2,719, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,83,2,2,2,718, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,84,2,2,2,717, +542,542,542,542,542,542,542,542,1,542,85,2,2,2,716, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,86,2,2,2,715, +542,542,1,542,87,2,2,2,714, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,88,2,2,2,713, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,89,2,2,2,712, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,90,2,2,2,711, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,91,2,2,2,710, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,92,2,2,2,709, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,93,2,2,2,708, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,94,2,2,2,707, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,95,2,2,2,706, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,96,2,2,2,705, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,97,2,2,2,704, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,98,2,2,2,703, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,99,2,2,2,702, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,100,2,2,2,701, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,101,2,2,2,700, +542,542,542,542,542,1,542,102,2,2,2,699, +542,542,542,542,542,1,542,103,2,2,2,698, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,104,2,2,2,697, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,105,2,2,2,696, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,106,2,2,2,695, +542,542,542,542,542,542,542,542,1,542,107,2,2,2,694, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,108,2,2,2,693, +542,542,542,542,542,542,542,542,1,542,109,2,2,2,692, +542,542,542,542,542,542,542,542,1,542,110,2,2,2,691, +542,542,542,542,1,542,111,2,2,2,690, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,112,2,2,2,689, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,113,2,2,2,688, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,114,2,2,2,687, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,115,2,2,2,686, +542,542,1,542,116,2,2,2,685, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,117,2,2,2,684, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,118,2,2,2,683, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,119,2,2,2,682, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,120,2,2,2,681, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,121,2,2,2,680, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,122,2,2,2,679, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,123,2,2,2,678, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,124,2,2,2,677, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,125,2,2,2,676, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,126,2,2,2,675, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,127,2,2,2,674, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,128,2,2,2,673, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,129,2,2,2,672, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,130,2,2,2,671, +542,542,542,542,1,542,131,2,2,2,670, +542,542,542,542,542,542,542,542,1,542,132,2,2,2,669, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,133,2,2,2,668, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,134,2,2,2,667, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,135,2,2,2,666, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,136,2,2,2,665, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,137,2,2,2,664, +542,542,542,542,1,542,138,2,2,2,663, +542,542,542,542,542,542,542,542,1,542,139,2,2,2,662, +542,542,542,542,1,542,140,2,2,2,661, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,141,2,2,2,659, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,142,2,2,2,658, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,143,2,2,2,657, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,144,2,2,2,656, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,145,2,2,2,655, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,146,2,2,2,654, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,147,2,2,2,653, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,148,2,2,2,652, +542,542,542,542,542,542,542,542,1,542,149,2,2,2,651, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,150,2,2,2,650, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,151,2,2,2,649, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,152,2,2,2,648, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,153,2,2,2,647, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,154,2,2,2,646, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,155,2,2,2,645, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,156,2,2,2,644, +542,542,542,542,542,542,542,542,1,542,157,2,2,2,643, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,158,2,2,2,642, +542,542,542,542,542,542,542,542,1,542,159,2,2,2,641, +542,542,542,542,542,542,542,542,1,542,160,2,2,2,640, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,161,2,2,2,638, +276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276, + 276,276,276,276,276,276,276,276,276,5,162,5,276, +277,277,277,277,277,277,277,277,5,163,5,277, +278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278, + 278,278,278,278,278,278,278,278,278,5,164,5,278, +279,279,279,279,279,279,279,279,5,165,5,279, +280,280,5,166,5,280, +281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281, + 281,281,281,281,281,281,281,281,281,5,167,5,281, +282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282, + 282,282,282,282,282,282,282,282,282,5,168,5,282, +283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283, + 283,283,283,283,283,283,283,283,283,5,169,5,283, +284,284,284,284,284,284,284,284,5,170,5,284, +285,285,5,171,5,285, +286,286,286,286,286,5,172,5,286, +287,287,287,287,287,5,173,5,287, +288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288, + 288,288,288,288,288,288,288,288,288,5,174,5,288, +289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289, + 289,289,289,289,289,289,289,289,289,5,175,5,289, +290,290,290,290,290,290,290,290,5,176,5,290, +291,291,291,291,291,291,291,291,5,177,5,291, +292,292,292,292,292,292,292,292,5,178,5,292, +293,293,293,293,5,179,5,293, +294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294, + 294,294,294,294,294,294,294,294,294,5,180,5,294, +295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295, + 295,295,295,295,295,295,295,295,295,5,181,5,295, +296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296, + 296,296,296,296,296,296,296,296,296,5,182,5,296, +297,297,5,183,5,297, +298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298, + 298,298,298,298,298,298,298,298,298,5,184,5,298, +299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299, + 299,299,299,299,299,299,299,299,299,5,185,5,299, +300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300, + 300,300,300,300,300,300,300,300,300,5,186,5,300, +301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301, + 301,301,301,301,301,301,301,301,301,5,187,5,301, +302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302, + 302,302,302,302,302,302,302,302,302,5,188,5,302, +303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303, + 303,303,303,303,303,303,303,303,303,5,189,5,303, +304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304, + 304,304,304,304,304,304,304,304,304,5,190,5,304, +305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305, + 305,305,305,305,305,305,305,305,305,5,191,5,305, +306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306, + 306,306,306,306,306,306,306,306,306,5,192,5,306, +307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307, + 307,307,307,307,307,307,307,307,307,5,193,5,307, +308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, + 308,308,308,308,308,308,308,308,308,5,194,5,308, +309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309, + 309,309,309,309,309,309,309,309,309,5,195,5,309, +310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310, + 310,310,310,310,310,310,310,310,310,5,196,5,310, +311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311, + 311,311,311,311,311,311,311,311,311,5,197,5,311, +312,312,312,312,5,198,5,312, +313,313,313,313,313,313,313,313,5,199,5,313, +314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314, + 314,314,314,314,314,314,314,314,314,5,200,5,314, +315,315,315,315,5,201,5,315, +316,316,316,316,316,316,316,316,5,202,5,316, +317,317,317,317,5,203,5,317, +318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, + 318,318,318,318,318,318,318,318,318,5,204,5,318, +319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319, + 319,319,319,319,319,319,319,319,319,5,205,5,319, +320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320, + 320,320,320,320,320,320,320,320,320,5,206,5,320, +321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, + 321,321,321,321,321,321,321,321,321,5,207,5,321, +322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322, + 322,322,322,322,322,322,322,322,322,5,208,5,322, +323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323, + 323,323,323,323,323,323,323,323,323,5,209,5,323, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, + 324,324,324,324,324,324,324,324,324,5,210,5,324, +325,325,325,325,325,325,325,325,5,211,5,325, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326, + 326,326,326,326,326,326,326,326,326,5,212,5,326, +327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, + 327,327,327,327,327,327,327,327,327,5,213,5,327, +328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328, + 328,328,328,328,328,328,328,328,328,5,214,5,328, +329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329, + 329,329,329,329,329,329,329,329,329,5,215,5,329, +330,330,330,330,330,330,330,330,5,216,5,330, +331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331, + 331,331,331,331,331,331,331,331,331,5,217,5,331, +332,332,332,332,332,332,332,332,5,218,5,332, +333,333,333,333,333,333,333,333,5,219,5,333, +334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334, + 334,334,334,334,334,334,334,334,334,5,220,5,334, +335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, + 335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, + 335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, + 335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, + 335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, + 335,17,17,17,17,5,221,5,335, +542,542,542,542,542,542,542,542,542,1,2,222,2,2,2,588, +82,82,82,82,82,82,82,82,81,223,70,265,265, +542,542,542,542,542,542,542,542,542,542,542,542,542,1,2,224,2,2,2,587, +85,85,85,85,85,85,85,85,85,85,85,85,85,225,69,272, +542,542,542,542,1,2,226,2,2,2,586, +542,542,542,542,1,542,227,2,2,2,585, +336,67,336, +542,542,1,2,229,2,2,2,583, +337,91,230,65,270,338,64,271,339, +542,542,542,542,1,2,231,2,2,2,581, +542,542,542,542,1,2,232,2,2,2,580, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,233,2,2,2,579, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,234,161,151,347,348,162,345,163,346,376,378, + 265,377,375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363, + 362,361,360,359,358,265,357,356, +542,542,542,542,542,542,542,542,542,542,542,542,542,1,2,235,2,2,2,578, +82,82,82,82,82,82,82,82,81,59,60,265,265, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,237,2,2,2,577, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,238,161,151,347,348,162,345,163,346,58,265,375, + 374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360, + 359,358,265,357,356, +542,542,542,542,542,542,542,542,542,1,2,239,2,2,2,576, +82,82,82,82,82,82,82,82,81,240,57,265,265, +542,542,542,542,542,542,542,542,542,1,2,241,2,2,2,575, +82,82,82,82,82,82,82,82,81,242,78,379,265,265, +542,542,542,542,542,542,542,542,542,1,2,243,2,2,2,574, +82,82,82,82,82,82,82,82,81,244,78,380,265,265, +542,542,542,542,542,542,542,542,542,1,2,245,2,2,2,573, +82,82,82,82,82,82,82,82,81,246,78,381,265,265, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,1,2,247,2,2,2,572, +82,82,82,82,82,82,82,173,173,341,340,382,82,91,349,350,351,352,353,354,355, + 59,37,365,65,342,343,182,81,248,161,151,347,348,162,345,72,270,163,346, + 338,383,74,383,265,375,374,373,372,371,370,370,370,369,368,367,150,370, + 366,364,363,362,361,360,359,358,271,265,339,357,356, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,1,2,249,2,2,2,571, +82,82,82,82,82,82,82,173,173,341,340,382,82,91,349,350,351,352,353,354,355, + 59,37,365,65,342,343,182,81,250,161,151,347,348,162,345,72,270,163,346, + 338,384,74,384,265,375,374,373,372,371,370,370,370,369,368,367,150,370, + 366,364,363,362,361,360,359,358,271,265,339,357,356, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,251,2,2,2,570, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,252,161,151,347,348,162,345,163,346,49,265,375, + 374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360, + 359,358,265,357,356, +542,542,542,542,1,2,253,2,2,2,569, +542,542,542,542,1,2,254,2,2,2,568, +542,542,542,542,1,2,255,2,2,2,567, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,256,2,2,2,566, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,257,161,151,347,348,162,345,163,346,44,265,375, + 374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360, + 359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,382,82,91,349,350,351,352,353,354,355, + 59,37,365,65,342,343,182,81,258,161,151,347,348,162,345,72,270,163,346, + 338,385,74,385,265,375,374,373,372,371,370,370,370,369,368,367,150,370, + 366,364,363,362,361,360,359,358,271,265,339,357,356, +82,82,82,82,82,82,82,173,173,341,340,382,82,91,349,350,351,352,353,354,355, + 59,37,365,65,342,343,182,81,259,161,151,347,348,162,345,72,270,163,346, + 338,386,74,386,265,375,374,373,372,371,370,370,370,369,368,367,150,370, + 366,364,363,362,361,360,359,358,271,265,339,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,260,161,151,347,348,162,345,163,346,48,265,375, + 374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360, + 359,358,265,357,356, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,261,2,2,2,565, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,262,161,151,347,348,162,345,163,346,39,265,375, + 374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360, + 359,358,265,357,356, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,263,2,2,2,564, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,264,161,151,347,348,162,345,163,346,38,265,375, + 374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360, + 359,358,265,357,356, +83,83,83,83,83,83,83,84,84,84,83,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,2,265,2, + 84,2,2,557, +542,542,542,542,1,2,266,2,2,2,556, +542,542,542,542,1,2,267,2,2,2,554, +97,97,387,97,97,97,97,97,97,95,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, + 97,97,97,97,97,97,97,97,268, +542,542,542,542,1,2,269,2,2,2,551, +92,92,388,92,92,92,92,92,92,92,92,92,92,92,92,92,92,90,92,92,92,92,92,92,92, + 92,92,92,92,92,92,92,92,92,270, +542,542,542,542,542,1,542,271,2,2,2,549, +86,86,86,86,86,86,86,86,86,86,86,86,86,542,542,542,1,2,272,2,2,2,552, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,273,161,151,347,348,162,345,163,346,41,265,375, + 374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360, + 359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,274,161,151,347,348,162,345,163,346,40,265,375, + 374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360, + 359,358,265,357,356, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,1,542,542,275,2,2,2,547, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,276,161,151,347,348,162,345,163,346,306,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +202,199,197,195,201,200,198,196,277,305,389, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,278,161,151,347,348,162,345,163,346,303,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +202,199,197,195,201,200,198,196,279,302,389, +390,391,280,212,213,300, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,281,161,151,347,348,162,345,163,346,299,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,282,161,151,347,348,162,345,163,346,295,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,283,161,151,347,348,162,345,163,346,294,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +202,199,197,195,201,200,198,196,284,293,389, +51,52,285,291,291, +392,393,394,390,391,286,209,207,208,211,276,210, +392,393,394,390,391,287,209,207,208,211,275,210, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,288,161,151,347,348,162,345,163,346,273,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,289,161,151,347,348,162,345,163,346,272,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +202,199,197,195,201,200,198,196,290,271,389, +202,199,197,195,201,200,198,196,291,395,389, +202,199,197,195,201,200,198,196,292,396,389, +205,204,203,206,293,398,397, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,294,161,151,347,348,162,345,163,346,265,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,295,161,151,347,348,162,345,163,346,264,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,296,161,151,347,348,162,345,163,346,263,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +390,391,297,212,213,262, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,298,161,151,347,348,162,345,163,346,261,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,299,161,151,347,348,162,345,163,346,260,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,300,161,151,347,348,162,345,163,346,259,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,301,161,151,347,348,162,345,163,346,258,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,302,161,151,347,348,162,345,163,346,257,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,303,161,151,347,348,162,345,163,346,256,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,304,161,151,347,348,162,345,163,346,255,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,305,161,151,347,348,162,345,163,346,254,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,306,161,151,347,348,162,345,163,346,253,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,307,161,151,347,348,162,345,163,346,252,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,308,161,151,347,348,162,345,163,346,251,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,309,161,151,347,348,162,345,163,346,250,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,310,161,151,347,348,162,345,163,346,249,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,311,161,151,347,348,162,345,163,346,248,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +205,204,203,206,312,247,397, +202,199,197,195,201,200,198,196,313,246,389, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,314,161,151,347,348,162,345,163,346,245,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +205,204,203,206,315,240,397, +202,199,197,195,201,200,198,196,316,239,389, +205,204,203,206,317,238,397, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,318,161,151,347,348,162,345,163,346,236,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,319,161,151,347,348,162,345,163,346,235,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,320,161,151,347,348,162,345,163,346,234,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,321,161,151,347,348,162,345,163,346,233,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,322,161,151,347,348,162,345,163,346,232,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,323,161,151,347,348,162,345,163,346,231,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,324,161,151,347,348,162,345,163,346,230,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +202,199,197,195,201,200,198,196,325,229,389, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,326,161,151,347,348,162,345,163,346,226,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,327,161,151,347,348,162,345,163,346,225,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,328,161,151,347,348,162,345,163,346,224,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,329,161,151,347,348,162,345,163,346,222,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +202,199,197,195,201,200,198,196,330,221,389, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,331,161,151,347,348,162,345,163,346,220,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +202,199,197,195,201,200,198,196,332,219,389, +202,199,197,195,201,200,198,196,333,218,389, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,334,161,151,347,348,162,345,163,346,217,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, + 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114, + 115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132, + 133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150, + 151,152,153,154,155,156,157,158,159,160,161,65,71,215,216,220,219,218, + 217,216,215,223,214,213,212,227,228,211,210,209,208,207,206,205,204,237, + 203,202,201,241,242,243,244,200,199,198,197,196,195,194,193,192,191,190, + 189,188,187,186,185,184,183,182,181,180,266,179,178,177,270,176,175,174, + 274,173,172,277,278,279,280,281,282,283,284,285,286,287,288,289,290,171, + 292,170,169,168,296,297,298,167,166,301,165,164,304,163,162,307, +173,173,341,344,342,343,182,16,336,66,347,399,163,346,357, +183,400,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, + 183,183,183,183,183,183,183,183,183,183,183,183,183,189,183,337,401, +183,400,183,183,183,183,183,183,183,183,183,183,183,183,87,183,183,183,183, + 183,183,183,183,183,183,183,183,183,183,183,183,183,183,189,183,338,89, +542,542,542,542,542,1,542,339,2,2,2,582, +193,193,193,340, +402,173, +172,172,172,342, +171,171,171,343, +183,400,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, + 183,183,183,183,183,183,183,183,183,183,183,183,183,189,183,344,403, +194,194,194,191, +180,180,180,180,166,346, +178,178,178,178,165, +175,179,174,174,174,192,176,167,170,168,169,164, +542,1,2,349,2,2,2,631, +542,1,2,350,2,2,2,630, +542,1,2,351,2,2,2,629, +542,1,2,352,2,2,2,628, +542,1,2,353,2,2,2,627, +542,1,2,354,2,2,2,626, +542,1,2,355,2,2,2,625, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,1,542,356,2,2,2,632, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,1,2,357,2,2,2,584, +59,358,404, +59,359,405, +59,360,406, +59,361,407, +59,362,408, +59,363,409, +59,364,410, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,1,2,365,2,2,2,621, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,366,161,151,347,348,162,345,163,346,411,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 342,343,182,81,367,161,151,347,348,162,345,163,346,265,149,150,149,366, + 364,363,362,361,360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 342,343,182,81,368,161,151,347,348,162,345,163,346,265,148,150,148,366, + 364,363,362,361,360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 342,343,182,81,369,161,151,347,348,162,345,163,346,265,147,150,147,366, + 364,363,362,361,360,359,358,265,357,356, +412,414,62,53,57,137,418,417,416,415,413, +55,56,132,420,419, +421,423,425,427,129,428,426,424,422, +429,61,126,431,430, +432,40,123,434,433, +435,38,122,437,436, +438,439,440,441,442,443,444,445,446,447,448,449,450,102,106,106,106,106,109, + 109,109,112,112,112,115,115,115,118,118,118,121,121,121, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,377,161,151,347,348,162,345,163,346,101,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +17,17,17,17,5,378,5,61, +451,56,56,56,56,5,379,5,451, +451,55,55,55,55,5,380,5,451, +451,54,54,54,54,5,381,5,451, +183,400,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, + 183,183,183,183,183,183,183,183,183,183,183,183,183,189,183,382,452, +453,17,17,17,17,5,383,5,453, +454,17,17,17,17,5,384,5,454, +455,17,17,17,17,5,385,5,455, +456,17,17,17,17,5,386,5,456, +98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98, + 98,98,98,98,98,98,99,98,98,98,387, +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93, + 93,93,93,93,93,93,94,93,93,93,388, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,1,542,389,2,2,2,639, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,390,2,2,2,634, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,391,2,2,2,633, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,392,2,2,2,637, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,393,2,2,2,636, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,394,2,2,2,635, +457,5,395,5,457, +458,5,396,5,458, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,1,542,397,2,2,2,660, +459,5,398,5,459, +175,179,174,174,174,176,167,170,168,169,164, +184,186,187,185,188,190,400, +183,400,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, + 183,183,183,183,183,183,183,183,183,183,183,183,183,189,183,401,88, +177,177,177,177,402, +181,403, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,404,161,151,347,348,162,345,163,346,460,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,405,161,151,347,348,162,345,163,346,461,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,406,161,151,347,348,162,345,163,346,462,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,407,161,151,347,348,162,345,163,346,463,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,408,161,151,347,348,162,345,163,346,464,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,409,161,151,347,348,162,345,163,346,465,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,410,161,151,347,348,162,345,163,346,466,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +58,411,467, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,1,542,412,2,2,2,619, +468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, + 468,468,468,468,468,468,5,413,5,468, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,1,542,414,2,2,2,618, +469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469, + 469,469,469,469,469,469,5,415,5,469, +470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470, + 470,470,470,470,470,470,5,416,5,470, +471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471, + 471,471,471,471,471,471,5,417,5,471, +472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, + 472,472,472,472,472,472,5,418,5,472, +473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, + 473,473,473,473,473,473,473,473,473,5,419,5,473, +474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474, + 474,474,474,474,474,474,474,474,474,5,420,5,474, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,421,2,2,2,612, +475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, + 475,475,475,475,475,475,475,475,475,5,422,5,475, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,423,2,2,2,611, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, + 476,476,476,476,476,476,476,476,476,5,424,5,476, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,425,2,2,2,610, +477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477, + 477,477,477,477,477,477,477,477,477,5,426,5,477, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,427,2,2,2,609, +478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478, + 478,478,478,478,478,478,478,478,478,5,428,5,478, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,429,2,2,2,608, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, + 479,479,479,479,479,479,479,479,479,5,430,5,479, +480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480, + 480,480,480,480,480,480,480,480,480,5,431,5,480, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,432,2,2,2,606, +481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481, + 481,481,481,481,481,481,481,481,481,5,433,5,481, +482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, + 482,482,482,482,482,482,482,482,482,5,434,5,482, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,542,435,2,2,2,604, +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, + 483,483,483,483,483,483,483,483,483,5,436,5,483, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, + 484,484,484,484,484,484,484,484,484,5,437,5,484, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,438,2,2,2,602, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,439,2,2,2,601, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,440,2,2,2,600, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,441,2,2,2,599, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,442,2,2,2,598, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,443,2,2,2,597, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,444,2,2,2,596, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,445,2,2,2,595, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,446,2,2,2,594, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,447,2,2,2,593, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,448,2,2,2,592, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,449,2,2,2,591, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,1,2,450,2,2,2,590, +485,451,486, +183,400,183,183,183,183,183,183,183,183,183,183,183,183,181,183,183,183,183, + 183,183,183,183,183,183,183,183,183,183,183,183,183,183,189,183,452,88, +485,53,487, +485,51,487, +485,52,487, +485,50,487, +485,457,488, +485,458,489, +8,459,490, +58,460,160, +58,461,159, +58,462,158, +58,463,157, +58,464,156, +58,465,155, +58,466,154, +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,5,467,5,153, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 342,343,182,81,468,161,151,347,348,162,345,163,346,265,145,150,145,366, + 364,363,362,361,360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 342,343,182,81,469,161,151,347,348,162,345,163,346,265,144,150,144,366, + 364,363,362,361,360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 342,343,182,81,470,161,151,347,348,162,345,163,346,265,143,150,143,366, + 364,363,362,361,360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 342,343,182,81,471,161,151,347,348,162,345,163,346,265,142,150,142,366, + 364,363,362,361,360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 342,343,182,81,472,161,151,347,348,162,345,163,346,265,141,150,141,366, + 364,363,362,361,360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,473,161,151,347,348,162,345,163,346,265,491, + 491,491,369,368,367,150,491,366,364,363,362,361,360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,474,161,151,347,348,162,345,163,346,265,492, + 492,492,369,368,367,150,492,366,364,363,362,361,360,359,358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,475,161,151,347,348,162,345,163,346,265,493, + 370,370,370,369,368,367,150,370,366,364,363,362,361,360,359,358,265,357, + 356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,476,161,151,347,348,162,345,163,346,265,494, + 370,370,370,369,368,367,150,370,366,364,363,362,361,360,359,358,265,357, + 356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,477,161,151,347,348,162,345,163,346,265,495, + 370,370,370,369,368,367,150,370,366,364,363,362,361,360,359,358,265,357, + 356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,478,161,151,347,348,162,345,163,346,265,496, + 370,370,370,369,368,367,150,370,366,364,363,362,361,360,359,358,265,357, + 356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,479,161,151,347,348,162,345,163,346,265,497, + 371,370,370,370,369,368,367,150,370,366,364,363,362,361,360,359,358,265, + 357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,480,161,151,347,348,162,345,163,346,265,498, + 371,370,370,370,369,368,367,150,370,366,364,363,362,361,360,359,358,265, + 357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,481,161,151,347,348,162,345,163,346,265,499, + 372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360,359,358, + 265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,482,161,151,347,348,162,345,163,346,265,500, + 372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360,359,358, + 265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,483,161,151,347,348,162,345,163,346,265,501, + 373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360,359, + 358,265,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,484,161,151,347,348,162,345,163,346,265,502, + 373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360,359, + 358,265,357,356, +542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, + 1,542,485,2,2,2,589, +503,503,503,503,503,503,503,503,503,5,486,5,503, +504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504, + 504,504,504,504,504,504,504,504,504,504,5,487,5,504, +505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505, + 505,505,505,505,505,505,505,505,505,5,488,5,505, +506,506,506,506,506,506,506,506,5,489,5,506, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, + 507,507,507,507,507,507,507,507,507,5,490,5,507, +412,414,62,53,57,139,418,417,416,415,413, +412,414,62,53,57,138,418,417,416,415,413, +55,56,136,420,419, +55,56,135,420,419, +55,56,134,420,419, +55,56,133,420,419, +421,423,425,427,131,428,426,424,422, +421,423,425,427,130,428,426,424,422, +429,61,128,431,430, +429,61,127,431,430, +432,40,125,434,433, +432,40,124,434,433, +82,82,82,82,82,82,82,82,81,503,79,265,265, +82,82,82,82,82,82,82,173,173,341,340,382,82,91,349,350,351,352,353,354,355, + 59,37,365,65,342,343,182,81,504,161,151,347,348,162,345,76,270,163,346, + 338,77,75,265,375,374,373,372,371,370,370,370,369,368,367,150,370,366, + 364,363,362,361,360,359,358,271,265,339,357,356, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,505,161,151,347,348,162,345,163,346,269,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, +202,199,197,195,201,200,198,196,506,268,389, +82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, + 37,365,65,342,343,182,81,507,161,151,347,348,162,345,163,346,267,265, + 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, + 360,359,358,265,357,356, + +}; + + +static const unsigned short ag_sbt[] = { + 0, 141, 178, 183, 326, 363, 365, 523, 665, 716, 757, 798, 869, 940, + 1011,1031,1047,1063,1074,1085,1101,1117,1126,1135,1157,1282,1509,1520, + 1533,1546,1559,1572,1577,1586,1610,1731,1741,1782,1832,1883,1924,1975, + 2016,2057,2098,2139,2180,2221,2262,2303,2344,2385,2518,2651,2701,2742, + 2793,2844,2894,3050,3101,3142,3193,3243,3284,3325,3467,3508,3576,3579, + 3582,3585,3688,3723,3738,3841,3876,3891,3994,4003,4038,4141,4244,4347, + 4382,4417,4432,4535,4544,4647,4750,4853,4956,5059,5162,5265,5368,5471, + 5574,5677,5780,5883,5986,5998,6010,6113,6148,6183,6198,6301,6316,6331, + 6342,6445,6480,6515,6550,6559,6594,6629,6664,6699,6734,6769,6804,6839, + 6874,6909,6944,6979,7014,7049,7060,7075,7110,7213,7316,7419,7522,7533, + 7548,7559,7662,7697,7732,7767,7802,7837,7872,7907,7922,8025,8128,8163, + 8198,8233,8336,8371,8386,8421,8436,8451,8486,8518,8530,8562,8574,8580, + 8612,8644,8676,8688,8694,8703,8712,8744,8776,8788,8800,8812,8820,8852, + 8884,8916,8922,8954,8986,9018,9050,9082,9114,9146,9178,9210,9242,9274, + 9306,9338,9370,9378,9390,9422,9430,9442,9450,9482,9514,9546,9578,9610, + 9642,9674,9686,9718,9750,9782,9814,9826,9858,9870,9882,9914,10014,10030, + 10043,10063,10079,10090,10101,10104,10113,10122,10133,10144,10179,10244, + 10264,10277,10312,10375,10391,10404,10420,10434,10450,10464,10480,10494, + 10530,10601,10637,10708,10743,10806,10817,10828,10839,10874,10937,11008, + 11079,11142,11177,11240,11275,11338,11382,11393,11404,11438,11449,11484, + 11496,11519,11582,11645,11787,11850,11861,11924,11935,11941,12004,12067, + 12130,12141,12146,12158,12170,12233,12296,12307,12318,12329,12336,12399, + 12462,12525,12531,12594,12657,12720,12783,12846,12909,12972,13035,13098, + 13161,13224,13287,13350,13413,13420,13431,13494,13501,13512,13519,13582, + 13645,13708,13771,13834,13897,13960,13971,14034,14097,14160,14223,14234, + 14297,14308,14319,14382,14568,14583,14619,14656,14668,14672,14674,14678, + 14682,14718,14722,14728,14733,14745,14753,14761,14769,14777,14785,14793, + 14801,14936,15071,15074,15077,15080,15083,15086,15089,15092,15124,15187, + 15236,15285,15334,15345,15350,15359,15364,15369,15374,15407,15470,15478, + 15487,15496,15505,15541,15550,15559,15568,15577,15613,15649,15753,15856, + 15959,16062,16165,16268,16273,16278,16381,16386,16397,16404,16440,16445, + 16447,16510,16573,16636,16699,16762,16825,16888,16891,16923,16952,16984, + 17013,17042,17071,17100,17132,17164,17199,17231,17266,17298,17333,17365, + 17400,17432,17467,17499,17531,17566,17598,17630,17665,17697,17729,17764, + 17799,17834,17869,17904,17939,17974,18009,18044,18079,18114,18149,18184, + 18187,18224,18227,18230,18233,18236,18239,18242,18245,18248,18251,18254, + 18257,18260,18263,18266,18398,18447,18496,18545,18594,18643,18700,18757, + 18815,18873,18931,18989,19048,19107,19167,19227,19288,19349,19393,19406, + 19439,19471,19483,19515,19526,19537,19542,19547,19552,19557,19566,19575, + 19580,19585,19590,19595,19608,19678,19741,19752,19815 +}; + + +static const unsigned short ag_sbe[] = { + 136, 176, 180, 319, 362, 364, 500, 660, 711, 752, 793, 833, 904, 975, + 1025,1042,1058,1069,1080,1096,1112,1121,1130,1152,1277,1394,1514,1529, + 1542,1555,1568,1574,1579,1601,1728,1735,1777,1827,1878,1919,1970,2011, + 2052,2093,2134,2175,2216,2257,2298,2339,2380,2513,2646,2696,2737,2788, + 2839,2889,3045,3096,3137,3188,3238,3279,3320,3462,3503,3542,3577,3580, + 3583,3683,3718,3733,3836,3871,3886,3989,3998,4033,4136,4239,4342,4377, + 4412,4427,4530,4539,4642,4745,4848,4951,5054,5157,5260,5363,5466,5569, + 5672,5775,5878,5981,5993,6005,6108,6143,6178,6193,6296,6311,6326,6337, + 6440,6475,6510,6545,6554,6589,6624,6659,6694,6729,6764,6799,6834,6869, + 6904,6939,6974,7009,7044,7055,7070,7105,7208,7311,7414,7517,7528,7543, + 7554,7657,7692,7727,7762,7797,7832,7867,7902,7917,8020,8123,8158,8193, + 8228,8331,8366,8381,8416,8431,8446,8481,8515,8527,8559,8571,8577,8609, + 8641,8673,8685,8691,8700,8709,8741,8773,8785,8797,8809,8817,8849,8881, + 8913,8919,8951,8983,9015,9047,9079,9111,9143,9175,9207,9239,9271,9303, + 9335,9367,9375,9387,9419,9427,9439,9447,9479,9511,9543,9575,9607,9639, + 9671,9683,9715,9747,9779,9811,9823,9855,9867,9879,9911,10011,10025,10039, + 10058,10076,10085,10096,10102,10108,10115,10128,10139,10174,10207,10259, + 10273,10307,10340,10386,10400,10415,10429,10445,10459,10475,10489,10525, + 10559,10632,10666,10738,10771,10812,10823,10834,10869,10902,10966,11037, + 11107,11172,11205,11270,11303,11376,11388,11399,11437,11444,11483,11491, + 11514,11547,11610,11782,11815,11858,11889,11932,11937,11969,12032,12095, + 12138,12143,12151,12163,12198,12261,12304,12315,12326,12333,12364,12427, + 12490,12527,12559,12622,12685,12748,12811,12874,12937,13000,13063,13126, + 13189,13252,13315,13378,13417,13428,13459,13498,13509,13516,13547,13610, + 13673,13736,13799,13862,13925,13968,13999,14062,14125,14188,14231,14262, + 14305,14316,14347,14474,14576,14617,14654,14663,14671,14673,14677,14681, + 14716,14721,14727,14732,14744,14748,14756,14764,14772,14780,14788,14796, + 14931,15066,15072,15075,15078,15081,15084,15087,15090,15119,15152,15212, + 15261,15310,15339,15347,15354,15361,15366,15371,15387,15435,15475,15484, + 15493,15502,15539,15547,15556,15565,15574,15612,15648,15748,15851,15954, + 16057,16160,16263,16270,16275,16376,16383,16396,16403,16438,16444,16446, + 16475,16538,16601,16664,16727,16790,16853,16889,16918,16949,16979,17010, + 17039,17068,17097,17129,17161,17194,17228,17261,17295,17328,17362,17395, + 17429,17462,17496,17528,17561,17595,17627,17660,17694,17726,17759,17794, + 17829,17864,17899,17934,17969,18004,18039,18074,18109,18144,18179,18185, + 18222,18225,18228,18231,18234,18237,18240,18243,18246,18249,18252,18255, + 18258,18261,18264,18395,18423,18472,18521,18570,18619,18671,18728,18785, + 18843,18901,18959,19017,19076,19135,19195,19255,19316,19388,19403,19436, + 19468,19480,19512,19520,19531,19539,19544,19549,19554,19561,19570,19577, + 19582,19587,19592,19604,19637,19706,19749,19780,19815 +}; + + +static const unsigned char ag_fl[] = { + 2,1,1,2,2,1,2,0,1,3,3,3,1,2,3,1,2,0,1,3,3,2,2,2,1,2,2,2,2,2,2,2,2,2,1, + 1,2,2,3,3,3,3,0,1,3,2,2,2,3,3,4,4,4,4,3,3,3,3,3,2,3,4,2,2,3,3,4,2,2,3, + 3,3,1,1,1,5,5,5,1,5,1,1,1,2,2,1,2,2,3,2,2,1,2,3,3,2,1,2,3,3,2,2,1,1,1, + 1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,4,4,1,4,4,1,4,4,1,4,4,4,4,1,4,4, + 1,4,4,4,4,4,1,2,2,2,1,1,1,4,4,4,4,4,4,4,4,1,1,1,1,1,2,2,2,2,2,2,2,1,2, + 2,2,3,2,2,2,3,1,1,2,2,2,2,2,1,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,3,3,3,3,3,3,3,3,1,3,3,3,1,1,3,3,3,3,3,3,3,3,1,3,3,3,1,1,1,1, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,7,7,7,1,3,3,3,1,3,3,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,3,1,3,3,3,1,1,1,3,3,1,3,3,1,3,3,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 +}; + +static const unsigned short ag_ptt[] = { + 0, 24, 25, 25, 22, 30, 30, 31, 31, 27, 27, 27, 37, 37, 2, 39, 39, 40, + 40, 23, 23, 23, 23, 23, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 57, 57, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 64, 64, 64, 64, 64, 64, 67, 67,298,298, 84, 84, 84,293,293,323, 19, 19, + 290, 13, 13, 13, 13,292, 15, 15, 15, 15,289, 74, 74,102,102,102, 98,105, + 105, 98,108,108, 98,111,111, 98,114,114, 98,117,117, 98, 55,118,118,118, + 119,119,119,122,122,122,125,125,125,125,125,128,128,128,133,133,133,133, + 133,133,136,136,136,136,138,138,138,138,147,147,147,147,147,147,147,146, + 146,325,325,325,325,325,325,325,325, 8, 8, 8, 8, 8, 8, 7, 7, 18, + 18, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17,373, 10, 10, 10,380,380,380, + 380,380,380,380,380,401,401,401,401,181,181,181,181,181,183,183, 82, 82, + 82,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, + 184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, + 184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, + 184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, + 184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, + 184,184, 32, 87, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 86, 86, 86, 86, 86, 86, 86, 86, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,161,161,161,166,166,166,166, + 169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, + 169,169,169,169,169,169,169,169,169,169,169,169,169,169,260,260,282,282, + 283,283,284,284, 28, 33, 34, 42, 12, 11, 43, 14, 20, 44, 46, 45, 47, 4, + 48, 49, 50, 51, 52, 53, 54, 56, 58, 59, 60, 61, 62, 63, 65, 66, 68, 69, + 70, 71, 72, 73, 75, 76, 21, 77, 3, 78, 79, 80, 81, 83, 99,100,101,103, + 104,106,107,109,110,112,113,115,116,120,121,123,124,126,127,129,130,131, + 132,134,135,137,139,140,141,142,143,144,145,149,148,150,151,152,153,154, + 155,156, 9,158,160,157,182,179,185, 5,186,187,188,189,190,191,192,193, + 194,195,196,197,198,199,200,201,202,203,204,205, 6,206,207,208,209,210, + 211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228, + 229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246, + 247,248,249,250,251,252,253,254,255,256,257,258,259,261,262,263,264,265, + 266,267,268,269,270,271,272,273,274,275,276,277, 90,163, 89,174,164,278, + 279, 95, 94,167,280,170,172,171,165, 92,162,281 +}; + + +static void ag_ra(void) +{ + switch(ag_rpx[(PCB).ag_ap]) { + case 1: ag_rp_1(); break; + case 2: ag_rp_6(); break; + case 3: ag_rp_7(); break; + case 4: ag_rp_8(); break; + case 5: ag_rp_9(); break; + case 6: ag_rp_10(); break; + case 7: ag_rp_11(); break; + case 8: ag_rp_12(); break; + case 9: ag_rp_13(); break; + case 10: ag_rp_14(); break; + case 11: ag_rp_15(); break; + case 12: ag_rp_16(); break; + case 13: ag_rp_17(); break; + case 14: ag_rp_18(); break; + case 15: ag_rp_19(); break; + case 16: ag_rp_20(); break; + case 17: ag_rp_21(); break; + case 18: ag_rp_22(); break; + case 19: ag_rp_23(); break; + case 20: ag_rp_24(); break; + case 21: ag_rp_25(); break; + case 22: ag_rp_26(); break; + case 23: ag_rp_27(); break; + case 24: ag_rp_28(); break; + case 25: ag_rp_29(); break; + case 26: ag_rp_30(); break; + case 27: ag_rp_31(); break; + case 28: ag_rp_32(); break; + case 29: ag_rp_33(); break; + case 30: ag_rp_34(); break; + case 31: ag_rp_35(); break; + case 32: ag_rp_36(); break; + case 33: ag_rp_37(); break; + case 34: ag_rp_38(); break; + case 35: ag_rp_39(); break; + case 36: ag_rp_40(V(3,int)); break; + case 37: ag_rp_41(); break; + case 38: ag_rp_42(); break; + case 39: ag_rp_43(); break; + case 40: ag_rp_44(); break; + case 41: ag_rp_45(); break; + case 42: ag_rp_46(); break; + case 43: ag_rp_47(); break; + case 44: ag_rp_48(); break; + case 45: ag_rp_49(); break; + case 46: ag_rp_50(); break; + case 47: ag_rp_51(); break; + case 48: ag_rp_52(); break; + case 49: ag_rp_53(V(0,int)); break; + case 50: ag_rp_54(V(1,int)); break; + case 51: ag_rp_55(V(1,int)); break; + case 52: ag_rp_56(V(0,int)); break; + case 53: ag_rp_57(V(1,int)); break; + case 54: ag_rp_58(V(1,int), V(2,int)); break; + case 55: ag_rp_59(V(1,int)); break; + case 56: ag_rp_60(); break; + case 57: ag_rp_61(V(1,int)); break; + case 58: ag_rp_62(V(2,int)); break; + case 59: ag_rp_63(); break; + case 60: ag_rp_64(); break; + case 61: ag_rp_65(V(1,int)); break; + case 62: ag_rp_66(V(2,int)); break; + case 63: ag_rp_67(); break; + case 64: ag_rp_68(); break; + case 65: ag_rp_69(); break; + case 66: ag_rp_70(); break; + case 67: ag_rp_71(); break; + case 68: ag_rp_72(); break; + case 69: ag_rp_73(); break; + case 70: ag_rp_74(); break; + case 71: ag_rp_75(); break; + case 72: ag_rp_76(); break; + case 73: ag_rp_77(); break; + case 74: ag_rp_78(); break; + case 75: ag_rp_79(); break; + case 76: ag_rp_80(); break; + case 77: ag_rp_81(); break; + case 78: ag_rp_82(); break; + case 79: ag_rp_83(); break; + case 80: ag_rp_84(); break; + case 81: ag_rp_85(); break; + case 82: ag_rp_86(); break; + case 83: ag_rp_87(); break; + case 84: ag_rp_88(); break; + case 85: ag_rp_89(); break; + case 86: ag_rp_90(); break; + case 87: ag_rp_91(); break; + case 88: ag_rp_92(); break; + case 89: ag_rp_93(); break; + case 90: ag_rp_94(); break; + case 91: ag_rp_95(); break; + case 92: ag_rp_96(V(0,double)); break; + case 93: ag_rp_97(); break; + case 94: ag_rp_98(); break; + case 95: ag_rp_99(); break; + case 96: ag_rp_100(); break; + case 97: ag_rp_101(); break; + case 98: ag_rp_102(); break; + case 99: ag_rp_103(); break; + case 100: ag_rp_104(); break; + case 101: V(0,double) = ag_rp_105(V(0,int)); break; + case 102: V(0,double) = ag_rp_106(V(0,double)); break; + case 103: V(0,int) = ag_rp_107(V(0,int)); break; + case 104: V(0,int) = ag_rp_108(); break; + case 105: V(0,int) = ag_rp_109(); break; + case 106: V(0,int) = ag_rp_110(); break; + case 107: V(0,int) = ag_rp_111(); break; + case 108: V(0,int) = ag_rp_112(); break; + case 109: V(0,int) = ag_rp_113(); break; + case 110: V(0,int) = ag_rp_114(); break; + case 111: ag_rp_115(V(1,int)); break; + case 112: ag_rp_116(V(1,int)); break; + case 113: ag_rp_117(V(0,int)); break; + case 114: ag_rp_118(V(1,int)); break; + case 115: ag_rp_119(V(2,int)); break; + case 116: ag_rp_120(V(1,int)); break; + case 117: ag_rp_121(V(1,int)); break; + case 118: ag_rp_122(V(1,int)); break; + case 119: V(0,int) = ag_rp_123(V(1,int)); break; + case 120: V(0,int) = ag_rp_124(); break; + case 121: V(0,int) = ag_rp_125(V(0,int)); break; + case 122: V(0,int) = ag_rp_126(); break; + case 123: V(0,int) = ag_rp_127(); break; + case 124: V(0,int) = ag_rp_128(); break; + case 125: V(0,int) = ag_rp_129(); break; + case 126: V(0,int) = ag_rp_130(); break; + case 127: V(0,int) = ag_rp_131(); break; + case 128: V(0,int) = ag_rp_132(); break; + case 129: V(0,double) = ag_rp_133(); break; + case 130: V(0,double) = ag_rp_134(V(1,int)); break; + case 131: V(0,double) = ag_rp_135(V(0,double), V(1,int)); break; + case 132: ag_rp_136(); break; + case 133: ag_rp_137(); break; + case 134: ag_rp_138(); break; + case 135: ag_rp_139(); break; + case 136: ag_rp_140(); break; + case 137: ag_rp_141(); break; + case 138: ag_rp_142(); break; + case 139: ag_rp_143(); break; + case 140: ag_rp_144(); break; + case 141: ag_rp_145(); break; + case 142: ag_rp_146(); break; + case 143: ag_rp_147(); break; + case 144: ag_rp_148(); break; + case 145: ag_rp_149(); break; + case 146: ag_rp_150(); break; + case 147: ag_rp_151(); break; + case 148: ag_rp_152(); break; + case 149: ag_rp_153(); break; + case 150: ag_rp_154(); break; + case 151: ag_rp_155(); break; + case 152: ag_rp_156(); break; + case 153: ag_rp_157(); break; + case 154: ag_rp_158(); break; + case 155: ag_rp_159(); break; + case 156: ag_rp_160(); break; + case 157: ag_rp_161(); break; + case 158: ag_rp_162(); break; + case 159: ag_rp_163(); break; + case 160: ag_rp_164(); break; + case 161: ag_rp_165(); break; + case 162: ag_rp_166(); break; + case 163: ag_rp_167(); break; + case 164: ag_rp_168(); break; + case 165: ag_rp_169(); break; + case 166: ag_rp_170(); break; + case 167: ag_rp_171(); break; + case 168: ag_rp_172(); break; + case 169: ag_rp_173(); break; + case 170: ag_rp_174(); break; + case 171: ag_rp_175(); break; + case 172: ag_rp_176(); break; + case 173: ag_rp_177(); break; + case 174: ag_rp_178(); break; + case 175: ag_rp_179(); break; + case 176: ag_rp_180(); break; + case 177: ag_rp_181(); break; + case 178: ag_rp_182(); break; + case 179: ag_rp_183(); break; + case 180: ag_rp_184(); break; + case 181: ag_rp_185(); break; + case 182: ag_rp_186(); break; + case 183: ag_rp_187(); break; + case 184: ag_rp_188(); break; + case 185: ag_rp_189(); break; + case 186: ag_rp_190(); break; + case 187: ag_rp_191(); break; + case 188: ag_rp_192(); break; + case 189: ag_rp_193(); break; + case 190: ag_rp_194(); break; + case 191: ag_rp_195(); break; + case 192: ag_rp_196(); break; + case 193: ag_rp_197(); break; + case 194: ag_rp_198(); break; + case 195: ag_rp_199(); break; + case 196: ag_rp_200(); break; + case 197: ag_rp_201(); break; + case 198: ag_rp_202(); break; + case 199: ag_rp_203(); break; + case 200: ag_rp_204(); break; + case 201: ag_rp_205(); break; + case 202: ag_rp_206(); break; + case 203: ag_rp_207(); break; + case 204: ag_rp_208(); break; + case 205: ag_rp_209(); break; + case 206: ag_rp_210(); break; + case 207: ag_rp_211(); break; + case 208: ag_rp_212(); break; + case 209: ag_rp_213(); break; + case 210: ag_rp_214(); break; + case 211: ag_rp_215(); break; + case 212: ag_rp_216(); break; + case 213: ag_rp_217(); break; + case 214: ag_rp_218(); break; + case 215: ag_rp_219(); break; + case 216: ag_rp_220(); break; + case 217: ag_rp_221(); break; + case 218: ag_rp_222(); break; + case 219: ag_rp_223(); break; + case 220: ag_rp_224(); break; + case 221: ag_rp_225(); break; + case 222: ag_rp_226(); break; + case 223: ag_rp_227(); break; + case 224: ag_rp_228(); break; + case 225: ag_rp_229(V(2,int)); break; + case 226: ag_rp_230(); break; + case 227: ag_rp_231(); break; + case 228: ag_rp_232(); break; + case 229: ag_rp_233(); break; + case 230: ag_rp_234(); break; + case 231: ag_rp_235(); break; + case 232: ag_rp_236(); break; + case 233: ag_rp_237(); break; + case 234: ag_rp_238(); break; + case 235: ag_rp_239(); break; + case 236: ag_rp_240(); break; + case 237: ag_rp_241(); break; + case 238: ag_rp_242(); break; + case 239: ag_rp_243(); break; + case 240: ag_rp_244(); break; + case 241: ag_rp_245(); break; + } +} + +#define TOKEN_NAMES a85parse_token_names +const char *const a85parse_token_names[491] = { + "a85parse", + "WS", + "cstyle comment", + "integer", + "literal name", + "register 8 bit", + "register 16 bit", + "hex integer", + "decimal integer", + "real", + "simple real", + "literal string", + "label", + "string chars", + "include string", + "include chars", + "ascii integer", + "escape char", + "asm hex value", + "singlequote chars", + "asm include", + "singlequote string", + "a85parse", + "statement", + "", + "", + "eof", + "comment", + "\"//\"", + "any text char", + "", + "", + "newline", + "';'", + "','", + "\"/*\"", + "", + "", + "\"*/\"", + "", + "", + "expression", + "'\\n'", + "\"INCLUDE\"", + "\"#INCLUDE\"", + "\"#PRAGMA\"", + "\"LIST\"", + "\"HEX\"", + "\"#IFDEF\"", + "\"#IFNDEF\"", + "\"#ELSE\"", + "\"#ENDIF\"", + "\"#DEFINE\"", + "\"#UNDEF\"", + "\"EQU\"", + "equation", + "\"SET\"", + "", + "\"ORG\"", + "\"ASEG\"", + "\"CSEG\"", + "\"DSEG\"", + "\"DS\"", + "\"DB\"", + "expression list", + "\"DW\"", + "\"EXTRN\"", + "name list", + "\"EXTERN\"", + "\"PUBLIC\"", + "\"NAME\"", + "\"STKLN\"", + "\"END\"", + "\"IF\"", + "condition", + "\"ELSE\"", + "\"ENDIF\"", + "\"TITLE\"", + "\"PAGE\"", + "\"SYM\"", + "\"LINK\"", + "\"MACLIB\"", + "instruction list", + "\",\"", + "literal alpha", + "\"$\"", + "", + "digit", + "asm incl char", + "'\\''", + "'\\\"'", + "string char", + "'\\\\'", + "", + "'>'", + "'<'", + "", + "\":\"", + "condition start", + "\"EQ\"", + "\"==\"", + "\"=\"", + "", + "\"NE\"", + "\"!=\"", + "", + "\"GE\"", + "\">=\"", + "", + "\"LE\"", + "\"<=\"", + "", + "\"GT\"", + "\">\"", + "", + "\"LT\"", + "\"<\"", + "", + "inclusive or exp", + "exclusive or exp", + "'|'", + "\"OR\"", + "and exp", + "'^'", + "\"XOR\"", + "shift exp", + "'&'", + "\"AND\"", + "additive exp", + "\"<<\"", + "\"SHL\"", + "\">>\"", + "\"SHR\"", + "multiplicative exp", + "'+'", + "'-'", + "urinary exp", + "'*'", + "primary exp", + "'/'", + "'%'", + "\"MOD\"", + "\"**\"", + "'!'", + "\"NOT\"", + "'~'", + "value", + "function", + "'('", + "')'", + "\"FLOOR\"", + "\"CEIL\"", + "\"LN\"", + "\"LOG\"", + "\"SQRT\"", + "\"IP\"", + "\"FP\"", + "\"H\"", + "\"B\"", + "\"Q\"", + "\"D\"", + "", + "'_'", + "'$'", + "'0'", + "", + "hex digit", + "", + "\"\\'\\\\\\'\"", + "", + "'n'", + "'t'", + "'r'", + "\"\\'\\'\"", + "'.'", + "\"C\"", + "\"E\"", + "\"L\"", + "\"M\"", + "\"A\"", + "\"SP\"", + "stack register", + "\"PSW\"", + "bd register", + "instruction", + "\"ACI\"", + "\"ADC\"", + "\"ADD\"", + "\"ADI\"", + "\"ANA\"", + "\"ANI\"", + "\"ASHR\"", + "\"CALL\"", + "\"CC\"", + "\"CM\"", + "\"CMA\"", + "\"CMC\"", + "\"CMP\"", + "\"CNC\"", + "\"CNZ\"", + "\"CP\"", + "\"CPE\"", + "\"CPI\"", + "\"CPO\"", + "\"CZ\"", + "\"DAA\"", + "\"DAD\"", + "\"DCR\"", + "\"DCX\"", + "\"DI\"", + "\"DSUB\"", + "\"EI\"", + "\"HLT\"", + "\"IN\"", + "\"INR\"", + "\"INX\"", + "\"JC\"", + "\"JD\"", + "\"JX\"", + "\"JM\"", + "\"JMP\"", + "\"JNC\"", + "\"JND\"", + "\"JNX\"", + "\"JNZ\"", + "\"JP\"", + "\"JPE\"", + "\"JPO\"", + "\"JZ\"", + "\"LDA\"", + "\"LDAX\"", + "\"LDEH\"", + "\"LDES\"", + "\"LHLD\"", + "\"LHLX\"", + "\"LXI\"", + "\"MOV\"", + "\"MVI\"", + "\"NOP\"", + "\"ORA\"", + "\"ORI\"", + "\"OUT\"", + "\"PCHL\"", + "\"POP\"", + "\"PUSH\"", + "\"RAL\"", + "\"RAR\"", + "\"RC\"", + "\"RET\"", + "\"RIM\"", + "\"RLC\"", + "\"RLDE\"", + "\"RM\"", + "\"RNC\"", + "\"RNZ\"", + "\"RP\"", + "\"RPE\"", + "\"RPO\"", + "\"RRC\"", + "\"RST\"", + "rst arg", + "\"RZ\"", + "\"SBB\"", + "\"SBI\"", + "\"SHLD\"", + "\"SHLX\"", + "\"SIM\"", + "\"SPHL\"", + "\"STA\"", + "\"STAX\"", + "\"STC\"", + "\"SUB\"", + "\"SUI\"", + "\"XCHG\"", + "\"XRA\"", + "\"XRI\"", + "\"XTHL\"", + "", + "", + "", + "", + "", + "", + "", + "", + "\"//\"", + "';'", + "','", + "'\\n'", + "label", + "literal string", + "\"INCLUDE\"", + "include string", + "asm include", + "\"#INCLUDE\"", + "\"LIST\"", + "\"#PRAGMA\"", + "\"HEX\"", + "literal name", + "\"#IFDEF\"", + "\"#IFNDEF\"", + "\"#ELSE\"", + "\"#ENDIF\"", + "\"#DEFINE\"", + "\"#UNDEF\"", + "\"EQU\"", + "\"SET\"", + "\"ORG\"", + "\"ASEG\"", + "\"CSEG\"", + "\"DSEG\"", + "\"DS\"", + "\"DB\"", + "\"DW\"", + "\"EXTRN\"", + "\"EXTERN\"", + "\"PUBLIC\"", + "\"NAME\"", + "\"STKLN\"", + "\"END\"", + "\"IF\"", + "\"ELSE\"", + "\"ENDIF\"", + "singlequote string", + "\"TITLE\"", + "integer", + "\"PAGE\"", + "\"SYM\"", + "\"LINK\"", + "\"MACLIB\"", + "\",\"", + "\"EQ\"", + "\"==\"", + "\"=\"", + "\"NE\"", + "\"!=\"", + "\"GE\"", + "\">=\"", + "\"LE\"", + "\"<=\"", + "\"GT\"", + "\">\"", + "\"LT\"", + "\"<\"", + "'|'", + "\"OR\"", + "'^'", + "\"XOR\"", + "'&'", + "\"AND\"", + "\"<<\"", + "\"SHL\"", + "\">>\"", + "\"SHR\"", + "'+'", + "'-'", + "'*'", + "'/'", + "'%'", + "\"MOD\"", + "\"**\"", + "'!'", + "\"NOT\"", + "'~'", + "')'", + "'('", + "\"FLOOR\"", + "\"CEIL\"", + "\"LN\"", + "\"LOG\"", + "\"SQRT\"", + "\"IP\"", + "\"FP\"", + "real", + "\"B\"", + "\"D\"", + "\"H\"", + "\"PSW\"", + "\"A\"", + "\"ACI\"", + "register 8 bit", + "\"ADC\"", + "\"ADD\"", + "\"ADI\"", + "\"ANA\"", + "\"ANI\"", + "\"ASHR\"", + "\"CALL\"", + "\"CC\"", + "\"CM\"", + "\"CMA\"", + "\"CMC\"", + "\"CMP\"", + "\"CNC\"", + "\"CNZ\"", + "\"CP\"", + "\"CPE\"", + "\"CPI\"", + "\"CPO\"", + "\"CZ\"", + "\"DAA\"", + "register 16 bit", + "\"DAD\"", + "\"DCR\"", + "\"DCX\"", + "\"DI\"", + "\"DSUB\"", + "\"EI\"", + "\"HLT\"", + "\"IN\"", + "\"INR\"", + "\"INX\"", + "\"JC\"", + "\"JD\"", + "\"JX\"", + "\"JM\"", + "\"JMP\"", + "\"JNC\"", + "\"JND\"", + "\"JNX\"", + "\"JNZ\"", + "\"JP\"", + "\"JPE\"", + "\"JPO\"", + "\"JZ\"", + "\"LDA\"", + "\"LDAX\"", + "\"LDEH\"", + "\"LDES\"", + "\"LHLD\"", + "\"LHLX\"", + "\"LXI\"", + "\"MOV\"", + "\"MVI\"", + "\"NOP\"", + "\"ORA\"", + "\"ORI\"", + "\"OUT\"", + "\"PCHL\"", + "\"POP\"", + "\"PUSH\"", + "\"RAL\"", + "\"RAR\"", + "\"RC\"", + "\"RET\"", + "\"RIM\"", + "\"RLC\"", + "\"RLDE\"", + "\"RM\"", + "\"RNC\"", + "\"RNZ\"", + "\"RP\"", + "\"RPE\"", + "\"RPO\"", + "\"RRC\"", + "\"RST\"", + "\"RZ\"", + "\"SBB\"", + "\"SBI\"", + "\"SHLD\"", + "\"SHLX\"", + "\"SIM\"", + "\"SPHL\"", + "\"STA\"", + "\"STAX\"", + "\"STC\"", + "\"SUB\"", + "\"SUI\"", + "\"XCHG\"", + "\"XRA\"", + "\"XRI\"", + "\"XTHL\"", + "", + "'\\\"'", + "'$'", + "'\\''", + "'.'", + "'0'", + "", + "", + "'<'", + "'>'", + "", + "", + "'n'", + "'r'", + "'t'", + "", + "'\\\\'", + "'_'", + "", + +}; + + +static const unsigned short ag_ctn[] = { + 0,0, 2,1, 0,0, 0,0, 0,0, 0,0, 23,1, 0,0, 0,0, 0,0, 27,1, 27,1, + 27,1, 27,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, + 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 23,2, + 29,1, 0,0, 0,0, 29,1, 0,0, 29,1, 29,1, 29,1, 29,1, 29,1, 29,1, 29,1, + 29,1, 29,1, 29,1, 0,0, 0,0, 0,0, 29,1, 0,0, 0,0, 0,0, 0,0, 0,0, + 29,1, 0,0, 0,0, 29,1, 29,1, 0,0, 29,1, 0,0, 27,2, 27,2, 27,2,184,1, + 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, + 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, + 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, + 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, + 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, + 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, + 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, + 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, + 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, + 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, + 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, + 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, + 184,1,184,1,184,1,184,1,184,1, 82,1, 0,0, 41,2, 0,0, 41,2, 0,0, 0,0, + 41,2, 0,0, 41,2, 0,0, 0,0, 0,0, 41,2, 0,0, 41,2, 0,0, 41,2, 0,0, + 41,2, 0,0, 41,2, 0,0, 41,2, 0,0, 41,2, 0,0, 41,2, 0,0, 41,2, 0,0, + 41,2, 0,0, 0,0, 0,0, 0,0, 41,2, 41,2, 41,2, 41,2, 0,0, 41,2, 0,0, + 41,2, 0,0, 0,0, 0,0,292,1, 0,0,290,1, 0,0, 0,0, 41,2, 41,2, 0,0, + 184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2, + 184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2, + 184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2, + 184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2, + 184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2, 82,2, + 0,0, 19,1,323,1, 0,0, 10,1, 7,1, 8,1, 8,1, 16,1, 10,1,325,1, 7,1, + 146,1,147,1,147,1,147,1,147,1,147,1,147,1,147,1,146,1, 0,0,147,1,147,1, + 147,1,147,1,147,1,147,1,147,1,136,1,138,1,136,1,136,1,136,1,133,1,128,1, + 125,1,122,1,119,1,118,1, 98,1, 74,1, 41,3, 67,1, 67,1, 67,1, 0,0, 64,1, + 64,1, 64,1, 64,1, 15,2, 13,2, 0,0, 0,0, 0,0,181,1,181,1,181,1,184,3, + 184,3, 0,0,184,3,325,1, 17,1, 19,2, 7,2, 16,2,147,2,147,2,147,2,147,2, + 147,2,147,2,147,2,138,2, 0,0,133,2, 0,0,133,2,133,2,133,2,133,2,128,2, + 128,2, 0,0,125,2, 0,0,125,2, 0,0,125,2, 0,0,125,2, 0,0,122,2,122,2, + 0,0,119,2,119,2, 0,0,118,2,118,2, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 67,2, 0,0, 64,2, 64,2, 64,2, + 64,2,184,4,184,4,184,4,147,3,147,3,147,3,147,3,147,3,147,3,147,3,138,3, + 133,3,133,3,133,3,133,3,133,3,128,3,128,3,125,3,125,3,125,3,125,3,122,3, + 122,3,119,3,119,3,118,3,118,3, 0,0, 67,3, 64,3,184,5,184,5,184,5,133,1, + 133,1,128,1,128,1,128,1,128,1,125,1,125,1,122,1,122,1,119,1,119,1, 67,4, + 64,4,184,6,184,6,184,6 +}; + +#ifndef MISSING_FORMAT +#define MISSING_FORMAT "Missing %s" +#endif +#ifndef UNEXPECTED_FORMAT +#define UNEXPECTED_FORMAT "Unexpected %s" +#endif +#ifndef UNNAMED_TOKEN +#define UNNAMED_TOKEN "input" +#endif + + +static void ag_diagnose(void) { + int ag_snd = (PCB).sn; + int ag_k = ag_sbt[ag_snd]; + + if (*TOKEN_NAMES[ag_tstt[ag_k]] && ag_astt[ag_k + 1] == ag_action_8) { + sprintf((PCB).ag_msg, MISSING_FORMAT, TOKEN_NAMES[ag_tstt[ag_k]]); + } + else if (ag_astt[ag_sbe[(PCB).sn]] == ag_action_8 + && (ag_k = (int) ag_sbe[(PCB).sn] + 1) == (int) ag_sbt[(PCB).sn+1] - 1 + && *TOKEN_NAMES[ag_tstt[ag_k]]) { + sprintf((PCB).ag_msg, MISSING_FORMAT, TOKEN_NAMES[ag_tstt[ag_k]]); + } + else if ((PCB).token_number && *TOKEN_NAMES[(PCB).token_number]) { + sprintf((PCB).ag_msg, UNEXPECTED_FORMAT, TOKEN_NAMES[(PCB).token_number]); + } + else if (isprint((*(PCB).lab)) && (*(PCB).lab) != '\\') { + char buf[20]; + sprintf(buf, "\'%c\'", (char) (*(PCB).lab)); + sprintf((PCB).ag_msg, UNEXPECTED_FORMAT, buf); + } + else sprintf((PCB).ag_msg, UNEXPECTED_FORMAT, UNNAMED_TOKEN); + (PCB).error_message = (PCB).ag_msg; + + +} +static int ag_action_1_r_proc(void); +static int ag_action_2_r_proc(void); +static int ag_action_3_r_proc(void); +static int ag_action_4_r_proc(void); +static int ag_action_1_s_proc(void); +static int ag_action_3_s_proc(void); +static int ag_action_1_proc(void); +static int ag_action_2_proc(void); +static int ag_action_3_proc(void); +static int ag_action_4_proc(void); +static int ag_action_5_proc(void); +static int ag_action_6_proc(void); +static int ag_action_7_proc(void); +static int ag_action_8_proc(void); +static int ag_action_9_proc(void); +static int ag_action_10_proc(void); +static int ag_action_11_proc(void); +static int ag_action_8_proc(void); + + +static int (*const ag_r_procs_scan[])(void) = { + ag_action_1_r_proc, + ag_action_2_r_proc, + ag_action_3_r_proc, + ag_action_4_r_proc +}; + +static int (*const ag_s_procs_scan[])(void) = { + ag_action_1_s_proc, + ag_action_2_r_proc, + ag_action_3_s_proc, + ag_action_4_r_proc +}; + +static int (*const ag_gt_procs_scan[])(void) = { + ag_action_1_proc, + ag_action_2_proc, + ag_action_3_proc, + ag_action_4_proc, + ag_action_5_proc, + ag_action_6_proc, + ag_action_7_proc, + ag_action_8_proc, + ag_action_9_proc, + ag_action_10_proc, + ag_action_11_proc, + ag_action_8_proc +}; + + +static int ag_rns(int ag_t, int *ag_sx, int ag_snd) { + while (1) { + int ag_act, ag_k = ag_sbt[ag_snd], ag_lim = ag_sbt[ag_snd+1]; + int ag_p; + + while (ag_k < ag_lim && ag_tstt[ag_k] != ag_t) ag_k++; + if (ag_k == ag_lim) break; + ag_act = ag_astt[ag_k]; + ag_p = ag_pstt[ag_k]; + if (ag_act == ag_action_2) return ag_p; + if (ag_act == ag_action_10 || ag_act == ag_action_11) { + (*ag_sx)--; + return ag_snd; + } + if (ag_act != ag_action_3 && + ag_act != ag_action_4) break; + *ag_sx -= (ag_fl[ag_p] - 1); + ag_snd = (PCB).ss[*ag_sx]; + ag_t = ag_ptt[ag_p]; + } + return 0; +} + +static int ag_jns(int ag_t) { + int ag_k; + + ag_k = ag_sbt[(PCB).sn]; + while (ag_tstt[ag_k] != ag_t && ag_tstt[ag_k]) ag_k++; + while (1) { + int ag_p = ag_pstt[ag_k]; + int ag_sd; + + switch (ag_astt[ag_k]) { + case ag_action_2: + (PCB).ss[(PCB).ssx] = (PCB).sn; + return ag_p; + case ag_action_10: + case ag_action_11: + return (PCB).ss[(PCB).ssx--]; + case ag_action_9: + (PCB).ss[(PCB).ssx] = (PCB).sn; + (PCB).ssx++; + (PCB).sn = ag_p; + ag_k = ag_sbt[(PCB).sn]; + while (ag_tstt[ag_k] != ag_t && ag_tstt[ag_k]) ag_k++; + continue; + case ag_action_3: + case ag_action_4: + ag_sd = ag_fl[ag_p] - 1; + if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd]; + else (PCB).ss[(PCB).ssx] = (PCB).sn; + ag_t = ag_ptt[ag_p]; + ag_k = ag_sbt[(PCB).sn+1]; + while (ag_tstt[--ag_k] != ag_t); + continue; + case ag_action_5: + case ag_action_6: + if (ag_fl[ag_p]) break; + (PCB).sn = ag_rns(ag_ptt[ag_p],&(PCB).ssx, (PCB).sn); + (PCB).ss[++(PCB).ssx] = (PCB).sn; + ag_k = ag_sbt[(PCB).sn]; + while (ag_tstt[ag_k] != ag_t && ag_tstt[ag_k]) ag_k++; + continue; + } + break; + } + return 0; +} + + +static int ag_atx(int ag_t, int *ag_sx, int ag_snd) { + int ag_k, ag_f; + int ag_save_btsx = (PCB).btsx; + int ag_flag = 1; + + while (1) { + int ag_a; + + (PCB).bts[128 - ++(PCB).btsx] = *ag_sx; + (PCB).ss[128 - (PCB).btsx] = (PCB).ss[*ag_sx]; + (PCB).ss[*ag_sx] = ag_snd; + ag_k = ag_sbt[ag_snd]; + while (ag_tstt[ag_k] != ag_t && ag_tstt[ag_k]) ag_k++; + ag_a = ag_astt[ag_k]; + if (ag_a == ag_action_2 || + ag_a == ag_action_3 || + ag_a == ag_action_10 || + ag_a == ag_action_11 || + ag_a == ag_action_1 || + ag_a == ag_action_4) break; + if ((ag_a == ag_action_5 || + ag_a == ag_action_6) && + (ag_k = ag_fl[ag_f = ag_pstt[ag_k]]) == 0) { + ag_snd = ag_rns(ag_ptt[ag_f],ag_sx, (PCB).ss[*ag_sx]); + (*ag_sx)++; + continue; + } + if (ag_a == ag_action_9) { + ag_snd = ag_pstt[ag_k]; + (*ag_sx)++; + continue; + } + ag_flag = 0; + break; + } + while ((PCB).btsx > ag_save_btsx) { + *ag_sx = (PCB).bts[128 - (PCB).btsx]; + (PCB).ss[*ag_sx] = (PCB).ss[128 - (PCB).btsx--]; + } + return ag_flag; +} + + +static int ag_tst_tkn(void) { + int ag_rk, ag_sx, ag_snd = (PCB).sn; + + if ((PCB).rx < (PCB).fx) { + (PCB).input_code = (PCB).lab[(PCB).rx++]; + (PCB).token_number = (a85parse_token_type) AG_TCV((PCB).input_code);} + else { + GET_INPUT; + (PCB).lab[(PCB).fx++] = (PCB).input_code; + (PCB).token_number = (a85parse_token_type) AG_TCV((PCB).input_code); + (PCB).rx++; + } + if (ag_key_index[(PCB).sn]) { + unsigned ag_k = ag_key_index[(PCB).sn]; + int ag_ch = CONVERT_CASE((PCB).input_code); + while (ag_key_ch[ag_k] < ag_ch) ag_k++; + if (ag_key_ch[ag_k] == ag_ch) ag_get_key_word(ag_k); + } + for (ag_rk = 0; ag_rk < (PCB).ag_lrss; ag_rk += 2) { + ag_sx = (PCB).ag_rss[ag_rk]; + if (ag_sx > (PCB).ssx || ag_sx > (PCB).ag_min_depth) continue; + (PCB).sn = (PCB).ag_rss[ag_rk + 1]; + if (ag_atx((PCB).token_number, &ag_sx, (PCB).sn)) break; + } + (PCB).sn = ag_snd; + return ag_rk; +} + +static void ag_set_error_procs(void); + +static void ag_auto_resynch(void) { + int ag_sx, ag_rk; + int ag_rk1, ag_rk2, ag_tk1; + (PCB).ss[(PCB).ssx] = (PCB).sn; + if ((PCB).ag_error_depth && (PCB).ag_min_depth >= (PCB).ag_error_depth) { + (PCB).ssx = (PCB).ag_error_depth; + (PCB).sn = (PCB).ss[(PCB).ssx]; + } + else { + ag_diagnose(); + SYNTAX_ERROR; + if ((PCB).exit_flag != AG_RUNNING_CODE) return; + (PCB).ag_error_depth = (PCB).ag_min_depth = 0; + (PCB).ag_lrss = 0; + (PCB).ss[ag_sx = (PCB).ssx] = (PCB).sn; + (PCB).ag_min_depth = (PCB).ag_rss[(PCB).ag_lrss++] = ag_sx; + (PCB).ag_rss[(PCB).ag_lrss++] = (PCB).sn; + while (ag_sx && (PCB).ag_lrss < 2*128) { + int ag_t = 0, ag_x, ag_s, ag_sxs = ag_sx; + + while (ag_sx && (ag_t = ag_ctn[2*(PCB).sn]) == 0) (PCB).sn = (PCB).ss[--ag_sx]; + if (ag_t) (PCB).sn = (PCB).ss[ag_sx -= ag_ctn[2*(PCB).sn +1]]; + else { + if (ag_sx == 0) (PCB).sn = 0; + ag_t = ag_ptt[0]; + } + if ((ag_s = ag_rns(ag_t, &ag_sx, (PCB).sn)) == 0) break; + for (ag_x = 0; ag_x < (PCB).ag_lrss; ag_x += 2) + if ((PCB).ag_rss[ag_x] == ag_sx + 1 && (PCB).ag_rss[ag_x+1] == ag_s) break; + if (ag_x == (PCB).ag_lrss) { + (PCB).ag_rss[(PCB).ag_lrss++] = ++ag_sx; + (PCB).ag_rss[(PCB).ag_lrss++] = (PCB).sn = ag_s; + } + else if (ag_sx >= ag_sxs) ag_sx--; + } + ag_set_error_procs(); + } + (PCB).rx = 0; + if ((PCB).ssx > (PCB).ag_min_depth) (PCB).ag_min_depth = (PCB).ssx; + while (1) { + ag_rk1 = ag_tst_tkn(); + if ((PCB).token_number == 26) + {(PCB).exit_flag = AG_SYNTAX_ERROR_CODE; return;} + if (ag_rk1 < (PCB).ag_lrss) break; + {(PCB).rx = 1; ag_track();} + } + ag_tk1 = (PCB).token_number; + ag_track(); + ag_rk2 = ag_tst_tkn(); + if (ag_rk2 < ag_rk1) {ag_rk = ag_rk2; ag_track();} + else {ag_rk = ag_rk1; (PCB).token_number = (a85parse_token_type) ag_tk1; (PCB).rx = 0;} + (PCB).ag_min_depth = (PCB).ssx = (PCB).ag_rss[ag_rk++]; + (PCB).sn = (PCB).ss[(PCB).ssx] = (PCB).ag_rss[ag_rk]; + (PCB).sn = ag_jns((PCB).token_number); + if ((PCB).ag_error_depth == 0 || (PCB).ag_error_depth > (PCB).ssx) + (PCB).ag_error_depth = (PCB).ssx; + if (++(PCB).ssx >= 128) { + (PCB).exit_flag = AG_STACK_ERROR_CODE; + PARSER_STACK_OVERFLOW; + return; + } + (PCB).ss[(PCB).ssx] = (PCB).sn; + (PCB).ag_tmp_depth = (PCB).ag_min_depth; + (PCB).rx = 0; + return; +} + + +static int ag_action_10_proc(void) { + int ag_t = (PCB).token_number; + (PCB).btsx = 0, (PCB).drt = -1; + do { + ag_track(); + if ((PCB).rx < (PCB).fx) { + (PCB).input_code = (PCB).lab[(PCB).rx++]; + (PCB).token_number = (a85parse_token_type) AG_TCV((PCB).input_code);} + else { + GET_INPUT; + (PCB).lab[(PCB).fx++] = (PCB).input_code; + (PCB).token_number = (a85parse_token_type) AG_TCV((PCB).input_code); + (PCB).rx++; + } + if (ag_key_index[(PCB).sn]) { + unsigned ag_k = ag_key_index[(PCB).sn]; + int ag_ch = CONVERT_CASE((PCB).input_code); + while (ag_key_ch[ag_k] < ag_ch) ag_k++; + if (ag_key_ch[ag_k] == ag_ch) ag_get_key_word(ag_k); + } + } while ((PCB).token_number == (a85parse_token_type) ag_t); + (PCB).rx = 0; + return 1; +} + +static int ag_action_11_proc(void) { + int ag_t = (PCB).token_number; + + (PCB).btsx = 0, (PCB).drt = -1; + do { + (*(int *) &(PCB).vs[(PCB).ssx]) = *(PCB).lab; + (PCB).ssx--; + ag_track(); + ag_ra(); + if ((PCB).exit_flag != AG_RUNNING_CODE) return 0; + (PCB).ssx++; + if ((PCB).rx < (PCB).fx) { + (PCB).input_code = (PCB).lab[(PCB).rx++]; + (PCB).token_number = (a85parse_token_type) AG_TCV((PCB).input_code);} + else { + GET_INPUT; + (PCB).lab[(PCB).fx++] = (PCB).input_code; + (PCB).token_number = (a85parse_token_type) AG_TCV((PCB).input_code); + (PCB).rx++; + } + if (ag_key_index[(PCB).sn]) { + unsigned ag_k = ag_key_index[(PCB).sn]; + int ag_ch = CONVERT_CASE((PCB).input_code); + while (ag_key_ch[ag_k] < ag_ch) ag_k++; + if (ag_key_ch[ag_k] == ag_ch) ag_get_key_word(ag_k); + } + } + while ((PCB).token_number == (a85parse_token_type) ag_t); + (PCB).rx = 0; + return 1; +} + +static int ag_action_3_r_proc(void) { + int ag_sd = ag_fl[(PCB).ag_ap] - 1; + if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd]; + (PCB).btsx = 0, (PCB).drt = -1; + (PCB).reduction_token = (a85parse_token_type) ag_ptt[(PCB).ag_ap]; + ag_ra(); + return (PCB).exit_flag == AG_RUNNING_CODE; +} + +static int ag_action_3_s_proc(void) { + int ag_sd = ag_fl[(PCB).ag_ap] - 1; + if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd]; + (PCB).btsx = 0, (PCB).drt = -1; + (PCB).reduction_token = (a85parse_token_type) ag_ptt[(PCB).ag_ap]; + ag_ra(); + return (PCB).exit_flag == AG_RUNNING_CODE;; +} + +static int ag_action_4_r_proc(void) { + int ag_sd = ag_fl[(PCB).ag_ap] - 1; + if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd]; + (PCB).reduction_token = (a85parse_token_type) ag_ptt[(PCB).ag_ap]; + return 1; +} + +static int ag_action_2_proc(void) { + (PCB).btsx = 0, (PCB).drt = -1; + if ((PCB).ssx >= 128) { + (PCB).exit_flag = AG_STACK_ERROR_CODE; + PARSER_STACK_OVERFLOW; + } + (*(int *) &(PCB).vs[(PCB).ssx]) = *(PCB).lab; + (PCB).ss[(PCB).ssx] = (PCB).sn; + (PCB).ssx++; + (PCB).sn = (PCB).ag_ap; + ag_track(); + return 0; +} + +static int ag_action_9_proc(void) { + if ((PCB).drt == -1) { + (PCB).drt=(PCB).token_number; + (PCB).dssx=(PCB).ssx; + (PCB).dsn=(PCB).sn; + } + ag_prot(); + (PCB).vs[(PCB).ssx] = ag_null_value; + (PCB).ss[(PCB).ssx] = (PCB).sn; + (PCB).ssx++; + (PCB).sn = (PCB).ag_ap; + (PCB).rx = 0; + return (PCB).exit_flag == AG_RUNNING_CODE; +} + +static int ag_action_2_r_proc(void) { + (PCB).ssx++; + (PCB).sn = (PCB).ag_ap; + return 0; +} + +static int ag_action_7_proc(void) { + --(PCB).ssx; + (PCB).rx = 0; + (PCB).exit_flag = AG_SUCCESS_CODE; + return 0; +} + +static int ag_action_1_proc(void) { + ag_track(); + (PCB).exit_flag = AG_SUCCESS_CODE; + return 0; +} + +static int ag_action_1_r_proc(void) { + (PCB).exit_flag = AG_SUCCESS_CODE; + return 0; +} + +static int ag_action_1_s_proc(void) { + (PCB).exit_flag = AG_SUCCESS_CODE; + return 0; +} + +static int ag_action_4_proc(void) { + int ag_sd = ag_fl[(PCB).ag_ap] - 1; + (PCB).reduction_token = (a85parse_token_type) ag_ptt[(PCB).ag_ap]; + (PCB).btsx = 0, (PCB).drt = -1; + (*(int *) &(PCB).vs[(PCB).ssx]) = *(PCB).lab; + if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd]; + else (PCB).ss[(PCB).ssx] = (PCB).sn; + ag_track(); + while ((PCB).exit_flag == AG_RUNNING_CODE) { + unsigned ag_t1 = ag_sbe[(PCB).sn] + 1; + unsigned ag_t2 = ag_sbt[(PCB).sn+1] - 1; + do { + unsigned ag_tx = (ag_t1 + ag_t2)/2; + if (ag_tstt[ag_tx] < (const unsigned short)(PCB).reduction_token) ag_t1 = ag_tx + 1; + else ag_t2 = ag_tx; + } while (ag_t1 < ag_t2); + (PCB).ag_ap = ag_pstt[ag_t1]; + if ((*(PCB).s_procs[ag_astt[ag_t1]])() == 0) break; + } + return 0; +} + +static int ag_action_3_proc(void) { + int ag_sd = ag_fl[(PCB).ag_ap] - 1; + (PCB).btsx = 0, (PCB).drt = -1; + (*(int *) &(PCB).vs[(PCB).ssx]) = *(PCB).lab; + if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd]; + else (PCB).ss[(PCB).ssx] = (PCB).sn; + ag_track(); + (PCB).reduction_token = (a85parse_token_type) ag_ptt[(PCB).ag_ap]; + ag_ra(); + while ((PCB).exit_flag == AG_RUNNING_CODE) { + unsigned ag_t1 = ag_sbe[(PCB).sn] + 1; + unsigned ag_t2 = ag_sbt[(PCB).sn+1] - 1; + do { + unsigned ag_tx = (ag_t1 + ag_t2)/2; + if (ag_tstt[ag_tx] < (const unsigned short)(PCB).reduction_token) ag_t1 = ag_tx + 1; + else ag_t2 = ag_tx; + } while (ag_t1 < ag_t2); + (PCB).ag_ap = ag_pstt[ag_t1]; + if ((*(PCB).s_procs[ag_astt[ag_t1]])() == 0) break; + } + return 0; +} + +static int ag_action_8_proc(void) { + ag_undo(); + (PCB).rx = 0; + ag_auto_resynch(); + return (PCB).exit_flag == AG_RUNNING_CODE; +} + +static int ag_action_5_proc(void) { + int ag_sd = ag_fl[(PCB).ag_ap]; + (PCB).btsx = 0, (PCB).drt = -1; + if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd]; + else { + (PCB).ss[(PCB).ssx] = (PCB).sn; + } + (PCB).rx = 0; + (PCB).reduction_token = (a85parse_token_type) ag_ptt[(PCB).ag_ap]; + ag_ra(); + while ((PCB).exit_flag == AG_RUNNING_CODE) { + unsigned ag_t1 = ag_sbe[(PCB).sn] + 1; + unsigned ag_t2 = ag_sbt[(PCB).sn+1] - 1; + do { + unsigned ag_tx = (ag_t1 + ag_t2)/2; + if (ag_tstt[ag_tx] < (const unsigned short)(PCB).reduction_token) ag_t1 = ag_tx + 1; + else ag_t2 = ag_tx; + } while (ag_t1 < ag_t2); + (PCB).ag_ap = ag_pstt[ag_t1]; + if ((*(PCB).r_procs[ag_astt[ag_t1]])() == 0) break; + } + return (PCB).exit_flag == AG_RUNNING_CODE; +} + +static int ag_action_6_proc(void) { + int ag_sd = ag_fl[(PCB).ag_ap]; + (PCB).reduction_token = (a85parse_token_type) ag_ptt[(PCB).ag_ap]; + if ((PCB).drt == -1) { + (PCB).drt=(PCB).token_number; + (PCB).dssx=(PCB).ssx; + (PCB).dsn=(PCB).sn; + } + if (ag_sd) { + (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd]; + } + else { + ag_prot(); + (PCB).vs[(PCB).ssx] = ag_null_value; + (PCB).ss[(PCB).ssx] = (PCB).sn; + } + (PCB).rx = 0; + while ((PCB).exit_flag == AG_RUNNING_CODE) { + unsigned ag_t1 = ag_sbe[(PCB).sn] + 1; + unsigned ag_t2 = ag_sbt[(PCB).sn+1] - 1; + do { + unsigned ag_tx = (ag_t1 + ag_t2)/2; + if (ag_tstt[ag_tx] < (const unsigned short)(PCB).reduction_token) ag_t1 = ag_tx + 1; + else ag_t2 = ag_tx; + } while (ag_t1 < ag_t2); + (PCB).ag_ap = ag_pstt[ag_t1]; + if ((*(PCB).r_procs[ag_astt[ag_t1]])() == 0) break; + } + return (PCB).exit_flag == AG_RUNNING_CODE; +} + + +static void ag_check_depth(int ag_fl) { + int ag_sx = (PCB).ssx - ag_fl; + if ((PCB).ag_error_depth && ag_sx < (PCB).ag_tmp_depth) (PCB).ag_tmp_depth = ag_sx; +} + +static int ag_action_3_er_proc(void) { + ag_check_depth(ag_fl[(PCB).ag_ap] - 1); + return ag_action_4_r_proc(); +} + +static int ag_action_2_e_proc(void) { + ag_action_2_proc(); + (PCB).ag_min_depth = (PCB).ag_tmp_depth; + return 0; +} + +static int ag_action_4_e_proc(void) { + ag_check_depth(ag_fl[(PCB).ag_ap] - 1); + (PCB).ag_min_depth = (PCB).ag_tmp_depth; + return ag_action_4_proc(); +} + +static int ag_action_6_e_proc(void) { + ag_check_depth(ag_fl[(PCB).ag_ap]); + return ag_action_6_proc(); +} + +static int ag_action_11_e_proc(void) { + return ag_action_10_proc(); +} + +static int (*ag_r_procs_error[])(void) = { + ag_action_1_r_proc, + ag_action_2_r_proc, + ag_action_3_er_proc, + ag_action_3_er_proc +}; + +static int (*ag_s_procs_error[])(void) = { + ag_action_1_s_proc, + ag_action_2_r_proc, + ag_action_3_er_proc, + ag_action_3_er_proc +}; + +static int (*ag_gt_procs_error[])(void) = { + ag_action_1_proc, + ag_action_2_e_proc, + ag_action_4_e_proc, + ag_action_4_e_proc, + ag_action_6_e_proc, + ag_action_6_e_proc, + ag_action_7_proc, + ag_action_8_proc, + ag_action_9_proc, + ag_action_10_proc, + ag_action_11_e_proc, + ag_action_8_proc +}; + +static void ag_set_error_procs(void) { + (PCB).gt_procs = ag_gt_procs_error; + (PCB).r_procs = ag_r_procs_error; + (PCB).s_procs = ag_s_procs_error; +} + + +void init_a85parse(void) { + (PCB).rx = (PCB).fx = 0; + (PCB).gt_procs = ag_gt_procs_scan; + (PCB).r_procs = ag_r_procs_scan; + (PCB).s_procs = ag_s_procs_scan; + (PCB).ag_error_depth = (PCB).ag_min_depth = (PCB).ag_tmp_depth = 0; + (PCB).ag_resynch_active = 0; + (PCB).ss[0] = (PCB).sn = (PCB).ssx = 0; + (PCB).exit_flag = AG_RUNNING_CODE; + (PCB).line = FIRST_LINE; + (PCB).column = FIRST_COLUMN; + (PCB).btsx = 0, (PCB).drt = -1; +} + +void a85parse(void) { + init_a85parse(); + (PCB).exit_flag = AG_RUNNING_CODE; + while ((PCB).exit_flag == AG_RUNNING_CODE) { + unsigned ag_t1 = ag_sbt[(PCB).sn]; + if (ag_tstt[ag_t1]) { + unsigned ag_t2 = ag_sbe[(PCB).sn] - 1; + if ((PCB).rx < (PCB).fx) { + (PCB).input_code = (PCB).lab[(PCB).rx++]; + (PCB).token_number = (a85parse_token_type) AG_TCV((PCB).input_code);} + else { + GET_INPUT; + (PCB).lab[(PCB).fx++] = (PCB).input_code; + (PCB).token_number = (a85parse_token_type) AG_TCV((PCB).input_code); + (PCB).rx++; + } + if (ag_key_index[(PCB).sn]) { + unsigned ag_k = ag_key_index[(PCB).sn]; + int ag_ch = CONVERT_CASE((PCB).input_code); + while (ag_key_ch[ag_k] < ag_ch) ag_k++; + if (ag_key_ch[ag_k] == ag_ch) ag_get_key_word(ag_k); + } + do { + unsigned ag_tx = (ag_t1 + ag_t2)/2; + if (ag_tstt[ag_tx] > (const unsigned short)(PCB).token_number) + ag_t1 = ag_tx + 1; + else ag_t2 = ag_tx; + } while (ag_t1 < ag_t2); + if (ag_tstt[ag_t1] != (const unsigned short)(PCB).token_number) + ag_t1 = ag_sbe[(PCB).sn]; + } + (PCB).ag_ap = ag_pstt[ag_t1]; + (*(PCB).gt_procs[ag_astt[ag_t1]])(); + } +} + + diff --git a/src/a85parse.h b/src/a85parse.h new file mode 100644 index 0000000..06b51a9 --- /dev/null +++ b/src/a85parse.h @@ -0,0 +1,87 @@ +#ifndef A85PARSE_H_1147178743 +#define A85PARSE_H_1147178743 + +typedef union { + long alignment; + char ag_vt_2[sizeof(int)]; + char ag_vt_4[sizeof(double)]; +} a85parse_vs_type; + +typedef enum { + a85parse_WS_token = 1, a85parse_cstyle_comment_token, + a85parse_hex_integer_token = 7, a85parse_decimal_integer_token, + a85parse_simple_real_token = 10, a85parse_string_chars_token = 13, + a85parse_include_chars_token = 15, a85parse_ascii_integer_token, + a85parse_escape_char_token, a85parse_asm_hex_value_token, + a85parse_singlequote_chars_token, a85parse_a85parse_token = 22, + a85parse_statement_token, a85parse_eof_token = 26, a85parse_comment_token, + a85parse_any_text_char_token = 29, a85parse_newline_token = 32, + a85parse_expression_token = 41, a85parse_equation_token = 55, + a85parse_expression_list_token = 64, a85parse_name_list_token = 67, + a85parse_condition_token = 74, a85parse_instruction_list_token = 82, + a85parse_literal_alpha_token = 84, a85parse_digit_token = 87, + a85parse_asm_incl_char_token, a85parse_string_char_token = 91, + a85parse_condition_start_token = 98, + a85parse_inclusive_or_exp_token = 118, a85parse_exclusive_or_exp_token, + a85parse_and_exp_token = 122, a85parse_shift_exp_token = 125, + a85parse_additive_exp_token = 128, + a85parse_multiplicative_exp_token = 133, a85parse_urinary_exp_token = 136, + a85parse_primary_exp_token = 138, a85parse_value_token = 146, + a85parse_function_token, a85parse_hex_digit_token = 166, + a85parse_stack_register_token = 181, a85parse_bd_register_token = 183, + a85parse_instruction_token, a85parse_rst_arg_token = 260, + a85parse_label_token = 289, a85parse_literal_string_token, + a85parse_include_string_token = 292, a85parse_asm_include_token, + a85parse_literal_name_token = 298, + a85parse_singlequote_string_token = 323, a85parse_integer_token = 325, + a85parse_real_token = 373, a85parse_register_8_bit_token = 380, + a85parse_register_16_bit_token = 401 +} a85parse_token_type; + +typedef struct a85parse_pcb_struct{ + a85parse_token_type token_number, reduction_token, error_frame_token; + int input_code; + int input_value; + int line, column; + int ssx, sn, error_frame_ssx; + int drt, dssx, dsn; + int ss[128]; + a85parse_vs_type vs[128]; + int ag_ap; + char *error_message; + char read_flag; + char exit_flag; + int bts[128], btsx; + int (* const *gt_procs)(void); + int (* const *r_procs)(void); + int (* const *s_procs)(void); + int lab[9], rx, fx; + const unsigned char *key_sp; + int save_index, key_state; + int ag_error_depth, ag_min_depth, ag_tmp_depth; + int ag_rss[2*128], ag_lrss; + char ag_msg[82]; + int ag_resynch_active; +} a85parse_pcb_type; + +#ifndef PRULE_CONTEXT +#define PRULE_CONTEXT(pcb) (&((pcb).cs[(pcb).ssx])) +#define PERROR_CONTEXT(pcb) ((pcb).cs[(pcb).error_frame_ssx]) +#define PCONTEXT(pcb) ((pcb).cs[(pcb).ssx]) +#endif + +#ifndef AG_RUNNING_CODE_CODE +/* PCB.exit_flag values */ +#define AG_RUNNING_CODE 0 +#define AG_SUCCESS_CODE 1 +#define AG_SYNTAX_ERROR_CODE 2 +#define AG_REDUCTION_ERROR_CODE 3 +#define AG_STACK_ERROR_CODE 4 +#define AG_SEMANTIC_ERROR_CODE 5 +#endif + +extern a85parse_pcb_type a85parse_pcb; +void init_a85parse(void); +void a85parse(void); +#endif + diff --git a/src/a85parse.syn b/src/a85parse.syn new file mode 100644 index 0000000..8e2fb1a --- /dev/null +++ b/src/a85parse.syn @@ -0,0 +1,705 @@ +{ +// 8085 Assembler Parser Syntax + +// Written by Kenneth D. Pettit +// This is an input syntax grammer for the Anagram LARL Parser Generator + +} + +[ + auto resynch + disregard WS + disregard cstyle comment + distinguish lexemes + distinguish keywords { 'a-z'+'A-Z' + '0-9' + '_' + '$' + '-' + '+' + 'e' + 'E' } + case sensitive = off + lexeme { integer, literal name, register 8 bit, register 16 bit, hex integer, + decimal integer, real, simple real, literal string, label, + string chars, include string, include chars, literal name, ascii integer, + escape char, asm hex value, singlequote chars, asm include, + singlequote string } + sticky { literal name, integer, label, string chars, decimal integer, ascii integer } + parser file name = ".\\#.cpp" +] + +any text char = ~eof - newline +ascii = 1..126 +WS = ' ' + '\t' +digit = '0-9' +eof = -1 + 0 +hex digit = '0-9' + 'A-F' + 'a-f' +newline = '\n' +letter = 'a-z' + 'A-Z' + '_' +string char = ~eof - ('"' + '\\' + '\n') +rst arg = '0-7' +asm incl char = 'a-z' + 'A-Z' + '0-9' + '_' + '.' + '\\' + '/' +PLUS = '+' +MINUS = '-' + +/* +============================================================================ + Define the target token below. This token is what the parser is trying + to reduce the file to. The token is a sequence of zero or more + statements followed by an end-of-file +============================================================================ +*/ +a85parse $ + -> { statement }..., + eof + +/* +============================================================================ + Define what a comment looks like. We allow C, C++, and assembly style + comments. +============================================================================ +*/ +comment + -> "//", any text char?..., newline + -> ';', any text char?..., newline + -> ',', any text char?..., newline + +cstyle comment + -> "/*", ~eof..., "*/" + + +/* +============================================================================ + Define what any individual statement can look like +============================================================================ +*/ +statement + -> WS?..., expression, '\n' + -> WS?..., expression, comment + -> WS?..., comment + -> WS?..., newline + -> WS?..., cstyle comment + +expression + -> label + -> "include", literal string = gAsm->include(ss[ss_idx--]); + -> "include", include string = gAsm->include(ss[ss_idx--]); + -> "include", asm include = gAsm->include(ss[ss_idx--]); + -> "#include", literal string = gAsm->include(ss[ss_idx--]); + -> "#include", include string = gAsm->include(ss[ss_idx--]); + -> "#pragma", "list" = gAsm->pragma_list(); + -> "#pragma", "hex" = gAsm->pragma_hex(); + -> "#ifdef", literal name = gAsm->preproc_ifdef(ss[ss_idx--]); + -> "#ifndef", literal name = gAsm->preproc_ifndef(ss[ss_idx--]); + -> "#else" = gAsm->preproc_else(); + -> "#endif" = gAsm->preproc_endif(); + -> "#define", literal name = gAsm->preproc_define(ss[ss_idx--]); + -> "#undef", literal name = gAsm->preproc_undef(ss[ss_idx--]); + -> literal name, "equ", equation = gAsm->equate(ss[ss_idx--]); + -> literal name, "set", equation = gAsm->directive_set(ss[ss_idx--]); + -> label, "equ", equation = gAsm->equate((const char *) -1); + -> label, "set", equation = gAsm->directive_set((const char *) -1); + -> label?, "org", equation = gAsm->directive_org(); + -> label?, "aseg" = gAsm->directive_aseg(); + -> label?, "cseg" = gAsm->directive_cseg(0); + -> label?, "dseg" = gAsm->directive_dseg(0); + -> literal name, "ds", equation = { gAsm->label(ss[ss_idx--]); gAsm->directive_ds(); } + -> label?, "ds", equation = gAsm->directive_ds(); + -> literal name, "db", expression list, WS?... = { gAsm->label(ss[ss_idx--]); gAsm->directive_db(); } + -> label?, "db", expression list, WS?... = gAsm->directive_db(); + -> literal name, "dw", expression list, WS?... = { gAsm->label(ss[ss_idx--]); gAsm->directive_dw(); } + -> label?, "dw", expression list, WS?... = gAsm->directive_dw(); + -> label?, "extrn", name list = gAsm->directive_extern(); + -> label?, "extern", name list = gAsm->directive_extern(); + -> label?, "public", name list = gAsm->directive_public(); + -> label?, "name", literal name = gAsm->directive_name(ss[ss_idx--]); + -> label?, "stkln", equation = gAsm->directive_stkln(); + -> label?, "end" = gAsm->directive_end(""); + -> label?, "end", literal name = gAsm->directive_end(ss[ss_idx--]); + -> label?, "if", condition, WS?... = gAsm->directive_if(); + -> label?, "else" = gAsm->directive_else(); + -> label?, "endif" = gAsm->directive_endif(); + -> label?, "title", singlequote string = gAsm->directive_title(ss[ss_idx--]); + -> label?, "title", literal string = gAsm->directive_title(ss[ss_idx--]); + -> label?, "page", WS..., integer:n = gAsm->directive_page(n); + -> label?, "page" = gAsm->directive_page(-1); + -> label?, "sym" = gAsm->directive_sym(); + -> label?, "link", asm include = gAsm->directive_link(ss[ss_idx--]); + -> label?, "maclib", literal name = gAsm->directive_maclib(ss[ss_idx--]); + -> label?, instruction list, WS?... + + +expression list + -> literal string = expression_list_literal(); + -> singlequote string + -> equation = expression_list_equation(); + -> expression list, WS?..., ",", WS?..., equation = expression_list_equation(); + -> expression list, WS?..., ",", WS?..., literal string = expression_list_literal(); + -> expression list, WS?..., ",", WS?..., singlequote string = expression_list_literal(); + +/* +============================================================================ + Define a literal name below. A literal name is a sequence of letters + with no space or punctuation between. +============================================================================ +*/ + +name list + -> literal name = gNameList->Add(ss[ss_idx--]); + -> name list, WS?..., ",", WS?..., literal name = gNameList->Add(ss[ss_idx--]); + +literal name + -> literal alpha + -> "$" = { strcpy(ss[++ss_idx], "$"); ss_len = 1; } + +literal alpha + -> letter+'$':c = { ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } + -> literal name, letter+'$':c = { ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } + -> literal name, digit:c = { ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } + +asm include + -> asm incl char:c = { ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } + -> asm include, asm incl char:c = { ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } + +singlequote string + -> singlequote chars, '\'' + +singlequote chars + -> '\'', escape char:ch1, escape char:ch2 = { ss_idx++; ss_len = 2; sprintf(ss[ss_idx], "%c%c", ch1, ch2); } + -> singlequote chars, escape char:c = { ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } + +literal string + -> string chars, '"' + +string chars + -> '"' = { ss_idx++; ss_len = 0; } + -> string chars, string char:c = { ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } + -> string chars, '\\', ~eof - '\n':c = { ss[ss_idx][ss_len++] = '\\'; ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } + -> string chars, '\\', '\n' + +include string + -> include chars, '>' = { ss[ss_idx][ss_len++] = '>'; ss[ss_idx][ss_len] = 0; } + +include chars + -> '<' = { ss[++ss_idx][0] = '<'; ss[ss_idx][1] = 0; ss_len = 1; } + -> include chars, string char - '>':c = { ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } + -> include chars, '\\', ~eof - '\n':c = { ss[ss_idx][ss_len++] = '\\'; ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } + -> include chars, '\\', '\n' + +label + -> literal name, ":" = gAsm->label(ss[ss_idx--]); + + +/* +============================================================================ + Define conditions. Conditions can be expressed using either the + traditional 8085 assembly 'EQ', 'NE' format or using C format syntax + such as '==', '!-', etc. +============================================================================ +*/ +condition + -> condition start, equation = condition(-1); + -> equation = condition(COND_NOCMP); + +condition start + -> equation, {"eq" | "==" | "="} = condition(COND_EQ); + -> equation, {"ne" | "!="} = condition(COND_NE); + -> equation, {"ge" | ">="} = condition(COND_GE); + -> equation, {"le" | "<="} = condition(COND_LE); + -> equation, {"gt" | ">"} = condition(COND_GT); + -> equation, {"lt" | "<"} = condition(COND_LT); + +condition start +// -> equation = { gCond->m_EqLeft = gEq; gEq = new CRpnEquation; } +// -> equation, {"eq" | "==" | "="}, equation = condition(COND_EQ); +// -> equation, {"ne" | "!="}, equation = condition(COND_NE); +// -> equation, {"ge" | ">="}, equation = condition(COND_GE); +// -> equation, {"le" | "<="}, equation = condition(COND_LE); +// -> equation, {"gt" | ">"}, equation = condition(COND_GT); +// -> equation, {"lt" | "<"}, equation = condition(COND_LT); + +/* +============================================================================ + Define equations. We support complex equations that consist of additive, + multiplicative, bit and operators, and functions. Order of presedence + for these components follows standard algebraic presedence. +============================================================================ +*/ + +equation + -> inclusive or exp + +(void) inclusive or exp + -> exclusive or exp + -> inclusive or exp,'|',WS?..., exclusive or exp = gEq->Add(RPN_BITOR); + -> inclusive or exp, "or", WS?...,exclusive or exp = gEq->Add(RPN_BITOR); + +(void) exclusive or exp + -> and exp + -> exclusive or exp, '^', WS?..., and exp = gEq->Add(RPN_BITXOR); + -> exclusive or exp, "xor", WS?..., and exp = gEq->Add(RPN_BITXOR); + +(void) and exp + -> shift exp + -> and exp, '&', WS?..., shift exp = gEq->Add(RPN_BITAND); + -> and exp, "and", WS?..., shift exp = gEq->Add(RPN_BITAND); + +(void) shift exp + -> additive exp + -> shift exp, "<<", WS?..., additive exp = gEq->Add(RPN_LEFTSHIFT); + -> shift exp, "shl", WS?..., additive exp = gEq->Add(RPN_LEFTSHIFT); + -> shift exp, ">>", WS?..., additive exp = gEq->Add(RPN_RIGHTSHIFT); + -> shift exp, "shr", WS?..., additive exp = gEq->Add(RPN_RIGHTSHIFT); + +(void) additive exp + -> multiplicative exp + -> additive exp, '+', WS?..., multiplicative exp = gEq->Add(RPN_ADD); + -> additive exp, '-', WS?..., multiplicative exp = gEq->Add(RPN_SUBTRACT); + +(void) multiplicative exp +// -> primary exp + -> urinary exp + -> multiplicative exp, '*', WS?..., primary exp = gEq->Add(RPN_MULTIPLY); + -> multiplicative exp, '/', WS?..., primary exp = gEq->Add(RPN_DIVIDE); + -> multiplicative exp, '%', WS?..., primary exp = gEq->Add(RPN_MODULUS); + -> multiplicative exp, "mod", WS?..., primary exp = gEq->Add(RPN_MODULUS); + -> multiplicative exp, "**", WS?..., primary exp = gEq->Add(RPN_EXPONENT); + +urinary exp + -> primary exp + -> '!', primary exp = gEq->Add(RPN_NOT); + -> "not", primary exp = gEq->Add(RPN_NOT); + -> '~', primary exp = gEq->Add(RPN_BITNOT); + +primary exp + -> value:n = gEq->Add((double) n); + -> literal name = gEq->Add(ss[ss_idx--]); + -> function + -> '(', equation, ')', WS?... + +(void) function +-> "floor", '(', equation, ')' = gEq->Add(RPN_FLOOR); +-> "ceil", '(', equation, ')' = gEq->Add(RPN_CEIL); +-> "ln", '(', equation, ')' = gEq->Add(RPN_LN); +-> "log", '(', equation, ')' = gEq->Add(RPN_LOG); +-> "sqrt", '(', equation, ')' = gEq->Add(RPN_SQRT); +-> "ip", '(', equation, ')' = gEq->Add(RPN_IP); +-> "fp", '(', equation, ')' = gEq->Add(RPN_FP); + +/* +============================================================================ + Define what values look like +============================================================================ +*/ + +(double) value + -> integer:n = n; + -> real:r = r; + +(int) integer + -> ascii integer:n = n; + -> decimal integer = conv_to_dec(); + -> hex integer = conv_to_hex(); + -> asm hex value, "h" = conv_to_hex(); + -> decimal integer, "h" = conv_to_hex(); + -> decimal integer, "b" = conv_to_bin(); + -> decimal integer, "q" = conv_to_oct(); + -> decimal integer, "d" = conv_to_dec(); + +decimal integer + -> '+', '0-9':n = { int_len = 1; integer[0] = n; integer[1] = 0; } + -> '-', '0-9':n = { int_len = 2; integer[0] = '-', integer[1] = n; integer[2] = 0; } + -> '0-9':n = { int_len = 1; integer[0] = n; integer[1] = 0; } + -> decimal integer, '0-9':n = { integer[int_len++] = n; integer[int_len] = 0; } + -> decimal integer, '_' + -> decimal integer, '$' + +hex integer + -> '0', 'x' + 'X', hex digit:n = { int_len = 1; integer[0] = n; integer[1] = 0; } + -> hex integer, hex digit:n = { integer[int_len++] = n; integer[int_len] = 0; } + +asm hex value + -> decimal integer, 'A-F' + 'a-f':n = { integer[int_len++] = n; integer[int_len] = 0; } + -> asm hex value, hex digit:n = { integer[int_len++] = n; integer[int_len] = 0; } + +(int) ascii integer + -> '\'', escape char:n, '\'' = n; + -> "'\\'" = '\\'; + +(int) escape char + -> ascii - '\\' - '\'':n = n; + -> '\\', '\\' = '\\'; + -> '\\', 'n' = '\n'; + -> '\\', 't' = '\t'; + -> '\\', 'r' = '\r'; + -> '\\', '0' = '\0'; + -> "''" = '\''; + -> '\\', '\'' = '\''; + +(double) real + -> simple real + +(double) simple real + -> decimal integer, '.' = { gDivisor = 1.0; return (double) conv_to_dec(); } + -> '.', '0-9':d = { gDivisor = 10.0; return ((double) (d - '0') / gDivisor); } + -> simple real:r, '0-9':d = { gDivisor *= 10.0; return (r + (double) (d - '0') / gDivisor); } + + +/* +============================================================================ + Define what registers look like +============================================================================ +*/ + +register 8 bit + -> "b" = reg[reg_cnt++] = '0'; + -> "c" = reg[reg_cnt++] = '1'; + -> "d" = reg[reg_cnt++] = '2'; + -> "e" = reg[reg_cnt++] = '3'; + -> "h" = reg[reg_cnt++] = '4'; + -> "l" = reg[reg_cnt++] = '5'; + -> "m" = reg[reg_cnt++] = '6'; + -> "a" = reg[reg_cnt++] = '7'; + +register 16 bit + -> "b" = reg[reg_cnt++] = '0'; + -> "d" = reg[reg_cnt++] = '1'; + -> "h" = reg[reg_cnt++] = '2'; + -> "sp" = reg[reg_cnt++] = '3'; + +stack register + -> "b" = reg[reg_cnt++] = '0'; + -> "d" = reg[reg_cnt++] = '1'; + -> "h" = reg[reg_cnt++] = '2'; + -> "psw" = reg[reg_cnt++] = '3'; + -> "a" = reg[reg_cnt++] = '3'; + +bd register + -> "b" = reg[reg_cnt++] = '0'; + -> "d" = reg[reg_cnt++] = '1'; + +/* +============================================================================ + Define the 8085 instruction set +============================================================================ +*/ +instruction list + -> instruction + -> instruction list, WS?..., '!' + -> instruction list, WS?..., instruction + +instruction + -> "aci", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_ACI); + -> "adc", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_ADC); + -> "add", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_ADD); + -> "adi", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_ADI); + -> "ana", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_ANA); + -> "ani", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_ANI); + -> "ashr" = gAsm->opcode_arg_0 (OPCODE_ASHR); + -> "call", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CALL); + -> "cc", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CC); + -> "cm", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CM); + -> "cma" = gAsm->opcode_arg_0 (OPCODE_CMA); + -> "cmc" = gAsm->opcode_arg_0 (OPCODE_CMC); + -> "cmp", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_CMP); + -> "cnc", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CNC); + -> "cnz", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CNZ); + -> "cp", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CP); + -> "cpe", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CPE); + -> "cpi", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_CPI); + -> "cpo", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CPO); + -> "cz", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CZ); + -> "daa" = gAsm->opcode_arg_0 (OPCODE_DAA); + -> "dad", WS?..., register 16 bit = gAsm->opcode_arg_1reg (OPCODE_DAD); + -> "dcr", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_DCR); + -> "dcx", WS?..., register 16 bit = gAsm->opcode_arg_1reg (OPCODE_DCX); + -> "di" = gAsm->opcode_arg_0 (OPCODE_DI); + -> "dsub" = gAsm->opcode_arg_0 (OPCODE_DSUB); + -> "ei" = gAsm->opcode_arg_0 (OPCODE_EI); + -> "hlt" = gAsm->opcode_arg_0 (OPCODE_HLT); + -> "in", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_IN); + -> "inr", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_INR); + -> "inx", WS?..., register 16 bit = gAsm->opcode_arg_1reg (OPCODE_INX); + -> "jc", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JC); + -> "jd", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JD); + -> "jx", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JD); + -> "jm", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JM); + -> "jmp", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JMP); + -> "jnc", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JNC); + -> "jnd", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JND); + -> "jnx", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JND); + -> "jnz", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JNZ); + -> "jp", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JP); + -> "jpe", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JPE); + -> "jpo", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JPO); + -> "jz", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JZ); + -> "lda", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_LDA); + -> "ldax", WS?..., bd register = gAsm->opcode_arg_1reg (OPCODE_LDAX); + -> "ldeh", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_LDEH); + -> "ldes", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_LDES); + -> "lhld", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_LHLD); + -> "lhlx" = gAsm->opcode_arg_0 (OPCODE_LHLX); + -> "lxi", WS?..., register 16 bit, WS?..., ',', + WS?..., equation = gAsm->opcode_arg_1reg_equ8(OPCODE_LXI); + -> "mov", WS?..., register 8 bit, WS?..., + ",", WS?..., register 8 bit = gAsm->opcode_arg_2reg (OPCODE_MOV); + -> "mvi", WS?..., register 8 bit,WS?..., + ",", WS?..., equation = gAsm->opcode_arg_1reg_equ8(OPCODE_MVI); + -> "nop" = gAsm->opcode_arg_0 (OPCODE_NOP); + -> "ora", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_ORA); + -> "ori", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_ORI); + -> "out", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_OUT); + -> "pchl" = gAsm->opcode_arg_0 (OPCODE_PCHL); + -> "pop", WS?..., stack register = gAsm->opcode_arg_1reg (OPCODE_POP); + -> "push", WS?..., stack register = gAsm->opcode_arg_1reg (OPCODE_PUSH); + -> "ral" = gAsm->opcode_arg_0 (OPCODE_RAL); + -> "rar" = gAsm->opcode_arg_0 (OPCODE_RAR); + -> "rc" = gAsm->opcode_arg_0 (OPCODE_RC); + -> "ret" = gAsm->opcode_arg_0 (OPCODE_RET); + -> "rim" = gAsm->opcode_arg_0 (OPCODE_RIM); + -> "rlc" = gAsm->opcode_arg_0 (OPCODE_RLC); + -> "rlde" = gAsm->opcode_arg_0 (OPCODE_RLDE); + -> "rm" = gAsm->opcode_arg_0 (OPCODE_RM); + -> "rnc" = gAsm->opcode_arg_0 (OPCODE_RNC); + -> "rnz" = gAsm->opcode_arg_0 (OPCODE_RNZ); + -> "rp" = gAsm->opcode_arg_0 (OPCODE_RP); + -> "rpe" = gAsm->opcode_arg_0 (OPCODE_RPE); + -> "rpo" = gAsm->opcode_arg_0 (OPCODE_RPO); + -> "rrc" = gAsm->opcode_arg_0 (OPCODE_RRC); + -> "rst", WS?..., rst arg:c = gAsm->opcode_arg_imm (OPCODE_RST, c); + -> "rz" = gAsm->opcode_arg_0 (OPCODE_RZ); + -> "sbb", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_SBB); + -> "sbi", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_SBI); + -> "shld", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_SHLD); + -> "shlx" = gAsm->opcode_arg_0 (OPCODE_SHLX); + -> "sim" = gAsm->opcode_arg_0 (OPCODE_SIM); + -> "sphl" = gAsm->opcode_arg_0 (OPCODE_SPHL); + -> "sta", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_STA); + -> "stax", WS?..., bd register = gAsm->opcode_arg_1reg (OPCODE_STAX); + -> "stc" = gAsm->opcode_arg_0 (OPCODE_STC); + -> "sub", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_SUB); + -> "sui", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_SUI); + -> "xchg" = gAsm->opcode_arg_0 (OPCODE_XCHG); + -> "xra", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_XRA); + -> "xri", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_XRI); + -> "xthl" = gAsm->opcode_arg_0 (OPCODE_XTHL); + + + +{ // Embedded C + +#include "MString.h" // Include MString header +#include "MStringArray.h" // Include MStringArray header +#include "assemble.h" // Include VTAssembler header + +#ifndef BOOL +typedef int BOOL; +#endif + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +VTAssembler* gAsm = 0; // Pointer to the assembler +CRpnEquation* gEq = 0; // Pointer to active equation +VTObArray* gExpList = 0; // Pointer to active expression list +MStringArray* gNameList = 0; // Pointer to active name list +CCondition* gCond = 0; // Pointer to active condition +char ss[32][256]; // String Stack; +char integer[64]; // Integer storage space +char int_len = 0; // Integer string length +int ss_idx = 0; // String Stack Index +int ss_len = 0; // SS string length +double gDivisor = 1.0; // Current divisor for float converwions +int gTabSize = 4; +char reg[10]; // Register arguments +int reg_cnt = 0; // Register Arg count +int label = 0; // Number of labels on string stack +int name_list_cnt = 0; // Number of strings in name list +int ex_cnt = 0; // Number of expressions in expression list + +void a85parse(void); + +// This function checks the string accumulator for errors +// parsing the file. If there are no errors, check the string +// accumulator to insure it is empty. If anything is left in the +// accumulator, then there is an error with our parser. +void check_string_stack(void) +{ + // If we have no errors... + if (gAsm->m_Errors.GetSize() == 0) + { + // Check string accumulator size + int stringCount; + if ((stringCount = ss_idx) != 0) + { + MString string; + string.Format("Internal Design Parse Error - %d string(s) left on stack!", + stringCount); + gAsm->m_Errors.Add(string); + } + } +} + +// ParseDesignFile is the entry point for parsing design files. The full path of +// the design file should be passed as the only parameter. If the design file is +// parsed successfully, the routine will return TRUE, otherwise it will return +// FALSE. +BOOL ParseASMFile(const char* filename, VTAssembler* pAsm) +{ + if (pAsm == NULL) + return FALSE; + + gAsm = pAsm; + + // Clear old design from the CDesign object + gAsm->ResetContent(); + + // Insure no active equation left over from a previous run + if (gEq != 0) + delete gEq; + if (gExpList != 0) + delete gExpList; + if (gNameList != 0) + delete gNameList; + if (gCond != 0) + delete gCond; + + // Allocate an active equation to be used during parsing + gEq = new CRpnEquation; + gExpList = new VTObArray; + gNameList = new MStringArray; + gCond = new CCondition; + gAsm->m_FileIndex = gAsm->m_Filenames.Add(filename); + + // Try to open the file + if ((gAsm->m_fd = fopen(gAsm->m_Filenames[gAsm->m_FileIndex], "r")) == 0) + return FALSE; + + // Reset the string stack + ss_idx = 0; + ss_len = 0; + int_len = 0; + + // Reset the Register, name, expression, and label counters + reg_cnt = label = ex_cnt = name_list_cnt = 0; + + // Parse the file. + a85parse(); + + fclose(gAsm->m_fd); + + // Check for parser errors + check_string_stack(); + + // Check if errors occured + int count = gAsm->m_Errors.GetSize(); + if (count != 0) + return FALSE; + + // No errors! + return TRUE; +} + +// Define macros to handle input and errors + +#define TAB_SPACING gTabSize + +#define GET_INPUT ((PCB).input_code = gAsm->m_fd != 0 ? \ + fgetc(gAsm->m_fd) : 0) + +#define SYNTAX_ERROR {MString string; string.Format("%s, line %d, column %d", \ + (PCB).error_message, (PCB).line, (PCB).column); gAsm->m_Errors.Add(string); } + +#define PARSER_STACK_OVERFLOW {MString string; string.Format(\ + "\nParser stack overflow, line %d, column %d",\ + (PCB).line, (PCB).column); gAsm->m_Errors.Add(string);} + +#define REDUCTION_TOKEN_ERROR {MString string; string.Format(\ + "\nReduction token error, line %d, column %d", \ + (PCB).line, (PCB).column); gAsm->m_Errors.Add(string);} + +int do_hex(int h, int n) +{ + int temp1, temp2; + + temp2 = h * 16; + temp1 = (n <='9' ? n-'0' : (n | 0x60) - 'a' + 10); + temp1 += temp2; + return temp1; +} + +void expression_list_literal() +{ + CExpression *pExp = new CExpression; + + pExp->m_Literal = ss[ss_idx--]; + gExpList->Add(pExp); +} + +void expression_list_equation() +{ + CExpression *pExp = new CExpression; + + pExp->m_Equation = gEq; + gEq = new CRpnEquation; + + gExpList->Add(pExp); +} + +void condition(int condition) +{ + if (condition == -1) + { + // Get Right hand side equation + gCond->m_EqRight = gEq; + } + else + { + // Save conditional + gCond->m_Condition = condition; + gCond->m_EqLeft = gEq; + } + + // Assign new equation for parser + gEq = new CRpnEquation; +} + +int conv_to_hex() +{ + int temp1; + + sscanf(integer, "%x", &temp1); + + return temp1; +} + +int conv_to_dec() +{ + int temp1; + + sscanf(integer, "%d", &temp1); + + return temp1; +} + +int conv_to_oct() +{ + int temp1; + + sscanf(integer, "%o", &temp1); + + return temp1; +} + +int conv_to_bin() +{ + int temp1, x; + + temp1 = 0; + x = 0; + + while (integer[x] != 0) + temp1 = (temp1 << 1) + integer[x++] - '0'; + + return temp1; +} + +} // End of Embedded C + + diff --git a/src/assemble.cpp b/src/assemble.cpp new file mode 100644 index 0000000..531fe77 --- /dev/null +++ b/src/assemble.cpp @@ -0,0 +1,3034 @@ +/* +======================================================================== +VTAssembler: This class defines an 8085 Macro Assembler for the + VirtualT project. + +======================================================================== +*/ + +#include "VirtualT.h" +#include "assemble.h" +#include "a85parse.h" +#include "elf.h" +#include +#include +#include +#include + +extern CRpnEquation* gEq; +extern VTObArray* gExpList; +extern MStringArray* gNameList; +extern CCondition* gCond; +extern char reg[10]; +extern int reg_cnt; + +#define PCB a85parse_pcb + +extern int ParseASMFile(const char *filename, class VTAssembler *pAsm); + +unsigned char gOpcodeType[INST_ORG] = { 0, + OPCODE_1REG, OPCODE_REG_EQU16, OPCODE_1REG, OPCODE_1REG, // 1-4 + OPCODE_1REG, OPCODE_1REG, OPCODE_1REG, OPCODE_REG_IMM, // 5-8 + OPCODE_1REG, OPCODE_1REG, OPCODE_1REG, OPCODE_1REG, // 9-12 + OPCODE_1REG, OPCODE_1REG, OPCODE_1REG, OPCODE_1REG, // 13-16 + OPCODE_1REG, OPCODE_1REG, OPCODE_1REG, OPCODE_NOARG, // 17-20 + OPCODE_EQU8, OPCODE_EQU16, OPCODE_NOARG, OPCODE_NOARG, // 21-24 + OPCODE_EQU16, OPCODE_NOARG, OPCODE_EQU8, OPCODE_EQU16, // 25-28 + OPCODE_NOARG, OPCODE_2REG, OPCODE_NOARG, OPCODE_NOARG, // 29-32 + OPCODE_NOARG, OPCODE_NOARG, OPCODE_NOARG, OPCODE_NOARG, // 33-36 + OPCODE_NOARG, OPCODE_NOARG, OPCODE_NOARG, OPCODE_NOARG, // 37-40 + OPCODE_NOARG, OPCODE_NOARG, OPCODE_NOARG, OPCODE_NOARG, // 41-44 + OPCODE_NOARG, OPCODE_NOARG, OPCODE_NOARG, OPCODE_NOARG, // 45-48 + OPCODE_NOARG, OPCODE_NOARG, OPCODE_EQU16, OPCODE_EQU16, // 49-52 + OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, // 53-56 + OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU8, OPCODE_EQU8, // 57-60 + OPCODE_NOARG, OPCODE_NOARG, OPCODE_NOARG, OPCODE_NOARG, // 61-64 + OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, // 55-68 + OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, // 69-72 + OPCODE_NOARG, OPCODE_EQU16, OPCODE_EQU16, OPCODE_NOARG, // 73-76 + OPCODE_EQU16, OPCODE_EQU8, OPCODE_EQU8, OPCODE_EQU8, // 77-80 + OPCODE_EQU8, OPCODE_EQU8, OPCODE_EQU8, OPCODE_EQU8, // 81-84 + OPCODE_EQU8, OPCODE_IMM, OPCODE_EQU16, OPCODE_NOARG, // 85-88 + OPCODE_NOARG // 89 +}; + +unsigned char gOpcodeBase[INST_ORG] = { 0, + 0x0A, 0x01, 0x02, 0x03, 0x0B, 0x04, 0x05, 0x06, // 1-8 + 0x80, 0x88, 0x90, 0x98, 0xA0, 0xA8, 0xB0, 0xB8, // 2-16 + 0x09, 0xC1, 0xC5, 0x27, 0x28, 0x2A, 0x2F, 0x30, // 17-24 + 0x32, 0x37, 0x38, 0x3A, 0x3F, 0x40, 0x07, 0x08, // 25-32 + 0x1F, 0x00, 0x0F, 0x10, 0x17, 0x18, 0xC0, 0xC8, // 33-40 + 0xD0, 0xD8, 0xE0, 0xE8, 0xF0, 0xF8, 0x20, 0xD9, // 41-48 + 0xE9, 0xF9, 0xC2, 0xCA, 0xD2, 0xDA, 0xE2, 0xEA, // 49-56 + 0xF2, 0xFA, 0xD3, 0xDB, 0xE3, 0xEB, 0xF3, 0xFB, // 57-64 + 0xC4, 0xCC, 0xD4, 0xDC, 0xE4, 0xEC, 0xF4, 0xFC, // 65-72 + 0x22, 0xCD, 0xDD, 0xED, 0xFD, 0xC6, 0xCE, 0xD6, // 73-80 + 0xDE, 0xE6, 0xEE, 0xF6, 0xFE, 0xC7, 0xC3, 0xC9, // 81-88 + 0x76 // 89 +}; + +unsigned char gShift[20] = { 0, + 4, 4, 4, 4, 4, 3, 3, 3, // 1-8 + 0, 0, 0, 0, 0, 0, 0, 0, // 9-16 + 4, 4, 4 +}; + +void cb_assembler(class Fl_Widget* w, void*) +{ + VTAssembler* pAsm = new VTAssembler; + + int x = sizeof(CInstruction); + + pAsm->Parse("test.asm"); + + delete pAsm; +} + +VTAssembler::VTAssembler() +{ + m_List = 0; + m_Hex = 0; + m_IncludeDepth = 0; + m_FileIndex = -1; + m_DebugInfo = 0; + + m_ActiveMod = new CModule; + + m_Symbols = m_ActiveMod->m_Symbols[ASEG]; + m_Instructions = m_ActiveMod->m_Instructions[ASEG]; + m_ActiveAddr = m_ActiveMod->m_ActiveAddr[ASEG]; + + // Initialize IF stack + m_IfDepth = 0; + m_IfStat[0] = IF_STAT_ASSEMBLE; +} + +VTAssembler::~VTAssembler() +{ + ResetContent(); + + delete m_ActiveMod; +} + +void VTAssembler::ResetContent(void) +{ + MString key; + POSITION pos; + int c, count, seg; + + // Loop through each segment + for (seg = 0; seg < 3; seg++) + { + // Delete all symbols + pos = m_ActiveMod->m_Symbols[seg]->GetStartPosition(); + while (pos != NULL) + { + CSymbol* pSymbol; + m_ActiveMod->m_Symbols[seg]->GetNextAssoc(pos, key, (VTObject*&) pSymbol); + delete pSymbol; + } + m_ActiveMod->m_Symbols[seg]->RemoveAll(); + + // Delete all Instrucitons + count = m_ActiveMod->m_Instructions[seg]->GetSize(); + for (c = count - 1; c >= 0; c--) + { + CInstruction* pInst = (CInstruction*) (*m_ActiveMod->m_Instructions[seg])[c]; + delete pInst; + } + m_ActiveMod->m_Instructions[seg]->RemoveAll(); + + // Delete all Relocation objects + count = m_Reloc[seg].GetSize(); + for (c = 0; c < count; c++) + { + CRelocation* pReloc = (CRelocation *) m_Reloc[seg][c]; + delete pReloc; + } + m_Reloc[seg].RemoveAll(); + + // Remove all items from Publics array. The actual items are duplicates + // and will be deleted elsewhere + m_Publics[seg].RemoveAll(); + } + + // Delete all Extern reference object + count = m_Externs.GetSize(); + for (c = 0; c < count; c++) + { + CExtern* pExt = (CExtern *) m_Externs[c]; + delete pExt; + } + m_Externs.RemoveAll(); + + // Delete all undefined symbols + m_UndefSymbols.RemoveAll(); + + // Delete all errors + m_Errors.RemoveAll(); + + // Delete filenames parsed + m_Filenames.RemoveAll(); + m_FileIndex = -1; + + m_Hex = 0; + m_List = 0; + m_Address = 0; + + // Initialize IF stack + m_IfDepth = 0; + m_IfStat[0] = IF_STAT_ASSEMBLE; +} + +/* +============================================================================ +The parser calls this function when it detects a list output pragma. +============================================================================ +*/ +void VTAssembler::pragma_list() +{ + if (m_IfStat[m_IfDepth] == IF_STAT_ASSEMBLE) + m_List = 1; +} + +/* +============================================================================ +The parser calls this function when it detects a hex output pragma. +============================================================================ +*/ +void VTAssembler::pragma_hex() +{ + if (m_IfStat[m_IfDepth] == IF_STAT_ASSEMBLE) + m_Hex = 1; +} + +/* +============================================================================ +This function evaluates equations and attempts to determine a numeric value +for the equation. If a numeric value can be achieved, it updates the value +parameter and returns TRUE. If it cannot achieve a numeric value, the +function returns FALSE, and creates an error report in design if the +reportError flag is TRUE. +============================================================================ +*/ +int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, + int reportError) +{ + double s1, s2; + CSymbol* symbol; + MString errMsg, temp; + double stack[200]; + int stk = 0; + int int_value; + const char* pStr; + int c, seg, local; + VTObject* dummy; + + // Get count of number of operations in equation and initalize stack + int count = eq->m_OperationArray.GetSize(); + + for (c = 0; c < count; c++) + { + CRpnOperation& op = eq->m_OperationArray[c]; + switch (op.m_Operation) + { + case RPN_VALUE: + stack[stk++] = op.m_Value; + break; + + case RPN_VARIABLE: + // Try to find variable in equate array + temp = op.m_Variable; + local = 0; + if ((temp[0] == '$') && (temp[1] != 0)) + { + temp = m_LastLabel + "%%" + op.m_Variable; + local = 1; + } + pStr = (const char *) temp; + symbol = (CSymbol *) 0; + for (seg = 0; seg < 3; seg++) + { + if (m_ActiveMod->m_Symbols[seg]->Lookup(pStr, (VTObject *&) symbol)) + break; + } + if (symbol != (CSymbol*) 0) + { + // If symbol has no vaule, try to get it + if ((symbol->m_SymType & SYM_HASVALUE) == 0) + { + if ((symbol->m_SymType & 0xFF) == SYM_EXTERN) + return 0; + + if (GetValue(symbol->m_Name, int_value)) + { + stack[stk++] = int_value; + break; + } + else + { + if (reportError) + { + errMsg.Format("Error in line %d(%s): Symbol %s has no numeric value", + m_Line, (const char *) m_Filenames[m_FileIndex], + (const char *) op.m_Variable); + m_Errors.Add(errMsg); + } + return 0; + } + } + + // Check if equate has a numeric value associated with it + if (symbol->m_SymType & SYM_HASVALUE) + { + stack[stk++] = symbol->m_Value; + } + } + else if (temp == "$") + stack[stk++] = m_Address; + else // Genereate error indication + { + if (reportError) + { + // Check if thie symbol has already been declared undefined + if (!m_UndefSymbols.Lookup(op.m_Variable, dummy)) + { + if (local) + errMsg.Format("Error in line %d(%s): Local symbol %s undefined", m_Line, + (const char *) m_Filenames[m_FileIndex], (const char *) op.m_Variable); + else + errMsg.Format("Error in line %d(%s): Symbol %s undefined", m_Line, + (const char *) m_Filenames[m_FileIndex], (const char *) op.m_Variable); + m_Errors.Add(errMsg); + m_UndefSymbols[op.m_Variable] = 0; + } + } + return 0; + } + break; + + case RPN_MULTIPLY: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = s2 * s1; + break; + + case RPN_DIVIDE: + s2 = stack[--stk]; + s1 = stack[--stk]; + if (s2 == 0.0) + { + // Divide by zero error + if (reportError) + { + errMsg.Format("Error in line %d(%s): Divide by zero!", m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(errMsg); + } + return 0; + } + stack[stk++] = s1 / s2; + break; + + case RPN_ADD: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = s1 + s2; + break; + + case RPN_SUBTRACT: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = s1 - s2; + break; + + case RPN_EXPONENT: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = pow(s1, s2); + break; + + case RPN_MODULUS: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = (double) ((int) s1 % (int) s2); + break; + + case RPN_BITOR: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = (double) ((int) s2 | (int) s1); + break; + + case RPN_BITAND: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = (double) ((int) s2 & (int) s1); + break; + + case RPN_BITXOR: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = (double) ((int) s1 ^ (int) s2); + break; + + case RPN_LEFTSHIFT: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = (double) ((int) s1 << (int) s2); + break; + + case RPN_RIGHTSHIFT: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = (double) ((int) s1 >> (int) s2); + break; + + case RPN_FLOOR: + s1 = stack[--stk]; + stack[stk++] = floor(s1); + break; + + case RPN_CEIL: + s1 = stack[--stk]; + stack[stk++] = ceil(s1); + break; + + case RPN_IP: + s1 = stack[--stk]; + stack[stk++] = floor(s1); + break; + + case RPN_FP: + s1 = stack[--stk]; + stack[stk++] = s1 - floor(s1); + break; + + case RPN_LN: + s1 = stack[--stk]; + stack[stk++] = log(s1); + break; + + case RPN_LOG: + s1 = stack[--stk]; + stack[stk++] = log10(s1); + break; + + case RPN_SQRT: + s1 = stack[--stk]; + stack[stk++] = sqrt(s1); + break; + } + } + + // Get the result from the equation and return to calling function + *value = stack[--stk]; + + return 1; +} + +int VTAssembler::GetValue(MString & string, int & value) +{ + int c, len; + int numericVal = 1; + double dValue; + + // Get length of string + len = string.GetLength(); + + // First check if string is a numeric value + for (c = 0; c < len; c++) + if ((string[c] > '9') || (string[c] < '0') && string[c] != '-') + { + numericVal = 0; + break; + } + + if (numericVal) + { + value = atoi((const char *) string); + return 1; + } + + // Make the string uppercase and search for it in the symbol table + // For each segment for each module + CSymbol* pSymbol = NULL; + MString myStr = string; + if ((string[0] == '$') && (string[1] != 0)) + { + myStr = m_LastLabel + "%%" + string; + } + for (c = 0; c < 3; c++) + { + if (m_ActiveMod->m_Symbols[c]->Lookup(myStr, (VTObject*&) pSymbol)) + { + // Check if symbol has been evaluated yet + if (pSymbol->m_SymType & SYM_HASVALUE) + { + value = pSymbol->m_Value; + return 1; + } + + // Evaluate the equation and save the value if any. Report errors. + if (pSymbol->m_Equation != NULL) + { + if (Evaluate(pSymbol->m_Equation, &dValue, 0)) + { + value = (int) dValue; + pSymbol->m_Value = (long) dValue; + pSymbol->m_SymType |= SYM_HASVALUE; + return 1; + } + } + } + } + + return 0; +} + +/* +=========================================================================================== +Function to process zero argument opcodes +=========================================================================================== +*/ +void VTAssembler::opcode_arg_0(int opcode) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + + // Update line number + m_Line = (PCB).line; + + // Read operand (register) from string accumulator + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = opcode; // Set opcode value + pInst->m_Line = m_Line; // Get Line number + pInst->m_Address = m_Address++; // Get current program address + m_ActiveAddr->length++; // Update add range length + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + m_Instructions->Add(pInst); // Save instruction + } +} + +/* +=========================================================================================== +Function to process opcodes that take a single register argument +=========================================================================================== +*/ +void VTAssembler::opcode_arg_1reg(int opcode) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + reg_cnt--; // Pop register arg from stack + return; + } + + // Update line number + m_Line = (PCB).line; + + // Read operand (register) from register stack + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = opcode; // Set opcode value + pInst->m_Operand1 = new MString; // Allocte operand object + pInst->m_Operand1->Format("%c", reg[--reg_cnt]); // Get register operand + pInst->m_Line = m_Line; // Get Line number + pInst->m_Address = m_Address++; // Get current program address + m_ActiveAddr->length++; // Update add range length + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + m_Instructions->Add(pInst); // Save instruction + } +} + +/* +=========================================================================================== +Function to process opcodes that take a single register argument +=========================================================================================== +*/ +void VTAssembler::opcode_arg_imm(int opcode, char c) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + + // Update line number + m_Line = (PCB).line; + + // Read operand (register) from register stack + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = opcode; // Set opcode value + pInst->m_Operand1 = new MString; // Allocte operand object + pInst->m_Operand1->Format("%c", c); // Get register operand + pInst->m_Line = m_Line; // Get Line number + pInst->m_Address = m_Address++; // Get current program address + m_ActiveAddr->length++; // Update add range length + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + m_Instructions->Add(pInst); // Save instruction + } +} + +/* +=========================================================================================== +Function to process opcodes that take two register argument +=========================================================================================== +*/ +void VTAssembler::opcode_arg_2reg(int opcode) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + reg_cnt -= 2; // Pop unused register args from stack + return; + } + + // Update line number + m_Line = (PCB).line; + + // Read operands (2 registers) from Register stack + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = opcode; // Set opcode value + pInst->m_Group = (VTObject *) (int) reg[--reg_cnt]; // Get register operand + pInst->m_Operand1 = new MString; // Allocte operand object + pInst->m_Operand1->Format("%c", reg[--reg_cnt]); // Get register operand + pInst->m_Line = m_Line; // Get Line number + pInst->m_Address = m_Address++; // Get current program address + m_ActiveAddr->length++; // Update add range length + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + m_Instructions->Add(pInst); // Save instruction + } +} + +/* +=========================================================================================== +Function to process opcodes that take a single register argument and an equation that +results in an 8-bit value +=========================================================================================== +*/ +void VTAssembler::opcode_arg_1reg_equ8(int opcode) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + reg_cnt--; // Pop unused reg operand from stack + delete gEq; // Delete the unused equaiton + gEq = new CRpnEquation; // Allocate new equation for parser + return; + } + + // Update line number + m_Line = (PCB).line; + + // Read operands (register & equation) from parser + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = opcode; // Set opcode value + pInst->m_Operand1 = new MString; // Allocte operand object + pInst->m_Operand1->Format("%c", reg[--reg_cnt]); // Get register operand + pInst->m_Group = gEq; // Get equation + pInst->m_Line = m_Line; // Get Line number + pInst->m_Address = m_Address++; // Get current program address + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + + // Allocate new equation for the parser + gEq = new CRpnEquation; + + // Increment Address again to account for 8-bit value + m_Address++; + m_ActiveAddr->length += 2; // Update add range length + m_Instructions->Add(pInst); // Save instruction + } +} + +/* +=========================================================================================== +Function to process opcodes that take an 8 bit equation argument +=========================================================================================== +*/ +void VTAssembler::opcode_arg_equ8(int opcode) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + delete gEq; // Delete the unused equaiton + gEq = new CRpnEquation; // Allocate new equation for parser + return; + } + + // Update line number + m_Line = (PCB).line; + + // Read operand (equation) from parser + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = opcode; // Set opcode value + pInst->m_Group = gEq; // Get equation + pInst->m_Line = m_Line; // Get Line number + pInst->m_Address = m_Address++; // Get current program address + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + + // Allocate new equation for the parser + gEq = new CRpnEquation; + + // Increment Address again to account for 8-bit value + m_Address++; + m_ActiveAddr->length += 2; // Update add range length + m_Instructions->Add(pInst); // Save instruction + } +} + +/* +=========================================================================================== +Function to process opcodes that take a 16 bit equation argument +=========================================================================================== +*/ +void VTAssembler::opcode_arg_equ16(int opcode) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + delete gEq; // Delete the unused equaiton + gEq = new CRpnEquation; // Allocate new equation for parser + return; + } + + // Update line number + m_Line = (PCB).line; + + // Read operand (register) from string accumulator + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = opcode; // Set opcode value + pInst->m_Group = gEq; // Get equation + pInst->m_Line = m_Line; // Get Line number + pInst->m_Address = m_Address++; // Get current program address + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + + // Allocate new equation for the parser + gEq = new CRpnEquation; + + // Increment Address to account for 16-bit value + m_Address += 2; + m_ActiveAddr->length += 3; // Update add range length + m_Instructions->Add(pInst); // Save instruction + } +} + +/* +============================================================================ +This function is called when the parser detects an include operation. +============================================================================ +*/ +void VTAssembler::include(const char *filename) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + + // Update line number + m_Line = (PCB).line; + + // Try to open the file + if ((m_fd = fopen(filename, "rb")) == 0) + { + MString errMsg; + errMsg.Format("Error in line %d(%s): Unable to open include file %s", + m_Line, (const char *) m_Filenames[m_FileIndex], (const char *) filename); + m_Errors.Add(errMsg); + return; + } else { +// m_IncludeName[m_IncludeDepth] = m_Filename; + m_IncludeIndex[m_IncludeDepth] = m_FileIndex; + m_IncludeStack[m_IncludeDepth++] = m_fd; + + m_FileIndex = m_Filenames.Add(filename); +// m_Filename = filename; + + a85parse(); + fclose(m_fd); + m_fd = m_IncludeStack[--m_IncludeDepth]; +// m_Filename = m_IncludeName[m_IncludeDepth]; + m_FileIndex = m_IncludeIndex[m_IncludeDepth]; + } +} + +char* types[5] = { "", "a label", "an equate", "a set", "an extern" }; + +/* +============================================================================ +This function is called when the parser detects an equate operation. +============================================================================ +*/ +void VTAssembler::equate(const char *name) +{ + double value; + VTObject* dummy; + int c; + CSymbol* pSymbol; + + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + delete gEq; // Delete the unused equaiton + gEq = new CRpnEquation; // Allocate new equation for parser + return; + } + + // Update line number + m_Line = (PCB).line; + + // Check if converting label to equate + if (name == (const char *) -1) + pSymbol = m_LastLabelSym; + else + pSymbol = new CSymbol; + + // Check if symbol valid + if (pSymbol != NULL) + { + if (name != (const char *) -1) + pSymbol->m_Name = (char *) name; + pSymbol->m_Line = m_Line; + pSymbol->m_FileIndex = m_FileIndex; // Save index of the current file + pSymbol->m_SymType = SYM_EQUATE; + pSymbol->m_pRange = m_ActiveAddr; + + // Try to evaluate the equation. Note that we may not be able to + // successfully evaluate it at this point because it may contain + // a forward reference, so don't report any errors yet. + if (Evaluate(gEq, &value, 0)) + { + pSymbol->m_Value = (long) value; + pSymbol->m_SymType |= SYM_HASVALUE; + } + else + { + // Symbol did not evaluate, save as an equation + pSymbol->m_SymType |= SYM_ISEQ; + } + + // Save equation + pSymbol->m_Equation = gEq; + gEq = new CRpnEquation; + + // Loop through all segments for the ative module and check if symbol exists + if (name != (const char *) -1) + { + for (c = 0; c < 3; c++) + { + if (m_ActiveMod->m_Symbols[c]->Lookup(pSymbol->m_Name, dummy)) + { + MString string; + string.Format("Error in line %d(%s): Symbol %s already defined as %s", + pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex], + (const char *) pSymbol->m_Name, + types[((CSymbol *)dummy)->m_SymType & 0x00FF]); + m_Errors.Add(string); + + // Cleanup + delete pSymbol->m_Equation; + delete pSymbol; + + return; + } + } + + // Assign symbol to active segment + (*m_Symbols)[(const char *) pSymbol->m_Name] = pSymbol; + } + } +} + +/* +============================================================================ +This function is called when the parser detects a label. +============================================================================ +*/ +void VTAssembler::label(const char *label) +{ + VTObject* dummy; + MString string; + int c; + int local; + + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + + // Update line number + m_Line = (PCB).line; + + // Determine is label is local (has format $###) + if (label[0] == '$') + local = 1; + else + local = 0; + + CSymbol* pSymbol = new CSymbol; + if (pSymbol != NULL) + { + if (local) + pSymbol->m_Name = m_LastLabel + "%%" + label; + else + pSymbol->m_Name = label; + pSymbol->m_Line = m_Line; + pSymbol->m_Value = m_Address; + pSymbol->m_FileIndex = m_FileIndex; // Save index of the current file + pSymbol->m_SymType = SYM_LABEL | SYM_HASVALUE; + pSymbol->m_pRange = m_ActiveAddr; + + // Check if label exists in the symbol table for this module + for (c = 0; c < 3; c++) + { + if (m_ActiveMod->m_Symbols[c]->Lookup(pSymbol->m_Name, dummy)) + { + string.Format("Error in line %d(%s): Label %s already defined as %s", + pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex], + (const char *) pSymbol->m_Name, + types[((CSymbol *)dummy)->m_SymType & 0x00FF]); + m_Errors.Add(string); + + // Cleanup + delete pSymbol; + + return; + } + } + + const char *pStr = (const char *) pSymbol->m_Name; + // Assign symbol to active segment + (*m_Symbols)[pStr] = pSymbol; + if (!local) + { + m_LastLabel = pStr; + m_LastLabelSym= pSymbol; + m_LastLabelAdded = 0; + } + else if (m_LastLabelAdded == 0) + { + CInstruction* pInst = new CInstruction; + pInst->m_ID = INST_LABEL; + pInst->m_Operand1 = new MString; + *pInst->m_Operand1 = m_LastLabel; + m_LastLabelAdded = 1; + m_Instructions->Add(pInst); // Save instruction + } + } +} + +void VTAssembler::directive_set(const char *name) +{ + double value; + VTObject* dummy; + int c, symtype; + CSymbol* pSymbol; + + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + delete gEq; // Delete the unused equaiton + gEq = new CRpnEquation; // Allocate new equation for parser + return; + } + + // Update line number + m_Line = (PCB).line; + + // Check if converting label to set + if (name == (const char *) -1) + pSymbol = m_LastLabelSym; + else + pSymbol = new CSymbol; + + // Check if symbol valid + if (pSymbol != NULL) + { + if (name != (const char *) -1) + pSymbol->m_Name = (char *) name; + pSymbol->m_Line = m_Line; + pSymbol->m_FileIndex = m_FileIndex; // Save index of the current file + pSymbol->m_SymType = SYM_SET; + pSymbol->m_pRange = m_ActiveAddr; + + // Try to evaluate the equation. Note that we may not be able to + // successfully evaluate it at this point because it may contain + // a forward reference, so don't report any errors yet. + if (Evaluate(gEq, &value, 0)) + { + pSymbol->m_Value = (long) value; + pSymbol->m_SymType |= SYM_HASVALUE; + } + else + { + // Symbol did not evaluate, save as an equation + pSymbol->m_SymType |= SYM_ISEQ; + } + + // Save equation + pSymbol->m_Equation = gEq; + gEq = new CRpnEquation; + + // Loop through all segments for the ative module and check if symbol exists + if (name != (const char *) -1) + { + for (c = 0; c < 3; c++) + { + if (m_ActiveMod->m_Symbols[c]->Lookup(pSymbol->m_Name, dummy)) + { + symtype = ((CSymbol*) dummy)->m_SymType & 0x00FF; + + // Now insure symbol esists as a SYM_SET object + if (symtype == SYM_SET) + { + // Update value of existing symbol object + if (pSymbol->m_SymType & SYM_HASVALUE) + { + ((CSymbol *) dummy)->m_Value = pSymbol->m_Value; + ((CSymbol *) dummy)->m_SymType |= SYM_HASVALUE; + } + else + ((CSymbol *) dummy)->m_SymType &= ~SYM_HASVALUE; + + // Save equation from the new symbol + ((CSymbol *) dummy)->m_Equation = pSymbol->m_Equation; + + // Delete the newly created CSymbol object + delete pSymbol->m_Equation; + delete pSymbol; + return; + } + else + { + MString string; + string.Format("Error in line %d(%s): Symbol %s already defined as %s", + pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex], + (const char *) pSymbol->m_Name, types[symtype]); + m_Errors.Add(string); + + // Delete the newly created CSymbol object + delete pSymbol->m_Equation; + delete pSymbol; + + return; + } + } + } + + const char *pStr = (const char *) pSymbol->m_Name; + // Assign symbol to active segment + (*m_Symbols)[pStr] = pSymbol; + } + } +} + +/* +============================================================================ +This function is called when the parser detects an org operation. +============================================================================ +*/ +void VTAssembler::directive_org() +{ + double value; + AddrRange* newRange; + AddrRange* thisRange; + AddrRange* prevRange; + + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + delete gEq; // Delete the unused equaiton + gEq = new CRpnEquation; // Allocate new equation for parser + return; + } + + // Update line number + m_Line = (PCB).line; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_ORG; + pInst->m_Line = m_Line; + pInst->m_Group = gEq; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + + // Try to calculate new address + if (Evaluate(gEq, &value, 0)) + { + m_Address = (unsigned short) value; + if (m_ActiveAddr->length != 0) + { + // Allocate a new AddrRange object for this ORG + newRange = new AddrRange; + newRange->address = m_Address; + newRange->length = 0; + + // Find location to insert this object + thisRange = m_ActiveMod->m_UsedAddr[m_ActiveMod->m_ActiveSeg]; + prevRange = 0; + + while ((thisRange != 0) && (thisRange->address < m_Address)) + { + prevRange = thisRange; + thisRange = thisRange->pNext; + } + + // Insert new range in list + if (prevRange->address + prevRange->length == m_Address) + { + delete newRange; + m_ActiveMod->m_ActiveAddr[m_ActiveMod->m_ActiveSeg] = prevRange; + m_ActiveAddr = prevRange; + } + else + { + newRange->pNext = 0; + prevRange->pNext = newRange; + + m_ActiveMod->m_ActiveAddr[m_ActiveMod->m_ActiveSeg] = newRange; + m_ActiveAddr = newRange; + } + } + else + { + m_ActiveAddr->address = m_Address; + } + } + + // Allocate a new equation for the parser + gEq = new CRpnEquation; + + // Add instruction to the active segment + m_Instructions->Add(pInst); + } +} + +void VTAssembler::preproc_ifdef(const char* name) +{ +} + +void VTAssembler::preproc_ifndef(const char* name) +{ +} + +void VTAssembler::preproc_else() +{ +} + +void VTAssembler::preproc_endif() +{ +} + +void VTAssembler::preproc_define(const char *name) +{ +} + +void VTAssembler::preproc_undef(const char *name) +{ +} + +void VTAssembler::directive_aseg() +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + + // Update line number + m_Line = (PCB).line; + + // Save current address in current module + m_ActiveMod->m_Address[m_ActiveMod->m_ActiveSeg] = m_Address; + + // Set segment of current module + m_ActiveMod->m_ActiveSeg = ASEG; + + // Update pointers to assembly objects + m_Instructions = m_ActiveMod->m_Instructions[ASEG]; + m_Symbols = m_ActiveMod->m_Symbols[ASEG]; + m_ActiveAddr = m_ActiveMod->m_ActiveAddr[ASEG]; + + // Update address location + m_Address = m_ActiveMod->m_Address[ASEG]; +} + +void VTAssembler::directive_cseg(int page) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + + // Update line number + m_Line = (PCB).line; + + // Save current address in current module + m_ActiveMod->m_Address[m_ActiveMod->m_ActiveSeg] = m_Address; + + // Set segment of current module + m_ActiveMod->m_ActiveSeg = CSEG; + + // Update pointers to assembly objects + m_Instructions = m_ActiveMod->m_Instructions[CSEG]; + m_Symbols = m_ActiveMod->m_Symbols[CSEG]; + m_ActiveMod->m_Page[CSEG] = page; + m_ActiveAddr = m_ActiveMod->m_ActiveAddr[CSEG]; + + // Update address location + m_Address = m_ActiveMod->m_Address[CSEG]; +} + +void VTAssembler::directive_dseg(int page) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + + // Update line number + m_Line = (PCB).line; + + // Save current address in current module + m_ActiveMod->m_Address[m_ActiveMod->m_ActiveSeg] = m_Address; + + // Set segment of current module + m_ActiveMod->m_ActiveSeg = DSEG; + + // Update pointers to assembly objects + m_Instructions = m_ActiveMod->m_Instructions[DSEG]; + m_Symbols = m_ActiveMod->m_Symbols[DSEG]; + m_ActiveMod->m_Page[DSEG] = page; + m_ActiveAddr = m_ActiveMod->m_ActiveAddr[DSEG]; + + // Update address location + m_Address = m_ActiveMod->m_Address[DSEG]; +} + +void VTAssembler::directive_ds() +{ + double len; + + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + delete gEq; // Delete the unused equaiton + gEq = new CRpnEquation; // Allocate new equation for parser + return; + } + + // Update line number + m_Line = (PCB).line; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_DS; + pInst->m_Line = m_Line; + pInst->m_Group = gEq; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + gEq = new CRpnEquation; + + // Try to evaluate the equation + if (Evaluate((CRpnEquation *) pInst->m_Group, &len, 0)) + { + m_Address += (int) len; + m_ActiveAddr->length += (unsigned short) len; + } + + m_Instructions->Add(pInst); + } +} + +void VTAssembler::directive_db() +{ + int c, len; + + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + for (c = 0; c < gExpList->GetSize(); c++) + delete (*gExpList)[c]; + delete gExpList; // Delete the unused expression list + gExpList = new VTObArray; // Allocate new expresssion list for parser + return; + } + + // Update line number + m_Line = (PCB).line; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_DB; + pInst->m_Line = m_Line; + pInst->m_Group = gExpList; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + + // Update address based on number of items in expression list + len = gExpList->GetSize(); + for (c = 0; c < len; c++) + { + if (((CExpression *) (*gExpList)[c])->m_Equation != NULL) + { + m_Address++; + m_ActiveAddr->length++; // Update add range length + } + else + { + int size = strlen(((CExpression *) (*gExpList)[c])->m_Literal); + m_Address += size; + m_ActiveAddr->length += size; // Update add range length + } + } + + gExpList = new VTObArray; + m_Instructions->Add(pInst); + } +} + +void VTAssembler::directive_dw() +{ + int len, c; + + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + for (c = 0; c < gExpList->GetSize(); c++) + delete (*gExpList)[c]; + delete gExpList; // Delete the unused expression list + gExpList = new VTObArray; // Allocate new expresssion list for parser + return; + } + + // Update line number + m_Line = (PCB).line; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_DW; + pInst->m_Line = m_Line; + pInst->m_Group = gExpList; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + + // Update address based on number of items in expression list + len = gExpList->GetSize(); + for (c = 0; c < len; c++) + { + if (((CExpression *) (*gExpList)[c])->m_Equation != NULL) + { + m_Address += 2; + m_ActiveAddr->length += 2; // Update add range length + } + else + { + int size = strlen(((CExpression *) (*gExpList)[c])->m_Literal); + if (size & 0x01) + size++; + m_Address += size; + m_ActiveAddr->length += size; // Update add range length + } + } + + gExpList = new VTObArray; + m_Instructions->Add(pInst); + } +} + +void VTAssembler::directive_extern() +{ + int c, count, x; + int exists; + CSymbol* pSymbol; + VTObject* dummy; + + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + delete gNameList; // Delete the unused name list + gNameList = new MStringArray; // Allocate new name list for parser + return; + } + + // Update line number + m_Line = (PCB).line; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_EXTERN; + pInst->m_Line = m_Line; + pInst->m_Group = (VTObject *) gNameList; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + + // Add names to symbol table as "extern" + count = gNameList->GetSize(); + for (c = 0; c < count; c++) + { + exists = 0; + + // Check if symbol already exists + for (x = 0; x < 3; x++) + { + if (m_ActiveMod->m_Symbols[x]->Lookup((*gNameList)[c], dummy)) + { + MString string; + string.Format("Error in line %d(%s): Symbol %s already defined as %s", + pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex], + (const char *) (*gNameList)[c], + types[((CSymbol *) dummy)->m_SymType & 0x00FF]); + m_Errors.Add(string); + exists = 1; + } + } + + // If symbol does not exist, add it to the symbol table + if (!exists) + { + pSymbol = new CSymbol; + pSymbol->m_Line = m_Line; + pSymbol->m_FileIndex = m_FileIndex; // Save index of the current file + pSymbol->m_Name = (*gNameList)[c]; + pSymbol->m_SymType = SYM_EXTERN; + (*m_Symbols)[pSymbol->m_Name] = pSymbol; + } + } + + gNameList = new MStringArray; + m_Instructions->Add(pInst); + } +} + +void VTAssembler::directive_public() +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + delete gNameList; // Delete the unused name list + gNameList = new MStringArray; // Allocate new name list for parser + return; + } + + // Update line number + m_Line = (PCB).line; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_PUBLIC; + pInst->m_Line = m_Line; + pInst->m_Group = (VTObject *) gNameList; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + gNameList = new MStringArray; + m_Instructions->Add(pInst); + } +} + +void VTAssembler::directive_sym() +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + + // Update line number + m_Line = (PCB).line; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_SYM; + pInst->m_Line = m_Line; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + m_Instructions->Add(pInst); + } +} + +void VTAssembler::directive_page(int page) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + + // Update line number + m_Line = (PCB).line; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_PAGE; + pInst->m_Line = m_Line; + pInst->m_Operand1 = new MString; // Allocte operand object + pInst->m_Operand1->Format("%d", page); + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + m_Instructions->Add(pInst); + } +} + +void VTAssembler::directive_link(const char *name) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + + // Update line number + m_Line = (PCB).line; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_LINK; + pInst->m_Line = m_Line; + pInst->m_Operand1 = new MString; // Allocte operand object + *pInst->m_Operand1 = name; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + m_Instructions->Add(pInst); + } +} + +void VTAssembler::directive_maclib(const char *name) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + + // Update line number + m_Line = (PCB).line; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_MACLIB; + pInst->m_Line = m_Line; + pInst->m_Operand1 = new MString; // Allocte operand object + *pInst->m_Operand1 = name; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + m_Instructions->Add(pInst); + } +} + +void VTAssembler::directive_name(const char *name) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + + // Update line number + m_Line = (PCB).line; + + // Check if module already has a name + if (m_ActiveMod->m_Name != "") + { + // Report an error + MString string; + + string.Format("Error in line %d(%s): Module name already specified as %s", + m_Line, (const char *) m_Filenames[m_FileIndex], + (const char *) m_ActiveMod->m_Name); + m_Errors.Add(string); + + return; + } + + // Save module name in active CModule object + m_ActiveMod->m_Name = name; +} + +void VTAssembler::directive_title(const char *name) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + + // Update line number + m_Line = (PCB).line; + + // Check if module already has a name + if (m_ActiveMod->m_Title != "") + { + // Report an error + MString string; + + string.Format("Error in line %d(%s): Module title already specified as %s", + m_Line, (const char *) m_Filenames[m_FileIndex], + (const char *) m_ActiveMod->m_Title); + m_Errors.Add(string); + + return; + } + + // Save module name in active CModule object + m_ActiveMod->m_Title = name; +} + +void VTAssembler::directive_stkln() +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + delete gEq; // Delete the unused equation + gEq = new CRpnEquation; // Allocate new equation for parser + return; + } + + // Update line number + m_Line = (PCB).line; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_STKLN; + pInst->m_Line = m_Line; + pInst->m_Group = gEq; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + gEq = new CRpnEquation; + m_Instructions->Add(pInst); + } +} + +void VTAssembler::directive_end(const char *name) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + + // Update line number + m_Line = (PCB).line; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_END; + pInst->m_Line = m_Line; + pInst->m_Operand1 = new MString; // Allocte operand object + *pInst->m_Operand1 = name; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + m_Instructions->Add(pInst); + } +} + +void VTAssembler::directive_if() +{ + double valuel, valuer; + MString err; + + // Update line number + m_Line = (PCB).line; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_IF; + pInst->m_Line = m_Line; + pInst->m_Group = gCond; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + + // First push results from previous IF/ELSE/ENDIF operation so + // we generate "nested if" conditions. Initialize condition to + // EVAL_ERROR in case the condition does not evaluate + if ((m_IfStat[m_IfDepth] == IF_STAT_DONT_ASSEMBLE) || + (m_IfStat[m_IfDepth] == IF_STAT_NESTED_DONT_ASSEMBLE) || + (m_IfStat[m_IfDepth] == IF_STAT_EVAL_ERROR)) + { + m_IfStat[++m_IfDepth] = IF_STAT_NESTED_DONT_ASSEMBLE; + } + else + m_IfStat[++m_IfDepth] = IF_STAT_EVAL_ERROR; + + if (m_IfDepth >= sizeof(m_IfStat)) + { + m_IfDepth--; + err.Format("Error in line %d(%s): Too many nested ifs", m_Line, + (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(err); + gCond = new CCondition; + m_Instructions->Add(pInst); + } + + // Determine if both equations can be evaluated + if (m_IfStat[m_IfDepth] == IF_STAT_EVAL_ERROR) + { + if (Evaluate(gCond->m_EqLeft, &valuel, 0)) + { + // Check if condition contains 2 equations or not + if (gCond->m_EqRight != 0) + { + if (Evaluate(gCond->m_EqRight, &valuer, 0)) + { + m_IfStat[m_IfDepth] = IF_STAT_DONT_ASSEMBLE; + + // Both equations evaluate, check condition + switch (gCond->m_Condition) + { + case COND_EQ: + if (valuel == valuer) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + break; + + case COND_NE: + if (valuel != valuer) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + break; + + case COND_GE: + if (valuel >= valuer) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + break; + + case COND_LE: + if (valuel <= valuer) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + break; + + case COND_GT: + if (valuel > valuer) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + break; + + case COND_LT: + if (valuel < valuer) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + break; + } + } + } + else + { + // Check bit 0 of the evaluated expression from equation 1 + if (((int) valuel) & 0x01) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + else + m_IfStat[m_IfDepth] = IF_STAT_DONT_ASSEMBLE; + } + } + } + gCond = new CCondition; + m_Instructions->Add(pInst); + } +} + +void VTAssembler::directive_else() +{ + MString err; + + // Update line number + m_Line = (PCB).line; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_ELSE; + pInst->m_Line = m_Line; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + m_Instructions->Add(pInst); + + // Process ELSE statement during parsing. First insure else has a matching if + if (m_IfDepth == 0) + { + err.Format("Error in line %d(%s): ELSE without a matching IF", m_Line, + (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(err); + return; + } + + // Now check if the active IF statement is not a NESTED_DONT_ASSEMBLE. + // If it isn't then change the state of the assembly + if (m_IfStat[m_IfDepth] == IF_STAT_ASSEMBLE) + m_IfStat[m_IfDepth] = IF_STAT_DONT_ASSEMBLE; + else + if (m_IfStat[m_IfDepth] == IF_STAT_DONT_ASSEMBLE) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + } +} + +void VTAssembler::directive_endif() +{ + MString err; + + // Update line number + m_Line = (PCB).line; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_ENDIF; + pInst->m_Line = m_Line; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + m_Instructions->Add(pInst); + + // Process ENDIF statement during parsing. First insure else has a matching if + if (m_IfDepth == 0) + { + err.Format("Error in line %d(%s): ENDIF without a matching IF", m_Line, + (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(err); + return; + } + + // Pop If from stack + m_IfDepth--; + } +} + +int VTAssembler::Assemble() +{ + MString err; + int c, count, len, x; + int seg, seg2; + int size; + CInstruction* pInst; + CRelocation* pRel; + CExtern * pExt; + CExpression* pExp; + VTObArray* pExpList; + MStringArray* pNameList; + CSymbol* pSymbol; + AddrRange* pRange; + unsigned char opcode; + unsigned char op1, op2; + unsigned char type; + double value; + char rel_mask; + int valid, extern_label; + + /* + ======================================================================== + Check if active module has a name and assign default name if it does not + ======================================================================== + */ + m_Address = 0; + m_IfDepth = 0; + m_IfStat[0] = IF_STAT_ASSEMBLE; + + /* + ======================================================================== + Loop through eash segment and assemble + ======================================================================== + */ + for (seg = 0; seg < 3; seg++) + { + m_Instructions = m_ActiveMod->m_Instructions[seg]; + m_Symbols = m_ActiveMod->m_Symbols[seg]; + m_Address = 0; + m_ActiveAddr = m_ActiveMod->m_UsedAddr[seg]; + + // Loop through all instructions and substitute equates and create instruction words + count = m_Instructions->GetSize(); + for (c = 0; c < count; c++) + { + pInst = (CInstruction*) (*m_Instructions)[c]; + m_Line = pInst->m_Line; + m_FileIndex = pInst->m_FileIndex; + rel_mask = 0; + + /* + ==================================================================== + First check if instruction is an opcode. Handle opcodes by looking + up the output value in the opcode table + ==================================================================== + */ + if (pInst->m_ID < INST_ORG) + { + // Get base opcode value + opcode = gOpcodeBase[pInst->m_ID]; + type = gOpcodeType[pInst->m_ID]; + valid = 1; + extern_label = 0; + + // Modifiy base opcode based on opcode type + switch (type) + { + case OPCODE_IMM: + opcode |= atoi(*pInst->m_Operand1) << 3; + break; + + case OPCODE_1REG: + case OPCODE_REG_IMM: + case OPCODE_REG_EQU16: + opcode |= atoi(*pInst->m_Operand1) << gShift[pInst->m_ID]; + break; + + case OPCODE_2REG: + opcode |= (int) pInst->m_Group - '0'; + opcode |= atoi(*pInst->m_Operand1) << 3; + break; + } + + // Now determine operand bytes + if ((type == OPCODE_EQU8) || (type == OPCODE_EQU16) || + (type == OPCODE_REG_IMM) || (type == OPCODE_REG_EQU16)) + { + // Try to get value of the equation + if (Evaluate((CRpnEquation *) pInst->m_Group, &value, 1)) + { + // Equation evaluated to a value.check if it is + // relative to a relocatable segment + if (InvalidRelocation((CRpnEquation *) pInst->m_Group, rel_mask)) + { + // Error, equation cannot be evaluted + err.Format("Error in line %d(%s): Equation depends on multiple segments", + pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(err); + valid = 0; + } + + op1 = (int) value & 0xFF; + op2 = ((int) value >> 8) & 0xFF; + } + else + { + if ((type == OPCODE_EQU8) || (type == OPCODE_REG_IMM)) + size = 1; + else + size = 2; + + // Equation does not evaluate. Check if it is an extern + if (EquationIsExtern((CRpnEquation *) pInst->m_Group, size)) + { + // Add a dummy value (0) with relocation + op1 = 0; + op2 = 0; + value = 0.0; + extern_label = 1; + } + else + { + // Error, equation cannot be evaluted + err.Format("Error in line %d(%s): Equation cannot be evaluated", + pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); +// m_Errors.Add(err); + valid = 0; + } + } + } + + // Add opcode and operands to array + m_AsmBytes[seg][m_Address++] = opcode; + + // Check if operand is PC relative + if ((rel_mask > 1) && valid) + { + // Add relocation information + pRel = new CRelocation; + pRel->m_Address = m_Address; + pRel->m_pSourceRange = m_ActiveAddr; + if (rel_mask & 0x02) + pRel->m_Segment = CSEG; + if (rel_mask & 0x04) + pRel->m_Segment = DSEG; + pRange = m_ActiveMod->m_UsedAddr[pRel->m_Segment]; + while ((pRange != 0) && (pRel->m_pTargetRange == 0)) + { + if ((pRange->address <= (int) value) && + (pRange->address + pRange->length > (int) value)) + { + pRel->m_pTargetRange = pRange; + } + pRange = pRange->pNext; + } + m_Reloc[pRel->m_Segment].Add(pRel); + } + + // Check if operand is extern + if (extern_label) + { + // Add extern linkage information + pExt = new CExtern; + pExt->m_Address = m_Address; + pExt->m_Name = ((CRpnEquation *) + pInst->m_Group)->m_OperationArray[0].m_Variable; + pExt->m_Segment = seg; + pExt->m_Size = size; + pExt->m_pRange = m_ActiveAddr; + m_Externs.Add(pExt); + } + + // Add operands to output + if ((type == OPCODE_REG_IMM) || (type == OPCODE_EQU8) || + (type == OPCODE_EQU16) || (type == OPCODE_REG_EQU16)) + { + m_AsmBytes[seg][m_Address++] = op1; + } + + if ((type == OPCODE_EQU16) || (type == OPCODE_REG_EQU16)) + { + m_AsmBytes[seg][m_Address++] = op2; + } + } + + + /* + ==================================================================== + An ORG instruciton has no FBI portion, so process it separately. + ==================================================================== + */ + else if (pInst->m_ID == INST_ORG) + { + // The parser takes care of this instruction but we need to start a new + // Segment in the .obj file + if (Evaluate((CRpnEquation *) pInst->m_Group, &value, 1)) + { + m_Address = (int) value; + + // Find AddrRange object for this ORG + pRange = m_ActiveMod->m_UsedAddr[seg]; + while (pRange != 0) + { + if ((pRange->address == m_Address) || ((pRange->address < m_Address) && + (pRange->address + pRange->length > m_Address))) + { + m_ActiveMod->m_ActiveAddr[seg] = pRange; + m_ActiveAddr = pRange; + break; + } + + // Point to next AddrRange + pRange = pRange->pNext; + } + } + else + { + err.Format("Error in line %d(%s): Equation cannot be evaluated", + pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(err); + } + } + + /* + ==================================================================== + Deal with DB directive by adding bytes to the output stream + ==================================================================== + */ + else if (pInst->m_ID == INST_DB) + { + // Get count of expression in list + pExpList = (VTObArray *) pInst->m_Group; + len = pExpList->GetSize(); + + // Update address based on number of items in expression list + for (x = 0; x < len; x++) + { + // Get next expression from expression list + pExp = (CExpression *) (*pExpList)[x]; + + // If expression has an equation, try to evaluate it + if (pExp->m_Equation != NULL) + { + if (Evaluate(pExp->m_Equation, &value, 1)) + m_AsmBytes[seg][m_Address++] = (unsigned char) value; + else + { + err.Format("Error in line %d(%s): Equation cannot be evaluated", + pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(err); + } + } + else + { + // Add bytes from the string + int y, str_len; + str_len = pExp->m_Literal.GetLength(); + for (y = 0; y < str_len; y++) + m_AsmBytes[seg][m_Address++] = pExp->m_Literal[y]; + } + } + } + + /* + ==================================================================== + Deal with DW directive by adding bytes to the output stream + ==================================================================== + */ + else if (pInst->m_ID == INST_DW) + { + // Get count of expression in list + pExpList = (VTObArray *) pInst->m_Group; + len = pExpList->GetSize(); + + // Update address based on number of items in expression list + for (x = 0; x < len; x++) + { + // Get next expression from expression list + pExp = (CExpression *) (*pExpList)[x]; + + // If expression has an equation, try to evaluate it + if (pExp->m_Equation != NULL) + { + if (Evaluate(pExp->m_Equation, &value, 1)) + { + m_AsmBytes[seg][m_Address++] = ((unsigned short) value) & 0xFF; + m_AsmBytes[seg][m_Address++] = ((unsigned short) value) >> 8; + } + else + { + err.Format("Error in line %d(%s): Equation cannot be evaluated", + pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(err); + } + } + else + { + // Add bytes from the string + int y, str_len; + str_len = pExt->m_Name.GetLength(); + for (y = 0; y < str_len; y++) + m_AsmBytes[seg][m_Address++] = pExt->m_Name[y]; + if (str_len & 1) + m_AsmBytes[seg][m_Address++] = 0; + } + } + } + + /* + ==================================================================== + Deal with LABEL instruction + ==================================================================== + */ + else if (pInst->m_ID == INST_LABEL) + { + m_LastLabel = *pInst->m_Operand1; + } + /* + ==================================================================== + Deal with DW directive by adding bytes to the output stream + ==================================================================== + */ + else if (pInst->m_ID == INST_DS) + { + if (Evaluate((CRpnEquation *) pInst->m_Group, &value, 1)) + { + // Increment address counter based on equation + m_Address += (int) value; + } + else + { + // Report error + err.Format("Error in line %d(%s): Equation cannot be evaluated", + pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(err); + } + } + /* + ==================================================================== + Deal with PUBLIC directive by insuring all PUBLIC symbols exists and + updating the symbol table with the SYM_PUBLIC bit + ==================================================================== + */ + else if (pInst->m_ID == INST_PUBLIC) + { + // Loop through each item in name list + pNameList = (MStringArray *) pInst->m_Group; + len = pNameList->GetSize(); + for (x = 0; x < len; x++) + { + // Lookup symbol in each segment + for (seg2 = 0; seg2 < 3; seg2++) + { + if (m_ActiveMod->m_Symbols[seg2]->Lookup((*pNameList)[x], + (VTObject *&) pSymbol)) + { + pSymbol->m_SymType |= SYM_PUBLIC; + + // Check if symbol is a relative label + if ((pSymbol->m_SymType & 0x00FF) == SYM_LABEL) + { + m_Publics[seg2].Add(pSymbol); + } + break; + } + else + pSymbol = 0; + } + + // Check if symbol was found in symbol table + if (pSymbol == 0) + { + // Report error + err.Format("Error in line %d(%s): Symbol %s undefined", + pInst->m_Line, (const char *) m_Filenames[m_FileIndex], + (const char *) (*pNameList)[x]); + m_Errors.Add(err); + } + } + } + } + } + + // Check for errors during assembly + if (m_Errors.GetSize() != 0) + return 0; + + return 1; +} + +/* +======================================================================== +This routine checks the specified equation to determine if it depends on +more than one segment. +======================================================================== +*/ +int VTAssembler::CreateObjFile(const char *filename) +{ + Elf32_Ehdr ehdr; + Elf32_Shdr strhdr, str2hdr, symhdr, *aseg_hdr, *cseg_hdr, *dseg_hdr; + Elf32_Shdr *rel_hdrs, null_hdr; + Elf32_Sym sym; + Elf32_Rel rel; + int c, idx; + int aseg_sections, cseg_sections, dseg_sections; + FILE* fd; + CSymbol* pSymbol; + CRelocation* pReloc; + AddrRange* pRange; + CExtern* pExt; + MString key; + POSITION pos; + char sectString[] = "\0.strtab\0.symtab\0.aseg\0.text\0.data\0"; + char relString[] = ".relcseg\0.reldseg\0"; + char debugString[] = ".debug\0"; + int debugStrSize = 7; + int strtab_off = 1; + int symtab_off = 9; + int aseg_off = 17; + int cseg_off = 23; + int dseg_off = 29; + int relcseg_off = 35; + int reldseg_off = 44; + int extern_off = 53; + int seg, len; + int first_aseg_idx, first_cseg_idx, first_dseg_idx; + int shidx, type, bind; + const char * pStr; + + // Now try to open the object file + if ((fd = fopen(filename, "wb+")) == 0) + { + // Report error + return 0; + } + + /* + ============================= + Add ELF header to .OBJ file + ============================= + */ + // Populate the ELF header + ehdr.e_ident[EI_MAG0] = ELFMAG0; + ehdr.e_ident[EI_MAG1] = ELFMAG1; + ehdr.e_ident[EI_MAG2] = ELFMAG2; + ehdr.e_ident[EI_MAG3] = ELFMAG3; + ehdr.e_ident[EI_CLASS] = ELFCLASS8; + ehdr.e_ident[EI_DATA] = ELFDATA2LSB; + ehdr.e_ident[EI_VERSION] = EV_CURRENT; + for (c = EI_PAD; c < EI_NIDENT; c++) + ehdr.e_ident[c] = 0; + ehdr.e_type = ET_REL; // Relocatable object file + ehdr.e_machine = ET_8085; // Model 100 machine + ehdr.e_version = EV_CURRENT; // Version info + ehdr.e_entry = 0; // No entry point for .obj file + ehdr.e_phoff = 0; // No Program Header for .obj file + ehdr.e_shoff = 0; // Fill in Section Header Table offset later + ehdr.e_flags = 0; // No machine specific flags + ehdr.e_ehsize = sizeof(ehdr); // Size of this header + ehdr.e_phentsize = 0; // No program header table + ehdr.e_phnum = 0; // No program header table + ehdr.e_shentsize = sizeof(strhdr);// Size of each section header entry + ehdr.e_shnum = 1; // Initialize to 1 section - the NULL section + ehdr.e_shstrndx = 1; // Make the section name string table the first entry + + // Write ELF header to file + fwrite(&ehdr, sizeof(ehdr), 1, fd); + + /* + =================================== + Create a NULL header + =================================== + */ + // Create section header for string table + null_hdr.sh_name = 0; // Name for NULL header is zero + null_hdr.sh_type = SHT_NULL; // Make section NULL + null_hdr.sh_flags = 0; // No flags for this section + null_hdr.sh_addr = 0; // No address data for string table + null_hdr.sh_offset = 0; // No offset for NULL header + null_hdr.sh_size = 0; // Initialize size to zero + null_hdr.sh_link = 0; // Set link data to zero + null_hdr.sh_info = 0; // Set info byte to zero + null_hdr.sh_addralign = 0; // Set allignment data to zero + null_hdr.sh_entsize = 0; // String table does not have equal size entries + + /* + =================================== + Create STRTAB section for .OBJ file + =================================== + */ + // Create section header for string table + strhdr.sh_name = strtab_off; // Put ".strtab" as first entry in table + strhdr.sh_type = SHT_STRTAB; // Make section a string table + strhdr.sh_flags = 0; // No flags for this section + strhdr.sh_addr = 0; // No address data for string table + strhdr.sh_offset = ftell(fd); + strhdr.sh_size = extern_off; // Initialize size to zero -- fill in later + strhdr.sh_link = 0; // Set link data to zero + strhdr.sh_info = 0; // Set info byte to zero + strhdr.sh_addralign = 0; // Set allignment data to zero + strhdr.sh_entsize = 0; // String table does not have equal size entries + ehdr.e_shnum++; // Increment Section Header count + + // Start STRTAB section for section strings + fwrite(sectString, relcseg_off, 1, fd); + fwrite(relString, 18, 1, fd); + if (m_DebugInfo) + { + fwrite(debugString, debugStrSize, 1, fd); + strhdr.sh_size += debugStrSize; + } + + /* + ========================================================= + Now create a STRTAB section for EXTERN and PUBLIC symbols + ========================================================= + */ + // Create section header for string table + str2hdr.sh_name = strtab_off; // Put ".strtab" as first entry in table + str2hdr.sh_type = SHT_STRTAB; // Make section a string table + str2hdr.sh_flags = 0; // No flags for this section + str2hdr.sh_addr = 0; // No address data for string table + str2hdr.sh_offset = ftell(fd); + str2hdr.sh_size = 1; // Initialize size to zero -- fill in later + str2hdr.sh_link = 0; // Set link data to zero + str2hdr.sh_info = 0; // Set info byte to zero + str2hdr.sh_addralign = 0; // Set allignment data to zero + str2hdr.sh_entsize = 0; // String table does not have equal size entries + ehdr.e_shnum++; // Increment Section Header count + + // Start with a null string + fwrite(sectString, 1, 1, fd); + idx = 1; + for (seg = 0; seg < 3; seg++) + { + pos = m_ActiveMod->m_Symbols[seg]->GetStartPosition(); + while (pos != 0) + { + // Get next symbol + m_ActiveMod->m_Symbols[seg]->GetNextAssoc(pos, key, (VTObject *&) pSymbol); + if ((pSymbol->m_SymType & SYM_PUBLIC) || (pSymbol->m_SymType & SYM_EXTERN)) + { + // Add string for this symbol + pSymbol->m_StrtabOffset = idx; + len = strlen(pSymbol->m_Name) + 1; + fwrite(pSymbol->m_Name, len, 1, fd); + str2hdr.sh_size += len; + idx++; + } + } + } + + /* + ========================================== + Create SYMTAB header section to .OBJ file + ========================================== + */ + symhdr.sh_name = symtab_off; // Put ".strtab" as first entry in table + symhdr.sh_type = SHT_SYMTAB; // Make section a symbol table + symhdr.sh_flags = 0; // No flags for this section + symhdr.sh_addr = 0; // No address data for symbol table + symhdr.sh_offset = ftell(fd); + symhdr.sh_size = 0; // Initialize size to zero -- fill in later + symhdr.sh_link = 0; // Set link data to zero + symhdr.sh_info = 0; // Set info byte to zero + symhdr.sh_addralign = 0; // Set allignment data to zero + symhdr.sh_entsize = sizeof(Elf32_Sym);// Symbol table has equal size items + ehdr.e_shnum++; // Increment Section Header count + + // Now add all EXTERN and PUBLIC symbols to string table + idx = 0; + for (seg = 0; seg < 3; seg++) + { + pos = m_ActiveMod->m_Symbols[seg]->GetStartPosition(); + while (pos != 0) + { + // Get next symbol + m_ActiveMod->m_Symbols[seg]->GetNextAssoc(pos, key, (VTObject *&) pSymbol); + if ((pSymbol->m_SymType & SYM_PUBLIC) || (pSymbol->m_SymType & SYM_EXTERN)) + { + // Add Elf32_Sym entry for this symbol + sym.st_name = pSymbol->m_StrtabOffset; + sym.st_value = pSymbol->m_Value; + + // Determine symbol Bind and type + if (pSymbol->m_SymType & SYM_PUBLIC) + bind = STB_GLOBAL; + else + bind = STB_EXTERN; + if ((pSymbol->m_SymType & 0xFF) == SYM_LABEL) + type = STT_FUNC; + else + type = STT_OBJECT; + + sym.st_info = ELF32_ST_INFO(bind, type); + sym.st_other = 0; + sym.st_shndx = 2; + + if ((pSymbol->m_SymType & (SYM_8BIT | SYM_16BIT)) == 0) + { + sym.st_size = 0; + pSymbol->m_Off16 = idx; + fwrite(&sym, sizeof(sym), 1, fd); + idx++; + } + if (pSymbol->m_SymType & SYM_8BIT) + { + sym.st_size = 1; + pSymbol->m_Off8 = idx; + fwrite(&sym, sizeof(sym), 1, fd); + idx++; + } + if (pSymbol->m_SymType & SYM_16BIT) + { + sym.st_size = 2; + pSymbol->m_Off16 = idx; + fwrite(&sym, sizeof(sym), 1, fd); + idx++; + } + + // If symbol is EXTERN, find all m_Externs and update index + if (bind == STB_EXTERN) + { + len = m_Externs.GetSize(); + for (c = 0; c < len; c++) + { + pExt = (CExtern *) m_Externs[c]; + pStr = pExt->m_Name; + if (pSymbol->m_Name == pExt->m_Name) + { + if (pExt->m_Size == 1) + pExt->m_SymIdx = pSymbol->m_Off8; + else + pExt->m_SymIdx = pSymbol->m_Off16; + } + } + } + } + } + } + symhdr.sh_size = len * sizeof(Elf32_Sym); + + /* + ========================================== + Create section for ASEG code + ========================================== + */ + // First count the number of sections needed + aseg_sections = 1; + pRange = m_ActiveMod->m_UsedAddr[ASEG]; + while (pRange->pNext != 0) + { + aseg_sections++; + pRange =pRange->pNext; + } + // Allocate pointers for aseg_section headers + aseg_hdr = (Elf32_Shdr *) malloc(aseg_sections * sizeof(Elf32_Shdr)); + + pRange = m_ActiveMod->m_UsedAddr[ASEG]; + idx = 0; + first_aseg_idx = ehdr.e_shnum; + while (pRange != NULL) + { + if (pRange->length == 0) + { + // If AddrRange is emtpy, don't write it to the .obj file + pRange = pRange->pNext; + aseg_hdr[idx].sh_name = 0; // Indicate empty section + idx++; // Increment to next index + continue; + } + + aseg_hdr[idx].sh_name = aseg_off; // Point to ".aseg" name + aseg_hdr[idx].sh_type = SHT_PROGBITS;// Make section a Program Bits section + aseg_hdr[idx].sh_flags = SHF_ALLOC | SHF_EXECINSTR; // Set flag bits + aseg_hdr[idx].sh_addr = pRange->address;// Address for this section + aseg_hdr[idx].sh_offset = ftell(fd); + aseg_hdr[idx].sh_size = pRange->length; // Get size from AddrRange + aseg_hdr[idx].sh_link = 0; // Set link data to zero + aseg_hdr[idx].sh_info = 0; // Set info byte to zero + aseg_hdr[idx].sh_addralign = 0; // Set allignment data to zero + aseg_hdr[idx].sh_entsize = 0; // Symbol table has equal size items + + // Save the index of this CSEG Section Header for relocation reference + pRange->shidx = ehdr.e_shnum; + + ehdr.e_shnum++; // Increment Section Header count + + // Write data to the file + fwrite(&m_AsmBytes[ASEG][pRange->address], pRange->length, 1, fd); + + // Point to next ASEG address range + pRange = pRange->pNext; + idx++; // Increment to next index + } + + + /* + ========================================== + Create section for CSEG code. CSEGs are + relocatable + ========================================== + */ + // First count the number of sections needed + cseg_sections = 1; + pRange = m_ActiveMod->m_UsedAddr[CSEG]; + while (pRange->pNext != 0) + { + cseg_sections++; + pRange =pRange->pNext; + } + // Allocate pointers for aseg_section headers + cseg_hdr = (Elf32_Shdr *) malloc(cseg_sections * sizeof(Elf32_Shdr)); + + pRange = m_ActiveMod->m_UsedAddr[CSEG]; + idx = 0; + first_cseg_idx = ehdr.e_shnum; + + while (pRange != NULL) + { + if (pRange->length == 0) + { + // If AddrRange is emtpy, don't write it to the .obj file + pRange = pRange->pNext; + cseg_hdr[idx].sh_name = 0; // Indicate empty section + idx++; // Increment to next index + continue; + } + + cseg_hdr[idx].sh_name = cseg_off; // Point to ".cseg" name + cseg_hdr[idx].sh_type = SHT_PROGBITS;// Make section a Program Bits section + cseg_hdr[idx].sh_flags = SHF_ALLOC | SHF_EXECINSTR; // Set flag bits + cseg_hdr[idx].sh_addr = pRange->address;// Address for this section + cseg_hdr[idx].sh_offset = ftell(fd); + cseg_hdr[idx].sh_size = pRange->length; // Get size from AddrRange + cseg_hdr[idx].sh_link = 0; // Set link data to zero + cseg_hdr[idx].sh_info = 0; // Set info byte to zero + cseg_hdr[idx].sh_addralign = 0; // Set allignment data to zero + cseg_hdr[idx].sh_entsize = 0; // Symbol table has equal size items + + // Save the index of this CSEG Section Header for relocation reference + pRange->shidx = ehdr.e_shnum; + + ehdr.e_shnum++; // Increment Section Header count + + // Write data to the file + fwrite(&m_AsmBytes[CSEG][pRange->address], pRange->length, 1, fd); + + // Point to next ASEG address range + pRange = pRange->pNext; + idx++; // Increment to next index + } + + + /* + ========================================== + Create section for DSEG code. DSEGs are + relocatable + ========================================== + */ + // First count the number of sections needed + dseg_sections = 1; + pRange = m_ActiveMod->m_UsedAddr[DSEG]; + while (pRange->pNext != 0) + { + dseg_sections++; + pRange =pRange->pNext; + } + // Allocate pointers for aseg_section headers + dseg_hdr = (Elf32_Shdr *) malloc(dseg_sections * sizeof(Elf32_Shdr)); + + pRange = m_ActiveMod->m_UsedAddr[DSEG]; + idx = 0; + first_dseg_idx = ehdr.e_shnum; + while (pRange != NULL) + { + if (pRange->length == 0) + { + // If AddrRange is emtpy, don't write it to the .obj file + pRange = pRange->pNext; + dseg_hdr[idx].sh_name = 0; // Indicate empty section + idx++; // Increment to next index + continue; + } + + dseg_hdr[idx].sh_name = dseg_off; // Point to ".dseg" name + dseg_hdr[idx].sh_type = SHT_PROGBITS;// Make section a Program Bits section + dseg_hdr[idx].sh_flags = SHF_WRITE; // Set flag bits + dseg_hdr[idx].sh_addr = pRange->address;// Address for this section + dseg_hdr[idx].sh_offset = ftell(fd); + dseg_hdr[idx].sh_size = pRange->length; // Get size from AddrRange + dseg_hdr[idx].sh_link = 0; // Set link data to zero + dseg_hdr[idx].sh_info = 0; // Set info byte to zero + dseg_hdr[idx].sh_addralign = 0; // Set allignment data to zero + dseg_hdr[idx].sh_entsize = 0; // Symbol table has equal size items + + // Save the index of this CSEG Section Header for relocation reference + pRange->shidx = ehdr.e_shnum; + + ehdr.e_shnum++; // Increment Section Header count + + // Write data to the file + fwrite(&m_AsmBytes[DSEG][pRange->address], pRange->length, 1, fd); + + // Point to next ASEG address range + pRange = pRange->pNext; + idx++; // Increment to next index + } + + /* + ======================================= + Add relocation sections to .OBJ file + ======================================= + */ + rel_hdrs = (Elf32_Shdr *) malloc((dseg_sections + + cseg_sections) * sizeof(Elf32_Shdr)); + idx = 0; + pRange = m_ActiveMod->m_UsedAddr[CSEG]; + while (idx < dseg_sections + cseg_sections) + { + if (idx < cseg_sections) + { + rel_hdrs[idx].sh_name = relcseg_off; + seg = CSEG; + } + else + { + rel_hdrs[idx].sh_name = reldseg_off; + seg = DSEG; + } + rel_hdrs[idx].sh_type = SHT_REL; // Make section a relocation section + rel_hdrs[idx].sh_flags = 0; // No flag bits for relocation section + rel_hdrs[idx].sh_addr = 0; // No address specifier for relocaton section + rel_hdrs[idx].sh_offset = ftell(fd);// Fill in offset later + rel_hdrs[idx].sh_size = 0; // Fill in size later + rel_hdrs[idx].sh_link = 3; // Point to symtab section + rel_hdrs[idx].sh_info = pRange->shidx; + rel_hdrs[idx].sh_addralign = 0; // No alignment requirements + rel_hdrs[idx].sh_entsize = sizeof(Elf32_Rel); + + // Generage Elf32_Rel object for each relocation relative to this section + len = m_Reloc[seg].GetSize(); + + // Loop through all relocation items in seg + for (c = 0; c < len; c++) + { + // Check if this relocation relative to current section + pReloc = (CRelocation *) m_Reloc[seg][c]; + if (pReloc->m_pTargetRange == pRange) + { + + if (pReloc->m_pSourceRange->shidx >= first_dseg_idx) + { + shidx = pReloc->m_pSourceRange->shidx - first_dseg_idx; + rel.r_offset = pReloc->m_Address - dseg_hdr[shidx].sh_addr + + dseg_hdr[shidx].sh_offset; + rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); + } + else if (pReloc->m_pSourceRange->shidx >= first_cseg_idx) + { + shidx = pReloc->m_pSourceRange->shidx - first_cseg_idx; + rel.r_offset = pReloc->m_Address - cseg_hdr[shidx].sh_addr + + cseg_hdr[shidx].sh_offset; + rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); + } + else + { + shidx = pReloc->m_pSourceRange->shidx - first_aseg_idx; + rel.r_offset = pReloc->m_Address - aseg_hdr[shidx].sh_addr + + aseg_hdr[shidx].sh_offset; + rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); + } + + // Update size of header + rel_hdrs[idx].sh_size += sizeof(Elf32_Rel); + + // Write entry to file + fwrite(&rel, sizeof(Elf32_Rel), 1, fd); + } + } + + // Loop through externs + len = m_Externs.GetSize(); + for (c = 0; c < len; c++) + { + // Get next extern from array + pExt = (CExtern *) m_Externs[c]; + + // Check if extern is for this address range + if (pExt->m_pRange == pRange) + { + // Set address for this relocation + rel.r_offset = pExt->m_Address; + rel.r_info = ELF32_R_INFO(pExt->m_SymIdx, SR_EXTERN); + + // Update size of header + rel_hdrs[idx].sh_size += sizeof(Elf32_Rel); + + // Write entry to file + fwrite(&rel, sizeof(Elf32_Rel), 1, fd); + } + } + + // Search for PUBLIC symbols in this section + len = m_Publics[seg].GetSize(); + for (c = 0; c < len; c++) + { + pSymbol = (CSymbol *) m_Publics[seg][c]; + + rel.r_offset = 0; + if (pSymbol->m_SymType & SYM_8BIT) + rel.r_info = ELF32_R_INFO(pSymbol->m_Off8, SR_PUBLIC); + else + rel.r_info = ELF32_R_INFO(pSymbol->m_Off16, SR_PUBLIC); + + // Update size of header + rel_hdrs[idx].sh_size += sizeof(Elf32_Rel); + + // Write entry to file + fwrite(&rel, sizeof(Elf32_Rel), 1, fd); + } + + // Check if anything actually written for this header. If not, we will + // omit writing header to section header table and therefore will not + // update the Elf header section header count + if (rel_hdrs[idx].sh_size != 0) + ehdr.e_shnum++; // Increment Section Header count + + // Update pRange + pRange = pRange->pNext; + if (pRange == 0) + pRange = m_ActiveMod->m_UsedAddr[DSEG]; + + idx++; // Increment to next index + } + + /* + ======================================= + Add debug sections to .OBJ file + ======================================= + */ + + + /* + ======================================= + Write Section Header table to .OBJ file + ======================================= + */ + // Get offset of Section Header Table for ELF header update + ehdr.e_shoff = ftell(fd); + + // Write the NULL Section header + fwrite(&null_hdr, sizeof(null_hdr), 1, fd); + + // Write String Table header + fwrite(&strhdr, sizeof(strhdr), 1, fd); + + // Write String Table 2 header + fwrite(&str2hdr, sizeof(str2hdr), 1, fd); + + // Write Symbol Table header + fwrite(&symhdr, sizeof(symhdr), 1, fd); + + // Write ASEG headers + for (c = 0; c < aseg_sections; c++) + { + if (aseg_hdr[c].sh_name != 0) + fwrite(&aseg_hdr[c], sizeof(Elf32_Shdr), 1, fd); + } + + // Write CSEG headers + for (c = 0; c < cseg_sections; c++) + { + if (cseg_hdr[c].sh_name != 0) + fwrite(&cseg_hdr[c], sizeof(Elf32_Shdr), 1, fd); + } + + // Write DSEG headers + for (c = 0; c < dseg_sections; c++) + { + if (dseg_hdr[c].sh_name != 0) + fwrite(&dseg_hdr[c], sizeof(Elf32_Shdr), 1, fd); + } + + // Write Relocation section headers + for (c = 0; c < cseg_sections + dseg_sections; c++) + { + // Skip writing empty headers + if (rel_hdrs[c].sh_size == 0) + continue; + + fwrite(&rel_hdrs[c], sizeof(Elf32_Shdr), 1, fd); + } + + // Write Debug section headers + + // Seek to beginning and update Elf Header + fseek(fd, SEEK_SET, 0); + fwrite(&ehdr, sizeof(ehdr), 1, fd); + + // Close the .OBJ file + fclose(fd); + + // Free memory used during build + free(aseg_hdr); + free(cseg_hdr); + free(dseg_hdr); + free(rel_hdrs); + + return 1; +} + +/* +======================================================================== +This routine checks the specified equation to determine if it depends on +more than one segment. +======================================================================== +*/ +int VTAssembler::InvalidRelocation(CRpnEquation *pEq, char &rel_mask) +{ + int c, count; + char rel[3]; + int seg; + CSymbol *pSym; + + count = pEq->m_OperationArray.GetSize(); + for (c = 0; c < 3; c++) + rel[c] = 0; + + for (c = 0; c < count; c++) + { + // Check if operation type is a variable + if (pEq->m_OperationArray[c].m_Operation == RPN_VARIABLE) + { + // Loop through all segments and find the symbol + for (seg = 0; seg < 3; seg++) + { + if (m_ActiveMod->m_Symbols[seg]->Lookup(pEq->m_OperationArray[c].m_Variable, + (VTObject *&) pSym)) + { + if ((pSym->m_SymType & 0x00FF) == SYM_LABEL) + rel[seg] = 1; + + break; + } + } + } + } + + rel_mask = rel[0] | (rel[1] << 1) | (rel[2] << 2); + + // Check if euqation is relative to more than one segment + if (rel[0] + rel[1] + rel[2] > 1) + return 1; + + return 0; +} + +/* +======================================================================== +This routine checks the specified equation to determine if it depends on +more than one segment. +======================================================================== +*/ +int VTAssembler::EquationIsExtern(CRpnEquation* pEq, int size) +{ + int seg, count; + CSymbol* pSym; + + // Get count of operation array + count = pEq->m_OperationArray.GetSize(); + + // Check if quation has exactly 1 operation + if (count == 1) + { + // Check if operation is a variable + if (pEq->m_OperationArray[0].m_Operation == RPN_VARIABLE) + { + for (seg = 0; seg < 3; seg++) + { + if (m_ActiveMod->m_Symbols[seg]->Lookup(pEq->m_OperationArray[0].m_Variable, + (VTObject *&) pSym)) + { + // Check if variable type s EXTERN + if (pSym->m_SymType == SYM_EXTERN) + { + if (size == 1) + pSym->m_SymType |= SYM_8BIT; + if (size == 2) + pSym->m_SymType |= SYM_16BIT; + return 1; + } + } + } + } + } + return 0; +} + +void VTAssembler::Parse(MString filename) +{ + int success = 1; + MString outfile; \ + MString temp; + + if (success = ParseASMFile(filename, this)) + { + // No parse errors! Try to assemble + if (success = Assemble()) + { + // Get Output filename + temp = filename.Right(4); + temp.MakeLower(); + if ((strcmp(temp, ".asm") == 0) || (strcmp(temp, "a85") == 0)) + { + outfile = filename.Left(filename.GetLength()-4); + } + else + outfile = filename; + + // Append .obj to filename + outfile += ".obj"; + + // Generate the object file + CreateObjFile(outfile); + + // Generate a listing file if requested + } + } + + // If not successful, display list of errors + if (!success) + { + char str[120]; + int count, c; + + count = m_Errors.GetSize(); + for (c = 0; c < count; c++) + { + strcpy(str, m_Errors[c]); + } + } + + // Clean up the assembler files + ResetContent(); +} + +void VTAssembler::CreateList() +{ +} + +void VTAssembler::CreateHex() +{ +} + +/* +===================================================================== +Implement the CModule class. This class is used to keep track of +assembly segments that are broken down into modules. +===================================================================== +*/ +CModule::CModule() +{ + int c; + + for (c=0; c < 3; c++) + { + m_Symbols[c] = new VTMapStringToOb; + m_Instructions[c] = new VTObArray; + + m_Address[c] = 0; + m_Page[c] = 0; + m_UsedAddr[c] = 0; + m_UsedAddr[c] = new AddrRange; + m_ActiveAddr[c] = m_UsedAddr[c]; + + m_ActiveAddr[c]->address = 0; + m_ActiveAddr[c]->length = 0; + m_ActiveAddr[c]->pNext = 0; + m_ActiveAddr[c]->shidx = 0; + } + + m_ActiveSeg = 0; +} + +CModule::~CModule() +{ + int c; + AddrRange* pRange; + AddrRange* pNext; + + for (c = 0; c < 3; c++) + { + delete m_Symbols[c]; + delete m_Instructions[c]; + + pRange = m_UsedAddr[c]; + while (pRange != 0) + { + pNext = pRange->pNext; + delete pRange; + pRange = pNext; + } + } +} + +IMPLEMENT_DYNCREATE(CInstruction, VTObject); +IMPLEMENT_DYNCREATE(CCondition, VTObject); + +CInstruction::~CInstruction() +{ + if (m_Operand1 != 0) + delete m_Operand1; + + // We used m_Group to hold reg2. Return without trying to delete m_Group + if (m_ID == OPCODE_MOV) + return; + + if (m_Group != 0) + { + if ((m_ID == INST_PUBLIC) || (m_ID == INST_EXTERN)) + { + MStringArray *pNameList = (MStringArray *) m_Group; + delete pNameList; + } + else if (strcmp(m_Group->GetClass()->m_ClassName, "CRpnEquation") == 0) + { + CRpnEquation *pEq = (CRpnEquation *) m_Group; + delete pEq; + } + else if (strcmp(m_Group->GetClass()->m_ClassName, "CCondition") == 0) + { + CCondition *pCond = (CCondition *) m_Group; + delete pCond; + } + else if (strcmp(m_Group->GetClass()->m_ClassName, "VTObArray") == 0) + { + // Delete all objects in array + int c, count; + VTObArray* pArray = (VTObArray *) m_Group; + count = pArray->GetSize(); + for (c = 0; c < count; c++) + { + VTObject * pOb = pArray->GetAt(c); + delete pOb; + } + delete pArray; + } + else + { + char str[30]; + strcpy(str, m_Group->GetClass()->m_ClassName); + } + } +} diff --git a/src/assemble.h b/src/assemble.h new file mode 100644 index 0000000..5f6fad6 --- /dev/null +++ b/src/assemble.h @@ -0,0 +1,373 @@ +#ifndef _VTAssembler_ +#define _VTAssembler_ + +#include "vtobj.h" +#include "rpn_eqn.h" +#include + +// Define values for opcodes +#define OPCODE_LDAX 1 +#define OPCODE_LXI 2 +#define OPCODE_STAX 3 +#define OPCODE_INX 4 +#define OPCODE_DCX 5 +#define OPCODE_INR 6 +#define OPCODE_DCR 7 +#define OPCODE_MVI 8 +#define OPCODE_ADD 9 +#define OPCODE_ADC 10 +#define OPCODE_SUB 11 +#define OPCODE_SBB 12 +#define OPCODE_ANA 13 +#define OPCODE_XRA 14 +#define OPCODE_ORA 15 +#define OPCODE_CMP 16 +#define OPCODE_DAD 17 +#define OPCODE_POP 18 +#define OPCODE_PUSH 19 +#define OPCODE_DAA 20 +#define OPCODE_LDEH 21 +#define OPCODE_LHLD 22 +#define OPCODE_CMA 23 +#define OPCODE_SIM 24 +#define OPCODE_STA 25 +#define OPCODE_STC 26 +#define OPCODE_LDES 27 +#define OPCODE_LDA 28 +#define OPCODE_CMC 29 +#define OPCODE_MOV 30 +#define OPCODE_RLC 31 +#define OPCODE_DSUB 32 +#define OPCODE_RAR 33 +#define OPCODE_NOP 34 +#define OPCODE_RRC 35 +#define OPCODE_ASHR 36 +#define OPCODE_RAL 37 +#define OPCODE_RLDE 38 +#define OPCODE_RNZ 39 +#define OPCODE_RZ 40 +#define OPCODE_RNC 41 +#define OPCODE_RC 42 +#define OPCODE_RPO 43 +#define OPCODE_RPE 44 +#define OPCODE_RP 45 +#define OPCODE_RM 46 +#define OPCODE_RIM 47 +#define OPCODE_SHLX 48 +#define OPCODE_PCHL 49 +#define OPCODE_SPHL 50 +#define OPCODE_JNZ 51 +#define OPCODE_JZ 52 +#define OPCODE_JNC 53 +#define OPCODE_JC 54 +#define OPCODE_JPO 55 +#define OPCODE_JPE 56 +#define OPCODE_JP 57 +#define OPCODE_JM 58 +#define OPCODE_OUT 59 +#define OPCODE_IN 60 +#define OPCODE_XTHL 61 +#define OPCODE_XCHG 62 +#define OPCODE_DI 63 +#define OPCODE_EI 64 +#define OPCODE_CNZ 65 +#define OPCODE_CZ 66 +#define OPCODE_CNC 67 +#define OPCODE_CC 68 +#define OPCODE_CPO 69 +#define OPCODE_CPE 70 +#define OPCODE_CP 71 +#define OPCODE_CM 72 +#define OPCODE_SHLD 73 +#define OPCODE_CALL 74 +#define OPCODE_JND 75 +#define OPCODE_LHLX 76 +#define OPCODE_JD 77 +#define OPCODE_ADI 78 +#define OPCODE_ACI 79 +#define OPCODE_SUI 80 +#define OPCODE_SBI 81 +#define OPCODE_ANI 82 +#define OPCODE_XRI 83 +#define OPCODE_ORI 84 +#define OPCODE_CPI 85 +#define OPCODE_RST 86 +#define OPCODE_JMP 87 +#define OPCODE_RET 88 +#define OPCODE_HLT 89 + +#define INST_ORG 90 +#define INST_DS 91 +#define INST_DB 92 +#define INST_DW 93 +#define INST_STKLN 94 +#define INST_END 95 +#define INST_PUBLIC 96 +#define INST_EXTERN 97 +#define INST_IF 98 +#define INST_ELSE 99 +#define INST_ENDIF 100 +#define INST_LINK 101 +#define INST_MACLIB 102 +#define INST_PAGE 103 +#define INST_SYM 104 +#define INST_LABEL 105 + +#define SYM_LABEL 1 +#define SYM_EQUATE 2 +#define SYM_SET 3 +#define SYM_EXTERN 4 +#define SYM_8BIT 0x0400 +#define SYM_16BIT 0x0800 +#define SYM_PUBLIC 0x1000 +#define SYM_HASVALUE 0x8000 +#define SYM_ISEQ 0x4000 +#define SYM_ISREG 0x2000 + +#define OPCODE_NOARG 0 +#define OPCODE_1REG 1 +#define OPCODE_2REG 2 +#define OPCODE_IMM 3 +#define OPCODE_REG_IMM 4 +#define OPCODE_EQU8 5 +#define OPCODE_EQU16 6 +#define OPCODE_REG_EQU16 7 + +#define PAGE 1 +#define INPAGE 2 + +#define COND_EQ 1 +#define COND_NE 2 +#define COND_GE 3 +#define COND_LE 4 +#define COND_GT 5 +#define COND_LT 6 +#define COND_NOCMP 7 + +#define IF_STAT_ASSEMBLE 1 +#define IF_STAT_DONT_ASSEMBLE 2 +#define IF_STAT_NESTED_DONT_ASSEMBLE 3 +#define IF_STAT_EVAL_ERROR 4 + +#define ASEG 0 +#define CSEG 1 +#define DSEG 2 + +// Support classes for VTAssembler objects... + +typedef struct sAddrRange { + unsigned short address; + unsigned short length; + unsigned short shidx; + struct sAddrRange* pNext; +} AddrRange; + +class CInstruction : public VTObject +{ +public: + CInstruction() { m_ID = 0; m_Line = -1; m_FileIndex = 0; m_Address = 0; + m_Operand1 = 0; m_Group = NULL; } + ~CInstruction(); + + DECLARE_DYNCREATE(CInstruction); + +// Attributes + unsigned char m_ID; + unsigned char m_FileIndex; + unsigned short m_Address; + long m_Line; + MString* m_Operand1; + VTObject* m_Group; +}; + +class CExpression : public VTObject +{ +public: + CExpression() { m_Equation = 0; } + ~CExpression() { if (m_Equation != 0) delete m_Equation; }; + MString m_Literal; + CRpnEquation* m_Equation; +}; + +class CExtern : public VTObject +{ +public: + CExtern() { m_Address = 0; m_pRange = 0; }; + + MString m_Name; + unsigned short m_Address; + unsigned short m_Segment; + unsigned short m_SymIdx; + AddrRange* m_pRange; + unsigned char m_Size; +}; + +class CCondition : public VTObject +{ +public: + CCondition() { m_EqRight = 0, m_EqLeft = 0; m_Condition = 0;}; + ~CCondition() { if (m_EqLeft != 0) delete m_EqLeft; if (m_EqRight != 0) delete m_EqRight; }; + + DECLARE_DYNCREATE(CCondition); + + CRpnEquation* m_EqRight; + CRpnEquation* m_EqLeft; + int m_Condition; +}; + +class CRelocation : public VTObject +{ +public: + CRelocation() { m_Address = 0; m_Segment = 0; m_pSourceRange = 0; m_pTargetRange = 0; }; + + unsigned short m_Address; + unsigned char m_Segment; + AddrRange* m_pSourceRange; + AddrRange* m_pTargetRange; +}; + +class CSymbol : public VTObject +{ +public: + CSymbol() { m_Line = -1; m_Value = -1; m_SymType = 0; m_Equation = 0; m_StrtabOffset = 0; } + ~CSymbol() { if (m_Equation != 0) delete m_Equation; }; + +// Attributes + + MString m_Name; + CRpnEquation* m_Equation; + long m_Line; + long m_Value; + unsigned short m_SymType; + unsigned short m_FileIndex; + long m_StrtabOffset; + unsigned long m_Off8; + unsigned long m_Off16; + AddrRange* m_pRange; +}; + +class CModule : public VTObject +{ +public: + CModule(); + ~CModule(); + + MString m_Name; // Module name + MString m_Title; // Module title + + int m_ActiveSeg; // Segment we are compiling into + + VTMapStringToOb* m_Symbols[3]; // Array of Symbols for each segment + VTObArray* m_Instructions[3]; // Array of Instructions for each segment + long m_Address[3]; // Address counter for each segment + int m_Page[3]; + + AddrRange* m_UsedAddr[3]; // List of used address ranges + AddrRange* m_ActiveAddr[3]; // Pointer to active address range +}; + +class VTAssembler : public VTObject +{ +public: + VTAssembler(); + ~VTAssembler(); + + // Define Preprocessor functions + void preproc_endif(void); + void preproc_ifndef(const char *name); + void preproc_ifdef(const char *name); + void preproc_else(void); + void preproc_define(const char *name); + void preproc_undef(const char *name); + + // Define Pragma functions + void pragma_list(); + void pragma_hex(); + + // Define directive functions + void directive_set(const char *name); + void directive_aseg(void); + void directive_cseg(int page); + void directive_dseg(int page); + void directive_ds(void); + void directive_db(void); + void directive_dw(void); + void directive_extern(void); + void directive_org(); + void directive_public(void); + void directive_name(const char *name); + void directive_stkln(void); + void directive_end(const char *name); + void directive_if(void); + void directive_else(void); + void directive_endif(void); + void directive_title(const char *name); + void directive_link(const char *name); + void directive_maclib(const char *name); + void directive_sym(void); + void directive_page(int page); + + void include(const char *filename); + void equate(const char *name); + void label(const char *label); + + void opcode_arg_0(int opcode); + void opcode_arg_1reg(int opcode); + void opcode_arg_imm(int opcode, char c); + void opcode_arg_2reg(int opcode); + void opcode_arg_1reg_equ8(int opcode); + void opcode_arg_equ8(int opcode); + void opcode_arg_equ16(int opcode); + +// Attributes +// MString m_Filename; // Filename that design was parsed from + FILE* m_fd; // File descriptor of open file + int m_Line; + int m_FileIndex; + + VTMapStringToOb* m_Modules; // Map of CModules + CModule* m_ActiveMod; // Pointer to active CModule + AddrRange* m_ActiveAddr; // Pointer to active address range + + VTMapStringToOb* m_Symbols; // Array of Symbols + VTObArray* m_Instructions; // Array of Instructions + long m_Address; + MStringArray m_Filenames; // Array of filenames parsed during assembly + MString m_LastLabel; // Save value of last label parsed + CSymbol* m_LastLabelSym; // Pointer to CSymbol object for last label + int m_LastLabelAdded; + + MStringArray m_Errors; // Array of error messages during parsing + unsigned char m_AsmBytes[3][65536]; + VTObArray m_Reloc[3]; + VTObArray m_Externs; + VTObArray m_Publics[3]; // Array of public symbols for each segment + VTMapStringToOb m_UndefSymbols; + int m_List; // Create a list file? + int m_Hex; // Create a HEX file? + int m_DebugInfo; // Include debug info in .obj? + MString m_IncludeName[32]; + FILE* m_IncludeStack[32]; + int m_IncludeIndex[32]; + int m_IncludeDepth; + + char m_IfStat[100]; + int m_IfDepth; + + +// Operations + int Evaluate(class CRpnEquation* eq, double* value, + int reportError); + int GetValue(MString & string, int & value); + void ResetContent(void); + int Assemble(); + int CreateObjFile(const char *filename); + int InvalidRelocation(CRpnEquation* pEq, char &rel_mask); + int EquationIsExtern(CRpnEquation* pEq, int size); + void Parse(MString filename); + void MakeBinary(int val, int length, MString& binary); + void CreateHex(); + void CreateList(); +}; + +#endif diff --git a/src/cpu.h b/src/cpu.h index 8340e35..18a2b9d 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -40,45 +40,66 @@ extern "C" { #endif #define RAMSIZE (gModel==MODEL_T200?24576:32768) -#define ROMSIZE (gModel==MODEL_T200?40960:32768) +//#define ROMSIZE (gModel==MODEL_T200?40960:32768) +#define ROMSIZE gRomSize #define RAMSTART (gModel==MODEL_T200?40960:32768) + #define OPTROMSIZE 32768 #define ADDRESSSPACE 65536 extern uchar cpu[14]; extern uchar *gMemory[64]; +extern int gRomSize; + //extern uchar gSysROM[65536]; //extern uchar gOptROM[32768]; -#define A cpu[0] -#define F cpu[1] -#define B cpu[2] -#define C cpu[3] -#define D cpu[4] -#define E cpu[5] -#define H cpu[6] -#define L cpu[7] -#define PCH cpu[8] -#define PCL cpu[9] -#define SPH cpu[10] -#define SPL cpu[11] +#define A cpu[1] +#define F cpu[0] +#define B cpu[3] +#define C cpu[2] +#define D cpu[5] +#define E cpu[4] +#define H cpu[7] +#define L cpu[6] +#define PCH cpu[9] +#define PCL cpu[8] +#define SPH cpu[11] +#define SPL cpu[10] /* Thoses macros can NOT be set */ +#ifdef WIN32 + +#define AF (*(ushort*)&F) +#define BC (*(ushort*)&C) +#define DE (*(ushort*)&E) +#define HL (*(ushort*)&L) +#define PC (*(ushort*)&PCL) +#define INCPC ((*(ushort*)&PCL)++) +#define INCPC2 ((*(ushort*)&PCL)+=2) +#define DECSP ((*(ushort*)&SPL)--) +#define DECSP2 ((*(ushort*)&SPL)-=2) + +#else + #define AF ((((ushort)A)<<8)|F) #define BC ((((ushort)B)<<8)|C) #define DE ((((ushort)D)<<8)|E) #define HL ((((ushort)H)<<8)|L) #define PC ((((ushort)PCH)<<8)|PCL) -#define SP ((((ushort)SPH)<<8)|SPL) -#define INCPC {PCL++; if(PCL==0) PCH++;} +#define INCPC PCL++; if(PCL==0) PCH++; #define INCPC2 {PCL+=2; if(PCL<2) PCH++;} -#define INCSP {SPL++; if(SPL==0) SPH++;} -#define INCSP2 {SPL+=2; if(SPL<2) SPH++;} -#define DECPC {PCL--; if(PCL==0xff) PCH--;} -#define DECPC2 {PCL-=2; if(PCL>0xfd) PCH--;} #define DECSP {SPL--; if(SPL==0xff) SPH--;} #define DECSP2 {SPL-=2; if(SPL>0xfd) SPH--;} +#endif + +#define DECPC {PCL--; if(PCL==0xff) PCH--;} +#define DECPC2 {PCL-=2; if(PCL>0xfd) PCH--;} +#define SP ((((ushort)SPH)<<8)|SPL) +#define INCSP {SPL++; if(SPL==0) SPH++;} +#define INCSP2 {SPL+=2; if(SPL<2) SPH++;} + extern int gIndex[65536]; #define cpuMISC cpu[13] @@ -127,12 +148,14 @@ the settings for ReMem support. #undef MEM #undef MDM16 #undef MEMSET +#undef INS_INC #ifdef NO_REMEM #define SETPCINS16 {int pc=PC; PCL=gBaseMemory[pc++]; PCH=gBaseMemory[pc];} #define M gBaseMemory[HL] #define INS gBaseMemory[PC] +#define INS_INC gBaseMemory[PC]; INCPC; #define NXTINS gBaseMemory[PC+1] #define INS16 (((int)gBaseMemory[PC])|((int)gBaseMemory[PC+1]<<8)) #define MEM(x) gBaseMemory[x] @@ -144,6 +167,7 @@ the settings for ReMem support. #define SETPCINS16 {int pc=PC; PCL=get_memory8((unsigned short) pc++); PCH=get_memory8((unsigned short) pc);} #define M (gMemory[gIndex[HL]][HL & 0x3FF]) #define INS (gMemory[gIndex[PC]][PC & 0x3FF]) +#define INS_INC (gMemory[gIndex[PC]][PC & 0x3FF]); INCPC; #define NXTINS (get_memory8((unsigned short) (PC+1))) #define INS16 (((int)get_memory8((unsigned short) (PC)))|(((int)get_memory8((unsigned short) (PC+1)))<<8)) #define MEM(x) (gMemory[gIndex[x]][x & 0x3FF]) diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index 968671a..8b7cebe 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -50,6 +50,8 @@ #define MENU_HEIGHT 32 +void cb_Ide(Fl_Widget* w, void*) ; + /* ============================================================================ Global variables @@ -66,15 +68,12 @@ int gDebugMonitorFreq = 8192; // Menu items for the disassembler Fl_Menu_Item gCpuRegs_menuitems[] = { { "&Tools", 0, 0, 0, FL_SUBMENU }, - { "CPU Registers", 0, 0 }, - { "Assembler", 0, 0 }, + { "Assembler / IDE", 0, cb_Ide }, { "Disassembler", 0, disassembler_cb }, - { "Debugger", 0, 0 }, { "Memory Editor", 0, cb_MemoryEditor }, { "Peripheral Devices", 0, cb_PeripheralDevices }, { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, 0 }, - { "BASIC Debugger", 0, 0 }, { 0 }, { 0 } }; @@ -342,6 +341,14 @@ void debug_monitor_cb(int fMonType, unsigned char data) } } +char get_m() +{ + if (gReMem) + return (gMemory[gIndex[HL]][HL & 0x3FF]); + else + return gBaseMemory[HL]; +} + /* ============================================================================ debug_cpuregs_cb: This routine is the callback for the CPURegs Monitor @@ -355,6 +362,10 @@ void debug_cpuregs_cb (void) char flags[10]; int x, len; + // Check for breakpoint + if (PC == 0x5797) + gStopped = 1; + if (!gStopped) if (++gDebugCount < gDebugMonitorFreq) return; @@ -410,7 +421,7 @@ void debug_cpuregs_cb (void) cpuregs_ctrl.pRegHL->value(str); // Update M edit box - sprintf(str, cpuregs_ctrl.sMfmt, M); + sprintf(str, cpuregs_ctrl.sMfmt, get_m()); cpuregs_ctrl.pRegM->value(str); // Update flags @@ -459,6 +470,7 @@ void debug_cpuregs_cb (void) gDebugMonitorFreq = gSaveFreq; } } + } /* @@ -770,7 +782,7 @@ void cb_reg_hl_changed(Fl_Widget* w, void*) cpuregs_ctrl.pRegL->value(str); // Update M edit box - sprintf(str, cpuregs_ctrl.sMfmt, M); + sprintf(str, cpuregs_ctrl.sMfmt, get_m()); cpuregs_ctrl.pRegM->value(str); } @@ -797,7 +809,7 @@ void cb_reg_h_changed(Fl_Widget* w, void*) cpuregs_ctrl.pRegHL->value(str); // Update M edit box - sprintf(str, cpuregs_ctrl.sMfmt, M); + sprintf(str, cpuregs_ctrl.sMfmt, get_m()); cpuregs_ctrl.pRegM->value(str); } @@ -824,7 +836,7 @@ void cb_reg_l_changed(Fl_Widget* w, void*) cpuregs_ctrl.pRegHL->value(str); // Update M edit box - sprintf(str, cpuregs_ctrl.sMfmt, M); + sprintf(str, cpuregs_ctrl.sMfmt, get_m()); cpuregs_ctrl.pRegM->value(str); } @@ -1289,7 +1301,7 @@ void cb_reg_m_hex(Fl_Widget* w, void*) char str[8]; strcpy(cpuregs_ctrl.sMfmt, "0x%02X"); - sprintf(str, cpuregs_ctrl.sMfmt, M); + sprintf(str, cpuregs_ctrl.sMfmt, get_m()); cpuregs_ctrl.pRegM->value(str); cpuregs_ctrl.pAllHex->value(0); @@ -1306,7 +1318,7 @@ void cb_reg_m_dec(Fl_Widget* w, void*) char str[8]; strcpy(cpuregs_ctrl.sMfmt, "%d"); - sprintf(str, cpuregs_ctrl.sMfmt, M); + sprintf(str, cpuregs_ctrl.sMfmt, get_m()); cpuregs_ctrl.pRegM->value(str); cpuregs_ctrl.pAllHex->value(0); diff --git a/src/disassemble.cpp b/src/disassemble.cpp index 0689b23..a316ce0 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -50,6 +50,8 @@ #include "cpuregs.h" #include "memory.h" +void cb_Ide(Fl_Widget* w, void*) ; + Fl_Window *gpDis; // Callback routine for the close box of the Disassembler window @@ -161,14 +163,11 @@ Fl_Menu_Item gDis_menuitems[] = { { "&Tools", 0, 0, 0, FL_SUBMENU }, { "CPU Registers", 0, cb_CpuRegs }, - { "Assembler", 0, 0 }, - { "Disassembler", 0, 0 }, - { "Debugger", 0, 0 }, + { "Assembler / IDE", 0, cb_Ide }, { "Memory Editor", 0, cb_MemoryEditor }, { "Peripheral Devices", 0, cb_PeripheralDevices }, { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, 0 }, - { "BASIC Debugger", 0, 0 }, { 0 }, { 0 } @@ -867,7 +866,7 @@ int VTDis::DisassembleLine(int address, char* line) unsigned char op_len; // Get opcode from memory - opcode = gMemory[address>>10][address&0x3FF]; + opcode = get_memory8(address); // Determine length of this opcode op_len = m_LenTable[opcode] & 0x03; @@ -882,7 +881,7 @@ int VTDis::DisassembleLine(int address, char* line) if (op_len == 1) { // Single byte argument - sprintf(arg, "%02XH", gMemory[(address+1)>>10][(address+1)&0x3FF]); + sprintf(arg, "%02XH", get_memory8(address+1)); strcat(line, arg); } diff --git a/src/display.cpp b/src/display.cpp index 895c7f0..6eee85b 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -27,7 +27,6 @@ * SUCH DAMAGE. */ -#include #include #include @@ -63,26 +62,65 @@ extern RomDescription_t gM100_Desc; extern RomDescription_t gM200_Desc; extern RomDescription_t gN8201_Desc; extern RomDescription_t *gStdRomDesc; +extern int gRomSize; } +void cb_Ide(Fl_Widget* w, void*) ; + Fl_Window *MainWin = NULL; T100_Disp *gpDisp; +T100_Disp *gpDebugMonitor; Fl_Box *gpCode, *gpGraph, *gpKey, *gpSpeed, *gpCaps, *gpKeyInfo; Fl_Menu_Bar *Menu; Fl_Preferences virtualt_prefs(Fl_Preferences::USER, "virtualt.", "virtualt" ); char gsMenuROM[40]; char gDelayedError[128] = {0}; - int MultFact = 3; int DisplayMode = 1; int SolidChars = 0; int DispHeight = 64; - int gRectsize = 2; int gXoffset; int gYoffset; + void switch_model(int model); +void setMonitorWindow(Fl_Window* pWin) +{ + if (pWin == 0) + { + gpDebugMonitor = 0; + return; + } + + if (gpDebugMonitor == 0) + { + if (gModel == MODEL_T200) + { + gpDebugMonitor = new T200_Disp(0, 0, 240*2, 128*2); + (T200_Disp &) *gpDebugMonitor = (T200_Disp &) *gpDisp; + } + else + { + gpDebugMonitor = new T100_Disp(0, 0, 240*2,64*2); + // Copy current monitor to debug monitor + *gpDebugMonitor = *gpDisp; + + } + + gpDebugMonitor->DisplayMode = 0; + gpDebugMonitor->SolidChars = 1; + gpDebugMonitor->MultFact = 2; + gpDebugMonitor->gRectsize = 2; + gpDebugMonitor->gXoffset = 0; + gpDebugMonitor->gYoffset = 0; + + pWin->insert(*gpDebugMonitor, 3); + gpDebugMonitor->show(); + } +} + + char *gSpKeyText[] = { "SHIFT", "CTRL", @@ -163,27 +201,45 @@ resize_window: This function resizes the main window and repositions void resize_window() { if (gModel == MODEL_T200) + { + gpDisp->DispHeight = 128; DispHeight = 128; + } else + { + gpDisp->DispHeight = 64; DispHeight = 64; - MainWin->resize(MainWin->x(), MainWin->y(), 240*MultFact + - 90*DisplayMode+2,DispHeight*MultFact + 50*DisplayMode + MENU_HEIGHT + 22); - Menu->resize(0, 0, 240*MultFact + 90*DisplayMode+2, MENU_HEIGHT-2); - gpDisp->resize(0, MENU_HEIGHT, 240*MultFact + 90*DisplayMode+2, DispHeight*MultFact - + 50*DisplayMode+2); - gpGraph->resize(0, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 60, 20); - gpCode->resize(60, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 60, 20); - gpCaps->resize(120, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 60, 20); - gpKey->resize(180, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 120, 20); - gpSpeed->resize(300, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 60, 20); - gpKeyInfo->resize(360, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, - MainWin->w()-360, 20); + } + MainWin->resize(MainWin->x(), MainWin->y(), 240*gpDisp->MultFact + + 90*gpDisp->DisplayMode+2,gpDisp->DispHeight*gpDisp->MultFact + + 50*gpDisp->DisplayMode + MENU_HEIGHT + 22); + Menu->resize(0, 0, 240*gpDisp->MultFact + 90*gpDisp->DisplayMode+2, + MENU_HEIGHT-2); + gpDisp->resize(0, MENU_HEIGHT, 240*gpDisp->MultFact + 90*gpDisp->DisplayMode+2, + gpDisp->DispHeight*gpDisp->MultFact + 50*gpDisp->DisplayMode+2); + gpGraph->resize(0, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + + 50*gpDisp->DisplayMode+2, 60, 20); + gpCode->resize(60, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + + 50*gpDisp->DisplayMode+2, 60, 20); + gpCaps->resize(120, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + + 50*gpDisp->DisplayMode+2, 60, 20); + gpKey->resize(180, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + + 50*gpDisp->DisplayMode+2, 120, 20); + gpSpeed->resize(300, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + + 50*gpDisp->DisplayMode+2, 60, 20); + gpKeyInfo->resize(360, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + + 50*gpDisp->DisplayMode+2, MainWin->w()-360, 20); gRectsize = MultFact - (1 - SolidChars); if (gRectsize == 0) gRectsize = 1; gXoffset = 45*DisplayMode+1; gYoffset = 25*DisplayMode + MENU_HEIGHT+1; + + gpDisp->gRectsize = gRectsize; + gpDisp->gXoffset = gXoffset; + gpDisp->gYoffset = gYoffset; + Fl::check(); MainWin->redraw(); } @@ -216,38 +272,50 @@ Menu Item Callbacks */ void cb_1x(Fl_Widget* w, void*) { + gpDisp->MultFact = 1; MultFact = 1; - virtualt_prefs.set("MultFact",1); + + virtualt_prefs.set("MultFact",1); resize_window(); } void cb_2x(Fl_Widget* w, void*) { + gpDisp->MultFact = 2; MultFact = 2; - virtualt_prefs.set("MultFact",2); + + virtualt_prefs.set("MultFact",2); resize_window(); } void cb_3x(Fl_Widget* w, void*) { + gpDisp->MultFact = 3; MultFact = 3; - virtualt_prefs.set("MultFact",3); + + virtualt_prefs.set("MultFact",3); resize_window(); } void cb_4x(Fl_Widget* w, void*) { + gpDisp->MultFact = 4; MultFact = 4; - virtualt_prefs.set("MultFact",4); + + virtualt_prefs.set("MultFact",4); resize_window(); } void cb_framed(Fl_Widget* w, void*) { - DisplayMode ^= 1; - virtualt_prefs.set("DisplayMode",DisplayMode); + gpDisp->DisplayMode ^= 1; + DisplayMode ^= 1; + + virtualt_prefs.set("DisplayMode",gpDisp->DisplayMode); resize_window(); } void cb_solidchars (Fl_Widget* w, void*) { - SolidChars ^= 1; - virtualt_prefs.set("SolidChars",SolidChars); + gpDisp->SolidChars ^= 1; + SolidChars ^= 1; + + virtualt_prefs.set("SolidChars",gpDisp->SolidChars); resize_window(); } void cb_save_basic(Fl_Widget* w, void*) @@ -267,6 +335,10 @@ void cb_reset (Fl_Widget* w, void*) if(a==1) resetcpu(); + + gpDisp->Reset(); + if (gpDebugMonitor != 0) + gpDebugMonitor->Reset(); } void cb_UnloadOptRom (Fl_Widget* w, void*) @@ -467,14 +539,12 @@ Fl_Menu_Item menuitems[] = { { "&Tools", 0, 0, 0, FL_SUBMENU }, { "CPU Registers", 0, cb_CpuRegs }, - { "Assembler", 0, 0 }, + { "Assembler / IDE", 0, cb_Ide}, { "Disassembler", 0, disassembler_cb }, - { "Debugger", 0, 0 }, { "Memory Editor", 0, cb_MemoryEditor }, { "Peripheral Devices", 0, cb_PeripheralDevices }, { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, 0 }, - { "BASIC Debugger", 0, 0 }, { 0 }, { "&Help", 0, 0, 0, FL_SUBMENU }, { "Help", 0, cb_help }, @@ -507,9 +577,13 @@ void switch_model(int model) load_memory_preferences(); init_mem(); + gRomSize = 32768; /* Set pointer to ROM Description */ if (gModel == MODEL_T200) + { gStdRomDesc = &gM200_Desc; + gRomSize = 40960; + } else if (gModel == MODEL_PC8201) gStdRomDesc = &gN8201_Desc; else @@ -517,6 +591,8 @@ void switch_model(int model) /* Clear the LCD */ gpDisp->Clear(); + if (gpDebugMonitor != 0) + gpDebugMonitor->Clear(); delete MainWin; init_display(); @@ -547,9 +623,35 @@ T100_Disp::T100_Disp(int x, int y, int w, int h) : { for (int c = 0; c < 256; c++) lcd[driver][c] = 0; + top_row[driver] = 0; } m_MyFocus = 0; + m_DebugMonitor = 0; + + MultFact = 3; + DisplayMode = 1; + SolidChars = 0; + DispHeight = 64; + gRectsize = 2; +} + +const T100_Disp& T100_Disp::operator=(const T100_Disp& srcDisp) +{ + int driver, c; + + // Copy the LCD data + if (this != &srcDisp) + { + for (driver = 0; driver < 10; driver++) + { + for (c = 0; c < 256; c++) + lcd[driver][c] = srcDisp.lcd[driver][c]; + top_row[driver] = srcDisp.top_row[driver]; + } + } + + return *this; } /* @@ -560,6 +662,14 @@ Command: This function processes commands sent to */ void T100_Disp::Command(int instruction, uchar data) { + int driver = instruction; + + if ((data & 0x3F) == 0x3E) + { + if (top_row[driver] != data >> 6) + damage(1, gXoffset, gYoffset, 240*MultFact, 64*MultFact); + top_row[driver] = data >> 6; + } } /* @@ -578,6 +688,24 @@ void T100_Disp::Clear(void) } } +/* +================================================================= +Reset: This routine Resets the "LCD" +================================================================= +*/ +void T100_Disp::Reset(void) +{ + int driver; + + for (driver = 0; driver < 10; driver++) + { + for (int c = 0; c < 256; c++) + lcd[driver][c] = 0; + top_row[driver] = 0; + } + redraw(); +} + /* ================================================================= drawpixel: This routine is called by the system to draw a single @@ -585,11 +713,12 @@ drawpixel: This routine is called by the system to draw a single ================================================================= */ // Draw the black pixels on the LCD -__inline void drawpixel(int x, int y, int color) +__inline void T100_Disp::drawpixel(int x, int y, int color) { // Check if the pixel color is black and draw if it is if (color) - fl_rectf(x*MultFact + gXoffset,y*MultFact + gYoffset,gRectsize,gRectsize); + fl_rectf(x*MultFact + gXoffset,y*MultFact + gYoffset, + gRectsize, gRectsize); } /* @@ -682,6 +811,7 @@ void T100_Disp::draw_static() } } } + } /* @@ -712,7 +842,7 @@ void T100_Disp::draw() x=(driver % 5) * 50; x+=col; - y = row << 3; + y = ((row-top_row[driver]+4) % 4) << 3; if (driver > 4) y += 32; @@ -762,12 +892,12 @@ void T100_Disp::SetByte(int driver, int col, uchar value) x=(driver % 5) * 50 + (col&0x3F); // Calcluate y position of byte - y = ((col & 0xC0) >> 6) * 8; + y = ((((col & 0xC0) >> 6) - top_row[driver] + 4) % 4) * 8; if (driver > 4) y += 32; // Set the display - gpDisp->window()->make_current(); + window()->make_current(); fl_color(FL_GRAY); fl_rectf(x*MultFact + gXoffset, y*MultFact + @@ -832,6 +962,7 @@ void init_display(void) else gpDisp = new T100_Disp(0, MENU_HEIGHT, 240*MultFact + 90*DisplayMode+2, DispHeight*MultFact + 50*DisplayMode+2); + MainWin->callback(close_disp_cb); Menu->menu(menuitems); @@ -975,6 +1106,14 @@ void init_display(void) if (gRectsize == 0) gRectsize = 1; + gpDisp->DispHeight = DispHeight; + gpDisp->DisplayMode = DisplayMode; + gpDisp->MultFact = MultFact; + gpDisp->SolidChars = SolidChars; + gpDisp->gRectsize = gRectsize; + gpDisp->gXoffset = gXoffset; + gpDisp->gYoffset = gYoffset; + /* End the Window and show it */ MainWin->end(); MainWin->show(); @@ -992,7 +1131,7 @@ void init_display(void) } } -char label[40]; +static char label[40]; void display_cpu_speed(void) { @@ -1004,6 +1143,18 @@ void display_cpu_speed(void) void drawbyte(int driver, int column, int value) { gpDisp->SetByte(driver, column, value); + if (gpDebugMonitor != 0) + gpDebugMonitor->SetByte(driver, column, value); + + + return; +} + +void lcdcommand(int driver, int value) +{ + gpDisp->Command(driver, value); + if (gpDebugMonitor != 0) + gpDebugMonitor->Command(driver, value); return; } @@ -1011,6 +1162,8 @@ void drawbyte(int driver, int column, int value) void power_down() { gpDisp->PowerDown(); + if (gpDebugMonitor != 0) + gpDebugMonitor->PowerDown(); return; } @@ -1025,6 +1178,7 @@ void process_windows_event() // Called when the Model T shuts its power off void T100_Disp::PowerDown() { + window()->make_current(); // Clear display fl_color(FL_GRAY); if (DisplayMode == 1) @@ -1102,6 +1256,9 @@ int T100_Disp::handle(int event) case FL_FOCUS: m_MyFocus = 1; break; + case FL_PUSH: + m_MyFocus = 1; + break; case FL_UNFOCUS: m_MyFocus = 0; @@ -1789,6 +1946,8 @@ t200_command: This function processes commands sent to void t200_command(unsigned char ir, unsigned char data) { gpDisp->Command(ir, data); + if (gpDebugMonitor != 0) + gpDebugMonitor->Command(ir, data); } /* @@ -1802,6 +1961,37 @@ unsigned char t200_readport(unsigned char port) return ((T200_Disp*)gpDisp)->ReadPort(port); } +const T200_Disp& T200_Disp::operator=(const T200_Disp& srcDisp) +{ + int c; + + // Copy the LCD data + if (this != &srcDisp) + { + for (c = 0; c < 8192; c++) + m_ram[c] = srcDisp.m_ram[c]; + + // Copy control variables + m_dstarth = srcDisp.m_dstarth; + m_dstartl = srcDisp.m_dstartl; + m_mcr = srcDisp.m_mcr; + m_hpitch = srcDisp.m_hpitch; + m_hcnt = srcDisp.m_hcnt; + m_curspos = srcDisp.m_curspos; + m_cursaddrh = srcDisp.m_cursaddrh; + m_cursaddrl = srcDisp.m_cursaddrl; + m_ramrd = srcDisp.m_ramrd; + m_ramwr = srcDisp.m_ramwr; + m_ramrd_addr = srcDisp.m_ramrd_addr; + m_ramrd_dummy = srcDisp.m_ramrd_dummy; + m_redraw_count = srcDisp.m_redraw_count; + m_tdiv = srcDisp.m_tdiv; + m_last_dstart = srcDisp.m_last_dstart; + } + + return *this; +} + /* ======================================================= T200:Disp: This is the class construcor @@ -2083,7 +2273,7 @@ void T200_Disp::SetByte(int driver, int col, uchar value) return; // Set the display - gpDisp->window()->make_current(); + window()->make_current(); fl_color(FL_GRAY); fl_rectf(x*MultFact + gXoffset, y*MultFact + @@ -2130,7 +2320,7 @@ void T200_Disp::redraw_active() uchar value; // Set the display - gpDisp->window()->make_current(); + window()->make_current(); /* Get RAM address where display should start */ addr =( (m_dstarth << 8) | m_dstartl) &(8192-1); diff --git a/src/display.h b/src/display.h index 340c3a8..29499e7 100644 --- a/src/display.h +++ b/src/display.h @@ -40,6 +40,7 @@ extern int gDelayUpdateKeys; void init_pref(void); void init_display(void); void drawbyte(int driver, int column, int value); +void lcdcommand(int driver, int value); void power_down(); void process_windows_event(); void display_cpu_speed(void); @@ -58,14 +59,30 @@ class T100_Disp : public Fl_Widget virtual void SetByte(int driver, int col, uchar value); virtual void Command(int instruction, uchar data); virtual void Clear(void); + virtual void Reset(void); + + int MultFact; + int DisplayMode; + int SolidChars; + int DispHeight; + + int gRectsize; + int gXoffset; + int gYoffset; + + int m_DebugMonitor; + + const virtual T100_Disp& operator=(const T100_Disp& srcDisp); protected: virtual int handle(int event); virtual void draw(); + __inline void drawpixel(int x, int y, int color); virtual void draw_static(); int m_MyFocus; uchar lcd[10][256]; + uchar top_row[10]; }; @@ -77,6 +94,7 @@ class T200_Disp : public T100_Disp virtual void Command(int instruction , uchar data); virtual void SetByte(int driver, int col, uchar value); unsigned char ReadPort(unsigned char port); + const virtual T200_Disp& operator=(const T200_Disp& srcDisp); protected: virtual void draw(); diff --git a/src/do_instruct.h b/src/do_instruct.h index 06f2b2c..4f11e06 100644 --- a/src/do_instruct.h +++ b/src/do_instruct.h @@ -29,62 +29,49 @@ #define LXI(rp,h,l,rps) { \ - INCPC; \ - l=INS; \ - INCPC; \ - h=INS; \ - INCPC; \ - cpu_delay(10); \ + l=INS_INC; \ + h=INS_INC; \ + cycle_delta+=10; \ } #define STAX(rp,rps) { \ - INCPC; \ MEMSET(rp,A); \ - cpu_delay(7); \ + cycle_delta+=7; \ } #define INX(rp,h,l,rps) { \ - INCPC; \ - l++; \ F &= ~XF_BIT; \ - if(!l) { \ + if(!(++l)) { \ h++; \ F |= XF_BIT; \ } \ - cpu_delay(6); \ + cycle_delta += 6; \ } #define INR(r,rs) { \ - INCPC; \ - r++; \ - if(r&0x0f==0) /* Low order nybble wrapped */ \ + if((++r)&0x0f==0) /* Low order nybble wrapped */ \ j=1; \ else \ j=0; \ setflags(r,-1,-1,j,-1,-2, (r==0x80) || (r==0), -2); \ - cpu_delay(4); \ + cycle_delta += 4; \ } #define DCR(r,rs) { \ - INCPC; \ - r--; \ - if(r&0x0f==0x0f) /* Low order nybble wrapped */ \ + if((--r)&0x0f==0x0f) /* Low order nybble wrapped */ \ j=1; \ else \ j=0; \ setflags(r,-1,-1,j,-1,-2, (r==0xFF) || (r==0x7F), -2); \ - cpu_delay(4); \ + cycle_delta += 4; \ } #define MVI(r,rs) { \ - INCPC; \ - r=INS; \ - INCPC; \ - cpu_delay(7); \ + r=INS_INC; \ + cycle_delta += 7; \ } #define DAD(rp,rps) { \ - INCPC; \ i=HL; \ i+=rp; \ j=(HL&0x8000)==(rp&0x8000); \ @@ -97,40 +84,35 @@ if (j) \ j = (HL&0x8000) != (rp&0x8000); \ setflags(0,-2,-2,-2,-2,i,j,-2 ); \ - cpu_delay(10); \ + cycle_delta += 10; \ } #define LDAX(rp,rps) { \ - INCPC; \ A=MEM(rp); \ - cpu_delay(7); \ + cycle_delta += 7; \ } #define DCX(rp,h,l,rps) { \ - INCPC; \ l--; \ F &= ~XF_BIT; \ if(l==0xff) { \ F |= XF_BIT; \ h--; \ } \ - cpu_delay(6); \ + cycle_delta += 6; \ } #define MOV(dest,src,ds,ss) { \ - INCPC; \ dest=src; \ - cpu_delay(4); \ + cycle_delta += 4; \ } #define MOVM(src,ss) { \ - INCPC; \ MEMSET(HL, src); \ - cpu_delay(7); \ + cycle_delta += 7; \ } #define ADD(r,rs) { \ - INCPC; \ i=A; \ i+=r; \ v=(A&0x80) == (r&0x80); \ @@ -143,11 +125,10 @@ if (v) \ v = (A&0x80) != (r&0x80); \ setflags(A,-1,-1,j,-1,i,v,-2); \ - cpu_delay(4); \ + cycle_delta += 4; \ } #define ADC(r,rs) { \ - INCPC; \ i=A; \ i+=r; \ i+=(CF?1:0); \ @@ -161,11 +142,10 @@ if (v) \ v = (A&0x80) != (r&0x80); \ setflags(A,-1,-1,j,-1,i,v,-2); \ - cpu_delay(4); \ + cycle_delta += 4; \ } #define SUB(r,rs) { \ - INCPC; \ i=A; \ i-=r; \ j = (((A & 0x0F)-(r & 0x0F)) & 0x10) >> 4; \ @@ -178,11 +158,10 @@ if (v) \ v = (A&0x80) != (r&0x80); \ setflags(A,-1,-1,j,-1,i,v,-2); \ - cpu_delay(4); \ + cycle_delta += 4; \ } #define SBB(r,rs) { \ - INCPC; \ i=A; \ i-=r; \ i-=(CF?1:0); \ @@ -196,32 +175,28 @@ if (v) \ v = (A&0x80) != (r&0x80); \ setflags(A,-1,-1,j,-1,i,v,-2); \ - cpu_delay(4); \ + cycle_delta += 4; \ } #define ANA(r,rs) { \ - INCPC; \ A&=r; \ setflags(A,-1,-1,1,-1,0,-2,-2); \ - cpu_delay(4); \ + cycle_delta += 4; \ } #define XRA(r,rs) { \ - INCPC; \ A^=r; \ setflags(A,-1,-1,0,-1,0,-2,-2); \ - cpu_delay(4); \ + cycle_delta += 4; \ } #define ORA(r,rs) { \ - INCPC; \ A|=r; \ setflags(A,-1,-1,0,-1,0,-2,-2); \ - cpu_delay(4); \ + cycle_delta += 4; \ } #define CMP(r,rs) { \ - INCPC; \ i=A; \ i-=r; \ if (i>0xFF) \ @@ -234,82 +209,74 @@ else \ v = 0; \ setflags(A-r,-1,-1,j,-1,i,v,-2); \ - cpu_delay(4); \ + cycle_delta += 4; \ } #define POP(rp,h,l,rps) { \ - INCPC; \ l=MEM(SP); \ h=MEM(SP+1); \ INCSP2; \ - cpu_delay(10); \ + cycle_delta += 10; \ } #define PUSH(rp,h,l,rps) { \ - INCPC; \ DECSP2; \ MEMSET(SP,l); \ MEMSET(SP+1,h); \ - cpu_delay(12); \ + cycle_delta += 12; \ } #define RST(num) { \ - INCPC; \ DECSP2; \ MEMSET(SP,PCL); MEMSET(SP+1,PCH); \ PCH=0; \ PCL=8*num; \ - cpu_delay(12); \ + cycle_delta += 12; \ } #define CALL(cond,ins) { \ - INCPC; \ INCPC2; \ if(cond) { \ DECSP2; \ MEMSET(SP,PCL); MEMSET(SP+1,PCH); /* MEM16(SP)=PC; */ \ DECPC2; \ SETPCINS16; \ - cpu_delay(9); \ + cycle_delta += 9; \ } \ - cpu_delay(9); \ + cycle_delta += 9; \ } #define RETURN(cond,ins) { \ - INCPC; \ if(cond) { \ PCL=MEM(SP); PCH=MEM(SP+1); /* PC=MEM16(SP) */ \ INCSP2; \ - cpu_delay(6); \ + cycle_delta += 6; \ } \ - cpu_delay(6); \ + cycle_delta += 6; \ } #define JUMP(cond,ins) { \ - INCPC; \ if(cond) { \ SETPCINS16; \ - cpu_delay(3); \ + cycle_delta += 3; \ } \ else \ INCPC2; \ - cpu_delay(7); \ + cycle_delta += 7; \ } { -// if(trace) -// p=op+sprintf(op,"%04x (%02x) ",PC,INS); - if(!(INS&0x80)) { - if(!(INS&0x40)) { - if(!(INS&0x20)) { - if(!(INS&0x10)) { - if(!(INS&0x08)) { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + ins = INS_INC; + if(!(ins&0x80)) { + if(!(ins&0x40)) { + if(!(ins&0x20)) { + if(!(ins&0x10)) { + if(!(ins&0x08)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x00: /* NOP */ - INCPC; - cpu_delay(4); + cycle_delta += 4; /* return; */ } else { @@ -318,7 +285,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x02: /* STAX B */ STAX(BC,"B"); } @@ -329,8 +296,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x04: /* INR B */ INR(B,"B"); } @@ -340,28 +307,26 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x06: /* MVI B */ MVI(B,"B"); } else { /* case 0x07: /* RLC */ - INCPC; i=A>>7; A=(A<<1)|i; setflags(A,-2,-2,-2,-2,i,-2,-2); - cpu_delay(4); + cycle_delta += 4; /* return; */ } } } } else { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x08: /* DSUB */ - INCPC; i = HL < BC;// - (CF?1:0); j = HL - BC;// - (CF?1:0); v = (HL&0x8000) == (BC&0x8000); @@ -370,7 +335,7 @@ if (v) v = (HL&0x8000) != (BC&0x8000); setflags(H | L,-2,-1,-2,-2,i,v,-2); - cpu_delay(10); + cycle_delta += 10; /* return; */ } else { @@ -379,7 +344,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x0A: /* LDAX B */ LDAX(BC,"B"); } @@ -390,8 +355,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x0C: /* INR C */ INR(C,"C"); } @@ -401,18 +366,17 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x0E: /* MVI C */ MVI(C,"C"); } else { /* case 0x0F: /* RRC */ - INCPC; i=A<<7&0x80; A=(A>>1)|i; i>>=7; setflags(A,-2,-2,-2,-2,i,-2,-2); - cpu_delay(4); + cycle_delta += 4; /* return; */ } } @@ -420,18 +384,17 @@ } } else { - if(!(INS&0x08)) { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x08)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x10: /* ASHR */ - INCPC; i = L & CF ; j = HL >> 1; L = j & 0xFF; H = (H & 0x80) | ((j >> 8) & 0xFF); setflags(0,-2,-2,-2,-2,i,-2,-2); - cpu_delay(7); + cycle_delta += 7; /* return; */ } else { @@ -440,7 +403,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x12: /* STAX D */ STAX(DE,"D"); } @@ -451,8 +414,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x14: /* INR D */ INR(D,"D"); } @@ -462,35 +425,33 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x16: /* MVI D */ MVI(D,"D"); } else { /* case 0x17: /* RAL */ - INCPC; i=A>>7; A<<=1; A|=(CF?1:0); setflags(A,-2,-2,-2,-2,i,-2,-2); - cpu_delay(4); + cycle_delta += 4; /* return; */ } } } } else { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x18: /* RLDE */ - INCPC; i = D & 0x80 ? 1 : 0; j = DE << 1; E = (j & 0xFF) | (CF ? 1 : 0); D = (j >> 8) & 0xFF; setflags(0,-2,-2,-2,-2,i,-2,-2); - cpu_delay(10); + cycle_delta += 10; /* return; */ } else { @@ -499,7 +460,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x1A: /* LDAX D */ LDAX(DE,"D"); } @@ -510,8 +471,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x1C: /* INR E */ INR(E,"E"); } @@ -521,18 +482,17 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x1E: /* MVI E */ MVI(E,"E"); } else { /* case 0x1F: /* RAR */ - INCPC; i=(A&0x01); A>>=1; A|=CF?0x80:0; setflags(A,-2,-2,-2,-2,i,-2,-2); - cpu_delay(4); + cycle_delta += 4; /* return; */ } } @@ -541,15 +501,14 @@ } } else { - if(!(INS&0x10)) { - if(!(INS&0x08)) { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x10)) { + if(!(ins&0x08)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x20: /* RIM */ - INCPC; A=IM; - cpu_delay(4); + cycle_delta += 4; /* return; */ } else { @@ -558,14 +517,13 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x22: /* SHLD */ - INCPC; MEMSET(INS16,L); MEMSET(INS16+1,H); /* MEM16(INS16)=HL; */ INCPC2; - cpu_delay(16); + cycle_delta += 16; /* return; */ } else { @@ -575,8 +533,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x24: /* INR H */ INR(H,"H"); } @@ -586,13 +544,12 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x26: /* MVI H */ MVI(H,"H"); } else { /* case 0x27: /* DAA */ - INCPC; i=j=0; /* Check if lower nibble greater than 9 */ if(((A&0x0F) > 9)) { @@ -608,23 +565,22 @@ i|=0x60;/* Add 6 to upper nibble */ A+=i; setflags(A,-1,-1,j,-1,i>>4?1:0,-2,-2); - cpu_delay(4); + cycle_delta += 4; /* return; */ /* Huh? */ } } } } else { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x28: /* LDEH */ - INCPC; j = HL + INS; INCPC; E = j & 0xFF; D = (j >> 8) & 0xFF; - cpu_delay(10); + cycle_delta += 10; /* return; */ } else { @@ -633,13 +589,12 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x2A: /* LHLD */ - INCPC; L=MEM(INS16); H=MEM(INS16+1); INCPC2; - cpu_delay(16); + cycle_delta += 16; } else { /* case 0x2B: /* DCX H */ @@ -648,8 +603,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x2C: /* INR L */ INR(L,"L"); } @@ -659,34 +614,32 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x2E: /* MVI L */ MVI(L,"L"); } else { /* case 0x2F: /* CMA */ - INCPC; A=~A; - cpu_delay(4); + cycle_delta += 4; } } } } } else { - if(!(INS&0x08)) { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x08)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x30: /* SIM */ - INCPC; if (A & 0x08) /* Check if Interrupt masking enabled */ IM=(IM & 0xF8) | (A&0x07); /* Turn RST 7.5 pending off if bit 4 set */ if(A&0x10) { IM&=0xBF; } - cpu_delay(4); + cycle_delta += 4; /* return; */ } else { @@ -695,12 +648,11 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x32: /* STA */ - INCPC; MEMSET(INS16,A); INCPC2; - cpu_delay(13); + cycle_delta += 13; /* return; */ } else { @@ -710,59 +662,54 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x34: /* INR M */ - INCPC; MEMSET(HL,(uchar) (M+1)); if(M&0x0f==0) /* Low order nybble wrapped */ j=1; else j=0; setflags(M,-1,-1,j,-1,-2, (M==0x80) || (M==0), -2); - cpu_delay(10); + cycle_delta += 10; } else { /* case 0x35: /* DCR M */ - INCPC; MEMSET(HL, (uchar)(M-1)); if(M&0x0f==0x0f) /* Low order nybble wrapped */ j=1; else j=0; setflags(M,-1,-1,j,-1,-2, (M==0xFF) || (M==0x7F), -2); - cpu_delay(10); + cycle_delta += 10; } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x36: /* MVI M */ - INCPC; MEMSET(HL,INS); INCPC; - cpu_delay(10); + cycle_delta += 10; } else { /* case 0x37: /* STC */ - INCPC; setflags(0,-2,-2,-2,-2,1,-2,-2); - cpu_delay(4); + cycle_delta += 4; /* return; */ } } } } else { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x38: /* LDES */ - INCPC; j = SP + INS; INCPC; E = j & 0xFF; D = (j >> 8) & 0xFF; - cpu_delay(10); + cycle_delta += 10; /* return; */ } else { @@ -771,12 +718,11 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x3A: /* LDA */ - INCPC; A=MEM(INS16); INCPC2; - cpu_delay(13); + cycle_delta += 13; /* return; */ } else { @@ -786,8 +732,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x3C: /* INR A */ INR(A,"A"); } @@ -797,15 +743,14 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x3E: /* MVI A */ MVI(A,"A"); } else { /* case 0x3F: /* CMC */ - INCPC; setflags(A,-2,-2,-2,-2,CF?0:1,-2,-2); - cpu_delay(4); + cycle_delta += 4; /* return; */ } } @@ -815,12 +760,12 @@ } } else { - if(!(INS&0x20)) { - if(!(INS&0x10)) { - if(!(INS&0x08)) { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x20)) { + if(!(ins&0x10)) { + if(!(ins&0x08)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x40: /* MOV B,B */ MOV(B,B,"B","B"); } @@ -830,7 +775,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x42: /* MOV B,D */ MOV(B,D,"B","D"); } @@ -841,8 +786,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x44: /* MOV B,H */ MOV(B,H,"B","H"); } @@ -852,10 +797,10 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x46: /* MOV B,M */ MOV(B,M,"B","M"); - cpu_delay(3); + cycle_delta += 3; /* return; */ } else { @@ -866,9 +811,9 @@ } } else { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x48: /* MOV C,B */ MOV(C,B,"C","B"); } @@ -878,7 +823,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x4A: /* MOV C,D */ MOV(C,D,"C","D"); } @@ -889,8 +834,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x4C: /* MOV C,H */ MOV(C,H,"C","H"); } @@ -900,10 +845,10 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x4E: /* MOV C,M */ MOV(C,M,"C","M"); - cpu_delay(3); + cycle_delta += 3; } else { /* case 0x4F: /* MOV C,A */ @@ -914,10 +859,10 @@ } } else { - if(!(INS&0x08)) { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x08)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x50: /* MOV D,B */ MOV(D,B,"D","B"); } @@ -927,7 +872,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x52: /* MOV D,D */ MOV(D,D,"D","D"); } @@ -938,8 +883,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x54: /* MOV D,H */ MOV(D,H,"D","H"); } @@ -949,10 +894,10 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x56: /* MOV D,M */ MOV(D,M,"D","M"); - cpu_delay(3); + cycle_delta += 3; } else { /* case 0x57: /* MOV D,A */ @@ -962,9 +907,9 @@ } } else { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x58: /* MOV E,B */ MOV(E,B,"E","B"); } @@ -974,7 +919,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x5A: /* MOV E,D */ MOV(E,D,"E","D"); } @@ -985,8 +930,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x5C: /* MOV E,H */ MOV(E,H,"E","H"); } @@ -996,10 +941,10 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x5E: /* MOV E,M */ MOV(E,M,"E","M"); - cpu_delay(3); + cycle_delta += 3; } else { /* case 0x5F: /* MOV E,A */ @@ -1011,11 +956,11 @@ } } else { - if(!(INS&0x10)) { - if(!(INS&0x08)) { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x10)) { + if(!(ins&0x08)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x60: /* MOV H,B */ MOV(H,B,"H","B"); } @@ -1025,7 +970,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x62: /* MOV H,D */ MOV(H,D,"H","D"); } @@ -1036,8 +981,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x64: /* MOV H,H */ MOV(H,H,"H","H"); } @@ -1047,7 +992,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x66: /* MOV H,M */ MOV(H,M,"H","M"); } @@ -1059,9 +1004,9 @@ } } else { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x68: /* MOV L,B */ MOV(L,B,"L","B"); } @@ -1071,7 +1016,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x6A: /* MOV L,D */ MOV(L,D,"L","D"); } @@ -1082,8 +1027,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x6C: /* MOV L,H */ MOV(L,H,"L","H"); } @@ -1093,10 +1038,10 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x6E: /* MOV L,M */ MOV(L,M,"L","M"); - cpu_delay(3); + cycle_delta += 3; } else { /* case 0x6F: /* MOV L,A */ @@ -1107,10 +1052,10 @@ } } else { - if(!(INS&0x08)) { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x08)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x70: /* MOV M,B */ MOVM(B,"B"); } @@ -1120,7 +1065,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x72: /* MOV M,D */ MOVM(D,"D"); } @@ -1131,8 +1076,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x74: /* MOV M,H */ MOVM(H,"H"); } @@ -1142,9 +1087,10 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x76: /* HLT */ - cpu_delay(4); + cycle_delta += 4; + DECPC; /* return; */ } else { @@ -1155,9 +1101,9 @@ } } else { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x78: /* MOV A,B */ MOV(A,B,"A","B"); } @@ -1167,7 +1113,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x7A: /* MOV A,D */ MOV(A,D,"A","D"); } @@ -1178,8 +1124,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x7C: /* MOV A,H */ MOV(A,H,"A","H"); } @@ -1189,10 +1135,10 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x7E: /* MOV A,M */ MOV(A,M,"A","M"); - cpu_delay(3); + cycle_delta += 3; } else { /* case 0x7F: /* MOV A,A */ @@ -1206,13 +1152,13 @@ } } else { - if(!(INS&0x40)) { - if(!(INS&0x20)) { - if(!(INS&0x10)) { - if(!(INS&0x08)) { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x40)) { + if(!(ins&0x20)) { + if(!(ins&0x10)) { + if(!(ins&0x08)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x80: /* ADD B */ ADD(B,"B"); } @@ -1222,7 +1168,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x82: /* ADD D */ ADD(D,"D"); } @@ -1233,8 +1179,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x84: /* ADD H */ ADD(H,"H"); } @@ -1244,10 +1190,10 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x86: /* ADD M */ ADD(M,"M"); - cpu_delay(3); + cycle_delta += 3; } else { /* case 0x87: /* ADD A */ @@ -1257,9 +1203,9 @@ } } else { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x88: /* ADC B */ ADC(B,"B"); } @@ -1269,7 +1215,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x8A: /* ADC D */ ADC(D,"D"); } @@ -1280,8 +1226,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x8C: /* ADC H */ ADC(H,"H"); } @@ -1291,10 +1237,10 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x8E: /* ADC M */ ADC(M,"M"); - cpu_delay(3); + cycle_delta += 3; } else { /* case 0x8F: /* ADC A */ @@ -1305,10 +1251,10 @@ } } else { - if(!(INS&0x08)) { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x08)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x90: /* SUB B */ SUB(B,"B"); } @@ -1318,7 +1264,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x92: /* SUB D */ SUB(D,"D"); } @@ -1329,8 +1275,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x94: /* SUB H */ SUB(H,"H"); } @@ -1340,10 +1286,10 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x96: /* SUB M */ SUB(M,"M"); - cpu_delay(3); + cycle_delta += 3; } else { /* case 0x97: /* SUB A */ @@ -1353,9 +1299,9 @@ } } else { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x98: /* SBB B */ SBB(B,"B"); } @@ -1365,7 +1311,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x9A: /* SBB D */ SBB(D,"D"); } @@ -1376,8 +1322,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0x9C: /* SBB H */ SBB(H,"H"); } @@ -1387,10 +1333,10 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0x9E: /* SBB M */ SBB(M,"M"); - cpu_delay(3); + cycle_delta += 3; } else { /* case 0x9F: /* SBB A */ @@ -1402,11 +1348,11 @@ } } else { - if(!(INS&0x10)) { - if(!(INS&0x08)) { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x10)) { + if(!(ins&0x08)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xA0: /* ANA B */ ANA(B,"B"); } @@ -1416,7 +1362,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xA2: /* ANA D */ ANA(D,"D"); } @@ -1427,8 +1373,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xA4: /* ANA H */ ANA(H,"H"); } @@ -1438,10 +1384,10 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xA6: /* ANA M */ ANA(M,"M"); - cpu_delay(3); + cycle_delta += 3; } else { /* case 0xA7: /* ANA A */ @@ -1451,9 +1397,9 @@ } } else { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xA8: /* XRA B */ XRA(B,"B"); } @@ -1463,7 +1409,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xAA: /* XRA D */ XRA(D,"D"); } @@ -1474,8 +1420,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xAC: /* XRA H */ XRA(H,"H"); } @@ -1485,10 +1431,10 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xAE: /* XRA M */ XRA(M,"M"); - cpu_delay(3); + cycle_delta += 3; } else { /* case 0xAF: /* XRA A */ @@ -1499,10 +1445,10 @@ } } else { - if(!(INS&0x08)) { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x08)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xB0: /* ORA B */ ORA(B,"B"); } @@ -1512,7 +1458,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xB2: /* ORA D */ ORA(D,"D"); } @@ -1523,8 +1469,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xB4: /* ORA H */ ORA(H,"H"); } @@ -1534,10 +1480,10 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xB6: /* ORA M */ ORA(M,"M"); - cpu_delay(3); + cycle_delta += 3; } else { /* case 0xB7: /* ORA A */ @@ -1547,9 +1493,9 @@ } } else { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xB8: /* CMP B */ CMP(B,"B"); } @@ -1559,7 +1505,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xBA: /* CMP D */ CMP(D,"D"); } @@ -1570,8 +1516,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xBC: /* CMP H */ CMP(H,"H"); } @@ -1581,10 +1527,10 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xBE: /* CMP M */ CMP(M,"M"); - cpu_delay(3); + cycle_delta += 3; } else { /* case 0xBF: /* CMP A */ @@ -1597,20 +1543,19 @@ } } else { - if(!(INS&0x20)) { - if(!(INS&0x10)) { - if(!(INS&0x08)) { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x20)) { + if(!(ins&0x10)) { + if(!(ins&0x08)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xC0: /* RNZ */ - INCPC; if(!ZF) { PCL=MEM(SP); PCH=MEM(SP+1); /* PC=MEM16(SP) */ INCSP2; - cpu_delay(6); + cycle_delta += 6; } - cpu_delay(6); + cycle_delta += 6; /* return; */ } else { @@ -1619,7 +1564,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xC2: /* JNZ addr */ JUMP(!ZF,"JNZ"); } @@ -1630,8 +1575,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xC4: /* CNZ addr */ CALL(!ZF,"CNZ"); } @@ -1641,22 +1586,21 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xC6: /* ADI n */ - INCPC; i=A; i+=INS; - j = (((A&0x0F)+(INS&0x0F)) &0x10)>>4; - v = (A&0x80) == (INS&0x80); + j = (((A&0x0F)+(ins&0x0F)) &0x10)>>4; + v = (A&0x80) == (ins&0x80); A=i; if(i>0xFF) i=1; else i=0; if (v) - v = (A&0x80) != (INS&0x80); + v = (A&0x80) != (ins&0x80); setflags(A,-1,-1,j,-1,i,v,-2); - cpu_delay(7); + cycle_delta += 7; INCPC; /* return; */ } @@ -1668,9 +1612,9 @@ } } else { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xC8: /* RZ */ RETURN(ZF,"RZ"); } @@ -1680,7 +1624,7 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xCA: /* JZ addr */ JUMP(ZF,"JZ"); } @@ -1692,8 +1636,8 @@ } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xCC: /* CZ addr */ CALL(ZF,"CZ"); } @@ -1703,23 +1647,22 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xCE: /* ACI n */ - INCPC; i=A; i+=INS; i+=(CF?1:0); - j = (((A&0x0F)+(INS&0x0F)+(CF?1:0)) &0x10)>>4; - v = (A&0x80) == (INS&0x80); + j = (((A&0x0F)+(ins&0x0F)+(CF?1:0)) &0x10)>>4; + v = (A&0x80) == (ins&0x80); A=i; if(i>0xFF) i=1; else i=0; if (v) - v = (A&0x80) != (INS&0x80); + v = (A&0x80) != (ins&0x80); setflags(A,-1,-1,j,-1,i,v,-2); - cpu_delay(7); + cycle_delta += 7; INCPC; /* return; */ } @@ -1732,10 +1675,10 @@ } } else { - if(!(INS&0x08)) { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x08)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xD0: /* RNC */ RETURN(!CF,"RNC"); } @@ -1745,23 +1688,22 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xD2: /* JNC addr */ JUMP(!CF,"JNC"); } else { /* case 0xD3: /* OUT port */ - INCPC; out(INS,A); INCPC; - cpu_delay(10); + cycle_delta += 10; /* return; */ } } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xD4: /* CNC addr */ CALL(!CF,"CNC"); } @@ -1771,22 +1713,21 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xD6: /* SUI n */ - INCPC; i=A; i-=INS; - j = (((A&0x0F)-(INS&0x0F)) &0x10)>>4; - v = (A&0x80) == (INS&0x80); + j = (((A&0x0F)-(ins&0x0F)) &0x10)>>4; + v = (A&0x80) == (ins&0x80); A=i; if (i>0xFF) i = 1; else i = 0; if (v) - v = (A&0x80) != (INS&0x80); + v = (A&0x80) != (ins&0x80); setflags(A,-1,-1,j,-1,i,v,-2); - cpu_delay(7); + cycle_delta += 7; INCPC; /* return; */ } @@ -1798,38 +1739,36 @@ } } else { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xD8: /* RC */ RETURN(CF,"RC"); } else { /* case 0xD9: /* SHLX */ - INCPC; MEMSET(DE, L); MEMSET(DE+1, H); - cpu_delay(10); + cycle_delta += 10; /* return; */ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xDA: /* JC addr */ JUMP(CF,"JC"); } else { /* case 0xDB: /* IN port */ - INCPC; A=inport(INS); INCPC; - cpu_delay(10); + cycle_delta += 10; } } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xDC: /* CC addr */ CALL(CF,"CC"); } @@ -1840,24 +1779,23 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xDE: /* SBI n */ - INCPC; i=A; i-=INS; i-=(CF?1:0); - j = (((A&0x0F)-(INS&0x0F)-(CF?1:0)) &0x10)>>4; - v = (A&0x80) == (INS&0x80); + j = (((A&0x0F)-(ins&0x0F)-(CF?1:0)) &0x10)>>4; + v = (A&0x80) == (ins&0x80); A=i; if (i>0xFF) i = 1; else i = 0; if (v) - v = (A&0x80) != (INS&0x80); + v = (A&0x80) != (ins&0x80); setflags(A,-1,-1,j,-1,i,v,-2); INCPC; - cpu_delay(7); + cycle_delta += 7; /* return; */ } else { @@ -1870,11 +1808,11 @@ } } else { - if(!(INS&0x10)) { - if(!(INS&0x08)) { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x10)) { + if(!(ins&0x08)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xE0: /* RPO */ RETURN(!PF,"RPO"); } @@ -1884,13 +1822,12 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xE2: /* JPO addr */ JUMP(!PF,"JPO"); } else { /* case 0xE3: /* XTHL */ - INCPC; i=H; j=L; L=MEM(SP); @@ -1899,14 +1836,14 @@ MEMSET(SP, (uchar) j); MEMSET(SP+1, (uchar) i); /* MEM16(SP)=i; */ - cpu_delay(16); + cycle_delta += 16; /* return; */ } } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xE4: /* CPO addr */ CALL(!PF,"CPO"); } @@ -1916,13 +1853,12 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xE6: /* ANI n */ - INCPC; A=A&INS; INCPC; setflags(A,-1,-1,1,-1,0,-2,-2); - cpu_delay(7); + cycle_delta += 7; /* return; */ } else { @@ -1933,9 +1869,9 @@ } } else { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xE8: /* RPE */ RETURN(PF,"RPE"); } @@ -1944,18 +1880,17 @@ PCH=H; PCL=L; /* PC=HL; */ - cpu_delay(6); + cycle_delta += 6; /* return; */ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xEA: /* JPE addr */ JUMP(PF,"JPE"); } else { /* case 0xEB: /* XCHG */ - INCPC; i=H; H=D; D=i; @@ -1965,34 +1900,32 @@ /* i=HL; */ /* HL=DE; */ /* DE=i; */ - cpu_delay(4); + cycle_delta += 4; /* return; */ } } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xEC: /* CPE addr */ CALL(PF,"CPE"); } else { /* case 0xED: /* LHLX */ - INCPC; L=MEM(DE); H=MEM(DE+1); - cpu_delay(10); + cycle_delta += 10; /* return; */ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xEE: /* XRI n */ - INCPC; A=A^INS; INCPC; setflags(A,-1,-1,0,-1,0,-2,-2); - cpu_delay(4); + cycle_delta += 7; /* return; */ } else { @@ -2004,10 +1937,10 @@ } } else { - if(!(INS&0x08)) { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x08)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xF0: /* RP */ RETURN(!SF,"RP"); } @@ -2017,22 +1950,21 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xF2: /* JP addr */ JUMP(!SF,"JP"); } else { /* case 0xF3: /* DI */ - INCPC; IM|=0x08; - cpu_delay(4); + cycle_delta += 4; /* return; */ } } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xF4: /* CP addr */ CALL(!SF,"CP"); } @@ -2042,13 +1974,12 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xF6: /* ORI n */ - INCPC; A=A|INS; INCPC; setflags(A,-1,-1,0,-1,0,-2,-2); - cpu_delay(7); + cycle_delta += 7; /* return; */ } else { @@ -2059,38 +1990,36 @@ } } else { - if(!(INS&0x04)) { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x04)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xF8: /* RM */ RETURN(SF,"RM"); } else { /* case 0xF9: /* SPHL */ - INCPC; SPH=H; SPL=L; - cpu_delay(6); + cycle_delta += 6; /* return; */ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xFA: /* JM addr */ JUMP(SF,"JM"); } else { /* case 0xFB: /* EI */ - INCPC; IM&=0xF7; - cpu_delay(4); + cycle_delta += 4; /* return; */ } } } else { - if(!(INS&0x02)) { - if(!(INS&0x01)) { + if(!(ins&0x02)) { + if(!(ins&0x01)) { /* case 0xFC: /* CM addr */ CALL(SF,"CM"); } @@ -2101,23 +2030,22 @@ } } else { - if(!(INS&0x01)) { + if(!(ins&0x01)) { /* case 0xFE: /* CPI n */ - INCPC; i=A; i-=INS; if(i>0xFF) i=1; else i=0; - j = (((A & 0x0F)-(INS & 0x0F)) & 0x10) >> 4; - if ((A&0x80) == (INS&0x80)) - v = (A&0x80) != (INS&0x80); - else - v = 0; - setflags(A-INS,-1,-1,j,-1,i,v,-2); +// j = (((A & 0x0F)-(INS & 0x0F)) & 0x10) >> 4; +// if ((A&0x80) == (ins&0x80)) +// v = (A&0x80) != (ins&0x80); +// else +// v = 0; + setflags(A-INS,-1,-1,j,-1,i,0,-2); INCPC; - cpu_delay(7); + cycle_delta += 7; /* return; */ } else { diff --git a/src/doins.c b/src/doins.c index 3b4479b..3a97a19 100644 --- a/src/doins.c +++ b/src/doins.c @@ -60,24 +60,32 @@ void setflags(int regval, int sign, int zero, int auxcarry, int parity, int carr __inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry, char ov, char ts) #endif { - if(sign>=0) - F=(F&0x7F)|(sign?0x80:0); - else if(sign==-1) - F=(F&0x7F)|(regval&0x80); + if (sign!=-2) + { + if(sign>=0) + F=(F&0x7F)|(sign?0x80:0); + else + F=(F&0x7F)|(regval&0x80); + } - if(zero>=0) - F=(F&0xBF)|(zero?0x40:0); - else if(zero==-1) - F=(F&0xBF)|(regval?0:0x40); + if (zero != -2) + { + if(zero>=0) + F=(F&0xBF)|(zero?0x40:0); + else + F=(F&0xBF)|(regval?0:0x40); + } if(auxcarry>=0) F=(F&0xEF)|(auxcarry?0x10:0); - if(parity>=0) - F=(F&0xFB)|(parity?0x04:0); - else if(parity==-1) { - /* Table Lookup */ - F=(F&0xFB)|paritybits[regval & 0xFF]; + if (parity != -2) + { + if(parity>=0) + F=(F&0xFB)|(parity?0x04:0); + else + /* Table Lookup */ + F=(F&0xFB)|paritybits[regval & 0xFF]; } if(carry>=0) diff --git a/src/elf.h b/src/elf.h new file mode 100644 index 0000000..c887a15 --- /dev/null +++ b/src/elf.h @@ -0,0 +1,237 @@ +/* elf.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef ELF_H +#define ELF_H + +typedef unsigned long Elf32_Addr; +typedef unsigned short Elf32_Half; +typedef unsigned long Elf32_Off; +typedef signed long Elf32_Sword; +typedef unsigned long Elf32_Word; +typedef unsigned char Elf32_Char; + +#define EI_NIDENT 16 + +typedef struct { + Elf32_Char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +// Define file types +#define ET_NONE 0 // No file type +#define ET_REL 1 // Relocatable file +#define ET_EXEC 2 // Executable file +#define ET_DYN 3 // Shared object file +#define ET_CORE 4 // Core file +#define ET_LOPROC 0xFF00 +#define ET_HIPROC 0xFFFF + + +// Define machine types +#define ET_NONE 0 // No machine type +#define ET_M32 1 // AT&T WE 32100 +#define ET_SPARC 2 // SPARC +#define ET_386 3 // Intel +#define ET_68K 4 // Motorola +#define ET_88K 5 // Motorola +#define ET_860 7 // Intel i860 +#define ET_MIPS 8 // MIPS RS3000 +#define ET_MIPS_RS4_BE 10 // MIPS RS4000 +#define ET_8085 12 // Model T - 8085 + +// Define version +#define EV_NONE 0 // Invalid version +#define EV_CURRENT 1 // Current version + +// Define Identification indexes +#define EI_MAG0 0 // File Identification +#define EI_MAG1 1 // File Identification +#define EI_MAG2 2 // File Identification +#define EI_MAG3 3 // File Identification +#define EI_CLASS 4 // File class +#define EI_DATA 5 // Data encoding +#define EI_VERSION 6 // File version +#define EI_PAD 7 // Start of padding + +// Define values in e_ident +#define ELFMAG0 0x7f // Value in e_ident[EI_MAG0] +#define ELFMAG1 'E' // Value in e_ident[EI_MAG1] +#define ELFMAG2 'L' // Value in e_ident[EI_MAG2] +#define ELFMAG3 'F' // Valee in e_ident[EI_MAG3] + +#define ELFCLASSNONE 0 // Invalid class +#define ELFCLASS32 1 // 32-bit objects +#define ELFCLASS64 2 // 64-bit objects +#define ELFCLASS16 3 // 16-bit objects +#define ELFCLASS8 4 // 8-bit objects + +#define ELFDATANONE 0 // Invalid data encoding +#define ELFDATA2LSB 1 // LSB first +#define ELFDATA2MSB 2 // MSB first + +// Define reserved section header indexes +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +// Define the section header +typedef struct { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_LOPROC 0x7000000 +#define SHT_HIPROC 0x7ffffff +#define SHT_LOUSER 0x8000000 +#define SHT_HIUSER 0xfffffff + +// Define Flags +#define SHF_WRITE 0x01 +#define SHF_ALLOC 0x02 +#define SHF_EXECINSTR 0x04 +#define SFH_MASKPROC 0xf0000000 + +// Define Symbol table items +#define STN_UNDEF 0 + +typedef struct { + Elf32_Word st_name; // Index into string table + Elf32_Addr st_value; // Symbol value + Elf32_Word st_size; // Symbol size + Elf32_Char st_info; + Elf32_Char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +#define ELF32_ST_BIND(i) ((i)>>4) +#define ELF32_ST_TYPE(i) ((i&0x0F)) +#define ELF32_ST_INFO(b,t) (((b)<<4)+(t&0x0f)) + +// Define binding types +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_EXTERN 3 +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +// Define symbol types +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_LOPROC 13 +#define STT_HIPROC 15 + +// Define relocation entries +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +#define ELF32_R_SYM(i) ((i)>>8) +#define ELF32_R_TYPE(i) ((Elf32_Char)(i)) +#define ELF32_R_INFO(s,t) (((s)<<8)+(Elf32_Char)(t)) + +#define SR_UNDEF 0 +#define SR_ADDR_XLATE 1 +#define SR_EXTERN 2 +#define SR_PUBLIC 3 + +// Define program header information +typedef struct { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +// Define program header types +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + + + +#endif diff --git a/src/flu_pixmaps.cpp b/src/flu_pixmaps.cpp new file mode 100644 index 0000000..2834ce1 --- /dev/null +++ b/src/flu_pixmaps.cpp @@ -0,0 +1,1629 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#include "FLU/flu_pixmaps.h" + +/* XPM */ +char * plus_xpm[] = { +"15 15 4 1", +" c None", +". c #444444", +"+ c #FFFFFF", +"@ c #000000", +" ", +" ", +" ........... ", +" .+++++++++. ", +" .++++@++++. ", +" .++++@++++. ", +" .++++@++++. ", +" .+@@@@@@@+. ", +" .++++@++++. ", +" .++++@++++. ", +" .++++@++++. ", +" .+++++++++. ", +" ........... ", +" ", +" "}; + +/* XPM */ +char * minus_xpm[] = { +"15 15 4 1", +" c None", +". c #444444", +"+ c #FFFFFF", +"@ c #000000", +" ", +" ", +" ........... ", +" .+++++++++. ", +" .+++++++++. ", +" .+++++++++. ", +" .+++++++++. ", +" .+@@@@@@@+. ", +" .+++++++++. ", +" .+++++++++. ", +" .+++++++++. ", +" .+++++++++. ", +" ........... ", +" ", +" "}; + +/* XPM */ +char * folder_save_xpm[] = { +"20 20 180 2", +" c None", +". c #000000", +"+ c #FFFFFF", +"@ c #FFF5F6", +"# c #FFF6F7", +"$ c #FFEBEE", +"% c #FFF1F3", +"& c #FFA4B5", +"* c #FFB3C1", +"= c #FFB4C1", +"- c #FFB8C5", +"; c #FFB9C6", +"> c #FFBCC8", +", c #FFBDC9", +"' c #FFBECA", +") c #FFC2CD", +"! c #FFC4CE", +"~ c #FFC4CF", +"{ c #FFC6D0", +"] c #FFC8D2", +"^ c #FFCED7", +"/ c #FFD1D9", +"( c #FFD7DE", +"_ c #FFDCE2", +": c #FFE4E9", +"< c #FFE9ED", +"[ c #FFEDF0", +"} c #FFEEF1", +"| c #FFF9FA", +"1 c #FF9AAD", +"2 c #FF9FB2", +"3 c #FFA1B3", +"4 c #FFA6B7", +"5 c #FFA7B8", +"6 c #FFA8B9", +"7 c #FFABBB", +"8 c #FFACBC", +"9 c #FFADBD", +"0 c #FFAFBE", +"a c #FFB1C0", +"b c #FFB5C3", +"c c #FFB5C4", +"d c #FFB7C5", +"e c #FFBBC8", +"f c #FFBFCB", +"g c #FFC1CD", +"h c #FFC5D0", +"i c #FFC7D2", +"j c #FFC8D3", +"k c #FFC9D4", +"l c #FFCAD4", +"m c #FFCCD6", +"n c #FFCED8", +"o c #FFD2DB", +"p c #FFD4DD", +"q c #FFD5DD", +"r c #FFD7DF", +"s c #FFD9E1", +"t c #FFDAE1", +"u c #FFDBE2", +"v c #FFDDE4", +"w c #FFE0E6", +"x c #FFE1E7", +"y c #FFE2E8", +"z c #FFE6EB", +"A c #FFE7EC", +"B c #FFEFF2", +"C c #FFCBD6", +"D c #FFD0DA", +"E c #FFD5DE", +"F c #FFDEE5", +"G c #FFE8ED", +"H c #FFF2F5", +"I c #FFEAEF", +"J c #C3C2C3", +"K c #C1C0C1", +"L c #979697", +"M c #2106C3", +"N c #2207C3", +"O c #270CC5", +"P c #2B11C6", +"Q c #3118C7", +"R c #3720C9", +"S c #3D26CC", +"T c #3D26CB", +"U c #3F28CB", +"V c #442DCD", +"W c #452ECE", +"X c #432ECD", +"Y c #452FCD", +"Z c #4630CD", +"` c #4A35CF", +" . c #4A35CE", +".. c #4B36CF", +"+. c #4C37D0", +"@. c #4C38D0", +"#. c #4E39D0", +"$. c #513CD1", +"%. c #513DD1", +"&. c #523ED1", +"*. c #533FD1", +"=. c #5440D2", +"-. c #5642D2", +";. c #5744D2", +">. c #5845D3", +",. c #5B48D4", +"'. c #5A47D3", +"). c #5D4AD4", +"!. c #5E4CD5", +"~. c #604ED5", +"{. c #6150D6", +"]. c #6351D6", +"^. c #6452D7", +"/. c #6452D6", +"(. c #6553D6", +"_. c #6756D7", +":. c #6958D8", +"<. c #6A59D8", +"[. c #6A5AD8", +"}. c #6F5EDA", +"|. c #7667DC", +"1. c #7566DB", +"2. c #7B6CDD", +"3. c #7E70DE", +"4. c #7F71DE", +"5. c #877AE1", +"6. c #887BE0", +"7. c #6858D8", +"8. c #6F60DA", +"9. c #7061DA", +"0. c #7668DB", +"a. c #7769DC", +"b. c #7C6FDE", +"c. c #8174DF", +"d. c #8276DF", +"e. c #8578E0", +"f. c #897DE1", +"g. c #8D82E2", +"h. c #8F84E3", +"i. c #8E83E2", +"j. c #9489E4", +"k. c #958BE5", +"l. c #9B92E7", +"m. c #9C93E7", +"n. c #B1AAED", +"o. c #A19AE8", +"p. c #A7A0EA", +"q. c #ADA6EB", +"r. c #B2ACED", +"s. c #7D7D7E", +"t. c #787979", +"u. c #B6B7B7", +"v. c #ACADAD", +"w. c #8C8D8D", +"x. c #767776", +"y. c #8F908F", +"z. c #B9B9B8", +"A. c #ADADAC", +"B. c #6C6B6B", +"C. c #B7B6B6", +"D. c #9E9D9D", +"E. c #C5C5C5", +"F. c #C2C2C2", +"G. c #AAAAAA", +"H. c #A2A2A2", +"I. c #A0A0A0", +"J. c #999999", +"K. c #949494", +"L. c #919191", +"M. c #8A8A8A", +"N. c #888888", +"O. c #858585", +"P. c #828282", +"Q. c #808080", +"R. c #7B7B7B", +"S. c #747474", +"T. c #727272", +"U. c #6E6E6E", +"V. c #6C6C6C", +"W. c #6A6A6A", +" ", +" . . . . . . . . . . . . . . . . . . ", +" . r.. 1 3 5 0 b e g i ^ p u x . F.. ", +" . r.. 2 T.T.T.T.T.T.T.T.T.T.z . . . ", +" . r.. & 7 a d , ! k D ( v : $ . [.. ", +" . r.. 6 T.T.T.T.T.n q _ y G } . ^.. ", +" . n.. 9 = ; f { m o s w A [ H . ).. ", +" . q.. a T.T.~ l T.T.T.T.T.% # . -.. ", +" . p.. c > g j n E _ y < B @ | . #.. ", +" . o.m.. . . . . . . . . . . . @.Z . ", +" . l.k.h.f.d.b.|.8.[.(.!.>.&...Y U . ", +" . j.i.6.c.2.1.}.:./.).;.$.` X S R . ", +" . g.5.. . . . . . . . . . . . . Q . ", +" . e.4.. E.E._.{.,.C.v.H.J.y.O.. P . ", +" . 3.a.. E.E.~.'.=.G.I.L w.P.t.. O . ", +" . 0.9.. E.J >.*.+.D.K.M.Q.x.U.. N . ", +" . 8.<.. K z.%...W L.N.s.S.V.W.. M . ", +" . 7.].. u.A. .V T O.R.T.B.W.W.. M . ", +" . . . . . . . . . . . . . . . . . ", +" "}; + +/* XPM */ +char * folder_load_xpm[] = { +"20 20 42 1", +" c None", +". c #000000", +"+ c #FFF1A5", +"@ c #FFEEA3", +"# c #FFECA1", +"$ c #FFE99F", +"% c #FFE79D", +"& c #FFE49B", +"* c #FFE299", +"= c #FFE097", +"- c #FFDD95", +"; c #FFDB93", +"> c #FFD891", +", c #FFD68F", +"' c #FFD48E", +") c #B59B69", +"! c #B59E6C", +"~ c #B5A26E", +"{ c #B5A571", +"] c #B5A974", +"^ c #B5AA75", +"/ c #B59665", +"( c #B59A68", +"_ c #B59D6B", +": c #B5A16D", +"< c #B5A470", +"[ c #B5A773", +"} c #B59867", +"| c #B59C69", +"1 c #B59F6C", +"2 c #B5A36F", +"3 c #B5A672", +"4 c #B59766", +"5 c #B59E6B", +"6 c #B5A16E", +"7 c #B5A873", +"8 c #B59967", +"9 c #B59C6A", +"0 c #B5A06D", +"a c #B5A370", +"b c #B5A772", +"c c #B59866", +" ", +" .... ", +" . . . ", +" . ... ", +" .... ... ", +".+@#$. .... ", +".@#$%. ", +".#$%&*........ ", +".$%&*=-;>,'''. ", +".%&*=-;>,''''. ", +".&*=-;>.............", +".*=-;>.)!~{]^^^^^^^.", +".=-;>./(_:<[^^^^^^. ", +".-;>.//}|123^^^^^. ", +".;>.///4(56{7^^^. ", +".>./////890ab^^. ", +"..//////c)!~{]. ", +".............. ", +" ", +" "}; + +/* XPM */ +char * reload_xpm[] = { +"20 20 41 1", +" c None", +". c #777777", +"+ c #000000", +"@ c #3439AC", +"# c #1C23A3", +"$ c #080F9A", +"% c #5257B8", +"& c #3A40AF", +"* c #2329A5", +"= c #0C139C", +"- c #585DBB", +"; c #4146B1", +"> c #2A30A8", +", c #5F63BE", +"' c #484DB4", +") c #3036AB", +"! c #666AC0", +"~ c #4E53B7", +"{ c #373DAD", +"] c #555ABA", +"^ c #3E43B0", +"/ c #262DA7", +"( c #5C60BC", +"_ c #444AB3", +": c #2D33A9", +"< c #5E5E5E", +"[ c #4B50B6", +"} c #676767", +"| c #646464", +"1 c #6D6D6D", +"2 c #767676", +"3 c #12199F", +"4 c #616161", +"5 c #6A6A6A", +"6 c #737373", +"7 c #7C7C7C", +"8 c #1920A1", +"9 c #707070", +"0 c #797979", +"a c #808080", +"b c #838383", +" .++++++. ", +" .++@#$$$$++. ", +" .+%&*=++++$$+. ", +" .+-;>++. .++$+.", +" .+,')+. .+++", +" +!~{+. .+", +" .+]^/+ .+. ", +" +(_:+. .+<+. ", +" .+[@#+ .+<<}+. ", +"++%&*=$++ .+<<|12+.", +".+;>3$$+. ++<4567++", +" .+8$$+. +}90+. ", +" .+$+. .+12a+ ", +" .+. +567+. ", +"+. .+90b+ ", +"+++. .+12a+. ", +".+<++. .++567+. ", +" .+<<++++<}90+. ", +" .++<<<<|1++. ", +" .++++++. "}; + +/* XPM */ +char * home_xpm[] = { +"20 20 46 1", +" c None", +". c #000000", +"+ c #1C2F54", +"@ c #4162AD", +"# c #872525", +"$ c #894226", +"% c #875B25", +"& c #DDDA30", +"* c #4665B0", +"= c #6279BF", +"- c #4A68B2", +"; c #697EC3", +"> c #4363AE", +", c #4C69B3", +"' c #556FB8", +") c #5D76BC", +"! c #667CC1", +"~ c #6E81C6", +"{ c #7687CA", +"] c #7989CC", +"^ c #4C6AB3", +"/ c #5570B8", +"( c #5E76BD", +"_ c #677DC2", +": c #7083C7", +"< c #828FD0", +"[ c #F43333", +"} c #ED3030", +"| c #E62E2E", +"1 c #3E60AB", +"2 c #E02C2C", +"3 c #D92A2A", +"4 c #3A5DA9", +"5 c #5A73BB", +"6 c #D22828", +"7 c #CC2626", +"8 c #3559A6", +"9 c #526EB6", +"0 c #C52424", +"a c #BF2222", +"b c #3055A3", +"c c #365AA7", +"d c #3C5EAA", +"e c #4262AD", +"f c #B82020", +"g c #B11D1D", +" ", +" . ", +" .+. .... ", +" .+@+..#$. ", +" .%%%%%.$#. ", +" .%&&%&&%.$. ", +" .+%&&%&&%+.. ", +" .+*%&&%&&%=+. . ", +" .+@-%%%%%%%;=+.+. ", +". .>,')!~{]{~!.+,+. ", +" .>^/(_:]<]:.+/^>+.", +" .>%%%%~{]{~%%%%>. ", +" .@%&&%;[}|;%&&%@. ", +" .1%&&%=|23=%&&%1. ", +" .4%&&%53675%&&%4. ", +" .8%%%%970a9%%%%8. ", +" .bcde*-afg-*edcb. ", +" ................. ", +" ", +" "}; + +/* XPM */ +char * trash_xpm[] = { +"20 20 8 1", +" c None", +". c #000000", +"+ c #B7B7B7", +"@ c #D3D3D3", +"# c #3F3F3F", +"$ c #8E8E8E", +"% c #FFFFFF", +"& c #666666", +" ", +" ........ ", +" ..+@####+$.. ", +" ..$@%#@@@@#@+$.. ", +" .#+@%%%@@@@@+$#. ", +" .+###%%%%@@###&. ", +" .+@%######+$&. ", +" .###@@@@$+###. ", +" .+@%######$&&. ", +" .+@%+@@$++$&&. ", +" .+@%+@@$++$&&. ", +" .+@%+@@$++$&&. ", +" .+@%+@@$++$&&. ", +" .+@%+@@$++$&&. ", +" .+@%+@@$++$&&. ", +" .+@%+@@$++$&&. ", +" .+@%+@@$++$&&. ", +" .+@%+@@$++$&&. ", +" ..%+@@$++$.. ", +" ........ "}; + +/* XPM */ +char * arrow_closed_xpm[] = { +"15 15 3 1", +" c None", +". c #FFFFFF", +"+ c #000000", +" ", +" ", +" ", +" ++ ", +" ++++ ", +" ++++++ ", +" ++++++++ ", +" +++++++++ ", +" ++++++++ ", +" ++++++ ", +" ++++ ", +" ++ ", +" ", +" ", +" "}; + +/* XPM */ +char * arrow_open_xpm[] = { +"15 15 3 1", +" c None", +". c #FFFFFF", +"+ c #000000", +" ", +" ", +" ", +" +++++++++ ", +" +++++++++ ", +" +++++++ ", +" +++++++ ", +" +++++ ", +" +++++ ", +" +++ ", +" +++ ", +" + ", +" ", +" ", +" "}; + +/* XPM */ +char * bluedot_xpm[] = { +"13 13 9 1", +" c None", +". c #D4D4FF", +"+ c #6363FF", +"@ c #1A1AFF", +"# c #0000FF", +"$ c #A8A8FF", +"% c #6060FF", +"& c #EAEAFF", +"* c #FFFFFF", +" ", +" .+@#@+. ", +" $#######$ ", +" .#%&&%####. ", +" +#&**&####+ ", +" @#&**&####@ ", +" ##%&&%##### ", +" @#########@ ", +" +#########+ ", +" .#########. ", +" $#######$ ", +" .+@#@+. ", +" "}; + +/* XPM */ +char * book_xpm[] = { +"18 18 15 1", +" c None", +". c #840084", +"+ c #000000", +"@ c #FF9CFF", +"# c #CE00CE", +"$ c #630063", +"% c #9C009C", +"& c #636363", +"* c #9C9C9C", +"= c #848484", +"- c #C6C6C6", +"; c #ADAD94", +"> c #E7E7D6", +", c #D60094", +"' c #CE63CE", +" ", +" .+ ", +" .@#$+ ", +" .@###%$+ ", +" .@#####..$+ ", +" .@#######..++ ", +" .@########.+. ", +" .@########.+&. ", +" .@########%+&*.+ ", +" ...######%+&*=.+ ", +" .*-..###%+&*;.+ ", +" .*>-;..%+=*-.+ ", +" .,'>>--.*;-.+ ", +" $$,'>>>--.+ ", +" $$,'>-.+ ", +" $$,.+ ", +" $+ ", +" "}; + +/* XPM */ +char * cd_drive_xpm[] = { +"18 16 29 1", +" c None", +". c #737373", +"+ c #9CCE9C", +"@ c #CECE63", +"# c #C6C6C6", +"$ c #319C9C", +"% c #63CE9C", +"& c #B5B5B5", +"* c #313131", +"= c #CECE9C", +"- c #DEDEDE", +"; c #848484", +"> c #319CCE", +", c #639CCE", +"' c #63CECE", +") c #D6D6D6", +"! c #949494", +"~ c #A5A5A5", +"{ c #639C9C", +"] c #000000", +"^ c #CECECE", +"/ c #F7F7F7", +"( c #E7E7E7", +"_ c #EFEFEF", +": c #FFFFFF", +"< c #CEFFFF", +"[ c #009CCE", +"} c #00FF00", +"| c #008400", +" ... ", +" ..+@#.. ", +" .$%+@&##* ", +" .%%$%=#&-&* ", +" ;>,%';&)#&* ", +" .!~{';];~&^^* ", +" .&&^;]/];^^^* ", +" .(/(&;];&_/^* ", +" ;;;;~&~~;$-(:* ", +" ;:::.~~&)=%><&* ", +" ;:###.~&^=+[[] ", +" ;:****;;^=+**] ", +" ;:}|::##***#.] ", +" .;;;;;;;;;;;;] ", +" ]]]]]]]]]]]] ", +" "}; + +/* XPM */ +char * computer_xpm[] = { +"20 20 47 1", +" c None", +". c #FFFFFF", +"+ c #848484", +"@ c #9C9CCE", +"# c #9C9C63", +"$ c #63639C", +"% c #393939", +"& c #FFFFCE", +"* c #FFFFF7", +"= c #CECEFF", +"- c #424242", +"; c #F7F7F7", +"> c #6363CE", +", c #000031", +"' c #003163", +") c #CEEFFF", +"! c #4A4A4A", +"~ c #9CCEFF", +"{ c #63FFFF", +"] c #9CFFFF", +"^ c #63CEFF", +"/ c #319CFF", +"( c #0063FF", +"_ c #B5B5B5", +": c #31CEFF", +"< c #3163CE", +"[ c #639CCE", +"} c #CEFFFF", +"| c #009CFF", +"1 c #313100", +"2 c #292929", +"3 c #ADAD94", +"4 c #DEDEDE", +"5 c #101010", +"6 c #CE9C9C", +"7 c #080808", +"8 c #000000", +"9 c #EFD6C6", +"0 c #CE9CCE", +"a c #636363", +"b c #633131", +"c c #636331", +"d c #848400", +"e c #C6C6C6", +"f c #EFEFEF", +"g c #E7E7D6", +"h c #212121", +" ", +" ", +" +@@@@@@@@@@#$ ", +" %&...&&&&&**.=- ", +" %=;&@>,,,,,,')! ", +" %~=;>{]]]^^/({- ", +" %_=*>]]]{]::<]- ", +" %=_*[{]]{{::<}- ", +" %__.[^]{{^^|<.- ", +" %_=./:::::/|(.- ", +" 11_&^<<<<<<<<.2 ", +" 113=4&&&&&&4@5 ", +" 167888888888752 ", +" 1%90ab%c33b5%a ", +" 1$de9=9f=&3g3=3a ", +" 1$$%=9=ggg=@dd=h ", +" 1$h9=9=&=&=9=9h ", +" chhhhhhhhhhhhh ", +" ", +" "}; + +/* XPM */ +char * ram_drive_xpm[] = { +"18 16 14 1", +" c None", +". c #444444", +"+ c #2D2D2D", +"@ c #000000", +"# c #FFFFFF", +"$ c #737373", +"% c #B5B5B5", +"& c #1C1C1C", +"* c #DEDEDE", +"= c #C6C6C6", +"- c #949494", +"; c #D6D6D6", +"> c #00CE00", +", c #008400", +" ", +" .+++++ ", +" @ +....@ @", +" @@+.#..@@@ ", +" @ +..#.@ @", +" @@+....@@@ ", +" @ +.##.@ @", +" $$$$@@+....@@@ ", +" $%%%@%%+.#..@& @", +" $#####@@+....@@@ ", +" $*%====%@@@@@@& ", +" $*$$$$$$$$$%-$& ", +" $;>,#######%-$& ", +" $$$$$$$$$$$$$& ", +" &&&&&&&&&&&& ", +" "}; + +/* XPM */ +char * network_drive_xpm[] = { +"18 16 15 1", +" c None", +". c #A80525", +"+ c #42000E", +"@ c #1A29A8", +"# c #737373", +"$ c #B5B5B5", +"% c #000000", +"& c #FFFFFF", +"* c #9C9C9C", +"= c #DEDEDE", +"- c #C6C6C6", +"; c #949494", +"> c #D6D6D6", +", c #00CE00", +"' c #008400", +" ", +" .. .. .. .. ", +" ..+ ..+ ..+ ..+ ", +" ..+ ..+ ..+ ..+ ", +" @+ @+ @+ @+ ", +" @@@@@@@@@@@@@@ ", +" @ ", +" ############ ", +" #$$$$$$$$$$$#% ", +" #&&&&&&&&&&&*#% ", +" #=$----$$$$$;#% ", +" #=#########$;#% ", +" #>,'&&&&&&&$;#% ", +" #############% ", +" %%%%%%%%%%%% ", +" "}; + +/* XPM */ +char * floppy_drive_xpm[] = { +"18 16 12 1", +" c None", +". c #858585", +"+ c #737373", +"@ c #9CFFFF", +"# c #000000", +"$ c #FFFFFF", +"% c #CEFDFD", +"& c #CECECE", +"* c #C5C5C5", +"= c #B5B5B5", +"- c #F40000", +"; c #808080", +" ", +" ...... ", +" +@@@@@@# ", +" +$$$$$## ", +" +$$$%%%# ", +" +%%%%%%# ", +" +&*&=*=# ", +" ......+*....*# ", +" .******+&+#+$=# ", +" .$$$$$$$$###### ", +" .*********-*.+# ", +" .***....&***.+# ", +" ;*;.####;.;*;+# ", +" .***$$$$****.+# ", +" ..;...;...;..# ", +" ############ "}; + +/* XPM */ +char * removable_drive_xpm[] = { +"20 12 12 1", +" c None", +". c #858585", +"+ c #B5B5B5", +"@ c #626262", +"# c #000000", +"$ c #FFFFFF", +"% c #808080", +"& c #E7E7D6", +"* c #C5C5C5", +"= c #F40000", +"- c #7B0006", +"; c #CECECE", +" ", +" ............. ", +" .++++++++++++@# ", +" .$$$$$$$$$$$$.@# ", +" %$+&*+*+*+*+*.@# ", +" %.$=-@######@*.@# ", +" .$&+$######$*.@# ", +" .$+&+$$$$$$*;.@# ", +" %$&+***++++++.@# ", +" .$............# ", +" ############# ", +" "}; + +/* XPM */ +char * disk_drive_xpm[] = { +"20 12 12 1", +" c None", +". c #737373", +"+ c #B5B5B5", +"@ c #000000", +"# c #FFFFFF", +"$ c #9C9C9C", +"% c #D6D6D6", +"& c #C6C6C6", +"* c #949494", +"= c #DEDEDE", +"- c #00CE00", +"; c #008400", +" ", +" ", +" ............. ", +" .++++++++++++.@ ", +" .############$.@ ", +" .%&&&&&&&++++*.@ ", +" .=+&&&&&+++++*.@ ", +" .=..........+*.@ ", +" .%-;########+*.@ ", +" ..............@ ", +" @@@@@@@@@@@@@ ", +" "}; + +/* XPM */ +char * filled_folder_xpm[] = { +"18 18 18 1", +" c None", +". c #63639C", +"+ c #CEFFFF", +"@ c #000000", +"# c #848400", +"$ c #FFFFFF", +"% c #CECEFF", +"& c #CECE63", +"* c #319CFF", +"= c #0063FF", +"- c #9CFFFF", +"; c #9C9C00", +"> c #3131CE", +", c #313100", +"' c #31009C", +") c #9C9CFF", +"! c #FFFF9C", +"~ c #FFCE9C", +" ", +" . ", +" .+@ ", +" ###.+$%@ ", +" #&&.+$*+%@ ", +" #&&.+$=-$+%@;; ", +" #&.+$>-$>$+%@&, ", +" #.+%')%')%%%%@, ", +" ;;;;;;;;;;;;)+%@ ", +" ;$!!!!!!~!~&,%%@ ", +" ;$!!!!~!!~!&,)@, ", +" ;$!!!!!~!~~;,;, ", +" ;$!!~!~!~~~&,;, ", +" ;$~!~!~~~~&;,, ", +" ;;;;;;;;;;;;,, ", +" ,,,,,,,,,,,,, ", +" ", +" "}; + +/* XPM */ +char * folder_up_xpm[] = { +"20 18 8 1", +" c None", +". c #9C9C00", +"+ c #000000", +"@ c #F7F7F7", +"# c #FFFFCE", +"$ c #FFFF9C", +"% c #CECE63", +"& c #FFCE9C", +" ", +" ", +" ", +" .....+ ", +" .@##$$.+ ", +" .%%%%%%%...... ", +" .###########$%+ ", +" .#$$$+$$$$$$&%+ ", +" .#$$+++$$&$&$%+ ", +" .#$+++++$$&$&%+ ", +" .#$$$+$&$&$&$%+ ", +" .#$$$+$$&$&$&%+ ", +" .#$$$++++++&&%+ ", +" .#&$&$&$&$&&&%+ ", +" .%%%%%%%%%%%%%+ ", +" ++++++++++++++ ", +" ", +" "}; + +/* XPM */ +char * folder_closed_xpm[] = { +"20 16 44 1", +" c None", +". c #A68A5E", +"+ c #54452F", +"@ c #FEE89E", +"# c #FEE59B", +"$ c #FEE298", +"% c #FEDE95", +"& c #FEDB93", +"* c #CEAB75", +"= c #FEF6A9", +"- c #FEF2A7", +"; c #FEEFA4", +"> c #FEECA1", +", c #FEE99E", +"' c #FEE69C", +") c #FEE399", +"! c #FEDF96", +"~ c #FEDC93", +"{ c #FED991", +"] c #FED68E", +"^ c #FEF3A7", +"/ c #FEF0A4", +"( c #FEEDA2", +"_ c #FEE99F", +": c #FEE097", +"< c #FEDD94", +"[ c #FEDA91", +"} c #FED78E", +"| c #FEF0A5", +"1 c #FEEA9F", +"2 c #FEE79D", +"3 c #FEE49A", +"4 c #FEE197", +"5 c #FEDA92", +"6 c #FED78F", +"7 c #FEEEA3", +"8 c #FEEAA0", +"9 c #FEE198", +"0 c #FEDB92", +"a c #FED88F", +"b c #FEEBA0", +"c c #FED890", +"d c #FEE299", +"e c #FED990", +" ", +" .....+ ", +" .@#$%&.+ ", +" ......*******. ", +" .=-;>,')!~{]].+ ", +" .^/(_'):<[}]].+ ", +" .|(1234<56]]].+ ", +" .78239%0a]]]].+ ", +" .b@#$%&c]]]]].+ ", +" .@#d!~e]]]]]].+ ", +" .')!~{]]]]]]].+ ", +" .):<[}]]]]]]].+ ", +" ..............+ ", +" ++++++++++++++ ", +" ", +" "}; +/* +"20 16 29 1", +" c None", +". c #9E9E02", +"+ c #222202", +"@ c #FEFECE", +"# c #FEF2C2", +"$ c #FEEABA", +"% c #FEDEAE", +"& c #FEDAA6", +"* c #CECE62", +"= c #FEFECA", +"- c #FEFACA", +"; c #FEF6C6", +"> c #FEEEBA", +", c #FEE6B6", +"' c #FEE2B2", +") c #FEDAAA", +"! c #FEEEBE", +"~ c #FEEAB6", +"{ c #FEE6B2", +"] c #FEE2AE", +"^ c #FEDEAA", +"/ c #FEFAC6", +"( c #FEF6C2", +"_ c #FEF2BE", +": c #FED6A2", +"< c #FED6A6", +"[ c #FED2A2", +"} c #FED29E", +"| c #FECE9E", +" ", +" .....+ ", +" .@#$%&.+ ", +" .*******...... ", +" .@@=-;#>$,'%)*+ ", +" .@@-;#!!~{]^)*+ ", +" .@-/(_>$,']^)*+ ", +" .@-;#!$,{')&:*+ ", +" .@/(#!~,]])<:*+ ", +" ./;#!$,'')&<[*+ ", +" .;#_>${]%)<}}*+ ", +" .##!${'%^<:[|*+ ", +" .*************+ ", +" ++++++++++++++ ", +" ", +" "}; +*/ + +char * folder_open_xpm[] = { +"20 16 34 1", +" c None", +". c #A68A5E", +"+ c #FEF3A7", +"@ c #FEECA1", +"# c #FEE49A", +"$ c #FEDD94", +"% c #FED68E", +"& c #FEF6A9", +"* c #FEEEA3", +"= c #FEE79D", +"- c #FEDF96", +"; c #FED890", +"> c #FEF1A5", +", c #FEE99F", +"' c #FEE298", +") c #FEDA92", +"! c #FEF0A5", +"~ c #FEEBA1", +"{ c #FEE69C", +"] c #FEE198", +"^ c #FEDC93", +"/ c #FED78F", +"( c #54452F", +"_ c #FEF2A6", +": c #FEEDA2", +"< c #FEE299", +"[ c #FEE99E", +"} c #FEDE95", +"| c #FED991", +"1 c #FEEFA4", +"2 c #FEEA9F", +"3 c #FEE59B", +"4 c #FEE096", +"5 c #FEDB92", +" ", +" ..... ", +" .+@#$%. ", +" ......&*=-;%%. ", +" .&&&&&>,')%%%. ", +" .&&&&+@#$%%%%. ", +" .&&............ ", +" .&&.&!~{]^/%%%.( ", +" .&&._:=<$;%%%%.( ", +" .&.+*[#}|%%%%.( ", +" .&.12345%%%%%.( ", +" .!~{]^/%%%%.( ", +" ............( ", +" (((((((((((( ", +" ", +" "}; + +/* +"20 16 41 1", +" c None", +". c #9E9E02", +"+ c #FEFECE", +"@ c #FEFACA", +"# c #F6F2C4", +"$ c #F2EABE", +"% c #EEE6B9", +"& c #FAF6C6", +"* c #F2EEBE", +"= c #EADEB2", +"- c #E2D6AA", +"; c #EAE2B6", +"> c #E6DAAE", +", c #E2D2AA", +"' c #DAC69E", +") c #D2C296", +"! c #CEBA92", +"~ c #CAB28A", +"{ c #C2AA82", +"] c #CECE62", +"^ c #222202", +"/ c #FEFECA", +"( c #D6C69A", +"_ c #C2A67E", +": c #FEF2BE", +"< c #FEEABA", +"[ c #FEE6B6", +"} c #FEE2B2", +"| c #FEDEAE", +"1 c #FEDAAA", +"2 c #BA9E7A", +"3 c #FEF6C6", +"4 c #FEF2C2", +"5 c #FEEEBA", +"6 c #FEEAB6", +"7 c #FEDEAA", +"8 c #FED6A4", +"9 c #FEEEBE", +"0 c #FED2A2", +"a c #FEF6C2", +"b c #FECE9E", +" ", +" ..... ", +" .+@#$%. ", +" .++&*%=-...... ", +" .+@#$;>,')!~{]^ ", +" ./&*%=>,()!~{]^ ", +" ............{_]^ ", +" .++@&:<[}|1]^2]^ ", +" .++@3456}|1]^2]^ ", +" ./@4:<[}718.^.^ ", +" .@349<[}1800^.^ ", +" .a:96}|180b.^^ ", +" ............^^ ", +" ^^^^^^^^^^^^^ ", +" ", +" "}; +*/ + +/* XPM */ +char * greendot_xpm[] = { +"13 13 9 1", +" c None", +". c #D4FFD4", +"+ c #63FF63", +"@ c #1AFF1A", +"# c #00FF00", +"$ c #A8FFA8", +"% c #60FF60", +"& c #EAFFEA", +"* c #FFFFFF", +" ", +" .+@#@+. ", +" $#######$ ", +" .#%&&%####. ", +" +#&**&####+ ", +" @#&**&####@ ", +" ##%&&%##### ", +" @#########@ ", +" +#########+ ", +" .#########. ", +" $#######$ ", +" .+@#@+. ", +" "}; + +/* XPM */ +char * purpledot_xpm[] = { +"13 13 9 1", +" c None", +". c #FFD4FF", +"+ c #FF63FF", +"@ c #FF1AFF", +"# c #FF00FF", +"$ c #FFA8FF", +"% c #FF60FF", +"& c #FFEAFF", +"* c #FFFFFF", +" ", +" .+@#@+. ", +" $#######$ ", +" .#%&&%####. ", +" +#&**&####+ ", +" @#&**&####@ ", +" ##%&&%##### ", +" @#########@ ", +" +#########+ ", +" .#########. ", +" $#######$ ", +" .+@#@+. ", +" "}; +/* XPM */ +char * question_book_xpm[] = { +"18 18 19 1", +" c None", +". c #840084", +"+ c #000000", +"@ c #FF9CFF", +"# c #CE00CE", +"$ c #630063", +"% c #9C009C", +"& c #9C6331", +"* c #FFFF00", +"= c #CE9C31", +"- c #FFCE31", +"; c #636363", +"> c #9C9C9C", +", c #848484", +"' c #C6C6C6", +") c #ADAD94", +"! c #E7E7D6", +"~ c #D60094", +"{ c #CE63CE", +" ", +" .+ ", +" .@#$+ ", +" .@###%$+ ", +" .@##&&$..$+ ", +" .@##***=$..++ ", +" .@#####-*$.+. ", +" .@####**-&.+;. ", +" .@###*-&%.%+;>.+ ", +" ...##%%##%+;>,.+ ", +" .>'..###%+;>).+ ", +" .>!')..%+,>'.+ ", +" .~{!!''.>)'.+ ", +" $$~{!!!''.+ ", +" $$~{!'.+ ", +" $$~.+ ", +" $+ ", +" "}; +/* XPM */ +char * reddot_xpm[] = { +"13 13 9 1", +" c None", +". c #FFD4D4", +"+ c #FF6363", +"@ c #FF1A1A", +"# c #FF0000", +"$ c #FFA8A8", +"% c #FF6060", +"& c #FFEAEA", +"* c #FFFFFF", +" ", +" .+@#@+. ", +" $#######$ ", +" .#%&&%####. ", +" +#&**&####+ ", +" @#&**&####@ ", +" ##%&&%##### ", +" @#########@ ", +" +#########+ ", +" .#########. ", +" $#######$ ", +" .+@#@+. ", +" "}; +/* XPM */ +char * tealdot_xpm[] = { +"13 13 9 1", +" c None", +". c #D4FFFF", +"+ c #63FFFF", +"@ c #1AFFFF", +"# c #00FFFF", +"$ c #A8FFFF", +"% c #60FFFF", +"& c #EAFFFF", +"* c #FFFFFF", +" ", +" .+@#@+. ", +" $#######$ ", +" .#%&&%####. ", +" +#&**&####+ ", +" @#&**&####@ ", +" ##%&&%##### ", +" @#########@ ", +" +#########+ ", +" .#########. ", +" $#######$ ", +" .+@#@+. ", +" "}; +/* XPM */ +char * textdoc_xpm[] = { +"15 18 5 1", +" c None", +". c #848484", +"+ c #FFFFFF", +"@ c #C6C6C6", +"# c #000000", +" ", +" .......... ", +" .++++++++@. ", +" .+@......@+. ", +" .++++++++...# ", +" .+@.......+@# ", +" .++++++++++@# ", +" .+@.......+@# ", +" .++++++++++@# ", +" .+@.......+@# ", +" .++++++++++@# ", +" .+@.......+@# ", +" .++++++++++@# ", +" .+@.......+@# ", +" .++++++++++@# ", +" .@@@@@@@@@@@# ", +" ############ ", +" "}; + +/* XPM */ +char * yellowdot_xpm[] = { +"13 13 9 1", +" c None", +". c #FFFFD4", +"+ c #FFFF63", +"@ c #FFFF1A", +"# c #FFFF00", +"$ c #FFFFA8", +"% c #FFFF60", +"& c #FFFFEA", +"* c #FFFFFF", +" ", +" .+@#@+. ", +" $#######$ ", +" .#%&&%####. ", +" +#&**&####+ ", +" @#&**&####@ ", +" ##%&&%##### ", +" @#########@ ", +" +#########+ ", +" .#########. ", +" $#######$ ", +" .+@#@+. ", +" "}; + +/* XPM */ +char * cdrom_xpm[] = { +"22 22 39 1", +" c None", +". c #ADADAD", +"+ c #C67BA5", +"@ c #DEDEDE", +"# c #E7E7E7", +"$ c #E6E6E6", +"% c #7B9CBD", +"& c #CE8CAD", +"* c #DE8CAD", +"= c #FFFFFF", +"- c #6BB58C", +"; c #7BCEBD", +"> c #8CA5D6", +", c #DE9CC6", +"' c #8CD67B", +") c #8CDEB5", +"! c #7BB5D6", +"~ c #9C9CDE", +"{ c #DE94B5", +"] c #FFB1FF", +"^ c #C0C0C0", +"/ c #9CBD63", +"( c #ADD67B", +"_ c #94DEC6", +": c #CEAD73", +"< c #D6C67B", +"[ c #BDD67B", +"} c #94C67B", +"| c #94B5D6", +"1 c #C6A584", +"2 c #DEBD8C", +"3 c #DECE94", +"4 c #9CCE84", +"5 c #7B7B7B", +"6 c #FFD48E", +"7 c #DEDEEF", +"8 c #FFEFEF", +"9 c #6BA5BD", +"0 c #C6849C", +" ", +" ...... ", +" ..+@#$#$.. ", +" ..%&*$$$$===.. ", +" .-;>,*$$$$===$.. ", +" .')!~{]$$$==$=^. ", +" ./('_%,]$$==$=^$$. ", +" .:<[}_|]#@=$=^$$$. ", +" .122234_.55.=^$$$$$. ", +" .$$$666.5555.$$$$$$. ", +" .$$$$$#55 55@$$$$$. ", +" .$$$$$$55 557$$$$$. ", +" .#$$$$$.5555.66688#. ", +" .$$$$$^=$55._}32<21. ", +" .$$$^=$=$#]|_}(<:. ", +" .$$^=$==$$],%_44/. ", +" .^=$===$$]{~!)'. ", +" ..$===$$$8*,>;-. ", +" ..===$$$8*&9.. ", +" ..=$@@#0.. ", +" ...... ", +" "}; + +/* XPM */ +char * big_folder_new_xpm[] = { +"20 20 73 1", +" c None", +". c #000000", +"+ c #FFFFFF", +"@ c #444444", +"# c #474747", +"$ c #353535", +"% c #CEC765", +"& c #FFF373", +"* c #FFEF77", +"= c #FFEC78", +"- c #FFE87C", +"; c #C8B46E", +"> c #3C3C3C", +", c #C0B666", +"' c #FFE97A", +") c #FFE67D", +"! c #FFE182", +"~ c #FFE082", +"{ c #FFDE83", +"] c #FAD982", +"^ c #C1AA70", +"/ c #BFA872", +"( c #FFEFA4", +"_ c #FFDB87", +": c #FFD88A", +"< c #FFD68B", +"[ c #FFD48E", +"} c #FFD48D", +"| c #FFD48C", +"1 c #FFD58B", +"2 c #EFC885", +"3 c #FFEEA3", +"4 c #FFECA1", +"5 c #C8BB86", +"6 c #FFE89F", +"7 c #FFE69D", +"8 c #FFE49B", +"9 c #FFE39A", +"0 c #FFE29A", +"a c #FFE199", +"b c #FFE098", +"c c #FFDF97", +"d c #FFDE96", +"e c #FFDD95", +"f c #FFDC94", +"g c #FFECA2", +"h c #FFEBA1", +"i c #FFE79E", +"j c #FFE299", +"k c #FFDC95", +"l c #FFDB94", +"m c #FFEBA0", +"n c #FFE89E", +"o c #FFE79D", +"p c #FFE097", +"q c #FFD992", +"r c #FFE99E", +"s c #FFE69C", +"t c #FFE59B", +"u c #FFDA93", +"v c #FFD690", +"w c #FFD790", +"x c #FFD791", +"y c #FFD891", +"z c #FFD58E", +"A c #FFD58F", +"B c #FFD68F", +"C c #FFE198", +"D c #FFDF96", +"E c #FFDE95", +"F c #FFDB93", +"G c #FFD991", +"H c #FFDA92", +" ", +" .+ . .+ @##### ", +" .+. .+ $%&*=-;> ", +" ##...+####,')!~{]^#", +"#...+.../(#_:<[}|12#", +"#++...++345#########", +"#/.+.+.+677890abcde#", +"#.+/.+/.+aabccddeff#", +"#(gh6i8jbddeekkflll#", +"#mno89pelqqqqqqqqqq#", +"#rstjbeuqvvvvwxxyyy#", +"#8jbdeuxv[[[zABBvww#", +"#CDEfFGwB[[[[zAABBB#", +"#cekuuyvA[[[[zAABBB#", +"#FHqyyvAz[[[[[zzzzz#", +"#qyywwBA[[[[[[[[[[[#", +"#zzzzz[[[[[[[[[[[[[#", +" ################## ", +" ", +" "}; + +/* XPM */ +char * big_folder_up_xpm[] = { +"20 20 70 1", +" c None", +". c #474747", +"+ c #434343", +"@ c #3B3B3B", +"# c #B9B260", +"$ c #FFF373", +"% c #FFEF77", +"& c #FFEC78", +"* c #FFE87C", +"= c #C8B46E", +"- c #3C3C3C", +"; c #C2B667", +"> c #FFE97B", +", c #FFE67D", +"' c #FFE182", +") c #FFE082", +"! c #FFDE83", +"~ c #FFDD84", +"{ c #D1B775", +"] c #FFF6AA", +"^ c #FFE79E", +"/ c #FFF1A5", +"( c #FFEFA4", +"_ c #484848", +": c #F7D584", +"< c #FFD88A", +"[ c #FFD68B", +"} c #FFD48E", +"| c #FFD48D", +"1 c #FFD48C", +"2 c #FFD58B", +"3 c #FFEEA3", +"4 c #FFECA1", +"5 c #BEB280", +"6 c #BFA872", +"7 c #000000", +"8 c #FFE89F", +"9 c #FFE69D", +"0 c #FFE49B", +"a c #FFE39A", +"b c #FFE29A", +"c c #FFE199", +"d c #FFE098", +"e c #FFDF97", +"f c #FFDE96", +"g c #FFDD95", +"h c #FFDC94", +"i c #FFECA2", +"j c #FFDC95", +"k c #FFDB94", +"l c #FFEBA0", +"m c #FFE89E", +"n c #FFD992", +"o c #FFE99E", +"p c #FFE69C", +"q c #FFE59B", +"r c #FFE299", +"s c #FFDA93", +"t c #FFD690", +"u c #FFD790", +"v c #FFD791", +"w c #FFD891", +"x c #FFD58E", +"y c #FFD58F", +"z c #FFD68F", +"A c #FFE198", +"B c #FFDF96", +"C c #FFDE95", +"D c #FFDB93", +"E c #FFDA92", +" ", +" .....+ ", +" @#$%&*=- ", +" ..........;>,')!~{.", +".]]^^////(_:<[}|122.", +".]]^^^33345.........", +".](3^6768990abcdefg.", +".((367776ccdeeffghh.", +".(i6777776fggjjhkkk.", +".lm7777777nnnnnnnnn.", +".opqr67snttttuvvwww.", +".0rdf67vt}}}xyzztuu.", +".ABCh67666666666zzz.", +".egjs67777777777zzz.", +".DEnwwtyx}}}}}xxxxx.", +".nwwuuzy}}}}}}}}}}}.", +".xxxxx}}}}}}}}}}}}}.", +" .................. ", +" ", +" "}; diff --git a/src/ide.cpp b/src/ide.cpp new file mode 100644 index 0000000..aa69d90 --- /dev/null +++ b/src/ide.cpp @@ -0,0 +1,1345 @@ +/* ide.cpp */ + +/* $Id$ */ + +/* + * Copyright 2006 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "FLU/Flu_Tree_Browser.h" +#include "FLU/flu_pixmaps.h" +#include +#include +#include + +#include "VirtualT.h" +#include "m100emu.h" +#include "ide.h" +#include "multiwin.h" +#include "disassemble.h" +#include "cpuregs.h" +#include "memedit.h" +#include "periph.h" + +VT_Ide * gpIde = 0; +Fl_Menu_Button* gPopup = 0; +void setMonitorWindow(Fl_Window* pWin); +Fl_Multi_Window* gpLcd; + +void close_cb(Fl_Widget* w, void*); +void cb_new_file(Fl_Widget* w, void*); +void cb_open_file(Fl_Widget* w, void*); +void cb_save_file(Fl_Widget* w, void*); +void cb_save_as(Fl_Widget* w, void*); +void cb_new_project(Fl_Widget* w, void*); +void cb_open_project(Fl_Widget* w, void*); +void cb_save_project(Fl_Widget* w, void*); +void cb_help(Fl_Widget* w, void*); +void cb_about(Fl_Widget* w, void*); +void cb_lcd_display(Fl_Widget* w, void*); + +IMPLEMENT_DYNCREATE(VT_IdeGroup, VTObject); +IMPLEMENT_DYNCREATE(VT_IdeSource, VTObject); + +/* +======================================================= +Menu Items for the IDE window +======================================================= +*/ +Fl_Menu_Item gIde_menuitems[] = { + { "&File", 0, 0, 0, FL_SUBMENU }, + { "New File", 0, cb_new_file, 0, 0 }, + { "Open File...", 0, cb_open_file, 0, 0 }, + { "Save File...", 0, cb_save_file, 0, 0}, + { "Save As...", 0, cb_save_as, 0, FL_MENU_DIVIDER }, + { "New Project...", 0, cb_new_project, 0, 0 }, + { "Open Project...", 0, cb_open_project, 0, 0 }, + { "Save Project...", 0, cb_save_project, 0, FL_MENU_DIVIDER }, + { "E&xit", FL_CTRL + 'q', close_cb, 0 }, + { 0 }, + { "&Debug", 0, 0, 0, FL_SUBMENU }, + { "Laptop Display", 0, cb_lcd_display, 0, 0 }, + { 0 }, +/* + { "&Emulation", 0, 0, 0, FL_SUBMENU }, + { "Reset", 0, cb_reset, 0, FL_MENU_DIVIDER }, + { "Model", 0, 0, 0, FL_SUBMENU } , + { "M100", 0, cb_M100, (void *) 1, FL_MENU_RADIO | FL_MENU_VALUE }, + { "M102", 0, cb_M102, (void *) 2, FL_MENU_RADIO }, + { "T200", 0, cb_M200, (void *) 3, FL_MENU_RADIO }, + { "PC-8201", 0, cb_PC8201, (void *) 4, FL_MENU_RADIO }, +// { "8300", 0, cb_PC8300, (void *) 5, FL_MENU_RADIO }, + { 0 }, + { "Speed", 0, 0, 0, FL_SUBMENU }, + { "2.4 MHz", 0, rspeed, (void *) 1, FL_MENU_RADIO | FL_MENU_VALUE }, + { "Max Speed", 0, fspeed, (void *) 1, FL_MENU_RADIO }, + { 0 }, + { "Display", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER}, + { "1x", 0, cb_1x, (void *) 1, FL_MENU_RADIO }, + { "2x", 0, cb_2x, (void *) 2, FL_MENU_RADIO }, + { "3x", 0, cb_3x, (void *) 3, FL_MENU_RADIO | FL_MENU_VALUE}, + { "4x", 0, cb_4x, (void *) 4, FL_MENU_RADIO | FL_MENU_DIVIDER}, + { "Framed", 0, cb_framed, (void *) 1, FL_MENU_TOGGLE|FL_MENU_VALUE }, + { "Solid Chars", 0, cb_solidchars, (void *) 1, FL_MENU_TOGGLE}, + { 0 }, +*/ + { "&Tools", 0, 0, 0, FL_SUBMENU }, + { "CPU Registers", 0, cb_CpuRegs }, + { "Disassembler", 0, disassembler_cb }, + { "Memory Editor", 0, cb_MemoryEditor }, + { "Peripheral Devices", 0, cb_PeripheralDevices }, + { "Simulation Log Viewer", 0, 0 }, + { "Model T File Viewer", 0, 0 }, + { 0 }, + { "&Help", 0, 0, 0, FL_SUBMENU }, + { "Help", 0, cb_help }, + { "About VirtualT", 0, cb_about }, + { 0 }, + + { 0 } +}; + +void cb_new_folder(Fl_Widget* w, void*); +void cb_add_files_to_folder(Fl_Widget* w, void*); +void cb_folder_properties(Fl_Widget* w, void*); +void cb_open_tree_file(Fl_Widget* w, void*); +void cb_assemble_tree_file(Fl_Widget* w, void*); +void cb_tree_file_properties(Fl_Widget* w, void*); +void cb_build(Fl_Widget* w, void*); +void cb_build_all(Fl_Widget* w, void*); +void cb_project_settings(Fl_Widget* w, void*); + +Fl_Menu_Item gGroupMenu[] = { + { "New Folder", 0, cb_new_folder, 0, 0 }, + { "Add Files to Folder",0, cb_add_files_to_folder, 0, 0 }, + { "Properties", 0, cb_folder_properties, 0, 0}, + { 0 } +}; + +Fl_Menu_Item gSourceMenu[] = { + { "Open", 0, cb_open_tree_file, 0, 0 }, + { "Assemble File", 0, cb_assemble_tree_file, 0, 0 }, + { "Properties", 0, cb_tree_file_properties, 0, 0}, + { 0 } +}; + +Fl_Menu_Item gRootMenu[] = { + { "Build", 0, cb_build, 0, 0 }, + { "Build All", 0, cb_build_all, 0, 0 }, + { "New Folder...", 0, cb_new_folder, 0, 0}, + { "Add Files to Project...", 0, cb_add_files_to_folder, 0, FL_MENU_DIVIDER }, + { "Project Settings...", 0, cb_project_settings, 0, 0}, + { 0 } +}; + +Fl_Pixmap gTextDoc( textdoc_xpm ), gComputer( computer_xpm ); + +/* +======================================================= +Callback routine for the close box of the IDE window +======================================================= +*/ +void close_ide_cb(Fl_Widget* w, void*) +{ + if (gpIde != NULL) + { + setMonitorWindow(0); + gpIde->hide(); + delete gpIde; + gpIde = 0; + gPopup = 0; + gpLcd = 0; + } +} + +/* +======================================================= +Callback routine for creating new files +======================================================= +*/ +void cb_new_file(Fl_Widget* w, void*) +{ +} + +/* +======================================================= +Callback routine for opening files +======================================================= +*/ +void cb_open_file(Fl_Widget* w, void*) +{ +} + +/* +======================================================= +Callback routine for saving files +======================================================= +*/ +void cb_save_file(Fl_Widget* w, void*) +{ +} + +/* +======================================================= +Callback routine for save as +======================================================= +*/ +void cb_save_as(Fl_Widget* w, void*) +{ +} + +/* +======================================================= +Callback routine for creating new project +======================================================= +*/ +void cb_new_project(Fl_Widget* w, void*) +{ + gpIde->NewProject(); +} + +/* +======================================================= +Callback routine for opening a project +======================================================= +*/ +void cb_open_project(Fl_Widget* w, void*) +{ + gpIde->OpenProject(); +} + +/* +======================================================= +Callback routine for saving current project +======================================================= +*/ +void cb_save_project(Fl_Widget* w, void*) +{ +} + +void cb_close_lcd(Fl_Widget* w, void*) +{ + setMonitorWindow(0); + delete gpLcd; + gpLcd = 0; +} + +/* +======================================================= +Callback routine for displaying the laptop screen +======================================================= +*/ +void cb_lcd_display(Fl_Widget* w, void*) +{ + if (gpLcd != 0) + { + gpIde->m_EditWindow->insert(*gpLcd, gpIde->m_EditWindow->children()); + gpLcd->show(); + gpLcd->show(); + gpLcd->redraw(); + return; + } + if (gModel == MODEL_T200) + gpLcd = new Fl_Multi_Window(0, 0, 240*2 + MW_BORDER_WIDTH*2, 128*2 + + MW_BORDER_WIDTH + MW_TITLE_HEIGHT, "Laptop Display"); + else + gpLcd = new Fl_Multi_Window(0, 0, 240*2 + MW_BORDER_WIDTH*2, 64*2 + + MW_BORDER_WIDTH + MW_TITLE_HEIGHT, "Laptop Display"); + + gpLcd->m_NoResize = 1; + gpLcd->callback(cb_close_lcd); + gpLcd->end(); + gpIde->m_EditWindow->insert(*gpLcd, gpIde->m_EditWindow->children()); + gpLcd->show(); + gpLcd->show(); + gpLcd->take_focus(); + setMonitorWindow(gpLcd->ClientArea()); +} + +/* +======================================================= +Callback routine to create new folder in Project Tree +======================================================= +*/ +void cb_new_folder(Fl_Widget* w, void* data) +{ + Flu_Tree_Browser::Node* n = (Flu_Tree_Browser::Node*) data; + + // Insure window exists + if (gpIde != 0) + gpIde->NewFolder(n); +} + +/* +======================================================= +Callback routine to add files to Project Tree Group +======================================================= +*/ +void cb_add_files_to_folder(Fl_Widget* w, void* data) +{ + Flu_Tree_Browser::Node* n = (Flu_Tree_Browser::Node*) data; + + // Insure window exists + if (gpIde != 0) + gpIde->AddFilesToFolder(n); +} + +/* +======================================================= +Callback routine to display Tree folder properties +======================================================= +*/ +void cb_folder_properties(Fl_Widget* w, void* data) +{ + Flu_Tree_Browser::Node* n = (Flu_Tree_Browser::Node*) data; + + // Insure window exists + if (gpIde != 0) + gpIde->FolderProperties(n); +} + +/* +======================================================= +Callback routine to open selected tree file +======================================================= +*/ +void cb_open_tree_file(Fl_Widget* w, void* data) +{ + Flu_Tree_Browser::Node* n = (Flu_Tree_Browser::Node*) data; + + // Insure window exists + if (gpIde != 0) + gpIde->OpenTreeFile(n); +} + +/* +======================================================= +Callback routine to assemble selected tree file +======================================================= +*/ +void cb_assemble_tree_file(Fl_Widget* w, void* data) +{ + Flu_Tree_Browser::Node* n = (Flu_Tree_Browser::Node*) data; + + // Insure window exists + if (gpIde != 0) + gpIde->AssembleTreeFile(n); +} + +/* +======================================================= +Callback routine to display selected tree file properties +======================================================= +*/ +void cb_tree_file_properties(Fl_Widget* w, void* data) +{ + Flu_Tree_Browser::Node* n = (Flu_Tree_Browser::Node*) data; + + // Insure window exists + if (gpIde != 0) + gpIde->TreeFileProperties(n); +} + +/* +======================================================= +Callback routine to build the project +======================================================= +*/ +void cb_build(Fl_Widget* w, void*) +{ +} + +/* +======================================================= +Callback routine to build all project files +======================================================= +*/ +void cb_build_all(Fl_Widget* w, void*) +{ +} + +/* +======================================================= +Callback routine to display project settings +======================================================= +*/ +void cb_project_settings(Fl_Widget* w, void*) +{ +} + +/* +======================================================= +Menu Item Callbacks +======================================================= +*/ +void cb_Ide(Fl_Widget* w, void*) +{ + + if (gpIde == NULL) + { + // Create a new window for the disassembler + gpIde = new VT_Ide(800, 600 , "Integrated Development Environment - Work in progress!!!"); + gpIde->show(); + } + +} + +void projtree_callback( Fl_Widget* w, void* ) +{ + Flu_Tree_Browser *t = (Flu_Tree_Browser*)w; + + int reason = t->callback_reason(); + Flu_Tree_Browser::Node *n = t->callback_node(); + + switch( reason ) + { + case FLU_HILIGHTED: + printf( "%s hilighted\n", n->label() ); + break; + + case FLU_UNHILIGHTED: + printf( "%s unhilighted\n", n->label() ); + break; + + case FLU_SELECTED: +/* if ((t1 != 0) && (t2 != 0)) + { + MString str = n->label(); + if (strcmp((const char *) str, "Header Files") == 0) + { + gpIde->m_EditWindow->insert(*t1, 0); + t1->hide(); + t1->show(); + t1->take_focus(); + } + else + { + gpIde->m_EditWindow->insert(*t2, 0); + t2->hide(); + t2->take_focus(); + t2->show(); + } + } + printf( "%s selected\n", n->label() );*/ + break; + + case FLU_UNSELECTED: + printf( "%s unselected\n", n->label() ); + break; + + case FLU_OPENED: + printf( "%s opened\n", n->label() ); + break; + + case FLU_CLOSED: + printf( "%s closed\n", n->label() ); + break; + + case FLU_DOUBLE_CLICK: + printf( "%s double-clicked\n", n->label() ); + if (gpIde != 0) + gpIde->OpenTreeFile(n); + break; + + case FLU_WIDGET_CALLBACK: + printf( "%s widget callback\n", n->label() ); + break; + + case FLU_RIGHT_CLICK: + printf( "%s right click\n", n->label()); + gpIde->RightClick(n); + break; + + case FLU_MOVED_NODE: + printf( "%s moved\n", n->label() ); + break; + + case FLU_NEW_NODE: + printf( "node '%s' added to the tree\n", n->label() ); + break; + } +} + + +VT_Ide::VT_Ide(int w, int h, const char *title) +: Fl_Window(w, h, title) +{ + // Parent window has no box, only child regions + box(FL_NO_BOX); + callback(close_ide_cb); + + // Create a menu for the new window. + Fl_Menu_Bar *m = new Fl_Menu_Bar(0, 0, 800, MENU_HEIGHT-2); + m->menu(gIde_menuitems); + + // Create a tiled window to support Project, Edit, and debug regions + Fl_Tile* tile = new Fl_Tile(0,MENU_HEIGHT-2,800,600-MENU_HEIGHT); + + /* + ============================================ + Create region for Project tree + ============================================ + */ + m_ProjWindow = new Fl_Window(2,MENU_HEIGHT-2,198,430,""); + m_ProjWindow->box(FL_DOWN_BOX); + + // Create Tree control + m_ProjTree = new Flu_Tree_Browser( 0, 0, 198, 430 ); + m_ProjTree->box( FL_DOWN_FRAME ); + m_ProjTree->callback( projtree_callback ); + m_ProjTree->selection_mode( FLU_SINGLE_SELECT ); + gPopup = new Fl_Menu_Button(0,0,100,400,"Popup"); + gPopup->type(Fl_Menu_Button::POPUP3); + gPopup->menu(gGroupMenu); + gPopup->selection_color(FL_LIGHT3); + gPopup->hide(); + m_ProjTree->hide(); + + m_ProjWindow->resizable(m_ProjTree); + m_ProjWindow->end(); + + /* + ================================================= + Create region and Child Window for editing files + ================================================= + */ + m_EditWindow = new Fl_Window(200,MENU_HEIGHT-2,600,430,"Edit"); + m_EditWindow->box(FL_DOWN_BOX); + m_EditWindow->color(FL_DARK2); + m_EditWindow->end(); + + /* + ================================================= + Create region for Debug and output tabs + ================================================= + */ + m_TabWindow = new Fl_Window(0,MENU_HEIGHT-2+430,800,170-MENU_HEIGHT+2,"Tab"); + m_TabWindow->box(FL_DOWN_BOX); + m_TabWindow->color(FL_LIGHT1); + + // Create a tab control + m_Tabs = new Fl_Tabs(0, 1, 800, 170-MENU_HEIGHT); + + /* + ==================== + Create build tab + ==================== + */ + m_BuildTab = new Fl_Group(2, 0, 797, 170-MENU_HEIGHT-20, " Build "); + m_BuildTab->box(FL_DOWN_BOX); + m_BuildTab->selection_color(FL_WHITE); + m_BuildTab->color(FL_WHITE); + + // Create a Text Editor to show the disassembled text + m_BuildTextDisp = new Fl_Text_Display(2, 0, 797, 170-MENU_HEIGHT-20); + m_BuildTextDisp->box(FL_DOWN_BOX); + m_BuildTextDisp->selection_color(FL_WHITE); + m_BuildTextDisp->color(FL_WHITE); + + // Create a Text Buffer for the Text Editor to work with + m_BuildTextBuf = new Fl_Text_Buffer(); + m_BuildTextDisp->buffer(m_BuildTextBuf); + + // Show the Disassembling text to indicate activity + m_BuildTextDisp->textfont(FL_COURIER); + m_BuildTextDisp->end(); + m_BuildTab->end(); + + /* + ==================== + Create Debug tab + ==================== + */ + m_DebugTab = new Fl_Group(2, 0, 797, 170-MENU_HEIGHT-20, " Debug "); + m_DebugTab->box(FL_DOWN_BOX); + m_DebugTab->selection_color(FL_WHITE); + m_DebugTab->color(FL_WHITE); + m_DebugTab->end(); + + /* + ==================== + Create watch tab + ==================== + */ + m_WatchTab = new Fl_Group(2, 0, 797, 170-MENU_HEIGHT-20, " Watch "); + m_WatchTab->box(FL_NO_BOX); + m_WatchTab->selection_color(FL_WHITE); + m_WatchTab->color(FL_WHITE); + + // Create tiled window for auto and watch variables + Fl_Tile* tile2 = new Fl_Tile(2, 0,800,170-MENU_HEIGHT-20); + + Fl_Box* box0 = new Fl_Box(2, 0,398,170-MENU_HEIGHT-20,"1"); + box0->box(FL_DOWN_BOX); + box0->color(FL_BACKGROUND_COLOR); + box0->labelsize(36); + box0->align(FL_ALIGN_CLIP); + Fl_Box* box1 = new Fl_Box(400, 0,400,170-MENU_HEIGHT-20,"2"); + box1->box(FL_DOWN_BOX); + box1->color(FL_BACKGROUND_COLOR); + box1->labelsize(36); + box1->align(FL_ALIGN_CLIP); + Fl_Box* r2 = new Fl_Box(0,0,800,170-MENU_HEIGHT-20); + tile2->resizable(r2); + tile2->end(); + m_WatchTab->resizable(tile2); + m_WatchTab->end(); + + m_Tabs->end(); + + m_TabWindow->resizable(m_Tabs); + m_TabWindow->end(); + + // Set resize region + Fl_Box* r = new Fl_Box(150,MENU_HEIGHT-2,800-150,430); + tile->resizable(r); + tile->end(); + resizable(m); + resizable(tile); + + // End the Window + end(); + + // Initialize other variables + m_ActivePrj = 0; +} + +/* +============================================================= +Override the default show function to display the children +windows +============================================================= +*/ +void VT_Ide::show() +{ + Fl_Window::show(); + m_EditWindow->show(); + m_TabWindow->show(); + m_BuildTextDisp->show_cursor(); +} + +/* +============================================================= +Override the default draw routine to display white regions +here and there +============================================================= +*/ +void VT_Ide::draw(void) +{ + // Color for outer border + fl_color(FL_WHITE); + + // Draw border along the top + fl_rectf(0,0,2,h()); + + Fl_Window::draw(); +} + +/* +============================================================= +NewProject routine handles the File->New Project menu item. +This routine creates an empty project and updates the Tree +control. +============================================================= +*/ +void VT_Ide::NewProject(void) +{ + VT_IdeGroup* pGroup; + + // Check if there is an active project + if (m_ActivePrj != 0) + { + // Check if project is dirty + if (m_ActivePrj->m_Dirty) + { + int c = fl_choice("Save project changes?", "Cancel", "Yes", "No"); + + if (c == 0) + return; + if (c == 1) + SaveProject(); + } + + // Delete existing project + delete m_ActivePrj; + m_ActivePrj = 0; + } + + // Create new project + m_ActivePrj = new VT_IdeProject; + m_ActivePrj->m_Name = "Unknown"; + + pGroup = new VT_IdeGroup; + pGroup->m_Name = "Source Files"; + m_ActivePrj->m_Groups.Add(pGroup); + + pGroup = new VT_IdeGroup; + pGroup->m_Name = "Header Files"; + m_ActivePrj->m_Groups.Add(pGroup); + + pGroup = new VT_IdeGroup; + pGroup->m_Name = "Object Files"; + m_ActivePrj->m_Groups.Add(pGroup); + + BuildTreeControl(); + + m_ProjTree->redraw(); + m_ProjTree->show(); +} + +/* +============================================================= +The SaveProject routine saves the active project structure to +a .prj file. +============================================================= +*/ +void VT_Ide::SaveProject(void) +{ +} + +/* +============================================================= +The OpenProject routine handles the File->Open Project menu +item. It presents a File Browser dialog to allow the user +to select a prj file then calls the ParsePrjFile method to +load the project. +============================================================= +*/ +void VT_Ide::OpenProject(void) +{ + MString filename; + Fl_File_Chooser *FileWin; + int count; + + FileWin = new Fl_File_Chooser("./Projects","*.prj",1,"Open Project file"); + FileWin->preview(0); + FileWin->show(); + + while (FileWin->visible()) + Fl::wait(); + + count = FileWin->count(); + if (count == 0) + { + delete FileWin; + return; + } + + // Get Filename + if (FileWin->value(1) == 0) + { + delete FileWin; + return; + } + filename = FileWin->value(1); + delete FileWin; + + // Check if there is an active project + if (m_ActivePrj != 0) + { + // Check if project is dirty + if (m_ActivePrj->m_Dirty) + { + int c = fl_choice("Save project changes?", "Cancel", "Yes", "No"); + + if (c == 0) + return; + if (c == 1) + SaveProject(); + } + + // Delete existing project + delete m_ActivePrj; + m_ActivePrj = 0; + } + + // Try to parse the file + if (ParsePrjFile(filename)) + BuildTreeControl(); + else + { + // Report parse error + } +} + +/* +============================================================= +The BuildTreeControl routine builds / rebuilds the Project +Tree control from the active Project structure. +============================================================= +*/ +void VT_Ide::BuildTreeControl(void) +{ + MString temp; + Flu_Tree_Browser::Node* n; + int len, c; + VT_IdeGroup* pGroup; + VT_IdeSource* pSource; + VTObject* pObj; + MString fmt, addStr; + + // Insure we have a project structure + if (m_ActivePrj == 0) + return; + + // set the default leaf icon to be a blue dot + m_ProjTree->leaf_icon( &gTextDoc ); + m_ProjTree->insertion_mode( FLU_INSERT_BACK ); + + // use the default branch icons (yellow folder) + m_ProjTree->branch_icons( NULL, NULL ); + + // Clear old contents of the tree + m_ProjTree->clear(); + + // Set the Root name + temp = m_ActivePrj->m_Name; + temp += " files"; + m_ProjTree->label( temp ); + + n = m_ProjTree->get_root(); + if( n ) + n->branch_icons( &gComputer, &gComputer ); + + // Initalize the format for adding items + fmt = "/%s"; + + // Loop through all objects in the project + len = m_ActivePrj->m_Groups.GetSize(); + for (c = 0; c < len; c++) + { + pObj = m_ActivePrj->m_Groups[c]; + const char *pStr = pObj->GetClass()->m_ClassName; + if (strcmp(pStr, "VT_IdeGroup") == 0) + { + // Object is a group add node to tree + pGroup = (VT_IdeGroup *) pObj; + addStr.Format(fmt, (const char *) pGroup->m_Name); + addStr += "/"; + n = m_ProjTree->add(addStr); + if (n) + { + n->user_data(pGroup); + pGroup->m_Node = n; + } + + addStr += "%s"; + + // Loop through all objects an add to tree + int sublen = pGroup->m_Objects.GetSize(); + for (int x = 0; x < sublen; x++) + { + AddGroupToTree(pGroup->m_Objects[x], addStr); + } + + } + else + { + // Object is a source + pSource = (VT_IdeSource *) pObj; + + // Get just the filename + int index = pSource->m_Name.ReverseFind("/"); + if (index == 0) + temp = pSource->m_Name; + else + temp = pSource->m_Name.Right(pSource->m_Name.GetLength() - index - 1); + addStr.Format(fmt, (const char *) temp); + + pStr = addStr; + n = m_ProjTree->add(addStr); + if( n ) + { + n->leaf_icon( &gTextDoc ); + n->user_data(pSource); + pSource->m_Node = n; + } + } + } + + m_ProjTree->open(TRUE); + m_ProjTree->show(); +} + +/* +============================================================= +The AddGroupToTree routine adds a complete subgroup to the +Project Tree control. This is a nested routine. +============================================================= +*/ +void VT_Ide::AddGroupToTree(VTObject *pObj, const char *fmt) +{ + MString temp; + Flu_Tree_Browser::Node* n; + int len, c; + VT_IdeGroup* pGroup; + VT_IdeSource* pSource; + MString addStr; + + const char *pStr = pObj->GetClass()->m_ClassName; + if (strcmp(pStr, "VT_IdeGroup") == 0) + { + // Object is a group add node to tree + pGroup = (VT_IdeGroup *) pObj; + addStr.Format(fmt, (const char *) pGroup->m_Name); + addStr += "/"; + n = m_ProjTree->add(addStr); + if (n) + { + n->user_data(pGroup); + pGroup->m_Node = n; + } + + addStr += "%s"; + + // Loop through all objects an add to tree + len = pGroup->m_Objects.GetSize(); + for (c = 0; c < len; c++) + { + AddGroupToTree(pGroup->m_Objects[c], addStr); + } + + } + else + { + // Object is a source + pSource = (VT_IdeSource *) pObj; + + // Get just the filename + int index = pSource->m_Name.ReverseFind("/"); + if (index == 0) + temp = pSource->m_Name; + else + temp = pSource->m_Name.Right(pSource->m_Name.GetLength() - index - 1); + addStr.Format(fmt, (const char *) temp); + + pStr = addStr; + n = m_ProjTree->add(addStr); + if( n ) + { + n->leaf_icon( &gTextDoc ); + n->user_data(pSource); + pSource->m_Node = n; + } + } +} + +/* +============================================================= +The ParsePrjFile routine parses the specified input file and +creates a Project structure which the IDE uses for control. +============================================================= +*/ +int VT_Ide::ParsePrjFile(const char *name) +{ + FILE* fd; + char line[512]; + char *param, *value; + MString sParam; + const char * sPtr; + VT_IdeGroup* pGroup = 0; + VT_IdeSource* pSource = 0; + VT_IdeGroup* stack[100]; + VTObject* pIns; + int index = 0; + int len, c; + + // Try to open input file + fd = fopen(name, "r+"); + if (fd == 0) + return 0; + + // Insure active project not null + if (m_ActivePrj == 0) + m_ActivePrj = new VT_IdeProject; + + // Loop through all lines in file + while (fgets(line, 512, fd) != 0) + { + // Skip comments and blank lines + if ((line[0] == '#') || (line[0] == '\n')) + continue; + + // Parse the line + param = strtok(line, "=\n"); + value = strtok(NULL, "=\n"); + + // Check for error in line + if (param == 0) + { + // Report error + continue; + } + + sParam = param; + sParam.MakeUpper(); + sPtr = (const char *) sParam; + if (strcmp(sPtr, "SOURCE") == 0) + { + // Insure there is an active group + if (pGroup != 0) + { + pSource = new VT_IdeSource; + pSource->m_Name = value; + + // Insert source alphabetically after groups + len = pGroup->m_Objects.GetSize(); + for (c = 0; c < len; c++) + { + pIns = pGroup->m_Objects[c]; + // Skip groups so they appear at top + if (strcmp(pIns->GetClass()->m_ClassName, "VT_IdeGroup") == 0) + continue; + + if (pSource->m_Name < ((VT_IdeSource *) pIns)->m_Name) + break; + } + pGroup->m_Objects.InsertAt(c, pSource); + pSource = 0; + } + } + else if (strcmp(sPtr, "GROUP") == 0) + { + // Check if there is an active group. If there is, we are adding a + // subgroup and need to "push" the pointer + if (pGroup != 0) + { + // Push pointer on stack + stack[index++] = pGroup; + + // Create new sub group item + VT_IdeGroup* newgrp = new VT_IdeGroup; + + // Assign name to new group + newgrp->m_Name = value; + + // Insert groups alphabetically before sources + len = pGroup->m_Objects.GetSize(); + for (c = 0; c < len; c++) + { + pIns = pGroup->m_Objects[c]; + // Stop at sign of first source + if (strcmp(pIns->GetClass()->m_ClassName, "VT_IdeSource") == 0) + break; + + if (pSource->m_Name < ((VT_IdeGroup *) pIns)->m_Name) + break; + } + pGroup->m_Objects.InsertAt(c, newgrp); + pGroup = newgrp; + } + else + { + pGroup = new VT_IdeGroup; + pGroup->m_Name = value; + } + } + else if (strcmp(sPtr, "ENDGROUP") == 0) + { + // Check if ending a sub group + if (index == 0) + { + // Not a subgroup, add group to project + m_ActivePrj->m_Groups.Add(pGroup); + + // Null out the group pointer + pGroup = 0; + } + else + { + // Pop the group from the stack + pGroup = stack[--index]; + } + } + else if (strcmp(sPtr, "FILESPEC") == 0) + { + if ((pGroup != 0) && (value != 0)) + pGroup->m_Filespec = value; + } + else if (strcmp(sPtr, "NAME") == 0) + { + if (value != 0) + m_ActivePrj->m_Name = value; + } + else if (strcmp(sPtr, "INCLPATH") == 0) + { + if (value != 0) + m_ActivePrj->m_IncludePath = value; + } + else if (strcmp(sPtr, "LINKPATH") == 0) + { + if (value != 0) + m_ActivePrj->m_LinkPath = value; + } + else if (strcmp(sPtr, "ASMOPT") == 0) + { + if (value != 0) + m_ActivePrj->m_AsmOptions = value; + } + else if (strcmp(sPtr, "LINKOPT") == 0) + { + if (value != 0) + m_ActivePrj->m_LinkOptions = value; + } + } + + // Close the file + fclose(fd); + return 1; +} + +VT_IdeProject::~VT_IdeProject() +{ + VTObject* pObj; + + for (int c =0; c < m_Groups.GetSize(); c++) + { + pObj = m_Groups[c]; + if (strcmp(pObj->GetClass()->m_ClassName, "VT_IdeGroup") == 0) + delete (VT_IdeGroup *) pObj; + else + delete (VT_IdeSource *) pObj; + } + m_Groups.RemoveAll(); +} + +VT_IdeGroup::~VT_IdeGroup() +{ + VTObject* pObj; + + for (int c =0; c < m_Objects.GetSize(); c++) + { + pObj = m_Objects[c]; + if (strcmp(pObj->GetClass()->m_ClassName, "VT_IdeGroup") == 0) + delete (VT_IdeGroup *) pObj; + else + delete (VT_IdeSource *) pObj; + } + + m_Objects.RemoveAll(); +} + +/* +============================================================= +The RightClick routine is called when the user performs a +RightClick operation on one of the items in the projec tree. +The routine displays a pop-up menu +============================================================= +*/ +void VT_Ide::RightClick(Flu_Tree_Browser::Node* n) +{ + if (n->is_root()) + { + gPopup->menu(gRootMenu); + } + else + { + VTObject* pObj = (VTObject *) n->user_data(); + if (strcmp(pObj->GetClass()->m_ClassName, "VT_IdeGroup") == 0) + { + gGroupMenu[0].user_data_ = n; + gGroupMenu[1].user_data_ = n; + gGroupMenu[2].user_data_ = n; + gPopup->menu(gGroupMenu); + } + else + { + gSourceMenu[0].user_data_ = n; + gSourceMenu[1].user_data_ = n; + gSourceMenu[2].user_data_ = n; + gPopup->menu(gSourceMenu); + } + } + gPopup->label(n->label()); + gPopup->popup(); +} + +void VT_Ide::NewFolder(Flu_Tree_Browser::Node* n) +{ + MString name, filespec; + VT_IdeGroup* pGroup; + VT_IdeGroup* pNewGrp; + int len, c, root; + Flu_Tree_Browser::Node* i; + Flu_Tree_Browser::Node* newNode; + + // Get Folder name + name = "ide"; + filespec = ""; + + // Create new VT_IdeGroup object for this folder + pNewGrp = new VT_IdeGroup; + pNewGrp->m_Name = name; + pNewGrp->m_Filespec = filespec; + + // Convert name to a branch + name += "/"; + + // Test if inserting at root + if (n == 0) + { + root = 1; + n = m_ProjTree->get_root(); + } + else + root = 0; + + if (root) + { + len = m_ActivePrj->m_Groups.GetSize(); + for (c = 0; c < len; c++) + { + // Stop when we encounter a source + if (strcmp(m_ActivePrj->m_Groups[c]->GetClass()->m_ClassName, "VT_IdeSource") == 0) + { + i = ((VT_IdeSource *) m_ActivePrj->m_Groups[c])->m_Node; + break; + } + + if (name < ((VT_IdeGroup*) m_ActivePrj->m_Groups[c])->m_Name) + { + i = ((VT_IdeGroup *) m_ActivePrj->m_Groups[c])->m_Node; + break; + } + } + } + else + { + // Seach group object for insertion point for folder + pGroup = (VT_IdeGroup *) n->user_data(); + len = pGroup->m_Objects.GetSize(); + for (c = 0; c < len; c++) + { + // Stop when we encounter a source + if (strcmp(pGroup->m_Objects[c]->GetClass()->m_ClassName, "VT_IdeSource") == 0) + { + i = ((VT_IdeSource *) pGroup->m_Objects[c])->m_Node; + break; + } + + if (name < ((VT_IdeGroup*)pGroup->m_Objects[c])->m_Name) + { + i = ((VT_IdeGroup *) pGroup->m_Objects[c])->m_Node; + break; + } + } + } + + // Test if adding at end of list + if (c == len) + newNode = m_ProjTree->insert_at(n, 0, name); + else + newNode = m_ProjTree->insert_at(n, i, name); + + newNode->user_data(pNewGrp); + pNewGrp->m_Node = newNode; + + // Add new node to active project + if (root) + { + if (c == len) + m_ActivePrj->m_Groups.Add(pNewGrp); + else + m_ActivePrj->m_Groups.InsertAt(c, pNewGrp); + } + else + { + if (c == len) + pGroup->m_Objects.Add(pNewGrp); + else + pGroup->m_Objects.InsertAt(c, pNewGrp); + } + + // Set Dirty flag + m_ActivePrj->m_Dirty = 1; +} + +void VT_Ide::AddFilesToFolder(Flu_Tree_Browser::Node* n) +{ +} + +void VT_Ide::FolderProperties(Flu_Tree_Browser::Node* n) +{ +} + +void VT_Ide::OpenTreeFile(Flu_Tree_Browser::Node* n) +{ + VT_IdeSource* pSource; + MString file; + + pSource = (VT_IdeSource *) n->user_data(); + if (pSource->m_Name.Left(2) == "./") + file = pSource->m_Name.Right(pSource->m_Name.GetLength()-2); + else + file = pSource->m_Name; + + int x = 10; + int y = 10; + const char *pStr = file; + if (file == "main.asm") + x = 200; + Fl_Multi_Window* mw = new Fl_Multi_Window(x, 10, 400, 300, (const char *)file); + Fl_Text_Editor* te = new Fl_Text_Editor(0, 0, mw->ClientArea()->w(), + mw->ClientArea()->h(), file); + Fl_Text_Buffer* tb = new Fl_Text_Buffer(); + te->buffer(tb); + + // Show the Disassembling text to indicate activity + tb->loadfile(file); + te->textfont(FL_COURIER); + te->end(); + mw->ClientArea()->resizable(te); + mw->end(); + + // Insert new window in EditWindow + Fl_Widget* prev = m_EditWindow->child(m_EditWindow->children()-1); + m_EditWindow->insert(*mw, m_EditWindow->children()); + mw->show(); + + // Redraw current window to show it as inactive + if (prev != 0) + prev->redraw(); + // Call show again to bring window to front + mw->show(); +} + +void VT_Ide::AssembleTreeFile(Flu_Tree_Browser::Node* n) +{ +} + +void VT_Ide::TreeFileProperties(Flu_Tree_Browser::Node* n) +{ +} + diff --git a/src/ide.h b/src/ide.h new file mode 100644 index 0000000..79742dd --- /dev/null +++ b/src/ide.h @@ -0,0 +1,125 @@ +/* ide.h */ + +/* $Id$ */ + +/* + * Copyright 2006 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef _IDE_H_ +#define _IDE_H_ + +#include "MString.h" +#include "vtobj.h" + + +void cb_Ide(Fl_Widget* w, void*) ; + + +#ifndef MENU_HEIGHT +#define MENU_HEIGHT 32 +#endif + +class VT_IdeSource : public VTObject +{ + DECLARE_DYNCREATE(VT_IdeSource); +public: + VT_IdeSource() {}; + + MString m_Name; + Flu_Tree_Browser::Node* m_Node; +}; + +class VT_IdeGroup : public VTObject +{ + DECLARE_DYNCREATE(VT_IdeGroup); + +public: + VT_IdeGroup() {}; + ~VT_IdeGroup(); + + MString m_Name; + MString m_Filespec; + VTObArray m_Objects; + Flu_Tree_Browser::Node* m_Node; +}; + + +class VT_IdeProject +{ +public: + VT_IdeProject() { m_Dirty = 0; }; + ~VT_IdeProject(); + + MString m_Name; + MString m_RootPath; + MString m_IncludePath; + MString m_LinkPath; + MString m_AsmOptions; + MString m_LinkOptions; + VTObArray m_Groups; + int m_Dirty; +}; + +class VT_Ide : public Fl_Window +{ +public: + VT_Ide(int w, int h, const char *title = 0); + +// Methods + virtual void show(); + + void NewProject(void); + void OpenProject(void); + void SaveProject(void); + void BuildTreeControl(void); + int ParsePrjFile(const char *name); + void RightClick(Flu_Tree_Browser::Node* n); + void NewFolder(Flu_Tree_Browser::Node* n); + void AddFilesToFolder(Flu_Tree_Browser::Node* n); + void FolderProperties(Flu_Tree_Browser::Node* n); + void OpenTreeFile(Flu_Tree_Browser::Node* n); + void AssembleTreeFile(Flu_Tree_Browser::Node* n); + void TreeFileProperties(Flu_Tree_Browser::Node* n); + + Fl_Window* m_EditWindow; +protected: + virtual void draw(); + void AddGroupToTree(VTObject *pObj, const char *fmt); + + Fl_Window* m_ProjWindow; + Flu_Tree_Browser* m_ProjTree; + Fl_Window* m_TabWindow; + Fl_Tabs* m_Tabs; + Fl_Group* m_BuildTab; + Fl_Text_Display* m_BuildTextDisp; + Fl_Text_Buffer* m_BuildTextBuf; + Fl_Group* m_DebugTab; + Fl_Group* m_WatchTab; + Flu_Tree_Browser::Node* m_Node; + VT_IdeProject* m_ActivePrj; +}; + +#endif diff --git a/src/io.c b/src/io.c index b7d94d3..b699a7c 100644 --- a/src/io.c +++ b/src/io.c @@ -667,7 +667,7 @@ void out(uchar port, uchar val) if ((val & 0x04) && !(ioE8 & 0x04)) { clock_chip_cmd(); - break; +// break; } } @@ -702,6 +702,8 @@ void out(uchar port, uchar val) /* New pointer loaded - mark it as "fresh" */ if ((A & 0x3F) < 50) lcd_fresh_ptr[c] = 1; + else + lcdcommand(c, A); } } } diff --git a/src/m100emu.c b/src/m100emu.c index 62bcfce..a05f486 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -31,8 +31,8 @@ #include #include #include -#include #include +#include #ifdef _WIN32 #include #endif @@ -68,8 +68,12 @@ extern uchar gOptROM[32768]; mem_monitor_cb gMemMonitor = NULL; +long hist[256]; +int order[256]; + char op[26]; UINT64 cycles=0; +int cycle_delta; UINT64 instructs=0; static UINT64 last_isr_cycle=0; int trace=0; @@ -132,7 +136,7 @@ __inline double hirestimer(void) #endif double last_instruct=0; -void cpu_delay(int cy) +void throttle(int cy) { double hires; @@ -157,7 +161,8 @@ void cpu_delay(int cy) else last_instruct = 0; cycles+=cy; - instructs++; + cycle_delta=0; +// instructs++; // if (hires-last_instruct > 1) // last_instruct = hires; } @@ -330,22 +335,22 @@ void get_rom_path(char* file, int model) switch (model) { case MODEL_M100: - strcpy(file, "ROMs/M100rom.bin"); + strcpy(file, "M100/M100rom.bin"); break; case MODEL_M102: - strcpy(file, "ROMs/M102rom.bin"); + strcpy(file, "M102/M102rom.bin"); break; case MODEL_T200: - strcpy(file, "ROMs/T200rom.bin"); + strcpy(file, "T200/T200rom.bin"); break; // case MODEL_M10: -// strcpy(file, "ROMs/m10rom.bin"); +// strcpy(file, "m10/m10rom.bin"); // break; case MODEL_PC8201: - strcpy(file, "ROMs/N8201rom.bin"); + strcpy(file, "PC8201/PC8201rom.bin"); break; case MODEL_PC8300: - strcpy(file, "ROMs/PC8300rom.bin"); + strcpy(file, "PC8300/PC8300rom.bin"); break; } } @@ -406,6 +411,8 @@ void init_cpu(void) show_error("Could not open ROM file"); } + gRomSize = gModel == MODEL_T200 ? 40960 : 32768; + /* Read data from the ROM file */ if (read(fd, gSysROM, ROMSIZE) -#include +#include +#include #include "VirtualT.h" #include "m100emu.h" @@ -29,9 +30,11 @@ uchar gMsplanROM[32768]; /* MSPLAN ROM T200 Only */ extern char path[255]; extern char file[255]; +int gOptRomRW = 0; /* Flag to make OptROM R/W */ unsigned char rambanks[3*32768]; /* Model T200 & NEC RAM banks */ uchar gRamBank = 0; /* Currently enabled bank */ -int gRomBank = 0; /* Current ROM Bank selection */ +int gRomBank = 0; /* Current ROM Bank selection */ +int gRomSize = 32768; /* Current ROM Size for R/O calculation */ uchar gReMem = 0; /* Flag indicating if ReMem emulation enabled */ uchar gReMemBoot = 0; /* ALT boot flag */ @@ -85,8 +88,8 @@ void set_memory8(unsigned short address, unsigned char data) void set_memory16(unsigned short address, unsigned short data) { - remem_set8(address, (unsigned char) (data & 0xFF)); - remem_set8(address+1, (unsigned char) (data >> 8)); + set_memory8(address, (unsigned char) (data & 0xFF)); + set_memory8((unsigned short)(address+1), (unsigned char) (data >> 8)); } /* @@ -108,7 +111,10 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) addr = RAMSTART + address; for (c = 0; c < count; c++) { - data[c] = gMemory[addr>>10][addr&0x3FF]; + if (gReMem) + data[c] = gMemory[addr>>10][addr&0x3FF]; + else + data[c] = gBaseMemory[addr]; addr++; } break; @@ -117,7 +123,10 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) addr = address; for (c = 0; c < count; c++) { - data[c] = gMemory[addr>>10][addr&0x3FF]; + if (gReMem) + data[c] = gMemory[addr>>10][addr&0x3FF]; + else + data[c] = gBaseMemory[addr]; addr++; } break; @@ -141,7 +150,10 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) addr = address + RAMSTART; for (c = 0; c < count; c++) { - data[c] = gMemory[addr>>10][addr&0x3FF]; + if (gReMem) + data[c] = gMemory[addr>>10][addr&0x3FF]; + else + data[c] = gBaseMemory[addr]; addr++; } } @@ -160,7 +172,10 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) addr = address + RAMSTART; for (c = 0; c < count; c++) { - data[c] = gMemory[addr>>10][addr&0x3FF]; + if (gReMem) + data[c] = gMemory[addr>>10][addr&0x3FF]; + else + data[c] = gBaseMemory[addr]; addr++; } } @@ -182,7 +197,10 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) addr = address + RAMSTART; for (c = 0; c < count; c++) { - data[c] = gMemory[addr>>10][addr&0x3FF]; + if (gReMem) + data[c] = gMemory[addr>>10][addr&0x3FF]; + else + data[c] = gBaseMemory[addr]; addr++; } } @@ -263,7 +281,10 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) addr = RAMSTART + address; for (c = 0; c < count; c++) { - gMemory[addr>>10][addr&0x3FF] = data[c]; + if (gReMem) + gMemory[addr>>10][addr&0x3FF] = data[c]; + else + gBaseMemory[addr] = data[c]; addr++; } break; @@ -272,7 +293,10 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) addr = address; for (c = 0; c < count; c++) { - gMemory[addr>>10][addr&0x3FF] = data[c]; + if (gReMem) + gMemory[addr>>10][addr&0x3FF] = data[c]; + else + gBaseMemory[addr] = data[c]; addr++; } break; @@ -296,7 +320,10 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) addr = address + RAMSTART; for (c = 0; c < count; c++) { - gMemory[addr>>10][addr&0x3FF] = data[c]; + if (gReMem) + gMemory[addr>>10][addr&0x3FF] = data[c]; + else + gBaseMemory[addr] = data[c]; addr++; } } @@ -315,7 +342,10 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) addr = address + RAMSTART; for (c = 0; c < count; c++) { - gMemory[addr>>10][addr&0x3FF] = data[c]; + if (gReMem) + gMemory[addr>>10][addr&0x3FF] = data[c]; + else + gBaseMemory[addr] = data[c]; addr++; } } @@ -337,7 +367,10 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) addr = address + RAMSTART; for (c = 0; c < count; c++) { - gMemory[addr>>10][addr&0x3FF] = data[c]; + if (gReMem) + gMemory[addr>>10][addr&0x3FF] = data[c]; + else + gBaseMemory[addr] = data[c]; addr++; } } @@ -446,6 +479,9 @@ void init_mem(void) gReMem = (mem_setup.mem_mode == SETUP_MEM_REMEM) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC); gRampac = (mem_setup.mem_mode == SETUP_MEM_RAMPAC) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC); + // Initialize ROM size base on current model + gRomSize = gModel == MODEL_T200 ? 40960 : 32768; + for (c = 0; c < 65536; c++) gIndex[c] = c >> 10; @@ -482,6 +518,13 @@ void init_mem(void) } else { + /* Reset Rom Size back to original */ + if (gModel == MODEL_T200) + gRomSize = 40960; + else + gRomSize = 32768; + + /* Copy Memory */ for (c = 0; c < ROMSIZE/1024; c++) gMemory[c] = &gSysROM[c*1024]; @@ -516,6 +559,9 @@ void init_mem(void) void reinit_mem(void) { + // Initialize ROM size base on current model + gRomSize = gModel == MODEL_T200 ? 40960 : 32768; + /* Check if ReMem emulation on */ if (gReMem) { @@ -1052,13 +1098,20 @@ void set_rom_bank(unsigned char bank) case MODEL_M102: gRomBank = bank; if (bank & 0x01) + { memcpy(gBaseMemory,gOptROM,ROMSIZE); + gRomSize = gOptRomRW ? 0 : 32768; + } else + { + gRomSize = 32768; memcpy(gBaseMemory,gSysROM,ROMSIZE); + } break; case MODEL_T200: /* Model 200 emulation */ gRomBank = bank; + gRomSize = 40960; switch (bank) { case 0: memcpy(gBaseMemory,gSysROM,ROMSIZE); @@ -1068,6 +1121,7 @@ void set_rom_bank(unsigned char bank) break; case 2: memcpy(gBaseMemory,gOptROM,sizeof(gOptROM)); + gRomSize = gOptRomRW ? 0 : 40960; break; } break; @@ -1075,6 +1129,7 @@ void set_rom_bank(unsigned char bank) case MODEL_PC8201: /* NEC laptops */ case MODEL_PC8300: gRomBank = bank; /* Update global ROM bank var */ + gRomSize = 32768; switch (bank) { @@ -1084,6 +1139,7 @@ void set_rom_bank(unsigned char bank) case 1: /* Option ROM bank */ memcpy(gBaseMemory,gOptROM,ROMSIZE); + gRomSize = gOptRomRW ? 0 : 32768; break; case 2: /* RAM banks */ diff --git a/src/multiwin.cpp b/src/multiwin.cpp new file mode 100644 index 0000000..73b95d6 --- /dev/null +++ b/src/multiwin.cpp @@ -0,0 +1,637 @@ +/* multiwin.cpp */ + +/* $Id$ */ + +/* + * Copyright 2006 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "VirtualT.h" +#include "m100emu.h" +#include "multiwin.h" +#include "multiwin_icons.h" + +int Fl_Multi_Window::m_WindowCount = 0; +int Fl_Multi_Window::m_MinimizeRegions[200] = { -1 }; + +Fl_Multi_Window* gpDestroyPtr = 0; + +void multi_window_idle_proc(void* w) +{ + if (gpDestroyPtr != 0) + { + gpDestroyPtr->do_callback(); + gpDestroyPtr = 0; + } + +} + +void multi_window_def_callback(Fl_Widget *w, void *) +{ + w->hide(); + delete (Fl_Multi_Window *) w; +} + +Fl_Multi_Window::Fl_Multi_Window(int x, int y, int w, int h, const char* title) +: Fl_Double_Window(x, y, w, h, title) +{ + int c; + + m_pClientArea = new Fl_Window(MW_BORDER_WIDTH, MW_TITLE_HEIGHT, w - MW_BORDER_WIDTH*2, + h - MW_BORDER_WIDTH - MW_TITLE_HEIGHT); + m_pClientArea->color(FL_WHITE); +// resizable(m_pClientArea); + m_pLabel = new char[strlen(title) + 1]; + strcpy(m_pLabel, title); + label(m_pLabel); + + // Set default Icon + m_pIcon = new Fl_Pixmap(gMultiWinDoc_xpm); + + // Set default callback + callback(multi_window_def_callback); + + m_InDragArea = 0; + m_InResizeArea = 0; + m_InIconArea = 0; + m_IconArea[0] = VT_Rect(w-25, 6, 19, 20); + m_IconArea[1] = VT_Rect(w-45, 6, 19, 20); + m_IconArea[2] = VT_Rect(w-65, 6, 19, 20); + + m_NormalIcon[0] = &gCloseIcon; + m_NormalIcon[1] = &gMaximizeIcon; + m_NormalIcon[2] = &gMinimizeIcon; + + m_PushedIcon[0] = &gCloseIconSelected; + m_PushedIcon[1] = &gMaximizeIconSelected; + m_PushedIcon[2] = &gMinimizeIconSelected; + + m_InactiveIcon[0] = &gCloseIconInactive; + m_InactiveIcon[1] = &gMaximizeIconInactive; + m_InactiveIcon[2] = &gMinimizeIconInactive; + + m_CaptureMode = 0; + m_NoResize = 0; + m_Minimized = 0; + m_Maximized = 0; + m_MinimizeLoc = -1; + + if (m_WindowCount++ == 0) + { + Fl::add_idle(multi_window_idle_proc, parent()); + } + + if (m_MinimizeRegions[0] == -1) + { + for (c = 0; c < 200; c++) + m_MinimizeRegions[c] = 0; + } +} + +Fl_Multi_Window::~Fl_Multi_Window() +{ + if (m_MinimizeLoc != -1) + m_MinimizeRegions[m_MinimizeLoc] = 0; + delete m_pLabel; + delete m_pIcon; + if (--m_WindowCount == 0) + Fl::remove_idle(multi_window_idle_proc, parent()); +} + +/* +=============================================================== +Routine to draw the border and title bar of the window +=============================================================== +*/ +void Fl_Multi_Window::draw(void) +{ + int baseColor; + int hilight; + int c; + + if (parent()->child(parent()->children()-1) == this) + { + baseColor = FL_BLUE; + hilight = 4; + } + else + { + baseColor = FL_BLUE+5; + hilight = 2; + } + + // Draw the window borders + fl_color(baseColor); + fl_rectf(0, 0, w(), MW_TITLE_HEIGHT); + fl_rectf(0, MW_TITLE_HEIGHT, MW_BORDER_WIDTH, h()-MW_TITLE_HEIGHT); + fl_rectf(w()-MW_BORDER_WIDTH, MW_TITLE_HEIGHT, MW_BORDER_WIDTH, h()-MW_TITLE_HEIGHT); + fl_rectf(0, h()-MW_BORDER_WIDTH, w(), MW_BORDER_WIDTH); + + // Draw hilight bars base on activation state of the window + fl_color(baseColor+hilight); + fl_rectf(1, 1, w()-2, 2); + fl_color(baseColor+hilight-1); + fl_rectf(1, 3, w()-2, 2); + fl_line(1, 1, 1, h()-2); + fl_line(w()-2, 1, w()-2, h()-2); + fl_line(1, h()-2, w()-2, h()-2); + if (baseColor == FL_BLUE) + { + for (c = 0; c < (m_NoResize ? 1 : 3); c++) + { + // Draw icons in upper right of window + if ((m_InIconArea == c+1) && (m_LastInIconArea)) + m_PushedIcon[c]->draw(m_IconArea[c].x(), m_IconArea[c].y()); + else + m_NormalIcon[c]->draw(m_IconArea[c].x(), m_IconArea[c].y()); + } + } + else + { + // Draw icons in upper right of window + for (c = 0; c < (m_NoResize ? 1 : 3); c++) + m_InactiveIcon[c]->draw(m_IconArea[c].x(), m_IconArea[c].y()); + } + + // Draw the icon + m_pIcon->draw(7,8); + + // Draw the window title + fl_font(FL_HELVETICA_BOLD, 14); + if (baseColor == FL_BLUE) + { + fl_color(FL_BLACK); + fl_draw(label(), 26, 23); + } + fl_color(FL_WHITE); + fl_draw(label(), 25, 22); +} + +/* +=============================================================== +Routine to handle events such as window move/resize, icon +processing, etc. +=============================================================== +*/ +int Fl_Multi_Window::handle(int event) +{ + int mx, my; + int ix, iy; + int newx, newy; + int absx, absy; + int c; + + Fl_Group* p; + Fl_Widget* prev; + + switch (event) + { + case FL_ENTER: + return 1; + + case FL_DRAG: + // Get window relative mouse coordinates + mx = Fl::event_x(); + my = Fl::event_y(); + + // Check if we are in capture mode + if (m_CaptureMode) + { + // Check if moving the window + if (m_InDragArea) + { + // Get absolute (screen) mouse coordinates + Fl::get_mouse(mx, my); + + // Calculate new window position + newx = m_WinAnchorX + mx - m_MouseAnchorX; + newy = m_WinAnchorY + my - m_MouseAnchorY; + + // Restrict position + if (newx + w() < 100) + newx = 100 - w(); + if (newx > parent()->w()-MW_TITLE_HEIGHT) + newx = parent()->w()-MW_TITLE_HEIGHT; + if (newy < 0) + newy = 0; + if (newy > parent()->h()-MW_TITLE_HEIGHT) + newy = parent()->h()-MW_TITLE_HEIGHT; + + // Move the window + position(newx, newy); + + // If window is minimized, save location of the window + if (m_Minimized) + { + m_MinimizeRect = VT_Rect(x(), y(), w(), h()); + if (m_MinimizeLoc != -1) + { + m_MinimizeRegions[m_MinimizeLoc] = 0; + m_MinimizeLoc = -1; + } + } + } + else if (m_InIconArea) + { + ix = m_IconArea[m_InIconArea-1].x(); + iy = m_IconArea[m_InIconArea-1].y(); + + // Dragging while in Capture to Icon area + if ((mx >= ix) && (mx <= m_IconArea[m_InIconArea-1].x1()) && + (my >= iy) && (my <= m_IconArea[m_InIconArea-1].y1()) ) + { + // Check if we were already in icon area before and skip drawing if so + if (!m_LastInIconArea) + { + // Select window for drawing + make_current(); + + // Draw the pushed icon + m_PushedIcon[m_InIconArea-1]->draw(m_IconArea[m_InIconArea-1].x(), + m_IconArea[m_InIconArea-1].y()); + m_LastInIconArea = 1; + } + } + else + // Test if we were already out of Icon area and skip drawing if so + if (m_LastInIconArea) + { + // Select window for drawing + make_current(); + + // Draw the normal ("unpushed") icon + m_NormalIcon[m_InIconArea-1]->draw(m_IconArea[m_InIconArea-1].x(), + m_IconArea[m_InIconArea-1].y()); + m_LastInIconArea = 0; + } + } + else if (m_InResizeArea) + { + // Resizing the window + Fl::get_mouse(mx, my); + newx = m_WinAnchorX + mx - m_MouseAnchorX; + newy = m_WinAnchorY + my - m_MouseAnchorY; + + // Set minimum window size + if (newx < 100) + newx = 100; + if (newy < 100) + newy = 100; + + // Resize window and it's client + resize(x(), y(), newx, newy); + m_pClientArea->resize(MW_BORDER_WIDTH, MW_TITLE_HEIGHT, newx - MW_BORDER_WIDTH*2, + newy - MW_BORDER_WIDTH - MW_TITLE_HEIGHT); + + // Move location of Icon Areas base on new window size + m_IconArea[0].x(w()-25); + m_IconArea[1].x(w()-45); + m_IconArea[2].x(w()-65); + } + } + return 1; + + case FL_RELEASE: + if (m_CaptureMode) + { + // Test if we are processing an Icon selection + if (m_InIconArea) + { + // Test if button release while still in icon + make_current(); + m_NormalIcon[m_InIconArea-1]->draw(m_IconArea[m_InIconArea-1].x(), + m_IconArea[m_InIconArea-1].y()); + + // Test if mouse released while in icon area and do some action + if (m_LastInIconArea) + { + // Check which Icon was selected + if (m_InIconArea == 1) + CloseIconSelected(); + else if (m_InIconArea == 2) + MaximizeIconSelected(); + else if (m_InIconArea == 3) + MinimizeIconSelected(); + } + + // Clear flags indicating active Icon manipulation + m_LastInIconArea = 0; + m_InIconArea = 0; + } + + // Release the mouse and all capture variables + Fl::release(); + m_CaptureMode = 0; + m_InDragArea = 0; + m_InResizeArea = 0; + } + break; + + case FL_PUSH: + // Get the mouse event coordinates + mx = Fl::event_x(); + my = Fl::event_y(); + + // Take action depending on which mouse button selected + switch (Fl::event_button()) + { + case FL_LEFT_MOUSE: + // Check if we are the first window + p = parent(); + prev = p->child(p->children()-1); + if (prev != this) + { + // Insert ourselves as the first window + p->remove(this); + p->insert(*this, p->children()); + + // Show window to bring to top. redraw and take focus + show(); + redraw(); + take_focus(); + + // Redraw previously selected window to change border color + prev->redraw(); + } + + // Test if in any of the icon areas + for (c = 0; c < (m_NoResize ? 1 : 3); c++) + { + // Get coordinates for this icon + ix = m_IconArea[c].x(); + iy = m_IconArea[c].y(); + + // Dragging while in Capture to Icon area + if ((mx >= ix) && (mx <= m_IconArea[c].x1()) && + (my >= iy) && (my <= m_IconArea[c].y1()) ) + { + // Setup capture mode for this icon + m_InIconArea = c+1; + Fl::grab(this); + m_CaptureMode = 1; + m_LastInIconArea = 1; + + // Draw the "Pushed" version of this icon + make_current(); + if (m_PushedIcon[c] != 0) + m_PushedIcon[c]->draw(m_IconArea[c].x(), m_IconArea[c].y()); + return 1; + } + } + + // Check if in title bar area + if (my < MW_TITLE_HEIGHT) + { + // Configure capture mode + Fl::get_mouse(absx, absy); + Fl::grab(this); + m_InDragArea = 1; + m_CaptureMode = 1; + + // Get anchor point for mouse and window + m_MouseAnchorX = absx; + m_MouseAnchorY = absy; + m_WinAnchorX = x(); + m_WinAnchorY = y(); + } + + // Check if in resize area + if ((mx > w()-12-MW_BORDER_WIDTH) && (my > h()-12-MW_BORDER_WIDTH) && + !m_NoResize) + { + // Configure capture mode + Fl::get_mouse(absx, absy); + Fl::grab(this); + m_InResizeArea = 1; + m_CaptureMode = 1; + + // Get anchor point for mouse and window size + m_MouseAnchorX = absx; + m_MouseAnchorY = absy; + m_WinAnchorX = w(); + m_WinAnchorY = h(); + } + + // Do other mouse button push stuff + Fl_Double_Window::handle(event); + return 1; + } + break; + + default: + break; + } + + return Fl_Double_Window::handle(event); +} + +/* +=============================================================== +Routine to handle selection of the close window icon +=============================================================== +*/ +void Fl_Multi_Window::CloseIconSelected() +{ + Fl_Window* p; + hide(); + p = (Fl_Window*) parent(); + p->remove(this); + if (p->children() != 0) + p->child(p->children()-1)->redraw(); + gpDestroyPtr = this; +} + +/* +=============================================================== +Routine to handle selection of the restore icon +=============================================================== +*/ +void Fl_Multi_Window::MaximizeIconSelected() +{ + int newx, newy; + + // Check if window minimized + if (m_Maximized) + { + m_NormalIcon[1] = &gMaximizeIcon; + m_PushedIcon[1] = &gMaximizeIconSelected; + m_InactiveIcon[1] = &gMaximizeIconInactive; + m_Maximized = 0; + + // Restore window to original location + resize(m_RestoreRect.x(), m_RestoreRect.y(), m_RestoreRect.w(), m_RestoreRect.h()); + m_pClientArea->resize(MW_BORDER_WIDTH, MW_TITLE_HEIGHT, m_RestoreRect.w() - MW_BORDER_WIDTH*2, + m_RestoreRect.h() - MW_BORDER_WIDTH - MW_TITLE_HEIGHT); + + // Move location of Icon Areas base on new window size + m_IconArea[0].x(w()-25); + m_IconArea[1].x(w()-45); + m_IconArea[2].x(w()-65); + + make_current(); + redraw(); + } + else + { + m_NormalIcon[1] = &gRestoreIcon; + m_PushedIcon[1] = &gRestoreIconSelected; + m_InactiveIcon[1] = &gRestoreIconInactive; + m_Maximized = 1; + + // If the window isn't minimized, save the current position for restoring purposes + if (!m_Minimized) + m_RestoreRect = VT_Rect(x(), y(), w(), h()); + + // Move window so it occupies the enntire client area of the parent + // such that the side and bottom borders are hidden + newx = parent()->w()+MW_BORDER_WIDTH*2; + newy = parent()->h()+MW_BORDER_WIDTH; + + resize(-MW_BORDER_WIDTH, 0, newx, newy); + m_pClientArea->resize(MW_BORDER_WIDTH, MW_TITLE_HEIGHT, newx - MW_BORDER_WIDTH*2, + newy - MW_BORDER_WIDTH - MW_TITLE_HEIGHT); + + // Move location of Icon Areas base on new window size + m_IconArea[0].x(w()-25); + m_IconArea[1].x(w()-45); + m_IconArea[2].x(w()-65); + + + + make_current(); + redraw(); + } +} + +/* +=============================================================== +Routine to handle selection of the minimize icon +=============================================================== +*/ +void Fl_Multi_Window::MinimizeIconSelected() +{ + // Check if window minimized + if (m_Minimized) + { + m_NormalIcon[2] = &gMinimizeIcon; + m_PushedIcon[2] = &gMinimizeIconSelected; + m_InactiveIcon[2] = &gMinimizeIconInactive; + + // Restore window to original location + resize(m_RestoreRect.x(), m_RestoreRect.y(), m_RestoreRect.w(), m_RestoreRect.h()); + + // Move location of Icon Areas base on new window size + m_IconArea[0].x(w()-25); + m_IconArea[1].x(w()-45); + m_IconArea[2].x(w()-65); + + parent()->insert(*this, parent()->children()-1); + m_Minimized = 0; + m_MinimizeRegions[m_MinimizeLoc] = 0; + m_MinimizeLoc = -1; + make_current(); + redraw(); + } + else + { + // Change icon to be displayed + m_NormalIcon[2] = &gRestoreIcon; + m_PushedIcon[2] = &gRestoreIconSelected; + m_InactiveIcon[2] = &gRestoreIconInactive; + + // If the window isn't maximized, save the current position for restoring purposes + if (!m_Maximized) + m_RestoreRect = VT_Rect(x(), y(), w(), h()); + + // Determine if this window has a specific minimize location + if (m_MinimizeRect.w() != 0) + { + // Determine if specified coords are still within the view + if ((m_MinimizeRect.x1() <= parent()->w()) && (m_MinimizeRect.y1() <= parent()->h())) + { + // Move to specified locaiton + resize(m_MinimizeRect.x(), m_MinimizeRect.y(), MW_MINIMIZE_WIDTH, MW_TITLE_HEIGHT); + + // Move location of Icon Areas base on new window size + m_IconArea[0].x(w()-25); + m_IconArea[1].x(w()-45); + m_IconArea[2].x(w()-65); + } + else + m_MinimizeRect = VT_Rect(0, 0, 0, 0); + } + + // Check if minimize operation to the next available location + if (m_MinimizeRect.w() == 0) + { + // Check if window already has a minimize location assigned + if (m_MinimizeLoc == -1) + { + // Assign a new minimize location + int c; + for (c = 0; c < 200; c++) + { + if (m_MinimizeRegions[c] == 0) + { + m_MinimizeLoc = c; + m_MinimizeRegions[c] = 1; + break; + } + } + } + + // Minimize window to the assigned location + int winPerLine = parent()->w() / MW_MINIMIZE_WIDTH; + int locX = m_MinimizeLoc % winPerLine; + int locY = m_MinimizeLoc / winPerLine; + resize(locX * MW_MINIMIZE_WIDTH, parent()->h()-(locY+1)*MW_TITLE_HEIGHT, + MW_MINIMIZE_WIDTH, MW_TITLE_HEIGHT); + + // Move location of Icon Areas base on new window size + m_IconArea[0].x(w()-25); + m_IconArea[1].x(w()-45); + m_IconArea[2].x(w()-65); + + parent()->insert(*this, 0); + parent()->child(parent()->children()-1)->redraw(); + } + + // Insert this window at the bottom + m_Minimized = 1; + make_current(); + redraw(); + } +} diff --git a/src/multiwin.h b/src/multiwin.h new file mode 100644 index 0000000..5f26ecc --- /dev/null +++ b/src/multiwin.h @@ -0,0 +1,86 @@ +/* multiwin.cpp */ + +/* $Id$ */ + +/* + * Copyright 2006 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef _MULTIWIN_H_ +#define _MULTIWIN_H_ + +#define MW_TITLE_HEIGHT 28 +#define MW_BORDER_WIDTH 4 +#define MW_MINIMIZE_WIDTH 150 + +#include +#include +#include "vtobj.h" + +class Fl_Multi_Window : public Fl_Double_Window +{ +public: + Fl_Multi_Window(int x, int y, int w, int h, const char *label = 0); + ~Fl_Multi_Window(); + + Fl_Window* ClientArea() { return m_pClientArea; }; + + int m_NoResize; + +protected: + void virtual draw(void); + int virtual handle(int event); + void CloseIconSelected(); + void MaximizeIconSelected(); + void MinimizeIconSelected(); + + Fl_Window* m_pClientArea; + Fl_Pixmap* m_pIcon; + char* m_pLabel; + int m_InDragArea; + int m_InResizeArea; + int m_InIconArea; + int m_LastInIconArea; + VT_Rect m_IconArea[3]; + Fl_Pixmap* m_NormalIcon[3]; + Fl_Pixmap* m_PushedIcon[3]; + Fl_Pixmap* m_InactiveIcon[3]; + int m_Minimized; + int m_Maximized; + VT_Rect m_MinimizeRect; + VT_Rect m_RestoreRect; + int m_MinimizeLoc; + static int m_MinimizeRegions[200]; + + int m_CaptureMode; + int m_MouseLastX, m_MouseLastY; + int m_MouseAnchorX, m_MouseAnchorY; + int m_WinAnchorX, m_WinAnchorY; + + static int m_WindowCount; +}; + +#endif + diff --git a/src/multiwin_icons.cpp b/src/multiwin_icons.cpp new file mode 100644 index 0000000..8d2fe74 --- /dev/null +++ b/src/multiwin_icons.cpp @@ -0,0 +1,389 @@ +/* multiwin_icons.cpp */ + +/* $Id$ */ + +/* + * Copyright 2006 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include + +/* XPM */ +char * gMultiWinDoc_xpm[] = { +"15 18 5 1", +" c None", +". c #848484", +"+ c #FFFFFF", +"@ c #C6C6C6", +"# c #000000", +" ", +" .......... ", +" .++++++++@. ", +" .+@......@+. ", +" .++++++++...# ", +" .+@.......+@# ", +" .++++++++++@# ", +" .+@.......+@# ", +" .++++++++++@# ", +" .+@.......+@# ", +" .++++++++++@# ", +" .+@.......+@# ", +" .++++++++++@# ", +" .+@.......+@# ", +" .++++++++++@# ", +" .@@@@@@@@@@@# ", +" ############ ", +" "}; + +/* XPM */ +char * gCloseBox[] = { +"20 19 4 1", +" c None", +". c #FF0000", +"+ c #FFFFFF", +"# c #000000", +" ", +" ++++++++++++++++ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +...++......++...+ ", +" +...+++....+++...+ ", +" +....+++..+++....+ ", +" +.....++++++.....+ ", +" +......++++......+ ", +" +.....++++++.....+ ", +" +....+++..+++....+ ", +" +...+++....+++...+ ", +" +...++......++...+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" ++++++++++++++++ ", +" "}; + +char * gCloseBoxSelected[] = { +"20 19 5 1", +" c None", +". c #A00000", +"+ c #FFFFFF", +"@ c #C0C0C0", +"# c #000000", +" ", +" ++++++++++++++++ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +...@@......@@...+ ", +" +...@@@....@@@...+ ", +" +....@@@..@@@....+ ", +" +.....@@@@@@.....+ ", +" +......@@@@......+ ", +" +.....@@@@@@.....+ ", +" +....@@@..@@@....+ ", +" +...@@@....@@@...+ ", +" +...@@......@@...+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" ++++++++++++++++ ", +" "}; + +char * gCloseBoxInactive[] = { +"20 19 4 1", +" c None", +". c #FF8080", +"+ c #FFFFFF", +"# c #000000", +" ", +" ++++++++++++++++ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +...++......++...+ ", +" +...+++....+++...+ ", +" +....+++..+++....+ ", +" +.....++++++.....+ ", +" +......++++......+ ", +" +.....++++++.....+ ", +" +....+++..+++....+ ", +" +...+++....+++...+ ", +" +...++......++...+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" ++++++++++++++++ ", +" "}; + +char * gMinimizeBox[] = { +"20 19 4 1", +" c None", +". c #0000FF", +"+ c #FFFFFF", +"# c #FFFFFF", +" ", +" ++++++++++++++++ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +...#######......+ ", +" +...#######......+ ", +" +...#######......+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" ++++++++++++++++ ", +" "}; +char * gMinimizeBoxSelected[] = { +"20 19 4 1", +" c None", +". c #0000A0", +"+ c #FFFFFF", +"# c #C0C0C0", +" ", +" ++++++++++++++++ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +...#######......+ ", +" +...#######......+ ", +" +...#######......+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" ++++++++++++++++ ", +" "}; + +char * gMinimizeBoxInactive[] = { +"20 19 4 1", +" c None", +". c #8080FF", +"+ c #FFFFFF", +"# c #D0D0D0", +" ", +" ++++++++++++++++ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" +...#######......+ ", +" +...#######......+ ", +" +...#######......+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" ++++++++++++++++ ", +" "}; + +char * gMaximizeBox[] = { +"20 19 4 1", +" c None", +". c #0000FF", +"+ c #FFFFFF", +"# c #FFFFFF", +" ", +" ++++++++++++++++ ", +" +................+ ", +" +................+ ", +" +...##########...+ ", +" +...##########...+ ", +" +...##########...+ ", +" +...##########...+ ", +" +...#........#...+ ", +" +...#........#...+ ", +" +...#........#...+ ", +" +...#........#...+ ", +" +...#........#...+ ", +" +...##########...+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" ++++++++++++++++ ", +" "}; + +char * gMaximizeBoxSelected[] = { +"20 19 4 1", +" c None", +". c #0000A0", +"+ c #FFFFFF", +"# c #C0C0C0", +" ", +" ++++++++++++++++ ", +" +................+ ", +" +................+ ", +" +...##########...+ ", +" +...##########...+ ", +" +...##########...+ ", +" +...##########...+ ", +" +...#........#...+ ", +" +...#........#...+ ", +" +...#........#...+ ", +" +...#........#...+ ", +" +...#........#...+ ", +" +...##########...+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" ++++++++++++++++ ", +" "}; + +char * gMaximizeBoxInactive[] = { +"20 19 4 1", +" c None", +". c #8080FF", +"+ c #FFFFFF", +"# c #D0D0D0", +" ", +" ++++++++++++++++ ", +" +................+ ", +" +................+ ", +" +...##########...+ ", +" +...##########...+ ", +" +...##########...+ ", +" +...##########...+ ", +" +...#........#...+ ", +" +...#........#...+ ", +" +...#........#...+ ", +" +...#........#...+ ", +" +...#........#...+ ", +" +...##########...+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" ++++++++++++++++ ", +" "}; + +char * gRestoreBox[] = { +"20 19 4 1", +" c None", +". c #0000FF", +"+ c #FFFFFF", +"# c #FFFFFF", +" ", +" ++++++++++++++++ ", +" +................+ ", +" +................+ ", +" +....#########...+ ", +" +....#########...+ ", +" +....#.......#...+ ", +" +..#########.#...+ ", +" +..#########.#...+ ", +" +..#.......#.#...+ ", +" +..#.......###...+ ", +" +..#.......#.....+ ", +" +..#.......#.....+ ", +" +..#########.....+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" ++++++++++++++++ ", +" "}; + +char * gRestoreBoxSelected[] = { +"20 19 4 1", +" c None", +". c #0000A0", +"+ c #FFFFFF", +"# c #C0C0C0", +" ", +" ++++++++++++++++ ", +" +................+ ", +" +................+ ", +" +....#########...+ ", +" +....#########...+ ", +" +....#.......#...+ ", +" +..#########.#...+ ", +" +..#########.#...+ ", +" +..#.......#.#...+ ", +" +..#.......###...+ ", +" +..#.......#.....+ ", +" +..#.......#.....+ ", +" +..#########.....+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" ++++++++++++++++ ", +" "}; + +char * gRestoreBoxInactive[] = { +"20 19 4 1", +" c None", +". c #8080FF", +"+ c #FFFFFF", +"# c #D0D0D0", +" ", +" ++++++++++++++++ ", +" +................+ ", +" +................+ ", +" +....#########...+ ", +" +....#########...+ ", +" +....#.......#...+ ", +" +..#########.#...+ ", +" +..#########.#...+ ", +" +..#.......#.#...+ ", +" +..#.......###...+ ", +" +..#.......#.....+ ", +" +..#.......#.....+ ", +" +..#########.....+ ", +" +................+ ", +" +................+ ", +" +................+ ", +" ++++++++++++++++ ", +" "}; + + + +Fl_Pixmap gMultiWinDocIcon(gMultiWinDoc_xpm); +Fl_Pixmap gCloseIcon(gCloseBox); +Fl_Pixmap gCloseIconSelected(gCloseBoxSelected); +Fl_Pixmap gCloseIconInactive(gCloseBoxInactive); +Fl_Pixmap gMinimizeIcon(gMinimizeBox); +Fl_Pixmap gMinimizeIconSelected(gMinimizeBoxSelected); +Fl_Pixmap gMinimizeIconInactive(gMinimizeBoxInactive); +Fl_Pixmap gMaximizeIcon(gMaximizeBox); +Fl_Pixmap gMaximizeIconSelected(gMaximizeBoxSelected); +Fl_Pixmap gMaximizeIconInactive(gMaximizeBoxInactive); +Fl_Pixmap gRestoreIcon(gRestoreBox); +Fl_Pixmap gRestoreIconSelected(gRestoreBoxSelected); +Fl_Pixmap gRestoreIconInactive(gRestoreBoxInactive); + diff --git a/src/multiwin_icons.h b/src/multiwin_icons.h new file mode 100644 index 0000000..e399c0c --- /dev/null +++ b/src/multiwin_icons.h @@ -0,0 +1,54 @@ +/* multiwin_icons.cpp */ + +/* $Id$ */ + +/* + * Copyright 2006 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef MULTIWIN_ICONS_H +#define MULTIIWN_ICONS_H + +#include +#include + +extern Fl_Pixmap gMultiWinDocIcon; +extern Fl_Pixmap gCloseIcon; +extern Fl_Pixmap gCloseIconSelected; +extern Fl_Pixmap gCloseIconInactive; +extern Fl_Pixmap gMinimizeIcon; +extern Fl_Pixmap gMinimizeIconSelected; +extern Fl_Pixmap gMinimizeIconInactive; +extern Fl_Pixmap gMaximizeIcon; +extern Fl_Pixmap gMaximizeIconSelected; +extern Fl_Pixmap gMaximizeIconInactive; +extern Fl_Pixmap gRestoreIcon; +extern Fl_Pixmap gRestoreIconSelected; +extern Fl_Pixmap gRestoreIconInactive; + +extern char * gMultiWinDoc_xpm[]; + +#endif + diff --git a/src/periph.cpp b/src/periph.cpp index 9b0d20f..75930b3 100644 --- a/src/periph.cpp +++ b/src/periph.cpp @@ -46,14 +46,16 @@ #include #include +#include "m100emu.h" #include "serial.h" #include "display.h" -#include "m100emu.h" #include "disassemble.h" #include "periph.h" #include "memedit.h" #include "cpuregs.h" +void cb_Ide(Fl_Widget* w, void*) ; + typedef struct periph_ctrl_struct { @@ -128,14 +130,11 @@ typedef struct periph_ctrl_struct Fl_Menu_Item gPeriph_menuitems[] = { { "&Tools", 0, 0, 0, FL_SUBMENU }, { "CPU Registers", 0, cb_CpuRegs }, - { "Assembler", 0, 0 }, + { "Assembler / IDE", 0, cb_Ide }, { "Disassembler", 0, disassembler_cb }, - { "Debugger", 0, 0 }, { "Memory Editor", 0, cb_MemoryEditor }, - { "Peripheral Devices", 0, 0 }, { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, 0 }, - { "BASIC Debugger", 0, 0 }, { 0 }, { 0 } diff --git a/src/rpn_eqn.cpp b/src/rpn_eqn.cpp new file mode 100644 index 0000000..75278ce --- /dev/null +++ b/src/rpn_eqn.cpp @@ -0,0 +1,50 @@ +#include "vtobj.h" +#include "MString.h" +#include "MStringArray.h" +#include "rpn_eqn.h" + +IMPLEMENT_DYNCREATE(CRpnEquation, VTObject); + +void CRpnEquation::ResetContent(void) +{ + for (int c = m_OperationArray.GetSize() - 1; c >= 0; c--) + { + delete (CRpnOperation*) m_OperationArray.GetAt(c); + } + m_OperationArray.RemoveAll(); +} + +void CRpnEquation::Add(int operation) +{ + CRpnOperation* op = new CRpnOperation; + + // Fill operation with operation code + op->m_Operation = operation; + + // Add operation to array + m_OperationArray.Add(op); +} + +void CRpnEquation::Add(double value) +{ + CRpnOperation* op = new CRpnOperation; + + // Fill operation with appropriate data + op->m_Operation = RPN_VALUE; + op->m_Value = value; + + // Add operation to array + m_OperationArray.Add(op); +} + +void CRpnEquation::Add(const char *var) +{ + CRpnOperation* op = new CRpnOperation; + + // Fill operation with appropriate data + op->m_Operation = RPN_VARIABLE; + op->m_Variable = var; + + // Add operation to array + m_OperationArray.Add(op); +} diff --git a/src/rpn_eqn.h b/src/rpn_eqn.h new file mode 100644 index 0000000..741f0bd --- /dev/null +++ b/src/rpn_eqn.h @@ -0,0 +1,68 @@ +// RpnEquation.h: This file defines the CRpnEquation class + +#include "MString.h" +#include "MStringArray.h" + + +// Define operation codes +const int RPN_VALUE = 1; +const int RPN_VARIABLE = 2; +const int RPN_MULTIPLY = 3; +const int RPN_DIVIDE = 4; +const int RPN_SUBTRACT = 5; +const int RPN_ADD = 6; +const int RPN_EXPONENT = 7; +const int RPN_MODULUS = 8; +const int RPN_FLOOR = 9; +const int RPN_CEIL = 10; +const int RPN_LN = 11; +const int RPN_LOG = 12; +const int RPN_BITAND = 13; +const int RPN_BITOR = 14; +const int RPN_BITXOR = 15; +const int RPN_LEFTSHIFT = 16; +const int RPN_RIGHTSHIFT = 17; +const int RPN_IP = 18; +const int RPN_FP = 20; +const int RPN_SQRT = 21; +const int RPN_LAST = 22; +const int RPN_NOT = 23; +const int RPN_BITNOT = 24; + +class CRpnOperation : public VTObject +{ +public: + CRpnOperation() { m_Value = 0.0; m_Operation = 0; }; + +// Attributes + int m_Operation; + MString m_Variable; // Used only for variable operations + double m_Value; +}; + +class CRpnOpArray : public VTObArray +{ +public: + CRpnOpArray() {}; + +// Attributes + CRpnOperation& operator [] (int index) { return *((CRpnOperation *) GetAt(index)); } +}; + +class CRpnEquation : public VTObject +{ + DECLARE_DYNCREATE(CRpnEquation); +public: + CRpnEquation() { m_EqPtr = 0; } + ~CRpnEquation() { ResetContent(); } + + + void ResetContent(void); + void Add(const char * var); + void Add(double value); + void Add(int operation); + +// Attributes + CRpnOpArray m_OperationArray; + int m_EqPtr; +}; diff --git a/src/serial.c b/src/serial.c index 970f909..1fb9781 100644 --- a/src/serial.c +++ b/src/serial.c @@ -29,18 +29,15 @@ #if defined(WIN32) #include -#else -#define TRUE (!0) -#define FALSE (0) #endif #include #include #include +#include "VirtualT.h" #include "serial.h" #include "setup.h" #include "display.h" -#include "gen_defs.h" ser_params_t sp; diff --git a/src/setup.cpp b/src/setup.cpp index 03b3be5..629c9ba 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -27,7 +27,6 @@ * SUCH DAMAGE. */ -#include #include #include @@ -110,8 +109,13 @@ typedef struct memory_ctrl_struct Fl_Button* pReMemBrowse; Fl_Button* pRampacBrowse; Fl_Box* pReMemText; + Fl_Check_Button* pOptRomRW; } memory_ctrl_t; +extern "C" { +extern int gOptRomRW; +} + Fl_Window *gpsw; // Peripheral Setup Window Fl_Window *gmsw; // Memory Setup Window @@ -529,6 +533,10 @@ void save_memory_preferences(void) strcpy(pref, str); strcat(pref, "_RampacFile"); virtualt_prefs.set(pref, mem_setup.rampac_file); + + strcpy(pref, str); + strcat(pref, "_OptRomRW"); + virtualt_prefs.set(pref, gOptRomRW); } void load_memory_preferences(void) @@ -561,6 +569,11 @@ void load_memory_preferences(void) virtualt_prefs.get(pref, mem_setup.rampac_file, path, 256); if (strlen(mem_setup.rampac_file) == 0) strcpy(mem_setup.rampac_file, path); + + // Load OptRom R/W or R/O option + strcpy(pref, str); + strcat(pref, "_OptRomRW"); + virtualt_prefs.get(pref, gOptRomRW, 0); } /* @@ -617,6 +630,9 @@ void cb_memory_OK(Fl_Widget* w, void*) else if (mem_ctrl.pReMem_Rampac->value() == 1) mem_setup.mem_mode = SETUP_MEM_REMEM_RAMPAC; + // Get OptRom R/W Enable setting + gOptRomRW = mem_ctrl.pOptRomRW->value(); + // Allocate ReMem and / or Rampac memory if not already init_mem(); @@ -847,7 +863,7 @@ Routine to create the PeripheralSetup Window and tabs void cb_MemorySetup (Fl_Widget* w, void*) { // Create Peripheral Setup window - gmsw = new Fl_Window(420, 260, "Memory Emulation Options"); + gmsw = new Fl_Window(420, 280, "Memory Emulation Options"); gmsw->callback(cb_memorywin); // Create items on the Tab @@ -908,14 +924,17 @@ void cb_MemorySetup (Fl_Widget* w, void*) mem_ctrl.pReMemText->hide(); } + // Option ROM RW Enable + mem_ctrl.pOptRomRW = new Fl_Check_Button(20, 200, 210, 20, "Make Option ROM R/W"); + mem_ctrl.pOptRomRW->value(gOptRomRW); + // OK button - { Fl_Button* o = new Fl_Button(160, 220, 60, 30, "Cancel"); + { Fl_Button* o = new Fl_Button(160, 240, 60, 30, "Cancel"); o->callback((Fl_Callback*)cb_memory_cancel); } - { Fl_Return_Button* o = new Fl_Return_Button(230, 220, 60, 30, "OK"); + { Fl_Return_Button* o = new Fl_Return_Button(230, 240, 60, 30, "OK"); o->callback((Fl_Callback*)cb_memory_OK); } gmsw->show(); } - diff --git a/src/sound.c b/src/sound.c index 6883d2d..ee0ad04 100644 --- a/src/sound.c +++ b/src/sound.c @@ -31,9 +31,9 @@ #include #include #include -#include #include #include +#include #ifdef _WIN32 #include @@ -353,7 +353,7 @@ void init_sound(void) gExit = 0; // Create sin table - gpOneHertz = malloc(m_SamplingRate * sizeof(unsigned short)); + gpOneHertz = (unsigned short *)malloc(m_SamplingRate * sizeof(unsigned short)); w = 2.0 * 3.14159 / (double) m_SamplingRate; for (x = 0; x < m_SamplingRate; x++) { diff --git a/src/vtobj.cpp b/src/vtobj.cpp new file mode 100644 index 0000000..a53ae25 --- /dev/null +++ b/src/vtobj.cpp @@ -0,0 +1,359 @@ +/* vtobj.cpp */ + +/* $Id$ */ + +/* + * Copyright 2004 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include "VirtualT.h" +#include "vtobj.h" + +const struct VTClass VTObject::classVTObject = + { "VTObject", sizeof(VTObject), 0, 0, 0}; + +VTClass* VTObject::GetClass() const +{ + return VT_CLASS(VTObject); +} + +VTObject* VTClass::CreateObject() +{ + if (m_pCreateObject == 0) + return 0; + + VTObject* pObject = (*m_pCreateObject)(); + + return pObject; +} + +VTObject::VTObject() +{ +} + +VTObject::~VTObject() +{ +} + +/* +======================================================================== +Implement the VTObArray class to handls object arrays +======================================================================== +*/ + +IMPLEMENT_DYNCREATE(VTObArray, VTObject) + +VTObArray::VTObArray() +{ + m_pData = 0; + m_Count = 0; + m_GrowBy = 16; + m_Size = 0; +} + +VTObArray::~VTObArray() +{ + if (m_pData != 0) + delete (char*) m_pData; + + m_pData = 0; +} + +int VTObArray::Add(VTObject *pObj) +{ + int index = m_Count; + + InsertAt(m_Count, pObj); + + return index; +} + +VTObject* VTObArray::GetAt(int nIndex) const +{ + VTObject* pObj; + + // Test if index out of bounds + if (nIndex > m_Count) + return 0; + + memcpy(&pObj, (char *) m_pData + nIndex * sizeof(VTObject *), sizeof(VTObject *)); + + return pObj; +} + +VTObject* VTObArray::operator [](int nIndex) const +{ + return GetAt(nIndex); +} + +void VTObArray::InsertAt(int nIndex, VTObject *newElement) +{ + int newCount = m_Count + 1; + char* pInsertLoc; + int c; + + // Test if array is big enough + if (newCount > m_Size) + SetSize(m_Size + m_GrowBy, 0); + + // Test if adding a end of array + if (nIndex == -1) + nIndex = m_Count; + + // Determine location for new entry + pInsertLoc = (char *) m_pData + (nIndex * sizeof(VTObject *)); + + // Make space for new entry in the array + for (c = m_Count - 1; c >= nIndex; c--) + memcpy((char *) m_pData + (c + 1) * sizeof(VTObject *), + (char *) m_pData + c * sizeof(VTObject *), sizeof(VTObject *)); + + // Add new entry to array + memcpy(pInsertLoc, &newElement, sizeof(VTObject *)); + + // Update Count + m_Count++; +} + +void VTObArray::RemoveAt(int nIndex, int nCount) +{ + char* pRemoveLoc; + int c; + + if (m_Count == 0) + return; + + // Check if removing from end of array + if (nIndex == -1) + nIndex = m_Count - 1; + + pRemoveLoc = (char *) m_pData + (nIndex * sizeof(VTObject *)); + + for (c = nIndex; c < m_Count; c++) + memcpy(pRemoveLoc + c * sizeof(VTObject *), pRemoveLoc + (c + 1) * sizeof(VTObject *), + sizeof(VTObject *)); + + // Drecrement count + m_Count--; +} + +void VTObArray::SetSize(int nNewSize, int nGrowBy) +{ + void* pNew; + + // Check if GrowBy value needs to be updated + if (nGrowBy != 0) + m_GrowBy = nGrowBy; + + // Check if new size is same as old size + if (nNewSize == m_Size) + return; + + pNew = (void *) malloc(nNewSize * sizeof(VTObject*)); + memcpy(pNew, m_pData, m_Count * sizeof(VTObject*)); + + // Delete old data + delete (char *)m_pData; + + // Assign new data + m_pData = pNew; + m_Size = nNewSize; +} + +IMPLEMENT_DYNCREATE(VTMapStringToOb, VTObject) + +VTMapStringToOb::VTMapStringToOb() +{ + int c; + + for (c = 0; c < 256; c++) + m_HashPtrs[c] = 0; + m_Count = 0; + m_Null = (VTObject *) 0; +} + +VTMapStringToOb::~VTMapStringToOb() +{ + RemoveAll(); +} + +unsigned char VTMapStringToOb::HashKey(const char *key) +{ + int c; + unsigned char hash[2]; + unsigned short *sHash; + + sHash = (unsigned short *) hash; + *sHash = 0; + for (c = 0; key[c] != 0; c++) + { + *sHash = (*sHash << 3) + key[c] + 0x26; + hash[0] -= hash[1] ^ 0x6A; + } + + return hash[0]; +} + +int VTMapStringToOb::Lookup(const char *key, VTObject *&rValue) +{ + POSITION iter; + unsigned char hash; + + // Calculate hash and get pointer to first entry in hash array + hash = HashKey(key); + iter = m_HashPtrs[hash]; + + // Iterate through all items which have this hash + while (iter != 0) + { + if (strcmp(iter->pKey, key) == 0) + { + rValue = iter->pObj; + return 1; + } + + iter = iter->pNext; + } + + return 0; +} + +VTObject*& VTMapStringToOb::operator[](const char *key) +{ + POSITION iter; + unsigned char hash; + + // Calculate hash and get pointer to first entry in hash array + hash = HashKey(key); + iter = m_HashPtrs[hash]; + + // Iterate through all items which have this hash + while (iter != 0) + { + if (strcmp(iter->pKey, key) == 0) + { + return iter->pObj; + } + + iter = iter->pNext; + } + + // Create new entry for this key + iter = new StrToObStruct; + iter->pKey = (char *) malloc(strlen(key) + 1); + strcpy(iter->pKey, key); + iter->hash = hash; + + // Insert new entry into hash + if (m_HashPtrs[hash] != 0) + iter->pNext = m_HashPtrs[hash]; + else + iter->pNext= 0; + m_HashPtrs[hash] = iter; + m_Count++; + + return iter->pObj; +} + +void VTMapStringToOb::GetNextAssoc(POSITION& rNextPosition, MString& rKey, VTObject*& rValue) const +{ + unsigned char hash; + + // First check if iterator is NULL - end of list + if (rNextPosition == (POSITION ) 0) + return; + + // Get Entry for this position + rKey = rNextPosition->pKey; + rValue = rNextPosition->pObj; + + // Now update the iterator + if (rNextPosition->pNext != 0) + { + rNextPosition = rNextPosition->pNext; + return; + } + + hash = rNextPosition->hash; + if (hash == 255) + rNextPosition = (POSITION) 0; + else + { + // Find next pointer in hash table + hash++; + while ((m_HashPtrs[hash] == 0) && (hash != 255)) + hash++; + + // Check if an entry was found or if we are at the end of the table + if (m_HashPtrs[hash] == 0) + rNextPosition = (POSITION) 0; + else + rNextPosition = m_HashPtrs[hash]; + } +} + +POSITION VTMapStringToOb::GetStartPosition(void) +{ + unsigned char hash; + + // Start at beginning of hash table + hash = 0; + + // Find first pointer in hash table + while ((m_HashPtrs[hash] == 0) && (hash != 255)) + hash++; + + // Check if an entry was found or if we are at the end of the table + if (m_HashPtrs[hash] == 0) + return (POSITION) 0; + else + return m_HashPtrs[hash]; + +} + +void VTMapStringToOb::RemoveAll(void) +{ + POSITION iter, next; + int hash; + + // Start at beginning of hash table + for (hash = 0; hash < 256; hash++) + { + // Get pointer to first item for this index + iter = m_HashPtrs[hash]; + while (iter != 0) + { + free(iter->pKey); + next = iter->pNext; + delete iter; + + iter = next; + } + + m_HashPtrs[hash] = 0; + } +} + diff --git a/src/vtobj.h b/src/vtobj.h new file mode 100644 index 0000000..af78f90 --- /dev/null +++ b/src/vtobj.h @@ -0,0 +1,184 @@ +/* vtobj.h */ + +/* $Id$ */ + +/* + * Copyright 2006 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef VTOBJ_H +#define VTOBJ_H + +#include +#include "MString.h" + +class VTObject; + +struct VTClass +{ + const char *m_ClassName; + int m_ObjectSize; + VTObject* (*m_pCreateObject)(); + VTClass *m_pBaseClass; + + VTObject* CreateObject(); + int IsDerivedFrom(const VTClass* pBaseClass) const; + VTClass *m_pNextClass; +}; + + +#define VT_CLASS(ClassName) ((VTClass*)(&ClassName::class##ClassName)) + +// not serializable, but dynamically constructable +#define DECLARE_DYNCREATE(ClassName) \ +public: \ + static const VTClass class##ClassName; \ + virtual VTClass* GetClass() const; \ + static VTObject* CreateObject(); + +#define IMPLEMENT_DYNCREATE(ClassName, BaseClassName) \ + VTObject* ClassName::CreateObject() \ + { return new ClassName; } \ + const VTClass ClassName::class##ClassName = { \ + #ClassName, sizeof(class ClassName), ClassName::CreateObject, \ + VT_CLASS(BaseClassName), 0 }; \ + VTClass* ClassName::GetClass() const \ + { return VT_CLASS(ClassName); } + + +class VTObject +{ +protected: + VTObject(); + +private: + VTObject (const VTObject& objectSrc); // no implementation + void operator=(const VTObject& objectSrc); // no implementation + +public: + virtual ~VTObject(void); + virtual VTClass *GetClass()const; + static const VTClass classVTObject; + +}; + + +class VTObArray : public VTObject +{ + DECLARE_DYNCREATE(VTObArray) + + +public: + VTObArray(); + ~VTObArray(); + void SetSize(int nNewSize, int nGrowBy = 0); + void InsertAt(int nIndex, VTObject* newElement); + void RemoveAt(int nIndex, int nCount); + int Add(VTObject* pObj); + VTObject* GetAt(int nIndex) const; + int GetSize() { return m_Count; }; + void RemoveAll() { m_Count = 0; }; + + // overloaded operator helpers + VTObject* operator[](int nIndex) const; + +protected: + int m_GrowBy; + int m_Size; + int m_Count; + void * m_pData; +}; + + +//typedef std::map STR_TO_OB_MAP; +//typedef std::map::iterator POSITION; + +typedef struct _StrToObStruct { + char * pKey; + VTObject* pObj; + struct _StrToObStruct* pNext; + unsigned char hash; +} StrToObStruct; + +typedef StrToObStruct* POSITION; + +class VTMapStringToOb : public VTObject +{ + + DECLARE_DYNCREATE(VTMapStringToOb) + +protected: + StrToObStruct* m_HashPtrs[256]; + int m_Count; + + VTObject* m_Null; + + unsigned char HashKey(const char *key); + +public: + VTMapStringToOb(); + ~VTMapStringToOb(); + int Lookup(const char *key, VTObject*& rValue); + VTObject*& operator[](const char *key); + void RemoveAll(); + int Size() { return m_Count; }; + void GetNextAssoc(POSITION& rNextPosition, + MString& rKey, VTObject*& rValue) const; + POSITION GetStartPosition(void); +}; + +class VT_Rect { +public: + VT_Rect() { m_X = 0; m_Y = 0; m_W = 0; m_H = 0; }; + VT_Rect(int x, int y, int w, int h) + { m_X = x; m_Y = y; m_W = w; m_H = h; }; + + const VT_Rect& operator=(const VT_Rect& srcRect) + { if (this == &srcRect) return *this; m_X = srcRect.m_X; + m_Y = srcRect.m_Y; m_W = srcRect.m_W; m_H = srcRect.m_H; + return *this; }; + int x() { return m_X; }; + int y() { return m_Y; }; + int w() { return m_W; }; + int h() { return m_H; }; + + void x(int x) { m_X = x; }; + void y(int y) { m_Y = y; }; + void w(int w) { m_W = w; }; + void h(int h) { m_H = h; }; + + int x1() { return m_X + m_W; }; + int y1() { return m_Y + m_H; }; + +private: + int m_X; + int m_Y; + int m_W; + int m_H; + +}; + +#endif + From 73da08720b712244ec59528e561ef94359a4a611 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 26 Jan 2008 14:38:04 +0000 Subject: [PATCH 050/327] Checkin for version 1.0. Many, many changes. --- src/serial.c | 768 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 483 insertions(+), 285 deletions(-) diff --git a/src/serial.c b/src/serial.c index 1fb9781..189a2a4 100644 --- a/src/serial.c +++ b/src/serial.c @@ -4,6 +4,7 @@ /* * Copyright 2004 Stephen Hurd and Ken Pettit + * POSIX code Copyright 2008 John R. Hogerhuis * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,8 +29,23 @@ */ #if defined(WIN32) + #include + +#else + + +#include /* UNIX standard function definitions */ +#include +#include +#include +#include +#include +#include +#include /* Error number definitions */ + #endif + #include #include #include @@ -41,6 +57,24 @@ ser_params_t sp; +#ifndef WIN32 +/* +=========================================================================== +ser_tx_remaining: Get # bytes remaining to transmit + +=========================================================================== +*/ +unsigned ser_tx_remaining () +{ + + int bytes; + ioctl (sp.fd, TIOCOUTQ, &bytes); + return (unsigned) bytes; +} + +#endif + + /* =========================================================================== ser_init: Initialize serial structures @@ -48,6 +82,7 @@ ser_init: Initialize serial structures */ int ser_init(void) { + // Initialize port name if (setup.com_mode == SETUP_COM_HOST) strcpy(sp.port_name, setup.com_port); @@ -57,20 +92,21 @@ int ser_init(void) strcpy(sp.port_name, setup.com_cmd); sp.baud_rate = 9600; // Default to 9600 baud rate - sp.open_flag = 0; // Port not open - sp.bit_size = 8; // Default to 8 bits - sp.parity = 'N'; // Initialize to no parity + sp.open_flag = 0; // Port not open + sp.bit_size = 8; // Default to 8 bits + sp.parity = 'N'; // Initialize to no parity sp.pCallback = NULL; // No callback funciton sp.pMonCallback = NULL; // No monitor callback function - sp.stop_bits = 1; // Initialize to 1 stop bit - sp.pCmdFile = NULL; // No open command file - sp.tx_empty = TRUE; // Indicate no active TX - sp.rxIn = 0; // Initialize Read buffer + sp.stop_bits = 1; // Initialize to 1 stop bit + sp.pCmdFile = NULL; // No open command file + +#ifdef WIN32 + sp.tx_empty = TRUE; // Indicate no active TX + sp.rxIn = 0; // Initialize Read buffer sp.rxOut = 0; - sp.txIn = 0; // Initialize TX buffer + sp.txIn = 0; // Initialize TX buffer sp.txOut = 0; -#ifdef WIN32 // Create overlapped read event. Must be closed before exiting // to avoid a handle leak. sp.osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); @@ -104,19 +140,21 @@ int ser_init(void) sp.dtrState = DTR_CONTROL_DISABLE; sp.rtsState = RTS_CONTROL_DISABLE; - // If Serial port emulation, open the port - if (setup.com_mode != SETUP_COM_NONE) - ser_open_port(); - #else - // ============================================ - // Add code here for POSIX initialization - // ============================================ - + // JRH -- I don't think any init is required. + // the line parameters will get set piecemeal as the emu + // calls in. The overlapped I/O stuff appearing in the + // windows emulation is unnecessary since the emulation + // is poll driven anyway. #endif + // If Serial port emulation, open the port + if (setup.com_mode != SETUP_COM_NONE) + ser_open_port(); + + return SER_NO_ERROR; } @@ -152,9 +190,7 @@ int ser_deinit(void) CloseHandle(sp.hComm); #else - // =============================================== - // Add code here to deinitialize for POSIX systems - // =============================================== + ser_close_port(); #endif @@ -165,10 +201,10 @@ int ser_deinit(void) =========================================================================== ser_get_port_list: Get a list of valid COM port names and count. - This function returns a comma seperated list of serial - port names valid for the host. This list will be - displayed in the Peripheral Setup dialog to allow the - user to select where emulation should be directed. + This function returns a comma seperated list of serial + port names valid for the host. This list will be + displayed in the Peripheral Setup dialog to allow the + user to select where emulation should be directed. =========================================================================== */ int ser_get_port_list(char* port_list, int max, int *count) @@ -233,6 +269,8 @@ int ser_get_port_list(char* port_list, int max, int *count) // Add code here to get port list for POSIX // ============================================ + strcat (port_list, "/dev/ttyUSB0"); //$$ FIXME + #endif return SER_NO_ERROR; @@ -358,64 +396,64 @@ ReadProc: Thread to read data from COM port */ DWORD ReadProc(LPVOID lpv) { - HANDLE hArray[3]; + HANDLE hArray[3]; OVERLAPPED osStatus; - DWORD dwStoredFlags = 0xFFFFFFFF; // local copy of event flags + DWORD dwStoredFlags = 0xFFFFFFFF; // local copy of event flags DWORD dwFlags = EV_CTS | EV_DSR; - DWORD dwRead; // bytes actually read - DWORD dwRes; // result from WaitForSingleObject + DWORD dwRead; // bytes actually read + DWORD dwRes; // result from WaitForSingleObject DWORD dwOvRes; DWORD dwCommEvent; COMSTAT comStat; DWORD dwError; - BOOL fWaitingOnStat = FALSE; - BOOL fThreadDone = FALSE; + BOOL fWaitingOnStat = FALSE; + BOOL fThreadDone = FALSE; char buf[128]; ser_params_t *sp; - sp = (ser_params_t *) lpv; + sp = (ser_params_t *) lpv; osStatus.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); ResetEvent(sp->osRead.hEvent); ResetEvent(sp->osWrite.hEvent); - // Detect the following events: - // Read events (from ReadFile) - // Thread exit evetns (from our shutdown functions) - hArray[0] = sp->osRead.hEvent; - hArray[1] = sp->hThreadExitEvent; + // Detect the following events: + // Read events (from ReadFile) + // Thread exit evetns (from our shutdown functions) + hArray[0] = sp->osRead.hEvent; + hArray[1] = sp->hThreadExitEvent; hArray[2] = osStatus.hEvent; - while ( !fThreadDone ) + while ( !fThreadDone ) { - // if no read is outstanding, then issue another one - if (!fWaitingOnRead) + // if no read is outstanding, then issue another one + if (!fWaitingOnRead) { - if (!ReadFile(sp->hComm, buf, 1, &dwRead, &sp->osRead)) + if (!ReadFile(sp->hComm, buf, 1, &dwRead, &sp->osRead)) { - if (GetLastError() != ERROR_IO_PENDING) // read not delayed? - ErrorReporter("ReadFile in ReaderAndStatusProc"); + if (GetLastError() != ERROR_IO_PENDING) // read not delayed? + ErrorReporter("ReadFile in ReaderAndStatusProc"); - fWaitingOnRead = TRUE; - } - else + fWaitingOnRead = TRUE; + } + else { // read completed immediately - if (dwRead) + if (dwRead) { process_read_byte(sp, buf[0]); } - } - } + } + } - if (dwStoredFlags != dwFlags) + if (dwStoredFlags != dwFlags) { - dwStoredFlags = dwFlags; - if (!SetCommMask(sp->hComm, dwStoredFlags)) - ErrorReporter("SetCommMask"); - } + dwStoredFlags = dwFlags; + if (!SetCommMask(sp->hComm, dwStoredFlags)) + ErrorReporter("SetCommMask"); + } if (!fWaitingOnStat) { if (!WaitCommEvent(sp->hComm, &dwCommEvent, &osStatus)) @@ -436,45 +474,45 @@ DWORD ReadProc(LPVOID lpv) } - // wait for pending operations to complete - if ( fWaitingOnRead || fWaitingOnStat ) -// if ( fWaitingOnRead) + // wait for pending operations to complete + if ( fWaitingOnRead || fWaitingOnStat ) + // if ( fWaitingOnRead) { - dwRes = WaitForMultipleObjects(3, hArray, FALSE, INFINITE); - switch(dwRes) - { - // read completed - case WAIT_OBJECT_0: - if (!GetOverlappedResult(sp->hComm, &sp->osRead, &dwRead, FALSE)) + dwRes = WaitForMultipleObjects(3, hArray, FALSE, INFINITE); + switch(dwRes) + { + // read completed + case WAIT_OBJECT_0: + if (!GetOverlappedResult(sp->hComm, &sp->osRead, &dwRead, FALSE)) { ClearCommError(sp->hComm, &dwError, &comStat); - ErrorReporter("GetOverlappedResult (in Reader)"); + ErrorReporter("GetOverlappedResult (in Reader)"); dwError = GetLastError(); } - else + else { // read completed successfully - if (dwRead) + if (dwRead) { if (fWaitingOnRead) process_read_byte(sp, buf[0]); } fWaitingOnRead = FALSE; - } + } - break; + break; case WAIT_TIMEOUT: break; - // thread exit event - case WAIT_OBJECT_0 + 1: - fThreadDone = TRUE; - break; + // thread exit event + case WAIT_OBJECT_0 + 1: + fThreadDone = TRUE; + break; case WAIT_OBJECT_0 + 2: if (!GetOverlappedResult(sp->hComm, &osStatus, &dwOvRes, FALSE)) - ErrorReporter("GetOverlappedResult Error (status read)"); + ErrorReporter("GetOverlappedResult Error (status read)"); else // Check for a monitor window and report change if (sp->pMonCallback != NULL) @@ -485,15 +523,15 @@ DWORD ReadProc(LPVOID lpv) fWaitingOnStat = FALSE; break; - default: - ErrorReporter("WaitForMultipleObjects(Reader & Status handles)"); - break; - } - } - } + default: + ErrorReporter("WaitForMultipleObjects(Reader & Status handles)"); + break; + } + } + } sp->fReadThread = FALSE; - return 1; + return 1; } /* @@ -503,35 +541,35 @@ WriteProc: Thread to write data to COM port */ DWORD WINAPI WriteProc(LPVOID lpv) { - HANDLE hArray[2]; + HANDLE hArray[2]; HANDLE hwArray[2]; - DWORD dwRes; + DWORD dwRes; DWORD dwWritten; - BOOL fDone = FALSE; + BOOL fDone = FALSE; ser_params_t *sp; sp = (ser_params_t*) lpv; - hArray[0] = sp->hWriteEvent; - hArray[1] = sp->hThreadExitEvent; + hArray[0] = sp->hWriteEvent; + hArray[1] = sp->hThreadExitEvent; - hwArray[0] = sp->osWrite.hEvent; + hwArray[0] = sp->osWrite.hEvent; hwArray[1] = sp->hThreadExitEvent; - - while ( !fDone ) { - dwRes = WaitForMultipleObjects(2, hArray, FALSE, INFINITE); - switch(dwRes) - { - case WAIT_FAILED: - ErrorReporter("WaitForMultipleObjects( writer proc )"); - break; - - // write request event - case WAIT_OBJECT_0: + + while ( !fDone ) { + dwRes = WaitForMultipleObjects(2, hArray, FALSE, INFINITE); + switch(dwRes) + { + case WAIT_FAILED: + ErrorReporter("WaitForMultipleObjects( writer proc )"); + break; + + // write request event + case WAIT_OBJECT_0: // Read bytes from sp structure -// WaitForSingleObject(sp->hWriteMutex, 2000); + // WaitForSingleObject(sp->hWriteMutex, 2000); -// ReleaseMutex(sp->hWriteMutex); + // ReleaseMutex(sp->hWriteMutex); // issue write if (!WriteFile(sp->hComm, sp->tx_buf, 1, &dwWritten, &sp->osWrite)) { @@ -547,14 +585,14 @@ DWORD WINAPI WriteProc(LPVOID lpv) if (!GetOverlappedResult(sp->hComm, &sp->osWrite, &dwWritten, FALSE)) { ErrorReporter("GetOverlappedResult(in Writer)"); } - + break; - // thread exit event set + // thread exit event set case WAIT_OBJECT_0 + 1: break; - // wait timed out + // wait timed out case WAIT_TIMEOUT: break; } @@ -562,18 +600,18 @@ DWORD WINAPI WriteProc(LPVOID lpv) sp->tx_empty = TRUE; } } - - break; - // thread exit event - case WAIT_OBJECT_0 + 1: - fDone = TRUE; - break; - } - } + break; + + // thread exit event + case WAIT_OBJECT_0 + 1: + fDone = TRUE; + break; + } + } sp->fWriteThread = FALSE; - return 1; + return 1; } @@ -584,30 +622,30 @@ start_threads:: Creates the Reader/Status and Writer threads */ int start_threads(void) { - DWORD dwReadStatId; - DWORD dwWriterId; + DWORD dwReadStatId; + DWORD dwWriterId; // Create read thread - sp.hReadThread = CreateThread( NULL, 0, - (LPTHREAD_START_ROUTINE) ReadProc, - (LPVOID) &sp, 0, &dwReadStatId); + sp.hReadThread = CreateThread( NULL, 0, + (LPTHREAD_START_ROUTINE) ReadProc, + (LPVOID) &sp, 0, &dwReadStatId); - if (sp.hReadThread == NULL) - return SER_IO_ERROR; + if (sp.hReadThread == NULL) + return SER_IO_ERROR; sp.fReadThread = TRUE; // Create write thread - sp.hWriteThread = CreateThread( NULL, 0, - (LPTHREAD_START_ROUTINE) WriteProc, - (LPVOID) &sp, 0, &dwWriterId ); - - if (sp.hWriteThread == NULL) - return SER_IO_ERROR; + sp.hWriteThread = CreateThread( NULL, 0, + (LPTHREAD_START_ROUTINE) WriteProc, + (LPVOID) &sp, 0, &dwWriterId ); + + if (sp.hWriteThread == NULL) + return SER_IO_ERROR; sp.fWriteThread = TRUE; - return SER_NO_ERROR; + return SER_NO_ERROR; } #endif @@ -617,11 +655,12 @@ int start_threads(void) =========================================================================== ser_set_baud: Set the baud rate to the numeric value passed. - The value will be in the range of 75 to 19200 + The value will be in the range of 75 to 19200 =========================================================================== */ int ser_set_baud(int baud) { + // Update baud rate sp.baud_rate = baud; @@ -644,9 +683,31 @@ int ser_set_baud(int baud) } #else - // ========================================== - // Add code here for POSIX to set baud rate - // ========================================== + { struct termios options; + unsigned baud_flag; + + switch (sp.baud_rate) { + case 75 : baud_flag = B75 ; break; + case 110 : baud_flag = B110 ; break; + case 150 : baud_flag = B150 ; break; + case 200 : baud_flag = B200 ; break; + case 300 : baud_flag = B300 ; break; + case 600 : baud_flag = B600 ; break; + case 1200 : baud_flag = B1200 ; break; + case 1800 : baud_flag = B1800 ; break; + case 2400 : baud_flag = B2400 ; break; + case 4800 : baud_flag = B4800 ; break; + case 9600 : baud_flag = B9600 ; break; + case 19200: baud_flag = B19200; break; + default: return SER_IO_ERROR; + } + + tcgetattr(sp.fd, &options); + cfsetispeed (&options, baud_flag); + cfsetospeed (&options, baud_flag); + options.c_cflag |= (CLOCAL | CREAD); + tcsetattr(sp.fd, TCSANOW, &options); + } #endif } @@ -665,6 +726,7 @@ ser_close_port: Close the opened serial port */ int ser_close_port(void) { + // Test if port is open if (sp.open_flag == 0) return SER_PORT_NOT_OPEN; @@ -688,9 +750,9 @@ int ser_close_port(void) sp.hComm = NULL; #else - // ============================================ - // Add code here for POSIX to close port - // ============================================ + int my_fd = sp.fd; + sp.fd = 0; + close (sp.fd); #endif } @@ -723,84 +785,99 @@ ser_open_port: Open the serial port specified by ser_set_port */ int ser_open_port(void) { + // Test if port is already opened if (sp.open_flag == 1) ser_close_port(); // Check if using HOST port emulation if ((setup.com_mode == SETUP_COM_HOST) || - (setup.com_mode == SETUP_COM_OTHER)) + (setup.com_mode == SETUP_COM_OTHER)) { // ============= // Open the port // ============= - #ifdef WIN32 - char msg[50]; +#ifdef WIN32 + char msg[50]; + + // Attempt to open the port specified by sp.port_name + sp.hComm = CreateFile( sp.port_name, + GENERIC_READ | GENERIC_WRITE, + 0, + 0, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + //FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + 0); + // Check for error opening port + if (sp.hComm == INVALID_HANDLE_VALUE) + { + sprintf(msg, "Error opening port %s", sp.port_name); + show_error(msg); + return SER_IO_ERROR; + } +#else - // Attempt to open the port specified by sp.port_name - sp.hComm = CreateFile( sp.port_name, - GENERIC_READ | GENERIC_WRITE, - 0, - 0, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - //FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, - 0); - // Check for error opening port - if (sp.hComm == INVALID_HANDLE_VALUE) - { - sprintf(msg, "Error opening port %s", sp.port_name); - show_error(msg); - return SER_IO_ERROR; - } - #else - - // ============================================ - // Add code here for POSIX to open the port - // ============================================ + // open the port + sp.fd = open (sp.port_name, O_RDWR | O_NOCTTY | O_NDELAY); + if (sp.fd == -1) return SER_IO_ERROR; - #endif + // configure for non-blocking reads + fcntl(sp.fd, F_SETFL, FNDELAY); + + { struct termios options; + + tcgetattr(sp.fd, &options); + + // turn off any line editing (raw mode) + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + + // disable automatic flow control + options.c_iflag &= ~(IXON | IXOFF | IXANY); + options.c_cflag &= ~CRTSCTS; + + tcsetattr(sp.fd, TCSANOW, &options); + } + +#endif // ========================================== // Configure port's baud rate, bit_size, etc. // ========================================== - #ifdef WIN32 - FillMemory(&sp.dcb, sizeof(sp.dcb), 0); - sp.dcb.DCBlength = sizeof(DCB); - if (!GetCommState(sp.hComm, &sp.dcb)) - { - DWORD err = GetLastError(); - - sprintf(msg,"I/O Error on %s", sp.port_name); - show_error(msg); - // Error reading port state - return SER_IO_ERROR; - } +#ifdef WIN32 - // Initialize the DCB to set baud rate, etc. - initialize_dcb(); + FillMemory(&sp.dcb, sizeof(sp.dcb), 0); + sp.dcb.DCBlength = sizeof(DCB); + if (!GetCommState(sp.hComm, &sp.dcb)) + { + DWORD err = GetLastError(); - // Update DCB settings - if (!SetCommState(sp.hComm, &sp.dcb)) - { - // Error updating port settings - CloseHandle(sp.hComm); - sp.hComm = 0; - return SER_IO_ERROR; - } + sprintf(msg,"I/O Error on %s", sp.port_name); + show_error(msg); + // Error reading port state + return SER_IO_ERROR; + } - // Start Read an Write Threads - start_threads(); + // Initialize the DCB to set baud rate, etc. + initialize_dcb(); - // Update flag indicating port open - sp.open_flag = TRUE; - #else + // Update DCB settings + if (!SetCommState(sp.hComm, &sp.dcb)) + { + // Error updating port settings + CloseHandle(sp.hComm); + sp.hComm = 0; + return SER_IO_ERROR; + } - // ============================================ - // Add code here for POSIX to configure port - // ============================================ + // Start Read an Write Threads + start_threads(); - #endif + // Update flag indicating port open + sp.open_flag = TRUE; +#else + sp.open_flag = TRUE; +#endif } else if (setup.com_mode == SETUP_COM_SIMULATED) { @@ -824,16 +901,17 @@ int ser_open_port(void) =========================================================================== ser_set_port: Set the active serial port for subsequent calls - Port is an OS specific string indicating the name of the - host serial port where all traffic will be directed. + Port is an OS specific string indicating the name of the + host serial port where all traffic will be directed. =========================================================================== */ int ser_set_port(char* port) { + // Save name of port for later use strcpy(sp.port_name, port); - // Check for a monitor window and report change + // Check for a monitor window and report change if (sp.pMonCallback != NULL) sp.pMonCallback(SER_MON_COM_PORT_CHANGE, SER_MON_COM_CHANGE_NAME); @@ -849,6 +927,7 @@ ser_get_port_settings: Provides current port emulation settings for int ser_get_port_settings(char* port, int* open_state, int* baud, int* size, int* stop_bits, char* parity) { + // Save name of port for later use strcpy(port, sp.port_name); *open_state = sp.open_flag; @@ -864,11 +943,12 @@ int ser_get_port_settings(char* port, int* open_state, int* baud, int* size, =========================================================================== ser_set_parity: Set parity for the emulated port - Valid values for parity are 'O', 'E', 'N', or 'I' + Valid values for parity are 'O', 'E', 'N', or 'I' =========================================================================== */ int ser_set_parity(char parity) { + // Check if parity changed if (parity == sp.parity) return SER_NO_ERROR; @@ -881,25 +961,43 @@ int ser_set_parity(char parity) return SER_NO_ERROR; if ((setup.com_mode == SETUP_COM_HOST) || - (setup.com_mode == SETUP_COM_OTHER)) + (setup.com_mode == SETUP_COM_OTHER)) { - #ifdef WIN32 - // Update DCB settings - initialize_dcb(); + #ifdef WIN32 + // Update DCB settings + initialize_dcb(); - // Update Port settings with new DCB - if (!SetCommState(sp.hComm, &sp.dcb)) - { - // Error updating port settings - return SER_IO_ERROR; + // Update Port settings with new DCB + if (!SetCommState(sp.hComm, &sp.dcb)) + { + // Error updating port settings + return SER_IO_ERROR; + } + #else + + { struct termios options; + + // enable or disable parity altogether + tcgetattr(sp.fd, &options); + if (sp.parity == 'O' || sp.parity == 'E') { + options.c_cflag |= PARENB; + options.c_iflag |= (INPCK | ISTRIP); + } else { + options.c_cflag &= ~PARENB; + } + + // set the type of parity + if (sp.parity == 'O') { + options.c_cflag |= PARODD; + } else { + options.c_cflag &= ~PARODD; } - #else - // ============================================ - // Add code here for POSIX to set parity - // ============================================ + tcsetattr(sp.fd, TCSANOW, &options); - #endif + } + + #endif } // Check for a monitor window and report change @@ -913,11 +1011,12 @@ int ser_set_parity(char parity) =========================================================================== ser_set_bit_size: Set the serial port's bit size - Valid values for bit_size are 6, 7, or 8 + Valid values for bit_size are 6, 7, or 8 =========================================================================== */ int ser_set_bit_size(int bit_size) { + // Check if bit size changed if (bit_size == sp.bit_size) return SER_NO_ERROR; @@ -943,10 +1042,24 @@ int ser_set_bit_size(int bit_size) return SER_IO_ERROR; } #else + { struct termios options; + unsigned flag; + + // map requested # bits to options flag + switch (bit_size) { + case 5: flag = CS5; break; + case 6: flag = CS6; break; + case 7: flag = CS7; break; + case 8: flag = CS8; break; + default: return SER_IO_ERROR; + } - // ============================================ - // Add code here for POSIX to set #bits - // ============================================ + tcgetattr(sp.fd, &options); + options.c_cflag &= ~CSIZE; + options.c_cflag |= flag; + + tcsetattr(sp.fd, TCSANOW, &options); + } #endif } @@ -962,11 +1075,12 @@ int ser_set_bit_size(int bit_size) =========================================================================== ser_set_stop_bits: Set the serial port's stop bits - Valid values for stop_bits are 1 or 2 + Valid values for stop_bits are 1 or 2 =========================================================================== */ int ser_set_stop_bits(int stop_bits) { + // Check if stop bits changed if (stop_bits == sp.stop_bits) return SER_NO_ERROR; @@ -993,9 +1107,18 @@ int ser_set_stop_bits(int stop_bits) } #else - // ============================================ - // Add code here for POSIX to set #stop bits - // ============================================ + { struct termios options; + + tcgetattr(sp.fd, &options); + + switch (sp.stop_bits) { + case 1: options.c_cflag &= ~CSTOPB; break; + case 2: options.c_cflag |= CSTOPB; break; + default: return SER_IO_ERROR; + } + + tcsetattr(sp.fd, TCSANOW, &options); + } #endif } @@ -1009,11 +1132,12 @@ int ser_set_stop_bits(int stop_bits) /* =========================================================================== -ser_set_callback: Set the callback routine for processing incomming data. +ser_set_callback: Set the callback routine for processing incoming data. =========================================================================== */ int ser_set_callback(ser_callback pCallback) { + // Save callback address sp.pCallback = pCallback; @@ -1022,12 +1146,13 @@ int ser_set_callback(ser_callback pCallback) /* =========================================================================== -ser_set_monitor_callback: Set the callback routine for reporting traffic - to a monitor window. +ser_set_monitor_callback: Set the callback routine for reporting traffic + to a monitor window. =========================================================================== */ int ser_set_monitor_callback(ser_monitor_cb pCallback) { + // Save callback address sp.pMonCallback = pCallback; @@ -1042,51 +1167,69 @@ ser_set_flags: Set the serial port's RTS and DTR flags */ int ser_set_signals(unsigned char flags) { + if ((setup.com_mode == SETUP_COM_HOST) || - (setup.com_mode == SETUP_COM_OTHER)) + (setup.com_mode == SETUP_COM_OTHER)) { - #ifdef WIN32 - // Update DTR flag - if (flags & SER_SIGNAL_DTR) - { - sp.dtrState = DTR_CONTROL_ENABLE; - EscapeCommFunction(sp.hComm, SETDTR); - } - else - { - sp.dtrState = DTR_CONTROL_DISABLE; - EscapeCommFunction(sp.hComm, CLRDTR); - } + #ifdef WIN32 + // Update DTR flag + if (flags & SER_SIGNAL_DTR) + { + sp.dtrState = DTR_CONTROL_ENABLE; + EscapeCommFunction(sp.hComm, SETDTR); + } + else + { + sp.dtrState = DTR_CONTROL_DISABLE; + EscapeCommFunction(sp.hComm, CLRDTR); + } - // Update RTS flag - if (flags & SER_SIGNAL_RTS) - { - sp.rtsState = RTS_CONTROL_ENABLE; - EscapeCommFunction(sp.hComm, SETRTS); - } - else - { - sp.rtsState = RTS_CONTROL_DISABLE; - EscapeCommFunction(sp.hComm, CLRRTS); - } + // Update RTS flag + if (flags & SER_SIGNAL_RTS) + { + sp.rtsState = RTS_CONTROL_ENABLE; + EscapeCommFunction(sp.hComm, SETRTS); + } + else + { + sp.rtsState = RTS_CONTROL_DISABLE; + EscapeCommFunction(sp.hComm, CLRRTS); + } - #else + #else - // ============================================ - // Add code here for POSIX to set DTR/RTS - // ============================================ + { int status; + + ioctl(sp.fd, TIOCMGET, &status); + + if (flags & SER_SIGNAL_DTR) { + status |= TIOCM_DTR; + } else { + status &= ~TIOCM_DTR; + } + + if (flags & SER_SIGNAL_RTS) { + status |= TIOCM_RTS; + } else { + status &= ~TIOCM_RTS; + } + + ioctl(sp.fd, TIOCMSET, &status); + } + + #endif - #endif } // Check for a monitor window and report change if (sp.pMonCallback != NULL) sp.pMonCallback(SER_MON_COM_SIGNAL, (char)((flags>>8) | - (flags & (SER_FLAG_DSR | SER_FLAG_CTS)))); + (flags & (SER_FLAG_DSR | SER_FLAG_CTS)))); return SER_NO_ERROR; } + /* =========================================================================== ser_get_flags: Get serial port's flags @@ -1095,6 +1238,7 @@ ser_get_flags: Get serial port's flags */ int ser_get_flags(unsigned char *flags) { + long modem_status; if ((setup.com_mode == SETUP_COM_HOST) || @@ -1146,11 +1290,26 @@ int ser_get_flags(unsigned char *flags) } } #else + { + + int status; + ioctl(sp.fd, TIOCMGET, &status); + + // interpret flags + if (!(status & TIOCM_CTS)) *flags |= SER_FLAG_CTS; + if (!(status & TIOCM_DSR)) *flags |= SER_FLAG_DSR; + if ( status & TIOCM_RNG ) *flags |= SER_FLAG_RING; + + // synthesized flags + + // TX_EMPTY + if (!ser_tx_remaining()) *flags |= SER_FLAG_TX_EMPTY; - // ============================================ - // Add code here for POSIX to read flags - // ============================================ + // OVERRUN flag $$ TBI + // FRAMING Error flag $$ TBI + + } #endif } else if (setup.com_mode == SETUP_COM_NONE) @@ -1167,6 +1326,7 @@ ser_get_signals: Get serial port's CTS, RTS, DTR, and DSR signals */ int ser_get_signals(unsigned char *flags) { + long modem_status; if ((setup.com_mode == SETUP_COM_HOST) || @@ -1204,10 +1364,18 @@ int ser_get_signals(unsigned char *flags) *flags |= SER_SIGNAL_DTR; #else + { - // ============================================ - // Add code here for POSIX to read flags - // ============================================ + int status; + ioctl(sp.fd, TIOCMGET, &status); + + // interpret flags + if (status & TIOCM_CTS) *flags |= SER_SIGNAL_CTS; + if (status & TIOCM_DSR) *flags |= SER_SIGNAL_DSR; + if (status & TIOCM_RTS) *flags |= SER_SIGNAL_RTS; + if (status & TIOCM_DTR) *flags |= SER_SIGNAL_DTR; + + } #endif } @@ -1223,6 +1391,7 @@ ser_read_byte: Read byte from the serial port */ int ser_read_byte(char* data) { + // Check if a port is open, return if not if (sp.open_flag == FALSE) { @@ -1232,41 +1401,47 @@ int ser_read_byte(char* data) // Check if COM emulation type is Host port if ((setup.com_mode == SETUP_COM_HOST) || - (setup.com_mode == SETUP_COM_OTHER)) + (setup.com_mode == SETUP_COM_OTHER)) { - #ifdef WIN32 - int new_rxOut; + #ifdef WIN32 + int new_rxOut; - WaitForSingleObject(sp.hReadMutex, 2000); - // Check if any bytes in RX buffer - if (sp.rxIn == sp.rxOut) - { - ReleaseMutex(sp.hReadMutex); - // No data in buffer! - *data = 0; - // Check if there is a monitor window open and report the write - if (sp.pMonCallback != NULL) - sp.pMonCallback(SER_MON_COM_READ, *data); - return SER_NO_DATA; - } + WaitForSingleObject(sp.hReadMutex, 2000); + // Check if any bytes in RX buffer + if (sp.rxIn == sp.rxOut) + { + ReleaseMutex(sp.hReadMutex); + // No data in buffer! + *data = 0; + // Check if there is a monitor window open and report the write + if (sp.pMonCallback != NULL) + sp.pMonCallback(SER_MON_COM_READ, *data); + return SER_NO_DATA; + } - *data = sp.rx_buf[sp.rxOut]; + *data = sp.rx_buf[sp.rxOut]; - new_rxOut = sp.rxOut + 1; - if (new_rxOut >= sizeof(sp.rx_buf)) - new_rxOut = 0; - sp.rxOut = new_rxOut; + new_rxOut = sp.rxOut + 1; + if (new_rxOut >= sizeof(sp.rx_buf)) + new_rxOut = 0; + sp.rxOut = new_rxOut; - ReleaseMutex(sp.hReadMutex); - sp.fIntPending = FALSE; + ReleaseMutex(sp.hReadMutex); + sp.fIntPending = FALSE; - #else + #else + { - // ============================================ - // Add code here for POSIX to write data - // ============================================ + int n_bytes; + n_bytes = read (sp.fd, data, 1); + + if (!n_bytes) { + *data = 0; + return SER_NO_DATA; + } - #endif + } + #endif } // Check if there is a monitor window open and report the write @@ -1284,6 +1459,7 @@ ser_write_byte: Write a byte to the serial port */ int ser_write_byte(char data) { + // Check if a port is open, return if not if (sp.open_flag == FALSE) return SER_NO_ERROR; @@ -1293,6 +1469,7 @@ int ser_write_byte(char data) (setup.com_mode == SETUP_COM_OTHER)) { #ifdef WIN32 + // Store data in structure WaitForSingleObject(sp.hWriteMutex, 2000); sp.tx_buf[0] = data; @@ -1304,13 +1481,8 @@ int ser_write_byte(char data) // Trigger the thread to write the byte SetEvent(sp.hWriteEvent); - #else - - // ================================================= - // Add code here for POSIX to write data (Host Mode) - // ================================================= - + write (sp.fd, &data, 1); #endif } @@ -1321,3 +1493,29 @@ int ser_write_byte(char data) return SER_NO_ERROR; } +/* +=========================================================================== +ser_poll: opportunity to invoke INT6.5 callback + +=========================================================================== +*/ + +int ser_poll () +{ + +#ifndef WIN32 + int bytes; + + ioctl(sp.fd, FIONREAD, &bytes); + + if (bytes && sp.pCallback) { + sp.pCallback(); + } + +#else + return 0; + +#endif + +} + From 48cfc348c2503b2510cec0b36b043c08e02e8564 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 26 Jan 2008 14:39:46 +0000 Subject: [PATCH 051/327] Checkin for version 1.0. Many changes. --- src/VirtualT.h | 3 +- src/a85parse.cpp | 7494 ++++++++++++++++++++-------------------- src/a85parse.h | 50 +- src/a85parse.syn | 36 +- src/assemble.cpp | 190 +- src/assemble.h | 21 +- src/clientsocket.cpp | 42 + src/clientsocket.h | 22 + src/cpu.h | 13 +- src/cpuregs.cpp | 350 +- src/cpuregs.h | 65 +- src/disassemble.cpp | 255 +- src/disassemble.h | 30 +- src/display.cpp | 1024 ++++-- src/display.h | 16 + src/do_instruct.h | 324 +- src/doins.c | 16 +- src/file.cpp | 93 +- src/fl_usage_box.cpp | 184 + src/fl_usage_box.h | 71 + src/genwrap.c | 2 +- src/ide.cpp | 1749 +++++++++- src/ide.h | 80 +- src/inet_pton.c | 305 ++ src/inet_pton.h | 22 + src/io.c | 215 +- src/io.h | 1 + src/m100emu.c | 388 ++- src/m100emu.h | 24 +- src/m100rom.c | 5 +- src/m10rom.c | 991 ++++++ src/m200rom.c | 5 +- src/memedit.cpp | 4 +- src/memory.c | 342 +- src/memory.h | 11 +- src/multieditwin.cpp | 314 ++ src/multieditwin.h | 68 + src/multiwin.cpp | 14 + src/multiwin.h | 12 +- src/n8201rom.c | 5 +- src/periph.cpp | 3 +- src/project.cpp | 881 +++++ src/project.h | 204 ++ src/rememcfg.cpp | 1032 ++++++ src/rememcfg.h | 97 + src/remote.cpp | 2301 ++++++++++++ src/remote.h | 61 + src/roms.h | 4 + src/serial.h | 49 +- src/serversocket.cpp | 59 + src/serversocket.h | 25 + src/setup.cpp | 35 +- src/socket.cpp | 202 ++ src/socket.h | 63 + src/socketexception.h | 23 + src/sound.c | 22 +- src/vt_client_main.cpp | 165 + 57 files changed, 15248 insertions(+), 4834 deletions(-) create mode 100644 src/clientsocket.cpp create mode 100644 src/clientsocket.h create mode 100644 src/fl_usage_box.cpp create mode 100644 src/fl_usage_box.h create mode 100644 src/inet_pton.c create mode 100644 src/inet_pton.h create mode 100644 src/m10rom.c create mode 100644 src/multieditwin.cpp create mode 100644 src/multieditwin.h create mode 100644 src/project.cpp create mode 100644 src/project.h create mode 100644 src/rememcfg.cpp create mode 100644 src/rememcfg.h create mode 100644 src/remote.cpp create mode 100644 src/remote.h create mode 100644 src/serversocket.cpp create mode 100644 src/serversocket.h create mode 100644 src/socket.cpp create mode 100644 src/socket.h create mode 100644 src/socketexception.h create mode 100644 src/vt_client_main.cpp diff --git a/src/VirtualT.h b/src/VirtualT.h index bc067d6..0c27aee 100644 --- a/src/VirtualT.h +++ b/src/VirtualT.h @@ -31,13 +31,14 @@ #ifndef _VIRTUALT_H_ #define _VIRTUALT_H_ -#define VERSION "0.9" +#define VERSION "1.0" enum { MODEL_M100 ,MODEL_M102 ,MODEL_T200 ,MODEL_PC8201 + ,MODEL_M10 ,MODEL_PC8300 }; diff --git a/src/a85parse.cpp b/src/a85parse.cpp index b07a8eb..dbbb445 100644 --- a/src/a85parse.cpp +++ b/src/a85parse.cpp @@ -17,11 +17,11 @@ */ -#ifndef A85PARSE_H_1147178743 +#ifndef A85PARSE_H_1176345433 #include "a85parse.h" #endif -#ifndef A85PARSE_H_1147178743 +#ifndef A85PARSE_H_1176345433 #error Mismatched header file #endif @@ -39,7 +39,7 @@ a85parse_pcb_type a85parse_pcb; #define PCB a85parse_pcb -/* Line 483, C:/Projects/VirtualT/src/asm/a85parse.syn */ +/* Line 493, C:/Projects/VirtualT/src/a85parse.syn */ // Embedded C #include "MString.h" // Include MString header @@ -129,7 +129,11 @@ BOOL ParseASMFile(const char* filename, VTAssembler* pAsm) // Try to open the file if ((gAsm->m_fd = fopen(gAsm->m_Filenames[gAsm->m_FileIndex], "r")) == 0) + { + // Add error indicating failure to open file + gAsm->m_Errors.Add("Error opening file"); return FALSE; + } // Reset the string stack ss_idx = 0; @@ -160,11 +164,15 @@ BOOL ParseASMFile(const char* filename, VTAssembler* pAsm) #define TAB_SPACING gTabSize -#define GET_INPUT ((PCB).input_code = gAsm->m_fd != 0 ? \ - fgetc(gAsm->m_fd) : 0) +#define GET_INPUT {(PCB).input_code = gAsm->m_fd != 0 ? \ + fgetc(gAsm->m_fd) : 0; if ((PCB).input_code == 13) (PCB).input_code = fgetc(gAsm->m_fd);} -#define SYNTAX_ERROR {MString string; string.Format("%s, line %d, column %d", \ - (PCB).error_message, (PCB).line, (PCB).column); gAsm->m_Errors.Add(string); } +#define SYNTAX_ERROR {MString string; if ((PCB).error_frame_token != 0) \ + string.Format("Malformed %s - %s, line %d, column %d", \ + TOKEN_NAMES[(PCB).error_frame_token], (PCB).error_message, (PCB).line, (PCB).column); else \ + string.Format("%s, line %d, column %d", \ + (PCB).error_message, (PCB).line, (PCB).column); \ + gAsm->m_Errors.Add(string); ss_idx = 0; ss_len = 0; } #define PARSER_STACK_OVERFLOW {MString string; string.Format(\ "\nParser stack overflow, line %d, column %d",\ @@ -320,21 +328,21 @@ static int agConvertCase(int c) { #define ag_rp_21() (gAsm->directive_dseg(0)) static void ag_rp_22(void) { -/* Line 100, C:/Projects/VirtualT/src/asm/a85parse.syn */ +/* Line 103, C:/Projects/VirtualT/src/a85parse.syn */ gAsm->label(ss[ss_idx--]); gAsm->directive_ds(); } #define ag_rp_23() (gAsm->directive_ds()) static void ag_rp_24(void) { -/* Line 102, C:/Projects/VirtualT/src/asm/a85parse.syn */ +/* Line 105, C:/Projects/VirtualT/src/a85parse.syn */ gAsm->label(ss[ss_idx--]); gAsm->directive_db(); } #define ag_rp_25() (gAsm->directive_db()) static void ag_rp_26(void) { -/* Line 104, C:/Projects/VirtualT/src/asm/a85parse.syn */ +/* Line 107, C:/Projects/VirtualT/src/a85parse.syn */ gAsm->label(ss[ss_idx--]); gAsm->directive_dw(); } @@ -376,483 +384,487 @@ static void ag_rp_26(void) { #define ag_rp_45() (expression_list_literal()) -#define ag_rp_46() (expression_list_equation()) +#define ag_rp_46() (expression_list_literal()) #define ag_rp_47() (expression_list_equation()) -#define ag_rp_48() (expression_list_literal()) +#define ag_rp_48() (expression_list_equation()) #define ag_rp_49() (expression_list_literal()) -#define ag_rp_50() (gNameList->Add(ss[ss_idx--])) +#define ag_rp_50() (expression_list_literal()) #define ag_rp_51() (gNameList->Add(ss[ss_idx--])) -static void ag_rp_52(void) { -/* Line 147, C:/Projects/VirtualT/src/asm/a85parse.syn */ +#define ag_rp_52() (gNameList->Add(ss[ss_idx--])) + +static void ag_rp_53(void) { +/* Line 151, C:/Projects/VirtualT/src/a85parse.syn */ strcpy(ss[++ss_idx], "$"); ss_len = 1; } -static void ag_rp_53(int c) { -/* Line 150, C:/Projects/VirtualT/src/asm/a85parse.syn */ +static void ag_rp_54(int c) { +/* Line 154, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_54(int c) { -/* Line 151, C:/Projects/VirtualT/src/asm/a85parse.syn */ +static void ag_rp_55(int c) { +/* Line 155, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_55(int c) { -/* Line 152, C:/Projects/VirtualT/src/asm/a85parse.syn */ +static void ag_rp_56(int c) { +/* Line 156, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_56(int c) { -/* Line 155, C:/Projects/VirtualT/src/asm/a85parse.syn */ +static void ag_rp_57(int c) { +/* Line 159, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_57(int c) { -/* Line 156, C:/Projects/VirtualT/src/asm/a85parse.syn */ +static void ag_rp_58(int c) { +/* Line 160, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_58(int ch1, int ch2) { -/* Line 162, C:/Projects/VirtualT/src/asm/a85parse.syn */ +static void ag_rp_59(int ch1, int ch2) { +/* Line 166, C:/Projects/VirtualT/src/a85parse.syn */ ss_idx++; ss_len = 2; sprintf(ss[ss_idx], "%c%c", ch1, ch2); } -static void ag_rp_59(int c) { -/* Line 163, C:/Projects/VirtualT/src/asm/a85parse.syn */ +static void ag_rp_60(int c) { +/* Line 167, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_60(void) { -/* Line 169, C:/Projects/VirtualT/src/asm/a85parse.syn */ +static void ag_rp_61(void) { +/* Line 174, C:/Projects/VirtualT/src/a85parse.syn */ ss_idx++; ss_len = 0; } -static void ag_rp_61(int c) { -/* Line 170, C:/Projects/VirtualT/src/asm/a85parse.syn */ +static void ag_rp_62(int c) { +/* Line 175, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_62(int c) { -/* Line 171, C:/Projects/VirtualT/src/asm/a85parse.syn */ +static void ag_rp_63(int c) { +/* Line 176, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '\\'; ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_63(void) { -/* Line 175, C:/Projects/VirtualT/src/asm/a85parse.syn */ +static void ag_rp_64(void) { +/* Line 181, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '>'; ss[ss_idx][ss_len] = 0; } -static void ag_rp_64(void) { -/* Line 178, C:/Projects/VirtualT/src/asm/a85parse.syn */ +static void ag_rp_65(void) { +/* Line 184, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = '<'; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_65(int c) { -/* Line 179, C:/Projects/VirtualT/src/asm/a85parse.syn */ +static void ag_rp_66(int c) { +/* Line 185, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_66(int c) { -/* Line 180, C:/Projects/VirtualT/src/asm/a85parse.syn */ +static void ag_rp_67(int c) { +/* Line 186, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '\\'; ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -#define ag_rp_67() (gAsm->label(ss[ss_idx--])) - -#define ag_rp_68() (condition(-1)) +#define ag_rp_68() (gAsm->label(ss[ss_idx--])) -#define ag_rp_69() (condition(COND_NOCMP)) +#define ag_rp_69() (condition(-1)) -#define ag_rp_70() (condition(COND_EQ)) +#define ag_rp_70() (condition(COND_NOCMP)) -#define ag_rp_71() (condition(COND_NE)) +#define ag_rp_71() (condition(COND_EQ)) -#define ag_rp_72() (condition(COND_GE)) +#define ag_rp_72() (condition(COND_NE)) -#define ag_rp_73() (condition(COND_LE)) +#define ag_rp_73() (condition(COND_GE)) -#define ag_rp_74() (condition(COND_GT)) +#define ag_rp_74() (condition(COND_LE)) -#define ag_rp_75() (condition(COND_LT)) +#define ag_rp_75() (condition(COND_GT)) -#define ag_rp_76() (gEq->Add(RPN_BITOR)) +#define ag_rp_76() (condition(COND_LT)) #define ag_rp_77() (gEq->Add(RPN_BITOR)) -#define ag_rp_78() (gEq->Add(RPN_BITXOR)) +#define ag_rp_78() (gEq->Add(RPN_BITOR)) #define ag_rp_79() (gEq->Add(RPN_BITXOR)) -#define ag_rp_80() (gEq->Add(RPN_BITAND)) +#define ag_rp_80() (gEq->Add(RPN_BITXOR)) #define ag_rp_81() (gEq->Add(RPN_BITAND)) -#define ag_rp_82() (gEq->Add(RPN_LEFTSHIFT)) +#define ag_rp_82() (gEq->Add(RPN_BITAND)) #define ag_rp_83() (gEq->Add(RPN_LEFTSHIFT)) -#define ag_rp_84() (gEq->Add(RPN_RIGHTSHIFT)) +#define ag_rp_84() (gEq->Add(RPN_LEFTSHIFT)) #define ag_rp_85() (gEq->Add(RPN_RIGHTSHIFT)) -#define ag_rp_86() (gEq->Add(RPN_ADD)) +#define ag_rp_86() (gEq->Add(RPN_RIGHTSHIFT)) -#define ag_rp_87() (gEq->Add(RPN_SUBTRACT)) +#define ag_rp_87() (gEq->Add(RPN_ADD)) -#define ag_rp_88() (gEq->Add(RPN_MULTIPLY)) +#define ag_rp_88() (gEq->Add(RPN_SUBTRACT)) -#define ag_rp_89() (gEq->Add(RPN_DIVIDE)) +#define ag_rp_89() (gEq->Add(RPN_MULTIPLY)) -#define ag_rp_90() (gEq->Add(RPN_MODULUS)) +#define ag_rp_90() (gEq->Add(RPN_DIVIDE)) #define ag_rp_91() (gEq->Add(RPN_MODULUS)) -#define ag_rp_92() (gEq->Add(RPN_EXPONENT)) +#define ag_rp_92() (gEq->Add(RPN_MODULUS)) -#define ag_rp_93() (gEq->Add(RPN_NOT)) +#define ag_rp_93() (gEq->Add(RPN_EXPONENT)) #define ag_rp_94() (gEq->Add(RPN_NOT)) -#define ag_rp_95() (gEq->Add(RPN_BITNOT)) +#define ag_rp_95() (gEq->Add(RPN_NOT)) -#define ag_rp_96(n) (gEq->Add((double) n)) +#define ag_rp_96() (gEq->Add(RPN_BITNOT)) -#define ag_rp_97() (gEq->Add(ss[ss_idx--])) +#define ag_rp_97(n) (gEq->Add((double) n)) -#define ag_rp_98() (gEq->Add(RPN_FLOOR)) +#define ag_rp_98() (gEq->Add(ss[ss_idx--])) -#define ag_rp_99() (gEq->Add(RPN_CEIL)) +#define ag_rp_99() (gEq->Add(RPN_FLOOR)) -#define ag_rp_100() (gEq->Add(RPN_LN)) +#define ag_rp_100() (gEq->Add(RPN_CEIL)) -#define ag_rp_101() (gEq->Add(RPN_LOG)) +#define ag_rp_101() (gEq->Add(RPN_LN)) -#define ag_rp_102() (gEq->Add(RPN_SQRT)) +#define ag_rp_102() (gEq->Add(RPN_LOG)) -#define ag_rp_103() (gEq->Add(RPN_IP)) +#define ag_rp_103() (gEq->Add(RPN_SQRT)) -#define ag_rp_104() (gEq->Add(RPN_FP)) +#define ag_rp_104() (gEq->Add(RPN_IP)) -#define ag_rp_105(n) (n) +#define ag_rp_105() (gEq->Add(RPN_FP)) -#define ag_rp_106(r) (r) +#define ag_rp_106(n) (n) -#define ag_rp_107(n) (n) +#define ag_rp_107(r) (r) -#define ag_rp_108() (conv_to_dec()) +#define ag_rp_108(n) (n) -#define ag_rp_109() (conv_to_hex()) +#define ag_rp_109() (conv_to_dec()) #define ag_rp_110() (conv_to_hex()) #define ag_rp_111() (conv_to_hex()) -#define ag_rp_112() (conv_to_bin()) +#define ag_rp_112() (conv_to_hex()) -#define ag_rp_113() (conv_to_oct()) +#define ag_rp_113() (conv_to_bin()) -#define ag_rp_114() (conv_to_dec()) +#define ag_rp_114() (conv_to_oct()) -static void ag_rp_115(int n) { -/* Line 304, C:/Projects/VirtualT/src/asm/a85parse.syn */ - int_len = 1; integer[0] = n; integer[1] = 0; -} +#define ag_rp_115() (conv_to_dec()) static void ag_rp_116(int n) { -/* Line 305, C:/Projects/VirtualT/src/asm/a85parse.syn */ - int_len = 2; integer[0] = '-', integer[1] = n; integer[2] = 0; +/* Line 312, C:/Projects/VirtualT/src/a85parse.syn */ + int_len = 1; integer[0] = n; integer[1] = 0; } static void ag_rp_117(int n) { -/* Line 306, C:/Projects/VirtualT/src/asm/a85parse.syn */ - int_len = 1; integer[0] = n; integer[1] = 0; +/* Line 313, C:/Projects/VirtualT/src/a85parse.syn */ + int_len = 2; integer[0] = '-', integer[1] = n; integer[2] = 0; } static void ag_rp_118(int n) { -/* Line 307, C:/Projects/VirtualT/src/asm/a85parse.syn */ - integer[int_len++] = n; integer[int_len] = 0; +/* Line 314, C:/Projects/VirtualT/src/a85parse.syn */ + int_len = 1; integer[0] = n; integer[1] = 0; } static void ag_rp_119(int n) { -/* Line 312, C:/Projects/VirtualT/src/asm/a85parse.syn */ - int_len = 1; integer[0] = n; integer[1] = 0; +/* Line 315, C:/Projects/VirtualT/src/a85parse.syn */ + integer[int_len++] = n; integer[int_len] = 0; } static void ag_rp_120(int n) { -/* Line 313, C:/Projects/VirtualT/src/asm/a85parse.syn */ - integer[int_len++] = n; integer[int_len] = 0; +/* Line 320, C:/Projects/VirtualT/src/a85parse.syn */ + int_len = 1; integer[0] = n; integer[1] = 0; } static void ag_rp_121(int n) { -/* Line 316, C:/Projects/VirtualT/src/asm/a85parse.syn */ +/* Line 321, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } static void ag_rp_122(int n) { -/* Line 317, C:/Projects/VirtualT/src/asm/a85parse.syn */ +/* Line 324, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -#define ag_rp_123(n) (n) +static void ag_rp_123(int n) { +/* Line 325, C:/Projects/VirtualT/src/a85parse.syn */ + integer[int_len++] = n; integer[int_len] = 0; +} -#define ag_rp_124() ('\\') +#define ag_rp_124(n) (n) -#define ag_rp_125(n) (n) +#define ag_rp_125(n1, n2) ((n1 << 8) | n2) #define ag_rp_126() ('\\') -#define ag_rp_127() ('\n') +#define ag_rp_127(n) (n) -#define ag_rp_128() ('\t') +#define ag_rp_128() ('\\') -#define ag_rp_129() ('\r') +#define ag_rp_129() ('\n') -#define ag_rp_130() ('\0') +#define ag_rp_130() ('\t') -#define ag_rp_131() ('\'') +#define ag_rp_131() ('\r') -#define ag_rp_132() ('\'') +#define ag_rp_132() ('\0') -static double ag_rp_133(void) { -/* Line 337, C:/Projects/VirtualT/src/asm/a85parse.syn */ +#define ag_rp_133() ('\'') + +#define ag_rp_134() ('\'') + +static double ag_rp_135(void) { +/* Line 346, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor = 1.0; return (double) conv_to_dec(); } -static double ag_rp_134(int d) { -/* Line 338, C:/Projects/VirtualT/src/asm/a85parse.syn */ +static double ag_rp_136(int d) { +/* Line 347, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor = 10.0; return ((double) (d - '0') / gDivisor); } -static double ag_rp_135(double r, int d) { -/* Line 339, C:/Projects/VirtualT/src/asm/a85parse.syn */ +static double ag_rp_137(double r, int d) { +/* Line 348, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor *= 10.0; return (r + (double) (d - '0') / gDivisor); } -#define ag_rp_136() (reg[reg_cnt++] = '0') +#define ag_rp_138() (reg[reg_cnt++] = '0') -#define ag_rp_137() (reg[reg_cnt++] = '1') +#define ag_rp_139() (reg[reg_cnt++] = '1') -#define ag_rp_138() (reg[reg_cnt++] = '2') +#define ag_rp_140() (reg[reg_cnt++] = '2') -#define ag_rp_139() (reg[reg_cnt++] = '3') +#define ag_rp_141() (reg[reg_cnt++] = '3') -#define ag_rp_140() (reg[reg_cnt++] = '4') +#define ag_rp_142() (reg[reg_cnt++] = '4') -#define ag_rp_141() (reg[reg_cnt++] = '5') +#define ag_rp_143() (reg[reg_cnt++] = '5') -#define ag_rp_142() (reg[reg_cnt++] = '6') +#define ag_rp_144() (reg[reg_cnt++] = '6') -#define ag_rp_143() (reg[reg_cnt++] = '7') +#define ag_rp_145() (reg[reg_cnt++] = '7') -#define ag_rp_144() (reg[reg_cnt++] = '0') +#define ag_rp_146() (reg[reg_cnt++] = '0') -#define ag_rp_145() (reg[reg_cnt++] = '1') +#define ag_rp_147() (reg[reg_cnt++] = '1') -#define ag_rp_146() (reg[reg_cnt++] = '2') +#define ag_rp_148() (reg[reg_cnt++] = '2') -#define ag_rp_147() (reg[reg_cnt++] = '3') +#define ag_rp_149() (reg[reg_cnt++] = '3') -#define ag_rp_148() (reg[reg_cnt++] = '0') +#define ag_rp_150() (reg[reg_cnt++] = '0') -#define ag_rp_149() (reg[reg_cnt++] = '1') +#define ag_rp_151() (reg[reg_cnt++] = '1') -#define ag_rp_150() (reg[reg_cnt++] = '2') +#define ag_rp_152() (reg[reg_cnt++] = '2') -#define ag_rp_151() (reg[reg_cnt++] = '3') +#define ag_rp_153() (reg[reg_cnt++] = '3') -#define ag_rp_152() (reg[reg_cnt++] = '3') +#define ag_rp_154() (reg[reg_cnt++] = '3') -#define ag_rp_153() (reg[reg_cnt++] = '0') +#define ag_rp_155() (reg[reg_cnt++] = '0') -#define ag_rp_154() (reg[reg_cnt++] = '1') +#define ag_rp_156() (reg[reg_cnt++] = '1') -#define ag_rp_155() (gAsm->opcode_arg_equ8 (OPCODE_ACI)) +#define ag_rp_157() (gAsm->opcode_arg_equ8 (OPCODE_ACI)) -#define ag_rp_156() (gAsm->opcode_arg_1reg (OPCODE_ADC)) +#define ag_rp_158() (gAsm->opcode_arg_1reg (OPCODE_ADC)) -#define ag_rp_157() (gAsm->opcode_arg_1reg (OPCODE_ADD)) +#define ag_rp_159() (gAsm->opcode_arg_1reg (OPCODE_ADD)) -#define ag_rp_158() (gAsm->opcode_arg_equ8 (OPCODE_ADI)) +#define ag_rp_160() (gAsm->opcode_arg_equ8 (OPCODE_ADI)) -#define ag_rp_159() (gAsm->opcode_arg_1reg (OPCODE_ANA)) +#define ag_rp_161() (gAsm->opcode_arg_1reg (OPCODE_ANA)) -#define ag_rp_160() (gAsm->opcode_arg_equ8 (OPCODE_ANI)) +#define ag_rp_162() (gAsm->opcode_arg_equ8 (OPCODE_ANI)) -#define ag_rp_161() (gAsm->opcode_arg_0 (OPCODE_ASHR)) +#define ag_rp_163() (gAsm->opcode_arg_0 (OPCODE_ASHR)) -#define ag_rp_162() (gAsm->opcode_arg_equ16 (OPCODE_CALL)) +#define ag_rp_164() (gAsm->opcode_arg_equ16 (OPCODE_CALL)) -#define ag_rp_163() (gAsm->opcode_arg_equ16 (OPCODE_CC)) +#define ag_rp_165() (gAsm->opcode_arg_equ16 (OPCODE_CC)) -#define ag_rp_164() (gAsm->opcode_arg_equ16 (OPCODE_CM)) +#define ag_rp_166() (gAsm->opcode_arg_equ16 (OPCODE_CM)) -#define ag_rp_165() (gAsm->opcode_arg_0 (OPCODE_CMA)) +#define ag_rp_167() (gAsm->opcode_arg_0 (OPCODE_CMA)) -#define ag_rp_166() (gAsm->opcode_arg_0 (OPCODE_CMC)) +#define ag_rp_168() (gAsm->opcode_arg_0 (OPCODE_CMC)) -#define ag_rp_167() (gAsm->opcode_arg_1reg (OPCODE_CMP)) +#define ag_rp_169() (gAsm->opcode_arg_1reg (OPCODE_CMP)) -#define ag_rp_168() (gAsm->opcode_arg_equ16 (OPCODE_CNC)) +#define ag_rp_170() (gAsm->opcode_arg_equ16 (OPCODE_CNC)) -#define ag_rp_169() (gAsm->opcode_arg_equ16 (OPCODE_CNZ)) +#define ag_rp_171() (gAsm->opcode_arg_equ16 (OPCODE_CNZ)) -#define ag_rp_170() (gAsm->opcode_arg_equ16 (OPCODE_CP)) +#define ag_rp_172() (gAsm->opcode_arg_equ16 (OPCODE_CP)) -#define ag_rp_171() (gAsm->opcode_arg_equ16 (OPCODE_CPE)) +#define ag_rp_173() (gAsm->opcode_arg_equ16 (OPCODE_CPE)) -#define ag_rp_172() (gAsm->opcode_arg_equ8 (OPCODE_CPI)) +#define ag_rp_174() (gAsm->opcode_arg_equ8 (OPCODE_CPI)) -#define ag_rp_173() (gAsm->opcode_arg_equ16 (OPCODE_CPO)) +#define ag_rp_175() (gAsm->opcode_arg_equ16 (OPCODE_CPO)) -#define ag_rp_174() (gAsm->opcode_arg_equ16 (OPCODE_CZ)) +#define ag_rp_176() (gAsm->opcode_arg_equ16 (OPCODE_CZ)) -#define ag_rp_175() (gAsm->opcode_arg_0 (OPCODE_DAA)) +#define ag_rp_177() (gAsm->opcode_arg_0 (OPCODE_DAA)) -#define ag_rp_176() (gAsm->opcode_arg_1reg (OPCODE_DAD)) +#define ag_rp_178() (gAsm->opcode_arg_1reg (OPCODE_DAD)) -#define ag_rp_177() (gAsm->opcode_arg_1reg (OPCODE_DCR)) +#define ag_rp_179() (gAsm->opcode_arg_1reg (OPCODE_DCR)) -#define ag_rp_178() (gAsm->opcode_arg_1reg (OPCODE_DCX)) +#define ag_rp_180() (gAsm->opcode_arg_1reg (OPCODE_DCX)) -#define ag_rp_179() (gAsm->opcode_arg_0 (OPCODE_DI)) +#define ag_rp_181() (gAsm->opcode_arg_0 (OPCODE_DI)) -#define ag_rp_180() (gAsm->opcode_arg_0 (OPCODE_DSUB)) +#define ag_rp_182() (gAsm->opcode_arg_0 (OPCODE_DSUB)) -#define ag_rp_181() (gAsm->opcode_arg_0 (OPCODE_EI)) +#define ag_rp_183() (gAsm->opcode_arg_0 (OPCODE_EI)) -#define ag_rp_182() (gAsm->opcode_arg_0 (OPCODE_HLT)) +#define ag_rp_184() (gAsm->opcode_arg_0 (OPCODE_HLT)) -#define ag_rp_183() (gAsm->opcode_arg_equ8 (OPCODE_IN)) +#define ag_rp_185() (gAsm->opcode_arg_equ8 (OPCODE_IN)) -#define ag_rp_184() (gAsm->opcode_arg_1reg (OPCODE_INR)) +#define ag_rp_186() (gAsm->opcode_arg_1reg (OPCODE_INR)) -#define ag_rp_185() (gAsm->opcode_arg_1reg (OPCODE_INX)) +#define ag_rp_187() (gAsm->opcode_arg_1reg (OPCODE_INX)) -#define ag_rp_186() (gAsm->opcode_arg_equ16 (OPCODE_JC)) +#define ag_rp_188() (gAsm->opcode_arg_equ16 (OPCODE_JC)) -#define ag_rp_187() (gAsm->opcode_arg_equ16 (OPCODE_JD)) +#define ag_rp_189() (gAsm->opcode_arg_equ16 (OPCODE_JD)) -#define ag_rp_188() (gAsm->opcode_arg_equ16 (OPCODE_JD)) +#define ag_rp_190() (gAsm->opcode_arg_equ16 (OPCODE_JD)) -#define ag_rp_189() (gAsm->opcode_arg_equ16 (OPCODE_JM)) +#define ag_rp_191() (gAsm->opcode_arg_equ16 (OPCODE_JM)) -#define ag_rp_190() (gAsm->opcode_arg_equ16 (OPCODE_JMP)) +#define ag_rp_192() (gAsm->opcode_arg_equ16 (OPCODE_JMP)) -#define ag_rp_191() (gAsm->opcode_arg_equ16 (OPCODE_JNC)) +#define ag_rp_193() (gAsm->opcode_arg_equ16 (OPCODE_JNC)) -#define ag_rp_192() (gAsm->opcode_arg_equ16 (OPCODE_JND)) +#define ag_rp_194() (gAsm->opcode_arg_equ16 (OPCODE_JND)) -#define ag_rp_193() (gAsm->opcode_arg_equ16 (OPCODE_JND)) +#define ag_rp_195() (gAsm->opcode_arg_equ16 (OPCODE_JND)) -#define ag_rp_194() (gAsm->opcode_arg_equ16 (OPCODE_JNZ)) +#define ag_rp_196() (gAsm->opcode_arg_equ16 (OPCODE_JNZ)) -#define ag_rp_195() (gAsm->opcode_arg_equ16 (OPCODE_JP)) +#define ag_rp_197() (gAsm->opcode_arg_equ16 (OPCODE_JP)) -#define ag_rp_196() (gAsm->opcode_arg_equ16 (OPCODE_JPE)) +#define ag_rp_198() (gAsm->opcode_arg_equ16 (OPCODE_JPE)) -#define ag_rp_197() (gAsm->opcode_arg_equ16 (OPCODE_JPO)) +#define ag_rp_199() (gAsm->opcode_arg_equ16 (OPCODE_JPO)) -#define ag_rp_198() (gAsm->opcode_arg_equ16 (OPCODE_JZ)) +#define ag_rp_200() (gAsm->opcode_arg_equ16 (OPCODE_JZ)) -#define ag_rp_199() (gAsm->opcode_arg_equ16 (OPCODE_LDA)) +#define ag_rp_201() (gAsm->opcode_arg_equ16 (OPCODE_LDA)) -#define ag_rp_200() (gAsm->opcode_arg_1reg (OPCODE_LDAX)) +#define ag_rp_202() (gAsm->opcode_arg_1reg (OPCODE_LDAX)) -#define ag_rp_201() (gAsm->opcode_arg_equ8 (OPCODE_LDEH)) +#define ag_rp_203() (gAsm->opcode_arg_equ8 (OPCODE_LDEH)) -#define ag_rp_202() (gAsm->opcode_arg_equ8 (OPCODE_LDES)) +#define ag_rp_204() (gAsm->opcode_arg_equ8 (OPCODE_LDES)) -#define ag_rp_203() (gAsm->opcode_arg_equ16 (OPCODE_LHLD)) +#define ag_rp_205() (gAsm->opcode_arg_equ16 (OPCODE_LHLD)) -#define ag_rp_204() (gAsm->opcode_arg_0 (OPCODE_LHLX)) +#define ag_rp_206() (gAsm->opcode_arg_0 (OPCODE_LHLX)) -#define ag_rp_205() (gAsm->opcode_arg_1reg_equ8(OPCODE_LXI)) +#define ag_rp_207() (gAsm->opcode_arg_1reg_equ8(OPCODE_LXI)) -#define ag_rp_206() (gAsm->opcode_arg_2reg (OPCODE_MOV)) +#define ag_rp_208() (gAsm->opcode_arg_2reg (OPCODE_MOV)) -#define ag_rp_207() (gAsm->opcode_arg_1reg_equ8(OPCODE_MVI)) +#define ag_rp_209() (gAsm->opcode_arg_1reg_equ8(OPCODE_MVI)) -#define ag_rp_208() (gAsm->opcode_arg_0 (OPCODE_NOP)) +#define ag_rp_210() (gAsm->opcode_arg_0 (OPCODE_NOP)) -#define ag_rp_209() (gAsm->opcode_arg_1reg (OPCODE_ORA)) +#define ag_rp_211() (gAsm->opcode_arg_1reg (OPCODE_ORA)) -#define ag_rp_210() (gAsm->opcode_arg_equ8 (OPCODE_ORI)) +#define ag_rp_212() (gAsm->opcode_arg_equ8 (OPCODE_ORI)) -#define ag_rp_211() (gAsm->opcode_arg_equ8 (OPCODE_OUT)) +#define ag_rp_213() (gAsm->opcode_arg_equ8 (OPCODE_OUT)) -#define ag_rp_212() (gAsm->opcode_arg_0 (OPCODE_PCHL)) +#define ag_rp_214() (gAsm->opcode_arg_0 (OPCODE_PCHL)) -#define ag_rp_213() (gAsm->opcode_arg_1reg (OPCODE_POP)) +#define ag_rp_215() (gAsm->opcode_arg_1reg (OPCODE_POP)) -#define ag_rp_214() (gAsm->opcode_arg_1reg (OPCODE_PUSH)) +#define ag_rp_216() (gAsm->opcode_arg_1reg (OPCODE_PUSH)) -#define ag_rp_215() (gAsm->opcode_arg_0 (OPCODE_RAL)) +#define ag_rp_217() (gAsm->opcode_arg_0 (OPCODE_RAL)) -#define ag_rp_216() (gAsm->opcode_arg_0 (OPCODE_RAR)) +#define ag_rp_218() (gAsm->opcode_arg_0 (OPCODE_RAR)) -#define ag_rp_217() (gAsm->opcode_arg_0 (OPCODE_RC)) +#define ag_rp_219() (gAsm->opcode_arg_0 (OPCODE_RC)) -#define ag_rp_218() (gAsm->opcode_arg_0 (OPCODE_RET)) +#define ag_rp_220() (gAsm->opcode_arg_0 (OPCODE_RET)) -#define ag_rp_219() (gAsm->opcode_arg_0 (OPCODE_RIM)) +#define ag_rp_221() (gAsm->opcode_arg_0 (OPCODE_RIM)) -#define ag_rp_220() (gAsm->opcode_arg_0 (OPCODE_RLC)) +#define ag_rp_222() (gAsm->opcode_arg_0 (OPCODE_RLC)) -#define ag_rp_221() (gAsm->opcode_arg_0 (OPCODE_RLDE)) +#define ag_rp_223() (gAsm->opcode_arg_0 (OPCODE_RLDE)) -#define ag_rp_222() (gAsm->opcode_arg_0 (OPCODE_RM)) +#define ag_rp_224() (gAsm->opcode_arg_0 (OPCODE_RM)) -#define ag_rp_223() (gAsm->opcode_arg_0 (OPCODE_RNC)) +#define ag_rp_225() (gAsm->opcode_arg_0 (OPCODE_RNC)) -#define ag_rp_224() (gAsm->opcode_arg_0 (OPCODE_RNZ)) +#define ag_rp_226() (gAsm->opcode_arg_0 (OPCODE_RNZ)) -#define ag_rp_225() (gAsm->opcode_arg_0 (OPCODE_RP)) +#define ag_rp_227() (gAsm->opcode_arg_0 (OPCODE_RP)) -#define ag_rp_226() (gAsm->opcode_arg_0 (OPCODE_RPE)) +#define ag_rp_228() (gAsm->opcode_arg_0 (OPCODE_RPE)) -#define ag_rp_227() (gAsm->opcode_arg_0 (OPCODE_RPO)) +#define ag_rp_229() (gAsm->opcode_arg_0 (OPCODE_RPO)) -#define ag_rp_228() (gAsm->opcode_arg_0 (OPCODE_RRC)) +#define ag_rp_230() (gAsm->opcode_arg_0 (OPCODE_RRC)) -#define ag_rp_229(c) (gAsm->opcode_arg_imm (OPCODE_RST, c)) +#define ag_rp_231(c) (gAsm->opcode_arg_imm (OPCODE_RST, c)) -#define ag_rp_230() (gAsm->opcode_arg_0 (OPCODE_RZ)) +#define ag_rp_232() (gAsm->opcode_arg_0 (OPCODE_RZ)) -#define ag_rp_231() (gAsm->opcode_arg_1reg (OPCODE_SBB)) +#define ag_rp_233() (gAsm->opcode_arg_1reg (OPCODE_SBB)) -#define ag_rp_232() (gAsm->opcode_arg_equ8 (OPCODE_SBI)) +#define ag_rp_234() (gAsm->opcode_arg_equ8 (OPCODE_SBI)) -#define ag_rp_233() (gAsm->opcode_arg_equ16 (OPCODE_SHLD)) +#define ag_rp_235() (gAsm->opcode_arg_equ16 (OPCODE_SHLD)) -#define ag_rp_234() (gAsm->opcode_arg_0 (OPCODE_SHLX)) +#define ag_rp_236() (gAsm->opcode_arg_0 (OPCODE_SHLX)) -#define ag_rp_235() (gAsm->opcode_arg_0 (OPCODE_SIM)) +#define ag_rp_237() (gAsm->opcode_arg_0 (OPCODE_SIM)) -#define ag_rp_236() (gAsm->opcode_arg_0 (OPCODE_SPHL)) +#define ag_rp_238() (gAsm->opcode_arg_0 (OPCODE_SPHL)) -#define ag_rp_237() (gAsm->opcode_arg_equ16 (OPCODE_STA)) +#define ag_rp_239() (gAsm->opcode_arg_equ16 (OPCODE_STA)) -#define ag_rp_238() (gAsm->opcode_arg_1reg (OPCODE_STAX)) +#define ag_rp_240() (gAsm->opcode_arg_1reg (OPCODE_STAX)) -#define ag_rp_239() (gAsm->opcode_arg_0 (OPCODE_STC)) +#define ag_rp_241() (gAsm->opcode_arg_0 (OPCODE_STC)) -#define ag_rp_240() (gAsm->opcode_arg_1reg (OPCODE_SUB)) +#define ag_rp_242() (gAsm->opcode_arg_1reg (OPCODE_SUB)) -#define ag_rp_241() (gAsm->opcode_arg_equ8 (OPCODE_SUI)) +#define ag_rp_243() (gAsm->opcode_arg_equ8 (OPCODE_SUI)) -#define ag_rp_242() (gAsm->opcode_arg_0 (OPCODE_XCHG)) +#define ag_rp_244() (gAsm->opcode_arg_0 (OPCODE_XCHG)) -#define ag_rp_243() (gAsm->opcode_arg_1reg (OPCODE_XRA)) +#define ag_rp_245() (gAsm->opcode_arg_1reg (OPCODE_XRA)) -#define ag_rp_244() (gAsm->opcode_arg_equ8 (OPCODE_XRI)) +#define ag_rp_246() (gAsm->opcode_arg_equ8 (OPCODE_XRI)) -#define ag_rp_245() (gAsm->opcode_arg_0 (OPCODE_XTHL)) +#define ag_rp_247() (gAsm->opcode_arg_0 (OPCODE_XTHL)) #define READ_COUNTS @@ -890,23 +902,23 @@ static a85parse_vs_type const ag_null_value NULL_VALUE_INITIALIZER; static const unsigned char ag_rpx[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 0, 0, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, - 41, 0, 42, 43, 44, 45, 46, 47, 0, 48, 49, 50, 51, 52, 53, 0, 54, 55, - 0, 56, 57, 58, 0, 59, 60, 61, 62, 0, 63, 64, 65, 0, 0, 0, 66, 0, - 0, 67, 0, 0, 68, 0, 0, 69, 0, 0, 70, 0, 0, 71, 0, 0, 72, 73, - 0, 74, 75, 0, 76, 77, 0, 78, 79, 80, 81, 0, 82, 83, 0, 84, 85, 86, - 87, 88, 0, 89, 90, 91, 92, 93, 0, 0, 94, 95, 96, 97, 98, 99,100,101, - 102,103,104,105,106,107,108,109,110,111,112,113,114, 0, 0,115,116,117, - 118,119,120,121,122,123,124,125,126,127,128, 0,129,130,131,132,133,134, - 135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150, 0, 0, - 0,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 0, 0, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 0, 41, 42, 43, 44, 45, 46, 47, 48, 0, 49, 50, 51, 52, 53, 54, 0, 55, + 56, 0, 57, 58, 59, 0, 60, 61, 62, 63, 0, 64, 65, 66, 0, 0, 0, 67, + 0, 0, 68, 0, 0, 69, 0, 0, 70, 0, 0, 71, 0, 0, 72, 0, 0, 73, + 74, 0, 75, 76, 0, 77, 78, 0, 79, 80, 81, 82, 0, 83, 84, 0, 85, 86, + 87, 88, 89, 0, 90, 91, 92, 93, 94, 0, 0, 95, 96, 97, 98, 99,100,101, + 102,103,104,105,106,107,108,109,110,111,112,113,114,115, 0, 0,116,117, + 118,119,120,121,122,123,124,125,126,127,128,129,130, 0,131,132,133,134, + 135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152, + 0, 0, 0,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167, 168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185, 186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203, 204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221, 222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, - 240,241 + 240,241,242,243 }; static const unsigned char ag_key_itt[] = { @@ -925,25 +937,25 @@ static const unsigned char ag_key_itt[] = { }; static const unsigned short ag_key_pt[] = { - 1,291, 1,295, 1,297, 1,305, 1,306, 1,307, 1,308, 1,309, - 1,310, 1,311, 1,312, 1,313, 1,314, 1,315, 1,316, 1,317, - 1,318, 1,319, 1,320, 1,321, 1,322, 1,324, 1,326, 1,327, - 1,328, 1,329, 1, 85, 1,331, 1,334, 1,336, 1,338, 1,340, - 1,342, 1,345, 1,347, 1,349, 1,351, 1,353, 1,359, 1,362, - 1,366, 1,367, 1,368, 1,369, 1,370, 1,371, 1,372, 1,376, - 1,374, 1,159, 1,375, 1,175, 1,176, 1,177, 1,178, 1,378, - 1,180, 1,377, 1,379, 1,381, 1,382, 1,383, 1,384, 1,385, - 1,386, 1,387, 1,388, 1,389, 1,390, 1,391, 1,392, 1,393, - 1,394, 1,395, 1,396, 1,397, 1,398, 1,399, 1,400, 1,402, - 1,403, 1,404, 1,405, 1,406, 1,407, 1,408, 1,409, 1,410, - 1,411, 1,412, 1,413, 1,414, 1,415, 1,416, 1,417, 1,418, - 1,419, 1,420, 1,421, 1,422, 1,423, 1,424, 1,425, 1,426, - 1,427, 1,428, 1,429, 1,430, 1,431, 1,432, 1,433, 1,434, - 1,435, 1,436, 1,437, 1,438, 1,439, 1,440, 1,441, 1,442, - 1,443, 1,444, 1,445, 1,446, 1,447, 1,448, 1,449, 1,450, - 1,451, 1,452, 1,453, 1,454, 1,455, 1,456, 1,457, 1,458, - 1,459, 1,460, 1,461, 1,462, 1,463, 1,464, 1,465, 1,466, - 1,467, 1,468, 1,469, 1,470, 1,471,0 + 1,292, 1,296, 1,298, 1,306, 1,307, 1,308, 1,309, 1,310, + 1,311, 1,312, 1,313, 1,314, 1,315, 1,316, 1,317, 1,318, + 1,319, 1,320, 1,321, 1,322, 1,323, 1,325, 1,327, 1,328, + 1,329, 1,330, 1, 86, 1,332, 1,335, 1,337, 1,339, 1,341, + 1,343, 1,346, 1,348, 1,350, 1,352, 1,354, 1,360, 1,363, + 1,367, 1,368, 1,369, 1,370, 1,371, 1,372, 1,373, 1,377, + 1,375, 1,160, 1,376, 1,176, 1,177, 1,178, 1,179, 1,379, + 1,181, 1,378, 1,380, 1,382, 1,383, 1,384, 1,385, 1,386, + 1,387, 1,388, 1,389, 1,390, 1,391, 1,392, 1,393, 1,394, + 1,395, 1,396, 1,397, 1,398, 1,399, 1,400, 1,401, 1,403, + 1,404, 1,405, 1,406, 1,407, 1,408, 1,409, 1,410, 1,411, + 1,412, 1,413, 1,414, 1,415, 1,416, 1,417, 1,418, 1,419, + 1,420, 1,421, 1,422, 1,423, 1,424, 1,425, 1,426, 1,427, + 1,428, 1,429, 1,430, 1,431, 1,432, 1,433, 1,434, 1,435, + 1,436, 1,437, 1,438, 1,439, 1,440, 1,441, 1,442, 1,443, + 1,444, 1,445, 1,446, 1,447, 1,448, 1,449, 1,450, 1,451, + 1,452, 1,453, 1,454, 1,455, 1,456, 1,457, 1,458, 1,459, + 1,460, 1,461, 1,462, 1,463, 1,464, 1,465, 1,466, 1,467, + 1,468, 1,469, 1,470, 1,471, 1,472,0 }; static const unsigned char ag_key_ch[] = { @@ -1276,7 +1288,7 @@ static const unsigned char ag_key_act[] = { }; static const unsigned short ag_key_parm[] = { - 0,301,302, 0,299,300, 0, 0,294, 0,303, 0, 0,296,304, 0, 35,285, + 0,302,303, 0,300,301, 0, 0,295, 0,304, 0, 0,297,305, 0, 35,286, 0,118,120,122, 0,124,126, 0, 12,128, 0,116, 0, 0, 0, 0,136,138, 140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146, 14,154, 0,156, 158, 0,160,162, 0, 16,166, 0, 0, 20, 0,164, 18, 22, 0, 40, 0, 34, @@ -1288,8 +1300,8 @@ static const unsigned short ag_key_parm[] = { 242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272,274, 0, 0, 0, 282, 0,280,284, 32, 0,286,288, 0, 0, 0,276,278, 0, 0, 46, 0,292, 294, 0,290, 0,296, 0, 0, 52, 0, 0, 0, 0, 0,170, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 42, 0, 0,301,302, 0,299,300, 0, 0,294, 0,303, - 0, 0,296,304, 0, 35,285, 0,350,339, 0,332, 0,337,352, 0,118,120, + 0, 0, 0, 0, 0, 42, 0, 0,302,303, 0,300,301, 0, 0,295, 0,304, + 0, 0,297,305, 0, 35,286, 0,351,340, 0,333, 0,338,353, 0,118,120, 122, 0,124, 70,126, 0, 12,128, 0,116, 0, 0, 0, 0,136,138,140, 0, 142,144, 0,148,150,152, 0,130,132, 82,134, 0,146, 14,154, 0,156,158, 0,160,162, 0, 16,166, 0, 0, 20, 0,164, 18, 22, 0, 40, 0, 34, 0, @@ -1302,10 +1314,10 @@ static const unsigned short ag_key_parm[] = { 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272,274, 0, 72, 74, 0,278, 0,282, 0,280,284, 32, 0, 286,288, 0, 0, 8, 0,276,112, 88, 0, 0, 46, 0,292,294, 0,290, 68, - 0,296, 0,335, 0, 52,168,360,330, 0,343,333,341,110, 96,102,100,104, - 0, 0, 94, 0, 0,106,108, 0, 0, 0, 0, 0, 42, 0, 0, 38, 0,301, - 302, 0,299,300, 0, 0,294, 0,303, 0, 0,296,304, 0, 35,285, 0,350, - 339, 0,332, 0,337,352, 0,118,120,122, 0,124, 70,126, 0, 12,128, 0, + 0,296, 0,336, 0, 52,169,361,331, 0,344,334,342,110, 96,102,100,104, + 0, 0, 94, 0, 0,106,108, 0, 0, 0, 0, 0, 42, 0, 0, 38, 0,302, + 303, 0,300,301, 0, 0,295, 0,304, 0, 0,297,305, 0, 35,286, 0,351, + 340, 0,333, 0,338,353, 0,118,120,122, 0,124, 70,126, 0, 12,128, 0, 116, 0, 0, 0, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132, 82,134, 0,146, 14,154, 0,156,158, 0,160,162, 0, 16,166, 0, 0, 20, 0,164, 18, 22, 0, 40, 0, 34, 0, 26, 24, 0, 0, 0,168, 38, 0, 54, @@ -1317,10 +1329,10 @@ static const unsigned short ag_key_parm[] = { 0,246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256, 262,264,266, 0,268,270, 0,272,274, 0, 72, 74, 0,278, 0,282, 0,280, 284, 32, 0,286,288, 0, 0, 0,276,112, 88, 0, 0, 46, 0,292,294, 0, - 290, 68, 0,296, 0,335, 0, 52,168,360,330, 0,343,333,341,110, 96,102, + 290, 68, 0,296, 0,336, 0, 52,169,361,331, 0,344,334,342,110, 96,102, 100,104, 0, 0, 94, 0, 0,106,108, 0, 0, 0, 0, 0, 42, 0, 0, 80, - 92, 0, 84, 86, 0, 52,168, 35, 82, 0, 90, 0, 78, 88, 0, 35, 0, 35, - 97, 0, 52, 35, 0, 35,285, 0, 0, 0, 35, 4, 2, 0, 35,285, 0,118, + 92, 0, 84, 86, 0, 52,169, 35, 82, 0, 90, 0, 78, 88, 0, 35, 0, 35, + 98, 0, 52, 35, 0, 35,286, 0, 0, 0, 35, 4, 2, 0, 35,286, 0,118, 120,122, 0,124,126, 0, 12,128, 0,116, 0, 0, 0, 0,136,138,140, 0, 142,144, 0,148,150,152, 0,130,132,134, 0,146, 14,154, 0,156,158, 0, 160,162, 0, 16,166, 0, 0, 20, 0,164, 18, 22, 0, 40, 0, 34, 0, 26, @@ -1354,9 +1366,9 @@ static const unsigned short ag_key_parm[] = { 0, 44,230,232, 0, 0,236,238, 0,246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272,274, 0, 0, 0,282, 0,280,284, 32, 0,286,288, 0, 0, 8, 0,276,278, 0, 0, - 46, 0,292,294, 0,290, 0,296, 0,285, 0, 0, 0, 0,170, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 42, 0, 0,285, 0, 80, 92, 0, 84, 86, 0, 52, - 168, 35, 82, 0, 90, 0, 88, 0, 35,285, 0,118,120,122, 0,124,126, 0, + 46, 0,292,294, 0,290, 0,296, 0,286, 0, 0, 0, 0,170, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 42, 0, 0,286, 0, 80, 92, 0, 84, 86, 0, 52, + 169, 35, 82, 0, 90, 0, 88, 0, 35,286, 0,118,120,122, 0,124,126, 0, 116, 0, 0,128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132, 134, 0,146,154, 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196, @@ -1365,8 +1377,8 @@ static const unsigned short ag_key_parm[] = { 246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262, 264,266, 0,268,270, 0,272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, 0, 0,292,294, 0,290, 0,296, 0, 0, 0, 0, - 0,168,170, 0, 0, 0, 0,222, 0, 0, 0, 0, 0, 0, 35,285, 0,350, - 339, 0,332, 0,337,352, 0,118,120,122, 0,124, 70,126, 0,116, 0, 0, + 0,168,170, 0, 0, 0, 0,222, 0, 0, 0, 0, 0, 0, 35,286, 0,351, + 340, 0,333, 0,338,353, 0,118,120,122, 0,124, 70,126, 0,116, 0, 0, 128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146, 154, 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198,200, 0,178,180, @@ -1375,8 +1387,8 @@ static const unsigned short ag_key_parm[] = { 0, 66,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, 0,258, 260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272, 274, 0, 72, 74, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, - 0, 0,292,294, 0,290, 68, 0,296, 0,335,360,330, 0,343,333,341, 0, - 0, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35,285, + 0, 0,292,294, 0,290, 68, 0,296, 0,336,361,331, 0,344,334,342, 0, + 0, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35,286, 0,118,120,122, 0,124,126, 0,116, 0, 0,128, 0,136,138,140, 0,142, 144, 0,148,150,152, 0,130,132, 82,134, 0,146,154, 0,156,158, 0,160, 162, 0, 0, 0,164,166, 0, 80, 92, 0,174,176, 0,172, 90, 0,186, 0, @@ -1385,10 +1397,10 @@ static const unsigned short ag_key_parm[] = { 220, 0,224,226, 0, 0,228, 0,230,232,234, 0,236,238, 0,246,248, 0, 252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0, 268,270, 0,272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0, - 276,278, 88, 0, 0, 0,292,294, 0,290, 0,296, 0, 52,168, 0, 0, 0, + 276,278, 88, 0, 0, 0,292,294, 0,290, 0,296, 0, 52,169, 0, 0, 0, 0,168, 0,170, 0, 0, 0, 0,222, 0, 0, 0, 0, 0, 0, 35,110, 96, 102,100,104, 94,106,108, 0, 35, 96,100, 0, 35,110, 96,100, 94,114, 0, - 35, 96,100, 94,112, 0, 80, 92, 0, 84, 86, 0, 52,168, 82, 0, 90, 0, + 35, 96,100, 94,112, 0, 80, 92, 0, 84, 86, 0, 52,169, 82, 0, 90, 0, 78, 88, 0,110, 96,102,100,104, 94,106,108, 0, 96,100, 0,110, 96,100, 94,114, 0, 96,100, 94,112, 0,118,120,122, 0,124,126, 0,116, 0, 0, 128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146, @@ -1398,11 +1410,11 @@ static const unsigned short ag_key_parm[] = { 220, 0,224,226, 0, 0,228, 0,230,232,234, 0,236,238, 0,246,248, 0, 252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0, 268,270, 0,272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0, - 276,278, 0, 0, 0,292,294, 0,290, 0,296, 0,285, 0, 0, 0,168,170, - 0, 0, 0, 0,222, 0, 0, 0, 0, 0, 0, 35,285, 0, 52, 0, 0, 52, - 285, 0, 35,285, 0,350,339, 0,332, 0,337,352, 0,335,360,330, 0,343, - 333,341, 0, 35,285, 0,330, 0, 0,168, 0,173, 0, 35,285, 0,350,339, - 0,332, 0,337,352, 0,118,120,122, 0,124, 70,126, 0,116, 0, 0,128, + 276,278, 0, 0, 0,292,294, 0,290, 0,296, 0,286, 0, 0, 0,168,170, + 0, 0, 0, 0,222, 0, 0, 0, 0, 0, 0, 35,286, 0, 52, 0, 0, 52, + 286, 0, 35,286, 0,351,340, 0,333, 0,338,353, 0,336,361,331, 0,344, + 334,342, 0, 35,286, 0,331, 0, 0,169, 0,174, 0, 35,286, 0,351,340, + 0,333, 0,338,353, 0,118,120,122, 0,124, 70,126, 0,116, 0, 0,128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146,154, 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, 0, 170, 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198,200, 0,178, @@ -1411,18 +1423,18 @@ static const unsigned short ag_key_parm[] = { 226, 0, 66,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, 0, 258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0, 272,274, 0, 72, 74, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, - 0, 0, 0,292,294, 0,290, 68, 0,296, 0,335,360,330, 0,343,333,341, + 0, 0, 0,292,294, 0,290, 68, 0,296, 0,336,361,331, 0,344,334,342, 0, 96, 0,100, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, - 0, 94, 0, 35,285, 0,350,339, 0,332, 0,337,352, 0, 58, 62, 0,170, + 0, 94, 0, 35,286, 0,351,340, 0,333, 0,338,353, 0, 58, 62, 0,170, 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198,200, 0,178,180, 184, 0,196,182,202, 0,206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 60, 0, 64,216, 0, 76,218, 0, 0,220, 0, 56,222, 0,224,226, 0, 66,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, 0,258, 260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272, 274, 0, 72, 74, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, - 0, 0,292,294, 0,290, 68, 0,296, 0,335,360,330, 0,343,333,341, 96, + 0, 0,292,294, 0,290, 68, 0,296, 0,336,361,331, 0,344,334,342, 96, 100, 0, 94, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 80, 92, 0, - 84, 86, 0, 52,168, 82, 0, 90, 0, 88, 0,350,339, 0,332, 0,337,352, + 84, 86, 0, 52,169, 82, 0, 90, 0, 88, 0,351,340, 0,333, 0,338,353, 0,118,120,122, 0,124, 70,126, 0,116, 0, 0,128, 0,136,138,140, 0, 142,144, 0,148,150,152, 0,130,132,134, 0,146,154, 0,156,158, 0,160, 162, 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, 0,174,176, 0,172, 0, @@ -1432,8 +1444,8 @@ static const unsigned short ag_key_parm[] = { 234, 0,236,238, 0,246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272,274, 0, 72, 74, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, 0, 0,292,294, 0,290, - 68, 0,296, 0,335,360,330,285,343,333,341, 0, 0, 0, 0, 0,170, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,350,339, 0,332, 0,337,352, 0, + 68, 0,296, 0,336,361,331,286,344,334,342, 0, 0, 0, 0, 0,170, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,351,340, 0,333, 0,338,353, 0, 118,120,122, 0,124, 70,126, 0,116, 0, 0,128, 0,136,138,140, 0,142, 144, 0,148,150,152, 0,130,132,134, 0,146,154, 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, 0,174,176, 0,172, 0,186, @@ -1443,8 +1455,8 @@ static const unsigned short ag_key_parm[] = { 0,246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256, 262,264,266, 0,268,270, 0,272,274, 0, 72, 74, 0,282, 0,280,284, 0, 286,288, 0, 0, 0,276,278, 0, 0, 0,292,294, 0,290, 68, 0,296, 0, - 335,330,285,343,333,341, 0, 0, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,339, 0,332, 0,337, 0,118,120,122, 0,124, 70,126, + 336,331,286,344,334,342, 0, 0, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,340, 0,333, 0,338, 0,118,120,122, 0,124, 70,126, 0,116, 0, 0,128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130, 132,134, 0,146,154, 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198, @@ -1453,9 +1465,9 @@ static const unsigned short ag_key_parm[] = { 226, 0, 66,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, 0, 258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0, 272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, - 0, 0,292,294, 0,290, 68, 0,296, 0,335,330,285,343,333,341, 0, 0, - 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,339, 0,332, - 0,337, 0,118,120,122, 0,124,126, 0,116, 0, 0,128, 0,136,138,140, + 0, 0,292,294, 0,290, 68, 0,296, 0,336,331,286,344,334,342, 0, 0, + 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,340, 0,333, + 0,338, 0,118,120,122, 0,124,126, 0,116, 0, 0,128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146,154, 0,156,158, 0, 160,162, 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, @@ -1464,8 +1476,8 @@ static const unsigned short ag_key_parm[] = { 236,238, 0,246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, 0, 0,292,294, 0,290, 68, 0,296, - 0,335,330,285,343,333,341, 0, 0, 0, 0, 0,170, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,339, 0,332, 0,337, 0,118,120,122, 0,124,126, + 0,336,331,286,344,334,342, 0, 0, 0, 0, 0,170, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,340, 0,333, 0,338, 0,118,120,122, 0,124,126, 0,116, 0, 0,128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130, 132,134, 0,146,154, 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198, @@ -1474,10 +1486,10 @@ static const unsigned short ag_key_parm[] = { 226, 0, 66,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, 0, 258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0, 272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, - 0, 0,292,294, 0,290, 0,296, 0,335,330,285,343,333,341, 0, 0, 0, - 0, 0,170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,339, 0,332, 0, - 337, 0, 58, 62, 0, 60, 64, 0,335,285,343,333,341, 54, 0, 0, 56, 0, - 330,285, 0, 35,285, 0,118,120,122, 0,124,126, 0,116, 0, 0,128, 0, + 0, 0,292,294, 0,290, 0,296, 0,336,331,286,344,334,342, 0, 0, 0, + 0, 0,170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,340, 0,333, 0, + 338, 0, 58, 62, 0, 60, 64, 0,336,286,344,334,342, 54, 0, 0, 56, 0, + 331,286, 0, 35,286, 0,118,120,122, 0,124,126, 0,116, 0, 0,128, 0, 136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146,154, 0, 156,158, 0,160,162, 0, 0, 0,164,166, 0,174,176, 0,172, 0,186, 0, 188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0,206, 0, @@ -1485,9 +1497,9 @@ static const unsigned short ag_key_parm[] = { 224,226, 0, 0,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, - 0, 0, 0,292,294, 0,290, 0,296, 0,330, 0, 0, 0, 0,168,170, 0, - 0, 0, 0,222, 0, 0, 0, 0, 0, 0,330, 0, 35,285, 0, 0, 96,100, - 94, 98, 0, 82, 0, 80, 92, 0, 84, 86, 0, 52,168, 35,110, 96,102,100, + 0, 0, 0,292,294, 0,290, 0,296, 0,331, 0, 0, 0, 0,168,170, 0, + 0, 0, 0,222, 0, 0, 0, 0, 0, 0,331, 0, 35,286, 0, 0, 96,100, + 94, 98, 0, 82, 0, 80, 92, 0, 84, 86, 0, 52,169, 35,110, 96,102,100, 104, 0, 94, 90,106,108, 78, 88, 0 }; @@ -1721,40 +1733,40 @@ static const unsigned short ag_key_jmp[] = { }; static const unsigned short ag_key_index[] = { - 204, 0,471,204,501,743,204,204,779,789,789, 0, 0, 0,791,794,794,800, - 800,794,794,802,789,789,995,1197,1218,1222,1222,1222,1222,1224, 0, 0, - 1413,1431,789,1439,779,789,779,789,789,789,789,789,789,789,789,789,789, - 1599,1599,1439,789,779,779,1439,1792,779,789,779,1439,789,789,1975,789, - 0, 0, 0, 0,1599,779,1995,1599,779,1995,1599,2005,779,1599,1599,1599, - 779,779,1995,1599,789,1599,1599,1599,1599,1599,1599,1599,1599,1599,1599, - 1599,1599,1599,1599,2009,2009,1599,779,779,1995,1599,1995,1995,2016,1599, - 779,779,779,2005,779,779,779,779,779,779,779,779,779,779,779,779,779,779, - 2016,1995,779,1599,1599,1599,1599,2016,1995,2016,1599,779,779,779,779, - 779,779,779,1995,1599,1599,779,779,779,1599,779,1995,779,1995,1995,779, - 2028,2037,2028,2037,2046,2028,2028,2028,2037, 0,2049,2049,2028,2028,2037, - 2037,2037,2055,2028,2028,2028,2046,2028,2028,2028,2028,2028,2028,2028, - 2028,2028,2028,2028,2028,2028,2028,2055,2037,2028,2055,2037,2055,2028, - 2028,2028,2028,2028,2028,2028,2037,2028,2028,2028,2028,2037,2028,2037, - 2037,2028,2208,794,1222,789, 0,800,800,1431,789, 0,800,800,779,2028, - 2228,2231,779,2028,794,1222,794,1222,794,1222,794,1222,779,2028,779,2028, - 779,2028,800,800,800,779,2028,2028,2028,2028,779,2028,779,2028,2245,800, - 800, 0,800, 0,2256,789,2028,2028,204,2028,2037,2028,2037,2046,2028,2028, - 2028,2037, 0,2049,2049,2028,2028,2037,2037,2037,2055,2028,2028,2028,2046, - 2028,2028,2028,2028,2028,2028,2028,2028,2028,2028,2028,2028,2028,2028, - 2055,2037,2028,2055,2037,2055,2028,2028,2028,2028,2028,2028,2028,2037, - 2028,2028,2028,2028,2037,2028,2037,2037,2028,2208,2259,2261,2261,2256, - 0,2441, 0, 0,2261,1792,2467,1792,2602,789,789,789,789,789,789,789, - 1792,1792, 0, 0, 0, 0, 0, 0, 0,1439,2028,2631,2631,2631,2812,3006, - 3006,3196,3385,3573,3608,2028,1431,3618,3618,3618,2261,3618,3618,3618, - 3618, 0, 0,3772,1599,1599,1599,1599,1599,3790,3790,1599, 0,3795, 0, - 2261, 0, 0,2028,2028,2028,2028,2028,2028,2028, 0,1439,2631,1439,2631, - 2631,2631,2631,2028,2028,779,2028,779,2028,779,2028,779,2028,779,2028, - 2028,779,2028,2028,779,2028,2028,779,779,779,779,779,779,779,779,779,779, - 779,779,779,3790,2261,3618,3618,3618,3618,3790,3790, 0, 0, 0, 0, 0, - 0, 0, 0,2812,2631,2631,2631,2631,2631,2028,2028,2028,2028,2028,2028, - 2028,2028,2028,2028,2028,2028,3809,1222,2028,2028,2037,2028,2812,2812, - 3006,3006,3006,3006,3006,3006,3196,3196,3385,3385,1222,2028,2028,2037, - 2028 + 204, 0,471,204,501,743, 0,204,204,204,779,789,789, 0, 0, 0,791,794, + 794,800,800,794,794,802,789,789,995,1197,1218,1222,1222,1222,1222,1224, + 0, 0,1413,1431,789,1439,779,789,779,789,789,789,789,789,789,789,789, + 789,789,1599,1599,1439,789,779,779,1439,1792,779,789,779,1439,789,789, + 1975,789, 0, 0, 0, 0,1599,779,1995,1599,779,1995,1599,2005,779,1599, + 1599,1599,779,779,1995,1599,789,1599,1599,1599,1599,1599,1599,1599,1599, + 1599,1599,1599,1599,1599,1599,2009,2009,1599,779,779,1995,1599,1995,1995, + 2016,1599,779,779,779,2005,779,779,779,779,779,779,779,779,779,779,779, + 779,779,779,2016,1995,779,1599,1599,1599,1599,2016,1995,2016,1599,779, + 779,779,779,779,779,779,1995,1599,1599,779,779,779,1599,779,1995,779,1995, + 1995,779,2028,2037,2028,2037,2046,2028,2028,2028,2037, 0,2049,2049,2028, + 2028,2037,2037,2037,2055,2028,2028,2028,2046,2028,2028,2028,2028,2028, + 2028,2028,2028,2028,2028,2028,2028,2028,2028,2055,2037,2028,2055,2037, + 2055,2028,2028,2028,2028,2028,2028,2028,2037,2028,2028,2028,2028,2037, + 2028,2037,2037,2028,2208,794,1222,789, 0,800,800,1431,789, 0,800,800, + 779,2028,2228,2231,779,2028,794,1222,794,1222,794,1222,794,1222,779,2028, + 779,2028,779,2028,800,800,800,779,2028,2028,2028,2028,779,2028,779,2028, + 2245,800,800, 0,800, 0,2256,789,2028,2028,2028,2037,2028,2037,2046,2028, + 2028,2028,2037, 0,2049,2049,2028,2028,2037,2037,2037,2055,2028,2028,2028, + 2046,2028,2028,2028,2028,2028,2028,2028,2028,2028,2028,2028,2028,2028, + 2028,2055,2037,2028,2055,2037,2055,2028,2028,2028,2028,2028,2028,2028, + 2037,2028,2028,2028,2028,2037,2028,2037,2037,2028,2208,2259,2261,2261, + 2256, 0,2441, 0, 0,2261,1792,2467,1792,2602,789,789,789,789,789,789, + 789,1792,1792, 0, 0, 0, 0, 0, 0, 0,1439,2028,2631,2631,2631,2812, + 3006,3006,3196,3385,3573,3608,2028,1431,3618,3618,3618,2261,3618,3618, + 3618,3618, 0, 0,3772,1599,1599,1599,1599,1599,3790,3790,1599, 0,3795, + 0,2261, 0,2261,2028,2028,2028,2028,2028,2028,2028, 0,1439,2631,1439, + 2631,2631,2631,2631,2028,2028,779,2028,779,2028,779,2028,779,2028,779, + 2028,2028,779,2028,2028,779,2028,2028,779,779,779,779,779,779,779,779, + 779,779,779,779,779,3790,2261,3618,3618,3618,3618,3790,3790, 0, 0, 0, + 0, 0, 0, 0, 0, 0,2812,2631,2631,2631,2631,2631,2028,2028,2028,2028, + 2028,2028,2028,2028,2028,2028,2028,2028,3809,1222,2261,2028,2028,2037, + 2028,2812,2812,3006,3006,3006,3006,3006,3006,3196,3196,3385,3385,1222, + 2028,2028,2037,2028 }; static const unsigned char ag_key_ends[] = { @@ -1844,21 +1856,21 @@ static const unsigned char ag_key_ends[] = { #define AG_TCV(x) (((int)(x) >= -1 && (int)(x) <= 255) ? ag_tcv[(x) + 1] : 0) static const unsigned short ag_tcv[] = { - 26, 26,472,472,472,472,472,472,472,472, 1,288,472,472,472,472,472,472, - 472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, 1,361,473, - 472,474,358,348,475,365,364,356,354,287,355,476,357,477,478,478,478,478, - 478,478,478,479,479,472,286,480,472,481,472,472,482,482,482,482,482,482, - 483,483,483,483,483,483,483,484,483,483,483,485,483,486,483,483,483,487, - 483,483,472,488,472,346,489,472,482,482,482,482,482,482,483,483,483,483, - 483,483,483,484,483,483,483,485,483,486,483,483,483,487,483,483,472,344, - 472,363,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490, - 490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490, - 490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490, - 490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490, - 490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490, - 490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490, - 490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490, - 490,490,490,490,490 + 26, 26,473,473,473,473,473,473,473,473, 1,289,473,473,473,473,473,473, + 473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, 1,362,474, + 473,475,359,349,476,366,365,357,355,288,356,477,358,478,479,479,479,479, + 479,479,479,480,480,473,287,481,473,482,473,473,483,483,483,483,483,483, + 484,484,484,484,484,484,484,485,484,484,484,486,484,487,484,484,484,488, + 484,484,473,489,473,347,490,473,483,483,483,483,483,483,484,484,484,484, + 484,484,484,485,484,484,484,486,484,487,484,484,484,488,484,484,473,345, + 473,364,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, + 491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, + 491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, + 491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, + 491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, + 491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, + 491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, + 491,491,491,491,491 }; #ifndef SYNTAX_ERROR @@ -2045,1291 +2057,1390 @@ static void ag_undo(void) { static const unsigned short ag_tstt[] = { -489,487,486,485,484,483,482,474,471,470,469,468,467,466,465,464,463,462,461, - 460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444,443, - 442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426,425, - 424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408,407, - 406,405,404,403,402,400,399,398,397,396,395,394,393,392,391,390,389,388, - 387,386,385,384,383,382,381,379,329,328,327,326,324,322,321,320,319,318, - 317,316,315,314,313,312,311,310,309,308,307,304,303,302,301,300,299,296, - 294,291,288,287,286,285,85,35,1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,1,0,37, -35,1,0,2,282, -489,487,486,485,484,483,482,474,471,470,469,468,467,466,465,464,463,462,461, - 460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444,443, - 442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426,425, - 424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408,407, - 406,405,404,403,402,400,399,398,397,396,395,394,393,392,391,390,389,388, - 387,386,385,384,383,382,381,379,329,328,327,326,324,322,321,320,319,318, - 317,316,315,314,313,312,311,310,309,308,307,304,303,302,301,300,299,296, - 294,291,288,287,286,285,85,35,1,0,22,23,24,25,39,40, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,38,1,0, +490,488,487,486,485,484,483,475,472,471,470,469,468,467,466,465,464,463,462, + 461,460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444, + 443,442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426, + 425,424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408, + 407,406,405,404,403,401,400,399,398,397,396,395,394,393,392,391,390,389, + 388,387,386,385,384,383,382,380,330,329,328,327,325,323,322,321,320,319, + 318,317,316,315,314,313,312,311,310,309,308,305,304,303,302,301,300,297, + 295,292,289,288,287,286,86,35,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,1,0,37, +35,1,0,2,283, +490,488,487,486,485,484,483,475,472,471,470,469,468,467,466,465,464,463,462, + 461,460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444, + 443,442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426, + 425,424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408, + 407,406,405,404,403,401,400,399,398,397,396,395,394,393,392,391,390,389, + 388,387,386,385,384,383,382,380,330,329,328,327,325,323,322,321,320,319, + 318,317,316,315,314,313,312,311,310,309,308,305,304,303,302,301,300,297, + 295,292,289,288,287,286,86,43,35,1,0,22,23,24,25,39,40, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,38,1,0, 1,0, -489,487,486,485,484,483,482,474,471,470,469,468,467,466,465,464,463,462,461, - 460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444,443, - 442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426,425, - 424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408,407, - 406,405,404,403,402,400,399,398,397,396,395,394,393,392,391,390,389,388, - 387,386,385,384,383,382,381,379,329,328,327,326,324,322,321,320,319,318, - 317,316,315,314,313,312,311,310,309,308,307,304,303,302,301,300,299,296, - 294,291,288,287,286,285,85,35,0,2,4,12,27,28,32,33,34,41,43,44,45,48,49, - 50,51,52,53,57,84,289,298, -489,487,486,485,484,483,482,474,471,470,469,468,467,466,465,464,463,462,461, - 460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444,443, - 442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426,425, - 424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408,407, - 406,405,404,403,402,400,399,398,397,396,395,394,393,392,391,390,389,388, - 387,386,385,384,383,382,381,379,329,328,327,326,324,322,321,320,319,318, - 317,316,315,314,313,312,311,310,309,308,307,304,303,302,301,300,299,296, - 294,291,288,287,286,285,85,35,26,1,0,23,24,39,40, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 372,371,370,369,368,367,366,365,364,363,362,361,358,357,356,355,354,348, - 346,344,288,287,286,168,85,35,1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,1,0,30,31, - 33,34,89,90,92,94,95,120,123,126,134,135,137,139,140,143,145,148,149, - 162,163,164,165,167,170,171,172,174,277,278,279,280,281, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,1,0,30,31, - 33,34,89,90,92,94,95,120,123,126,134,135,137,139,140,143,145,148,149, - 162,163,164,165,167,170,171,172,174,277,278,279,280,281, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,1,0,30,31, - 33,34,89,90,92,94,95,120,123,126,134,135,137,139,140,143,145,148,149, - 162,163,164,165,167,170,171,172,174,277,278,279,280,281, -489,487,486,485,484,483,482,479,478,477,474,97,35,1,0,2,87,282,283,284, -489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, -288,287,286,285,35,1,0,2,282,283,284, -288,287,286,285,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, -297,295,35,1,0,2,282,283,284, -480,473,35,1,0,2,282,283,284, -489,488,487,486,485,484,483,482,480,479,478,477,476,473,357,35,1,0,2,282, - 283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 329,328,327,326,324,322,321,320,319,318,317,316,315,314,313,312,311,310, - 309,308,307,306,305,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 329,328,327,326,324,322,321,320,319,318,317,316,315,314,313,312,311,310, - 309,308,307,0,58,59,60,61,62,63,65,66,68,69,70,71,72,73,75,76,77,78,79, - 80,81,82,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198, - 199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234, - 235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252, - 253,254,255,256,257,258,259,261,262,263,264,265,266,267,268,269,270,271, - 272,273,274,275,276, -313,312,311,306,305,0,54,56,62,63,65, -489,487,486,485,484,483,482,474,85,0,4,84,298, -489,487,486,485,484,483,482,474,85,0,4,84,298, -489,487,486,485,484,483,482,474,85,0,4,84,298, -489,487,486,485,484,483,482,474,85,0,4,84,298, -297,295,0,46,47, -480,473,0,11,13,14,15,290,292, -489,488,487,486,485,484,483,482,480,479,478,477,476,473,357,0,11,13,14,15, - 20,290,292,293, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 329,328,327,326,324,322,321,320,319,318,317,316,315,314,313,312,311,310, - 309,308,307,306,305,288,287,286,285,0,54,56, -288,287,286,285,0,27,28,33,34,42, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 372,371,370,369,368,367,366,365,364,363,361,358,357,356,355,354,348,346, - 344,288,287,286,168,85,35,1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 372,371,370,369,368,367,366,365,364,363,362,361,358,357,356,355,354,348, - 346,344,288,287,286,168,85,35,1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 372,371,370,369,368,367,366,365,364,363,362,361,358,357,356,355,354,348, - 346,344,288,287,286,168,85,35,1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, +289,0,42, +490,488,487,486,485,484,483,475,472,471,470,469,468,467,466,465,464,463,462, + 461,460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444, + 443,442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426, + 425,424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408, + 407,406,405,404,403,401,400,399,398,397,396,395,394,393,392,391,390,389, + 388,387,386,385,384,383,382,380,330,329,328,327,325,323,322,321,320,319, + 318,317,316,315,314,313,312,311,310,309,308,305,304,303,302,301,300,297, + 295,292,289,288,287,286,86,35,0,2,4,12,27,28,32,33,34,41,44,45,46,49,50, + 51,52,53,54,58,85,290,299, +490,488,487,486,485,484,483,475,472,471,470,469,468,467,466,465,464,463,462, + 461,460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444, + 443,442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426, + 425,424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408, + 407,406,405,404,403,401,400,399,398,397,396,395,394,393,392,391,390,389, + 388,387,386,385,384,383,382,380,330,329,328,327,325,323,322,321,320,319, + 318,317,316,315,314,313,312,311,310,309,308,305,304,303,302,301,300,297, + 295,292,289,288,287,286,86,43,35,26,1,0,23,24,39,40, +490,488,487,486,485,484,483,475,472,471,470,469,468,467,466,465,464,463,462, + 461,460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444, + 443,442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426, + 425,424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408, + 407,406,405,404,403,401,400,399,398,397,396,395,394,393,392,391,390,389, + 388,387,386,385,384,383,382,380,330,329,328,327,325,323,322,321,320,319, + 318,317,316,315,314,313,312,311,310,309,308,305,304,303,302,301,300,297, + 295,292,289,288,287,286,86,35,26,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 373,372,371,370,369,368,367,366,365,364,363,362,359,358,357,356,355,349, + 347,345,289,288,287,169,86,35,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,1,0,30,31, + 33,34,90,91,93,95,96,121,124,127,135,136,138,140,141,144,146,149,150, + 163,164,165,166,168,171,172,173,175,278,279,280,281,282, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,1,0,30,31, + 33,34,90,91,93,95,96,121,124,127,135,136,138,140,141,144,146,149,150, + 163,164,165,166,168,171,172,173,175,278,279,280,281,282, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,1,0,30,31, + 33,34,90,91,93,95,96,121,124,127,135,136,138,140,141,144,146,149,150, + 163,164,165,166,168,171,172,173,175,278,279,280,281,282, +490,488,487,486,485,484,483,480,479,478,475,98,35,1,0,2,88,283,284,285, +490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, +289,288,287,286,35,1,0,2,283,284,285, +289,288,287,286,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, +298,296,35,1,0,2,283,284,285, +481,474,35,1,0,2,283,284,285, +490,489,488,487,486,485,484,483,481,480,479,478,477,474,358,35,1,0,2,283, + 284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 330,329,328,327,325,323,322,321,320,319,318,317,316,315,314,313,312,311, + 310,309,308,307,306,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 330,329,328,327,325,323,322,321,320,319,318,317,316,315,314,313,312,311, + 310,309,308,0,59,60,61,62,63,64,66,67,69,70,71,72,73,74,76,77,78,79,80, + 81,82,83,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199, + 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235, + 236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253, + 254,255,256,257,258,259,260,262,263,264,265,266,267,268,269,270,271,272, + 273,274,275,276,277, +314,313,312,307,306,0,55,57,63,64,66, +490,488,487,486,485,484,483,475,86,0,4,85,299, +490,488,487,486,485,484,483,475,86,0,4,85,299, +490,488,487,486,485,484,483,475,86,0,4,85,299, +490,488,487,486,485,484,483,475,86,0,4,85,299, +298,296,0,47,48, +481,474,0,11,13,14,15,291,293, +490,489,488,487,486,485,484,483,481,480,479,478,477,474,358,0,11,13,14,15, + 20,291,293,294, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 330,329,328,327,325,323,322,321,320,319,318,317,316,315,314,313,312,311, + 310,309,308,307,306,289,288,287,286,0,55,57, +289,288,287,286,0,27,28,33,34,42, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 373,372,371,370,369,368,367,366,365,364,362,359,358,357,356,355,349,347, + 345,289,288,287,169,86,35,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 373,372,371,370,369,368,367,366,365,364,363,362,359,358,357,356,355,349, + 347,345,289,288,287,169,86,35,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 373,372,371,370,369,368,367,366,365,364,363,362,359,358,357,356,355,349, + 347,345,289,288,287,169,86,35,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455, + 454,453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437, + 436,435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419, + 418,417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400, + 399,398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382, + 380,366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,286,35, + 1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455, + 454,453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437, + 436,435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419, + 418,417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400, + 399,398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382, + 380,366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,286,35, + 1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 373,372,371,370,369,368,367,366,365,364,362,359,358,357,356,355,349,347, + 345,289,288,287,169,86,35,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 373,372,371,370,369,368,367,366,365,364,363,362,359,358,357,356,355,349, + 347,345,289,288,287,169,86,35,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 373,372,371,370,369,368,367,366,365,364,363,362,359,358,357,356,355,349, + 347,345,289,288,287,169,86,35,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 373,372,371,370,369,368,367,366,365,364,362,359,358,357,356,355,349,347, + 345,289,288,287,169,86,35,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455, + 454,453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437, + 436,435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419, + 418,417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400, + 399,398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382, + 380,366,365,364,362,361,360,359,358,357,356,355,354,353,352,351,350,349, + 348,347,346,345,344,343,342,341,340,339,338,337,336,335,334,333,332,331, + 289,288,287,286,35,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 373,372,371,370,369,368,367,366,365,364,363,362,359,358,357,356,355,349, + 347,345,289,288,287,169,86,35,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 373,372,371,370,369,368,367,366,365,364,363,362,359,358,357,356,355,349, + 347,345,289,288,287,169,86,35,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 373,372,371,370,369,368,367,366,365,364,362,359,358,357,356,355,349,347, + 345,289,288,287,169,86,35,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455, + 454,453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437, + 436,435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419, + 418,417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400, + 399,398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382, + 380,373,372,371,370,369,368,367,366,365,364,362,359,358,357,356,355,349, + 347,345,289,288,287,286,169,86,35,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, + 283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,288,287,1,0,33,34,90,91, + 93,95,96,121,124,127,135,136,138,140,141,144,146,149,150,163,164,165, + 166,168,171,172,173,175,278,279,280,281,282, +289,0,32, +289,0,32, +289,0,32, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +376,375,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +479,478,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381, - 379,365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,285,35, - 1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381, - 379,365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,285,35, - 1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 372,371,370,369,368,367,366,365,364,363,361,358,357,356,355,354,348,346, - 344,288,287,286,168,85,35,1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 372,371,370,369,368,367,366,365,364,363,362,361,358,357,356,355,354,348, - 346,344,288,287,286,168,85,35,1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 372,371,370,369,368,367,366,365,364,363,362,361,358,357,356,355,354,348, - 346,344,288,287,286,168,85,35,1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 372,371,370,369,368,367,366,365,364,363,361,358,357,356,355,354,348,346, - 344,288,287,286,168,85,35,1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381, - 379,365,364,363,361,360,359,358,357,356,355,354,353,352,351,350,349,348, - 347,346,345,344,343,342,341,340,339,338,337,336,335,334,333,332,331,330, - 288,287,286,285,35,1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 372,371,370,369,368,367,366,365,364,363,362,361,358,357,356,355,354,348, - 346,344,288,287,286,168,85,35,1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 372,371,370,369,368,367,366,365,364,363,362,361,358,357,356,355,354,348, - 346,344,288,287,286,168,85,35,1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 372,371,370,369,368,367,366,365,364,363,361,358,357,356,355,354,348,346, - 344,288,287,286,168,85,35,1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381, - 379,372,371,370,369,368,367,366,365,364,363,361,358,357,356,355,354,348, - 346,344,288,287,286,285,168,85,35,1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,35,1,0,2, - 282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,287,286,1,0,33,34,89,90, - 92,94,95,120,123,126,134,135,137,139,140,143,145,148,149,162,163,164, - 165,167,170,171,172,174,277,278,279,280,281, -288,0,32, -288,0,32, -288,0,32, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -375,374,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -478,477,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -378,377,376,375,374,35,1,0,2,282,283,284, -378,377,376,375,374,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, -378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, -376,375,374,180,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -375,374,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -376,375,374,180,35,1,0,2,282,283,284, -378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -376,375,374,180,35,1,0,2,282,283,284, -378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, -376,375,374,180,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, -378,376,375,374,178,177,176,175,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -378,376,375,374,178,177,176,175,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -378,376,375,374,178,177,176,175,1,0,39,40, -375,374,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -378,376,375,374,178,177,176,175,1,0,39,40, -478,477,1,0,39,40, -378,377,376,375,374,1,0,39,40, -378,377,376,375,374,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -378,376,375,374,178,177,176,175,1,0,39,40, -378,376,375,374,178,177,176,175,1,0,39,40, -378,376,375,374,178,177,176,175,1,0,39,40, -376,375,374,180,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -375,374,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -376,375,374,180,1,0,39,40, -378,376,375,374,178,177,176,175,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -376,375,374,180,1,0,39,40, -378,376,375,374,178,177,176,175,1,0,39,40, -376,375,374,180,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -378,376,375,374,178,177,176,175,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -378,376,375,374,178,177,176,175,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -378,376,375,374,178,177,176,175,1,0,39,40, -378,376,375,374,178,177,176,175,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,1,0,39,40, -489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,474,85,0,4,84,298, -489,488,487,486,485,484,483,482,479,478,477,476,357,35,1,0,2,282,283,284, -489,488,487,486,485,484,483,482,479,478,477,476,357,0,20,293, -288,287,286,285,35,1,0,2,282,283,284, -288,287,286,285,35,1,0,2,282,283,284, -1,0,39, -475,473,35,1,0,2,282,283,284, -475,473,0,11,13,19,21,290,323, -288,287,286,285,35,1,0,2,282,283,284, -288,287,286,285,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,74,84,98,118, - 119,122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154, - 155,156,298,325,373, -489,487,486,485,484,483,482,474,288,287,286,285,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,474,85,0,4,84,298, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,474,85,0,4,84,298, -489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,474,85,0,4,67,84,298, -489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,474,85,0,4,67,84,298, -489,487,486,485,484,483,482,474,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,474,85,0,4,67,84,298, -489,487,486,485,484,483,482,479,478,477,476,475,474,473,372,371,370,369,368, - 367,366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,473,372,371,370,369,368, - 367,366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,11,13,16,18,19,21, - 55,64,84,118,119,122,125,128,133,136,138,143,144,145,146,147,148,150, - 151,152,153,154,155,156,290,298,323,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,473,372,371,370,369,368, - 367,366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,473,372,371,370,369,368, - 367,366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,11,13,16,18,19,21, - 55,64,84,118,119,122,125,128,133,136,138,143,144,145,146,147,148,150, - 151,152,153,154,155,156,290,298,323,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -288,287,286,285,35,1,0,2,282,283,284, -288,287,286,285,35,1,0,2,282,283,284, -288,287,286,285,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,473,372,371,370,369,368, - 367,366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,11,13,16,18,19,21, - 55,64,84,118,119,122,125,128,133,136,138,143,144,145,146,147,148,150, - 151,152,153,154,155,156,290,298,323,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,473,372,371,370,369,368, - 367,366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,11,13,16,18,19,21, - 55,64,84,118,119,122,125,128,133,136,138,143,144,145,146,147,148,150, - 151,152,153,154,155,156,290,298,323,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,474,364,361,360,358,357,356,355,354, - 352,350,348,346,344,343,341,339,337,335,333,332,330,288,287,286,285,35, - 1,0,2,87,282,283,284, -288,287,286,285,35,1,0,2,282,283,284, -288,287,286,285,35,1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,472,365, - 364,363,361,358,357,356,355,354,348,346,344,287,286,1,0, -288,287,286,285,35,1,0,2,282,283,284, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,287,286,1,0, -330,288,287,286,285,35,1,0,2,282,283,284, -489,488,487,486,485,484,483,482,479,478,477,476,357,288,287,286,35,1,0,2, - 282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,474,471,470,469,468,467,466,465,464,463,462,461, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +379,378,377,376,375,35,1,0,2,283,284,285, +379,378,377,376,375,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, +379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, +377,376,375,181,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +376,375,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +377,376,375,181,35,1,0,2,283,284,285, +379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +377,376,375,181,35,1,0,2,283,284,285, +379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, +377,376,375,181,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, +379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +379,377,376,375,179,178,177,176,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +379,377,376,375,179,178,177,176,1,0,39,40, +376,375,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +379,377,376,375,179,178,177,176,1,0,39,40, +479,478,1,0,39,40, +379,378,377,376,375,1,0,39,40, +379,378,377,376,375,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +379,377,376,375,179,178,177,176,1,0,39,40, +379,377,376,375,179,178,177,176,1,0,39,40, +379,377,376,375,179,178,177,176,1,0,39,40, +377,376,375,181,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +376,375,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +377,376,375,181,1,0,39,40, +379,377,376,375,179,178,177,176,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +377,376,375,181,1,0,39,40, +379,377,376,375,179,178,177,176,1,0,39,40, +377,376,375,181,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +379,377,376,375,179,178,177,176,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +379,377,376,375,179,178,177,176,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +379,377,376,375,179,178,177,176,1,0,39,40, +379,377,376,375,179,178,177,176,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,1,0,39,40, +490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,475,86,0,4,85,299, +490,489,488,487,486,485,484,483,480,479,478,477,358,35,1,0,2,283,284,285, +490,489,488,487,486,485,484,483,480,479,478,477,358,0,20,294, +289,288,287,286,35,1,0,2,283,284,285, +289,288,287,286,35,1,0,2,283,284,285, +289,288,287,286,1,0,39, +476,474,35,1,0,2,283,284,285, +476,474,0,11,13,19,21,291,324, +289,288,287,286,35,1,0,2,283,284,285, +289,288,287,286,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,75,85,99,119, + 120,123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155, + 156,157,299,326,374, +490,488,487,486,485,484,483,475,289,288,287,286,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,475,289,288,287,286,86,0,4,85,299, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,475,86,0,4,85,299, +490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,475,86,0,4,68,85,299, +490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,475,86,0,4,68,85,299, +490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,475,86,0,4,68,85,299, +490,488,487,486,485,484,483,480,479,478,477,476,475,474,373,372,371,370,369, + 368,367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,474,373,372,371,370,369, + 368,367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,11,13,16,18,19,21, + 56,65,85,119,120,123,126,129,134,137,139,144,145,146,147,148,149,151, + 152,153,154,155,156,157,291,299,324,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,474,373,372,371,370,369, + 368,367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,474,373,372,371,370,369, + 368,367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,11,13,16,18,19,21, + 56,65,85,119,120,123,126,129,134,137,139,144,145,146,147,148,149,151, + 152,153,154,155,156,157,291,299,324,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +289,288,287,286,35,1,0,2,283,284,285, +289,288,287,286,35,1,0,2,283,284,285, +289,288,287,286,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,474,373,372,371,370,369, + 368,367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,11,13,16,18,19,21, + 56,65,85,119,120,123,126,129,134,137,139,144,145,146,147,148,149,151, + 152,153,154,155,156,157,291,299,324,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,474,373,372,371,370,369, + 368,367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,11,13,16,18,19,21, + 56,65,85,119,120,123,126,129,134,137,139,144,145,146,147,148,149,151, + 152,153,154,155,156,157,291,299,324,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,475,365,362,361,359,358,357,356,355, + 353,351,349,347,345,344,342,340,338,336,334,333,331,289,288,287,286,35, + 1,0,2,88,283,284,285, +289,288,287,286,35,1,0,2,283,284,285, +289,288,287,286,35,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,473,366, + 365,364,362,359,358,357,356,355,349,347,345,288,287,1,0, +289,288,287,286,35,1,0,2,283,284,285, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,288,287,1,0, +331,289,288,287,286,35,1,0,2,283,284,285, +490,489,488,487,486,485,484,483,480,479,478,477,358,289,288,287,35,1,0,2, + 283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +379,377,376,375,179,178,177,176,0,5,381, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +379,377,376,375,179,178,177,176,0,5,381, +376,375,0,159,161,184, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +379,377,376,375,179,178,177,176,0,5,381, +479,478,0,165,279, +379,378,377,376,375,0,158,159,161,180,182,183, +379,378,377,376,375,0,158,159,161,180,182,183, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +379,377,376,375,179,178,177,176,0,5,381, +379,377,376,375,179,178,177,176,0,5,381, +379,377,376,375,179,178,177,176,0,5,381, +377,376,375,181,0,6,402, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +376,375,0,159,161,184, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +377,376,375,181,0,6,402, +379,377,376,375,179,178,177,176,0,5,381, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +377,376,375,181,0,6,402, +379,377,376,375,179,178,177,176,0,5,381, +377,376,375,181,0,6,402, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +379,377,376,375,179,178,177,176,0,5,381, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +379,377,376,375,179,178,177,176,0,5,381, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +379,377,376,375,179,178,177,176,0,5,381, +379,377,376,375,179,178,177,176,0,5,381, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,0,144,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199, + 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235, + 236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253, + 254,255,256,257,258,259,260,262,263,264,265,266,267,268,269,270,271,272, + 273,274,275,276,277, +480,479,478,476,356,355,169,1,0,3,7,8,16,18,326, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,475,474,473,366,365, + 364,362,359,358,357,356,355,349,347,345,289,288,287,174,1,0,17, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,366, + 365,364,362,359,358,357,356,355,349,347,345,289,288,287,174,1,0,17, +331,289,288,287,286,35,1,0,2,283,284,285, +480,479,478,0, +490,488,483,480,479,478,477,475,472,471,470,469,468,467,466,465,464,463,462, + 461,460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444, + 443,442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426, + 425,424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408, + 407,406,405,404,403,401,400,399,398,397,396,395,394,393,392,391,390,389, + 388,387,386,385,384,383,382,380,377,376,375,365,362,361,360,359,358,357, + 356,355,354,353,352,351,350,349,348,347,346,345,344,343,342,341,340,339, + 338,337,336,335,334,333,332,331,289,288,287,286,160,35,1,0, +480,479,478,0, +480,479,478,0, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,475,474,473,366,365, + 364,362,359,358,357,356,355,349,347,345,289,288,287,174,1,0,17, +480,479,478,0, +483,480,479,478,377,0, +483,480,479,478,472,471,470,469,468,467,466,465,464,463,462,461,460,459,458, + 457,456,455,454,453,452,451,450,449,448,447,446,445,444,443,442,441,440, + 439,438,437,436,435,434,433,432,431,430,429,428,427,426,425,424,423,422, + 421,420,419,418,417,416,415,414,413,412,411,410,409,408,407,406,405,404, + 403,401,400,399,398,397,396,395,394,393,392,391,390,389,388,387,386,385, + 384,383,382,380,365,362,361,360,359,358,357,356,355,354,353,352,351,350, + 349,348,347,346,345,344,343,342,341,340,339,338,337,336,335,334,333,332, + 331,289,288,287,286,35,1,0, +490,483,480,479,478,477,475,472,471,470,469,468,467,466,465,464,463,462,461, 460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444,443, 442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426,425, - 424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408,407, - 406,405,404,403,402,400,399,398,397,396,395,394,393,392,391,390,389,388, - 387,386,385,384,383,382,381,379,329,328,327,326,324,322,321,320,319,318, - 317,316,315,314,313,312,311,310,309,308,307,304,303,302,301,300,299,296, - 294,291,288,287,286,285,85,35,26,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -378,376,375,374,178,177,176,175,0,5,380, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -378,376,375,374,178,177,176,175,0,5,380, -375,374,0,158,160,183, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -378,376,375,374,178,177,176,175,0,5,380, -478,477,0,164,278, -378,377,376,375,374,0,157,158,160,179,181,182, -378,377,376,375,374,0,157,158,160,179,181,182, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -378,376,375,374,178,177,176,175,0,5,380, -378,376,375,374,178,177,176,175,0,5,380, -378,376,375,374,178,177,176,175,0,5,380, -376,375,374,180,0,6,401, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -375,374,0,158,160,183, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -376,375,374,180,0,6,401, -378,376,375,374,178,177,176,175,0,5,380, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -376,375,374,180,0,6,401, -378,376,375,374,178,177,176,175,0,5,380, -376,375,374,180,0,6,401, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -378,376,375,374,178,177,176,175,0,5,380, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -378,376,375,374,178,177,176,175,0,5,380, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -378,376,375,374,178,177,176,175,0,5,380, -378,376,375,374,178,177,176,175,0,5,380, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,0,143,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198, - 199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234, - 235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252, - 253,254,255,256,257,258,259,261,262,263,264,265,266,267,268,269,270,271, - 272,273,274,275,276, -479,478,477,475,355,354,168,1,0,3,7,8,16,18,325, -489,488,487,486,485,484,483,482,481,480,479,478,477,476,474,473,472,365,364, - 363,361,358,357,356,355,354,348,346,344,288,287,286,173,1,0,17, -489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472,365, - 364,363,361,358,357,356,355,354,348,346,344,288,287,286,173,1,0,17, -330,288,287,286,285,35,1,0,2,282,283,284, -479,478,477,0, -487,0, -479,478,477,0, -479,478,477,0, -489,488,487,486,485,484,483,482,481,480,479,478,477,476,474,473,472,365,364, - 363,361,358,357,356,355,354,348,346,344,288,287,286,173,1,0,17, -479,478,477,0, -482,479,478,477,376,0, -482,479,478,477,0, -489,482,479,478,477,476,474,376,375,374,159,0, -365,35,1,0,2,282,283,284, -365,35,1,0,2,282,283,284, -365,35,1,0,2,282,283,284, -365,35,1,0,2,282,283,284, -365,35,1,0,2,282,283,284, -365,35,1,0,2,282,283,284, -365,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 364,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346,345, - 344,343,342,341,340,339,338,337,336,335,334,333,332,331,330,288,287,286, - 285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 364,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346,345, - 344,343,342,341,340,339,338,337,336,335,334,333,332,331,330,288,287,286, - 285,35,1,0,2,282,283,284, -365,0,148, -365,0,148, -365,0,148, -365,0,148, -365,0,148, -365,0,148, -365,0,148, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,355,354,168,85,0,3,4,7,8,9,10,16,18,84,138,146,147,148,150,151, - 152,153,154,155,156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,355,354,168,85,0,3,4,7,8,9,10,16,18,84,138,146,147,148,150,151, - 152,153,154,155,156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,355,354,168,85,0,3,4,7,8,9,10,16,18,84,138,146,147,148,150,151, - 152,153,154,155,156,298,325,373, -360,359,358,357,356,0,137,139,140,141,142, -355,354,0,134,135, -353,352,351,350,0,129,130,131,132, -349,348,0,126,127, -347,346,0,123,124, -345,344,0,120,121, -343,342,341,340,339,338,337,336,335,334,333,332,331,0,99,100,101,102,103, - 104,105,106,107,108,109,110,111,112,113,114,115,116,117, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -288,287,286,285,1,0,39,40, -330,288,287,286,285,1,0,39,40, -330,288,287,286,285,1,0,39,40, -330,288,287,286,285,1,0,39,40, -489,488,487,486,485,484,483,482,481,480,479,478,477,476,474,473,472,365,364, - 363,361,358,357,356,355,354,348,346,344,288,287,286,173,1,0,17, -330,288,287,286,285,1,0,39,40, -330,288,287,286,285,1,0,39,40, -330,288,287,286,285,1,0,39,40, -330,288,287,286,285,1,0,39,40, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,1,0, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 365,364,363,361,358,357,356,355,354,348,346,344,288,287,286,1,0, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,330,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -330,1,0,39,40, -330,1,0,39,40, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 361,288,287,286,285,35,1,0,2,282,283,284, -287,1,0,39,40, -489,482,479,478,477,474,376,375,374,159,0, -488,486,485,484,477,475,0, -489,488,487,486,485,484,483,482,481,480,479,478,477,476,474,473,472,365,364, - 363,361,358,357,356,355,354,348,346,344,288,287,286,173,1,0,17, -482,479,478,477,0, -475,0, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -364,0,149, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,35,1,0,2,282,283,284, -330,0,83, -489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472,365, - 364,363,361,358,357,356,355,354,348,346,344,288,287,286,173,1,0,17, -330,0,83, -330,0,83, -330,0,83, -330,0,83, -330,0,83, -330,0,83, -287,0,34, -364,0,149, -364,0,149, -364,0,149, -364,0,149, -364,0,149, -364,0,149, -364,0,149, -471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,453, - 452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435, - 434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418,417, - 416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,400,399,398, - 397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,379, - 364,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346,345, - 344,343,342,341,340,339,338,337,336,335,334,333,332,331,330,288,287,286, - 285,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,355,354,168,85,0,3,4,7,8,9,10,16,18,84,138,146,147,148,150,151, - 152,153,154,155,156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,355,354,168,85,0,3,4,7,8,9,10,16,18,84,138,146,147,148,150,151, - 152,153,154,155,156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,355,354,168,85,0,3,4,7,8,9,10,16,18,84,138,146,147,148,150,151, - 152,153,154,155,156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,355,354,168,85,0,3,4,7,8,9,10,16,18,84,138,146,147,148,150,151, - 152,153,154,155,156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,355,354,168,85,0,3,4,7,8,9,10,16,18,84,138,146,147,148,150,151, - 152,153,154,155,156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,133,136,138, - 143,144,145,146,147,148,150,151,152,153,154,155,156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,133,136,138, - 143,144,145,146,147,148,150,151,152,153,154,155,156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,128,133,136, - 138,143,144,145,146,147,148,150,151,152,153,154,155,156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,128,133,136, - 138,143,144,145,146,147,148,150,151,152,153,154,155,156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,128,133,136, - 138,143,144,145,146,147,148,150,151,152,153,154,155,156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,128,133,136, - 138,143,144,145,146,147,148,150,151,152,153,154,155,156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,125,128,133, - 136,138,143,144,145,146,147,148,150,151,152,153,154,155,156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,125,128,133, - 136,138,143,144,145,146,147,148,150,151,152,153,154,155,156,298,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,122,125,128, - 133,136,138,143,144,145,146,147,148,150,151,152,153,154,155,156,298,325, - 373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,122,125,128, - 133,136,138,143,144,145,146,147,148,150,151,152,153,154,155,156,298,325, - 373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,119,122,125, - 128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155,156,298, - 325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,84,119,122,125, - 128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155,156,298, - 325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,473,378,376,375,374,372, - 371,370,369,368,367,366,365,363,362,361,355,354,178,177,176,175,168,85, - 35,1,0,2,282,283,284, -489,487,486,485,484,483,482,474,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,473,372,371,370,369,368, - 367,366,365,363,362,361,355,354,168,85,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -378,376,375,374,178,177,176,175,1,0,39,40, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,1,0,39,40, -360,359,358,357,356,0,137,139,140,141,142, -360,359,358,357,356,0,137,139,140,141,142, -355,354,0,134,135, -355,354,0,134,135, -355,354,0,134,135, -355,354,0,134,135, -353,352,351,350,0,129,130,131,132, -353,352,351,350,0,129,130,131,132, -349,348,0,126,127, -349,348,0,126,127, -347,346,0,123,124, -347,346,0,123,124, -489,487,486,485,484,483,482,474,85,0,4,84,298, -489,487,486,485,484,483,482,479,478,477,476,475,474,473,372,371,370,369,368, - 367,366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,11,13,16,18,19,21, - 55,84,118,119,122,125,128,133,136,138,143,144,145,146,147,148,150,151, - 152,153,154,155,156,290,298,323,325,373, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, -378,376,375,374,178,177,176,175,0,5,380, -489,487,486,485,484,483,482,479,478,477,476,475,474,372,371,370,369,368,367, - 366,365,363,362,361,355,354,168,85,0,3,4,7,8,9,10,16,18,55,84,118,119, - 122,125,128,133,136,138,143,144,145,146,147,148,150,151,152,153,154,155, - 156,298,325,373, + 424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,377,376, + 375,365,362,361,360,359,358,357,356,355,354,353,352,351,349,348,347,346, + 345,344,343,342,341,340,339,338,337,336,335,334,333,331,289,288,287,286, + 160,35,1,0, +366,35,1,0,2,283,284,285, +366,35,1,0,2,283,284,285, +366,35,1,0,2,283,284,285, +366,35,1,0,2,283,284,285, +366,35,1,0,2,283,284,285, +366,35,1,0,2,283,284,285, +366,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 365,362,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346, + 345,344,343,342,341,340,339,338,337,336,335,334,333,332,331,289,288,287, + 286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 365,362,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346, + 345,344,343,342,341,340,339,338,337,336,335,334,333,332,331,289,288,287, + 286,35,1,0,2,283,284,285, +366,0,149, +366,0,149, +366,0,149, +366,0,149, +366,0,149, +366,0,149, +366,0,149, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,356,355,169,86,0,3,4,7,8,9,10,16,18,85,139,147,148,149,151,152, + 153,154,155,156,157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,356,355,169,86,0,3,4,7,8,9,10,16,18,85,139,147,148,149,151,152, + 153,154,155,156,157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,356,355,169,86,0,3,4,7,8,9,10,16,18,85,139,147,148,149,151,152, + 153,154,155,156,157,299,326,374, +361,360,359,358,357,0,138,140,141,142,143, +356,355,0,135,136, +354,353,352,351,0,130,131,132,133, +350,349,0,127,128, +348,347,0,124,125, +346,345,0,121,122, +344,343,342,341,340,339,338,337,336,335,334,333,332,289,288,287,286,1,0,100, + 101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +289,288,287,286,1,0,39,40, +331,289,288,287,286,1,0,39,40, +331,289,288,287,286,1,0,39,40, +331,289,288,287,286,1,0,39,40, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,475,474,473,366,365, + 364,362,359,358,357,356,355,349,347,345,289,288,287,174,1,0,17, +331,289,288,287,286,1,0,39,40, +331,289,288,287,286,1,0,39,40, +331,289,288,287,286,1,0,39,40, +331,289,288,287,286,1,0,39,40, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,1,0, +491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, + 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,1,0, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,331,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +331,1,0,39,40, +331,1,0,39,40, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 362,289,288,287,286,35,1,0,2,283,284,285, +288,1,0,39,40, +490,483,480,479,478,475,377,376,375,289,288,287,286,160,35,1,0, +489,487,486,485,478,476,0, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,475,474,473,366,365, + 364,362,359,358,357,356,355,349,347,345,289,288,287,174,1,0,17, +483,480,479,478,0, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,366, + 365,364,362,359,358,357,356,355,349,347,345,289,288,287,174,1,0,17, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +365,0,150, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, +331,0,84, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,366, + 365,364,362,359,358,357,356,355,349,347,345,289,288,287,174,1,0,17, +331,289,288,287,286,0,84, +331,289,288,287,286,0,84, +331,289,288,287,286,0,84, +331,289,288,287,286,0,84, +331,0,84, +331,0,84, +288,0,34, +476,0, +365,0,150, +365,0,150, +365,0,150, +365,0,150, +365,0,150, +365,0,150, +365,0,150, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 365,362,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346, + 345,344,343,342,341,340,339,338,337,336,335,334,333,332,331,289,288,287, + 286,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,356,355,169,86,0,3,4,7,8,9,10,16,18,85,139,147,148,149,151,152, + 153,154,155,156,157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,356,355,169,86,0,3,4,7,8,9,10,16,18,85,139,147,148,149,151,152, + 153,154,155,156,157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,356,355,169,86,0,3,4,7,8,9,10,16,18,85,139,147,148,149,151,152, + 153,154,155,156,157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,356,355,169,86,0,3,4,7,8,9,10,16,18,85,139,147,148,149,151,152, + 153,154,155,156,157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,356,355,169,86,0,3,4,7,8,9,10,16,18,85,139,147,148,149,151,152, + 153,154,155,156,157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,134,137,139, + 144,145,146,147,148,149,151,152,153,154,155,156,157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,134,137,139, + 144,145,146,147,148,149,151,152,153,154,155,156,157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,129,134,137, + 139,144,145,146,147,148,149,151,152,153,154,155,156,157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,129,134,137, + 139,144,145,146,147,148,149,151,152,153,154,155,156,157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,129,134,137, + 139,144,145,146,147,148,149,151,152,153,154,155,156,157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,129,134,137, + 139,144,145,146,147,148,149,151,152,153,154,155,156,157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,126,129,134, + 137,139,144,145,146,147,148,149,151,152,153,154,155,156,157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,126,129,134, + 137,139,144,145,146,147,148,149,151,152,153,154,155,156,157,299,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,123,126,129, + 134,137,139,144,145,146,147,148,149,151,152,153,154,155,156,157,299,326, + 374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,123,126,129, + 134,137,139,144,145,146,147,148,149,151,152,153,154,155,156,157,299,326, + 374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,120,123,126, + 129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156,157,299, + 326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,120,123,126, + 129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156,157,299, + 326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,474,379,377,376,375,373, + 372,371,370,369,368,367,366,364,363,362,356,355,179,178,177,176,169,86, + 35,1,0,2,283,284,285, +490,488,487,486,485,484,483,475,86,1,0,39,40, +490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,366, + 365,364,362,359,358,357,356,355,349,347,345,289,288,287,174,1,0, +490,488,487,486,485,484,483,480,479,478,477,476,475,474,373,372,371,370,369, + 368,367,366,364,363,362,356,355,169,86,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +379,377,376,375,179,178,177,176,1,0,39,40, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,1,0,39,40, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 365,362,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346, + 345,344,343,342,341,340,339,338,337,336,335,334,333,332,331,289,288,287, + 286,1,0,138,140,141,142,143, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 365,362,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346, + 345,344,343,342,341,340,339,338,337,336,335,334,333,332,331,289,288,287, + 286,1,0,138,140,141,142,143, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 365,362,356,355,354,353,352,351,350,349,348,347,346,345,344,343,342,341, + 340,339,338,337,336,335,334,333,332,331,289,288,287,286,1,0,135,136, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 365,362,356,355,354,353,352,351,350,349,348,347,346,345,344,343,342,341, + 340,339,338,337,336,335,334,333,332,331,289,288,287,286,1,0,135,136, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 365,362,356,355,354,353,352,351,350,349,348,347,346,345,344,343,342,341, + 340,339,338,337,336,335,334,333,332,331,289,288,287,286,1,0,135,136, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 365,362,356,355,354,353,352,351,350,349,348,347,346,345,344,343,342,341, + 340,339,338,337,336,335,334,333,332,331,289,288,287,286,1,0,135,136, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 365,362,354,353,352,351,350,349,348,347,346,345,344,343,342,341,340,339, + 338,337,336,335,334,333,332,331,289,288,287,286,1,0,130,131,132,133, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 365,362,354,353,352,351,350,349,348,347,346,345,344,343,342,341,340,339, + 338,337,336,335,334,333,332,331,289,288,287,286,1,0,130,131,132,133, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 365,362,350,349,348,347,346,345,344,343,342,341,340,339,338,337,336,335, + 334,333,332,331,289,288,287,286,1,0,127,128, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 365,362,350,349,348,347,346,345,344,343,342,341,340,339,338,337,336,335, + 334,333,332,331,289,288,287,286,1,0,127,128, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 365,362,348,347,346,345,344,343,342,341,340,339,338,337,336,335,334,333, + 332,331,289,288,287,286,1,0,124,125, +472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, + 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, + 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, + 365,362,348,347,346,345,344,343,342,341,340,339,338,337,336,335,334,333, + 332,331,289,288,287,286,1,0,124,125, +490,488,487,486,485,484,483,475,86,0,4,85,299, +490,488,487,486,485,484,483,480,479,478,477,476,475,474,373,372,371,370,369, + 368,367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,11,13,16,18,19,21, + 56,85,119,120,123,126,129,134,137,139,144,145,146,147,148,149,151,152, + 153,154,155,156,157,291,299,324,326,374, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, +379,377,376,375,179,178,177,176,0,5,381, +490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, + 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, + 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, + 157,299,326,374, }; -static unsigned const char ag_astt[19815] = { +static unsigned const char ag_astt[21732] = { 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, @@ -3338,535 +3449,587 @@ static unsigned const char ag_astt[19815] = { 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,0,1,1,1,1,1,9,9,9,9,9,9,9, - 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,3,9,7,9,5,2,2,2,2,2, - 2,2,2,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,8,1,7,0,1,1,1,1,1,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,3,9,7,9,5,1,7,3,2, + 2,2,2,2,2,2,2,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,1,1,1,1,1,1,1,1,1,3,1,1,1,2,1,7,3,1,1,3,1,3,1,1,1,1,1,1,1,1,2,2,1, - 1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,1,1,1,1,1,1,1,1,1,3,1,1,1,2,1,7,3,1,1,3,1,3,1,1,1,1,1,1,1, + 1,2,2,1,1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,3,1,7,3,3,1,1,5, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,8,3,1,7, + 3,3,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,5,7,1,1,1,3,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,8,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,8,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,8,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,7,1,2,1,1,3,5,5,5,5,5, - 5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1,1,7,1,1,1, - 3,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5, - 1,1,7,1,1,1,3,5,5,1,1,7,1,1,1,3,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,1,1,1,1,1,1,1,8,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,7,1,2,1,1,3,5,5,5,5,5,5, + 5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1,1,7,1,1,1,3, + 5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,1, + 1,7,1,1,1,3,5,5,1,1,7,1,1,1,3,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,2,2,2,1,1,1,1,1,1,1, - 1,1,1,2,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,2, - 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,2,1,1,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,1,1,2,2,2,1,1,2,1,1,2,1,1,2,1,1,1,1,1,7,1,1, - 1,1,1,2,2,2,2,2,2,2,2,2,7,2,1,1,2,2,2,2,2,2,2,2,2,7,2,1,1,2,2,2,2,2,2,2,2, - 2,7,2,1,1,2,2,2,2,2,2,2,2,2,7,2,1,1,1,1,7,2,2,2,2,7,2,1,2,1,1,1,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,7,2,1,2,1,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,2,2,2,1,1,1,1,1,1,1,1, + 1,1,2,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,2,2, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,2,1,1,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,1,2,1,1,1,2,2,2,1,1,2,1,1,2,1,1,2,1,1,1,1,1,7,1,1,1, + 1,1,2,2,2,2,2,2,2,2,2,7,2,1,1,2,2,2,2,2,2,2,2,2,7,2,1,1,2,2,2,2,2,2,2,2,2, + 7,2,1,1,2,2,2,2,2,2,2,2,2,7,2,1,1,1,1,7,2,2,2,2,7,2,1,2,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,7,2,1,2,1,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,5,5,5,5,7,1,1,1,1,1,1,7,3,1,1, - 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, - 5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,5,5,5,5,7,1,1,1,1,1,1,7,3,1,1,1, 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5, 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1, - 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7, 1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1, + 1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,5,3,3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,7,3,3,7,3,3,7,3,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1, - 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1, - 5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5, - 1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5, - 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,5,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,7,3,3,7,3,3,7,3,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5, + 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,1, + 5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7, + 1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, - 5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5, + 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1, - 1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,1,5,7, - 1,1,1,3,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, - 5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7, - 1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7, - 1,1,1,3,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,1,5,7,1, + 1,1,3,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5, 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1, - 1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1, - 3,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, + 1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1, + 1,1,3,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, 5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7, 1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1, 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5, - 5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, - 5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5, + 5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5, + 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1, + 1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5, + 1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5, + 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, - 5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1, - 1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1, - 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7, - 1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,1,5,7,1,1,1,3,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5, + 5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1, + 1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, - 5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,1,7,1,1,8,8,8,8, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5, + 5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,1,7,1,1,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,1,7,1,1,8,8, + 8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, + 8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1, + 7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, + 1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, + 1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,1,7,1,1,8, - 8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8,8, 8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8, - 8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7, 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8, - 8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1, - 7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,5,5,5,5,1,7,1,1,5,5,5,5,5,5,5,5,5,1,1,7,1, - 1,1,3,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2, - 2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1,5,7,1,1,1,3, - 1,4,1,5,5,1,1,7,1,1,1,3,1,2,7,2,1,1,2,1,1,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1, - 1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7, - 1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1, - 2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5, - 5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,4,2,1,1,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2, - 2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,7,2,1,1,1, - 5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5, - 5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1,1,7,1,1,1,3,5,5, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,5,5,5,5,1,7,1,1,5,5,5,5,5,5,5,5,5,1,1,7,1,1, + 1,3,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2, + 2,2,2,2,2,2,2,2,2,2,2,7,2,1,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1,5,7,1,1,1,3,4, + 4,4,4,1,7,1,5,5,1,1,7,1,1,1,3,1,2,7,2,1,1,2,1,1,5,5,5,5,1,1,7,1,1,1,3,5,5, + 5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2, + 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,4,4,4,4,2,7,2,1,1,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2, 2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1, - 1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1, + 1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1, + 3,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2, + 2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,7,2,1,1,1, + 5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2, + 2,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,2,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1,1, + 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1, 1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2, - 1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1, - 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,2,1,1,3,5,5,5,5,1,1,7,1,1,1,3,5,5,5, - 5,1,1,7,1,1,1,3,10,10,1,10,10,10,10,10,10,2,10,10,10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10,10,10,10,10,10,7,5,5,5,5,1,1,7,1,1,1,3,10,10,1,10, - 10,10,10,10,10,10,10,10,10,10,10,10,10,3,10,10,10,10,10,10,10,10,10,10,10, - 10,10,10,10,10,7,5,5,5,5,5,1,5,7,1,1,1,3,10,10,10,10,10,10,10,10,10,10,10, - 10,10,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1, - 2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,5,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,1,1,7,2,2,2,2,2,2,2,2,2,2,2,2, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2, - 1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, - 2,2,2,7,2,1,1,1,7,2,2,1,1,1,1,1,7,2,2,2,2,2,2,1,1,1,1,1,7,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1, - 2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,7,1,1,2,2, - 2,2,2,2,2,2,7,1,1,2,2,2,2,7,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1, - 1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, - 2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,2,2,2,2,2,2,2,2,2,2,2,1,1, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1, - 2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, - 2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7, - 2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1, + 1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 2,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1, + 1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1, 1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1, - 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1, - 1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, - 2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,7,2, - 1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,7,2,1,2,2,2, - 2,2,2,2,2,7,2,1,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2, + 2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,2,1,1,3,5,5,5,5,1,1,7, + 1,1,1,3,5,5,5,5,1,1,7,1,1,1,3,10,10,1,10,10,10,10,10,10,2,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,7,5,5,5,5,1,1,7,1,1, + 1,3,10,10,1,10,10,10,10,10,10,10,10,10,10,10,10,10,10,3,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,7,5,5,5,5,5,1,5,7,1,1,1,3,10,10,10,10,10,10, + 10,10,10,10,10,10,10,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,2,2, + 2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,1,1, + 7,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1, 2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, 2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1, 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1, 1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7, - 2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1, - 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,1, - 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,7,2, - 1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,1,1,7,2,2,1,1,1,1,1,7,2,2,2,2,2,2,1, + 1,1,1,1,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1, + 2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1, + 2,2,2,2,2,2,2,2,7,1,1,2,2,2,2,2,2,2,2,7,1,1,2,2,2,2,7,1,1,2,2,2,2,2,2,2,2, + 2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2, + 2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2, + 2,2,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1, + 2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2, + 1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2, + 1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2, + 2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 7,2,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2, + 1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,2, + 2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2, + 1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 7,2,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2, + 1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 7,2,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,5,3,3,1,1,1,1,1,1,2,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,2,2, - 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,2,1,1,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,1,2,1,1,1,2,2,2,1,1,2,1,1,2,1,1,2,2,2,1,1,1,1,2,9,7, - 2,1,1,2,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,7,2,5,5,5,5,5,1,5,7,1,1,1,3,2,2,2,7,1,4,2,2,2,7,2,2,2,7,2,1,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,10,10,10,5,10, - 10,10,10,2,7,10,10,10,10,4,9,2,10,10,10,2,9,2,2,2,2,4,5,1,1,7,1,1,1,3,5,1, - 1,7,1,1,1,3,5,1,1,7,1,1,1,3,5,1,1,7,1,1,1,3,5,1,1,7,1,1,1,3,5,1,1,7,1,1,1, - 3,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,3,3,1,1,1,1,1,1,2,1,1,1,2,2,1, + 1,1,1,1,1,1,1,2,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 1,1,1,2,1,1,1,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,1,1,2,2,2,1,1,2,1,1, + 2,1,1,2,2,2,1,1,1,1,2,9,7,2,1,1,2,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,1,5,7,1,1,1,3,2,2,2,7,4,1,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,7,2,2,2,7, + 2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,10, + 10,10,5,10,10,10,10,2,7,10,10,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 7,9,2,10,10,10,2,9,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2, + 2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 2,4,4,7,5,1,1,7,1,1,1,3,5,1,1,7,1,1,1,3,5,1,1,7,1,1,1,3,5,1,1,7,1,1,1,3,5, + 1,1,7,1,1,1,3,5,1,1,7,1,1,1,3,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7, - 1,1,7,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2, - 2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1, - 2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2, - 2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2, - 7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1, - 5,1,1,1,1,1,1,5,1,1,1,1,1,1,5,1,1,1,1,5,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,1,7,1,2,8,4,4,4,4,1,7,1,1,8,4,4,4,4,1,7,1, - 1,8,4,4,4,4,1,7,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,7,1,8,5,5,5,5,1,7,1,1,8,5,5,5,5,1,7,1,1,8,5,5,5,5,1,7,1,1,8, - 5,5,5,5,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,3,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,3,2,2,2,7,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,1,7,1, + 1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,5,1,1,1,1,1,1,1,5,1,1,1,1,1,1,5,1,1,1,1,1,1,5,1,1,1,1,5,1,1,1, + 1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1, + 1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,1,7, + 1,2,8,4,4,4,4,1,7,1,1,8,4,4,4,4,1,7,1,1,8,4,4,4,4,1,7,1,1,2,1,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,8,5,5,5,5,1,7,1,1, + 8,5,5,5,5,1,7,1,1,8,5,5,5,5,1,7,1,1,8,5,5,5,5,1,7,1,1,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,7,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7, - 1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,1,7,1, - 1,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,1, - 7,1,1,9,2,10,10,10,9,2,2,2,2,4,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,7,2,7,2,2,2,2,2,2,2,2,2, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2, - 1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, - 2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, - 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1, - 1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8, + 5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,1,7,1,1,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,1,7,1,1,9,2,10,10,10,9,2,2,2,4,4,4,4,2, + 4,4,7,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,7,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,7,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2, + 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,7,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, + 1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, + 1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, - 1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1, - 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1, - 1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1, - 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5, + 8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5, + 7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, + 1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,1,7,1,2,1,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,4,1,1,4,1,1,4, - 1,1,4,1,1,7,1,1,7,1,1,7,1,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,1,1,7,1,1,1,3,1,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,4,4,4,4,7,1,1,4,4,4,4,7,1,1,4,4,4,4,7,1,1, + 4,4,4,4,7,1,1,7,1,1,7,1,1,7,1,2,7,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7, + 2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, - 2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1, - 2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, - 2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1, - 1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1, - 2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2, - 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, - 2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1, - 2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, - 2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,1,1,1,1,1,4,1,1,1,1,1,1, - 1,1,1,1,4,1,1,1,1,1,1,1,4,1,1,1,1,4,1,1,1,1,4,1,1,1,1,4,1,1,1,1,1,1,4,1,1, - 1,1,1,1,1,1,4,1,1,1,1,1,1,4,1,1,1,1,4,1,1,1,1,4,1,1,1,1,4,1,1,2,2,2,2,2,2, - 2,2,2,7,2,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7, - 2,2,1,1,2,1,2,1,2,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2, - 1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, - 7,2,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2, - 1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1 + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2, + 1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7, + 2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1, + 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2, + 1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,1,7,1,1,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1, + 1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1, + 1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,7,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,2,2,2,2,2,2,2,2,2,7,2,1,1,2, + 2,2,2,2,2,2,2,2,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1, + 2,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,2, + 2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1 }; @@ -3876,1423 +4039,1524 @@ static const unsigned short ag_pstt[] = { 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,0,2,2,2,3, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,4, -1,541,543,541,541, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,5,3,0,7,7,7,5,6, +1,543,545,543,543, +7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,6,7,5,3,0,8,8,8,5,7, 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, 13,13,13,13,13,13,13,13,13,14,13,4, 16,18, -82,82,82,82,82,82,82,82,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25, - 25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25, - 25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25, - 25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25, - 25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,15, - 16,17,18,19,20,21,22,23,22,8,9,10,81,1,6,23,26,34,21,13,22,12,11,35,33, - 32,31,30,29,34,35,28,27,25,14,24,14, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,4,5,7,3,3,5,6, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,1,542,8,2,2,2,546, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,9,2,2, - 2,545, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,10,2, - 2,2,544, -36,39,41,42,43,44,45,46,47,48,49,50,51,52,54,60,63,64,66,59,58,37,65,62,53, - 57,55,56,61,40,38,68,8,9,67,11,67,68,67,67,67,67,67,67,67,67,67,67,67, - 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, -36,39,41,42,43,44,45,46,47,48,49,50,51,52,54,60,63,64,66,59,58,37,65,62,53, - 57,55,56,61,40,38,69,8,9,67,12,67,69,67,67,67,67,67,67,67,67,67,67,67, - 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, -36,39,41,42,43,44,45,46,47,48,49,50,51,52,54,60,63,64,66,59,58,37,65,62,53, - 57,55,56,61,40,38,70,8,9,67,13,67,70,67,67,67,67,67,67,67,67,67,67,67, - 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, -83,83,83,83,83,83,83,84,84,84,83,100,1,2,14,2,84,2,2,557, -542,542,542,542,542,542,542,542,542,1,2,15,2,2,2,563, -542,542,542,542,542,542,542,542,542,1,2,16,2,2,2,562, -542,542,542,542,1,2,17,2,2,2,561, -542,542,542,542,1,2,18,2,2,2,560, -542,542,542,542,542,542,542,542,542,1,2,19,2,2,2,559, -542,542,542,542,542,542,542,542,542,1,2,20,2,2,2,558, -542,542,1,2,21,2,2,2,555, -542,542,1,2,22,2,2,2,553, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,2,23,2,2,2, - 550, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,24,2,2,2,548, -71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, - 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114, - 115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132, - 133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150, - 151,152,153,154,155,156,157,158,159,160,161,222,224,226,227,229,231,232, - 233,235,237,239,241,243,245,247,249,251,253,254,255,256,25,257,45,46,47, - 252,250,248,246,244,242,240,238,236,234,62,63,230,228,68,225,223,221, - 221,220,219,218,217,216,215,223,214,213,212,227,228,211,210,209,208,207, - 206,205,204,237,203,202,201,241,242,243,244,200,199,198,197,196,195,194, - 193,192,191,190,189,188,187,186,185,184,183,182,181,180,266,179,178,177, - 270,176,175,174,274,173,172,277,278,279,280,281,282,283,284,285,286,287, - 288,289,290,171,292,170,169,168,296,297,298,167,166,301,165,164,304,163, - 162,307, -247,249,251,261,263,26,264,262,260,259,258, -82,82,82,82,82,82,82,82,81,27,37,265,265, -82,82,82,82,82,82,82,82,81,28,36,265,265, -82,82,82,82,82,82,82,82,81,29,33,265,265, -82,82,82,82,82,82,82,82,81,30,32,265,265, -266,267,31,30,31, -96,91,32,28,270,29,268,271,269, -85,85,85,85,85,85,85,85,96,85,85,85,85,91,85,33,25,270,26,268,27,271,269, - 272, -43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, - 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, - 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, - 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, - 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,261,263,24,24,24,24,34,274, - 273, -275,8,9,10,35,20,13,12,11,19, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,36,2, +9,6,24, +83,83,83,83,83,83,83,83,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27, + 27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27, + 27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27, + 27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27, + 27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,17, + 18,19,20,21,22,23,24,25,22,10,11,12,82,1,7,23,28,36,21,15,22,14,13,37, + 35,34,33,32,31,35,36,30,29,27,16,26,16, +7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,6,7,4,5,8,3,3,5,7, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,1,544,544,9,2,2,2,549, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,1,544,10,2,2,2,548, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,11,2, + 2,2,547, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,12,2, + 2,2,546, +38,41,43,44,45,46,47,48,49,50,51,52,53,54,56,62,65,66,68,61,60,39,67,64,55, + 59,57,58,63,42,40,70,10,11,69,13,69,70,69,69,69,69,69,69,69,69,69,69,69, + 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69, +38,41,43,44,45,46,47,48,49,50,51,52,53,54,56,62,65,66,68,61,60,39,67,64,55, + 59,57,58,63,42,40,71,10,11,69,14,69,71,69,69,69,69,69,69,69,69,69,69,69, + 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69, +38,41,43,44,45,46,47,48,49,50,51,52,53,54,56,62,65,66,68,61,60,39,67,64,55, + 59,57,58,63,42,40,72,10,11,69,15,69,72,69,69,69,69,69,69,69,69,69,69,69, + 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69, +84,84,84,84,84,84,84,85,85,85,84,101,1,2,16,2,85,2,2,559, +544,544,544,544,544,544,544,544,544,1,2,17,2,2,2,565, +544,544,544,544,544,544,544,544,544,1,2,18,2,2,2,564, +544,544,544,544,1,2,19,2,2,2,563, +544,544,544,544,1,2,20,2,2,2,562, +544,544,544,544,544,544,544,544,544,1,2,21,2,2,2,561, +544,544,544,544,544,544,544,544,544,1,2,22,2,2,2,560, +544,544,1,2,23,2,2,2,557, +544,544,1,2,24,2,2,2,555, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,2,25,2,2,2, + 552, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,26,2,2,2,550, +73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97, + 98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115, + 116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133, + 134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151, + 152,153,154,155,156,157,158,159,160,161,162,163,224,226,228,229,231,233, + 234,235,237,239,241,243,245,247,249,251,253,255,256,257,258,27,259,46, + 47,48,254,252,250,248,246,244,242,240,238,236,63,64,232,230,69,227,225, + 223,223,222,221,220,219,218,217,225,216,215,214,229,230,213,212,211,210, + 209,208,207,206,239,205,204,203,243,244,245,246,202,201,200,199,198,197, + 196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,268,181,180, + 179,272,178,177,176,276,175,174,279,280,281,282,283,284,285,286,287,288, + 289,290,291,292,173,294,172,171,170,298,299,300,169,168,303,167,166,306, + 165,164,309, +249,251,253,263,265,28,266,264,262,261,260, +83,83,83,83,83,83,83,83,82,29,38,267,267, +83,83,83,83,83,83,83,83,82,30,37,267,267, +83,83,83,83,83,83,83,83,82,31,34,267,267, +83,83,83,83,83,83,83,83,82,32,33,267,267, +268,269,33,31,32, +97,92,34,29,272,30,270,273,271, +86,86,86,86,86,86,86,86,97,86,86,86,86,92,86,35,26,272,27,270,28,273,271, + 274, +44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, + 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, + 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, + 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, + 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,263,265,25,25,25,25,36,276, + 275, +9,10,11,12,37,20,15,14,13,19, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,38,2, + 2,2,751, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,1,544,39,2,2,2,624, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,1,544,40,2,2,2,605, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,41,2, + 2,2,750, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,1,544,42,2,2,2,607, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,43,2, 2,2,749, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,1,542,37,2,2,2,622, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,1,542,38,2,2,2,603, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,39,2, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,44,2, 2,2,748, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,1,542,40,2,2,2,605, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,41,2, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,45,2, 2,2,747, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,42,2, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,46,2, 2,2,746, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,43,2, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,47,2, 2,2,745, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,44,2, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,48,2, 2,2,744, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,45,2, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,49,2, 2,2,743, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,46,2, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,50,2, 2,2,742, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,47,2, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,51,2, 2,2,741, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,48,2, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,52,2, 2,2,740, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,49,2, - 2,2,739, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,50,2, - 2,2,738, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1, - 542,51,2,2,2,737, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1, - 542,52,2,2,2,736, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,1,542,53,2,2,2,616, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,54,2, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1, + 544,53,2,2,2,739, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1, + 544,54,2,2,2,738, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,1,544,55,2,2,2,618, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,56,2, + 2,2,737, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,1,544,57,2,2,2,616, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,1,544,58,2,2,2,615, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,1,544,59,2,2,2,617, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,1,544,60,2,2,2,625, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,1,544,61,2,2,2,626, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,62,2, + 2,2,736, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,1,544,63,2,2,2,609, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,1,544,64,2,2,2,619, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,65,2, 2,2,735, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,1,542,55,2,2,2,614, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,1,542,56,2,2,2,613, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,1,542,57,2,2,2,615, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,1,542,58,2,2,2,623, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,1,542,59,2,2,2,624, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,60,2, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,66,2, 2,2,734, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,1,542,61,2,2,2,607, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,1,542,62,2,2,2,617, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,63,2, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,1,544,67,2,2,2,622, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,68,2, 2,2,733, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,64,2, - 2,2,732, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,1,542,65,2,2,2,620, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,542,66,2, - 2,2,731, -36,39,41,42,43,44,45,46,47,48,49,50,51,52,54,60,63,64,66,59,58,37,65,62,53, - 57,55,56,61,40,38,8,9,6,8,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6, -11,68,11, -10,69,10, -9,70,9, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,71,2,2,2,730, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,72,2,2,2,729, -542,542,542,542,542,542,542,542,1,542,73,2,2,2,728, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,74,2,2,2,727, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,75,2,2,2,726, -542,542,542,542,542,542,542,542,1,542,76,2,2,2,725, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,77,2,2,2,724, -542,542,1,542,78,2,2,2,723, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,79,2,2,2,722, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,80,2,2,2,721, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,81,2,2,2,720, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,82,2,2,2,719, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,83,2,2,2,718, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,84,2,2,2,717, -542,542,542,542,542,542,542,542,1,542,85,2,2,2,716, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,86,2,2,2,715, -542,542,1,542,87,2,2,2,714, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,88,2,2,2,713, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,89,2,2,2,712, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,90,2,2,2,711, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,91,2,2,2,710, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,92,2,2,2,709, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,93,2,2,2,708, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,94,2,2,2,707, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,95,2,2,2,706, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,96,2,2,2,705, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,97,2,2,2,704, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,98,2,2,2,703, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,99,2,2,2,702, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,100,2,2,2,701, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,101,2,2,2,700, -542,542,542,542,542,1,542,102,2,2,2,699, -542,542,542,542,542,1,542,103,2,2,2,698, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,104,2,2,2,697, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,105,2,2,2,696, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,106,2,2,2,695, -542,542,542,542,542,542,542,542,1,542,107,2,2,2,694, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,108,2,2,2,693, -542,542,542,542,542,542,542,542,1,542,109,2,2,2,692, -542,542,542,542,542,542,542,542,1,542,110,2,2,2,691, -542,542,542,542,1,542,111,2,2,2,690, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,112,2,2,2,689, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,113,2,2,2,688, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,114,2,2,2,687, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,115,2,2,2,686, -542,542,1,542,116,2,2,2,685, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,117,2,2,2,684, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,118,2,2,2,683, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,119,2,2,2,682, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,120,2,2,2,681, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,121,2,2,2,680, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,122,2,2,2,679, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,123,2,2,2,678, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,124,2,2,2,677, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,125,2,2,2,676, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,126,2,2,2,675, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,127,2,2,2,674, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,128,2,2,2,673, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,129,2,2,2,672, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,130,2,2,2,671, -542,542,542,542,1,542,131,2,2,2,670, -542,542,542,542,542,542,542,542,1,542,132,2,2,2,669, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,133,2,2,2,668, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,134,2,2,2,667, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,135,2,2,2,666, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,136,2,2,2,665, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,137,2,2,2,664, -542,542,542,542,1,542,138,2,2,2,663, -542,542,542,542,542,542,542,542,1,542,139,2,2,2,662, -542,542,542,542,1,542,140,2,2,2,661, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,141,2,2,2,659, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,142,2,2,2,658, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,143,2,2,2,657, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,144,2,2,2,656, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,145,2,2,2,655, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,146,2,2,2,654, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,147,2,2,2,653, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,148,2,2,2,652, -542,542,542,542,542,542,542,542,1,542,149,2,2,2,651, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,150,2,2,2,650, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,151,2,2,2,649, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,152,2,2,2,648, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,153,2,2,2,647, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,154,2,2,2,646, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,155,2,2,2,645, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,156,2,2,2,644, -542,542,542,542,542,542,542,542,1,542,157,2,2,2,643, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,158,2,2,2,642, -542,542,542,542,542,542,542,542,1,542,159,2,2,2,641, -542,542,542,542,542,542,542,542,1,542,160,2,2,2,640, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,161,2,2,2,638, -276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276, - 276,276,276,276,276,276,276,276,276,5,162,5,276, -277,277,277,277,277,277,277,277,5,163,5,277, -278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278, - 278,278,278,278,278,278,278,278,278,5,164,5,278, -279,279,279,279,279,279,279,279,5,165,5,279, -280,280,5,166,5,280, -281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281, - 281,281,281,281,281,281,281,281,281,5,167,5,281, +38,41,43,44,45,46,47,48,49,50,51,52,53,54,56,62,65,66,68,61,60,39,67,64,55, + 59,57,58,63,42,40,10,11,6,8,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6, +11,70,11, +10,71,10, +9,72,9, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,73,2,2,2,732, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,74,2,2,2,731, +544,544,544,544,544,544,544,544,1,544,75,2,2,2,730, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,76,2,2,2,729, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,77,2,2,2,728, +544,544,544,544,544,544,544,544,1,544,78,2,2,2,727, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,79,2,2,2,726, +544,544,1,544,80,2,2,2,725, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,81,2,2,2,724, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,82,2,2,2,723, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,83,2,2,2,722, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,84,2,2,2,721, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,85,2,2,2,720, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,86,2,2,2,719, +544,544,544,544,544,544,544,544,1,544,87,2,2,2,718, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,88,2,2,2,717, +544,544,1,544,89,2,2,2,716, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,90,2,2,2,715, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,91,2,2,2,714, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,92,2,2,2,713, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,93,2,2,2,712, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,94,2,2,2,711, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,95,2,2,2,710, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,96,2,2,2,709, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,97,2,2,2,708, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,98,2,2,2,707, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,99,2,2,2,706, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,100,2,2,2,705, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,101,2,2,2,704, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,102,2,2,2,703, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,103,2,2,2,702, +544,544,544,544,544,1,544,104,2,2,2,701, +544,544,544,544,544,1,544,105,2,2,2,700, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,106,2,2,2,699, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,107,2,2,2,698, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,108,2,2,2,697, +544,544,544,544,544,544,544,544,1,544,109,2,2,2,696, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,110,2,2,2,695, +544,544,544,544,544,544,544,544,1,544,111,2,2,2,694, +544,544,544,544,544,544,544,544,1,544,112,2,2,2,693, +544,544,544,544,1,544,113,2,2,2,692, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,114,2,2,2,691, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,115,2,2,2,690, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,116,2,2,2,689, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,117,2,2,2,688, +544,544,1,544,118,2,2,2,687, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,119,2,2,2,686, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,120,2,2,2,685, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,121,2,2,2,684, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,122,2,2,2,683, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,123,2,2,2,682, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,124,2,2,2,681, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,125,2,2,2,680, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,126,2,2,2,679, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,127,2,2,2,678, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,128,2,2,2,677, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,129,2,2,2,676, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,130,2,2,2,675, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,131,2,2,2,674, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,132,2,2,2,673, +544,544,544,544,1,544,133,2,2,2,672, +544,544,544,544,544,544,544,544,1,544,134,2,2,2,671, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,135,2,2,2,670, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,136,2,2,2,669, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,137,2,2,2,668, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,138,2,2,2,667, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,139,2,2,2,666, +544,544,544,544,1,544,140,2,2,2,665, +544,544,544,544,544,544,544,544,1,544,141,2,2,2,664, +544,544,544,544,1,544,142,2,2,2,663, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,143,2,2,2,661, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,144,2,2,2,660, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,145,2,2,2,659, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,146,2,2,2,658, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,147,2,2,2,657, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,148,2,2,2,656, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,149,2,2,2,655, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,150,2,2,2,654, +544,544,544,544,544,544,544,544,1,544,151,2,2,2,653, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,152,2,2,2,652, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,153,2,2,2,651, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,154,2,2,2,650, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,155,2,2,2,649, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,156,2,2,2,648, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,157,2,2,2,647, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,158,2,2,2,646, +544,544,544,544,544,544,544,544,1,544,159,2,2,2,645, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,160,2,2,2,644, +544,544,544,544,544,544,544,544,1,544,161,2,2,2,643, +544,544,544,544,544,544,544,544,1,544,162,2,2,2,642, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,163,2,2,2,640, +277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277, + 277,277,277,277,277,277,277,277,277,5,164,5,277, +278,278,278,278,278,278,278,278,5,165,5,278, +279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279, + 279,279,279,279,279,279,279,279,279,5,166,5,279, +280,280,280,280,280,280,280,280,5,167,5,280, +281,281,5,168,5,281, 282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282, - 282,282,282,282,282,282,282,282,282,5,168,5,282, + 282,282,282,282,282,282,282,282,282,5,169,5,282, 283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283, - 283,283,283,283,283,283,283,283,283,5,169,5,283, -284,284,284,284,284,284,284,284,5,170,5,284, -285,285,5,171,5,285, -286,286,286,286,286,5,172,5,286, -287,287,287,287,287,5,173,5,287, -288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288, - 288,288,288,288,288,288,288,288,288,5,174,5,288, + 283,283,283,283,283,283,283,283,283,5,170,5,283, +284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284, + 284,284,284,284,284,284,284,284,284,5,171,5,284, +285,285,285,285,285,285,285,285,5,172,5,285, +286,286,5,173,5,286, +287,287,287,287,287,5,174,5,287, +288,288,288,288,288,5,175,5,288, 289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289, - 289,289,289,289,289,289,289,289,289,5,175,5,289, -290,290,290,290,290,290,290,290,5,176,5,290, -291,291,291,291,291,291,291,291,5,177,5,291, -292,292,292,292,292,292,292,292,5,178,5,292, -293,293,293,293,5,179,5,293, -294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294, - 294,294,294,294,294,294,294,294,294,5,180,5,294, + 289,289,289,289,289,289,289,289,289,5,176,5,289, +290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,290, + 290,290,290,290,290,290,290,290,290,5,177,5,290, +291,291,291,291,291,291,291,291,5,178,5,291, +292,292,292,292,292,292,292,292,5,179,5,292, +293,293,293,293,293,293,293,293,5,180,5,293, +294,294,294,294,5,181,5,294, 295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295, - 295,295,295,295,295,295,295,295,295,5,181,5,295, + 295,295,295,295,295,295,295,295,295,5,182,5,295, 296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296, - 296,296,296,296,296,296,296,296,296,5,182,5,296, -297,297,5,183,5,297, -298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298, - 298,298,298,298,298,298,298,298,298,5,184,5,298, + 296,296,296,296,296,296,296,296,296,5,183,5,296, +297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, + 297,297,297,297,297,297,297,297,297,5,184,5,297, +298,298,5,185,5,298, 299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299, - 299,299,299,299,299,299,299,299,299,5,185,5,299, + 299,299,299,299,299,299,299,299,299,5,186,5,299, 300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300, - 300,300,300,300,300,300,300,300,300,5,186,5,300, + 300,300,300,300,300,300,300,300,300,5,187,5,300, 301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301, - 301,301,301,301,301,301,301,301,301,5,187,5,301, + 301,301,301,301,301,301,301,301,301,5,188,5,301, 302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302, - 302,302,302,302,302,302,302,302,302,5,188,5,302, + 302,302,302,302,302,302,302,302,302,5,189,5,302, 303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303, - 303,303,303,303,303,303,303,303,303,5,189,5,303, + 303,303,303,303,303,303,303,303,303,5,190,5,303, 304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304, - 304,304,304,304,304,304,304,304,304,5,190,5,304, + 304,304,304,304,304,304,304,304,304,5,191,5,304, 305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305, - 305,305,305,305,305,305,305,305,305,5,191,5,305, + 305,305,305,305,305,305,305,305,305,5,192,5,305, 306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306, - 306,306,306,306,306,306,306,306,306,5,192,5,306, + 306,306,306,306,306,306,306,306,306,5,193,5,306, 307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307, - 307,307,307,307,307,307,307,307,307,5,193,5,307, + 307,307,307,307,307,307,307,307,307,5,194,5,307, 308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, - 308,308,308,308,308,308,308,308,308,5,194,5,308, + 308,308,308,308,308,308,308,308,308,5,195,5,308, 309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309, - 309,309,309,309,309,309,309,309,309,5,195,5,309, + 309,309,309,309,309,309,309,309,309,5,196,5,309, 310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310, - 310,310,310,310,310,310,310,310,310,5,196,5,310, + 310,310,310,310,310,310,310,310,310,5,197,5,310, 311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311, - 311,311,311,311,311,311,311,311,311,5,197,5,311, -312,312,312,312,5,198,5,312, -313,313,313,313,313,313,313,313,5,199,5,313, -314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314, - 314,314,314,314,314,314,314,314,314,5,200,5,314, -315,315,315,315,5,201,5,315, -316,316,316,316,316,316,316,316,5,202,5,316, -317,317,317,317,5,203,5,317, -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, - 318,318,318,318,318,318,318,318,318,5,204,5,318, + 311,311,311,311,311,311,311,311,311,5,198,5,311, +312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312, + 312,312,312,312,312,312,312,312,312,5,199,5,312, +313,313,313,313,5,200,5,313, +314,314,314,314,314,314,314,314,5,201,5,314, +315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, + 315,315,315,315,315,315,315,315,315,5,202,5,315, +316,316,316,316,5,203,5,316, +317,317,317,317,317,317,317,317,5,204,5,317, +318,318,318,318,5,205,5,318, 319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319, - 319,319,319,319,319,319,319,319,319,5,205,5,319, + 319,319,319,319,319,319,319,319,319,5,206,5,319, 320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320, - 320,320,320,320,320,320,320,320,320,5,206,5,320, + 320,320,320,320,320,320,320,320,320,5,207,5,320, 321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, - 321,321,321,321,321,321,321,321,321,5,207,5,321, + 321,321,321,321,321,321,321,321,321,5,208,5,321, 322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322, - 322,322,322,322,322,322,322,322,322,5,208,5,322, + 322,322,322,322,322,322,322,322,322,5,209,5,322, 323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323, - 323,323,323,323,323,323,323,323,323,5,209,5,323, + 323,323,323,323,323,323,323,323,323,5,210,5,323, 324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, - 324,324,324,324,324,324,324,324,324,5,210,5,324, -325,325,325,325,325,325,325,325,5,211,5,325, -326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326, - 326,326,326,326,326,326,326,326,326,5,212,5,326, + 324,324,324,324,324,324,324,324,324,5,211,5,324, +325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325, + 325,325,325,325,325,325,325,325,325,5,212,5,325, +326,326,326,326,326,326,326,326,5,213,5,326, 327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, - 327,327,327,327,327,327,327,327,327,5,213,5,327, + 327,327,327,327,327,327,327,327,327,5,214,5,327, 328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328, - 328,328,328,328,328,328,328,328,328,5,214,5,328, + 328,328,328,328,328,328,328,328,328,5,215,5,328, 329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329, - 329,329,329,329,329,329,329,329,329,5,215,5,329, -330,330,330,330,330,330,330,330,5,216,5,330, -331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331, - 331,331,331,331,331,331,331,331,331,5,217,5,331, -332,332,332,332,332,332,332,332,5,218,5,332, -333,333,333,333,333,333,333,333,5,219,5,333, -334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334, - 334,334,334,334,334,334,334,334,334,5,220,5,334, + 329,329,329,329,329,329,329,329,329,5,216,5,329, +330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330, + 330,330,330,330,330,330,330,330,330,5,217,5,330, +331,331,331,331,331,331,331,331,5,218,5,331, +332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332, + 332,332,332,332,332,332,332,332,332,5,219,5,332, +333,333,333,333,333,333,333,333,5,220,5,333, +334,334,334,334,334,334,334,334,5,221,5,334, 335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, - 335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, - 335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, - 335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, - 335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, - 335,17,17,17,17,5,221,5,335, -542,542,542,542,542,542,542,542,542,1,2,222,2,2,2,588, -82,82,82,82,82,82,82,82,81,223,70,265,265, -542,542,542,542,542,542,542,542,542,542,542,542,542,1,2,224,2,2,2,587, -85,85,85,85,85,85,85,85,85,85,85,85,85,225,69,272, -542,542,542,542,1,2,226,2,2,2,586, -542,542,542,542,1,542,227,2,2,2,585, -336,67,336, -542,542,1,2,229,2,2,2,583, -337,91,230,65,270,338,64,271,339, -542,542,542,542,1,2,231,2,2,2,581, -542,542,542,542,1,2,232,2,2,2,580, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,233,2,2,2,579, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,234,161,151,347,348,162,345,163,346,376,378, - 265,377,375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363, - 362,361,360,359,358,265,357,356, -542,542,542,542,542,542,542,542,542,542,542,542,542,1,2,235,2,2,2,578, -82,82,82,82,82,82,82,82,81,59,60,265,265, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,237,2,2,2,577, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,238,161,151,347,348,162,345,163,346,58,265,375, - 374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360, - 359,358,265,357,356, -542,542,542,542,542,542,542,542,542,1,2,239,2,2,2,576, -82,82,82,82,82,82,82,82,81,240,57,265,265, -542,542,542,542,542,542,542,542,542,1,2,241,2,2,2,575, -82,82,82,82,82,82,82,82,81,242,78,379,265,265, -542,542,542,542,542,542,542,542,542,1,2,243,2,2,2,574, -82,82,82,82,82,82,82,82,81,244,78,380,265,265, -542,542,542,542,542,542,542,542,542,1,2,245,2,2,2,573, -82,82,82,82,82,82,82,82,81,246,78,381,265,265, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,1,2,247,2,2,2,572, -82,82,82,82,82,82,82,173,173,341,340,382,82,91,349,350,351,352,353,354,355, - 59,37,365,65,342,343,182,81,248,161,151,347,348,162,345,72,270,163,346, - 338,383,74,383,265,375,374,373,372,371,370,370,370,369,368,367,150,370, - 366,364,363,362,361,360,359,358,271,265,339,357,356, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,1,2,249,2,2,2,571, -82,82,82,82,82,82,82,173,173,341,340,382,82,91,349,350,351,352,353,354,355, - 59,37,365,65,342,343,182,81,250,161,151,347,348,162,345,72,270,163,346, - 338,384,74,384,265,375,374,373,372,371,370,370,370,369,368,367,150,370, - 366,364,363,362,361,360,359,358,271,265,339,357,356, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,251,2,2,2,570, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,252,161,151,347,348,162,345,163,346,49,265,375, - 374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360, - 359,358,265,357,356, -542,542,542,542,1,2,253,2,2,2,569, -542,542,542,542,1,2,254,2,2,2,568, -542,542,542,542,1,2,255,2,2,2,567, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,256,2,2,2,566, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,257,161,151,347,348,162,345,163,346,44,265,375, - 374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360, - 359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,382,82,91,349,350,351,352,353,354,355, - 59,37,365,65,342,343,182,81,258,161,151,347,348,162,345,72,270,163,346, - 338,385,74,385,265,375,374,373,372,371,370,370,370,369,368,367,150,370, - 366,364,363,362,361,360,359,358,271,265,339,357,356, -82,82,82,82,82,82,82,173,173,341,340,382,82,91,349,350,351,352,353,354,355, - 59,37,365,65,342,343,182,81,259,161,151,347,348,162,345,72,270,163,346, - 338,386,74,386,265,375,374,373,372,371,370,370,370,369,368,367,150,370, - 366,364,363,362,361,360,359,358,271,265,339,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,260,161,151,347,348,162,345,163,346,48,265,375, - 374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360, - 359,358,265,357,356, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,261,2,2,2,565, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,262,161,151,347,348,162,345,163,346,39,265,375, - 374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360, - 359,358,265,357,356, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,263,2,2,2,564, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,264,161,151,347,348,162,345,163,346,38,265,375, - 374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360, - 359,358,265,357,356, -83,83,83,83,83,83,83,84,84,84,83,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,1,2,265,2, - 84,2,2,557, -542,542,542,542,1,2,266,2,2,2,556, -542,542,542,542,1,2,267,2,2,2,554, -97,97,387,97,97,97,97,97,97,95,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, - 97,97,97,97,97,97,97,97,268, -542,542,542,542,1,2,269,2,2,2,551, -92,92,388,92,92,92,92,92,92,92,92,92,92,92,92,92,92,90,92,92,92,92,92,92,92, - 92,92,92,92,92,92,92,92,92,270, -542,542,542,542,542,1,542,271,2,2,2,549, -86,86,86,86,86,86,86,86,86,86,86,86,86,542,542,542,1,2,272,2,2,2,552, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,273,161,151,347,348,162,345,163,346,41,265,375, - 374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360, - 359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,274,161,151,347,348,162,345,163,346,40,265,375, - 374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360, - 359,358,265,357,356, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,1,542,542,275,2,2,2,547, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,276,161,151,347,348,162,345,163,346,306,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -202,199,197,195,201,200,198,196,277,305,389, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,278,161,151,347,348,162,345,163,346,303,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -202,199,197,195,201,200,198,196,279,302,389, -390,391,280,212,213,300, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,281,161,151,347,348,162,345,163,346,299,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,282,161,151,347,348,162,345,163,346,295,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,283,161,151,347,348,162,345,163,346,294,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -202,199,197,195,201,200,198,196,284,293,389, -51,52,285,291,291, -392,393,394,390,391,286,209,207,208,211,276,210, -392,393,394,390,391,287,209,207,208,211,275,210, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,288,161,151,347,348,162,345,163,346,273,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,289,161,151,347,348,162,345,163,346,272,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -202,199,197,195,201,200,198,196,290,271,389, -202,199,197,195,201,200,198,196,291,395,389, -202,199,197,195,201,200,198,196,292,396,389, -205,204,203,206,293,398,397, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,294,161,151,347,348,162,345,163,346,265,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,295,161,151,347,348,162,345,163,346,264,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,296,161,151,347,348,162,345,163,346,263,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -390,391,297,212,213,262, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,298,161,151,347,348,162,345,163,346,261,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,299,161,151,347,348,162,345,163,346,260,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,300,161,151,347,348,162,345,163,346,259,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,301,161,151,347,348,162,345,163,346,258,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,302,161,151,347,348,162,345,163,346,257,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,303,161,151,347,348,162,345,163,346,256,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,304,161,151,347,348,162,345,163,346,255,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,305,161,151,347,348,162,345,163,346,254,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,306,161,151,347,348,162,345,163,346,253,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,307,161,151,347,348,162,345,163,346,252,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,308,161,151,347,348,162,345,163,346,251,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,309,161,151,347,348,162,345,163,346,250,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,310,161,151,347,348,162,345,163,346,249,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,311,161,151,347,348,162,345,163,346,248,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -205,204,203,206,312,247,397, -202,199,197,195,201,200,198,196,313,246,389, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,314,161,151,347,348,162,345,163,346,245,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -205,204,203,206,315,240,397, -202,199,197,195,201,200,198,196,316,239,389, -205,204,203,206,317,238,397, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,318,161,151,347,348,162,345,163,346,236,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,319,161,151,347,348,162,345,163,346,235,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,320,161,151,347,348,162,345,163,346,234,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,321,161,151,347,348,162,345,163,346,233,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,322,161,151,347,348,162,345,163,346,232,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,323,161,151,347,348,162,345,163,346,231,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,324,161,151,347,348,162,345,163,346,230,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -202,199,197,195,201,200,198,196,325,229,389, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,326,161,151,347,348,162,345,163,346,226,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,327,161,151,347,348,162,345,163,346,225,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,328,161,151,347,348,162,345,163,346,224,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,329,161,151,347,348,162,345,163,346,222,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -202,199,197,195,201,200,198,196,330,221,389, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,331,161,151,347,348,162,345,163,346,220,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -202,199,197,195,201,200,198,196,332,219,389, -202,199,197,195,201,200,198,196,333,218,389, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,334,161,151,347,348,162,345,163,346,217,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, - 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114, - 115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132, - 133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150, - 151,152,153,154,155,156,157,158,159,160,161,65,71,215,216,220,219,218, - 217,216,215,223,214,213,212,227,228,211,210,209,208,207,206,205,204,237, - 203,202,201,241,242,243,244,200,199,198,197,196,195,194,193,192,191,190, - 189,188,187,186,185,184,183,182,181,180,266,179,178,177,270,176,175,174, - 274,173,172,277,278,279,280,281,282,283,284,285,286,287,288,289,290,171, - 292,170,169,168,296,297,298,167,166,301,165,164,304,163,162,307, -173,173,341,344,342,343,182,16,336,66,347,399,163,346,357, -183,400,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, - 183,183,183,183,183,183,183,183,183,183,183,183,183,189,183,337,401, -183,400,183,183,183,183,183,183,183,183,183,183,183,183,87,183,183,183,183, - 183,183,183,183,183,183,183,183,183,183,183,183,183,183,189,183,338,89, -542,542,542,542,542,1,542,339,2,2,2,582, -193,193,193,340, -402,173, -172,172,172,342, -171,171,171,343, -183,400,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, - 183,183,183,183,183,183,183,183,183,183,183,183,183,189,183,344,403, -194,194,194,191, -180,180,180,180,166,346, -178,178,178,178,165, -175,179,174,174,174,192,176,167,170,168,169,164, -542,1,2,349,2,2,2,631, -542,1,2,350,2,2,2,630, -542,1,2,351,2,2,2,629, -542,1,2,352,2,2,2,628, -542,1,2,353,2,2,2,627, -542,1,2,354,2,2,2,626, -542,1,2,355,2,2,2,625, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,1,542,356,2,2,2,632, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,1,2,357,2,2,2,584, -59,358,404, -59,359,405, -59,360,406, -59,361,407, -59,362,408, -59,363,409, -59,364,410, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,1,2,365,2,2,2,621, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,366,161,151,347,348,162,345,163,346,411,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 342,343,182,81,367,161,151,347,348,162,345,163,346,265,149,150,149,366, - 364,363,362,361,360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 342,343,182,81,368,161,151,347,348,162,345,163,346,265,148,150,148,366, - 364,363,362,361,360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 342,343,182,81,369,161,151,347,348,162,345,163,346,265,147,150,147,366, - 364,363,362,361,360,359,358,265,357,356, -412,414,62,53,57,137,418,417,416,415,413, -55,56,132,420,419, -421,423,425,427,129,428,426,424,422, -429,61,126,431,430, -432,40,123,434,433, -435,38,122,437,436, -438,439,440,441,442,443,444,445,446,447,448,449,450,102,106,106,106,106,109, - 109,109,112,112,112,115,115,115,118,118,118,121,121,121, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,377,161,151,347,348,162,345,163,346,101,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -17,17,17,17,5,378,5,61, -451,56,56,56,56,5,379,5,451, -451,55,55,55,55,5,380,5,451, -451,54,54,54,54,5,381,5,451, -183,400,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, - 183,183,183,183,183,183,183,183,183,183,183,183,183,189,183,382,452, -453,17,17,17,17,5,383,5,453, + 335,335,335,335,335,335,335,335,335,5,222,5,335, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, + 336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, + 336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, + 336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, + 336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, + 336,17,17,17,17,5,223,5,336, +544,544,544,544,544,544,544,544,544,1,2,224,2,2,2,590, +83,83,83,83,83,83,83,83,82,225,71,267,267, +544,544,544,544,544,544,544,544,544,544,544,544,544,1,2,226,2,2,2,589, +86,86,86,86,86,86,86,86,86,86,86,86,86,227,70,274, +544,544,544,544,1,2,228,2,2,2,588, +544,544,544,544,1,544,229,2,2,2,587, +68,68,68,68,337,230,337, +544,544,1,2,231,2,2,2,585, +338,92,232,66,272,339,65,273,340, +544,544,544,544,1,2,233,2,2,2,583, +544,544,544,544,1,2,234,2,2,2,582, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,235,2,2,2,581, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,236,162,152,348,349,163,346,164,347,377,379, + 267,378,376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364, + 363,362,361,360,359,267,358,357, +544,544,544,544,544,544,544,544,544,544,544,544,544,1,2,237,2,2,2,580, +83,83,83,83,83,83,83,83,60,60,60,60,82,238,61,267,267, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,239,2,2,2,579, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,240,162,152,348,349,163,346,164,347,59,267,376, + 375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361, + 360,359,267,358,357, +544,544,544,544,544,544,544,544,544,1,2,241,2,2,2,578, +83,83,83,83,83,83,83,83,82,242,58,267,267, +544,544,544,544,544,544,544,544,544,1,2,243,2,2,2,577, +83,83,83,83,83,83,83,83,82,244,79,380,267,267, +544,544,544,544,544,544,544,544,544,1,2,245,2,2,2,576, +83,83,83,83,83,83,83,83,82,246,79,381,267,267, +544,544,544,544,544,544,544,544,544,1,2,247,2,2,2,575, +83,83,83,83,83,83,83,83,82,248,79,382,267,267, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,1,2,249,2,2,2,574, +83,83,83,83,83,83,83,174,174,342,341,383,83,92,350,351,352,353,354,355,356, + 61,39,366,67,343,344,184,82,250,162,152,348,349,163,346,73,272,164,347, + 339,74,75,384,267,376,375,374,373,372,371,371,371,370,369,368,151,371, + 367,365,364,363,362,361,360,359,273,267,340,358,357, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,1,2,251,2,2,2,573, +83,83,83,83,83,83,83,174,174,342,341,383,83,92,350,351,352,353,354,355,356, + 61,39,366,67,343,344,184,82,252,162,152,348,349,163,346,73,272,164,347, + 339,74,75,385,267,376,375,374,373,372,371,371,371,370,369,368,151,371, + 367,365,364,363,362,361,360,359,273,267,340,358,357, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,253,2,2,2,572, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,254,162,152,348,349,163,346,164,347,50,267,376, + 375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361, + 360,359,267,358,357, +544,544,544,544,1,2,255,2,2,2,571, +544,544,544,544,1,2,256,2,2,2,570, +544,544,544,544,1,2,257,2,2,2,569, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,258,2,2,2,568, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,259,162,152,348,349,163,346,164,347,45,267,376, + 375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361, + 360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,383,83,92,350,351,352,353,354,355,356, + 61,39,366,67,343,344,184,82,260,162,152,348,349,163,346,73,272,164,347, + 339,74,75,386,267,376,375,374,373,372,371,371,371,370,369,368,151,371, + 367,365,364,363,362,361,360,359,273,267,340,358,357, +83,83,83,83,83,83,83,174,174,342,341,383,83,92,350,351,352,353,354,355,356, + 61,39,366,67,343,344,184,82,261,162,152,348,349,163,346,73,272,164,347, + 339,74,75,387,267,376,375,374,373,372,371,371,371,370,369,368,151,371, + 367,365,364,363,362,361,360,359,273,267,340,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,262,162,152,348,349,163,346,164,347,49,267,376, + 375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361, + 360,359,267,358,357, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,263,2,2,2,567, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,264,162,152,348,349,163,346,164,347,40,267,376, + 375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361, + 360,359,267,358,357, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,265,2,2,2,566, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,266,162,152,348,349,163,346,164,347,39,267,376, + 375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361, + 360,359,267,358,357, +84,84,84,84,84,84,84,85,85,85,84,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,2,267,2, + 85,2,2,559, +544,544,544,544,1,2,268,2,2,2,558, +544,544,544,544,1,2,269,2,2,2,556, +98,98,388,98,98,98,98,98,98,96,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98, + 98,98,98,98,98,98,98,98,270, +544,544,544,544,1,2,271,2,2,2,553, +93,93,389,93,93,93,93,93,93,93,93,93,93,93,93,93,93,91,93,93,93,93,93,93,93, + 93,93,93,93,93,93,93,93,93,272, +544,544,544,544,544,1,544,273,2,2,2,551, +87,87,87,87,87,87,87,87,87,87,87,87,87,544,544,544,1,2,274,2,2,2,554, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,275,162,152,348,349,163,346,164,347,42,267,376, + 375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361, + 360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,276,162,152,348,349,163,346,164,347,41,267,376, + 375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361, + 360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,277,162,152,348,349,163,346,164,347,308,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +204,201,199,197,203,202,200,198,278,307,390, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,279,162,152,348,349,163,346,164,347,305,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +204,201,199,197,203,202,200,198,280,304,390, +391,392,281,214,215,302, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,282,162,152,348,349,163,346,164,347,301,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,283,162,152,348,349,163,346,164,347,297,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,284,162,152,348,349,163,346,164,347,296,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +204,201,199,197,203,202,200,198,285,295,390, +53,54,286,293,293, +393,394,395,391,392,287,211,209,210,213,278,212, +393,394,395,391,392,288,211,209,210,213,277,212, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,289,162,152,348,349,163,346,164,347,275,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,290,162,152,348,349,163,346,164,347,274,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +204,201,199,197,203,202,200,198,291,273,390, +204,201,199,197,203,202,200,198,292,396,390, +204,201,199,197,203,202,200,198,293,397,390, +207,206,205,208,294,399,398, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,295,162,152,348,349,163,346,164,347,267,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,296,162,152,348,349,163,346,164,347,266,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,297,162,152,348,349,163,346,164,347,265,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +391,392,298,214,215,264, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,299,162,152,348,349,163,346,164,347,263,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,300,162,152,348,349,163,346,164,347,262,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,301,162,152,348,349,163,346,164,347,261,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,302,162,152,348,349,163,346,164,347,260,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,303,162,152,348,349,163,346,164,347,259,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,304,162,152,348,349,163,346,164,347,258,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,305,162,152,348,349,163,346,164,347,257,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,306,162,152,348,349,163,346,164,347,256,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,307,162,152,348,349,163,346,164,347,255,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,308,162,152,348,349,163,346,164,347,254,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,309,162,152,348,349,163,346,164,347,253,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,310,162,152,348,349,163,346,164,347,252,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,311,162,152,348,349,163,346,164,347,251,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,312,162,152,348,349,163,346,164,347,250,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +207,206,205,208,313,249,398, +204,201,199,197,203,202,200,198,314,248,390, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,315,162,152,348,349,163,346,164,347,247,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +207,206,205,208,316,242,398, +204,201,199,197,203,202,200,198,317,241,390, +207,206,205,208,318,240,398, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,319,162,152,348,349,163,346,164,347,238,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,320,162,152,348,349,163,346,164,347,237,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,321,162,152,348,349,163,346,164,347,236,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,322,162,152,348,349,163,346,164,347,235,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,323,162,152,348,349,163,346,164,347,234,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,324,162,152,348,349,163,346,164,347,233,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,325,162,152,348,349,163,346,164,347,232,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +204,201,199,197,203,202,200,198,326,231,390, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,327,162,152,348,349,163,346,164,347,228,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,328,162,152,348,349,163,346,164,347,227,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,329,162,152,348,349,163,346,164,347,226,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,330,162,152,348,349,163,346,164,347,224,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +204,201,199,197,203,202,200,198,331,223,390, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,332,162,152,348,349,163,346,164,347,222,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +204,201,199,197,203,202,200,198,333,221,390, +204,201,199,197,203,202,200,198,334,220,390, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,335,162,152,348,349,163,346,164,347,219,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97, + 98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115, + 116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133, + 134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151, + 152,153,154,155,156,157,158,159,160,161,162,163,67,72,217,218,222,221, + 220,219,218,217,225,216,215,214,229,230,213,212,211,210,209,208,207,206, + 239,205,204,203,243,244,245,246,202,201,200,199,198,197,196,195,194,193, + 192,191,190,189,188,187,186,185,184,183,182,268,181,180,179,272,178,177, + 176,276,175,174,279,280,281,282,283,284,285,286,287,288,289,290,291,292, + 173,294,172,171,170,298,299,300,169,168,303,167,166,306,165,164,309, +174,174,342,345,343,344,184,16,337,67,348,400,164,347,358, +185,401,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, + 185,185,185,185,185,185,185,185,185,185,185,185,185,191,185,338,402, +185,401,185,185,185,185,185,185,185,185,185,185,185,185,88,185,185,185,185, + 185,185,185,185,185,185,185,185,185,185,185,185,185,185,191,185,339,90, +544,544,544,544,544,1,544,340,2,2,2,584, +195,195,195,341, +174,403,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, + 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, + 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, + 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, + 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, + 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, + 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, + 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,342, +173,173,173,343, +172,172,172,344, +185,401,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, + 185,185,185,185,185,185,185,185,185,185,185,185,185,191,185,345,404, +196,196,196,193, +181,181,181,181,167,347, +179,179,179,179,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, + 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, + 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, + 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, + 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, + 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, + 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, + 166,166,166,166,166,166,166,348, +176,180,175,175,175,194,177,165,165,165,165,165,165,165,165,165,165,165,165, + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,168,171, + 169,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, + 170,165,165,349, +544,1,2,350,2,2,2,633, +544,1,2,351,2,2,2,632, +544,1,2,352,2,2,2,631, +544,1,2,353,2,2,2,630, +544,1,2,354,2,2,2,629, +544,1,2,355,2,2,2,628, +544,1,2,356,2,2,2,627, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,1,544,357,2,2,2,634, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,1,2,358,2,2,2,586, +61,359,405, +61,360,406, +61,361,407, +61,362,408, +61,363,409, +61,364,410, +61,365,411, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,1,2,366,2,2,2,623, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,367,162,152,348,349,163,346,164,347,412,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 343,344,184,82,368,162,152,348,349,163,346,164,347,267,150,151,150,367, + 365,364,363,362,361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 343,344,184,82,369,162,152,348,349,163,346,164,347,267,149,151,149,367, + 365,364,363,362,361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 343,344,184,82,370,162,152,348,349,163,346,164,347,267,148,151,148,367, + 365,364,363,362,361,360,359,267,358,357, +413,415,64,55,59,138,419,418,417,416,414, +57,58,133,421,420, +422,424,426,428,130,429,427,425,423, +430,63,127,432,431, +433,42,124,435,434, +436,40,123,438,437, +439,440,441,442,443,444,445,446,447,448,449,450,451,103,103,103,103,103,377, + 107,107,107,107,110,110,110,113,113,113,116,116,116,119,119,119,122,122, + 122, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,378,162,152,348,349,163,346,164,347,102,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +17,17,17,17,5,379,5,62, +452,57,57,57,57,5,380,5,452, +452,56,56,56,56,5,381,5,452, +452,55,55,55,55,5,382,5,452, +185,401,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, + 185,185,185,185,185,185,185,185,185,185,185,185,185,191,185,383,453, 454,17,17,17,17,5,384,5,454, 455,17,17,17,17,5,385,5,455, 456,17,17,17,17,5,386,5,456, -98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98, - 98,98,98,98,98,98,99,98,98,98,387, -93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93, - 93,93,93,93,93,93,94,93,93,93,388, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,1,542,389,2,2,2,639, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,390,2,2,2,634, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,391,2,2,2,633, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,392,2,2,2,637, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,393,2,2,2,636, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,394,2,2,2,635, -457,5,395,5,457, +457,17,17,17,17,5,387,5,457, +99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, + 99,99,99,99,99,99,100,99,99,99,388, +94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94, + 94,94,94,94,94,94,95,94,94,94,389, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,1,544,390,2,2,2,641, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,391,2,2,2,636, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,392,2,2,2,635, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,393,2,2,2,639, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,394,2,2,2,638, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,395,2,2,2,637, 458,5,396,5,458, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,1,542,397,2,2,2,660, -459,5,398,5,459, -175,179,174,174,174,176,167,170,168,169,164, -184,186,187,185,188,190,400, -183,400,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183, - 183,183,183,183,183,183,183,183,183,183,183,183,183,189,183,401,88, -177,177,177,177,402, -181,403, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,404,161,151,347,348,162,345,163,346,460,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,405,161,151,347,348,162,345,163,346,461,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,406,161,151,347,348,162,345,163,346,462,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,407,161,151,347,348,162,345,163,346,463,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,408,161,151,347,348,162,345,163,346,464,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,409,161,151,347,348,162,345,163,346,465,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,410,161,151,347,348,162,345,163,346,466,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -58,411,467, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,1,542,412,2,2,2,619, -468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, - 468,468,468,468,468,468,5,413,5,468, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,1,542,414,2,2,2,618, -469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469, - 469,469,469,469,469,469,5,415,5,469, +459,5,397,5,459, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,1,544,398,2,2,2,662, +460,5,399,5,460, +176,180,175,175,175,177,168,171,169,165,165,165,165,170,165,165,400, +186,188,189,187,190,192,401, +185,401,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, + 185,185,185,185,185,185,185,185,185,185,185,185,185,191,185,402,89, +178,178,178,178,403, +185,401,185,185,185,185,185,185,185,185,185,185,185,185,182,185,185,185,185, + 185,185,185,185,185,185,185,185,185,185,185,185,185,185,191,185,404,461, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,405,162,152,348,349,163,346,164,347,462,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,406,162,152,348,349,163,346,164,347,463,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,407,162,152,348,349,163,346,164,347,464,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,408,162,152,348,349,163,346,164,347,465,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,409,162,152,348,349,163,346,164,347,466,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,410,162,152,348,349,163,346,164,347,467,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,411,162,152,348,349,163,346,164,347,468,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +60,412,469, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,1,544,413,2,2,2,621, 470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470, - 470,470,470,470,470,470,5,416,5,470, + 470,470,470,470,470,470,5,414,5,470, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,1,544,415,2,2,2,620, 471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471, - 471,471,471,471,471,471,5,417,5,471, + 471,471,471,471,471,471,5,416,5,471, 472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, - 472,472,472,472,472,472,5,418,5,472, + 472,472,472,472,472,472,5,417,5,472, 473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, - 473,473,473,473,473,473,473,473,473,5,419,5,473, + 473,473,473,473,473,473,5,418,5,473, 474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474, - 474,474,474,474,474,474,474,474,474,5,420,5,474, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,421,2,2,2,612, + 474,474,474,474,474,474,5,419,5,474, 475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, - 475,475,475,475,475,475,475,475,475,5,422,5,475, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,423,2,2,2,611, + 475,475,475,475,475,475,475,475,475,5,420,5,475, 476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, - 476,476,476,476,476,476,476,476,476,5,424,5,476, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,425,2,2,2,610, + 476,476,476,476,476,476,476,476,476,5,421,5,476, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,422,2,2,2,614, 477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477, - 477,477,477,477,477,477,477,477,477,5,426,5,477, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,427,2,2,2,609, + 477,477,477,477,477,477,477,477,477,5,423,5,477, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,424,2,2,2,613, 478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478, - 478,478,478,478,478,478,478,478,478,5,428,5,478, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,429,2,2,2,608, + 478,478,478,478,478,478,478,478,478,5,425,5,478, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,426,2,2,2,612, 479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, - 479,479,479,479,479,479,479,479,479,5,430,5,479, + 479,479,479,479,479,479,479,479,479,5,427,5,479, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,428,2,2,2,611, 480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480, - 480,480,480,480,480,480,480,480,480,5,431,5,480, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,432,2,2,2,606, + 480,480,480,480,480,480,480,480,480,5,429,5,480, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,430,2,2,2,610, 481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481, - 481,481,481,481,481,481,481,481,481,5,433,5,481, + 481,481,481,481,481,481,481,481,481,5,431,5,481, 482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, - 482,482,482,482,482,482,482,482,482,5,434,5,482, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,542,435,2,2,2,604, + 482,482,482,482,482,482,482,482,482,5,432,5,482, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,433,2,2,2,608, 483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, - 483,483,483,483,483,483,483,483,483,5,436,5,483, + 483,483,483,483,483,483,483,483,483,5,434,5,483, 484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, - 484,484,484,484,484,484,484,484,484,5,437,5,484, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,438,2,2,2,602, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,439,2,2,2,601, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,440,2,2,2,600, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,441,2,2,2,599, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,442,2,2,2,598, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,443,2,2,2,597, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,444,2,2,2,596, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,445,2,2,2,595, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,446,2,2,2,594, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,447,2,2,2,593, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,448,2,2,2,592, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,449,2,2,2,591, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,1,2,450,2,2,2,590, -485,451,486, -183,400,183,183,183,183,183,183,183,183,183,183,183,183,181,183,183,183,183, - 183,183,183,183,183,183,183,183,183,183,183,183,183,183,189,183,452,88, -485,53,487, -485,51,487, -485,52,487, -485,50,487, -485,457,488, -485,458,489, -8,459,490, -58,460,160, -58,461,159, -58,462,158, -58,463,157, -58,464,156, -58,465,155, -58,466,154, + 484,484,484,484,484,484,484,484,484,5,435,5,484, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,544,436,2,2,2,606, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, + 485,485,485,485,485,485,485,485,485,5,437,5,485, +486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, + 486,486,486,486,486,486,486,486,486,5,438,5,486, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,439,2,2,2,604, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,440,2,2,2,603, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,441,2,2,2,602, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,442,2,2,2,601, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,443,2,2,2,600, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,444,2,2,2,599, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,445,2,2,2,598, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,446,2,2,2,597, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,447,2,2,2,596, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,448,2,2,2,595, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,449,2,2,2,594, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,450,2,2,2,593, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,1,2,451,2,2,2,592, +487,452,488, +185,401,185,185,185,185,185,185,185,185,185,185,185,185,182,185,185,185,185, + 185,185,185,185,185,185,185,185,185,185,185,185,185,185,191,185,453,489, +487,54,54,54,54,454,490, +487,52,52,52,52,455,490, +487,53,53,53,53,456,490, +487,51,51,51,51,457,490, +487,458,491, +487,459,492, +10,460,493, +183,461, +60,462,161, +60,463,160, +60,464,159, +60,465,158, +60,466,157, +60,467,156, +60,468,155, 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,5,467,5,153, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 342,343,182,81,468,161,151,347,348,162,345,163,346,265,145,150,145,366, - 364,363,362,361,360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 342,343,182,81,469,161,151,347,348,162,345,163,346,265,144,150,144,366, - 364,363,362,361,360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 342,343,182,81,470,161,151,347,348,162,345,163,346,265,143,150,143,366, - 364,363,362,361,360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 342,343,182,81,471,161,151,347,348,162,345,163,346,265,142,150,142,366, - 364,363,362,361,360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 342,343,182,81,472,161,151,347,348,162,345,163,346,265,141,150,141,366, - 364,363,362,361,360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,473,161,151,347,348,162,345,163,346,265,491, - 491,491,369,368,367,150,491,366,364,363,362,361,360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,474,161,151,347,348,162,345,163,346,265,492, - 492,492,369,368,367,150,492,366,364,363,362,361,360,359,358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,475,161,151,347,348,162,345,163,346,265,493, - 370,370,370,369,368,367,150,370,366,364,363,362,361,360,359,358,265,357, - 356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,476,161,151,347,348,162,345,163,346,265,494, - 370,370,370,369,368,367,150,370,366,364,363,362,361,360,359,358,265,357, - 356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,477,161,151,347,348,162,345,163,346,265,495, - 370,370,370,369,368,367,150,370,366,364,363,362,361,360,359,358,265,357, - 356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,478,161,151,347,348,162,345,163,346,265,496, - 370,370,370,369,368,367,150,370,366,364,363,362,361,360,359,358,265,357, - 356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,479,161,151,347,348,162,345,163,346,265,497, - 371,370,370,370,369,368,367,150,370,366,364,363,362,361,360,359,358,265, - 357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,480,161,151,347,348,162,345,163,346,265,498, - 371,370,370,370,369,368,367,150,370,366,364,363,362,361,360,359,358,265, - 357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,481,161,151,347,348,162,345,163,346,265,499, - 372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360,359,358, - 265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,482,161,151,347,348,162,345,163,346,265,500, - 372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360,359,358, - 265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,483,161,151,347,348,162,345,163,346,265,501, - 373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360,359, - 358,265,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,484,161,151,347,348,162,345,163,346,265,502, - 373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361,360,359, - 358,265,357,356, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, - 1,542,485,2,2,2,589, -503,503,503,503,503,503,503,503,503,5,486,5,503, -504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504, - 504,504,504,504,504,504,504,504,504,504,5,487,5,504, -505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505, - 505,505,505,505,505,505,505,505,505,5,488,5,505, -506,506,506,506,506,506,506,506,5,489,5,506, + 17,17,17,17,17,17,17,5,469,5,154, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 343,344,184,82,470,162,152,348,349,163,346,164,347,267,146,151,146,367, + 365,364,363,362,361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 343,344,184,82,471,162,152,348,349,163,346,164,347,267,145,151,145,367, + 365,364,363,362,361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 343,344,184,82,472,162,152,348,349,163,346,164,347,267,144,151,144,367, + 365,364,363,362,361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 343,344,184,82,473,162,152,348,349,163,346,164,347,267,143,151,143,367, + 365,364,363,362,361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 343,344,184,82,474,162,152,348,349,163,346,164,347,267,142,151,142,367, + 365,364,363,362,361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,475,162,152,348,349,163,346,164,347,267,494, + 494,494,370,369,368,151,494,367,365,364,363,362,361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,476,162,152,348,349,163,346,164,347,267,495, + 495,495,370,369,368,151,495,367,365,364,363,362,361,360,359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,477,162,152,348,349,163,346,164,347,267,496, + 371,371,371,370,369,368,151,371,367,365,364,363,362,361,360,359,267,358, + 357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,478,162,152,348,349,163,346,164,347,267,497, + 371,371,371,370,369,368,151,371,367,365,364,363,362,361,360,359,267,358, + 357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,479,162,152,348,349,163,346,164,347,267,498, + 371,371,371,370,369,368,151,371,367,365,364,363,362,361,360,359,267,358, + 357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,480,162,152,348,349,163,346,164,347,267,499, + 371,371,371,370,369,368,151,371,367,365,364,363,362,361,360,359,267,358, + 357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,481,162,152,348,349,163,346,164,347,267,500, + 372,371,371,371,370,369,368,151,371,367,365,364,363,362,361,360,359,267, + 358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,482,162,152,348,349,163,346,164,347,267,501, + 372,371,371,371,370,369,368,151,371,367,365,364,363,362,361,360,359,267, + 358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,483,162,152,348,349,163,346,164,347,267,502, + 373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361,360,359, + 267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,484,162,152,348,349,163,346,164,347,267,503, + 373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361,360,359, + 267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,485,162,152,348,349,163,346,164,347,267,504, + 374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361,360, + 359,267,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,486,162,152,348,349,163,346,164,347,267,505, + 374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361,360, + 359,267,358,357, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, + 1,544,487,2,2,2,591, +506,506,506,506,506,506,506,506,506,5,488,5,506, +89,89,89,89,89,89,89,89,89,89,89,89,89,89,183,89,89,89,89,89,89,89,89,89,89, + 89,89,89,89,89,89,89,89,89,89,489, 507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, - 507,507,507,507,507,507,507,507,507,5,490,5,507, -412,414,62,53,57,139,418,417,416,415,413, -412,414,62,53,57,138,418,417,416,415,413, -55,56,136,420,419, -55,56,135,420,419, -55,56,134,420,419, -55,56,133,420,419, -421,423,425,427,131,428,426,424,422, -421,423,425,427,130,428,426,424,422, -429,61,128,431,430, -429,61,127,431,430, -432,40,125,434,433, -432,40,124,434,433, -82,82,82,82,82,82,82,82,81,503,79,265,265, -82,82,82,82,82,82,82,173,173,341,340,382,82,91,349,350,351,352,353,354,355, - 59,37,365,65,342,343,182,81,504,161,151,347,348,162,345,76,270,163,346, - 338,77,75,265,375,374,373,372,371,370,370,370,369,368,367,150,370,366, - 364,363,362,361,360,359,358,271,265,339,357,356, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,505,161,151,347,348,162,345,163,346,269,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, -202,199,197,195,201,200,198,196,506,268,389, -82,82,82,82,82,82,82,173,173,341,340,344,82,349,350,351,352,353,354,355,59, - 37,365,65,342,343,182,81,507,161,151,347,348,162,345,163,346,267,265, - 375,374,373,372,371,370,370,370,369,368,367,150,370,366,364,363,362,361, - 360,359,358,265,357,356, + 507,507,507,507,507,507,507,507,507,507,5,490,5,507, +508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508, + 508,508,508,508,508,508,508,508,508,5,491,5,508, +509,509,509,509,509,509,509,509,5,492,5,509, +510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, + 510,510,510,510,510,510,510,510,510,5,493,5,510, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, + 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, + 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, + 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, + 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, + 140,140,413,415,64,55,59,140,140,140,140,140,140,140,140,140,140,140, + 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, + 140,140,494,419,418,417,416,414, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, + 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, + 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, + 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, + 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, + 139,139,413,415,64,55,59,139,139,139,139,139,139,139,139,139,139,139, + 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, + 139,139,495,419,418,417,416,414, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, + 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, + 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, + 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, + 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, + 137,137,57,58,137,137,137,137,137,137,137,137,137,137,137,137,137,137, + 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,496,421,420, +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, + 136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, + 136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, + 136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, + 136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, + 136,136,57,58,136,136,136,136,136,136,136,136,136,136,136,136,136,136, + 136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,497,421,420, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, + 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, + 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, + 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, + 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, + 135,135,57,58,135,135,135,135,135,135,135,135,135,135,135,135,135,135, + 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,498,421,420, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, + 134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, + 134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, + 134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, + 134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, + 134,134,57,58,134,134,134,134,134,134,134,134,134,134,134,134,134,134, + 134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,499,421,420, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, + 132,132,422,424,426,428,132,132,132,132,132,132,132,132,132,132,132,132, + 132,132,132,132,132,132,132,132,132,132,132,132,132,500,429,427,425,423, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, + 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, + 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, + 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, + 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, + 131,131,422,424,426,428,131,131,131,131,131,131,131,131,131,131,131,131, + 131,131,131,131,131,131,131,131,131,131,131,131,131,501,429,427,425,423, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,430,63,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,502,432,431, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, + 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, + 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, + 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, + 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, + 128,128,430,63,128,128,128,128,128,128,128,128,128,128,128,128,128,128, + 128,128,128,128,128,128,128,128,128,503,432,431, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, + 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, + 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, + 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, + 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, + 126,126,433,42,126,126,126,126,126,126,126,126,126,126,126,126,126,126, + 126,126,126,126,126,126,126,504,435,434, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, + 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, + 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, + 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, + 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, + 125,125,433,42,125,125,125,125,125,125,125,125,125,125,125,125,125,125, + 125,125,125,125,125,125,125,505,435,434, +83,83,83,83,83,83,83,83,82,506,80,267,267, +83,83,83,83,83,83,83,174,174,342,341,383,83,92,350,351,352,353,354,355,356, + 61,39,366,67,343,344,184,82,507,162,152,348,349,163,346,77,272,164,347, + 339,78,76,267,376,375,374,373,372,371,371,371,370,369,368,151,371,367, + 365,364,363,362,361,360,359,273,267,340,358,357, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,508,162,152,348,349,163,346,164,347,271,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, +204,201,199,197,203,202,200,198,509,270,390, +83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, + 39,366,67,343,344,184,82,510,162,152,348,349,163,346,164,347,269,267, + 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, + 361,360,359,267,358,357, }; static const unsigned short ag_sbt[] = { - 0, 141, 178, 183, 326, 363, 365, 523, 665, 716, 757, 798, 869, 940, - 1011,1031,1047,1063,1074,1085,1101,1117,1126,1135,1157,1282,1509,1520, - 1533,1546,1559,1572,1577,1586,1610,1731,1741,1782,1832,1883,1924,1975, - 2016,2057,2098,2139,2180,2221,2262,2303,2344,2385,2518,2651,2701,2742, - 2793,2844,2894,3050,3101,3142,3193,3243,3284,3325,3467,3508,3576,3579, - 3582,3585,3688,3723,3738,3841,3876,3891,3994,4003,4038,4141,4244,4347, - 4382,4417,4432,4535,4544,4647,4750,4853,4956,5059,5162,5265,5368,5471, - 5574,5677,5780,5883,5986,5998,6010,6113,6148,6183,6198,6301,6316,6331, - 6342,6445,6480,6515,6550,6559,6594,6629,6664,6699,6734,6769,6804,6839, - 6874,6909,6944,6979,7014,7049,7060,7075,7110,7213,7316,7419,7522,7533, - 7548,7559,7662,7697,7732,7767,7802,7837,7872,7907,7922,8025,8128,8163, - 8198,8233,8336,8371,8386,8421,8436,8451,8486,8518,8530,8562,8574,8580, - 8612,8644,8676,8688,8694,8703,8712,8744,8776,8788,8800,8812,8820,8852, - 8884,8916,8922,8954,8986,9018,9050,9082,9114,9146,9178,9210,9242,9274, - 9306,9338,9370,9378,9390,9422,9430,9442,9450,9482,9514,9546,9578,9610, - 9642,9674,9686,9718,9750,9782,9814,9826,9858,9870,9882,9914,10014,10030, - 10043,10063,10079,10090,10101,10104,10113,10122,10133,10144,10179,10244, - 10264,10277,10312,10375,10391,10404,10420,10434,10450,10464,10480,10494, - 10530,10601,10637,10708,10743,10806,10817,10828,10839,10874,10937,11008, - 11079,11142,11177,11240,11275,11338,11382,11393,11404,11438,11449,11484, - 11496,11519,11582,11645,11787,11850,11861,11924,11935,11941,12004,12067, - 12130,12141,12146,12158,12170,12233,12296,12307,12318,12329,12336,12399, - 12462,12525,12531,12594,12657,12720,12783,12846,12909,12972,13035,13098, - 13161,13224,13287,13350,13413,13420,13431,13494,13501,13512,13519,13582, - 13645,13708,13771,13834,13897,13960,13971,14034,14097,14160,14223,14234, - 14297,14308,14319,14382,14568,14583,14619,14656,14668,14672,14674,14678, - 14682,14718,14722,14728,14733,14745,14753,14761,14769,14777,14785,14793, - 14801,14936,15071,15074,15077,15080,15083,15086,15089,15092,15124,15187, - 15236,15285,15334,15345,15350,15359,15364,15369,15374,15407,15470,15478, - 15487,15496,15505,15541,15550,15559,15568,15577,15613,15649,15753,15856, - 15959,16062,16165,16268,16273,16278,16381,16386,16397,16404,16440,16445, - 16447,16510,16573,16636,16699,16762,16825,16888,16891,16923,16952,16984, - 17013,17042,17071,17100,17132,17164,17199,17231,17266,17298,17333,17365, - 17400,17432,17467,17499,17531,17566,17598,17630,17665,17697,17729,17764, - 17799,17834,17869,17904,17939,17974,18009,18044,18079,18114,18149,18184, - 18187,18224,18227,18230,18233,18236,18239,18242,18245,18248,18251,18254, - 18257,18260,18263,18266,18398,18447,18496,18545,18594,18643,18700,18757, - 18815,18873,18931,18989,19048,19107,19167,19227,19288,19349,19393,19406, - 19439,19471,19483,19515,19526,19537,19542,19547,19552,19557,19566,19575, - 19580,19585,19590,19595,19608,19678,19741,19752,19815 + 0, 141, 178, 183, 327, 364, 366, 369, 527, 670, 812, 863, 904, 945, + 1016,1087,1158,1178,1194,1210,1221,1232,1248,1264,1273,1282,1304,1429, + 1656,1667,1680,1693,1706,1719,1724,1733,1757,1878,1888,1929,1979,2030, + 2071,2122,2163,2204,2245,2286,2327,2368,2409,2450,2491,2532,2665,2798, + 2848,2889,2940,2991,3041,3197,3248,3289,3340,3390,3431,3472,3614,3655, + 3723,3726,3729,3732,3835,3870,3885,3988,4023,4038,4141,4150,4185,4288, + 4391,4494,4529,4564,4579,4682,4691,4794,4897,5000,5103,5206,5309,5412, + 5515,5618,5721,5824,5927,6030,6133,6145,6157,6260,6295,6330,6345,6448, + 6463,6478,6489,6592,6627,6662,6697,6706,6741,6776,6811,6846,6881,6916, + 6951,6986,7021,7056,7091,7126,7161,7196,7207,7222,7257,7360,7463,7566, + 7669,7680,7695,7706,7809,7844,7879,7914,7949,7984,8019,8054,8069,8172, + 8275,8310,8345,8380,8483,8518,8533,8568,8583,8598,8633,8665,8677,8709, + 8721,8727,8759,8791,8823,8835,8841,8850,8859,8891,8923,8935,8947,8959, + 8967,8999,9031,9063,9069,9101,9133,9165,9197,9229,9261,9293,9325,9357, + 9389,9421,9453,9485,9517,9525,9537,9569,9577,9589,9597,9629,9661,9693, + 9725,9757,9789,9821,9833,9865,9897,9929,9961,9973,10005,10017,10029, + 10061,10161,10177,10190,10210,10226,10237,10248,10255,10264,10273,10284, + 10295,10330,10395,10415,10432,10467,10530,10546,10559,10575,10589,10605, + 10619,10635,10649,10685,10756,10792,10863,10898,10961,10972,10983,10994, + 11029,11092,11163,11234,11297,11332,11395,11430,11493,11537,11548,11559, + 11593,11604,11639,11651,11674,11737,11800,11863,11874,11937,11948,11954, + 12017,12080,12143,12154,12159,12171,12183,12246,12309,12320,12331,12342, + 12349,12412,12475,12538,12544,12607,12670,12733,12796,12859,12922,12985, + 13048,13111,13174,13237,13300,13363,13426,13433,13444,13507,13514,13525, + 13532,13595,13658,13721,13784,13847,13910,13973,13984,14047,14110,14173, + 14236,14247,14310,14321,14332,14395,14581,14596,14632,14669,14681,14685, + 14828,14832,14836,14872,14876,14882,15017,15130,15138,15146,15154,15162, + 15170,15178,15186,15321,15456,15459,15462,15465,15468,15471,15474,15477, + 15509,15572,15621,15670,15719,15730,15735,15744,15749,15754,15759,15797, + 15860,15868,15877,15886,15895,15931,15940,15949,15958,15967,16003,16039, + 16143,16246,16349,16452,16555,16658,16663,16668,16771,16776,16793,16800, + 16836,16841,16878,16941,17004,17067,17130,17193,17256,17319,17322,17354, + 17383,17415,17444,17473,17502,17531,17563,17595,17630,17662,17697,17729, + 17764,17796,17831,17863,17898,17930,17962,17997,18029,18061,18096,18128, + 18160,18195,18230,18265,18300,18335,18370,18405,18440,18475,18510,18545, + 18580,18615,18618,18655,18662,18669,18676,18683,18686,18689,18692,18694, + 18697,18700,18703,18706,18709,18712,18715,18847,18896,18945,18994,19043, + 19092,19149,19206,19264,19322,19380,19438,19497,19556,19616,19676,19737, + 19798,19842,19855,19891,19924,19956,19968,20000,20135,20270,20397,20524, + 20651,20778,20905,21032,21153,21274,21393,21512,21525,21595,21658,21669, + 21732 }; static const unsigned short ag_sbe[] = { - 136, 176, 180, 319, 362, 364, 500, 660, 711, 752, 793, 833, 904, 975, - 1025,1042,1058,1069,1080,1096,1112,1121,1130,1152,1277,1394,1514,1529, - 1542,1555,1568,1574,1579,1601,1728,1735,1777,1827,1878,1919,1970,2011, - 2052,2093,2134,2175,2216,2257,2298,2339,2380,2513,2646,2696,2737,2788, - 2839,2889,3045,3096,3137,3188,3238,3279,3320,3462,3503,3542,3577,3580, - 3583,3683,3718,3733,3836,3871,3886,3989,3998,4033,4136,4239,4342,4377, - 4412,4427,4530,4539,4642,4745,4848,4951,5054,5157,5260,5363,5466,5569, - 5672,5775,5878,5981,5993,6005,6108,6143,6178,6193,6296,6311,6326,6337, - 6440,6475,6510,6545,6554,6589,6624,6659,6694,6729,6764,6799,6834,6869, - 6904,6939,6974,7009,7044,7055,7070,7105,7208,7311,7414,7517,7528,7543, - 7554,7657,7692,7727,7762,7797,7832,7867,7902,7917,8020,8123,8158,8193, - 8228,8331,8366,8381,8416,8431,8446,8481,8515,8527,8559,8571,8577,8609, - 8641,8673,8685,8691,8700,8709,8741,8773,8785,8797,8809,8817,8849,8881, - 8913,8919,8951,8983,9015,9047,9079,9111,9143,9175,9207,9239,9271,9303, - 9335,9367,9375,9387,9419,9427,9439,9447,9479,9511,9543,9575,9607,9639, - 9671,9683,9715,9747,9779,9811,9823,9855,9867,9879,9911,10011,10025,10039, - 10058,10076,10085,10096,10102,10108,10115,10128,10139,10174,10207,10259, - 10273,10307,10340,10386,10400,10415,10429,10445,10459,10475,10489,10525, - 10559,10632,10666,10738,10771,10812,10823,10834,10869,10902,10966,11037, - 11107,11172,11205,11270,11303,11376,11388,11399,11437,11444,11483,11491, - 11514,11547,11610,11782,11815,11858,11889,11932,11937,11969,12032,12095, - 12138,12143,12151,12163,12198,12261,12304,12315,12326,12333,12364,12427, - 12490,12527,12559,12622,12685,12748,12811,12874,12937,13000,13063,13126, - 13189,13252,13315,13378,13417,13428,13459,13498,13509,13516,13547,13610, - 13673,13736,13799,13862,13925,13968,13999,14062,14125,14188,14231,14262, - 14305,14316,14347,14474,14576,14617,14654,14663,14671,14673,14677,14681, - 14716,14721,14727,14732,14744,14748,14756,14764,14772,14780,14788,14796, - 14931,15066,15072,15075,15078,15081,15084,15087,15090,15119,15152,15212, - 15261,15310,15339,15347,15354,15361,15366,15371,15387,15435,15475,15484, - 15493,15502,15539,15547,15556,15565,15574,15612,15648,15748,15851,15954, - 16057,16160,16263,16270,16275,16376,16383,16396,16403,16438,16444,16446, - 16475,16538,16601,16664,16727,16790,16853,16889,16918,16949,16979,17010, - 17039,17068,17097,17129,17161,17194,17228,17261,17295,17328,17362,17395, - 17429,17462,17496,17528,17561,17595,17627,17660,17694,17726,17759,17794, - 17829,17864,17899,17934,17969,18004,18039,18074,18109,18144,18179,18185, - 18222,18225,18228,18231,18234,18237,18240,18243,18246,18249,18252,18255, - 18258,18261,18264,18395,18423,18472,18521,18570,18619,18671,18728,18785, - 18843,18901,18959,19017,19076,19135,19195,19255,19316,19388,19403,19436, - 19468,19480,19512,19520,19531,19539,19544,19549,19554,19561,19570,19577, - 19582,19587,19592,19604,19637,19706,19749,19780,19815 + 136, 176, 180, 320, 363, 365, 367, 504, 665, 807, 858, 899, 940, 980, + 1051,1122,1172,1189,1205,1216,1227,1243,1259,1268,1277,1299,1424,1541, + 1661,1676,1689,1702,1715,1721,1726,1748,1875,1882,1924,1974,2025,2066, + 2117,2158,2199,2240,2281,2322,2363,2404,2445,2486,2527,2660,2793,2843, + 2884,2935,2986,3036,3192,3243,3284,3335,3385,3426,3467,3609,3650,3689, + 3724,3727,3730,3830,3865,3880,3983,4018,4033,4136,4145,4180,4283,4386, + 4489,4524,4559,4574,4677,4686,4789,4892,4995,5098,5201,5304,5407,5510, + 5613,5716,5819,5922,6025,6128,6140,6152,6255,6290,6325,6340,6443,6458, + 6473,6484,6587,6622,6657,6692,6701,6736,6771,6806,6841,6876,6911,6946, + 6981,7016,7051,7086,7121,7156,7191,7202,7217,7252,7355,7458,7561,7664, + 7675,7690,7701,7804,7839,7874,7909,7944,7979,8014,8049,8064,8167,8270, + 8305,8340,8375,8478,8513,8528,8563,8578,8593,8628,8662,8674,8706,8718, + 8724,8756,8788,8820,8832,8838,8847,8856,8888,8920,8932,8944,8956,8964, + 8996,9028,9060,9066,9098,9130,9162,9194,9226,9258,9290,9322,9354,9386, + 9418,9450,9482,9514,9522,9534,9566,9574,9586,9594,9626,9658,9690,9722, + 9754,9786,9818,9830,9862,9894,9926,9958,9970,10002,10014,10026,10058, + 10158,10172,10186,10205,10223,10232,10243,10253,10259,10266,10279,10290, + 10325,10358,10410,10428,10462,10495,10541,10555,10570,10584,10600,10614, + 10630,10644,10680,10714,10787,10821,10893,10926,10967,10978,10989,11024, + 11057,11121,11192,11262,11327,11360,11425,11458,11531,11543,11554,11592, + 11599,11638,11646,11669,11702,11765,11828,11871,11902,11945,11950,11982, + 12045,12108,12151,12156,12164,12176,12211,12274,12317,12328,12339,12346, + 12377,12440,12503,12540,12572,12635,12698,12761,12824,12887,12950,13013, + 13076,13139,13202,13265,13328,13391,13430,13441,13472,13511,13522,13529, + 13560,13623,13686,13749,13812,13875,13938,13981,14012,14075,14138,14201, + 14244,14275,14318,14329,14360,14487,14589,14630,14667,14676,14684,14827, + 14831,14835,14870,14875,14881,15016,15129,15133,15141,15149,15157,15165, + 15173,15181,15316,15451,15457,15460,15463,15466,15469,15472,15475,15504, + 15537,15597,15646,15695,15724,15732,15739,15746,15751,15756,15777,15825, + 15865,15874,15883,15892,15929,15937,15946,15955,15964,16002,16038,16138, + 16241,16344,16447,16550,16653,16660,16665,16766,16773,16792,16799,16834, + 16840,16876,16906,16969,17032,17095,17158,17221,17284,17320,17349,17380, + 17410,17441,17470,17499,17528,17560,17592,17625,17659,17692,17726,17759, + 17793,17826,17860,17893,17927,17959,17992,18026,18058,18091,18125,18157, + 18190,18225,18260,18295,18330,18365,18400,18435,18470,18505,18540,18575, + 18610,18616,18653,18660,18667,18674,18681,18684,18687,18690,18693,18695, + 18698,18701,18704,18707,18710,18713,18844,18872,18921,18970,19019,19068, + 19120,19177,19234,19292,19350,19408,19466,19525,19584,19644,19704,19765, + 19837,19852,19890,19921,19953,19965,19997,20129,20264,20394,20521,20648, + 20775,20900,21027,21150,21271,21390,21509,21521,21554,21623,21666,21697,21732 }; static const unsigned char ag_fl[] = { - 2,1,1,2,2,1,2,0,1,3,3,3,1,2,3,1,2,0,1,3,3,2,2,2,1,2,2,2,2,2,2,2,2,2,1, - 1,2,2,3,3,3,3,0,1,3,2,2,2,3,3,4,4,4,4,3,3,3,3,3,2,3,4,2,2,3,3,4,2,2,3, - 3,3,1,1,1,5,5,5,1,5,1,1,1,2,2,1,2,2,3,2,2,1,2,3,3,2,1,2,3,3,2,2,1,1,1, - 1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,4,4,1,4,4,1,4,4,1,4,4,4,4,1,4,4, - 1,4,4,4,4,4,1,2,2,2,1,1,1,4,4,4,4,4,4,4,4,1,1,1,1,1,2,2,2,2,2,2,2,1,2, - 2,2,3,2,2,2,3,1,1,2,2,2,2,2,1,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,3,3,3,3,3,3,3,3,1,3,3,3,1,1,3,3,3,3,3,3,3,3,1,3,3,3,1,1,1,1, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,7,7,7,1,3,3,3,1,3,3,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,3,1,3,3,3,1,1,1,3,3,1,3,3,1,3,3,1,1,1,1,1,1,1,1, + 2,1,1,2,2,1,2,0,1,3,3,3,1,2,3,1,2,0,1,3,3,2,2,2,2,1,2,2,2,2,2,2,2,2,2, + 1,1,2,2,3,3,3,3,0,1,3,2,2,2,3,3,4,4,4,4,3,3,3,3,3,2,3,4,2,2,3,3,4,2,2, + 3,3,3,1,1,1,5,5,5,1,5,1,1,1,2,2,1,2,2,3,2,2,1,2,3,3,2,1,2,3,3,2,2,1,1, + 1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,4,4,1,4,4,1,4,4,1,4,4,4,4,1,4, + 4,1,4,4,4,4,4,1,2,2,2,1,1,1,4,4,4,4,4,4,4,4,1,1,1,1,1,2,2,2,2,2,2,2,1, + 2,2,2,3,2,2,2,3,4,1,1,2,2,2,2,2,1,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,1,3,3,3,1,1,3,3,3,3,3,3,3,3,1,3,3,3,1,1, + 1,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,7,7,7,1,3,3,3,1,3,3,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,3,3,1,1,1,3,3,1,3,3,1,3,3,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 }; static const unsigned short ag_ptt[] = { 0, 24, 25, 25, 22, 30, 30, 31, 31, 27, 27, 27, 37, 37, 2, 39, 39, 40, - 40, 23, 23, 23, 23, 23, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 57, 57, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 40, 23, 23, 23, 23, 23, 23, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 58, 58, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 64, 64, 64, 64, 64, 64, 67, 67,298,298, 84, 84, 84,293,293,323, 19, 19, - 290, 13, 13, 13, 13,292, 15, 15, 15, 15,289, 74, 74,102,102,102, 98,105, - 105, 98,108,108, 98,111,111, 98,114,114, 98,117,117, 98, 55,118,118,118, - 119,119,119,122,122,122,125,125,125,125,125,128,128,128,133,133,133,133, - 133,133,136,136,136,136,138,138,138,138,147,147,147,147,147,147,147,146, - 146,325,325,325,325,325,325,325,325, 8, 8, 8, 8, 8, 8, 7, 7, 18, - 18, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17,373, 10, 10, 10,380,380,380, - 380,380,380,380,380,401,401,401,401,181,181,181,181,181,183,183, 82, 82, - 82,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, - 184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, - 184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, - 184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, - 184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, - 184,184, 32, 87, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 41, 65, 65, 65, 65, 65, 65, 68, 68,299,299, 85, 85, 85,294,294,324, 19, + 19,291, 13, 13, 13, 13,293, 15, 15, 15, 15,290, 75, 75,103,103,103, 99, + 106,106, 99,109,109, 99,112,112, 99,115,115, 99,118,118, 99, 56,119,119, + 119,120,120,120,123,123,123,126,126,126,126,126,129,129,129,134,134,134, + 134,134,134,137,137,137,137,139,139,139,139,148,148,148,148,148,148,148, + 147,147,326,326,326,326,326,326,326,326, 8, 8, 8, 8, 8, 8, 7, 7, + 18, 18, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17,374, 10, 10, 10,381, + 381,381,381,381,381,381,381,402,402,402,402,182,182,182,182,182,184,184, + 83, 83, 83,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, + 185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, + 185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, + 185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, + 185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, + 185,185,185,185, 32, 88, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 29, 29, 29, 29, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 86, 86, 86, 86, 86, 86, 86, 86, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, - 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, - 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, - 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,161,161,161,166,166,166,166, - 169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, - 169,169,169,169,169,169,169,169,169,169,169,169,169,169,260,260,282,282, - 283,283,284,284, 28, 33, 34, 42, 12, 11, 43, 14, 20, 44, 46, 45, 47, 4, - 48, 49, 50, 51, 52, 53, 54, 56, 58, 59, 60, 61, 62, 63, 65, 66, 68, 69, - 70, 71, 72, 73, 75, 76, 21, 77, 3, 78, 79, 80, 81, 83, 99,100,101,103, - 104,106,107,109,110,112,113,115,116,120,121,123,124,126,127,129,130,131, - 132,134,135,137,139,140,141,142,143,144,145,149,148,150,151,152,153,154, - 155,156, 9,158,160,157,182,179,185, 5,186,187,188,189,190,191,192,193, - 194,195,196,197,198,199,200,201,202,203,204,205, 6,206,207,208,209,210, - 211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228, - 229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246, - 247,248,249,250,251,252,253,254,255,256,257,258,259,261,262,263,264,265, - 266,267,268,269,270,271,272,273,274,275,276,277, 90,163, 89,174,164,278, - 279, 95, 94,167,280,170,172,171,165, 92,162,281 + 36, 36, 36, 87, 87, 87, 87, 87, 87, 87, 87, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,162,162,162,167,167, + 167,167,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, + 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,261,261, + 283,283,284,284,285,285, 28, 33, 34, 42, 12, 11, 44, 14, 20, 45, 47, 46, + 48, 4, 49, 50, 51, 52, 53, 54, 55, 57, 59, 60, 61, 62, 63, 64, 66, 67, + 69, 70, 71, 72, 73, 74, 76, 77, 21, 78, 3, 79, 80, 81, 82, 84,100,101, + 102,104,105,107,108,110,111,113,114,116,117,121,122,124,125,127,128,130, + 131,132,133,135,136,138,140,141,142,143,144,145,146,150,149,151,152,153, + 154,155,156,157, 9,159,161,158,183,180,186, 5,187,188,189,190,191,192, + 193,194,195,196,197,198,199,200,201,202,203,204,205,206, 6,207,208,209, + 210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227, + 228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245, + 246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,262,263,264, + 265,266,267,268,269,270,271,272,273,274,275,276,277,278, 91,164, 90,175, + 165,279,280, 96, 95,168,281,171,173,172,166, 93,163,282 }; @@ -5347,21 +5611,21 @@ static void ag_ra(void) case 46: ag_rp_50(); break; case 47: ag_rp_51(); break; case 48: ag_rp_52(); break; - case 49: ag_rp_53(V(0,int)); break; - case 50: ag_rp_54(V(1,int)); break; + case 49: ag_rp_53(); break; + case 50: ag_rp_54(V(0,int)); break; case 51: ag_rp_55(V(1,int)); break; - case 52: ag_rp_56(V(0,int)); break; - case 53: ag_rp_57(V(1,int)); break; - case 54: ag_rp_58(V(1,int), V(2,int)); break; - case 55: ag_rp_59(V(1,int)); break; - case 56: ag_rp_60(); break; - case 57: ag_rp_61(V(1,int)); break; - case 58: ag_rp_62(V(2,int)); break; - case 59: ag_rp_63(); break; + case 52: ag_rp_56(V(1,int)); break; + case 53: ag_rp_57(V(0,int)); break; + case 54: ag_rp_58(V(1,int)); break; + case 55: ag_rp_59(V(1,int), V(2,int)); break; + case 56: ag_rp_60(V(1,int)); break; + case 57: ag_rp_61(); break; + case 58: ag_rp_62(V(1,int)); break; + case 59: ag_rp_63(V(2,int)); break; case 60: ag_rp_64(); break; - case 61: ag_rp_65(V(1,int)); break; - case 62: ag_rp_66(V(2,int)); break; - case 63: ag_rp_67(); break; + case 61: ag_rp_65(); break; + case 62: ag_rp_66(V(1,int)); break; + case 63: ag_rp_67(V(2,int)); break; case 64: ag_rp_68(); break; case 65: ag_rp_69(); break; case 66: ag_rp_70(); break; @@ -5390,8 +5654,8 @@ static void ag_ra(void) case 89: ag_rp_93(); break; case 90: ag_rp_94(); break; case 91: ag_rp_95(); break; - case 92: ag_rp_96(V(0,double)); break; - case 93: ag_rp_97(); break; + case 92: ag_rp_96(); break; + case 93: ag_rp_97(V(0,double)); break; case 94: ag_rp_98(); break; case 95: ag_rp_99(); break; case 96: ag_rp_100(); break; @@ -5399,39 +5663,39 @@ static void ag_ra(void) case 98: ag_rp_102(); break; case 99: ag_rp_103(); break; case 100: ag_rp_104(); break; - case 101: V(0,double) = ag_rp_105(V(0,int)); break; - case 102: V(0,double) = ag_rp_106(V(0,double)); break; - case 103: V(0,int) = ag_rp_107(V(0,int)); break; - case 104: V(0,int) = ag_rp_108(); break; + case 101: ag_rp_105(); break; + case 102: V(0,double) = ag_rp_106(V(0,int)); break; + case 103: V(0,double) = ag_rp_107(V(0,double)); break; + case 104: V(0,int) = ag_rp_108(V(0,int)); break; case 105: V(0,int) = ag_rp_109(); break; case 106: V(0,int) = ag_rp_110(); break; case 107: V(0,int) = ag_rp_111(); break; case 108: V(0,int) = ag_rp_112(); break; case 109: V(0,int) = ag_rp_113(); break; case 110: V(0,int) = ag_rp_114(); break; - case 111: ag_rp_115(V(1,int)); break; + case 111: V(0,int) = ag_rp_115(); break; case 112: ag_rp_116(V(1,int)); break; - case 113: ag_rp_117(V(0,int)); break; - case 114: ag_rp_118(V(1,int)); break; - case 115: ag_rp_119(V(2,int)); break; - case 116: ag_rp_120(V(1,int)); break; + case 113: ag_rp_117(V(1,int)); break; + case 114: ag_rp_118(V(0,int)); break; + case 115: ag_rp_119(V(1,int)); break; + case 116: ag_rp_120(V(2,int)); break; case 117: ag_rp_121(V(1,int)); break; case 118: ag_rp_122(V(1,int)); break; - case 119: V(0,int) = ag_rp_123(V(1,int)); break; - case 120: V(0,int) = ag_rp_124(); break; - case 121: V(0,int) = ag_rp_125(V(0,int)); break; + case 119: ag_rp_123(V(1,int)); break; + case 120: V(0,int) = ag_rp_124(V(1,int)); break; + case 121: V(0,int) = ag_rp_125(V(1,int), V(2,int)); break; case 122: V(0,int) = ag_rp_126(); break; - case 123: V(0,int) = ag_rp_127(); break; + case 123: V(0,int) = ag_rp_127(V(0,int)); break; case 124: V(0,int) = ag_rp_128(); break; case 125: V(0,int) = ag_rp_129(); break; case 126: V(0,int) = ag_rp_130(); break; case 127: V(0,int) = ag_rp_131(); break; case 128: V(0,int) = ag_rp_132(); break; - case 129: V(0,double) = ag_rp_133(); break; - case 130: V(0,double) = ag_rp_134(V(1,int)); break; - case 131: V(0,double) = ag_rp_135(V(0,double), V(1,int)); break; - case 132: ag_rp_136(); break; - case 133: ag_rp_137(); break; + case 129: V(0,int) = ag_rp_133(); break; + case 130: V(0,int) = ag_rp_134(); break; + case 131: V(0,double) = ag_rp_135(); break; + case 132: V(0,double) = ag_rp_136(V(1,int)); break; + case 133: V(0,double) = ag_rp_137(V(0,double), V(1,int)); break; case 134: ag_rp_138(); break; case 135: ag_rp_139(); break; case 136: ag_rp_140(); break; @@ -5523,9 +5787,9 @@ static void ag_ra(void) case 222: ag_rp_226(); break; case 223: ag_rp_227(); break; case 224: ag_rp_228(); break; - case 225: ag_rp_229(V(2,int)); break; + case 225: ag_rp_229(); break; case 226: ag_rp_230(); break; - case 227: ag_rp_231(); break; + case 227: ag_rp_231(V(2,int)); break; case 228: ag_rp_232(); break; case 229: ag_rp_233(); break; case 230: ag_rp_234(); break; @@ -5540,11 +5804,13 @@ static void ag_ra(void) case 239: ag_rp_243(); break; case 240: ag_rp_244(); break; case 241: ag_rp_245(); break; + case 242: ag_rp_246(); break; + case 243: ag_rp_247(); break; } } #define TOKEN_NAMES a85parse_token_names -const char *const a85parse_token_names[491] = { +const char *const a85parse_token_names[492] = { "a85parse", "WS", "cstyle comment", @@ -5555,16 +5821,16 @@ const char *const a85parse_token_names[491] = { "hex integer", "decimal integer", "real", - "simple real", + "", "literal string", "label", - "string chars", + "", "include string", - "include chars", + "", "ascii integer", "escape char", "asm hex value", - "singlequote chars", + "", "asm include", "singlequote string", "a85parse", @@ -5588,6 +5854,7 @@ const char *const a85parse_token_names[491] = { "", "expression", "'\\n'", + "error", "\"INCLUDE\"", "\"#INCLUDE\"", "\"#PRAGMA\"", @@ -5609,7 +5876,7 @@ const char *const a85parse_token_names[491] = { "\"DSEG\"", "\"DS\"", "\"DB\"", - "expression list", + "", "\"DW\"", "\"EXTRN\"", "name list", @@ -5643,7 +5910,7 @@ const char *const a85parse_token_names[491] = { "'<'", "", "\":\"", - "condition start", + "", "\"EQ\"", "\"==\"", "\"=\"", @@ -6041,49 +6308,49 @@ const char *const a85parse_token_names[491] = { static const unsigned short ag_ctn[] = { - 0,0, 2,1, 0,0, 0,0, 0,0, 0,0, 23,1, 0,0, 0,0, 0,0, 27,1, 27,1, - 27,1, 27,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, - 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 23,2, - 29,1, 0,0, 0,0, 29,1, 0,0, 29,1, 29,1, 29,1, 29,1, 29,1, 29,1, 29,1, - 29,1, 29,1, 29,1, 0,0, 0,0, 0,0, 29,1, 0,0, 0,0, 0,0, 0,0, 0,0, - 29,1, 0,0, 0,0, 29,1, 29,1, 0,0, 29,1, 0,0, 27,2, 27,2, 27,2,184,1, - 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, - 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, - 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, - 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, - 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, - 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, - 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, - 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, - 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, - 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, - 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, - 184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1,184,1, - 184,1,184,1,184,1,184,1,184,1, 82,1, 0,0, 41,2, 0,0, 41,2, 0,0, 0,0, - 41,2, 0,0, 41,2, 0,0, 0,0, 0,0, 41,2, 0,0, 41,2, 0,0, 41,2, 0,0, + 0,0, 2,1, 0,0, 0,0, 0,0, 0,0, 23,1, 23,1, 0,0, 0,0, 0,0, 0,0, + 27,1, 27,1, 27,1, 27,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, + 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, + 41,1, 23,2, 29,1, 0,0, 0,0, 29,1, 0,0, 29,1, 29,1, 29,1, 29,1, 29,1, + 29,1, 29,1, 29,1, 29,1, 29,1, 0,0, 0,0, 0,0, 29,1, 0,0, 0,0, 0,0, + 0,0, 0,0, 29,1, 0,0, 0,0, 29,1, 29,1, 0,0, 29,1, 0,0, 27,2, 27,2, + 27,2,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, + 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, + 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, + 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, + 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, + 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, + 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, + 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, + 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, + 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, + 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, + 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, + 185,1,185,1,185,1,185,1,185,1,185,1,185,1, 83,1, 0,0, 41,2, 0,0, 41,2, + 0,0, 0,0, 41,2, 0,0, 41,2, 0,0, 0,0, 0,0, 41,2, 0,0, 41,2, 0,0, 41,2, 0,0, 41,2, 0,0, 41,2, 0,0, 41,2, 0,0, 41,2, 0,0, 41,2, 0,0, - 41,2, 0,0, 0,0, 0,0, 0,0, 41,2, 41,2, 41,2, 41,2, 0,0, 41,2, 0,0, - 41,2, 0,0, 0,0, 0,0,292,1, 0,0,290,1, 0,0, 0,0, 41,2, 41,2, 0,0, - 184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2, - 184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2, - 184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2, - 184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2, - 184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2,184,2, 82,2, - 0,0, 19,1,323,1, 0,0, 10,1, 7,1, 8,1, 8,1, 16,1, 10,1,325,1, 7,1, - 146,1,147,1,147,1,147,1,147,1,147,1,147,1,147,1,146,1, 0,0,147,1,147,1, - 147,1,147,1,147,1,147,1,147,1,136,1,138,1,136,1,136,1,136,1,133,1,128,1, - 125,1,122,1,119,1,118,1, 98,1, 74,1, 41,3, 67,1, 67,1, 67,1, 0,0, 64,1, - 64,1, 64,1, 64,1, 15,2, 13,2, 0,0, 0,0, 0,0,181,1,181,1,181,1,184,3, - 184,3, 0,0,184,3,325,1, 17,1, 19,2, 7,2, 16,2,147,2,147,2,147,2,147,2, - 147,2,147,2,147,2,138,2, 0,0,133,2, 0,0,133,2,133,2,133,2,133,2,128,2, - 128,2, 0,0,125,2, 0,0,125,2, 0,0,125,2, 0,0,125,2, 0,0,122,2,122,2, - 0,0,119,2,119,2, 0,0,118,2,118,2, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, - 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 67,2, 0,0, 64,2, 64,2, 64,2, - 64,2,184,4,184,4,184,4,147,3,147,3,147,3,147,3,147,3,147,3,147,3,138,3, - 133,3,133,3,133,3,133,3,133,3,128,3,128,3,125,3,125,3,125,3,125,3,122,3, - 122,3,119,3,119,3,118,3,118,3, 0,0, 67,3, 64,3,184,5,184,5,184,5,133,1, - 133,1,128,1,128,1,128,1,128,1,125,1,125,1,122,1,122,1,119,1,119,1, 67,4, - 64,4,184,6,184,6,184,6 + 41,2, 0,0, 41,2, 0,0, 0,0, 0,0, 0,0, 41,2, 41,2, 41,2, 41,2, 0,0, + 41,2, 0,0, 41,2, 0,0, 0,0, 0,0,293,1, 0,0,291,1, 0,0, 0,0, 41,2, + 41,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2, + 185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2, + 185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2, + 185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2, + 185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2, + 83,2, 0,0,324,1,324,1, 0,0,374,1, 7,1, 8,1, 8,1, 16,1,374,1,326,1, + 7,1,147,1,148,1,148,1,148,1,148,1,148,1,148,1,148,1,147,1, 0,0,148,1, + 148,1,148,1,148,1,148,1,148,1,148,1,137,1,139,1,137,1,137,1,137,1,134,1, + 129,1,126,1,123,1,120,1,119,1, 75,1, 75,1, 41,3, 68,1, 68,1, 68,1, 0,0, + 0,0, 0,0, 0,0, 0,0,293,2,291,2, 0,0, 0,0, 0,0,182,1,182,1,182,1, + 185,3,185,3, 0,0,185,3,326,1, 17,1,324,2, 7,2, 16,2,148,2,148,2,148,2, + 148,2,148,2,148,2,148,2,139,2, 0,0,134,2, 0,0,134,2,134,2,134,2,134,2, + 129,2,129,2, 0,0,126,2, 0,0,126,2, 0,0,126,2, 0,0,126,2, 0,0,123,2, + 123,2, 0,0,120,2,120,2, 0,0,119,2,119,2, 0,0, 0,0, 0,0, 0,0, 0,0, + 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 68,2, 0,0, 0,0, 0,0, + 0,0, 0,0,185,4,185,4,185,4, 16,3,148,3,148,3,148,3,148,3,148,3,148,3, + 148,3,139,3,134,3,134,3,134,3,134,3,134,3,129,3,129,3,126,3,126,3,126,3, + 126,3,123,3,123,3,120,3,120,3,119,3,119,3, 0,0, 68,3, 16,3, 0,0,185,5, + 185,5,185,5,134,1,134,1,129,1,129,1,129,1,129,1,126,1,126,1,123,1,123,1, + 120,1,120,1, 68,4, 0,0,185,6,185,6,185,6 }; #ifndef MISSING_FORMAT @@ -6121,6 +6388,29 @@ static void ag_diagnose(void) { (PCB).error_message = (PCB).ag_msg; +{ + int ag_sx, ag_t; + + ag_sx = (PCB).ssx; + (PCB).ss[ag_sx] = (PCB).sn; + do { + while (ag_sx && ag_ctn[2*(ag_snd = (PCB).ss[ag_sx])] == 0) ag_sx--; + if (ag_sx) { + ag_t = ag_ctn[2*ag_snd]; + ag_sx -= ag_ctn[2*ag_snd +1]; + ag_snd = (PCB).ss[ag_sx]; + } + else { + ag_snd = 0; + ag_t = ag_ptt[0]; + } + } while (ag_sx && *TOKEN_NAMES[ag_t]==0); + if (*TOKEN_NAMES[ag_t] == 0) ag_t = 0; + (PCB).error_frame_ssx = ag_sx; + (PCB).error_frame_token = (a85parse_token_type) ag_t; +} + + } static int ag_action_1_r_proc(void); static int ag_action_2_r_proc(void); @@ -6172,214 +6462,66 @@ static int (*const ag_gt_procs_scan[])(void) = { }; -static int ag_rns(int ag_t, int *ag_sx, int ag_snd) { - while (1) { - int ag_act, ag_k = ag_sbt[ag_snd], ag_lim = ag_sbt[ag_snd+1]; - int ag_p; - - while (ag_k < ag_lim && ag_tstt[ag_k] != ag_t) ag_k++; - if (ag_k == ag_lim) break; - ag_act = ag_astt[ag_k]; - ag_p = ag_pstt[ag_k]; - if (ag_act == ag_action_2) return ag_p; - if (ag_act == ag_action_10 || ag_act == ag_action_11) { - (*ag_sx)--; - return ag_snd; - } - if (ag_act != ag_action_3 && - ag_act != ag_action_4) break; - *ag_sx -= (ag_fl[ag_p] - 1); - ag_snd = (PCB).ss[*ag_sx]; - ag_t = ag_ptt[ag_p]; - } - return 0; -} - -static int ag_jns(int ag_t) { - int ag_k; +static int ag_action_1_er_proc(void); +static int ag_action_2_er_proc(void); +static int ag_action_3_er_proc(void); +static int ag_action_4_er_proc(void); - ag_k = ag_sbt[(PCB).sn]; - while (ag_tstt[ag_k] != ag_t && ag_tstt[ag_k]) ag_k++; - while (1) { - int ag_p = ag_pstt[ag_k]; - int ag_sd; - - switch (ag_astt[ag_k]) { - case ag_action_2: - (PCB).ss[(PCB).ssx] = (PCB).sn; - return ag_p; - case ag_action_10: - case ag_action_11: - return (PCB).ss[(PCB).ssx--]; - case ag_action_9: - (PCB).ss[(PCB).ssx] = (PCB).sn; - (PCB).ssx++; - (PCB).sn = ag_p; - ag_k = ag_sbt[(PCB).sn]; - while (ag_tstt[ag_k] != ag_t && ag_tstt[ag_k]) ag_k++; - continue; - case ag_action_3: - case ag_action_4: - ag_sd = ag_fl[ag_p] - 1; - if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd]; - else (PCB).ss[(PCB).ssx] = (PCB).sn; - ag_t = ag_ptt[ag_p]; - ag_k = ag_sbt[(PCB).sn+1]; - while (ag_tstt[--ag_k] != ag_t); - continue; - case ag_action_5: - case ag_action_6: - if (ag_fl[ag_p]) break; - (PCB).sn = ag_rns(ag_ptt[ag_p],&(PCB).ssx, (PCB).sn); - (PCB).ss[++(PCB).ssx] = (PCB).sn; - ag_k = ag_sbt[(PCB).sn]; - while (ag_tstt[ag_k] != ag_t && ag_tstt[ag_k]) ag_k++; - continue; - } - break; - } - return 0; -} +static int (*const ag_er_procs_scan[])(void) = { + ag_action_1_er_proc, + ag_action_2_er_proc, + ag_action_3_er_proc, + ag_action_4_er_proc +}; -static int ag_atx(int ag_t, int *ag_sx, int ag_snd) { - int ag_k, ag_f; - int ag_save_btsx = (PCB).btsx; - int ag_flag = 1; +static void ag_error_resynch(void) { + int ag_k; + int ag_ssx = (PCB).ssx; + ag_diagnose(); + SYNTAX_ERROR; + if ((PCB).exit_flag != AG_RUNNING_CODE) return; while (1) { - int ag_a; - - (PCB).bts[128 - ++(PCB).btsx] = *ag_sx; - (PCB).ss[128 - (PCB).btsx] = (PCB).ss[*ag_sx]; - (PCB).ss[*ag_sx] = ag_snd; - ag_k = ag_sbt[ag_snd]; - while (ag_tstt[ag_k] != ag_t && ag_tstt[ag_k]) ag_k++; - ag_a = ag_astt[ag_k]; - if (ag_a == ag_action_2 || - ag_a == ag_action_3 || - ag_a == ag_action_10 || - ag_a == ag_action_11 || - ag_a == ag_action_1 || - ag_a == ag_action_4) break; - if ((ag_a == ag_action_5 || - ag_a == ag_action_6) && - (ag_k = ag_fl[ag_f = ag_pstt[ag_k]]) == 0) { - ag_snd = ag_rns(ag_ptt[ag_f],ag_sx, (PCB).ss[*ag_sx]); - (*ag_sx)++; - continue; - } - if (ag_a == ag_action_9) { - ag_snd = ag_pstt[ag_k]; - (*ag_sx)++; - continue; - } - ag_flag = 0; - break; - } - while ((PCB).btsx > ag_save_btsx) { - *ag_sx = (PCB).bts[128 - (PCB).btsx]; - (PCB).ss[*ag_sx] = (PCB).ss[128 - (PCB).btsx--]; - } - return ag_flag; -} - - -static int ag_tst_tkn(void) { - int ag_rk, ag_sx, ag_snd = (PCB).sn; - - if ((PCB).rx < (PCB).fx) { - (PCB).input_code = (PCB).lab[(PCB).rx++]; - (PCB).token_number = (a85parse_token_type) AG_TCV((PCB).input_code);} - else { - GET_INPUT; - (PCB).lab[(PCB).fx++] = (PCB).input_code; - (PCB).token_number = (a85parse_token_type) AG_TCV((PCB).input_code); - (PCB).rx++; - } - if (ag_key_index[(PCB).sn]) { - unsigned ag_k = ag_key_index[(PCB).sn]; - int ag_ch = CONVERT_CASE((PCB).input_code); - while (ag_key_ch[ag_k] < ag_ch) ag_k++; - if (ag_key_ch[ag_k] == ag_ch) ag_get_key_word(ag_k); + ag_k = ag_sbt[(PCB).sn]; + while (ag_tstt[ag_k] != 43 && ag_tstt[ag_k]) ag_k++; + if (ag_tstt[ag_k] || (PCB).ssx == 0) break; + (PCB).sn = (PCB).ss[--(PCB).ssx]; } - for (ag_rk = 0; ag_rk < (PCB).ag_lrss; ag_rk += 2) { - ag_sx = (PCB).ag_rss[ag_rk]; - if (ag_sx > (PCB).ssx || ag_sx > (PCB).ag_min_depth) continue; - (PCB).sn = (PCB).ag_rss[ag_rk + 1]; - if (ag_atx((PCB).token_number, &ag_sx, (PCB).sn)) break; - } - (PCB).sn = ag_snd; - return ag_rk; -} - -static void ag_set_error_procs(void); - -static void ag_auto_resynch(void) { - int ag_sx, ag_rk; - int ag_rk1, ag_rk2, ag_tk1; - (PCB).ss[(PCB).ssx] = (PCB).sn; - if ((PCB).ag_error_depth && (PCB).ag_min_depth >= (PCB).ag_error_depth) { - (PCB).ssx = (PCB).ag_error_depth; - (PCB).sn = (PCB).ss[(PCB).ssx]; - } - else { - ag_diagnose(); - SYNTAX_ERROR; - if ((PCB).exit_flag != AG_RUNNING_CODE) return; - (PCB).ag_error_depth = (PCB).ag_min_depth = 0; - (PCB).ag_lrss = 0; - (PCB).ss[ag_sx = (PCB).ssx] = (PCB).sn; - (PCB).ag_min_depth = (PCB).ag_rss[(PCB).ag_lrss++] = ag_sx; - (PCB).ag_rss[(PCB).ag_lrss++] = (PCB).sn; - while (ag_sx && (PCB).ag_lrss < 2*128) { - int ag_t = 0, ag_x, ag_s, ag_sxs = ag_sx; - - while (ag_sx && (ag_t = ag_ctn[2*(PCB).sn]) == 0) (PCB).sn = (PCB).ss[--ag_sx]; - if (ag_t) (PCB).sn = (PCB).ss[ag_sx -= ag_ctn[2*(PCB).sn +1]]; - else { - if (ag_sx == 0) (PCB).sn = 0; - ag_t = ag_ptt[0]; - } - if ((ag_s = ag_rns(ag_t, &ag_sx, (PCB).sn)) == 0) break; - for (ag_x = 0; ag_x < (PCB).ag_lrss; ag_x += 2) - if ((PCB).ag_rss[ag_x] == ag_sx + 1 && (PCB).ag_rss[ag_x+1] == ag_s) break; - if (ag_x == (PCB).ag_lrss) { - (PCB).ag_rss[(PCB).ag_lrss++] = ++ag_sx; - (PCB).ag_rss[(PCB).ag_lrss++] = (PCB).sn = ag_s; - } - else if (ag_sx >= ag_sxs) ag_sx--; - } - ag_set_error_procs(); + if (ag_tstt[ag_k] == 0) { + (PCB).sn = PCB.ss[(PCB).ssx = ag_ssx]; + (PCB).exit_flag = AG_SYNTAX_ERROR_CODE; + return; } - (PCB).rx = 0; - if ((PCB).ssx > (PCB).ag_min_depth) (PCB).ag_min_depth = (PCB).ssx; + ag_k = ag_sbt[(PCB).sn]; + while (ag_tstt[ag_k] != 43 && ag_tstt[ag_k]) ag_k++; + (PCB).ag_ap = ag_pstt[ag_k]; + (ag_er_procs_scan[ag_astt[ag_k]])(); while (1) { - ag_rk1 = ag_tst_tkn(); + ag_k = ag_sbt[(PCB).sn]; + while (ag_tstt[ag_k] != (const unsigned short) (PCB).token_number && ag_tstt[ag_k]) + ag_k++; + if (ag_tstt[ag_k] && ag_astt[ag_k] != ag_action_10) break; if ((PCB).token_number == 26) - {(PCB).exit_flag = AG_SYNTAX_ERROR_CODE; return;} - if (ag_rk1 < (PCB).ag_lrss) break; + {(PCB).exit_flag = AG_SYNTAX_ERROR_CODE; return;} {(PCB).rx = 1; ag_track();} + if ((PCB).rx < (PCB).fx) { + (PCB).input_code = (PCB).lab[(PCB).rx++]; + (PCB).token_number = (a85parse_token_type) AG_TCV((PCB).input_code);} + else { + GET_INPUT; + (PCB).lab[(PCB).fx++] = (PCB).input_code; + (PCB).token_number = (a85parse_token_type) AG_TCV((PCB).input_code); + (PCB).rx++; + } + if (ag_key_index[(PCB).sn]) { + unsigned ag_k = ag_key_index[(PCB).sn]; + int ag_ch = CONVERT_CASE((PCB).input_code); + while (ag_key_ch[ag_k] < ag_ch) ag_k++; + if (ag_key_ch[ag_k] == ag_ch) ag_get_key_word(ag_k); + } } - ag_tk1 = (PCB).token_number; - ag_track(); - ag_rk2 = ag_tst_tkn(); - if (ag_rk2 < ag_rk1) {ag_rk = ag_rk2; ag_track();} - else {ag_rk = ag_rk1; (PCB).token_number = (a85parse_token_type) ag_tk1; (PCB).rx = 0;} - (PCB).ag_min_depth = (PCB).ssx = (PCB).ag_rss[ag_rk++]; - (PCB).sn = (PCB).ss[(PCB).ssx] = (PCB).ag_rss[ag_rk]; - (PCB).sn = ag_jns((PCB).token_number); - if ((PCB).ag_error_depth == 0 || (PCB).ag_error_depth > (PCB).ssx) - (PCB).ag_error_depth = (PCB).ssx; - if (++(PCB).ssx >= 128) { - (PCB).exit_flag = AG_STACK_ERROR_CODE; - PARSER_STACK_OVERFLOW; - return; - } - (PCB).ss[(PCB).ssx] = (PCB).sn; - (PCB).ag_tmp_depth = (PCB).ag_min_depth; (PCB).rx = 0; - return; } @@ -6540,7 +6682,7 @@ static int ag_action_4_proc(void) { else ag_t2 = ag_tx; } while (ag_t1 < ag_t2); (PCB).ag_ap = ag_pstt[ag_t1]; - if ((*(PCB).s_procs[ag_astt[ag_t1]])() == 0) break; + if ((ag_s_procs_scan[ag_astt[ag_t1]])() == 0) break; } return 0; } @@ -6563,15 +6705,17 @@ static int ag_action_3_proc(void) { else ag_t2 = ag_tx; } while (ag_t1 < ag_t2); (PCB).ag_ap = ag_pstt[ag_t1]; - if ((*(PCB).s_procs[ag_astt[ag_t1]])() == 0) break; + if ((ag_s_procs_scan[ag_astt[ag_t1]])() == 0) break; } return 0; } static int ag_action_8_proc(void) { - ag_undo(); + int ag_k = ag_sbt[(PCB).sn]; + while (ag_tstt[ag_k] != 43 && ag_tstt[ag_k]) ag_k++; + if (ag_tstt[ag_k] == 0) ag_undo(); (PCB).rx = 0; - ag_auto_resynch(); + ag_error_resynch(); return (PCB).exit_flag == AG_RUNNING_CODE; } @@ -6594,7 +6738,7 @@ static int ag_action_5_proc(void) { else ag_t2 = ag_tx; } while (ag_t1 < ag_t2); (PCB).ag_ap = ag_pstt[ag_t1]; - if ((*(PCB).r_procs[ag_astt[ag_t1]])() == 0) break; + if ((ag_r_procs_scan[ag_astt[ag_t1]])() == 0) break; } return (PCB).exit_flag == AG_RUNNING_CODE; } @@ -6625,86 +6769,70 @@ static int ag_action_6_proc(void) { else ag_t2 = ag_tx; } while (ag_t1 < ag_t2); (PCB).ag_ap = ag_pstt[ag_t1]; - if ((*(PCB).r_procs[ag_astt[ag_t1]])() == 0) break; + if ((ag_r_procs_scan[ag_astt[ag_t1]])() == 0) break; } return (PCB).exit_flag == AG_RUNNING_CODE; } -static void ag_check_depth(int ag_fl) { - int ag_sx = (PCB).ssx - ag_fl; - if ((PCB).ag_error_depth && ag_sx < (PCB).ag_tmp_depth) (PCB).ag_tmp_depth = ag_sx; -} - -static int ag_action_3_er_proc(void) { - ag_check_depth(ag_fl[(PCB).ag_ap] - 1); - return ag_action_4_r_proc(); -} - -static int ag_action_2_e_proc(void) { - ag_action_2_proc(); - (PCB).ag_min_depth = (PCB).ag_tmp_depth; +static int ag_action_2_er_proc(void) { + (PCB).btsx = 0, (PCB).drt = -1; + (*(int *) &(PCB).vs[(PCB).ssx]) = *(PCB).lab; + (PCB).ssx++; + (PCB).sn = (PCB).ag_ap; return 0; } -static int ag_action_4_e_proc(void) { - ag_check_depth(ag_fl[(PCB).ag_ap] - 1); - (PCB).ag_min_depth = (PCB).ag_tmp_depth; - return ag_action_4_proc(); -} - -static int ag_action_6_e_proc(void) { - ag_check_depth(ag_fl[(PCB).ag_ap]); - return ag_action_6_proc(); +static int ag_action_1_er_proc(void) { + (PCB).btsx = 0, (PCB).drt = -1; + (PCB).exit_flag = AG_SUCCESS_CODE; + return 0; } -static int ag_action_11_e_proc(void) { - return ag_action_10_proc(); +static int ag_action_4_er_proc(void) { + int ag_sd = ag_fl[(PCB).ag_ap] - 1; + (PCB).btsx = 0, (PCB).drt = -1; + (PCB).reduction_token = (a85parse_token_type) ag_ptt[(PCB).ag_ap]; + if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd]; + else (PCB).ss[(PCB).ssx] = (PCB).sn; + while ((PCB).exit_flag == AG_RUNNING_CODE) { + unsigned ag_t1 = ag_sbe[(PCB).sn] + 1; + unsigned ag_t2 = ag_sbt[(PCB).sn+1] - 1; + do { + unsigned ag_tx = (ag_t1 + ag_t2)/2; + if (ag_tstt[ag_tx] < (const unsigned short)(PCB).reduction_token) ag_t1 = ag_tx + 1; + else ag_t2 = ag_tx; + } while (ag_t1 < ag_t2); + (PCB).ag_ap = ag_pstt[ag_t1]; + if ((ag_s_procs_scan[ag_astt[ag_t1]])() == 0) break; + } + return 0; } -static int (*ag_r_procs_error[])(void) = { - ag_action_1_r_proc, - ag_action_2_r_proc, - ag_action_3_er_proc, - ag_action_3_er_proc -}; - -static int (*ag_s_procs_error[])(void) = { - ag_action_1_s_proc, - ag_action_2_r_proc, - ag_action_3_er_proc, - ag_action_3_er_proc -}; - -static int (*ag_gt_procs_error[])(void) = { - ag_action_1_proc, - ag_action_2_e_proc, - ag_action_4_e_proc, - ag_action_4_e_proc, - ag_action_6_e_proc, - ag_action_6_e_proc, - ag_action_7_proc, - ag_action_8_proc, - ag_action_9_proc, - ag_action_10_proc, - ag_action_11_e_proc, - ag_action_8_proc -}; - -static void ag_set_error_procs(void) { - (PCB).gt_procs = ag_gt_procs_error; - (PCB).r_procs = ag_r_procs_error; - (PCB).s_procs = ag_s_procs_error; +static int ag_action_3_er_proc(void) { + int ag_sd = ag_fl[(PCB).ag_ap] - 1; + (PCB).btsx = 0, (PCB).drt = -1; + if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd]; + else (PCB).ss[(PCB).ssx] = (PCB).sn; + (PCB).reduction_token = (a85parse_token_type) ag_ptt[(PCB).ag_ap]; + ag_ra(); + while ((PCB).exit_flag == AG_RUNNING_CODE) { + unsigned ag_t1 = ag_sbe[(PCB).sn] + 1; + unsigned ag_t2 = ag_sbt[(PCB).sn+1] - 1; + do { + unsigned ag_tx = (ag_t1 + ag_t2)/2; + if (ag_tstt[ag_tx] < (const unsigned short)(PCB).reduction_token) ag_t1 = ag_tx + 1; + else ag_t2 = ag_tx; + } while (ag_t1 < ag_t2); + (PCB).ag_ap = ag_pstt[ag_t1]; + if ((ag_s_procs_scan[ag_astt[ag_t1]])() == 0) break; + } + return 0; } void init_a85parse(void) { (PCB).rx = (PCB).fx = 0; - (PCB).gt_procs = ag_gt_procs_scan; - (PCB).r_procs = ag_r_procs_scan; - (PCB).s_procs = ag_s_procs_scan; - (PCB).ag_error_depth = (PCB).ag_min_depth = (PCB).ag_tmp_depth = 0; - (PCB).ag_resynch_active = 0; (PCB).ss[0] = (PCB).sn = (PCB).ssx = 0; (PCB).exit_flag = AG_RUNNING_CODE; (PCB).line = FIRST_LINE; @@ -6744,7 +6872,7 @@ void a85parse(void) { ag_t1 = ag_sbe[(PCB).sn]; } (PCB).ag_ap = ag_pstt[ag_t1]; - (*(PCB).gt_procs[ag_astt[ag_t1]])(); + (ag_gt_procs_scan[ag_astt[ag_t1]])(); } } diff --git a/src/a85parse.h b/src/a85parse.h index 06b51a9..f935f7d 100644 --- a/src/a85parse.h +++ b/src/a85parse.h @@ -1,5 +1,5 @@ -#ifndef A85PARSE_H_1147178743 -#define A85PARSE_H_1147178743 +#ifndef A85PARSE_H_1176345433 +#define A85PARSE_H_1176345433 typedef union { long alignment; @@ -16,26 +16,26 @@ typedef enum { a85parse_singlequote_chars_token, a85parse_a85parse_token = 22, a85parse_statement_token, a85parse_eof_token = 26, a85parse_comment_token, a85parse_any_text_char_token = 29, a85parse_newline_token = 32, - a85parse_expression_token = 41, a85parse_equation_token = 55, - a85parse_expression_list_token = 64, a85parse_name_list_token = 67, - a85parse_condition_token = 74, a85parse_instruction_list_token = 82, - a85parse_literal_alpha_token = 84, a85parse_digit_token = 87, - a85parse_asm_incl_char_token, a85parse_string_char_token = 91, - a85parse_condition_start_token = 98, - a85parse_inclusive_or_exp_token = 118, a85parse_exclusive_or_exp_token, - a85parse_and_exp_token = 122, a85parse_shift_exp_token = 125, - a85parse_additive_exp_token = 128, - a85parse_multiplicative_exp_token = 133, a85parse_urinary_exp_token = 136, - a85parse_primary_exp_token = 138, a85parse_value_token = 146, - a85parse_function_token, a85parse_hex_digit_token = 166, - a85parse_stack_register_token = 181, a85parse_bd_register_token = 183, - a85parse_instruction_token, a85parse_rst_arg_token = 260, - a85parse_label_token = 289, a85parse_literal_string_token, - a85parse_include_string_token = 292, a85parse_asm_include_token, - a85parse_literal_name_token = 298, - a85parse_singlequote_string_token = 323, a85parse_integer_token = 325, - a85parse_real_token = 373, a85parse_register_8_bit_token = 380, - a85parse_register_16_bit_token = 401 + a85parse_expression_token = 41, a85parse_error_token = 43, + a85parse_equation_token = 56, a85parse_expression_list_token = 65, + a85parse_name_list_token = 68, a85parse_condition_token = 75, + a85parse_instruction_list_token = 83, a85parse_literal_alpha_token = 85, + a85parse_digit_token = 88, a85parse_asm_incl_char_token, + a85parse_string_char_token = 92, a85parse_condition_start_token = 99, + a85parse_inclusive_or_exp_token = 119, a85parse_exclusive_or_exp_token, + a85parse_and_exp_token = 123, a85parse_shift_exp_token = 126, + a85parse_additive_exp_token = 129, + a85parse_multiplicative_exp_token = 134, a85parse_urinary_exp_token = 137, + a85parse_primary_exp_token = 139, a85parse_value_token = 147, + a85parse_function_token, a85parse_hex_digit_token = 167, + a85parse_stack_register_token = 182, a85parse_bd_register_token = 184, + a85parse_instruction_token, a85parse_rst_arg_token = 261, + a85parse_label_token = 290, a85parse_literal_string_token, + a85parse_include_string_token = 293, a85parse_asm_include_token, + a85parse_literal_name_token = 299, + a85parse_singlequote_string_token = 324, a85parse_integer_token = 326, + a85parse_real_token = 374, a85parse_register_8_bit_token = 381, + a85parse_register_16_bit_token = 402 } a85parse_token_type; typedef struct a85parse_pcb_struct{ @@ -52,16 +52,10 @@ typedef struct a85parse_pcb_struct{ char read_flag; char exit_flag; int bts[128], btsx; - int (* const *gt_procs)(void); - int (* const *r_procs)(void); - int (* const *s_procs)(void); int lab[9], rx, fx; const unsigned char *key_sp; int save_index, key_state; - int ag_error_depth, ag_min_depth, ag_tmp_depth; - int ag_rss[2*128], ag_lrss; char ag_msg[82]; - int ag_resynch_active; } a85parse_pcb_type; #ifndef PRULE_CONTEXT diff --git a/src/a85parse.syn b/src/a85parse.syn index 8e2fb1a..fbc5960 100644 --- a/src/a85parse.syn +++ b/src/a85parse.syn @@ -7,7 +7,9 @@ } [ - auto resynch +// auto resynch + diagnose errors + error frame disregard WS disregard cstyle comment distinguish lexemes @@ -72,7 +74,8 @@ statement -> WS?..., expression, comment -> WS?..., comment -> WS?..., newline - -> WS?..., cstyle comment + -> WS?..., cstyle comment + -> error, '\n' expression -> label @@ -125,11 +128,12 @@ expression expression list -> literal string = expression_list_literal(); - -> singlequote string + -> singlequote string = expression_list_literal(); -> equation = expression_list_equation(); -> expression list, WS?..., ",", WS?..., equation = expression_list_equation(); -> expression list, WS?..., ",", WS?..., literal string = expression_list_literal(); -> expression list, WS?..., ",", WS?..., singlequote string = expression_list_literal(); + [ hidden {expression list} ] /* ============================================================================ @@ -140,7 +144,7 @@ expression list name list -> literal name = gNameList->Add(ss[ss_idx--]); - -> name list, WS?..., ",", WS?..., literal name = gNameList->Add(ss[ss_idx--]); + -> name list, WS?..., ",", WS?..., literal name = gNameList->Add(ss[ss_idx--]); literal name -> literal alpha @@ -161,6 +165,7 @@ singlequote string singlequote chars -> '\'', escape char:ch1, escape char:ch2 = { ss_idx++; ss_len = 2; sprintf(ss[ss_idx], "%c%c", ch1, ch2); } -> singlequote chars, escape char:c = { ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } +[ hidden {singlequote chars} ] literal string -> string chars, '"' @@ -170,6 +175,7 @@ string chars -> string chars, string char:c = { ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -> string chars, '\\', ~eof - '\n':c = { ss[ss_idx][ss_len++] = '\\'; ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -> string chars, '\\', '\n' +[ hidden {string chars} ] include string -> include chars, '>' = { ss[ss_idx][ss_len++] = '>'; ss[ss_idx][ss_len] = 0; } @@ -179,6 +185,7 @@ include chars -> include chars, string char - '>':c = { ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -> include chars, '\\', ~eof - '\n':c = { ss[ss_idx][ss_len++] = '\\'; ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -> include chars, '\\', '\n' +[ hidden {include chars} ] label -> literal name, ":" = gAsm->label(ss[ss_idx--]); @@ -202,8 +209,9 @@ condition start -> equation, {"le" | "<="} = condition(COND_LE); -> equation, {"gt" | ">"} = condition(COND_GT); -> equation, {"lt" | "<"} = condition(COND_LT); +[ hidden {condition start} ] -condition start +//condition start // -> equation = { gCond->m_EqLeft = gEq; gEq = new CRpnEquation; } // -> equation, {"eq" | "==" | "="}, equation = condition(COND_EQ); // -> equation, {"ne" | "!="}, equation = condition(COND_NE); @@ -318,6 +326,7 @@ asm hex value (int) ascii integer -> '\'', escape char:n, '\'' = n; + -> '\'', escape char:n1, escape char:n2, '\'' = (n1 << 8) | n2; -> "'\\'" = '\\'; (int) escape char @@ -337,6 +346,7 @@ asm hex value -> decimal integer, '.' = { gDivisor = 1.0; return (double) conv_to_dec(); } -> '.', '0-9':d = { gDivisor = 10.0; return ((double) (d - '0') / gDivisor); } -> simple real:r, '0-9':d = { gDivisor *= 10.0; return (r + (double) (d - '0') / gDivisor); } +[ hidden {simple real} ] /* @@ -569,7 +579,11 @@ BOOL ParseASMFile(const char* filename, VTAssembler* pAsm) // Try to open the file if ((gAsm->m_fd = fopen(gAsm->m_Filenames[gAsm->m_FileIndex], "r")) == 0) + { + // Add error indicating failure to open file + gAsm->m_Errors.Add("Error opening file"); return FALSE; + } // Reset the string stack ss_idx = 0; @@ -600,11 +614,15 @@ BOOL ParseASMFile(const char* filename, VTAssembler* pAsm) #define TAB_SPACING gTabSize -#define GET_INPUT ((PCB).input_code = gAsm->m_fd != 0 ? \ - fgetc(gAsm->m_fd) : 0) +#define GET_INPUT {(PCB).input_code = gAsm->m_fd != 0 ? \ + fgetc(gAsm->m_fd) : 0; if ((PCB).input_code == 13) (PCB).input_code = fgetc(gAsm->m_fd);} -#define SYNTAX_ERROR {MString string; string.Format("%s, line %d, column %d", \ - (PCB).error_message, (PCB).line, (PCB).column); gAsm->m_Errors.Add(string); } +#define SYNTAX_ERROR {MString string; if ((PCB).error_frame_token != 0) \ + string.Format("Malformed %s - %s, line %d, column %d", \ + TOKEN_NAMES[(PCB).error_frame_token], (PCB).error_message, (PCB).line, (PCB).column); else \ + string.Format("%s, line %d, column %d", \ + (PCB).error_message, (PCB).line, (PCB).column); \ + gAsm->m_Errors.Add(string); ss_idx = 0; ss_len = 0; } #define PARSER_STACK_OVERFLOW {MString string; string.Format(\ "\nParser stack overflow, line %d, column %d",\ diff --git a/src/assemble.cpp b/src/assemble.cpp index 531fe77..875e920 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -150,8 +150,16 @@ void VTAssembler::ResetContent(void) // Remove all items from Publics array. The actual items are duplicates // and will be deleted elsewhere m_Publics[seg].RemoveAll(); + + // Delete the CModule and create a new one + delete m_ActiveMod; + m_ActiveMod = new CModule; + m_Symbols = m_ActiveMod->m_Symbols[ASEG]; + m_Instructions = m_ActiveMod->m_Instructions[ASEG]; + m_ActiveAddr = m_ActiveMod->m_ActiveAddr[ASEG]; } + // Delete all Extern reference object count = m_Externs.GetSize(); for (c = 0; c < count; c++) @@ -174,6 +182,14 @@ void VTAssembler::ResetContent(void) m_Hex = 0; m_List = 0; m_Address = 0; + m_DebugInfo = 0; + m_LastLabelAdded = 0; + + // Clean up include stack + while (m_IncludeDepth != 0) + fclose(m_IncludeStack[--m_IncludeDepth]); + for (c = 0; c < 32; c++) + m_IncludeName[c] = ""; // Initialize IF stack m_IfDepth = 0; @@ -240,10 +256,13 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, // Try to find variable in equate array temp = op.m_Variable; local = 0; - if ((temp[0] == '$') && (temp[1] != 0)) + if (temp.GetLength() > 1) { - temp = m_LastLabel + "%%" + op.m_Variable; - local = 1; + if ((temp[0] == '$') && (temp[1] != 0)) + { + temp = m_LastLabel + "%%" + op.m_Variable; + local = 1; + } } pStr = (const char *) temp; symbol = (CSymbol *) 0; @@ -297,8 +316,22 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, errMsg.Format("Error in line %d(%s): Local symbol %s undefined", m_Line, (const char *) m_Filenames[m_FileIndex], (const char *) op.m_Variable); else + { + // Check if AuotExtern is enabled + if (m_AsmOptions.Find("-e") != -1) + { + // Add symbol as an EXTERN + symbol = new CSymbol; + symbol->m_Line = m_Line; + symbol->m_FileIndex = m_FileIndex; // Save index of the current file + symbol->m_Name = op.m_Variable; + symbol->m_SymType = SYM_EXTERN; + (*m_Symbols)[symbol->m_Name] = symbol; + return 0; + } errMsg.Format("Error in line %d(%s): Symbol %s undefined", m_Line, (const char *) m_Filenames[m_FileIndex], (const char *) op.m_Variable); + } m_Errors.Add(errMsg); m_UndefSymbols[op.m_Variable] = 0; } @@ -731,6 +764,10 @@ This function is called when the parser detects an include operation. */ void VTAssembler::include(const char *filename) { + int count, c; + MString incPathFile; + FILE* fd; + // Determine if conditional assembly enabled if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) return; @@ -739,7 +776,23 @@ void VTAssembler::include(const char *filename) m_Line = (PCB).line; // Try to open the file - if ((m_fd = fopen(filename, "rb")) == 0) + fd = fopen(filename, "rb"); + + // If file did not open, then look in include directories + if (fd == 0) + { + count = m_IncludeDirs.GetSize(); + for (c = 0; c < count; c++) + { + incPathFile = m_IncludeDirs[c] + filename; + fd = fopen((const char *) incPathFile, "rb"); + if (fd != 0) + break; + } + } + + // Check if file was found in any of the directories + if (fd == 0) { MString errMsg; errMsg.Format("Error in line %d(%s): Unable to open include file %s", @@ -747,17 +800,21 @@ void VTAssembler::include(const char *filename) m_Errors.Add(errMsg); return; } else { -// m_IncludeName[m_IncludeDepth] = m_Filename; m_IncludeIndex[m_IncludeDepth] = m_FileIndex; m_IncludeStack[m_IncludeDepth++] = m_fd; - m_FileIndex = m_Filenames.Add(filename); -// m_Filename = filename; + // Check if this file already in the m_Filenames list! + + m_FileIndex = m_Filenames.Add(filename); + + // Now loading from a different FD! + m_fd = fd; a85parse(); fclose(m_fd); + + // Restore the previous FD m_fd = m_IncludeStack[--m_IncludeDepth]; -// m_Filename = m_IncludeName[m_IncludeDepth]; m_FileIndex = m_IncludeIndex[m_IncludeDepth]; } } @@ -1158,7 +1215,7 @@ void VTAssembler::directive_aseg() m_ActiveAddr = m_ActiveMod->m_ActiveAddr[ASEG]; // Update address location - m_Address = m_ActiveMod->m_Address[ASEG]; + m_Address = (unsigned short) m_ActiveMod->m_Address[ASEG]; } void VTAssembler::directive_cseg(int page) @@ -1183,7 +1240,7 @@ void VTAssembler::directive_cseg(int page) m_ActiveAddr = m_ActiveMod->m_ActiveAddr[CSEG]; // Update address location - m_Address = m_ActiveMod->m_Address[CSEG]; + m_Address = (unsigned short) m_ActiveMod->m_Address[CSEG]; } void VTAssembler::directive_dseg(int page) @@ -1208,7 +1265,7 @@ void VTAssembler::directive_dseg(int page) m_ActiveAddr = m_ActiveMod->m_ActiveAddr[DSEG]; // Update address location - m_Address = m_ActiveMod->m_Address[DSEG]; + m_Address = (unsigned short) m_ActiveMod->m_Address[DSEG]; } void VTAssembler::directive_ds() @@ -2408,9 +2465,9 @@ int VTAssembler::CreateObjFile(const char *filename) if (pSymbol->m_Name == pExt->m_Name) { if (pExt->m_Size == 1) - pExt->m_SymIdx = pSymbol->m_Off8; + pExt->m_SymIdx = (unsigned short) pSymbol->m_Off8; else - pExt->m_SymIdx = pSymbol->m_Off16; + pExt->m_SymIdx = (unsigned short) pSymbol->m_Off16; } } } @@ -2718,6 +2775,9 @@ int VTAssembler::CreateObjFile(const char *filename) Add debug sections to .OBJ file ======================================= */ + if (m_AsmOptions.Find("-g") >= 0) + { + } /* @@ -2879,9 +2939,14 @@ int VTAssembler::EquationIsExtern(CRpnEquation* pEq, int size) void VTAssembler::Parse(MString filename) { int success = 1; - MString outfile; \ + MString outfile; MString temp; + + // Clean up the assembler files from previous assembler + ResetContent(); + + // Try to assemble the file if (success = ParseASMFile(filename, this)) { // No parse errors! Try to assemble @@ -2898,34 +2963,38 @@ void VTAssembler::Parse(MString filename) outfile = filename; // Append .obj to filename + temp = outfile; outfile += ".obj"; // Generate the object file CreateObjFile(outfile); // Generate a listing file if requested + CreateList(temp); } } +} - // If not successful, display list of errors - if (!success) - { - char str[120]; - int count, c; +void VTAssembler::CreateList(MString& filename) +{ + MString outfile; + FILE* fd; - count = m_Errors.GetSize(); - for (c = 0; c < count; c++) + if ((m_AsmOptions.Find("-l") != -1) || (m_List)) + { + if ((strcmp(filename, ".asm") == 0) || (strcmp(filename, "a85") == 0)) { - strcpy(str, m_Errors[c]); + outfile = filename.Left(filename.GetLength()-4); } - } + else + outfile = filename; - // Clean up the assembler files - ResetContent(); -} + // Append .lst to filename + outfile += ".lst"; -void VTAssembler::CreateList() -{ + fd = fopen(outfile, "wb+"); + fclose(fd); + } } void VTAssembler::CreateHex() @@ -3032,3 +3101,68 @@ CInstruction::~CInstruction() } } } + +void VTAssembler::SetAsmOptions(const MString& options) +{ + // Set the options string in case we need it later + m_AsmOptions = options; + + // Parse the options later during assembly +} + +void VTAssembler::SetIncludeDirs(const MString& dirs) +{ + // Save the string in case we need it later + m_IncludePath = dirs; + + // Recalculate the include directories + CalcIncludeDirs(); +} + +void VTAssembler::SetDefines(const MString& defines) +{ + // Save the string in case we need it later + m_ExtDefines = defines; +} + +void VTAssembler::SetRootPath(const MString& path) +{ + // Save the string in case we need it later + m_RootPath = path; + + // Recalculate the include directories + CalcIncludeDirs(); +} + +void VTAssembler::CalcIncludeDirs(void) +{ + char* pStr; + char* pToken; + MString temp; + + m_IncludeDirs.RemoveAll(); + + // Check if there is an include path + if (m_IncludePath.GetLength() == 0) + return; + + // Copy path to a char array so we can tokenize + pStr = new char[m_IncludePath.GetLength()]; + strcpy(pStr, (const char *) m_IncludePath); + + pToken = strtok(pStr, ",;"); + while (pToken != NULL) + { + // Generate the path + temp = pToken; + temp.Trim(); + temp += "/"; + temp = m_RootPath + "/" + temp; + + // Now add it to the array + m_IncludeDirs.Add(temp); + + // Get next token + pToken = strtok(NULL, ",;"); + } +} diff --git a/src/assemble.h b/src/assemble.h index 5f6fad6..c6e8164 100644 --- a/src/assemble.h +++ b/src/assemble.h @@ -331,7 +331,7 @@ class VTAssembler : public VTObject VTMapStringToOb* m_Symbols; // Array of Symbols VTObArray* m_Instructions; // Array of Instructions - long m_Address; + unsigned short m_Address; MStringArray m_Filenames; // Array of filenames parsed during assembly MString m_LastLabel; // Save value of last label parsed CSymbol* m_LastLabelSym; // Pointer to CSymbol object for last label @@ -350,6 +350,11 @@ class VTAssembler : public VTObject FILE* m_IncludeStack[32]; int m_IncludeIndex[32]; int m_IncludeDepth; + MString m_AsmOptions; // Assembler options + MString m_IncludePath; + MString m_ExtDefines; // External additional defines + MString m_RootPath; // Root path of project. + MStringArray m_IncludeDirs; // Array of '/' terminated include dirs char m_IfStat[100]; int m_IfDepth; @@ -358,16 +363,24 @@ class VTAssembler : public VTObject // Operations int Evaluate(class CRpnEquation* eq, double* value, int reportError); + int Assemble(); int GetValue(MString & string, int & value); void ResetContent(void); - int Assemble(); int CreateObjFile(const char *filename); int InvalidRelocation(CRpnEquation* pEq, char &rel_mask); int EquationIsExtern(CRpnEquation* pEq, int size); - void Parse(MString filename); void MakeBinary(int val, int length, MString& binary); void CreateHex(); - void CreateList(); + void CreateList(MString& filename); + void CalcIncludeDirs(); + +// Public Access functions + void Parse(MString filename); + void SetAsmOptions(const MString& options); + void SetIncludeDirs(const MString& dirs); + void SetDefines(const MString& defines); + void SetRootPath(const MString& rootPath); + const MStringArray& GetErrors() { return m_Errors; }; }; #endif diff --git a/src/clientsocket.cpp b/src/clientsocket.cpp new file mode 100644 index 0000000..540ead2 --- /dev/null +++ b/src/clientsocket.cpp @@ -0,0 +1,42 @@ +// Implementation of the ClientSocket class + +#include "clientsocket.h" +#include "socketexception.h" + + +ClientSocket::ClientSocket ( std::string host, int port ) +{ + if ( ! Socket::create() ) + { + throw SocketException ( "Could not create client socket." ); + } + + if ( ! Socket::connect ( host, port ) ) + { + throw SocketException ( "Could not bind to port." ); + } + +} + + +const ClientSocket& ClientSocket::operator << ( const std::string& s ) const +{ + if ( ! Socket::send ( s ) ) + { + throw SocketException ( "Could not write to socket." ); + } + + return *this; + +} + + +const ClientSocket& ClientSocket::operator >> ( std::string& s ) const +{ + if ( ! Socket::recv ( s ) ) + { + throw SocketException ( "Could not read from socket." ); + } + + return *this; +} diff --git a/src/clientsocket.h b/src/clientsocket.h new file mode 100644 index 0000000..4b42c08 --- /dev/null +++ b/src/clientsocket.h @@ -0,0 +1,22 @@ +// Definition of the ClientSocket class + +#ifndef ClientSocket_class +#define ClientSocket_class + +#include "socket.h" + + +class ClientSocket : private Socket +{ + public: + + ClientSocket ( std::string host, int port ); + virtual ~ClientSocket(){}; + + const ClientSocket& operator << ( const std::string& ) const; + const ClientSocket& operator >> ( std::string& ) const; + +}; + + +#endif diff --git a/src/cpu.h b/src/cpu.h index 18a2b9d..b37fe8e 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -104,16 +104,21 @@ extern int gIndex[65536]; #define cpuMISC cpu[13] #define CF (F&0x01) -#define XF ((F&0x02)>>1) -#define XF_BIT 0x02 +#define CF_BIT 0x01 #define OV ((F&0x02)>>1) #define OV_BIT 0x02 #define PF ((F&0x04)>>2) +#define PF_BIT 0x04 +#define TS ((F&0x08)>>3) +#define TS_BIT 0x08 #define AC ((F&0x10)>>4) -#define TS ((F&0x20)>>5) -#define TS_BIT 0x20 +#define AC_BIT 0x10 +#define XF ((F&0x20)>>5) +#define XF_BIT 0x20 #define ZF ((F&0x40)>>6) +#define ZF_BIT 0x40 #define SF ((F&0x80)>>7) +#define SF_BIT 0x80 #define RST55MASK (IM&0x01) #define RST65MASK ((IM&0x02)>>1) #define RST75MASK ((IM&0x04)>>2) diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index 8b7cebe..633e170 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -3,29 +3,29 @@ /* $Id$ */ /* - * Copyright 2006 Ken Pettit - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ +* Copyright 2006 Ken Pettit +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +*/ #include #include @@ -52,13 +52,14 @@ void cb_Ide(Fl_Widget* w, void*) ; +VTDis cpu_dis; /* ============================================================================ Global variables ============================================================================ */ cpuregs_ctrl_t cpuregs_ctrl; -Fl_Window *gcpuw; +Fl_Window *gcpuw = NULL; int gStopCountdown = 0; int gSaveFreq = 0; int gDisableRealtimeTrace = 0; @@ -72,13 +73,13 @@ Fl_Menu_Item gCpuRegs_menuitems[] = { { "Disassembler", 0, disassembler_cb }, { "Memory Editor", 0, cb_MemoryEditor }, { "Peripheral Devices", 0, cb_PeripheralDevices }, - { "Simulation Log Viewer", 0, 0 }, +// { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, 0 }, { 0 }, { 0 } }; -void debug_cpuregs_cb (void); +void debug_cpuregs_cb (int); /* ============================================================================ @@ -87,7 +88,7 @@ Callback routine for the CPU Regs window */ void cb_cpuregswin (Fl_Widget* w, void*) { - // Hide the window + // Hide the window gcpuw->hide(); // Disable debug processes @@ -147,6 +148,7 @@ void get_reg_edits(void) { const char* pStr; int val, flags; + int x; // Get value of PC pStr = cpuregs_ctrl.pRegPC->value(); @@ -188,7 +190,7 @@ void get_reg_edits(void) if (val != BC) { // Update the values of B and C from the BC edit field - B = val >> 8; + B = val >> 8; C = val & 0xFF; } else @@ -218,7 +220,7 @@ void get_reg_edits(void) if (val != DE) { // Update the values of D and E from the DE edit field - D = val >> 8; + D = val >> 8; E = val & 0xFF; } else @@ -248,7 +250,7 @@ void get_reg_edits(void) if (val != HL) { // Update the values of H and L from the HL edit field - H = val >> 8; + H = val >> 8; L = val & 0xFF; } else @@ -288,6 +290,70 @@ void get_reg_edits(void) flags |= 0x01; F = flags; + + // Get value of Breakpoint 1 + pStr = cpuregs_ctrl.pBreak1->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + cpuregs_ctrl.breakAddr[0] = val; + } + else + cpuregs_ctrl.breakAddr[0] = -1; + + // Get value of Breakpoint 2 + pStr = cpuregs_ctrl.pBreak2->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + cpuregs_ctrl.breakAddr[1] = val; + } + else + cpuregs_ctrl.breakAddr[1] = -1; + + // Get value of Breakpoint 3 + pStr = cpuregs_ctrl.pBreak3->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + cpuregs_ctrl.breakAddr[2] = val; + } + else + cpuregs_ctrl.breakAddr[2] = -1; + + // Get value of Breakpoint 4 + pStr = cpuregs_ctrl.pBreak4->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + cpuregs_ctrl.breakAddr[3] = val; + } + else + cpuregs_ctrl.breakAddr[3] = -1; + + // Check if any breakpoints set + for (x = 0; x < 4; x++) + if (cpuregs_ctrl.breakAddr[x] != -1) + break; + + // If no breakpoints set, restore old monitor frequency + if (x == 4) + { + if (cpuregs_ctrl.breakMonitorFreq != 0) + gSaveFreq = cpuregs_ctrl.breakMonitorFreq; + } + else + { + if (cpuregs_ctrl.breakMonitorFreq == 0) + cpuregs_ctrl.breakMonitorFreq = gSaveFreq; + gSaveFreq = 1; + gDebugMonitorFreq = 1; + } + + cpuregs_ctrl.breakEnable[0] = !cpuregs_ctrl.pBreakDisable1->value(); + cpuregs_ctrl.breakEnable[1] = !cpuregs_ctrl.pBreakDisable2->value(); + cpuregs_ctrl.breakEnable[2] = !cpuregs_ctrl.pBreakDisable3->value(); + cpuregs_ctrl.breakEnable[3] = !cpuregs_ctrl.pBreakDisable4->value(); } /* @@ -315,9 +381,9 @@ void cb_redraw_trace(Fl_Widget* w, void*) draw = cpuregs_ctrl.iInstTraceHead; for (x = 0; x < 8; x++) { - // Draw the Stack + // Draw the Stack sprintf(str, "0x%02X", get_memory8(SP+x)); - fl_draw(str, 560, 212+MENU_HEIGHT+x*15); + fl_draw(str, 560, 212+MENU_HEIGHT+x*15); // Now draw the Instruction Trace if (x == 7) @@ -349,22 +415,90 @@ char get_m() return gBaseMemory[HL]; } +/* +============================================================================ +activate_controls: This routine activates all the CPU controls except the +STOP button, which it deactivates. +============================================================================ +*/ +void activate_controls() +{ + // Change activation state of processor controls + cpuregs_ctrl.pStop->deactivate(); + cpuregs_ctrl.pStep->activate(); + cpuregs_ctrl.pRun->activate(); + cpuregs_ctrl.pRedraw->activate(); + + // Activate the edit fields to allow register updates + cpuregs_ctrl.pRegA->activate(); + cpuregs_ctrl.pRegB->activate(); + cpuregs_ctrl.pRegC->activate(); + cpuregs_ctrl.pRegD->activate(); + cpuregs_ctrl.pRegE->activate(); + cpuregs_ctrl.pRegH->activate(); + cpuregs_ctrl.pRegL->activate(); + cpuregs_ctrl.pRegPC->activate(); + cpuregs_ctrl.pRegSP->activate(); + cpuregs_ctrl.pRegBC->activate(); + cpuregs_ctrl.pRegDE->activate(); + cpuregs_ctrl.pRegHL->activate(); + cpuregs_ctrl.pRegM->activate(); + + // Activate Flags + cpuregs_ctrl.pSFlag->activate(); + cpuregs_ctrl.pZFlag->activate(); + cpuregs_ctrl.pCFlag->activate(); + cpuregs_ctrl.pTSFlag->activate(); + cpuregs_ctrl.pACFlag->activate(); + cpuregs_ctrl.pPFlag->activate(); + cpuregs_ctrl.pOVFlag->activate(); + cpuregs_ctrl.pXFlag->activate(); + + // Activate Breakpoints + cpuregs_ctrl.pBreak1->activate(); + cpuregs_ctrl.pBreak2->activate(); + cpuregs_ctrl.pBreak3->activate(); + cpuregs_ctrl.pBreak4->activate(); + cpuregs_ctrl.pBreakDisable1->activate(); + cpuregs_ctrl.pBreakDisable2->activate(); + cpuregs_ctrl.pBreakDisable3->activate(); + cpuregs_ctrl.pBreakDisable4->activate(); +} + +void clear_trace(void) +{ + int x; + + for (x = 0; x < 8; x++) + cpuregs_ctrl.sInstTrace[x][0] = 0; +} + /* ============================================================================ debug_cpuregs_cb: This routine is the callback for the CPURegs Monitor - window. This routine handles updating of Register + window. This routine handles updating of Register values while the CPU is running. ============================================================================ */ -void debug_cpuregs_cb (void) +void debug_cpuregs_cb (int reason) { char str[100]; char flags[10]; int x, len; // Check for breakpoint - if (PC == 0x5797) - gStopped = 1; + if (!gStopped) + { + for (x = 0; x < 4; x++) + { + if ((PC == cpuregs_ctrl.breakAddr[x]) && (cpuregs_ctrl.breakEnable[x])) + { + activate_controls(); + clear_trace(); + gStopped = 1; + } + } + } if (!gStopped) if (++gDebugCount < gDebugMonitorFreq) @@ -375,7 +509,7 @@ void debug_cpuregs_cb (void) // Update PC edit box sprintf(str, cpuregs_ctrl.sPCfmt, PC); cpuregs_ctrl.pRegPC->value(str); - + // Update SP edit box sprintf(str, cpuregs_ctrl.sSPfmt, SP); cpuregs_ctrl.pRegSP->value(str); @@ -437,7 +571,7 @@ void debug_cpuregs_cb (void) if (!gDisableRealtimeTrace || (gStopCountdown != 0) || gStopped) { // Disassemble 1 instruction - VTDis::DisassembleLine(PC, cpuregs_ctrl.sInstTrace[cpuregs_ctrl.iInstTraceHead]); + cpu_dis.DisassembleLine(PC, cpuregs_ctrl.sInstTrace[cpuregs_ctrl.iInstTraceHead]); // Append spaces after opcode len = 20 - strlen(cpuregs_ctrl.sInstTrace[cpuregs_ctrl.iInstTraceHead]); @@ -467,7 +601,7 @@ void debug_cpuregs_cb (void) if (--gStopCountdown == 0) { gStopped = 1; - gDebugMonitorFreq = gSaveFreq; + gDebugMonitorFreq = gSaveFreq; } } @@ -480,36 +614,7 @@ Routine to handle Stop button */ void cb_debug_stop(Fl_Widget* w, void*) { - // Change activation state of processor controls - cpuregs_ctrl.pStop->deactivate(); - cpuregs_ctrl.pStep->activate(); - cpuregs_ctrl.pRun->activate(); - cpuregs_ctrl.pRedraw->activate(); - - // Activate the edit fields to allow register updates - cpuregs_ctrl.pRegA->activate(); - cpuregs_ctrl.pRegB->activate(); - cpuregs_ctrl.pRegC->activate(); - cpuregs_ctrl.pRegD->activate(); - cpuregs_ctrl.pRegE->activate(); - cpuregs_ctrl.pRegH->activate(); - cpuregs_ctrl.pRegL->activate(); - cpuregs_ctrl.pRegPC->activate(); - cpuregs_ctrl.pRegSP->activate(); - cpuregs_ctrl.pRegBC->activate(); - cpuregs_ctrl.pRegDE->activate(); - cpuregs_ctrl.pRegHL->activate(); - cpuregs_ctrl.pRegM->activate(); - - // Activate Flags - cpuregs_ctrl.pSFlag->activate(); - cpuregs_ctrl.pZFlag->activate(); - cpuregs_ctrl.pCFlag->activate(); - cpuregs_ctrl.pTSFlag->activate(); - cpuregs_ctrl.pACFlag->activate(); - cpuregs_ctrl.pPFlag->activate(); - cpuregs_ctrl.pOVFlag->activate(); - cpuregs_ctrl.pXFlag->activate(); + activate_controls(); // Stop the processor gStopCountdown = 8; @@ -569,6 +674,16 @@ void cb_debug_run(Fl_Widget* w, void*) cpuregs_ctrl.pOVFlag->deactivate(); cpuregs_ctrl.pXFlag->deactivate(); + // Deactivate breakpoints + cpuregs_ctrl.pBreak1->deactivate(); + cpuregs_ctrl.pBreak2->deactivate(); + cpuregs_ctrl.pBreak3->deactivate(); + cpuregs_ctrl.pBreak4->deactivate(); + cpuregs_ctrl.pBreakDisable1->deactivate(); + cpuregs_ctrl.pBreakDisable2->deactivate(); + cpuregs_ctrl.pBreakDisable3->deactivate(); + cpuregs_ctrl.pBreakDisable4->deactivate(); + // Get Register updates get_reg_edits(); @@ -576,6 +691,39 @@ void cb_debug_run(Fl_Widget* w, void*) gStopped = 0; } +/* +============================================================================ +Routines to handle remote debugging commands +============================================================================ +*/ +int remote_cpureg_stop(void) +{ + if (gcpuw != NULL) + { + cb_debug_stop(NULL, NULL); + return 1; + } + return 0; +} +int remote_cpureg_run(void) +{ + if (gcpuw != NULL) + { + cb_debug_run(NULL, NULL); + return 1; + } + return 0; +} +int remote_cpureg_step(void) +{ + if (gcpuw != NULL) + { + cb_debug_step(NULL, NULL); + return 1; + } + return 0; +} + /* ============================================================================ Routine to handle Change to PC edit field @@ -596,7 +744,7 @@ void cb_reg_pc_changed(Fl_Widget* w, void*) trace_tail = 7; // Disassemble 1 instruction - VTDis::DisassembleLine(new_pc, cpuregs_ctrl.sInstTrace[trace_tail]); + cpu_dis.DisassembleLine(new_pc, cpuregs_ctrl.sInstTrace[trace_tail]); // Append spaces after opcode len = 20 - strlen(cpuregs_ctrl.sInstTrace[trace_tail]); @@ -784,7 +932,7 @@ void cb_reg_hl_changed(Fl_Widget* w, void*) // Update M edit box sprintf(str, cpuregs_ctrl.sMfmt, get_m()); cpuregs_ctrl.pRegM->value(str); - + } /* @@ -811,7 +959,7 @@ void cb_reg_h_changed(Fl_Widget* w, void*) // Update M edit box sprintf(str, cpuregs_ctrl.sMfmt, get_m()); cpuregs_ctrl.pRegM->value(str); - + } /* @@ -838,7 +986,7 @@ void cb_reg_l_changed(Fl_Widget* w, void*) // Update M edit box sprintf(str, cpuregs_ctrl.sMfmt, get_m()); cpuregs_ctrl.pRegM->value(str); - + } /* @@ -889,7 +1037,7 @@ Routine to handle Reg A Hex display mode ============================================================================ */ void cb_reg_a_hex(Fl_Widget* w, void*) -{ +{ char str[8]; strcpy(cpuregs_ctrl.sAfmt, "0x%02X"); @@ -1361,7 +1509,7 @@ void cb_reg_all_hex(Fl_Widget* w, void*) cpuregs_ctrl.pDEDec->value(0); cpuregs_ctrl.pHLDec->value(0); cpuregs_ctrl.pMDec->value(0); - + // Select all "Hex" buttons cpuregs_ctrl.pAHex->value(1); cpuregs_ctrl.pBHex->value(1); @@ -1450,7 +1598,7 @@ void cb_CpuRegs (Fl_Widget* w, void*) return; // Create Peripheral Setup window - gcpuw = new Fl_Window(630, 400, "CPU Registers"); + gcpuw = new Fl_Window(630, 480, "CPU Registers"); gcpuw->callback(cb_cpuregswin); // Create a menu for the new window. @@ -1468,7 +1616,7 @@ void cb_CpuRegs (Fl_Widget* w, void*) o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); o = new Fl_Box(FL_NO_BOX, 20, 120+MENU_HEIGHT, 50, 15, "H"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - + o = new Fl_Box(FL_NO_BOX, 120, 20+MENU_HEIGHT, 50, 15, "A"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); o = new Fl_Box(FL_NO_BOX, 120, 70+MENU_HEIGHT, 50, 15, "C"); @@ -1488,7 +1636,7 @@ void cb_CpuRegs (Fl_Widget* w, void*) o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - // Program Counter edit box + // Program Counter edit box cpuregs_ctrl.pRegPC = new Fl_Input(50, 19+MENU_HEIGHT, 60, 20, ""); cpuregs_ctrl.pRegPC->deactivate(); cpuregs_ctrl.pRegPC->callback(cb_reg_pc_changed); @@ -1691,7 +1839,7 @@ void cb_CpuRegs (Fl_Widget* w, void*) // Group the Reg D radio buttons togther { cpuregs_ctrl.g = new Fl_Group(370, 90 + MENU_HEIGHT, 100, 20, ""); - + // Display format for Reg D o = new Fl_Box(FL_NO_BOX, 340, 91+MENU_HEIGHT, 50, 15, "D"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); @@ -1884,7 +2032,7 @@ void cb_CpuRegs (Fl_Widget* w, void*) o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); o = new Fl_Box(FL_DOWN_BOX, 20, 200+MENU_HEIGHT, 520, 124, ""); cpuregs_ctrl.iInstTraceHead = 0; - + // Create checkbox to disable realtime trace cpuregs_ctrl.pDisableTrace = new Fl_Check_Button(200, 180+MENU_HEIGHT, 180, 20, "Disable Real-time Trace"); cpuregs_ctrl.pDisableTrace->callback(cb_disable_realtime_trace); @@ -1895,22 +2043,46 @@ void cb_CpuRegs (Fl_Widget* w, void*) o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); o = new Fl_Box(FL_DOWN_BOX, 550, 200+MENU_HEIGHT, 60, 124, ""); + // Create Breakpoint edit boxes + o = new Fl_Box(FL_NO_BOX, 20, 375, 100, 15, "Breakpoints:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + cpuregs_ctrl.pBreak1 = new Fl_Input(120, 375, 60, 20, ""); + cpuregs_ctrl.pBreak1->deactivate(); + cpuregs_ctrl.pBreak1->value(""); + cpuregs_ctrl.pBreakDisable1 = new Fl_Check_Button(125, 395, 40, 20, "Off"); + cpuregs_ctrl.pBreakDisable1->deactivate(); + cpuregs_ctrl.pBreak2 = new Fl_Input(200, 375, 60, 20, ""); + cpuregs_ctrl.pBreak2->deactivate(); + cpuregs_ctrl.pBreak2->value(""); + cpuregs_ctrl.pBreakDisable2 = new Fl_Check_Button(205, 395, 40, 20, "Off"); + cpuregs_ctrl.pBreakDisable2->deactivate(); + cpuregs_ctrl.pBreak3 = new Fl_Input(280, 375, 60, 20, ""); + cpuregs_ctrl.pBreak3->deactivate(); + cpuregs_ctrl.pBreak3->value(""); + cpuregs_ctrl.pBreakDisable3 = new Fl_Check_Button(285, 395, 40, 20, "Off"); + cpuregs_ctrl.pBreakDisable3->deactivate(); + cpuregs_ctrl.pBreak4 = new Fl_Input(360, 375, 60, 20, ""); + cpuregs_ctrl.pBreak4->deactivate(); + cpuregs_ctrl.pBreak4->value(""); + cpuregs_ctrl.pBreakDisable4 = new Fl_Check_Button(365, 395, 40, 20, "Off"); + cpuregs_ctrl.pBreakDisable4->deactivate(); + // Create Stop button - cpuregs_ctrl.pStop = new Fl_Button(30, 365, 80, 25, "Stop"); + cpuregs_ctrl.pStop = new Fl_Button(30, 445, 80, 25, "Stop"); cpuregs_ctrl.pStop->callback(cb_debug_stop); // Create Step button - cpuregs_ctrl.pStep = new Fl_Button(130, 365, 80, 25, "Step"); + cpuregs_ctrl.pStep = new Fl_Button(130, 445, 80, 25, "Step"); cpuregs_ctrl.pStep->deactivate(); cpuregs_ctrl.pStep->callback(cb_debug_step); // Create Run button - cpuregs_ctrl.pRun = new Fl_Button(230, 365, 80, 25, "Run"); + cpuregs_ctrl.pRun = new Fl_Button(230, 445, 80, 25, "Run"); cpuregs_ctrl.pRun->deactivate(); cpuregs_ctrl.pRun->callback(cb_debug_run); // Create Redraw button - cpuregs_ctrl.pRedraw = new Fl_Button(330, 365, 80, 25, "Redraw"); + cpuregs_ctrl.pRedraw = new Fl_Button(330, 445, 80, 25, "Redraw"); cpuregs_ctrl.pRedraw->deactivate(); cpuregs_ctrl.pRedraw->callback(cb_redraw_trace); @@ -1922,6 +2094,16 @@ void cb_CpuRegs (Fl_Widget* w, void*) // Indicate an active debug window gDebugActive++; + cpuregs_ctrl.breakMonitorFreq = 0; + cpuregs_ctrl.breakAddr[0] = -1; + cpuregs_ctrl.breakAddr[1] = -1; + cpuregs_ctrl.breakAddr[2] = -1; + cpuregs_ctrl.breakAddr[3] = -1; + cpuregs_ctrl.breakEnable[0] = 1; + cpuregs_ctrl.breakEnable[1] = 1; + cpuregs_ctrl.breakEnable[2] = 1; + cpuregs_ctrl.breakEnable[3] = 1; } + diff --git a/src/cpuregs.h b/src/cpuregs.h index 5da1f1e..7375678 100644 --- a/src/cpuregs.h +++ b/src/cpuregs.h @@ -3,29 +3,29 @@ /* $Id$ */ /* - * Copyright 2004 Ken Pettit - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ +* Copyright 2004 Ken Pettit +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +*/ #ifndef CPUREGS_H @@ -39,7 +39,7 @@ void cb_CpuRegs(Fl_Widget* w, void*); -typedef struct cpuregs_ctrl_struct +typedef struct cpuregs_ctrl_struct { Fl_Menu_Bar* pMenu; @@ -60,6 +60,15 @@ typedef struct cpuregs_ctrl_struct Fl_Input* pRegSP; Fl_Input* pRegM; + Fl_Input* pBreak1; + Fl_Input* pBreak2; + Fl_Input* pBreak3; + Fl_Input* pBreak4; + Fl_Check_Button* pBreakDisable1; + Fl_Check_Button* pBreakDisable2; + Fl_Check_Button* pBreakDisable3; + Fl_Check_Button* pBreakDisable4; + Fl_Check_Button* pSFlag; Fl_Check_Button* pZFlag; Fl_Check_Button* pTSFlag; @@ -97,12 +106,18 @@ typedef struct cpuregs_ctrl_struct Fl_Round_Button* pHLDec; Fl_Round_Button* pMHex; Fl_Round_Button* pMDec; + Fl_Round_Button* pBreakHex; + Fl_Round_Button* pBreakDec; Fl_Box* pInstTrace[8]; char sInstTrace[8][120]; int iInstTraceHead; Fl_Check_Button* pDisableTrace; + int breakAddr[4]; + int breakEnable[4]; + int breakMonitorFreq; + Fl_Button* pStop; Fl_Button* pStep; Fl_Button* pRun; @@ -121,6 +136,7 @@ typedef struct cpuregs_ctrl_struct char sDEfmt[8]; char sHLfmt[8]; char sMfmt[8]; + char sBreakfmt[8]; Fl_Group* g; @@ -128,3 +144,4 @@ typedef struct cpuregs_ctrl_struct #endif + diff --git a/src/disassemble.cpp b/src/disassemble.cpp index a316ce0..f6a7ef3 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -66,7 +66,7 @@ void close_cb(Fl_Widget* w, void*) } // Table of OPCODE -char * VTDis::m_StrTable[256] = { +char * gStrTable[256] = { "NOP", "LXI B,", "STAX B", "INX B", "INR B", "DCR B", "MVI B,", "RLC", "DSUB", "DAD B", "LDAX B", "DCX B", "INR C", "DCR C", "MVI C,", "RRC", @@ -117,7 +117,7 @@ char * VTDis::m_StrTable[256] = { }; // Table indicating length of each opcode -unsigned char VTDis::m_LenTable[256] = { +unsigned char gLenTable[256] = { 0,2,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,2,0,0,0,0,1,0, @@ -152,7 +152,6 @@ unsigned char VTDis::m_LenTable[256] = { 0,0,2,0,2,2,1,0 }; - // Menu items for the disassembler Fl_Menu_Item gDis_menuitems[] = { { "&File", 0, 0, 0, FL_SUBMENU }, @@ -166,7 +165,7 @@ Fl_Menu_Item gDis_menuitems[] = { { "Assembler / IDE", 0, cb_Ide }, { "Memory Editor", 0, cb_MemoryEditor }, { "Peripheral Devices", 0, cb_PeripheralDevices }, - { "Simulation Log Viewer", 0, 0 }, +// { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, 0 }, { 0 }, @@ -243,6 +242,8 @@ VTDis::VTDis() { m_StartAddress = 0; m_EndAddress = ROMSIZE-1; + m_BaseAddress = 0; + m_WantComments = 0; } void VTDis::SetTextViewer(Fl_Text_Editor *pTextViewer) @@ -250,11 +251,110 @@ void VTDis::SetTextViewer(Fl_Text_Editor *pTextViewer) m_pTextViewer = pTextViewer; } +void VTDis::AppendComments(char* line, int opcode, int address) +{ + int i, x, len, op_len; + + // Calculate # spaces to add for fixed line len (make comments line up) + len = 28 - strlen(line); + + // Determine length of this opcode + op_len = gLenTable[opcode] & 0x03; + + // Add comments for known addresses. Opcodes less that 128 are Variable + // spaces (these opcodes are LXI, LHLD, etc.) + if ((op_len == 2) && (opcode < 128)) + { + x = 0; + while (m_pRom->pVars[x].addr != -1) + { + if (m_pRom->pVars[x].addr == address) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; "); + strcat(line, gDisStrings[m_pRom->pVars[x].strnum].desc); + break; + } + + x++; + } + } + // Add comments for known function call addresses. Opcodes 128 and greater + // are CALLs and JMPs + if ((op_len == 2) && (opcode > 128)) + { + x = 0; + while (m_pRom->pFuns[x].addr != -1) + { + if (m_pRom->pFuns[x].addr == address) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; "); + strcat(line, gDisStrings[m_pRom->pFuns[x].strnum].desc); + break; + } + + x++; + } + } + + // Handle RST 1 Commenting + if (opcode == 0xCF) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; Compare next byte with M"); + } + // Handle RST 2 Commenting + if (opcode == 0xD7) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; Get next non-white char from M"); + } + // Handle RST 3 Commenting + if (opcode == 0xDF) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; Compare DE and HL"); + } + // Handle RST 4 Commenting + if (opcode == 0xE7) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; Send character in A to screen/printer"); + } + // Handle RST 5 Commenting + if (opcode == 0xEF) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; Determine type of last var used"); + } + // Handle RST 6 Commenting + if (opcode == 0xF7) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; Get sign of FAC1"); + } + // Handle RST 7 Commenting + if (opcode == 0xFF) + { + for (i = 0; i < len; i++) + strcat(line, " "); + strcat(line, "; Jump to RST 38H Vector entry of following byte"); + } +} + void VTDis::Disassemble() { int c; - int x, i; - int len; + int x; int table; char line[200]; char arg[60]; @@ -349,7 +449,7 @@ void VTDis::Disassemble() if (next + 1 == last) { - if (m_memory[next-1] & 0x80 == 0) + if ((m_memory[next-1] & 0x80) == 0) strcat(line, "\""); strcat(line, "\n\n"); tb->append(line); @@ -360,7 +460,8 @@ void VTDis::Disassemble() // Modified strings are those that start with a 0x80 and ends // when the next string is found (the next 0x80). All the // BASIC keywords are stored this way - else if (m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING2) + else if ((m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING2) + || (m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING3)) { int next; int last = c + m_pRom->pTables[x].size; @@ -378,7 +479,13 @@ void VTDis::Disassemble() { sprintf(arg, "\",'%c' or 80H", m_memory[next] & 0x7F); strcat(line, arg); - sprintf(arg, ", %02XH\n", m_memory[next+1]); + if (m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING2) + { + sprintf(arg, ", %02XH\n", m_memory[next+1]); + next++; + } + else + strcpy(arg, "\n"); strcat(line, arg); // if ((m_memory[next-1] & 0x80) == 0) // strcat(line, "\""); @@ -386,7 +493,6 @@ void VTDis::Disassemble() tb->append(line); line[0]=0; str_active = 0; - next++; continue; } if (!str_active) @@ -394,12 +500,17 @@ void VTDis::Disassemble() if (m_memory[next] & 0x80) { sprintf(line, "%04XH DB '%c' OR 80H", next, m_memory[next] & 0x7F); - sprintf(arg, ", %02XH\n", m_memory[next+1]); + if (m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING2) + { + sprintf(arg, ", %02XH\n", m_memory[next+1]); + next++; + } + else + strcpy(arg, "\n"); strcat(line, arg); tb->append(line); line[0]=0; str_active = 0; - next++; continue; } else @@ -416,7 +527,7 @@ void VTDis::Disassemble() if (next + 1 == last) { - if (m_memory[next-1] & 0x80 == 0) + if ((m_memory[next-1] & 0x80) == 0) strcat(line, "\""); strcat(line, "\n\n"); tb->append(line); @@ -699,13 +810,13 @@ void VTDis::Disassemble() opcode = m_memory[c]; // Determine length of this opcode - op_len = m_LenTable[opcode] & 0x03; + op_len = gLenTable[opcode] & 0x03; // Print the address and opcode value to the temporary line buffer sprintf(line, "%04XH (%02XH) ", c, opcode); // Print the opcode text to the temp line buffer - strcat(line, m_StrTable[opcode]); + strcat(line, gStrTable[opcode]); // Check if this opcode has a single byte argument if (op_len == 1) @@ -724,104 +835,14 @@ void VTDis::Disassemble() strcat(line, arg); } - // Calculate # spaces to add for fixed line len (make comments line up) - len = 28 - strlen(line); + AppendComments(line, opcode, addr); - // Add comments for known addresses. Opcodes less that 128 are Variable - // spaces (these opcodes are LXI, LHLD, etc.) - if ((op_len == 2) && (opcode < 128)) - { - x = 0; - while (m_pRom->pVars[x].addr != -1) - { - if (m_pRom->pVars[x].addr == addr) - { - for (i = 0; i < len; i++) - strcat(line, " "); - strcat(line, "; "); - strcat(line, gDisStrings[m_pRom->pVars[x].strnum].desc); - break; - } - - x++; - } - } - // Add comments for known function call addresses. Opcodes 128 and greater - // are CALLs and JMPs - if ((op_len == 2) && (opcode > 128)) - { - x = 0; - while (m_pRom->pFuns[x].addr != -1) - { - if (m_pRom->pFuns[x].addr == addr) - { - for (i = 0; i < len; i++) - strcat(line, " "); - strcat(line, "; "); - strcat(line, gDisStrings[m_pRom->pFuns[x].strnum].desc); - break; - } - - x++; - } - } - - // Handle RST 1 Commenting - if (opcode == 0xCF) - { - for (i = 0; i < len; i++) - strcat(line, " "); - strcat(line, "; Compare next byte with M"); - } - // Handle RST 2 Commenting - if (opcode == 0xD7) - { - for (i = 0; i < len; i++) - strcat(line, " "); - strcat(line, "; Get next non-white char from M"); - } - // Handle RST 3 Commenting - if (opcode == 0xDF) - { - for (i = 0; i < len; i++) - strcat(line, " "); - strcat(line, "; Compare DE and HL"); - } - // Handle RST 4 Commenting - if (opcode == 0xE7) - { - for (i = 0; i < len; i++) - strcat(line, " "); - strcat(line, "; Send character in A to screen/printer"); - } - // Handle RST 5 Commenting - if (opcode == 0xEF) - { - for (i = 0; i < len; i++) - strcat(line, " "); - strcat(line, "; Determine type of last var used"); - } - // Handle RST 6 Commenting - if (opcode == 0xF7) - { - for (i = 0; i < len; i++) - strcat(line, " "); - strcat(line, "; Get sign of FAC1"); - } - // Handle RST 7 Commenting - if (opcode == 0xFF) - { - for (i = 0; i < len; i++) - strcat(line, " "); - strcat(line, "; Jump to RST 38H Vector entry of following byte"); - } + // Finish off the line + strcat(line, "\n"); // Increment memory counter by opcode length c += op_len; - // Finish off the line - strcat(line, "\n"); - // Add a blank line for JMP, CALL, and RET to provide routine separation if (opcode == 195 || opcode == 201 || opcode == 0xE9) { @@ -858,6 +879,11 @@ void VTDis::CopyIntoMem(unsigned char *ptr, int len) } } +void VTDis::SetBaseAddress(int address) +{ + m_BaseAddress = address; +} + int VTDis::DisassembleLine(int address, char* line) { char arg[60]; @@ -869,13 +895,13 @@ int VTDis::DisassembleLine(int address, char* line) opcode = get_memory8(address); // Determine length of this opcode - op_len = m_LenTable[opcode] & 0x03; + op_len = gLenTable[opcode] & 0x03; // Print the address and opcode value to the temporary line buffer - sprintf(line, "%04XH ", address); + sprintf(line, "%04XH ", address + m_BaseAddress); // Print the opcode text to the temp line buffer - strcat(line, m_StrTable[opcode]); + strcat(line, gStrTable[opcode]); // Check if this opcode has a single byte argument if (op_len == 1) @@ -892,7 +918,12 @@ int VTDis::DisassembleLine(int address, char* line) addr = get_memory8(address+1) | (get_memory8(address+2) << 8); sprintf(arg, "%04XH", addr); strcat(line, arg); + + if (m_WantComments) + { + AppendComments(line, opcode, addr); + } } - return 1; + return 1+op_len; } diff --git a/src/disassemble.h b/src/disassemble.h index 9c6367c..b211c27 100644 --- a/src/disassemble.h +++ b/src/disassemble.h @@ -38,24 +38,28 @@ void disassembler_cb(Fl_Widget* w, void*); class VTDis { public: - int m_EndAddress; - void CopyIntoMem(unsigned char * ptr, int len); - unsigned char m_memory[65536]; - int m_StartAddress; - class Fl_Text_Editor* m_pTextViewer; - RomDescription_t *m_pRom; - VTDis(); - void Disassemble(); - void SetTextViewer(class Fl_Text_Editor* pTextViewer); + int m_StartAddress; + int m_EndAddress; + unsigned char m_memory[65536]; + class Fl_Text_Editor* m_pTextViewer; + RomDescription_t *m_pRom; + int m_WantComments; - static int DisassembleLine(int address, char* line); -protected: - static char* m_StrTable[256]; - static unsigned char m_LenTable[256]; + void Disassemble(); + void SetTextViewer(class Fl_Text_Editor* pTextViewer); + void CopyIntoMem(unsigned char * ptr, int len); + int DisassembleLine(int address, char* line); + void SetBaseAddress(int address); + void AppendComments(char* line, int opcode, int address); +protected: + char* m_StrTable[256]; + unsigned char m_LenTable[256]; + int m_BaseAddress; }; #endif + diff --git a/src/display.cpp b/src/display.cpp index 6eee85b..8ed6869 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include //Added by J. VERNET for pref files // see also cb_xxxxxx @@ -56,13 +55,17 @@ #include "memory.h" #include "memedit.h" #include "cpuregs.h" +#include "rememcfg.h" extern "C" { extern RomDescription_t gM100_Desc; extern RomDescription_t gM200_Desc; extern RomDescription_t gN8201_Desc; +extern RomDescription_t gM10_Desc; extern RomDescription_t *gStdRomDesc; extern int gRomSize; +extern int gMaintCount; +extern int gOsDelay; } void cb_Ide(Fl_Widget* w, void*) ; @@ -71,6 +74,7 @@ Fl_Window *MainWin = NULL; T100_Disp *gpDisp; T100_Disp *gpDebugMonitor; Fl_Box *gpCode, *gpGraph, *gpKey, *gpSpeed, *gpCaps, *gpKeyInfo; +Fl_Box *gpMap = NULL; Fl_Menu_Bar *Menu; Fl_Preferences virtualt_prefs(Fl_Preferences::USER, "virtualt.", "virtualt" ); char gsMenuROM[40]; @@ -82,6 +86,7 @@ int DispHeight = 64; int gRectsize = 2; int gXoffset; int gYoffset; +int gSimKey = 0; void switch_model(int model); @@ -120,6 +125,8 @@ void setMonitorWindow(Fl_Window* pWin) } } +int T100_Disp::m_simKeys[32]; +int T100_Disp::m_simEventKey; char *gSpKeyText[] = { "SHIFT", @@ -170,13 +177,43 @@ void disassembler_cb(Fl_Widget* w, void*); void rspeed(Fl_Widget* w, void*) { fullspeed=0; - virtualt_prefs.set("fullspeed",0); + gMaintCount = 4096; + virtualt_prefs.set("fullspeed",0); } void fspeed(Fl_Widget* w, void*) +{ + fullspeed=3; +#ifdef WIN32 + gMaintCount = 300000; +#else + gMaintCount = 131272; +#endif + virtualt_prefs.set("fullspeed",3); + +} + +void pf1speed(Fl_Widget* w, void*) { fullspeed=1; - virtualt_prefs.set("fullspeed",1); +#ifdef WIN32 + gMaintCount = 16384; +#else + gMaintCount = 4096; +#endif + virtualt_prefs.set("fullspeed",1); + +} + +void pf2speed(Fl_Widget* w, void*) +{ + fullspeed=2; +#ifdef WIN32 + gMaintCount = 100000; +#else + gMaintCount = 16384; +#endif + virtualt_prefs.set("fullspeed",2); } @@ -227,8 +264,10 @@ void resize_window() 50*gpDisp->DisplayMode+2, 120, 20); gpSpeed->resize(300, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + 50*gpDisp->DisplayMode+2, 60, 20); - gpKeyInfo->resize(360, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + - 50*gpDisp->DisplayMode+2, MainWin->w()-360, 20); + gpMap->resize(360, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + + 50*gpDisp->DisplayMode+2, 60, 20); + gpKeyInfo->resize(420, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + + 50*gpDisp->DisplayMode+2, MainWin->w()-420, 20); gRectsize = MultFact - (1 - SolidChars); if (gRectsize == 0) @@ -331,14 +370,72 @@ void cb_save_co(Fl_Widget* w, void*) void cb_reset (Fl_Widget* w, void*) { - int a=fl_ask("Really Reset ?"); + int a; + if (w != NULL) + a=fl_choice("Really Reset ?", "No", "Yes", NULL); + else + a = 1; + if(a==1) + { resetcpu(); + show_remem_mode(); - gpDisp->Reset(); - if (gpDebugMonitor != 0) - gpDebugMonitor->Reset(); + if (gpDisp != NULL) + gpDisp->Reset(); + if (gpDebugMonitor != 0) + gpDebugMonitor->Reset(); + } +} + +void remote_reset(void) +{ + cb_reset(NULL, NULL); +} + +void cb_coldBoot (Fl_Widget* w, void*) +{ + int x; + int a; + + if (gReMem) + { + if (w != NULL) + a = fl_choice("Reload OpSys ROM?", "Cancel", "Yes", "No", NULL); + else + a = 2; + if (a == 1) + reload_sys_rom(); + } + else + { + if (w != NULL) + a = fl_choice("Really Cold Boot ?", "No", "Yes", NULL); + else + a = 2; + } + + if(a != 0) + { + resetcpu(); + reinit_mem(); + + // Clear the RAM + for (x = 32768; x < 65536; x++) + set_memory8(x, 0); + + show_remem_mode(); + + gpDisp->Reset(); + if (gpDebugMonitor != 0) + gpDebugMonitor->Reset(); + } +} + +void remote_cold_boot(void) +{ + cb_coldBoot(NULL, NULL); } void cb_UnloadOptRom (Fl_Widget* w, void*) @@ -378,11 +475,11 @@ void cb_M200(Fl_Widget* w, void*) /* Switch to new model */ switch_model(MODEL_T200); } -//void cb_M10(Fl_Widget* w, void*) -//{ +void cb_M10(Fl_Widget* w, void*) +{ /* Switch to new model */ -// switch_model(MODEL_M10); -//} + switch_model(MODEL_M10); +} void cb_PC8201(Fl_Widget* w, void*) { /* Switch to new model */ @@ -430,7 +527,8 @@ void cb_help (Fl_Widget* w, void*) Fl_Help_Dialog *HelpWin; HelpWin = new Fl_Help_Dialog(); - HelpWin->load("help.htm"); + HelpWin->resize(HelpWin->x(), HelpWin->y(), 760, 550); + HelpWin->load("doc/help.html"); HelpWin->show(); } @@ -445,43 +543,47 @@ void cb_about (Fl_Widget* w, void*) Fl_Window* o = new Fl_Window(420, 340); - { Fl_Box* o = new Fl_Box(20, 0, 325, 95, "Virtual T"); + { Fl_Box* o = new Fl_Box(20, 0, 345, 95, "Virtual T"); o->labelfont(11); o->labelsize(80); } - { Fl_Box* o = new Fl_Box(40, 105, 305, 40, "A Tandy Model 100/102/200 Emulator"); + { Fl_Box* o = new Fl_Box(50, 105, 305, 40, "A Tandy Model 100/102/200 Emulator"); o->labelfont(8); o->labelsize(24); } - { Fl_Box* o = new Fl_Box(20, 150, 335, 35, "written by: "); + { Fl_Box* o = new Fl_Box(30, 150, 335, 35, "written by: "); o->labelfont(8); o->labelsize(18); } - { Fl_Box* o = new Fl_Box(20, 170, 335, 35, "Ken Pettit"); + { Fl_Box* o = new Fl_Box(30, 170, 335, 35, "Ken Pettit"); o->labelfont(8); o->labelsize(18); } - { Fl_Box* o = new Fl_Box(15, 190, 340, 35, "Stephen Hurd"); + { Fl_Box* o = new Fl_Box(25, 190, 340, 35, "Stephen Hurd"); o->labelfont(8); o->labelsize(18); } - { Fl_Box* o = new Fl_Box(15, 210, 340, 35, "Jerome Vernet (Mac OsX Port)"); + { Fl_Box* o = new Fl_Box(25, 210, 340, 35, "Jerome Vernet"); o->labelfont(8); o->labelsize(18); } - { Fl_Box* o = new Fl_Box(85, 255, 195, 25, "V "VERSION); + { Fl_Box* o = new Fl_Box(25, 230, 340, 35, "John Hogerhuis"); o->labelfont(8); o->labelsize(18); } - { Fl_Box* o = new Fl_Box(25, 295, 320, 25, "This program may be distributed freely "); + { Fl_Box* o = new Fl_Box(95, 265, 195, 25, "V "VERSION); + o->labelfont(8); + o->labelsize(18); + } + { Fl_Box* o = new Fl_Box(35, 295, 320, 25, "This program may be distributed freely "); o->labelfont(8); o->labelsize(16); } - { Fl_Box* o = new Fl_Box(25, 315, 320, 25, "under the terms of the BSD license"); + { Fl_Box* o = new Fl_Box(35, 315, 320, 25, "under the terms of the BSD license"); o->labelfont(8); o->labelsize(16); } - { Fl_Box* o = new Fl_Box(10, 75, 320, 20, "in FLTK"); + { Fl_Box* o = new Fl_Box(20, 75, 320, 20, "in FLTK"); o->labelfont(8); o->labelsize(18); } @@ -499,23 +601,27 @@ Fl_Menu_Item menuitems[] = { { "Save Basic as ASCII", 0, cb_save_basic, (void *) 1, FL_MENU_TOGGLE }, { "Save CO as HEX", 0, cb_save_co, (void *) 2, FL_MENU_TOGGLE }, { 0 }, - { "Load RAM...", 0, cb_LoadRam, 0 }, - { "Save RAM...", 0, cb_SaveRam, 0, FL_MENU_DIVIDER }, - { "E&xit", FL_CTRL + 'q', close_disp_cb, 0 }, +// { "Load RAM...", 0, cb_LoadRam, 0 }, +// { "Save RAM...", 0, cb_SaveRam, 0, 0 }, +// { "RAM Snapshots...", 0, 0, 0, FL_MENU_DIVIDER }, + { "E&xit", 0, close_disp_cb, 0 }, { 0 }, { "&Emulation", 0, 0, 0, FL_SUBMENU }, - { "Reset", 0, cb_reset, 0, FL_MENU_DIVIDER }, + { "Reset", 0, cb_reset, 0, 0 }, + { "Cold Boot", 0, cb_coldBoot, 0, FL_MENU_DIVIDER }, { "Model", 0, 0, 0, FL_SUBMENU } , { "M100", 0, cb_M100, (void *) 1, FL_MENU_RADIO | FL_MENU_VALUE }, { "M102", 0, cb_M102, (void *) 2, FL_MENU_RADIO }, { "T200", 0, cb_M200, (void *) 3, FL_MENU_RADIO }, { "PC-8201", 0, cb_PC8201, (void *) 4, FL_MENU_RADIO }, -// { "8300", 0, cb_PC8300, (void *) 5, FL_MENU_RADIO }, + { "M10", 0, cb_M10, (void *) 5, FL_MENU_RADIO }, { 0 }, { "Speed", 0, 0, 0, FL_SUBMENU }, { "2.4 MHz", 0, rspeed, (void *) 1, FL_MENU_RADIO | FL_MENU_VALUE }, - { "Max Speed", 0, fspeed, (void *) 1, FL_MENU_RADIO }, + { "Very CPU Friendly",0, pf1speed, (void *) 2, FL_MENU_RADIO }, + { "CPU Friendly",0, pf2speed, (void *) 3, FL_MENU_RADIO }, + { "Max Speed", 0, fspeed, (void *) 4, FL_MENU_RADIO }, { 0 }, { "Display", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER}, { "1x", 0, cb_1x, (void *) 1, FL_MENU_RADIO }, @@ -542,8 +648,9 @@ Fl_Menu_Item menuitems[] = { { "Assembler / IDE", 0, cb_Ide}, { "Disassembler", 0, disassembler_cb }, { "Memory Editor", 0, cb_MemoryEditor }, + { "ReMem Configuration", 0, cb_RememCfg, 0, 0 }, { "Peripheral Devices", 0, cb_PeripheralDevices }, - { "Simulation Log Viewer", 0, 0 }, +// { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, 0 }, { 0 }, { "&Help", 0, 0, 0, FL_SUBMENU }, @@ -554,6 +661,67 @@ Fl_Menu_Item menuitems[] = { { 0 } }; +/* +============================================================================ +remote_set_speed: This function sets the speed of the emulation +============================================================================ +*/ +void remote_set_speed(int speed) +{ + int mIndex; + int i; + + /* Set CPU Speed */ + fullspeed = speed; + switch (fullspeed) + { +#ifdef WIN32 + case 0: gMaintCount = 4096; break; + case 1: gMaintCount = 16384; break; + case 2: gMaintCount = 100000; break; + case 3: gMaintCount = 300000; break; + default: gMaintCount = 4096; break; +#else + case 0: gMaintCount = 4096; break; + case 1: gMaintCount = 4096; break; + case 2: gMaintCount = 16384; break; + case 3: gMaintCount = 131272; break; + default: gMaintCount = 4096; break; +#endif + } + + //================================================== + // Update Speed menu item if not default value + //================================================== + mIndex = 0; + while (menuitems[mIndex].callback_ != rspeed) + mIndex++; + for (i = 0; i < 4; i++) + { + if (i == fullspeed) + menuitems[mIndex+i].flags= FL_MENU_RADIO |FL_MENU_VALUE; + else + menuitems[mIndex+i].flags= FL_MENU_RADIO; + } +} + +void init_menus(void) +{ + int remem_menu_flag = FL_MENU_INVISIBLE; + int mIndex; + + if (gReMem) + { + remem_menu_flag = 0; + } + + // Locate the ReMem Configuration menu item + mIndex = 0; + while (menuitems[mIndex].callback_ != cb_RememCfg) + mIndex++; + menuitems[mIndex].flags= remem_menu_flag; +} + /* ============================================================================ switch_model: This function is called by the menu callback routines that @@ -566,6 +734,7 @@ void switch_model(int model) { /* Save RAM for current emulation */ save_ram(); + free_mem(); /* Switch to new model */ gModel = model; @@ -586,6 +755,10 @@ void switch_model(int model) } else if (gModel == MODEL_PC8201) gStdRomDesc = &gN8201_Desc; + else if (gModel == MODEL_M10) + { + gStdRomDesc = &gM10_Desc; + } else gStdRomDesc = &gM100_Desc; @@ -596,6 +769,7 @@ void switch_model(int model) delete MainWin; init_display(); + show_remem_mode(); /* Resize the window in case of size difference */ resize_window(); @@ -617,7 +791,7 @@ T100:Disp: This is the class construcor T100_Disp::T100_Disp(int x, int y, int w, int h) : Fl_Widget(x, y, w, h) { - int driver; + int driver, c; for (driver = 0; driver < 10; driver++) { @@ -625,6 +799,8 @@ T100_Disp::T100_Disp(int x, int y, int w, int h) : lcd[driver][c] = 0; top_row[driver] = 0; } + for (c = 0; c < 32; c++) + m_simKeys[c] = 0; m_MyFocus = 0; m_DebugMonitor = 0; @@ -881,6 +1057,9 @@ void T100_Disp::SetByte(int driver, int col, uchar value) if (lcd[driver][col] == value) return; + //if (driver == 4) + //printf("%d=%d ", col, value); + // Load new value into lcd "RAM" lcd[driver][col] = value; @@ -933,6 +1112,24 @@ void init_pref(void) strcat(option_name, "_OptRomFile"); virtualt_prefs.get(option_name,gsOptRomFile,"", 256); + /* Set CPU Speed */ + switch (fullspeed) + { +#ifdef WIN32 + case 0: gMaintCount = 4096; break; + case 1: gMaintCount = 16384; break; + case 2: gMaintCount = 100000; break; + case 3: gMaintCount = 300000; break; + default: gMaintCount = 4096; break; +#else + case 0: gMaintCount = 4096; break; + case 1: gMaintCount = 4096; break; + case 2: gMaintCount = 16384; break; + case 3: gMaintCount = 131272; break; + default: gMaintCount = 4096; break; +#endif + } + if (strlen(gsOptRomFile) == 0) { strcpy(gsMenuROM, "No ROM loaded"); @@ -947,6 +1144,7 @@ void init_display(void) { int mIndex; int i; + char temp[20]; if (gModel == MODEL_T200) DispHeight = 128; @@ -966,19 +1164,22 @@ void init_display(void) MainWin->callback(close_disp_cb); Menu->menu(menuitems); - + init_menus(); + // Treat Values read in pref files // J. VERNET //================================================== // Update Speed menu item if not default value //================================================== - if(fullspeed==1) + mIndex = 0; + while (menuitems[mIndex].callback_ != rspeed) + mIndex++; + for (i = 0; i < 4; i++) { - mIndex = 0; - while (menuitems[mIndex].callback_ != rspeed) - mIndex++; - menuitems[mIndex+1].flags= FL_MENU_RADIO |FL_MENU_VALUE; - menuitems[mIndex].flags= FL_MENU_RADIO; + if (i == fullspeed) + menuitems[mIndex+i].flags= FL_MENU_RADIO |FL_MENU_VALUE; + else + menuitems[mIndex+i].flags= FL_MENU_RADIO; } //================================================== @@ -1010,7 +1211,7 @@ void init_display(void) while (menuitems[mIndex].callback_ != cb_M100) mIndex++; - for(i=MODEL_M100;i<=MODEL_PC8201;i++) + for(i=MODEL_M100;i<=MODEL_M10;i++) { if(i==gModel) if(i==MODEL_PC8300) @@ -1095,10 +1296,14 @@ void init_display(void) gpSpeed = new Fl_Box(FL_DOWN_BOX,300, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 60, 20,""); gpSpeed->labelsize(10); - gpKeyInfo = new Fl_Box(FL_DOWN_BOX,360, MENU_HEIGHT+DispHeight*MultFact + - 50*DisplayMode+2, MainWin->w()-360, 20, + gpMap = new Fl_Box(FL_DOWN_BOX,360, MENU_HEIGHT+DispHeight*MultFact + + 50*DisplayMode+2, 60, 20,""); + gpMap->labelsize(10); + gpKeyInfo = new Fl_Box(FL_DOWN_BOX,420, MENU_HEIGHT+DispHeight*MultFact + + 50*DisplayMode+2, MainWin->w()-420, 20, "F9:Label F10:Print F11:Paste F12:Pause"); gpKeyInfo->labelsize(10); + gSimKey = 0; gXoffset = 45*DisplayMode+1; gYoffset = 25*DisplayMode + MENU_HEIGHT+1; @@ -1118,6 +1323,21 @@ void init_display(void) MainWin->end(); MainWin->show(); + // Set the initial string for ReMem + show_remem_mode(); + if (gReMem) + { + // Check if ReMem is in "Normal" mode or MMU mode + if (inport(REMEM_MODE_PORT) & 0x01) + { + // Read the MMU Map + sprintf(temp, "Map:%d", (inport(REMEM_MODE_PORT) >> 3) & 0x07); + display_map_mode(temp); + } + else + display_map_mode("Normal"); + } + /* Check for Fl_Window event */ Fl::check(); @@ -1132,6 +1352,7 @@ void init_display(void) } static char label[40]; +static char mapStr[40]; void display_cpu_speed(void) { @@ -1140,6 +1361,16 @@ void display_cpu_speed(void) gpSpeed->label(label); } +void display_map_mode(char *str) +{ + if (gpMap == NULL) + return; + + strcpy(mapStr, str); + Fl::check(); + gpMap->label(mapStr); +} + void drawbyte(int driver, int column, int value) { gpDisp->SetByte(driver, column, value); @@ -1170,8 +1401,15 @@ void power_down() void process_windows_event() { - //Fl::wait(0); + if (gOsDelay) +#ifdef WIN32 + Fl::wait(0.001); +#else + Fl::wait(0.00001); +#endif + else Fl::check(); + return; } @@ -1197,9 +1435,7 @@ void T100_Disp::PowerDown() int driver, column; int addr; - addr = 0x7711; - if (gModel == MODEL_PC8201) - addr = 0x78B7; + addr = gStdRomDesc->sCharTable; for (driver = 0; driver < 10; driver++) for (col = 0; col < 256; col++) @@ -1241,6 +1477,120 @@ void T100_Disp::PowerDown() } } +void simulate_keydown(int key) +{ + if (gpDisp == NULL) + return; + + gpDisp->SimulateKeydown(key); +} + +void simulate_keyup(int key) +{ + if (gpDisp == NULL) + return; + + gpDisp->SimulateKeyup(key); +} + +void handle_simkey(void) +{ + if (gpDisp == NULL) + return; + + if (gSimKey) + gpDisp->HandleSimkey(); +} + +void T100_Disp::HandleSimkey(void) +{ + int simkey = gSimKey; + gSimKey = 0; + handle(simkey); +} + +/* +========================================================================== +siulate_keydown: Simulates an FL_KEYDOWN event +========================================================================== +*/ +void T100_Disp::SimulateKeydown(int key) +{ + int c; + + // Loop through array and check if key is already down + for (c = 0; c < 32; c++) + { + if (m_simKeys[c] == key) + break; + } + + // Test if key needs to be added to simKeys + if (c != 32) + { + // Find first non-zero entry + for (c = 0; c < 32; c++) + if (m_simKeys[c] == 0) + break; + if (c != 32) + m_simKeys[c] = key; + } + m_simEventKey = key; + gSimKey = VT_SIM_KEYDOWN; +} + +/* +========================================================================== +siulate_keyup: Simulates an FL_KEYUP event +========================================================================== +*/ +void T100_Disp::SimulateKeyup(int key) +{ + int c; + + // Loop through array and check if key is already down + for (c = 0; c < 32; c++) + { + if (m_simKeys[c] == key) + { + m_simKeys[c] = 0; + break; + } + } + + m_simEventKey = key; + gSimKey = VT_SIM_KEYUP; +} + +/* +========================================================================== +sim_get_key: Returns the key that caused the event +========================================================================== +*/ +int T100_Disp::sim_get_key(int key) +{ + int c; + + // Loop through array and check if key is already down + for (c = 0; c < 32; c++) + { + if (m_simKeys[c] == key) + return TRUE; + } + + return FALSE; +} + +/* +========================================================================== +sim_event_key: Returns the state of a simulated key +========================================================================== +*/ +int T100_Disp::sim_event_key(void) +{ + return m_simEventKey; +} + // Handle mouse events, key events, focus events, etc. char keylabel[128]; int T100_Disp::handle(int event) @@ -1248,9 +1598,28 @@ int T100_Disp::handle(int event) char keystr[10]; char isSpecialKey = 1; int c; + int simulated; + get_key_t get_key; + event_key_t event_key; unsigned int key; + get_key = Fl::get_key; + event_key = Fl::event_key; + simulated = FALSE; + + if ((event == VT_SIM_KEYUP) || (event == VT_SIM_KEYDOWN)) + { + get_key = sim_get_key; + event_key = sim_event_key; + simulated = TRUE; + + if (event == VT_SIM_KEYUP) + event = FL_KEYUP; + else + event = FL_KEYDOWN; + } + switch (event) { case FL_FOCUS: @@ -1272,13 +1641,12 @@ int T100_Disp::handle(int event) break; case FL_KEYUP: - if (!m_MyFocus) + if (!m_MyFocus && !simulated) return 1; // Get the Key that was pressed - key = Fl::event_key(); - //fprintf(stderr,"Touche: %d\n",key); - //fprintf(stderr,"Texte %s\n",Fl::event_text()); + //key = Fl::event_key(); + key = event_key(); switch (key) { case FL_Escape: @@ -1407,53 +1775,7 @@ int T100_Disp::handle(int event) ========================================= ========================================= */ - if (gModel != MODEL_PC8201) - { - if (key == ']') - { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) - { - gSpecialKeys |= MT_GRAPH; - gSpecialKeys &= ~MT_SHIFT; - gKeyStates[']'] = 0; - gKeyStates['0'] = 0; - } - else - { - gSpecialKeys |= MT_SHIFT; - gKeyStates['['] = 0; - } - } - if (key == '[') - { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) - { - gSpecialKeys |= MT_GRAPH; - gSpecialKeys &= ~MT_SHIFT; - gKeyStates['['] = 0; - gKeyStates['9'] = 0; - } - } - if (key == '`') - { - gSpecialKeys |= MT_GRAPH; - gKeyStates['['] = 0; - } - if (key == '\\') - { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) - { - gSpecialKeys |= MT_GRAPH; - gKeyStates[';'] = 0; - } - else - { - gSpecialKeys |= MT_GRAPH; - gKeyStates['-'] = 0; - } - } - } - else + if (gModel == MODEL_PC8201) { // Handle the '^' key (Shift 6) if (key == '6') @@ -1533,7 +1855,7 @@ int T100_Disp::handle(int event) else gSpecialKeys |= MT_SHIFT; } - // Handle the '_' key + // Handle the ':' key if (key == ';') { gKeyStates[';'] = 0; @@ -1574,46 +1896,211 @@ int T100_Disp::handle(int event) gSpecialKeys |= MT_SHIFT; } } - - isSpecialKey = 0; - break; - } - update_keys(); - break; - - case FL_KEYDOWN: - if (!m_MyFocus) - return 1; - - if (ioBA & 0x10) - { - resetcpu(); - break; - } - - // Get the Key that was pressed - key = Fl::event_key(); - switch (key) - { - case FL_Escape: - gSpecialKeys &= ~MT_ESC; - break; - case FL_Delete: - gSpecialKeys &= ~MT_SHIFT; - case FL_BackSpace: - gSpecialKeys &= ~MT_BKSP; - break; - case FL_Tab: - gSpecialKeys &= ~MT_TAB; - break; - case FL_Enter: - gSpecialKeys &= ~MT_ENTER; - break; - case FL_Print: - gSpecialKeys &= ~MT_PRINT; - break; - case FL_F+12: - case FL_Pause: + else if (gModel == MODEL_M10) + { + // Handle the '@' key + if (key == '2') + { + gKeyStates['2'] = 0; + gKeyStates['@'] = 0; + gSpecialKeys |= MT_SHIFT; + } + // Handle the '#' key + if (key == '3') + { + gSpecialKeys |= MT_GRAPH; + gKeyStates['h'] = 0; + } + // Handle the '^' key (Shift 6) + if (key == '6') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['6'] = 0; + gKeyStates['^'] = 0; + } + else + { + gSpecialKeys |= MT_SHIFT; + gKeyStates['^'] = 0; + } + } + if (key == '`') + { + gKeyStates['@'] = 0; + gKeyStates['^'] = 0; + } + // Handle the '&' key + if (key == '7') + { + gKeyStates['7'] = 0; + gKeyStates['6'] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + gSpecialKeys &= ~MT_SHIFT; + else + gSpecialKeys |= MT_SHIFT; + } + // Handle the '(' key + if (key == '9') + { + gKeyStates['8'] = 0; + gKeyStates['9'] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + gSpecialKeys &= ~MT_SHIFT; + else + gSpecialKeys |= MT_SHIFT; + } + // Handle the ')' key + if (key == '0') + { + gKeyStates['9'] = 0; + gKeyStates['0'] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + gSpecialKeys &= ~MT_SHIFT; + else + gSpecialKeys |= MT_SHIFT; + } + // Handle the '*' key + if (key == '8') + { + gKeyStates['8'] = 0; + gKeyStates[':'] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + gSpecialKeys &= ~MT_SHIFT; + else + gSpecialKeys |= MT_SHIFT; + } + // Handle the '_' key + if (key == '-') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gKeyStates['-'] = 0; + gKeyStates['0'] = 0; + gSpecialKeys |= MT_SHIFT; + } + } + if (key == '=') + { + gKeyStates[';'] = 0; + gKeyStates['-'] = 0; + gSpecialKeys |= MT_SHIFT; + } + // Handle the ':' key + if (key == ';') + { + gKeyStates[';'] = 0; + gKeyStates[':'] = 0; + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + gSpecialKeys &= ~MT_SHIFT; + else + gSpecialKeys |= MT_SHIFT; + } + // Handle the '"' key (shift ') + if (key == '\'') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['\''] = 0; + gKeyStates['2'] = 0; + gKeyStates['7'] = 0; + } + else + { + gSpecialKeys |= MT_SHIFT; + gKeyStates['2'] = 0; + gKeyStates['7'] = 0; + } + } + } + else + { + if (key == ']') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys |= MT_GRAPH; + gSpecialKeys &= ~MT_SHIFT; + gKeyStates[']'] = 0; + gKeyStates['0'] = 0; + } + else + { + gSpecialKeys |= MT_SHIFT; + gKeyStates['['] = 0; + } + } + if (key == '[') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys |= MT_GRAPH; + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['['] = 0; + gKeyStates['9'] = 0; + } + } + if (key == '`') + { + gSpecialKeys |= MT_GRAPH; + gKeyStates['['] = 0; + } + if (key == '\\') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys |= MT_GRAPH; + gKeyStates[';'] = 0; + } + else + { + gSpecialKeys |= MT_GRAPH; + gKeyStates['-'] = 0; + } + } + } + + isSpecialKey = 0; + break; + } + update_keys(); + break; + + case FL_KEYDOWN: + if (!m_MyFocus && !simulated) + return 1; + + if (ioBA & 0x10) + { + resetcpu(); + break; + } + + // Get the Key that was pressed + key = event_key(); + switch (key) + { + case FL_Escape: + gSpecialKeys &= ~MT_ESC; + break; + case FL_Delete: + gSpecialKeys &= ~MT_SHIFT; + case FL_BackSpace: + gSpecialKeys &= ~MT_BKSP; + break; + case FL_Tab: + gSpecialKeys &= ~MT_TAB; + break; + case FL_Enter: + gSpecialKeys &= ~MT_ENTER; + break; + case FL_Print: + gSpecialKeys &= ~MT_PRINT; + break; + case FL_F+12: + case FL_Pause: gSpecialKeys &= ~MT_PAUSE; break; case FL_Left: @@ -1708,68 +2195,7 @@ int T100_Disp::handle(int event) { gSpecialKeys &= ~MT_SPACE; } - if (gModel != MODEL_PC8201) - { - if (key == ']') - { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) - { - gSpecialKeys &= ~MT_GRAPH; - gSpecialKeys |= MT_SHIFT; - gKeyStates[']'] = 0; - gKeyStates['0'] = 1; - } - else - { - gSpecialKeys &= ~MT_SHIFT; - gKeyStates['['] = 1; - gKeyStates[key] = 0; - } - } - if (key == '[') - { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) - { - gSpecialKeys &= ~MT_GRAPH; - gSpecialKeys |= MT_SHIFT; - gKeyStates['['] = 0; - gKeyStates['9'] = 1; - } - } - if (key == '`') - { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) - { - gSpecialKeys &= ~MT_GRAPH; - gSpecialKeys &= ~MT_SHIFT; - gKeyStates['`'] = 0; - gKeyStates['['] = 1; - } - else - { - gSpecialKeys &= ~MT_GRAPH; - gKeyStates['`'] = 0; - gKeyStates['['] = 1; - } - } - if (key == '\\') - { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) - { - gSpecialKeys &= ~MT_GRAPH; - gSpecialKeys &= ~MT_SHIFT; - gKeyStates['\\'] = 0; - gKeyStates[';'] = 1; - } - else - { - gSpecialKeys &= ~MT_GRAPH; - gKeyStates['-'] = 1; - gKeyStates['\\'] = 0; - } - } - } - else + if (gModel == MODEL_PC8201) { // Deal with special keys for the PC-8201 @@ -1883,6 +2309,204 @@ int T100_Disp::handle(int event) } } } + else if (gModel == MODEL_M10) + { + // Handle the '@' key + if (key == '2') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys |= MT_SHIFT; + gKeyStates['2'] = 0; + gKeyStates['@'] = 1; + } + } + // Handle the '#' key + if (key == '3') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_GRAPH; + gKeyStates['3'] = 0; + gKeyStates['h'] = 1; + } + } + // Handle the '^' key (Shift 6) + if (key == '6') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys |= MT_SHIFT; + gKeyStates['6'] = 0; + gKeyStates['^'] = 1; + } + else + { + gKeyStates['^'] = 0; + } + } + if (key == '`') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['`'] = 0; + gKeyStates['^'] = 1; + } + else + { + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['`'] = 0; + gKeyStates['@'] = 1; + } + } + // Handle the '&' key + if (key == '7') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gKeyStates['7'] = 0; + gKeyStates['6'] = 1; + } + } + // Handle the '(' key + if (key == '9') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gKeyStates['9'] = 0; + gKeyStates['8'] = 1; + } + } + // Handle the '(' key + if (key == '0') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gKeyStates['0'] = 0; + gKeyStates['9'] = 1; + } + } + // Handle the '*' key + if (key == '8') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gKeyStates['8'] = 0; + gKeyStates[':'] = 1; + } + } + // Handle the '_' key + if (key == '-') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gKeyStates['-'] = 0; + gKeyStates['0'] = 1; + } + } + if (key == '=') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['='] = 0; + gKeyStates[';'] = 1; + } + else + { + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['='] = 0; + gKeyStates['-'] = 1; + } + } + // Handle the ':' key + if (key == ';') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys |= MT_SHIFT; + gKeyStates[';'] = 0; + gKeyStates[':'] = 1; + } + } + // Handle the '"' key (Shift ') + if (key == '\'') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gKeyStates['\''] = 0; + gKeyStates['2'] = 1; + } + else + { + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['2'] = 0; + gKeyStates['7'] = 1; + } + } + } + else + { + if (key == ']') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_GRAPH; + gSpecialKeys |= MT_SHIFT; + gKeyStates[']'] = 0; + gKeyStates['0'] = 1; + } + else + { + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['['] = 1; + gKeyStates[key] = 0; + } + } + if (key == '[') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_GRAPH; + gSpecialKeys |= MT_SHIFT; + gKeyStates['['] = 0; + gKeyStates['9'] = 1; + } + } + if (key == '`') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_GRAPH; + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['`'] = 0; + gKeyStates['['] = 1; + } + else + { + gSpecialKeys &= ~MT_GRAPH; + gKeyStates['`'] = 0; + gKeyStates['['] = 1; + } + } + if (key == '\\') + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + { + gSpecialKeys &= ~MT_GRAPH; + gSpecialKeys &= ~MT_SHIFT; + gKeyStates['\\'] = 0; + gKeyStates[';'] = 1; + } + else + { + gSpecialKeys &= ~MT_GRAPH; + gKeyStates['-'] = 1; + gKeyStates['\\'] = 0; + } + } + } isSpecialKey = 0; break; } diff --git a/src/display.h b/src/display.h index 29499e7..805b890 100644 --- a/src/display.h +++ b/src/display.h @@ -44,12 +44,21 @@ void lcdcommand(int driver, int value); void power_down(); void process_windows_event(); void display_cpu_speed(void); +void display_map_mode(char *str); void show_error(const char*); void t200_command(unsigned char ir, unsigned char data); unsigned char t200_readport(unsigned char port); +void handle_simkey(void); +void switch_model(int); + +typedef int (*get_key_t)(int); +typedef int (*event_key_t)(void); #ifdef __cplusplus +#define VT_SIM_KEYUP 3120 +#define VT_SIM_KEYDOWN 3121 + class T100_Disp : public Fl_Widget { public: @@ -60,6 +69,9 @@ class T100_Disp : public Fl_Widget virtual void Command(int instruction, uchar data); virtual void Clear(void); virtual void Reset(void); + void SimulateKeydown(int key); + void SimulateKeyup(int key); + void HandleSimkey(void); int MultFact; int DisplayMode; @@ -77,8 +89,12 @@ class T100_Disp : public Fl_Widget protected: virtual int handle(int event); virtual void draw(); + static int sim_get_key(int key); + static int sim_event_key(void); __inline void drawpixel(int x, int y, int color); virtual void draw_static(); + static int m_simKeys[32]; + static int m_simEventKey; int m_MyFocus; uchar lcd[10][256]; diff --git a/src/do_instruct.h b/src/do_instruct.h index 4f11e06..3e649f5 100644 --- a/src/do_instruct.h +++ b/src/do_instruct.h @@ -29,49 +29,64 @@ #define LXI(rp,h,l,rps) { \ - l=INS_INC; \ - h=INS_INC; \ - cycle_delta+=10; \ + INCPC; \ + l=INS; \ + INCPC; \ + h=INS; \ + INCPC; \ + cycle_delta+=(10); \ } #define STAX(rp,rps) { \ + INCPC; \ MEMSET(rp,A); \ - cycle_delta+=7; \ + cycle_delta+=(7); \ } #define INX(rp,h,l,rps) { \ - F &= ~XF_BIT; \ - if(!(++l)) { \ - h++; \ + INCPC; \ + F &= ~(OV_BIT|XF_BIT); \ + if ((l==0xFF) && (h==0xFF)) \ F |= XF_BIT; \ + l++; \ + if(!l) { \ + h++; \ + F |= OV_BIT; \ } \ - cycle_delta += 6; \ + cycle_delta+=(6); \ } #define INR(r,rs) { \ - if((++r)&0x0f==0) /* Low order nybble wrapped */ \ + INCPC; \ + r++; \ + if((r&0x0f)==0) /* Low order nybble wrapped */ \ j=1; \ else \ j=0; \ setflags(r,-1,-1,j,-1,-2, (r==0x80) || (r==0), -2); \ - cycle_delta += 4; \ + cycle_delta+=(4); \ } #define DCR(r,rs) { \ - if((--r)&0x0f==0x0f) /* Low order nybble wrapped */ \ + INCPC; \ + r--; \ + if((r&0x0f)==0x0f) /* Low order nybble wrapped */ \ j=1; \ else \ j=0; \ setflags(r,-1,-1,j,-1,-2, (r==0xFF) || (r==0x7F), -2); \ - cycle_delta += 4; \ + cycle_delta+=(4); \ } #define MVI(r,rs) { \ - r=INS_INC; \ - cycle_delta += 7; \ + INCPC; \ + r=INS; \ + INCPC; \ + cycle_delta+=(7); \ } #define DAD(rp,rps) { \ + INCPC; \ i=HL; \ i+=rp; \ j=(HL&0x8000)==(rp&0x8000); \ @@ -84,35 +99,42 @@ if (j) \ j = (HL&0x8000) != (rp&0x8000); \ setflags(0,-2,-2,-2,-2,i,j,-2 ); \ - cycle_delta += 10; \ + cycle_delta+=(10); \ } #define LDAX(rp,rps) { \ + INCPC; \ A=MEM(rp); \ - cycle_delta += 7; \ + cycle_delta+=(7); \ } #define DCX(rp,h,l,rps) { \ + INCPC; \ + F &= ~(OV_BIT|XF_BIT); \ + if ((l == 0) && (h == 0)) \ + F |= XF_BIT; \ l--; \ - F &= ~XF_BIT; \ if(l==0xff) { \ - F |= XF_BIT; \ + F |= OV_BIT; \ h--; \ } \ - cycle_delta += 6; \ + cycle_delta+=(6); \ } #define MOV(dest,src,ds,ss) { \ + INCPC; \ dest=src; \ - cycle_delta += 4; \ + cycle_delta+=(4); \ } #define MOVM(src,ss) { \ + INCPC; \ MEMSET(HL, src); \ - cycle_delta += 7; \ + cycle_delta+=(7); \ } #define ADD(r,rs) { \ + INCPC; \ i=A; \ i+=r; \ v=(A&0x80) == (r&0x80); \ @@ -125,10 +147,11 @@ if (v) \ v = (A&0x80) != (r&0x80); \ setflags(A,-1,-1,j,-1,i,v,-2); \ - cycle_delta += 4; \ + cycle_delta+=(4); \ } #define ADC(r,rs) { \ + INCPC; \ i=A; \ i+=r; \ i+=(CF?1:0); \ @@ -142,10 +165,11 @@ if (v) \ v = (A&0x80) != (r&0x80); \ setflags(A,-1,-1,j,-1,i,v,-2); \ - cycle_delta += 4; \ + cycle_delta+=(4); \ } #define SUB(r,rs) { \ + INCPC; \ i=A; \ i-=r; \ j = (((A & 0x0F)-(r & 0x0F)) & 0x10) >> 4; \ @@ -158,10 +182,11 @@ if (v) \ v = (A&0x80) != (r&0x80); \ setflags(A,-1,-1,j,-1,i,v,-2); \ - cycle_delta += 4; \ + cycle_delta+=(4); \ } #define SBB(r,rs) { \ + INCPC; \ i=A; \ i-=r; \ i-=(CF?1:0); \ @@ -175,28 +200,32 @@ if (v) \ v = (A&0x80) != (r&0x80); \ setflags(A,-1,-1,j,-1,i,v,-2); \ - cycle_delta += 4; \ + cycle_delta+=(4); \ } #define ANA(r,rs) { \ + INCPC; \ A&=r; \ setflags(A,-1,-1,1,-1,0,-2,-2); \ - cycle_delta += 4; \ + cycle_delta+=(4); \ } #define XRA(r,rs) { \ + INCPC; \ A^=r; \ setflags(A,-1,-1,0,-1,0,-2,-2); \ - cycle_delta += 4; \ + cycle_delta+=(4); \ } #define ORA(r,rs) { \ + INCPC; \ A|=r; \ setflags(A,-1,-1,0,-1,0,-2,-2); \ - cycle_delta += 4; \ + cycle_delta+=(4); \ } #define CMP(r,rs) { \ + INCPC; \ i=A; \ i-=r; \ if (i>0xFF) \ @@ -209,64 +238,72 @@ else \ v = 0; \ setflags(A-r,-1,-1,j,-1,i,v,-2); \ - cycle_delta += 4; \ + cycle_delta+=(4); \ } #define POP(rp,h,l,rps) { \ + INCPC; \ l=MEM(SP); \ h=MEM(SP+1); \ INCSP2; \ - cycle_delta += 10; \ + cycle_delta+=(10); \ } #define PUSH(rp,h,l,rps) { \ + INCPC; \ DECSP2; \ MEMSET(SP,l); \ MEMSET(SP+1,h); \ - cycle_delta += 12; \ + cycle_delta+=(12); \ } #define RST(num) { \ + INCPC; \ DECSP2; \ MEMSET(SP,PCL); MEMSET(SP+1,PCH); \ PCH=0; \ PCL=8*num; \ - cycle_delta += 12; \ + cycle_delta+=(12); \ } #define CALL(cond,ins) { \ + INCPC; \ INCPC2; \ if(cond) { \ DECSP2; \ MEMSET(SP,PCL); MEMSET(SP+1,PCH); /* MEM16(SP)=PC; */ \ DECPC2; \ SETPCINS16; \ - cycle_delta += 9; \ + cycle_delta+=(9); \ } \ - cycle_delta += 9; \ + cycle_delta+=(9); \ } #define RETURN(cond,ins) { \ + INCPC; \ if(cond) { \ PCL=MEM(SP); PCH=MEM(SP+1); /* PC=MEM16(SP) */ \ INCSP2; \ - cycle_delta += 6; \ + cycle_delta+=(6); \ } \ - cycle_delta += 6; \ + cycle_delta+=(6); \ } #define JUMP(cond,ins) { \ + INCPC; \ if(cond) { \ SETPCINS16; \ - cycle_delta += 3; \ + cycle_delta+=(3); \ } \ else \ INCPC2; \ - cycle_delta += 7; \ + cycle_delta+=(7); \ } { - ins = INS_INC; +// if(trace) +// p=op+sprintf(op,"%04x (%02x) ",PC,INS); +ins = INS; if(!(ins&0x80)) { if(!(ins&0x40)) { if(!(ins&0x20)) { @@ -276,7 +313,8 @@ if(!(ins&0x02)) { if(!(ins&0x01)) { /* case 0x00: /* NOP */ - cycle_delta += 4; + INCPC; + cycle_delta+=(4); /* return; */ } else { @@ -313,10 +351,11 @@ } else { /* case 0x07: /* RLC */ + INCPC; i=A>>7; A=(A<<1)|i; setflags(A,-2,-2,-2,-2,i,-2,-2); - cycle_delta += 4; + cycle_delta+=(4); /* return; */ } } @@ -327,6 +366,7 @@ if(!(ins&0x02)) { if(!(ins&0x01)) { /* case 0x08: /* DSUB */ + INCPC; i = HL < BC;// - (CF?1:0); j = HL - BC;// - (CF?1:0); v = (HL&0x8000) == (BC&0x8000); @@ -334,8 +374,8 @@ H=(j >> 8) & 0xFF; if (v) v = (HL&0x8000) != (BC&0x8000); - setflags(H | L,-2,-1,-2,-2,i,v,-2); - cycle_delta += 10; + setflags(H | L,H&0x80,-1,-2,-2,i,v,-2); + cycle_delta+=(10); /* return; */ } else { @@ -372,11 +412,12 @@ } else { /* case 0x0F: /* RRC */ + INCPC; i=A<<7&0x80; A=(A>>1)|i; i>>=7; setflags(A,-2,-2,-2,-2,i,-2,-2); - cycle_delta += 4; + cycle_delta+=(4); /* return; */ } } @@ -389,12 +430,13 @@ if(!(ins&0x02)) { if(!(ins&0x01)) { /* case 0x10: /* ASHR */ + INCPC; i = L & CF ; j = HL >> 1; L = j & 0xFF; H = (H & 0x80) | ((j >> 8) & 0xFF); setflags(0,-2,-2,-2,-2,i,-2,-2); - cycle_delta += 7; + cycle_delta+=(7); /* return; */ } else { @@ -431,11 +473,12 @@ } else { /* case 0x17: /* RAL */ + INCPC; i=A>>7; A<<=1; A|=(CF?1:0); setflags(A,-2,-2,-2,-2,i,-2,-2); - cycle_delta += 4; + cycle_delta+=(4); /* return; */ } } @@ -446,12 +489,13 @@ if(!(ins&0x02)) { if(!(ins&0x01)) { /* case 0x18: /* RLDE */ + INCPC; i = D & 0x80 ? 1 : 0; j = DE << 1; E = (j & 0xFF) | (CF ? 1 : 0); D = (j >> 8) & 0xFF; setflags(0,-2,-2,-2,-2,i,-2,-2); - cycle_delta += 10; + cycle_delta+=(10); /* return; */ } else { @@ -488,11 +532,12 @@ } else { /* case 0x1F: /* RAR */ + INCPC; i=(A&0x01); A>>=1; A|=CF?0x80:0; setflags(A,-2,-2,-2,-2,i,-2,-2); - cycle_delta += 4; + cycle_delta+=(4); /* return; */ } } @@ -507,8 +552,9 @@ if(!(ins&0x02)) { if(!(ins&0x01)) { /* case 0x20: /* RIM */ + INCPC; A=IM; - cycle_delta += 4; + cycle_delta+=(4); /* return; */ } else { @@ -519,11 +565,12 @@ else { if(!(ins&0x01)) { /* case 0x22: /* SHLD */ + INCPC; MEMSET(INS16,L); MEMSET(INS16+1,H); /* MEM16(INS16)=HL; */ INCPC2; - cycle_delta += 16; + cycle_delta+=(16); /* return; */ } else { @@ -550,6 +597,7 @@ } else { /* case 0x27: /* DAA */ + INCPC; i=j=0; /* Check if lower nibble greater than 9 */ if(((A&0x0F) > 9)) { @@ -565,7 +613,7 @@ i|=0x60;/* Add 6 to upper nibble */ A+=i; setflags(A,-1,-1,j,-1,i>>4?1:0,-2,-2); - cycle_delta += 4; + cycle_delta+=(4); /* return; */ /* Huh? */ } } @@ -576,11 +624,12 @@ if(!(ins&0x02)) { if(!(ins&0x01)) { /* case 0x28: /* LDEH */ + INCPC; j = HL + INS; INCPC; E = j & 0xFF; D = (j >> 8) & 0xFF; - cycle_delta += 10; + cycle_delta+=(10); /* return; */ } else { @@ -591,10 +640,11 @@ else { if(!(ins&0x01)) { /* case 0x2A: /* LHLD */ + INCPC; L=MEM(INS16); H=MEM(INS16+1); INCPC2; - cycle_delta += 16; + cycle_delta+=(16); } else { /* case 0x2B: /* DCX H */ @@ -620,8 +670,9 @@ } else { /* case 0x2F: /* CMA */ + INCPC; A=~A; - cycle_delta += 4; + cycle_delta+=(4); } } } @@ -633,13 +684,14 @@ if(!(ins&0x02)) { if(!(ins&0x01)) { /* case 0x30: /* SIM */ + INCPC; if (A & 0x08) /* Check if Interrupt masking enabled */ IM=(IM & 0xF8) | (A&0x07); /* Turn RST 7.5 pending off if bit 4 set */ if(A&0x10) { IM&=0xBF; } - cycle_delta += 4; + cycle_delta+=(4); /* return; */ } else { @@ -650,9 +702,10 @@ else { if(!(ins&0x01)) { /* case 0x32: /* STA */ + INCPC; MEMSET(INS16,A); INCPC2; - cycle_delta += 13; + cycle_delta+=(13); /* return; */ } else { @@ -665,36 +718,40 @@ if(!(ins&0x02)) { if(!(ins&0x01)) { /* case 0x34: /* INR M */ + INCPC; MEMSET(HL,(uchar) (M+1)); - if(M&0x0f==0) /* Low order nybble wrapped */ + if((M&0x0f)==0) /* Low order nybble wrapped */ j=1; else j=0; setflags(M,-1,-1,j,-1,-2, (M==0x80) || (M==0), -2); - cycle_delta += 10; + cycle_delta+=(10); } else { /* case 0x35: /* DCR M */ + INCPC; MEMSET(HL, (uchar)(M-1)); - if(M&0x0f==0x0f) /* Low order nybble wrapped */ + if((M&0x0f)==0x0f) /* Low order nybble wrapped */ j=1; else j=0; setflags(M,-1,-1,j,-1,-2, (M==0xFF) || (M==0x7F), -2); - cycle_delta += 10; + cycle_delta+=(10); } } else { if(!(ins&0x01)) { /* case 0x36: /* MVI M */ + INCPC; MEMSET(HL,INS); INCPC; - cycle_delta += 10; + cycle_delta+=(10); } else { /* case 0x37: /* STC */ + INCPC; setflags(0,-2,-2,-2,-2,1,-2,-2); - cycle_delta += 4; + cycle_delta+=(4); /* return; */ } } @@ -705,11 +762,12 @@ if(!(ins&0x02)) { if(!(ins&0x01)) { /* case 0x38: /* LDES */ + INCPC; j = SP + INS; INCPC; E = j & 0xFF; D = (j >> 8) & 0xFF; - cycle_delta += 10; + cycle_delta+=(10); /* return; */ } else { @@ -720,9 +778,10 @@ else { if(!(ins&0x01)) { /* case 0x3A: /* LDA */ + INCPC; A=MEM(INS16); INCPC2; - cycle_delta += 13; + cycle_delta+=(13); /* return; */ } else { @@ -749,8 +808,9 @@ } else { /* case 0x3F: /* CMC */ + INCPC; setflags(A,-2,-2,-2,-2,CF?0:1,-2,-2); - cycle_delta += 4; + cycle_delta+=(4); /* return; */ } } @@ -800,7 +860,7 @@ if(!(ins&0x01)) { /* case 0x46: /* MOV B,M */ MOV(B,M,"B","M"); - cycle_delta += 3; + cycle_delta+=(3); /* return; */ } else { @@ -848,7 +908,7 @@ if(!(ins&0x01)) { /* case 0x4E: /* MOV C,M */ MOV(C,M,"C","M"); - cycle_delta += 3; + cycle_delta+=(3); } else { /* case 0x4F: /* MOV C,A */ @@ -897,7 +957,7 @@ if(!(ins&0x01)) { /* case 0x56: /* MOV D,M */ MOV(D,M,"D","M"); - cycle_delta += 3; + cycle_delta+=(3); } else { /* case 0x57: /* MOV D,A */ @@ -944,7 +1004,7 @@ if(!(ins&0x01)) { /* case 0x5E: /* MOV E,M */ MOV(E,M,"E","M"); - cycle_delta += 3; + cycle_delta+=(3); } else { /* case 0x5F: /* MOV E,A */ @@ -1041,7 +1101,7 @@ if(!(ins&0x01)) { /* case 0x6E: /* MOV L,M */ MOV(L,M,"L","M"); - cycle_delta += 3; + cycle_delta+=(3); } else { /* case 0x6F: /* MOV L,A */ @@ -1089,8 +1149,7 @@ else { if(!(ins&0x01)) { /* case 0x76: /* HLT */ - cycle_delta += 4; - DECPC; + cycle_delta+=(4); /* return; */ } else { @@ -1138,7 +1197,7 @@ if(!(ins&0x01)) { /* case 0x7E: /* MOV A,M */ MOV(A,M,"A","M"); - cycle_delta += 3; + cycle_delta+=(3); } else { /* case 0x7F: /* MOV A,A */ @@ -1193,7 +1252,7 @@ if(!(ins&0x01)) { /* case 0x86: /* ADD M */ ADD(M,"M"); - cycle_delta += 3; + cycle_delta+=(3); } else { /* case 0x87: /* ADD A */ @@ -1240,7 +1299,7 @@ if(!(ins&0x01)) { /* case 0x8E: /* ADC M */ ADC(M,"M"); - cycle_delta += 3; + cycle_delta+=(3); } else { /* case 0x8F: /* ADC A */ @@ -1289,7 +1348,7 @@ if(!(ins&0x01)) { /* case 0x96: /* SUB M */ SUB(M,"M"); - cycle_delta += 3; + cycle_delta+=(3); } else { /* case 0x97: /* SUB A */ @@ -1336,7 +1395,7 @@ if(!(ins&0x01)) { /* case 0x9E: /* SBB M */ SBB(M,"M"); - cycle_delta += 3; + cycle_delta+=(3); } else { /* case 0x9F: /* SBB A */ @@ -1387,7 +1446,7 @@ if(!(ins&0x01)) { /* case 0xA6: /* ANA M */ ANA(M,"M"); - cycle_delta += 3; + cycle_delta+=(3); } else { /* case 0xA7: /* ANA A */ @@ -1434,7 +1493,7 @@ if(!(ins&0x01)) { /* case 0xAE: /* XRA M */ XRA(M,"M"); - cycle_delta += 3; + cycle_delta+=(3); } else { /* case 0xAF: /* XRA A */ @@ -1483,7 +1542,7 @@ if(!(ins&0x01)) { /* case 0xB6: /* ORA M */ ORA(M,"M"); - cycle_delta += 3; + cycle_delta+=(3); } else { /* case 0xB7: /* ORA A */ @@ -1530,7 +1589,7 @@ if(!(ins&0x01)) { /* case 0xBE: /* CMP M */ CMP(M,"M"); - cycle_delta += 3; + cycle_delta+=(3); } else { /* case 0xBF: /* CMP A */ @@ -1550,12 +1609,13 @@ if(!(ins&0x02)) { if(!(ins&0x01)) { /* case 0xC0: /* RNZ */ + INCPC; if(!ZF) { PCL=MEM(SP); PCH=MEM(SP+1); /* PC=MEM16(SP) */ INCSP2; - cycle_delta += 6; + cycle_delta+=(6); } - cycle_delta += 6; + cycle_delta+=(6); /* return; */ } else { @@ -1588,19 +1648,20 @@ else { if(!(ins&0x01)) { /* case 0xC6: /* ADI n */ + INCPC; i=A; i+=INS; - j = (((A&0x0F)+(ins&0x0F)) &0x10)>>4; - v = (A&0x80) == (ins&0x80); + j = (((A&0x0F)+(INS&0x0F)) &0x10)>>4; + v = (A&0x80) == (INS&0x80); A=i; if(i>0xFF) i=1; else i=0; if (v) - v = (A&0x80) != (ins&0x80); + v = (A&0x80) != (INS&0x80); setflags(A,-1,-1,j,-1,i,v,-2); - cycle_delta += 7; + cycle_delta+=(7); INCPC; /* return; */ } @@ -1629,8 +1690,9 @@ JUMP(ZF,"JZ"); } else { - /* case 0xCB: /* INVALID? */ - bail("0xCB is invalid"); + /* case 0xCB: /* RSTV */ + if (OV) + RST(8); /* return; */ } } @@ -1649,20 +1711,21 @@ else { if(!(ins&0x01)) { /* case 0xCE: /* ACI n */ + INCPC; i=A; i+=INS; i+=(CF?1:0); - j = (((A&0x0F)+(ins&0x0F)+(CF?1:0)) &0x10)>>4; - v = (A&0x80) == (ins&0x80); + j = (((A&0x0F)+(INS&0x0F)+(CF?1:0)) &0x10)>>4; + v = (A&0x80) == (INS&0x80); A=i; if(i>0xFF) i=1; else i=0; if (v) - v = (A&0x80) != (ins&0x80); + v = (A&0x80) != (INS&0x80); setflags(A,-1,-1,j,-1,i,v,-2); - cycle_delta += 7; + cycle_delta+=(7); INCPC; /* return; */ } @@ -1694,9 +1757,10 @@ } else { /* case 0xD3: /* OUT port */ + INCPC; out(INS,A); INCPC; - cycle_delta += 10; + cycle_delta+=(10); /* return; */ } } @@ -1715,19 +1779,20 @@ else { if(!(ins&0x01)) { /* case 0xD6: /* SUI n */ + INCPC; i=A; i-=INS; - j = (((A&0x0F)-(ins&0x0F)) &0x10)>>4; - v = (A&0x80) == (ins&0x80); + j = (((A&0x0F)-(INS&0x0F)) &0x10)>>4; + v = (A&0x80) == (INS&0x80); A=i; if (i>0xFF) i = 1; else i = 0; if (v) - v = (A&0x80) != (ins&0x80); + v = (A&0x80) != (INS&0x80); setflags(A,-1,-1,j,-1,i,v,-2); - cycle_delta += 7; + cycle_delta+=(7); INCPC; /* return; */ } @@ -1747,9 +1812,10 @@ } else { /* case 0xD9: /* SHLX */ + INCPC; MEMSET(DE, L); MEMSET(DE+1, H); - cycle_delta += 10; + cycle_delta+=(10); /* return; */ } } @@ -1760,9 +1826,10 @@ } else { /* case 0xDB: /* IN port */ + INCPC; A=inport(INS); INCPC; - cycle_delta += 10; + cycle_delta+=(10); } } } @@ -1774,28 +1841,29 @@ } else { /* case 0xDD: /* JNX addr */ - JUMP(!OV,"JND"); + JUMP(!XF,"JNX"); /* return; */ } } else { if(!(ins&0x01)) { /* case 0xDE: /* SBI n */ + INCPC; i=A; i-=INS; i-=(CF?1:0); - j = (((A&0x0F)-(ins&0x0F)-(CF?1:0)) &0x10)>>4; - v = (A&0x80) == (ins&0x80); + j = (((A&0x0F)-(INS&0x0F)-(CF?1:0)) &0x10)>>4; + v = (A&0x80) == (INS&0x80); A=i; if (i>0xFF) i = 1; else i = 0; if (v) - v = (A&0x80) != (ins&0x80); + v = (A&0x80) != (INS&0x80); setflags(A,-1,-1,j,-1,i,v,-2); INCPC; - cycle_delta += 7; + cycle_delta+=(7); /* return; */ } else { @@ -1828,6 +1896,7 @@ } else { /* case 0xE3: /* XTHL */ + INCPC; i=H; j=L; L=MEM(SP); @@ -1836,7 +1905,7 @@ MEMSET(SP, (uchar) j); MEMSET(SP+1, (uchar) i); /* MEM16(SP)=i; */ - cycle_delta += 16; + cycle_delta+=(16); /* return; */ } } @@ -1855,10 +1924,11 @@ else { if(!(ins&0x01)) { /* case 0xE6: /* ANI n */ + INCPC; A=A&INS; INCPC; setflags(A,-1,-1,1,-1,0,-2,-2); - cycle_delta += 7; + cycle_delta+=(7); /* return; */ } else { @@ -1880,7 +1950,7 @@ PCH=H; PCL=L; /* PC=HL; */ - cycle_delta += 6; + cycle_delta+=(6); /* return; */ } } @@ -1891,6 +1961,7 @@ } else { /* case 0xEB: /* XCHG */ + INCPC; i=H; H=D; D=i; @@ -1900,7 +1971,7 @@ /* i=HL; */ /* HL=DE; */ /* DE=i; */ - cycle_delta += 4; + cycle_delta+=(4); /* return; */ } } @@ -1913,19 +1984,21 @@ } else { /* case 0xED: /* LHLX */ + INCPC; L=MEM(DE); H=MEM(DE+1); - cycle_delta += 10; + cycle_delta+=(10); /* return; */ } } else { if(!(ins&0x01)) { /* case 0xEE: /* XRI n */ + INCPC; A=A^INS; INCPC; setflags(A,-1,-1,0,-1,0,-2,-2); - cycle_delta += 7; + cycle_delta+=(4); /* return; */ } else { @@ -1956,8 +2029,9 @@ } else { /* case 0xF3: /* DI */ + INCPC; IM|=0x08; - cycle_delta += 4; + cycle_delta+=(4); /* return; */ } } @@ -1976,10 +2050,11 @@ else { if(!(ins&0x01)) { /* case 0xF6: /* ORI n */ + INCPC; A=A|INS; INCPC; setflags(A,-1,-1,0,-1,0,-2,-2); - cycle_delta += 7; + cycle_delta+=(7); /* return; */ } else { @@ -1998,9 +2073,10 @@ } else { /* case 0xF9: /* SPHL */ + INCPC; SPH=H; SPL=L; - cycle_delta += 6; + cycle_delta+=(6); /* return; */ } } @@ -2011,8 +2087,9 @@ } else { /* case 0xFB: /* EI */ + INCPC; IM&=0xF7; - cycle_delta += 4; + cycle_delta+=(4); /* return; */ } } @@ -2025,27 +2102,28 @@ } else { /* case 0xFD: /* JX addr */ - JUMP(OV,"JD"); + JUMP(XF,"JX"); /* return; */ } } else { if(!(ins&0x01)) { /* case 0xFE: /* CPI n */ + INCPC; i=A; i-=INS; if(i>0xFF) i=1; else i=0; -// j = (((A & 0x0F)-(INS & 0x0F)) & 0x10) >> 4; -// if ((A&0x80) == (ins&0x80)) -// v = (A&0x80) != (ins&0x80); -// else -// v = 0; - setflags(A-INS,-1,-1,j,-1,i,0,-2); + j = (((A & 0x0F)-(INS & 0x0F)) & 0x10) >> 4; + if ((A&0x80) == (INS&0x80)) + v = (A&0x80) != (INS&0x80); + else + v = 0; + setflags(A-INS,-1,-1,j,-1,i,v,-2); INCPC; - cycle_delta += 7; + cycle_delta+=(7); /* return; */ } else { diff --git a/src/doins.c b/src/doins.c index 3a97a19..4a1de92 100644 --- a/src/doins.c +++ b/src/doins.c @@ -63,33 +63,33 @@ __inline void setflags(unsigned char regval, char sign, char zero, char auxcarry if (sign!=-2) { if(sign>=0) - F=(F&0x7F)|(sign?0x80:0); + F=(F&~SF_BIT)|(sign?SF_BIT:0); else - F=(F&0x7F)|(regval&0x80); + F=(F&~SF_BIT)|(regval&SF_BIT); } if (zero != -2) { if(zero>=0) - F=(F&0xBF)|(zero?0x40:0); + F=(F&~ZF_BIT)|(zero?ZF_BIT:0); else - F=(F&0xBF)|(regval?0:0x40); + F=(F&~ZF_BIT)|(regval?0:ZF_BIT); } if(auxcarry>=0) - F=(F&0xEF)|(auxcarry?0x10:0); + F=(F&~AC_BIT)|(auxcarry?AC_BIT:0); if (parity != -2) { if(parity>=0) - F=(F&0xFB)|(parity?0x04:0); + F=(F&~PF_BIT)|(parity?PF_BIT:0); else /* Table Lookup */ - F=(F&0xFB)|paritybits[regval & 0xFF]; + F=(F&~PF_BIT)|paritybits[regval & 0xFF]; } if(carry>=0) - F=(F&0xFE)|(carry?1:0); + F=(F&~CF_BIT)|(carry?CF_BIT:0); if (ov >= 0) F=(F&~OV_BIT)|(ov?OV_BIT:0); diff --git a/src/file.cpp b/src/file.cpp index 1454c00..1df2d7a 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -486,7 +486,9 @@ int tokenize(unsigned char* in, unsigned char* out, unsigned short addr) } -void cb_LoadFromHost(Fl_Widget* w, void*) +int gLoadError; + +void cb_LoadFromHost(Fl_Widget* w, void* host_filename) { int count, i, x; Fl_File_Chooser *fc; @@ -505,35 +507,50 @@ void cb_LoadFromHost(Fl_Widget* w, void*) int move_len; int need_tokenize; - fc = new Fl_File_Chooser(".","Model T Files (*.{do,txt,ba,co,hex})",1,"Load file from Host"); - fc->preview(0); - fc->show(); + if (w != NULL) + { + fc = new Fl_File_Chooser(".","Model T Files (*.{do,txt,ba,co,hex})",1,"Load file from Host"); + fc->preview(0); + fc->show(); - while (fc->visible()) - Fl::wait(); + while (fc->visible()) + Fl::wait(); - count = fc->count(); - if (count == 0) - { - delete fc; - return; - } + count = fc->count(); + if (count == 0) + { + delete fc; + return; + } // Get Filename - filename = fc->value(1); - if (filename == 0) - { + filename = fc->value(1); + if (filename == 0) + { + delete fc; + return; + } + + len = strlen(filename); delete fc; - return; } - len = strlen(filename); - delete fc; + else + { + if (host_filename == NULL) + return; + + filename = (const char*) host_filename; + len = strlen(filename); + } // Open file fd = fopen(filename, "rb"); if (fd == 0) { - fl_message("Unable to open file %s", filename); + if (w != NULL) + fl_message("Unable to open file %s", filename); + else + gLoadError = 1; return; } @@ -583,7 +600,10 @@ void cb_LoadFromHost(Fl_Widget* w, void*) if (len > 262144) { fclose(fd); - fl_message(gTooLargeMsg); + if (w != NULL) + fl_message(gTooLargeMsg); + else + gLoadError = 1; return; } @@ -620,7 +640,10 @@ void cb_LoadFromHost(Fl_Widget* w, void*) conv[x++] = ch; if (x >= 32768) { - fl_message(gTooLargeMsg); + if (w != NULL) + fl_message(gTooLargeMsg); + else + gLoadError = 1; return; } } @@ -671,7 +694,12 @@ void cb_LoadFromHost(Fl_Widget* w, void*) { len = load_hex_file((char *) filename, (char *) data, &start_addr); if (len == 0) - fl_message("Invalid HEX file format"); + { + if (w != NULL) + fl_message("Invalid HEX file format"); + else + gLoadError = 1; + } } if (len == 0) @@ -682,7 +710,10 @@ void cb_LoadFromHost(Fl_Widget* w, void*) addr2 = get_memory16(gStdRomDesc->sBeginVar); if (addr3 - addr2 < len) { - fl_message(gTooLargeMsg); + if (w != NULL) + fl_message(gTooLargeMsg); + else + gLoadError = 1; return; } @@ -700,7 +731,10 @@ void cb_LoadFromHost(Fl_Widget* w, void*) if (x == 8) { - fl_message("File %s already exists", filename_name); + if (w != NULL) + fl_message("File %s already exists", filename_name); + else + gLoadError = 1; return; } @@ -717,7 +751,10 @@ void cb_LoadFromHost(Fl_Widget* w, void*) addr4 += 11; if (++dir_index >= gStdRomDesc->sDirCount) { - fl_message("Too many files in directory"); + if (w != NULL) + fl_message("Too many files in directory"); + else + gLoadError = 1; return; } } @@ -830,6 +867,12 @@ void cb_LoadFromHost(Fl_Widget* w, void*) } +int remote_load_from_host(const char *filename) +{ + gLoadError = 0; + cb_LoadFromHost(NULL, (void *) filename); + return gLoadError; +} /* ======================================================================= diff --git a/src/fl_usage_box.cpp b/src/fl_usage_box.cpp new file mode 100644 index 0000000..50cbc64 --- /dev/null +++ b/src/fl_usage_box.cpp @@ -0,0 +1,184 @@ +/* fl_usage_box.cpp */ + +/* $Id$ */ + +/* + * Copyright 2008 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include "fl_usage_box.h" + +#include +#include + +/* +======================================================= +Fl_Usage_Box: This is the class construcor +======================================================= +*/ +Fl_Usage_Box::Fl_Usage_Box(int x, int y, int w, int h) : + Fl_Box(x, y, w, h) +{ + int i; + + // Allocate space for the usage data + m_usageMapSize = (w-4) * (h-4); // Leave room for border + + m_pUsageMap = new unsigned char[m_usageMapSize]; + for (i = 0; i < m_usageMapSize; i++) + m_pUsageMap[i] = 0; + + m_usageMin = 0; + m_usageMax = 99; + m_maxUsageEntry = 0; + m_backgroundColor = fl_rgb_color(255, 255, 255); + m_pixelsPerUsage = m_usageMapSize / 100; + m_usageScale = 1.0 / 100.0; +} + +/* +========================================================== +SetUsageRange: This function sets the range of the usage + box. This range is used to perform + scaling during usage updates. +========================================================== +*/ +void Fl_Usage_Box::SetUsageRange(int min, int max) +{ + m_usageMin = min; + m_usageMax = max; + m_pixelsPerUsage = m_usageMapSize / (max - min+1); + m_usageScale = 1.0 / ((double) (max - min + 1)); +} + +/* +========================================================== +SetUsageColor: This function sets the display color for + the specified usage entry. +========================================================== +*/ +void Fl_Usage_Box::SetUsageColor(int index, int color) +{ + if (index > 255) + return; + + m_usageColors[index] = color; + if (index > m_maxUsageEntry) + m_maxUsageEntry = index; +} + +/* +========================================================== +ClearUsageMap: This function clears the usage map for the + entire usage box. +========================================================== +*/ +void Fl_Usage_Box::ClearUsageMap(void) +{ + int c; + + for (c = 0; c < m_usageMapSize; c++) + m_pUsageMap[c] = 0; + + redraw(); +} + +/* +========================================================== +AddUsageEvent: This function adds a new usage event to + the usage box and forces a redraw. +========================================================== +*/ +void Fl_Usage_Box::AddUsageEvent(int start, int end, unsigned char usage) +{ + int i; + int usage_start, usage_end; + + // Ensure start and end are within specified usage range + if ((start < m_usageMin) || (start > m_usageMax) || (end < m_usageMin) + || (end > m_usageMax) || (start > end)) + { + return; + } + + // Determine first and last usage entry point to update + usage_start = (int) ((double) start * m_usageScale * m_usageMapSize) ; + usage_end = (int) ((double) (end + 1) * m_usageScale * m_usageMapSize) - 1; + + // Fill in usage map entries for this usage + for (i = usage_start; i <= usage_end; i++) + m_pUsageMap[i] += usage; + + if (usage > m_maxUsageEntry) + m_maxUsageEntry = usage; + + redraw(); +} + +/* +================================================================= +draw_static: This routine draws the static portions of the LCD, + such as erasing the background, drawing function + key labls, etc. +================================================================= +*/ +void Fl_Usage_Box::draw() +{ + int c, i; + int x_pos, y_pos; + + // Draw background + fl_color(m_backgroundColor); + fl_rectf(x()+1,y()+1,w()-2,h()-2); + + // Draw frame + fl_color(FL_BLACK); + fl_rect(x(),y(), w(), h()); + + // Draw usage information + for (c = 1; c < 256; c++) + { + // Test if index greater than max usage entry + if (c > m_maxUsageEntry) + break; + + // Selet Color for this usage entry + fl_color(m_usageColors[c]); + + // "Walk" through the usage map and draw a pixel for each entry with this usage + for (i = 0; i < m_usageMapSize; i++) + { + if (m_pUsageMap[i] == c) + { + x_pos = i / (h()-4) + 2; + y_pos = i % (h()-4) + 2; + fl_point(x() + x_pos, y() + y_pos); + } + } + } +} + diff --git a/src/fl_usage_box.h b/src/fl_usage_box.h new file mode 100644 index 0000000..bc5144d --- /dev/null +++ b/src/fl_usage_box.h @@ -0,0 +1,71 @@ +/* fl_usage_box.h */ + +/* $Id$ */ + +/* + * Copyright 2008 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef _FL_USAGE_BOX_H_ +#define _FL_USAGE_BOX_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus + +class Fl_Usage_Box : public Fl_Box +{ +public: + Fl_Usage_Box(int x, int y, int w, int h); + + void SetUsageColor(int index, int color); + void SetUsageRange(int min, int max); + void SetBackgroundColor(int color); + void AddUsageEvent(int start, int end, unsigned char usage); + void ClearUsageMap(void); + +protected: + virtual void draw(); + + unsigned char* m_pUsageMap; + int m_usageMapSize; + int m_usageMin, m_usageMax; + + int m_usageColors[256]; + int m_maxUsageEntry; + int m_backgroundColor; + int m_pixelsPerUsage; + double m_usageScale; +}; + +} +#endif + +#endif diff --git a/src/genwrap.c b/src/genwrap.c index 7cba246..52dac46 100644 --- a/src/genwrap.c +++ b/src/genwrap.c @@ -258,7 +258,7 @@ int DLLCALL xp_random(int n) static BOOL initialized; if(!initialized) { - srand(time(NULL)); /* seed random number generator */ + srand((int) time(NULL)); /* seed random number generator */ rand(); /* throw away first result */ initialized=TRUE; } diff --git a/src/ide.cpp b/src/ide.cpp index aa69d90..d13e6b1 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -43,22 +43,43 @@ #include #include #include +#include +#include +#include +#ifdef _WIN32 +#include +#endif #include "VirtualT.h" #include "m100emu.h" #include "ide.h" -#include "multiwin.h" +#include "multieditwin.h" #include "disassemble.h" #include "cpuregs.h" #include "memedit.h" #include "periph.h" +#include "MStringArray.h" +#include "assemble.h" VT_Ide * gpIde = 0; Fl_Menu_Button* gPopup = 0; void setMonitorWindow(Fl_Window* pWin); Fl_Multi_Window* gpLcd; +#ifdef _WIN32 +extern "C" +#endif +extern char path[]; + +MString gRootpath; + +extern Fl_Preferences virtualt_prefs; + void close_cb(Fl_Widget* w, void*); +void cb_help(Fl_Widget* w, void*); +void cb_about(Fl_Widget* w, void*); +void cb_lcd_display(Fl_Widget* w, void*); +// Define File Manu callbacks void cb_new_file(Fl_Widget* w, void*); void cb_open_file(Fl_Widget* w, void*); void cb_save_file(Fl_Widget* w, void*); @@ -66,13 +87,39 @@ void cb_save_as(Fl_Widget* w, void*); void cb_new_project(Fl_Widget* w, void*); void cb_open_project(Fl_Widget* w, void*); void cb_save_project(Fl_Widget* w, void*); -void cb_help(Fl_Widget* w, void*); -void cb_about(Fl_Widget* w, void*); -void cb_lcd_display(Fl_Widget* w, void*); +// Define Edit menu callbacks +void cb_copy(Fl_Widget* w, void*); +void cb_cut(Fl_Widget* w, void*); +void cb_paste(Fl_Widget* w, void*); +void cb_find(Fl_Widget* w, void*); +void cb_find_next(Fl_Widget* w, void*); +void cb_replace(Fl_Widget* w, void*); +// Define Window management routines +void cb_window_cascade(Fl_Widget* w, void*); +void cb_window_1(Fl_Widget* w, void*); +void cb_window_2(Fl_Widget* w, void*); +void cb_window_3(Fl_Widget* w, void*); +void cb_window_4(Fl_Widget* w, void*); +void cb_window_5(Fl_Widget* w, void*); +void cb_window_6(Fl_Widget* w, void*); +void cb_window_more(Fl_Widget* w, void*); +// Define project management routines +void cb_build_project(Fl_Widget* w, void*); +void cb_rebuild_project(Fl_Widget* w, void*); +void cb_clean_project(Fl_Widget* w, void*); +void cb_project_settings(Fl_Widget* w, void*); IMPLEMENT_DYNCREATE(VT_IdeGroup, VTObject); IMPLEMENT_DYNCREATE(VT_IdeSource, VTObject); +char gProjectTypes[][6] = { + ".co", + ".obj", + ".rom", + ".ba", + "" +}; + /* ======================================================= Menu Items for the IDE window @@ -80,55 +127,56 @@ Menu Items for the IDE window */ Fl_Menu_Item gIde_menuitems[] = { { "&File", 0, 0, 0, FL_SUBMENU }, - { "New File", 0, cb_new_file, 0, 0 }, - { "Open File...", 0, cb_open_file, 0, 0 }, - { "Save File...", 0, cb_save_file, 0, 0}, + { "New File", FL_CTRL + 'n', cb_new_file, 0, 0 }, + { "Open File...", FL_CTRL + 'o', cb_open_file, 0, 0 }, + { "Save File", FL_CTRL + 's', cb_save_file, 0, 0}, { "Save As...", 0, cb_save_as, 0, FL_MENU_DIVIDER }, { "New Project...", 0, cb_new_project, 0, 0 }, { "Open Project...", 0, cb_open_project, 0, 0 }, - { "Save Project...", 0, cb_save_project, 0, FL_MENU_DIVIDER }, + { "Save Project", 0, cb_save_project, 0, FL_MENU_DIVIDER }, { "E&xit", FL_CTRL + 'q', close_cb, 0 }, { 0 }, + { "&Edit", 0, 0, 0, FL_SUBMENU }, + { "Copy", FL_CTRL + 'c', cb_copy, 0, 0 }, + { "Cut", FL_CTRL + 'x', cb_cut, 0, 0 }, + { "Paste", FL_CTRL + 'v', cb_paste, 0, FL_MENU_DIVIDER}, + { "Find...", FL_CTRL + 'f', cb_find, 0, 0 }, + { "Find Next", FL_F + 3, cb_find_next, 0, 0 }, + { "Replace", FL_CTRL + 'r', cb_replace, 0, 0 }, + { 0 }, + { "&Project", 0, 0, 0, FL_SUBMENU }, + { "Build", FL_SHIFT + FL_F+8, cb_build_project, 0, 0 }, + { "Rebuild", 0, cb_rebuild_project, 0, 0 }, + { "Clean", 0, cb_clean_project, 0, FL_MENU_DIVIDER }, + { "Settings", 0, cb_project_settings, 0, 0 }, + { 0 }, { "&Debug", 0, 0, 0, FL_SUBMENU }, { "Laptop Display", 0, cb_lcd_display, 0, 0 }, { 0 }, -/* - { "&Emulation", 0, 0, 0, FL_SUBMENU }, - { "Reset", 0, cb_reset, 0, FL_MENU_DIVIDER }, - { "Model", 0, 0, 0, FL_SUBMENU } , - { "M100", 0, cb_M100, (void *) 1, FL_MENU_RADIO | FL_MENU_VALUE }, - { "M102", 0, cb_M102, (void *) 2, FL_MENU_RADIO }, - { "T200", 0, cb_M200, (void *) 3, FL_MENU_RADIO }, - { "PC-8201", 0, cb_PC8201, (void *) 4, FL_MENU_RADIO }, -// { "8300", 0, cb_PC8300, (void *) 5, FL_MENU_RADIO }, - { 0 }, - { "Speed", 0, 0, 0, FL_SUBMENU }, - { "2.4 MHz", 0, rspeed, (void *) 1, FL_MENU_RADIO | FL_MENU_VALUE }, - { "Max Speed", 0, fspeed, (void *) 1, FL_MENU_RADIO }, - { 0 }, - { "Display", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER}, - { "1x", 0, cb_1x, (void *) 1, FL_MENU_RADIO }, - { "2x", 0, cb_2x, (void *) 2, FL_MENU_RADIO }, - { "3x", 0, cb_3x, (void *) 3, FL_MENU_RADIO | FL_MENU_VALUE}, - { "4x", 0, cb_4x, (void *) 4, FL_MENU_RADIO | FL_MENU_DIVIDER}, - { "Framed", 0, cb_framed, (void *) 1, FL_MENU_TOGGLE|FL_MENU_VALUE }, - { "Solid Chars", 0, cb_solidchars, (void *) 1, FL_MENU_TOGGLE}, - { 0 }, -*/ - { "&Tools", 0, 0, 0, FL_SUBMENU }, - { "CPU Registers", 0, cb_CpuRegs }, - { "Disassembler", 0, disassembler_cb }, - { "Memory Editor", 0, cb_MemoryEditor }, - { "Peripheral Devices", 0, cb_PeripheralDevices }, - { "Simulation Log Viewer", 0, 0 }, - { "Model T File Viewer", 0, 0 }, - { 0 }, - { "&Help", 0, 0, 0, FL_SUBMENU }, - { "Help", 0, cb_help }, - { "About VirtualT", 0, cb_about }, - { 0 }, + { "&Tools", 0, 0, 0, FL_SUBMENU }, + { "CPU Registers", 0, cb_CpuRegs }, + { "Disassembler", 0, disassembler_cb }, + { "Memory Editor", 0, cb_MemoryEditor }, + { "Peripheral Devices", 0, cb_PeripheralDevices }, + { "Simulation Log Viewer", 0, 0 }, + { "Model T File Viewer", 0, 0 }, + { 0 }, + { "&Window", 0, 0, 0, FL_SUBMENU }, + { "Cascade", 0, cb_window_cascade, 0, 0 }, + { "1", 0, cb_window_1, 0, 0 }, + { "2", 0, cb_window_2, 0, 0 }, + { "3", 0, cb_window_3, 0, 0 }, + { "4", 0, cb_window_4, 0, 0 }, + { "5", 0, cb_window_5, 0, 0 }, + { "6", 0, cb_window_6, 0, 0 }, + { "More...", 0, cb_window_more, 0, 0 }, + { 0 }, + { "&Help", 0, 0, 0, FL_SUBMENU }, + { "Help", 0, cb_help }, + { "About VirtualT", 0, cb_about }, + { 0 }, - { 0 } + { 0 } }; void cb_new_folder(Fl_Widget* w, void*); @@ -137,9 +185,6 @@ void cb_folder_properties(Fl_Widget* w, void*); void cb_open_tree_file(Fl_Widget* w, void*); void cb_assemble_tree_file(Fl_Widget* w, void*); void cb_tree_file_properties(Fl_Widget* w, void*); -void cb_build(Fl_Widget* w, void*); -void cb_build_all(Fl_Widget* w, void*); -void cb_project_settings(Fl_Widget* w, void*); Fl_Menu_Item gGroupMenu[] = { { "New Folder", 0, cb_new_folder, 0, 0 }, @@ -156,8 +201,8 @@ Fl_Menu_Item gSourceMenu[] = { }; Fl_Menu_Item gRootMenu[] = { - { "Build", 0, cb_build, 0, 0 }, - { "Build All", 0, cb_build_all, 0, 0 }, + { "Build", 0, cb_build_project, 0, 0 }, + { "Build All", 0, cb_rebuild_project, 0, 0 }, { "New Folder...", 0, cb_new_folder, 0, 0}, { "Add Files to Project...", 0, cb_add_files_to_folder, 0, FL_MENU_DIVIDER }, { "Project Settings...", 0, cb_project_settings, 0, 0}, @@ -173,8 +218,30 @@ Callback routine for the close box of the IDE window */ void close_ide_cb(Fl_Widget* w, void*) { + int ans; + MString question; + if (gpIde != NULL) { + // Check if project is dirty + if (gpIde->ProjectDirty()) + { + // Ask if project should be saved + question.Format("Save changes to project %s?", (const char *) gpIde->ProjectName()); + ans = fl_choice((const char *) question, "Cancel", "Yes", "No"); + if (ans == 0) + return; + if (ans == 1) + gpIde->SaveProject(); + } + + // Save window parameters to preferences + virtualt_prefs.set("IdeX", gpIde->x()); + virtualt_prefs.set("IdeY", gpIde->y()); + virtualt_prefs.set("IdeW", gpIde->w()); + virtualt_prefs.set("IdeH", gpIde->h()); + + // Okay, close the window setMonitorWindow(0); gpIde->hide(); delete gpIde; @@ -191,6 +258,10 @@ Callback routine for creating new files */ void cb_new_file(Fl_Widget* w, void*) { + if (gpIde != NULL) + { + gpIde->NewFile(); + } } /* @@ -200,6 +271,8 @@ Callback routine for opening files */ void cb_open_file(Fl_Widget* w, void*) { + if (gpIde != NULL) + gpIde->OpenFile(); } /* @@ -209,6 +282,8 @@ Callback routine for saving files */ void cb_save_file(Fl_Widget* w, void*) { + if (gpIde != NULL) + gpIde->SaveFile(); } /* @@ -218,6 +293,8 @@ Callback routine for save as */ void cb_save_as(Fl_Widget* w, void*) { + if (gpIde != NULL) + gpIde->SaveAs(); } /* @@ -227,7 +304,8 @@ Callback routine for creating new project */ void cb_new_project(Fl_Widget* w, void*) { - gpIde->NewProject(); + if (gpIde != NULL) + gpIde->NewProject(); } /* @@ -237,7 +315,8 @@ Callback routine for opening a project */ void cb_open_project(Fl_Widget* w, void*) { - gpIde->OpenProject(); + if (gpIde != NULL) + gpIde->OpenProject(); } /* @@ -247,6 +326,74 @@ Callback routine for saving current project */ void cb_save_project(Fl_Widget* w, void*) { + if (gpIde != NULL) + gpIde->SaveProject(); +} + +/* +======================================================= +Callback routine for copying text +======================================================= +*/ +void cb_copy(Fl_Widget* w, void*) +{ + if (gpIde != NULL) + gpIde->Copy(); +} + +/* +======================================================= +Callback routine for cutting text +======================================================= +*/ +void cb_cut(Fl_Widget* w, void*) +{ + if (gpIde != NULL) + gpIde->Cut(); +} + +/* +======================================================= +Callback routine for pasting text +======================================================= +*/ +void cb_paste(Fl_Widget* w, void*) +{ + if (gpIde != NULL) + gpIde->Paste(); +} + +/* +======================================================= +Callback routine for finding text +======================================================= +*/ +void cb_find(Fl_Widget* w, void*) +{ + if (gpIde != NULL) + gpIde->Find(); +} + +/* +======================================================= +Callback routine for finding next text +======================================================= +*/ +void cb_find_next(Fl_Widget* w, void*) +{ + if (gpIde != NULL) + gpIde->FindNext(); +} + +/* +======================================================= +Callback routine for replacing text +======================================================= +*/ +void cb_replace(Fl_Widget* w, void*) +{ + if (gpIde != NULL) + gpIde->Replace(); } void cb_close_lcd(Fl_Widget* w, void*) @@ -297,7 +444,7 @@ void cb_new_folder(Fl_Widget* w, void* data) { Flu_Tree_Browser::Node* n = (Flu_Tree_Browser::Node*) data; - // Insure window exists + // Ensure window exists if (gpIde != 0) gpIde->NewFolder(n); } @@ -311,7 +458,7 @@ void cb_add_files_to_folder(Fl_Widget* w, void* data) { Flu_Tree_Browser::Node* n = (Flu_Tree_Browser::Node*) data; - // Insure window exists + // Ensure window exists if (gpIde != 0) gpIde->AddFilesToFolder(n); } @@ -325,7 +472,7 @@ void cb_folder_properties(Fl_Widget* w, void* data) { Flu_Tree_Browser::Node* n = (Flu_Tree_Browser::Node*) data; - // Insure window exists + // Ensure window exists if (gpIde != 0) gpIde->FolderProperties(n); } @@ -339,7 +486,7 @@ void cb_open_tree_file(Fl_Widget* w, void* data) { Flu_Tree_Browser::Node* n = (Flu_Tree_Browser::Node*) data; - // Insure window exists + // Ensure window exists if (gpIde != 0) gpIde->OpenTreeFile(n); } @@ -353,7 +500,7 @@ void cb_assemble_tree_file(Fl_Widget* w, void* data) { Flu_Tree_Browser::Node* n = (Flu_Tree_Browser::Node*) data; - // Insure window exists + // Ensure window exists if (gpIde != 0) gpIde->AssembleTreeFile(n); } @@ -367,7 +514,7 @@ void cb_tree_file_properties(Fl_Widget* w, void* data) { Flu_Tree_Browser::Node* n = (Flu_Tree_Browser::Node*) data; - // Insure window exists + // knsure window exists if (gpIde != 0) gpIde->TreeFileProperties(n); } @@ -377,8 +524,11 @@ void cb_tree_file_properties(Fl_Widget* w, void* data) Callback routine to build the project ======================================================= */ -void cb_build(Fl_Widget* w, void*) +void cb_build_project(Fl_Widget* w, void*) { + // Call the routine to build the project + if (gpIde != NULL) + gpIde->BuildProject(); } /* @@ -386,8 +536,11 @@ void cb_build(Fl_Widget* w, void*) Callback routine to build all project files ======================================================= */ -void cb_build_all(Fl_Widget* w, void*) +void cb_rebuild_project(Fl_Widget* w, void*) { + // Rebuild is a clean followed by a build + cb_clean_project(w, NULL); + cb_build_project(w, NULL); } /* @@ -396,6 +549,93 @@ Callback routine to display project settings ======================================================= */ void cb_project_settings(Fl_Widget* w, void*) +{ + // Display the project settings + if (gpIde != NULL) + gpIde->ShowProjectSettings(); +} + +/* +======================================================= +Callback routine to clean the active project +======================================================= +*/ +void cb_clean_project(Fl_Widget* w, void*) +{ + // Delete all output files for this project + if (gpIde != NULL) + gpIde->CleanProject(); +} + +/* +======================================================= +Callback routine to cascade all windows +======================================================= +*/ +void cb_window_cascade(Fl_Widget* w, void*) +{ +} + +/* +======================================================= +Callback routine to select window 1 +======================================================= +*/ +void cb_window_1(Fl_Widget* w, void*) +{ +} + +/* +======================================================= +Callback routine to select window 2 +======================================================= +*/ +void cb_window_2(Fl_Widget* w, void*) +{ +} + +/* +======================================================= +Callback routine to select window 3 +======================================================= +*/ +void cb_window_3(Fl_Widget* w, void*) +{ +} + +/* +======================================================= +Callback routine to select window 4 +======================================================= +*/ +void cb_window_4(Fl_Widget* w, void*) +{ +} + +/* +======================================================= +Callback routine to select window 5 +======================================================= +*/ +void cb_window_5(Fl_Widget* w, void*) +{ +} + +/* +======================================================= +Callback routine to select window 6 +======================================================= +*/ +void cb_window_6(Fl_Widget* w, void*) +{ +} + +/* +======================================================= +Callback routine to display more windows +======================================================= +*/ +void cb_window_more(Fl_Widget* w, void*) { } @@ -404,13 +644,20 @@ void cb_project_settings(Fl_Widget* w, void*) Menu Item Callbacks ======================================================= */ -void cb_Ide(Fl_Widget* w, void*) +void cb_Ide(Fl_Widget* widget, void*) { + int x, y, w, h; if (gpIde == NULL) { - // Create a new window for the disassembler - gpIde = new VT_Ide(800, 600 , "Integrated Development Environment - Work in progress!!!"); + // Get the initial window size from the user preferences + virtualt_prefs.get("IdeX", x, 40); + virtualt_prefs.get("IdeY", y, 40); + virtualt_prefs.get("IdeW", w, 800); + virtualt_prefs.get("IdeH", h, 600); + + // Create a new window for the IDE workspace + gpIde = new VT_Ide(x, y, w, h , "Integrated Development Environment - Work in progress!!!"); gpIde->show(); } @@ -426,11 +673,9 @@ void projtree_callback( Fl_Widget* w, void* ) switch( reason ) { case FLU_HILIGHTED: - printf( "%s hilighted\n", n->label() ); break; case FLU_UNHILIGHTED: - printf( "%s unhilighted\n", n->label() ); break; case FLU_SELECTED: @@ -452,71 +697,76 @@ void projtree_callback( Fl_Widget* w, void* ) t2->show(); } } - printf( "%s selected\n", n->label() );*/ +*/ break; case FLU_UNSELECTED: - printf( "%s unselected\n", n->label() ); break; case FLU_OPENED: - printf( "%s opened\n", n->label() ); break; case FLU_CLOSED: - printf( "%s closed\n", n->label() ); break; case FLU_DOUBLE_CLICK: - printf( "%s double-clicked\n", n->label() ); if (gpIde != 0) gpIde->OpenTreeFile(n); break; case FLU_WIDGET_CALLBACK: - printf( "%s widget callback\n", n->label() ); + printf("Flu WIDGET callback\n"); + break; break; case FLU_RIGHT_CLICK: - printf( "%s right click\n", n->label()); gpIde->RightClick(n); break; case FLU_MOVED_NODE: - printf( "%s moved\n", n->label() ); break; case FLU_NEW_NODE: - printf( "node '%s' added to the tree\n", n->label() ); break; + + case FLU_DELETE: + gpIde->DeleteItem(n); + break; } } -VT_Ide::VT_Ide(int w, int h, const char *title) -: Fl_Window(w, h, title) +/* +============================================================================== +VT_Ide constructor. This routine creates a new VT_Ide window +============================================================================== +*/ +VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) +: Fl_Window(x, y, w, h, title) { // Parent window has no box, only child regions box(FL_NO_BOX); callback(close_ide_cb); + // Get the window size from the preferences + // Create a menu for the new window. - Fl_Menu_Bar *m = new Fl_Menu_Bar(0, 0, 800, MENU_HEIGHT-2); + Fl_Menu_Bar *m = new Fl_Menu_Bar(0, 0, w, MENU_HEIGHT-2); m->menu(gIde_menuitems); // Create a tiled window to support Project, Edit, and debug regions - Fl_Tile* tile = new Fl_Tile(0,MENU_HEIGHT-2,800,600-MENU_HEIGHT); + Fl_Tile* tile = new Fl_Tile(0,MENU_HEIGHT-2,w,h-MENU_HEIGHT); /* ============================================ Create region for Project tree ============================================ */ - m_ProjWindow = new Fl_Window(2,MENU_HEIGHT-2,198,430,""); + m_ProjWindow = new Fl_Window(2,MENU_HEIGHT-2,198,h-170,""); m_ProjWindow->box(FL_DOWN_BOX); // Create Tree control - m_ProjTree = new Flu_Tree_Browser( 0, 0, 198, 430 ); + m_ProjTree = new Flu_Tree_Browser( 0, 0, 198, h-170 ); m_ProjTree->box( FL_DOWN_FRAME ); m_ProjTree->callback( projtree_callback ); m_ProjTree->selection_mode( FLU_SINGLE_SELECT ); @@ -535,7 +785,7 @@ VT_Ide::VT_Ide(int w, int h, const char *title) Create region and Child Window for editing files ================================================= */ - m_EditWindow = new Fl_Window(200,MENU_HEIGHT-2,600,430,"Edit"); + m_EditWindow = new Fl_Window(200,MENU_HEIGHT-2,w-200,h-170,"Edit"); m_EditWindow->box(FL_DOWN_BOX); m_EditWindow->color(FL_DARK2); m_EditWindow->end(); @@ -545,25 +795,25 @@ VT_Ide::VT_Ide(int w, int h, const char *title) Create region for Debug and output tabs ================================================= */ - m_TabWindow = new Fl_Window(0,MENU_HEIGHT-2+430,800,170-MENU_HEIGHT+2,"Tab"); + m_TabWindow = new Fl_Window(0,MENU_HEIGHT-2+h-170,w,170-MENU_HEIGHT+2,"Tab"); m_TabWindow->box(FL_DOWN_BOX); m_TabWindow->color(FL_LIGHT1); // Create a tab control - m_Tabs = new Fl_Tabs(0, 1, 800, 170-MENU_HEIGHT); + m_Tabs = new Fl_Tabs(0, 1, w, 170-MENU_HEIGHT); /* ==================== Create build tab ==================== */ - m_BuildTab = new Fl_Group(2, 0, 797, 170-MENU_HEIGHT-20, " Build "); + m_BuildTab = new Fl_Group(2, 0, w-3, 170-MENU_HEIGHT-20, " Build "); m_BuildTab->box(FL_DOWN_BOX); m_BuildTab->selection_color(FL_WHITE); m_BuildTab->color(FL_WHITE); // Create a Text Editor to show the disassembled text - m_BuildTextDisp = new Fl_Text_Display(2, 0, 797, 170-MENU_HEIGHT-20); + m_BuildTextDisp = new Fl_Text_Display(2, 0, w-3, 170-MENU_HEIGHT-20); m_BuildTextDisp->box(FL_DOWN_BOX); m_BuildTextDisp->selection_color(FL_WHITE); m_BuildTextDisp->color(FL_WHITE); @@ -582,7 +832,7 @@ VT_Ide::VT_Ide(int w, int h, const char *title) Create Debug tab ==================== */ - m_DebugTab = new Fl_Group(2, 0, 797, 170-MENU_HEIGHT-20, " Debug "); + m_DebugTab = new Fl_Group(2, 0, w-3, 170-MENU_HEIGHT-20, " Debug "); m_DebugTab->box(FL_DOWN_BOX); m_DebugTab->selection_color(FL_WHITE); m_DebugTab->color(FL_WHITE); @@ -593,25 +843,25 @@ VT_Ide::VT_Ide(int w, int h, const char *title) Create watch tab ==================== */ - m_WatchTab = new Fl_Group(2, 0, 797, 170-MENU_HEIGHT-20, " Watch "); + m_WatchTab = new Fl_Group(2, 0, w-3, 170-MENU_HEIGHT-20, " Watch "); m_WatchTab->box(FL_NO_BOX); m_WatchTab->selection_color(FL_WHITE); m_WatchTab->color(FL_WHITE); // Create tiled window for auto and watch variables - Fl_Tile* tile2 = new Fl_Tile(2, 0,800,170-MENU_HEIGHT-20); + Fl_Tile* tile2 = new Fl_Tile(2, 0,w,170-MENU_HEIGHT-20); - Fl_Box* box0 = new Fl_Box(2, 0,398,170-MENU_HEIGHT-20,"1"); + Fl_Box* box0 = new Fl_Box(2, 0,w/2-2,170-MENU_HEIGHT-20,"1"); box0->box(FL_DOWN_BOX); box0->color(FL_BACKGROUND_COLOR); box0->labelsize(36); box0->align(FL_ALIGN_CLIP); - Fl_Box* box1 = new Fl_Box(400, 0,400,170-MENU_HEIGHT-20,"2"); + Fl_Box* box1 = new Fl_Box(w/2, 0,w/2,170-MENU_HEIGHT-20,"2"); box1->box(FL_DOWN_BOX); box1->color(FL_BACKGROUND_COLOR); box1->labelsize(36); box1->align(FL_ALIGN_CLIP); - Fl_Box* r2 = new Fl_Box(0,0,800,170-MENU_HEIGHT-20); + Fl_Box* r2 = new Fl_Box(0,0,w,170-MENU_HEIGHT-20); tile2->resizable(r2); tile2->end(); m_WatchTab->resizable(tile2); @@ -623,7 +873,7 @@ VT_Ide::VT_Ide(int w, int h, const char *title) m_TabWindow->end(); // Set resize region - Fl_Box* r = new Fl_Box(150,MENU_HEIGHT-2,800-150,430); + Fl_Box* r = new Fl_Box(150,MENU_HEIGHT-2,w-150,h-170); tile->resizable(r); tile->end(); resizable(m); @@ -632,8 +882,15 @@ VT_Ide::VT_Ide(int w, int h, const char *title) // End the Window end(); + // Create a replace dialog + m_pReplaceDlg = new VT_ReplaceDlg(this); + m_pFindDlg = new VT_FindDlg(this); + // Initialize other variables m_ActivePrj = 0; + m_LastDir = "."; + m_OpenLocation = 0; + gRootpath = path; } /* @@ -650,6 +907,39 @@ void VT_Ide::show() m_BuildTextDisp->show_cursor(); } +/* +============================================================= +Override the default handle function to handle key sequences. +============================================================= +*/ +int VT_Ide::handle(int event) +{ + int key; + + switch (event) + { + case FL_KEYDOWN: + key = Fl::event_key(); + switch (key) + { + case FL_Escape: + return 1; + + default: + // Process all other keys using default processing + return Fl_Window::handle(event); + } + break; + + default: + // Handle all other events using default processing + return Fl_Window::handle(event); + break; + } + + return 0; +} + /* ============================================================= Override the default draw routine to display white regions @@ -667,6 +957,375 @@ void VT_Ide::draw(void) Fl_Window::draw(); } +/* +============================================================= +NewFile routine handles the File->New File menu item. +This routine creates an empty file with no filename. The +title of the window will be Text1, Text2, etc. +============================================================= +*/ +void VT_Ide::NewFile(void) +{ + int seq; // Next sequence number + MString title; // Tile of new file + int children, child; + Fl_Widget* pWidget; + + // Get number of child windows in the Ide + children = m_EditWindow->children(); + + for (seq = 1; ; seq++) + { + // Try next sequence number ot see if window already exists + title.Format("Text%d", seq); + + for (child = 0; child < children; child++) + { + pWidget = (Fl_Widget*) m_EditWindow->child(child); + if (strcmp((const char *) title, pWidget->label()) == 0) + break; + } + + // Check if title already exists + if (child == children) + { + // Okay, now create a new window + NewEditWindow(title, ""); + break; + } + } +} + +/* +============================================================= +SaveFile routine handles the File->Save File menu item. +This routine performs a save operation if the active edit +window has a filename associated with it, or a SaveAs +if it doesn't. +============================================================= +*/ +void VT_Ide::SaveFile(void) +{ + Fl_Multi_Edit_Window* mw; + int children; + MString rootpath; + MString title; + + // First get a pointer to the active (topmost) window + children = m_EditWindow->children(); + mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + if (mw == NULL) + return; + + // Validate this is truly a Multi_Edit_Window + if (strcmp(mw->GetClass()->m_ClassName, "Fl_Multi_Edit_Window") != 0) + return; + + // Determine root path + if (m_ActivePrj == NULL) + rootpath = path; + else + rootpath = m_ActivePrj->m_RootPath; + + mw->SaveFile(rootpath); + title = MakePathRelative(mw->Filename(), rootpath); + mw->Title(title); +} + +/* +============================================================= +SaveAs routine handles the File->Save As File menu item. +This routine determines the active edit window and calls +its SaveAs function. +============================================================= +*/ +void VT_Ide::SaveAs(void) +{ + Fl_Multi_Edit_Window* mw; + int children; + MString rootpath; + MString title; + + // First get a pointer to the active (topmost) window + children = m_EditWindow->children(); + mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + if (mw == NULL) + return; + + // Validate this is truly a Multi_Edit_Window + if (strcmp(mw->GetClass()->m_ClassName, "Fl_Multi_Edit_Window") != 0) + return; + + // Determine root path + if (m_ActivePrj == NULL) + rootpath = path; + else + rootpath = m_ActivePrj->m_RootPath; + + mw->SaveAs(rootpath); + title = MakePathRelative(mw->Filename(), rootpath); + mw->Title(title); +} + +/* +============================================================= +OpenFile routine handles the File->Save File menu item. +This routine opens an existing file and creates an edit +window for the newly opened file. +============================================================= +*/ +void VT_Ide::OpenFile(void) +{ + Fl_File_Chooser* fc; + int count; + MString filename; + MString title; + MString rootpath; + + if (m_ActivePrj == NULL) + rootpath = path; + else + rootpath = m_ActivePrj->m_RootPath; + + fc = new Fl_File_Chooser((const char *) path, "*.asm,*.a85", 1, "Open File"); + fc->preview(0); + fc->show(); + + // Wait for user to select a file or escape + while (fc->visible()) + Fl::wait(); + + // Determine if a file was selected or not + count = fc->count(); + if (count == 0) + { + delete fc; + return; + } + + // Get the filename from the file chooser + filename = fc->value(1); + delete fc; + title = MakePathRelative(filename, rootpath); + + // Determine if file is already open + int children = m_EditWindow->children(); + for (int c = 0; c < children; c++) + { + Fl_Widget* pWidget = (Fl_Widget*) m_EditWindow->child(c); + if (strcmp((const char *) title, pWidget->label()) == 0) + { + // File already open...bring file to foreground + return; + } + } + + // Create a new edit window for the file + NewEditWindow(title, filename); +} + +/* +============================================================= +Copy routine handles the Edit->Copy menu item. +The routine identifies the active window and calls the Fl +copy routine. +============================================================= +*/ +void VT_Ide::Copy(void) +{ + Fl_Multi_Edit_Window* mw; + int children; + + // First get a pointer to the active (topmost) window + children = m_EditWindow->children(); + mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + if (mw == NULL) + return; + + Fl_Text_Editor::kf_copy(0, mw->m_te); +} + +/* +============================================================= +Cut routine handles the Edit->Cut menu item. +The routine identifies the active window and calls the Fl +cut routine. +============================================================= +*/ +void VT_Ide::Cut(void) +{ + Fl_Multi_Edit_Window* mw; + int children; + + // First get a pointer to the active (topmost) window + children = m_EditWindow->children(); + mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + if (mw == NULL) + return; + + Fl_Text_Editor::kf_cut(0, mw->m_te); +} + +/* +============================================================= +Paste routine handles the Edit->Paste menu item. +The routine identifies the active window and calls the Fl +cut routine. +============================================================= +*/ +void VT_Ide::Paste(void) +{ + Fl_Multi_Edit_Window* mw; + int children; + + // First get a pointer to the active (topmost) window + children = m_EditWindow->children(); + mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + if (mw == NULL) + return; + + Fl_Text_Editor::kf_paste(0, mw->m_te); +} + +/* +============================================================= +Find routine handles the Edit->Find menu item. +The routine identifies the active window and calls the Fl +cut routine. +============================================================= +*/ +void VT_Ide::Find(void) +{ + Fl_Multi_Edit_Window* mw; + int children; + + // First get a pointer to the active (topmost) window + children = m_EditWindow->children(); + mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + if (mw == NULL) + return; + + m_pFindDlg->m_pFindDlg->show(); + m_pFindDlg->m_pFind->take_focus(); +} + +/* +============================================================= +FindAgain routine handles the Edit->Find Next menu item. +The routine identifies the active window and calls the Fl +cut routine. +============================================================= +*/ +void VT_Ide::FindNext(void) +{ + Fl_Multi_Edit_Window* mw; + int children; + const char * pFind; + + // First get a pointer to the active (topmost) window + children = m_EditWindow->children(); + mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + if (mw == NULL) + return; + + // Ensure there is a search string + pFind = m_pFindDlg->m_pFind->value(); + if (pFind[0] == '\0') + { + m_pFindDlg->m_pFindDlg->show(); + m_pFindDlg->m_pFind->take_focus(); + return; + } + + // Find the text + + // Hide the dialog box + m_pFindDlg->m_pFindDlg->hide(); +} + +/* +============================================================= +Replace routine handles the Edit->Replace Next menu item. +The routine identifies the active window and calls the Fl +cut routine. +============================================================= +*/ +void VT_Ide::Replace(void) +{ + m_pReplaceDlg->m_pReplaceDlg->show(); + m_pReplaceDlg->m_pFind->take_focus(); +} + +/* +============================================================= +ReplaceAll routine is called when the RelaceAll button is +pressed in the ReplaceDlg. +============================================================= +*/ +void VT_Ide::ReplaceAll(void) +{ + Fl_Multi_Edit_Window* mw; + int children; + const char * pFind; + const char * pReplace; + + // First get a pointer to the active (topmost) window + children = m_EditWindow->children(); + mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + if (mw == NULL) + return; + + // Ensure there is a search string + pFind = (const char *) m_pReplaceDlg->m_pFind->value(); + pReplace = (const char *) m_pReplaceDlg->m_pWith->value(); + if (pFind[0] == '\0') + { + m_pReplaceDlg->m_pReplaceDlg->show(); + m_pReplaceDlg->m_pFind->take_focus(); + return; + } + + m_pReplaceDlg->m_pReplaceDlg->hide(); + + // Do the replacement + if (!mw->ReplaceAll(pFind, pReplace)) + fl_alert("No occurrences of \'%s\' found!", pFind); +} + +/* +============================================================= +ReplaceNext routine is called when the RelaceNext button is +pressed in the ReplaceDlg. +============================================================= +*/ +void VT_Ide::ReplaceNext(void) +{ + Fl_Multi_Edit_Window* mw; + int children; + const char * pFind; + const char * pReplace; + + // First get a pointer to the active (topmost) window + children = m_EditWindow->children(); + mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + if (mw == NULL) + return; + + // Ensure there is a search string + pFind = (const char *) m_pReplaceDlg->m_pFind->value(); + pReplace = (const char *) m_pReplaceDlg->m_pWith->value(); + if (pFind[0] == '\0') + { + m_pReplaceDlg->m_pReplaceDlg->show(); + m_pReplaceDlg->m_pFind->take_focus(); + return; + } + + // Do the replacement + if (!mw->ReplaceNext(pFind, pReplace)) + fl_alert("No occurrences of \'%s\' found!", pFind); +} + /* ============================================================= NewProject routine handles the File->New Project menu item. @@ -677,6 +1336,23 @@ control. void VT_Ide::NewProject(void) { VT_IdeGroup* pGroup; + VT_NewProject* pProj; + const char * pRootDir; + char fullPath[512]; + + // Get project parameters + pProj = new VT_NewProject; + pProj->m_Dir = m_LastDir; + pProj->show(); + + while (pProj->visible()) + Fl::wait(); + + if (pProj->m_makeProj == FALSE) + { + delete pProj; + return; + } // Check if there is an active project if (m_ActivePrj != 0) @@ -687,7 +1363,10 @@ void VT_Ide::NewProject(void) int c = fl_choice("Save project changes?", "Cancel", "Yes", "No"); if (c == 0) + { + delete pProj; return; + } if (c == 1) SaveProject(); } @@ -698,35 +1377,180 @@ void VT_Ide::NewProject(void) } // Create new project - m_ActivePrj = new VT_IdeProject; - m_ActivePrj->m_Name = "Unknown"; + m_ActivePrj = new VT_Project; + m_ActivePrj->m_Name = pProj->getProjName(); pGroup = new VT_IdeGroup; pGroup->m_Name = "Source Files"; + pGroup->m_Filespec = "*.asm;*.a85"; m_ActivePrj->m_Groups.Add(pGroup); pGroup = new VT_IdeGroup; pGroup->m_Name = "Header Files"; + pGroup->m_Filespec = "*.h;*.inc"; m_ActivePrj->m_Groups.Add(pGroup); pGroup = new VT_IdeGroup; pGroup->m_Name = "Object Files"; + pGroup->m_Filespec = "*.obj"; m_ActivePrj->m_Groups.Add(pGroup); + // Get root directory + pRootDir = pProj->getLocation(); + if (pRootDir[0] == '.') + { + strcpy(fullPath, path); + strcat(fullPath, "/"); + strcat(fullPath, &pRootDir[2]); + m_ActivePrj->m_RootPath = fullPath; + } + else + { + m_ActivePrj->m_RootPath = pRootDir; + } + + + // Check if path ends with '/' + if (m_ActivePrj->m_RootPath[m_ActivePrj->m_RootPath.GetLength()-1] != '/') + m_ActivePrj->m_RootPath = m_ActivePrj->m_RootPath + "/"; + + m_ActivePrj->m_RootPath = m_ActivePrj->m_RootPath + m_ActivePrj->m_Name; + + // Try to create the project directory +#ifdef _WIN32 + if (_mkdir((const char *) m_ActivePrj->m_RootPath) != 0) +#else + if (mkdir((const char *) m_ActivePrj->m_RootPath, 0755) != 0) +#endif + { + fl_alert("Unable to create directory %s", (const char *) m_ActivePrj->m_RootPath); + delete pProj; + return; + } + + // Save the project type + m_ActivePrj->m_ProjectType = pProj->getProjType(); + if (m_ActivePrj->m_ProjectType == 0) + m_ActivePrj->m_AutoLoad = 1; + else + m_ActivePrj->m_AutoLoad = 0; + + // Save the target model + m_ActivePrj->m_TargetModel = pProj->getTargetModel(); + gRootpath = m_ActivePrj->m_RootPath; + + // Save the new project + SaveProject(); + BuildTreeControl(); + m_ProjTree->open_on_select(TRUE); m_ProjTree->redraw(); m_ProjTree->show(); + + delete pProj; +} + +/* +============================================================= +The ProjectDirty routine returns TRUE if there is an active +project and the project is dirty. +============================================================= +*/ +int VT_Ide::ProjectDirty(void) +{ + if (m_ActivePrj == NULL) + return 0; + + return m_ActivePrj->m_Dirty; +} + +/* +============================================================= +The ProjectName routine returns the name of he active project +or "" if no active project. +============================================================= +*/ +MString VT_Ide::ProjectName(void) +{ + if (m_ActivePrj == NULL) + return ""; + + return m_ActivePrj->m_Name; } -/* -============================================================= -The SaveProject routine saves the active project structure to -a .prj file. -============================================================= -*/ -void VT_Ide::SaveProject(void) -{ +/* +============================================================= +The SaveProject routine saves the active project structure to +a .prj file. +============================================================= +*/ +void VT_Ide::SaveProject(void) +{ + FILE* fd; + char fullPath[512]; + char model[10]; + int count, c, objs, x; + VT_IdeGroup* pGroup; + VT_IdeSource* pObj; + + // Check if m_ActiveProj is valid + if (m_ActivePrj == NULL) + return; + + // Create the path + sprintf(fullPath, "%s/%s.prj", (const char *) m_ActivePrj->m_RootPath, + (const char *) m_ActivePrj->m_Name); + + // Try to open the file for write mode + if ((fd = fopen(fullPath, "w+")) == NULL) + { + // Error opening file!! + fl_alert("Error opening projec file for write mode!"); + return; + } + + // Write header information + fprintf(fd, "NAME=%s\n", (const char *) m_ActivePrj->m_Name); + fprintf(fd, "INCLPATH=%s\n", (const char *) m_ActivePrj->m_IncludePath); + fprintf(fd, "DEFINES=%s\n", (const char *) m_ActivePrj->m_Defines); + fprintf(fd, "LINKPATH=%s\n", (const char *) m_ActivePrj->m_LinkPath); + fprintf(fd, "LINKLIBS=%s\n", (const char *) m_ActivePrj->m_LinkLibs); + fprintf(fd, "CSEG=%s\n", (const char *) m_ActivePrj->m_CodeAddr); + fprintf(fd, "DSEG=%s\n", (const char *) m_ActivePrj->m_DataAddr); + fprintf(fd, "ASMOPT=%s\n", (const char *) m_ActivePrj->m_AsmOptions); + fprintf(fd, "LINKOPT=%s\n", (const char *) m_ActivePrj->m_LinkOptions); + fprintf(fd, "TYPE=%s\n", gProjectTypes[m_ActivePrj->m_ProjectType]); + get_model_string(model, m_ActivePrj->m_TargetModel); + fprintf(fd, "TARGET=%s\n", model); + fprintf(fd, "AUTOLOAD=%d\n", m_ActivePrj->m_AutoLoad); + fprintf(fd, "UPDATEHIMEM=%d\n", m_ActivePrj->m_UpdateHIMEM); + fprintf(fd, "\n"); + + // Write group information to the file + count = m_ActivePrj->m_Groups.GetSize(); + for (c = 0; c < count; c++) + { + pGroup = (VT_IdeGroup*) m_ActivePrj->m_Groups[c]; + fprintf(fd, "GROUP=%s\n", (const char *) pGroup->m_Name); + fprintf(fd, "FILESPEC=%s\n", (const char *) pGroup->m_Filespec); + + // Write objects + objs = pGroup->m_Objects.GetSize(); + for (x = 0; x < objs; x++) + { + pObj = (VT_IdeSource*) pGroup->m_Objects[x]; + fprintf(fd, "SOURCE=%s\n", (const char *) pObj->m_Name); + } + + // End the group + fprintf(fd, "ENDGROUP\n\n"); + } + + m_ActivePrj->m_Dirty = 0; + + // Close the file + fclose(fd); } /* @@ -792,6 +1616,7 @@ void VT_Ide::OpenProject(void) { // Report parse error } + gRootpath = m_ActivePrj->m_RootPath; } /* @@ -810,13 +1635,13 @@ void VT_Ide::BuildTreeControl(void) VTObject* pObj; MString fmt, addStr; - // Insure we have a project structure + // Ensure we have a project structure if (m_ActivePrj == 0) return; // set the default leaf icon to be a blue dot m_ProjTree->leaf_icon( &gTextDoc ); - m_ProjTree->insertion_mode( FLU_INSERT_BACK ); + m_ProjTree->insertion_mode( FLU_INSERT_SORTED ); // use the default branch icons (yellow folder) m_ProjTree->branch_icons( NULL, NULL ); @@ -857,7 +1682,7 @@ void VT_Ide::BuildTreeControl(void) addStr += "%s"; - // Loop through all objects an add to tree + // Loop through all objects and add to tree int sublen = pGroup->m_Objects.GetSize(); for (int x = 0; x < sublen; x++) { @@ -924,7 +1749,7 @@ void VT_Ide::AddGroupToTree(VTObject *pObj, const char *fmt) addStr += "%s"; - // Loop through all objects an add to tree + // Loop through all objects and add to tree len = pGroup->m_Objects.GetSize(); for (c = 0; c < len; c++) { @@ -967,7 +1792,7 @@ int VT_Ide::ParsePrjFile(const char *name) FILE* fd; char line[512]; char *param, *value; - MString sParam; + MString sParam, temp; const char * sPtr; VT_IdeGroup* pGroup = 0; VT_IdeSource* pSource = 0; @@ -981,23 +1806,37 @@ int VT_Ide::ParsePrjFile(const char *name) if (fd == 0) return 0; - // Insure active project not null + // Ensure active project not null if (m_ActivePrj == 0) - m_ActivePrj = new VT_IdeProject; + m_ActivePrj = new VT_Project; // Loop through all lines in file while (fgets(line, 512, fd) != 0) { // Skip comments and blank lines - if ((line[0] == '#') || (line[0] == '\n')) + if ((line[0] == '#') || (line[0] == '\n') || (line[0] == '\x0d')) continue; - // Parse the line - param = strtok(line, "=\n"); - value = strtok(NULL, "=\n"); + // Parse the line - find the first '=' + for (c = 0; (line[c] != 0) && (line[c] != '=') && (line[c] != '\n') && (line[c] != 13) ; c++) + ; + param = line; + if (line[c] == '=') + { + line[c] = 0; + value = &line[c+1]; + for (c++; (line[c] != 0) && (line[c] != '\n') && (line[c] != 13); c++) + ; + line[c] = 0; + } + else + { + line[c] = 0; + value = ""; + } // Check for error in line - if (param == 0) + if (value == 0) { // Report error continue; @@ -1008,7 +1847,7 @@ int VT_Ide::ParsePrjFile(const char *name) sPtr = (const char *) sParam; if (strcmp(sPtr, "SOURCE") == 0) { - // Insure there is an active group + // Ensure there is an active group if (pGroup != 0) { pSource = new VT_IdeSource; @@ -1027,6 +1866,7 @@ int VT_Ide::ParsePrjFile(const char *name) break; } pGroup->m_Objects.InsertAt(c, pSource); + pSource->m_ParentGroup = pGroup; pSource = 0; } } @@ -1093,16 +1933,56 @@ int VT_Ide::ParsePrjFile(const char *name) if (value != 0) m_ActivePrj->m_Name = value; } + else if (strcmp(sPtr, "TARGET") == 0) + { + if (value != 0) + m_ActivePrj->m_TargetModel = get_model_from_string(value); + } + else if (strcmp(sPtr, "AUTOLOAD") == 0) + { + if (value != 0) + m_ActivePrj->m_AutoLoad = atoi(value); + } + else if (strcmp(sPtr, "UPDATEHIMEM") == 0) + { + if (value != 0) + m_ActivePrj->m_UpdateHIMEM = atoi(value); + } + else if (strcmp(sPtr, "TYPE") == 0) + { + if (value != 0) + { + // Search for type in global array + for (c = 0; strlen(gProjectTypes[c]) != 0; c++) + { + if (strcmp(gProjectTypes[c], value) == 0) + { + m_ActivePrj->m_ProjectType = c; + break; + } + } + } + } else if (strcmp(sPtr, "INCLPATH") == 0) { if (value != 0) m_ActivePrj->m_IncludePath = value; } + else if (strcmp(sPtr, "DEFINES") == 0) + { + if (value != 0) + m_ActivePrj->m_Defines = value; + } else if (strcmp(sPtr, "LINKPATH") == 0) { if (value != 0) m_ActivePrj->m_LinkPath = value; } + else if (strcmp(sPtr, "LINKLIBS") == 0) + { + if (value != 0) + m_ActivePrj->m_LinkLibs = value; + } else if (strcmp(sPtr, "ASMOPT") == 0) { if (value != 0) @@ -1113,26 +1993,45 @@ int VT_Ide::ParsePrjFile(const char *name) if (value != 0) m_ActivePrj->m_LinkOptions = value; } + else if (strcmp(sPtr, "DSEG") == 0) + { + if (value != 0) + m_ActivePrj->m_DataAddr = value; + } + else if (strcmp(sPtr, "CSEG") == 0) + { + if (value != 0) + m_ActivePrj->m_CodeAddr = value; + } } + // Set the RootPath + temp = name; + // Get just the path + index = temp.ReverseFind("/"); + if (index == 0) + m_ActivePrj->m_RootPath = path; + else + m_ActivePrj->m_RootPath = temp.Left(index); + // Close the file fclose(fd); return 1; } -VT_IdeProject::~VT_IdeProject() -{ - VTObject* pObj; +VT_Project::~VT_Project() +{ + VTObject* pObj; - for (int c =0; c < m_Groups.GetSize(); c++) - { - pObj = m_Groups[c]; - if (strcmp(pObj->GetClass()->m_ClassName, "VT_IdeGroup") == 0) - delete (VT_IdeGroup *) pObj; - else - delete (VT_IdeSource *) pObj; - } - m_Groups.RemoveAll(); + for (int c =0; c < m_Groups.GetSize(); c++) + { + pObj = m_Groups[c]; + if (strcmp(pObj->GetClass()->m_ClassName, "VT_IdeGroup") == 0) + delete (VT_IdeGroup *) pObj; + else + delete (VT_IdeSource *) pObj; + } + m_Groups.RemoveAll(); } VT_IdeGroup::~VT_IdeGroup() @@ -1151,6 +2050,92 @@ VT_IdeGroup::~VT_IdeGroup() m_Objects.RemoveAll(); } +/* +============================================================= +The delete routine is called when the user presses delete on +a specific item in the tree. +============================================================= +*/ +void VT_Ide::DeleteItem(Flu_Tree_Browser::Node* n) +{ + int ans; + MString question; + + if (!n->is_root()) + { + // Get user data from the node + VTObject* pObj = (VTObject *) n->user_data(); + if (pObj == NULL) + return; + + // Determine if node is a group or a leaf (source) + if (strcmp(pObj->GetClass()->m_ClassName, "VT_IdeGroup") == 0) + { + // For groups, ask before deleting the entire group + VT_IdeGroup* pGroup = (VT_IdeGroup*) pObj; + question.Format("Delete group %s and all its members?", (const char *) pGroup->m_Name); + ans = fl_choice((const char *) question, "No", "Yes", NULL); + if (ans == 1) + { + // First delete all subitems from the group + int count = pGroup->m_Objects.GetSize(); + while (count != 0) + { + VT_IdeSource* pSrc = (VT_IdeSource*) pGroup->m_Objects[0]; + count--; + + // Delete the tree item + pGroup->m_Objects.RemoveAt(0, 1); + m_ProjTree->remove(pSrc->m_Node); + + // Delete the object + delete pSrc; + } + + // Now delete the group - tree node first + m_ProjTree->remove(pGroup->m_Node); + + // Now find the group entry in the active project + count = m_ActivePrj->m_Groups.GetSize(); + for (int c = 0; c < count; c++) + { + if (pGroup == (VT_IdeGroup*) m_ActivePrj->m_Groups[c]) + { + m_ActivePrj->m_Groups.RemoveAt(c, 1); + break; + } + } + delete pGroup; + + // Mark the project dirty + m_ActivePrj->m_Dirty = 1; + } + } + else + { + VT_IdeSource* pSrc = (VT_IdeSource*) pObj; + + // Delete the source from the tree + m_ProjTree->remove(pSrc->m_Node); + + // Delete the source from the parent Group + int count = pSrc->m_ParentGroup->m_Objects.GetSize(); + for (int c = 0; c < count; c++) + { + if (pSrc == (VT_IdeSource*) pSrc->m_ParentGroup->m_Objects[c]) + { + pSrc->m_ParentGroup->m_Objects.RemoveAt(c, 1); + break; + } + } + delete pSrc; + + // Mark the project dirty + m_ActivePrj->m_Dirty = 1; + } + } +} + /* ============================================================= The RightClick routine is called when the user performs a @@ -1166,9 +2151,15 @@ void VT_Ide::RightClick(Flu_Tree_Browser::Node* n) } else { + // Get user data from the node VTObject* pObj = (VTObject *) n->user_data(); + if (pObj == NULL) + return; + + // Determine if node is a group or a leaf (source) if (strcmp(pObj->GetClass()->m_ClassName, "VT_IdeGroup") == 0) { + // Select group popup menu gGroupMenu[0].user_data_ = n; gGroupMenu[1].user_data_ = n; gGroupMenu[2].user_data_ = n; @@ -1176,16 +2167,26 @@ void VT_Ide::RightClick(Flu_Tree_Browser::Node* n) } else { + // Select source popup menu gSourceMenu[0].user_data_ = n; gSourceMenu[1].user_data_ = n; gSourceMenu[2].user_data_ = n; gPopup->menu(gSourceMenu); } } + // Add label to popup menu & display gPopup->label(n->label()); gPopup->popup(); } +/* +============================================================= +The NewFolder routine is called when the user selects Add New +Folder from the popup menu. This routine asks the user for +the name of the new folder and adds it to both the active +project and to the tree control. +============================================================= +*/ void VT_Ide::NewFolder(Flu_Tree_Browser::Node* n) { MString name, filespec; @@ -1194,9 +2195,15 @@ void VT_Ide::NewFolder(Flu_Tree_Browser::Node* n) int len, c, root; Flu_Tree_Browser::Node* i; Flu_Tree_Browser::Node* newNode; + const char* pName; // Get Folder name - name = "ide"; + pName = fl_input("Please enter Folder Name", ""); + if (pName == NULL) + return; + if (strlen(pName) == 0) + return; + name = pName; filespec = ""; // Create new VT_IdeGroup object for this folder @@ -1239,6 +2246,8 @@ void VT_Ide::NewFolder(Flu_Tree_Browser::Node* n) { // Seach group object for insertion point for folder pGroup = (VT_IdeGroup *) n->user_data(); + if (pGroup == NULL) + return; len = pGroup->m_Objects.GetSize(); for (c = 0; c < len; c++) { @@ -1286,8 +2295,107 @@ void VT_Ide::NewFolder(Flu_Tree_Browser::Node* n) m_ActivePrj->m_Dirty = 1; } +/* +============================================================= +The AddFilesToFolder routine is called when the user selects +Add Files to Project from the popup menu. The routine asks +the user which files should be added then adds them to the +requested folder. +============================================================= +*/ void VT_Ide::AddFilesToFolder(Flu_Tree_Browser::Node* n) { + Fl_File_Chooser *fc; /* File Chooser */ + int count, c; + int len, index, x; + MString filename, relPath; + MString temp, path; + MStringArray errFiles; + VT_IdeGroup* pGroup = 0; + VT_IdeSource* pSource = 0; + VTObject* pIns; + + /* Create a new File Chooser object */ + fc = new Fl_File_Chooser((const char *) m_LastDir, "Source Files (*.{asm,inc,h})", + Fl_File_Chooser::MULTI, "Add Files to Project"); + fc->preview(0); + fc->show(); + + /* Wait until the files have been choosen or they hit cancel */ + while (fc->visible()) + Fl::wait(); + + /* Get count of files selected */ + count = fc->count(); + + /* Check if cancel was pressed & return if it was */ + if (count == 0) + { + delete fc; + return; + } + + // Get the Group item associated with this tree node + pGroup = (VT_IdeGroup*) n->user_data(); + + // Get the current directory and save for future use + m_LastDir = fc->directory(); + + // Calculate relative path for files + + /* Loop through all files selected and try to add to project */ + for (c = 0; c < count; c++) + { + // Get next filename from the FileChooser + filename = fc->value(c+1); + + // Get just the filename + index = filename.ReverseFind('/'); + if (index == 0) + temp = filename; + else + temp = filename.Right(filename.GetLength() - index - 1); + + // Check if entry aleady exists + if (n->find((const char *) temp) != NULL) + { + // Add file to list of "error" files + errFiles.Add(temp); + continue; + } + + // Create an IdeSource object for this entry + pSource = new VT_IdeSource; + pSource->m_Name = m_LastDir + '/' + temp; + + // Insert source alphabetically after groups + len = pGroup->m_Objects.GetSize(); + for (x = 0; x < len; x++) + { + pIns = pGroup->m_Objects[x]; + // Skip groups so they appear at top + if (strcmp(pIns->GetClass()->m_ClassName, "VT_IdeGroup") == 0) + continue; + + if (pSource->m_Name < ((VT_IdeSource *) pIns)->m_Name) + break; + } + pGroup->m_Objects.InsertAt(x, pSource); + pSource->m_ParentGroup = pGroup; + + // Insert item in tree + pSource->m_Node = n->add((const char *) temp); + if (pSource->m_Node == NULL) + printf("Error inserting node!\n"); + else + pSource->m_Node->user_data(pSource); + + m_ActivePrj->m_Dirty = 1; + } + + /* Delete the file chooser */ + delete fc; + return; } void VT_Ide::FolderProperties(Flu_Tree_Browser::Node* n) @@ -1298,29 +2406,66 @@ void VT_Ide::OpenTreeFile(Flu_Tree_Browser::Node* n) { VT_IdeSource* pSource; MString file; + MString title; + int children, c; + int count = 6; + Fl_Widget* pWidget; pSource = (VT_IdeSource *) n->user_data(); + if (pSource == NULL) + return; + + // Process the open request if (pSource->m_Name.Left(2) == "./") file = pSource->m_Name.Right(pSource->m_Name.GetLength()-2); else file = pSource->m_Name; + title = MakePathRelative(file, m_ActivePrj->m_RootPath); - int x = 10; - int y = 10; - const char *pStr = file; - if (file == "main.asm") - x = 200; - Fl_Multi_Window* mw = new Fl_Multi_Window(x, 10, 400, 300, (const char *)file); - Fl_Text_Editor* te = new Fl_Text_Editor(0, 0, mw->ClientArea()->w(), - mw->ClientArea()->h(), file); - Fl_Text_Buffer* tb = new Fl_Text_Buffer(); - te->buffer(tb); + // Check if the file is already open + children = m_EditWindow->children(); + for (c = 0; c < children; c++) + { + pWidget = (Fl_Widget*) m_EditWindow->child(c); + if (strcmp((const char *) title, pWidget->label()) == 0) + { + // File already open...bring file to foreground + return; + } + } - // Show the Disassembling text to indicate activity - tb->loadfile(file); - te->textfont(FL_COURIER); - te->end(); - mw->ClientArea()->resizable(te); + file = MakePathAbsolute(file, m_ActivePrj->m_RootPath); + NewEditWindow(title, file); +} + +/* +=============================================================================== +NewEditWindow: This routine creates a new edit window with the specified + title. If the File parameter is not empty, then the edit + window is loaded from the file. +=============================================================================== +*/ +void VT_Ide::NewEditWindow(const MString& title, const MString& file) +{ + int x = 1; + int y = 1; + int w = 400; + int h = 300; + int count = 6; + + /* Calculate location of next window */ + if (m_EditWindow->h() < 550) + count = 5; + h = m_EditWindow->h() - 28 * count; + w = m_EditWindow->w() - 28 * count; + x = y = m_OpenLocation++ * 28; + if (m_OpenLocation >= count) + m_OpenLocation = 0; + + /* Create window */ + Fl_Multi_Edit_Window* mw = new Fl_Multi_Edit_Window(x, y, w, h, (const char *) title); + if (file != "") + mw->OpenFile((const char *) file); mw->end(); // Insert new window in EditWindow @@ -1333,6 +2478,7 @@ void VT_Ide::OpenTreeFile(Flu_Tree_Browser::Node* n) prev->redraw(); // Call show again to bring window to front mw->show(); + mw->take_focus(); } void VT_Ide::AssembleTreeFile(Flu_Tree_Browser::Node* n) @@ -1343,3 +2489,322 @@ void VT_Ide::TreeFileProperties(Flu_Tree_Browser::Node* n) { } +/* +============================================================================= +BuildProjet: This routine is the reason for all this mess! Try to assemble + each file in the project and then link if no errors. +============================================================================= +*/ +void VT_Ide::BuildProject(void) +{ + int groups, sources; + int c, x, err; + int index; + VT_IdeGroup* pGroup; + VT_IdeSource* pSource; + int errorCount, totalErrors=0; + MString text, temp; + VTAssembler assembler; + int assemblyNeeded; + MStringArray errors; + MString filename; + + // Be sure we have an active project + if (m_ActivePrj == NULL) + return; + + // Clear the Build tab at the bottom + m_BuildTextBuf ->remove(0, m_BuildTextBuf->length()); + + // Configure the assembler + assembler.SetRootPath(m_ActivePrj->m_RootPath); + assembler.SetAsmOptions(m_ActivePrj->m_AsmOptions); + assembler.SetIncludeDirs(m_ActivePrj->m_IncludePath); + assembler.SetDefines(m_ActivePrj->m_Defines); + + m_BuildTextBuf->append("Assembling...\n"); + + // Loop through each group and look for files to assemble + errorCount = 0; + groups = m_ActivePrj->m_Groups.GetSize(); + for (c = 0; c < groups; c++) + { + // Get group + pGroup = (VT_IdeGroup*) m_ActivePrj->m_Groups[c]; + + // Loop through each source in group + sources = pGroup->m_Objects.GetSize(); + for (x = 0; x < sources; x++) + { + // Get next source from group + pSource = (VT_IdeSource*) pGroup->m_Objects[x]; + + // Get extension of this source + + // Test if source is .asm or .a85 + assemblyNeeded = FALSE; + temp = pSource->m_Name.Right(4); + temp.MakeLower(); + if ((temp == ".asm") || (temp == ".a85")) + { + // Check source dependencies + + assemblyNeeded = TRUE; + + // Delete old .obj file + } + + // Try to assemble the file + if (assemblyNeeded) + { + // Display build indication + index = pSource->m_Name.ReverseFind('/'); + temp = pSource->m_Name.Right(pSource->m_Name.GetLength()-index-1); + text.Format("%s\n", (const char *) temp); + m_BuildTextBuf->append((const char *) text); + + // Try to assemble this file + filename = MakePathAbsolute(pSource->m_Name, m_ActivePrj->m_RootPath); + assembler.Parse(filename); + + // Check if any errors occurred & report them + errors = assembler.GetErrors(); + errorCount = errors.GetSize(); + totalErrors += errorCount; + for (err = 0; err < errorCount; err++) + { + m_BuildTextBuf->append((const char *) errors[err]); + m_BuildTextBuf->append("\n"); + } + } + } + } + + // Check if there were any erros during assembly and if not, + // invoke the linker + if (totalErrors != 0) + { + temp.Format("\n%d Errors during assembly - skipping link step\n", totalErrors); + m_BuildTextBuf->append((const char *) temp); + } + else + { + m_BuildTextBuf->append("Linking...\n"); + } + +} + +void VT_Ide::CleanProject(void) +{ +} + +void VT_Ide::ShowProjectSettings(void) +{ + VT_ProjectSettings* pProj; + + // Ensure there is an active project + if (m_ActivePrj == NULL) + return; + + // Get project parameters + pProj = new VT_ProjectSettings(m_ActivePrj); + pProj->show(); + + while (pProj->visible()) + Fl::wait(); + +} + +/* +=============================================================================== +This routine returns a string which is the relative form of the given path +realtive to the relTo path. The routine detects both relativeness in bot +directions and uses '..' as necessary in the returned string. +=============================================================================== +*/ +MString VT_Ide::MakePathRelative(const MString& path, const MString& relTo) +{ + int c; + int lenPath, lenRel; // Length of each string + int lastRelBranch; // Index of last '/' in relTo + int lastMatch; + MString temp; + int slashIndex = 0; + + // Determine if path is already relative + if ((path.Left(2) == "./") || (path.Left(3) == "../")) + return path; + if (path.Find("/", 0) == -1) + return path; + if (path[1] == ':') + slashIndex = 2; + if (path[slashIndex] != '/') + return path; + + // Find the location of the last '/' in each string + lastRelBranch = relTo.ReverseFind('/'); + lenPath = path.GetLength(); + lenRel = relTo.GetLength(); + + // Start at beginning of string and compare each path segment + // to find the first location where they don't match + c = lastMatch = 0; + while ((c != lenPath) && (c != lenRel)) + { + // Test + if (path[c] != relTo[c]) + break; + if (path[c] == '/') + lastMatch = c; + c++; + } + // Determine if the last branch is identical. This must be done because + // the loop could have exited simply becuase we came to the end of one of + // the 2 strings: + if (((c == lenPath) && (relTo[c] == '/')) || ((path[c] == '/') && (c == lenRel))) + lastMatch = c; + + // Okay, now we know where the path's are different, scan through the + // relTo path to determine how many '../' entries we need, if any + c = lastMatch; + while (c != lenRel) + { + if (c == lastRelBranch) + { + temp += "../"; // Add another 'prev dir' indicator + break; // At last branch...exit + } + // Check for a directory specifier + if (relTo[c] == '/') + { + temp += "../"; + } + c++; + } + + // Now append the remainder of the path from the lastMatch point + c = lastMatch; + if (path[c] == '/') + c++; + while (c < lenPath) + { + temp += path[c++]; + } + + return temp; +} + +/* +=============================================================================== +This routine returns a string which is the absolute form of the given path +realtive to the relTo path. If the path is already an absolute path, it is +simply returned unaltered. The routine resolves ./ and ../ references. +=============================================================================== +*/ +MString VT_Ide::MakePathAbsolute(const MString& path, const MString& relTo) +{ + int index; + MString temp, newRel; + int slashIndex = 0; + + // Determine if path is already absolute + if (path[1] == ':') + slashIndex = 2; + if (path[slashIndex] == '/') + return path; + + // If path starts with ./ then simply remove it + if (path.Left(2) == "./") + temp = path.Right(path.GetLength()-2); + else + temp = path; + + newRel = relTo; + while (temp.Left(3) == "../") + { + index = newRel.ReverseFind('/'); + if (index != -1) + newRel = newRel.Left(index - 1); + } + + temp = newRel + '/' + temp; + return temp; +} + +void cb_replace_all(Fl_Widget* w, void* v) +{ + VT_ReplaceDlg* pDlg = (VT_ReplaceDlg*) v; + + pDlg->m_pParent->ReplaceAll(); +} + +void cb_replace_next(Fl_Widget* w, void* v) +{ + VT_ReplaceDlg* pDlg = (VT_ReplaceDlg*) v; + + pDlg->m_pParent->ReplaceNext(); +} + +void cb_replace_cancel(Fl_Widget* w, void* v) +{ + VT_ReplaceDlg* pDlg = (VT_ReplaceDlg*) v; + + pDlg->m_pReplaceDlg->hide(); +} + +/* +================================================================================ +VT_ReplaceDlg routines below. +================================================================================ +*/ +VT_ReplaceDlg::VT_ReplaceDlg(class VT_Ide* pParent) +{ + m_pReplaceDlg = new Fl_Window(300, 105, "Replace"); + m_pFind = new Fl_Input(80, 10, 210, 25, "Find:"); + m_pFind->align(FL_ALIGN_LEFT); + + m_pWith = new Fl_Input(80, 40, 210, 25, "Replace:"); + m_pWith->align(FL_ALIGN_LEFT); + + m_pAll = new Fl_Button(10, 70, 90, 25, "Replace All"); + m_pAll->callback(cb_replace_all, this); + + m_pNext = new Fl_Button(105, 70, 120, 25, "Replace Next"); + m_pNext->callback(cb_replace_next, this); + + m_pCancel = new Fl_Button(230, 70, 60, 25, "Cancel"); + m_pCancel->callback(cb_replace_cancel, this); + + m_pReplaceDlg->end(); + m_pReplaceDlg->set_non_modal(); + + m_pParent = pParent; +} + +/* +================================================================================ +VT_FindDlg routines below. +================================================================================ +*/ +VT_FindDlg::VT_FindDlg(class VT_Ide* pParent) +{ + m_pFindDlg = new Fl_Window(300, 105, "Find"); + m_pFind = new Fl_Input(40, 10, 250, 25, "Find:"); + m_pFind->align(FL_ALIGN_LEFT); + + m_pForward = new Fl_Round_Button(80, 40, 90, 25, "Forward"); + m_pForward->value(1); + m_pBackward = new Fl_Round_Button(200, 40, 90, 25, "Backward"); + + m_pNext = new Fl_Return_Button(105, 70, 100, 25, "Find Next"); + m_pNext->callback(cb_replace_next, this); + + m_pCancel = new Fl_Button(230, 70, 60, 25, "Cancel"); + m_pCancel->callback(cb_replace_cancel, this); + + m_pFindDlg->end(); + m_pFindDlg->set_non_modal(); + + m_pParent = pParent; +} + diff --git a/src/ide.h b/src/ide.h index 79742dd..8318b9f 100644 --- a/src/ide.h +++ b/src/ide.h @@ -33,7 +33,7 @@ #include "MString.h" #include "vtobj.h" - +#include "project.h" void cb_Ide(Fl_Widget* w, void*) ; @@ -50,6 +50,7 @@ class VT_IdeSource : public VTObject MString m_Name; Flu_Tree_Browser::Node* m_Node; + class VT_IdeGroup* m_ParentGroup; }; class VT_IdeGroup : public VTObject @@ -66,30 +67,50 @@ class VT_IdeGroup : public VTObject Flu_Tree_Browser::Node* m_Node; }; +class VT_ReplaceDlg +{ +public: + VT_ReplaceDlg(class VT_Ide* pParent); + ~VT_ReplaceDlg(); + + Fl_Window* m_pReplaceDlg; + Fl_Input* m_pFind; + Fl_Input* m_pWith; + Fl_Button* m_pAll; + Fl_Button* m_pNext; + Fl_Button* m_pCancel; + + class VT_Ide* m_pParent; -class VT_IdeProject + char search[256]; +}; + +class VT_FindDlg { public: - VT_IdeProject() { m_Dirty = 0; }; - ~VT_IdeProject(); - - MString m_Name; - MString m_RootPath; - MString m_IncludePath; - MString m_LinkPath; - MString m_AsmOptions; - MString m_LinkOptions; - VTObArray m_Groups; - int m_Dirty; + VT_FindDlg(class VT_Ide* pParent); + ~VT_FindDlg(); + + Fl_Window* m_pFindDlg; + Fl_Input* m_pFind; + Fl_Round_Button* m_pForward; + Fl_Round_Button* m_pBackward; + Fl_Button* m_pNext; + Fl_Button* m_pCancel; + + class VT_Ide* m_pParent; + + char search[256]; }; class VT_Ide : public Fl_Window { public: - VT_Ide(int w, int h, const char *title = 0); + VT_Ide(int x, int y, int w, int h, const char *title = 0); // Methods virtual void show(); + virtual int handle(int event); void NewProject(void); void OpenProject(void); @@ -98,16 +119,40 @@ class VT_Ide : public Fl_Window int ParsePrjFile(const char *name); void RightClick(Flu_Tree_Browser::Node* n); void NewFolder(Flu_Tree_Browser::Node* n); + void NewFile(void); + void SaveFile(void); + void SaveAs(void); + void OpenFile(void); + void Copy(void); + void Cut(void); + void Paste(void); + void Find(void); + void FindNext(void); + void Replace(void); + void ReplaceAll(void); + void ReplaceNext(void); void AddFilesToFolder(Flu_Tree_Browser::Node* n); + void DeleteItem(Flu_Tree_Browser::Node* n); void FolderProperties(Flu_Tree_Browser::Node* n); void OpenTreeFile(Flu_Tree_Browser::Node* n); void AssembleTreeFile(Flu_Tree_Browser::Node* n); void TreeFileProperties(Flu_Tree_Browser::Node* n); + void BuildProject(void); + void CleanProject(void); + void ShowProjectSettings(void); + MString MakePathRelative(const MString& path, const MString& relTo); + MString MakePathAbsolute(const MString& path, const MString& relTo); + MString ProjectName(void); + int ProjectDirty(void); + + Fl_Window* m_EditWindow; + VT_ReplaceDlg* m_pReplaceDlg; + VT_FindDlg* m_pFindDlg; - Fl_Window* m_EditWindow; protected: virtual void draw(); void AddGroupToTree(VTObject *pObj, const char *fmt); + void NewEditWindow(const MString& title, const MString& file); Fl_Window* m_ProjWindow; Flu_Tree_Browser* m_ProjTree; @@ -119,7 +164,10 @@ class VT_Ide : public Fl_Window Fl_Group* m_DebugTab; Fl_Group* m_WatchTab; Flu_Tree_Browser::Node* m_Node; - VT_IdeProject* m_ActivePrj; + VT_Project* m_ActivePrj; + MString m_LastDir; + int m_OpenLocation; }; #endif + diff --git a/src/inet_pton.c b/src/inet_pton.c new file mode 100644 index 0000000..a71b0c8 --- /dev/null +++ b/src/inet_pton.c @@ -0,0 +1,305 @@ +/* + This file is part of PlibC. + (C) 2005 Nils Durner (and other contributing authors) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef HAVE_INET_PTON + +#include "inet_pton.h" + + /* + * Net-SNMP Win32 additions + */ +#include +#include +#include + + +/* + * Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +int inet_pton4(char *src, u_char *dst, int pton); +#if USE_IPV6 +int inet_pton6(char *src, u_char *dst); +#endif + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * author: + * Paul Vixie, 1996. + */ +int inet_pton(int af, char *src, void *dst) +{ + + switch (af) { + case AF_INET: + return (inet_pton4(src, dst, 1)); +#if USE_IPV6 + case AF_INET6: + return (inet_pton6(src, dst)); +#endif + default: + errno = EAFNOSUPPORT; + return (-1); + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst, pton) + * when last arg is 0: inet_aton(). with hexadecimal, octal and shorthand. + * when last arg is 1: inet_pton(). decimal dotted-quad only. + * return: + * 1 if `src' is a valid input, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +int inet_pton4(char *src, u_char *dst, int pton) +{ + u_int val; + u_int digit; + int base, n; + unsigned char c; + u_int parts[4]; + register u_int *pp = parts; + if (strcmp(src, "localhost") == 0) + src = "127.0.0.1"; + + c = *src; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; base = 10; + if (c == '0') { + c = *++src; + if (c == 'x' || c == 'X') + base = 16, c = *++src; + else if (isdigit(c) && c != '9') + base = 8; + } + /* inet_pton() takes decimal only */ + if (pton && base != 10) + return (0); + for (;;) { + if (isdigit(c)) { + digit = c - '0'; + if (digit >= base) + break; + val = (val * base) + digit; + c = *++src; + } else if (base == 16 && isxdigit(c)) { + digit = c + 10 - (islower(c) ? 'a' : 'A'); + if (digit >= 16) + break; + val = (val << 4) | digit; + c = *++src; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + * a (with a treated as 32 bits) + */ + if (pp >= parts + 3) + return (0); + *pp++ = val; + c = *++src; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && !isspace(c)) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + /* inet_pton() takes dotted-quad only. it does not take shorthand. */ + if (pton && n != 4) + return (0); + switch (n) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (parts[0] > 0xff || val > 0xffffff) + return (0); + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if ((parts[0] | parts[1]) > 0xff || val > 0xffff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if ((parts[0] | parts[1] | parts[2] | val) > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + if (dst) { + val = htonl(val); + memcpy(dst, &val, INADDRSZ); + } + return (1); +} + +#if USE_IPV6 +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +int inet_pton6(char *src, u_char *dst) +{ + static char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp; + char *xdigits, *curtok; + int ch, saw_xdigit; + u_int val; + + memset((tp = tmp), '\0', IN6ADDRSZ); + endp = tp + IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } else if (*src == '\0') + return (0); + if (tp + INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + INADDRSZ) <= endp) && + inet_pton4(curtok, tp, 1) > 0) { + tp += INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if (saw_xdigit) { + if (tp + INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + return (0); + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return (0); + memcpy(dst, tmp, IN6ADDRSZ); + return (1); +} +#endif + +#endif /* HAVE_INET_PTON */ \ No newline at end of file diff --git a/src/inet_pton.h b/src/inet_pton.h new file mode 100644 index 0000000..5243529 --- /dev/null +++ b/src/inet_pton.h @@ -0,0 +1,22 @@ +#ifndef EAFNOSUPPORT +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#endif + +#ifndef IN6ADDRSZ +#define IN6ADDRSZ 16 +#endif + +#ifndef INT16SZ +#define INT16SZ 2 +#endif + /* + * End of Net-SNMP Win32 additions + */ + +#ifndef INADDRSZ +#define INADDRSZ 4 +#endif + + +typedef unsigned char u_char; +int inet_pton(int af, char *src, void *dst); diff --git a/src/io.c b/src/io.c index b699a7c..40e12ec 100644 --- a/src/io.c +++ b/src/io.c @@ -34,6 +34,7 @@ #include "VirtualT.h" #include "cpu.h" #include "gen_defs.h" +#include "roms.h" #include "io.h" #include "serial.h" #include "display.h" @@ -74,21 +75,20 @@ uchar clock_sr[5]; /* 40 Bit shift register */ uchar clock_sr_index = 0; uchar clock_serial_out = 0; extern int gRomBank; +extern RomDescription_t *gStdRomDesc; void update_keys(void) { int equal = 1; - int buf_index = 0xFF9A; + int buf_index; int c; unsigned char key; - if (gModel == MODEL_T200) - buf_index = 0xFD0E; - else if (gModel == MODEL_PC8201) - buf_index = 0xFE58; - - + if (gStdRomDesc == NULL) + return; + + buf_index = gStdRomDesc->sKeyscan; /* Insure keystroke was recgonized by the system */ for (c = 0; c < 9; c++) @@ -105,7 +105,7 @@ void update_keys(void) if (!equal) { - if (++gDelayCount < 20) + if (++gDelayCount < 10) { gDelayUpdateKeys = 1; return; @@ -115,69 +115,122 @@ void update_keys(void) gDelayUpdateKeys = 0; gDelayCount = 0; - keyscan[0] = ~(gKeyStates['z'] | (gKeyStates['x'] << 1) | - (gKeyStates['c'] << 2) | (gKeyStates['v'] << 3) | - (gKeyStates['b'] << 4) | (gKeyStates['n'] << 5) | - (gKeyStates['m'] << 6) | (gKeyStates['l'] << 7)); - - keyscan[1] = ~(gKeyStates['a'] | (gKeyStates['s'] << 1) | - (gKeyStates['d'] << 2) | (gKeyStates['f'] << 3) | - (gKeyStates['g'] << 4) | (gKeyStates['h'] << 5) | - (gKeyStates['j'] << 6) | (gKeyStates['k'] << 7)); - - keyscan[2] = ~(gKeyStates['q'] | (gKeyStates['w'] << 1) | - (gKeyStates['e'] << 2) | (gKeyStates['r'] << 3) | - (gKeyStates['t'] << 4) | (gKeyStates['y'] << 5) | - (gKeyStates['u'] << 6) | (gKeyStates['i'] << 7)); - - keyscan[4] = ~(gKeyStates['1'] | (gKeyStates['2'] << 1) | - (gKeyStates['3'] << 2) | (gKeyStates['4'] << 3) | - (gKeyStates['5'] << 4) | (gKeyStates['6'] << 5) | - (gKeyStates['7'] << 6) | (gKeyStates['8'] << 7)); - - if (gModel != MODEL_PC8201) + if (gModel == MODEL_M10) { - keyscan[3] = ~(gKeyStates['o'] | (gKeyStates['p'] << 1) | - (gKeyStates['['] << 2) | (gKeyStates[';'] << 3) | - (gKeyStates['\''] << 4) | (gKeyStates[','] << 5) | - (gKeyStates['.'] << 6) | (gKeyStates['/'] << 7)); - - keyscan[5] = ~(gKeyStates['9'] | (gKeyStates['0'] << 1) | - (gKeyStates['-'] << 2) | (gKeyStates['='] << 3)) & - (unsigned char) (gSpecialKeys >> 24); - - keyscan[6] = (unsigned char) ((gSpecialKeys >> 16) & 0xFF); + keyscan[0] = ~(gKeyStates['q'] | (gKeyStates['w'] << 1) | + (gKeyStates['['] << 2) | (gKeyStates['1'] << 3) | + (gKeyStates['2'] << 4) | (gKeyStates['3'] << 5) | + (gKeyStates['4'] << 6) | (gKeyStates['5'] << 7)); + + keyscan[1] = ~(gKeyStates['y'] | (gKeyStates['6'] << 1) | + (gKeyStates['7'] << 2) | (gKeyStates['8'] << 3) | + (gKeyStates['9'] << 4) | (gKeyStates['0'] << 5) | + (gKeyStates['-'] << 6) | (gKeyStates['^'] << 7)); + + keyscan[2] = ~(gKeyStates[']'] | (gKeyStates['@'] << 1) | + (gKeyStates[';'] << 2) | (gKeyStates[':'] << 3) | + (gKeyStates['/'] << 4) | (gKeyStates['.'] << 5) | + (gKeyStates[','] << 6) | (gKeyStates['m'] << 7)); + + keyscan[3] = ~(gKeyStates['a'] | (gKeyStates['\\'] << 1) | + (gKeyStates['z'] << 2) | (gKeyStates['x'] << 3) | + (gKeyStates['c'] << 4) | (gKeyStates['v'] << 5) | + (gKeyStates['b'] << 6) | (gKeyStates['n'] << 7)); + + keyscan[4] = ~(gKeyStates['s'] | (gKeyStates['d'] << 1) | + (gKeyStates['f'] << 2) | (gKeyStates['g'] << 3) | + (gKeyStates['h'] << 4) | (gKeyStates['j'] << 5) | + (gKeyStates['k'] << 6) | (gKeyStates['l'] << 7)); + + keyscan[5] = ~(gKeyStates['e'] | (gKeyStates['r'] << 1) | + (gKeyStates['t'] << 2) | (gKeyStates['u'] << 3) | + (gKeyStates['i'] << 4) | (gKeyStates['o'] << 5) | + (gKeyStates['p'] << 6)) & + (unsigned char) (((gSpecialKeys & MT_SPACE) | ~MT_SPACE) >> 9); + + keyscan[6] = (unsigned char) (((gSpecialKeys & MT_LEFT) >> 28) | ~(MT_LEFT >> 28)) & + (unsigned char) (((gSpecialKeys & MT_RIGHT) >> 28) | ~(MT_RIGHT >> 28)) & + (unsigned char) (((gSpecialKeys & MT_UP) >> 28) | ~(MT_UP >> 28)) & + (unsigned char) (((gSpecialKeys & MT_DOWN) >> 28) | ~(MT_DOWN >> 28)) & + (unsigned char) (((gSpecialKeys & MT_BKSP) >> 13) | ~(MT_BKSP >> 13)) & + (unsigned char) (((gSpecialKeys & MT_TAB) >> 13) | ~(MT_TAB >> 13)) & + (unsigned char) (((gSpecialKeys & MT_ENTER) >> 17) | ~(MT_ENTER >> 17)) & + (unsigned char) (((gSpecialKeys & MT_PASTE) >> 13) | ~(MT_PASTE >> 13)); keyscan[7] = (unsigned char) ((gSpecialKeys >> 8) & 0xFF); - keyscan[8] = (unsigned char) (gSpecialKeys & 0xFF); + keyscan[8] = (unsigned char) ((gSpecialKeys & 0x80) | 0x7F) & + (unsigned char) (((gSpecialKeys & 0x30) << 1) | 0x9F) & + (unsigned char) (((gSpecialKeys & 0x07) << 2) | 0xE3) & + (unsigned char) (((gSpecialKeys & MT_PRINT) >> 21) | ~(MT_PRINT >> 21)) & + (unsigned char) (((gSpecialKeys & MT_LABEL) >> 21) | ~(MT_LABEL >> 21)); } else { - keyscan[3] = ~(gKeyStates['o'] | (gKeyStates['p'] << 1) | - (gKeyStates['@'] << 2) | (gKeyStates['\\'] << 3) | - (gKeyStates[','] << 4) | (gKeyStates['.'] << 5) | - (gKeyStates['/'] << 6) | (gKeyStates[']'] << 7)); - - keyscan[5] = ~(gKeyStates['9'] | (gKeyStates['0'] << 1) | - (gKeyStates[';'] << 2) | (gKeyStates[':'] << 3) | - (gKeyStates['-'] << 4) | (gKeyStates['['] << 5)) & - (unsigned char) (((gSpecialKeys & MT_SPACE) | ~MT_SPACE) >> 10) & - (unsigned char) (((gSpecialKeys & MT_INS) | ~MT_INS) >> 17); - - keyscan[6] = (unsigned char) (((gSpecialKeys & MT_BKSP) >> 17) | ~(MT_BKSP >> 17)) & - (unsigned char) (((gSpecialKeys & MT_UP) >> 29) | ~(MT_UP >> 29)) & - (unsigned char) (((gSpecialKeys & MT_DOWN) >> 29) | ~(MT_DOWN >> 29)) & - (unsigned char) (((gSpecialKeys & MT_LEFT) >> 25) | ~(MT_LEFT >> 25)) & - (unsigned char) (((gSpecialKeys & MT_RIGHT) >> 25) | ~(MT_RIGHT >> 25)) & - (unsigned char) (((gSpecialKeys & MT_TAB) >> 13) | ~(MT_TAB >> 13)) & - (unsigned char) (((gSpecialKeys & MT_ESC) >> 13) | ~(MT_ESC >> 13)) & - (unsigned char) (((gSpecialKeys & MT_ENTER) >> 16) | ~(MT_ENTER >> 16)); - - keyscan[7] = (unsigned char) ((gSpecialKeys >> 8) & 0x1F); - - keyscan[8] = (unsigned char) ((gSpecialKeys & 0x07) | 0xF8) & - (unsigned char) (((gSpecialKeys & MT_CAP_LOCK) | ~MT_CAP_LOCK) >> 1); + keyscan[0] = ~(gKeyStates['z'] | (gKeyStates['x'] << 1) | + (gKeyStates['c'] << 2) | (gKeyStates['v'] << 3) | + (gKeyStates['b'] << 4) | (gKeyStates['n'] << 5) | + (gKeyStates['m'] << 6) | (gKeyStates['l'] << 7)); + + keyscan[1] = ~(gKeyStates['a'] | (gKeyStates['s'] << 1) | + (gKeyStates['d'] << 2) | (gKeyStates['f'] << 3) | + (gKeyStates['g'] << 4) | (gKeyStates['h'] << 5) | + (gKeyStates['j'] << 6) | (gKeyStates['k'] << 7)); + + keyscan[2] = ~(gKeyStates['q'] | (gKeyStates['w'] << 1) | + (gKeyStates['e'] << 2) | (gKeyStates['r'] << 3) | + (gKeyStates['t'] << 4) | (gKeyStates['y'] << 5) | + (gKeyStates['u'] << 6) | (gKeyStates['i'] << 7)); + + keyscan[4] = ~(gKeyStates['1'] | (gKeyStates['2'] << 1) | + (gKeyStates['3'] << 2) | (gKeyStates['4'] << 3) | + (gKeyStates['5'] << 4) | (gKeyStates['6'] << 5) | + (gKeyStates['7'] << 6) | (gKeyStates['8'] << 7)); + + if (gModel != MODEL_PC8201) + { + keyscan[3] = ~(gKeyStates['o'] | (gKeyStates['p'] << 1) | + (gKeyStates['['] << 2) | (gKeyStates[';'] << 3) | + (gKeyStates['\''] << 4) | (gKeyStates[','] << 5) | + (gKeyStates['.'] << 6) | (gKeyStates['/'] << 7)); + + keyscan[5] = ~(gKeyStates['9'] | (gKeyStates['0'] << 1) | + (gKeyStates['-'] << 2) | (gKeyStates['='] << 3)) & + (unsigned char) (gSpecialKeys >> 24); + + keyscan[6] = (unsigned char) ((gSpecialKeys >> 16) & 0xFF); + + keyscan[7] = (unsigned char) ((gSpecialKeys >> 8) & 0xFF); + + keyscan[8] = (unsigned char) (gSpecialKeys & 0xFF); + } + else + { + keyscan[3] = ~(gKeyStates['o'] | (gKeyStates['p'] << 1) | + (gKeyStates['@'] << 2) | (gKeyStates['\\'] << 3) | + (gKeyStates[','] << 4) | (gKeyStates['.'] << 5) | + (gKeyStates['/'] << 6) | (gKeyStates[']'] << 7)); + + keyscan[5] = ~(gKeyStates['9'] | (gKeyStates['0'] << 1) | + (gKeyStates[';'] << 2) | (gKeyStates[':'] << 3) | + (gKeyStates['-'] << 4) | (gKeyStates['['] << 5)) & + (unsigned char) (((gSpecialKeys & MT_SPACE) | ~MT_SPACE) >> 10) & + (unsigned char) (((gSpecialKeys & MT_INS) | ~MT_INS) >> 17); + + keyscan[6] = (unsigned char) (((gSpecialKeys & MT_BKSP) >> 17) | ~(MT_BKSP >> 17)) & + (unsigned char) (((gSpecialKeys & MT_UP) >> 29) | ~(MT_UP >> 29)) & + (unsigned char) (((gSpecialKeys & MT_DOWN) >> 29) | ~(MT_DOWN >> 29)) & + (unsigned char) (((gSpecialKeys & MT_LEFT) >> 25) | ~(MT_LEFT >> 25)) & + (unsigned char) (((gSpecialKeys & MT_RIGHT) >> 25) | ~(MT_RIGHT >> 25)) & + (unsigned char) (((gSpecialKeys & MT_TAB) >> 13) | ~(MT_TAB >> 13)) & + (unsigned char) (((gSpecialKeys & MT_ESC) >> 13) | ~(MT_ESC >> 13)) & + (unsigned char) (((gSpecialKeys & MT_ENTER) >> 16) | ~(MT_ENTER >> 16)); + + keyscan[7] = (unsigned char) ((gSpecialKeys >> 8) & 0x1F); + + keyscan[8] = (unsigned char) ((gSpecialKeys & 0x07) | 0xF8) & + (unsigned char) (((gSpecialKeys & MT_CAP_LOCK) | ~MT_CAP_LOCK) >> 1); + } } } @@ -278,18 +331,44 @@ void clock_chip_cmd(void) } } } + +void show_remem_mode(void) +{ + char temp[20]; + + /* Update Display map if output to Mode Port */ + if (gReMem) + { + if (inport(REMEM_MODE_PORT) & 0x01) + { + sprintf(temp, "Map:%d", (inport(REMEM_MODE_PORT) >> 3) & 0x07); + display_map_mode(temp); + } + else + display_map_mode("Normal"); + + return; + } + + /* Not in ReMem emulation mode */ + display_map_mode(""); +} + void out(uchar port, uchar val) { int c; unsigned char flags; switch(port) { + case REMEM_MODE_PORT: /* ReMem Mode port */ case REMEM_SECTOR_PORT: /* ReMem Sector access port */ case REMEM_DATA_PORT: /* ReMem Data Port */ - case REMEM_MODE_PORT: /* ReMem Mode port */ case RAMPAC_SECTOR_PORT: /* ReMem/RAMPAC emulation port */ case RAMPAC_DATA_PORT: /* ReMem RAMPAC emulation port */ + case 0x85: remem_out(port, val); + if (port == REMEM_MODE_PORT) + show_remem_mode(); /* Update ReMem mode */ break; case 0x90: /* T200 Clock/Timer chip */ @@ -1021,12 +1100,14 @@ int inport(uchar port) /* Read keyboard status -- First check bit 0 of output port 0xBA */ if ((ioBA & 0x01) == 0) - return (unsigned char) (gSpecialKeys & 0xFF); + //return (unsigned char) (gSpecialKeys & 0xFF); + return keyscan[8]; if (ioB9 == 0) { - return keyscan[7] & keyscan[6] & keyscan[5] & keyscan[4] & + ret = keyscan[7] & keyscan[6] & keyscan[5] & keyscan[4] & keyscan[3] & keyscan[2] & keyscan[1] & keyscan[0]; + return ret; } /* Check Bit 7 of port B9 */ diff --git a/src/io.h b/src/io.h index 56057f1..62f07fa 100644 --- a/src/io.h +++ b/src/io.h @@ -49,6 +49,7 @@ void out(uchar port, uchar val); void update_keys(void); void io_set_ram_bank(unsigned char bank); int inport(uchar port); +void show_remem_mode(void); #ifdef __cplusplus } #endif diff --git a/src/m100emu.c b/src/m100emu.c index a05f486..12cf22c 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -27,7 +27,6 @@ * SUCH DAMAGE. */ - #include #include #include @@ -35,6 +34,7 @@ #include #ifdef _WIN32 #include +#include #endif #ifdef __unix__ @@ -55,22 +55,18 @@ #include "memory.h" #include "m100emu.h" #include "sound.h" +#include "remote.h" int fullspeed=0; int gModel = MODEL_M100; uchar cpu[14]; extern uchar *gMemory[64]; -extern uchar gBaseMemory[65536]; -extern uchar gSysROM[65536]; extern uchar gMsplanROM[32768]; extern uchar gOptROM[32768]; mem_monitor_cb gMemMonitor = NULL; -long hist[256]; -int order[256]; - char op[26]; UINT64 cycles=0; int cycle_delta; @@ -85,10 +81,16 @@ DWORD one_sec_time; UINT64 one_sec_cycles; DWORD update_secs = 0; float cpu_speed; -int gExitApp = 0; -int gExitLoop = 0; +volatile int gExitApp = 0; +volatile int gExitLoop = 0; char gsOptRomFile[256]; +int gShowVersion = 0; DWORD last_one_sec_time; +int gMaintCount = 262888; +int gOsDelay = 0; +int gNoGUI = 0; +int gSocketPort = 0; +int gRemoteSwitchModel = -1; //Added J. VERNET @@ -98,10 +100,11 @@ char file[255]; extern RomDescription_t gM100_Desc; extern RomDescription_t gM200_Desc; extern RomDescription_t gN8201_Desc; +extern RomDescription_t gM10_Desc; extern uchar gReMem; extern int cROM; extern unsigned char ioD0; -RomDescription_t *gStdRomDesc; +RomDescription_t *gStdRomDesc = NULL; /* Define Debug global variables */ @@ -140,13 +143,15 @@ void throttle(int cy) { double hires; - if(!fullspeed) { + if(!fullspeed) + { if(last_instruct==0) last_instruct=hirestimer(); last_instruct+=cy*0.000000416666666667; - while((hires = hirestimer())= argc) + { + printf("%s: -p port not specified\n", argv[0]); + return 1; + } + else + { + gSocketPort = atoi(argv[i+1]); + i++; + } + } + } } - if (trace) - tracefile = fopen("trace.txt", "w+"); + return 0; +} +void setup_unix_signals(void) +{ #ifdef __unix__ signal(SIGTERM,handle_sig); signal(SIGHUP,handle_sig); signal(SIGQUIT,handle_sig); signal(SIGINT,handle_sig); +#endif +} + +void setup_working_path(char **argv) +{ +#ifdef __unix__ + int i; + + getcwd(path, sizeof(path)); //J. VERNET: Get Absolute Path, as getcwd doesn't return anything when launch from finder - i = strlen(argv[0])-1; - // Find last '/' in path to remove app name from the path - while ((argv[0][i] != '/') && (i > 0)) - i--; - strncpy(path,argv[0], i+1); + if (strlen(path) == 0) + { + i = strlen(argv[0])-1; + // Find last '/' in path to remove app name from the path + while ((argv[0][i] != '/') && (i > 0)) + i--; + strncpy(path,argv[0], i+1); + } + + // Check if the last character is '/' + i = strlen(path); + if (path[i-1] != '/') + strcat(path, "/"); # else - strcpy(path,"./"); + _getcwd(path, sizeof(path)); + strcat(path,"\\"); #endif +} + +/* +======================================================================== +main: This is the main entry point for the VirtualT application. +======================================================================== +*/ +int main(int argc, char **argv) +{ + if (process_args(argc, argv)) /* Parse command line args */ + return; + + setup_unix_signals(); /* Setup Unix signal handling */ + setup_working_path(argv); /* Create a working dir path */ // Added by JV for prefs init_pref(); /* load user Menu preferences */ @@ -732,11 +887,12 @@ int main(int argc, char **argv) init_sound(); /* Initialize Sound system */ init_display(); /* Initialize the Display */ init_cpu(); /* Initialize the CPU */ + init_remote(); /* Initialize the remote control */ /* Perform Emulation */ emulate(); /* Main emulation loop */ - /* Save RAM comtents after emulation */ + /* Save RAM contents after emulation */ save_ram(); /* Cleanup */ diff --git a/src/m100emu.h b/src/m100emu.h index f4867da..a98ef39 100644 --- a/src/m100emu.h +++ b/src/m100emu.h @@ -42,28 +42,44 @@ extern "C" { extern char op[26]; extern int trace; extern int fullspeed; -extern int gExitApp; -extern int gExitLoop; +extern volatile int gExitApp; +extern volatile int gExitLoop; extern float cpu_speed; extern uchar *gMemory[64]; extern RomDescription_t *gStdRomDesc; extern int gModel; extern char gsOptRomFile[256]; -__inline double hirestimer(void); +double hirestimer(void); typedef void (*mem_monitor_cb)(void); -typedef void (*debug_monitor_callback)(); +typedef void (*debug_monitor_callback)(int reason); void mem_set_monitor_callback(mem_monitor_cb cb); int debug_set_monitor_callback(debug_monitor_callback pCallback); void debug_clear_monitor_callback(debug_monitor_callback pCallback); +void debug_step(void); +void debug_halt(void); +void debug_run(void); +void remote_switch_model(int model); extern char gDebugActive; extern char gStopped; extern char gSingleStep; extern int gDebugMonitorFreq; +extern int gSocketPort; +extern int gNoGUI; +#define DEBUG_PC_CHANGED 1 +#define DEBUG_CPU_HALTED 2 +#define DEBUG_CPU_RESUME 3 +#define DEBUG_CPU_STEP 4 + +#define SPEED_REAL 0 +#define SPEED_FRIENDLY1 1 +#define SPEED_FRIENDLY2 2 +#define SPEED_FULL 3 int check_model_support(int model); void get_emulation_path(char* emu, int model); void get_model_string(char* str, int model); +int get_model_from_string(char* str); void get_rom_path(char* file, int model); void init_cpu(void); //void cpu_delay(int cy); diff --git a/src/m100rom.c b/src/m100rom.c index a414974..c04dedb 100644 --- a/src/m100rom.c +++ b/src/m100rom.c @@ -998,8 +998,11 @@ RomDescription_t gM100_Desc = { 0xF962, /* Start of RAM directory */ 0xF678, /* BASIC string buffer pointer */ 0xFAD8, /* BASIC Size */ + 0xFF9A, /* Keyscan location */ + 0x7711, /* Character generator table */ 24, /* Number of directory entries */ - 8 /* Index of first Dir entry */ + 8, /* Index of first Dir entry */ + 0x5B0D /* Addres of MS Copyright string */ }; diff --git a/src/m10rom.c b/src/m10rom.c new file mode 100644 index 0000000..07e9198 --- /dev/null +++ b/src/m10rom.c @@ -0,0 +1,991 @@ +/* m10rom.c */ + +/* $Id$ */ + +/* + * Copyright 2007 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "roms.h" +#include "romstrings.h" + + +Std_ROM_Table_t gM10_Tables[] = { + { 0x0003, 5, TABLE_TYPE_STRING }, + { 0x0040, 64, TABLE_TYPE_JUMP }, + { 0x0080, 271, TABLE_TYPE_MODIFIED_STRING }, + { 0x018F, 97, TABLE_TYPE_MODIFIED_STRING }, + { 0x01F0, 112, TABLE_TYPE_MODIFIED_STRING }, + { 0x0262, 140, TABLE_TYPE_JUMP }, + { 0x02EE, 46, TABLE_TYPE_JUMP }, + { 0x031C, 62, TABLE_TYPE_2BYTE }, + { 0x036F, 130, TABLE_TYPE_CODE }, + { 0x03F1, 23, TABLE_TYPE_STRING }, + { 0x0C7B, 19, TABLE_TYPE_STRING }, + { 0x0D78, 17, TABLE_TYPE_STRING }, + { 0x14DD, 6, TABLE_TYPE_JUMP }, + { 0x14FD, 6, TABLE_TYPE_JUMP }, + { 0x1507, 10, TABLE_TYPE_JUMP }, + { 0x168A, 10, TABLE_TYPE_JUMP }, + { 0x175F, 6, TABLE_TYPE_JUMP }, + { 0x176D, 10, TABLE_TYPE_JUMP }, +// { 0x17D1, 10, TABLE_TYPE_JUMP }, + { 0x1844, 10, TABLE_TYPE_JUMP }, + { 0x1942, 21, TABLE_TYPE_3BYTE }, + { 0x2459, 16, TABLE_TYPE_STRING }, + { 0x25AD, 18, TABLE_TYPE_STRING }, + { 0x26D7, 14, TABLE_TYPE_STRING }, + { 0x3235, 32, TABLE_TYPE_CODE }, + { 0x3255, 2, TABLE_TYPE_CODE }, + { 0x3257, 88, TABLE_TYPE_CODE }, + { 0x32AF, 1, TABLE_TYPE_CODE }, + { 0x32B0, 32, TABLE_TYPE_CODE }, + { 0x32D0, 1, TABLE_TYPE_CODE }, + { 0x32D1, 24, TABLE_TYPE_CODE }, + { 0x32E9, 1, TABLE_TYPE_CODE }, + { 0x32EA, 32, TABLE_TYPE_CODE }, + { 0x330A, 1, TABLE_TYPE_CODE }, + { 0x330B, 40, TABLE_TYPE_CODE }, + { 0x3333, 1, TABLE_TYPE_CODE }, + { 0x3334, 64, TABLE_TYPE_CODE }, + { 0x3374, 1, TABLE_TYPE_CODE }, + { 0x3375, 64, TABLE_TYPE_CODE }, + { 0x436A, 24, TABLE_TYPE_BYTE_LOOKUP }, + { 0x4398, 66, TABLE_TYPE_BYTE_LOOKUP }, + { 0x4623, 21, TABLE_TYPE_BYTE_LOOKUP }, + { 0x50B8, 29, TABLE_TYPE_CTRL_DELIM }, + { 0x50D6, 14, TABLE_TYPE_JUMP }, + { 0x5143, 9, TABLE_TYPE_STRING }, + { 0x514C, 18, TABLE_TYPE_4BYTE_CMD }, + { 0x515E, 1, TABLE_TYPE_CODE }, + { 0x515F, 20, TABLE_TYPE_CTRL_DELIM }, + { 0x5191, 18, TABLE_TYPE_MODIFIED_STRING3 }, +// { 0x51E7, 6, TABLE_TYPE_STRING }, +// { 0x5244, 9, TABLE_TYPE_STRING }, +// { 0x5443, 18, TABLE_TYPE_CTRL_DELIM }, + { 0x5255, 16, TABLE_TYPE_JUMP }, + { 0x5265, 1, TABLE_TYPE_CODE }, + { 0x52CB, 18, TABLE_TYPE_STRING }, + { 0x52DD, 6, TABLE_TYPE_STRING }, + { 0x52E3, 2, TABLE_TYPE_CODE }, + { 0x5481, 53, TABLE_TYPE_STRING }, + { 0x580C, 36, TABLE_TYPE_3BYTE }, + { 0x5830, 17, TABLE_TYPE_STRING }, + { 0x5841, 6, TABLE_TYPE_CODE }, + { 0x5847, 19, TABLE_TYPE_STRING }, + { 0x585A, 15, TABLE_TYPE_CODE }, + { 0x5869, 34, TABLE_TYPE_CTRL_DELIM }, + { 0x59F1, 33, TABLE_TYPE_STRING }, + { 0x5A12, 18, TABLE_TYPE_4BYTE_CMD }, + { 0x5A24, 1, TABLE_TYPE_CODE }, + { 0x5A25, 8, TABLE_TYPE_STRING }, + { 0x5A2D, 51, TABLE_TYPE_CTRL_DELIM }, + { 0x5B35, 13, TABLE_TYPE_STRING }, + { 0x5B42, 8, TABLE_TYPE_CODE }, + { 0x5B4A, 36, TABLE_TYPE_CTRL_DELIM }, + { 0x5C58, 17, TABLE_TYPE_STRING }, + { 0x5C69, 2, TABLE_TYPE_CODE }, + { 0x5C6B, 26, TABLE_TYPE_STRING }, +// { 0x5F60, 5, TABLE_TYPE_STRING }, + { 0x5D36, 64, TABLE_TYPE_JUMP }, + { 0x5DD1, 13, TABLE_TYPE_STRING }, + { 0x62EE, 17, TABLE_TYPE_STRING }, + { 0x637D, 21, TABLE_TYPE_BYTE_LOOKUP }, + { 0x642C, 7, TABLE_TYPE_STRING }, + { 0x6455, 9, TABLE_TYPE_STRING }, + { 0x6911, 88, TABLE_TYPE_CATALOG }, + { 0x6BD6, 18, TABLE_TYPE_JUMP }, + { 0x726B, 240, TABLE_TYPE_CODE }, + { 0x735D, 20, TABLE_TYPE_CODE }, + { 0x7425, 6, TABLE_TYPE_CODE }, + { 0x742B, 96*5, TABLE_TYPE_CODE }, + { 0x760B, 128*6, TABLE_TYPE_CODE }, + { 0x790B, 322-42, TABLE_TYPE_CODE }, + { 0x7BF3, 14, TABLE_TYPE_CODE }, + { 0x7C8A, 36, TABLE_TYPE_STRING }, + { 0x7CAE, 21, TABLE_TYPE_STRING }, + { 0x7CFB, 773, TABLE_TYPE_CODE }, + { -1, 0, 0 } +}; + +Std_ROM_Addresses_t gM10_Vars[] = { + { 0x0040, R_FUN_VCTR_TBL }, + { 0x0080, R_BASIC_TBL }, + { 0x018E, R_FUN_TBL_TAB }, + { 0x01F0, R_FUN_TBL_SGN }, + { 0x0262, R_BASIC_VCTR_TBL }, + { 0x02EE, R_MATH_VCTR_TBL }, + { 0x031A, R_BASIC_ERR_TXT }, + { 0x035A, R_INIT_IMAGE }, + { 0x036F, R_XROM_DET_IMAGE }, + { 0x03F1, R_BASIC_STRINGS }, + { 0x1F24, R_CAS_FREQ_CNT }, + { 0x4349, R_CAS_FREQ_CNT }, + { 0x551D, R_TERM_FKEY_VCTR_TBL }, + { 0x5841, R_DIR_DISP_ORDER_TBL }, + { 0x5B42, R_TEXT_FKEY_VCTR_TBL }, + { 0x6911, R_ROM_CAT_ENTRIES }, + { 0x6F02, R_INT_EXIT_FUN }, + { 0x6F03, R_INT_EXIT_FUN }, + { 0x726B, R_8155_PIO_PAT1 }, + { 0x735D, R_8155_PIO_PAT2 }, + { 0x7BF3, R_INIT_CLK_VALUES }, + { 0x7C8A, R_MENU_STRINGS }, + { 0x7C96, R_MODEL_NUM_STRING }, + { 0xF5F0, R_ACTIVE_SIGNATURE }, + { 0xF5F4, R_HIMEM }, + { 0xF5F9, R_RST_5_5_VCTR }, + { 0xF5FC, R_RST_6_5_VCTR }, + { 0xF5FF, R_RST_7_5_VCTR }, + { 0xF602, R_TRAP_VCTR }, + { 0xF62A, R_OPTION_ROM_FLAG }, + { 0xF637, R_FKEY_STAT_TBL }, + { 0xF63F, R_NEW_CONSOLE_FLAG }, + { 0xF640, R_CURSOR_ROW }, + { 0xF641, R_CURSOR_COL }, + { 0xF642, R_ACTIVE_ROW_CNT }, + { 0xF643, R_ACTIVE_COL_CNT }, + { 0xF644, R_LABEL_LINE_PROT }, + { 0xF645, R_SCROLL_DISABLE }, + { 0xF646, R_CURSOR_STAT }, + { 0xF647, R_CURSOR_ROW2 }, + { 0xF648, R_CURSOR_COL2 }, + { 0xF64D, R_ESC_MODE_FLAG }, + { 0xF64F, R_REV_VID_SWITCH }, + { 0xF655, R_LAST_PLOT_X }, + { 0xF656, R_LAST_PLOT_Y }, + { 0xF65D, R_PWR_OFF_STAT }, + { 0xF65F, R_DUPLEX_SWITCH }, + { 0xF662, R_RS232_PARAM_TBL }, + { 0xF668, R_ADDRESS_LAST_CALLED }, + { 0xF66E, R_OUT_STMT_HOOK }, + { 0xF671, R_INP_STMT_HOOK }, + { 0xF679, R_LAST_ERROR_CODE }, + { 0xF67B, R_LPT_HEAD_POS }, + { 0xF67C, R_OUTPUT_DEVICE }, + { 0xF67F, R_BASIC_STR_BUF_PTR }, + { 0xF681, R_CUR_BASIC_LINE_NUM }, + { 0xF683, R_START_BASIC_PGM_PTR }, + { 0xF687, R_END_OF_STMT_MARKER }, + { 0xF68C, R_KEYBOARD_BUF }, + { 0xF78F, R_CURSOR_H_POS }, + { 0xF790, R_FKEY_DEF_BUF }, + { 0xF811, R_BASIC_FKEY_DEF_BUF }, + { 0xF893, R_FILE_RAM_END }, + + { 0xF92A, R_SEC_ONES }, + { 0xF92B, R_SEC_TENS }, + { 0xF92C, R_MIN_ONES }, + { 0xF92D, R_MIN_TENS }, + { 0xF92E, R_HR_ONES }, + { 0xF92F, R_HR_TENS }, + { 0xF930, R_DATE_ONES }, + { 0xF931, R_DATE_TENS }, + { 0xF932, R_DAY_CODE }, + { 0xF933, R_MONTH }, + { 0xF934, R_YEAR_ONES }, + { 0xF935, R_YEAR_TENS }, + { 0xF93A, R_SEC_ONES2 }, + { 0xF93B, R_SEC_TENS2 }, + { 0xF93C, R_MIN_ONES2 }, + { 0xF93D, R_MIN_TENS2 }, + { 0xF93E, R_HR_ONES2 }, + { 0xF93F, R_HR_TENS2 }, + { 0xF940, R_DATE_ONES2 }, + { 0xF941, R_DATE_TENS2 }, + { 0xF942, R_DAY_CODE2 }, + { 0xF944, R_ONTIME_TIME }, + { 0xF94B, R_ONCOM_FLAG }, + { 0xF94C, R_ONCOM_ADDRESS }, + { 0xF94E, R_ONTIME_FLAG }, + { 0xF94F, R_ONTIME_ADDRESS }, + { 0xF950, R_FKEY_VCTR_TBL }, + { 0xF969, R_DIR_RAM_START }, + { 0xF9A1, R_UNSAVED_BASIC_PTR }, + { 0xF9AC, R_PASTE_RAM_START }, + { 0xFAB3, R_LAST_CHAR_PRINTED }, + { 0xFAB4, R_LABEL_ENABLE_FLAG }, + { 0xFAB6, R_IPL_FILENAME_START }, + { 0xFAC1, R_BASIC_LIST_START }, + { 0xFAC5, R_SP_SAVE_BUF }, + { 0xFAC7, R_LOWEST_RAM }, + { 0xFAD0, R_RST_38H_OFFSET }, + { 0xFAD6, R_LAST_PGRM_LEN }, + { 0xFAE0, R_RST_38H_VCTR_TBL }, + { 0xFAE8, R_LCD_OUTPUT_HOOK }, + { 0xFAEA, R_LPT_OUTPUT_HOOK }, + { 0xFB76, R_VAR_CREATE_LOC_FLAG }, + { 0xFB77, R_LAST_VAR_TYPE }, + { 0xFB79, R_FILE_BUF_PTR }, + { 0xFBA6, R_DATA_STMT_LINE_NUM }, + { 0xFBA8, R_FOR_NEXT_ACTIVE_FLAG }, + { 0xFBAB, R_LAST_VAR_ASSIGNED_ADDR }, + { 0xFBAD, R_RUNNING_LINE_NUM_ADDR }, + { 0xFBAF, R_BASIC_SP_BUF }, + { 0xFBB1, R_LAST_ERR_LINE_NUM }, + { 0xFBB3, R_LAST_ENTERED_LINE_NUM }, + { 0xFBB5, R_ERR_PTR }, + { 0xFBB7, R_ONERROR_ADDRESS }, + { 0xFBB9, R_BASIC_RUNNING }, + { 0xFBBC, R_BREAK_LINE_NUM }, + { 0xFBBE, R_BREAK_ADDRESS }, + { 0xFBC0, R_DO_FILES_PTR }, + { 0xFBC2, R_CO_FILES_PTR }, + { 0xFBC4, R_VAR_PTR }, + { 0xFBC6, R_ARRAY_TBL_PTR }, + { 0xFBC8, R_UNUSED_MEM_PTR }, + { 0xFBCA, R_DATA_SEARCH_ADDR }, + { 0xFBCC, R_DEF_TBL }, + { 0xFBF9, R_FP_TEMP1 }, + { 0xFC2A, R_FP_FAC1 }, + { 0xFC2C, R_INT_FAC1 }, + { 0xFC72, R_FP_TEMP2 }, + { 0xFC7B, R_FP_FAC2 }, + { 0xFC7D, R_INT_FAC2 }, + { 0xFC8B, R_FP_TEMP3 }, + { 0xFC94, R_MAXFILES }, + { 0xFC95, R_FILE_NUM_TBL_PTR }, + { 0xFCA5, R_BASIC_FILENAME }, + { 0xFCAE, R_LAST_LOAD_FILENAME }, + { 0xFCC0, R_ALT_LCD_CHAR_BUF }, + { 0xFDA1, R_MENU_TO_RAM_MAP }, + { 0xFDED, R_MENU_OR_CMD_FLAG }, + { 0xFDEE, R_CUR_MENU_DIR_LOC }, + { 0xFDEF, R_MAX_MENU_DIR_LOC }, + { 0xFE00, R_LCD_CHAR_BUF }, + { 0xFF40, R_XON_XOFF_CTRL }, + { 0xFF41, R_XON_XOFF_CTRL }, + { 0xFF42, R_XON_XOFF_ENABLE }, + { 0xFF43, R_RS232_INIT_STAT }, + { 0xFF44, R_SOUND_FLAG }, + { 0xFF46, R_PORT_E8H }, + { 0xFFA1, R_RS232_CHAR_BUF }, + { 0xFF47, R_RS232_BUF_CNT }, + { 0xFF48, R_RS232_BUF_OUT }, + { 0xFF49, R_RS232_BUF_IN }, + { 0xFF4B, R_CTRL_S_STAT }, + { 0xFF4C, R_UART_BAUD_TIMER_VAL }, + { 0xFF4E, R_RS232_PARITY_CTRL }, + { 0xFF4F, R_CAS_PULSE_CTRL }, + { 0xFF5B, R_KEY_SCAN_STORAGE1 }, + { 0xFF65, R_KEY_SCAN_STORAGE2 }, + { 0xFF66, R_SHIFT_KEY_STAT }, + { 0xFF67, R_KEY_REPT_START }, + { 0xFF69, R_KEY_POSITION }, + { 0xFF6B, R_2ND_KEY_BUF_PTR }, + { 0xFF6D, R_KEY_BUF_CNT }, + { 0xFF90, R_CURSOR_BIT_PAT_BUF }, + { -1, -1 } +}; + +Std_ROM_Addresses_t gM10_Funs[] = { + { 0x0000, R_RESET_VECTOR }, + { 0x0008, R_COMP_BYTE_M }, + { 0x0010, R_GET_NONWHITE }, + { 0x0018, R_COMP_DE_HL }, + { 0x001E, R_PRINT_SPACE }, + { 0x0020, R_PRINT_CHAR }, + { 0x0024, R_PWR_DOWN_TRAP }, + { 0x0028, R_DET_LAST_VAR_TYPE }, + { 0x002C, R_RST_5_5 }, + { 0x0030, R_GET_FAC1_SIGN }, + { 0x0034, R_RST_6_5 }, + { 0x0038, R_RAM_VCTR_TBL_DRIVER }, + { 0x003C, R_RST_7_5 }, + { 0x0040, R_FUN_VCTR_TBL }, + { 0x0080, R_BASIC_KEYWORD_TBL }, + { 0x018F, R_FUN_KEYWORD_TBL1 }, + { 0x01F0, R_FUN_KEYWORD_TBL2 }, + { 0x0262, R_BASIC_VECTOR_TBL }, + { 0x02E2, R_MATH_PRIORITY_TBL }, + { 0x02EE, R_MATH_VCTR_TBL }, + { 0x031C, R_BASIC_ERR_MSG_TXT }, + { 0x035A, R_FUN_INIT_IMAGE }, + { 0x036F, R_FUN_XROM_IMAGE }, + { 0x03F1, R_FUN_BASIC_STRINGS }, + { 0x0408, R_POP_FOR_NEXT }, + { 0x0429, R_INIT_AND_READY }, + { 0x044D, R_GEN_SN_ERROR }, + { 0x0450, R_GEN_d0_ERROR }, + { 0x0453, R_GEN_NF_ERROR }, + { 0x0456, R_GEN_DD_ERROR }, + { 0x0459, R_GEN_RW_ERROR }, + { 0x045C, R_GEN_OV_ERROR }, + { 0x045F, R_GEN_MO_ERROR }, + { 0x0462, R_GEN_TM_ERROR }, + { 0x0464, R_GEN_ERR_IN_E }, + { 0x0494, R_RESTORE_JMP_BC }, + { 0x04CC, R_PRINT_BASIC_ERR }, + { 0x0508, R_POP_GO_BASIC_RDY }, + { 0x0509, R_GO_BASIC_RDY_OK }, + { 0x0518, R_GO_BASIC_RDY }, + { 0x052A, R_PERFORM_M_GO_RDY }, + { 0x05F7, R_UPDATE_LINE_ADDR }, + { 0x0611, R_EVAL_LIST_ARGS }, + { 0x062F, R_FIND_LINE_IN_DE }, + { 0x0632, R_FIND_LINE_DE_AT_HL }, + { 0x064D, R_TOKEN_COMPRESS }, + { 0x072D, R_FOR_STMT }, + { 0x0772, R_TO_STMT }, + { 0x078A, R_STEP_STMT }, + { 0x080B, R_RUN_BASIC_PGRM }, + { 0x0841, R_RUN_BASIC_AT_HL }, + { 0x0847, R_EXEC_INST_IN_A }, + { 0x085F, R_RST_10H_INC_HL }, + { 0x0860, R_RST_10H }, + { 0x0879, R_DEF_STMT }, + { 0x0888, R_DEFDBL_STMT }, + { 0x088D, R_DEFINT_STMT }, + { 0x089D, R_DEFSNG_STMT }, + { 0x08A6, R_DEFSTR_STMT }, + { 0x08A8, R_DECL_VAR_TYPE_E }, + { 0x08E2, R_GEN_FC_ERROR }, + { 0x08E7, R_EVAL_LINE_NUM }, + { 0x08F2, R_ASCII_TO_BIN }, + { 0x08F3, R_ASCII_TO_BIN_PREINC }, + { 0x0916, R_RUN_STMT }, + { 0x0925, R_GOSUB_STMT }, + { 0x093D, R_GOTO_STMT }, + { 0x0954, R_GEN_UL_ERROR }, + { 0x096D, R_RETURN_STMT }, + { 0x09A5, R_DATA_STMT }, + { 0x09A7, R_REM_STMT }, + { 0x09CA, R_LET_STMT }, + { 0x0A36, R_ON_STMT }, + { 0x0A3B, R_ON_ERROR_STMT }, + { 0x0A62, R_ON_KEY_STMT }, + { 0x0A9B, R_ON_TIME_STMT }, + { 0x0AB7, R_RESUME_STMT }, + { 0x0B16, R_ERROR_STMT }, + { 0x0B21, R_IF_STMT }, + { 0x0B55, R_LPRINT_STMT }, + { 0x0B5D, R_PRINT_STMT }, + { 0x0C08, R_TAB_STMT }, + { 0x0C4C, R_LINE_STMT }, + { 0x0CA0, R_INPUT_NO_STMT }, + { 0x0CAA, R_INPUT_STMT }, + { 0x0CE0, R_READ_STMT }, + { 0x0DB2, R_EVAL_BASIC_INST }, + { 0x0F14, R_INT16_DIV }, + { 0x0F23, R_EVAL_FUN }, + { 0x0F4E, R_ERR_FUN }, + { 0x0F5D, R_ERL_FUN }, + { 0x0F85, R_VARPTR_FUN }, + { 0x0F8D, R_VARPTR_BUF_FUN }, + { 0x0F99, R_VARPTR_VAR_FUN }, + { 0x0FE1, R_EVAL_VAR }, + { 0x0FEF, R_CONV_M_TOUPPER }, + { 0x0FF0, R_CONV_A_TOUPPER }, + { 0x103E, R_ASCII_NUM_CONV }, + { 0x105B, R_NOT_FUN }, + { 0x1070, R_RST_28H }, + { 0x1093, R_OR_FUN }, + { 0x109E, R_AND_FUN }, + { 0x10A9, R_XOR_FUN }, + { 0x10B4, R_EQV_FUN }, + { 0x10BC, R_IMP_FUN }, + { 0x10CF, R_LPOS_FUN }, + { 0x10D5, R_POS_FUN }, + { 0x10D8, R_LD_FAC1_INT }, + { 0x10ED, R_CHK_RUNNING_PGRM }, + { 0x10F6, R_GEN_ID_ERROR }, + { 0x1107, R_INP_FUN }, + { 0x1113, R_OUT_STMT }, + { 0x1119, R_EVAL_EXPR }, + { 0x111A, R_EVAL_EXPR_PREDEC }, + { 0x1134, R_EVAL_EXPR }, + { 0x1135, R_EVAL_EXPR_PREDEC }, + { 0x1142, R_LLIST_STMT }, + { 0x1147, R_LIST_STMT }, + { 0x11A9, R_BUF_TO_LCD }, + { 0x128D, R_PEEK_FUN }, + { 0x1294, R_POKE_FUN }, + { 0x12A0, R_EVAL_EXPR }, + { 0x12CB, R_WAIT_KEY }, + { 0x13AE, R_TOGGLE_LABEL }, + { 0x13E4, R_CHK_KEY_QUEUE }, + { 0x1422, R_POWER_STMT }, + { 0x143F, R_LOW_PWR_TRAP }, + { 0x1450, R_POWER_DOWN }, + { 0x146D, R_POWER_CONT_STMT }, + { 0x1465, R_POWER_ON_STMT }, + { 0x1484, R_OUT_CH_TO_LPT }, + { 0x1496, R_LOAD_CAS_HDR }, + { 0x14A0, R_GEN_IO_ERROR }, + { 0x14A5, R_DET_CAS_SYNC_HDR }, + { 0x14B4, R_CAS_MOTOR_ON }, + { 0x14B6, R_CAS_MOTOR_OFF }, + { 0x14BC, R_CAS_READ_BYTE }, + { 0x14CD, R_CAS_WRITE_BYTE }, + { 0x14DD, R_LCD_DCB }, + { 0x14E3, R_LCD_OPEN }, + { 0x14F0, R_LCD_OUT }, + { 0x14ED, R_POP_ALL_REGS }, + { 0x14FD, R_CRT_DCB }, + { 0x1507, R_RAM_DCB }, + { 0x1511, R_RAM_OPEN }, + { 0x1598, R_RAM_CLOSE }, + { 0x15B7, R_RAM_OUT }, + { 0x15CF, R_RAM_IN }, + { 0x1626, R_RAM_IO }, + { 0x168A, R_CAS_DCB }, + { 0x1694, R_CAS_OPEN }, + { 0x16B8, R_CAS_CLOSE }, + { 0x16D2, R_CAS_OUT }, + { 0x16DD, R_CAS_IN }, + { 0x175F, R_LPT_DCB }, + { 0x1765, R_LPT_OUT }, + { 0x176D, R_COM_DCB }, +// { 0x1777, R_MDM_OPEN }, + { 0x1777, R_COM_OPEN }, + { 0x1792, R_COM_CLOSE }, + { 0x179C, R_COM_OUT }, + { 0x17A7, R_COM_IN }, + { 0x17C1, R_COM_IO }, +// { 0x17D1, R_MDM_DCB }, +// { 0x17DB, R_MDM_CLOSE }, + { 0x17C8, R_SET_RS232_PARAMS }, + { 0x1844, R_BCR_DCB }, + { 0x1856, R_EOF_FUN }, + { 0x18CC, R_TIME_FUN }, + { 0x18D7, R_READ_TIME }, + { 0x18F7, R_DATE_FUN }, + { 0x191F, R_DAY_FUN }, + { 0x192C, R_READ_DAY }, + { 0x196A, R_UPDATE_CLK_VALUES }, + { 0x1975, R_TIME_STMT }, + { 0x197D, R_UPDATE_CLK_CHIP }, + { 0x1987, R_DATE_STMT }, + { 0x19BD, R_DAY_STMT }, + { 0x1A0E, R_GET_TIME_STRING }, + { 0x1A44, R_IPL_STMT }, + { 0x1A62, R_ERASE_IPL_PRGM }, + { 0x1A6A, R_COM_MDM_STMT }, + { 0x1A7E, R_KEY_FUN }, + { 0x1A8F, R_KEY_ON_OFF_STMT }, + { 0x1AB6, R_DET_TIME_ARG }, + { 0x1AC8, R_DET_DEVICE_ARG }, + { 0x1AD8, R_ONTIME_STMT }, + { 0x1AEB, R_ONCOM_STMT }, + { 0x1AFB, R_RST7_5_ISR }, + { 0x1B7A, R_KICK_PWR_OFF_WDT }, + { 0x1B81, R_KEY_STMT }, + { 0x1B86, R_KEY_LIST_STMT }, + { 0x1BA9, R_SEND_CHARS_TO_LCD }, + { 0x1C20, R_PSET_STMT }, + { 0x1C2F, R_PRESET_STMT }, + { 0x1C36, R_LINE_STMT }, + { 0x1C6F, R_DRAW_FBOX }, + { 0x1C85, R_DRAW_BOX }, + { 0x1CF7, R_TOKENIZE_XY }, + { 0x1D59, R_CSRLIN_FUN }, + { 0x1D64, R_MAX_FUN }, + { 0x1D70, R_MAXRAM_FUN }, + { 0x1D7B, R_MAXFILES_FUN }, + { 0x1D82, R_HIMEM_FUN }, + { 0x1D8C, R_WIDTH_STMT }, + { 0x1D8E, R_SOUND_STMT }, + { 0x1DAE, R_SOUND_OFF_STMT }, + { 0x1DE6, R_SOUND_ON_STMT }, + { 0x1DB5, R_MOTOR_STMT }, + { 0x1DBA, R_MOTOR_ON_STMT }, + { 0x1DBE, R_MOTOR_OFF_STMT }, + { 0x1DC3, R_CALL_STMT }, + { 0x1DEB, R_SCREEN_STMT }, + { 0x1E29, R_LCOPY_STMT }, + { 0x1F07, R_FILES_STMT }, + { 0x1F0F, R_DISPLAY_CAT }, + { 0x1F63, R_KILL_STMT }, + { 0x1F8F, R_KILL_TEXT_FILE }, + { 0x2008, R_NAME_STMT }, + { 0x20CF, R_NEW_STMT }, + { 0x21D2, R_STRLEN }, + { 0x21DE, R_GET_FIND_DO_FILE }, + { 0x21E7, R_OPEN_TEXT_FILE }, + { 0x2258, R_CSAVE_STMT }, + { 0x2291, R_CAS_WRITE_BUF }, + { 0x22A4, R_SAVEM_STMT }, + { 0x22B5, R_CSAVEM_STMT }, + { 0x234F, R_CLOAD_STMT }, + { 0x23EB, R_CAS_READ_REC }, + { 0x2450, R_GEN_VERIFY_FAIL_ERR }, + { 0x2469, R_LOADM_STMT }, + { 0x247F, R_CLOADM_STMT }, + { 0x251A, R_MOVE_B_BYTES }, + { 0x2523, R_EXEC_CO_FILE }, + { 0x25E3, R_CAS_OPEN_OUT_BA }, + { 0x25E6, R_CAS_OPEN_OUT_DO }, + { 0x25E9, R_CAS_OPEN_OUT_CO }, + { 0x2628, R_CAS_OPEN_IN_BA }, + { 0x262B, R_CAS_OPEN_IN_DO }, + { 0x262E, R_CAS_OPEN_IN_CO }, + { 0x2713, R_STR_FUN }, + { 0x278A, R_PRINT_STRING }, + { 0x28E8, R_MOVE_L_BYTES }, + { 0x291C, R_LEN_FUN }, + { 0x2928, R_ASC_FUN }, + { 0x2938, R_CHR_FUN }, + { 0x2946, R_STRING_FUN }, + { 0x2967, R_SPACE_FUN }, + { 0x2984, R_LEFT_FUN }, + { 0x29B5, R_RIGHT_FUN }, + { 0x29BF, R_MID_FUN }, + { 0x29E0, R_VAL_FUN }, + { 0x2A10, R_INSTR_FUN }, + { 0x2B25, R_FRE_FUN }, + { 0x2B42, R_DBL_SUB }, + { 0x2B4E, R_DBL_ADD }, + { 0x2C28, R_BCD_ADD }, + { 0x2CD8, R_DBL_MULT }, + { 0x2DA0, R_DBL_DIV }, + { 0x2EBF, R_MOVE_C_BYTES }, + { 0x2EC8, R_COS_FUN }, + { 0x2EE2, R_SIN_FUN }, + { 0x2F31, R_TAN_FUN }, + { 0x2F4A, R_ATN_FUN }, + { 0x2FA8, R_LOG_FUN }, + { 0x3033, R_SQR_FUN }, + { 0x307D, R_EXP_FUN }, + { 0x3117, R_RND_FUN }, + { 0x315B, R_INIT_TEMP3 }, + { 0x3179, R_DBL_SQR }, + { 0x317C, R_MULT_M_FAC2 }, + { 0x318E, R_FAC2_EQ_FAC1 }, + { 0x3191, R_FAC2_EQ_FP }, + { 0x319A, R_FAC1_EQ_FAC2 }, + { 0x319D, R_FAC1_EQ_FP }, + { 0x31A3, R_M_EQ_FAC1 }, + { 0x31C4, R_MULT_FAC1_SQR_FAC1 }, +// { 0x31CA, R_SWAP_FAC1_FAC2 }, +// { 0x31E2, R_SQR_FAC1_MULT_TBL }, + { 0x31E2, R_TBL_BASED_MATH }, + { 0x3207, R_PUSH_FAC2 }, + { 0x320D, R_PUSH_FAC1 }, + { 0x321E, R_POP_FAC2 }, + { 0x3224, R_POP_FAC1 }, + { 0x3235, R_FP_NUMBERS }, + { 0x3255, R_FP_SHARED_NUMBERS }, + { 0x3257, R_FP_NUMBERS }, + { 0x32AF, R_EXP_MATH_TBL }, + { 0x32D0, R_EXP_MATH_TBL }, + { 0x32E0, R_LOG_MATH_TBL }, + { 0x330A, R_LOG_MATH_TBL }, + { 0x3333, R_SIN_MATH_TBL }, + { 0x3374, R_ATN_MATH_TBL }, + { 0x33B5, R_RST_30H_FUN }, + { 0x33CB, R_ABS_FUN }, + { 0x33E0, R_SGN_FUN }, + { 0x33FB, R_PUSH_SNGL_FAC1 }, + { 0x3408, R_SNGL_FAC1_EQ_M }, + { 0x340B, R_SNGL_FAC1_EQ_BCDE }, + { 0x3416, R_SNGL_BCDE_EQ_FAC1 }, + { 0x3420, R_SNGL_BCDE_EQ_M }, + { 0x3429, R_SNGL_DECB_EQ_M }, + { 0x3432, R_SNGL_M_EQ_FAC1 }, + { 0x343A, R_LOAD_FAC2_FROM_M }, + { 0x3442, R_MOVE_B_BYTES_INC }, + { 0x344B, R_MOVE_B_BYTES_DEC }, + { 0x3471, R_SNGL_CMP_BCDE_FAC1 }, + { 0x3489, R_SNGL_CMP_BCDE_M }, + { 0x349B, R_SINT_CMP }, + { 0x34D3, R_CMP_FAC1_FAC2 }, + { 0x34DA, R_CINT_FUN }, + { 0x34E9, R_FAC1_EQ_SINT_HL }, + { 0x3503, R_CSNG_FUN }, + { 0x3519, R_CONV_SINT_SNGL }, + { 0x351C, R_CONV_SINT_HL_SNGL }, + { 0x3593, R_CDBL_FUN }, + { 0x35D1, R_SINT_SUB }, + { 0x361E, R_FIX_FUN }, + { 0x362D, R_INT_FUN }, + { 0x36DD, R_SINT_ADD }, + { 0x36FE, R_SINT_MULT }, + { 0x3757, R_SINT_DIV }, + { 0x37CD, R_SNGL_ADD_BCDE }, + { 0x37D0, R_SNGL_ADD_FAC2 }, + { 0x37D6, R_SNGL_SUB }, + { 0x37DC, R_SNGL_MULT_BCDE }, + { 0x37DF, R_SNGL_MULT_FAC2 }, + { 0x37E7, R_SNGL_DIV }, + { 0x3800, R_SNGL_LOAD }, + { 0x3819, R_ASCII_TO_DBL }, + { 0x3840, R_ASCII_FND_e }, + { 0x3863, R_ASCII_FND_E }, + { 0x38DD, R_ASCII_FND_DOT }, + { 0x38F3, R_ASCII_FND_PERC }, + { 0x3902, R_ASCII_FND_LB }, + { 0x390A, R_ASCII_CONV_HELPER }, + { 0x3919, R_ASCII_CONV_HELPER2 }, + { 0x39A5, R_PRNT_BASIC_ERR_TERM }, + { 0x39AD, R_PRINT_HL_ON_LCD }, + { 0x39C1, R_PRINT_FAC1 }, + { 0x39C5, R_PRINT_FAC1_FORMAT }, + { 0x3CEA, R_FAC1_EQ_ZERO }, + { 0x3D58, R_SNGL_EXP }, + { 0x3D67, R_DBL_EXP }, + { 0x3DD0, R_INT_EXP }, + { 0x3F04, R_INIT_BASIC_VARS }, + { 0x3F7C, R_TIME_ON_STMT }, + { 0x3F8E, R_TIME_OFF_STMT }, + { 0x3F95, R_TIME_STOP_STMT }, + { 0x3FAE, R_TRIG_INTR }, + { 0x3FCD, R_CLEAR_INTR }, + { 0x3FE5, R_CLEAR_COM_INT_DEF }, + { 0x405B, R_RESTORE_STMT }, + { 0x4076, R_STOP_STMT }, + { 0x407B, R_END_STMT }, + { 0x40B6, R_CONT_STMT }, + { 0x40CD, R_ISALPHA_M }, + { 0x40CE, R_ISALPHA_A }, + { 0x40D5, R_CLEAR_STMT }, + { 0x4150, R_NEXT_STMT }, + { 0x41FE, R_SEND_CRLF }, + { 0x4201, R_SEND_LF }, + { 0x4205, R_BEEP_STMT }, + { 0x4209, R_HOME_CURSOR }, + { 0x420D, R_CLS_STMT }, + { 0x4211, R_PROTECT_LABEL }, + { 0x4216, R_UNPROT_LABEL }, + { 0x421B, R_STOP_AUTO_SCROLL }, + { 0x4220, R_RESUME_AUTO_SCROLL }, + { 0x4225, R_TURN_CURSOR_ON }, + { 0x422A, R_TURN_CURSOR_OFF }, + { 0x422F, R_DEL_CUR_LINE }, + { 0x4234, R_INSERT_LINE }, + { 0x4239, R_ERASE_TO_EOL }, + { 0x423E, R_SEND_ESC_X }, + { 0x4245, R_INV_CHAR_ENABLE }, + { 0x424A, R_INV_CHAR_DISABLE }, + { 0x424C, R_END_ESC_SEQ }, + { 0x4253, R_CURSOR_TO_LOW_LEFT }, + { 0x4258, R_SET_CURSOR_POS }, + { 0x4266, R_ERASE_FKEY_DISP }, + { 0x4281, R_SET_DISP_FKEY }, + { 0x4284, R_DISP_FKEY_LINE }, + { 0x42ED, R_PRINT_A_TO_LCD }, +// { 0x4431, R_CHAR_PLOT_3 }, + { 0x430A, R_CHAR_PLOT_4 }, + { 0x431F, R_CHAR_PLOT_5 }, + { 0x4353, R_LCD_OUT_DRIVER }, + { 0x436A, R_RST_20H_LKUP_TBL }, + { 0x438F, R_ESC_Y }, + { 0x4392, R_LCD_OUT_ESC_FUN }, + { 0x4398, R_LCD_ESC_LKUP_TBL }, + { 0x43DA, R_ESC_SEQ_DRIVER }, + { 0x4411, R_ESC_p_FUN }, + { 0x4412, R_ESC_q_FUN }, + { 0x4417, R_ESC_U_FUN }, + { 0x4419, R_ESC_T_FUN }, + { 0x441B, R_ESC_X_FUN }, + { 0x441F, R_ESC_V_FUN }, + { 0x4420, R_ESC_W_FUN }, + { 0x4433, R_ESC_C_FUN }, + { 0x443C, R_ESC_D_FUN }, + { 0x4441, R_BKSPACE_FUN }, + { 0x4449, R_ESC_A_FUN }, + { 0x444E, R_ESC_B_FUN }, + { 0x4460, R_TAB_FUN }, +// { 0x4494, R_LF_FUN }, + { 0x4476, R_ESC_H_FUN }, + { 0x4478, R_CR_FUN }, +// { 0x44AF, R_ESC_P_FUN }, +// { 0x44BA, R_ESC_Q_FUN }, + { 0x448E, R_ESC_M_FUN }, + { 0x449C, R_LCD_SCROLL }, + { 0x44B4, R_ESC_L_FUN }, + { 0x44DC, R_GET_LCD_CHAR }, + { 0x45F5, R_ESC_l_FUN }, + { 0x45F7, R_ESC_K_FUN }, + { 0x4505, R_CLS_FUN }, + { 0x450B, R_ESC_J_FUN }, + { 0x451D, R_CHAR_PLOT_6 }, + { 0x45F2, R_INP_DISP_LINE }, + { 0x45F8, R_INP_DISP_LINE_NO_Q }, + { 0x4638, R_INP_CTRL_C_HANDLER }, + { 0x464B, R_INP_ENTER_HANDLER }, + { 0x4657, R_INP_BKSP_HANDLER }, + { 0x467A, R_INP_CTRL_U_HANDLER }, + { 0x4681, R_INP_TAB_HANDLER }, + { 0x4741, R_DIM_STMT }, + { 0x4746, R_FIND_VAR_ADDR }, + { 0x495F, R_USING_FUN }, + { 0x4B12, R_SEND_A_LCD_LPT }, + { 0x4B23, R_PRINT_A_EXPAND }, + { 0x4B65, R_SET_OUT_DEV_LCD }, + { 0x4B79, R_LCD_CHAR_OUT_FUN }, + { 0x4B86, R_LCD_NEW_LINE }, + { 0x4BB8, R_INKEY_FUN }, + { 0x4C52, R_GET_FILE_DESC }, + { 0x4C99, R_OPEN_STMT }, + { 0x4D27, R_LCD_CLOSE_FUN }, + { 0x4D3C, R_RUN_STMT }, + { 0x4D3E, R_LOAD_STMT }, + { 0x4D3F, R_MERGE_STMT }, + { 0x4D9D, R_SAVE_STMT }, + { 0x4DF6, R_CLOSE_STMT }, + { 0x4E5A, R_INPUT_STMT }, + { 0x4ED1, R_CLEAR_MEM }, + { 0x4ED2, R_LOAD_MEM }, + { 0x4EF5, R_PRINT_LB_INIT_FUN }, + { 0x4F22, R_LINE_INPUT_STMT }, + { 0x5015, R_GEN_NM_ERR_FUN }, + { 0x5018, R_GEN_AO_ERR_FUN }, + { 0x501B, R_GEN_DS_ERR_FUN }, + { 0x501E, R_GEN_FF_ERR_FUN }, + { 0x5021, R_GEN_CF_ERR_FUN }, + { 0x5024, R_GEN_BN_ERR_FUN }, + { 0x5027, R_GEN_IE_ERR_FUN }, + { 0x502A, R_GEN_EF_ERR_FUN }, + { 0x502D, R_GEN_FL_ERR_FUN }, + { 0x5032, R_LOF_FUN }, + { 0x5034, R_LOC_FUN }, + { 0x5036, R_LFILES_FUN }, + { 0x5038, R_DSKO_FUN }, + { 0x503A, R_DSKI_FUN }, + { 0x50B8, R_DEV_NAME_TBL }, + { 0x50D6, R_DCB_VCTR_TBL }, + { 0x5109, R_TELCOM_ENTRY }, + { 0x5120, R_TELCOM_RE_ENTRY }, + { 0x514C, R_TELCOM_INST_VCTR_TBL }, + { 0x515F, R_TELCOM_LABEL_TXT }, + { 0x5173, R_TELCOM_STAT_FUN }, + { 0x5179, R_PRINT_TELCOM_STAT }, + { 0x51ED, R_SET_TELCOM_STAT }, + +/* { 0x522F, R_TELCOM_CALL_FUN }, + { 0x524D, R_TELCOM_FIND_FUN }, + { 0x52B4, R_GO_OFFHOOK }, + { 0x52BB, R_DISCONNECT_PHONE }, + { 0x52D0, R_CONNECT_PHONE }, + { 0x52E4, R_GO_OFFHOOK_WAIT }, + { 0x5310, R_TELCOM_PAUSE }, + { 0x532D, R_EXEC_LOGON_SEQ }, + { 0x5359, R_DIALING_FUN }, + { 0x539E, R_AUTO_LOGIN_SEQ }, + { 0x540A, R_DIAL_DIGIT }, */ + { 0x51A5, R_TELCOM_TERM_FUN }, + { 0x5244, R_TELCOM_DISPATCH }, + { 0x5255, R_TERM_FKEY_VCTR_TBL }, + { 0x526B, R_TELCOM_PREV_FUN }, + { 0x5286, R_TELCOM_FULL_FUN }, + { 0x52AA, R_TELCOM_ECHO_FUN }, + { 0x52E5, R_TELCOM_UP_FUN }, + { 0x53C7, R_TELCOM_DOWN_FUN }, + { 0x5467, R_TELCOM_BYE_FUN }, + { 0x54B6, R_PRINT_STRING }, + { 0x54BC, R_MENU_ENTRY }, + { 0x551D, R_DISP_DIR }, + { 0x555C, R_MENU_CTRL_U_HANDLER }, + { 0x557F, R_MENU_CMD_LOOP }, + { 0x55B3, R_MENU_BKSP_HANDLER }, + { 0x561C, R_MENU_ENTER_HANDLER }, + { 0x5694, R_EXEC_ROM_FILE }, + { 0x5695, R_DISP_DIR_TYPE_C }, + { 0x56D2, R_CONV_FILENAME }, + { 0x56EE, R_NEXT_DIR_ENTRY }, + { 0x5734, R_CLS_PRINT_TIME_DAY }, + { 0x5737, R_PRINT_TIME_DAY }, + { 0x577B, R_PRINT_STRING2 }, + { 0x5785, R_COPY_MEM_DE_M }, + { 0x5790, R_CMP_MEM_DE_M }, + { 0x579C, R_CLEAR_FKEY_TBL }, + { 0x579F, R_SET_FKEYS }, + { 0x57C1, R_DISP_FKEYS }, + { 0x57CC, R_SEARCH_DIR }, + { 0x5806, R_GET_FILE_ADDR }, + { 0x5841, R_DIR_DISP_ORDER_TBL }, + { 0x588B, R_ADDRSS_ENTRY }, + { 0x588E, R_ADDRSS_ENTRY_W_FILE }, + { 0x5892, R_SCHEDL_ENTRY }, + { 0x5895, R_SCHEDL_ENTRY_W_FILE }, + { 0x5918, R_ADDRSS_FIND_FUN }, + { 0x591A, R_ADDRSS_LFND_FUN }, + { 0x5962, R_FIND_TEXT_IN_FILE }, + { 0x5990, R_FIND_NEXT_LINE_IN_FILE }, + { 0x5997, R_CHECK_FOR_CRLF }, +// { 0x5CEF, R_ADDRSS_INST_VCTR_TBL }, + { 0x5A84, R_GET_KEY_CONV_TOUPPER }, + { 0x5A8A, R_SEND_CURSOR_HOME }, + { 0x5A90, R_PRINT_TIME_LOOP }, + { 0x5B0E, R_TEXT_ENTRY }, + { 0x5B42, R_TEXT_FKEY_TBL }, + { 0x5B71, R_EDIT_STMT }, + { 0x5C4F, R_WAIT_FOR_SPACE_KEY }, + { 0x5C85, R_EDIT_DO_FILE_FUN }, + { 0x5CFD, R_TEXT_EDIT_LOOP }, + { 0x5D36, R_TEXT_CTRL_VCTR_TBL }, + { 0x5D76, R_TEXT_ESC_FUN }, + { 0x5D9C, R_TEXT_CTRL_P_FUN }, + { 0x5DAA, R_TEXT_CTRL_I_FUN }, + { 0x5DDE, R_TEXT_CTRL_M_FUN }, + { 0x5DFE, R_TEXT_CTRL_D_FUN }, + { 0x5E02, R_TEXT_CTRL_X_FUN }, + { 0x5E2B, R_TEXT_CTRL_H_FUN }, + { 0x5E71, R_TEXT_CTRL_S_FUN }, + { 0x5E75, R_TEXT_CTRL_E_FUN }, + { 0x5E9A, R_TEXT_CTRL_F_FUN }, + { 0x5EAC, R_TEXT_CTRL_A_FUN }, + { 0x5EE2, R_TEXT_CTRL_T_FUN }, + { 0x5EF7, R_TEXT_CTRL_B_FUN }, + { 0x5F1D, R_TEXT_CTRL_R_FUN }, +// { 0x5F30, R_TEXT_CTRL_Q_FUN }, + { 0x5F30, R_TEXT_CTRL_W_FUN }, + { 0x5F3C, R_TEXT_CTRL_Z_FUN }, + { 0x5F62, R_TEXT_CTRL_L_FUN }, + { 0x5FAF, R_TEXT_CTRL_C_FUN }, + { 0x6105, R_TEXT_GET_NEXT_BYTE }, + { 0x6151, R_TEXT_CTRL_O_FUN }, + { 0x6165, R_TEXT_CTRL_U_FUN }, + { 0x6271, R_TEXT_CTRL_N_FUN }, + { 0x62E3, R_COPY_NULL_STRING }, + { 0x63B1, R_TEXT_CTRL_Y_FUN }, + { 0x6433, R_TEXT_CTRL_G_FUN }, + { 0x6494, R_TEXT_CTRL_V_FUN }, + { 0x6881, R_INSERT_A_INTO_FILE }, + { 0x688D, R_INSERT_SPACES }, + { 0x68BF, R_DELETE_CHARS }, + { 0x68FB, R_MOVE_BC_BYTES_INC }, + { 0x6906, R_MOVE_BC_BYTES_DEC }, + { 0x6911, R_ROM_CAT_ENTRIES }, + { 0x6969, R_BASIC_ENTRY }, + { 0x69B3, R_LOAD_BASIC_FKEYS }, + { 0x69BC, R_LOAD_BASIC_FKEYS }, + { 0x69F6, R_RE_INIT_SYSTEM }, + { 0x6A10, R_WARM_RESET }, + { 0x6A6D, R_SEND_A_TO_LPT }, + { 0x6A9D, R_CHECK_RS232_QUEUE }, + { 0x6AAE, R_READ_RS232_QUEUE }, + { 0x6ADC, R_RST_6_5_FUN }, + { 0x6B2C, R_INC_RS232_QUEUE_IN }, + { 0x6B3B, R_SEND_XON }, + { 0x6B4E, R_DISABLE_XON_XOFF }, + { 0x6B62, R_SEND_A_USING_XON }, + { 0x6B6D, R_SEND_C_TO_RS232 }, + { 0x6B8F, R_XON_XOFF_HANDLER }, + { 0x6BB7, R_SET_RS232_BAUD_RATE }, + { 0x6BD6, R_RS232_BAUD_TIMER_VALS }, + { 0x6BE8, R_INIT_RS232_MDM }, + { 0x6C25, R_UNINIT_RS232_MDM }, +/* { 0x6EE5, R_CLICK_SND_PORT }, + { 0x6EEF, R_CHECK_CD }, */ + { 0x6C0D, R_ENABLE_XON_XOFF }, + { 0x6C15, R_INIT_SER_BUF_PARAMS }, + { 0x6C30, R_CAS_WRITE_HEADER }, + { 0x6C45, R_CAS_WRITE_NO_CHKSUM }, + { 0x6C54, R_CAS_WRITE_BIT }, + { 0x6C6F, R_CAS_READ_HEADER }, + { 0x6CC5, R_CAS_READ_BIT }, + { 0x6D0D, R_CAS_COUNT_BITS }, + { 0x6D14, R_CAS_READ_NO_CHKSUM }, + { 0x6D2D, R_CAS_REMOTE_FUN }, + { 0x6D3F, R_KEYSCAN_MGT_FUN }, + { 0x6D4A, R_KEY_DETECTION }, + { 0x6DA9, R_KEY_REPEAT_DET }, +// { 0x70B0, R_GET_KEY_MATRIX }, +// { 0x7122, R_INIT_KEY_RPT_CNT }, + { 0x6E1D, R_KEY_DECODE }, + { 0x6EE3, R_KEY_FIRST_IN_BUF }, + { 0x6EF2, R_KEY_ADD_TO_BUF }, + { 0x6F02, R_ISR_EXIT_FUN }, + { 0x6F15, R_UNSHIFTED_KEY }, +/* { 0x7222, R_ARROW_KEY }, + { 0x722C, R_CAPS_LOCK_KEY }, + { 0x7233, R_NUM_KEY }, */ + { 0x6F2E, R_SCAN_KEYBOARD }, + { 0x6F5A, R_ENABLE_INTERRUPTS }, + { 0x6F60, R_CHK_PENDING_KEYS }, + { 0x6F73, R_CHK_BREAK }, + { 0x6F8F, R_CHK_SHIFT_BREAK }, + { 0x6FA1, R_SCAN_SPECIAL_KEYS }, + { 0x6FB4, R_GEN_TONE }, + { 0x7018, R_GET_CLK_CHIP_REGS }, +// { 0x7041, R_PUT_CLK_CHIP_REGS }, + { 0x7041, R_READ_CLK_CHIP_BIT }, + { 0x7072, R_SET_CLK_CHIP_MODE }, + { 0x7098, R_BLINK_CURSOR }, + { 0x70DD, R_CHAR_PLOT_7 }, + { 0x7166, R_PLOT_POINT }, + { 0x7167, R_CLEAR_POINT }, + { 0x71BC, R_LCD_BYTE_PLOT }, + { 0x7255, R_ENABLE_LCD_DRIVER }, + { 0x7262, R_WAIT_LCD_DRIVER }, + { 0x726B, R_LCD_BIT_PATTERNS }, + { 0x735D, R_LCD_BIT_PATTERNS }, + { 0x7371, R_DELAY_FUN }, + { 0x7376, R_SET_INTR_1DH }, + { 0x737C, R_BEEP_FUN }, + { 0x7390, R_CLICK_SOUND_PORT }, + { 0x739C, R_CHK_XTRNL_CNTRLER }, + { 0x73A9, R_XTRNL_CNTRLER_DRIVER }, + { 0x742B, R_LCD_CHAR_SHAPE_TBL1 }, + { 0x760B, R_LCD_CHAR_SHAPE_TBL2 }, + { 0x790B, R_KEYBOARD_CONV_MATRIX }, + { 0x7A23, R_BOOT_ROUTINE }, + { 0x7ADE, R_COLD_BOOT }, + { 0x7B98, R_DISP_MODEL }, + { 0x7B9E, R_DISP_FREE_BYTES }, + { 0x7BB8, R_INIT_RST_38H_TBL }, + { 0x7BD3, R_CALC_FREE_RAM }, + { 0x7BF3, R_INIT_CLK_CHIP_REGS }, + { 0x7C8A, R_MENU_TEXT_STRINGS }, + { 0x7CC3, R_RST_38H_DRIVER }, + { 0xF5F9, R_RST_5_5_VECTOR }, + { 0xF5FC, R_RST_6_5_VECTOR }, + { 0xF5FF, R_RST_7_5_VECTOR }, + { 0xF602, R_TRAP_VECTOR }, + { 0xF605, R_DETECT_OPTION_ROM }, + { -1, -1 } +}; + +RomDescription_t gM10_Desc = { + 0x3C003845, /* Signature */ + 0x7A20, /* Signature address */ + 1, /* StdRom */ + + gM10_Tables, /* Known tables */ + gM10_Vars, /* Known variables */ + gM10_Funs, /* Known functions */ + + 0xF9A1, /* Address of unsaved BASIC prgm */ + 0xF9AC, /* Address of next DO file */ + 0xFBC0, /* Start of DO file area */ + 0xFBC2, /* Start of CO file area */ + 0xFBC4, /* Start of Variable space */ + 0xFBC6, /* Start of Array data */ + 0xFBC8, /* Pointer to unused memory */ + 0xF5F4, /* Address where HIMEM is stored */ + 0xF893, /* End of RAM for file storage */ + 0xFAC7, /* Lowest RAM used by system */ + 0xF969, /* Start of RAM directory */ + 0xF67F, /* BASIC string buffer pointer */ + 0xFADE, /* BASIC Size */ + 0xFF5C, /* Keyscan array */ + 0x742B, /* Character generator table */ + + 24, /* Number of directory entries */ + 8, /* Index of first Dir entry */ + 0x5830 /* Address of MS Copyright string */ +}; + + diff --git a/src/m200rom.c b/src/m200rom.c index 17b48aa..b1b2cec 100644 --- a/src/m200rom.c +++ b/src/m200rom.c @@ -983,8 +983,11 @@ RomDescription_t gM200_Desc = { 0xF252, /* Start of RAM directory */ 0xEF63, /* BASIC string buffer pointer */ 0xF505, /* BASIC size */ + 0xFD0E, /* Keyscan array */ + 0x9063, /* Character generator array */ 52, /* Number of directory entries */ - 9 /* Index of first dir entry */ + 9, /* Index of first dir entry */ + 0x6803 /* Address of MS Copyright string */ }; diff --git a/src/memedit.cpp b/src/memedit.cpp index e1b974a..6f3b835 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -120,7 +120,7 @@ Fl_Menu_Item gMemEdit_menuitems[] = { { "Assembler / IDE", 0, cb_Ide }, { "Disassembler", 0, disassembler_cb }, { "Peripheral Devices", 0, cb_PeripheralDevices }, - { "Simulation Log Viewer", 0, 0 }, +// { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, 0 }, { 0 }, @@ -867,6 +867,7 @@ void T100_MemEditor::SetRegionOptions(void) { case MODEL_M100: case MODEL_M102: + case MODEL_M10: memedit_ctrl.pRegion->add("RAM"); memedit_ctrl.pRegion->add("ROM"); memedit_ctrl.pRegion->add("Opt ROM"); @@ -916,6 +917,7 @@ void T100_MemEditor::SetScrollSize(void) switch (gModel) { case MODEL_M100: + case MODEL_M10: case MODEL_M102: case MODEL_PC8201: if (region == 0) diff --git a/src/memory.c b/src/memory.c index a6f94c3..c1bfde0 100644 --- a/src/memory.c +++ b/src/memory.c @@ -10,6 +10,7 @@ memory.c ============================================================================ */ +#include #include #include #include @@ -17,10 +18,12 @@ memory.c #include "VirtualT.h" #include "m100emu.h" #include "memory.h" +#include "display.h" #include "cpu.h" #include "io.h" #include "intelhex.h" #include "setup.h" +#include "filewrap.h" uchar *gMemory[64]; /* CPU Memory space */ uchar gBaseMemory[65536]; /* System Memory */ @@ -61,6 +64,11 @@ unsigned char *gRampacSaveSectPtr = 0;/* Pointer to current Sector memory */ int gIndex[65536]; +extern RomDescription_t gM100_Desc; +extern RomDescription_t gM200_Desc; +extern RomDescription_t gN8201_Desc; +extern RomDescription_t gM10_Desc; +extern int gShowVersion; unsigned char get_memory8(unsigned short address) { @@ -429,7 +437,7 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) for (cp_ptr = 0; cp_ptr < count; cp_ptr++) { /* Determine if address is part of MMU */ - if ((addr >= REMEM_MAP_OFFSET) && (addr <= (REMEM_MAP_OFFSET + REMEM_MAP_SIZE * 8))) + if ((addr >= REMEM_MAP_OFFSET) && (addr < (REMEM_MAP_OFFSET + REMEM_MAP_SIZE * 8))) /* Indiacte possible map chage */ map_changed = 1; @@ -734,11 +742,15 @@ void save_ram(void) switch (gModel) { case MODEL_M100: /* M100 & M102 have single bank */ + case MODEL_M10: /* M100 & M102 have single bank */ case MODEL_M102: fwrite(gBaseMemory+RAMSTART, 1, RAMSIZE, fd); break; case MODEL_T200: + /* Copy base memory to rambanks */ + set_ram_bank(gRamBank); + /* Save RAM */ fwrite(rambanks, 1, 3*RAMSIZE, fd); @@ -749,6 +761,9 @@ void save_ram(void) case MODEL_PC8201: case MODEL_PC8300: + /* Copy base memory to rambanks */ + set_ram_bank(gRamBank); + /* Save RAM */ fwrite(rambanks, 1, 3*RAMSIZE, fd); @@ -822,8 +837,17 @@ void load_remem_ram(void) } /* Initalize MsplanROM area */ - for (x = 0; x < sizeof(gMsplanROM); x++) - gReMemFlash1[0x10000 + x] = gMsplanROM[x]; + if (gModel == MODEL_T200) + for (x = 0; x < sizeof(gMsplanROM); x++) + gReMemFlash1[0x10000 + x] = gMsplanROM[x]; +} + +void reload_sys_rom(void) +{ + int x; + + for (x = 0; x < ROMSIZE; x++) + gReMemFlash1[x] = gSysROM[x]; } /* @@ -898,6 +922,7 @@ void load_ram(void) switch (gModel) { case MODEL_M100: /* M100 & M102 have single bank */ + case MODEL_M10: /* M100 & M102 have single bank */ case MODEL_M102: fread(gBaseMemory+RAMSTART, 1, RAMSIZE, fd); break; @@ -960,6 +985,100 @@ void load_ram(void) } } +/* +============================================================================= +load_opt_rom: This function loads option ROMS as specified by user settings. +============================================================================= +*/ +void load_sys_rom(void) +{ + int fd; + unsigned short address; + char oldString[15]; + char newString[40]; + int c, srchLen, strLen; + + /* Get Path to ROM based on current Model selection */ + get_rom_path(file, gModel); + + /* Open the ROM file */ + fd = open(file,O_RDONLY | O_BINARY); + if (fd < 0) + { + show_error("Could not open ROM file"); + } + + gRomSize = gModel == MODEL_T200 ? 40960 : 32768; + + /* Read data from the ROM file */ + if (read(fd, gSysROM, ROMSIZE)sMSCopyright; + + /* Check if the copyright string is where we expect it to be */ + if (strncmp(&gSysROM[address], oldString, strlen(oldString)) != 0) + { + /* Okay, the copyright string has been moved (by the user?) Find it */ + address = 0; + srchLen = ROMSIZE-strlen(oldString)-1; + strLen = strlen(oldString); + + for (c = 0; c < srchLen; c++) + { + if (strncmp(&gSysROM[c], oldString, strLen) == 0) + { + address = (unsigned short) c; + break; + } + } + } + + /* If the address is good, update the ROM */ + if (address != 0) + strcpy(&gSysROM[address], newString); + } + + /* Copy ROM into system memory */ + memcpy(gBaseMemory, gSysROM, ROMSIZE); +} /* ============================================================================= load_opt_rom: This function loads option ROMS as specified by user settings. @@ -999,10 +1118,10 @@ void load_opt_rom(void) { if (gModel == MODEL_T200) for (c = 0; c < len; c++) - gReMemFlash1[0x20000 + c] = buf[c]; + gReMemFlash1[0x18000 + c] = buf[c]; else for (c = 0; c < len; c++) - gReMemFlash1[0x10000 + c] = buf[c]; + gReMemFlash1[0x8000 + c] = buf[c]; } } @@ -1020,10 +1139,10 @@ void load_opt_rom(void) { if (gModel == MODEL_T200) for (c = 0; c < OPTROMSIZE; c++) - gReMemFlash1[0x20000 + c] = gOptROM[c]; + gReMemFlash1[0x18000 + c] = gOptROM[c]; else for (c = 0; c < OPTROMSIZE; c++) - gReMemFlash1[0x10000 + c] = gOptROM[c]; + gReMemFlash1[0x8000 + c] = gOptROM[c]; } } } @@ -1078,6 +1197,26 @@ void set_ram_bank(unsigned char bank) } } +/* +============================================================================= +get_ram_bank: This function gets the current RAM bank. +============================================================================= +*/ +unsigned char get_ram_bank(void) +{ + return gRamBank; +} + +/* +============================================================================= +get_rom_bank: This function gets the current ROM bank. +============================================================================= +*/ +unsigned char get_rom_bank(void) +{ + return gRomBank; +} + /* ============================================================================= set_rom_bank: This function sets the current ROM bank for all models. It @@ -1196,26 +1335,22 @@ void remem_set8(unsigned int address, unsigned char data) int ramBank; /* The currently mapped ramBank within the Map */ /* Calculate which block is being accessed */ -// block = address >> 10; block = gIndex[address]; /* Test if ReMem memory block is read-only */ if ((gReMemMode & REMEM_MODE_NORMAL) && (gReMemMap[block] & REMEM_VCTR_READ_ONLY)) return; + /* Test if ReMem is in Normal mode and writing to ROM */ + if (!(gReMemMode & REMEM_MODE_NORMAL) && (address < (unsigned int) ROMSIZE)) + return; + /* Test if accessing MMU vector for current map */ if (gReMemMap[block] & REMEM_VCTR_MMU_ACTIVE) { /* Need to validate that address is accssing active portion of MMU page */ if (((address & 0x3FF) >= gReMemMapLower) && ((address & 0x3FF) < gReMemMapUpper)) { - /* System is making a change to the active MAP!! Now we need to determine if */ - /* The portion of the map being modified is selected by the current ROM/RAM */ - /* bank settings */ - bank = block / REMEM_BANK_SIZE; - romBank = gModel == MODEL_T200 ? gRomBank : gRomBank << 1; - ramBank = gModel == MODEL_T200 ? gRamBank : 1; - /* First validate that the data is actually changing */ if (gMemory[block][address&0x3FF] == data) return; @@ -1223,12 +1358,21 @@ void remem_set8(unsigned int address, unsigned char data) /* Okay, data is really changing first update system memory */ gMemory[block][address&0x3FF] = data; + /* System is making a change to the active MAP!! Now we need to determine if */ + /* The portion of the map being modified is selected by the current ROM/RAM */ + /* bank settings */ + bank = ((address & 0x3FF) - gReMemMapLower) / REMEM_SECTOR_SIZE; + romBank = gModel == MODEL_T200 ? gRomBank : gRomBank << 1; + ramBank = gModel == MODEL_T200 ? gRamBank : 1; + /* Determine if the change was made in a mapped bank ROM or RAM */ if ((bank != romBank) && (bank != ramBank)) return; /* Determine which map entry was modified */ - mmuBlock = ((address & 0x3FF) - gReMemMapLower - (bank * REMEM_BANK_SIZE)) >> 1; + mmuBlock = ((address & 0x3FF) - gReMemMapLower - (bank * REMEM_SECTOR_SIZE)) >> 1; + if ((gModel != MODEL_T200) && (bank == 1)) + mmuBlock += 32; /* Update the gReMemMap vector table for this block */ if (address & 0x01) @@ -1257,7 +1401,6 @@ remem_in: This function services in operations to the ReMem emulation. int remem_in(unsigned char port, unsigned char *data) { int ret = 0; /* Indicate if port serviced or not */ - int map; /* Test if ReMem emulation is enabled */ if (!(gReMem | gRampac) || (gReMemRam == 0)) @@ -1288,17 +1431,14 @@ int remem_in(unsigned char port, unsigned char *data) *data = *gReMemSectPtr++; /* Get data at current Sector Pointer */ /* Update the ReMem Counter and Sector */ gReMemCounter++; /* Increment Sector Counter */ - if (gReMemCounter >= REMEM_BANK_SIZE) + if (gReMemCounter >= REMEM_SECTOR_SIZE) { - /* Get the map number */ - map = (gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT; - gReMemSector++; /* Increment to next sector */ - if (gReMemSector >= REMEM_BLOCKS_PER_BANK) + if (gReMemSector >= REMEM_TOTAL_SECTORS) gReMemSector = 0; gReMemCounter = 0; /* Clear sector counter */ gReMemSectPtr = (unsigned char *) (gReMemRam + REMEM_MAP_OFFSET + - map * REMEM_MAP_SIZE + gReMemSector * REMEM_BANK_SIZE); + gReMemSector * REMEM_SECTOR_SIZE); } } else @@ -1458,12 +1598,9 @@ int remem_out(unsigned char port, unsigned char data) gReMemSector = data; /* Update Sector number */ gReMemCounter = 0; /* Clear the ReMem counter */ - /* Get the map number */ - map = (gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT; - /* Calculate pointer to actual RAM storage for this sector */ gReMemSectPtr = (unsigned char *) (gReMemRam + REMEM_MAP_OFFSET + - map * REMEM_MAP_SIZE + gReMemSector * REMEM_BANK_SIZE); + gReMemSector * REMEM_SECTOR_SIZE); } ret = 1; break; @@ -1471,85 +1608,93 @@ int remem_out(unsigned char port, unsigned char data) /* ReMem port for writing vector data */ case REMEM_DATA_PORT: /* First check if RamPac Mode enabled */ - if (gReMemMode & REMEM_MODE_IOENABLE) - { - /* Calculate ReMem Vector block based on current ReMemCounter */ - block = (gReMemCounter >> 1) + gReMemSector * REMEM_BLOCKS_PER_BANK; + ret = 1; + if (!(gReMemMode & REMEM_MODE_IOENABLE)) + break; - /* Check if MMU mode is enabled. If it is, we may need to dynamically */ - /* load and unload blocks from system memory to ReMem Memory as a */ - /* Result of the I/O update */ - if (gReMemMode & REMEM_MODE_NORMAL) - { - /* MMU mode is enabled - Test if update changes mapped block */ - /* Calculate current MMU ROM bank */ - bank = gModel == MODEL_T200 ? gRomBank : gRomBank << 1; + /* Check if MMU mode is enabled. If it is, we may need to dynamically */ + /* load and unload blocks from system memory to ReMem Memory as a */ + /* Result of the I/O update */ + if (gReMemMode & REMEM_MODE_NORMAL) + { + /* MMU mode is enabled - Test if update changes mapped block */ - /* Convert current MMU map / ROM bank to sector format */ - romSector = ((gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT) * - REMEM_BANKS_PER_MAP + bank; + /* Calculate current MMU ROM bank */ + bank = gModel == MODEL_T200 ? gRomBank : gRomBank << 1; - /* Calculate current MMU RAM bank */ - bank = gModel == MODEL_T200 ? gRamBank : 1; + /* Convert current MMU map / ROM bank to sector format */ + romSector = ((gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT) * + REMEM_SECTORS_PER_MAP + bank; - /* Convert current MMU map / ROM bank to sector format */ - ramSector = ((gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT) * - REMEM_BANKS_PER_MAP + bank; + /* Calculate current MMU RAM bank */ + bank = gModel == MODEL_T200 ? gRamBank : 1; - /* Test if Current ReMem Sector same as current ReMem Map/Bank selection */ - /* If it is, this means we are writing to an actively mapped bank and */ - /* Need to swap the memory to/from system RAM */ - if ((gReMemSector == romSector) || (gReMemSector == ramSector)) + /* Convert current MMU map / ROM bank to sector format */ + ramSector = ((gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT) * + REMEM_SECTORS_PER_MAP + bank; + + /* Test if Current ReMem Sector same as current ReMem Map/Bank selection */ + /* If it is, this means we are writing to an actively mapped bank and */ + /* Need to swap the memory to/from system RAM */ + if ((gReMemSector == romSector) || (gReMemSector == ramSector)) + { + /* Swap memory in/out only if data actually changes */ + if (*gReMemSectPtr != data) { - /* Swap memory in/out only if data actually changes */ - if (*gReMemSectPtr != data) + /* Calculate which ReMem Vector block is being changed */ + block = (gReMemCounter >> 1); + if ((gModel != MODEL_T200) && (gReMemSector == ramSector)) + block += 32; + if (block >= 64) + { + printf("Panic! Error calculating ReMem block update, block = %d\n", block); + break; + } + + /* Update ReMem Vector table */ + if (gReMemCounter & 0x01) + gReMemMap[block] = (gReMemMap[block] & 0x00FF) | (data << 8); + else + gReMemMap[block] = (gReMemMap[block] & 0xFF00) | data; + + /* Check if new assignment maps the MMU bank to system memory */ + map = (gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT; + mmuBlock = (unsigned short) ((REMEM_MAP_OFFSET + map * REMEM_MAP_SIZE) >> 10); + + if ((gReMemMap[block] & REMEM_VCTR_ADDRESS) == mmuBlock) { - /* Update ReMem Vector table */ - if (gReMemCounter & 0x01) - gReMemMap[block] = (gReMemMap[block] & 0x00FF) | (data << 8); - else - gReMemMap[block] = (gReMemMap[block] & 0xFF00) | data; - - /* Check if new assignment maps the MMU bank to system memory */ - map = (gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT; - mmuBlock = (unsigned short) ((REMEM_MAP_OFFSET + map * REMEM_MAP_SIZE) >> 10); - - if ((gReMemMap[block] & REMEM_VCTR_ADDRESS) == mmuBlock) - { - gReMemMap[block] |= REMEM_VCTR_MMU_ACTIVE; - gReMemMapLower = (map & 0x02) * REMEM_MAP_SIZE; - gReMemMapUpper = ((map & 0x02) + 1) * REMEM_MAP_SIZE; - } - - /* Copy new MMU data to system based on new vector */ - remem_copy_mmu_to_block(block); + gReMemMap[block] |= REMEM_VCTR_MMU_ACTIVE; + gReMemMapLower = (map & 0x02) * REMEM_MAP_SIZE; + gReMemMapUpper = ((map & 0x02) + 1) * REMEM_MAP_SIZE; } + + /* Copy new MMU data to system based on new vector */ + remem_copy_mmu_to_block(block); } } + } - /* Update ReMem MAP RAM with new value */ - *gReMemSectPtr++ = data; + /* Update ReMem MAP RAM with new value */ + *gReMemSectPtr++ = data; - /* Update the ReMem Counter and Sector */ - gReMemCounter++; /* Increment Sector Counter */ - if (gReMemCounter >= REMEM_BANK_SIZE) - { - /* Get the map number */ - map = (gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT; + /* Update the ReMem Counter and Sector */ + gReMemCounter++; /* Increment Sector Counter */ + if (gReMemCounter >= REMEM_SECTOR_SIZE) + { + /* Get the map number */ + map = (gReMemMode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT; - gReMemSector++; /* Increment to next sector */ - if (gReMemSector >= REMEM_BLOCKS_PER_BANK) - gReMemSector = 0; - gReMemCounter = 0; /* Clear sector counter */ - gReMemSectPtr = (unsigned char *) (gReMemRam + REMEM_MAP_OFFSET + - map * REMEM_MAP_SIZE + gReMemSector * REMEM_BANK_SIZE); - } + gReMemSector++; /* Increment to next sector */ + if (gReMemSector >= REMEM_TOTAL_SECTORS) + gReMemSector = 0; + gReMemCounter = 0; /* Clear sector counter */ + gReMemSectPtr = (unsigned char *) (gReMemRam + REMEM_MAP_OFFSET + + gReMemSector * REMEM_SECTOR_SIZE); } - ret = 1; /* Indicate Port I/O processed */ break; - /* RamPac Write Byte port */ + case 0x85: case RAMPAC_SECTOR_PORT: /* Store new value for RampacSector & Clear counter */ gRampacSector = data; /* Update Sector for Rampac */ @@ -1635,9 +1780,9 @@ void remem_update_vectors(unsigned char targetMode) else bank = gModel == MODEL_T200 ? gRamBank : 1; mmuBlock = (unsigned short) ((REMEM_MAP_OFFSET + map * REMEM_MAP_SIZE + - bank * REMEM_BANK_SIZE) >> 10); + bank * REMEM_SECTOR_SIZE) >> 10); pMapPtr = (unsigned short *) (gReMemRam + REMEM_MAP_OFFSET + map * REMEM_MAP_SIZE + - bank * REMEM_BANK_SIZE + (x ? REMEM_RAM_MAP_OFFSET : 0)); + bank * REMEM_SECTOR_SIZE + (x ? REMEM_RAM_MAP_OFFSET : 0)); /* Update ReMem ROM/RAM blocks */ for (c = 0; c < (!x ? romBlocks : ramBlocks); c++) @@ -1662,8 +1807,8 @@ void remem_update_vectors(unsigned char targetMode) if (x && ((gReMemMap[block] & REMEM_VCTR_ADDRESS) == mmuBlock)) { gReMemMap[block] |= REMEM_VCTR_MMU_ACTIVE; - gReMemMapLower = (map & 0x02) * REMEM_MAP_SIZE; - gReMemMapUpper = ((map & 0x02) + 1) * REMEM_MAP_SIZE; + gReMemMapLower = (map & 0x01) * REMEM_MAP_SIZE; + gReMemMapUpper = ((map & 0x01) + 1) * REMEM_MAP_SIZE; } /* Increment to next block */ @@ -1687,8 +1832,10 @@ void remem_copy_normal_to_system(void) /* First copy ROM to system memory */ blocks = gModel == MODEL_T200 ? 40 : 32; - pSrc = (gReMemBoot ? gReMemFlash2 : gReMemFlash1) + - 0x10000 * gRomBank; + if (gModel != MODEL_T200) + pSrc = (gReMemBoot ? gReMemFlash2 : gReMemFlash1) + 0x8000 * gRomBank; + else + pSrc = (gReMemBoot ? gReMemFlash2 : gReMemFlash1) + (gRomBank == 0 ? 0 : 0x10000 + 0x8000 * (gRomBank - 1)); dest = 0; /* Copy the ROM bytes */ @@ -1697,7 +1844,10 @@ void remem_copy_normal_to_system(void) /* Now prepare to copy the RAM bytes */ blocks = gModel == MODEL_T200 ? 24 : 32; - pSrc = gReMemRam + 0x10000 * gRamBank + (gModel == MODEL_T200 ? 40960 : 32768); + if (gModel != MODEL_T200) + pSrc = gReMemRam; + else + pSrc = gReMemRam + 0x8000 * gRamBank; /* Copy the RAM bytes */ for (c = 0; c < blocks; c++) diff --git a/src/memory.h b/src/memory.h index b6cacc9..61efb5b 100644 --- a/src/memory.h +++ b/src/memory.h @@ -49,9 +49,10 @@ extern "C" { #define REMEM_MAP_OFFSET 0x1BF000 #define REMEM_MAP_SIZE 512 -#define REMEM_BANK_SIZE 128 -#define REMEM_BANKS_PER_MAP 4 -#define REMEM_BLOCKS_PER_BANK 32 +#define REMEM_SECTOR_SIZE 128 +#define REMEM_SECTORS_PER_MAP 4 +#define REMEM_TOTAL_SECTORS 32 +#define REMEM_BLOCKS_PER_BANK (gModel == MODEL_T200 ? 40 : 32) #define REMEM_RAM_MAP_OFFSET (gModel == MODEL_T200 ? 0x50 : 0) #define REMEM_RAMPAC_OFFSET 0x1C0000 #define RAMPAC_SECTOR_SIZE 1024 @@ -84,6 +85,7 @@ void load_rampac_ram(void); void load_remem_ram(void); void save_rampac_ram(void); void save_remem_ram(void); +void reload_sys_rom(void); unsigned char get_memory8(unsigned short address); unsigned short get_memory16(unsigned short address); @@ -106,9 +108,12 @@ void remem_copy_block_to_mmu(int block); void save_ram(void); void load_ram(void); +void load_sys_rom(void); void load_opt_rom(void); void set_ram_bank(unsigned char page); void set_rom_bank(unsigned char bank); +unsigned char get_ram_bank(void); +unsigned char get_rom_bank(void); #ifdef __cplusplus diff --git a/src/multieditwin.cpp b/src/multieditwin.cpp new file mode 100644 index 0000000..7984d26 --- /dev/null +++ b/src/multieditwin.cpp @@ -0,0 +1,314 @@ +/* multieditwin.cpp */ + +/* $Id$ */ + +/* + * Copyright 2007 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "VirtualT.h" +#include "m100emu.h" +#include "multieditwin.h" + +extern MString gRootpath; + +IMPLEMENT_DYNCREATE(Fl_Multi_Edit_Window, Fl_Multi_Window) + +void multiEditModCB(int pos, int nInserted, int nDeleted, int nRestyled, + const char* deletedText, void* cbArg) +{ + Fl_Multi_Edit_Window* mw = (Fl_Multi_Edit_Window *) cbArg; + + mw->ModifedCB(pos, nInserted, nDeleted, nRestyled, deletedText); +} + +void cb_multieditwin(Fl_Widget* w, void *) +{ + Fl_Multi_Edit_Window* mw = (Fl_Multi_Edit_Window*) w; + int ans; + + // Check if buffer is modified & ask to close if it is + if (mw->IsModified()) + { + ans = fl_choice("Save file before closing?", "Cancel", "Yes", "No"); + if (ans == 0) + return; + if (ans == 1) + mw->SaveFile(gRootpath); + } + + mw->hide(); + delete mw; +} + +Fl_Multi_Edit_Window::Fl_Multi_Edit_Window(int x, int y, int w, int h, const char* title) +: Fl_Multi_Window(x, y, w, h, title) +{ + /* Create window */ + m_te = new Fl_Text_Editor(15, 0, ClientArea()->w()-15, + ClientArea()->h(), (const char *) title); + m_tb = new Fl_Text_Buffer(); + m_tb->add_modify_callback(multiEditModCB, this); + m_te->buffer(m_tb); + m_te->textfont(FL_COURIER); + m_te->end(); + ClientArea()->resizable(m_te); + m_Modified = 0; + m_Title = title; +} + +Fl_Multi_Edit_Window::~Fl_Multi_Edit_Window() +{ +} + +/* +=============================================================== +Routine to draw the border and title bar of the window +=============================================================== +*/ +void Fl_Multi_Edit_Window::OpenFile(const MString& filename) +{ + + // Show the Disassembling text to indicate activity + if (filename != "") + { + m_tb->loadfile((const char *) filename); + m_FileName = filename; + } + + if (m_Title.Right(1) == '*') + m_Title = m_Title.Left(m_Title.GetLength()-1); + + label((const char *) m_Title); + redraw(); + m_Modified = 0; +} + +/* +=============================================================== +Routine to draw the border and title bar of the window +=============================================================== +*/ +void Fl_Multi_Edit_Window::SaveFile(const MString& rootpath) +{ + // Validate the Text Buffer is valid + if (m_tb == NULL) + return; + + // Check if we have a valid filename. If not, to a save as + if (m_FileName == "") + { + SaveAs(rootpath); + return; + } + + m_tb->savefile((const char *) m_FileName); + + // Check if buffer had been modified + if (m_Modified) + { + m_Title = m_Title.Left(m_Title.GetLength()-1); + label((const char *) m_Title); + redraw(); + } + + m_Modified = 0; +} + +/* +=============================================================== +Routine to draw the border and title bar of the window +=============================================================== +*/ +void Fl_Multi_Edit_Window::SaveAs(const MString& rootpath) +{ + Fl_File_Chooser* fc; + int count; + + // Validate the Text Buffer is valid + if (m_tb == NULL) + return; + + fc = new Fl_File_Chooser((const char *) rootpath, "*.asm,*.a85", Fl_File_Chooser::CREATE, "Save File As"); + fc->preview(0); + fc->show(); + + while (fc->visible()) + Fl::wait(); + + // Determine if a filename was selected + count = fc->count(); + if (count == 0) + { + delete fc; + return; + } + + m_FileName = fc->value(1); + m_tb->savefile((const char *) m_FileName); + + delete fc; + m_Modified = 0; +} + +/* +=============================================================== +Routine to handle modifications to the text buffer +=============================================================== +*/ +void Fl_Multi_Edit_Window::ModifedCB(int pos, int nInserted, int nDeleted, + int nRestyled, const char* deletedText) +{ + // Check if buffer had already been modified before + if (m_Modified) + return; + + // Update the window title to append a '*' + if (m_Title.Right(1) == '*') + return; + + m_Title += '*'; + label((const char *) m_Title); + redraw(); + + m_Modified = 1; +} + +/* +================================================================================ +OkToClose: Overridden function to test if buffer is modified +================================================================================ +*/ +int Fl_Multi_Edit_Window::OkToClose(void) +{ + int ans; + + // Check if buffer is modified & ask to close if it is + if (IsModified()) + { + ans = fl_choice("Save file before closing?", "Cancel", "Yes", "No"); + if (ans == 0) + return FALSE; + if (ans == 1) + SaveFile(gRootpath); + } + + return TRUE; +} + +/* +=============================================================== +This routine updates the title of the Edit Window +=============================================================== +*/ +void Fl_Multi_Edit_Window::Title(const MString& title) +{ + m_Title = title; + + label((const char *) m_Title); + redraw(); +} + +/* +=============================================================== +This routine performs a find and replace all on the buffer +=============================================================== +*/ +int Fl_Multi_Edit_Window::ReplaceAll(const char* pFind, + const char * pReplace) +{ + int replacement = 0; + + // Start at the beginning of the buffer + m_te->insert_position(0); + + // Loop while text found + for (int found = 1; found; ) + { + int pos = m_te->insert_position(); + found = m_tb->search_forward(pos, pFind, &pos); + + if (found) + { + replacement = 1; + // Found a match...update with new text + m_tb->select(pos, pos+strlen(pFind)); + m_tb->remove_selection(); + m_tb->insert(pos, pReplace); + m_tb->select(pos, pos+strlen(pReplace)); + m_te->insert_position(pos+strlen(pReplace)); + m_te->show_insert_position(); + } + } + + return replacement; +} + +/* +=============================================================== +This routine performs a find and replace the first occurance +of pFind with pReplace +=============================================================== +*/ +int Fl_Multi_Edit_Window::ReplaceNext(const char* pFind, + const char * pReplace) +{ + int replacement = 0; + + // Start at the beginning of the buffer + m_te->insert_position(0); + + // Search for the pFind text + int pos = m_te->insert_position(); + int found = m_tb->search_forward(pos, pFind, &pos); + + if (found) + { + replacement = 1; + // Found a match...update with new text + m_tb->select(pos, pos+strlen(pFind)); + m_tb->remove_selection(); + m_tb->insert(pos, pReplace); + m_tb->select(pos, pos+strlen(pReplace)); + m_te->insert_position(pos+strlen(pReplace)); + m_te->show_insert_position(); + } + + return replacement; +} + diff --git a/src/multieditwin.h b/src/multieditwin.h new file mode 100644 index 0000000..add4ef4 --- /dev/null +++ b/src/multieditwin.h @@ -0,0 +1,68 @@ +/* multieditwin.h */ + +/* $Id$ */ + +/* + * Copyright 2007 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef _MULTIEDITWIN_H_ +#define _MULTIEDITWIN_H_ + +#include "multiwin.h" + +class Fl_Multi_Edit_Window : public Fl_Multi_Window +{ +public: + Fl_Multi_Edit_Window(int x=0, int y=0, int w=600, int h=500, const char *label = 0); + ~Fl_Multi_Edit_Window(); + + DECLARE_DYNCREATE(Fl_Multi_Edit_Window) + + void OpenFile(const MString& filename); + void SaveFile(const MString& rootpath); + void SaveAs(const MString& rootpath); + void Copy(void); + void Cut(void); + void Paste(void); + int ReplaceAll(const char * pFind, const char *pReplace); + int ReplaceNext(const char * pFind, const char *pReplace); + int IsModified(void) { return m_Modified; } + void Modified(void); + void ModifedCB(int, int, int, int, const char *); + const MString& Filename(void) { return m_FileName; } + void Title(const MString& title); + + Fl_Text_Editor* m_te; +protected: + Fl_Text_Buffer* m_tb; + MString m_FileName; + MString m_Title; + int m_Modified; + int virtual OkToClose(void); +}; + +#endif + diff --git a/src/multiwin.cpp b/src/multiwin.cpp index 73b95d6..cab3c09 100644 --- a/src/multiwin.cpp +++ b/src/multiwin.cpp @@ -49,6 +49,8 @@ int Fl_Multi_Window::m_MinimizeRegions[200] = { -1 }; Fl_Multi_Window* gpDestroyPtr = 0; +IMPLEMENT_DYNCREATE(Fl_Multi_Window, VTObject) + void multi_window_idle_proc(void* w) { if (gpDestroyPtr != 0) @@ -340,7 +342,10 @@ int Fl_Multi_Window::handle(int event) { // Check which Icon was selected if (m_InIconArea == 1) + { + Fl::release(); CloseIconSelected(); + } else if (m_InIconArea == 2) MaximizeIconSelected(); else if (m_InIconArea == 3) @@ -466,6 +471,11 @@ Routine to handle selection of the close window icon void Fl_Multi_Window::CloseIconSelected() { Fl_Window* p; + + // Check if it is okay to close + if (!OkToClose()) + return; + hide(); p = (Fl_Window*) parent(); p->remove(this); @@ -474,6 +484,10 @@ void Fl_Multi_Window::CloseIconSelected() gpDestroyPtr = this; } +int Fl_Multi_Window::OkToClose(void) +{ + return TRUE; +} /* =============================================================== Routine to handle selection of the restore icon diff --git a/src/multiwin.h b/src/multiwin.h index 5f26ecc..09d00c8 100644 --- a/src/multiwin.h +++ b/src/multiwin.h @@ -1,4 +1,4 @@ -/* multiwin.cpp */ +/* multiwin.h */ /* $Id$ */ @@ -37,24 +37,30 @@ #include #include +#include +#include #include "vtobj.h" +#include "MString.h" -class Fl_Multi_Window : public Fl_Double_Window +class Fl_Multi_Window : public Fl_Double_Window, public VTObject { public: - Fl_Multi_Window(int x, int y, int w, int h, const char *label = 0); + Fl_Multi_Window(int x=0, int y=0, int w=600, int h=500, const char *label = 0); ~Fl_Multi_Window(); Fl_Window* ClientArea() { return m_pClientArea; }; int m_NoResize; + DECLARE_DYNCREATE(Fl_Multi_Window) + protected: void virtual draw(void); int virtual handle(int event); void CloseIconSelected(); void MaximizeIconSelected(); void MinimizeIconSelected(); + int virtual OkToClose(void); Fl_Window* m_pClientArea; Fl_Pixmap* m_pIcon; diff --git a/src/n8201rom.c b/src/n8201rom.c index 2508a34..4d2de24 100644 --- a/src/n8201rom.c +++ b/src/n8201rom.c @@ -909,8 +909,11 @@ RomDescription_t gN8201_Desc = { 0xF84F, /* Start of RAM directory */ 0xF459, /* BASIC string buffer pointer */ 0xF9CA, /* BASIC Size */ + 0xFE58, /* Keyscan array */ + 0x78B7, /* Character generator array */ 24, /* Number of directory entries */ - 8 /* Index of first Dir entry */ + 8, /* Index of first Dir entry */ + 0x7FAE /* Address of MS Copyright string */ }; diff --git a/src/periph.cpp b/src/periph.cpp index 75930b3..b606ce2 100644 --- a/src/periph.cpp +++ b/src/periph.cpp @@ -56,7 +56,6 @@ void cb_Ide(Fl_Widget* w, void*) ; - typedef struct periph_ctrl_struct { Fl_Menu_Bar* pMenu; @@ -133,7 +132,7 @@ Fl_Menu_Item gPeriph_menuitems[] = { { "Assembler / IDE", 0, cb_Ide }, { "Disassembler", 0, disassembler_cb }, { "Memory Editor", 0, cb_MemoryEditor }, - { "Simulation Log Viewer", 0, 0 }, +// { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, 0 }, { 0 }, diff --git a/src/project.cpp b/src/project.cpp new file mode 100644 index 0000000..553da95 --- /dev/null +++ b/src/project.cpp @@ -0,0 +1,881 @@ +/* project.cpp */ + +/* $Id$ */ + +/* + * Copyright 2007 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "VirtualT.h" +#include "project.h" + +#ifdef _WIN32 +extern "C" +#endif +extern char path[]; + +void cb_SelLocation(Fl_Widget* w, void*) +{ + Fl_File_Chooser *fileWin; + int count; + Fl_Round_Button* pButton; + VT_NewProject* pNewProj; + const char * pNewLoc; + char newPath[512]; + + // Get current location from the window + pButton = (Fl_Round_Button*) w; + pNewProj = (VT_NewProject*) pButton->user_data(); + + // Create a File chooser + fileWin = new Fl_File_Chooser(pNewProj->getLocation(), "", + Fl_File_Chooser::DIRECTORY, "Choose Project Location"); + fileWin->preview(0); + fileWin->show(); + + // Wait until selection is made or cancel + while (fileWin->visible()) + Fl::wait(); + + // Determine if selection made + count = fileWin->count(); + if (count == 0) + { + delete fileWin; + return; + } + + // Get the path of the new location + pNewLoc = fileWin->value(1); + + printf("Path = %s\n", path); + printf("New = %s\n", pNewLoc); + // Check if path is in the current directory and replace with "./" + if (strncmp(path, pNewLoc, strlen(path)) == 0) + { + strcpy(newPath, "."); + strcat(newPath, &pNewLoc[strlen(path)]); + if (newPath[1] == '\0') + strcat(newPath, "/"); + } + else + { + strcpy(newPath, pNewLoc); + } + pNewProj->setLocation(newPath); + + delete fileWin; +} + +void cb_cancelNewProject(Fl_Widget* w, void*) +{ + VT_NewProject* pNewProject; + + pNewProject = (VT_NewProject*) w->user_data(); + pNewProject->hide(); +} + +void cb_okNewProject(Fl_Widget* w, void*) +{ + const char * projName; + VT_NewProject* pNewProject; + char projPath[512]; + FILE* fd; + + pNewProject = (VT_NewProject*) w->user_data(); + if (pNewProject == NULL) + return; + + // Check if project name provided + projName = pNewProject->getProjName(); + if (projName == NULL) + { + fl_alert("Must provide project name!"); + return; + } + if (strlen(projName) == 0) + { + fl_alert("Project name must be provided!"); + return; + } + + // Check if project type provided + if (pNewProject->getProjType() == 0) + { + fl_alert("Project type must be specified!"); + return; + } + + // Check if project already exists + sprintf(projPath, "%s/%s/%s.prj", pNewProject->getLocation(), projName, projName); + fd = fopen(projPath, "r+"); + if (fd != NULL) + { + fclose(fd); + sprintf(projPath, "Project %s already exists!", projName); + fl_alert(projPath); + return; + } + + // Mark project "okay" to create + pNewProject->hide(); + pNewProject->m_makeProj = TRUE; +} + +void browse_cb(Fl_Widget* w, void*) +{ + int sel; + int c; + const char *item; + char newtxt[30]; + + Fl_Browser* pB = (Fl_Browser*) w; + sel = pB->value(); + + // Clear bold from all enries + for (c = 1; ;c++) + { + item = pB->text(c); + if (item == NULL) + break; + if (item[0] == '@') + pB->text(c, &item[2]); + } + + // Check if selection is zero (no selection) + if (sel == 0) + return; + + // Make selection bold + strcpy(&newtxt[2], pB->text(sel)); + newtxt[0] = '@'; + newtxt[1] = 'b'; + pB->text(sel, newtxt); +} + +VT_NewProject::VT_NewProject() +{ + Fl_Box* o; + Fl_Button* b; + + // Set flag indicating project parameters not valid yet. + m_makeProj = FALSE; + + // Create new window + m_pWnd = new Fl_Double_Window(100, 150, 380,320, "Create New Project"); + + // Text for project name + o = new Fl_Box(10, 10, 100, 20, "Project Name"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + + // Create Project Name edit field + m_pProjName = new Fl_Input(14,30,150,25,""); + + // Text for the project type + o = new Fl_Box(10, 60, 100, 20, "Project Type"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + + // Create a browser + m_pProjType = new Fl_Select_Browser(14, 80, 150, 100); + m_pProjType->add("@bAssembly .CO"); + m_pProjType->add("Assembly .obj"); + m_pProjType->add("Assembly ROM"); + m_pProjType->add("BASIC"); + m_pProjType->callback(browse_cb); + m_pProjType->value(1); + + // Creae location edit field & browse button + o = new Fl_Box(10, 190, 150, 20, "Location"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pLocation = new Fl_File_Input(14,210, 300,35,""); + m_pLocation->value("./Projects/"); + b = new Fl_Button(324, 210, 35, 35, "..."); + b->callback(cb_SelLocation); + b->user_data(this); + + // Text for target device + o = new Fl_Box(180, 10, 100, 20, "Target Model"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + + // Create radio buttons for each model + m_pM100 = new Fl_Round_Button(200, 35, 100, 20, "Model 100"); + m_pM100->type(FL_RADIO_BUTTON); + m_pM100->value(1); + m_pM102 = new Fl_Round_Button(200, 60, 100, 20, "Model 102"); + m_pM102->type(FL_RADIO_BUTTON); + m_pT200 = new Fl_Round_Button(200, 85, 100, 20, "Model 200"); + m_pT200->type(FL_RADIO_BUTTON); + m_pPC8201 = new Fl_Round_Button(200, 110, 100, 20, "Model PC-8201"); + m_pPC8201->type(FL_RADIO_BUTTON); + + // Create an Ok button + m_pOk = new Fl_Button(60, 265, 90, 30, "OK"); + m_pOk->callback(cb_okNewProject); + m_pOk->user_data(this); + + // Create a Cancel button + m_pCancel = new Fl_Button(200, 265, 90, 30, "Cancel"); + m_pCancel->callback(cb_cancelNewProject); + m_pCancel->user_data(this); + + m_pWnd->end(); +} + +VT_NewProject::~VT_NewProject() +{ + if (m_pWnd != NULL) + delete m_pWnd; +} + +void VT_NewProject::show(void) +{ + if (m_pWnd != NULL) + m_pWnd->show(); +} + +void VT_NewProject::hide(void) +{ + if (m_pWnd != NULL) + m_pWnd->hide(); +} + +const char * VT_NewProject::getProjName(void) +{ + if (m_pProjName == NULL) + return NULL; + + return m_pProjName->value(); +} + +int VT_NewProject::getProjType(void) +{ + if (m_pProjType == NULL) + return 0; + + return m_pProjType->value(); +} + +int VT_NewProject::visible(void) +{ + return m_pWnd->visible(); +} + +const char * VT_NewProject::getLocation(void) +{ + if (m_pLocation == NULL) + return NULL; + + return m_pLocation->value(); +} + +void VT_NewProject::setLocation(char *pPath) +{ + if (m_pLocation == NULL) + return; + + m_pLocation->value(pPath); +} + +int VT_NewProject::getTargetModel() +{ + if (m_pM100->value() == 1) + return MODEL_M100; + else if (m_pM102->value() == 1) + return MODEL_M102; + else if (m_pT200->value() == 1) + return MODEL_T200; + else if (m_pPC8201->value() == 1) + return MODEL_PC8201; + + return -1; +} + +/* +============================================================================== +ProjectSettings dialog box functions defined below. This dialog is uses to +set the assembler, linker, and other settings for the active project. +============================================================================== +*/ +void cb_settings_cancel(Fl_Widget* w, void*) +{ + VT_ProjectSettings* pProj; + + pProj = (VT_ProjectSettings*) w->user_data(); + pProj->hide(); +} + +void cb_settings_ok(Fl_Widget* w, void*) +{ + VT_ProjectSettings* pProj; + VT_Project* pProject; + + // Get a pointer to the projectSettings object + pProj = (VT_ProjectSettings*) w->user_data(); + if (pProj == NULL) + return; + pProject = pProj->m_pProject; + + // Test the validity of the IncludePath + + // Test the validity of the Defines + + // Test the validity of the LinkPath + + // Test the validity of the LinkLibs + + // Update the General Options + pProject->m_ProjectType = pProj->getProjType(); + pProject->m_TargetModel = pProj->getTargetModel(); + pProject->m_AutoLoad = pProj->getAutoLoad(); + pProject->m_UpdateHIMEM = pProj->getUpdateHIMEM(); + + // Update the Assembler Options + pProject->AsmDebugInfo(pProj->getAsmDebugInfo()); + pProject->AsmListing(pProj->getAsmListing()); + pProject->BrowseInfo(pProj->getBrowseInfo()); + pProject->AutoExtern(pProj->getAutoExtern()); + pProject->m_IncludePath = pProj->getIncludeDirs(); + pProject->m_Defines = pProj->getDefines(); + + // Update the Linker Options + pProject->LinkDebugInfo(pProj->getLinkDebugInfo()); + pProject->MapFile(pProj->getMapFile()); + pProject->IgnoreStdLibs(pProj->getIgnoreStdLibs()); + pProject->m_LinkPath = pProj->getLinkPath(); + pProject->m_LinkLibs = pProj->getLinkObjs(); + pProject->m_CodeAddr = pProj->getCodeAddr(); + pProject->m_DataAddr = pProj->getDataAddr(); + + // Hide the window to end the session + pProj->m_pProject->m_Dirty = 1; + pProj->hide(); +} + +void cb_AutoLoad(Fl_Widget* w, void*) +{ + VT_ProjectSettings* pProj; + + pProj = (VT_ProjectSettings*) w->user_data(); + if (pProj == NULL) + return; + + pProj->EnableUpdateHIMEM(pProj->getAutoLoad()); +} + +VT_ProjectSettings::VT_ProjectSettings(VT_Project *pProj) +{ + Fl_Box* o; + Fl_Group* g; + + // Set flag indicating project parameters not valid yet. + m_makeProj = FALSE; + m_pProject = pProj; + + // Create new window + m_pWnd = new Fl_Double_Window(100, 150, 380,320, "Project Settings"); + + m_pTabs = new Fl_Tabs(10, 10, 360, 260); + + // Create the General tab + g = new Fl_Group(10, 30, 380, 280, "General"); + + // Text for the project type + o = new Fl_Box(20, 50, 100, 20, "Project Type"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + + // Create a browser + m_pProjType = new Fl_Select_Browser(24, 75, 150, 100); + m_pProjType->add("Assembly .CO"); + m_pProjType->add("Assembly .obj"); + m_pProjType->add("Assembly ROM"); + m_pProjType->add("BASIC"); + m_pProjType->callback(browse_cb); + m_pProjType->value(m_pProject->m_ProjectType); + + // Text for target device + o = new Fl_Box(180, 50, 100, 20, "Target Model"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + + // Create radio buttons for each model + m_pM100 = new Fl_Round_Button(210, 75, 100, 20, "Model 100"); + m_pM100->type(FL_RADIO_BUTTON); + if (m_pProject->m_TargetModel == MODEL_M100) + m_pM100->value(1); + m_pM102 = new Fl_Round_Button(210, 100, 100, 20, "Model 102"); + m_pM102->type(FL_RADIO_BUTTON); + if (m_pProject->m_TargetModel == MODEL_M102) + m_pM102->value(1); + m_pT200 = new Fl_Round_Button(210, 125, 100, 20, "Model 200"); + m_pT200->type(FL_RADIO_BUTTON); + if (m_pProject->m_TargetModel == MODEL_T200) + m_pT200->value(1); + m_pPC8201 = new Fl_Round_Button(210, 150, 100, 20, "Model PC-8201"); + m_pPC8201->type(FL_RADIO_BUTTON); + if (m_pProject->m_TargetModel == MODEL_PC8201) + m_pPC8201->value(1); + + // Create checkbox for AutoLoad + m_pAutoLoad = new Fl_Check_Button(24, 200, 250, 20, "Load to Emulation after assembly"); + m_pAutoLoad->value(m_pProject->m_AutoLoad); + m_pAutoLoad->callback(cb_AutoLoad); + m_pAutoLoad->user_data(this); + + m_pUpdateHIMEM = new Fl_Check_Button(44, 230, 250, 20, "Update HIMEM automatically"); + m_pUpdateHIMEM->value(m_pProject->m_UpdateHIMEM); + if (m_pProject->m_AutoLoad == 0) + EnableUpdateHIMEM(FALSE); + + g->end(); + + // Create an Assembler tab + g = new Fl_Group(10, 30, 380, 280, "Assembler"); + + // Create checkboxes + m_pAsmDebugInfo = new Fl_Check_Button(20, 50, 165, 20, "Generate Debug Info"); + m_pAsmDebugInfo->value(m_pProject->AsmDebugInfo()); + m_pList = new Fl_Check_Button(20, 75, 170, 20, "Generate List Files"); + m_pList->value(m_pProject->AsmListing()); + m_pBrowseInfo = new Fl_Check_Button(190, 50, 165, 20, "Generate Browse Info"); + m_pBrowseInfo->value(m_pProject->BrowseInfo()); + m_pAutoExtern = new Fl_Check_Button(190, 75, 165, 20, "Automatic Externs"); + m_pAutoExtern->value(m_pProject->AutoExtern()); + + // Create edit field for Include Directories + o = new Fl_Box(20, 110, 100, 20, "Additional Include Directories"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pIncludeDirs = new Fl_Input(20, 130, 320, 20, ""); + m_pIncludeDirs->value(m_pProject->m_IncludePath); + + // Create edit field for Additional Defines + o = new Fl_Box(20, 170, 100, 20, "Additional Assembler Defines"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pDefines = new Fl_Input(20, 190, 320, 20, ""); + m_pDefines->value(m_pProject->m_Defines); + + // End the Assembler tab + g->end(); + + // Create a Linker tab + g = new Fl_Group(10, 30, 380, 280, "Linker"); + + // Create checkboxes + m_pLinkDebugInfo = new Fl_Check_Button(20, 50, 165, 20, "Generate Debug Info"); + m_pLinkDebugInfo->value(m_pProject->LinkDebugInfo()); + m_pMapFile = new Fl_Check_Button(20, 75, 170, 20, "Generate Map File"); + m_pMapFile->value(m_pProject->MapFile()); + m_pIgnoreStdLibs = new Fl_Check_Button(20, 100, 165, 20, "Ingore Std Libraries"); + m_pIgnoreStdLibs->value(m_pProject->IgnoreStdLibs()); + + // Create Edit field for Output Name + o = new Fl_Box(20, 125, 100, 20, "Output Name"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pOutputName = new Fl_Input(20, 145, 320, 20, ""); + m_pOutputName->value(m_pProject->m_Name); + + // Create Edit field for Link libs + o = new Fl_Box(20, 170, 100, 20, "Additional Link Objects"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pLinkObjs = new Fl_Input(20, 190, 320, 20, ""); + m_pLinkObjs->value(m_pProject->m_LinkLibs); + + // Create Edit field for Link Dirs + o = new Fl_Box(20, 215, 100, 20, "Additional Object Directories"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pObjPath = new Fl_Input(20, 235, 320, 20, ""); + m_pObjPath->value(m_pProject->m_LinkPath); + + // Add edit fields for Code and Data segment addresses + o = new Fl_Box(235, 50, 100, 20, "Segment Address"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o = new Fl_Box(200, 75, 40, 20, "Code"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o = new Fl_Box(200, 100, 40, 20, "Data"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + + m_pCodeAddr = new Fl_Input(250, 75, 90, 20, ""); + m_pCodeAddr->value("test"); + m_pCodeAddr->value((const char *) m_pProject->m_CodeAddr); + m_pDataAddr = new Fl_Input(250, 100, 90, 20, ""); + m_pDataAddr->value((const char *) m_pProject->m_DataAddr); + + // End the Linker tab + g->end(); + + m_pTabs->end(); + + // OK button + { + Fl_Button* o = new Fl_Button(200, 282, 60, 30, "Cancel"); + o->callback((Fl_Callback*)cb_settings_cancel); + o->user_data(this); + } + { + Fl_Return_Button* o = new Fl_Return_Button(280, 282, 60, 30, "OK"); + o->callback((Fl_Callback*)cb_settings_ok); + o->user_data(this); + } +} + +void VT_ProjectSettings::show(void) +{ + if (m_pWnd != NULL) + m_pWnd->show(); +} + +int VT_ProjectSettings::visible(void) +{ + return m_pWnd->visible(); +} + +void VT_ProjectSettings::hide(void) +{ + if (m_pWnd != NULL) + m_pWnd->hide(); +} + +int VT_ProjectSettings::getProjType(void) +{ + if (m_pProjType == NULL) + return 0; + + return m_pProjType->value(); +} + +int VT_ProjectSettings::getTargetModel() +{ + if (m_pM100->value() == 1) + return MODEL_M100; + else if (m_pM102->value() == 1) + return MODEL_M102; + else if (m_pT200->value() == 1) + return MODEL_T200; + else if (m_pPC8201->value() == 1) + return MODEL_PC8201; + + return -1; +} + +int VT_ProjectSettings::getAutoLoad() +{ + if (m_pAutoLoad == NULL) + return 0; + + return m_pAutoLoad->value(); +} + +int VT_ProjectSettings::getUpdateHIMEM() +{ + if (m_pUpdateHIMEM == NULL) + return 0; + + return m_pUpdateHIMEM->value(); +} + +MString VT_ProjectSettings::getDefines(void) +{ + if (m_pDefines == NULL) + return ""; + + return m_pDefines->value(); +} + +MString VT_ProjectSettings::getIncludeDirs(void) +{ + if (m_pIncludeDirs == NULL) + return ""; + + return m_pIncludeDirs->value(); +} + +int VT_ProjectSettings::getAsmDebugInfo(void) +{ + if (m_pAsmDebugInfo == NULL) + return 0; + + return m_pAsmDebugInfo->value(); +} + +int VT_ProjectSettings::getAsmListing(void) +{ + if (m_pList == NULL) + return 0; + + return m_pList->value(); +} + +int VT_ProjectSettings::getBrowseInfo(void) +{ + if (m_pBrowseInfo == NULL) + return 0; + + return m_pBrowseInfo->value(); +} + +int VT_ProjectSettings::getAutoExtern(void) +{ + if (m_pAutoExtern == NULL) + return 0; + + return m_pAutoExtern->value(); +} + +int VT_ProjectSettings::getLinkDebugInfo(void) +{ + if (m_pLinkDebugInfo == NULL) + return 0; + + return m_pLinkDebugInfo->value(); +} + +int VT_ProjectSettings::getMapFile(void) +{ + if (m_pMapFile == NULL) + return 0; + + return m_pMapFile->value(); +} + +int VT_ProjectSettings::getIgnoreStdLibs(void) +{ + if (m_pIgnoreStdLibs == NULL) + return 0; + + return m_pIgnoreStdLibs->value(); +} + +MString VT_ProjectSettings::getLinkPath(void) +{ + if (m_pObjPath == NULL) + return ""; + + return m_pObjPath->value(); +} + +MString VT_ProjectSettings::getLinkObjs(void) +{ + if (m_pLinkObjs == NULL) + return ""; + + return m_pLinkObjs->value(); +} + +MString VT_ProjectSettings::getCodeAddr(void) +{ + if (m_pCodeAddr == NULL) + return ""; + + return m_pCodeAddr->value(); +} + +MString VT_ProjectSettings::getDataAddr(void) +{ + if (m_pDataAddr == NULL) + return ""; + + return m_pDataAddr->value(); +} + +void VT_ProjectSettings::EnableUpdateHIMEM(int enable) +{ + // Insure the pointer is not NULL + if (m_pUpdateHIMEM == NULL) + return; + + if (enable) + m_pUpdateHIMEM->activate(); + else + m_pUpdateHIMEM->deactivate(); +} + +/* +======================================================================== +VT_Project implementation routines. +======================================================================== +*/ +void VT_Project::AsmDebugInfo(int enable) +{ + if (enable) + AddAsmOption("-g"); + else + RemoveAsmOption("-g"); +} + +int VT_Project::AsmDebugInfo(void) const +{ + return m_AsmOptions.Find("-g", 0) != -1; +} + +void VT_Project::AsmListing(int enable) +{ + if (enable) + AddAsmOption("-l"); + else + RemoveAsmOption("-l"); +} + +int VT_Project::AsmListing(void) const +{ + return m_AsmOptions.Find("-l", 0) != -1; +} + +void VT_Project::BrowseInfo(int enable) +{ + if (enable) + AddAsmOption("-b"); + else + RemoveAsmOption("-b"); +} + +int VT_Project::BrowseInfo(void) const +{ + return m_AsmOptions.Find("-b", 0) != -1; +} + +void VT_Project::AutoExtern(int enable) +{ + if (enable) + AddAsmOption("-e"); + else + RemoveAsmOption("-e"); +} + +int VT_Project::AutoExtern(void) const +{ + return m_AsmOptions.Find("-e", 0) != -1; +} + +void VT_Project::AddAsmOption(char* pOpt) +{ + int index; + + // Determine if option already exists in m_AsmOptions + index = m_AsmOptions.Find(pOpt, 0); + if (index != -1) + return; + + // Append option to end of the m_AsmOptions string + m_AsmOptions = m_AsmOptions + " " + pOpt; +} + +void VT_Project::RemoveAsmOption(char* pOpt) +{ + int index; + MString temp; + + // Determin if option already exists in m_AsmOptions + index = m_AsmOptions.Find(pOpt, 0); + if (index == -1) + return; + + // Need to remove option from the m_AsmOptons string + temp = m_AsmOptions.Left(index); + temp.Trim(); + if (m_AsmOptions.GetLength() > index + 2) + temp += m_AsmOptions.Right(m_AsmOptions.GetLength() - (index + 2)); + + // Assign new m_AsmOptions + m_AsmOptions = temp; +} + +void VT_Project::AddLinkOption(char* pOpt) +{ + int index; + + // Determine if option already exists in m_AsmOptions + index = m_LinkOptions.Find(pOpt, 0); + if (index != -1) + return; + + // Append option to end of the m_AsmOptions string + m_LinkOptions = m_LinkOptions + " " + pOpt; +} + +void VT_Project::RemoveLinkOption(char* pOpt) +{ + int index; + MString temp; + + // Determin if option already exists in m_AsmOptions + index = m_LinkOptions.Find(pOpt, 0); + if (index == -1) + return; + + // Need to remove option from the m_AsmOptons string + temp = m_LinkOptions.Left(index); + temp.Trim(); + if (m_LinkOptions.GetLength() > index + 2) + temp += m_LinkOptions.Right(m_LinkOptions.GetLength() - (index + 2)); + + // Assign new m_AsmOptions + m_LinkOptions = temp; +} + +void VT_Project::LinkDebugInfo(int enable) +{ + if (enable) + AddLinkOption("-g"); + else + RemoveLinkOption("-g"); +} + +int VT_Project::LinkDebugInfo(void) const +{ + return m_LinkOptions.Find("-g", 0) != -1; +} + +void VT_Project::MapFile(int enable) +{ + if (enable) + AddLinkOption("-m"); + else + RemoveLinkOption("-m"); +} + +int VT_Project::MapFile(void) const +{ + return m_LinkOptions.Find("-m", 0) != -1; +} + +void VT_Project::IgnoreStdLibs(int enable) +{ + if (enable) + AddLinkOption("-i"); + else + RemoveLinkOption("-i"); +} + +int VT_Project::IgnoreStdLibs(void) const +{ + return m_LinkOptions.Find("-i", 0) != -1; +} + diff --git a/src/project.h b/src/project.h new file mode 100644 index 0000000..f3217ba --- /dev/null +++ b/src/project.h @@ -0,0 +1,204 @@ +/* project.h */ + +/* $Id$ */ + +/* + * Copyright 2007 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef PROJECT_H +#define PROJECT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "MString.h" +#include "vtobj.h" + +void cb_NewProject (Fl_Widget* w, void*); + +class VT_Project +{ +public: + VT_Project() { m_Dirty = 0; m_AutoLoad = 0; m_ProjectType = 0; + m_TargetModel = 0; m_UpdateHIMEM = 0; m_CodeAddr = "auto"; + m_DataAddr = "auto"; }; + ~VT_Project(); + + void AsmDebugInfo(int enable); + int AsmDebugInfo(void) const; + void AsmListing(int enable); + int AsmListing(void) const; + void BrowseInfo(int enable); + int BrowseInfo(void) const; + void AutoExtern(int enable); + int AutoExtern(void) const; + + void AddAsmOption(char *pOpt); + void RemoveAsmOption(char *pOpt); + + void LinkDebugInfo(int enable); + int LinkDebugInfo(void) const; + void MapFile(int enable); + int MapFile(void) const; + void IgnoreStdLibs(int enable); + int IgnoreStdLibs(void) const; + + void AddLinkOption(char *pOpt); + void RemoveLinkOption(char *pOpt); + + MString m_Name; // Project name + MString m_RootPath; + MString m_IncludePath; + MString m_Defines; + MString m_LinkPath; + MString m_LinkLibs; + MString m_AsmOptions; + MString m_LinkOptions; + MString m_CodeAddr; + MString m_DataAddr; + VTObArray m_Groups; + int m_Dirty; // Set true when project settings change + int m_ProjectType; // Type of project + int m_TargetModel; // Target model to assemble for + int m_AutoLoad; // Load to emulator after assemble? + int m_UpdateHIMEM; // Auto update HIMEM variable? +}; + +class VT_NewProject +{ +public: + VT_NewProject(); + ~VT_NewProject(); + + MString m_Dir; + void show(); + void hide(); + int visible(); + const char * getLocation(); + void setLocation(char *pPath); + const char * getProjName(); + int getProjType(); + int getTargetModel(); + int m_makeProj; + +protected: + Fl_Double_Window* m_pWnd; + Fl_Select_Browser* m_pProjType; + Fl_Button* m_pOk; + Fl_Button* m_pCancel; + Fl_Button* m_pBrowse; + Fl_Input* m_pProjName; + Fl_File_Input* m_pLocation; + Fl_Round_Button* m_pM100; + Fl_Round_Button* m_pM102; + Fl_Round_Button* m_pT200; + Fl_Round_Button* m_pPC8201; +}; + +class VT_ProjectSettings +{ +public: + VT_ProjectSettings(VT_Project* pProj); + ~VT_ProjectSettings(); + + MString m_Dir; + int m_makeProj; + class VT_Project* m_pProject; + + void show(); + void hide(); + int visible(); + + int getProjType(); + int getTargetModel(); + int getAutoLoad(); + int getUpdateHIMEM(); + + MString getDefines(void); + MString getIncludeDirs(void); + int getAsmListing(void); + int getAsmDebugInfo(void); + int getBrowseInfo(void); + int getAutoExtern(void); + + int getLinkDebugInfo(void); + int getMapFile(void); + int getIgnoreStdLibs(void); + MString getLinkPath(void); + MString getOutputName(void); + MString getLinkObjs(void); + MString getCodeAddr(void); + MString getDataAddr(void); + + void EnableUpdateHIMEM(int enable); + +protected: + Fl_Double_Window* m_pWnd; + + // Define a tabs object + Fl_Tabs* m_pTabs; + + // Define General tab items + Fl_Select_Browser* m_pProjType; + Fl_Round_Button* m_pM100; + Fl_Round_Button* m_pM102; + Fl_Round_Button* m_pT200; + Fl_Round_Button* m_pPC8201; + Fl_Check_Button* m_pAutoLoad; + Fl_Check_Button* m_pUpdateHIMEM; + + // Define Assembler tab items + Fl_Button* m_pAsmDebugInfo; + Fl_Button* m_pList; + Fl_Button* m_pBrowseInfo; + Fl_Button* m_pAutoExtern; + Fl_Input* m_pIncludeDirs; + Fl_Input* m_pDefines; + + // Define Link tab items + Fl_Button* m_pIgnoreStdLibs; + Fl_Button* m_pMapFile; + Fl_Button* m_pLinkDebugInfo; + Fl_Input* m_pObjPath; + Fl_Input* m_pOutputName; + Fl_Input* m_pLinkObjs; + Fl_Input* m_pCodeAddr; + Fl_Input* m_pDataAddr; + + Fl_Button* m_pOk; + Fl_Button* m_pCancel; +}; + + +#endif + diff --git a/src/rememcfg.cpp b/src/rememcfg.cpp new file mode 100644 index 0000000..11a78ba --- /dev/null +++ b/src/rememcfg.cpp @@ -0,0 +1,1032 @@ +/* rememcfg.cpp */ + +/* $Id$ */ + +/* +* Copyright 2008 Ken Pettit +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include + +#if defined(WIN32) +#include +#endif +#include +#include +#include + +#include "cpuregs.h" +#include "rememcfg.h" +#include "m100emu.h" +#include "disassemble.h" +#include "periph.h" +#include "memedit.h" +#include "cpu.h" +#include "memory.h" +#include "io.h" +#include "VirtualT.h" + +#define MENU_HEIGHT 32 + +void cb_Ide(Fl_Widget* w, void*); +int str_to_i(const char *pStr); + + +/* +============================================================================ +Global variables +============================================================================ +*/ +rememcfg_ctrl_t rememcfg_ctrl; +Fl_Window *grmcw = NULL; + +static int gMap; // Map currently being edited +static int gRegion; // Region currently being edited +static int gVector; // Vector currently being edited +static int gMapModified; // Flag indicating if map has been modified +static char gMapData[REMEM_MAP_SIZE]; // 512 bytes of Map Data being edited + +// Menu items +Fl_Menu_Item gRememCfg_menuitems[] = { + { "&Tools", 0, 0, 0, FL_SUBMENU }, + { "CPU Registers", 0, cb_CpuRegs }, + { "Assembler / IDE", 0, cb_Ide }, + { "Disassembler", 0, disassembler_cb }, + { "Memory Editor", 0, cb_MemoryEditor }, + { "Peripheral Devices", 0, cb_PeripheralDevices }, +// { "Simulation Log Viewer", 0, 0 }, + { "Model T File Viewer", 0, 0 }, + { 0 }, + { 0 } +}; + +void cb_readStatus (Fl_Widget* w, void*) +{ + int mode = inport(REMEM_MODE_PORT); + + rememcfg_ctrl.pRememEnable->value(mode & REMEM_MODE_NORMAL); + rememcfg_ctrl.pIOEnable->value(mode & REMEM_MODE_IOENABLE); + rememcfg_ctrl.pRampacEnable->value(mode & REMEM_MODE_RAMPAC); + rememcfg_ctrl.pStatusMap->value((mode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT); + sprintf(rememcfg_ctrl.sStatus, "0x%02X", mode); + rememcfg_ctrl.pStatus->label(rememcfg_ctrl.sStatus); +} + +void cb_writeStatus (Fl_Widget* w, void*) +{ + int mode; + + mode = (int) rememcfg_ctrl.pStatusMap->value() << REMEM_MODE_MAP_SHIFT; + mode |= rememcfg_ctrl.pIOEnable->value() ? REMEM_MODE_IOENABLE : 0; + mode |= rememcfg_ctrl.pRampacEnable->value() ? REMEM_MODE_RAMPAC: 0; + mode |= rememcfg_ctrl.pRememEnable->value() ? REMEM_MODE_NORMAL: 0; + + out(REMEM_MODE_PORT, mode); + + sprintf(rememcfg_ctrl.sStatus, "0x%02X", mode); + rememcfg_ctrl.pStatus->label(rememcfg_ctrl.sStatus); +} + +int get_region_offset(int region) +{ + if (gModel != MODEL_T200) + return region * 64; + + return (region >> 1) * 128 + (region & 1) * 0x50; +} + +/* +============================================================================ +Routine to read Map data from RAM chip to local storage for editing. +============================================================================ +*/ +void read_map_data(void) +{ + get_memory8_ext(REGION_REMEM_RAM, REMEM_MAP_OFFSET + gMap * REMEM_MAP_SIZE, + REMEM_MAP_SIZE, (unsigned char *) gMapData); +} + +/* +============================================================================ +Routine to read Map data from RAM chip to local storage for editing. +============================================================================ +*/ +void write_map_data(void) +{ + set_memory8_ext(REGION_REMEM_RAM, REMEM_MAP_OFFSET + gMap * REMEM_MAP_SIZE, + REMEM_MAP_SIZE, (unsigned char *) gMapData); +} + +void add_memory_usage(void) +{ + int block, c; + unsigned char mem[512]; // Read memory from ReMem 512 bytes at a time + + // First add RAM usage. Usage is in 512 byte blocks + for (block = 0; block < 4096-520; block++) + { + // Calulate base address + get_memory8_ext(REGION_REMEM_RAM, block*512, 512, mem); + + // Loop through data searching for non-zero + for (c = 0; c < 512; c++) + { + if (mem[c] != 0) + { + rememcfg_ctrl.pRAM->AddUsageEvent(block, block, REMCFG_SECTOR_COLOR); + break; // No need to search further + } + } + } + // Now add Flash1 usage. Usage is in 512 byte blocks + for (block = 0; block < 4096; block++) + { + // Calulate base address + get_memory8_ext(REGION_FLASH1, block*512, 512, mem); + + // Loop through data searching for non-zero + for (c = 0; c < 512; c++) + { + if (mem[c] != 0) + { + rememcfg_ctrl.pFlash1->AddUsageEvent(block, block, REMCFG_SECTOR_COLOR); + break; // No need to search further + } + } + } + // Now add Flash1 usage. Usage is in 512 byte blocks + for (block = 0; block < 4096; block++) + { + // Calulate base address + get_memory8_ext(REGION_FLASH2, block*512, 512, mem); + + // Loop through data searching for non-zero + for (c = 0; c < 512; c++) + { + if (mem[c] != 0) + { + rememcfg_ctrl.pFlash2->AddUsageEvent(block, block, REMCFG_SECTOR_COLOR); + break; // No need to search further + } + } + } +} + +/* +============================================================================ +Routine to update the RAM and FLASH bars based on the current MAP and vector +selection. +============================================================================ +*/ +void update_mem_bars(void) +{ + int c, mapdata; + + // Test if map and region are valid + if ((gMap == -1) || (gRegion == -1)) + return; + + rememcfg_ctrl.pRAM->ClearUsageMap(); + rememcfg_ctrl.pFlash1->ClearUsageMap(); + rememcfg_ctrl.pFlash2->ClearUsageMap(); + + // Add Memory usage information + if (rememcfg_ctrl.pShowUsage->value()) + add_memory_usage(); + + // Loop through all vectors and add entries as appropriate + for (c = 0; c < 256; c++) + { + // Skip unused areas + if (((gModel != MODEL_T200) && (c & 0x20)) || (c >= 192)) + continue; + + mapdata = (unsigned char) gMapData[c*2] + ((unsigned char) gMapData[c*2+1] << 8); + if (mapdata == 0) + continue; + + if (!(mapdata & REMEM_VCTR_RAM_CS)) + rememcfg_ctrl.pRAM->AddUsageEvent((mapdata & REMEM_VCTR_ADDRESS)<<1, + ((mapdata & REMEM_VCTR_ADDRESS)<<1)+1, REMCFG_MAPPING_COLOR); + if (!(mapdata & REMEM_VCTR_FLASH1_CS)) + rememcfg_ctrl.pFlash1->AddUsageEvent((mapdata & REMEM_VCTR_ADDRESS)<<1, + ((mapdata & REMEM_VCTR_ADDRESS)<<1)+1, REMCFG_MAPPING_COLOR); + if (!(mapdata & REMEM_VCTR_FLASH2_CS)) + rememcfg_ctrl.pFlash2->AddUsageEvent((mapdata & REMEM_VCTR_ADDRESS)<<1, + ((mapdata & REMEM_VCTR_ADDRESS)<<1)+1, REMCFG_MAPPING_COLOR); + } + + // Add Rampac memory region + rememcfg_ctrl.pRAM->AddUsageEvent(4096-512, 4095, REMCFG_RAMPAC_COLOR); + + // Add location of the map + rememcfg_ctrl.pRAM->AddUsageEvent((REMEM_MAP_OFFSET + gMap*REMEM_MAP_SIZE) >> 9, + ((REMEM_MAP_OFFSET + gMap*REMEM_MAP_SIZE) >> 9), REMCFG_MAPLOC_COLOR); +} + +/* +============================================================================ +Routine to disable the vector browser and the edit controls. +============================================================================ +*/ +void disable_vector_editing(void) +{ + rememcfg_ctrl.pVectorSelect->deactivate(); + rememcfg_ctrl.pSectorLock->deactivate(); + rememcfg_ctrl.pRamCS->deactivate(); + rememcfg_ctrl.pFlash1CS->deactivate(); + rememcfg_ctrl.pFlash2CS->deactivate(); + rememcfg_ctrl.pMapData->deactivate(); +} + +/* +============================================================================ +Routine to disable the vector browser and the edit controls. +============================================================================ +*/ +void enable_vector_editing(void) +{ + rememcfg_ctrl.pVectorSelect->activate(); + rememcfg_ctrl.pSectorLock->activate(); + rememcfg_ctrl.pRamCS->activate(); + rememcfg_ctrl.pFlash1CS->activate(); + rememcfg_ctrl.pFlash2CS->activate(); + rememcfg_ctrl.pMapData->activate(); +} + +/* +============================================================================ +Routine to update the active vector edit information with based on current +selection in the vector list. +============================================================================ +*/ +void save_vector_edits(void) +{ + int mapdata, address; + const char* pStr; + char temp[20]; + + if ((gRegion == -1) || (gVector == -1)) + return; + + pStr = rememcfg_ctrl.pMapData->value(); + mapdata = 0; + if (pStr[0] != 0) + { + mapdata = str_to_i(pStr) & REMEM_VCTR_ADDRESS; + } + mapdata |= rememcfg_ctrl.pSectorLock->value() ? REMEM_VCTR_READ_ONLY : 0; + mapdata |= rememcfg_ctrl.pRamCS->value() ? REMEM_VCTR_RAM_CS : 0; + mapdata |= rememcfg_ctrl.pFlash1CS->value() ? REMEM_VCTR_FLASH1_CS : 0; + mapdata |= rememcfg_ctrl.pFlash2CS->value() ? REMEM_VCTR_FLASH2_CS : 0; + + address = get_region_offset(gRegion) + (gVector * 2); + if (((unsigned char) gMapData[address] != (mapdata & 0xFF)) || + ((unsigned char) gMapData[address+1] != (mapdata >> 8))) + { + gMapData[address] = mapdata & 0xFF; + gMapData[address+1] = mapdata >> 8; + gMapModified = TRUE; + } + + // Update the vector browser text + sprintf(temp, "%02d 0x%04X", gVector, mapdata); + rememcfg_ctrl.pVectorSelect->text(gVector+1, temp); +} + +/* +============================================================================ +Routine to update the active vector edit information with based on current +selection in the vector list. +============================================================================ +*/ +void update_edit_info(void) +{ + int region, vector; + int mapdata; + char temp[20]; + int regionAddr; + + region = rememcfg_ctrl.pRegionSelect->value(); + vector = rememcfg_ctrl.pVectorSelect->value(); + + if ((region == 0) || (vector == 0)) + { + return; + } + + region--; + vector--; + + regionAddr = get_region_offset(region); + + // Get map data from local storage + mapdata = (unsigned char) gMapData[regionAddr + (vector<<1)] + + ((unsigned char) gMapData[regionAddr + (vector<<1) + 1] << 8); + + // Update controls base on map data + rememcfg_ctrl.pSectorLock->value(mapdata & REMEM_VCTR_READ_ONLY); + rememcfg_ctrl.pRamCS->value(mapdata & REMEM_VCTR_RAM_CS); + rememcfg_ctrl.pFlash1CS->value(mapdata & REMEM_VCTR_FLASH1_CS); + rememcfg_ctrl.pFlash2CS->value(mapdata & REMEM_VCTR_FLASH2_CS); + sprintf(rememcfg_ctrl.sVectorAddress, "0x1BF%03X", gMap * REMEM_MAP_SIZE + + regionAddr + vector * 2); + rememcfg_ctrl.pVectorAddress->label(rememcfg_ctrl.sVectorAddress); + sprintf(temp, "0x%03X", mapdata & REMEM_VCTR_ADDRESS); + rememcfg_ctrl.pMapData->value(temp); +} + +/* +============================================================================ +Routine to update the vector select browser with accurate data base on the +current map and region selections. +============================================================================ +*/ +void update_vector_browser(void) +{ + int region, start; + int c; + char temp[20]; + int vectors; + + region = rememcfg_ctrl.pRegionSelect->value() - 1; + + // If no region is selected, disable the vector browser + if (region == -1) + { + disable_vector_editing(); + return; + } + + // Enable editing + enable_vector_editing(); + + vectors = gModel == MODEL_T200 ? 40 - (region & 1) * 16 : 32; + + // Add or delete vectors in T200 emulation mode as needed + if (gModel == MODEL_T200) + { + if ((vectors == 40) && (rememcfg_ctrl.pVectorSelect->size() == 24)) + { + for (c = 0; c < 16; c++) + rememcfg_ctrl.pVectorSelect->add("XX 0000"); + } + else if ((vectors == 24) && (rememcfg_ctrl.pVectorSelect->size() == 40)) + { + for (c = 0; c < 16; c++) + rememcfg_ctrl.pVectorSelect->remove(25); + if (rememcfg_ctrl.pVectorSelect->value() == 0) + { + rememcfg_ctrl.pVectorSelect->select(1); + rememcfg_ctrl.pVectorSelect->show(1); + } + } + } + + // Now populate the entries with the proper values + start = get_region_offset(region); + for (c = 0; c < vectors; c++) + { + sprintf(temp, "%02d 0x%02X%02X", c, (unsigned char)gMapData[start+(c<<1)+1], + (unsigned char) gMapData[start+(c<<1)]); + rememcfg_ctrl.pVectorSelect->text(c+1, temp); + } + + // Now update the vector edit controls based on new vector browser data + update_edit_info(); +} + +/* +============================================================================ +Callback routine for the RememCfg window +============================================================================ +*/ +void cb_rememcfgwin (Fl_Widget* w, void*) +{ + int ret; + char temp[40]; + + // Test if current map was modified + save_vector_edits(); + if (gMapModified) + { + sprintf(temp, "Save Map %d changes to ReMem RAM?", gMap); + // Ask user if map should be saved + ret = fl_choice(temp, "Cancel", "Yes", "No"); + + // Test for Cancel + if (ret == 0) + return; + + // Test for "Yes" + if (ret == 1) + write_map_data(); + } + + // Hide the window + grmcw->hide(); + + // Delete the window and set to NULL + delete grmcw; + grmcw = NULL; +} + +/* +============================================================================ +Callback function for the Map Select browser. +============================================================================ +*/ +void cb_mapselect (Fl_Widget* w, void*) +{ + int ret, map; + char temp[40]; + + save_vector_edits(); // Save any vector modifications + + map = ((Fl_Browser*)w)->value()-1; + if (map == gMap) + return; + + // Test if current map was modified + if (gMapModified) + { + sprintf(temp, "Save Map %d changes to ReMem RAM?", gMap); + + // Ask user if map should be saved + ret = fl_choice(temp, "Cancel", "Yes", "No"); + + // Test for Cancel + if (ret == 0) + { + rememcfg_ctrl.pMapSelect->select(gMap+1); + return; + } + + // Test for "Yes" + if (ret == 1) + write_map_data(); + + gMapModified = FALSE; + } + + + // Set new gMap value + gMap = map; + + // Read the map data from ReMem RAM + read_map_data(); + + update_vector_browser(); + + // Draw new memory bar information + update_mem_bars(); + + // Update the edit info based on current selection + update_edit_info(); + +} + +void cb_regionselect (Fl_Widget* w, void*) +{ + save_vector_edits(); + update_vector_browser(); + gRegion = ((Fl_Browser*)w)->value()-1; +} + +void cb_vectorselect (Fl_Widget* w, void*) +{ + save_vector_edits(); + update_edit_info(); + gVector = ((Fl_Browser*)w)->value()-1; +} + +/* +============================================================================ +Callback routine for Save Map button +============================================================================ +*/ +void cb_save_map (Fl_Widget* w, void*) +{ + write_map_data(); + gMapModified = FALSE; +} + +/* +============================================================================ +Callback routine for Load Map button +============================================================================ +*/ +void cb_revert_map (Fl_Widget* w, void*) +{ + read_map_data(); + update_vector_browser(); + update_mem_bars(); +} + +void create_default_map(int map) +{ + int c, mapdata; + + // First zero all map memory + for (c = 0; c < sizeof(gMapData); c++) + gMapData[c] = 0; + + // Now create defaults for each region + if (gModel == MODEL_T200) + { + // Rom Region + mapdata = 0x7000; // Default for all maps + for (c = 0; c < 40; c++) + { + gMapData[c*2] = mapdata & 0xFF; + gMapData[c*2 + 1] = mapdata >> 8; + mapdata++; + } + + // RAM 1 Region + if (map == 0) + { + mapdata = 0x1800; + for (c = 40; c < 64; c++) + { + gMapData[c*2] = mapdata & 0xFF; + gMapData[c*2 + 1] = mapdata >> 8; + mapdata++; + } + } + else if (map == 1) + { + mapdata = 0x1818; + for (c = 40; c < 48; c++) + { + gMapData[c*2] = mapdata & 0xFF; + gMapData[c*2 + 1] = mapdata >> 8; + mapdata++; + } + mapdata = 0x1838; + for (c = 48; c < 56; c++) + { + gMapData[c*2] = mapdata & 0xFF; + gMapData[c*2 + 1] = mapdata >> 8; + mapdata++; + } + mapdata = 0x1858; + for (c = 56; c < 64; c++) + { + gMapData[c*2] = mapdata & 0xFF; + gMapData[c*2 + 1] = mapdata >> 8; + mapdata++; + } + } + else + { + mapdata = 0x1890 + (map-2) * 72 ; + for (c = 40; c < 64; c++) + { + gMapData[c*2] = mapdata & 0xFF; + gMapData[c*2 + 1] = mapdata >> 8; + mapdata++; + } + } + // MSPLAN ROM + mapdata = 0x7040; + for (c = 64; c < 96; c++) + { + gMapData[c*2] = mapdata & 0xFF; + gMapData[c*2 + 1] = mapdata >> 8; + mapdata++; + } + // RAM 2 + if (map == 0) + { + mapdata = 0x1820; + for (c = 104; c < 104+24; c++) + { + gMapData[c*2] = mapdata & 0xFF; + gMapData[c*2 + 1] = mapdata >> 8; + mapdata++; + } + } + else + { + mapdata = 0x1860 + (map-1) * 72; + for (c = 104; c < 104+24; c++) + { + gMapData[c*2] = mapdata & 0xFF; + gMapData[c*2 + 1] = mapdata >> 8; + mapdata++; + } + } + // Opt ROM + mapdata = 0x7060 + map*0x20; + for (c = 128; c < 128+32; c++) + { + gMapData[c*2] = mapdata & 0xFF; + gMapData[c*2 + 1] = mapdata >> 8; + mapdata++; + } + // RAM 3 + if (map == 0) + { + mapdata = 0x1840; + for (c = 168; c < 168+24; c++) + { + gMapData[c*2] = mapdata & 0xFF; + gMapData[c*2 + 1] = mapdata >> 8; + mapdata++; + } + } + else + { + mapdata = 0x1878 + (map-1) * 72; + for (c = 168; c < 168+24; c++) + { + gMapData[c*2] = mapdata & 0xFF; + gMapData[c*2 + 1] = mapdata >> 8; + mapdata++; + } + } + } + else + { + // Rom Region + mapdata = 0x7000; // Default for all maps + for (c = 0; c < 32; c++) + { + gMapData[c*2] = mapdata & 0xFF; + gMapData[c*2 + 1] = mapdata >> 8; + mapdata++; + } + + // RAM Region + mapdata = 0x1800 + 0x20 * map; + for (c = 0x40; c < 0x60; c++) + { + gMapData[c*2] = mapdata & 0xFF; + gMapData[c*2 + 1] = mapdata >> 8; + mapdata++; + } + + // Opt ROM Region + mapdata = 0x7000 + 0x20 * (map+1); + for (c = 0x80; c < 0xA0; c++) + { + gMapData[c*2] = mapdata & 0xFF; + gMapData[c*2 + 1] = mapdata >> 8; + mapdata++; + } + } +} +/* +============================================================================ +Callback routine for Default Map button +============================================================================ +*/ +void cb_default_map (Fl_Widget* w, void*) +{ + int ret, c, oldmap; + + ret = fl_choice("Create default map for what?", "Cancel", "Current Map", "All Maps"); + if (ret == 0) + return; + + if (ret == 1) + { + create_default_map(gMap); + gMapModified = TRUE; + } + + if (ret == 2) + { + oldmap = gMap; + for (c = 0; c < 8; c++) + { + gMap = c; + create_default_map(c); + write_map_data(); + } + gMap = oldmap; + read_map_data(); + gMapModified = FALSE; + } + + update_vector_browser(); + update_mem_bars(); +} + +/* +============================================================================ +Callback routine for Copy Sequential button +============================================================================ +*/ +void cb_copy_sequential (Fl_Widget* w, void*) +{ + int mapdata, c, address, vectors; + int regionAddr; + + // Test if selection valid + if ((gMap == -1) || (gRegion == -1) || (gVector == -1)) + return; + + // Get the map data for the current vector + save_vector_edits(); + regionAddr = get_region_offset(gRegion); + address = regionAddr + gVector * 2; + mapdata = (unsigned char) gMapData[address] + ((unsigned char) gMapData[address+1] << 8); + vectors = gModel == MODEL_T200 ? 40-16*(gRegion&1) : 32; + + // Copy current vector to remainder of region + for (c = gVector+1; c < vectors; c++) + { + if (mapdata != 0) + mapdata++; + gMapData[regionAddr + c*2] = mapdata & 0xFF; + gMapData[regionAddr + c*2 + 1] = mapdata >> 8; + } + + gMapModified = 1; + update_vector_browser(); + update_mem_bars(); +} + +/* +============================================================================ +Callback routine for Show Memory Usage checkbox +============================================================================ +*/ +void cb_show_usage (Fl_Widget* w, void*) +{ + update_mem_bars(); +} +/* +============================================================================ +Routine to create the ReMemCfg Window and tabs +============================================================================ +*/ +void cb_RememCfg (Fl_Widget* w, void*) +{ + Fl_Box* o; + int mode = inport(REMEM_MODE_PORT); + char temp[20]; + int x, vectors; + + if (grmcw != NULL) + return; + + // Create Peripheral Setup window + grmcw = new Fl_Window(610, 520, "ReMem Configuration"); + grmcw->callback(cb_rememcfgwin); + + // Create a menu for the new window. + rememcfg_ctrl.pMenu = new Fl_Menu_Bar(0, 0, 630, MENU_HEIGHT-2); + rememcfg_ctrl.pMenu->menu(gRememCfg_menuitems); + + // Create a "Group Box" for the status / control items + rememcfg_ctrl.g = new Fl_Group(15, 15 + MENU_HEIGHT, 580, 120, ""); + rememcfg_ctrl.g->box(FL_EMBOSSED_FRAME); + + o = new Fl_Box(FL_NO_BOX, 250, 30+MENU_HEIGHT, 100, 15, "FW Version:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 30, 30+MENU_HEIGHT, 100, 15, "ReMem Status:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 90, 65+MENU_HEIGHT, 100, 15, "Active Map"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 250, 65+MENU_HEIGHT, 100, 15, "I/O Enable"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 250, 85+MENU_HEIGHT, 100, 15, "Rampac Enable"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 250, 105+MENU_HEIGHT, 100, 15, "ReMem Enable"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + rememcfg_ctrl.pFWVersion = new Fl_Box(360, 30+MENU_HEIGHT, 50, 15, ""); + sprintf(rememcfg_ctrl.sFW, "%d", inport(REMEM_REVID_PORT)); + rememcfg_ctrl.pFWVersion->label(rememcfg_ctrl.sFW); + + rememcfg_ctrl.pStatus = new Fl_Box(130, 30+MENU_HEIGHT, 50, 15, ""); + sprintf(rememcfg_ctrl.sStatus, "0x%02X", mode); + rememcfg_ctrl.pStatus->label(rememcfg_ctrl.sStatus); + + // Create a slider for selecting the active map + rememcfg_ctrl.pStatusMap = new Fl_Value_Slider(20, 85+MENU_HEIGHT, 200, 20, ""); + rememcfg_ctrl.pStatusMap->type(5); + rememcfg_ctrl.pStatusMap->box(FL_FLAT_BOX); + rememcfg_ctrl.pStatusMap->labelsize(8); + rememcfg_ctrl.pStatusMap->precision(0); + rememcfg_ctrl.pStatusMap->range(0, 7); + rememcfg_ctrl.pStatusMap->value((mode & REMEM_MODE_MAP_BITS) >> REMEM_MODE_MAP_SHIFT); + + // Create a check box for the I/O Enable + rememcfg_ctrl.pIOEnable = new Fl_Check_Button(375, 64+MENU_HEIGHT, 20,20,""); + rememcfg_ctrl.pIOEnable->value(mode & REMEM_MODE_IOENABLE); + rememcfg_ctrl.pRampacEnable = new Fl_Check_Button(375, 84+MENU_HEIGHT, 20,20,""); + rememcfg_ctrl.pRampacEnable->value(mode & REMEM_MODE_RAMPAC); + rememcfg_ctrl.pRememEnable = new Fl_Check_Button(375, 104+MENU_HEIGHT, 20,20,""); + rememcfg_ctrl.pRememEnable->value(mode & REMEM_MODE_NORMAL); + + // Create HW Read and Write buttons + rememcfg_ctrl.pReadHW = new Fl_Button(430, 70+MENU_HEIGHT, 140, 20, "Read from HW"); + rememcfg_ctrl.pReadHW->callback(cb_readStatus); + rememcfg_ctrl.pWriteHW = new Fl_Button(430, 100+MENU_HEIGHT, 140, 20, "Write to HW"); + rememcfg_ctrl.pWriteHW->callback(cb_writeStatus); + + rememcfg_ctrl.g->end(); + + // Create a select browser to selet the map + rememcfg_ctrl.pMapSelect = new Fl_Hold_Browser(20, 145+MENU_HEIGHT, 60, 140, 0); + rememcfg_ctrl.pMapSelect->add("Map 0"); + rememcfg_ctrl.pMapSelect->add("Map 1"); + rememcfg_ctrl.pMapSelect->add("Map 2"); + rememcfg_ctrl.pMapSelect->add("Map 3"); + rememcfg_ctrl.pMapSelect->add("Map 4"); + rememcfg_ctrl.pMapSelect->add("Map 5"); + rememcfg_ctrl.pMapSelect->add("Map 6"); + rememcfg_ctrl.pMapSelect->add("Map 7"); + rememcfg_ctrl.pMapSelect->has_scrollbar(0); + rememcfg_ctrl.pMapSelect->select(1); + rememcfg_ctrl.pMapSelect->callback(cb_mapselect); + + // Create a select browser to selet the vector + rememcfg_ctrl.pRegionSelect = new Fl_Hold_Browser(110, 145+MENU_HEIGHT, 130, 140, 0); + if (gModel != MODEL_T200) + { + rememcfg_ctrl.pRegionSelect->add("000-03F ROM"); + rememcfg_ctrl.pRegionSelect->add("040-07F unused"); + rememcfg_ctrl.pRegionSelect->add("080-0BF RAM"); + rememcfg_ctrl.pRegionSelect->add("0C0-0FF unused"); + rememcfg_ctrl.pRegionSelect->add("100-13F OPT"); + rememcfg_ctrl.pRegionSelect->add("140-17F unused"); + rememcfg_ctrl.pRegionSelect->add("180-1BF unused"); + rememcfg_ctrl.pRegionSelect->add("1C0-1FF unused"); + } + else + { + rememcfg_ctrl.pRegionSelect->add("000-04F ROM"); + rememcfg_ctrl.pRegionSelect->add("050-07F RAM 1"); + rememcfg_ctrl.pRegionSelect->add("080-0CF MPLAN"); + rememcfg_ctrl.pRegionSelect->add("0D0-0FF RAM 2"); + rememcfg_ctrl.pRegionSelect->add("100-14F OPT"); + rememcfg_ctrl.pRegionSelect->add("150-17F RAM 3"); + rememcfg_ctrl.pRegionSelect->add("180-1CF unused"); + rememcfg_ctrl.pRegionSelect->add("1D0-1FF unused"); + } + rememcfg_ctrl.pRegionSelect->has_scrollbar(0); + rememcfg_ctrl.pRegionSelect->select(1); + rememcfg_ctrl.pRegionSelect->callback(cb_regionselect); + + rememcfg_ctrl.pVectorSelect = new Fl_Hold_Browser(260, 145+MENU_HEIGHT, 110, 140, 0); + vectors = 40; + if (gModel != MODEL_T200) + vectors = 32; + for (x = 0; x < vectors; x++) + { + sprintf(temp, "%02d 0x0000", x); + rememcfg_ctrl.pVectorSelect->add(temp); + } + rememcfg_ctrl.pVectorSelect->callback(cb_vectorselect); + rememcfg_ctrl.pVectorSelect->select(1); + + // Create controls for editing the vector + o = new Fl_Box(FL_NO_BOX, 390, 145+MENU_HEIGHT, 100, 15, "RAM Address:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + rememcfg_ctrl.pVectorAddress = new Fl_Box(510, 145+MENU_HEIGHT, 100, 15, ""); + sprintf(rememcfg_ctrl.sVectorAddress, "0x1BF000"); + rememcfg_ctrl.pVectorAddress->label(rememcfg_ctrl.sVectorAddress); + + o = new Fl_Box(FL_NO_BOX, 390, 170+MENU_HEIGHT, 100, 15, "Sector Lock"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + rememcfg_ctrl.pSectorLock = new Fl_Check_Button(500, 170+MENU_HEIGHT, 20,20,0); + + o = new Fl_Box(FL_NO_BOX, 390, 190+MENU_HEIGHT, 100, 15, "RAM CS"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + rememcfg_ctrl.pRamCS = new Fl_Check_Button(500, 190+MENU_HEIGHT, 20,20,0); + + o = new Fl_Box(FL_NO_BOX, 390, 210+MENU_HEIGHT, 100, 15, "Flash 1 CS"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + rememcfg_ctrl.pFlash1CS = new Fl_Check_Button(500, 210+MENU_HEIGHT, 20,20,0); + + o = new Fl_Box(FL_NO_BOX, 390, 230+MENU_HEIGHT, 100, 15, "Flash 2 CS"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + rememcfg_ctrl.pFlash2CS = new Fl_Check_Button(500, 230+MENU_HEIGHT, 20,20,0); + + o = new Fl_Box(FL_NO_BOX, 390, 255+MENU_HEIGHT, 100, 15, "Map Data"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + rememcfg_ctrl.pMapData = new Fl_Input(500, 255+MENU_HEIGHT, 90,20,0); + + // Create buttons for managing the map + rememcfg_ctrl.pSaveMap = new Fl_Button(40, 295+MENU_HEIGHT, 80, 20, "Save Map"); + rememcfg_ctrl.pSaveMap->callback(cb_save_map); + rememcfg_ctrl.pLoadMap = new Fl_Button(140, 295+MENU_HEIGHT, 90, 20, "Revert Map"); + rememcfg_ctrl.pLoadMap->callback(cb_revert_map); + rememcfg_ctrl.pDefaultMap = new Fl_Button(260, 295+MENU_HEIGHT, 90, 20, "Default Map"); + rememcfg_ctrl.pDefaultMap->callback(cb_default_map); + rememcfg_ctrl.pCopySequential = new Fl_Button(420, 295+MENU_HEIGHT, 120, 20, "Copy Sequential"); + rememcfg_ctrl.pCopySequential->callback(cb_copy_sequential); + + // Create a box for RAM + o = new Fl_Box(FL_NO_BOX, 20, 365, 100, 15, "RAM"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + rememcfg_ctrl.pRAM = new Fl_Usage_Box(80, 355, 516, 36); + rememcfg_ctrl.pRAM->box(FL_BORDER_BOX); + rememcfg_ctrl.pRAM->SetUsageColor(REMCFG_MAPPING_COLOR, fl_rgb_color(225, 225, 0)); + rememcfg_ctrl.pRAM->SetUsageColor(REMCFG_SECTOR_COLOR, fl_rgb_color(128, 128, 0)); + rememcfg_ctrl.pRAM->SetUsageColor(REMCFG_COMBO_COLOR, fl_rgb_color(225, 0, 0)); + rememcfg_ctrl.pRAM->SetUsageColor(REMCFG_RAMPAC_COLOR, fl_rgb_color(225, 225, 225)); + rememcfg_ctrl.pRAM->SetUsageColor(REMCFG_MAPLOC_COLOR, fl_rgb_color(0, 0, 225)); + rememcfg_ctrl.pRAM->SetUsageColor(REMCFG_MAPSEL_COLOR, fl_rgb_color(0, 0, 225)); + rememcfg_ctrl.pRAM->SetUsageRange(0, 4095); + rememcfg_ctrl.pRAM->AddUsageEvent(4096-512, 4095, REMCFG_RAMPAC_COLOR); + + // Create a box for Flash1 + o = new Fl_Box(FL_NO_BOX, 20, 405, 100, 15, "Flash1"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + rememcfg_ctrl.pFlash1 = new Fl_Usage_Box(80, 395, 516, 36); + rememcfg_ctrl.pFlash1->box(FL_BORDER_BOX); + rememcfg_ctrl.pFlash1->SetUsageColor(REMCFG_MAPPING_COLOR, fl_rgb_color(225, 225, 0)); + rememcfg_ctrl.pFlash1->SetUsageColor(REMCFG_SECTOR_COLOR, fl_rgb_color(128, 128, 0)); + rememcfg_ctrl.pFlash1->SetUsageColor(REMCFG_COMBO_COLOR, fl_rgb_color(225, 0, 0)); + rememcfg_ctrl.pFlash1->SetUsageRange(0, 4095); + + // Create a box for Flash2 + o = new Fl_Box(FL_NO_BOX, 20, 445, 100, 15, "Flash2"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + rememcfg_ctrl.pFlash2 = new Fl_Usage_Box(80, 435, 516, 36); + rememcfg_ctrl.pFlash2->box(FL_BORDER_BOX); + rememcfg_ctrl.pFlash2->SetUsageColor(REMCFG_MAPPING_COLOR, fl_rgb_color(225, 225, 0)); + rememcfg_ctrl.pFlash2->SetUsageColor(REMCFG_SECTOR_COLOR, fl_rgb_color(128, 128, 0)); + rememcfg_ctrl.pFlash2->SetUsageColor(REMCFG_COMBO_COLOR, fl_rgb_color(225, 0, 0)); + rememcfg_ctrl.pFlash2->SetUsageRange(0, 4095); + + o = new Fl_Box(FL_NO_BOX, 20, 485, 100, 15, "Show Memory Usage"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + rememcfg_ctrl.pShowUsage = new Fl_Check_Button(170, 484, 20,20,""); + rememcfg_ctrl.pShowUsage->value(1); + rememcfg_ctrl.pShowUsage->callback(cb_show_usage); + + // Create color code boxes + o = new Fl_Box(FL_NO_BOX, 230, 480, 60, 15, "Free"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_DOWN_BOX, 290, 480, 15, 15, ""); + o->color(fl_rgb_color(255, 255, 255)); + + o = new Fl_Box(FL_NO_BOX, 230, 500, 60, 15, "Used"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_DOWN_BOX, 290, 500, 15, 15, ""); + o->color(fl_rgb_color(128, 128, 0)); + + o = new Fl_Box(FL_NO_BOX, 340, 480, 60, 15, "Mapped"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_DOWN_BOX, 410, 480, 15, 15, ""); + o->color(fl_rgb_color(255, 255, 0)); + + o = new Fl_Box(FL_NO_BOX, 340, 500, 60, 15, " (used)"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_DOWN_BOX, 410, 500, 15, 15, ""); + o->color(fl_rgb_color(255, 0, 0)); + + o = new Fl_Box(FL_NO_BOX, 470, 480, 60, 15, "Map "); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_DOWN_BOX, 550, 480, 15, 15, ""); + o->color(fl_rgb_color(0, 0, 225)); + + o = new Fl_Box(FL_NO_BOX, 470, 500, 60, 15, "Rampac"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_DOWN_BOX, 550, 500, 15, 15, ""); + o->color(fl_rgb_color(225, 225, 225)); + + gMapModified = FALSE; + gMap = 0; + gRegion = 0; + gVector = 0; + + read_map_data(); /* Get map data for map 0 */ + update_vector_browser(); + update_mem_bars(); /* Draw the memory data */ + + // Show the new window + grmcw->show(); +} diff --git a/src/rememcfg.h b/src/rememcfg.h new file mode 100644 index 0000000..e91ba22 --- /dev/null +++ b/src/rememcfg.h @@ -0,0 +1,97 @@ +/* rememcfg.h */ + +/* $Id$ */ + +/* +* Copyright 2008 Ken Pettit +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +*/ + + +#ifndef REMEMCFG_H +#define REMEMCFG_H + +#include +#include +#include +#include +#include +#include +#include +#include "fl_usage_box.h" + +#define REMCFG_MAPPING_COLOR 1 +#define REMCFG_SECTOR_COLOR 2 +#define REMCFG_COMBO_COLOR 3 +#define REMCFG_RAMPAC_COLOR 4 +#define REMCFG_MAPLOC_COLOR 5 +#define REMCFG_MAPSEL_COLOR 6 + +void cb_RememCfg(Fl_Widget* w, void*); + +typedef struct rememcfg_ctrl_struct +{ + Fl_Menu_Bar* pMenu; + + Fl_Box* pFWVersion; + Fl_Box* pStatus; + Fl_Value_Slider* pStatusMap; + Fl_Check_Button* pIOEnable; + Fl_Check_Button* pRampacEnable; + Fl_Check_Button* pRememEnable; + Fl_Button* pReadHW; + Fl_Button* pWriteHW; + + Fl_Hold_Browser* pMapSelect; + Fl_Hold_Browser* pRegionSelect; + Fl_Hold_Browser* pVectorSelect; + Fl_Box* pVectorAddress; + + Fl_Input* pMapData; + Fl_Check_Button* pRamCS; + Fl_Check_Button* pFlash1CS; + Fl_Check_Button* pFlash2CS; + Fl_Check_Button* pSectorLock; + + Fl_Usage_Box* pRAM; + Fl_Usage_Box* pFlash1; + Fl_Usage_Box* pFlash2; + + char sFW[10]; + char sStatus[10]; + char sVectorAddress[10]; + char sMap[8][120]; + + Fl_Button* pSaveMap; + Fl_Button* pLoadMap; + Fl_Button* pDefaultMap; + Fl_Button* pCopySequential; + Fl_Check_Button* pShowUsage; + + Fl_Group* g; + +} rememcfg_ctrl_t; + + +#endif + diff --git a/src/remote.cpp b/src/remote.cpp new file mode 100644 index 0000000..bbc00e5 --- /dev/null +++ b/src/remote.cpp @@ -0,0 +1,2301 @@ +/* remote.cpp */ + +/* $Id$ */ + +/* + * Copyright 2008 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#ifdef WIN32 +#include +#include +#else +#include +#endif + +#include "VirtualT.h" +#include "m100emu.h" +#include "remote.h" +#include "socket.h" +#include "serversocket.h" +#include "socketexception.h" +#include "cpu.h" +#include "memory.h" +#include "io.h" +#include "roms.h" +#include "romstrings.h" +#include "disassemble.h" + + +#ifdef WIN32 +HANDLE gRemoteThread; // The remote control thread +HANDLE gRemoteLock; // Lock to access emulation +#else +pthread_t gRemoteThread; // The remote control thread +pthread_mutex_t gRemoteLock; // Lock to access emulation +#endif + +int gRadix = 10; // Radix used for reporting values +int gRemoteBreak[65536];// Storage of breakpoint types +int gBreakActive = 0; // Indicates if an active debug was reported +int gHaltActive = 0; // Indicates if an active halt was issued +int gLcdTrapAddr = -1; // Address of LCD level 6 output routine +int gLcdRowAddr = -1; // Address of LCD output row storage +int gMonitorLcd = 0; // Flag indicating if LCD is monitored +std::string gLcdString; // String being sent to LCD +UINT64 gLcdUpdateCycle; // Cycle time when LCD last updated +int gLcdTimeoutCycles; // Number of cycles for the string timeout +int gLcdRow = -1; // Current LCD update row +int gLcdCol = -1; // Current LCD update col +int gLcdColStart = -1; // Column where current string started +ServerSocket gOpenSock; +int gSocketOpened = FALSE; +lcd_rect_t gIgnoreRects[10]; +int gIgnoreCount = 0; +int gLastDisAddress = 0; +int gTraceOpen = 0; +int gTraceActive = 0; +std::string gTraceFile; +FILE* gTraceFileFd; +VTDis gTraceDis; + +int remote_cpureg_stop(void); +int remote_cpureg_run(void); +int remote_cpureg_step(void); +void remote_reset(void); +void remote_cold_boot(void); +int remote_load_from_host(const char *filename); +void remote_set_speed(int speed); +int str_to_i(const char *pStr); +void remote_switch_model(int model); +extern int fullspeed; +extern int fl_wait(double); +extern void simulate_keydown(int key); +extern void simulate_keyup(int key); + +extern "C" +{ +extern int gDelayUpdateKeys; +extern UINT64 cycles; +extern RomDescription_t *gStdRomDesc; +void process_windows_event(void); +} + +#define LCD_TIMEOUT_NORMAL 100000 + +/* +======================================================= +Help command: Send list of supported commands +======================================================= +*/ +std::string cmd_help(ServerSocket& sock) +{ + sock << "Help\n====\n"; + sock << " clear_break(cb) address\n"; + sock << " cold_boot\n"; + sock << " dis address [lines]\n"; + sock << " flags [all S Z ac P=1 s=0 ...]\n"; + sock << " halt\n"; + sock << " in port\n"; + sock << " key [enter f1 esc ctrl+c shift+code+a \"Text\" ...]\n"; + sock << " lcd_ignore(li) [none (row,col)-(row,col)]\n"; + sock << " lcd_mon(lm) [on off]\n"; + sock << " list_break(lb)\n"; + sock << " load filename\n"; + sock << " model [m100 m102 t200 pc8201 m10]\n"; + sock << " out port, value\n"; + sock << " radix [10 or 16]\n"; + sock << " read_mem(rm) address [count]\n"; + sock << " read_reg(rr) [all A B h m DE ...]\n"; + sock << " reset\n"; + sock << " run\n"; + sock << " set_break(sb) address [main opt mplan ram ram2 ram3]\n"; + sock << " speed [2.4 friendly max]\n"; + sock << " step [count]\n"; + sock << " string address\n"; + sock << " terminate\n"; + sock << " write_mem(wm) address [data data data ...]\n"; + sock << " write_reg(wr) [A=xx B=xx hl=xx ...]\n"; + + return "Ok"; +} + +/* +======================================================= +LCD String timeout routine +======================================================= +*/ +void handle_lcd_timeout() +{ + char str[120]; + + if ((int) (cycles - gLcdUpdateCycle) > gLcdTimeoutCycles) + { + // New string being written. Send the old one + sprintf(str, "event, lcdwrite, (%d,%d),%s\n", gLcdRow, gLcdColStart, + gLcdString.c_str()); + if (gSocketOpened) + gOpenSock << str; + gLcdUpdateCycle = (UINT64) -1; + gLcdRow = -1; + gLcdColStart = -1; + gLcdString = ""; + } +} + +/* +======================================================= +Remote debug monitor routine. This is called from the +main execution thread and loop! +======================================================= +*/ +void handle_lcd_trap() +{ + int row, col; + int c; + char str[120]; + + // Get row and column + row = get_memory8(gLcdRowAddr); + col = get_memory8(gLcdRowAddr+1); + + // Test if there are any ignore regions + if (gIgnoreCount) + { + // Loop through all ignore rects + for (c = 0; c < gIgnoreCount; c++) + { + // Test if row,col is in this region + if ((row >= gIgnoreRects[c].top_row) && + (row <= gIgnoreRects[c].bottom_row) && + (col >= gIgnoreRects[c].top_col) && + (col <= gIgnoreRects[c].bottom_col)) + { + return; + } + } + } + + // Test if this is a new string + if ((row != gLcdRow) || (col != gLcdCol +1)) + { + if (gLcdRow != -1) + { + // New string being written. Send the old one + sprintf(str, "event, lcdwrite, (%d,%d),%s\n", gLcdRow, gLcdColStart, + gLcdString.c_str()); + if (gSocketOpened) + gOpenSock << str; + } + + // Start a new string + gLcdString = ""; + + // Now save the Row & Col as the start of the new string + gLcdColStart = col; + } + + // Save the byte being written to the display + gLcdString += C; + + // Now update the current row/col + gLcdRow = row; + gLcdCol = col; + + // Save the cycle count for timeout purposes + gLcdUpdateCycle = cycles; +} + +/* +======================================================= +Remote debug monitor routine. This is called from the +main execution thread and loop! +======================================================= +*/ +void cb_remote_debug(int reason) +{ + unsigned char bank; + char str[40]; + + // Check if trace is on + if (gTraceActive && gTraceOpen) + { +/* gTraceDis.DisassembleLine(PC, line); + len = strlen(line); + for (c = len; c < 28; c++) + line[c] = ' '; + line[c] = 0; + + // Add flags +*/ + + // Print to file + fprintf(gTraceFileFd, "%04X\n", PC); + } + + // Check if the processor is stopped. + if (!gStopped) + { + // Check if there is a breakpoint for this address + if (gRemoteBreak[PC] != 0) + { + // Check if the correct bank is selected + if (PC < ROMSIZE) + { + bank = get_rom_bank(); + if ((gModel == MODEL_T200) && (bank != 0)) + bank ^= 0x03; + if ((bank == 0) && (gRemoteBreak[PC] & BPTYPE_MAIN)) + gStopped = 1; + if ((bank == 1) && (gRemoteBreak[PC] & BPTYPE_OPT)) + gStopped = 1; + if ((bank == 2) && (gRemoteBreak[PC] & BPTYPE_MPLAN)) + gStopped = 1; + } + else + { + bank = get_ram_bank(); + if ((bank == 0) && (gRemoteBreak[PC] & BPTYPE_RAM)) + gStopped = 1; + if ((bank == 1) && (gRemoteBreak[PC] & BPTYPE_RAM2)) + gStopped = 1; + if ((bank == 2) && (gRemoteBreak[PC] & BPTYPE_RAM3)) + gStopped = 1; + } + + // Report break to client socket + if (gStopped) + { + if (gSocketOpened) + { + if (gRadix == 10) + sprintf(str, "event, break, PC=%d\n", PC); + else + sprintf(str, "event, break, PC=%04X\n", PC); + gOpenSock << str; + } + } + } + } + + // Trap output to the display + if ((PC == gLcdTrapAddr) && (get_rom_bank() == 0)) + handle_lcd_trap(); + // Perform LCD string timeout processing + if (gLcdUpdateCycle != (UINT64) -1) + handle_lcd_timeout(); +} + +/* +======================================================= +Parse next argument from argumen list. +======================================================= +*/ +std::string get_next_arg(std::string& more_args) +{ + std::string next_arg; + int pos; + + // Extract string of next byte to be written + pos = more_args.find(' '); + if (pos != -1) + { + next_arg = more_args.substr(0, pos); + more_args = more_args.substr(pos+1, more_args.length()-pos-1); + } + else + { + next_arg = more_args; + more_args = ""; + } + + return next_arg; +} + +/* +======================================================= +Terminate command: Send list of supported commands +======================================================= +*/ +std::string cmd_terminate(ServerSocket& sock) +{ + gExitApp = TRUE; + gExitLoop = TRUE; + return "Ok"; +} + +/* +======================================================= +Status command: Report status of CPU and any async + events. +======================================================= +*/ +std::string cmd_status(ServerSocket& sock) +{ + char modelStr[10]; + char retStr[80]; + + get_model_string(modelStr, gModel); + + if (gStopped) + sprintf(retStr, "Model=%s, CPU halted\nOk", modelStr); + else + sprintf(retStr, "Model=%s, CPU running\nOk", modelStr); + + return retStr; + +} + +/* +======================================================= +Halt command: Halt the CPU +======================================================= +*/ +std::string cmd_halt(ServerSocket& sock) +{ + if (!gStopped) + if (!remote_cpureg_stop()) + { + lock_remote(); + gDebugActive++; + gHaltActive = 1; + gStopped = 1; + unlock_remote(); + } + + return "Ok"; +} + +/* +======================================================= +Reset command: Reset the CPU +======================================================= +*/ +std::string cmd_reset(ServerSocket& sock) +{ + remote_reset(); + return "Ok"; +} + +/* +======================================================= +Cold Boot command: Cold boot the machine +======================================================= +*/ +std::string cmd_cold_boot(ServerSocket& sock) +{ + remote_cold_boot(); + return "Ok"; +} + +/* +======================================================= +Run command: Resume the CPU +======================================================= +*/ +std::string cmd_run(ServerSocket& sock) +{ + // Check if CPU running. Continue only if halted + if (gStopped) + if (!remote_cpureg_run()) + { + lock_remote(); + if (gHaltActive) + { + gDebugActive--; + gHaltActive = 0; + } + gStopped = 0; + unlock_remote(); + } + + return "Ok"; +} + +/* +======================================================= +Step command: Single steps the CPU the specified + number of steps. +======================================================= +*/ +std::string cmd_step(ServerSocket& sock, std::string& args) +{ + int value; + std::string next_arg; + std::string more_args; + int c; + + // If argument list is empty, assume 1 + if (args == "") + { + next_arg = "1"; + } + else + { + // Get first parameter if more than 1 + next_arg = get_next_arg(args); + } + + // Get address of read + value = str_to_i(next_arg.c_str()); + if (value < 0) + return "Parameter Error\nOk"; + + // Loop for each step + for (c = 0; c < value; c++) + { + lock_remote(); + gSingleStep = 1; + unlock_remote(); + + while (gSingleStep) + fl_wait(0.001); + } + + return "Ok"; +} + +int get_address(std::string arg) +{ + int address; + + // Convert address to lower + std::transform(arg.begin(), arg.end(), arg.begin(), (int(*)(int)) std::tolower); + + // Get address + if (arg == "pc") + address = PC; + else if (arg == "hl") + address = HL; + else if (arg == "de") + address = DE; + else if (arg == "bc") + address = BC; + else if (arg == "sp") + address = SP; + else + address = str_to_i(arg.c_str()); + + return address; +} + +/* +======================================================= +Write Mem command: Writes data to memory space +======================================================= +*/ +std::string cmd_write_mem(ServerSocket& sock, std::string& args) +{ + int address; + int value; + std::string next_arg; + std::string more_args; + + // Separate the address from the other args + more_args = args; + next_arg = get_next_arg(more_args); + + // Get address of read + address = get_address(next_arg); + + // Loop through all data to be written + lock_remote(); + while (more_args != "") + { + // Extract string of next byte to be written + next_arg = get_next_arg(more_args); + + // Convert string to integer + value = str_to_i(next_arg.c_str()); + + // Write byte to memory + set_memory8(address++, value); + } + unlock_remote(); + + return "Ok"; +} + +/* +======================================================= +Read Mem command: Reads data to memory space +======================================================= +*/ +std::string cmd_read_mem(ServerSocket& sock, std::string& args) +{ + int address; + int len, c; + std::string next_arg; + std::string more_args; + std::string ret; + char str[10]; + + // Separate arguments + more_args = args; + next_arg = get_next_arg(more_args); + + address = get_address(next_arg); + + // Get length of + if (more_args != "") + len = str_to_i(more_args.c_str()); + else + len = 1; + + // Build string of return values + ret = ""; + lock_remote(); + for (c = 0; c < len; c++) + { + if (gRadix == 10) + sprintf(str, "%d ", get_memory8(address++)); + else + sprintf(str, "%02X ", get_memory8(address++)); + + ret += str; + } + unlock_remote(); + ret += "\n"; + + return ret + "Ok"; +} + +/* +======================================================= +Read reg command: Reads registers +======================================================= +*/ +std::string cmd_read_reg(ServerSocket& sock, std::string& args) +{ + std::string next_arg; + std::string more_args; + std::string format_str; + std::string format_str16; + std::string ret=""; + char reg_str[100]; + + // Lock the global access object so the registers are stable + lock_remote(); + + // Parse the registers and build a reply string + if (args == "all") + { + if (gRadix == 10) + sprintf(reg_str, "A=%d F=%d B=%d C=%d D=%d E=%d H=%d L=%d M=%d PC=%d SP=%d\nOk", + A, F, B, C, D, E, H, L, M, PC, SP); + else + sprintf(reg_str, "A=%02X F=%02X B=%02X C=%02X D=%02X E=%02X H=%02X L=%02X M=%02X PC=%04X SP=%04X\nOk", + A, F, B, C, D, E, H, L, M, PC, SP); + unlock_remote(); + return reg_str; + } + else + { + if (gRadix == 10) + { + format_str = "%d "; + format_str16 = "%d "; + } + else + { + format_str = "%02X "; + format_str16 = "%04X "; + } + more_args = args; + // Convert to lower + std::transform(more_args.begin(), more_args.end(), more_args.begin(), (int(*)(int)) std::tolower); + + while (more_args != "") + { + next_arg = get_next_arg(more_args); + + // Now figure out which reg it is + if (next_arg == "a") + { + sprintf(reg_str, format_str.c_str(), A); + ret += reg_str; + } + else if (next_arg == "b") + { + sprintf(reg_str, format_str.c_str(), B); + ret += reg_str; + } + else if (next_arg == "c") + { + sprintf(reg_str, format_str.c_str(), C); + ret += reg_str; + } + else if (next_arg == "d") + { + sprintf(reg_str, format_str.c_str(), D); + ret += reg_str; + } + else if (next_arg == "e") + { + sprintf(reg_str, format_str.c_str(), E); + ret += reg_str; + } + else if (next_arg == "h") + { + sprintf(reg_str, format_str.c_str(), H); + ret += reg_str; + } + else if (next_arg == "l") + { + sprintf(reg_str, format_str.c_str(), L); + ret += reg_str; + } + else if (next_arg == "f") + { + sprintf(reg_str, format_str.c_str(), F); + ret += reg_str; + } + else if (next_arg == "m") + { + sprintf(reg_str, format_str.c_str(), M); + ret += reg_str; + } + else if (next_arg == "bc") + { + sprintf(reg_str, format_str16.c_str(), BC); + ret += reg_str; + } + else if (next_arg == "de") + { + sprintf(reg_str, format_str16.c_str(), DE); + ret += reg_str; + } + else if (next_arg == "hl") + { + sprintf(reg_str, format_str16.c_str(), HL); + ret += reg_str; + } + else if (next_arg == "pc") + { + sprintf(reg_str, format_str16.c_str(), PC); + ret += reg_str; + } + else if (next_arg == "sp") + { + sprintf(reg_str, format_str16.c_str(), SP); + ret += reg_str; + } + + else + { + ret += "xx "; + } + } + unlock_remote(); + return ret + "\nOk"; + } + return "Ok"; +} + +/* +======================================================= +Write reg command: Writes registers +======================================================= +*/ +std::string cmd_write_reg(ServerSocket& sock, std::string& args) +{ + std::string next_arg; + std::string more_args; + std::string regStr; + std::string valueStr; + int pos; + int value; + + // Convert to lower + more_args = args; + std::transform(more_args.begin(), more_args.end(), more_args.begin(), (int(*)(int)) std::tolower); + + // Lock the global access object so the registers are stable + lock_remote(); + + // Loop through all arguments + while (more_args != "") + { + // Get next argument from arg list + next_arg = get_next_arg(more_args); + + // Split argument into reg and value + pos = next_arg.find('='); + if (pos == -1) + { + unlock_remote(); + return "Parameter Error\nOk"; + } + regStr = next_arg.substr(0, pos); + valueStr = next_arg.substr(pos+1, next_arg.length()-pos-1); + value = str_to_i(valueStr.c_str()); + + // Now update the register + if (regStr == "a") + A = value; + else if (regStr == "b") + B = value; + else if (regStr == "c") + C = value; + else if (regStr == "d") + D = value; + else if (regStr == "e") + E = value; + else if (regStr == "h") + H = value; + else if (regStr == "l") + L = value; + else if (regStr == "f") + F = value; + else if (regStr == "m") + M = value; + else if (regStr == "bc") + { + B = value >> 8; + C = value & 0xFF; + } + else if (regStr == "de") + { + D = value >> 8; + E = value & 0xFF; + } + else if (regStr == "hl") + { + H = value >> 8; + L = value & 0xFF; + } + else if (regStr == "pc") + { + PCH = value >> 8; + PCL = value & 0xFF; + } + else if (regStr == "sp") + { + SPH = value >> 8; + SPL = value & 0xFF; + } + } + + // Unlock access to remote control + unlock_remote(); + + return "Ok"; +} + +/* +======================================================= +Load command: Loads a target file from the host +======================================================= +*/ +std::string cmd_load(ServerSocket& sock, std::string& args) +{ + if (remote_load_from_host(args.c_str())) + return "Load Error\nOk"; + + return "Ok"; +} + +/* +======================================================= +Radix command: Changes the radix +======================================================= +*/ +std::string cmd_radix(ServerSocket& sock, std::string& args) +{ + char str[10]; + + if (args == "") + { + sprintf(str, "%d\nOk", gRadix); + return str; + } + + if ((args != "10") && (args != "16")) + return "Parameter error\nOk"; + + gRadix = str_to_i(args.c_str()); + return "Ok"; +} + +/* +======================================================= +In command: Prints data from the specified I/O port +======================================================= +*/ +std::string cmd_in(ServerSocket& sock, std::string& args) +{ + int port; + char str[20]; + + // Ensure there are params + if (args == "") + return "Parameter error\nOk"; + + // Convert the port # to integer + port = str_to_i(args.c_str()); + + // Report the value based on radix + if (gRadix = 10) + sprintf(str, "%d\nOk", inport(port)); + else + sprintf(str, "%02X\nOk", inport(port)); + return str; +} + +/* +======================================================= +Flags command: Print or set the CPU flags +======================================================= +*/ +std::string cmd_flags(ServerSocket& sock, std::string& args) +{ + std::string next_arg; + std::string more_args; + std::string regStr; + std::string valueStr; + std::string str; + int pos; + int value; + char cstr[10]; + + // Test if flags should be set or printed + lock_remote(); + if (args == "") + { + // Print all flags that are set + if (ZF) str += "Z "; + if (SF) str += "S "; + if (CF) str += "C "; + if (PF) str += "P "; + if (OV) str += "OV "; + if (AC) str += "AC "; + if (TS) str += "TS "; + if (str == "") str = "(none)"; + str += "\n"; + } + else + { + // Okay we have parameters. Loop through each and test if setting + // or requesting status + more_args = args; + + // Convert to lower + std::transform(more_args.begin(), more_args.end(), more_args.begin(), (int(*)(int)) std::tolower); + + // Loop through all arguments + while (more_args != "") + { + // Get next argument from arg list + next_arg = get_next_arg(more_args); + + // Now check if this arg is being set or requested + pos = next_arg.find('='); + if (pos == -1) + { + // Report the status of this flag + cstr[0] = 0; + if ((next_arg == "z") || (next_arg == "all")) {sprintf(cstr, "Z=%d ", ZF);str+=cstr;} + if ((next_arg == "s") || (next_arg == "all")) {sprintf(cstr, "S=%d ", SF);str+=cstr;} + if ((next_arg == "c") || (next_arg == "all")) {sprintf(cstr, "C=%d ", CF);str+=cstr;} + if ((next_arg == "p") || (next_arg == "all")) {sprintf(cstr, "P=%d ", PF);str+=cstr;} + if ((next_arg == "ov") || (next_arg == "all")) {sprintf(cstr, "OV=%d ", OV);str+=cstr;} + if ((next_arg == "ac") || (next_arg == "all")) {sprintf(cstr, "AC=%d ", AC);str+=cstr;} + if ((next_arg == "ts") || (next_arg == "all")) {sprintf(cstr, "TS=%d ", TS);str+=cstr;} + } + else + { + // Okay, tring to set a flag, parse the args + regStr = next_arg.substr(0, pos); + valueStr = next_arg.substr(pos+1, next_arg.length()-pos-1); + value = str_to_i(valueStr.c_str()); + + // Set the flag + if (regStr == "z") + { + if (value) F |= ZF_BIT; else F &= ~ZF_BIT; + } + else if (regStr == "c") + { + if (value) F |= CF_BIT; else F &= ~CF_BIT; + } + else if (regStr == "s") + { + if (value) F |= SF_BIT; else F &= ~SF_BIT; + } + else if (regStr == "p") + { + if (value) F |= PF_BIT; else F &= ~PF_BIT; + } + else if (regStr == "ov") + { + if (value) F |= OV_BIT; else F &= ~OV_BIT; + } + else if (regStr == "ac") + { + if (value) F |= AC_BIT; else F &= ~AC_BIT; + } + else if (regStr == "ts") + { + if (value) F |= TS_BIT; else F &= ~TS_BIT; + } + } + } + str += "\n"; + } + str += "Ok"; + + unlock_remote(); + return str; +} + +/* +======================================================= +Out command: Sends data to the specified I/O port +======================================================= +*/ +std::string cmd_out(ServerSocket& sock, std::string& args) +{ + int port; + int pos, value; + std::string portStr, valStr; + + // Validate there are parameters + if (args == "") + return "Parameter error\nOk"; + + // Find the comma separating the port and value + pos = args.find(','); + if (pos != -1) + { + // Comma found, separate port and value strings + portStr = args.substr(0, pos); + valStr = args.substr(pos + 1, args.length()-pos-1); + + // Check for a space after the comma + if (valStr[0] == ' ') + valStr = valStr.substr(1, valStr.length()-1); + } + else + { + // No comma found, check for space separated params + pos = args.find(' '); + if (pos != -1) + { + // Space found. Separate port and value strings + portStr = args.substr(0, pos); + valStr = args.substr(pos + 1, args.length()-pos-1); + } + else + { + // Invalid format + return "Parameter Error\nOk"; + } + } + + // Convert to integer + port = str_to_i(portStr.c_str()); + value = str_to_i(valStr.c_str()); + + // Perform the out function + out(port, value); + return "Ok"; +} + +/* +======================================================= +Set Break command: Sets a breakpoint and configures + the remote debugger for debug monitoring if needed. +======================================================= +*/ +std::string cmd_set_break(ServerSocket& sock, std::string& args) +{ + std::string next_arg; + std::string more_args; + std::string regStr; + std::string valueStr; + int value, address; + + // Get breakpoint arguments + more_args = args; + next_arg = get_next_arg(more_args); + + // Convert address + address = get_address(next_arg); + if ((address > 65535) || (address < 0)) + return "Parameter Error\nOk"; + + // Determine the types of breaks + if (more_args == "") + { + // Not specified - break for all + if (gModel == MODEL_T200) + { + if (address < ROMSIZE) + value = 0x07; // All T200 Banks + else + value = 0x38; // All T200 Banks + } + else + { + if (address < ROMSIZE) + value = 0x03; // Main & Opt + else + value = 0x08; // RAM + } + } + else + { + // Convert to lower + std::transform(more_args.begin(), more_args.end(), more_args.begin(), (int(*)(int)) std::tolower); + + value = 0; + + // Loop through all arguments + while (more_args != "") + { + // Get next argument from arg list + next_arg = get_next_arg(more_args); + + // Determine type of this break + if (next_arg == "ram2") value |= BPTYPE_RAM2; + if (next_arg == "ram3") value |= BPTYPE_RAM3; + if (next_arg == "main") value |= BPTYPE_MAIN; + if (next_arg == "opt") value |= BPTYPE_OPT; + if (next_arg == "mplan") value |= BPTYPE_MPLAN; + if (next_arg == "ram") value |= BPTYPE_RAM; + } + + if (value == 0) + { + return "Parameter Error\nOk"; + } + } + + // Okay, now set the breakpoint + lock_remote(); + gRemoteBreak[address] = value; + + // Check if we need to increment the gDebugActive variable + if (!gBreakActive) + gDebugActive++; + gBreakActive = 1; + + // Unlock access to global vars + unlock_remote(); + + return "Ok"; +} + +/* +======================================================= +Clear Break command: Clears one or more breakpoints. +======================================================= +*/ +std::string cmd_clear_break(ServerSocket& sock, std::string& args) +{ + std::string next_arg; + std::string more_args; + int address; + int c; + + // Get breakpoint arguments + more_args = args; + next_arg = get_next_arg(more_args); + + // Check if all breakpoints being cleared + if (next_arg == "all") + { + for (c = 0; c < 65536; c++) + gRemoteBreak[c] = 0; + } + else + { + // Convert address + address = get_address(next_arg); + if ((address > 65535) || (address < 0)) + return "Parameter Error\nOk"; + + // Clear the breakpoint + gRemoteBreak[address] = 0; + } + + // Check if any active breakpoints + if (gBreakActive) + { + for (c = 0; c < 65536; c++) + { + if (gRemoteBreak[c] != 0) + break; + } + + // If no active breakpoints, decrement gDebugActive + if (c == 65536) + { + lock_remote(); + gDebugActive--; + gBreakActive = 0; + unlock_remote(); + } + } + + return "Ok"; +} + +/* +======================================================= +List Break command: Lists all breakpoints. +======================================================= +*/ +std::string cmd_list_break(ServerSocket& sock, std::string& args) +{ + int c; + char str[80]; + + for (c = 0; c < 65536; c++) + { + if (gRemoteBreak[c] != 0) + { + if (gRadix == 10) + sprintf(str, "%5d: ", c); + else + sprintf(str, "%04X: ", c); + + if (gRemoteBreak[c] & BPTYPE_MAIN) + strcat(str, "main "); + if (gRemoteBreak[c] & BPTYPE_OPT) + strcat(str, "opt "); + if (gRemoteBreak[c] & BPTYPE_MPLAN) + strcat(str, "mplan "); + if (gRemoteBreak[c] & BPTYPE_RAM) + strcat(str, "ram "); + if (gRemoteBreak[c] & BPTYPE_RAM2) + strcat(str, "ram2 "); + if (gRemoteBreak[c] & BPTYPE_RAM3) + strcat(str, "ram3 "); + strcat(str, "\n"); + sock << str; + } + } + return "Ok"; +} + +void key_delay(void) +{ + fl_wait(0.01); + while (gDelayUpdateKeys) + fl_wait(0.001); +} +/* +======================================================= +key_press: Causes a keydown & keyup event for the + specified key. +======================================================= +*/ +void key_press(int key) +{ + static char specialShift[] = "~!@#$%^&*()_+{}|:\"<>?"; + static char specialUnshft[] = "`1234567890-=[]\\;',./"; + int index; + char* ptr; + + // Test if it is an alpha key and is cap + if (isalpha(key)) + { + if (key != tolower(key)) + { + simulate_keydown(FL_Shift_L); + key_delay(); + simulate_keydown(tolower(key)); + key_delay(); + simulate_keyup(tolower(key)); + key_delay(); + simulate_keyup(FL_Shift_L); + key_delay(); + return; + } + } + else if ((ptr = strchr(specialShift, key)) != NULL) + { + index = ptr-specialShift; + simulate_keydown(FL_Shift_L); + key_delay(); + simulate_keydown(specialUnshft[index]); + key_delay(); + simulate_keyup(specialUnshft[index]); + key_delay(); + simulate_keyup(FL_Shift_L); + key_delay(); + return; + } + + + simulate_keydown(key); + key_delay(); + simulate_keyup(key); + key_delay(); +} + +/* +======================================================= +key_press: Causes a keydown & keyup event for the + specified key. +======================================================= +*/ +int keyword_lookup(std::string& keyword) +{ + // Make the keyword lowercase + std::transform(keyword.begin(), keyword.end(), keyword.begin(), (int(*)(int)) std::tolower); + + if (keyword == "enter") + return FL_Enter; + else if (keyword == "esc") + return FL_Escape; + else if (keyword == "tab") + return FL_Tab; + else if (keyword == "ctrl") + return FL_Control_L; + else if ((keyword == "graph") || (keyword == "grph")) + return FL_Alt_L; + else if (keyword == "code") + return FL_Alt_R; + else if ((keyword == "delete") || (keyword == "del")) + return FL_Delete; + else if ((keyword == "insert") || (keyword == "ins")) + return FL_Insert; + else if (keyword == "shift") + return FL_Shift_L; + else if (keyword == "f1") + return FL_F + 1; + else if (keyword == "f2") + return FL_F + 2; + else if (keyword == "f3") + return FL_F + 3; + else if (keyword == "f4") + return FL_F + 4; + else if (keyword == "f5") + return FL_F + 5; + else if (keyword == "f6") + return FL_F + 6; + else if (keyword == "f7") + return FL_F + 7; + else if (keyword == "f8") + return FL_F + 8; + else if (keyword == "space") + return ' '; + else if (keyword == "left") + return FL_Left; + else if (keyword == "right") + return FL_Right; + else if (keyword == "up") + return FL_Up; + else if (keyword == "down") + return FL_Down; + else if (keyword == "label") + return FL_F + 9; + else if (keyword == "print") + return FL_F + 10; + else if (keyword == "paste") + return FL_F + 11; + else if (keyword == "pause") + return FL_F + 12; + else if (keyword == "bksp") + return FL_BackSpace; + else if (keyword == "backspace") + return FL_BackSpace; + else if (keyword == "back") + return FL_BackSpace; + else if (keyword == "home") + return FL_Home; + else if (keyword == "end") + return FL_End; + else if ((keyword == "pgup") || (keyword == "pageup")) + return FL_Page_Up; + else if ((keyword == "pgdn") || (keyword == "pagedown")) + return FL_Page_Down; + + return 0; +} + +/* +======================================================= +send_key_list: Sends a list of keywords as a single + sequence. +======================================================= +*/ +void send_key_list(int* key_list, int count) +{ + int c; + + for (c = 0; c < count; c++) + { + simulate_keydown(key_list[c]); + key_delay(); + } + for (c = count-1; c >= 0; c--) + { + simulate_keyup(key_list[c]); + key_delay(); + } +} + +/* +======================================================= +Key command: Simulates a keystroke sequence from the + keyboard. +======================================================= +*/ +std::string cmd_key(ServerSocket& sock, std::string& args) +{ + int quote; + int escape; + int len, c; + int key; + int key_list[50], key_count; + std::string keyword; + + quote = 0; + escape = 0; + key_count = 0; + len = args.length(); + + // Check if it is a simple 1-character key + if (len == 1) + { + key_press(args[0]); + return "Ok"; + } + + // Loop through all charaters + for (c = 0; c < len; c++) + { + // First check if we are in a quote + if (quote) + { + // In a quote string, copy bytes directly except '"' and '\' + if (args[c] == '"') + { + if (escape) + { + key_press('"'); + escape = 0; + } + else + { + quote = 0; + gLcdTimeoutCycles = LCD_TIMEOUT_NORMAL; + } + } + else if (args[c] == '\\') + { + // Test if last char was escape + if (escape) + { + key_press('\\'); + escape = 0; + } + else + escape = 1; + } + else + { + // Perform a keypress operation for the character + key_press(args[c]); + } + } + // Search for quote + else if (args[c] == '"') + { + quote = 1; + gLcdTimeoutCycles = 3000000; + } + else if (args[c] == '+') + { + // Check if there is an acive keyword + if (keyword != "") + { + // Append the key to the key_sequence array + if (keyword.length() == 1) + key = keyword[0]; + else + key = keyword_lookup(keyword); + keyword = ""; + key_list[key_count++] = key; + } + } + else if (args[c] == ' ') + { + if (keyword != "") + { + if (keyword.length() == 1) + key = keyword[0]; + else + key = keyword_lookup(keyword); + keyword = ""; + key_list[key_count++] = key; + } + if (key_count != 0) + { + send_key_list(key_list, key_count); + key_count = 0; + } + } + else + { + // Build keyword + keyword += args[c]; + } + } + + if (keyword != "") + { + if (keyword.length() == 1) + key = keyword[0]; + else + key = keyword_lookup(keyword); + key_list[key_count++] = key; + } + if (key_count != 0) + { + send_key_list(key_list, key_count); + } + + return "Ok"; +} + +/* +======================================================= +local_switch_model: Switches to a new model and checks + if LCD monitoring is turned on. LCD monitoring + must be turned off to switch models because each + uses a different trap address. +======================================================= +*/ +static void local_switch_model(int model) +{ + if (gMonitorLcd) + { + lock_remote(); + gMonitorLcd = 0; + gDebugActive--; + unlock_remote(); + } + + remote_switch_model(model); +} +/* +======================================================= +Model command: Sets the emulation model +======================================================= +*/ +std::string cmd_model(ServerSocket& sock, std::string& args) +{ + char str[30]; + char model[10]; + std::string more_args = args; + + if (args == "") + { + get_model_string(model, gModel); + sprintf(str, "%s\nOk", model); + return str; + } + + // Convert args to lowercase + std::transform(more_args.begin(), more_args.end(), more_args.begin(), (int(*)(int)) std::tolower); + + // Check wich model it is + if ((more_args == "m100") || (more_args == "t102")) + { + if (gModel != MODEL_M100) + local_switch_model(MODEL_M100); + } + else if ((more_args == "m102") || (more_args == "t102")) + { + if (gModel != MODEL_M102) + local_switch_model(MODEL_M102); + } + else if ((more_args == "m200") || (more_args == "t200")) + { + if (gModel != MODEL_T200) + local_switch_model(MODEL_T200); + } + else if (more_args == "m10") + { + if (gModel != MODEL_M10) + local_switch_model(MODEL_M10); + } + else if (more_args == "pc8201") + { + if (gModel != MODEL_PC8201) + local_switch_model(MODEL_PC8201); + } + else + return "Parameter Error\nOk"; + + fl_wait(0.25); + return "Ok"; +} + +/* +======================================================= +Speed command: Sets the emulation speed +======================================================= +*/ +std::string cmd_speed(ServerSocket& sock, std::string& args) +{ + std::string more_args = args; + + if (args == "") + { + switch (fullspeed) + { + case SPEED_REAL: return "2.4\nOk"; + case SPEED_FRIENDLY1: + case SPEED_FRIENDLY2: return "friendly\nOk"; + case SPEED_FULL: return "max\nOk"; + } + } + + // Convert args to lowercase + std::transform(more_args.begin(), more_args.end(), more_args.begin(), (int(*)(int)) std::tolower); + + // Check wich model it is + if (more_args == "2.4") + { + remote_set_speed(SPEED_REAL); + } + else if (more_args == "friendly") + { + remote_set_speed(SPEED_FRIENDLY1); + } + else if (more_args == "max") + { + remote_set_speed(SPEED_FULL); + } + else + return "Parameter Error\nOk"; + + return "Ok"; +} + +/* +======================================================= +get_lcd_coords: Extracts row and column values from + a string with the format (c,r) +======================================================= +*/ +int get_lcd_coords(std::string& str, int& row, int& col) +{ + int pos, c; + + // Ensure there is a '(' + if (str[0] != '(') + return 1; + + // Find the ',' + pos = str.find(","); + if (pos == -1) + return 1; + + // Find the position of the col value + for (c = pos+1; c < (int) str.length(); c++) + { + if (str[c] != ' ') + break; + } + + // Check for valid format + if (c == str.length()) + return 1; + if (str[c] == ')') + return 1; + + // Get the values + row = atoi(&str.c_str()[1]); + col = atoi(&str.c_str()[c]); + + return 0; +} + +/* +======================================================= +Lcd_ignore command: Configures regions of the LCD to + ignore during monitoring. +======================================================= +*/ +std::string cmd_lcd_ignore(ServerSocket& sock, std::string& args) +{ + std::string next_arg; + std::string more_args; + int pos; + int top_row, top_col, bottom_row, bottom_col; + char str[30]; + + // If no args, then list the ignores + if (args == "") + { + if (gIgnoreCount == 0) + return "none\nOk"; + + for (pos = 0; pos < gIgnoreCount; pos++) + { + sprintf(str, "(%d,%d)-(%d,%d)\n", gIgnoreRects[pos].top_row, + gIgnoreRects[pos].top_col, gIgnoreRects[pos].bottom_row, + gIgnoreRects[pos].bottom_col); + sock << str; + } + return "Ok"; + } + + // Ckeck if clearing all ignores + if (args == "none") + { + // Clear the ignore count so all regions are monitored + gIgnoreCount = 0; + return "Ok"; + } + + // Separate coordinates + pos = args.find('-'); + if (pos != -1) + { + next_arg = args.substr(0, pos); + more_args = args.substr(pos+1, args.length()-pos-1); + } + else + return "Parameter Error\nOk"; + + // Get row from first argument + if (get_lcd_coords(next_arg, top_row, top_col)) + return "Parameter Error\nOk"; + if (get_lcd_coords(more_args, bottom_row, bottom_col)) + return "Parameter Error\nOk"; + + // Update the ignore region + gIgnoreRects[gIgnoreCount].top_row = top_row; + gIgnoreRects[gIgnoreCount].top_col = top_col; + gIgnoreRects[gIgnoreCount].bottom_row = bottom_row; + gIgnoreRects[gIgnoreCount].bottom_col = bottom_col; + gIgnoreCount++; + + return "Ok"; +} + +/* +======================================================= +Show reg command: Outputs the specified value +======================================================= +*/ +std::string cmd_show_reg(ServerSocket& sock, int value, int size) +{ + char str[10]; + + if (gRadix == 10) + sprintf(str, "%d\nOk", value); + else + { + if (size == 2) + sprintf(str, "%04X\nOk", value); + else + sprintf(str, "%02X\nOk", value); + } + + return str; +} +/* +======================================================= +Lcd_mon command: Enables or disables LCD monitoring. +======================================================= +*/ +std::string cmd_lcd_mon(ServerSocket& sock, std::string& args) +{ + int c; + + // Get breakpoint arguments + if (args == "") + { + if (gMonitorLcd) + return "on\nOk"; + else + return "off\nOk"; + } + + std::transform(args.begin(), args.end(), args.begin(), (int(*)(int)) std::tolower); + if (args == "on") + { + if (!gMonitorLcd) + { + // Configure LCD monitoring + gLcdRow = -1; + gLcdCol = -1; + gLcdColStart = -1; + gLcdUpdateCycle = (UINT64) -1; + gLcdTimeoutCycles = LCD_TIMEOUT_NORMAL; + + // Find the LCD Trap address + for (c = 0; ;c++) + { + // Test for end of table + if (gStdRomDesc->pFuns[c].strnum == -1) + return "Error - no trap vector \nOk"; + + // Search for the Level 6 plotting function + if (gStdRomDesc->pFuns[c].strnum == R_CHAR_PLOT_6) + { + gLcdTrapAddr = gStdRomDesc->pFuns[c].addr; + break; + } + } + + // Now find the address of the LCD Row storage + for (c = 0; ;c++) + { + // Test for end of table + if (gStdRomDesc->pVars[c].strnum == -1) + return "Error - no row vector\nOk"; + + // Search for the Level 6 plotting function + if (gStdRomDesc->pVars[c].strnum == R_CURSOR_ROW) + { + gLcdRowAddr = gStdRomDesc->pVars[c].addr; + break; + } + } + + // Enable LCD monitoring + gMonitorLcd = 1; + lock_remote(); + + // Increment debug counter + gDebugActive++; + unlock_remote(); + } + } + else if (args == "off") + { + if (gMonitorLcd) + { + // Turn off LCD monitoring + gMonitorLcd = 0; + lock_remote(); + + // Decrement debug counter + gDebugActive--; + unlock_remote(); + } + } + else + return "Parameter Error\nOk"; + + return "Ok"; +} + +/* +======================================================= +string command: Outputs data at address as a string. +======================================================= +*/ +std::string cmd_string(ServerSocket& sock, std::string& args) +{ + int address; + int ch; + char build[10]; + std::string str; + + address = get_address(args); + while ((ch = get_memory8(address)) != 0) + { + if ((ch < ' ') || (ch > '~')) + { + if (gRadix == 10) + sprintf(build, "<%d>", ch); + else + sprintf(build,"<%02X>", ch); + str += build; + } + else + str += ch; + address++; + } + + str += "\nOk"; + return str; +} + +/* +======================================================= +Disassemble command: Dissassembles code at the + address specified. +======================================================= +*/ +std::string cmd_disassemble(ServerSocket& sock, std::string& args) +{ + std::string next_arg; + std::string more_args; + int address; + int lineCount; + int dis_addr; + int c; + VTDis dis; + char line[300]; + + // Get breakpoint arguments + more_args = args; + next_arg = get_next_arg(more_args); + + if (next_arg == "") + address = gLastDisAddress; + else + address = get_address(next_arg); + + // Get line count + if (more_args == "") + lineCount = 10; + else + lineCount = str_to_i(more_args.c_str()); + + // Create a disassembler + dis.m_pRom = gStdRomDesc; + dis.m_WantComments = 1; + + // Disassemble lineCount lines + dis_addr = address; + for (c = 0; c < lineCount; c++) + { + dis_addr += dis.DisassembleLine(dis_addr, line); + strcat(line, "\n"); + sock << line; + } + gLastDisAddress = dis_addr; + + return "Ok"; +} + +/* +======================================================= +Trace command: Enables instruction tracing for all or + specific address ranges. +======================================================= +*/ +std::string cmd_trace(ServerSocket& sock, std::string& args) +{ + std::string next_arg, more_args; + std::string trace_file; + int on_off_flag; + int create_new_flag; + char line[300]; + + + // Get next argument for trace command + more_args = args; + next_arg = get_next_arg(more_args); + + // Set default flags + on_off_flag = -1; // Default to "not specified" + create_new_flag = 0; // Default to append mode + + // Loop through all arguments + while (next_arg != "") + { + if (next_arg == "off") + on_off_flag = 0; + else if (next_arg == "on") + on_off_flag = 1; + else if ((next_arg.substr(0, 2) == "0x") || isdigit(next_arg[0])) + { + // Handle address argument + } + else if (next_arg == "-c") + { + // Handle "create new file" flag + create_new_flag = 1; + } + else + { + // Must be a filename. Only 1 filename allowed + if (trace_file != "") + { + sprintf(line, "Error filename \"%s\" already specified\nOk", trace_file.c_str()); + return line; + } + // Save filename + trace_file = next_arg; + } + + // Get next argument + next_arg = get_next_arg(more_args); + } + + // Check if a trace file was specified + if (trace_file != "") + { + // If there is an open trace file, then start tracing to a new file + if (gTraceOpen) + fclose(gTraceFileFd); + + gTraceOpen = 0; + gTraceFile = trace_file; + + // If tracing active, then open the new file + if ((on_off_flag == 1) || (gTraceActive)) + { + if (create_new_flag) + gTraceFileFd = fopen(gTraceFile.c_str(), "w"); + else + gTraceFileFd = fopen(gTraceFile.c_str(), "a"); + + // Set flag indicating if trace open + if (gTraceFileFd != NULL) + gTraceOpen = 1; + else + { + sock << "Error opening file\n"; + } + } + } + + if (on_off_flag) + { + // Ensure tracing is turned on, the file is open, and we are in Active Debug mode + if (!gTraceActive) + { + // Update the active debug + lock_remote(); + gDebugActive++; + gTraceActive = 1; + unlock_remote(); + + // Open trece file + if (!gTraceOpen) + { + gTraceFileFd = fopen(gTraceFile.c_str(), "wa"); + gTraceOpen = (gTraceFileFd != NULL); + } + } + gTraceDis.m_pRom = gStdRomDesc; + gTraceDis.m_WantComments = 0; + } + else + { + // Close any open trace file and end the trace mode + if (gTraceActive) + { + // Update the active debug + lock_remote(); + gDebugActive--; + gTraceActive = 0; + unlock_remote(); + + // Close open trece file + if (gTraceOpen) + { + gTraceOpen = 0; + fclose(gTraceFileFd); + } + } + } + + return "Ok"; +} +/* +======================================================= +Routine to process remote commands +======================================================= +*/ +std::string process_command(ServerSocket& sock, std::string cmd) +{ + std::string ret = "Syntax error"; + std::string cmd_word; + std::string args; + + // Separate out the command word from any arguments + args = cmd; + cmd_word = get_next_arg(args); + + if (cmd == "help") // Check for help + ret = cmd_help(sock); + + else if (cmd == "run") // Check for run + ret = cmd_run(sock); + + else if (cmd == "reset") // Check for reset + ret = cmd_reset(sock); + + else if (cmd == "terminate") // Check for terminate + ret = cmd_terminate(sock); + + else if (cmd == "cold_boot") // Check for terminate + ret = cmd_cold_boot(sock); + + else if (cmd == "halt") // Check for halt + ret = cmd_halt(sock); + + else if (cmd == "status") // Report status and any events + ret = cmd_status(sock); + + else if (cmd_word == "load") + ret = cmd_load(sock, args); + + else if ((cmd_word == "read_mem") || (cmd_word == "rm")) + ret = cmd_read_mem(sock, args); + + else if ((cmd_word == "write_mem") || (cmd_word == "wm")) + ret = cmd_write_mem(sock, args); + + else if ((cmd_word == "read_reg") || (cmd_word == "rr")) + ret = cmd_read_reg(sock, args); + + else if ((cmd_word == "write_reg") || (cmd_word == "wr")) + ret = cmd_write_reg(sock, args); + + else if (cmd_word == "radix") + ret = cmd_radix(sock, args); + + else if (cmd_word == "in") + ret = cmd_in(sock, args); + + else if (cmd_word == "out") + ret = cmd_out(sock, args); + + else if (cmd_word == "flags") + ret = cmd_flags(sock, args); + + else if (cmd_word == "step") + ret = cmd_step(sock, args); + + else if ((cmd_word == "lcd_mon") || (cmd_word == "lm")) + ret = cmd_lcd_mon(sock, args); + + else if ((cmd_word == "lcd_ignore") || (cmd_word == "li")) + ret = cmd_lcd_ignore(sock, args); + + else if ((cmd_word == "set_break") || (cmd_word == "sb")) + ret = cmd_set_break(sock, args); + + else if ((cmd_word == "clear_break") || (cmd_word == "cb")) + ret = cmd_clear_break(sock, args); + + else if ((cmd_word == "list_break") || (cmd_word == "lb")) + ret = cmd_list_break(sock, args); + + else if (cmd_word == "key") + ret = cmd_key(sock, args); + + else if (cmd_word == "model") + ret = cmd_model(sock, args); + + else if (cmd_word == "speed") + ret = cmd_speed(sock, args); + + else if (cmd_word == "dis") + ret = cmd_disassemble(sock, args); + + else if (cmd_word == "pc") + ret = cmd_show_reg(sock, PC, 2); + + else if (cmd_word == "hl") + ret = cmd_show_reg(sock, HL, 2); + + else if (cmd_word == "sp") + ret = cmd_show_reg(sock, SP, 2); + + else if (cmd_word == "de") + ret = cmd_show_reg(sock, DE, 2); + + else if (cmd_word == "bc") + ret = cmd_show_reg(sock, BC, 2); + + else if (cmd_word == "im") + ret = cmd_show_reg(sock, IM, 1); + + else if (cmd_word == "a") + ret = cmd_show_reg(sock, A, 1); + + else if (cmd_word == "b") + ret = cmd_show_reg(sock, B, 1); + + else if (cmd_word == "c") + ret = cmd_show_reg(sock, C, 1); + + else if (cmd_word == "d") + ret = cmd_show_reg(sock, D, 1); + + else if (cmd_word == "e") + ret = cmd_show_reg(sock, E, 1); + + else if (cmd_word == "h") + ret = cmd_show_reg(sock, H, 1); + + else if (cmd_word == "l") + ret = cmd_show_reg(sock, L, 1); + + else if (cmd_word == "m") + ret = cmd_show_reg(sock, M, 1); + + else if (cmd_word == "string") + ret = cmd_string(sock, args); + + else if (cmd_word == "trace") + ret = cmd_trace(sock, args); + + return ret; +} + + +/* +======================================================= +Routine that will become the remote control thread. +======================================================= +*/ +void* remote_control(void* arg) +{ + gSocketOpened = FALSE; + try + { + ServerSocket server(gSocketPort); + while (!gExitApp) + { + server.accept(gOpenSock); + try + { + gSocketOpened = TRUE; + while (!gExitApp) + { + std::string data; + gOpenSock >> data; + gOpenSock << process_command(gOpenSock, data); + } + } + catch (SocketException&) + { + gSocketOpened = FALSE; + } + } + } + catch (SocketException& e) + { + printf("Exception was caught: %s\nExiting thread\n",e.description().c_str()); + } + + gSocketOpened = FALSE; + + // Unhook from the debug callback processor + debug_clear_monitor_callback(cb_remote_debug); + + return NULL; +} + +/* +======================================================= +Configure remote control using sockets inerface. +======================================================= +*/ +void init_remote(void) +{ + int c; + + // Check if Remote Socket interface enabled + if (gSocketPort == 0) + return; + + // Initialize breakpoints + for (c = 0; c < 32768; c++) + { + // Zero all breakpoints + gRemoteBreak[c] = 0; + } + + // Hook our routine to the debug monitor + debug_set_monitor_callback(cb_remote_debug); + + // Create the thread +#ifdef WIN32 + DWORD id; + gRemoteLock = CreateMutex(NULL, FALSE, NULL); + gRemoteThread = CreateThread( NULL, 0, + (LPTHREAD_START_ROUTINE) remote_control, + NULL, 0, &id); + + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD( 1, 1 ); + + err = WSAStartup( wVersionRequested, &wsaData ); + if ( err != 0 ) + { + /* Tell the user that we couldn't find a useable */ + /* winsock.dll. */ + return; + } + + /* Confirm that the Windows Sockets DLL supports 1.1.*/ + /* Note that if the DLL supports versions greater */ + /* than 1.1 in addition to 1.1, it will still return */ + /* 1.1 in wVersion since that is the version we */ + /* requested. */ + + if ( LOBYTE( wsaData.wVersion ) != 1 || + HIBYTE( wsaData.wVersion ) != 1 ) + { + /* Tell the user that we couldn't find a useable */ + /* winsock.dll. */ + WSACleanup( ); + return; + } + +#else + // Initialize thread processing + pthread_mutex_init(&gRemoteLock, NULL); + + pthread_create(&gRemoteThread, NULL, remote_control, NULL); +#endif +} + +void lock_remote(void) +{ + if (gSocketPort != 0) +#ifdef WIN32 + WaitForSingleObject(gRemoteLock, INFINITE); +#else + pthread_mutex_lock(&gRemoteLock); +#endif +} + +void unlock_remote(void) +{ + if (gSocketPort != 0) +#ifdef WIN32 + ReleaseMutex(gRemoteLock); +#else + pthread_mutex_unlock(&gRemoteLock); +#endif +} + diff --git a/src/remote.h b/src/remote.h new file mode 100644 index 0000000..f2848c7 --- /dev/null +++ b/src/remote.h @@ -0,0 +1,61 @@ +/* remote.h */ + +/* $Id$ */ + +/* + * Copyright 2008 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef _REMOTE_H_ +#define _REMOTE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void init_remote(void); +void lock_remote(void); +void unlock_remote(void); + +#ifdef __cplusplus +} +#endif + +#define BPTYPE_MAIN 0x01 +#define BPTYPE_OPT 0x02 +#define BPTYPE_MPLAN 0x04 +#define BPTYPE_RAM 0x08 +#define BPTYPE_RAM2 0x10 +#define BPTYPE_RAM3 0x20 + +typedef struct +{ + int top_row; + int top_col; + int bottom_row; + int bottom_col; +} lcd_rect_t; + +#endif diff --git a/src/roms.h b/src/roms.h index e5640b3..95d56b1 100644 --- a/src/roms.h +++ b/src/roms.h @@ -75,9 +75,12 @@ typedef struct RomDescription { unsigned short sDirectory; /* Start of RAM directory */ unsigned short sBasicStrings; /* BASIC string buffer pointer */ unsigned short sBasicSize; /* Size of all BASIC programs */ + unsigned short sKeyscan; /* Location of Keyscan array */ + unsigned short sCharTable; /* Location of Charater generator table */ unsigned short sDirCount; /* Number of entries in Directory */ unsigned short sFirstDirEntry; /* Index of first available enry */ + unsigned short sMSCopyright; /* Address of MS Copyright string on MENU */ } RomDescription_t; enum { @@ -86,6 +89,7 @@ enum { TABLE_TYPE_CODE, TABLE_TYPE_MODIFIED_STRING, TABLE_TYPE_MODIFIED_STRING2, + TABLE_TYPE_MODIFIED_STRING3, TABLE_TYPE_2BYTE, TABLE_TYPE_3BYTE, TABLE_TYPE_CTRL_DELIM, diff --git a/src/serial.h b/src/serial.h index 4c8806b..a45bbeb 100644 --- a/src/serial.h +++ b/src/serial.h @@ -92,6 +92,7 @@ int ser_set_monitor_callback(ser_monitor_cb pCallback); int ser_set_port(char* port); int ser_get_port_settings(char* port, int* open_state, int* baud, int* size, int* stop_bits, char* parity); +int ser_poll(); int ser_open_port(void); int ser_close_port(void); @@ -111,42 +112,46 @@ int ser_write_byte(char data); typedef struct ser_params { char port_name[256]; // Host port name for emulation - char parity; // Current parity setting - int baud_rate; // Current baud rate - int bit_size; // Bit size for theport - int stop_bits; // Number of stop bits - int open_flag; // Set to 1 when the port is open - char rx_buf[128]; // Read buffer - int rxIn; // Read buffer input location - int rxOut; // Read buffer output location - char tx_buf[32]; // Read buffer - int txIn; // Read buffer input location - int txOut; // Read buffer output location - int tx_empty; // Flag to indicate when TX is done + char parity; // Current parity setting + int baud_rate; // Current baud rate + int bit_size; // Bit size for theport + int stop_bits; // Number of stop bits + int open_flag; // Set to 1 when the port is open ser_callback pCallback; // Callback function for RX data ser_monitor_cb pMonCallback; - FILE* pCmdFile; // Command file for Simulated I/O + FILE* pCmdFile; // Command file for Simulated I/O // Host COM port control structures #ifdef WIN32 - HANDLE hComm; // Handle to the serial port - OVERLAPPED osRead; // Overlapped I/O structure for reading - OVERLAPPED osWrite; // Overlapped I/O structure for writing - DCB dcb; // Device control block + HANDLE hComm; // Handle to the serial port + OVERLAPPED osRead; // Overlapped I/O structure for reading + OVERLAPPED osWrite; // Overlapped I/O structure for writing + DCB dcb; // Device control block HANDLE hReadThread; // Read COM thread HANDLE hWriteThread; // Write COM thread HANDLE hThreadExitEvent; // Event to trigger thread exiting HANDLE hWriteEvent; // Event to trigger a write operation HANDLE hWriteMutex; HANDLE hReadMutex; - int fReadThread; // Flag indicating if Read Thread active - int fWriteThread; // Flag indicating if Write Tread active - int fIntPending; - int dtrState; // Current state of DTR - int rtsState; // Current state of RTS + int fReadThread; // Flag indicating if Read Thread active + int fWriteThread; // Flag indicating if Write Tread active + int fIntPending; + int dtrState; // Current state of DTR + int rtsState; // Current state of RTS + char rx_buf[128]; // Read buffer + int rxIn; // Read buffer input location + int rxOut; // Read buffer output location + char tx_buf[32]; // Read buffer + int txIn; // Read buffer input location + int txOut; // Read buffer output location + int tx_empty; // Flag to indicate when TX is done + +#else + int fd; // fd of open serial port + #endif } ser_params_t; diff --git a/src/serversocket.cpp b/src/serversocket.cpp new file mode 100644 index 0000000..ff9601e --- /dev/null +++ b/src/serversocket.cpp @@ -0,0 +1,59 @@ +// Implementation of the ServerSocket class + +#include "serversocket.h" +#include "socketexception.h" + + +ServerSocket::ServerSocket ( int port ) +{ + if ( ! Socket::create() ) + { + throw SocketException ( "Could not create server socket." ); + } + + if ( ! Socket::bind ( port ) ) + { + throw SocketException ( "Could not bind to port." ); + } + + if ( ! Socket::listen() ) + { + throw SocketException ( "Could not listen to socket." ); + } + +} + +ServerSocket::~ServerSocket() +{ +} + + +const ServerSocket& ServerSocket::operator << ( const std::string& s ) const +{ + if ( ! Socket::send ( s ) ) + { + throw SocketException ( "Could not write to socket." ); + } + + return *this; + +} + + +const ServerSocket& ServerSocket::operator >> ( std::string& s ) const +{ + if ( ! Socket::recv ( s ) ) + { + throw SocketException ( "Could not read from socket." ); + } + + return *this; +} + +void ServerSocket::accept ( ServerSocket& sock ) +{ + if ( ! Socket::accept ( sock ) ) + { + throw SocketException ( "Could not accept socket." ); + } +} diff --git a/src/serversocket.h b/src/serversocket.h new file mode 100644 index 0000000..4e393a6 --- /dev/null +++ b/src/serversocket.h @@ -0,0 +1,25 @@ +// Definition of the ServerSocket class + +#ifndef ServerSocket_class +#define ServerSocket_class + +#include "socket.h" + + +class ServerSocket : private Socket +{ + public: + + ServerSocket ( int port ); + ServerSocket (){}; + virtual ~ServerSocket(); + + const ServerSocket& operator << ( const std::string& ) const; + const ServerSocket& operator >> ( std::string& ) const; + + void accept ( ServerSocket& ); + +}; + + +#endif diff --git a/src/setup.cpp b/src/setup.cpp index 629c9ba..4b58520 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -52,9 +52,11 @@ #include "setup.h" #include "memory.h" #include "memedit.h" +#include "io.h" #include "file.h" extern Fl_Preferences virtualt_prefs; +void init_menus(void); typedef struct setup_ctrl_struct { @@ -110,10 +112,12 @@ typedef struct memory_ctrl_struct Fl_Button* pRampacBrowse; Fl_Box* pReMemText; Fl_Check_Button* pOptRomRW; + Fl_Check_Button* pShowVersion; } memory_ctrl_t; extern "C" { extern int gOptRomRW; +extern int gShowVersion; } @@ -207,6 +211,7 @@ void cb_setup_cancel (Fl_Widget* w, void*) { gpsw->hide(); delete gpsw; + gpsw = NULL; } void cb_setup_OK(Fl_Widget* w, void*) @@ -307,12 +312,14 @@ void cb_setupwin (Fl_Widget* w, void*) { gpsw->hide(); delete gpsw; + gpsw = NULL; } void cb_memorywin (Fl_Widget* w, void*) { gmsw->hide(); delete gmsw; + gpsw = NULL; } /* @@ -537,6 +544,10 @@ void save_memory_preferences(void) strcpy(pref, str); strcat(pref, "_OptRomRW"); virtualt_prefs.set(pref, gOptRomRW); + + strcpy(pref, str); + strcat(pref, "_ShowVersion"); + virtualt_prefs.set(pref, gShowVersion); } void load_memory_preferences(void) @@ -574,6 +585,11 @@ void load_memory_preferences(void) strcpy(pref, str); strcat(pref, "_OptRomRW"); virtualt_prefs.get(pref, gOptRomRW, 0); + + // Load Show Version on MENU option + strcpy(pref, str); + strcat(pref, "_ShowVersion"); + virtualt_prefs.get(pref, gShowVersion, 1); } /* @@ -633,8 +649,12 @@ void cb_memory_OK(Fl_Widget* w, void*) // Get OptRom R/W Enable setting gOptRomRW = mem_ctrl.pOptRomRW->value(); + // Get Show Version setting + gShowVersion = mem_ctrl.pShowVersion->value(); + // Allocate ReMem and / or Rampac memory if not already init_mem(); + init_menus(); // If we are in ReMem or ReMem_Rampac mode, check if ReMem filename changed if ((mem_setup.mem_mode == SETUP_MEM_REMEM) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC)) @@ -690,10 +710,15 @@ void cb_memory_OK(Fl_Widget* w, void*) // Update Memory Editor cb_MemoryEditorUpdate(); + // Reload the SysROM in case the Show Verion changed + load_sys_rom(); + /* Reset the CPU */ resetcpu(); gExitLoop = 1; + show_remem_mode(); + // Destroy the window gmsw->hide(); delete gmsw; @@ -863,7 +888,7 @@ Routine to create the PeripheralSetup Window and tabs void cb_MemorySetup (Fl_Widget* w, void*) { // Create Peripheral Setup window - gmsw = new Fl_Window(420, 280, "Memory Emulation Options"); + gmsw = new Fl_Window(420, 310, "Memory Emulation Options"); gmsw->callback(cb_memorywin); // Create items on the Tab @@ -928,11 +953,15 @@ void cb_MemorySetup (Fl_Widget* w, void*) mem_ctrl.pOptRomRW = new Fl_Check_Button(20, 200, 210, 20, "Make Option ROM R/W"); mem_ctrl.pOptRomRW->value(gOptRomRW); + // Show Version Checkbox + mem_ctrl.pShowVersion = new Fl_Check_Button(20, 230, 210, 20, "Patch ROM on load to show VirtualT version"); + mem_ctrl.pShowVersion->value(gShowVersion); + // OK button - { Fl_Button* o = new Fl_Button(160, 240, 60, 30, "Cancel"); + { Fl_Button* o = new Fl_Button(160, 270, 60, 30, "Cancel"); o->callback((Fl_Callback*)cb_memory_cancel); } - { Fl_Return_Button* o = new Fl_Return_Button(230, 240, 60, 30, "OK"); + { Fl_Return_Button* o = new Fl_Return_Button(230, 270, 60, 30, "OK"); o->callback((Fl_Callback*)cb_memory_OK); } diff --git a/src/socket.cpp b/src/socket.cpp new file mode 100644 index 0000000..4e54724 --- /dev/null +++ b/src/socket.cpp @@ -0,0 +1,202 @@ +// Implementation of the Socket class. + + +#include "socket.h" +#include "string.h" +#include +#include +#include + + + +Socket::Socket() : + m_sock ( -1 ) +{ + + memset ( &m_addr, + 0, + sizeof ( m_addr ) ); + +} + +Socket::~Socket() +{ + if ( is_valid() ) +#ifdef WIN32 + ::closesocket ( m_sock ); +#else + ::close ( m_sock ); +#endif +} + +bool Socket::create() +{ + m_sock = socket ( AF_INET, + SOCK_STREAM, + 0 ); + + if ( ! is_valid() ) + return false; + + + // TIME_WAIT - argh + int on = 1; + if ( setsockopt ( m_sock, SOL_SOCKET, SO_REUSEADDR, ( const char* ) &on, sizeof ( on ) ) == -1 ) + return false; + + + return true; + +} + + + +bool Socket::bind ( const int port ) +{ + + if ( ! is_valid() ) + { + return false; + } + + + + m_addr.sin_family = AF_INET; + m_addr.sin_addr.s_addr = INADDR_ANY; + m_addr.sin_port = htons ( port ); + + int bind_return = ::bind ( m_sock, + ( struct sockaddr * ) &m_addr, + sizeof ( m_addr ) ); + + + if ( bind_return == -1 ) + { + return false; + } + + return true; +} + + +bool Socket::listen() const +{ + if ( ! is_valid() ) + { + return false; + } + + int listen_return = ::listen ( m_sock, MAXCONNECTIONS ); + + + if ( listen_return == -1 ) + { + return false; + } + + return true; +} + + +bool Socket::accept ( Socket& new_socket ) const +{ + int addr_length = sizeof ( m_addr ); + new_socket.m_sock = ::accept ( m_sock, ( sockaddr * ) &m_addr, ( socklen_t * ) &addr_length ); + + if ( new_socket.m_sock <= 0 ) + return false; + else + return true; +} + + +bool Socket::send ( const std::string s ) const +{ + int flags; +#ifdef WIN32 + flags = 0; +#else + flags = MSG_NOSIGNAL; +#endif + int status = ::send ( m_sock, s.c_str(), s.size(), flags ); + if ( status == -1 ) + { + return false; + } + else + { + return true; + } +} + + +int Socket::recv ( std::string& s ) const +{ + char buf [ MAXRECV + 1 ]; + + s = ""; + + memset ( buf, 0, MAXRECV + 1 ); + + int status = ::recv ( m_sock, buf, MAXRECV, 0 ); + + if ( status == -1 ) + { + printf("status == -1 errno == %d in Socket::recv\n", errno); + return 0; + } + else if ( status == 0 ) + { + return 0; + } + else + { + s = buf; + return status; + } +} + + + +bool Socket::connect ( const std::string host, const int port ) +{ + if ( ! is_valid() ) return false; + + m_addr.sin_family = AF_INET; + m_addr.sin_port = htons ( port ); + + int status = inet_pton ( AF_INET, (char *) host.c_str(), &m_addr.sin_addr ); + + if ( errno == EAFNOSUPPORT ) return false; + + status = ::connect ( m_sock, ( sockaddr * ) &m_addr, sizeof ( m_addr ) ); + + if ( status == 0 ) + return true; + else + return false; +} + +/*void Socket::set_non_blocking ( const bool b ) +{ + + int opts; + + opts = fcntl ( m_sock, + F_GETFL ); + + if ( opts < 0 ) + { + return; + } + + if ( b ) + opts = ( opts | O_NONBLOCK ); + else + opts = ( opts & ~O_NONBLOCK ); + + fcntl ( m_sock, + F_SETFL,opts ); + +} +*/ diff --git a/src/socket.h b/src/socket.h new file mode 100644 index 0000000..3985291 --- /dev/null +++ b/src/socket.h @@ -0,0 +1,63 @@ +// Definition of the Socket class + +#ifndef Socket_class +#define Socket_class + +#include + +#ifdef WIN32 +typedef int socklen_t; +#include +extern "C" +{ +#include "inet_pton.h" +} +#else +#include +#include +#include +#include +#include +#endif + +#include + + +const int MAXHOSTNAME = 200; +const int MAXCONNECTIONS = 5; +const int MAXRECV = 500; + +class Socket +{ + public: + Socket(); + virtual ~Socket(); + + // Server initialization + bool create(); + bool bind ( const int port ); + bool listen() const; + bool accept ( Socket& ) const; + + // Client initialization + bool connect ( const std::string host, const int port ); + + // Data Transimission + bool send ( const std::string ) const; + int recv ( std::string& ) const; + + +// void set_non_blocking ( const bool ); + + bool is_valid() const { return m_sock != -1; } + + private: + + int m_sock; + sockaddr_in m_addr; + + +}; + + +#endif diff --git a/src/socketexception.h b/src/socketexception.h new file mode 100644 index 0000000..009622c --- /dev/null +++ b/src/socketexception.h @@ -0,0 +1,23 @@ +// SocketException class + + +#ifndef SocketException_class +#define SocketException_class + +#include + +class SocketException +{ + public: + SocketException ( std::string s ) : m_s ( s ) {}; + ~SocketException (){}; + + std::string description() { return m_s; } + + private: + + std::string m_s; + +}; + +#endif diff --git a/src/sound.c b/src/sound.c index ee0ad04..be9683c 100644 --- a/src/sound.c +++ b/src/sound.c @@ -27,7 +27,7 @@ * SUCH DAMAGE. */ -#define _MT +//#define _MT #include #include #include @@ -83,8 +83,9 @@ int gFlushBuffers = 0; int gExit = 0; int gBeepOn = 0; int gOneHzPtr = 0; -extern double last_instruct; -static double spkr_cycle = 0; +extern UINT64 cycles; +extern int cycle_delta; +static UINT64 spkr_cycle = 0; #ifdef _WIN32 HANDLE g_hEquThread; @@ -319,7 +320,7 @@ DWORD WINAPI EquProc(LPVOID lpParam) if (gBeepOn) { - if (last_instruct - spkr_cycle > 0.001) + if (cycles + cycle_delta - spkr_cycle > 0.001) { gPlayTone = 0; gBeepOn = 0; @@ -359,12 +360,13 @@ void init_sound(void) { gpOneHertz[x] = (unsigned short) (sin(w * (double) x) * 32767.0); } + spkr_cycle = cycles; return; #ifdef _WIN32 // Start thread to handle Sound I/O - g_hEquThread = (HANDLE)_beginthreadex(0,0,EquProc,0,0,&dwThreadID); +// g_hEquThread = (HANDLE)_beginthreadex(0,0,EquProc,0,0,&dwThreadID); #endif } @@ -395,6 +397,7 @@ void sound_start_tone(int freq) { if (freq < m_SamplingRate / 2.0) { +// printf("Playing tone of frequency %d\n", freq); gToneFreq = freq; gPlayTone = 1; } @@ -408,6 +411,7 @@ stop_tone: This routine stops playing of tones void sound_stop_tone(void) { +// printf("Stop playing tone\n"); #ifdef _WIN32 // waveOutReset (hOutput) ; #endif @@ -426,14 +430,14 @@ toggle_speaker: This routine handles toggling of the I/O bit that */ void sound_toggle_speaker(int bitVal) { - double delta; + UINT64 delta; /* Calculate delta between current cycle and last cycle */ - delta = last_instruct - spkr_cycle; - spkr_cycle = last_instruct; + delta = cycles + cycle_delta - spkr_cycle; + spkr_cycle = cycles + cycle_delta; /* Test if delta is within a valid range */ - if ((delta < 5000) && (delta != 0.0)) + if ((delta < 5000) && (delta != 0)) { gBeepOn = 1; sound_start_tone((int) (60000.0 / delta)); diff --git a/src/vt_client_main.cpp b/src/vt_client_main.cpp new file mode 100644 index 0000000..4d5d504 --- /dev/null +++ b/src/vt_client_main.cpp @@ -0,0 +1,165 @@ +#include "clientsocket.h" +#include "socketexception.h" +#include +#include +#include + +using namespace std; + +int main ( int argc, char* argv[] ) +{ + fstream filestr; + + if (argc != 2) + { + printf("usage: %s port#\n", argv[0]); + return 1; + } + +#ifdef WIN32 + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD( 1, 1 ); + + err = WSAStartup( wVersionRequested, &wsaData ); + if ( err != 0 ) + { + /* Tell the user that we couldn't find a useable */ + /* winsock.dll. */ + return 1; + } + + /* Confirm that the Windows Sockets DLL supports 1.1.*/ + /* Note that if the DLL supports versions greater */ + /* than 1.1 in addition to 1.1, it will still return */ + /* 1.1 in wVersion since that is the version we */ + /* requested. */ + + if ( LOBYTE( wsaData.wVersion ) != 1 || + HIBYTE( wsaData.wVersion ) != 1 ) + { + /* Tell the user that we couldn't find a useable */ + /* winsock.dll. */ + WSACleanup( ); + return 1; + } +#endif + + std::cout << "Use decimal or C hex notation for input (0x2a)\n"; + std::cout << "Return data reported according to specified radix\n"; + std::cout << "Type 'help' or 'quit' to exit\n"; + + try + { + + ClientSocket client_socket ( "localhost", atoi(argv[1]) ); + + std::string reply; + std::string cmd; + std::string outfile; + int pos,c; + std::cout << "Ok> "; + + while (true) + { + getline(std::cin, cmd); + + outfile = "stdout"; + // Search for '>' in the command + if ((pos = cmd.find('>')) != -1) + { + for (c = pos+1; c < cmd.length(); c++) + { + if (cmd[c] != ' ') + break; + } + + outfile = cmd.substr(c, cmd.length()-c); + cmd = cmd.substr(0, pos); + while (cmd[cmd.length()-1] == ' ') + cmd = cmd.substr(0, cmd.length()-1); + } + + if (cmd == "quit") + break; + if (cmd == "") + { + std::cout << "Ok> "; + continue; + } + + try + { + client_socket << cmd; + } + catch ( SocketException& ) + {} + + // Get response(s) + if (outfile != "stdout") + filestr.open(outfile.c_str(), fstream::out); + reply = ""; + int retry = 0; // Only wait so long for "Ok" + while (reply != "Ok") + { + // Get response + try + { + client_socket >> reply; + } + catch ( SocketException& e) + { + std::cout << "Exception!\n"; + } + + // Check if response is "Ok" or contains "Ok" at the end + int len = reply.length(); + if ((reply[len-1] == 'k') && (reply[len-2] == 'O')) + { + // Check if output goes to a file + if (outfile == "stdout") + std::cout << reply << "> "; + else + { + reply = reply.substr(0, reply.length()-2); + filestr << reply; + std::cout << "Ok> "; + } + reply = "Ok"; + } + else + { + if (outfile == "stdout") + std::cout << reply; + else + { + filestr << reply; + } + } + + // Check if response is "Syntax error" + if (reply == "Syntax error") + { + reply = "Ok"; + std::cout << "\nOk> "; + } + } + if (outfile != "stdout") + filestr.close(); + + if (cmd == "terminate") + break; + } + + } + catch ( SocketException& e ) + { + std::cout << "Exception was caught:" << e.description() << "\n"; + } + + std::cout << "\n"; + + return 0; +} From e54c746a92c30207afcf15c7af09db2b678c712d Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 26 Jan 2008 14:55:16 +0000 Subject: [PATCH 052/327] Checkin for version 1.0. Added enumeration for FL_DELETE --- src/FLU/Flu_Enumerations.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/FLU/Flu_Enumerations.h b/src/FLU/Flu_Enumerations.h index 89b7586..6a7086d 100644 --- a/src/FLU/Flu_Enumerations.h +++ b/src/FLU/Flu_Enumerations.h @@ -65,7 +65,8 @@ enum { FLU_RIGHT_CLICK, FLU_WIDGET_CALLBACK, FLU_MOVED_NODE, - FLU_NEW_NODE + FLU_NEW_NODE, + FLU_DELETE }; /* not done */ From 93162d5de5b927a0e7fc695d03d2353b9df7416c Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 26 Jan 2008 15:04:42 +0000 Subject: [PATCH 053/327] Checkin for version 1.0. Many changes and additions. --- GNUmakefile | 50 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index e929c2b..7fd6b1c 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -2,16 +2,18 @@ CFLAGS += -I $(FLTKDIR) -I src/FLU CPPFLAGS += -I $(FLTKDIR) EXECUTABLE = virtualt +CLIENT = vt_client FLTKCONFIG = $(FLTKDIR)/fltk-config VPATH = src:obj -CFLAGS += `$(FLTKCONFIG) --cflags --use-images` -LDFLAGS += `$(FLTKCONFIG) --ldstaticflags --use-images` -L /usr/X11R6/lib -L $(FLTKDIR)/lib +#CFLAGS += `$(FLTKCONFIG) --cflags --use-images` +LDFLAGS += -g `$(FLTKCONFIG) --ldstaticflags --use-images` -L /usr/X11R6/lib -L $(FLTKDIR)/lib OBJECTS = $(SOURCES:.c=.o) OBJECTSCPP = $(SOURCESCPP:.cpp=.o) -LIBFILES = -lstdc++ -lfltk -lfltk_images -lfltk_jpeg -lfltk_png -lfltk_z -lm -lc -lX11 +CLIENT_OBJS = $(CLIENT_SRC:.cpp=.o) +LIBFILES = -lstdc++ -lfltk -lfltk_images -lfltk_jpeg -lfltk_png -lfltk_z -lm -lc -lX11 -lpthread #LIBFILES = /$(FLTKDIR)/lib/libfltk.a ../$(FLTKDIR)/lib/libfltk_images.a ../$(FLTKDIR)/lib/libfltk_jpeg.a ../$(FLTKDIR)/lib/libfltk_png.a \ # /$(FLTKDIR)/lib/libfltk_z.a -lm -lc -lX11 OBJDIR = obj @@ -21,17 +23,20 @@ OBJDIR = obj # Define all source files below # ============================= SOURCES = m100emu.c doins.c genwrap.c serial.c intelhex.c memory.c m100rom.c \ - m200rom.c n8201rom.c romstrings.c sound.c io.c + m200rom.c n8201rom.c romstrings.c sound.c io.c m10rom.c SOURCESCPP = display.cpp setup.cpp periph.cpp disassemble.cpp file.cpp memedit.cpp cpuregs.cpp \ a85parse.cpp assemble.cpp MString.cpp MStringArray.cpp rpn_eqn.cpp vtobj.cpp \ Flu_DND.cpp flu_pixmaps.cpp Flu_Tree_Browser.cpp FluSimpleString.cpp ide.cpp \ - multiwin.cpp multiwin_icons.cpp - + multiwin.cpp multiwin_icons.cpp project.cpp multieditwin.cpp rememcfg.cpp \ + fl_usage_box.cpp remote.cpp socket.cpp serversocket.cpp +CLIENT_SRC = clientsocket.cpp vt_client_main.cpp socket.cpp # ======================== # Rule for all files below # ======================== -all: $(SOURCES) $(SOURCESCPP) $(EXECUTABLE) +all: virtualt vt_client +virtualt: $(SOURCES) $(SOURCESCPP) +vt_client: $(CLIENT_SRC) $(EXECUTABLE): $(OBJECTS) $(OBJECTSCPP) ifndef FLTKDIR @@ -41,6 +46,14 @@ else cd .. endif +$(CLIENT): $(CLIENT_OBJS) +ifndef FLTKDIR + @echo "FLTKDIR environment variable must be set first!" +else + cd obj; gcc $(LDFLAGS) $(CLIENT_OBJS) $(LIBFILES) -o ../$@ + cd .. +endif + # =============================== # Rule for compiling source files @@ -56,6 +69,7 @@ endif # Declare dependencies on header files below # ========================================== $(OBJECTS) $(OBJECTSCPP): m100emu.h GNUmakefile VirtualT.h +$(CLIENT_OBJS): socket.h disassemble.o: disassemble.h io.h cpu.h periph.h memedit.h romstrings.h display.o: display.h io.h file.h setup.h periph.h memory.h memedit.h @@ -64,14 +78,19 @@ file.o: memory.h roms.h intelhex.h io.o: cpu.h gen_defs.h io.h serial.h display.h setup.h memory.h intelhex.o: intelhex.h m100emu.o: io.h cpu.h doins.h display.h genwrap.h filewrap.h roms.h \ - intelhex.h setup.h memory.h + intelhex.h setup.h memory.h do_instruct.h memedit.o: memedit.h disassemble.h memory.h cpu.h memory.o: memory.h cpu.h io.h intelhex.h setup.h periph.o: periph.h serial.h setup.h display.h disassemble.h serial.o: serial.h setup.h display.h +rememcfg.o: rememcfg.h setup.h display.h +fl_usage_box.o: fl_usage_box.h setup.o: setup.h io.h serial.h memory.h memedit.h sound.c: sound.h -m100rom.o m102rom.o m200rom.o n8201rom.o romstrings.o: roms.h romstrings.h +m100rom.o m102rom.o m200rom.o n8201rom.o romstrings.o m10rom.o: roms.h romstrings.h +remote.o: remote.cpp m100emu.h socket.h serversocket.h socketexception.h +socket.o: socket.h +serversocket.o: serversocket.h # ========== # asm files @@ -90,9 +109,17 @@ Flu_DND.o: FLU/Flu_DND.h flu_pixmaps.o: FLU/flu_pixmaps.h Flu_Tree_Browser.o: FLU/Flu_Tree_Browser.h FluSimpleString.o: FLU/FluSimpleString.h -ide.o: ide.h -multiwin.o: multiwin.h +ide.o: ide.h vtobj.h multiwin.h multieditwin.h +multiwin.o: multiwin.h vtobj.h +multiwin.o: multieditwin.h multiwin.h vtobj.h multiwin_icons.o: multiwin_icons.h +project.o: project.h + +# ========== +# client files +# ========== +clientsocket.o: clientsocket.h socket.h +vt_client_main.o: clientsocket.h socket.h # ============================= # Rule to clean all build files @@ -100,4 +127,5 @@ multiwin_icons.o: multiwin_icons.h clean: cd obj; rm *.o; cd .. rm virtualt + rm vt_client From 41632bf196f9829de48df026bbf0706fec9e4fe1 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 26 Jan 2008 15:08:30 +0000 Subject: [PATCH 054/327] Socket client application for controlling VirtualT remotely. This is the project file for a simple client. The main sources are in the src directory. --- vt_client/stdafx.cpp | 8 ++ vt_client/stdafx.h | 15 +++ vt_client/vt_client.cpp | 11 ++ vt_client/vt_client.vcproj | 236 +++++++++++++++++++++++++++++++++++++ 4 files changed, 270 insertions(+) create mode 100644 vt_client/stdafx.cpp create mode 100644 vt_client/stdafx.h create mode 100644 vt_client/vt_client.cpp create mode 100644 vt_client/vt_client.vcproj diff --git a/vt_client/stdafx.cpp b/vt_client/stdafx.cpp new file mode 100644 index 0000000..3c1362b --- /dev/null +++ b/vt_client/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// vt_client.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/vt_client/stdafx.h b/vt_client/stdafx.h new file mode 100644 index 0000000..ddacb46 --- /dev/null +++ b/vt_client/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/vt_client/vt_client.cpp b/vt_client/vt_client.cpp new file mode 100644 index 0000000..de30fd6 --- /dev/null +++ b/vt_client/vt_client.cpp @@ -0,0 +1,11 @@ +// vt_client.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" + + +int _tmain(int argc, _TCHAR* argv[]) +{ + return 0; +} + diff --git a/vt_client/vt_client.vcproj b/vt_client/vt_client.vcproj new file mode 100644 index 0000000..f3606e0 --- /dev/null +++ b/vt_client/vt_client.vcproj @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 5895cc16ea4c476b84be33b294de31b0146db45a Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 26 Jan 2008 15:11:31 +0000 Subject: [PATCH 055/327] Initial checkin of documentation / help system. --- doc/about_hw.html | 22 ++++++++++ doc/asm_ref.html | 21 +++++++++ doc/basics.html | 23 ++++++++++ doc/emulation.html | 22 ++++++++++ doc/help.html | 90 +++++++++++++++++++++++++++++++++++++++ doc/host.html | 30 +++++++++++++ doc/ide.html | 23 ++++++++++ doc/license.html | 53 +++++++++++++++++++++++ doc/linker_ref.html | 21 +++++++++ doc/mail_list.html | 21 +++++++++ doc/models.html | 22 ++++++++++ doc/preface.html | 101 ++++++++++++++++++++++++++++++++++++++++++++ doc/tools.html | 23 ++++++++++ 13 files changed, 472 insertions(+) create mode 100644 doc/about_hw.html create mode 100644 doc/asm_ref.html create mode 100644 doc/basics.html create mode 100644 doc/emulation.html create mode 100644 doc/help.html create mode 100644 doc/host.html create mode 100644 doc/ide.html create mode 100644 doc/license.html create mode 100644 doc/linker_ref.html create mode 100644 doc/mail_list.html create mode 100644 doc/models.html create mode 100644 doc/preface.html create mode 100644 doc/tools.html diff --git a/doc/about_hw.html b/doc/about_hw.html new file mode 100644 index 0000000..5df2017 --- /dev/null +++ b/doc/about_hw.html @@ -0,0 +1,22 @@ + + + VirtualT Help - About the Hardware + + + + + +

Chapter 7 - About the Hardware

+ +

This chapter details all aspects of the emulated hardware and explains how VirtualT +emulates the original Model T system. + +

    +
+ +Home + +
+ + + diff --git a/doc/asm_ref.html b/doc/asm_ref.html new file mode 100644 index 0000000..a4f9a94 --- /dev/null +++ b/doc/asm_ref.html @@ -0,0 +1,21 @@ + + + VirtualT Help - Assembler Reference + + + + + +

Appendix A - Assembler Reference

+ +

This appendix details all features and operation of the integrated assembler. + +

    +
+ +Home + +
+ + + diff --git a/doc/basics.html b/doc/basics.html new file mode 100644 index 0000000..7b35a3d --- /dev/null +++ b/doc/basics.html @@ -0,0 +1,23 @@ + + + VirtualT Help - Basics + + + + + +

Chapter 1 - Model T Basics

+ +

VirtualT is an emulator for the Tandy line of laptop computers, specifically +the Model 100, Model 102 and Model 200. The emulator has also been expanded to +support the Tandy's close relatives, the NEC PC-8201 and Ollivetti M10 models. + +

    +
+ +Home + +
+ + + diff --git a/doc/emulation.html b/doc/emulation.html new file mode 100644 index 0000000..bf49106 --- /dev/null +++ b/doc/emulation.html @@ -0,0 +1,22 @@ + + + VirtualT Help - Emulation Features + + + + + +

Chapter 4 - Emulation Features

+ +

This chapter describes the emulation features supported by VirtualT. These include +things such as display and speed settings, Peripherials, Option ROMs, etc. + +

    +
+ +Home + +
+ + + diff --git a/doc/help.html b/doc/help.html new file mode 100644 index 0000000..ec8fe6e --- /dev/null +++ b/doc/help.html @@ -0,0 +1,90 @@ + + + VirtualT Help + + + + + + + + +
+

Virtual T!

+

A Model 100/102/200 Emulator

+

Version 1.0 by Ken Pettit
+ Copyright 2004-2008 by Ken Pettit, Jerome Vernet and James Hurd.

+
+ + + + + +
This software and manual are + provided under the terms of the BSD License.
+ + + + + + +
Preface +

+
+
+ 1 - Model T Basics +
+
+ 2 - Emulated Models +
+
+ 3 - Interfacing with the Host +

+ 4 - Emulation Features + +
+ 5 - Tools + + 6 - Integrated Development Environment + + 7 - About the Hardware +
+
+ A - Assembler Reference +
+
+ B - Linker Reference +
+
+ C - Software License +
+
+ D - Model T Mailing List +
+ + + diff --git a/doc/host.html b/doc/host.html new file mode 100644 index 0000000..3921120 --- /dev/null +++ b/doc/host.html @@ -0,0 +1,30 @@ + + + VirtualT Help - Host + + + + + +

Chapter 3 - Interfacing with the Host

+ +

This chapter describes support for interfacing with the Host OS. Supported features vary +between Linux, Windows and MacOS and are detailed here. + +

    +
+ +Home + +
+ +

Directory Structure

+ +

Loading / Saving RAM

+ +

RAM Snapshots

+ +

Loading / Saving Files

+ + + diff --git a/doc/ide.html b/doc/ide.html new file mode 100644 index 0000000..d0f7edb --- /dev/null +++ b/doc/ide.html @@ -0,0 +1,23 @@ + + + VirtualT Help - Integrated Development Environment (IDE) + + + + + +

Chapter 6 - Integrated Development Environment (IDE)

+ +

This chapter describes VirtualT's Integrated Development Environment (IDE). The IDE provides +an enviroment for writing, assembling and debugging assembly language programs directly on the +emulated hardware. + +

    +
+ +Home + +
+ + + diff --git a/doc/license.html b/doc/license.html new file mode 100644 index 0000000..dd98eb1 --- /dev/null +++ b/doc/license.html @@ -0,0 +1,53 @@ + + + +

Appendix C - BSD License

+ +

VirtualT and included programs are provided under the terms +of the BSD Public License with the following exceptions:

+ +
    + +
  1. Any binary ROM images that may have been received as part of the + distribution to support specific model emulation are not covered under + the terms of the BSD License.
    +
    + +
+ +Home + +
+ +

BSD LICENSE

+
+

Copyright (c) 2004-2008, Ken Pettit, Jerome Vernet, Steven Hurd +

All rights reserved. + +

Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +

+
1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer.
+
2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution.
+
3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission.
+
+

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +

END OF TERMS AND CONDITIONS

+ + + diff --git a/doc/linker_ref.html b/doc/linker_ref.html new file mode 100644 index 0000000..0b1f9c3 --- /dev/null +++ b/doc/linker_ref.html @@ -0,0 +1,21 @@ + + + VirtualT Help - Linker Reference + + + + + +

Appendix B - Linker Reference

+ +

This appendix details all features and operation of the integrated linker. + +

    +
+ +Home + +
+ + + diff --git a/doc/mail_list.html b/doc/mail_list.html new file mode 100644 index 0000000..aae0392 --- /dev/null +++ b/doc/mail_list.html @@ -0,0 +1,21 @@ + + + VirtualT Help - Mailing List + + + + + +

Appendix D - Model T Mailing List

+ +

This appendix details the Model T Mailing list and various Model T support sites. + +

    +
+ +Home + +
+ + + diff --git a/doc/models.html b/doc/models.html new file mode 100644 index 0000000..1461598 --- /dev/null +++ b/doc/models.html @@ -0,0 +1,22 @@ + + + VirtualT Help - Models + + + + + +

Chapter 2 - Emulated Models

+ +

This chapter describes the various laptop models that are emulated and a comparison +of the features supported by each. + +

    +
+ +Home + +
+ + + diff --git a/doc/preface.html b/doc/preface.html new file mode 100644 index 0000000..f6405c1 --- /dev/null +++ b/doc/preface.html @@ -0,0 +1,101 @@ + + + + + + VirtualT 1.0 Help System + + + + + +

Preface

+ +

This manual describes VirtualT version 1.0, a Tandy Model 100/102/200 +Emulator for Linux, Microsoft Windows and MacOS. Each +of the chapters in this manual is designed as a tutorial for +using VirtualT, while the appendices provide additional reference material.

+ +

This manual may be printed, modified, and/or used under +the terms of the BSD license provided in Appendix C. + +

Home + +


+ +

Organization

+ +

This manual is organized into the following chapters and appendices:

+ + + +

Conventions

+ +

The following typeface conventions are used in this manual:

+ +
    +
  • Function and constant names are shown in bold courier type
  • + +
  • Code samples and commands are shown in regular courier type
  • + +
+ +

Abbreviations

+ +

The following abbreviations are used in this manual:

+ +
+ +
X11
+
The X Window System version 11.
+ +
Xlib
+
The X Window System interface library.
+ +
WIN32
+
The Microsoft Windows 32-bit Application Programmer's Interface.
+ +
MacOS
+
The Apple Macintosh OS 8.6 and later, including OS X.
+ +
+ +

Copyrights and Trademarks

+ +

VirtualT is Copyright 2004-2008 by Ken Pettit and others. Use and +distribution of VirtualT is governed by the BSD License, located +in Appendix C.

+ +

Linux is a registered trademark of Linus Torvalds. +Microsoft and Windows are registered trademarks of Microsoft +Corporation. Apple, Macintosh, MacOS, and Mac OS X are +registered trademarks of Apple Computer, Inc.

+ + + + diff --git a/doc/tools.html b/doc/tools.html new file mode 100644 index 0000000..c5f20a7 --- /dev/null +++ b/doc/tools.html @@ -0,0 +1,23 @@ + + + VirtualT Help - Tools + + + + + +

Chapter 5 - Tools

+ +

This chapter describes additional tools that VirtualT offers beyond the original +functinality of the hardware. These tools include things such as a CPU Register +view / edit window, a memory editor, disassembler, etc. + +

    +
+ +Home + +
+ + + From 0dcc98595567216940ed218a910fd4343d82d816 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 26 Jan 2008 15:12:42 +0000 Subject: [PATCH 056/327] Addition of ROM image for the M10 emulation. --- ROMs/m10rom.bin | Bin 0 -> 32784 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ROMs/m10rom.bin diff --git a/ROMs/m10rom.bin b/ROMs/m10rom.bin new file mode 100644 index 0000000000000000000000000000000000000000..0a63828f24565e2d09d8b5ee1a7de4ee790d822b GIT binary patch literal 32784 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 bfSk>V-qC&Pe?R{_0{>r+06+deyZ`?H$Cnd# literal 0 HcmV?d00001 From bb05bdce0bafd9c440ba9ead88c431891d18bb4a Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 26 Jan 2008 15:16:22 +0000 Subject: [PATCH 057/327] Checkin for version 1.0. Also converts from Visual Studio 6 to Visual Studio 2005. --- VirtualT.sln | 26 + VirtualT.suo | Bin 0 -> 72704 bytes VirtualT.vcproj | 1204 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1230 insertions(+) create mode 100644 VirtualT.sln create mode 100644 VirtualT.suo create mode 100644 VirtualT.vcproj diff --git a/VirtualT.sln b/VirtualT.sln new file mode 100644 index 0000000..3c1f19f --- /dev/null +++ b/VirtualT.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VirtualT", "VirtualT.vcproj", "{823B96D9-CEF2-4B9D-8B90-A6F0DEC5B97A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vt_client", "vt_client\vt_client.vcproj", "{2EE29331-FFC1-46AF-96AB-AA0643DF918E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {823B96D9-CEF2-4B9D-8B90-A6F0DEC5B97A}.Debug|Win32.ActiveCfg = Debug|Win32 + {823B96D9-CEF2-4B9D-8B90-A6F0DEC5B97A}.Debug|Win32.Build.0 = Debug|Win32 + {823B96D9-CEF2-4B9D-8B90-A6F0DEC5B97A}.Release|Win32.ActiveCfg = Release|Win32 + {823B96D9-CEF2-4B9D-8B90-A6F0DEC5B97A}.Release|Win32.Build.0 = Release|Win32 + {2EE29331-FFC1-46AF-96AB-AA0643DF918E}.Debug|Win32.ActiveCfg = Debug|Win32 + {2EE29331-FFC1-46AF-96AB-AA0643DF918E}.Debug|Win32.Build.0 = Debug|Win32 + {2EE29331-FFC1-46AF-96AB-AA0643DF918E}.Release|Win32.ActiveCfg = Release|Win32 + {2EE29331-FFC1-46AF-96AB-AA0643DF918E}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/VirtualT.suo b/VirtualT.suo new file mode 100644 index 0000000000000000000000000000000000000000..ae9f473b1a686305991aca4d293b9fad6b114e38 GIT binary patch literal 72704 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 LAG=GD-=+C~o-&=| literal 0 HcmV?d00001 diff --git a/VirtualT.vcproj b/VirtualT.vcproj new file mode 100644 index 0000000..fe90b91 --- /dev/null +++ b/VirtualT.vcproj @@ -0,0 +1,1204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 9da4678a5a1950d84f1d362208af0afc833d47e9 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 26 Jan 2008 16:15:45 +0000 Subject: [PATCH 058/327] Fixed bug when ROM file not found. --- src/memory.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/memory.c b/src/memory.c index c1bfde0..5f67a6e 100644 --- a/src/memory.c +++ b/src/memory.c @@ -1006,6 +1006,7 @@ void load_sys_rom(void) if (fd < 0) { show_error("Could not open ROM file"); + return; } gRomSize = gModel == MODEL_T200 ? 40960 : 32768; From 65ffb739a3021029fcfa867a6368ed9ba1fd4261 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 27 Jan 2008 04:23:09 +0000 Subject: [PATCH 059/327] Added release notes for version 1.0 which is soon to be released. --- release.txt | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 release.txt diff --git a/release.txt b/release.txt new file mode 100644 index 0000000..d0506e2 --- /dev/null +++ b/release.txt @@ -0,0 +1,132 @@ +==================== +VirtualT Release.txt +==================== + + +This file lists the changes and additions for each of the versions of VirtualT since v0.3 + +===================== +v1.0 January 17 2008 +===================== + +1. Fixed ReMem emulation in both Normal and MMU modes. Memory mapping now consistent with + an actual ReMem. Emulation supports only the latest ReMem FW version (64, 65, 66). In + MMU mode, both sector access and direct memory access work properly. Also fixed some bugs + with the the Rampac emulation. + +2. Added configuration page for ReMem Map display and setup. + +3. Added support for M10 Emulation. + +4. Added breakpoint capability to CPURegs window. Up to 4 breakpoints can be specified and + enabled or disabled. + +5. Added Remote control interface via sockets. The socket interface is enabled via a command + line switch to specify the socket port, such as "virtualt -p 20000". The protocol is + simple text command and response with async text messages sent for breakpoint and otional + screen output messages. See Help for full details. + +6. Added serial I/O support under Linux. The current implementation has a few "hard coded" + port names in the port list, but allows the user to specify an "Other Host Port" name to + specify the serial device. + +7. Modified the main emulatin loop so it uses fewer CPU cycles. Previous versions consumed + up to 100% CPU cycles causing heat issues and reduced battery life on laptops. Added + new Speed menu selections to allow finer setting of emulation speed vs. CPU utilization. + +8. Fixed a bug with the emulation of interrupts and with the extended opcode DSUB flags. + +9. Added a vt_client project / application to communicate with VirtualT socket interface + using a very simple command line interface. + +10. Added a "Cold Boot" option to the Emulation menu. + +11. Added content to the Help system. + +12. Transitioned the Windows development environment to Visual Studio 2005. The project files + are no longer compatible with Visual Studio 6. + +13. Adds a feature to patch the ROM on load to show VirtualT version in the MENU. This can be + disabled in the "Memory Options" menu. + + +=================== +v0.8 May 11 2006 +=================== + +1. Added the beginnings of an Integrated Development Environment. The IDE included a project + manager that supports "Tree" browsing of source files and a project settings dialog for + specifying assember and linker options. Also has a multi-window edit capability using a + very simple text editor. The editor will be expanded in a future release and will also + include features for source level debugging, such as display of breakpoints and current + execution location. + +2. Added an 8085 assembler, but no linker. The assembler gernerates ELF format .obj output + files for use with the linker to be released in a later version. The assembler is + basically useless without the assembler, but is included in the project. + +3. Added the beginnings of the Help system, although no real help info available. + +4. Maybe other bug fixes but I have forgotten because I am writing this 1 year after release. + + +=================== +v0.7 April 20 2006 +=================== + +1. Fixed memory access issue in M100/M102 modes when not in ReMem emulation mode. + + +=================== +v0.6 April 17 2006 +=================== + +1. Added CPU Registers window to the Tools menu. This window allows viewing / modifying of + 8085 CPU registers in addition to simple stop/step/run operations. It is not intended as + a full blown debugger, but rather as a tool to be used along with a debugger to be added + later. + +2. Completed ReMem emulation support. VirtualT emulates rev 4 of the ReMem firmware. All + features of ReMem are emulated inclulding Rampac support. See the ReMem documentation for + operation of the ReMem emulation. + +3. Added Load and Save operations to the Memory Editor Window. + +4. Added MSPLAN to the T200 ROM and support for running option ROMs from T200 emulation mode. + +5. Changed the name of this file from readme.txt to release.txt. + + +=================== +v0.4 August 3 2005 +=================== + +1. Added a directory structure to deal with multiple emulation platforms. Each model has its + own directory. Each directory contains the ROM and RAM files for emulation of that specific + model. This directory structure must be maintained since the emulator searches for the + ROM file using this tree structure. The directories are: + + + | + +-- M100 + +-- M102 + +-- T200 + +-- PC8201 + +2. Option ROMs are now loaded based on the model being emulated. Old Option ROM selection + will be lost and must be re-selected. + +3. Support for the M102, T200, and PC8201 have been added. Loading and saving BASIC files + for the PC8201 will cause an error that will "crash" the emulation and dump the RAM contents. + The BASIC tokens for the NEC machines are different than the Tandy machines and the tokenizer + has not been updated yet. + +4. Partial support for ReMem and Rampac have been added under the "Emulation, Memory Options" + menu item. Emulation is not fully supported yet and selecting anything but "Base Memory" + will cause unexpected results. + +5. A HEX memory editor has been added in the "Tools, Memory Editor" menu item. The editor is + fully functional except the "Load" and "Save" options under the file menu. + +6. The "Tools, Disassembler" has been updated to disassemble the M102, T200, and PC8201 ROMS. + From 84b41e18ef850fe561ba075167e22731318e7e8f Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 1 Feb 2008 06:00:40 +0000 Subject: [PATCH 060/327] Deleted old ROM image files. --- ROMs/N8201rom.bin | Bin 32768 -> 0 bytes ROMs/m100.rom.txt | 2049 --------------------------------------------- ROMs/m102.rom.txt | 2049 --------------------------------------------- ROMs/m10rom.bin | Bin 32784 -> 0 bytes 4 files changed, 4098 deletions(-) delete mode 100644 ROMs/N8201rom.bin delete mode 100644 ROMs/m100.rom.txt delete mode 100644 ROMs/m102.rom.txt delete mode 100644 ROMs/m10rom.bin diff --git a/ROMs/N8201rom.bin b/ROMs/N8201rom.bin deleted file mode 100644 index 4b8f17ca958e60217fec0eafca496f8fa45866d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32768 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 bfSk>V-qC&Pe?R{_0{>r+06+deyZ`?H$Cnd# From e4c5f51def9b645422ad4d72d856dadfdd81ed39 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 1 Feb 2008 06:03:16 +0000 Subject: [PATCH 061/327] Added PC-8201 ROM image back with different filename. --- ROMs/PC8201rom.bin | Bin 0 -> 32768 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ROMs/PC8201rom.bin diff --git a/ROMs/PC8201rom.bin b/ROMs/PC8201rom.bin new file mode 100644 index 0000000000000000000000000000000000000000..4b8f17ca958e60217fec0eafca496f8fa45866d0 GIT binary patch literal 32768 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 Date: Fri, 1 Feb 2008 06:03:58 +0000 Subject: [PATCH 062/327] Added M10 ROM image back with different filename. --- ROMs/M10rom.bin | Bin 0 -> 32784 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ROMs/M10rom.bin diff --git a/ROMs/M10rom.bin b/ROMs/M10rom.bin new file mode 100644 index 0000000000000000000000000000000000000000..0a63828f24565e2d09d8b5ee1a7de4ee790d822b GIT binary patch literal 32784 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 bfSk>V-qC&Pe?R{_0{>r+06+deyZ`?H$Cnd# literal 0 HcmV?d00001 From 157152917a186e36bedf8012c87da5390e454b2d Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 1 Feb 2008 06:09:30 +0000 Subject: [PATCH 063/327] Updated makefile to compile with MacOS and to fix link issues with FLTK Help_Dialog. --- GNUmakefile | 85 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 14 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 7fd6b1c..1df19de 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,22 +1,37 @@ +# =============================================== +# Makefile for VirtualT. Notice that the order +# of the fltk_images and fltk libraries in the +# LIBFILES definition is order dependent. +# +# This Makefile builds silently except to echo +# the current compile file. To see the actual +# build commands, comment out the .SILENT: +# line below. +# =============================================== +.SILENT: + -include $(shell uname).mk + CFLAGS += -I $(FLTKDIR) -I src/FLU CPPFLAGS += -I $(FLTKDIR) EXECUTABLE = virtualt CLIENT = vt_client FLTKCONFIG = $(FLTKDIR)/fltk-config +FLTKLIB = $(FLTKDIR)/lib/libfltk.a VPATH = src:obj -#CFLAGS += `$(FLTKCONFIG) --cflags --use-images` -LDFLAGS += -g `$(FLTKCONFIG) --ldstaticflags --use-images` -L /usr/X11R6/lib -L $(FLTKDIR)/lib +LDFLAGS += -g -L/usr/X11R6/lib -L$(FLTKDIR)/lib +LIBFILES = -lstdc++ -lfltk_images -lfltk_jpeg -lfltk_png -lfltk_z -lfltk -lm -lc -lX11 -lpthread + +MACLDFLAGS = -L$(FLTKDIR)/lib +MACLIBFILES = -lstdc++ `$(FLTKCONFIG) --ldstaticflags --use-images` --lm -lpthread OBJECTS = $(SOURCES:.c=.o) OBJECTSCPP = $(SOURCESCPP:.cpp=.o) CLIENT_OBJS = $(CLIENT_SRC:.cpp=.o) -LIBFILES = -lstdc++ -lfltk -lfltk_images -lfltk_jpeg -lfltk_png -lfltk_z -lm -lc -lX11 -lpthread -#LIBFILES = /$(FLTKDIR)/lib/libfltk.a ../$(FLTKDIR)/lib/libfltk_images.a ../$(FLTKDIR)/lib/libfltk_jpeg.a ../$(FLTKDIR)/lib/libfltk_png.a \ -# /$(FLTKDIR)/lib/libfltk_z.a -lm -lc -lX11 OBJDIR = obj +POSTBUILD = $(FLTKCONFIG) --post # ============================= @@ -31,26 +46,53 @@ SOURCESCPP = display.cpp setup.cpp periph.cpp disassemble.cpp file.cpp memedit.c fl_usage_box.cpp remote.cpp socket.cpp serversocket.cpp CLIENT_SRC = clientsocket.cpp vt_client_main.cpp socket.cpp +# =============================== +# Rule for building 2 exectuables +# =============================== +all: virtualt vt_client + # ======================== -# Rule for all files below +# Rule to build VirtualT # ======================== -all: virtualt vt_client -virtualt: $(SOURCES) $(SOURCESCPP) -vt_client: $(CLIENT_SRC) - $(EXECUTABLE): $(OBJECTS) $(OBJECTSCPP) ifndef FLTKDIR @echo "FLTKDIR environment variable must be set first!" + exit 1 else - cd obj; gcc $(LDFLAGS) $(OBJECTS) $(OBJECTSCPP) $(LIBFILES) -o ../$@ + # Test if FLTK libraries built + if ! test -f $(FLTKLIB); then \ + echo "Please ensure the FLTK, JPEG, PNG and ZLIB libraries and run make again"; \ + exit 1; \ + fi; + @echo "Linking" $(EXECUTABLE) + if test -f /Developer/Tools/Rez; then \ + cd obj; g++ $(MACLDFLAGS) $(OBJECTS) $(OBJECTSCPP) $(MACLIBFILES) -o ../$@ ; \ + else \ + cd obj; gcc $(LDFLAGS) $(OBJECTS) $(OBJECTSCPP) $(LIBFILES) -o ../$@ ; \ + fi; cd .. + + # If bulding on MacOS, post the resource file to the executable + if test -f /Developer/Tools/Rez; then \ + $(POSTBUILD) $(EXECUTABLE); \ + fi; endif +# ======================== +# Rule to build vt_client +# ======================== $(CLIENT): $(CLIENT_OBJS) ifndef FLTKDIR @echo "FLTKDIR environment variable must be set first!" + exit 1 else - cd obj; gcc $(LDFLAGS) $(CLIENT_OBJS) $(LIBFILES) -o ../$@ + @echo "Linking" $(CLIENT) +# cd obj; gcc $(LDFLAGS) $(OBJECTS) $(OBJECTSCPP) $(LIBFILES) -o ../$@ + if test -f /Developer/Tools/Rez; then \ + cd obj; g++ $(MACLDFLAGS) $(CLIENT_OBJS) $(MACLIBFILES) -o ../$@ ; \ + else \ + cd obj; gcc $(LDFLAGS) $(CLIENT_OBJS) $(LIBFILES) -o ../$@ ; \ + fi cd .. endif @@ -59,10 +101,22 @@ endif # Rule for compiling source files # =============================== .cpp.o: +ifndef FLTKDIR + @echo "FLTKDIR environment variable must be set first!" + exit 1 +else + @echo "Compiling" $< -mkdir -p obj; g++ $(CPPFLAGS) -c $< -o obj/$@ +endif .c.o: +ifndef FLTKDIR + @echo "FLTKDIR environment variable must be set first!" + exit 1 +else + @echo "Compiling" $< -mkdir -p obj; gcc $(CFLAGS) -c $< -o obj/$@ +endif # ========================================== @@ -125,7 +179,10 @@ vt_client_main.o: clientsocket.h socket.h # Rule to clean all build files # ============================= clean: - cd obj; rm *.o; cd .. - rm virtualt + echo "=== cleaning ==="; + cd obj; rm *.o; cd ..; \ + rm virtualt rm vt_client + + From d78368a6aabb7745337853495cfa9ea6740b93b9 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 1 Feb 2008 06:18:04 +0000 Subject: [PATCH 064/327] Modifications to compile on MacOS and to provide automatic generation / installation of emulation directories and copying of ROM image files. --- src/display.cpp | 44 ++++++++---- src/genwrap.c | 4 +- src/genwrap.h | 2 + src/intelhex.c | 2 +- src/io.c | 4 +- src/m100emu.c | 172 ++++++++++++++++++++++++++++++++++++++++++----- src/memory.c | 22 +++--- src/multiwin.cpp | 3 +- src/multiwin.h | 3 +- src/remote.cpp | 12 ++-- src/setup.cpp | 4 -- src/socket.cpp | 4 +- src/sound.c | 4 +- src/vtobj.cpp | 2 +- 14 files changed, 222 insertions(+), 60 deletions(-) diff --git a/src/display.cpp b/src/display.cpp index 8ed6869..a21b927 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -237,6 +237,9 @@ resize_window: This function resizes the main window and repositions */ void resize_window() { + if (gpDisp == NULL) + return; + if (gModel == MODEL_T200) { gpDisp->DispHeight = 128; @@ -427,7 +430,8 @@ void cb_coldBoot (Fl_Widget* w, void*) show_remem_mode(); - gpDisp->Reset(); + if (gpDisp != NULL) + gpDisp->Reset(); if (gpDebugMonitor != 0) gpDebugMonitor->Reset(); } @@ -763,7 +767,8 @@ void switch_model(int model) gStdRomDesc = &gM100_Desc; /* Clear the LCD */ - gpDisp->Clear(); + if (gpDisp != NULL) + gpDisp->Clear(); if (gpDebugMonitor != 0) gpDebugMonitor->Clear(); @@ -1311,13 +1316,16 @@ void init_display(void) if (gRectsize == 0) gRectsize = 1; - gpDisp->DispHeight = DispHeight; - gpDisp->DisplayMode = DisplayMode; - gpDisp->MultFact = MultFact; - gpDisp->SolidChars = SolidChars; - gpDisp->gRectsize = gRectsize; - gpDisp->gXoffset = gXoffset; - gpDisp->gYoffset = gYoffset; + if (gpDisp != 0) + { + gpDisp->DispHeight = DispHeight; + gpDisp->DisplayMode = DisplayMode; + gpDisp->MultFact = MultFact; + gpDisp->SolidChars = SolidChars; + gpDisp->gRectsize = gRectsize; + gpDisp->gXoffset = gXoffset; + gpDisp->gYoffset = gYoffset; + } /* End the Window and show it */ MainWin->end(); @@ -1373,7 +1381,8 @@ void display_map_mode(char *str) void drawbyte(int driver, int column, int value) { - gpDisp->SetByte(driver, column, value); + if (gpDisp != NULL) + gpDisp->SetByte(driver, column, value); if (gpDebugMonitor != 0) gpDebugMonitor->SetByte(driver, column, value); @@ -1383,7 +1392,8 @@ void drawbyte(int driver, int column, int value) void lcdcommand(int driver, int value) { - gpDisp->Command(driver, value); + if (gpDisp != NULL) + gpDisp->Command(driver, value); if (gpDebugMonitor != 0) gpDebugMonitor->Command(driver, value); @@ -1392,7 +1402,8 @@ void lcdcommand(int driver, int value) void power_down() { - gpDisp->PowerDown(); + if (gpDisp != NULL) + gpDisp->PowerDown(); if (gpDebugMonitor != 0) gpDebugMonitor->PowerDown(); @@ -1401,9 +1412,13 @@ void power_down() void process_windows_event() { + Fl::check(); + return; if (gOsDelay) #ifdef WIN32 Fl::wait(0.001); +#elif defined(__APPLE__) + Fl::check(); #else Fl::wait(0.00001); #endif @@ -2569,7 +2584,8 @@ t200_command: This function processes commands sent to */ void t200_command(unsigned char ir, unsigned char data) { - gpDisp->Command(ir, data); + if (gpDisp != NULL) + gpDisp->Command(ir, data); if (gpDebugMonitor != 0) gpDebugMonitor->Command(ir, data); } @@ -2582,6 +2598,8 @@ t200_readport: This function returns the I/O port data */ unsigned char t200_readport(unsigned char port) { + if (gpDisp == NULL) + return 0; return ((T200_Disp*)gpDisp)->ReadPort(port); } diff --git a/src/genwrap.c b/src/genwrap.c index 52dac46..3db7187 100644 --- a/src/genwrap.c +++ b/src/genwrap.c @@ -43,7 +43,7 @@ #include /* errno */ #include /* toupper/tolower */ -#if defined(__unix__) +#if defined(__unix__) || (defined __APPLE__) #include /* ioctl() */ #include /* uname() */ /* KIOCSOUND */ @@ -329,7 +329,7 @@ char* DLLCALL os_version(char *str) ,winver.dwMajorVersion, winver.dwMinorVersion ,winver.dwBuildNumber,winver.szCSDVersion); -#elif defined(__unix__) +#elif defined(__unix__) || defined(__APPLE__) struct utsname unixver; diff --git a/src/genwrap.h b/src/genwrap.h index d478dea..74cf913 100644 --- a/src/genwrap.h +++ b/src/genwrap.h @@ -123,6 +123,8 @@ extern "C" { #define PLATFORM_DESC "NetBSD" #elif defined(__APPLE__) && defined(__MACH__) && defined(__POWERPC__) #define PLATFORM_DESC "MacOSX" +#elif defined(__APPLE__) + #define PLATFORM_DESC "MacOSX" #elif defined(BSD) #define PLATFORM_DESC "BSD" #elif defined(__solaris__) diff --git a/src/intelhex.c b/src/intelhex.c index 91c5f82..bb53a01 100644 --- a/src/intelhex.c +++ b/src/intelhex.c @@ -193,7 +193,7 @@ void save_hex_file_ext(int begin, int end, int region, FILE* fd) while (count > 0) { // Read next buffer from memory - get_memory8_ext(region, addr, len, buffer); + get_memory8_ext(region, addr, len, (unsigned char*) buffer); // Output all bytes in the buffer for (x = 0; x < len; x++) diff --git a/src/io.c b/src/io.c index 40e12ec..c37026c 100644 --- a/src/io.c +++ b/src/io.c @@ -1014,7 +1014,7 @@ int inport(uchar port) case 0xCE: if (gModel == MODEL_T200) { - ser_read_byte(&ret); + ser_read_byte((char *) &ret); return ret; } case 0xCF: @@ -1034,7 +1034,7 @@ int inport(uchar port) } } else - ser_read_byte(&ret); + ser_read_byte((char *) &ret); return ret; case 0xD0: /* Status control register for UART, modem, and phone (6402) */ diff --git a/src/m100emu.c b/src/m100emu.c index 12cf22c..ec58e96 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -37,7 +37,7 @@ #include #endif -#ifdef __unix__ +#ifdef __unix__ #include #include #endif @@ -114,6 +114,12 @@ char gSingleStep = 0; debug_monitor_callback gpDebugMonitors[3] = { NULL, NULL, NULL }; +/* +============================================================================= +This routine supplies an OS independant high-resolution timer for use with +emulation speed calculations and throttling. +============================================================================= +*/ #ifdef _WIN32 __inline double hirestimer(void) { @@ -138,6 +144,12 @@ __inline double hirestimer(void) } #endif +/* +============================================================================= +This routine "throttles" the emulation speed based on the instruction cycle +count. This is used for 2.4 Mhz emulation speed. +============================================================================= +*/ double last_instruct=0; void throttle(int cy) { @@ -167,12 +179,13 @@ void throttle(int cy) last_instruct = 0; cycles+=cy; cycle_delta=0; -// instructs++; -// if (hires-last_instruct > 1) -// last_instruct = hires; } -/* #define cpu_delay(x) cycles+=x; instructs++ */ +/* +============================================================================= +This routine bails from the app in case of a panic. +============================================================================= +*/ void bail(char *msg) { int endtime; @@ -186,6 +199,11 @@ void bail(char *msg) exit(1); } +/* +============================================================================= +This routine performs a quick "warm" reset with no re-initialization of mem. +============================================================================= +*/ void jump_to_zero(void) { int i; @@ -195,7 +213,6 @@ void jump_to_zero(void) cpu[i] = 0; } - /* ============================================================================= debug_set_monitor_callback: This function adds a new debug monitor process. @@ -364,7 +381,7 @@ void get_rom_path(char* file, int model) strcpy(file, "T200/T200rom.bin"); break; case MODEL_M10: - strcpy(file, "M10/m10rom.bin"); + strcpy(file, "M10/M10rom.bin"); break; case MODEL_PC8201: strcpy(file, "PC8201/PC8201rom.bin"); @@ -388,23 +405,104 @@ check_model_support: This function checks for support for the specified int check_model_support(int model) { char file[256]; - int fd; - + FILE* fd; /* Get the path for the model supplied */ get_rom_path(file, model); /* Attempt to open the ROM file */ - if ((fd = open(file, O_RDONLY)) == -1) + if ((fd = fopen(file, "r")) == NULL) return FALSE; /* Open successful, close the file and return */ - close(fd); + fclose(fd); return TRUE; } +/* +============================================================================= +check_installation: This routine checks that VirtualT is properly installed + with model directories and appropriate rom files. + + If the files are not installed, it attempts to create + them using files in the ROMs directory. +============================================================================= +*/ +void check_installation(void) +{ + int model, len; + char path[256]; + char roms_path[256]; + char errors[256]; + FILE *fd, *fd2; + + errors[0] = 0; + + /* Check each model */ + for (model = MODEL_M100; model < MODEL_PC8300; model++) + { + /* Check if ROM file exists for this model */ + if (check_model_support(model)) + continue; + + /* ROM file doesn't exist. Try to open in ROMs dir */ + get_rom_path(path, model); + sprintf(roms_path, "ROMs%s", strrchr(path, '/')); + if ((fd = fopen(roms_path, "rb")) == NULL) + { + /* Error - ROM file not in ROMs dir */ + if (strlen(errors) != 0) + strcat(errors, ", "); + get_model_string(path, model); + strcat(errors, path); + continue; + } + + /* Create the emulation directory */ + get_emulation_path(path, model); +#ifdef WIN32 + _mkdir(path); +#else + mkdir(path, 0755); +#endif + /* Create ROM in the emulation directory */ + get_rom_path(path, model); + printf("%s\n", path); + fd2 = fopen(path, "wb"); + if (fd2 == NULL) + { + if (strlen(errors) != 0) + strcat(errors, ", "); + get_model_string(path, model); + strcat(errors, path); + fclose(fd); + continue; + } + + /* Copy the ROM file from ROMs dir */ + while (1) + { + /* Read the ROM contents so we can save in Model directory */ + len = fread(gOptROM, 1, 32768, fd); + if (len == 0) + break; + fwrite(gOptROM, 1, len, fd2); + } + + /* Close both files */ + fclose(fd); + fclose(fd2); + } + + if (strlen(errors) > 0) + { + sprintf(path, "No ROM file for %s", errors); + show_error(path); + } +} + void model_8201_bug_workaround(int reason) { - // Remove debugging after + // Remove debugging after we get the to main menu if (PC == 0x6d91) { lock_remote(); @@ -467,6 +565,11 @@ void init_cpu(void) } +/* +======================================================================== +This routine peforms a CPU reset and reinitializes memory. +======================================================================== +*/ void resetcpu(void) { int i; @@ -521,6 +624,11 @@ void cb_int65(void) } +/* +======================================================================== +This routine processes CPU interrupts. +======================================================================== +*/ __inline void check_interrupts(void) { static UINT64 last_rst75=0; @@ -597,6 +705,12 @@ void remote_switch_model(int model) gRemoteSwitchModel = model; } +/* +======================================================================== +This routine performs periodic maintenance operations, such as checking +interrupts and processing FLTK window events. +======================================================================== +*/ void maint(void) { static time_t systime; @@ -608,7 +722,6 @@ void maint(void) hires = hirestimer(); if (hires > last_hires + .05) -// if (systime != (time_t) one_sec_time) { last_hires = hires; one_sec_cycle_count = (DWORD) (cycles - one_sec_cycles) / 100; @@ -653,6 +766,12 @@ void maint(void) } +/* +======================================================================== +This routine checks if there are any active debug monitors and calls +each attached monitor so it can perform it's debug tasks. +======================================================================== +*/ void do_debug_stuff(void) { int i; @@ -774,6 +893,12 @@ void emulate(void) unlock_remote(); } +/* +======================================================================== +handle_sig: This routine handles unix signals and kills the app if there + is a panic. +======================================================================== +*/ #ifdef __unix__ void handle_sig(int sig) { @@ -781,6 +906,11 @@ void handle_sig(int sig) } #endif +/* +======================================================================== +process_args: This routine processes the command-line arguments. +======================================================================== +*/ int process_args(int argc, char **argv) { int i; @@ -826,6 +956,11 @@ int process_args(int argc, char **argv) return 0; } +/* +======================================================================== +This routine sets unix signals and links them to a 'bail' routine. +======================================================================== +*/ void setup_unix_signals(void) { #ifdef __unix__ @@ -836,9 +971,15 @@ void setup_unix_signals(void) #endif } +/* +======================================================================== +This routine sets the working path. On Linus and MacOS platforms, this +is done by looking at the argv[0] argument and removing the app name. +======================================================================== +*/ void setup_working_path(char **argv) { -#ifdef __unix__ +#if defined(__unix__) || defined(__APPLE__) int i; getcwd(path, sizeof(path)); @@ -872,7 +1013,8 @@ int main(int argc, char **argv) { if (process_args(argc, argv)) /* Parse command line args */ return; - + + check_installation(); /* Test if install needs to be performed */ setup_unix_signals(); /* Setup Unix signal handling */ setup_working_path(argv); /* Create a working dir path */ diff --git a/src/memory.c b/src/memory.c index 5f67a6e..294aa2a 100644 --- a/src/memory.c +++ b/src/memory.c @@ -12,8 +12,8 @@ memory.c #include #include -#include #include +#include #include "VirtualT.h" #include "m100emu.h" @@ -992,7 +992,8 @@ load_opt_rom: This function loads option ROMS as specified by user settings. */ void load_sys_rom(void) { - int fd; + FILE* fd; + //int fd; unsigned short address; char oldString[15]; char newString[40]; @@ -1002,8 +1003,9 @@ void load_sys_rom(void) get_rom_path(file, gModel); /* Open the ROM file */ - fd = open(file,O_RDONLY | O_BINARY); - if (fd < 0) + fd = fopen(file, "rb"); + //fd = open(file,O_RDONLY | O_BINARY); + if (fd == NULL) { show_error("Could not open ROM file"); return; @@ -1012,17 +1014,17 @@ void load_sys_rom(void) gRomSize = gModel == MODEL_T200 ? 40960 : 32768; /* Read data from the ROM file */ - if (read(fd, gSysROM, ROMSIZE)sMSCopyright; /* Check if the copyright string is where we expect it to be */ - if (strncmp(&gSysROM[address], oldString, strlen(oldString)) != 0) + if (strncmp((char*) &gSysROM[address], oldString, strlen(oldString)) != 0) { /* Okay, the copyright string has been moved (by the user?) Find it */ address = 0; @@ -1064,7 +1066,7 @@ void load_sys_rom(void) for (c = 0; c < srchLen; c++) { - if (strncmp(&gSysROM[c], oldString, strLen) == 0) + if (strncmp((char*) &gSysROM[c], oldString, strLen) == 0) { address = (unsigned short) c; break; @@ -1074,7 +1076,7 @@ void load_sys_rom(void) /* If the address is good, update the ROM */ if (address != 0) - strcpy(&gSysROM[address], newString); + strcpy((char*) &gSysROM[address], newString); } /* Copy ROM into system memory */ diff --git a/src/multiwin.cpp b/src/multiwin.cpp index cab3c09..75af7a0 100644 --- a/src/multiwin.cpp +++ b/src/multiwin.cpp @@ -74,8 +74,7 @@ Fl_Multi_Window::Fl_Multi_Window(int x, int y, int w, int h, const char* title) m_pClientArea = new Fl_Window(MW_BORDER_WIDTH, MW_TITLE_HEIGHT, w - MW_BORDER_WIDTH*2, h - MW_BORDER_WIDTH - MW_TITLE_HEIGHT); - m_pClientArea->color(FL_WHITE); -// resizable(m_pClientArea); + resizable(m_pClientArea); m_pLabel = new char[strlen(title) + 1]; strcpy(m_pLabel, title); label(m_pLabel); diff --git a/src/multiwin.h b/src/multiwin.h index 09d00c8..cf41afe 100644 --- a/src/multiwin.h +++ b/src/multiwin.h @@ -48,7 +48,8 @@ class Fl_Multi_Window : public Fl_Double_Window, public VTObject Fl_Multi_Window(int x=0, int y=0, int w=600, int h=500, const char *label = 0); ~Fl_Multi_Window(); - Fl_Window* ClientArea() { return m_pClientArea; }; +// Fl_Window* ClientArea() { return m_pClientArea; }; + Fl_Window* ClientArea() { return this; }; int m_NoResize; diff --git a/src/remote.cpp b/src/remote.cpp index bbc00e5..dac65f4 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -598,7 +598,7 @@ std::string cmd_read_reg(ServerSocket& sock, std::string& args) std::string format_str; std::string format_str16; std::string ret=""; - char reg_str[100]; + char reg_str[300]; // Lock the global access object so the registers are stable lock_remote(); @@ -608,10 +608,10 @@ std::string cmd_read_reg(ServerSocket& sock, std::string& args) { if (gRadix == 10) sprintf(reg_str, "A=%d F=%d B=%d C=%d D=%d E=%d H=%d L=%d M=%d PC=%d SP=%d\nOk", - A, F, B, C, D, E, H, L, M, PC, SP); + A, F, B, C, D, E, H, L, get_memory8(HL), PC, SP); else sprintf(reg_str, "A=%02X F=%02X B=%02X C=%02X D=%02X E=%02X H=%02X L=%02X M=%02X PC=%04X SP=%04X\nOk", - A, F, B, C, D, E, H, L, M, PC, SP); + A, F, B, C, D, E, H, L, get_memory8(HL), PC, SP); unlock_remote(); return reg_str; } @@ -678,7 +678,7 @@ std::string cmd_read_reg(ServerSocket& sock, std::string& args) } else if (next_arg == "m") { - sprintf(reg_str, format_str.c_str(), M); + sprintf(reg_str, format_str.c_str(), get_memory8(HL)); ret += reg_str; } else if (next_arg == "bc") @@ -774,7 +774,7 @@ std::string cmd_write_reg(ServerSocket& sock, std::string& args) else if (regStr == "f") F = value; else if (regStr == "m") - M = value; + set_memory8(HL, value); else if (regStr == "bc") { B = value >> 8; @@ -2156,7 +2156,7 @@ std::string process_command(ServerSocket& sock, std::string cmd) ret = cmd_show_reg(sock, L, 1); else if (cmd_word == "m") - ret = cmd_show_reg(sock, M, 1); + ret = cmd_show_reg(sock, get_memory8(HL), 1); else if (cmd_word == "string") ret = cmd_string(sock, args); diff --git a/src/setup.cpp b/src/setup.cpp index 4b58520..d057e46 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -190,11 +190,7 @@ void load_setup_preferences(void) else { strcpy(path,ret); - #ifdef __unix__ strcat(path,"/"); - #else - strcat(path,"\\"); - #endif virtualt_prefs.set("Path",path); // set pref path } } diff --git a/src/socket.cpp b/src/socket.cpp index 4e54724..b7515ab 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -113,8 +113,10 @@ bool Socket::accept ( Socket& new_socket ) const bool Socket::send ( const std::string s ) const { int flags; -#ifdef WIN32 +#if defined(WIN32) flags = 0; +#elif defined(__APPLE__) + flags = SO_NOSIGPIPE; #else flags = MSG_NOSIGNAL; #endif diff --git a/src/sound.c b/src/sound.c index be9683c..57c0279 100644 --- a/src/sound.c +++ b/src/sound.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #ifdef _WIN32 #include @@ -42,7 +42,7 @@ #include #endif -#ifdef __unix__ +#if defined(__unix__) || defined(__APPLE__) #include #include #endif diff --git a/src/vtobj.cpp b/src/vtobj.cpp index a53ae25..ff0ab78 100644 --- a/src/vtobj.cpp +++ b/src/vtobj.cpp @@ -28,7 +28,7 @@ */ #include -#include +#include #include "VirtualT.h" #include "vtobj.h" From cd7d509fa450f2da34a8a83cd901731ff76ecf1c Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 1 Feb 2008 08:29:25 +0000 Subject: [PATCH 065/327] Patched with Y2K Fix. --- ROMs/M102rom.bin | Bin 32768 -> 630 bytes ROMs/PC8201rom.bin | Bin 32768 -> 32768 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/ROMs/M102rom.bin b/ROMs/M102rom.bin index a0b765ee947c894c0ab34480a715dbc533019e61..a776ccfc03969a5984cdee8fb2cde561c352489f 100644 GIT binary patch delta 8 PcmZo@VEV?gp^OOt4{!q| literal 32768 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 diff --git a/ROMs/PC8201rom.bin b/ROMs/PC8201rom.bin index 4b8f17ca958e60217fec0eafca496f8fa45866d0..54744526ccff0bfdc33630cf132b9197943cb305 100644 GIT binary patch delta 19 acmZo@U}|V!+AuMe#YoxAVDr@2Y$X6giUyPb delta 19 acmZo@U}|V!+AuMe#ZcMIa`V*KY$X6gw+5U5 From fa4598504732440d78ad7eb581c812aa62908059 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 1 Feb 2008 08:49:21 +0000 Subject: [PATCH 066/327] Patched with Y2K fix. --- ROMs/M100rom.bin | Bin 32768 -> 630 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/ROMs/M100rom.bin b/ROMs/M100rom.bin index be7873eec8c27a73df33988c06a454f8cf369594..4c2127d2c8ab338013ad9ecc4c6edd1302fafe72 100644 GIT binary patch delta 8 PcmZo@VEV?gp^OOt4{!q| literal 32768 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 From 9fbe7c998508650a71da29f8dcdb7ee33f6bf8f2 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 1 Feb 2008 08:53:44 +0000 Subject: [PATCH 067/327] Added additional feature descriptions for version 1.0 --- release.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/release.txt b/release.txt index d0506e2..cc123ae 100644 --- a/release.txt +++ b/release.txt @@ -46,8 +46,13 @@ v1.0 January 17 2008 12. Transitioned the Windows development environment to Visual Studio 2005. The project files are no longer compatible with Visual Studio 6. -13. Adds a feature to patch the ROM on load to show VirtualT version in the MENU. This can be +13. Added a feature to patch the ROM on load to show VirtualT version in the MENU. This can be disabled in the "Memory Options" menu. + +14. Added auto detection and creation of missing emulation directories. For new installations, + all emulation directories will be created and ROM images copied from the ROMs directory. + +15. Patched all ROM images with Y2K fix. =================== From b98f507a3edf7b973f9cf9249a835d402f033f29 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 1 Feb 2008 09:19:50 +0000 Subject: [PATCH 068/327] Documentation update. --- doc/about_hw.html | 2 +- doc/basics.html | 28 ++++++++- doc/build.html | 137 +++++++++++++++++++++++++++++++++++++++++++++ doc/emulation.html | 2 +- doc/help.html | 22 +++++--- doc/host.html | 2 +- doc/ide.html | 2 +- doc/models.html | 2 +- doc/preface.html | 16 +++--- doc/tools.html | 2 +- 10 files changed, 192 insertions(+), 23 deletions(-) create mode 100644 doc/build.html diff --git a/doc/about_hw.html b/doc/about_hw.html index 5df2017..03d8344 100644 --- a/doc/about_hw.html +++ b/doc/about_hw.html @@ -6,7 +6,7 @@ -

Chapter 7 - About the Hardware

+

Chapter 8 - About the Hardware

This chapter details all aspects of the emulated hardware and explains how VirtualT emulates the original Model T system. diff --git a/doc/basics.html b/doc/basics.html index 7b35a3d..1f92090 100644 --- a/doc/basics.html +++ b/doc/basics.html @@ -6,7 +6,7 @@ -

Chapter 1 - Model T Basics

+

Chapter 2 - Model T Basics

VirtualT is an emulator for the Tandy line of laptop computers, specifically the Model 100, Model 102 and Model 200. The emulator has also been expanded to @@ -19,5 +19,31 @@


+

What is a Model T?

+

In 1983, Tandy Corporation introduced a laptop computer (The Model 100) based on a CMOS +8085 processor running at 2.4 Mhz. Since this was the world's first laptop, the Model 100 user +group likes to call it the "Model T". The laptop has an integrated monochrome LCD display that is 40 +characters by 8 lines, integrated 300 bps modem, serial and parallel ports, cassette interface port, +and 32K RAM. The operating software is ROM based and includes BASIC, a text editor, and telecom, +schedule and address applications. Also included is Menu program that allows the user to browse +files stored in the laptop's RAM. + +

File Storage

+

Files in the Model T are saved in the battery backed RAM using a very simple file system with a +fixed size File Directory Table. On all emulated models except the T200, the directory table is +24 files in size. For the T200, the table is 48 files. The File Directory Table defines the name +of each file using an 8 character filename using a "6.2" format. The File Directory Table also +defines the file attributes and starting memory loacation. +

+Files in memory are organized as contiguous memory objects and files of similar type are grouped +together in memory. If a file size changes, then memory representing other files will be moved +to maintain contiguous memory usage. + +

MENU Program

+

When the Model T is first powered on, it presents a display for interfacing with the Laptop's +ROM based applications and for selecting and using files stored in the the RAM filesystem. + +

+ diff --git a/doc/build.html b/doc/build.html new file mode 100644 index 0000000..aad6e96 --- /dev/null +++ b/doc/build.html @@ -0,0 +1,137 @@ + + + VirtualT Help - Build and Install + + + + + +

Chapter 1 - Build and Install

+ +

This chapter describes the steps necessary to build and install the VirtualT application for +Linux, Windows and MacOS platforms.

+ +
    +
+ +Home + +
+ +

Building VirtualT

+

VirtualT is a freeware, open source software project that is provided under the terms of the +BSD License (see Appendix C). As an open source project, the program +is provided in source code format and can be built and/or modified by the user. + +

To successfully build the application for a given Linux system or MacOSX, +perform the following steps: +

    +
  1. Download the FLTK distribution from the FLTK website. VirtualT +version 1.0 was tested using FLTK release 1.1.7. +
  2. Unpack / unzip the FLTK distribution and 'cd' to that directory. +
  3. Run the FLTK configure script ("./configure"). This will configure the build environment for FLTK based on +your environment and available tools and libraries. +
  4. Build the FLTK libraries by typing "make" while in the FLTK directory. +
  5. On some distributions, the JPEG, PNG and ZLIB libraries are not built when +building the FLTK libraries. These libraries are provided in the FLTK distribution. To build them +manually, 'cd' into each of the FLTK subdirectories below and type "make". +

    +

      +
    • jpeg +
    • png +
    • zlib +
    +

    +

  6. Set the FLTKDIR environment variable. The VirtualT GNUMakefile relies on an environment +variable to specify the location of the active FLTK library. This environment variable must be +set to the root directory of the FLTK distribution to be linked with VirtualT, such as: +

    FLTKDIR=/users/myname/fltk-1.1.7

    +

  7. Check the directory structure for the VirtualT source. The root build directory should have the +following files and subdirectories: +

    +

      +
    • GNUMakefile - The makefile for the Linux make utility +
    • src - Subdirectory of all VirtualT source files +
    • doc - Subdirecotry with all help files and images +
    • ROMs - Subdirectory with ROM images +
    • vt_client - Subdirectory for the vt_client socket application for Windows builds +
    • +
    +
  8. Build VirtualT by changing to the root VirtualT directory and typing "make". +
+ +

For Windows users, a binary distribution is provided, but if you wish to perform your own builds +of intermediate version of VirtualT, the following process should be followed: +

    +
  1. Download the FLTK distribution from the FLTK website. +
  2. Unzip the FLTK source to a directory. +
  3. Open the FLTK Project file using Visual Studio. The Visual Studio projet file is +located in the visualc subdirectory of the FLTK distribution. +
  4. Select Release or Debug build. +
  5. Build the FLTK libraries. +
  6. From within Visual Studio, select and build each of the image libraries: +

    +

      +
    • jpeg +
    • png +
    • zlib +
    +

    +

  7. Set the FLTKDIR environment variable. For Windows XP / 2000, this environment variable is +set by Right-Clicking on "My Computer" and selecting "Preferences". Browse to the "Advanced" +tab and click "Environment Variables". Add the FLTKDIR variable as a new User variable. +
  8. Open the VirtualT Project file using Visual Studio. +
  9. Select Release or Debug build. +
  10. Perform the Build. This should build both the VirtualT application and the vt_client app. +If not, manually select the vt_client project and set it as the "Current" or "Startup" project, +then perform the build. +

    NOTE: With VirtualT 1.0, the Visual Studio 6 project files have not been updated to include
    +the new files.  Instead, Visual Studio 2005 Solution and Project files (.sln, .vcproj) have been
    +provided.  The main reason for the migration is temporary lack of access to Visual Studio 6
    +environment.  A Visual Studio 6 project file will be provided later.
    +
+ +

Installing VirtualT

+

VirtualT uses a very specific directory structure to allow emulation of multiple laptop models +while keeping program data separated (RAM storage files, ROM files, etc.). Version 1.0 and later +releases will automatically create the necessary directory structure using ROM image files located +in the ROMs subdirectory. This directory will be created the first time VirtualT is launched. Below +is the directory structure that will be created: + +

+   main_virtualt_dir
+       |
+       |----virtualt  (application)
+       |----M10       (Emulation directory)
+       |----M100      (Emulation directory)
+       |----M102      (Emulation directory)
+       |----PC8201    (Emulation directory)
+       |----T200      (Emulation directory)
+
+ + +

Launching and Using VirtualT

+

For the most part, VirtualT is a GUI driven application with all features configurable from +within the GUI. The only exception to this is the socket interface used for remote control and +debugging. To enable the socket interface, VirtualT must be envoked with a command-line option +to specify the socket port as follows: + +

    virtualt -p port_number
+

    NOTE:  On Windows platforms, the Windows firewall sometimes blocks unkown ports and may
    +need to be configured.  Sometimes simply envoking VirtualT with the '-p' option a second time
    +will "open" the port.
+ +

This will cause VirtualT to launch a socket listener thread for remote control appliations as +described in Chapter 5. To connect to the socket interface using +the vt_client application, from a command prompt perform the following: +

+
    +
  1. 'cd' to the VirtualT directory +
  2. type './vt_client port_number' +
+

The vt_client application will connect to the socket interface of VirtualT and present a +command-line interface for control. + + + + diff --git a/doc/emulation.html b/doc/emulation.html index bf49106..61c36cc 100644 --- a/doc/emulation.html +++ b/doc/emulation.html @@ -6,7 +6,7 @@ -

Chapter 4 - Emulation Features

+

Chapter 5 - Emulation Features

This chapter describes the emulation features supported by VirtualT. These include things such as display and speed settings, Peripherials, Option ROMs, etc. diff --git a/doc/help.html b/doc/help.html index ec8fe6e..fd5c88f 100644 --- a/doc/help.html +++ b/doc/help.html @@ -11,7 +11,7 @@

Virtual T!

A Model 100/102/200 Emulator

Version 1.0 by Ken Pettit
- Copyright 2004-2008 by Ken Pettit, Jerome Vernet and James Hurd.

+ Copyright 2004-2008 by Ken Pettit, Jerome Vernet, James Hurd and John Hogerhuis.

@@ -26,23 +26,25 @@

A Model 100/102/200 Emulator

- - - - + + + + + - - - - + + + + + - - - - + + + + + - - - + + + + - - - - - + + + + + - - - - + + + + + - - - - + + + + +
Preface -



- 1 - Model T Basics + 1 - Build and Install

- 2 - Emulated Models + 2 - Model T Basics

- 3 - Interfacing with the Host + 3 - Emulated Models +
+
+ 4 - Interfacing with the Host

- 4 - Emulation Features + 5 - Emulation Features
- 5 - Tools + 6 - Tools - 6 - Integrated Development Environment + 7 - Integrated Development Environment - 7 - About the Hardware + 8 - About the Hardware

A - Assembler Reference diff --git a/doc/host.html b/doc/host.html index 3921120..d014ade 100644 --- a/doc/host.html +++ b/doc/host.html @@ -6,7 +6,7 @@ -

Chapter 3 - Interfacing with the Host

+

Chapter 4 - Interfacing with the Host

This chapter describes support for interfacing with the Host OS. Supported features vary between Linux, Windows and MacOS and are detailed here. diff --git a/doc/ide.html b/doc/ide.html index d0f7edb..5d3e8c6 100644 --- a/doc/ide.html +++ b/doc/ide.html @@ -6,7 +6,7 @@ -

Chapter 6 - Integrated Development Environment (IDE)

+

Chapter 7 - Integrated Development Environment (IDE)

This chapter describes VirtualT's Integrated Development Environment (IDE). The IDE provides an enviroment for writing, assembling and debugging assembly language programs directly on the diff --git a/doc/models.html b/doc/models.html index 1461598..d91b5c0 100644 --- a/doc/models.html +++ b/doc/models.html @@ -6,7 +6,7 @@ -

Chapter 2 - Emulated Models

+

Chapter 3 - Emulated Models

This chapter describes the various laptop models that are emulated and a comparison of the features supported by each. diff --git a/doc/preface.html b/doc/preface.html index f6405c1..b45ebe0 100644 --- a/doc/preface.html +++ b/doc/preface.html @@ -30,19 +30,21 @@

Organization

    -
  • Chapter 1 - Model T Basics
  • +
  • Chapter 1 - Build and Install
  • -
  • Chapter 2 - Emulated Models
  • +
  • Chapter 2 - Model T Basics
  • -
  • Chapter 3 - Interfacing with the Host
  • +
  • Chapter 3 - Emulated Models
  • -
  • Chapter 4 - Emulation Features
  • +
  • Chapter 4 - Interfacing with the Host
  • -
  • Chapter 5 - Tools
  • +
  • Chapter 5 - Emulation Features
  • -
  • Chapter 6 - Integrated Development Environment
  • +
  • Chapter 6 - Tools
  • -
  • Chapter 7 - About the Hardware
  • +
  • Chapter 7 - Integrated Development Environment
  • + +
  • Chapter 8 - About the Hardware
  • Appendix A - Assembler Reference
  • diff --git a/doc/tools.html b/doc/tools.html index c5f20a7..8f3e72e 100644 --- a/doc/tools.html +++ b/doc/tools.html @@ -6,7 +6,7 @@ -

    Chapter 5 - Tools

    +

    Chapter 6 - Tools

    This chapter describes additional tools that VirtualT offers beyond the original functinality of the hardware. These tools include things such as a CPU Register From f0d1d7781d4e961633ecdda710f1b7cb865162f9 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 2 Feb 2008 07:11:37 +0000 Subject: [PATCH 069/327] Updated help with some Model T Basics information and images. --- doc/basics.html | 51 ++++++++++++++++++++++++++++++++++++++-------- doc/menu.JPG | Bin 0 -> 17069 bytes doc/model_100.JPG | Bin 0 -> 20796 bytes 3 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 doc/menu.JPG create mode 100644 doc/model_100.JPG diff --git a/doc/basics.html b/doc/basics.html index 1f92090..0c19d24 100644 --- a/doc/basics.html +++ b/doc/basics.html @@ -10,7 +10,9 @@

    VirtualT is an emulator for the Tandy line of laptop computers, specifically the Model 100, Model 102 and Model 200. The emulator has also been expanded to -support the Tandy's close relatives, the NEC PC-8201 and Ollivetti M10 models. +support the Tandy's close relatives, the NEC PC-8201 and Ollivetti M10 models. The +purpose of this help system is primarly for use of the VirtualT, so only a brief +description of the Model T will be provided here.

    @@ -27,23 +29,56 @@

    What is a Model T?

    and 32K RAM. The operating software is ROM based and includes BASIC, a text editor, and telecom, schedule and address applications. Also included is Menu program that allows the user to browse files stored in the laptop's RAM. +

    File Storage

    Files in the Model T are saved in the battery backed RAM using a very simple file system with a -fixed size File Directory Table. On all emulated models except the T200, the directory table is -24 files in size. For the T200, the table is 48 files. The File Directory Table defines the name +fixed size File Directory Table. On all emulated models except the T200, the directory table can +store 24 file names. For the T200, the table is 48 files. The File Directory Table defines the name of each file using an 8 character filename using a "6.2" format. The File Directory Table also -defines the file attributes and starting memory loacation. +defines the file attributes such as defining if the file is a ROM or RAM object, the file type +and the file's starting memory loacation.

    -Files in memory are organized as contiguous memory objects and files of similar type are grouped +Files in memory are organized as contiguous objects and files of similar type are grouped together in memory. If a file size changes, then memory representing other files will be moved -to maintain contiguous memory usage. +to maintain contiguous memory usage. When editing files on the Model T, all changes are made "in place" +to reduce memory requirements. There is also a sort-of "pseudo file" that represents the "unsaved" +BASIC program. This is a special storage location in memory without an associated filename or +File Directory Table entry. It is a "pseudo file" only because it is persisted between successive +calls to BASIC.

    MENU Program

    When the Model T is first powered on, it presents a display for interfacing with the Laptop's -ROM based applications and for selecting and using files stored in the the RAM filesystem. +ROM based applications and for selecting and using files stored in the the RAM filesystem. The MENU +program displays the time and date, and presents a user interface for navigating each of the visible +entries in the File Directory Table. +

    -

    +

    BASIC Program

    +

    The BASIC Program provides powerful, feature rich programming capability to the Model T. The +BASIC implementation is a line number based interpreter with keyword tokenization at entry time. +The tokenization saves memory and inreases program execution speed. The language provides full +support for different variable precision, text and graphic output to the LCD, file access to RAM, +serial and cassette files, string manipulation, etc. + +

    TEXT Program

    +

    The TEXT program is a document editing application for writing / editing text documents. It +provides basic word processing features for seleting, copying and pasting text. + +

    TELCOM Program

    +

    The TELCOM Program provides terminal support for the built-in modem and for the serial port. + +

    ADDRSS Program

    +

    The ADDRSS Program is a basic address storage utility for saving address and phone number +information. This program uses TEXT in conjunction with a specially named file, "ADDRSS.DO" to +provide this functionality. The ADDRSS.DO file does not exist as a default and must be created +using TEXT prior to using the ADDRSS program. + +

    SCHEDL Program

    +

    The SCHEDL Program is a basic schedule management utility for keeping track of schedule items. +Like ADDRSS, this program also uses TEXT in conjunction with a specially named file, "SCHEDL.DO" to +provide this functionality. The SCHEDL.DO file does not exist as a default and must be created +using TEXT prior to using the SCHEDL program. diff --git a/doc/menu.JPG b/doc/menu.JPG new file mode 100644 index 0000000000000000000000000000000000000000..ae5f42460038c7a4b11e8cf4a1c8a924570cbe02 GIT binary patch literal 17069 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 literal 0 HcmV?d00001 From 730d846031ec2069b54db1046213c23ac1ed2c7e Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 3 Feb 2008 03:40:27 +0000 Subject: [PATCH 070/327] Documentation update - Interfacing with the Host and reorg of Socket Interface. --- doc/about_hw.html | 2 +- doc/help.html | 43 ++++++++++++++++------------ doc/host.html | 71 ++++++++++++++++++++++++++++++++++++++++++++--- doc/ide.html | 2 +- doc/preface.html | 8 ++++-- doc/sockets.html | 23 +++++++++++++++ doc/tools.html | 2 +- 7 files changed, 123 insertions(+), 28 deletions(-) create mode 100644 doc/sockets.html diff --git a/doc/about_hw.html b/doc/about_hw.html index 03d8344..04dbdef 100644 --- a/doc/about_hw.html +++ b/doc/about_hw.html @@ -6,7 +6,7 @@ -

    Chapter 8 - About the Hardware

    +

    Chapter 9 - About the Hardware

    This chapter details all aspects of the emulated hardware and explains how VirtualT emulates the original Model T system. diff --git a/doc/help.html b/doc/help.html index fd5c88f..433e524 100644 --- a/doc/help.html +++ b/doc/help.html @@ -40,40 +40,47 @@

    A Model 100/102/200 Emulator

    4 - Interfacing with the Host 5 - Emulation Features + 6 - Socket Interface +
- 6 - Tools + 7 - Tools - 7 - Integrated Development Environment + 8 - Integrated Development Environment - 8 - About the Hardware + 9 - About the Hardware

A - Assembler Reference diff --git a/doc/host.html b/doc/host.html index d014ade..8ec22cc 100644 --- a/doc/host.html +++ b/doc/host.html @@ -18,13 +18,76 @@
-

Directory Structure

+

Directory Structure

+

VirtualT uses a very specific directory structure to allow emulation of multiple laptop models +while keeping program data separated (RAM storage files, ROM files, etc.). Version 1.0 and later +releases will automatically create the necessary directory structure using ROM image files located +in the ROMs subdirectory. Below is the directory structure that will be created. The src and +vt_client directories will be present only if the source code was downloaded and unzipped. -

Loading / Saving RAM

+

Each of the emulation directories (M10, M100, T200, etc.) will contain machine specific files +such as ROM images and RAM files for base memory and/or ReMem memory. Additionally they provide +a structure for keeping Model T files (.BA, .CO, etc.) separated when they are targeted for as +specific model. While the IDE is not completed yet, it assumes a default project storage directory +under the main VirtualT directory called "Projects". +

+   main_virtualt_dir
+       |
+       |----virtualt  (application)  (virtualt.exe for windows)
+       |----doc       (Help Files directory)
+       |----src       (Source Code directory)
+       |----M10       (Emulation directory)
+       |----M100      (Emulation directory)
+       |----M102      (Emulation directory)
+       |----PC8201    (Emulation directory)
+       |----T200      (Emulation directory)
+       |----vt_client (Build directory for vt_client app)
+       |----Projects  (IDE Projects directory)
+
-

RAM Snapshots

+

RAM Files

+

VirtualT saves the emulation RAM into a file within active Emulation Directory. File loading is +done when the program starts and is saved just prior to The file +that is used is dependant on the selected memory configuration (see Memory Setup. +For Base Memory configurations, the RAM is saved in a file named RAM.bin. The file is a binary +copy of the emulation RAM. On models that contain multiple RAM banks such as the T200, each RAM +bank is stored to the file in sequence followed by a single byte representing the active RAM bank. +

+For ReMem meory configuration, the RAM and FLASH contents are saved in a file named remem.bin. This +file contains three 2M binary sections. The first section is the 2M RAM chip contents, the second +section is the FLASH1 chip contents, and the third section is the FLASH2 chip contents. -

Loading / Saving Files

+

Loading / Saving Files

+

Model T files (.BA, .DO, etc.) can be loaded from and saved to the Host Operating System using +the "Load from Host" and "Save to Host" menu items in the File menu. When performing load and save +operations, VirtualT manually reads and writes to system RAM during emulation. The reads / writes +include accessing the File Directory Table, the file storage areas, and system pointers and variables +used for memory management and housekeeping. For this reason, files should be loaded and saved only +when there is no file activity in the emulation. After a Load from Host operation, Virtualt performs +a warm reset of the emulation to force a redraw of the Menu screen. This warm reset will occur +regardless of the current emualtion state (running BASIC, TEXT, etc.). +

+During load operations, VirtualT will automatically determine if the file being loaded is too +large for available memory, determine the type of file being loaded base on file extension, +tokenize ASCII BASIC files, and determine the appropriate location in memory to store the file. +Currently any file extension other than .BA, .DO or .CO are converted into .DO files and loaded +as TEXT documents. This functionality needs to be changed in future releases to detect 2 character +extensions and load them with no conversion. + +

Preferences

+Preferences for VirtualT settings, such as CPU emulation speed, Display size, etc., are saved to +the host when VirtualT is terminated and restored when it is launched again. The preferences are +saved by the FLKT library routines and the storage method are OS dependant. The following are the +locations of the VirtualT preferences files for each OS: + +

+     Linux   -  $HOME/.fltk/virtualt./virtualt.prefs
+     MacOS   -  $HOME/Library/Preferences/virtualt./virtualt.prefs
+     Windows -  C:/Documents and Settings/UserName/Application Data/virtualt/virtualt.prefs
+
+ +

VirtualT saves general settings such as display characteristics on a global basis and emulation +preferences such as memory configuration and ROM / RAM filenames on a per model basis. diff --git a/doc/ide.html b/doc/ide.html index 5d3e8c6..340e250 100644 --- a/doc/ide.html +++ b/doc/ide.html @@ -6,7 +6,7 @@ -

Chapter 7 - Integrated Development Environment (IDE)

+

Chapter 8 - Integrated Development Environment (IDE)

This chapter describes VirtualT's Integrated Development Environment (IDE). The IDE provides an enviroment for writing, assembling and debugging assembly language programs directly on the diff --git a/doc/preface.html b/doc/preface.html index b45ebe0..a1460c5 100644 --- a/doc/preface.html +++ b/doc/preface.html @@ -40,11 +40,13 @@

Organization

  • Chapter 5 - Emulation Features
  • -
  • Chapter 6 - Tools
  • +
  • Chapter 6 - Socket Interface
  • -
  • Chapter 7 - Integrated Development Environment
  • +
  • Chapter 7 - Tools
  • -
  • Chapter 8 - About the Hardware
  • +
  • Chapter 8 - Integrated Development Environment
  • + +
  • Chapter 9 - About the Hardware
  • Appendix A - Assembler Reference
  • diff --git a/doc/sockets.html b/doc/sockets.html new file mode 100644 index 0000000..de4dc82 --- /dev/null +++ b/doc/sockets.html @@ -0,0 +1,23 @@ + + + VirtualT Help - Socket Interface + + + + + +

    Chapter 6 - Socket Interface

    + +

    This chapter describes the socket interface supported by VirtualT. The Socekt +Interface provides the capability of remote control of most of VirtualT's emulation +functionality. The interface also adds low-level debug control of the emulation. + +

      +
    + +Home + +
    + + + diff --git a/doc/tools.html b/doc/tools.html index 8f3e72e..0753ab2 100644 --- a/doc/tools.html +++ b/doc/tools.html @@ -6,7 +6,7 @@ -

    Chapter 6 - Tools

    +

    Chapter 7 - Tools

    This chapter describes additional tools that VirtualT offers beyond the original functinality of the hardware. These tools include things such as a CPU Register From 014b44fffdfe4292336973baba35a32126ea3aee Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 3 Feb 2008 05:58:36 +0000 Subject: [PATCH 071/327] Documentation updates for Emulated Models. --- doc/check.gif | Bin 0 -> 971 bytes doc/menu.JPG | Bin 17069 -> 0 bytes doc/model_100.JPG | Bin 20796 -> 0 bytes doc/models.html | 66 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 doc/check.gif delete mode 100644 doc/menu.JPG delete mode 100644 doc/model_100.JPG diff --git a/doc/check.gif b/doc/check.gif new file mode 100644 index 0000000000000000000000000000000000000000..114e5dfb25f64551069913672f5d1d8bf49d7cbc GIT binary patch literal 971 zcmb_b!Aq2J5S>6t57CN=2vQbSW)UqzsT2k!?k15*mK2L2*}!%QJP3MesZOFGDZiINzJN3SxekSeK> zdW;&A37L`^SuiDMav@i81ML6~XkcL&-5z@)gjt!5*<&p-5f)`J77rFEs<0}nv3ig~ zuL+y78JmM6M%jg3*^M1r!5Uy74VIvV8WsZ^(7?j5hoHz2Dq`A>MRik$k8m0WfEU_fG}OXM_yL-jh8^Gp!B7a+00U`Ef);pSF|YycaiZu( z89BmnF&GJbSc}ZkOBTMSdq**yFlQRM~*$&_oeR6r|E`{@ug1w@$tc-+r5{69^L%#^mO&_)~&J8{`1F2 zUT;s-uM8}7TzfHkFZ;4G?~Av#^RseesU+m&B^&rWWgS^k>6|820idvDLb@l*Y)Q`NcQrVO3^51VnMxBvhE literal 0 HcmV?d00001 diff --git a/doc/menu.JPG b/doc/menu.JPG deleted file mode 100644 index ae5f42460038c7a4b11e8cf4a1c8a924570cbe02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17069 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 diff --git a/doc/models.html b/doc/models.html index d91b5c0..35eb5ad 100644 --- a/doc/models.html +++ b/doc/models.html @@ -18,5 +18,71 @@


    +

    Model Comparison

    +

    The table below details the laptop models that VirutalT emulates and describes any +emulation differences between them. It also describes specific model features, filenames, etc. + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Model 100Model 102Model 200NEC PC-8201Olivetti M10
    Emulation Dir + M100M102T200PC8201M10
    ROM File + M100ROM.binM102ROM.binT200ROM.binPC8201ROM.binM10ROM.bin
    RAM File Size + 32K32K72K96K32K
    ReMem Support + Limited testingNot testedNot tested
    File Load/Save + No BASIC Tokenizer
    Serial Support +
    LCD + 240 x 64240 x 64240 x 128
    Char generator
    not supported
    240 x 64240 x 64
    + From f50f279309172f161ebda218013bf4da188d794f Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 3 Feb 2008 06:00:32 +0000 Subject: [PATCH 072/327] Added images back with lower case extension for Linux. --- doc/menu.jpg | Bin 0 -> 17069 bytes doc/model_100.jpg | Bin 0 -> 20796 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/menu.jpg create mode 100644 doc/model_100.jpg diff --git a/doc/menu.jpg b/doc/menu.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ae5f42460038c7a4b11e8cf4a1c8a924570cbe02 GIT binary patch literal 17069 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 literal 0 HcmV?d00001 From c405227529efea959489b5e4cec2e39e23c6f913 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 3 Feb 2008 06:41:54 +0000 Subject: [PATCH 073/327] Updated comparison table. --- doc/models.html | 70 ++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/doc/models.html b/doc/models.html index 35eb5ad..25317b5 100644 --- a/doc/models.html +++ b/doc/models.html @@ -28,59 +28,59 @@

    Model Comparison

    Emulation Dir - M100M102T200PC8201M10M100M102T200PC8201M10
    ROM File - M100ROM.binM102ROM.binT200ROM.binPC8201ROM.binM10ROM.binM100ROM.binM102ROM.binT200ROM.binPC8201ROM.binM10ROM.bin
    RAM File Size - 32K32K72K96K32K32K32K72K96K32K
    ReMem Support - Limited testingNot testedYYLimited testingNot tested Not tested
    File Load/Save - No BASIC TokenizerFile Load/Save + YYYNo BASIC TokenizerY
    Serial Support - YYYYY
    LCD - 240 x 64240 x 64240 x 128
    Char generator
    not supported
    240 x 64240 x 64240 x 64240 x 64240 x 128

    Char generator not supported

    240 x 64240 x 64
    From ee552142a63248eedba717d42f55264f41386782 Mon Sep 17 00:00:00 2001 From: "John R. Hogerhuis" Date: Sun, 3 Feb 2008 22:41:55 +0000 Subject: [PATCH 074/327] Repaired broken build under Linux by moving vt_client directory to vt_client_src and updating the GNUmakefile. The problem was that it was attempting to build the executable as "vt_client" in the main VirtualT directory, but that conflicted with the source directory name for vt_client. --- GNUmakefile | 4 +- vt_client_src/stdafx.cpp | 8 ++ vt_client_src/stdafx.h | 15 +++ vt_client_src/vt_client.cpp | 11 ++ vt_client_src/vt_client.vcproj | 236 +++++++++++++++++++++++++++++++++ 5 files changed, 272 insertions(+), 2 deletions(-) create mode 100644 vt_client_src/stdafx.cpp create mode 100644 vt_client_src/stdafx.h create mode 100644 vt_client_src/vt_client.cpp create mode 100644 vt_client_src/vt_client.vcproj diff --git a/GNUmakefile b/GNUmakefile index 1df19de..7a54b81 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -19,7 +19,7 @@ CLIENT = vt_client FLTKCONFIG = $(FLTKDIR)/fltk-config FLTKLIB = $(FLTKDIR)/lib/libfltk.a -VPATH = src:obj +VPATH = src:vt_client_src:obj LDFLAGS += -g -L/usr/X11R6/lib -L$(FLTKDIR)/lib LIBFILES = -lstdc++ -lfltk_images -lfltk_jpeg -lfltk_png -lfltk_z -lfltk -lm -lc -lX11 -lpthread @@ -79,7 +79,7 @@ else endif # ======================== -# Rule to build vt_client +# Rule to link vt_client # ======================== $(CLIENT): $(CLIENT_OBJS) ifndef FLTKDIR diff --git a/vt_client_src/stdafx.cpp b/vt_client_src/stdafx.cpp new file mode 100644 index 0000000..3c1362b --- /dev/null +++ b/vt_client_src/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// vt_client.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/vt_client_src/stdafx.h b/vt_client_src/stdafx.h new file mode 100644 index 0000000..ddacb46 --- /dev/null +++ b/vt_client_src/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/vt_client_src/vt_client.cpp b/vt_client_src/vt_client.cpp new file mode 100644 index 0000000..de30fd6 --- /dev/null +++ b/vt_client_src/vt_client.cpp @@ -0,0 +1,11 @@ +// vt_client.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" + + +int _tmain(int argc, _TCHAR* argv[]) +{ + return 0; +} + diff --git a/vt_client_src/vt_client.vcproj b/vt_client_src/vt_client.vcproj new file mode 100644 index 0000000..f3606e0 --- /dev/null +++ b/vt_client_src/vt_client.vcproj @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From d7bcdb35cdedeb9b4eb8b2a8273f2e31fd15b098 Mon Sep 17 00:00:00 2001 From: "John R. Hogerhuis" Date: Sun, 3 Feb 2008 22:44:11 +0000 Subject: [PATCH 075/327] Removing old vt_client directory since moved it to vt_client_src --- vt_client/stdafx.cpp | 8 -- vt_client/stdafx.h | 15 --- vt_client/vt_client.cpp | 11 -- vt_client/vt_client.vcproj | 236 ------------------------------------- 4 files changed, 270 deletions(-) delete mode 100644 vt_client/stdafx.cpp delete mode 100644 vt_client/stdafx.h delete mode 100644 vt_client/vt_client.cpp delete mode 100644 vt_client/vt_client.vcproj diff --git a/vt_client/stdafx.cpp b/vt_client/stdafx.cpp deleted file mode 100644 index 3c1362b..0000000 --- a/vt_client/stdafx.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// vt_client.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file diff --git a/vt_client/stdafx.h b/vt_client/stdafx.h deleted file mode 100644 index ddacb46..0000000 --- a/vt_client/stdafx.h +++ /dev/null @@ -1,15 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#pragma once - - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -#include -#include - - - -// TODO: reference additional headers your program requires here diff --git a/vt_client/vt_client.cpp b/vt_client/vt_client.cpp deleted file mode 100644 index de30fd6..0000000 --- a/vt_client/vt_client.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// vt_client.cpp : Defines the entry point for the console application. -// - -#include "stdafx.h" - - -int _tmain(int argc, _TCHAR* argv[]) -{ - return 0; -} - diff --git a/vt_client/vt_client.vcproj b/vt_client/vt_client.vcproj deleted file mode 100644 index f3606e0..0000000 --- a/vt_client/vt_client.vcproj +++ /dev/null @@ -1,236 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 2e6dcc1b25cacc8be3ef4338119ff341dd6b6533 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Mon, 4 Feb 2008 07:34:13 +0000 Subject: [PATCH 076/327] Documentation update - added "Emulation Features" stuff. --- doc/emulation.html | 119 +++++++++++++++++++++++++++++++++++++++++++ doc/help.html | 2 +- doc/memory_setup.jpg | Bin 0 -> 20463 bytes doc/periph_setup.jpg | Bin 0 -> 15862 bytes 4 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 doc/memory_setup.jpg create mode 100644 doc/periph_setup.jpg diff --git a/doc/emulation.html b/doc/emulation.html index 61c36cc..10fd9c3 100644 --- a/doc/emulation.html +++ b/doc/emulation.html @@ -18,5 +18,124 @@
    +

    Display

    +

    VirtualT emulates the Model T LCD display at the hardware level, like it does all other devices. +Because of this, all software written for the Model T will also work on VirtualT, even if they make +direct access to the LCD hardware. +

    The LCD hardware implementation varies depending on the emulation model. For the T200, the LCD +uses a single single controller with 8K display RAM. On the other models, the LCD consists of 10 +independant controllers, each responsibile for a specific region of the display. With the exception +of the T200 control chip's character generator ROM, the VirtualT emulation exactly matches the +hardware at a register (I/O operation) level. +

    Several features provided by the LCD emulation and can be accessed using the "Emulation->Display" +menu items. These features are: +

      +
    • Display Size: Allows magnification of the LCD (1x, 2x, 3x and 4x). This is direct pixel copying +of each pixel on the LCD. +
    • Solid Chars: Allows characters to be display with or without "spacing" between pixels. On the real +Model T, the old LCD techonology was coarse enough to see the spacing. This allows the user to +choose between a "retro" look or a more readable look. +
    • Framed: This feature allows the user to view the LCD with the familiar "black frame" as seen on the +original Model T, complete with function key labels, or as a simple window. +
    + +

    Keyboard

    +

    The Model T keyboard, while very easy to use, has a non-standard of special and punctuation compared +with modern day keyboards. The keyboard is a simple scan matrix of keys with 8 scan rows and 9 scan +columns. Each model uses the same keyscan arragement, but each assigns the key mappings differently. +Plus the Model T has a few extra keys that are not present on today's keyboards, such as CODE and GRPH. + +

    Because of these differences, VirtualT must perform keyboard translation based on the emulated Model. +Additionally, several keys of the standard 101-key keyboard are "mapped" to represent the extra keys +present on the Model T. The mapping of these keys is as follows: +

    +

    +   F9        - Label Key
    +   F10       - Print Key
    +   F11       - Paste Key
    +   F12       - Pause Key
    +   Left Alt  - GRAPH
    +   Right Alt - CODE
    +
    + +

    There are no user controls for controlling the operation of the keyboard emulation. + +

    Speed

    +

    Emulation speed can be controlled using the "Emulation->Speed" menu item. Emulation speed is calculated +by analyzing the number of CPU cycles that have occurred over a given time interval. A high-resolution timer +is used to measure time in milliseconds for accurate measurement. Even using a high-resolution timer, the +speed estimates calculated are still approximate. For emulation speeds less than full speed, VirtualT slows +the emulation by performing an FLTK wait operation, effectively giving control back to the OS and putting the +application to "sleep". There are four options for emulation speed accessible in the "Emulation->Speed" menu: +

    +

    +   2.4 Mhz           - Forces emulation to match origial Model T speed
    +   Very CPU Friendly - Moderate emulation speed - consumes fewer Host CPU cycles 
    +   CPU Friendly      - Faster emulation speed - cosumes more Host CPU cycles
    +   Max Speed         - Provides the fastest emulation
    +
    + +

    Option ROMs

    +

    The Model T laptops use a system ROM to store the operating system and built-in applications. In addition +to the built in Operating System ROM (OpSys ROM), the laptops have a socket for adding an additional "Option ROM" +in a covered compartment on the bottom of the unit. Various option ROMs were developed for the Model T and are +still available today at varous on-line stores / auctions. +

    VirtualT provides emulation of the Option ROM functinality via menu items on the "Emulation->Option ROM" menu. +The sub-menu title will display the currently loaded Option ROM, if any, and the "Load ROM" and "Unload ROM" items +can be used to control which "ROM" is loaded. A single ROM can be "loaded" at any given time by choosing the +"Load ROM" menu item and selecting the ROM image file from the browser dialog box. The ROM image files can be either +binary or Intel-Hex formatted files. The selected ROM image file will be saved with other Preferences and will +be associated with the current emulation model. + +

    Memory Setup

    +

    Each Model T was shipped with base memory and an option to install additional memory base on the model. +The Model 100 was upgradeable in 8K increments up to 32K while the Model 200 was upgradeable in 24K increments +up to 72K. Additional memory expansion products were developed as add-on modules to increase available memory. +Most of these products were designed to connect to the system bus in the expansion compartment on the bottom of +the laptop and provided 128K or 256K of expansion. The newest expansion module called "ReMem" was developed +by Steven Adolph in the 2006 / 2007 timeframe. This device boosts the memory capability of the Model T to +2Meg RAM plus 4Meg FLASH, plus provides legacy interface protocol for the Rampac expansion module. + +

    The default memory emulation in VirutalT matches that of a factory standard unit with maximum RAM expansion. +he selected model. Additional memory emulation configurations can be selected using the +"Emulation->Memory Configuration" menu. This menu item will display the Memory Configuration dialog box +shown below. +

    + +

    The details of each option are: +

      +
    • Base Memory - Emulates the maximum "Factory Shipped" memory configuration. +
    • Rampac - Emulates Base Memory plus a 256K RAM Rampac expansion module. +
    • ReMem - Emulates a ReMem expansion module. Rampac accesses can be "emulated" by the ReMem +and will show up in the ReMem memory space and RAM file. +
    • ReMem + RamPac - Emulates a ReMem expansion module and a Rampac. Rampac accesses are directed +to the Rampac memory space and saved in the Rampac RAM file. +

    • Make option ROM R/W - Useful for ReMem emulation. Allows writes to the OptionROM space. +
    • Patch ROM onload (...) - Enables / disables automatic patching to display version on MENU screen. +
    + +

    Peripheral Setup

    +

    The Peripheral Setup dialog box is accessed via the "Emulation->Peripheral Setup" menu item and allows +configuration of peripheral emulation options. Currenlty the only peripheral that is supported is the +serial port. The Peripheral Setup dialog is displayed below. It has a separate configuration tab for each +of of the peripherals on the Model T, although most of them are simply placeholders for future functionality. + +

    + +

    COM port setup tab

    +

    This tab provides configuration options for emulation of the Model T serial port. The controls on this tab +provide the follwoing functionality: +

      +
    • No emulation - No serial port emulation provided. +
    • Use Simulated Port - Not supported. The idea is to provide a scriptable way to emulate something +connected to a serial port with action / response capabilities. +
    • Use Host Port - Provides a list of know host ports to "connect" to the Model T's serial port. +
    • Use Other Host Port - Allows the user to type a device name to "connect" to the Model T's serial port. +
    +

    All serial port traffic and configuration updates are trapped by VirtualT and translated into the +appropriate OS system calls to affect the desired response on a "real-world" serial device. Serial I/O and +configuration data can be monitored in the Peripherial Devices dialog. + +

    diff --git a/doc/help.html b/doc/help.html index 433e524..3f059fe 100644 --- a/doc/help.html +++ b/doc/help.html @@ -67,7 +67,7 @@

    A Model 100/102/200 Emulator

    • CPU Registers
    • Memory Editor
    • -
    • Peripheral Monitoring
    • +
    • Peripheral Devices
    • Integrated Development Environment
    • Dissassembler
    • ReMem Configuration
    • diff --git a/doc/memory_setup.jpg b/doc/memory_setup.jpg new file mode 100644 index 0000000000000000000000000000000000000000..05e75eacf9dfc705b3093279b99cbf1799147aa0 GIT binary patch literal 20463 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 MnAN)l{QqwP0PvgwC;$Ke literal 0 HcmV?d00001 diff --git a/doc/periph_setup.jpg b/doc/periph_setup.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8fe2e00c9bc71a3a587f7f03cfe014ee0c2bec8d GIT binary patch literal 15862 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 Date: Mon, 4 Feb 2008 07:52:50 +0000 Subject: [PATCH 077/327] Updates to reflect change in vt_client soruce directory. --- VirtualT.sln | 2 +- VirtualT.suo | Bin 72704 -> 74240 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/VirtualT.sln b/VirtualT.sln index 3c1f19f..11be2c5 100644 --- a/VirtualT.sln +++ b/VirtualT.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VirtualT", "VirtualT.vcproj", "{823B96D9-CEF2-4B9D-8B90-A6F0DEC5B97A}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vt_client", "vt_client\vt_client.vcproj", "{2EE29331-FFC1-46AF-96AB-AA0643DF918E}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vt_client", "vt_client_src\vt_client.vcproj", "{2EE29331-FFC1-46AF-96AB-AA0643DF918E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/VirtualT.suo b/VirtualT.suo index ae9f473b1a686305991aca4d293b9fad6b114e38..7969d92cb4812f3973701c19291bf1c6ca126155 100644 GIT binary patch delta 3699 zcmbtX4Nz3q8NGM+?Jj@f0?UsexJD8Y41#V!Py#4PK&hY*sm@N6@Fxu}6c?HR&2F4T zrg{Zm8J8EM45 z!J~SYwnCa0fLjIa_;WfHSv49ny{K_B{dx0zgS6=Hgm|Rc0FT-4F>%v9^my2N78wFM zEzr^(UO}g{Y#I%(G+Q8t`eof6Vbf+GK$BOv8RBfOBYODGwMi+3VEt7figsG#^+D@X zl1k#T47&w&Mz1o5!5tCkWi;B(6>p*^y9?w7x_u*w_7_-nukDny2$VV*rHY8FG~3Wj z^Iw|dLC*+%JnjL51;cUBf`VkOgbsGkp#D(@RsJ z>g6cyBy8l&Db;?(i??gcptyapTtUI&f?eL%l{(78nRKfK#i zR=PajS<+h9vAMzJ-eRwH)!VBY-0o&q(-voO{pMzuv$(CTrMa%w-Q4Q3m(;pzot@3? z?vC0P_m?EIt-Yaf3nkZYpwo3Fy0^Z_D0lhZ3YUe4HkoHTMKPADO|*z+Q73A#)Xkz* zxP)Dl_^)c|z*ua0C)9S_>wwmRoQW3gqCqtJUy+-ae#bAhe_m*#%T6Knchl~=Ec)0r z-?tTONRQrpNcXlHtWlrgCFQB&x8)*pimjOy$ydc1J`f&FAN2IZ2DWO^p0|x2R%-xm zw-opmz_9^f?LJ^5z|jD(#?c61HpQa=Ys{|#JkSk*wN*e1z%dQNRNF`p_Qyzc&mv#! z1>wdoAx~*9gJeQ`MQL~@(GQ-Etg}Xaqbv2WeUDA|@K`oT9G@yX^9$hI{bx#x0l%nx zIk>?z7RY52qEczhSA(;>R%tW9Ygj-uDvf!QL3sSe79}P^+^mcpLB>vSmb;b4#q_X% z*rqh*+rjxfd{${Z@N>%da**#Q%GYZM4?GDEe3V}DCV9>(8$aJP%o|T#6h8Qxhdrmd zi&q*XkpRxa@?pn59ySG>V`Y$5uCywp@%?IWZo4j^B?&HNy)wFjjIBm0>h(?+dDsIB z#rNRKUbx6X({Eg5ZjGKA3dPyR^>?d&x!Cu? zdAN_1=AT;@5Eqoj{14y;ee$fFNo$64=y*}IOs0Z)P0~V_#&dDBAEP&~eY^jv*WlY4 zAu~O^6KipfWnu?oYT9b%axXmMRPeT053m*r@Ydnz0$8&Ghk^TnUjkFw`{46|50n;x z{3#FzT$s{$gN^~SfXOKlIUc>NKu$#F4rc=SAQ{L@m1YMo1D}JuR%vPAb>KP3^-ALc z-OAUYG)UqJ@G3q&o>n6Ni~2rz67sW3&S;2WO5|qYsF%O*QB3)@b7kSE;uQXm%FTha-4X>qPQqYql zg|y3Vr?#;Kx;)|_``AqK9^Ob_jFpFb#d47^oT5^+`&LKD3Q8$Vkx9PSHMx?!cdg~B z$aAtnpxyIoj?H}O$eQ6>{3pWRR(~)^r zx$PQoJ94!dCpnA!BsCCuv#(P|)|$ZiwQ5!x7x*zc=lH$Sn12G!9sf~j+~!Z<9LYE* zc?^yeaQ4kn+C3Owq~d~OS&(tLGL|Zh-{Ugns|xZ}E8jY$&4q70I7cfopQ+5hb_Th~ zVbfw=-pP>UxMh=Fcqdv-p!E|8^vvx}8XS%w$GN*q{6+o= zx;`>DXrz=k%<_yhtnwc&1EUrhVUS-wpW~~x@18-q4c(UqzRDHP`X9c<&HC@(;&OTG z=aT(a#IDCRdhgmfU%w_xzw#)Mp>*#R&wosGk72J(mKsU|PvN%7^Y|HaKOXm+e#PgG zllZk!4q>$t;$=nP=SQV_@_0Nst@+Vnx;Rq(|E?PKbVbm`am~L9L*rk&BGN{E6WghM UVi^s-R_!ZKl%Gp4-l)8P0Vb*RP5=M^ delta 2640 zcmbtVZBUd|6uxKo-DN>QSU1F#a8VTeNDxUS0arytQ(4TRW+Y}!N^KOZko;`diK!-Q zQjYqTIg^!5pHt%7q~#a+QK^+_HPh6uoOFsTt+q+2+@7<0$^F&Tbl~iL-se8|+;h)) z_ip&85#DR;`of-kH5!eINBL`ee^*E;wI1GKEKLt=IJeCk{DACu4!>fpHfEC34eU|8 z@!SaZXBd3hvEA4V%6if{%0^D>m@7oCQV_9#8;c4ZvbdaArJP7oNq{NwwXJ<>lgPlc zEB+km6L89sfNwwG{Y1Yn|sk;;HU2 z+?o~7%NEPa*&nOkBC98>+Ex&caEoeDE3kSY)+I!c$(RMP?*MZ!QK`8rkJ354*kvr* zn)eZJEcEc%0e3hvAj^zLe*o~Rn^$}1*s^t5yr=kxF~%_rGwpn3;HFS2(0yCA&7baKqut;bITMg&P8Ihl@P}7j6=K2V877TsSc+KByBIrMgOW0yRjnMIu|? zuB@!4lVZ`pdD!Ws-fx3VB-((u{QgOq$nmBlAT)F2RDE7hk!w+9ybMf{hC{RZK(BfRJ=vqjS#(dtqa^$ zQJwZ%P2(Rj6-%9;{e1|BzfXDIUzwY>$%dC3&hV?77L4U^Lt$srZM3^_vx8q~F6Q#4 zDh@Xf?~~RI?f# zOHs=I_@SfmR#)eEaw|bd@#Omc?9B^7Q z@=~0Ei+zF^#Gf{g4yp43L4Bu3neGObU_WY3a6f$9h|z;l^rPSx1;7e4C%6z8|7ui% z?gk-X8!*O747@hRS>YC222ZJ|w7NoTuQMbW%fIEYJ)|S6b@GV{m)VyxkYVHk22aKOb5-%^aLgA9HwceJt7(+#WaKY6-|C$I**bNmPsA zb+JvIdjR(muf8-xei@tx@i>9F&NY*d{#4FESCx!tb1om4Kbdp>ywq`Mn>`!*go@{L z@oIzpvmc-w?(81Vd-VTiP+v%NbYFlNYMB_*@CGK&V1CM zYz{wBNqu>J&pq6H#_h<&!ntOhLGROeYyIVs^zU+bh`Ux+N!i<6f8xz)M-3P5=foJZ uHH%Iqso5X`n&?lp@}BL9^v97*TN;&^Cw%k=`-eC2u5Ls6*~qz*QvU)IG-A&H From e4c1f3988d045c14c91f7766d273d3367acdad35 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Mon, 4 Feb 2008 08:06:44 +0000 Subject: [PATCH 078/327] Changes to support automatic directory creation. --- src/m100emu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/m100emu.c b/src/m100emu.c index ec58e96..458c5dd 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -444,6 +444,8 @@ void check_installation(void) if (check_model_support(model)) continue; + printf("copying rom file\n"); + /* ROM file doesn't exist. Try to open in ROMs dir */ get_rom_path(path, model); sprintf(roms_path, "ROMs%s", strrchr(path, '/')); From 1f117f878c95a16846145eb56eba0ec1677d23f7 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Mon, 4 Feb 2008 08:45:39 +0000 Subject: [PATCH 079/327] Removed M100rom.bin file to change it to a binary type. --- ROMs/M100rom.bin | Bin 630 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 ROMs/M100rom.bin diff --git a/ROMs/M100rom.bin b/ROMs/M100rom.bin deleted file mode 100644 index 4c2127d2c8ab338013ad9ecc4c6edd1302fafe72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 630 zcmWkqJ!lj`7(GRZ2LYp%U?aGw8^MdlTwxKMyZv@=xY_w8GqcIX##$tWU}@CCMg$A( zwNMa@VlNuJ%P`3Rxru3XZ@5p~HFwwj>Bija zqZ~j-_lPD57m@DKumIwvpf^!t5%I(?Kxve)i7ILopd-l(2uqFPEA@0MW(rcuA@-<_ zr9^4RqY#FX9`c@Qqcar14MRJH#LGYi(5DPkNfsgX$1D|+a@_+z$2R0+ZjkGgDxES5 zh5?cG0P&2nJ0lu`W95!v*)bSqUbqd*hN%qzQDVfsw25LlSD*k)gM{{^?^G@PzAbL-i%tv{Qj9M^!G! z!ivTq?g(RB%14BEHO~RsG5RSsQ}oR^7R3YOHCUf^Qs7pWvqM-{HBC!8r65gkQt-7? h(4eKAjC#)N2QRLjow!4uS6@y(4!%#CYQ1`_`X6lC2KoR1 From 623f3619ca4c938fa76b44f89387f10500e6630e Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Mon, 4 Feb 2008 08:47:27 +0000 Subject: [PATCH 080/327] Readding ROM file as binary type. --- ROMs/M100rom.bin | Bin 0 -> 32768 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ROMs/M100rom.bin diff --git a/ROMs/M100rom.bin b/ROMs/M100rom.bin new file mode 100644 index 0000000000000000000000000000000000000000..43835e75ee45cf45cf09315bf162168b388a4e19 GIT binary patch literal 32768 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 THL9_}d=Jho41Zng>G=NxhYqG- literal 0 HcmV?d00001 From ca3e6470382410c14bf67145cba9d477b0042e35 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Mon, 4 Feb 2008 08:49:28 +0000 Subject: [PATCH 081/327] Removed M102rom.bin to readd as binary type. --- ROMs/M102rom.bin | Bin 630 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 ROMs/M102rom.bin diff --git a/ROMs/M102rom.bin b/ROMs/M102rom.bin deleted file mode 100644 index a776ccfc03969a5984cdee8fb2cde561c352489f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 630 zcmWkqJ!lj`7(GRZ2LYp%kVbG(H-Z<9NnsJ3yZv@=xY_w8GqcIX##$srz|z0MMg$A( zwNMBc#a=XcncGX2?A|TAXH*C_0h<(pV!+P1=6&yj@8`W|)+R&XQRV*r#-@Ml?7nFq zKbSf=Jh=Pp^S$TE{2Al5D(2{6#oU^x{4xLjn!OoY->#V52ew|B9J{LLe$TLrm6O{O z{fQgX^Opy;*VDf)Rcr0qYVFaf$ER1sZE<9FYWBk{%r)F==f|edz3D!6*WEq$ryFyx zhq4cC-6fhNTtvD{!vctxg5E-nMZ^=o0HsmF7OJRTfQ}?DAS^YCuhi4cm?=mphuEV! zmJ+2Mk3twkdceD?h0Z_#Hw^6*5-$T8K#wv|C0T^jAF)(O%5@j~99xi&xIwN{s&vXM z7zRYz1H?1R?hI)Nj+HxtWyfHcdEpK$8>Th^M2Qji(gupg7rxVJCw1qApv+FmWHH$VTfN8<-snILd#e(YpK*$Q{W_AX=xo%%UWPxE6FGy z`2Mz46b_sA1nN?QSbz8C{f`d!2J#!qcwsRKMTXwq#;1>Ez!R=Jb=8w#(@q7d996j> z3o9CfxGjurDIXHv(L4ue#ptKlNYOW=SQHP8S7$xiPJvrl&Msjc)i6!zl!7$CNx|1n hL4&4tGU_>N4_{tCH+F}-sJVKJb2MhoJ From 94b156d67e92dd2c9bcafe0318c5b0d629fd3cfd Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Mon, 4 Feb 2008 08:51:38 +0000 Subject: [PATCH 082/327] Adding M102rom.bin back as binary type. --- ROMs/M102rom.bin | Bin 0 -> 32768 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ROMs/M102rom.bin diff --git a/ROMs/M102rom.bin b/ROMs/M102rom.bin new file mode 100644 index 0000000000000000000000000000000000000000..a3e9140f9db0978127d3d5f81694d5abab3a7f93 GIT binary patch literal 32768 zcmZs@3tUr2`Zu0Hhy=L>5Cj!C38D}LiCiQ?xP_YnK`x@UR@-{1s}(Qpa?wV6we9w% zz1r>ezQuOCP48H{+mdsPC8tgy(SVJ1-INV>o42*GO;my>?{|Xz{oeoQ^G9>eoH;Yk zJoC&m&pgk}^Bk^!PE$>DhsZGg1zRgoj&rNS-PvxRd*9)~d!Dvv(>dJ=5f|bUaa&_W zzjD{S-1#NAzk4S)x*vD-oEZh}MVFT}szmak*l%LjF4pD`=e@c3Qm!m-b>6PL2jU)? zeP_$I7I9&A;qk(nqUtQof*INRto2z>Wc@AceAYykxmkBo-}+6>>h=?r?Uk11mX7ul z4NbP1O5LfN_OJBqdRs@crPfx{)~;`@`AXl`QDv)X?`Und)ij-M*SCx{=-TVejcqlj z8k%d&x`uXhYpcE$#XFj6hCAAan@_Z@&}R&{)HHLAdX&;v>PSs%UCqgc#+tU%m8)t_ z)zZ|dmez*m_7gR=Bl;CJBQ(wFo7+z{w6&jV#D#0DscZ#+N*&jRI%gW1YBGQ>y{yUL z^i4$9^mWY|uCa}+scAW_?`YPYs@Aux8ELC&A8D<@m7pW7q;mC$zO$y4t88o}pt+@` z@tew~ny(ug8&6la*3>kAQ`32-vTETOy}hlWxo)(wwWYn)+}emPoo)wCbs3iCw)R%^ zr~#=JHE6o6wXvajxVCl(7&V=#2MB%p>GqnIzy19kq9#$A;!%if6mQ{A_boUBL|BTJdNzamw(S@x>z#R_iTtFoHNmAAyqd_N*m zo)@vJXYLOFQ{1YVj*1HTGWoTNZsh^R-;)2C>`8t(<>i!P zbMmXQs?76lN$s4wdG7z2H*<7_Ncb10y$qTdZKKy;J4!I#i2{1m+minp+Hi6wP=2ERLqq!wxGGTt+};MudA)r zuhKVlG*-3gba{)xaZUQR#gEQ0b8Bm7M@^Hyp{A<2wzg7VQ`_96YpZRnu5Ef$ zB>Kf`5sCa35w7^p6Af5|k_vUKt9uW;Xpf=$H@`8o~{Xz8@ba!zE?{9YnjH0!z$_;5-j zO0U_yyKA>7ed~^Nk$ziLgs5uwrdzj(7>TIFpcL*MY*yAPT^qLcedOkoCGHF2M3Hky z#)V15;xO)UNp_!a-(O34jYQM$A4rX7*GaffE4X!%>}ULnK3{5xICZ8tRV+@85T_=H zQ>Eh6L~&}AQQbe4ZSd{;gx@34O!&JQkw{_i`LkPnu6>^j0;J*U}yZ-FI`uBa}X8QfSS@ITZmK3@r3e{c@9qQb$*q$ICa#2F$iYVPtz;@6-C8 z7wfX$^UDM^6aC2#bZ;PJS=;k&wblAgYwfM zrBZ49LdgnYZouPy3zLgPc7Bf3O8y;g=QE_kR{3P$#J|I_D!8rVF4WUCp_&Ty49d-2 z7dC9AxALL#5l$sFsyF-fK#7v&M`@j);A3VC@QE{&1Cz~Cm1eVlz`*_}70R`5;I%@Y}$Qpb-{yL`XMEGAO3biYBk)$zPk*lT-UILebCox1~<*d1<}JZE^RStZv~@k%m1djZ_K&_P^31jZ*r= zPGw}ITNxK0IjZ5WN`(g2F9pJ*?R?mb(Oqn_w9Y`0JqFyAagp(ybOsY9(#dp9%mH6q zJpNg<8`aPG2`4kT$jdUtVLuZhDj{JKcJ&OIUA0Pei&E*zKJ35Xw6dBR)@zEt_@k}v z=tvUK(rgf~&o@47y2Rfk@shtqd0e(bGcFI!AmYMtxmaWnhEK)G?JhT&Q^5T=gB&lk zGFJm7*X-nAffFy~52>|cc3{RBs=Dy@ihTBz6S&bbUNhNL;Ph~w86>-qlodG5c5!7a zMiTW<$vuO-i#owqSDbb;{TpDf%+QADFV&e{*+=~2(tFKI$enkdSXiNH_YIs-Rghof z!NhLxUkUo*HV7JC6Fxw71B^buP@=p=xyp?h;vSPr!tFz&2OOMCsIdJOJ3}uOxtZHS zWDq1~H^xUZ0&Z9xF3hxT4;N%Mq!yQ#mRW><^ACj!I`*;fvEi!W#?)}`weYdj5L}1b zgl6{7$gWG3(8u=S*3?kqsSwvn%x6a{^>t%{mHkKf7_#tKH`a6LZ0R_2+%FZ$_9)BP zufjpDoWU^)kHpJ=NezR1G6=cuY)nERq5@sUMqFOzh2#s4NZD=MlCzStJfn*tBa+=t z?oznNY2g=^+jcaOoN}=woGX+?hhhv(uHXPdD4UV1eaySW3|T;4m0{5Pd>5SORnjvH zr5m=Y&Y~~tB-5qMw47T7QYs;!1``8BED;{#cgs|iJyJsouH_4 z-zV$~GR^b;0ahHwNW#apPO&ChBo+16gF%Om4Jk3N-jt0#%J$2SJ=)3j%RDDTxltK; zs&4o@x8jK3ZP#q_2RUrK4yj{3{Dh2*#Ucro5kgpxOrA335<=Omh-@V2NHX{PE;!~z zWPj?vV71MUU>^2gaLkQh{(#&32(6VAX1Ph-0^G*IXjZ31c!s?xVr=+f5TNfPzCMCv zN?X=AZA~&aq?P+DT^#lfX?FY8bB{{MREp!72=mzRV@8wtGg~c~KUmA~zqLFj?*TJW z%u$V*tV3q|aE_;x+Z;i1<%T*C>$QmChgB=0diaWP@_)iHwA||vv;}rBLj702`Yk`# zDk;TMVG!=)&qV202#*O_gR(FC>&}2Mq)4WCUcNQrY)LDH}c$ z^e*E+s-We#mt|;raDYEY#}U&F>~soj`!KJXIZRY8A}?_AnwevcA{kd6o+ySa7#JE8 z4zZ;(XW_>!nW+`4@Ah#UW=4k)m0qYgwSJyz?9|sQ_>xG0CFJmArm&1J zh&0hDeThFgll)LZwk;@1$FLM&g<;v5NNMi&4e)=PskzJdkPzTLo2e=F)s^z>OwGer z9x6NLU}v7Pt~l}a3i9!Sfm0tZaH3gpxCjzo1_%cB>davMA8CEzXYTS$%^!VrsCw+o z*DGuVk)zSJt26UBRU}y?AI?&_{@<#Zk-@6UNL1zU@bHzq`%$H|PMdx)jLnO5j&Yl2 z8qrhNmM*L+;ED&>JLirGO8zE2nTR!zk0Zg8Y_& zqoaat-4_Lw0QG{{DGjOtTG38v-=x3fWy_+*I_WZ&8!X+)tD+J$(i|1(T7Ws{W@@6w z?cA7bOq?HO<|>w|#&~^{ki#B~99NC86OmThgqwY~A_(x#D8m4=E9wMv4z47!yr$=_ z-M6N1-Lj)=_oj{LI^`nv&rwvorb_sAHw5f6e)pJgKYL#k7acYH9rw4W;f1P1kv&=r zfkfuUU{%MGZZasI@Czeng$pCXd0STW=*W8Zd=%!p5W1H?wUGHf1fs2H)$tLt_;{4L zPgv=wiJlOIKE5WJ0e@}skA`AR8lb{pG9@~D_LS>;+)}4p*>k5{Cqq}%nZ?_q&Dl@* zx%Z+HMWg2(E2D)_8!qCccaC>DY9(lXj8jG1v6NX|;@z>FBDzP|IAXTT!!|N?v93$( z)hG&G9Jv6mOubljsbFFsj21%p*P;ap|4X#(|GjAY?mz9U%};Qu^NIK_W9PvF=$V#bCS3QG2H3?`wAJkW?$=-C*OQ$L*La$|8g z7fxae0pcsZI9ssrKdul?@^@wl5AaVk3q1eSJYk66(=vL&b~%Q;9W|U~NxX-=7X`L( z5#JK01sv~kqhFU!7z&&gs7q&sy(1IrEmF}8y?LxxC~?e+rS)dC+>B%*-Z9Gkcncz`AD$?Mvew*@GexZ^>t3@``Vs?F(dIsrht3)@Cq>1Y^Pcv}&)9I{F<*Kwa+mbkg5OA59lsMPm%m|^0 zUTWy2m0mQ19*;8te_U0Z$!Sn>!MeT>Kr&hY*eBsK+!|*I>bkGRxt$iVxX^s*>XoaQyW$$P{Er973k7GzHJjvZ8<4Vf zNW^BE=6)-7+0Eok9QSiVK$4x~%b3rL;%j>b_#fl2F0k&nEs7jpk44ksJ9w5FSGhiI zl=`*F>|EbHZT8C6_LF$>!5mVxdt`Jb|4W>0Fus(3 z1;1NTOZmUXucx>i+g(ako`zg30D!a*?lpP@}%qKj@n7rE@SK z<#z5S_wOEpbd5_8;s=2{9));*Bp!NUNCGf7s^1B4FIJ4c$*)Ne7O=M_jPWZIhI59W z#iZfN6TF&LzJ9R&Dj&Nt!SgGK?hV=sUraJHUs7E5{(A1XFZT5DKa#BpYW1}-I)j7= z$GLEIr%#=K%@T+p<#*clCm7Xal6xk>3(Ap65Xoa9M-#|{T_fb3gw!~yejQDK#yzv= z1NM~!uD0t}xj$9JRqwRB%p`lK<4{7M>0W)G(`vE1I`7q+`^ZgQ$TT72Y{Hr*SAsU= zbGEq!+Q}Yh^&T%ttEP>Zpu%3o`^khrML;K=_4urJXPuZeC(&hx1-Dla^Odu(2HiZ1 z#3&pGX4#2jwiQS?Qzk;#l`Sd0khpkidn=ViBIPdSPOFpqR|1`@jPcs3C)4@P7B{&& z(b(O!1$I2g%yL>&L!biHG6XLZXRT`wTF&A?z@Q8jQrNp^aT&9wLA%M9Xm1atq8kTN9fA0j15gJO}GV-jhr?HqxKqI5?SvoyBnJf?qsW*G8lwXfzmC5URE{VJ>RI88HAML za`w??KjTFl&<)cEhbpTW^(7YGvCbyi5*)L zU52=LWfZ$Q(Mquy;%XW3m4K{Bgbs2^<@W5?C*_AGldYCV691m~RiZ61HpyidLs}cV z)lW?B#TYcVU^My@NpxnA%A_rmdp!}P;Rh34vZ54aB>PFClO!e?Q66N%2$v+CN=)K@ zOmH(#O#V)dKq409Oee;Wyr0mm3}b&tM54E!J(K`Gn{TZ9-(CX_?KCRWPLujzEdwzn zpjK)USD0xK#6uKCgB}B;Pg);L7l4p1y=)KU6n#Y>`-2>~HVG(otN=cDCcT_=H0k{$ zKFL??J^y*D$Lq2)PfwAFBy_k(7;K5moxN9>J#;d1{X{r&edU~bwooGt;TO#wZI()KD;uoq z`Di`n>*E1b&lf^QKANtp%)S#pCSLG~4kMc7X?^bfhSdwlK-BL?AK z`3w;&N)GN|$lSYCd*ri4$=ttZkGaU>$s{J3dwceDi>1!qOp5*8mE@^0ro%}auJ;vvAE1Q-Q4{jHyIJGklsa4ldIz9}U&L~z$ zhORXH9hT*B2&rU}m}LMNH*XWdZy@1zLVuKJ(Y9bBOt-Bex1|hgXpR&)a}3JS#X9jbFYU8B({Yms*ca3{H#l_TJBR{4% zJ!70aJlNfE)G@fonH28b6jy4v-HW8hI*&a`GqC5I=S!xQl9Q8B4_hqGZj10d|7yAL zHUD9`@Ff3PIr<~~9Xv85yf-8m#ox%lS+Y$Q-vM(ev7N_;DN48k+|j> zcA0jA=mAV%vsW9n*w5r$D`elBQ*@8Akli$=C^EPqMD@%QAIvfI^PA?-Y-Le^S#r&V zF|-CDr##0#JcrVG_nc4J$L7$k*~+y>b@eswZ*zz}eMtCau+)-W;!|AoF%z2=tv>G0 zn~dC&d&qr%bp*t7e4H?fj&kbXj&fN)VUq5#jd3h~)dOL`eJ1@rNJ>Phj=S!b&fRi{b}ko~+qI!Ldan9*U$1(TPbb;epQfh@^_|F-lhRbx*if+Bu6|;S2d?U+zJ7W5!t4s4HkxluHR3s-Rh0PL zie*0aA5j;wVg(}-Qo|D$8pzHBkF3e`!Ttv*NKyw_=}<{1QfYciH2qW5cZ;?SW#i2Zu|Jh2=QhfRW^JCSGM9 zZ*no|>53y$P7X;5TBpAt74cVtu%%*}Kx5JntT0Y9`W>4F7OOOcLEA9OL#}$cna!rK z$?!CCZ#qZ_Oim=FQ}yjX>A*sJz)cTNNQr`+VbG+DRHZpN92<3Biw?zzVot40i1f?`wv;xWnZMHO>-=EfVvFGANh}V^An7!C}=W5bO zUpn@XY9)PGd-D}*JY4mjGf|Kqypuahk zo~Vp0uN`MdRwXH5%qVa244p-;45MKImUhyp0Bg1(*=IctdI90q^uSsd(4^FBR7~Sb z2g05G`qTwvI+2S7om46y6Ji<%6R%pbADfgPxpu)K)>m_Hr{CZQ{?&9kb{HqIUWaUP zWfgN|YNv7+h^=)}5~Ex4!&B1mcxB2L>__Qg>|i?VRY)k6s^4N3&lJf_Fm#9dFWb{C zH&paNbe6tAKEJu;pyP77We_6`#g;j84FjD0;x%;5*sbhVx^c9IUf(#9o3{2ioT43{ zbZ7r#@}8&l`(CVbgP1o?;4DT`wLN=qQt4uzxF!z-$dhyUyO|hA2jdE={1=?I4o25B zjULy*?0vn|%0JHF2+b$%rpI}1@*=}EGw5BAeS~iADMll^S~kft{CkX&Rs`9SE!q^E z*uBrVF|zIpgW3?a?5f3$F$y9~bHp?UX7;pY4fIrs7q2PBAtE=~zm0b72F6gxU8#Y& z24z2c9n3-|88Wkx>JmX?#a%oIo~P%FE^P|Ab(`^Q;_h8|ID4V>u%7(!GfKn=i|`r{tV#_epLp!INulWdc5o*T8r*1X+_25{98&8 zqZK3KDfVg)c&QB7k|~_#|EUyS;?)`CyG-sKC3I~wKcMt@UQr*OBIB7PkdA)1fc`%0 zMh1~*GBcn-+!%Fg3t35g2Ai1y8@1I38wls#AT@-j=I~TMi$kxFu;^)HiBfh}M$lY> z&Xdky&jhLn3@5a6Y(@6{Q`D%0fn6k~I(pG{94CXns5$ml6Zv7ji?n2-y&%;gzMq=U z_GDm-8&|aIv@rK(kVBo^o{UwSc5mI>o4)zht=og!;bS-`hxC{p$&WHHk{2@qw~T>S zd*)BmDo9)xS(TY>!JHZf-CXwc5%Qh-fxz=I}w*?iY@%^CBp zw5t7o>H=BN?wd)slMb}UmQxOCh_cW}uoPm%IY~Hqb3RsH%1IY2@^2;~-eKN^u~qXe z1b|7we8-*h-9bPUNU$MPKe55bJ>N;Ps&E}cHz@l552iut1nCka{uhHvO8vw0r>Q@^ zc{zwCU2eucpOE>0ud*h)nRCGhN`@gf5hnsiakj*ax%vk6zwY-+w# zis`9Mj{~~D&gVihA%R&*X5w|s88Dtjds?i0Nvs|5k|PNo7{1XWn5ps*X>gv+VwIVg z2Z<5$km$`T#d~Rj5!W!b46K-dI@-rMWS*8wUy@5l%wSj3F&?~9yq#N}Ngho=U%0X>opL9mvKs|VZnS{vM^T-$6u4x7aMMD?Q+{VNWULHp z)>HKL%?rhQ7n+Tq1{b*@%s=#a!`8FT@eAW{M;bACJkZN6R-Bd(scKctF4c}qk*sBn zDp->Is&!%~4u|jDZwuhjfMX1tj==&bG|&gvL-H7r1DlEK7FaQ)c$ejZeeEWaEc|B% zV9mnlca9tANO$Ed8j6Sujpw4WP#?A3^!R(w-m+#+GewGBl2s=I?VJ`+jH05tFo>bC zh^?_^u#U0QFfg62%Yp=>-AS>Kn-<`N0Zr~Pp&=aiK*Of0InML4#&Ps}Fbl7_N3%#< zmX$nBAGGP-y+F6lBMIZTW}znCwt78_+nPo4vW?? zBe-mVhl0F^zS7N%ylksI` z&equVL2bpATnjI)9`%HO_c*j3HwJkl`sT2Bn`l zQdGV5QBsi|5I1j=)mh!mLDINUB!ybNLt(61Wl0SPS$u;k2pH#Yl-)t9l1uEDv2>1l z76iARz&qTRvCP&foaFp`pqn$O$gKs_j}!ar;F^&#!0#=X*#DI6byZ%e*Ch>4X}+O9 zJ*#qhgxC?UQJp@e-ZjPiVah}Po`brY*;DULo>OUdP2mlx&9N=WaT^NWo9vK~%Q*&L zY&W+chpf$ElBdL?a2$X9s!~Qpg|YupaX&4Y_=OeV%e+;NoN>@ma{5j@e>QWM^s_#lAP%Vl|``@X6KYV z4JC{zPb`R=gO~ao3$tqq71)hA1#(mlFV-IUM)aIM<=*K6f5xwaJW(X;>+KN z7L<3R=0m8NK4or+mbeBCNi^p#IaM%`{+wg745WDn_{kh^(3Zw#UUK_7nKm5T|6~HV zE932TP(i}jksPOIq}OckjFwaZNE*%i9=&BR&_o-~IdVKBoHysnkY?-D0RPjH zI&}8Ei39o`3<;dh4%8KiCI*LuK{j&{*CFXSSpi414^-XqEmQE6VA7`SXi{mEhEv!T zi>%_Ki_FBhh`Ld@@y5-pr%G{ijun~FGvqrl#_aAzbE3FA7NyLwGkH@79S<$ypIsym zhb-+`6tiH8>@Fx0S))+XqB1DExqqqP^_3hQDh(e#Zdlr3A zBtnXQ2sAbx7CRPwk5f+jhb_8>vP=&y(Yc6XCSRkvKpImNmI$>`5cq8Co+ot zJXeU}-_4DgVf#GS>;l?S%BFASf}DTKb(&D8bb2uVlFJR#4DRz>P14l*GIi3_-!3b2 z!N+O6j+42cb}PBBbFpK6use*Mp9|K(5P|f&3%H|;sA?9)ewS-8#Hr>)u@ku#<{LG6 zBOkM8V!wL!6!V0dyqHg}FX3YH{^!lW)ObEAP?Po|@<~2fp(a~ZC@)kvTJto?Q^I`Q zg}ZGHd3ek0QlpC2u%o; zjw3-Bs0SEdEh5v8@6ksNU_Mn7WB#Ni54bR2sL3<=07esUMeLl#pu@D^1v&jn%pl;H|c5! zt>meJn1PsyB`0Imf0)wFn8t?W2KzBx69j!Df12(9UB>QP%$f3;yMnnu5IzM-ul$4m zdhx!2%R`IFa3RKrF{n9Etb;nEQ0I`}2aOJnG2hGowAk^}V)_7*p=(#v1fzqljjD+| zNJO*`(4hE+DZ&SHFzDz79x%YsE!B9S8Ku zl%IXk|6lMobA8G9e`)@!G>4O^X}Um-^fV0s-{8gW1)lkQClK_M4S9o)Z{YD*z6N2`e}MzntOi!dHbEVOGv-QUixQT;kX{weh?w|{huXuE zMHL<Uo4JT~S^2Onq`_Mn%i-Uh0*x)2WL2)A!2!+ZOzBL*fG!4?Xzsb4#TymCBIS zEr*X(RL;-&YCT&T$;4-p{1R>*jX~&k-BNR($4^`c}p|xQ_M?70ukQ9;;`azgz zLgrcE#rVsm$&q5XS7F4abrPD{mGlbroS|OIm(MSO1_yZsZj#%?XJq;%6oW_Ll5b2k=n zk5XMozNx^D8q{?yWDs7e7APR+moOKXxUTdL0nPV%uafr*(%!c8!Zz-~Z!dm*&kZ`A zmcDoQP5!XtI6GW$&(lM&%g`VcsvDJ4^fzilsd|pRQb2L|vA|>jBw{OIFD|iMLMN`G z&*Wc)jt&X!9JbXqL8~|4a5foaLOqR`{u75&To(0RLK{S6gua1LKJt z_x7gQUMlniS2OO_LJtvCmpWSYS-vnUOJ zTx5}QA_j~8ZQHWWW}QvOkJ@=>>8c;bUPmhjE`XKJ@?}NNfnVI@WU+g|GVqJjQf!%N zfq%|rESJ}pVA14!ODv2kC0^lQZ#qoP_G~ro2ail z|68$J(KV&Gb4sy|awddPkIDtIzy-@&q>asT`0CwRZkwk_hEy3lUIe$IeMzs>p%c9? za5IW&+SQlzO7g=o?_SOzsu6;>cJZ0?j#cq?GTT#64ojPJFc4H-sEi~$% z?dpArPG9gNK!mTIBwnw3ORG=&mVCnMGxBTHNA*Xu}=wQ^fh#A}`;$R8Zlf8go>X zz*$mKB5dNfEEQ_lN0++Bgzfx2ONB;y*+nlao%|z9FWKH$YUJKrY7pl0DJAgp%_%$_JB#j(q+V>W*2UYvHDm(G}R|BQ#=z0bYBH1z;3ktk|> zdi|xzAC^*f<9}G%_tgC-D=@PLro<&4*C{ZjZEC6W2WsoNNOGZtEXZ+Mu!>)zRc%Qn zXouEhlS(?d&ZT3XU_nM)=<;$mu)rOrsrOWNq36VL_>wv;ql?+5k`MT%lGoAggg#*g zySjuTZ11_Z6d@Ld(Z$|Nmme_9IAyF6S1VmrYXolASYqykK5 zva+uQk<2hyY>z09NUOY60LRYJwZr`^bRF&-Mh zE=rYmA@y!C#dADHodWxDpRu(OWUelQb z@$29 zmFBQ5qurui(mQTh<}_hz5Ww;7%88CLr)l!uW#;ugho7dn+*FFreRQH7zxzwA+=OO* z@4yMo()%YLTV^zSrxul&_C94=e_zjJ|FU2OGiq?hmJwZPFF9DMHy(Z(NpqbZP)r}N z+%mZP-cLK$!d=opLRA!6fy(MDUNj7D^7amR0sVl!Z$cu7UxBCG)85OHQnILwm4FtP zsfmyHA+vXKW~ni+^g!u-b!0p_FZt}}Y?|%dP~^l2TB2@ zC>J~@sb_mjm6kB}$RE49lfOSNGrWA?hRPg84Fj#HflTr%w)Y&&0?jCp2t?o@hAWvqpE ztJ`XcUGPKbMo|QUEiXZ#l}3*+bFk5D!KCq;A?gcZSD>r?r%vQsO`hO9qCN%Kdswd( z^ZGKNM+rEOEh}>>dt&NHP7c{pW;#HH0_K&ZjIu+;QxHE+(}0Ec#xN1X?kj^oFRsvl zwxN3vK~xk|69|^#w3*0Hm2E-Y0e*&->hR~aj_=Fd*fpir4%GVdS|qS@YMZ5nQR#I- z$)8r+sa1C(-wAEx^1sS%EC?>HjTT243V)bdqOjq(Hy7jFBt*-IMO>Vg9`k7TCD~%M zT!RGS9g7HBvrlU^Sd+w}fu6Lw-ZZ_f0I;;|gIcVsFKb=5ZNrn>$!BO`zuzz%f<_=U z-h<^gYt8h<8~LVS4KuofXBWlNg-7WSF2?~eUM6;1?+ ztU{WCkh7w2D3ZnHbmgC^a3grj zg*e#_TdjyCQz?%5-Il>p?(K>}N?z|NMKg`8ohBLM3z&d{%S-*X`3l4Z(@^1egQPsR z!o&DOS-7c-!?NE+q_A90Pd?n)@6ae^w}pe(m{56ExTzc~(QOJRPMveg10phpV^``> zgENIKe!im8Ih5sE#Vf!CM^<*Zq|&6i=jrwPUhD+Z zxG?5s@vHDVxM0JXv7*NZRrEKnQ?bSG#3>?b5Y_(aBSd;e{8Sy~Cb5KVlw7mJ_O`=K ze)985sCSjvLzJDA(BmINfg6VeHeV&FD_x7C22$p%x!rMdLQNZs0`WU^+K!n4U^FU`o@rAb z8wuhkyDMD?C4(!QMH_Wd8*$O1oq^v>{37vd=XO?UJLqK!w`3%#tQmnM2?q?Z-+ zvKp69hqOCsdY4x_=c4DLC3~4KQ>c2?bUGVS6%{4DTq?;j$XDtNxRNOu)kSLK9T z6uGU+Xd(O7A{X9L|6~WNT;!*kTrqvsR^?peLJgFLA6#mb!rP>{(FuLh31_|6|tvjE2OZ>(|=;?|F%Y@d>|Yiy~L(xw~C6m!q$n1`#Q!y70xb2VOx9VgEbP>f0F@rszvydIAqDAlmL3KLV+*i6>F=*GVgM&*s0%fW}Z{v*=#^N0vvdG)j z&z|KAYrL5Yb4XmxBC@$=K5N(Iz+|%NxWbzMDYYe7Y&*&=Lb;q^x$C+`C^t#Vxm@I- znr0_?r{*oE!!H6!Ts;`-tyP&~v=^OjMAeLaLY6~QgXjevIbB21D6Rn}|2#XC zDbC?m(j35Wc>(ps8Ydv{vXY0|~zfuoU^7bCBY_a8@g9jgk7Qg~1~{^NtLD>gOWs@E!7^R@%Dgc#F%xMI!bekH=uh@c%;+>0r_H)-u7N~*r{=wG zINYE~M3(&GVg{$g72=|FC5@u^zUF`5$OosGALu*o+&1tsr7b9Nqc?1LZO%P{jFr}M z%c=n)Rh%ex*_(ki&fH+(WU-mGbN8Y^My&-glr($^QInx{7(q2ZDSyx>6_c;yn2uW4 zS@8d>weUSfRLz~W(KEnZp%2uCzgjEfYong4oyFD8=4$7?TI8T2O46b@n;yl z$}X(KTK?D+b7Hc<5OZd074vilEGozgCvv4C0E7R)r236X(%0-*Q`ap-@ojaO>&Se?4tD{bflJH=d*YR7hRs|g^#Shh) z0e+*u83FDHt~Az-Ir{4medzeG4#}f5X**gcWZJ%|lb^4%Cx!^~5rLP1A2XB~E+~gQ zy%YPfYvW>i{mHAGsy?hCW18m>-~5mI%f33p=tBPS`q3r07^!}N1&d3mr|}!{pRtMc z(3<{zZ?UtBN$F6M%j z@2y8v8|v%LQc-AVD0C_p{Zs<|XvL>~EQ25WRYjr;?3Q}#9wq+ocEfoTiZQevgeS6p zs%N~R)DT9P-bVj;C%kY+!%ZG6eeTju8nXLzJ&sx5uNT(A9cm1Af>W^(!9aGo%M0HF zZSoB_gQ@yka7OzX`yK7c=eQY;1-B$wwqCOl(Zza+N7uw_mp;d@ZIH{TPKR>cO3;hC zn$lfsJz{GSc=d#Tml8FSdf_Z+%V;o#?(*U#Ia>q?F}J~6wZffD{fxrP(Yav1${RvE z5hQzyJ4@zPsn9>A$MJYWo!+2KbO!hRpg8#I0U+5^rfXu?H=to%Q`V@&@nAz1|7b(j z!1s?f$V@Ufj5!Ow*gzzEhL=$jhI_k#MiTQMH(1^91AW0?>b2JfkMV=2(cJll)vo9e z1mNAw&sZU(vu7G2!&t7tS*^X9XjWV_uJ6RH6Ym*bvI1Kxxy!@&UzQ6hZ8(3S0Vj&s zp=nx<%3n5o!JcgpGWZ3{g>0mhJwk{hZMi|n(5ADhD5vCCFSpC@U2bn*C)_fKP21`JJ)@GdR%=~? zl6PDCRC6c7**BKYL$KZ(%MGK8_?MRp0y4DWCnfiFhB-a_wdGLk{}yFM>``^ky+Shd zus+`b^4}7=-Ju#Q=Es(UI*6$sT@HM}B__Ai<+U50QYMPl(-k(kXMjE5!2PzI(#7dv zUu`)5^$O|^LPN5n#ad4oUQ9PM?ZkkVFaVX&B801cn1wKNJb9i&1U$&kF2BgBS9tpd zw5k)j6&?$WFi61GW@j*L{+$&bFXYW1R%p`^0EDzGC44$jUs(3j3`fo*y5`pWT~Gx)Bz-h zxUW~>I4PwH@`kmpm{!#A$bY*6VS)7P0j}w)MpUsNiUk3R!U_myFWgc*>&d39>4_Kg zHNx!Um_~G-x@_PKxuX%YXY;o8j?nW9bl&E+WQr88PiDE{T9{173`Y|#xkQu<>1}(jF_6k_XmJ__iY+R9X#hS`@T5U3$^$fJ z2(md4X%Ux1nyE|MSYzVV;d_M#QpNmKqwpMmxe;#4E%Tqc8t0& z^`V%0L28C4pwAi~1;ZPk$ugp&}7B%jG_!7x*{vhcbXFzc-b-dGAey z)9OKGAO)_EuQVA(a|YN~ny8z5vDa%%#nKF)s44Lbk<9bT!~vfe>xsupJw6Qslk=KA zCj#lPGL7WRMtt4}kWVRKZcyOg27!M|fj_JWB&xiTK-aB!C zpV^!m;xT%SXvpK3-K-kpD&zqL1~HI<3pzP))rcWtmo>Y*17vBFr|fcGGYu)fK{!`2 zGH-l)Wm&V6`fGWCu~tGhH3!lG!fSWqGgHY1w-s%s=sn|wfybH!3442s(`fJxXL-iG_fU@>7d)oi@P_4m z&0uc?x4N6V5s-4K*<*4BVgbkucPJ06MtpF}$tfgs^}fA@`?i_H>0O9`jL_vE5qrqwVjIY*n>skyJ@k`}qBe%5a z621o^PtRey^lP~;eUKls^wZu+cJV)D#?JL#vunC-NbCFb3A5PUdc<%)uiq==Xz9Ik zJ$?Nn)mo$heV?G{tI3Y0XdRnsggsx?}m=M9gkJrfGi!IFm=m8}Pw*mZ) z^FQi8$BzWd+FsJT@W}$N9_=cFm6a{1f#)0^sVH{V@0k&J1_|_tMZ>_vVPKrtDt*AW zcNAZ|YMK6uhvkwNZo20ymU_-qEOlB2hOlKY=;1P2Qj5i@h2qqu;?x3hsz#i;M4YM? zrxuA*OR(GqngcC?*1)Pjdtf2H4&->Q#nndcY2=@3!8eBf+=Arg2V2%Uje%@SAQ$cS zJzXY**p9Yf!wS)$VYcQLlijSZlY3e)?|+Cf*QF@qkD1u>Em7=13%(9D)*|HNDL#ce z-{N#yaXd9Sg#7r+|8A*wy5N8_&;me>)w)1+Yr9Zg*>=5J-!#=(*{t(7wzN++>6)&! zRyJJ~*%B@%>`%Ncse5*Nk~L{6A+XqG_fkQm4Lo-c>H-tLG8xOd2P!zdOZ%qnw|CtM z@7%Wb%J#vP?KQ1U9qrZlI$&OFZ9}uJsg-`2@%hd`?baO|U#-4%`}SAc?z;7^SKBx3 zzVq<|2M#oC+Hv>eDtw)c{b?l=jJBkKCZ|?vb1rIBz8J0gg^SF^mDJJorj?7+ckbLH zatJFi-Vv>c_!FAg)|E;Gp(4ao6~rs(#U>>1DXpUscvq@c`B0J3wUX6qt>l4LVC?o4 zBO^X(f?cDK+{ilyx$k|r1vJK(p2k@YIZ_+2`zH22Px8fT!-?id-Lacso z^7PSS%el{S3URHKjI@$hcAq7ecCbIUTF4MB3wHzZbL&}bA1AiqeZR%14Lgz2R>sD+ zMGuk8HvErb=e9}T4PzI!p<%Bt{Pc0Mrp@H-nFy}~B3Ir&ecUsGC|kfo&}U*BZ8!u7 z7|}Q}(QJ}JK~rpF+f)<-1Xj`BIQf^`(4m*x#_;o=k7)NecD4zn#WcI@RBRi!v&~Bf z@=Qvb$M$)v<|d!eR6OWnZua$K+#p>O+nfj&K1=qjBGUFDK|3Ur@fX{KTlnj3LOK6a zo4}kxK2h&5mQrwB8!d*=;j_8v%4(-9M*y`~t2#P}S>V*80ZIbQXAl zrl%aJ&q^a zFV<<+;N^*q6~w%Xd$QfAt_XnYj)`_WU~(GOYkX)D59<>H%)E}|pt2!)>8qTYLBR?e({A-&}M1 z9bM`8i%Rdjb?aT}qV#m;(khU`rD5sk9S}ydvXjaYE#%0M`sCzv(9R$}F2L;TMHBR(NoPdFHC(@Kv?q8eVyM|WiyZhChCDm@a{x@if4PeJKGi{wle@f%SwmqnyE>^@e6n5t`^OZ}BY9`AE4}E-kPwBBeDoJvn1_Bx zg^J8Id`Yk>;#MeIwfL}C0N7vepzHw&u=94Vc4aN%Skmw6O7GaYz3bMEqTe4eL3RW) z(r>-3YxiBjP?u(W1Pi6{4Jh5#J-2u5*sbygqdJ|k^W~|oR$<8&_cajl{s9M?2T6 z`T6>K&*=Yc>Pi5by3+MYKuA!8fLaB_++bS;7fKZ|10f)YI9h5&Q5GSAu!JRq9fbsI zr#g1Aoi6sh&a|Cwc9|(%-bl5r4|1i$O}#S$VrggxqlVg-)*3ZoQIq$b#C8VTn{&_d zpZ)y*`L`P-DB9IOC17{;o9(+&%olg1^qI$Y?fcR{PyX|rlT&-qHp)P?Rga*BgIYW& z|d@T|RRMV+`i^Q4G3HgPx~g*sTWOIrnSk-`?x~(5&0-zGhzP zf|EB*F$@VKBkeFMq{dZ$tl^C{K9cwi#XNWGY|un+}eDOQ4~miKN%pJ8w$yX zbHW(rn0YQANeA+eh6jh4p3k3U+Mf@mchBi}(qU*-s1RXMp)&6PGS}{43~_b&CVvDq zd&g_8Sb_|-`KHl)>l|*-J8ZK|$MZSL1+sISRdpLR>aD7VwEBjvs`kyzb(@=O(wZx_ zYwB}Kn;z1&WN1p4ZCJjws`IrN#7g_Wlv6NK`B$ zgyK8;M|XMSQ(Lg%rLS*SwP>WTKhj+H)RwBoCJ<^~It@KI$~F~9ghkl4Ki$Fp8R6f} z$LcY?TVR!8;Tk31W% z!0M+tL$$O3UV2PR3;D}M02CP!j*G^+!jbTO9}k)W3jx7Ly4@}qv5iFFXv_gUe!{f9 zFg%7$FLaakKC4+<2-@bwLQpy;Wub#jEgS@=7B97hT!cF~ycd2Sdc(O9CXTj=|De!$ zmuUXH$l=}ww?0ht-2{+|uOc<5h<&OMIK_E1VWrDKkK=6vSpV*=1MUqtuT38mewoOn zWjwNdRYnex*6Et0<xXi3Giezwm5sUF zQVweS?yTWQ*I?V$Ty>MqvX=z^&j?Hltg;pbb6|)`;RTIJE|49bqSmf(HwM(u2L~k6 za9Q_N82dvABM`71>E4qH2-10Ge!c@5FCFO)tGT|2(?k3Ar#oxfzh~s$v)6k+(x}FtSV+2*q%1V!T`FIDwRrnpPL% z?$*{Mt*WV6S*~lS)szL2;2_Y!jg8XAdR3`Ls#Y~%{WVBQEezlm%Y?Dn-GF45oTa!%A9;_&cEHICXF5voZT}8sU3zM5* zbtNpBlwEW|!aNBdzttd&24lZ>E#mo7NU*A`{OnRXz26mM%xrR$x!~e$r6}y=f7CcE z0u8Y7LKUPlhfCm@hFMTToh+7Dd1aCFOP*AHtvaIqSIG|5UR8L-Y}MhC`S_QvK2@?! z^FUcg$!zr<)i#w$m08wQ5vsme@@#pOdS}VMO17zXs4kYsFSyP}_IjtrlZ5^Ofzs}d zm14cqJK%xRSk2@QXbzh33kl}rkEr>VwfwZ!0m{wtMv0BzuC}rpRs72u8>WW;Kx4%Q z+N!D5HNajNL~|hV6^T{f0zdq?>5USUKzZ;?Uo2Gwu`iVHS4!5MbC$5Lse$t_ic3Eq zYF0ro*9iwtT3F#**9~B}zW7#B$~LPguxTwFwgT0t?*;berC@ADKpEbKwpsb(rTk7c zY_ft)8&w8M2CJMlc9n{H?ciUjva&8U3a>j?uJToRuc=vuYAbAfrZ%=>a@?9ay7J6o zIts@)TGyK@Q>O|~^8pq6ii*Z`tIS7Kc$!|I@w`h7Kxjap`4v?Rds1Zw6!;OuTO5=N zc}#O;2G9a_N6ax0ED&I(9 zA<8bhigMXc)UX?#+l740de@6tsNHK8ifRXfXByOzkyJo3>w1}*LnRR5Bjdp=iQUEg z_s@E?*)w$PQHyUwYb#2{+$ae9rCC# z23TJ!!S>xpyUAvhu0VKPL)*D4o!_CQ^~MzC#>J%^#E#)7s_lc&v%uJXRb_Qh>p#H& zJea+pd-eH>^=F|y4{Z|lEqgdTFTh_MmBE&maPIV_txcK+WB7H+-xl|SblySKX`}0y+I7kfq z`1!ScGytCR6dWSht)ub@9J148VpKxw;^^{4e}HnPwE)-wfB;P~&*svi+(-b4FiAE1 z-^*aR>N{i|IGez_o}zpH@hb0H#4y{=p*t)NkC!3=$;N!Gkt~@U;r+@7!CYBqenP{u z8d&23?h#EmrM!-42K)PcD;bIVtB!qpL$i+ghvwV|8g{uF&7x#F4yRt|xa^~g7q?cR zb*qamNnoO}@BvC#oY276UQGBg(`k*B!;P|5)l^zZwl_6^BPS=2`ILHh0{Cp{jMdeB zYM_;_1^~va0;ptD@d*Ek#wWaoTAmlhS;ESXnZwGhxVhz)!^==9gy|J@I~AonyaN7X zY)UyQXXNGo7V;a)nSye!kRMslS+=d*uc4eu`#Z{mo6CQd_9NBW9R`jvB=$Kt9M6k! z|2Sn?p5E?Hh4=hR8s<9ndPNZtb%8afLbBO~as0X)`fTM1hg`pMGX@i~DP9D*iX7mW zqtawxMj#k^N@Ckn4u++icbD@wG(e5$0sCDseFe$!zJ~pw+=p1H#0}-RysEOMN;&i@ zDtJYO<$5`)ixyJpOT{ES_h22|UxAYBM7fv5Z_>%h$gi#SHP*_LaxiD^x>G5spuQER z)(yDb_}{Z`0HjN*f^d>^|E|Esd__HRU_Ya;U_D%lrt%&uW$*V?fT3YNS~2u~g%_Wl zd$DxrC~X0c9fxOZHTq=3%JCk}=$NlpCo8=75b9oAPP!AGnZkquB7pbm(P4$$^Tpl2RgVS1Sx_|MU~zrdlQfN62qb9a<&qs&~{Vh8kVbE zV}O9wR4JEDr<}qe@rS8a%B`XScp)^nBhBAeLa6VniIYDw#mJ^loxR%*MI?YJeoG(0 z^by3Kt;AtQQ+ovyF7U%H!*$@`P->NZ+_JUG_d2w-D(F~m@_qH}c0}XtZge7|2fFXm z+k{@Q4#3KiGtHO(S=_Sa$%=xaxRtT1u@jFi0ZIirMercd zAWq#B({okHz^%^MAL!Rp%vE;q;~ZK1{n|Ds-cstXX?^%9RoUG6Mz9TwKib?BS8LRgu;B2{uPohvPK-yA}uI=axCuRv5cg zOnTift*)jxmxBu!95SFq&}!@WP--=dx@Ha7`+1eN4^A;ECgCFB;c7el7ZWEiPv2;L z4AA!RTjJ4QG>u2sr;hgXY&9Z%TBIXIxnk&)*dybhFnt=hzK^4*i~3tdp1WkgAd<$a z?a0^H{cO&w&tzF`zkEREV|+*EW9q#_42>JeXMq+d)iGA>wST6;iE8e{?3(nn?b#co zQu5)|B6>XmM}vI05#pyUkcS~yS&){2d-Qe$bp_iuY|6~oA|;0)DM`5HVIOUg4j|YM zZ!3LV)g~G%o?@S3q?E<=w&6cLX;Hq{EBTa9nha`#X{*6a#^-AYPKF>cYHSK7&_NQk z3DCa^cx^aRb1#^l9CSG)K~wDOHB8VHWf66OE{yvc{2p6?e}tFQ5FTSXQ!~rdT>~F= zJ_(%7zVu!Wo(s;@gj?BnYi=+~Prw%t>n1yIC>F(!4JbAYe@blx8WlecpX^S^^bB7a zeurOC!#~*EJ?zF)@f-ZaHPg`gVK)qATZW=*yA$?94?m?=e%sSyN~v`Wpt%xqVf-wA zyv1o*T+wa@ibvM@Xw`<{X8bsj0TJyWL|I4{N z91nGWh}M}&y=`oOdCK#4&e-V0+$_^rZM$1y9;$VRBM9|SrH5A33#bOSa=^XpTy$Ok zniv4=)3@~u*kjhN=|%0WT+Bo5$Y$plNcMyW>-PzdVfgbH!|)dhcKA~(M>bVwl5~>RrBo`V%21_9NxL0z zujP}v`}_h{-r$?-+J;Y#jdo5f86M@=>rxUnc-TojB!RtjayNLmXo7YL-ZRaE!+cYdE>CebezB=Tr+7GiFBj0okLgC+-6G5HbZ{y8 zI}|ynqXP!ML4cB9P(QkjKK4F4^oeeDvU|4Wq;9DKPB7olDU@HBIo|wN`tIQqV^@+Dp5YVbJ9>q2ZeUzw7L7ux=@0c0 zr%w0R)5Nxr;OkxWafw3aEzeqWgnrGG{Fo>99naeX^7lOOJj}dFfd_ybzTshIdZ?0Q zDY~Kq^WHX}uYb*av3_sJ;_E#8a~s0o@8c~`@+s3*y!COd?SX-TpTNSQVbCsn$75%| ztB=Ssgaw{$3mm<~oYr3oAP*Zt6n>+Ma4s$}H%|V#r&a#8Cr7e^q`M!qJg8@mdFthF zctV`*pIIK$yW@v8=^f4x1eu>Z97B)jnXwMBA+QI=GMDvk(NLEjnz$1eOkH~Dp3pCy zb?ISOAqIQ4OW*G5Vn_6|*voo{<@fqsAx=wB1C!kmV)>h%`Lp*YWatAuSev z*gI(M(T9Ayq5(0B#16xdN$)N>JCSPX8OWLV8S=Hu-nx46+n!+excz#W_dM{;#$MAS z08BWrCNQRW5%e4#IE<(#^jjSB42F?;))OFMgL2y45zOKa%W=JXg=KLAzR@LXa5&kg z_2*YGt2=YVY>yr}&PK1`4ABA1bjPWfftbbD*EeuD@h~YpW^DuW7mwjfVVuDkx7HAt z6C?SnCwQi+fqsvS-2+&(S`Oak&4vav*U$h}E?N*ye(fFuw4-{i;kyLpNnEYPVljN; z_F22R{;?A|SUgUgsgAyh{k`irx;!9vcW2=QxZ-R}hWMSkv2XZus37{z4$3T z+Awsb0lIB=4?Ep3x2%6|G@sYf7i{{!26)D8z-i%+Ob6Fz{N6@I6ILj*u1a{~b_AZV`tPN*F{(m3|nlD$jvy4j+} zy&-vuP-?0+e8MFjJ~1&ld?MJi0nt=(JH+cRrqQ7go;lFi4KQqSlNVi}F;^yT4PT+d z$?T}NF*oQ6?~F6_Tz|Xq!c{@5jroyo@YkCH0^%TZh5^~%8eG4R*UH2G5 zzJ0ebv5UQ_2kXKY16MCGi2@8hcoZ~>e%NcuGk>vNcGJ@?32lX5PiRxPyTlUOB>AYt z39T0BrY;vdoR%d`;zf?3_$JAZo{@lAkXm<#S-mxOCro>QECG{3^npT0d_y!c*S&Yn zoV@c1Lpz(mSKQFD@1A?^8LDk!wzi0~_}?_QP4s@86)iw_cxTh#!}}%zDK`cAu&5Df zI@+}Q?SSL0>9`2FngG=n9UymlAV2JBa)+8vG`ShmXHARom$QFA3d(PKFxCv$Y&qM+ zY-{#bA#-`!j%Qit^OH^U6ami-6x(85o*2|^MdexZEw1hnXB)q%dDv|ZY{u`H$6<Z4yXEz&$Ju!<-vzrGw`i@vnE8ZjVPH6+hu$zM=Q(g;`)?yew5rf5c`}pw57|uy^ zXE!^53SdzfARu!DBuqdS3P`koEQKp_0f`q9e<2AHl29R8AS6*jA`_BjLbA%A2>pr3 zpUm|q^ZZGKKau*A`~1lY5g{THAR==_BuqpWib%AGEX60DL?k|x_=l39P!bwS7KDyk{~4sRgwit5~UyEg2;5-8zDN*81Ph5Enh2H>K`ar()0PT@h%l507Z70-5z0J% zKz;=6C!uJ7l62Aj3xiF0E!+*o;&|+?!WJ;gT3Y5ljA5H)s%XKSj-9-U9m>gXd6FTM z@Qgh=5okWr0x9P4-b8$GZTP@gm%@K||8N(_cebqS#U`Hdbo2je;cvAB22S{K-Uw!P zD?H327Wb-Nn$)wdmmwDrpqp%{g(Vl9I0P&=TgDy@92#$t&v=ISI{?$+;Gb)OGzw`> zq`|KFR?AoyC#2m5LF@g?!7~v5<{9yCX{<38#I&ePEzjH>zYNoed{MGALegYWM1~wP zkw_sDk**R<8T}(A2q~qZB7eoU>`X;Qx>2cAZ`+o=QI?jSow#sbm@zafGjq8ld2@Dl zyq}#%!r4AzNQ&*bP5!xLvBPXj3mvNhWSrR6&OYHWNB!GQfU;<5gLsFqIe@MtDq$U z6lvR-Jx1}OhX|>(Y|`z!P?p`MaiUFtveZ8{BSV@D;;b2LN>BuO{-I75>iD)2c#T2C_iU@6<5Ti;+d24odYx(WRzrK2#csoVf zTGX58lB*dWPsY_bTZ~)gkdB?kogJjJHLKM~ga)A^orFrGghFBNny3ZyNm}WS>{7Bc zENp2Q$;c?q$iPf1=)w_2DF}J#W?0zGm!_T%3wwTQp3EqlM_${Rvhy{vC3bP_CX%#l z{Vcx_vLIyvA?f$dUzRKL7p7vsLZt?2D3(raln7vAv4EoTRC!SZvo;U=UX~$?CQ)Jf zuqaeR7oT*;&fGSVlyN#^87VVnW=atcFTdorQkkqomRSh<&xxAjj~^o*5pTWq)-KGM zW}6YuqHH5kt`4otxHvzRJ`on3`#3;s6d1|!*pArcq-}oK{5F!jA$>zKQKTu;6j<)G zFG7I;)k}Be?m+FC8JS5WIZerQkgkr+o7WJ%q(Y)6Nx3_BEJS>|w1Xs}oeSxtaD8m2c75-X$c@V&#FUc47<@bg0BxK5ag7_X&C?yin7(zV0rx#9$ zH<`9UB=UtRe36LeNnH{W=qKpvy>M;nw!kkiWJ&7nscRQ{yLP-s|LtunZBf_N)~FiG z$}1|h)%sRVLsNTmm9D$O|v-|L@;DK^`TKlb4@+{>bkS zKJ)C;FLjmt;mQ9xdic;E|MbeM|MTG+`#KAsy6`h?t!vu;<4;%b+`2jQ{gog7@3#Be zjq47BlT1w#>%~i#Z45_5Ttw_RU8_N~vi5wd}c3s}-Wi0$Se9}vnUYU55@)ykCcg9|GO12&zH+|nJ@0-cvt%j2b^0QoU z>(Shq!o<2x;XU@c)9W(mx)YyH8aKVu8GCAGnumzyY-jA0#|AA!YsWG3PxGePwM|~x z@MoP!f>0MJU}WQq8Td#POv=4wYEvOxwz<0b3pMl;RPqhD%-_|+WGC)zG&7ZGfATVD!%?ONqY$LQRm^Y1( zOo01B9cuc#ItZ?N#Q2CB^O6zja*Sn0AY3fDVWhfLvrPXq1cXb*M8ODf4Cw{Ad}?)T zhiS^N!gSeiURp78*|3UyDXoz8&fv4$^iP2Q{`n_-;AE8qwjb_L7#P7m+X=%82W|Um zYOd#mfw;u!UX*e@!ARTTH5TuDR@d=Tg#%tgp1kWfTukl19SM)#u2#zq+=dH*id%iY zTo{nJxW4Ir*iz_L;2Rr@>>~oPfHv8lNW}J(>yH|(0x=QG4&LUZ>FrILMtmewqanGE zY+soaFWssugQCR)@$u5_&`)YrH9&I^N*E2Rqz|l5dQkeS<`VP?FF6ef+>9dzW_eDG bjhvgIw<>B> Date: Tue, 5 Feb 2008 02:40:54 +0000 Subject: [PATCH 083/327] Modified filename of the ROM files with proper case. --- doc/models.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/models.html b/doc/models.html index 25317b5..109ab2f 100644 --- a/doc/models.html +++ b/doc/models.html @@ -36,11 +36,11 @@

      Model Comparison

      ROM File - M100ROM.bin - M102ROM.bin - T200ROM.bin - PC8201ROM.bin - M10ROM.bin + M100rom.bin + M102rom.bin + T200rom.bin + PC8201rom.bin + M10rom.bin RAM File Size From be4fbdde9de8e1887a34090dad6d908ac051f7a4 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 5 Feb 2008 02:42:15 +0000 Subject: [PATCH 084/327] General documentation edits / updates. --- doc/emulation.html | 10 +++++----- doc/help.html | 2 +- doc/mail_list.html | 16 ++++++++++++++-- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/doc/emulation.html b/doc/emulation.html index 10fd9c3..b9a56a0 100644 --- a/doc/emulation.html +++ b/doc/emulation.html @@ -23,24 +23,24 @@

      Display

      Because of this, all software written for the Model T will also work on VirtualT, even if they make direct access to the LCD hardware.

      The LCD hardware implementation varies depending on the emulation model. For the T200, the LCD -uses a single single controller with 8K display RAM. On the other models, the LCD consists of 10 +uses a single controller with 8K display RAM. On the other models, the LCD consists of 10 independant controllers, each responsibile for a specific region of the display. With the exception of the T200 control chip's character generator ROM, the VirtualT emulation exactly matches the hardware at a register (I/O operation) level.

      Several features provided by the LCD emulation and can be accessed using the "Emulation->Display" menu items. These features are:

        -
      • Display Size: Allows magnification of the LCD (1x, 2x, 3x and 4x). This is direct pixel copying +
      • Display Size: Allows magnification of the LCD (1x, 2x, 3x and 4x). This is direct pixel copying of each pixel on the LCD. -
      • Solid Chars: Allows characters to be display with or without "spacing" between pixels. On the real +
      • Solid Chars: Allows characters to be display with or without "spacing" between pixels. On the real Model T, the old LCD techonology was coarse enough to see the spacing. This allows the user to choose between a "retro" look or a more readable look. -
      • Framed: This feature allows the user to view the LCD with the familiar "black frame" as seen on the +
      • Framed: This feature allows the user to view the LCD with the familiar "black frame" as seen on the original Model T, complete with function key labels, or as a simple window.

      Keyboard

      -

      The Model T keyboard, while very easy to use, has a non-standard of special and punctuation compared +

      The Model T keyboard, while very easy to use, has a non-standard layout of special symbols and punctuation compared with modern day keyboards. The keyboard is a simple scan matrix of keys with 8 scan rows and 9 scan columns. Each model uses the same keyscan arragement, but each assigns the key mappings differently. Plus the Model T has a few extra keys that are not present on today's keyboards, such as CODE and GRPH. diff --git a/doc/help.html b/doc/help.html index 3f059fe..5a9d845 100644 --- a/doc/help.html +++ b/doc/help.html @@ -92,7 +92,7 @@

      A Model 100/102/200 Emulator

      C - Software License

      - D - Model T Mailing List + D - Model T User Resources diff --git a/doc/mail_list.html b/doc/mail_list.html index aae0392..4524a06 100644 --- a/doc/mail_list.html +++ b/doc/mail_list.html @@ -1,12 +1,12 @@ - VirtualT Help - Mailing List + VirtualT Help - User Resources -

      Appendix D - Model T Mailing List

      +

      Appendix D - Model T User Resources

      This appendix details the Model T Mailing list and various Model T support sites. @@ -17,5 +17,17 @@


      +

      Club100

      +Club 100 is the original (and even considered "Official") Model 100 Users +Group website. + +

      Bitchin100

      +Bitchin 100 is maintained by John Hogerhuis and supports open source devleopment +for Model T applications. + +

      Web 8201

      +Web 8201 is a site maintained by Gary Weber dedicated to the NEC laptops. + +"Official" From 2ed16474c63414973b612da76a80ab7be3ab0744 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 5 Feb 2008 03:14:17 +0000 Subject: [PATCH 085/327] Modified directory name of vt_client. --- doc/host.html | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/doc/host.html b/doc/host.html index 8ec22cc..06b06b7 100644 --- a/doc/host.html +++ b/doc/host.html @@ -33,16 +33,17 @@

          main_virtualt_dir
              |
      -       |----virtualt  (application)  (virtualt.exe for windows)
      -       |----doc       (Help Files directory)
      -       |----src       (Source Code directory)
      -       |----M10       (Emulation directory)
      -       |----M100      (Emulation directory)
      -       |----M102      (Emulation directory)
      -       |----PC8201    (Emulation directory)
      -       |----T200      (Emulation directory)
      -       |----vt_client (Build directory for vt_client app)
      -       |----Projects  (IDE Projects directory)
      +       |----virtualt      (application)  (virtualt.exe for windows)
      +       |----vt_client     (application)  (vt_client.exe for windows)
      +       |----doc           (Help Files directory)
      +       |----src           (Source Code directory)
      +       |----M10           (Emulation directory)
      +       |----M100          (Emulation directory)
      +       |----M102          (Emulation directory)
      +       |----PC8201        (Emulation directory)
      +       |----T200          (Emulation directory)
      +       |----vt_client_src (Build directory for vt_client app)
      +       |----Projects      (IDE Projects directory)
       

      RAM Files

      From d58586147aa99fb6881cc375fd0a2db261a15301 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 5 Feb 2008 03:18:28 +0000 Subject: [PATCH 086/327] Modified name of the vt_client build directory. --- doc/build.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/build.html b/doc/build.html index aad6e96..2c09579 100644 --- a/doc/build.html +++ b/doc/build.html @@ -50,11 +50,11 @@

      Building VirtualT

      following files and subdirectories:

        -
      • GNUMakefile - The makefile for the Linux make utility -
      • src - Subdirectory of all VirtualT source files -
      • doc - Subdirecotry with all help files and images -
      • ROMs - Subdirectory with ROM images -
      • vt_client - Subdirectory for the vt_client socket application for Windows builds +
      • GNUMakefile - The makefile for the Linux make utility +
      • src - Subdirectory of all VirtualT source files +
      • doc - Subdirecotry with all help files and images +
      • ROMs - Subdirectory with ROM images +
      • vt_client_src - Subdirectory for the vt_client socket application for Windows builds
    • Build VirtualT by changing to the root VirtualT directory and typing "make". From af88edcb445e72d040b72f31c3a1fa8aab0c1b5c Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Thu, 7 Feb 2008 05:46:22 +0000 Subject: [PATCH 087/327] Removed test code I had added while investigating the speed on the Mac. Was preventing CPU Friendly speeds from being CPU friendly. --- src/display.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/display.cpp b/src/display.cpp index a21b927..c7ddf25 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -1412,13 +1412,11 @@ void power_down() void process_windows_event() { - Fl::check(); - return; if (gOsDelay) #ifdef WIN32 Fl::wait(0.001); #elif defined(__APPLE__) - Fl::check(); + Fl::check(); #else Fl::wait(0.00001); #endif From ddf599a7d1d04206b5221d157959815b23427941 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Thu, 7 Feb 2008 09:21:23 +0000 Subject: [PATCH 088/327] Documentation update. Added socket interface docs and corrected some typos. --- doc/build.html | 4 +- doc/help.html | 2 +- doc/linker_ref.html | 4 +- doc/models.html | 2 +- doc/sockets.html | 560 +++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 565 insertions(+), 7 deletions(-) diff --git a/doc/build.html b/doc/build.html index 2c09579..0f0d512 100644 --- a/doc/build.html +++ b/doc/build.html @@ -113,12 +113,12 @@

      Installing VirtualT

      Launching and Using VirtualT

      For the most part, VirtualT is a GUI driven application with all features configurable from within the GUI. The only exception to this is the socket interface used for remote control and -debugging. To enable the socket interface, VirtualT must be envoked with a command-line option +debugging. To enable the socket interface, VirtualT must be invoked with a command-line option to specify the socket port as follows:

        virtualt -p port_number

        NOTE:  On Windows platforms, the Windows firewall sometimes blocks unkown ports and may
        -need to be configured.  Sometimes simply envoking VirtualT with the '-p' option a second time
        +need to be configured.  Sometimes simply invoking VirtualT with the '-p' option a second time
         will "open" the port.

      This will cause VirtualT to launch a socket listener thread for remote control appliations as diff --git a/doc/help.html b/doc/help.html index 5a9d845..2f27e95 100644 --- a/doc/help.html +++ b/doc/help.html @@ -54,7 +54,7 @@

      A Model 100/102/200 Emulator

    6 - Socket Interface

    to halt the CPU emulation and activate the edit fields.

    In addition to displaying CPU registers, the dialog provides limited debug capability -and a disassembly window. The debug features consist of Stop, Step and Run buttons and -four edit fields for specifying debug breakpoints and enabling and disabling them. +and a disassembly window. The debug features consist of Stop, Step Step Over and Run buttons and +four edit fields for specifying debug breakpoints and enabling and disabling them. Also, +the debugger can be configured to ignore ISR debugging which will prevent single step operations +from stepping into an interrupt handler. The ISR will be allowed to complete before the single +step operation is considered complete.

    From 2f1768bb67382fd7deadea62311db3d2699aef4c Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Thu, 25 Sep 2008 15:24:07 +0000 Subject: [PATCH 145/327] Added emulation for clock updates, bug fixes for improper Open COM port error message, etc. See release notes for release 1.3. --- src/VirtualT.h | 2 +- src/clock.cpp | 631 ++++++++++++++++++++++++++++++++++++++++++++++++ src/clock.h | 70 ++++++ src/display.cpp | 5 + src/io.c | 198 ++------------- src/m100emu.c | 3 + src/remote.cpp | 10 +- src/serial.c | 28 ++- src/setup.cpp | 64 ++++- src/sound.c | 6 +- 10 files changed, 816 insertions(+), 201 deletions(-) create mode 100644 src/clock.cpp create mode 100644 src/clock.h diff --git a/src/VirtualT.h b/src/VirtualT.h index 030b10a..8611e3a 100644 --- a/src/VirtualT.h +++ b/src/VirtualT.h @@ -31,7 +31,7 @@ #ifndef _VIRTUALT_H_ #define _VIRTUALT_H_ -#define VERSION "1.2" +#define VERSION "1.3" enum { MODEL_M100 diff --git a/src/clock.cpp b/src/clock.cpp new file mode 100644 index 0000000..a24f333 --- /dev/null +++ b/src/clock.cpp @@ -0,0 +1,631 @@ +/* clock.cpp */ + +/* $Id$ */ + +/* + * Copyright 2008 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "VirtualT.h" +#include "gen_defs.h" +#include "roms.h" +#include "io.h" +#include "setup.h" +#include "m100emu.h" +#include "memory.h" +#include "clock.h" + +uchar gClockMode = 255; +uchar gRp5c01_mode; +uchar gRp5c01_data[4][13]; +time_t clock_time = 0; +time_t last_clock_time = 1; +time_t gStartTime = 0; +time_t gRefTime = 0; +uchar clock_sr[5]; /* 40 Bit shift register */ +uchar clock_sr_save[5]; /* 40 Bit shift register backup storage */ +uchar clock_sr_index = 0; +int gClockTimingMode; +int gTimeElapse; +int gReload; +clock_ctrl_t gClockCtrl; +extern RomDescription_t *gStdRomDesc; +extern Fl_Preferences virtualt_prefs; + +extern "C" +{ +struct tm *mytime ; +uchar clock_serial_out = 0; + +void init_clock(void) +{ + /* Do clock initialization stuff */ +} + +/* +=================================================================== +Handle commands written to the uPD1990AC clock chip for models +other than T200. +=================================================================== +*/ +void pd1990ac_chip_cmd(uchar val) +{ + static int clk_cnt = 1; + time_t time_delta; + struct tm when; + int x; + + gClockMode = val & 0x07; + + /* Clock chip command strobe */ + switch (gClockMode) + { + case 0: /* NOP */ + break; + case 1: /* Serial Shift */ + clock_serial_out = clock_sr[0] & 0x01; +// clock_sr_index = 0; + break; + case 2: /* Write Clock chip */ + // Reset the start time + gStartTime = time(&gStartTime); + mytime = localtime(&gStartTime); + + /* Update Clock Chip Shift register Seconds */ + when.tm_sec = (clock_sr[0]& 0x0F) + (clock_sr[0] >> 4) * 10; + + /* Minutes */ + when.tm_min = (clock_sr[1] & 0x0F) + (clock_sr[1] >> 4) * 10; + + /* Hours */ + when.tm_hour = (clock_sr[2] & 0x0F) + (clock_sr[2] >> 4) * 10; + + /* Day of month */ + when.tm_mday = (clock_sr[3] & 0x0F) + (clock_sr[3] >> 4) * 10; + + /* Day of week */ + when.tm_wday = clock_sr[4] & 0x0F; + + /* Month */ + when.tm_mon = (clock_sr[4] >> 4) - 1; + + when.tm_isdst = -1; + when.tm_year = mytime->tm_year; + + gRefTime = mktime(&when); + + for (x = 0; x < 5; x++) + clock_sr_save[x] = clock_sr[x]; + + break; + case 3: /* Read clock chip */ + for (x = 0; x < 5; x++) + clock_sr[x] = clock_sr_save[x]; + + // Get current time and test if it changed from the last check + clock_time = time(&clock_time); + if (clock_time == last_clock_time) + break; + + // Calculate the time delta from start of program + if (gStartTime == 0) + { + gStartTime = clock_time; + gRefTime = clock_time; + } + time_delta = clock_time - gStartTime; + last_clock_time = clock_time; + clock_time = gRefTime + time_delta; + mytime = localtime(&clock_time); + + /* Update Clock Chip Shift register Seconds */ + clock_sr[0] = mytime->tm_sec % 10; + clock_sr[0] |= (mytime->tm_sec / 10) << 4; + + /* Minutes */ + clock_sr[1] = mytime->tm_min % 10; + clock_sr[1] |= (mytime->tm_min / 10) << 4; + + /* Hours */ + clock_sr[2] = mytime->tm_hour % 10; + clock_sr[2] |= (mytime->tm_hour / 10) << 4; + + /* Day of month */ + clock_sr[3] = mytime->tm_mday % 10; + clock_sr[3] |= (mytime->tm_mday / 10) << 4; + + /* Day of week */ + clock_sr[4] = (mytime->tm_wday) % 10; + + /* Month */ + clock_sr[4] |= (mytime->tm_mon + 1) << 4; + + for (x = 0; x < 5; x++) + clock_sr_save[x] = clock_sr[x]; +// clock_sr_index = 0; + + if (gModel == MODEL_PC8201) + { + if ((get_memory8(gStdRomDesc->sYear+1) == '8') && (get_memory8(gStdRomDesc->sYear) == '3')) + { + set_memory8(gStdRomDesc->sYear, (unsigned char) (mytime->tm_year % 10) + '0'); + set_memory8(gStdRomDesc->sYear+1, (unsigned char) ((mytime->tm_year % 100) / 10) + '0'); + } + } + else + { + if ((get_memory8(gStdRomDesc->sYear+1) == 0) && (get_memory8(gStdRomDesc->sYear) == 0)) + { + set_memory8(gStdRomDesc->sYear, (unsigned char) (mytime->tm_year % 10)); + set_memory8(gStdRomDesc->sYear+1, (unsigned char) ((mytime->tm_year % 100) / 10)); + } + } + } +} + +/* +=================================================================== +Handle writes to the T200 clock chip, RP5C01. +=================================================================== +*/ +void rp5c01_write(uchar port, uchar val) +{ + struct tm when; + + /* Test if writing to Mode Register */ + if (port == 0x9D) + { + if (gModel == MODEL_T200) + gRp5c01_mode = val; + } + else + { + /* Save write data to array */ + gRp5c01_data[gRp5c01_mode & 0x03][port & 0x0F] = val; + + /* Check if the time is being set */ + if ((gRp5c01_mode & 3) == 0) + { + // Check if the last byte is being written and update + // the gStartTime if it is using the new time data + if (port == 0x9C) + { + /* Update Clock Chip Shift register Seconds */ + when.tm_sec = gRp5c01_data[0][0]+ gRp5c01_data[0][1] * 10;; + + /* Minutes */ + when.tm_min = gRp5c01_data[0][2] + gRp5c01_data[0][3] * 10; + + /* Hours */ + /* Test if we are in 12 or 24 hour mode */ + if (gRp5c01_data[1][10] == 1) + { + when.tm_hour = gRp5c01_data[0][4] + gRp5c01_data[0][5] * 10; + } + else + { + when.tm_hour = gRp5c01_data[0][4] + (gRp5c01_data[0][5] & 0x01) * 10 + + (gRp5c01_data[0][5] & 0x02) ? 12 : 0; + } + + /* Day of week */ + when.tm_wday = gRp5c01_data[0][6]; + + /* Day of month */ + when.tm_mday = gRp5c01_data[0][7] + gRp5c01_data[0][8] * 10; + + /* Month */ + when.tm_mon = (gRp5c01_data[0][9] + gRp5c01_data[0][10] * 10)-1; + + /* Year */ + when.tm_year = gRp5c01_data[0][11] + gRp5c01_data[0][12] * 10 + 100; + + when.tm_isdst = -1; + when.tm_yday = 1; + + gRefTime = mktime(&when); + } + /* Add code here to update the system time */ + } + /* Check if the alarm is being set */ + else if ((gRp5c01_mode& 3) == 1) + { + } + } +} + +/* +=================================================================== +Handle reads from the T200 clock chip, RP5C01. +=================================================================== +*/ +uchar rp5c01_read(uchar port) +{ + time_t time_delta; + uchar ret = 0; + + if (gModel == MODEL_T200) + { + /* Test for clock Mode Register */ + if (port == 0x9D) + return gRp5c01_mode; + + /* Check if the time is being set */ + if ((gRp5c01_mode & 3) == 0) + { + /* Read system clock and update "chip" */ + if (port == 0x90) + { + clock_time = time(&clock_time); + if (clock_time != last_clock_time) + { + // Check if we just started up + if (gStartTime == 0) + { + gStartTime = clock_time; + gRefTime = clock_time; + } + + // Calculated emulated time + last_clock_time = clock_time; + time_delta = clock_time - gStartTime; + clock_time = gRefTime + time_delta; + mytime = localtime(&clock_time); + + /* Update Clock Chip Shift register Seconds */ + gRp5c01_data[0][0] = mytime->tm_sec % 10; + gRp5c01_data[0][1] = mytime->tm_sec / 10; + + /* Minutes */ + gRp5c01_data[0][2] = mytime->tm_min % 10; + gRp5c01_data[0][3] = mytime->tm_min / 10; + + /* Hours */ + /* Test if we are in 12 or 24 hour mode */ + if (gRp5c01_data[1][10] == 1) + { + gRp5c01_data[0][4] = mytime->tm_hour % 10; + gRp5c01_data[0][5] = mytime->tm_hour / 10; + } + else + { + gRp5c01_data[0][4] = (mytime->tm_hour % 12) % 10; + gRp5c01_data[0][5] = (mytime->tm_hour % 12) / 10; + if (mytime->tm_hour >=12) + gRp5c01_data[0][5] |= 2; + } + + /* Day of week */ + gRp5c01_data[0][6] = mytime->tm_wday; + + /* Day of month */ + gRp5c01_data[0][7] = mytime->tm_mday % 10; + gRp5c01_data[0][8] = mytime->tm_mday / 10; + + /* Month */ + gRp5c01_data[0][9] = (mytime->tm_mon+1) % 10; + gRp5c01_data[0][10] = (mytime->tm_mon+1) / 10; + + /* Year */ + gRp5c01_data[0][11] = mytime->tm_year % 10; + gRp5c01_data[0][12] = (mytime->tm_year % 100) / 10; + } + } + } + /* Check if the alarm is being set */ + else if ((gRp5c01_mode & 3) == 1) + { + } + + /* Return data stored in the RP5C01 "chip" */ + ret = gRp5c01_data[gRp5c01_mode & 0x03][port & 0x0F]; + } + + return ret; +} + +/* +=================================================================== +Handle a pulse on the chip's CLK pin. This causes the shift +register to shift 1 bit if in the Shift Mode. +=================================================================== +*/ +void pd1990ac_clk_pulse(uchar val) +{ + if (gClockMode == 1) + { + /* Perform a shift operation */ + clock_sr[0] >>= 1; + clock_sr[0] |= clock_sr[1] & 1 ? 0x80 : 0; + clock_sr[1] >>= 1; + clock_sr[1] |= clock_sr[2] & 1 ? 0x80 : 0; + clock_sr[2] >>= 1; + clock_sr[2] |= clock_sr[3] & 1 ? 0x80 : 0; + clock_sr[3] >>= 1; + clock_sr[3] |= clock_sr[4] & 1 ? 0x80 : 0; + clock_sr[4] >>= 1; + clock_sr[4] |= val & 0x10 ? 0x80 : 0; + clock_serial_out = clock_sr[0] & 1; + } +} + +/* +============================================================================= +save_model_time: Saves the emulated time for the current model. +============================================================================= +*/ +void save_model_time(void) +{ + char str[16]; + char pref[64]; + time_t now; + + get_model_string(str, gModel); + + // Save Reference Time + strcpy(pref, str); + strcat(pref, "_RefTime"); + virtualt_prefs.set(pref, ctime(&gRefTime)); + printf(ctime(&gRefTime)); + + // Save Start Time + strcpy(pref, str); + strcat(pref, "_StartTime"); + virtualt_prefs.set(pref, ctime(&gStartTime)); + + // Save Suspend Time + now = time(&now); + strcpy(pref, str); + strcat(pref, "_SuspendTime"); + virtualt_prefs.set(pref, ctime(&now)); +} + +/* +============================================================================= +convert_ctime: Convert from string time to time_t. +============================================================================= +*/ +char *gMonths[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +time_t convert_ctime(char* stime) +{ + char month[5]; // Storage for month + struct tm tm_time; // Used to build time_t + int x; + time_t convTime; // Converted time + + // If the string is blank, return current time + if ((strlen(stime) == 0) || (strlen(stime) < 24)) + { + convTime = time(&convTime); + return convTime; + } + + // Convert month from string to integer + tm_time.tm_mon = 0; + strncpy(month, &stime[4], 3); // Get month + month[3] = 0; + for (x = 0; x < 12; x++) + { + if (strcmp(month, gMonths[x]) == 0) + { + // Save month in tm struct + tm_time.tm_mon = x; + break; + } + } + + tm_time.tm_mday = atoi(&stime[8]); // Convert day + tm_time.tm_hour = atoi(&stime[11]); // Convert hours + tm_time.tm_min = atoi(&stime[14]); // Convert minutes + tm_time.tm_sec = atoi(&stime[17]); // Convert seconds + tm_time.tm_year = atoi(&stime[20]); // Convert year + tm_time.tm_year -= 1900; + + // Convert to time_t format + convTime = mktime(&tm_time); + return convTime; +} + +/* +============================================================================= +get_model_time: Gets the emulated time for the current model. +============================================================================= +*/ +void get_model_time(void) +{ + char str[16]; + char pref[64]; + char stringtime[30]; + time_t now, suspendTime; + + get_model_string(str, gModel); + + // Save Reference Time + strcpy(pref, str); + strcat(pref, "_RefTime"); + virtualt_prefs.get(pref, stringtime, "", 30); + gRefTime = convert_ctime(stringtime); + + // Save Start Time + strcpy(pref, str); + strcat(pref, "_StartTime"); + virtualt_prefs.get(pref, stringtime, "", 30); + gStartTime = convert_ctime(stringtime); + + // Save Suspend Time + strcpy(pref, str); + strcat(pref, "_SuspendTime"); + virtualt_prefs.get(pref, stringtime, "", 30); + suspendTime = convert_ctime(stringtime); + + // Set the Emulation time base on preferences + now = time(&now); + if (gClockTimingMode == CLOCK_MODE_SYS) + { + // Reset the clock to current time + if (gReload) + { + gRefTime = now; + gStartTime = now; + clock_time = now; + } + } + else + { + // Use emulated time. Test if time elapses during suspend + if (!gTimeElapse) + { + // Time doesn't elapse during suspend. Therefore we must + // update the gStartTime variable to add in the elapsed time + // so the calculation now - gStartTime won't reflect the + // actual elapsed time since the last suspension + time_t delta = suspendTime - gStartTime; + gStartTime = now - delta; + } + } +} + +} // End of Extern "C" items + +/* +======================================================= +Callback routines for radio butons +======================================================= +*/ +void cb_clock_radio_sys(Fl_Widget* w, void*) +{ + gClockCtrl.pReload->activate(); + gClockCtrl.pTimeElapse->deactivate(); +} + +/* +======================================================= +Callback routines for radio butons +======================================================= +*/ +void cb_clock_radio_emul(Fl_Widget* w, void*) +{ + gClockCtrl.pReload->deactivate(); + gClockCtrl.pTimeElapse->activate(); +} + +/* +======================================================= +Build the CLOCK tab on the Peripheral Setup dialog +======================================================= +*/ +void build_clock_setup_tab(void) +{ + Fl_Box* pText = new Fl_Box(20, 10, 60, 80, "Clock operation upon power-up"); + pText->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + // Create Radio button for "Host Time" + gClockCtrl.pSysTime = new Fl_Round_Button(20, 70, 200, 20, "Reset to Host Time"); + gClockCtrl.pSysTime->type(FL_RADIO_BUTTON); + gClockCtrl.pSysTime->callback(cb_clock_radio_sys); + + gClockCtrl.pReload = new Fl_Check_Button(45, 95, 250, 20, "Reset time when changing models"); + gClockCtrl.pReload->value(gReload); + if (gClockTimingMode != CLOCK_MODE_SYS) + gClockCtrl.pReload->deactivate(); + + // Create Radio button for Model Clock Time + gClockCtrl.pEmulTime = new Fl_Round_Button(20, 130, 200, 20, "Restore Emulated Time"); + gClockCtrl.pEmulTime->type(FL_RADIO_BUTTON); + gClockCtrl.pEmulTime->callback(cb_clock_radio_emul); + + gClockCtrl.pTimeElapse = new Fl_Check_Button(45, 155, 270, 20, "Time elapses while emulation stopped"); + gClockCtrl.pTimeElapse->value(gTimeElapse); + if (gClockTimingMode != CLOCK_MODE_EMUL) + gClockCtrl.pTimeElapse->deactivate(); + + // Select the correct radio button base on preferences + if (gClockTimingMode == CLOCK_MODE_SYS) + gClockCtrl.pSysTime->value(1); + else if (gClockTimingMode == CLOCK_MODE_EMUL) + gClockCtrl.pEmulTime->value(1); +} + +/* +============================================================================= +load_clock_preferences: Loads the emulated printer preferences from the Host. +============================================================================= +*/ +void load_clock_preferences(Fl_Preferences* pPref) +{ + // Load the preferences + pPref->get("ClockTimingMode", gClockTimingMode, CLOCK_MODE_SYS); + pPref->get("ClockReload", gReload, 1); + pPref->get("ClockTimeElapse", gTimeElapse, 0); +} + +/* +============================================================================= +save_clock_preferences: Saves the emulated printer preferences to the Host. +============================================================================= +*/ +void save_clock_preferences(Fl_Preferences* pPref) +{ + pPref->set("ClockTimingMode", gClockTimingMode); + pPref->set("ClockReload", gReload); + pPref->set("ClockTimeElapse", gTimeElapse); +} + + +/* +============================================================================= +get_clock_options: Gets the LPT options from the Dialog Tab and saves them + to the preferences. This routien is called when the + user selects "Ok". +============================================================================= +*/ +void get_clock_options() +{ + // End any active print sessions + // Check if Timing Mode is "System Timing" + if (gClockCtrl.pSysTime->value()) + gClockTimingMode = CLOCK_MODE_SYS; + else + gClockTimingMode = CLOCK_MODE_EMUL; + + // Check if Reload option is selectd + gReload = gClockCtrl.pReload->value(); + + // Check if Time Elapse if selected + gTimeElapse = gClockCtrl.pTimeElapse->value(); +} + diff --git a/src/clock.h b/src/clock.h new file mode 100644 index 0000000..b60b670 --- /dev/null +++ b/src/clock.h @@ -0,0 +1,70 @@ +/* clock.h */ + +/* $Id$ */ + +/* + * Copyright 2008 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CLOCK_H +#define CLOCK_H + +#ifdef __cplusplus +extern "C" { +#endif + +void init_clock (void); +void rp5c01_write (uchar port, uchar val); +uchar rp5c01_read (uchar val); +void pd1990ac_chip_cmd (uchar val); +void pd1990ac_clk_pulse (uchar val); +void save_model_time(void); +void get_model_time(void); + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus + +void load_clock_preferences(Fl_Preferences* pPref); +void save_clock_preferences(Fl_Preferences* pPref); +void get_clock_options(void); +void build_clock_setup_tab(void); + +typedef struct +{ + Fl_Round_Button* pSysTime; + Fl_Round_Button* pEmulTime; + Fl_Check_Button* pReload; + Fl_Check_Button* pTimeElapse; +} clock_ctrl_t; + +#define CLOCK_MODE_SYS 1 +#define CLOCK_MODE_EMUL 2 + +#endif + + +#endif diff --git a/src/display.cpp b/src/display.cpp index 2b3a5dc..b5363e3 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -59,6 +59,7 @@ #include "rememcfg.h" #include "lpt.h" #include "fl_action_icon.h" +#include "clock.h" extern "C" { extern RomDescription_t gM100_Desc; @@ -784,6 +785,9 @@ void switch_model(int model) save_ram(); free_mem(); + // Save time for current model + save_model_time(); + /* Switch to new model */ gModel = model; virtualt_prefs.set("Model",gModel); @@ -793,6 +797,7 @@ void switch_model(int model) /* Load Memory preferences */ load_memory_preferences(); init_mem(); + get_model_time(); gRomSize = 32768; /* Set pointer to ROM Description */ diff --git a/src/io.c b/src/io.c index 7c5c991..4858c9b 100644 --- a/src/io.c +++ b/src/io.c @@ -43,6 +43,7 @@ #include "memory.h" #include "sound.h" #include "lpt.h" +#include "clock.h" uchar lcd[10][256]; uchar lcdpointers[10]={0,0,0,0,0,0,0,0,0,0}; @@ -59,22 +60,15 @@ uchar ioD0; /* D0-DF io for T200 */ uchar t200_ir; /* Instruction register */ uchar t200_mcr; /* Mode Control Register */ uchar t200_uart_state = 0; -uchar gRp5c01_mode; -uchar gRp5c01_data[4][13]; uchar keyscan[9] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; char keyin[9]; uint lcdbits=0; -time_t clock_time = 0; -time_t last_clock_time = 1; -struct tm *mytime ; unsigned long gSpecialKeys = 0; unsigned char gKeyStates[128]; int gDelayUpdateKeys = 0; int gDelayCount = 0; -uchar clock_sr[5]; /* 40 Bit shift register */ -uchar clock_sr_index = 0; -uchar clock_serial_out = 0; +extern uchar clock_serial_out; extern int gRomBank; extern RomDescription_t *gStdRomDesc; @@ -251,6 +245,7 @@ void init_io(void) /* Initialize serial I/O structures */ t200_uart_state = 0; /* Confiture 8152 to Mode state */ ser_init(); + init_clock(); /* Setup callback for serial I/O */ ser_set_callback(cb_int65); @@ -264,6 +259,7 @@ void init_io(void) ioBC = 0; /* Low byte of 14-bit timer */ ioBD = 0; /* High byte of 14-bit timer */ ioD0 = 0; /* D0-DF io for T200 */ + } void deinit_io(void) @@ -272,78 +268,6 @@ void deinit_io(void) ser_deinit(); } -void clock_chip_cmd(void) -{ - static int clk_cnt = 1; - - /* Clock chip command strobe */ - switch (ioB9 & 0x07) - { - case 0: /* NOP */ - break; - case 1: /* Serial Shift */ - clock_serial_out = clock_sr[0] & 0x01; - clock_sr_index = 0; - break; - case 2: /* Write Clock chip */ - clock_sr_index = 0; - break; - case 3: /* Read clock chip */ - if (--clk_cnt > 0) - break; - - clk_cnt = 20; - - clock_time = time(&clock_time); - if (clock_time == last_clock_time) - break; - - last_clock_time = clock_time; - mytime = localtime(&clock_time); - - /* Update Clock Chip Shift register Seconds */ - clock_sr[0] = mytime->tm_sec % 10; - clock_sr[0] |= (mytime->tm_sec / 10) << 4; - - /* Minutes */ - clock_sr[1] = mytime->tm_min % 10; - clock_sr[1] |= (mytime->tm_min / 10) << 4; - - /* Hours */ - clock_sr[2] = mytime->tm_hour % 10; - clock_sr[2] |= (mytime->tm_hour / 10) << 4; - - /* Day of month */ - clock_sr[3] = mytime->tm_mday % 10; - clock_sr[3] |= (mytime->tm_mday / 10) << 4; - - /* Day of week */ - clock_sr[4] = (mytime->tm_wday) % 10; - - /* Month */ - clock_sr[4] |= (mytime->tm_mon + 1) << 4; - - clock_sr_index = 0; - - if (gModel == MODEL_PC8201) - { - if ((get_memory8(gStdRomDesc->sYear+1) == '8') && (get_memory8(gStdRomDesc->sYear) == '3')) - { - set_memory8(gStdRomDesc->sYear, (unsigned char) (mytime->tm_year % 10) + '0'); - set_memory8(gStdRomDesc->sYear+1, (unsigned char) ((mytime->tm_year % 100) / 10) + '0'); - } - } - else - { - if ((get_memory8(gStdRomDesc->sYear+1) == 0) && (get_memory8(gStdRomDesc->sYear) == 0)) - { - set_memory8(gStdRomDesc->sYear, (unsigned char) (mytime->tm_year % 10)); - set_memory8(gStdRomDesc->sYear+1, (unsigned char) ((mytime->tm_year % 100) / 10)); - } - } - } -} - void show_remem_mode(void) { char temp[20]; @@ -403,7 +327,7 @@ void out(uchar port, uchar val) { if ((val & 0x10) && !(io90 & 0x10)) { - clock_chip_cmd(); + pd1990ac_chip_cmd(ioB9); break; } @@ -428,25 +352,9 @@ void out(uchar port, uchar val) case 0x9A: case 0x9B: case 0x9C: - if (gModel == MODEL_T200) - { - gRp5c01_data[gRp5c01_mode & 0x03][port & 0x0F] = val; - - /* Check if the time is being set */ - if (gRp5c01_mode == 0) - { - /* Add code here to update the system time */ - } - /* Check if the alarm is being set */ - else if (gRp5c01_mode == 1) - { - } - } - break; - case 0x9D: /* Clock chip Mode Register */ if (gModel == MODEL_T200) - gRp5c01_mode = val & 0x03; + rp5c01_write(port, val); break; case 0x9E: @@ -521,13 +429,8 @@ void out(uchar port, uchar val) /* Check for clock chip serial shift clock */ if ((val & 0x08) && !(ioB9 & 0x08)) { - - /* Increment shift register index */ - clock_sr_index++; - - /* Update clock chip output bit based on index */ - clock_serial_out = clock_sr[clock_sr_index / 8] & (0x01 << clock_sr_index % 8) ? 1 : 0; - + /* Call routine to process the CLK pulse */ + pd1990ac_clk_pulse(val); } ioB9 = val; return; @@ -731,7 +634,7 @@ void out(uchar port, uchar val) } else { - /* ROM and RAM bank seleciton bits */ + /* ROM and RAM bank selection bits */ /* Check for a change in the current RAM bank */ if ((ioD0 & 0x0C) != (val & 0x0C)) { @@ -779,8 +682,7 @@ void out(uchar port, uchar val) /* Check for Clock Chip strobe */ if ((val & 0x04) && !(ioE8 & 0x04)) { - clock_chip_cmd(); -// break; + pd1990ac_chip_cmd(ioB9); } /* Check for data to the printer */ @@ -789,13 +691,12 @@ void out(uchar port, uchar val) } else { - // T200 Printer port is on Bit 0, not Bit 1 + // T200 Printer port STROBE is on Bit 0, not Bit 1 if ((val & 0x01) && !(ioE8 & 0x01)) send_to_lpt(ioB9); } ioE8 = val; - return; case 0xF0: /* LCD display data bus (F0H-FFH same) */ @@ -877,8 +778,8 @@ void out(uchar port, uchar val) int inport(uchar port) { int c; - unsigned char ret; - unsigned char flags; + unsigned char ret; + unsigned char flags; switch(port) { case REMEM_SECTOR_PORT: /* ReMem Sector access port */ @@ -908,73 +809,8 @@ int inport(uchar port) case 0x9A: case 0x9B: case 0x9C: - if (gModel == MODEL_T200) - { - /* Check if the time is being set */ - if (gRp5c01_mode == 0) - { - /* Read system clock and update "chip" */ - if (port == 0x90) - { - clock_time = time(&clock_time); - if (clock_time != last_clock_time) - { - last_clock_time = clock_time; - mytime = localtime(&clock_time); - - /* Update Clock Chip Shift register Seconds */ - gRp5c01_data[0][0] = mytime->tm_sec % 10; - gRp5c01_data[0][1] = mytime->tm_sec / 10; - - /* Minutes */ - gRp5c01_data[0][2] = mytime->tm_min % 10; - gRp5c01_data[0][3] = mytime->tm_min / 10; - - /* Hours */ - /* Test if we are in 12 or 24 hour mode */ - if (gRp5c01_data[1][10] == 1) - { - gRp5c01_data[0][4] = mytime->tm_hour % 10; - gRp5c01_data[0][5] = mytime->tm_hour / 10; - } - else - { - gRp5c01_data[0][4] = (mytime->tm_hour % 12) % 10; - gRp5c01_data[0][5] = (mytime->tm_hour % 12) / 10; - if (mytime->tm_hour >=12) - gRp5c01_data[0][5] |= 2; - } - - /* Day of week */ - gRp5c01_data[0][6] = mytime->tm_wday; - - /* Day of month */ - gRp5c01_data[0][7] = mytime->tm_mday % 10; - gRp5c01_data[0][8] = mytime->tm_mday / 10; - - /* Month */ - gRp5c01_data[0][9] = (mytime->tm_mon+1) % 10; - gRp5c01_data[0][10] = (mytime->tm_mon+1) / 10; - - /* Year */ - gRp5c01_data[0][11] = mytime->tm_year % 10; - gRp5c01_data[0][12] = (mytime->tm_year % 100) / 10; - } - } - } - /* Check if the alarm is being set */ - else if (gRp5c01_mode == 1) - { - } - - /* Return data stored in the RP5C01 "chip" */ - ret = gRp5c01_data[gRp5c01_mode & 0x03][port & 0x0F]; - return ret; - } - return 0;; - case 0x9D: /* Clock chip Mode Register */ - return gRp5c01_mode; + return rp5c01_read(port); case 0x9E: case 0x9F: @@ -1075,10 +911,8 @@ int inport(uchar port) else { ret |= (flags & (SER_FLAG_OVERRUN | SER_FLAG_FRAME_ERR)) << 3; - ret |= flags & SER_FLAG_PARITY_ERR; - ret |= (flags & SER_FLAG_TX_EMPTY); - ret |= (flags & SER_FLAG_TX_EMPTY) << 2; - ret |= (flags & SER_FLAG_DSR) << 1; + ret |= flags & (SER_FLAG_PARITY_ERR | SER_FLAG_TX_EMPTY); + ret |= (flags & (SER_FLAG_TX_EMPTY | SER_FLAG_DSR)) << 2; } } else diff --git a/src/m100emu.c b/src/m100emu.c index 1ab79ce..fecded1 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -58,6 +58,7 @@ #include "remote.h" #include "serial.h" #include "lpt.h" +#include "clock.h" int fullspeed=0; int gModel = MODEL_M100; @@ -1117,12 +1118,14 @@ int main(int argc, char **argv) init_cpu(); /* Initialize the CPU */ init_remote(); /* Initialize the remote control */ init_lpt(); /* Initialize the printer subsystem */ + get_model_time(); /* Load the emulated time for current model */ /* Perform Emulation */ emulate(); /* Main emulation loop */ /* Save RAM contents after emulation */ save_ram(); + save_model_time(); /* Save the emulated time */ /* Cleanup */ deinit_io(); /* Deinitialize I/O */ diff --git a/src/remote.cpp b/src/remote.cpp index 2b0047e..0d69cb6 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -140,12 +140,14 @@ std::string cmd_help(ServerSocket& sock) sock << " run\n"; sock << " set_break(sb) address [main opt mplan ram ram2 ram3]\n"; sock << " speed [2.4 friendly max]\n"; + sock << " status\n"; sock << " step(s) [count]\n"; sock << " step_over(so) [count]\n"; sock << " string address\n"; sock << " terminate\n"; sock << " write_mem(wm) address [data data data ...]\n"; sock << " write_reg(wr) [A=xx B=xx hl=xx ...]\n"; + sock << " x [lines]\n"; return "Ok"; } @@ -2158,8 +2160,6 @@ Lcd_mon command: Enables or disables LCD monitoring. */ std::string cmd_debug_isr(ServerSocket& sock, std::string& args) { - int c; - // Get breakpoint arguments if (args == "") { @@ -2545,6 +2545,12 @@ std::string process_command(ServerSocket& sock, std::string cmd) else if ((cmd_word == "debug_isr") || (cmd_word == "isr")) ret = cmd_debug_isr(sock, args); + else if (cmd_word == "x") + { + args = "pc " + args; + ret = cmd_disassemble(sock, args); + } + return ret; } diff --git a/src/serial.c b/src/serial.c index e1514a6..577f733 100644 --- a/src/serial.c +++ b/src/serial.c @@ -56,6 +56,8 @@ #include "display.h" ser_params_t sp; +extern int gModel; + #ifndef WIN32 /* @@ -258,7 +260,7 @@ int ser_get_port_list(char* port_list, int max, int *count) // Append port name to list strcat(port_list, str); - *count++; + (*count)++; } } #else @@ -1277,12 +1279,28 @@ int ser_get_flags(unsigned char *flags) } { // Set CTS flag - if ((modem_status & MS_CTS_ON) == 0) - *flags |= SER_FLAG_CTS; + if (gModel == MODEL_T200) + { + if (modem_status & MS_CTS_ON) + *flags |= SER_FLAG_CTS; + } + else + { + if ((modem_status & MS_CTS_ON) == 0) + *flags |= SER_FLAG_CTS; + } // Set DSR flag - if ((modem_status & MS_DSR_ON) == 0) - *flags |= SER_FLAG_DSR; + if (gModel == MODEL_T200) + { + if (modem_status & MS_DSR_ON) + *flags |= SER_FLAG_DSR; + } + else + { + if ((modem_status & MS_DSR_ON) == 0) + *flags |= SER_FLAG_DSR; + } } // RING flag diff --git a/src/setup.cpp b/src/setup.cpp index e8000c1..88e0180 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -55,6 +55,7 @@ #include "io.h" #include "file.h" #include "lpt.h" +#include "clock.h" extern Fl_Preferences virtualt_prefs; void init_menus(void); @@ -78,7 +79,7 @@ typedef struct setup_ctrl_struct struct { Fl_Group* g; - Fl_Box* pText; +// Fl_Box* pText; } lpt; struct { @@ -100,6 +101,10 @@ typedef struct setup_ctrl_struct Fl_Group* g; Fl_Box* pText; } sound; + struct + { + Fl_Group* g; + } clock; } setup_ctrl_t; @@ -157,6 +162,9 @@ void save_setup_preferences(void) // Save BCR emulation settings // Save Sound emulation settings + + // Save Clock preference settings + save_clock_preferences(&virtualt_prefs); } void load_setup_preferences(void) @@ -186,6 +194,9 @@ void load_setup_preferences(void) // Load Sound emulation settings + // Load Clock emulation settings + load_clock_preferences(&virtualt_prefs); + #ifdef __APPLE__ //JV 08/10/05 // Load Path Preferences @@ -220,27 +231,41 @@ void cb_setup_cancel (Fl_Widget* w, void*) void cb_setup_OK(Fl_Widget* w, void*) { + int open_port = FALSE; + // First check if Host port needs to be closed if (setup.com_mode == SETUP_COM_HOST) { // Check if we are turning Host port emulation off if (setup_ctrl.com.pHost->value() != 1) + { ser_close_port(); + open_port = TRUE; + } // Check if we are changing ports if (strcmp(setup_ctrl.com.pPort->text(), setup.com_port) != 0) + { ser_close_port(); + open_port = TRUE; + } } if (setup.com_mode == SETUP_COM_OTHER) { // Check if we are turning Host port emulation off if (setup_ctrl.com.pOther->value() != 1) + { ser_close_port(); + open_port = TRUE; + } // Check if we are changing ports if (strcmp(setup_ctrl.com.pOtherName->value(), setup.com_other) != 0) + { ser_close_port(); + open_port = TRUE; + } } // =========================== @@ -271,8 +296,11 @@ void cb_setup_OK(Fl_Widget* w, void*) setup.com_mode = SETUP_COM_HOST; // Open the Host port - ser_set_port(setup.com_port); - ser_open_port(); + if (open_port) + { + ser_set_port(setup.com_port); + ser_open_port(); + } } else if (setup_ctrl.com.pOther->value() == 1) { @@ -280,8 +308,11 @@ void cb_setup_OK(Fl_Widget* w, void*) setup.com_mode = SETUP_COM_OTHER; // Open the Host port - ser_set_port(setup.com_other); - ser_open_port(); + if (open_port) + { + ser_set_port(setup.com_other); + ser_open_port(); + } } setup.com_ignore_flow = setup_ctrl.com.pIgnoreFlow->value(); @@ -310,6 +341,11 @@ void cb_setup_OK(Fl_Widget* w, void*) // =========================== // get_sound_options(); + // =========================== + // Get Clock options + // =========================== + get_clock_options(); + // Save setup preferences to file save_setup_preferences(); @@ -492,13 +528,13 @@ void cb_PeripheralSetup (Fl_Widget* w, void*) // BCR Port Tab { // Create the Group item (the "Tab") - setup_ctrl.bcr.g = new Fl_Group(10, 30, 300, 260, " BCR "); +// setup_ctrl.bcr.g = new Fl_Group(10, 30, 300, 260, " BCR "); // Create controls - setup_ctrl.bcr.pText = new Fl_Box(120, 60, 60, 80, "BCR Port not supported yet"); +// setup_ctrl.bcr.pText = new Fl_Box(120, 60, 60, 80, "BCR Port not supported yet"); // End of control for this tab - setup_ctrl.bcr.g->end(); +// setup_ctrl.bcr.g->end(); } // Speaker Port Tab @@ -513,6 +549,18 @@ void cb_PeripheralSetup (Fl_Widget* w, void*) setup_ctrl.sound.g->end(); } + // Clock Port Tab + { + // Create the Group item (the "Tab") + setup_ctrl.clock.g = new Fl_Group(10, 30, 350, 260, " Clock "); + + // Create controls + build_clock_setup_tab(); + + // End of control for this tab + setup_ctrl.clock.g->end(); + } + setup_ctrl.pTabs->value(setup_ctrl.com.g); setup_ctrl.pTabs->end(); diff --git a/src/sound.c b/src/sound.c index 57c0279..c55327e 100644 --- a/src/sound.c +++ b/src/sound.c @@ -54,7 +54,7 @@ #pragma comment(lib, "winmm.lib") #define snd_Buffers 2 -#define cwSizel 32 +#define cwSizel 128 /* * module static data @@ -366,7 +366,7 @@ void init_sound(void) #ifdef _WIN32 // Start thread to handle Sound I/O -// g_hEquThread = (HANDLE)_beginthreadex(0,0,EquProc,0,0,&dwThreadID); + g_hEquThread = (HANDLE)_beginthreadex(0,0,EquProc,0,0,&dwThreadID); #endif } @@ -383,7 +383,7 @@ void deinit_sound(void) free(gpOneHertz); #ifdef _WIN32 -// sndCloseOutput(); + sndCloseOutput(); #endif } From e0b2f7e5020d86fc7f48f06c6f44d91c9511bf78 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Thu, 25 Sep 2008 15:25:51 +0000 Subject: [PATCH 146/327] Updated makefile and Visual Studio project file with clock.cpp. --- GNUmakefile | 11 ++++++----- VirtualT.vcproj | 8 ++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 4f9a87a..c655978 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -45,7 +45,7 @@ SOURCESCPP = display.cpp setup.cpp periph.cpp disassemble.cpp file.cpp memedit.c multiwin.cpp multiwin_icons.cpp project.cpp multieditwin.cpp rememcfg.cpp \ fl_usage_box.cpp remote.cpp socket.cpp serversocket.cpp lpt.cpp printer.cpp \ fileprint.cpp hostprint.cpp fx80print.cpp chargen.cpp fl_action_icon.cpp fx80rom.cpp \ - vtpaper.cpp autofile.cpp + vtpaper.cpp autofile.cpp clock.cpp CLIENT_SRC = clientsocket.cpp vt_client_main.cpp socket.cpp # =============================== @@ -128,20 +128,20 @@ $(OBJECTS) $(OBJECTSCPP): m100emu.h GNUmakefile VirtualT.h $(CLIENT_OBJS): socket.h disassemble.o: disassemble.h io.h cpu.h periph.h memedit.h romstrings.h -display.o: display.h io.h file.h setup.h periph.h memory.h memedit.h lpt.h +display.o: display.h io.h file.h setup.h periph.h memory.h memedit.h lpt.h clock.h doins.o: cpu.h io.h file.o: memory.h roms.h intelhex.h -io.o: cpu.h gen_defs.h io.h serial.h display.h setup.h memory.h lpt.h +io.o: cpu.h gen_defs.h io.h serial.h display.h setup.h memory.h lpt.h clock.h intelhex.o: intelhex.h m100emu.o: io.h cpu.h doins.h display.h genwrap.h filewrap.h roms.h \ - intelhex.h setup.h memory.h do_instruct.h lpt.h + intelhex.h setup.h memory.h do_instruct.h lpt.h clock.h memedit.o: memedit.h disassemble.h memory.h cpu.h memory.o: memory.h cpu.h io.h intelhex.h setup.h periph.o: periph.h serial.h setup.h display.h disassemble.h lpt.h serial.o: serial.h setup.h display.h rememcfg.o: rememcfg.h setup.h display.h fl_usage_box.o: fl_usage_box.h -setup.o: setup.h io.h serial.h memory.h memedit.h lpt.h +setup.o: setup.h io.h serial.h memory.h memedit.h lpt.h clock.h sound.c: sound.h m100rom.o m102rom.o m200rom.o n8201rom.o romstrings.o m10rom.o kc85rom.o: roms.h romstrings.h remote.o: remote.cpp m100emu.h socket.h serversocket.h socketexception.h @@ -157,6 +157,7 @@ fl_action_icon.o:fl_action_icon.h fx80rom.o: vtpaper.o: printer.h vtpaper.h autofile.h autofile.o: autofile.h +clock.o: clock.h # ========== # asm files diff --git a/VirtualT.vcproj b/VirtualT.vcproj index cec307f..a95e7ab 100644 --- a/VirtualT.vcproj +++ b/VirtualT.vcproj @@ -215,6 +215,10 @@ Name="Source Files" Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" > + + @@ -1052,6 +1056,10 @@ Name="Header Files" Filter="h;hpp;hxx;hm;inl" > + + From 4049532693c52f3115c622ee365e981b23fc3239 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Thu, 25 Sep 2008 15:29:36 +0000 Subject: [PATCH 147/327] Changed release date for v1.3. --- release.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release.txt b/release.txt index 3f41817..d34fc61 100644 --- a/release.txt +++ b/release.txt @@ -7,7 +7,7 @@ This file lists the changes and additions for each of the versions of VirtualT s ======================= -v1.3 September 22 2008 +v1.3 September 24 2008 ======================= 1. Fixed a bug with the Remem Overrides Rampac checkbox where it wouldn't properly override From 0541d66a11fb9bd6faaf401405067be195428aa6 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 28 Sep 2008 01:56:28 +0000 Subject: [PATCH 148/327] Modified ComLog event handler and draw routines to properly deal with byte selection and redrawing when the display is scrolled. --- src/periph.cpp | 90 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 26 deletions(-) diff --git a/src/periph.cpp b/src/periph.cpp index 84339c7..6d172e3 100644 --- a/src/periph.cpp +++ b/src/periph.cpp @@ -537,6 +537,20 @@ void update_com_port_settings() periph_ctrl.com.sComMdm[0] = 0; } +void cb_test_data(Fl_Widget* w, void*) +{ + int x; + + for (x = 0; x < 512; x++) + { + Fl::wait(.001); + periph_ctrl.com.pLog->AddByte(x & 0x10, (x&0x7F) | 0x40, 0); + } + periph_ctrl.com.pLog->AddByte(x & 0x10, 'T', 0); + periph_ctrl.com.pLog->AddByte(x & 0x10, 'e', 0); + periph_ctrl.com.pLog->AddByte(x & 0x10, 's', 0); + periph_ctrl.com.pLog->AddByte(x & 0x10, 't', 0); +} /* ============================================================================ Routine to create the PeripheralSetup Window and tabs @@ -693,6 +707,9 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) periph_ctrl.com.pFont->add("16"); periph_ctrl.com.pFont->value(0); + Fl_Button *but = new Fl_Button(440, 360, 60, 25, "Test"); + but->callback(cb_test_data); + periph_ctrl.com.g->end(); update_com_port_settings(); @@ -926,7 +943,7 @@ void T100_ComMon::AddByte(int rx_tx, char byte, char flags) b->entries[b->used].flags = flags; b->entries[b->used].time = hirestimer(); - // Check if last char was save type as this & advance col if it was + // Check if last char was same type as this & advance col if it was if (m_pLastEntry != NULL) { if ((m_pLastEntry->flags & 0x80) == (b->entries[b->used].flags & 0x80) || @@ -1099,7 +1116,7 @@ void T100_ComMon::draw() m_Height = fl_height(); // Calculate max cols and lines - lines = (int) (h() / m_Height); + lines = ((int) (h() / m_Height)) & ~1; cols = (int) (w() / m_Width); if ((lines != m_Lines) || (cols != m_Cols)) @@ -1175,23 +1192,40 @@ void T100_ComMon::draw() if (&clb->entries[index] == m_pStartTime) { - fl_color(FL_GREEN); - fl_rectf(xpos, ypos-(int) m_Height+3, (int) (adder * m_Width), (int) m_Height-1); - fl_color(FL_BLACK); - m_StartTimeLine = line; - if ((clb->entries[index].flags & 0x80) == 0) - m_StartTimeLine++; - m_StartTimeCol = col; + if ((m_StartTimeLine >= m_FirstLine) && + (m_StartTimeLine < m_FirstLine + m_Lines)) + { + if (m_pStartTime == m_pStopTime) + fl_color(FL_YELLOW); + else + fl_color(FL_GREEN); + fl_rectf(xpos, ypos-(int) m_Height+3, (int) (adder * m_Width), (int) m_Height-1); + fl_color(FL_BLACK); + m_StartTimeLine = line + m_FirstLine; + if ((clb->entries[index].flags & 0x80) == 0) + m_StartTimeLine++; + m_StartTimeCol = col; + } } else if (&clb->entries[index] == m_pStopTime) { - fl_color(FL_RED); - fl_rectf(xpos, ypos-(int)m_Height+3, (int) (adder * m_Width), (int) m_Height-1); - fl_color(FL_WHITE); - m_StopTimeLine = line; - if ((clb->entries[index].flags & 0x80) == 0) - m_StopTimeLine++; - m_StopTimeCol = col; + if ((m_StopTimeLine >= m_FirstLine) && + (m_StopTimeLine < m_FirstLine + m_Lines)) + { + if (m_pStartTime == m_pStopTime) + fl_color(FL_YELLOW); + else + fl_color(FL_RED); + fl_rectf(xpos, ypos-(int)m_Height+3, (int) (adder * m_Width), (int) m_Height-1); + if (m_pStartTime == m_pStopTime) + fl_color(FL_BLACK); + else + fl_color(FL_WHITE); + m_StopTimeLine = line + m_FirstLine; + if ((clb->entries[index].flags & 0x80) == 0) + m_StopTimeLine++; + m_StopTimeCol = col; + } } // Draw the text if (gHexOn) @@ -1333,7 +1367,8 @@ int T100_ComMon::handle(int event) // Check for correct line number if (cle->flags & 0x80) { - if (line == line_click) + if (!(line_click & 0x01)) +// if (line == line_click) { cle_sel = &clb->entries[index]; break; @@ -1341,7 +1376,8 @@ int T100_ComMon::handle(int event) } else { - if (line + 1 == line_click) + if (line_click & 0x01) +// if (line + 1 == line_click) { cle_sel = &clb->entries[index]; break; @@ -1376,7 +1412,7 @@ int T100_ComMon::handle(int event) (m_StopTimeLine < m_FirstLine + m_Lines)) { xpos = (int) (x() + m_StopTimeCol * m_Width); - ypos = (int) (y() + m_StopTimeLine * m_Height); + ypos = (int) (y() + (m_StopTimeLine - m_FirstLine) * m_Height); prev_cle = m_pStopTime; line = m_StopTimeLine; } @@ -1392,7 +1428,7 @@ int T100_ComMon::handle(int event) (m_StartTimeLine < m_FirstLine + m_Lines)) { xpos = (int) (x() + m_StartTimeCol * m_Width); - ypos = (int) (y() + m_StartTimeLine * m_Height); + ypos = (int) (y() + (m_StartTimeLine - m_FirstLine) * m_Height); prev_cle = m_pStartTime; line = m_StartTimeLine; } @@ -1435,7 +1471,7 @@ int T100_ComMon::handle(int event) sprintf(periph_ctrl.com.sStopChar, "%c (%02xh)", cle_sel->byte, cle_sel->byte); periph_ctrl.com.pStopChar->label(periph_ctrl.com.sStopChar); m_pStopTime = cle_sel; - m_StopTimeLine = line_click; + m_StopTimeLine = line_click + m_FirstLine; m_StopTimeCol = col; fl_color(FL_RED); } @@ -1445,16 +1481,17 @@ int T100_ComMon::handle(int event) sprintf(periph_ctrl.com.sStartChar, "%c (%02xh)", cle_sel->byte, cle_sel->byte); periph_ctrl.com.pStartChar->label(periph_ctrl.com.sStartChar); m_pStartTime = cle_sel; - m_StartTimeLine = line_click; + m_StartTimeLine = line_click + m_FirstLine; m_StartTimeCol = col; } - if (m_pStartTime != NULL) + if ((m_pStartTime != NULL) && (m_StartTimeLine >= m_FirstLine) && + (m_StartTimeLine < m_FirstLine + m_Lines)) { // Draw the Start selecton box fl_color(FL_GREEN); xpos = (int) (x() + m_StartTimeCol * m_Width); - ypos = (int) (y() + m_StartTimeLine * m_Height); + ypos = (int) (y() + (m_StartTimeLine - m_FirstLine) * m_Height); fl_rectf(xpos, ypos+3, (int) (adder * m_Width), (int) m_Height-1); // Draw the StartTime text @@ -1466,7 +1503,8 @@ int T100_ComMon::handle(int event) fl_draw(string, xpos, ypos + (int)m_Height-2); } - if (m_pStopTime != NULL) + if ((m_pStopTime != NULL) && (m_StopTimeLine >= m_FirstLine) && + (m_StopTimeLine < m_FirstLine + m_Lines)) { // Draw the Start selecton box if (m_pStartTime == m_pStopTime) @@ -1474,7 +1512,7 @@ int T100_ComMon::handle(int event) else fl_color(FL_RED); xpos = (int) (x() + m_StopTimeCol * m_Width); - ypos = (int) (y() + m_StopTimeLine * m_Height); + ypos = (int) (y() + (m_StopTimeLine - m_FirstLine) * m_Height); fl_rectf(xpos, ypos+3, (int) (adder * m_Width), (int) m_Height-1); // Draw the StartTime text From d224b4d7214f4818d6581866205631a8a1fc5287 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 28 Sep 2008 01:57:10 +0000 Subject: [PATCH 149/327] Updates for version 1.4 --- release.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/release.txt b/release.txt index d34fc61..72a1495 100644 --- a/release.txt +++ b/release.txt @@ -6,6 +6,16 @@ VirtualT Release.txt This file lists the changes and additions for each of the versions of VirtualT since v0.3 +======================= +v1.4 Not released yet +======================= + +1. The COM data log on the Peripherals Window was not allowing selection of data to show + time delta between 2 bytes when the top line in the window was not the first line of + data. This has been corrected. Also The last line of data would not be displayed if + the number of lines that would fit in the window was odd. This has also been fixed. + + ======================= v1.3 September 24 2008 ======================= From 87257d69360e968e25ac1f5c1122db234ad44cae Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 4 Nov 2008 02:56:27 +0000 Subject: [PATCH 150/327] Added fullscreen display mode. --- src/display.cpp | 113 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 88 insertions(+), 25 deletions(-) diff --git a/src/display.cpp b/src/display.cpp index b5363e3..a94bab2 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -60,6 +60,7 @@ #include "lpt.h" #include "fl_action_icon.h" #include "clock.h" +#include "fileview.h" extern "C" { extern RomDescription_t gM100_Desc; @@ -90,6 +91,7 @@ char gsMenuROM[40]; char gDelayedError[128] = {0}; int MultFact = 3; int DisplayMode = 1; +int Fullscreen = 0; int SolidChars = 0; int DispHeight = 64; int gRectsize = 2; @@ -263,13 +265,40 @@ void resize_window() gpDisp->DispHeight = 64; DispHeight = 64; } - MainWin->resize(MainWin->x(), MainWin->y(), 240*gpDisp->MultFact + - 90*gpDisp->DisplayMode+2,gpDisp->DispHeight*gpDisp->MultFact + - 50*gpDisp->DisplayMode + MENU_HEIGHT + 22); - Menu->resize(0, 0, 240*gpDisp->MultFact + 90*gpDisp->DisplayMode+2, - MENU_HEIGHT-2); - gpDisp->resize(0, MENU_HEIGHT, 240*gpDisp->MultFact + 90*gpDisp->DisplayMode+2, - gpDisp->DispHeight*gpDisp->MultFact + 50*gpDisp->DisplayMode+2); + if (Fullscreen) + { + MainWin->fullscreen(); + MultFact = min(MainWin->w()/240, MainWin->h()/128); + gpDisp->MultFact = MultFact; + } + else + { + if (MainWin->y() <= 0) + MainWin->fullscreen_off(32, 32, 240*gpDisp->MultFact + + 90*gpDisp->DisplayMode+2, gpDisp->DispHeight*gpDisp->MultFact + + 50*gpDisp->DisplayMode + MENU_HEIGHT + 22); + else + MainWin->fullscreen_off(MainWin->x(), MainWin->y(), 240*gpDisp->MultFact + + 90*gpDisp->DisplayMode+2, gpDisp->DispHeight*gpDisp->MultFact + + 50*gpDisp->DisplayMode + MENU_HEIGHT + 22); + } + + if (MainWin->y() <= 0) + { + if (!Fullscreen) + MainWin->resize(32, 32, 240*gpDisp->MultFact + + 90*gpDisp->DisplayMode+2,gpDisp->DispHeight*gpDisp->MultFact + + 50*gpDisp->DisplayMode + MENU_HEIGHT + 22); + } + else + { + MainWin->resize(MainWin->x(), MainWin->y(), 240*gpDisp->MultFact + + 90*gpDisp->DisplayMode+2,gpDisp->DispHeight*gpDisp->MultFact + + 50*gpDisp->DisplayMode + MENU_HEIGHT + 22); + } + + Menu->resize(0, 0, MainWin->w(), MENU_HEIGHT-2); + gpDisp->resize(0, MENU_HEIGHT, MainWin->w(), MainWin->h() - MENU_HEIGHT - 20); gpGraph->resize(0, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + 50*gpDisp->DisplayMode+2, 60, 20); gpCode->resize(60, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + @@ -341,6 +370,7 @@ void cb_1x(Fl_Widget* w, void*) { gpDisp->MultFact = 1; MultFact = 1; + Fullscreen = 0; virtualt_prefs.set("MultFact",1); resize_window(); @@ -349,6 +379,7 @@ void cb_2x(Fl_Widget* w, void*) { gpDisp->MultFact = 2; MultFact = 2; + Fullscreen = 0; virtualt_prefs.set("MultFact",2); resize_window(); @@ -357,6 +388,7 @@ void cb_3x(Fl_Widget* w, void*) { gpDisp->MultFact = 3; MultFact = 3; + Fullscreen = 0; virtualt_prefs.set("MultFact",3); resize_window(); @@ -365,10 +397,20 @@ void cb_4x(Fl_Widget* w, void*) { gpDisp->MultFact = 4; MultFact = 4; + Fullscreen = 0; virtualt_prefs.set("MultFact",4); resize_window(); } +void cb_fullscreen(Fl_Widget* w, void*) +{ + gpDisp->MultFact = 5; + MultFact = 5; + Fullscreen = 1; + + virtualt_prefs.set("MultFact",5); + resize_window(); +} void cb_framed(Fl_Widget* w, void*) { gpDisp->DisplayMode ^= 1; @@ -424,7 +466,6 @@ void remote_reset(void) void cb_coldBoot (Fl_Widget* w, void*) { - int x; int a; if (gReMem) @@ -449,16 +490,13 @@ void cb_coldBoot (Fl_Widget* w, void*) resetcpu(); reinit_mem(); - // Clear the RAM - for (x = 32768; x < 65536; x++) - set_memory8(x, 0); - show_remem_mode(); if (gpDisp != NULL) gpDisp->Reset(); if (gpDebugMonitor != 0) gpDebugMonitor->Reset(); + fileview_model_changed(); } } @@ -676,7 +714,8 @@ Fl_Menu_Item menuitems[] = { { "1x", 0, cb_1x, (void *) 1, FL_MENU_RADIO }, { "2x", 0, cb_2x, (void *) 2, FL_MENU_RADIO }, { "3x", 0, cb_3x, (void *) 3, FL_MENU_RADIO | FL_MENU_VALUE}, - { "4x", 0, cb_4x, (void *) 4, FL_MENU_RADIO | FL_MENU_DIVIDER}, + { "4x", 0, cb_4x, (void *) 4, FL_MENU_RADIO }, + { "Fullscreen", 0, cb_fullscreen, (void *) 5, FL_MENU_RADIO | FL_MENU_DIVIDER}, { "Framed", 0, cb_framed, (void *) 1, FL_MENU_TOGGLE|FL_MENU_VALUE }, { "Solid Chars", 0, cb_solidchars, (void *) 1, FL_MENU_TOGGLE}, { 0 }, @@ -700,7 +739,7 @@ Fl_Menu_Item menuitems[] = { { "ReMem Configuration", 0, cb_RememCfg, 0, 0 }, { "Peripheral Devices", 0, cb_PeripheralDevices }, // { "Simulation Log Viewer", 0, 0 }, - { "Model T File Viewer", 0, 0 }, + { "Model T File Viewer", 0, cb_FileView }, { 0 }, { "&Help", 0, 0, 0, FL_SUBMENU }, { "Help", 0, cb_help }, @@ -842,6 +881,9 @@ void switch_model(int model) /* Update Memory Editor window if any */ cb_MemoryEditorUpdate(); + + // Update the File View window if it is open + fileview_model_changed(); } @@ -1021,7 +1063,8 @@ void T100_Disp::draw_static() fl_color(FL_WHITE); fl_font(FL_COURIER,12); char text[3] = "F1"; - y_pos = h()+20; +// y_pos = h()+20; + y_pos = y()+DispHeight*MultFact+40; xl_start = 2*MultFact; xl_end = 7*MultFact; @@ -1173,6 +1216,10 @@ void init_pref(void) virtualt_prefs.get("BasicSaveMode",BasicSaveMode,0); virtualt_prefs.get("COSaveMode",COSaveMode,0); virtualt_prefs.get("Model",gModel, MODEL_M100); + + Fullscreen = 0; + if (MultFact == 5) + Fullscreen = 1; get_model_string(option_name, gModel); strcat(option_name, "_OptRomFile"); @@ -1218,14 +1265,26 @@ void init_display(void) DispHeight = 64; MainWin = new Fl_Window(240*MultFact + 90*DisplayMode+2,DispHeight*MultFact + 50*DisplayMode + MENU_HEIGHT + 22, "Virtual T"); - Menu = new Fl_Menu_Bar(0, 0, 240*MultFact + 90*DisplayMode+2, - MENU_HEIGHT-2); + + // Check if we are running in full screen mode + if (MultFact == 5) + { + MainWin->fullscreen(); + MultFact = min(MainWin->w()/240, MainWin->h()/128); + } + else + { + if (MainWin->y() <= 0) + MainWin->fullscreen_off(32, 32, + 240*MultFact + 90*DisplayMode+2,DispHeight*MultFact + + 50*DisplayMode + MENU_HEIGHT + 22); + } + + Menu = new Fl_Menu_Bar(0, 0, MainWin->w(), MENU_HEIGHT-2); if (gModel == MODEL_T200) - gpDisp = new T200_Disp(0, MENU_HEIGHT, 240*MultFact + 90*DisplayMode+2, - DispHeight*MultFact + 50*DisplayMode+2); + gpDisp = new T200_Disp(0, MENU_HEIGHT, MainWin->w(), MainWin->h() - MENU_HEIGHT - 20); else - gpDisp = new T100_Disp(0, MENU_HEIGHT, 240*MultFact + 90*DisplayMode+2, - DispHeight*MultFact + 50*DisplayMode+2); + gpDisp = new T100_Disp(0, MENU_HEIGHT, MainWin->w(), MainWin->h() - MENU_HEIGHT - 20); MainWin->callback(close_disp_cb); Menu->menu(menuitems); @@ -1257,16 +1316,20 @@ void init_display(void) mIndex++; mIndex--; - for(i=1;i<5;i++) + for(i=1;i<6;i++) { if(i==MultFact) - if(i==4) + { + if(i==5) menuitems[i+mIndex].flags=FL_MENU_RADIO | FL_MENU_VALUE | FL_MENU_DIVIDER; else menuitems[i+mIndex].flags=FL_MENU_RADIO | FL_MENU_VALUE; - else - if(i==4) + } + else + { + if(i==5) menuitems[i+mIndex].flags=FL_MENU_RADIO | FL_MENU_DIVIDER; else menuitems[i+mIndex].flags=FL_MENU_RADIO; + } } //================================================== From 9d5e7e4b042ffc9c0b8e5f89dbc763283f4a9612 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 4 Nov 2008 07:31:22 +0000 Subject: [PATCH 151/327] Added model T file viewer, fixed an issue with the COM log viewer where the bottom line wasnt' being displayed, and started additons for REX. The REX additions are incomplete and selecting REX will not function properly at the moment. --- src/VirtualT.h | 2 +- src/clock.cpp | 1 - src/cpu.h | 24 +- src/cpuregs.cpp | 3 +- src/disassemble.cpp | 3 +- src/display.cpp | 5 +- src/file.cpp | 11 +- src/file.h | 4 + src/fileview.cpp | 871 ++++++++++++++++++++++++++++++++++++++++++++ src/fileview.h | 85 +++++ src/intelhex.c | 1 + src/lpt.cpp | 2 + src/m100emu.c | 23 +- src/m100emu.h | 1 + src/memedit.cpp | 7 +- src/memory.c | 19 + src/memory.h | 21 ++ src/periph.cpp | 3 +- src/rememcfg.cpp | 3 +- src/remote.cpp | 35 +- src/setup.cpp | 330 ++++++++++++++++- src/setup.h | 6 +- 22 files changed, 1411 insertions(+), 49 deletions(-) create mode 100644 src/fileview.cpp create mode 100644 src/fileview.h diff --git a/src/VirtualT.h b/src/VirtualT.h index 8611e3a..bdeb942 100644 --- a/src/VirtualT.h +++ b/src/VirtualT.h @@ -31,7 +31,7 @@ #ifndef _VIRTUALT_H_ #define _VIRTUALT_H_ -#define VERSION "1.3" +#define VERSION "1.4" enum { MODEL_M100 diff --git a/src/clock.cpp b/src/clock.cpp index a24f333..a8d0860 100644 --- a/src/clock.cpp +++ b/src/clock.cpp @@ -399,7 +399,6 @@ void save_model_time(void) strcpy(pref, str); strcat(pref, "_RefTime"); virtualt_prefs.set(pref, ctime(&gRefTime)); - printf(ctime(&gRefTime)); // Save Start Time strcpy(pref, str); diff --git a/src/cpu.h b/src/cpu.h index b37fe8e..274f7d8 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -168,16 +168,28 @@ the settings for ReMem support. #define MEMSET(a,v) {if(a>=ROMSIZE) gBaseMemory[a] = v; } #else - + #define SETPCINS16 {int pc=PC; PCL=get_memory8((unsigned short) pc++); PCH=get_memory8((unsigned short) pc);} -#define M (gMemory[gIndex[HL]][HL & 0x3FF]) -#define INS (gMemory[gIndex[PC]][PC & 0x3FF]) -#define INS_INC (gMemory[gIndex[PC]][PC & 0x3FF]); INCPC; +#define M (get_memory8(HL)) +#define INS (get_memory8(PC)) +#define INS_INC (get_memory8(PC); INCPC;) #define NXTINS (get_memory8((unsigned short) (PC+1))) #define INS16 (((int)get_memory8((unsigned short) (PC)))|(((int)get_memory8((unsigned short) (PC+1)))<<8)) -#define MEM(x) (gMemory[gIndex[x]][x & 0x3FF]) +#define MEM(x) (get_memory8(x)) #define MEM16(x) (((ushort)MEM(x))|((ushort)MEM(x+1))<<8) -#define MEMSET(a,v) {remem_set8((unsigned short) (a), v); } +#define MEMSET(a,v) {gRex?rex_set8((unsigned short)(a),v):remem_set8((unsigned short) (a), v); } + + +//#define SETPCINS16 {int pc=PC; PCL=get_memory8((unsigned short) pc++); PCH=get_memory8((unsigned short) pc);} +//#define M (gMemory[gIndex[HL]][HL & 0x3FF]) +//#define INS (gMemory[gIndex[PC]][PC & 0x3FF]) +//#define INS_INC (gMemory[gIndex[PC]][PC & 0x3FF]); INCPC; +//#define NXTINS (get_memory8((unsigned short) (PC+1))) +//#define INS16 (((int)get_memory8((unsigned short) (PC)))|(((int)get_memory8((unsigned short) (PC+1)))<<8)) +//#define MEM(x) (gMemory[gIndex[x]][x & 0x3FF]) +//#define MEM16(x) (((ushort)MEM(x))|((ushort)MEM(x+1))<<8) +//#define MEMSET(a,v) {remem_set8((unsigned short) (a), v); } + #endif diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index 744921e..a1b3a0e 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -47,6 +47,7 @@ #include "memedit.h" #include "cpu.h" #include "memory.h" +#include "fileview.h" #define MENU_HEIGHT 32 @@ -74,7 +75,7 @@ Fl_Menu_Item gCpuRegs_menuitems[] = { { "Memory Editor", 0, cb_MemoryEditor }, { "Peripheral Devices", 0, cb_PeripheralDevices }, // { "Simulation Log Viewer", 0, 0 }, - { "Model T File Viewer", 0, 0 }, + { "Model T File Viewer", 0, cb_FileView }, { 0 }, { 0 } }; diff --git a/src/disassemble.cpp b/src/disassemble.cpp index f6a7ef3..e2fdd0b 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -49,6 +49,7 @@ #include "romstrings.h" #include "cpuregs.h" #include "memory.h" +#include "fileview.h" void cb_Ide(Fl_Widget* w, void*) ; @@ -166,7 +167,7 @@ Fl_Menu_Item gDis_menuitems[] = { { "Memory Editor", 0, cb_MemoryEditor }, { "Peripheral Devices", 0, cb_PeripheralDevices }, // { "Simulation Log Viewer", 0, 0 }, - { "Model T File Viewer", 0, 0 }, + { "Model T File Viewer", 0, cb_FileView }, { 0 }, { 0 } diff --git a/src/display.cpp b/src/display.cpp index a94bab2..5a29db8 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -1430,10 +1430,9 @@ void init_display(void) gpMap->labelsize(10); gpPrint = new Fl_Action_Icon(420, MENU_HEIGHT+DispHeight*MultFact + 50*DisplayMode+2, 60, 20, "Print Menu"); - gpPrint->set_image(&gPrinterIcon); gpPrint->align(FL_ALIGN_TOP | FL_ALIGN_INSIDE | FL_ALIGN_LEFT); + gpPrint->set_image(&gPrinterIcon); gpPrint->menu(gPrintMenu); - gpPrint->label("Idle"); if (MultFact < 3) { gpKeyInfo = new Fl_Box(FL_DOWN_BOX,480, MENU_HEIGHT+DispHeight*MultFact + @@ -1495,6 +1494,8 @@ void init_display(void) fl_alert(gDelayedError); gDelayedError[0] = '\0'; } + + gpPrint->label("Idle"); } static char label[40]; diff --git a/src/file.cpp b/src/file.cpp index ee7d540..5e93864 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -47,10 +47,13 @@ extern "C" #include "roms.h" #include "intelhex.h" #include "m100emu.h" + extern RomDescription_t *gStdRomDesc; void jump_to_zero(void); } + #include "file.h" +#include "fileview.h" int BasicSaveMode = 0; int COSaveMode = 0; @@ -171,12 +174,6 @@ void cb_LoadOptRom (Fl_Widget* w, void*) char *gIllformedBasic = "Ill formed BASIC file"; static char *gTooLargeMsg = "File too large for available memory"; -#define TYPE_BA 0x80 -#define TYPE_CO 0xA0 -#define TYPE_DO 0xC0 -#define TYPE_HEX 0x40 - - char *gKeywordTable[] = { "END", "FOR", "NEXT", "DATA", "INPUT", "DIM", "READ", "LET", "GOTO", "RUN", "IF", "RESTORE", "GOSUB", "RETURN", "REM", "STOP", @@ -887,6 +884,8 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) set_memory8(addr1+x, conv[x]); } + // Update file view if open + fileview_model_changed(); // Reset the system so file will show up jump_to_zero(); diff --git a/src/file.h b/src/file.h index 5398cab..fff4cc0 100644 --- a/src/file.h +++ b/src/file.h @@ -33,6 +33,10 @@ #include "gen_defs.h" +#define TYPE_BA 0x80 +#define TYPE_CO 0xA0 +#define TYPE_DO 0xC0 +#define TYPE_HEX 0x40 void cb_LoadRam (Fl_Widget* w, void*); void cb_SaveRam (Fl_Widget* w, void*); diff --git a/src/fileview.cpp b/src/fileview.cpp new file mode 100644 index 0000000..846f98d --- /dev/null +++ b/src/fileview.cpp @@ -0,0 +1,871 @@ +/* fileview.cpp */ + +/* $Id$ */ + +/* + * Copyright 2008 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define FILE_VIEW_MAIN + +#include +#include +#include +#ifdef _WIN32 +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "roms.h" +#include "fl_usage_box.h" +#include "fileview.h" +#include "display.h" +#include "cpuregs.h" +#include "disassemble.h" +#include "periph.h" +#include "memedit.h" +#include "file.h" + +// =============================================== +// Extern "C" linkage items +// =============================================== +extern "C" +{ +#include "memory.h" +#include "m100emu.h" + +extern RomDescription_t *gStdRomDesc; +void jump_to_zero(void); +} + +// =============================================== +// Extern and global variables +// =============================================== +extern Fl_Preferences virtualt_prefs; +extern Fl_Menu_Item gCpuRegs_menuitems[]; +extern char *gKeywordTable[]; +Fl_Window* gfvw = NULL; +int gLowmem = 0; +int gPrevUnused = 0; +unsigned char gRam[32768]; +fileview_ctrl_t gFvCtrl; + +void cb_Ide(Fl_Widget* w, void*) ; +void cb_view_refreseh(Fl_Widget*w, void*); + +// Menu items for the disassembler +Fl_Menu_Item gFileView_menuitems[] = { + { "&View", 0, 0, 0, FL_SUBMENU }, + { "Refresh", 0, cb_view_refreseh, 0, 0 }, + { 0 }, + { "&Tools", 0, 0, 0, FL_SUBMENU }, + { "CPU Registers", 0, cb_CpuRegs }, + { "Assembler / IDE", 0, cb_Ide }, + { "Disassembler", 0, disassembler_cb }, + { "Memory Editor", 0, cb_MemoryEditor }, + { "Peripheral Devices", 0, cb_PeripheralDevices }, + { 0 }, + { 0 } +}; +void fileview_mem_monitor(void); + +/* +============================================================================ +Callback routine for the File Viewer window +============================================================================ +*/ +void cb_fvwin (Fl_Widget* w, void*) +{ + mem_clear_monitor_callback(fileview_mem_monitor); + + // Hide the window + gfvw->hide(); + + // Delete the window and set to NULL + delete gfvw; + gfvw = NULL; +} + +/* +============================================================================ +Callback routine when a file is selected +============================================================================ +*/ +void display_file(int index) +{ + int addr1, addr2, c, x, y, lineno, maxline; + char line[1000], substr[10], linefmt[6], fill[7]; + unsigned char ch; + file_view_files_t *pfile; + + // First clear the text buffer +// gFvCtrl.pTb->remove(0, gFvCtrl.pTb->length()); + gFvCtrl.pView->clear(); + + // Populate with data based on file type + pfile = &gFvCtrl.tFiles[index]; + switch (pfile->type) + { + case TYPE_BA: + // Get first BASIC line pointer + addr1 = pfile->address; + + // Calculate the maximum linenumber length + while (get_memory16(addr1) != 0) + { + addr2 = addr1; + addr1 = get_memory16(addr1); + } + maxline = get_memory16(addr2+2); + if (maxline > 9999) + { + strcpy(linefmt, "%5u "); + strcpy(fill, " "); + } + else if (maxline > 999) + { + strcpy(linefmt, "%4u "); + strcpy(fill, " "); + } + else if (maxline > 99) + { + strcpy(linefmt, "%3u "); + strcpy(fill, " "); + } + else if (maxline > 9) + { + strcpy(linefmt, "%2u "); + strcpy(fill, " "); + } + else + { + strcpy(linefmt, "%1u "); + strcpy(fill, " "); + } + + // Restore pointer to beginning of file + addr1 = pfile->address; + + // Get BASIC lines until NULL + while ((addr2 = get_memory16(addr1)) != 0) + { + // Detokenize the line and save as ASCII + addr1 += 2; + line[0] = 0; + + // Print line number + lineno = get_memory16(addr1); + addr1 += 2; + sprintf(substr, linefmt, lineno); + strcat(line, substr); + + // Read remaining data & detokenize + while (addr1 < addr2) + { + // Get next byte + ch = get_memory8(addr1++); + + // Check if byte is ':' + if (ch == ':') + { + // Get next character + ch = get_memory8(addr1); + + // Check for REM tick + if (ch == 0x8E) + { + if (get_memory8(addr1+1) == 0xFF) + { + ch = '\''; + line[strlen(line)+1] = 0; + line[strlen(line)] = ch; + if (strlen(line) > 54) + { + strcat(line, "\n"); + gFvCtrl.pView->add(line); +// gFvCtrl.pTb->append(line); + strcpy(line, fill); + } + addr1 += 2; + continue; + } + } + + // Check for ELSE + if (ch == 0x91) + continue; + + ch = ':'; + line[strlen(line)+1] = 0; + line[strlen(line)] = ch; + if (strlen(line) > 54) + { + strcat(line, "\n"); + gFvCtrl.pView->add(line); +// gFvCtrl.pTb->append(line); + strcpy(line, fill); + } + } + else if (ch > 0x7F) + { + if (strlen(line) + strlen(gKeywordTable[ch & 0x7F]) > 54) + { + strcat(line, "\n"); + gFvCtrl.pView->add(line); +// gFvCtrl.pTb->append(line); + strcpy(line, fill); + } + sprintf(substr, "%s", gKeywordTable[ch & 0x7F]); + strcat(line, substr); + } + else if (ch == 0) + { + if (strlen(line) != strlen(fill)) + strcat(line, "\n"); + } + else + { + line[strlen(line)+1] = 0; + line[strlen(line)] = ch; + if (strlen(line) > 54) + { + strcat(line, "\n"); + gFvCtrl.pView->add(line); +// gFvCtrl.pTb->append(line); + strcpy(line, fill); + } + } + } +// gFvCtrl.pTb->append(line); + if (strlen(line) != strlen(fill)) + gFvCtrl.pView->add(line); + } + break; + + case TYPE_DO: + // Start at beginning of file + c = 0; + while (c < pfile->size) + { + // Y is the line input location (we skip CR) + y = 0; + // Copy up to 999 bytes into temp line storage + for (x = 0; x < 999; x++) + { + // Test if past end of file + if (x + c > pfile->size) + break; + + // Get next byte from file + line[y] = get_memory8(pfile->address + x + c); + line[y+1] = 0; + + // Write line if newline received + if (line[y] == 0x0A) + { + line[y+1] = 0; + gFvCtrl.pView->add(line); +// gFvCtrl.pTb->append(line); + y = 0; + line[0] = 0; + continue; + } + + if (strlen(line) > 55) + { + line[y+1] = '\n'; + line[y+2] = 0; +// gFvCtrl.pTb->append(line); + gFvCtrl.pView->add(line); + y = 0; + line[0] = 0; + continue; + } + + // Test for end of file + if (line[y] == 0x1A) + break; + + // If byte isn't CR, increment input location + if (line[y] != 0x0D) + y++; + } + + // Terminate the string add add to buffer + line[y] = 0; +// gFvCtrl.pTb->append(line); + gFvCtrl.pView->add(line); + + // Add this block to length processed + c += x; + } + break; + + case TYPE_CO: + x = 0; + while (x < pfile->size) + { + // Start new line + sprintf(line, "%04X: ", pfile->address + x); + + // Add up to 16 bytes to line + for (c = 0; c < 16; c++) + { + // Test if at end of line + if (x + c > pfile->size) + break; + + // Add next byte to line + sprintf(substr, "%02X ", get_memory8(pfile->address + c + x)); + strcat(line, substr); + } + + // Add line to text buffer + strcat(line, "\n"); +// gFvCtrl.pTb->append(line); + gFvCtrl.pView->add(line); + x += c; + } + break; + } +} + +/* +============================================================================ +Callback routine when a file is selected +============================================================================ +*/ +void cb_FileSelect(Fl_Widget* w, void*) +{ + int index, x, usage, lowram; + file_view_files_t *pfile; + + lowram = get_memory16(gStdRomDesc->sLowRam); + + // Check if there is an active selection and restore usage map + if (gFvCtrl.selectIndex != -1) + { + pfile = & gFvCtrl.tFiles[gFvCtrl.selectIndex]; + gFvCtrl.pRAM->AddUsageEvent(pfile->address - lowram, + pfile->address + pfile->size - lowram, -FV_SELECT_FILE_COLOR); + switch (pfile->type) + { + case TYPE_BA: + usage = FV_BASIC_FILE_COLOR; + break; + case TYPE_DO: + usage = FV_TEXT_FILE_COLOR; + break; + case TYPE_CO: + usage = FV_CO_FILE_COLOR; + break; + } + gFvCtrl.pRAM->AddUsageEvent(pfile->address - lowram, pfile->address + + pfile->size - lowram, usage); + gFvCtrl.selectIndex = -1; + } + + // Get selection from Hold Browser + index = ((Fl_Browser*)w)->value()-1; + if ((index < 0) || (index > gFvCtrl.tCount)) + { + // Clear the Directry Entry text + gFvCtrl.sDirEntry[0] = 0; + gFvCtrl.sAddress[0] = 0; + gFvCtrl.pAddress->label(gFvCtrl.sAddress); + gFvCtrl.pDirEntry->label(gFvCtrl.sDirEntry); +// gFvCtrl.pTb->remove(0, gFvCtrl.pTb->length()); + gFvCtrl.pView->clear(); + return; + } + + pfile = & gFvCtrl.tFiles[index]; + + // Format the Directory Entry text + if (strcmp(pfile->name, "Unsaved BA") == 0) + sprintf(gFvCtrl.sDirEntry, "%04Xh: %02X %02X ", pfile->dir_address, + pfile->address & 0xFF,pfile->address >> 8); + else + { + sprintf(gFvCtrl.sDirEntry, "%04Xh: %02X %02X %02X ", pfile->dir_address, + pfile->type, pfile->address & 0xFF,pfile->address >> 8); + + // Add the filename bytes + for (x = 3; x < 11; x++) + { + char substr[5]; + sprintf(substr, "%02x ", get_memory8(pfile->dir_address+x)); + strcat(gFvCtrl.sDirEntry, substr); + } + } + + // Update file address + sprintf(gFvCtrl.sAddress, "Addr: %d (%04Xh)", pfile->address, pfile->address); + gFvCtrl.pAddress->label(gFvCtrl.sAddress); + + // Set the text label + gFvCtrl.pDirEntry->label(gFvCtrl.sDirEntry); + + // Change selection on usage map + switch (pfile->type) + { + case TYPE_BA: + usage = FV_BASIC_FILE_COLOR; + break; + case TYPE_DO: + usage = FV_TEXT_FILE_COLOR; + break; + case TYPE_CO: + usage = FV_CO_FILE_COLOR; + break; + } + + // Clear the previous usage + gFvCtrl.pRAM->AddUsageEvent(pfile->address - lowram, pfile->address + + pfile->size - lowram, -usage); + gFvCtrl.pRAM->AddUsageEvent(pfile->address - lowram, pfile->address + + pfile->size - lowram, FV_SELECT_FILE_COLOR); + gFvCtrl.selectIndex = index; + + // Display the file + display_file(index); +} + +/* +============================================================================ +Get list of files in tFiles structure and update SelectBrowser +============================================================================ +*/ +void get_file_list(void) +{ + int dir_index, addr1, addr2; + unsigned char file_type; + int c, x; + char mt_file[40], fdata; + + // Initialize variables + dir_index = 0; + gFvCtrl.tCount = 0; + gFvCtrl.pFileSelect->clear(); + gFvCtrl.selectIndex = -1; + + // Check for Unsved BASIC program + addr2 = get_memory16(gStdRomDesc->sFilePtrBA); +// addr2 = get_memory16(addr2); + if ((get_memory16(addr2) != 0) && (addr2 != 0)) + { + // Add entry for unsaved BASIC program + strcpy(gFvCtrl.tFiles[0].name, "Unsaved BA"); + gFvCtrl.tFiles[0].dir_address = gStdRomDesc->sFilePtrBA; + gFvCtrl.tFiles[0].address = addr2; + gFvCtrl.tFiles[0].type = TYPE_BA; + addr1 = get_memory16(addr2); + if (addr1 == 0) + { + gFvCtrl.tFiles[0].size = addr2 - get_memory16(gStdRomDesc->sFilePtrBA); + } + else + { + while ((get_memory16(addr1) != 0) && (addr1 != 0)) + { + // Point to next BASIC line + addr1 = get_memory16(addr1); + } + gFvCtrl.tFiles[0].size = addr1 - addr2; + } + + // Add file to Hold Browser + sprintf(mt_file, "%-11s %d", gFvCtrl.tFiles[gFvCtrl.tCount].name, + gFvCtrl.tFiles[gFvCtrl.tCount].size); + gFvCtrl.pFileSelect->add(mt_file); + + // Increment file count + gFvCtrl.tCount++; + } + + // Now point to the file directory + addr1 = gStdRomDesc->sDirectory; + while (dir_index < gStdRomDesc->sDirCount) + { + file_type = get_memory8(addr1); + if ((file_type != TYPE_BA) && (file_type != TYPE_DO) && + (file_type != TYPE_CO)) + { + dir_index++; + addr1 += 11; + continue; + } + + // Get the 1st part of the filename + c = 0; + for (x = 0; x < 6; x++) + { + if (get_memory8(addr1+3+x) != ' ') + mt_file[c++] = get_memory8(addr1+3+x); + } + + // Check for extension and add to mt_file + if (get_memory8(addr1+3+x) != ' ') + mt_file[c++] = '.'; + mt_file[c++] = get_memory8(addr1+3+x++); + mt_file[c++] = get_memory8(addr1+3+x); + mt_file[c] = '\0'; + + // Add filename to tFiles structure + strcpy(gFvCtrl.tFiles[gFvCtrl.tCount].name, mt_file); + gFvCtrl.tFiles[gFvCtrl.tCount].type = file_type; + + // Get address of file + gFvCtrl.tFiles[gFvCtrl.tCount].address = get_memory16(addr1+1); + gFvCtrl.tFiles[gFvCtrl.tCount].dir_address = addr1; + + // Calculate file size + if (file_type == TYPE_CO) + { + // Get file size from the .CO file + gFvCtrl.tFiles[gFvCtrl.tCount].size = + get_memory16(gFvCtrl.tFiles[gFvCtrl.tCount].address + 2) + 6; + } + else if (file_type == TYPE_DO) + { + // Start at beginning of file + x = 0; + fdata = get_memory8(gFvCtrl.tFiles[gFvCtrl.tCount].address); + + // Search through the file until 0x1A found + while (fdata != 0x1A) + { + x++; + fdata = get_memory8(gFvCtrl.tFiles[gFvCtrl.tCount].address + x); + } + + // Set size + gFvCtrl.tFiles[gFvCtrl.tCount].size = x; + } + else if (file_type == TYPE_BA) + { + // Scan through BASIC file until NULL pointer reached + addr2 = get_memory16(gFvCtrl.tFiles[gFvCtrl.tCount].address); + while (get_memory16(addr2) != 0) + { + // Get line pointer of the next line + addr2 = get_memory16(addr2); + } + gFvCtrl.tFiles[gFvCtrl.tCount].size = addr2 - gFvCtrl.tFiles[gFvCtrl.tCount].address; + } + + // Space pad the filename + sprintf(mt_file, "%-11s %d", gFvCtrl.tFiles[gFvCtrl.tCount].name, + gFvCtrl.tFiles[gFvCtrl.tCount].size); + + // Add file to Hold Browser and increment for next file + gFvCtrl.pFileSelect->add(mt_file); + gFvCtrl.tCount++; + dir_index++; + addr1 += 11; + } +} + +/* +============================================================================ +Update the RAM usage map +============================================================================ +*/ +void update_ram_usage_map(void) +{ + int lowram; + + // Clear old usage information + gFvCtrl.pRAM->ClearUsageMap(); + + // Get LOWRAM address. This will change for T200 emulation + lowram = get_memory16(gStdRomDesc->sLowRam); + gLowmem = lowram; + gFvCtrl.pRAM->SetUsageRange(0, 65536 - lowram); + + // Set usage for BASIC files + gFvCtrl.pRAM->AddUsageEvent(1, get_memory16(gStdRomDesc->sBeginDO) - + lowram, FV_BASIC_FILE_COLOR); + + // Set usage for TEXT files + gFvCtrl.pRAM->AddUsageEvent(get_memory16(gStdRomDesc->sBeginDO)-lowram, + get_memory16(gStdRomDesc->sBeginCO) - lowram, FV_TEXT_FILE_COLOR); + + // Set usage for CO files + gFvCtrl.pRAM->AddUsageEvent(get_memory16(gStdRomDesc->sBeginCO)-lowram, + get_memory16(gStdRomDesc->sBeginVar) - lowram, FV_CO_FILE_COLOR); + + // Set usage for CO files + gFvCtrl.pRAM->AddUsageEvent(get_memory16(gStdRomDesc->sBeginVar)-lowram, + get_memory16(gStdRomDesc->sUnusedMem) - lowram, FV_BASIC_VARS_COLOR); + + // Set usage for Directory + gFvCtrl.pRAM->AddUsageEvent(gStdRomDesc->sDirectory-lowram, + gStdRomDesc->sDirectory - lowram + 11 * gStdRomDesc->sDirCount, FV_DIR_COLOR); + + // Set usage for Directory + gFvCtrl.pRAM->AddUsageEvent(gStdRomDesc->sDirectory-lowram + gStdRomDesc->sDirCount * 11, + 65536-lowram, FV_SYS_VARS_COLOR); +} + +/* +============================================================================ +Routine to change display when the model changes +============================================================================ +*/ +void fileview_model_changed(void) +{ + // Test if File View window is open + if (gfvw == NULL) + return; + + // Update the usage map + update_ram_usage_map(); + + // Update the FileList + get_file_list(); + + cb_FileSelect(gFvCtrl.pFileSelect, NULL); +} + +void cb_view_refreseh(Fl_Widget*w, void*) +{ + fileview_model_changed(); +} +/* +============================================================================ +Update file pointers in tFiles structure +============================================================================ +*/ +void adjust_file_pointers() +{ + // Calculate all BASIC file pointers +} + +/* +============================================================================ +Monitor routine for memory changes +============================================================================ +*/ +void fileview_mem_monitor(void) +{ + int unused, x, c; + int index; + char selectfile[15]; + + // Test if unused memory changed + unused = get_memory16(gStdRomDesc->sBeginVar); + if (unused == gPrevUnused) + return; + gPrevUnused = unused; + + // Test if file area changed + for (x = gLowmem; x < gPrevUnused; x++) + { + // Test if memory changed + if (get_memory8(x) != gRam[x-gLowmem]) + { + // Memory changed - Update file menu + strcpy(selectfile, gFvCtrl.tFiles[gFvCtrl.selectIndex].name); + get_file_list(); + + // Detect if any file pointers are incorrect because of data inserted + adjust_file_pointers(); + + // Update usage map + update_ram_usage_map(); + + // Reselect the previously selected file + index = -1; + for (c = 0; c < gFvCtrl.tCount; c++) + { + // Find the name of the previously selected file + if (strcmp(selectfile, gFvCtrl.tFiles[c].name) == 0) + { + index = c; + break; + } + } + + // Test if file still exists + if (index != -1) + { + gFvCtrl.pFileSelect->select(index+1); + cb_FileSelect(gFvCtrl.pFileSelect, NULL); + } + else + { + // File is gone! Select nothing +// gFvCtrl.pTb->remove(0, gFvCtrl.pTb->length()); + gFvCtrl.pView->clear(); + gFvCtrl.sAddress[0] = 0; + gFvCtrl.sDirEntry[0] = 0; + gFvCtrl.pAddress->label(gFvCtrl.sAddress); + gFvCtrl.pDirEntry->label(gFvCtrl.sDirEntry); + } + + // Save RAM for next comparison + for (; x < gPrevUnused; x++) + gRam[x-gLowmem] = get_memory8(x); + return; + } + } + + return; +} + +/* +============================================================================ +Routine to create the Model T File viewer window +============================================================================ +*/ +void cb_FileView(Fl_Widget* w, void*) +{ + Fl_Box* o; + + if (gfvw != NULL) + return; + + // Create File Viewer window + gfvw = new Fl_Double_Window(650, 480, "Model T File Viewer"); + gfvw->callback(cb_fvwin); + + // Create a menu for the new window. + gFvCtrl.pMenu = new Fl_Menu_Bar(0, 0, 700, MENU_HEIGHT-2); + gFvCtrl.pMenu->menu(gFileView_menuitems); + + o = new Fl_Box(20, 40, 80, 20, "File Directory"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + // Create a browser for the files + gFvCtrl.pFileSelect = new Fl_Hold_Browser(20, 65, 170, 270, 0); + gFvCtrl.pFileSelect->textfont(FL_COURIER); + gFvCtrl.pFileSelect->has_scrollbar(Fl_Browser_::VERTICAL); + gFvCtrl.pFileSelect->callback(cb_FileSelect); + + // Create a Text Editor / Text Buffer for the file display + gFvCtrl.pView = new Fl_Hold_Browser(200, 65, 420, 270, ""); + gFvCtrl.pView->has_scrollbar(Fl_Browser_::VERTICAL ); +// gFvCtrl.pView = new Fl_Text_Display(200, 65, 420, 270, ""); +// gFvCtrl.pTb = new Fl_Text_Buffer(); +// gFvCtrl.pView->buffer(gFvCtrl.pTb); + gFvCtrl.pView->textfont(FL_COURIER); + gFvCtrl.pView->textsize(12); +// gFvCtrl.pView->wrap_mode(56, 56); +// gFvCtrl.pView->end(); + + // Create a box for RAM + o = new Fl_Box(FL_NO_BOX, 40, 380, 100, 15, "RAM"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_NO_BOX, 40, 395, 100, 15, "Map"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + gFvCtrl.pRAM = new Fl_Usage_Box(100, 365, 516, 68); + gFvCtrl.pRAM->box(FL_BORDER_BOX); + gFvCtrl.pRAM->SetUsageColor(FV_SELECT_FILE_COLOR, fl_rgb_color(64, 64, 64)); + gFvCtrl.pRAM->SetUsageColor(FV_BASIC_FILE_COLOR , fl_rgb_color(96, 255,96)); + gFvCtrl.pRAM->SetUsageColor(FV_TEXT_FILE_COLOR , fl_rgb_color(96, 96, 255)); + gFvCtrl.pRAM->SetUsageColor(FV_CO_FILE_COLOR , fl_rgb_color(255, 96, 96)); + gFvCtrl.pRAM->SetUsageColor(FV_BASIC_VARS_COLOR , fl_rgb_color(255, 255, 96)); + gFvCtrl.pRAM->SetUsageColor(FV_DIR_COLOR , fl_rgb_color(255, 128, 0)); + gFvCtrl.pRAM->SetUsageColor(FV_SYS_VARS_COLOR , fl_rgb_color(0, 128, 255)); + gFvCtrl.pRAM->SetUsageColor(FV_LCD_BUF_COLOR , fl_rgb_color(225, 225, 0)); + + // Create Directory Entry display box + o = new Fl_Box(200, 40, 80, 20, "Dir Entry:"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + // Create a text box for showing Directory Entry information + gFvCtrl.pDirEntry = new Fl_Box(280, 40, 400, 20, ""); + gFvCtrl.pDirEntry->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + gFvCtrl.pDirEntry->labelfont(FL_COURIER); + + // Create a text box for showing the file address + gFvCtrl.pAddress = new Fl_Box(20, 340, 150, 20, ""); + gFvCtrl.pAddress->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + // Create color code boxes + o = new Fl_Box(FL_NO_BOX, 100, 440, 60, 15, "Free"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_DOWN_BOX, 150, 440, 15, 15, ""); + o->color(fl_rgb_color(255, 255, 255)); + + // Create color code boxes + o = new Fl_Box(FL_NO_BOX, 180, 440, 60, 15, "BASIC"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_DOWN_BOX, 230, 440, 15, 15, ""); + o->color(fl_rgb_color(96, 255, 96)); + + // Create color code boxes + o = new Fl_Box(FL_NO_BOX, 255, 440, 60, 15, "Text"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_DOWN_BOX, 300, 440, 15, 15, ""); + o->color(fl_rgb_color(96, 96, 255)); + + // Create color code boxes + o = new Fl_Box(FL_NO_BOX, 330, 440, 60, 15, "CO"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_DOWN_BOX, 365, 440, 15, 15, ""); + o->color(fl_rgb_color(255, 96, 96)); + + // Create color code boxes + o = new Fl_Box(FL_NO_BOX, 400, 440, 60, 15, "Dir"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_DOWN_BOX, 435, 440, 15, 15, ""); + o->color(fl_rgb_color(255, 128, 0)); + + // Create color code boxes + o = new Fl_Box(FL_NO_BOX, 475, 440, 60, 15, "Sys"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_DOWN_BOX, 510, 440, 15, 15, ""); + o->color(fl_rgb_color(0, 128, 255)); + + // Create color code boxes + o = new Fl_Box(FL_NO_BOX, 545, 440, 60, 15, "Select"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o = new Fl_Box(FL_DOWN_BOX, 595, 440, 15, 15, ""); + o->color(fl_rgb_color(64, 64, 64)); + + // Populate file list and usage map with data + get_file_list(); + update_ram_usage_map(); + + gfvw->show(); + +// mem_set_monitor_callback(fileview_mem_monitor); +} diff --git a/src/fileview.h b/src/fileview.h new file mode 100644 index 0000000..b57ff26 --- /dev/null +++ b/src/fileview.h @@ -0,0 +1,85 @@ +/* fileview.h */ + +/* $Id$ */ + +/* +* Copyright 2008 Ken Pettit +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +*/ + + +#ifndef FILEVIEW_H +#define FILEVIEW_H + +void fileview_model_changed(void); + +#ifdef __cplusplus +void cb_FileView(Fl_Widget* w, void*); +#endif + +#ifdef FILE_VIEW_MAIN + +typedef struct { + char name[12]; + unsigned short address; + unsigned short dir_address; + unsigned short size; + unsigned char type; +} file_view_files_t; + +typedef struct fileview_ctrl_struct +{ + Fl_Menu_Bar* pMenu; // Pointer to Menu bar + + Fl_Box* pDirAddress; // Pointer to Dir star taddress + char sDirAddr[20]; + Fl_Box* pDirEntry; // DirEntry information box + char sDirEntry[100]; // Text for directory entry + Fl_Box* pAddress; // Address information box + char sAddress[100]; // Text for Address entry + Fl_Hold_Browser* pFileSelect; // Pointer to Directory Table files + Fl_Hold_Browser* pView; // Pointer to Browser for file contents +// Fl_Text_Display* pView; // Pointer to the text display +// Fl_Text_Buffer* pTb; // Pointer to a text buffer for display + Fl_Usage_Box* pRAM; // Pointer to Usage bar for RAM + file_view_files_t tFiles[24]; // Storage for up to 24 files + int tCount; + + int selectIndex; // Index of active selection + Fl_Group* g; + +} fileview_ctrl_t; + +#define FV_SELECT_FILE_COLOR 1 +#define FV_BASIC_FILE_COLOR 2 +#define FV_TEXT_FILE_COLOR 3 +#define FV_CO_FILE_COLOR 4 +#define FV_BASIC_VARS_COLOR 5 +#define FV_DIR_COLOR 6 +#define FV_SYS_VARS_COLOR 7 +#define FV_LCD_BUF_COLOR 8 + +#endif + +#endif + diff --git a/src/intelhex.c b/src/intelhex.c index bb53a01..94ed8bb 100644 --- a/src/intelhex.c +++ b/src/intelhex.c @@ -41,6 +41,7 @@ #include #include +#include "gen_defs.h" #include "intelhex.h" #include "memory.h" diff --git a/src/lpt.cpp b/src/lpt.cpp index d05da3e..17fce58 100644 --- a/src/lpt.cpp +++ b/src/lpt.cpp @@ -411,6 +411,8 @@ void init_lpt(void) gLpt->UpdatePreferences(&virtualt_prefs); } + gpPrint->label("Idle"); + } /* diff --git a/src/m100emu.c b/src/m100emu.c index fecded1..18ab1ec 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -59,6 +59,7 @@ #include "serial.h" #include "lpt.h" #include "clock.h" +#include "fileview.h" int fullspeed=0; int gModel = MODEL_M100; @@ -68,7 +69,8 @@ extern uchar *gMemory[64]; extern uchar gMsplanROM[32768]; extern uchar gOptROM[32768]; -mem_monitor_cb gMemMonitor = NULL; +mem_monitor_cb gMemMonitor1 = NULL; +mem_monitor_cb gMemMonitor2 = NULL; char op[26]; UINT64 cycles=0; @@ -734,7 +736,18 @@ __inline void check_interrupts(void) void mem_set_monitor_callback(mem_monitor_cb cb) { - gMemMonitor = cb; + if (gMemMonitor1 == NULL) + gMemMonitor1 = cb; + else if (gMemMonitor2 == NULL) + gMemMonitor2 = cb; +} + +void mem_clear_monitor_callback(mem_monitor_cb cb) +{ + if (gMemMonitor1 == cb) + gMemMonitor1 = NULL; + else if (gMemMonitor2 == cb) + gMemMonitor2 = NULL; } void remote_switch_model(int model) @@ -785,8 +798,10 @@ void maint(void) twice_flag = 0; // Check if we need to update the Memory Editor monitor - if (gMemMonitor != NULL) - gMemMonitor(); + if (gMemMonitor1 != NULL) + gMemMonitor1(); + if (gMemMonitor2 != NULL) + gMemMonitor2(); } else twice_flag++; diff --git a/src/m100emu.h b/src/m100emu.h index dd2eb75..30ad1d0 100644 --- a/src/m100emu.h +++ b/src/m100emu.h @@ -53,6 +53,7 @@ double hirestimer(void); typedef void (*mem_monitor_cb)(void); typedef void (*debug_monitor_callback)(int reason); void mem_set_monitor_callback(mem_monitor_cb cb); +void mem_clear_monitor_callback(mem_monitor_cb cb); int debug_set_monitor_callback(debug_monitor_callback pCallback); void debug_clear_monitor_callback(debug_monitor_callback pCallback); void debug_step(void); diff --git a/src/memedit.cpp b/src/memedit.cpp index 03856f2..f1f9555 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -54,6 +54,8 @@ #include "memory.h" #include "cpu.h" #include "cpuregs.h" +#include "fileview.h" + extern "C" { #include "intelhex.h" @@ -105,6 +107,7 @@ extern "C" { extern uchar gReMem; /* Flag indicating if ReMem emulation enabled */ extern uchar gRampac; +void memory_monitor_cb(void); } @@ -121,7 +124,7 @@ Fl_Menu_Item gMemEdit_menuitems[] = { { "Disassembler", 0, disassembler_cb }, { "Peripheral Devices", 0, cb_PeripheralDevices }, // { "Simulation Log Viewer", 0, 0 }, - { "Model T File Viewer", 0, 0 }, + { "Model T File Viewer", 0, cb_FileView }, { 0 }, { 0 } @@ -141,7 +144,7 @@ Callback routine for the Peripherial Devices window void cb_memeditwin (Fl_Widget* w, void*) { gmew->hide(); - mem_set_monitor_callback(NULL); + mem_clear_monitor_callback(memory_monitor_cb); delete gmew; gmew = NULL; } diff --git a/src/memory.c b/src/memory.c index 0be1a75..6d41bc9 100644 --- a/src/memory.c +++ b/src/memory.c @@ -2391,3 +2391,22 @@ void remem_flash_proc_timer(void) } +void rex_set8(unsigned short address, unsigned char val) +{ +} + +void load_rex2_ram(void) +{ +} + +void save_rex2_ram(void) +{ +} + +void load_rex_flash(void) +{ +} + +void save_rex_flash(void) +{ +} diff --git a/src/memory.h b/src/memory.h index 571068b..bde1fe9 100644 --- a/src/memory.h +++ b/src/memory.h @@ -102,12 +102,27 @@ extern "C" { #define REGION_FLASH1 8 #define REGION_FLASH2 9 #define REGION_RAMPAC 10 +#define REGION_REX_FLASH 11 +#define REGION_REX2_RAM 12 +#define REX 1 +#define REX2 2 + +#define REX_ROM_REPLACEMENT 0x01 +#define REX2_RAM_MODE 0x02 + +typedef struct { + int gFlashState; + UINT64 gFlashTime; + int gFlashBusy; + char* pFlash; +} amd_flash_t; extern unsigned char *gMemory[64]; extern unsigned char gSysROM[65536]; extern unsigned char gBaseMemory[65536]; extern unsigned char gReMem; +extern int gRex; void init_mem(void); void reinit_mem(void); @@ -119,6 +134,10 @@ void load_remem_ram(void); void save_rampac_ram(void); void save_remem_ram(void); void reload_sys_rom(void); +void save_rex2_ram(void); +void save_rex_flash(void); +void load_rex2_ram(void); +void load_rex_flash(void); unsigned char get_memory8(unsigned short address); unsigned short get_memory16(unsigned short address); @@ -141,6 +160,8 @@ void remem_copy_block_to_mmu(int block); unsigned char remem_flash_sm_read(unsigned short address); void remem_flash_proc_timer(void); void patch_vt_version(char* pMem, int size); +unsigned char rex_read(unsigned short address); +void rex_set8(unsigned short address, unsigned char val); void save_ram(void); void load_ram(void); diff --git a/src/periph.cpp b/src/periph.cpp index 6d172e3..2727225 100644 --- a/src/periph.cpp +++ b/src/periph.cpp @@ -56,6 +56,7 @@ #include "memedit.h" #include "cpuregs.h" #include "lpt.h" +#include "fileview.h" void cb_Ide(Fl_Widget* w, void*) ; @@ -147,7 +148,7 @@ Fl_Menu_Item gPeriph_menuitems[] = { { "Disassembler", 0, disassembler_cb }, { "Memory Editor", 0, cb_MemoryEditor }, // { "Simulation Log Viewer", 0, 0 }, - { "Model T File Viewer", 0, 0 }, + { "Model T File Viewer", 0, cb_FileView }, { 0 }, { 0 } diff --git a/src/rememcfg.cpp b/src/rememcfg.cpp index 11a78ba..cd9a25a 100644 --- a/src/rememcfg.cpp +++ b/src/rememcfg.cpp @@ -50,6 +50,7 @@ #include "memory.h" #include "io.h" #include "VirtualT.h" +#include "fileview.h" #define MENU_HEIGHT 32 @@ -80,7 +81,7 @@ Fl_Menu_Item gRememCfg_menuitems[] = { { "Memory Editor", 0, cb_MemoryEditor }, { "Peripheral Devices", 0, cb_PeripheralDevices }, // { "Simulation Log Viewer", 0, 0 }, - { "Model T File Viewer", 0, 0 }, + { "Model T File Viewer", 0, cb_FileView }, { 0 }, { 0 } }; diff --git a/src/remote.cpp b/src/remote.cpp index 0d69cb6..20890fb 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -65,7 +65,8 @@ int gRadix = 10; // Radix used for reporting values int gRemoteBreak[65536];// Storage of breakpoint types int gBreakActive = 0; // Indicates if an active debug was reported int gHaltActive = 0; // Indicates if an active halt was issued -int gStepOverBreak = -1;// Indicates if a break was for a "Step Over" +int gStepOverBreak = 0; // Indicates if a break was for a "Step Over" +unsigned char gLastIns = 0; // Saves last instruction for stepover break int gLcdTrapAddr = -1; // Address of LCD level 6 output routine int gLcdRowAddr = -1; // Address of LCD output row storage int gMonitorLcd = 0; // Flag indicating if LCD is monitored @@ -414,8 +415,6 @@ void cb_remote_debug(int reason) // Test if callback is for an interrupt if (reason == DEBUG_INTERRUPT) { -// gIntActive = TRUE; -// gIntSP = SP; return; } @@ -466,7 +465,7 @@ void cb_remote_debug(int reason) } // Report break to client socket - if (gStopped && (PC != gStepOverBreak)) + if (gStopped) { if (gSocketOpened) { @@ -497,6 +496,22 @@ void cb_remote_debug(int reason) } } } + // Check for step-over break condition + if (!gStopped && gStepOverBreak) + { + // Check if SP equals gStepOverBreak upon return + if (gStepOverBreak == SP) + { + // Check if we are about to execute a retrun + if ((gLastIns == 0xC9) || ((gLastIns & 0xC7) == 0xC0)) + { + // Stop the processor + gStopped = 1; + } + } + // Save this instruction for next test + gLastIns = INS; + } } // Trap output to the display @@ -684,7 +699,7 @@ Step command: Single steps the CPU the specified */ std::string cmd_step_over(ServerSocket& sock, std::string& args) { - int value, inst, saveBrk; + int value, inst; std::string next_arg; std::string more_args; int c, addr; @@ -715,7 +730,7 @@ std::string cmd_step_over(ServerSocket& sock, std::string& args) // Check if instruction is a CALL type inst. if (((inst & 0xC7) == 0xC4) || (inst == 0xCD) || ((inst & 0xC7) == 0xC7)) { - if ((inst & 0xC7) == 0xC7) +/* if ((inst & 0xC7) == 0xC7) { if ((inst == 0xCF) || (inst == 0xFF)) { @@ -742,6 +757,10 @@ std::string cmd_step_over(ServerSocket& sock, std::string& args) gRemoteBreak[addr] = 0x3F; gStepOverBreak = addr; } +*/ + + // Set gStepOverBreak to current SP */ + gStepOverBreak = SP; // Take the processor out of STOP mode lock_remote(); @@ -752,8 +771,8 @@ std::string cmd_step_over(ServerSocket& sock, std::string& args) while (!gStopped) fl_wait(0.001); - gRemoteBreak[addr] = saveBrk; - gStepOverBreak = -1; +// gRemoteBreak[addr] = saveBrk; + gStepOverBreak = 0; } else { diff --git a/src/setup.cpp b/src/setup.cpp index 88e0180..6aba70b 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -114,11 +114,17 @@ typedef struct memory_ctrl_struct Fl_Round_Button* pReMem; Fl_Round_Button* pRampac; Fl_Round_Button* pReMem_Rampac; + Fl_Round_Button* pRex; + Fl_Round_Button* pRex2; Fl_Check_Button* pReMemOverride; Fl_Input* pReMemFile; Fl_Input* pRampacFile; + Fl_Input* pRexFlashFile; + Fl_Input* pRex2RamFile; Fl_Button* pReMemBrowse; Fl_Button* pRampacBrowse; + Fl_Button* pRexFlashBrowse; + Fl_Button* pRex2RamBrowse; Fl_Box* pReMemText; Fl_Check_Button* pOptRomRW; Fl_Check_Button* pShowVersion; @@ -602,11 +608,18 @@ void save_memory_preferences(void) strcat(pref, "_ReMemFile"); virtualt_prefs.set(pref, mem_setup.remem_file); - strcpy(pref, str); strcat(pref, "_RampacFile"); virtualt_prefs.set(pref, mem_setup.rampac_file); + strcpy(pref, str); + strcat(pref, "_RexFlashFile"); + virtualt_prefs.set(pref, mem_setup.rex_flash_file); + + strcpy(pref, str); + strcat(pref, "_Rex2RamFile"); + virtualt_prefs.set(pref, mem_setup.rex2_ram_file); + strcpy(pref, str); strcat(pref, "_OptRomRW"); virtualt_prefs.set(pref, gOptRomRW); @@ -652,6 +665,24 @@ void load_memory_preferences(void) if (strlen(mem_setup.rampac_file) == 0) strcpy(mem_setup.rampac_file, path); + // Load Rex Flash filename based on Model + strcpy(pref, str); + strcat(pref, "_RexFlashFile"); + get_emulation_path(path, gModel); + strcat(path, "rex_flash.bin"); + virtualt_prefs.get(pref, mem_setup.rex_flash_file, path, 256); + if (strlen(mem_setup.rex_flash_file) == 0) + strcpy(mem_setup.rex_flash_file, path); + + // Load Rex2 Ram filename based on Model + strcpy(pref, str); + strcat(pref, "_Rex2RamFile"); + get_emulation_path(path, gModel); + strcat(path, "rex2_ram.bin"); + virtualt_prefs.get(pref, mem_setup.rex2_ram_file, path, 256); + if (strlen(mem_setup.rex2_ram_file) == 0) + strcpy(mem_setup.rex2_ram_file, path); + // Load OptRom R/W or R/O option strcpy(pref, str); strcat(pref, "_OptRomRW"); @@ -677,12 +708,13 @@ void cb_memory_OK(Fl_Widget* w, void*) Save Base memory if needed =================================================== */ - if ((mem_setup.mem_mode == SETUP_MEM_RAMPAC) || (mem_setup.mem_mode == SETUP_MEM_BASE)) + if ((mem_setup.mem_mode == SETUP_MEM_RAMPAC) || (mem_setup.mem_mode == SETUP_MEM_BASE) || + (mem_setup.mem_mode == SETUP_MEM_REX)) save_ram(); /* =================================================== - First check if ReMem memory needs to be deallocated + Check if ReMem memory needs to be deallocated =================================================== */ if ((mem_setup.mem_mode == SETUP_MEM_REMEM) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC)) @@ -703,11 +735,29 @@ void cb_memory_OK(Fl_Widget* w, void*) if ((mem_setup.mem_mode == SETUP_MEM_RAMPAC) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC)) { // Check if we are turning Host port emulation off -// if ((mem_ctrl.pRampac->value() != 1) && (mem_ctrl.pReMem_Rampac->value() != 1)) -// { save_rampac_ram(); // Write Rampac memory to file -// free_rampac_mem(); // Deallocate Rampac memory -// } + } + + /* + =================================================== + Check if Rex Flash needs to be saved / deallocated + =================================================== + */ + if ((mem_setup.mem_mode == SETUP_MEM_REX) || (mem_setup.mem_mode == SETUP_MEM_REX2)) + { + // Save Rex Flash + save_rex_flash(); // Write Rex flash memory to file + } + + /* + =================================================== + Check if Rex Flash needs to be saved / deallocated + =================================================== + */ + if (mem_setup.mem_mode == SETUP_MEM_REX2) + { + // Save Rex Flash + save_rex2_ram(); // Write Rex RAM memory to file } // Save old mem_mode so we know when to load data from file @@ -724,6 +774,10 @@ void cb_memory_OK(Fl_Widget* w, void*) mem_setup.mem_mode = SETUP_MEM_REMEM; else if (mem_ctrl.pReMem_Rampac->value() == 1) mem_setup.mem_mode = SETUP_MEM_REMEM_RAMPAC; + else if (mem_ctrl.pRex->value() == 1) + mem_setup.mem_mode = SETUP_MEM_REX; + else if (mem_ctrl.pRex2->value() == 1) + mem_setup.mem_mode = SETUP_MEM_REX2; // Get OptRom R/W Enable setting gOptRomRW = mem_ctrl.pOptRomRW->value(); @@ -743,8 +797,9 @@ void cb_memory_OK(Fl_Widget* w, void*) Load Base memory if needed =================================================== */ - if ((mem_setup.mem_mode == SETUP_MEM_RAMPAC) || (mem_setup.mem_mode == SETUP_MEM_BASE)) - load_ram(); + if ((mem_setup.mem_mode == SETUP_MEM_RAMPAC) || (mem_setup.mem_mode == SETUP_MEM_BASE) || + (mem_setup.mem_mode == SETUP_MEM_REX)) + load_ram(); // If we are in ReMem or ReMem_Rampac mode, check if ReMem filename changed if ((mem_setup.mem_mode == SETUP_MEM_REMEM) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC)) @@ -790,9 +845,55 @@ void cb_memory_OK(Fl_Widget* w, void*) } } + // If we are in Rex or Rex2 mode, check if Rex Flash filename changed + if ((mem_setup.mem_mode == SETUP_MEM_REX) || (mem_setup.mem_mode == SETUP_MEM_REX2)) + { + // Check if we are changing Rampac filename + if (strcmp(mem_ctrl.pRexFlashFile->value(), mem_setup.rex_flash_file) != 0) + { + // Save memory to old file + save_rex_flash(); + + // Copy new filename to preferences + strcpy(mem_setup.rex_flash_file, mem_ctrl.pRexFlashFile->value()); + + // Load Rampac data from new file + load_rex_flash(); + } + else if ((old_mode != SETUP_MEM_REX) && (old_mode != SETUP_MEM_REX2)) + { + // Load Rampac data from file + load_rex_flash(); + } + } + + // If we are in Rex or Rex2 mode, check if Rex Flash filename changed + if (mem_setup.mem_mode == SETUP_MEM_REX2) + { + // Check if we are changing Rampac filename + if (strcmp(mem_ctrl.pRex2RamFile->value(), mem_setup.rex2_ram_file) != 0) + { + // Save memory to old file + save_rex2_ram(); + + // Copy new filename to preferences + strcpy(mem_setup.rex2_ram_file, mem_ctrl.pRex2RamFile->value()); + + // Load Rampac data from new file + load_rex2_ram(); + } + else if (old_mode != SETUP_MEM_REX2) + { + // Load Rampac data from file + load_rex2_ram(); + } + } + // Copy new ReMem filename and Rampac filename to preferences strcpy(mem_setup.remem_file, mem_ctrl.pReMemFile->value()); strcpy(mem_setup.rampac_file, mem_ctrl.pRampacFile->value()); + strcpy(mem_setup.rex_flash_file, mem_ctrl.pRexFlashFile->value()); + strcpy(mem_setup.rex2_ram_file, mem_ctrl.pRex2RamFile->value()); // Save memory preferences to file save_memory_preferences(); @@ -871,6 +972,120 @@ void cb_remem_browse(Fl_Widget* w, void*) delete fc; } +void cb_rex_browse(Fl_Widget* w, void*) +{ + int count; + Fl_File_Chooser *fc; + const char *filename; + const char *filename_name; + int len; + char mstr[16]; + char mstr_upper[16]; + char path[256]; + int c; + + // Create chooser window to pick file + strcpy(path, mem_ctrl.pRexFlashFile->value()); + fc = new Fl_File_Chooser(path,"Binary Files (*.bin)",2,"Choose Rex Flash File"); + fc->preview(0); + fc->show(); + + // Show Chooser window + while (fc->visible()) + Fl::wait(); + + count = fc->count(); + if (count == 0) + { + delete fc; + return; + } + + // Get Filename + filename = fc->value(1); + if (filename == 0) + { + delete fc; + return; + } + len = strlen(filename); + + // Copy filename to edit field + filename_name = fl_filename_name(filename); + + get_model_string(mstr, gModel); + strcpy(mstr_upper, mstr); + for (c = strlen(mstr_upper)-1; c >= 0; c--) + mstr_upper[c] = toupper(mstr_upper[c]); + if (strstr(filename, mstr) || strstr(filename, mstr_upper)) + { + get_emulation_path(path, gModel); + strcat(path, filename_name); + mem_ctrl.pRexFlashFile->value(path); + } + else + mem_ctrl.pRexFlashFile->value(filename); + + delete fc; +} + +void cb_rex2_browse(Fl_Widget* w, void*) +{ + int count; + Fl_File_Chooser *fc; + const char *filename; + const char *filename_name; + int len; + char mstr[16]; + char mstr_upper[16]; + char path[256]; + int c; + + // Create chooser window to pick file + strcpy(path, mem_ctrl.pRex2RamFile->value()); + fc = new Fl_File_Chooser(path,"Binary Files (*.bin)",2,"Choose Rex2 RAM File"); + fc->preview(0); + fc->show(); + + // Show Chooser window + while (fc->visible()) + Fl::wait(); + + count = fc->count(); + if (count == 0) + { + delete fc; + return; + } + + // Get Filename + filename = fc->value(1); + if (filename == 0) + { + delete fc; + return; + } + len = strlen(filename); + + // Copy filename to edit field + filename_name = fl_filename_name(filename); + + get_model_string(mstr, gModel); + strcpy(mstr_upper, mstr); + for (c = strlen(mstr_upper)-1; c >= 0; c--) + mstr_upper[c] = toupper(mstr_upper[c]); + if (strstr(filename, mstr) || strstr(filename, mstr_upper)) + { + get_emulation_path(path, gModel); + strcat(path, filename_name); + mem_ctrl.pRex2RamFile->value(path); + } + else + mem_ctrl.pRex2RamFile->value(filename); + + delete fc; +} + void cb_radio_base_memory (Fl_Widget* w, void*) { mem_ctrl.pRampacFile->deactivate(); @@ -879,6 +1094,10 @@ void cb_radio_base_memory (Fl_Widget* w, void*) mem_ctrl.pReMemFile->deactivate(); mem_ctrl.pReMemBrowse->deactivate(); mem_ctrl.pReMemText->hide(); + mem_ctrl.pRexFlashFile->deactivate(); + mem_ctrl.pRexFlashBrowse->deactivate(); + mem_ctrl.pRex2RamFile->deactivate(); + mem_ctrl.pRex2RamBrowse->deactivate(); } void cb_radio_remem (Fl_Widget* w, void*) @@ -889,6 +1108,10 @@ void cb_radio_remem (Fl_Widget* w, void*) mem_ctrl.pRampacFile->deactivate(); mem_ctrl.pRampacBrowse->deactivate(); mem_ctrl.pReMemText->show(); + mem_ctrl.pRexFlashFile->deactivate(); + mem_ctrl.pRexFlashBrowse->deactivate(); + mem_ctrl.pRex2RamFile->deactivate(); + mem_ctrl.pRex2RamBrowse->deactivate(); } void cb_radio_rampac (Fl_Widget* w, void*) @@ -899,6 +1122,10 @@ void cb_radio_rampac (Fl_Widget* w, void*) mem_ctrl.pReMemFile->deactivate(); mem_ctrl.pReMemBrowse->deactivate(); mem_ctrl.pReMemText->hide(); + mem_ctrl.pRexFlashFile->deactivate(); + mem_ctrl.pRexFlashBrowse->deactivate(); + mem_ctrl.pRex2RamFile->deactivate(); + mem_ctrl.pRex2RamBrowse->deactivate(); } void cb_radio_remem_and_rampac (Fl_Widget* w, void*) @@ -909,6 +1136,38 @@ void cb_radio_remem_and_rampac (Fl_Widget* w, void*) mem_ctrl.pRampacFile->activate(); mem_ctrl.pRampacBrowse->activate(); mem_ctrl.pReMemText->show(); + mem_ctrl.pRexFlashFile->deactivate(); + mem_ctrl.pRexFlashBrowse->deactivate(); + mem_ctrl.pRex2RamFile->deactivate(); + mem_ctrl.pRex2RamBrowse->deactivate(); +} + +void cb_radio_rex (Fl_Widget* w, void*) +{ + mem_ctrl.pRampacFile->deactivate(); + mem_ctrl.pRampacBrowse->deactivate(); + mem_ctrl.pReMemOverride->deactivate(); + mem_ctrl.pReMemFile->deactivate(); + mem_ctrl.pReMemBrowse->deactivate(); + mem_ctrl.pReMemText->hide(); + mem_ctrl.pRexFlashFile->activate(); + mem_ctrl.pRexFlashBrowse->activate(); + mem_ctrl.pRex2RamFile->deactivate(); + mem_ctrl.pRex2RamBrowse->deactivate(); +} + +void cb_radio_rex2 (Fl_Widget* w, void*) +{ + mem_ctrl.pRampacFile->deactivate(); + mem_ctrl.pRampacBrowse->deactivate(); + mem_ctrl.pReMemOverride->deactivate(); + mem_ctrl.pReMemFile->deactivate(); + mem_ctrl.pReMemBrowse->deactivate(); + mem_ctrl.pReMemText->hide(); + mem_ctrl.pRexFlashFile->activate(); + mem_ctrl.pRexFlashBrowse->activate(); + mem_ctrl.pRex2RamFile->activate(); + mem_ctrl.pRex2RamBrowse->activate(); } void cb_memory_cancel (Fl_Widget* w, void*) @@ -982,7 +1241,7 @@ Routine to create the PeripheralSetup Window and tabs void cb_MemorySetup (Fl_Widget* w, void*) { // Create Peripheral Setup window - gmsw = new Fl_Window(420, 310, "Memory Emulation Options"); + gmsw = new Fl_Window(420, 415, "Memory Emulation Options"); gmsw->callback(cb_memorywin); // Create items on the Tab @@ -1049,19 +1308,62 @@ void cb_MemorySetup (Fl_Widget* w, void*) mem_ctrl.pReMemText->hide(); } + // Create Rex radio button + mem_ctrl.pRex = new Fl_Round_Button(20, 210, 270, 20, "Rex (1 Meg Flash Option ROM)"); + mem_ctrl.pRex->type(FL_RADIO_BUTTON); + mem_ctrl.pRex->callback(cb_radio_rex); + if (mem_setup.mem_mode == SETUP_MEM_REX) + mem_ctrl.pRex->value(1); + + // Create Rex radio button + mem_ctrl.pRex2 = new Fl_Round_Button(20, 235, 270, 20, "Rex2 (1 Meg Opt ROM + 256K SRAM)"); + mem_ctrl.pRex2->type(FL_RADIO_BUTTON); + mem_ctrl.pRex2->callback(cb_radio_rex2); + if (mem_setup.mem_mode == SETUP_MEM_REX2) + mem_ctrl.pRex2->value(1); + + // =============================================== + // Setup Rex Flash File edit field and Browser button + // =============================================== + mem_ctrl.pRexFlashFile = new Fl_Input(105, 260, 210, 20, "Flash File"); + mem_ctrl.pRexFlashFile->value(mem_setup.rex_flash_file); + mem_ctrl.pRexFlashBrowse = new Fl_Button(330, 257, 60, 30, "Browse"); + mem_ctrl.pRexFlashBrowse->callback((Fl_Callback*)cb_rex_browse); + + if ((mem_setup.mem_mode != SETUP_MEM_REX) && (mem_setup.mem_mode != SETUP_MEM_REX2)) + { + mem_ctrl.pRexFlashFile->deactivate(); + mem_ctrl.pRexFlashBrowse->deactivate(); + } + + // =============================================== + // Setup Rex Flash File edit field and Browser button + // =============================================== + mem_ctrl.pRex2RamFile = new Fl_Input(105, 295, 210, 20, "RAM File"); + mem_ctrl.pRex2RamFile->value(mem_setup.rex2_ram_file); + mem_ctrl.pRex2RamBrowse = new Fl_Button(330, 292, 60, 30, "Browse"); + mem_ctrl.pRex2RamBrowse->callback((Fl_Callback*)cb_rex2_browse); + + if (mem_setup.mem_mode != SETUP_MEM_REX2) + { + mem_ctrl.pRex2RamFile->deactivate(); + mem_ctrl.pRex2RamBrowse->deactivate(); + } + + // Option ROM RW Enable - mem_ctrl.pOptRomRW = new Fl_Check_Button(20, 210, 210, 20, "Make Option ROM R/W"); + mem_ctrl.pOptRomRW = new Fl_Check_Button(20, 320, 210, 20, "Make Option ROM R/W"); mem_ctrl.pOptRomRW->value(gOptRomRW); // Show Version Checkbox - mem_ctrl.pShowVersion = new Fl_Check_Button(20, 240, 210, 20, "Patch ROM on load to show VirtualT version"); + mem_ctrl.pShowVersion = new Fl_Check_Button(20, 345, 210, 20, "Patch ROM on load to show VirtualT version"); mem_ctrl.pShowVersion->value(gShowVersion); // OK button - { Fl_Button* o = new Fl_Button(140, 270, 60, 30, "Cancel"); + { Fl_Button* o = new Fl_Button(140, 375, 60, 30, "Cancel"); o->callback((Fl_Callback*)cb_memory_cancel); } - { Fl_Return_Button* o = new Fl_Return_Button(220, 270, 60, 30, "OK"); + { Fl_Return_Button* o = new Fl_Return_Button(220, 375, 60, 30, "OK"); o->callback((Fl_Callback*)cb_memory_OK); } diff --git a/src/setup.h b/src/setup.h index b42e88c..fc15526 100644 --- a/src/setup.h +++ b/src/setup.h @@ -71,6 +71,8 @@ typedef struct memory_setup int remem_override; // Override setting for ReMem's Rampac char remem_file[256]; // Filename for ReMem storage char rampac_file[256]; // Filename for RamPac storage + char rex_flash_file[256]; // Rex flash file + char rex2_ram_file[256]; // Rex2 RAM file } memory_setup_t; extern memory_setup_t mem_setup; @@ -86,7 +88,9 @@ enum { SETUP_MEM_BASE, SETUP_MEM_RAMPAC, SETUP_MEM_REMEM, - SETUP_MEM_REMEM_RAMPAC + SETUP_MEM_REMEM_RAMPAC, + SETUP_MEM_REX, + SETUP_MEM_REX2 }; #ifdef __cplusplus From 49a37e15158583d7a781ffce3de9b6bdb9571195 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 4 Nov 2008 07:35:11 +0000 Subject: [PATCH 152/327] Added files to support Model T file viewer. --- VirtualT.suo | Bin 79360 -> 151040 bytes VirtualT.vcproj | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/VirtualT.suo b/VirtualT.suo index 5bb89182605e0cda91dff17c3d507fccdbe9fb56..f74589178fa77835b6803d79530c4ac6778a5b22 100644 GIT binary patch literal 151040 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 F{RW_VvaJ9B literal 79360 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 Kok3mqNB%$F_l>9k diff --git a/VirtualT.vcproj b/VirtualT.vcproj index a95e7ab..0020c91 100644 --- a/VirtualT.vcproj +++ b/VirtualT.vcproj @@ -329,6 +329,10 @@ /> + + @@ -669,6 +673,10 @@ /> + + @@ -1088,6 +1096,10 @@ RelativePath=".\src\file.h" > + + @@ -1132,6 +1144,10 @@ RelativePath=".\src\rememcfg.h" > + + @@ -1297,6 +1313,10 @@ Name="Resource Files" Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" > + + From 85e7729388eea3d9e2fd1348ec8069a1073403ba Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 4 Nov 2008 07:35:42 +0000 Subject: [PATCH 153/327] Added change log for fullscreen mode. --- release.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/release.txt b/release.txt index 72a1495..6472e53 100644 --- a/release.txt +++ b/release.txt @@ -15,6 +15,15 @@ v1.4 Not released yet data. This has been corrected. Also The last line of data would not be displayed if the number of lines that would fit in the window was odd. This has also been fixed. +2. Fixed a bug with cold boot in T200 emulation mode. + +3. Added Model T File Viewer window. This window allows selection of files in the Model T + directory and provides details regarding the storage location for the directory entry + and the actual file contents. Also provides a view of the file's contents. + +4. Added fullscreen display mode with automatic adjustment of multiplication factor. This + feature was added to support sub-notbook platforms with smaller display resolutions that + cannot display full window borders well. ======================= v1.3 September 24 2008 From 19c9ae0a47aacced23dff637294a06e1067612b6 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 4 Nov 2008 16:42:15 +0000 Subject: [PATCH 154/327] Added Window Icon resource. --- ModelT.ico | Bin 0 -> 766 bytes VirtualT.rc | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++ resource.h | 16 ++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 ModelT.ico create mode 100644 VirtualT.rc create mode 100644 resource.h diff --git a/ModelT.ico b/ModelT.ico new file mode 100644 index 0000000000000000000000000000000000000000..eb6e995a95f3b38fe7a78828ac26f9a2a612165e GIT binary patch literal 766 zcmchTF&e@k4256)9N6OI+|grrw2ZxlSLtyaxdHy6?FX$c4*DRF@RAom8W`hvk#yGc zBwg`t*ofV+f%6Ku4UrwTz$K>KmyHz{bItP%QR-AF;bDw8iseffMIEx0oL31m0%lW; z*pwSATVwHv3uO(&yM%15xO&#flZpNg2YvYNvbdE;BCZkJJKyV<2mPlhO?+hHKcjw) mr Date: Wed, 5 Nov 2008 05:25:40 +0000 Subject: [PATCH 155/327] Fixed to compile on Visual C++ 2008 Express Edition --- VirtualT.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VirtualT.rc b/VirtualT.rc index ffef32f..98cc38a 100644 --- a/VirtualT.rc +++ b/VirtualT.rc @@ -7,7 +7,7 @@ // // Generated from the TEXTINCLUDE 2 resource. // -#include "afxres.h" +#include "windows.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS From cca0f8e00eb6a0dec008b607f0b57e52672cd714 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 31 Dec 2008 05:06:15 +0000 Subject: [PATCH 156/327] Added button to Serial Monitor Tab to allow saving serial log to a file. --- src/periph.cpp | 219 +++++++++++++++++++++++++++++++++++++++++++++---- src/periph.h | 1 + 2 files changed, 205 insertions(+), 15 deletions(-) diff --git a/src/periph.cpp b/src/periph.cpp index 2727225..dba8f43 100644 --- a/src/periph.cpp +++ b/src/periph.cpp @@ -278,7 +278,6 @@ void cb_lpt_save (Fl_Widget* w, void*) // Test for Yes if (ret == 1) { - printf ("Yes selected\n"); break; } } @@ -538,19 +537,14 @@ void update_com_port_settings() periph_ctrl.com.sComMdm[0] = 0; } -void cb_test_data(Fl_Widget* w, void*) +/* +============================================================================ +Routine to create the PeripheralSetup Window and tabs +============================================================================ +*/ +void cb_save_serial_log(Fl_Widget* w, void*) { - int x; - - for (x = 0; x < 512; x++) - { - Fl::wait(.001); - periph_ctrl.com.pLog->AddByte(x & 0x10, (x&0x7F) | 0x40, 0); - } - periph_ctrl.com.pLog->AddByte(x & 0x10, 'T', 0); - periph_ctrl.com.pLog->AddByte(x & 0x10, 'e', 0); - periph_ctrl.com.pLog->AddByte(x & 0x10, 's', 0); - periph_ctrl.com.pLog->AddByte(x & 0x10, 't', 0); + periph_ctrl.com.pLog->SaveLog(); } /* ============================================================================ @@ -708,8 +702,8 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) periph_ctrl.com.pFont->add("16"); periph_ctrl.com.pFont->value(0); - Fl_Button *but = new Fl_Button(440, 360, 60, 25, "Test"); - but->callback(cb_test_data); + Fl_Button *but = new Fl_Button(430, 360, 80, 25, "Save Log"); + but->callback(cb_save_serial_log); periph_ctrl.com.g->end(); @@ -1568,3 +1562,198 @@ int T100_ComMon::handle(int event) return 1; } + +/* +============================================================================ +Routine to save serial log to a file in ASCII format. +============================================================================ +*/ +#define CLE_RX 1 +#define CLE_TX 2 +void T100_ComMon::SaveLog(void) +{ + int bytesPerLine = 16; + int line, col, cnt, rxtx, fill; + comLogEntry_t *cle; + TcomLogBlock *clb; + int index; + char string[4], outLine[90]; + Fl_File_Chooser *fc; + const char *filename; + FILE* fd; + unsigned char bytes[16]; + + // Create a file chooser + fc = new Fl_File_Chooser(".","*.{txt,log}", Fl_File_Chooser::CREATE, + "Choose file for Serial Log"); + + while (1) + { + // Show the file chooser + fc->show(); + while (fc->visible()) + Fl::wait(); + + // Validate a file was selected + if (fc->value() == 0) + return; + + // Validate length of filename + if (strlen(fc->value()) == 0) + return; + + // Check if the file exists + if ((fd = fopen(fc->value(), "r")) != NULL) + { + fclose(fd); + int ret = fl_choice("Overwrite existing file?", "Cancel", "Yes", "No"); + + // Test for Cancel + if (ret == 0) + { + // Delete the file chooser and return + delete fc; + return; + } + + // Test for Yes + if (ret == 1) + { + break; + } + } + else + break; + } + + // Open the file + filename = fc->value(1); + fd = fopen(filename, "w+"); + if (fd == NULL) + { + delete fc; + fl_message("Error creating log file"); + return; + } + + // Write log data to file. First write a Header so we know it was generated by VirtualT, not NADSBox + fprintf(fd, "Serial Hex Log from VirtualT\n"); + + // Get pointer/index of first comLogEntry of first line/col + clb = m_LineStarts[0].clb; + index = m_LineStarts[0].index; + + line = 0; + rxtx = 0; + cnt = 0; + cle = NULL; + index = 0; + while (clb != NULL) + { + if (index >= clb->used) + break; + + while (cnt < bytesPerLine) + { + if (index >= clb->used) + break; + + // Get pointer to next comLogEntry + cle = &clb->entries[index]; + + // Test if this entry's rx/tx marker is different from current packet + if ((rxtx != 0) && ((cle->flags & 0x80) && (rxtx == CLE_RX) || (!(cle->flags & 0x80) && (rxtx == CLE_TX)))) + { + // This byte doesn't match the current line! Terminate the current line and start a new one + fill = 0; + while (cnt + fill++ < bytesPerLine) + strcat(outLine, " "); + strcat(outLine, " "); + + // Now append the ASCII representation of the data + col = strlen(outLine); + for (fill = 0; fill < cnt; fill++) + { + if ((bytes[fill] < ' ') || (bytes[fill] > '~')) + outLine[col + fill] = '.'; + else + outLine[col + fill] = bytes[fill]; + } + outLine[col + fill] = 0; + strcat(outLine, "\n"); + fprintf(fd, outLine); + outLine[0] = 0; + + // Clear RXTX so we will start a new line below + rxtx = 0; + } + + // Test if we are at the start of a packet and put the packet hearder on + if (rxtx == 0) + { + if (cle->flags & 0x80) + rxtx = CLE_TX; + else + rxtx = CLE_RX; + + sprintf(outLine, "%04d %s ", line++, rxtx == CLE_TX ? "tx" : "rx"); + cnt = 0; // No bytes on this line yet + } + + // Draw the text + sprintf(string, "%02X ", cle->byte); + strcat(outLine, string); + bytes[cnt++] = cle->byte; + + // Get location of next byte + if (++index == clb->max) + { + // Get pointer to next clb + if (clb->next == NULL) + // No more data -- break loop + break; + + clb = clb->next; + index = 0; + } + } + + // Terminate the line from above + if (cnt != 0) + { + // Fill the hex region to the end + fill = 0; + while (cnt + fill++ < bytesPerLine) + strcat(outLine, " "); + strcat(outLine, " "); + + // Now append the ASCII representation of the data + col = strlen(outLine); + for (fill = 0; fill < cnt; fill++) + { + if ((bytes[fill] < ' ') || (bytes[fill] > '~')) + outLine[col + fill] = '.'; + else + outLine[col + fill] = bytes[fill]; + } + + // Terminate the line, append \n and print to file + outLine[col + fill] = 0; + strcat(outLine, "\n"); + fprintf(fd, outLine); + + // Next line of same packet + strcpy(outLine, " "); + } + + cnt = 0; + + if (index >= clb->used) + break; + } + + // Cleanup + fclose(fd); + delete fc; +} + diff --git a/src/periph.h b/src/periph.h index cf8882b..6ecf316 100644 --- a/src/periph.h +++ b/src/periph.h @@ -75,6 +75,7 @@ class T100_ComMon : public Fl_Widget void AddByte(int rx_tx, char byte, char flags); void CalcLineStarts(void); void Clear(void); + void SaveLog(void); int m_FirstLine; protected: From d6e7eaf0809401c8918ccc534147412ec8efd064 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 31 Dec 2008 05:07:30 +0000 Subject: [PATCH 157/327] Fixed compile error with WSAGetLastError invocation under Linux build. --- src/socket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/socket.cpp b/src/socket.cpp index c21319e..e04c676 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -37,7 +37,7 @@ bool Socket::create() if ( ! is_valid() ) { - int err = WSAGetLastError(); +// int err = WSAGetLastError(); return false; } From 04ce11248db34da7afc3705df75aa576ee7b8b60 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 31 Dec 2008 05:09:09 +0000 Subject: [PATCH 158/327] Removed definition of tzname variable type so it doesn't conflict with the Windows data structure by the same name. --- src/genwrap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/genwrap.h b/src/genwrap.h index 74cf913..d9c8397 100644 --- a/src/genwrap.h +++ b/src/genwrap.h @@ -187,7 +187,7 @@ extern "C" { #define BEEP(freq,dur) Beep((DWORD)(freq),(DWORD)(dur)) #define popen _popen #define pclose _pclose - #define tzname _tzname +// #define tzname _tzname #elif defined(__OS2__) From 9ca395139b0cb41a0226f36960ad56d8914bbb7b Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 31 Dec 2008 05:11:05 +0000 Subject: [PATCH 159/327] Validated the selected COM string text is not NULL prior to peforming a compare. If device does not exist (USB serial port removed), it would sometimes cause the program to crash when hitting "Ok". --- src/setup.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/setup.cpp b/src/setup.cpp index 6aba70b..60d950a 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -250,10 +250,13 @@ void cb_setup_OK(Fl_Widget* w, void*) } // Check if we are changing ports - if (strcmp(setup_ctrl.com.pPort->text(), setup.com_port) != 0) - { - ser_close_port(); - open_port = TRUE; + if (setup_ctrl.com.pPort->text() != NULL) + { + if (strcmp(setup_ctrl.com.pPort->text(), setup.com_port) != 0) + { + ser_close_port(); + open_port = TRUE; + } } } From 98037017ddfb9a01a935575db27525c246e9dea7 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 31 Dec 2008 05:13:10 +0000 Subject: [PATCH 160/327] Added mutex exclusion around the serial callback routine in Windows emulation to fix spurattic receipt of 00h characters. --- src/serial.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/serial.c b/src/serial.c index 577f733..c5fd49e 100644 --- a/src/serial.c +++ b/src/serial.c @@ -354,14 +354,15 @@ void process_read_byte(ser_params_t *sp, char byte) sp->rxIn = new_rxIn; - ReleaseMutex(sp->hReadMutex); - // Call callback to indicate receipt of data if (sp->pCallback != NULL) { sp->pCallback(); sp->fIntPending = TRUE; } + + ReleaseMutex(sp->hReadMutex); + } /* @@ -1315,6 +1316,8 @@ int ser_get_flags(unsigned char *flags) // FRAMING Error flag + WaitForSingleObject(sp.hReadMutex, 2000); + if ((sp.rxIn != sp.rxOut) && (sp.fIntPending == 0)) { if (sp.pCallback != NULL) @@ -1323,6 +1326,9 @@ int ser_get_flags(unsigned char *flags) sp.fIntPending = TRUE; } } + + ReleaseMutex(sp.hReadMutex); + #else { From 023f7bca7d48e2206c371504608ef95cde29a297 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 31 Dec 2008 06:49:15 +0000 Subject: [PATCH 161/327] Make serial port log file rx/tx indication all CAPS. --- src/periph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/periph.cpp b/src/periph.cpp index dba8f43..104cec3 100644 --- a/src/periph.cpp +++ b/src/periph.cpp @@ -1696,7 +1696,7 @@ void T100_ComMon::SaveLog(void) else rxtx = CLE_RX; - sprintf(outLine, "%04d %s ", line++, rxtx == CLE_TX ? "tx" : "rx"); + sprintf(outLine, "%04d %s ", line++, rxtx == CLE_TX ? "TX" : "RX"); cnt = 0; // No bytes on this line yet } From 339071ac63aeb6d109f85c2a4cf5052a58773040 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 4 Jan 2009 05:38:14 +0000 Subject: [PATCH 162/327] Added fileview.cpp to the build --- GNUmakefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index c655978..f58875e 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -45,7 +45,7 @@ SOURCESCPP = display.cpp setup.cpp periph.cpp disassemble.cpp file.cpp memedit.c multiwin.cpp multiwin_icons.cpp project.cpp multieditwin.cpp rememcfg.cpp \ fl_usage_box.cpp remote.cpp socket.cpp serversocket.cpp lpt.cpp printer.cpp \ fileprint.cpp hostprint.cpp fx80print.cpp chargen.cpp fl_action_icon.cpp fx80rom.cpp \ - vtpaper.cpp autofile.cpp clock.cpp + vtpaper.cpp autofile.cpp clock.cpp fileview.cpp CLIENT_SRC = clientsocket.cpp vt_client_main.cpp socket.cpp # =============================== @@ -158,6 +158,7 @@ fx80rom.o: vtpaper.o: printer.h vtpaper.h autofile.h autofile.o: autofile.h clock.o: clock.h +fileview.o: display.h cpuregs.h disassemble.h fileview.h periph.h memedit.h file.h # ========== # asm files From ab6d2ce69d9afc9adbd9e8e28f3ec70e07d597f5 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 4 Jan 2009 05:48:50 +0000 Subject: [PATCH 163/327] Added routine to perform "cold boot" of RAM. --- src/memory.c | 17 +++++++++++++++++ src/memory.h | 1 + 2 files changed, 18 insertions(+) diff --git a/src/memory.c b/src/memory.c index 6d41bc9..0acd6b4 100644 --- a/src/memory.c +++ b/src/memory.c @@ -619,7 +619,24 @@ void reinit_mem(void) gRomBank = 0; } +/* +============================================================================ +Clear RAM to emulate a cold-boot based on Memory mode selected. +============================================================================ +*/ +void cold_boot_mem(void) +{ + int x; + if (gReMem) + { + } + else + { + for (x = ROMSIZE; x < 65536; x++) + gBaseMemory[x] = 0; + } +} /* ======================================================================== diff --git a/src/memory.h b/src/memory.h index bde1fe9..e8eaf30 100644 --- a/src/memory.h +++ b/src/memory.h @@ -126,6 +126,7 @@ extern int gRex; void init_mem(void); void reinit_mem(void); +void cold_boot_mem(void); void free_mem(void); void free_remem_mem(void); void free_rampac_mem(void); From ab711d597c3544c421a6778162cc346629b2d90d Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 4 Jan 2009 05:49:25 +0000 Subject: [PATCH 164/327] Modified callback routine for "Cold Boot" menu option to actually perform a cold boot. --- src/display.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/display.cpp b/src/display.cpp index 5a29db8..e947fec 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -61,6 +61,7 @@ #include "fl_action_icon.h" #include "clock.h" #include "fileview.h" +//#include "tpddclient.h" extern "C" { extern RomDescription_t gM100_Desc; @@ -487,8 +488,8 @@ void cb_coldBoot (Fl_Widget* w, void*) if(a != 0) { + cold_boot_mem(); resetcpu(); - reinit_mem(); show_remem_mode(); @@ -740,6 +741,7 @@ Fl_Menu_Item menuitems[] = { { "Peripheral Devices", 0, cb_PeripheralDevices }, // { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, cb_FileView }, +// { "TPDD Client", 0, cb_TpddClient }, { 0 }, { "&Help", 0, 0, 0, FL_SUBMENU }, { "Help", 0, cb_help }, From 5ce0a7384a3067bf2ff3fc65a0eadef010d5c676 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 4 Jan 2009 06:18:15 +0000 Subject: [PATCH 165/327] Added macro for 'min' for Linux builds and included gen_defs.h in memory.h for UINT64 definition. --- src/display.cpp | 2 ++ src/memory.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/display.cpp b/src/display.cpp index e947fec..f84d320 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -106,6 +106,8 @@ extern Fl_Pixmap gPrinterIcon; void switch_model(int model); +#define min(a,b) ((a)<(b) ? (a):(b)) + void setMonitorWindow(Fl_Window* pWin) { if (pWin == 0) diff --git a/src/memory.h b/src/memory.h index e8eaf30..35a7e96 100644 --- a/src/memory.h +++ b/src/memory.h @@ -111,6 +111,8 @@ extern "C" { #define REX_ROM_REPLACEMENT 0x01 #define REX2_RAM_MODE 0x02 +#include "gen_defs.h" + typedef struct { int gFlashState; UINT64 gFlashTime; From cf3ba0eceb8f537a7f18dfb7637053b1d3d783df Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 4 Jan 2009 06:25:38 +0000 Subject: [PATCH 166/327] Excluded definiiton of 'min' for WIN32 platform. --- src/display.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/display.cpp b/src/display.cpp index f84d320..0c1990d 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -106,7 +106,9 @@ extern Fl_Pixmap gPrinterIcon; void switch_model(int model); +#ifndef WIN32 #define min(a,b) ((a)<(b) ? (a):(b)) +#endif void setMonitorWindow(Fl_Window* pWin) { From e5428e09f913258e4a5e5adab126bfaead8e69d6 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 4 Jan 2009 06:43:14 +0000 Subject: [PATCH 167/327] Fixed issue with suplicate filename detection during "Load from HD" operation. --- src/file.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/file.cpp b/src/file.cpp index 5e93864..37dfe9d 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -743,8 +743,16 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) // Determine if file alaready exists in directory addr2 = gStdRomDesc->sDirectory; dir_index = 0; - while ((get_memory8(addr2) != 0) && (dir_index < gStdRomDesc->sDirCount)) + while (dir_index < gStdRomDesc->sDirCount) { + // Test if this slot is empty + if (get_memory8(addr2) == 0) + { + addr2 += 11; + dir_index++; + continue; + } + // Compare this entry to the file being added for (x = 0; x < 8; x++) { From 7b0f887f23b25b882b388c8079daee193be80f39 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Thu, 5 Feb 2009 04:39:59 +0000 Subject: [PATCH 168/327] Added reload option ROM feature and modfied Memory Load / Save operations with RAM to use absolute addresses. --- release.txt | 6 ++++++ src/display.cpp | 6 ++++++ src/memedit.cpp | 26 +++++++++++++++++++------- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/release.txt b/release.txt index 6472e53..9f8ca78 100644 --- a/release.txt +++ b/release.txt @@ -25,6 +25,12 @@ v1.4 Not released yet feature was added to support sub-notbook platforms with smaller display resolutions that cannot display full window borders well. +5. Added option to reload the Option ROM image. This is useful when developing a new OptROM + image and using VirtualT for debugging. + +6. Modified the Memory Editor's Load and Save features so they properly address the absolute + memory addresses to RAM vs. relative offsets from the beginning RAM address. + ======================= v1.3 September 24 2008 ======================= diff --git a/src/display.cpp b/src/display.cpp index 0c1990d..4f4ebb5 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -510,6 +510,11 @@ void remote_cold_boot(void) cb_coldBoot(NULL, NULL); } +void cb_ReloadOptRom (Fl_Widget* w, void*) +{ + load_opt_rom(); +} + void cb_UnloadOptRom (Fl_Widget* w, void*) { char option_name[32]; @@ -733,6 +738,7 @@ Fl_Menu_Item menuitems[] = { { gsMenuROM, 0, 0, 0, FL_MENU_DIVIDER }, { "Load ROM...", 0, cb_LoadOptRom, 0, 0 }, { "Unload ROM", 0, cb_UnloadOptRom, 0, 0 }, + { "Reload ROM", 0, cb_ReloadOptRom, 0, 0 }, { 0 }, { 0 }, diff --git a/src/memedit.cpp b/src/memedit.cpp index f1f9555..fea278d 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -287,10 +287,16 @@ void update_length_field(const char *filename) void load_file_to_mem(const char *filename, int address) { - int len; + int len, region; unsigned char *buffer; unsigned short start_addr; + // Adjust address if writing to RAM region + region = memedit_ctrl.pMemEdit->GetRegionEnum(); + if ((region == REGION_RAM) || (region == REGION_RAM1) || (region == REGION_RAM2) || + (region == REGION_RAM3)) + address -= RAMSTART; + // Check for hex file len = strlen(filename); if (((filename[len-1] | 0x20) == 'x') && @@ -307,7 +313,7 @@ void load_file_to_mem(const char *filename, int address) else { // Write data to the selected region - set_memory8_ext(memedit_ctrl.pMemEdit->GetRegionEnum(), address, len, buffer); + set_memory8_ext(region, address, len, buffer); } // Free the memory @@ -325,12 +331,11 @@ void load_file_to_mem(const char *filename, int address) buffer = new unsigned char[len]; fseek(fd, 0, SEEK_SET); fread(buffer, 1, len, fd); - set_memory8_ext(memedit_ctrl.pMemEdit->GetRegionEnum(), address, len, buffer); + set_memory8_ext(region, address, len, buffer); fclose(fd); delete buffer; } - } } @@ -338,8 +343,15 @@ void save_mem_to_file(const char *filename, int address, int count, int save_as_ { unsigned char *buffer; FILE *fd; + int region; + // Adjust address if writing from RAM + region = memedit_ctrl.pMemEdit->GetRegionEnum(); + if ((region == REGION_RAM) || (region == REGION_RAM1) || (region == REGION_RAM2) || + (region == REGION_RAM3)) + address -= RAMSTART; + // Check for hex file if (save_as_hex) { @@ -348,7 +360,7 @@ void save_mem_to_file(const char *filename, int address, int count, int save_as_ if (fd == NULL) return; - save_hex_file_ext(address, address+count-1, memedit_ctrl.pMemEdit->GetRegionEnum(), fd); + save_hex_file_ext(address, address+count-1, region, fd); fclose(fd); } @@ -359,13 +371,13 @@ void save_mem_to_file(const char *filename, int address, int count, int save_as_ if ((fd = fopen(filename, "wb+")) != NULL) { buffer = new unsigned char[count]; - get_memory8_ext(memedit_ctrl.pMemEdit->GetRegionEnum(), address, count, buffer); + + get_memory8_ext(region, address, count, buffer); fwrite(buffer, count, 1, fd); fclose(fd); delete buffer; } - } } From 1f14aff509784149e8048c1417b70895770ddc04 Mon Sep 17 00:00:00 2001 From: "John R. Hogerhuis" Date: Mon, 23 Mar 2009 04:58:12 +0000 Subject: [PATCH 169/327] Fixed various missing header file includes --- src/assemble.cpp | 1 + src/fileprint.cpp | 4 ++++ src/hostprint.cpp | 1 + src/remote.cpp | 3 ++- src/vt_client_main.cpp | 2 ++ 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/assemble.cpp b/src/assemble.cpp index 875e920..6a0ab47 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -14,6 +14,7 @@ VTAssembler: This class defines an 8085 Macro Assembler for the #include #include #include +#include extern CRpnEquation* gEq; extern VTObArray* gExpList; diff --git a/src/fileprint.cpp b/src/fileprint.cpp index e700044..b948701 100644 --- a/src/fileprint.cpp +++ b/src/fileprint.cpp @@ -42,6 +42,10 @@ #include #include +#include +#include +#include + #include "VirtualT.h" #include "fileprint.h" #include "m100emu.h" diff --git a/src/hostprint.cpp b/src/hostprint.cpp index 506f509..458aaa1 100644 --- a/src/hostprint.cpp +++ b/src/hostprint.cpp @@ -45,6 +45,7 @@ #include #ifdef __unix__ +#include #endif #include "VirtualT.h" diff --git a/src/remote.cpp b/src/remote.cpp index 20890fb..e205d24 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -32,8 +32,9 @@ #include #include -#ifdef WIN32 #include + +#ifdef WIN32 #include #else #include diff --git a/src/vt_client_main.cpp b/src/vt_client_main.cpp index 4d5d504..eb5c561 100644 --- a/src/vt_client_main.cpp +++ b/src/vt_client_main.cpp @@ -4,6 +4,8 @@ #include #include +#include + using namespace std; int main ( int argc, char* argv[] ) From 1c7cd3aab4b829092c96a53225caf64d83f6583f Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 5 Apr 2009 05:34:42 +0000 Subject: [PATCH 170/327] Added telnet capablility to socket interface, added a few socket interface shortcuts and bug fixes. --- src/a85parse.syn | 8 +- src/cpuregs.cpp | 32 +++- src/disassemble.cpp | 8 +- src/io.c | 7 +- src/m100emu.c | 6 +- src/m100emu.h | 1 + src/memedit.cpp | 11 +- src/memory.h | 1 + src/remote.cpp | 397 ++++++++++++++++++++++++++--------------- src/vt_client_main.cpp | 2 +- 10 files changed, 314 insertions(+), 159 deletions(-) diff --git a/src/a85parse.syn b/src/a85parse.syn index fbc5960..5673ec8 100644 --- a/src/a85parse.syn +++ b/src/a85parse.syn @@ -96,10 +96,10 @@ expression -> literal name, "set", equation = gAsm->directive_set(ss[ss_idx--]); -> label, "equ", equation = gAsm->equate((const char *) -1); -> label, "set", equation = gAsm->directive_set((const char *) -1); - -> label?, "org", equation = gAsm->directive_org(); - -> label?, "aseg" = gAsm->directive_aseg(); - -> label?, "cseg" = gAsm->directive_cseg(0); - -> label?, "dseg" = gAsm->directive_dseg(0); + -> label?, '.'?, "org", equation = gAsm->directive_org(); + -> label?, '.'?, "aseg" = gAsm->directive_aseg(); + -> label?, '.'?, "cseg" = gAsm->directive_cseg(0); + -> label?, '.'?, "dseg" = gAsm->directive_dseg(0); -> literal name, "ds", equation = { gAsm->label(ss[ss_idx--]); gAsm->directive_ds(); } -> label?, "ds", equation = gAsm->directive_ds(); -> literal name, "db", expression list, WS?... = { gAsm->label(ss[ss_idx--]); gAsm->directive_db(); } diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index a1b3a0e..4f8e6a5 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -118,14 +118,38 @@ str_to_i: This routine converts a hex or decimal string to an integer. */ int str_to_i(const char *pStr) { - int x; + int x, len, hex = FALSE; int val, digit; // Test for Hex number if (strncmp("0x", pStr, 2) == 0) { - x = 2; val = 0; - while (pStr[x] != '\0') + hex = TRUE; + pStr += 2; + } + else + { + // Scan scring for any hex digits + len = strlen(pStr); + if ((pStr[len-1] == 'h') || (pStr[len-1] == 'H')) + hex = TRUE; + else + for (x = 0; x < len; x++) + { + if (((pStr[x] >= 'A') && (pStr[x] <= 'F')) || + ((pStr[x] >= 'a') && (pStr[x] <= 'f'))) + { + hex = TRUE; + break; + } + } + } + + // If it's a hex string, use hex conversion + if (hex) + { + x = 0; val = 0; + while ((pStr[x] != '\0') && (pStr[x] != 'h') && (pStr[x] != 'H')) { digit = pStr[x] > '9' ? (pStr[x] | 0x60) - 'a' + 10 : pStr[x] - '0'; val = val * 16 + digit; @@ -133,7 +157,9 @@ int str_to_i(const char *pStr) } } else + { val = atoi(pStr); + } // Return value to caller return val; diff --git a/src/disassemble.cpp b/src/disassemble.cpp index e2fdd0b..f85ad87 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -105,7 +105,7 @@ char * gStrTable[256] = { "CMP B", "CMP C", "CMP D", "CMP E", "CMP H", "CMP L", "CMP M", "CMP A", "RNZ", "POP B", "JNZ ", "JMP ", "CNZ ", "PUSH B", "ADI ", "RST 0", - "RZ", "RET", "JZ ", "-", "CZ ", "CALL ", "ACI ", "RST 1", + "RZ", "RET", "JZ ", "RSTV", "CZ ", "CALL ", "ACI ", "RST 1", "RNC", "POP D", "JNC ", "OUT ", "CNC ", "PUSH D", "SUI ", "RST 2", "RC", "SHLX", "JC ", "IN ", "CC ", "JNX ", "SBI ", "RST 3", @@ -173,8 +173,6 @@ Fl_Menu_Item gDis_menuitems[] = { { 0 } }; - - /* ======================================================= Menu Item Callbacks @@ -372,7 +370,7 @@ void VTDis::Disassemble() { // Search for C in the function table x = 0; - while (m_pRom->pFuns[x].addr != -1) +/* while (m_pRom->pFuns[x].addr != -1) { if (m_pRom->pFuns[x].addr == c) { @@ -386,7 +384,7 @@ void VTDis::Disassemble() x++; } - +*/ // Check if address is a table instead of code x = 0; table = 0; diff --git a/src/io.c b/src/io.c index 4858c9b..a1a2fe6 100644 --- a/src/io.c +++ b/src/io.c @@ -107,9 +107,6 @@ void update_keys(void) } } - gDelayUpdateKeys = 0; - gDelayCount = 0; - if (gModel == MODEL_M10) { keyscan[0] = ~(gKeyStates['q'] | (gKeyStates['w'] << 1) | @@ -227,6 +224,10 @@ void update_keys(void) (unsigned char) (((gSpecialKeys & MT_CAP_LOCK) | ~MT_CAP_LOCK) >> 1); } } + + gDelayUpdateKeys = 0; + gDelayCount = 0; + } void init_io(void) diff --git a/src/m100emu.c b/src/m100emu.c index 18ab1ec..32eff75 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -96,6 +96,7 @@ int gMaintCount = 262888; int gOsDelay = 0; int gNoGUI = 0; int gSocketPort = 0; +int gTelnet = FALSE; int gRemoteSwitchModel = -1; //Added J. VERNET @@ -906,7 +907,7 @@ void emulate(void) } /* Instruction emulation contained in header file */ - #include "do_instruct.h" + // #include "do_instruct.h" // Check if next inst is SIM if (get_memory8(PC) == 0xF3) @@ -1030,6 +1031,9 @@ int process_args(int argc, char **argv) if (!strcmp(argv[i], "-nogui")) gNoGUI = 1; + if (!strcmp(argv[i], "-t")) + gTelnet = TRUE; + // Search for Socket Port flag if (!strncmp(argv[i], "-p", 2)) { diff --git a/src/m100emu.h b/src/m100emu.h index 30ad1d0..aa6a5b9 100644 --- a/src/m100emu.h +++ b/src/m100emu.h @@ -67,6 +67,7 @@ extern char gStopped; extern char gSingleStep; extern int gDebugMonitorFreq; extern int gSocketPort; +extern int gTelnet; extern int gNoGUI; #define DEBUG_PC_CHANGED 1 diff --git a/src/memedit.cpp b/src/memedit.cpp index fea278d..c64ce68 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -325,13 +325,20 @@ void load_file_to_mem(const char *filename, int address) FILE* fd; if ((fd = fopen(filename, "r")) != NULL) { + int read_len; + // Determine file length fseek(fd, 0, SEEK_END); len = ftell(fd); buffer = new unsigned char[len]; fseek(fd, 0, SEEK_SET); - fread(buffer, 1, len, fd); - set_memory8_ext(region, address, len, buffer); + while (len != 0) + { + read_len = fread(buffer, 1, len, fd); + set_memory8_ext(region, address, read_len, buffer); + len -= read_len; + address += read_len; + } fclose(fd); delete buffer; diff --git a/src/memory.h b/src/memory.h index 35a7e96..407e115 100644 --- a/src/memory.h +++ b/src/memory.h @@ -122,6 +122,7 @@ typedef struct { extern unsigned char *gMemory[64]; extern unsigned char gSysROM[65536]; +extern unsigned char gOptROM[32768]; extern unsigned char gBaseMemory[65536]; extern unsigned char gReMem; extern int gRex; diff --git a/src/remote.cpp b/src/remote.cpp index e205d24..09aebce 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -87,6 +87,10 @@ int gTraceActive = 0; std::string gTraceFile; FILE* gTraceFileFd; VTDis gTraceDis; +std::string gLineTerm = "\n"; +std::string gOk = "Ok"; +std::string gParamError = "Parameter Error\nOk"; +std::string gTelnetCmd; int remote_cpureg_stop(void); int remote_cpureg_run(void); @@ -119,39 +123,39 @@ Help command: Send list of supported commands */ std::string cmd_help(ServerSocket& sock) { - sock << "Help\n====\n"; - sock << " clear_break(cb) address\n"; - sock << " cold_boot\n"; - sock << " debug_isr(isr) [on off]\n"; - sock << " dis address [lines]\n"; - sock << " flags [all S Z ac P=1 s=0 ...]\n"; - sock << " halt\n"; - sock << " in port\n"; - sock << " key [enter f1 esc ctrl+c shift+code+a \"Text\" ...]\n"; - sock << " lcd_ignore(li) [none (row,col)-(row,col)]\n"; - sock << " lcd_mon(lm) [on off]\n"; - sock << " list_break(lb)\n"; - sock << " load filename\n"; - sock << " model [m100 m102 t200 pc8201 m10 kc85]\n"; - sock << " optrom [unload, filename]\n"; - sock << " out port, value\n"; - sock << " radix [10 or 16]\n"; - sock << " read_mem(rm) address [count]\n"; - sock << " read_reg(rr) [all A B h m DE ...]\n"; - sock << " reset\n"; - sock << " run\n"; - sock << " set_break(sb) address [main opt mplan ram ram2 ram3]\n"; - sock << " speed [2.4 friendly max]\n"; - sock << " status\n"; - sock << " step(s) [count]\n"; - sock << " step_over(so) [count]\n"; - sock << " string address\n"; - sock << " terminate\n"; - sock << " write_mem(wm) address [data data data ...]\n"; - sock << " write_reg(wr) [A=xx B=xx hl=xx ...]\n"; - sock << " x [lines]\n"; - - return "Ok"; + sock << "Help" << gLineTerm << "====" << gLineTerm; + sock << " clear_break(cb) address" << gLineTerm; + sock << " cold_boot" << gLineTerm; + sock << " debug_isr(isr) [on off]" << gLineTerm; + sock << " dis address [lines]" << gLineTerm; + sock << " flags [all S Z ac P=1 s=0 ...]" << gLineTerm; + sock << " halt" << gLineTerm; + sock << " in port" << gLineTerm; + sock << " key(k) [enter cr f1 esc ctrl+c shift+code+a \"Text\" ...]" << gLineTerm; + sock << " lcd_ignore(li) [none (row,col)-(row,col)]" << gLineTerm; + sock << " lcd_mon(lm) [on off]" << gLineTerm; + sock << " list_break(lb)" << gLineTerm; + sock << " load filename" << gLineTerm; + sock << " model [m10 m102 t200 pc8201 m10 kc85]" << gLineTerm; + sock << " optrom [unload, filename]" << gLineTerm; + sock << " out port, value" << gLineTerm; + sock << " radix [10 or 16]" << gLineTerm; + sock << " read_mem(rm) address [count]" << gLineTerm; + sock << " read_reg(rr) [all A B h m DE ...]" << gLineTerm; + sock << " reset" << gLineTerm; + sock << " run" << gLineTerm; + sock << " set_break(sb) address [main opt mplan ram ram2 ram3 read write]" << gLineTerm; + sock << " speed [2.4 friendly max]" << gLineTerm; + sock << " status" << gLineTerm; + sock << " step(s) [count]" << gLineTerm; + sock << " step_over(so) [count]" << gLineTerm; + sock << " string address" << gLineTerm; + sock << " terminate" << gLineTerm; + sock << " write_mem(wm) address [data data data ...]" << gLineTerm; + sock << " write_reg(wr) [A=xx B=xx hl=xx ...]" << gLineTerm; + sock << " x [lines] (short for \"dis pc\")" << gLineTerm; + + return gOk; } /* @@ -166,8 +170,8 @@ void handle_lcd_timeout() if ((int) (cycles - gLcdUpdateCycle) > gLcdTimeoutCycles) { // New string being written. Send the old one - sprintf(str, "event, lcdwrite, (%d,%d),%s\n", gLcdRow, gLcdColStart, - gLcdString.c_str()); + sprintf(str, "event, lcdwrite, (%d,%d),%s%s", gLcdRow, gLcdColStart, + gLcdString.c_str(), gLineTerm.c_str()); if ((gLcdRow != -1) && (gLcdColStart != -1)) if (gSocketOpened) @@ -218,8 +222,8 @@ void handle_lcd_trap() if (gLcdRow != -1) { // New string being written. Send the old one - sprintf(str, "event, lcdwrite, (%d,%d),%s\n", gLcdRow, gLcdColStart, - gLcdString.c_str()); + sprintf(str, "event, lcdwrite, (%d,%d),%s%s", gLcdRow, gLcdColStart, + gLcdString.c_str(), gLineTerm.c_str()); if (gSocketOpened) gOpenSock << str; } @@ -288,9 +292,10 @@ int check_mem_access_break(void) case 0x11: /* LXI D */ case 0x21: /* LXI H */ case 0x31: /* LXI SP */ - address = (int) (PC) | ((int) (PC) << 8); + address = (((int)get_memory8((unsigned short) (PC+1)))|(((int)get_memory8((unsigned short) (PC+2)))<<8)); read = TRUE; len = 2; + break; case 0x22: /* SHLD */ write = TRUE; @@ -471,9 +476,9 @@ void cb_remote_debug(int reason) if (gSocketOpened) { if (gRadix == 10) - sprintf(str, "event, break, PC=%d\n", PC); + sprintf(str, "event, break, PC=%d%s", PC, gLineTerm.c_str()); else - sprintf(str, "event, break, PC=%04X\n", PC); + sprintf(str, "event, break, PC=%04X%s", PC, gLineTerm.c_str()); gOpenSock << str; } } @@ -490,9 +495,9 @@ void cb_remote_debug(int reason) if (gSocketOpened) { if (gRadix == 10) - sprintf(str, "event, break, PC=%d\n", PC); + sprintf(str, "event, break, PC=%d%s", PC, gLineTerm.c_str()); else - sprintf(str, "event, break, PC=%04X\n", PC); + sprintf(str, "event, break, PC=%04X%s", PC, gLineTerm.c_str()); gOpenSock << str; } } @@ -558,7 +563,7 @@ std::string cmd_terminate(ServerSocket& sock) { gExitApp = TRUE; gExitLoop = TRUE; - return "Ok"; + return gOk; } /* @@ -575,9 +580,11 @@ std::string cmd_status(ServerSocket& sock) get_model_string(modelStr, gModel); if (gStopped) - sprintf(retStr, "Model=%s, CPU halted\nOk", modelStr); + sprintf(retStr, "Model=%s, CPU halted%s%s", modelStr, + gLineTerm.c_str(), gOk.c_str()); else - sprintf(retStr, "Model=%s, CPU running\nOk", modelStr); + sprintf(retStr, "Model=%s, CPU running%s%s", modelStr, + gLineTerm.c_str(), gOk.c_str()); return retStr; @@ -600,7 +607,7 @@ std::string cmd_halt(ServerSocket& sock) unlock_remote(); } - return "Ok"; + return gOk; } /* @@ -611,7 +618,7 @@ Reset command: Reset the CPU std::string cmd_reset(ServerSocket& sock) { remote_reset(); - return "Ok"; + return gOk; } /* @@ -622,7 +629,7 @@ Cold Boot command: Cold boot the machine std::string cmd_cold_boot(ServerSocket& sock) { remote_cold_boot(); - return "Ok"; + return gOk; } /* @@ -646,7 +653,7 @@ std::string cmd_run(ServerSocket& sock) unlock_remote(); } - return "Ok"; + return gOk; } /* @@ -673,10 +680,10 @@ std::string cmd_step(ServerSocket& sock, std::string& args) next_arg = get_next_arg(args); } - // Get address of read + // Get step count value = str_to_i(next_arg.c_str()); if (value < 0) - return "Parameter Error\nOk"; + return gParamError; // Loop for each step for (c = 0; c < value; c++) @@ -689,7 +696,7 @@ std::string cmd_step(ServerSocket& sock, std::string& args) fl_wait(0.001); } - return "Ok"; + return gOk; } /* @@ -716,10 +723,10 @@ std::string cmd_step_over(ServerSocket& sock, std::string& args) next_arg = get_next_arg(args); } - // Get address of read + // Get step over count value = str_to_i(next_arg.c_str()); if (value < 0) - return "Parameter Error\nOk"; + return gParamError; // Loop for each step for (c = 0; c < value; c++) @@ -788,7 +795,7 @@ std::string cmd_step_over(ServerSocket& sock, std::string& args) } } - return "Ok"; + return gOk; } int get_address(std::string arg) @@ -849,7 +856,7 @@ std::string cmd_write_mem(ServerSocket& sock, std::string& args) } unlock_remote(); - return "Ok"; + return gOk; } /* @@ -891,9 +898,9 @@ std::string cmd_read_mem(ServerSocket& sock, std::string& args) ret += str; } unlock_remote(); - ret += "\n"; + ret += gLineTerm; - return ret + "Ok"; + return ret + gOk; } /* @@ -917,11 +924,11 @@ std::string cmd_read_reg(ServerSocket& sock, std::string& args) if (args == "all") { if (gRadix == 10) - sprintf(reg_str, "A=%d F=%d B=%d C=%d D=%d E=%d H=%d L=%d M=%d PC=%d SP=%d\nOk", - A, F, B, C, D, E, H, L, get_memory8(HL), PC, SP); + sprintf(reg_str, "A=%d F=%d B=%d C=%d D=%d E=%d H=%d L=%d M=%d PC=%d SP=%d%s%s", + A, F, B, C, D, E, H, L, get_memory8(HL), PC, SP, gLineTerm.c_str(), gOk.c_str()); else - sprintf(reg_str, "A=%02X F=%02X B=%02X C=%02X D=%02X E=%02X H=%02X L=%02X M=%02X PC=%04X SP=%04X\nOk", - A, F, B, C, D, E, H, L, get_memory8(HL), PC, SP); + sprintf(reg_str, "A=%02X F=%02X B=%02X C=%02X D=%02X E=%02X H=%02X L=%02X M=%02X PC=%04X SP=%04X%s%s", + A, F, B, C, D, E, H, L, get_memory8(HL), PC, SP, gLineTerm.c_str(), gOk.c_str()); unlock_remote(); return reg_str; } @@ -1023,9 +1030,9 @@ std::string cmd_read_reg(ServerSocket& sock, std::string& args) } } unlock_remote(); - return ret + "\nOk"; + return ret + gLineTerm + gOk; } - return "Ok"; + return gOk; } /* @@ -1060,7 +1067,7 @@ std::string cmd_write_reg(ServerSocket& sock, std::string& args) if (pos == -1) { unlock_remote(); - return "Parameter Error\nOk"; + return gParamError; } regStr = next_arg.substr(0, pos); valueStr = next_arg.substr(pos+1, next_arg.length()-pos-1); @@ -1115,7 +1122,7 @@ std::string cmd_write_reg(ServerSocket& sock, std::string& args) // Unlock access to remote control unlock_remote(); - return "Ok"; + return gOk; } /* @@ -1126,9 +1133,12 @@ Load command: Loads a target file from the host std::string cmd_load(ServerSocket& sock, std::string& args) { if (remote_load_from_host(args.c_str())) - return "Load Error\nOk"; + { + std::string ret = "Load Error" + gLineTerm + gOk; + return ret; + } - return "Ok"; + return gOk; } /* @@ -1140,31 +1150,35 @@ void cb_UnloadOptRom (Fl_Widget* w, void*); std::string cmd_optrom(ServerSocket& sock, std::string& args) { - int ret; + int err; // if (args == "") { if (strlen(gsOptRomFile) == 0) - return "none\nOk"; + { + std::string ret = "none" + gLineTerm + gOk; + return ret; + } sock << gsOptRomFile; - return "\nOk"; + return gLineTerm + gOk; } if (args == "unload") { cb_UnloadOptRom(NULL, NULL); - return "Ok"; + return gOk; } // Load the optrom specified - ret = load_optrom_file(args.c_str()); - if (ret == FILE_ERROR_INVALID_HEX) - return "Invalid hex file\nOk"; - if (ret == FILE_ERROR_FILE_NOT_FOUND) - return "File not found\nOk"; + std::string ret = gOk; + err = load_optrom_file(args.c_str()); + if (err == FILE_ERROR_INVALID_HEX) + ret = "Invalid hex file" + gLineTerm + gOk; + if (err == FILE_ERROR_FILE_NOT_FOUND) + ret = "File not found" + gLineTerm + gOk; - return "Ok"; + return ret; } /* @@ -1178,15 +1192,15 @@ std::string cmd_radix(ServerSocket& sock, std::string& args) if (args == "") { - sprintf(str, "%d\nOk", gRadix); + sprintf(str, "%d%s%s", gRadix, gLineTerm.c_str(), gOk.c_str()); return str; } if ((args != "10") && (args != "16")) - return "Parameter error\nOk"; + return gParamError; gRadix = str_to_i(args.c_str()); - return "Ok"; + return gOk; } /* @@ -1201,16 +1215,16 @@ std::string cmd_in(ServerSocket& sock, std::string& args) // Ensure there are params if (args == "") - return "Parameter error\nOk"; + return gParamError; // Convert the port # to integer port = str_to_i(args.c_str()); // Report the value based on radix - if (gRadix = 10) - sprintf(str, "%d\nOk", inport(port)); + if (gRadix == 10) + sprintf(str, "%d%s%s", inport(port), gLineTerm.c_str(), gOk.c_str()); else - sprintf(str, "%02X\nOk", inport(port)); + sprintf(str, "%02X%s%s", inport(port), gLineTerm.c_str(), gOk.c_str()); return str; } @@ -1243,7 +1257,7 @@ std::string cmd_flags(ServerSocket& sock, std::string& args) if (AC) str += "AC "; if (TS) str += "TS "; if (str == "") str = "(none)"; - str += "\n"; + str += gLineTerm; } else { @@ -1312,9 +1326,9 @@ std::string cmd_flags(ServerSocket& sock, std::string& args) } } } - str += "\n"; + str += gLineTerm; } - str += "Ok"; + str += gOk; unlock_remote(); return str; @@ -1333,7 +1347,7 @@ std::string cmd_out(ServerSocket& sock, std::string& args) // Validate there are parameters if (args == "") - return "Parameter error\nOk"; + return gParamError; // Find the comma separating the port and value pos = args.find(','); @@ -1360,7 +1374,7 @@ std::string cmd_out(ServerSocket& sock, std::string& args) else { // Invalid format - return "Parameter Error\nOk"; + return gParamError; } } @@ -1370,7 +1384,7 @@ std::string cmd_out(ServerSocket& sock, std::string& args) // Perform the out function out(port, value); - return "Ok"; + return gOk; } /* @@ -1394,7 +1408,7 @@ std::string cmd_set_break(ServerSocket& sock, std::string& args) // Convert address address = get_address(next_arg); if ((address > 65535) || (address < 0)) - return "Parameter Error\nOk"; + return gParamError; // Determine the types of breaks if (more_args == "") @@ -1440,9 +1454,7 @@ std::string cmd_set_break(ServerSocket& sock, std::string& args) } if (value == 0) - { - return "Parameter Error\nOk"; - } + return gParamError; } // Okay, now set the breakpoint @@ -1457,7 +1469,7 @@ std::string cmd_set_break(ServerSocket& sock, std::string& args) // Unlock access to global vars unlock_remote(); - return "Ok"; + return gOk; } /* @@ -1487,7 +1499,7 @@ std::string cmd_clear_break(ServerSocket& sock, std::string& args) // Convert address address = get_address(next_arg); if ((address > 65535) || (address < 0)) - return "Parameter Error\nOk"; + return gParamError; // Clear the breakpoint gRemoteBreak[address] = 0; @@ -1512,7 +1524,7 @@ std::string cmd_clear_break(ServerSocket& sock, std::string& args) } } - return "Ok"; + return gOk; } /* @@ -1550,11 +1562,11 @@ std::string cmd_list_break(ServerSocket& sock, std::string& args) strcat(str, "read "); if (gRemoteBreak[c] & BPTYPE_WRITE) strcat(str, "write "); - strcat(str, "\n"); + strcat(str, gLineTerm.c_str()); sock << str; } } - return "Ok"; + return gOk; } void key_delay(void) @@ -1562,6 +1574,7 @@ void key_delay(void) fl_wait(0.01); while (gDelayUpdateKeys) fl_wait(0.001); + fl_wait(0.01); } /* ======================================================= @@ -1626,6 +1639,8 @@ int keyword_lookup(std::string& keyword) if (keyword == "enter") return FL_Enter; + else if (keyword == "cr") + return FL_Enter; else if (keyword == "esc") return FL_Escape; else if (keyword == "tab") @@ -1740,7 +1755,7 @@ std::string cmd_key(ServerSocket& sock, std::string& args) if (len == 1) { key_press(args[0]); - return "Ok"; + return gOk; } // Loop through all charaters @@ -1837,7 +1852,7 @@ std::string cmd_key(ServerSocket& sock, std::string& args) send_key_list(key_list, key_count); } - return "Ok"; + return gOk; } /* @@ -1874,7 +1889,7 @@ std::string cmd_model(ServerSocket& sock, std::string& args) if (args == "") { get_model_string(model, gModel); - sprintf(str, "%s\nOk", model); + sprintf(str, "%s%s%s", model, gLineTerm.c_str(), gOk.c_str()); return str; } @@ -1913,10 +1928,10 @@ std::string cmd_model(ServerSocket& sock, std::string& args) local_switch_model(MODEL_KC85); } else - return "Parameter Error\nOk"; + return gParamError; fl_wait(0.25); - return "Ok"; + return gOk; } /* @@ -1927,15 +1942,22 @@ Speed command: Sets the emulation speed std::string cmd_speed(ServerSocket& sock, std::string& args) { std::string more_args = args; + std::string ret; if (args == "") { switch (fullspeed) { - case SPEED_REAL: return "2.4\nOk"; + case SPEED_REAL: + ret = "2.4" + gLineTerm + gOk; + return ret; case SPEED_FRIENDLY1: - case SPEED_FRIENDLY2: return "friendly\nOk"; - case SPEED_FULL: return "max\nOk"; + case SPEED_FRIENDLY2: + ret = "friendly" + gLineTerm + gOk; + return ret; + case SPEED_FULL: + ret = "max" + gLineTerm + gOk; + return ret; } } @@ -1956,9 +1978,9 @@ std::string cmd_speed(ServerSocket& sock, std::string& args) remote_set_speed(SPEED_FULL); } else - return "Parameter Error\nOk"; + return gParamError; - return "Ok"; + return gOk; } /* @@ -2018,16 +2040,19 @@ std::string cmd_lcd_ignore(ServerSocket& sock, std::string& args) if (args == "") { if (gIgnoreCount == 0) - return "none\nOk"; + { + std::string ret = "none" + gLineTerm + gOk; + return ret; + } for (pos = 0; pos < gIgnoreCount; pos++) { - sprintf(str, "(%d,%d)-(%d,%d)\n", gIgnoreRects[pos].top_row, + sprintf(str, "(%d,%d)-(%d,%d)%s", gIgnoreRects[pos].top_row, gIgnoreRects[pos].top_col, gIgnoreRects[pos].bottom_row, - gIgnoreRects[pos].bottom_col); + gIgnoreRects[pos].bottom_col, gLineTerm.c_str()); sock << str; } - return "Ok"; + return gOk; } // Ckeck if clearing all ignores @@ -2035,7 +2060,7 @@ std::string cmd_lcd_ignore(ServerSocket& sock, std::string& args) { // Clear the ignore count so all regions are monitored gIgnoreCount = 0; - return "Ok"; + return gOk; } // Separate coordinates @@ -2046,13 +2071,13 @@ std::string cmd_lcd_ignore(ServerSocket& sock, std::string& args) more_args = args.substr(pos+1, args.length()-pos-1); } else - return "Parameter Error\nOk"; + return gParamError; // Get row from first argument if (get_lcd_coords(next_arg, top_row, top_col)) - return "Parameter Error\nOk"; + return gParamError; if (get_lcd_coords(more_args, bottom_row, bottom_col)) - return "Parameter Error\nOk"; + return gParamError; // Update the ignore region gIgnoreRects[gIgnoreCount].top_row = top_row; @@ -2061,7 +2086,7 @@ std::string cmd_lcd_ignore(ServerSocket& sock, std::string& args) gIgnoreRects[gIgnoreCount].bottom_col = bottom_col; gIgnoreCount++; - return "Ok"; + return gOk; } /* @@ -2074,13 +2099,13 @@ std::string cmd_show_reg(ServerSocket& sock, int value, int size) char str[10]; if (gRadix == 10) - sprintf(str, "%d\nOk", value); + sprintf(str, "%d%s%s", value, gLineTerm.c_str(), gOk.c_str()); else { if (size == 2) - sprintf(str, "%04X\nOk", value); + sprintf(str, "%04X%s%s", value, gLineTerm.c_str(), gOk.c_str()); else - sprintf(str, "%02X\nOk", value); + sprintf(str, "%02X%s%s", value, gLineTerm.c_str(), gOk.c_str()); } return str; @@ -2097,10 +2122,12 @@ std::string cmd_lcd_mon(ServerSocket& sock, std::string& args) // Get breakpoint arguments if (args == "") { + std::string ret; if (gMonitorLcd) - return "on\nOk"; + ret = "on"; else - return "off\nOk"; + ret = "off"; + return ret + gLineTerm + gOk; } std::transform(args.begin(), args.end(), args.begin(), (int(*)(int)) std::tolower); @@ -2120,7 +2147,10 @@ std::string cmd_lcd_mon(ServerSocket& sock, std::string& args) { // Test for end of table if (gStdRomDesc->pFuns[c].strnum == -1) - return "Error - no trap vector \nOk"; + { + std::string ret = "Error - no trap vector" + gLineTerm + gOk; + return ret; + } // Search for the Level 6 plotting function if (gStdRomDesc->pFuns[c].strnum == R_CHAR_PLOT_6) @@ -2135,7 +2165,10 @@ std::string cmd_lcd_mon(ServerSocket& sock, std::string& args) { // Test for end of table if (gStdRomDesc->pVars[c].strnum == -1) - return "Error - no row vector\nOk"; + { + std::string ret = "Error - no row vector" + gLineTerm + gOk; + return ret; + } // Search for the Level 6 plotting function if (gStdRomDesc->pVars[c].strnum == R_CURSOR_ROW) @@ -2168,9 +2201,9 @@ std::string cmd_lcd_mon(ServerSocket& sock, std::string& args) } } else - return "Parameter Error\nOk"; + return gParamError; - return "Ok"; + return gOk; } /* @@ -2183,10 +2216,12 @@ std::string cmd_debug_isr(ServerSocket& sock, std::string& args) // Get breakpoint arguments if (args == "") { + std::string ret; if (gDebugInts) - return "on\nOk"; + ret = "on"; else - return "off\nOk"; + ret = "off"; + return ret + gLineTerm + gOk; } std::transform(args.begin(), args.end(), args.begin(), (int(*)(int)) std::tolower); @@ -2203,9 +2238,9 @@ std::string cmd_debug_isr(ServerSocket& sock, std::string& args) unlock_remote(); } else - return "Parameter Error\nOk"; + return gParamError; - return "Ok"; + return gOk; } /* @@ -2236,7 +2271,7 @@ std::string cmd_string(ServerSocket& sock, std::string& args) address++; } - str += "\nOk"; + str += gLineTerm + gOk; return str; } @@ -2281,12 +2316,12 @@ std::string cmd_disassemble(ServerSocket& sock, std::string& args) for (c = 0; c < lineCount; c++) { dis_addr += dis.DisassembleLine(dis_addr, line); - strcat(line, "\n"); + strcat(line, gLineTerm.c_str()); sock << line; } gLastDisAddress = dis_addr; - return "Ok"; + return gOk; } /* @@ -2333,7 +2368,8 @@ std::string cmd_trace(ServerSocket& sock, std::string& args) // Must be a filename. Only 1 filename allowed if (trace_file != "") { - sprintf(line, "Error filename \"%s\" already specified\nOk", trace_file.c_str()); + sprintf(line, "Error filename \"%s\" already specified%s%s", trace_file.c_str(), + gLineTerm.c_str(), gOk.c_str()); return line; } // Save filename @@ -2367,7 +2403,7 @@ std::string cmd_trace(ServerSocket& sock, std::string& args) gTraceOpen = 1; else { - sock << "Error opening file\n"; + sock << "Error opening file" << gLineTerm; } } } @@ -2413,8 +2449,62 @@ std::string cmd_trace(ServerSocket& sock, std::string& args) } } - return "Ok"; + return gOk; } + +/* +======================================================= +Routine to process remote commands +======================================================= +*/ +int telnet_command_ready(ServerSocket& sock, std::string &cmd) +{ + int len, x, cmd_term; + + len = cmd.length(); + cmd_term = FALSE; + for (x = 0; x < len; x++) + { + char ch = cmd.c_str()[x]; + + /* Test for 0x0D and ignore it */ + if (ch == 0x0D) + continue; + /* Test for 0x0a command line terminaor */ + if (ch == 0x0A) + { + cmd_term = TRUE; + cmd = gTelnetCmd; + gTelnetCmd = ""; + break; + } + // Test for backspace + if (ch == 0x08) + { + if (gTelnetCmd.length() == 0) + continue; + gTelnetCmd = gTelnetCmd.substr(0, gTelnetCmd.length()-1); + sock << " \x08"; + continue; + + } + /* If this character isn't a control char, add it to the cmd */ + if ((ch >= ' ') && (ch <= '~')) + { + char temp[2]; + temp[0] = ch; + temp[1] = 0; + gTelnetCmd = gTelnetCmd + temp; + } + else + { + // TODO: Process telnet out-of band characters + } + } + + return cmd_term; +} + /* ======================================================= Routine to process remote commands @@ -2426,6 +2516,16 @@ std::string process_command(ServerSocket& sock, std::string cmd) std::string cmd_word; std::string args; + // Test for telnet protocol bytes + if (gTelnet) + { + ret += gLineTerm + gOk; + if (!telnet_command_ready(sock, cmd)) + return ""; + if (cmd == "") + return gOk; + } + // Separate out the command word from any arguments args = cmd; cmd_word = get_next_arg(args); @@ -2496,7 +2596,7 @@ std::string process_command(ServerSocket& sock, std::string cmd) else if ((cmd_word == "list_break") || (cmd_word == "lb")) ret = cmd_list_break(sock, args); - else if (cmd_word == "key") + else if ((cmd_word == "key") || (cmd_word == "k")) ret = cmd_key(sock, args); else if (cmd_word == "model") @@ -2582,6 +2682,8 @@ Routine that will become the remote control thread. */ void* remote_control(void* arg) { + std::string ret; + gSocketOpened = FALSE; try { @@ -2596,7 +2698,14 @@ void* remote_control(void* arg) { std::string data; gOpenSock >> data; - gOpenSock << process_command(gOpenSock, data); + ret = process_command(gOpenSock, data); + if (gTelnet) + { + if (ret != "") + gOpenSock << ret; + } + else + gOpenSock << ret; } } catch (SocketException&) @@ -2641,6 +2750,14 @@ void init_remote(void) // Hook our routine to the debug monitor debug_set_monitor_callback(cb_remote_debug); + // Setup the line termination for \r\n if in telnet mode + if (gTelnet) + { + gLineTerm = "\r\n"; + gOk = "Ok> "; + gParamError = "Parameter Error" + gLineTerm + "Ok> "; + } + // Create the thread #ifdef WIN32 DWORD id; diff --git a/src/vt_client_main.cpp b/src/vt_client_main.cpp index eb5c561..08c05c4 100644 --- a/src/vt_client_main.cpp +++ b/src/vt_client_main.cpp @@ -49,7 +49,7 @@ int main ( int argc, char* argv[] ) } #endif - std::cout << "Use decimal or C hex notation for input (0x2a)\n"; + std::cout << "Use decimal, C hex (0x2a) or Asm hex (14h) for input\n"; std::cout << "Return data reported according to specified radix\n"; std::cout << "Type 'help' or 'quit' to exit\n"; From 1752503e21aea062a9be403edf18299dca69a1c3 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 5 Apr 2009 06:11:55 +0000 Subject: [PATCH 171/327] Updates for verrsion 1.4 --- release.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/release.txt b/release.txt index 9f8ca78..042cd19 100644 --- a/release.txt +++ b/release.txt @@ -31,6 +31,22 @@ v1.4 Not released yet 6. Modified the Memory Editor's Load and Save features so they properly address the absolute memory addresses to RAM vs. relative offsets from the beginning RAM address. +7. Fixed socket interface break on memory write function so an LXI H,XXXX doesn't cause a + breakpoint at address XXXX. + +8. Added socket interface shortcuts for the key command (k) and for the "enter" keyword (cr). + +9. Modified hexadecimal input for GUI and socket interfaces to accept HEX formats using the + "04h" notation or for values that contain 'a' through 'f', simply using "5d" notation. + It is case insensitive for both the hex values and 'H'. + +10. Fixed timing race condition on some platforms with the socket interface 'key' command + where the first keystroke would sometimes be dropped. + +11. Modified remote socket interface to support telnet character based transfer and line endings. + + + ======================= v1.3 September 24 2008 ======================= From f23e60871d84d4292bc8e55d5c90581b1378c000 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 5 Apr 2009 08:18:35 +0000 Subject: [PATCH 172/327] Added feature to allow disassembly to continue from previous 'dis' command with empty command line (CR only). Only works if 'dis' was the last command. --- src/remote.cpp | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/remote.cpp b/src/remote.cpp index 09aebce..c8d0a31 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -82,6 +82,8 @@ int gSocketOpened = FALSE; lcd_rect_t gIgnoreRects[10]; int gIgnoreCount = 0; int gLastDisAddress = 0; +int gLastDisCount = 10; +int gLastCmdDis = FALSE; int gTraceOpen = 0; int gTraceActive = 0; std::string gTraceFile; @@ -2303,7 +2305,7 @@ std::string cmd_disassemble(ServerSocket& sock, std::string& args) // Get line count if (more_args == "") - lineCount = 10; + lineCount = gLastDisCount; else lineCount = str_to_i(more_args.c_str()); @@ -2320,6 +2322,7 @@ std::string cmd_disassemble(ServerSocket& sock, std::string& args) sock << line; } gLastDisAddress = dis_addr; + gLastDisCount = lineCount; return gOk; } @@ -2466,6 +2469,7 @@ int telnet_command_ready(ServerSocket& sock, std::string &cmd) for (x = 0; x < len; x++) { char ch = cmd.c_str()[x]; + printf("<%02Xh> ", ch); /* Test for 0x0D and ignore it */ if (ch == 0x0D) @@ -2482,7 +2486,10 @@ int telnet_command_ready(ServerSocket& sock, std::string &cmd) if (ch == 0x08) { if (gTelnetCmd.length() == 0) + { + sock << " "; continue; + } gTelnetCmd = gTelnetCmd.substr(0, gTelnetCmd.length()-1); sock << " \x08"; continue; @@ -2523,13 +2530,26 @@ std::string process_command(ServerSocket& sock, std::string cmd) if (!telnet_command_ready(sock, cmd)) return ""; if (cmd == "") + { + if (gLastCmdDis) + { + ret = cmd_disassemble(sock, args); + return ret; + } return gOk; + } } // Separate out the command word from any arguments args = cmd; cmd_word = get_next_arg(args); + if ((cmd == "") && gLastCmdDis) + { + ret = cmd_disassemble(sock, args); + return ret; + } + if (cmd == "help") // Check for help ret = cmd_help(sock); @@ -2606,7 +2626,11 @@ std::string process_command(ServerSocket& sock, std::string cmd) ret = cmd_speed(sock, args); else if (cmd_word == "dis") + { ret = cmd_disassemble(sock, args); + gLastCmdDis = TRUE; + return ret; + } else if (cmd_word == "pc") ret = cmd_show_reg(sock, PC, 2); @@ -2669,8 +2693,12 @@ std::string process_command(ServerSocket& sock, std::string cmd) { args = "pc " + args; ret = cmd_disassemble(sock, args); + gLastCmdDis = TRUE; + return ret; } + gLastCmdDis = FALSE; + return ret; } From 59d45d3b32e900719853e82063a0286e551afd37 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Mon, 6 Apr 2009 02:16:51 +0000 Subject: [PATCH 173/327] Uncommented Remem mode 8085 CPU opcode emulator that I had commented as a test to check compiled code size of this module. --- src/m100emu.c | 89 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 25 deletions(-) diff --git a/src/m100emu.c b/src/m100emu.c index 32eff75..a2f59f8 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -92,7 +92,7 @@ volatile int gExitLoop = 0; char gsOptRomFile[256]; int gShowVersion = 0; DWORD last_one_sec_time; -int gMaintCount = 262888; +int gMaintCount = 65536; int gOsDelay = 0; int gNoGUI = 0; int gSocketPort = 0; @@ -101,8 +101,8 @@ int gRemoteSwitchModel = -1; //Added J. VERNET -char path[255]; -char file[255]; +char path[512]; +char file[512]; extern RomDescription_t gM100_Desc; extern RomDescription_t gM200_Desc; @@ -461,8 +461,8 @@ check_installation: This routine checks that VirtualT is properly installed void check_installation(void) { int model, len; - char path[256]; - char roms_path[256]; + char localpath[256]; + char roms_path[512]; char errors[256]; FILE *fd, *fd2; @@ -476,35 +476,39 @@ void check_installation(void) continue; /* ROM file doesn't exist. Try to open in ROMs dir */ - get_rom_path(path, model); - sprintf(roms_path, "ROMs%s", strrchr(path, '/')); - + get_rom_path(localpath, model); +#if defined(__APPLE__) + sprintf(roms_path, "%sROMs%s", path, strrchr(localpath, '/')); +#else + sprintf(roms_path, "ROMs%s", strrchr(localpath, '/')); +#endif + if ((fd = fopen(roms_path, "rb")) == NULL) { /* Error - ROM file not in ROMs dir */ if (strlen(errors) != 0) strcat(errors, ", "); - get_model_string(path, model); - strcat(errors, path); + get_model_string(localpath, model); + strcat(errors, localpath); continue; } /* Create the emulation directory */ - get_emulation_path(path, model); + get_emulation_path(localpath, model); #ifdef WIN32 - _mkdir(path); + _mkdir(localpath); #else - mkdir(path, 0755); + mkdir(localpath, 0755); #endif /* Create ROM in the emulation directory */ - get_rom_path(path, model); - fd2 = fopen(path, "wb"); + get_rom_path(localpath, model); + fd2 = fopen(localpath, "wb"); if (fd2 == NULL) { if (strlen(errors) != 0) strcat(errors, ", "); - get_model_string(path, model); - strcat(errors, path); + get_model_string(localpath, model); + strcat(errors, localpath); fclose(fd); continue; } @@ -526,8 +530,8 @@ void check_installation(void) if (strlen(errors) > 0) { - sprintf(path, "No ROM file for %s", errors); - show_error(path); + sprintf(localpath, "No ROM file for %s", errors); + show_error(localpath); } } @@ -907,7 +911,7 @@ void emulate(void) } /* Instruction emulation contained in header file */ - // #include "do_instruct.h" + #include "do_instruct.h" // Check if next inst is SIM if (get_memory8(PC) == 0xF3) @@ -928,7 +932,11 @@ void emulate(void) } /* Do maintenance tasks (Windows events, interrupts, etc.) */ +#ifdef __APPLE__ + if(!(--nxtmaint)) +#else if(!(--nxtmaint & 0x3FF)) +#endif { unlock_remote(); gOsDelay = nxtmaint == 0; @@ -977,7 +985,11 @@ void emulate(void) } /* Do maintenance tasks (Windows events, interrupts, etc.) */ +#ifdef __APPLE__ + if(!(--nxtmaint)) +#else if(!(--nxtmaint & 0x3FF)) +#endif { unlock_remote(); gOsDelay = nxtmaint == 0; @@ -1086,19 +1098,46 @@ is done by looking at the argv[0] argument and removing the app name. void setup_working_path(char **argv) { #if defined(__unix__) || defined(__APPLE__) - int i; + int i, found; + char temp[512]; + struct stat romStat; getcwd(path, sizeof(path)); //J. VERNET: Get Absolute Path, as getcwd doesn't return anything when launch from finder - if (strlen(path) == 0) +#if defined(__APPLE__) + found = FALSE; + + /* Recursively search up the path until we find the ROMs directory */ + i = strlen(argv[0])-1; + strcpy(temp, argv[0]); + while (!found) { - i = strlen(argv[0])-1; // Find last '/' in path to remove app name from the path while ((argv[0][i] != '/') && (i > 0)) i--; - strncpy(path,argv[0], i+1); + if (i < 0) + break; + temp[i+1] = 0; + + /* Now append "ROMs" and check if the directory exists */ + strcat(temp, "ROMs"); + if (stat(temp, &romStat) == 0) + { + if (S_ISDIR(romStat.st_mode)) + { + found = TRUE; + strncpy(path, argv[0], i+1); + path[i+1] = 0; + } + } + else + { + /* Not this directory segment...skip the '/' and find next higher */ + i--; + } } +#endif // Check if the last character is '/' i = strlen(path); @@ -1120,9 +1159,9 @@ int main(int argc, char **argv) if (process_args(argc, argv)) /* Parse command line args */ return 1; + setup_working_path(argv); /* Create a working dir path */ check_installation(); /* Test if install needs to be performed */ setup_unix_signals(); /* Setup Unix signal handling */ - setup_working_path(argv); /* Create a working dir path */ // Added by JV for prefs init_pref(); /* load user Menu preferences */ From d1bb43c6b532cbde68de212bc2535c778d5f8507 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 30 Oct 2010 19:11:15 +0000 Subject: [PATCH 174/327] Updated "std::remove" to simply "remove" to eliminate compile error. --- src/fileprint.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fileprint.cpp b/src/fileprint.cpp index b948701..c9aa0d3 100644 --- a/src/fileprint.cpp +++ b/src/fileprint.cpp @@ -721,7 +721,7 @@ int VTFilePrint::CancelPrintJob(void) // Remove all files in the print job count = m_printFiles.GetSize(); for (c = 0; c < count; c++) - std::remove((const char *) m_printFiles[c]); + remove((const char *) m_printFiles[c]); // Delete all print files from the array m_printFiles.RemoveAll(); From 3ae0c2793852f6724a8ef25837c8f2d13f72e8c8 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 30 Oct 2010 19:12:37 +0000 Subject: [PATCH 175/327] Added include for to eliminate printf compile error. --- src/socket.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/socket.cpp b/src/socket.cpp index e04c676..8659696 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -4,6 +4,7 @@ #include "socket.h" #include "string.h" #include +#include #include #include From c820ca828b92200e203ce05fc54767ef629f00ff Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 31 Oct 2010 05:37:24 +0000 Subject: [PATCH 176/327] Modificaitons to remove gcc compiler warnings. --- src/FLU/flu_pixmaps.h | 64 +++--- src/a85parse.cpp | 2 +- src/a85parse.syn | 2 +- src/assemble.cpp | 22 +- src/clock.cpp | 2 +- src/disassemble.cpp | 2 +- src/display.cpp | 8 +- src/do_instruct.h | 512 ++++++++++++++++++++--------------------- src/file.cpp | 6 +- src/fileprint.cpp | 2 +- src/flu_pixmaps.cpp | 64 +++--- src/ide.cpp | 28 +-- src/lpt.cpp | 16 +- src/m100emu.c | 9 +- src/memory.c | 10 +- src/multiwin_icons.cpp | 26 +-- src/project.cpp | 46 ++-- src/serial.c | 10 +- src/setup.cpp | 2 +- src/vtpaper.cpp | 2 +- 20 files changed, 420 insertions(+), 415 deletions(-) diff --git a/src/FLU/flu_pixmaps.h b/src/FLU/flu_pixmaps.h index 716c630..ad15fbe 100644 --- a/src/FLU/flu_pixmaps.h +++ b/src/FLU/flu_pixmaps.h @@ -18,37 +18,37 @@ #include "flu_export.h" -FLU_EXPORT extern char* plus_xpm[]; -FLU_EXPORT extern char* minus_xpm[]; -FLU_EXPORT extern char* arrow_closed_xpm[]; -FLU_EXPORT extern char* arrow_open_xpm[]; -FLU_EXPORT extern char* bluedot_xpm[]; -FLU_EXPORT extern char* book_xpm[]; -FLU_EXPORT extern char* floppy_drive_xpm[]; -FLU_EXPORT extern char* network_drive_xpm[]; -FLU_EXPORT extern char* ram_drive_xpm[]; -FLU_EXPORT extern char* removable_drive_xpm[]; -FLU_EXPORT extern char* cd_drive_xpm[]; -FLU_EXPORT extern char* computer_xpm[]; -FLU_EXPORT extern char* disk_drive_xpm[]; -FLU_EXPORT extern char* filled_folder_xpm[]; -FLU_EXPORT extern char* folder_closed_xpm[]; -FLU_EXPORT extern char* folder_open_xpm[]; -FLU_EXPORT extern char* folder_up_xpm[]; -FLU_EXPORT extern char* folder_load_xpm[]; -FLU_EXPORT extern char* folder_save_xpm[]; -FLU_EXPORT extern char* big_folder_up_xpm[]; -FLU_EXPORT extern char* big_folder_new_xpm[]; -FLU_EXPORT extern char* greendot_xpm[]; -FLU_EXPORT extern char* purpledot_xpm[]; -FLU_EXPORT extern char* question_book_xpm[]; -FLU_EXPORT extern char* reddot_xpm[]; -FLU_EXPORT extern char* tealdot_xpm[]; -FLU_EXPORT extern char* textdoc_xpm[]; -FLU_EXPORT extern char* yellowdot_xpm[]; -FLU_EXPORT extern char* cdrom_xpm[]; -FLU_EXPORT extern char* trash_xpm[]; -FLU_EXPORT extern char* home_xpm[]; -FLU_EXPORT extern char* reload_xpm[]; +FLU_EXPORT extern const char* plus_xpm[]; +FLU_EXPORT extern const char* minus_xpm[]; +FLU_EXPORT extern const char* arrow_closed_xpm[]; +FLU_EXPORT extern const char* arrow_open_xpm[]; +FLU_EXPORT extern const char* bluedot_xpm[]; +FLU_EXPORT extern const char* book_xpm[]; +FLU_EXPORT extern const char* floppy_drive_xpm[]; +FLU_EXPORT extern const char* network_drive_xpm[]; +FLU_EXPORT extern const char* ram_drive_xpm[]; +FLU_EXPORT extern const char* removable_drive_xpm[]; +FLU_EXPORT extern const char* cd_drive_xpm[]; +FLU_EXPORT extern const char* computer_xpm[]; +FLU_EXPORT extern const char* disk_drive_xpm[]; +FLU_EXPORT extern const char* filled_folder_xpm[]; +FLU_EXPORT extern const char* folder_closed_xpm[]; +FLU_EXPORT extern const char* folder_open_xpm[]; +FLU_EXPORT extern const char* folder_up_xpm[]; +FLU_EXPORT extern const char* folder_load_xpm[]; +FLU_EXPORT extern const char* folder_save_xpm[]; +FLU_EXPORT extern const char* big_folder_up_xpm[]; +FLU_EXPORT extern const char* big_folder_new_xpm[]; +FLU_EXPORT extern const char* greendot_xpm[]; +FLU_EXPORT extern const char* purpledot_xpm[]; +FLU_EXPORT extern const char* question_book_xpm[]; +FLU_EXPORT extern const char* reddot_xpm[]; +FLU_EXPORT extern const char* tealdot_xpm[]; +FLU_EXPORT extern const char* textdoc_xpm[]; +FLU_EXPORT extern const char* yellowdot_xpm[]; +FLU_EXPORT extern const char* cdrom_xpm[]; +FLU_EXPORT extern const char* trash_xpm[]; +FLU_EXPORT extern const char* home_xpm[]; +FLU_EXPORT extern const char* reload_xpm[]; #endif diff --git a/src/a85parse.cpp b/src/a85parse.cpp index dbbb445..e6bb017 100644 --- a/src/a85parse.cpp +++ b/src/a85parse.cpp @@ -131,7 +131,7 @@ BOOL ParseASMFile(const char* filename, VTAssembler* pAsm) if ((gAsm->m_fd = fopen(gAsm->m_Filenames[gAsm->m_FileIndex], "r")) == 0) { // Add error indicating failure to open file - gAsm->m_Errors.Add("Error opening file"); + gAsm->m_Errors.Add((char *) "Error opening file"); return FALSE; } diff --git a/src/a85parse.syn b/src/a85parse.syn index 5673ec8..66764ac 100644 --- a/src/a85parse.syn +++ b/src/a85parse.syn @@ -581,7 +581,7 @@ BOOL ParseASMFile(const char* filename, VTAssembler* pAsm) if ((gAsm->m_fd = fopen(gAsm->m_Filenames[gAsm->m_FileIndex], "r")) == 0) { // Add error indicating failure to open file - gAsm->m_Errors.Add("Error opening file"); + gAsm->m_Errors.Add((char *) "Error opening file"); return FALSE; } diff --git a/src/assemble.cpp b/src/assemble.cpp index 6a0ab47..e3d35d1 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -261,7 +261,7 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, { if ((temp[0] == '$') && (temp[1] != 0)) { - temp = m_LastLabel + "%%" + op.m_Variable; + temp = m_LastLabel + (char *) "%%" + op.m_Variable; local = 1; } } @@ -319,7 +319,7 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, else { // Check if AuotExtern is enabled - if (m_AsmOptions.Find("-e") != -1) + if (m_AsmOptions.Find((char *) "-e") != -1) { // Add symbol as an EXTERN symbol = new CSymbol; @@ -489,7 +489,7 @@ int VTAssembler::GetValue(MString & string, int & value) MString myStr = string; if ((string[0] == '$') && (string[1] != 0)) { - myStr = m_LastLabel + "%%" + string; + myStr = m_LastLabel + (char *) "%%" + string; } for (c = 0; c < 3; c++) { @@ -820,7 +820,7 @@ void VTAssembler::include(const char *filename) } } -char* types[5] = { "", "a label", "an equate", "a set", "an extern" }; +const char* types[5] = { "", "a label", "an equate", "a set", "an extern" }; /* ============================================================================ @@ -936,7 +936,7 @@ void VTAssembler::label(const char *label) if (pSymbol != NULL) { if (local) - pSymbol->m_Name = m_LastLabel + "%%" + label; + pSymbol->m_Name = m_LastLabel + (char *) "%%" + label; else pSymbol->m_Name = label; pSymbol->m_Line = m_Line; @@ -2776,7 +2776,7 @@ int VTAssembler::CreateObjFile(const char *filename) Add debug sections to .OBJ file ======================================= */ - if (m_AsmOptions.Find("-g") >= 0) + if (m_AsmOptions.Find((char *) "-g") >= 0) { } @@ -2965,7 +2965,7 @@ void VTAssembler::Parse(MString filename) // Append .obj to filename temp = outfile; - outfile += ".obj"; + outfile += (char *) ".obj"; // Generate the object file CreateObjFile(outfile); @@ -2981,7 +2981,7 @@ void VTAssembler::CreateList(MString& filename) MString outfile; FILE* fd; - if ((m_AsmOptions.Find("-l") != -1) || (m_List)) + if ((m_AsmOptions.Find((char *) "-l") != -1) || (m_List)) { if ((strcmp(filename, ".asm") == 0) || (strcmp(filename, "a85") == 0)) { @@ -2991,7 +2991,7 @@ void VTAssembler::CreateList(MString& filename) outfile = filename; // Append .lst to filename - outfile += ".lst"; + outfile += (char *) ".lst"; fd = fopen(outfile, "wb+"); fclose(fd); @@ -3157,8 +3157,8 @@ void VTAssembler::CalcIncludeDirs(void) // Generate the path temp = pToken; temp.Trim(); - temp += "/"; - temp = m_RootPath + "/" + temp; + temp += (char *) "/"; + temp = m_RootPath + (char *) "/" + temp; // Now add it to the array m_IncludeDirs.Add(temp); diff --git a/src/clock.cpp b/src/clock.cpp index a8d0860..30f3e73 100644 --- a/src/clock.cpp +++ b/src/clock.cpp @@ -417,7 +417,7 @@ void save_model_time(void) convert_ctime: Convert from string time to time_t. ============================================================================= */ -char *gMonths[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", +const char *gMonths[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; time_t convert_ctime(char* stime) { diff --git a/src/disassemble.cpp b/src/disassemble.cpp index f85ad87..269ee48 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -67,7 +67,7 @@ void close_cb(Fl_Widget* w, void*) } // Table of OPCODE -char * gStrTable[256] = { +const char * gStrTable[256] = { "NOP", "LXI B,", "STAX B", "INX B", "INR B", "DCR B", "MVI B,", "RLC", "DSUB", "DAD B", "LDAX B", "DCX B", "INR C", "DCR C", "MVI C,", "RRC", diff --git a/src/display.cpp b/src/display.cpp index 4f4ebb5..7e232f7 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -148,7 +148,7 @@ void setMonitorWindow(Fl_Window* pWin) int T100_Disp::m_simKeys[32]; int T100_Disp::m_simEventKey; -char *gSpKeyText[] = { +const char *gSpKeyText[] = { "SHIFT", "CTRL", "GRAPH", @@ -1492,7 +1492,7 @@ void init_display(void) display_map_mode(temp); } else - display_map_mode("Normal"); + display_map_mode((char *) "Normal"); } @@ -1592,8 +1592,8 @@ void T100_Disp::PowerDown() Fl::check(); // Print power down message - char *msg = "System Powered Down"; - char *msg2 = "Press any key to reset"; + char *msg = (char *) "System Powered Down"; + char *msg2 = (char *) "Press any key to reset"; int x; int col; int driver, column; diff --git a/src/do_instruct.h b/src/do_instruct.h index 3e649f5..a77145b 100644 --- a/src/do_instruct.h +++ b/src/do_instruct.h @@ -312,23 +312,23 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x00: /* NOP */ + /* case 0x00: NOP */ INCPC; cycle_delta+=(4); /* return; */ } else { - /* case 0x01: /* LXI B */ + /* case 0x01: LXI B */ LXI(BC,B,C,"B"); } } else { if(!(ins&0x01)) { - /* case 0x02: /* STAX B */ + /* case 0x02: STAX B */ STAX(BC,"B"); } else { - /* case 0x03: /* INX B */ + /* case 0x03: INX B */ INX(BC,B,C,"B"); } } @@ -336,21 +336,21 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x04: /* INR B */ + /* case 0x04: INR B */ INR(B,"B"); } else { - /* case 0x05: /* DCR B */ + /* case 0x05: DCR B */ DCR(B,"B"); } } else { if(!(ins&0x01)) { - /* case 0x06: /* MVI B */ + /* case 0x06: MVI B */ MVI(B,"B"); } else { - /* case 0x07: /* RLC */ + /* case 0x07: RLC */ INCPC; i=A>>7; A=(A<<1)|i; @@ -365,7 +365,7 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x08: /* DSUB */ + /* case 0x08: DSUB */ INCPC; i = HL < BC;// - (CF?1:0); j = HL - BC;// - (CF?1:0); @@ -379,17 +379,17 @@ ins = INS; /* return; */ } else { - /* case 0x09: /* DAD B */ + /* case 0x09: DAD B */ DAD(BC,"B"); } } else { if(!(ins&0x01)) { - /* case 0x0A: /* LDAX B */ + /* case 0x0A: LDAX B */ LDAX(BC,"B"); } else { - /* case 0x0B: /* DCX B */ + /* case 0x0B: DCX B */ DCX(BC,B,C,"B"); } } @@ -397,21 +397,21 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x0C: /* INR C */ + /* case 0x0C: INR C */ INR(C,"C"); } else { - /* case 0x0D: /* DCR C */ + /* case 0x0D: DCR C */ DCR(C,"C"); } } else { if(!(ins&0x01)) { - /* case 0x0E: /* MVI C */ + /* case 0x0E: MVI C */ MVI(C,"C"); } else { - /* case 0x0F: /* RRC */ + /* case 0x0F: RRC */ INCPC; i=A<<7&0x80; A=(A>>1)|i; @@ -429,7 +429,7 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x10: /* ASHR */ + /* case 0x10: ASHR */ INCPC; i = L & CF ; j = HL >> 1; @@ -440,17 +440,17 @@ ins = INS; /* return; */ } else { - /* case 0x11: /* LXI D */ + /* case 0x11: LXI D */ LXI(DE,D,E,"D"); } } else { if(!(ins&0x01)) { - /* case 0x12: /* STAX D */ + /* case 0x12: STAX D */ STAX(DE,"D"); } else { - /* case 0x13: /* INX D */ + /* case 0x13: INX D */ INX(DE,D,E,"D"); } } @@ -458,21 +458,21 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x14: /* INR D */ + /* case 0x14: INR D */ INR(D,"D"); } else { - /* case 0x15: /* DCR D */ + /* case 0x15: DCR D */ DCR(D,"D"); } } else { if(!(ins&0x01)) { - /* case 0x16: /* MVI D */ + /* case 0x16: MVI D */ MVI(D,"D"); } else { - /* case 0x17: /* RAL */ + /* case 0x17: RAL */ INCPC; i=A>>7; A<<=1; @@ -488,7 +488,7 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x18: /* RLDE */ + /* case 0x18: RLDE */ INCPC; i = D & 0x80 ? 1 : 0; j = DE << 1; @@ -499,17 +499,17 @@ ins = INS; /* return; */ } else { - /* case 0x19: /* DAD D */ + /* case 0x19: DAD D */ DAD(DE,"D"); } } else { if(!(ins&0x01)) { - /* case 0x1A: /* LDAX D */ + /* case 0x1A: LDAX D */ LDAX(DE,"D"); } else { - /* case 0x1B: /* DCX D */ + /* case 0x1B: DCX D */ DCX(DE,D,E,"D"); } } @@ -517,21 +517,21 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x1C: /* INR E */ + /* case 0x1C: INR E */ INR(E,"E"); } else { - /* case 0x1D: /* DCR E */ + /* case 0x1D: DCR E */ DCR(E,"E"); } } else { if(!(ins&0x01)) { - /* case 0x1E: /* MVI E */ + /* case 0x1E: MVI E */ MVI(E,"E"); } else { - /* case 0x1F: /* RAR */ + /* case 0x1F: RAR */ INCPC; i=(A&0x01); A>>=1; @@ -551,20 +551,20 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x20: /* RIM */ + /* case 0x20: RIM */ INCPC; A=IM; cycle_delta+=(4); /* return; */ } else { - /* case 0x21: /* LXI H */ + /* case 0x21: LXI H */ LXI(HL,H,L,"H"); } } else { if(!(ins&0x01)) { - /* case 0x22: /* SHLD */ + /* case 0x22: SHLD */ INCPC; MEMSET(INS16,L); MEMSET(INS16+1,H); @@ -574,7 +574,7 @@ ins = INS; /* return; */ } else { - /* case 0x23: /* INX H */ + /* case 0x23: INX H */ INX(HL,H,L,"H"); } } @@ -582,21 +582,21 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x24: /* INR H */ + /* case 0x24: INR H */ INR(H,"H"); } else { - /* case 0x25: /* DCR H */ + /* case 0x25: DCR H */ DCR(H,"H"); } } else { if(!(ins&0x01)) { - /* case 0x26: /* MVI H */ + /* case 0x26: MVI H */ MVI(H,"H"); } else { - /* case 0x27: /* DAA */ + /* case 0x27: DAA */ INCPC; i=j=0; /* Check if lower nibble greater than 9 */ @@ -623,7 +623,7 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x28: /* LDEH */ + /* case 0x28: LDEH */ INCPC; j = HL + INS; INCPC; @@ -633,13 +633,13 @@ ins = INS; /* return; */ } else { - /* case 0x29: /* DAD H */ + /* case 0x29: DAD H */ DAD(HL,"H"); } } else { if(!(ins&0x01)) { - /* case 0x2A: /* LHLD */ + /* case 0x2A: LHLD */ INCPC; L=MEM(INS16); H=MEM(INS16+1); @@ -647,7 +647,7 @@ ins = INS; cycle_delta+=(16); } else { - /* case 0x2B: /* DCX H */ + /* case 0x2B: DCX H */ DCX(HL,H,L,"H"); } } @@ -655,21 +655,21 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x2C: /* INR L */ + /* case 0x2C: INR L */ INR(L,"L"); } else { - /* case 0x2D: /* DCR L */ + /* case 0x2D: DCR L */ DCR(L,"L"); } } else { if(!(ins&0x01)) { - /* case 0x2E: /* MVI L */ + /* case 0x2E: MVI L */ MVI(L,"L"); } else { - /* case 0x2F: /* CMA */ + /* case 0x2F: CMA */ INCPC; A=~A; cycle_delta+=(4); @@ -683,7 +683,7 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x30: /* SIM */ + /* case 0x30: SIM */ INCPC; if (A & 0x08) /* Check if Interrupt masking enabled */ IM=(IM & 0xF8) | (A&0x07); @@ -695,13 +695,13 @@ ins = INS; /* return; */ } else { - /* case 0x31: /* LXI SP */ + /* case 0x31: LXI SP */ LXI(SP,SPH,SPL,"SP"); } } else { if(!(ins&0x01)) { - /* case 0x32: /* STA */ + /* case 0x32: STA */ INCPC; MEMSET(INS16,A); INCPC2; @@ -709,7 +709,7 @@ ins = INS; /* return; */ } else { - /* case 0x33: /* INX SP */ + /* case 0x33: INX SP */ INX(SP,SPH,SPL,"SP"); } } @@ -717,7 +717,7 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x34: /* INR M */ + /* case 0x34: INR M */ INCPC; MEMSET(HL,(uchar) (M+1)); if((M&0x0f)==0) /* Low order nybble wrapped */ @@ -728,7 +728,7 @@ ins = INS; cycle_delta+=(10); } else { - /* case 0x35: /* DCR M */ + /* case 0x35: DCR M */ INCPC; MEMSET(HL, (uchar)(M-1)); if((M&0x0f)==0x0f) /* Low order nybble wrapped */ @@ -741,14 +741,14 @@ ins = INS; } else { if(!(ins&0x01)) { - /* case 0x36: /* MVI M */ + /* case 0x36: MVI M */ INCPC; MEMSET(HL,INS); INCPC; cycle_delta+=(10); } else { - /* case 0x37: /* STC */ + /* case 0x37: STC */ INCPC; setflags(0,-2,-2,-2,-2,1,-2,-2); cycle_delta+=(4); @@ -761,7 +761,7 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x38: /* LDES */ + /* case 0x38: LDES */ INCPC; j = SP + INS; INCPC; @@ -771,13 +771,13 @@ ins = INS; /* return; */ } else { - /* case 0x39: /* DAD SP */ + /* case 0x39: DAD SP */ DAD(SP,"SP"); } } else { if(!(ins&0x01)) { - /* case 0x3A: /* LDA */ + /* case 0x3A: LDA */ INCPC; A=MEM(INS16); INCPC2; @@ -785,7 +785,7 @@ ins = INS; /* return; */ } else { - /* case 0x3B: /* DCX SP */ + /* case 0x3B: DCX SP */ DCX(SP,SPH,SPL,"SP"); } } @@ -793,21 +793,21 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x3C: /* INR A */ + /* case 0x3C: INR A */ INR(A,"A"); } else { - /* case 0x3D: /* DCR A */ + /* case 0x3D: DCR A */ DCR(A,"A"); } } else { if(!(ins&0x01)) { - /* case 0x3E: /* MVI A */ + /* case 0x3E: MVI A */ MVI(A,"A"); } else { - /* case 0x3F: /* CMC */ + /* case 0x3F: CMC */ INCPC; setflags(A,-2,-2,-2,-2,CF?0:1,-2,-2); cycle_delta+=(4); @@ -826,21 +826,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x40: /* MOV B,B */ + /* case 0x40: MOV B,B */ MOV(B,B,"B","B"); } else { - /* case 0x41: /* MOV B,C */ + /* case 0x41: MOV B,C */ MOV(B,C,"B","C"); } } else { if(!(ins&0x01)) { - /* case 0x42: /* MOV B,D */ + /* case 0x42: MOV B,D */ MOV(B,D,"B","D"); } else { - /* case 0x43: /* MOV B,E */ + /* case 0x43: MOV B,E */ MOV(B,E,"B","E"); } } @@ -848,23 +848,23 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x44: /* MOV B,H */ + /* case 0x44: MOV B,H */ MOV(B,H,"B","H"); } else { - /* case 0x45: /* MOV B,L */ + /* case 0x45: MOV B,L */ MOV(B,L,"B","L"); } } else { if(!(ins&0x01)) { - /* case 0x46: /* MOV B,M */ + /* case 0x46: MOV B,M */ MOV(B,M,"B","M"); cycle_delta+=(3); /* return; */ } else { - /* case 0x47: /* MOV B,A */ + /* case 0x47: MOV B,A */ MOV(B,A,"B","A"); } } @@ -874,21 +874,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x48: /* MOV C,B */ + /* case 0x48: MOV C,B */ MOV(C,B,"C","B"); } else { - /* case 0x49: /* MOV C,C */ + /* case 0x49: MOV C,C */ MOV(C,C,"C","C"); } } else { if(!(ins&0x01)) { - /* case 0x4A: /* MOV C,D */ + /* case 0x4A: MOV C,D */ MOV(C,D,"C","D"); } else { - /* case 0x4B: /* MOV C,E */ + /* case 0x4B: MOV C,E */ MOV(C,E,"C","E"); } } @@ -896,22 +896,22 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x4C: /* MOV C,H */ + /* case 0x4C: MOV C,H */ MOV(C,H,"C","H"); } else { - /* case 0x4D: /* MOV C,L */ + /* case 0x4D: MOV C,L */ MOV(C,L,"C","L"); } } else { if(!(ins&0x01)) { - /* case 0x4E: /* MOV C,M */ + /* case 0x4E: MOV C,M */ MOV(C,M,"C","M"); cycle_delta+=(3); } else { - /* case 0x4F: /* MOV C,A */ + /* case 0x4F: MOV C,A */ MOV(C,A,"C","A"); } } @@ -923,21 +923,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x50: /* MOV D,B */ + /* case 0x50: MOV D,B */ MOV(D,B,"D","B"); } else { - /* case 0x51: /* MOV D,C */ + /* case 0x51: MOV D,C */ MOV(D,C,"D","C"); } } else { if(!(ins&0x01)) { - /* case 0x52: /* MOV D,D */ + /* case 0x52: MOV D,D */ MOV(D,D,"D","D"); } else { - /* case 0x53: /* MOV D,E */ + /* case 0x53: MOV D,E */ MOV(D,E,"D","E"); } } @@ -945,22 +945,22 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x54: /* MOV D,H */ + /* case 0x54: MOV D,H */ MOV(D,H,"D","H"); } else { - /* case 0x55: /* MOV D,L */ + /* case 0x55: MOV D,L */ MOV(D,L,"D","L"); } } else { if(!(ins&0x01)) { - /* case 0x56: /* MOV D,M */ + /* case 0x56: MOV D,M */ MOV(D,M,"D","M"); cycle_delta+=(3); } else { - /* case 0x57: /* MOV D,A */ + /* case 0x57: MOV D,A */ MOV(D,A,"D","A"); } } @@ -970,21 +970,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x58: /* MOV E,B */ + /* case 0x58: MOV E,B */ MOV(E,B,"E","B"); } else { - /* case 0x59: /* MOV E,C */ + /* case 0x59: MOV E,C */ MOV(E,C,"E","C"); } } else { if(!(ins&0x01)) { - /* case 0x5A: /* MOV E,D */ + /* case 0x5A: MOV E,D */ MOV(E,D,"E","D"); } else { - /* case 0x5B: /* MOV E,E */ + /* case 0x5B: MOV E,E */ MOV(E,E,"E","E"); } } @@ -992,22 +992,22 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x5C: /* MOV E,H */ + /* case 0x5C: MOV E,H */ MOV(E,H,"E","H"); } else { - /* case 0x5D: /* MOV E,L */ + /* case 0x5D: MOV E,L */ MOV(E,L,"E","L"); } } else { if(!(ins&0x01)) { - /* case 0x5E: /* MOV E,M */ + /* case 0x5E: MOV E,M */ MOV(E,M,"E","M"); cycle_delta+=(3); } else { - /* case 0x5F: /* MOV E,A */ + /* case 0x5F: MOV E,A */ MOV(E,A,"E","A"); } } @@ -1021,21 +1021,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x60: /* MOV H,B */ + /* case 0x60: MOV H,B */ MOV(H,B,"H","B"); } else { - /* case 0x61: /* MOV H,C */ + /* case 0x61: MOV H,C */ MOV(H,C,"H","C"); } } else { if(!(ins&0x01)) { - /* case 0x62: /* MOV H,D */ + /* case 0x62: MOV H,D */ MOV(H,D,"H","D"); } else { - /* case 0x63: /* MOV H,E */ + /* case 0x63: MOV H,E */ MOV(H,E,"H","E"); } } @@ -1043,21 +1043,21 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x64: /* MOV H,H */ + /* case 0x64: MOV H,H */ MOV(H,H,"H","H"); } else { - /* case 0x65: /* MOV H,L */ + /* case 0x65: MOV H,L */ MOV(H,L,"H","L"); } } else { if(!(ins&0x01)) { - /* case 0x66: /* MOV H,M */ + /* case 0x66: MOV H,M */ MOV(H,M,"H","M"); } else { - /* case 0x67: /* MOV H,A */ + /* case 0x67: MOV H,A */ MOV(H,A,"H","A"); } } @@ -1067,21 +1067,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x68: /* MOV L,B */ + /* case 0x68: MOV L,B */ MOV(L,B,"L","B"); } else { - /* case 0x69: /* MOV L,C */ + /* case 0x69: MOV L,C */ MOV(L,C,"L","C"); } } else { if(!(ins&0x01)) { - /* case 0x6A: /* MOV L,D */ + /* case 0x6A: MOV L,D */ MOV(L,D,"L","D"); } else { - /* case 0x6B: /* MOV L,E */ + /* case 0x6B: MOV L,E */ MOV(L,E,"L","E"); } } @@ -1089,22 +1089,22 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x6C: /* MOV L,H */ + /* case 0x6C: MOV L,H */ MOV(L,H,"L","H"); } else { - /* case 0x6D: /* MOV L,L */ + /* case 0x6D: MOV L,L */ MOV(L,L,"L","L"); } } else { if(!(ins&0x01)) { - /* case 0x6E: /* MOV L,M */ + /* case 0x6E: MOV L,M */ MOV(L,M,"L","M"); cycle_delta+=(3); } else { - /* case 0x6F: /* MOV L,A */ + /* case 0x6F: MOV L,A */ MOV(L,A,"L","A"); } } @@ -1116,21 +1116,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x70: /* MOV M,B */ + /* case 0x70: MOV M,B */ MOVM(B,"B"); } else { - /* case 0x71: /* MOV M,C */ + /* case 0x71: MOV M,C */ MOVM(C,"C"); } } else { if(!(ins&0x01)) { - /* case 0x72: /* MOV M,D */ + /* case 0x72: MOV M,D */ MOVM(D,"D"); } else { - /* case 0x73: /* MOV M,E */ + /* case 0x73: MOV M,E */ MOVM(E,"E"); } } @@ -1138,22 +1138,22 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x74: /* MOV M,H */ + /* case 0x74: MOV M,H */ MOVM(H,"H"); } else { - /* case 0x75: /* MOV M,L */ + /* case 0x75: MOV M,L */ MOVM(L,"L"); } } else { if(!(ins&0x01)) { - /* case 0x76: /* HLT */ + /* case 0x76: HLT */ cycle_delta+=(4); /* return; */ } else { - /* case 0x77: /* MOV M,A */ + /* case 0x77: MOV M,A */ MOVM(A,"A"); } } @@ -1163,21 +1163,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x78: /* MOV A,B */ + /* case 0x78: MOV A,B */ MOV(A,B,"A","B"); } else { - /* case 0x79: /* MOV A,C */ + /* case 0x79: MOV A,C */ MOV(A,C,"A","C"); } } else { if(!(ins&0x01)) { - /* case 0x7A: /* MOV A,D */ + /* case 0x7A: MOV A,D */ MOV(A,D,"A","D"); } else { - /* case 0x7B: /* MOV A,E */ + /* case 0x7B: MOV A,E */ MOV(A,E,"A","E"); } } @@ -1185,22 +1185,22 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x7C: /* MOV A,H */ + /* case 0x7C: MOV A,H */ MOV(A,H,"A","H"); } else { - /* case 0x7D: /* MOV A,L */ + /* case 0x7D: MOV A,L */ MOV(A,L,"A","L"); } } else { if(!(ins&0x01)) { - /* case 0x7E: /* MOV A,M */ + /* case 0x7E: MOV A,M */ MOV(A,M,"A","M"); cycle_delta+=(3); } else { - /* case 0x7F: /* MOV A,A */ + /* case 0x7F: MOV A,A */ MOV(A,A,"A","A"); } } @@ -1218,21 +1218,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x80: /* ADD B */ + /* case 0x80: ADD B */ ADD(B,"B"); } else { - /* case 0x81: /* ADD C */ + /* case 0x81: ADD C */ ADD(C,"C"); } } else { if(!(ins&0x01)) { - /* case 0x82: /* ADD D */ + /* case 0x82: ADD D */ ADD(D,"D"); } else { - /* case 0x83: /* ADD E */ + /* case 0x83: ADD E */ ADD(E,"E"); } } @@ -1240,22 +1240,22 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x84: /* ADD H */ + /* case 0x84: ADD H */ ADD(H,"H"); } else { - /* case 0x85: /* ADD L */ + /* case 0x85: ADD L */ ADD(L,"L"); } } else { if(!(ins&0x01)) { - /* case 0x86: /* ADD M */ + /* case 0x86: ADD M */ ADD(M,"M"); cycle_delta+=(3); } else { - /* case 0x87: /* ADD A */ + /* case 0x87: ADD A */ ADD(A,"A"); } } @@ -1265,21 +1265,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x88: /* ADC B */ + /* case 0x88: ADC B */ ADC(B,"B"); } else { - /* case 0x89: /* ADC C */ + /* case 0x89: ADC C */ ADC(C,"C"); } } else { if(!(ins&0x01)) { - /* case 0x8A: /* ADC D */ + /* case 0x8A: ADC D */ ADC(D,"D"); } else { - /* case 0x8B: /* ADC E */ + /* case 0x8B: ADC E */ ADC(E,"E"); } } @@ -1287,22 +1287,22 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x8C: /* ADC H */ + /* case 0x8C: ADC H */ ADC(H,"H"); } else { - /* case 0x8D: /* ADC L */ + /* case 0x8D: ADC L */ ADC(L,"L"); } } else { if(!(ins&0x01)) { - /* case 0x8E: /* ADC M */ + /* case 0x8E: ADC M */ ADC(M,"M"); cycle_delta+=(3); } else { - /* case 0x8F: /* ADC A */ + /* case 0x8F: ADC A */ ADC(A,"A"); } } @@ -1314,21 +1314,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x90: /* SUB B */ + /* case 0x90: SUB B */ SUB(B,"B"); } else { - /* case 0x91: /* SUB C */ + /* case 0x91: SUB C */ SUB(C,"C"); } } else { if(!(ins&0x01)) { - /* case 0x92: /* SUB D */ + /* case 0x92: SUB D */ SUB(D,"D"); } else { - /* case 0x93: /* SUB E */ + /* case 0x93: SUB E */ SUB(E,"E"); } } @@ -1336,22 +1336,22 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x94: /* SUB H */ + /* case 0x94: SUB H */ SUB(H,"H"); } else { - /* case 0x95: /* SUB L */ + /* case 0x95: SUB L */ SUB(L,"L"); } } else { if(!(ins&0x01)) { - /* case 0x96: /* SUB M */ + /* case 0x96: SUB M */ SUB(M,"M"); cycle_delta+=(3); } else { - /* case 0x97: /* SUB A */ + /* case 0x97: SUB A */ SUB(A,"A"); } } @@ -1361,21 +1361,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x98: /* SBB B */ + /* case 0x98: SBB B */ SBB(B,"B"); } else { - /* case 0x99: /* SBB C */ + /* case 0x99: SBB C */ SBB(C,"C"); } } else { if(!(ins&0x01)) { - /* case 0x9A: /* SBB D */ + /* case 0x9A: SBB D */ SBB(D,"D"); } else { - /* case 0x9B: /* SBB E */ + /* case 0x9B: SBB E */ SBB(E,"E"); } } @@ -1383,22 +1383,22 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0x9C: /* SBB H */ + /* case 0x9C: SBB H */ SBB(H,"H"); } else { - /* case 0x9D: /* SBB L */ + /* case 0x9D: SBB L */ SBB(L,"L"); } } else { if(!(ins&0x01)) { - /* case 0x9E: /* SBB M */ + /* case 0x9E: SBB M */ SBB(M,"M"); cycle_delta+=(3); } else { - /* case 0x9F: /* SBB A */ + /* case 0x9F: SBB A */ SBB(A,"A"); } } @@ -1412,21 +1412,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xA0: /* ANA B */ + /* case 0xA0: ANA B */ ANA(B,"B"); } else { - /* case 0xA1: /* ANA C */ + /* case 0xA1: ANA C */ ANA(C,"C"); } } else { if(!(ins&0x01)) { - /* case 0xA2: /* ANA D */ + /* case 0xA2: ANA D */ ANA(D,"D"); } else { - /* case 0xA3: /* ANA E */ + /* case 0xA3: ANA E */ ANA(E,"E"); } } @@ -1434,22 +1434,22 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xA4: /* ANA H */ + /* case 0xA4: ANA H */ ANA(H,"H"); } else { - /* case 0xA5: /* ANA L */ + /* case 0xA5: ANA L */ ANA(L,"L"); } } else { if(!(ins&0x01)) { - /* case 0xA6: /* ANA M */ + /* case 0xA6: ANA M */ ANA(M,"M"); cycle_delta+=(3); } else { - /* case 0xA7: /* ANA A */ + /* case 0xA7: ANA A */ ANA(A,"A"); } } @@ -1459,21 +1459,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xA8: /* XRA B */ + /* case 0xA8: XRA B */ XRA(B,"B"); } else { - /* case 0xA9: /* XRA C */ + /* case 0xA9: XRA C */ XRA(C,"C"); } } else { if(!(ins&0x01)) { - /* case 0xAA: /* XRA D */ + /* case 0xAA: XRA D */ XRA(D,"D"); } else { - /* case 0xAB: /* XRA E */ + /* case 0xAB: XRA E */ XRA(E,"E"); } } @@ -1481,22 +1481,22 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xAC: /* XRA H */ + /* case 0xAC: XRA H */ XRA(H,"H"); } else { - /* case 0xAD: /* XRA L */ + /* case 0xAD: XRA L */ XRA(L,"L"); } } else { if(!(ins&0x01)) { - /* case 0xAE: /* XRA M */ + /* case 0xAE: XRA M */ XRA(M,"M"); cycle_delta+=(3); } else { - /* case 0xAF: /* XRA A */ + /* case 0xAF: XRA A */ XRA(A,"A"); } } @@ -1508,21 +1508,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xB0: /* ORA B */ + /* case 0xB0: ORA B */ ORA(B,"B"); } else { - /* case 0xB1: /* ORA C */ + /* case 0xB1: ORA C */ ORA(C,"C"); } } else { if(!(ins&0x01)) { - /* case 0xB2: /* ORA D */ + /* case 0xB2: ORA D */ ORA(D,"D"); } else { - /* case 0xB3: /* ORA E */ + /* case 0xB3: ORA E */ ORA(E,"E"); } } @@ -1530,22 +1530,22 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xB4: /* ORA H */ + /* case 0xB4: ORA H */ ORA(H,"H"); } else { - /* case 0xB5: /* ORA L */ + /* case 0xB5: ORA L */ ORA(L,"L"); } } else { if(!(ins&0x01)) { - /* case 0xB6: /* ORA M */ + /* case 0xB6: ORA M */ ORA(M,"M"); cycle_delta+=(3); } else { - /* case 0xB7: /* ORA A */ + /* case 0xB7: ORA A */ ORA(A,"A"); } } @@ -1555,21 +1555,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xB8: /* CMP B */ + /* case 0xB8: CMP B */ CMP(B,"B"); } else { - /* case 0xB9: /* CMP C */ + /* case 0xB9: CMP C */ CMP(C,"C"); } } else { if(!(ins&0x01)) { - /* case 0xBA: /* CMP D */ + /* case 0xBA: CMP D */ CMP(D,"D"); } else { - /* case 0xBB: /* CMP E */ + /* case 0xBB: CMP E */ CMP(E,"E"); } } @@ -1577,22 +1577,22 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xBC: /* CMP H */ + /* case 0xBC: CMP H */ CMP(H,"H"); } else { - /* case 0xBD: /* CMP L */ + /* case 0xBD: CMP L */ CMP(L,"L"); } } else { if(!(ins&0x01)) { - /* case 0xBE: /* CMP M */ + /* case 0xBE: CMP M */ CMP(M,"M"); cycle_delta+=(3); } else { - /* case 0xBF: /* CMP A */ + /* case 0xBF: CMP A */ CMP(A,"A"); } } @@ -1608,7 +1608,7 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xC0: /* RNZ */ + /* case 0xC0: RNZ */ INCPC; if(!ZF) { PCL=MEM(SP); PCH=MEM(SP+1); /* PC=MEM16(SP) */ @@ -1619,17 +1619,17 @@ ins = INS; /* return; */ } else { - /* case 0xC1: /* POP B */ + /* case 0xC1: POP B */ POP(BC,B,C,"B"); } } else { if(!(ins&0x01)) { - /* case 0xC2: /* JNZ addr */ + /* case 0xC2: JNZ addr */ JUMP(!ZF,"JNZ"); } else { - /* case 0xC3: /* JMP addr */ + /* case 0xC3: JMP addr */ JUMP(1,"JMP"); } } @@ -1637,17 +1637,17 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xC4: /* CNZ addr */ + /* case 0xC4: CNZ addr */ CALL(!ZF,"CNZ"); } else { - /* case 0xC5: /* PUSH B */ + /* case 0xC5: PUSH B */ PUSH(BC,B,C,"B"); } } else { if(!(ins&0x01)) { - /* case 0xC6: /* ADI n */ + /* case 0xC6: ADI n */ INCPC; i=A; i+=INS; @@ -1666,7 +1666,7 @@ ins = INS; /* return; */ } else { - /* case 0xC7: /* RST 0 */ + /* case 0xC7: RST 0 */ RST(0); } } @@ -1676,21 +1676,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xC8: /* RZ */ + /* case 0xC8: RZ */ RETURN(ZF,"RZ"); } else { - /* case 0xC9: /* RET */ + /* case 0xC9: RET */ RETURN(1,"RET"); } } else { if(!(ins&0x01)) { - /* case 0xCA: /* JZ addr */ + /* case 0xCA: JZ addr */ JUMP(ZF,"JZ"); } else { - /* case 0xCB: /* RSTV */ + /* case 0xCB: RSTV */ if (OV) RST(8); /* return; */ @@ -1700,17 +1700,17 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xCC: /* CZ addr */ + /* case 0xCC: CZ addr */ CALL(ZF,"CZ"); } else { - /* case 0xCD: /* CALL addr */ + /* case 0xCD: CALL addr */ CALL(1,"CALL"); } } else { if(!(ins&0x01)) { - /* case 0xCE: /* ACI n */ + /* case 0xCE: ACI n */ INCPC; i=A; i+=INS; @@ -1730,7 +1730,7 @@ ins = INS; /* return; */ } else { - /* case 0xCF: /* RST 1 */ + /* case 0xCF: RST 1 */ RST(1); } } @@ -1742,21 +1742,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xD0: /* RNC */ + /* case 0xD0: RNC */ RETURN(!CF,"RNC"); } else { - /* case 0xD1: /* POP D */ + /* case 0xD1: POP D */ POP(DE,D,E,"D"); } } else { if(!(ins&0x01)) { - /* case 0xD2: /* JNC addr */ + /* case 0xD2: JNC addr */ JUMP(!CF,"JNC"); } else { - /* case 0xD3: /* OUT port */ + /* case 0xD3: OUT port */ INCPC; out(INS,A); INCPC; @@ -1768,17 +1768,17 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xD4: /* CNC addr */ + /* case 0xD4: CNC addr */ CALL(!CF,"CNC"); } else { - /* case 0xD5: /* PUSH D */ + /* case 0xD5: PUSH D */ PUSH(DE,D,E,"D"); } } else { if(!(ins&0x01)) { - /* case 0xD6: /* SUI n */ + /* case 0xD6: SUI n */ INCPC; i=A; i-=INS; @@ -1797,7 +1797,7 @@ ins = INS; /* return; */ } else { - /* case 0xD7: /* RST 2 */ + /* case 0xD7: RST 2 */ RST(2); } } @@ -1807,11 +1807,11 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xD8: /* RC */ + /* case 0xD8: RC */ RETURN(CF,"RC"); } else { - /* case 0xD9: /* SHLX */ + /* case 0xD9: SHLX */ INCPC; MEMSET(DE, L); MEMSET(DE+1, H); @@ -1821,11 +1821,11 @@ ins = INS; } else { if(!(ins&0x01)) { - /* case 0xDA: /* JC addr */ + /* case 0xDA: JC addr */ JUMP(CF,"JC"); } else { - /* case 0xDB: /* IN port */ + /* case 0xDB: IN port */ INCPC; A=inport(INS); INCPC; @@ -1836,18 +1836,18 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xDC: /* CC addr */ + /* case 0xDC: CC addr */ CALL(CF,"CC"); } else { - /* case 0xDD: /* JNX addr */ + /* case 0xDD: JNX addr */ JUMP(!XF,"JNX"); /* return; */ } } else { if(!(ins&0x01)) { - /* case 0xDE: /* SBI n */ + /* case 0xDE: SBI n */ INCPC; i=A; i-=INS; @@ -1867,7 +1867,7 @@ ins = INS; /* return; */ } else { - /* case 0xDF: /* RST 3 */ + /* case 0xDF: RST 3 */ RST(3); } } @@ -1881,21 +1881,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xE0: /* RPO */ + /* case 0xE0: RPO */ RETURN(!PF,"RPO"); } else { - /* case 0xE1: /* POP H */ + /* case 0xE1: POP H */ POP(HL,H,L,"H"); } } else { if(!(ins&0x01)) { - /* case 0xE2: /* JPO addr */ + /* case 0xE2: JPO addr */ JUMP(!PF,"JPO"); } else { - /* case 0xE3: /* XTHL */ + /* case 0xE3: XTHL */ INCPC; i=H; j=L; @@ -1913,17 +1913,17 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xE4: /* CPO addr */ + /* case 0xE4: CPO addr */ CALL(!PF,"CPO"); } else { - /* case 0xE5: /* PUSH H */ + /* case 0xE5: PUSH H */ PUSH(HL,H,L,"H"); } } else { if(!(ins&0x01)) { - /* case 0xE6: /* ANI n */ + /* case 0xE6: ANI n */ INCPC; A=A&INS; INCPC; @@ -1932,7 +1932,7 @@ ins = INS; /* return; */ } else { - /* case 0xE7: /* RST 4 */ + /* case 0xE7: RST 4 */ RST(4); } } @@ -1942,11 +1942,11 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xE8: /* RPE */ + /* case 0xE8: RPE */ RETURN(PF,"RPE"); } else { - /* case 0xE9: /* PCHL */ + /* case 0xE9: PCHL */ PCH=H; PCL=L; /* PC=HL; */ @@ -1956,11 +1956,11 @@ ins = INS; } else { if(!(ins&0x01)) { - /* case 0xEA: /* JPE addr */ + /* case 0xEA: JPE addr */ JUMP(PF,"JPE"); } else { - /* case 0xEB: /* XCHG */ + /* case 0xEB: XCHG */ INCPC; i=H; H=D; @@ -1979,11 +1979,11 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xEC: /* CPE addr */ + /* case 0xEC: CPE addr */ CALL(PF,"CPE"); } else { - /* case 0xED: /* LHLX */ + /* case 0xED: LHLX */ INCPC; L=MEM(DE); H=MEM(DE+1); @@ -1993,7 +1993,7 @@ ins = INS; } else { if(!(ins&0x01)) { - /* case 0xEE: /* XRI n */ + /* case 0xEE: XRI n */ INCPC; A=A^INS; INCPC; @@ -2002,7 +2002,7 @@ ins = INS; /* return; */ } else { - /* case 0xEF: /* RST 5 */ + /* case 0xEF: RST 5 */ RST(5); } } @@ -2014,21 +2014,21 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xF0: /* RP */ + /* case 0xF0: RP */ RETURN(!SF,"RP"); } else { - /* case 0xF1: /* POP PSW */ + /* case 0xF1: POP PSW */ POP(AF,A,F,"PSW"); } } else { if(!(ins&0x01)) { - /* case 0xF2: /* JP addr */ + /* case 0xF2: JP addr */ JUMP(!SF,"JP"); } else { - /* case 0xF3: /* DI */ + /* case 0xF3: DI */ INCPC; IM|=0x08; cycle_delta+=(4); @@ -2039,17 +2039,17 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xF4: /* CP addr */ + /* case 0xF4: CP addr */ CALL(!SF,"CP"); } else { - /* case 0xF5: /* PUSH PSW */ + /* case 0xF5: PUSH PSW */ PUSH(AF,A,F,"PSW"); } } else { if(!(ins&0x01)) { - /* case 0xF6: /* ORI n */ + /* case 0xF6: ORI n */ INCPC; A=A|INS; INCPC; @@ -2058,7 +2058,7 @@ ins = INS; /* return; */ } else { - /* case 0xF7: /* RST 6 */ + /* case 0xF7: RST 6 */ RST(6); } } @@ -2068,11 +2068,11 @@ ins = INS; if(!(ins&0x04)) { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xF8: /* RM */ + /* case 0xF8: RM */ RETURN(SF,"RM"); } else { - /* case 0xF9: /* SPHL */ + /* case 0xF9: SPHL */ INCPC; SPH=H; SPL=L; @@ -2082,11 +2082,11 @@ ins = INS; } else { if(!(ins&0x01)) { - /* case 0xFA: /* JM addr */ + /* case 0xFA: JM addr */ JUMP(SF,"JM"); } else { - /* case 0xFB: /* EI */ + /* case 0xFB: EI */ INCPC; IM&=0xF7; cycle_delta+=(4); @@ -2097,18 +2097,18 @@ ins = INS; else { if(!(ins&0x02)) { if(!(ins&0x01)) { - /* case 0xFC: /* CM addr */ + /* case 0xFC: CM addr */ CALL(SF,"CM"); } else { - /* case 0xFD: /* JX addr */ + /* case 0xFD: JX addr */ JUMP(XF,"JX"); /* return; */ } } else { if(!(ins&0x01)) { - /* case 0xFE: /* CPI n */ + /* case 0xFE: CPI n */ INCPC; i=A; i-=INS; @@ -2127,7 +2127,7 @@ ins = INS; /* return; */ } else { - /* case 0xFF: /* RST 7 */ + /* case 0xFF: RST 7 */ RST(7); } } diff --git a/src/file.cpp b/src/file.cpp index 37dfe9d..cd3bdf0 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -171,10 +171,10 @@ void cb_LoadOptRom (Fl_Widget* w, void*) } -char *gIllformedBasic = "Ill formed BASIC file"; -static char *gTooLargeMsg = "File too large for available memory"; +const char *gIllformedBasic = "Ill formed BASIC file"; +static const char *gTooLargeMsg = "File too large for available memory"; -char *gKeywordTable[] = { +const char *gKeywordTable[] = { "END", "FOR", "NEXT", "DATA", "INPUT", "DIM", "READ", "LET", "GOTO", "RUN", "IF", "RESTORE", "GOSUB", "RETURN", "REM", "STOP", "WIDTH", "ELSE", "LINE", "EDIT", "ERROR", "RESUME", "OUT", "ON", diff --git a/src/fileprint.cpp b/src/fileprint.cpp index c9aa0d3..5253d95 100644 --- a/src/fileprint.cpp +++ b/src/fileprint.cpp @@ -561,7 +561,7 @@ int VTFilePrint::OpenSession(void) else { filename = m_DirName; - filename += "lpt_out.txt"; + filename += (char *) "lpt_out.txt"; } // Check if Prompt is enabled diff --git a/src/flu_pixmaps.cpp b/src/flu_pixmaps.cpp index 2834ce1..2f568a6 100644 --- a/src/flu_pixmaps.cpp +++ b/src/flu_pixmaps.cpp @@ -16,7 +16,7 @@ #include "FLU/flu_pixmaps.h" /* XPM */ -char * plus_xpm[] = { +const char * plus_xpm[] = { "15 15 4 1", " c None", ". c #444444", @@ -39,7 +39,7 @@ char * plus_xpm[] = { " "}; /* XPM */ -char * minus_xpm[] = { +const char * minus_xpm[] = { "15 15 4 1", " c None", ". c #444444", @@ -62,7 +62,7 @@ char * minus_xpm[] = { " "}; /* XPM */ -char * folder_save_xpm[] = { +const char * folder_save_xpm[] = { "20 20 180 2", " c None", ". c #000000", @@ -266,7 +266,7 @@ char * folder_save_xpm[] = { " "}; /* XPM */ -char * folder_load_xpm[] = { +const char * folder_load_xpm[] = { "20 20 42 1", " c None", ". c #000000", @@ -332,7 +332,7 @@ char * folder_load_xpm[] = { " "}; /* XPM */ -char * reload_xpm[] = { +const char * reload_xpm[] = { "20 20 41 1", " c None", ". c #777777", @@ -397,7 +397,7 @@ char * reload_xpm[] = { " .++++++. "}; /* XPM */ -char * home_xpm[] = { +const char * home_xpm[] = { "20 20 46 1", " c None", ". c #000000", @@ -467,7 +467,7 @@ char * home_xpm[] = { " "}; /* XPM */ -char * trash_xpm[] = { +const char * trash_xpm[] = { "20 20 8 1", " c None", ". c #000000", @@ -499,7 +499,7 @@ char * trash_xpm[] = { " ........ "}; /* XPM */ -char * arrow_closed_xpm[] = { +const char * arrow_closed_xpm[] = { "15 15 3 1", " c None", ". c #FFFFFF", @@ -521,7 +521,7 @@ char * arrow_closed_xpm[] = { " "}; /* XPM */ -char * arrow_open_xpm[] = { +const char * arrow_open_xpm[] = { "15 15 3 1", " c None", ". c #FFFFFF", @@ -543,7 +543,7 @@ char * arrow_open_xpm[] = { " "}; /* XPM */ -char * bluedot_xpm[] = { +const char * bluedot_xpm[] = { "13 13 9 1", " c None", ". c #D4D4FF", @@ -569,7 +569,7 @@ char * bluedot_xpm[] = { " "}; /* XPM */ -char * book_xpm[] = { +const char * book_xpm[] = { "18 18 15 1", " c None", ". c #840084", @@ -606,7 +606,7 @@ char * book_xpm[] = { " "}; /* XPM */ -char * cd_drive_xpm[] = { +const char * cd_drive_xpm[] = { "18 16 29 1", " c None", ". c #737373", @@ -655,7 +655,7 @@ char * cd_drive_xpm[] = { " "}; /* XPM */ -char * computer_xpm[] = { +const char * computer_xpm[] = { "20 20 47 1", " c None", ". c #FFFFFF", @@ -726,7 +726,7 @@ char * computer_xpm[] = { " "}; /* XPM */ -char * ram_drive_xpm[] = { +const char * ram_drive_xpm[] = { "18 16 14 1", " c None", ". c #444444", @@ -760,7 +760,7 @@ char * ram_drive_xpm[] = { " "}; /* XPM */ -char * network_drive_xpm[] = { +const char * network_drive_xpm[] = { "18 16 15 1", " c None", ". c #A80525", @@ -795,7 +795,7 @@ char * network_drive_xpm[] = { " "}; /* XPM */ -char * floppy_drive_xpm[] = { +const char * floppy_drive_xpm[] = { "18 16 12 1", " c None", ". c #858585", @@ -827,7 +827,7 @@ char * floppy_drive_xpm[] = { " ############ "}; /* XPM */ -char * removable_drive_xpm[] = { +const char * removable_drive_xpm[] = { "20 12 12 1", " c None", ". c #858585", @@ -855,7 +855,7 @@ char * removable_drive_xpm[] = { " "}; /* XPM */ -char * disk_drive_xpm[] = { +const char * disk_drive_xpm[] = { "20 12 12 1", " c None", ". c #737373", @@ -883,7 +883,7 @@ char * disk_drive_xpm[] = { " "}; /* XPM */ -char * filled_folder_xpm[] = { +const char * filled_folder_xpm[] = { "18 18 18 1", " c None", ". c #63639C", @@ -923,7 +923,7 @@ char * filled_folder_xpm[] = { " "}; /* XPM */ -char * folder_up_xpm[] = { +const char * folder_up_xpm[] = { "20 18 8 1", " c None", ". c #9C9C00", @@ -953,7 +953,7 @@ char * folder_up_xpm[] = { " "}; /* XPM */ -char * folder_closed_xpm[] = { +const char * folder_closed_xpm[] = { "20 16 44 1", " c None", ". c #A68A5E", @@ -1064,7 +1064,7 @@ char * folder_closed_xpm[] = { " "}; */ -char * folder_open_xpm[] = { +const char * folder_open_xpm[] = { "20 16 34 1", " c None", ". c #A68A5E", @@ -1179,7 +1179,7 @@ char * folder_open_xpm[] = { */ /* XPM */ -char * greendot_xpm[] = { +const char * greendot_xpm[] = { "13 13 9 1", " c None", ". c #D4FFD4", @@ -1205,7 +1205,7 @@ char * greendot_xpm[] = { " "}; /* XPM */ -char * purpledot_xpm[] = { +const char * purpledot_xpm[] = { "13 13 9 1", " c None", ". c #FFD4FF", @@ -1230,7 +1230,7 @@ char * purpledot_xpm[] = { " .+@#@+. ", " "}; /* XPM */ -char * question_book_xpm[] = { +const char * question_book_xpm[] = { "18 18 19 1", " c None", ". c #840084", @@ -1270,7 +1270,7 @@ char * question_book_xpm[] = { " $+ ", " "}; /* XPM */ -char * reddot_xpm[] = { +const char * reddot_xpm[] = { "13 13 9 1", " c None", ". c #FFD4D4", @@ -1295,7 +1295,7 @@ char * reddot_xpm[] = { " .+@#@+. ", " "}; /* XPM */ -char * tealdot_xpm[] = { +const char * tealdot_xpm[] = { "13 13 9 1", " c None", ". c #D4FFFF", @@ -1320,7 +1320,7 @@ char * tealdot_xpm[] = { " .+@#@+. ", " "}; /* XPM */ -char * textdoc_xpm[] = { +const char * textdoc_xpm[] = { "15 18 5 1", " c None", ". c #848484", @@ -1347,7 +1347,7 @@ char * textdoc_xpm[] = { " "}; /* XPM */ -char * yellowdot_xpm[] = { +const char * yellowdot_xpm[] = { "13 13 9 1", " c None", ". c #FFFFD4", @@ -1373,7 +1373,7 @@ char * yellowdot_xpm[] = { " "}; /* XPM */ -char * cdrom_xpm[] = { +const char * cdrom_xpm[] = { "22 22 39 1", " c None", ". c #ADADAD", @@ -1438,7 +1438,7 @@ char * cdrom_xpm[] = { " "}; /* XPM */ -char * big_folder_new_xpm[] = { +const char * big_folder_new_xpm[] = { "20 20 73 1", " c None", ". c #000000", @@ -1535,7 +1535,7 @@ char * big_folder_new_xpm[] = { " "}; /* XPM */ -char * big_folder_up_xpm[] = { +const char * big_folder_up_xpm[] = { "20 20 70 1", " c None", ". c #474747", diff --git a/src/ide.cpp b/src/ide.cpp index d13e6b1..73f87c0 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -1412,7 +1412,7 @@ void VT_Ide::NewProject(void) // Check if path ends with '/' if (m_ActivePrj->m_RootPath[m_ActivePrj->m_RootPath.GetLength()-1] != '/') - m_ActivePrj->m_RootPath = m_ActivePrj->m_RootPath + "/"; + m_ActivePrj->m_RootPath = m_ActivePrj->m_RootPath + (char *) "/"; m_ActivePrj->m_RootPath = m_ActivePrj->m_RootPath + m_ActivePrj->m_Name; @@ -1651,7 +1651,7 @@ void VT_Ide::BuildTreeControl(void) // Set the Root name temp = m_ActivePrj->m_Name; - temp += " files"; + temp += (char *) " files"; m_ProjTree->label( temp ); n = m_ProjTree->get_root(); @@ -1672,7 +1672,7 @@ void VT_Ide::BuildTreeControl(void) // Object is a group add node to tree pGroup = (VT_IdeGroup *) pObj; addStr.Format(fmt, (const char *) pGroup->m_Name); - addStr += "/"; + addStr += (char *) "/"; n = m_ProjTree->add(addStr); if (n) { @@ -1680,7 +1680,7 @@ void VT_Ide::BuildTreeControl(void) pGroup->m_Node = n; } - addStr += "%s"; + addStr += (char *) "%s"; // Loop through all objects and add to tree int sublen = pGroup->m_Objects.GetSize(); @@ -1696,7 +1696,7 @@ void VT_Ide::BuildTreeControl(void) pSource = (VT_IdeSource *) pObj; // Get just the filename - int index = pSource->m_Name.ReverseFind("/"); + int index = pSource->m_Name.ReverseFind((char *) "/"); if (index == 0) temp = pSource->m_Name; else @@ -1739,7 +1739,7 @@ void VT_Ide::AddGroupToTree(VTObject *pObj, const char *fmt) // Object is a group add node to tree pGroup = (VT_IdeGroup *) pObj; addStr.Format(fmt, (const char *) pGroup->m_Name); - addStr += "/"; + addStr += (char *) "/"; n = m_ProjTree->add(addStr); if (n) { @@ -1747,7 +1747,7 @@ void VT_Ide::AddGroupToTree(VTObject *pObj, const char *fmt) pGroup->m_Node = n; } - addStr += "%s"; + addStr += (char *) "%s"; // Loop through all objects and add to tree len = pGroup->m_Objects.GetSize(); @@ -1763,7 +1763,7 @@ void VT_Ide::AddGroupToTree(VTObject *pObj, const char *fmt) pSource = (VT_IdeSource *) pObj; // Get just the filename - int index = pSource->m_Name.ReverseFind("/"); + int index = pSource->m_Name.ReverseFind((char *) "/"); if (index == 0) temp = pSource->m_Name; else @@ -1832,7 +1832,7 @@ int VT_Ide::ParsePrjFile(const char *name) else { line[c] = 0; - value = ""; + value = (char *) ""; } // Check for error in line @@ -2008,7 +2008,7 @@ int VT_Ide::ParsePrjFile(const char *name) // Set the RootPath temp = name; // Get just the path - index = temp.ReverseFind("/"); + index = temp.ReverseFind((char *) "/"); if (index == 0) m_ActivePrj->m_RootPath = path; else @@ -2212,7 +2212,7 @@ void VT_Ide::NewFolder(Flu_Tree_Browser::Node* n) pNewGrp->m_Filespec = filespec; // Convert name to a branch - name += "/"; + name += (char *) "/"; // Test if inserting at root if (n == 0) @@ -2634,7 +2634,7 @@ MString VT_Ide::MakePathRelative(const MString& path, const MString& relTo) // Determine if path is already relative if ((path.Left(2) == "./") || (path.Left(3) == "../")) return path; - if (path.Find("/", 0) == -1) + if (path.Find((char *) "/", 0) == -1) return path; if (path[1] == ':') slashIndex = 2; @@ -2671,13 +2671,13 @@ MString VT_Ide::MakePathRelative(const MString& path, const MString& relTo) { if (c == lastRelBranch) { - temp += "../"; // Add another 'prev dir' indicator + temp += (char *) "../"; // Add another 'prev dir' indicator break; // At last branch...exit } // Check for a directory specifier if (relTo[c] == '/') { - temp += "../"; + temp += (char *) "../"; } c++; } diff --git a/src/lpt.cpp b/src/lpt.cpp index 17fce58..919e637 100644 --- a/src/lpt.cpp +++ b/src/lpt.cpp @@ -71,7 +71,7 @@ typedef struct } lptCtrl_t; // Define a Printer bitmap -char* print_xpm[] = { +const char* print_xpm[] = { "18 18 14 1", " c None", ". c #555555", @@ -109,7 +109,7 @@ char* print_xpm[] = { // Define a Cancel Printer bitmap -char* cancel_print_xpm[] = { +const char* cancel_print_xpm[] = { "18 18 15 1", " c None", ". c #555555", @@ -147,7 +147,7 @@ char* cancel_print_xpm[] = { }; // Define a Printer Error bitmap -char* error_print_xpm[] = { +const char* error_print_xpm[] = { "18 18 15 1", " c None", ". c #555555", @@ -185,7 +185,7 @@ char* error_print_xpm[] = { }; // Define a Printer bitmap -char* print_xpm2[] = { +const char* print_xpm2[] = { "18 18 14 1", " c None", ". c #555555", @@ -222,7 +222,7 @@ char* print_xpm2[] = { }; // Define a Printer bitmap -char* print_xpm3[] = { +const char* print_xpm3[] = { "18 18 15 1", " c None", ". c #555555", @@ -260,7 +260,7 @@ char* print_xpm3[] = { }; // Define a Printer bitmap -char* print_xpm4[] = { +const char* print_xpm4[] = { "18 18 15 1", " c None", ". c #555555", @@ -298,7 +298,7 @@ char* print_xpm4[] = { }; // Define a Printer bitmap -char* print_xpm5[] = { +const char* print_xpm5[] = { "18 18 14 1", " c None", ". c #555555", @@ -336,7 +336,7 @@ char* print_xpm5[] = { // Define a Printer bitmap -char* print_xpm6[] = { +const char* print_xpm6[] = { "18 18 14 1", " c None", ". c #555555", diff --git a/src/m100emu.c b/src/m100emu.c index a2f59f8..cc91d93 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -667,7 +667,6 @@ This routine processes CPU interrupts. __inline void check_interrupts(void) { static UINT64 last_rst75=0; - static DWORD last_rst_ms = 0; if (((last_rst75 + rst7cycles) < cycles) && !INTDIS) { @@ -889,8 +888,6 @@ void emulate(void) { unsigned int i,j; unsigned int v; - int top=0; -//har *p; int nxtmaint=1; int ins; @@ -1098,14 +1095,16 @@ is done by looking at the argv[0] argument and removing the app name. void setup_working_path(char **argv) { #if defined(__unix__) || defined(__APPLE__) - int i, found; + int i; + +#if defined(__APPLE__) + int found; char temp[512]; struct stat romStat; getcwd(path, sizeof(path)); //J. VERNET: Get Absolute Path, as getcwd doesn't return anything when launch from finder -#if defined(__APPLE__) found = FALSE; /* Recursively search up the path until we find the ROMs directory */ diff --git a/src/memory.c b/src/memory.c index 0acd6b4..2b5e1f3 100644 --- a/src/memory.c +++ b/src/memory.c @@ -709,7 +709,7 @@ void save_remem_ram(void) /* Check if file opened successfully */ if (fd != 0) { - size = 1024 * 2048; /* Copy 2 meg of RAM & FLASH + size = 1024 * 2048; /* Copy 2 meg of RAM & FLASH */ /* Write ReMem RAM first */ fwrite(gReMemRam, 1, size, fd); @@ -740,7 +740,7 @@ void save_rampac_ram(void) /* Check if file opened successfully */ if (fd != 0) { - size = 1024 * 256; /* Copy 256 K of RAM + size = 1024 * 256; /* Copy 256 K of RAM */ /* Write ReMem RAM first */ fwrite(gRampacRam, 1, size, fd); @@ -856,7 +856,7 @@ void load_remem_ram(void) /* Check if file opened successfully */ if (fd != 0) { - size = 1024 * 2048; /* Copy 2 meg of RAM & FLASH + size = 1024 * 2048; /* Copy 2 meg of RAM & FLASH */ /* Read ReMem RAM first */ fread(gReMemRam, 1, size, fd); @@ -918,7 +918,7 @@ void load_rampac_ram(void) /* Check if file opened successfully */ if (fd != 0) { - size = 1024 * 256; /* Copy 256 K of RAM + size = 1024 * 256; /* Copy 256 K of RAM */ /* Write ReMem RAM first */ fread(gRampacRam, 1, size, fd); @@ -1350,7 +1350,7 @@ void set_rom_bank(unsigned char bank) // Save any writes to OptROM space if ((gOptRomRW) && (gRomBank == 2)) - memcpy(gOptROM, gBaseMemory, ROMSIZE); + memcpy(gOptROM, gBaseMemory, OPTROMSIZE); // Save ROM bank gRomBank = bank; diff --git a/src/multiwin_icons.cpp b/src/multiwin_icons.cpp index 8d2fe74..1754cf0 100644 --- a/src/multiwin_icons.cpp +++ b/src/multiwin_icons.cpp @@ -32,7 +32,7 @@ #include /* XPM */ -char * gMultiWinDoc_xpm[] = { +const char * gMultiWinDoc_xpm[] = { "15 18 5 1", " c None", ". c #848484", @@ -59,7 +59,7 @@ char * gMultiWinDoc_xpm[] = { " "}; /* XPM */ -char * gCloseBox[] = { +const char * gCloseBox[] = { "20 19 4 1", " c None", ". c #FF0000", @@ -85,7 +85,7 @@ char * gCloseBox[] = { " ++++++++++++++++ ", " "}; -char * gCloseBoxSelected[] = { +const char * gCloseBoxSelected[] = { "20 19 5 1", " c None", ". c #A00000", @@ -112,7 +112,7 @@ char * gCloseBoxSelected[] = { " ++++++++++++++++ ", " "}; -char * gCloseBoxInactive[] = { +const char * gCloseBoxInactive[] = { "20 19 4 1", " c None", ". c #FF8080", @@ -138,7 +138,7 @@ char * gCloseBoxInactive[] = { " ++++++++++++++++ ", " "}; -char * gMinimizeBox[] = { +const char * gMinimizeBox[] = { "20 19 4 1", " c None", ". c #0000FF", @@ -163,7 +163,7 @@ char * gMinimizeBox[] = { " +................+ ", " ++++++++++++++++ ", " "}; -char * gMinimizeBoxSelected[] = { +const char * gMinimizeBoxSelected[] = { "20 19 4 1", " c None", ". c #0000A0", @@ -189,7 +189,7 @@ char * gMinimizeBoxSelected[] = { " ++++++++++++++++ ", " "}; -char * gMinimizeBoxInactive[] = { +const char * gMinimizeBoxInactive[] = { "20 19 4 1", " c None", ". c #8080FF", @@ -215,7 +215,7 @@ char * gMinimizeBoxInactive[] = { " ++++++++++++++++ ", " "}; -char * gMaximizeBox[] = { +const char * gMaximizeBox[] = { "20 19 4 1", " c None", ". c #0000FF", @@ -241,7 +241,7 @@ char * gMaximizeBox[] = { " ++++++++++++++++ ", " "}; -char * gMaximizeBoxSelected[] = { +const char * gMaximizeBoxSelected[] = { "20 19 4 1", " c None", ". c #0000A0", @@ -267,7 +267,7 @@ char * gMaximizeBoxSelected[] = { " ++++++++++++++++ ", " "}; -char * gMaximizeBoxInactive[] = { +const char * gMaximizeBoxInactive[] = { "20 19 4 1", " c None", ". c #8080FF", @@ -293,7 +293,7 @@ char * gMaximizeBoxInactive[] = { " ++++++++++++++++ ", " "}; -char * gRestoreBox[] = { +const char * gRestoreBox[] = { "20 19 4 1", " c None", ". c #0000FF", @@ -319,7 +319,7 @@ char * gRestoreBox[] = { " ++++++++++++++++ ", " "}; -char * gRestoreBoxSelected[] = { +const char * gRestoreBoxSelected[] = { "20 19 4 1", " c None", ". c #0000A0", @@ -345,7 +345,7 @@ char * gRestoreBoxSelected[] = { " ++++++++++++++++ ", " "}; -char * gRestoreBoxInactive[] = { +const char * gRestoreBoxInactive[] = { "20 19 4 1", " c None", ". c #8080FF", diff --git a/src/project.cpp b/src/project.cpp index f990d21..61a430e 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -736,53 +736,53 @@ VT_Project implementation routines. void VT_Project::AsmDebugInfo(int enable) { if (enable) - AddAsmOption("-g"); + AddAsmOption((char *) "-g"); else - RemoveAsmOption("-g"); + RemoveAsmOption((char *) "-g"); } int VT_Project::AsmDebugInfo(void) const { - return m_AsmOptions.Find("-g", 0) != -1; + return m_AsmOptions.Find((char *) "-g", 0) != -1; } void VT_Project::AsmListing(int enable) { if (enable) - AddAsmOption("-l"); + AddAsmOption((char *) "-l"); else - RemoveAsmOption("-l"); + RemoveAsmOption((char *) "-l"); } int VT_Project::AsmListing(void) const { - return m_AsmOptions.Find("-l", 0) != -1; + return m_AsmOptions.Find((char *) "-l", 0) != -1; } void VT_Project::BrowseInfo(int enable) { if (enable) - AddAsmOption("-b"); + AddAsmOption((char *) "-b"); else - RemoveAsmOption("-b"); + RemoveAsmOption((char *) "-b"); } int VT_Project::BrowseInfo(void) const { - return m_AsmOptions.Find("-b", 0) != -1; + return m_AsmOptions.Find((char *) "-b", 0) != -1; } void VT_Project::AutoExtern(int enable) { if (enable) - AddAsmOption("-e"); + AddAsmOption((char *) "-e"); else - RemoveAsmOption("-e"); + RemoveAsmOption((char *) "-e"); } int VT_Project::AutoExtern(void) const { - return m_AsmOptions.Find("-e", 0) != -1; + return m_AsmOptions.Find((char *) "-e", 0) != -1; } void VT_Project::AddAsmOption(char* pOpt) @@ -795,7 +795,7 @@ void VT_Project::AddAsmOption(char* pOpt) return; // Append option to end of the m_AsmOptions string - m_AsmOptions = m_AsmOptions + " " + pOpt; + m_AsmOptions = m_AsmOptions + (char *) " " + pOpt; } void VT_Project::RemoveAsmOption(char* pOpt) @@ -828,7 +828,7 @@ void VT_Project::AddLinkOption(char* pOpt) return; // Append option to end of the m_AsmOptions string - m_LinkOptions = m_LinkOptions + " " + pOpt; + m_LinkOptions = m_LinkOptions + (char *) " " + pOpt; } void VT_Project::RemoveLinkOption(char* pOpt) @@ -854,39 +854,39 @@ void VT_Project::RemoveLinkOption(char* pOpt) void VT_Project::LinkDebugInfo(int enable) { if (enable) - AddLinkOption("-g"); + AddLinkOption((char *) "-g"); else - RemoveLinkOption("-g"); + RemoveLinkOption((char *) "-g"); } int VT_Project::LinkDebugInfo(void) const { - return m_LinkOptions.Find("-g", 0) != -1; + return m_LinkOptions.Find((char *) "-g", 0) != -1; } void VT_Project::MapFile(int enable) { if (enable) - AddLinkOption("-m"); + AddLinkOption((char *) "-m"); else - RemoveLinkOption("-m"); + RemoveLinkOption((char *) "-m"); } int VT_Project::MapFile(void) const { - return m_LinkOptions.Find("-m", 0) != -1; + return m_LinkOptions.Find((char *) "-m", 0) != -1; } void VT_Project::IgnoreStdLibs(int enable) { if (enable) - AddLinkOption("-i"); + AddLinkOption((char *) "-i"); else - RemoveLinkOption("-i"); + RemoveLinkOption((char *) "-i"); } int VT_Project::IgnoreStdLibs(void) const { - return m_LinkOptions.Find("-i", 0) != -1; + return m_LinkOptions.Find((char *) "-i", 0) != -1; } diff --git a/src/serial.c b/src/serial.c index c5fd49e..7256e08 100644 --- a/src/serial.c +++ b/src/serial.c @@ -755,7 +755,7 @@ int ser_close_port(void) int my_fd = sp.fd; sp.fd = 0; - close (sp.fd); + close (my_fd); #endif } @@ -1249,7 +1249,9 @@ ser_get_flags: Get serial port's flags int ser_get_flags(unsigned char *flags) { +#ifdef WIN32 long modem_status; +#endif if ((setup.com_mode == SETUP_COM_HOST) || (setup.com_mode == SETUP_COM_OTHER)) @@ -1375,7 +1377,9 @@ ser_get_signals: Get serial port's CTS, RTS, DTR, and DSR signals int ser_get_signals(unsigned char *flags) { +#ifdef WIN32 long modem_status; +#endif if ((setup.com_mode == SETUP_COM_HOST) || (setup.com_mode == SETUP_COM_OTHER)) @@ -1550,7 +1554,8 @@ int ser_write_byte(char data) // Trigger the thread to write the byte SetEvent(sp.hWriteEvent); #else - write (sp.fd, &data, 1); + if (write (sp.fd, &data, 1) <= 0) + return SER_IO_ERROR; #endif } @@ -1586,6 +1591,7 @@ int ser_poll () if (bytes && sp.pCallback) { sp.pCallback(); } + return 0; #else return 0; diff --git a/src/setup.cpp b/src/setup.cpp index 60d950a..2e62360 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -289,7 +289,7 @@ void cb_setup_OK(Fl_Widget* w, void*) if (setup_ctrl.com.pNone->value() == 1) { - ser_set_port("No Emulation"); + ser_set_port((char *) "No Emulation"); setup.com_mode = SETUP_COM_NONE; } else if (setup_ctrl.com.pSim->value() == 1) diff --git a/src/vtpaper.cpp b/src/vtpaper.cpp index 344679f..0f8aabe 100644 --- a/src/vtpaper.cpp +++ b/src/vtpaper.cpp @@ -1526,7 +1526,7 @@ int VTlprPaper::Print(void) // Test if stderr redirection is part of cmd line if (strstr((const char *) cmd, "2>&1") == NULL) - cmd += " 2>&1"; + cmd += (char *) " 2>&1"; // Now spool the job //if (fork() == 0) From 68a74264982ee0c03577cedd46e3d4e839d403fe Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 31 Oct 2010 05:42:58 +0000 Subject: [PATCH 177/327] Fixed improperly placed #ifdef causing getcwd to be skipped in Linux. --- GNUmakefile | 4 ++-- src/m100emu.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index f58875e..a12ca65 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -12,8 +12,8 @@ -include $(shell uname).mk -CFLAGS += -I $(FLTKDIR) -I src/FLU -CPPFLAGS += -I $(FLTKDIR) +CFLAGS += -I $(FLTKDIR) -I src/FLU -g +CPPFLAGS += -I $(FLTKDIR) -g EXECUTABLE = virtualt CLIENT = vt_client diff --git a/src/m100emu.c b/src/m100emu.c index cc91d93..a87918b 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -1101,10 +1101,12 @@ void setup_working_path(char **argv) int found; char temp[512]; struct stat romStat; +#endif getcwd(path, sizeof(path)); //J. VERNET: Get Absolute Path, as getcwd doesn't return anything when launch from finder +#if defined(__APPLE__) found = FALSE; /* Recursively search up the path until we find the ROMs directory */ From c99173f44c6903d1f77386750e0f4ccd37a7579d Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 9 Jul 2011 08:16:21 +0000 Subject: [PATCH 178/327] Checkin of Version 1.5 with MANY changes and additions, such as new File Open Dialog boxes (may not work on OSX), linker (90% done), setting display colors and processing mouse clicks in the main window, crude sound implementation, REX emulation, Assembler / IDE updates, Working Assembler (needs documentation). --- GNUmakefile | 28 +- VirtualT.sln | 16 +- VirtualT.suo | Bin 151040 -> 352768 bytes VirtualT.vcproj | 192 +- release.txt | 7 + src/FLU/Flu_Button.h | 91 + src/FLU/Flu_Combo_Box.h | 117 + src/FLU/Flu_Combo_List.h | 50 + src/FLU/Flu_Combo_Tree.h | 49 + src/FLU/Flu_File_Chooser.h | 529 ++ src/FLU/Flu_Label.h | 61 + src/FLU/Flu_Return_Button.h | 34 + src/FLU/Flu_Separator.h | 55 + src/FLU/Flu_Tree_Browser.h | 11 +- src/FLU/Flu_Wrap_Group.h | 177 + src/FLU/VectorClass.h | 102 + src/FLU/flu_file_chooser_pixmaps.h | 35 + src/Flu_Button.cpp | 191 + src/Flu_Combo_Box.cpp | 252 + src/Flu_Combo_List.cpp | 75 + src/Flu_Combo_Tree.cpp | 96 + src/Flu_File_Chooser.cpp | 3644 +++++++++ src/Flu_Label.cpp | 50 + src/Flu_Return_Button.cpp | 26 + src/Flu_Separator.cpp | 31 + src/Flu_Tree_Browser.cpp | 91 +- src/Flu_Wrap_Group.cpp | 284 + src/MString.h | 4 +- src/My_Text_Display.cpp | 3120 ++++++++ src/My_Text_Display.h | 297 + src/My_Text_Editor.cpp | 607 ++ src/My_Text_Editor.h | 128 + src/VirtualT.h | 2 +- src/a85parse.cpp | 10806 ++++++++++++++------------- src/a85parse.h | 75 +- src/a85parse.syn | 710 +- src/assemble.cpp | 2971 ++++++-- src/assemble.h | 202 +- src/autofile.cpp | 8 +- src/chargen.cpp | 22 +- src/clock.cpp | 5 +- src/clock.h | 2 +- src/cpu.h | 2 +- src/disassemble.cpp | 7 +- src/display.cpp | 1964 ++++- src/display.h | 48 + src/elf.h | 137 +- src/file.cpp | 91 +- src/fileprint.cpp | 8 +- src/fileview.cpp | 21 +- src/fl_action_icon.cpp | 6 +- src/flu_file_chooser_pixmaps.cpp | 2470 ++++++ src/fx80print.cpp | 15 +- src/highlight.cpp | 744 ++ src/highlight.h | 75 + src/ide.cpp | 1565 +++- src/ide.h | 44 +- src/idetabs.cpp | 429 ++ src/idetabs.h | 59 + src/intelhex.c | 17 + src/intelhex.h | 2 +- src/io.c | 119 +- src/kc85rom.c | 2 + src/linker.cpp | 1501 ++++ src/linker.h | 237 + src/m100emu.c | 457 +- src/m100emu.h | 2 +- src/m100rom.c | 2 + src/m10rom.c | 2 + src/m200rom.c | 3 + src/memedit.cpp | 180 +- src/memedit.h | 1 + src/memory.c | 1260 +++- src/memory.h | 19 +- src/multieditwin.cpp | 174 +- src/multieditwin.h | 13 +- src/multiwin.cpp | 2 +- src/multiwin.h | 5 +- src/multiwin_icons.h | 2 +- src/n8201rom.c | 6 +- src/periph.cpp | 21 +- src/pref_form.cpp | 270 + src/pref_form.h | 67 + src/project.cpp | 320 +- src/project.h | 24 +- src/remote.cpp | 847 ++- src/remote.h | 45 + src/roms.h | 2 + src/rpn_eqn.cpp | 25 + src/rpn_eqn.h | 17 +- src/serial.c | 165 +- src/serial.h | 3 +- src/serversocket.cpp | 13 + src/serversocket.h | 3 + src/setup.cpp | 39 +- src/setup.h | 2 + src/socket.cpp | 27 + src/socket.h | 2 + src/socketdlg.cpp | 283 + src/sound.c | 618 +- src/tpddclient.cpp | 579 ++ src/tpddclient.h | 69 + src/vt_client_main.cpp | 59 +- src/vtobj.cpp | 51 +- src/vtobj.h | 8 + src/vtpaper.cpp | 24 +- 106 files changed, 32686 insertions(+), 7841 deletions(-) create mode 100644 src/FLU/Flu_Button.h create mode 100644 src/FLU/Flu_Combo_Box.h create mode 100644 src/FLU/Flu_Combo_List.h create mode 100644 src/FLU/Flu_Combo_Tree.h create mode 100644 src/FLU/Flu_File_Chooser.h create mode 100644 src/FLU/Flu_Label.h create mode 100644 src/FLU/Flu_Return_Button.h create mode 100644 src/FLU/Flu_Separator.h create mode 100644 src/FLU/Flu_Wrap_Group.h create mode 100644 src/FLU/VectorClass.h create mode 100644 src/FLU/flu_file_chooser_pixmaps.h create mode 100644 src/Flu_Button.cpp create mode 100644 src/Flu_Combo_Box.cpp create mode 100644 src/Flu_Combo_List.cpp create mode 100644 src/Flu_Combo_Tree.cpp create mode 100644 src/Flu_File_Chooser.cpp create mode 100644 src/Flu_Label.cpp create mode 100644 src/Flu_Return_Button.cpp create mode 100644 src/Flu_Separator.cpp create mode 100644 src/Flu_Wrap_Group.cpp create mode 100644 src/My_Text_Display.cpp create mode 100644 src/My_Text_Display.h create mode 100644 src/My_Text_Editor.cpp create mode 100644 src/My_Text_Editor.h create mode 100644 src/flu_file_chooser_pixmaps.cpp create mode 100644 src/highlight.cpp create mode 100644 src/highlight.h create mode 100644 src/idetabs.cpp create mode 100644 src/idetabs.h create mode 100644 src/linker.cpp create mode 100644 src/linker.h create mode 100644 src/pref_form.cpp create mode 100644 src/pref_form.h create mode 100644 src/socketdlg.cpp create mode 100644 src/tpddclient.cpp create mode 100644 src/tpddclient.h diff --git a/GNUmakefile b/GNUmakefile index a12ca65..656bf70 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -13,7 +13,7 @@ -include $(shell uname).mk CFLAGS += -I $(FLTKDIR) -I src/FLU -g -CPPFLAGS += -I $(FLTKDIR) -g +CPPFLAGS += -I $(FLTKDIR) -I src -g EXECUTABLE = virtualt CLIENT = vt_client @@ -32,6 +32,7 @@ OBJECTSCPP = $(SOURCESCPP:.cpp=.o) CLIENT_OBJS = $(CLIENT_SRC:.cpp=.o) OBJDIR = obj POSTBUILD = $(FLTKCONFIG) --post +FLTKLIBS = $(FLTKDIR)/lib # ============================= @@ -45,7 +46,12 @@ SOURCESCPP = display.cpp setup.cpp periph.cpp disassemble.cpp file.cpp memedit.c multiwin.cpp multiwin_icons.cpp project.cpp multieditwin.cpp rememcfg.cpp \ fl_usage_box.cpp remote.cpp socket.cpp serversocket.cpp lpt.cpp printer.cpp \ fileprint.cpp hostprint.cpp fx80print.cpp chargen.cpp fl_action_icon.cpp fx80rom.cpp \ - vtpaper.cpp autofile.cpp clock.cpp fileview.cpp + vtpaper.cpp autofile.cpp clock.cpp fileview.cpp Flu_Wrap_Group.cpp \ + Flu_Button.cpp Flu_Combo_Box.cpp Flu_Combo_List.cpp Flu_Combo_Tree.cpp Flu_File_Chooser.cpp \ + flu_file_chooser_pixmaps.cpp Flu_Label.cpp Flu_Return_Button.cpp Flu_Separator.cpp \ + highlight.cpp idetabs.cpp linker.cpp My_Text_Display.cpp My_Text_Editor.cpp \ + socketdlg.cpp tpddclient.cpp pref_form.cpp + CLIENT_SRC = clientsocket.cpp vt_client_main.cpp socket.cpp # =============================== @@ -56,7 +62,8 @@ all: virtualt vt_client # ======================== # Rule to build VirtualT # ======================== -$(EXECUTABLE): $(OBJECTS) $(OBJECTSCPP) +$(EXECUTABLE): $(OBJECTS) $(OBJECTSCPP) $(FLTKLIBS)/libfltk.a \ + $(FLTKLIBS)/libfltk_z.a $(FLTKLIBS)/libfltk_jpeg.a $(FLTKLIBS)/libfltk_png.a ifndef FLTKDIR @echo "FLTKDIR environment variable must be set first!" exit 1 @@ -121,6 +128,21 @@ else endif +# ========================================== +# Declare dependencies on FLTK libs +# ========================================== +$(FLTKLIBS)/libfltk.a: + $(MAKE) -C $(FLTKDIR) + +$(FLTKLIBS)/libfltk_z.a: + $(MAKE) -C $(FLTKDIR)/zlib + +$(FLTKLIBS)/libfltk_jpeg.a: + $(MAKE) -C $(FLTKDIR)/jpeg + +$(FLTKLIBS)/libfltk_png.a: + $(MAKE) -C $(FLTKDIR)/png + # ========================================== # Declare dependencies on header files below # ========================================== diff --git a/VirtualT.sln b/VirtualT.sln index 11be2c5..7f5f4d0 100644 --- a/VirtualT.sln +++ b/VirtualT.sln @@ -1,9 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VirtualT", "VirtualT.vcproj", "{823B96D9-CEF2-4B9D-8B90-A6F0DEC5B97A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vt_client", "vt_client_src\vt_client.vcproj", "{2EE29331-FFC1-46AF-96AB-AA0643DF918E}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VirtualT", "VirtualT.vcproj", "{4B62EF01-B8D4-4C99-BC7B-661B97684568}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -11,14 +9,10 @@ Global Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {823B96D9-CEF2-4B9D-8B90-A6F0DEC5B97A}.Debug|Win32.ActiveCfg = Debug|Win32 - {823B96D9-CEF2-4B9D-8B90-A6F0DEC5B97A}.Debug|Win32.Build.0 = Debug|Win32 - {823B96D9-CEF2-4B9D-8B90-A6F0DEC5B97A}.Release|Win32.ActiveCfg = Release|Win32 - {823B96D9-CEF2-4B9D-8B90-A6F0DEC5B97A}.Release|Win32.Build.0 = Release|Win32 - {2EE29331-FFC1-46AF-96AB-AA0643DF918E}.Debug|Win32.ActiveCfg = Debug|Win32 - {2EE29331-FFC1-46AF-96AB-AA0643DF918E}.Debug|Win32.Build.0 = Debug|Win32 - {2EE29331-FFC1-46AF-96AB-AA0643DF918E}.Release|Win32.ActiveCfg = Release|Win32 - {2EE29331-FFC1-46AF-96AB-AA0643DF918E}.Release|Win32.Build.0 = Release|Win32 + {4B62EF01-B8D4-4C99-BC7B-661B97684568}.Debug|Win32.ActiveCfg = Debug|Win32 + {4B62EF01-B8D4-4C99-BC7B-661B97684568}.Debug|Win32.Build.0 = Debug|Win32 + {4B62EF01-B8D4-4C99-BC7B-661B97684568}.Release|Win32.ActiveCfg = Release|Win32 + {4B62EF01-B8D4-4C99-BC7B-661B97684568}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/VirtualT.suo b/VirtualT.suo index f74589178fa77835b6803d79530c4ac6778a5b22..c657bb41ab296e79291749cd0be893ece6a1c85c 100644 GIT binary patch literal 352768 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 z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�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 diff --git a/VirtualT.vcproj b/VirtualT.vcproj index 0020c91..8f8ee0a 100644 --- a/VirtualT.vcproj +++ b/VirtualT.vcproj @@ -3,7 +3,7 @@ ProjectType="Visual C++" Version="8.00" Name="VirtualT" - ProjectGUID="{823B96D9-CEF2-4B9D-8B90-A6F0DEC5B97A}" + ProjectGUID="{4B62EF01-B8D4-4C99-BC7B-661B97684568}" > + + @@ -724,6 +728,10 @@ /> + + @@ -816,6 +824,22 @@ + + + + + + + + @@ -838,6 +862,18 @@ /> + + + + + + @@ -860,6 +896,14 @@ /> + + + + @@ -882,6 +926,10 @@ /> + + @@ -904,6 +952,10 @@ /> + + @@ -927,26 +979,12 @@ + + - - - - - - + + + + + + - - - - - - - - + + @@ -1223,6 +1255,22 @@ + + + + + + + + @@ -1235,14 +1283,34 @@ RelativePath="src\FLU\flu_export.h" > + + + + + + + + + + @@ -1252,7 +1320,11 @@ > + + + + + + @@ -1313,10 +1393,6 @@ Name="Resource Files" Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" > - - diff --git a/release.txt b/release.txt index 042cd19..500f110 100644 --- a/release.txt +++ b/release.txt @@ -44,6 +44,13 @@ v1.4 Not released yet where the first keystroke would sometimes be dropped. 11. Modified remote socket interface to support telnet character based transfer and line endings. + Added "-t" comand line option to enable telnet protocol. + +12. Modified MacOSX working directory detection and ROM installation to automatically detect + the location of the ROMs directory within path of the application bundle. + +13. Modified the MacOSX maintenance update timing to provide faster execution speed during + FLTK drawing updates to the LCD. diff --git a/src/FLU/Flu_Button.h b/src/FLU/Flu_Button.h new file mode 100644 index 0000000..2ef6171 --- /dev/null +++ b/src/FLU/Flu_Button.h @@ -0,0 +1,91 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#ifndef _FLU_BUTTON_H +#define _FLU_BUTTON_H + +#include +#include + +#include +#include +#include + +#include "FLU/flu_export.h" + +//! This class extends Fl_Button to make a more attractive alternative that hilights as the mouse enters/leaves and automatically grayscales any image for deactivation +class FLU_EXPORT Flu_Button : public Fl_Button +{ + public: + + //! Normal FLTK widget constructor + Flu_Button( int X,int Y,int W,int H,const char *l = 0 ); + + //! Default destructor + virtual ~Flu_Button(); + + //! Override of Fl_Widget::color() + inline void color( unsigned c ) + { col = (Fl_Color)c; Fl_Button::color(col); } + + //! Override of Fl_Widget::color() + inline Fl_Color color() const + { return col; } + + //! Override of Fl_Widget::selection_color() + inline void selection_color( unsigned c ) + { sCol = (Fl_Color)c; Fl_Button::selection_color(sCol); } + + //! Override of Fl_Widget::selection_color() + inline Fl_Color selection_color() const + { return sCol; } + + //! Set the box to use when the mouse is over the button. If this is \c FL_NO_BOX, then the regular box() is used + inline void enter_box( Fl_Boxtype b ) + { eBox = b; } + + //! Get the box to use when the mouse enters + inline Fl_Boxtype enter_box() const + { return eBox; } + + //! Override of Fl_Widget::image() + void image( Fl_Image *i ); + + //! Override of Fl_Widget::image() + inline void image( Fl_Image &i ) + { image( &i ); } + + //! Override of Fl_Button::handle() + int handle( int event ); + + // Override of Fl_Button::draw() + void draw(); + + protected: + + bool retBtn, linkBtn, overLink; + + private: + + void checkLink(); + int labelSize[4]; + bool hover; + Fl_Color col, sCol; + Fl_Image *inactiveImg; + Fl_Boxtype eBox; + +}; + +#endif diff --git a/src/FLU/Flu_Combo_Box.h b/src/FLU/Flu_Combo_Box.h new file mode 100644 index 0000000..cfad6ca --- /dev/null +++ b/src/FLU/Flu_Combo_Box.h @@ -0,0 +1,117 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#ifndef _FLU_COMBO_BOX_H +#define _FLU_COMBO_BOX_H + +#include +#include +#include + +#include "FLU/Flu_Enumerations.h" + +//! This is a generic base class for implementing widgets with combo-box-like behavior (i.e. a pulldown menu where the "input" area is editable +class FLU_EXPORT Flu_Combo_Box : public Fl_Group +{ + +public: + + //! Normal FLTK widget constructor + Flu_Combo_Box( int x, int y, int w, int h, const char *l = 0 ); + + //! Default destructor + ~Flu_Combo_Box(); + + //! Get whether the input field can be edited. Default is \c true + inline bool editable() const + { return (int)(!input.readonly()); } + + //! Set whether the input field can be edited. + inline void editable( bool b ) + { input.readonly( (int)(!b) ); } + + //! Get the string in the input field + inline const char* value() const + { return input.value(); } + + //! Set the string in the input field and the value of the popup box. + void value( const char *v ); + + //! Set the height of the popup box + inline void pop_height( int h ) + { popHeight = h; } + + //! Get the height of the popup box + inline int pop_height() + { return popHeight; } + + //! Override of Fl_Group::handle() + int handle( int ); + + //! Override of Fl_Group::resize() + void resize( int X, int Y, int W, int H ); + + //! Set the function that will be called when the input area is interacted with + inline void input_callback( void (*cb)(Fl_Widget*,void*), void* cbd = NULL ) + { _inputCB = cb; _inputCBD = cbd; } + + //! Publicly exposed input widget + Fl_Input input; + +protected: + + void (*_inputCB)(Fl_Widget*,void*); + void* _inputCBD; + + virtual bool _value( const char *v ) = 0; + virtual const char* _next() = 0; + virtual const char* _previous() = 0; + + void draw(); + + void selected( const char *v ); + + void set_combo_widget( Fl_Widget *w ); + + uchar _valbox; + bool _pushed, _popped; + Fl_Widget *_cbox; + int popHeight; + + static void input_cb( Fl_Widget*, void* v ); + + class FLU_EXPORT Popup : public Fl_Double_Window + { + + public: + + Popup( Flu_Combo_Box *b, Fl_Widget *c, int H ); + + ~Popup(); + + int handle( int event ); + + protected: + + Flu_Combo_Box *combo; + bool dragging; + const char* selected; + + }; + friend class Popup; + +}; + +#endif diff --git a/src/FLU/Flu_Combo_List.h b/src/FLU/Flu_Combo_List.h new file mode 100644 index 0000000..b6e6e0f --- /dev/null +++ b/src/FLU/Flu_Combo_List.h @@ -0,0 +1,50 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#ifndef _FLU_COMBO_LIST_H +#define _FLU_COMBO_LIST_H + +#include + +#include "FLU/Flu_Combo_Box.h" + +//! Just like the Fl_Choice widget except the input area is editable +class FLU_EXPORT Flu_Combo_List : public Flu_Combo_Box +{ + +public: + + //! Normal FLTK widget constructor + Flu_Combo_List( int x, int y, int w, int h, const char *l = 0 ); + + //! Default destructor + ~Flu_Combo_List(); + + //! Publicly exposed list widget (instance of Fl_Hold_Browser) + Fl_Hold_Browser list; + + protected: + + bool _value( const char *v ); + const char* _next(); + const char* _previous(); + + inline static void _cb( Fl_Widget *w, void *arg ) + { ((Flu_Combo_List*)arg)->cb(); } + void cb(); + +}; + +#endif diff --git a/src/FLU/Flu_Combo_Tree.h b/src/FLU/Flu_Combo_Tree.h new file mode 100644 index 0000000..a0370b9 --- /dev/null +++ b/src/FLU/Flu_Combo_Tree.h @@ -0,0 +1,49 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#ifndef _FLU_COMBO_TREE_H +#define _FLU_COMBO_TREE_H + +#include "FLU/Flu_Combo_Box.h" +#include "FLU/Flu_Tree_Browser.h" + +//! Just like the Fl_Choice widget except the input area is editable and it can display a tree instead of a list (using Flu_Tree_Browser) +class FLU_EXPORT Flu_Combo_Tree : public Flu_Combo_Box +{ + +public: + + //! Normal FLTK widget constructor + Flu_Combo_Tree( int x, int y, int w, int h, const char *l = 0 ); + + //! Default destructor + ~Flu_Combo_Tree(); + + //! Publicly exposed tree widget (instance of Flu_Tree_Browser) + Flu_Tree_Browser tree; + + protected: + + bool _value( const char *v ); + const char* _next(); + const char* _previous(); + + inline static void _cb( Fl_Widget *w, void *arg ) + { ((Flu_Combo_Tree*)arg)->cb(); } + void cb(); + +}; + +#endif diff --git a/src/FLU/Flu_File_Chooser.h b/src/FLU/Flu_File_Chooser.h new file mode 100644 index 0000000..b969489 --- /dev/null +++ b/src/FLU/Flu_File_Chooser.h @@ -0,0 +1,529 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#ifndef _FLU_FILE_CHOOSER_H +#define _FLU_FILE_CHOOSER_H + +#include +#include +#include +#include +#include +#include +#include + +#include "FLU/Flu_Button.h" +#include "FLU/Flu_Return_Button.h" +#include "FLU/Flu_Wrap_Group.h" +#include "FLU/Flu_Combo_Tree.h" +#include "FLU/Flu_Combo_List.h" +#include "FLU/flu_export.h" +#include "FLU/FluSimpleString.h" +#include "FLU/VectorClass.h" + +FLU_EXPORT const char* flu_file_chooser( const char *message, const char *pattern, const char *filename ); +FLU_EXPORT const char* flu_dir_chooser( const char *message, const char *filename ); + +MakeVectorClass( FluSimpleString, StringVector ); + +//! A file and directory choosing widget that looks and acts similar to the stock Windows file chooser +class FLU_EXPORT Flu_File_Chooser : public Fl_Double_Window +{ + + friend class FileInput; + class FileInput : public Fl_Input + { + public: + FileInput( int x, int y, int w, int h, const char *l, Flu_File_Chooser *c ); + ~FileInput(); + + int handle( int event ); + protected: + Flu_File_Chooser *chooser; + }; + + public: + + //! This class must be derived from to create a "preview" widget. + /*! Simply derive from this class and overload Fl_Group's methods to create a widget + able to preview whatever file type you want. Register it with Flu_File_Chooser::add_preview_handler() + When a file is previewed, all registered handlers are visited until the preview() virtual function + for one of them returns nonzero. When preview() is called, the absolute path of the file is passed in, + and the widget should determine whether it can preview the file and update itself accordingly. If + it can preview the file, it should return nonzero, else it should return zero. + */ + class PreviewWidgetBase : public Fl_Group + { + public: + PreviewWidgetBase(); + virtual ~PreviewWidgetBase(); + virtual int preview( const char *filename ) = 0; + }; + + //! File entry type + enum { + ENTRY_NONE = 1, /*!< An empty (or non-existant) entry */ + ENTRY_DIR = 2, /*!< A directory entry */ + ENTRY_FILE = 4, /*!< A file entry */ + ENTRY_FAVORITE = 8, /*!< A favorite entry */ + ENTRY_DRIVE = 16, /*!< An entry that refers to a disk drive */ + ENTRY_MYDOCUMENTS = 32, /*!< The entry referring to the current user's documents */ + ENTRY_MYCOMPUTER = 64 /*!< The entry referring to "My Computer" in Windows */ + }; + + //! Chooser type + enum { + SINGLE = 0, /*!< Chooser a single file or directory */ + MULTI = 1, /*!< Choose multiple files or directories */ + DIRECTORY = 4 /*!< Choose directories (choosing files is implicit if this bit is clear) */ + }; + + //! Structure holding the info needed for custom file types + struct FileTypeInfo + { + Fl_Image *icon; + FluSimpleString extensions; + FluSimpleString type, shortType; + }; + + //! Constructor opening a file chooser with title \b title visiting directory \b path with files filtered according to \b pattern. \b type is a logical OR of Flu_File_Chooser::SINGLE, Flu_File_Chooser::MULTI, and Flu_File_Chooser::DIRECTORY + Flu_File_Chooser( const char *path, const char *pattern, int type, const char *title ); + + //! Destructor + ~Flu_File_Chooser(); + + //! Add a custom callback that is called when the user right-clicks on an entry + /*! \param type is the type of entry to handle (i.e. a logical OR of \c ENTRY_NONE, \c ENTRY_DIR, \c ENTRY_FILE, \c ENTRY_FAVORITE, \c ENTRY_DRIVE, \c ENTRY_MYDOCUMENTS, \c ENTRY_MYCOMPUTER). To add a "nothing" handler (when the user right-clicks on nothing), use ENTRY_NONE + \param ext is the extension of the file that will cause this handler to be added to the popup menu + \param name is the name that will appear in the popup menu for this handler + */ + static void add_context_handler( int type, const char *ext, const char *name, + void (*cb)(const char*,int,void*), void *cbd ); + + //! Add a "preview" widget (derived from class Flu_File_Chooser::PreviewWidgetBase) that will handle custom previewing of files + static void add_preview_handler( PreviewWidgetBase *w ); + + //! Add descriptive information and an icon for a file type + /*! \param extensions is a space- or comma-delimited list of file extensions, or \c NULL for directories. e.g. "zip,tgz,rar" + \param short_description is a short description (!) of the file type. e.g. "Compressed Archive" + \param icon is an optional custom icon to use for this file type + */ + static void add_type( const char *extensions, const char *short_description, Fl_Image *icon = NULL ); + + //! Set whether the names of files/directories are allowed to be edited by the user (by selecting the file and then clicking on it again). Default is on (true) + inline void allow_file_editing( int b ) + { fileEditing = b; } + + //! Get whether the names of files/directories are allowed to be edited by the user (by selecting the file and then clicking on it again) + inline int allow_file_editing() const + { return fileEditing; } + + //! Set whether file sorting is case insensitive. Default value is case-insensitive for windows, case-sensitive for everything else + inline void case_insensitive_sort( int b ) + { caseSort = !b; } + + //! Get whether file sorting is case insensitive + inline int case_insensitive_sort() const + { return !caseSort; } + + //! Change the current directory the chooser is browsing to \b path + void cd( const char *path ); + + //! Clear the history of which directories have been visited + void clear_history(); + + //! \return how many files are selected + int count(); + + //! Set the default icon to use for all files for which no other icon has been specified + inline void default_file_icon( Fl_Image* i ) + { defaultFileIcon = i; } + + //! Alias for cd() + inline void directory( const char *d ) + { cd( d ); } + + //! Alias for pattern() + inline void filter( const char *p ) + { pattern( p ); } + + //! Alias for pattern() + inline const char* filter() const + { return pattern(); } + + //! \return a pointer to a FileTypeInfo structure for files with type \b extension + static FileTypeInfo *find_type( const char *extension ); + + //! \return the current directory that the browser is visiting + inline const char* get_current_directory() const + { return currentDir.c_str(); } + + //! Override of Fl_Double_Window::handle() + int handle( int event ); + + //! Change the file filter pattern to \b p + void pattern( const char *p ); + + //! Get the current file filter pattern + inline const char* pattern() const + { return rawPattern.c_str(); } + + //! Set the state of the preview button + inline void preview( int b ) + { previewBtn->value(b); previewBtn->do_callback(); } + + //! Get the state of the preview button + inline int preview() const + { return previewBtn->value(); } + + //! Refresh the current directory + inline void rescan() { reloadCB(); } + + //! Override of Fl_Double_Window::resize() + void resize( int x, int y, int w, int h ); + + //! Set a custom sorting function for sorting entries based on filename + inline void set_sort_function( int (*cb)(const char*,const char*) ) + { customSort = cb; rescan(); } + + //! Unselect all entries + void unselect_all(); + + //! Set the current file the chooser is selecting + void value( const char *v ); + + //! Get the current file the chooser is selecting + const char *value(); + + //! For MULTI file queries, get selected file \b n + const char *value( int n ); + + FileInput filename; + // the key behavior is not correct for versions before 1.1.4rc2 +#if FL_MAJOR_VERSION >= 1 && FL_MINOR_VERSION >= 1 && FL_PATCH_VERSION >= 4 + Flu_Return_Button ok; +#else + Flu_Button ok; +#endif + Flu_Button cancel; + + // apparently there is a bug in VC6 that prevents friend classes from accessing + // non-public members. stupid windows + // several other compilers were reported to have a problem with this too, so + // i'm just making the whole class public to eliminate potential problems. + // bad c++ - i know... + //#ifndef WIN32 + //protected: + //#endif + + class ContextHandler + { + public: + FluSimpleString ext, name; + int type; + void (*callback)(const char*,int,void*); + void *callbackData; + inline ContextHandler& operator =( const ContextHandler &c ) + { ext = c.ext; name = c.name; type = c.type; callback = c.callback; callbackData = c.callbackData; return *this; } + }; + MakeVectorClass( ContextHandler, ContextHandlerVector ); + static ContextHandlerVector contextHandlers; + + typedef PreviewWidgetBase* pPreviewWidgetBase; + MakeVectorClass( pPreviewWidgetBase, PreviewHandlerVector ); + static PreviewHandlerVector previewHandlers; + + Fl_Check_Button *hiddenFiles; + Flu_Combo_Tree *filesystems; + + inline static void _backCB( Fl_Widget *w, void *arg ) + { ((Flu_File_Chooser*)arg)->backCB(); } + void backCB(); + + inline static void _forwardCB( Fl_Widget *w, void *arg ) + { ((Flu_File_Chooser*)arg)->forwardCB(); } + void forwardCB(); + + inline static void _sortCB( Fl_Widget *w, void *arg ) + { ((Flu_File_Chooser*)arg)->sortCB( w ); } + void sortCB( Fl_Widget *w ); + + inline static void _previewCB( Fl_Widget*, void *arg ) + { ((Flu_File_Chooser*)arg)->previewCB(); } + void previewCB(); + + inline static void _filenameCB( Fl_Widget *w, void *arg ) + { ((Flu_File_Chooser*)arg)->filenameCB(); } + void filenameCB(); + + inline static void _filesystemsCB( Fl_Widget *w, void *arg ) + { ((Flu_File_Chooser*)arg)->filesystemsCB( ((Flu_Combo_Tree*)w)->value() ); } + void filesystemsCB( const char *path ); + + inline static void delayedCdCB( void *arg ) + { ((Flu_File_Chooser*)arg)->cd( ((Flu_File_Chooser*)arg)->delayedCd.c_str() ); } + + inline static void selectCB( void *arg ) + { ((Flu_File_Chooser*)arg)->hide(); } + + inline static void _cancelCB( Fl_Widget*, void *arg ) + { ((Flu_File_Chooser*)arg)->cancelCB(); } + void cancelCB(); + + inline static void _okCB( Fl_Widget*, void *arg ) + { ((Flu_File_Chooser*)arg)->okCB(); } + void okCB(); + + inline static void _trashCB( Fl_Widget*, void *arg ) + { ((Flu_File_Chooser*)arg)->trashCB(); } + void trashCB( int recycle = true ); + + inline static void _newFolderCB( Fl_Widget*, void *arg ) + { ((Flu_File_Chooser*)arg)->newFolderCB(); } + void newFolderCB(); + + inline static void upDirCB( Fl_Widget*, void *arg ) + { ((Flu_File_Chooser*)arg)->cd( "../" ); } + + inline static void reloadCB( Fl_Widget*, void *arg ) + { ((Flu_File_Chooser*)arg)->reloadCB(); } + void reloadCB(); + + inline static void _homeCB( Fl_Widget*, void *arg ) + { ((Flu_File_Chooser*)arg)->homeCB(); } + void homeCB(); + + inline static void _desktopCB( Fl_Widget*, void *arg ) + { ((Flu_File_Chooser*)arg)->desktopCB(); } + void desktopCB(); + + inline static void _favoritesCB( Fl_Widget*, void *arg ) + { ((Flu_File_Chooser*)arg)->favoritesCB(); } + void favoritesCB(); + + inline static void _myComputerCB( Fl_Widget*, void *arg ) + { ((Flu_File_Chooser*)arg)->myComputerCB(); } + void myComputerCB(); + + inline static void _addToFavoritesCB( Fl_Widget*, void *arg ) + { ((Flu_File_Chooser*)arg)->addToFavoritesCB(); } + void addToFavoritesCB(); + + inline static void _documentsCB( Fl_Widget*, void *arg ) + { ((Flu_File_Chooser*)arg)->documentsCB(); } + void documentsCB(); + + enum { + SORT_NAME = 1, + SORT_SIZE = 2, + SORT_TYPE = 4, + SORT_DATE = 8, + SORT_REVERSE = 16 + }; + static void _qSort( int how, int caseSort, Fl_Widget **array, int low, int high ); + + friend class Entry; + class Entry : public Fl_Input + { + public: + Entry( const char* name, int t, int d, Flu_File_Chooser *c ); + ~Entry(); + + int handle( int event ); + void draw(); + + void updateSize(); + void updateIcon(); + + FluSimpleString filename, date, filesize, shortname, + description, shortDescription, toolTip, altname; + //FluSimpleString permissions; + //unsigned char pU, pG, pO; // 3-bit unix style permissions + unsigned int type, idate; + unsigned long isize; + int selected; + int editMode; + Flu_File_Chooser *chooser; + Fl_Image *icon; + + int nameW, typeW, sizeW, dateW; + int details; + + inline static void _inputCB( Fl_Widget *w, void *arg ) + { ((Entry*)arg)->inputCB(); } + void inputCB(); + + inline static void _editCB( void *arg ) + { ((Entry*)arg)->editCB(); } + void editCB(); + }; + + friend class FileList; + class FileList : public Flu_Wrap_Group + { + public: + FileList( int x, int y, int w, int h, Flu_File_Chooser *c ); + ~FileList(); + + int handle( int event ); + void sort( int numDirs = -1 ); + + int numDirs; + Flu_File_Chooser *chooser; + }; + + friend class FileDetails; + class FileDetails : public Fl_Pack + { + public: + FileDetails( int x, int y, int w, int h, Flu_File_Chooser *c ); + ~FileDetails(); + + int handle( int event ); + void sort( int numDirs = -1 ); + + void scroll_to( Fl_Widget *w ); + + int numDirs; + Flu_File_Chooser *chooser; + }; + + friend class CBTile; + class CBTile : public Fl_Tile + { + public: + CBTile( int x, int y, int w, int h, Flu_File_Chooser *c ); + int handle( int event ); + Flu_File_Chooser *chooser; + }; + + friend class FileColumns; + class FileColumns : public Fl_Tile + { + public: + FileColumns( int x, int y, int w, int h, Flu_File_Chooser *c ); + ~FileColumns(); + + int handle( int event ); + void resize( int x, int y, int w, int h ); + Flu_File_Chooser *chooser; + int W1, W2, W3, W4; + }; + + friend class PreviewTile; + class PreviewTile : public Fl_Tile + { + public: + PreviewTile( int x, int y, int w, int h, Flu_File_Chooser *c ); + int handle( int event ); + Flu_File_Chooser *chooser; + int last; + }; + + class ImgTxtPreview : public PreviewWidgetBase + { + public: + int preview( const char *filename ); + unsigned char previewTxt[1024]; + }; + + friend class PreviewGroup; + class PreviewGroup : public Fl_Group + { + public: + PreviewGroup( int x, int y, int w, int h, Flu_File_Chooser *c ); + void draw(); + Flu_File_Chooser *chooser; + FluSimpleString lastFile, file; + PreviewWidgetBase* handled; + }; + + Fl_Group *getEntryGroup(); + + void win2unix( FluSimpleString &s ); + + void cleanupPath( FluSimpleString &s ); + + int correctPath( FluSimpleString &path ); + + void updateEntrySizes(); + + void buildFilesystemsCombo(); + + void addToHistory(); + + FluSimpleString formatDate( const char *d ); + + void recursiveScan( const char *dir, StringVector *files ); + + int stripPatterns( FluSimpleString s, StringVector* patterns ); + + int popupContextMenu( Entry *entry ); + + FluSimpleString commonStr(); + + static ImgTxtPreview *imgTxtPreview; + + static int (*customSort)(const char*,const char*); + + PreviewGroup *previewGroup; + PreviewTile *previewTile; + Fl_Group *fileGroup; + Fl_Menu_Button entryPopup; + Fl_Image *defaultFileIcon; + Entry *lastSelected; + FileList *filelist; + FileColumns *filecolumns; + Fl_Scroll *filescroll; + FileDetails *filedetails; + Flu_Button *detailNameBtn, *detailTypeBtn, *detailSizeBtn, *detailDateBtn; + FluSimpleString currentDir, delayedCd, rawPattern; + FluSimpleString userHome, configFilename; + FluSimpleString drives[26]; + Fl_Pixmap* driveIcons[26]; + Flu_Button *fileListBtn, *fileListWideBtn, *fileDetailsBtn, *backBtn, *forwardBtn, *upDirBtn, *trashBtn, + *newDirBtn, *addFavoriteBtn, *reloadBtn, *previewBtn; + Fl_Browser *favoritesList; + Flu_Combo_List *filePattern; + int selectionType; + int filenameEnterCallback, filenameTabCallback, walkingHistory, caseSort, fileEditing; + int sortMethod; + + StringVector patterns; + + static FileTypeInfo *types; + static int numTypes; + static int typeArraySize; + +#ifdef WIN32 + unsigned int driveMask; + unsigned int driveTypes[26]; + FluSimpleString volumeNames[26]; + int refreshDrives; +#endif + + class History + { + public: + History() { last = next = NULL; } + FluSimpleString path; + History *last, *next; + }; + + History *history, *currentHist; + +}; + +#endif diff --git a/src/FLU/Flu_Label.h b/src/FLU/Flu_Label.h new file mode 100644 index 0000000..0f2999a --- /dev/null +++ b/src/FLU/Flu_Label.h @@ -0,0 +1,61 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#ifndef _FLU_LABEL_H +#define _FLU_LABEL_H + +#include +#include +#include + +#include "FLU/Flu_Enumerations.h" + +//! This class just provides an easier interface to making labels in FLTK +/*! All this class does is copy the label string to internal storage + since FLTK needs non-transient memory for labels. */ +class FLU_EXPORT Flu_Label : public Fl_Box +{ + + public: + + //! Normal FLTK widget constructor + Flu_Label( int x, int y, int w, int h, const char* l = 0 ); + + //! Default destructor + virtual ~Flu_Label(); + + //! Alias for label() + inline void value( const char* l ) + { label(l); } + + //! \return the label + inline const char* value() const + { return _label; } + + //! Set the label to \b l + void label( const char* l ); + + //! \return the label + inline const char* label() const + { return _label; } + + protected: + + char* _label; + //bool _truncate; + +}; + +#endif diff --git a/src/FLU/Flu_Return_Button.h b/src/FLU/Flu_Return_Button.h new file mode 100644 index 0000000..a8a0a67 --- /dev/null +++ b/src/FLU/Flu_Return_Button.h @@ -0,0 +1,34 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#ifndef _FLU_RETURN_BUTTON_H +#define _FLU_RETURN_BUTTON_H + +#include "FLU/Flu_Button.h" + +//! This class extends Flu_Button to make a button similar to Fl_Return_Button +class FLU_EXPORT Flu_Return_Button : public Flu_Button +{ + public: + + //! Normal FLTK widget constructor + Flu_Return_Button( int X,int Y,int W,int H,const char *l = 0 ); + + //! Default destructor + ~Flu_Return_Button(); + +}; + +#endif diff --git a/src/FLU/Flu_Separator.h b/src/FLU/Flu_Separator.h new file mode 100644 index 0000000..fabf2fd --- /dev/null +++ b/src/FLU/Flu_Separator.h @@ -0,0 +1,55 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#ifndef _FLU_SEPARATOR_H +#define _FLU_SEPARATOR_H + +/* fltk includes */ +#include +#include +#include + +#include "FLU/Flu_Enumerations.h" + +//! A simple class that draws a separator line using the current box type +class FLU_EXPORT Flu_Separator : public Fl_Widget +{ + public: + + enum { + HORIZONTAL, + VERTICAL + }; + + //! Normal FLTK constructor. Default type() is \b HORIZONTAL + Flu_Separator( int X, int Y, int W, int H, const char *l = 0 ); + + //! Get the type + inline int type() const + { return _type; } + + //! Set the type + inline void type( int t ) + { _type = t; } + + protected: + + int _type; + + void draw(); + +}; + +#endif diff --git a/src/FLU/Flu_Tree_Browser.h b/src/FLU/Flu_Tree_Browser.h index d04b79d..5933920 100644 --- a/src/FLU/Flu_Tree_Browser.h +++ b/src/FLU/Flu_Tree_Browser.h @@ -29,6 +29,7 @@ #include #include #include +#include #include /* flu includes */ @@ -42,9 +43,9 @@ typedef struct { bool dummy; } Flu_DND_Event; // for compatibilty when not comp //! This class provides a browser for hierarchical data representation (i.e. a "tree") #ifdef USE_FLU_DND -class FLU_EXPORT Flu_Tree_Browser : public Fl_Group, public Flu_DND +class FLU_EXPORT Flu_Tree_Browser : public Fl_Double_Window, public Flu_DND #else -class FLU_EXPORT Flu_Tree_Browser : public Fl_Group +class FLU_EXPORT Flu_Tree_Browser : public Fl_Double_Window #endif { @@ -638,6 +639,7 @@ class FLU_EXPORT Flu_Tree_Browser : public Fl_Group void *cbd; unsigned int when, cbReason; Node *cbNode, *lastOpenBranch; + int firstConnector; //int (*sortCB)(Node*,Node*); }; @@ -699,7 +701,10 @@ class FLU_EXPORT Flu_Tree_Browser : public Fl_Group Node* insert_at( Node* p, Node* i, const char* path, RData &rdata, Fl_Widget *w, bool showLabel ); - //! Add the entry specified by \b fullpath to this node. If \b w is not \c NULL then that widget is the entry and the label (as specified in \b fullPath) is visible depending on the value of \b showLabel. Note that the widget is destroyed by the tree/node on clear() or the destructor + //! Add the entry specified by \b fullpath to this node. If \b w is not \c NULL then + // that widget is the entry and the label (as specified in \b fullPath) is visible + // depending on the value of \b showLabel. Note that the widget is destroyed by the + // tree/node on clear() or the destructor /*! \return a pointer to the Node of the added entry or NULL if the add failed */ inline Node* add( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true ) { return( modify( fullpath, ADD, tree->rdata, w, showLabel ) ); } diff --git a/src/FLU/Flu_Wrap_Group.h b/src/FLU/Flu_Wrap_Group.h new file mode 100644 index 0000000..750ee2a --- /dev/null +++ b/src/FLU/Flu_Wrap_Group.h @@ -0,0 +1,177 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#ifndef _FLU_WRAP_GROUP_H +#define _FLU_WRAP_GROUP_H + +/* fltk includes */ +#include +#include +#include +#include + +#include "FLU/Flu_Enumerations.h" + +//! This class provides an alternative to Fl_Group that automatically arranges the children either left to right and top to bottom (for type() == \c FL_VERTICAL), or top to bottom and left to right (for type() == \c FL_HORIZONTAL), within the available size of the group, with a scrollbar turning on if they don't all fit +/*! This class is a group with a scrollbar and an \b Fl_Group inside (both publicly exposed). The \b Fl_Group + contains the actual child widgets of this group. + + Most of the \b Fl_Group member functions are reimplemented here in a pass-through fashion to the + internal group. This means that casual use of a descendent instance will be almost exactly the same + as for a regular \b Fl_Group, with any additional access provided directly through member \b group. + + The goal of this class is to provide a group that dynamically and evenly distributes its children within + a fixed space, similar to those available in other GUI toolkits. +*/ +class FLU_EXPORT Flu_Wrap_Group : public Fl_Group +{ + + public: + + class Scrollbar : public Fl_Scrollbar + { + public: + Scrollbar( int x, int y, int w, int h, const char *l = 0 ); + int handle( int event ); + }; + + //! Normal FLTK constructor + Flu_Wrap_Group( int x, int y, int w, int h, const char *l = 0 ); + + //! Set the offset for where the first child starts + inline void offset( int x, int y ) + { _offset[0] = x, _offset[1] = y; redraw(); } + + //! \return the x offset for where the first child starts + inline int offset_x() const + { return _offset[0]; } + + //! \return the y offset for where the first child starts + inline int offset_y() const + { return _offset[1]; } + + //! Set the spacing between children + inline void spacing( int x, int y ) + { _spacing[0] = x, _spacing[1] = y; redraw(); } + + //! \return the x spacing between children + inline int spacing_x() const + { return _spacing[0]; } + + //! \return the y spacing between children + inline int spacing_y() const + { return _spacing[1]; } + + //! Set the wrap type. Must be either \c FL_VERTICAL (children wrap according to the width, with a vertical scrollbar) or \c FL_HORIZONTAL (children wrap according to the height, with a horizontal scrollbar). Default is \c FL_HORIZONTAL + void type( int t ); + + //! Get the wrap type + inline int type() const + { return _type; } + + //! Override of Fl_Group::draw() + void draw(); + + //! Override of Fl_Group::resize() + void resize( int x, int y, int w, int h ); + + //! Scroll the group so that the given widget is shown (usually aligned to the left/top) + void scroll_to( const Fl_Widget *w ); + + //! Scroll the group so that the given widget is shown (usually aligned to the left/top) + inline void scroll_to( const Fl_Widget& w ) + { scroll_to( &w ); } + + //! Scroll the group to the beginning of the list + void scroll_to_beginning(); + + //! Scroll the group to the end of the list + void scroll_to_end(); + + /*! \name Pass-through functions for the internal Fl_Group + * These are strictly for convenience. Only the most commonly called functions have been re-implemented. + * You can also explicitly access the group object for more control. + */ + //@{ + + inline Fl_Widget* const* array() const + { return group.array(); } + + inline int find( const Fl_Widget* w ) const + { return group.find( w ); } + + inline int find( const Fl_Widget& w ) const + { return group.find( w ); } + + inline void clear() + { group.clear(); } + + inline Fl_Widget *child(int n) const + { return group.child(n); } + + inline int children() const + { return group.children(); } + + inline void begin() + { group.begin(); } + + inline void end() + { group.end(); Fl_Group::end(); } + + inline void resizable(Fl_Widget *box) + { group.resizable(box); } + + inline void resizable(Fl_Widget &box) + { group.resizable(box); } + + inline Fl_Widget *resizable() const + { return group.resizable(); } + + inline void add( Fl_Widget &w ) + { group.add( w ); } + + inline void add( Fl_Widget *w ) + { group.add( w ); } + + inline void insert( Fl_Widget &w, int n ) + { group.insert( w, n ); } + + inline void insert( Fl_Widget &w, Fl_Widget* beforethis ) + { group.insert( w, beforethis ); } + + inline void remove( Fl_Widget &w ) + { group.remove( w ); } + + inline void add_resizable( Fl_Widget &box ) + { group.add_resizable( box ); } + + //@} + + Scrollbar scrollbar; + Fl_Group group; + + protected: + + inline static void _scrollCB( Fl_Widget*, void *arg ) + { ((Flu_Wrap_Group*)arg)->redraw(); } + + bool layout( bool sbVisible, bool doScrollTo ); + + const Fl_Widget *scrollTo; + int _offset[2], _spacing[2], _type; + +}; + +#endif diff --git a/src/FLU/VectorClass.h b/src/FLU/VectorClass.h new file mode 100644 index 0000000..c210e7f --- /dev/null +++ b/src/FLU/VectorClass.h @@ -0,0 +1,102 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#ifndef _FLU_VECTOR_CLASS_H +#define _FLU_VECTOR_CLASS_H + +#define MakeVectorClass( T, C ) \ +class C \ +{ \ +public: \ + \ + C() { _array = NULL; _size = 0; } \ + \ + ~C() { clear(); } \ + \ + inline void add( const T& item ) { insert( size(), item ); } \ + \ + inline T& operator [](int i) { return _array[i]; } \ + \ + inline T operator [](int i) const { return _array[i]; } \ + \ + inline unsigned int size() const { return _size; } \ + \ + C& operator =( const C &v ) \ + { \ + clear(); \ + if( v.size() ) \ + { \ + _array = new T[v.size()]; \ + for( unsigned int i = 0; i < v.size(); i++ ) \ + _array[i] = v._array[i]; \ + } \ + return *this; \ + } \ + \ + void insert( unsigned int pos, const T &item ) \ + { \ + if( pos > _size ) \ + pos = _size; \ + if( _size == 0 ) \ + { \ + _array = new T[1]; \ + } \ + else \ + { \ + if( !( _size & (_size-1) ) ) \ + { \ + T* temp = new T[_size*2]; \ + for( unsigned int i = 0; i < _size; i++ ) \ + temp[i] = _array[i]; \ + delete[] _array; \ + _array = temp; \ + } \ + for( unsigned int s = _size; s > pos; s-- ) \ + _array[s] = _array[s-1]; \ + } \ + _size++; \ + _array[pos] = item; \ + } \ + \ + void erase( unsigned int pos ) \ + { \ + if( pos >= _size ) \ + return; \ + _size--; \ + if( _size == 0 ) \ + { \ + delete[] _array; \ + _array = NULL; \ + } \ + else \ + { \ + for( ; pos < _size; pos++ ) \ + _array[pos] = _array[pos+1]; \ + } \ + } \ + \ + void clear() \ + { \ + if( _array ) \ + delete[] _array; \ + _size = 0; \ + } \ + \ +protected: \ + T *_array; \ + unsigned int _size; \ +} + +#endif diff --git a/src/FLU/flu_file_chooser_pixmaps.h b/src/FLU/flu_file_chooser_pixmaps.h new file mode 100644 index 0000000..dafeafa --- /dev/null +++ b/src/FLU/flu_file_chooser_pixmaps.h @@ -0,0 +1,35 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#ifndef _FLU_FILE_CHOOSER_PIXMAPS_H +#define _FLU_FILE_CHOOSER_PIXMAPS_H + +#include "FLU/flu_export.h" + +FLU_EXPORT extern const char* monalisa_xpm[]; +FLU_EXPORT extern const char* filedetails_xpm[]; +FLU_EXPORT extern const char* filelist_xpm[]; +FLU_EXPORT extern const char* filelistwide_xpm[]; +FLU_EXPORT extern const char* bighome_xpm[]; +FLU_EXPORT extern const char* folder_favorite_xpm[]; +FLU_EXPORT extern const char* bigfavorites_xpm[]; +FLU_EXPORT extern const char* desktop_xpm[]; +FLU_EXPORT extern const char* bigtemporary_xpm[]; +FLU_EXPORT extern const char* bigdocuments_xpm[]; +FLU_EXPORT extern const char* mini_folder_favorites_xpm[]; +FLU_EXPORT extern const char* mini_desktop_xpm[]; +FLU_EXPORT extern const char* my_computer_xpm[]; + +#endif diff --git a/src/Flu_Button.cpp b/src/Flu_Button.cpp new file mode 100644 index 0000000..2bbf29b --- /dev/null +++ b/src/Flu_Button.cpp @@ -0,0 +1,191 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#include +#include "FLU/Flu_Button.h" + +#include + +// taken explicitly from Fl_Return_Button.cpp +int flu_return_arrow(int x, int y, int w, int h) +{ + int size = w; if (hcopy(); + inactiveImg->desaturate(); + Fl_Button::deimage( inactiveImg ); + } +} diff --git a/src/Flu_Combo_Box.cpp b/src/Flu_Combo_Box.cpp new file mode 100644 index 0000000..406abed --- /dev/null +++ b/src/Flu_Combo_Box.cpp @@ -0,0 +1,252 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#include +#include +#include +#include +#include +#include + +#include "FLU/Flu_Combo_Box.h" + +Flu_Combo_Box :: Flu_Combo_Box( int X, int Y, int W, int H, const char* l ) + : Fl_Group( X, Y, W, H, l ), input( X+2, Y+2, W-20-1-2, H-4 ) +{ + box( FL_DOWN_BOX ); + align( FL_ALIGN_LEFT ); + pop_height( 250 ); + + _cbox = NULL; + _valbox = FL_UP_BOX; + + input_callback( NULL ); + input.box( FL_FLAT_BOX ); + input.callback( input_cb, this ); + input.when( FL_WHEN_ENTER_KEY_ALWAYS ); + input.color( FL_WHITE, selection_color()); + input.textfont( FL_HELVETICA ); + input.textsize( FL_NORMAL_SIZE ); + input.textcolor( FL_FOREGROUND_COLOR ); + + editable( true ); + + end(); +} + +Flu_Combo_Box::~Flu_Combo_Box() +{ +} + +void Flu_Combo_Box :: set_combo_widget( Fl_Widget *w ) +{ + _cbox = w; + this->add( w ); +} + +void Flu_Combo_Box :: input_cb( Fl_Widget*, void* v ) +{ + // taken from Fl_Counter.cxx + Flu_Combo_Box& t = *(Flu_Combo_Box*)v; + + if( strcmp( t.input.value(), t.value() )!=0 || t.input.when() & FL_WHEN_NOT_CHANGED) + { + if( t.when() ) + { + t.clear_changed(); + if( t._inputCB ) + t._inputCB( &t, t._inputCBD ); + else + t.do_callback(); + } + else + { + t.set_changed(); + } + } +} + +void Flu_Combo_Box :: resize( int X, int Y, int W, int H ) +{ + Fl_Group::resize( X, Y, W, H ); + input.resize( X+2, Y+2, W-20-1-2, H-4 ); +} + +void Flu_Combo_Box :: draw() +{ + int W = 18, H = h()-4; + int X = x()+w()-W-2, Y = y()+2; + + fl_draw_box( box(), x(), y(), w(), h(), color() ); + + // draw the arrow button + fl_draw_box( (Fl_Boxtype)_valbox, X, Y, W, H, color() ); + fl_color( active_r() ? FL_FOREGROUND_COLOR : fl_inactive(FL_FOREGROUND_COLOR) ); + fl_polygon( X+W/2-4, Y+H/2-2, X+W/2+4, Y+H/2-2, X+W/2, Y+H/2+2 ); + + draw_child( input ); + if (Fl::focus() == this) draw_focus(); +} + +Flu_Combo_Box::Popup :: Popup( Flu_Combo_Box *b, Fl_Widget *c, int H ) + : Fl_Double_Window( b->window()->x()+b->x()-2, b->window()->y()+b->y()+b->h()-2, b->w()+4, H, 0 ) +{ + combo = b; + dragging = false; + selected = NULL; + + box( FL_BORDER_FRAME ); + border( 0 ); + add( c ); + end(); + //set_non_modal(); + set_modal(); + + c->resize( 1, 1, w()-2, h()-2 ); +} + +Flu_Combo_Box::Popup :: ~Popup() +{ + while( children() ) + remove( child(0) ); +} + +void Flu_Combo_Box :: value( const char *v ) +{ + if( _value( v ) ) + input.value( v ); +} + +void Flu_Combo_Box :: selected( const char *v ) +{ + if( v ) + input.value( v ); + _popped = false; + do_callback(); +} + +int Flu_Combo_Box::Popup :: handle( int event ) +{ + // FL_MOVE is generated while window is moving + // this attempts to keep the popup window moving with the enclosing window + if( event == FL_MOVE ) + position( combo->window()->x()+combo->x()-2, combo->window()->y()+combo->y()+combo->h()-2 ); + + if( event == FL_DRAG ) + dragging = true; + + // if push outside the popup window, popdown + if( event == FL_PUSH && + !Fl::event_inside( child(0) ) ) + { + combo->_popped = false; + return 0; + } + + // if release after dragging outside the popup window, popdown + if( event == FL_RELEASE && dragging && + !Fl::event_inside( child(0) ) ) + { + combo->_popped = false; + return 0; + } + + if( event == FL_KEYDOWN ) + { + if( Fl::event_key( FL_Escape ) ) + { + combo->_popped = false; + return 0; + } + else if( Fl::event_key( FL_Up ) ) + { + selected = combo->_previous(); + return 1; + } + else if( Fl::event_key( FL_Down ) ) + { + selected = combo->_next(); + return 1; + } + else if( Fl::event_key( FL_Enter ) || Fl::event_key( ' ' ) ) + { + if( selected ) + { + combo->value( selected ); + combo->selected( selected ); + } + combo->_popped = false; + return 1; + } + } + + return Fl_Double_Window::handle( event ); +} + +int Flu_Combo_Box :: handle( int event ) +{ + // is it time to popup? + bool open = ( event == FL_PUSH ) && + (!Fl::event_inside( &input ) || ( !editable() && Fl::event_inside( &input ) ) ); + open |= ( event == FL_KEYDOWN ) && Fl::event_key( ' ' ); + + if( open ) + { + fl_cursor( FL_CURSOR_DEFAULT ); + + _valbox = FL_THIN_DOWN_BOX; + redraw(); + + // remember old current group + Fl_Group *c = Fl_Group::current(); + + // set current group to 0 so this is a top level popup window + Fl_Group::current( 0 ); + Popup *_popup = new Popup( this, _cbox, popHeight ); + + // show it and make FLTK send all events there + value( value() ); + _popup->show(); + Fl::grab( *_popup ); + Fl::focus( _cbox ); + _popped = true; + Fl::pushed( _cbox ); + + // wait for a selection to be made + while( _popped ) + Fl::wait(); + + // restore things and delete the popup + _popup->hide(); + Fl::grab( 0 ); + delete _popup; + Fl_Group::current( c ); + Fl::focus( this ); + + _valbox = FL_UP_BOX; + redraw(); + + return 1; + } + + if( input.handle(event) ) + { + if( !editable() && ( event == FL_ENTER || event == FL_LEAVE ) ) + fl_cursor( FL_CURSOR_DEFAULT ); + return 1; + } + else + return 0; +} diff --git a/src/Flu_Combo_List.cpp b/src/Flu_Combo_List.cpp new file mode 100644 index 0000000..8bbfa24 --- /dev/null +++ b/src/Flu_Combo_List.cpp @@ -0,0 +1,75 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#include +#include +#include +#include +#include +#include + +#include "FLU/Flu_Combo_List.h" + +Flu_Combo_List :: Flu_Combo_List( int X, int Y, int W, int H, const char* l ) + : Flu_Combo_Box( X, Y, W, H, l ), list(0,0,0,0) +{ + list.box( FL_FLAT_BOX ); + list.callback( _cb, this ); + set_combo_widget( &list ); +} + +Flu_Combo_List :: ~Flu_Combo_List() +{ +} + +void Flu_Combo_List :: cb() +{ + if( list.value() == 0 ) + selected( 0 ); + else + selected( list.text( list.value() ) ); +} + +bool Flu_Combo_List :: _value( const char *v ) +{ + // see if 'v' is in the list, and if so, make it the current selection + for( int i = 1; i <= list.size(); i++ ) + { + if( strcmp( list.text(i), v ) == 0 ) + { + list.value( i ); + return true; + } + } + return false; +} + +const char* Flu_Combo_List :: _next() +{ + int v = list.value(); + if( v < list.size() ) + list.value( v+1 ); + list.middleline( list.value() ); + return list.text(list.value()); +} + +const char* Flu_Combo_List :: _previous() +{ + int v = list.value(); + if( v > 1 ) + list.value( v-1 ); + list.middleline( list.value() ); + return list.text(list.value()); +} diff --git a/src/Flu_Combo_Tree.cpp b/src/Flu_Combo_Tree.cpp new file mode 100644 index 0000000..76ee728 --- /dev/null +++ b/src/Flu_Combo_Tree.cpp @@ -0,0 +1,96 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#include +#include +#include +#include +#include +#include + +#include "FLU/Flu_Combo_Tree.h" + +Flu_Combo_Tree :: Flu_Combo_Tree( int X, int Y, int W, int H, const char* l ) + : Flu_Combo_Box( X, Y, W, H, l ), tree(0,0,0,0) +{ + tree.callback( _cb, this ); + tree.selection_mode( FLU_SINGLE_SELECT ); + tree.when( FL_WHEN_RELEASE ); + set_combo_widget( &tree ); +} + +Flu_Combo_Tree :: ~Flu_Combo_Tree() +{ +} + +void Flu_Combo_Tree :: cb() +{ + //if( tree.callback_reason() == FLU_UNSELECTED ) + //selected( 0 ); + if( tree.callback_reason() == FLU_SELECTED ) + selected( tree.callback_node()->find_path() ); +} + +bool Flu_Combo_Tree :: _value( const char *v ) +{ + // see if 'v' is in the tree, and if so, make it the current selection + Flu_Tree_Browser::Node *n = tree.find( v ); + if( n ) + { + tree.unselect_all(); + tree.set_hilighted( n ); + n->select( true ); + return true; + } + return false; +} + +const char* Flu_Combo_Tree :: _next() +{ + Flu_Tree_Browser::Node *n = tree.get_selected( 1 ); + if( n ) + { + Flu_Tree_Browser::Node *n2 = n->next(); + if( n2 ) + { + n->select( false ); + n2->select( true ); + tree.set_hilighted( n2 ); + const char *path = n2->find_path(); + return( strlen(path) ? path : NULL ); + } + } + return NULL; +} + +const char* Flu_Combo_Tree :: _previous() +{ + Flu_Tree_Browser::Node *n = tree.get_selected( 1 ); + if( n ) + { + Flu_Tree_Browser::Node *n2 = n->previous(); + if( n2 ) + { + if( n2->is_root() && !tree.show_root() ) + return NULL; + n->select( false ); + n2->select( true ); + tree.set_hilighted( n2 ); + const char *path = n2->find_path(); + return( strlen(path) ? path : NULL ); + } + } + return NULL; +} diff --git a/src/Flu_File_Chooser.cpp b/src/Flu_File_Chooser.cpp new file mode 100644 index 0000000..0192d35 --- /dev/null +++ b/src/Flu_File_Chooser.cpp @@ -0,0 +1,3644 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#include +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +#include +#include +#include +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "FLU/flu_pixmaps.h" +#include "FLU/Flu_Label.h" +#include "FLU/Flu_Tree_Browser.h" +#include "FLU/Flu_Separator.h" +#include "FLU/Flu_Enumerations.h" + +#include "FLU/Flu_File_Chooser.h" +#include "FLU/flu_file_chooser_pixmaps.h" +#include "FLU/flu_pixmaps.h" + +// just a string that no file could probably ever be called +#define FAVORITES_UNIQUE_STRING "\t!@#$%^&*(Favorites)-=+" + +#define DEFAULT_ENTRY_WIDTH 235 + +Fl_Pixmap up_folder_img( big_folder_up_xpm ), trash( trash_xpm ), new_folder( big_folder_new_xpm ), + reload( reload_xpm ), preview_img( monalisa_xpm ), file_list_img( filelist_xpm ), file_listwide_img( filelistwide_xpm ), + fileDetails( filedetails_xpm ), add_to_favorite_folder( folder_favorite_xpm ), + home( bighome_xpm ), favorites( bigfavorites_xpm ), desktop( desktop_xpm ), + folder_closed( folder_closed_xpm ), default_file( textdoc_xpm ), my_computer( my_computer_xpm ), + computer( computer_xpm ), disk_drive( disk_drive_xpm ), cd_drive( cd_drive_xpm ), + floppy_drive( floppy_drive_xpm ), removable_drive( removable_drive_xpm ), + ram_drive( ram_drive_xpm ), network_drive( network_drive_xpm ), + documents( filled_folder_xpm ), + littlehome( home_xpm ), little_favorites( mini_folder_favorites_xpm ), + little_desktop( mini_desktop_xpm ), bigdocuments( bigdocuments_xpm ), bigtemporary( bigtemporary_xpm ); + +// External CWD path declaraition +extern "C" +{ +extern char path[]; +} + +#define streq(a,b) (strcmp(a,b)==0) + +Flu_File_Chooser::FileTypeInfo* Flu_File_Chooser::types = NULL; +int Flu_File_Chooser::numTypes = 0; +int Flu_File_Chooser::typeArraySize = 0; +Flu_File_Chooser::ContextHandlerVector Flu_File_Chooser::contextHandlers; +Flu_File_Chooser::PreviewHandlerVector Flu_File_Chooser::previewHandlers; +Flu_File_Chooser::ImgTxtPreview* Flu_File_Chooser::imgTxtPreview = 0; +int (*Flu_File_Chooser::customSort)(const char*,const char*) = 0; + +// taken explicitly from fltk/src/filename_match.cxx +// and changed to support case-sensitive matching +int flu_filename_match(const char *s, const char *p) { + int matched; + + for (;;) { + switch(*p++) { + + case '?' : // match any single character + if (!*s++) return 0; + break; + + case '*' : // match 0-n of any characters + if (!*p) return 1; // do trailing * quickly + while (!flu_filename_match(s, p)) if (!*s++) return 0; + return 1; + + case '[': { // match one character in set of form [abc-d] or [^a-b] + if (!*s) return 0; + int reverse = (*p=='^' || *p=='!'); if (reverse) p++; + matched = 0; + char last = 0; + while (*p) { + if (*p=='-' && last) { + if (*s <= *++p && *s >= last ) matched = 1; + last = 0; + } else { + if (*s == *p) matched = 1; + } + last = *p++; + if (*p==']') break; + } + if (matched == reverse) return 0; + s++; p++;} + break; + + case '{' : // {pattern1|pattern2|pattern3} + NEXTCASE: + if (flu_filename_match(s,p)) return 1; + for (matched = 0;;) { + switch (*p++) { + case '\\': if (*p) p++; break; + case '{': matched++; break; + case '}': if (!matched--) return 0; break; + case '|': case ',': if (matched==0) goto NEXTCASE; + case 0: return 0; + } + } + case '|': // skip rest of |pattern|pattern} when called recursively + case ',': + for (matched = 0; *p && matched >= 0;) { + switch (*p++) { + case '\\': if (*p) p++; break; + case '{': matched++; break; + case '}': matched--; break; + } + } + break; + case '}': + break; + + case 0: // end of pattern + return !*s; + + case '\\': // quote next character + if (*p) p++; + default: + if (tolower(*s) != tolower(*(p-1))) return 0; + //if( *s != *(p-1) ) return 0; + s++; + break; + } + } +} + +void Flu_File_Chooser :: add_context_handler( int type, const char *ext, const char *name, + void (*cb)(const char*,int,void*), void *cbd ) +{ + if( cb == NULL ) + return; + ContextHandler h; + h.ext = ext ? ext : ""; + h.ext.downcase(); + h.type = type; + h.name = name; + h.callback = cb; + h.callbackData = cbd; + Flu_File_Chooser::contextHandlers.add( h ); +} + +void Flu_File_Chooser :: add_preview_handler( PreviewWidgetBase *w ) +{ + if( w == NULL ) + return; + Flu_File_Chooser::previewHandlers.add( w ); +} + +// extensions == NULL implies directories +void Flu_File_Chooser :: add_type( const char *extensions, const char *short_description, Fl_Image *icon ) +{ + FluSimpleString ext; + if( extensions ) + ext = extensions; + else + ext = "\t"; // indicates a directory + ext.upcase(); + + // are we overwriting an existing type? + for( int i = 0; i < numTypes; i++ ) + { + if( types[i].extensions == ext ) + { + types[i].icon = icon; + types[i].type = short_description; + return; + } + } + + if( numTypes == typeArraySize ) + { + int newSize = ( typeArraySize == 0 ) ? 1 : typeArraySize*2; // double the size of the old list (same behavior as STL vector) + // allocate the new list + FileTypeInfo* newTypes = new FileTypeInfo[ newSize ]; + // copy the old list to the new list + for( int i = 0; i < numTypes; i++ ) + { + newTypes[i].icon = types[i].icon; + newTypes[i].extensions = types[i].extensions; + newTypes[i].type = types[i].type; + } + // delete the old list and replace it with the new list + delete[] types; + types = newTypes; + typeArraySize = newSize; + } + + types[numTypes].icon = icon; + types[numTypes].extensions = ext; + types[numTypes].type = short_description; + + numTypes++; +} + +Flu_File_Chooser::FileTypeInfo* Flu_File_Chooser :: find_type( const char *extension ) +{ + FluSimpleString ext; + if( extension ) + ext = extension; + else + ext = "\t"; // indicates a directory + ext.upcase(); + + // lookup the type based on the extension + for( int i = 0; i < numTypes; i++ ) + { + // check extension against every token + FluSimpleString e = types[i].extensions; + char *tok = strtok( (char*)e.c_str(), " ," ); + while( tok ) + { + if( ext == tok ) + return &(types[i]); + tok = strtok( NULL, " ," ); + } + } + + return NULL; +} + +Flu_File_Chooser :: Flu_File_Chooser( const char *pathname, const char *pat, int type, const char *title ) + : Fl_Double_Window( 600, 400, title ), + filename( 70, h()-60, w()-70-85-10, 25, "Filename:", this ), + ok( w()-90, h()-60, 85, 25, "Ok" ), + cancel( w()-90, h()-30, 85, 25, "Cancel" ), + entryPopup( 0, 0, 0, 0 ) +{ + Fl_Double_Window::size_range( 600, 400 ); + + Fl_Group *g; + + add_type( NULL, "Directory", &folder_closed ); + + history = currentHist = NULL; + walkingHistory = false; + fileEditing = true; +#ifdef WIN32 + refreshDrives = true; + caseSort = false; +#else + caseSort = true; +#endif + + int oldNormalSize = FL_NORMAL_SIZE; + FL_NORMAL_SIZE = 12; + selectionType = type; + filenameEnterCallback = filenameTabCallback = false; + sortMethod = SORT_NAME; + + lastSelected = NULL; + filename.labelsize( 12 ); + filename.when( FL_WHEN_ENTER_KEY_ALWAYS ); + filename.callback( _filenameCB, this ); + filename.value( "" ); + + Fl_Group *quickIcons = new Fl_Group( 5, 5, 100, h()-10-60 ); + quickIcons->box( FL_DOWN_BOX ); + quickIcons->color( FL_DARK3 ); + + Flu_Button *desktopBtn = new Flu_Button( 30, 18, 50, 48 ); + desktopBtn->box( FL_FLAT_BOX ); + desktopBtn->image( desktop ); + desktopBtn->enter_box( FL_THIN_UP_BOX ); + desktopBtn->color( FL_DARK3 ); + desktopBtn->callback( _desktopCB, this ); + { + Flu_Label *l = new Flu_Label( 5, 62, 100, 20, "Desktop" ); + l->labelcolor( FL_WHITE ); + l->align( FL_ALIGN_CENTER ); + } + + Flu_Button *homeBtn = new Flu_Button( 30, 98, 50, 48 ); + homeBtn->box( FL_FLAT_BOX ); + homeBtn->enter_box( FL_THIN_UP_BOX ); + homeBtn->color( FL_DARK3 ); + homeBtn->callback( _homeCB, this ); + { +#ifdef WIN32 + Flu_Label *l = new Flu_Label( 5, 142, 100, 20, "My Computer" ); + homeBtn->image( my_computer ); +#else + Flu_Label *l = new Flu_Label( 5, 142, 100, 20, "Home" ); + homeBtn->image( home ); +#endif + l->labelcolor( FL_WHITE ); + l->align( FL_ALIGN_CENTER ); + } + + Flu_Button *documentsBtn = new Flu_Button( 30, 178, 50, 48 ); + documentsBtn->box( FL_FLAT_BOX ); + documentsBtn->enter_box( FL_THIN_UP_BOX ); + documentsBtn->labelcolor( FL_WHITE ); + documentsBtn->color( FL_DARK3 ); + documentsBtn->callback( _documentsCB, this ); + { +#ifdef WIN32 + Flu_Label *l = new Flu_Label( 5, 222, 100, 20, "My Documents" ); + documentsBtn->image( &bigdocuments ); +#else + Flu_Label *l = new Flu_Label( 5, 222, 100, 20, "Temporary" ); + documentsBtn->image( &bigtemporary ); +#endif + l->labelcolor( FL_WHITE ); + l->align( FL_ALIGN_CENTER ); + } + + Flu_Button *favoritesBtn = new Flu_Button( 30, 258, 50, 48 ); + favoritesBtn->box( FL_FLAT_BOX ); + favoritesBtn->image( favorites ); + favoritesBtn->enter_box( FL_THIN_UP_BOX ); + favoritesBtn->color( FL_DARK3 ); + favoritesBtn->callback( _favoritesCB, this ); + { + Flu_Label *l = new Flu_Label( 5, 302, 100, 20, "Favorites" ); + l->labelcolor( FL_WHITE ); + l->align( FL_ALIGN_CENTER ); + } + + favoritesList = new Fl_Browser( 0, 0, 0, 0 ); + favoritesList->hide(); + + quickIcons->end(); + + Fl_Group *dummy = new Fl_Group( 110, 0, w()-110, 60 ); + + filesystems = new Flu_Combo_Tree( 166, 5, w()-171, 22, "Location:" ); + filesystems->editable( false ); + filesystems->tree.all_branches_always_open( true ); +#ifdef WIN32 + filesystems->tree.show_root( false ); +#endif + filesystems->tree.show_connectors( false ); + filesystems->tree.horizontal_gap( -10 ); + filesystems->tree.show_leaves( false ); + filesystems->callback( _filesystemsCB, this ); + + //////////////////////////////////////////////////////////////// + + g = new Fl_Group( 110, 30, w()-110, 30 ); // group enclosing all the buttons at top + + backBtn = new Flu_Button( 285, 33, 25, 25, "@<-" ); + backBtn->labelcolor( fl_rgb_color( 80, 180, 200 ) ); + backBtn->labelsize( 16 ); + backBtn->box( FL_FLAT_BOX ); + backBtn->enter_box( FL_THIN_UP_BOX ); + backBtn->callback( _backCB, this ); + backBtn->tooltip( "Go back one directory in the history" ); + + forwardBtn = new Flu_Button( 310, 33, 25, 25, "@->" ); + forwardBtn->labelcolor( fl_rgb_color( 80, 180, 200 ) ); + forwardBtn->labelsize( 16 ); + forwardBtn->box( FL_FLAT_BOX ); + forwardBtn->enter_box( FL_THIN_UP_BOX ); + forwardBtn->callback( _forwardCB, this ); + forwardBtn->tooltip( "Go forward one directory in the history" ); + + upDirBtn = new Flu_Button( 335, 33, 25, 25 ); + upDirBtn->image( up_folder_img ); + upDirBtn->box( FL_FLAT_BOX ); + upDirBtn->enter_box( FL_THIN_UP_BOX ); + upDirBtn->callback( upDirCB, this ); + upDirBtn->tooltip( "Go to the parent directory" ); + + reloadBtn = new Flu_Button( 360, 33, 25, 25 ); + reloadBtn->image( reload ); + reloadBtn->box( FL_FLAT_BOX ); + reloadBtn->enter_box( FL_THIN_UP_BOX ); + reloadBtn->callback( reloadCB, this ); + reloadBtn->tooltip( "Refresh this directory" ); + + { + Flu_Separator *sep = new Flu_Separator( 385, 32, 10, 28 ); + sep->type( Flu_Separator::VERTICAL ); + sep->box( FL_ENGRAVED_BOX ); + } + + trashBtn = new Flu_Button( 395, 33, 25, 25 ); + trashBtn->image( trash ); + trashBtn->box( FL_FLAT_BOX ); + trashBtn->enter_box( FL_THIN_UP_BOX ); + trashBtn->callback( _trashCB, this ); + trashBtn->tooltip( "Delete file(s)" ); + + newDirBtn = new Flu_Button( 420, 33, 25, 25 ); + newDirBtn->image( new_folder ); + newDirBtn->box( FL_FLAT_BOX ); + newDirBtn->enter_box( FL_THIN_UP_BOX ); + newDirBtn->callback( _newFolderCB, this ); + newDirBtn->tooltip( "Create new directory" ); + + addFavoriteBtn = new Flu_Button( 445, 33, 25, 25 ); + addFavoriteBtn->image( add_to_favorite_folder ); + addFavoriteBtn->box( FL_FLAT_BOX ); + addFavoriteBtn->enter_box( FL_THIN_UP_BOX ); + addFavoriteBtn->callback( _addToFavoritesCB, this ); + addFavoriteBtn->tooltip( "Add this directory to my favorites" ); + + { + Flu_Separator *sep = new Flu_Separator( 470, 32, 10, 28 ); + sep->type( Flu_Separator::VERTICAL ); + sep->box( FL_ENGRAVED_BOX ); + } + + previewBtn = new Flu_Button( 482, 33, 23, 25 ); + previewBtn->type( FL_TOGGLE_BUTTON ); + previewBtn->image( preview_img ); + previewBtn->callback( _previewCB, this ); + previewBtn->tooltip( "Preview files" ); + + { + Fl_Group *g = new Fl_Group( 511, 33, 81, 25 ); + fileListBtn = new Flu_Button( 511, 33, 25, 25 ); + fileListBtn->type( FL_RADIO_BUTTON ); + fileListBtn->value(1); + fileListBtn->callback( reloadCB, this ); + fileListBtn->image( file_list_img ); + fileListBtn->tooltip( "List mode" ); + fileListWideBtn = new Flu_Button( 540, 33, 25, 25 ); + fileListWideBtn->type( FL_RADIO_BUTTON ); + fileListWideBtn->callback( reloadCB, this ); + fileListWideBtn->image( file_listwide_img ); + fileListWideBtn->tooltip( "Wide List mode" ); + fileDetailsBtn = new Flu_Button( 569, 33, 25, 25 ); + fileDetailsBtn->type( FL_RADIO_BUTTON ); + fileDetailsBtn->image( fileDetails ); + fileDetailsBtn->callback( reloadCB, this ); + fileDetailsBtn->tooltip( "Detail mode" ); + g->end(); + } + + hiddenFiles = new Fl_Check_Button( 110, 33, 130, 25, "Show Hidden Files" ); + hiddenFiles->callback( reloadCB, this ); +#ifdef WIN32 + hiddenFiles->hide(); +#endif + + g->resizable( hiddenFiles ); + g->end(); + + dummy->resizable( filesystems ); + dummy->end(); + + //////////////////////////////////////////////////////////////// + + previewTile = new PreviewTile( 110, 60, w()-110-5, h()-80-40-5, this ); + fileGroup = new Fl_Group( 110, 60, w()-120-5, h()-80-40-5 ); + { + fileGroup->box( FL_DOWN_FRAME ); + filelist = new FileList( fileGroup->x()+2, fileGroup->y()+2, fileGroup->w()-4, fileGroup->h()-4, this ); + filelist->box( FL_FLAT_BOX ); + filelist->color( FL_WHITE ); + filelist->type( FL_HORIZONTAL ); + filelist->spacing( 4, 1 ); + filelist->scrollbar.linesize( DEFAULT_ENTRY_WIDTH+4 ); + filelist->end(); + + filecolumns = new FileColumns( fileGroup->x()+2, fileGroup->y()+2, fileGroup->w()-4, 20, this ); + filecolumns->hide(); + filescroll = new Fl_Scroll( fileGroup->x()+2, fileGroup->y()+22, fileGroup->w()-4, fileGroup->h()-20-4 ); + filescroll->color( FL_WHITE ); + filescroll->scrollbar.linesize( 20 ); + filescroll->box( FL_FLAT_BOX ); + filescroll->type( Fl_Scroll::VERTICAL ); + { + filedetails = new FileDetails( fileGroup->x()+2, fileGroup->y()+22, fileGroup->w()-4, fileGroup->h()-20-4, this ); + filedetails->end(); + } + filescroll->end(); + filescroll->hide(); + + fileGroup->resizable( filelist ); + } + fileGroup->end(); + + previewGroup = new PreviewGroup( fileGroup->x()+fileGroup->w(), fileGroup->y(), previewTile->w()-fileGroup->w(), fileGroup->h(), this ); + previewGroup->end(); + { + Fl_Box *b = new Fl_Box( previewTile->x()+250, previewTile->y(), previewTile->w()-350, previewTile->h() ); + previewTile->add_resizable( *b ); + } + previewTile->end(); + previewTile->position( previewGroup->x(), previewGroup->y(), previewTile->x()+previewTile->w(), previewGroup->y() ); + previewTile->last = previewTile->x()+previewTile->w()-200; + + resizable( previewTile ); + + filePattern = new Flu_Combo_List( 70, h()-30, w()-70-85-10, 25, "File types:" ); + filePattern->editable( false ); + filePattern->callback( reloadCB, this ); + + ok.callback( _okCB, this ); + cancel.callback( _cancelCB, this ); + + { + g = new Fl_Group( 0, h()-60, w(), 30 ); + g->end(); + g->add( filename ); + g->add( ok ); + g->resizable( filename ); + g = new Fl_Group( 0, h()-30, w(), 30 ); + g->end(); + g->add( filePattern ); + g->add( cancel ); + g->resizable( filePattern ); + } + + end(); + + FL_NORMAL_SIZE = oldNormalSize; + + char buf[1024]; + + // determine the user's home area for loading/storing favorites and transient config info +#ifdef WIN32 + { + LPTSTR lpszSystemInfo; // pointer to system information string + DWORD cchBuff = 256; // size of user name + TCHAR tchBuffer[UNLEN + 1]; // buffer for expanded string + + lpszSystemInfo = tchBuffer; + + // Get the user name. + GetUserName(lpszSystemInfo, &cchBuff); + userHome = "C:/Documents and Settings/"; + userHome += lpszSystemInfo; + userHome += "/"; + } +#else + fl_filename_expand( buf, 1024, "~/" ); + userHome = buf; +#endif + configFilename = userHome + ".Flu_File_Chooser.favorites"; + + int neww, newh; + // try to load the favorites + { + FILE *f = fopen( configFilename.c_str(), "r" ); + //printf( "load: %s %X\n", buf, f ); + if( f ) + { + fscanf(f, "%d, %d\n", &neww, &newh); + buf[0] = '\0'; + while( !feof(f) ) + { + fgets( buf, 1024, f ); + char *newline = strrchr( buf, '\n' ); + if( newline ) + *newline = '\0'; + if( strlen( buf ) > 0 ) + { + // eliminate duplicates + bool duplicate = false; + for( int i = 1; i <= favoritesList->size(); i++ ) + { + if( streq( buf, favoritesList->text(i) ) ) + { + duplicate = true; + break; + } + } + if( !duplicate ) + favoritesList->add( buf ); + } + } + fclose( f ); + } + } + + if( !imgTxtPreview ) + { + imgTxtPreview = new ImgTxtPreview(); + add_preview_handler( imgTxtPreview ); + } + + pattern( pat ); + default_file_icon( &default_file ); + cd( NULL ); // prime with the current directory + clear_history(); + cd( pathname ); + resize(x(), y(), neww, newh); +} + +Flu_File_Chooser :: ~Flu_File_Chooser() +{ + int i; + FILE *f = fopen( configFilename.c_str(), "w" ); + if( f ) + { + fprintf( f, "%d, %d\n", w(), h()); + for( i = 1; i <= favoritesList->size(); i++ ) + fprintf( f, "%s\n", favoritesList->text(i) ); + fclose( f ); + } + + Fl::remove_timeout( Entry::_editCB ); + + filelist->clear(); + filedetails->clear(); + + clear_history(); +} + +void Flu_File_Chooser :: cancelCB() +{ + filename.value(""); + filename.position( filename.size(), filename.size() ); + unselect_all(); + hide(); +} + +void Flu_File_Chooser :: pattern( const char *p ) +{ + int count = 0; + + // just like in Fl_File_Chooser, we accept tab, |, and ; delimited strings like this: + // "Description (patterns)" or just "patterns" where patterns is + // of the form *.xxx or *.{xxx,yyy,zzz}} + + rawPattern = p; + + // clear out the old + filePattern->list.clear(); + filePattern->input.value( "" ); + patterns.clear(); + + if( p == 0 ) + p = "*"; + else if( p[0] == '\0' ) + p = "*"; + + FluSimpleString pat = p, pattern; + + bool addedAll = false; + const char *next = strtok( (char*)pat.c_str(), "\t|;" ); + const char *start; + while( next ) + { + //printf( "next pattern = %s\n", next ); + + if( next[0] == '\0' ) + break; + + // eat whitespace + while( isspace( *next ) ) + next++; + + // degenerate check + if( strcmp( next, "*" ) == 0 ) + { + addedAll = true; + filePattern->list.add( "All Files (*)" ); + patterns.add( "*" ); + next = strtok( NULL, "\t|;" ); + count++; + continue; + } + + // extract the patterns from the substring + if( next[0] != '*' ) // starts with description + { + // the pattern starts after the first '(' + start = strchr( next, '(' ); + if( !start ) // error: couldn't find the '(' + { + next = strtok( NULL, "\t|;" ); + continue; + } + start++; // skip the '(' + } + else + start = next; + + if( start[0] != '*' ) + { + next = strtok( NULL, "\t|;" ); + continue; + } + start++; // skip the '*' + + if( start[0] != '.' ) + { + next = strtok( NULL, "\t|;" ); + continue; + } + start++; // skip the '.' + + if( start[0] == '{' ) + { + // the pattern is between '{' and '}' + pattern = start+1; + } + else + pattern = start; + + // remove the last '}' + int brace = pattern.find( '}' ); + if( brace != -1 ) + pattern[brace] = '\0'; + + // remove the last ')' + int paren = pattern.find( ')' ); + if( paren != -1 ) + pattern[paren] = '\0'; + + //printf( "patterns: %s\n", pattern.c_str() ); + if( pattern.size() ) + { + // add the whole string to the list + filePattern->list.add( next ); + patterns.add( pattern ); + count++; + } + + // advance to the pattern token + next = strtok( NULL, "\t|;" ); + } + + // add all files + if( !addedAll ) + { + filePattern->list.add( "All Files (*)" ); + patterns.add( "*" ); + count++; + } + + // choose the first added item + filePattern->value( filePattern->list.text(1) ); + if (count * 35 < 250) + filePattern->pop_height(count * 35); +} + +int Flu_File_Chooser :: handle( int event ) +{ + if( Fl_Double_Window::handle( event ) ) + return 1; + else if( event == FL_KEYDOWN && Fl::event_key(FL_Escape) ) + { + cancel.do_callback(); + return 1; + } + else + return 0; +} + +void Flu_File_Chooser :: newFolderCB() +{ + // start with the name "New Folder". while the name exists, keep appending a number (1..2..etc) + FluSimpleString newName = "New Folder", path = currentDir + newName; + int count = 1; + int i; + for(;;) + { + bool found = false; + // see if any entry already has that name + Fl_Group *g = getEntryGroup(); + for( i = 0; i < g->children(); i++ ) + { + if( ((Entry*)g->child(i))->filename == newName ) + { + found = true; + break; + } + } + + // since an entry already exists, change the name and try again + if( found ) + { + char buf[16]; + sprintf( buf, "%d", count++ ); + newName = "New Folder" + FluSimpleString(buf); + path = currentDir + newName; + } + else + break; + } + + // try to create the folder +#ifdef WIN32 + if( _mkdir( path.c_str() ) != 0 ) +#else + if( mkdir( path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ) != 0 ) +#endif + { + fl_alert( "Could not create directory '%s'. You may not have permission to perform this operation.", + newName.c_str() ); + return; + } + + // create a new entry with the name of the new folder. add to either the list or the details + Entry *entry = new Entry( newName.c_str(), ENTRY_DIR, fileDetailsBtn->value(), this ); + if( !fileDetailsBtn->value() ) + filelist->add( *entry ); + else + filedetails->add( *entry ); + + // switch that entry to input mode and scroll the browser to it + entry->editMode = 2; + entry->value( entry->filename.c_str() ); + entry->take_focus(); + entry->position( 0, entry->filename.size() ); + if( !fileDetailsBtn->value() ) + filelist->scroll_to( entry ); + else + filedetails->scroll_to( entry ); + entry->redraw(); +} + +void Flu_File_Chooser :: recursiveScan( const char *dir, StringVector *files ) +{ + dirent **e; + char *name; + FluSimpleString fullpath; + int num = fl_filename_list( dir, &e ); + for( int i = 0; i < num; i++ ) + { + name = e[i]->d_name; + + // if 'name' ends in '/' or '\', remove it + if( name[strlen(name)-1] == '/' || name[strlen(name)-1] == '\\' ) + name[strlen(name)-1] = '\0'; + + // ignore the "." and ".." names + if( strcmp( name, "." ) == 0 || strcmp( name, ".." ) == 0 ) + continue; + + // file or directory? + fullpath = dir; + fullpath += "/"; + fullpath += name; + if( fl_filename_isdir( fullpath.c_str() ) != 0 ) + recursiveScan( fullpath.c_str(), files ); + + files->add( fullpath ); + } + files->add( dir ); +} + +void Flu_File_Chooser :: trashCB( int recycle ) +{ + // linux doesn't have a recycle bin +#ifndef WIN32 + recycle = false; +#endif + + bool inFavorites = ( currentDir == FAVORITES_UNIQUE_STRING ); + if( inFavorites ) + recycle = false; + + // see how many files are selected + FluSimpleString name; + int selected = 0; + int i; + const char *first = ""; + Fl_Group *g = getEntryGroup(); + for( i = 0; i < g->children(); i++ ) + { + if( ((Entry*)g->child(i))->selected ) + { + if( selected == 0 ) + first = ((Entry*)g->child(i))->filename.c_str(); + selected++; + } + } + + if( selected ) + { + if( selected == 1 ) + { + if( recycle ) + { + if( !fl_ask( "Really send '%s' to the Recycle Bin?", first ) ) + return; + } + else + { + if( !fl_ask( "Really delete '%s'?", first ) ) + return; + } + } + else + { + if( recycle ) + { + if( !fl_ask( "Really send these %d files to the Recycle Bin?", selected ) ) + return; + } + else + { + if( !fl_ask( "Really delete these %d files?", selected ) ) + return; + } + } + + if( inFavorites ) + { + for( i = 0; i < g->children(); ) + { + Entry *e = ((Entry*)g->child(i)); + if( e->selected ) + { + favoritesList->remove(i+1); + g->remove( *e ); + delete e; + } + else + i++; + } + // save the favorites + FILE *f = fopen( configFilename.c_str(), "w" ); + if( f ) + { + fprintf( f, "%d, %d\n", w(), h()); + for( i = 1; i <= favoritesList->size(); i++ ) + fprintf( f, "%s\n", favoritesList->text(i) ); + fclose( f ); + } + cd( FAVORITES_UNIQUE_STRING ); + return; + } + +#ifdef WIN32 + SHFILEOPSTRUCT fileop; + memset( &fileop, 0, sizeof(SHFILEOPSTRUCT) ); + fileop.fFlags = FOF_SILENT | FOF_NOERRORUI | FOF_NOCONFIRMATION; + if( recycle ) + fileop.fFlags |= FOF_ALLOWUNDO; + fileop.wFunc = FO_DELETE; + fileop.pTo = NULL; +#endif + + for( i = 0; i < g->children(); i++ ) + { + if( ((Entry*)g->child(i))->selected ) + { + int result = 0; + + name = currentDir + ((Entry*)g->child(i))->filename; + + // if directory, recursively remove + if( ((Entry*)g->child(i))->type == ENTRY_DIR ) + { + // if we are recycling in windows, then the recursive part happens automatically +#ifdef WIN32 + if( !recycle ) +#endif + { + Fl_Group::current(0); + Fl_Window *win = new Fl_Window( 200, 100, "Notice" ); + Flu_Label *label = new Flu_Label( 30, 30, 150, 30, "Preparing to delete..." ); + win->end(); + win->show(); + Fl::check(); + // recursively build a list of all files that will be deleted + StringVector files; + recursiveScan( name.c_str(), &files ); + // delete all the files + label->label( "Deleting files..." ); + for( unsigned int i = 0; i < files.size(); i++ ) + { + //printf( "%s\n", files[i].c_str() ); + if( ::remove( files[i].c_str() ) != 0 ) + { + win->hide(); + delete win; + cd( "./" ); + return; + } + } + win->hide(); + delete win; + Fl::check(); + continue; + } + } + +#ifdef WIN32 + // this moves files to the recycle bin, depending on the value of 'recycle' + { + int len = name.size(); + char *buf = (char*)malloc( len+2 ); + strcpy( buf, name.c_str() ); + buf[len+1] = '\0'; // have to have 2 '\0' at the end + fileop.pFrom = buf; + result = SHFileOperation( &fileop ); + free( buf ); + } +#else + result = ::remove( name.c_str() ); +#endif + + // if remove fails, report an error + if( result != 0 ) + { + fl_alert( "An error ocurred while trying to delete '%s'.", name.c_str() ); + cd( "./" ); + return; + } + } + } + + // refresh this directory + cd( "./" ); + } +} + +void Flu_File_Chooser :: filesystemsCB( const char *path ) +{ + //printf( "filesystems: %s\n", path ); +#ifdef WIN32 + FluSimpleString p = path; + if( p == "/Favorites/" ) + favoritesCB(); + else if( p == "/Desktop/My Computer/" ) + myComputerCB(); + else if( p == "/Desktop/My Documents/" ) + documentsCB(); + else if( p == "/Desktop/" ) + desktopCB(); + // if the path leads off with "/Desktop/My Computer", then strip that part off and cd + // to the remaining + else if( strstr( path, "/Desktop/My Computer/" ) == path ) + { + // seach for '(' and if present, extract the drive name and cd to it + const char *paren = strrchr( path, '(' ); + if( paren ) + { + char drive[] = "A:/"; + drive[0] = paren[1]; + cd( drive ); + } + else + { + cd( path+21 ); + } + } +#else + cd( path ); +#endif +} + +void Flu_File_Chooser :: favoritesCB() +{ + cd( FAVORITES_UNIQUE_STRING ); +} + +void Flu_File_Chooser :: myComputerCB() +{ + cd( "/" ); +} + +void Flu_File_Chooser :: documentsCB() +{ +#ifdef WIN32 + FluSimpleString s = userHome + "My Documents"; + cd( s.c_str() ); +#else + cd( "/tmp/" ); +#endif +} + +Flu_File_Chooser :: FileInput :: FileInput( int x, int y, int w, int h, const char *l, Flu_File_Chooser *c ) + : Fl_Input( x, y, w, h, l ) +{ + chooser = c; +} + +Flu_File_Chooser :: FileInput :: ~FileInput() +{ +} + +int Flu_File_Chooser :: FileInput :: handle( int event ) +{ + if( event == FL_KEYDOWN ) + { + if( Fl::event_key(FL_Tab) ) + { + chooser->filenameTabCallback = true; + FluSimpleString v(value()); +#ifdef WIN32 + // turn "c:" into "c:\" + if( v.size() >= 2 ) + if( v[1] == ':' && v[2] == '\0' ) + { + v += "/"; + value( v.c_str() ); + position( size(), size() ); + } +#endif + chooser->delayedCd = v + "*"; + Fl::add_timeout( 0.0f, Flu_File_Chooser::delayedCdCB, chooser ); + return 1; + } + else if( Fl::event_key(FL_Left) || Fl::event_key(FL_Right) ) + return 1; + else if( Fl::event_key(FL_Up) || Fl::event_key(FL_Down) ) + // TODO add a command 'history' like in a shell + return 1; + } + + return Fl_Input::handle( event ); +} + +Flu_File_Chooser :: PreviewTile :: PreviewTile( int x, int y, int w, int h, Flu_File_Chooser *c ) + : Fl_Tile( x, y, w, h ) +{ + chooser = c; +} + +int Flu_File_Chooser :: PreviewTile :: handle( int event ) +{ + // if we're not in preview mode, then the user isn't allowed to resize the tile + if( !chooser->previewBtn->value() ) + return Fl_Group::handle( event ); + if( event == FL_DRAG ) + { + // the user is probably dragging to resize the columns + // update the sizes for each entry + chooser->updateEntrySizes(); + chooser->redraw(); + } + return Fl_Tile::handle(event); +} + +Flu_File_Chooser :: PreviewWidgetBase :: PreviewWidgetBase() + : Fl_Group( 0, 0, 0, 0 ) +{ +} + +Flu_File_Chooser :: PreviewWidgetBase :: ~PreviewWidgetBase() +{ +} + +Flu_File_Chooser :: PreviewGroup :: PreviewGroup( int x, int y, int w, int h, Flu_File_Chooser *c ) + : Fl_Group( x, y, w, h ) +{ + box( FL_DOWN_BOX ); + align( FL_ALIGN_CENTER | FL_ALIGN_CLIP ); + labelsize( 60 ); + labelfont( FL_HELVETICA ); + chooser = c; + handled = 0; +} + +void Flu_File_Chooser :: PreviewGroup :: draw() +{ + if( !chooser->previewBtn->value() ) + return; + + if( file.size() == 0 ) + return; + + FILE *f = fopen( file.c_str(), "rb" ); + if( !f ) + { + label( "" ); + Fl_Group::draw(); + return; + } + fclose( f ); + + if( lastFile != file ) + { + lastFile = file; + + handled = 0; + PreviewWidgetBase *next; + for( int i = chooser->previewHandlers.size()-1; i >= 0; i-- ) + { + next = chooser->previewHandlers[i]; + next->hide(); + if( !handled ) + { + Fl_Group *p = next->parent(); + Fl_Group::add( next ); + if( next->preview( file.c_str() ) != 0 ) + { + next->show(); + handled = next; + } + Fl_Group::remove( *next ); + if( p ) + p->add( next ); + } + } + } + + if( handled == 0 ) + { + label( "?" ); + Fl_Group::draw(); + } + else + { + label( "" ); + Fl_Group *p = handled->parent(); + Fl_Group::add( handled ); + handled->resize( x()+Fl::box_dx(box()), y()+Fl::box_dy(box()), + w()-Fl::box_dw(box()), h()-Fl::box_dh(box()) ); + Fl_Group::draw(); + Fl_Group::remove( *handled ); + if( p ) + p->add( handled ); + } +} + +// adapted from Fl_File_Chooser2.cxx : update_preview() +int Flu_File_Chooser :: ImgTxtPreview :: preview( const char *filename ) +{ + Fl_Shared_Image *img, // New image + *oldimg; // Old image + int pbw, pbh; // Width and height of preview box + int w, h; // Width and height of preview image + + window()->cursor( FL_CURSOR_WAIT ); + Fl::check(); + + img = Fl_Shared_Image::get( filename ); + if( img ) + { + window()->cursor( FL_CURSOR_DEFAULT ); + Fl::check(); + } + + oldimg = (Fl_Shared_Image*)image(); + if( oldimg ) + oldimg->release(); + image(0); + + if( !img ) + { + // Try reading the first 1k of data for a label... + FILE *f = fopen( filename, "rb" ); + if( f ) + { + int bytes = fread( previewTxt, 1, sizeof(previewTxt) - 1, f ); + previewTxt[bytes] = '\0'; + fclose( f ); + } + else + return 0; + + window()->cursor( FL_CURSOR_DEFAULT ); + Fl::check(); + + // Scan the buffer for printable chars... + unsigned char *ptr; + for( ptr = previewTxt; *ptr && (isprint(*ptr) || isspace(*ptr)); ptr++ ); + + if( *ptr || ptr == previewTxt ) + { + // Non-printable file - can't handle + return 0; + } + else + { + // Show the first 1k of text... + label( (const char*)previewTxt ); + align((Fl_Align)(FL_ALIGN_CLIP | FL_ALIGN_INSIDE | FL_ALIGN_LEFT | FL_ALIGN_TOP)); + labelsize( 12 ); + labelfont( FL_COURIER ); + } + } + else if( img->w() > 0 && img->h() > 0 ) + { + + pbw = this->w() - 20; + pbh = this->h() - 20; + pbw = (pbw < 10) ? 10 : pbw; + pbh = (pbh < 10) ? 10 : pbh; + + if( img->w() > pbw || img->h() > pbh ) + { + w = pbw; + h = int(float(w*img->h()) / float(img->w())); + + if( h > pbh ) + { + h = pbh; + w = int(float(h*img->w()) / float(img->h())); + } + + oldimg = (Fl_Shared_Image *)img->copy(w, h); + image((Fl_Image *)oldimg); + + img->release(); + } + else + image((Fl_Image *)img); + + align( FL_ALIGN_CLIP ); + label(0); + } + + redraw(); + + return 1; +} + +void Flu_File_Chooser :: previewCB() +{ + if( previewBtn->value() ) + { + fileGroup->resize( fileGroup->x(), fileGroup->y(), previewTile->last-fileGroup->x(), fileGroup->h() ); + previewGroup->resize( previewTile->last, previewGroup->y(), previewTile->w()-fileGroup->w(), previewGroup->h() ); + previewGroup->show(); + } + else + { + previewTile->last = previewGroup->x(); + fileGroup->resize( fileGroup->x(), fileGroup->y(), previewTile->w(), fileGroup->h() ); + previewGroup->resize( previewTile->x()+previewTile->w(), previewGroup->y(), 0, previewGroup->h() ); + previewGroup->hide(); + } + previewGroup->redraw(); + previewTile->init_sizes(); + filescroll->parent()->init_sizes(); + updateEntrySizes(); + redraw(); +} + +void Flu_File_Chooser :: sortCB( Fl_Widget *w ) +{ + // if the sort method is already selected, toggle the REVERSE bit + if( w == detailNameBtn ) + { + if( sortMethod & SORT_NAME ) + sortMethod ^= SORT_REVERSE; + else + sortMethod = SORT_NAME; + } + else if( w == detailSizeBtn ) + { + if( sortMethod & SORT_SIZE ) + sortMethod ^= SORT_REVERSE; + else + sortMethod = SORT_SIZE; + } + else if( w == detailDateBtn ) + { + if( sortMethod & SORT_DATE ) + sortMethod ^= SORT_REVERSE; + else + sortMethod = SORT_DATE; + } + else if( w == detailTypeBtn ) + { + if( sortMethod & SORT_TYPE ) + sortMethod ^= SORT_REVERSE; + else + sortMethod = SORT_TYPE; + } + + int reverse = ( sortMethod & SORT_REVERSE ); + detailNameBtn->label( "Name" ); + detailSizeBtn->label( "Size" ); + detailDateBtn->label( "Date" ); + detailTypeBtn->label( "Type" ); + switch( sortMethod & ~SORT_REVERSE ) + { + case SORT_NAME: detailNameBtn->label( reverse?"@-12DnArrow Name":"@-18UpArrow Name" ); break; + case SORT_SIZE: detailSizeBtn->label( reverse?"@-12DnArrow Size":"@-18UpArrow Size" ); break; + case SORT_DATE: detailDateBtn->label( reverse?"@-12DnArrow Date":"@-18UpArrow Date" ); break; + case SORT_TYPE: detailTypeBtn->label( reverse?"@-12DnArrow Type":"@-18UpArrow Type" ); break; + } + + filelist->sort(); + filedetails->sort(); +} + +Flu_File_Chooser :: CBTile :: CBTile( int x, int y, int w, int h, Flu_File_Chooser *c ) + : Fl_Tile( x, y, w, h ) +{ + chooser = c; +} + +int Flu_File_Chooser :: CBTile :: handle( int event ) +{ + if( event == FL_DRAG ) + { + // the user is probably dragging to resize the columns + // update the sizes for each entry + chooser->updateEntrySizes(); + chooser->redraw(); + } + return Fl_Tile::handle(event); +} + +Flu_File_Chooser :: FileColumns :: FileColumns( int x, int y, int w, int h, Flu_File_Chooser *c ) + : Fl_Tile( x, y, w, h ) +{ + chooser = c; + + W1 = int(float(w)*0.35f); + W2 = int(float(w)*0.20f); + W3 = int(float(w)*0.15f); + W4 = w-W1-W2-W3; + + Fl_Box *box = new Fl_Box( x+50, y, w-200, h ); + add_resizable( *box ); + c->detailNameBtn = new Flu_Button( x, y, W1, h, "Name" ); + c->detailNameBtn->align( FL_ALIGN_CLIP ); + c->detailNameBtn->callback( Flu_File_Chooser::_sortCB, c ); + { + CBTile *tile = new CBTile( x+W1, y, W2+W3+W4, h, c ); + Fl_Box *box = new Fl_Box( tile->x()+50, tile->y(), tile->w()-150, tile->h() ); + tile->add_resizable( *box ); + c->detailTypeBtn = new Flu_Button( x+W1, y, W2, h, "Type" ); + c->detailTypeBtn->align( FL_ALIGN_CLIP ); + c->detailTypeBtn->callback( Flu_File_Chooser::_sortCB, c ); + { + CBTile *tile = new CBTile( x+W1+W2, y, W3+W4, h, c ); + Fl_Box *box = new Fl_Box( tile->x()+50, tile->y(), tile->w()-100, tile->h() ); + tile->add_resizable( *box ); + c->detailSizeBtn = new Flu_Button( x+W1+W2, y, W3, h, "Size" ); + c->detailSizeBtn->align( FL_ALIGN_CLIP ); + c->detailSizeBtn->callback( Flu_File_Chooser::_sortCB, c ); + c->detailDateBtn = new Flu_Button( x+W1+W2+W3, y, W4, h, "Date" ); + c->detailDateBtn->align( FL_ALIGN_CLIP ); + c->detailDateBtn->callback( Flu_File_Chooser::_sortCB, c ); + tile->end(); + } + tile->end(); + } + end(); +} + +Flu_File_Chooser :: FileColumns :: ~FileColumns() +{ +} + +void Flu_File_Chooser :: FileColumns :: resize( int x, int y, int w, int h ) +{ + // TODO resize the buttons/tiles according to their stored relative sizes + Fl_Tile::resize( x, y, w, h ); +} + +int Flu_File_Chooser :: FileColumns :: handle( int event ) +{ + if( event == FL_DRAG ) + { + // the user is probably dragging to resize the columns + // update the sizes for each entry + chooser->updateEntrySizes(); + chooser->redraw(); + } + return Fl_Tile::handle(event); +} + +void Flu_File_Chooser :: filenameCB() +{ + filenameEnterCallback = true; + cd( filename.value() ); +} + +inline int _isProbablyAPattern( const char *s ) +{ + return( strpbrk( s, "*;|[]?" ) != NULL ); +} + +void Flu_File_Chooser :: okCB() +{ + // only hide if the filename is not blank or the user is choosing directories, + // in which case use the current directory + + //printf( "%s\n", filename.value() ); + + if( selectionType & DIRECTORY ) + { +#ifdef WIN32 + if( strcmp( filename.value(), "My Computer" ) == 0 ) + return; +#endif + if( !(selectionType & MULTI )) + { + if( strlen( filename.value() ) != 0 ) + cd( filename.value() ); + filename.value( currentDir.c_str() ); + filename.position( filename.size(), filename.size() ); + } + hide(); + } + else + { + if( strlen( filename.value() ) != 0 ) + { + if( _isProbablyAPattern( filename.value() ) ) + { + cd( filename.value() ); + return; + } +#ifdef WIN32 + if( filename.value()[1] == ':' ) +#else + if( filename.value()[0] == '/' ) +#endif + if( fl_filename_isdir( filename.value() ) ) + { + filename.value( "" ); + return; + } + // prepend the path + FluSimpleString path = currentDir + filename.value(); + filename.value( path.c_str() ); + filename.position( filename.size(), filename.size() ); + hide(); + } + } +} + +void Flu_File_Chooser :: homeCB() +{ +#ifdef WIN32 + cd( "/" ); +#else + cd( userHome.c_str() ); +#endif +} + +void Flu_File_Chooser :: desktopCB() +{ +#ifdef WIN32 + FluSimpleString s = "/Desktop"; +#else + FluSimpleString s = userHome + "Desktop"; +#endif + cd( s.c_str() ); +} + +#define QSCANL( field ) \ + while( ((Flu_File_Chooser::Entry*)array[left])->field < \ + ((Flu_File_Chooser::Entry*)array[pivot])->field ) left++ +#define QSCANR( field ) \ + while( ((Flu_File_Chooser::Entry*)array[right])->field > \ + ((Flu_File_Chooser::Entry*)array[pivot])->field ) right-- + +#define RQSCANL( field ) \ + while( ((Flu_File_Chooser::Entry*)array[left])->field > \ + ((Flu_File_Chooser::Entry*)array[pivot])->field ) left++ +#define RQSCANR( field ) \ + while( ((Flu_File_Chooser::Entry*)array[right])->field < \ + ((Flu_File_Chooser::Entry*)array[pivot])->field ) right-- + +#define CASE_QSCANL( field ) \ + while( casecompare( ((Flu_File_Chooser::Entry*)array[left])->field, \ + ((Flu_File_Chooser::Entry*)array[pivot])->field ) < 0 ) left++ +#define CASE_QSCANR( field ) \ + while( casecompare( ((Flu_File_Chooser::Entry*)array[right])->field, \ + ((Flu_File_Chooser::Entry*)array[pivot])->field ) > 0 ) right-- + +#define CASE_RQSCANL( field ) \ + while( casecompare( ((Flu_File_Chooser::Entry*)array[left])->field, \ + ((Flu_File_Chooser::Entry*)array[pivot])->field ) > 0 ) left++ +#define CASE_RQSCANR( field ) \ + while( casecompare( ((Flu_File_Chooser::Entry*)array[right])->field, \ + ((Flu_File_Chooser::Entry*)array[pivot])->field ) < 0 ) right-- + +#define CUSTOM_QSCANL( field ) \ + while( customSort( ((Flu_File_Chooser::Entry*)array[left])->field, \ + ((Flu_File_Chooser::Entry*)array[pivot])->field ) < 0 ) left++ +#define CUSTOM_QSCANR( field ) \ + while( customSort( ((Flu_File_Chooser::Entry*)array[right])->field, \ + ((Flu_File_Chooser::Entry*)array[pivot])->field ) > 0 ) right-- + +#define CUSTOM_RQSCANL( field ) \ + while( customSort( ((Flu_File_Chooser::Entry*)array[left])->field, \ + ((Flu_File_Chooser::Entry*)array[pivot])->field ) > 0 ) left++ +#define CUSTOM_RQSCANR( field ) \ + while( customSort( ((Flu_File_Chooser::Entry*)array[right])->field, \ + ((Flu_File_Chooser::Entry*)array[pivot])->field ) < 0 ) right-- + +void Flu_File_Chooser :: _qSort( int how, int caseSort, Fl_Widget **array, int low, int high ) +{ + int left, right, pivot; + Fl_Widget *temp; + int reverse = ( how & SORT_REVERSE ); + + if( high > low ) + { + left = low; + right = high; + pivot = low; + + while( right >= left ) + { + switch( how & ~SORT_REVERSE ) + { + case SORT_NAME: + if( reverse ) + { + if( customSort ) + { + CUSTOM_RQSCANL( filename.c_str() ); + CUSTOM_RQSCANR( filename.c_str() ); + } + else if( !caseSort ) + { + CASE_RQSCANL( filename ); + CASE_RQSCANR( filename ); + } + else + { + RQSCANL( filename ); + RQSCANR( filename ); + } + } + else + { + if( customSort ) + { + CUSTOM_QSCANL( filename.c_str() ); + CUSTOM_QSCANR( filename.c_str() ); + } + else if( !caseSort ) + { + CASE_QSCANL( filename ); + CASE_QSCANR( filename ); + } + else + { + QSCANL( filename ); + QSCANR( filename ); + } + } + break; + case SORT_SIZE: + if( reverse ) + { + RQSCANL( isize ); + RQSCANR( isize ); + } + else + { + QSCANL( isize ); + QSCANR( isize ); + } + break; + case SORT_DATE: + if( reverse ) + { + RQSCANL( idate ); + RQSCANR( idate ); + } + else + { + QSCANL( idate ); + QSCANR( idate ); + } + break; + case SORT_TYPE: + if( reverse ) + { + RQSCANL( description ); + RQSCANR( description ); + } + else + { + QSCANL( description ); + QSCANR( description ); + } + break; + } + + if( left > right ) + break; + + temp = array[left]; + array[left] = array[right]; + array[right] = temp; + left++; + right--; + } + + _qSort( how, caseSort, array, low, right ); + _qSort( how, caseSort, array, left, high ); + } +} + +Flu_File_Chooser :: FileList :: FileList( int x, int y, int w, int h, Flu_File_Chooser *c ) + : Flu_Wrap_Group( x, y, w, h ) +{ + chooser = c; +} + +Flu_File_Chooser :: FileList :: ~FileList() +{ +} + +void Flu_File_Chooser :: FileList :: sort( int n ) +{ + if( n != -1 ) + numDirs = n; + if( children() == 0 ) + return; + // the directories are already first. sort the directories then the names lexigraphically + //if( chooser->sortMethod & Flu_File_Chooser::SORT_NAME ) + Flu_File_Chooser::_qSort( chooser->sortMethod, chooser->caseSort, (Fl_Widget**)array(), 0, numDirs-1 ); + Flu_File_Chooser::_qSort( chooser->sortMethod, chooser->caseSort, (Fl_Widget**)array(), numDirs, children()-1 ); + chooser->redraw(); +} + +int Flu_File_Chooser :: FileList :: handle( int event ) +{ + if( Flu_Wrap_Group::handle( event ) ) + return 1; + // if push on no file, unselect all files and turn off editing mode + else if( event == FL_PUSH && !Fl::event_key( FL_SHIFT ) && !Fl::event_key( FL_CTRL ) ) + { + chooser->unselect_all(); + chooser->filename.value( "" ); + chooser->filename.position( chooser->filename.size(), chooser->filename.size() ); + + if( Fl::event_button3() ) + return chooser->popupContextMenu( NULL ); + + return 1; + } + else if( event == FL_KEYDOWN && Fl::event_key( FL_Delete ) ) + { + // recycle by default, unless the shift key is held down + chooser->trashCB( !Fl::event_state( FL_SHIFT ) ); + return 1; + } + else + return 0; +} + +Flu_File_Chooser :: FileDetails :: FileDetails( int x, int y, int w, int h, Flu_File_Chooser *c ) + : Fl_Pack( x, y, w, h ) +{ + chooser = c; +} + +Flu_File_Chooser :: FileDetails :: ~FileDetails() +{ +} + +void Flu_File_Chooser :: FileDetails :: scroll_to( Fl_Widget *w ) +{ + // we know all the widgets are the same height + // so just find this widget and scroll to the accumulated height + int H = 0; + for( int i = 0; i < children(); i++ ) + { + if( child(i) == w ) + { + if( H > (int)chooser->filescroll->scrollbar.maximum() ) + H = (int)chooser->filescroll->scrollbar.maximum(); + chooser->filescroll->position( 0, H ); + return; + } + H += w->h(); + } +} + +void Flu_File_Chooser :: FileDetails :: sort( int n ) +{ + if( n != -1 ) + numDirs = n; + if( children() == 0 ) + return; + // the directories are already first. sort the directories then the names lexigraphically + //if( chooser->sortMethod & Flu_File_Chooser::SORT_NAME ) + Flu_File_Chooser::_qSort( chooser->sortMethod, chooser->caseSort, (Fl_Widget**)array(), 0, numDirs-1 ); + Flu_File_Chooser::_qSort( chooser->sortMethod, chooser->caseSort, (Fl_Widget**)array(), numDirs, children()-1 ); + chooser->redraw(); +} + +int Flu_File_Chooser :: FileDetails :: handle( int event ) +{ + if( Fl_Pack::handle( event ) ) + return 1; + else if( event == FL_PUSH ) + return 1; + else + return 0; +} + +Flu_File_Chooser :: Entry :: Entry( const char* name, int t, int d, Flu_File_Chooser *c ) + : Fl_Input( 0, 0, 0, 0 ) +{ + resize( 0, 0, DEFAULT_ENTRY_WIDTH, 20 ); + labelsize( 12 ); + textsize( 12 ); + box( FL_BORDER_BOX ); + when( FL_WHEN_RELEASE_ALWAYS | FL_WHEN_ENTER_KEY_ALWAYS ); + callback( _inputCB, this ); + filename = name; + selected = false; + chooser = c; + details = d; + type = t; + icon = NULL; + editMode = 0; + description = ""; + + updateSize(); + updateIcon(); +} + +void Flu_File_Chooser :: Entry :: updateIcon() +{ + Flu_File_Chooser::FileTypeInfo *tt = NULL; + if( type==ENTRY_MYCOMPUTER ) + { + icon = &computer; + description = "My Computer"; + } + else if( type==ENTRY_MYDOCUMENTS ) + { + icon = &documents; + description = "My Documents"; + } + else if( type==ENTRY_DRIVE ) + { + //icon = &disk_drive; + //description = ""; + } + else if( type==ENTRY_DIR || type==ENTRY_FAVORITE ) + tt = Flu_File_Chooser::find_type( NULL ); + else + { + const char *dot = strrchr( filename.c_str(), '.' ); + if( dot ) + { + tt = Flu_File_Chooser::find_type( dot+1 ); + if( !tt ) + description = dot+1; + } + } + if( tt ) + { + icon = tt->icon; + description = tt->type; + } + // if there is no icon, assign a default one + if( !icon && type==ENTRY_FILE ) + icon = chooser->defaultFileIcon; + if( type==ENTRY_FAVORITE ) + icon = &little_favorites; + + toolTip = "Name: " + filename; + if( type == ENTRY_FILE ) + toolTip += "\nSize: " + filesize; + toolTip += "\nType: " + description; + tooltip( toolTip.c_str() ); + + redraw(); +} + +void Flu_File_Chooser :: resize( int x, int y, int w, int h ) +{ + Fl_Double_Window::resize( x, y, w, h ); + if( fileListWideBtn->value() ) + filelist->scrollbar.linesize( filelist->w() ); + else if( fileListBtn->value() ) + filelist->scrollbar.linesize( DEFAULT_ENTRY_WIDTH+4 ); + for( int i = 0; i < filelist->children(); i++ ) + ((Entry*)filelist->child(i))->updateSize(); +} + +void Flu_File_Chooser :: Entry :: updateSize() +{ + if( type==ENTRY_FAVORITE || chooser->fileListWideBtn->value() ) + { + resize( x(), y(), chooser->filelist->w()-4, 20 ); + } + + if( details ) + { + nameW = chooser->detailNameBtn->w(); + typeW = chooser->detailTypeBtn->w(); + sizeW = chooser->detailSizeBtn->w(); + dateW = chooser->detailDateBtn->w(); + resize( x(), y(), chooser->filedetails->w(), 20 ); + } + else + nameW = w(); + + // how big is the icon? + int iW = 0, iH = 0; + if( icon ) + { + iW = icon->w()+2; + iH = icon->h(); + } + + fl_font( labelfont(), labelsize() ); + + // measure the name and see if we need a truncated version + int W = 0, H = 0; + fl_measure( filename.c_str(), W, H ); + if( W > nameW-iW ) + { + // progressively strip characters off the end of the name until + // it fits with "..." at the end + if( altname[0] != '\0' ) + shortname = altname; + else + shortname = filename; + int len = shortname.size(); + while( W > (nameW-iW) && len > 3 ) + { + shortname[len-3] = '.'; + shortname[len-2] = '.'; + shortname[len-1] = '.'; + shortname[len] = '\0'; + len--; + W = 0; + fl_measure( shortname.c_str(), W, H ); + } + } + else + shortname = ""; + + // measure the description and see if we need a truncated version + shortDescription = ""; + if( details ) + { + W = 0; H = 0; + fl_measure( description.c_str(), W, H ); + if( W > typeW-4 ) + { + // progressively strip characters off the end of the description until + // it fits with "..." at the end + shortDescription = description; + int len = shortDescription.size(); + while( W > typeW-4 && len > 3 ) + { + shortDescription[len-3] = '.'; + shortDescription[len-2] = '.'; + shortDescription[len-1] = '.'; + shortDescription[len] = '\0'; + len--; + W = 0; + fl_measure( shortDescription.c_str(), W, H ); + } + } + } + + redraw(); +} + +Flu_File_Chooser :: Entry :: ~Entry() +{ +} + +void Flu_File_Chooser :: Entry :: inputCB() +{ + redraw(); + + // if the user tried to change the string to nothing, restore the original name and turn off edit mode + if( strlen( value() ) == 0 ) + { + editMode = 0; + return; + } + + // if input text is different from filename, try to change the filename + if( strcmp( value(), filename.c_str() ) != 0 ) + { + // build the total old filename and new filename + FluSimpleString oldName = chooser->currentDir + filename, + newName = chooser->currentDir + value(); + // see if new name already exists + struct stat s; + int result = ::stat( newName.c_str(), &s ); + if( result == 0 ) + { + fl_alert( "File '%s' already exists!", newName.c_str() ); + return; // leave editing on + } + + if( rename( oldName.c_str(), newName.c_str() ) == -1 ) + { + fl_alert( "Unable to rename '%s' to '%s'", oldName.c_str(), newName.c_str() ); + //return; // leave editing on + } + else + { + filename = value(); + updateSize(); + updateIcon(); + } + // QUESTION: should we set the chooser filename to the modified name? + //chooser->filename.value( filename.c_str() ); + } + + // only turn off editing if we have a successful name change + editMode = 0; +} + +Fl_Group* Flu_File_Chooser :: getEntryGroup() +{ + return (!fileDetailsBtn->value() || currentDir == FAVORITES_UNIQUE_STRING ) ? &(filelist->group) : filedetails; +} + +int Flu_File_Chooser :: Entry :: handle( int event ) +{ + if( editMode ) + { + // if user hits 'Escape' while in edit mode, restore the original name and turn off edit mode + if( event == FL_KEYDOWN && Fl::event_key( FL_Escape ) ) + { + editMode = 0; + redraw(); + if( selected ) + chooser->trashBtn->activate(); + return 1; + } + return Fl_Input::handle( event ); + } + + if( event == FL_FOCUS || event == FL_UNFOCUS ) + return 1; + + if( event == FL_ENTER || event == FL_LEAVE ) + return 1; + + Fl_Group *g = chooser->getEntryGroup(); + if( event == FL_PUSH ) + { + if( Fl::event_clicks() > 0 ) + { + Fl::event_clicks(0); + // double-clicking a favorite cd's to it + if( type == ENTRY_FAVORITE ) + { + chooser->delayedCd = filename; + Fl::add_timeout( 0.0f, Flu_File_Chooser::delayedCdCB, chooser ); + } + // double-clicking a directory cd's to it + else if( type != ENTRY_FILE ) + { +#ifdef WIN32 + if( filename[1] == ':' ) + chooser->delayedCd = filename; + else +#endif + chooser->delayedCd = chooser->currentDir + filename + "/"; + Fl::add_timeout( 0.0f, Flu_File_Chooser::delayedCdCB, chooser ); + } + // double-clicking a file chooses it if we are in file selection mode + else if( (chooser->selectionType & DIRECTORY) == 0 ) + { + // prepend the path + FluSimpleString path = chooser->currentDir + filename; + chooser->filename.value( path.c_str() ); + //chooser->filename.value( filename.c_str() ); + chooser->filename.position( chooser->filename.size(), chooser->filename.size() ); + Fl::add_timeout( 0.0f, Flu_File_Chooser::selectCB, chooser ); + } + if( selected ) + chooser->trashBtn->activate(); + return 1; + } + + if( selected && !Fl::event_button3() && !Fl::event_state(FL_CTRL) && !Fl::event_state(FL_SHIFT) ) + { + // only allow editing of certain files and directories + if( chooser->fileEditing && ( type == ENTRY_FILE || type == ENTRY_DIR ) ) + { + // if already selected, switch to input mode + Fl::add_timeout( 1.0, _editCB, this ); + return 1; + } + } + + else if( chooser->selectionType & MULTI ) + { + if( Fl::event_state(FL_CTRL) ) + { + selected = !selected; // toggle this item + chooser->lastSelected = this; + if( type == ENTRY_FILE ) + chooser->previewGroup->file = chooser->currentDir + filename; + chooser->redraw(); + } + else if( Fl::event_state(FL_SHIFT) ) + { + // toggle all items from the last selected item to this one + if( chooser->lastSelected == NULL ) + { + selected = true; + chooser->lastSelected = this; + if( type == ENTRY_FILE ) + chooser->previewGroup->file = chooser->currentDir + filename; + chooser->redraw(); + } + else + { + // get the index of the last selected item and this item + int lastindex = -1, thisindex = -1; + int i; + for( i = 0; i < g->children(); i++ ) + { + if( g->child(i) == chooser->lastSelected ) + lastindex = i; + if( g->child(i) == this ) + thisindex = i; + if( lastindex >= 0 && thisindex >= 0 ) + break; + } + if( lastindex >= 0 && thisindex >= 0 ) + { + // loop from this item to the last item, toggling each item except the last + int inc; + if( thisindex > lastindex ) + inc = -1; + else + inc = 1; + Entry *e; + for( i = thisindex; i != lastindex; i += inc ) + { + e = (Entry*)g->child(i); + e->selected = !e->selected; + e->redraw(); + } + chooser->lastSelected = this; + if( type == ENTRY_FILE ) + chooser->previewGroup->file = chooser->currentDir + filename; + chooser->redraw(); + } + } + } + else + { + chooser->unselect_all(); + selected = true; + chooser->lastSelected = this; + if( type == ENTRY_FILE ) + chooser->previewGroup->file = chooser->currentDir + filename; + chooser->redraw(); + } + } + else + { + chooser->unselect_all(); + selected = true; + chooser->lastSelected = this; + if( type == ENTRY_FILE ) + chooser->previewGroup->file = chooser->currentDir + filename; + chooser->redraw(); + } + + g->take_focus(); + + redraw(); + if( selected ) + chooser->trashBtn->activate(); + + if( Fl::event_button3() ) + return chooser->popupContextMenu( this ); + + // don't put the filename into the box if we are directory but we are not choosing directories + if( (chooser->selectionType & Flu_File_Chooser::DIRECTORY) || type==ENTRY_FILE ) + chooser->filename.value( filename.c_str() ); + else + chooser->filename.value( "" ); + chooser->filename.position( chooser->filename.size(), chooser->filename.size() ); + + return 1; + } + else if( event == FL_DRAG ) + { + if( chooser->selectionType & MULTI ) + { + // toggle all items from the last selected item to this one + if( chooser->lastSelected != NULL ) + { + selected = true; + // get the index of the last selected item and this item + int lastindex = -1, thisindex = -1; + int i; + for( i = 0; i < g->children(); i++ ) + { + if( g->child(i) == chooser->lastSelected ) + lastindex = i; + if( g->child(i) == this ) + thisindex = i; + if( lastindex >= 0 && thisindex >= 0 ) + break; + } + if( lastindex >= 0 && thisindex >= 0 ) + { + // loop from this item to the last item, toggling each item except the last + int inc; + if( thisindex > lastindex ) + inc = -1; + else + inc = 1; + Entry *e; + for( i = thisindex; i != lastindex; i += inc ) + { + e = (Entry*)g->child(i); + e->selected = !e->selected; + e->redraw(); + } + chooser->lastSelected = this; + if( type == ENTRY_FILE ) + chooser->previewGroup->file = chooser->currentDir + filename; + chooser->redraw(); + } + redraw(); + if( selected ) + chooser->trashBtn->activate(); + return 1; + } + } + } + return Fl_Widget::handle(event); +} + +void Flu_File_Chooser :: Entry :: editCB() +{ + // if already selected, switch to input mode + editMode = 2; + value( filename.c_str() ); + take_focus(); + position( 0, filename.size() ); + chooser->trashBtn->deactivate(); +} + +int Flu_File_Chooser :: popupContextMenu( Entry *entry ) +{ + int type = entry ? entry->type : ENTRY_NONE; + const char *filename = entry ? entry->filename.c_str() : NULL; + char *ext = NULL; + + if( filename ) + ext = (char *) strrchr( filename, '.' ); + if( ext ) + { + ext = strdup( ext+1 ); // skip the '.' + for( unsigned int i = 0; i < strlen(ext); i++ ) + ext[i] = tolower( ext[i] ); + } + + enum { ACTION_NEW_FOLDER = -1, ACTION_RENAME = -2, ACTION_DELETE = -3 }; + + entryPopup.clear(); + switch( type ) + { + case ENTRY_NONE: // right click on nothing + entryPopup.add( "New Folder", 0, 0, (void*)ACTION_NEW_FOLDER ); + break; + + case ENTRY_DIR: + entryPopup.add( "Rename", 0, 0, (void*)ACTION_RENAME ); + entryPopup.add( "Delete", 0, 0, (void*)ACTION_DELETE ); + break; + + case ENTRY_FILE: + entryPopup.add( "Rename", 0, 0, (void*)ACTION_RENAME ); + entryPopup.add( "Delete", 0, 0, (void*)ACTION_DELETE ); + break; + + case ENTRY_FAVORITE: + entryPopup.add( "Delete", 0, 0, (void*)ACTION_DELETE ); + break; + + case ENTRY_DRIVE: + break; + + case ENTRY_MYDOCUMENTS: + break; + + case ENTRY_MYCOMPUTER: + break; + } + + // add the programmable context handlers + for( unsigned int i = 0; i < contextHandlers.size(); i++ ) + { + if( !(contextHandlers[i].type & type) ) + continue; + if( type == ENTRY_FILE ) + if( contextHandlers[i].ext.size() && contextHandlers[i].ext != ext ) + continue; + entryPopup.add( contextHandlers[i].name.c_str(), 0, 0, (void*)i ); + } + if( ext ) + free( ext ); + + entryPopup.position( Fl::event_x(), Fl::event_y() ); + const Fl_Menu_Item *selection = entryPopup.popup(); + if( selection ) + { + int handler = (int)selection->user_data(); + switch( handler ) + { + case ACTION_NEW_FOLDER: + newFolderCB(); + break; + case ACTION_RENAME: + entry->editMode = 2; + entry->value( entry->filename.c_str() ); + entry->take_focus(); + entry->position( 0, entry->filename.size() ); + trashBtn->deactivate(); + break; + case ACTION_DELETE: + // recycle by default, unless the shift key is held down + trashCB( !Fl::event_state( FL_SHIFT ) ); + break; + default: + contextHandlers[handler].callback( filename, type, contextHandlers[handler].callbackData ); + break; + } + } + else + return handle( FL_PUSH ); + return 1; +} + +void Flu_File_Chooser :: Entry :: draw() +{ + if( editMode ) + { + if( editMode == 2 ) + { + editMode--; + fl_draw_box( FL_FLAT_BOX, x(), y(), w(), h(), FL_WHITE ); + redraw(); + } + Fl_Input::draw(); + return; + } + + if( selected ) + { + fl_draw_box( FL_FLAT_BOX, x(), y(), w(), h(), FL_SELECTION_COLOR ); + fl_color( FL_WHITE ); + } + else + { + fl_draw_box( FL_FLAT_BOX, x(), y(), w(), h(), FL_WHITE ); + fl_color( FL_BLACK ); + } + + int X = x()+4; + if( icon ) + { + icon->draw( X, y()+h()/2-icon->h()/2 ); + X += icon->w()+2; + } + + fl_font( labelfont(), labelsize() ); + + if( shortname[0] != '\0' ) + fl_draw( shortname.c_str(), X, y(), nameW, h(), FL_ALIGN_LEFT ); + else if( altname[0] != '\0' ) + fl_draw( altname.c_str(), X, y(), nameW, h(), FL_ALIGN_LEFT ); + else + fl_draw( filename.c_str(), X, y(), nameW, h(), FL_ALIGN_LEFT ); + + X = x()+4 + nameW; + + if( details ) + { + if( shortDescription[0] != '\0' ) + fl_draw( shortDescription.c_str(), X, y(), typeW-4, h(), Fl_Align(FL_ALIGN_LEFT | FL_ALIGN_CLIP) ); + else + fl_draw( description.c_str(), X, y(), typeW-4, h(), Fl_Align(FL_ALIGN_LEFT | FL_ALIGN_CLIP) ); + + X += typeW; + + fl_draw( filesize.c_str(), X, y(), sizeW-4, h(), Fl_Align(FL_ALIGN_RIGHT | FL_ALIGN_CLIP) ); + + X += sizeW+4; + + fl_draw( date.c_str(), X, y(), dateW-4, h(), Fl_Align(FL_ALIGN_LEFT | FL_ALIGN_CLIP) ); + } +} + +void Flu_File_Chooser :: unselect_all() +{ + Fl_Group *g = getEntryGroup(); + Entry *e; + for( int i = 0; i < g->children(); i++ ) + { + e = ((Entry*)g->child(i)); + e->selected = false; + e->editMode = 0; + } + lastSelected = 0; + previewGroup->file = ""; + previewGroup->redraw(); + trashBtn->deactivate(); + redraw(); +} + +void Flu_File_Chooser :: updateEntrySizes() +{ + filecolumns->W1 = detailNameBtn->w(); + filecolumns->W2 = detailTypeBtn->w(); + filecolumns->W3 = detailSizeBtn->w(); + filecolumns->W4 = detailDateBtn->w(); + + // update the size of each entry because the user changed the size of each column + filedetails->resize( filedetails->x(), filedetails->y(), filescroll->w(), filedetails->h() ); + for( int i = 0; i < filedetails->children(); i++ ) + ((Entry*)filedetails->child(i))->updateSize(); +} + +const char* Flu_File_Chooser :: value() +{ + if( filename.size() == 0 ) + return NULL; + else + return filename.value(); +} + +int Flu_File_Chooser :: count() +{ + if( selectionType & MULTI ) + { + int n = 0; + Fl_Group *g = getEntryGroup(); + for( int i = 0; i < g->children(); i++ ) + { +#ifdef WIN32 + if( ((Entry*)g->child(i))->filename == "My Computer" ) + continue; +#endif + if( ((Entry*)g->child(i))->selected ) + n++; + } + return n; + } + else + return (strlen(filename.value())==0)? 0 : 1; +} + +void Flu_File_Chooser :: value( const char *v ) +{ + cd( v ); + if( !v ) + return; + // try to find the file and select it + const char *slash = strrchr( v, '/' ); + if( slash ) + slash++; + else + { + slash = strrchr( v, '\\' ); + if( slash ) + slash++; + else + slash = v; + } + filename.value( slash ); + filename.position( filename.size(), filename.size() ); + Fl_Group *g = getEntryGroup(); + for( int i = 0; i < g->children(); i++ ) + { + if( ((Entry*)g->child(i))->filename == slash ) + { + ((Entry*)g->child(i))->selected = true; + filelist->scroll_to( (Entry*)g->child(i) ); + filedetails->scroll_to( (Entry*)g->child(i) ); + redraw(); + return; + } + } +} + +const char* Flu_File_Chooser :: value( int n ) +{ + Fl_Group *g = getEntryGroup(); + for( int i = 0; i < g->children(); i++ ) + { +#ifdef WIN32 + if( ((Entry*)g->child(i))->filename == "My Computer" ) + continue; +#endif + if( ((Entry*)g->child(i))->selected ) + { + if( n == 0 ) + { + FluSimpleString s = currentDir + ((Entry*)g->child(i))->filename; + filename.value( s.c_str() ); + filename.position( filename.size(), filename.size() ); + return value(); + } + n--; + } + } + return ""; +} + +void Flu_File_Chooser :: reloadCB() +{ +#ifdef WIN32 + refreshDrives = true; +#endif + cd( currentDir.c_str() ); +} + +void Flu_File_Chooser :: addToFavoritesCB() +{ + // eliminate duplicates + bool duplicate = false; + for( int i = 1; i <= favoritesList->size(); i++ ) + { + if( streq( currentDir.c_str(), favoritesList->text(i) ) ) + { + duplicate = true; + break; + } + } + if( !duplicate ) + favoritesList->add( currentDir.c_str() ); + + // save the favorites + FILE *f = fopen( configFilename.c_str(), "w" ); + if( f ) + { + fprintf( f, "%d, %d\n", w(), h()); + for( int i = 1; i <= favoritesList->size(); i++ ) + fprintf( f, "%s\n", favoritesList->text(i) ); + fclose( f ); + } +} + +FluSimpleString Flu_File_Chooser :: formatDate( const char *d ) +{ + // convert style "Wed Mar 19 07:23:11 2003" to "MM/DD/YY HH:MM AM|PM" + + int month, day, year, hour, minute, second; + bool pm; + char MM[16], dummy[64]; + + sscanf( d, "%s %s %d %d:%d:%d %d", dummy, MM, &day, &hour, &minute, &second, &year ); + + pm = ( hour >= 12 ); + if( hour == 0 ) + hour = 12; + if( hour >= 13 ) + hour -= 12; + + if( strcmp(MM,"Jan")==0 ) month = 1; + else if( strcmp(MM,"Feb")==0 ) month = 2; + else if( strcmp(MM,"Mar")==0 ) month = 3; + else if( strcmp(MM,"Apr")==0 ) month = 4; + else if( strcmp(MM,"May")==0 ) month = 5; + else if( strcmp(MM,"Jun")==0 ) month = 6; + else if( strcmp(MM,"Jul")==0 ) month = 7; + else if( strcmp(MM,"Aug")==0 ) month = 8; + else if( strcmp(MM,"Sep")==0 ) month = 9; + else if( strcmp(MM,"Oct")==0 ) month = 10; + else if( strcmp(MM,"Nov")==0 ) month = 11; + else month = 12; + + sprintf( dummy, "%d/%d/%02d %d:%02d %s", month, day, year, hour, minute, pm?"PM":"AM" ); + + FluSimpleString formatted = dummy; + + return formatted; +} + +void Flu_File_Chooser :: win2unix( FluSimpleString &s ) +{ + int len = s.size(); + for( int i = 0; i < len; i++ ) + if( s[i] == '\\' ) + s[i] = '/'; +} + +void Flu_File_Chooser :: cleanupPath( FluSimpleString &s ) +{ + // convert all '\' to '/' + win2unix( s ); + + FluSimpleString newS(s.size()+1); + + int oldPos, newPos; + for( oldPos = 0, newPos = 0; oldPos < s.size(); oldPos++ ) + { + // remove "./" + if( s[oldPos] == '.' && s[oldPos+1] == '/' ) + oldPos += 2; + + // convert "//" to "/" + else if( s[oldPos] == '/' && s[oldPos+1] == '/' ) + oldPos++; + +#ifdef WIN32 + // upcase "c:" to "C:" + else if( s[oldPos+1] == ':' ) + s[oldPos] = toupper( s[oldPos] ); +#endif + + // remove "../" by removing everything back to the last "/" + if( oldPos+2 < s.size() ) // bounds check + { + if( s[oldPos] == '.' && s[oldPos+1] == '.' && s[oldPos+2] == '/' && newS != "/" ) + { + // erase the last character, which should be a '/' + newPos--; + newS[newPos] = '\0'; + // look for the previous '/' + char *lastSlash = (char *) strrchr( newS.c_str(), '/' ); + // make the new string position after the slash + newPos = (lastSlash-newS.c_str())+1; + oldPos += 3; + } + } + + newS[newPos] = s[oldPos]; + newPos++; + } + + newS[newPos] = '\0'; + s = newS; +} + +int Flu_File_Chooser :: correctPath( FluSimpleString &path ) +{ + // the path may or may not be an alias, needing corrected +#ifdef WIN32 + // point to the correct desktop + if( path == "/Desktop/" || path == "/Desktop" ) + { + path = userHome + "Desktop"; + return true; + } + else if( path == userHome+"Desktop" || path == userHome+"Desktop/" ) + return true; + else if( path == "/Desktop/My Computer/" || path == "/Desktop/My Computer" || + path == userHome+"Desktop/My Computer/" || path == userHome+"Desktop/My Computer" ) + path = "/"; + else if( path == "/Desktop/My Documents/" || path == "/Desktop/My Documents" || + path == userHome+"Desktop/My Documents/" || path == userHome+"Desktop/My Documents" ) + path = userHome + "My Documents"; +#endif + return false; +} + +void Flu_File_Chooser :: backCB() +{ + if( !currentHist ) return; + if( currentHist->last ) + { + currentHist = currentHist->last; + walkingHistory = true; + delayedCd = currentHist->path; + Fl::add_timeout( 0.0f, Flu_File_Chooser::delayedCdCB, this ); + } +} + +void Flu_File_Chooser :: forwardCB() +{ + if( !currentHist ) return; + if( currentHist->next ) + { + currentHist = currentHist->next; + walkingHistory = true; + delayedCd = currentHist->path; + Fl::add_timeout( 0.0f, Flu_File_Chooser::delayedCdCB, this ); + } +} + +void Flu_File_Chooser :: buildFilesystemsCombo() +{ + // add all filesystems + filesystems->tree.clear(); + +#ifdef WIN32 + char volumeName[1024]; + Flu_Tree_Browser::Node *n; + n = filesystems->tree.add( "Desktop/" ); n->branch_icon( &little_desktop ); + n = filesystems->tree.add( "Desktop/My Documents/" ); n->branch_icon( &documents ); + n = filesystems->tree.add( "Desktop/My Computer/" ); n->branch_icon( &computer ); + // get the filesystems and add them + { + if( refreshDrives ) + driveMask = ::_getdrives(); + DWORD mask = driveMask; + + for( int i = 0; i < 26; i++ ) + { + drives[i] = ""; + driveIcons[i] = &disk_drive; + if( mask & 1 ) + { + FluSimpleString s = "Desktop/My Computer/"; + char drive[] = "A:"; + char windrive[] = "A:\\"; + windrive[0] = drive[0] = 'A' + i; + DWORD dummy1, dummy2; + DWORD type; + if( refreshDrives ) + { + volumeName[0] = '\0'; + GetVolumeInformation( windrive, volumeName, 1024, NULL, &dummy1, &dummy2, NULL, 0 ); + type = driveTypes[i] = GetDriveType( windrive ); + volumeNames[i] = volumeName; + } + else + { + strncpy( volumeName, volumeNames[i].c_str(), 1024 ); + type = driveTypes[i]; + } + + //s += volume + const char *disk = "Disk"; + switch( type ) + { + case DRIVE_REMOVABLE: + disk = strlen(volumeName)?volumeName:"Floppy Disk"; + driveIcons[i] = &floppy_drive; + break; + case DRIVE_FIXED: + disk = strlen(volumeName)?volumeName:"Local Disk"; + //driveIcons[i] = &disk_drive; + break; + case DRIVE_CDROM: + disk = strlen(volumeName)?volumeName:"Compact Disk"; + driveIcons[i] = &cd_drive; + break; + case DRIVE_REMOTE: + disk = strlen(volumeName)?volumeName:"Network Disk"; + driveIcons[i] = &network_drive; + break; + case DRIVE_RAMDISK: + disk = strlen(volumeName)?volumeName:"RAM Disk"; + driveIcons[i] = &ram_drive; + break; + } + drives[i] = FluSimpleString(disk) + " (" + FluSimpleString(drive) + ")/"; + s += drives[i]; + n = filesystems->tree.add( s.c_str() ); n->branch_icon( driveIcons[i] ); + // erase the trailing '/' to make things look nicer + drives[i][ drives[i].size()-1 ] = '\0'; + } + mask >>= 1; + } + } + n = filesystems->tree.add( "Favorites/" ); n->branch_icon( &little_favorites ); + refreshDrives = false; + +#elif defined __APPLE__ + + filesystems->tree.label( "/" ); + + // get all volume mount points and add to the filesystems combobox + dirent **e; + char *name; + int num = fl_filename_list( "/Volumes/", &e ); + if( num > 0 ) + { + int i; + for( i = 0; i < num; i++ ) + { + name = e[i]->d_name; + + // ignore the "." and ".." names + if( strcmp( name, "." ) == 0 || strcmp( name, ".." ) == 0 || + strcmp( name, "./" ) == 0 || strcmp( name, "../" ) == 0 || + strcmp( name, ".\\" ) == 0 || strcmp( name, "..\\" ) == 0 ) + continue; + + // if 'name' ends in '/', remove it + if( name[strlen(name)-1] == '/' ) + name[strlen(name)-1] = '\0'; + + FluSimpleString fullpath = "/Volumes/"; + fullpath += name; + fullpath += "/"; + filesystems->tree.add( fullpath.c_str() ); + } + } + +#else + + filesystems->tree.label( "/" ); + + // get all mount points and add to the filesystems combobox + FILE *fstab; // /etc/mtab or /etc/mnttab file + char dummy[256], mountPoint[256], line[1024]; // Input line + FluSimpleString mount; + + fstab = fopen( "/etc/fstab", "r" ); // Otherwise fallback to full list + if( fstab ) + { + while( fgets( line, 1024, fstab ) ) + { + if( line[0] == '#' || line[0] == '\n' ) + continue; + + // in fstab, mount point is second full string + sscanf( line, "%s %s", dummy, mountPoint ); + mount = mountPoint; + + // cull some stuff + if( mount[0] != '/' ) continue; + if( mount == "/" ) continue; + if( mount == "/boot" ) continue; + if( mount == "/proc" ) continue; + + // now add the mount point + mount += "/"; + filesystems->tree.add( mount.c_str() ); + } + + fclose( fstab ); + } + +#endif +} + +void Flu_File_Chooser :: clear_history() +{ + currentHist = history; + while( currentHist ) + { + History *next = currentHist->next; + delete currentHist; + currentHist = next; + } + currentHist = history = NULL; + backBtn->deactivate(); + forwardBtn->deactivate(); +} + +void Flu_File_Chooser :: addToHistory() +{ + // remember history + // only store this path in the history if it is not the current directory + if( currentDir.size() && !walkingHistory ) + { + if( history == NULL ) + { + history = new History; + currentHist = history; + currentHist->path = currentDir; + } + else if( currentHist->path != currentDir ) + { + // since we are adding a new path, delete everything after this path + History *h = currentHist->next; + while( h ) + { + History *next = h->next; + delete h; + h = next; + } + currentHist->next = new History; + currentHist->next->last = currentHist; + currentHist = currentHist->next; + currentHist->path = currentDir; + } + History * h = history; + while( h ) + h = h->next; + } + walkingHistory = false; + + if( currentHist ) + { + if( currentHist->last ) + backBtn->activate(); + else + backBtn->deactivate(); + if( currentHist->next ) + forwardBtn->activate(); + else + forwardBtn->deactivate(); + } +} + +// treating the string as a '|' or ';' delimited sequence of patterns, strip them out and place in patterns +// return whether it is likely that "s" represents a regexp file-matching pattern +int Flu_File_Chooser :: stripPatterns( FluSimpleString s, StringVector* patterns ) +{ + if( s.size() == 0 ) + return false; + + char *tok = strtok( (char*)s.c_str(), "|;" ); + while( tok ) + { + patterns->add( tok ); + tok = strtok( NULL, "|;" ); + } + + return _isProbablyAPattern( s.c_str() ); +} + +void Flu_File_Chooser :: cd( const char *localpath ) +{ + Entry *entry; + char cwd[1024]; + + if( !localpath || localpath[0] == '\0' ) + { + localpath = path; + if( !localpath ) + localpath = "./"; + } + + lastSelected = 0; + previewGroup->file = ""; + previewGroup->redraw(); + + filelist->scroll_to_beginning(); + filescroll->position( 0, 0 ); + + bool listMode = !fileDetailsBtn->value() || streq( localpath, FAVORITES_UNIQUE_STRING ); + +#ifdef WIN32 + // refresh the drives if viewing "My Computer" + if( strcmp( localpath, "/" ) == 0 ) + refreshDrives = true; +#endif + buildFilesystemsCombo(); + + filename.take_focus(); + + trashBtn->deactivate(); + reloadBtn->activate(); + newDirBtn->activate(); + previewBtn->activate(); + hiddenFiles->activate(); + addFavoriteBtn->activate(); + + resize( x(), y(), w(), h() ); + if( listMode ) + { + filecolumns->hide(); + filescroll->hide(); + filelist->show(); + filelist->parent()->resizable( filelist ); + } + else + { + filelist->hide(); + filecolumns->show(); + filescroll->show(); + filescroll->parent()->resizable( filescroll ); + updateEntrySizes(); + } + + FluSimpleString currentFile = filename.value(); + filescroll->position( 0, 0 ); + Fl::focus( &filename ); + upDirBtn->activate(); + ok.activate(); + + // check for favorites + if( streq( localpath, FAVORITES_UNIQUE_STRING ) ) + { + currentDir = FAVORITES_UNIQUE_STRING; + addToHistory(); + + newDirBtn->deactivate(); + previewBtn->deactivate(); + reloadBtn->deactivate(); + addFavoriteBtn->deactivate(); + hiddenFiles->deactivate(); + filesystems->input.value( "Favorites" ); + + filelist->clear(); + filedetails->clear(); + if( listMode ) + filelist->begin(); + else + filedetails->begin(); + for( int i = 1; i <= favoritesList->size(); i++ ) + { + entry = new Entry( favoritesList->text(i), ENTRY_FAVORITE, false/*fileDetailsBtn->value()*/, this ); + entry->updateSize(); + entry->updateIcon(); + } + if( listMode ) + filelist->end(); + else + filedetails->end(); + + redraw(); + ok.deactivate(); + return; + } + // check for the current directory + else if( streq( localpath, "." ) || streq( localpath, "./" ) || streq( localpath, ".\\" ) ) + { + // do nothing. just rescan this directory + } + // check for parent directory + else if( streq( localpath, ".." ) || streq( localpath, "../" ) || streq( localpath, "..\\" ) ) + { + // if we are viewing the favorites and want to go back a directory, go to the previous directory + if( currentDir == FAVORITES_UNIQUE_STRING ) + { + backCB(); + return; + } +#ifdef WIN32 + // if we are at the desktop already, then we cannot go back any further + if( currentDir == "/Desktop/" || currentDir == "/Desktop" ) + { + // do nothing + } + else if( currentDir == userHome+"Desktop" || currentDir == userHome+"Desktop/" ) + currentDir = userHome; + // if we are viewing "My Computer" and want to go back a directory, go to the desktop + else if( currentDir == "/" ) + currentDir = userHome + "Desktop"; + // if we are at a top level drive, go to "My Computer" (i.e. "/") + else if( currentDir[1] == ':' && currentDir[3] == '\0' ) + currentDir = "/"; + else +#else + // if the current directory is already as far back as we can go, ignore + if( currentDir != "/" ) +#endif + { + // strip everything off the end to the next "/" + int end = currentDir.size()-1; + currentDir[end] = '\0'; + while( currentDir[end] != '/' ) + { + currentDir[end] = '\0'; + end--; + } + } + } + // check for absolute path +#ifdef WIN32 + else if( localpath[1] == ':' || localpath[0] == '/' ) +#else + else if( localpath[0] == '/' ) +#endif + { + currentDir = localpath; + } + // else relative path + else + { + // concatenate currentDir with path to make an absolute path + currentDir += localpath; + } + + int numDirs = 0, numFiles = 0; + filelist->clear(); + filedetails->clear(); + + cleanupPath( currentDir ); + +#ifdef WIN32 + bool isTopDesktop = ( currentDir == "/Desktop" || currentDir == "/Desktop/" ); + int isDesktop = correctPath( currentDir ); + if( isTopDesktop ) + upDirBtn->deactivate(); +#else + correctPath( currentDir ); + if( currentDir == "/" ) + upDirBtn->deactivate(); +#endif + +#ifdef WIN32 + bool root = false; + // check for my computer + if( currentDir == "/" ) + { + ok.deactivate(); + root = true; + if( listMode ) + filelist->begin(); + else + filedetails->begin(); + for( int i = 0; i < 26; i++ ) + { + if( drives[i][0] != '\0' ) + { + char drive[] = "A:/"; + drive[0] = 'A' + i; + entry = new Entry( drive, ENTRY_DRIVE, fileDetailsBtn->value(), this ); + switch( driveTypes[i] ) + { + case DRIVE_REMOVABLE: entry->description = "Floppy Disk"; break; + case DRIVE_FIXED: entry->description = "Local Disk"; break; + case DRIVE_CDROM: entry->description = "Compact Disk"; break; + case DRIVE_REMOTE: entry->description = "Network Disk"; break; + case DRIVE_RAMDISK: entry->description = "RAM Disk"; break; + } + entry->icon = driveIcons[i]; + entry->altname = drives[i]; + entry->updateSize(); + entry->updateIcon(); + } + } + if( listMode ) + filelist->end(); + else + filedetails->end(); + + redraw(); + } + // check for desktop. if so, add My Computer and My Documents + else if( isDesktop ) + { + if( listMode ) + filelist->begin(); + else + filedetails->begin(); + entry = new Entry( "My Documents", ENTRY_MYDOCUMENTS, fileDetailsBtn->value(), this ); + entry->updateSize(); + entry->updateIcon(); + entry = new Entry( "My Computer", ENTRY_MYCOMPUTER, fileDetailsBtn->value(), this ); + entry->updateSize(); + entry->updateIcon(); + if( listMode ) + filelist->end(); + else + filedetails->end(); + numDirs += 2; + } +#endif + + // see if currentDir is in fact a directory + // if so, make sure there is a trailing "/" and we're done + if( fl_filename_isdir( currentDir.c_str() ) || currentDir=="/" ) + { + if( currentDir[strlen(currentDir.c_str())-1] != '/' ) + currentDir += "/"; +#ifdef WIN32 + if( filename.value()[1] != ':' ) +#else + if( filename.value()[0] != '/' ) +#endif + filename.value( "" ); + currentFile = ""; + } + + // now we have the current directory and possibly a file at the end + // try to split into path and file + if( currentDir[currentDir.size()-1] != '/' ) + { + char *lastSlash = (char *) strrchr( currentDir.c_str(), '/' ); + if( lastSlash ) + { + currentFile = lastSlash+1; + lastSlash[1] = '\0'; + } + } + // make sure currentDir ends in '/' + if( currentDir[currentDir.size()-1] != '/' ) + currentDir += "/"; + +#ifdef WIN32 + { + FluSimpleString tmp = currentDir; + if( isTopDesktop ) + currentDir = "/Desktop/"; + addToHistory(); + if( isTopDesktop ) + currentDir = tmp; + } +#else + addToHistory(); +#endif + + delayedCd = "./"; + +#ifdef WIN32 + // set the filesystems input value + // check for drives + if( currentDir[1] == ':' && currentDir[3] == '\0' ) + { + filesystems->input.value( currentDir.c_str() ); + } + else if( currentDir == "/" ) + filesystems->input.value( "My Computer" ); + else +#endif + { + filesystems->input.value( currentDir.c_str() ); +#ifdef WIN32 + FluSimpleString treePath = "/Desktop/My Computer/" + currentDir; + Flu_Tree_Browser::Node *n = filesystems->tree.add( treePath.c_str() ); + if( currentDir == userHome + "Desktop/" ) + n->branch_icon( &little_desktop ); + if( currentDir == userHome + "My Documents/" ) + n->branch_icon( &documents ); +#else + filesystems->tree.add( currentDir.c_str() ); +#endif + } + +#ifdef WIN32 + if( root ) + return; +#endif + + FluSimpleString pathbase, fullpath; + bool isDir, isCurrentFile = false; + const char *lastAddedFile = NULL, *lastAddedDir = NULL; + + pathbase = currentDir; + + // take the current pattern and make a list of filter pattern strings + StringVector currentPatterns; + { + int val = filePattern->list.value(); + if (val < 1) + val = 1; + FluSimpleString pat = patterns[val-1]; + while( pat.size() ) + { + int p = pat.find( ',' ); + if( p == -1 ) + { + if( pat != "*" ) + pat = "*." + pat; + currentPatterns.add( pat ); + break; + } + else + { + FluSimpleString s = pat.c_str() + p + 1; + pat[p] = '\0'; + if( pat != "*" ) + pat = "*." + pat; + currentPatterns.add( pat ); + pat = s; + } + } + } + + // add any user-defined patterns + StringVector userPatterns; + //if( stripPatterns( currentFile, &userPatterns ) && !filenameTabCallback ) + //filename.value( "" ); + stripPatterns( currentFile, &userPatterns ); + + // read the directory + dirent **e; + char *name; + int num = fl_filename_list( pathbase.c_str(), &e ); + if( num > 0 ) + { + int i; + for( i = 0; i < num; i++ ) + { + name = e[i]->d_name; + + // ignore the "." and ".." names + if( strcmp( name, "." ) == 0 || strcmp( name, ".." ) == 0 || + strcmp( name, "./" ) == 0 || strcmp( name, "../" ) == 0 || + strcmp( name, ".\\" ) == 0 || strcmp( name, "..\\" ) == 0 ) + continue; + + // if 'name' ends in '/', remove it + if( name[strlen(name)-1] == '/' ) + name[strlen(name)-1] = '\0'; + + // file or directory? + fullpath = pathbase + name; + isDir = ( fl_filename_isdir( fullpath.c_str() ) != 0 ); + + // was this file specified explicitly? + isCurrentFile = ( currentFile == name ); + +#ifndef WIN32 + // filter hidden files + if( !isCurrentFile && !hiddenFiles->value() && ( name[0] == '.' ) ) + continue; +#endif + + if( /*!isDir &&*/ !isCurrentFile ) + { + // only directories? + if( (selectionType & DIRECTORY) && !isDir ) + continue; + + // filter according to the user pattern in the filename input + if( userPatterns.size() ) + { + bool cull = true; + for( unsigned int i = 0; i < userPatterns.size(); i++ ) + { + if( flu_filename_match( name, userPatterns[i].c_str() ) != 0 ) + { + cull = false; + break; + } + } + if( cull ) + { + // only filter directories if someone just hit + if( !isDir || ( isDir && filenameTabCallback ) ) + continue; + } + } + // filter files according to the current pattern + else + { + bool cull = true; + for( unsigned int i = 0; i < currentPatterns.size(); i++ ) + { + if( flu_filename_match( name, currentPatterns[i].c_str() ) != 0 ) + { + cull = false; + break; + } + } + if( cull ) + { + // only filter directories if someone just hit + if( !isDir || ( isDir && filenameTabCallback ) ) + continue; + } + } + } + + // add directories at the beginning, and files at the end + entry = new Entry( name, isDir?ENTRY_DIR:ENTRY_FILE, fileDetailsBtn->value(), this ); + if( isDir ) + { + if( listMode ) + filelist->insert( *entry, 0 ); + else + filedetails->insert( *entry, 0 ); + numDirs++; + lastAddedDir = entry->filename.c_str(); + } + else + { + if( listMode ) + filelist->add( entry ); + else + filedetails->add( entry ); + numFiles++; + lastAddedFile = entry->filename.c_str(); + } + + // get some information about the file + struct stat s; + ::stat( fullpath.c_str(), &s ); + + // store size as human readable and sortable integer + entry->isize = s.st_size; + if( isDir && entry->isize == 0 ) + entry->filesize = ""; + else + { + char buf[32]; + /* + if( (entry->isize >> 40) > 0 ) // terrabytes + { + double TB = double(entry->isize)/double(1<<40); + sprintf( buf, "%.1f TB", TB ); + } + */ + if( (entry->isize >> 30) > 0 ) // gigabytes + { + double GB = double(entry->isize)/double(1<<30); + sprintf( buf, "%.1f GB", GB ); + } + else if( (entry->isize >> 20) > 0 ) // megabytes + { + double MB = double(entry->isize)/double(1<<20); + sprintf( buf, "%.1f MB", MB ); + } + else if( (entry->isize >> 10) > 0 ) // kilabytes + { + double KB = double(entry->isize)/double(1<<10); + sprintf( buf, "%.1f KB", KB ); + } + else // bytes + { + sprintf( buf, "%d bytes", (int)entry->isize ); + } + entry->filesize = buf; + } + + // store date as human readable and sortable integer + entry->date = formatDate( ctime( &s.st_mtime ) );//ctime( &s.st_mtime ); + entry->idate = (int) s.st_mtime; + + // convert the permissions into UNIX style rwx-rwx-rwx (user-group-others) + /* + unsigned int p = s.st_mode; + entry->pU = bool(p&S_IRUSR)<<2 | bool(p&S_IWUSR)<<1 | bool(p&S_IXUSR); + entry->pG = bool(p&S_IRGRP)<<2 | bool(p&S_IWGRP)<<1 | bool(p&S_IXGRP); + entry->pO = bool(p&S_IROTH)<<2 | bool(p&S_IWOTH)<<1 | bool(p&S_IXOTH); + char* perms[8] = { "---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx" }; + entry->permissions = perms[entry->pU]; + entry->permissions += perms[entry->pG]; + entry->permissions += perms[entry->pO]; + */ + + entry->updateSize(); + entry->updateIcon(); + + if( isCurrentFile ) + { + filename.value( name ); + entry->selected = true; + lastSelected = entry; + if( entry->type == ENTRY_FILE ) + previewGroup->file = currentDir + name; + previewGroup->redraw(); + filelist->scroll_to( entry ); + filedetails->scroll_to( entry ); + break; + } + } + + for( i = 0; i < num; i++ ) + free((void*)(e[i])); + free((void*)e); + } + + // sort the files: directories first, then files + if( listMode ) + filelist->sort( numDirs ); + else + filedetails->sort( numDirs ); + + // see if the user pushed in the filename input field + if( filenameTabCallback ) + { + filenameTabCallback = false; + + FluSimpleString prefix = commonStr(); + + if( numDirs == 1 && + currentFile == (FluSimpleString(lastAddedDir)+"*") ) + { + delayedCd = lastAddedDir; + Fl::add_timeout( 0.0f, Flu_File_Chooser::delayedCdCB, this ); + } + + if( numDirs == 1 && numFiles == 0 ) + { +#ifdef WIN32 + if( filename.value()[1] == ':' ) +#else + if( filename.value()[0] == '/' ) +#endif + { + FluSimpleString s = currentDir + lastAddedDir + "/"; + filename.value( s.c_str() ); + } + else + filename.value( lastAddedDir ); + } + else if( numFiles == 1 && numDirs == 0 ) + { +#ifdef WIN32 + if( filename.value()[1] == ':' ) +#else + if( filename.value()[0] == '/' ) +#endif + { + FluSimpleString s = currentDir + lastAddedFile; + filename.value( s.c_str() ); + } + else + filename.value( lastAddedFile ); + } + else if( prefix.size() >= currentFile.size() ) + { +#ifdef WIN32 + if( filename.value()[1] == ':' ) +#else + if( filename.value()[0] == '/' ) +#endif + { + FluSimpleString s = currentDir + prefix; + filename.value( s.c_str() ); + } + else + filename.value( prefix.c_str() ); + } + + if( currentFile == "*" && +#ifdef WIN32 + filename.value()[1] != ':' ) +#else + filename.value()[0] != '/' ) +#endif + { + filename.value( "" ); + } + } + + // see if the user pushed in the filename input field + if( filenameEnterCallback ) + { + filenameEnterCallback = false; + +#ifdef WIN32 + if( filename.value()[1] == ':' ) +#else + if( filename.value()[0] == '/' ) +#endif + filename.value( "" ); + + //if( isCurrentFile && numFiles == 1 ) + if( !_isProbablyAPattern( filename.value() ) ) + okCB(); + } + + if( _isProbablyAPattern( filename.value() ) ) + filename.position( 0, filename.size() ); + else + filename.position( filename.size(), filename.size() ); + filename.take_focus(); + + redraw(); +} + +// find the prefix string that is common to all entries in the list +FluSimpleString Flu_File_Chooser :: commonStr() +{ + FluSimpleString common; + int index = 0; + const char* name; + int len, i; + Fl_Group *g = getEntryGroup(); + for(;;) + { + bool allSkipped = true; + for( i = 0; i < g->children(); i++ ) + { + name = ((Entry*)g->child(i))->filename.c_str(); + len = strlen( name ); + if( index >= len ) + continue; + allSkipped = false; + if( i == 0 ) + common.push_back( name[index] ); + else if( toupper(common[index]) != toupper(name[index]) ) + { + common[index] = '\0'; + return common; + } + } + if( allSkipped ) + break; + index++; + } + return common; +} + +const char* _flu_file_chooser( const char *message, const char *pattern, const char *filename, int type ) +{ + static Flu_File_Chooser *fc = NULL; + static FluSimpleString retname; + + if( !fc ) + { + fc = new Flu_File_Chooser( filename, pattern, type, message ); + } + else + { + fc->clear_history(); + fc->label( message ); + if( !filename || filename[0] == '\0' ) + { + if( (!pattern || !fc->filter() || strcmp(pattern,fc->filter())) && fc->value() ) + { + // if pattern is different, remove name but leave old directory: + retname = fc->value(); + char *p = (char *) strrchr( retname.c_str(), '/' ); + if( p ) + { + // If the filename is "/foo", then the directory will be "/", not "" + if( p == retname.c_str() ) + retname[1] = '\0'; + else + p[1] = '\0'; + } + } + fc->filter( pattern ); + fc->value( retname.c_str() ); + } + else + { + fc->filter( pattern ); + fc->value( filename ); + } + } + + fc->set_modal(); + fc->show(); + + while( fc->shown() ) + Fl::wait(); + + if( fc->value() ) + { + retname = fc->value(); + return retname.c_str(); + } + else + return 0; +} + +const char* flu_file_chooser( const char *message, const char *pattern, const char *filename ) +{ + return _flu_file_chooser( message, pattern, filename, Flu_File_Chooser::SINGLE ); +} + +const char* flu_dir_chooser( const char *message, const char *filename ) +{ + return _flu_file_chooser( message, "*", filename, Flu_File_Chooser::DIRECTORY ); +} diff --git a/src/Flu_Label.cpp b/src/Flu_Label.cpp new file mode 100644 index 0000000..a1f1b20 --- /dev/null +++ b/src/Flu_Label.cpp @@ -0,0 +1,50 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#include "FLU/Flu_Label.h" + +Flu_Label :: Flu_Label( int x, int y, int w, int h, const char* l ) + : Fl_Box( x, y, w, h, 0 ) +{ + align( FL_ALIGN_LEFT | FL_ALIGN_INSIDE ); + _label = NULL; + label( l ); + //box( FL_FLAT_BOX ); + box( FL_NO_BOX ); +} + +Flu_Label :: ~Flu_Label() +{ + if( _label ) + delete[] _label; +} + +void Flu_Label :: label( const char* l ) +{ + if( _label ) + delete[] _label; + if( l == NULL ) + { + _label = new char[1]; + _label[0] = '\0'; + } + else + { + _label = new char[strlen(l)+1]; + strcpy( _label, l ); + } + Fl_Box::label( _label ); + redraw(); +} diff --git a/src/Flu_Return_Button.cpp b/src/Flu_Return_Button.cpp new file mode 100644 index 0000000..89db642 --- /dev/null +++ b/src/Flu_Return_Button.cpp @@ -0,0 +1,26 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#include "FLU/Flu_Return_Button.h" + +Flu_Return_Button :: Flu_Return_Button( int X,int Y,int W,int H,const char *l ) + : Flu_Button( X,Y,W,H,l ) +{ + retBtn = true; +} + +Flu_Return_Button :: ~Flu_Return_Button() +{ +} diff --git a/src/Flu_Separator.cpp b/src/Flu_Separator.cpp new file mode 100644 index 0000000..6b160fa --- /dev/null +++ b/src/Flu_Separator.cpp @@ -0,0 +1,31 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#include "FLU/Flu_Separator.h" + +Flu_Separator :: Flu_Separator( int X, int Y, int W, int H, const char *l ) + : Fl_Widget( X, Y, W, H, l ) +{ + type( HORIZONTAL ); + box( FL_EMBOSSED_BOX ); +} + +void Flu_Separator :: draw() +{ + if( _type == HORIZONTAL ) + draw_box( box(), x()+3, y()+h()/2, w()-6, 2, color() ); + else + draw_box( box(), x()+w()/2, y()+3, 2, h()-6, color() ); +} diff --git a/src/Flu_Tree_Browser.cpp b/src/Flu_Tree_Browser.cpp index 6813162..12c790a 100644 --- a/src/Flu_Tree_Browser.cpp +++ b/src/Flu_Tree_Browser.cpp @@ -586,7 +586,7 @@ Flu_Tree_Browser::Node* Flu_Tree_Browser :: NodeList :: find( const char* n, int #define SCROLL_SIZE 15 Flu_Tree_Browser :: Flu_Tree_Browser( int x, int y, int w, int h, const char *l ) - : Fl_Group( x, y, w, h ) + : Fl_Double_Window( x, y, w, h ) #ifdef USE_FLU_DND , Flu_DND( "Flu_Tree_Browser" ) #endif @@ -713,7 +713,7 @@ void Flu_Tree_Browser :: leaf_icon( Fl_Image *icon ) void Flu_Tree_Browser :: resize( int X, int Y, int W, int H ) { - Fl_Group::resize( X, Y, W, H ); + Fl_Double_Window::resize( X, Y, W, H ); int dx = Fl::box_dx(box()), dy = Fl::box_dy(box()), dw = Fl::box_dw(box()), dh = Fl::box_dh(box()); @@ -990,6 +990,11 @@ int Flu_Tree_Browser :: handle( int event ) return 1; #endif + if ((Fl::focus() != this) && rdata.lastHilighted) + { + set_hilighted(NULL); + } + if( event == FL_NO_EVENT || event == FL_MOVE ) return 0; @@ -997,11 +1002,17 @@ int Flu_Tree_Browser :: handle( int event ) { set_hilighted( rdata.lastHilighted ); lastEvent = event; - Fl_Group::handle( event ); + Fl_Double_Window::handle( event ); redraw(); return 1; } + if (event == FL_FOCUS) + { + Fl::focus(this); + return 1; + } + if( event == FL_UNFOCUS ) { if( lastEvent != FL_LEAVE ) @@ -1010,16 +1021,27 @@ int Flu_Tree_Browser :: handle( int event ) } set_hilighted( NULL ); lastEvent = event; - Fl_Group::handle( event ); + Fl_Double_Window::handle( event ); redraw(); return 1; } + if (event == FL_PUSH) + Fl::focus(this); + + if (Fl::focus() != this) + { + if ((event == FL_KEYUP) || (event == FL_KEYDOWN)) + return 1; + } + if( !rdata.dragging ) { - if( ! (event == FL_MOVE || event == FL_ENTER || event == FL_LEAVE ) ) - _box->redraw(); - if( Fl_Group::handle( event ) ) +// if( ! (event == FL_MOVE || event == FL_ENTER || event == FL_LEAVE ) ) +// _box->redraw(); + + + if( Fl_Double_Window::handle( event ) ) { //if( event == FL_KEYDOWN || event == FL_KEYUP ) // redraw(); @@ -1029,11 +1051,11 @@ int Flu_Tree_Browser :: handle( int event ) if( event == FL_RELEASE ) { - Fl::focus(this); +// Fl::focus(this); rdata.dragging = false; rdata.grabbed = 0; rdata.dragNode = 0; - redraw(); +// redraw(); } int dx = Fl::box_dx(box()), dy = Fl::box_dy(box()); @@ -1053,6 +1075,9 @@ int Flu_Tree_Browser :: handle( int event ) // catch cursor keys for moving the hilighted entry or selecting all entries if( event == FL_KEYDOWN ) { + if (Fl::focus() != this) + return 1; + // move hilighted entry up if( Fl::event_key() == FL_Up ) { @@ -1146,10 +1171,16 @@ void Flu_Tree_Browser :: set_hilighted( Flu_Tree_Browser::Node* n ) return; if( rdata.hilighted ) + { rdata.hilighted->do_callback( FLU_UNHILIGHTED ); + rdata.hilighted->select(false); + } rdata.hilighted = n; - if( rdata.hilighted ) + if ( rdata.hilighted ) + { rdata.hilighted->do_callback( FLU_HILIGHTED ); + n->select(true); + } if( rdata.hilighted ) { @@ -1165,6 +1196,7 @@ void Flu_Tree_Browser :: set_hilighted( Flu_Tree_Browser::Node* n ) if( rdata.hilighted->currentY-y() < scrollV->value() ) ((Fl_Valuator*)scrollV)->value( rdata.hilighted->currentY-y() ); } + redraw(); } @@ -1540,6 +1572,7 @@ void Flu_Tree_Browser :: draw() // set up the recursive data structure rdata.x = x()+dx; rdata.y = y()+dy; + rdata.firstConnector = 0; // account for the positions of the scrollbars if( scrollH->visible() ) rdata.x -= scrollH->value(); @@ -1742,7 +1775,20 @@ void Flu_Tree_Browser :: Node :: draw( RData &rdata, bool measure ) draw_Rdash( X-halfHGap, Y-halfVGap, rdata.collapseIcons[which]->w()+4+rdata.hGap, currentH+rdata.vGap ); } else if( rdata.last ) + { +// if (parent() != NULL) +// { +// if (parent()->parent() != NULL) +// { + if (depth()-1 == rdata.firstConnector) + rdata.firstConnector++; +// if ((depth() - 1 == rdata.firstConnector) && parent() != +// parent()->parent()->child(parent()->parent()->children() -1)) +// rdata.firstConnector++; +// } +// } draw_L( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap ); + } else draw_T( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap ); } @@ -2149,7 +2195,7 @@ int Flu_Tree_Browser :: Node :: recurse( RData &rdata, int type, int event ) int d = depth()-1; for( i = 0; i < rdata.branchConnectors.size(); i++ ) { - if( i != d ) + if( i != d - rdata.firstConnector ) { fl_color( rdata.lineColor ); fl_line_style( rdata.lineStyle, rdata.lineWidth ); @@ -2258,15 +2304,21 @@ int Flu_Tree_Browser :: Node :: recurse( RData &rdata, int type, int event ) // check for the left/right cursor keys opening/closing this entry else if( (Fl::event_key() == FL_Left) && (rdata.hilighted == this) ) - { - open( false ); - return 1; - } + { + open( false ); + return 1; + } else if( (Fl::event_key() == FL_Right) && (rdata.hilighted == this) ) - { - open( true ); - do_callback(FLU_RIGHT_CLICK); - return 1; + { + open( true ); + do_callback(FLU_RIGHT_CLICK); + return 1; + } + else if( (Fl::event_key() == FL_Delete) && (rdata.hilighted == this) ) + { + open( true ); + do_callback(FLU_DELETE); + return 1; } } @@ -2416,6 +2468,7 @@ int Flu_Tree_Browser :: Node :: recurse( RData &rdata, int type, int event ) if( Fl::event_button() == FL_RIGHT_MOUSE) { do_callback( FLU_RIGHT_CLICK ); + return 1; } if( is_leaf() ) { diff --git a/src/Flu_Wrap_Group.cpp b/src/Flu_Wrap_Group.cpp new file mode 100644 index 0000000..dab28e3 --- /dev/null +++ b/src/Flu_Wrap_Group.cpp @@ -0,0 +1,284 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#include "FLU/Flu_Wrap_Group.h" +#include +#include + +#define MAX( x, y ) ( (x)>(y) ? (x) : (y) ) + +#define SCROLL_SIZE 15 + +Flu_Wrap_Group :: Scrollbar :: Scrollbar( int x, int y, int w, int h, const char *l ) + : Fl_Scrollbar( x, y, w, h, l ) +{ +} + +int Flu_Wrap_Group :: Scrollbar :: handle( int event ) +{ + if( event == FL_MOUSEWHEEL ) + { + handle_drag( clamp( value() + linesize() * Fl::e_dy ) ); + return 1; + } + else + return Fl_Scrollbar::handle( event ); +} + +Flu_Wrap_Group :: Flu_Wrap_Group( int x, int y, int w, int h, const char *l ) + : Fl_Group( x, y, w, h, l ), scrollbar( x+w-SCROLL_SIZE, y, SCROLL_SIZE, h ), group( x, y, w-SCROLL_SIZE, h ) +{ + offset( 0, 0 ); + spacing( 0, 0 ); + _type = FL_VERTICAL; + scrollTo = NULL; + + Fl_Group::add( &scrollbar ); + scrollbar.callback( _scrollCB, this ); + scrollbar.linesize( 10 ); + scrollbar.range( 0, 100 ); + scrollbar.show(); + + Fl_Group::add( &group ); + Fl_Group::resizable( group ); + Fl_Group::end(); + group.begin(); +} + +void Flu_Wrap_Group :: resize( int x, int y, int w, int h ) +{ + group.resizable( NULL ); + Fl_Group::resize( x, y, w, h ); + if( type() == FL_VERTICAL ) + { + scrollbar.resize( x+w-SCROLL_SIZE-Fl::box_dx(box()), y+Fl::box_dy(box()), SCROLL_SIZE, h-Fl::box_dh(box()) ); + group.resize( x, y, w-SCROLL_SIZE-Fl::box_dx(box()), h ); + } + else + { + scrollbar.resize( x+Fl::box_dx(box()), y+h-SCROLL_SIZE-Fl::box_dy(box()), w-Fl::box_dw(box()), SCROLL_SIZE ); + group.resize( x, y, w, h-SCROLL_SIZE-Fl::box_dh(box()) ); + } + Fl_Group::init_sizes(); + redraw(); +} + +void Flu_Wrap_Group :: scroll_to( const Fl_Widget *w ) +{ + scrollTo = w; + redraw(); +} + +void Flu_Wrap_Group :: scroll_to_beginning() +{ + ((Fl_Valuator*)&scrollbar)->value( scrollbar.minimum() ); +} + +void Flu_Wrap_Group :: scroll_to_end() +{ + ((Fl_Valuator*)&scrollbar)->value( scrollbar.maximum() ); +} + +void Flu_Wrap_Group :: type( int t ) +{ + _type = t; + resize( x(), y(), w(), h() ); +} + +bool Flu_Wrap_Group :: layout( bool sbVisible, bool doScrollTo ) +{ + int xx = x()+Fl::box_dx(box()), yy = y()+Fl::box_dy(box()), + ww = w()-Fl::box_dw(box()), hh = h()-Fl::box_dh(box()); + + if( type() == FL_VERTICAL ) + { + int i, X, Y, maxH, H, col, row, maxW, scrollY; + Fl_Widget *c; + + scrollbar.type( FL_VERTICAL ); + + BEGIN_H: + + X = xx+_offset[0]; + Y = yy+_offset[1] - (sbVisible ? scrollbar.value() : 0); + maxH = _offset[1]; + H = 0; + col = 0; + row = 0; + scrollY = 0; + maxW = xx + ww - (sbVisible ? scrollbar.w() : 0); + + for( i = 0; i < group.children(); i++ ) + { + c = group.child(i); + if( !c->visible() ) + continue; + H = MAX( H, c->h() ); + if( col == 0 ) + maxH += H + _spacing[1]; + if( ( X + c->w() ) > maxW ) + { + Y += H + _spacing[1]; + scrollY += H + _spacing[1]; + if( i == group.children()-1 ) + maxH += H + _spacing[1]; + + c->position( xx+_offset[0], Y ); + + col = 0; + row++; + H = 0; + X = xx+c->w() + _offset[0] + _spacing[0]; + } + else + { + c->position( X, Y ); + X += c->w() + _spacing[0]; + col++; + } + + if( doScrollTo && (c == scrollTo) ) + { + if( scrollY > scrollbar.maximum() ) + scrollY = (int)scrollbar.maximum(); + ((Fl_Valuator*)&scrollbar)->value( scrollY ); + scrollTo = NULL; + goto BEGIN_H; + } + + // if we exceed the height and the scrollbar is not visible, + // then it will soon become visible so we don't need to process anymore + if( !sbVisible && maxH > hh ) + return true; + } + + if( maxH > hh ) + { + scrollbar.range( 0, maxH-hh ); + scrollbar.slider_size( MAX( float(scrollbar.h()-(maxH-hh))/float(scrollbar.h()), 0.08f ) ); + return true; + } + else + return false; + } + else + { + int i, X, Y, W, maxW, maxH, col, row, scrollX; + Fl_Widget *c; + + scrollbar.type( FL_HORIZONTAL ); + + BEGIN_W: + + X = xx+_offset[0] - (sbVisible ? scrollbar.value() : 0); + Y = yy+_offset[1]; + maxW = _offset[0]; + W = 0; + col = 0; + row = 0; + scrollX = 0; + maxH = yy + hh - (sbVisible ? scrollbar.h() : 0); + + for( i = 0; i < group.children(); i++ ) + { + c = group.child(i); + if( !c->visible() ) + continue; + + W = MAX( W, c->w() ); + + if( row == 0 ) + maxW += W + _spacing[0]; + + if( ( Y + c->h() ) > maxH ) + { + X += W + _spacing[0]; + scrollX += W + _spacing[0]; + if( i == group.children()-1 ) + maxW += W + _spacing[0]; + + c->position( X, yy+_offset[1] ); + + row = 0; + col++; + W = 0; + Y = yy+c->h() + _offset[1] + _spacing[1]; + } + else + { + c->position( X, Y ); + Y += c->h() + _spacing[1]; + row++; + } + + if( doScrollTo && (c == scrollTo) ) + { + if( scrollX > scrollbar.maximum() ) + scrollX = (int)scrollbar.maximum(); + ((Fl_Valuator*)&scrollbar)->value( scrollX ); + scrollTo = NULL; + goto BEGIN_W; + } + + // if we exceed the width and the scrollbar is not visible, + // then it will soon become visible so we don't need to process anymore + if( !sbVisible && maxW > ww ) + return true; + } + + if( maxW > ww ) + { + scrollbar.range( 0, maxW-ww ); + scrollbar.slider_size( MAX( float(scrollbar.w()-(maxW-ww))/float(scrollbar.w()), 0.08f ) ); + return true; + } + else + return false; + } +} + +void Flu_Wrap_Group :: draw() +{ + // we first try to fit all children assuming no scrollbar. if they do not all fit, + // we have to turn the scrollbar on and try again + if( layout( false, false ) ) + { + scrollbar.show(); + layout( true, false ); + } + else + scrollbar.hide(); + + // hack to look right when resizing smaller + if( scrollbar.value() > scrollbar.maximum() ) + { + ((Fl_Valuator*)&scrollbar)->value( scrollbar.maximum() ); + layout( scrollbar.visible(), scrollTo!=NULL ); + } + else if( scrollTo ) + layout( scrollbar.visible(), true ); + + scrollTo = NULL; + + if( damage() & ~FL_DAMAGE_CHILD) + { + draw_box(); + draw_label(); + } + fl_push_clip( x()+Fl::box_dx(box()), y()+Fl::box_dy(box()), + w()-Fl::box_dw(box()), h()-Fl::box_dh(box()) ); + draw_children(); + fl_pop_clip(); +} diff --git a/src/MString.h b/src/MString.h index cbb38e0..056bb1b 100644 --- a/src/MString.h +++ b/src/MString.h @@ -73,7 +73,7 @@ struct MStringData { char * pcStr; int precision; int iBufLen; // length of buffer minus 1 for null terminator - int iBufferInUse; +// int iBufferInUse; }; class MString { @@ -367,7 +367,7 @@ class MString { int precision; int iBufLen; // length of buffer minus 1 for null terminator - int iBufferInUse; +// int iBufferInUse; // flag to indicate that the MString has been modified since the // last time char* GetBuffer() was called diff --git a/src/My_Text_Display.cpp b/src/My_Text_Display.cpp new file mode 100644 index 0000000..d24efea --- /dev/null +++ b/src/My_Text_Display.cpp @@ -0,0 +1,3120 @@ +// +// "$Id$" +// +// Copyright 2001-2003 by Bill Spitzak and others. +// Original code Copyright Mark Edel. Permission to distribute under +// the LGPL for the FLTK library granted by Mark Edel. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to "fltk-bugs@fltk.org". +// + +#include +#include +//#include +#include +#include +#include +#include +#include +#include "My_Text_Display.h" +#include +#include + +#undef min +#undef max + +// Text area margins. Left & right margins should be at least 3 so that +// there is some room for the overhanging parts of the cursor! +#define TOP_MARGIN 1 +#define BOTTOM_MARGIN 1 +#define LEFT_MARGIN 18 +#define RIGHT_MARGIN 3 + +#define NO_HINT -1 + +/* Masks for text drawing methods. These are or'd together to form an + integer which describes what drawing calls to use to draw a string */ +#define FILL_MASK 0x100 +#define SECONDARY_MASK 0x200 +#define PRIMARY_MASK 0x400 +#define HIGHLIGHT_MASK 0x800 +#define STYLE_LOOKUP_MASK 0xff + +/* Maximum displayable line length (how many characters will fit across the + widest window). This amount of memory is temporarily allocated from the + stack in the draw_vline() method for drawing strings */ +#define MAX_DISP_LINE_LEN 1000 + +static int max( int i1, int i2 ); +static int min( int i1, int i2 ); +static int countlines( const char *string ); + +// CET - FIXME +#define TMPFONTWIDTH 6 + +My_Text_Display::My_Text_Display(int X, int Y, int W, int H, const char* l) + : Fl_Double_Window(X, Y, W, H, l) { + int i; + + border(0); + mMaxsize = 0; + mCurrentCol = 0; + damage_range1_start = damage_range1_end = -1; + damage_range2_start = damage_range2_end = -1; + dragPos = dragType = dragging = 0; + display_insert_position_hint = 0; + + color(FL_BACKGROUND2_COLOR);//, FL_SELECTION_COLOR); +// box(FL_DOWN_FRAME); + box(FL_NO_BOX); + textsize((uchar)FL_NORMAL_SIZE); + textcolor(FL_FOREGROUND_COLOR); + textfont(FL_HELVETICA); + + text_area.x = 0; + text_area.y = 0; + text_area.w = 0; + text_area.h = 0; + + mVScrollBar = new Fl_Scrollbar(0,0,1,1); + mVScrollBar->callback((Fl_Callback*)v_scrollbar_cb, this); + mHScrollBar = new Fl_Scrollbar(0,0,1,1); + mHScrollBar->callback((Fl_Callback*)h_scrollbar_cb, this); + mHScrollBar->type(FL_HORIZONTAL); + + end(); + + scrollbar_width(16); + scrollbar_align(FL_ALIGN_BOTTOM_RIGHT); + + mCursorOn = 0; + mCursorPos = 0; + mCursorOldY = -100; + mCursorToHint = NO_HINT; + mCursorStyle = NORMAL_CURSOR; + mCursorPreferredCol = -1; + mBuffer = 0; + mFirstChar = 0; + mLastChar = 0; + mNBufferLines = 0; + mTopLineNum = mTopLineNumHint = 1; + mAbsTopLineNum = 1; + mNeedAbsTopLineNum = 0; + mHorizOffset = mHorizOffsetHint = 0; + + mCursor_color = FL_BLACK; + + mFixedFontWidth = TMPFONTWIDTH;// CET - FIXME + mStyleBuffer = 0; + mStyleTable = 0; + mNStyles = 0; + mNVisibleLines = 1; + mLineStarts = new int[mNVisibleLines]; + mLineStarts[0] = 0; + for (i=1; iremove_modify_callback(buffer_modified_cb, this); + if (mLineStarts) delete[] mLineStarts; +} + +/* +** Attach a text buffer to display, replacing the current buffer (if any) +*/ +void My_Text_Display::buffer( Fl_Text_Buffer *buf ) { + /* If the text display is already displaying a buffer, clear it off + of the display and remove our callback from it */ + if ( mBuffer != 0 ) { + buffer_modified_cb( 0, 0, mBuffer->length(), 0, 0, this ); + mBuffer->remove_modify_callback( buffer_modified_cb, this ); + mBuffer->remove_predelete_callback( buffer_predelete_cb, this ); + } + + /* Add the buffer to the display, and attach a callback to the buffer for + receiving modification information when the buffer contents change */ + mBuffer = buf; + mBuffer->add_modify_callback( buffer_modified_cb, this ); + mBuffer->add_predelete_callback( buffer_predelete_cb, this ); + + /* Update the display */ + buffer_modified_cb( 0, buf->length(), 0, 0, 0, this ); + + /* Resize the widget to update the screen... */ + resize(x(), y(), w(), h()); +} + +/* +** Attach (or remove) highlight information in text display and redisplay. +** Highlighting information consists of a style buffer which parallels the +** normal text buffer, but codes font and color information for the display; +** a style table which translates style buffer codes (indexed by buffer +** character - 'A') into fonts and colors; and a callback mechanism for +** as-needed highlighting, triggered by a style buffer entry of +** "unfinishedStyle". Style buffer can trigger additional redisplay during +** a normal buffer modification if the buffer contains a primary Fl_Text_Selection +** (see extendRangeForStyleMods for more information on this protocol). +** +** Style buffers, tables and their associated memory are managed by the caller. +*/ +void +My_Text_Display::highlight_data(Fl_Text_Buffer *styleBuffer, + const Style_Table_Entry *styleTable, + int nStyles, char unfinishedStyle, + Unfinished_Style_Cb unfinishedHighlightCB, + void *cbArg ) { + mStyleBuffer = styleBuffer; + mStyleTable = styleTable; + mNStyles = nStyles; + mUnfinishedStyle = unfinishedStyle; + mUnfinishedHighlightCB = unfinishedHighlightCB; + mHighlightCBArg = cbArg; + + mStyleBuffer->canUndo(0); +#if 0 + // FIXME: this is in nedit code -- is it needed? + /* Call TextDSetFont to combine font information from style table and + primary font, adjust font-related parameters, and then redisplay */ + TextDSetFont(textD, textD->fontStruct); +#endif + damage(FL_DAMAGE_EXPOSE); +} + +#if 0 + // FIXME: this is in nedit code -- is it needed? +/* +** Change the (non highlight) font +*/ +void TextDSetFont(textDisp *textD, XFontStruct *fontStruct) { + Display *display = XtDisplay(textD->w); + int i, maxAscent = fontStruct->ascent, maxDescent = fontStruct->descent; + int width, height, fontWidth; + Pixel bgPixel, fgPixel, selectFGPixel, selectBGPixel; + Pixel highlightFGPixel, highlightBGPixel; + XGCValues values; + XFontStruct *styleFont; + + /* If font size changes, cursor will be redrawn in a new position */ + blankCursorProtrusions(textD); + + /* If there is a (syntax highlighting) style table in use, find the new + maximum font height for this text display */ + for (i=0; inStyles; i++) { + styleFont = textD->styleTable[i].font; + if (styleFont != NULL && styleFont->ascent > maxAscent) + maxAscent = styleFont->ascent; + if (styleFont != NULL && styleFont->descent > maxDescent) + maxDescent = styleFont->descent; + } + textD->ascent = maxAscent; + textD->descent = maxDescent; + + /* If all of the current fonts are fixed and match in width, compute */ + fontWidth = fontStruct->max_bounds.width; + if (fontWidth != fontStruct->min_bounds.width) + fontWidth = -1; + else { + for (i=0; inStyles; i++) { + styleFont = textD->styleTable[i].font; + if (styleFont != NULL && (styleFont->max_bounds.width != fontWidth || + styleFont->max_bounds.width != styleFont->min_bounds.width)) + fontWidth = -1; + } + } + textD->fixedFontWidth = fontWidth; + + /* Don't let the height dip below one line, or bad things can happen */ + if (textD->height < maxAscent + maxDescent) + textD->height = maxAscent + maxDescent; + + /* Change the font. In most cases, this means re-allocating the + affected GCs (they are shared with other widgets, and if the primary + font changes, must be re-allocated to change it). Unfortunately, + this requres recovering all of the colors from the existing GCs */ + textD->fontStruct = fontStruct; + XGetGCValues(display, textD->gc, GCForeground|GCBackground, &values); + fgPixel = values.foreground; + bgPixel = values.background; + XGetGCValues(display, textD->selectGC, GCForeground|GCBackground, &values); + selectFGPixel = values.foreground; + selectBGPixel = values.background; + XGetGCValues(display, textD->highlightGC,GCForeground|GCBackground,&values); + highlightFGPixel = values.foreground; + highlightBGPixel = values.background; + releaseGC(textD->w, textD->gc); + releaseGC(textD->w, textD->selectGC); + releaseGC(textD->w, textD->highlightGC); + releaseGC(textD->w, textD->selectBGGC); + releaseGC(textD->w, textD->highlightBGGC); + if (textD->lineNumGC != NULL) + releaseGC(textD->w, textD->lineNumGC); + textD->lineNumGC = NULL; + allocateFixedFontGCs(textD, fontStruct, bgPixel, fgPixel, selectFGPixel, + selectBGPixel, highlightFGPixel, highlightBGPixel); + XSetFont(display, textD->styleGC, fontStruct->fid); + + /* Do a full resize to force recalculation of font related parameters */ + width = textD->width; + height = textD->height; + textD->width = textD->height = 0; + TextDResize(textD, width, height); + + /* Redisplay */ + TextDRedisplayRect(textD, textD->left, textD->top, textD->width, + textD->height); + + /* Clean up line number area in case spacing has changed */ + draw_line_numbers(textD, True); +} + +int TextDMinFontWidth(textDisp *textD, Boolean considerStyles) { + int fontWidth = textD->fontStruct->max_bounds.width; + int i; + + if (considerStyles) { + for (i = 0; i < textD->nStyles; ++i) { + int thisWidth = (textD->styleTable[i].font)->min_bounds.width; + if (thisWidth < fontWidth) { + fontWidth = thisWidth; + } + } + } + return(fontWidth); +} + +int TextDMaxFontWidth(textDisp *textD, Boolean considerStyles) { + int fontWidth = textD->fontStruct->max_bounds.width; + int i; + + if (considerStyles) { + for (i = 0; i < textD->nStyles; ++i) { + int thisWidth = (textD->styleTable[i].font)->max_bounds.width; + if (thisWidth > fontWidth) { + fontWidth = thisWidth; + } + } + } + return(fontWidth); +} +#endif + +int My_Text_Display::longest_vline() { + int longest = 0; + for (int i = 0; i < mNVisibleLines; i++) + longest = max(longest, measure_vline(i)); + return longest; +} + +/* +** Change the size of the displayed text area +*/ +void My_Text_Display::resize(int X, int Y, int W, int H) +{ + const int oldWidth = w(); + Fl_Double_Window::resize(X,Y,W,H); + if (!buffer()) return; + + Y = 0; + + X += Fl::box_dx(box()); + Y += Fl::box_dy(box()); + W -= Fl::box_dw(box()); + H -= Fl::box_dh(box()); + + text_area.x = X+LEFT_MARGIN; + text_area.y = Y+TOP_MARGIN; + text_area.w = W-LEFT_MARGIN-RIGHT_MARGIN; + text_area.h = H-TOP_MARGIN-BOTTOM_MARGIN; + int i; + + /* Find the new maximum font height for this text display */ + for (i = 0, mMaxsize = fl_height(textfont(), textsize()); i < mNStyles; i++) + mMaxsize = max(mMaxsize, fl_height(mStyleTable[i].font, mStyleTable[i].size)); + + // did we have scrollbars initially? + int hscrollbarvisible = mHScrollBar->visible(); + int vscrollbarvisible = mVScrollBar->visible(); + + // try without scrollbars first + mVScrollBar->clear_visible(); + mHScrollBar->clear_visible(); + + for (int again = 1; again;) { + again = 0; + /* In continuous wrap mode, a change in width affects the total number of + lines in the buffer, and can leave the top line number incorrect, and + the top character no longer pointing at a valid line start */ + if (mContinuousWrap && !mWrapMargin && W!=oldWidth) { + int oldFirstChar = mFirstChar; + mNBufferLines = count_lines(0, buffer()->length(), true); + mFirstChar = line_start(mFirstChar); + mTopLineNum = count_lines(0, mFirstChar, true)+1; + absolute_top_line_number(oldFirstChar); + } + + /* reallocate and update the line starts array, which may have changed + size and / or contents. */ + int nvlines = (text_area.h + mMaxsize - 1) / mMaxsize; + if (nvlines < 1) nvlines = 1; + if (mNVisibleLines != nvlines) { + mNVisibleLines = nvlines; + if (mLineStarts) delete[] mLineStarts; + mLineStarts = new int [mNVisibleLines]; + calc_line_starts(0, mNVisibleLines); + calc_last_char(); + } + + // figure the scrollbars + if (scrollbar_width()) { + /* Decide if the vertical scroll bar needs to be visible */ + if (scrollbar_align() & (FL_ALIGN_LEFT|FL_ALIGN_RIGHT) && + mNBufferLines >= mNVisibleLines - 1) + { + mVScrollBar->set_visible(); + if (scrollbar_align() & FL_ALIGN_LEFT) { + text_area.x = X+scrollbar_width()+LEFT_MARGIN; + text_area.w = W-scrollbar_width()-LEFT_MARGIN-RIGHT_MARGIN; + mVScrollBar->resize(X, text_area.y-TOP_MARGIN, scrollbar_width(), + text_area.h+TOP_MARGIN+BOTTOM_MARGIN); + } else { + text_area.x = X+LEFT_MARGIN; + text_area.w = W-scrollbar_width()-LEFT_MARGIN-RIGHT_MARGIN; + mVScrollBar->resize(X+W-scrollbar_width(), text_area.y-TOP_MARGIN, + scrollbar_width(), text_area.h+TOP_MARGIN+BOTTOM_MARGIN); + } + } + + /* + Decide if the horizontal scroll bar needs to be visible. If there + is a vertical scrollbar, a horizontal is always created too. This + is because the alternatives are unatractive: + * Dynamically creating a horizontal scrollbar based on the currently + visible lines is what the original nedit does, but it always wastes + space for the scrollbar even when it's not used. Since the FLTK + widget dynamically allocates the space for the scrollbar and + rearranges the widget to make room for it, this would create a very + visually displeasing "bounce" effect when the vertical scrollbar is + dragged. Trust me, I tried it and it looks really bad. + * The other alternative would be to keep track of what the longest + line in the entire buffer is and base the scrollbar on that. I + didn't do this because I didn't see any easy way to do that using + the nedit code and this could involve a lengthy calculation for + large buffers. If an efficient and non-costly way of doing this + can be found, this might be a way to go. + */ + /* WAS: Suggestion: Try turning the horizontal scrollbar on when + you first see a line that is too wide in the window, but then + don't turn it off (ie mix both of your solutions). */ + if (scrollbar_align() & (FL_ALIGN_TOP|FL_ALIGN_BOTTOM) && + (mVScrollBar->visible() || longest_vline() > text_area.w)) + { + if (!mHScrollBar->visible()) { + mHScrollBar->set_visible(); + again = 1; // loop again to see if we now need vert. & recalc sizes + } + if (scrollbar_align() & FL_ALIGN_TOP) { + text_area.y = Y + scrollbar_width()+TOP_MARGIN; + text_area.h = H - scrollbar_width()-TOP_MARGIN-BOTTOM_MARGIN; + mHScrollBar->resize(text_area.x-LEFT_MARGIN, Y, + text_area.w+LEFT_MARGIN+RIGHT_MARGIN, scrollbar_width()); + } else { + text_area.y = Y+TOP_MARGIN; + text_area.h = H - scrollbar_width()-TOP_MARGIN-BOTTOM_MARGIN; + mHScrollBar->resize(text_area.x-LEFT_MARGIN, Y+H-scrollbar_width(), + text_area.w+LEFT_MARGIN+RIGHT_MARGIN, scrollbar_width()); + } + } + } + } + + // user request to change viewport + if (mTopLineNumHint != mTopLineNum || mHorizOffsetHint != mHorizOffset) + scroll_(mTopLineNumHint, mHorizOffsetHint); + + // everything will fit in the viewport + if (mNBufferLines < mNVisibleLines || mBuffer == NULL || mBuffer->length() == 0) + scroll_(1, mHorizOffset); + /* if empty lines become visible, there may be an opportunity to + display more text by scrolling down */ + else while (mLineStarts[mNVisibleLines-2] == -1) + scroll_(mTopLineNum-1, mHorizOffset); + + // user request to display insert position + if (display_insert_position_hint) + display_insert(); + + // in case horizontal offset is now greater than longest line + int maxhoffset = max(0, longest_vline()-text_area.w); + if (mHorizOffset > maxhoffset) + scroll_(mTopLineNumHint, maxhoffset); + + mTopLineNumHint = mTopLineNum; + mHorizOffsetHint = mHorizOffset; + display_insert_position_hint = 0; + + if (mContinuousWrap || + hscrollbarvisible != mHScrollBar->visible() || + vscrollbarvisible != mVScrollBar->visible()) + redraw(); + + update_v_scrollbar(); + update_h_scrollbar(); + redraw(); +} + +/* +** Refresh a rectangle of the text display. left and top are in coordinates of +** the text drawing window +*/ +void My_Text_Display::draw_text( int left, int top, int width, int height ) { + int fontHeight, firstLine, lastLine, line; + + /* find the line number range of the display */ + fontHeight = mMaxsize ? mMaxsize : textsize_; + firstLine = ( top - text_area.y - fontHeight + 1 ) / fontHeight; + lastLine = ( top + height - text_area.y ) / fontHeight + 1; + + fl_push_clip( left, top, width, height ); + Fl_Region r = XRectangleRegion(left, top, width, height); + fl_clip_region(r); + + /* draw the lines */ + for ( line = firstLine; line <= lastLine; line++ ) + draw_vline( line, left, left + width, 0, INT_MAX ); + + /* draw the line numbers if exposed area includes them */ + if (mLineNumWidth != 0 && left <= mLineNumLeft + mLineNumWidth) + draw_line_numbers(false); + + fl_pop_clip(); +} + +void My_Text_Display::redisplay_range(int startpos, int endpos) { + if (damage_range1_start == -1 && damage_range1_end == -1) { + damage_range1_start = startpos; + damage_range1_end = endpos; + } else if ((startpos >= damage_range1_start && startpos <= damage_range1_end) || + (endpos >= damage_range1_start && endpos <= damage_range1_end)) { + damage_range1_start = min(damage_range1_start, startpos); + damage_range1_end = max(damage_range1_end, endpos); + } else if (damage_range2_start == -1 && damage_range2_end == -1) { + damage_range2_start = startpos; + damage_range2_end = endpos; + } else { + damage_range2_start = min(damage_range2_start, startpos); + damage_range2_end = max(damage_range2_end, endpos); + } + damage(FL_DAMAGE_SCROLL); +} +/* +** Refresh all of the text between buffer positions "start" and "end" +** not including the character at the position "end". +** If end points beyond the end of the buffer, refresh the whole display +** after pos, including blank lines which are not technically part of +** any range of characters. +*/ +void My_Text_Display::draw_range(int startpos, int endpos) { + int i, startLine, lastLine, startIndex, endIndex; + + /* If the range is outside of the displayed text, just return */ + if ( endpos < mFirstChar || ( startpos > mLastChar && + !empty_vlines() ) ) return; + + /* Clean up the starting and ending values */ + if ( startpos < 0 ) startpos = 0; + if ( startpos > mBuffer->length() ) startpos = mBuffer->length(); + if ( endpos < 0 ) endpos = 0; + if ( endpos > mBuffer->length() ) endpos = mBuffer->length(); + + /* Get the starting and ending lines */ + if ( startpos < mFirstChar ) + startpos = mFirstChar; + if ( !position_to_line( startpos, &startLine ) ) + startLine = mNVisibleLines - 1; + if ( endpos >= mLastChar ) { + lastLine = mNVisibleLines - 1; + } else { + if ( !position_to_line( endpos, &lastLine ) ) { + /* shouldn't happen */ + lastLine = mNVisibleLines - 1; + } + } + + /* Get the starting and ending positions within the lines */ + startIndex = mLineStarts[ startLine ] == -1 ? 0 : + startpos - mLineStarts[ startLine ]; + if ( endpos >= mLastChar ) + endIndex = INT_MAX; + else if ( mLineStarts[ lastLine ] == -1 ) + endIndex = 0; + else + endIndex = endpos - mLineStarts[ lastLine ]; + + /* If the starting and ending lines are the same, redisplay the single + line between "start" and "end" */ + if ( startLine == lastLine ) { + draw_vline( startLine, 0, INT_MAX, startIndex, endIndex ); + return; + } + + /* Redisplay the first line from "start" */ + draw_vline( startLine, 0, INT_MAX, startIndex, INT_MAX ); + + /* Redisplay the lines in between at their full width */ + for ( i = startLine + 1; i < lastLine; i++ ) + draw_vline( i, 0, INT_MAX, 0, INT_MAX ); + + /* Redisplay the last line to "end" */ + draw_vline( lastLine, 0, INT_MAX, 0, endIndex ); +} + +/* +** Set the position of the text insertion cursor for text display +*/ +void My_Text_Display::insert_position( int newPos ) { + /* make sure new position is ok, do nothing if it hasn't changed */ + if ( newPos == mCursorPos ) + return; + if ( newPos < 0 ) newPos = 0; + if ( newPos > mBuffer->length() ) newPos = mBuffer->length(); + + /* cursor movement cancels vertical cursor motion column */ + mCursorPreferredCol = -1; + + /* erase the cursor at it's previous position */ + redisplay_range(mCursorPos - 1, mCursorPos + 1); + + mCursorPos = newPos; + + /* draw cursor at its new position */ + redisplay_range(mCursorPos - 1, mCursorPos + 1); + int line; + position_to_linecol(mCursorPos, &line, &mCurrentCol); + +} + +void My_Text_Display::show_cursor(int b) { + mCursorOn = b; + redisplay_range(mCursorPos - 1, mCursorPos + 1); +} + +void My_Text_Display::cursor_style(int style) { + mCursorStyle = style; + if (mCursorOn) show_cursor(); +} + +void My_Text_Display::wrap_mode(int wrap, int wrapMargin) { + mWrapMargin = wrapMargin; + mContinuousWrap = wrap; + + /* wrapping can change change the total number of lines, re-count */ + mNBufferLines = count_lines(0, buffer()->length(), true); + + /* changing wrap margins wrap or changing from wrapped mode to non-wrapped + can leave the character at the top no longer at a line start, and/or + change the line number */ + mFirstChar = line_start(mFirstChar); + mTopLineNum = count_lines(0, mFirstChar, true) + 1; + reset_absolute_top_line_number(); + + /* update the line starts array */ + calc_line_starts(0, mNVisibleLines); + calc_last_char(); + +#if 0 + // FIXME! + /* Update the scroll bar page increment size (as well as other scroll + bar parameters) */ + updateVScrollBarRange(textD); + updateHScrollBarRange(textD); + + /* Decide if the horizontal scroll bar needs to be visible */ + hideOrShowHScrollBar(textD); + + /* Do a full redraw */ + TextDRedisplayRect(textD, 0, textD->top, textD->width + textD->left, + textD->height); +#else + resize(x(), y(), w(), h()); +#endif +} + +/* +** Insert "text" at the current cursor location. This has the same +** effect as inserting the text into the buffer using BufInsert and +** then moving the insert position after the newly inserted text, except +** that it's optimized to do less redrawing. +*/ +void My_Text_Display::insert(const char* text) +{ + int pos = mCursorPos; + int line; + + mCursorToHint = pos + strlen( text ); + mBuffer->insert( pos, text ); + position_to_linecol(insert_position(), &line, &mCurrentCol); + mCursorToHint = NO_HINT; +} + +/* +** Insert "text" (which must not contain newlines), overstriking the current +** cursor location. +*/ +void My_Text_Display::overstrike(const char* text) { + int startPos = mCursorPos; + Fl_Text_Buffer *buf = mBuffer; + int lineStart = buf->line_start( startPos ); + int textLen = strlen( text ); + int i, p, endPos, indent, startIndent, endIndent; + const char *c; + char ch, *paddedText = NULL; + + /* determine how many displayed character positions are covered */ + startIndent = mBuffer->count_displayed_characters( lineStart, startPos ); + indent = startIndent; + for ( c = text; *c != '\0'; c++ ) + indent += Fl_Text_Buffer::character_width( *c, indent, buf->tab_distance(), buf->null_substitution_character() ); + endIndent = indent; + + /* find which characters to remove, and if necessary generate additional + padding to make up for removed control characters at the end */ + indent = startIndent; + for ( p = startPos; ; p++ ) { + if ( p == buf->length() ) + break; + ch = buf->character( p ); + if ( ch == '\n' ) + break; + indent += Fl_Text_Buffer::character_width( ch, indent, buf->tab_distance(), buf->null_substitution_character() ); + if ( indent == endIndent ) { + p++; + break; + } else if ( indent > endIndent ) { + if ( ch != '\t' ) { + p++; + paddedText = new char [ textLen + FL_TEXT_MAX_EXP_CHAR_LEN + 1 ]; + strcpy( paddedText, text ); + for ( i = 0; i < indent - endIndent; i++ ) + paddedText[ textLen + i ] = ' '; + paddedText[ textLen + i ] = '\0'; + } + break; + } + } + endPos = p; + + mCursorToHint = startPos + textLen; + buf->replace( startPos, endPos, paddedText == NULL ? text : paddedText ); + mCursorToHint = NO_HINT; + if ( paddedText != NULL ) + delete [] paddedText; +} + +/* +** Translate a buffer text position to the XY location where the top left +** of the cursor would be positioned to point to that character. Returns +** 0 if the position is not displayed because it is VERTICALLY out +** of view. If the position is horizontally out of view, returns the +** X coordinate where the position would be if it were visible. +*/ + +int My_Text_Display::position_to_xy( int pos, int* X, int* Y ) { + int charIndex, lineStartPos, fontHeight, lineLen; + int visLineNum, charLen, outIndex, xStep, charStyle; + char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ]; + const char *lineStr; + +// printf("position_to_xy(pos=%d, X=%p, Y=%p)\n", pos, X, Y); + + /* If position is not displayed, return false */ + if (pos < mFirstChar || (pos > mLastChar && !empty_vlines())) { +// printf(" returning 0\n" +// " mFirstChar=%d, mLastChar=%d, empty_vlines()=0\n", +// mFirstChar, mLastChar); + return 0; + } + + /* Calculate Y coordinate */ + if (!position_to_line(pos, &visLineNum)) { +// puts(" returning 0\n" +// " position_to_line()=0"); + return 0; + } + + if (visLineNum < 0 || visLineNum > mNBufferLines) { +// printf(" returning 0\n" +// " visLineNum=%d, mNBufferLines=%d\n", +// visLineNum, mNBufferLines); + return 0; + } + + fontHeight = mMaxsize; + *Y = text_area.y + visLineNum * fontHeight; + + /* Get the text, length, and buffer position of the line. If the position + is beyond the end of the buffer and should be at the first position on + the first empty line, don't try to get or scan the text */ + lineStartPos = mLineStarts[visLineNum]; + if ( lineStartPos == -1 ) { + *X = text_area.x - mHorizOffset; + return 1; + } + lineLen = vline_length( visLineNum ); + lineStr = mBuffer->text_range( lineStartPos, lineStartPos + lineLen ); + + /* Step through character positions from the beginning of the line + to "pos" to calculate the X coordinate */ + xStep = text_area.x - mHorizOffset; + outIndex = 0; + for ( charIndex = 0; charIndex < lineLen && charIndex < pos - lineStartPos; charIndex++ ) { + charLen = Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar, + mBuffer->tab_distance(), mBuffer->null_substitution_character() ); + charStyle = position_style( lineStartPos, lineLen, charIndex, + outIndex ); + xStep += string_width( expandedChar, charLen, charStyle ); + outIndex += charLen; + } + *X = xStep; + delete [] (char *)lineStr; + return 1; +} + +/* +** Find the line number of position "pos". Note: this only works for +** displayed lines. If the line is not displayed, the function returns +** 0 (without the mLineStarts array it could turn in to very long +** calculation involving scanning large amounts of text in the buffer). +** If continuous wrap mode is on, returns the absolute line number (as opposed +** to the wrapped line number which is used for scrolling). +*/ +int My_Text_Display::position_to_linecol( int pos, int* lineNum, int* column ) { + int retVal; + + /* In continuous wrap mode, the absolute (non-wrapped) line count is + maintained separately, as needed. Only return it if we're actually + keeping track of it and pos is in the displayed text */ + if (mContinuousWrap) { + if (!maintaining_absolute_top_line_number() || + pos < mFirstChar || pos > mLastChar) + return 0; + *lineNum = mAbsTopLineNum + buffer()->count_lines(mFirstChar, pos); + *column + = buffer()->count_displayed_characters(buffer()->line_start(pos), pos); + return 1; + } + + retVal = position_to_line( pos, lineNum ); + if ( retVal ) { + *column = mBuffer->count_displayed_characters( + mLineStarts[ *lineNum ], pos ); + *lineNum += mTopLineNum; + } + return retVal; +} + +/* +** Return 1 if position (X, Y) is inside of the primary Fl_Text_Selection +*/ +int My_Text_Display::in_selection( int X, int Y ) { + int row, column, pos = xy_to_position( X, Y, CHARACTER_POS ); + Fl_Text_Buffer *buf = mBuffer; + + xy_to_rowcol( X, Y, &row, &column, CHARACTER_POS ); + if (range_touches_selection(buf->primary_selection(), mFirstChar, mLastChar)) + column = wrapped_column(row, column); + return buf->primary_selection()->includes(pos, buf->line_start( pos ), column); +} + +/* +** Correct a column number based on an unconstrained position (as returned by +** TextDXYToUnconstrainedPosition) to be relative to the last actual newline +** in the buffer before the row and column position given, rather than the +** last line start created by line wrapping. This is an adapter +** for rectangular selections and code written before continuous wrap mode, +** which thinks that the unconstrained column is the number of characters +** from the last newline. Obviously this is time consuming, because it +** invloves character re-counting. +*/ +int My_Text_Display::wrapped_column(int row, int column) { + int lineStart, dispLineStart; + + if (!mContinuousWrap || row < 0 || row > mNVisibleLines) + return column; + dispLineStart = mLineStarts[row]; + if (dispLineStart == -1) + return column; + lineStart = buffer()->line_start(dispLineStart); + return column + + buffer()->count_displayed_characters(lineStart, dispLineStart); +} + +/* +** Correct a row number from an unconstrained position (as returned by +** TextDXYToUnconstrainedPosition) to a straight number of newlines from the +** top line of the display. Because rectangular selections are based on +** newlines, rather than display wrapping, and anywhere a rectangular selection +** needs a row, it needs it in terms of un-wrapped lines. +*/ +int My_Text_Display::wrapped_row(int row) { + if (!mContinuousWrap || row < 0 || row > mNVisibleLines) + return row; + return buffer()->count_lines(mFirstChar, mLineStarts[row]); +} + +/* +** Scroll the display to bring insertion cursor into view. +** +** Note: it would be nice to be able to do this without counting lines twice +** (scroll_() counts them too) and/or to count from the most efficient +** starting point, but the efficiency of this routine is not as important to +** the overall performance of the text display. +*/ +void My_Text_Display::display_insert() { + int hOffset, topLine, X, Y; + hOffset = mHorizOffset; + topLine = mTopLineNum; + +// FIXME: I don't understand this well enough to know if it is correct +// it is different than nedit 5.3 + if (insert_position() < mFirstChar) { + topLine -= count_lines(insert_position(), mFirstChar, false); + } else if (mLineStarts[mNVisibleLines-2] != -1) { + int lastChar = buffer()->line_end(mLineStarts[mNVisibleLines-2]); + if (insert_position() >= lastChar) + topLine + += count_lines(lastChar - (wrap_uses_character(mLastChar) ? 0 : 1), + insert_position(), false); + } + + /* Find the new setting for horizontal offset (this is a bit ungraceful). + If the line is visible, just use PositionToXY to get the position + to scroll to, otherwise, do the vertical scrolling first, then the + horizontal */ + if (!position_to_xy( mCursorPos, &X, &Y )) { + scroll_(topLine, hOffset); + if (!position_to_xy( mCursorPos, &X, &Y )) + return; /* Give up, it's not worth it (but why does it fail?) */ + } + if (X > text_area.x + text_area.w) + hOffset += X-(text_area.x + text_area.w); + else if (X < text_area.x) + hOffset += X-text_area.x; + + /* Do the scroll */ + if (topLine != mTopLineNum || hOffset != mHorizOffset) + scroll_(topLine, hOffset); +} + +void My_Text_Display::show_insert_position() { + display_insert_position_hint = 1; + resize(x(), y(), w(), h()); +} + +/* +** Cursor movement functions +*/ +int My_Text_Display::move_right() { + if ( mCursorPos >= mBuffer->length() ) + return 0; + insert_position( mCursorPos + 1 ); + return 1; +} + +int My_Text_Display::move_left() { + if ( mCursorPos <= 0 ) + return 0; + insert_position( mCursorPos - 1 ); + return 1; +} + +int My_Text_Display::move_up() { + int lineStartPos, column, prevLineStartPos, newPos, visLineNum; + + /* Find the position of the start of the line. Use the line starts array + if possible */ + if ( position_to_line( mCursorPos, &visLineNum ) ) + lineStartPos = mLineStarts[ visLineNum ]; + else { + lineStartPos = buffer()->line_start( mCursorPos ); + visLineNum = -1; + } + if ( lineStartPos == 0 ) + return 0; + + /* Decide what column to move to, if there's a preferred column use that */ + column = mCursorPreferredCol >= 0 ? mCursorPreferredCol : + mBuffer->count_displayed_characters( lineStartPos, mCursorPos ); + + /* count forward from the start of the previous line to reach the column */ + if ( visLineNum != -1 && visLineNum != 0 ) + prevLineStartPos = mLineStarts[ visLineNum - 1 ]; + else + prevLineStartPos = buffer()->rewind_lines( lineStartPos, 1 ); + newPos = mBuffer->skip_displayed_characters( prevLineStartPos, column ); + if (mContinuousWrap) + newPos = min(newPos, line_end(prevLineStartPos, true)); + + /* move the cursor */ + insert_position( newPos ); + + /* if a preferred column wasn't aleady established, establish it */ + mCursorPreferredCol = column; + return 1; +} + +int My_Text_Display::move_down() { + int lineStartPos, column, nextLineStartPos, newPos, visLineNum; + + if ( mCursorPos == mBuffer->length() ) + return 0; + if ( position_to_line( mCursorPos, &visLineNum ) ) + lineStartPos = mLineStarts[ visLineNum ]; + else { + lineStartPos = buffer()->line_start( mCursorPos ); + visLineNum = -1; + } + column = mCursorPreferredCol >= 0 ? mCursorPreferredCol : + mBuffer->count_displayed_characters( lineStartPos, mCursorPos ); + nextLineStartPos = skip_lines( lineStartPos, 1, true ); + newPos = mBuffer->skip_displayed_characters( nextLineStartPos, column ); + if (mContinuousWrap) + newPos = min(newPos, line_end(nextLineStartPos, true)); + + insert_position( newPos ); + mCursorPreferredCol = column; + return 1; +} + +/* +** Same as BufCountLines, but takes in to account wrapping if wrapping is +** turned on. If the caller knows that startPos is at a line start, it +** can pass "startPosIsLineStart" as True to make the call more efficient +** by avoiding the additional step of scanning back to the last newline. +*/ +int My_Text_Display::count_lines(int startPos, int endPos, + bool startPosIsLineStart) { + int retLines, retPos, retLineStart, retLineEnd; + + /* If we're not wrapping use simple (and more efficient) BufCountLines */ + if (!mContinuousWrap) + return buffer()->count_lines(startPos, endPos); + + wrapped_line_counter(buffer(), startPos, endPos, INT_MAX, + startPosIsLineStart, 0, &retPos, &retLines, &retLineStart, + &retLineEnd); + return retLines; +} + +/* +** Same as BufCountForwardNLines, but takes in to account line breaks when +** wrapping is turned on. If the caller knows that startPos is at a line start, +** it can pass "startPosIsLineStart" as True to make the call more efficient +** by avoiding the additional step of scanning back to the last newline. +*/ +int My_Text_Display::skip_lines(int startPos, int nLines, + bool startPosIsLineStart) { + int retLines, retPos, retLineStart, retLineEnd; + + /* if we're not wrapping use more efficient BufCountForwardNLines */ + if (!mContinuousWrap) + return buffer()->skip_lines(startPos, nLines); + + /* wrappedLineCounter can't handle the 0 lines case */ + if (nLines == 0) + return startPos; + + /* use the common line counting routine to count forward */ + wrapped_line_counter(buffer(), startPos, buffer()->length(), + nLines, startPosIsLineStart, 0, &retPos, &retLines, &retLineStart, + &retLineEnd); + return retPos; +} + +/* +** Same as BufEndOfLine, but takes in to account line breaks when wrapping +** is turned on. If the caller knows that startPos is at a line start, it +** can pass "startPosIsLineStart" as True to make the call more efficient +** by avoiding the additional step of scanning back to the last newline. +** +** Note that the definition of the end of a line is less clear when continuous +** wrap is on. With continuous wrap off, it's just a pointer to the newline +** that ends the line. When it's on, it's the character beyond the last +** DISPLAYABLE character on the line, where a whitespace character which has +** been "converted" to a newline for wrapping is not considered displayable. +** Also note that, a line can be wrapped at a non-whitespace character if the +** line had no whitespace. In this case, this routine returns a pointer to +** the start of the next line. This is also consistent with the model used by +** visLineLength. +*/ +int My_Text_Display::line_end(int pos, bool startPosIsLineStart) { + int retLines, retPos, retLineStart, retLineEnd; + + /* If we're not wrapping use more efficien BufEndOfLine */ + if (!mContinuousWrap) + return buffer()->line_end(pos); + + if (pos == buffer()->length()) + return pos; + wrapped_line_counter(buffer(), pos, buffer()->length(), 1, + startPosIsLineStart, 0, &retPos, &retLines, &retLineStart, + &retLineEnd); + return retLineEnd; +} + +/* +** Same as BufStartOfLine, but returns the character after last wrap point +** rather than the last newline. +*/ +int My_Text_Display::line_start(int pos) { + int retLines, retPos, retLineStart, retLineEnd; + + /* If we're not wrapping, use the more efficient BufStartOfLine */ + if (!mContinuousWrap) + return buffer()->line_start(pos); + + wrapped_line_counter(buffer(), buffer()->line_start(pos), pos, INT_MAX, true, 0, + &retPos, &retLines, &retLineStart, &retLineEnd); + return retLineStart; +} + +/* +** Same as BufCountBackwardNLines, but takes in to account line breaks when +** wrapping is turned on. +*/ +int My_Text_Display::rewind_lines(int startPos, int nLines) { + Fl_Text_Buffer *buf = buffer(); + int pos, lineStart, retLines, retPos, retLineStart, retLineEnd; + + /* If we're not wrapping, use the more efficient BufCountBackwardNLines */ + if (!mContinuousWrap) + return buf->rewind_lines(startPos, nLines); + + pos = startPos; + while (true) { + lineStart = buf->line_start(pos); + wrapped_line_counter(buf, lineStart, pos, INT_MAX, + true, 0, &retPos, &retLines, &retLineStart, &retLineEnd); + if (retLines > nLines) + return skip_lines(lineStart, retLines-nLines, + true); + nLines -= retLines; + pos = lineStart - 1; + if (pos < 0) + return 0; + nLines -= 1; + } +} + +static inline int fl_isseparator(int c) { + return c != '$' && c != '_' && (isspace(c) || ispunct(c)); +} + +void My_Text_Display::next_word() { + int pos = insert_position(); + while (pos < buffer()->length() && !fl_isseparator(buffer()->character(pos))) { + pos++; + } + while (pos < buffer()->length() && fl_isseparator(buffer()->character(pos))) { + pos++; + } + + insert_position( pos ); +} + +void My_Text_Display::previous_word() { + int pos = insert_position(); + pos--; + while (pos && fl_isseparator(buffer()->character(pos))) { + pos--; + } + while (pos && !fl_isseparator(buffer()->character(pos))) { + pos--; + } + if (fl_isseparator(buffer()->character(pos))) pos++; + + insert_position( pos ); +} + +/* +** Callback attached to the text buffer to receive delete information before +** the modifications are actually made. +*/ +void My_Text_Display::buffer_predelete_cb(int pos, int nDeleted, void *cbArg) { + My_Text_Display *textD = (My_Text_Display *)cbArg; + if (textD->mContinuousWrap && + (textD->mFixedFontWidth == -1 || textD->mModifyingTabDistance)) + /* Note: we must perform this measurement, even if there is not a + single character deleted; the number of "deleted" lines is the + number of visual lines spanned by the real line in which the + modification takes place. + Also, a modification of the tab distance requires the same + kind of calculations in advance, even if the font width is "fixed", + because when the width of the tab characters changes, the layout + of the text may be completely different. */ + textD->measure_deleted_lines(pos, nDeleted); + else + textD->mSuppressResync = 0; /* Probably not needed, but just in case */ +} + +/* +** Callback attached to the text buffer to receive modification information +*/ +void My_Text_Display::buffer_modified_cb( int pos, int nInserted, int nDeleted, + int nRestyled, const char *deletedText, void *cbArg ) { + int linesInserted, linesDeleted, startDispPos, endDispPos; + My_Text_Display *textD = ( My_Text_Display * ) cbArg; + Fl_Text_Buffer *buf = textD->mBuffer; + int oldFirstChar = textD->mFirstChar; + int scrolled, origCursorPos = textD->mCursorPos; + int wrapModStart, wrapModEnd; + + /* buffer modification cancels vertical cursor motion column */ + if ( nInserted != 0 || nDeleted != 0 ) + textD->mCursorPreferredCol = -1; + + /* Count the number of lines inserted and deleted, and in the case + of continuous wrap mode, how much has changed */ + if (textD->mContinuousWrap) { + textD->find_wrap_range(deletedText, pos, nInserted, nDeleted, + &wrapModStart, &wrapModEnd, &linesInserted, &linesDeleted); + } else { + linesInserted = nInserted == 0 ? 0 : + buf->count_lines( pos, pos + nInserted ); + linesDeleted = nDeleted == 0 ? 0 : countlines( deletedText ); + } + + /* Update the line starts and mTopLineNum */ + if ( nInserted != 0 || nDeleted != 0 ) { + if (textD->mContinuousWrap) { + textD->update_line_starts( wrapModStart, wrapModEnd-wrapModStart, + nDeleted + pos-wrapModStart + (wrapModEnd-(pos+nInserted)), + linesInserted, linesDeleted, &scrolled ); + } else { + textD->update_line_starts( pos, nInserted, nDeleted, linesInserted, + linesDeleted, &scrolled ); + } + } else + scrolled = 0; + + /* If we're counting non-wrapped lines as well, maintain the absolute + (non-wrapped) line number of the text displayed */ + if (textD->maintaining_absolute_top_line_number() && + (nInserted != 0 || nDeleted != 0)) { + if (pos + nDeleted < oldFirstChar) + textD->mAbsTopLineNum += buf->count_lines(pos, pos + nInserted) - + countlines(deletedText); + else if (pos < oldFirstChar) + textD->reset_absolute_top_line_number(); + } + + /* Update the line count for the whole buffer */ + textD->mNBufferLines += linesInserted - linesDeleted; + + /* Update the cursor position */ + if ( textD->mCursorToHint != NO_HINT ) { + textD->mCursorPos = textD->mCursorToHint; + textD->mCursorToHint = NO_HINT; + } else if ( textD->mCursorPos > pos ) { + if ( textD->mCursorPos < pos + nDeleted ) + textD->mCursorPos = pos; + else + textD->mCursorPos += nInserted - nDeleted; + } + + // refigure scrollbars & stuff + if ((nInserted > 0) || (nDeleted > 0)) + textD->resize(textD->x(), textD->y(), textD->w(), textD->h()); + + // don't need to do anything else if not visible? + if (!textD->visible_r()) return; + + /* If the changes caused scrolling, re-paint everything and we're done. */ + if ( scrolled ) { + textD->damage(FL_DAMAGE_EXPOSE); + if ( textD->mStyleBuffer ) /* See comments in extendRangeForStyleMods */ + textD->mStyleBuffer->primary_selection()->selected(0); + return; + } + + /* If the changes didn't cause scrolling, decide the range of characters + that need to be re-painted. Also if the cursor position moved, be + sure that the redisplay range covers the old cursor position so the + old cursor gets erased, and erase the bits of the cursor which extend + beyond the left and right edges of the text. */ + startDispPos = textD->mContinuousWrap ? wrapModStart : pos; + if ( origCursorPos == startDispPos && textD->mCursorPos != startDispPos ) + startDispPos = min( startDispPos, origCursorPos - 1 ); + if ( linesInserted == linesDeleted ) { + if ( nInserted == 0 && nDeleted == 0 ) + endDispPos = pos + nRestyled; + else { + endDispPos = textD->mContinuousWrap ? wrapModEnd : + buf->line_end( pos + nInserted ) + 1; + // CET - FIXME if ( origCursorPos >= startDispPos && + // ( origCursorPos <= endDispPos || endDispPos == buf->length() ) ) + } + + if (linesInserted > 1) textD->draw_line_numbers(false); + } else { + endDispPos = textD->mLastChar + 1; + // CET - FIXME if ( origCursorPos >= pos ) + /* If more than one line is inserted/deleted, a line break may have + been inserted or removed in between, and the line numbers may + have changed. If only one line is altered, line numbers cannot + be affected (the insertion or removal of a line break always + results in at least two lines being redrawn). */ + textD->draw_line_numbers(false); + } + + /* If there is a style buffer, check if the modification caused additional + changes that need to be redisplayed. (Redisplaying separately would + cause double-redraw on almost every modification involving styled + text). Extend the redraw range to incorporate style changes */ + if ( textD->mStyleBuffer ) + textD->extend_range_for_styles( &startDispPos, &endDispPos ); + + /* Redisplay computed range */ + textD->redisplay_range( startDispPos, endDispPos ); +} + +/* +** In continuous wrap mode, internal line numbers are calculated after +** wrapping. A separate non-wrapped line count is maintained when line +** numbering is turned on. There is some performance cost to maintaining this +** line count, so normally absolute line numbers are not tracked if line +** numbering is off. This routine allows callers to specify that they still +** want this line count maintained (for use via TextDPosToLineAndCol). +** More specifically, this allows the line number reported in the statistics +** line to be calibrated in absolute lines, rather than post-wrapped lines. +*/ +void My_Text_Display::maintain_absolute_top_line_number(int state) { + mNeedAbsTopLineNum = state; + reset_absolute_top_line_number(); +} + +/* +** Returns the absolute (non-wrapped) line number of the first line displayed. +** Returns 0 if the absolute top line number is not being maintained. +*/ +int My_Text_Display::get_absolute_top_line_number() { + if (!mContinuousWrap) + return mTopLineNum; + if (maintaining_absolute_top_line_number()) + return mAbsTopLineNum; + return 0; +} + +/* +** Re-calculate absolute top line number for a change in scroll position. +*/ +void My_Text_Display::absolute_top_line_number(int oldFirstChar) { + if (maintaining_absolute_top_line_number()) { + if (mFirstChar < oldFirstChar) + mAbsTopLineNum -= buffer()->count_lines(mFirstChar, oldFirstChar); + else + mAbsTopLineNum += buffer()->count_lines(oldFirstChar, mFirstChar); + } +} + +/* +** Return true if a separate absolute top line number is being maintained +** (for displaying line numbers or showing in the statistics line). +*/ +int My_Text_Display::maintaining_absolute_top_line_number() { + return mContinuousWrap && + (mLineNumWidth != 0 || mNeedAbsTopLineNum); +} + +/* +** Count lines from the beginning of the buffer to reestablish the +** absolute (non-wrapped) top line number. If mode is not continuous wrap, +** or the number is not being maintained, does nothing. +*/ +void My_Text_Display::reset_absolute_top_line_number() { + mAbsTopLineNum = 1; + absolute_top_line_number(0); +} + +/* +** Find the line number of position "pos" relative to the first line of +** displayed text. Returns 0 if the line is not displayed. +*/ +int My_Text_Display::position_to_line( int pos, int *lineNum ) { + int i; + + *lineNum = 0; + if ( pos < mFirstChar ) return 0; + if ( pos > mLastChar ) { + if ( empty_vlines() ) { + if ( mLastChar < mBuffer->length() ) { + if ( !position_to_line( mLastChar, lineNum ) ) { + Fl::error("My_Text_Display::position_to_line(): Consistency check ptvl failed"); + return 0; + } + return ++( *lineNum ) <= mNVisibleLines - 1; + } else { + position_to_line( mLastChar - 1, lineNum ); + return 1; + } + } + return 0; + } + + for ( i = mNVisibleLines - 1; i >= 0; i-- ) { + if ( mLineStarts[ i ] != -1 && pos >= mLineStarts[ i ] ) { + *lineNum = i; + return 1; + } + } + return 0; /* probably never be reached */ +} + +/* +** Draw the text on a single line represented by "visLineNum" (the +** number of lines down from the top of the display), limited by +** "leftClip" and "rightClip" window coordinates and "leftCharIndex" and +** "rightCharIndex" character positions (not including the character at +** position "rightCharIndex"). +*/ +void My_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip, + int leftCharIndex, int rightCharIndex) { + Fl_Text_Buffer * buf = mBuffer; + int i, X, Y, startX, charIndex, lineStartPos, lineLen, fontHeight; + int stdCharWidth, charWidth, startIndex, charStyle, style; + int charLen, outStartIndex, outIndex; + int dispIndexOffset; + char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ], outStr[ MAX_DISP_LINE_LEN ]; + char *outPtr; + const char *lineStr; + +// printf("draw_vline(visLineNum=%d, leftClip=%d, rightClip=%d, leftCharIndex=%d, rightCharIndex=%d)\n", +// visLineNum, leftClip, rightClip, leftCharIndex, rightCharIndex); +// printf("nNVisibleLines=%d\n", mNVisibleLines); + + /* If line is not displayed, skip it */ + if ( visLineNum < 0 || visLineNum >= mNVisibleLines ) + return; + + /* Calculate Y coordinate of the string to draw */ + fontHeight = mMaxsize; + Y = text_area.y + visLineNum * fontHeight; + + /* Get the text, length, and buffer position of the line to display */ + lineStartPos = mLineStarts[ visLineNum ]; +// printf("lineStartPos=%d\n", lineStartPos); + if ( lineStartPos == -1 ) { + lineLen = 0; + lineStr = NULL; + } else { + lineLen = vline_length( visLineNum ); + lineStr = buf->text_range( lineStartPos, lineStartPos + lineLen ); + } + + /* Space beyond the end of the line is still counted in units of characters + of a standardized character width (this is done mostly because style + changes based on character position can still occur in this region due + to rectangular Fl_Text_Selections). stdCharWidth must be non-zero to + prevent a potential infinite loop if X does not advance */ + stdCharWidth = TMPFONTWIDTH; //mFontStruct->max_bounds.width; + if ( stdCharWidth <= 0 ) { + Fl::error("My_Text_Display::draw_vline(): bad font measurement"); + free((void *)lineStr); + return; + } + + /* Shrink the clipping range to the active display area */ + leftClip = max( text_area.x, leftClip ); + rightClip = min( rightClip, text_area.x + text_area.w ); + + /* Rectangular Fl_Text_Selections are based on "real" line starts (after + a newline or start of buffer). Calculate the difference between the + last newline position and the line start we're using. Since scanning + back to find a newline is expensive, only do so if there's actually a + rectangular Fl_Text_Selection which needs it */ + if (mContinuousWrap && (range_touches_selection(buf->primary_selection(), + lineStartPos, lineStartPos + lineLen) || range_touches_selection( + buf->secondary_selection(), lineStartPos, lineStartPos + lineLen) || + range_touches_selection(buf->highlight_selection(), lineStartPos, + lineStartPos + lineLen))) { + dispIndexOffset = buf->count_displayed_characters( + buf->line_start(lineStartPos), lineStartPos); + } else + dispIndexOffset = 0; + + /* Step through character positions from the beginning of the line (even if + that's off the left edge of the displayed area) to find the first + character position that's not clipped, and the X coordinate for drawing + that character */ + X = text_area.x - mHorizOffset; + outIndex = 0; + for ( charIndex = 0; ; charIndex++ ) { + charLen = charIndex >= lineLen ? 1 : + Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, + expandedChar, buf->tab_distance(), buf->null_substitution_character() ); + style = position_style( lineStartPos, lineLen, charIndex, + outIndex + dispIndexOffset ); + charWidth = charIndex >= lineLen ? stdCharWidth : + string_width( expandedChar, charLen, style ); + if ( X + charWidth >= leftClip && charIndex >= leftCharIndex ) { + startIndex = charIndex; + outStartIndex = outIndex; + startX = X; + break; + } + X += charWidth; + outIndex += charLen; + } + + /* Scan character positions from the beginning of the clipping range, and + draw parts whenever the style changes (also note if the cursor is on + this line, and where it should be drawn to take advantage of the x + position which we've gone to so much trouble to calculate) */ + outPtr = outStr; + outIndex = outStartIndex; + X = startX; + for ( charIndex = startIndex; charIndex < rightCharIndex; charIndex++ ) { + charLen = charIndex >= lineLen ? 1 : + Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar, + buf->tab_distance(), buf->null_substitution_character() ); + charStyle = position_style( lineStartPos, lineLen, charIndex, + outIndex + dispIndexOffset ); + for ( i = 0; i < charLen; i++ ) { + if ( i != 0 && charIndex < lineLen && lineStr[ charIndex ] == '\t' ) + charStyle = position_style( lineStartPos, lineLen, + charIndex, outIndex + dispIndexOffset ); + if ( charStyle != style ) { + draw_string( style, startX, Y, X, outStr, outPtr - outStr ); + outPtr = outStr; + startX = X; + style = charStyle; + } + if ( charIndex < lineLen ) { + *outPtr = expandedChar[ i ]; + charWidth = string_width( &expandedChar[ i ], 1, charStyle ); + } else + charWidth = stdCharWidth; + outPtr++; + X += charWidth; + outIndex++; + } + if ( outPtr - outStr + FL_TEXT_MAX_EXP_CHAR_LEN >= MAX_DISP_LINE_LEN || X >= rightClip ) + break; + } + + /* Draw the remaining style segment */ + draw_string( style, startX, Y, X, outStr, outPtr - outStr ); + + /* Draw the cursor if part of it appeared on the redisplayed part of + this line. Also check for the cases which are not caught as the + line is scanned above: when the cursor appears at the very end + of the redisplayed section. */ + /* CET - FIXME + if ( mCursorOn ) + { + if ( hasCursor ) + draw_cursor( cursorX, Y ); + else if ( charIndex < lineLen && ( lineStartPos + charIndex + 1 == cursorPos ) + && X == rightClip ) + { + if ( cursorPos >= buf->length() ) + draw_cursor( X - 1, Y ); + else + { + draw_cursor( X - 1, Y ); + } + } + } + */ + if ( lineStr != NULL ) + free((void *)lineStr); +} + +/* +** Draw a string or blank area according to parameter "style", using the +** appropriate colors and drawing method for that style, with top left +** corner at X, y. If style says to draw text, use "string" as source of +** characters, and draw "nChars", if style is FILL, erase +** rectangle where text would have drawn from X to toX and from Y to +** the maximum Y extent of the current font(s). +*/ +void My_Text_Display::draw_string( int style, int X, int Y, int toX, + const char *string, int nChars ) { + const Style_Table_Entry * styleRec; + + /* Draw blank area rather than text, if that was the request */ + if ( style & FILL_MASK ) { + clear_rect( style, X, Y, toX - X, mMaxsize ); + return; + } + + /* Set font, color, and gc depending on style. For normal text, GCs + for normal drawing, or drawing within a Fl_Text_Selection or highlight are + pre-allocated and pre-configured. For syntax highlighting, GCs are + configured here, on the fly. */ + + Fl_Font font = textfont(); + int fsize = textsize(); + Fl_Color foreground; + Fl_Color background; + + if ( style & STYLE_LOOKUP_MASK ) + { + int si = (style & STYLE_LOOKUP_MASK) - 'A'; + if (si < 0) si = 0; + else if (si >= mNStyles) si = mNStyles - 1; + + styleRec = mStyleTable + si; + font = styleRec->font; + fsize = styleRec->size; + + if ( style & (HIGHLIGHT_MASK | PRIMARY_MASK) && Fl::focus() == this) + { + background = selection_color(); + foreground = fl_contrast(styleRec->color, background); + foreground = FL_WHITE; + } else { + background = color(); + foreground = styleRec->color; + } + } else if ( style & (HIGHLIGHT_MASK | PRIMARY_MASK) && Fl::focus() == this ) { + background = selection_color(); + //foreground = fl_contrast(textcolor(), background); + foreground = textcolor(); + foreground = FL_WHITE; + } else { + foreground = textcolor(); + background = color(); + } + + fl_color( background ); + fl_rectf( X, Y, toX - X, mMaxsize ); + fl_color( foreground ); + fl_font( font, fsize ); + fl_draw( string, nChars, X, Y + mMaxsize - fl_descent()); + + // CET - FIXME + /* If any space around the character remains unfilled (due to use of + different sized fonts for highlighting), fill in above or below + to erase previously drawn characters */ + /* + if (fs->ascent < mAscent) + clear_rect( style, X, Y, toX - X, mAscent - fs->ascent); + if (fs->descent < mDescent) + clear_rect( style, X, Y + mAscent + fs->descent, toX - x, + mDescent - fs->descent); + */ + /* Underline if style is secondary Fl_Text_Selection */ + + /* + if (style & SECONDARY_MASK) + XDrawLine(XtDisplay(mW), XtWindow(mW), gc, x, + y + mAscent, toX - 1, Y + fs->ascent); + */ +} + +/* +** Clear a rectangle with the appropriate background color for "style" +*/ +void My_Text_Display::clear_rect( int style, int X, int Y, + int width, int height ) { + /* A width of zero means "clear to end of window" to XClearArea */ + if ( width == 0 ) + return; + + if ( Fl::focus() != this ) { + fl_color( color() ); + fl_rectf( X, Y, width, height ); + } else if ( style & HIGHLIGHT_MASK ) { + fl_color( fl_contrast(textcolor(), color()) ); + fl_rectf( X, Y, width, height ); + } else if ( style & PRIMARY_MASK ) { + fl_color( selection_color() ); + fl_rectf( X, Y, width, height ); + } else { + fl_color( color() ); + fl_rectf( X, Y, width, height ); + } +} + + + +/* +** Draw a cursor with top center at X, y. +*/ +void My_Text_Display::draw_cursor( int X, int Y ) { + typedef struct { + int x1, y1, x2, y2; + } + Segment; + + Segment segs[ 5 ]; + int left, right, cursorWidth, midY; + // int fontWidth = mFontStruct->min_bounds.width, nSegs = 0; + int fontWidth = TMPFONTWIDTH; // CET - FIXME + int nSegs = 0; + int fontHeight = mMaxsize; + int bot = Y + fontHeight - 1; + + if ( X < text_area.x - 1 || X > text_area.x + text_area.w ) + return; + + /* For cursors other than the block, make them around 2/3 of a character + width, rounded to an even number of pixels so that X will draw an + odd number centered on the stem at x. */ + cursorWidth = 4; //(fontWidth/3) * 2; + left = X - cursorWidth / 2; + right = left + cursorWidth; + + /* Create segments and draw cursor */ + if ( mCursorStyle == CARET_CURSOR ) { + midY = bot - fontHeight / 5; + segs[ 0 ].x1 = left; segs[ 0 ].y1 = bot; segs[ 0 ].x2 = X; segs[ 0 ].y2 = midY; + segs[ 1 ].x1 = X; segs[ 1 ].y1 = midY; segs[ 1 ].x2 = right; segs[ 1 ].y2 = bot; + segs[ 2 ].x1 = left; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = X; segs[ 2 ].y2 = midY - 1; + segs[ 3 ].x1 = X; segs[ 3 ].y1 = midY - 1; segs[ 3 ].x2 = right; segs[ 3 ].y2 = bot; + nSegs = 4; + } else if ( mCursorStyle == NORMAL_CURSOR ) { + segs[ 0 ].x1 = left; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = right; segs[ 0 ].y2 = Y; + segs[ 1 ].x1 = X; segs[ 1 ].y1 = Y; segs[ 1 ].x2 = X; segs[ 1 ].y2 = bot; + segs[ 2 ].x1 = left; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = right; segs[ 2 ].y2 = bot; + nSegs = 3; + } else if ( mCursorStyle == HEAVY_CURSOR ) { + segs[ 0 ].x1 = X - 1; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = X - 1; segs[ 0 ].y2 = bot; + segs[ 1 ].x1 = X; segs[ 1 ].y1 = Y; segs[ 1 ].x2 = X; segs[ 1 ].y2 = bot; + segs[ 2 ].x1 = X + 1; segs[ 2 ].y1 = Y; segs[ 2 ].x2 = X + 1; segs[ 2 ].y2 = bot; + segs[ 3 ].x1 = left; segs[ 3 ].y1 = Y; segs[ 3 ].x2 = right; segs[ 3 ].y2 = Y; + segs[ 4 ].x1 = left; segs[ 4 ].y1 = bot; segs[ 4 ].x2 = right; segs[ 4 ].y2 = bot; + nSegs = 5; + } else if ( mCursorStyle == DIM_CURSOR ) { + midY = Y + fontHeight / 2; + segs[ 0 ].x1 = X; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = X; segs[ 0 ].y2 = Y; + segs[ 1 ].x1 = X; segs[ 1 ].y1 = midY; segs[ 1 ].x2 = X; segs[ 1 ].y2 = midY; + segs[ 2 ].x1 = X; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = X; segs[ 2 ].y2 = bot; + nSegs = 3; + } else if ( mCursorStyle == BLOCK_CURSOR ) { + right = X + fontWidth; + segs[ 0 ].x1 = X; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = right; segs[ 0 ].y2 = Y; + segs[ 1 ].x1 = right; segs[ 1 ].y1 = Y; segs[ 1 ].x2 = right; segs[ 1 ].y2 = bot; + segs[ 2 ].x1 = right; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = X; segs[ 2 ].y2 = bot; + segs[ 3 ].x1 = X; segs[ 3 ].y1 = bot; segs[ 3 ].x2 = X; segs[ 3 ].y2 = Y; + nSegs = 4; + } + fl_color( mCursor_color ); + + for ( int k = 0; k < nSegs; k++ ) { + fl_line( segs[ k ].x1, segs[ k ].y1, segs[ k ].x2, segs[ k ].y2 ); + } +} + +/* +** Determine the drawing method to use to draw a specific character from "buf". +** "lineStartPos" gives the character index where the line begins, "lineIndex", +** the number of characters past the beginning of the line, and "dispIndex", +** the number of displayed characters past the beginning of the line. Passing +** lineStartPos of -1 returns the drawing style for "no text". +** +** Why not just: position_style(pos)? Because style applies to blank areas +** of the window beyond the text boundaries, and because this routine must also +** decide whether a position is inside of a rectangular Fl_Text_Selection, and do +** so efficiently, without re-counting character positions from the start of the +** line. +** +** Note that style is a somewhat incorrect name, drawing method would +** be more appropriate. +*/ +int My_Text_Display::position_style( int lineStartPos, + int lineLen, int lineIndex, int dispIndex ) { + Fl_Text_Buffer * buf = mBuffer; + Fl_Text_Buffer *styleBuf = mStyleBuffer; + int pos, style = 0; + + if ( lineStartPos == -1 || buf == NULL ) + return FILL_MASK; + + pos = lineStartPos + min( lineIndex, lineLen ); + + if ( lineIndex >= lineLen ) + style = FILL_MASK; + else if ( styleBuf != NULL ) { + style = ( unsigned char ) styleBuf->character( pos ); + if (style == mUnfinishedStyle) { + /* encountered "unfinished" style, trigger parsing */ + (mUnfinishedHighlightCB)( pos, mHighlightCBArg); + style = (unsigned char) styleBuf->character( pos); + } + } + if (buf->primary_selection()->includes(pos, lineStartPos, dispIndex)) + style |= PRIMARY_MASK; + if (buf->highlight_selection()->includes(pos, lineStartPos, dispIndex)) + style |= HIGHLIGHT_MASK; + if (buf->secondary_selection()->includes(pos, lineStartPos, dispIndex)) + style |= SECONDARY_MASK; + return style; +} + +/* +** Find the width of a string in the font of a particular style +*/ +int My_Text_Display::string_width( const char *string, int length, int style ) { + Fl_Font font; + int fsize; + + if ( style & STYLE_LOOKUP_MASK ) { + int si = (style & STYLE_LOOKUP_MASK) - 'A'; + if (si < 0) si = 0; + else if (si >= mNStyles) si = mNStyles - 1; + + font = mStyleTable[si].font; + fsize = mStyleTable[si].size; + } else { + font = textfont(); + fsize = textsize(); + } + fl_font( font, fsize ); + + return ( int ) ( fl_width( string, length ) ); +} + +/* +** Translate window coordinates to the nearest (insert cursor or character +** cell) text position. The parameter posType specifies how to interpret the +** position: CURSOR_POS means translate the coordinates to the nearest cursor +** position, and CHARACTER_POS means return the position of the character +** closest to (X, Y). +*/ +int My_Text_Display::xy_to_position( int X, int Y, int posType ) { + int charIndex, lineStart, lineLen, fontHeight; + int charWidth, charLen, charStyle, visLineNum, xStep, outIndex; + char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ]; + const char *lineStr; + + /* Find the visible line number corresponding to the Y coordinate */ + fontHeight = mMaxsize; + visLineNum = ( Y - text_area.y ) / fontHeight; + if ( visLineNum < 0 ) + return mFirstChar; + if ( visLineNum >= mNVisibleLines ) + visLineNum = mNVisibleLines - 1; + + /* Find the position at the start of the line */ + lineStart = mLineStarts[ visLineNum ]; + + /* If the line start was empty, return the last position in the buffer */ + if ( lineStart == -1 ) + return mBuffer->length(); + + /* Get the line text and its length */ + lineLen = vline_length( visLineNum ); + lineStr = mBuffer->text_range( lineStart, lineStart + lineLen ); + + /* Step through character positions from the beginning of the line + to find the character position corresponding to the X coordinate */ + xStep = text_area.x - mHorizOffset; + outIndex = 0; + for ( charIndex = 0; charIndex < lineLen; charIndex++ ) { + charLen = Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar, + mBuffer->tab_distance(), mBuffer->null_substitution_character() ); + charStyle = position_style( lineStart, lineLen, charIndex, outIndex ); + charWidth = string_width( expandedChar, charLen, charStyle ); + if ( X < xStep + ( posType == CURSOR_POS ? charWidth / 2 : charWidth ) ) { + delete [] (char *)lineStr; + return lineStart + charIndex; + } + xStep += charWidth; + outIndex += charLen; + } + + /* If the X position was beyond the end of the line, return the position + of the newline at the end of the line */ + delete [] (char *)lineStr; + return lineStart + lineLen; +} + +/* +** Translate window coordinates to the nearest row and column number for +** positioning the cursor. This, of course, makes no sense when the font is +** proportional, since there are no absolute columns. The parameter posType +** specifies how to interpret the position: CURSOR_POS means translate the +** coordinates to the nearest position between characters, and CHARACTER_POS +** means translate the position to the nearest character cell. +*/ +void My_Text_Display::xy_to_rowcol( int X, int Y, int *row, + int *column, int posType ) { + int fontHeight = mMaxsize; + int fontWidth = TMPFONTWIDTH; //mFontStruct->max_bounds.width; + + /* Find the visible line number corresponding to the Y coordinate */ + *row = ( Y - text_area.y ) / fontHeight; + if ( *row < 0 ) * row = 0; + if ( *row >= mNVisibleLines ) * row = mNVisibleLines - 1; + *column = ( ( X - text_area.x ) + mHorizOffset + + ( posType == CURSOR_POS ? fontWidth / 2 : 0 ) ) / fontWidth; + if ( *column < 0 ) * column = 0; +} + +/* +** Offset the line starts array, mTopLineNum, mFirstChar and lastChar, for a new +** vertical scroll position given by newTopLineNum. If any currently displayed +** lines will still be visible, salvage the line starts values, otherwise, +** count lines from the nearest known line start (start or end of buffer, or +** the closest value in the mLineStarts array) +*/ +void My_Text_Display::offset_line_starts( int newTopLineNum ) { + int oldTopLineNum = mTopLineNum; + int oldFirstChar = mFirstChar; + int lineDelta = newTopLineNum - oldTopLineNum; + int nVisLines = mNVisibleLines; + int *lineStarts = mLineStarts; + int i, lastLineNum; + Fl_Text_Buffer *buf = mBuffer; + + /* If there was no offset, nothing needs to be changed */ + if ( lineDelta == 0 ) + return; + + /* Find the new value for mFirstChar by counting lines from the nearest + known line start (start or end of buffer, or the closest value in the + lineStarts array) */ + lastLineNum = oldTopLineNum + nVisLines - 1; + if ( newTopLineNum < oldTopLineNum && newTopLineNum < -lineDelta ) { + mFirstChar = skip_lines( 0, newTopLineNum - 1, true ); + } else if ( newTopLineNum < oldTopLineNum ) { + mFirstChar = buffer()->rewind_lines( mFirstChar, -lineDelta ); + } else if ( newTopLineNum < lastLineNum ) { + mFirstChar = lineStarts[ newTopLineNum - oldTopLineNum ]; + } else if ( newTopLineNum - lastLineNum < mNBufferLines - newTopLineNum ) { + mFirstChar = skip_lines( lineStarts[ nVisLines - 1 ], + newTopLineNum - lastLineNum, true ); + } else { + mFirstChar = buffer()->rewind_lines( buf->length(), mNBufferLines - newTopLineNum + 1 ); + } + + /* Fill in the line starts array */ + if ( lineDelta < 0 && -lineDelta < nVisLines ) { + for ( i = nVisLines - 1; i >= -lineDelta; i-- ) + lineStarts[ i ] = lineStarts[ i + lineDelta ]; + calc_line_starts( 0, -lineDelta ); + } else if ( lineDelta > 0 && lineDelta < nVisLines ) { + for ( i = 0; i < nVisLines - lineDelta; i++ ) + lineStarts[ i ] = lineStarts[ i + lineDelta ]; + calc_line_starts( nVisLines - lineDelta, nVisLines - 1 ); + } else + calc_line_starts( 0, nVisLines ); + + /* Set lastChar and mTopLineNum */ + calc_last_char(); + mTopLineNum = newTopLineNum; + + /* If we're numbering lines or being asked to maintain an absolute line + number, re-calculate the absolute line number */ + absolute_top_line_number(oldFirstChar); +} + +/* +** Update the line starts array, mTopLineNum, mFirstChar and lastChar for text +** display "textD" after a modification to the text buffer, given by the +** position where the change began "pos", and the nmubers of characters +** and lines inserted and deleted. +*/ +void My_Text_Display::update_line_starts( int pos, int charsInserted, + int charsDeleted, int linesInserted, int linesDeleted, int *scrolled ) { + int * lineStarts = mLineStarts; + int i, lineOfPos, lineOfEnd, nVisLines = mNVisibleLines; + int charDelta = charsInserted - charsDeleted; + int lineDelta = linesInserted - linesDeleted; + + /* If all of the changes were before the displayed text, the display + doesn't change, just update the top line num and offset the line + start entries and first and last characters */ + if ( pos + charsDeleted < mFirstChar ) { + mTopLineNum += lineDelta; + for ( i = 0; i < nVisLines && lineStarts[i] != -1; i++ ) + lineStarts[ i ] += charDelta; + mFirstChar += charDelta; + mLastChar += charDelta; + *scrolled = 0; + return; + } + + /* The change began before the beginning of the displayed text, but + part or all of the displayed text was deleted */ + if ( pos < mFirstChar ) { + /* If some text remains in the window, anchor on that */ + if ( position_to_line( pos + charsDeleted, &lineOfEnd ) && + ++lineOfEnd < nVisLines && lineStarts[ lineOfEnd ] != -1 ) { + mTopLineNum = max( 1, mTopLineNum + lineDelta ); + mFirstChar = buffer()->rewind_lines( + lineStarts[ lineOfEnd ] + charDelta, lineOfEnd ); + /* Otherwise anchor on original line number and recount everything */ + } else { + if ( mTopLineNum > mNBufferLines + lineDelta ) { + mTopLineNum = 1; + mFirstChar = 0; + } else + mFirstChar = skip_lines( 0, mTopLineNum - 1, true ); + } + calc_line_starts( 0, nVisLines - 1 ); + /* calculate lastChar by finding the end of the last displayed line */ + calc_last_char(); + *scrolled = 1; + return; + } + + /* If the change was in the middle of the displayed text (it usually is), + salvage as much of the line starts array as possible by moving and + offsetting the entries after the changed area, and re-counting the + added lines or the lines beyond the salvaged part of the line starts + array */ + if ( pos <= mLastChar ) { + /* find line on which the change began */ + position_to_line( pos, &lineOfPos ); + /* salvage line starts after the changed area */ + if ( lineDelta == 0 ) { + for ( i = lineOfPos + 1; i < nVisLines && lineStarts[ i ] != -1; i++ ) + lineStarts[ i ] += charDelta; + } else if ( lineDelta > 0 ) { + for ( i = nVisLines - 1; i >= lineOfPos + lineDelta + 1; i-- ) + lineStarts[ i ] = lineStarts[ i - lineDelta ] + + ( lineStarts[ i - lineDelta ] == -1 ? 0 : charDelta ); + } else /* (lineDelta < 0) */ { + for ( i = max( 0, lineOfPos + 1 ); i < nVisLines + lineDelta; i++ ) + lineStarts[ i ] = lineStarts[ i - lineDelta ] + + ( lineStarts[ i - lineDelta ] == -1 ? 0 : charDelta ); + } + /* fill in the missing line starts */ + if ( linesInserted >= 0 ) + calc_line_starts( lineOfPos + 1, lineOfPos + linesInserted ); + if ( lineDelta < 0 ) + calc_line_starts( nVisLines + lineDelta, nVisLines ); + /* calculate lastChar by finding the end of the last displayed line */ + calc_last_char(); + *scrolled = 0; + return; + } + + /* Change was past the end of the displayed text, but displayable by virtue + of being an insert at the end of the buffer into visible blank lines */ + if ( empty_vlines() ) { + position_to_line( pos, &lineOfPos ); + calc_line_starts( lineOfPos, lineOfPos + linesInserted ); + calc_last_char(); + *scrolled = 0; + return; + } + + /* Change was beyond the end of the buffer and not visible, do nothing */ + *scrolled = 0; +} + +/* +** Scan through the text in the "textD"'s buffer and recalculate the line +** starts array values beginning at index "startLine" and continuing through +** (including) "endLine". It assumes that the line starts entry preceding +** "startLine" (or mFirstChar if startLine is 0) is good, and re-counts +** newlines to fill in the requested entries. Out of range values for +** "startLine" and "endLine" are acceptable. +*/ +void My_Text_Display::calc_line_starts( int startLine, int endLine ) { + int startPos, bufLen = mBuffer->length(); + int line, lineEnd, nextLineStart, nVis = mNVisibleLines; + int *lineStarts = mLineStarts; + + /* Clean up (possibly) messy input parameters */ + if ( endLine < 0 ) endLine = 0; + if ( endLine >= nVis ) endLine = nVis - 1; + if ( startLine < 0 ) startLine = 0; + if ( startLine >= nVis ) startLine = nVis - 1; + if ( startLine > endLine ) + return; + + /* Find the last known good line number -> position mapping */ + if ( startLine == 0 ) { + lineStarts[ 0 ] = mFirstChar; + startLine = 1; + } + startPos = lineStarts[ startLine - 1 ]; + + /* If the starting position is already past the end of the text, + fill in -1's (means no text on line) and return */ + if ( startPos == -1 ) { + for ( line = startLine; line <= endLine; line++ ) + lineStarts[ line ] = -1; + return; + } + + /* Loop searching for ends of lines and storing the positions of the + start of the next line in lineStarts */ + for ( line = startLine; line <= endLine; line++ ) { + find_line_end(startPos, true, &lineEnd, &nextLineStart); + startPos = nextLineStart; + if ( startPos >= bufLen ) { + /* If the buffer ends with a newline or line break, put + buf->length() in the next line start position (instead of + a -1 which is the normal marker for an empty line) to + indicate that the cursor may safely be displayed there */ + if ( line == 0 || ( lineStarts[ line - 1 ] != bufLen && + lineEnd != nextLineStart ) ) { + lineStarts[ line ] = bufLen; + line++; + } + break; + } + lineStarts[ line ] = startPos; + } + + /* Set any entries beyond the end of the text to -1 */ + for ( ; line <= endLine; line++ ) + lineStarts[ line ] = -1; +} + +/* +** Given a My_Text_Display with a complete, up-to-date lineStarts array, update +** the lastChar entry to point to the last buffer position displayed. +*/ +void My_Text_Display::calc_last_char() { + int i; + for (i = mNVisibleLines - 1; i >= 0 && mLineStarts[i] == -1; i--) ; + mLastChar = i < 0 ? 0 : line_end(mLineStarts[i], true); +} + +void My_Text_Display::scroll(int topLineNum, int horizOffset) { + mTopLineNumHint = topLineNum; + mHorizOffsetHint = horizOffset; + resize(x(), y(), w(), h()); +} + +void My_Text_Display::scroll_(int topLineNum, int horizOffset) { + /* Limit the requested scroll position to allowable values */ + if (topLineNum > mNBufferLines + 3 - mNVisibleLines) + topLineNum = mNBufferLines + 3 - mNVisibleLines; + if (topLineNum < 1) topLineNum = 1; + + if (horizOffset > longest_vline() - text_area.w) + horizOffset = longest_vline() - text_area.w; + if (horizOffset < 0) horizOffset = 0; + + /* Do nothing if scroll position hasn't actually changed or there's no + window to draw in yet */ + if (mHorizOffset == horizOffset && mTopLineNum == topLineNum) + return; + + /* If the vertical scroll position has changed, update the line + starts array and related counters in the text display */ + offset_line_starts(topLineNum); + + /* Just setting mHorizOffset is enough information for redisplay */ + mHorizOffset = horizOffset; + + // redraw all text + damage(FL_DAMAGE_EXPOSE); +} + +/* +** Update the minimum, maximum, slider size, page increment, and value +** for vertical scroll bar. +*/ +void My_Text_Display::update_v_scrollbar() { + /* The Vert. scroll bar value and slider size directly represent the top + line number, and the number of visible lines respectively. The scroll + bar maximum value is chosen to generally represent the size of the whole + buffer, with minor adjustments to keep the scroll bar widget happy */ + mVScrollBar->value(mTopLineNum, mNVisibleLines, 1, mNBufferLines+2); + mVScrollBar->linesize(3); +} + +/* +** Update the minimum, maximum, slider size, page increment, and value +** for the horizontal scroll bar. +*/ +void My_Text_Display::update_h_scrollbar() { + int sliderMax = max(longest_vline(), text_area.w + mHorizOffset); + mHScrollBar->value( mHorizOffset, text_area.w, 0, sliderMax ); +} + +/* +** Callbacks for drag or valueChanged on scroll bars +*/ +void My_Text_Display::v_scrollbar_cb(Fl_Scrollbar* b, My_Text_Display* textD) { + if (b->value() == textD->mTopLineNum) return; + textD->scroll(b->value(), textD->mHorizOffset); +} + +void My_Text_Display::h_scrollbar_cb(Fl_Scrollbar* b, My_Text_Display* textD) { + if (b->value() == textD->mHorizOffset) return; + textD->scroll(textD->mTopLineNum, b->value()); +} + +/* +** Refresh the line number area. If clearAll is False, writes only over +** the character cell areas. Setting clearAll to True will clear out any +** stray marks outside of the character cell area, which might have been +** left from before a resize or font change. +*/ +void My_Text_Display::draw_line_numbers(bool clearAll) { +#if 0 + // FIXME: don't want this yet, so will leave for another time + + int y, line, visLine, nCols, lineStart; + char lineNumString[12]; + int lineHeight = mMaxsize ? mMaxsize : textsize_; + int charWidth = TMPFONTWIDTH; //mFontStruct->max_bounds.width; + + /* Don't draw if mLineNumWidth == 0 (line numbers are hidden), or widget is + not yet realized */ + if (mLineNumWidth == 0 || visible_r()) + return; + + /* GC is allocated on demand, since not everyone will use line numbering */ + if (textD->lineNumGC == NULL) { + XGCValues values; + values.foreground = textD->lineNumFGPixel; + values.background = textD->bgPixel; + values.font = textD->fontStruct->fid; + textD->lineNumGC = XtGetGC(textD->w, + GCFont| GCForeground | GCBackground, &values); + } + + /* Erase the previous contents of the line number area, if requested */ + if (clearAll) + XClearArea(XtDisplay(textD->w), XtWindow(textD->w), textD->lineNumLeft, + textD->top, textD->lineNumWidth, textD->height, False); + + /* Draw the line numbers, aligned to the text */ + nCols = min(11, textD->lineNumWidth / charWidth); + y = textD->top; + line = getAbsTopLineNum(textD); + for (visLine=0; visLine < textD->nVisibleLines; visLine++) { + lineStart = textD->lineStarts[visLine]; + if (lineStart != -1 && (lineStart==0 || + BufGetCharacter(textD->buffer, lineStart-1)=='\n')) { + sprintf(lineNumString, "%*d", nCols, line); + XDrawImageString(XtDisplay(textD->w), XtWindow(textD->w), + textD->lineNumGC, textD->lineNumLeft, y + textD->ascent, + lineNumString, strlen(lineNumString)); + line++; + } else { + XClearArea(XtDisplay(textD->w), XtWindow(textD->w), + textD->lineNumLeft, y, textD->lineNumWidth, + textD->ascent + textD->descent, False); + if (visLine == 0) + line++; + } + y += lineHeight; + } +#endif +} + +static int max( int i1, int i2 ) { + return i1 >= i2 ? i1 : i2; +} + +static int min( int i1, int i2 ) { + return i1 <= i2 ? i1 : i2; +} + +/* +** Count the number of newlines in a null-terminated text string; +*/ +static int countlines( const char *string ) { + const char * c; + int lineCount = 0; + + if (!string) return 0; + + for ( c = string; *c != '\0'; c++ ) + if ( *c == '\n' ) lineCount++; + return lineCount; +} + +/* +** Return the width in pixels of the displayed line pointed to by "visLineNum" +*/ +int My_Text_Display::measure_vline( int visLineNum ) { + int i, width = 0, len, style, lineLen = vline_length( visLineNum ); + int charCount = 0, lineStartPos = mLineStarts[ visLineNum ]; + char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ]; + + if (lineStartPos < 0 || lineLen == 0) return 0; + if ( mStyleBuffer == NULL ) { + for ( i = 0; i < lineLen; i++ ) { + len = mBuffer->expand_character( lineStartPos + i, + charCount, expandedChar ); + + fl_font( textfont(), textsize() ); + + width += ( int ) fl_width( expandedChar, len ); + + charCount += len; + } + } else { + for ( i = 0; i < lineLen; i++ ) { + len = mBuffer->expand_character( lineStartPos + i, + charCount, expandedChar ); + style = ( unsigned char ) mStyleBuffer->character( + lineStartPos + i ) - 'A'; + + if (style < 0) style = 0; + else if (style >= mNStyles) style = mNStyles - 1; + + fl_font( mStyleTable[ style ].font, mStyleTable[ style ].size ); + + width += ( int ) fl_width( expandedChar, len ); + + charCount += len; + } + } + return width; +} + +/* +** Return true if there are lines visible with no corresponding buffer text +*/ +int My_Text_Display::empty_vlines() { + return mNVisibleLines > 0 && + mLineStarts[ mNVisibleLines - 1 ] == -1; +} + +/* +** Return the length of a line (number of displayable characters) by examining +** entries in the line starts array rather than by scanning for newlines +*/ +int My_Text_Display::vline_length( int visLineNum ) { + int nextLineStart, lineStartPos; + + if (visLineNum < 0 || visLineNum >= mNVisibleLines) + return (0); + + lineStartPos = mLineStarts[ visLineNum ]; + + if ( lineStartPos == -1 ) + return 0; + if ( visLineNum + 1 >= mNVisibleLines ) + return mLastChar - lineStartPos; + nextLineStart = mLineStarts[ visLineNum + 1 ]; + if ( nextLineStart == -1 ) + return mLastChar - lineStartPos; + if (wrap_uses_character(nextLineStart-1)) + return nextLineStart-1 - lineStartPos; + return nextLineStart - lineStartPos; +} + +/* +** When continuous wrap is on, and the user inserts or deletes characters, +** wrapping can happen before and beyond the changed position. This routine +** finds the extent of the changes, and counts the deleted and inserted lines +** over that range. It also attempts to minimize the size of the range to +** what has to be counted and re-displayed, so the results can be useful +** both for delimiting where the line starts need to be recalculated, and +** for deciding what part of the text to redisplay. +*/ +void My_Text_Display::find_wrap_range(const char *deletedText, int pos, + int nInserted, int nDeleted, int *modRangeStart, int *modRangeEnd, + int *linesInserted, int *linesDeleted) { + int length, retPos, retLines, retLineStart, retLineEnd; + Fl_Text_Buffer *deletedTextBuf, *buf = buffer(); + int nVisLines = mNVisibleLines; + int *lineStarts = mLineStarts; + int countFrom, countTo, lineStart, adjLineStart, i; + int visLineNum = 0, nLines = 0; + + /* + ** Determine where to begin searching: either the previous newline, or + ** if possible, limit to the start of the (original) previous displayed + ** line, using information from the existing line starts array + */ + if (pos >= mFirstChar && pos <= mLastChar) { + for (i=nVisLines-1; i>0; i--) + if (lineStarts[i] != -1 && pos >= lineStarts[i]) + break; + if (i > 0) { + countFrom = lineStarts[i-1]; + visLineNum = i-1; + } else + countFrom = buf->line_start(pos); + } else + countFrom = buf->line_start(pos); + + + /* + ** Move forward through the (new) text one line at a time, counting + ** displayed lines, and looking for either a real newline, or for the + ** line starts to re-sync with the original line starts array + */ + lineStart = countFrom; + *modRangeStart = countFrom; + while (true) { + + /* advance to the next line. If the line ended in a real newline + or the end of the buffer, that's far enough */ + wrapped_line_counter(buf, lineStart, buf->length(), 1, true, 0, + &retPos, &retLines, &retLineStart, &retLineEnd); + if (retPos >= buf->length()) { + countTo = buf->length(); + *modRangeEnd = countTo; + if (retPos != retLineEnd) + nLines++; + break; + } else + lineStart = retPos; + nLines++; + if (lineStart > pos + nInserted && + buf->character(lineStart-1) == '\n') { + countTo = lineStart; + *modRangeEnd = lineStart; + break; + } + + /* Don't try to resync in continuous wrap mode with non-fixed font + sizes; it would result in a chicken-and-egg dependency between + the calculations for the inserted and the deleted lines. + If we're in that mode, the number of deleted lines is calculated in + advance, without resynchronization, so we shouldn't resynchronize + for the inserted lines either. */ + if (mSuppressResync) + continue; + + /* check for synchronization with the original line starts array + before pos, if so, the modified range can begin later */ + if (lineStart <= pos) { + while (visLineNum pos + nInserted) { + adjLineStart = lineStart - nInserted + nDeleted; + while (visLineNumcopy(buffer(), countFrom, pos, 0); + if (nDeleted != 0) + deletedTextBuf->insert(pos-countFrom, deletedText); + deletedTextBuf->copy(buffer(), + pos+nInserted, countTo, pos-countFrom+nDeleted); + /* Note that we need to take into account an offset for the style buffer: + the deletedTextBuf can be out of sync with the style buffer. */ + wrapped_line_counter(deletedTextBuf, 0, length, INT_MAX, true, + countFrom, &retPos, &retLines, &retLineStart, &retLineEnd, false); + delete deletedTextBuf; + *linesDeleted = retLines; + mSuppressResync = 0; +} + +/* +** This is a stripped-down version of the findWrapRange() function above, +** intended to be used to calculate the number of "deleted" lines during +** a buffer modification. It is called _before_ the modification takes place. +** +** This function should only be called in continuous wrap mode with a +** non-fixed font width. In that case, it is impossible to calculate +** the number of deleted lines, because the necessary style information +** is no longer available _after_ the modification. In other cases, we +** can still perform the calculation afterwards (possibly even more +** efficiently). +*/ +void My_Text_Display::measure_deleted_lines(int pos, int nDeleted) { + int retPos, retLines, retLineStart, retLineEnd; + Fl_Text_Buffer *buf = buffer(); + int nVisLines = mNVisibleLines; + int *lineStarts = mLineStarts; + int countFrom, lineStart; + int visLineNum = 0, nLines = 0, i; + /* + ** Determine where to begin searching: either the previous newline, or + ** if possible, limit to the start of the (original) previous displayed + ** line, using information from the existing line starts array + */ + if (pos >= mFirstChar && pos <= mLastChar) { + for (i=nVisLines-1; i>0; i--) + if (lineStarts[i] != -1 && pos >= lineStarts[i]) + break; + if (i > 0) { + countFrom = lineStarts[i-1]; + visLineNum = i-1; + } else + countFrom = buf->line_start(pos); + } else + countFrom = buf->line_start(pos); + + /* + ** Move forward through the (new) text one line at a time, counting + ** displayed lines, and looking for either a real newline, or for the + ** line starts to re-sync with the original line starts array + */ + lineStart = countFrom; + while (true) { + /* advance to the next line. If the line ended in a real newline + or the end of the buffer, that's far enough */ + wrapped_line_counter(buf, lineStart, buf->length(), 1, true, 0, + &retPos, &retLines, &retLineStart, &retLineEnd); + if (retPos >= buf->length()) { + if (retPos != retLineEnd) + nLines++; + break; + } else + lineStart = retPos; + nLines++; + if (lineStart > pos + nDeleted && + buf->character(lineStart-1) == '\n') { + break; + } + + /* Unlike in the findWrapRange() function above, we don't try to + resync with the line starts, because we don't know the length + of the inserted text yet, nor the updated style information. + + Because of that, we also shouldn't resync with the line starts + after the modification either, because we must perform the + calculations for the deleted and inserted lines in the same way. + + This can result in some unnecessary recalculation and redrawing + overhead, and therefore we should only use this two-phase mode + of calculation when it's really needed (continuous wrap + variable + font width). */ + } + mNLinesDeleted = nLines; + mSuppressResync = 1; +} + +/* +** Count forward from startPos to either maxPos or maxLines (whichever is +** reached first), and return all relevant positions and line count. +** The provided textBuffer may differ from the actual text buffer of the +** widget. In that case it must be a (partial) copy of the actual text buffer +** and the styleBufOffset argument must indicate the starting position of the +** copy, to take into account the correct style information. +** +** Returned values: +** +** retPos: Position where counting ended. When counting lines, the +** position returned is the start of the line "maxLines" +** lines beyond "startPos". +** retLines: Number of line breaks counted +** retLineStart: Start of the line where counting ended +** retLineEnd: End position of the last line traversed +*/ +void My_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos, + int maxPos, int maxLines, bool startPosIsLineStart, int styleBufOffset, + int *retPos, int *retLines, int *retLineStart, int *retLineEnd, + bool countLastLineMissingNewLine) { + int lineStart, newLineStart = 0, b, p, colNum, wrapMargin; + int maxWidth, i, foundBreak, width; + bool countPixels; + int nLines = 0, tabDist = buffer()->tab_distance(); + unsigned char c; + char nullSubsChar = buffer()->null_substitution_character(); + + /* If the font is fixed, or there's a wrap margin set, it's more efficient + to measure in columns, than to count pixels. Determine if we can count + in columns (countPixels == False) or must count pixels (countPixels == + True), and set the wrap target for either pixels or columns */ + if (mFixedFontWidth != -1 || mWrapMargin != 0) { + countPixels = false; + wrapMargin = mWrapMargin ? mWrapMargin : text_area.w / (mFixedFontWidth + 1); + maxWidth = INT_MAX; + } else { + countPixels = true; + wrapMargin = INT_MAX; + maxWidth = text_area.w; + } + + /* Find the start of the line if the start pos is not marked as a + line start. */ + if (startPosIsLineStart) + lineStart = startPos; + else + lineStart = line_start(startPos); + + /* + ** Loop until position exceeds maxPos or line count exceeds maxLines. + ** (actually, contines beyond maxPos to end of line containing maxPos, + ** in case later characters cause a word wrap back before maxPos) + */ + colNum = 0; + width = 0; + for (p=lineStart; plength(); p++) { + c = (unsigned char)buf->character(p); + + /* If the character was a newline, count the line and start over, + otherwise, add it to the width and column counts */ + if (c == '\n') { + if (p >= maxPos) { + *retPos = maxPos; + *retLines = nLines; + *retLineStart = lineStart; + *retLineEnd = maxPos; + return; + } + nLines++; + if (nLines >= maxLines) { + *retPos = p + 1; + *retLines = nLines; + *retLineStart = p + 1; + *retLineEnd = p; + return; + } + lineStart = p + 1; + colNum = 0; + width = 0; + } else { + colNum += Fl_Text_Buffer::character_width(c, colNum, tabDist, nullSubsChar); + if (countPixels) + width += measure_proportional_character(c, colNum, p+styleBufOffset); + } + + /* If character exceeded wrap margin, find the break point + and wrap there */ + if (colNum > wrapMargin || width > maxWidth) { + foundBreak = false; + for (b=p; b>=lineStart; b--) { + c = (unsigned char)buf->character(b); + if (c == '\t' || c == ' ') { + newLineStart = b + 1; + if (countPixels) { + colNum = 0; + width = 0; + for (i=b+1; icharacter(i), colNum, + i+styleBufOffset); + colNum++; + } + } else + colNum = buf->count_displayed_characters(b+1, p+1); + foundBreak = true; + break; + } + } + if (!foundBreak) { /* no whitespace, just break at margin */ + newLineStart = max(p, lineStart+1); + colNum = Fl_Text_Buffer::character_width(c, colNum, tabDist, nullSubsChar); + if (countPixels) + width = measure_proportional_character(c, colNum, p+styleBufOffset); + } + if (p >= maxPos) { + *retPos = maxPos; + *retLines = maxPos < newLineStart ? nLines : nLines + 1; + *retLineStart = maxPos < newLineStart ? lineStart : + newLineStart; + *retLineEnd = maxPos; + return; + } + nLines++; + if (nLines >= maxLines) { + *retPos = foundBreak ? b + 1 : max(p, lineStart+1); + *retLines = nLines; + *retLineStart = lineStart; + *retLineEnd = foundBreak ? b : p; + return; + } + lineStart = newLineStart; + } + } + + /* reached end of buffer before reaching pos or line target */ + *retPos = buf->length(); + *retLines = nLines; + if (countLastLineMissingNewLine && colNum > 0) + ++(*retLines); + *retLineStart = lineStart; + *retLineEnd = buf->length(); +} + +/* +** Measure the width in pixels of a character "c" at a particular column +** "colNum" and buffer position "pos". This is for measuring characters in +** proportional or mixed-width highlighting fonts. +** +** A note about proportional and mixed-width fonts: the mixed width and +** proportional font code in nedit does not get much use in general editing, +** because nedit doesn't allow per-language-mode fonts, and editing programs +** in a proportional font is usually a bad idea, so very few users would +** choose a proportional font as a default. There are still probably mixed- +** width syntax highlighting cases where things don't redraw properly for +** insertion/deletion, though static display and wrapping and resizing +** should now be solid because they are now used for online help display. +*/ +int My_Text_Display::measure_proportional_character(char c, int colNum, int pos) { + int charLen, style; + char expChar[ FL_TEXT_MAX_EXP_CHAR_LEN ]; + Fl_Text_Buffer *styleBuf = mStyleBuffer; + + charLen = Fl_Text_Buffer::expand_character(c, colNum, expChar, + buffer()->tab_distance(), buffer()->null_substitution_character()); + if (styleBuf == 0) { + style = 0; + } else { + style = (unsigned char)styleBuf->character(pos); + if (style == mUnfinishedStyle) { + /* encountered "unfinished" style, trigger parsing */ + (mUnfinishedHighlightCB)(pos, mHighlightCBArg); + style = (unsigned char)styleBuf->character(pos); + } + } + return string_width(expChar, charLen, style); +} + +/* +** Finds both the end of the current line and the start of the next line. Why? +** In continuous wrap mode, if you need to know both, figuring out one from the +** other can be expensive or error prone. The problem comes when there's a +** trailing space or tab just before the end of the buffer. To translate an +** end of line value to or from the next lines start value, you need to know +** whether the trailing space or tab is being used as a line break or just a +** normal character, and to find that out would otherwise require counting all +** the way back to the beginning of the line. +*/ +void My_Text_Display::find_line_end(int startPos, bool startPosIsLineStart, + int *lineEnd, int *nextLineStart) { + int retLines, retLineStart; + + /* if we're not wrapping use more efficient BufEndOfLine */ + if (!mContinuousWrap) { + *lineEnd = buffer()->line_end(startPos); + *nextLineStart = min(buffer()->length(), *lineEnd + 1); + return; + } + + /* use the wrapped line counter routine to count forward one line */ + wrapped_line_counter(buffer(), startPos, buffer()->length(), + 1, startPosIsLineStart, 0, nextLineStart, &retLines, + &retLineStart, lineEnd); + return; +} + +/* +** Line breaks in continuous wrap mode usually happen at newlines or +** whitespace. This line-terminating character is not included in line +** width measurements and has a special status as a non-visible character. +** However, lines with no whitespace are wrapped without the benefit of a +** line terminating character, and this distinction causes endless trouble +** with all of the text display code which was originally written without +** continuous wrap mode and always expects to wrap at a newline character. +** +** Given the position of the end of the line, as returned by TextDEndOfLine +** or BufEndOfLine, this returns true if there is a line terminating +** character, and false if there's not. On the last character in the +** buffer, this function can't tell for certain whether a trailing space was +** used as a wrap point, and just guesses that it wasn't. So if an exact +** accounting is necessary, don't use this function. +*/ +int My_Text_Display::wrap_uses_character(int lineEndPos) { + char c; + + if (!mContinuousWrap || lineEndPos == buffer()->length()) + return 1; + + c = buffer()->character(lineEndPos); + return c == '\n' || ((c == '\t' || c == ' ') && + lineEndPos + 1 != buffer()->length()); +} + +/* +** Return true if the selection "sel" is rectangular, and touches a +** buffer position withing "rangeStart" to "rangeEnd" +*/ +int My_Text_Display::range_touches_selection(Fl_Text_Selection *sel, + int rangeStart, int rangeEnd) { + return sel->selected() && sel->rectangular() && sel->end() >= rangeStart && + sel->start() <= rangeEnd; +} + +/* +** Extend the range of a redraw request (from *start to *end) with additional +** redraw requests resulting from changes to the attached style buffer (which +** contains auxiliary information for coloring or styling text). +*/ +void My_Text_Display::extend_range_for_styles( int *startpos, int *endpos ) { + Fl_Text_Selection * sel = mStyleBuffer->primary_selection(); + int extended = 0; + + /* The peculiar protocol used here is that modifications to the style + buffer are marked by selecting them with the buffer's primary Fl_Text_Selection. + The style buffer is usually modified in response to a modify callback on + the text buffer BEFORE My_Text_Display.c's modify callback, so that it can keep + the style buffer in step with the text buffer. The style-update + callback can't just call for a redraw, because My_Text_Display hasn't processed + the original text changes yet. Anyhow, to minimize redrawing and to + avoid the complexity of scheduling redraws later, this simple protocol + tells the text display's buffer modify callback to extend it's redraw + range to show the text color/and font changes as well. */ + if ( sel->selected() ) { + if ( sel->start() < *startpos ) { + *startpos = sel->start(); + extended = 1; + } + if ( sel->end() > *endpos ) { + *endpos = sel->end(); + extended = 1; + } + } + + /* If the Fl_Text_Selection was extended due to a style change, and some of the + fonts don't match in spacing, extend redraw area to end of line to + redraw characters exposed by possible font size changes */ + if ( mFixedFontWidth == -1 && extended ) + *endpos = mBuffer->line_end( *endpos ) + 1; +} + +// The draw() method. It tries to minimize what is draw as much as possible. +void My_Text_Display::draw(void) { + // don't even try if there is no associated text buffer! + if (!buffer()) { draw_box(); return; } + + // draw the non-text, non-scrollbar areas. + if (damage() & FL_DAMAGE_ALL) { + Fl_Region r = XRectangleRegion(0, 0, w(), h()); + fl_push_clip(0, 0, w(), h()); + // fl_clip_region(r); + +// printf("drawing all (box = %d)\n", box()); + // draw the box() + int W = w(), H = h(); + + if (mHScrollBar->visible()) + W -= scrollbar_width(); + if (mVScrollBar->visible()) + H -= scrollbar_width(); + + draw_box(box(), x(), y(), w(), h(), color()); + // left margin + fl_rectf(text_area.x-LEFT_MARGIN, text_area.y-TOP_MARGIN, + LEFT_MARGIN, text_area.h+TOP_MARGIN+BOTTOM_MARGIN, color()); + + // right margin + fl_rectf(text_area.x+text_area.w, text_area.y-TOP_MARGIN, + RIGHT_MARGIN + scrollbar_width(), text_area.h+TOP_MARGIN+BOTTOM_MARGIN, + color()); + + // top margin + fl_rectf(text_area.x, text_area.y-TOP_MARGIN, + W, TOP_MARGIN, color()); + + // bottom margin + fl_rectf(text_area.x, text_area.y+text_area.h, + W, BOTTOM_MARGIN, color()); + + // draw that little box in the corner of the scrollbars + if (mVScrollBar->visible() && mHScrollBar->visible()) + fl_rectf(mVScrollBar->x(), mHScrollBar->y(), + mVScrollBar->w(), mHScrollBar->h(), + FL_GRAY); + + // blank the previous cursor protrusions + + fl_pop_clip(); + } + else if (damage() & (FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE)) { +// printf("blanking previous cursor extrusions at Y: %d\n", mCursorOldY); + // CET - FIXME - save old cursor position instead and just draw side needed? + fl_push_clip(0, 0, w(), text_area.h + scrollbar_width()); + Fl_Region r = XRectangleRegion(0, 0, w(), text_area.h + scrollbar_width()); + fl_clip_region(r); + fl_rectf(text_area.x, text_area.y-TOP_MARGIN, + w(), TOP_MARGIN, color()); + fl_rectf(text_area.x-LEFT_MARGIN, text_area.y, + LEFT_MARGIN, text_area.h, color()); + fl_rectf(text_area.x+text_area.w, text_area.y, + RIGHT_MARGIN, text_area.h, color()); + fl_pop_clip(); + } + + // draw the scrollbars + if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_CHILD)) { + mVScrollBar->damage(FL_DAMAGE_ALL); + mHScrollBar->damage(FL_DAMAGE_ALL); + } + update_child(*mVScrollBar); + update_child(*mHScrollBar); + + // draw all of the text + if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_EXPOSE)) { + //printf("drawing all text\n"); + int X, Y, W, H; + if (fl_clip_box(text_area.x, text_area.y, text_area.w, text_area.h, + X, Y, W, H)) { + // Draw text using the intersected clipping box... + // (this sets the clipping internally) + draw_text(X, Y, W, H); + } else { + // Draw the whole area... + draw_text(text_area.x, text_area.y, text_area.w, text_area.h); + } + } + else if (damage() & FL_DAMAGE_SCROLL) { + // draw some lines of text + fl_push_clip(text_area.x, text_area.y, + text_area.w, text_area.h); + Fl_Region r = XRectangleRegion(text_area.x, text_area.y, + text_area.w, text_area.h); + fl_clip_region(r); + //printf("drawing text from %d to %d\n", damage_range1_start, damage_range1_end); + draw_range(damage_range1_start, damage_range1_end); + if (damage_range2_end != -1) { + //printf("drawing text from %d to %d\n", damage_range2_start, damage_range2_end); + draw_range(damage_range2_start, damage_range2_end); + } + damage_range1_start = damage_range1_end = -1; + damage_range2_start = damage_range2_end = -1; + fl_pop_clip(); + } + + // draw the text cursor + if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE) + && !buffer()->primary_selection()->selected() && + mCursorOn && Fl::focus() == this ) { + fl_push_clip(text_area.x-LEFT_MARGIN, + text_area.y, + text_area.w+LEFT_MARGIN+RIGHT_MARGIN, + text_area.h); + Fl_Region r = XRectangleRegion(0, 0, + w(), h()); + fl_clip_region(r); + + int X, Y; + if (position_to_xy(mCursorPos, &X, &Y)) draw_cursor(X, Y); +// else puts("position_to_xy() failed - unable to draw cursor!"); + //printf("drew cursor at pos: %d (%d,%d)\n", mCursorPos, X, Y); + mCursorOldY = Y; + fl_pop_clip(); + } +} + +// this processes drag events due to mouse for My_Text_Display and +// also drags due to cursor movement with shift held down for +// Fl_Text_Editor +void fl_text_drag_me(int pos, My_Text_Display* d) { + if (d->dragType == My_Text_Display::DRAG_CHAR) { + if (pos >= d->dragPos) { + d->buffer()->select(d->dragPos, pos); + } else { + d->buffer()->select(pos, d->dragPos); + } + d->insert_position(pos); + } else if (d->dragType == My_Text_Display::DRAG_WORD) { + if (pos >= d->dragPos) { + d->insert_position(d->word_end(pos)); + d->buffer()->select(d->word_start(d->dragPos), d->word_end(pos)); + } else { + d->insert_position(d->word_start(pos)); + d->buffer()->select(d->word_start(pos), d->word_end(d->dragPos)); + } + } else if (d->dragType == My_Text_Display::DRAG_LINE) { + if (pos >= d->dragPos) { + d->insert_position(d->buffer()->line_end(pos)+1); + d->buffer()->select(d->buffer()->line_start(d->dragPos), + d->buffer()->line_end(pos)+1); + } else { + d->insert_position(d->buffer()->line_start(pos)); + d->buffer()->select(d->buffer()->line_start(pos), + d->buffer()->line_end(d->dragPos)+1); + } + } +} + +int My_Text_Display::handle(int event) +{ + int line, ret; + + if (!buffer()) return 0; + + // This isn't very elegant! + if (!Fl::event_inside(text_area.x, text_area.y, text_area.w, text_area.h) && + !dragging && event != FL_LEAVE && event != FL_ENTER && event != FL_MOVE) + { + ret = Fl_Group::handle(event); + position_to_linecol(insert_position(), &line, &mCurrentCol); + } + + switch (event) { + case FL_ENTER: + case FL_MOVE: + if (active_r()) { + if (Fl::event_inside(text_area.x, text_area.y, text_area.w, text_area.h)) + window()->cursor(FL_CURSOR_INSERT); + else if ((Fl::event_x() < text_area.x) && (Fl::event_y() >= text_area.y) && + (Fl::event_y() <= text_area.y + text_area.h)) + window()->cursor(FL_CURSOR_ARROW); + else + window()->cursor(FL_CURSOR_DEFAULT); + } + break; + + case FL_LEAVE: + case FL_HIDE: + if (active_r()) + { + if (window() != NULL) + window()->cursor(FL_CURSOR_DEFAULT); + + } + break; + + case FL_PUSH: { + if ((mVScrollBar->visible() && Fl::event_x() > text_area.x + text_area.w)) + break; + if ((mHScrollBar->visible() && Fl::event_y() > text_area.y + text_area.h)) + break; + if (Fl::focus() != this) { + Fl::focus(this); + handle(FL_FOCUS); + } + if (Fl::event_state()&FL_SHIFT) + return handle(FL_DRAG); + dragging = 1; + int pos = xy_to_position(Fl::event_x(), Fl::event_y(), CURSOR_POS); + dragType = Fl::event_clicks(); + dragPos = pos; + if (dragType == DRAG_CHAR) + buffer()->unselect(); + else if (dragType == DRAG_WORD) + buffer()->select(word_start(pos), word_end(pos)); + else if (dragType == DRAG_LINE) + buffer()->select(buffer()->line_start(pos), buffer()->line_end(pos)+1); + + if (buffer()->primary_selection()->selected()) + insert_position(buffer()->primary_selection()->end()); + else + insert_position(pos); + show_insert_position(); + position_to_linecol(pos, &line, &mCurrentCol); + return 1; + } + + case FL_DRAG: { + if (dragType < 0) return 1; + int X = Fl::event_x(), Y = Fl::event_y(), pos; + if (Y < text_area.y) { + move_up(); + scroll(mTopLineNum - 1, mHorizOffset); + pos = insert_position(); + } else if (Y >= text_area.y+text_area.h) { + move_down(); + scroll(mTopLineNum + 1, mHorizOffset); + pos = insert_position(); + } else pos = xy_to_position(X, Y, CURSOR_POS); + fl_text_drag_me(pos, this); + position_to_linecol(pos, &line, &mCurrentCol); + return 1; + } + + case FL_RELEASE: { + dragging = 0; + + // convert from WORD or LINE selection to CHAR + if (insert_position() >= dragPos) + dragPos = buffer()->primary_selection()->start(); + else + dragPos = buffer()->primary_selection()->end(); + dragType = DRAG_CHAR; + + const char* copy = buffer()->selection_text(); + if (*copy) Fl::copy(copy, strlen(copy), 0); + free((void*)copy); + return 1; + } + + case FL_MOUSEWHEEL: + return mVScrollBar->handle(event); + +/* case FL_FOCUS: + if (buffer()->primary_selection()->start() != + buffer()->primary_selection()->end()) redraw(); // Redraw selections... + color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR); + + break; + case FL_UNFOCUS: + if (buffer()->primary_selection()->start() != + buffer()->primary_selection()->end()) redraw(); // Redraw selections... + color(FL_INACTIVE_COLOR, FL_BLACK); + break; */ + } + + return Fl_Double_Window::handle(event); +} + + +// +// End of "$Id$". +// diff --git a/src/My_Text_Display.h b/src/My_Text_Display.h new file mode 100644 index 0000000..ac13745 --- /dev/null +++ b/src/My_Text_Display.h @@ -0,0 +1,297 @@ +// +// "$Id$" +// +// Header file for My_Text_Display class. +// +// Copyright 2001-2003 by Bill Spitzak and others. +// Original code Copyright Mark Edel. Permission to distribute under +// the LGPL for the FLTK library granted by Mark Edel. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to "fltk-bugs@fltk.org". +// + +#ifndef MY_TEXT_DISPLAY_H +#define MY_TEXT_DISPLAY_H + +#include +#include +#include +#include +#include + +#include + +class FL_EXPORT My_Text_Display: public Fl_Double_Window { + public: + enum { + NORMAL_CURSOR, CARET_CURSOR, DIM_CURSOR, + BLOCK_CURSOR, HEAVY_CURSOR + }; + + enum { + CURSOR_POS, CHARACTER_POS + }; + + // drag types- they match Fl::event_clicks() so that single clicking to + // start a collection selects by character, double clicking selects by + // word and triple clicking selects by line. + enum { + DRAG_CHAR = 0, DRAG_WORD = 1, DRAG_LINE = 2 + }; + friend void fl_text_drag_me(int pos, My_Text_Display* d); + + typedef void (*Unfinished_Style_Cb)(int, void *); + + // style attributes - currently not implemented! + enum { + ATTR_NONE = 0, + ATTR_UNDERLINE = 1, + ATTR_HIDDEN = 2 + }; + + struct Style_Table_Entry { + Fl_Color color; + Fl_Font font; + int size; + unsigned attr; + }; + + My_Text_Display(int X, int Y, int W, int H, const char *l = 0); + ~My_Text_Display(); + + virtual int handle(int e); + void buffer(Fl_Text_Buffer* buf); + void buffer(Fl_Text_Buffer& buf) { buffer(&buf); } + Fl_Text_Buffer* buffer() { return mBuffer; } + void redisplay_range(int start, int end); + void scroll(int topLineNum, int horizOffset); + void insert(const char* text); + void overstrike(const char* text); + void insert_position(int newPos); + int insert_position() { return mCursorPos; } + int in_selection(int x, int y); + void show_insert_position(); + int move_right(); + int move_left(); + int move_up(); + int move_down(); + int count_lines(int start, int end, bool start_pos_is_line_start); + int line_start(int pos); + int line_end(int pos, bool start_pos_is_line_start); + int skip_lines(int startPos, int nLines, bool startPosIsLineStart); + int rewind_lines(int startPos, int nLines); + void next_word(void); + void previous_word(void); + void show_cursor(int b = 1); + void hide_cursor() { show_cursor(0); } + void cursor_style(int style); + int scrollbar_width() { return scrollbar_width_; } + Fl_Align scrollbar_align() { return scrollbar_align_; } + void scrollbar_width(int W) { scrollbar_width_ = W; } + void scrollbar_align(Fl_Align a) { scrollbar_align_ = a; } + int word_start(int pos) { return buffer()->word_start(pos); } + int word_end(int pos) { return buffer()->word_end(pos); } + int current_column(void) { return mCurrentCol; } + + + void highlight_data(Fl_Text_Buffer *styleBuffer, + const Style_Table_Entry *styleTable, + int nStyles, char unfinishedStyle, + Unfinished_Style_Cb unfinishedHighlightCB, + void *cbArg); + + int position_style(int lineStartPos, int lineLen, int lineIndex, + int dispIndex); + + Fl_Font textfont() const {return (Fl_Font)textfont_;} + void textfont(uchar s) {textfont_ = s;} + uchar textsize() const {return textsize_;} + void textsize(uchar s) {textsize_ = s;} + Fl_Color textcolor() const {return (Fl_Color)textcolor_;} + void textcolor(unsigned n) {textcolor_ = n;} + + int wrapped_column(int row, int column); + int wrapped_row(int row); + void wrap_mode(int wrap, int wrap_margin); + + virtual void resize(int X, int Y, int W, int H); + + Fl_Color mCursor_color; + + protected: + // Most (all?) of this stuff should only be called from resize() or + // draw(). + // Anything with "vline" indicates thats it deals with currently + // visible lines. + + virtual void draw(); + void draw_text(int X, int Y, int W, int H); + void draw_range(int start, int end); + void draw_cursor(int, int); + + void draw_string(int style, int x, int y, int toX, const char *string, + int nChars); + + void draw_vline(int visLineNum, int leftClip, int rightClip, + int leftCharIndex, int rightCharIndex); + + void draw_line_numbers(bool clearAll); + + void clear_rect(int style, int x, int y, int width, int height); + void display_insert(); + + void offset_line_starts(int newTopLineNum); + + void calc_line_starts(int startLine, int endLine); + + void update_line_starts(int pos, int charsInserted, int charsDeleted, + int linesInserted, int linesDeleted, int *scrolled); + + void calc_last_char(); + + int position_to_line( int pos, int* lineNum ); + int string_width(const char* string, int length, int style); + + static void buffer_predelete_cb(int pos, int nDeleted, void* cbArg); + static void buffer_modified_cb(int pos, int nInserted, int nDeleted, + int nRestyled, const char* deletedText, + void* cbArg); + + static void h_scrollbar_cb(Fl_Scrollbar* w, My_Text_Display* d); + static void v_scrollbar_cb( Fl_Scrollbar* w, My_Text_Display* d); + void update_v_scrollbar(); + void update_h_scrollbar(); + int measure_vline(int visLineNum); + int longest_vline(); + int empty_vlines(); + int vline_length(int visLineNum); + int xy_to_position(int x, int y, int PosType = CHARACTER_POS); + + void xy_to_rowcol(int x, int y, int* row, int* column, + int PosType = CHARACTER_POS); + + int position_to_xy(int pos, int* x, int* y); + void maintain_absolute_top_line_number(int state); + int get_absolute_top_line_number(); + void absolute_top_line_number(int oldFirstChar); + int maintaining_absolute_top_line_number(); + void reset_absolute_top_line_number(); + int position_to_linecol(int pos, int* lineNum, int* column); + void scroll_(int topLineNum, int horizOffset); + + void extend_range_for_styles(int* start, int* end); + + void find_wrap_range(const char *deletedText, int pos, int nInserted, + int nDeleted, int *modRangeStart, int *modRangeEnd, + int *linesInserted, int *linesDeleted); + void measure_deleted_lines(int pos, int nDeleted); + void wrapped_line_counter(Fl_Text_Buffer *buf, int startPos, int maxPos, + int maxLines, bool startPosIsLineStart, + int styleBufOffset, int *retPos, int *retLines, + int *retLineStart, int *retLineEnd, + bool countLastLineMissingNewLine = true); + void find_line_end(int pos, bool start_pos_is_line_start, int *lineEnd, + int *nextLineStart); + int measure_proportional_character(char c, int colNum, int pos); + int wrap_uses_character(int lineEndPos); + int range_touches_selection(Fl_Text_Selection *sel, int rangeStart, + int rangeEnd); + + int damage_range1_start, damage_range1_end; + int damage_range2_start, damage_range2_end; + int mCurrentCol; /* Current column number */ + int mCursorPos; + int mCursorOn; + int mCursorOldY; /* Y pos. of cursor for blanking */ + int mCursorToHint; /* Tells the buffer modified callback + where to move the cursor, to reduce + the number of redraw calls */ + int mCursorStyle; /* One of enum cursorStyles above */ + int mCursorPreferredCol; /* Column for vert. cursor movement */ + int mNVisibleLines; /* # of visible (displayed) lines */ + int mNBufferLines; /* # of newlines in the buffer */ + Fl_Text_Buffer* mBuffer; /* Contains text to be displayed */ + Fl_Text_Buffer* mStyleBuffer; /* Optional parallel buffer containing + color and font information */ + int mFirstChar, mLastChar; /* Buffer positions of first and last + displayed character (lastChar points + either to a newline or one character + beyond the end of the buffer) */ + int mContinuousWrap; /* Wrap long lines when displaying */ + int mWrapMargin; /* Margin in # of char positions for + wrapping in continuousWrap mode */ + int* mLineStarts; + int mTopLineNum; /* Line number of top displayed line + of file (first line of file is 1) */ + int mAbsTopLineNum; /* In continuous wrap mode, the line + number of the top line if the text + were not wrapped (note that this is + only maintained as needed). */ + int mNeedAbsTopLineNum; /* Externally settable flag to continue + maintaining absTopLineNum even if + it isn't needed for line # display */ + int mHorizOffset; /* Horizontal scroll pos. in pixels */ + int mTopLineNumHint; /* Line number of top displayed line + of file (first line of file is 1) */ + int mHorizOffsetHint; /* Horizontal scroll pos. in pixels */ + int mNStyles; /* Number of entries in styleTable */ + const Style_Table_Entry *mStyleTable; /* Table of fonts and colors for + coloring/syntax-highlighting */ + char mUnfinishedStyle; /* Style buffer entry which triggers + on-the-fly reparsing of region */ + Unfinished_Style_Cb mUnfinishedHighlightCB; /* Callback to parse "unfinished" */ + /* regions */ + void* mHighlightCBArg; /* Arg to unfinishedHighlightCB */ + + int mMaxsize; + + int mFixedFontWidth; /* Font width if all current fonts are + fixed and match in width, else -1 */ + int mSuppressResync; /* Suppress resynchronization of line + starts during buffer updates */ + int mNLinesDeleted; /* Number of lines deleted during + buffer modification (only used + when resynchronization is suppressed) */ + int mModifyingTabDistance; /* Whether tab distance is being + modified */ + + + Fl_Scrollbar* mHScrollBar; + Fl_Scrollbar* mVScrollBar; + int scrollbar_width_; + Fl_Align scrollbar_align_; + int dragPos, dragType, dragging; + int display_insert_position_hint; + struct { int x, y, w, h; } text_area; + + uchar textfont_; + uchar textsize_; + unsigned textcolor_; + + // The following are not presently used from the original NEdit code, + // but are being put here so that future versions of My_Text_Display + // can implement line numbers without breaking binary compatibility. + int mLineNumLeft, mLineNumWidth; + /* Line number margin and width */ +}; + +#endif + +// +// End of "$Id$". +// diff --git a/src/My_Text_Editor.cpp b/src/My_Text_Editor.cpp new file mode 100644 index 0000000..b211294 --- /dev/null +++ b/src/My_Text_Editor.cpp @@ -0,0 +1,607 @@ +// +// "$Id$" +// +// Copyright 2001-2003 by Bill Spitzak and others. +// Original code Copyright Mark Edel. Permission to distribute under +// the LGPL for the FLTK library granted by Mark Edel. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to "fltk-bugs@fltk.org". +// + +#include +#include +#include +#include +#include +#include "My_Text_Editor.h" +#include + + +My_Text_Editor::My_Text_Editor(int X, int Y, int W, int H, const char* l) + : My_Text_Display(X, Y, W, H, l) { + mCursorOn = 1; + insert_mode_ = 1; + key_bindings = 0; + autobrace = 0; + auto_brace_mode = 0; + smart_indent = 1; + m_pStatusBar = NULL; + + // handle the default key bindings + add_default_key_bindings(&key_bindings); + + // handle everything else + default_key_function(kf_default); +} + +My_Text_Editor::Key_Binding* My_Text_Editor::global_key_bindings = 0; + +static int ctrl_a(int, My_Text_Editor* e); + +// These are the default key bindings every widget should start with +static struct { + int key; + int state; + My_Text_Editor::Key_Func func; +} default_key_bindings[] = { + { FL_Escape, My_Text_Editor_ANY_STATE, My_Text_Editor::kf_ignore }, + { FL_Enter, My_Text_Editor_ANY_STATE, My_Text_Editor::kf_enter }, + { FL_KP_Enter, My_Text_Editor_ANY_STATE, My_Text_Editor::kf_enter }, + { FL_BackSpace, My_Text_Editor_ANY_STATE, My_Text_Editor::kf_backspace }, + { FL_Insert, My_Text_Editor_ANY_STATE, My_Text_Editor::kf_insert }, + { FL_Delete, My_Text_Editor_ANY_STATE, My_Text_Editor::kf_delete }, + { FL_Home, 0, My_Text_Editor::kf_move }, + { FL_End, 0, My_Text_Editor::kf_move }, + { FL_Left, 0, My_Text_Editor::kf_move }, + { FL_Up, 0, My_Text_Editor::kf_move }, + { FL_Right, 0, My_Text_Editor::kf_move }, + { FL_Down, 0, My_Text_Editor::kf_move }, + { FL_Page_Up, 0, My_Text_Editor::kf_move }, + { FL_Page_Down, 0, My_Text_Editor::kf_move }, + { FL_Home, FL_SHIFT, My_Text_Editor::kf_shift_move }, + { FL_End, FL_SHIFT, My_Text_Editor::kf_shift_move }, + { FL_Left, FL_SHIFT, My_Text_Editor::kf_shift_move }, + { FL_Up, FL_SHIFT, My_Text_Editor::kf_shift_move }, + { FL_Right, FL_SHIFT, My_Text_Editor::kf_shift_move }, + { FL_Down, FL_SHIFT, My_Text_Editor::kf_shift_move }, + { FL_Page_Up, FL_SHIFT, My_Text_Editor::kf_shift_move }, + { FL_Page_Down, FL_SHIFT, My_Text_Editor::kf_shift_move }, + { FL_Home, FL_CTRL, My_Text_Editor::kf_ctrl_move }, + { FL_End, FL_CTRL, My_Text_Editor::kf_ctrl_move }, + { FL_Left, FL_CTRL, My_Text_Editor::kf_ctrl_move }, + { FL_Up, FL_CTRL, My_Text_Editor::kf_ctrl_move }, + { FL_Right, FL_CTRL, My_Text_Editor::kf_ctrl_move }, + { FL_Down, FL_CTRL, My_Text_Editor::kf_ctrl_move }, + { FL_Page_Up, FL_CTRL, My_Text_Editor::kf_ctrl_move }, + { FL_Page_Down, FL_CTRL, My_Text_Editor::kf_ctrl_move }, + { FL_Home, FL_CTRL|FL_SHIFT, My_Text_Editor::kf_c_s_move }, + { FL_End, FL_CTRL|FL_SHIFT, My_Text_Editor::kf_c_s_move }, + { FL_Left, FL_CTRL|FL_SHIFT, My_Text_Editor::kf_c_s_move }, + { FL_Up, FL_CTRL|FL_SHIFT, My_Text_Editor::kf_c_s_move }, + { FL_Right, FL_CTRL|FL_SHIFT, My_Text_Editor::kf_c_s_move }, + { FL_Down, FL_CTRL|FL_SHIFT, My_Text_Editor::kf_c_s_move }, + { FL_Page_Up, FL_CTRL|FL_SHIFT, My_Text_Editor::kf_c_s_move }, + { FL_Page_Down, FL_CTRL|FL_SHIFT, My_Text_Editor::kf_c_s_move }, +//{ FL_Clear, 0, My_Text_Editor::delete_to_eol }, + { 'z', FL_CTRL, My_Text_Editor::kf_undo }, + { '/', FL_CTRL, My_Text_Editor::kf_undo }, + { 'x', FL_CTRL, My_Text_Editor::kf_cut }, + { FL_Delete, FL_SHIFT, My_Text_Editor::kf_cut }, + { 'c', FL_CTRL, My_Text_Editor::kf_copy }, + { FL_Insert, FL_CTRL, My_Text_Editor::kf_copy }, + { 'v', FL_CTRL, My_Text_Editor::kf_paste }, + { FL_Insert, FL_SHIFT, My_Text_Editor::kf_paste }, + { 'a', FL_CTRL, ctrl_a }, + +#ifdef __APPLE__ + // Define CMD+key accelerators... + { 'z', FL_COMMAND, My_Text_Editor::kf_undo }, + { 'x', FL_COMMAND, My_Text_Editor::kf_cut }, + { 'c', FL_COMMAND, My_Text_Editor::kf_copy }, + { 'v', FL_COMMAND, My_Text_Editor::kf_paste }, + { 'a', FL_COMMAND, ctrl_a }, +#endif // __APPLE__ + + { 0, 0, 0 } +}; + +void My_Text_Editor::add_default_key_bindings(Key_Binding** list) { + for (int i = 0; default_key_bindings[i].key; i++) { + add_key_binding(default_key_bindings[i].key, + default_key_bindings[i].state, + default_key_bindings[i].func, + list); + } +} + +My_Text_Editor::Key_Func +My_Text_Editor::bound_key_function(int key, int state, Key_Binding* list) { + Key_Binding* cur; + for (cur = list; cur; cur = cur->next) + if (cur->key == key) + if (cur->state == My_Text_Editor_ANY_STATE || cur->state == state) + break; + if (!cur) return 0; + return cur->function; +} + +void +My_Text_Editor::remove_all_key_bindings(Key_Binding** list) { + Key_Binding *cur, *next; + for (cur = *list; cur; cur = next) { + next = cur->next; + delete cur; + } + *list = 0; +} + +void +My_Text_Editor::remove_key_binding(int key, int state, Key_Binding** list) { + Key_Binding *cur, *last = 0; + for (cur = *list; cur; last = cur, cur = cur->next) + if (cur->key == key && cur->state == state) break; + if (!cur) return; + if (last) last->next = cur->next; + else *list = cur->next; + delete cur; +} + +void +My_Text_Editor::add_key_binding(int key, int state, Key_Func function, + Key_Binding** list) { + Key_Binding* kb = new Key_Binding; + kb->key = key; + kb->state = state; + kb->function = function; + kb->next = *list; + *list = kb; +} + +//////////////////////////////////////////////////////////////// + +#define NORMAL_INPUT_MOVE 0 + +static void kill_selection(My_Text_Editor* e) { + if (e->buffer()->selected()) { + e->insert_position(e->buffer()->primary_selection()->start()); + e->buffer()->remove_selection(); + } +} + +int My_Text_Editor::kf_default(int c, My_Text_Editor* e) { + if (!c || (!isprint(c) && c != '\t')) return 0; + char s[2] = "\0"; + s[0] = (char)c; + kill_selection(e); + if (e->insert_mode()) e->insert(s); + else e->overstrike(s); + e->show_insert_position(); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); + else e->set_changed(); + return 1; +} + +int My_Text_Editor::kf_ignore(int, My_Text_Editor*) { + return 0; // don't handle +} + +int My_Text_Editor::kf_backspace(int, My_Text_Editor* e) { + if (!e->buffer()->selected() && e->move_left()) + e->buffer()->select(e->insert_position(), e->insert_position()+1); + kill_selection(e); + e->show_insert_position(); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); else e->set_changed(); + return 1; +} + +int My_Text_Editor::kf_enter(int, My_Text_Editor* e) { + kill_selection(e); + e->insert("\n"); + e->show_insert_position(); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); else e->set_changed(); + return 1; +} + +extern void fl_text_drag_me(int pos, My_Text_Display* d); + +int My_Text_Editor::kf_move(int c, My_Text_Editor* e) { + int i; + int selected = e->buffer()->selected(); + if (!selected) + e->dragPos = e->insert_position(); + e->buffer()->unselect(); + switch (c) { + case FL_Home: + e->insert_position(e->buffer()->line_start(e->insert_position())); + break; + case FL_End: + e->insert_position(e->buffer()->line_end(e->insert_position())); + break; + case FL_Left: + e->move_left(); + break; + case FL_Right: + e->move_right(); + break; + case FL_Up: + e->move_up(); + break; + case FL_Down: + e->move_down(); + break; + case FL_Page_Up: + for (i = 0; i < e->mNVisibleLines - 1; i++) e->move_up(); + break; + case FL_Page_Down: + for (i = 0; i < e->mNVisibleLines - 1; i++) e->move_down(); + break; + } + e->show_insert_position(); + return 1; +} + +int My_Text_Editor::kf_shift_move(int c, My_Text_Editor* e) { + kf_move(c, e); + fl_text_drag_me(e->insert_position(), e); + return 1; +} + +int My_Text_Editor::kf_ctrl_move(int c, My_Text_Editor* e) { + if (!e->buffer()->selected()) + e->dragPos = e->insert_position(); + if (c != FL_Up && c != FL_Down) { + e->buffer()->unselect(); + e->show_insert_position(); + } + switch (c) { + case FL_Home: + e->insert_position(0); + e->scroll(0, 0); + break; + case FL_End: + e->insert_position(e->buffer()->length()); + e->scroll(e->count_lines(0, e->buffer()->length(), 1), 0); + break; + case FL_Left: + e->previous_word(); + break; + case FL_Right: + e->next_word(); + break; + case FL_Up: + e->scroll(e->mTopLineNum-1, e->mHorizOffset); + break; + case FL_Down: + e->scroll(e->mTopLineNum+1, e->mHorizOffset); + break; + case FL_Page_Up: + e->insert_position(e->mLineStarts[0]); + break; + case FL_Page_Down: + e->insert_position(e->mLineStarts[e->mNVisibleLines-2]); + break; + } + return 1; +} + +int My_Text_Editor::kf_c_s_move(int c, My_Text_Editor* e) { + kf_ctrl_move(c, e); + fl_text_drag_me(e->insert_position(), e); + return 1; +} + +static int ctrl_a(int, My_Text_Editor* e) { + // make 2+ ^A's in a row toggle select-all: + int i = e->buffer()->line_start(e->insert_position()); + if (i != e->insert_position()) + return My_Text_Editor::kf_move(FL_Home, e); + else { + if (e->buffer()->selected()) + e->buffer()->unselect(); + else + My_Text_Editor::kf_select_all(0, e); + } + return 1; +} + +int My_Text_Editor::kf_home(int, My_Text_Editor* e) { + return kf_move(FL_Home, e); +} + +int My_Text_Editor::kf_end(int, My_Text_Editor* e) { + return kf_move(FL_End, e); +} + +int My_Text_Editor::kf_left(int, My_Text_Editor* e) { + return kf_move(FL_Left, e); +} + +int My_Text_Editor::kf_up(int, My_Text_Editor* e) { + return kf_move(FL_Up, e); +} + +int My_Text_Editor::kf_right(int, My_Text_Editor* e) { + return kf_move(FL_Right, e); +} + +int My_Text_Editor::kf_down(int, My_Text_Editor* e) { + return kf_move(FL_Down, e); +} + +int My_Text_Editor::kf_page_up(int, My_Text_Editor* e) { + return kf_move(FL_Page_Up, e); +} + +int My_Text_Editor::kf_page_down(int, My_Text_Editor* e) { + return kf_move(FL_Page_Down, e); +} + + +int My_Text_Editor::kf_insert(int, My_Text_Editor* e) { + e->insert_mode(e->insert_mode() ? 0 : 1); + return 1; +} + +int My_Text_Editor::kf_delete(int, My_Text_Editor* e) { + if (!e->buffer()->selected()) + e->buffer()->select(e->insert_position(), e->insert_position()+1); + kill_selection(e); + e->show_insert_position(); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); else e->set_changed(); + return 1; +} + +int My_Text_Editor::kf_copy(int, My_Text_Editor* e) { + if (!e->buffer()->selected()) return 1; + const char *copy = e->buffer()->selection_text(); + if (*copy) Fl::copy(copy, strlen(copy), 1); + free((void*)copy); + e->show_insert_position(); + return 1; +} + +int My_Text_Editor::kf_cut(int c, My_Text_Editor* e) { + kf_copy(c, e); + kill_selection(e); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); else e->set_changed(); + return 1; +} + +int My_Text_Editor::kf_paste(int, My_Text_Editor* e) { + kill_selection(e); + Fl::paste(*e, 1); + e->show_insert_position(); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); else e->set_changed(); + return 1; +} + +int My_Text_Editor::kf_select_all(int, My_Text_Editor* e) { + e->buffer()->select(0, e->buffer()->length()); + return 1; +} + +int My_Text_Editor::kf_undo(int , My_Text_Editor* e) { + e->buffer()->unselect(); + int crsr; + int ret = e->buffer()->undo(&crsr); + e->insert_position(crsr); + e->show_insert_position(); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); else e->set_changed(); + return ret; +} + +int My_Text_Editor::handle_key() { + // Call FLTK's rules to try to turn this into a printing character. + // This uses the right-hand ctrl key as a "compose prefix" and returns + // the changes that should be made to the text, as a number of + // bytes to delete and a string to insert: + int del; + if (Fl::compose(del)) { + if (del) buffer()->select(insert_position()-del, insert_position()); + kill_selection(this); + if (Fl::event_length()) { + if (insert_mode()) + { + insert(Fl::event_text()); + if(strcmp(Fl::event_text(),"{")==0 && auto_brace_mode) + autobrace = true; + else + autobrace = false; + } + else overstrike(Fl::event_text()); + } + show_insert_position(); + if (when()&FL_WHEN_CHANGED) do_callback(); + else set_changed(); + return 1; + } + + int key = Fl::event_key(), state = Fl::event_state(), c = Fl::event_text()[0]; + state &= FL_SHIFT|FL_CTRL|FL_ALT|FL_META; // only care about these states + + if(Fl::event_key()==FL_Enter && smart_indent) + { + char *line = new char[strlen(buffer()->line_text(insert_position()))+1]; + strcpy(line, buffer()->line_text(insert_position())); + for(unsigned int i = 0; i < strlen(line); i++) { + if(line[i]!=' ' && line[i]!='\t') line[i]='\0'; + } + kf_enter(c,this); + insert(line); + + if(autobrace) { + int inspos = insert_position(); + kf_enter(c,this); + insert(line); + insert("}"); + insert_position(inspos); + insert("\t"); + } + delete line; + autobrace = false; + return 1; + } + + + else if(Fl::event_key()==FL_Home) { + int pos = 0; + char *line = new char[strlen(buffer()->line_text(insert_position()))+1]; + strcpy(line, buffer()->line_text(insert_position())); + for(unsigned int i = 0; i < strlen(line); i++) { + if(line[i]!=' ' && line[i]!='\t') { pos = i; break; } + } + delete line; + int old = insert_position(); + insert_position(buffer()->line_start(insert_position()) + pos); + if(state == FL_SHIFT) + buffer()->select(insert_position(),old); + if(insert_position() != old) + return 1; + } + + Key_Func f; + f = bound_key_function(key, state, global_key_bindings); + if (!f) f = bound_key_function(key, state, key_bindings); + if (f) return f(key, this); + if (default_key_function_ && !state) return default_key_function_(c, this); + return 0; +} + +void My_Text_Editor::maybe_do_callback() { +// printf("My_Text_Editor::maybe_do_callback()\n"); +// printf("changed()=%d, when()=%x\n", changed(), when()); + if (changed() || (when()&FL_WHEN_NOT_CHANGED)) { + clear_changed(); do_callback();} +} + +int My_Text_Editor::handle(int event) +{ + int ret; + + if (!buffer()) return 0; + + if (event == FL_PUSH && Fl::event_button() == 2) { + dragType = -1; + Fl::paste(*this, 0); + Fl::focus(this); + if (when()&FL_WHEN_CHANGED) do_callback(); else set_changed(); + UpdateStatusBar(); + return 1; + } + + switch (event) { + case FL_FOCUS: + show_cursor(mCursorOn); // redraws the cursor + if (buffer()->primary_selection()->start() != + buffer()->primary_selection()->end()) redraw(); // Redraw selections... + UpdateStatusBar(); + Fl::focus(this); + return 1; + + case FL_UNFOCUS: + show_cursor(mCursorOn); // redraws the cursor + if (buffer()->primary_selection()->start() != + buffer()->primary_selection()->end()) redraw(); // Redraw selections... + case FL_HIDE: + if (when() & FL_WHEN_RELEASE) + maybe_do_callback(); +// ret = My_Text_Display::handle(event); +// return ret; + break; + + case FL_KEYBOARD: + ret = handle_key(); + + UpdateStatusBar(); + return ret; + + case FL_PASTE: + if (!Fl::event_text()) { + fl_beep(); + return 1; + } + buffer()->remove_selection(); + if (insert_mode()) insert(Fl::event_text()); + else overstrike(Fl::event_text()); + show_insert_position(); + if (when()&FL_WHEN_CHANGED) do_callback(); else set_changed(); + UpdateStatusBar(); + return 1; + + case FL_ENTER: +// MRS: WIN32 only? Need to test! +// case FL_MOVE: + show_cursor(mCursorOn); + UpdateStatusBar(); + break; +// My_Text_Display::handle(event); +// return 1; + } + + ret = My_Text_Display::handle(event); + UpdateStatusBar(); + return ret; +} + +void My_Text_Editor::UpdateStatusBar(void) +{ + int zeile = count_lines(0,insert_position(),0) + 1; + int spalte = current_column(); + int ins_mode = insert_mode(); + int oldzeile = 0; + int oldspalte = 0; + int oldins_mode = 0; + + if (m_pStatusBar != NULL) + { + oldzeile = m_pStatusBar->line; + oldspalte = m_pStatusBar->col; + oldins_mode = m_pStatusBar->ins_mode; + } + + if (zeile != oldzeile || spalte != oldspalte || ins_mode != oldins_mode) + { + if (m_pStatusBar != NULL) + { + // Update row + sprintf(m_pStatusBar->linestr, "Ln %d", zeile); + m_pStatusBar->m_pLineBox->label(m_pStatusBar->linestr); + m_pStatusBar->line = zeile; + + // Update col + sprintf(m_pStatusBar->colstr, "Col %d", spalte+1); + m_pStatusBar->m_pColBox->label(m_pStatusBar->colstr); + m_pStatusBar->col = spalte; + + // Update ins mode + if (ins_mode) + { + m_pStatusBar->m_pInsBox->label("INS"); + } + else + { + m_pStatusBar->m_pInsBox->label("OVR"); + } + m_pStatusBar->ins_mode = ins_mode; + } + } +} + +// +// End of "$Id$". +// diff --git a/src/My_Text_Editor.h b/src/My_Text_Editor.h new file mode 100644 index 0000000..65e74fa --- /dev/null +++ b/src/My_Text_Editor.h @@ -0,0 +1,128 @@ +// +// "$Id$" +// +// Header file for My_Text_Editor class. +// +// Copyright 2001-2003 by Bill Spitzak and others. +// Original code Copyright Mark Edel. Permission to distribute under +// the LGPL for the FLTK library granted by Mark Edel. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to "fltk-bugs@fltk.org". +// + + +#ifndef My_Text_Editor_H +#define My_Text_Editor_H + +#include +#include "My_Text_Display.h" + +typedef struct _StatusBar +{ + int line; + int col; + int ins_mode; + Fl_Box* m_pLineBox; + Fl_Box* m_pColBox; + Fl_Box* m_pInsBox; + char linestr[20]; + char colstr[20]; +} StatusBar_t; + +// key will match in any state +#define My_Text_Editor_ANY_STATE (-1L) + +class FL_EXPORT My_Text_Editor : public My_Text_Display { + public: + typedef int (*Key_Func)(int key, My_Text_Editor* editor); + + struct Key_Binding { + int key; + int state; + Key_Func function; + Key_Binding* next; + }; + + int autobrace; + int smart_indent; + int auto_brace_mode; + + My_Text_Editor(int X, int Y, int W, int H, const char* l = 0); + ~My_Text_Editor() { remove_all_key_bindings(); } + virtual int handle(int e); + void insert_mode(int b) { insert_mode_ = b; } + int insert_mode() { return insert_mode_; } + + void add_status_bar(StatusBar_t* pStatusBar) { m_pStatusBar = pStatusBar; }; + void add_key_binding(int key, int state, Key_Func f, Key_Binding** list); + void add_key_binding(int key, int state, Key_Func f) + { add_key_binding(key, state, f, &key_bindings); } + void remove_key_binding(int key, int state, Key_Binding** list); + void remove_key_binding(int key, int state) + { remove_key_binding(key, state, &key_bindings); } + void remove_all_key_bindings(Key_Binding** list); + void remove_all_key_bindings() { remove_all_key_bindings(&key_bindings); } + void add_default_key_bindings(Key_Binding** list); + Key_Func bound_key_function(int key, int state, Key_Binding* list); + Key_Func bound_key_function(int key, int state) + { return bound_key_function(key, state, key_bindings); } + void default_key_function(Key_Func f) { default_key_function_ = f; } + + // functions for the built in default bindings + static int kf_default(int c, My_Text_Editor* e); + static int kf_ignore(int c, My_Text_Editor* e); + static int kf_backspace(int c, My_Text_Editor* e); + static int kf_enter(int c, My_Text_Editor* e); + static int kf_move(int c, My_Text_Editor* e); + static int kf_shift_move(int c, My_Text_Editor* e); + static int kf_ctrl_move(int c, My_Text_Editor* e); + static int kf_c_s_move(int c, My_Text_Editor* e); + static int kf_home(int, My_Text_Editor* e); + static int kf_end(int c, My_Text_Editor* e); + static int kf_left(int c, My_Text_Editor* e); + static int kf_up(int c, My_Text_Editor* e); + static int kf_right(int c, My_Text_Editor* e); + static int kf_down(int c, My_Text_Editor* e); + static int kf_page_up(int c, My_Text_Editor* e); + static int kf_page_down(int c, My_Text_Editor* e); + static int kf_insert(int c, My_Text_Editor* e); + static int kf_delete(int c, My_Text_Editor* e); + static int kf_copy(int c, My_Text_Editor* e); + static int kf_cut(int c, My_Text_Editor* e); + static int kf_paste(int c, My_Text_Editor* e); + static int kf_select_all(int c, My_Text_Editor* e); + static int kf_undo(int c, My_Text_Editor* e); + + protected: + int handle_key(); + void maybe_do_callback(); + + StatusBar_t* m_pStatusBar; + int insert_mode_; + Key_Binding* key_bindings; + static Key_Binding* global_key_bindings; + Key_Func default_key_function_; + void UpdateStatusBar(void); +}; + +#endif + +// +// End of "$Id$". +// + diff --git a/src/VirtualT.h b/src/VirtualT.h index bdeb942..55b8f6d 100644 --- a/src/VirtualT.h +++ b/src/VirtualT.h @@ -31,7 +31,7 @@ #ifndef _VIRTUALT_H_ #define _VIRTUALT_H_ -#define VERSION "1.4" +#define VERSION "1.5" enum { MODEL_M100 diff --git a/src/a85parse.cpp b/src/a85parse.cpp index e6bb017..bc94b77 100644 --- a/src/a85parse.cpp +++ b/src/a85parse.cpp @@ -17,11 +17,11 @@ */ -#ifndef A85PARSE_H_1176345433 +#ifndef A85PARSE_H_1277850585 #include "a85parse.h" #endif -#ifndef A85PARSE_H_1176345433 +#ifndef A85PARSE_H_1277850585 #error Mismatched header file #endif @@ -39,7 +39,7 @@ a85parse_pcb_type a85parse_pcb; #define PCB a85parse_pcb -/* Line 493, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 648, C:/Projects/VirtualT/src/a85parse.syn */ // Embedded C #include "MString.h" // Include MString header @@ -58,13 +58,19 @@ typedef int BOOL; VTAssembler* gAsm = 0; // Pointer to the assembler CRpnEquation* gEq = 0; // Pointer to active equation VTObArray* gExpList = 0; // Pointer to active expression list +CMacro* gMacro = 0; // Pointer to active macro MStringArray* gNameList = 0; // Pointer to active name list +int gDefine = 0; // Indicated in a #define reduction CCondition* gCond = 0; // Pointer to active condition +const char* gFilename = 0; // Pointer to the filename char ss[32][256]; // String Stack; +CMacro* gMacroStack[32]; // Macro Stack; +int ms_idx = 0; // Macro Stack Index char integer[64]; // Integer storage space char int_len = 0; // Integer string length int ss_idx = 0; // String Stack Index int ss_len = 0; // SS string length +int ss_addr = 0; // Address at start of literal name double gDivisor = 1.0; // Current divisor for float converwions int gTabSize = 4; char reg[10]; // Register arguments @@ -72,7 +78,8 @@ int reg_cnt = 0; // Register Arg count int label = 0; // Number of labels on string stack int name_list_cnt = 0; // Number of strings in name list int ex_cnt = 0; // Number of expressions in expression list - +int gAbort = 0; // Abort on #error +int page, seg; void a85parse(void); // This function checks the string accumulator for errors @@ -84,6 +91,8 @@ void check_string_stack(void) // If we have no errors... if (gAsm->m_Errors.GetSize() == 0) { + int c; + // Check string accumulator size int stringCount; if ((stringCount = ss_idx) != 0) @@ -92,6 +101,11 @@ void check_string_stack(void) string.Format("Internal Design Parse Error - %d string(s) left on stack!", stringCount); gAsm->m_Errors.Add(string); + for (c = 0; c < stringCount; c++) + { + string.Format(" %s", ss[ss_idx--]); + gAsm->m_Errors.Add(string); + } } } } @@ -105,11 +119,9 @@ BOOL ParseASMFile(const char* filename, VTAssembler* pAsm) if (pAsm == NULL) return FALSE; + // Make the given assembler a global gAsm = pAsm; - // Clear old design from the CDesign object - gAsm->ResetContent(); - // Insure no active equation left over from a previous run if (gEq != 0) delete gEq; @@ -119,13 +131,17 @@ BOOL ParseASMFile(const char* filename, VTAssembler* pAsm) delete gNameList; if (gCond != 0) delete gCond; + if (gMacro != 0) + delete gMacro; // Allocate an active equation to be used during parsing gEq = new CRpnEquation; gExpList = new VTObArray; gNameList = new MStringArray; gCond = new CCondition; + gMacro = new CMacro; gAsm->m_FileIndex = gAsm->m_Filenames.Add(filename); + gFilename = filename; // Try to open the file if ((gAsm->m_fd = fopen(gAsm->m_Filenames[gAsm->m_FileIndex], "r")) == 0) @@ -139,6 +155,12 @@ BOOL ParseASMFile(const char* filename, VTAssembler* pAsm) ss_idx = 0; ss_len = 0; int_len = 0; + gAbort = 0; + + // Reset the Macro stack + for (int c = 0; c < 32; c++) + gMacroStack[c] = 0; + ms_idx = 0; // Reset the Register, name, expression, and label counters reg_cnt = label = ex_cnt = name_list_cnt = 0; @@ -160,27 +182,166 @@ BOOL ParseASMFile(const char* filename, VTAssembler* pAsm) return TRUE; } +void handle_error(void) +{ + char msg[512]; + + sprintf(msg, "Error token = %d", (PCB).error_frame_token); +} + +void syntax_error(const char *token_name) +{ + MString string; + int eolMsg; + int expected_immediate = 0; + int expected_reg = 0; + + // Determine if this is the "unexpected eol" message + eolMsg = !strcmp("Unexpected '\\n'", (PCB).error_message); + + switch ((PCB).error_frame_token) + { + // Handle general statement syntax error + case a85parse_statement_token: + string.Format("Error in line %d(%s), column %d: Malformed %s - %s", + (PCB).line, gFilename, (PCB).column, + token_name, (PCB).error_message); + break; + + // Handle improper LXI instruction error + case a85parse_lxi_inst_start_token: + if (reg_cnt == 0) + expected_reg = 16; + else + expected_immediate = 1; + break; + + // Handle improper MVI instruction error + case a85parse_mvi_inst_start_token: + if (reg_cnt == 0) + expected_reg = 8; + else + expected_immediate = 1; + break; + + // Handle improper 16-bit register argument error + case a85parse_sixteen_bit_reg_inst_token: + case a85parse_stack_reg_inst_token: + expected_reg = 16; + break; + + // Handle improper 8-bit register argument error + case a85parse_eight_bit_reg_inst_token: + expected_reg = 8; + break; + + case a85parse_lxi_inst_token: + case a85parse_mvi_inst_token: + case a85parse_immediate_operand_inst_token: + expected_immediate = 1; + break; + + case a85parse_rst_inst_token: + if (eolMsg) + string.Format("Error in line %d(%s), column %d: Expected RST number", + (PCB).line, gFilename, (PCB).column); + else + string.Format("Error in line %d(%s), column %d: Invalid RST number", + (PCB).line, gFilename, (PCB).column, (PCB).error_message); + break; + + case a85parse_preproc_start_token: + if (eolMsg) + string.Format("Error in line %d(%s), column %d: Expected preprocessor directive", + (PCB).line, gFilename, (PCB).column); + else + string.Format("Error in line %d(%s), column %d: Unknown preprocessor directive", + (PCB).line, gFilename, (PCB).column, (PCB).error_message); + break; + + case a85parse_preproc_inst_token: + string.Format("Error in line %d(%s), column %d: Invalid preprocessor directive syntax", + (PCB).line, gFilename, (PCB).column, (PCB).error_message); + break; + + default: + if (eolMsg) + string.Format("Error in line %d(%s), column %d: Unexpected end of line", + (PCB).line, gFilename, (PCB).column); + else + string.Format("Error in line %d(%s), column %d: %s", + (PCB).line, gFilename, (PCB).column, (PCB).error_message); + break; + } + + if (expected_reg == 16) + { + if (eolMsg) + string.Format("Error in line %d(%s), column %d: Expected 16-bit register", + (PCB).line, gFilename, (PCB).column); + else + string.Format("Error in line %d(%s), column %d: Invalid 16-bit register", + (PCB).line, gFilename, (PCB).column); + } + else if (expected_reg == 8) + { + if (eolMsg) + string.Format("Error in line %d(%s), column %d: Expected 8-bit register", + (PCB).line, gFilename, (PCB).column); + else + string.Format("Error in line %d(%s), column %d: Invalid 8-bit register", + (PCB).line, gFilename, (PCB).column); + } + + if (expected_immediate) + { + if (eolMsg) + string.Format("Error in line %d(%s), column %d: Expected immediate operand", + (PCB).line, gFilename, (PCB).column); + else + string.Format("Error in line %d(%s), column %d: Invalid immediate operand", + (PCB).line, gFilename, (PCB).column); + } + + if (!gAbort) + gAsm->m_Errors.Add(string); + + // Clear the string stack + ss_idx = 0; + ss_len = 0; +} + // Define macros to handle input and errors #define TAB_SPACING gTabSize -#define GET_INPUT {(PCB).input_code = gAsm->m_fd != 0 ? \ - fgetc(gAsm->m_fd) : 0; if ((PCB).input_code == 13) (PCB).input_code = fgetc(gAsm->m_fd);} +#define GET_INPUT {(PCB).input_code = (gAsm->m_fd != 0 && !gAbort) ? \ + fgetc(gAsm->m_fd) : 0; if ((PCB).input_code == 13) (PCB).input_code = fgetc(gAsm->m_fd);\ + } + +#define SYNTAX_ERROR { syntax_error(TOKEN_NAMES[(PCB).error_frame_token]); } +/* #define SYNTAX_ERROR {MString string; if ((PCB).error_frame_token != 0) \ - string.Format("Malformed %s - %s, line %d, column %d", \ - TOKEN_NAMES[(PCB).error_frame_token], (PCB).error_message, (PCB).line, (PCB).column); else \ - string.Format("%s, line %d, column %d", \ - (PCB).error_message, (PCB).line, (PCB).column); \ - gAsm->m_Errors.Add(string); ss_idx = 0; ss_len = 0; } + string.Format("Error in line %d(%s), column%d: Malformed %s - %s", \ + (PCB).line, gFilename, (PCB).column, \ + TOKEN_NAMES[(PCB).error_frame_token], (PCB).error_message); \ + else if (strcmp("Unexpected '\\n'", (PCB).error_message) == 0) \ + string.Format("Error in line %d(%s), column %d: Unexpected end of line", \ + (PCB).line, gFilename, (PCB).column); \ + else \ + string.Format("Error in line %d(%s), column %d: %s", (PCB).line, gFilenaeme, \ + (PCB).column, (PCB).error_message); \ + if (!gAbort) gAsm->m_Errors.Add(string); ss_idx = 0; ss_len = 0; } +*/ #define PARSER_STACK_OVERFLOW {MString string; string.Format(\ "\nParser stack overflow, line %d, column %d",\ - (PCB).line, (PCB).column); gAsm->m_Errors.Add(string);} + (PCB).line, (PCB).column); if (!gAbort) gAsm->m_Errors.Add(string);} #define REDUCTION_TOKEN_ERROR {MString string; string.Format(\ "\nReduction token error, line %d, column %d", \ - (PCB).line, (PCB).column); gAsm->m_Errors.Add(string);} + (PCB).line, (PCB).column); if (!gAbort) gAsm->m_Errors.Add(string);} int do_hex(int h, int n) { @@ -268,6 +429,15 @@ int conv_to_bin() return temp1; } +int chtoh(char ch) +{ + if (ch < 'A') + return ch - '0'; + if (ch < 'a') + return ch = 'A' + 10; + return ch - 'a' + 10; +} + #ifndef CONVERT_CASE @@ -293,578 +463,741 @@ static int agConvertCase(int c) { #define TAB_SPACING 8 #endif -#define ag_rp_1() (gAsm->include(ss[ss_idx--])) +#define ag_rp_1() (gAsm->equate((const char *) -1)) + +#define ag_rp_2() (gAsm->directive_set((const char *) -1)) + +#define ag_rp_3() (gAsm->include(ss[ss_idx--])) + +#define ag_rp_4() (gAsm->include(ss[ss_idx--])) + +#define ag_rp_5() (gAsm->include(ss[ss_idx--])) -#define ag_rp_6() (gAsm->pragma_list()) +#define ag_rp_6() (gAsm->directive_cdseg(seg, page)) -#define ag_rp_7() (gAsm->pragma_hex()) +#define ag_rp_7() (gAsm->directive_cdseg(seg, page)) -#define ag_rp_8() (gAsm->preproc_ifdef(ss[ss_idx--])) +#define ag_rp_8() (handle_error()) -#define ag_rp_9() (gAsm->preproc_ifndef(ss[ss_idx--])) +#define ag_rp_9() (gAsm->include(ss[ss_idx--])) -#define ag_rp_10() (gAsm->preproc_else()) +#define ag_rp_10() (gAsm->include(ss[ss_idx--])) -#define ag_rp_11() (gAsm->preproc_endif()) +#define ag_rp_11() (gAsm->pragma_list()) -#define ag_rp_12() (gAsm->preproc_define(ss[ss_idx--])) +#define ag_rp_12() (gAsm->pragma_hex()) -#define ag_rp_13() (gAsm->preproc_undef(ss[ss_idx--])) +#define ag_rp_13() (gAsm->preproc_ifdef(ss[ss_idx--])) -#define ag_rp_14() (gAsm->equate(ss[ss_idx--])) +#define ag_rp_14() (gAsm->preproc_if()) -#define ag_rp_15() (gAsm->directive_set(ss[ss_idx--])) +#define ag_rp_15() (gAsm->preproc_elif()) -#define ag_rp_16() (gAsm->equate((const char *) -1)) +#define ag_rp_16() (gAsm->preproc_ifndef(ss[ss_idx--])) -#define ag_rp_17() (gAsm->directive_set((const char *) -1)) +#define ag_rp_17() (gAsm->preproc_else()) -#define ag_rp_18() (gAsm->directive_org()) +#define ag_rp_18() (gAsm->preproc_endif()) -#define ag_rp_19() (gAsm->directive_aseg()) +static void ag_rp_19(void) { +/* Line 122, C:/Projects/VirtualT/src/a85parse.syn */ +if (gAsm->preproc_error(ss[ss_idx--])) gAbort = TRUE; +} -#define ag_rp_20() (gAsm->directive_cseg(0)) +#define ag_rp_20() (gAsm->preproc_undef(ss[ss_idx--])) -#define ag_rp_21() (gAsm->directive_dseg(0)) +static void ag_rp_21(void) { +/* Line 125, C:/Projects/VirtualT/src/a85parse.syn */ + if (gMacroStack[ms_idx] != 0) { delete gMacroStack[ms_idx]; \ + gMacroStack[ms_idx] = 0; } \ + gMacro = gMacroStack[--ms_idx]; \ + gMacro->m_DefString = ss[ss_idx--]; \ + gAsm->preproc_define(); \ + gMacroStack[ms_idx] = 0; gDefine = 0; +} static void ag_rp_22(void) { -/* Line 103, C:/Projects/VirtualT/src/a85parse.syn */ - gAsm->label(ss[ss_idx--]); gAsm->directive_ds(); +/* Line 133, C:/Projects/VirtualT/src/a85parse.syn */ + if (gAsm->preproc_macro()) \ + PCB.reduction_token = a85parse_WS_token; } -#define ag_rp_23() (gAsm->directive_ds()) +static void ag_rp_23(void) { +/* Line 135, C:/Projects/VirtualT/src/a85parse.syn */ + if (gAsm->preproc_macro()) \ + PCB.reduction_token = a85parse_WS_token; +} static void ag_rp_24(void) { -/* Line 105, C:/Projects/VirtualT/src/a85parse.syn */ - gAsm->label(ss[ss_idx--]); gAsm->directive_db(); +/* Line 139, C:/Projects/VirtualT/src/a85parse.syn */ + gMacro->m_ParamList = gExpList; \ + gMacro->m_Name = ss[ss_idx--]; \ + gExpList = new VTObArray; \ + gMacroStack[ms_idx++] = gMacro; \ + if (gAsm->preproc_macro()) \ + PCB.reduction_token = a85parse_WS_token; \ + gMacro = new CMacro; +} + +static void ag_rp_25(void) { +/* Line 146, C:/Projects/VirtualT/src/a85parse.syn */ + gMacro->m_Name = ss[ss_idx--]; gMacroStack[ms_idx++] = gMacro; \ + if (gAsm->preproc_macro()) \ + PCB.reduction_token = a85parse_WS_token; \ + gMacro = new CMacro; +} + +static void ag_rp_26(int c) { +/* Line 152, C:/Projects/VirtualT/src/a85parse.syn */ + ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } -#define ag_rp_25() (gAsm->directive_db()) +static void ag_rp_27(int c) { +/* Line 153, C:/Projects/VirtualT/src/a85parse.syn */ + ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; +} + +static void ag_rp_28(void) { +/* Line 154, C:/Projects/VirtualT/src/a85parse.syn */ + ss[ss_idx][ss_len++] = '\n'; ss[ss_idx][ss_len] = 0; +} + +static void ag_rp_29(void) { +/* Line 157, C:/Projects/VirtualT/src/a85parse.syn */ + page = 0; seg = CSEG; +} -static void ag_rp_26(void) { -/* Line 107, C:/Projects/VirtualT/src/a85parse.syn */ - gAsm->label(ss[ss_idx--]); gAsm->directive_dw(); +static void ag_rp_30(void) { +/* Line 158, C:/Projects/VirtualT/src/a85parse.syn */ + page = 0; seg = DSEG; } -#define ag_rp_27() (gAsm->directive_dw()) +#define ag_rp_31(p) (page = p) + +#define ag_rp_32() (gAsm->pragma_list()) + +#define ag_rp_33() (gAsm->pragma_hex()) + +#define ag_rp_34() (gAsm->directive_org()) + +#define ag_rp_35() (gAsm->directive_aseg()) + +#define ag_rp_36() (gAsm->directive_ds()) + +#define ag_rp_37() (gAsm->directive_db()) + +#define ag_rp_38() (gAsm->directive_dw()) + +#define ag_rp_39() (gAsm->directive_public()) + +#define ag_rp_40() (gAsm->directive_extern()) -#define ag_rp_28() (gAsm->directive_extern()) +#define ag_rp_41() (gAsm->directive_extern()) -#define ag_rp_29() (gAsm->directive_extern()) +#define ag_rp_42() (gAsm->directive_module(ss[ss_idx--])) -#define ag_rp_30() (gAsm->directive_public()) +#define ag_rp_43() (gAsm->directive_name(ss[ss_idx--])) -#define ag_rp_31() (gAsm->directive_name(ss[ss_idx--])) +#define ag_rp_44() (gAsm->directive_stkln()) -#define ag_rp_32() (gAsm->directive_stkln()) +#define ag_rp_45() (gAsm->directive_echo()) -#define ag_rp_33() (gAsm->directive_end("")) +#define ag_rp_46() (gAsm->directive_echo(ss[ss_idx--])) -#define ag_rp_34() (gAsm->directive_end(ss[ss_idx--])) +#define ag_rp_47() (gAsm->directive_fill()) -#define ag_rp_35() (gAsm->directive_if()) +#define ag_rp_48() (gAsm->directive_printf(ss[ss_idx--])) -#define ag_rp_36() (gAsm->directive_else()) +#define ag_rp_49() (gAsm->directive_end("")) -#define ag_rp_37() (gAsm->directive_endif()) +#define ag_rp_50() (gAsm->directive_end(ss[ss_idx--])) -#define ag_rp_38() (gAsm->directive_title(ss[ss_idx--])) +#define ag_rp_51() (gAsm->directive_if()) -#define ag_rp_39() (gAsm->directive_title(ss[ss_idx--])) +#define ag_rp_52() (gAsm->directive_else()) -#define ag_rp_40(n) (gAsm->directive_page(n)) +#define ag_rp_53() (gAsm->directive_endif()) -#define ag_rp_41() (gAsm->directive_page(-1)) +#define ag_rp_54() (gAsm->directive_endian(1)) -#define ag_rp_42() (gAsm->directive_sym()) +#define ag_rp_55() (gAsm->directive_endian(0)) -#define ag_rp_43() (gAsm->directive_link(ss[ss_idx--])) +#define ag_rp_56() (gAsm->directive_title(ss[ss_idx--])) -#define ag_rp_44() (gAsm->directive_maclib(ss[ss_idx--])) +#define ag_rp_57() (gAsm->directive_title(ss[ss_idx--])) -#define ag_rp_45() (expression_list_literal()) +#define ag_rp_58() (gAsm->directive_page(-1)) -#define ag_rp_46() (expression_list_literal()) +#define ag_rp_59() (gAsm->directive_sym()) -#define ag_rp_47() (expression_list_equation()) +#define ag_rp_60() (gAsm->directive_link(ss[ss_idx--])) -#define ag_rp_48() (expression_list_equation()) +#define ag_rp_61() (gAsm->directive_maclib(ss[ss_idx--])) -#define ag_rp_49() (expression_list_literal()) +#define ag_rp_62() (gAsm->directive_page(page)) -#define ag_rp_50() (expression_list_literal()) +#define ag_rp_63() (page = 60) -#define ag_rp_51() (gNameList->Add(ss[ss_idx--])) +#define ag_rp_64(n) (page = n) -#define ag_rp_52() (gNameList->Add(ss[ss_idx--])) +#define ag_rp_65() (expression_list_literal()) -static void ag_rp_53(void) { -/* Line 151, C:/Projects/VirtualT/src/a85parse.syn */ +#define ag_rp_66() (expression_list_literal()) + +#define ag_rp_67() (expression_list_equation()) + +#define ag_rp_68() (expression_list_equation()) + +#define ag_rp_69() (expression_list_literal()) + +#define ag_rp_70() (expression_list_literal()) + +#define ag_rp_71() (gNameList->Add(ss[ss_idx--])) + +#define ag_rp_72() (gNameList->Add(ss[ss_idx--])) + +static void ag_rp_73(void) { +/* Line 236, C:/Projects/VirtualT/src/a85parse.syn */ strcpy(ss[++ss_idx], "$"); ss_len = 1; } -static void ag_rp_54(int c) { -/* Line 154, C:/Projects/VirtualT/src/a85parse.syn */ - ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; +static void ag_rp_74(void) { +/* Line 237, C:/Projects/VirtualT/src/a85parse.syn */ + strcpy(ss[++ss_idx], "&"); ss_len = 1; +} + +static void ag_rp_75(int c) { +/* Line 240, C:/Projects/VirtualT/src/a85parse.syn */ + ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; \ + if (PCB.column == 2) ss_addr = gAsm->m_ActiveSeg->m_Address; } -static void ag_rp_55(int c) { -/* Line 155, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_76(int c) { +/* Line 242, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_56(int c) { -/* Line 156, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_77(int c) { +/* Line 243, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_57(int c) { -/* Line 159, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_78(int c) { +/* Line 246, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_58(int c) { -/* Line 160, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_79(int c) { +/* Line 247, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_59(int ch1, int ch2) { -/* Line 166, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_80(int ch1, int ch2) { +/* Line 253, C:/Projects/VirtualT/src/a85parse.syn */ ss_idx++; ss_len = 2; sprintf(ss[ss_idx], "%c%c", ch1, ch2); } -static void ag_rp_60(int c) { -/* Line 167, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_81(int c) { +/* Line 254, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_61(void) { -/* Line 174, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_82(void) { +/* Line 261, C:/Projects/VirtualT/src/a85parse.syn */ ss_idx++; ss_len = 0; } -static void ag_rp_62(int c) { -/* Line 175, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_83(int c) { +/* Line 262, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_63(int c) { -/* Line 176, C:/Projects/VirtualT/src/a85parse.syn */ - ss[ss_idx][ss_len++] = '\\'; ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; -} +#define ag_rp_84(n) (n) + +#define ag_rp_85() ('\\') + +#define ag_rp_86() ('\n') + +#define ag_rp_87() ('\t') -static void ag_rp_64(void) { -/* Line 181, C:/Projects/VirtualT/src/a85parse.syn */ +#define ag_rp_88() ('\r') + +#define ag_rp_89() ('\0') + +#define ag_rp_90() ('"') + +#define ag_rp_91() (0x08) + +#define ag_rp_92() (0x0C) + +#define ag_rp_93(n1, n2, n3) ((n1-'0') * 64 + (n2-'0') * 8 + n3-'0') + +#define ag_rp_94(n1, n2) (chtoh(n1) * 16 + chtoh(n2)) + +#define ag_rp_95(n1) (chtoh(n1)) + +static void ag_rp_96(void) { +/* Line 282, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '>'; ss[ss_idx][ss_len] = 0; } -static void ag_rp_65(void) { -/* Line 184, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_97(void) { +/* Line 285, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = '<'; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_66(int c) { -/* Line 185, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_98(int c) { +/* Line 286, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_67(int c) { -/* Line 186, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_99(int c) { +/* Line 287, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '\\'; ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -#define ag_rp_68() (gAsm->label(ss[ss_idx--])) +#define ag_rp_100() (gAsm->label(ss[ss_idx--])) + +#define ag_rp_101() (gAsm->label(ss[ss_idx--])) + +#define ag_rp_102() (PAGE) + +#define ag_rp_103() (INPAGE) + +#define ag_rp_104() (condition(-1)) + +#define ag_rp_105() (condition(COND_NOCMP)) + +#define ag_rp_106() (condition(COND_EQ)) + +#define ag_rp_107() (condition(COND_NE)) + +#define ag_rp_108() (condition(COND_GE)) -#define ag_rp_69() (condition(-1)) +#define ag_rp_109() (condition(COND_LE)) -#define ag_rp_70() (condition(COND_NOCMP)) +#define ag_rp_110() (condition(COND_GT)) -#define ag_rp_71() (condition(COND_EQ)) +#define ag_rp_111() (condition(COND_LT)) -#define ag_rp_72() (condition(COND_NE)) +#define ag_rp_112() (gEq->Add(RPN_BITOR)) -#define ag_rp_73() (condition(COND_GE)) +#define ag_rp_113() (gEq->Add(RPN_BITOR)) -#define ag_rp_74() (condition(COND_LE)) +#define ag_rp_114() (gEq->Add(RPN_BITXOR)) -#define ag_rp_75() (condition(COND_GT)) +#define ag_rp_115() (gEq->Add(RPN_BITXOR)) -#define ag_rp_76() (condition(COND_LT)) +#define ag_rp_116() (gEq->Add(RPN_BITAND)) -#define ag_rp_77() (gEq->Add(RPN_BITOR)) +#define ag_rp_117() (gEq->Add(RPN_BITAND)) -#define ag_rp_78() (gEq->Add(RPN_BITOR)) +#define ag_rp_118() (gEq->Add(RPN_LEFTSHIFT)) -#define ag_rp_79() (gEq->Add(RPN_BITXOR)) +#define ag_rp_119() (gEq->Add(RPN_LEFTSHIFT)) -#define ag_rp_80() (gEq->Add(RPN_BITXOR)) +#define ag_rp_120() (gEq->Add(RPN_RIGHTSHIFT)) -#define ag_rp_81() (gEq->Add(RPN_BITAND)) +#define ag_rp_121() (gEq->Add(RPN_RIGHTSHIFT)) -#define ag_rp_82() (gEq->Add(RPN_BITAND)) +#define ag_rp_122() (gEq->Add(RPN_ADD)) -#define ag_rp_83() (gEq->Add(RPN_LEFTSHIFT)) +#define ag_rp_123() (gEq->Add(RPN_SUBTRACT)) -#define ag_rp_84() (gEq->Add(RPN_LEFTSHIFT)) +#define ag_rp_124() (gEq->Add(RPN_MULTIPLY)) -#define ag_rp_85() (gEq->Add(RPN_RIGHTSHIFT)) +#define ag_rp_125() (gEq->Add(RPN_DIVIDE)) -#define ag_rp_86() (gEq->Add(RPN_RIGHTSHIFT)) +#define ag_rp_126() (gEq->Add(RPN_MODULUS)) -#define ag_rp_87() (gEq->Add(RPN_ADD)) +#define ag_rp_127() (gEq->Add(RPN_MODULUS)) -#define ag_rp_88() (gEq->Add(RPN_SUBTRACT)) +#define ag_rp_128() (gEq->Add(RPN_EXPONENT)) -#define ag_rp_89() (gEq->Add(RPN_MULTIPLY)) +#define ag_rp_129() (gEq->Add(RPN_NOT)) -#define ag_rp_90() (gEq->Add(RPN_DIVIDE)) +#define ag_rp_130() (gEq->Add(RPN_NOT)) -#define ag_rp_91() (gEq->Add(RPN_MODULUS)) +#define ag_rp_131() (gEq->Add(RPN_BITNOT)) -#define ag_rp_92() (gEq->Add(RPN_MODULUS)) +#define ag_rp_132() (gEq->Add(RPN_NEGATE)) -#define ag_rp_93() (gEq->Add(RPN_EXPONENT)) +#define ag_rp_133(n) (gEq->Add((double) n)) -#define ag_rp_94() (gEq->Add(RPN_NOT)) +static void ag_rp_134(void) { +/* Line 375, C:/Projects/VirtualT/src/a85parse.syn */ + delete gMacro; gMacro = gMacroStack[ms_idx-1]; \ + gMacroStack[ms_idx--] = 0; if (gMacro->m_ParamList == 0) \ + {\ + gEq->Add(gMacro->m_Name); gMacro->m_Name = ""; }\ + else { \ + gEq->Add((VTObject *) gMacro); gMacro = new CMacro; \ + } +} + +#define ag_rp_135() (gEq->Add(RPN_FLOOR)) -#define ag_rp_95() (gEq->Add(RPN_NOT)) +#define ag_rp_136() (gEq->Add(RPN_CEIL)) -#define ag_rp_96() (gEq->Add(RPN_BITNOT)) +#define ag_rp_137() (gEq->Add(RPN_LN)) -#define ag_rp_97(n) (gEq->Add((double) n)) +#define ag_rp_138() (gEq->Add(RPN_LOG)) -#define ag_rp_98() (gEq->Add(ss[ss_idx--])) +#define ag_rp_139() (gEq->Add(RPN_SQRT)) -#define ag_rp_99() (gEq->Add(RPN_FLOOR)) +#define ag_rp_140() (gEq->Add(RPN_IP)) -#define ag_rp_100() (gEq->Add(RPN_CEIL)) +#define ag_rp_141() (gEq->Add(RPN_FP)) -#define ag_rp_101() (gEq->Add(RPN_LN)) +#define ag_rp_142() (gEq->Add(RPN_HIGH)) -#define ag_rp_102() (gEq->Add(RPN_LOG)) +#define ag_rp_143() (gEq->Add(RPN_LOW)) -#define ag_rp_103() (gEq->Add(RPN_SQRT)) +#define ag_rp_144() (gEq->Add(RPN_DEFINED, ss[ss_idx--])) -#define ag_rp_104() (gEq->Add(RPN_IP)) +#define ag_rp_145(n) (n) -#define ag_rp_105() (gEq->Add(RPN_FP)) +#define ag_rp_146(r) (r) -#define ag_rp_106(n) (n) +#define ag_rp_147(n) (n) -#define ag_rp_107(r) (r) +#define ag_rp_148() (conv_to_dec()) -#define ag_rp_108(n) (n) +#define ag_rp_149() (conv_to_hex()) -#define ag_rp_109() (conv_to_dec()) +#define ag_rp_150() (conv_to_bin()) -#define ag_rp_110() (conv_to_hex()) +#define ag_rp_151() (conv_to_oct()) -#define ag_rp_111() (conv_to_hex()) +#define ag_rp_152() (conv_to_hex()) -#define ag_rp_112() (conv_to_hex()) +#define ag_rp_153() (conv_to_hex()) -#define ag_rp_113() (conv_to_bin()) +#define ag_rp_154() (conv_to_bin()) -#define ag_rp_114() (conv_to_oct()) +#define ag_rp_155() (conv_to_oct()) -#define ag_rp_115() (conv_to_dec()) +#define ag_rp_156() (conv_to_dec()) -static void ag_rp_116(int n) { -/* Line 312, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_157(int n) { +/* Line 421, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_117(int n) { -/* Line 313, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_158(int n) { +/* Line 422, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 2; integer[0] = '-', integer[1] = n; integer[2] = 0; } -static void ag_rp_118(int n) { -/* Line 314, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_159(int n) { +/* Line 423, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_119(int n) { -/* Line 315, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_160(int n) { +/* Line 424, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_120(int n) { -/* Line 320, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_161(int n) { +/* Line 429, C:/Projects/VirtualT/src/a85parse.syn */ + int_len = 1; integer[0] = n; integer[1] = 0; +} + +static void ag_rp_162(int n) { +/* Line 430, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_121(int n) { -/* Line 321, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_163(int n) { +/* Line 431, C:/Projects/VirtualT/src/a85parse.syn */ + integer[int_len++] = n; integer[int_len] = 0; +} + +static void ag_rp_164(int n) { +/* Line 434, C:/Projects/VirtualT/src/a85parse.syn */ + integer[int_len++] = n; integer[int_len] = 0; +} + +static void ag_rp_165(int n) { +/* Line 435, C:/Projects/VirtualT/src/a85parse.syn */ + integer[int_len++] = n; integer[int_len] = 0; +} + +static void ag_rp_166(int n) { +/* Line 438, C:/Projects/VirtualT/src/a85parse.syn */ + integer[int_len++] = n; integer[int_len] = 0; +} + +static void ag_rp_167(int n) { +/* Line 439, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_122(int n) { -/* Line 324, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_168(int n) { +/* Line 442, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_123(int n) { -/* Line 325, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_169(int n) { +/* Line 443, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -#define ag_rp_124(n) (n) +#define ag_rp_170(n) (n) -#define ag_rp_125(n1, n2) ((n1 << 8) | n2) +#define ag_rp_171(n1, n2) ((n1 << 8) | n2) -#define ag_rp_126() ('\\') +#define ag_rp_172() ('\\') -#define ag_rp_127(n) (n) +#define ag_rp_173(n) (n) -#define ag_rp_128() ('\\') +#define ag_rp_174() ('\\') -#define ag_rp_129() ('\n') +#define ag_rp_175() ('\n') -#define ag_rp_130() ('\t') +#define ag_rp_176() ('\t') -#define ag_rp_131() ('\r') +#define ag_rp_177() ('\r') -#define ag_rp_132() ('\0') +#define ag_rp_178() ('\0') -#define ag_rp_133() ('\'') +#define ag_rp_179() ('\'') -#define ag_rp_134() ('\'') +#define ag_rp_180() ('\'') -static double ag_rp_135(void) { -/* Line 346, C:/Projects/VirtualT/src/a85parse.syn */ +static double ag_rp_181(void) { +/* Line 464, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor = 1.0; return (double) conv_to_dec(); } -static double ag_rp_136(int d) { -/* Line 347, C:/Projects/VirtualT/src/a85parse.syn */ +static double ag_rp_182(int d) { +/* Line 465, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor = 10.0; return ((double) (d - '0') / gDivisor); } -static double ag_rp_137(double r, int d) { -/* Line 348, C:/Projects/VirtualT/src/a85parse.syn */ +static double ag_rp_183(double r, int d) { +/* Line 466, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor *= 10.0; return (r + (double) (d - '0') / gDivisor); } -#define ag_rp_138() (reg[reg_cnt++] = '0') - -#define ag_rp_139() (reg[reg_cnt++] = '1') +#define ag_rp_184() (reg[reg_cnt++] = '0') -#define ag_rp_140() (reg[reg_cnt++] = '2') +#define ag_rp_185() (reg[reg_cnt++] = '1') -#define ag_rp_141() (reg[reg_cnt++] = '3') +#define ag_rp_186() (reg[reg_cnt++] = '2') -#define ag_rp_142() (reg[reg_cnt++] = '4') +#define ag_rp_187() (reg[reg_cnt++] = '3') -#define ag_rp_143() (reg[reg_cnt++] = '5') +#define ag_rp_188() (reg[reg_cnt++] = '4') -#define ag_rp_144() (reg[reg_cnt++] = '6') +#define ag_rp_189() (reg[reg_cnt++] = '5') -#define ag_rp_145() (reg[reg_cnt++] = '7') +#define ag_rp_190() (reg[reg_cnt++] = '6') -#define ag_rp_146() (reg[reg_cnt++] = '0') +#define ag_rp_191() (reg[reg_cnt++] = '7') -#define ag_rp_147() (reg[reg_cnt++] = '1') +#define ag_rp_192() (reg[reg_cnt++] = '0') -#define ag_rp_148() (reg[reg_cnt++] = '2') +#define ag_rp_193() (reg[reg_cnt++] = '1') -#define ag_rp_149() (reg[reg_cnt++] = '3') +#define ag_rp_194() (reg[reg_cnt++] = '2') -#define ag_rp_150() (reg[reg_cnt++] = '0') +#define ag_rp_195() (reg[reg_cnt++] = '3') -#define ag_rp_151() (reg[reg_cnt++] = '1') +#define ag_rp_196() (reg[reg_cnt++] = '0') -#define ag_rp_152() (reg[reg_cnt++] = '2') +#define ag_rp_197() (reg[reg_cnt++] = '1') -#define ag_rp_153() (reg[reg_cnt++] = '3') +#define ag_rp_198() (reg[reg_cnt++] = '2') -#define ag_rp_154() (reg[reg_cnt++] = '3') +#define ag_rp_199() (reg[reg_cnt++] = '3') -#define ag_rp_155() (reg[reg_cnt++] = '0') +#define ag_rp_200() (reg[reg_cnt++] = '3') -#define ag_rp_156() (reg[reg_cnt++] = '1') +#define ag_rp_201() (reg[reg_cnt++] = '0') -#define ag_rp_157() (gAsm->opcode_arg_equ8 (OPCODE_ACI)) +#define ag_rp_202() (reg[reg_cnt++] = '1') -#define ag_rp_158() (gAsm->opcode_arg_1reg (OPCODE_ADC)) +#define ag_rp_203() (gAsm->opcode_arg_0 (OPCODE_ASHR)) -#define ag_rp_159() (gAsm->opcode_arg_1reg (OPCODE_ADD)) +#define ag_rp_204() (gAsm->opcode_arg_0 (OPCODE_CMA)) -#define ag_rp_160() (gAsm->opcode_arg_equ8 (OPCODE_ADI)) +#define ag_rp_205() (gAsm->opcode_arg_0 (OPCODE_CMC)) -#define ag_rp_161() (gAsm->opcode_arg_1reg (OPCODE_ANA)) +#define ag_rp_206() (gAsm->opcode_arg_0 (OPCODE_DAA)) -#define ag_rp_162() (gAsm->opcode_arg_equ8 (OPCODE_ANI)) +#define ag_rp_207() (gAsm->opcode_arg_0 (OPCODE_DI)) -#define ag_rp_163() (gAsm->opcode_arg_0 (OPCODE_ASHR)) +#define ag_rp_208() (gAsm->opcode_arg_0 (OPCODE_DSUB)) -#define ag_rp_164() (gAsm->opcode_arg_equ16 (OPCODE_CALL)) +#define ag_rp_209() (gAsm->opcode_arg_0 (OPCODE_EI)) -#define ag_rp_165() (gAsm->opcode_arg_equ16 (OPCODE_CC)) +#define ag_rp_210() (gAsm->opcode_arg_0 (OPCODE_HLT)) -#define ag_rp_166() (gAsm->opcode_arg_equ16 (OPCODE_CM)) +#define ag_rp_211() (gAsm->opcode_arg_0 (OPCODE_LHLX)) -#define ag_rp_167() (gAsm->opcode_arg_0 (OPCODE_CMA)) +#define ag_rp_212() (gAsm->opcode_arg_0 (OPCODE_NOP)) -#define ag_rp_168() (gAsm->opcode_arg_0 (OPCODE_CMC)) +#define ag_rp_213() (gAsm->opcode_arg_0 (OPCODE_PCHL)) -#define ag_rp_169() (gAsm->opcode_arg_1reg (OPCODE_CMP)) +#define ag_rp_214() (gAsm->opcode_arg_0 (OPCODE_RAL)) -#define ag_rp_170() (gAsm->opcode_arg_equ16 (OPCODE_CNC)) +#define ag_rp_215() (gAsm->opcode_arg_0 (OPCODE_RAR)) -#define ag_rp_171() (gAsm->opcode_arg_equ16 (OPCODE_CNZ)) +#define ag_rp_216() (gAsm->opcode_arg_0 (OPCODE_RC)) -#define ag_rp_172() (gAsm->opcode_arg_equ16 (OPCODE_CP)) +#define ag_rp_217() (gAsm->opcode_arg_0 (OPCODE_RET)) -#define ag_rp_173() (gAsm->opcode_arg_equ16 (OPCODE_CPE)) +#define ag_rp_218() (gAsm->opcode_arg_0 (OPCODE_RIM)) -#define ag_rp_174() (gAsm->opcode_arg_equ8 (OPCODE_CPI)) +#define ag_rp_219() (gAsm->opcode_arg_0 (OPCODE_RLC)) -#define ag_rp_175() (gAsm->opcode_arg_equ16 (OPCODE_CPO)) +#define ag_rp_220() (gAsm->opcode_arg_0 (OPCODE_RLDE)) -#define ag_rp_176() (gAsm->opcode_arg_equ16 (OPCODE_CZ)) +#define ag_rp_221() (gAsm->opcode_arg_0 (OPCODE_RM)) -#define ag_rp_177() (gAsm->opcode_arg_0 (OPCODE_DAA)) +#define ag_rp_222() (gAsm->opcode_arg_0 (OPCODE_RNC)) -#define ag_rp_178() (gAsm->opcode_arg_1reg (OPCODE_DAD)) +#define ag_rp_223() (gAsm->opcode_arg_0 (OPCODE_RNZ)) -#define ag_rp_179() (gAsm->opcode_arg_1reg (OPCODE_DCR)) +#define ag_rp_224() (gAsm->opcode_arg_0 (OPCODE_RP)) -#define ag_rp_180() (gAsm->opcode_arg_1reg (OPCODE_DCX)) +#define ag_rp_225() (gAsm->opcode_arg_0 (OPCODE_RPE)) -#define ag_rp_181() (gAsm->opcode_arg_0 (OPCODE_DI)) +#define ag_rp_226() (gAsm->opcode_arg_0 (OPCODE_RPO)) -#define ag_rp_182() (gAsm->opcode_arg_0 (OPCODE_DSUB)) +#define ag_rp_227() (gAsm->opcode_arg_0 (OPCODE_RRC)) -#define ag_rp_183() (gAsm->opcode_arg_0 (OPCODE_EI)) +#define ag_rp_228() (gAsm->opcode_arg_0 (OPCODE_RSTV)) -#define ag_rp_184() (gAsm->opcode_arg_0 (OPCODE_HLT)) +#define ag_rp_229() (gAsm->opcode_arg_0 (OPCODE_RZ)) -#define ag_rp_185() (gAsm->opcode_arg_equ8 (OPCODE_IN)) +#define ag_rp_230() (gAsm->opcode_arg_0 (OPCODE_SHLX)) -#define ag_rp_186() (gAsm->opcode_arg_1reg (OPCODE_INR)) +#define ag_rp_231() (gAsm->opcode_arg_0 (OPCODE_SIM)) -#define ag_rp_187() (gAsm->opcode_arg_1reg (OPCODE_INX)) +#define ag_rp_232() (gAsm->opcode_arg_0 (OPCODE_SPHL)) -#define ag_rp_188() (gAsm->opcode_arg_equ16 (OPCODE_JC)) +#define ag_rp_233() (gAsm->opcode_arg_0 (OPCODE_STC)) -#define ag_rp_189() (gAsm->opcode_arg_equ16 (OPCODE_JD)) +#define ag_rp_234() (gAsm->opcode_arg_0 (OPCODE_XCHG)) -#define ag_rp_190() (gAsm->opcode_arg_equ16 (OPCODE_JD)) +#define ag_rp_235() (gAsm->opcode_arg_0 (OPCODE_XTHL)) -#define ag_rp_191() (gAsm->opcode_arg_equ16 (OPCODE_JM)) +#define ag_rp_236() (gAsm->opcode_arg_1reg (OPCODE_STAX)) -#define ag_rp_192() (gAsm->opcode_arg_equ16 (OPCODE_JMP)) +#define ag_rp_237() (gAsm->opcode_arg_1reg (OPCODE_LDAX)) -#define ag_rp_193() (gAsm->opcode_arg_equ16 (OPCODE_JNC)) +#define ag_rp_238() (gAsm->opcode_arg_1reg (OPCODE_POP)) -#define ag_rp_194() (gAsm->opcode_arg_equ16 (OPCODE_JND)) +#define ag_rp_239() (gAsm->opcode_arg_1reg (OPCODE_PUSH)) -#define ag_rp_195() (gAsm->opcode_arg_equ16 (OPCODE_JND)) +#define ag_rp_240() (gAsm->opcode_arg_1reg (OPCODE_ADC)) -#define ag_rp_196() (gAsm->opcode_arg_equ16 (OPCODE_JNZ)) +#define ag_rp_241() (gAsm->opcode_arg_1reg (OPCODE_ADD)) -#define ag_rp_197() (gAsm->opcode_arg_equ16 (OPCODE_JP)) +#define ag_rp_242() (gAsm->opcode_arg_1reg (OPCODE_ANA)) -#define ag_rp_198() (gAsm->opcode_arg_equ16 (OPCODE_JPE)) +#define ag_rp_243() (gAsm->opcode_arg_1reg (OPCODE_CMP)) -#define ag_rp_199() (gAsm->opcode_arg_equ16 (OPCODE_JPO)) +#define ag_rp_244() (gAsm->opcode_arg_1reg (OPCODE_DCR)) -#define ag_rp_200() (gAsm->opcode_arg_equ16 (OPCODE_JZ)) +#define ag_rp_245() (gAsm->opcode_arg_1reg (OPCODE_INR)) -#define ag_rp_201() (gAsm->opcode_arg_equ16 (OPCODE_LDA)) +#define ag_rp_246() (gAsm->opcode_arg_2reg (OPCODE_MOV)) -#define ag_rp_202() (gAsm->opcode_arg_1reg (OPCODE_LDAX)) +#define ag_rp_247() (gAsm->opcode_arg_1reg (OPCODE_ORA)) -#define ag_rp_203() (gAsm->opcode_arg_equ8 (OPCODE_LDEH)) +#define ag_rp_248() (gAsm->opcode_arg_1reg (OPCODE_SBB)) -#define ag_rp_204() (gAsm->opcode_arg_equ8 (OPCODE_LDES)) +#define ag_rp_249() (gAsm->opcode_arg_1reg (OPCODE_SUB)) -#define ag_rp_205() (gAsm->opcode_arg_equ16 (OPCODE_LHLD)) +#define ag_rp_250() (gAsm->opcode_arg_1reg (OPCODE_XRA)) -#define ag_rp_206() (gAsm->opcode_arg_0 (OPCODE_LHLX)) +#define ag_rp_251() (gAsm->opcode_arg_1reg (OPCODE_DAD)) -#define ag_rp_207() (gAsm->opcode_arg_1reg_equ8(OPCODE_LXI)) +#define ag_rp_252() (gAsm->opcode_arg_1reg (OPCODE_DCX)) -#define ag_rp_208() (gAsm->opcode_arg_2reg (OPCODE_MOV)) +#define ag_rp_253() (gAsm->opcode_arg_1reg (OPCODE_INX)) -#define ag_rp_209() (gAsm->opcode_arg_1reg_equ8(OPCODE_MVI)) +#define ag_rp_254() (gAsm->opcode_arg_1reg_equ16(OPCODE_LXI)) -#define ag_rp_210() (gAsm->opcode_arg_0 (OPCODE_NOP)) +#define ag_rp_255() (gAsm->opcode_arg_1reg_equ8(OPCODE_MVI)) -#define ag_rp_211() (gAsm->opcode_arg_1reg (OPCODE_ORA)) +#define ag_rp_256(c) (gAsm->opcode_arg_imm (OPCODE_RST, c)) -#define ag_rp_212() (gAsm->opcode_arg_equ8 (OPCODE_ORI)) +#define ag_rp_257() (gAsm->opcode_arg_equ8 (OPCODE_ACI)) -#define ag_rp_213() (gAsm->opcode_arg_equ8 (OPCODE_OUT)) +#define ag_rp_258() (gAsm->opcode_arg_equ8 (OPCODE_ADI)) -#define ag_rp_214() (gAsm->opcode_arg_0 (OPCODE_PCHL)) +#define ag_rp_259() (gAsm->opcode_arg_equ8 (OPCODE_ANI)) -#define ag_rp_215() (gAsm->opcode_arg_1reg (OPCODE_POP)) +#define ag_rp_260() (gAsm->opcode_arg_equ16 (OPCODE_CALL)) -#define ag_rp_216() (gAsm->opcode_arg_1reg (OPCODE_PUSH)) +#define ag_rp_261() (gAsm->opcode_arg_equ16 (OPCODE_CC)) -#define ag_rp_217() (gAsm->opcode_arg_0 (OPCODE_RAL)) +#define ag_rp_262() (gAsm->opcode_arg_equ16 (OPCODE_CM)) -#define ag_rp_218() (gAsm->opcode_arg_0 (OPCODE_RAR)) +#define ag_rp_263() (gAsm->opcode_arg_equ16 (OPCODE_CNC)) -#define ag_rp_219() (gAsm->opcode_arg_0 (OPCODE_RC)) +#define ag_rp_264() (gAsm->opcode_arg_equ16 (OPCODE_CNZ)) -#define ag_rp_220() (gAsm->opcode_arg_0 (OPCODE_RET)) +#define ag_rp_265() (gAsm->opcode_arg_equ16 (OPCODE_CP)) -#define ag_rp_221() (gAsm->opcode_arg_0 (OPCODE_RIM)) +#define ag_rp_266() (gAsm->opcode_arg_equ16 (OPCODE_CPE)) -#define ag_rp_222() (gAsm->opcode_arg_0 (OPCODE_RLC)) +#define ag_rp_267() (gAsm->opcode_arg_equ8 (OPCODE_CPI)) -#define ag_rp_223() (gAsm->opcode_arg_0 (OPCODE_RLDE)) +#define ag_rp_268() (gAsm->opcode_arg_equ16 (OPCODE_CPO)) -#define ag_rp_224() (gAsm->opcode_arg_0 (OPCODE_RM)) +#define ag_rp_269() (gAsm->opcode_arg_equ16 (OPCODE_CZ)) -#define ag_rp_225() (gAsm->opcode_arg_0 (OPCODE_RNC)) +#define ag_rp_270() (gAsm->opcode_arg_equ8 (OPCODE_IN)) -#define ag_rp_226() (gAsm->opcode_arg_0 (OPCODE_RNZ)) +#define ag_rp_271() (gAsm->opcode_arg_equ16 (OPCODE_JC)) -#define ag_rp_227() (gAsm->opcode_arg_0 (OPCODE_RP)) +#define ag_rp_272() (gAsm->opcode_arg_equ16 (OPCODE_JD)) -#define ag_rp_228() (gAsm->opcode_arg_0 (OPCODE_RPE)) +#define ag_rp_273() (gAsm->opcode_arg_equ16 (OPCODE_JM)) -#define ag_rp_229() (gAsm->opcode_arg_0 (OPCODE_RPO)) +#define ag_rp_274() (gAsm->opcode_arg_equ16 (OPCODE_JMP)) -#define ag_rp_230() (gAsm->opcode_arg_0 (OPCODE_RRC)) +#define ag_rp_275() (gAsm->opcode_arg_equ16 (OPCODE_JNC)) -#define ag_rp_231(c) (gAsm->opcode_arg_imm (OPCODE_RST, c)) +#define ag_rp_276() (gAsm->opcode_arg_equ16 (OPCODE_JND)) -#define ag_rp_232() (gAsm->opcode_arg_0 (OPCODE_RZ)) +#define ag_rp_277() (gAsm->opcode_arg_equ16 (OPCODE_JNZ)) -#define ag_rp_233() (gAsm->opcode_arg_1reg (OPCODE_SBB)) +#define ag_rp_278() (gAsm->opcode_arg_equ16 (OPCODE_JP)) -#define ag_rp_234() (gAsm->opcode_arg_equ8 (OPCODE_SBI)) +#define ag_rp_279() (gAsm->opcode_arg_equ16 (OPCODE_JPE)) -#define ag_rp_235() (gAsm->opcode_arg_equ16 (OPCODE_SHLD)) +#define ag_rp_280() (gAsm->opcode_arg_equ16 (OPCODE_JPO)) -#define ag_rp_236() (gAsm->opcode_arg_0 (OPCODE_SHLX)) +#define ag_rp_281() (gAsm->opcode_arg_equ16 (OPCODE_JZ)) -#define ag_rp_237() (gAsm->opcode_arg_0 (OPCODE_SIM)) +#define ag_rp_282() (gAsm->opcode_arg_equ16 (OPCODE_LDA)) -#define ag_rp_238() (gAsm->opcode_arg_0 (OPCODE_SPHL)) +#define ag_rp_283() (gAsm->opcode_arg_equ8 (OPCODE_LDEH)) -#define ag_rp_239() (gAsm->opcode_arg_equ16 (OPCODE_STA)) +#define ag_rp_284() (gAsm->opcode_arg_equ8 (OPCODE_LDES)) -#define ag_rp_240() (gAsm->opcode_arg_1reg (OPCODE_STAX)) +#define ag_rp_285() (gAsm->opcode_arg_equ16 (OPCODE_LHLD)) -#define ag_rp_241() (gAsm->opcode_arg_0 (OPCODE_STC)) +#define ag_rp_286() (gAsm->opcode_arg_equ8 (OPCODE_ORI)) -#define ag_rp_242() (gAsm->opcode_arg_1reg (OPCODE_SUB)) +#define ag_rp_287() (gAsm->opcode_arg_equ8 (OPCODE_OUT)) -#define ag_rp_243() (gAsm->opcode_arg_equ8 (OPCODE_SUI)) +#define ag_rp_288() (gAsm->opcode_arg_equ8 (OPCODE_SBI)) -#define ag_rp_244() (gAsm->opcode_arg_0 (OPCODE_XCHG)) +#define ag_rp_289() (gAsm->opcode_arg_equ16 (OPCODE_SHLD)) -#define ag_rp_245() (gAsm->opcode_arg_1reg (OPCODE_XRA)) +#define ag_rp_290() (gAsm->opcode_arg_equ16 (OPCODE_STA)) -#define ag_rp_246() (gAsm->opcode_arg_equ8 (OPCODE_XRI)) +#define ag_rp_291() (gAsm->opcode_arg_equ8 (OPCODE_SUI)) -#define ag_rp_247() (gAsm->opcode_arg_0 (OPCODE_XTHL)) +#define ag_rp_292() (gAsm->opcode_arg_equ8 (OPCODE_XRI)) #define READ_COUNTS @@ -900,30 +1233,36 @@ typedef enum { static a85parse_vs_type const ag_null_value NULL_VALUE_INITIALIZER; -static const unsigned char ag_rpx[] = { +static const unsigned short ag_rpx[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 0, 0, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 0, 41, 42, 43, 44, 45, 46, 47, 48, 0, 49, 50, 51, 52, 53, 54, 0, 55, - 56, 0, 57, 58, 59, 0, 60, 61, 62, 63, 0, 64, 65, 66, 0, 0, 0, 67, - 0, 0, 68, 0, 0, 69, 0, 0, 70, 0, 0, 71, 0, 0, 72, 0, 0, 73, - 74, 0, 75, 76, 0, 77, 78, 0, 79, 80, 81, 82, 0, 83, 84, 0, 85, 86, - 87, 88, 89, 0, 90, 91, 92, 93, 94, 0, 0, 95, 96, 97, 98, 99,100,101, - 102,103,104,105,106,107,108,109,110,111,112,113,114,115, 0, 0,116,117, - 118,119,120,121,122,123,124,125,126,127,128,129,130, 0,131,132,133,134, - 135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152, - 0, 0, 0,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167, - 168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185, - 186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203, - 204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221, - 222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, - 240,241,242,243 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 3, 4, 5, 6, + 7, 8, 0, 0, 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 0, 31, 0, 32, 33, 0, 0, 0, + 34, 35, 0, 0, 36, 0, 0, 0, 37, 0, 0, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 0, 0, 73, 74, 75, 76, 77, + 78, 79, 0, 80, 81, 0, 82, 83, 0, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 0, 0, 94, 95, 96, 97, 98, 99, 0,100,101,102,103,104,105, 0, 0, + 0,106, 0, 0,107, 0, 0,108, 0, 0,109, 0, 0,110, 0, 0,111, 0, + 0,112,113, 0,114,115, 0,116,117, 0,118,119,120,121, 0,122,123, 0, + 124,125,126,127,128, 0,129,130,131,132,133,134, 0, 0,135,136,137,138, + 139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154, 0, 0, + 155,156,157,158,159,160, 0, 0,161,162,163,164,165,166,167,168,169,170, + 171,172,173,174,175,176,177,178,179,180, 0,181,182,183,184,185,186,187, + 188,189, 0, 0,190,191, 0, 0,192, 0, 0,193, 0, 0,194,195,196,197, + 198,199,200,201,202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,203,204,205,206,207, 0, 0,208,209,210, 0, 0, 0,211,212,213, + 214,215,216,217,218,219, 0, 0,220,221,222,223,224,225,226,227,228,229, + 0, 0, 0,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244, + 245,246,247,248,249,250,251,252,253, 0,254, 0,255,256,257,258,259,260, + 261,262,263,264,265,266,267,268,269,270,271, 0, 0, 0, 0, 0,272,273, + 274,275, 0, 0, 0, 0, 0,276,277,278,279,280,281,282, 0, 0, 0,283, + 0, 0,284,285,286,287,288,289,290,291,292 }; static const unsigned char ag_key_itt[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -937,940 +1276,576 @@ static const unsigned char ag_key_itt[] = { }; static const unsigned short ag_key_pt[] = { - 1,292, 1,296, 1,298, 1,306, 1,307, 1,308, 1,309, 1,310, - 1,311, 1,312, 1,313, 1,314, 1,315, 1,316, 1,317, 1,318, - 1,319, 1,320, 1,321, 1,322, 1,323, 1,325, 1,327, 1,328, - 1,329, 1,330, 1, 86, 1,332, 1,335, 1,337, 1,339, 1,341, - 1,343, 1,346, 1,348, 1,350, 1,352, 1,354, 1,360, 1,363, - 1,367, 1,368, 1,369, 1,370, 1,371, 1,372, 1,373, 1,377, - 1,375, 1,160, 1,376, 1,176, 1,177, 1,178, 1,179, 1,379, - 1,181, 1,378, 1,380, 1,382, 1,383, 1,384, 1,385, 1,386, - 1,387, 1,388, 1,389, 1,390, 1,391, 1,392, 1,393, 1,394, - 1,395, 1,396, 1,397, 1,398, 1,399, 1,400, 1,401, 1,403, - 1,404, 1,405, 1,406, 1,407, 1,408, 1,409, 1,410, 1,411, + 1,399, 1,400, 1,401, 1,402, 1,408, 1,407, 1,409, 1,411, 1,412, 1,413, 1,414, 1,415, 1,416, 1,417, 1,418, 1,419, - 1,420, 1,421, 1,422, 1,423, 1,424, 1,425, 1,426, 1,427, - 1,428, 1,429, 1,430, 1,431, 1,432, 1,433, 1,434, 1,435, - 1,436, 1,437, 1,438, 1,439, 1,440, 1,441, 1,442, 1,443, - 1,444, 1,445, 1,446, 1,447, 1,448, 1,449, 1,450, 1,451, - 1,452, 1,453, 1,454, 1,455, 1,456, 1,457, 1,458, 1,459, - 1,460, 1,461, 1,462, 1,463, 1,464, 1,465, 1,466, 1,467, - 1,468, 1,469, 1,470, 1,471, 1,472,0 + 1,424, 1,425, 1,426, 1,429, 1,430, 1,431, 1,432, 1,433, + 1,434, 1,435, 1,436, 1,437, 1,438, 1,439, 1,440, 1,441, + 1,442, 1,443, 1,444, 1,446, 1,447, 1,448, 1,449, 1,451, + 1,452, 1,453, 1,454, 1,455, 1,456, 1,131, 1,459, 1,460, + 1,463, 1,465, 1,467, 1,469, 1,471, 1,474, 1,476, 1,478, + 1,480, 1,482, 1,488, 1,491, 1,493, 1,494, 1,495, 1,496, + 1,497, 1,498, 1,499, 1,500, 1,501, 1,503, 1,216, 1,217, + 1,229, 1,230, 1,231, 1,232, 1,233, 1,234, 1,235, 1,506, + 1,239, 1,241, 1,243, 1,245, 1,505, 1,507, 1,508, 1,509, + 1,510, 1,511, 1,512, 1,513, 1,514, 1,515, 1,516, 1,517, + 1,518, 1,519, 1,520, 1,521, 1,522, 1,523, 1,524, 1,525, + 1,526, 1,527, 1,528, 1,529, 1,530, 1,531, 1,532, 1,533, + 1,534, 1,535, 1,536, 1,537, 1,538, 1,539, 1,540, 1,541, + 1,542, 1,543, 1,544, 1,545, 1,546, 1,547, 1,548, 1,549, + 1,550, 1,551, 1,552, 1,553, 1,555, 1,556, 1,557, 1,558, + 1,559, 1,560, 1,561, 1,562, 1,563, 1,564, 1,565, 1,567, + 1,568, 1,569, 1,570, 1,571, 1,572, 1,573, 1,574, 1,575, + 1,576, 1,577, 1,578, 1,579, 1,580, 1,581, 1,582, 1,583, + 1,584, 1,585, 1,586, 1,587, 1,588, 1,589, 1,590, 1,591, + 1,592, 1,593, 1,594, 1,595, 1,596, 1,597, 1,598, 1,599, + 1,600, 1,601, 1,602, 1,603, 1,604, 1,605, 1,606, 1,607, + 1,608, 1,609, 1,610, 1,611, 1,612, 1,613, 1,614, 1,615, + 1,616, 1,617, 1,618, 1,619,0 }; static const unsigned char ag_key_ch[] = { - 0, 76, 78,255, 68, 78,255, 70, 78,255, 68, 69, 73, 80, 85,255, 42, 47, - 255, 67, 68, 73,255, 65, 73,255, 69, 72,255, 67, 68, 78, 83,255, 65, 67, + 0, 42, 47,255, 85,255, 76,255, 67,255, 78,255, 35, 36, 38, 47, 73,255, + 61,255, 61,255, 42, 47, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, 62, + 255, 67, 68, 73,255, 65, 68, 73,255, 69, 72,255, 67, 68, 78, 82, 83,255, + 67, 76, 89,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 69, + 77, 78, 80, 83, 90,255, 65, 68,255, 82, 88,255, 68,255, 69,255, 78,255, + 73,255, 70, 72, 83,255, 69, 85,255, 65, 66, 67, 69, 73, 83, 87,255, 73, + 83,255, 73,255, 68,255, 85,255, 69, 82,255, 84,255, 67, 73, 76, 78, 81, + 82, 88,255, 73, 76, 80,255, 69, 84,255, 77, 84,255, 69, 73, 76,255, 68, + 78,255, 85,255, 76,255, 67, 80, 82, 88,255, 70, 78, 80,255, 80,255, 53, + 255, 67, 68, 75, 88, 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, + 77, 78, 80, 84, 88, 90,255, 88,255, 72, 83,255, 65, 69, 72,255, 69,255, + 68, 73, 88,255, 76,255, 78, 83,255, 71, 87,255, 68, 69, 72, 73, 78, 79, + 83, 84, 88,255, 85,255, 68, 86,255, 65, 79, 83, 86,255, 65,255, 80, 84, + 255, 65, 69, 79,255, 65, 71, 73,255, 82, 85,255, 65, 73,255, 66, 83,255, + 65, 67, 79, 82, 83, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, 79, + 255, 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, + 83, 90,255, 66, 73,255, 69,255, 68, 73, 82, 88,255, 76, 82,255, 72,255, + 88,255, 65, 67, 75,255, 66, 73,255, 66, 69, 72, 73, 80, 81, 84, 85, 89, + 255, 69, 73,255, 65, 73,255, 67, 79, 82, 84,255, 33, 35, 36, 38, 39, 40, + 42, 44, 47, 60, 61, 62, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, + 78, 79, 80, 82, 83, 84, 85, 87, 88, 92,255, 42, 47,255, 35, 36, 38, 47, + 255, 73, 83,255, 76, 78, 82,255, 68, 78,255, 70, 78,255, 68, 69, 73, 80, + 85,255, 42, 47,255, 38, 42, 47, 58,255, 61,255, 42, 47,255, 67, 68, 73, + 255, 65, 73,255, 69, 72,255, 67, 68, 78, 82, 83,255, 76, 89,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 83, 90,255, 65, - 68,255, 82, 88,255, 69, 85,255, 65, 66, 67, 73, 83, 87,255, 73,255, 68, - 255, 69, 82,255, 84,255, 73, 76, 78, 88,255, 67, 82, 88,255, 70, 78,255, - 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, - 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 72, 73, 88,255, - 65, 79, 86,255, 65, 79,255, 65, 71, 73,255, 82, 85,255, 66, 83,255, 65, - 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, 79,255, 65, 67, - 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, 68, 88,255, 76,255, - 88,255, 65, 67, 75,255, 66, 73,255, 66, 72, 73, 80, 84, 85, 89,255, 65, - 73,255, 67, 82, 84,255, 35, 36, 47, 65, 67, 68, 69, 72, 73, 74, 76, 77, - 78, 79, 80, 82, 83, 84, 88,255, 76, 78,255, 68, 78,255, 70, 78,255, 68, - 69, 73, 80, 85,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 67, 68, - 73,255, 65, 68, 73,255, 69, 72,255, 67, 68, 78, 83,255, 65, 67, 80,255, - 67, 90,255, 69, 73, 79,255, 65, 67, 69, 77, 78, 80, 83, 90,255, 65, 68, - 255, 82, 88,255, 69, 85,255, 65, 66, 67, 73, 83, 87,255, 73,255, 68,255, - 85,255, 69, 82,255, 84,255, 73, 76, 78, 81, 88,255, 76, 80,255, 69, 84, - 255, 69, 76,255, 67, 82, 88,255, 70, 78, 80,255, 80,255, 67, 68, 88, 90, - 255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, 88,255, 72, 83,255, 65, - 69,255, 68, 88,255, 76,255, 78, 83,255, 68, 69, 72, 73, 78, 79, 84, 88, - 255, 68, 86,255, 65, 79, 86,255, 80, 84,255, 65, 69, 79,255, 65, 71, 73, - 255, 82, 85,255, 66, 83,255, 65, 67, 79, 83, 85,255, 76, 82,255, 67, 68, - 255, 67, 90,255, 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90, - 255, 66, 73,255, 68, 88,255, 76, 82,255, 72,255, 88,255, 65, 67, 75,255, - 66, 73,255, 66, 69, 72, 73, 80, 81, 84, 85, 89,255, 65, 73,255, 67, 79, - 82, 84,255, 33, 35, 36, 39, 42, 44, 47, 60, 61, 62, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, 88,255, 42,255, 76, - 78,255, 68, 78,255, 70, 78,255, 68, 69, 73, 80, 85,255, 42, 47,255, 60, - 61,255, 61,255, 61, 62,255, 67, 68, 73,255, 65, 68, 73,255, 69, 72,255, - 67, 68, 78, 83,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, - 69, 77, 78, 80, 83, 90,255, 65, 68,255, 82, 88,255, 69, 85,255, 65, 66, - 67, 73, 83, 87,255, 73,255, 68,255, 69, 82,255, 84,255, 73, 76, 78, 81, - 88,255, 76, 80,255, 69, 84,255, 76,255, 67, 82, 88,255, 70, 78, 80,255, - 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, - 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 69, 72, 73, 78, - 79, 84, 88,255, 68, 86,255, 65, 79, 86,255, 80, 84,255, 65, 69, 79,255, - 65, 71, 73,255, 82, 85,255, 66, 83,255, 65, 67, 79, 83, 85,255, 76, 82, - 255, 67, 68,255, 67, 90,255, 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, - 82, 83, 90,255, 66, 73,255, 68, 88,255, 76, 82,255, 72,255, 88,255, 65, - 67, 75,255, 66, 73,255, 66, 72, 73, 80, 81, 84, 85, 89,255, 65, 73,255, - 67, 79, 82, 84,255, 33, 35, 36, 39, 42, 44, 47, 60, 61, 62, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, 88,255, 76, - 80,255, 78, 79,255, 36, 39, 47, 67, 70, 73, 76, 78, 83,255, 47,255, 47, - 58,255, 36, 47,255, 42, 47,255, 47,255, 47, 72, 76,255, 42, 47,255, 67, - 68, 73,255, 65, 73,255, 69, 72,255, 67, 68, 78, 83,255, 65, 67, 80,255, + 68,255, 82, 88,255, 72, 83,255, 69, 85,255, 65, 66, 67, 69, 73, 83, 87, + 255, 73,255, 68,255, 69, 82,255, 84,255, 67, 73, 76, 78, 81, 88,255, 77, + 84,255, 69, 76,255, 82, 88,255, 70, 78,255, 80,255, 53,255, 67, 68, 75, + 88, 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, + 88, 90,255, 88,255, 72, 83,255, 65, 69, 72,255, 69,255, 68, 73, 88,255, + 76,255, 78, 83,255, 68, 72, 73, 83, 88,255, 68, 86,255, 65, 79, 83, 86, + 255, 65,255, 80,255, 65, 79,255, 65, 71, 73,255, 82, 85,255, 66, 83,255, + 65, 67, 79, 82, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, 79,255, + 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, + 90,255, 66, 73,255, 69,255, 68, 73, 82, 88,255, 76,255, 88,255, 65, 67, + 75,255, 66, 73,255, 66, 69, 72, 73, 80, 84, 85, 89,255, 69, 73,255, 65, + 73,255, 67, 82, 84,255, 36, 38, 42, 47, 65, 66, 67, 68, 69, 70, 72, 73, + 74, 76, 77, 78, 79, 80, 82, 83, 84, 87, 88,255, 42, 47,255, 85,255, 76, + 255, 67,255, 78,255, 47, 73,255, 61,255, 42, 47,255, 67, 68, 73,255, 65, + 73,255, 69, 72,255, 67, 68, 78, 82, 83,255, 76, 89,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 83, 90,255, 65, 68,255, - 82, 88,255, 69, 85,255, 65, 66, 67, 73, 83, 87,255, 73,255, 68,255, 69, - 82,255, 84,255, 73, 76, 78, 81, 88,255, 82, 88,255, 70, 78,255, 80,255, - 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, 88,255, - 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 72, 73, 88,255, 65, 79, - 86,255, 65, 79,255, 65, 71, 73,255, 82, 85,255, 66, 83,255, 65, 67, 79, - 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, 79,255, 65, 67, 69, 73, - 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, 68, 88,255, 76,255, 88,255, - 65, 67, 75,255, 66, 73,255, 66, 69, 72, 73, 80, 84, 85, 89,255, 65, 73, - 255, 67, 82, 84,255, 47, 65, 67, 68, 69, 72, 73, 74, 76, 77, 78, 79, 80, - 82, 83, 84, 88,255, 67, 68, 73,255, 65, 73,255, 69, 72,255, 67, 68, 78, - 83,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, - 83, 90,255, 65, 68,255, 82, 88,255, 69, 85,255, 65, 66, 67, 73, 83, 87, - 255, 73,255, 68,255, 69, 82,255, 84,255, 73, 76, 78, 88,255, 82, 88,255, - 70, 78,255, 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, - 88, 90,255, 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 72, - 73, 88,255, 65, 79, 86,255, 65, 79,255, 65, 71, 73,255, 82, 85,255, 66, - 83,255, 65, 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, 79, - 255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, 68, 88, - 255, 76,255, 88,255, 65, 67, 75,255, 66, 73,255, 66, 72, 73, 80, 84, 85, - 89,255, 65, 73,255, 67, 82, 84,255, 65, 67, 68, 69, 72, 73, 74, 76, 77, - 78, 79, 80, 82, 83, 84, 88,255, 66, 83, 87,255, 68, 69, 83,255, 36,255, - 72, 76,255, 67, 68, 73,255, 65, 73,255, 69, 72,255, 67, 68, 78, 83,255, - 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 83, 90, - 255, 65, 68,255, 82, 88,255, 69, 85,255, 65, 66, 67, 73, 83, 87,255, 73, - 255, 68,255, 69, 82,255, 84,255, 73, 76, 78, 81, 88,255, 82, 88,255, 70, - 78,255, 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, - 90,255, 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 72, 73, - 88,255, 65, 79, 86,255, 65, 79,255, 65, 71, 73,255, 82, 85,255, 66, 83, - 255, 65, 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, 79,255, - 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, 68, 88,255, - 76,255, 88,255, 65, 67, 75,255, 66, 73,255, 66, 69, 72, 73, 80, 84, 85, - 89,255, 65, 73,255, 67, 82, 84,255, 47, 65, 67, 68, 69, 72, 73, 74, 76, - 77, 78, 79, 80, 82, 83, 84, 88,255, 47,255, 76, 80,255, 78, 79,255, 36, - 39, 47, 67, 70, 73, 76, 83,255, 42, 47,255, 67, 68, 73,255, 65, 73,255, - 67, 68, 78, 83,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, - 77, 78, 80, 90,255, 65, 68,255, 82, 88,255, 65, 67, 73, 83,255, 82, 88, - 255, 78,255, 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, - 88, 90,255, 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 72, - 88,255, 79, 86,255, 65, 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, - 67, 68,255, 67, 90,255, 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, - 83, 90,255, 66, 73,255, 68, 88,255, 76,255, 88,255, 65, 67,255, 66, 73, - 255, 66, 72, 73, 80, 84, 85,255, 65, 73,255, 67, 82, 84,255, 47, 65, 67, - 68, 69, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 42, 47,255, 60, - 61,255, 61,255, 61, 62,255, 67, 68, 73,255, 65, 68, 73,255, 67, 68, 78, - 83,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, - 90,255, 65, 68,255, 82, 88,255, 65, 67, 73, 83,255, 73, 81,255, 69, 84, - 255, 82, 88,255, 78,255, 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, - 77, 78, 80, 88, 90,255, 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76, - 255, 68, 69, 72, 84, 88,255, 68, 86,255, 79, 86,255, 69, 79,255, 65, 73, - 255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, - 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, 68, - 88,255, 76, 82,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, 73, 80, 84, - 85,255, 65, 73,255, 67, 79, 82, 84,255, 33, 42, 44, 47, 60, 61, 62, 65, - 67, 68, 69, 71, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 42, 47, - 255, 67, 68, 73,255, 65, 73,255, 67, 68, 78, 83,255, 65, 67, 80,255, 67, - 90,255, 69, 73, 79,255, 65, 67, 69, 77, 78, 80, 90,255, 65, 68,255, 82, - 88,255, 65, 67, 73, 83,255, 76, 80,255, 82, 88,255, 78, 80,255, 80,255, - 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, 88,255, - 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 72, 78, 79, 88,255, 79, - 86,255, 65, 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 67, 68,255, - 67, 90,255, 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, - 66, 73,255, 68, 88,255, 76,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, - 73, 80, 81, 84, 85,255, 65, 73,255, 67, 82, 84,255, 36, 39, 47, 65, 67, - 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 47, 65, 66, - 67, 68, 69, 72, 76, 77,255, 47, 66, 68,255, 47, 65, 66, 68, 72, 80,255, - 47, 66, 68, 72, 83,255, 76, 80,255, 78, 79,255, 36, 39, 67, 70, 73, 76, - 78, 83,255, 65, 66, 67, 68, 69, 72, 76, 77,255, 66, 68,255, 65, 66, 68, - 72, 80,255, 66, 68, 72, 83,255, 67, 68, 73,255, 65, 73,255, 67, 68, 78, - 83,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, - 90,255, 65, 68,255, 82, 88,255, 65, 67, 73, 83,255, 82, 88,255, 78,255, - 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, - 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 72, 88,255, 79, - 86,255, 65, 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 67, 68,255, - 67, 90,255, 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, - 66, 73,255, 68, 88,255, 76,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, - 73, 80, 84, 85,255, 65, 73,255, 67, 82, 84,255, 47, 65, 67, 68, 69, 72, - 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 42, 47,255, 36, 47,255, 36, - 47,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 33, 42, 44, 47, 60, - 61, 62,255, 42, 47,255, 44, 47,255, 39,255, 39,255, 42, 47,255, 60, 61, - 255, 61,255, 61, 62,255, 67, 68, 73,255, 65, 68, 73,255, 67, 68, 78, 83, - 255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 90, - 255, 65, 68,255, 82, 88,255, 65, 67, 73, 83,255, 73, 81,255, 69, 84,255, - 76,255, 82, 88,255, 78,255, 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, - 68, 77, 78, 80, 88, 90,255, 88,255, 72, 83,255, 65, 69,255, 68, 88,255, - 76,255, 68, 69, 72, 84, 88,255, 68, 86,255, 79, 86,255, 69, 79,255, 65, - 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, - 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, - 68, 88,255, 76, 82,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, 73, 80, - 84, 85,255, 65, 73,255, 67, 79, 82, 84,255, 33, 42, 44, 47, 60, 61, 62, - 65, 66, 67, 68, 69, 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 83, 88, - 255, 72,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 76, - 255, 82, 88,255, 78,255, 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, - 77, 78, 80, 88, 90,255, 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76, - 255, 68, 69, 72, 84, 88,255, 68, 86,255, 79, 86,255, 69, 79,255, 65, 73, - 255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, - 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, 68, - 88,255, 76, 82,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, 73, 80, 84, - 85,255, 65, 73,255, 67, 79, 82, 84,255, 33, 42, 44, 47, 60, 61, 62, 66, - 68, 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 83, 88,255, 76, 80,255, - 78, 79,255, 36, 39, 67, 70, 73, 76, 83,255, 60, 61,255, 61,255, 61, 62, - 255, 67, 68, 73,255, 65, 68, 73,255, 67, 68, 78, 83,255, 65, 67, 80,255, - 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 90,255, 65, 68,255, 82, - 88,255, 65, 67, 73, 83,255, 73, 81,255, 69, 84,255, 82, 88,255, 78,255, - 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, - 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 69, 72, 84, 88, - 255, 68, 86,255, 79, 86,255, 69, 79,255, 65, 73,255, 82, 85,255, 67, 79, - 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, 79,255, 65, 67, 69, 73, - 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, 68, 88,255, 76, 82,255, 88, - 255, 65, 67,255, 66, 73,255, 66, 72, 73, 80, 84, 85,255, 65, 73,255, 67, - 79, 82, 84,255, 33, 42, 44, 47, 60, 61, 62, 65, 67, 68, 69, 71, 72, 73, - 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 60, 61,255, 61,255, 61, 62,255, - 67, 68, 73,255, 65, 68, 73,255, 67, 68, 78, 83,255, 65, 67, 80,255, 67, - 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 90,255, 65, 68,255, 82, 88, - 255, 65, 67, 73, 83,255, 73, 81,255, 69, 84,255, 82, 88,255, 78,255, 80, - 255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, 88, - 255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 69, 72, 84, 88,255, - 79, 86,255, 69, 79,255, 65, 73,255, 82, 85,255, 67, 79, 85,255, 76, 82, - 255, 67, 68,255, 67, 90,255, 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, - 82, 83, 90,255, 66, 73,255, 68, 88,255, 76, 82,255, 88,255, 65, 67,255, - 66, 73,255, 66, 72, 73, 80, 84, 85,255, 65, 73,255, 67, 79, 82, 84,255, - 33, 44, 47, 60, 61, 62, 65, 67, 68, 69, 71, 72, 73, 74, 76, 77, 78, 79, - 80, 82, 83, 88,255, 61,255, 61,255, 61,255, 67, 68, 73,255, 65, 68, 73, - 255, 67, 68, 78, 83,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, - 67, 77, 78, 80, 90,255, 65, 68,255, 82, 88,255, 65, 67, 73, 83,255, 73, - 81,255, 69, 84,255, 82, 88,255, 78,255, 80,255, 67, 68, 88, 90,255, 69, - 79,255, 67, 68, 77, 78, 80, 88, 90,255, 88,255, 72, 83,255, 65, 69,255, - 68, 88,255, 76,255, 68, 69, 72, 84, 88,255, 79, 86,255, 69, 79,255, 65, - 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, - 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, - 68, 88,255, 76,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, 73, 80, 84, - 85,255, 65, 73,255, 67, 79, 82, 84,255, 33, 44, 47, 60, 61, 62, 65, 67, - 68, 69, 71, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 61,255, 61, - 255, 61,255, 67, 68, 73,255, 65, 73,255, 67, 68, 78, 83,255, 65, 67, 80, - 255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 90,255, 65, 68,255, - 82, 88,255, 65, 67, 73, 83,255, 73, 81,255, 69, 84,255, 82, 88,255, 78, - 255, 80,255, 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90, - 255, 88,255, 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 69, 72, 84, - 88,255, 79, 86,255, 69, 79,255, 65, 73,255, 82, 85,255, 67, 79, 85,255, - 76, 82,255, 67, 68,255, 67, 90,255, 69, 79,255, 65, 67, 69, 73, 76, 77, - 78, 80, 82, 83, 90,255, 66, 73,255, 68, 88,255, 76,255, 88,255, 65, 67, - 255, 66, 73,255, 66, 72, 73, 80, 84, 85,255, 65, 73,255, 67, 79, 82, 84, - 255, 33, 44, 47, 60, 61, 62, 65, 67, 68, 69, 71, 72, 73, 74, 76, 77, 78, - 79, 80, 82, 83, 88,255, 61,255, 61,255, 61,255, 67, 68, 73,255, 65, 73, - 255, 67, 68, 78, 83,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, - 67, 77, 78, 80, 90,255, 65, 68,255, 82, 88,255, 65, 67, 73, 83,255, 73, - 81,255, 69, 84,255, 82, 88,255, 78,255, 80,255, 67, 68, 88, 90,255, 69, - 79,255, 67, 68, 77, 78, 80, 88, 90,255, 88,255, 72, 83,255, 65, 69,255, - 68, 88,255, 76,255, 68, 69, 72, 84, 88,255, 79, 86,255, 69, 79,255, 65, - 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, - 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, - 68, 88,255, 76,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, 73, 80, 84, - 85,255, 65, 73,255, 67, 82, 84,255, 33, 44, 47, 60, 61, 62, 65, 67, 68, - 69, 71, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 61,255, 61,255, - 61,255, 69, 84,255, 69, 84,255, 33, 47, 60, 61, 62, 69, 71, 76, 78,255, - 44, 47,255, 42, 47,255, 67, 68, 73,255, 65, 73,255, 67, 68, 78, 83,255, - 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 90,255, - 65, 68,255, 82, 88,255, 65, 67, 73, 83,255, 82, 88,255, 78,255, 80,255, - 67, 68, 88, 90,255, 69, 79,255, 67, 68, 77, 78, 80, 88, 90,255, 88,255, - 72, 83,255, 65, 69,255, 68, 88,255, 76,255, 68, 72, 88,255, 79, 86,255, - 65, 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 67, 68,255, 67, 90, - 255, 69, 79,255, 65, 67, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73, - 255, 68, 88,255, 76,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, 73, 80, - 84, 85,255, 65, 73,255, 67, 82, 84,255, 44, 47, 65, 67, 68, 69, 72, 73, - 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 44,255, 42, 47,255, 47, 66, 68, - 72, 81,255, 69,255, 76, 80,255, 78, 79,255, 36, 39, 47, 65, 66, 67, 68, - 69, 70, 72, 73, 76, 77, 78, 83,255 + 82, 88,255, 72, 83,255, 69, 85,255, 65, 66, 67, 69, 73, 83, 87,255, 73, + 255, 68,255, 69, 82,255, 84,255, 67, 73, 76, 78, 88,255, 77, 84,255, 69, + 76,255, 85,255, 76,255, 67, 82, 88,255, 70, 78,255, 80,255, 53,255, 67, + 68, 75, 88, 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, + 80, 84, 88, 90,255, 88,255, 72, 83,255, 65, 69, 72,255, 69,255, 68, 73, + 88,255, 76,255, 78, 83,255, 68, 72, 73, 83, 88,255, 68, 86,255, 65, 79, + 83, 86,255, 65,255, 80,255, 65, 79,255, 65, 71, 73,255, 82, 85,255, 66, + 83,255, 65, 67, 79, 82, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, + 79,255, 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, + 82, 83, 90,255, 66, 73,255, 69,255, 68, 73, 82, 88,255, 76,255, 88,255, + 65, 67, 75,255, 66, 73,255, 66, 72, 73, 80, 84, 85, 89,255, 69, 73,255, + 65, 73,255, 67, 82, 84,255, 36, 38, 42, 47, 65, 66, 67, 68, 69, 70, 72, + 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, 87, 88,255, 36, 38,255, 42, 47, + 255, 47,255, 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, 67, 68, 70, + 72, 73, 76, 78, 83,255, 72, 76,255, 42, 47,255, 85,255, 76,255, 67,255, + 78,255, 35, 36, 38, 42, 47, 73,255, 47, 61,255, 42, 47,255, 76, 89,255, + 69,255, 66, 83, 87,255, 69, 82,255, 84,255, 67, 78, 81, 88,255, 85,255, + 76,255, 67,255, 78,255, 78, 83,255, 73, 83,255, 65, 79, 83,255, 65, 79, + 255, 65, 82, 85,255, 69, 84, 89,255, 69, 73,255, 36, 42, 47, 65, 66, 67, + 68, 69, 70, 72, 73, 76, 77, 78, 79, 80, 83, 84, 87, 92,255, 85,255, 76, + 255, 67,255, 78,255, 73,255, 42, 47,255, 42, 47,255, 42, 47, 92,255, 42, + 47,255, 47, 73, 80,255, 42, 47,255, 33, 47,255, 40, 65, 66, 67, 68, 69, + 72, 76, 77,255, 67,255, 69,255, 76,255, 66, 68, 72, 83,255, 67,255, 69, + 255, 76,255, 65, 66, 68, 72, 80,255, 67,255, 69,255, 66, 68,255, 61,255, + 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 33, 42, 44, 47, 60, 61, 62, + 255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, + 84,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 65, 69, 71, 76, + 77, 78, 79, 83, 88,255, 76, 89,255, 69,255, 66, 83, 87,255, 69, 82,255, + 84,255, 67, 78, 88,255, 78, 83,255, 73, 83,255, 65, 79, 83,255, 65, 79, + 255, 65, 82, 85,255, 84, 89,255, 69, 73,255, 36, 42, 65, 66, 67, 68, 69, + 70, 72, 76, 77, 78, 79, 80, 83, 84, 87,255, 42, 47,255, 44, 47,255, 61, + 255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, + 82,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 65, 69, 71, 76, + 77, 78, 79, 81, 83, 88,255, 39,255, 61,255, 42, 47,255, 60, 61,255, 61, + 255, 61, 62,255, 69, 84,255, 69, 84,255, 82,255, 76, 82,255, 72,255, 33, + 42, 44, 47, 60, 61, 62, 71, 76, 77, 78, 79, 81, 83, 88,255, 42, 47,255, + 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, 42, 47, 67, 68, 70, 72, + 73, 76, 78, 83, 92,255, 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, + 67, 68, 70, 72, 73, 76, 83,255, 42, 47,255, 76, 80,255, 71, 87,255, 78, + 79,255, 36, 38, 39, 42, 47, 67, 68, 70, 72, 73, 76, 83, 92,255, 61,255, + 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72, + 255, 33, 42, 44, 60, 61, 62, 65, 69, 71, 76, 77, 78, 79, 83, 88,255, 61, + 255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, + 76, 82,255, 72,255, 33, 44, 47, 60, 61, 62, 65, 69, 71, 76, 78, 79, 83, + 88,255, 61,255, 42, 47,255, 61,255, 61,255, 61,255, 69, 84,255, 69, 84, + 255, 33, 44, 47, 60, 61, 62, 65, 69, 71, 76, 78, 79, 88,255, 61,255, 42, + 47,255, 61,255, 61,255, 61,255, 69, 84,255, 69, 84,255, 33, 44, 47, 60, + 61, 62, 69, 71, 76, 78, 79, 88,255, 61,255, 42, 47,255, 61,255, 61,255, + 61,255, 69, 84,255, 69, 84,255, 33, 44, 47, 60, 61, 62, 69, 71, 76, 78, + 79,255, 42, 47,255, 61,255, 61,255, 61,255, 69, 84,255, 69, 84,255, 33, + 47, 60, 61, 62, 69, 71, 76, 78,255, 61,255, 42, 47,255, 42, 47,255, 60, + 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, + 33, 42, 44, 47, 60, 61, 62, 65, 69, 71, 76, 77, 78, 79, 83, 88, 92,255, + 76, 89,255, 69,255, 66, 83, 87,255, 69, 82,255, 84,255, 67, 78, 81, 88, + 255, 78, 83,255, 73, 83,255, 65, 79, 83,255, 65, 79,255, 65, 82, 85,255, + 69, 84, 89,255, 69, 73,255, 36, 42, 65, 66, 67, 68, 69, 70, 72, 76, 77, + 78, 79, 80, 83, 84, 87,255, 39,255, 67, 68, 73,255, 65, 73,255, 67, 68, + 78, 82, 83,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, + 78, 80, 90,255, 65, 68,255, 82, 88,255, 72, 83,255, 65, 67, 69, 73, 83, + 255, 77, 84,255, 76,255, 82, 88,255, 78,255, 80,255, 53,255, 67, 68, 75, + 88, 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, + 88, 90,255, 88,255, 72, 83,255, 65, 69, 72,255, 69,255, 68, 73, 88,255, + 76,255, 68, 72, 88,255, 79, 86,255, 65, 73,255, 82, 85,255, 67, 79, 85, + 255, 76, 82,255, 67, 68,255, 67, 90,255, 69, 79,255, 67, 72,255, 86,255, + 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, + 69,255, 68, 73, 82, 88,255, 76,255, 88,255, 65, 67,255, 66, 73,255, 66, + 72, 73, 80, 84, 85,255, 65, 73,255, 67, 82, 84,255, 65, 67, 68, 69, 72, + 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 42, 47,255, 36, 38, 47,255, + 42, 47,255, 33, 44, 47,255, 44,255, 42, 47,255, 47, 79, 81,255, 92,255, + 69,255, 69,255, 76, 80,255, 73,255, 71, 87,255, 78, 79,255, 36, 38, 39, + 40, 65, 66, 67, 68, 69, 70, 72, 73, 76, 77, 78, 83,255, 33,255, 42, 47, + 255, 47, 92,255 }; static const unsigned char ag_key_act[] = { - 0,3,3,4,3,3,4,2,3,4,3,2,2,3,3,4,0,0,4,5,5,5,4,5,5,4,7,7,4,7,2,2,2,4,5, - 5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5,4,5,5,4,5,5,4,7,7,4,2,5,2,5,6,5,4,7, - 4,6,4,7,7,4,2,4,5,7,2,2,4,7,5,5,4,5,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6, - 5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,2,7,7,4,7,7,7,4,7,7,4,5,5,5,4,2,7,4, - 7,7,4,7,7,7,2,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4, - 5,5,4,2,4,5,4,6,5,7,4,5,5,4,2,2,7,7,2,2,7,4,5,5,4,7,2,7,4,2,5,2,2,2,2, - 2,7,2,2,2,2,2,2,2,2,2,7,2,4,3,3,4,3,3,4,2,3,4,3,2,2,3,3,4,0,0,4,0,0,4, - 0,4,0,0,4,5,5,5,4,5,5,5,4,7,7,4,7,2,2,2,4,5,5,5,4,5,5,4,5,5,5,4,7,5,7, - 6,2,6,7,5,4,5,5,4,5,5,4,7,7,4,2,5,2,5,6,5,4,7,4,6,4,5,4,7,7,4,2,4,5,7, - 2,6,2,4,7,5,4,5,5,4,7,7,4,7,5,5,4,5,6,5,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2, - 6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,7,7,4,2,5,2,2,5,7,5,7,4,5,5,4,7,2,7, - 4,5,5,4,7,5,2,4,5,5,5,4,6,7,4,7,7,4,7,7,7,7,2,4,5,5,4,5,7,4,5,5,4,5,5, - 4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,6,5,4,7,4,5,4,6,5,7,4,5,5,4,2,7, - 2,7,6,7,2,2,7,4,5,5,4,7,7,2,7,4,3,2,5,3,3,0,2,1,1,1,6,5,6,6,6,2,2,6,2, - 2,6,6,2,2,2,2,2,7,2,4,3,4,3,3,4,3,3,4,2,3,4,3,2,2,3,3,4,0,0,4,0,0,4,0, - 4,0,0,4,5,5,5,4,5,5,5,4,7,7,4,7,2,2,2,4,5,5,5,4,5,5,4,5,5,5,4,7,5,7,6, - 2,6,7,5,4,5,5,4,5,5,4,7,7,4,2,5,2,5,6,5,4,7,4,6,4,7,7,4,2,4,5,7,2,5,2, - 4,7,5,4,5,5,4,7,4,7,5,5,4,5,6,5,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4, - 5,4,5,5,4,6,2,4,5,5,4,2,4,2,5,2,7,5,7,5,7,4,5,5,4,7,2,7,4,5,5,4,7,5,2, - 4,5,5,5,4,6,7,4,7,7,4,7,7,7,7,2,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7,2,5, - 2,6,7,7,5,4,5,5,4,5,5,4,6,5,4,7,4,5,4,6,5,7,4,5,5,4,2,2,7,6,7,2,2,7,4, - 5,5,4,7,7,2,7,4,3,2,5,3,3,0,2,1,1,1,6,5,6,6,6,2,2,6,2,2,6,6,2,2,2,2,2, - 7,2,4,7,5,4,5,7,4,5,3,3,7,2,7,2,7,7,4,3,4,3,0,4,5,3,4,0,0,4,2,4,3,7,7, - 4,0,0,4,5,5,5,4,5,5,4,7,7,4,7,2,2,2,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6, - 7,5,4,5,5,4,5,5,4,7,7,4,2,5,2,5,6,5,4,7,4,6,4,7,7,4,2,4,5,7,2,7,2,4,5, - 5,4,5,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2, - 4,2,2,7,7,4,7,7,7,4,7,7,4,5,5,5,4,2,7,4,7,7,4,7,7,7,2,4,5,5,4,5,7,4,5, - 5,4,5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,2,4,5,4,6,5,7,4,5,5,4,2, - 7,2,7,7,2,2,7,4,5,5,4,7,2,7,4,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,7,2,4,5,5, - 5,4,5,5,4,7,7,4,7,2,2,2,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5,4,5,5,4, - 5,5,4,7,7,4,2,5,2,5,6,5,4,7,4,6,4,7,7,4,2,4,5,7,2,2,4,5,5,4,5,6,4,5,4, - 5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,2,7,7,4,7, - 7,7,4,7,7,4,5,5,5,4,2,7,4,7,7,4,7,7,7,2,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5, - 7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,2,4,5,4,6,5,7,4,5,5,4,2,2,7,7,2,2,7,4, - 5,5,4,7,2,7,4,2,2,2,2,7,2,2,2,2,2,2,2,2,2,7,2,4,5,5,5,4,2,7,7,4,5,4,7, - 7,4,5,5,5,4,5,5,4,7,7,4,7,2,2,2,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5, - 4,5,5,4,5,5,4,7,7,4,2,5,2,5,6,5,4,7,4,6,4,7,7,4,2,4,5,7,2,7,2,4,5,5,4, - 5,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2, - 2,7,7,4,7,7,7,4,7,7,4,5,5,5,4,2,7,4,7,7,4,7,7,7,2,4,5,5,4,5,7,4,5,5,4, - 5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,2,4,5,4,6,5,7,4,5,5,4,2,7,2, - 7,7,2,2,7,4,5,5,4,7,2,7,4,3,2,2,2,2,7,2,2,2,2,2,2,2,2,2,7,2,4,3,4,7,5, - 4,5,7,4,5,3,3,7,2,7,2,7,4,0,0,4,5,5,5,4,5,5,4,7,2,2,7,4,5,5,5,4,5,5,4, - 5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,2,2,5,7,4,5,5,4,6,4,5,4,5,5,5,5,4,5, - 5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,2,7,4,7,7,4,5,5,4,2,7, - 4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4, - 2,4,5,4,6,5,4,5,5,4,2,2,7,7,2,2,4,5,5,4,7,2,7,4,2,2,2,2,7,7,2,2,2,2,7, - 2,2,2,2,2,4,0,0,4,0,0,4,0,4,0,0,4,5,5,5,4,5,5,5,4,7,2,2,7,4,5,5,5,4,5, - 5,4,5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,2,2,5,7,4,5,5,4,5,5,4,5,5,4,6,4, - 5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,5,2,5, - 7,4,5,5,4,2,7,4,5,7,4,5,5,4,6,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5, - 7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,6,5,4,5,4,6,5,4,5,5,4,2,2,7,7,2,2,4,5, - 5,4,7,7,2,7,4,3,3,0,2,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,4,0,0,4,5, - 5,5,4,5,5,4,7,2,2,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5,7,6,2,6,5,4,5,5,4,5,5, - 4,2,2,5,7,4,7,5,4,5,5,4,6,5,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4, - 5,5,4,6,2,4,5,5,4,2,4,2,2,5,7,7,4,7,7,4,5,5,4,2,7,4,7,7,7,4,5,5,4,5,7, - 4,5,5,4,5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,2,4,5,4,6,5,4,5,5,4, - 2,2,7,7,7,2,2,4,5,5,4,7,2,7,4,5,3,2,2,2,2,7,2,7,2,2,2,2,7,2,2,2,2,2,4, - 3,5,5,5,5,5,5,5,5,4,3,5,5,4,3,5,5,5,5,7,4,3,5,5,5,7,4,7,5,4,5,7,4,5,3, - 7,2,7,2,7,7,4,5,5,5,5,5,5,5,5,4,5,5,4,5,5,5,5,7,4,5,5,5,7,4,5,5,5,4,5, - 5,4,7,2,2,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,2,2,5,7, - 4,5,5,4,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4, - 2,4,2,2,7,4,7,7,4,5,5,4,2,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7, - 2,5,2,6,7,7,5,4,5,5,4,5,5,4,2,4,5,4,6,5,4,5,5,4,2,2,7,7,2,2,4,5,5,4,7, - 2,7,4,3,2,2,2,7,7,2,2,2,2,7,2,2,2,2,2,4,0,0,4,5,2,4,5,3,4,0,0,4,0,0,4, - 0,4,0,0,4,3,3,0,2,1,1,1,4,0,0,4,0,2,4,3,4,3,4,0,0,4,0,0,4,0,4,0,0,4,5, - 5,5,4,5,5,5,4,7,2,2,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5, - 4,2,2,5,7,4,5,5,4,5,5,4,7,4,5,5,4,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5, - 5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,5,2,5,7,4,5,5,4,2,7,4,5,7,4,5,5,4,6,7, - 4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4, - 6,5,4,5,4,6,5,4,5,5,4,2,2,7,7,2,2,4,5,5,4,7,7,2,7,4,3,3,0,2,1,1,1,2,5, - 2,6,2,2,6,2,2,2,2,2,2,2,5,2,2,2,4,5,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,7,4, - 5,5,4,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2, - 4,2,5,2,5,7,4,5,5,4,2,7,4,5,7,4,5,5,4,6,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4, - 5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,6,5,4,5,4,6,5,4,5,5,4,2,2,7, - 7,2,2,4,5,5,4,7,7,2,7,4,3,3,0,2,1,1,1,5,5,2,6,2,2,2,2,2,2,2,5,2,2,2,4, - 7,5,4,5,7,4,5,3,7,2,7,2,7,4,0,0,4,0,4,0,0,4,5,5,5,4,5,5,5,4,7,2,2,7,4, - 5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,2,2,5,7,4,5,5,4,5,5,4, - 5,5,4,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2, - 4,2,5,2,5,7,4,5,5,4,2,7,4,5,7,4,5,5,4,6,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4, - 5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,6,5,4,5,4,6,5,4,5,5,4,2,2,7, - 7,2,2,4,5,5,4,7,7,2,7,4,3,3,0,3,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2, - 4,0,0,4,0,4,0,0,4,5,5,5,4,5,5,5,4,7,2,2,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5, - 6,2,6,5,4,5,5,4,5,5,4,2,2,5,7,4,5,5,4,5,5,4,5,5,4,6,4,5,4,5,5,5,5,4,5, - 5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,5,2,5,7,4,7,7,4,5,7,4, - 5,5,4,6,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5, - 5,4,5,5,4,6,5,4,5,4,6,5,4,5,5,4,2,2,7,7,2,2,4,5,5,4,7,7,2,7,4,3,0,3,1, - 1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,4,0,4,0,4,0,4,5,5,5,4,5,5,5,4,7,2, - 2,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,2,2,5,7,4,5,5,4, - 5,5,4,5,5,4,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5, - 5,4,2,4,2,5,2,5,7,4,7,7,4,5,7,4,5,5,4,6,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4, - 5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4,2,4,5,4,6,5,4,5,5,4,2,2,7,7, - 2,2,4,5,5,4,7,7,2,7,4,3,0,3,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,4,0, - 4,0,4,0,4,5,5,5,4,5,5,4,7,2,2,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,5,4, - 5,5,4,5,5,4,2,2,5,7,4,5,5,4,5,5,4,5,5,4,6,4,5,4,5,5,5,5,4,5,5,4,5,5,6, - 2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,5,2,5,7,4,7,7,4,5,7,4,5,5,4,6,7, - 4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4,5,5,4, - 2,4,5,4,6,5,4,5,5,4,2,2,7,7,2,2,4,5,5,4,7,7,2,7,4,3,0,3,1,1,1,2,2,2,2, - 2,7,2,2,2,2,2,2,2,2,2,2,4,0,4,0,4,0,4,5,5,5,4,5,5,4,7,2,2,7,4,5,5,5,4, - 5,5,4,5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,2,2,5,7,4,5,5,4,5,5,4,5,5,4,6, - 4,5,4,5,5,5,5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,5,2, - 5,7,4,7,7,4,5,7,4,5,5,4,6,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7, - 2,5,2,6,7,7,5,4,5,5,4,5,5,4,2,4,5,4,6,5,4,5,5,4,2,2,7,7,2,2,4,5,5,4,7, - 2,7,4,3,0,3,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,4,0,4,0,4,0,4,5,5,4, - 5,5,4,3,3,1,1,1,7,2,2,7,4,0,3,4,0,0,4,5,5,5,4,5,5,4,7,2,2,7,4,5,5,5,4, - 5,5,4,5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,2,2,5,7,4,5,5,4,6,4,5,4,5,5,5, - 5,4,5,5,4,5,5,6,2,6,5,5,4,5,4,5,5,4,6,2,4,5,5,4,2,4,2,2,7,4,7,7,4,5,5, - 4,2,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,2,5,7,7,2,5,2,6,7,7,5,4,5,5,4, - 5,5,4,2,4,5,4,6,5,4,5,5,4,2,2,7,7,2,2,4,5,5,4,7,2,7,4,0,2,2,2,2,7,7,2, - 2,2,2,7,2,2,2,2,2,4,0,4,0,0,4,2,5,5,5,5,4,7,4,7,5,4,5,7,4,5,3,3,5,5,6, - 5,5,2,5,7,6,5,7,7,4 + 0,0,0,4,7,4,6,4,2,4,2,4,0,5,0,2,2,4,0,4,0,4,0,0,0,4,0,0,4,0,0,4,0,4,0, + 0,4,5,5,5,4,5,5,5,4,7,7,4,7,2,2,7,2,4,5,7,7,4,5,5,5,4,5,5,4,5,5,5,4,7, + 5,7,6,2,6,7,5,4,5,5,4,5,5,4,5,4,6,4,2,4,2,4,2,7,7,4,7,7,4,2,5,2,6,5,6, + 5,4,7,7,4,7,4,6,4,5,4,7,7,4,2,4,7,5,2,2,6,7,2,4,7,7,5,4,5,5,4,7,5,4,7, + 7,6,4,7,7,4,7,4,6,4,2,7,5,5,4,6,6,5,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4, + 5,4,5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,4,5,4,6,5,5,4,2,4,7,7,4,5,5,4, + 2,5,2,2,5,2,7,5,7,4,7,4,6,5,4,7,2,7,7,4,7,4,6,5,4,7,5,2,4,5,5,5,4,6,7, + 4,7,7,4,7,7,4,7,7,7,2,7,2,4,5,5,4,5,7,4,5,5,4,5,5,4,5,7,4,5,4,6,4,2,5, + 7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,4,6,5,5,5,4,6,5,4,7,4,5,4,6,5,7,4,5,5,4, + 2,7,2,7,6,7,2,2,7,4,7,7,4,5,5,4,7,7,2,7,4,6,0,6,0,3,3,2,0,2,1,1,1,6,6, + 6,6,6,2,2,6,2,2,6,6,2,2,2,2,2,2,7,7,2,3,4,0,0,4,0,5,0,2,4,7,7,4,2,7,7, + 4,7,7,4,6,7,4,7,2,2,7,7,4,0,0,4,0,3,2,0,4,0,4,0,0,4,5,5,5,4,5,5,4,7,7, + 4,7,2,2,7,2,4,7,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5,4,5,5,4,5,5,4, + 7,7,4,7,7,4,2,5,2,2,5,6,5,4,7,4,6,4,7,7,4,2,4,7,5,7,2,7,2,4,7,5,4,7,2, + 4,5,5,4,5,6,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5,4, + 5,4,5,5,4,6,2,7,4,5,4,6,5,5,4,2,4,7,7,4,2,2,2,7,7,4,7,5,4,7,2,7,7,4,7, + 4,6,4,7,2,4,5,5,5,4,2,7,4,7,7,4,7,7,7,7,2,4,5,5,4,5,7,4,5,5,4,5,5,4,5, + 7,4,5,4,6,4,2,5,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,4,6,5,5,5,4,2,4,5,4,6,5, + 7,4,5,5,4,2,7,2,7,7,2,2,7,4,7,7,4,5,5,4,7,2,7,4,6,0,3,2,2,2,2,2,2,7,2, + 2,2,2,2,2,2,2,2,2,2,7,2,4,0,0,4,7,4,6,4,2,4,2,4,2,2,4,0,4,0,0,4,5,5,5, + 4,5,5,4,7,7,4,7,2,2,7,2,4,7,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5,4, + 5,5,4,5,5,4,7,7,4,7,7,4,2,5,2,2,5,6,5,4,7,4,6,4,7,7,4,2,4,7,5,7,2,2,4, + 7,5,4,7,2,4,7,4,6,4,2,5,5,4,5,6,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4, + 5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,4,5,4,6,5,5,4,2,4,7,7,4,2,2,2,7,7, + 4,7,5,4,7,2,7,7,4,7,4,6,4,7,2,4,5,5,5,4,2,7,4,7,7,4,7,7,7,7,2,4,5,5,4, + 5,7,4,5,5,4,5,5,4,5,7,4,5,4,6,4,2,5,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,4,6, + 5,5,5,4,2,4,5,4,6,5,7,4,5,5,4,2,2,7,7,2,2,7,4,7,7,4,5,5,4,7,2,7,4,6,0, + 3,2,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,7,2,4,5,0,4,0,0,4,2,4,7,5,4,5,5, + 4,5,2,4,5,0,3,7,7,2,7,7,2,7,7,4,7,7,4,0,0,4,7,4,6,4,2,4,2,4,0,5,0,3,2, + 2,4,0,0,4,0,0,4,7,7,4,7,4,5,6,5,4,7,7,4,2,4,7,7,7,2,4,7,4,6,4,2,4,2,4, + 7,7,4,2,7,4,7,7,7,4,7,7,4,7,7,7,4,7,7,7,4,7,7,4,3,2,2,7,2,7,2,2,7,7,2, + 2,2,2,7,2,2,2,7,3,4,7,4,6,4,2,4,2,4,2,4,3,3,4,0,0,4,3,2,3,4,0,0,4,2,7, + 7,4,0,0,4,5,2,4,3,5,5,5,5,5,5,5,5,4,5,4,5,4,5,4,6,6,6,7,4,5,4,5,4,5,4, + 5,6,6,6,7,4,5,4,5,4,6,6,4,0,4,0,0,4,0,0,4,0,4,0,0,4,6,3,0,2,1,1,1,4,0, + 4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,3,0,2,1,1,1,7,7,2,2,7, + 7,7,2,7,4,7,7,4,7,4,5,6,5,4,7,7,4,2,4,7,7,2,4,7,7,4,2,7,4,7,7,7,4,7,7, + 4,7,7,7,4,7,7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2,2,7,2,2,2,7,4,0,0,4,0,2,4, + 0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,4,5,5,4,2,4,6,3,0,2,1,1,1,7,7, + 2,2,7,7,6,5,2,7,4,3,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,4,5,5,4, + 2,4,6,3,0,2,1,1,1,2,2,7,7,6,5,2,7,4,0,0,4,7,5,4,5,5,4,5,2,4,5,0,3,3,2, + 7,7,2,7,7,2,7,7,3,4,7,5,4,5,5,4,5,2,4,5,0,3,7,7,2,7,7,2,7,4,0,0,4,7,5, + 4,5,5,4,5,2,4,5,0,3,3,2,7,7,2,7,7,2,7,3,4,0,4,0,0,4,0,4,0,0,4,5,5,4,5, + 5,4,5,5,4,2,4,6,3,0,1,1,1,7,7,2,2,7,7,7,2,7,4,0,4,0,0,4,0,0,4,0,4,0,0, + 4,5,5,4,5,5,4,5,5,4,2,4,6,0,2,1,1,1,7,7,2,2,7,7,2,7,4,0,4,0,0,4,0,4,0, + 4,0,4,5,5,4,5,5,4,6,0,2,1,1,1,7,7,2,2,7,7,7,4,0,4,0,0,4,0,4,0,4,0,4,5, + 5,4,5,5,4,6,0,2,1,1,1,7,2,2,7,7,7,4,0,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4, + 6,0,2,1,1,1,7,2,2,7,7,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,3,2,1,1,1,7,2,2, + 7,4,0,4,0,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,2,0,2,1,1, + 1,7,7,2,2,7,7,7,2,7,3,4,7,7,4,7,4,5,6,5,4,7,7,4,2,4,7,7,7,2,4,7,7,4,2, + 7,4,7,7,7,4,7,7,4,7,7,7,4,7,7,7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2,2,7,2,2, + 2,7,4,3,4,5,5,5,4,5,5,4,7,2,2,7,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,5, + 4,5,5,4,5,5,4,7,7,4,2,2,2,5,7,4,7,5,4,2,4,5,5,4,6,4,5,4,5,4,5,5,5,6,5, + 4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,4,5,4,6,5,5,4,2, + 4,2,2,7,4,7,7,4,5,5,4,2,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,5,7,4,5,4, + 6,4,2,5,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,4,6,5,5,5,4,2,4,5,4,6,5,4,5,5,4, + 2,2,7,7,2,2,4,5,5,4,7,2,7,4,2,2,2,7,2,2,2,2,2,7,2,2,2,2,2,4,0,0,4,5,0, + 2,4,0,0,4,5,0,2,4,0,4,0,0,4,2,5,5,4,3,4,7,4,7,4,7,5,4,7,4,5,5,4,5,2,4, + 5,0,3,3,5,5,6,6,5,2,6,7,6,5,7,7,4,5,4,0,0,4,2,3,4 }; static const unsigned short ag_key_parm[] = { - 0,302,303, 0,300,301, 0, 0,295, 0,304, 0, 0,297,305, 0, 35,286, - 0,118,120,122, 0,124,126, 0, 12,128, 0,116, 0, 0, 0, 0,136,138, - 140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146, 14,154, 0,156, - 158, 0,160,162, 0, 16,166, 0, 0, 20, 0,164, 18, 22, 0, 40, 0, 34, - 0, 26, 24, 0, 0, 0,168, 38, 0, 0, 0, 0,174,176, 0, 36,172, 0, - 186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0, - 206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 0, 48,216, 0, - 50,218,220, 0, 30,222, 0,224, 10,226, 0, 0,228, 0, 28,234, 0, 44, - 230,232, 0, 0,236,238, 0,246,248, 0,252,254, 0,258,260, 0, 0,240, - 242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272,274, 0, 0, 0, - 282, 0,280,284, 32, 0,286,288, 0, 0, 0,276,278, 0, 0, 46, 0,292, - 294, 0,290, 0,296, 0, 0, 52, 0, 0, 0, 0, 0,170, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 42, 0, 0,302,303, 0,300,301, 0, 0,295, 0,304, - 0, 0,297,305, 0, 35,286, 0,351,340, 0,333, 0,338,353, 0,118,120, - 122, 0,124, 70,126, 0, 12,128, 0,116, 0, 0, 0, 0,136,138,140, 0, - 142,144, 0,148,150,152, 0,130,132, 82,134, 0,146, 14,154, 0,156,158, - 0,160,162, 0, 16,166, 0, 0, 20, 0,164, 18, 22, 0, 40, 0, 34, 0, - 6, 0, 26, 24, 0, 0, 0,168, 38, 0, 54, 0, 0, 80, 92, 0, 58, 62, - 0, 4,170, 0, 0,174,176, 0, 36,172, 90, 0,186, 0,188,190,192,194, - 0,198,200, 0,178,180,184, 0,196,182,202, 0,206, 0,208,210, 0,204, - 0, 0,212,214, 0, 0, 0, 48, 2, 0, 0, 60, 0, 0, 84, 86, 64,216, - 0, 76,218, 0, 50, 0,220, 0,222, 78, 0, 30, 56, 0, 0,224, 10,226, - 0, 66,228, 0, 28,234, 0, 44,230,232,114, 0, 0,236,238, 0,246,248, - 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, - 0,268,270, 0,272,274, 0, 72, 74, 0,278, 0,282, 0,280,284, 32, 0, - 286,288, 0, 0, 8, 0,276,112, 88, 0, 0, 46, 0,292,294, 0,290, 68, - 0,296, 0,336, 0, 52,169,361,331, 0,344,334,342,110, 96,102,100,104, - 0, 0, 94, 0, 0,106,108, 0, 0, 0, 0, 0, 42, 0, 0, 38, 0,302, - 303, 0,300,301, 0, 0,295, 0,304, 0, 0,297,305, 0, 35,286, 0,351, - 340, 0,333, 0,338,353, 0,118,120,122, 0,124, 70,126, 0, 12,128, 0, - 116, 0, 0, 0, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132, - 82,134, 0,146, 14,154, 0,156,158, 0,160,162, 0, 16,166, 0, 0, 20, - 0,164, 18, 22, 0, 40, 0, 34, 0, 26, 24, 0, 0, 0,168, 38, 0, 54, - 0, 0, 80, 92, 0, 58, 62, 0,170, 0, 0,174,176, 0, 36,172, 90, 0, - 186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0, - 206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 60, 0, 48, 84, - 86, 64,216, 0, 76,218, 0, 50, 0,220, 0,222, 78, 0, 30, 56, 0, 0, - 224, 10,226, 0, 66,228, 0, 28,234, 0, 44,230,232,114, 0, 0,236,238, - 0,246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256, - 262,264,266, 0,268,270, 0,272,274, 0, 72, 74, 0,278, 0,282, 0,280, - 284, 32, 0,286,288, 0, 0, 0,276,112, 88, 0, 0, 46, 0,292,294, 0, - 290, 68, 0,296, 0,336, 0, 52,169,361,331, 0,344,334,342,110, 96,102, - 100,104, 0, 0, 94, 0, 0,106,108, 0, 0, 0, 0, 0, 42, 0, 0, 80, - 92, 0, 84, 86, 0, 52,169, 35, 82, 0, 90, 0, 78, 88, 0, 35, 0, 35, - 98, 0, 52, 35, 0, 35,286, 0, 0, 0, 35, 4, 2, 0, 35,286, 0,118, - 120,122, 0,124,126, 0, 12,128, 0,116, 0, 0, 0, 0,136,138,140, 0, - 142,144, 0,148,150,152, 0,130,132,134, 0,146, 14,154, 0,156,158, 0, - 160,162, 0, 16,166, 0, 0, 20, 0,164, 18, 22, 0, 40, 0, 34, 0, 26, - 24, 0, 0, 0,168, 38, 0, 6, 0, 0,174,176, 0, 36,172, 0,186, 0, - 188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0,206, 0, - 208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 0, 48,216, 0, 50,218, - 220, 0, 30,222, 0,224, 10,226, 0, 0,228, 0, 28,234, 0, 44,230,232, - 0, 0,236,238, 0,246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, - 0,250, 0,256,262,264,266, 0,268,270, 0,272,274, 0, 0, 0,282, 0, - 280,284, 32, 0,286,288, 0, 0, 8, 0,276,278, 0, 0, 46, 0,292,294, - 0,290, 0,296, 0, 0, 0, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 42, 0, 0,118,120,122, 0,124,126, 0, 12,128, 0,116, 0, 0, - 0, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146, - 14,154, 0,156,158, 0,160,162, 0, 16,166, 0, 0, 20, 0,164, 18, 22, - 0, 40, 0, 34, 0, 26, 24, 0, 0, 0,168, 38, 0, 0, 0,174,176, 0, - 36,172, 0,186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196, - 182,202, 0,206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 0, - 48,216, 0, 50,218,220, 0, 30,222, 0,224, 10,226, 0, 0,228, 0, 28, - 234, 0, 44,230,232, 0, 0,236,238, 0,246,248, 0,252,254, 0,258,260, - 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272,274, - 0, 0, 0,282, 0,280,284, 32, 0,286,288, 0, 0, 0,276,278, 0, 0, - 46, 0,292,294, 0,290, 0,296, 0, 0, 0, 0, 0,170, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 42, 0, 0, 20, 18, 22, 0, 0, 6, 8, 0, 52, 0, - 4, 2, 0,118,120,122, 0,124,126, 0, 12,128, 0,116, 0, 0, 0, 0, - 136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146, 14,154, - 0,156,158, 0,160,162, 0, 16,166, 0, 0, 20, 0,164, 18, 22, 0, 40, - 0, 34, 0, 26, 24, 0, 0, 0,168, 38, 0, 6, 0, 0,174,176, 0, 36, - 172, 0,186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182, - 202, 0,206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 0, 48, - 216, 0, 50,218,220, 0, 30,222, 0,224, 10,226, 0, 0,228, 0, 28,234, - 0, 44,230,232, 0, 0,236,238, 0,246,248, 0,252,254, 0,258,260, 0, - 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272,274, 0, - 0, 0,282, 0,280,284, 32, 0,286,288, 0, 0, 8, 0,276,278, 0, 0, - 46, 0,292,294, 0,290, 0,296, 0,286, 0, 0, 0, 0,170, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 42, 0, 0,286, 0, 80, 92, 0, 84, 86, 0, 52, - 169, 35, 82, 0, 90, 0, 88, 0, 35,286, 0,118,120,122, 0,124,126, 0, - 116, 0, 0,128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132, - 134, 0,146,154, 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,174,176, - 0,172, 0,186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196, - 182,202, 0,206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 0, - 216, 0,218,220, 0,224,226, 0, 0,228, 0,230,232,234, 0,236,238, 0, - 246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262, - 264,266, 0,268,270, 0,272,274, 0, 0, 0,282, 0,280,284, 0,286,288, - 0, 0, 0,276,278, 0, 0, 0,292,294, 0,290, 0,296, 0, 0, 0, 0, - 0,168,170, 0, 0, 0, 0,222, 0, 0, 0, 0, 0, 0, 35,286, 0,351, - 340, 0,333, 0,338,353, 0,118,120,122, 0,124, 70,126, 0,116, 0, 0, - 128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146, - 154, 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, - 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198,200, 0,178,180, - 184, 0,196,182,202, 0,206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, - 0, 0, 60, 0, 64,216, 0, 76,218, 0, 0,220, 0, 56,222, 0,224,226, - 0, 66,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, 0,258, - 260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272, - 274, 0, 72, 74, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, - 0, 0,292,294, 0,290, 68, 0,296, 0,336,361,331, 0,344,334,342, 0, - 0, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35,286, - 0,118,120,122, 0,124,126, 0,116, 0, 0,128, 0,136,138,140, 0,142, - 144, 0,148,150,152, 0,130,132, 82,134, 0,146,154, 0,156,158, 0,160, - 162, 0, 0, 0,164,166, 0, 80, 92, 0,174,176, 0,172, 90, 0,186, 0, - 188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0,206, 0, - 208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 0, 84, 86,216, 0,218, - 220, 0,224,226, 0, 0,228, 0,230,232,234, 0,236,238, 0,246,248, 0, - 252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0, - 268,270, 0,272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0, - 276,278, 88, 0, 0, 0,292,294, 0,290, 0,296, 0, 52,169, 0, 0, 0, - 0,168, 0,170, 0, 0, 0, 0,222, 0, 0, 0, 0, 0, 0, 35,110, 96, - 102,100,104, 94,106,108, 0, 35, 96,100, 0, 35,110, 96,100, 94,114, 0, - 35, 96,100, 94,112, 0, 80, 92, 0, 84, 86, 0, 52,169, 82, 0, 90, 0, - 78, 88, 0,110, 96,102,100,104, 94,106,108, 0, 96,100, 0,110, 96,100, - 94,114, 0, 96,100, 94,112, 0,118,120,122, 0,124,126, 0,116, 0, 0, - 128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146, - 154, 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,174,176, 0,172, 0, - 186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0, - 206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 0,216, 0,218, - 220, 0,224,226, 0, 0,228, 0,230,232,234, 0,236,238, 0,246,248, 0, - 252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0, - 268,270, 0,272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0, - 276,278, 0, 0, 0,292,294, 0,290, 0,296, 0,286, 0, 0, 0,168,170, - 0, 0, 0, 0,222, 0, 0, 0, 0, 0, 0, 35,286, 0, 52, 0, 0, 52, - 286, 0, 35,286, 0,351,340, 0,333, 0,338,353, 0,336,361,331, 0,344, - 334,342, 0, 35,286, 0,331, 0, 0,169, 0,174, 0, 35,286, 0,351,340, - 0,333, 0,338,353, 0,118,120,122, 0,124, 70,126, 0,116, 0, 0,128, - 0,136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146,154, - 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, 0, - 170, 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198,200, 0,178, - 180,184, 0,196,182,202, 0,206, 0,208,210, 0,204, 0, 0,212,214, 0, - 0, 0, 0, 60, 0, 64,216, 0, 76,218, 0, 0,220, 0, 56,222, 0,224, - 226, 0, 66,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, 0, - 258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0, - 272,274, 0, 72, 74, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, - 0, 0, 0,292,294, 0,290, 68, 0,296, 0,336,361,331, 0,344,334,342, - 0, 96, 0,100, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, - 0, 94, 0, 35,286, 0,351,340, 0,333, 0,338,353, 0, 58, 62, 0,170, - 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198,200, 0,178,180, - 184, 0,196,182,202, 0,206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, - 0, 0, 60, 0, 64,216, 0, 76,218, 0, 0,220, 0, 56,222, 0,224,226, - 0, 66,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, 0,258, - 260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0,272, - 274, 0, 72, 74, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, - 0, 0,292,294, 0,290, 68, 0,296, 0,336,361,331, 0,344,334,342, 96, - 100, 0, 94, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 80, 92, 0, - 84, 86, 0, 52,169, 82, 0, 90, 0, 88, 0,351,340, 0,333, 0,338,353, - 0,118,120,122, 0,124, 70,126, 0,116, 0, 0,128, 0,136,138,140, 0, - 142,144, 0,148,150,152, 0,130,132,134, 0,146,154, 0,156,158, 0,160, - 162, 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, 0,174,176, 0,172, 0, - 186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0, - 206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 60, 0, 64,216, - 0, 76,218, 0, 0,220, 0, 56,222, 0,224,226, 0, 66,228, 0,230,232, - 234, 0,236,238, 0,246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, - 0,250, 0,256,262,264,266, 0,268,270, 0,272,274, 0, 72, 74, 0,282, - 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, 0, 0,292,294, 0,290, - 68, 0,296, 0,336,361,331,286,344,334,342, 0, 0, 0, 0, 0,170, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,351,340, 0,333, 0,338,353, 0, - 118,120,122, 0,124, 70,126, 0,116, 0, 0,128, 0,136,138,140, 0,142, - 144, 0,148,150,152, 0,130,132,134, 0,146,154, 0,156,158, 0,160,162, - 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, 0,174,176, 0,172, 0,186, - 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0,206, - 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 60, 0, 64,216, 0, - 218,220, 0, 56,222, 0,224,226, 0, 66,228, 0,230,232,234, 0,236,238, - 0,246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, 0,256, - 262,264,266, 0,268,270, 0,272,274, 0, 72, 74, 0,282, 0,280,284, 0, - 286,288, 0, 0, 0,276,278, 0, 0, 0,292,294, 0,290, 68, 0,296, 0, - 336,331,286,344,334,342, 0, 0, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,340, 0,333, 0,338, 0,118,120,122, 0,124, 70,126, - 0,116, 0, 0,128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130, - 132,134, 0,146,154, 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,168, - 54, 0, 58, 62, 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198, - 200, 0,178,180,184, 0,196,182,202, 0,206, 0,208,210, 0,204, 0, 0, - 212,214, 0, 0, 0, 0, 60, 0, 64,216, 0,218,220, 0, 56,222, 0,224, - 226, 0, 66,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, 0, - 258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0, - 272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, - 0, 0,292,294, 0,290, 68, 0,296, 0,336,331,286,344,334,342, 0, 0, - 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,340, 0,333, - 0,338, 0,118,120,122, 0,124,126, 0,116, 0, 0,128, 0,136,138,140, - 0,142,144, 0,148,150,152, 0,130,132,134, 0,146,154, 0,156,158, 0, - 160,162, 0, 0, 0,164,166, 0,168, 54, 0, 58, 62, 0,174,176, 0,172, - 0,186, 0,188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, - 0,206, 0,208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 60, 0, 64, - 216, 0,218,220, 0, 56,222, 0,224,226, 0, 66,228, 0,230,232,234, 0, - 236,238, 0,246,248, 0,252,254, 0,258,260, 0, 0,240,242,244, 0,250, - 0,256,262,264,266, 0,268,270, 0,272,274, 0, 0, 0,282, 0,280,284, - 0,286,288, 0, 0, 0,276,278, 0, 0, 0,292,294, 0,290, 68, 0,296, - 0,336,331,286,344,334,342, 0, 0, 0, 0, 0,170, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,340, 0,333, 0,338, 0,118,120,122, 0,124,126, - 0,116, 0, 0,128, 0,136,138,140, 0,142,144, 0,148,150,152, 0,130, - 132,134, 0,146,154, 0,156,158, 0,160,162, 0, 0, 0,164,166, 0,168, - 54, 0, 58, 62, 0,174,176, 0,172, 0,186, 0,188,190,192,194, 0,198, - 200, 0,178,180,184, 0,196,182,202, 0,206, 0,208,210, 0,204, 0, 0, - 212,214, 0, 0, 0, 0, 60, 0, 64,216, 0,218,220, 0, 56,222, 0,224, - 226, 0, 66,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, 0, - 258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, 0, - 272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, 0, - 0, 0,292,294, 0,290, 0,296, 0,336,331,286,344,334,342, 0, 0, 0, - 0, 0,170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,340, 0,333, 0, - 338, 0, 58, 62, 0, 60, 64, 0,336,286,344,334,342, 54, 0, 0, 56, 0, - 331,286, 0, 35,286, 0,118,120,122, 0,124,126, 0,116, 0, 0,128, 0, - 136,138,140, 0,142,144, 0,148,150,152, 0,130,132,134, 0,146,154, 0, - 156,158, 0,160,162, 0, 0, 0,164,166, 0,174,176, 0,172, 0,186, 0, - 188,190,192,194, 0,198,200, 0,178,180,184, 0,196,182,202, 0,206, 0, - 208,210, 0,204, 0, 0,212,214, 0, 0, 0, 0, 0,216, 0,218,220, 0, - 224,226, 0, 0,228, 0,230,232,234, 0,236,238, 0,246,248, 0,252,254, - 0,258,260, 0, 0,240,242,244, 0,250, 0,256,262,264,266, 0,268,270, - 0,272,274, 0, 0, 0,282, 0,280,284, 0,286,288, 0, 0, 0,276,278, - 0, 0, 0,292,294, 0,290, 0,296, 0,331, 0, 0, 0, 0,168,170, 0, - 0, 0, 0,222, 0, 0, 0, 0, 0, 0,331, 0, 35,286, 0, 0, 96,100, - 94, 98, 0, 82, 0, 80, 92, 0, 84, 86, 0, 52,169, 35,110, 96,102,100, - 104, 0, 94, 90,106,108, 78, 88, 0 + 0,396,393, 0, 4, 0, 6, 0, 0, 0, 0, 0,406, 90,132, 0, 0, 0, + 464, 0,427, 0,489,395,428, 0,396,393, 0,479,468, 0,461, 0,466,481, + 0,264,266,300, 0,268,110,302, 0, 38,172, 0,298, 0, 0,176, 0, 0, + 160, 42, 46, 0,180,182,270, 0,310,312, 0,316,318,320, 0,304,306,122, + 308, 0,314, 32,322, 0,184,286, 0,272,288, 0,138, 0, 30, 0, 0, 0, + 0, 0, 0,368,374, 0, 34,188, 0, 0, 44, 0,162,186, 40, 50, 0, 18, + 22, 0, 24, 0, 72, 0, 0, 0, 58, 56, 0, 0, 0, 66,192, 0, 0, 94, + 26, 0, 0, 68,120,132, 0, 98,102, 0,190,194, 0, 12,134,164, 0, 14, + 20, 0, 4, 0, 6, 0, 0, 92,274,290, 0, 16,324,130, 0,340, 0,346, + 0,342,352,350,344,354, 0,358,360, 0,332,348, 0,330, 0,326,336,334, + 338, 0,356, 0,328,362, 0,258, 0,366,372, 0,364, 0,370, 0,200, 0, + 376,198,196, 0, 0, 0, 84, 10, 0,126,136, 0, 0,100, 0, 0,124, 0, + 76,104,292, 0, 60, 0,116,276, 0, 86, 0, 74,294, 0, 80, 0,202,118, + 0, 62, 96, 0, 0,278, 36,378, 0,106,380, 0, 8, 70, 0, 54,262, 0, + 88,204,260, 0,168, 0, 0,206,208, 0,216,218, 0,224,226, 0,230,232, + 0,234,178, 0,236, 0,296, 0, 0,210,220,212,214, 0,222, 0,228, 0, + 0,238, 0,280,382, 0,244, 0,384,242,174,240, 0,112,114, 0,248, 0, + 256, 0,386,250, 64, 0,282,388, 0, 0, 2, 0,246,166,128, 0, 0, 82, + 0, 48, 78, 0,284,390, 0,252,108, 0,254, 0,170,406, 90,132,226,236, + 0,458, 0,472,462,470,158,144,146,148,150, 0, 0,152, 0, 0,154,156, + 0, 0, 0, 0, 0, 0, 28, 52, 0,423, 0,396,393, 0,406, 90,132, 0, + 0, 18, 22, 0, 0, 24, 26, 0, 14, 20, 0, 16, 4, 0, 30, 0, 0, 8, + 28, 0,396,393, 0,132,428, 0,158, 0,427, 0,396,393, 0,264,266,300, + 0,268,302, 0, 38,172, 0,298, 0, 0,176, 0, 0, 42, 46, 0,180,182, + 270, 0,310,312, 0,316,318,320, 0,304,306,308, 0,314, 32,322, 0,184, + 286, 0,272,288, 0,368,374, 0, 34,188, 0, 0, 44, 0, 0,186, 40, 50, + 0, 24, 0, 72, 0, 58, 56, 0, 0, 0, 66,192, 22, 0, 0, 0, 0,190, + 194, 0, 12, 0, 0,274,290, 0, 16,324, 0,340, 0,346, 0,342,352,350, + 344,354, 0,358,360, 0,332,348, 0,330, 0,326,336,334,338, 0,356, 0, + 328,362, 0,258, 0,366,372, 0,364, 0,370, 0,200, 0,376,198,196, 0, + 0, 0, 84, 10, 0, 0, 0, 0, 76,292, 0, 60,276, 0, 86, 0, 74,294, + 0, 80, 0,202, 0, 62, 0, 0,278, 36,378, 0, 0,380, 0, 54,262, 0, + 88,204,260, 70, 0, 0,206,208, 0,216,218, 0,224,226, 0,230,232, 0, + 234,178, 0,236, 0,296, 0, 0,210,220,212,214, 0,222, 0,228, 0, 0, + 238, 0,280,382, 0,244, 0,384,242,174,240, 0, 0, 0,256, 0,386,250, + 64, 0,282,388, 0, 0, 2, 0,246,248, 0, 0, 82, 0, 48, 78, 0,284, + 390, 0,252, 0,254, 0, 90,132,428, 0, 0, 0, 0, 0, 0, 68, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0,396,393, 0, 4, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0,427, 0,396,393, 0,264,266,300, 0,268, + 302, 0, 38,172, 0,298, 0, 0,176, 0, 0, 42, 46, 0,180,182,270, 0, + 310,312, 0,316,318,320, 0,304,306,308, 0,314, 32,322, 0,184,286, 0, + 272,288, 0,368,374, 0, 34,188, 0, 0, 44, 0, 0,186, 40, 50, 0, 24, + 0, 72, 0, 58, 56, 0, 0, 0, 66,192, 22, 0, 0, 0,190,194, 0, 12, + 0, 0, 4, 0, 6, 0, 0,274,290, 0, 16,324, 0,340, 0,346, 0,342, + 352,350,344,354, 0,358,360, 0,332,348, 0,330, 0,326,336,334,338, 0, + 356, 0,328,362, 0,258, 0,366,372, 0,364, 0,370, 0,200, 0,376,198, + 196, 0, 0, 0, 84, 10, 0, 0, 0, 0, 76,292, 0, 60,276, 0, 86, 0, + 74,294, 0, 80, 0,202, 0, 62, 0, 0,278, 36,378, 0, 0,380, 0, 54, + 262, 0, 88,204,260, 70, 0, 0,206,208, 0,216,218, 0,224,226, 0,230, + 232, 0,234,178, 0,236, 0,296, 0, 0,210,220,212,214, 0,222, 0,228, + 0, 0,238, 0,280,382, 0,244, 0,384,242,174,240, 0, 0, 0,256, 0, + 386,250, 64, 0,282,388, 0, 0, 0,246,248, 0, 0, 82, 0, 48, 78, 0, + 284,390, 0,252, 0,254, 0, 90,132,428, 0, 0, 0, 0, 0, 0, 68, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 90,132, 0,396,393, + 0, 0, 0,120,132, 0,126,136, 0,124, 0, 0, 90,132,226,122,138, 0, + 134,130, 0,118,128, 0, 12, 10, 0,396,393, 0, 4, 0, 6, 0, 0, 0, + 0, 0,406, 90,132,395, 0, 0, 0,395,428, 0,396,393, 0, 42, 46, 0, + 34, 0, 44, 40, 50, 0, 58, 56, 0, 0, 0, 66, 72, 0, 0, 0, 4, 0, + 6, 0, 0, 0, 0, 0, 84, 10, 0, 0, 76, 0, 86, 60, 74, 0, 62, 80, + 0, 88, 70, 54, 0, 2, 64, 82, 0, 48, 78, 0,427, 0, 0, 38, 0, 32, + 0, 0, 68, 12, 0, 0, 0, 0, 36, 0, 0, 0, 52,423, 0, 4, 0, 6, + 0, 0, 0, 0, 0, 0, 0,395,396, 0,396,393, 0,395, 0,423, 0,396, + 393, 0, 0, 92, 88, 0,396,393, 0,170, 0, 0,236,158,144,146,148,150, + 152,154,156, 0,160, 0,162, 0,164, 0,144,148,152,166, 0,160, 0,162, + 0,164, 0,158,144,148,152,168, 0,160, 0,162, 0,144,148, 0,464, 0, + 396,393, 0,479,468, 0,461, 0,466,481, 0,170,489,458, 0,472,462,470, + 0,464, 0,396,393, 0,479,468, 0,461, 0,466,481, 0, 98,102, 0,100, + 104, 0,112,114, 0, 0, 0,170,489,458, 0,472,462,470,110, 94, 0, 0, + 116, 96,106, 0,108, 0, 42, 46, 0, 34, 0, 44, 40, 50, 0, 58, 56, 0, + 0, 0, 66, 72, 0, 0, 84, 10, 0, 0, 76, 0, 86, 60, 74, 0, 62, 80, + 0, 88, 70, 54, 0, 64, 82, 0, 48, 78, 0,427,428, 38, 0, 32, 0, 0, + 68, 12, 0, 0, 0, 36, 0, 0, 0, 52, 0,396,393, 0,458, 0, 0,464, + 0,396,393, 0,479,468, 0,461, 0,466,481, 0, 98,102, 0,100,104, 0, + 106, 0,112,114, 0, 0, 0,170,489,458, 0,472,462,470,110, 94, 0, 0, + 116, 96,142,140, 0,108, 0,228, 0,464, 0,396,393, 0,479,468, 0,461, + 0,466,481, 0, 98,102, 0,100,104, 0,106, 0,112,114, 0, 0, 0,170, + 489,458, 0,472,462,470, 0, 0,116, 96,142,140, 0,108, 0,396,393, 0, + 120,132, 0,126,136, 0,124, 0, 0, 90,132,226,395, 0,122,138, 0,134, + 130, 0,118,128,423, 0,120,132, 0,126,136, 0,124, 0, 0, 90,132,226, + 122,138, 0,134,130, 0,128, 0,396,393, 0,120,132, 0,126,136, 0,124, + 0, 0, 90,132,226,395, 0,122,138, 0,134,130, 0,128,423, 0,464, 0, + 479,468, 0,461, 0,466,481, 0, 98,102, 0,100,104, 0,112,114, 0, 0, + 0,170,489,458,472,462,470,110, 94, 0, 0,116, 96,106, 0,108, 0,464, + 0,396,393, 0,479,468, 0,461, 0,466,481, 0, 98,102, 0,100,104, 0, + 112,114, 0, 0, 0,170,458, 0,472,462,470,110, 94, 0, 0, 96,106, 0, + 108, 0,464, 0,396,393, 0,468, 0,461, 0,466, 0, 98,102, 0,100,104, + 0,170,458, 0,472,462,470,110, 94, 0, 0, 96,106,108, 0,464, 0,396, + 393, 0,468, 0,461, 0,466, 0, 98,102, 0,100,104, 0,170,458, 0,472, + 462,470, 94, 0, 0, 96,106,108, 0,464, 0,396,393, 0,468, 0,461, 0, + 466, 0, 98,102, 0,100,104, 0,170,458, 0,472,462,470, 94, 0, 0, 96, + 106, 0,396,393, 0,468, 0,461, 0,466, 0, 98,102, 0,100,104, 0,464, + 0,472,462,470, 94, 0, 0, 96, 0,464, 0,489,395, 0,396,393, 0,479, + 468, 0,461, 0,466,481, 0, 98,102, 0,100,104, 0,112,114, 0, 0, 0, + 170, 0,458, 0,472,462,470,110, 94, 0, 0,116, 96,106, 0,108,423, 0, + 42, 46, 0, 34, 0, 44, 40, 50, 0, 58, 56, 0, 0, 0, 66, 72, 0, 0, + 0, 84, 10, 0, 0, 76, 0, 86, 60, 74, 0, 62, 80, 0, 88, 70, 54, 0, + 2, 64, 82, 0, 48, 78, 0,427,428, 38, 0, 32, 0, 0, 68, 12, 0, 0, + 0, 36, 0, 0, 0, 52, 0,226, 0,264,266,300, 0,268,302, 0,298, 0, + 0,176,172, 0,180,182,270, 0,310,312, 0,316,318,320, 0,304,306,308, + 0,314,322, 0,184,286, 0,272,288, 0,368,374, 0, 0, 0, 0,186,188, + 0,190,194, 0, 0, 0,274,290, 0,324, 0,340, 0,346, 0,342,352,350, + 344,354, 0,358,360, 0,332,348, 0,330, 0,326,336,334,338, 0,356, 0, + 328,362, 0,258, 0,366,372, 0,364, 0,370, 0,200, 0,376,198,196, 0, + 0, 0, 0, 0,292, 0,276,294, 0,278,378, 0, 0,380, 0,204,260,262, + 0,206,208, 0,216,218, 0,224,226, 0,230,232, 0,234,178, 0,236, 0, + 296, 0, 0,210,220,212,214, 0,222, 0,228, 0, 0,238, 0,280,382, 0, + 244, 0,384,242,174,240, 0, 0, 0,256, 0,386,250, 0,282,388, 0, 0, + 0,246,248, 0, 0, 0,284,390, 0,252, 0,254, 0, 0, 0, 0,192, 0, + 0, 0, 0, 0,202, 0, 0, 0, 0, 0, 0,396,393, 0, 90,132, 0, 0, + 396,393, 0,170,458, 0, 0,458, 0,396,393, 0, 0,142,140, 0,423, 0, + 122, 0,138, 0,120,132, 0,134, 0,126,136, 0,124, 0, 0, 90,132,226, + 236,158,144,146,148,150, 0,152,130,154,156,118,128, 0,170, 0,396,393, + 0, 0,423, 0 }; static const unsigned short ag_key_jmp[] = { - 0, 6, 9, 0, 13, 16, 0, 4, 20, 0, 0, 1, 7, 26, 32, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 39, 41, 0, 37, 19, 23, 26, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 0, 34, 38, 41, 46, 0, 0, 0, - 0, 0, 0, 0, 0, 49, 51, 0, 53, 0, 56, 0, 59, 0, 0, 56, 0, 69, - 0, 58, 61, 0, 73, 0, 0, 53, 71, 76, 0, 66, 0, 0, 0, 0, 83, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 92, 97, 0, 0, 0, - 0, 0, 0, 0, 0,108,110, 0, 0, 0, 0,116, 0,113,119, 71, 74, 0, - 76, 81, 83, 0, 85, 88, 0, 0, 0, 0, 0,133, 90, 0,100,104, 0, 92, - 95, 98,140, 0, 0, 0, 0, 0,110, 0, 0, 0, 0, 0, 0, 0,148, 0, - 106,108,151, 0,154,157,112,114, 0, 0, 0, 0, 0, 0, 0, 0,175, 0, - 0, 0,180, 0,121, 0, 0, 0, 0,172,178,116,118,182,186,124, 0, 0, - 0, 0,131,197,134, 0, 10, 0, 16, 29, 45, 62, 78, 63, 87,100,121,126, - 130,137,143,160,189,126,200, 0,145,148, 0,152,155, 0,227,159, 0,139, - 224,230,165,171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,183,185, 0,181,250,254,258, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,187, 0,190,266,270,273,193, 0, 0, 0, 0, - 0, 0, 0, 0,196,198, 0,286, 0,289, 0,292, 0, 0,203, 0,302, 0, - 0, 0,205,208, 0,308, 0, 0,200,304,306,311, 0,210, 0, 0, 0, 0, - 0,214,216, 0,218, 0, 0, 0, 0,328, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,336,338,343, 0, 0, 0, 0, 0, 0, 0, 0,354, - 356, 0, 0, 0, 0,362, 0,223,225, 0,359, 0,365,367, 0,227, 0,229, - 0, 0, 0, 0,231,379,236, 0, 0, 0, 0,238, 0,386, 0, 0, 0, 0, - 0,393,241, 0,253,257, 0,243,246,249,251,400, 0, 0, 0, 0, 0,263, - 0, 0, 0, 0, 0, 0, 0,409, 0,259,261,412, 0,415,418,265,267, 0, - 0, 0, 0, 0, 0, 0, 0,436, 0, 0,273, 0, 0, 0,444, 0,278, 0, - 0, 0, 0,433,269,439,271,442,275,446,450,281, 0, 0, 0, 0,288,291, - 463,293, 0,137,233, 0,176,179, 0,239,242,245,247,261, 0,277,295,313, - 319,322,325,332,346,370,382,389,397,403,421,453,283,466, 0,296, 0,306, - 309, 0,313,316, 0,506,320, 0,300,503,509,326,332, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,344,346, 0, - 342,529,533,537, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,348, 0, - 351,545,549,552,354, 0, 0, 0, 0, 0, 0, 0, 0,357,359, 0,565, 0, - 568, 0,571, 0, 0,364, 0,581, 0,366,369, 0,585, 0, 0,361,583, 0, - 588, 0,371, 0, 0, 0, 0, 0,375, 0,377, 0, 0, 0, 0,604, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,612,614,619, 0, 0, 0, - 0, 0, 0, 0, 0,630,632, 0, 0, 0, 0,638, 0,635, 0,641,382, 0, - 385, 0,387, 0, 0, 0, 0,389,652,394, 0, 0, 0, 0,396, 0,659, 0, - 0, 0, 0, 0,666,399, 0,411,415, 0,401,404,407,409,673, 0, 0, 0, - 0, 0,421, 0, 0, 0, 0, 0, 0, 0,682, 0,417,419,685, 0,688,691, - 423,425, 0, 0, 0, 0, 0, 0, 0, 0,709, 0, 0,429, 0, 0, 0,717, - 0,434, 0, 0, 0, 0,706,712,427,715,431,719,723,437, 0, 0, 0, 0, - 444,447,735,449, 0,298,512, 0,337,340, 0,518,521,524,526,540, 0,556, - 574,590,596,599,602,608,622,643,655,662,670,676,694,726,439,738, 0,461, - 0, 0, 0,467, 0, 0,452,455,457,773,465,776,469,472, 0,476, 0,478, - 0, 0, 0,480, 0, 0, 0, 0,797, 0,482,484,487, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,493,495, 0,491,809,813,816, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,497, 0,824,828,831,500, 0, 0, 0, 0, 0, - 0, 0, 0,503,505, 0,843, 0,846, 0,849, 0, 0,510, 0,859, 0,514, - 517, 0,863, 0, 0,507,861,512,866, 0, 0, 0, 0, 0,874, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,880,882,887, 0, 0, 0, 0, 0, - 0, 0, 0,898,900, 0, 0, 0, 0,906, 0,903,909,522,525, 0,527,532, - 534, 0,536,539, 0, 0, 0, 0, 0,923,541, 0,551,555, 0,543,546,549, - 930, 0, 0, 0, 0, 0,561, 0, 0, 0, 0, 0, 0, 0,938, 0,557,559, - 941, 0,944,947,563,565, 0, 0, 0, 0, 0, 0, 0, 0,965, 0, 0, 0, - 970, 0,574, 0, 0, 0, 0,962,567,968,569,571,972,976,577, 0, 0, 0, - 0,584,988,587, 0,806,819,835,852,868,519,877,890,911,916,920,927,933, - 950,979,579,991, 0, 0, 0, 0, 0, 0, 0, 0,592,594, 0,590,1013,1017, - 1020, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,596, 0,1028,1032, - 1035,599, 0, 0, 0, 0, 0, 0, 0, 0,602,604, 0,1047, 0,1050, 0, - 1053, 0, 0,609, 0,1063, 0,611,614, 0,1067, 0, 0,606,1065,1070, 0, - 0, 0, 0, 0,1077, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1083,1085,1090, 0, 0, 0, 0, 0, 0, 0, 0,1101,1103, 0, 0, 0, 0, - 1109, 0,1106,1112,619,622, 0,624,629,631, 0,633,636, 0, 0, 0, 0, - 0,1126,638, 0,648,652, 0,640,643,646,1133, 0, 0, 0, 0, 0,658, - 0, 0, 0, 0, 0, 0, 0,1141, 0,654,656,1144, 0,1147,1150,660,662, - 0, 0, 0, 0, 0, 0, 0, 0,1168, 0, 0, 0,1173, 0,669, 0, 0, - 0, 0,1165,1171,664,666,1175,1179,672, 0, 0, 0, 0,679,1190,682, 0, - 1023,1039,1056,1072,616,1080,1093,1114,1119,1123,1130,1136,1153,1182,674, - 1193, 0, 0, 0, 0, 0,1214,685,688, 0, 0, 0,691,694, 0, 0, 0, - 0, 0, 0, 0, 0,702,704, 0,700,1227,1231,1234, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,706, 0,1242,1246,1249,709, 0, 0, 0, 0, - 0, 0, 0, 0,712,714, 0,1261, 0,1264, 0,1267, 0, 0,719, 0,1277, - 0,723,726, 0,1281, 0, 0,716,1279,721,1284, 0, 0, 0, 0, 0,1292, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1298,1300,1305, 0, - 0, 0, 0, 0, 0, 0, 0,1316,1318, 0, 0, 0, 0,1324, 0,1321,1327, - 731,734, 0,736,741,743, 0,745,748, 0, 0, 0, 0, 0,1341,750, 0,760, - 764, 0,752,755,758,1348, 0, 0, 0, 0, 0,770, 0, 0, 0, 0, 0, 0, - 0,1356, 0,766,768,1359, 0,1362,1365,772,774, 0, 0, 0, 0, 0, 0, - 0, 0,1383, 0, 0, 0,1388, 0,783, 0, 0, 0, 0,1380,776,1386,778, - 780,1390,1394,786, 0, 0, 0, 0,793,1406,796, 0,698,1237,1253,1270, - 1286,728,1295,1308,1329,1334,1338,1345,1351,1368,1397,788,1409, 0,799, - 0,810, 0, 0, 0,816, 0, 0,801,804,806,1433,814,1436,818, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,822,1451,1455,824, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,827, 0,1463,1467,1470, 0, 0, 0, 0, - 0, 0, 0, 0,1481,1484, 0,830, 0, 0, 0, 0,1492, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1497,1499,1504, 0, 0, 0, 0, 0, - 0, 0, 0,1515,1517, 0, 0, 0, 0,1523, 0,1520,1526,838, 0,840,842, - 0, 0, 0, 0,1535,847, 0,849,852,854, 0, 0, 0, 0, 0,861, 0, 0, - 0, 0, 0, 0, 0,1545, 0,857,859,1548, 0,1551,1554,863,865, 0, 0, - 0, 0, 0, 0, 0, 0,1572, 0, 0, 0,1577, 0, 0, 0, 0, 0,1569, - 1575,867,869,1579,1582, 0, 0, 0, 0,872,1592,875, 0,1448,1458,1474, - 1487,833,835,1495,1507,1528,1532,844,1538,1541,1557,1585,1595, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 0, 6, 0, 8, 0, 0, 0, 0, 1, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 17, 0, 10, 37, 41, 12, 45, 0, + 0, 19, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 29, + 58, 62, 65, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 0, 86, 0, + 88, 0, 90, 35, 37, 0, 39, 41, 0, 78, 0, 81, 92, 0, 96, 0, 0, 46, + 48, 0, 50, 0,110, 0, 0, 0, 56, 59, 0,116, 0, 43, 0,107,112,114, + 52,119, 0, 61, 64, 0, 0, 0, 0, 0, 73, 0, 0, 68, 70,136, 0, 76, + 79, 0, 83, 0,146, 0,148, 86, 0, 0, 0,143,150, 0, 0, 0, 0, 0, + 0, 0, 0, 0,161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 159,163,169,172,175, 0, 0, 0, 0, 0, 0, 0,187,189, 90, 0, 0, 0, + 196, 0, 0, 0,198, 0, 92, 94, 0, 0, 0, 0,192, 0,202,204, 0,207, + 96, 0,102, 0,109, 0,220, 0, 0,104,222,112,118, 0,123, 0,230, 0, + 0,120, 0,232, 0, 0, 0, 0, 0,239,126, 0,136,140, 0,146,150, 0, + 128,131,134,246,144,249, 0, 0, 0, 0, 0,159, 0, 0, 0, 0, 0, 0, + 0, 0,161, 0, 0, 0,274, 0,259, 0,152,155,157,262, 0,265,268,271, + 276, 0, 0, 0, 0, 0, 0, 0,294, 0, 0, 0, 0,296, 0, 0,167, 0, + 0, 0,306, 0,172, 0, 0, 0, 0,291,163,301,165,304,169,308,312,175, + 0,177,180, 0, 0, 0, 0,193,196,328,198, 0, 18, 0, 20, 0, 3, 6, + 22, 0, 26, 29, 32, 34, 48, 54, 69, 99,121,129,133,139,155,177,210,225, + 235,243,252,278,315,325,184,189,331,201, 0, 0, 0, 0, 0, 0, 0,371, + 0,209,211, 0,379,213,217, 0,221,224, 0,386,228, 0,203,382,389,234, + 240, 0, 0, 0, 0, 0,245,398, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,254,256, 0,249,411,415,251,418, 0,258,262, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,265, 0,430,434,437,268, 0, 0, 0, + 0, 0, 0, 0, 0,271,273, 0,275,277, 0,449, 0,452,455, 0,458, 0, + 0,285, 0,469, 0,289,292, 0,473, 0,279, 0,282,471,287,476, 0,300, + 0, 0,298,485, 0, 0, 0, 0, 0,491, 0, 0, 0, 0, 0, 0, 0, 0, + 499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,497,501,507,510, + 513, 0, 0, 0, 0, 0, 0, 0,525,527,303, 0, 0, 0,534, 0, 0, 0, + 536, 0,305,307, 0,530,540,542,309,315, 0,322, 0, 0,317,551,326,332, + 0,337, 0,559, 0,334,561, 0, 0, 0, 0, 0,566,340, 0,355,359, 0, + 342,345,348,350,573, 0, 0, 0, 0, 0,368, 0, 0, 0, 0, 0, 0, 0, + 0,370, 0, 0, 0,597, 0,582, 0,361,364,366,585, 0,588,591,594,599, + 0, 0, 0, 0, 0, 0, 0,617, 0, 0, 0, 0,619, 0, 0, 0,626, 0, + 379, 0, 0, 0, 0,614,372,624,374,376,628,632,382, 0,384,387, 0, 0, + 0, 0,395,647,398, 0,406, 0,247,408,421,427,441,461,478,294,488,494, + 515,545,554,563,570,576,601,635,644,391,650, 0, 0, 0, 0,401, 0,681, + 0,683, 0,685, 0,678,687, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,411,413, 0,406,697,701,408,704, 0,415,419, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,422, 0,716,720,723,425, 0, 0, 0, 0, 0, + 0, 0, 0,428,430, 0,432,434, 0,735, 0,738,741, 0,744, 0, 0,442, + 0,755, 0,444,447, 0,759, 0,436, 0,439,757,762, 0,455, 0, 0,453, + 770, 0,458, 0,776, 0,778, 0, 0, 0, 0,780, 0, 0, 0, 0, 0, 0, + 0, 0,789, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,787,791, + 797,800,803, 0, 0, 0, 0, 0, 0, 0,815,817,461, 0, 0, 0,824, 0, + 0, 0,826, 0,463,465, 0,820,830,832,467,473, 0,480, 0, 0,475,841, + 484,490, 0,495, 0,849, 0,492,851, 0, 0, 0, 0, 0,856,498, 0,513, + 517, 0,500,503,506,508,863, 0, 0, 0, 0, 0,526, 0, 0, 0, 0, 0, + 0, 0, 0,528, 0, 0, 0,887, 0,872, 0,519,522,524,875, 0,878,881, + 884,889, 0, 0, 0, 0, 0, 0, 0,907, 0, 0, 0, 0,909, 0, 0, 0, + 916, 0,535, 0, 0, 0, 0,904,914,530,532,918,922,538, 0,540,543, 0, + 0, 0, 0,551,936,554, 0,692, 0,404,694,707,713,727,747,764,449,773, + 784,805,835,844,853,860,866,891,925,933,547,939, 0, 0, 0, 0, 0, 0, + 0,970, 0,571, 0, 0, 0, 0, 0, 0,978, 0, 0, 0,557,560,564,975, + 575,579,981,581,584, 0,588,591, 0, 0, 0, 0,597, 0,1002, 0,1004, + 0,1006, 0, 0, 0, 0,595,999,1008, 0, 0, 0, 0, 0, 0, 0,606, + 610, 0,617, 0, 0,1026, 0, 0,626,629, 0,1032, 0,619,622,624,1035, + 0,638, 0,1042, 0,1044, 0,1046, 0,641,643, 0,1050,645, 0,651,656, + 661, 0,667,670, 0,678,681,686, 0,691,693,697, 0,699,702, 0,600,1017, + 1020,602,1023,613,1028,1037,631,635,1048,1053,1056,1060,675,1063,1067, + 1071,706,710, 0,712, 0,1095, 0,1097, 0,1099, 0,1101, 0,715,717, 0, + 0, 0, 0,719,1108,721, 0, 0, 0, 0,1115,723,729, 0, 0, 0, 0, + 0,1122, 0,733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,1138,1140,1142,737, 0, 0, 0, 0, 0, 0, 0, 0,1149,1151,1153, + 739, 0, 0, 0, 0, 0,1161,1163, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,1168,742, 0,1170,1173,1176,1178, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1208, 0,1189,744, 0,1191,1194,1197,1199,746,749,1202,1205,751,754,756, + 1211,758, 0,769,773, 0,780, 0, 0,1233, 0, 0,787,790, 0,1239, 0, + 782,785,1242, 0,799,801, 0,1248,803, 0,809,814,819, 0,825,828, 0, + 836,839,844, 0,849,853, 0,855,858, 0,761,763,765,1230,776,1235,1244, + 792,796,1251,1254,1258,833,1261,1265,1268,862, 0, 0, 0, 0, 0,1289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 882,1627,1631,884, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,887, - 0,1640,1644,1647, 0, 0, 0, 0, 0, 0, 0, 0,1658,1661, 0,890, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1675, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,1680,1682,1687, 0, 0, 0, 0, 0, 0, 0, 0,1698, - 1700, 0, 0, 0, 0,1706, 0,1703, 0,1709, 0,896, 0, 0, 0, 0,1717, - 898, 0, 0,900, 0, 0, 0, 0,1726,902, 0,904,907,909, 0, 0, 0, 0, - 0,916, 0, 0, 0, 0, 0, 0, 0,1736, 0,912,914,1739, 0,1742,1745, - 918,920, 0, 0, 0, 0, 0, 0, 0, 0,1763, 0, 0, 0, 0,1769, 0, - 0, 0, 0, 0,1760,1766,922,924,1771,1774, 0, 0, 0, 0,927,930,1784, - 932, 0,878,880, 0,1616,1619,1622,1624,1635,1651,1664,1669,1672,893,1678, - 1690,1711,1720,1723,1729,1732,1748,1777,1787, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,938,1819,1823,940, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,943, 0,946,1831,1835,1838, 0, 0, 0, 0, 0, 0, 0, 0, - 1850,1853, 0,949, 0,954, 0, 0, 0, 0, 0,1864, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1870,1872,1877, 0, 0, 0, 0, 0, - 0, 0, 0,1888,1890, 0, 0, 0, 0,1896, 0,1893,1899, 0,961,963, 0, - 965,967, 0, 0, 0, 0,1910,972, 0,974,977,979, 0, 0, 0, 0, 0,986, - 0, 0, 0, 0, 0, 0, 0,1920, 0,982,984,1923, 0,1926,1929,988,990, - 0, 0, 0, 0, 0, 0, 0, 0,1947, 0, 0, 0,1952, 0, 0, 0, 0, - 0,1944,1950,992,994,997,1954,1957, 0, 0, 0, 0,1000,1968,1003, 0, - 0,935,1816,1826,1842,1856,952,1861,958,1867,1880,1901,1907,969,1913, - 1916,1932,1960,1971, 0,1006, 0, 0, 0, 0, 0, 0, 0, 0, 0,1008, - 0, 0, 0,1010, 0, 0, 0, 0,1012, 0,1015, 0, 0, 0,1017, 0,1026, - 0, 0, 0,1032, 0, 0,1019,1022,2022,1030,2025,1034,1037, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1041, 0, 0, 0, - 0,1044, 0, 0, 0, 0, 0, 0, 0, 0,1048,2060,2064,1050, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1053, 0,2072,2076,2079, 0, 0, 0, - 0, 0, 0, 0, 0,2090,2093, 0,1056, 0, 0, 0, 0,2101, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2106,2108,2113, 0, 0, 0, 0, - 0, 0, 0, 0,2124,2126, 0, 0, 0, 0,2132, 0,2129,2135,1064, 0, - 1066,1068, 0, 0, 0, 0,2144,1073, 0,1075,1078,1080, 0, 0, 0, 0, - 0,1087, 0, 0, 0, 0, 0, 0, 0,2154, 0,1083,1085,2157, 0,2160, - 2163,1089,1091, 0, 0, 0, 0, 0, 0, 0, 0,2181, 0, 0, 0,2186, 0, - 0, 0, 0, 0,2178,2184,1093,1095,2188,2191, 0, 0, 0, 0,1098,2201, - 1101, 0,1046,2067,2083,2096,1059,1061,2104,2116,2137,2141,1070,2147,2150, - 2166,2194,2204, 0, 0, 0, 0, 0,2225, 0, 0,1104, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,1106,1108, 0,2234,2237,2240,2242, 0, 0, - 0, 0, 0,2253, 0,1110, 0,1113, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1119,2274,2278,1121, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1124, 0,2287,2291,2294, 0, 0, - 0, 0, 0, 0, 0, 0,2305,2308, 0,1127, 0, 0, 0, 0, 0, 0, 0, - 1130, 0, 0, 0, 0,2324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,2329,2331,2336, 0, 0, 0, 0, 0, 0, 0, 0,2347,2349, 0, 0, - 0, 0,2355, 0,2352, 0,2358, 0,1132, 0, 0, 0, 0,2366,1134, 0, - 0,1136, 0, 0, 0, 0,2375,1138, 0,1140,1143,1145, 0, 0, 0, 0, - 0,1152, 0, 0, 0, 0, 0, 0, 0,2385, 0,1148,1150,2388, 0,2391, - 2394,1154,1156, 0, 0, 0, 0, 0, 0, 0, 0,2412, 0, 0, 0, 0,2418, - 0, 0, 0, 0, 0,2409,2415,1158,1160,2420,2423, 0, 0, 0, 0,1163, - 1166,2433,1168, 0,1115,1117, 0,2263,2266,2269,2271,2282, 0,2298,2311, - 2316,2319,2322,2327,2339,2360,2369,2372,2378,2381, 0,2397,2426,2436, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1175, 0, - 0, 0, 0,2485, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2490, - 2492,2497, 0, 0, 0, 0, 0, 0, 0, 0,2508,2510, 0, 0, 0, 0,2516, - 0,2513, 0,2519, 0,1177, 0, 0, 0, 0,2527,1179, 0, 0,1181, 0, - 0, 0, 0,2536,1183, 0,1185,1188,1190, 0, 0, 0, 0, 0,1197, 0, - 0, 0, 0, 0, 0, 0,2546, 0,1193,1195,2549, 0,2552,2555,1199,1201, - 0, 0, 0, 0, 0, 0, 0, 0,2573, 0, 0, 0, 0,2579, 0, 0, 0, - 0, 0,2570,2576,1203,1205,2581,2584, 0, 0, 0, 0,1208,1211,2594,1213, - 0,1171,1173, 0,2469,2472,2475,2477, 0, 0,2480,2483,2488,2500,2521, - 2530,2533,2539,2542, 0,2558,2587,2597, 0,1223, 0, 0, 0,1229, 0, 0, - 1216,1219,2625,1227,2628,1231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,1241,2647,2651,1243, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1246, 0,2660,2664,2667, 0, 0, 0, 0, 0, 0, - 0, 0,2678,2681, 0,1249, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2695, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2700,2702,2707, 0, - 0, 0, 0, 0, 0, 0, 0,2718,2720, 0, 0, 0, 0,2726, 0,2723, 0, - 2729, 0,1255, 0, 0, 0, 0,2737,1257, 0, 0,1259, 0, 0, 0, 0,2746, - 1261, 0,1263,1266,1268, 0, 0, 0, 0, 0,1275, 0, 0, 0, 0, 0, 0, - 0,2756, 0,1271,1273,2759, 0,2762,2765,1277,1279, 0, 0, 0, 0, 0, - 0, 0, 0,2783, 0, 0, 0, 0,2789, 0, 0, 0, 0, 0,2780,2786,1281, - 1283,2791,2794, 0, 0, 0, 0,1286,1289,2804,1291, 0,1235,1237, 0,1239, - 2639,2642,2644,2655,2671,2684,2689,2692,1252,2698,2710,2731,2740,2743, - 2749,2752,2768,2797,2807, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,1298,2844,2848,1300, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,1303, 0,2857,2861,2864, 0, 0, 0, 0, 0, 0, 0, 0, - 2875,2878, 0,1306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2892, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2897,2899,2904, 0, 0, 0, - 0, 0, 0, 0, 0,2915,2917, 0, 0, 0, 0,2923, 0,2920, 0,2926, 0, - 1312, 0,1314,1316, 0, 0,1318, 0, 0, 0, 0,2940,1320, 0,1322,1325, - 1327, 0, 0, 0, 0, 0,1334, 0, 0, 0, 0, 0, 0, 0,2950, 0,1330, - 1332,2953, 0,2956,2959,1336,1338, 0, 0, 0, 0, 0, 0, 0, 0,2977, - 0, 0, 0, 0,2983, 0, 0, 0, 0, 0,2974,2980,1340,1342,2985,2988, - 0, 0, 0, 0,1345,1348,2998,1350, 0,1294, 0,1296,2836,2839,2841,2852, - 2868,2881,2886,2889,1309,2895,2907,2928,2934,2937,2943,2946,2962,2991, - 3001, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1357, - 3035,3039,1359, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1362, 0, - 3048,3052,3055, 0, 0, 0, 0, 0, 0, 0, 0,3066,3069, 0,1365, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,3083, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,3088,3090,3095, 0, 0, 0, 0, 0, 0, 0, 0,3106, - 3108, 0, 0, 0, 0,3114, 0,3111, 0,3117, 0,1371, 0,1373,1375, 0, - 0,1377, 0, 0, 0, 0,3131,1379, 0,1381,1384,1386, 0, 0, 0, 0, - 0,1393, 0, 0, 0, 0, 0, 0, 0,3141, 0,1389,1391,3144, 0,3147, - 3150,1395,1397, 0, 0, 0, 0, 0, 0, 0, 0,3168, 0, 0, 0,3173, 0, - 0, 0, 0, 0,3165,3171,1399,1401,3175,3178, 0, 0, 0, 0,1404,1407, - 3188,1409, 0,1353, 0,1355,3029,3031,3033,3043,3059,3072,3077,3080,1368, - 3086,3098,3119,3125,3128,3134,3137,3153,3181,3191, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1416,3225,3229,1418, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1421, 0,3237,3241,3244, 0, 0, 0, 0, - 0, 0, 0, 0,3255,3258, 0,1424, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0,3272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,3277,3279, - 3284, 0, 0, 0, 0, 0, 0, 0, 0,3295,3297, 0, 0, 0, 0,3303, 0, - 3300, 0,3306, 0,1430, 0,1432,1434, 0, 0,1436, 0, 0, 0, 0,3320, - 1438, 0,1440,1443,1445, 0, 0, 0, 0, 0,1452, 0, 0, 0, 0, 0, 0, - 0,3330, 0,1448,1450,3333, 0,3336,3339,1454,1456, 0, 0, 0, 0, 0, - 0, 0, 0,3357, 0, 0, 0,3362, 0, 0, 0, 0, 0,3354,3360,1458,1460, - 3364,3367, 0, 0, 0, 0,1463,1466,3377,1468, 0,1412, 0,1414,3219,3221, - 3223,3232,3248,3261,3266,3269,1427,3275,3287,3308,3314,3317,3323,3326, - 3342,3370,3380, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1475,3414,3418,1477, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1480, - 0,3426,3430,3433, 0, 0, 0, 0, 0, 0, 0, 0,3444,3447, 0,1483, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,3461, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,3466,3468,3473, 0, 0, 0, 0, 0, 0, 0, 0, - 3484,3486, 0, 0, 0, 0,3492, 0,3489, 0,3495, 0,1489, 0,1491,1493, - 0, 0,1495, 0, 0, 0, 0,3509,1497, 0,1499,1502,1504, 0, 0, 0, - 0, 0,1511, 0, 0, 0, 0, 0, 0, 0,3519, 0,1507,1509,3522, 0,3525, - 3528,1513,1515, 0, 0, 0, 0, 0, 0, 0, 0,3546, 0, 0, 0,3551, 0, - 0, 0, 0, 0,3543,3549,1517,1519,3553,3556, 0, 0, 0, 0,1522,3566, - 1525, 0,1471, 0,1473,3408,3410,3412,3421,3437,3450,3455,3458,1486,3464, - 3476,3497,3503,3506,3512,3515,3531,3559,3569, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1528,1530,3596,3598,3600,1532,3602,3605,1534, 0, - 0,1536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1538,3624,3628,1540, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1543, 0,3636,3640,3643, - 0, 0, 0, 0, 0, 0, 0, 0,3654,3657, 0,1546, 0, 0, 0, 0,3665, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,3670,3672,3677, 0, - 0, 0, 0, 0, 0, 0, 0,3688,3690, 0, 0, 0, 0,3696, 0,3693,3699, - 1554, 0,1556,1558, 0, 0, 0, 0,3708,1563, 0,1565,1568,1570, 0, 0, - 0, 0, 0,1577, 0, 0, 0, 0, 0, 0, 0,3718, 0,1573,1575,3721, 0, - 3724,3727,1579,1581, 0, 0, 0, 0, 0, 0, 0, 0,3745, 0, 0, 0,3750, - 0, 0, 0, 0, 0,3742,3748,1583,1585,3752,3755, 0, 0, 0, 0,1588, - 3765,1591, 0, 0,3621,3631,3647,3660,1549,1551,3668,3680,3701,3705,1560, - 3711,3714,3730,3758,3768, 0, 0, 0, 0, 0, 0,3792, 0, 0, 0, 0, - 0,1599, 0,1602, 0, 0, 0,1608, 0, 0,1594,1597, 0, 0,3801, 0, - 0,3803, 0,1606,3806, 0,1610,1613, 0 + 0, 0, 0, 0, 0, 0, 0,1316, 0,1295,866, 0,1297,1300,1303,1305, + 868,871,1308,1311,873,876,1314, 0,1319,878, 0,881, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,1362, 0,1341,883, 0,1343,1346,1349,1351,1354,1357,885,888,1360, + 0,1365,890, 0, 0, 0, 0,909, 0, 0, 0, 0, 0, 0,1389, 0, 0, + 0,893,896,1383,898,902,1386,913,917,1392,919,922,926, 0,942, 0, 0, + 0, 0, 0, 0,1413, 0, 0, 0,928,931,935,1410,946,950,1416,952, 0, + 0, 0, 0,972, 0, 0, 0, 0, 0, 0,1436, 0, 0, 0,956,959,1430, + 961,965,1433,976,980,1439,982,986, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1472, 0,1456,988, 0,1458, + 1461,1463,990,993,1466,1469,995,998,1000,1475,1002, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1512, 0,1493, 0,1495,1498,1501,1503,1005,1008,1506,1509,1010,1012,1515, + 1014, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,1532, 0,1534,1537,1539,1541,1017,1020,1543,1546,1022,1024,1026, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1563, + 0,1565,1568,1570,1572,1029,1574,1577,1031,1033,1035, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1593, 0,1595, + 1598,1600,1602,1038,1604,1607,1040,1042, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1044,1622,1625,1627,1629,1046,1631,1634, + 1048, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1669, 0,1647,1649, 0,1652,1655,1658, + 1660,1050,1053,1663,1666,1055,1058,1060,1672,1062,1065, 0,1075,1079, 0, + 1086, 0, 0,1695, 0, 0,1095,1098, 0,1701, 0,1088,1091,1093,1704, 0, + 1107,1109, 0,1711,1111, 0,1117,1122,1127, 0,1133,1136, 0,1144,1147, + 1152, 0,1157,1159,1163, 0,1165,1168, 0,1067,1069,1071,1692,1082,1697, + 1706,1100,1104,1714,1717,1721,1141,1724,1728,1732,1172, 0,1176, 0, 0, + 0, 0, 0, 0, 0, 0,1179,1755,1759,1181,1184, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1187, 0,1768,1772,1775, 0, 0, 0, 0, 0, 0, + 0, 0,1190,1192, 0,1786,1789,1792, 0,1194, 0,1199, 0, 0,1801, 0, + 0, 0, 0,1806, 0, 0, 0, 0, 0, 0, 0, 0,1813, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1811,1815,1821,1824,1827, 0, 0, 0, + 0, 0, 0, 0,1839,1841,1202, 0, 0, 0,1848, 0, 0, 0,1850, 0,1844, + 1854,1204, 0,1206,1208, 0, 0, 0, 0,1863,1213, 0,1215,1218,1220, 0, + 0, 0, 0, 0,1230, 0, 0, 0, 0, 0, 0, 0, 0,1232, 0, 0, 0, + 1888, 0,1873, 0,1223,1226,1228,1876, 0,1879,1882,1885,1890, 0, 0, + 0, 0, 0, 0, 0,1908, 0, 0, 0, 0,1910, 0, 0, 0,1917, 0, 0, + 0, 0, 0,1905,1915,1234,1236,1919,1922, 0, 0, 0, 0,1239,1932,1242, + 0,1762,1779,1795,1197,1804,1809,1829,1856,1860,1210,1866,1869,1892,1925, + 1935, 0, 0, 0, 0, 0, 0,1955, 0, 0, 0, 0, 0, 0,1962, 0, 0, + 0, 0, 0, 0,1971, 0, 0, 0,1245, 0,1254, 0,1257, 0,1263, 0, 0, + 1267, 0, 0, 0, 0, 0,1989, 0, 0, 0,1247,1250, 0, 0,1980,1982, + 0,1984,1987,1270,1992, 0,1272,1275, 0, 0, 0, 0, 0, 0,2014,1279, + 0 }; static const unsigned short ag_key_index[] = { - 204, 0,471,204,501,743, 0,204,204,204,779,789,789, 0, 0, 0,791,794, - 794,800,800,794,794,802,789,789,995,1197,1218,1222,1222,1222,1222,1224, - 0, 0,1413,1431,789,1439,779,789,779,789,789,789,789,789,789,789,789, - 789,789,1599,1599,1439,789,779,779,1439,1792,779,789,779,1439,789,789, - 1975,789, 0, 0, 0, 0,1599,779,1995,1599,779,1995,1599,2005,779,1599, - 1599,1599,779,779,1995,1599,789,1599,1599,1599,1599,1599,1599,1599,1599, - 1599,1599,1599,1599,1599,1599,2009,2009,1599,779,779,1995,1599,1995,1995, - 2016,1599,779,779,779,2005,779,779,779,779,779,779,779,779,779,779,779, - 779,779,779,2016,1995,779,1599,1599,1599,1599,2016,1995,2016,1599,779, - 779,779,779,779,779,779,1995,1599,1599,779,779,779,1599,779,1995,779,1995, - 1995,779,2028,2037,2028,2037,2046,2028,2028,2028,2037, 0,2049,2049,2028, - 2028,2037,2037,2037,2055,2028,2028,2028,2046,2028,2028,2028,2028,2028, - 2028,2028,2028,2028,2028,2028,2028,2028,2028,2055,2037,2028,2055,2037, - 2055,2028,2028,2028,2028,2028,2028,2028,2037,2028,2028,2028,2028,2037, - 2028,2037,2037,2028,2208,794,1222,789, 0,800,800,1431,789, 0,800,800, - 779,2028,2228,2231,779,2028,794,1222,794,1222,794,1222,794,1222,779,2028, - 779,2028,779,2028,800,800,800,779,2028,2028,2028,2028,779,2028,779,2028, - 2245,800,800, 0,800, 0,2256,789,2028,2028,2028,2037,2028,2037,2046,2028, - 2028,2028,2037, 0,2049,2049,2028,2028,2037,2037,2037,2055,2028,2028,2028, - 2046,2028,2028,2028,2028,2028,2028,2028,2028,2028,2028,2028,2028,2028, - 2028,2055,2037,2028,2055,2037,2055,2028,2028,2028,2028,2028,2028,2028, - 2037,2028,2028,2028,2028,2037,2028,2037,2037,2028,2208,2259,2261,2261, - 2256, 0,2441, 0, 0,2261,1792,2467,1792,2602,789,789,789,789,789,789, - 789,1792,1792, 0, 0, 0, 0, 0, 0, 0,1439,2028,2631,2631,2631,2812, - 3006,3006,3196,3385,3573,3608,2028,1431,3618,3618,3618,2261,3618,3618, - 3618,3618, 0, 0,3772,1599,1599,1599,1599,1599,3790,3790,1599, 0,3795, - 0,2261, 0,2261,2028,2028,2028,2028,2028,2028,2028, 0,1439,2631,1439, - 2631,2631,2631,2631,2028,2028,779,2028,779,2028,779,2028,779,2028,779, - 2028,2028,779,2028,2028,779,2028,2028,779,779,779,779,779,779,779,779, - 779,779,779,779,779,3790,2261,3618,3618,3618,3618,3790,3790, 0, 0, 0, - 0, 0, 0, 0, 0, 0,2812,2631,2631,2631,2631,2631,2028,2028,2028,2028, - 2028,2028,2028,2028,2028,2028,2028,2028,3809,1222,2261,2028,2028,2037, - 2028,2812,2812,3006,3006,3006,3006,3006,3006,3196,3196,3385,3385,1222, - 2028,2028,2037,2028 + 12,336,374,392,401,392,654, 0,689,654,943,374,967,967, 0,973,973,967, + 984,984,967,996, 0,967,967, 0,973,973,967,984,984,967,996, 0,1010,1074, + 1103,1105,1111, 0,1105, 0, 0,654,1118,1125,1125,1125,1125,1125,1125, + 1125,1125,1125,1125,1125,1125,1125,1125,1128,1144,984,984,984,984,984, + 984,984,984,984,984,984,984,984,984,984,1125,1125,1125,1125,1125,1125, + 1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125, + 1125,1125,1125,1125,1125,1125,1125,1125, 0,1128,1144,984,984,984,984, + 984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984, + 984,984,984,984,984,984,984,984,984,984,1155,1155,1165,1165,1144,1144, + 1144,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128, 0, 0, 0, + 984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984, + 984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984, + 1155,1155,1165,1165,1144,1144,1144,1128,1128,1128,1128,1128,1128,1128, + 1128,1128,1128,1128,1181,1125,1213,973,1125,984,1271,973, 0, 0,973, 0, + 1292,973,973,973,973, 0, 0, 0,1213,1321, 0,1339,1213, 0,1213,1213, + 1213,1367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1213,1213,1395, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1419,1442,1419,1442,984,1419,1419,1419, + 1419,1213,1477,1517,1517,1549,1580,1610,1637,984,973,973,973,973,973,973, + 973, 0,973,973,973, 0, 0,1111,1395,1111,1395,1105,1111,1111,1111,1111, + 1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111, + 1111,1442,1395,1395,1395,1442,1674,1111,1395,1442,1111,1105,1111,1111, + 1010, 0, 0, 0,1735,973,1118,1128,1144, 0, 0, 0,984,984,984,984,984, + 984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984, + 984,984,984,984,984,984,984,984,984,984,984,984,984,1155,1155,1165,1165, + 1144,1144,1144,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128, + 984,1753,1939,1939,973,967,967, 0, 0,973,973, 0, 0,973,973,1958,1958, + 0, 0,984,984,984,984,984,984,967,967,967,967,967,967,967,967,967,967, + 984,984,984,984,984,984,984,984,984,984,973,984,984,984,984,1118,1118, + 973, 0, 0,973, 0,973,973, 0, 0,1339,1213,1213, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,984, 0,1419,1419,1419,1419,1419,1419,1419,984,984, + 984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984, + 984,984,984,984,984,984,984,984,984,984,984,984,973,973,973,973,973, 0, + 973,973, 0,973,973,973,984,984,984,984,973,973,973,1965,1125,984,984, + 1125,1125,1969,1339,1339,1292,1969, 0,1974,1939,1339, 0,984,1292,1292, + 1292,1292,1292, 0, 0,1978, 0, 0, 0, 0,967,984,984,984,984,984,984, + 984,984,984, 0,1419,1419,1419,1419,1419,984,984,984,984,984,984,984,984, + 984,984,984,984,973,973,973,973,973,973,984,984,1969,1339,1995,984,2012, + 1125,1339,984,1292,967,2017,2017,973, 0, 0,967, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,1477,1477,1517,1517,1517,1517,1517,1517,1549,1549,1580, + 1580,973,973,1128,1339,984,984,967, 0, 0, 0,1128, 0 }; static const unsigned char ag_key_ends[] = { -69,70,73,78,69,0, 83,69,0, 68,73,70,0, 69,70,0, 68,69,70,0, -67,76,85,68,69,0, 82,65,71,77,65,0, 78,68,69,70,0, 73,0, 71,0, -82,0, 76,76,0, 69,71,0, 71,0, 66,0, 83,69,0, 70,0, 82,78,0, -78,0, 76,84,0, 76,85,68,69,0, 78,75,0, 73,0, 67,76,73,66,0, -86,0, 73,0, 77,69,0, 80,0, 84,0, 71,69,0, 72,76,0, 80,0, -76,73,67,0, 72,0, 84,0, 77,0, 69,0, 67,0, 84,0, 77,0, -72,76,0, 76,78,0, 77,0, 73,84,76,69,0, 72,71,0, 72,76,0, 61,0, -69,70,73,78,69,0, 83,69,0, 68,73,70,0, 69,70,0, 68,69,70,0, -67,76,85,68,69,0, 82,65,71,77,65,0, 78,68,69,70,0, 92,39,0, 42,0, -73,0, 71,0, 82,0, 76,76,0, 73,76,0, 69,71,0, 71,0, 66,0, -83,69,0, 70,0, 82,78,0, 78,0, 79,79,82,0, 88,0, 84,0, -76,85,68,69,0, 75,0, 84,0, 71,0, 73,0, 67,76,73,66,0, 73,0, -77,69,0, 84,0, 71,69,0, 72,76,0, 80,0, 87,0, 76,73,67,0, 72,0, -84,0, 77,0, 69,0, 67,0, 84,0, 84,0, 77,0, 76,0, 82,84,0, -76,78,0, 77,0, 73,84,76,69,0, 72,71,0, 82,0, 72,76,0, 47,0, -61,0, 69,70,73,78,69,0, 83,69,0, 68,73,70,0, 69,70,0, -68,69,70,0, 67,76,85,68,69,0, 82,65,71,77,65,0, 78,68,69,70,0, -92,39,0, 42,0, 73,0, 71,0, 82,0, 76,76,0, 73,76,0, 69,71,0, -71,0, 66,0, 83,69,0, 70,0, 82,78,0, 78,0, 79,79,82,0, 84,0, -76,85,68,69,0, 78,75,0, 71,0, 73,0, 67,76,73,66,0, 73,0, -77,69,0, 84,0, 71,69,0, 72,76,0, 80,0, 87,0, 76,73,67,0, 72,0, -84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 76,0, 82,84,0, 76,78,0, -77,0, 73,84,76,69,0, 72,71,0, 82,0, 72,76,0, 92,39,0, 42,0, -69,73,76,0, 79,79,82,0, 80,0, 71,0, 79,84,0, 81,82,84,0, 42,0, -42,0, 42,0, 42,0, 69,88,0, 73,83,84,0, 73,0, 71,0, 82,0, -76,76,0, 69,71,0, 71,0, 66,0, 83,69,0, 70,0, 85,0, 82,78,0, -78,0, 76,84,0, 78,75,0, 73,0, 67,76,73,66,0, 86,0, 73,0, -77,69,0, 80,0, 84,0, 71,69,0, 72,76,0, 80,0, 76,73,67,0, 72,0, -84,0, 77,0, 69,0, 67,0, 84,0, 84,0, 77,0, 72,76,0, 76,78,0, -77,0, 73,84,76,69,0, 72,71,0, 72,76,0, 73,0, 71,0, 82,0, -76,76,0, 69,71,0, 71,0, 66,0, 83,69,0, 70,0, 82,78,0, 78,0, -76,84,0, 78,75,0, 73,0, 67,76,73,66,0, 86,0, 73,0, 77,69,0, -80,0, 84,0, 71,69,0, 72,76,0, 80,0, 76,73,67,0, 72,0, 84,0, -77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, 76,78,0, 77,0, -73,84,76,69,0, 72,71,0, 72,76,0, 81,85,0, 69,84,0, 69,88,0, -73,83,84,0, 47,0, 73,0, 71,0, 82,0, 76,76,0, 69,71,0, 71,0, -66,0, 83,69,0, 70,0, 85,0, 82,78,0, 78,0, 76,84,0, 78,75,0, -73,0, 67,76,73,66,0, 86,0, 73,0, 77,69,0, 80,0, 84,0, 71,69,0, -72,76,0, 80,0, 76,73,67,0, 72,0, 84,0, 77,0, 69,0, 67,0, -84,0, 84,0, 77,0, 72,76,0, 76,78,0, 77,0, 73,84,76,69,0, -72,71,0, 72,76,0, 47,0, 92,39,0, 42,0, 69,73,76,0, 79,79,82,0, -80,0, 71,0, 81,82,84,0, 73,0, 72,82,0, 76,76,0, 85,66,0, 73,0, -76,84,0, 73,0, 86,0, 73,0, 79,80,0, 84,0, 72,76,0, 80,0, -83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, -72,71,0, 72,76,0, 61,0, 42,0, 73,0, 72,82,0, 76,76,0, 85,66,0, -76,84,0, 73,0, 73,0, 80,0, 84,0, 72,76,0, 80,0, 83,72,0, -84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, 72,71,0, 82,0, -72,76,0, 92,39,0, 73,0, 72,82,0, 76,76,0, 73,76,0, 85,66,0, -73,0, 79,79,82,0, 76,84,0, 71,0, 73,0, 86,0, 73,0, 79,80,0, -84,0, 72,76,0, 80,0, 83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, -77,0, 72,76,0, 82,84,0, 72,71,0, 72,76,0, 42,0, 42,0, 42,0, -83,87,0, 42,0, 80,0, 92,39,0, 69,73,76,0, 79,79,82,0, 80,0, -71,0, 79,84,0, 81,82,84,0, 83,87,0, 80,0, 47,0, 73,0, 72,82,0, -76,76,0, 85,66,0, 73,0, 76,84,0, 73,0, 86,0, 73,0, 79,80,0, -84,0, 72,76,0, 80,0, 83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, -77,0, 72,76,0, 72,71,0, 72,76,0, 47,0, 61,0, 42,0, 92,39,0, -39,0, 61,0, 42,0, 73,0, 72,82,0, 76,76,0, 85,66,0, 84,0, -73,0, 73,0, 80,0, 84,0, 72,76,0, 80,0, 83,72,0, 84,0, 77,0, -69,0, 67,0, 84,0, 77,0, 72,76,0, 72,71,0, 82,0, 72,76,0, -61,0, 42,0, 84,0, 73,0, 73,0, 80,0, 84,0, 72,76,0, 80,0, -83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, -72,71,0, 82,0, 72,76,0, 92,39,0, 69,73,76,0, 79,79,82,0, 80,0, -71,0, 81,82,84,0, 61,0, 42,0, 47,0, 73,0, 72,82,0, 76,76,0, -85,66,0, 76,84,0, 73,0, 73,0, 80,0, 84,0, 72,76,0, 80,0, -83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, -72,71,0, 82,0, 72,76,0, 61,0, 47,0, 73,0, 72,82,0, 76,76,0, -85,66,0, 76,84,0, 73,0, 86,0, 73,0, 80,0, 84,0, 72,76,0, -80,0, 83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, -72,71,0, 82,0, 72,76,0, 61,0, 47,0, 73,0, 72,82,0, 76,76,0, -85,66,0, 76,84,0, 73,0, 86,0, 73,0, 80,0, 84,0, 72,76,0, -80,0, 83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, -72,71,0, 82,0, 72,76,0, 61,0, 47,0, 73,0, 72,82,0, 76,76,0, -85,66,0, 76,84,0, 73,0, 86,0, 73,0, 80,0, 84,0, 72,76,0, -80,0, 83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, -72,71,0, 82,0, 72,76,0, 61,0, 47,0, 73,0, 72,82,0, 76,76,0, -85,66,0, 76,84,0, 73,0, 86,0, 73,0, 80,0, 84,0, 72,76,0, -80,0, 83,72,0, 84,0, 77,0, 69,0, 67,0, 84,0, 77,0, 72,76,0, -72,71,0, 72,76,0, 61,0, 47,0, 81,0, 69,0, 47,0, 73,0, -72,82,0, 76,76,0, 85,66,0, 73,0, 76,84,0, 73,0, 86,0, 73,0, -79,80,0, 84,0, 72,76,0, 80,0, 83,72,0, 84,0, 77,0, 69,0, -67,0, 84,0, 77,0, 72,76,0, 72,71,0, 72,76,0, 92,39,0, 42,0, -73,76,0, 79,79,82,0, 80,0, 71,0, 79,84,0, 81,82,84,0, +68,69,0, 92,39,0, 72,76,41,0, 73,0, 72,76,0, 71,0, 82,0, +79,67,75,0, 84,69,0, 76,76,0, 73,76,0, 69,71,0, 76,0, 80,0, +71,0, 66,0, 72,79,0, 70,0, 69,0, 70,0, 82,79,82,0, 82,78,0, +78,0, 76,76,0, 79,79,82,0, 88,0, 71,72,0, 66,67,0, 69,70,0, +68,69,70,0, 68,69,0, 65,71,69,0, 73,0, 75,0, 84,0, +70,73,82,83,84,0, 73,0, 67,76,73,66,0, 76,69,0, 70,73,82,83,84,0, +73,0, 77,69,0, 71,69,0, 84,0, 71,69,0, 72,76,0, 80,0, +71,77,65,0, 78,84,70,0, 87,0, 76,73,67,0, 72,0, 69,76,0, 84,0, +77,0, 69,0, 76,0, 84,0, 77,0, 76,0, 82,84,0, 76,78,0, 77,0, +88,84,0, 84,76,69,0, 78,68,69,70,0, 79,82,68,0, 72,71,0, 82,0, +72,76,0, 10,0, 69,70,73,78,69,0, 70,0, 69,0, 68,73,70,0, +82,79,82,0, 69,70,0, 68,69,70,0, 67,76,85,68,69,0, +82,65,71,77,65,0, 78,68,69,70,0, 61,0, 61,0, 73,0, 72,76,0, +71,0, 82,0, 79,67,75,0, 84,69,0, 76,76,0, 69,71,0, 76,0, 80,0, +71,0, 66,0, 72,79,0, 83,69,0, 70,0, 85,0, 82,78,0, 78,0, +73,76,76,0, 88,0, 66,67,0, 73,0, 75,0, 84,0, 70,73,82,83,84,0, +73,0, 67,76,73,66,0, 85,76,69,0, 70,73,82,83,84,0, 73,0, +77,69,0, 71,69,0, 84,0, 71,69,0, 72,76,0, 80,0, 73,78,84,70,0, +76,73,67,0, 72,0, 69,76,0, 84,0, 77,0, 69,0, 76,0, 84,0, +77,0, 72,76,0, 76,78,0, 77,0, 88,84,0, 84,76,69,0, 79,82,68,0, +72,71,0, 72,76,0, 68,69,0, 61,0, 73,0, 72,76,0, 71,0, 82,0, +79,67,75,0, 84,69,0, 76,76,0, 69,71,0, 76,0, 80,0, 71,0, 66,0, +72,79,0, 83,69,0, 70,0, 82,78,0, 78,0, 73,76,76,0, 88,0, +66,67,0, 68,69,0, 73,0, 75,0, 84,0, 70,73,82,83,84,0, 73,0, +67,76,73,66,0, 85,76,69,0, 70,73,82,83,84,0, 73,0, 77,69,0, +71,69,0, 84,0, 71,69,0, 72,76,0, 80,0, 73,78,84,70,0, +76,73,67,0, 72,0, 69,76,0, 84,0, 77,0, 69,0, 76,0, 77,0, +72,76,0, 76,78,0, 77,0, 88,84,0, 84,76,69,0, 79,82,68,0, +72,71,0, 72,76,0, 92,39,0, 69,73,76,0, 69,70,73,78,69,68,0, +79,79,82,0, 73,71,72,0, 80,0, 79,84,0, 81,82,84,0, 69,88,0, +73,83,84,0, 47,0, 68,69,0, 61,0, 83,69,71,0, 79,67,75,0, +84,69,0, 83,69,71,0, 71,0, 72,79,0, 68,0, 85,0, 82,78,0, 78,0, +73,76,76,0, 69,88,0, 68,69,0, 75,0, 84,0, 70,73,82,83,84,0, +67,76,73,66,0, 68,85,76,69,0, 70,73,82,83,84,0, 77,69,0, +80,65,71,69,0, 82,71,0, 71,69,0, 73,78,84,70,0, 66,76,73,67,0, +84,0, 75,76,78,0, 77,0, 88,84,0, 84,76,69,0, 79,82,68,0, 10,0, +68,69,0, 47,0, 42,0, 47,0, 10,0, 78,80,65,71,69,0, 65,71,69,0, +72,76,41,0, 80,0, 83,87,0, 42,0, 42,0, 78,68,0, 81,0, 79,68,0, +69,0, 82,0, 79,82,0, 61,0, 61,0, 83,69,71,0, 79,67,75,0, +84,69,0, 83,69,71,0, 71,0, 72,79,0, 68,0, 82,78,0, 78,0, +73,76,76,0, 69,88,0, 75,0, 84,0, 70,73,82,83,84,0, +67,76,73,66,0, 68,85,76,69,0, 70,73,82,83,84,0, 77,69,0, +80,65,71,69,0, 82,71,0, 71,69,0, 73,78,84,70,0, 66,76,73,67,0, +75,76,78,0, 77,0, 88,84,0, 84,76,69,0, 79,82,68,0, 42,0, +78,68,0, 81,0, 79,68,0, 69,0, 79,82,0, 39,0, 42,0, 79,68,0, +69,0, 79,82,0, 92,39,0, 47,0, 69,73,76,0, 69,70,73,78,69,68,0, +79,79,82,0, 73,71,72,0, 80,0, 79,84,0, 81,82,84,0, 10,0, +92,39,0, 69,73,76,0, 69,70,73,78,69,68,0, 79,79,82,0, 73,71,72,0, +80,0, 81,82,84,0, 92,39,0, 47,0, 69,73,76,0, +69,70,73,78,69,68,0, 79,79,82,0, 73,71,72,0, 80,0, 81,82,84,0, +10,0, 42,0, 78,68,0, 81,0, 79,68,0, 69,0, 82,0, 79,82,0, +78,68,0, 81,0, 69,0, 82,0, 79,82,0, 78,68,0, 81,0, 69,0, +82,0, 79,82,0, 81,0, 69,0, 82,0, 79,82,0, 81,0, 69,0, 82,0, +61,0, 81,0, 69,0, 78,68,0, 81,0, 79,68,0, 69,0, 82,0, +79,82,0, 10,0, 61,0, 61,0, 83,69,71,0, 79,67,75,0, 84,69,0, +83,69,71,0, 71,0, 72,79,0, 68,0, 85,0, 82,78,0, 78,0, +73,76,76,0, 69,88,0, 75,0, 84,0, 70,73,82,83,84,0, +67,76,73,66,0, 68,85,76,69,0, 70,73,82,83,84,0, 77,69,0, +80,65,71,69,0, 82,71,0, 71,69,0, 73,78,84,70,0, 66,76,73,67,0, +84,0, 75,76,78,0, 77,0, 88,84,0, 84,76,69,0, 79,82,68,0, +92,39,0, 73,0, 72,76,0, 72,82,0, 76,76,0, 76,0, 80,0, 85,66,0, +73,0, 66,67,0, 73,0, 73,0, 86,0, 73,0, 79,80,0, 84,0, +72,76,0, 80,0, 83,72,0, 69,76,0, 84,0, 77,0, 69,0, 76,0, +77,0, 72,76,0, 72,71,0, 72,76,0, 10,0, 92,39,0, 72,76,41,0, +73,76,0, 70,73,78,69,68,0, 79,79,82,0, 71,72,0, 80,0, 79,84,0, +81,82,84,0, 10,0, }; #define AG_TCV(x) (((int)(x) >= -1 && (int)(x) <= 255) ? ag_tcv[(x) + 1] : 0) static const unsigned short ag_tcv[] = { - 26, 26,473,473,473,473,473,473,473,473, 1,289,473,473,473,473,473,473, - 473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, 1,362,474, - 473,475,359,349,476,366,365,357,355,288,356,477,358,478,479,479,479,479, - 479,479,479,480,480,473,287,481,473,482,473,473,483,483,483,483,483,483, - 484,484,484,484,484,484,484,485,484,484,484,486,484,487,484,484,484,488, - 484,484,473,489,473,347,490,473,483,483,483,483,483,483,484,484,484,484, - 484,484,484,485,484,484,484,486,484,487,484,484,484,488,484,484,473,345, - 473,364,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, - 491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, - 491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, - 491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, - 491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, - 491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, - 491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, - 491,491,491,491,491 + 38, 38,620,620,620,620,620,620,620,620, 1,392,620,620,620,620,620,620, + 620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, 1,490,621, + 622,623,487,477,624,422,420,485,483,445,484,398,486,625,626,627,627,628, + 628,628,628,629,629,620,394,630,620,631,632,633,634,635,634,636,634,637, + 638,639,638,638,638,638,638,640,638,638,638,641,638,642,638,638,638,643, + 638,638,620,644,620,475,645,633,634,635,634,636,634,637,638,639,638,638, + 638,638,638,640,638,638,638,641,638,642,638,638,638,643,638,638,632,473, + 632,492,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646, + 646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646, + 646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646, + 646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646, + 646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646, + 646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646, + 646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646, + 646,646,646,646,646 }; #ifndef SYNTAX_ERROR @@ -2057,3506 +2032,3917 @@ static void ag_undo(void) { static const unsigned short ag_tstt[] = { -490,488,487,486,485,484,483,475,472,471,470,469,468,467,466,465,464,463,462, - 461,460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444, - 443,442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426, - 425,424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408, - 407,406,405,404,403,401,400,399,398,397,396,395,394,393,392,391,390,389, - 388,387,386,385,384,383,382,380,330,329,328,327,325,323,322,321,320,319, - 318,317,316,315,314,313,312,311,310,309,308,305,304,303,302,301,300,297, - 295,292,289,288,287,286,86,35,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,1,0,37, -35,1,0,2,283, -490,488,487,486,485,484,483,475,472,471,470,469,468,467,466,465,464,463,462, - 461,460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444, - 443,442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426, - 425,424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408, - 407,406,405,404,403,401,400,399,398,397,396,395,394,393,392,391,390,389, - 388,387,386,385,384,383,382,380,330,329,328,327,325,323,322,321,320,319, - 318,317,316,315,314,313,312,311,310,309,308,305,304,303,302,301,300,297, - 295,292,289,288,287,286,86,43,35,1,0,22,23,24,25,39,40, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,38,1,0, +645,643,642,641,640,639,638,637,636,635,634,632,623,406,402,401,398,396,394, + 393,392,132,131,1,0,51,52, 1,0, -289,0,42, -490,488,487,486,485,484,483,475,472,471,470,469,468,467,466,465,464,463,462, - 461,460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444, - 443,442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426, - 425,424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408, - 407,406,405,404,403,401,400,399,398,397,396,395,394,393,392,391,390,389, - 388,387,386,385,384,383,382,380,330,329,328,327,325,323,322,321,320,319, - 318,317,316,315,314,313,312,311,310,309,308,305,304,303,302,301,300,297, - 295,292,289,288,287,286,86,35,0,2,4,12,27,28,32,33,34,41,44,45,46,49,50, - 51,52,53,54,58,85,290,299, -490,488,487,486,485,484,483,475,472,471,470,469,468,467,466,465,464,463,462, - 461,460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444, - 443,442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426, - 425,424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408, - 407,406,405,404,403,401,400,399,398,397,396,395,394,393,392,391,390,389, - 388,387,386,385,384,383,382,380,330,329,328,327,325,323,322,321,320,319, - 318,317,316,315,314,313,312,311,310,309,308,305,304,303,302,301,300,297, - 295,292,289,288,287,286,86,43,35,26,1,0,23,24,39,40, -490,488,487,486,485,484,483,475,472,471,470,469,468,467,466,465,464,463,462, - 461,460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444, - 443,442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426, - 425,424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408, - 407,406,405,404,403,401,400,399,398,397,396,395,394,393,392,391,390,389, - 388,387,386,385,384,383,382,380,330,329,328,327,325,323,322,321,320,319, - 318,317,316,315,314,313,312,311,310,309,308,305,304,303,302,301,300,297, - 295,292,289,288,287,286,86,35,26,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 373,372,371,370,369,368,367,366,365,364,363,362,359,358,357,356,355,349, - 347,345,289,288,287,169,86,35,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,1,0,30,31, - 33,34,90,91,93,95,96,121,124,127,135,136,138,140,141,144,146,149,150, - 163,164,165,166,168,171,172,173,175,278,279,280,281,282, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,1,0,30,31, - 33,34,90,91,93,95,96,121,124,127,135,136,138,140,141,144,146,149,150, - 163,164,165,166,168,171,172,173,175,278,279,280,281,282, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,1,0,30,31, - 33,34,90,91,93,95,96,121,124,127,135,136,138,140,141,144,146,149,150, - 163,164,165,166,168,171,172,173,175,278,279,280,281,282, -490,488,487,486,485,484,483,480,479,478,475,98,35,1,0,2,88,283,284,285, -490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, -289,288,287,286,35,1,0,2,283,284,285, -289,288,287,286,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, -298,296,35,1,0,2,283,284,285, -481,474,35,1,0,2,283,284,285, -490,489,488,487,486,485,484,483,481,480,479,478,477,474,358,35,1,0,2,283, - 284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 330,329,328,327,325,323,322,321,320,319,318,317,316,315,314,313,312,311, - 310,309,308,307,306,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 330,329,328,327,325,323,322,321,320,319,318,317,316,315,314,313,312,311, - 310,309,308,0,59,60,61,62,63,64,66,67,69,70,71,72,73,74,76,77,78,79,80, - 81,82,83,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199, - 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235, - 236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253, - 254,255,256,257,258,259,260,262,263,264,265,266,267,268,269,270,271,272, - 273,274,275,276,277, -314,313,312,307,306,0,55,57,63,64,66, -490,488,487,486,485,484,483,475,86,0,4,85,299, -490,488,487,486,485,484,483,475,86,0,4,85,299, -490,488,487,486,485,484,483,475,86,0,4,85,299, -490,488,487,486,485,484,483,475,86,0,4,85,299, -298,296,0,47,48, -481,474,0,11,13,14,15,291,293, -490,489,488,487,486,485,484,483,481,480,479,478,477,474,358,0,11,13,14,15, - 20,291,293,294, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 330,329,328,327,325,323,322,321,320,319,318,317,316,315,314,313,312,311, - 310,309,308,307,306,289,288,287,286,0,55,57, -289,288,287,286,0,27,28,33,34,42, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 373,372,371,370,369,368,367,366,365,364,362,359,358,357,356,355,349,347, - 345,289,288,287,169,86,35,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 373,372,371,370,369,368,367,366,365,364,363,362,359,358,357,356,355,349, - 347,345,289,288,287,169,86,35,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 373,372,371,370,369,368,367,366,365,364,363,362,359,358,357,356,355,349, - 347,345,289,288,287,169,86,35,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455, - 454,453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437, - 436,435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419, - 418,417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400, - 399,398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382, - 380,366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,286,35, - 1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455, - 454,453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437, - 436,435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419, - 418,417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400, - 399,398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382, - 380,366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,286,35, - 1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 373,372,371,370,369,368,367,366,365,364,362,359,358,357,356,355,349,347, - 345,289,288,287,169,86,35,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 373,372,371,370,369,368,367,366,365,364,363,362,359,358,357,356,355,349, - 347,345,289,288,287,169,86,35,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 373,372,371,370,369,368,367,366,365,364,363,362,359,358,357,356,355,349, - 347,345,289,288,287,169,86,35,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 373,372,371,370,369,368,367,366,365,364,362,359,358,357,356,355,349,347, - 345,289,288,287,169,86,35,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455, - 454,453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437, - 436,435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419, - 418,417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400, - 399,398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382, - 380,366,365,364,362,361,360,359,358,357,356,355,354,353,352,351,350,349, - 348,347,346,345,344,343,342,341,340,339,338,337,336,335,334,333,332,331, - 289,288,287,286,35,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 373,372,371,370,369,368,367,366,365,364,363,362,359,358,357,356,355,349, - 347,345,289,288,287,169,86,35,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 373,372,371,370,369,368,367,366,365,364,363,362,359,358,357,356,355,349, - 347,345,289,288,287,169,86,35,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 373,372,371,370,369,368,367,366,365,364,362,359,358,357,356,355,349,347, - 345,289,288,287,169,86,35,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455, - 454,453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437, - 436,435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419, - 418,417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400, - 399,398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382, - 380,373,372,371,370,369,368,367,366,365,364,362,359,358,357,356,355,349, - 347,345,289,288,287,286,169,86,35,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,35,1,0,2, - 283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,288,287,1,0,33,34,90,91, - 93,95,96,121,124,127,135,136,138,140,141,144,146,149,150,163,164,165, - 166,168,171,172,173,175,278,279,280,281,282, -289,0,32, -289,0,32, -289,0,32, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -376,375,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -479,478,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -379,378,377,376,375,35,1,0,2,283,284,285, -379,378,377,376,375,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, -379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, -377,376,375,181,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -376,375,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -377,376,375,181,35,1,0,2,283,284,285, -379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -377,376,375,181,35,1,0,2,283,284,285, -379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, -377,376,375,181,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, -379,377,376,375,179,178,177,176,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -379,377,376,375,179,178,177,176,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -379,377,376,375,179,178,177,176,1,0,39,40, -376,375,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -379,377,376,375,179,178,177,176,1,0,39,40, -479,478,1,0,39,40, -379,378,377,376,375,1,0,39,40, -379,378,377,376,375,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -379,377,376,375,179,178,177,176,1,0,39,40, -379,377,376,375,179,178,177,176,1,0,39,40, -379,377,376,375,179,178,177,176,1,0,39,40, -377,376,375,181,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -376,375,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -377,376,375,181,1,0,39,40, -379,377,376,375,179,178,177,176,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -377,376,375,181,1,0,39,40, -379,377,376,375,179,178,177,176,1,0,39,40, -377,376,375,181,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -379,377,376,375,179,178,177,176,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -379,377,376,375,179,178,177,176,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -379,377,376,375,179,178,177,176,1,0,39,40, -379,377,376,375,179,178,177,176,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,1,0,39,40, -490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,475,86,0,4,85,299, -490,489,488,487,486,485,484,483,480,479,478,477,358,35,1,0,2,283,284,285, -490,489,488,487,486,485,484,483,480,479,478,477,358,0,20,294, -289,288,287,286,35,1,0,2,283,284,285, -289,288,287,286,35,1,0,2,283,284,285, -289,288,287,286,1,0,39, -476,474,35,1,0,2,283,284,285, -476,474,0,11,13,19,21,291,324, -289,288,287,286,35,1,0,2,283,284,285, -289,288,287,286,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,75,85,99,119, - 120,123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155, - 156,157,299,326,374, -490,488,487,486,485,484,483,475,289,288,287,286,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,475,289,288,287,286,86,0,4,85,299, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,475,86,0,4,85,299, -490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,475,86,0,4,68,85,299, -490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,475,86,0,4,68,85,299, -490,488,487,486,485,484,483,475,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,475,86,0,4,68,85,299, -490,488,487,486,485,484,483,480,479,478,477,476,475,474,373,372,371,370,369, - 368,367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,474,373,372,371,370,369, - 368,367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,11,13,16,18,19,21, - 56,65,85,119,120,123,126,129,134,137,139,144,145,146,147,148,149,151, - 152,153,154,155,156,157,291,299,324,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,474,373,372,371,370,369, - 368,367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,474,373,372,371,370,369, - 368,367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,11,13,16,18,19,21, - 56,65,85,119,120,123,126,129,134,137,139,144,145,146,147,148,149,151, - 152,153,154,155,156,157,291,299,324,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -289,288,287,286,35,1,0,2,283,284,285, -289,288,287,286,35,1,0,2,283,284,285, -289,288,287,286,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,474,373,372,371,370,369, - 368,367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,11,13,16,18,19,21, - 56,65,85,119,120,123,126,129,134,137,139,144,145,146,147,148,149,151, - 152,153,154,155,156,157,291,299,324,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,474,373,372,371,370,369, - 368,367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,11,13,16,18,19,21, - 56,65,85,119,120,123,126,129,134,137,139,144,145,146,147,148,149,151, - 152,153,154,155,156,157,291,299,324,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,475,365,362,361,359,358,357,356,355, - 353,351,349,347,345,344,342,340,338,336,334,333,331,289,288,287,286,35, - 1,0,2,88,283,284,285, -289,288,287,286,35,1,0,2,283,284,285, -289,288,287,286,35,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,473,366, - 365,364,362,359,358,357,356,355,349,347,345,288,287,1,0, -289,288,287,286,35,1,0,2,283,284,285, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,288,287,1,0, -331,289,288,287,286,35,1,0,2,283,284,285, -490,489,488,487,486,485,484,483,480,479,478,477,358,289,288,287,35,1,0,2, - 283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -379,377,376,375,179,178,177,176,0,5,381, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -379,377,376,375,179,178,177,176,0,5,381, -376,375,0,159,161,184, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -379,377,376,375,179,178,177,176,0,5,381, -479,478,0,165,279, -379,378,377,376,375,0,158,159,161,180,182,183, -379,378,377,376,375,0,158,159,161,180,182,183, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -379,377,376,375,179,178,177,176,0,5,381, -379,377,376,375,179,178,177,176,0,5,381, -379,377,376,375,179,178,177,176,0,5,381, -377,376,375,181,0,6,402, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -376,375,0,159,161,184, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -377,376,375,181,0,6,402, -379,377,376,375,179,178,177,176,0,5,381, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -377,376,375,181,0,6,402, -379,377,376,375,179,178,177,176,0,5,381, -377,376,375,181,0,6,402, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -379,377,376,375,179,178,177,176,0,5,381, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -379,377,376,375,179,178,177,176,0,5,381, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -379,377,376,375,179,178,177,176,0,5,381, -379,377,376,375,179,178,177,176,0,5,381, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,0,144,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199, - 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235, - 236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253, - 254,255,256,257,258,259,260,262,263,264,265,266,267,268,269,270,271,272, - 273,274,275,276,277, -480,479,478,476,356,355,169,1,0,3,7,8,16,18,326, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,475,474,473,366,365, - 364,362,359,358,357,356,355,349,347,345,289,288,287,174,1,0,17, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,366, - 365,364,362,359,358,357,356,355,349,347,345,289,288,287,174,1,0,17, -331,289,288,287,286,35,1,0,2,283,284,285, -480,479,478,0, -490,488,483,480,479,478,477,475,472,471,470,469,468,467,466,465,464,463,462, - 461,460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444, - 443,442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426, - 425,424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408, - 407,406,405,404,403,401,400,399,398,397,396,395,394,393,392,391,390,389, - 388,387,386,385,384,383,382,380,377,376,375,365,362,361,360,359,358,357, - 356,355,354,353,352,351,350,349,348,347,346,345,344,343,342,341,340,339, - 338,337,336,335,334,333,332,331,289,288,287,286,160,35,1,0, -480,479,478,0, -480,479,478,0, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,475,474,473,366,365, - 364,362,359,358,357,356,355,349,347,345,289,288,287,174,1,0,17, -480,479,478,0, -483,480,479,478,377,0, -483,480,479,478,472,471,470,469,468,467,466,465,464,463,462,461,460,459,458, - 457,456,455,454,453,452,451,450,449,448,447,446,445,444,443,442,441,440, - 439,438,437,436,435,434,433,432,431,430,429,428,427,426,425,424,423,422, - 421,420,419,418,417,416,415,414,413,412,411,410,409,408,407,406,405,404, - 403,401,400,399,398,397,396,395,394,393,392,391,390,389,388,387,386,385, - 384,383,382,380,365,362,361,360,359,358,357,356,355,354,353,352,351,350, - 349,348,347,346,345,344,343,342,341,340,339,338,337,336,335,334,333,332, - 331,289,288,287,286,35,1,0, -490,483,480,479,478,477,475,472,471,470,469,468,467,466,465,464,463,462,461, - 460,459,458,457,456,455,454,453,452,451,450,449,448,447,446,445,444,443, - 442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427,426,425, - 424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,377,376, - 375,365,362,361,360,359,358,357,356,355,354,353,352,351,349,348,347,346, - 345,344,343,342,341,340,339,338,337,336,335,334,333,331,289,288,287,286, - 160,35,1,0, -366,35,1,0,2,283,284,285, -366,35,1,0,2,283,284,285, -366,35,1,0,2,283,284,285, -366,35,1,0,2,283,284,285, -366,35,1,0,2,283,284,285, -366,35,1,0,2,283,284,285, -366,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 365,362,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346, - 345,344,343,342,341,340,339,338,337,336,335,334,333,332,331,289,288,287, - 286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 365,362,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346, - 345,344,343,342,341,340,339,338,337,336,335,334,333,332,331,289,288,287, - 286,35,1,0,2,283,284,285, -366,0,149, -366,0,149, -366,0,149, -366,0,149, -366,0,149, -366,0,149, -366,0,149, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,356,355,169,86,0,3,4,7,8,9,10,16,18,85,139,147,148,149,151,152, - 153,154,155,156,157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,356,355,169,86,0,3,4,7,8,9,10,16,18,85,139,147,148,149,151,152, - 153,154,155,156,157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,356,355,169,86,0,3,4,7,8,9,10,16,18,85,139,147,148,149,151,152, - 153,154,155,156,157,299,326,374, -361,360,359,358,357,0,138,140,141,142,143, -356,355,0,135,136, -354,353,352,351,0,130,131,132,133, -350,349,0,127,128, -348,347,0,124,125, -346,345,0,121,122, -344,343,342,341,340,339,338,337,336,335,334,333,332,289,288,287,286,1,0,100, - 101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -289,288,287,286,1,0,39,40, -331,289,288,287,286,1,0,39,40, -331,289,288,287,286,1,0,39,40, -331,289,288,287,286,1,0,39,40, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,475,474,473,366,365, - 364,362,359,358,357,356,355,349,347,345,289,288,287,174,1,0,17, -331,289,288,287,286,1,0,39,40, -331,289,288,287,286,1,0,39,40, -331,289,288,287,286,1,0,39,40, -331,289,288,287,286,1,0,39,40, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,1,0, -491,490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473, - 366,365,364,362,359,358,357,356,355,349,347,345,289,288,287,1,0, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,331,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -331,1,0,39,40, -331,1,0,39,40, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 362,289,288,287,286,35,1,0,2,283,284,285, -288,1,0,39,40, -490,483,480,479,478,475,377,376,375,289,288,287,286,160,35,1,0, -489,487,486,485,478,476,0, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,475,474,473,366,365, - 364,362,359,358,357,356,355,349,347,345,289,288,287,174,1,0,17, -483,480,479,478,0, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,366, - 365,364,362,359,358,357,356,355,349,347,345,289,288,287,174,1,0,17, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -365,0,150, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,35,1,0,2,283,284,285, -331,0,84, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,366, - 365,364,362,359,358,357,356,355,349,347,345,289,288,287,174,1,0,17, -331,289,288,287,286,0,84, -331,289,288,287,286,0,84, -331,289,288,287,286,0,84, -331,289,288,287,286,0,84, -331,0,84, -331,0,84, -288,0,34, -476,0, -365,0,150, -365,0,150, -365,0,150, -365,0,150, -365,0,150, -365,0,150, -365,0,150, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 365,362,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346, - 345,344,343,342,341,340,339,338,337,336,335,334,333,332,331,289,288,287, - 286,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,356,355,169,86,0,3,4,7,8,9,10,16,18,85,139,147,148,149,151,152, - 153,154,155,156,157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,356,355,169,86,0,3,4,7,8,9,10,16,18,85,139,147,148,149,151,152, - 153,154,155,156,157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,356,355,169,86,0,3,4,7,8,9,10,16,18,85,139,147,148,149,151,152, - 153,154,155,156,157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,356,355,169,86,0,3,4,7,8,9,10,16,18,85,139,147,148,149,151,152, - 153,154,155,156,157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,356,355,169,86,0,3,4,7,8,9,10,16,18,85,139,147,148,149,151,152, - 153,154,155,156,157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,134,137,139, - 144,145,146,147,148,149,151,152,153,154,155,156,157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,134,137,139, - 144,145,146,147,148,149,151,152,153,154,155,156,157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,129,134,137, - 139,144,145,146,147,148,149,151,152,153,154,155,156,157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,129,134,137, - 139,144,145,146,147,148,149,151,152,153,154,155,156,157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,129,134,137, - 139,144,145,146,147,148,149,151,152,153,154,155,156,157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,129,134,137, - 139,144,145,146,147,148,149,151,152,153,154,155,156,157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,126,129,134, - 137,139,144,145,146,147,148,149,151,152,153,154,155,156,157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,126,129,134, - 137,139,144,145,146,147,148,149,151,152,153,154,155,156,157,299,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,123,126,129, - 134,137,139,144,145,146,147,148,149,151,152,153,154,155,156,157,299,326, - 374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,123,126,129, - 134,137,139,144,145,146,147,148,149,151,152,153,154,155,156,157,299,326, - 374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,120,123,126, - 129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156,157,299, - 326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,85,120,123,126, - 129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156,157,299, - 326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,474,379,377,376,375,373, - 372,371,370,369,368,367,366,364,363,362,356,355,179,178,177,176,169,86, - 35,1,0,2,283,284,285, -490,488,487,486,485,484,483,475,86,1,0,39,40, -490,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,366, - 365,364,362,359,358,357,356,355,349,347,345,289,288,287,174,1,0, -490,488,487,486,485,484,483,480,479,478,477,476,475,474,373,372,371,370,369, - 368,367,366,364,363,362,356,355,169,86,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -379,377,376,375,179,178,177,176,1,0,39,40, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,1,0,39,40, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 365,362,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346, - 345,344,343,342,341,340,339,338,337,336,335,334,333,332,331,289,288,287, - 286,1,0,138,140,141,142,143, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 365,362,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346, - 345,344,343,342,341,340,339,338,337,336,335,334,333,332,331,289,288,287, - 286,1,0,138,140,141,142,143, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 365,362,356,355,354,353,352,351,350,349,348,347,346,345,344,343,342,341, - 340,339,338,337,336,335,334,333,332,331,289,288,287,286,1,0,135,136, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 365,362,356,355,354,353,352,351,350,349,348,347,346,345,344,343,342,341, - 340,339,338,337,336,335,334,333,332,331,289,288,287,286,1,0,135,136, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 365,362,356,355,354,353,352,351,350,349,348,347,346,345,344,343,342,341, - 340,339,338,337,336,335,334,333,332,331,289,288,287,286,1,0,135,136, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 365,362,356,355,354,353,352,351,350,349,348,347,346,345,344,343,342,341, - 340,339,338,337,336,335,334,333,332,331,289,288,287,286,1,0,135,136, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 365,362,354,353,352,351,350,349,348,347,346,345,344,343,342,341,340,339, - 338,337,336,335,334,333,332,331,289,288,287,286,1,0,130,131,132,133, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 365,362,354,353,352,351,350,349,348,347,346,345,344,343,342,341,340,339, - 338,337,336,335,334,333,332,331,289,288,287,286,1,0,130,131,132,133, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 365,362,350,349,348,347,346,345,344,343,342,341,340,339,338,337,336,335, - 334,333,332,331,289,288,287,286,1,0,127,128, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 365,362,350,349,348,347,346,345,344,343,342,341,340,339,338,337,336,335, - 334,333,332,331,289,288,287,286,1,0,127,128, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 365,362,348,347,346,345,344,343,342,341,340,339,338,337,336,335,334,333, - 332,331,289,288,287,286,1,0,124,125, -472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, - 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,423,422,421,420,419,418, - 417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,401,400,399, - 398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,380, - 365,362,348,347,346,345,344,343,342,341,340,339,338,337,336,335,334,333, - 332,331,289,288,287,286,1,0,124,125, -490,488,487,486,485,484,483,475,86,0,4,85,299, -490,488,487,486,485,484,483,480,479,478,477,476,475,474,373,372,371,370,369, - 368,367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,11,13,16,18,19,21, - 56,85,119,120,123,126,129,134,137,139,144,145,146,147,148,149,151,152, - 153,154,155,156,157,291,299,324,326,374, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, -379,377,376,375,179,178,177,176,0,5,381, -490,488,487,486,485,484,483,480,479,478,477,476,475,373,372,371,370,369,368, - 367,366,364,363,362,356,355,169,86,0,3,4,7,8,9,10,16,18,56,85,119,120, - 123,126,129,134,137,139,144,145,146,147,148,149,151,152,153,154,155,156, - 157,299,326,374, +645,643,642,641,640,639,638,637,636,635,634,632,623,406,398,396,394,393,392, + 132,131,63,1,0,11,34,35,36,37,51,52,53,64,65,130,397,410, +419,418,417,416,415,414,413,412,411,408,401,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,632,629,628,627,626,625,623,428, + 398,396,394,393,392,158,132,1,0,135, +419,418,417,416,415,414,413,412,411,408,401,0,59,66,67,70,72,74,75,76,77,78, + 79,80, +645,643,642,641,640,639,638,637,636,635,634,632,623,619,618,617,616,615,614, + 613,612,611,610,609,608,607,606,605,604,603,602,601,600,599,598,597,596, + 595,594,593,592,591,590,589,588,587,586,585,584,583,582,581,580,579,578, + 577,576,575,574,573,572,571,570,569,568,567,565,564,563,562,561,560,559, + 558,557,556,555,553,552,551,550,549,548,547,546,545,544,543,542,541,540, + 539,538,537,536,535,534,533,532,531,530,529,528,527,526,525,524,523,522, + 521,520,519,518,517,516,515,514,513,512,511,510,509,508,456,455,454,453, + 452,451,449,448,447,446,444,443,442,441,440,439,438,437,436,435,434,433, + 432,431,430,429,428,427,426,425,424,416,415,412,409,407,400,399,398,396, + 394,393,392,132,131,1,0,51,52, +392,0,45, +402,401,398,396,394,393,392,0,39,40,41,45,46,47,49,54,55, +645,643,642,641,640,639,638,637,636,635,634,632,623,619,618,617,616,615,614, + 613,612,611,610,609,608,607,606,605,604,603,602,601,600,599,598,597,596, + 595,594,593,592,591,590,589,588,587,586,585,584,583,582,581,580,579,578, + 577,576,575,574,573,572,571,570,569,568,567,565,564,563,562,561,560,559, + 558,557,556,555,553,552,551,550,549,548,547,546,545,544,543,542,541,540, + 539,538,537,536,535,534,533,532,531,530,529,528,527,526,525,524,523,522, + 521,520,519,518,517,516,515,514,513,512,511,510,509,508,456,455,454,453, + 452,451,449,448,447,446,444,443,442,441,440,439,438,437,436,435,434,433, + 432,431,430,429,428,427,426,425,424,416,415,412,409,407,400,399,398,396, + 394,393,392,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,632,623,619,618,617,616,615,614, + 613,612,611,610,609,608,607,606,605,604,603,602,601,600,599,598,597,596, + 595,594,593,592,591,590,589,588,587,586,585,584,583,582,581,580,579,578, + 577,576,575,574,573,572,571,570,569,568,567,565,564,563,562,561,560,559, + 558,557,556,555,553,552,551,550,549,548,547,546,545,544,543,542,541,540, + 539,538,537,536,535,534,533,532,531,530,529,528,527,526,525,524,523,522, + 521,520,519,518,517,516,515,514,513,512,511,510,509,508,456,455,454,453, + 452,451,449,448,447,446,444,443,442,441,440,439,438,437,436,435,434,433, + 432,431,430,429,428,427,426,425,424,416,415,412,409,407,402,401,398,396, + 394,393,392,132,131,1,0,21,30,31,32,33,54,55,62,72,76,77,86,91,130,249, + 250,251,252,253,254,255,256,257,259,260,261,262,263,264,265,266,267,268, + 269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286, + 287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304, + 305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322, + 323,324,325,326,327,328,330,331,332,333,334,335,336,337,338,339,340,341, + 342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359, + 360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377, + 378,379,380,410, +645,643,642,641,640,639,638,637,636,635,634,632,623,406,398,396,394,393,392, + 132,131,63,38,1,0,11,35,36,51,52,53,64,65,130,397,410, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, +621,1,0,51,52, +396,394,393,392,1,0,51,52, +396,394,393,392,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, +409,407,1,0,51,52, +645,644,643,642,641,640,639,638,637,636,635,634,630,629,628,627,626,625,621, + 486,398,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,81,130,410, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,130,410, +621,0,10,12,403, +396,394,393,392,1,0,51,52, +396,394,393,392,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,130,410, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,73,83,86, + 130,160,191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211, + 212,213,214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,73,83,86, + 130,160,191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211, + 212,213,214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,130,410, +409,407,0,68,69, +630,621,0,10,12,13,14,403,404, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,422,420,406,402,401,398,396,395,394,393,392,132,131,38,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 456,455,454,453,452,451,449,448,447,446,445,444,443,442,441,440,439,438, + 437,436,435,434,433,432,431,430,429,428,427,426,425,424,423,422,420,409, + 407,402,401,400,399,398,396,395,394,393,392,1,0,51,52, +402,401,0,59,60,61, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,422,420,398,396,395,394,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,422,420,398,394,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,422,420,398,396,395,394,392,1,0,40,45,46,47,48,49,54,83,85,119,137, + 138,140,142,143,144,145,146,147,151,154,155,180,182,184,190,191,192,194, + 195,198,200,215,219,220,224,381,382,383,384,385,386,387,388,389,390,391, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,422,420,398,394,392,1,0,43,44,46,54,83,85,119,137,138,140,142,143, + 144,145,146,147,151,154,155,180,182,184,190,191,192,194,195,198,200,215, + 219,220,224,381,382,383,384,385,386,387,388,389,390,391, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,422,420,398,394,392,1,0,43,44,46,54,83,85,119,137,138,140,142,143, + 144,145,146,147,151,154,155,180,182,184,190,191,192,194,195,198,200,215, + 219,220,224,381,382,383,384,385,386,387,388,389,390,391, +645,643,642,641,640,639,638,637,636,635,634,632,623,619,618,617,616,615,614, + 613,612,611,610,609,608,607,606,605,604,603,602,601,600,599,598,597,596, + 595,594,593,592,591,590,589,588,587,586,585,584,583,582,581,580,579,578, + 577,576,575,574,573,572,571,570,569,568,567,565,564,563,562,561,560,559, + 558,557,556,555,553,552,551,550,549,548,547,546,545,544,543,542,541,540, + 539,538,537,536,535,534,533,532,531,530,529,528,527,526,525,524,523,522, + 521,520,519,518,517,516,515,514,513,512,511,510,509,508,456,455,454,453, + 452,451,449,448,447,446,444,443,442,441,440,439,438,437,436,435,434,433, + 432,431,430,429,428,427,426,425,424,416,415,412,409,407,400,399,398,396, + 394,393,392,132,131,0,21,30,31,32,33,39,40,41,45,46,47,49,54,55,62,72, + 76,77,86,91,130,249,250,251,252,253,254,255,256,257,259,260,261,262,263, + 264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281, + 282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299, + 300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317, + 318,319,320,321,322,323,324,325,326,327,328,330,331,332,333,334,335,336, + 337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354, + 355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372, + 373,374,375,376,377,378,379,380,410, +459,456,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +245,243,241,239,233,231,229,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +628,627,626,625,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +245,243,241,239,233,231,229,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +506,505,243,241,239,233,231,229,1,0,51,52, +506,505,243,241,239,233,231,229,1,0,51,52, +241,239,231,229,1,0,51,52, +241,239,231,229,1,0,51,52, +245,243,241,239,233,231,229,1,0,51,52, +245,243,241,239,233,231,229,1,0,51,52, +245,243,241,239,233,231,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +628,627,626,625,1,0,51,52, +445,1,0,51,52, +445,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +506,505,243,241,239,233,231,229,1,0,51,52, +506,505,243,241,239,233,231,229,1,0,51,52, +241,239,231,229,1,0,51,52, +241,239,231,229,1,0,51,52, +245,243,241,239,233,231,229,1,0,51,52, +245,243,241,239,233,231,229,1,0,51,52, +245,243,241,239,233,231,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +506,236,235,234,233,232,231,230,229,1,0,51,52, +646,645,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,621,620,507,492,490,489,487,486,485,484,483,481,479,477, + 475,473,472,470,468,466,464,462,461,458,445,422,420,398,396,394,393,392, + 1,0,51,52,135, +507,396,394,393,392,1,0,51,52, +507,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,460,458,422,420,396,394,393, + 392,1,0,83, +396,394,393,392,1,0,51, +507,0,258, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,73,83,86, + 130,160,191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211, + 212,213,214,410,457,504, +456,455,454,453,452,451,449,448,447,446,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,409,407,0,68,69,92,93, + 94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,111,112,113, + 114,115,116,117,118,120,121,122,123,124,125,126,127,128, +396,394,393,392,1,0,51,52, +646,645,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,621,620,492,490,487,486,485,484,483,477,475,473,445,422, + 420,398,394,1,0,83, +646,645,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,621,620,492,490,487,486,485,484,483,477,475,473,445,422, + 420,398,394,1,0,51,52, +396,394,393,392,1,0,51,52, +645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445, + 422,420,398,394,392,1,0,139, +458,445,420,396,394,393,392,1,0,51,52, +396,394,393,392,1,0,51,52, +396,394,393,392,0,39,40,41,45,46,47,49, +396,394,393,392,0,39,40,41,45,46,47,49, +396,394,393,392,1,0,51,52, +629,628,627,626,625,0, +628,627,626,625,0, +626,625,0, +645,643,642,641,640,639,638,637,636,635,634,632,629,628,627,626,625,623,507, + 489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,460,458,422,420,398,396,394, + 393,392,1,0, +645,643,639,637,636,635,634,629,628,627,626,625,623,507,489,488,487,486,485, + 484,483,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467, + 466,465,464,463,462,461,460,458,420,398,396,394,393,392,217,216,1,0, +629,628,627,626,625,0, +645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445,422, + 420,398,394,392,228,1,0,16, +629,628,627,626,625,0, +639,637,636,635,634,629,628,627,626,625,0, +628,627,626,625,507,489,488,487,486,485,484,483,482,481,480,479,478,477,476, + 475,474,473,472,471,470,469,468,467,466,465,464,463,462,461,460,458,420, + 396,394,393,392,1,0, +626,625,507,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474, + 473,472,471,470,469,468,467,466,465,464,463,462,461,460,458,420,396,394, + 393,392,1,0, +637,636,635,634,629,628,627,626,625,507,489,488,487,486,485,484,483,482,481, + 480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465,464,463, + 462,461,460,458,420,396,394,393,392,1,0, +645,639,637,636,635,634,629,628,627,626,625,623,507,489,488,487,486,485,484, + 483,482,481,480,479,477,476,475,474,473,472,471,470,469,468,467,466,465, + 464,463,462,461,458,420,398,396,394,393,392,217,216,1,0,218, +422,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +507,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,460,458,420,396,394,393,392, + 1,0,51,52, +507,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,460,458,420,396,394,393,392, + 1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, + 492,491,490,487,486,485,484,483,477,475,473,445,423,422,421,420,398,396, + 395,394,393,392,226,132,131,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +422,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, + 492,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395,394, + 393,392,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, + 492,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395,394, + 393,392,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, + 209,210,211,212,213,214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, + 209,210,211,212,213,214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, + 209,210,211,212,213,214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, + 209,210,211,212,213,214,410,457,504, +507,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,460,458,420,396,394,393,392, + 1,0,51,52, +507,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,460,458,420,394,392,1,0,51, + 52,192,194,195,196,197, +507,484,483,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467, + 466,465,464,463,462,461,460,458,420,396,394,393,392,1,0,51,52,190,191, +507,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465, + 464,463,462,461,460,458,420,396,394,393,392,1,0,51,52,186,187,188,189, +507,478,477,476,475,474,473,472,471,470,469,468,467,466,465,464,463,462,461, + 460,458,420,396,394,393,392,1,0,51,52,184,185, +507,476,475,474,473,472,471,470,469,468,467,466,465,464,463,462,461,460,458, + 420,396,394,393,392,1,0,51,52,182,183, +474,473,0,180,181, +472,471,470,469,468,467,466,465,464,463,462,461,460,396,394,393,392,1,0,161, + 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +396,394,393,392,1,0,51,52, +396,394,393,392,1,0,51,52, +396,394,393,392,1,0,71, +396,394,393,392,1,0,51,52, +396,394,393,392,1,0,51,52, +396,394,393,392,1,0,51,52, +396,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,620,492,490,487,486,485,484,483,477,475,473,445, + 422,420,398,394,1,0, +396,394,393,392,1,0,51,52, +396,394,393,392,1,0,51,52, +396,394,393,392,1,0,51,52, +645,644,643,642,641,640,639,638,637,636,635,634,630,629,628,627,626,625,621, + 486,398,1,0,51,52, +645,644,643,642,641,640,639,638,637,636,635,634,630,629,628,627,626,625,621, + 486,398,0,10,12,13,14,19,403,404,405, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, + 492,491,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395, + 394,393,392,226,132,131,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, + 492,491,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395, + 394,393,392,226,132,131,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,422,420,398,396,395,394,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, + 492,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395,394, + 393,392,226,132,131,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, + 492,491,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395, + 394,393,392,226,132,131,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, + 492,491,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395, + 394,393,392,226,132,131,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, + 492,491,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395, + 394,393,392,226,132,131,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, + 492,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395,394, + 393,392,226,132,131,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,507,492,490,489,488,487,486,485,484,483, + 482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465, + 464,463,462,461,460,458,445,423,422,420,398,396,395,394,393,392,1,0,51, + 52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, + 492,491,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395, + 394,393,392,226,132,131,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, + 492,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395,394, + 393,392,226,132,131,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,422,420,398,396,395,394,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,423,422,420,398,396,395,394,393,392,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,422,420,406,402,401,398,396,395,394,393,392,132,131,38,1,0,51,52, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,422,420,398,394,1,0,46,54,83,85,119,137,138,140,142,143,144,145,146, + 147,151,154,155,180,182,184,190,191,192,194,195,198,200,215,219,220,224, + 381,382,383,384,385,386,387,388,389,390,391, +392,0,45, +392,0,45, +456,455,454,453,452,451,449,448,447,446,444,443,442,441,440,439,438,437,436, + 435,434,433,432,431,430,429,428,427,426,425,424,409,407,400,399,0,56,58, + 68,69,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109, + 111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128, +396,394,393,392,1,0,51,52, +459,456,396,394,393,392,0,22,39,40,41,45,46,47,49,128,159, +506,236,235,234,233,232,231,230,229,0,4,237,554, +245,243,241,239,233,231,229,0,5,240,242,244,566, +628,627,626,625,0,329, +445,0,119, +445,0,119, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +506,505,243,241,239,233,231,229,0,238,240,242,244,246,247, +506,505,243,241,239,233,231,229,0,238,240,242,244,246,247, +241,239,231,229,0,240,242,248, +241,239,231,229,0,240,242,248, +245,243,241,239,233,231,229,0,5,240,242,244,566, +245,243,241,239,233,231,229,0,5,240,242,244,566, +245,243,241,239,233,231,229,0,5,240,242,244,566, +506,236,235,234,233,232,231,230,229,0,4,237,554, +506,236,235,234,233,232,231,230,229,0,4,237,554, +506,236,235,234,233,232,231,230,229,0,4,237,554, +506,236,235,234,233,232,231,230,229,0,4,237,554, +506,236,235,234,233,232,231,230,229,0,4,237,554, +506,236,235,234,233,232,231,230,229,0,4,237,554, +506,236,235,234,233,232,231,230,229,0,4,237,554, +506,236,235,234,233,232,231,230,229,0,4,237,554, +506,236,235,234,233,232,231,230,229,0,4,237,554, +506,236,235,234,233,232,231,230,229,0,4,237,554, +506,236,235,234,233,232,231,230,229,0,4,237,554, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, + 422,398,226,132,131,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27,28, + 29,57,83,86,87,130,191,193,198,199,200,201,202,203,204,205,206,207,208, + 209,210,211,212,213,214,403,410,450,457,504, +633,629,628,627,626,625,624,623,487,484,483,226,1,0,2,6,7,15,17,213,214,457, +619,618,617,616,615,614,613,612,611,610,609,608,607,606,605,604,603,602,601, + 600,599,598,597,596,595,594,593,592,591,590,589,588,587,586,585,584,583, + 582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,565,564, + 563,562,561,560,559,558,557,556,555,553,552,551,550,549,548,547,546,545, + 544,543,542,541,540,539,538,537,536,535,534,533,532,531,530,529,528,527, + 526,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509, + 508,1,0,51,52, +619,618,617,616,615,614,613,612,611,610,609,608,607,606,605,604,603,602,601, + 600,599,598,597,596,595,594,593,592,591,590,589,588,587,586,585,584,583, + 582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,565,564, + 563,562,561,560,559,558,557,556,555,553,552,551,550,549,548,547,546,545, + 544,543,542,541,540,539,538,537,536,535,534,533,532,531,530,529,528,527, + 526,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509, + 508,1,0,51,52, +396,394,393,392,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,130,410, +645,644,643,642,641,640,639,638,637,636,635,634,629,628,627,626,625,486,398, + 1,0,51,52, +645,644,643,642,641,640,639,638,637,636,635,634,629,628,627,626,625,486,398, + 0,19,405, +396,394,393,392,1,0,51,52, +396,394,393,392,1,0,51,52, +624,621,1,0,51,52, +624,621,0,10,12,18,20,403,450, +396,394,393,392,1,0,51,52, +396,394,393,392,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,632,623,396,394,393,392,132,131, + 1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,632,623,396,394,393,392,132,131, + 1,0,21,130,410, +621,1,0,51,52, +621,0,10,12,403, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, + 422,398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, + 422,398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, + 422,398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, + 422,398,226,132,131,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28,29,57, + 83,86,130,191,193,198,199,200,201,202,203,204,205,206,207,208,209,210, + 211,212,213,214,403,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,130,410, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,130,410, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,110,130, + 410, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,110,130, + 410, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,110,130, + 410, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, + 422,398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, + 422,398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, + 422,398,226,132,131,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27,28, + 29,57,83,86,87,130,191,193,198,199,200,201,202,203,204,205,206,207,208, + 209,210,211,212,213,214,403,410,450,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, + 422,398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, + 422,398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, + 422,398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, + 422,398,226,132,131,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27,28, + 29,57,83,86,87,130,191,193,198,199,200,201,202,203,204,205,206,207,208, + 209,210,211,212,213,214,403,410,450,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +396,394,393,392,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +459,456,396,394,393,392,1,0,51,52, +459,456,396,394,393,392,1,0,51,52, +396,394,393,392,0,39,40,41,45,46,47,49, +421,0,84, +646,645,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,621,620,492,490,487,486,485,484,483,477,475,473,445,422, + 420,398,394,0,46,54,82,83,85,119,137,138,142,143,144,145,146,147,151, + 154,155,180,182,184,190,191,192,194,195,198,200,215,219,220,224,381,382, + 384,385,386,387,388,389,390,391, +396,394,393,392,0,39,40,41,45,46,47,49, +644,643,642,641,640,637,635,627,626,625,623,621,392,0,152, +396,394,393,392,0,39,40,41,45,46,47,49, +396,394,393,392,0,39,40,41,45,46,47,49, +637,636,635,634,629,628,627,626,625,0, +644,642,641,640,625,624,0, +645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445, + 422,420,398,394,392,228,1,0,16, +639,637,636,635,634,629,628,627,626,625,507,489,488,487,486,485,484,483,482, + 481,480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465,464, + 463,462,461,460,458,420,396,394,393,392,1,0, +639,637,636,635,634,629,628,627,626,625,507,489,488,487,486,485,484,483,482, + 481,480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465,464, + 463,462,461,460,458,420,396,394,393,392,1,0, +422,0,83, +422,0,83, +422,0,83, +422,0,83, +422,0,83, +422,0,83, +422,0,83, +422,0,83, +422,0,83, +422,0,83, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +629,628,627,626,625,0, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +396,394,393,392,0,39,40,41,45,46,47,49, +396,394,393,392,0,39,40,41,45,46,47,49, +396,394,393,392,0,39,40,41,45,46,47,49, +396,394,393,392,0,39,40,41,45,46,47,49, +396,394,393,392,0,39,40,41,45,46,47,49, +646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, + 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, + 445,422,420,398,394,392,1,0, +396,394,393,392,0,39,40,41,45,46,47,49, +396,394,393,392,0,39,40,41,45,46,47,49, +645,644,643,642,641,640,639,638,637,636,635,634,629,628,627,626,625,486,398, + 394,392,1,0,51,52, +396,394,393,392,1,0,51,52, +396,394,393,392,1,0,51,52, +396,394,393,392,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +396,394,393,392,0,39,40,41,45,46,47,49, +396,394,393,392,1,0,51,52, +396,394,393,392,1,0,51,52, +507,458,445,396,394,393,392,1,0,51,52, +507,445,396,394,393,392,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +507,396,394,393,392,1,0,51,52, +507,396,394,393,392,1,0,51,52, +458,1,0,51,52, +645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445,422, + 420,398,394,392,228,1,0,16, +645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445, + 422,420,398,394,392,228,1,0,16, +458,420,396,394,393,392,1,0,51,52, +458,420,0,85,129, +637,636,635,634,629,628,627,626,625,0, +645,639,637,636,635,634,629,628,627,626,625,623,396,394,393,392,217,216,1,0, + 218, +619,618,617,616,615,614,613,612,611,610,609,608,607,606,605,604,603,602,601, + 600,599,598,597,596,595,594,593,592,591,590,589,588,587,586,585,584,583, + 582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,565,564, + 563,562,561,560,559,558,557,556,555,553,552,551,550,549,548,547,546,545, + 544,543,542,541,540,539,538,537,536,535,534,533,532,531,530,529,528,527, + 526,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509, + 508,0,31,32,249,250,251,252,253,254,255,256,257,259,260,261,262,263,264, + 265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282, + 283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300, + 301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318, + 319,320,321,322,323,324,325,326,327,328,330,331,332,333,334,335,336,337, + 338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355, + 356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373, + 374,375,376,377,378,379,380, +645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445,422, + 420,398,394,392,228,1,0,16, +445,0,119, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, + 422,398,226,132,131,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27,28, + 29,57,83,86,87,130,191,193,198,199,200,201,202,203,204,205,206,207,208, + 209,210,211,212,213,214,403,410,450,457,504, +458,396,394,393,392,1,0,129, +458,396,394,393,392,1,0,129, +458,396,394,393,392,1,0,129, +458,396,394,393,392,1,0,129, +458,396,394,393,392,1,0,129, +420,1,0,51,52, +420,0,85, +646,645,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,621,620,492,490,487,486,485,484,483,477,475,473,445,423, + 422,420,398,394,392,1,0,46,51,52,54,83,85,90,119,137,138,142,143,144, + 145,146,147,151,154,155,180,182,184,190,191,192,194,195,198,200,215,219, + 220,224,381,382,384,385,386,387,388,389,390,391, +637,636,635,634,629,628,627,626,625,0, +629,628,627,626,625,0, +645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445, + 422,420,398,394,392,1,0, +624,0, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +420,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, + 209,210,211,212,213,214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, + 209,210,211,212,213,214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, + 209,210,211,212,213,214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, + 209,210,211,212,213,214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, + 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, + 209,210,211,212,213,214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,25,29,83,86,130,191,193,198,199, + 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,25,29,83,86,130,191,193,198,199, + 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,25,27,29,83,86,130,191,193,198,199, + 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,25,27,29,83,86,130,191,193,198,199, + 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,25,27,29,83,86,130,191,193,198,199, + 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,25,27,29,83,86,130,191,193,198,199, + 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,24,25,27,29,83,86,130,191,193,198, + 199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410,457, + 504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,24,25,27,29,83,86,130,191,193,198, + 199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410,457, + 504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,27,29,83,86,130,191,193, + 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410, + 457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,27,29,83,86,130,191,193, + 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410, + 457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,83,86,130,191, + 193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214, + 410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,83,86,130,191, + 193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214, + 410,457,504, +396,394,393,392,0,39,40,41,45,46,47,49, +396,394,393,392,0,39,40,41,45,46,47,49, +396,394,393,392,0,39,40,41,45,46,47,49, +396,394,393,392,1,0,51,52, +396,394,393,392,1,0,51,52, +396,394,393,392,0,39,40,41,45,46,47,49, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +458,0,129, +645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445, + 422,420,398,394,392,228,1,0,16, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,621,506,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484, + 483,422,398,236,235,234,233,232,231,230,229,226,132,131,1,0,51,52, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, + 422,398,226,132,131,1,0,51,52, +507,0,258, +507,396,394,393,392,1,0,51,52, +645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445,422, + 420,398,394,392,228,1,0,16, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,1,0,51,52, +458,396,394,393,392,1,0,129, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, +646,645,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,621,620,492,490,487,486,485,484,483,477,475,473,445,423, + 422,420,398,396,394,393,392,1,0,51,52, +646,645,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,621,620,492,490,487,486,485,484,483,477,475,473,445,423, + 422,420,398,396,394,393,392,1,0, +396,394,393,392,0,39,40,41,45,46,47,49, +645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445, + 422,420,398,394,392,1,0, +629,628,627,626,625,0, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,3,130,410,502, +420,0,85, +420,0,85, +420,0,85, +420,0,85, +420,0,85, +420,0,85, +420,0,85, +420,0,85, +420,0,85, +420,0,85, +507,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,460,458,420,394,392,1,0,192, + 194,195,196,197, +507,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,460,458,420,394,392,1,0,192, + 194,195,196,197, +507,484,483,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467, + 466,465,464,463,462,461,460,458,420,396,394,393,392,1,0,190,191, +507,484,483,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467, + 466,465,464,463,462,461,460,458,420,396,394,393,392,1,0,190,191, +507,484,483,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467, + 466,465,464,463,462,461,460,458,420,396,394,393,392,1,0,190,191, +507,484,483,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467, + 466,465,464,463,462,461,460,458,420,396,394,393,392,1,0,190,191, +507,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465, + 464,463,462,461,460,458,420,396,394,393,392,1,0,186,187,188,189, +507,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465, + 464,463,462,461,460,458,420,396,394,393,392,1,0,186,187,188,189, +507,478,477,476,475,474,473,472,471,470,469,468,467,466,465,464,463,462,461, + 460,458,420,396,394,393,392,1,0,184,185, +507,478,477,476,475,474,473,472,471,470,469,468,467,466,465,464,463,462,461, + 460,458,420,396,394,393,392,1,0,184,185, +507,476,475,474,473,472,471,470,469,468,467,466,465,464,463,462,461,460,458, + 420,396,394,393,392,1,0,182,183, +507,476,475,474,473,472,471,470,469,468,467,466,465,464,463,462,461,460,458, + 420,396,394,393,392,1,0,182,183, +396,394,393,392,0,39,40,41,45,46,47,49, +396,394,393,392,0,39,40,41,45,46,47,49, +506,236,235,234,233,232,231,230,229,1,0,51,52, +645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445, + 422,420,398,394,392,228,1,0, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, + 422,398,226,132,131,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27,28, + 29,57,83,86,130,191,193,198,199,200,201,202,203,204,205,206,207,208,209, + 210,211,212,213,214,403,410,450,457,504, +645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, + 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, + 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, + 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, + 214,410,457,504, +645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,130,410, +645,643,642,641,640,639,638,637,636,635,634,632,629,628,627,626,625,623,420, + 398,1,0,51,52,135, +420,1,0,51,52, +420,1,0,51,52, +506,236,235,234,233,232,231,230,229,0,4,237,554, +420,0,85, }; -static unsigned const char ag_astt[21732] = { - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,8,7,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,9,5,3,3,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,8,1,7,0,1,1,1,1,1,9,9,9,9,9,9, - 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,3,9,7,9,5,1,7,3,2, - 2,2,2,2,2,2,2,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, +static unsigned const char ag_astt[23459] = { + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,7,1,1,9,5,2,2,2,2,2,2,2,2, + 2,2,2,2,2,1,8,8,8,8,8,2,2,1,1,7,1,0,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5, + 5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,4,4,4,4,2,4,4,7,2,1, + 1,1,1,1,1,1,1,1,1,1,7,1,3,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,7,1,3,1,7,2,8,8,1,1,1,1,1,7,3,3,1,3,1,1,1,1,1,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,1,1,1,1,1,1,1,1,1,3,1,1,1,2,1,7,3,1,1,3,1,3,1,1,1,1,1,1,1, - 1,2,2,1,1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,8,3,1,7, - 3,3,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 8,8,8,8,5,5,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,1,1,8,8,5,5,1,5,5,5,5,2,2, + 9,7,1,1,1,1,1,1,1,2,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,2,2,2,2,2,2,2,2,2,2,1,8,8,8,8,8,2,2,1,3,1,7,1,3,3,1,1,3,1,1,1,1,1,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5, + 1,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, + 5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,7,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,2,7,1,1, + 1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,2, + 2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7, + 1,1,1,1,1,7,1,1,2,2,7,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,5,7,1,1,1,3,5,5, + 5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,7,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,7,3,3,3,1,3,1,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,8,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,8,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,8,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,7,1,2,1,1,3,5,5,5,5,5,5, - 5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1,1,7,1,1,1,3, - 5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,1, - 1,7,1,1,1,3,5,5,1,1,7,1,1,1,3,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 1,1,1,8,8,8,8,1,1,1,1,1,2,2,7,1,1,1,1,1,3,3,1,3,1,1,1,1,1,2,1,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,2,2,2,1,1,1,1,1,1,1,1, - 1,1,2,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,2,2, - 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,2,1,1,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,1,2,1,1,1,2,2,2,1,1,2,1,1,2,1,1,2,1,1,1,1,1,7,1,1,1, - 1,1,2,2,2,2,2,2,2,2,2,7,2,1,1,2,2,2,2,2,2,2,2,2,7,2,1,1,2,2,2,2,2,2,2,2,2, - 7,2,1,1,2,2,2,2,2,2,2,2,2,7,2,1,1,1,1,7,2,2,2,2,7,2,1,2,1,1,1,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,7,2,1,2,1,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,5,5,5,5,7,1,1,1,1,1,1,7,3,1,1,1, - 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5, - 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7, - 1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1, - 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1, - 1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,5,3,3,3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,7,3,3,7,3,3,7,3,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5, - 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,1, - 5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7, - 1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1, + 3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5, - 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1, + 3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5, + 5,7,1,3,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, + 5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1, + 7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, + 1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, + 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, + 1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8, + 8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, + 1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, + 8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, + 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, + 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,5,2,2,2,2,2,2,2,2,2,2,2,5,2, + 5,5,2,2,2,2,2,5,2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,2, + 5,5,5,5,1,7,1,3,2,5,5,5,5,5,1,7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,1,4,4,4,4,4,4,7,1,4,4,4,4,1,7,1,1,5,1,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, + 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,7,2,2,2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,2,2, + 1,1,2,8,8,8,8,1,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,1,4,4,4,4,7,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,2,1,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,7,2,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1, + 1,7,2,2,1,2,1,1,1,8,8,8,8,1,7,1,1,2,2,2,2,2,7,2,2,2,2,7,2,2,7,4,4,4,4,4,4, + 4,2,2,2,2,4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,4,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2, + 2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,7,1,10,10,10,10,10,5,2,10,10,10,10,10,10,10,10,10,7,10, + 10,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,7,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,7,10,10,10,10,10,10,10,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,9,2,2,1,1,2,10,10,10, + 10,10,9,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4, + 4,4,4,2,2,4,7,2,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1, + 3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8, + 1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,5,5,5, + 5,5,5,5,5,5,5,5,5,5,2,2,2,2,2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7, 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, + 2,1,2,1,1,1,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, + 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, + 2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,2,2,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,1,7,1,3,5,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,5,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,1,7,1,3,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,7,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1, + 2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1, + 7,1,1,8,8,8,8,1,7,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,8,8,8, + 8,1,7,1,1,10,10,1,10,10,10,10,10,10,10,10,10,10,10,10,2,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,7,5,5,5,5,5,7, + 1,3,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,1,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5, + 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,1,5,7,1, - 1,1,3,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5, - 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1, - 1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1, - 1,1,3,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, - 5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7, - 1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1, - 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, - 5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5, - 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1, - 1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1, - 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5, - 1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5, - 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,1,5,7,1,1,1,3,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5, - 5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,7,3,1,7,3,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,2,2,2,2,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,1,1,2,8,8,8,8,1, + 7,1,1,1,1,1,1,1,1,7,1,3,3,1,3,1,1,1,2,2,2,2,2,2,2,2,2,2,2,7,3,2,1,2,2,2,2, + 2,2,2,7,3,2,2,2,1,2,2,2,2,7,2,1,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, + 1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, + 2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1, + 1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1, + 1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, + 2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, + 1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, + 2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2, + 1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1, + 1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, + 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, + 2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, + 2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, + 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, + 1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2, + 1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, + 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, + 1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1, + 2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2, + 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, + 1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2, + 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, + 1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, + 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, + 1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2, + 1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,7,2,2,2,2,2,2,1,1,2,2,2,2,2,2,7,2, + 2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2,1,2,2,2, + 2,2,2,2,7,2,2,2,2,1,2,2,2,2,2,2,2,7,2,2,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2, + 2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2, + 1,2,2,2,2,2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7, + 2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2, + 2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1, + 1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,2,1,1,1,1,1,1,2,9,7,2,1,1,2,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1, - 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1, - 1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,7,2,1,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,1,7,1,3,1,2,7,2,1,1,2,1,1, + 5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2,2,4,7,2,1,1,5,1,7,1,3,2,7,1,1,1,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2, + 1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, + 2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1, + 3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7, + 1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, + 7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,1,2,1, + 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1, + 1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, + 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5, - 5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,1,7,1,1,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,1,7,1,1,8,8, - 8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1, + 2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,7,1,3,5,5,5, + 5,5,5,5,7,1,3,1,1,1,1,7,3,3,1,3,1,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,2,1,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,7,2,2, + 1,2,1,1,1,2,1,2,2,2,2,2,1,1,1,1,2,3,7,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7, + 2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,7,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7, + 1,1,7,1,1,7,1,1,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,7,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, + 1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, - 8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1, - 7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, - 1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, - 1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8,8, - 8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7, - 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,5,5,5,5,1,7,1,1,5,5,5,5,5,5,5,5,5,1,1,7,1,1, - 1,3,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2, - 2,2,2,2,2,2,2,2,2,2,2,7,2,1,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1,5,7,1,1,1,3,4, - 4,4,4,1,7,1,5,5,1,1,7,1,1,1,3,1,2,7,2,1,1,2,1,1,5,5,5,5,1,1,7,1,1,1,3,5,5, - 5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2, - 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,4,4,4,4,2,7,2,1,1,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2, - 2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1, - 1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1, - 3,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2, - 2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,7,2,1,1,1, - 5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2, - 2,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,2,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1, - 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,2,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1, - 1,1,1,1,1,1,1,1,1,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,1,1, - 7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1, - 1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2, - 1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, - 2,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,2,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1, - 1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,2,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2, - 2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,2,1,1,3,5,5,5,5,1,1,7, - 1,1,1,3,5,5,5,5,1,1,7,1,1,1,3,10,10,1,10,10,10,10,10,10,2,10,10,10,10,10, - 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,7,5,5,5,5,1,1,7,1,1, - 1,3,10,10,1,10,10,10,10,10,10,10,10,10,10,10,10,10,10,3,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10,10,10,7,5,5,5,5,5,1,5,7,1,1,1,3,10,10,10,10,10,10, - 10,10,10,10,10,10,10,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,2,2, - 2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,1,1, - 7,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1, - 2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, - 2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,1,1,7,2,2,1,1,1,1,1,7,2,2,2,2,2,2,1, - 1,1,1,1,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1, - 2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1, - 2,2,2,2,2,2,2,2,7,1,1,2,2,2,2,2,2,2,2,7,1,1,2,2,2,2,7,1,1,2,2,2,2,2,2,2,2, - 2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2, - 2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2, - 2,2,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1, - 2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2, - 1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, - 2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2, - 1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, - 2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2, - 2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, - 7,2,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2, - 1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, - 2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,2, - 2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2, - 1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, - 7,2,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2, - 1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, - 7,2,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,3,3,1,1,1,1,1,1,2,1,1,1,2,2,1, - 1,1,1,1,1,1,1,2,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 1,1,1,2,1,1,1,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,1,1,2,2,2,1,1,2,1,1, - 2,1,1,2,2,2,1,1,1,1,2,9,7,2,1,1,2,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,1,5,7,1,1,1,3,2,2,2,7,4,1,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,7,2,2,2,7, - 2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,10, - 10,10,5,10,10,10,10,2,7,10,10,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 7,9,2,10,10,10,2,9,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2, - 2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 2,4,4,7,5,1,1,7,1,1,1,3,5,1,1,7,1,1,1,3,5,1,1,7,1,1,1,3,5,1,1,7,1,1,1,3,5, - 1,1,7,1,1,1,3,5,1,1,7,1,1,1,3,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,1,7,1, - 1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,1,7,1,1,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1, - 2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1, - 1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,5,1,1,1,1,1,1,1,5,1,1,1,1,1,1,5,1,1,1,1,1,1,5,1,1,1,1,5,1,1,1, - 1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1, - 1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,1,7, - 1,2,8,4,4,4,4,1,7,1,1,8,4,4,4,4,1,7,1,1,8,4,4,4,4,1,7,1,1,2,1,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,8,5,5,5,5,1,7,1,1, - 8,5,5,5,5,1,7,1,1,8,5,5,5,5,1,7,1,1,8,5,5,5,5,1,7,1,1,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,7,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1, - 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,1,7,1,1,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5, + 8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,1,7,1,1,9,2,10,10,10,9,2,2,2,4,4,4,4,2, - 4,4,7,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,7,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,7,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, - 2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2, - 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, - 2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,7,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, - 1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, - 1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5, - 7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, - 1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,1,1,7,1,1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,1,1,7,1,1,1,3,1,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,4,4,4,4,7,1,1,4,4,4,4,7,1,1,4,4,4,4,7,1,1, - 4,4,4,4,7,1,1,7,1,1,7,1,1,7,1,2,7,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7, - 2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1, - 1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2, - 1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1, - 1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, - 2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,2,2,2,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7, - 2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, - 2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1, - 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2, - 1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,5,7,1,1,1,3,8,8,8,8,8,8,8,8,8,1,7,1,1,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1, - 1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1, - 1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,7,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,2,2,2,2,2,2,2,2,2,7,2,1,1,2, - 2,2,2,2,2,2,2,2,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1, - 2,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, - 2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,7,2,1,2,2,2,2,2, - 2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,2,1,1,2,1,2,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1 + 5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,7,2,2,1,2,1,1,1,1,1, + 1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1, + 1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,7,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1, + 2,1,1,1,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,7,1, + 3,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2, + 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,3,3,1,3,1,1,1,5,5,5, + 5,5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,8,1,7,1,1,2, + 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,7,1,3,1,1,7,2,1,2,2,2,2,2,2, + 2,2,2,7,9,2,2,1,1,2,10,10,10,10,10,9,4,4,4,4,2,2,4,7,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, + 2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1, + 1,2,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,1,4,4, + 4,4,4,7,1,5,1,7,1,3,1,7,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,7,1, + 1,1,1,1,7,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,7,2,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2, + 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, + 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, + 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, + 1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2, + 1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1, + 1,2,1,2,1,1,1,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, + 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, + 1,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, + 1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, + 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, + 1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, + 2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 7,2,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, + 1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, + 2,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,8,8, + 8,8,1,7,1,1,8,8,8,8,1,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2, + 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, + 1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,1,7,1,1,1,7,1,5,5,5,5,5,1,7,1,3,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, + 1,4,4,4,4,4,7,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, + 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,5,5,5,5,5,7,1,1,1,1,7,2,2,1,2,1,1,1,4,4,4,4,4,4,4,4,2,2,2,2,4,4,4, + 4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,7,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1, + 7,2,1,7,2,1,7,2,1,7,3,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1, + 1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7, + 2,2,1,2,1,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2, + 2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, + 2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,5,2,1,7,1,3,2,5,5,7,1,3,8,1,7,1,1,2,2,2,2, + 2,2,2,2,2,7,2,2,1,1,7,2 }; static const unsigned short ag_pstt[] = { -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,0,2,2,2,3, -4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,4, -1,543,545,543,543, -7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,6,7,5,3,0,8,8,8,5,7, -13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, - 13,13,13,13,13,13,13,13,13,14,13,4, -16,18, -9,6,24, -83,83,83,83,83,83,83,83,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27, - 27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27, - 27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27, - 27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27, - 27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,17, - 18,19,20,21,22,23,24,25,22,10,11,12,82,1,7,23,28,36,21,15,22,14,13,37, - 35,34,33,32,31,35,36,30,29,27,16,26,16, -7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,6,7,4,5,8,3,3,5,7, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,1,544,544,9,2,2,2,549, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,1,544,10,2,2,2,548, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,11,2, - 2,2,547, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,12,2, - 2,2,546, -38,41,43,44,45,46,47,48,49,50,51,52,53,54,56,62,65,66,68,61,60,39,67,64,55, - 59,57,58,63,42,40,70,10,11,69,13,69,70,69,69,69,69,69,69,69,69,69,69,69, - 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69, -38,41,43,44,45,46,47,48,49,50,51,52,53,54,56,62,65,66,68,61,60,39,67,64,55, - 59,57,58,63,42,40,71,10,11,69,14,69,71,69,69,69,69,69,69,69,69,69,69,69, - 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69, -38,41,43,44,45,46,47,48,49,50,51,52,53,54,56,62,65,66,68,61,60,39,67,64,55, - 59,57,58,63,42,40,72,10,11,69,15,69,72,69,69,69,69,69,69,69,69,69,69,69, - 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69, -84,84,84,84,84,84,84,85,85,85,84,101,1,2,16,2,85,2,2,559, -544,544,544,544,544,544,544,544,544,1,2,17,2,2,2,565, -544,544,544,544,544,544,544,544,544,1,2,18,2,2,2,564, -544,544,544,544,1,2,19,2,2,2,563, -544,544,544,544,1,2,20,2,2,2,562, -544,544,544,544,544,544,544,544,544,1,2,21,2,2,2,561, -544,544,544,544,544,544,544,544,544,1,2,22,2,2,2,560, -544,544,1,2,23,2,2,2,557, -544,544,1,2,24,2,2,2,555, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,2,25,2,2,2, - 552, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,26,2,2,2,550, -73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97, - 98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115, - 116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133, - 134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151, - 152,153,154,155,156,157,158,159,160,161,162,163,224,226,228,229,231,233, - 234,235,237,239,241,243,245,247,249,251,253,255,256,257,258,27,259,46, - 47,48,254,252,250,248,246,244,242,240,238,236,63,64,232,230,69,227,225, - 223,223,222,221,220,219,218,217,225,216,215,214,229,230,213,212,211,210, - 209,208,207,206,239,205,204,203,243,244,245,246,202,201,200,199,198,197, - 196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,268,181,180, - 179,272,178,177,176,276,175,174,279,280,281,282,283,284,285,286,287,288, - 289,290,291,292,173,294,172,171,170,298,299,300,169,168,303,167,166,306, - 165,164,309, -249,251,253,263,265,28,266,264,262,261,260, -83,83,83,83,83,83,83,83,82,29,38,267,267, -83,83,83,83,83,83,83,83,82,30,37,267,267, -83,83,83,83,83,83,83,83,82,31,34,267,267, -83,83,83,83,83,83,83,83,82,32,33,267,267, -268,269,33,31,32, -97,92,34,29,272,30,270,273,271, -86,86,86,86,86,86,86,86,97,86,86,86,86,92,86,35,26,272,27,270,28,273,271, - 274, -44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, - 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, - 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, - 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, - 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,263,265,25,25,25,25,36,276, - 275, -9,10,11,12,37,20,15,14,13,19, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,38,2, - 2,2,751, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,1,544,39,2,2,2,624, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,1,544,40,2,2,2,605, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,41,2, - 2,2,750, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,1,544,42,2,2,2,607, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,43,2, - 2,2,749, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,44,2, - 2,2,748, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,45,2, - 2,2,747, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,46,2, - 2,2,746, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,47,2, - 2,2,745, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,48,2, - 2,2,744, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,49,2, - 2,2,743, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,50,2, - 2,2,742, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,51,2, - 2,2,741, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,52,2, - 2,2,740, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1, - 544,53,2,2,2,739, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1, - 544,54,2,2,2,738, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,1,544,55,2,2,2,618, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,56,2, - 2,2,737, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,1,544,57,2,2,2,616, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,1,544,58,2,2,2,615, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,1,544,59,2,2,2,617, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,1,544,60,2,2,2,625, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,1,544,61,2,2,2,626, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,62,2, - 2,2,736, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,1,544,63,2,2,2,609, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,1,544,64,2,2,2,619, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,65,2, - 2,2,735, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,66,2, - 2,2,734, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,1,544,67,2,2,2,622, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,544,68,2, - 2,2,733, -38,41,43,44,45,46,47,48,49,50,51,52,53,54,56,62,65,66,68,61,60,39,67,64,55, - 59,57,58,63,42,40,10,11,6,8,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6, -11,70,11, -10,71,10, -9,72,9, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,73,2,2,2,732, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,74,2,2,2,731, -544,544,544,544,544,544,544,544,1,544,75,2,2,2,730, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,76,2,2,2,729, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,77,2,2,2,728, -544,544,544,544,544,544,544,544,1,544,78,2,2,2,727, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,79,2,2,2,726, -544,544,1,544,80,2,2,2,725, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,81,2,2,2,724, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,82,2,2,2,723, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,83,2,2,2,722, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,84,2,2,2,721, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,85,2,2,2,720, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,86,2,2,2,719, -544,544,544,544,544,544,544,544,1,544,87,2,2,2,718, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,88,2,2,2,717, -544,544,1,544,89,2,2,2,716, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,90,2,2,2,715, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,91,2,2,2,714, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,92,2,2,2,713, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,93,2,2,2,712, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,94,2,2,2,711, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,95,2,2,2,710, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,96,2,2,2,709, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,97,2,2,2,708, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,98,2,2,2,707, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,99,2,2,2,706, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,100,2,2,2,705, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,101,2,2,2,704, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,102,2,2,2,703, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,103,2,2,2,702, -544,544,544,544,544,1,544,104,2,2,2,701, -544,544,544,544,544,1,544,105,2,2,2,700, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,106,2,2,2,699, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,107,2,2,2,698, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,108,2,2,2,697, -544,544,544,544,544,544,544,544,1,544,109,2,2,2,696, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,110,2,2,2,695, -544,544,544,544,544,544,544,544,1,544,111,2,2,2,694, -544,544,544,544,544,544,544,544,1,544,112,2,2,2,693, -544,544,544,544,1,544,113,2,2,2,692, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,114,2,2,2,691, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,115,2,2,2,690, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,116,2,2,2,689, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,117,2,2,2,688, -544,544,1,544,118,2,2,2,687, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,119,2,2,2,686, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,120,2,2,2,685, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,121,2,2,2,684, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,122,2,2,2,683, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,123,2,2,2,682, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,124,2,2,2,681, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,125,2,2,2,680, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,126,2,2,2,679, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,127,2,2,2,678, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,128,2,2,2,677, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,129,2,2,2,676, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,130,2,2,2,675, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,131,2,2,2,674, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,132,2,2,2,673, -544,544,544,544,1,544,133,2,2,2,672, -544,544,544,544,544,544,544,544,1,544,134,2,2,2,671, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,135,2,2,2,670, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,136,2,2,2,669, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,137,2,2,2,668, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,138,2,2,2,667, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,139,2,2,2,666, -544,544,544,544,1,544,140,2,2,2,665, -544,544,544,544,544,544,544,544,1,544,141,2,2,2,664, -544,544,544,544,1,544,142,2,2,2,663, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,143,2,2,2,661, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,144,2,2,2,660, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,145,2,2,2,659, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,146,2,2,2,658, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,147,2,2,2,657, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,148,2,2,2,656, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,149,2,2,2,655, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,150,2,2,2,654, -544,544,544,544,544,544,544,544,1,544,151,2,2,2,653, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,152,2,2,2,652, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,153,2,2,2,651, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,154,2,2,2,650, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,155,2,2,2,649, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,156,2,2,2,648, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,157,2,2,2,647, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,158,2,2,2,646, -544,544,544,544,544,544,544,544,1,544,159,2,2,2,645, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,160,2,2,2,644, -544,544,544,544,544,544,544,544,1,544,161,2,2,2,643, -544,544,544,544,544,544,544,544,1,544,162,2,2,2,642, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,163,2,2,2,640, -277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277, - 277,277,277,277,277,277,277,277,277,5,164,5,277, -278,278,278,278,278,278,278,278,5,165,5,278, -279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279, - 279,279,279,279,279,279,279,279,279,5,166,5,279, -280,280,280,280,280,280,280,280,5,167,5,280, -281,281,5,168,5,281, -282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282, - 282,282,282,282,282,282,282,282,282,5,169,5,282, -283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283, - 283,283,283,283,283,283,283,283,283,5,170,5,283, -284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284, - 284,284,284,284,284,284,284,284,284,5,171,5,284, -285,285,285,285,285,285,285,285,5,172,5,285, -286,286,5,173,5,286, -287,287,287,287,287,5,174,5,287, -288,288,288,288,288,5,175,5,288, -289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289, - 289,289,289,289,289,289,289,289,289,5,176,5,289, -290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,290, - 290,290,290,290,290,290,290,290,290,5,177,5,290, -291,291,291,291,291,291,291,291,5,178,5,291, -292,292,292,292,292,292,292,292,5,179,5,292, -293,293,293,293,293,293,293,293,5,180,5,293, -294,294,294,294,5,181,5,294, -295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295, - 295,295,295,295,295,295,295,295,295,5,182,5,295, -296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296, - 296,296,296,296,296,296,296,296,296,5,183,5,296, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, - 297,297,297,297,297,297,297,297,297,5,184,5,297, -298,298,5,185,5,298, -299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299, - 299,299,299,299,299,299,299,299,299,5,186,5,299, -300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300, - 300,300,300,300,300,300,300,300,300,5,187,5,300, -301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301, - 301,301,301,301,301,301,301,301,301,5,188,5,301, -302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302, - 302,302,302,302,302,302,302,302,302,5,189,5,302, -303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303, - 303,303,303,303,303,303,303,303,303,5,190,5,303, -304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304, - 304,304,304,304,304,304,304,304,304,5,191,5,304, -305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305, - 305,305,305,305,305,305,305,305,305,5,192,5,305, -306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306, - 306,306,306,306,306,306,306,306,306,5,193,5,306, -307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307, - 307,307,307,307,307,307,307,307,307,5,194,5,307, -308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, - 308,308,308,308,308,308,308,308,308,5,195,5,308, -309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309, - 309,309,309,309,309,309,309,309,309,5,196,5,309, -310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310, - 310,310,310,310,310,310,310,310,310,5,197,5,310, -311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311, - 311,311,311,311,311,311,311,311,311,5,198,5,311, -312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312, - 312,312,312,312,312,312,312,312,312,5,199,5,312, -313,313,313,313,5,200,5,313, -314,314,314,314,314,314,314,314,5,201,5,314, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, - 315,315,315,315,315,315,315,315,315,5,202,5,315, -316,316,316,316,5,203,5,316, -317,317,317,317,317,317,317,317,5,204,5,317, -318,318,318,318,5,205,5,318, -319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319, - 319,319,319,319,319,319,319,319,319,5,206,5,319, -320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320, - 320,320,320,320,320,320,320,320,320,5,207,5,320, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, - 321,321,321,321,321,321,321,321,321,5,208,5,321, -322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322, - 322,322,322,322,322,322,322,322,322,5,209,5,322, -323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323, - 323,323,323,323,323,323,323,323,323,5,210,5,323, -324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, - 324,324,324,324,324,324,324,324,324,5,211,5,324, -325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325, - 325,325,325,325,325,325,325,325,325,5,212,5,325, -326,326,326,326,326,326,326,326,5,213,5,326, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, - 327,327,327,327,327,327,327,327,327,5,214,5,327, -328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328, - 328,328,328,328,328,328,328,328,328,5,215,5,328, -329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329, - 329,329,329,329,329,329,329,329,329,5,216,5,329, -330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330, - 330,330,330,330,330,330,330,330,330,5,217,5,330, -331,331,331,331,331,331,331,331,5,218,5,331, -332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332, - 332,332,332,332,332,332,332,332,332,5,219,5,332, -333,333,333,333,333,333,333,333,5,220,5,333, -334,334,334,334,334,334,334,334,5,221,5,334, -335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, - 335,335,335,335,335,335,335,335,335,5,222,5,335, -336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,1,2, +18,20, +123,123,123,123,123,123,123,123,123,123,123,123,123,3,8,8,8,8,8,122,121,7, + 10,2,9,0,11,11,11,10,8,11,5,5,4,6,4, +19,19,19,19,19,19,19,19,19,19,19,1,3,1,849, +124,124,124,124,124,124,124,124,124,124,124,124,125,125,125,125,125,124,155, + 124,155,155,155,155,154,155,155,4,125, +12,13,14,15,16,17,18,19,20,21,22,5,33,39,32,31,30,29,28,27,26,25,24,23, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1, + 6,1,840, +34,7,37, +36,36,35,37,38,39,34,8,24,24,42,24,41,40,40,36,36, +43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,19,19,43,43,43,43,43,43,43,1, + 9,1,43, +123,123,123,123,123,123,123,123,123,123,123,123,123,107,108,109,110,111,112, + 113,114,61,62,63,64,65,115,116,117,118,119,120,66,67,68,69,70,121,122, + 123,71,72,73,74,75,124,125,126,127,128,129,130,131,132,133,134,135,136, + 137,138,104,59,60,143,144,145,146,147,148,149,150,151,152,153,154,155, + 156,139,140,141,142,76,77,78,79,80,45,46,47,81,82,83,84,85,86,87,88,89, + 48,49,90,91,92,93,94,95,96,97,50,51,52,98,99,53,54,100,101,102,103,55, + 56,57,58,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, + 220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,15,16, + 19,220,220,20,20,35,20,20,20,20,122,121,18,10,216,217,218,215,221,220, + 220,35,219,97,98,221,44,214,215,215,215,215,215,215,215,215,215,308,308, + 308,308,308,309,310,311,312,315,315,315,316,317,321,321,321,321,322,323, + 324,325,326,327,328,329,332,332,332,333,334,335,336,337,338,339,340,341, + 345,345,345,345,346,347,348,349,350,199,198,197,196,213,212,211,210,209, + 208,207,206,205,204,203,202,201,200,159,106,158,105,157,195,194,193,192, + 191,190,189,188,187,186,185,184,183,182,181,180,180,180,180,180,180,179, + 178,177,176,176,176,176,176,176,175,174,173,172,171,170,169,169,169,169, + 168,168,168,167,166,165,164,163,162,161,160,214, +123,123,123,123,123,123,123,123,123,123,123,123,123,3,8,8,8,8,8,122,121,7,4, + 10,11,9,3,3,10,8,3,5,5,4,6,4, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,12,1,862, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,13,1,861, +19,1,14,1,860, +19,19,19,19,19,15,1,859, +19,19,19,19,19,16,1,858, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,17,1,857, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,18,1,856, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,19,1,855, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,20,1,854, +19,19,1,21,1,851, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,22,1,844, +123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,23,222,223,214, + 214, +123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,24,224,214,214, +132,25,227,225,226, +228,228,228,228,1,26,1,228, +229,229,229,229,1,27,1,229, +123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,28,230,214,214, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,29,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,283,285,271,209,214,284,272,276,275,274,273,208,276,266,265,264, + 263,262,261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,30,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,283,286,271,209,214,284,272,276,275,274,273,208,276,266,265,264, + 263,262,261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,31,287,214,214, +288,290,32,291,289, +150,132,33,295,225,294,292,226,293, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,34,1,835, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,35,1,841, +296,22,36,297,297,297, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,37,1,839, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,38, + 1,837, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,39,1,836, +298,300,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318, + 319,320,321,328,331,332,333,334,268,270,330,322,326,323,325,329,301,299, + 324,256,327,35,37,335,38,34,15,40,16,15,15,40,13,40,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15, +298,300,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318, + 319,320,321,328,331,332,333,334,268,270,330,322,326,323,325,329,301,299, + 324,256,327,35,38,337,336,41,336,337,336,336,336,336,336,336,336,336, 336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, + 336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +298,300,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318, + 319,320,321,328,331,332,333,334,268,270,330,322,326,323,325,329,301,299, + 324,256,327,35,38,338,336,42,336,338,336,336,336,336,336,336,336,336, 336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, - 336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, - 336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, - 336,17,17,17,17,5,223,5,336, -544,544,544,544,544,544,544,544,544,1,2,224,2,2,2,590, -83,83,83,83,83,83,83,83,82,225,71,267,267, -544,544,544,544,544,544,544,544,544,544,544,544,544,1,2,226,2,2,2,589, -86,86,86,86,86,86,86,86,86,86,86,86,86,227,70,274, -544,544,544,544,1,2,228,2,2,2,588, -544,544,544,544,1,544,229,2,2,2,587, -68,68,68,68,337,230,337, -544,544,1,2,231,2,2,2,585, -338,92,232,66,272,339,65,273,340, -544,544,544,544,1,2,233,2,2,2,583, -544,544,544,544,1,2,234,2,2,2,582, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,235,2,2,2,581, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,236,162,152,348,349,163,346,164,347,377,379, - 267,378,376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364, - 363,362,361,360,359,267,358,357, -544,544,544,544,544,544,544,544,544,544,544,544,544,1,2,237,2,2,2,580, -83,83,83,83,83,83,83,83,60,60,60,60,82,238,61,267,267, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,239,2,2,2,579, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,240,162,152,348,349,163,346,164,347,59,267,376, - 375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361, - 360,359,267,358,357, -544,544,544,544,544,544,544,544,544,1,2,241,2,2,2,578, -83,83,83,83,83,83,83,83,82,242,58,267,267, -544,544,544,544,544,544,544,544,544,1,2,243,2,2,2,577, -83,83,83,83,83,83,83,83,82,244,79,380,267,267, -544,544,544,544,544,544,544,544,544,1,2,245,2,2,2,576, -83,83,83,83,83,83,83,83,82,246,79,381,267,267, -544,544,544,544,544,544,544,544,544,1,2,247,2,2,2,575, -83,83,83,83,83,83,83,83,82,248,79,382,267,267, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,1,2,249,2,2,2,574, -83,83,83,83,83,83,83,174,174,342,341,383,83,92,350,351,352,353,354,355,356, - 61,39,366,67,343,344,184,82,250,162,152,348,349,163,346,73,272,164,347, - 339,74,75,384,267,376,375,374,373,372,371,371,371,370,369,368,151,371, - 367,365,364,363,362,361,360,359,273,267,340,358,357, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,1,2,251,2,2,2,573, -83,83,83,83,83,83,83,174,174,342,341,383,83,92,350,351,352,353,354,355,356, - 61,39,366,67,343,344,184,82,252,162,152,348,349,163,346,73,272,164,347, - 339,74,75,385,267,376,375,374,373,372,371,371,371,370,369,368,151,371, - 367,365,364,363,362,361,360,359,273,267,340,358,357, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,253,2,2,2,572, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,254,162,152,348,349,163,346,164,347,50,267,376, - 375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361, - 360,359,267,358,357, -544,544,544,544,1,2,255,2,2,2,571, -544,544,544,544,1,2,256,2,2,2,570, -544,544,544,544,1,2,257,2,2,2,569, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,258,2,2,2,568, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,259,162,152,348,349,163,346,164,347,45,267,376, - 375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361, - 360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,383,83,92,350,351,352,353,354,355,356, - 61,39,366,67,343,344,184,82,260,162,152,348,349,163,346,73,272,164,347, - 339,74,75,386,267,376,375,374,373,372,371,371,371,370,369,368,151,371, - 367,365,364,363,362,361,360,359,273,267,340,358,357, -83,83,83,83,83,83,83,174,174,342,341,383,83,92,350,351,352,353,354,355,356, - 61,39,366,67,343,344,184,82,261,162,152,348,349,163,346,73,272,164,347, - 339,74,75,387,267,376,375,374,373,372,371,371,371,370,369,368,151,371, - 367,365,364,363,362,361,360,359,273,267,340,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,262,162,152,348,349,163,346,164,347,49,267,376, - 375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361, - 360,359,267,358,357, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,263,2,2,2,567, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,264,162,152,348,349,163,346,164,347,40,267,376, - 375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361, - 360,359,267,358,357, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,265,2,2,2,566, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,266,162,152,348,349,163,346,164,347,39,267,376, - 375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361, - 360,359,267,358,357, -84,84,84,84,84,84,84,85,85,85,84,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,1,2,267,2, - 85,2,2,559, -544,544,544,544,1,2,268,2,2,2,558, -544,544,544,544,1,2,269,2,2,2,556, -98,98,388,98,98,98,98,98,98,96,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98, - 98,98,98,98,98,98,98,98,270, -544,544,544,544,1,2,271,2,2,2,553, -93,93,389,93,93,93,93,93,93,93,93,93,93,93,93,93,93,91,93,93,93,93,93,93,93, - 93,93,93,93,93,93,93,93,93,272, -544,544,544,544,544,1,544,273,2,2,2,551, -87,87,87,87,87,87,87,87,87,87,87,87,87,544,544,544,1,2,274,2,2,2,554, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,275,162,152,348,349,163,346,164,347,42,267,376, - 375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361, - 360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,276,162,152,348,349,163,346,164,347,41,267,376, - 375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361, - 360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,277,162,152,348,349,163,346,164,347,308,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -204,201,199,197,203,202,200,198,278,307,390, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,279,162,152,348,349,163,346,164,347,305,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -204,201,199,197,203,202,200,198,280,304,390, -391,392,281,214,215,302, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,282,162,152,348,349,163,346,164,347,301,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,283,162,152,348,349,163,346,164,347,297,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,284,162,152,348,349,163,346,164,347,296,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -204,201,199,197,203,202,200,198,285,295,390, -53,54,286,293,293, -393,394,395,391,392,287,211,209,210,213,278,212, -393,394,395,391,392,288,211,209,210,213,277,212, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,289,162,152,348,349,163,346,164,347,275,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,290,162,152,348,349,163,346,164,347,274,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -204,201,199,197,203,202,200,198,291,273,390, -204,201,199,197,203,202,200,198,292,396,390, -204,201,199,197,203,202,200,198,293,397,390, -207,206,205,208,294,399,398, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,295,162,152,348,349,163,346,164,347,267,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,296,162,152,348,349,163,346,164,347,266,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,297,162,152,348,349,163,346,164,347,265,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -391,392,298,214,215,264, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,299,162,152,348,349,163,346,164,347,263,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,300,162,152,348,349,163,346,164,347,262,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,301,162,152,348,349,163,346,164,347,261,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,302,162,152,348,349,163,346,164,347,260,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,303,162,152,348,349,163,346,164,347,259,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,304,162,152,348,349,163,346,164,347,258,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,305,162,152,348,349,163,346,164,347,257,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,306,162,152,348,349,163,346,164,347,256,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,307,162,152,348,349,163,346,164,347,255,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,308,162,152,348,349,163,346,164,347,254,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,309,162,152,348,349,163,346,164,347,253,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,310,162,152,348,349,163,346,164,347,252,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,311,162,152,348,349,163,346,164,347,251,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,312,162,152,348,349,163,346,164,347,250,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -207,206,205,208,313,249,398, -204,201,199,197,203,202,200,198,314,248,390, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,315,162,152,348,349,163,346,164,347,247,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -207,206,205,208,316,242,398, -204,201,199,197,203,202,200,198,317,241,390, -207,206,205,208,318,240,398, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,319,162,152,348,349,163,346,164,347,238,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,320,162,152,348,349,163,346,164,347,237,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,321,162,152,348,349,163,346,164,347,236,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,322,162,152,348,349,163,346,164,347,235,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,323,162,152,348,349,163,346,164,347,234,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,324,162,152,348,349,163,346,164,347,233,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,325,162,152,348,349,163,346,164,347,232,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -204,201,199,197,203,202,200,198,326,231,390, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,327,162,152,348,349,163,346,164,347,228,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,328,162,152,348,349,163,346,164,347,227,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,329,162,152,348,349,163,346,164,347,226,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,330,162,152,348,349,163,346,164,347,224,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -204,201,199,197,203,202,200,198,331,223,390, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,332,162,152,348,349,163,346,164,347,222,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -204,201,199,197,203,202,200,198,333,221,390, -204,201,199,197,203,202,200,198,334,220,390, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,335,162,152,348,349,163,346,164,347,219,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97, - 98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115, - 116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133, - 134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151, - 152,153,154,155,156,157,158,159,160,161,162,163,67,72,217,218,222,221, - 220,219,218,217,225,216,215,214,229,230,213,212,211,210,209,208,207,206, - 239,205,204,203,243,244,245,246,202,201,200,199,198,197,196,195,194,193, - 192,191,190,189,188,187,186,185,184,183,182,268,181,180,179,272,178,177, - 176,276,175,174,279,280,281,282,283,284,285,286,287,288,289,290,291,292, - 173,294,172,171,170,298,299,300,169,168,303,167,166,306,165,164,309, -174,174,342,345,343,344,184,16,337,67,348,400,164,347,358, -185,401,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, - 185,185,185,185,185,185,185,185,185,185,185,185,185,191,185,338,402, -185,401,185,185,185,185,185,185,185,185,185,185,185,185,88,185,185,185,185, - 185,185,185,185,185,185,185,185,185,185,185,185,185,185,191,185,339,90, -544,544,544,544,544,1,544,340,2,2,2,584, -195,195,195,341, -174,403,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, - 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, - 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, - 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, - 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, - 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, - 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, - 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,342, -173,173,173,343, -172,172,172,344, -185,401,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, - 185,185,185,185,185,185,185,185,185,185,185,185,185,191,185,345,404, -196,196,196,193, -181,181,181,181,167,347, -179,179,179,179,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, - 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, - 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, - 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, - 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, - 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, - 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, - 166,166,166,166,166,166,166,348, -176,180,175,175,175,194,177,165,165,165,165,165,165,165,165,165,165,165,165, - 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, - 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, - 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,168,171, - 169,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, - 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, - 170,165,165,349, -544,1,2,350,2,2,2,633, -544,1,2,351,2,2,2,632, -544,1,2,352,2,2,2,631, -544,1,2,353,2,2,2,630, -544,1,2,354,2,2,2,629, -544,1,2,355,2,2,2,628, -544,1,2,356,2,2,2,627, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,1,544,357,2,2,2,634, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,1,2,358,2,2,2,586, -61,359,405, -61,360,406, -61,361,407, -61,362,408, -61,363,409, -61,364,410, -61,365,411, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,1,2,366,2,2,2,623, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,367,162,152,348,349,163,346,164,347,412,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 343,344,184,82,368,162,152,348,349,163,346,164,347,267,150,151,150,367, - 365,364,363,362,361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 343,344,184,82,369,162,152,348,349,163,346,164,347,267,149,151,149,367, - 365,364,363,362,361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 343,344,184,82,370,162,152,348,349,163,346,164,347,267,148,151,148,367, - 365,364,363,362,361,360,359,267,358,357, -413,415,64,55,59,138,419,418,417,416,414, -57,58,133,421,420, -422,424,426,428,130,429,427,425,423, -430,63,127,432,431, -433,42,124,435,434, -436,40,123,438,437, -439,440,441,442,443,444,445,446,447,448,449,450,451,103,103,103,103,103,377, - 107,107,107,107,110,110,110,113,113,113,116,116,116,119,119,119,122,122, - 122, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,378,162,152,348,349,163,346,164,347,102,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -17,17,17,17,5,379,5,62, -452,57,57,57,57,5,380,5,452, -452,56,56,56,56,5,381,5,452, -452,55,55,55,55,5,382,5,452, -185,401,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, - 185,185,185,185,185,185,185,185,185,185,185,185,185,191,185,383,453, -454,17,17,17,17,5,384,5,454, -455,17,17,17,17,5,385,5,455, -456,17,17,17,17,5,386,5,456, -457,17,17,17,17,5,387,5,457, -99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, - 99,99,99,99,99,99,100,99,99,99,388, -94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94, - 94,94,94,94,94,94,95,94,94,94,389, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,1,544,390,2,2,2,641, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,391,2,2,2,636, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,392,2,2,2,635, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,393,2,2,2,639, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,394,2,2,2,638, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,395,2,2,2,637, -458,5,396,5,458, -459,5,397,5,459, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,1,544,398,2,2,2,662, -460,5,399,5,460, -176,180,175,175,175,177,168,171,169,165,165,165,165,170,165,165,400, -186,188,189,187,190,192,401, -185,401,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, - 185,185,185,185,185,185,185,185,185,185,185,185,185,191,185,402,89, -178,178,178,178,403, -185,401,185,185,185,185,185,185,185,185,185,185,185,185,182,185,185,185,185, - 185,185,185,185,185,185,185,185,185,185,185,185,185,185,191,185,404,461, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,405,162,152,348,349,163,346,164,347,462,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,406,162,152,348,349,163,346,164,347,463,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,407,162,152,348,349,163,346,164,347,464,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,408,162,152,348,349,163,346,164,347,465,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,409,162,152,348,349,163,346,164,347,466,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,410,162,152,348,349,163,346,164,347,467,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,411,162,152,348,349,163,346,164,347,468,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -60,412,469, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,1,544,413,2,2,2,621, -470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470, - 470,470,470,470,470,470,5,414,5,470, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,1,544,415,2,2,2,620, -471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471, - 471,471,471,471,471,471,5,416,5,471, -472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, - 472,472,472,472,472,472,5,417,5,472, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, - 473,473,473,473,473,473,5,418,5,473, -474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474, - 474,474,474,474,474,474,5,419,5,474, + 336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +123,123,123,123,123,123,123,123,123,123,123,123,123,107,108,109,110,111,112, + 113,114,61,62,63,64,65,115,116,117,118,119,120,66,67,68,69,70,121,122, + 123,71,72,73,74,75,124,125,126,127,128,129,130,131,132,133,134,135,136, + 137,138,104,59,60,143,144,145,146,147,148,149,150,151,152,153,154,155, + 156,139,140,141,142,76,77,78,79,80,45,46,47,81,82,83,84,85,86,87,88,89, + 48,49,90,91,92,93,94,95,96,97,50,51,52,98,99,53,54,100,101,102,103,55, + 56,57,58,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339, + 339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,15,16, + 19,339,339,339,339,35,37,38,39,34,122,121,43,216,217,218,215,340,23,23, + 42,23,41,40,40,339,339,36,219,97,98,340,44,214,215,215,215,215,215,215, + 215,215,215,308,308,308,308,308,309,310,311,312,315,315,315,316,317,321, + 321,321,321,322,323,324,325,326,327,328,329,332,332,332,333,334,335,336, + 337,338,339,340,341,345,345,345,345,346,347,348,349,350,199,198,197,196, + 213,212,211,210,209,208,207,206,205,204,203,202,201,200,159,106,158,105, + 157,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,180, + 180,180,180,180,179,178,177,176,176,176,176,176,176,175,174,173,172,171, + 170,169,169,169,169,168,168,168,167,166,165,164,163,162,161,160,214, +341,341,341,341,341,341,1,44,1,341, +19,19,19,19,19,19,45,1,987, +19,19,19,19,19,19,46,1,986, +19,19,19,19,19,19,47,1,985, +19,19,19,19,19,19,48,1,975, +19,19,19,19,19,19,49,1,974, +19,19,19,19,19,19,50,1,965, +19,19,19,19,19,19,51,1,964, +19,19,19,19,19,19,52,1,963, +19,19,19,19,19,19,53,1,960, +19,19,19,19,19,19,54,1,959, +19,19,19,19,19,19,55,1,954, +19,19,19,19,19,19,56,1,953, +19,19,19,19,19,19,57,1,952, +19,19,19,19,19,19,58,1,951, +19,19,19,19,19,19,19,19,19,19,59,1,1014, +19,19,19,19,19,19,19,19,60,1,1013, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,61,1,1054, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,62,1,1053, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,63,1,1052, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,64,1,1051, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,65,1,1050, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,66,1,1043, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,67,1,1042, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,68,1,1041, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,69,1,1040, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,70,1,1039, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,71,1,1035, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,72,1,1034, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,73,1,1033, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,74,1,1032, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,75,1,1031, +19,19,19,19,19,19,76,1,992, +19,19,19,19,19,19,77,1,991, +19,19,19,19,19,19,78,1,990, +19,19,19,19,19,19,79,1,989, +19,19,19,19,19,19,80,1,988, +19,19,19,19,19,19,81,1,984, +19,19,19,19,19,19,82,1,983, +19,19,19,19,19,19,83,1,982, +19,19,19,19,19,19,84,1,981, +19,19,19,19,19,19,85,1,980, +19,19,19,19,19,19,86,1,979, +19,19,19,19,19,19,87,1,978, +19,19,19,19,19,19,88,1,977, +19,19,19,19,19,19,89,1,976, +19,19,19,19,19,19,90,1,973, +19,19,19,19,19,19,91,1,972, +19,19,19,19,19,19,92,1,971, +19,19,19,19,19,19,93,1,970, +19,19,19,19,19,19,94,1,969, +19,19,19,19,19,19,95,1,968, +19,19,19,19,19,19,96,1,967, +19,19,19,19,19,19,97,1,966, +19,19,19,19,19,19,98,1,962, +19,19,19,19,19,19,99,1,961, +19,19,19,19,19,19,100,1,958, +19,19,19,19,19,19,101,1,957, +19,19,19,19,19,19,102,1,956, +19,19,19,19,19,19,103,1,955, +19,19,19,19,19,104,1,1015, +342,342,342,342,342,342,342,342,342,1,105,1,342, +343,343,343,343,343,343,343,1,106,1,343, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,107,1,1062, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,108,1,1061, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,109,1,1060, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,110,1,1059, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,111,1,1058, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,112,1,1057, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,113,1,1056, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,114,1,1055, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,115,1,1049, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,116,1,1048, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,117,1,1047, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,118,1,1046, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,119,1,1045, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,120,1,1044, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,121,1,1038, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,122,1,1037, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,123,1,1036, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,124,1,1030, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,125,1,1029, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,126,1,1028, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,127,1,1027, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,128,1,1026, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,129,1,1025, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,130,1,1024, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,131,1,1023, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,132,1,1022, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,133,1,1021, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,134,1,1020, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,135,1,1019, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,136,1,1018, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,137,1,1017, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,138,1,1016, +19,19,19,19,19,19,19,19,19,139,1,996, +19,19,19,19,19,19,19,19,19,140,1,995, +19,19,19,19,19,141,1,994, +19,19,19,19,19,142,1,993, +19,19,19,19,19,19,19,19,143,1,1012, +19,19,19,19,19,19,19,19,144,1,1011, +19,19,19,19,19,19,19,19,145,1,1010, +19,19,19,19,19,19,19,19,19,19,146,1,1008, +19,19,19,19,19,19,19,19,19,19,147,1,1007, +19,19,19,19,19,19,19,19,19,19,148,1,1006, +19,19,19,19,19,19,19,19,19,19,149,1,1005, +19,19,19,19,19,19,19,19,19,19,150,1,1004, +19,19,19,19,19,19,19,19,19,19,151,1,1003, +19,19,19,19,19,19,19,19,19,19,152,1,1002, +19,19,19,19,19,19,19,19,19,19,153,1,1001, +19,19,19,19,19,19,19,19,19,19,154,1,1000, +19,19,19,19,19,19,19,19,19,19,155,1,999, +19,19,19,19,19,19,19,19,19,19,156,1,998, +344,344,344,344,1,157,1,344, +345,1,158,1,345, +346,1,159,1,346, +347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347, + 347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347, + 347,347,347,347,1,160,1,347, +348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348, + 348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348, + 348,348,348,348,1,161,1,348, +349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349, + 349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349, + 349,349,349,349,1,162,1,349, +350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350, + 350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350, + 350,350,350,350,1,163,1,350, +351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351, + 351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351, + 351,351,351,351,1,164,1,351, +352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352, + 352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352, + 352,352,352,352,1,165,1,352, +353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353, + 353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353, + 353,353,353,353,1,166,1,353, +354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354, + 354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354, + 354,354,354,354,1,167,1,354, +355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355, + 355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355, + 355,355,355,355,1,168,1,355, +356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, + 356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, + 356,356,356,356,1,169,1,356, +357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357, + 357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357, + 357,357,357,357,1,170,1,357, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, + 358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, + 358,358,358,358,1,171,1,358, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, + 359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, + 359,359,359,359,1,172,1,359, +360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, + 360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, + 360,360,360,360,1,173,1,360, +361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361, + 361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361, + 361,361,361,361,1,174,1,361, +362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362, + 362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362, + 362,362,362,362,1,175,1,362, +363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363, + 363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363, + 363,363,363,363,1,176,1,363, +364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364, + 364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364, + 364,364,364,364,1,177,1,364, +365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365, + 365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365, + 365,365,365,365,1,178,1,365, +366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366, + 366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366, + 366,366,366,366,1,179,1,366, +367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367, + 367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367, + 367,367,367,367,1,180,1,367, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, + 368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, + 368,368,368,368,1,181,1,368, +369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, + 369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, + 369,369,369,369,1,182,1,369, +370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, + 370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, + 370,370,370,370,1,183,1,370, +371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371, + 371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371, + 371,371,371,371,1,184,1,371, +372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372, + 372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372, + 372,372,372,372,1,185,1,372, +373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373, + 373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373, + 373,373,373,373,1,186,1,373, +374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374, + 374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374, + 374,374,374,374,1,187,1,374, +375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375, + 375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375, + 375,375,375,375,1,188,1,375, +376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376, + 376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376, + 376,376,376,376,1,189,1,376, +377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377, + 377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377, + 377,377,377,377,1,190,1,377, +378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378, + 378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378, + 378,378,378,378,1,191,1,378, +379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379, + 379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379, + 379,379,379,379,1,192,1,379, +380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380, + 380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380, + 380,380,380,380,1,193,1,380, +381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381, + 381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381, + 381,381,381,381,1,194,1,381, +382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382, + 382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382, + 382,382,382,382,1,195,1,382, +383,383,383,383,383,383,383,383,1,196,1,383, +384,384,384,384,384,384,384,384,1,197,1,384, +385,385,385,385,1,198,1,385, +386,386,386,386,1,199,1,386, +387,387,387,387,387,387,387,1,200,1,387, +388,388,388,388,388,388,388,1,201,1,388, +389,389,389,389,389,389,389,1,202,1,389, +390,390,390,390,390,390,390,390,390,1,203,1,390, +391,391,391,391,391,391,391,391,391,1,204,1,391, +392,392,392,392,392,392,392,392,392,1,205,1,392, +393,393,393,393,393,393,393,393,393,1,206,1,393, +394,394,394,394,394,394,394,394,394,1,207,1,394, +395,395,395,395,395,395,395,395,395,1,208,1,395, +396,396,396,396,396,396,396,396,396,1,209,1,396, +397,397,397,397,397,397,397,397,397,1,210,1,397, +398,398,398,398,398,398,398,398,398,1,211,1,398, +399,399,399,399,399,399,399,399,399,1,212,1,399, +400,400,400,400,400,400,400,400,400,1,213,1,400, +19,124,124,124,124,124,124,124,124,124,124,124,19,124,19,19,125,125,125,125, + 125,19,124,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,124,19,19,19,19,1,214,1,853,125, +19,19,19,19,19,1,215,1,293, +58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58, + 58,58,58,58,58,58,58,256,58,58,58,58,58,58,216,401, +108,108,108,108,402,217,402, +403,107,404, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,219,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,283,96,271,209,214,284,272,276,275,274,273,208,276,266,265,264, + 263,262,261,260,259,258,257,241,240,214,255,254, +405,406,408,410,411,412,414,415,416,418,420,422,424,426,428,430,432,434,436, + 437,439,440,441,443,444,446,447,448,449,451,452,288,290,220,67,68,62,63, + 450,450,450,450,73,445,445,445,442,442,442,442,438,438,438,435,433,431, + 429,427,425,423,421,419,417,99,100,413,103,104,409,407,109, +453,453,453,453,1,221,1,453, +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56, + 56,56,56,56,56,56,56,56,56,56,56,256,56,56,56,56,222,454, +455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455, + 455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455, + 455,455,455,1,223,1,455, +456,456,456,456,1,224,1,456, +135,457,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, + 135,135,135,135,135,131,135,135,135,135,135,135,135,135,135,135,135,135, + 135,135,135,135,135,135,225,133, +19,19,19,19,19,19,19,19,226,1,846, +458,458,458,458,1,227,1,458, +37,38,39,34,228,51,51,42,51,41,40,40, +37,38,39,34,229,50,50,42,50,41,40,40, +459,459,459,459,1,230,1,459, +264,264,264,264,264,231, +249,249,249,249,232, +247,247,233, +123,123,123,123,123,123,123,243,243,243,243,123,243,243,243,243,243,123,123, + 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, + 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, + 123,123,123,234, +238,460,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, + 238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, + 238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,235, +236,236,236,236,236,236, +254,461,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, + 254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, + 254,254,254,254,260,254,237,462, +265,265,265,265,265,262, +229,246,246,246,246,246,246,246,246,246,239, +250,250,250,250,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, + 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, + 228,228,228,228,228,240, +248,248,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, + 227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, + 227,227,227,241, +244,244,244,244,244,244,244,244,244,226,226,226,226,226,226,226,226,226,226, + 226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, + 226,226,226,226,226,226,226,226,226,226,242, +240,230,245,463,464,245,239,239,239,239,239,241,225,225,225,225,225,225,225, + 225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, + 225,225,225,225,225,225,263,225,225,225,225,234,234,225,243,234, +19,19,244,1,946, +19,19,245,1,944, +19,19,246,1,943, +19,19,247,1,942, +19,19,248,1,941, +19,19,249,1,940, +19,19,250,1,939, +19,19,251,1,938, +19,19,252,1,937, +19,19,253,1,936, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,254,1,947, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,1,255,1,900, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,256,1,865, +465,1,257,1,465, +466,1,258,1,466, +467,1,259,1,467, +468,1,260,1,468, +469,1,261,1,469, +470,1,262,1,470, +471,1,263,1,471, +472,1,264,1,472, +473,1,265,1,473, +474,1,266,1,474, +19,19,19,19,19,19,19,19,19,19,19,19,19,237,237,237,237,237,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,267,1,927, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,268,1,935, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,1,269,1,934, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,270,1,933, 475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, - 475,475,475,475,475,475,475,475,475,5,420,5,475, -476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, - 476,476,476,476,476,476,476,476,476,5,421,5,476, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,422,2,2,2,614, -477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477, - 477,477,477,477,477,477,477,477,477,5,423,5,477, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,424,2,2,2,613, -478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478, - 478,478,478,478,478,478,478,478,478,5,425,5,478, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,426,2,2,2,612, -479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, - 479,479,479,479,479,479,479,479,479,5,427,5,479, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,428,2,2,2,611, -480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480, - 480,480,480,480,480,480,480,480,480,5,429,5,480, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,430,2,2,2,610, -481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481, - 481,481,481,481,481,481,481,481,481,5,431,5,481, -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, - 482,482,482,482,482,482,482,482,482,5,432,5,482, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,433,2,2,2,608, -483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, - 483,483,483,483,483,483,483,483,483,5,434,5,483, -484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, - 484,484,484,484,484,484,484,484,484,5,435,5,484, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,544,436,2,2,2,606, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, - 485,485,485,485,485,485,485,485,485,5,437,5,485, -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, - 486,486,486,486,486,486,486,486,486,5,438,5,486, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,439,2,2,2,604, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,440,2,2,2,603, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,441,2,2,2,602, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,442,2,2,2,601, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,443,2,2,2,600, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,444,2,2,2,599, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,445,2,2,2,598, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,446,2,2,2,597, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,447,2,2,2,596, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,448,2,2,2,595, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,449,2,2,2,594, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,450,2,2,2,593, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,1,2,451,2,2,2,592, -487,452,488, -185,401,185,185,185,185,185,185,185,185,185,185,185,185,182,185,185,185,185, - 185,185,185,185,185,185,185,185,185,185,185,185,185,185,191,185,453,489, -487,54,54,54,54,454,490, -487,52,52,52,52,455,490, -487,53,53,53,53,456,490, -487,51,51,51,51,457,490, -487,458,491, -487,459,492, -10,460,493, -183,461, -60,462,161, -60,463,160, -60,464,159, -60,465,158, -60,466,157, -60,467,156, -60,468,155, -17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,5,469,5,154, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 343,344,184,82,470,162,152,348,349,163,346,164,347,267,146,151,146,367, - 365,364,363,362,361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 343,344,184,82,471,162,152,348,349,163,346,164,347,267,145,151,145,367, - 365,364,363,362,361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 343,344,184,82,472,162,152,348,349,163,346,164,347,267,144,151,144,367, - 365,364,363,362,361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 343,344,184,82,473,162,152,348,349,163,346,164,347,267,143,151,143,367, - 365,364,363,362,361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 343,344,184,82,474,162,152,348,349,163,346,164,347,267,142,151,142,367, - 365,364,363,362,361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,475,162,152,348,349,163,346,164,347,267,494, - 494,494,370,369,368,151,494,367,365,364,363,362,361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,476,162,152,348,349,163,346,164,347,267,495, - 495,495,370,369,368,151,495,367,365,364,363,362,361,360,359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,477,162,152,348,349,163,346,164,347,267,496, - 371,371,371,370,369,368,151,371,367,365,364,363,362,361,360,359,267,358, - 357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,478,162,152,348,349,163,346,164,347,267,497, - 371,371,371,370,369,368,151,371,367,365,364,363,362,361,360,359,267,358, - 357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,479,162,152,348,349,163,346,164,347,267,498, - 371,371,371,370,369,368,151,371,367,365,364,363,362,361,360,359,267,358, - 357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,480,162,152,348,349,163,346,164,347,267,499, - 371,371,371,370,369,368,151,371,367,365,364,363,362,361,360,359,267,358, - 357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,481,162,152,348,349,163,346,164,347,267,500, - 372,371,371,371,370,369,368,151,371,367,365,364,363,362,361,360,359,267, - 358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,482,162,152,348,349,163,346,164,347,267,501, - 372,371,371,371,370,369,368,151,371,367,365,364,363,362,361,360,359,267, - 358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,483,162,152,348,349,163,346,164,347,267,502, - 373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361,360,359, - 267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,484,162,152,348,349,163,346,164,347,267,503, - 373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361,360,359, - 267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,485,162,152,348,349,163,346,164,347,267,504, - 374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361,360, - 359,267,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,486,162,152,348,349,163,346,164,347,267,505, - 374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362,361,360, - 359,267,358,357, -544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, - 1,544,487,2,2,2,591, -506,506,506,506,506,506,506,506,506,5,488,5,506, -89,89,89,89,89,89,89,89,89,89,89,89,89,89,183,89,89,89,89,89,89,89,89,89,89, - 89,89,89,89,89,89,89,89,89,89,489, -507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, - 507,507,507,507,507,507,507,507,507,507,5,490,5,507, -508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508, - 508,508,508,508,508,508,508,508,508,5,491,5,508, -509,509,509,509,509,509,509,509,5,492,5,509, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, - 510,510,510,510,510,510,510,510,510,5,493,5,510, -140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, - 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, - 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, - 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, - 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, - 140,140,413,415,64,55,59,140,140,140,140,140,140,140,140,140,140,140, - 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, - 140,140,494,419,418,417,416,414, -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, - 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, - 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, - 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, - 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, - 139,139,413,415,64,55,59,139,139,139,139,139,139,139,139,139,139,139, - 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, - 139,139,495,419,418,417,416,414, -137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, - 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, - 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, - 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, - 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, - 137,137,57,58,137,137,137,137,137,137,137,137,137,137,137,137,137,137, - 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,496,421,420, -136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, - 136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, - 136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, - 136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, - 136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, - 136,136,57,58,136,136,136,136,136,136,136,136,136,136,136,136,136,136, - 136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,497,421,420, -135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, - 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, - 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, - 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, - 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, - 135,135,57,58,135,135,135,135,135,135,135,135,135,135,135,135,135,135, - 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,498,421,420, -134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, - 134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, - 134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, - 134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, - 134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, - 134,134,57,58,134,134,134,134,134,134,134,134,134,134,134,134,134,134, - 134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,499,421,420, -132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, - 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, - 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, - 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, - 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, - 132,132,422,424,426,428,132,132,132,132,132,132,132,132,132,132,132,132, - 132,132,132,132,132,132,132,132,132,132,132,132,132,500,429,427,425,423, -131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, - 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, - 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, - 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, - 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, - 131,131,422,424,426,428,131,131,131,131,131,131,131,131,131,131,131,131, - 131,131,131,131,131,131,131,131,131,131,131,131,131,501,429,427,425,423, -129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, - 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, - 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, - 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, - 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, - 129,129,430,63,129,129,129,129,129,129,129,129,129,129,129,129,129,129, - 129,129,129,129,129,129,129,129,129,502,432,431, -128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,430,63,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,503,432,431, + 475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, + 475,475,475,475,1,271,1,475, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, + 121,272,222,242,243,223,238,224,239,216,271,209,214,207,208,207,266,265, + 264,263,262,261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, + 121,273,222,242,243,223,238,224,239,216,271,209,214,206,208,206,266,265, + 264,263,262,261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, + 121,274,222,242,243,223,238,224,239,216,271,209,214,205,208,205,266,265, + 264,263,262,261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, + 121,275,222,242,243,223,238,224,239,216,271,209,214,204,208,204,266,265, + 264,263,262,261,260,259,258,257,241,240,214,255,254, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,1,276,1,197, +19,477,479,330,322,326,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,1,277,1,194,483,482,481,480,478, +19,323,325,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,1,278,1,189,485,484, +19,486,488,490,492,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,1,279,1,186,493,491,489,487, +19,494,329,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,1,280,1,183,496,495, +19,497,301,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1, + 281,1,180,499,498, +500,299,179,502,501, +503,504,505,506,507,508,509,510,511,512,513,514,515,159,159,159,159,159,283, + 163,163,163,163,166,166,166,169,169,169,172,172,172,175,175,175,178,178, + 178, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,284,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,158,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +516,516,516,516,1,285,1,516, +517,517,517,517,1,286,1,517, +518,518,518,518,518,287,518, +19,19,19,19,19,288,1,852, +519,519,519,519,1,289,1,519, +19,19,19,19,19,290,1,850, +520,520,520,520,1,291,1,520, +151,151,521,151,151,151,151,151,151,151,151,151,151,151,151,149,151,151,151, + 151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, + 151,151,151,151,151,292, +19,19,19,19,19,293,1,847, +522,522,522,522,1,294,1,522, +523,523,523,523,1,295,1,523, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,296,1,845, +126,126,126,126,126,126,126,126,126,126,126,126,150,126,126,126,126,126,132, + 126,126,297,527,225,526,292,525,226,293,524, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 298,1,1089, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,299,1,916, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 300,1,1088, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,301,1,918, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,302,1, + 1087, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 303,1,1086, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 304,1,1085, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 305,1,1084, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 306,1,1083, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 307,1,1082, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 308,1,1081, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 309,1,1080, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 310,1,1079, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 311,1,1078, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 312,1,1077, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 313,1,1076, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 314,1,1075, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 315,1,1074, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 316,1,1073, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 317,1,1072, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 318,1,1071, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 319,1,1070, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 320,1,1069, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 321,1,1068, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,322,1,929, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,323,1,927, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,324,1,888, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,325,1,926, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,326,1,928, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 327,1,863, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 328,1,1067, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,329,1,920, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,330,1,930, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 331,1,1066, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,332,1, + 1065, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 333,1,1064, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 334,1,1063, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,335,1,838, +298,300,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318, + 319,320,321,328,331,332,333,334,268,270,330,322,326,323,325,329,301,299, + 324,256,327,35,38,7,9,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, +34,337,11, +34,338,10, +405,406,408,410,411,412,414,415,416,418,420,422,424,426,428,430,432,434,436, + 437,439,440,441,443,444,446,447,448,449,451,452,288,290,528,530,339,531, + 529,67,68,62,63,450,450,450,450,73,445,445,445,442,442,442,442,438,438, + 438,435,433,431,429,427,425,423,421,419,417,99,100,413,103,104,409,407, + 109, +532,532,532,532,1,340,1,532, +533,405,37,38,39,34,341,534,64,64,42,64,41,40,40,156,157, +275,274,274,271,270,269,268,267,266,342,371,274,535, +285,284,281,278,284,281,278,343,369,278,281,284,536, +373,373,373,373,344,373, +324,345,537, +324,346,538, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,347,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,424,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,348,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,423,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,349,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,422,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,350,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,421,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,351,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,420,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,352,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,419,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,353,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,418,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,354,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,417,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,355,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,416,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,356,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,413,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,357,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,409,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,358,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,408,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,359,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,407,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,360,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,406,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,361,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,405,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,362,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,404,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,363,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,403,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,364,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,397,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,365,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,396,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,366,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,395,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,367,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,394,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,368,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,388,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,369,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,387,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,370,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,386,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,371,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,385,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,372,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,384,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,373,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,383,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,374,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,382,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,375,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,381,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,376,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,380,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,377,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,379,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,378,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,378,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,379,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,377,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,380,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,376,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,381,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,375,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,382,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,374,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +539,540,288,287,286,288,287,286,383,290,286,287,288,354,289, +539,540,288,287,286,288,287,286,384,290,286,287,288,353,289, +292,291,292,291,385,291,292,352, +292,291,292,291,386,291,292,351, +285,284,281,278,284,281,278,387,368,278,281,284,536, +285,284,281,278,284,281,278,388,367,278,281,284,536, +285,284,281,278,284,281,278,389,366,278,281,284,536, +275,274,274,271,270,269,268,267,266,390,365,274,535, +275,274,274,271,270,269,268,267,266,391,364,274,535, +275,274,274,271,270,269,268,267,266,392,363,274,535, +275,274,274,271,270,269,268,267,266,393,362,274,535, +275,274,274,271,270,269,268,267,266,394,541,274,535, +275,274,274,271,270,269,268,267,266,395,360,274,535, +275,274,274,271,270,269,268,267,266,396,359,274,535, +275,274,274,271,270,269,268,267,266,397,358,274,535, +275,274,274,271,270,269,268,267,266,398,357,274,535, +275,274,274,271,270,269,268,267,266,399,356,274,535, +275,274,274,271,270,269,268,267,266,400,355,274,535, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,542, + 234,132,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236, + 256,231,253,122,121,401,222,242,243,223,238,111,225,224,239,543,112,216, + 280,279,277,282,278,281,276,113,271,209,545,214,272,276,275,274,273,208, + 276,266,265,264,263,262,261,260,259,258,257,241,240,226,214,544,255,254, +232,238,238,238,238,235,237,546,233,476,236,253,18,402,110,242,547,224,239, + 241,240,255, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,403,1,950, +548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548, + 548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548, + 548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548, + 548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548, + 548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548, + 548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548, + 548,1,404,1,548, +19,19,19,19,19,405,1,899, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,406,1,898, +123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,407,106,214,214, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,408,1,897, 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, - 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, - 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, - 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, - 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, - 126,126,433,42,126,126,126,126,126,126,126,126,126,126,126,126,126,126, - 126,126,126,126,126,126,126,504,435,434, -125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, - 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, - 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, - 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, - 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, - 125,125,433,42,125,125,125,125,125,125,125,125,125,125,125,125,125,125, - 125,125,125,125,125,125,125,505,435,434, -83,83,83,83,83,83,83,83,82,506,80,267,267, -83,83,83,83,83,83,83,174,174,342,341,383,83,92,350,351,352,353,354,355,356, - 61,39,366,67,343,344,184,82,507,162,152,348,349,163,346,77,272,164,347, - 339,78,76,267,376,375,374,373,372,371,371,371,370,369,368,151,371,367, - 365,364,363,362,361,360,359,273,267,340,358,357, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,508,162,152,348,349,163,346,164,347,271,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, -204,201,199,197,203,202,200,198,509,270,390, -83,83,83,83,83,83,83,174,174,342,341,345,83,350,351,352,353,354,355,356,61, - 39,366,67,343,344,184,82,510,162,152,348,349,163,346,164,347,269,267, - 376,375,374,373,372,371,371,371,370,369,368,151,371,367,365,364,363,362, - 361,360,359,267,358,357, + 409,105,524, +19,19,19,19,19,410,1,896, +19,19,19,19,19,411,1,895, +19,19,1,412,1,894, +549,132,413,102,225,543,101,226,544, +19,19,19,19,19,414,1,892, +19,19,19,19,19,415,1,891, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,416,1,890, +123,123,123,123,123,123,123,123,123,123,123,123,123,94,94,94,94,122,121,94, + 417,95,214,214, +19,1,418,1,889, +132,419,550,225,226, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,420,1,887, +551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, + 551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, + 551,551,551,551,551,1,421,1,551, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,422,1,886, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,132,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236, + 256,231,253,122,121,423,222,242,243,223,238,91,225,224,239,216,280,279, + 277,282,278,281,276,90,271,209,214,272,276,275,274,273,208,276,266,265, + 264,263,262,261,260,259,258,257,241,240,226,214,255,254, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,424,1,885, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,425,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,89,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,426,1,884, +123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,427,88,214,214, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,428,1,883, +123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,429,87,214,214, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,430,1,882, +123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,431,117,552,214, + 214, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,432,1,881, +123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,433,117,553,214, + 214, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,434,1,880, +123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,435,117,554,214, + 214, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,436,1,879, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,437,1,878, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,542, + 234,132,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236, + 256,231,253,122,121,438,222,242,243,223,238,111,225,224,239,543,112,216, + 280,279,277,282,278,281,276,113,271,209,555,214,272,276,275,274,273,208, + 276,266,265,264,263,262,261,260,259,258,257,241,240,226,214,544,255,254, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,439,1,877, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,440,1,876, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,441,1,875, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,542, + 234,132,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236, + 256,231,253,122,121,442,222,242,243,223,238,111,225,224,239,543,112,216, + 280,279,277,282,278,281,276,113,271,209,556,214,272,276,275,274,273,208, + 276,266,265,264,263,262,261,260,259,258,257,241,240,226,214,544,255,254, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,443,1,874, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,444,1,873, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,445,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,76,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +19,19,19,19,19,446,1,872, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,447,1,871, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,448,1,870, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,449,1,869, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,450,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,72,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +19,19,19,19,19,19,19,451,1,868, +19,19,19,19,19,19,19,452,1,867, +37,38,39,34,453,21,21,42,21,41,40,40, +557,454,558, +298,300,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319, + 320,321,328,331,333,334,268,270,330,322,326,323,325,329,301,299,324,256, + 327,35,38,455,59,59,559,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59, + 59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59, +37,38,39,34,456,53,53,42,53,41,40,40, +136,560,138,139,137,143,142,561,561,562,560,141,134,457,560, +37,38,39,34,458,52,52,42,52,41,40,40, +37,38,39,34,459,49,49,42,49,41,40,40, +242,242,242,242,242,242,242,242,242,460, +255,257,258,256,259,261,461, +254,461,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, + 254,254,251,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, + 254,254,254,254,254,260,254,462,563, +245,245,245,245,245,245,245,245,245,245,235,235,235,235,235,235,235,235,235, + 235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, + 235,235,235,235,235,235,235,235,235,235,235,463, +245,245,245,245,245,245,245,245,245,245,231,231,231,231,231,231,231,231,231, + 231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, + 231,231,231,231,231,231,231,231,231,231,231,464, +256,465,564, +256,466,565, +256,467,566, +256,468,567, +256,469,568, +256,470,569, +256,471,570, +256,472,571, +256,473,572, +256,474,573, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,475,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,574,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +237,237,237,237,237,476, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,477,1,932, +575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575, + 575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575, + 575,1,478,1,575, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,479,1,931, +576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576, + 576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576, + 576,1,480,1,576, +577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577, + 577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577, + 577,1,481,1,577, +578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578, + 578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578, + 578,1,482,1,578, +579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579, + 579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579, + 579,1,483,1,579, +580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580, + 580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580, + 580,580,580,580,1,484,1,580, +581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, + 581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, + 581,581,581,581,1,485,1,581, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,486,1,925, +582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582, + 582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582, + 582,582,582,582,1,487,1,582, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,488,1,924, +583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583, + 583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583, + 583,583,583,583,1,489,1,583, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,490,1,923, +584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584, + 584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584, + 584,584,584,584,1,491,1,584, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,492,1,922, +585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585, + 585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585, + 585,585,585,585,1,493,1,585, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,494,1,921, +586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, + 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, + 586,586,586,586,1,495,1,586, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, + 587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, + 587,587,587,587,1,496,1,587, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,497,1,919, +588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588, + 588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588, + 588,588,588,588,1,498,1,588, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, + 589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, + 589,589,589,589,1,499,1,589, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,500,1,917, +590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590, + 590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590, + 590,590,590,590,1,501,1,590, +591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591, + 591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591, + 591,591,591,591,1,502,1,591, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,503,1,915, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,504,1,914, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,505,1,913, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,506,1,912, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,507,1,911, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,508,1,910, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,509,1,909, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,510,1,908, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,511,1,907, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,512,1,906, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,513,1,905, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,514,1,904, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,515,1,903, +37,38,39,34,516,48,48,42,48,41,40,40, +37,38,39,34,517,47,47,42,47,41,40,40, +37,38,39,34,518,46,46,42,46,41,40,40, +37,38,39,34,519,43,43,42,43,41,40,40, +37,38,39,34,520,42,42,42,42,41,40,40, +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, + 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, + 152,152,152,152,152,153,152,521, +37,38,39,34,522,41,41,42,41,41,40,40, +37,38,39,34,523,40,40,42,40,41,40,40, +127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, + 19,19,19,524,1,848, +592,592,592,592,1,525,1,592, +593,593,593,593,1,526,1,593, +594,594,594,594,1,527,1,594, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,528,1,843, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,529,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,595,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,530,1,842, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,531,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,596,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +37,38,39,34,532,22,22,42,22,41,40,40, +19,19,19,19,19,533,1,902, +597,597,597,597,1,534,1,597, +19,19,19,19,19,19,19,19,535,1,997, +19,19,19,19,19,19,19,536,1,1009, +598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598, + 598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598, + 598,598,598,598,1,537,1,598, +599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599, + 599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599, + 599,599,599,599,1,538,1,599, +19,19,19,19,19,19,539,1,949, +19,19,19,19,19,19,540,1,948, +600,1,541,1,600, +254,461,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, + 254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, + 254,254,254,254,260,254,542,601, +254,461,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, + 254,254,128,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, + 254,254,254,254,254,260,254,543,130, +19,19,19,19,19,19,19,544,1,893, +602,327,545,57,603, +243,243,243,243,243,243,243,243,243,546, +240,230,245,463,464,245,239,239,239,239,239,241,225,225,225,225,234,234,225, + 547,234, +107,108,109,110,111,112,113,114,61,62,63,64,65,115,116,117,118,119,120,66, + 67,68,69,70,121,122,123,71,72,73,74,75,124,125,126,127,128,129,130,131, + 132,133,134,135,136,137,138,104,59,60,143,144,145,146,147,148,149,150, + 151,152,153,154,155,156,139,140,141,142,76,77,78,79,80,45,46,47,81,82, + 83,84,85,86,87,88,89,48,49,90,91,92,93,94,95,96,97,50,51,52,98,99,53,54, + 100,101,102,103,55,56,57,58,548,604,605,605,605,605,605,605,605,605,605, + 605,308,308,308,308,308,309,310,311,312,315,315,315,316,317,321,321,321, + 321,322,323,324,325,326,327,328,329,332,332,332,333,334,335,336,337,338, + 339,340,341,345,345,345,345,346,347,348,349,350,199,198,197,196,213,212, + 211,210,209,208,207,206,205,204,203,202,201,200,159,106,158,105,157,195, + 194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,180,180,180, + 180,180,179,178,177,176,176,176,176,176,176,175,174,173,172,171,170,169, + 169,169,169,168,168,168,167,166,165,164,163,162,161,160, +254,461,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, + 254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, + 254,254,254,254,260,254,549,606, +324,550,607, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,542, + 234,132,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236, + 256,231,253,122,121,551,222,242,243,223,238,111,225,224,239,543,112,216, + 280,279,277,282,278,281,276,113,271,209,608,214,272,276,275,274,273,208, + 276,266,265,264,263,262,261,260,259,258,257,241,240,226,214,544,255,254, +602,86,86,86,86,86,552,609, +602,85,85,85,85,85,553,609, +602,84,84,84,84,84,554,609, +602,83,83,83,83,83,555,603, +602,80,80,80,80,80,556,603, +19,1,557,1,864, +327,558,55, +298,300,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319, + 320,321,328,331,333,334,268,270,330,322,326,323,325,329,301,299,324,610, + 256,327,35,38,612,611,559,60,1,612,60,60,60,61,60,60,60,60,60,60,60,60, + 60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60, + 60,60,60,60, +613,613,613,613,613,613,613,613,613,560, +614,614,614,614,614,561, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,614,614,614, + 614,614,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, + 140,140,140,140,140,140,562, +252,563, +615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,1,564,1,615, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,565,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,616,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,566,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,617,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,567,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,618,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,568,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,619,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,569,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,620,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,570,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,621,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,571,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,622,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,572,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,623,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,573,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,624,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +625,1,574,1,625, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, + 121,575,222,242,243,223,238,224,239,216,271,209,214,202,208,202,266,265, + 264,263,262,261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, + 121,576,222,242,243,223,238,224,239,216,271,209,214,201,208,201,266,265, + 264,263,262,261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, + 121,577,222,242,243,223,238,224,239,216,271,209,214,200,208,200,266,265, + 264,263,262,261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, + 121,578,222,242,243,223,238,224,239,216,271,209,214,199,208,199,266,265, + 264,263,262,261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, + 121,579,222,242,243,223,238,224,239,216,271,209,214,198,208,198,266,265, + 264,263,262,261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,580,222,242,243,223,238,224,239,216,626,276,271,209,214, + 272,276,275,274,273,208,276,266,265,264,263,262,261,260,259,258,257,241, + 240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,581,222,242,243,223,238,224,239,216,627,276,271,209,214, + 272,276,275,274,273,208,276,266,265,264,263,262,261,260,259,258,257,241, + 240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,582,222,242,243,223,238,224,239,216,277,628,276,271,209, + 214,272,276,275,274,273,208,276,266,265,264,263,262,261,260,259,258,257, + 241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,583,222,242,243,223,238,224,239,216,277,629,276,271,209, + 214,272,276,275,274,273,208,276,266,265,264,263,262,261,260,259,258,257, + 241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,584,222,242,243,223,238,224,239,216,277,630,276,271,209, + 214,272,276,275,274,273,208,276,266,265,264,263,262,261,260,259,258,257, + 241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,585,222,242,243,223,238,224,239,216,277,631,276,271,209, + 214,272,276,275,274,273,208,276,266,265,264,263,262,261,260,259,258,257, + 241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,586,222,242,243,223,238,224,239,216,632,277,278,276,271, + 209,214,272,276,275,274,273,208,276,266,265,264,263,262,261,260,259,258, + 257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,587,222,242,243,223,238,224,239,216,633,277,278,276,271, + 209,214,272,276,275,274,273,208,276,266,265,264,263,262,261,260,259,258, + 257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,588,222,242,243,223,238,224,239,216,634,279,277,278,276, + 271,209,214,272,276,275,274,273,208,276,266,265,264,263,262,261,260,259, + 258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,589,222,242,243,223,238,224,239,216,635,279,277,278,276, + 271,209,214,272,276,275,274,273,208,276,266,265,264,263,262,261,260,259, + 258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,590,222,242,243,223,238,224,239,216,280,279,277,278,636, + 276,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262,261,260, + 259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,591,222,242,243,223,238,224,239,216,280,279,277,278,637, + 276,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262,261,260, + 259,258,257,241,240,214,255,254, +37,38,39,34,592,34,34,42,34,41,40,40, +37,38,39,34,593,33,33,42,33,41,40,40, +37,38,39,34,594,32,32,42,32,41,40,40, +638,638,638,638,1,595,1,638, +639,639,639,639,1,596,1,639, +37,38,39,34,597,65,65,42,65,41,40,40, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,598,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,372,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,599,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,370,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +602,600,640, +254,461,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, + 254,254,251,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, + 254,254,254,254,254,260,254,601,641, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,602,1,901, +642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, + 642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, + 642,642,642,642,642,1,603,1,642, +403,604,404, +19,303,303,303,303,1,605,1,293, +254,461,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, + 254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, + 254,254,254,254,260,254,606,129, +643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643, + 643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643, + 643,643,643,643,1,607,1,643, +602,92,92,92,92,92,608,603, +644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,1,609,1,644, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,610,1,866, +60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60, + 60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,17,17,17,17,17,611, +37,38,39,34,612,54,54,42,54,41,40,40, +148,148,148,148,148,148,148,148,147,147,147,147,148,148,148,148,147,147,147, + 147,147,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, + 148,148,148,148,148,148,613, +144,144,144,144,144,614, +123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,615,647,645,645, + 646, +327,616,220, +327,617,219, +327,618,218, +327,619,217, +327,620,216, +327,621,215, +327,622,214, +327,623,213, +327,624,212, +327,625,211, +196,477,479,330,322,326,196,196,196,196,196,196,196,196,196,196,196,196,196, + 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,626, + 483,482,481,480,478, +195,477,479,330,322,326,195,195,195,195,195,195,195,195,195,195,195,195,195, + 195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,627, + 483,482,481,480,478, +193,323,325,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, + 193,193,193,193,193,193,193,193,193,193,193,193,193,193,628,485,484, +192,323,325,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, + 192,192,192,192,192,192,192,192,192,192,192,192,192,192,629,485,484, +191,323,325,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, + 191,191,191,191,191,191,191,191,191,191,191,191,191,191,630,485,484, +190,323,325,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, + 190,190,190,190,190,190,190,190,190,190,190,190,190,190,631,485,484, +188,486,488,490,492,188,188,188,188,188,188,188,188,188,188,188,188,188,188, + 188,188,188,188,188,188,188,188,188,188,188,188,632,493,491,489,487, +187,486,488,490,492,187,187,187,187,187,187,187,187,187,187,187,187,187,187, + 187,187,187,187,187,187,187,187,187,187,187,187,633,493,491,489,487, +185,494,329,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, + 185,185,185,185,185,185,185,185,634,496,495, +184,494,329,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, + 184,184,184,184,184,184,184,184,635,496,495, +182,497,301,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, + 182,182,182,182,182,182,636,499,498, +181,497,301,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, + 181,181,181,181,181,181,637,499,498, +37,38,39,34,638,29,29,42,29,41,40,40, +37,38,39,34,639,28,28,42,28,41,40,40, +648,648,648,648,648,648,648,648,648,1,640,1,648, +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,252,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,641, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,542, + 234,132,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236, + 256,231,253,122,121,642,222,242,243,223,238,115,225,224,239,543,116,216, + 280,279,277,282,278,281,276,114,271,209,214,272,276,275,274,273,208,276, + 266,265,264,263,262,261,260,259,258,257,241,240,226,214,544,255,254, +123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, + 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, + 231,253,122,121,643,222,242,243,223,238,224,239,216,280,279,277,282,278, + 281,276,93,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, + 261,260,259,258,257,241,240,214,255,254, +123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,644,118,214,214, +124,124,124,124,124,124,124,124,124,124,124,124,125,125,125,125,125,124,19, + 124,1,645,1,119,125, +19,19,646,1,945, +649,1,647,1,649, +275,274,274,271,270,269,268,267,266,648,361,274,535, +327,649,221, }; static const unsigned short ag_sbt[] = { - 0, 141, 178, 183, 327, 364, 366, 369, 527, 670, 812, 863, 904, 945, - 1016,1087,1158,1178,1194,1210,1221,1232,1248,1264,1273,1282,1304,1429, - 1656,1667,1680,1693,1706,1719,1724,1733,1757,1878,1888,1929,1979,2030, - 2071,2122,2163,2204,2245,2286,2327,2368,2409,2450,2491,2532,2665,2798, - 2848,2889,2940,2991,3041,3197,3248,3289,3340,3390,3431,3472,3614,3655, - 3723,3726,3729,3732,3835,3870,3885,3988,4023,4038,4141,4150,4185,4288, - 4391,4494,4529,4564,4579,4682,4691,4794,4897,5000,5103,5206,5309,5412, - 5515,5618,5721,5824,5927,6030,6133,6145,6157,6260,6295,6330,6345,6448, - 6463,6478,6489,6592,6627,6662,6697,6706,6741,6776,6811,6846,6881,6916, - 6951,6986,7021,7056,7091,7126,7161,7196,7207,7222,7257,7360,7463,7566, - 7669,7680,7695,7706,7809,7844,7879,7914,7949,7984,8019,8054,8069,8172, - 8275,8310,8345,8380,8483,8518,8533,8568,8583,8598,8633,8665,8677,8709, - 8721,8727,8759,8791,8823,8835,8841,8850,8859,8891,8923,8935,8947,8959, - 8967,8999,9031,9063,9069,9101,9133,9165,9197,9229,9261,9293,9325,9357, - 9389,9421,9453,9485,9517,9525,9537,9569,9577,9589,9597,9629,9661,9693, - 9725,9757,9789,9821,9833,9865,9897,9929,9961,9973,10005,10017,10029, - 10061,10161,10177,10190,10210,10226,10237,10248,10255,10264,10273,10284, - 10295,10330,10395,10415,10432,10467,10530,10546,10559,10575,10589,10605, - 10619,10635,10649,10685,10756,10792,10863,10898,10961,10972,10983,10994, - 11029,11092,11163,11234,11297,11332,11395,11430,11493,11537,11548,11559, - 11593,11604,11639,11651,11674,11737,11800,11863,11874,11937,11948,11954, - 12017,12080,12143,12154,12159,12171,12183,12246,12309,12320,12331,12342, - 12349,12412,12475,12538,12544,12607,12670,12733,12796,12859,12922,12985, - 13048,13111,13174,13237,13300,13363,13426,13433,13444,13507,13514,13525, - 13532,13595,13658,13721,13784,13847,13910,13973,13984,14047,14110,14173, - 14236,14247,14310,14321,14332,14395,14581,14596,14632,14669,14681,14685, - 14828,14832,14836,14872,14876,14882,15017,15130,15138,15146,15154,15162, - 15170,15178,15186,15321,15456,15459,15462,15465,15468,15471,15474,15477, - 15509,15572,15621,15670,15719,15730,15735,15744,15749,15754,15759,15797, - 15860,15868,15877,15886,15895,15931,15940,15949,15958,15967,16003,16039, - 16143,16246,16349,16452,16555,16658,16663,16668,16771,16776,16793,16800, - 16836,16841,16878,16941,17004,17067,17130,17193,17256,17319,17322,17354, - 17383,17415,17444,17473,17502,17531,17563,17595,17630,17662,17697,17729, - 17764,17796,17831,17863,17898,17930,17962,17997,18029,18061,18096,18128, - 18160,18195,18230,18265,18300,18335,18370,18405,18440,18475,18510,18545, - 18580,18615,18618,18655,18662,18669,18676,18683,18686,18689,18692,18694, - 18697,18700,18703,18706,18709,18712,18715,18847,18896,18945,18994,19043, - 19092,19149,19206,19264,19322,19380,19438,19497,19556,19616,19676,19737, - 19798,19842,19855,19891,19924,19956,19968,20000,20135,20270,20397,20524, - 20651,20778,20905,21032,21153,21274,21393,21512,21525,21595,21658,21669, - 21732 + 0, 27, 29, 66, 81, 110, 134, 306, 309, 326, 498, 813, 849, 868, + 887, 892, 900, 908, 927, 972,1017,1036,1042,1067,1087,1106,1111,1119, + 1127,1146,1231,1316,1335,1340,1349,1405,1493,1499,1548,1599,1646,1740, + 1829,1918,2239,2249,2258,2267,2276,2285,2294,2303,2312,2321,2330,2339, + 2348,2357,2366,2375,2388,2399,2444,2489,2534,2579,2624,2669,2714,2759, + 2804,2849,2894,2939,2984,3029,3074,3083,3092,3101,3110,3119,3128,3137, + 3146,3155,3164,3173,3182,3191,3200,3209,3218,3227,3236,3245,3254,3263, + 3272,3281,3290,3299,3308,3317,3326,3334,3347,3358,3403,3448,3493,3538, + 3583,3628,3673,3718,3763,3808,3853,3898,3943,3988,4033,4078,4123,4168, + 4213,4258,4303,4348,4393,4438,4483,4528,4573,4618,4663,4708,4753,4798, + 4810,4822,4830,4838,4849,4860,4871,4884,4897,4910,4923,4936,4949,4962, + 4975,4988,5001,5014,5022,5027,5032,5077,5122,5167,5212,5257,5302,5347, + 5392,5437,5482,5527,5572,5617,5662,5707,5752,5797,5842,5887,5932,5977, + 6022,6067,6112,6157,6202,6247,6292,6337,6382,6427,6472,6517,6562,6607, + 6652,6664,6676,6684,6692,6703,6714,6725,6738,6751,6764,6777,6790,6803, + 6816,6829,6842,6855,6868,6928,6937,6978,6985,6988,7073,7144,7152,7195, + 7239,7247,7292,7303,7311,7323,7335,7343,7349,7354,7357,7416,7471,7477, + 7522,7528,7539,7582,7623,7671,7724,7729,7734,7739,7744,7749,7754,7759, + 7764,7769,7774,7815,7856,7922,7927,7932,7937,7942,7947,7952,7957,7962, + 7967,7972,8014,8078,8120,8184,8229,8297,8365,8433,8501,8542,8586,8624, + 8662,8694,8724,8729,8767,8850,8858,8866,8873,8881,8889,8897,8905,8948, + 8956,8964,8972,8997,9027,9078,9143,9194,9259,9308,9359,9410,9461,9512, + 9563,9614,9665,9716,9767,9818,9869,9920,9971,10022,10073,10124,10175, + 10226,10277,10341,10406,10471,10536,10600,10675,10726,10791,10855,10906, + 10955,11006,11057,11113,11199,11202,11205,11280,11288,11305,11318,11331, + 11337,11340,11343,11426,11509,11592,11675,11758,11841,11924,12007,12090, + 12173,12256,12339,12422,12505,12588,12671,12754,12837,12920,13003,13086, + 13169,13252,13335,13418,13501,13584,13667,13750,13833,13916,13999,14082, + 14165,14248,14331,14346,14361,14369,14377,14390,14403,14416,14429,14442, + 14455,14468,14481,14494,14507,14520,14533,14546,14559,14650,14672,14786, + 14900,14908,14927,14946,14969,14991,14999,15007,15013,15022,15030,15038, + 15061,15085,15090,15095,15141,15187,15233,15320,15365,15448,15467,15486, + 15505,15524,15543,15563,15582,15602,15621,15641,15687,15733,15824,15870, + 15916,15962,16053,16098,16143,16226,16234,16279,16324,16369,16452,16462, + 16472,16484,16487,16569,16581,16596,16608,16620,16630,16637,16683,16732, + 16781,16784,16787,16790,16793,16796,16799,16802,16805,16808,16811,16894, + 16900,16942,16984,17026,17068,17110,17152,17194,17239,17284,17329,17374, + 17419,17464,17509,17554,17599,17644,17689,17734,17779,17824,17869,17914, + 17959,18004,18049,18094,18139,18184,18229,18274,18319,18364,18409,18454, + 18499,18544,18589,18634,18646,18658,18670,18682,18694,18739,18751,18763, + 18788,18796,18804,18812,18857,18940,18985,19068,19080,19088,19096,19107, + 19117,19162,19207,19216,19225,19230,19275,19321,19331,19336,19346,19367, + 19610,19655,19658,19749,19757,19765,19773,19781,19789,19794,19797,19884, + 19894,19900,19944,19946,19965,20048,20131,20214,20297,20380,20463,20546, + 20629,20712,20717,20785,20853,20921,20989,21057,21134,21211,21289,21367, + 21445,21523,21602,21681,21761,21841,21922,22003,22015,22027,22039,22047, + 22055,22067,22150,22233,22236,22282,22337,22383,22386,22395,22440,22485, + 22493,22512,22560,22606,22618,22662,22668,22688,22691,22694,22697,22700, + 22703,22706,22709,22712,22715,22718,22760,22802,22838,22874,22910,22946, + 22982,23018,23048,23078,23106,23134,23146,23158,23171,23216,23306,23389, + 23408,23433,23438,23443,23456,23459 }; static const unsigned short ag_sbe[] = { - 136, 176, 180, 320, 363, 365, 367, 504, 665, 807, 858, 899, 940, 980, - 1051,1122,1172,1189,1205,1216,1227,1243,1259,1268,1277,1299,1424,1541, - 1661,1676,1689,1702,1715,1721,1726,1748,1875,1882,1924,1974,2025,2066, - 2117,2158,2199,2240,2281,2322,2363,2404,2445,2486,2527,2660,2793,2843, - 2884,2935,2986,3036,3192,3243,3284,3335,3385,3426,3467,3609,3650,3689, - 3724,3727,3730,3830,3865,3880,3983,4018,4033,4136,4145,4180,4283,4386, - 4489,4524,4559,4574,4677,4686,4789,4892,4995,5098,5201,5304,5407,5510, - 5613,5716,5819,5922,6025,6128,6140,6152,6255,6290,6325,6340,6443,6458, - 6473,6484,6587,6622,6657,6692,6701,6736,6771,6806,6841,6876,6911,6946, - 6981,7016,7051,7086,7121,7156,7191,7202,7217,7252,7355,7458,7561,7664, - 7675,7690,7701,7804,7839,7874,7909,7944,7979,8014,8049,8064,8167,8270, - 8305,8340,8375,8478,8513,8528,8563,8578,8593,8628,8662,8674,8706,8718, - 8724,8756,8788,8820,8832,8838,8847,8856,8888,8920,8932,8944,8956,8964, - 8996,9028,9060,9066,9098,9130,9162,9194,9226,9258,9290,9322,9354,9386, - 9418,9450,9482,9514,9522,9534,9566,9574,9586,9594,9626,9658,9690,9722, - 9754,9786,9818,9830,9862,9894,9926,9958,9970,10002,10014,10026,10058, - 10158,10172,10186,10205,10223,10232,10243,10253,10259,10266,10279,10290, - 10325,10358,10410,10428,10462,10495,10541,10555,10570,10584,10600,10614, - 10630,10644,10680,10714,10787,10821,10893,10926,10967,10978,10989,11024, - 11057,11121,11192,11262,11327,11360,11425,11458,11531,11543,11554,11592, - 11599,11638,11646,11669,11702,11765,11828,11871,11902,11945,11950,11982, - 12045,12108,12151,12156,12164,12176,12211,12274,12317,12328,12339,12346, - 12377,12440,12503,12540,12572,12635,12698,12761,12824,12887,12950,13013, - 13076,13139,13202,13265,13328,13391,13430,13441,13472,13511,13522,13529, - 13560,13623,13686,13749,13812,13875,13938,13981,14012,14075,14138,14201, - 14244,14275,14318,14329,14360,14487,14589,14630,14667,14676,14684,14827, - 14831,14835,14870,14875,14881,15016,15129,15133,15141,15149,15157,15165, - 15173,15181,15316,15451,15457,15460,15463,15466,15469,15472,15475,15504, - 15537,15597,15646,15695,15724,15732,15739,15746,15751,15756,15777,15825, - 15865,15874,15883,15892,15929,15937,15946,15955,15964,16002,16038,16138, - 16241,16344,16447,16550,16653,16660,16665,16766,16773,16792,16799,16834, - 16840,16876,16906,16969,17032,17095,17158,17221,17284,17320,17349,17380, - 17410,17441,17470,17499,17528,17560,17592,17625,17659,17692,17726,17759, - 17793,17826,17860,17893,17927,17959,17992,18026,18058,18091,18125,18157, - 18190,18225,18260,18295,18330,18365,18400,18435,18470,18505,18540,18575, - 18610,18616,18653,18660,18667,18674,18681,18684,18687,18690,18693,18695, - 18698,18701,18704,18707,18710,18713,18844,18872,18921,18970,19019,19068, - 19120,19177,19234,19292,19350,19408,19466,19525,19584,19644,19704,19765, - 19837,19852,19890,19921,19953,19965,19997,20129,20264,20394,20521,20648, - 20775,20900,21027,21150,21271,21390,21509,21521,21554,21623,21666,21697,21732 + 24, 28, 52, 78, 108, 121, 303, 307, 316, 495, 667, 837, 865, 884, + 889, 897, 905, 924, 969,1014,1033,1039,1064,1082,1102,1107,1116,1124, + 1142,1187,1272,1331,1337,1342,1402,1490,1495,1545,1596,1643,1692,1784, + 1873,2086,2246,2255,2264,2273,2282,2291,2300,2309,2318,2327,2336,2345, + 2354,2363,2372,2385,2396,2441,2486,2531,2576,2621,2666,2711,2756,2801, + 2846,2891,2936,2981,3026,3071,3080,3089,3098,3107,3116,3125,3134,3143, + 3152,3161,3170,3179,3188,3197,3206,3215,3224,3233,3242,3251,3260,3269, + 3278,3287,3296,3305,3314,3323,3331,3344,3355,3400,3445,3490,3535,3580, + 3625,3670,3715,3760,3805,3850,3895,3940,3985,4030,4075,4120,4165,4210, + 4255,4300,4345,4390,4435,4480,4525,4570,4615,4660,4705,4750,4795,4807, + 4819,4827,4835,4846,4857,4868,4881,4894,4907,4920,4933,4946,4959,4972, + 4985,4998,5011,5019,5024,5029,5074,5119,5164,5209,5254,5299,5344,5389, + 5434,5479,5524,5569,5614,5659,5704,5749,5794,5839,5884,5929,5974,6019, + 6064,6109,6154,6199,6244,6289,6334,6379,6424,6469,6514,6559,6604,6649, + 6661,6673,6681,6689,6700,6711,6722,6735,6748,6761,6774,6787,6800,6813, + 6826,6839,6852,6865,6924,6934,6976,6983,6986,7029,7106,7149,7193,7236, + 7244,7290,7300,7308,7315,7327,7340,7348,7353,7356,7415,7470,7476,7520, + 7527,7538,7581,7622,7670,7722,7726,7731,7736,7741,7746,7751,7756,7761, + 7766,7771,7812,7853,7919,7924,7929,7934,7939,7944,7949,7954,7959,7964, + 7969,8011,8075,8117,8181,8226,8267,8335,8403,8471,8539,8578,8619,8655, + 8689,8719,8726,8747,8808,8855,8863,8871,8878,8886,8894,8902,8947,8953, + 8961,8969,8994,9018,9075,9140,9191,9256,9305,9356,9407,9458,9509,9560, + 9611,9662,9713,9764,9815,9866,9917,9968,10019,10070,10121,10172,10223, + 10274,10338,10403,10468,10533,10597,10672,10723,10788,10852,10903,10952, + 11003,11054,11110,11156,11200,11203,11240,11285,11294,11314,11325,11335, + 11338,11341,11384,11467,11550,11633,11716,11799,11882,11965,12048,12131, + 12214,12297,12380,12463,12546,12629,12712,12795,12878,12961,13044,13127, + 13210,13293,13376,13459,13542,13625,13708,13791,13874,13957,14040,14123, + 14206,14289,14339,14354,14365,14373,14384,14397,14410,14425,14438,14451, + 14464,14477,14490,14503,14516,14529,14542,14555,14601,14663,14783,14897, + 14905,14924,14942,14966,14988,14996,15004,15010,15015,15027,15035,15058, + 15081,15087,15091,15138,15184,15230,15275,15362,15406,15464,15482,15502, + 15520,15540,15558,15579,15597,15618,15636,15684,15730,15775,15867,15913, + 15959,16004,16095,16140,16184,16231,16276,16321,16366,16410,16459,16469, + 16476,16485,16527,16573,16594,16600,16612,16629,16636,16681,16731,16780, + 16782,16785,16788,16791,16794,16797,16800,16803,16806,16809,16852,16899, + 16939,16981,17023,17065,17107,17149,17191,17236,17281,17326,17371,17416, + 17461,17506,17551,17596,17641,17686,17731,17776,17821,17866,17911,17956, + 18001,18046,18091,18136,18181,18226,18271,18316,18361,18406,18451,18496, + 18541,18586,18631,18638,18650,18662,18674,18686,18738,18743,18755,18785, + 18793,18801,18809,18854,18898,18982,19026,19072,19085,19093,19104,19114, + 19159,19204,19213,19222,19227,19273,19319,19328,19333,19345,19365,19477, + 19653,19656,19700,19755,19763,19771,19779,19787,19791,19795,19840,19893, + 19899,19943,19945,19962,20006,20089,20172,20255,20338,20421,20504,20587, + 20670,20714,20755,20823,20891,20959,21027,21098,21175,21252,21330,21408, + 21486,21564,21643,21722,21802,21882,21963,22007,22019,22031,22044,22052, + 22059,22108,22191,22234,22280,22334,22380,22384,22392,22438,22482,22491, + 22509,22557,22605,22610,22661,22667,22683,22689,22692,22695,22698,22701, + 22704,22707,22710,22713,22716,22754,22796,22835,22871,22907,22943,22977, + 23013,23045,23075,23103,23131,23138,23150,23168,23215,23258,23347,23404, + 23429,23435,23440,23452,23457,23459 }; static const unsigned char ag_fl[] = { - 2,1,1,2,2,1,2,0,1,3,3,3,1,2,3,1,2,0,1,3,3,2,2,2,2,1,2,2,2,2,2,2,2,2,2, - 1,1,2,2,3,3,3,3,0,1,3,2,2,2,3,3,4,4,4,4,3,3,3,3,3,2,3,4,2,2,3,3,4,2,2, - 3,3,3,1,1,1,5,5,5,1,5,1,1,1,2,2,1,2,2,3,2,2,1,2,3,3,2,1,2,3,3,2,2,1,1, - 1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,4,4,1,4,4,1,4,4,1,4,4,4,4,1,4, - 4,1,4,4,4,4,4,1,2,2,2,1,1,1,4,4,4,4,4,4,4,4,1,1,1,1,1,2,2,2,2,2,2,2,1, - 2,2,2,3,2,2,2,3,4,1,1,2,2,2,2,2,1,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,1,3,3,3,1,1,3,3,3,3,3,3,3,3,1,3,3,3,1,1, - 1,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,7,7,7,1,3,3,3,1,3,3,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,3,3,1,1,1,3,3,1,3,3,1,3,3,1,1,1,1,1,1, + 2,1,1,2,2,1,1,2,0,1,3,3,1,2,1,2,2,1,2,0,1,4,5,3,2,1,0,1,7,7,1,1,6,6,6, + 2,3,2,1,2,4,4,4,4,0,1,4,4,4,4,3,3,4,4,6,4,1,4,1,1,2,2,2,2,3,5,1,2,2,1, + 1,1,3,2,1,1,3,1,1,1,3,1,1,3,3,3,3,3,3,3,3,3,4,6,2,3,2,1,1,2,2,3,3,2,2, + 3,3,1,1,2,3,1,1,1,4,4,4,1,4,2,1,1,1,1,2,2,1,2,2,3,2,2,1,2,3,1,2,2,2,2, + 2,2,2,2,4,1,1,4,3,2,1,2,3,3,2,1,1,1,2,1,1,1,1,2,1,1,2,1,1,2,1,1,2,1,1, + 2,1,1,2,1,2,4,4,2,4,4,2,4,4,2,4,4,4,4,2,4,4,2,4,4,4,4,4,1,2,2,2,2,1,1, + 1,5,5,5,5,5,5,5,5,5,5,7,1,1,1,1,1,1,1,2,2,2,1,1,2,2,2,2,1,2,2,2,3,2,2, + 2,2,2,2,2,2,3,4,1,1,2,2,2,2,2,1,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,3,3,3,3,3,3,3,3,3,3,7,3,3,3,3,3,3,3,3,5,3,5,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,1,1,1,1,1,3,3,3,3,1,1,1,1,1,3,3,3,3,3,3,3,1,1,1,3,1,1,3,3,3,3, + 3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2 }; static const unsigned short ag_ptt[] = { - 0, 24, 25, 25, 22, 30, 30, 31, 31, 27, 27, 27, 37, 37, 2, 39, 39, 40, - 40, 23, 23, 23, 23, 23, 23, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 58, 58, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 65, 65, 65, 65, 65, 65, 68, 68,299,299, 85, 85, 85,294,294,324, 19, - 19,291, 13, 13, 13, 13,293, 15, 15, 15, 15,290, 75, 75,103,103,103, 99, - 106,106, 99,109,109, 99,112,112, 99,115,115, 99,118,118, 99, 56,119,119, - 119,120,120,120,123,123,123,126,126,126,126,126,129,129,129,134,134,134, - 134,134,134,137,137,137,137,139,139,139,139,148,148,148,148,148,148,148, - 147,147,326,326,326,326,326,326,326,326, 8, 8, 8, 8, 8, 8, 7, 7, - 18, 18, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17,374, 10, 10, 10,381, - 381,381,381,381,381,381,381,402,402,402,402,182,182,182,182,182,184,184, - 83, 83, 83,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, - 185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, - 185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, - 185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, - 185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, - 185,185,185,185, 32, 88, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 87, 87, 87, 87, 87, 87, 87, 87, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,162,162,162,167,167, - 167,167,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, - 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,261,261, - 283,283,284,284,285,285, 28, 33, 34, 42, 12, 11, 44, 14, 20, 45, 47, 46, - 48, 4, 49, 50, 51, 52, 53, 54, 55, 57, 59, 60, 61, 62, 63, 64, 66, 67, - 69, 70, 71, 72, 73, 74, 76, 77, 21, 78, 3, 79, 80, 81, 82, 84,100,101, - 102,104,105,107,108,110,111,113,114,116,117,121,122,124,125,127,128,130, - 131,132,133,135,136,138,140,141,142,143,144,145,146,150,149,151,152,153, - 154,155,156,157, 9,159,161,158,183,180,186, 5,187,188,189,190,191,192, - 193,194,195,196,197,198,199,200,201,202,203,204,205,206, 6,207,208,209, - 210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227, - 228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245, - 246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,262,263,264, - 265,266,267,268,269,270,271,272,273,274,275,276,277,278, 91,164, 90,175, - 165,279,280, 96, 95,168,281,171,173,172,166, 93,163,282 + 0, 36, 37, 37, 34, 39, 43, 43, 44, 44, 39, 39, 39, 40, 47, 47, 47, 51, + 51, 52, 52, 35, 35, 35, 35, 35, 55, 55, 35, 35, 61, 61, 35, 35, 35, 35, + 35, 35, 64, 53, 66, 66, 66, 66, 71, 71, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 81, 81, 86, 86, 82, 82, 82, 91, 91, 62, 62, 33, 33, 33, 97, 97, 97, + 33, 33,101,101, 33,105,105,105, 33,108,108, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 30, 30, 87, 87, 87, 87, 87, 87,110,110,502,410,410,410,130,130,130, + 405,405,450, 18, 18,403, 12, 12, 12,139,139,139,139,139,139,139,139,139, + 139,152,152,139,139,404, 14, 14, 14, 14,397,397, 22, 22, 73, 73,164,164, + 164,160,167,167,160,170,170,160,173,173,160,176,176,160,179,179,160, 57, + 26, 26, 26, 28, 28, 28, 23, 23, 23, 24, 24, 24, 24, 24, 27, 27, 27, 25, + 25, 25, 25, 25, 25, 29, 29, 29, 29, 29,193,193,193,193,202,202,202,202, + 202,202,202,202,202,202,201,201,457,457,457,457,457,457,457,457,218,218, + 457,457, 7, 7, 7, 7, 7, 7, 6, 6, 6, 17, 17,213,213,214,214, 15, + 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,504, 9, 9, 9,554,554,554,554, + 554,554,237,237,554,554,240,240,566,242,242,566,244,244,566,566,246,246, + 246,246,246,248,248, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,263,263, + 263,263,257,257,257,257,257,270,270,257,257,257,276,276,276,257,257,257, + 257,257,257,257,257,257,287,287,257,257,257,257,257,257,257,257,257,257, + 300,300,300,257,257,257,257,257,257,251,251,252,252,249,249,249,249,249, + 249,249,249,249,249,249,250,250,250,324,254,326,255,256,253,253,253,253, + 253,253,253,253,253,253,253,253,253,253,253,350,350,350,350,350,253,253, + 253,253,359,359,359,359,359,253,253,253,253,253,253,253,369,369,369,253, + 372,372,253,253,253,253,253,253,253,253,253,135,329,150,221, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89,133,133,133,133,133,133,133,133,133,133,133,133,133,134,134, + 134,134,134,134,134,134,134,134,134,134,134,134,136,136,136,136,136,136, + 136,136,136,136,136,136,136,136,136,136,136,136,136,141,141,141,141,141, + 141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, + 141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, + 148,148,148,149,149,149,149,149,153,153,153,153,153,153,153,153,153,156, + 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, + 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, + 156,156,156,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, + 157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, + 157,157,157,157,157,157,157,157,157,157,222,222,222,222,223,223,225,225, + 225,225,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, + 227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, + 227,227,227,227,227,227,227, 45, 41, 46, 48, 49, 11, 54, 56, 58, 59, 60, + 10, 13, 19, 65, 68, 67, 69, 21, 70, 72, 74, 75, 76, 77, 78, 79, 80, 85, + 84, 83, 90, 92, 93, 94, 95, 96, 98, 99,100,102,103,104,106,107,109,111, + 112,113,114,115,116,117,119,118,120,121,122, 20,123,124,125,126,127,128, + 2,129,159,161,162,163,165,166,168,169,171,172,174,175,177,178,180,181, + 182,183,184,185,186,187,188,189,190,191,192,194,195,196,197,198,199,200, + 203,204,205,206,207,208,209,210,211, 3,212, 8,247,238,258,259,260,261, + 262,264,265,266,267,268,269,271,272,273,274,275,277,278,279,280,281,282, + 283,284,285,286,288,289,290,291,292,293,294,295,296,297,298,299,301,302, + 303,304,305,306,307,308,309, 4,310,311,312,313,314,315,316,317,318,319, + 320, 5,321,322,323,325,327,328,330,331,332,333,334,335,336,337,338,339, + 340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358, + 360,361,362,363,364,365,366,367,368,370,371,373,374,375,376,377,378,379, + 380,382,138,383,151,137,145,384,385,386,387,155,154,388,224,389,146,219, + 147,390,215,142,144,143,381,140,220,391 }; @@ -5564,256 +5950,304 @@ static void ag_ra(void) { switch(ag_rpx[(PCB).ag_ap]) { case 1: ag_rp_1(); break; - case 2: ag_rp_6(); break; - case 3: ag_rp_7(); break; - case 4: ag_rp_8(); break; - case 5: ag_rp_9(); break; - case 6: ag_rp_10(); break; - case 7: ag_rp_11(); break; - case 8: ag_rp_12(); break; - case 9: ag_rp_13(); break; - case 10: ag_rp_14(); break; - case 11: ag_rp_15(); break; - case 12: ag_rp_16(); break; - case 13: ag_rp_17(); break; - case 14: ag_rp_18(); break; - case 15: ag_rp_19(); break; - case 16: ag_rp_20(); break; - case 17: ag_rp_21(); break; - case 18: ag_rp_22(); break; - case 19: ag_rp_23(); break; - case 20: ag_rp_24(); break; - case 21: ag_rp_25(); break; - case 22: ag_rp_26(); break; - case 23: ag_rp_27(); break; - case 24: ag_rp_28(); break; - case 25: ag_rp_29(); break; - case 26: ag_rp_30(); break; - case 27: ag_rp_31(); break; - case 28: ag_rp_32(); break; - case 29: ag_rp_33(); break; - case 30: ag_rp_34(); break; - case 31: ag_rp_35(); break; - case 32: ag_rp_36(); break; - case 33: ag_rp_37(); break; - case 34: ag_rp_38(); break; - case 35: ag_rp_39(); break; - case 36: ag_rp_40(V(3,int)); break; - case 37: ag_rp_41(); break; - case 38: ag_rp_42(); break; - case 39: ag_rp_43(); break; - case 40: ag_rp_44(); break; - case 41: ag_rp_45(); break; - case 42: ag_rp_46(); break; - case 43: ag_rp_47(); break; - case 44: ag_rp_48(); break; - case 45: ag_rp_49(); break; - case 46: ag_rp_50(); break; - case 47: ag_rp_51(); break; - case 48: ag_rp_52(); break; - case 49: ag_rp_53(); break; - case 50: ag_rp_54(V(0,int)); break; - case 51: ag_rp_55(V(1,int)); break; - case 52: ag_rp_56(V(1,int)); break; - case 53: ag_rp_57(V(0,int)); break; - case 54: ag_rp_58(V(1,int)); break; - case 55: ag_rp_59(V(1,int), V(2,int)); break; - case 56: ag_rp_60(V(1,int)); break; - case 57: ag_rp_61(); break; - case 58: ag_rp_62(V(1,int)); break; - case 59: ag_rp_63(V(2,int)); break; - case 60: ag_rp_64(); break; - case 61: ag_rp_65(); break; - case 62: ag_rp_66(V(1,int)); break; - case 63: ag_rp_67(V(2,int)); break; - case 64: ag_rp_68(); break; - case 65: ag_rp_69(); break; - case 66: ag_rp_70(); break; - case 67: ag_rp_71(); break; - case 68: ag_rp_72(); break; - case 69: ag_rp_73(); break; - case 70: ag_rp_74(); break; - case 71: ag_rp_75(); break; - case 72: ag_rp_76(); break; - case 73: ag_rp_77(); break; - case 74: ag_rp_78(); break; - case 75: ag_rp_79(); break; - case 76: ag_rp_80(); break; - case 77: ag_rp_81(); break; - case 78: ag_rp_82(); break; - case 79: ag_rp_83(); break; - case 80: ag_rp_84(); break; - case 81: ag_rp_85(); break; - case 82: ag_rp_86(); break; - case 83: ag_rp_87(); break; - case 84: ag_rp_88(); break; - case 85: ag_rp_89(); break; - case 86: ag_rp_90(); break; - case 87: ag_rp_91(); break; - case 88: ag_rp_92(); break; - case 89: ag_rp_93(); break; - case 90: ag_rp_94(); break; - case 91: ag_rp_95(); break; - case 92: ag_rp_96(); break; - case 93: ag_rp_97(V(0,double)); break; - case 94: ag_rp_98(); break; - case 95: ag_rp_99(); break; - case 96: ag_rp_100(); break; - case 97: ag_rp_101(); break; - case 98: ag_rp_102(); break; - case 99: ag_rp_103(); break; - case 100: ag_rp_104(); break; - case 101: ag_rp_105(); break; - case 102: V(0,double) = ag_rp_106(V(0,int)); break; - case 103: V(0,double) = ag_rp_107(V(0,double)); break; - case 104: V(0,int) = ag_rp_108(V(0,int)); break; - case 105: V(0,int) = ag_rp_109(); break; - case 106: V(0,int) = ag_rp_110(); break; - case 107: V(0,int) = ag_rp_111(); break; - case 108: V(0,int) = ag_rp_112(); break; - case 109: V(0,int) = ag_rp_113(); break; - case 110: V(0,int) = ag_rp_114(); break; - case 111: V(0,int) = ag_rp_115(); break; - case 112: ag_rp_116(V(1,int)); break; - case 113: ag_rp_117(V(1,int)); break; - case 114: ag_rp_118(V(0,int)); break; - case 115: ag_rp_119(V(1,int)); break; - case 116: ag_rp_120(V(2,int)); break; - case 117: ag_rp_121(V(1,int)); break; - case 118: ag_rp_122(V(1,int)); break; - case 119: ag_rp_123(V(1,int)); break; - case 120: V(0,int) = ag_rp_124(V(1,int)); break; - case 121: V(0,int) = ag_rp_125(V(1,int), V(2,int)); break; - case 122: V(0,int) = ag_rp_126(); break; - case 123: V(0,int) = ag_rp_127(V(0,int)); break; - case 124: V(0,int) = ag_rp_128(); break; - case 125: V(0,int) = ag_rp_129(); break; - case 126: V(0,int) = ag_rp_130(); break; - case 127: V(0,int) = ag_rp_131(); break; - case 128: V(0,int) = ag_rp_132(); break; - case 129: V(0,int) = ag_rp_133(); break; - case 130: V(0,int) = ag_rp_134(); break; - case 131: V(0,double) = ag_rp_135(); break; - case 132: V(0,double) = ag_rp_136(V(1,int)); break; - case 133: V(0,double) = ag_rp_137(V(0,double), V(1,int)); break; - case 134: ag_rp_138(); break; - case 135: ag_rp_139(); break; - case 136: ag_rp_140(); break; - case 137: ag_rp_141(); break; - case 138: ag_rp_142(); break; - case 139: ag_rp_143(); break; - case 140: ag_rp_144(); break; - case 141: ag_rp_145(); break; - case 142: ag_rp_146(); break; - case 143: ag_rp_147(); break; - case 144: ag_rp_148(); break; - case 145: ag_rp_149(); break; - case 146: ag_rp_150(); break; - case 147: ag_rp_151(); break; - case 148: ag_rp_152(); break; - case 149: ag_rp_153(); break; - case 150: ag_rp_154(); break; - case 151: ag_rp_155(); break; - case 152: ag_rp_156(); break; - case 153: ag_rp_157(); break; - case 154: ag_rp_158(); break; - case 155: ag_rp_159(); break; - case 156: ag_rp_160(); break; - case 157: ag_rp_161(); break; - case 158: ag_rp_162(); break; - case 159: ag_rp_163(); break; - case 160: ag_rp_164(); break; - case 161: ag_rp_165(); break; - case 162: ag_rp_166(); break; - case 163: ag_rp_167(); break; - case 164: ag_rp_168(); break; - case 165: ag_rp_169(); break; - case 166: ag_rp_170(); break; - case 167: ag_rp_171(); break; - case 168: ag_rp_172(); break; - case 169: ag_rp_173(); break; - case 170: ag_rp_174(); break; - case 171: ag_rp_175(); break; - case 172: ag_rp_176(); break; - case 173: ag_rp_177(); break; - case 174: ag_rp_178(); break; - case 175: ag_rp_179(); break; - case 176: ag_rp_180(); break; - case 177: ag_rp_181(); break; - case 178: ag_rp_182(); break; - case 179: ag_rp_183(); break; - case 180: ag_rp_184(); break; - case 181: ag_rp_185(); break; - case 182: ag_rp_186(); break; - case 183: ag_rp_187(); break; - case 184: ag_rp_188(); break; - case 185: ag_rp_189(); break; - case 186: ag_rp_190(); break; - case 187: ag_rp_191(); break; - case 188: ag_rp_192(); break; - case 189: ag_rp_193(); break; - case 190: ag_rp_194(); break; - case 191: ag_rp_195(); break; - case 192: ag_rp_196(); break; - case 193: ag_rp_197(); break; - case 194: ag_rp_198(); break; - case 195: ag_rp_199(); break; - case 196: ag_rp_200(); break; - case 197: ag_rp_201(); break; - case 198: ag_rp_202(); break; - case 199: ag_rp_203(); break; - case 200: ag_rp_204(); break; - case 201: ag_rp_205(); break; - case 202: ag_rp_206(); break; - case 203: ag_rp_207(); break; - case 204: ag_rp_208(); break; - case 205: ag_rp_209(); break; - case 206: ag_rp_210(); break; - case 207: ag_rp_211(); break; - case 208: ag_rp_212(); break; - case 209: ag_rp_213(); break; - case 210: ag_rp_214(); break; - case 211: ag_rp_215(); break; - case 212: ag_rp_216(); break; - case 213: ag_rp_217(); break; - case 214: ag_rp_218(); break; - case 215: ag_rp_219(); break; - case 216: ag_rp_220(); break; - case 217: ag_rp_221(); break; - case 218: ag_rp_222(); break; - case 219: ag_rp_223(); break; - case 220: ag_rp_224(); break; - case 221: ag_rp_225(); break; - case 222: ag_rp_226(); break; - case 223: ag_rp_227(); break; - case 224: ag_rp_228(); break; - case 225: ag_rp_229(); break; - case 226: ag_rp_230(); break; - case 227: ag_rp_231(V(2,int)); break; - case 228: ag_rp_232(); break; - case 229: ag_rp_233(); break; - case 230: ag_rp_234(); break; - case 231: ag_rp_235(); break; - case 232: ag_rp_236(); break; - case 233: ag_rp_237(); break; - case 234: ag_rp_238(); break; - case 235: ag_rp_239(); break; - case 236: ag_rp_240(); break; - case 237: ag_rp_241(); break; - case 238: ag_rp_242(); break; - case 239: ag_rp_243(); break; - case 240: ag_rp_244(); break; - case 241: ag_rp_245(); break; - case 242: ag_rp_246(); break; - case 243: ag_rp_247(); break; + case 2: ag_rp_2(); break; + case 3: ag_rp_3(); break; + case 4: ag_rp_4(); break; + case 5: ag_rp_5(); break; + case 6: ag_rp_6(); break; + case 7: ag_rp_7(); break; + case 8: ag_rp_8(); break; + case 9: ag_rp_9(); break; + case 10: ag_rp_10(); break; + case 11: ag_rp_11(); break; + case 12: ag_rp_12(); break; + case 13: ag_rp_13(); break; + case 14: ag_rp_14(); break; + case 15: ag_rp_15(); break; + case 16: ag_rp_16(); break; + case 17: ag_rp_17(); break; + case 18: ag_rp_18(); break; + case 19: ag_rp_19(); break; + case 20: ag_rp_20(); break; + case 21: ag_rp_21(); break; + case 22: ag_rp_22(); break; + case 23: ag_rp_23(); break; + case 24: ag_rp_24(); break; + case 25: ag_rp_25(); break; + case 26: ag_rp_26(V(0,int)); break; + case 27: ag_rp_27(V(1,int)); break; + case 28: ag_rp_28(); break; + case 29: ag_rp_29(); break; + case 30: ag_rp_30(); break; + case 31: ag_rp_31(V(2,int)); break; + case 32: ag_rp_32(); break; + case 33: ag_rp_33(); break; + case 34: ag_rp_34(); break; + case 35: ag_rp_35(); break; + case 36: ag_rp_36(); break; + case 37: ag_rp_37(); break; + case 38: ag_rp_38(); break; + case 39: ag_rp_39(); break; + case 40: ag_rp_40(); break; + case 41: ag_rp_41(); break; + case 42: ag_rp_42(); break; + case 43: ag_rp_43(); break; + case 44: ag_rp_44(); break; + case 45: ag_rp_45(); break; + case 46: ag_rp_46(); break; + case 47: ag_rp_47(); break; + case 48: ag_rp_48(); break; + case 49: ag_rp_49(); break; + case 50: ag_rp_50(); break; + case 51: ag_rp_51(); break; + case 52: ag_rp_52(); break; + case 53: ag_rp_53(); break; + case 54: ag_rp_54(); break; + case 55: ag_rp_55(); break; + case 56: ag_rp_56(); break; + case 57: ag_rp_57(); break; + case 58: ag_rp_58(); break; + case 59: ag_rp_59(); break; + case 60: ag_rp_60(); break; + case 61: ag_rp_61(); break; + case 62: ag_rp_62(); break; + case 63: ag_rp_63(); break; + case 64: ag_rp_64(V(2,int)); break; + case 65: ag_rp_65(); break; + case 66: ag_rp_66(); break; + case 67: ag_rp_67(); break; + case 68: ag_rp_68(); break; + case 69: ag_rp_69(); break; + case 70: ag_rp_70(); break; + case 71: ag_rp_71(); break; + case 72: ag_rp_72(); break; + case 73: ag_rp_73(); break; + case 74: ag_rp_74(); break; + case 75: ag_rp_75(V(0,int)); break; + case 76: ag_rp_76(V(1,int)); break; + case 77: ag_rp_77(V(1,int)); break; + case 78: ag_rp_78(V(0,int)); break; + case 79: ag_rp_79(V(1,int)); break; + case 80: ag_rp_80(V(1,int), V(2,int)); break; + case 81: ag_rp_81(V(1,int)); break; + case 82: ag_rp_82(); break; + case 83: ag_rp_83(V(1,int)); break; + case 84: V(0,int) = ag_rp_84(V(0,int)); break; + case 85: V(0,int) = ag_rp_85(); break; + case 86: V(0,int) = ag_rp_86(); break; + case 87: V(0,int) = ag_rp_87(); break; + case 88: V(0,int) = ag_rp_88(); break; + case 89: V(0,int) = ag_rp_89(); break; + case 90: V(0,int) = ag_rp_90(); break; + case 91: V(0,int) = ag_rp_91(); break; + case 92: V(0,int) = ag_rp_92(); break; + case 93: V(0,int) = ag_rp_93(V(1,int), V(2,int), V(3,int)); break; + case 94: V(0,int) = ag_rp_94(V(2,int), V(3,int)); break; + case 95: V(0,int) = ag_rp_95(V(2,int)); break; + case 96: ag_rp_96(); break; + case 97: ag_rp_97(); break; + case 98: ag_rp_98(V(1,int)); break; + case 99: ag_rp_99(V(2,int)); break; + case 100: ag_rp_100(); break; + case 101: ag_rp_101(); break; + case 102: V(0,int) = ag_rp_102(); break; + case 103: V(0,int) = ag_rp_103(); break; + case 104: ag_rp_104(); break; + case 105: ag_rp_105(); break; + case 106: ag_rp_106(); break; + case 107: ag_rp_107(); break; + case 108: ag_rp_108(); break; + case 109: ag_rp_109(); break; + case 110: ag_rp_110(); break; + case 111: ag_rp_111(); break; + case 112: ag_rp_112(); break; + case 113: ag_rp_113(); break; + case 114: ag_rp_114(); break; + case 115: ag_rp_115(); break; + case 116: ag_rp_116(); break; + case 117: ag_rp_117(); break; + case 118: ag_rp_118(); break; + case 119: ag_rp_119(); break; + case 120: ag_rp_120(); break; + case 121: ag_rp_121(); break; + case 122: ag_rp_122(); break; + case 123: ag_rp_123(); break; + case 124: ag_rp_124(); break; + case 125: ag_rp_125(); break; + case 126: ag_rp_126(); break; + case 127: ag_rp_127(); break; + case 128: ag_rp_128(); break; + case 129: ag_rp_129(); break; + case 130: ag_rp_130(); break; + case 131: ag_rp_131(); break; + case 132: ag_rp_132(); break; + case 133: ag_rp_133(V(0,double)); break; + case 134: ag_rp_134(); break; + case 135: ag_rp_135(); break; + case 136: ag_rp_136(); break; + case 137: ag_rp_137(); break; + case 138: ag_rp_138(); break; + case 139: ag_rp_139(); break; + case 140: ag_rp_140(); break; + case 141: ag_rp_141(); break; + case 142: ag_rp_142(); break; + case 143: ag_rp_143(); break; + case 144: ag_rp_144(); break; + case 145: V(0,double) = ag_rp_145(V(0,int)); break; + case 146: V(0,double) = ag_rp_146(V(0,double)); break; + case 147: V(0,int) = ag_rp_147(V(0,int)); break; + case 148: V(0,int) = ag_rp_148(); break; + case 149: V(0,int) = ag_rp_149(); break; + case 150: V(0,int) = ag_rp_150(); break; + case 151: V(0,int) = ag_rp_151(); break; + case 152: V(0,int) = ag_rp_152(); break; + case 153: V(0,int) = ag_rp_153(); break; + case 154: V(0,int) = ag_rp_154(); break; + case 155: V(0,int) = ag_rp_155(); break; + case 156: V(0,int) = ag_rp_156(); break; + case 157: ag_rp_157(V(1,int)); break; + case 158: ag_rp_158(V(1,int)); break; + case 159: ag_rp_159(V(0,int)); break; + case 160: ag_rp_160(V(1,int)); break; + case 161: ag_rp_161(V(2,int)); break; + case 162: ag_rp_162(V(1,int)); break; + case 163: ag_rp_163(V(1,int)); break; + case 164: ag_rp_164(V(1,int)); break; + case 165: ag_rp_165(V(1,int)); break; + case 166: ag_rp_166(V(1,int)); break; + case 167: ag_rp_167(V(1,int)); break; + case 168: ag_rp_168(V(1,int)); break; + case 169: ag_rp_169(V(1,int)); break; + case 170: V(0,int) = ag_rp_170(V(1,int)); break; + case 171: V(0,int) = ag_rp_171(V(1,int), V(2,int)); break; + case 172: V(0,int) = ag_rp_172(); break; + case 173: V(0,int) = ag_rp_173(V(0,int)); break; + case 174: V(0,int) = ag_rp_174(); break; + case 175: V(0,int) = ag_rp_175(); break; + case 176: V(0,int) = ag_rp_176(); break; + case 177: V(0,int) = ag_rp_177(); break; + case 178: V(0,int) = ag_rp_178(); break; + case 179: V(0,int) = ag_rp_179(); break; + case 180: V(0,int) = ag_rp_180(); break; + case 181: V(0,double) = ag_rp_181(); break; + case 182: V(0,double) = ag_rp_182(V(1,int)); break; + case 183: V(0,double) = ag_rp_183(V(0,double), V(1,int)); break; + case 184: ag_rp_184(); break; + case 185: ag_rp_185(); break; + case 186: ag_rp_186(); break; + case 187: ag_rp_187(); break; + case 188: ag_rp_188(); break; + case 189: ag_rp_189(); break; + case 190: ag_rp_190(); break; + case 191: ag_rp_191(); break; + case 192: ag_rp_192(); break; + case 193: ag_rp_193(); break; + case 194: ag_rp_194(); break; + case 195: ag_rp_195(); break; + case 196: ag_rp_196(); break; + case 197: ag_rp_197(); break; + case 198: ag_rp_198(); break; + case 199: ag_rp_199(); break; + case 200: ag_rp_200(); break; + case 201: ag_rp_201(); break; + case 202: ag_rp_202(); break; + case 203: ag_rp_203(); break; + case 204: ag_rp_204(); break; + case 205: ag_rp_205(); break; + case 206: ag_rp_206(); break; + case 207: ag_rp_207(); break; + case 208: ag_rp_208(); break; + case 209: ag_rp_209(); break; + case 210: ag_rp_210(); break; + case 211: ag_rp_211(); break; + case 212: ag_rp_212(); break; + case 213: ag_rp_213(); break; + case 214: ag_rp_214(); break; + case 215: ag_rp_215(); break; + case 216: ag_rp_216(); break; + case 217: ag_rp_217(); break; + case 218: ag_rp_218(); break; + case 219: ag_rp_219(); break; + case 220: ag_rp_220(); break; + case 221: ag_rp_221(); break; + case 222: ag_rp_222(); break; + case 223: ag_rp_223(); break; + case 224: ag_rp_224(); break; + case 225: ag_rp_225(); break; + case 226: ag_rp_226(); break; + case 227: ag_rp_227(); break; + case 228: ag_rp_228(); break; + case 229: ag_rp_229(); break; + case 230: ag_rp_230(); break; + case 231: ag_rp_231(); break; + case 232: ag_rp_232(); break; + case 233: ag_rp_233(); break; + case 234: ag_rp_234(); break; + case 235: ag_rp_235(); break; + case 236: ag_rp_236(); break; + case 237: ag_rp_237(); break; + case 238: ag_rp_238(); break; + case 239: ag_rp_239(); break; + case 240: ag_rp_240(); break; + case 241: ag_rp_241(); break; + case 242: ag_rp_242(); break; + case 243: ag_rp_243(); break; + case 244: ag_rp_244(); break; + case 245: ag_rp_245(); break; + case 246: ag_rp_246(); break; + case 247: ag_rp_247(); break; + case 248: ag_rp_248(); break; + case 249: ag_rp_249(); break; + case 250: ag_rp_250(); break; + case 251: ag_rp_251(); break; + case 252: ag_rp_252(); break; + case 253: ag_rp_253(); break; + case 254: ag_rp_254(); break; + case 255: ag_rp_255(); break; + case 256: ag_rp_256(V(2,int)); break; + case 257: ag_rp_257(); break; + case 258: ag_rp_258(); break; + case 259: ag_rp_259(); break; + case 260: ag_rp_260(); break; + case 261: ag_rp_261(); break; + case 262: ag_rp_262(); break; + case 263: ag_rp_263(); break; + case 264: ag_rp_264(); break; + case 265: ag_rp_265(); break; + case 266: ag_rp_266(); break; + case 267: ag_rp_267(); break; + case 268: ag_rp_268(); break; + case 269: ag_rp_269(); break; + case 270: ag_rp_270(); break; + case 271: ag_rp_271(); break; + case 272: ag_rp_272(); break; + case 273: ag_rp_273(); break; + case 274: ag_rp_274(); break; + case 275: ag_rp_275(); break; + case 276: ag_rp_276(); break; + case 277: ag_rp_277(); break; + case 278: ag_rp_278(); break; + case 279: ag_rp_279(); break; + case 280: ag_rp_280(); break; + case 281: ag_rp_281(); break; + case 282: ag_rp_282(); break; + case 283: ag_rp_283(); break; + case 284: ag_rp_284(); break; + case 285: ag_rp_285(); break; + case 286: ag_rp_286(); break; + case 287: ag_rp_287(); break; + case 288: ag_rp_288(); break; + case 289: ag_rp_289(); break; + case 290: ag_rp_290(); break; + case 291: ag_rp_291(); break; + case 292: ag_rp_292(); break; } } #define TOKEN_NAMES a85parse_token_names -const char *const a85parse_token_names[492] = { +const char *const a85parse_token_names[647] = { "a85parse", "WS", - "cstyle comment", "integer", "literal name", "register 8 bit", @@ -5833,83 +6267,145 @@ const char *const a85parse_token_names[492] = { "", "asm include", "singlequote string", + "literal name nows", + "pagespec", + "and exp", + "shift exp", + "multiplicative exp", + "inclusive or exp", + "additive exp", + "exclusive or exp", + "urinary exp", + "page exp", + "instruction list", + "instruction", + "expression", "a85parse", "statement", "", "", "eof", "comment", + "cstyle comment", "\"//\"", "any text char", "", "", - "newline", + "'\\n'", "';'", - "','", + "cstyle comment head", + "\"*/\"", "\"/*\"", "", "", - "\"*/\"", "", + "preproc inst", + "'.'", "", - "expression", - "'\\n'", - "error", - "\"INCLUDE\"", - "\"#INCLUDE\"", - "\"#PRAGMA\"", - "\"LIST\"", - "\"HEX\"", - "\"#IFDEF\"", - "\"#IFNDEF\"", - "\"#ELSE\"", - "\"#ENDIF\"", - "\"#DEFINE\"", - "\"#UNDEF\"", "\"EQU\"", "equation", "\"SET\"", + "\"INCLUDE\"", + "\"INCL\"", "", - "\"ORG\"", - "\"ASEG\"", + "cdseg statement", + "error", + "preproc start", + "\"#\"", + "preprocessor directive", + "\"PRAGMA\"", + "\"LIST\"", + "\"HEX\"", + "\"IFDEF\"", + "", + "\"IF\"", + "condition", + "\"ELIF\"", + "\"IFNDEF\"", + "\"ELSE\"", + "\"ENDIF\"", + "\"ERROR\"", + "\"UNDEF\"", + "\"DEFINE\"", + "macro definition", + "macro expansion", + "'('", + "parameter list", + "')'", + "macro", + "", + "", + "define chars", + "\"\\\\\\n\"", + "cdseg statement start", "\"CSEG\"", "\"DSEG\"", + "\"ORG\"", + "\"$=\"", + "\"*=\"", + "", + "\"ASEG\"", "\"DS\"", + "\"BLOCK\"", + "", "\"DB\"", + "\"BYTE\"", + "\"TEXT\"", "", "\"DW\"", - "\"EXTRN\"", + "\"WORD\"", + "", + "\"PUBLIC\"", "name list", + "\"EXTRN\"", "\"EXTERN\"", - "\"PUBLIC\"", + "\"MODULE\"", "\"NAME\"", "\"STKLN\"", + "\"ECHO\"", + "\"FILL\"", + "\"PRINTF\"", + "','", "\"END\"", - "\"IF\"", - "condition", - "\"ELSE\"", - "\"ENDIF\"", + "\"MSFIRST\"", + "\"LSFIRST\"", "\"TITLE\"", - "\"PAGE\"", + "\"NOPAGE\"", "\"SYM\"", "\"LINK\"", "\"MACLIB\"", - "instruction list", + "\"PAGE\"", "\",\"", "literal alpha", "\"$\"", + "\"&\"", + "", "", "digit", "asm incl char", "'\\''", "'\\\"'", - "string char", + "", "'\\\\'", "", + "'n'", + "'t'", + "'r'", + "'0'", + "'b'", + "'f'", + "", + "", + "'x'", + "'$'", + "", + "hex digit", "'>'", "'<'", "", + "", "\":\"", + "\"INPAGE\"", "", "\"EQ\"", "\"==\"", @@ -5930,25 +6426,18 @@ const char *const a85parse_token_names[492] = { "\"LT\"", "\"<\"", "", - "inclusive or exp", - "exclusive or exp", "'|'", "\"OR\"", - "and exp", "'^'", "\"XOR\"", - "shift exp", "'&'", "\"AND\"", - "additive exp", "\"<<\"", "\"SHL\"", "\">>\"", "\"SHR\"", - "multiplicative exp", "'+'", "'-'", - "urinary exp", "'*'", "primary exp", "'/'", @@ -5960,8 +6449,6 @@ const char *const a85parse_token_names[492] = { "'~'", "value", "function", - "'('", - "')'", "\"FLOOR\"", "\"CEIL\"", "\"LN\"", @@ -5969,47 +6456,132 @@ const char *const a85parse_token_names[492] = { "\"SQRT\"", "\"IP\"", "\"FP\"", - "\"H\"", - "\"B\"", + "\"HIGH\"", + "\"LOW\"", + "\"DEFINED\"", + "binary integer", + "octal integer", + "", "\"Q\"", - "\"D\"", + "\"O\"", "", + "'d'", "'_'", - "'$'", - "'0'", "", - "hex digit", + "", + "", + "'@'", "", "\"\\'\\\\\\'\"", "", - "'n'", - "'t'", - "'r'", "\"\\'\\'\"", - "'.'", + "\"B\"", "\"C\"", + "\"D\"", "\"E\"", + "\"H\"", "\"L\"", "\"M\"", + "\"(HL)\"", + "", "\"A\"", + "\"BC\"", + "", + "\"DE\"", + "", + "\"HL\"", + "", "\"SP\"", "stack register", "\"PSW\"", "bd register", - "instruction", - "\"ACI\"", + "eight bit reg inst", + "sixteen bit reg inst", + "bd reg inst", + "stack reg inst", + "immediate operand inst", + "lxi inst", + "mvi inst", + "rst inst", + "no arg inst", + "\"!\"", + "\"ASHR\"", + "\"SHLR\"", + "\"ARHL\"", + "\"RRHL\"", + "", + "\"CMA\"", + "\"CMC\"", + "\"DAA\"", + "\"DI\"", + "\"DSUB\"", + "\"HLMBC\"", + "", + "\"EI\"", + "\"HLT\"", + "\"LHLX\"", + "\"LHLI\"", + "\"LHLDE\"", + "", + "\"NOP\"", + "\"PCHL\"", + "\"RAL\"", + "\"RAR\"", + "\"RC\"", + "\"RET\"", + "\"RIM\"", + "\"RLC\"", + "\"RLDE\"", + "\"RDEL\"", + "", + "\"RM\"", + "\"RNC\"", + "\"RNZ\"", + "\"RP\"", + "\"RPE\"", + "\"RPO\"", + "\"RRC\"", + "\"RSTV\"", + "\"RZ\"", + "\"SHLX\"", + "\"SHLI\"", + "\"SHLDE\"", + "", + "\"SIM\"", + "\"SPHL\"", + "\"STC\"", + "\"XCHG\"", + "\"XTHL\"", + "\"STAX\"", + "\"LDAX\"", + "\"POP\"", + "\"PUSH\"", "\"ADC\"", "\"ADD\"", - "\"ADI\"", "\"ANA\"", + "\"CMP\"", + "\"DCR\"", + "\"INR\"", + "\"MOV\"", + "\"ORA\"", + "\"SBB\"", + "\"SUB\"", + "\"XRA\"", + "\"DAD\"", + "\"DCX\"", + "\"INX\"", + "lxi inst start", + "\"LXI\"", + "mvi inst start", + "\"MVI\"", + "\"RST\"", + "rst arg", + "\"ACI\"", + "\"ADI\"", "\"ANI\"", - "\"ASHR\"", "\"CALL\"", "\"CC\"", "\"CM\"", - "\"CMA\"", - "\"CMC\"", - "\"CMP\"", "\"CNC\"", "\"CNZ\"", "\"CP\"", @@ -6017,78 +6589,44 @@ const char *const a85parse_token_names[492] = { "\"CPI\"", "\"CPO\"", "\"CZ\"", - "\"DAA\"", - "\"DAD\"", - "\"DCR\"", - "\"DCX\"", - "\"DI\"", - "\"DSUB\"", - "\"EI\"", - "\"HLT\"", "\"IN\"", - "\"INR\"", - "\"INX\"", "\"JC\"", - "\"JD\"", "\"JX\"", + "\"JX5\"", + "\"JTM\"", + "\"JK\"", + "\"JD\"", + "", "\"JM\"", "\"JMP\"", "\"JNC\"", - "\"JND\"", "\"JNX\"", + "\"JNX5\"", + "\"JTP\"", + "\"JNK\"", + "\"JND\"", + "", "\"JNZ\"", "\"JP\"", "\"JPE\"", "\"JPO\"", "\"JZ\"", "\"LDA\"", - "\"LDAX\"", "\"LDEH\"", + "\"DEHL\"", + "\"LDHI\"", + "", "\"LDES\"", + "\"DESP\"", + "", "\"LHLD\"", - "\"LHLX\"", - "\"LXI\"", - "\"MOV\"", - "\"MVI\"", - "\"NOP\"", - "\"ORA\"", "\"ORI\"", "\"OUT\"", - "\"PCHL\"", - "\"POP\"", - "\"PUSH\"", - "\"RAL\"", - "\"RAR\"", - "\"RC\"", - "\"RET\"", - "\"RIM\"", - "\"RLC\"", - "\"RLDE\"", - "\"RM\"", - "\"RNC\"", - "\"RNZ\"", - "\"RP\"", - "\"RPE\"", - "\"RPO\"", - "\"RRC\"", - "\"RST\"", - "rst arg", - "\"RZ\"", - "\"SBB\"", "\"SBI\"", "\"SHLD\"", - "\"SHLX\"", - "\"SIM\"", - "\"SPHL\"", "\"STA\"", - "\"STAX\"", - "\"STC\"", - "\"SUB\"", "\"SUI\"", - "\"XCHG\"", - "\"XRA\"", "\"XRI\"", - "\"XTHL\"", "", "", "", @@ -6097,52 +6635,77 @@ const char *const a85parse_token_names[492] = { "", "", "", + "", + "", + "", + "'\\n'", "\"//\"", "';'", - "','", - "'\\n'", + "\"*/\"", + "\"/*\"", "label", - "literal string", + "'.'", + "\"EQU\"", + "\"SET\"", "\"INCLUDE\"", + "\"INCL\"", + "literal string", "include string", "asm include", - "\"#INCLUDE\"", + "\"#\"", "\"LIST\"", - "\"#PRAGMA\"", + "\"PRAGMA\"", "\"HEX\"", - "literal name", - "\"#IFDEF\"", - "\"#IFNDEF\"", - "\"#ELSE\"", - "\"#ENDIF\"", - "\"#DEFINE\"", - "\"#UNDEF\"", - "\"EQU\"", - "\"SET\"", - "\"ORG\"", - "\"ASEG\"", + "literal name nows", + "\"IFDEF\"", + "\"IF\"", + "\"ELIF\"", + "\"IFNDEF\"", + "\"ELSE\"", + "\"ENDIF\"", + "\"ERROR\"", + "\"UNDEF\"", + "\"DEFINE\"", + "')'", + "parameter list", + "'('", + "\"\\\\\\n\"", "\"CSEG\"", "\"DSEG\"", + "\"ORG\"", + "\"$=\"", + "\"*=\"", + "\"ASEG\"", "\"DS\"", + "\"BLOCK\"", "\"DB\"", + "\"BYTE\"", + "\"TEXT\"", "\"DW\"", + "\"WORD\"", + "\"PUBLIC\"", "\"EXTRN\"", "\"EXTERN\"", - "\"PUBLIC\"", + "\"MODULE\"", "\"NAME\"", "\"STKLN\"", + "\"ECHO\"", + "\"FILL\"", + "','", + "\"PRINTF\"", "\"END\"", - "\"IF\"", - "\"ELSE\"", - "\"ENDIF\"", + "\"MSFIRST\"", + "\"LSFIRST\"", "singlequote string", "\"TITLE\"", - "integer", - "\"PAGE\"", + "\"NOPAGE\"", "\"SYM\"", "\"LINK\"", "\"MACLIB\"", + "\"PAGE\"", + "integer", "\",\"", + "\"INPAGE\"", "\"EQ\"", "\"==\"", "\"=\"", @@ -6176,8 +6739,6 @@ const char *const a85parse_token_names[492] = { "'!'", "\"NOT\"", "'~'", - "')'", - "'('", "\"FLOOR\"", "\"CEIL\"", "\"LN\"", @@ -6185,26 +6746,85 @@ const char *const a85parse_token_names[492] = { "\"SQRT\"", "\"IP\"", "\"FP\"", + "\"HIGH\"", + "\"LOW\"", + "literal name", + "\"DEFINED\"", "real", - "\"B\"", - "\"D\"", - "\"H\"", "\"PSW\"", "\"A\"", - "\"ACI\"", + "\"!\"", + "\"ASHR\"", + "\"SHLR\"", + "\"ARHL\"", + "\"RRHL\"", + "\"CMA\"", + "\"CMC\"", + "\"DAA\"", + "\"DI\"", + "\"DSUB\"", + "\"HLMBC\"", + "\"EI\"", + "\"HLT\"", + "\"LHLX\"", + "\"LHLI\"", + "\"LHLDE\"", + "\"NOP\"", + "\"PCHL\"", + "\"RAL\"", + "\"RAR\"", + "\"RC\"", + "\"RET\"", + "\"RIM\"", + "\"RLC\"", + "\"RLDE\"", + "\"RDEL\"", + "\"RM\"", + "\"RNC\"", + "\"RNZ\"", + "\"RP\"", + "\"RPE\"", + "\"RPO\"", + "\"RRC\"", + "\"RSTV\"", + "\"RZ\"", + "\"SHLX\"", + "\"SHLI\"", + "\"SHLDE\"", + "\"SIM\"", + "\"SPHL\"", + "\"STC\"", + "\"XCHG\"", + "\"XTHL\"", + "\"STAX\"", + "\"LDAX\"", + "\"POP\"", + "\"PUSH\"", "register 8 bit", "\"ADC\"", "\"ADD\"", - "\"ADI\"", "\"ANA\"", + "\"CMP\"", + "\"DCR\"", + "\"INR\"", + "\"MOV\"", + "\"ORA\"", + "\"SBB\"", + "\"SUB\"", + "\"XRA\"", + "register 16 bit", + "\"DAD\"", + "\"DCX\"", + "\"INX\"", + "\"LXI\"", + "\"MVI\"", + "\"RST\"", + "\"ACI\"", + "\"ADI\"", "\"ANI\"", - "\"ASHR\"", "\"CALL\"", "\"CC\"", "\"CM\"", - "\"CMA\"", - "\"CMC\"", - "\"CMP\"", "\"CNC\"", "\"CNZ\"", "\"CP\"", @@ -6212,89 +6832,59 @@ const char *const a85parse_token_names[492] = { "\"CPI\"", "\"CPO\"", "\"CZ\"", - "\"DAA\"", - "register 16 bit", - "\"DAD\"", - "\"DCR\"", - "\"DCX\"", - "\"DI\"", - "\"DSUB\"", - "\"EI\"", - "\"HLT\"", "\"IN\"", - "\"INR\"", - "\"INX\"", "\"JC\"", - "\"JD\"", "\"JX\"", + "\"JX5\"", + "\"JTM\"", + "\"JK\"", + "\"JD\"", "\"JM\"", "\"JMP\"", "\"JNC\"", - "\"JND\"", "\"JNX\"", + "\"JNX5\"", + "\"JTP\"", + "\"JNK\"", + "\"JND\"", "\"JNZ\"", "\"JP\"", "\"JPE\"", "\"JPO\"", "\"JZ\"", "\"LDA\"", - "\"LDAX\"", "\"LDEH\"", + "\"DEHL\"", + "\"LDHI\"", "\"LDES\"", + "\"DESP\"", "\"LHLD\"", - "\"LHLX\"", - "\"LXI\"", - "\"MOV\"", - "\"MVI\"", - "\"NOP\"", - "\"ORA\"", "\"ORI\"", "\"OUT\"", - "\"PCHL\"", - "\"POP\"", - "\"PUSH\"", - "\"RAL\"", - "\"RAR\"", - "\"RC\"", - "\"RET\"", - "\"RIM\"", - "\"RLC\"", - "\"RLDE\"", - "\"RM\"", - "\"RNC\"", - "\"RNZ\"", - "\"RP\"", - "\"RPE\"", - "\"RPO\"", - "\"RRC\"", - "\"RST\"", - "\"RZ\"", - "\"SBB\"", "\"SBI\"", "\"SHLD\"", - "\"SHLX\"", - "\"SIM\"", - "\"SPHL\"", "\"STA\"", - "\"STAX\"", - "\"STC\"", - "\"SUB\"", "\"SUI\"", - "\"XCHG\"", - "\"XRA\"", "\"XRI\"", - "\"XTHL\"", "", "'\\\"'", + "", "'$'", "'\\''", - "'.'", "'0'", "", "", + "", + "", "'<'", "'>'", "", + "'@'", + "", + "'b'", + "'d'", + "'f'", + "", "", "'n'", "'r'", @@ -6308,49 +6898,61 @@ const char *const a85parse_token_names[492] = { static const unsigned short ag_ctn[] = { - 0,0, 2,1, 0,0, 0,0, 0,0, 0,0, 23,1, 23,1, 0,0, 0,0, 0,0, 0,0, - 27,1, 27,1, 27,1, 27,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, - 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, 41,1, - 41,1, 23,2, 29,1, 0,0, 0,0, 29,1, 0,0, 29,1, 29,1, 29,1, 29,1, 29,1, - 29,1, 29,1, 29,1, 29,1, 29,1, 0,0, 0,0, 0,0, 29,1, 0,0, 0,0, 0,0, - 0,0, 0,0, 29,1, 0,0, 0,0, 29,1, 29,1, 0,0, 29,1, 0,0, 27,2, 27,2, - 27,2,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, - 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, - 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, - 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, - 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, - 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, - 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, - 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, - 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, - 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, - 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, - 185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1,185,1, - 185,1,185,1,185,1,185,1,185,1,185,1,185,1, 83,1, 0,0, 41,2, 0,0, 41,2, - 0,0, 0,0, 41,2, 0,0, 41,2, 0,0, 0,0, 0,0, 41,2, 0,0, 41,2, 0,0, - 41,2, 0,0, 41,2, 0,0, 41,2, 0,0, 41,2, 0,0, 41,2, 0,0, 41,2, 0,0, - 41,2, 0,0, 41,2, 0,0, 0,0, 0,0, 0,0, 41,2, 41,2, 41,2, 41,2, 0,0, - 41,2, 0,0, 41,2, 0,0, 0,0, 0,0,293,1, 0,0,291,1, 0,0, 0,0, 41,2, - 41,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2, - 185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2, - 185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2, - 185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2, - 185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2,185,2, - 83,2, 0,0,324,1,324,1, 0,0,374,1, 7,1, 8,1, 8,1, 16,1,374,1,326,1, - 7,1,147,1,148,1,148,1,148,1,148,1,148,1,148,1,148,1,147,1, 0,0,148,1, - 148,1,148,1,148,1,148,1,148,1,148,1,137,1,139,1,137,1,137,1,137,1,134,1, - 129,1,126,1,123,1,120,1,119,1, 75,1, 75,1, 41,3, 68,1, 68,1, 68,1, 0,0, - 0,0, 0,0, 0,0, 0,0,293,2,291,2, 0,0, 0,0, 0,0,182,1,182,1,182,1, - 185,3,185,3, 0,0,185,3,326,1, 17,1,324,2, 7,2, 16,2,148,2,148,2,148,2, - 148,2,148,2,148,2,148,2,139,2, 0,0,134,2, 0,0,134,2,134,2,134,2,134,2, - 129,2,129,2, 0,0,126,2, 0,0,126,2, 0,0,126,2, 0,0,126,2, 0,0,123,2, - 123,2, 0,0,120,2,120,2, 0,0,119,2,119,2, 0,0, 0,0, 0,0, 0,0, 0,0, - 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 68,2, 0,0, 0,0, 0,0, - 0,0, 0,0,185,4,185,4,185,4, 16,3,148,3,148,3,148,3,148,3,148,3,148,3, - 148,3,139,3,134,3,134,3,134,3,134,3,134,3,129,3,129,3,126,3,126,3,126,3, - 126,3,123,3,123,3,120,3,120,3,119,3,119,3, 0,0, 68,3, 16,3, 0,0,185,5, - 185,5,185,5,134,1,134,1,129,1,129,1,129,1,129,1,126,1,126,1,123,1,123,1, - 120,1,120,1, 68,4, 0,0,185,6,185,6,185,6 + 0,0, 0,0, 0,0, 64,1,397,1, 53,1, 35,1, 35,1, 35,1, 35,1, 35,1, 0,0, + 66,1, 66,1, 66,1, 0,0, 0,0, 66,1, 66,1, 0,0, 66,1, 66,1, 0,0, 66,1, + 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 0,0, 0,0, + 35,2, 47,1, 0,0, 39,1, 40,1, 39,1, 39,1, 35,2, 62,1,257,1,257,1,257,1, + 257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,326,1, + 324,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1, + 253,1,253,1,253,1,253,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1, + 257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1, + 257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,256,1,326,1,324,1,253,1, + 253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1, + 253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1, + 253,1,253,1,253,1,253,1,253,1,253,1,253,1,252,1,252,1,251,1,251,1,250,1, + 250,1,250,1,249,1,249,1,249,1,249,1,249,1,249,1,249,1,249,1,249,1,249,1, + 249,1,256,1,255,1,254,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1, + 253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1, + 253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1, + 253,1,253,1,253,1,253,1,252,1,252,1,251,1,251,1,250,1,250,1,250,1,249,1, + 249,1,249,1,249,1,249,1,249,1,249,1,249,1,249,1,249,1,249,1, 0,0, 32,1, + 86,1, 30,1, 32,1, 33,1, 33,1, 35,2, 81,1, 66,2, 66,2,403,1, 0,0, 66,2, + 66,2, 66,2, 66,2,504,1,214,1,213,1, 6,1, 6,1, 7,1, 15,1,504,1,457,1, + 214,1,213,1, 6,1,201,1,202,1,202,1,202,1,202,1,202,1,202,1,202,1,202,1, + 202,1,202,1,201,1, 0,0, 0,0,202,1,202,1,202,1,202,1,202,1,202,1,202,1, + 202,1,202,1,202,1, 29,1, 0,0, 29,1, 0,0,193,1, 29,1, 29,1, 29,1, 29,1, + 25,1, 27,1, 24,1, 23,1, 28,1, 26,1, 26,1, 73,1, 73,1, 66,2, 66,2, 66,2, + 0,0, 66,2, 0,0, 66,2,404,1, 0,0, 66,2, 66,2, 0,0, 35,3, 0,0, 0,0, + 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0,0, 39,2, 39,2, 33,1, 35,3, 62,2,326,2,324,2,256,2,255,2,254,2,253,2, + 253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2, + 253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2, + 253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,252,2, + 252,2,251,2,251,2,250,2,250,2,250,2,249,2,249,2,249,2,249,2,249,2,249,2, + 249,2,249,2,249,2,249,2,249,2, 86,2, 0,0, 0,0, 32,2, 0,0, 0,0, 33,2, + 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, 33,2, + 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, + 0,0, 33,2, 0,0, 33,2, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, + 0,0, 33,2, 0,0, 0,0, 0,0, 0,0, 33,2, 0,0, 0,0, 35,3, 81,2, 66,3, + 66,3, 0,0, 66,3, 66,3, 6,2, 16,1, 15,2, 0,0, 0,0,202,2,202,2,202,2, + 202,2,202,2,202,2,202,2,202,2,202,2,202,2,193,2, 7,1, 0,0, 25,2, 0,0, + 25,2, 25,2, 25,2, 25,2, 27,2, 27,2, 0,0, 24,2, 0,0, 24,2, 0,0, 24,2, + 0,0, 24,2, 0,0, 23,2, 23,2, 0,0, 28,2, 28,2, 0,0, 26,2, 26,2, 0,0, + 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 66,3, 66,3, 66,3, 66,3, 66,3,404,2, 66,3, 66,3, 0,0, 35,4, 35,4, 35,4, + 0,0, 35,4, 0,0, 35,4, 35,4, 22,1, 62,3, 0,0, 0,0,255,3,254,3,246,1, + 246,1,249,3, 0,0,450,1, 0,0, 0,0, 6,1,457,1, 32,3,450,1, 33,3, 33,3, + 110,1,110,1,110,1, 0,0, 0,0, 0,0, 81,3, 82,1, 0,0, 0,0, 0,0, 15,3, + 202,3,202,3,202,3,202,3,202,3,202,3,202,3,202,3,202,3,202,3,193,3, 25,3, + 25,3, 25,3, 25,3, 25,3, 27,3, 27,3, 24,3, 24,3, 24,3, 24,3, 23,3, 23,3, + 28,3, 28,3, 26,3, 26,3, 35,5, 35,5, 35,5, 35,5, 35,5, 62,4,255,4,254,4, + 249,4, 0,0, 0,0, 0,0, 32,1, 32,1,450,2, 33,4, 0,0,110,2, 0,0, 0,0, + 66,5, 0,0, 0,0,202,4,202,4,202,4,202,4,202,4,202,4,202,4,202,4,202,4, + 202,4,193,4, 25,1, 25,1, 27,1, 27,1, 27,1, 27,1, 24,1, 24,1, 23,1, 23,1, + 28,1, 28,1, 35,6, 35,6,249,5, 15,3, 0,0, 33,5,110,3,502,1, 0,0,202,5, + 249,6,202,6 }; #ifndef MISSING_FORMAT @@ -6484,7 +7086,7 @@ static void ag_error_resynch(void) { if ((PCB).exit_flag != AG_RUNNING_CODE) return; while (1) { ag_k = ag_sbt[(PCB).sn]; - while (ag_tstt[ag_k] != 43 && ag_tstt[ag_k]) ag_k++; + while (ag_tstt[ag_k] != 63 && ag_tstt[ag_k]) ag_k++; if (ag_tstt[ag_k] || (PCB).ssx == 0) break; (PCB).sn = (PCB).ss[--(PCB).ssx]; } @@ -6494,7 +7096,7 @@ static void ag_error_resynch(void) { return; } ag_k = ag_sbt[(PCB).sn]; - while (ag_tstt[ag_k] != 43 && ag_tstt[ag_k]) ag_k++; + while (ag_tstt[ag_k] != 63 && ag_tstt[ag_k]) ag_k++; (PCB).ag_ap = ag_pstt[ag_k]; (ag_er_procs_scan[ag_astt[ag_k]])(); while (1) { @@ -6502,7 +7104,7 @@ static void ag_error_resynch(void) { while (ag_tstt[ag_k] != (const unsigned short) (PCB).token_number && ag_tstt[ag_k]) ag_k++; if (ag_tstt[ag_k] && ag_astt[ag_k] != ag_action_10) break; - if ((PCB).token_number == 26) + if ((PCB).token_number == 38) {(PCB).exit_flag = AG_SYNTAX_ERROR_CODE; return;} {(PCB).rx = 1; ag_track();} if ((PCB).rx < (PCB).fx) { @@ -6712,7 +7314,7 @@ static int ag_action_3_proc(void) { static int ag_action_8_proc(void) { int ag_k = ag_sbt[(PCB).sn]; - while (ag_tstt[ag_k] != 43 && ag_tstt[ag_k]) ag_k++; + while (ag_tstt[ag_k] != 63 && ag_tstt[ag_k]) ag_k++; if (ag_tstt[ag_k] == 0) ag_undo(); (PCB).rx = 0; ag_error_resynch(); diff --git a/src/a85parse.h b/src/a85parse.h index f935f7d..43960cf 100644 --- a/src/a85parse.h +++ b/src/a85parse.h @@ -1,5 +1,5 @@ -#ifndef A85PARSE_H_1176345433 -#define A85PARSE_H_1176345433 +#ifndef A85PARSE_H_1277850585 +#define A85PARSE_H_1277850585 typedef union { long alignment; @@ -8,34 +8,47 @@ typedef union { } a85parse_vs_type; typedef enum { - a85parse_WS_token = 1, a85parse_cstyle_comment_token, - a85parse_hex_integer_token = 7, a85parse_decimal_integer_token, - a85parse_simple_real_token = 10, a85parse_string_chars_token = 13, - a85parse_include_chars_token = 15, a85parse_ascii_integer_token, - a85parse_escape_char_token, a85parse_asm_hex_value_token, - a85parse_singlequote_chars_token, a85parse_a85parse_token = 22, - a85parse_statement_token, a85parse_eof_token = 26, a85parse_comment_token, - a85parse_any_text_char_token = 29, a85parse_newline_token = 32, - a85parse_expression_token = 41, a85parse_error_token = 43, - a85parse_equation_token = 56, a85parse_expression_list_token = 65, - a85parse_name_list_token = 68, a85parse_condition_token = 75, - a85parse_instruction_list_token = 83, a85parse_literal_alpha_token = 85, - a85parse_digit_token = 88, a85parse_asm_incl_char_token, - a85parse_string_char_token = 92, a85parse_condition_start_token = 99, - a85parse_inclusive_or_exp_token = 119, a85parse_exclusive_or_exp_token, - a85parse_and_exp_token = 123, a85parse_shift_exp_token = 126, - a85parse_additive_exp_token = 129, - a85parse_multiplicative_exp_token = 134, a85parse_urinary_exp_token = 137, - a85parse_primary_exp_token = 139, a85parse_value_token = 147, - a85parse_function_token, a85parse_hex_digit_token = 167, - a85parse_stack_register_token = 182, a85parse_bd_register_token = 184, - a85parse_instruction_token, a85parse_rst_arg_token = 261, - a85parse_label_token = 290, a85parse_literal_string_token, - a85parse_include_string_token = 293, a85parse_asm_include_token, - a85parse_literal_name_token = 299, - a85parse_singlequote_string_token = 324, a85parse_integer_token = 326, - a85parse_real_token = 374, a85parse_register_8_bit_token = 381, - a85parse_register_16_bit_token = 402 + a85parse_WS_token = 1, a85parse_hex_integer_token = 6, + a85parse_decimal_integer_token, a85parse_simple_real_token = 9, + a85parse_string_chars_token = 12, a85parse_include_chars_token = 14, + a85parse_ascii_integer_token, a85parse_escape_char_token, + a85parse_asm_hex_value_token, a85parse_singlequote_chars_token, + a85parse_pagespec_token = 22, a85parse_and_exp_token, + a85parse_shift_exp_token, a85parse_multiplicative_exp_token, + a85parse_inclusive_or_exp_token, a85parse_additive_exp_token, + a85parse_exclusive_or_exp_token, a85parse_urinary_exp_token, + a85parse_page_exp_token, a85parse_instruction_list_token, + a85parse_instruction_token, a85parse_expression_token, + a85parse_a85parse_token, a85parse_statement_token, + a85parse_eof_token = 38, a85parse_comment_token, + a85parse_cstyle_comment_token, a85parse_any_text_char_token = 42, + a85parse_cstyle_comment_head_token = 47, a85parse_preproc_inst_token = 53, + a85parse_equation_token = 57, a85parse_cdseg_statement_token = 62, + a85parse_error_token, a85parse_preproc_start_token, + a85parse_preprocessor_directive_token = 66, a85parse_condition_token = 73, + a85parse_macro_definition_token = 81, a85parse_macro_expansion_token, + a85parse_macro_token = 86, a85parse_expression_list_token, + a85parse_define_chars_token = 89, + a85parse_cdseg_statement_start_token = 91, a85parse_name_list_token = 110, + a85parse_literal_alpha_token = 130, a85parse_digit_token = 135, + a85parse_asm_incl_char_token, a85parse_str_escape_char_token = 139, + a85parse_hex_digit_token = 153, a85parse_condition_start_token = 160, + a85parse_primary_exp_token = 193, a85parse_value_token = 201, + a85parse_function_token, a85parse_binary_integer_token = 213, + a85parse_octal_integer_token, a85parse_stack_register_token = 246, + a85parse_bd_register_token = 248, a85parse_eight_bit_reg_inst_token, + a85parse_sixteen_bit_reg_inst_token, a85parse_bd_reg_inst_token, + a85parse_stack_reg_inst_token, a85parse_immediate_operand_inst_token, + a85parse_lxi_inst_token, a85parse_mvi_inst_token, a85parse_rst_inst_token, + a85parse_no_arg_inst_token, a85parse_lxi_inst_start_token = 324, + a85parse_mvi_inst_start_token = 326, a85parse_rst_arg_token = 329, + a85parse_label_token = 397, a85parse_literal_string_token = 403, + a85parse_include_string_token, a85parse_asm_include_token, + a85parse_literal_name_nows_token = 410, + a85parse_parameter_list_token = 421, + a85parse_singlequote_string_token = 450, a85parse_integer_token = 457, + a85parse_literal_name_token = 502, a85parse_real_token = 504, + a85parse_register_8_bit_token = 554, a85parse_register_16_bit_token = 566 } a85parse_token_type; typedef struct a85parse_pcb_struct{ @@ -52,7 +65,7 @@ typedef struct a85parse_pcb_struct{ char read_flag; char exit_flag; int bts[128], btsx; - int lab[9], rx, fx; + int lab[8], rx, fx; const unsigned char *key_sp; int save_index, key_state; char ag_msg[82]; diff --git a/src/a85parse.syn b/src/a85parse.syn index 66764ac..156310e 100644 --- a/src/a85parse.syn +++ b/src/a85parse.syn @@ -7,20 +7,25 @@ } [ -// auto resynch diagnose errors error frame disregard WS - disregard cstyle comment distinguish lexemes - distinguish keywords { 'a-z'+'A-Z' + '0-9' + '_' + '$' + '-' + '+' + 'e' + 'E' } + distinguish keywords { 'a-z'+'A-Z' + '0-9' + '_' + '$' + '-' + '+' + 'e' + 'E' + '!' } case sensitive = off - lexeme { integer, literal name, register 8 bit, register 16 bit, hex integer, + lexeme { + integer, literal name, register 8 bit, register 16 bit, hex integer, decimal integer, real, simple real, literal string, label, string chars, include string, include chars, literal name, ascii integer, escape char, asm hex value, singlequote chars, asm include, - singlequote string } - sticky { literal name, integer, label, string chars, decimal integer, ascii integer } + singlequote string, literal name nows + } + sticky { + literal name nows, integer, label, string chars, decimal integer, + ascii integer, pagespec, and exp, shift exp, multiplicative exp, + inclusive or exp, additive exp, exclusive or exp, urinary exp, + page exp, instruction list, instruction, expression, literal name nows, + } parser file name = ".\\#.cpp" ] @@ -32,9 +37,11 @@ eof = -1 + 0 hex digit = '0-9' + 'A-F' + 'a-f' newline = '\n' letter = 'a-z' + 'A-Z' + '_' +label char = '$' + '?' + '{' + '}' string char = ~eof - ('"' + '\\' + '\n') rst arg = '0-7' asm incl char = 'a-z' + 'A-Z' + '0-9' + '_' + '.' + '\\' + '/' +define chars = ~eof - newline - '\\' - '#' PLUS = '+' MINUS = '-' @@ -55,13 +62,21 @@ a85parse $ comments. ============================================================================ */ + comment - -> "//", any text char?..., newline - -> ';', any text char?..., newline - -> ',', any text char?..., newline + -> cstyle comment + -> "//", any text char?..., '\n' + -> ';', any text char?..., '\n' +// -> ',', any text char?..., '\n' + -> '\n' cstyle comment - -> "/*", ~eof..., "*/" + -> cstyle comment head, "*/" + +cstyle comment head + -> "/*" + -> cstyle comment head, ~eof + -> cstyle comment head, cstyle comment /* @@ -70,69 +85,136 @@ cstyle comment ============================================================================ */ statement - -> WS?..., expression, '\n' - -> WS?..., expression, comment + -> WS..., expression, WS?..., comment + -> label, WS?..., expression, WS?..., comment + -> label, WS?..., comment -> WS?..., comment - -> WS?..., newline - -> WS?..., cstyle comment - -> error, '\n' - + -> preproc inst + -> label, WS?..., '.'?, "equ", equation, WS?..., comment = gAsm->equate((const char *) -1); + -> label, WS?..., '.'?, "set", equation, WS?..., comment = gAsm->directive_set((const char *) -1); + -> WS?..., '.'?, {"include" | "incl"}, literal string, + WS?..., comment = gAsm->include(ss[ss_idx--]); + -> WS?..., '.'?, {"include" | "incl"}, include string, + WS?..., comment = gAsm->include(ss[ss_idx--]); + -> WS?..., '.'?, {"include" | "incl"}, asm include, + WS?..., comment = gAsm->include(ss[ss_idx--]); + -> WS..., cdseg statement = gAsm->directive_cdseg(seg, page); + -> label, WS?..., cdseg statement = gAsm->directive_cdseg(seg, page); + -> error, '\n' = handle_error(); + +preproc start + -> "#" + +preproc inst + -> preproc start, preprocessor directive + +preprocessor directive + -> "include", literal string, WS?..., comment = gAsm->include(ss[ss_idx--]); + -> "include", include string, WS?..., comment = gAsm->include(ss[ss_idx--]); + -> "pragma", "list", WS?..., comment = gAsm->pragma_list(); + -> "pragma", "hex", WS?..., comment = gAsm->pragma_hex(); + -> "ifdef", literal name nows, WS?, comment = gAsm->preproc_ifdef(ss[ss_idx--]); + -> "if", condition, WS?..., comment = gAsm->preproc_if(); + -> "elif", condition, WS?..., comment = gAsm->preproc_elif(); + -> "ifndef", literal name nows, WS?..., comment = gAsm->preproc_ifndef(ss[ss_idx--]); + -> "else", WS?..., comment = gAsm->preproc_else(); + -> "endif", WS?..., comment = gAsm->preproc_endif(); + -> "error", literal string, WS?..., comment = {if (gAsm->preproc_error(ss[ss_idx--])) gAbort = TRUE;} + -> "undef", literal name nows, WS?..., comment = gAsm->preproc_undef(ss[ss_idx--]); + -> "define", macro definition, WS?..., + macro expansion, WS?..., comment = { if (gMacroStack[ms_idx] != 0) { delete gMacroStack[ms_idx]; \ + gMacroStack[ms_idx] = 0; } \ + gMacro = gMacroStack[--ms_idx]; \ + gMacro->m_DefString = ss[ss_idx--]; \ + gAsm->preproc_define(); \ + gMacroStack[ms_idx] = 0; gDefine = 0; } + +macro definition + -> literal name nows, '(', parameter list, ')' = { if (gAsm->preproc_macro()) \ + PCB.reduction_token = a85parse_WS_token; } + -> literal name nows = { if (gAsm->preproc_macro()) \ + PCB.reduction_token = a85parse_WS_token; } + +macro + -> literal name nows, '(', expression list, ')' = { gMacro->m_ParamList = gExpList; \ + gMacro->m_Name = ss[ss_idx--]; \ + gExpList = new VTObArray; \ + gMacroStack[ms_idx++] = gMacro; \ + if (gAsm->preproc_macro()) \ + PCB.reduction_token = a85parse_WS_token; \ + gMacro = new CMacro; } + -> literal name nows = { gMacro->m_Name = ss[ss_idx--]; gMacroStack[ms_idx++] = gMacro; \ + if (gAsm->preproc_macro()) \ + PCB.reduction_token = a85parse_WS_token; \ + gMacro = new CMacro; } + +macro expansion + -> define chars - WS:c = { ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } + -> macro expansion, define chars:c = { ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } + -> macro expansion, "\\\n" = { ss[ss_idx][ss_len++] = '\n'; ss[ss_idx][ss_len] = 0; } + +cdseg statement start + -> '.'?, "cseg" = { page = 0; seg = CSEG; } + -> '.'?, "dseg" = { page = 0; seg = DSEG; } + +cdseg statement + -> cdseg statement start, WS?..., comment + -> cdseg statement start, WS?..., pagespec:p, + WS?..., comment = page = p; + expression - -> label - -> "include", literal string = gAsm->include(ss[ss_idx--]); - -> "include", include string = gAsm->include(ss[ss_idx--]); - -> "include", asm include = gAsm->include(ss[ss_idx--]); - -> "#include", literal string = gAsm->include(ss[ss_idx--]); - -> "#include", include string = gAsm->include(ss[ss_idx--]); - -> "#pragma", "list" = gAsm->pragma_list(); - -> "#pragma", "hex" = gAsm->pragma_hex(); - -> "#ifdef", literal name = gAsm->preproc_ifdef(ss[ss_idx--]); - -> "#ifndef", literal name = gAsm->preproc_ifndef(ss[ss_idx--]); - -> "#else" = gAsm->preproc_else(); - -> "#endif" = gAsm->preproc_endif(); - -> "#define", literal name = gAsm->preproc_define(ss[ss_idx--]); - -> "#undef", literal name = gAsm->preproc_undef(ss[ss_idx--]); - -> literal name, "equ", equation = gAsm->equate(ss[ss_idx--]); - -> literal name, "set", equation = gAsm->directive_set(ss[ss_idx--]); - -> label, "equ", equation = gAsm->equate((const char *) -1); - -> label, "set", equation = gAsm->directive_set((const char *) -1); - -> label?, '.'?, "org", equation = gAsm->directive_org(); - -> label?, '.'?, "aseg" = gAsm->directive_aseg(); - -> label?, '.'?, "cseg" = gAsm->directive_cseg(0); - -> label?, '.'?, "dseg" = gAsm->directive_dseg(0); - -> literal name, "ds", equation = { gAsm->label(ss[ss_idx--]); gAsm->directive_ds(); } - -> label?, "ds", equation = gAsm->directive_ds(); - -> literal name, "db", expression list, WS?... = { gAsm->label(ss[ss_idx--]); gAsm->directive_db(); } - -> label?, "db", expression list, WS?... = gAsm->directive_db(); - -> literal name, "dw", expression list, WS?... = { gAsm->label(ss[ss_idx--]); gAsm->directive_dw(); } - -> label?, "dw", expression list, WS?... = gAsm->directive_dw(); - -> label?, "extrn", name list = gAsm->directive_extern(); - -> label?, "extern", name list = gAsm->directive_extern(); - -> label?, "public", name list = gAsm->directive_public(); - -> label?, "name", literal name = gAsm->directive_name(ss[ss_idx--]); - -> label?, "stkln", equation = gAsm->directive_stkln(); - -> label?, "end" = gAsm->directive_end(""); - -> label?, "end", literal name = gAsm->directive_end(ss[ss_idx--]); - -> label?, "if", condition, WS?... = gAsm->directive_if(); - -> label?, "else" = gAsm->directive_else(); - -> label?, "endif" = gAsm->directive_endif(); - -> label?, "title", singlequote string = gAsm->directive_title(ss[ss_idx--]); - -> label?, "title", literal string = gAsm->directive_title(ss[ss_idx--]); - -> label?, "page", WS..., integer:n = gAsm->directive_page(n); - -> label?, "page" = gAsm->directive_page(-1); - -> label?, "sym" = gAsm->directive_sym(); - -> label?, "link", asm include = gAsm->directive_link(ss[ss_idx--]); - -> label?, "maclib", literal name = gAsm->directive_maclib(ss[ss_idx--]); - -> label?, instruction list, WS?... + -> macro + -> '.'?, "list" = gAsm->pragma_list(); + -> '.'?, "hex" = gAsm->pragma_hex(); + -> '.'?, {"org" | "$=" | "*="}, equation = gAsm->directive_org(); + -> '.'?, "aseg" = gAsm->directive_aseg(); + -> '.'?, {"ds" | "block"}, equation = gAsm->directive_ds(); + -> '.'?, {"db" | "byte" | "text"}, + expression list = gAsm->directive_db(); + -> '.'?, {"dw" | "word"}, + expression list = gAsm->directive_dw(); + -> '.'?, "public", name list = gAsm->directive_public(); + -> '.'?, "extrn", name list = gAsm->directive_extern(); + -> '.'?, "extern", name list = gAsm->directive_extern(); + -> '.'?, "module", literal name nows = gAsm->directive_module(ss[ss_idx--]); + -> '.'?, "name", literal name nows = gAsm->directive_name(ss[ss_idx--]); + -> '.'?, "stkln", equation = gAsm->directive_stkln(); + -> '.'?, "echo", equation = gAsm->directive_echo(); + -> '.'?, "echo", literal string = gAsm->directive_echo(ss[ss_idx--]); + -> '.'?, "fill", WS?..., expression list = gAsm->directive_fill(); + -> '.'?, "printf", literal string, + ',', WS?..., equation = gAsm->directive_printf(ss[ss_idx--]); + -> '.'?, "end" = gAsm->directive_end(""); + -> '.'?, "end", literal name nows = gAsm->directive_end(ss[ss_idx--]); + -> "if", condition = gAsm->directive_if(); + -> "else" = gAsm->directive_else(); + -> "endif" = gAsm->directive_endif(); + -> '.'?, "msfirst" = gAsm->directive_endian(1); + -> '.'?, "lsfirst" = gAsm->directive_endian(0); + -> '.'?, "title", singlequote string = gAsm->directive_title(ss[ss_idx--]); + -> '.'?, "title", literal string = gAsm->directive_title(ss[ss_idx--]); + -> '.'?, "nopage" = gAsm->directive_page(-1); + -> '.'?, "sym" = gAsm->directive_sym(); + -> '.'?, "link", asm include = gAsm->directive_link(ss[ss_idx--]); + -> '.'?, "maclib", literal name nows = gAsm->directive_maclib(ss[ss_idx--]); + -> instruction list + -> page exp = gAsm->directive_page(page); + +page exp + -> '.'?, "page" = page = 60; + -> page exp, WS..., integer:n = page = n; expression list -> literal string = expression_list_literal(); -> singlequote string = expression_list_literal(); -> equation = expression_list_equation(); - -> expression list, WS?..., ",", WS?..., equation = expression_list_equation(); - -> expression list, WS?..., ",", WS?..., literal string = expression_list_literal(); - -> expression list, WS?..., ",", WS?..., singlequote string = expression_list_literal(); + -> expression list, ",", WS?..., + equation = expression_list_equation(); + -> expression list, ",", WS?..., + literal string = expression_list_literal(); + -> expression list, ",", WS?..., + singlequote string = expression_list_literal(); [ hidden {expression list} ] /* @@ -143,17 +225,22 @@ expression list */ name list - -> literal name = gNameList->Add(ss[ss_idx--]); - -> name list, WS?..., ",", WS?..., literal name = gNameList->Add(ss[ss_idx--]); + -> literal name nows = gNameList->Add(ss[ss_idx--]); + -> name list, ",", WS?..., literal name nows = gNameList->Add(ss[ss_idx--]); literal name + -> literal name nows, WS?... + +literal name nows -> literal alpha -> "$" = { strcpy(ss[++ss_idx], "$"); ss_len = 1; } + -> "&" = { strcpy(ss[++ss_idx], "&"); ss_len = 1; } literal alpha - -> letter+'$':c = { ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } - -> literal name, letter+'$':c = { ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } - -> literal name, digit:c = { ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } + -> letter + label char:c = { ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; \ + if (PCB.column == 2) ss_addr = gAsm->m_ActiveSeg->m_Address; } + -> literal name nows, letter+label char + '.':c = { ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } + -> literal name nows, digit:c = { ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } asm include -> asm incl char:c = { ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } @@ -172,11 +259,25 @@ literal string string chars -> '"' = { ss_idx++; ss_len = 0; } - -> string chars, string char:c = { ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } - -> string chars, '\\', ~eof - '\n':c = { ss[ss_idx][ss_len++] = '\\'; ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } + -> string chars, str escape char:c = { ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -> string chars, '\\', '\n' [ hidden {string chars} ] +(int) str escape char + -> ascii - '"' - '\\':n = n; + -> '\\', '\\' = '\\'; + -> '\\', 'n' = '\n'; + -> '\\', 't' = '\t'; + -> '\\', 'r' = '\r'; + -> '\\', '0' = '\0'; + -> '\\', '"' = '"'; + -> '\\', 'b' = 0x08; + -> '\\', 'f' = 0x0C; + -> '\\', '0-3':n1, '0-9':n2, '0-9':n3 = (n1-'0') * 64 + (n2-'0') * 8 + n3-'0'; + -> '\\', {'x'|'$'}, hex digit:n1, hex digit:n2 = chtoh(n1) * 16 + chtoh(n2); + -> '\\', {'x'|'$'}, hex digit:n1 = chtoh(n1); +[ hidden {str escape char} ] + include string -> include chars, '>' = { ss[ss_idx][ss_len++] = '>'; ss[ss_idx][ss_len] = 0; } @@ -188,8 +289,12 @@ include chars [ hidden {include chars} ] label - -> literal name, ":" = gAsm->label(ss[ss_idx--]); + -> literal name nows, ":" = gAsm->label(ss[ss_idx--]); + -> literal name nows = gAsm->label(ss[ss_idx--]); +(int) pagespec + -> "page" = PAGE; + -> "inpage" = INPAGE; /* ============================================================================ @@ -211,15 +316,6 @@ condition start -> equation, {"lt" | "<"} = condition(COND_LT); [ hidden {condition start} ] -//condition start -// -> equation = { gCond->m_EqLeft = gEq; gEq = new CRpnEquation; } -// -> equation, {"eq" | "==" | "="}, equation = condition(COND_EQ); -// -> equation, {"ne" | "!="}, equation = condition(COND_NE); -// -> equation, {"ge" | ">="}, equation = condition(COND_GE); -// -> equation, {"le" | "<="}, equation = condition(COND_LE); -// -> equation, {"gt" | ">"}, equation = condition(COND_GT); -// -> equation, {"lt" | "<"}, equation = condition(COND_LT); - /* ============================================================================ Define equations. We support complex equations that consist of additive, @@ -232,35 +328,34 @@ equation -> inclusive or exp (void) inclusive or exp - -> exclusive or exp - -> inclusive or exp,'|',WS?..., exclusive or exp = gEq->Add(RPN_BITOR); - -> inclusive or exp, "or", WS?...,exclusive or exp = gEq->Add(RPN_BITOR); + -> exclusive or exp, WS?... + -> inclusive or exp, '|', WS?..., exclusive or exp = gEq->Add(RPN_BITOR); + -> inclusive or exp, "or", WS?..., exclusive or exp = gEq->Add(RPN_BITOR); (void) exclusive or exp - -> and exp + -> and exp, WS?... -> exclusive or exp, '^', WS?..., and exp = gEq->Add(RPN_BITXOR); -> exclusive or exp, "xor", WS?..., and exp = gEq->Add(RPN_BITXOR); (void) and exp - -> shift exp + -> shift exp, WS?... -> and exp, '&', WS?..., shift exp = gEq->Add(RPN_BITAND); -> and exp, "and", WS?..., shift exp = gEq->Add(RPN_BITAND); (void) shift exp - -> additive exp + -> additive exp, WS?... -> shift exp, "<<", WS?..., additive exp = gEq->Add(RPN_LEFTSHIFT); -> shift exp, "shl", WS?..., additive exp = gEq->Add(RPN_LEFTSHIFT); -> shift exp, ">>", WS?..., additive exp = gEq->Add(RPN_RIGHTSHIFT); -> shift exp, "shr", WS?..., additive exp = gEq->Add(RPN_RIGHTSHIFT); (void) additive exp - -> multiplicative exp + -> multiplicative exp, WS?... -> additive exp, '+', WS?..., multiplicative exp = gEq->Add(RPN_ADD); -> additive exp, '-', WS?..., multiplicative exp = gEq->Add(RPN_SUBTRACT); (void) multiplicative exp -// -> primary exp - -> urinary exp + -> urinary exp, WS?... -> multiplicative exp, '*', WS?..., primary exp = gEq->Add(RPN_MULTIPLY); -> multiplicative exp, '/', WS?..., primary exp = gEq->Add(RPN_DIVIDE); -> multiplicative exp, '%', WS?..., primary exp = gEq->Add(RPN_MODULUS); @@ -272,21 +367,33 @@ urinary exp -> '!', primary exp = gEq->Add(RPN_NOT); -> "not", primary exp = gEq->Add(RPN_NOT); -> '~', primary exp = gEq->Add(RPN_BITNOT); + -> '-', primary exp = gEq->Add(RPN_NEGATE); primary exp -> value:n = gEq->Add((double) n); - -> literal name = gEq->Add(ss[ss_idx--]); +// -> literal name nows = gEq->Add(ss[ss_idx--]); + -> macro = { delete gMacro; gMacro = gMacroStack[ms_idx-1]; \ + gMacroStack[ms_idx--] = 0; if (gMacro->m_ParamList == 0) \ + {\ + gEq->Add(gMacro->m_Name); gMacro->m_Name = ""; }\ + else { \ + gEq->Add((VTObject *) gMacro); gMacro = new CMacro; \ + } } -> function - -> '(', equation, ')', WS?... + -> '(', WS?..., equation, WS?..., ')' (void) function --> "floor", '(', equation, ')' = gEq->Add(RPN_FLOOR); --> "ceil", '(', equation, ')' = gEq->Add(RPN_CEIL); --> "ln", '(', equation, ')' = gEq->Add(RPN_LN); --> "log", '(', equation, ')' = gEq->Add(RPN_LOG); --> "sqrt", '(', equation, ')' = gEq->Add(RPN_SQRT); --> "ip", '(', equation, ')' = gEq->Add(RPN_IP); --> "fp", '(', equation, ')' = gEq->Add(RPN_FP); + -> "floor", WS?..., '(', equation, ')' = gEq->Add(RPN_FLOOR); + -> "ceil", WS?..., '(', equation, ')' = gEq->Add(RPN_CEIL); + -> "ln", WS?..., '(', equation, ')' = gEq->Add(RPN_LN); + -> "log", WS?..., '(', equation, ')' = gEq->Add(RPN_LOG); + -> "sqrt", WS?..., '(', equation, ')' = gEq->Add(RPN_SQRT); + -> "ip", WS?..., '(', equation, ')' = gEq->Add(RPN_IP); + -> "fp", WS?..., '(', equation, ')' = gEq->Add(RPN_FP); + -> "high", WS?..., '(', equation, ')' = gEq->Add(RPN_HIGH); + -> "low", WS?..., '(', equation, ')' = gEq->Add(RPN_LOW); + -> "defined", WS?..., '(', WS?..., literal name, + WS?..., ')' = gEq->Add(RPN_DEFINED, ss[ss_idx--]); /* ============================================================================ @@ -302,11 +409,13 @@ primary exp -> ascii integer:n = n; -> decimal integer = conv_to_dec(); -> hex integer = conv_to_hex(); - -> asm hex value, "h" = conv_to_hex(); - -> decimal integer, "h" = conv_to_hex(); - -> decimal integer, "b" = conv_to_bin(); - -> decimal integer, "q" = conv_to_oct(); - -> decimal integer, "d" = conv_to_dec(); + -> binary integer = conv_to_bin(); + -> octal integer = conv_to_oct(); + -> asm hex value, 'h'+'H' = conv_to_hex(); + -> decimal integer, 'h'+'H' = conv_to_hex(); + -> decimal integer, 'b' = conv_to_bin(); + -> decimal integer, {"q"|"o"} = conv_to_oct(); + -> decimal integer, 'd' = conv_to_dec(); decimal integer -> '+', '0-9':n = { int_len = 1; integer[0] = n; integer[1] = 0; } @@ -318,12 +427,21 @@ decimal integer hex integer -> '0', 'x' + 'X', hex digit:n = { int_len = 1; integer[0] = n; integer[1] = 0; } + -> '$', hex digit:n = { int_len = 1; integer[0] = n; integer[1] = 0; } -> hex integer, hex digit:n = { integer[int_len++] = n; integer[int_len] = 0; } asm hex value -> decimal integer, 'A-F' + 'a-f':n = { integer[int_len++] = n; integer[int_len] = 0; } -> asm hex value, hex digit:n = { integer[int_len++] = n; integer[int_len] = 0; } +binary integer + -> '%', '0-1':n = { integer[int_len++] = n; integer[int_len] = 0; } + -> binary integer, '0-1':n = { integer[int_len++] = n; integer[int_len] = 0; } + +octal integer + -> '@', '0-7':n = { integer[int_len++] = n; integer[int_len] = 0; } + -> octal integer, '0-7':n = { integer[int_len++] = n; integer[int_len] = 0; } + (int) ascii integer -> '\'', escape char:n, '\'' = n; -> '\'', escape char:n1, escape char:n2, '\'' = (n1 << 8) | n2; @@ -362,25 +480,25 @@ register 8 bit -> "e" = reg[reg_cnt++] = '3'; -> "h" = reg[reg_cnt++] = '4'; -> "l" = reg[reg_cnt++] = '5'; - -> "m" = reg[reg_cnt++] = '6'; + -> {"m" | "(hl)"} = reg[reg_cnt++] = '6'; -> "a" = reg[reg_cnt++] = '7'; register 16 bit - -> "b" = reg[reg_cnt++] = '0'; - -> "d" = reg[reg_cnt++] = '1'; - -> "h" = reg[reg_cnt++] = '2'; + -> {"b" | "bc" } = reg[reg_cnt++] = '0'; + -> {"d" | "de" } = reg[reg_cnt++] = '1'; + -> {"h" | "hl" } = reg[reg_cnt++] = '2'; -> "sp" = reg[reg_cnt++] = '3'; stack register - -> "b" = reg[reg_cnt++] = '0'; - -> "d" = reg[reg_cnt++] = '1'; - -> "h" = reg[reg_cnt++] = '2'; + -> {"b" | "bc" } = reg[reg_cnt++] = '0'; + -> {"d" | "de" } = reg[reg_cnt++] = '1'; + -> {"h" | "hl" } = reg[reg_cnt++] = '2'; -> "psw" = reg[reg_cnt++] = '3'; -> "a" = reg[reg_cnt++] = '3'; bd register - -> "b" = reg[reg_cnt++] = '0'; - -> "d" = reg[reg_cnt++] = '1'; + -> {"b" | "bc" } = reg[reg_cnt++] = '0'; + -> {"d" | "de" } = reg[reg_cnt++] = '1'; /* ============================================================================ @@ -388,24 +506,111 @@ bd register ============================================================================ */ instruction list - -> instruction - -> instruction list, WS?..., '!' - -> instruction list, WS?..., instruction + -> instruction, WS?... +// -> instruction, WS?... +// -> instruction list, WS?..., "!" +// -> instruction list, WS?..., "\\" +// -> instruction list, '!', WS..., instruction +// -> instruction list, '\\', WS?..., instruction +// -> instruction list, instruction instruction - -> "aci", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_ACI); + -> eight bit reg inst + -> sixteen bit reg inst + -> bd reg inst + -> stack reg inst + -> immediate operand inst + -> lxi inst + -> mvi inst + -> rst inst + -> no arg inst + -> instruction list, "!", WS?..., instruction +// -> instruction list, "\\", WS?..., instruction + +no arg inst + -> {"ashr" | "shlr" | "arhl" | "rrhl" } = gAsm->opcode_arg_0 (OPCODE_ASHR); + -> "cma" = gAsm->opcode_arg_0 (OPCODE_CMA); + -> "cmc" = gAsm->opcode_arg_0 (OPCODE_CMC); + -> "daa" = gAsm->opcode_arg_0 (OPCODE_DAA); + -> "di" = gAsm->opcode_arg_0 (OPCODE_DI); + -> {"dsub" | "hlmbc" } = gAsm->opcode_arg_0 (OPCODE_DSUB); + -> "ei" = gAsm->opcode_arg_0 (OPCODE_EI); + -> "hlt" = gAsm->opcode_arg_0 (OPCODE_HLT); + -> {"lhlx" | "lhli" | "lhlde" } = gAsm->opcode_arg_0 (OPCODE_LHLX); + -> "nop" = gAsm->opcode_arg_0 (OPCODE_NOP); + -> "pchl" = gAsm->opcode_arg_0 (OPCODE_PCHL); + -> "ral" = gAsm->opcode_arg_0 (OPCODE_RAL); + -> "rar" = gAsm->opcode_arg_0 (OPCODE_RAR); + -> "rc" = gAsm->opcode_arg_0 (OPCODE_RC); + -> "ret" = gAsm->opcode_arg_0 (OPCODE_RET); + -> "rim" = gAsm->opcode_arg_0 (OPCODE_RIM); + -> "rlc" = gAsm->opcode_arg_0 (OPCODE_RLC); + -> {"rlde" | "rdel" } = gAsm->opcode_arg_0 (OPCODE_RLDE); + -> "rm" = gAsm->opcode_arg_0 (OPCODE_RM); + -> "rnc" = gAsm->opcode_arg_0 (OPCODE_RNC); + -> "rnz" = gAsm->opcode_arg_0 (OPCODE_RNZ); + -> "rp" = gAsm->opcode_arg_0 (OPCODE_RP); + -> "rpe" = gAsm->opcode_arg_0 (OPCODE_RPE); + -> "rpo" = gAsm->opcode_arg_0 (OPCODE_RPO); + -> "rrc" = gAsm->opcode_arg_0 (OPCODE_RRC); + -> "rstv" = gAsm->opcode_arg_0 (OPCODE_RSTV); + -> "rz" = gAsm->opcode_arg_0 (OPCODE_RZ); + -> {"shlx" | "shli" | "shlde"} = gAsm->opcode_arg_0 (OPCODE_SHLX); + -> "sim" = gAsm->opcode_arg_0 (OPCODE_SIM); + -> "sphl" = gAsm->opcode_arg_0 (OPCODE_SPHL); + -> "stc" = gAsm->opcode_arg_0 (OPCODE_STC); + -> "xchg" = gAsm->opcode_arg_0 (OPCODE_XCHG); + -> "xthl" = gAsm->opcode_arg_0 (OPCODE_XTHL); + +bd reg inst + -> "stax", WS?..., bd register = gAsm->opcode_arg_1reg (OPCODE_STAX); + -> "ldax", WS?..., bd register = gAsm->opcode_arg_1reg (OPCODE_LDAX); + +stack reg inst + -> "pop", WS?..., stack register = gAsm->opcode_arg_1reg (OPCODE_POP); + -> "push", WS?..., stack register = gAsm->opcode_arg_1reg (OPCODE_PUSH); + +eight bit reg inst -> "adc", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_ADC); -> "add", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_ADD); - -> "adi", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_ADI); -> "ana", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_ANA); + -> "cmp", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_CMP); + -> "dcr", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_DCR); + -> "inr", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_INR); + -> "mov", WS?..., register 8 bit, WS?..., ",", + WS?..., register 8 bit = gAsm->opcode_arg_2reg (OPCODE_MOV); + -> "ora", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_ORA); + -> "sbb", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_SBB); + -> "sub", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_SUB); + -> "xra", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_XRA); + +sixteen bit reg inst + -> "dad", WS?..., register 16 bit = gAsm->opcode_arg_1reg (OPCODE_DAD); + -> "dcx", WS?..., register 16 bit = gAsm->opcode_arg_1reg (OPCODE_DCX); + -> "inx", WS?..., register 16 bit = gAsm->opcode_arg_1reg (OPCODE_INX); + +lxi inst start + -> "lxi", WS?..., register 16 bit + +lxi inst + -> lxi inst start, WS?..., ',', WS?..., equation = gAsm->opcode_arg_1reg_equ16(OPCODE_LXI); + +mvi inst start + -> "mvi", WS?..., register 8 bit + +mvi inst + -> mvi inst start, WS?..., ',', WS?..., equation = gAsm->opcode_arg_1reg_equ8(OPCODE_MVI); + +rst inst + -> "rst", WS?..., rst arg:c = gAsm->opcode_arg_imm (OPCODE_RST, c); + +immediate operand inst + -> "aci", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_ACI); + -> "adi", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_ADI); -> "ani", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_ANI); - -> "ashr" = gAsm->opcode_arg_0 (OPCODE_ASHR); -> "call", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CALL); -> "cc", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CC); -> "cm", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CM); - -> "cma" = gAsm->opcode_arg_0 (OPCODE_CMA); - -> "cmc" = gAsm->opcode_arg_0 (OPCODE_CMC); - -> "cmp", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_CMP); -> "cnc", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CNC); -> "cnz", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CNZ); -> "cp", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CP); @@ -413,82 +618,32 @@ instruction -> "cpi", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_CPI); -> "cpo", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CPO); -> "cz", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_CZ); - -> "daa" = gAsm->opcode_arg_0 (OPCODE_DAA); - -> "dad", WS?..., register 16 bit = gAsm->opcode_arg_1reg (OPCODE_DAD); - -> "dcr", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_DCR); - -> "dcx", WS?..., register 16 bit = gAsm->opcode_arg_1reg (OPCODE_DCX); - -> "di" = gAsm->opcode_arg_0 (OPCODE_DI); - -> "dsub" = gAsm->opcode_arg_0 (OPCODE_DSUB); - -> "ei" = gAsm->opcode_arg_0 (OPCODE_EI); - -> "hlt" = gAsm->opcode_arg_0 (OPCODE_HLT); -> "in", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_IN); - -> "inr", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_INR); - -> "inx", WS?..., register 16 bit = gAsm->opcode_arg_1reg (OPCODE_INX); -> "jc", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JC); - -> "jd", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JD); - -> "jx", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JD); + -> {"jx" | "jx5" | "jtm" | "jk" | "jd" }, WS?..., + equation = gAsm->opcode_arg_equ16 (OPCODE_JD); -> "jm", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JM); -> "jmp", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JMP); -> "jnc", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JNC); - -> "jnd", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JND); - -> "jnx", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JND); + -> {"jnx" | "jnx5" | "jtp" | "jnk" | "jnd" }, + WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JND); -> "jnz", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JNZ); -> "jp", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JP); -> "jpe", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JPE); -> "jpo", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JPO); -> "jz", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JZ); -> "lda", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_LDA); - -> "ldax", WS?..., bd register = gAsm->opcode_arg_1reg (OPCODE_LDAX); - -> "ldeh", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_LDEH); - -> "ldes", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_LDES); + -> {"ldeh" | "dehl" | "ldhi"}, WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_LDEH); + -> {"ldes" | "desp"}, WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_LDES); -> "lhld", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_LHLD); - -> "lhlx" = gAsm->opcode_arg_0 (OPCODE_LHLX); - -> "lxi", WS?..., register 16 bit, WS?..., ',', - WS?..., equation = gAsm->opcode_arg_1reg_equ8(OPCODE_LXI); - -> "mov", WS?..., register 8 bit, WS?..., - ",", WS?..., register 8 bit = gAsm->opcode_arg_2reg (OPCODE_MOV); - -> "mvi", WS?..., register 8 bit,WS?..., - ",", WS?..., equation = gAsm->opcode_arg_1reg_equ8(OPCODE_MVI); - -> "nop" = gAsm->opcode_arg_0 (OPCODE_NOP); - -> "ora", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_ORA); -> "ori", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_ORI); -> "out", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_OUT); - -> "pchl" = gAsm->opcode_arg_0 (OPCODE_PCHL); - -> "pop", WS?..., stack register = gAsm->opcode_arg_1reg (OPCODE_POP); - -> "push", WS?..., stack register = gAsm->opcode_arg_1reg (OPCODE_PUSH); - -> "ral" = gAsm->opcode_arg_0 (OPCODE_RAL); - -> "rar" = gAsm->opcode_arg_0 (OPCODE_RAR); - -> "rc" = gAsm->opcode_arg_0 (OPCODE_RC); - -> "ret" = gAsm->opcode_arg_0 (OPCODE_RET); - -> "rim" = gAsm->opcode_arg_0 (OPCODE_RIM); - -> "rlc" = gAsm->opcode_arg_0 (OPCODE_RLC); - -> "rlde" = gAsm->opcode_arg_0 (OPCODE_RLDE); - -> "rm" = gAsm->opcode_arg_0 (OPCODE_RM); - -> "rnc" = gAsm->opcode_arg_0 (OPCODE_RNC); - -> "rnz" = gAsm->opcode_arg_0 (OPCODE_RNZ); - -> "rp" = gAsm->opcode_arg_0 (OPCODE_RP); - -> "rpe" = gAsm->opcode_arg_0 (OPCODE_RPE); - -> "rpo" = gAsm->opcode_arg_0 (OPCODE_RPO); - -> "rrc" = gAsm->opcode_arg_0 (OPCODE_RRC); - -> "rst", WS?..., rst arg:c = gAsm->opcode_arg_imm (OPCODE_RST, c); - -> "rz" = gAsm->opcode_arg_0 (OPCODE_RZ); - -> "sbb", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_SBB); -> "sbi", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_SBI); -> "shld", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_SHLD); - -> "shlx" = gAsm->opcode_arg_0 (OPCODE_SHLX); - -> "sim" = gAsm->opcode_arg_0 (OPCODE_SIM); - -> "sphl" = gAsm->opcode_arg_0 (OPCODE_SPHL); -> "sta", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_STA); - -> "stax", WS?..., bd register = gAsm->opcode_arg_1reg (OPCODE_STAX); - -> "stc" = gAsm->opcode_arg_0 (OPCODE_STC); - -> "sub", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_SUB); -> "sui", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_SUI); - -> "xchg" = gAsm->opcode_arg_0 (OPCODE_XCHG); - -> "xra", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_XRA); -> "xri", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_XRI); - -> "xthl" = gAsm->opcode_arg_0 (OPCODE_XTHL); - { // Embedded C @@ -508,13 +663,19 @@ typedef int BOOL; VTAssembler* gAsm = 0; // Pointer to the assembler CRpnEquation* gEq = 0; // Pointer to active equation VTObArray* gExpList = 0; // Pointer to active expression list +CMacro* gMacro = 0; // Pointer to active macro MStringArray* gNameList = 0; // Pointer to active name list +int gDefine = 0; // Indicated in a #define reduction CCondition* gCond = 0; // Pointer to active condition +const char* gFilename = 0; // Pointer to the filename char ss[32][256]; // String Stack; +CMacro* gMacroStack[32]; // Macro Stack; +int ms_idx = 0; // Macro Stack Index char integer[64]; // Integer storage space char int_len = 0; // Integer string length int ss_idx = 0; // String Stack Index int ss_len = 0; // SS string length +int ss_addr = 0; // Address at start of literal name double gDivisor = 1.0; // Current divisor for float converwions int gTabSize = 4; char reg[10]; // Register arguments @@ -522,7 +683,8 @@ int reg_cnt = 0; // Register Arg count int label = 0; // Number of labels on string stack int name_list_cnt = 0; // Number of strings in name list int ex_cnt = 0; // Number of expressions in expression list - +int gAbort = 0; // Abort on #error +int page, seg; void a85parse(void); // This function checks the string accumulator for errors @@ -534,6 +696,8 @@ void check_string_stack(void) // If we have no errors... if (gAsm->m_Errors.GetSize() == 0) { + int c; + // Check string accumulator size int stringCount; if ((stringCount = ss_idx) != 0) @@ -542,6 +706,11 @@ void check_string_stack(void) string.Format("Internal Design Parse Error - %d string(s) left on stack!", stringCount); gAsm->m_Errors.Add(string); + for (c = 0; c < stringCount; c++) + { + string.Format(" %s", ss[ss_idx--]); + gAsm->m_Errors.Add(string); + } } } } @@ -555,11 +724,9 @@ BOOL ParseASMFile(const char* filename, VTAssembler* pAsm) if (pAsm == NULL) return FALSE; + // Make the given assembler a global gAsm = pAsm; - // Clear old design from the CDesign object - gAsm->ResetContent(); - // Insure no active equation left over from a previous run if (gEq != 0) delete gEq; @@ -569,13 +736,17 @@ BOOL ParseASMFile(const char* filename, VTAssembler* pAsm) delete gNameList; if (gCond != 0) delete gCond; + if (gMacro != 0) + delete gMacro; // Allocate an active equation to be used during parsing gEq = new CRpnEquation; gExpList = new VTObArray; gNameList = new MStringArray; gCond = new CCondition; + gMacro = new CMacro; gAsm->m_FileIndex = gAsm->m_Filenames.Add(filename); + gFilename = filename; // Try to open the file if ((gAsm->m_fd = fopen(gAsm->m_Filenames[gAsm->m_FileIndex], "r")) == 0) @@ -589,6 +760,12 @@ BOOL ParseASMFile(const char* filename, VTAssembler* pAsm) ss_idx = 0; ss_len = 0; int_len = 0; + gAbort = 0; + + // Reset the Macro stack + for (int c = 0; c < 32; c++) + gMacroStack[c] = 0; + ms_idx = 0; // Reset the Register, name, expression, and label counters reg_cnt = label = ex_cnt = name_list_cnt = 0; @@ -610,27 +787,166 @@ BOOL ParseASMFile(const char* filename, VTAssembler* pAsm) return TRUE; } +void handle_error(void) +{ + char msg[512]; + + sprintf(msg, "Error token = %d", (PCB).error_frame_token); +} + +void syntax_error(const char *token_name) +{ + MString string; + int eolMsg; + int expected_immediate = 0; + int expected_reg = 0; + + // Determine if this is the "unexpected eol" message + eolMsg = !strcmp("Unexpected '\\n'", (PCB).error_message); + + switch ((PCB).error_frame_token) + { + // Handle general statement syntax error + case a85parse_statement_token: + string.Format("Error in line %d(%s), column %d: Malformed %s - %s", + (PCB).line, gFilename, (PCB).column, + token_name, (PCB).error_message); + break; + + // Handle improper LXI instruction error + case a85parse_lxi_inst_start_token: + if (reg_cnt == 0) + expected_reg = 16; + else + expected_immediate = 1; + break; + + // Handle improper MVI instruction error + case a85parse_mvi_inst_start_token: + if (reg_cnt == 0) + expected_reg = 8; + else + expected_immediate = 1; + break; + + // Handle improper 16-bit register argument error + case a85parse_sixteen_bit_reg_inst_token: + case a85parse_stack_reg_inst_token: + expected_reg = 16; + break; + + // Handle improper 8-bit register argument error + case a85parse_eight_bit_reg_inst_token: + expected_reg = 8; + break; + + case a85parse_lxi_inst_token: + case a85parse_mvi_inst_token: + case a85parse_immediate_operand_inst_token: + expected_immediate = 1; + break; + + case a85parse_rst_inst_token: + if (eolMsg) + string.Format("Error in line %d(%s), column %d: Expected RST number", + (PCB).line, gFilename, (PCB).column); + else + string.Format("Error in line %d(%s), column %d: Invalid RST number", + (PCB).line, gFilename, (PCB).column, (PCB).error_message); + break; + + case a85parse_preproc_start_token: + if (eolMsg) + string.Format("Error in line %d(%s), column %d: Expected preprocessor directive", + (PCB).line, gFilename, (PCB).column); + else + string.Format("Error in line %d(%s), column %d: Unknown preprocessor directive", + (PCB).line, gFilename, (PCB).column, (PCB).error_message); + break; + + case a85parse_preproc_inst_token: + string.Format("Error in line %d(%s), column %d: Invalid preprocessor directive syntax", + (PCB).line, gFilename, (PCB).column, (PCB).error_message); + break; + + default: + if (eolMsg) + string.Format("Error in line %d(%s), column %d: Unexpected end of line", + (PCB).line, gFilename, (PCB).column); + else + string.Format("Error in line %d(%s), column %d: %s", + (PCB).line, gFilename, (PCB).column, (PCB).error_message); + break; + } + + if (expected_reg == 16) + { + if (eolMsg) + string.Format("Error in line %d(%s), column %d: Expected 16-bit register", + (PCB).line, gFilename, (PCB).column); + else + string.Format("Error in line %d(%s), column %d: Invalid 16-bit register", + (PCB).line, gFilename, (PCB).column); + } + else if (expected_reg == 8) + { + if (eolMsg) + string.Format("Error in line %d(%s), column %d: Expected 8-bit register", + (PCB).line, gFilename, (PCB).column); + else + string.Format("Error in line %d(%s), column %d: Invalid 8-bit register", + (PCB).line, gFilename, (PCB).column); + } + + if (expected_immediate) + { + if (eolMsg) + string.Format("Error in line %d(%s), column %d: Expected immediate operand", + (PCB).line, gFilename, (PCB).column); + else + string.Format("Error in line %d(%s), column %d: Invalid immediate operand", + (PCB).line, gFilename, (PCB).column); + } + + if (!gAbort) + gAsm->m_Errors.Add(string); + + // Clear the string stack + ss_idx = 0; + ss_len = 0; +} + // Define macros to handle input and errors #define TAB_SPACING gTabSize -#define GET_INPUT {(PCB).input_code = gAsm->m_fd != 0 ? \ - fgetc(gAsm->m_fd) : 0; if ((PCB).input_code == 13) (PCB).input_code = fgetc(gAsm->m_fd);} +#define GET_INPUT {(PCB).input_code = (gAsm->m_fd != 0 && !gAbort) ? \ + fgetc(gAsm->m_fd) : 0; if ((PCB).input_code == 13) (PCB).input_code = fgetc(gAsm->m_fd);\ + } + +#define SYNTAX_ERROR { syntax_error(TOKEN_NAMES[(PCB).error_frame_token]); } +/* #define SYNTAX_ERROR {MString string; if ((PCB).error_frame_token != 0) \ - string.Format("Malformed %s - %s, line %d, column %d", \ - TOKEN_NAMES[(PCB).error_frame_token], (PCB).error_message, (PCB).line, (PCB).column); else \ - string.Format("%s, line %d, column %d", \ - (PCB).error_message, (PCB).line, (PCB).column); \ - gAsm->m_Errors.Add(string); ss_idx = 0; ss_len = 0; } + string.Format("Error in line %d(%s), column%d: Malformed %s - %s", \ + (PCB).line, gFilename, (PCB).column, \ + TOKEN_NAMES[(PCB).error_frame_token], (PCB).error_message); \ + else if (strcmp("Unexpected '\\n'", (PCB).error_message) == 0) \ + string.Format("Error in line %d(%s), column %d: Unexpected end of line", \ + (PCB).line, gFilename, (PCB).column); \ + else \ + string.Format("Error in line %d(%s), column %d: %s", (PCB).line, gFilenaeme, \ + (PCB).column, (PCB).error_message); \ + if (!gAbort) gAsm->m_Errors.Add(string); ss_idx = 0; ss_len = 0; } +*/ #define PARSER_STACK_OVERFLOW {MString string; string.Format(\ "\nParser stack overflow, line %d, column %d",\ - (PCB).line, (PCB).column); gAsm->m_Errors.Add(string);} + (PCB).line, (PCB).column); if (!gAbort) gAsm->m_Errors.Add(string);} #define REDUCTION_TOKEN_ERROR {MString string; string.Format(\ "\nReduction token error, line %d, column %d", \ - (PCB).line, (PCB).column); gAsm->m_Errors.Add(string);} + (PCB).line, (PCB).column); if (!gAbort) gAsm->m_Errors.Add(string);} int do_hex(int h, int n) { @@ -718,6 +1034,14 @@ int conv_to_bin() return temp1; } -} // End of Embedded C +int chtoh(char ch) +{ + if (ch < 'A') + return ch - '0'; + if (ch < 'a') + return ch = 'A' + 10; + return ch - 'a' + 10; +} +} // End of Embedded C diff --git a/src/assemble.cpp b/src/assemble.cpp index e3d35d1..4eeb785 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -1,6 +1,31 @@ /* -======================================================================== -VTAssembler: This class defines an 8085 Macro Assembler for the + * $Id$ + * + * Copyright 2010 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + + + VTAssembler: This class defines an 8085 Macro Assembler for the VirtualT project. ======================================================================== @@ -8,20 +33,28 @@ VTAssembler: This class defines an 8085 Macro Assembler for the #include "VirtualT.h" #include "assemble.h" -#include "a85parse.h" #include "elf.h" +#include "project.h" #include #include #include #include #include +extern "C" +{ +#include "intelhex.h" +} + extern CRpnEquation* gEq; extern VTObArray* gExpList; extern MStringArray* gNameList; extern CCondition* gCond; -extern char reg[10]; -extern int reg_cnt; +extern CMacro* gMacro; +extern char reg[10]; +extern int reg_cnt; +extern const char * gFilename; +extern int gDefine; #define PCB a85parse_pcb @@ -46,11 +79,11 @@ unsigned char gOpcodeType[INST_ORG] = { 0, OPCODE_NOARG, OPCODE_NOARG, OPCODE_NOARG, OPCODE_NOARG, // 61-64 OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, // 55-68 OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, // 69-72 - OPCODE_NOARG, OPCODE_EQU16, OPCODE_EQU16, OPCODE_NOARG, // 73-76 + OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, OPCODE_NOARG, // 73-76 OPCODE_EQU16, OPCODE_EQU8, OPCODE_EQU8, OPCODE_EQU8, // 77-80 OPCODE_EQU8, OPCODE_EQU8, OPCODE_EQU8, OPCODE_EQU8, // 81-84 OPCODE_EQU8, OPCODE_IMM, OPCODE_EQU16, OPCODE_NOARG, // 85-88 - OPCODE_NOARG // 89 + OPCODE_NOARG, OPCODE_NOARG // 89 }; unsigned char gOpcodeBase[INST_ORG] = { 0, @@ -65,7 +98,7 @@ unsigned char gOpcodeBase[INST_ORG] = { 0, 0xC4, 0xCC, 0xD4, 0xDC, 0xE4, 0xEC, 0xF4, 0xFC, // 65-72 0x22, 0xCD, 0xDD, 0xED, 0xFD, 0xC6, 0xCE, 0xD6, // 73-80 0xDE, 0xE6, 0xEE, 0xF6, 0xFE, 0xC7, 0xC3, 0xC9, // 81-88 - 0x76 // 89 + 0x76, 0xCB // 89 }; unsigned char gShift[20] = { 0, @@ -74,6 +107,9 @@ unsigned char gShift[20] = { 0, 4, 4, 4 }; +const char* types[5] = { "", "a label", "an equate", "a set", "an extern" }; + + void cb_assembler(class Fl_Widget* w, void*) { VTAssembler* pAsm = new VTAssembler; @@ -92,12 +128,28 @@ VTAssembler::VTAssembler() m_IncludeDepth = 0; m_FileIndex = -1; m_DebugInfo = 0; - - m_ActiveMod = new CModule; - - m_Symbols = m_ActiveMod->m_Symbols[ASEG]; - m_Instructions = m_ActiveMod->m_Instructions[ASEG]; - m_ActiveAddr = m_ActiveMod->m_ActiveAddr[ASEG]; + m_LastLabelLine = -1; + m_LastIfElseLine = -1; + m_LastIfElseIsIf = 0; + m_MsbFirst = FALSE; + m_LocalModuleChar = '_'; + m_ActiveSeg = ASEG; + + // Create a new symbol module + m_ActiveMod = new CModule("basemod"); + m_Modules["basemod"] = m_ActiveMod; + + // Create a segment to assemble into and a seglines line tracker + m_ActiveSeg = new CSegment(".aseg", ASEG, m_ActiveMod); + m_Segments[".aseg"] = m_ActiveSeg; + m_ActiveSegLines = new CSegLines(m_ActiveSeg, 1); + m_SegLines.Add(m_ActiveSegLines); + + // Assign the active pointers for module and segment + m_Symbols = m_ActiveMod->m_Symbols; + m_Instructions = m_ActiveSeg->m_Instructions; + m_ActiveAddr = m_ActiveSeg->m_ActiveAddr; + m_pStdoutFunc = NULL; // Initialize IF stack m_IfDepth = 0; @@ -109,57 +161,54 @@ VTAssembler::~VTAssembler() ResetContent(); delete m_ActiveMod; + delete m_ActiveSeg; + delete m_ActiveSegLines; +} + +void VTAssembler::SetStdoutFunction(void *pContext, stdOutFunc_t pFunc) +{ + m_pStdoutFunc = pFunc; + m_pStdoutContext = pContext; } void VTAssembler::ResetContent(void) { - MString key; - POSITION pos; - int c, count, seg; + MString key, modName; + POSITION modPos; + int c, count; + CModule* pMod; + CSegment* pSeg; + CSegLines* pSegLines; + CSymbol* pSym; - // Loop through each segment - for (seg = 0; seg < 3; seg++) + // Loop through each module and delete them + modPos = m_Modules.GetStartPosition(); + while (modPos != NULL) { - // Delete all symbols - pos = m_ActiveMod->m_Symbols[seg]->GetStartPosition(); - while (pos != NULL) - { - CSymbol* pSymbol; - m_ActiveMod->m_Symbols[seg]->GetNextAssoc(pos, key, (VTObject*&) pSymbol); - delete pSymbol; - } - m_ActiveMod->m_Symbols[seg]->RemoveAll(); - - // Delete all Instrucitons - count = m_ActiveMod->m_Instructions[seg]->GetSize(); - for (c = count - 1; c >= 0; c--) - { - CInstruction* pInst = (CInstruction*) (*m_ActiveMod->m_Instructions[seg])[c]; - delete pInst; - } - m_ActiveMod->m_Instructions[seg]->RemoveAll(); - - // Delete all Relocation objects - count = m_Reloc[seg].GetSize(); - for (c = 0; c < count; c++) - { - CRelocation* pReloc = (CRelocation *) m_Reloc[seg][c]; - delete pReloc; - } - m_Reloc[seg].RemoveAll(); - - // Remove all items from Publics array. The actual items are duplicates - // and will be deleted elsewhere - m_Publics[seg].RemoveAll(); - - // Delete the CModule and create a new one - delete m_ActiveMod; - m_ActiveMod = new CModule; - m_Symbols = m_ActiveMod->m_Symbols[ASEG]; - m_Instructions = m_ActiveMod->m_Instructions[ASEG]; - m_ActiveAddr = m_ActiveMod->m_ActiveAddr[ASEG]; + // Get the next module + m_Modules.GetNextAssoc(modPos, modName, (VTObject *&) pMod); + delete pMod; } + m_Modules.RemoveAll(); + // Loop through each segment + modPos = m_Segments.GetStartPosition(); + while (modPos != NULL) + { + // Get the next module + m_Segments.GetNextAssoc(modPos, modName, (VTObject *&) pSeg); + delete pSeg; + } + m_Segments.RemoveAll(); + + // Delete all module line objects + count = m_SegLines.GetSize(); + for (c = 0; c < count; c++) + { + pSegLines = (CSegLines *) m_SegLines[c]; + delete pSegLines; + } + m_SegLines.RemoveAll(); // Delete all Extern reference object count = m_Externs.GetSize(); @@ -170,16 +219,50 @@ void VTAssembler::ResetContent(void) } m_Externs.RemoveAll(); + // Delete all #defines + count = m_Defines.GetSize(); + for (c = 0; c < count; c++) + { + CMacro* pMacro = (CMacro *) m_Defines[c]; + delete pMacro; + } + m_Defines.RemoveAll(); + // Delete all undefined symbols m_UndefSymbols.RemoveAll(); // Delete all errors m_Errors.RemoveAll(); + m_IncludeDirs.RemoveAll(); // Delete filenames parsed m_Filenames.RemoveAll(); m_FileIndex = -1; + // Create a new basemod + m_ActiveMod = new CModule("basemod"); + m_Modules["basemod"] = m_ActiveMod; + + // Create a new segment to assmeble into + m_ActiveSeg = new CSegment(".aseg", ASEG, m_ActiveMod); + m_Segments[".aseg"] = m_ActiveSeg; + + // Assign active assembly pointers + m_Symbols = m_ActiveMod->m_Symbols; + m_Instructions = m_ActiveSeg->m_Instructions; + m_ActiveAddr = m_ActiveSeg->m_ActiveAddr; + + // Add the "VTASM" symbol + pSym = new CSymbol(); + pSym->m_Name = "VTASM"; + pSym->m_Value = 1; + pSym->m_SymType = SYM_EQUATE | SYM_HASVALUE; + (*m_Symbols)[(const char *) pSym->m_Name] = pSym; + + // Create a new SegLines object + m_ActiveSegLines = new CSegLines(m_ActiveSeg, 1); + m_SegLines.Add(m_ActiveSegLines); + m_Hex = 0; m_List = 0; m_Address = 0; @@ -238,7 +321,7 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, int stk = 0; int int_value; const char* pStr; - int c, seg, local; + int c, local; VTObject* dummy; // Get count of number of operations in equation and initalize stack @@ -259,22 +342,36 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, local = 0; if (temp.GetLength() > 1) { - if ((temp[0] == '$') && (temp[1] != 0)) + // Check if label is local to the last label only + if (temp[0] == '&') { + // Prepend the last label to make this a local symbol temp = m_LastLabel + (char *) "%%" + op.m_Variable; local = 1; } + else if (temp[0] == m_LocalModuleChar) + { + // Prepend the last label to make this a local symbol + temp = m_ActiveMod->m_Name + (char *) "%%" + op.m_Variable; + local = 1; + } } + + // Lookup symbol in active module pStr = (const char *) temp; - symbol = (CSymbol *) 0; - for (seg = 0; seg < 3; seg++) + if (!m_ActiveMod->m_Symbols->Lookup(pStr, (VTObject *&) symbol)) + symbol = NULL; + + // If symbol not found, look in other modules if not module local + if ((symbol == NULL) && !local) { - if (m_ActiveMod->m_Symbols[seg]->Lookup(pStr, (VTObject *&) symbol)) - break; + symbol = LookupSymOtherModules(op.m_Variable); } - if (symbol != (CSymbol*) 0) + + // If symbol was found, try to evaluate it + if (symbol != (CSymbol*) NULL) { - // If symbol has no vaule, try to get it + // If symbol has no value, try to get it if ((symbol->m_SymType & SYM_HASVALUE) == 0) { if ((symbol->m_SymType & 0xFF) == SYM_EXTERN) @@ -314,8 +411,10 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, if (!m_UndefSymbols.Lookup(op.m_Variable, dummy)) { if (local) + { errMsg.Format("Error in line %d(%s): Local symbol %s undefined", m_Line, (const char *) m_Filenames[m_FileIndex], (const char *) op.m_Variable); + } else { // Check if AuotExtern is enabled @@ -341,6 +440,10 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, } break; + case RPN_MACRO: + // Need to add code here to process macros + break; + case RPN_MULTIPLY: s2 = stack[--stk]; s1 = stack[--stk]; @@ -355,7 +458,8 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, // Divide by zero error if (reportError) { - errMsg.Format("Error in line %d(%s): Divide by zero!", m_Line, (const char *) m_Filenames[m_FileIndex]); + errMsg.Format("Error in line %d(%s): Divide by zero!", + m_Line, (const char *) m_Filenames[m_FileIndex]); m_Errors.Add(errMsg); } return 0; @@ -399,6 +503,11 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, stack[stk++] = (double) ((int) s2 & (int) s1); break; + case RPN_NEGATE: + s1 = stack[--stk]; + stack[stk++] = -s1; + break; + case RPN_BITXOR: s2 = stack[--stk]; s1 = stack[--stk]; @@ -442,6 +551,16 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, stack[stk++] = log(s1); break; + case RPN_HIGH: + s1 = stack[--stk]; + stack[stk++] = ((unsigned int) s1 >> 8) & 0xFF; + break; + + case RPN_LOW: + s1 = stack[--stk]; + stack[stk++] = (unsigned int) s1 & 0xFF; + break; + case RPN_LOG: s1 = stack[--stk]; stack[stk++] = log10(s1); @@ -451,6 +570,27 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, s1 = stack[--stk]; stack[stk++] = sqrt(s1); break; + + case RPN_DEFINED: + if (LookupSymbol(op.m_Variable, symbol)) + stack[stk++] = 1.0; + else + stack[stk++] = 0.0; + break; + + case RPN_NOT: + s1 = stack[--stk]; + if (s1 == 0.0) + stack[stk++] = 1.0; + else + stack[stk++] = 0.0; + break; + + case RPN_BITNOT: + s1 = stack[--stk]; + stack[stk++] = (double) (~((int) s1)); + break; + } } @@ -460,6 +600,12 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, return 1; } +/* +============================================================================ +Returns the value of the given string. If the value is numeric, it converts +it to an integer, otherwise it searches the symbol tables for the value. +============================================================================ +*/ int VTAssembler::GetValue(MString & string, int & value) { int c, len; @@ -487,31 +633,34 @@ int VTAssembler::GetValue(MString & string, int & value) // For each segment for each module CSymbol* pSymbol = NULL; MString myStr = string; - if ((string[0] == '$') && (string[1] != 0)) + if ((string[0] == '%') && (string[1] != 0)) { myStr = m_LastLabel + (char *) "%%" + string; } - for (c = 0; c < 3; c++) + + // Lookup the symbol in all modules + if (!m_ActiveMod->m_Symbols->Lookup(myStr, (VTObject*&) pSymbol)) + pSymbol = LookupSymOtherModules(myStr); + + // If symbol was found, evaluate it + if (pSymbol != NULL) { - if (m_ActiveMod->m_Symbols[c]->Lookup(myStr, (VTObject*&) pSymbol)) + // Check if symbol has been evaluated yet + if (pSymbol->m_SymType & SYM_HASVALUE) { - // Check if symbol has been evaluated yet - if (pSymbol->m_SymType & SYM_HASVALUE) - { - value = pSymbol->m_Value; - return 1; - } + value = pSymbol->m_Value; + return 1; + } - // Evaluate the equation and save the value if any. Report errors. - if (pSymbol->m_Equation != NULL) + // Evaluate the equation and save the value if any. Report errors. + if (pSymbol->m_Equation != NULL) + { + if (Evaluate(pSymbol->m_Equation, &dValue, 0)) { - if (Evaluate(pSymbol->m_Equation, &dValue, 0)) - { - value = (int) dValue; - pSymbol->m_Value = (long) dValue; - pSymbol->m_SymType |= SYM_HASVALUE; - return 1; - } + value = (int) dValue; + pSymbol->m_Value = (long) dValue; + pSymbol->m_SymType |= SYM_HASVALUE; + return 1; } } } @@ -521,29 +670,45 @@ int VTAssembler::GetValue(MString & string, int & value) /* =========================================================================================== -Function to process zero argument opcodes +Add a new instruction to the instruction array with the specified opcode and default +settings for line number, file index, etc. =========================================================================================== */ -void VTAssembler::opcode_arg_0(int opcode) +CInstruction* VTAssembler::AddInstruction(int opcode) { - // Determine if conditional assembly enabled - if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) - return; + CInstruction *pInst; // Update line number m_Line = (PCB).line; - - // Read operand (register) from string accumulator - CInstruction* pInst = new CInstruction; + + /* Create a new instruction object */ + pInst = new CInstruction; if (pInst != NULL) { pInst->m_ID = opcode; // Set opcode value pInst->m_Line = m_Line; // Get Line number - pInst->m_Address = m_Address++; // Get current program address + pInst->m_Address = m_ActiveSeg->m_Address++;// Get current program address m_ActiveAddr->length++; // Update add range length pInst->m_FileIndex = m_FileIndex; // Save index of the current file m_Instructions->Add(pInst); // Save instruction } + + return pInst; +} + +/* +=========================================================================================== +Function to process zero argument opcodes +=========================================================================================== +*/ +void VTAssembler::opcode_arg_0(int opcode) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + + // Read operand (register) from string accumulator + AddInstruction(opcode); } /* @@ -560,21 +725,13 @@ void VTAssembler::opcode_arg_1reg(int opcode) return; } - // Update line number - m_Line = (PCB).line; - // Read operand (register) from register stack - CInstruction* pInst = new CInstruction; + CInstruction* pInst = AddInstruction(opcode); if (pInst != NULL) { - pInst->m_ID = opcode; // Set opcode value + // Append instruction with operand pInst->m_Operand1 = new MString; // Allocte operand object pInst->m_Operand1->Format("%c", reg[--reg_cnt]); // Get register operand - pInst->m_Line = m_Line; // Get Line number - pInst->m_Address = m_Address++; // Get current program address - m_ActiveAddr->length++; // Update add range length - pInst->m_FileIndex = m_FileIndex; // Save index of the current file - m_Instructions->Add(pInst); // Save instruction } } @@ -589,21 +746,13 @@ void VTAssembler::opcode_arg_imm(int opcode, char c) if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) return; - // Update line number - m_Line = (PCB).line; - // Read operand (register) from register stack - CInstruction* pInst = new CInstruction; + CInstruction* pInst = AddInstruction(opcode); if (pInst != NULL) { - pInst->m_ID = opcode; // Set opcode value + // Append instruction with operand pInst->m_Operand1 = new MString; // Allocte operand object pInst->m_Operand1->Format("%c", c); // Get register operand - pInst->m_Line = m_Line; // Get Line number - pInst->m_Address = m_Address++; // Get current program address - m_ActiveAddr->length++; // Update add range length - pInst->m_FileIndex = m_FileIndex; // Save index of the current file - m_Instructions->Add(pInst); // Save instruction } } @@ -621,22 +770,14 @@ void VTAssembler::opcode_arg_2reg(int opcode) return; } - // Update line number - m_Line = (PCB).line; - // Read operands (2 registers) from Register stack - CInstruction* pInst = new CInstruction; + CInstruction* pInst = AddInstruction(opcode); if (pInst != NULL) { - pInst->m_ID = opcode; // Set opcode value + // Append instruction with operands pInst->m_Group = (VTObject *) (int) reg[--reg_cnt]; // Get register operand pInst->m_Operand1 = new MString; // Allocte operand object pInst->m_Operand1->Format("%c", reg[--reg_cnt]); // Get register operand - pInst->m_Line = m_Line; // Get Line number - pInst->m_Address = m_Address++; // Get current program address - m_ActiveAddr->length++; // Update add range length - pInst->m_FileIndex = m_FileIndex; // Save index of the current file - m_Instructions->Add(pInst); // Save instruction } } @@ -657,28 +798,56 @@ void VTAssembler::opcode_arg_1reg_equ8(int opcode) return; } - // Update line number - m_Line = (PCB).line; - // Read operands (register & equation) from parser - CInstruction* pInst = new CInstruction; + CInstruction* pInst = AddInstruction(opcode); if (pInst != NULL) { - pInst->m_ID = opcode; // Set opcode value + // Append instruction with operands pInst->m_Operand1 = new MString; // Allocte operand object pInst->m_Operand1->Format("%c", reg[--reg_cnt]); // Get register operand pInst->m_Group = gEq; // Get equation - pInst->m_Line = m_Line; // Get Line number - pInst->m_Address = m_Address++; // Get current program address - pInst->m_FileIndex = m_FileIndex; // Save index of the current file // Allocate new equation for the parser gEq = new CRpnEquation; // Increment Address again to account for 8-bit value - m_Address++; + m_ActiveSeg->m_Address++; m_ActiveAddr->length += 2; // Update add range length - m_Instructions->Add(pInst); // Save instruction + } +} + +/* +=========================================================================================== +Function to process opcodes that take a single register argument and an equation that +results in an 16-bit value +=========================================================================================== +*/ +void VTAssembler::opcode_arg_1reg_equ16(int opcode) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + reg_cnt--; // Pop unused reg operand from stack + delete gEq; // Delete the unused equaiton + gEq = new CRpnEquation; // Allocate new equation for parser + return; + } + + // Read operands (register & equation) from parser + CInstruction* pInst = AddInstruction(opcode); + if (pInst != NULL) + { + // Append instruction with operands + pInst->m_Operand1 = new MString; // Allocte operand object + pInst->m_Operand1->Format("%c", reg[--reg_cnt]); // Get register operand + pInst->m_Group = gEq; // Get equation + + // Allocate new equation for the parser + gEq = new CRpnEquation; + + // Add 2 to address to account for 16-bit argument + m_ActiveSeg->m_Address += 2; + m_ActiveAddr->length += 3; // Update add range length } } @@ -697,26 +866,20 @@ void VTAssembler::opcode_arg_equ8(int opcode) return; } - // Update line number - m_Line = (PCB).line; - // Read operand (equation) from parser - CInstruction* pInst = new CInstruction; + CInstruction* pInst = AddInstruction(opcode); if (pInst != NULL) { - pInst->m_ID = opcode; // Set opcode value + // Append instruction with operands pInst->m_Group = gEq; // Get equation pInst->m_Line = m_Line; // Get Line number - pInst->m_Address = m_Address++; // Get current program address - pInst->m_FileIndex = m_FileIndex; // Save index of the current file // Allocate new equation for the parser gEq = new CRpnEquation; // Increment Address again to account for 8-bit value - m_Address++; + m_ActiveSeg->m_Address++; m_ActiveAddr->length += 2; // Update add range length - m_Instructions->Add(pInst); // Save instruction } } @@ -735,26 +898,19 @@ void VTAssembler::opcode_arg_equ16(int opcode) return; } - // Update line number - m_Line = (PCB).line; - // Read operand (register) from string accumulator - CInstruction* pInst = new CInstruction; + CInstruction* pInst = AddInstruction(opcode); if (pInst != NULL) { - pInst->m_ID = opcode; // Set opcode value + // Append instruction with operand pInst->m_Group = gEq; // Get equation - pInst->m_Line = m_Line; // Get Line number - pInst->m_Address = m_Address++; // Get current program address - pInst->m_FileIndex = m_FileIndex; // Save index of the current file // Allocate new equation for the parser gEq = new CRpnEquation; // Increment Address to account for 16-bit value - m_Address += 2; + m_ActiveSeg->m_Address += 2; m_ActiveAddr->length += 3; // Update add range length - m_Instructions->Add(pInst); // Save instruction } } @@ -774,11 +930,18 @@ void VTAssembler::include(const char *filename) return; // Update line number - m_Line = (PCB).line; + m_Line = (PCB).line - 1; // Try to open the file fd = fopen(filename, "rb"); + // If file not open, try to append the current asm file path and open + if (fd == 0) + { + incPathFile = m_FileDir + filename; + fd = fopen((const char *) incPathFile, "rb"); + } + // If file did not open, then look in include directories if (fd == 0) { @@ -801,6 +964,9 @@ void VTAssembler::include(const char *filename) m_Errors.Add(errMsg); return; } else { + /* Save the parser control block for the current file */ + memcpy(&m_ParserPCBs[m_IncludeDepth], &a85parse_pcb, + sizeof(a85parse_pcb_type)); m_IncludeIndex[m_IncludeDepth] = m_FileIndex; m_IncludeStack[m_IncludeDepth++] = m_fd; @@ -811,17 +977,19 @@ void VTAssembler::include(const char *filename) // Now loading from a different FD! m_fd = fd; + gFilename = filename; a85parse(); fclose(m_fd); // Restore the previous FD m_fd = m_IncludeStack[--m_IncludeDepth]; m_FileIndex = m_IncludeIndex[m_IncludeDepth]; + gFilename = (const char *) m_Filenames[m_FileIndex]; + memcpy(&a85parse_pcb, &m_ParserPCBs[m_IncludeDepth], + sizeof(a85parse_pcb_type)); } } -const char* types[5] = { "", "a label", "an equate", "a set", "an extern" }; - /* ============================================================================ This function is called when the parser detects an equate operation. @@ -831,7 +999,6 @@ void VTAssembler::equate(const char *name) { double value; VTObject* dummy; - int c; CSymbol* pSymbol; // Determine if conditional assembly enabled @@ -843,7 +1010,7 @@ void VTAssembler::equate(const char *name) } // Update line number - m_Line = (PCB).line; + m_Line = (PCB).line - 1; // Check if converting label to equate if (name == (const char *) -1) @@ -882,23 +1049,32 @@ void VTAssembler::equate(const char *name) // Loop through all segments for the ative module and check if symbol exists if (name != (const char *) -1) { - for (c = 0; c < 3; c++) + if (name[0] == '&') + pSymbol->m_Name = m_LastLabel + (char *) "%%" + pSymbol->m_Name; + else if (name[0] == m_LocalModuleChar) + pSymbol->m_Name = m_ActiveMod->m_Name + (char *) "%%" + pSymbol->m_Name; + + // Look in active module for the symbol + if (!m_Symbols->Lookup(pSymbol->m_Name, dummy)) { - if (m_ActiveMod->m_Symbols[c]->Lookup(pSymbol->m_Name, dummy)) - { - MString string; - string.Format("Error in line %d(%s): Symbol %s already defined as %s", - pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex], - (const char *) pSymbol->m_Name, - types[((CSymbol *)dummy)->m_SymType & 0x00FF]); - m_Errors.Add(string); + // Not found. If symbol isn't a local label, look in other modules + if ((name[0] != '&') && (name[0] != m_LocalModuleChar)) + dummy = LookupSymOtherModules(pSymbol->m_Name); + } - // Cleanup - delete pSymbol->m_Equation; - delete pSymbol; + // If symbol exists, report error + if (dummy != NULL) + { + MString string; + string.Format("Error in line %d(%s): Symbol %s already defined as %s", + pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex], + (const char *) pSymbol->m_Name, + types[((CSymbol *)dummy)->m_SymType & 0x00FF]); + m_Errors.Add(string); - return; - } + // Cleanup + delete pSymbol; + return; } // Assign symbol to active segment @@ -912,11 +1088,10 @@ void VTAssembler::equate(const char *name) This function is called when the parser detects a label. ============================================================================ */ -void VTAssembler::label(const char *label) +void VTAssembler::label(const char *label, int address) { - VTObject* dummy; + VTObject* dummy = NULL; MString string; - int c; int local; // Determine if conditional assembly enabled @@ -925,9 +1100,10 @@ void VTAssembler::label(const char *label) // Update line number m_Line = (PCB).line; + m_LastLabelLine = m_Line; // Determine is label is local (has format $###) - if (label[0] == '$') + if (label[0] == '&') local = 1; else local = 0; @@ -937,58 +1113,70 @@ void VTAssembler::label(const char *label) { if (local) pSymbol->m_Name = m_LastLabel + (char *) "%%" + label; + else if (label[0] == m_LocalModuleChar) + pSymbol->m_Name = m_ActiveMod->m_Name + (char *) "%%" + label; else pSymbol->m_Name = label; pSymbol->m_Line = m_Line; - pSymbol->m_Value = m_Address; + if (address == -1) + pSymbol->m_Value = m_ActiveSeg->m_Address; + else + pSymbol->m_Value = address; pSymbol->m_FileIndex = m_FileIndex; // Save index of the current file pSymbol->m_SymType = SYM_LABEL | SYM_HASVALUE; pSymbol->m_pRange = m_ActiveAddr; + if (m_ActiveSeg->m_Type == CSEG) + pSymbol->m_SymType |= SYM_CSEG; + else if (m_ActiveSeg->m_Type == DSEG) + pSymbol->m_SymType |= SYM_DSEG; // Check if label exists in the symbol table for this module - for (c = 0; c < 3; c++) + if (!m_ActiveMod->m_Symbols->Lookup(pSymbol->m_Name, dummy)) { - if (m_ActiveMod->m_Symbols[c]->Lookup(pSymbol->m_Name, dummy)) - { - string.Format("Error in line %d(%s): Label %s already defined as %s", - pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex], - (const char *) pSymbol->m_Name, - types[((CSymbol *)dummy)->m_SymType & 0x00FF]); - m_Errors.Add(string); + if (!local && (label[0] != m_LocalModuleChar)) + dummy = LookupSymOtherModules(pSymbol->m_Name); + } - // Cleanup - delete pSymbol; + // If Symbol already exists, report an error + if (dummy != NULL) + { + string.Format("Error in line %d(%s): Label %s already defined as %s", + pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex], + (const char *) pSymbol->m_Name, + types[((CSymbol *)dummy)->m_SymType & 0x00FF]); + m_Errors.Add(string); - return; - } + // Cleanup + delete pSymbol; + return; } - - const char *pStr = (const char *) pSymbol->m_Name; + // Assign symbol to active segment + const char *pStr = (const char *) pSymbol->m_Name; (*m_Symbols)[pStr] = pSymbol; if (!local) { m_LastLabel = pStr; m_LastLabelSym= pSymbol; - m_LastLabelAdded = 0; - } - else if (m_LastLabelAdded == 0) - { CInstruction* pInst = new CInstruction; pInst->m_ID = INST_LABEL; pInst->m_Operand1 = new MString; *pInst->m_Operand1 = m_LastLabel; - m_LastLabelAdded = 1; m_Instructions->Add(pInst); // Save instruction } } } +/* +============================================================================ +This function is called when a set directive is encountered +============================================================================ +*/ void VTAssembler::directive_set(const char *name) { double value; VTObject* dummy; - int c, symtype; + int symtype; CSymbol* pSymbol; // Determine if conditional assembly enabled @@ -1000,7 +1188,7 @@ void VTAssembler::directive_set(const char *name) } // Update line number - m_Line = (PCB).line; + m_Line = (PCB).line - 1; // Check if converting label to set if (name == (const char *) -1) @@ -1036,54 +1224,65 @@ void VTAssembler::directive_set(const char *name) pSymbol->m_Equation = gEq; gEq = new CRpnEquation; - // Loop through all segments for the ative module and check if symbol exists + // Search all modules to see if the symbol exists if (name != (const char *) -1) { - for (c = 0; c < 3; c++) + // Convert local symbol names + if (name[0] == '&') + pSymbol->m_Name = m_LastLabel + (char *) "%%" + pSymbol->m_Name; + else if (name[0] == m_LocalModuleChar) + pSymbol->m_Name = m_ActiveMod->m_Name + (char *) "%%" + pSymbol->m_Name; + + // Look in active module for the symbol + if (!m_Symbols->Lookup(pSymbol->m_Name, dummy)) { - if (m_ActiveMod->m_Symbols[c]->Lookup(pSymbol->m_Name, dummy)) - { - symtype = ((CSymbol*) dummy)->m_SymType & 0x00FF; + // Not found. If symbol isn't a local label, look in other modules + if ((name[0] != '&') && (name[0] != m_LocalModuleChar)) + dummy = LookupSymOtherModules(pSymbol->m_Name); + } - // Now insure symbol esists as a SYM_SET object - if (symtype == SYM_SET) + if (dummy != NULL) + { + symtype = ((CSymbol*) dummy)->m_SymType & 0x00FF; + + // Now insure symbol exists as a SYM_SET object + if (symtype == SYM_SET) + { + // Update value of existing symbol object + if (pSymbol->m_SymType & SYM_HASVALUE) { - // Update value of existing symbol object - if (pSymbol->m_SymType & SYM_HASVALUE) - { - ((CSymbol *) dummy)->m_Value = pSymbol->m_Value; - ((CSymbol *) dummy)->m_SymType |= SYM_HASVALUE; - } - else - ((CSymbol *) dummy)->m_SymType &= ~SYM_HASVALUE; - - // Save equation from the new symbol - ((CSymbol *) dummy)->m_Equation = pSymbol->m_Equation; - - // Delete the newly created CSymbol object - delete pSymbol->m_Equation; - delete pSymbol; - return; + ((CSymbol *) dummy)->m_Value = pSymbol->m_Value; + ((CSymbol *) dummy)->m_SymType |= SYM_HASVALUE; } else - { - MString string; - string.Format("Error in line %d(%s): Symbol %s already defined as %s", - pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex], - (const char *) pSymbol->m_Name, types[symtype]); - m_Errors.Add(string); + ((CSymbol *) dummy)->m_SymType &= ~SYM_HASVALUE; - // Delete the newly created CSymbol object - delete pSymbol->m_Equation; - delete pSymbol; + // Save equation from the new symbol + ((CSymbol *) dummy)->m_Equation = pSymbol->m_Equation; - return; - } + // Delete the newly created CSymbol object + delete pSymbol->m_Equation; + delete pSymbol; + return; + } + else + { + MString string; + string.Format("Error in line %d(%s): Symbol %s already defined as %s", + pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex], + (const char *) pSymbol->m_Name, types[symtype]); + m_Errors.Add(string); + + // Delete the newly created CSymbol object + delete pSymbol->m_Equation; + delete pSymbol; + + return; } } - const char *pStr = (const char *) pSymbol->m_Name; // Assign symbol to active segment + const char *pStr = (const char *) pSymbol->m_Name; (*m_Symbols)[pStr] = pSymbol; } } @@ -1123,43 +1322,57 @@ void VTAssembler::directive_org() // Try to calculate new address if (Evaluate(gEq, &value, 0)) { - m_Address = (unsigned short) value; + m_ActiveSeg->m_Address = (unsigned short) value; + pInst->m_Address = m_ActiveSeg->m_Address; + if (m_ActiveAddr->length != 0) { // Allocate a new AddrRange object for this ORG newRange = new AddrRange; - newRange->address = m_Address; + newRange->address = m_ActiveSeg->m_Address; newRange->length = 0; // Find location to insert this object - thisRange = m_ActiveMod->m_UsedAddr[m_ActiveMod->m_ActiveSeg]; + thisRange = m_ActiveSeg->m_UsedAddr; prevRange = 0; - while ((thisRange != 0) && (thisRange->address < m_Address)) + while ((thisRange != 0) && (thisRange->address < m_ActiveSeg->m_Address)) { prevRange = thisRange; thisRange = thisRange->pNext; } - // Insert new range in list - if (prevRange->address + prevRange->length == m_Address) + // Hmmm... we have a region being inserted before the first + // region. This may be possible if the ORG statements are out of order + // Make this range the first in the list + if (prevRange == NULL) { - delete newRange; - m_ActiveMod->m_ActiveAddr[m_ActiveMod->m_ActiveSeg] = prevRange; - m_ActiveAddr = prevRange; + newRange->pNext = m_ActiveSeg->m_UsedAddr; + m_ActiveSeg->m_UsedAddr = newRange; + m_ActiveSeg->m_ActiveAddr = newRange; } else { - newRange->pNext = 0; - prevRange->pNext = newRange; + // Insert new range in list + if (prevRange->address + prevRange->length == m_ActiveSeg->m_Address) + { + delete newRange; + m_ActiveSeg->m_ActiveAddr = prevRange; + m_ActiveAddr = prevRange; + } + else + { + newRange->pNext = 0; + prevRange->pNext = newRange; - m_ActiveMod->m_ActiveAddr[m_ActiveMod->m_ActiveSeg] = newRange; - m_ActiveAddr = newRange; + m_ActiveSeg->m_ActiveAddr = newRange; + m_ActiveAddr = newRange; + } } } else { - m_ActiveAddr->address = m_Address; + m_ActiveAddr->address = m_ActiveSeg->m_Address; } } @@ -1171,32 +1384,225 @@ void VTAssembler::directive_org() } } -void VTAssembler::preproc_ifdef(const char* name) +/* +============================================================================ +This function is called when an echo string directive is encountered +============================================================================ +*/ +void VTAssembler::directive_echo(const char *string) { + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + + if (m_pStdoutFunc != NULL) + m_pStdoutFunc(m_pStdoutContext, string); } -void VTAssembler::preproc_ifndef(const char* name) +/* +============================================================================ +This function is called when a printf directive is encountered +============================================================================ +*/ +void VTAssembler::directive_printf(const char *string) { + char str[256]; + double value = 0.0; + long lval; + const char *ptr; + char fmtCh = 0; + int fmtDigits = 0; + + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + delete gEq; // Delete the unused equaiton + gEq = new CRpnEquation; // Allocate new equation for parser + return; + } + + // Find the locaiton of the format specifier + ptr = string; + while ((*ptr != '%') && (*ptr != '\0')) + ptr++; + if (*ptr == '%') + { + while (VT_ISDIGIT(*(ptr + 1 + fmtDigits))) + fmtDigits++; + fmtCh = *(ptr + 1 + fmtDigits); + } + + // Try to evaluate the equation. Note that we may not be able to + // successfully evaluate it at this point because it may contain + // a forward reference, so don't report any errors yet. + if (Evaluate(gEq, &value, 0)) + { + if (fmtCh == 'f') + sprintf(str, string, value); + else + { + lval = (int) value; + sprintf(str, string, lval); + } + } + else + { + strncpy(str, string, (int) (ptr - string)); + strcat(str, "#UNDEFINED"); + if (*ptr != '\0') + strcat(str, ptr + 2 + fmtDigits); + } + + if (m_pStdoutFunc != NULL) + m_pStdoutFunc(m_pStdoutContext, (const char *) str); } -void VTAssembler::preproc_else() +/* +============================================================================ +This function is called when an echo equation directive is encountered +============================================================================ +*/ +void VTAssembler::directive_echo() { + double value, value2; + long lval; + char str[20]; + + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + delete gEq; // Delete the unused equaiton + gEq = new CRpnEquation; // Allocate new equation for parser + return; + } + + // Try to evaluate the equation. Note that we may not be able to + // successfully evaluate it at this point because it may contain + // a forward reference, so don't report any errors yet. + if (Evaluate(gEq, &value, 0)) + { + // Check if value is integer or float + lval = (long) value; + value2 = lval; + if (value != value2) + sprintf(str, "%f", value2); + else + { + sprintf(str, "%ld", lval); + } + if (m_pStdoutFunc != NULL) + m_pStdoutFunc(m_pStdoutContext, (const char *) str); + } + else + { + if (m_pStdoutFunc != NULL) + m_pStdoutFunc(m_pStdoutContext, "#UNDEFINED"); + } + + delete gEq; // Delete the unused equaiton + gEq = new CRpnEquation; // Allocate new equation for parser } -void VTAssembler::preproc_endif() +/* +============================================================================ +This function searches for the specified #define +============================================================================ +*/ +int VTAssembler::LookupMacro(MString& name, CMacro *¯o) { + int count, c; + CMacro* pMacro; + + count = m_Defines.GetSize(); + for (c = 0; c < count; c++) + { + pMacro = (CMacro *) m_Defines[c]; + + // Check if this + if (pMacro->m_Name == gMacro->m_Name) + { + // We found a match on the macro name + macro = pMacro; + return TRUE; + } + } + + macro = NULL; + return FALSE; } -void VTAssembler::preproc_define(const char *name) +/* +============================================================================ +This function searches for the specified symbol in the active module +============================================================================ +*/ +int VTAssembler::LookupSymbol(MString& name, CSymbol *&symbol) { + + // Test if the specified label / define exists + if (m_ActiveMod->m_Symbols->Lookup(name, (VTObject*&) symbol)) + return TRUE; + + // Symbol not found in active module. Check other modules + if (name.GetLength() > 1) + { + if ((name[0] != '&') && (name[0] != m_LocalModuleChar)) + { + if ((symbol = LookupSymOtherModules(name)) != NULL) + return TRUE; + } + } + + symbol = NULL; + return FALSE; } -void VTAssembler::preproc_undef(const char *name) +/* +============================================================================ +This function searches for the specified symbol in the active module +============================================================================ +*/ +CSymbol * VTAssembler::LookupSymOtherModules(MString& name, CSegment** pSeg) { + CSymbol *pSymbol; + CModule *pMod; + POSITION pos; + MString key; + + pos = m_Modules.GetStartPosition(); + + // Scan all modules that have been created + while (pos != NULL) + { + // Get pointer to next module + m_Modules.GetNextAssoc(pos, key, (VTObject *&) pMod); + if (pMod == m_ActiveMod) + { + // Don't search the active module + continue; + } + + // Test if the specified label / define exists + if (pMod->m_Symbols->Lookup(name, (VTObject*&) pSymbol)) + { + if (pSeg != NULL) + *pSeg = pSymbol->m_Segment; + return pSymbol; + } + } + + return NULL; } +/* +============================================================================ +This function is called when an ASEG directive is found by the parser +============================================================================ +*/ void VTAssembler::directive_aseg() { + CSegment* pSeg; + // Determine if conditional assembly enabled if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) return; @@ -1204,71 +1610,110 @@ void VTAssembler::directive_aseg() // Update line number m_Line = (PCB).line; - // Save current address in current module - m_ActiveMod->m_Address[m_ActiveMod->m_ActiveSeg] = m_Address; - // Set segment of current module - m_ActiveMod->m_ActiveSeg = ASEG; + m_Segments.Lookup(".aseg", (VTObject *&) pSeg); +// pSeg = (CSegment *) m_Segments[".aseg"]; - // Update pointers to assembly objects - m_Instructions = m_ActiveMod->m_Instructions[ASEG]; - m_Symbols = m_ActiveMod->m_Symbols[ASEG]; - m_ActiveAddr = m_ActiveMod->m_ActiveAddr[ASEG]; - - // Update address location - m_Address = (unsigned short) m_ActiveMod->m_Address[ASEG]; + // Activate the new segment + ActivateSegment(pSeg); } -void VTAssembler::directive_cseg(int page) +/* +============================================================================ +This function sets the specified Segment as Active. +============================================================================ +*/ +void VTAssembler::ActivateSegment(CSegment* pSeg) { - // Determine if conditional assembly enabled - if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + // Check if we were already in the ASEG + if (pSeg == m_ActiveSeg) return; - // Update line number - m_Line = (PCB).line; - - // Save current address in current module - m_ActiveMod->m_Address[m_ActiveMod->m_ActiveSeg] = m_Address; - - // Set segment of current module - m_ActiveMod->m_ActiveSeg = CSEG; + // Update the active segment to assemble into + m_ActiveSeg = pSeg; // Update pointers to assembly objects - m_Instructions = m_ActiveMod->m_Instructions[CSEG]; - m_Symbols = m_ActiveMod->m_Symbols[CSEG]; - m_ActiveMod->m_Page[CSEG] = page; - m_ActiveAddr = m_ActiveMod->m_ActiveAddr[CSEG]; + m_Instructions = m_ActiveSeg->m_Instructions; + m_ActiveAddr = m_ActiveSeg->m_ActiveAddr; + + // Update last line of current SegLines + m_ActiveSegLines->lastLine = (PCB).line - 1; - // Update address location - m_Address = (unsigned short) m_ActiveMod->m_Address[CSEG]; + // Create a new SegLines and add to the array + m_ActiveSegLines = new CSegLines(m_ActiveSeg, m_Line); + m_SegLines.Add(m_ActiveSegLines); + + // Check if the module changed while we were away + if (m_ActiveSeg->m_LastMod != m_ActiveMod) + { + // Add an artificial instruction to reflect change in module + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_MODULE; + pInst->m_Line = m_Line; + pInst->m_Operand1 = new MString; // Allocte operand object + *pInst->m_Operand1 = m_ActiveMod->m_Name; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + m_Instructions->Add(pInst); + } + } } -void VTAssembler::directive_dseg(int page) +/* +============================================================================ +This function is called when a cseg or dseg directive is encountered +============================================================================ +*/ +void VTAssembler::directive_cdseg(int segType, int page) { + MString segName = ".text"; + const char *name; + CSegment* pSeg; + MString err; + // Determine if conditional assembly enabled if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) return; // Update line number - m_Line = (PCB).line; + m_Line = (PCB).line - 1; + if (segType == DSEG) + segName = ".data"; - // Save current address in current module - m_ActiveMod->m_Address[m_ActiveMod->m_ActiveSeg] = m_Address; + // If this line has a label on it, then change the segment name + if (m_LastLabelLine == m_Line) + { + segName = m_LastLabel; + } - // Set segment of current module - m_ActiveMod->m_ActiveSeg = DSEG; + // Lookup the segment in our map + name = (const char *) segName; + if (!m_Segments.Lookup(name, (VTObject *&) pSeg)) + { + // Segment does not exist. Create new segment + pSeg = new CSegment(name, segType, m_ActiveMod); + if (pSeg == NULL) + { + err.Format("Error in line %d(%s): Error allocating new segment %s", m_Line, + (const char *) m_Filenames[m_FileIndex], name); + m_Errors.Add(err); + return; + } - // Update pointers to assembly objects - m_Instructions = m_ActiveMod->m_Instructions[DSEG]; - m_Symbols = m_ActiveMod->m_Symbols[DSEG]; - m_ActiveMod->m_Page[DSEG] = page; - m_ActiveAddr = m_ActiveMod->m_ActiveAddr[DSEG]; + // Add segment to our list of segments + m_Segments[name] = pSeg; + } - // Update address location - m_Address = (unsigned short) m_ActiveMod->m_Address[DSEG]; + // Activate the new segment + ActivateSegment(pSeg); } +/* +============================================================================ +This function is called when a ds directive is encountered +============================================================================ +*/ void VTAssembler::directive_ds() { double len; @@ -1291,12 +1736,13 @@ void VTAssembler::directive_ds() pInst->m_Line = m_Line; pInst->m_Group = gEq; pInst->m_FileIndex = m_FileIndex; // Save index of the current file + pInst->m_Address = m_ActiveSeg->m_Address; gEq = new CRpnEquation; // Try to evaluate the equation if (Evaluate((CRpnEquation *) pInst->m_Group, &len, 0)) { - m_Address += (int) len; + m_ActiveSeg->m_Address += (int) len; m_ActiveAddr->length += (unsigned short) len; } @@ -1304,6 +1750,93 @@ void VTAssembler::directive_ds() } } +/* +============================================================================ +This function is called when a fill directive is encountered +============================================================================ +*/ +void VTAssembler::directive_fill() +{ + int c, len; + int fillToAddr = -1; + unsigned char fillByte = 0xFF; + double value; + MString string; + + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + for (c = 0; c < gExpList->GetSize(); c++) + delete (*gExpList)[c]; + delete gExpList; // Delete the unused expression list + gExpList = new VTObArray; // Allocate new expresssion list for parser + return; + } + + // Update line number + m_Line = (PCB).line; + + CInstruction *pInst = new CInstruction; + + if (pInst != NULL) + { + pInst->m_ID = INST_FILL; + pInst->m_Line = m_Line; + pInst->m_Group = gExpList; + pInst->m_Address = m_ActiveSeg->m_Address; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + + // Test for syntax error if too many expressions + len = gExpList->GetSize(); + if (len > 2) + { + // Log an error + string.Format("Error in line %d(%s): Too many expressions for fill", + m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(string); + } + else + { + // Update address based on number of items in expression list + if (((CExpression *) (*gExpList)[0])->m_Equation != NULL) + { + // Try to evaluate the equation + CRpnEquation *pEq = ((CExpression *) (*gExpList)[0])->m_Equation; + if (Evaluate(pEq, &value, 0)) + { + // Update address based on fill size + len = (int) value; + m_ActiveSeg->m_Address += len; + m_ActiveAddr->length += len; // Update add range length + } + else + { + // Log an error + string.Format("Error in line %d(%s): Must be able to evaluate fill size on first pass!", + m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(string); + } + } + else + { + // Log an error + string.Format("Error in line %d(%s): Number of bytes for fill must be an equation", + m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(string); + } + } + + // Add new instruction to the instruction list and create new expression list + gExpList = new VTObArray; + m_Instructions->Add(pInst); + } +} + +/* +============================================================================ +This function is called when a db directive is encountered +============================================================================ +*/ void VTAssembler::directive_db() { int c, len; @@ -1327,6 +1860,7 @@ void VTAssembler::directive_db() pInst->m_ID = INST_DB; pInst->m_Line = m_Line; pInst->m_Group = gExpList; + pInst->m_Address = m_ActiveSeg->m_Address; pInst->m_FileIndex = m_FileIndex; // Save index of the current file // Update address based on number of items in expression list @@ -1335,13 +1869,13 @@ void VTAssembler::directive_db() { if (((CExpression *) (*gExpList)[c])->m_Equation != NULL) { - m_Address++; + m_ActiveSeg->m_Address++; m_ActiveAddr->length++; // Update add range length } else { int size = strlen(((CExpression *) (*gExpList)[c])->m_Literal); - m_Address += size; + m_ActiveSeg->m_Address += size; m_ActiveAddr->length += size; // Update add range length } } @@ -1351,6 +1885,11 @@ void VTAssembler::directive_db() } } +/* +============================================================================ +This function is called when a dw directive is encountered +============================================================================ +*/ void VTAssembler::directive_dw() { int len, c; @@ -1374,6 +1913,9 @@ void VTAssembler::directive_dw() pInst->m_ID = INST_DW; pInst->m_Line = m_Line; pInst->m_Group = gExpList; + pInst->m_Address = m_ActiveSeg->m_Address; + pInst->m_Operand1 = new MString; // Allocte operand object + pInst->m_Operand1->Format("%d", m_MsbFirst); pInst->m_FileIndex = m_FileIndex; // Save index of the current file // Update address based on number of items in expression list @@ -1382,7 +1924,7 @@ void VTAssembler::directive_dw() { if (((CExpression *) (*gExpList)[c])->m_Equation != NULL) { - m_Address += 2; + m_ActiveSeg->m_Address += 2; m_ActiveAddr->length += 2; // Update add range length } else @@ -1390,7 +1932,7 @@ void VTAssembler::directive_dw() int size = strlen(((CExpression *) (*gExpList)[c])->m_Literal); if (size & 0x01) size++; - m_Address += size; + m_ActiveSeg->m_Address += size; m_ActiveAddr->length += size; // Update add range length } } @@ -1400,12 +1942,15 @@ void VTAssembler::directive_dw() } } +/* +============================================================================ +This function is called when an extern directive is encountered +============================================================================ +*/ void VTAssembler::directive_extern() { - int c, count, x; - int exists; + int c, count; CSymbol* pSymbol; - VTObject* dummy; // Determine if conditional assembly enabled if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) @@ -1430,25 +1975,17 @@ void VTAssembler::directive_extern() count = gNameList->GetSize(); for (c = 0; c < count; c++) { - exists = 0; - // Check if symbol already exists - for (x = 0; x < 3; x++) + if (LookupSymbol((*gNameList)[c], pSymbol)) { - if (m_ActiveMod->m_Symbols[x]->Lookup((*gNameList)[c], dummy)) - { - MString string; - string.Format("Error in line %d(%s): Symbol %s already defined as %s", - pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex], - (const char *) (*gNameList)[c], - types[((CSymbol *) dummy)->m_SymType & 0x00FF]); - m_Errors.Add(string); - exists = 1; - } + MString string; + string.Format("Error in line %d(%s): Symbol %s already defined as %s", + pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex], + (const char *) (*gNameList)[c], + types[pSymbol->m_SymType & 0x00FF]); + m_Errors.Add(string); } - - // If symbol does not exist, add it to the symbol table - if (!exists) + else { pSymbol = new CSymbol; pSymbol->m_Line = m_Line; @@ -1464,6 +2001,11 @@ void VTAssembler::directive_extern() } } +/* +============================================================================ +This function is called when a public directive is encountered +============================================================================ +*/ void VTAssembler::directive_public() { // Determine if conditional assembly enabled @@ -1489,6 +2031,11 @@ void VTAssembler::directive_public() } } +/* +============================================================================ +This function is called when a sym directive is encountered +============================================================================ +*/ void VTAssembler::directive_sym() { // Determine if conditional assembly enabled @@ -1508,6 +2055,11 @@ void VTAssembler::directive_sym() } } +/* +============================================================================ +This function is called when a page directive is encountered +============================================================================ +*/ void VTAssembler::directive_page(int page) { // Determine if conditional assembly enabled @@ -1529,8 +2081,18 @@ void VTAssembler::directive_page(int page) } } +/* +============================================================================ +This function is called when a link directive is encountered +============================================================================ +*/ void VTAssembler::directive_link(const char *name) { + MString linkName = name; + + linkName += (char *) ".asm"; + include ((const char *) linkName); + return; // Determine if conditional assembly enabled if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) return; @@ -1550,6 +2112,11 @@ void VTAssembler::directive_link(const char *name) } } +/* +============================================================================ +This function is called when a maclib directive is encountered +============================================================================ +*/ void VTAssembler::directive_maclib(const char *name) { // Determine if conditional assembly enabled @@ -1571,6 +2138,58 @@ void VTAssembler::directive_maclib(const char *name) } } +/* +============================================================================ +This function is called when a module directive is encountered. Modules +allow definition of local labels using the _ prefix. +============================================================================ +*/ +void VTAssembler::directive_module(const char *name) +{ + CModule* pMod; + MString err; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_MODULE; + pInst->m_Line = m_Line; + pInst->m_Operand1 = new MString; // Allocte operand object + *pInst->m_Operand1 = name; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + m_Instructions->Add(pInst); + } + + // Check if module already exists + if (m_Modules.Lookup(name, (VTObject *&) pMod)) + { + m_ActiveMod = pMod; + m_Symbols = m_ActiveMod->m_Symbols; + m_ActiveSeg->m_LastMod = m_ActiveMod; + return; + } + + // Module doesn't exit. Create a new module + pMod = new CModule(name); + if (pMod == NULL) + { + err.Format("Error in line %d(%s): Error creating new module %s", m_Line, + (const char *) m_Filenames[m_FileIndex], name); + m_Errors.Add(err); + } + + // Add this module to the list and make it active + m_Modules[name] = pMod; + m_ActiveMod = pMod; + m_Symbols = m_ActiveMod->m_Symbols; + m_ActiveSeg->m_LastMod = m_ActiveMod; +} + +/* +============================================================================ +This function is called when a name directive is encountered +============================================================================ +*/ void VTAssembler::directive_name(const char *name) { // Determine if conditional assembly enabled @@ -1581,7 +2200,7 @@ void VTAssembler::directive_name(const char *name) m_Line = (PCB).line; // Check if module already has a name - if (m_ActiveMod->m_Name != "") + if (m_ActiveMod->m_Name != "basemod") { // Report an error MString string; @@ -1595,9 +2214,18 @@ void VTAssembler::directive_name(const char *name) } // Save module name in active CModule object + m_Modules.RemoveAt(m_ActiveMod->m_Name); m_ActiveMod->m_Name = name; + + // Reassign current module with new name + m_Modules[name] = m_ActiveMod; } +/* +============================================================================ +This function is called when a title directive is encountered +============================================================================ +*/ void VTAssembler::directive_title(const char *name) { // Determine if conditional assembly enabled @@ -1625,6 +2253,11 @@ void VTAssembler::directive_title(const char *name) m_ActiveMod->m_Title = name; } +/* +============================================================================ +This function is called when a stkln directive is encountered +============================================================================ +*/ void VTAssembler::directive_stkln() { // Determine if conditional assembly enabled @@ -1650,6 +2283,26 @@ void VTAssembler::directive_stkln() } } +/* +============================================================================ +This function is called when a lsfirst / msfirst directive is encountered +============================================================================ +*/ +void VTAssembler::directive_endian(int msbFirst) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + return; + } + m_MsbFirst = msbFirst; +} + +/* +============================================================================ +This function is called when an end directive is encountered +============================================================================ +*/ void VTAssembler::directive_end(const char *name) { // Determine if conditional assembly enabled @@ -1658,20 +2311,281 @@ void VTAssembler::directive_end(const char *name) // Update line number m_Line = (PCB).line; - - CInstruction* pInst = new CInstruction; + + CInstruction* pInst = new CInstruction; + if (pInst != NULL) + { + pInst->m_ID = INST_END; + pInst->m_Line = m_Line; + pInst->m_Operand1 = new MString; // Allocte operand object + *pInst->m_Operand1 = name; + pInst->m_FileIndex = m_FileIndex; // Save index of the current file + m_Instructions->Add(pInst); + } +} + +/* +============================================================================ +This function is called when an echo string directive is encountered +============================================================================ +*/ +int VTAssembler::preproc_error(const char *string) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + return FALSE; + } + + MString err = string; + err.Format("Error in line %d(%s): %s", m_Line, + (const char *) m_Filenames[m_FileIndex], string); + m_Errors.Add(err); + + return TRUE; +} + +/* +============================================================================ +This is the preprocessor function to handle conditional IFDEF statements +============================================================================ +*/ +void VTAssembler::preproc_ifdef(const char* name, int negate) +{ + MString err, strName; + CSymbol* dummy; + int defined; + + // Update line number + m_Line = (PCB).line; + + m_LastIfElseLine = m_Line; + m_LastIfElseIsIf = 1; + + // First push results from previous IF/ELSE/ENDIF operation so + // we generate "nested if" conditions. Initialize condition to + // EVAL_ERROR in case the condition does not evaluate + if ((m_IfStat[m_IfDepth] == IF_STAT_DONT_ASSEMBLE) || + (m_IfStat[m_IfDepth] == IF_STAT_NESTED_DONT_ASSEMBLE) || + (m_IfStat[m_IfDepth] == IF_STAT_EVAL_ERROR)) + { + m_IfStat[++m_IfDepth] = IF_STAT_NESTED_DONT_ASSEMBLE; + } + else + m_IfStat[++m_IfDepth] = IF_STAT_EVAL_ERROR; + + // Ensure our #ifdef stack depth hasn't overflowed + if (m_IfDepth >= sizeof(m_IfStat)) + { + m_IfDepth--; + err.Format("Error in line %d(%s): Too many nested ifs", m_Line, + (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(err); + } + else if (m_IfStat[m_IfDepth] == IF_STAT_EVAL_ERROR) + { + m_IfStat[m_IfDepth] = IF_STAT_DONT_ASSEMBLE; + strName = name; + defined = LookupSymbol(strName, dummy); + if ((defined && !negate) || (!defined && negate)) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + } +} + +/* +============================================================================ +This is the preprocessor function to handle conditional IF statements +============================================================================ +*/ +void VTAssembler::preproc_if(void) +{ + directive_if(); +} + +/* +============================================================================ +This is the preprocessor function to handle conditional ELIF statements +============================================================================ +*/ +void VTAssembler::preproc_elif(void) +{ + directive_if(INST_ELIF); +} + +/* +============================================================================ +This is the preprocessor function to handle conditional IFNDEF statements +============================================================================ +*/ +void VTAssembler::preproc_ifndef(const char* name) +{ + preproc_ifdef(name, TRUE); +} + +/* +============================================================================ +This is the preprocessor function to handle conditional ELSE statements +============================================================================ +*/ +void VTAssembler::preproc_else() +{ + directive_else(); +} + +/* +============================================================================ +This is the preprocessor function to handle conditional ENDIF statements +============================================================================ +*/ +void VTAssembler::preproc_endif() +{ + directive_endif(); +} + +/* +============================================================================ +This is the preprocessor function to handle conditional DEFINE statements +============================================================================ +*/ +void VTAssembler::preproc_define() +{ + // Update line number + m_Line = (PCB).line; + + CInstruction *pInst = new CInstruction; + if (pInst != NULL) { - pInst->m_ID = INST_END; + pInst->m_ID = INST_DEFINE; pInst->m_Line = m_Line; - pInst->m_Operand1 = new MString; // Allocte operand object - *pInst->m_Operand1 = name; + pInst->m_Group = gMacro; // Save the macro + pInst->m_Operand1 = new MString; + *pInst->m_Operand1 = gMacro->m_Name; // Save name of define + pInst->m_Address = m_ActiveSeg->m_Address; pInst->m_FileIndex = m_FileIndex; // Save index of the current file + + // Add the macro to our array of defines + m_Defines.Add(gMacro); + + // Add new instruction to the instruction list and create new expression list + gMacro = new CMacro; // Create a new macro object m_Instructions->Add(pInst); } } -void VTAssembler::directive_if() +/* +============================================================================ +This is the preprocessor function to handle conditional UNDEF statements +============================================================================ +*/ +void VTAssembler::preproc_undef(const char *name) +{ +} + +/* +============================================================================ +This is the preprocessor function to handle macros found in the code that +is acrually a statement vs. a parameter / equation +============================================================================ +*/ +int VTAssembler::preproc_macro() +{ + CMacro* pMacro; + MString err, replace; + + // Test if we are in the middle of a #define reduction and simply exit if we are + if (gDefine) + return 0; + + // Test if the macro is found in our m_Defines array + if (LookupMacro(gMacro->m_Name, pMacro)) + { + // Macro found. We need to do any parameter substitution and configure + // a macro string for parser input + if (pMacro->m_ParamList != NULL) + { + if ((gMacro->m_ParamList == NULL) || (pMacro->m_ParamList->GetSize() != gMacro->m_ParamList->GetSize())) + { + // Invalid number of parameters to macro! + err.Format("Error in line %d(%s): Macro %s expects %d parameters", m_Line, + (const char *) m_Filenames[m_FileIndex], (const char *) pMacro->m_Name, + pMacro->m_ParamList->GetSize()); + m_Errors.Add(err); + return FALSE; + } + } + else if (gMacro->m_ParamList != 0) + { + // Invalid number of parameters to macro! + err.Format("Error in line %d(%s): Macro %s expects no parameters", m_Line, + (const char *) m_Filenames[m_FileIndex], (const char *) pMacro->m_Name); + m_Errors.Add(err); + return FALSE; + } + + // Assign the replacement string + replace = pMacro->m_DefString; + + // Do parameter substitution + if (pMacro->m_ParamList != NULL) + { + int c, count; + + // Loop for each parameter + count = pMacro->m_ParamList->GetSize(); + for (c = 0; c < count; c++) + { + int atEnd = FALSE; + int pos = 0; + CExpression* paramExp = (CExpression *) pMacro->m_ParamList->GetAt(c); + MString param = paramExp->m_Literal; + int len = param.GetLength(); + CExpression* argExp = (CExpression *) gMacro->m_ParamList->GetAt(c); + MString arg = argExp->m_Literal; + + // Find all occurances of this parameter in the Definition String + while (pos != -1) + { + int wholeMatch = TRUE; + pos = replace.Find((char *) (const char *) param, pos); + if (pos >= 0) + { + // Test if the item found is a full match + if (pos != 0) + { + char ch = replace[pos-1]; // Get char before the find + if ((ch >= 'A') && (ch <= 'z') || (ch == '_') || (ch == '$') || (ch == '&')) + wholeMatch = FALSE; + } + if (pos + len != replace.GetLength()-1) + { + char ch = replace[pos + len +1 ]; + if ((ch >= 'A') && (ch <= 'z') || (ch == '_') || (ch == '$') || (ch == '&')) + wholeMatch = FALSE; + } + + // If this is full match then substitue the text + replace.Delete(pos, len); + replace.Insert(pos, (char *) (const char *) arg); + pos += arg.GetLength(); + } + } + } + } + + // Indicate the token should be changed to WS + return TRUE; + } + + return 0; +} + +/* +============================================================================ +This function is called when an if directive is encountered +============================================================================ +*/ +void VTAssembler::directive_if(int inst) { double valuel, valuer; MString err; @@ -1679,34 +2593,57 @@ void VTAssembler::directive_if() // Update line number m_Line = (PCB).line; - CInstruction* pInst = new CInstruction; - if (pInst != NULL) - { - pInst->m_ID = INST_IF; - pInst->m_Line = m_Line; - pInst->m_Group = gCond; - pInst->m_FileIndex = m_FileIndex; // Save index of the current file +// CInstruction* pInst = new CInstruction; +// if (pInst != NULL) +// { +// pInst->m_ID = inst; // If or elif +// pInst->m_Line = m_Line; +// pInst->m_Group = gCond; +// pInst->m_FileIndex = m_FileIndex; // Save index of the current file + m_LastIfElseLine = m_Line; + m_LastIfElseIsIf = 1; // First push results from previous IF/ELSE/ENDIF operation so // we generate "nested if" conditions. Initialize condition to // EVAL_ERROR in case the condition does not evaluate - if ((m_IfStat[m_IfDepth] == IF_STAT_DONT_ASSEMBLE) || - (m_IfStat[m_IfDepth] == IF_STAT_NESTED_DONT_ASSEMBLE) || - (m_IfStat[m_IfDepth] == IF_STAT_EVAL_ERROR)) + if (inst == INST_IF) { - m_IfStat[++m_IfDepth] = IF_STAT_NESTED_DONT_ASSEMBLE; + // Process if instrution + if ((m_IfStat[m_IfDepth] == IF_STAT_DONT_ASSEMBLE) || + (m_IfStat[m_IfDepth] == IF_STAT_NESTED_DONT_ASSEMBLE) || + (m_IfStat[m_IfDepth] == IF_STAT_EVAL_ERROR)) + { + m_IfStat[++m_IfDepth] = IF_STAT_NESTED_DONT_ASSEMBLE; + } + else + m_IfStat[++m_IfDepth] = IF_STAT_EVAL_ERROR; + + if (m_IfDepth >= sizeof(m_IfStat)) + { + m_IfDepth--; + err.Format("Error in line %d(%s): Too many nested ifs", m_Line, + (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(err); + gCond = new CCondition; +// m_Instructions->Add(pInst); + } } else - m_IfStat[++m_IfDepth] = IF_STAT_EVAL_ERROR; - - if (m_IfDepth >= sizeof(m_IfStat)) { - m_IfDepth--; - err.Format("Error in line %d(%s): Too many nested ifs", m_Line, - (const char *) m_Filenames[m_FileIndex]); - m_Errors.Add(err); - gCond = new CCondition; - m_Instructions->Add(pInst); + // Process elif instruction + if (m_IfDepth == 0) + { + err.Format("Error in line %d(%s): ELSE without a matching IF", m_Line, + (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(err); + return; + } + + if (m_IfStat[m_IfDepth] == IF_STAT_ASSEMBLE) + m_IfStat[m_IfDepth] = IF_STAT_NESTED_DONT_ASSEMBLE; + else + if (m_IfStat[m_IfDepth] == IF_STAT_DONT_ASSEMBLE) + m_IfStat[m_IfDepth] = IF_STAT_EVAL_ERROR; } // Determine if both equations can be evaluated @@ -1767,10 +2704,15 @@ void VTAssembler::directive_if() } } gCond = new CCondition; - m_Instructions->Add(pInst); - } +// m_Instructions->Add(pInst); +// } } +/* +============================================================================ +This function is called when an else directive is encountered +============================================================================ +*/ void VTAssembler::directive_else() { MString err; @@ -1778,13 +2720,15 @@ void VTAssembler::directive_else() // Update line number m_Line = (PCB).line; - CInstruction* pInst = new CInstruction; - if (pInst != NULL) - { - pInst->m_ID = INST_ELSE; - pInst->m_Line = m_Line; - pInst->m_FileIndex = m_FileIndex; // Save index of the current file - m_Instructions->Add(pInst); +// CInstruction* pInst = new CInstruction; +// if (pInst != NULL) +// { +// pInst->m_ID = INST_ELSE; +// pInst->m_Line = m_Line; +// pInst->m_FileIndex = m_FileIndex; // Save index of the current file + m_LastIfElseLine = m_Line; + m_LastIfElseIsIf = 0; +// m_Instructions->Add(pInst); // Process ELSE statement during parsing. First insure else has a matching if if (m_IfDepth == 0) @@ -1802,9 +2746,14 @@ void VTAssembler::directive_else() else if (m_IfStat[m_IfDepth] == IF_STAT_DONT_ASSEMBLE) m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; - } +// } } +/* +============================================================================ +This function is called when an endif directive is encountered +============================================================================ +*/ void VTAssembler::directive_endif() { MString err; @@ -1812,13 +2761,13 @@ void VTAssembler::directive_endif() // Update line number m_Line = (PCB).line; - CInstruction* pInst = new CInstruction; - if (pInst != NULL) - { - pInst->m_ID = INST_ENDIF; - pInst->m_Line = m_Line; - pInst->m_FileIndex = m_FileIndex; // Save index of the current file - m_Instructions->Add(pInst); +// CInstruction* pInst = new CInstruction; +// if (pInst != NULL) +// { +// pInst->m_ID = INST_ENDIF; +// pInst->m_Line = m_Line; +// pInst->m_FileIndex = m_FileIndex; // Save index of the current file +// m_Instructions->Add(pInst); // Process ENDIF statement during parsing. First insure else has a matching if if (m_IfDepth == 0) @@ -1831,14 +2780,21 @@ void VTAssembler::directive_endif() // Pop If from stack m_IfDepth--; - } +// } } +/* +============================================================================ +This is the main assemble routine. It is called after the parsing has +completed and generates object code for all ASEG, CSEG and DSEG segments +defined in the input file. The object code is stored in 3 separate arrays, +one for each segment to be writen to the object file later. +============================================================================ +*/ int VTAssembler::Assemble() { MString err; int c, count, len, x; - int seg, seg2; int size; CInstruction* pInst; CRelocation* pRel; @@ -1849,32 +2805,42 @@ int VTAssembler::Assemble() CSymbol* pSymbol; AddrRange* pRange; unsigned char opcode; - unsigned char op1, op2; + unsigned char op1 = 0xCC, op2 = 0xCC; unsigned char type; + unsigned short address; double value; char rel_mask; int valid, extern_label; + POSITION pos; + MString key; + CSegment* relSeg; /* ======================================================================== - Check if active module has a name and assign default name if it does not + Set the #ifdef level to zero. Not sure we need this ======================================================================== */ - m_Address = 0; m_IfDepth = 0; m_IfStat[0] = IF_STAT_ASSEMBLE; /* ======================================================================== - Loop through eash segment and assemble + Loop through each segment and assemble ======================================================================== */ - for (seg = 0; seg < 3; seg++) + pos = m_Segments.GetStartPosition(); + while (pos != NULL) { - m_Instructions = m_ActiveMod->m_Instructions[seg]; - m_Symbols = m_ActiveMod->m_Symbols[seg]; + // Get next segment to assemble + m_Segments.GetNextAssoc(pos, key, (VTObject *&) m_ActiveSeg); + + m_Instructions = m_ActiveSeg->m_Instructions; + m_ActiveAddr = m_ActiveSeg->m_UsedAddr; m_Address = 0; - m_ActiveAddr = m_ActiveMod->m_UsedAddr[seg]; + + // Get the initial module that was active during segment creation + m_ActiveMod = m_ActiveSeg->m_InitialMod; + m_Symbols = m_ActiveMod->m_Symbols; // Loop through all instructions and substitute equates and create instruction words count = m_Instructions->GetSize(); @@ -1884,6 +2850,7 @@ int VTAssembler::Assemble() m_Line = pInst->m_Line; m_FileIndex = pInst->m_FileIndex; rel_mask = 0; + address = m_Address; /* ==================================================================== @@ -1927,12 +2894,13 @@ int VTAssembler::Assemble() { // Equation evaluated to a value.check if it is // relative to a relocatable segment - if (InvalidRelocation((CRpnEquation *) pInst->m_Group, rel_mask)) + if (InvalidRelocation((CRpnEquation *) pInst->m_Group, rel_mask, + relSeg)) { // Error, equation cannot be evaluted - err.Format("Error in line %d(%s): Equation depends on multiple segments", - pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); - m_Errors.Add(err); +// err.Format("Error in line %d(%s): Equation depends on multiple segments", +// pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); +// m_Errors.Add(err); valid = 0; } @@ -1958,8 +2926,8 @@ int VTAssembler::Assemble() else { // Error, equation cannot be evaluted - err.Format("Error in line %d(%s): Equation cannot be evaluated", - pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); +// err.Format("Error in line %d(%s): Equation cannot be evaluated", +// pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); // m_Errors.Add(err); valid = 0; } @@ -1967,7 +2935,7 @@ int VTAssembler::Assemble() } // Add opcode and operands to array - m_AsmBytes[seg][m_Address++] = opcode; + m_ActiveSeg->m_AsmBytes[m_Address++] = opcode; // Check if operand is PC relative if ((rel_mask > 1) && valid) @@ -1976,11 +2944,8 @@ int VTAssembler::Assemble() pRel = new CRelocation; pRel->m_Address = m_Address; pRel->m_pSourceRange = m_ActiveAddr; - if (rel_mask & 0x02) - pRel->m_Segment = CSEG; - if (rel_mask & 0x04) - pRel->m_Segment = DSEG; - pRange = m_ActiveMod->m_UsedAddr[pRel->m_Segment]; + pRel->m_Segment = relSeg; + pRange = m_ActiveSeg->m_UsedAddr; while ((pRange != 0) && (pRel->m_pTargetRange == 0)) { if ((pRange->address <= (int) value) && @@ -1990,7 +2955,7 @@ int VTAssembler::Assemble() } pRange = pRange->pNext; } - m_Reloc[pRel->m_Segment].Add(pRel); + m_ActiveSeg->m_Reloc.Add(pRel); } // Check if operand is extern @@ -2001,7 +2966,7 @@ int VTAssembler::Assemble() pExt->m_Address = m_Address; pExt->m_Name = ((CRpnEquation *) pInst->m_Group)->m_OperationArray[0].m_Variable; - pExt->m_Segment = seg; + pExt->m_Segment = m_ActiveSeg->m_Type; pExt->m_Size = size; pExt->m_pRange = m_ActiveAddr; m_Externs.Add(pExt); @@ -2011,12 +2976,12 @@ int VTAssembler::Assemble() if ((type == OPCODE_REG_IMM) || (type == OPCODE_EQU8) || (type == OPCODE_EQU16) || (type == OPCODE_REG_EQU16)) { - m_AsmBytes[seg][m_Address++] = op1; + m_ActiveSeg->m_AsmBytes[m_Address++] = op1; } if ((type == OPCODE_EQU16) || (type == OPCODE_REG_EQU16)) { - m_AsmBytes[seg][m_Address++] = op2; + m_ActiveSeg->m_AsmBytes[m_Address++] = op2; } } @@ -2028,6 +2993,9 @@ int VTAssembler::Assemble() */ else if (pInst->m_ID == INST_ORG) { + // Indicate instruction address not to be reported in listing + pInst->m_Bytes = -1; + // The parser takes care of this instruction but we need to start a new // Segment in the .obj file if (Evaluate((CRpnEquation *) pInst->m_Group, &value, 1)) @@ -2035,13 +3003,13 @@ int VTAssembler::Assemble() m_Address = (int) value; // Find AddrRange object for this ORG - pRange = m_ActiveMod->m_UsedAddr[seg]; + pRange = m_ActiveSeg->m_UsedAddr; while (pRange != 0) { if ((pRange->address == m_Address) || ((pRange->address < m_Address) && (pRange->address + pRange->length > m_Address))) { - m_ActiveMod->m_ActiveAddr[seg] = pRange; + m_ActiveSeg->m_ActiveAddr = pRange; m_ActiveAddr = pRange; break; } @@ -2052,10 +3020,54 @@ int VTAssembler::Assemble() } else { - err.Format("Error in line %d(%s): Equation cannot be evaluated", - pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); - m_Errors.Add(err); +// err.Format("Error in line %d(%s): Equation cannot be evaluated", +// pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); +// m_Errors.Add(err); + } + } + + /* + ==================================================================== + Deal with FILL directive by adding bytes to the output stream + ==================================================================== + */ + else if (pInst->m_ID == INST_FILL) + { + unsigned char fillVal = 0xFF; + size = 0; + + // Get count of expression in list + pExpList = (VTObArray *) pInst->m_Group; + len = pExpList->GetSize(); + + // Try to evaluate the fill to expression + pExp = (CExpression *) (*pExpList)[0]; + if (Evaluate(pExp->m_Equation, &value, 1)) + { + // Update address based on fill size + size = (int) value; + } + + // If 2nd expression given, try to evaluate the fill value + if (len == 2) + { + // Get next expression from expression list + pExp = (CExpression *) (*pExpList)[1]; + + // If expression has an equation, try to evaluate it + if (pExp->m_Equation != NULL) + { + if (Evaluate(pExp->m_Equation, &value, 1)) + { + fillVal = (unsigned char) value; + } + } } + + // Add bytes with the fill character + int y; + for (y = 0; y < size; y++) + m_ActiveSeg->m_AsmBytes[m_Address++] = fillVal; } /* @@ -2079,12 +3091,12 @@ int VTAssembler::Assemble() if (pExp->m_Equation != NULL) { if (Evaluate(pExp->m_Equation, &value, 1)) - m_AsmBytes[seg][m_Address++] = (unsigned char) value; + m_ActiveSeg->m_AsmBytes[m_Address++] = (unsigned char) value; else { - err.Format("Error in line %d(%s): Equation cannot be evaluated", - pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); - m_Errors.Add(err); +// err.Format("Error in line %d(%s): Equation cannot be evaluated", +// pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); +// m_Errors.Add(err); } } else @@ -2093,7 +3105,7 @@ int VTAssembler::Assemble() int y, str_len; str_len = pExp->m_Literal.GetLength(); for (y = 0; y < str_len; y++) - m_AsmBytes[seg][m_Address++] = pExp->m_Literal[y]; + m_ActiveSeg->m_AsmBytes[m_Address++] = pExp->m_Literal[y]; } } } @@ -2120,14 +3132,23 @@ int VTAssembler::Assemble() { if (Evaluate(pExp->m_Equation, &value, 1)) { - m_AsmBytes[seg][m_Address++] = ((unsigned short) value) & 0xFF; - m_AsmBytes[seg][m_Address++] = ((unsigned short) value) >> 8; + // Test operand1 to check if MSFIRST is on or not + if (*pInst->m_Operand1 == "1") + { + m_ActiveSeg->m_AsmBytes[m_Address++] = ((unsigned short) value) >> 8; + m_ActiveSeg->m_AsmBytes[m_Address++] = ((unsigned short) value) & 0xFF; + } + else + { + m_ActiveSeg->m_AsmBytes[m_Address++] = ((unsigned short) value) & 0xFF; + m_ActiveSeg->m_AsmBytes[m_Address++] = ((unsigned short) value) >> 8; + } } else { - err.Format("Error in line %d(%s): Equation cannot be evaluated", - pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); - m_Errors.Add(err); +// err.Format("Error in line %d(%s): Equation cannot be evaluated", +// pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); +// m_Errors.Add(err); } } else @@ -2136,9 +3157,9 @@ int VTAssembler::Assemble() int y, str_len; str_len = pExt->m_Name.GetLength(); for (y = 0; y < str_len; y++) - m_AsmBytes[seg][m_Address++] = pExt->m_Name[y]; + m_ActiveSeg->m_AsmBytes[m_Address++] = pExt->m_Name[y]; if (str_len & 1) - m_AsmBytes[seg][m_Address++] = 0; + m_ActiveSeg->m_AsmBytes[m_Address++] = 0; } } } @@ -2167,9 +3188,9 @@ int VTAssembler::Assemble() else { // Report error - err.Format("Error in line %d(%s): Equation cannot be evaluated", - pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); - m_Errors.Add(err); +// err.Format("Error in line %d(%s): Equation cannot be evaluated", +// pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); +// m_Errors.Add(err); } } /* @@ -2185,27 +3206,18 @@ int VTAssembler::Assemble() len = pNameList->GetSize(); for (x = 0; x < len; x++) { - // Lookup symbol in each segment - for (seg2 = 0; seg2 < 3; seg2++) + // Lookup symbol in each module + if (LookupSymbol((*pNameList)[x], pSymbol)) { - if (m_ActiveMod->m_Symbols[seg2]->Lookup((*pNameList)[x], - (VTObject *&) pSymbol)) - { - pSymbol->m_SymType |= SYM_PUBLIC; + pSymbol->m_SymType |= SYM_PUBLIC; - // Check if symbol is a relative label - if ((pSymbol->m_SymType & 0x00FF) == SYM_LABEL) - { - m_Publics[seg2].Add(pSymbol); - } - break; + // Check if symbol is a relative label + if ((pSymbol->m_SymType & 0x00FF) == SYM_LABEL) + { + m_ActiveMod->m_Publics.Add(pSymbol); } - else - pSymbol = 0; } - - // Check if symbol was found in symbol table - if (pSymbol == 0) + else { // Report error err.Format("Error in line %d(%s): Symbol %s undefined", @@ -2214,8 +3226,29 @@ int VTAssembler::Assemble() m_Errors.Add(err); } } + pInst->m_Bytes = -1; + } + + /* + ==================================================================== + Deal with Module directive by changing the active module + ==================================================================== + */ + else if (pInst->m_ID == INST_MODULE) + { + // Search for module name in map + m_Modules.Lookup((const char *) pInst->m_Operand1, + (VTObject *&) m_ActiveMod); + pInst->m_Bytes = -1; } + + // Set the instructions length in bytes based on the distance it + // increased m_Address + if (pInst->m_Bytes != -1) + pInst->m_Bytes = m_Address - address; } + + // Here we should check if m_Address == m_ActiveSeg->m_Address as validation } // Check for errors during assembly @@ -2227,8 +3260,7 @@ int VTAssembler::Assemble() /* ======================================================================== -This routine checks the specified equation to determine if it depends on -more than one segment. +This routine creates the ELF object file. ======================================================================== */ int VTAssembler::CreateObjFile(const char *filename) @@ -2242,24 +3274,25 @@ int VTAssembler::CreateObjFile(const char *filename) int aseg_sections, cseg_sections, dseg_sections; FILE* fd; CSymbol* pSymbol; + CSegment* pSegment; CRelocation* pReloc; AddrRange* pRange; CExtern* pExt; - MString key; - POSITION pos; + MString key, modname; + POSITION pos, modPos; char sectString[] = "\0.strtab\0.symtab\0.aseg\0.text\0.data\0"; char relString[] = ".relcseg\0.reldseg\0"; char debugString[] = ".debug\0"; - int debugStrSize = 7; - int strtab_off = 1; - int symtab_off = 9; - int aseg_off = 17; - int cseg_off = 23; - int dseg_off = 29; - int relcseg_off = 35; - int reldseg_off = 44; - int extern_off = 53; - int seg, len; + const int debugStrSize = 7; + const int strtab_off = 1; + const int symtab_off = 9; + const int aseg_off = 17; + const int cseg_off = 23; + const int dseg_off = 29; + const int relcseg_off = 35; + const int reldseg_off = 44; + const int extern_off = 53; + int len, strtab_start; int first_aseg_idx, first_cseg_idx, first_dseg_idx; int shidx, type, bind; const char * pStr; @@ -2281,13 +3314,13 @@ int VTAssembler::CreateObjFile(const char *filename) ehdr.e_ident[EI_MAG1] = ELFMAG1; ehdr.e_ident[EI_MAG2] = ELFMAG2; ehdr.e_ident[EI_MAG3] = ELFMAG3; - ehdr.e_ident[EI_CLASS] = ELFCLASS8; + ehdr.e_ident[EI_CLASS] = ELFCLASS32; ehdr.e_ident[EI_DATA] = ELFDATA2LSB; ehdr.e_ident[EI_VERSION] = EV_CURRENT; for (c = EI_PAD; c < EI_NIDENT; c++) ehdr.e_ident[c] = 0; ehdr.e_type = ET_REL; // Relocatable object file - ehdr.e_machine = ET_8085; // Model 100 machine + ehdr.e_machine = EM_8085; // Model 100 machine ehdr.e_version = EV_CURRENT; // Version info ehdr.e_entry = 0; // No entry point for .obj file ehdr.e_phoff = 0; // No Program Header for .obj file @@ -2328,10 +3361,9 @@ int VTAssembler::CreateObjFile(const char *filename) // Create section header for string table strhdr.sh_name = strtab_off; // Put ".strtab" as first entry in table strhdr.sh_type = SHT_STRTAB; // Make section a string table - strhdr.sh_flags = 0; // No flags for this section + strhdr.sh_flags = SHF_STRINGS; // This section contains NULL terminated strings strhdr.sh_addr = 0; // No address data for string table strhdr.sh_offset = ftell(fd); - strhdr.sh_size = extern_off; // Initialize size to zero -- fill in later strhdr.sh_link = 0; // Set link data to zero strhdr.sh_info = 0; // Set info byte to zero strhdr.sh_addralign = 0; // Set allignment data to zero @@ -2339,13 +3371,37 @@ int VTAssembler::CreateObjFile(const char *filename) ehdr.e_shnum++; // Increment Section Header count // Start STRTAB section for section strings - fwrite(sectString, relcseg_off, 1, fd); - fwrite(relString, 18, 1, fd); + strtab_start = ftell(fd); + fwrite(sectString, sizeof(sectString), 1, fd); + fwrite(relString, sizeof(relString), 1, fd); + strhdr.sh_size = sizeof(sectString) + sizeof(relString); if (m_DebugInfo) { fwrite(debugString, debugStrSize, 1, fd); strhdr.sh_size += debugStrSize; } + + // Write section names for all other sections + pos = m_Segments.GetStartPosition(); + while (pos != NULL) + { + m_Segments.GetNextAssoc(pos, key, (VTObject *&) pSegment); + if (pSegment->m_Name == ".aseg") + pSegment->m_sh_offset = aseg_off; + else if (pSegment->m_Name == ".text") + pSegment->m_sh_offset = cseg_off; + else if (pSegment->m_Name == ".data") + pSegment->m_sh_offset = dseg_off; + else + { + // Write string to the file including NULL termination. Also, + // calculate the string's ofset from beginning of STRTAB section + pStr = (const char *) pSegment->m_Name; + pSegment->m_sh_offset = ftell(fd) - strtab_start; + fwrite(pStr, 1, strlen(pStr) + 1, fd); + strhdr.sh_size += strlen(pStr) + 1; + } + } /* ========================================================= @@ -2355,7 +3411,7 @@ int VTAssembler::CreateObjFile(const char *filename) // Create section header for string table str2hdr.sh_name = strtab_off; // Put ".strtab" as first entry in table str2hdr.sh_type = SHT_STRTAB; // Make section a string table - str2hdr.sh_flags = 0; // No flags for this section + str2hdr.sh_flags = SHF_STRINGS; // This section contains NULL terminates strings str2hdr.sh_addr = 0; // No address data for string table str2hdr.sh_offset = ftell(fd); str2hdr.sh_size = 1; // Initialize size to zero -- fill in later @@ -2366,23 +3422,27 @@ int VTAssembler::CreateObjFile(const char *filename) ehdr.e_shnum++; // Increment Section Header count // Start with a null string + strtab_start = ftell(fd); fwrite(sectString, 1, 1, fd); - idx = 1; - for (seg = 0; seg < 3; seg++) + modPos = m_Modules.GetStartPosition(); + while (modPos != NULL) { - pos = m_ActiveMod->m_Symbols[seg]->GetStartPosition(); + // Get the pointer to this module + m_Modules.GetNextAssoc(modPos, modname, (VTObject *&) m_ActiveMod); + + // Loop through all symbols for this module + pos = m_ActiveMod->m_Symbols->GetStartPosition(); while (pos != 0) { // Get next symbol - m_ActiveMod->m_Symbols[seg]->GetNextAssoc(pos, key, (VTObject *&) pSymbol); + m_ActiveMod->m_Symbols->GetNextAssoc(pos, key, (VTObject *&) pSymbol); if ((pSymbol->m_SymType & SYM_PUBLIC) || (pSymbol->m_SymType & SYM_EXTERN)) { // Add string for this symbol - pSymbol->m_StrtabOffset = idx; + pSymbol->m_StrtabOffset = ftell(fd) - strtab_start; len = strlen(pSymbol->m_Name) + 1; fwrite(pSymbol->m_Name, len, 1, fd); str2hdr.sh_size += len; - idx++; } } } @@ -2395,24 +3455,28 @@ int VTAssembler::CreateObjFile(const char *filename) symhdr.sh_name = symtab_off; // Put ".strtab" as first entry in table symhdr.sh_type = SHT_SYMTAB; // Make section a symbol table symhdr.sh_flags = 0; // No flags for this section - symhdr.sh_addr = 0; // No address data for symbol table + symhdr.sh_addr = 0; // No address data for symbol table symhdr.sh_offset = ftell(fd); - symhdr.sh_size = 0; // Initialize size to zero -- fill in later - symhdr.sh_link = 0; // Set link data to zero - symhdr.sh_info = 0; // Set info byte to zero + symhdr.sh_size = 0; // Initialize size to zero -- fill in later + symhdr.sh_link = 0; // Set link data to zero + symhdr.sh_info = 0; // Set info byte to zero symhdr.sh_addralign = 0; // Set allignment data to zero symhdr.sh_entsize = sizeof(Elf32_Sym);// Symbol table has equal size items ehdr.e_shnum++; // Increment Section Header count // Now add all EXTERN and PUBLIC symbols to string table idx = 0; - for (seg = 0; seg < 3; seg++) + modPos = m_Modules.GetStartPosition(); + while (modPos != NULL) { - pos = m_ActiveMod->m_Symbols[seg]->GetStartPosition(); + // Get the pointer to this module + m_Modules.GetNextAssoc(modPos, modname, (VTObject *&) m_ActiveMod); + + pos = m_ActiveMod->m_Symbols->GetStartPosition(); while (pos != 0) { // Get next symbol - m_ActiveMod->m_Symbols[seg]->GetNextAssoc(pos, key, (VTObject *&) pSymbol); + m_ActiveMod->m_Symbols->GetNextAssoc(pos, key, (VTObject *&) pSymbol); if ((pSymbol->m_SymType & SYM_PUBLIC) || (pSymbol->m_SymType & SYM_EXTERN)) { // Add Elf32_Sym entry for this symbol @@ -2437,24 +3501,21 @@ int VTAssembler::CreateObjFile(const char *filename) { sym.st_size = 0; pSymbol->m_Off16 = idx; - fwrite(&sym, sizeof(sym), 1, fd); - idx++; } if (pSymbol->m_SymType & SYM_8BIT) { sym.st_size = 1; pSymbol->m_Off8 = idx; - fwrite(&sym, sizeof(sym), 1, fd); - idx++; } if (pSymbol->m_SymType & SYM_16BIT) { sym.st_size = 2; pSymbol->m_Off16 = idx; - fwrite(&sym, sizeof(sym), 1, fd); - idx++; } + fwrite(&sym, sizeof(sym), 1, fd); + idx++; + // If symbol is EXTERN, find all m_Externs and update index if (bind == STB_EXTERN) { @@ -2475,7 +3536,8 @@ int VTAssembler::CreateObjFile(const char *filename) } } } - symhdr.sh_size = len * sizeof(Elf32_Sym); + // Set the symbol table size in bytes + symhdr.sh_size = idx * sizeof(Elf32_Sym); /* ========================================== @@ -2484,7 +3546,8 @@ int VTAssembler::CreateObjFile(const char *filename) */ // First count the number of sections needed aseg_sections = 1; - pRange = m_ActiveMod->m_UsedAddr[ASEG]; + m_Segments.Lookup(".aseg", (VTObject *&) m_ActiveSeg); + pRange = m_ActiveSeg->m_UsedAddr; while (pRange->pNext != 0) { aseg_sections++; @@ -2493,7 +3556,7 @@ int VTAssembler::CreateObjFile(const char *filename) // Allocate pointers for aseg_section headers aseg_hdr = (Elf32_Shdr *) malloc(aseg_sections * sizeof(Elf32_Shdr)); - pRange = m_ActiveMod->m_UsedAddr[ASEG]; + pRange = m_ActiveSeg->m_UsedAddr; idx = 0; first_aseg_idx = ehdr.e_shnum; while (pRange != NULL) @@ -2509,7 +3572,8 @@ int VTAssembler::CreateObjFile(const char *filename) aseg_hdr[idx].sh_name = aseg_off; // Point to ".aseg" name aseg_hdr[idx].sh_type = SHT_PROGBITS;// Make section a Program Bits section - aseg_hdr[idx].sh_flags = SHF_ALLOC | SHF_EXECINSTR; // Set flag bits + // Set flag bits. Note the SHF_8085_ABSOLUTE bit is OS specific + aseg_hdr[idx].sh_flags = SHF_ALLOC | SHF_EXECINSTR | SHF_8085_ABSOLUTE; aseg_hdr[idx].sh_addr = pRange->address;// Address for this section aseg_hdr[idx].sh_offset = ftell(fd); aseg_hdr[idx].sh_size = pRange->length; // Get size from AddrRange @@ -2518,13 +3582,13 @@ int VTAssembler::CreateObjFile(const char *filename) aseg_hdr[idx].sh_addralign = 0; // Set allignment data to zero aseg_hdr[idx].sh_entsize = 0; // Symbol table has equal size items - // Save the index of this CSEG Section Header for relocation reference + // Save the index of this ASEG Section Header for relocation reference pRange->shidx = ehdr.e_shnum; ehdr.e_shnum++; // Increment Section Header count // Write data to the file - fwrite(&m_AsmBytes[ASEG][pRange->address], pRange->length, 1, fd); + fwrite(&m_ActiveSeg->m_AsmBytes[pRange->address], pRange->length, 1, fd); // Point to next ASEG address range pRange = pRange->pNext; @@ -2539,56 +3603,74 @@ int VTAssembler::CreateObjFile(const char *filename) ========================================== */ // First count the number of sections needed - cseg_sections = 1; - pRange = m_ActiveMod->m_UsedAddr[CSEG]; - while (pRange->pNext != 0) + cseg_sections = 0; + pos = m_Segments.GetStartPosition(); + while (pos != NULL) { + m_Segments.GetNextAssoc(pos, key, (VTObject *&) m_ActiveSeg); + if (m_ActiveSeg->m_Type != CSEG) + continue; + + // Count the first address range cseg_sections++; - pRange =pRange->pNext; + pRange = m_ActiveSeg->m_UsedAddr; + while (pRange->pNext != 0) + { + cseg_sections++; + pRange =pRange->pNext; + } } - // Allocate pointers for aseg_section headers + // Allocate pointers for cseg_section headers cseg_hdr = (Elf32_Shdr *) malloc(cseg_sections * sizeof(Elf32_Shdr)); - pRange = m_ActiveMod->m_UsedAddr[CSEG]; idx = 0; + pos = m_Segments.GetStartPosition(); first_cseg_idx = ehdr.e_shnum; - - while (pRange != NULL) + while (pos != NULL) { - if (pRange->length == 0) - { - // If AddrRange is emtpy, don't write it to the .obj file - pRange = pRange->pNext; - cseg_hdr[idx].sh_name = 0; // Indicate empty section - idx++; // Increment to next index + // Get pointer to next segment and validate it is a CSEG type + m_Segments.GetNextAssoc(pos, key, (VTObject *&) m_ActiveSeg); + if (m_ActiveSeg->m_Type != CSEG) continue; - } - - cseg_hdr[idx].sh_name = cseg_off; // Point to ".cseg" name - cseg_hdr[idx].sh_type = SHT_PROGBITS;// Make section a Program Bits section - cseg_hdr[idx].sh_flags = SHF_ALLOC | SHF_EXECINSTR; // Set flag bits - cseg_hdr[idx].sh_addr = pRange->address;// Address for this section - cseg_hdr[idx].sh_offset = ftell(fd); - cseg_hdr[idx].sh_size = pRange->length; // Get size from AddrRange - cseg_hdr[idx].sh_link = 0; // Set link data to zero - cseg_hdr[idx].sh_info = 0; // Set info byte to zero - cseg_hdr[idx].sh_addralign = 0; // Set allignment data to zero - cseg_hdr[idx].sh_entsize = 0; // Symbol table has equal size items - - // Save the index of this CSEG Section Header for relocation reference - pRange->shidx = ehdr.e_shnum; - - ehdr.e_shnum++; // Increment Section Header count - // Write data to the file - fwrite(&m_AsmBytes[CSEG][pRange->address], pRange->length, 1, fd); + // Start with first AddrRange and loop for all + pRange = m_ActiveSeg->m_UsedAddr; + while (pRange != NULL) + { + // If the address range is zero, mark this as an empty section + if (pRange->length == 0) + { + // If AddrRange is emtpy, don't write it to the .obj file + pRange = pRange->pNext; + cseg_hdr[idx].sh_name = 0; // Indicate empty section + idx++; // Increment to next index + continue; + } - // Point to next ASEG address range - pRange = pRange->pNext; - idx++; // Increment to next index + cseg_hdr[idx].sh_name = m_ActiveSeg->m_sh_offset; // Point segment name + cseg_hdr[idx].sh_type = SHT_PROGBITS;// Make section a Program Bits section + cseg_hdr[idx].sh_flags = SHF_ALLOC | SHF_EXECINSTR; // Set flag bits + cseg_hdr[idx].sh_addr = pRange->address;// Address for this section + cseg_hdr[idx].sh_offset = ftell(fd); + cseg_hdr[idx].sh_size = pRange->length; // Get size from AddrRange + cseg_hdr[idx].sh_link = 0; // Set link data to zero + cseg_hdr[idx].sh_info = 0; // Set info byte to zero + cseg_hdr[idx].sh_addralign = 0; // Set allignment data to zero + cseg_hdr[idx].sh_entsize = 0; // Symbol table has equal size items + + // Save the index of this CSEG Section Header for relocation reference + pRange->shidx = ehdr.e_shnum; + ehdr.e_shnum++; // Increment Section Header count + + // Write data to the file + fwrite(&m_ActiveSeg->m_AsmBytes[pRange->address], pRange->length, 1, fd); + + // Point to next ASEG address range + pRange = pRange->pNext; + idx++; // Increment to next index + } } - /* ========================================== Create section for DSEG code. DSEGs are @@ -2596,52 +3678,69 @@ int VTAssembler::CreateObjFile(const char *filename) ========================================== */ // First count the number of sections needed - dseg_sections = 1; - pRange = m_ActiveMod->m_UsedAddr[DSEG]; - while (pRange->pNext != 0) + dseg_sections = 0; + pos = m_Segments.GetStartPosition(); + while (pos != NULL) { + m_Segments.GetNextAssoc(pos, key, (VTObject *&) m_ActiveSeg); + if (m_ActiveSeg->m_Type != DSEG) + continue; + dseg_sections++; - pRange =pRange->pNext; + pRange = m_ActiveSeg->m_UsedAddr; + while (pRange->pNext != 0) + { + dseg_sections++; + pRange =pRange->pNext; + } } - // Allocate pointers for aseg_section headers + // Allocate pointers for dseg_section headers dseg_hdr = (Elf32_Shdr *) malloc(dseg_sections * sizeof(Elf32_Shdr)); - pRange = m_ActiveMod->m_UsedAddr[DSEG]; idx = 0; first_dseg_idx = ehdr.e_shnum; - while (pRange != NULL) + pos = m_Segments.GetStartPosition(); + while (pos != NULL) { - if (pRange->length == 0) - { - // If AddrRange is emtpy, don't write it to the .obj file - pRange = pRange->pNext; - dseg_hdr[idx].sh_name = 0; // Indicate empty section - idx++; // Increment to next index + m_Segments.GetNextAssoc(pos, key, (VTObject *&) m_ActiveSeg); + if (m_ActiveSeg->m_Type != DSEG) continue; - } - dseg_hdr[idx].sh_name = dseg_off; // Point to ".dseg" name - dseg_hdr[idx].sh_type = SHT_PROGBITS;// Make section a Program Bits section - dseg_hdr[idx].sh_flags = SHF_WRITE; // Set flag bits - dseg_hdr[idx].sh_addr = pRange->address;// Address for this section - dseg_hdr[idx].sh_offset = ftell(fd); - dseg_hdr[idx].sh_size = pRange->length; // Get size from AddrRange - dseg_hdr[idx].sh_link = 0; // Set link data to zero - dseg_hdr[idx].sh_info = 0; // Set info byte to zero - dseg_hdr[idx].sh_addralign = 0; // Set allignment data to zero - dseg_hdr[idx].sh_entsize = 0; // Symbol table has equal size items + pRange = m_ActiveSeg->m_UsedAddr; + while (pRange != NULL) + { + if (pRange->length == 0) + { + // If AddrRange is emtpy, don't write it to the .obj file + pRange = pRange->pNext; + dseg_hdr[idx].sh_name = 0; // Indicate empty section + idx++; // Increment to next index + continue; + } - // Save the index of this CSEG Section Header for relocation reference - pRange->shidx = ehdr.e_shnum; - - ehdr.e_shnum++; // Increment Section Header count + dseg_hdr[idx].sh_name = m_ActiveSeg->m_sh_offset; // Point to segment name + dseg_hdr[idx].sh_type = SHT_PROGBITS;// Make section a Program Bits section + dseg_hdr[idx].sh_flags = SHF_WRITE; // Set flag bits + dseg_hdr[idx].sh_addr = pRange->address;// Address for this section + dseg_hdr[idx].sh_offset = ftell(fd); + dseg_hdr[idx].sh_size = pRange->length; // Get size from AddrRange + dseg_hdr[idx].sh_link = 0; // Set link data to zero + dseg_hdr[idx].sh_info = 0; // Set info byte to zero + dseg_hdr[idx].sh_addralign = 0; // Set allignment data to zero + dseg_hdr[idx].sh_entsize = 0; // Symbol table has equal size items + + // Save the index of this CSEG Section Header for relocation reference + pRange->shidx = ehdr.e_shnum; + + ehdr.e_shnum++; // Increment Section Header count - // Write data to the file - fwrite(&m_AsmBytes[DSEG][pRange->address], pRange->length, 1, fd); + // Write data to the file + fwrite(&m_ActiveSeg->m_AsmBytes[pRange->address], pRange->length, 1, fd); - // Point to next ASEG address range - pRange = pRange->pNext; - idx++; // Increment to next index + // Point to next ASEG address range + pRange = pRange->pNext; + idx++; // Increment to next index + } } /* @@ -2652,83 +3751,101 @@ int VTAssembler::CreateObjFile(const char *filename) rel_hdrs = (Elf32_Shdr *) malloc((dseg_sections + cseg_sections) * sizeof(Elf32_Shdr)); idx = 0; - pRange = m_ActiveMod->m_UsedAddr[CSEG]; - while (idx < dseg_sections + cseg_sections) + pos = m_Segments.GetStartPosition(); + while (pos != NULL) { - if (idx < cseg_sections) - { - rel_hdrs[idx].sh_name = relcseg_off; - seg = CSEG; - } - else + m_Segments.GetNextAssoc(pos, key, (VTObject *&) m_ActiveSeg); + if (m_ActiveSeg->m_Type == ASEG) + continue; + + pRange = m_ActiveSeg->m_UsedAddr; + while (pRange != NULL) { - rel_hdrs[idx].sh_name = reldseg_off; - seg = DSEG; - } - rel_hdrs[idx].sh_type = SHT_REL; // Make section a relocation section - rel_hdrs[idx].sh_flags = 0; // No flag bits for relocation section - rel_hdrs[idx].sh_addr = 0; // No address specifier for relocaton section - rel_hdrs[idx].sh_offset = ftell(fd);// Fill in offset later - rel_hdrs[idx].sh_size = 0; // Fill in size later - rel_hdrs[idx].sh_link = 3; // Point to symtab section - rel_hdrs[idx].sh_info = pRange->shidx; - rel_hdrs[idx].sh_addralign = 0; // No alignment requirements - rel_hdrs[idx].sh_entsize = sizeof(Elf32_Rel); + // Set the relative section's name offset based on type + rel_hdrs[idx].sh_name = m_ActiveSeg->m_sh_offset; + rel_hdrs[idx].sh_type = SHT_REL; // Make section a relocation section + rel_hdrs[idx].sh_flags = 0; // No flag bits for relocation section + rel_hdrs[idx].sh_addr = 0; // No address specifier for relocaton section + rel_hdrs[idx].sh_offset = ftell(fd);// Fill in offset later + rel_hdrs[idx].sh_size = 0; // Fill in size later + rel_hdrs[idx].sh_link = 3; // Point to symtab section + rel_hdrs[idx].sh_info = pRange->shidx; + rel_hdrs[idx].sh_addralign = 0; // No alignment requirements + rel_hdrs[idx].sh_entsize = sizeof(Elf32_Rel); + + // Generage Elf32_Rel object for each relocation relative to this section + len = m_ActiveSeg->m_Reloc.GetSize(); + + // Loop through all relocation items in seg + for (c = 0; c < len; c++) + { + // Check if this relocation relative to current section + pReloc = (CRelocation *) m_ActiveSeg->m_Reloc[c]; + if (pReloc->m_pTargetRange == pRange) + { + if (pReloc->m_pSourceRange->shidx >= first_dseg_idx) + { + shidx = pReloc->m_pSourceRange->shidx - first_dseg_idx; + rel.r_offset = pReloc->m_Address - dseg_hdr[shidx].sh_addr + + dseg_hdr[shidx].sh_offset; + rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); + } + else if (pReloc->m_pSourceRange->shidx >= first_cseg_idx) + { + shidx = pReloc->m_pSourceRange->shidx - first_cseg_idx; + rel.r_offset = pReloc->m_Address - cseg_hdr[shidx].sh_addr + + cseg_hdr[shidx].sh_offset; + rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); + } + else + { + shidx = pReloc->m_pSourceRange->shidx - first_aseg_idx; + rel.r_offset = pReloc->m_Address - aseg_hdr[shidx].sh_addr + + aseg_hdr[shidx].sh_offset; + rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); + } + + // Update size of header + rel_hdrs[idx].sh_size += sizeof(Elf32_Rel); - // Generage Elf32_Rel object for each relocation relative to this section - len = m_Reloc[seg].GetSize(); + // Write entry to file + fwrite(&rel, sizeof(Elf32_Rel), 1, fd); + } + } - // Loop through all relocation items in seg - for (c = 0; c < len; c++) - { - // Check if this relocation relative to current section - pReloc = (CRelocation *) m_Reloc[seg][c]; - if (pReloc->m_pTargetRange == pRange) + // Loop through externs + len = m_Externs.GetSize(); + for (c = 0; c < len; c++) { - - if (pReloc->m_pSourceRange->shidx >= first_dseg_idx) - { - shidx = pReloc->m_pSourceRange->shidx - first_dseg_idx; - rel.r_offset = pReloc->m_Address - dseg_hdr[shidx].sh_addr + - dseg_hdr[shidx].sh_offset; - rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); - } - else if (pReloc->m_pSourceRange->shidx >= first_cseg_idx) - { - shidx = pReloc->m_pSourceRange->shidx - first_cseg_idx; - rel.r_offset = pReloc->m_Address - cseg_hdr[shidx].sh_addr + - cseg_hdr[shidx].sh_offset; - rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); - } - else + // Get next extern from array + pExt = (CExtern *) m_Externs[c]; + + // Check if extern is for this address range + if (pExt->m_pRange == pRange) { - shidx = pReloc->m_pSourceRange->shidx - first_aseg_idx; - rel.r_offset = pReloc->m_Address - aseg_hdr[shidx].sh_addr + - aseg_hdr[shidx].sh_offset; - rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); - } + // Set address for this relocation + rel.r_offset = pExt->m_Address; + rel.r_info = ELF32_R_INFO(pExt->m_SymIdx, SR_EXTERN); - // Update size of header - rel_hdrs[idx].sh_size += sizeof(Elf32_Rel); + // Update size of header + rel_hdrs[idx].sh_size += sizeof(Elf32_Rel); - // Write entry to file - fwrite(&rel, sizeof(Elf32_Rel), 1, fd); + // Write entry to file + fwrite(&rel, sizeof(Elf32_Rel), 1, fd); + } } - } - - // Loop through externs - len = m_Externs.GetSize(); - for (c = 0; c < len; c++) - { - // Get next extern from array - pExt = (CExtern *) m_Externs[c]; - // Check if extern is for this address range - if (pExt->m_pRange == pRange) + // Search for PUBLIC symbols in this section + len = m_ActiveMod->m_Publics.GetSize(); + for (c = 0; c < len; c++) { - // Set address for this relocation - rel.r_offset = pExt->m_Address; - rel.r_info = ELF32_R_INFO(pExt->m_SymIdx, SR_EXTERN); + pSymbol = (CSymbol *) m_ActiveMod->m_Publics[c]; + + rel.r_offset = 0; + if (pSymbol->m_SymType & SYM_8BIT) + rel.r_info = ELF32_R_INFO(pSymbol->m_Off8, SR_PUBLIC); + else + rel.r_info = ELF32_R_INFO(pSymbol->m_Off16, SR_PUBLIC); // Update size of header rel_hdrs[idx].sh_size += sizeof(Elf32_Rel); @@ -2736,39 +3853,17 @@ int VTAssembler::CreateObjFile(const char *filename) // Write entry to file fwrite(&rel, sizeof(Elf32_Rel), 1, fd); } - } - - // Search for PUBLIC symbols in this section - len = m_Publics[seg].GetSize(); - for (c = 0; c < len; c++) - { - pSymbol = (CSymbol *) m_Publics[seg][c]; - - rel.r_offset = 0; - if (pSymbol->m_SymType & SYM_8BIT) - rel.r_info = ELF32_R_INFO(pSymbol->m_Off8, SR_PUBLIC); - else - rel.r_info = ELF32_R_INFO(pSymbol->m_Off16, SR_PUBLIC); - // Update size of header - rel_hdrs[idx].sh_size += sizeof(Elf32_Rel); + // Check if anything actually written for this header. If not, we will + // omit writing header to section header table and therefore will not + // update the Elf header section header count + if (rel_hdrs[idx].sh_size != 0) + ehdr.e_shnum++; // Increment Section Header count - // Write entry to file - fwrite(&rel, sizeof(Elf32_Rel), 1, fd); + // Update pRange + pRange = pRange->pNext; + idx++; // Increment to next index } - - // Check if anything actually written for this header. If not, we will - // omit writing header to section header table and therefore will not - // update the Elf header section header count - if (rel_hdrs[idx].sh_size != 0) - ehdr.e_shnum++; // Increment Section Header count - - // Update pRange - pRange = pRange->pNext; - if (pRange == 0) - pRange = m_ActiveMod->m_UsedAddr[DSEG]; - - idx++; // Increment to next index } /* @@ -2780,7 +3875,6 @@ int VTAssembler::CreateObjFile(const char *filename) { } - /* ======================================= Write Section Header table to .OBJ file @@ -2856,44 +3950,55 @@ This routine checks the specified equation to determine if it depends on more than one segment. ======================================================================== */ -int VTAssembler::InvalidRelocation(CRpnEquation *pEq, char &rel_mask) +int VTAssembler::InvalidRelocation(CRpnEquation *pEq, char &rel_mask, + CSegment *&pSeg) { - int c, count; + int c, count, invalid; char rel[3]; - int seg; CSymbol *pSym; + // Initialize to not invalid. If the equation references labels + // in more than just one segment, we will mark the equation invalid + // for relocation. + invalid = FALSE; count = pEq->m_OperationArray.GetSize(); for (c = 0; c < 3; c++) rel[c] = 0; + pSeg = NULL; for (c = 0; c < count; c++) { // Check if operation type is a variable if (pEq->m_OperationArray[c].m_Operation == RPN_VARIABLE) { - // Loop through all segments and find the symbol - for (seg = 0; seg < 3; seg++) + // Find the symbol + if (LookupSymbol(pEq->m_OperationArray[c].m_Variable, pSym)) { - if (m_ActiveMod->m_Symbols[seg]->Lookup(pEq->m_OperationArray[c].m_Variable, - (VTObject *&) pSym)) + if ((pSym->m_SymType & 0x00FF) == SYM_LABEL) { - if ((pSym->m_SymType & 0x00FF) == SYM_LABEL) - rel[seg] = 1; + if (pSym->m_SymType & SYM_CSEG) + rel[CSEG] = 1; + else if (pSym->m_SymType & SYM_DSEG) + rel[DSEG] = 1; + else + rel[ASEG] = 1; - break; + // Assign or test the segment to ensure all are the same + if (pSeg == NULL) + pSeg = pSym->m_Segment; + else + { + if (pSeg != pSym->m_Segment) + invalid = TRUE; + } } } } } + // Update rel_mask based on which types of segments referenced rel_mask = rel[0] | (rel[1] << 1) | (rel[2] << 2); - - // Check if euqation is relative to more than one segment - if (rel[0] + rel[1] + rel[2] > 1) - return 1; - - return 0; + return invalid; } /* @@ -2904,7 +4009,7 @@ more than one segment. */ int VTAssembler::EquationIsExtern(CRpnEquation* pEq, int size) { - int seg, count; + int count; CSymbol* pSym; // Get count of operation array @@ -2916,20 +4021,16 @@ int VTAssembler::EquationIsExtern(CRpnEquation* pEq, int size) // Check if operation is a variable if (pEq->m_OperationArray[0].m_Operation == RPN_VARIABLE) { - for (seg = 0; seg < 3; seg++) + if (LookupSymbol(pEq->m_OperationArray[0].m_Variable, pSym)) { - if (m_ActiveMod->m_Symbols[seg]->Lookup(pEq->m_OperationArray[0].m_Variable, - (VTObject *&) pSym)) + // Check if variable type s EXTERN + if (pSym->m_SymType == SYM_EXTERN) { - // Check if variable type s EXTERN - if (pSym->m_SymType == SYM_EXTERN) - { - if (size == 1) - pSym->m_SymType |= SYM_8BIT; - if (size == 2) - pSym->m_SymType |= SYM_16BIT; - return 1; - } + if (size == 1) + pSym->m_SymType |= SYM_8BIT; + if (size == 2) + pSym->m_SymType |= SYM_16BIT; + return 1; } } } @@ -2937,21 +4038,117 @@ int VTAssembler::EquationIsExtern(CRpnEquation* pEq, int size) return 0; } +/* +============================================================================ +This function is called to parse an input file. If there are no errors +during parsing, the routine calls the routines to assemlbe and generate +output files for .obj, .lst, .hex, etc. +============================================================================ +*/ +void VTAssembler::ParseExternalDefines(void) +{ + int startIndex, endIndex; + MString def; + int len; + + // If zero length then we're done + if ((len = m_ExtDefines.GetLength()) == 0) + return; + + // Convert any commas to semicolons to make searches easy + m_ExtDefines.Replace(',', ';'); + + // Loop for all items in the string and assign labels + startIndex = 0; + while (startIndex >= 0) + { + // Find end of next define + endIndex = m_ExtDefines.Find(';', startIndex); + if (endIndex < 0) + endIndex = len; + + // Extract the define from the string + def = m_ExtDefines.Mid(startIndex, endIndex - startIndex); + + // Now assign this define + CSymbol* pSymbol = new CSymbol; + if (pSymbol != NULL) + { + pSymbol->m_Name = def; + pSymbol->m_Line = -1; + pSymbol->m_SymType = SYM_DEFINE; + pSymbol->m_pRange = NULL; + pSymbol->m_FileIndex = -1; + + // Assign symbol to active segment + const char *pStr = (const char *) pSymbol->m_Name; + (*m_Symbols)[pStr] = pSymbol; + } + + // Update startIndex + startIndex = endIndex + 1; + if (startIndex >= len) + startIndex = -1; + while (startIndex > 0) + { + if (m_ExtDefines[startIndex] == ' ') + { + if (++startIndex >= len) + startIndex = -1; + } + else + break; + } + } +} + +/* +============================================================================ +This function is called to parse an input file. If there are no errors +during parsing, the routine calls the routines to assemlbe and generate +output files for .obj, .lst, .hex, etc. +============================================================================ +*/ void VTAssembler::Parse(MString filename) { int success = 1; - MString outfile; + int lastDirMark; + MString outfile, errMsg; MString temp; // Clean up the assembler files from previous assembler ResetContent(); + // Assign the file's directory for searching include files + lastDirMark = filename.ReverseFind('/'); + if (lastDirMark == -1) + lastDirMark = filename.ReverseFind('\\'); + if (lastDirMark != -1) + { + m_FileDir = filename.Left(lastDirMark + 1); + } + + // Assign external defines + ParseExternalDefines(); + // Try to assemble the file if (success = ParseASMFile(filename, this)) { + // Test if #ifdef stack is zero (mis-matched if / else / end + if (m_IfDepth != 0) + { + if (m_LastIfElseIsIf) + errMsg.Format("Error in line %d(%s): #ifdef without matching #endif", + m_Line, (const char *) m_Filenames[m_FileIndex]); + else + errMsg.Format("Error in line %d(%s): #else without matching #endif", + m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(errMsg); + } + // No parse errors! Try to assemble - if (success = Assemble()) + else if (success = Assemble()) { // Get Output filename temp = filename.Right(4); @@ -2971,90 +4168,335 @@ void VTAssembler::Parse(MString filename) CreateObjFile(outfile); // Generate a listing file if requested - CreateList(temp); + outfile = temp + (char *) ".lst"; + CreateList(outfile, filename); + + // Generate a hex file if requested + outfile = temp + (char *) ".hex"; + CreateHex(outfile); } } } -void VTAssembler::CreateList(MString& filename) +/* +============================================================================ +This function creates a listing file if one was requested. +============================================================================ +*/ +void VTAssembler::CreateList(MString& filename, MString& asmFilename) { - MString outfile; - FILE* fd; + MString outfile; + FILE* fd; + FILE* inFd; + int lineNo = 1; + int c; // Segment this line was found in + char * pRead; + char lineBuf[256]; + CInstruction* pInst; // Next instruction pointer + int firstInst; + CSegLines* pSegLines; // Pointer to the current SegLines object + int segLinesCnt; // Number of segLines objects + int segLines; // Index of active SegLines + CSegment* pSeg; + POSITION pos; + MString key; + + // Test if listing requested + if (!((m_AsmOptions.Find((char *) "-t") != -1) || (m_List))) + { + // No listing requested...return + return; + } - if ((m_AsmOptions.Find((char *) "-l") != -1) || (m_List)) + // Open the output listing file + if ((fd = fopen(filename, "wb+")) == NULL) + return; + + // Open the input file + if ((inFd = fopen(asmFilename, "rb")) == NULL) + { + // Unable to open input file + fclose(fd); + return; + } + + // Initialize the pInst m_Count and current pInst m_Index for each segment + segLinesCnt = m_SegLines.GetSize(); + pos = m_Segments.GetStartPosition(); + while (pos != NULL) + { + m_Segments.GetNextAssoc(pos, key, (VTObject *&) pSeg); + pSeg->m_Count = pSeg->m_Instructions->GetSize(); + pSeg->m_Index = 0; + } + + // Get the first SegLines object + segLines = 0; + pSegLines = (CSegLines *) m_SegLines[0]; + pSeg = pSegLines->pSegment; + + if (pSeg->m_Count != 0) + { + pInst = (CInstruction*) (*pSeg->m_Instructions)[0]; + while ((pInst != NULL) && (pInst->m_ID == INST_LABEL)) + { + if (++pSeg->m_Index < pSeg->m_Count) + pInst = (CInstruction *) (*pSeg->m_Instructions)[pSeg->m_Index]; + else + pInst = NULL; + } + } + else + pInst = NULL; + + // Read lines from the input file and locate them + while (TRUE) { - if ((strcmp(filename, ".asm") == 0) || (strcmp(filename, "a85") == 0)) + // Read the line from the file + pRead = fgets(lineBuf, sizeof(lineBuf), inFd); + if (pRead == NULL) + { + break; + } + + // If the line has a segment entry, then print the address and + // opcode / data information for this line + if ((pInst != NULL) && (pInst->m_Line == lineNo)) { - outfile = filename.Left(filename.GetLength()-4); + firstInst = TRUE; + while ((pInst != NULL) && (pInst->m_Line == lineNo)) + { + // Don't print the address if m_Bytes is -1 + if (pInst->m_Bytes != -1) + { + if (firstInst) + { + // Segment found. Print address + fprintf(fd, "%04X ", pInst->m_Address); + + // Print bytes on 1st line. Up to 4 bytes + for (int x = 0; x < 4; x++) + { + if (x < pInst->m_Bytes) + fprintf(fd, "%02X ", pSeg->m_AsmBytes + [pInst->m_Address + x]); + else + fprintf(fd, " "); + } + + // Write line to output file + fprintf(fd, " "); + fputs(lineBuf, fd); + } + else + { + // Segment found. Print address + fprintf(fd, "%04X ", pInst->m_Address); + + // Not the first instruction on this line. Just print the bytes + // Print bytes on 1st line. Up to 4 bytes + for (int x = 0; x < 4; x++) + { + if (x < pInst->m_Bytes) + fprintf(fd, "%02X ", pSeg->m_AsmBytes[pInst->m_Address + x]); + else + fprintf(fd, " "); + } + fprintf(fd, LINE_ENDING); + } + + // Print any remaining bytes (dw or db statement) + for (c = 4; c < pInst->m_Bytes; c+= 4) + { + if (pInst->m_ID == INST_FILL) + { + if (c == 4) + { + if (pInst->m_Bytes > 12) + { + fprintf(fd, "...%s", LINE_ENDING); + continue; + } + } + else if (c + 4 < pInst->m_Bytes) + continue; + } + + // Segment found. Print address + fprintf(fd, "%04X ", pInst->m_Address + c); + + // Not the first instruction on this line. Just print the bytes + // Print bytes on 1st line. Up to 4 bytes + for (int x = 0; x < 4; x++) + { + if (x + c < pInst->m_Bytes) + fprintf(fd, "%02X ", pSeg->m_AsmBytes[pInst->m_Address + x + c]); + else + fprintf(fd, " "); + } + fprintf(fd, LINE_ENDING); + } + + firstInst = FALSE; + } + else + { + // Write line to output file + fprintf(fd, " "); + fputs(lineBuf, fd); + } + + // Increment to next instruction for this segment + pSeg->m_Index++; + if (pSeg->m_Index < pSeg->m_Count) + { + pInst = (CInstruction*) (*pSeg->m_Instructions)[pSeg->m_Index]; + while ((pInst != NULL) && (pInst->m_ID == INST_LABEL)) + { + if (++pSeg->m_Index < pSeg->m_Count) + pInst = (CInstruction *) (*pSeg->m_Instructions)[pSeg->m_Index]; + else + pInst = NULL; + } + } + else + pInst = NULL; + } } else - outfile = filename; + { + // Write line to output file + fprintf(fd, " "); + fputs(lineBuf, fd); + } // Append .lst to filename outfile += (char *) ".lst"; - fd = fopen(outfile, "wb+"); - fclose(fd); + // Increment the line number + lineNo++; + + // Test if the new lineNo causes us to change to a new segment + if ((pSegLines->lastLine != -1) && (lineNo > pSegLines->lastLine)) + { + // Increment to the next m_Index in m_SegLines + if (++segLines >= segLinesCnt) + { + MString err; + err.Format("Error in line %d(%s): Internal parse error - Segment line mismatch", + lineNo, (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(err); + break; + } + + // Update pSegLines and pSeg plus pInst structures + pSegLines = (CSegLines *) m_SegLines[segLines]; + pSeg = pSegLines->pSegment; + + // Get the pInst for this module + if (pSeg->m_Index < pSeg->m_Count) + { + while ((pInst != NULL) && (pInst->m_ID == INST_LABEL)) + { + if (++pSeg->m_Index < pSeg->m_Count) + pInst = (CInstruction *) (*pSeg->m_Instructions)[pSeg->m_Index]; + else + pInst = NULL; + } + } + else + pInst = NULL; + } } + + /* Close the input and output file */ + fclose(fd); + fclose(inFd); } -void VTAssembler::CreateHex() +/* +============================================================================ +This function sets the type of project being built (.CO, ROM, BASIC, etc.) +============================================================================ +*/ +void VTAssembler::SetProjectType(int type) { + m_ProjectType = type; } /* -===================================================================== -Implement the CModule class. This class is used to keep track of -assembly segments that are broken down into modules. -===================================================================== +============================================================================ +This function creates an Intel HEX output file of the assembled file +============================================================================ */ -CModule::CModule() +void VTAssembler::CreateHex(MString& filename) { - int c; + unsigned short start, len; + MString outfile; + FILE* fd; + CSegment* pSeg; - for (c=0; c < 3; c++) + // Test if HEX output requested + if (!((m_AsmOptions.Find((char *) "-h") != -1) || (m_Hex))) + { + // No ASEG Hex output requested...return + return; + } + + if (m_ProjectType == VT_PROJ_TYPE_ROM) + { + start = 0; + len = 32768; + } + else { - m_Symbols[c] = new VTMapStringToOb; - m_Instructions[c] = new VTObArray; + start = 32768; + len = 16384; + } - m_Address[c] = 0; - m_Page[c] = 0; - m_UsedAddr[c] = 0; - m_UsedAddr[c] = new AddrRange; - m_ActiveAddr[c] = m_UsedAddr[c]; + // Open the output listing file + if ((fd = fopen(filename, "wb+")) == NULL) + return; - m_ActiveAddr[c]->address = 0; - m_ActiveAddr[c]->length = 0; - m_ActiveAddr[c]->pNext = 0; - m_ActiveAddr[c]->shidx = 0; - } + // Save the Intel Hex file + m_Segments.Lookup(".aseg", (VTObject *&) pSeg); + save_hex_file_buf((char *) pSeg->m_AsmBytes, start, start + len, fd); - m_ActiveSeg = 0; + fclose(fd); +} + +/* +===================================================================== +Implement the CModule class. This class is used to keep track of +assembly segments that are broken down into modules. +===================================================================== +*/ +CModule::CModule(const char *name) +{ + // Initialze the variables + m_Name = name; + m_Symbols = new VTMapStringToOb; } CModule::~CModule() { - int c; - AddrRange* pRange; - AddrRange* pNext; + CSymbol* pSymbol; + POSITION pos; + MString key; - for (c = 0; c < 3; c++) + // Delete symbols + pos = m_Symbols->GetStartPosition(); + while (pos != NULL) { - delete m_Symbols[c]; - delete m_Instructions[c]; - - pRange = m_UsedAddr[c]; - while (pRange != 0) - { - pNext = pRange->pNext; - delete pRange; - pRange = pNext; - } + m_Symbols->GetNextAssoc(pos, key, (VTObject *&) pSymbol); + delete pSymbol; } -} + m_Symbols->RemoveAll(); + delete m_Symbols; -IMPLEMENT_DYNCREATE(CInstruction, VTObject); -IMPLEMENT_DYNCREATE(CCondition, VTObject); + // Delete publics. The actual sybols are already deleted, so just the array + m_Publics.RemoveAll(); +} CInstruction::~CInstruction() { @@ -3148,7 +4590,7 @@ void VTAssembler::CalcIncludeDirs(void) return; // Copy path to a char array so we can tokenize - pStr = new char[m_IncludePath.GetLength()]; + pStr = new char[m_IncludePath.GetLength() + 1]; strcpy(pStr, (const char *) m_IncludePath); pToken = strtok(pStr, ",;"); @@ -3166,4 +4608,99 @@ void VTAssembler::CalcIncludeDirs(void) // Get next token pToken = strtok(NULL, ",;"); } + + delete pStr; +} + +CSegment::CSegment(const char *name, int type, CModule* initialMod) +{ + m_Name = name; + m_Type = type; + m_InitialMod = initialMod; + m_LastMod = initialMod; + m_InstIndex = 0; + m_Instructions = new VTObArray; + m_Address = 0; + m_UsedAddr = new AddrRange; + m_Index = m_Count = 0; + + // Initialize the active Addr range to the first in the list + m_ActiveAddr = m_UsedAddr; + m_ActiveAddr->address = 0; + m_ActiveAddr->length = 0; + m_ActiveAddr->pNext = 0; + m_ActiveAddr->shidx = 0; +} + +CSegment::~CSegment() +{ + int c, size; + CInstruction* pInst; + AddrRange* pRange; + AddrRange* pNext; + CRelocation* pReloc; + + // Delete the instructions + size = m_Instructions->GetSize(); + for (c = 0; c < size; c++) + { + pInst = (CInstruction *) (*m_Instructions)[c]; + delete pInst; + } + m_Instructions->RemoveAll(); + delete m_Instructions; + + // Delete tha used address range structs + pRange = m_UsedAddr; + while (pRange != 0) + { + pNext = pRange->pNext; + delete pRange; + pRange = pNext; + } + + // Delete the relocation objects + size = m_Reloc.GetSize(); + for (c = 0; c < size; c++) + { + pReloc = (CRelocation *) m_Reloc[c]; + delete pReloc; + } + m_Reloc.RemoveAll(); +} + +/* +============================================================================ +Implement the CInstruction object dynamic constructs +============================================================================ +*/ +IMPLEMENT_DYNCREATE(CInstruction, VTObject); +IMPLEMENT_DYNCREATE(CCondition, VTObject); +IMPLEMENT_DYNCREATE(CMacro, VTObject); + +CMacro::~CMacro() +{ + // Delete equation if we have one + if (m_DefList != 0) + { + int size = m_DefList->GetSize(); + for (int c = 0; c < size; c++) + { + CExpression* pExp = (CExpression *) m_DefList->GetAt(c); + delete pExp; + } + delete m_DefList; + } + + // Delete expression list if we have one + if (m_ParamList != 0) + { + int size = m_ParamList->GetSize(); + for (int c = 0; c < size; c++) + { + CExpression* pExp = (CExpression *) m_ParamList->GetAt(c); + delete pExp; + } + delete m_ParamList; + } } diff --git a/src/assemble.h b/src/assemble.h index c6e8164..d38472e 100644 --- a/src/assemble.h +++ b/src/assemble.h @@ -3,6 +3,7 @@ #include "vtobj.h" #include "rpn_eqn.h" +#include "a85parse.h" #include // Define values for opcodes @@ -95,34 +96,45 @@ #define OPCODE_JMP 87 #define OPCODE_RET 88 #define OPCODE_HLT 89 - -#define INST_ORG 90 -#define INST_DS 91 -#define INST_DB 92 -#define INST_DW 93 -#define INST_STKLN 94 -#define INST_END 95 -#define INST_PUBLIC 96 -#define INST_EXTERN 97 -#define INST_IF 98 -#define INST_ELSE 99 -#define INST_ENDIF 100 -#define INST_LINK 101 -#define INST_MACLIB 102 -#define INST_PAGE 103 -#define INST_SYM 104 -#define INST_LABEL 105 +#define OPCODE_RSTV 90 + +#define INST_ORG 91 +#define INST_DS 92 +#define INST_DB 93 +#define INST_DW 94 +#define INST_STKLN 95 +#define INST_END 96 +#define INST_PUBLIC 97 +#define INST_EXTERN 98 +#define INST_IF 99 +#define INST_ELSE 100 +#define INST_ENDIF 101 +#define INST_LINK 102 +#define INST_MACLIB 103 +#define INST_PAGE 104 +#define INST_SYM 105 +#define INST_LABEL 106 +#define INST_FILL 107 +#define INST_ENDIAN 108 +#define INST_ELIF 109 +#define INST_MODULE 110 +#define INST_DEFINE 111 +#define INST_UNDEFINE 112 +#define INST_MACRO 113 #define SYM_LABEL 1 #define SYM_EQUATE 2 #define SYM_SET 3 #define SYM_EXTERN 4 +#define SYM_DEFINE 5 +#define SYM_CSEG 0x0100 +#define SYM_DSEG 0x0200 #define SYM_8BIT 0x0400 #define SYM_16BIT 0x0800 #define SYM_PUBLIC 0x1000 -#define SYM_HASVALUE 0x8000 -#define SYM_ISEQ 0x4000 #define SYM_ISREG 0x2000 +#define SYM_ISEQ 0x4000 +#define SYM_HASVALUE 0x8000 #define OPCODE_NOARG 0 #define OPCODE_1REG 1 @@ -153,6 +165,13 @@ #define CSEG 1 #define DSEG 2 +#define VT_ISDIGIT(x) (((x) >= '0') && ((x) <= '9')) + +#ifdef WIN32 +#define LINE_ENDING "\r\n" +#else +#define LINE_ENDING "\n" +#endif // Support classes for VTAssembler objects... typedef struct sAddrRange { @@ -166,7 +185,7 @@ class CInstruction : public VTObject { public: CInstruction() { m_ID = 0; m_Line = -1; m_FileIndex = 0; m_Address = 0; - m_Operand1 = 0; m_Group = NULL; } + m_Operand1 = 0; m_Group = NULL; m_Bytes = 0; } ~CInstruction(); DECLARE_DYNCREATE(CInstruction); @@ -176,10 +195,47 @@ class CInstruction : public VTObject unsigned char m_FileIndex; unsigned short m_Address; long m_Line; + int m_Bytes; MString* m_Operand1; VTObject* m_Group; }; +class CModule : public VTObject +{ +public: + CModule(const char *name); + ~CModule(); + + MString m_Name; // Module name + MString m_Title; // Module title + + VTMapStringToOb* m_Symbols; // Array of Symbols for this module + VTObArray m_Publics; // Array of public symbols from this module +}; + +class CSegment : public VTObject +{ +public: + CSegment(const char *name, int type, CModule* pInitialMod); + ~CSegment(); + + MString m_Name; // Name of segment + CModule* m_InitialMod; // Initial module upon creation + CModule* m_LastMod; // Last active module + int m_Type; // ASEG, CSEG or DSEG type + int m_InstIndex; // Used for listing generation + int m_Page; + int m_Index; // Current index for listing + int m_Count; // Instruction count for listing + int m_sh_offset; // Offset in .obj file of segment name + VTObArray* m_Instructions; // Array of Instructions for each segment + unsigned short m_Address; // Address counter for each segment + VTObArray m_Reloc; + unsigned char m_AsmBytes[65536]; + AddrRange* m_UsedAddr; // List of used address ranges + AddrRange* m_ActiveAddr; // Pointer to active address range +}; + class CExpression : public VTObject { public: @@ -189,6 +245,20 @@ class CExpression : public VTObject CRpnEquation* m_Equation; }; +class CMacro : public VTObject +{ +public: + CMacro() { m_ParamList = 0; m_DefList = 0; } + ~CMacro(); + + DECLARE_DYNCREATE(CMacro); + + MString m_Name; + VTObArray* m_ParamList; + VTObArray* m_DefList; + MString m_DefString; +}; + class CExtern : public VTObject { public: @@ -221,7 +291,7 @@ class CRelocation : public VTObject CRelocation() { m_Address = 0; m_Segment = 0; m_pSourceRange = 0; m_pTargetRange = 0; }; unsigned short m_Address; - unsigned char m_Segment; + CSegment* m_Segment; AddrRange* m_pSourceRange; AddrRange* m_pTargetRange; }; @@ -229,7 +299,9 @@ class CRelocation : public VTObject class CSymbol : public VTObject { public: - CSymbol() { m_Line = -1; m_Value = -1; m_SymType = 0; m_Equation = 0; m_StrtabOffset = 0; } + CSymbol() { m_Line = -1; m_Value = -1; m_SymType = 0; m_Equation = NULL; + m_StrtabOffset = 0; m_Segment = NULL; m_FileIndex = -1; + m_pRange = NULL; m_Off8 = 0; m_Off16 = 0; } ~CSymbol() { if (m_Equation != 0) delete m_Equation; }; // Attributes @@ -238,6 +310,7 @@ class CSymbol : public VTObject CRpnEquation* m_Equation; long m_Line; long m_Value; + CSegment* m_Segment; unsigned short m_SymType; unsigned short m_FileIndex; long m_StrtabOffset; @@ -246,24 +319,17 @@ class CSymbol : public VTObject AddrRange* m_pRange; }; -class CModule : public VTObject +typedef void (*stdOutFunc_t)(void *pContext, const char *msg); + +class CSegLines : public VTObject { public: - CModule(); - ~CModule(); - - MString m_Name; // Module name - MString m_Title; // Module title - - int m_ActiveSeg; // Segment we are compiling into + CSegLines(CSegment* pSeg, int start) + { pSegment = pSeg, startLine = start, lastLine = -1; } - VTMapStringToOb* m_Symbols[3]; // Array of Symbols for each segment - VTObArray* m_Instructions[3]; // Array of Instructions for each segment - long m_Address[3]; // Address counter for each segment - int m_Page[3]; - - AddrRange* m_UsedAddr[3]; // List of used address ranges - AddrRange* m_ActiveAddr[3]; // Pointer to active address range + CSegment* pSegment; // Pointer to the segment + int startLine; // First line for this entry + int lastLine; // Last line for this entry }; class VTAssembler : public VTObject @@ -275,10 +341,14 @@ class VTAssembler : public VTObject // Define Preprocessor functions void preproc_endif(void); void preproc_ifndef(const char *name); - void preproc_ifdef(const char *name); + void preproc_if(void); + void preproc_elif(void); + void preproc_ifdef(const char *name, int negate = 0); void preproc_else(void); - void preproc_define(const char *name); + int preproc_error(const char *msg); + void preproc_define(); void preproc_undef(const char *name); + int preproc_macro(void); // Define Pragma functions void pragma_list(); @@ -287,19 +357,24 @@ class VTAssembler : public VTObject // Define directive functions void directive_set(const char *name); void directive_aseg(void); - void directive_cseg(int page); - void directive_dseg(int page); + void directive_cdseg(int seg, int page); void directive_ds(void); void directive_db(void); void directive_dw(void); + void directive_echo(void); + void directive_echo(const char *msg); + void directive_fill(void); + void directive_printf(const char *fmt); void directive_extern(void); + void directive_endian(int msbFirst); void directive_org(); void directive_public(void); void directive_name(const char *name); void directive_stkln(void); void directive_end(const char *name); - void directive_if(void); + void directive_if(int inst = INST_IF); void directive_else(void); + void directive_module(const char *name); void directive_endif(void); void directive_title(const char *name); void directive_link(const char *name); @@ -309,46 +384,59 @@ class VTAssembler : public VTObject void include(const char *filename); void equate(const char *name); - void label(const char *label); + void label(const char *label, int address = -1); void opcode_arg_0(int opcode); void opcode_arg_1reg(int opcode); void opcode_arg_imm(int opcode, char c); void opcode_arg_2reg(int opcode); void opcode_arg_1reg_equ8(int opcode); + void opcode_arg_1reg_equ16(int opcode); void opcode_arg_equ8(int opcode); void opcode_arg_equ16(int opcode); // Attributes // MString m_Filename; // Filename that design was parsed from + MString m_FileDir; FILE* m_fd; // File descriptor of open file int m_Line; + int m_LastLabelLine; // Line number of last label int m_FileIndex; + int m_ProjectType; + int m_LastIfElseLine; // Line number of last #if, #ifdef, IF, or else + int m_LastIfElseIsIf; // True if last was #if or #ifdef - VTMapStringToOb* m_Modules; // Map of CModules + VTMapStringToOb m_Modules; // Map of CModules + VTMapStringToOb m_Segments; // Map of CSegments CModule* m_ActiveMod; // Pointer to active CModule - AddrRange* m_ActiveAddr; // Pointer to active address range - + CSegment* m_ActiveSeg; // Active segment for assembly + AddrRange* m_ActiveAddr; // Pointer to active address range from segment + CSegLines* m_ActiveSegLines; // Active segment line tracker VTMapStringToOb* m_Symbols; // Array of Symbols VTObArray* m_Instructions; // Array of Instructions - unsigned short m_Address; + VTObArray m_Defines; // Array of preprocessor defines + + VTObArray m_SegLines; // Array of segment line objects + unsigned short m_Address; MStringArray m_Filenames; // Array of filenames parsed during assembly MString m_LastLabel; // Save value of last label parsed CSymbol* m_LastLabelSym; // Pointer to CSymbol object for last label int m_LastLabelAdded; + char m_LocalModuleChar; // Module local label starting character + stdOutFunc_t m_pStdoutFunc; // Standard out message routine + void* m_pStdoutContext; // Opaque context for stdout MStringArray m_Errors; // Array of error messages during parsing - unsigned char m_AsmBytes[3][65536]; - VTObArray m_Reloc[3]; VTObArray m_Externs; - VTObArray m_Publics[3]; // Array of public symbols for each segment VTMapStringToOb m_UndefSymbols; int m_List; // Create a list file? int m_Hex; // Create a HEX file? int m_DebugInfo; // Include debug info in .obj? + int m_MsbFirst; // Output WORDS MSB first instead of LSB MString m_IncludeName[32]; FILE* m_IncludeStack[32]; int m_IncludeIndex[32]; + a85parse_pcb_struct m_ParserPCBs[32]; int m_IncludeDepth; MString m_AsmOptions; // Assembler options MString m_IncludePath; @@ -365,14 +453,20 @@ class VTAssembler : public VTObject int reportError); int Assemble(); int GetValue(MString & string, int & value); + int LookupSymbol(MString& name, CSymbol *& symbol); + int LookupMacro(MString& name, CMacro *& macro); + CSymbol* LookupSymOtherModules(MString& name, CSegment** pSeg = NULL); void ResetContent(void); int CreateObjFile(const char *filename); - int InvalidRelocation(CRpnEquation* pEq, char &rel_mask); + int InvalidRelocation(CRpnEquation* pEq, char &rel_mask, CSegment *&pSeg); int EquationIsExtern(CRpnEquation* pEq, int size); void MakeBinary(int val, int length, MString& binary); - void CreateHex(); - void CreateList(MString& filename); + void CreateHex(MString& filename); + void CreateList(MString& filename, MString& asmFilename); void CalcIncludeDirs(); + void ParseExternalDefines(void); + void ActivateSegment(CSegment* pSeg); + CInstruction* AddInstruction(int opcode); // Public Access functions void Parse(MString filename); @@ -380,6 +474,8 @@ class VTAssembler : public VTObject void SetIncludeDirs(const MString& dirs); void SetDefines(const MString& defines); void SetRootPath(const MString& rootPath); + void SetProjectType(int type); + void SetStdoutFunction(void *pContext, stdOutFunc_t pFunc); const MStringArray& GetErrors() { return m_Errors; }; }; diff --git a/src/autofile.cpp b/src/autofile.cpp index be72113..6e3debd 100644 --- a/src/autofile.cpp +++ b/src/autofile.cpp @@ -34,6 +34,8 @@ #include #include +#include "FLU/Flu_File_Chooser.h" + #include #include #include @@ -171,7 +173,7 @@ name or autogenerated name. */ int VTAutoFile::PromptFilename() { - Fl_File_Chooser* fc; + Flu_File_Chooser* fc; char text[80]; while (1) @@ -184,8 +186,10 @@ int VTAutoFile::PromptFilename() if (m_Filename == "") m_Filename = "."; // Prompt the user with the filename & give a chance to change - fc = new Fl_File_Chooser((const char *) m_Filename, "*.*", + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser((const char *) m_Filename, "*.*", Fl_File_Chooser::CREATE, text); + fl_cursor(FL_CURSOR_DEFAULT); fc->show(); fc->value((const char *) m_Filename); diff --git a/src/chargen.cpp b/src/chargen.cpp index 2325256..be9bbfd 100644 --- a/src/chargen.cpp +++ b/src/chargen.cpp @@ -42,6 +42,8 @@ #include #include +#include "FLU/Flu_File_Chooser.h" + #include #include #include @@ -672,7 +674,7 @@ Load data from a file */ void VTCharacterGen::Load(void) { - Fl_File_Chooser* fc; + Flu_File_Chooser* fc; unsigned char data[12]; int index; @@ -681,7 +683,9 @@ void VTCharacterGen::Load(void) return; // Create a file chooser - fc = new Fl_File_Chooser(".", "*.fcr", 1, "Load FX-80 Character ROM"); + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser(".", "*.fcr", 1, "Load FX-80 Character ROM"); + fl_cursor(FL_CURSOR_DEFAULT); // Show the file dialog fc->show(); @@ -738,7 +742,7 @@ Save data to a file */ void VTCharacterGen::Save(int format) { - Fl_File_Chooser* fc; + Flu_File_Chooser* fc; unsigned char data[12]; int index, len, c; char ch; @@ -753,20 +757,26 @@ void VTCharacterGen::Save(int format) // Create a file chooser if (format == CHARGEN_FORMAT_BINARY) { - fc = new Fl_File_Chooser(".", "*.fcr", Fl_File_Chooser::CREATE, + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser(".", "*.fcr", Fl_File_Chooser::CREATE, "Save FX-80 Character ROM"); + fl_cursor(FL_CURSOR_DEFAULT); strcpy(ext, ".fcr"); } else if (format == CHARGEN_FORMAT_C) { - fc = new Fl_File_Chooser(".", "*.c", Fl_File_Chooser::CREATE, + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser(".", "*.c", Fl_File_Chooser::CREATE, "Save FX-80 Character ROM"); + fl_cursor(FL_CURSOR_DEFAULT); strcpy(ext, ".c"); } else if (format == CHARGEN_FORMAT_BASIC) { - fc = new Fl_File_Chooser(".", "*.BA", Fl_File_Chooser::CREATE, + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser(".", "*.BA", Fl_File_Chooser::CREATE, "Save FX-80 Character ROM"); + fl_cursor(FL_CURSOR_DEFAULT); strcpy(ext, ".ba"); } diff --git a/src/clock.cpp b/src/clock.cpp index 30f3e73..644b572 100644 --- a/src/clock.cpp +++ b/src/clock.cpp @@ -61,7 +61,7 @@ uchar clock_sr_index = 0; int gClockTimingMode; int gTimeElapse; int gReload; -clock_ctrl_t gClockCtrl; +vt_clock_ctrl_t gClockCtrl; extern RomDescription_t *gStdRomDesc; extern Fl_Preferences virtualt_prefs; @@ -453,6 +453,9 @@ time_t convert_ctime(char* stime) tm_time.tm_sec = atoi(&stime[17]); // Convert seconds tm_time.tm_year = atoi(&stime[20]); // Convert year tm_time.tm_year -= 1900; + tm_time.tm_wday = 0; + tm_time.tm_yday = 1; + tm_time.tm_isdst = 0; // Convert to time_t format convTime = mktime(&tm_time); diff --git a/src/clock.h b/src/clock.h index b60b670..b1fedd6 100644 --- a/src/clock.h +++ b/src/clock.h @@ -59,7 +59,7 @@ typedef struct Fl_Round_Button* pEmulTime; Fl_Check_Button* pReload; Fl_Check_Button* pTimeElapse; -} clock_ctrl_t; +} vt_clock_ctrl_t; #define CLOCK_MODE_SYS 1 #define CLOCK_MODE_EMUL 2 diff --git a/src/cpu.h b/src/cpu.h index 274f7d8..16a1b07 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -47,7 +47,7 @@ extern "C" { #define OPTROMSIZE 32768 #define ADDRESSSPACE 65536 -extern uchar cpu[14]; +extern volatile uchar cpu[14]; extern uchar *gMemory[64]; extern int gRomSize; diff --git a/src/disassemble.cpp b/src/disassemble.cpp index 269ee48..13b8633 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -56,7 +56,7 @@ void cb_Ide(Fl_Widget* w, void*) ; Fl_Window *gpDis; // Callback routine for the close box of the Disassembler window -void close_cb(Fl_Widget* w, void*) +static void close_cb(Fl_Widget* w, void*) { if (gpDis != NULL) { @@ -213,6 +213,7 @@ void disassembler_cb(Fl_Widget* w, void*) { // Give the disassembler something to disassemble pDisassembler->CopyIntoMem(gSysROM, ROMSIZE); +// pDisassembler->CopyIntoMem((unsigned char*) gBaseMemory, 65536); gpDis->resizable(m); gpDis->resizable(td); @@ -370,7 +371,7 @@ void VTDis::Disassemble() { // Search for C in the function table x = 0; -/* while (m_pRom->pFuns[x].addr != -1) + while (m_pRom->pFuns[x].addr != -1) { if (m_pRom->pFuns[x].addr == c) { @@ -384,7 +385,7 @@ void VTDis::Disassemble() x++; } -*/ + // Check if address is a table instead of code x = 0; table = 0; diff --git a/src/display.cpp b/src/display.cpp index 7e232f7..983f2a6 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -40,8 +40,10 @@ //Added by J. VERNET for pref files // see also cb_xxxxxx #include +#include - +#include "FLU/Flu_Button.h" +#include "FLU/Flu_Return_Button.h" #include #include @@ -61,6 +63,7 @@ #include "fl_action_icon.h" #include "clock.h" #include "fileview.h" +#include "romstrings.h" //#include "tpddclient.h" extern "C" { @@ -76,6 +79,8 @@ extern RomDescription_t *gStdRomDesc; extern int gRomSize; extern int gMaintCount; extern int gOsDelay; +extern int gInMsPlanROM; +void set_target_frequency(int freq); } void cb_Ide(Fl_Widget* w, void*) ; @@ -99,17 +104,41 @@ int gRectsize = 2; int gXoffset; int gYoffset; int gSimKey = 0; +int gFrameColor = FL_BLACK; +int gDetailColor = FL_WHITE; +int gBackgroundColor = FL_GRAY; +int gPixelColor = FL_BLACK; +int gLabelColor = FL_WHITE; + +Fl_Double_Window* gDisplayColors; +Fl_Button* gLcdBkButton; +Fl_Button* gLcdPixelButton; +Fl_Button* gFrameButton; +Fl_Button* gDetailButton; +Fl_Button* gFkeyLabelsButton; + extern char* print_xpm[]; extern Fl_Menu_Item gPrintMenu[]; extern Fl_Pixmap gPrinterIcon; void switch_model(int model); +void key_delay(void); +int remote_load_from_host(const char *filename); + +#include "FLU/flu_pixmaps.h" +extern Fl_Pixmap littlehome, little_desktop, little_favorites, ram_drive; #ifndef WIN32 #define min(a,b) ((a)<(b) ? (a):(b)) #endif +#define VT_SPEED0_FREQ 2457600 +#define VT_SPEED1_FREQ 8000000 +#define VT_SPEED2_FREQ 20000000 +#define VT_SPEED3_FREQ 50000000 + + void setMonitorWindow(Fl_Window* pWin) { if (pWin == 0) @@ -196,18 +225,23 @@ void disassembler_cb(Fl_Widget* w, void*); void rspeed(Fl_Widget* w, void*) { - fullspeed=0; + fullspeed = 0; + set_target_frequency(VT_SPEED0_FREQ); gMaintCount = 4096; virtualt_prefs.set("fullspeed",0); } void fspeed(Fl_Widget* w, void*) { - fullspeed=3; -#ifdef WIN32 - gMaintCount = 300000; + fullspeed = 3; + set_target_frequency(VT_SPEED3_FREQ); +#ifdef WIN32 + gMaintCount = 100000; +/// gMaintCount = 4096; +#elif defined(__APPLE__) + gMaintCount = 65536; #else - gMaintCount = 131272; + gMaintCount = 131072; #endif virtualt_prefs.set("fullspeed",3); @@ -215,9 +249,11 @@ void fspeed(Fl_Widget* w, void*) void pf1speed(Fl_Widget* w, void*) { - fullspeed=1; + fullspeed = 1; + set_target_frequency(VT_SPEED1_FREQ); #ifdef WIN32 gMaintCount = 16384; +// gMaintCount = 4096; #else gMaintCount = 4096; #endif @@ -227,9 +263,11 @@ void pf1speed(Fl_Widget* w, void*) void pf2speed(Fl_Widget* w, void*) { - fullspeed=2; + fullspeed = 2; + set_target_frequency(VT_SPEED2_FREQ); #ifdef WIN32 gMaintCount = 100000; +// gMaintCount = 4096; #else gMaintCount = 16384; #endif @@ -257,9 +295,14 @@ resize_window: This function resizes the main window and repositions */ void resize_window() { +#ifdef WIN32 + int hiddenTaskBarAdjust = 0; +#endif + if (gpDisp == NULL) return; + /* Determine the height of the display based on model */ if (gModel == MODEL_T200) { gpDisp->DispHeight = 128; @@ -270,9 +313,20 @@ void resize_window() gpDisp->DispHeight = 64; DispHeight = 64; } + +#ifdef ZIPIT_Z2 + MainWin->fullscreen(); +#else if (Fullscreen) { MainWin->fullscreen(); +#ifdef WIN32 + int sx, sy, sw, sh; + Fl::screen_xywh(sx, sy, sw, sh); + if ((sh == 480) || (sh == 800) || (sh == 600) || (sh == 768) || (sh == 1024) || (sh == 1280)) + hiddenTaskBarAdjust = 4; + MainWin->resize(sx, sy, sw, sh - hiddenTaskBarAdjust); +#endif /* WIN32 */ MultFact = min(MainWin->w()/240, MainWin->h()/128); gpDisp->MultFact = MultFact; } @@ -288,6 +342,7 @@ void resize_window() 50*gpDisp->DisplayMode + MENU_HEIGHT + 22); } + /* Ensure the window isn't off the top of the screen */ if (MainWin->y() <= 0) { if (!Fullscreen) @@ -301,25 +356,31 @@ void resize_window() 90*gpDisp->DisplayMode+2,gpDisp->DispHeight*gpDisp->MultFact + 50*gpDisp->DisplayMode + MENU_HEIGHT + 22); } +#endif /* ZIPIT_Z2 */ Menu->resize(0, 0, MainWin->w(), MENU_HEIGHT-2); gpDisp->resize(0, MENU_HEIGHT, MainWin->w(), MainWin->h() - MENU_HEIGHT - 20); - gpGraph->resize(0, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + - 50*gpDisp->DisplayMode+2, 60, 20); - gpCode->resize(60, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + - 50*gpDisp->DisplayMode+2, 60, 20); - gpCaps->resize(120, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + - 50*gpDisp->DisplayMode+2, 60, 20); - gpKey->resize(180, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + - 50*gpDisp->DisplayMode+2, 120, 20); - gpSpeed->resize(300, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + - 50*gpDisp->DisplayMode+2, 60, 20); - gpMap->resize(360, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + - 50*gpDisp->DisplayMode+2, 60, 20); - gpPrint->resize(420, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + - 50*gpDisp->DisplayMode+2, 60, 20); - gpKeyInfo->resize(480, MENU_HEIGHT+gpDisp->DispHeight*gpDisp->MultFact + - 50*gpDisp->DisplayMode+2, MainWin->w()-480, 20); + int ctrlY = MainWin->h() - 20; + +#ifdef ZIPIT_Z2 + /* Running on Zipit Z2! Make the status items a bit smaller */ + gpGraph->resize(0, ctrlY, 60, 20); + gpCode->resize(60, ctrlY, 60, 20); + gpCaps->resize(-120, ctrlY, 60, 20); /* Remove this from display completely */ + gpKey->resize(-180, ctrlY, 120, 20); /* Remove this from display completely */ + gpSpeed->resize(120, ctrlY, 60, 20); + gpMap->resize(180, ctrlY, 60, 20); + gpPrint->resize(240, ctrlY, 60, 20); + gpKeyInfo->resize(-480, ctrlY, MainWin->w()-480, 20); +#else + gpGraph->resize(0, ctrlY, 60, 20); + gpCode->resize(60, ctrlY, 60, 20); + gpCaps->resize(120, ctrlY, 60, 20); + gpKey->resize(180, ctrlY, 120, 20); + gpSpeed->resize(300, ctrlY, 60, 20); + gpMap->resize(360, ctrlY, 60, 20); + gpPrint->resize(420, ctrlY, 60, 20); + gpKeyInfo->resize(480, ctrlY, MainWin->w()-480, 20); if (gpDisp->MultFact < 3) { gpKeyInfo->label("F Keys"); @@ -330,22 +391,124 @@ void resize_window() gpKeyInfo->tooltip(""); gpKeyInfo->label("F9:Label F10:Print F11:Paste F12:Pause"); } +#endif /* ZIPIT_Z2 */ - gRectsize = MultFact - (1 - SolidChars); - if (gRectsize == 0) - gRectsize = 1; - gXoffset = 45*DisplayMode+1; - gYoffset = 25*DisplayMode + MENU_HEIGHT+1; - - gpDisp->gRectsize = gRectsize; - gpDisp->gXoffset = gXoffset; - gpDisp->gYoffset = gYoffset; + gpDisp->CalcScreenCoords(); Fl::check(); MainWin->redraw(); } -/* use this Function to display a pop up box */ +/* +======================================================= +Calculate the xoffset, yoffset, border locations, etc. +======================================================= +*/ +void T100_Disp::CalcScreenCoords(void) +{ + // Calculatet the pixel rectangle size + ::gRectsize = MultFact - (1 - SolidChars); + if (::gRectsize == 0) + ::gRectsize = 1; + + // Calculate xoffset and yoffset +#ifdef ZIPIT_Z2 + { + ::gXoffset = 0; + ::gYoffset = (MainWin->h() - MENU_HEIGHT - 20 - (int) (float) DispHeight * 1.3333) / 3 + MENU_HEIGHT+1; + } +#else + if (Fullscreen) + { + ::gXoffset = MainWin->w() / 2 - 120 * MultFact; + ::gYoffset = (MainWin->h() - MENU_HEIGHT - 20 - DispHeight * MultFact) / 3 + MENU_HEIGHT+1; + } + else + { + ::gXoffset = 45*DisplayMode+1; + ::gYoffset = 25*DisplayMode + MENU_HEIGHT+1; + } +#endif + + gRectsize = ::gRectsize; + gXoffset = ::gXoffset; + gYoffset = ::gYoffset; + + // If the display is framed, then calculate the frame coords + if (DisplayMode) + { + // Calculate the Bezel location + int wantedH = 20; + int wantedW = 40; +// int topH, bottomH, leftW, rightW; + int bottomSpace; + int rightSpace; + + // Calculate the top height of the Bezel + m_HasTopChassis = TRUE; + if (gYoffset-1 - MENU_HEIGHT-1 >= wantedH + 5) + m_BezelTopH = wantedH; + else + { + // Test if there's room for both Bezel and chassis detail + if (gYoffset > 6) + m_BezelTopH = gYoffset - MENU_HEIGHT - 1 - 6; + else + { + m_BezelTopH = gYoffset - MENU_HEIGHT - 1 - 1; + m_HasTopChassis = FALSE; + } + } + m_BezelTop = gYoffset - m_BezelTopH - 1; + + // Calculate the bottom height of the Bezel + m_BezelBottom = gYoffset + DispHeight * MultFact + 1; + bottomSpace = MainWin->h() - m_BezelBottom - 20; + m_HasBottomChassis = TRUE; + if (bottomSpace >= wantedH + 5) + m_BezelBottomH = wantedH; + else + { + m_BezelBottomH = bottomSpace; + m_HasBottomChassis = FALSE; + } + + // Calculate the left Bezel border width + m_HasLeftChassis = TRUE; + if (gXoffset-1 >= wantedW + 5) + m_BezelLeftW = wantedW; + else + { + // Test if there's room for Bezel plus chassis + if (gXoffset > 6) + m_BezelLeftW = gXoffset - 6; + else + { + m_BezelLeftW = gXoffset - 1; + m_HasLeftChassis = FALSE; + } + } + m_BezelLeft = gXoffset - m_BezelLeftW - 1; + + // Calculate the Bezel right width + m_BezelRight = gXoffset + 240 * MultFact + 1; + rightSpace = w() - m_BezelRight; + m_HasRightChassis = TRUE; + if (rightSpace >= wantedW + 5) + m_BezelRightW = wantedW; + else + { + // Test if there's room for Bezel plus chassis + if (rightSpace > 5) + m_BezelRightW = rightSpace - 5; + else + { + m_BezelRightW = rightSpace; + m_HasRightChassis = FALSE; + } + } + } +} void show_error (const char *st) { @@ -583,24 +746,227 @@ void cb_choosewkdir(Fl_Widget* w, void*) /* Choose the working directory (ROM, RAM Files... */ char *ret; - - ret=ChooseWorkDir(); - if(ret==NULL) exit(-1); - else - { - strcpy(path,ret); - //#ifdef __unix__ - //strcat(path,"/"); - //#else - //strcat(path,"\\"); - //#endif - virtualt_prefs.set("Path",path); - } - + /* Get working directory from chooser */ + ret=ChooseWorkDir(); + if(ret==NULL) + return; + else + { + strcpy(path,ret); + //#ifdef __unix__ + //strcat(path,"/"); + //#else + //strcat(path,"\\"); + //#endif + virtualt_prefs.set("Path",path); + } } //--JV #endif +/* +======================================================= +cb_frame_btn: Process the frame color button. +======================================================= +*/ +void cb_frame_btn (Fl_Widget* w, void*) +{ + gFrameButton->color(fl_show_colormap(gFrameButton->color())); +} + +/* +======================================================= +cb_detail_btn: Process the detail color button. +======================================================= +*/ +void cb_detail_btn (Fl_Widget* w, void*) +{ + gDetailButton->color(fl_show_colormap(gDetailButton->color())); +} + +/* +======================================================= +cb_background_btn: Process the background color button. +======================================================= +*/ +void cb_background_btn (Fl_Widget* w, void*) +{ + gLcdBkButton->color(fl_show_colormap(gLcdBkButton->color())); +} + +/* +======================================================= +cb_pixel_btn: Process the pixel color button. +======================================================= +*/ +void cb_pixels_btn (Fl_Widget* w, void*) +{ + gLcdPixelButton->color(fl_show_colormap(gLcdPixelButton->color())); +} + +/* +======================================================= +cb_fkey_labels_btn: Process the pixel color button. +======================================================= +*/ +void cb_fkey_labels_btn (Fl_Widget* w, void*) +{ + gFkeyLabelsButton->color(fl_show_colormap(gFkeyLabelsButton->color())); +} + +/* +======================================================= +cb_colors_ok_btn: Process the colors OK button. +======================================================= +*/ +void cb_colors_ok_btn (Fl_Widget* w, void*) +{ + if (gDisplayColors != NULL) + gDisplayColors->hide(); + + gFrameColor = gFrameButton->color(); + gDetailColor = gDetailButton->color(); + gBackgroundColor = gLcdBkButton->color(); + gPixelColor = gLcdPixelButton->color(); + gLabelColor = gFkeyLabelsButton->color(); + virtualt_prefs.set("BackgroundColor",gBackgroundColor); + virtualt_prefs.set("PixelColor",gPixelColor); + virtualt_prefs.set("FrameColor",gFrameColor); + virtualt_prefs.set("DetailColor",gDetailColor); + virtualt_prefs.set("LabelColor",gLabelColor); + + if (gpDisp != NULL) + { + gpDisp->m_BackgroundColor = gBackgroundColor; + gpDisp->m_PixelColor = gPixelColor; + gpDisp->m_FrameColor = gFrameColor; + gpDisp->m_DetailColor = gDetailColor; + gpDisp->m_LabelColor = gLabelColor; + gpDisp->redraw(); + } +} + +/* +======================================================= +cb_colors_cancel_btn: Process the colors Cancel button +======================================================= +*/ +void cb_colors_cancel_btn (Fl_Widget* w, void*) +{ + if (gDisplayColors != NULL) + gDisplayColors->hide(); + + if (gpDisp != NULL) + { + gpDisp->m_BackgroundColor = gBackgroundColor; + gpDisp->m_PixelColor = gPixelColor; + gpDisp->m_FrameColor = gFrameColor; + gpDisp->m_DetailColor = gDetailColor; + gpDisp->m_LabelColor = gLabelColor; + gpDisp->redraw(); + } +} + +/* +======================================================= +cb_colors_cancel_btn: Process the colors Cancel button +======================================================= +*/ +void cb_colors_preview_btn (Fl_Widget* w, void*) +{ + if (gpDisp != NULL) + { + gpDisp->m_BackgroundColor = gLcdBkButton->color(); + gpDisp->m_PixelColor = gLcdPixelButton->color(); + gpDisp->m_FrameColor = gFrameButton->color(); + gpDisp->m_DetailColor = gDetailButton->color(); + gpDisp->m_LabelColor = gFkeyLabelsButton->color(); + gpDisp->redraw(); + } +} +/* +======================================================= +cb_colors_defaults_btn: Process the default colors btn +======================================================= +*/ +void cb_colors_defaults_btn (Fl_Widget* w, void*) +{ + gLcdBkButton->color(FL_GRAY); + gLcdPixelButton->color(FL_BLACK); + gFrameButton->color(FL_BLACK); + gDetailButton->color(FL_WHITE); + gFkeyLabelsButton->color(FL_WHITE); + gLcdBkButton->redraw(); + gLcdPixelButton->redraw(); + gFrameButton->redraw(); + gDetailButton->redraw(); + gFkeyLabelsButton->redraw(); +} + +/* +======================================================= +cb_colors: This routine creates a dialog box for +selecting the main display colors. +======================================================= +*/ +void cb_display_colors (Fl_Widget* w, void*) +{ + gDisplayColors = new Fl_Double_Window(330, 170, "Display Colors"); + gDisplayColors->callback(cb_colors_cancel_btn); + + gDisplayColors->align(FL_ALIGN_TOP_LEFT); + + { Flu_Button* o = new Flu_Button(20, 130, 80, 25, "Cancel"); + o->callback((Fl_Callback*)cb_colors_cancel_btn); + } + { Flu_Button* o = new Flu_Button(120, 130, 80, 25, "Preview"); + o->callback((Fl_Callback*)cb_colors_preview_btn); + } + { Flu_Return_Button* o = new Flu_Return_Button(220, 130, 85, 25, "OK"); + o->callback((Fl_Callback*)cb_colors_ok_btn); + } + { Flu_Button* o = new Flu_Button(220, 60, 85, 25, "Defaults"); + o->callback((Fl_Callback*)cb_colors_defaults_btn); + } + + { Fl_Button* o = gLcdBkButton = new Fl_Button(30, 20, 15, 15, "LCD Background"); + o->callback((Fl_Callback*)cb_background_btn); + o->align(FL_ALIGN_RIGHT); + } + { Fl_Button* o = gLcdPixelButton = new Fl_Button(30, 40, 15, 15, "LCD Pixels"); + o->callback((Fl_Callback*)cb_pixels_btn); + o->align(FL_ALIGN_RIGHT); + } + { Fl_Button* o = gFrameButton = new Fl_Button(30, 60, 15, 15, "Bezel"); + o->callback((Fl_Callback*)cb_frame_btn); + o->align(FL_ALIGN_RIGHT); + } + { Fl_Button* o = gDetailButton = new Fl_Button(30, 80, 15, 15, "Chassis"); + o->callback((Fl_Callback*)cb_detail_btn); + o->align(FL_ALIGN_RIGHT); + } + { Fl_Button* o = gFkeyLabelsButton = new Fl_Button(30, 100, 15, 15, "FKey Labels"); + o->callback((Fl_Callback*)cb_fkey_labels_btn); + o->align(FL_ALIGN_RIGHT); + } + + gFrameButton->color(gFrameColor); + gDetailButton->color(gDetailColor); + gLcdBkButton->color(gBackgroundColor); + gLcdPixelButton->color(gPixelColor); + gFkeyLabelsButton->color(gLabelColor); + + gDisplayColors->set_modal(); + gDisplayColors->end(); + gDisplayColors->show(); + + while (gDisplayColors->visible()) + Fl::wait(); + + delete gDisplayColors; + gDisplayColors = NULL; +} + /* ======================================================= cb_help: This routine displays the Help Subsystem @@ -686,7 +1052,76 @@ void cb_about (Fl_Widget* w, void*) o->show(); } +/* +======================================================= +cb_select_copy: This routine handles the copy menu +item from the select menu +======================================================= +*/ +void cb_select_copy (Fl_Widget* w, void*) +{ + if (gpDisp != NULL) + { + gpDisp->m_SimulatedCtrl = TRUE; + gpDisp->WheelKey(FL_F + 5); + } +} + +/* +======================================================= +cb_select_cut: This routine handles the copy menu +item from the select menu +======================================================= +*/ +void cb_select_cut (Fl_Widget* w, void*) +{ + if (gpDisp != NULL) + { + gpDisp->m_SimulatedCtrl = TRUE; + gpDisp->WheelKey(FL_F + 6); + } +} + +/* +======================================================= +cb_select_cut: This routine handles the copy menu +item from the select menu +======================================================= +*/ +void cb_select_cancel (Fl_Widget* w, void*) +{ + if (gpDisp != NULL) + { + gpDisp->m_SimulatedCtrl = TRUE; + gpDisp->WheelKey(FL_Control_L); + gpDisp->WheelKey('c'); + } +} + +void cb_menu_fkey (Fl_Widget* w, void* key) +{ + int fkey = (int) key; + + if (gpDisp != NULL) + { + gpDisp->WheelKey(fkey); + } +} + +Fl_Menu_Item gCopyCutMenu[] = { + { " Copy ", 0, cb_select_copy, 0, 0 }, + { " Cut ", 0, cb_select_cut, 0, FL_MENU_DIVIDER }, + { " Cancel ", 0, cb_select_cancel, 0, 0 }, + { 0 } +}; +Fl_Menu_Item gLeftClickMenu[] = { + { " Paste ", 0, cb_menu_fkey, (void *) (FL_F + 11), FL_MENU_DIVIDER }, + { " Label ", 0, cb_menu_fkey, (void *) (FL_F + 9), 0 }, + { " Print ", 0, cb_menu_fkey, (void *) (FL_F + 10), 0 }, + { " Pause ", 0, cb_menu_fkey, (void *) (FL_F + 12), 0 }, + { 0 } +}; Fl_Menu_Item menuitems[] = { { "&File", 0, 0, 0, FL_SUBMENU }, @@ -727,7 +1162,8 @@ Fl_Menu_Item menuitems[] = { { "4x", 0, cb_4x, (void *) 4, FL_MENU_RADIO }, { "Fullscreen", 0, cb_fullscreen, (void *) 5, FL_MENU_RADIO | FL_MENU_DIVIDER}, { "Framed", 0, cb_framed, (void *) 1, FL_MENU_TOGGLE|FL_MENU_VALUE }, - { "Solid Chars", 0, cb_solidchars, (void *) 1, FL_MENU_TOGGLE}, + { "Solid Chars", 0, cb_solidchars, (void *) 1, FL_MENU_TOGGLE | FL_MENU_DIVIDER}, + { "Display Colors", 0, cb_display_colors, 0, 0 }, { 0 }, { "Peripheral Setup...", 0, cb_PeripheralSetup, 0, 0 }, #ifdef __APPLE__ @@ -749,15 +1185,18 @@ Fl_Menu_Item menuitems[] = { { "Memory Editor", 0, cb_MemoryEditor }, { "ReMem Configuration", 0, cb_RememCfg, 0, 0 }, { "Peripheral Devices", 0, cb_PeripheralDevices }, -// { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, cb_FileView }, + { "Socket Configuration", 0, cb_SocketSetup }, // { "TPDD Client", 0, cb_TpddClient }, { 0 }, - { "&Help", 0, 0, 0, FL_SUBMENU }, + { "&Help", 0, 0, 0, FL_SUBMENU}, // | FL_MENU_DIVIDER}, { "Help", 0, cb_help }, { "About VirtualT", 0, cb_about }, { 0 }, - +// { "HomeIcon", 0, 0, 0, 0 }, +// { "Icon2", 0, 0, 0, 0 }, +// { "Icon3", 0, 0, 0, 0 }, +// { "Icon4", 0, 0, 0, 0 }, { 0 } }; @@ -776,16 +1215,35 @@ void remote_set_speed(int speed) switch (fullspeed) { #ifdef WIN32 - case 0: gMaintCount = 4096; break; - case 1: gMaintCount = 16384; break; - case 2: gMaintCount = 100000; break; - case 3: gMaintCount = 300000; break; - default: gMaintCount = 4096; break; + case 0: + gMaintCount = 4096; + set_target_frequency(VT_SPEED0_FREQ); + break; + case 1: + set_target_frequency(VT_SPEED1_FREQ); + gMaintCount = 16384; + break; + case 2: + set_target_frequency(VT_SPEED2_FREQ); + gMaintCount = 100000; + break; + case 3: + set_target_frequency(VT_SPEED3_FREQ); + gMaintCount = 100000; + break; + default: + set_target_frequency(VT_SPEED0_FREQ); + gMaintCount = 4096; + break; #else case 0: gMaintCount = 4096; break; - case 1: gMaintCount = 4096; break; + case 1: gMaintCount = 8192; break; case 2: gMaintCount = 16384; break; - case 3: gMaintCount = 131272; break; +#ifdef __APPLE__ + case 3: gMaintCount = 65536; break; +#else + case 3: gMaintCount = 131072; break; +#endif default: gMaintCount = 4096; break; #endif } @@ -898,7 +1356,19 @@ void switch_model(int model) fileview_model_changed(); } - +/* +======================================================= +cb_select_cut: This routine handles the copy menu +item from the select menu +======================================================= +*/ +void cb_leftclick_cancel (Fl_Widget* w, void*) +{ + if (gpDisp != NULL) + { + gpDisp->take_focus(); + } +} /* ======================================================= @@ -908,25 +1378,64 @@ T100:Disp: This is the class construcor T100_Disp::T100_Disp(int x, int y, int w, int h) : Fl_Widget(x, y, w, h) { - int driver, c; + int driver, c; + + m_FrameColor = gFrameColor; + m_DetailColor = gDetailColor; + m_BackgroundColor = gBackgroundColor; + m_PixelColor = gPixelColor; + m_LabelColor = gLabelColor; + m_HaveMouse = FALSE; + m_Select = FALSE; + m_SelectComplete = FALSE; + m_SimulatedCtrl = FALSE; - for (driver = 0; driver < 10; driver++) - { - for (int c = 0; c < 256; c++) + for (driver = 0; driver < 10; driver++) + { + for (int c = 0; c < 256; c++) lcd[driver][c] = 0; - top_row[driver] = 0; - } - for (c = 0; c < 32; c++) + top_row[driver] = 0; + } + for (c = 0; c < 32; c++) m_simKeys[c] = 0; - m_MyFocus = 0; - m_DebugMonitor = 0; + m_MyFocus = 0; + m_DebugMonitor = 0; + +#ifdef ZIPIT_Z2 + MultFact = 1; + DisplayMode = 1; + SolidChars = 1; + DispHeight = 64; + gRectsize = 1; +#else + MultFact = 3; + DisplayMode = 1; + SolidChars = 0; + DispHeight = 64; + gRectsize = 2; +#endif /* ZIPIT_Z2 */ + + m_WheelKeyIn = 0; + m_WheelKeyOut = 0; + m_BezelTop = m_BezelLeft = m_BezelBottom = m_BezelRight = 0; + m_BezelTopH = m_BezelLeftW = m_BezelBottomH = m_BezelRightW = 0; + m_CopyCut = new Fl_Menu_Button(x, y, w, h, "Action"); + m_CopyCut->type(Fl_Menu_Button::POPUP123); + m_CopyCut->hide(); + m_CopyCut->callback(cb_select_cancel); + + m_LeftClick = new Fl_Menu_Button(x, y, w, h, "Action"); + m_LeftClick->menu(gLeftClickMenu); + m_LeftClick->type(0); + m_LeftClick->callback(cb_leftclick_cancel); + m_LeftClick->hide(); +} - MultFact = 3; - DisplayMode = 1; - SolidChars = 0; - DispHeight = 64; - gRectsize = 2; +T100_Disp::~T100_Disp() +{ + delete m_LeftClick; + delete m_CopyCut; } const T100_Disp& T100_Disp::operator=(const T100_Disp& srcDisp) @@ -956,13 +1465,20 @@ Command: This function processes commands sent to void T100_Disp::Command(int instruction, uchar data) { int driver = instruction; + int cmd = data & 0x3F; - if ((data & 0x3F) == 0x3E) + if (cmd == 0x3E) { if (top_row[driver] != data >> 6) damage(1, gXoffset, gYoffset, 240*MultFact, 64*MultFact); top_row[driver] = data >> 6; } + else if (cmd == 0x3B) + { + } + else if (cmd == 0x3C) + { + } } /* @@ -1008,10 +1524,15 @@ drawpixel: This routine is called by the system to draw a single // Draw the black pixels on the LCD __inline void T100_Disp::drawpixel(int x, int y, int color) { +#ifdef ZIPIT_Z2 + if (color) + fl_rectf(m_xCoord[x],m_yCoord[y], m_rectSize[x], m_rectSize[y]); +#else // Check if the pixel color is black and draw if it is if (color) fl_rectf(x*MultFact + gXoffset,y*MultFact + gYoffset, gRectsize, gRectsize); +#endif } /* @@ -1030,53 +1551,65 @@ void T100_Disp::draw_static() int num_labels; // Draw gray "screen" - fl_color(FL_GRAY); + fl_color(m_BackgroundColor); fl_rectf(x(),y(),w(),h()); /* Check if the user wants the display "framed" */ if (DisplayMode == 1) { // Color for outer border - fl_color(FL_WHITE); + fl_color(m_DetailColor); // Draw border along the top - fl_rectf(x(),y(),240*MultFact+92,5); + if (m_HasTopChassis) + fl_rectf(x(),y(),w(),m_BezelTop - MENU_HEIGHT - 1); // Draw border along the bottom - fl_rectf(x(),y()+DispHeight*MultFact+45,240*MultFact+92,5); + if (m_HasBottomChassis) + fl_rectf(x(),m_BezelBottom + m_BezelBottomH,w(),MainWin->h() - m_BezelBottom - m_BezelBottomH - 20); // Draw border along the left - fl_rectf(x(),y()+5,5,DispHeight*MultFact+42); + if (m_HasLeftChassis) + fl_rectf(x(),y(),m_BezelLeft,h()); // Draw border along the right - fl_rectf(x()+240*MultFact+87,y()+5,5,DispHeight*MultFact+42); + if (m_HasRightChassis) + fl_rectf(m_BezelRight + m_BezelRightW,y(),w()-m_BezelRight,h()); // Color for inner border - fl_color(FL_BLACK); + fl_color(m_FrameColor); // Draw border along the top - fl_rectf(x()+5,y()+5,240*MultFact+42,20); + if (m_BezelTopH > 0) + fl_rectf(m_BezelLeft,m_BezelTop,m_BezelRight - m_BezelLeft + m_BezelRightW,m_BezelTopH); // Draw border along the bottom - fl_rectf(x()+5,y()+DispHeight*MultFact+27,240*MultFact+82,20); + if (m_BezelBottomH > 0) + fl_rectf(m_BezelLeft,m_BezelBottom,m_BezelRight - m_BezelLeft + m_BezelRightW,m_BezelBottomH); // Draw border along the left - fl_rectf(x()+5,y()+5,40,DispHeight*MultFact+32); + if (m_BezelLeftW > 0) + fl_rectf(m_BezelLeft, m_BezelTop, m_BezelLeftW, m_BezelBottom - m_BezelTop + m_BezelBottomH); // Draw border along the right - fl_rectf(x()+240*MultFact+47,y()+5,40,DispHeight*MultFact+32); + if (m_BezelRightW > 0) + fl_rectf(m_BezelRight,m_BezelTop, m_BezelRightW, m_BezelBottom - m_BezelTop + m_BezelBottomH); - width = w() - 90; +#ifdef ZIPIT_Z2 + width = 320; +#else + width = 240 * MultFact; +#endif num_labels = gModel == MODEL_PC8201 ? 5 : 8; inc = width / num_labels; - start = 28 + width/16 + (4-MultFact)*2; - fl_color(FL_WHITE); + start = gXoffset + width/16 - 2 * (5- (MultFact > 5? 5 : MultFact)); + fl_color(m_LabelColor); fl_font(FL_COURIER,12); char text[3] = "F1"; // y_pos = h()+20; - y_pos = y()+DispHeight*MultFact+40; + y_pos = m_BezelBottom + 13; //y()+DispHeight*MultFact+40; xl_start = 2*MultFact; xl_end = 7*MultFact; @@ -1148,10 +1681,14 @@ void T100_Disp::draw() value = lcd[driver][row*64+col]; // Erase line so it is grey, then fill in with black where needed - fl_color(FL_GRAY); + fl_color(m_BackgroundColor); +#ifdef ZIPIT_Z2 + fl_rectf(m_xCoord[x],m_yCoord[y], m_rectSize[x],10+m_rectSize[y+8] == 2?0:1); +#else fl_rectf(x*MultFact + gXoffset,y*MultFact + gYoffset,gRectsize,8*MultFact); - fl_color(FL_BLACK); +#endif + fl_color(m_PixelColor); // Draw the black pixels drawpixel(x,y++, value&0x01); @@ -1167,6 +1704,12 @@ void T100_Disp::draw() } } +/* +================================================================================ +SetByte: Updates the LCD with a byte of data as written from the I/O + interface from the 8085. +================================================================================ +*/ void T100_Disp::SetByte(int driver, int col, uchar value) { int x; @@ -1199,10 +1742,10 @@ void T100_Disp::SetByte(int driver, int col, uchar value) // Set the display window()->make_current(); - fl_color(FL_GRAY); + fl_color(m_BackgroundColor); fl_rectf(x*MultFact + gXoffset, y*MultFact + gYoffset, gRectsize,MultFact<<3); - fl_color(FL_BLACK); + fl_color(m_PixelColor); // Draw each pixel of byte drawpixel(x,y++,value&0x01); @@ -1214,9 +1757,14 @@ void T100_Disp::SetByte(int driver, int col, uchar value) drawpixel(x,y++,(value&0x40)>>6); drawpixel(x,y++,(value&0x80)>>7); } -// read Pref File -// J. VERNET +/* +================================================================================ +init_pref: Reads Preferences File with all saved information. + + Initial implementation added by J. VERNET +================================================================================ +*/ void init_pref(void) { char option_name[32]; @@ -1228,6 +1776,11 @@ void init_pref(void) virtualt_prefs.get("BasicSaveMode",BasicSaveMode,0); virtualt_prefs.get("COSaveMode",COSaveMode,0); virtualt_prefs.get("Model",gModel, MODEL_M100); + virtualt_prefs.get("BackgroundColor",gBackgroundColor, FL_GRAY); + virtualt_prefs.get("PixelColor",gPixelColor, FL_BLACK); + virtualt_prefs.get("FrameColor",gFrameColor, FL_BLACK); + virtualt_prefs.get("DetailColor",gDetailColor, FL_WHITE); + virtualt_prefs.get("LabelColor",gLabelColor, FL_WHITE); Fullscreen = 0; if (MultFact == 5) @@ -1241,16 +1794,35 @@ void init_pref(void) switch (fullspeed) { #ifdef WIN32 - case 0: gMaintCount = 4096; break; - case 1: gMaintCount = 16384; break; - case 2: gMaintCount = 100000; break; - case 3: gMaintCount = 300000; break; - default: gMaintCount = 4096; break; + case 0: + set_target_frequency(VT_SPEED0_FREQ); + gMaintCount = 4096; + break; + case 1: + set_target_frequency(VT_SPEED1_FREQ); + gMaintCount = 16384; + break; + case 2: + set_target_frequency(VT_SPEED2_FREQ); + gMaintCount = 100000; + break; + case 3: + set_target_frequency(VT_SPEED3_FREQ); + gMaintCount = 100000; + break; + default: + set_target_frequency(VT_SPEED0_FREQ); + gMaintCount = 4096; + break; #else case 0: gMaintCount = 4096; break; - case 1: gMaintCount = 4096; break; + case 1: gMaintCount = 8192; break; case 2: gMaintCount = 16384; break; - case 3: gMaintCount = 131272; break; +#ifdef __APPLE__ + case 3: gMaintCount = 65536; break; +#else + case 3: gMaintCount = 131072; break; +#endif default: gMaintCount = 4096; break; #endif } @@ -1264,24 +1836,62 @@ void init_pref(void) strcpy(gsMenuROM, fl_filename_name(gsOptRomFile)); } } -// Create the main display window and all children (status, etc.) + +/* +================================================================================ +deinit_display: Hide and destroy the main window +================================================================================ +*/ +void deinit_display(void) +{ + if (MainWin != NULL) + { + MainWin->hide(); + delete MainWin; + MainWin = NULL; + } +} + +/* +================================================================================ +init_display: Creates the main display window and all children (status, etc.). + This routine takes into account the current model, display + size setting, and the platform (Zipit, etc.). +================================================================================ +*/ void init_display(void) { - int mIndex; - int i; + int mIndex; + int i; char temp[20]; +#ifdef WIN32 + int hiddenTaskBarAdjust = 0; +#endif + + Fl::visual(FL_DOUBLE|FL_INDEX); if (gModel == MODEL_T200) DispHeight = 128; else DispHeight = 64; +#ifdef ZIPIT_Z2 MainWin = new Fl_Window(240*MultFact + 90*DisplayMode+2,DispHeight*MultFact + 50*DisplayMode + MENU_HEIGHT + 22, "Virtual T"); + MainWin->fullscreen(); +#else /* ZIPIT_Z2 */ + MainWin = new Fl_Window(320, 240, "Virtual T"); // Check if we are running in full screen mode if (MultFact == 5) { MainWin->fullscreen(); +#ifdef WIN32 + int sx, sy, sw, sh; + Fl::screen_xywh(sx, sy, sw, sh); + if ((sh == 480) || (sh == 800) || (sh == 600) || (sh == 768) || (sh == 1024) || (sh == 1280)) + hiddenTaskBarAdjust = 4; + MainWin->resize(sx, sy, sw, sh-hiddenTaskBarAdjust); +#endif /* WIN32 */ MultFact = min(MainWin->w()/240, MainWin->h()/128); } else @@ -1291,6 +1901,7 @@ void init_display(void) 240*MultFact + 90*DisplayMode+2,DispHeight*MultFact + 50*DisplayMode + MENU_HEIGHT + 22); } +#endif /* ZIPIT_Z2 */ Menu = new Fl_Menu_Bar(0, 0, MainWin->w(), MENU_HEIGHT-2); if (gModel == MODEL_T200) @@ -1298,6 +1909,31 @@ void init_display(void) else gpDisp = new T100_Disp(0, MENU_HEIGHT, MainWin->w(), MainWin->h() - MENU_HEIGHT - 20); + int subMenuDepth = 0; + for (i = 0; ; i++) + { + if (menuitems[i].text != NULL) + { + if (strcmp(menuitems[i].text, "HomeIcon") == 0) + { + menuitems[i++].image(littlehome); + menuitems[i++].image(little_favorites); + menuitems[i++].image(little_desktop); + menuitems[i++].image(ram_drive); + break; + } + if (menuitems[i].flags & FL_SUBMENU) + subMenuDepth++; + } + else + { + if (subMenuDepth == 0) + break; + else + subMenuDepth--; + } + } + MainWin->callback(close_disp_cb); Menu->menu(menuitems); @@ -1328,9 +1964,12 @@ void init_display(void) mIndex++; mIndex--; + int mf = MultFact; + if (Fullscreen) + mf = 5; for(i=1;i<6;i++) { - if(i==MultFact) + if(i==mf) { if(i==5) menuitems[i+mIndex].flags=FL_MENU_RADIO | FL_MENU_VALUE | FL_MENU_DIVIDER; @@ -1385,7 +2024,7 @@ void init_display(void) mIndex = 0; while (menuitems[mIndex].callback_ != cb_solidchars) mIndex++; - menuitems[mIndex].flags=FL_MENU_TOGGLE|FL_MENU_VALUE; + menuitems[mIndex].flags=FL_MENU_TOGGLE|FL_MENU_VALUE|FL_MENU_DIVIDER; } /* @@ -1419,70 +2058,84 @@ void init_display(void) Create Status boxes for various things ======================================== */ - gpGraph = new Fl_Box(FL_DOWN_BOX,0, MENU_HEIGHT+DispHeight*MultFact + - 50*DisplayMode+2, 60, 20,"GRAPH"); + int ctrlY = MainWin->h() - 20; +#ifdef ZIPIT_Z2 + gpGraph = new Fl_Box(FL_DOWN_BOX,0, ctrlY, 60, 20,"GRAPH"); + gpCode = new Fl_Box(FL_DOWN_BOX,60, ctrlY, 60, 20,"CODE"); + gpCaps = new Fl_Box(FL_DOWN_BOX,-120, ctrlY, 60, 20,"CAPS"); + gpKey = new Fl_Box(FL_DOWN_BOX,-180, ctrlY, 120, 20,""); + gpSpeed = new Fl_Box(FL_DOWN_BOX,120, ctrlY, 60, 20,""); + gpMap = new Fl_Box(FL_DOWN_BOX,180, ctrlY, 60, 20,""); + gpPrint = new Fl_Action_Icon(240, ctrlY, 60, 20, "Print Menu"); +#else + gpGraph = new Fl_Box(FL_DOWN_BOX,0, ctrlY, 60, 20,"GRAPH"); + gpCode = new Fl_Box(FL_DOWN_BOX,60, ctrlY, 60, 20,"CODE"); + gpCaps = new Fl_Box(FL_DOWN_BOX,120, ctrlY, 60, 20,"CAPS"); + gpKey = new Fl_Box(FL_DOWN_BOX,180, ctrlY, 120, 20,""); + gpSpeed = new Fl_Box(FL_DOWN_BOX,300, ctrlY, 60, 20,""); + gpMap = new Fl_Box(FL_DOWN_BOX,360, ctrlY, 60, 20,""); + gpPrint = new Fl_Action_Icon(420, ctrlY, 60, 20, "Print Menu"); +#endif + + /* + ============================================= + Assign labels and label sizes to status boxes + ============================================= + */ gpGraph->labelsize(10); gpGraph->deactivate(); - gpCode = new Fl_Box(FL_DOWN_BOX,60, MENU_HEIGHT+DispHeight*MultFact + - 50*DisplayMode+2, 60, 20,"CODE"); gpCode->labelsize(10); gpCode->deactivate(); - gpCaps = new Fl_Box(FL_DOWN_BOX,120, MENU_HEIGHT+DispHeight*MultFact + - 50*DisplayMode+2, 60, 20,"CAPS"); gpCaps->labelsize(10); gpCaps->deactivate(); - gpKey = new Fl_Box(FL_DOWN_BOX,180, MENU_HEIGHT+DispHeight*MultFact + - 50*DisplayMode+2, 120, 20,""); gpKey->labelsize(10); - gpSpeed = new Fl_Box(FL_DOWN_BOX,300, MENU_HEIGHT+DispHeight*MultFact + - 50*DisplayMode+2, 60, 20,""); gpSpeed->labelsize(10); - gpMap = new Fl_Box(FL_DOWN_BOX,360, MENU_HEIGHT+DispHeight*MultFact + - 50*DisplayMode+2, 60, 20,""); gpMap->labelsize(10); - gpPrint = new Fl_Action_Icon(420, MENU_HEIGHT+DispHeight*MultFact + - 50*DisplayMode+2, 60, 20, "Print Menu"); gpPrint->align(FL_ALIGN_TOP | FL_ALIGN_INSIDE | FL_ALIGN_LEFT); gpPrint->set_image(&gPrinterIcon); gpPrint->menu(gPrintMenu); + +#ifdef ZIPIT_Z2 + gpKeyInfo = new Fl_Box(FL_DOWN_BOX,-480, ctrlY, 20, 20, ""); +#else if (MultFact < 3) { - gpKeyInfo = new Fl_Box(FL_DOWN_BOX,480, MENU_HEIGHT+DispHeight*MultFact + - 50*DisplayMode+2, MainWin->w()-480, 20, + gpKeyInfo = new Fl_Box(FL_DOWN_BOX,480, ctrlY, MainWin->w()-480, 20, "F Keys"); gpKeyInfo->tooltip("F9:Label F10:Print F11:Paste F12:Pause"); } else - gpKeyInfo = new Fl_Box(FL_DOWN_BOX,480, MENU_HEIGHT+DispHeight*MultFact + - 50*DisplayMode+2, MainWin->w()-480, 20, + gpKeyInfo = new Fl_Box(FL_DOWN_BOX,480, ctrlY, MainWin->w()-480, 20, "F9:Label F10:Print F11:Paste F12:Pause"); +#endif gpKeyInfo->labelsize(10); gSimKey = 0; - gXoffset = 45*DisplayMode+1; - gYoffset = 25*DisplayMode + MENU_HEIGHT+1; - gRectsize = MultFact - (1 - SolidChars); - if (gRectsize == 0) - gRectsize = 1; - if (gpDisp != 0) { gpDisp->DispHeight = DispHeight; gpDisp->DisplayMode = DisplayMode; gpDisp->MultFact = MultFact; gpDisp->SolidChars = SolidChars; - gpDisp->gRectsize = gRectsize; - gpDisp->gXoffset = gXoffset; - gpDisp->gYoffset = gYoffset; + gpDisp->CalcScreenCoords(); } /* End the Window and show it */ MainWin->end(); MainWin->show(); +#ifdef WIN32 + // On Win32 platforms, the show() routine causes the window to shrink. Reset it if fullscreen. + if (Fullscreen) + { + int sx, sy, sw, sh; + Fl::screen_xywh(sx, sy, sw, sh); + MainWin->resize(sx, sy, sw, sh - hiddenTaskBarAdjust); + } +#endif // Set the initial string for ReMem show_remem_mode(); - if (gReMem) + if (gReMem && !gRex) { // Check if ReMem is in "Normal" mode or MMU mode if (inport(REMEM_MODE_PORT) & 0x01) @@ -1508,8 +2161,41 @@ void init_display(void) } gpPrint->label("Idle"); + + /* + ===================================================================== + For Zipit Z2, create an array of x and y offsets plus pixel sizes for + "stretched" display mode. + ===================================================================== + */ +#ifdef ZIPIT_Z2 + int size = 1; + int x, m, cur; + + m = 0; + cur = 0; + for (x = 0; x <= 240; x++) + { + gpDisp->m_xCoord[x] = cur; + gpDisp->m_rectSize[x] = size; + gpDisp->m_yCoord[x] = cur + gYoffset; + cur += size; + if (++m == 3) + { + size = 1; + m = 0; + } + else if (m == 2) + size = 2; + } +#endif } +/* +================================================================================ +display_cpu_speed: Updates the emulated CPU speed status box. +================================================================================ +*/ static char label[40]; static char mapStr[40]; @@ -1566,8 +2252,8 @@ void process_windows_event() if (gOsDelay) #ifdef WIN32 Fl::wait(0.001); -#elif defined(__APPLE__) - Fl::check(); +//#elif defined(__APPLE__) +// Fl::check(); #else Fl::wait(0.00001); #endif @@ -1582,7 +2268,7 @@ void T100_Disp::PowerDown() { window()->make_current(); // Clear display - fl_color(FL_GRAY); + fl_color(m_BackgroundColor); if (DisplayMode == 1) fl_rectf(45,25+30,w()-90,h()-49); else @@ -1606,7 +2292,7 @@ void T100_Disp::PowerDown() lcd[driver][col] = 0; // Display first line of powerdown message - fl_color(FL_BLACK); + fl_color(m_PixelColor); col = 20 - strlen(msg) / 2; for (x = 0; x < (int) strlen(msg); x++) { @@ -1627,134 +2313,829 @@ void T100_Disp::PowerDown() col = 20 - strlen(msg2) / 2; for (x = 0; x < (int) strlen(msg2); x++) { - int mem_index = addr + (msg2[x] - ' ')*5; - column = col++ * 6; - for (int c = 0; c < 6; c++) + int mem_index = addr + (msg2[x] - ' ')*5; + column = col++ * 6; + for (int c = 0; c < 6; c++) + { + driver = column / 50 + 5; // 50 pixels per driver + if (c == 5) + SetByte(driver, (column % 50), 0); + else + SetByte(driver, (column % 50), gSysROM[mem_index++]); + column++; + } + } +} + +void simulate_keydown(int key) +{ + if (gpDisp == NULL) + return; + + gpDisp->SimulateKeydown(key); +} + +void simulate_keyup(int key) +{ + if (gpDisp == NULL) + return; + + gpDisp->SimulateKeyup(key); +} + +void handle_simkey(void) +{ + if (gpDisp == NULL) + return; + + if (gSimKey) + gpDisp->HandleSimkey(); +} + +void do_wheel_key(void*) +{ + if (gpDisp == NULL) + return; + + if (gSimKey) + gpDisp->HandleSimkey(); +} + +void T100_Disp::HandleSimkey(void) +{ + int simkey = gSimKey; + gSimKey = 0; + handle(simkey); +} + +/* +========================================================================== +siulate_keydown: Simulates an FL_KEYDOWN event +========================================================================== +*/ +void T100_Disp::SimulateKeydown(int key) +{ + int c; + + // Loop through array and check if key is already down + for (c = 0; c < 32; c++) + { + if (m_simKeys[c] == key) + break; + } + + // Test if key needs to be added to simKeys + if (c == 32) + { + // Find first non-zero entry + for (c = 0; c < 32; c++) + if (m_simKeys[c] == 0) + break; + if (c != 32) + m_simKeys[c] = key; + } + m_simEventKey = key; + gSimKey = VT_SIM_KEYDOWN; +} + +/* +========================================================================== +siulate_keyup: Simulates an FL_KEYUP event +========================================================================== +*/ +void T100_Disp::SimulateKeyup(int key) +{ + int c; + + // Loop through array and check if key is already down + for (c = 0; c < 32; c++) + { + if (m_simKeys[c] == key) + { + m_simKeys[c] = 0; + break; + } + } + + m_simEventKey = key; + gSimKey = VT_SIM_KEYUP; +} + +/* +========================================================================== +sim_get_key: Returns the key that caused the event +========================================================================== +*/ +int T100_Disp::sim_get_key(int key) +{ + int c; + + // Loop through array and check if key is already down + for (c = 0; c < 32; c++) + { + if (m_simKeys[c] == key) + return TRUE; + } + + return FALSE; +} + +/* +========================================================================== +sim_event_key: Returns the state of a simulated key +========================================================================== +*/ +int T100_Disp::sim_event_key(void) +{ + return m_simEventKey; +} + +/* +========================================================================== +Handle simulatged wheel keys (Function buttons, Enter, etc.) +========================================================================== +*/ +extern "C" +void handle_wheel_keys(void*) +{ + + // If no keys to process, just exit + if (gpDisp->m_WheelKeyIn == gpDisp->m_WheelKeyOut) + return; + + // If the key wasn't processed yet, just return + if (gDelayUpdateKeys) + { +// Fl::repeat_timeout(0.01, cb_mousewheel, key); + return; + } + + int which_key = gpDisp->m_WheelKeys[gpDisp->m_WheelKeyOut]; + if ((gpDisp->m_WheelKeyDown == VT_SIM_KEYDOWN) && (which_key != FL_Control_L)) + { + // Handle CTRL-key sequences + if (gpDisp->m_SimulatedCtrl) + { + gpDisp->SimulateKeyup(FL_Control_L); + gpDisp->m_SimulatedCtrl = FALSE; + gpDisp->HandleSimkey(); + } + gpDisp->SimulateKeyup(which_key); + gpDisp->m_WheelKeyDown = VT_SIM_KEYUP; + gpDisp->HandleSimkey(); +// Fl::repeat_timeout(0.01, cb_mousewheel, (void *)VT_SIM_KEYUP); + } + else + { + if (++gpDisp->m_WheelKeyOut >= 32) + gpDisp->m_WheelKeyOut = 0; + if (gpDisp->m_WheelKeyOut != gpDisp->m_WheelKeyIn) + { + gpDisp->SimulateKeydown(gpDisp->m_WheelKeys[gpDisp->m_WheelKeyOut]); + gpDisp->m_WheelKeyDown = VT_SIM_KEYDOWN; + gpDisp->HandleSimkey(); +// Fl::repeat_timeout(0.0, do_wheel_key, (void *)VT_SIM_KEYDOWN); + } + } +} + +/* +========================================================================== +Simulate a keystroke as a result of Mouse events (Mouse wheel, clicks, etc) +========================================================================== +*/ +void T100_Disp::WheelKey(int key) +{ + int startTimer = m_WheelKeyIn == m_WheelKeyOut; + + // Add the wheel key event + m_WheelKeys[m_WheelKeyIn++] = key; + if (m_WheelKeyIn >= 32) + m_WheelKeyIn = 0; + + if (startTimer) + { + SimulateKeydown(key); + m_WheelKeyDown = VT_SIM_KEYDOWN; + handle(VT_SIM_KEYDOWN); +// Fl::add_timeout(0.01, cb_mousewheel, (void *)VT_SIM_KEYDOWN); + } +} + +/* +========================================================================== +Test if the emulation is currently in the MENU program or TS-DOS menu +========================================================================== +*/ +int T100_Disp::IsInMenu(void) +{ + int lines, c, first_line = 0; + unsigned short lcdAddr, curAddr; + char lcdStr[21]; + + lines = gModel == MODEL_T200 ? 16 : 8; + + // For Model 200, the 1st byte of the LCD character buffer isn't + // always the first row on the LCD. There is a 1st row offset + // variable at FEAEh that tells which row is the 1st row + if (gModel == MODEL_T200) + first_line = get_memory8(0xFEAE); + lcdAddr = gStdRomDesc->sLcdBuf; + + // Now loop through each row and build a string to send + curAddr = lcdAddr + first_line * 40; + + /* Test for TS-DOS menu */ + /* Get first 20 bytes from LCD to test for " BASIC TEXT " */ + for (c = 0; c < 9; c++) + lcdStr[c] = get_memory8(curAddr++); + lcdStr[c] = 0; + + if (strcmp(" TS-DOS (", lcdStr) == 0) + return 2; + + /* Skip to second line to test for main menu */ + curAddr = lcdAddr + first_line * 40 + 40; + unsigned short maxAddr = lcdAddr + lines * 40; + if (curAddr >= maxAddr) + curAddr = lcdAddr; + + /* Get first 20 bytes from LCD to test for " BASIC TEXT " */ + for (c = 0; c < 20; c++) + lcdStr[c] = get_memory8(curAddr++); + lcdStr[c] = 0; + + if (strcmp(" BASIC TEXT ", lcdStr) == 0) + return 1; + + return FALSE; +} + +/* +========================================================================== +Locate the specified address entry in the StdRom descriptor +========================================================================== +*/ +unsigned short find_stdrom_addr(int entry) +{ + int c; + + for (c = 0; ;c++) + { + // Test for end of table + if (gStdRomDesc->pVars[c].strnum == -1) + { + return 0; + } + + // Search for the Level 6 plotting function + if (gStdRomDesc->pVars[c].strnum == entry) + { + return gStdRomDesc->pVars[c].addr; + } + } + + return 0; +} + +/* +========================================================================== +Test if the emulation is currently in the TEXT program +========================================================================== +*/ +int T100_Disp::IsInText(void) +{ + int fkeyAddr, c, x, i; + char fkeyStr[41]; + + // Find the adress of the FKey label buffer + fkeyAddr = find_stdrom_addr(R_FKEY_DEF_BUF); + + // Read the Fkey labels + for (c = 0, i = 0; i < 8; i++) + { + for (x = 0; x < 4; x++) { - driver = column / 50 + 5; // 50 pixels per driver - if (c == 5) - SetByte(driver, (column % 50), 0); - else - SetByte(driver, (column % 50), gSysROM[mem_index++]); - column++; + fkeyStr[c] = get_memory8(fkeyAddr++); + if (fkeyStr[c] < 'A') + fkeyStr[c] = ' '; + c++; } + fkeyStr[c++] = ' '; + fkeyAddr += 12; } + + // Test for TEXT "FIND" label + if (strncmp(fkeyStr, "Find Load", 9) == 0) + return 1; + if (strncmp(fkeyStr, "Find Edit", 19) == 0) + return 1; + if (strncmp(fkeyStr, "Find Next", 9) == 0) + return 1; + return 0; } -void simulate_keydown(int key) +/* +========================================================================== +Waits for the selection to be complete and pops up the action menu +========================================================================== +*/ +void cb_await_selection_complete(void *pContext) { - if (gpDisp == NULL) + if (!gpDisp->m_SelectComplete) + { + Fl::repeat_timeout(0.02, cb_await_selection_complete, NULL); return; + } - gpDisp->SimulateKeydown(key); + gpDisp->m_CopyCut->menu(gCopyCutMenu); + gpDisp->m_CopyCut->type(Fl_Menu_Button::POPUP123); + if (gpDisp->m_CopyCut->popup() == NULL) + cb_select_cancel(gpDisp, NULL); + gpDisp->m_CopyCut->type(0); } -void simulate_keyup(int key) +/* +========================================================================== +Adds a short delay after a selection to allow the display to update. +========================================================================== +*/ +void cb_select_delay(void *pContext) { - if (gpDisp == NULL) - return; - - gpDisp->SimulateKeyup(key); + gpDisp->m_SelectComplete = TRUE; } -void handle_simkey(void) +/* +========================================================================== +Process word selection logic after the timeout for display update +========================================================================== +*/ +typedef struct { - if (gpDisp == NULL) + unsigned short addr; + char col; + char row; + char delay; +} WordSel_t; + +void cb_wordsel(void *pContext) +{ + WordSel_t *pWordSel = (WordSel_t *) pContext; + + if (gpDisp->m_WheelKeyIn != gpDisp->m_WheelKeyOut) + { + Fl::repeat_timeout(0.02, cb_wordsel, pContext); return; + } - if (gSimKey) - gpDisp->HandleSimkey(); + if (pWordSel->delay) + { + Fl::repeat_timeout(0.2 / (fullspeed + 1), cb_wordsel, pContext); + pWordSel->delay = 0; + return; + } + // Set the new col based on if the column is zero or not + if (pWordSel->col == 0) + { + set_memory8(pWordSel->addr, pWordSel->col + 1); + gpDisp->WheelKey(FL_Left); + } + else + { + set_memory8(pWordSel->addr, pWordSel->col - 1); + gpDisp->WheelKey(FL_Right); + } + + Fl::add_timeout(0.2 / (fullspeed + 1), cb_select_delay); + delete (char *) pContext; } -void T100_Disp::HandleSimkey(void) +void cb_dragsel(void *pContext) { - int simkey = gSimKey; - gSimKey = 0; - handle(simkey); + unsigned short cursorRow; + WordSel_t *pWordSel = (WordSel_t *) pContext; + + // Test if this dragsel object is still valid. If a later dragsel was queued, then + // The position won't match any longer + if (pWordSel->row * 40 + pWordSel->col != gpDisp->m_LastPos) + { + delete pWordSel; + return; + } + + // Test if the simulated keystroke buffer is empty + if (gpDisp->m_WheelKeyIn != gpDisp->m_WheelKeyOut) + { + Fl::repeat_timeout(0.02, cb_dragsel, pContext); + return; + } + + // Delay to allow time for the emulation to perform highlighting + if (pWordSel->delay) + { + Fl::repeat_timeout(0.2 / (fullspeed + 1), cb_dragsel, pContext); + pWordSel->delay = 0; + return; + } + + int lines = gModel == MODEL_T200 ? 16 : 8; + cursorRow = find_stdrom_addr(R_CURSOR_ROW); + int row = pWordSel->row; + if (row < 1) + row = 1; + if (row > lines) + row = lines; + set_memory8(cursorRow, row); + + // Set the new col based on if the column is zero or not + if (pWordSel->col == 0) + { + set_memory8(pWordSel->addr, pWordSel->col + 1); + gpDisp->WheelKey(FL_Left); + } + else + { + set_memory8(pWordSel->addr, pWordSel->col - 1); + gpDisp->WheelKey(FL_Right); + } + + // Test for scroll up + if (pWordSel->row < 1) + gpDisp->WheelKey(FL_Up); + if (pWordSel->row > lines) + gpDisp->WheelKey(FL_Down); + + Fl::add_timeout(0.2 / (fullspeed + 1), cb_select_delay); + delete (char *) pContext; } /* ========================================================================== -siulate_keydown: Simulates an FL_KEYDOWN event +Process mouse click events while the MsPlan ROM is active ========================================================================== */ -void T100_Disp::SimulateKeydown(int key) +int T100_Disp::ButtonClickInText(int mx, int my) { - int c; + int cursorRow, cursorCol; + int newRow, newCol; - // Loop through array and check if key is already down - for (c = 0; c < 32; c++) + // Find address of cursor row and col + cursorRow = find_stdrom_addr(R_CURSOR_ROW); + cursorCol = find_stdrom_addr(R_CURSOR_COL); + + // Calculate new row and col + newCol = (mx - gXoffset) / MultFact / 6 + 1; + newRow = (my - gYoffset) / MultFact / 8 + 1; + m_LastPos = newRow * 40 + newCol; + + // Set the new row + set_memory8(cursorRow, newRow); + + if (Fl::event_clicks() == 0) { - if (m_simKeys[c] == key) - break; + m_Select = FALSE; + // Set the new col based on if the column is zero or not + if (newCol == 0) + { + set_memory8(cursorCol, newCol + 1); + WheelKey(FL_Left); + } + else + { + set_memory8(cursorCol, newCol - 1); + WheelKey(FL_Right); + } } - - // Test if key needs to be added to simKeys - if (c != 32) + else { - // Find first non-zero entry - for (c = 0; c < 32; c++) - if (m_simKeys[c] == 0) - break; - if (c != 32) - m_simKeys[c] = key; + // Double click in a TEXT document. Select the word + Fl::event_clicks(0); + m_Select = 2; + + // Get the address of the LCD buffer + int lines, first_line = 0; + unsigned short lcdAddr, curAddr; + + lines = gModel == MODEL_T200 ? 16 : 8; + + // For Model 200, the 1st byte of the LCD character buffer isn't + // always the first row on the LCD. There is a 1st row offset + // variable at FEAEh that tells which row is the 1st row + if (gModel == MODEL_T200) + first_line = get_memory8(0xFEAE); + lcdAddr = gStdRomDesc->sLcdBuf; + unsigned short maxAddr = lcdAddr + lines * 40; + curAddr = lcdAddr + first_line * 40; + curAddr += 40 * (newRow-1) + newCol - 1; + if (curAddr >= maxAddr) + curAddr -= lines * 40; + + // Read the character under the cursor + char ch = get_memory8(curAddr); + + // Read backward to find the first character of the word / whitespace + while (newCol > 1) + { + newCol--; + curAddr--; + char nextCh = get_memory8(curAddr); + if (ch == ' ') + { + // Group all whitespace togeher + if (nextCh != ' ') + { + newCol++; + curAddr++; + break; + } + } + else if (((ch < 'A') || (ch > 'z')) && (ch != '_')) + { + // Group all control symbols together + if ((nextCh == ' ') || ((nextCh >= 'A') && (nextCh <= 'z'))) + { + newCol++; + curAddr++; + break; + } + } + else + { + if (((nextCh < 'A') || (nextCh > 'z')) && (nextCh != '_')) + { + newCol++; + curAddr++; + break; + } + } + } + if (newCol == 0) + { + set_memory8(cursorCol, newCol + 1); + WheelKey(FL_Left); + } + else + { + set_memory8(cursorCol, newCol - 1); + WheelKey(FL_Right); + } + + // Now send the key for 'Sel' + WheelKey(FL_F + 7); + + // Now find the end of the word + while (newCol <= 40) + { + newCol++; + curAddr++; + char nextCh = get_memory8(curAddr); +// WheelKey(FL_Right); + if (ch == ' ') + { + // Group all whitespace togeher + if (nextCh != ' ') + break; + } + else if (((ch < 'A') || (ch > 'z')) && (ch != '_')) + { + // Group all control symbols together + if ((nextCh == ' ') || ((nextCh >= 'A') && (nextCh <= 'z'))) + break; + } + else + { + if (((nextCh < 'A') || (nextCh > 'z')) && (nextCh != '_')) + break; + } + } + WordSel_t* pSelWord = new WordSel_t; + pSelWord->addr = cursorCol; + pSelWord->col = newCol; + pSelWord->row = newRow; + pSelWord->delay = 1; + m_SelectComplete = FALSE; + Fl::add_timeout(0.08, cb_wordsel, pSelWord); } - m_simEventKey = key; - gSimKey = VT_SIM_KEYDOWN; + return 1; } /* ========================================================================== -siulate_keyup: Simulates an FL_KEYUP event +Process mouse click events while the MsPlan ROM is active ========================================================================== */ -void T100_Disp::SimulateKeyup(int key) +int T100_Disp::ButtonClickInMsPlan(int mx, int my) { - int c; + int lines, first_line = 0; + unsigned short lcdAddr, curAddr; - // Loop through array and check if key is already down - for (c = 0; c < 32; c++) + lines = gModel == MODEL_T200 ? 16 : 8; + + // For Model 200, the 1st byte of the LCD character buffer isn't + // always the first row on the LCD. There is a 1st row offset + // variable at FEAEh that tells which row is the 1st row + if (gModel == MODEL_T200) + first_line = get_memory8(0xFEAE); + lcdAddr = gStdRomDesc->sLcdBuf; + + // Now loop through each row and build a string to send + curAddr = lcdAddr + first_line * 40; + + // Point to last line + curAddr += 40 * (lines - 1); + unsigned short maxAddr = lcdAddr + lines * 40; + if (curAddr >= maxAddr) + curAddr -= lines * 40; + + // Point to 2nd column to test for digit + curAddr++; + int ch = get_memory8(curAddr); + int labelActive = TRUE; + if ((ch >= '0') && (ch <= '9')) + labelActive = FALSE; + + // Now perform click processing base on labelActive + if (labelActive && (my > gYoffset + (lines - 1) * 8 * MultFact)) { - if (m_simKeys[c] == key) + int num_labels = gModel == MODEL_PC8201 ? 5 : 8; + int pixPerLabel = 240 / num_labels; + int fk = (mx - gXoffset) / MultFact / pixPerLabel + 1; + WheelKey(FL_F + fk); + Fl::event_clicks(0); + } + else + { + int topCell = get_memory8(0xEB58); + int leftCell = get_memory8(0xEB5A); + int curCellX = get_memory8(0xE910); + int curCellY = get_memory8(0xE90E); + int cellWidth = get_memory8(0xE920); + int charX = (mx - gXoffset) / MultFact / 6; + int charY = (my- gYoffset) / MultFact / 8; + + if (cellWidth == 0) + cellWidth = 9; + int targetCellX = leftCell + (charX - 3) / cellWidth; + int targetCellY = topCell + charY - 1; + while (targetCellX > curCellX) { - m_simKeys[c] = 0; - break; + WheelKey(FL_Right); + curCellX++; + } + while (targetCellX < curCellX) + { + WheelKey(FL_Left); + curCellX--; + } + while (targetCellY > curCellY) + { + WheelKey(FL_Down); + curCellY++; + } + while (targetCellY < curCellY) + { + WheelKey(FL_Up); + curCellY--; } } - m_simEventKey = key; - gSimKey = VT_SIM_KEYUP; + return 1; } /* ========================================================================== -sim_get_key: Returns the key that caused the event +Process mouse click events while the MENU program is active ========================================================================== */ -int T100_Disp::sim_get_key(int key) +int T100_Disp::ButtonClickInMenu(int mx, int my) { - int c; + int lineHeight = MultFact * 8; + int charWidth = MultFact * 6; + int lines = gModel == MODEL_T200 ? 16 : 8; - // Loop through array and check if key is already down - for (c = 0; c < 32; c++) + // Determine which menu item was selected + if ((my > gYoffset + lineHeight) && (my <= gYoffset + lineHeight * (lines - 2))) { - if (m_simKeys[c] == key) - return TRUE; + int row = (my - gYoffset - lineHeight) / lineHeight; + int col = (mx - gXoffset) / (charWidth * 10); + int entry = row * 4 + col; + + // Test if this entry is larger than + int maxEntryAddr = find_stdrom_addr(R_MAX_MENU_DIR_LOC); + int curEntryAddr = find_stdrom_addr(R_CUR_MENU_DIR_LOC); + if ((maxEntryAddr != 0) && (curEntryAddr != 0)) + { + // Read the max and current menu entries + int maxEntry = get_memory8(maxEntryAddr); + int curEntry = get_memory8(curEntryAddr); + + // Test if clicked on current item and start drag-n-drop + if (curEntry == entry) + { +// Fl::copy("c:\test.do", 11, 1); +// Fl::dnd(); + } + + // Test if entry is a valid file + else if (entry <= maxEntry) + { + if (m_WheelKeyIn != m_WheelKeyOut) + { + m_WheelKeyIn = m_WheelKeyOut; + if (m_WheelKeyIn >= 32) + m_WheelKeyIn = 0; + } + // Send keystrokes to get to the entry + int curRow = curEntry / 4; + int curCol = curEntry - curRow * 4; + while (row < curRow) + { + WheelKey(FL_Up); + curRow--; + } + while (col < curCol) + { + WheelKey(FL_Left); + curCol--; + } + while (row > curRow) + { + WheelKey(FL_Down); + curRow++; + } + while (col > curCol) + { + WheelKey(FL_Right); + curCol++; + } + } + } } - return FALSE; + return 1; } /* ========================================================================== -sim_event_key: Returns the state of a simulated key +Handle the mouse movement while emulation is in TEXT program. Performs +drag selection and word drag selection. ========================================================================== */ -int T100_Disp::sim_event_key(void) +int T100_Disp::MouseMoveInText(int mx, int my) { - return m_simEventKey; + int lines = gModel == MODEL_T200 ? 16 : 8; + int cursorRow, cursorCol; + int newCol, newRow, pos; + + // Calculate new row and col + newCol = (mx - gXoffset) / MultFact / 6 + 1; + newRow = (my - gYoffset) / MultFact / 8 + 1; + if (newCol < 1) + newCol = 1; + if (newCol > 40) + newCol = 40; + + pos = newRow * 40 + newCol; + // Find address of cursor row and col + cursorRow = find_stdrom_addr(R_CURSOR_ROW); + cursorCol = find_stdrom_addr(R_CURSOR_COL); + + // Test if the cursor changed positions + if (pos != m_LastPos) + { + m_LastPos = pos; + + // If a selection wasn't started yet, then start it now + if (!m_Select) + { + // Simulate an F7 keystroke to start selection + WheelKey(FL_F + 7); + m_Select = 1; + } + + // Test if select mode is word select + if (m_Select == 2) + { + } + + // Test if we are in word select mode and update new selection based on this + WordSel_t* pSelWord = new WordSel_t; + pSelWord->addr = cursorCol; + pSelWord->col = newCol; + pSelWord->row = newRow; + pSelWord->delay = 1; + m_SelectComplete = FALSE; + Fl::add_timeout(0.04, cb_dragsel, pSelWord); + } + + return 1; } +/* +========================================================================== +Window handler for all events. +========================================================================== +*/ // Handle mouse events, key events, focus events, etc. char keylabel[128]; int T100_Disp::handle(int event) @@ -1772,6 +3153,7 @@ int T100_Disp::handle(int event) event_key = Fl::event_key; simulated = FALSE; + // Test for simulated key events if ((event == VT_SIM_KEYUP) || (event == VT_SIM_KEYDOWN)) { get_key = sim_get_key; @@ -1784,12 +3166,164 @@ int T100_Disp::handle(int event) event = FL_KEYDOWN; } + // Test for Mouse Wheel events + if (event == FL_MOUSEWHEEL) + { + int x = Fl::e_dx; + int y = Fl::e_dy; + + // Test for up arrow + if (((gSpecialKeys & (MT_GRAPH | MT_CODE)) != (MT_GRAPH | MT_CODE)) || IsInMenu()) + { + if (y < 0) + WheelKey(FL_Left); + else if (y > 0) + // Must be down arrow + WheelKey(FL_Right); + } + else + { + if (y < 0) + WheelKey(FL_Up); + else if (y > 0) + // Must be down arrow + WheelKey(FL_Down); + } + if (x < 0) + WheelKey(FL_Left); + else if (x > 0) + WheelKey(FL_Right); + return 1; + } + switch (event) { + case FL_DND_DRAG: + case FL_DND_ENTER: + case FL_DND_RELEASE: + return 1; + case FL_PASTE: + printf("PASTE: %s", Fl::event_text()); + if (IsInMenu() == 1) + remote_load_from_host(Fl::event_text()); + return 1; case FL_FOCUS: m_MyFocus = 1; break; + + case FL_ENTER: + case FL_LEAVE: + return 1; + + case FL_DRAG: + if (m_HaveMouse) + { + int mx = Fl::event_x(); + int my = Fl::event_y(); + + if (IsInText()) + MouseMoveInText(mx, my); + + } + break; + + case FL_RELEASE: + // If text was selected, then popup the menu for copy/cut + if (m_Select) + { + if (m_WheelKeyIn == m_WheelKeyOut) + Fl::add_timeout(0.02, cb_await_selection_complete, NULL); + } + + if (!Fl::event_clicks()) + m_Select = FALSE; + m_HaveMouse = FALSE; + Fl::release(); + break; + case FL_PUSH: + Fl::grab(); + m_HaveMouse = TRUE; + if (Fl::event_button3()) + { + m_LeftClick->type(Fl_Menu_Button::POPUP123); + m_LeftClick->popup(); + m_LeftClick->type(0); + take_focus(); + return 1; + } + + if (m_MyFocus == 1) + { + int mx = Fl::event_x(); + int my = Fl::event_y(); + int wx = x(); + int wy = y(); + int procFkey = FALSE; + int whichMenu; + if ((mx >= m_BezelLeft + m_BezelLeftW) && (mx <= m_BezelRight) && + (my >= m_BezelTop + m_BezelTopH) && (my <= m_BezelBottom)) + { + if (Fl::event_clicks()) + { + if (IsInMenu()) + { + WheelKey(FL_Enter); + Fl::event_clicks(0); + m_Select = FALSE; + return 1; + } + } + // Test if we are in the menu + if (whichMenu = IsInMenu()) + { + m_Select = FALSE; + // Test if mouse is in FKey area + if (my >= m_BezelBottom - 1 - 8 * MultFact) + procFkey = TRUE; + else + { + if (whichMenu == 1) + { + return ButtonClickInMenu(mx, my); + } + } + } + else + { + if (gInMsPlanROM) + return ButtonClickInMsPlan(mx, my); + int labelEn = get_memory8(gStdRomDesc->sLabelEn); + if ((gStdRomDesc->sLabelEn && labelEn) && + (my >= m_BezelBottom - 1 - 8 * MultFact)) + { + procFkey = TRUE; + } + + // Test if emulation is in Text mode + else if (IsInText()) + { + return ButtonClickInText(mx, my); + } + } + } + else if ((mx >= gXoffset) && (mx <= m_BezelRight) && + (my >= m_BezelBottom) && (my <= m_BezelBottom + m_BezelBottomH)) + { + // In FKey area + procFkey = TRUE; + } + + if (procFkey) + { + int num_labels = gModel == MODEL_PC8201 ? 5 : 8; + int pixPerLabel = 240 / num_labels; + int fk = (mx - gXoffset) / MultFact / pixPerLabel + 1; + WheelKey(FL_F + fk); + m_Select = FALSE; + Fl::event_clicks(0); + } + } m_MyFocus = 1; break; @@ -2677,6 +4211,10 @@ int T100_Disp::handle(int event) update_keys(); break; + default: + Fl_Widget::handle(event); + break; + } // Display keystroke info on status line of display @@ -2999,7 +4537,7 @@ void T200_Disp::draw() /* Get RAM address where display should start */ addr = ((m_dstarth << 8) | m_dstartl) & (8192-1); - fl_color(FL_BLACK); + fl_color(m_PixelColor); /* Check if the driver is in "graphics" mode */ if (m_mcr & 0x02) @@ -3067,10 +4605,14 @@ void T200_Disp::SetByte(int driver, int col, uchar value) // Set the display window()->make_current(); - fl_color(FL_GRAY); + fl_color(m_BackgroundColor); +#ifdef ZIPIT_Z2 + fl_rectf(m_xCoord[x], m_yCoord[y], 8, m_rectSize[y]); +#else fl_rectf(x*MultFact + gXoffset, y*MultFact + gYoffset, MultFact*6, gRectsize); - fl_color(FL_BLACK); +#endif + fl_color(m_PixelColor); // Draw each pixel of byte drawpixel(x++,y,value&0x01); @@ -3125,10 +4667,14 @@ void T200_Disp::redraw_active() { // Erase line so it is grey, then fill in with black where needed y = row; - fl_color(FL_GRAY); + fl_color(m_BackgroundColor); +#ifdef ZIPIT_Z2 + fl_rectf(m_xCoord[x],m_yCoord[y], 320,m_rectSize[y]); +#else fl_rectf(gXoffset,y*MultFact + gYoffset,240*MultFact,gRectsize); - fl_color(FL_BLACK); +#endif + fl_color(m_PixelColor); /* Loop through all 40 LCD columns */ for (col = 0; col < 40; col++) diff --git a/src/display.h b/src/display.h index 805b890..dbdf61a 100644 --- a/src/display.h +++ b/src/display.h @@ -32,6 +32,7 @@ #define _DISPLAY_H_ #define MENU_HEIGHT 32 +#define TAB_HEIGHT 24 #ifdef __cplusplus extern "C" { @@ -39,6 +40,7 @@ extern "C" { extern int gDelayUpdateKeys; void init_pref(void); void init_display(void); +void deinit_display(void); void drawbyte(int driver, int column, int value); void lcdcommand(int driver, int value); void power_down(); @@ -56,6 +58,9 @@ typedef int (*event_key_t)(void); #ifdef __cplusplus +//#include +//#include + #define VT_SIM_KEYUP 3120 #define VT_SIM_KEYDOWN 3121 @@ -63,15 +68,24 @@ class T100_Disp : public Fl_Widget { public: T100_Disp(int x, int y, int w, int h); + ~T100_Disp(); virtual void PowerDown(); virtual void SetByte(int driver, int col, uchar value); virtual void Command(int instruction, uchar data); virtual void Clear(void); virtual void Reset(void); + virtual void CalcScreenCoords(void); void SimulateKeydown(int key); void SimulateKeyup(int key); void HandleSimkey(void); + void WheelKey(int key); + int IsInMenu(void); + int IsInText(void); + int ButtonClickInMenu(int mx, int my); + int ButtonClickInMsPlan(int mx, int my); + int ButtonClickInText(int mx, int my); + int MouseMoveInText(int mx, int my); int MultFact; int DisplayMode; @@ -81,8 +95,42 @@ class T100_Disp : public Fl_Widget int gRectsize; int gXoffset; int gYoffset; + int m_BezelTop; + int m_BezelLeft; + int m_BezelBottom; + int m_BezelRight; + int m_BezelTopH; + int m_BezelBottomH; + int m_BezelLeftW; + int m_BezelRightW; + int m_HasTopChassis; + int m_HasBottomChassis; + int m_HasLeftChassis; + int m_HasRightChassis; + + int m_FrameColor; + int m_DetailColor; + int m_BackgroundColor; + int m_PixelColor; + int m_LabelColor; int m_DebugMonitor; + int m_WheelKeys[32]; + int m_WheelKeyIn; + int m_WheelKeyOut; + int m_WheelKeyDown; + class Fl_Menu_Button* m_CopyCut; + class Fl_Menu_Button* m_LeftClick; + char m_SimulatedCtrl; + char m_SelectComplete; + char m_HaveMouse; + char m_Select; + int m_LastPos; +#ifdef ZIPIT_Z2 + int m_xCoord[241]; + int m_yCoord[241]; + int m_rectSize[241]; +#endif const virtual T100_Disp& operator=(const T100_Disp& srcDisp); diff --git a/src/elf.h b/src/elf.h index c887a15..865d961 100644 --- a/src/elf.h +++ b/src/elf.h @@ -63,21 +63,77 @@ typedef struct { #define ET_EXEC 2 // Executable file #define ET_DYN 3 // Shared object file #define ET_CORE 4 // Core file -#define ET_LOPROC 0xFF00 -#define ET_HIPROC 0xFFFF +#define ET_LOOS 0xFE00 // Operating system specific +#define ET_HIOS 0xFEFF // Operating system specific +#define ET_LOPROC 0xFF00 // Processor specific +#define ET_HIPROC 0xFFFF // Processor specific // Define machine types -#define ET_NONE 0 // No machine type -#define ET_M32 1 // AT&T WE 32100 -#define ET_SPARC 2 // SPARC -#define ET_386 3 // Intel -#define ET_68K 4 // Motorola -#define ET_88K 5 // Motorola -#define ET_860 7 // Intel i860 -#define ET_MIPS 8 // MIPS RS3000 -#define ET_MIPS_RS4_BE 10 // MIPS RS4000 -#define ET_8085 12 // Model T - 8085 +#define EM_NONE 0 // No machine type +#define EM_M32 1 // AT&T WE 32100 +#define EM_SPARC 2 // SPARC +#define EM_386 3 // Intel +#define EM_68K 4 // Motorola +#define EM_88K 5 // Motorola +#define EM_860 7 // Intel i860 +#define EM_MIPS 8 // MIPS RS3000 +#define EM_S370 9 // IBM System/370 Processor +#define EM_MIPS_RS4_BE 10 // MIPS RS4000 +// Codes 11-14 reserved for future use, so we use #12 +#define EM_8085 12 // Model T - 8085 +#define EM_PARISC 15 // HP PA-RISC +#define EM_VPP500 17 // Fujitsu VPP500 +#define EM_SPARC32PLUS 18 // Enhanced instruction set SPARC +#define EM_960 19 // Intel 80960 +#define EM_PPC 20 // PowerPC +#define EM_PPC64 21 // 64-bit PowerPC +// Codes 22-35 reserved for future use +#define EM_V800 36 // NEC V800 +#define EM_FR20 37 // Fujitsu FR20 +#define EM_RH32 38 // TRW RH-32 +#define EM_RCE 39 // Motorola RCE +#define EM_ARM 40 // Advanced RISC Machines ARM +#define EM_ALPHA 41 // Digital Alpha +#define EM_SH 42 // Hitachi SH +#define EM_SPARCV9 43 // SPARC Version 9 +#define EM_TRICORE 44 // Siemens Tricore embedded processor +#define EM_ARC 45 // Argonaut RISC core +#define EM_H8_300 46 // Hitachi H8/30 +#define EM_H8_300H 47 // Hitachi H8/300H +#define EM_H8S 48 // Hitachi H8S +#define EM_H8_500 49 // Hitachi H8/500 +#define EM_IA_64 50 // Intel IA-64 processor architecture +#define EM_MIPS_X 51 // Stanford MIPS-X +#define EM_COLDFIRE 52 // Motorola ColdFire +#define EM_68HC12 53 // Motorola M68HC12 +#define EM_MMA 54 // Fujitsu MMA Multimedia Accelerator +#define EM_PCP 55 // Siemens PCP +#define EM_NCPU 56 // Sony nCPU embedded RISC processor +#define EM_NDR1 57 // Denso NDR1 microprocessor +#define EM_STARCORE 58 // Motorola Star*Core processor +#define EM_ME16 59 // Toyota ME16 processor +#define EM_ST100 60 // STMicroelectronics ST100 processor +#define EM_TINYJ 61 // Advanced Logic Corp. TinyJ embedded processor +// Codes 52-65 reserved for future use +#define EM_FX66 66 // Siemens FX66 microcontroller +#define EM_ST9PLUS 67 // STMicroelectronics ST9+ 8/16 bit microcontroller +#define EM_ST7 68 // STMicroelectronics ST7 8-bit microcontroller +#define EM_68HC16 69 // Motorola MC68HC16 microcontroller +#define EM_68HC11 70 // Motorola MC68HC11 microcontroller +#define EM_68HC08 71 // Motorola MC68HC08 microcontroller +#define EM_68HC05 72 // Motorola MC68HC05 microcontroller +#define EM_SVX 73 // Silicon Graphics SVx +#define EM_ST19 74 // STMicroelectronics ST19 8-bit microcontroller +#define EM_VAX 75 // Digital VAX +#define EM_CRIS 76 // Axis Communications 32-bit embedded processor +#define EM_JAVELIN 77 // Infineon Technologies 32-bit embedded processor +#define EM_FIREPATH 78 // Element 14 64-bit DSP processor +#define EM_ZSP 79 // LSI Logic 16-bit DSP processor +#define EM_MMIX 80 // Donald Knuth's educational 64-bit processor +#define EM_HAUNY 81 // Harvard University machine-independent object files +#define EM_PRISM 82 // SiTera Prism + // Define version #define EV_NONE 0 // Invalid version @@ -102,8 +158,6 @@ typedef struct { #define ELFCLASSNONE 0 // Invalid class #define ELFCLASS32 1 // 32-bit objects #define ELFCLASS64 2 // 64-bit objects -#define ELFCLASS16 3 // 16-bit objects -#define ELFCLASS8 4 // 8-bit objects #define ELFDATANONE 0 // Invalid data encoding #define ELFDATA2LSB 1 // LSB first @@ -132,28 +186,43 @@ typedef struct { Elf32_Word sh_entsize; } Elf32_Shdr; -#define SHT_NULL 0 -#define SHT_PROGBITS 1 -#define SHT_SYMTAB 2 -#define SHT_STRTAB 3 -#define SHT_RELA 4 -#define SHT_HASH 5 -#define SHT_DYNAMIC 6 -#define SHT_NOTE 7 -#define SHT_NOBITS 8 -#define SHT_REL 9 -#define SHT_SHLIB 10 -#define SHT_DYNSYM 11 -#define SHT_LOPROC 0x7000000 -#define SHT_HIPROC 0x7ffffff -#define SHT_LOUSER 0x8000000 -#define SHT_HIUSER 0xfffffff +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_INIT_ARRAY 14 +#define SHT_FINI_ARRAY 15 +#define SHT_PREINIT_ARRAY 16 +#define SHT_GROUP 17 +#define SHT_SYMTAB_SHNDX 18 +#define SHT_LOOS 0x6000000 +#define SHT_HIOS 0x6ffffff +#define SHT_LOPROC 0x7000000 +#define SHT_HIPROC 0x7ffffff +#define SHT_LOUSER 0x8000000 +#define SHT_HIUSER 0xfffffff // Define Flags -#define SHF_WRITE 0x01 -#define SHF_ALLOC 0x02 -#define SHF_EXECINSTR 0x04 -#define SFH_MASKPROC 0xf0000000 +#define SHF_WRITE 0x01 +#define SHF_ALLOC 0x02 +#define SHF_EXECINSTR 0x04 +#define SHF_MERGE 0x10 +#define SHF_STRINGS 0x20 +#define SHF_INFO_LINK 0x40 +#define SHF_LINK_ORDER 0x80 +#define SHF_OS_NONCONFORMING 0x100 +#define SHF_GROUP 0x200 +#define SHF_8085_ABSOLUTE 0x00100000 +#define SHF_MASKOS 0x0ff00000 +#define SFH_MASKPROC 0xf0000000 // Define Symbol table items #define STN_UNDEF 0 diff --git a/src/file.cpp b/src/file.cpp index cd3bdf0..eca6561 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -41,6 +41,8 @@ #include #include +#include "FLU/Flu_File_Chooser.h" + extern "C" { #include "memory.h" @@ -62,9 +64,15 @@ extern char gsMenuROM[40]; void cb_LoadRam (Fl_Widget* w, void*) { - Fl_File_Chooser *FileWin; - - FileWin = new Fl_File_Chooser(".","*.bin",1,"Load RAM file"); + Flu_File_Chooser *FileWin; + + fl_cursor(FL_CURSOR_WAIT); +#ifdef __APPLE__ + FileWin = new Flu_File_Chooser(path,"*.bin",1,"Load RAM file"); +#else + FileWin = new Flu_File_Chooser(".","*.bin",1,"Load RAM file"); +#endif + fl_cursor(FL_CURSOR_DEFAULT); FileWin->preview(0); FileWin->show(); @@ -72,9 +80,15 @@ void cb_LoadRam (Fl_Widget* w, void*) void cb_SaveRam (Fl_Widget* w, void*) { - Fl_File_Chooser *FileWin; + Flu_File_Chooser *FileWin; - FileWin = new Fl_File_Chooser(".","*.bin",1,"Save RAM file"); + fl_cursor(FL_CURSOR_WAIT); +#ifdef __APPLE__ + FileWin = new Flu_File_Chooser(path,"*.bin",1,"Save RAM file"); +#else + FileWin = new Flu_File_Chooser(".","*.bin",1,"Save RAM file"); +#endif + fl_cursor(FL_CURSOR_DEFAULT); FileWin->preview(0); // FileWin.value(0)="RAM.bin" FileWin->show(); @@ -132,12 +146,18 @@ int load_optrom_file(const char* filename) void cb_LoadOptRom (Fl_Widget* w, void*) { - Fl_File_Chooser *FileWin; + Flu_File_Chooser *FileWin; int count; int ret; const char *filename; - FileWin = new Fl_File_Chooser(".","*.{bin,hex}",1,"Load Optional ROM file"); + fl_cursor(FL_CURSOR_WAIT); +#ifdef __APPLE__ + FileWin = new Flu_File_Chooser(".","*.{bin,hex}",1,"Load Optional ROM file"); +#else + FileWin = new Flu_File_Chooser(".","*.{bin,hex}",1,"Load Optional ROM file"); +#endif + fl_cursor(FL_CURSOR_DEFAULT); FileWin->preview(0); FileWin->show(); @@ -152,7 +172,7 @@ void cb_LoadOptRom (Fl_Widget* w, void*) } // Get Filename - filename = FileWin->value(1); + filename = FileWin->value(); if (filename == 0) { delete FileWin; @@ -514,7 +534,7 @@ int gLoadError; void cb_LoadFromHost(Fl_Widget* w, void* host_filename) { int count, i, x; - Fl_File_Chooser *fc; + Flu_File_Chooser *fc = NULL; const char *filename; const char *filename_name; char mt_file[8]; @@ -532,7 +552,13 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) if (w != NULL) { - fc = new Fl_File_Chooser(".","Model T Files (*.{do,txt,ba,co,hex})",1,"Load file from Host"); + fl_cursor(FL_CURSOR_WAIT); +#ifdef __APPLE__ + fc = new Flu_File_Chooser(path,"Model T Files (*.{do,txt,ba,co,hex})",1,"Load file from Host"); +#else + fc = new Flu_File_Chooser(".","Model T Files (*.{do,txt,ba,co,hex})",1,"Load file from Host"); +#endif + fl_cursor(FL_CURSOR_DEFAULT); fc->preview(0); fc->show(); @@ -547,7 +573,7 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) } // Get Filename - filename = fc->value(1); + filename = fc->value(); if (filename == 0) { delete fc; @@ -555,7 +581,6 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) } len = strlen(filename); - delete fc; } else { @@ -574,6 +599,8 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) fl_message("Unable to open file %s", filename); else gLoadError = 1; + if (fc != NULL) + delete fc; return; } @@ -582,6 +609,10 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) if (((filename[len-1] | 0x20) == 'o') && ((filename[len-2] | 0x20) == 'c')) file_type = TYPE_CO; + // Deal with other binary types + if (((filename[len-2] | 0x20) == 'c') && + (filename[len-3] == '.')) + file_type = TYPE_CO; if (((filename[len-1] | 0x20) == 'a') && ((filename[len-2] | 0x20) == 'b')) file_type = TYPE_BA; @@ -610,12 +641,16 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) mt_file[6] = 'D'; mt_file[7] = 'O'; } - else if ((file_type == TYPE_CO) || (file_type == TYPE_HEX)) + else if (file_type == TYPE_CO) + { + mt_file[6] = 'C'; + mt_file[7] = toupper(filename[len-1]); + } + else if (file_type == TYPE_HEX) { mt_file[6] = 'C'; mt_file[7] = 'O'; } - // Determine "RAW" length of file (w/o CRLF expansion) fseek(fd, 0, SEEK_END); @@ -627,6 +662,8 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) fl_message(gTooLargeMsg); else gLoadError = 1; + if (fc != NULL) + delete fc; return; } @@ -667,6 +704,8 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) fl_message(gTooLargeMsg); else gLoadError = 1; + if (fc != NULL) + delete fc; return; } } @@ -726,7 +765,11 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) } if (len == 0) + { + if (fc != NULL) + delete fc; return; + } // Determine if file will fit in memory addr3 = get_memory16(gStdRomDesc->sBasicStrings); @@ -737,6 +780,8 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) fl_message(gTooLargeMsg); else gLoadError = 1; + if (fc != NULL) + delete fc; return; } @@ -766,6 +811,8 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) fl_message("File %s already exists", filename_name); else gLoadError = 1; + if (fc != NULL) + delete fc; return; } @@ -786,6 +833,8 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) fl_message("Too many files in directory"); else gLoadError = 1; + if (fc != NULL) + delete fc; return; } } @@ -898,6 +947,8 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) // Reset the system so file will show up jump_to_zero(); + if (fc != NULL) + delete fc; } int remote_load_from_host(const char *filename) @@ -944,7 +995,7 @@ void save_file(model_t_files_t *pFile) unsigned char type; unsigned short line; FILE *fd; - Fl_File_Chooser *fc; + Flu_File_Chooser *fc; char filename[12]; if (pFile == 0) @@ -962,7 +1013,13 @@ void save_file(model_t_files_t *pFile) } } - fc = new Fl_File_Chooser(filename,"*.*",Fl_File_Chooser::CREATE,"Save file as"); + fl_cursor(FL_CURSOR_WAIT); +#ifdef __APPLE__ + fc = new Flu_File_Chooser(filename,"*.*",Fl_File_Chooser::CREATE,"Save file as"); +#else + fc = new Flu_File_Chooser(filename,"*.*",Fl_File_Chooser::CREATE,"Save file as"); +#endif + fl_cursor(FL_CURSOR_DEFAULT); fc->preview(0); // FileWin.value(0)="RAM.bin" fc->show(); @@ -1237,7 +1294,7 @@ char* ChooseWorkDir() { char *ret=NULL; - ret = fl_dir_chooser("Choose Working Directory",".",0); + ret = fl_dir_chooser("Choose Working Directory",path,0); return ret; } diff --git a/src/fileprint.cpp b/src/fileprint.cpp index 5253d95..9deaa03 100644 --- a/src/fileprint.cpp +++ b/src/fileprint.cpp @@ -38,6 +38,8 @@ #include #include +#include "FLU/Flu_File_Chooser.h" + #include #include #include @@ -484,7 +486,7 @@ name or autogenerated name. */ int VTFilePrint::PromptFilename(MString& filename) { - Fl_File_Chooser* fc; + Flu_File_Chooser* fc; char text[80]; while (1) @@ -495,8 +497,10 @@ int VTFilePrint::PromptFilename(MString& filename) sprintf(text, "Select File for Page %d", m_PageNum); // Prompt the user with the filename & give a chance to change - fc = new Fl_File_Chooser((const char *) filename, "*.*", + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser((const char *) filename, "*.*", Fl_File_Chooser::CREATE, text); + fl_cursor(FL_CURSOR_DEFAULT); fc->show(); fc->value((const char *) filename); diff --git a/src/fileview.cpp b/src/fileview.cpp index 846f98d..9a32ca0 100644 --- a/src/fileview.cpp +++ b/src/fileview.cpp @@ -79,7 +79,7 @@ void jump_to_zero(void); // =============================================== extern Fl_Preferences virtualt_prefs; extern Fl_Menu_Item gCpuRegs_menuitems[]; -extern char *gKeywordTable[]; +extern const char *gKeywordTable[]; Fl_Window* gfvw = NULL; int gLowmem = 0; int gPrevUnused = 0; @@ -758,16 +758,23 @@ Routine to create the Model T File viewer window void cb_FileView(Fl_Widget* w, void*) { Fl_Box* o; + int width; if (gfvw != NULL) return; +#ifdef WIN32 + width = 650; +#else + width = 760; +#endif + // Create File Viewer window - gfvw = new Fl_Double_Window(650, 480, "Model T File Viewer"); + gfvw = new Fl_Double_Window(width, 480, "Model T File Viewer"); gfvw->callback(cb_fvwin); // Create a menu for the new window. - gFvCtrl.pMenu = new Fl_Menu_Bar(0, 0, 700, MENU_HEIGHT-2); + gFvCtrl.pMenu = new Fl_Menu_Bar(0, 0, width, MENU_HEIGHT-2); gFvCtrl.pMenu->menu(gFileView_menuitems); o = new Fl_Box(20, 40, 80, 20, "File Directory"); @@ -780,13 +787,17 @@ void cb_FileView(Fl_Widget* w, void*) gFvCtrl.pFileSelect->callback(cb_FileSelect); // Create a Text Editor / Text Buffer for the file display - gFvCtrl.pView = new Fl_Hold_Browser(200, 65, 420, 270, ""); + gFvCtrl.pView = new Fl_Hold_Browser(200, 65, width-230, 270, ""); gFvCtrl.pView->has_scrollbar(Fl_Browser_::VERTICAL ); // gFvCtrl.pView = new Fl_Text_Display(200, 65, 420, 270, ""); // gFvCtrl.pTb = new Fl_Text_Buffer(); // gFvCtrl.pView->buffer(gFvCtrl.pTb); gFvCtrl.pView->textfont(FL_COURIER); +#ifdef WIN32 gFvCtrl.pView->textsize(12); +#else + gFvCtrl.pView->textsize(14); +#endif // gFvCtrl.pView->wrap_mode(56, 56); // gFvCtrl.pView->end(); @@ -795,7 +806,7 @@ void cb_FileView(Fl_Widget* w, void*) o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); o = new Fl_Box(FL_NO_BOX, 40, 395, 100, 15, "Map"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - gFvCtrl.pRAM = new Fl_Usage_Box(100, 365, 516, 68); + gFvCtrl.pRAM = new Fl_Usage_Box(100, 365, width-134, 68); gFvCtrl.pRAM->box(FL_BORDER_BOX); gFvCtrl.pRAM->SetUsageColor(FV_SELECT_FILE_COLOR, fl_rgb_color(64, 64, 64)); gFvCtrl.pRAM->SetUsageColor(FV_BASIC_FILE_COLOR , fl_rgb_color(96, 255,96)); diff --git a/src/fl_action_icon.cpp b/src/fl_action_icon.cpp index 154f331..25417c3 100644 --- a/src/fl_action_icon.cpp +++ b/src/fl_action_icon.cpp @@ -119,11 +119,15 @@ Draw the action icon. */ void Fl_Action_Icon::draw(void) { + int tx = x() + m_pImage->w() + 5; + int ty = y() + h() - 5; + fl_push_clip(x(), y(), w(), h()); Fl_Box::draw(); // Draw the label window()->make_current(); fl_color(FL_BLACK); - fl_draw(label(),x() + m_pImage->w() + 5, y() + h() -5 ); + fl_draw(label(),tx, ty ); + fl_pop_clip(); } diff --git a/src/flu_file_chooser_pixmaps.cpp b/src/flu_file_chooser_pixmaps.cpp new file mode 100644 index 0000000..b97acdb --- /dev/null +++ b/src/flu_file_chooser_pixmaps.cpp @@ -0,0 +1,2470 @@ +// $Id$ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + +const char * monalisa_xpm[] = { +"17 21 212 2", +" c None", +". c #565A2E", +"+ c #7A7A43", +"@ c #7E7A47", +"# c #7A723E", +"$ c #76723E", +"% c #767A46", +"& c #767644", +"* c #86824A", +"= c #8A8246", +"- c #8E864A", +"; c #96925A", +"> c #968E56", +", c #5E6236", +"' c #8E824A", +") c #92864E", +"! c #928A4C", +"~ c #8A8A4E", +"{ c #867A42", +"] c #928252", +"^ c #9E8E52", +"/ c #9A8E52", +"( c #AA9A59", +"_ c #A29656", +": c #827E4A", +"< c #666A3E", +"[ c #A69658", +"} c #867A4E", +"| c #524222", +"1 c #2A2A10", +"2 c #1E1E16", +"3 c #625A3A", +"4 c #B29E62", +"5 c #B6A262", +"6 c #B6A664", +"7 c #AE9E5A", +"8 c #BAA662", +"9 c #B6A25C", +"0 c #92764A", +"a c #F6D66E", +"b c #CA9A52", +"c c #322E12", +"d c #121A12", +"e c #928A5A", +"f c #BEAA62", +"g c #C6B66A", +"h c #BAAA62", +"i c #A29252", +"j c #4E522A", +"k c #827E42", +"l c #B2A25E", +"m c #CAB66A", +"n c #8A7A46", +"o c #A67E3A", +"p c #E2C262", +"q c #CA9242", +"r c #6E5A2A", +"s c #12160A", +"t c #3A3E26", +"u c #9E9255", +"v c #CABA66", +"w c #C6B262", +"x c #867E46", +"y c #262E1A", +"z c #5A5E32", +"A c #52562A", +"B c #86864A", +"C c #4E4E2E", +"D c #866A36", +"E c #BA863A", +"F c #A28246", +"G c #7E6236", +"H c #161A0D", +"I c #222A10", +"J c #4E5A32", +"K c #565E2A", +"L c #6A6E3A", +"M c #1A260E", +"N c #364626", +"O c #424E28", +"P c #3A4A22", +"Q c #323E26", +"R c #262A1A", +"S c #9E7636", +"T c #BA8E4A", +"U c #D6A252", +"V c #564616", +"W c #121E10", +"X c #3A4E2E", +"Y c #465632", +"Z c #6A7242", +"` c #5E6632", +" . c #3E4625", +".. c #121A0A", +"+. c #32421F", +"@. c #36421E", +"#. c #363E1E", +"$. c #1E2616", +"%. c #4A3A22", +"&. c #AE823E", +"*. c #927236", +"=. c #363214", +"-. c #1A1A0C", +";. c #161E0D", +">. c #2A3216", +",. c #0E160D", +"'. c #223216", +"). c #3A4622", +"!. c #363A1C", +"~. c #362E12", +"{. c #26260A", +"]. c #12160E", +"^. c #121A0E", +"/. c #4A5232", +"(. c #323218", +"_. c #0E120E", +":. c #3E321A", +"<. c #8A6E36", +"[. c #7E662E", +"}. c #2E260A", +"|. c #3A4226", +"1. c #5E5626", +"2. c #565626", +"3. c #1E1E0D", +"4. c #4A461E", +"5. c #1E2612", +"6. c #0E1A0E", +"7. c #52421D", +"8. c #E2B65A", +"9. c #EAB252", +"0. c #EEB256", +"a. c #5E421A", +"b. c #2E2214", +"c. c #525226", +"d. c #726A2E", +"e. c #262A0F", +"f. c #3A3612", +"g. c #5A5626", +"h. c #524A18", +"i. c #CA9E4A", +"j. c #F6CE6A", +"k. c #5E3E14", +"l. c #4E4A26", +"m. c #6E622E", +"n. c #221E0E", +"o. c #4A421A", +"p. c #12120A", +"q. c #BA964E", +"r. c #E6CA66", +"s. c #FAE67A", +"t. c #CAAA52", +"u. c #2A260A", +"v. c #0A0E02", +"w. c #060E06", +"x. c #121206", +"y. c #3E2E12", +"z. c #423212", +"A. c #120E0A", +"B. c #6A461E", +"C. c #0A160E", +"D. c #222E12", +"E. c #2E2E0A", +"F. c #46421E", +"G. c #0E120A", +"H. c #0E1206", +"I. c #3A2616", +"J. c #26160A", +"K. c #624A22", +"L. c #564222", +"M. c #1A220E", +"N. c #0E0E06", +"O. c #261E0E", +"P. c #1A160C", +"Q. c #3E3A16", +"R. c #0A1209", +"S. c #060A02", +"T. c #0A0E0A", +"U. c #16120C", +"V. c #020A02", +"W. c #020A06", +"X. c #0A0E06", +"Y. c #0A0A0A", +"Z. c #26220E", +"`. c #1A1212", +" + c #060E10", +".+ c #060A06", +"++ c #060606", +"@+ c #020606", +"#+ c #060602", +"$+ c #0E0A06", +"%+ c #060E0A", +"&+ c #664E1E", +"*+ c #96622E", +"=+ c #422E1E", +"-+ c #060A0E", +";+ c #020602", +">+ c #0A0A02", +",+ c #16160A", +"'+ c #6E5226", +")+ c #AE7232", +"!+ c #B27236", +"~+ c #825A2E", +"{+ c #322A0A", +"]+ c #020202", +"^+ c #826232", +"/+ c #664216", +"(+ c #5E3A26", +"_+ c #46261A", +":+ c #0A0602", +"<+ c #4A3A12", +"[+ c #262216", +"}+ c #1E1A0A", +". + + @ # $ % & @ @ * = = - ; > & ", +", ' - ) - ' ! ~ { ] ^ ^ / ^ ( _ : ", +"< _ ( _ [ [ } | 1 2 3 4 ( 5 6 4 ! ", +"< 7 8 9 4 6 0 a b c d e 8 f g h i ", +"j k ( l m n o p q r s t + u v w x ", +"y , z A B C D E F G H I J K w 7 L ", +"M N O P Q R S T U V W M X Y Z ` .", +"..+.@.Q #.$.%.&.*.=.-.;.N N X X >.", +",.'.@.).A !.,.%.~.{.].H N ).+. .>.", +"^.Q O P /.(._.:.<.[.}.H y |.1.2.I ", +"3.!.4.!.5.6.7.8.9.0.a.b.3.c.d.2.e.", +"3.f.g.h.e.{.i.j.j.9.k.7.l.3.C m.h.", +"n.7.V o.p.:.q.r.s.t.4.u.v.w.x.y.z.", +"A.k.B.n.C.D.E.F.F.1 G.$.3.].H.I.J.", +"A.K.L.].C.H H M.M.w.H.5.(.N._.O.P.", +"-.Q.1 H C.H.R.6.R.S.w.-.N.T.T.s U.", +"G.H ^.-.H w.w.s V.W.S.V.X.X.w.N.A.", +"Y.s Z.E.s `. +R..+++@+#+$+S..+%+N.", +".+X.=.=.&+q *+=+-+;+#+V.>+#+S.W.++", +".+.+N.,+Z.'+)+!+~+b.Z.{+U.S.%+.+]+", +";+S.;+.+| ^+/+~+(+_+}.}.P.#+#+V.:+"}; + +const char * filedetails_xpm[] = { +"21 21 42 1", +" c None", +". c #000000", +"+ c #3559A0", +"@ c #3B5DA2", +"# c #4062A5", +"$ c #4666A7", +"% c #4B6AAA", +"& c #506FAC", +"* c #5673AF", +"= c #5B78B1", +"- c #607CB4", +"; c #6681B6", +"> c #6B85B9", +", c #7089BB", +"' c #768EBE", +") c #7B92C1", +"! c #8197C3", +"~ c #869BC6", +"{ c #8BA0C8", +"] c #91A4CB", +"^ c #96A8CD", +"/ c #2F549D", +"( c #35589F", +"_ c #3A5DA2", +": c #4061A4", +"< c #4566A7", +"[ c #4A6AA9", +"} c #506EAC", +"| c #5573AE", +"1 c #5A77B1", +"2 c #6580B6", +"3 c #758DBE", +"4 c #7B92C0", +"5 c #8096C3", +"6 c #859BC5", +"7 c #8B9FC8", +"8 c #90A4CA", +"9 c #8E8E8E", +"0 c #474747", +"a c #FFFFFF", +"b c #917D2F", +"c c #EAD264", +" ", +".....................", +".+@#$%&*=-;>,')!~{]^.", +"./(_:<[}|1-2>,345678.", +".....................", +".9999099990999909999.", +".9999099990999909999.", +".0000000000000000000.", +".aaaaaaaaaaaaaaaaaaa.", +".bccba....a....a...a.", +".aaaaaaaaaaaaaaaaaaa.", +".bccba....a....a...a.", +".aaaaaaaaaaaaaaaaaaa.", +"./^^/a....a....a...a.", +".aaaaaaaaaaaaaaaaaaa.", +"./^^/a....a....a...a.", +".aaaaaaaaaaaaaaaaaaa.", +".aaaaaaaaaaaaaaaaaaa.", +".....................", +" ", +" "}; + +const char * filelist_xpm[] = { +"21 21 39 1", +" c None", +". c #000000", +"+ c #3559A0", +"@ c #3B5DA2", +"# c #4062A5", +"$ c #4666A7", +"% c #4B6AAA", +"& c #506FAC", +"* c #5673AF", +"= c #5B78B1", +"- c #607CB4", +"; c #6681B6", +"> c #6B85B9", +", c #7089BB", +"' c #768EBE", +") c #7B92C1", +"! c #8197C3", +"~ c #869BC6", +"{ c #8BA0C8", +"] c #91A4CB", +"^ c #96A8CD", +"/ c #2F549D", +"( c #35589F", +"_ c #3A5DA2", +": c #4061A4", +"< c #4566A7", +"[ c #4A6AA9", +"} c #506EAC", +"| c #5573AE", +"1 c #5A77B1", +"2 c #6580B6", +"3 c #758DBE", +"4 c #7B92C0", +"5 c #8096C3", +"6 c #859BC5", +"7 c #8B9FC8", +"8 c #90A4CA", +"9 c #FFFFFF", +"0 c #EAD264", +" ", +".....................", +".+@#$%&*=-;>,')!~{]^.", +"./(_:<[}|1-2>,345678.", +".....................", +".9999999999999999999.", +".9....99999....99999.", +".9.00.9...9.00.9...9.", +".9....99999....99999.", +".9999999999999999999.", +".9....99999....99999.", +".9.00.9...9.00.9...9.", +".9....99999....99999.", +".9999999999999999999.", +".9....99999....99999.", +".9.00.9...9.00.9...9.", +".9....99999....99999.", +".9999999999999999999.", +".....................", +" ", +" "}; + +const char * filelistwide_xpm[] = { +"21 21 39 1", +" c None", +". c #000000", +"+ c #3559A0", +"@ c #3B5DA2", +"# c #4062A5", +"$ c #4666A7", +"% c #4B6AAA", +"& c #506FAC", +"* c #5673AF", +"= c #5B78B1", +"- c #607CB4", +"; c #6681B6", +"> c #6B85B9", +", c #7089BB", +"' c #768EBE", +") c #7B92C1", +"! c #8197C3", +"~ c #869BC6", +"{ c #8BA0C8", +"] c #91A4CB", +"^ c #96A8CD", +"/ c #2F549D", +"( c #35589F", +"_ c #3A5DA2", +": c #4061A4", +"< c #4566A7", +"[ c #4A6AA9", +"} c #506EAC", +"| c #5573AE", +"1 c #5A77B1", +"2 c #6580B6", +"3 c #758DBE", +"4 c #7B92C0", +"5 c #8096C3", +"6 c #859BC5", +"7 c #8B9FC8", +"8 c #90A4CA", +"9 c #FFFFFF", +"0 c #EAD264", +" ", +".....................", +".+@#$%&*=-;>,')!~{]^.", +"./(_:<[}|1-2>,345678.", +".....................", +".9999999999999999999.", +".9....99999999999999.", +".9.00.9............9.", +".9....99999999999999.", +".9999999999999999999.", +".9....99999999999999.", +".9.00.9............9.", +".9....99999999999999.", +".9999999999999999999.", +".9....99999999999999.", +".9.00.9............9.", +".9....99999999999999.", +".9999999999999999999.", +".....................", +" ", +" "}; + +// this xpm is a modification of the KDE home desktop icon +/* XPM */ +const char * bighome_xpm[] = { +"44 44 98 2", +" c None", +". c #32363A", +"+ c #7E929E", +"@ c #7E8E9E", +"# c #8696A6", +"$ c #8296A2", +"% c #7A8A9A", +"& c #768A96", +"* c #8EA2B2", +"= c #8A9EAE", +"- c #768692", +"; c #524857", +"> c #96A6BA", +", c #92A6BA", +"' c #869AAA", +") c #8292A2", +"! c #82929E", +"~ c #7E8E9A", +"{ c #7A8E9A", +"] c #72828E", +"^ c #6E828A", +"/ c #9EB2C5", +"( c #9AAEBE", +"_ c #92A2B6", +": c #8A9AAA", +"< c #7A8A96", +"[ c #768696", +"} c #6E7E8A", +"| c #8E727A", +"1 c #A2B6CA", +"2 c #96AABE", +"3 c #96AABA", +"4 c #92A6B6", +"5 c #8E9EB1", +"6 c #8296A6", +"7 c #7A626A", +"8 c #525A62", +"9 c #525E62", +"0 c #9AAEC2", +"a c #727E8A", +"b c #565E66", +"c c #4E5A60", +"d c #6E7A86", +"e c #5A666A", +"f c #56626A", +"g c #525E66", +"h c #5A6A70", +"i c #5A666E", +"j c #566266", +"k c #6E7E86", +"l c #564A5A", +"m c #626E76", +"n c #5E6A72", +"o c #768290", +"p c #6A7A86", +"q c #667682", +"r c #4E565A", +"s c #66767E", +"t c #666E7A", +"u c #5E6E76", +"v c #5E6672", +"w c #66727A", +"x c #4E5656", +"y c #4A565C", +"z c #6A7682", +"A c #62727A", +"B c #5A626A", +"C c #6A7A82", +"D c #626E7A", +"E c #4E5256", +"F c #4A5256", +"G c #5E6A76", +"H c #4A525A", +"I c #66727E", +"J c #626A76", +"K c #525A5A", +"L c #4F565E", +"M c #72828A", +"N c #41494E", +"O c #4F5A5E", +"P c #7A8696", +"Q c #383C40", +"R c #A2BACE", +"S c #4A5252", +"T c #4A4E52", +"U c #CEE6FE", +"V c #464E52", +"W c #B6C6DA", +"X c #C2D6EA", +"Y c #464E4E", +"Z c #AABAC6", +"` c #BED2E6", +" . c #4E565E", +".. c #464A4E", +"+. c #AEBECA", +"@. c #3B4043", +"#. c #9AAAB2", +"$. c #363A3E", +" ", +" . . ", +" . . + @ . ", +" . . . # $ @ % & . . . . ", +" . . . * = # # $ + % & - . . ; ; ; . ", +" . . > , * = = ' ) ! ~ { - ] ^ . . . ; . . ", +" . . . / ( > _ * = : ' ) @ % < [ ] } . ; | . | . ", +" . . 1 1 / ( 2 3 4 5 = ' 6 + ) ~ < - ] ^ . 7 ; . 7 . ", +" . 8 9 . 1 0 0 2 , _ 5 = # # ) @ % < - a } . | | . | . ", +" . b 8 8 c . / 2 , 4 * 5 : ' 6 + ~ % [ ] ] d . | 7 . 7 . ", +" . e f g 9 9 c . 2 3 4 * = : 6 ) @ { & [ ] ^ d . | ; . | . ", +" . h i f j g 8 8 8 . > 4 = 5 ' # ) @ % < [ ^ } k . 7 | . l . . ", +" . m n n i e f j 9 c c . _ = : ' $ ) ~ < - o a d p q . | . . 9 r . ", +" . s t m u v i e f g 9 8 8 . = : # $ + @ < [ ] ^ } p q w . . f r x y . ", +" . z q A m m u h i e B j g 8 8 . ' # ) @ % % [ ] } d C s A D h g r E F . . ", +" . k d C z s A m m n h i f j g 8 8 . ) ) ~ { & - ] } p q A D G h 9 H . . - . ", +" . ] ^ a k z z I I D J n n i e f 9 g g . + @ < - ] ^ } p z A A G f K . ! & ] . ", +" . [ - o ^ k a C z I w A u n h i e f b L L . % & [ o a k z q I u u . . $ % - M . ", +" . < - o ] M a k C C I w D m n i i e j j N O . & [ ^ } k C s D u . = # ) < ] d . ", +" . ~ ~ < P ] ] a } C C z s D D u n i i f f L g . ] ] } p q A . . * = 6 { [ ^ p . ", +" . @ @ % < - - M a k C z z s w m u h i e e b b 8 . } p C q . 0 4 5 # ) % o } z . ", +" . ) @ ~ % < - o ] a } C C s w A m m n i f e j g 8 Q d . . / 3 _ = # @ & ^ C s . ", +" . # $ ! @ % % P - o M k d p z s w A D u i i i j g . . R / 0 , 5 ' + S o d q D . ", +" . ' # ) + ! ~ { P - o a a d d z I w A m u h i i j . R 1 / 2 4 = T T U F p I u . ", +" . : ' # ) + @ { < & P ] ] } k p z I w t m n n i e . R 1 0 , 5 V W X U F C D h . ", +" . = : : ' ) ! ! { H F H F M a } d C s s D D n n i . 1 / 2 4 Y Z W X V S A u 8 . ", +" . * = : : # ) ) @ H H H H H F F } d z z s w A m J . 1 / > * Y Z W S U F A h E . ", +" . 4 5 5 = ' ' # + F F V F F H H H } d C z s w m u . / 2 4 = Y Z V ` U Y m g F . ", +" . 3 4 _ 5 5 ' ' 6 V H V H H y y y M } k z z s w A . / > * ' Y Y Z ` U V n y V . ", +" . > 4 4 _ = 5 : # y y y y y .c 9 ] M } } C C s w . 2 4 5 # ..3 +.` V u g T . ", +" . 2 3 3 4 * * = : y y y c 9 c 8 g P o ] a d d z z @.2 * = $ ..#.Z V I n r . ", +" . / 2 3 > 4 _ * = c g g g 8 j j f & < o ] ] k k z . 4 5 # + ..#.V s m f . ", +" . / 0 0 2 > , 4 5 c c g f g f B B < < [ - ] } } d . * = # ~ ....z s u . ", +" . 1 / 0 0 ( > , , f f f f i B i v @ { < [ o o M } . * : + { ] k p u . ", +" . R 1 / 0 0 2 3 > B i i i n n n G ! @ ~ { & - ] ] . : ) @ < ^ p I . ", +" . . . 1 1 / 0 2 3 i i v G G G m t ) ! @ % < P P ] $.' 6 % ] } s . ", +" . . . . / 0 0 G G J J t D D w ' $ $ @ @ < < - $.# + % a d . ", +" . . . J t m w D w w I : # ) $ + @ % < . ) % [ ] . ", +" . . . . t I t t 5 : # ) $ ! @ % . ) & ] . ", +" . . . . = 5 : : # $ ! ! . % - . ", +" . . . : # 6 ) + . < . ", +" . . . . ) . . ", +" . . . ", +" "}; + +/* +char * bighome_xpm[] = { +"44 44 250 2", +" c None", +". c #1262C2", +"+ c #62AAE2", +"@ c #9BD6F7", +"# c #0656BE", +"$ c #AAE2FA", +"% c #A7DEFA", +"& c #023A92", +"* c #A2E2FA", +"= c #A2DEFA", +"- c #9EDEFA", +"; c #9EDAFA", +"> c #022246", +", c #9ADAFA", +"' c #A6E2FA", +") c #96DAF9", +"! c #0252AA", +"~ c #AAE6FA", +"{ c #9ADFFA", +"] c #96D6FA", +"^ c #92D6F9", +"/ c #8ED6FA", +"( c #26528E", +"_ c #023E99", +": c #C2EEFE", +"< c #92DAF9", +"[ c #8BD2F8", +"} c #86D0F2", +"| c #76BAE9", +"1 c #CDF2FE", +"2 c #B0E8FA", +"3 c #A2E6FA", +"4 c #96DEFA", +"5 c #8DDAFA", +"6 c #8AD6F8", +"7 c #82CEF9", +"8 c #75BEE9", +"9 c #D2F2FE", +"0 c #9EE2FA", +"a c #86D6F8", +"b c #86D2F9", +"c c #82D2F7", +"d c #7ECEF6", +"e c #7ACAF3", +"f c #79C2EB", +"g c #024E9E", +"h c #92DFFA", +"i c #76C9F0", +"j c #6EBEEA", +"k c #6ABAE2", +"l c #0E72DA", +"m c #C6EEFE", +"n c #86DAF9", +"o c #70C6EE", +"p c #68C1EC", +"q c #62BDE9", +"r c #268ADF", +"s c #0A66CE", +"t c #0256BE", +"u c #7BD2F5", +"v c #2186DE", +"w c #0B6ACF", +"x c #3A96DE", +"y c #79CEF2", +"z c #BAEAFC", +"A c #44AAEE", +"B c #167AD8", +"C c #0F6ECF", +"D c #0A6ECE", +"E c #0F6ED7", +"F c #7EC2E6", +"G c #5AB4EC", +"H c #3E9EE6", +"I c #288EE0", +"J c #1C7ED8", +"K c #2082D6", +"L c #92D6EE", +"M c #8AD2EE", +"N c #56B6E6", +"O c #4DAEE7", +"P c #46AAE2", +"Q c #36A2DE", +"R c #2A96DA", +"S c #1A84D8", +"T c #167ECE", +"U c #0E76D6", +"V c #1276CE", +"W c #0E72D3", +"X c #4BB2E5", +"Y c #43A5E5", +"Z c #2E86D6", +"` c #0866CA", +" . c #2692D6", +".. c #1B8AD9", +"+. c #5EBEEA", +"@. c #369DE0", +"#. c #1282CE", +"$. c #127AD7", +"%. c #1276D7", +"&. c #1676DA", +"*. c #72C2EE", +"=. c #2A92E2", +"-. c #0A66BE", +";. c #2A8ED6", +">. c #1E86E6", +",. c #167EE2", +"'. c #0A6AC8", +"). c #96DAF2", +"!. c #57BAEB", +"~. c #2E98DD", +"{. c #208EE0", +"]. c #1E86D6", +"^. c #1A82DF", +"/. c #1582D9", +"(. c #167ED7", +"_. c #127ED8", +":. c #248EEF", +"<. c #4CAAEA", +"[. c #1A82EA", +"}. c #62B6E6", +"|. c #0A72D2", +"1. c #0A6AC2", +"2. c #9BDAF2", +"3. c #4AB6EF", +"4. c #1A86DE", +"5. c #1E86EE", +"6. c #1E8AE1", +"7. c #2692DE", +"8. c #3A9EEA", +"9. c #228ADB", +"0. c #5EBAEA", +"a. c #2292DA", +"b. c #46AEEB", +"c. c #3EA2EA", +"d. c #2E9AE7", +"e. c #2692E6", +"f. c #42AEED", +"g. c #37A6EB", +"h. c #2E9EE6", +"i. c #289AE4", +"j. c #2996E4", +"k. c #2292E2", +"l. c #62C2EF", +"m. c #6AC6EE", +"n. c #2896F2", +"o. c #329EEA", +"p. c #1A8ADF", +"q. c #1686D8", +"r. c #1282DE", +"s. c #4AB2ED", +"t. c #1E8EEA", +"u. c #1E92E2", +"v. c #269AEE", +"w. c #289AF2", +"x. c #168ADE", +"y. c #1686DE", +"z. c #3EAEEA", +"A. c #42B2EF", +"B. c #2EA2EB", +"C. c #2A9EF2", +"D. c #29A2EA", +"E. c #3EAAEE", +"F. c #37A2E6", +"G. c #2FA2F6", +"H. c #3EB6F3", +"I. c #36AEF3", +"J. c #1A8EDF", +"K. c #2296E8", +"L. c #52BAEE", +"M. c #55BFEE", +"N. c #30A6EC", +"O. c #32A2EA", +"P. c #30A6F4", +"Q. c #46B2F1", +"R. c #36AAF3", +"S. c #31AAEF", +"T. c #2AA6EA", +"U. c #41BAF6", +"V. c #3AB2F4", +"W. c #32AEEE", +"X. c #1A92E2", +"Y. c #37AAEC", +"Z. c #A2AEFE", +"`. c #0F6EBE", +" + c #0C6ABA", +".+ c #0656AA", +"++ c #0A66BA", +"@+ c #229AE5", +"#+ c #46B6F0", +"$+ c #42B6F4", +"%+ c #3EB2F2", +"&+ c #DAE2FE", +"*+ c #BAC2FE", +"=+ c #96A6FE", +"-+ c #3BAEF1", +";+ c #022E7C", +">+ c #02327E", +",+ c #269EE7", +"'+ c #5EC6F4", +")+ c #53C2F4", +"!+ c #4CBEF3", +"~+ c #47BAF4", +"{+ c #F2F6FE", +"]+ c #CED6FE", +"^+ c #AEBAFE", +"/+ c #023284", +"(+ c #022A75", +"_+ c #02266A", +":+ c #71CAF1", +"<+ c #72CEF4", +"[+ c #5ABEEA", +"}+ c #E6EAFE", +"|+ c #C2CEFE", +"1+ c #3AB2EE", +"2+ c #6ACEF6", +"3+ c #62CAF6", +"4+ c #5AC6F6", +"5+ c #56C6F6", +"6+ c #3EB6FA", +"7+ c #02368B", +"8+ c #72D2F9", +"9+ c #6ACAF6", +"0+ c #62C6F2", +"a+ c #46BEF5", +"b+ c #2492EE", +"c+ c #023A8A", +"d+ c #82DAF9", +"e+ c #76D2F8", +"f+ c #6ED2F8", +"g+ c #66CEF7", +"h+ c #46BAFA", +"i+ c #023785", +"j+ c #4EBAEA", +"k+ c #4EC2F2", +"l+ c #80D6F7", +"m+ c #79D6F9", +"n+ c #8EDEFA", +"o+ c #5ECAF6", +"p+ c #52C2FA", +"q+ c #0242A0", +"r+ c #0246A7", +"s+ c #02429A", +"t+ c #8ADEFA", +"u+ c #024AAB", +"v+ c #6AD2F7", +"w+ c #065ABA", +"x+ c #A6E6FA", +"y+ c #0346A1", +"z+ c #9E9E9E", +"A+ c #2686D6", +" ", +" . . ", +" . . + @ # ", +" . . . @ $ $ % % # & & & ", +" . . . @ * = % = % - - ; # & > > > > ", +" . . , ' * * = = - ; , , @ , ) & ! ! > ! & ", +" . . . ~ ' ' * - - { , , ) ] ^ ^ ] / ( & _ ! & ( ", +" . . : ~ ~ ' ' = - , , , ) < ] ^ / [ } } & ( & ! & & ", +" . | = 1 2 ~ 3 * - - 4 ) 5 / / 6 6 [ [ 7 7 & & ( ! & ( ", +" . 8 ; , * 9 2 ' 0 0 { 4 < < / a [ b c d e f ( & & g ( & ", +" . | , , ^ ) * 9 ~ = { ) h / 6 6 a c d i j k l & ( & g & ( ", +" . 8 ) ^ ^ [ [ [ ' m * { 4 < 5 n c e o p j q r s ( & & ! ( & t ", +" . f ] ^ / / 6 b b b 2 m 0 h 5 b u i o o p q v w s s & ( g & w x t ", +" . 8 / / / [ [ 7 d d e y z z < a c y y i p A B C C D w w & ! w E E x t ", +" . 8 F 7 [ c e G H I r J K r L M N O P Q R S T U V W W D E E l E E E v X # ", +" . f f 8 8 Y Z B l C w w s ` ...L +.@.R ...K T #.$.%.U %.U l l l &.Y *.=.! ", +" -.8 F k H ;.>.,.B &.%.W C '.'.s ` @.).!.@.~. .{.].^./.(._.$.$.%.%.:.o <.,.[.t ", +" . 8 F }.@.=.I >.^.(._.V W |.C D D 1.1.O 2.3.Q ~. .{.{.4.^.^.,.,.^.X p {.,.5.6.# ", +" 7.f }.8.~.=.7.9.>.^._.(.$.U W |.|.|.|.T 0.2.X Q ~.R a.{...6.4.@.e b.,.5.6.:.:.t ", +" 7.}.c.8.d.d.e.{.6.4.4._.$.$.$.U V U U U a.p 2.f.g.h.i.j.a.k.l.m.j.^.:.:.n.n.n.# ", +" 7.<.A Y o.h.d.j.{.p.p.4.q.r._.$._._._._._.g.o L f.Q h.i.3.M s.t.{.u.v.n.n.w.w.t ", +" e.b.A g.g.o.i.j.k.{.{.x.y.q.y.#.r.#.#.#.#.x.X y ).z.A.y i B.j.i.C.D.C.C.C.w.C.# ", +" k.b.b.E.g.F.D.G.H.I.D.k.J.x.x.x.x.x.y.x.x.x.K.L.d ).).M.B.B.B.N.O.G.'.P.P.o.G.t ", +" e.s.Q.E.R.S.O.#.q.T.H.U.V.W.D.u.X.J.X.X.X.X.X.N.M.{ A.z.Y.I.I.I.1.1.Z.s P.P.P.# ", +" k.s.Q.f.E.R.g.`. +.+++q.@+N.H.H.V.S.@+@+@+@+i.@+#+l.3.X $+H.%+-.&+*+=+-.R.R.S.t ", +" e.3.Q.-+-+R.g. +++;+;+;+>+g ++T ,+W.,+,+D.D.T.D.N.'+)+)+!+~+-.{+]+^+-.'.V.I.I.# ", +" k.s.3.A.%+I.Y.`.-./+;+;+(+(+_+;+J.:+T.T.T.T.S.S.W.<+'+[+)+!+-.}+|+` ^+-.%+V.V.t ", +" e.3.$+%+V.V.-+ +-./+/+;+;+(+(+>+J.<+W.S.W.W.1+1+1+<+2+3+4+5+-.&+-.|+Z.'.U.V.6+# ", +" 7.3.#+A.%+V.-+++-.7+7+/+>+;+(+>+J.<+1+1+H.H.H.H.H.u 8+9+0+'+` -.&+*+=+` a+6+6+t ", +" b+3.~+$+H.H.V. +-.& 7+7+/+>+;+c+X.u U.H.#+U.U.a+!+d+e+f+2+g+-.{+]+^+-.a+h+h+t ", +" k.#+U.H.%+H.H. +'._ & 7+7+/+;+i+X.u a+a+j+!+k+!+!+5 l+m+<+g+-.}+|+` )+k+k+t ", +" 7.h+$+$+U.H.H. +-._ _ & 7+7+i+i+..n !+)+k+5+)+5+5+n+n m+m+8+-.&+-.o+5+p+t ", +" 7.~+U.$+H.H.H.-.1._ q+_ & 7+7+i+..n )+5+M.5+5+o+4+h h l+l+m+-.` g+o+o+t ", +" 7.~+~+U.U.U.U.++'.r+_ s+_ & 7+i+..5 o+o+o+o+3+o+3+- h t+d+m+e+f+g+4+t ", +" 7.H.~+U.U.U.a+ +'.r+q+q+s+_ & c+x.5 o+o+o+g+g+g+g+0 4 n+n d+m+e+M.t ", +" k.t ^.B.V.H.~+++'.u+r+r+_ s+& c+J.h 3+g+v+g+g+v+v+3 0 h 5 d+d+j+t ", +" Z t t t C ! w+u+r+u+q+q+_ _ ..{ g+2+<+2+2+f+<+x+0 h n+5 !.t ", +" t # t y+y+r+r+y+y+s+..{ v+2+v+8+f+f+f+x+0 h 5 [+t ", +" t t t t _ _ y+#.4 f+f+f+8+f+m+f+2 3 n 0.t ", +" Z t t .+Z j+m.3+m+8+8+8+~ l+q t ", +" z+.+t t O N L.j+4+y p t ", +" Z t t .+A+k w+ ", +" r t t ", +" "}; +*/ + +const char * folder_favorite_xpm[] = { +"20 20 78 1", +" c None", +". c #444444", +"+ c #474747", +"@ c #414141", +"# c #383838", +"$ c #CEC765", +"% c #FFF373", +"& c #FFEF77", +"* c #FFEC78", +"= c #FFE87C", +"- c #B7A569", +"; c #DACD6D", +"> c #FFE97B", +", c #FFE67D", +"' c #FFE182", +") c #FFE082", +"! c #FFDE83", +"~ c #FFDD84", +"{ c #DABE78", +"] c #FFF6AA", +"^ c #FFE79E", +"/ c #FFF1A5", +"( c #FFEFA4", +"_ c #FFDB87", +": c #FFD88A", +"< c #FFD68B", +"[ c #FFD48E", +"} c #FFD48D", +"| c #FFD48C", +"1 c #FFD58B", +"2 c #F6CE88", +"3 c #FFEEA3", +"4 c #FFECA1", +"5 c #DACB8F", +"6 c #FFE89F", +"7 c #FFE69D", +"8 c #FFE49B", +"9 c #FFE39A", +"0 c #FFE29A", +"a c #FFE199", +"b c #FFE098", +"c c #FFDF97", +"d c #FFDE96", +"e c #FFDD95", +"f c #FFDC94", +"g c #FFECA2", +"h c #FFEBA1", +"i c #FF0000", +"j c #FFDC95", +"k c #FFDB94", +"l c #FFEBA0", +"m c #FFE89E", +"n c #FFE79D", +"o c #FFD992", +"p c #FFE99E", +"q c #FFE69C", +"r c #FFE59B", +"s c #FFE299", +"t c #FFD791", +"u c #FFD891", +"v c #FFD68F", +"w c #FFD690", +"x c #FFD790", +"y c #FFE198", +"z c #FFDF96", +"A c #FFDE95", +"B c #FF8357", +"C c #FF8658", +"D c #FFD58F", +"E c #FFDA93", +"F c #FF9262", +"G c #FF8558", +"H c #FFD58E", +"I c #FFDB93", +"J c #FFDA92", +"K c #FF9664", +"L c #FF9060", +"M c #FF895B", +" ", +" .++++@ ", +" #$%&*=-. ", +" ++++++++++;>,')!~{+", +"+]]^^////(+_:<[}|12+", +"+]]^^^33345+++++++++", +"+](3^^^6677890abcde+", +"+((36^^aaaabccddeff+", +"+(gh6^iiidiiijjfkkk+", +"+lmn8iiiiiiiiiooooo+", +"+pqrsiiiiiiiiittuuu+", +"+8sbdiiiiiiiiivvwxx+", +"+yzAfBiiiiiiiCDDvvv+", +"+cejEEFiiiiiGHDDvvv+", +"+IJouuwKiiiL[[HHHHH+", +"+ouuxxvDBiM[[[[[[[[+", +"+HHHHH[[[[[[[[[[[[[+", +" ++++++++++++++++++ ", +" ", +" "}; + +const char * bigfavorites_xpm[] = { +"44 44 263 2", +" c None", +". c #DB4848", +"+ c #FF0000", +"@ c #FF9393", +"# c #FF4C4C", +"$ c #FA9191", +"% c #F64F4F", +"& c #F80505", +"* c #FC0808", +"= c #FC9A9A", +"- c #FA6262", +"; c #FC2C2C", +"> c #FC4141", +", c #FF3A3A", +"' c #FF1111", +") c #FE0D0D", +"! c #F92222", +"~ c #FF8181", +"{ c #FFF2F2", +"] c #FF0202", +"^ c #FF0707", +"/ c #EE0808", +"( c #FC2525", +"_ c #FE0000", +": c #C70808", +"< c #B60B0B", +"[ c #BD0A0A", +"} c #591A1A", +"| c #663939", +"1 c #736040", +"2 c #907750", +"3 c #927851", +"4 c #937952", +"5 c #917751", +"6 c #746040", +"7 c #FA0303", +"8 c #F60808", +"9 c #BF0909", +"0 c #A80D0D", +"a c #961010", +"b c #957B52", +"c c #E0B87D", +"d c #9C8157", +"e c #FC1717", +"f c #FA2323", +"g c #FF3F3F", +"h c #E41616", +"i c #E30404", +"j c #BE0A0A", +"k c #9D7272", +"l c #7C6745", +"m c #AF9161", +"n c #836D49", +"o c #DD5454", +"p c #FF5050", +"q c #FF8383", +"r c #FF7070", +"s c #5A1C1B", +"t c #5A1B1B", +"u c #7E4D48", +"v c #E1D0C5", +"w c #C1AD96", +"x c #927951", +"y c #967C53", +"z c #AB8D5F", +"A c #DC4D4D", +"B c #FF2525", +"C c #FF5252", +"D c #D8C8B9", +"E c #E2D3C8", +"F c #DBCBBE", +"G c #B7A489", +"H c #5C1E1C", +"I c #632722", +"J c #5D1E1E", +"K c #7A433F", +"L c #F5DECC", +"M c #E4C290", +"N c #DFB97C", +"O c #B69765", +"P c #EDE19E", +"Q c #F2E5B5", +"R c #F8ECD5", +"S c #F8EBD6", +"T c #F3E3C0", +"U c #E6C78F", +"V c #7A4233", +"W c #60231F", +"X c #622323", +"Y c #804C47", +"Z c #EFD6BA", +"` c #B59564", +" . c #806E4A", +".. c #ECDD9F", +"+. c #F4E5C6", +"@. c #F7E8D4", +"#. c #F3E1C4", +"$. c #E3C385", +"%. c #E1BF81", +"&. c #7E4635", +"*. c #5F211E", +"=. c #9D7068", +"-. c #E5C392", +";. c #CBA770", +">. c #A98D5E", +",. c #B29664", +"'. c #BB9C69", +"). c #BC9D6A", +"!. c #B89A67", +"~. c #8D754E", +"{. c #947F56", +"]. c #EBDC99", +"^. c #E9D795", +"/. c #E8D291", +"(. c #F2DFBF", +"_. c #F6E5D1", +":. c #F1DBBD", +"<. c #72372C", +"[. c #C7A48B", +"}. c #CAA770", +"|. c #A5895C", +"1. c #E2C384", +"2. c #FFDD96", +"3. c #FFDC94", +"4. c #FFDB93", +"5. c #967D54", +"6. c #958057", +"7. c #E6CE8D", +"8. c #E4C889", +"9. c #F2DDC2", +"0. c #F5E2CF", +"a. c #EBCFA9", +"b. c #C9A06C", +"c. c #DCC182", +"d. c #FFE39A", +"e. c #FFE299", +"f. c #FFE098", +"g. c #FFDF97", +"h. c #FFDE96", +"i. c #FFDC95", +"j. c #FFDB94", +"k. c #ECC887", +"l. c #9A8156", +"m. c #E4C48D", +"n. c #F5E0CD", +"o. c #C8A66F", +"p. c #DCC685", +"q. c #FFE99F", +"r. c #FFE79E", +"s. c #FFE69D", +"t. c #FFE59C", +"u. c #FFE39B", +"v. c #FFE198", +"w. c #FFDD95", +"x. c #FFDA93", +"y. c #C0A16C", +"z. c #CBAB73", +"A. c #DDCA8A", +"B. c #FFEEA4", +"C. c #FFEDA3", +"D. c #FFECA1", +"E. c #FFEAA0", +"F. c #FFE89E", +"G. c #FFE49B", +"H. c #FFE29A", +"I. c #FFE199", +"J. c #FFD992", +"K. c #C0A26C", +"L. c #E4D592", +"M. c #FFF4A8", +"N. c #FFF3A7", +"O. c #FFF1A6", +"P. c #FFF0A5", +"Q. c #FFEFA4", +"R. c #FFECA2", +"S. c #FFEBA1", +"T. c #FFE9A0", +"U. c #FFE89F", +"V. c #FFE79D", +"W. c #FFD891", +"X. c #C2A46E", +"Y. c #FFF6A9", +"Z. c #FFF5A9", +"`. c #FFF3A8", +" + c #FFF2A7", +".+ c #FFF1A5", +"++ c #FFEEA3", +"@+ c #FFEDA2", +"#+ c #FFD791", +"$+ c #C2A36E", +"%+ c #CCAE76", +"&+ c #FFE097", +"*+ c #EAC483", +"=+ c #947E55", +"-+ c #FFD790", +";+ c #C0A06B", +">+ c #BFA16C", +",+ c #DECF8D", +"'+ c #FFF4A9", +")+ c #FFF2A6", +"!+ c #FFD892", +"~+ c #FFD68F", +"{+ c #947D54", +"]+ c #FFEFA5", +"^+ c #FFD690", +"/+ c #FFD58F", +"(+ c #C2A26D", +"_+ c #937C54", +":+ c #A68A5C", +"<+ c #FFEBA0", +"[+ c #FFDE97", +"}+ c #FFD48E", +"|+ c #7F6A47", +"1+ c #DBCB8B", +"2+ c #FFE69C", +"3+ c #FFDA92", +"4+ c #E8C181", +"5+ c #9E8358", +"6+ c #FFD58E", +"7+ c #C09F6B", +"8+ c #BFA06B", +"9+ c #DCCC8A", +"0+ c #C2A26C", +"a+ c #A78A5D", +"b+ c #BF9F6B", +"c+ c #BF9F6A", +"d+ c #C2A16C", +"e+ c #E4D390", +"f+ c #ECC886", +"g+ c #C1A36D", +"h+ c #C0A06C", +"i+ c #907850", +"j+ c #CBA86F", +"k+ c #E8C887", +"l+ c #C0A26E", +"m+ c #BFA26D", +"n+ c #C1A46E", +"o+ c #BFA26C", +"p+ c #8A734D", +"q+ c #EDD18C", +"r+ c #C7AC74", +"s+ c #C2A670", +"t+ c #BFA36E", +"u+ c #C0A46E", +"v+ c #89724C", +"w+ c #DAC788", +"x+ c #F2DB95", +"y+ c #C0A570", +"z+ c #BFA570", +"A+ c #C1A771", +"B+ c #C2A771", +"C+ c #C9AF76", +"D+ c #F2DE98", +"E+ c #C0A670", +"F+ c #BFA771", +"G+ c #C1A972", +"H+ c #BFA670", +"I+ c #A2875B", +"J+ c #9A8459", +"K+ c #9C865A", +"L+ c #AF9564", +"M+ c #B39967", +"N+ c #BDA56F", +" ", +" ", +" ", +" ", +" ", +" . . . . ", +" . + + + . . @ + + ", +" . + + # + + . . $ % & + + ", +" . + # @ # + + . * = - ; > , ", +" . + @ # + + + + ' + ) ! # ~ { ", +" . + @ # + + + ] + ^ + + / ( { { { ", +" . + + + + + ] + + + _ : < [ } } } | 1 2 3 4 4 4 5 6 ", +" . + + 7 8 & + + _ 9 0 a } } } } | { { { b c c c c c c d ", +" . * e f ; > g h i j } } | } } } } k { { l m c c c c c c c n ", +" o + ) ! p q @ r } | } s t } u v w x x y m c c c c c c c c z ", +" A + + ^ B C D E F G } | | H } I J K L M N N N N c c c c c c c O ", +" . + + + P P Q R S T } | U V } W X Y Z N N N N N N N N N N N ` ", +" .P . + P P P P ..+.@.#.| $.%.&.} *.} =.-.N N N N N N N N ;.>.,.'.).!.~. ", +" {.P P P P P P ].^./.(._.:.%.N N <.} } } [.N N N }.|.|.|.|.|.|.1.2.3.4.5. ", +" 6.P P P P P ].^./.7.8.9.0.a.N N b.} } } |.|.|.|.|.|.c.d.e.f.g.h.i.j.k.l. ", +" 6.P P P P ].^./.7.8.$.m.n.n.M o.|.|.|.|.|.p.q.r.s.t.u.e.v.g.h.w.j.x.y. ", +" 6.P P P ].^./.7.8.$.z.|.|.|.|.|.A.B.C.D.E.q.F.s.t.G.H.I.f.h.w.3.x.J.K. ", +" 6.P P ].^./.7.|.|.|.|.L.M.N.O.P.Q.C.R.S.T.U.V.t.G.d.I.f.g.2.i.j.J.W.X. ", +" 6.P ].^./.7.8.|.Y.Y.Y.Z.`. +.+Q.++@+S.E.q.r.s.t.d.e.v.g.h.w.j.x.J.#+$+ ", +" {.].^./.7.8.%+|.Y.Y.Z.M. +O.P.B.@+D.E.q.F.s.t.G.H.I.&+h.w.3.x.J.W.*+y. ", +" =+^./.7.8.$.|.|.Y.Z.M.N.O.P.Q.C.R.S.q.F.V.t.G.d.I.f.g.2.3.4.J.W.-+;+>+ ", +" =+/.7.8.$.%.|.,+Y.'+N.)+P.Q.++R.S.E.U.r.s.G.d.e.f.g.h.i.j.x.!+-+~+y. ", +" {+7.8.$.%.;.|.Y.Z.`. +O.]+++@+S.E.q.r.s.t.u.H.v.g.h.w.j.x.J.#+^+/+(+ ", +" _+8.$.%.N :+|.Z.M.N.O.P.Q.C.R.<+q.F.V.t.G.H.I.f.[+w.3.x.J.W.^+/+}+(+ ", +" |+$.%.N N |.1+M.N.)+P.Q.++R.S.E.U.V.2+G.d.e.f.g.h.i.j.3+W.-+~+}+4+;+ ", +" 5+N N }.|.Z.`. +.+Q.++@+S.E.q.r.s.t.d.e.v.g.h.w.j.x.J.#+^+6+}+7+8+ ", +" x N N |.|.M. +O.P.B.C.D.E.q.F.s.t.G.H.I.f.h.w.3.x.J.W.^+/+}+}+;+ ", +" x N N |.9+N.O.P.Q.C.R.S.T.F.V.t.G.d.I.f.g.2.i.4.J.W.-+/+}+}+}+0+ ", +" x N ;.|.`.)+P.Q.++R.S.E.U.r.s.G.d.e.f.g.h.i.j.x.!+-+~+}+}+}+}+;+ ", +" x N a+|. +O.P.++@+D.E.q.F.s.t.G.H.v.&+h.w.3.x.J.W.^+/+4+7+b+c+d+ ", +" x N |.e+O.P.Q.C.R.S.q.F.V.t.G.d.I.f.g.2.3.4.f+y.>+g+(+8+h+ ", +" i+j+|.)+P.Q.++R.S.E.U.r.2+G.d.e.f.g.k+l+m+n+o+g+ ", +" p+|.|.O.Q.++@+S.E.q.r.s.t.u.q+r+s+s+t+u+ ", +" v+|.w+P.B.C.D.E.q.x+y+z+A+B+C+ ", +" v+|.P.Q.C.D+E+F+G+H+E+ ", +" v+I+J+K+L+M+N+ ", +" ", +" ", +" "}; + +const char * desktop_xpm[] = { +"46 37 247 2", +" c None", +". c #262626", +"+ c #9BA6BB", +"@ c #94A2B9", +"# c #96A6BD", +"$ c #919EB6", +"% c #8C99B1", +"& c #8697AC", +"* c #3D3D3D", +"= c #FFFFFF", +"- c #9DAABD", +"; c #929AAE", +"> c #A6AEBF", +", c #A3AABD", +"' c #9AA2AE", +") c #99989C", +"! c #969DAB", +"~ c #AAB2C1", +"{ c #9EA6B1", +"] c #848A8B", +"^ c #8A8179", +"/ c #8F8A82", +"( c #7C7269", +"_ c #AAAEBF", +": c #99A0A0", +"< c #AAAAAA", +"[ c #7E8688", +"} c #62615B", +"| c #8A867D", +"1 c #867864", +"2 c #93867D", +"3 c #958774", +"4 c #B4ACAA", +"5 c #7C7667", +"6 c #AEA69E", +"7 c #95908B", +"8 c #A8A09C", +"9 c #AA9B8D", +"0 c #D7CDC3", +"a c #AEB2C2", +"b c #AEB6C3", +"c c #B3B6C1", +"d c #696E68", +"e c #6E6C68", +"f c #726852", +"g c #69625A", +"h c #AF9E91", +"i c #827159", +"j c #C6B4A5", +"k c #736E61", +"l c #868078", +"m c #585C4E", +"n c #293D44", +"o c #7B7E76", +"p c #727A80", +"q c #525B53", +"r c #4D5246", +"s c #4C4E46", +"t c #605D4F", +"u c #B4BAC4", +"v c #BEC0C6", +"w c #AEB2B2", +"x c #79828F", +"y c #9A8F87", +"z c #E1D1C3", +"A c #E3D6CA", +"B c #C4BBB0", +"C c #3F505D", +"D c #585E5D", +"E c #31414C", +"F c #52525A", +"G c #404A41", +"H c #3A3D2E", +"I c #5B5644", +"J c #57563A", +"K c #3C4435", +"L c #434A32", +"M c #4A5662", +"N c #E8E0DA", +"O c #DAD4CA", +"P c #CCC6C4", +"Q c #727E82", +"R c #3D4F4A", +"S c #BAA68E", +"T c #A1917E", +"U c #90806D", +"V c #BCAE9C", +"W c #827A6F", +"X c #BAB4B2", +"Y c #A09992", +"Z c #56626E", +"` c #263538", +" . c #323A46", +".. c #82847E", +"+. c #4A4E2D", +"@. c #7A182D", +"#. c #6C6148", +"$. c #7C6A4E", +"%. c #646969", +"&. c #524F3A", +"*. c #525636", +"=. c #657274", +"-. c #6D7980", +";. c #6E7269", +">. c #B5A89B", +",. c #72665A", +"'. c #D0C0B2", +"). c #4E606C", +"!. c #2F464E", +"~. c #3A4A38", +"{. c #726746", +"]. c #7C7059", +"^. c #0F1A27", +"/. c #2A3436", +"(. c #4A483B", +"_. c #5E5538", +":. c #BEB2AA", +"<. c #E3DAD3", +"[. c #9E8A82", +"}. c #999692", +"|. c #788189", +"1. c #787974", +"2. c #4A3E2E", +"3. c #193625", +"4. c #3C432C", +"5. c #5A5A42", +"6. c #6A6648", +"7. c #887252", +"8. c #5E5A3F", +"9. c #AAA6A4", +"0. c #8A8E8F", +"a. c #787A82", +"b. c #5E6666", +"c. c #6E6B5D", +"d. c #223444", +"e. c #51564D", +"f. c #213A26", +"g. c #2E432E", +"h. c #293F2C", +"i. c #183224", +"j. c #43452C", +"k. c #1A222A", +"l. c #665642", +"m. c #5D6D73", +"n. c #656E77", +"o. c #203A44", +"p. c #324A4C", +"q. c #32423E", +"r. c #3B484A", +"s. c #3D4440", +"t. c #A39788", +"u. c #232D2D", +"v. c #35432F", +"w. c #645D3E", +"x. c #1A3448", +"y. c #132E3D", +"z. c #1B2D37", +"A. c #273A37", +"B. c #1D333E", +"C. c #363D39", +"D. c #4A5250", +"E. c #68695D", +"F. c #132630", +"G. c #263427", +"H. c #92865E", +"I. c #4C513B", +"J. c #313E2B", +"K. c #152E24", +"L. c #32352D", +"M. c #123246", +"N. c #203537", +"O. c #344641", +"P. c #1D2D32", +"Q. c #061627", +"R. c #0A1E2B", +"S. c #152A2F", +"T. c #2A3A32", +"U. c #2E3A36", +"V. c #1B2A29", +"W. c #203332", +"X. c #A28A68", +"Y. c #565E3A", +"Z. c #203625", +"`. c #1F3225", +" + c #2A3827", +".+ c #112637", +"++ c #102234", +"@+ c #0F1E29", +"#+ c #112229", +"$+ c #152627", +"%+ c #1B2E24", +"&+ c #5252EA", +"*+ c #85DD88", +"=+ c #4D563D", +"-+ c #585238", +";+ c #424536", +">+ c #0A1A2A", +",+ c #8E7A58", +"'+ c #193237", +")+ c #152A26", +"!+ c #293E3A", +"~+ c #364A36", +"{+ c #454F3B", +"]+ c #364A3C", +"^+ c #303E3B", +"/+ c #1E2E2C", +"(+ c #6D623E", +"_+ c #1A322D", +":+ c #1E322E", +"<+ c #1A2627", +"[+ c #313A28", +"}+ c #86764C", +"|+ c #4A4930", +"1+ c #4A422A", +"2+ c #504A37", +"3+ c #2E3E42", +"4+ c #991299", +"5+ c #4A5652", +"6+ c #444E47", +"7+ c #AAAD62", +"8+ c #827F74", +"9+ c #62624F", +"0+ c #605D46", +"a+ c #847658", +"b+ c #7E7970", +"c+ c #525144", +"d+ c #5D6259", +"e+ c #8E7E62", +"f+ c #B7A18B", +"g+ c #737266", +"h+ c #676655", +"i+ c #726E56", +"j+ c #897E67", +"k+ c #717873", +"l+ c #61675C", +"m+ c #AAA292", +"n+ c #8A8888", +"o+ c #8E8F8F", +"p+ c #7E8280", +"q+ c #9C8A73", +"r+ c #BEA894", +"s+ c #778181", +"t+ c #868E92", +"u+ c #5A5651", +"v+ c #919191", +"w+ c #4F4F4F", +"x+ c #000000", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". + + @ @ @ @ # # # # @ @ @ @ + # # # # # # # # @ @ @ @ @ @ @ $ $ $ % % % % % % & & & & & . ", +". # * * = + + + # - - - + + + - - - - + # # # # @ # # # # @ @ $ $ $ $ $ $ $ % $ % % ; ; & . ", +". - + = * + - + - + - - - - > - - - - - , - , + - + + ' @ # @ # @ @ @ @ $ $ $ % $ ; % % & . ", +". , - * = - > - > > , , , > > , , > , , > > > , > , , + - - + + + + @ ) ' # @ @ @ ! $ ; % . ", +". > * = * > , , , , > > ~ ~ ~ ~ > > ~ > > > , > , , , > , - ! { ] ^ / ( _ ) , { : ' ; : ! . ", +". _ > _ , > > > ~ ~ ~ ~ ~ > > > > ~ ~ > ~ > > > , < > > { [ } | } 1 2 3 4 5 6 7 / 8 9 0 < . ", +". _ > ~ a , + a ~ ~ ~ ~ ~ b b b c ~ a b ~ ~ ~ > > > , { d e f | g h i j 4 k / l 2 ( 4 m n . ", +". o p q r s t ! u ~ a b a ~ u v u b c a a w ~ _ ~ ) ! x l y z 6 f j h A z z B 9 p C D E F . ", +". G H I J K L t a u @ M ' v N A O P b u b b c w Q C R q y S T T U A z V 5 W X Y Z ` n .... ", +". +.= @.= #.$.I %.! K &.*.N X a A N 0 u c c ~ =.Z -.;.8 j B >.,./ '.z 7 g D -.-.).!.D ( | . ", +". ~.@.@.@.{.$.].^./.(.#._.( ] >.:.N <.8 < _ -.!.D 7 h V h >.[.T 3 '.z }.|.|.Z ). .1.2.( k . ", +". 3.4.@.@.5.6.#.^.K #.7.8.( Y 4 A 9.) 0.a.|.D b.c.} o t ^ ,.t k #.B P [ M p d./.%.s } e e.. ", +". f.g.h.i.f.j.h.k.4.g {.l.8.1 j x m.x n.).o.p.p.q.p.r.s.o ;.W V T t.y |.=.C d.Z e.s.F u.F . ", +". ~.h.j.~.i.3.i.v.H w.{.&.8.7.l !.x.x.C y.z.R A.E B. .E C.D.K E.5 q.u.r.E F.G.G.F s.H s.G.. ", +". H.I.J.v.f.K.i.q.L.&.8.L.l._.D x.M.M.y.y.n z.x.M.N.R q D s.O.u.z.N.P.!.Q.R.S.T./.U.u.V.W.. ", +". X.Y.3.h.Z.K.i.3.`.`.I 2.2.G. +T.x.y.y.y.x.y..+.+++S.V.o.N.F.S.S.@+z.++Q.Q.@+#+$+K.V.%+K.. ", +". X.&+*+i.i.K.i.i.3.f.=+-+K c.{.w.;+z.x.y.p.x..+R.++.+++++#+S.#+R.>+.+Q.Q.^.@+++$+#+$+$+K.. ", +". L.*+i.&+K.i.K.i.i.3.%+K.H 7.,+w.L i.'+!.'+y..+.+++R.>+++++++R.>+Q.Q.Q.Q.>+Q.F.R.R.#+)+)+. ", +". %+&+*+&+K.K.i.K.i.i.i.i.Z.J.v.G.%+Z.i.T.R !+E .+++++.+#+#+R.#+R.>+Q.Q.Q.^.>+#+R.@+@+)+F.. ", +". L *+&+*+g.h.h.h.~+L v.v.~+{+=+{+~.~+O.K R R R O.]+g.!.O.O.O.!.q.^+q.E A.A.W.` /+/+/+%+`.. ", +". 6.v.Z.Z.`.i.3.i.Z.f.v. +4.(+(+-+J._+%+!+]+:+_+.+.+F.#+$+$+$+#+@+@+^.Q.>+>+@+$+$+$+$+<+)+. ", +". {.v.Z.`.%+i.`.`.Z.G.J.[+L (+6.-+J.Z._+q.R A.'+S.)+F.F.$+S.)+$+#+@+@+@+@+@+#+)+$+$+$+V.)+. ", +". }++.Z.G.`.%+`.Z.Z. +|+4.1+w.(+-+v.N.B.o.q.'+z.S.S.S./+W.W./+V.<+k.W.F.^.k.#+<+V.V.<+%+%+. ", +". }++.f.[+`.`.`.G.f.4.J j.2+w.w.L ^+^+` ` A.W.:+z.u.A.U.^+U.T.C.q./.3+u.@+@+$+/+G.u.V.%+V.. ", +". (+4+ +v.G.Z.G. +L.+._.1+_.w.].w.e.D.5+O.O.3+` A.!+G r 6+{+s.(.;+L ;+E u./+V.L.K [+L.[+[+. ", +". _.7+4+7+[+v.G. +4.-+w.2+(+$.U 8+5 t 5+r.q.^+^+q.K r (.9+0+-+f w.9+g 5+E 3+G.C.K C.H K H . ", +". +.7+7+4+|+|+4.G.2.-+w._.{.a+t.3 5 b+e D D q G s c+t 5.c.6.6.a+f ,+W d+D.G U.G r L ;+j.{+. ", +". 4.4+j.|+|+&.+.[+-+5._._.7.e+8 f+h t.1.g+d b.5+q 5.h+6.( 1 i e+i t.t.5 D D 6+(.s |+&.c+c+. ", +". I.-+*.I._._.&.9+d c.w.6.T 9 9 t.T 7 ..o ..%.r 5.E.i+k U U j+i i f+f+5 m e.r 5+s s 2+#.0+. ", +". c+8.9+w.8._.5.9+g+E.f g+t.y 9 S >.Y | / 0.;.D t h+E.W e+H.e+j+}+f+S | c.,.k t s (.(.8.i+. ", +". d+0+I c+w.0+h+k+k+9+l+b+h Y }.m+9.: / n+o+p+k+-.;.k+;.^ T q+,+].r+f+3 ].f ( e D.6+e.2+c.. ", +". h+l+l+k+o s+[ [ p+1.5 1.7 7 y 6 8 ) n+t+t+] p 1.1.5 1 W a+1 3 i j f+T ].j+^ W q C.u+t k . ", +". v+&+v+v+v+4+v+v+*+*+*+v+v+v+v+@.v+v+v+w+v+v+v+v+v+v+w+v+v+v+v+v+v+v+w+v+v+w+v+v+v+v+v+v+. ", +". &+x+x+v+4+4+4+v+*+7+*+v+v+v+@.v+@.v+v+w+v+x+x+v+x+v+w+v+x+x+v+x+x+v+w+v+v+w+v+x+x+v+x+v+. ", +". x+v+&+v+v+4+v+v+*+*+*+v+v+@.v+@.v+@.v+w+v+v+v+v+v+v+w+v+v+v+v+v+v+v+w+v+v+w+v+v+v+v+v+v+. ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "}; + +const char * bigtemporary_xpm[] = { +"44 44 124 2", +" c None", +". c #726242", +"+ c #927652", +"@ c #927A52", +"# c #766242", +"$ c #967A52", +"% c #DEBA7A", +"& c #967E56", +"* c #7E6646", +"= c #AA8E5E", +"- c #DEBA7E", +"; c #826E4A", +"> c #967E52", +", c #A68A5E", +"' c #E2BE82", +") c #B69666", +"! c #E6CE8E", +"~ c #E6CA8A", +"{ c #E2C686", +"] c #E2BE7E", +"^ c #CAAE76", +"/ c #E2C282", +"( c #CAA672", +"_ c #BA9E6A", +": c #BE9E6A", +"< c #BA9A66", +"[ c #8E764E", +"} c #CAA66E", +"| c #A2865A", +"1 c #A68A5A", +"2 c #FEDA96", +"3 c #AE9A6A", +"4 c #CEBE86", +"5 c #EAD692", +"6 c #E6D292", +"7 c #EAC282", +"8 c #FEDE96", +"9 c #FEE29A", +"0 c #EAC682", +"a c #9A8256", +"b c #DECE8A", +"c c #EADA96", +"d c #FEE69E", +"e c #FEDA92", +"f c #C2A26E", +"g c #A28A5E", +"h c #C2AE7A", +"i c #E2D292", +"j c #EEDE9E", +"k c #EADA9A", +"l c #FEEEA6", +"m c #FEEAA2", +"n c #9A825A", +"o c #BAA672", +"p c #D6C68E", +"q c #EEE29E", +"r c #EADE9E", +"s c #EADE9A", +"t c #EAD696", +"u c #EED28E", +"v c #DEC686", +"w c #FEF2A6", +"x c #FEF2AA", +"y c #FEEEA2", +"z c #FED692", +"A c #C2A66E", +"B c #D2BE86", +"C c #B29666", +"D c #FEEA9E", +"E c #FED68E", +"F c #86724E", +"G c #E2CE92", +"H c #BEAA72", +"I c #E6D692", +"J c #FEE296", +"K c #968256", +"L c #D6C286", +"M c #BEA26A", +"N c #BEA26E", +"O c #A28E62", +"P c #BEA672", +"Q c #B29A66", +"R c #FAEEA2", +"S c #FEF6AA", +"T c #FEE69A", +"U c #C29E6A", +"V c #EEE29A", +"W c #D2BE82", +"X c #C2AE76", +"Y c #CEB67E", +"Z c #F6EAA2", +"` c #9A865A", +" . c #EEDE9A", +".. c #A68E5E", +"+. c #C2A26A", +"@. c #D2BA82", +"#. c #B69E6A", +"$. c #B29E6E", +"%. c #D6BA7E", +"&. c #E2D692", +"*. c #C6AA72", +"=. c #DECA8A", +"-. c #C6B27E", +";. c #A69262", +">. c #DEC282", +",. c #F2E69E", +"'. c #7E6A46", +"). c #C6AE76", +"!. c #EECA86", +"~. c #B29A6A", +"{. c #AE9262", +"]. c #E2D28E", +"^. c #EACA86", +"/. c #C2A672", +"(. c #D2BA7E", +"_. c #9E8256", +":. c #F6DE96", +"<. c #DAC286", +"[. c #B29262", +"}. c #E6D28E", +"|. c #FAE69E", +"1. c #8A724E", +"2. c #BAA26E", +"3. c #AA9666", +" ", +" ", +" ", +" ", +" ", +" ", +" . + @ @ @ @ + # ", +" $ % % % % % % & ", +" * = % - - - % % % ; ", +" @ @ @ > = - - % % % - % - , ", +" @ @ @ @ @ ' - - - % % % % % % - % % ) ", +" ! ~ { ' ] - % % % - ^ % % % % % % ) ", +" # / ' % % % % % - - - % ^ - ( , ) _ : < [ ", +" @ & . . / ' % - ^ % - % % } | | | 1 1 | / 2 2 2 & ", +" 3 4 5 6 ! . . ] - % - - | | | | , , 7 8 8 9 8 8 8 8 0 a ", +" @ @ b c c 6 ! # . ' ( , | | , | 7 d 9 9 9 9 9 9 8 8 8 e e f ", +" @ g h i j k 5 ! ~ . | | { l m m m d m d d 9 9 9 8 8 8 8 e e f ", +" @ n o p q j r s t 6 u v . w x w m y m d m d d 9 d 9 8 9 8 e e z z A ", +" B j q j q q j s 6 ^ C . # y l y m m D d d d 9 9 9 8 8 8 2 e e E f ", +" F b q j q r j s G f H I w . # y m m D d d 9 9 9 9 J 8 8 8 e e E 7 f ", +" K h q r q q q L o , I w w w . . m y y D D d d d 9 8 8 8 8 e e e e e M N ", +" O r q j r P Q v R S w w l # l y y m D d d d T 9 9 9 8 8 2 2 e z z E U ", +" K p V q j W X S S S w w . . m D m m d d 9 9 9 9 9 8 8 8 e e E z z f ", +" o r j s Y , Z x x x y . # m d D d T d 9 9 8 8 8 e e e e z E E f ", +" ` q q .H ..I S w w l y y . # d D d 9 T J 9 8 8 8 e e z E E E 7 +. ", +" K 4 r r @.#.V S S w w l l D m d T T T 9 9 8 8 8 e 2 e E z E E : : ", +" $. .c %.1 Z w w w w y y D . D D D d d 9 9 8 8 8 2 8 e e e E z E E : ", +" & &.k *., =.S S y y y m m d d 9 9 9 8 9 9 8 8 e e z z z E E E f ", +" & -.k @.3 c w w w l l y # d T T 9 8 8 8 e e e e E E E E E E U ", +" ;.5 >.1 ,.w w l y y m . . d 9 9 9 9 8 2 8 2 z z z E ] U U U f ", +" '.).*.= L x w l y m D d D . ; 9 9 8 8 8 e e !.+.U f U U : ", +" ~.{.].w w w y y m D d T v 9 9 8 9 ^.f f A N f ", +" | = V w y l y m m D d T d u ^ A /.N P ", +" ) = (.l w y m y D d d 9 *.^ ", +" _.{.b l l y m m m :.v ", +" , 5 w y y y D 9 <./. ", +" [.[.(.w y m m }.(.P A ", +" @ ..Y l l |.).P ", +" 1.| b y 5 Y 2. ", +" 1.> #.3.g ", +" [ g ", +" ", +" ", +" "}; + +const char * bigdocuments_xpm[] = { +"44 44 173 2", +" c None", +". c #746242", +"+ c #927A52", +"@ c #9292C6", +"# c #9292C2", +"$ c #927652", +"% c #929EFE", +"& c #928276", +"* c #A2A2E6", +"= c #B6BEFE", +"- c #AAB2FE", +"; c #B6AAC2", +"> c #DEBA7A", +", c #9E8258", +"' c #96A2FE", +") c #82767A", +"! c #929AE6", +"~ c #BAC2FE", +"{ c #BAC2EA", +"] c #D6DEFE", +"^ c #A2A6EA", +"/ c #C2AEB2", +"( c #826E4A", +"_ c #9AA2FE", +": c #DAE2FE", +"< c #9AA6FE", +"[ c #968A96", +"} c #C2CAFD", +"| c #D2DAFA", +"1 c #525A8E", +"2 c #5E669C", +"3 c #CAD2FE", +"4 c #9A9EF6", +"5 c #CAB2A2", +"6 c #A68A5E", +"7 c #C2CAF0", +"8 c #626EA2", +"9 c #7E86C8", +"0 c #9EA2EA", +"a c #C6CEFE", +"b c #AAB2DA", +"c c #464E86", +"d c #D2DAFE", +"e c #323A76", +"f c #7A82B2", +"g c #969EF2", +"h c #D2B28E", +"i c #BA9A66", +"j c #D6CEB6", +"k c #AEB2E0", +"l c #B2BEFE", +"m c #A6AEDA", +"n c #8A92BE", +"o c #727AAA", +"p c #1A2662", +"q c #AAB2F6", +"r c #A6AEFE", +"s c #CAD6FE", +"t c #626AA0", +"u c #AEB6E3", +"v c #929AC6", +"w c #B6BEEE", +"x c #B29668", +"y c #ECDE9C", +"z c #AAAEE6", +"A c #B2BAFE", +"B c #8E96C6", +"C c #161E5E", +"D c #B2BAE4", +"E c #828EE6", +"F c #AEB6FD", +"G c #C2CAF6", +"H c #9EA6D6", +"I c #767EB6", +"J c #2A3672", +"K c #3A467E", +"L c #6672AA", +"M c #CAA671", +"N c #AA8E5E", +"O c #BA9E6A", +"P c #BE9E6A", +"Q c #8E764E", +"R c #968256", +"S c #EEE29E", +"T c #6E7AB2", +"U c #BEC6F8", +"V c #6A72A8", +"W c #AEBAE6", +"X c #8A96F2", +"Y c #626AA6", +"Z c #C6CEFA", +"` c #A2865A", +" . c #E2C284", +".. c #FEDE96", +"+. c #FEDA92", +"@. c #967E56", +"#. c #CECABE", +"$. c #4E569A", +"%. c #727EC2", +"&. c #DEC282", +"*. c #FEE69A", +"=. c #FEE296", +"-. c #FEDA96", +";. c #EDCA86", +">. c #9A8256", +",. c #AAB6FE", +"'. c #868ECA", +"). c #4E5A96", +"!. c #A2AADA", +"~. c #121A5A", +"{. c #BAC6FE", +"]. c #DCC688", +"^. c #FEE69E", +"/. c #FEE29A", +"(. c #C29E6A", +"_. c #9292BA", +":. c #AEB6F6", +"<. c #B6C2FE", +"[. c #0A1656", +"}. c #222E6E", +"|. c #CAAA70", +"1. c #DCCA8A", +"2. c #FEEEA6", +"3. c #FEEA9E", +"4. c #FED692", +"5. c #BEA26D", +"6. c #968A8A", +"7. c #020E4E", +"8. c #A2AEEE", +"9. c #3A4286", +"0. c #7E8AC2", +"a. c #E6D692", +"b. c #FEF6AA", +"c. c #FEF2A6", +"d. c #FEEEA2", +"e. c #C2A66E", +"f. c #A2AEE6", +"g. c #A6B2FE", +"h. c #565EA2", +"i. c #FEEAA2", +"j. c #FED68E", +"k. c #C2A26E", +"l. c #969EFE", +"m. c #9AA2EA", +"n. c #2E3A7E", +"o. c #C8AE76", +"p. c #EAC282", +"q. c #A6AAEA", +"r. c #A2AEFE", +"s. c #C6BEBA", +"t. c #0A1256", +"u. c #DECE8A", +"v. c #F2DA96", +"w. c #9EAAFE", +"x. c #927E56", +"y. c #EADA96", +"z. c #7E6A46", +"A. c #E6D292", +"B. c #E6CE8E", +"C. c #C2A26A", +"D. c #E6CA8A", +"E. c #E2C686", +"F. c #E6C68A", +"G. c #E2BE82", +"H. c #EAC682", +"I. c #8A724E", +"J. c #EED28E", +"K. c #C2A672", +"L. c #BEA671", +"M. c #F2DE9A", +"N. c #C2AA72", +"O. c #9E865A", +"P. c #B29A66", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" . + @ # + + $ . ", +" % & * = - ; > > , ", +" % ' - % ) ! ~ { ] ^ / > > ( ", +" % _ = ] : < & [ _ } | 1 2 3 4 5 > 6 ", +" + + & # _ = ] 7 8 9 ~ 0 < a b c d e f } g h i ", +" + + + + + + + + j k _ l d m n o m p q r s t u 7 v { b w ~ * x ", +" ( y y y y y y j z < A 3 B b C 3 k D E F G H I J 3 K L D e M N x O P i Q ", +" R S S S S j z < A a T U 2 G V W 9 X F { H Y Z D M 6 6 ` 6 ` 6 .....+.@. ", +" @.y y #.z < A } } } $.L w V Z %.% = } J 6 6 6 6 6 ` &.*.=.=.....-.+.;.>. ", +" R #.z < ,.~ '.Y m ).!.~.{.9 F M ` ` ` 6 6 ].^.^.^././././.......-.-.(. ", +" _._ - :.= <.^ [.A }.|.` 6 6 6 6 1.2.2.3.3.3.3.^.*.^./.........+.+.4.5. ", +" 6.< r 7.8.9.0.6 ` 6 6 a.b.c.c.c.c.d.d.3.^.^.3.^././././...-...-.+.+.e.% ", +" R f.g.$.h.%.$.6 b.b.b.b.c.c.d.d.d.d.i.i.i.3.*.*.*././.......+.+.+.j.k.l. ", +" @.#.< m.n.,.o.6 b.b.c.c.c.c.c.d.i.i.3.3.^.^././././.........+.+.+.p.5. ", +" @.y q.r.^ 9 6 6 b.b.b.b.c.c.d.i.d.d.i.^.^./.^././...=...+.+.+.4.4.k.5. ", +" @.y s.< ! t.6 u.b.c.c.c.2.2.2.i.3.3.3.3.^./.*././.......+.+.+.j.j.(. ", +" @.y v.^ w.|.` b.b.b.c.c.2.d.d.d.i.3.^.*.^.*./.=.......+.-.+.j.4.j.k. ", +" x.y.a.s._ 6 6 c.c.c.c.c.d.d.i.3.^.3.^.*././...........+.+.4.j.j.j.k. ", +" z.a.A.B.^ 6 1.b.c.c.d.d.2.i.3.i.i.^.^./././././...+.+.+.4.+.j.j.p.C. ", +" , B.D.M 6 b.b.c.c.2.d.d.d.3.3.^.*.^.^././.......-.+.+.j.4.j.j.i k. ", +" + D.E.6 ` c.c.c.2.d.d.d.i.i.^.^.^.*./.........-.+.+.4.4.j.j.j.k. ", +" + F.E.6 u.c.c.c.c.d.i.3.3.3.^./././././...-...+.+.+.j.j.j.j.j.(. ", +" + E.M 6 c.c.2.d.d.i.i.i.^.^.*.^./.=./.......+.+.4.j.4.j.j.j.j.k. ", +" + .6 6 c.c.c.d.d.d.3.i.^.^.*.^./...........-.+.4.j.4.G.(.(.i k. ", +" $ G.6 A.c.d.d.i.d.3.3.^.3.^././././.=...+.+.;.(.C.k.(.(.(. ", +" Q M 6 c.c.2.2.i.i.i.3.^.*.^././.....H.k.k.k.5.5. ", +" I.6 ` 2.d.d.d.i.i.^.^.^.^./.J.|.K.K.L.L. ", +" I.6 1.c.d.d.d.3.3.v.e.e.K.e.o. ", +" I.6 d.d.d.M.e.N.N.e.L. ", +" I.` >.O.x P.5. ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; + +const char * mini_folder_favorites_xpm[] = { +"20 16 36 1", +" c None", +". c #A68A5E", +"+ c #54452F", +"@ c #FEE89E", +"# c #FEE59B", +"$ c #FEE298", +"% c #FEDE95", +"& c #FEDB93", +"* c #CEAB75", +"= c #FEF6A9", +"- c #FEF2A7", +"; c #FEEFA4", +"> c #FEECA1", +", c #FEE99E", +"' c #FEE69C", +") c #FEE399", +"! c #FEDF96", +"~ c #FEDC93", +"{ c #FED991", +"] c #FED68E", +"^ c #FEF3A7", +"/ c #FEF0A4", +"( c #FEEDA2", +"_ c #FEE99F", +": c #FEE097", +"< c #FEDD94", +"[ c #FEDA91", +"} c #FED78E", +"| c #FEF0A5", +"1 c #FEEA9F", +"2 c #FEE79D", +"3 c #FF0000", +"4 c #FEEEA3", +"5 c #FEEAA0", +"6 c #FEEBA0", +"7 c #FEE299", +" ", +" .....+ ", +" .@#$%&.+ ", +" ......*******. ", +" .=-;>,')!~{]].+ ", +" .^/(_'):<[}]].+ ", +" .|(1233<33]]].+ ", +" .4523333333]].+ ", +" .6@#$33333]]].+ ", +" .@#7!~333]]]].+ ", +" .')!~{]3]]]]].+ ", +" .):<[}]]]]]]].+ ", +" ..............+ ", +" ++++++++++++++ ", +" ", +" "}; + +const char * mini_desktop_xpm[] = { +"20 16 284 2", +" c None", +". c #666F7B", +"+ c #656D7A", +"@ c #676E7A", +"# c #676F7C", +"$ c #666F7C", +"% c #646B79", +"& c #626A77", +"* c #616876", +"= c #606875", +"- c #A0A9B9", +"; c #9DA9BD", +"> c #9FAABD", +", c #9EA9BD", +"' c #A0ABBD", +") c #9FA9BD", +"! c #9FAABE", +"~ c #9CA8BC", +"{ c #9BA6BB", +"] c #97A5BB", +"^ c #96A3BA", +"/ c #95A2B9", +"( c #949FB3", +"_ c #919FB6", +": c #909DB4", +"< c #999CA4", +"[ c #9FA7B6", +"} c #A5ADBE", +"| c #A7AFBF", +"1 c #A8B0C0", +"2 c #A7AFC0", +"3 c #A6ADBF", +"4 c #A5ACBD", +"5 c #A5ABBB", +"6 c #9BA4B3", +"7 c #8A8F94", +"8 c #878380", +"9 c #98928F", +"0 c #9A9BA0", +"a c #989B9F", +"b c #A3A3A7", +"c c #5E6163", +"d c #7E8487", +"e c #767B7C", +"f c #A3A9B5", +"g c #A8B0BF", +"h c #A9B1BF", +"i c #B8BCC5", +"j c #B3B7C2", +"k c #AEB4C2", +"l c #ACB2BE", +"m c #A3AAB8", +"n c #9097A3", +"o c #83817D", +"p c #9C9285", +"q c #9C8E7F", +"r c #C1B2A5", +"s c #A9A196", +"t c #827F7B", +"u c #636767", +"v c #393E41", +"w c #42433A", +"x c #8D6265", +"y c #6F6550", +"z c #696965", +"A c #696F6F", +"B c #858479", +"C c #C0BBB9", +"D c #D9D1CA", +"E c #B8B9BE", +"F c #A8AEBA", +"G c #687378", +"H c #757974", +"I c #B1A497", +"J c #9B8D7E", +"K c #C0B3A5", +"L c #A0988F", +"M c #767A7B", +"N c #59646C", +"O c #4D5251", +"P c #565450", +"Q c #283228", +"R c #522C2C", +"S c #544C38", +"T c #373C35", +"U c #5A5643", +"V c #6C624B", +"W c #A2988E", +"X c #A4A3A4", +"Y c #83888D", +"Z c #5A686E", +"` c #4E5856", +" . c #656862", +".. c #7F7A70", +"+. c #877E70", +"@. c #A99D8F", +"#. c #818689", +"$. c #485661", +"%. c #4C5355", +"&. c #545451", +"*. c #424240", +"=. c #454738", +"-. c #38442F", +";. c #203727", +">. c #25392C", +",. c #4F4D38", +"'. c #56503B", +"). c #6A6454", +"!. c #203A4B", +"~. c #203949", +"{. c #243840", +"]. c #203742", +"^. c #304044", +"/. c #444D4B", +"(. c #424A44", +"_. c #364242", +":. c #2A3A42", +"<. c #182A2F", +"[. c #333D3B", +"}. c #2F3833", +"|. c #262E2B", +"1. c #59544C", +"2. c #476A66", +"3. c #1B332C", +"4. c #183224", +"5. c #263A2A", +"6. c #444433", +"7. c #5A5741", +"8. c #3A443A", +"9. c #18313E", +"0. c #1D3643", +"a. c #102434", +"b. c #112431", +"c. c #152834", +"d. c #12252E", +"e. c #0E1F2C", +"f. c #0A1B2C", +"g. c #0C1A28", +"h. c #12242B", +"i. c #152727", +"j. c #1D2A25", +"k. c #333E3A", +"l. c #648EAB", +"m. c #2A4343", +"n. c #1D3627", +"o. c #253A29", +"p. c #4A5039", +"q. c #33412F", +"r. c #283C32", +"s. c #304442", +"t. c #25383F", +"u. c #1B2E35", +"v. c #1D2F35", +"w. c #1A2D35", +"x. c #172730", +"y. c #142430", +"z. c #14242D", +"A. c #14262D", +"B. c #152629", +"C. c #1E2928", +"D. c #474736", +"E. c #2D4233", +"F. c #1E3526", +"G. c #1D3425", +"H. c #283A28", +"I. c #36402C", +"J. c #655E3E", +"K. c #3D4531", +"L. c #233730", +"M. c #2F423C", +"N. c #192F33", +"O. c #152930", +"P. c #182A2C", +"Q. c #17292A", +"R. c #13212B", +"S. c #0F1F2B", +"T. c #11202A", +"U. c #162828", +"V. c #172727", +"W. c #1E2826", +"X. c #544B39", +"Y. c #363C2F", +"Z. c #223326", +"`. c #223426", +" + c #37412C", +".+ c #4B4830", +"++ c #655D3F", +"@+ c #404839", +"#+ c #2A3B3E", +"$+ c #273A3A", +"%+ c #1D2F33", +"&+ c #253534", +"*+ c #2D3C37", +"=+ c #2C3833", +"-+ c #2B3634", +";+ c #1E2C31", +">+ c #162429", +",+ c #23302A", +"'+ c #202D28", +")+ c #222B26", +"!+ c #4E4836", +"~+ c #8F646C", +"{+ c #454536", +"]+ c #2D3928", +"^+ c #504D34", +"/+ c #5F563A", +"(+ c #83755D", +"_+ c #757162", +":+ c #545A56", +"<+ c #3D4A48", +"[+ c #36423D", +"}+ c #4B4F42", +"|+ c #5B5C49", +"1+ c #625D46", +"2+ c #66604B", +"3+ c #49514F", +"4+ c #2C3A36", +"5+ c #3C4438", +"6+ c #3B4031", +"7+ c #32362C", +"8+ c #3F3934", +"9+ c #614D48", +"0+ c #554E38", +"a+ c #4C4E38", +"b+ c #615E49", +"c+ c #73684C", +"d+ c #A09281", +"e+ c #A59686", +"f+ c #818078", +"g+ c #6B6F6C", +"h+ c #52574B", +"i+ c #686653", +"j+ c #817664", +"k+ c #85765D", +"l+ c #9B8A75", +"m+ c #787467", +"n+ c #4E544D", +"o+ c #4B4E44", +"p+ c #524F3C", +"q+ c #434237", +"r+ c #5F5D4A", +"s+ c #636049", +"t+ c #6A6C5F", +"u+ c #6D6E62", +"v+ c #868074", +"w+ c #9F968D", +"x+ c #ACA399", +"y+ c #908E89", +"z+ c #838684", +"A+ c #696E6A", +"B+ c #717267", +"C+ c #8C816C", +"D+ c #8F7F65", +"E+ c #A7947C", +"F+ c #918573", +"G+ c #776E60", +"H+ c #575952", +"I+ c #4F4F42", +"J+ c #8D578E", +"K+ c #8C7E8F", +"L+ c #87BC7E", +"M+ c #8B9989", +"N+ c #907F80", +"O+ c #907176", +"P+ c #818282", +"Q+ c #757777", +"R+ c #717272", +"S+ c #72706D", +"T+ c #74716C", +"U+ c #77736E", +"V+ c #76716C", +"W+ c #7E7A74", +"X+ c #7A7773", +"Y+ c #696A68", +"Z+ c #635C63", +"`+ c #5E8B5B", +" @ c #616C62", +".@ c #5D4348", +"+@ c #5C3E44", +"@@ c #554A4C", +"#@ c #555555", +"$@ c #585858", +"%@ c #535353", +"&@ c #525252", +"+ + . . + @ # $ $ + + + % & * = + + ", +"+ - ; > , ' > ) ! ~ { ] ^ / ( _ : + ", +" < [ } | 1 2 | | 3 4 5 6 7 8 9 0 a b ", +"c d e f g h i j k l m n o p q r s t u v ", +"w x y z A B C D E F G H I J K L M N O P ", +"Q R S T U V W X Y Z ` ...+.@.#.$.%.&.*.", +"=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.", +"1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.", +"k.l.m.n.o.5.p.q.r.s.t.u.v.w.x.y.z.A.B.C.", +"D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.", +"X.Y.Z.`. +.+++@+#+$+%+&+*+=+-+;+>+,+'+)+", +"!+~+{+]+^+/+(+_+:+<+[+}+|+1+2+3+4+5+6+7+", +"8+9+0+a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+", +" r+s+t+u+v+w+x+y+z+A+B+C+D+E+F+G+H+I+ ", +"+ J+K+L+M+N+O+P+Q+R+S+T+U+V+W+X+Y+ + ", +"+ + Z+`+ @.@+@@@#@$@%@#@$@%@&@&@ + + "}; + +const char * my_computer_xpm[] = { +"44 32 101 2", +" c None", +". c #1C2028", +"+ c #292F3A", +"@ c #2F3643", +"# c #232830", +"$ c #12141A", +"% c #080A0B", +"& c #030304", +"* c #0C0E12", +"= c #6A7A9F", +"- c #6E7EA3", +"; c #65789C", +"> c #7083A8", +", c #7286B2", +"' c #627293", +") c #55617D", +"! c #495469", +"~ c #394150", +"{ c #3F4AA7", +"] c #565EBA", +"^ c #515DA2", +"/ c #5562A1", +"( c #5A6987", +"_ c #7E90B0", +": c #8696B1", +"< c #768AB6", +"[ c #525C6B", +"} c #8A96A3", +"| c #9EACBD", +"1 c #8E9EB5", +"2 c #5E6774", +"3 c #171A1E", +"4 c #6674F5", +"5 c #7786FA", +"6 c #8291FC", +"7 c #7785F6", +"8 c #5662E6", +"9 c #4A56E2", +"0 c #3A46E5", +"a c #2530B5", +"b c #2830A4", +"c c #2A369E", +"d c #3A469A", +"e c #444C59", +"f c #A6B4C1", +"g c #ADBCC9", +"h c #93A1B5", +"i c #8390A2", +"j c #8B9AB2", +"k c #323A49", +"l c #6272A8", +"m c #6F7EEE", +"n c #92A1FE", +"o c #6472E8", +"p c #424EEF", +"q c #3642F4", +"r c #1F2AE7", +"s c #111AE7", +"t c #0202DA", +"u c #3E49B1", +"v c #798AAC", +"w c #4B535C", +"x c #5F6E8A", +"y c #77859C", +"z c #667385", +"A c #4A56EE", +"B c #2732EA", +"C c #161EE6", +"D c #020ADA", +"E c #4A55AF", +"F c #778392", +"G c #646E78", +"H c #535FF0", +"I c #030CE5", +"J c #6A7890", +"K c #6E7A89", +"L c #7786A8", +"M c #98A6B8", +"N c #3F4655", +"O c #6C7CF6", +"P c #606CF1", +"Q c #323EEA", +"R c #0912E3", +"S c #727E90", +"T c #7C8A9B", +"U c #5E6AAD", +"V c #0B13D3", +"W c #586270", +"X c #8F9BA6", +"Y c #1B25E7", +"Z c #101AB8", +"` c #434E65", +" . c #1A22B2", +".. c #4E5D79", +"+. c #141ECA", +"@. c #5E6E96", +"#. c #4652A2", +"$. c #2E3AC2", +"%. c #6E7A96", +"&. c #B6C6D2", +"*. c #727A85", +" . + + @ + # . $ $ % & ", +" * = = - - ; - > , > - ' ) ! ~ + . % + @ + # . ", +" . ' { ] ^ ^ ^ ^ / ) ( ; , _ : < < ~ . $ # [ } | | | | 1 2 3 ", +" + ( 4 5 6 6 7 4 8 9 0 a b c d ' _ e - _ [ # . [ } f g f g g h } i j e ", +" k l m 6 n n 6 7 o 8 p q r s t u v w j h | x . . 2 } h | g f y [ z : j | w ", +" ~ ; m 6 n n 6 7 4 8 A q B C D E F 2 f f i ~ ( x [ [ e w G w e y h 1 h | e ", +" e l m 6 n n 6 5 4 H p q B C I / J K g f w J L v > ; > L # + | M M M | f N ", +" ! l 4 5 6 6 5 O P H p Q r s R l G S f S N : i y T _ i > # z | M | | f f ~ ", +" [ U P O O m 4 P 8 A 0 B r V V - [ S h [ W 1 M j y S J G + i f | f f g f @ ", +" [ ^ H 8 P P P 8 A p Q B C R V v w = < e G } } } M h } 2 ~ X f f f f | | # ", +" [ { A A H H A A 0 q B Y s R Z i ` - ' e X | f M | h h [ e M f f | | | h 3 ", +" z { Q p p p 0 0 Q B r s R I .i ` - ) e h i i X | X h e [ h | M M h h } * ", +" z d r Q Q Q Q B r Y s R V I a } ` , ..w } X X X T X T w 2 X M h h 1 1 T ", +" , c C Y Y r Y Y C V R R R I d X ` < ! G j T y T F i z [ 2 } 1 j : : : J ", +" y ^ r +.V R R R R R R R R t E X ! < ! x _ T i _ y } [ 2 2 _ j : _ _ _ ) ", +" ) 1 : L @.#.$.+.V D D I I D l } ..< ` @.' ) ( %.F i e z W _ _ v < , < ! ", +" % e : M M M M 1 v / { a Z Z v T .., ! ' > > - - ; > k F w > < > > > < N ", +" $ ..L 1 | | f g f | M } f S ) < ! ' - @.( = ( ; ~ T ` = > > - - , k ", +" % e w + $ & . ! x y X f g g &.&.&.F ) ; k ; > > = - ( l @ i w ; - - - > , @ ", +" 3 *.L G S *.[ ~ . * k z 2 [ 2 2 G *.z W + * & $ ; > ; @.; ( ; ~ i ..; > > = - < + ", +" $ S S ( ' > = > K K W ~ @ ~ ~ k # & $ ; > - > , ( @.k : [ ; - > > , N ", +"% G - ( S i y T y > > > J z 2 N # * * - > - - > ( @.k j ..l > , ; k ", +"~ S 2 ; _ _ y 1 K j i S : > ; ' @.( ! @ . % ; > - - > @.' ~ 1 ! ; > ..3 ", +"+ F } y K ( x F i : i 1 j K J J - = @.( ( ) ~ & ..> , , > ; ; k M ! ..@ & ", +" # 2 i } S ; ' ; - _ T y F T 1 S ; = = e N . & 3 k ..l > ; ~ : # & ", +" @ G y _ z 2 ( ' _ : j 1 T i > ` ~ ..% # ~ 3 & 3 + $ $ ", +" * ~ G , S ( [ ( J z J ' e k w $ w f | ) ~ k + $ ", +" $ e @.= @.! ..( N . . . y f g J F > ( - > ; + ", +" . ! l > ! $ % ~ j | | f W ( @.` ; , ( $ ", +" % + * & % e J h g g h G ( ( , ' $ ", +" 3 e *.} h 1 _ @.3 ", +" % # ~ ` $ "}; diff --git a/src/fx80print.cpp b/src/fx80print.cpp index 3e53981..85f1a50 100644 --- a/src/fx80print.cpp +++ b/src/fx80print.cpp @@ -40,6 +40,8 @@ #include #include +#include "FLU/Flu_File_Chooser.h" + #include #include #include @@ -92,9 +94,12 @@ VTFX80Print::VTFX80Print(void) m_pUseRomFile = NULL; m_pUseRamFile = NULL; m_pPaperChoice = NULL; - + + m_useRomFile = FALSE; m_useRamFile = FALSE; m_marksMade = FALSE; + m_defSkipPerf = TRUE; + m_defCompressed = FALSE; // Add all papers to the m_paper object m_papers.Add(new VTVirtualPaper()); @@ -259,7 +264,7 @@ Property Dialog callbacks */ void VTFX80Print::CharRomBrowse(Fl_Widget* w) { - Fl_File_Chooser* fc; + Flu_File_Chooser* fc; char defaultfile[256]; // Get default filename for browse @@ -278,7 +283,9 @@ void VTFX80Print::CharRomBrowse(Fl_Widget* w) } // Create a file browser for .fcr files - fc = new Fl_File_Chooser(defaultfile, "*.fcr", 1, "Choose FX-80 Char ROM File"); + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser(defaultfile, "*.fcr", 1, "Choose FX-80 Char ROM File"); + fl_cursor(FL_CURSOR_DEFAULT); // Show the dialog fc->show(); @@ -881,7 +888,7 @@ void VTFX80Print::Deinit(void) { // Delete page memory if (m_pPage != NULL) - delete m_pPage; + delete[] m_pPage; m_pPage = NULL; // Deinitialize the paper diff --git a/src/highlight.cpp b/src/highlight.cpp new file mode 100644 index 0000000..c4fe680 --- /dev/null +++ b/src/highlight.cpp @@ -0,0 +1,744 @@ +/* +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include +#include +#include "highlight.h" + + +//Editor colors +#if 0 +Fl_Color hl_plain = FL_BLACK; +Fl_Color hl_linecomment = FL_DARK_GREEN; +Fl_Color hl_blockcomment = FL_DARK_GREEN; +Fl_Color hl_string = FL_BLUE; +Fl_Color hl_directive = FL_DARK_MAGENTA; +Fl_Color hl_type = FL_DARK_RED; +Fl_Color hl_keyword = FL_BLUE; +Fl_Color hl_character = FL_DARK_RED; +Fl_Color hl_label = FL_DARK_BLUE; +Fl_Color background_color = FL_WHITE; +#endif + +Fl_Color hl_plain = FL_WHITE; +Fl_Color hl_linecomment = (Fl_Color) 95; +Fl_Color hl_blockcomment = (Fl_Color) 93; +Fl_Color hl_string = (Fl_Color) 219; +Fl_Color hl_directive = (Fl_Color) 219; +Fl_Color hl_type = (Fl_Color) 74; +Fl_Color hl_keyword = (Fl_Color) 220; +Fl_Color hl_character = (Fl_Color) 75; +Fl_Color hl_label = (Fl_Color) 116; +Fl_Color background_color = FL_BLACK; + +extern int gDisableHl; + +const char *code_keywords[] = { // List of known C/C++ keywords... + "and", + "and_eq", + "asm", + "bitand", + "bitor", + "break", + "case", + "catch", + "compl", + "continue", + "default", + "delete", + "do", + "else", + "false", + "for", + "goto", + "if", + "new", + "not", + "not_eq", + "operator", + "or", + "or_eq", + "return", + "switch", + "template", + "this", + "throw", + "true", + "try", + "using", + "while", + "xor", + "xor_eq" +}; + +const char *asm_code_keywords[] = { + "aci", + "adc", + "add", + "adi", + "ana", + "ani", + "arhl", + "ashr", + "call", + "cc", + "cm", + "cma", + "cmc", + "cmp", + "cnc", + "cnz", + "cpe", + "cpi", + "cpo", + "cz", + "daa", + "dad", + "dcr", + "dcx", + "dehl", + "desp", + "di", + "dsub", + "ei", + "hlmbc", + "hlt", + "in", + "inr", + "inx", + "jc", + "jd", + "jk", + "jm", + "jmp", + "jnc", + "jnd", + "jnk", + "jnx", + "jnx5", + "jnz", + "jp", + "jpe", + "jpo", + "jtm", + "jtp", + "jx", + "jx5", + "jz", + "lda", + "ldax", + "ldeh", + "ldes", + "ldhi", + "lhld", + "lhlde", + "lhli", + "lhlx", + "lxi", + "mov", + "mvi", + "nop", + "ora", + "ori", + "out", + "pchl", + "pop", + "push", + "ral", + "rar", + "rc", + "rdel", + "ret", + "rim", + "rlc", + "rlde", + "rm", + "rnc", + "rnz", + "rp", + "rpe", + "rpo", + "rrc", + "rrhl", + "rst", + "rstv", + "rz", + "sbb", + "sbi", + "shld", + "shlde", + "shli", + "shlr", + "shlx", + "sim", + "sphl", + "sta", + "stax", + "stc", + "sub", + "sui", + "xchg", + "xra", + "xri", + "xthl" + }; +const char *code_types[] = { // List of known C/C++ types... + "auto", + "bool", + "char", + "class", + "const", + "const_cast", + "double", + "dynamic_cast", + "enum", + "explicit", + "extern", + "float", + "friend", + "inline", + "int", + "long", + "mutable", + "namespace", + "private", + "protected", + "public", + "register", + "short", + "signed", + "sizeof", + "static", + "static_cast", + "struct", + "template", + "typedef", + "typename", + "union", + "unsigned", + "virtual", + "void", + "volatile" +}; + +const char *asm_code_types[] = { // List of known C/C++asm types... + "and", + "aseg", + "cseg", + "db", + "ds", + "dseg", + "dw", + "echo", + "else", + "elsif", + "end", + "endif", + "equ", + "extern", + "extrn", + "fill", + "if", + "include", + "link", + "lsfirst", + "maclib", + "module", + "msfirst", + "name", + "nopage", + "not", + "or", + "org", + "page", + "printf", + "public", + "set", + "stkln", + "sym", + "text", + "title", + "xor" + }; +// +// 'style_parse()' - Parse text and produce style data. +// +// +void style_parse(const char *text, char *style, int length) +{ + char current; + int last; + char buf[255], + *bufptr; + const char *temp; + int col = 0; + + for (current = *style, last = 0; length > 0; length --, text ++) + { + //if ((current != 'C') && (current != 'D') && (current != 'E')) current = 'A'; + //if ((current == 'B')) current = 'A'; + + if (current == 'A') + { + // Check for directives, comments, strings, and keywords... + if (*text == '#') + { + // Set style to directive + current = 'E'; + } + + else if ((strncmp(text, "//", 2) == 0) || (*text == ';')) + { + current = 'B'; + for (; length > 0 && *text != '\n'; length --, text ++) + *style++ = 'B'; + + if (length == 0) break; + } + + else if (strncmp(text, "/*", 2) == 0) + { + current = 'C'; + *style++ = current; + *style--; + } + + else if (strncmp(text, "\\\"", 2) == 0) + { + // Quoted quote... + *style++ = current; + *style++ = current; + text ++; + length --; + continue; + } + + else if (*text == '\"' /*| *text == '\''*/) + { + current = 'D'; + } + + else if (*text == '\'') + { + current = 'H'; + } + + else if (!last && /*islower(*text) && */ text > 0)// && +// !(isalnum(*(text-1)) || *(text-1)=='_')) + { + // Might be a keyword... + for (temp = text, bufptr = buf; (isalnum(*temp) || *temp=='_') && + bufptr < (buf + sizeof(buf) - 1); *bufptr++ = tolower(*temp++)); + { + //if (!islower(*temp)) + { + *bufptr = '\0'; + bufptr = buf; + + if (bsearch(&bufptr, asm_code_types, sizeof(asm_code_types) / + sizeof(asm_code_types[0]), sizeof(asm_code_types[0]), compare_keywords)) + { + while (text < temp) + { + *style++ = 'F'; + text ++; + length --; + } + text --; + length ++; + last = 1; + continue; + + } + else if (bsearch(&bufptr, asm_code_keywords, sizeof(asm_code_keywords) / + sizeof(asm_code_keywords[0]), sizeof(asm_code_keywords[0]), compare_keywords)) + { + while (text < temp) + { + *style++ = 'G'; + text ++; + length --; + } + + text --; + length ++; + last = 1; + continue; + } + } + } + + /* Test if label */ + if ((col == 0) && !isspace(*text)) + { + current = 'I'; + } + } + + + } + else if (current == 'C' && strncmp(text, "*/", 2) == 0) + { + // Close a C comment... + *style++ = current; + *style++ = current; + text ++; + length --; + current = 'A'; + continue; + } + else if (current == 'D') + { + // Continuing in string... + if (strncmp(text, "\\\"", 2) == 0 || strncmp(text, "\\\'", 2) == 0) + { + // Quoted end quote... + *style++ = current; + *style++ = current; + text ++; + length --; + continue; + } + else if (*text == '\"'/* || *text == '\''*/) + { + // End quote... + *style++ = current; + current = 'A'; + continue; + } + } + else if (current == 'H') + { + // Continuing in char... + if (strncmp(text, "\\\'", 2) == 0) { + // Quoted end quote... + *style++ = current; + *style++ = current; + text ++; + length --; + continue; + } else if (*text == '\'') { + // End quote... + *style++ = current; + current = 'A'; + continue; + } + } + else if (current == 'I') + { + // Continuing in label... + col++; + if ((*text == ':') || (*text == ' ') || (*text == '\t')) + { + // End label... + *style++ = current; + current = 'A'; + last = 0; + continue; + } + *style++ = current; + continue; + } + + + // Copy style info... + if (current == 'A' && (*text == '{' || *text == '}')) *style++ = 'G'; + /*else if(current == 'E' && strncmp(text, "/*", 2) == 0) { + *style++ = 'C'; + *style++ = 'C'; + //*style--; + }*/ + else if(current == 'E' && strncmp(text, "/*", 2) == 0) + { + *style++ = 'C'; + current = 'C'; + } + else if(current == 'E' && strncmp(text, "//", 2) == 0) + { + *style++ = 'B'; + current = 'B'; + } + else if((current == 'E') && (text[0] == ';')) + { + *style++ = 'B'; + current = 'B'; + } + else *style++ = current; + + last = isalnum(*text) || *text == '_'; + if (*text != 0x0a) + col++; + + if (*text == '\n') + { + // Reset column and possibly reset the style + if (current != 'D' && current != 'C') current = 'A'; + col = 0; + } + } //for +} + +int compare_keywords(const void *a, const void *b) +{ + return (strcmp(*((const char **)a), *((const char **)b))); +} + + +/* +========================================================================== +style_init() - Initialize the style buffer... +========================================================================== +*/ +void style_init(HighlightCtrl_t *pHlCtrl) +{ + char *style = new char[pHlCtrl->textbuf->length() + 1]; + char *text = pHlCtrl->textbuf->text(); + + + memset(style, 'A', pHlCtrl->textbuf->length()); + style[pHlCtrl->textbuf->length()] = '\0'; + + if (!pHlCtrl->stylebuf) + pHlCtrl->stylebuf = new Fl_Text_Buffer(pHlCtrl->textbuf->length()); + + if (pHlCtrl->cppfile) + style_parse(text, style, pHlCtrl->textbuf->length()); + + pHlCtrl->stylebuf->text(style); + delete[] style; + free(text); +} + + +/* +========================================================================== +style_unfinished_cb() - Update unfinished styles +========================================================================== +*/ +void style_unfinished_cb(int, void*) +{ +} + + +// +// 'style_update()' - Update the style buffer... +// + +void +old_style_update( int pos, // I - Position of update + int nInserted, // I - Number of inserted chars + int nDeleted, // I - Number of deleted chars + int /*nRestyled*/, // I - Number of restyled chars + const char * /*deletedText*/,// I - Text that was deleted + void *cbArg) { // I - Callback data +/* int start, // Start of text + end; // End of text + char last, // Last style on line + stringdeleted=0; + char *style, // Style data + *text; // Text data +*/ +/* + // If this is just a selection change, just unselect the style buffer... + if (nInserted == 0 && nDeleted == 0) { + stylebuf->unselect(); + return; + } + + // Track changes in the text buffer... + if (nInserted > 0) { + // Insert characters into the style buffer... + style = (char*)malloc(nInserted + 1); + memset(style, 'A', nInserted); + style[nInserted] = '\0'; + + stylebuf->replace(pos, pos + nDeleted, style); + free(style); + } else { + // Just delete characters in the style buffer... + if((stylebuf->character(pos) == 'D') || (stylebuf->character(pos) == 'C')) stringdeleted = 1; + + stylebuf->remove(pos, pos + nDeleted); + if(pos < 2) style_init(); + } + + + + // Select the area that was just updated to avoid unnecessary + // callbacks... + stylebuf->select(pos, pos + nInserted - nDeleted); + + // Re-parse the changed region; we do this by parsing from the + // beginning of the line of the changed region to the end of + // the line of the changed region... Then we check the last + // style character and keep updating if we have a multi-line + // comment character... + start = textbuf->line_start(pos); + end = textbuf->line_end(pos + nInserted); + text = textbuf->text_range(start, end); + style = stylebuf->text_range(start, end); + last = style[end - start - 1]; + + + style_parse(text, style, end - start); + + + stylebuf->replace(start, end, style); + ((Fl_Text_Editor_ext *)cbArg)->redisplay_range(start, end); + + if ((last != style[end - start - 1]) || nDeleted || style[end - start - 1] == 'D') + if (last == 'C' || last == 'D') + //if(update_count > 10) + { + // The last character on the line changed styles, so reparse the + // remainder of the buffer... + free(text); + free(style); + + start = 0; + end = textbuf->length(); + text = textbuf->text_range(start, end); + style = stylebuf->text_range(start, end); + + style_parse(text, style, end - start); + + //if(update_count > 10) + { + update_count = 0; + if(browser_nav_grp->visible()) navigator_update(text,style,end - start); + } + + stylebuf->replace(start, end, style); + //((Fl_Text_Editor *)cbArg)->redisplay_range(start, end); + + te->redraw(); + } + update_count+= nInserted > nDeleted ? nInserted : nDeleted; + + free(text); + free(style); +*/ +} + + +void +style_update( int pos, // I - Position of update + int nInserted, // I - Number of inserted chars + int nDeleted, // I - Number of deleted chars + int /*nRestyled*/, // I - Number of restyled chars + const char * /*deletedText*/,// I - Text that was deleted + void *cbArg) +{ + int start, // Start of text + end; // End of text + char last, // Last style on line + stringdeleted=0; + char *style, // Style data + *text; // Text data + + if (gDisableHl) + return; + + HighlightCtrl_t *pHlCtrl; + + pHlCtrl = (HighlightCtrl_t *) cbArg; + + // If this is just a selection change, just unselect the style buffer... + if (nInserted == 0 && nDeleted == 0) + { + pHlCtrl->stylebuf->unselect(); + return; + } + + // Track changes in the text buffer... + if (nInserted > 0) + { + // Insert characters into the style buffer... + style = (char*) malloc(nInserted + 1); + memset(style, 'A', nInserted); + style[nInserted] = '\0'; + + pHlCtrl->stylebuf->replace(pos, pos + nDeleted, style); + free(style); + } + else + { + // Just delete characters in the style buffer... + if((pHlCtrl->stylebuf->character(pos) == 'D') || (pHlCtrl->stylebuf->character(pos) == 'C')) stringdeleted = 1; + + pHlCtrl->stylebuf->remove(pos, pos + nDeleted); + if(pos < 2) + style_init(pHlCtrl); + } + + // Select the area that was just updated to avoid unnecessary + // callbacks... + pHlCtrl->stylebuf->select(pos, pos + nInserted - nDeleted); + + // Re-parse the changed region; we do this by parsing from the + // beginning of the line of the changed region to the end of + // the line of the changed region... Then we check the last + // style character and keep updating if we have a multi-line + // comment character... + start = pHlCtrl->textbuf->line_start(pos); + end = pHlCtrl->textbuf->line_end(pos + nInserted); + text = pHlCtrl->textbuf->text_range(start, end); + style = pHlCtrl->stylebuf->text_range(start, end); + last = style[end - start - 1]; + + style_parse(text, style, end - start); + + pHlCtrl->stylebuf->replace(start, end, style); + pHlCtrl->te->redisplay_range(start, end); + + //if ((last != style[end - start - 1]) || nDeleted || style[end - start - 1] == 'D') + //if(update_count > 10) + { + // The last character on the line changed styles, so reparse the + // remainder of the buffer... + free(text); + free(style); + + start = 0; + end = pHlCtrl->textbuf->length(); + text = pHlCtrl->textbuf->text_range(start, end); + style = pHlCtrl->stylebuf->text_range(start, end); + + style_parse(text, style, end - start); + +// add_nav_timeout_handler(); + //if(update_count > 10) + { + //update_count = 0; + //if(browser_nav_grp->visible()) navigator_update(text,style,end - start); + } + + pHlCtrl->stylebuf->replace(start, end, style); + //((Fl_Text_Editor *)cbArg)->redisplay_range(start, end); + + pHlCtrl->te->redraw(); + } + //update_count+= nInserted > nDeleted ? nInserted : nDeleted; + + free(text); + free(style); +} + + + + diff --git a/src/highlight.h b/src/highlight.h new file mode 100644 index 0000000..6983033 --- /dev/null +++ b/src/highlight.h @@ -0,0 +1,75 @@ +/* +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#ifndef HIGHLIGHT_H +#define HIGHLIGHT_H + +#include +#include "My_Text_Editor.h" + +#define TEXTSIZE 12 + +typedef struct _HighlightCtrl +{ + Fl_Text_Buffer *textbuf; + Fl_Text_Buffer *stylebuf; + Fl_Text_Buffer *op_stylebuf; + My_Text_Editor *te; + int cppfile; +} HighlightCtrl_t; + + +// +// 'compare_keywords()' - Compare two keywords... +// +int compare_keywords(const void *a, const void *b); + +// +// 'style_parse()' - Parse text and produce style data. +// +// +void style_parse(const char *text, char *style, int length) ; +// +// 'style_init()' - Initialize the style buffer... +// + +void style_init(HighlightCtrl_t* pHlCtrl); +// +// 'style_unfinished_cb()' - Update unfinished styles. +// + +void style_unfinished_cb(int, void*); + +// +// 'style_update()' - Update the style buffer... +// + +void old_style_update( int pos, // I - Position of update + int nInserted, // I - Number of inserted chars + int nDeleted, // I - Number of deleted chars + int /*nRestyled*/, // I - Number of restyled chars + const char * /*deletedText*/,// I - Text that was deleted + void *cbArg); + +void style_update( int pos, // I - Position of update + int nInserted, // I - Number of inserted chars + int nDeleted, // I - Number of deleted chars + int /*nRestyled*/, // I - Number of restyled chars + const char * /*deletedText*/,// I - Text that was deleted + void *cbArg); + +#endif diff --git a/src/ide.cpp b/src/ide.cpp index 73f87c0..8f62b40 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -38,10 +38,13 @@ #include #include #include +#include #include "FLU/Flu_Tree_Browser.h" #include "FLU/flu_pixmaps.h" +#include "FLU/Flu_File_Chooser.h" #include #include +#include #include #include #include @@ -60,22 +63,51 @@ #include "periph.h" #include "MStringArray.h" #include "assemble.h" +#include "linker.h" +#include "multiwin.h" +#include "idetabs.h" +#include "pref_form.h" -VT_Ide * gpIde = 0; -Fl_Menu_Button* gPopup = 0; -void setMonitorWindow(Fl_Window* pWin); +/* +======================================================= +Define global variables +======================================================= +*/ +#define VT_NUM_RECENT_FILES 6 +#define VT_NUM_RECENT_PROJECTS 4 + +VT_Ide * gpIde = 0; +Fl_Menu_Button* gPopup = 0; Fl_Multi_Window* gpLcd; +MString gRootpath; +char usrdocdir[256]; +int gIdeX, gIdeY, gIdeW, gIdeH; +char gRecentFile[VT_NUM_RECENT_FILES][256]; +char gRecentProject[VT_NUM_RECENT_PROJECTS][256]; +int gDisableHl, gSmartIndent, gReloadProject; +static Fl_Menu_Bar *gMenuBar = 0; +char gProjectTypes[][6] = { + ".co", + ".obj", + ".rom", + ".ba", + "" }; #ifdef _WIN32 extern "C" #endif extern char path[]; -MString gRootpath; - +extern My_Text_Display::Style_Table_Entry gStyleTable[9]; extern Fl_Preferences virtualt_prefs; -void close_cb(Fl_Widget* w, void*); +/* +======================================================= +Define function prototypes for callbacks +======================================================= +*/ +void setMonitorWindow(Fl_Window* pWin); +void close_ide_cb(Fl_Widget* w, void*); void cb_help(Fl_Widget* w, void*); void cb_about(Fl_Widget* w, void*); void cb_lcd_display(Fl_Widget* w, void*); @@ -88,61 +120,67 @@ void cb_new_project(Fl_Widget* w, void*); void cb_open_project(Fl_Widget* w, void*); void cb_save_project(Fl_Widget* w, void*); // Define Edit menu callbacks +void cb_undo(Fl_Widget* w, void*); void cb_copy(Fl_Widget* w, void*); void cb_cut(Fl_Widget* w, void*); void cb_paste(Fl_Widget* w, void*); void cb_find(Fl_Widget* w, void*); void cb_find_next(Fl_Widget* w, void*); void cb_replace(Fl_Widget* w, void*); -// Define Window management routines -void cb_window_cascade(Fl_Widget* w, void*); -void cb_window_1(Fl_Widget* w, void*); -void cb_window_2(Fl_Widget* w, void*); -void cb_window_3(Fl_Widget* w, void*); -void cb_window_4(Fl_Widget* w, void*); -void cb_window_5(Fl_Widget* w, void*); -void cb_window_6(Fl_Widget* w, void*); -void cb_window_more(Fl_Widget* w, void*); +void cb_prefs(Fl_Widget* w, void*); // Define project management routines void cb_build_project(Fl_Widget* w, void*); void cb_rebuild_project(Fl_Widget* w, void*); void cb_clean_project(Fl_Widget* w, void*); void cb_project_settings(Fl_Widget* w, void*); +void add_recent_file_to_menu(const char *filename); +void add_recent_project_to_menu(const char *filename); IMPLEMENT_DYNCREATE(VT_IdeGroup, VTObject); IMPLEMENT_DYNCREATE(VT_IdeSource, VTObject); -char gProjectTypes[][6] = { - ".co", - ".obj", - ".rom", - ".ba", - "" -}; - /* ======================================================= Menu Items for the IDE window ======================================================= */ +const int gProjOffset = 16; +const int gFileOffset = 4; + Fl_Menu_Item gIde_menuitems[] = { { "&File", 0, 0, 0, FL_SUBMENU }, { "New File", FL_CTRL + 'n', cb_new_file, 0, 0 }, { "Open File...", FL_CTRL + 'o', cb_open_file, 0, 0 }, + { "Recent Files", 0, 0, 0, FL_SUBMENU }, + { "", 0, 0, 0, FL_MENU_INVISIBLE }, + { "", 0, 0, 0, FL_MENU_INVISIBLE }, + { "", 0, 0, 0, FL_MENU_INVISIBLE }, + { "", 0, 0, 0, FL_MENU_INVISIBLE }, + { "", 0, 0, 0, FL_MENU_INVISIBLE }, + { "", 0, 0, 0, FL_MENU_INVISIBLE }, + { 0 }, { "Save File", FL_CTRL + 's', cb_save_file, 0, 0}, { "Save As...", 0, cb_save_as, 0, FL_MENU_DIVIDER }, { "New Project...", 0, cb_new_project, 0, 0 }, { "Open Project...", 0, cb_open_project, 0, 0 }, + { "Recent Projects", 0, 0, 0, FL_SUBMENU }, + { "", 0, 0, 0, FL_MENU_INVISIBLE }, + { "", 0, 0, 0, FL_MENU_INVISIBLE }, + { "", 0, 0, 0, FL_MENU_INVISIBLE }, + { "", 0, 0, 0, FL_MENU_INVISIBLE }, + { 0 }, { "Save Project", 0, cb_save_project, 0, FL_MENU_DIVIDER }, - { "E&xit", FL_CTRL + 'q', close_cb, 0 }, + { "Exit", FL_CTRL + 'q', close_ide_cb, 0 }, { 0 }, { "&Edit", 0, 0, 0, FL_SUBMENU }, - { "Copy", FL_CTRL + 'c', cb_copy, 0, 0 }, - { "Cut", FL_CTRL + 'x', cb_cut, 0, 0 }, - { "Paste", FL_CTRL + 'v', cb_paste, 0, FL_MENU_DIVIDER}, + { "&Undo", 'u', cb_undo, 0, 0 }, + { "Copy", 'c', cb_copy, 0, 0 }, + { "Cut", 't', cb_cut, 0, 0 }, + { "&Paste", 'p', cb_paste, 0, FL_MENU_DIVIDER}, { "Find...", FL_CTRL + 'f', cb_find, 0, 0 }, { "Find Next", FL_F + 3, cb_find_next, 0, 0 }, - { "Replace", FL_CTRL + 'r', cb_replace, 0, 0 }, + { "Replace", FL_CTRL + 'r', cb_replace, 0, FL_MENU_DIVIDER }, + { "Preferences", 0, cb_prefs, 0, 0 }, { 0 }, { "&Project", 0, 0, 0, FL_SUBMENU }, { "Build", FL_SHIFT + FL_F+8, cb_build_project, 0, 0 }, @@ -150,27 +188,16 @@ Fl_Menu_Item gIde_menuitems[] = { { "Clean", 0, cb_clean_project, 0, FL_MENU_DIVIDER }, { "Settings", 0, cb_project_settings, 0, 0 }, { 0 }, - { "&Debug", 0, 0, 0, FL_SUBMENU }, - { "Laptop Display", 0, cb_lcd_display, 0, 0 }, - { 0 }, +// { "&Debug", 0, 0, 0, FL_SUBMENU }, +// { "Laptop Display", 0, cb_lcd_display, 0, 0 }, +// { 0 }, { "&Tools", 0, 0, 0, FL_SUBMENU }, { "CPU Registers", 0, cb_CpuRegs }, { "Disassembler", 0, disassembler_cb }, { "Memory Editor", 0, cb_MemoryEditor }, { "Peripheral Devices", 0, cb_PeripheralDevices }, - { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, 0 }, { 0 }, - { "&Window", 0, 0, 0, FL_SUBMENU }, - { "Cascade", 0, cb_window_cascade, 0, 0 }, - { "1", 0, cb_window_1, 0, 0 }, - { "2", 0, cb_window_2, 0, 0 }, - { "3", 0, cb_window_3, 0, 0 }, - { "4", 0, cb_window_4, 0, 0 }, - { "5", 0, cb_window_5, 0, 0 }, - { "6", 0, cb_window_6, 0, 0 }, - { "More...", 0, cb_window_more, 0, 0 }, - { 0 }, { "&Help", 0, 0, 0, FL_SUBMENU }, { "Help", 0, cb_help }, { "About VirtualT", 0, cb_about }, @@ -180,32 +207,36 @@ Fl_Menu_Item gIde_menuitems[] = { }; void cb_new_folder(Fl_Widget* w, void*); +void cb_delete_folder(Fl_Widget* w, void*); void cb_add_files_to_folder(Fl_Widget* w, void*); void cb_folder_properties(Fl_Widget* w, void*); void cb_open_tree_file(Fl_Widget* w, void*); +void cb_remove_tree_file(Fl_Widget* w, void*); void cb_assemble_tree_file(Fl_Widget* w, void*); void cb_tree_file_properties(Fl_Widget* w, void*); Fl_Menu_Item gGroupMenu[] = { - { "New Folder", 0, cb_new_folder, 0, 0 }, - { "Add Files to Folder",0, cb_add_files_to_folder, 0, 0 }, - { "Properties", 0, cb_folder_properties, 0, 0}, + { " New Folder ", 0, cb_new_folder, 0, 0 }, + { " Add Files to Folder ",0, cb_add_files_to_folder, 0, 0 }, + { " Remove ", 0, cb_remove_tree_file, 0, FL_MENU_DIVIDER }, + { " Properties ", 0, cb_folder_properties, 0, 0}, { 0 } }; Fl_Menu_Item gSourceMenu[] = { - { "Open", 0, cb_open_tree_file, 0, 0 }, - { "Assemble File", 0, cb_assemble_tree_file, 0, 0 }, - { "Properties", 0, cb_tree_file_properties, 0, 0}, + { " Open ", 0, cb_open_tree_file, 0, 0 }, + { " Remove ", 0, cb_remove_tree_file, 0, FL_MENU_DIVIDER }, + { " Assemble File ", 0, cb_assemble_tree_file, 0, 0 }, + { " Properties ", 0, cb_tree_file_properties, 0, 0}, { 0 } }; Fl_Menu_Item gRootMenu[] = { - { "Build", 0, cb_build_project, 0, 0 }, - { "Build All", 0, cb_rebuild_project, 0, 0 }, - { "New Folder...", 0, cb_new_folder, 0, 0}, - { "Add Files to Project...", 0, cb_add_files_to_folder, 0, FL_MENU_DIVIDER }, - { "Project Settings...", 0, cb_project_settings, 0, 0}, + { " Build ", 0, cb_build_project, 0, 0 }, + { " Build All ", 0, cb_rebuild_project, 0, FL_MENU_DIVIDER }, + { " New Folder... ", 0, cb_new_folder, 0, FL_MENU_DIVIDER}, +// { " Add Files to Project... ", 0, cb_add_files_to_folder, 0, FL_MENU_DIVIDER }, + { " Project Settings... ", 0, cb_project_settings, 0, 0}, { 0 } }; @@ -236,10 +267,14 @@ void close_ide_cb(Fl_Widget* w, void*) } // Save window parameters to preferences - virtualt_prefs.set("IdeX", gpIde->x()); - virtualt_prefs.set("IdeY", gpIde->y()); - virtualt_prefs.set("IdeW", gpIde->w()); - virtualt_prefs.set("IdeH", gpIde->h()); + if (save_window_size) + { + virtualt_prefs.set("IdeX", gpIde->x()); + virtualt_prefs.set("IdeY", gpIde->y()); + virtualt_prefs.set("IdeW", gpIde->w()); + virtualt_prefs.set("IdeH", gpIde->h()); + } + gpIde->SavePrefs(); // Okay, close the window setMonitorWindow(0); @@ -251,6 +286,160 @@ void close_ide_cb(Fl_Widget* w, void*) } } +/* +======================================================= +Callback for opening recent files +======================================================= +*/void recent_file_cb(Fl_Widget* w, void*) +{ +// if (!check_save()) return; + Fl_Menu_* mw = (Fl_Menu_*)w; + const Fl_Menu_Item* m = mw->mvalue(); + if (m) { + char *newfile = (char*)m->label(); + char *path = new char[strlen(newfile)+1]; + strcpy(path, newfile); + + if (newfile != NULL) + { + char *slash; + slash = strrchr(path, '/'); + *slash = '\0'; + gpIde->OpenFile(newfile); + add_recent_file_to_menu(newfile); + } + } +} + +/* +======================================================= +Routine to update the recent files menu items +======================================================= +*/void add_recent_file_to_menu(const char *filename) +{ + int c; + + // Check if filename is already in the recent file list + for (c = 0; c < VT_NUM_RECENT_FILES; c++) + { + if(strcmp(filename, gIde_menuitems[c + gFileOffset].label()) == 0) + break; + } + // Return if filename is already the 1st file in the list + if (c == 0) + return; + + // If the filename already exists, then just reorder the list + if (c < VT_NUM_RECENT_FILES) + { + Fl_Menu_Item mi = gIde_menuitems[c + gFileOffset]; + + for (int x = c; x > 0; x--) + gIde_menuitems[x + gFileOffset] = gIde_menuitems[x + gFileOffset-1]; + gIde_menuitems[gFileOffset] = mi; + } + else + { + char *path = new char[strlen(filename)+1]; + strcpy(path, filename); + + Fl_Menu_Item mi = { path, 0, recent_file_cb }; + + char *t = (char *)gIde_menuitems[VT_NUM_RECENT_FILES + gFileOffset-1].text; + //cout << t << endl; + if(t) + if (strlen(t) != 0) + free(t); + + for (int x = VT_NUM_RECENT_FILES - 1; x > 0; x--) + gIde_menuitems[x + gFileOffset] = gIde_menuitems[x + gFileOffset-1]; + gIde_menuitems[gFileOffset] = mi; + } + + gMenuBar->copy(gIde_menuitems, gpIde); + + for (c = 0; c < VT_NUM_RECENT_FILES; c++) + strcpy(gRecentFile[c], gIde_menuitems[c + gFileOffset].text); +} + +/* +======================================================= +Callback for opening recent projects +======================================================= +*/void recent_project_cb(Fl_Widget* w, void*) +{ +// if (!check_save()) return; + Fl_Menu_* mw = (Fl_Menu_*)w; + const Fl_Menu_Item* m = mw->mvalue(); + if (m) { + char *newfile = (char*)m->label(); + char *path = new char[strlen(newfile)+1]; + strcpy(path, newfile); + + if (newfile != NULL) + { + char *slash; + slash = strrchr(path, '/'); + *slash = '\0'; + gpIde->OpenProject(newfile); + add_recent_project_to_menu(newfile); + } + } +} + +/* +======================================================= +Routine to update the recent projects menu items +======================================================= +*/ +void add_recent_project_to_menu(const char *filename) +{ + int c; + + // Check if filename is already in the recent file list + for (c = 0; c < VT_NUM_RECENT_PROJECTS; c++) + { + if(strcmp(filename, gIde_menuitems[c + gProjOffset].label()) == 0) + break; + } + // Return if filename is already the 1st file in the list + if (c == 0) + return; + + // If the filename already exists, then just reorder the list + if (c < VT_NUM_RECENT_PROJECTS) + { + Fl_Menu_Item mi = gIde_menuitems[c + gProjOffset]; + + for (int x = c; x > 0; x--) + gIde_menuitems[x + gProjOffset] = gIde_menuitems[x + gProjOffset-1]; + gIde_menuitems[gProjOffset] = mi; + } + else + { + char *path = new char[strlen(filename)+1]; + strcpy(path, filename); + + Fl_Menu_Item mi = { path, 0, recent_project_cb }; + + char *t = (char *)gIde_menuitems[VT_NUM_RECENT_PROJECTS + + gProjOffset-1].text; + //cout << t << endl; + if(t) + if (strlen(t) != 0) + free(t); + + for (int x = VT_NUM_RECENT_PROJECTS - 1; x > 0; x--) + gIde_menuitems[x + gProjOffset] = gIde_menuitems[x + gProjOffset-1]; + gIde_menuitems[gProjOffset] = mi; + } + + gMenuBar->copy(gIde_menuitems, gpIde); + + for (c = 0; c < VT_NUM_RECENT_PROJECTS; c++) + strcpy(gRecentProject[c], gIde_menuitems[c + gProjOffset].text); +} + /* ======================================================= Callback routine for creating new files @@ -275,6 +464,131 @@ void cb_open_file(Fl_Widget* w, void*) gpIde->OpenFile(); } +/* +======================================================= +Callback routine for handling preferences +======================================================= +*/ +void set_text_size(int t) +{ + gStyleTable[0].size = t; + gStyleTable[0].color = hl_plain; + + gStyleTable[1].size = t; + gStyleTable[1].color = hl_linecomment; + + gStyleTable[2].size = t; + gStyleTable[2].color = hl_blockcomment; + + gStyleTable[3].size = t; + gStyleTable[3].color = hl_string; + + gStyleTable[4].size = t; + gStyleTable[4].color = hl_directive; + + gStyleTable[5].size = t; + gStyleTable[5].color = hl_type; + + gStyleTable[6].size = t; + gStyleTable[6].color = hl_keyword; + + gStyleTable[7].size = t; + gStyleTable[7].color = hl_character; + + gStyleTable[8].size = t; + gStyleTable[8].color = hl_label; + +} + +/* +======================================================= +Routine to set the window colors after a change in the +perferences dialog. +======================================================= +*/ +void VT_Ide::SetColors(int fg, int bg) +{ + // Set all editor background colors + int children = m_EditTabs->children(); + for (int c = 0; c < children; c++) + { + Fl_Multi_Edit_Window* te = (Fl_Multi_Edit_Window *) m_EditTabs->child(c); + te->color(background_color); + te->textcolor(hl_plain); + te->selection_color(FL_DARK_BLUE); + te->mCursor_color = hl_plain; + te->smart_indent = gSmartIndent; + te->textsize(text_size); + if (gDisableHl) + te->DisableHl(); + else + te->EnableHl(); + } + + // Set Browser Tree colors + m_ProjTree->connector_style(hl_plain, FL_SOLID); + m_ProjTree->leaf_text(hl_plain, m_ProjTree->leaf_font(), m_ProjTree->leaf_size()); + m_ProjTree->branch_text(hl_plain, m_ProjTree->branch_font(), m_ProjTree->branch_size()); + m_ProjTree->color(background_color); + m_ProjTree->shaded_entry_colors(background_color, background_color); + m_ProjTree->root_color(hl_plain); + Flu_Tree_Browser::Node * n = m_ProjTree->get_root(); + while (n != NULL) + { + n->label_color(hl_plain); + n->label_size(text_size); + n = n->next(); + } + + // Set the colors of the Build, Output and Watch windows + m_BuildTextDisp->color(background_color); + m_BuildTextDisp->textcolor(hl_plain); + m_BuildTextDisp->textsize(text_size); + m_DebugTab->color(background_color); +// m_DebugTab->labelcolor(hl_plain); + + m_BuildTextDisp->redraw(); + m_ProjTree->redraw(); + m_DebugTab->redraw(); + if (m_EditTabs->value() != NULL) + m_EditTabs->value()->redraw(); +} + +/* +======================================================= +Callback routine for displaying the editor preferences +dialog box. +======================================================= +*/ +void cb_prefs(Fl_Widget* w, void*) +{ + text_size_choice->value((text_size - 6)/2); + save_wsoe_check->value(save_window_size); + hide_output_check->value(auto_hide); + + plain_btn->color(hl_plain); + line_btn->color(hl_linecomment); + block_btn->color(hl_blockcomment); + string_btn->color(hl_string); + directive_btn->color(hl_directive); + type_btn->color(hl_type); + keyword_btn->color(hl_keyword); + character_btn->color(hl_character); + label_btn->color(hl_label); + bg_btn->color(background_color); + + pref_window->show(); + while(pref_window->visible()) + { + Fl::wait(5); + } + + set_text_size(text_size); + gpIde->SetColors(hl_plain, background_color); + gpIde->m_EditTabs->redraw(); +} + + /* ======================================================= Callback routine for saving files @@ -341,6 +655,17 @@ void cb_copy(Fl_Widget* w, void*) gpIde->Copy(); } +/* +======================================================= +Callback routine for undo operation +======================================================= +*/ +void cb_undo(Fl_Widget* w, void*) +{ + if (gpIde != NULL) + gpIde->Undo(); +} + /* ======================================================= Callback routine for cutting text @@ -410,29 +735,35 @@ Callback routine for displaying the laptop screen */ void cb_lcd_display(Fl_Widget* w, void*) { +#if 0 if (gpLcd != 0) { - gpIde->m_EditWindow->insert(*gpLcd, gpIde->m_EditWindow->children()); + gpIde->m_EditTabs->insert(*gpLcd, gpIde->m_EditTabs->children()); gpLcd->show(); gpLcd->show(); gpLcd->redraw(); return; } if (gModel == MODEL_T200) - gpLcd = new Fl_Multi_Window(0, 0, 240*2 + MW_BORDER_WIDTH*2, 128*2 + - MW_BORDER_WIDTH + MW_TITLE_HEIGHT, "Laptop Display"); + gpLcd = new Fl_Multi_Window(0, TAB_HEIGHT, 240*2 + MW_BORDER_WIDTH*2, 128*2 + + MW_BORDER_WIDTH + MW_TITLE_HEIGHT + TAB_HEIGHT, "Laptop Display"); else - gpLcd = new Fl_Multi_Window(0, 0, 240*2 + MW_BORDER_WIDTH*2, 64*2 + - MW_BORDER_WIDTH + MW_TITLE_HEIGHT, "Laptop Display"); + gpLcd = new Fl_Multi_Window(0, TAB_HEIGHT, 240*2 + MW_BORDER_WIDTH*2, 64*2 + + MW_BORDER_WIDTH + MW_TITLE_HEIGHT + TAB_HEIGHT, "Laptop Display"); gpLcd->m_NoResize = 1; gpLcd->callback(cb_close_lcd); gpLcd->end(); - gpIde->m_EditWindow->insert(*gpLcd, gpIde->m_EditWindow->children()); + gpLcd->resize(0, TAB_HEIGHT, gpIde->m_EditTabs->w(), gpIde->m_EditTabs->h() - + TAB_HEIGHT); + gpIde->m_EditTabs->insert(*gpLcd, gpIde->m_EditTabs->children()); + if (gpIde->m_EditTabs->children() == 1) + gpIde->m_EditTabs->show(); gpLcd->show(); gpLcd->show(); gpLcd->take_focus(); setMonitorWindow(gpLcd->ClientArea()); +#endif } /* @@ -491,6 +822,20 @@ void cb_open_tree_file(Fl_Widget* w, void* data) gpIde->OpenTreeFile(n); } +/* +======================================================= +Callback routine to open selected tree file +======================================================= +*/ +void cb_remove_tree_file(Fl_Widget* w, void* data) +{ + Flu_Tree_Browser::Node* n = (Flu_Tree_Browser::Node*) data; + + // Ensure window exists + if (gpIde != 0) + gpIde->DeleteItem(n); +} + /* ======================================================= Callback routine to assemble selected tree file @@ -569,75 +914,134 @@ void cb_clean_project(Fl_Widget* w, void*) /* ======================================================= -Callback routine to cascade all windows -======================================================= -*/ -void cb_window_cascade(Fl_Widget* w, void*) -{ -} - -/* -======================================================= -Callback routine to select window 1 -======================================================= -*/ -void cb_window_1(Fl_Widget* w, void*) -{ -} - -/* -======================================================= -Callback routine to select window 2 +Routine to load the IDE preferences ======================================================= */ -void cb_window_2(Fl_Widget* w, void*) +void VT_Ide::LoadPrefs(void) { -} + int pc, c; + char sRecentFile[32]; -/* -======================================================= -Callback routine to select window 3 -======================================================= -*/ -void cb_window_3(Fl_Widget* w, void*) -{ -} - -/* -======================================================= -Callback routine to select window 4 -======================================================= -*/ -void cb_window_4(Fl_Widget* w, void*) -{ -} + // Get the initial window size from the user preferences + virtualt_prefs.get("Ide_SaveWindowSize", save_window_size, 1); + virtualt_prefs.get("Ide_AutoHide", auto_hide, 0); + virtualt_prefs.get("Ide_TextSize", text_size, 12); + for (c = 0; c < VT_NUM_RECENT_FILES; c++) + { + sprintf(sRecentFile, "Ide_RecentFile%d", c + 1); + virtualt_prefs.get(sRecentFile, gRecentFile[c], "", + sizeof(gRecentFile[0])); + if (strlen(gRecentFile[c]) != 0) + { + char *path = new char[strlen(gRecentFile[c])+1]; + strcpy(path, gRecentFile[c]); + Fl_Menu_Item mi = { path, 0, recent_file_cb }; + gIde_menuitems[c + gFileOffset] = mi; + } + } -/* -======================================================= -Callback routine to select window 5 -======================================================= -*/ -void cb_window_5(Fl_Widget* w, void*) -{ -} + for (c = 0; c < VT_NUM_RECENT_PROJECTS; c++) + { + sprintf(sRecentFile, "Ide_RecentProject%d", c + 1); + virtualt_prefs.get(sRecentFile, gRecentProject[c], "", + sizeof(gRecentProject[0])); + if (strlen(gRecentProject[c]) != 0) + { + char *path = new char[strlen(gRecentProject[c])+1]; + strcpy(path, gRecentProject[c]); + Fl_Menu_Item mi = { path, 0, recent_project_cb }; + gIde_menuitems[c + gProjOffset] = mi; + } + } -/* -======================================================= -Callback routine to select window 6 -======================================================= -*/ -void cb_window_6(Fl_Widget* w, void*) -{ + virtualt_prefs.get("Ide_ColorText", pc, FL_BLACK); + hl_plain = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorLineComment", pc, 95); + hl_linecomment = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorBlockComment", pc, 93); + hl_blockcomment = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorString", pc, 219); + hl_string = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorDirective", pc, 219); + hl_directive = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorKeyword", pc, 74); + hl_type = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorInstruction", pc, 220); + hl_keyword = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorCharacter", pc, 75); + hl_character = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorLabel", pc, 116); + hl_label = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorBackground", pc, FL_BLACK); + background_color = (Fl_Color) pc; + virtualt_prefs.get("Ide_SmartIndent", gSmartIndent, 1); + virtualt_prefs.get("Ide_ReloadProject", gReloadProject, 1); + virtualt_prefs.get("Ide_AutoBrace", auto_brace_mode, 1); + virtualt_prefs.get("Ide_CreateBackups", backup_file, 0); + virtualt_prefs.get("Ide_DeleteBackups", delbak, 0); + virtualt_prefs.get("Ide_DisableSyntaxHilight", gDisableHl, 0); + + smart_indent_check->value(gSmartIndent!=0); + auto_brace_check->value(auto_brace_mode!=0); + rec_pr_check->value(gReloadProject!=0); + bak_check->value(backup_file!=0); + delbak_check->value(delbak!=0); + + set_text_size(text_size); +} +/* +======================================================= +Routine to save the IDE preferences +======================================================= +*/ +void VT_Ide::SavePrefs(void) +{ + char sRecentFile[32]; + + // Get the initial window size from the user preferences + virtualt_prefs.set("Ide_SaveWindowSize", save_window_size); + virtualt_prefs.set("Ide_AutoHide", auto_hide); + virtualt_prefs.set("Ide_TextSize", text_size); + for (int c = 0; c < VT_NUM_RECENT_FILES; c++) + { + sprintf(sRecentFile, "Ide_RecentFile%d", c + 1); + virtualt_prefs.set(sRecentFile, gRecentFile[c]); + } + for (int c = 0; c < VT_NUM_RECENT_PROJECTS; c++) + { + sprintf(sRecentFile, "Ide_RecentProject%d", c + 1); + virtualt_prefs.set(sRecentFile, gRecentProject[c]); + } + virtualt_prefs.set("Ide_ColorText", (int) hl_plain); + virtualt_prefs.set("Ide_ColorLineComment", (int) hl_linecomment); + virtualt_prefs.set("Ide_ColorBlockComment", (int) hl_blockcomment); + virtualt_prefs.set("Ide_ColorString", (int) hl_string); + virtualt_prefs.set("Ide_ColorDirective", (int) hl_directive); + virtualt_prefs.set("Ide_ColorKeyword", (int) hl_type); + virtualt_prefs.set("Ide_ColorInstruction", (int) hl_keyword); + virtualt_prefs.set("Ide_ColorCharacter", (int) hl_character); + virtualt_prefs.set("Ide_ColorLabel", (int) hl_label); + virtualt_prefs.set("Ide_ColorBackground", (int) background_color); + virtualt_prefs.set("Ide_SmartIndent", gSmartIndent); + virtualt_prefs.set("Ide_ReloadProject", gReloadProject); + virtualt_prefs.set("Ide_AutoBrace", (int) auto_brace_mode); + virtualt_prefs.set("Ide_CreateBackups", backup_file); + virtualt_prefs.set("Ide_DeleteBackups", delbak); + virtualt_prefs.set("Ide_DisableSyntaxHilight", gDisableHl); + + smart_indent_check->value(gSmartIndent!=0); + auto_brace_check->value(auto_brace_mode!=0); + rec_pr_check->value(gReloadProject!=0); + bak_check->value(backup_file!=0); + delbak_check->value(delbak!=0); + disable_hl_check->value(gDisableHl != 0); + + if (m_ActivePrj != NULL) + { + SaveProjectIdeSettings(); + } } -/* -======================================================= -Callback routine to display more windows -======================================================= -*/ -void cb_window_more(Fl_Widget* w, void*) -{ -} /* ======================================================= @@ -646,20 +1050,44 @@ Menu Item Callbacks */ void cb_Ide(Fl_Widget* widget, void*) { - int x, y, w, h; + int maxH, maxW; if (gpIde == NULL) { - // Get the initial window size from the user preferences - virtualt_prefs.get("IdeX", x, 40); - virtualt_prefs.get("IdeY", y, 40); - virtualt_prefs.get("IdeW", w, 800); - virtualt_prefs.get("IdeH", h, 600); - + // Get X/Y coords for IDE + virtualt_prefs.get("IdeX", gIdeX, 40); + virtualt_prefs.get("IdeY", gIdeY, 40); + virtualt_prefs.get("IdeW", gIdeW, 800); + virtualt_prefs.get("IdeH", gIdeH, 600); + + make_pref_form(); + +//#if defined(__APPLE__) || defined(WIN32) +// int sx, sy, sw, sh; +// Fl::screen_xywh(sx, sy, sw, sh); +// maxH = sh; +// maxW = sw; +//#else + maxH = Fl::h(); + maxW = Fl::w(); +//#endif + + if ((gIdeW >= maxW) && (gIdeX < 0)) + gIdeW = maxW - 50; + if ((gIdeH >= maxH) && (gIdeY < 0)) + gIdeH = maxH - 50; + if (gIdeY < 0) + gIdeY = 0; + if (gIdeX < 0) + gIdeX = 0; // Create a new window for the IDE workspace - gpIde = new VT_Ide(x, y, w, h , "Integrated Development Environment - Work in progress!!!"); + gpIde = new VT_Ide(gIdeX, gIdeY, gIdeW, gIdeH , "Integrated Development Environment"); gpIde->show(); - } + + // Test if last project should be opened + if (gReloadProject && (strlen(gRecentProject[0]) != 0)) + gpIde->OpenProject(gRecentProject[0]); + } } @@ -748,10 +1176,11 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) box(FL_NO_BOX); callback(close_ide_cb); - // Get the window size from the preferences + // Create the preferences tab and load the preferences + LoadPrefs(); // Create a menu for the new window. - Fl_Menu_Bar *m = new Fl_Menu_Bar(0, 0, w, MENU_HEIGHT-2); + Fl_Menu_Bar *m = gMenuBar = new Fl_Menu_Bar(0, 0, w, MENU_HEIGHT-2); m->menu(gIde_menuitems); // Create a tiled window to support Project, Edit, and debug regions @@ -762,19 +1191,26 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) Create region for Project tree ============================================ */ - m_ProjWindow = new Fl_Window(2,MENU_HEIGHT-2,198,h-170,""); + m_ProjWindow = new Fl_Window(2,MENU_HEIGHT-2,198,h-75,""); m_ProjWindow->box(FL_DOWN_BOX); + m_ProjWindow->color(background_color); // Create Tree control - m_ProjTree = new Flu_Tree_Browser( 0, 0, 198, h-170 ); + m_ProjTree = new Flu_Tree_Browser( 0, 0, 198, h-75 ); m_ProjTree->box( FL_DOWN_FRAME ); m_ProjTree->callback( projtree_callback ); m_ProjTree->selection_mode( FLU_SINGLE_SELECT ); +// m_ProjTree->animate(TRUE); + m_ProjTree->leaf_text(hl_plain, m_ProjTree->leaf_font(), text_size); + m_ProjTree->branch_text(hl_plain, m_ProjTree->branch_font(), text_size); + Fl_Window* b = new Fl_Window(40, 20, 10, 10, ""); + b->hide(); gPopup = new Fl_Menu_Button(0,0,100,400,"Popup"); gPopup->type(Fl_Menu_Button::POPUP3); gPopup->menu(gGroupMenu); gPopup->selection_color(FL_LIGHT3); gPopup->hide(); + b->end(); m_ProjTree->hide(); m_ProjWindow->resizable(m_ProjTree); @@ -785,100 +1221,133 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) Create region and Child Window for editing files ================================================= */ - m_EditWindow = new Fl_Window(200,MENU_HEIGHT-2,w-200,h-170,"Edit"); + m_EditWindow = new Fl_Window(200,MENU_HEIGHT-2,w-200,h - 75,"Edit"); m_EditWindow->box(FL_DOWN_BOX); - m_EditWindow->color(FL_DARK2); +// m_EditWindow->color(background_color); + m_EditTabs = new Fl_Ide_Tabs(0, 0, m_EditWindow->w(), m_EditWindow->h()); + m_EditTabs->hide(); + m_EditTabs->end(); + m_EditWindow->resizable(m_EditTabs); m_EditWindow->end(); +// tile->resizable(m_EditWindow); /* ================================================= Create region for Debug and output tabs ================================================= */ - m_TabWindow = new Fl_Window(0,MENU_HEIGHT-2+h-170,w,170-MENU_HEIGHT+2,"Tab"); + m_TabWindow = new Fl_Window(0,MENU_HEIGHT-2+h-75,w,75-MENU_HEIGHT+2,"Tab"); m_TabWindow->box(FL_DOWN_BOX); - m_TabWindow->color(FL_LIGHT1); +// m_TabWindow->color(background_color); // Create a tab control - m_Tabs = new Fl_Tabs(0, 1, w, 170-MENU_HEIGHT); + m_Tabs = new Fl_Tabs(0, 1, w, 75-MENU_HEIGHT); /* ==================== Create build tab ==================== */ - m_BuildTab = new Fl_Group(2, 0, w-3, 170-MENU_HEIGHT-20, " Build "); + m_BuildTab = new Fl_Group(2, 0, w-3, 75-MENU_HEIGHT-20, " Build "); m_BuildTab->box(FL_DOWN_BOX); - m_BuildTab->selection_color(FL_WHITE); - m_BuildTab->color(FL_WHITE); + m_BuildTab->selection_color(FL_LIGHT2); + m_BuildTab->color(background_color); // Create a Text Editor to show the disassembled text - m_BuildTextDisp = new Fl_Text_Display(2, 0, w-3, 170-MENU_HEIGHT-20); + m_BuildTextDisp = new My_Text_Display(0, 0, w-3, 75-MENU_HEIGHT-20); m_BuildTextDisp->box(FL_DOWN_BOX); - m_BuildTextDisp->selection_color(FL_WHITE); - m_BuildTextDisp->color(FL_WHITE); +// m_BuildTextDisp->selection_color(FL_WHITE); + m_BuildTextDisp->textcolor(hl_plain); + m_BuildTextDisp->color(background_color); // Create a Text Buffer for the Text Editor to work with m_BuildTextBuf = new Fl_Text_Buffer(); m_BuildTextDisp->buffer(m_BuildTextBuf); // Show the Disassembling text to indicate activity + if (text_size == 0) + text_size = 12; m_BuildTextDisp->textfont(FL_COURIER); + m_BuildTextDisp->textsize(text_size); m_BuildTextDisp->end(); m_BuildTab->end(); + m_Tabs->resizable(m_BuildTab); /* ==================== Create Debug tab ==================== */ - m_DebugTab = new Fl_Group(2, 0, w-3, 170-MENU_HEIGHT-20, " Debug "); + m_DebugTab = new Fl_Group(2, 0, w-3, 75-MENU_HEIGHT-20, " Debug "); m_DebugTab->box(FL_DOWN_BOX); - m_DebugTab->selection_color(FL_WHITE); - m_DebugTab->color(FL_WHITE); + m_DebugTab->selection_color(FL_LIGHT2); + m_DebugTab->color(background_color); +// m_DebugTab->labelcolor(hl_plain); m_DebugTab->end(); + m_Tabs->resizable(m_DebugTab); /* ==================== Create watch tab ==================== */ - m_WatchTab = new Fl_Group(2, 0, w-3, 170-MENU_HEIGHT-20, " Watch "); + m_WatchTab = new Fl_Group(2, 0, w-3, 75-MENU_HEIGHT-20, " Watch "); m_WatchTab->box(FL_NO_BOX); - m_WatchTab->selection_color(FL_WHITE); - m_WatchTab->color(FL_WHITE); + m_WatchTab->selection_color(FL_LIGHT2); + m_WatchTab->color(background_color); // Create tiled window for auto and watch variables - Fl_Tile* tile2 = new Fl_Tile(2, 0,w,170-MENU_HEIGHT-20); + Fl_Tile* tile2 = new Fl_Tile(2, 0,w,75-MENU_HEIGHT-20); - Fl_Box* box0 = new Fl_Box(2, 0,w/2-2,170-MENU_HEIGHT-20,"1"); + Fl_Box* box0 = new Fl_Box(2, 0,w/2-2,75-MENU_HEIGHT-20,"1"); box0->box(FL_DOWN_BOX); - box0->color(FL_BACKGROUND_COLOR); + box0->color(background_color); + box0->labelcolor(hl_plain); box0->labelsize(36); box0->align(FL_ALIGN_CLIP); - Fl_Box* box1 = new Fl_Box(w/2, 0,w/2,170-MENU_HEIGHT-20,"2"); + Fl_Box* box1 = new Fl_Box(w/2, 0,w/2,75-MENU_HEIGHT-20,"2"); box1->box(FL_DOWN_BOX); - box1->color(FL_BACKGROUND_COLOR); + box1->color(background_color); + box1->labelcolor(hl_plain); box1->labelsize(36); box1->align(FL_ALIGN_CLIP); - Fl_Box* r2 = new Fl_Box(0,0,w,170-MENU_HEIGHT-20); + Fl_Box* r2 = new Fl_Box(0,0,w,75-MENU_HEIGHT-20); tile2->resizable(r2); tile2->end(); m_WatchTab->resizable(tile2); m_WatchTab->end(); - - m_Tabs->end(); + m_Tabs->resizable(m_WatchTab); + m_Tabs->end(); m_TabWindow->resizable(m_Tabs); + + // Create a line display box + Fl_Group* g = new Fl_Group(0, 0, m_TabWindow->w(), m_TabWindow->h()); + Fl_Box* b1 = new Fl_Box(0, 0, m_TabWindow->w(), m_TabWindow->h() - 25); +// b1->box(FL_BOX_NONE); + m_StatusBar.m_pLineBox = new Fl_Box(m_TabWindow->w() - 250, m_TabWindow->h() - 21, 100, 20, ""); + m_StatusBar.m_pColBox = new Fl_Box(m_TabWindow->w() - 150, m_TabWindow->h() - 21, 100, 20, ""); + m_StatusBar.m_pInsBox = new Fl_Box(m_TabWindow->w() - 50, m_TabWindow->h() - 21, 50, 20, ""); + m_StatusBar.line = m_StatusBar.col = m_StatusBar.ins_mode = -1; + g->resizable(b1); + g->end(); + m_TabWindow->end(); + // Set resize region - Fl_Box* r = new Fl_Box(150,MENU_HEIGHT-2,w-150,h-170); + Fl_Box* r = new Fl_Box(50,MENU_HEIGHT-2,w-50,h-75); + r->hide(); tile->resizable(r); tile->end(); resizable(m); resizable(tile); + // Reposition the tile separators to be a little bigger than the minimum + tile->position(150,MENU_HEIGHT-2+h-75, 150,MENU_HEIGHT-2+h-170); + + SetColors(hl_plain, background_color); + // End the Window end(); @@ -893,6 +1362,14 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) gRootpath = path; } +VT_Ide::~VT_Ide() +{ + m_EditTabs->clear(); + + delete m_pReplaceDlg; + delete m_pFindDlg; +} + /* ============================================================= Override the default show function to display the children @@ -972,16 +1449,16 @@ void VT_Ide::NewFile(void) Fl_Widget* pWidget; // Get number of child windows in the Ide - children = m_EditWindow->children(); + children = m_EditTabs->children(); for (seq = 1; ; seq++) { - // Try next sequence number ot see if window already exists + // Try next sequence number to see if window already exists title.Format("Text%d", seq); for (child = 0; child < children; child++) { - pWidget = (Fl_Widget*) m_EditWindow->child(child); + pWidget = (Fl_Widget*) m_EditTabs->child(child); if (strcmp((const char *) title, pWidget->label()) == 0) break; } @@ -1006,15 +1483,13 @@ if it doesn't. */ void VT_Ide::SaveFile(void) { - Fl_Multi_Edit_Window* mw; - int children; + Fl_Multi_Edit_Window* mw = NULL; MString rootpath; MString title; // First get a pointer to the active (topmost) window - children = m_EditWindow->children(); - mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); - if (mw == NULL) + mw = (Fl_Multi_Edit_Window*) m_EditTabs->value(); + if ((mw == NULL) || !mw->active()) return; // Validate this is truly a Multi_Edit_Window @@ -1028,7 +1503,7 @@ void VT_Ide::SaveFile(void) rootpath = m_ActivePrj->m_RootPath; mw->SaveFile(rootpath); - title = MakePathRelative(mw->Filename(), rootpath); + title = MakeTitle(mw->Filename()); mw->Title(title); } @@ -1042,13 +1517,11 @@ its SaveAs function. void VT_Ide::SaveAs(void) { Fl_Multi_Edit_Window* mw; - int children; MString rootpath; MString title; // First get a pointer to the active (topmost) window - children = m_EditWindow->children(); - mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + mw = (Fl_Multi_Edit_Window*) m_EditTabs->value(); if (mw == NULL) return; @@ -1063,8 +1536,9 @@ void VT_Ide::SaveAs(void) rootpath = m_ActivePrj->m_RootPath; mw->SaveAs(rootpath); - title = MakePathRelative(mw->Filename(), rootpath); + title = MakeTitle(mw->Filename()); mw->Title(title); + add_recent_file_to_menu((const char *) mw->Filename()); } /* @@ -1076,18 +1550,14 @@ window for the newly opened file. */ void VT_Ide::OpenFile(void) { - Fl_File_Chooser* fc; + Flu_File_Chooser* fc; int count; MString filename; - MString title; - MString rootpath; - if (m_ActivePrj == NULL) - rootpath = path; - else - rootpath = m_ActivePrj->m_RootPath; - fc = new Fl_File_Chooser((const char *) path, "*.asm,*.a85", 1, "Open File"); + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser((const char *) m_LastDir, "*.asm,*.a85", 1, "Open File"); + fl_cursor(FL_CURSOR_DEFAULT); fc->preview(0); fc->show(); @@ -1104,15 +1574,34 @@ void VT_Ide::OpenFile(void) } // Get the filename from the file chooser - filename = fc->value(1); + filename = fc->value(); + filename.Replace('\\', '/'); + + // Get the current directory and save for future use + m_LastDir = fc->get_current_directory(); + if (m_LastDir[m_LastDir.GetLength() - 1] == '/') + m_LastDir = m_LastDir.Left(m_LastDir.GetLength() - 1); delete fc; - title = MakePathRelative(filename, rootpath); + OpenFile(filename); +} + +void VT_Ide::OpenFile(const char *file) +{ + MString title; + MString rootpath; + + if (m_ActivePrj == NULL) + rootpath = path; + else + rootpath = m_ActivePrj->m_RootPath; + + title = MakeTitle(file); // Determine if file is already open - int children = m_EditWindow->children(); + int children = m_EditTabs->children(); for (int c = 0; c < children; c++) { - Fl_Widget* pWidget = (Fl_Widget*) m_EditWindow->child(c); + Fl_Widget* pWidget = (Fl_Widget*) m_EditTabs->child(c); if (strcmp((const char *) title, pWidget->label()) == 0) { // File already open...bring file to foreground @@ -1121,7 +1610,8 @@ void VT_Ide::OpenFile(void) } // Create a new edit window for the file - NewEditWindow(title, filename); + NewEditWindow(title, file); + add_recent_file_to_menu(file); } /* @@ -1134,15 +1624,30 @@ copy routine. void VT_Ide::Copy(void) { Fl_Multi_Edit_Window* mw; - int children; // First get a pointer to the active (topmost) window - children = m_EditWindow->children(); - mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + mw = (Fl_Multi_Edit_Window*) m_EditTabs->value(); + if (mw == NULL) + return; + + My_Text_Editor::kf_copy(0, mw); +} + +/* +============================================================= +Undo routine handles the Edit->Undo menu item. +============================================================= +*/ +void VT_Ide::Undo(void) +{ + Fl_Multi_Edit_Window* mw; + + // First get a pointer to the active (topmost) window + mw = (Fl_Multi_Edit_Window*) m_EditTabs->value(); if (mw == NULL) return; - Fl_Text_Editor::kf_copy(0, mw->m_te); + My_Text_Editor::kf_undo(0, mw); } /* @@ -1155,15 +1660,13 @@ cut routine. void VT_Ide::Cut(void) { Fl_Multi_Edit_Window* mw; - int children; // First get a pointer to the active (topmost) window - children = m_EditWindow->children(); - mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + mw = (Fl_Multi_Edit_Window*) m_EditTabs->value(); if (mw == NULL) return; - Fl_Text_Editor::kf_cut(0, mw->m_te); + My_Text_Editor::kf_cut(0, mw); } /* @@ -1176,15 +1679,13 @@ cut routine. void VT_Ide::Paste(void) { Fl_Multi_Edit_Window* mw; - int children; // First get a pointer to the active (topmost) window - children = m_EditWindow->children(); - mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + mw = (Fl_Multi_Edit_Window*) m_EditTabs->value(); if (mw == NULL) return; - Fl_Text_Editor::kf_paste(0, mw->m_te); + My_Text_Editor::kf_paste(0, mw); } /* @@ -1197,11 +1698,9 @@ cut routine. void VT_Ide::Find(void) { Fl_Multi_Edit_Window* mw; - int children; // First get a pointer to the active (topmost) window - children = m_EditWindow->children(); - mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + mw = (Fl_Multi_Edit_Window*) m_EditTabs->value(); if (mw == NULL) return; @@ -1219,12 +1718,10 @@ cut routine. void VT_Ide::FindNext(void) { Fl_Multi_Edit_Window* mw; - int children; const char * pFind; // First get a pointer to the active (topmost) window - children = m_EditWindow->children(); - mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + mw = (Fl_Multi_Edit_Window*) m_EditTabs->value(); if (mw == NULL) return; @@ -1238,9 +1735,15 @@ void VT_Ide::FindNext(void) } // Find the text + m_Search = pFind; + if (!mw->ForwardSearch(pFind, m_pFindDlg->m_pMatchCase->value())) + { + fl_alert("Search string %s not found", pFind); + mw->take_focus(); + } // Hide the dialog box - m_pFindDlg->m_pFindDlg->hide(); +// m_pFindDlg->m_pFindDlg->hide(); } /* @@ -1265,13 +1768,11 @@ pressed in the ReplaceDlg. void VT_Ide::ReplaceAll(void) { Fl_Multi_Edit_Window* mw; - int children; const char * pFind; const char * pReplace; // First get a pointer to the active (topmost) window - children = m_EditWindow->children(); - mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + mw = (Fl_Multi_Edit_Window*) m_EditTabs->value(); if (mw == NULL) return; @@ -1301,13 +1802,11 @@ pressed in the ReplaceDlg. void VT_Ide::ReplaceNext(void) { Fl_Multi_Edit_Window* mw; - int children; const char * pFind; const char * pReplace; // First get a pointer to the active (topmost) window - children = m_EditWindow->children(); - mw = (Fl_Multi_Edit_Window*) m_EditWindow->child(children-1); + mw = (Fl_Multi_Edit_Window*) m_EditTabs->value(); if (mw == NULL) return; @@ -1399,8 +1898,12 @@ void VT_Ide::NewProject(void) pRootDir = pProj->getLocation(); if (pRootDir[0] == '.') { + char ch; + strcpy(fullPath, path); - strcat(fullPath, "/"); + ch = path[strlen(path)-1]; + if ((ch != '\\') && (ch != '/')) + strcat(fullPath, "/"); strcat(fullPath, &pRootDir[2]); m_ActivePrj->m_RootPath = fullPath; } @@ -1409,6 +1912,7 @@ void VT_Ide::NewProject(void) m_ActivePrj->m_RootPath = pRootDir; } + m_ActivePrj->m_RootPath.Replace('\\', '/'); // Check if path ends with '/' if (m_ActivePrj->m_RootPath[m_ActivePrj->m_RootPath.GetLength()-1] != '/') @@ -1438,6 +1942,7 @@ void VT_Ide::NewProject(void) // Save the target model m_ActivePrj->m_TargetModel = pProj->getTargetModel(); gRootpath = m_ActivePrj->m_RootPath; + m_LastDir = gRootpath; // Save the new project SaveProject(); @@ -1487,70 +1992,20 @@ a .prj file. */ void VT_Ide::SaveProject(void) { - FILE* fd; char fullPath[512]; - char model[10]; - int count, c, objs, x; - VT_IdeGroup* pGroup; - VT_IdeSource* pObj; // Check if m_ActiveProj is valid if (m_ActivePrj == NULL) return; - // Create the path + m_ActivePrj->SaveProject(); + SaveProjectIdeSettings(); + + // Create the project file path and add to recent sprintf(fullPath, "%s/%s.prj", (const char *) m_ActivePrj->m_RootPath, (const char *) m_ActivePrj->m_Name); + add_recent_project_to_menu(fullPath); - // Try to open the file for write mode - if ((fd = fopen(fullPath, "w+")) == NULL) - { - // Error opening file!! - fl_alert("Error opening projec file for write mode!"); - return; - } - - // Write header information - fprintf(fd, "NAME=%s\n", (const char *) m_ActivePrj->m_Name); - fprintf(fd, "INCLPATH=%s\n", (const char *) m_ActivePrj->m_IncludePath); - fprintf(fd, "DEFINES=%s\n", (const char *) m_ActivePrj->m_Defines); - fprintf(fd, "LINKPATH=%s\n", (const char *) m_ActivePrj->m_LinkPath); - fprintf(fd, "LINKLIBS=%s\n", (const char *) m_ActivePrj->m_LinkLibs); - fprintf(fd, "CSEG=%s\n", (const char *) m_ActivePrj->m_CodeAddr); - fprintf(fd, "DSEG=%s\n", (const char *) m_ActivePrj->m_DataAddr); - fprintf(fd, "ASMOPT=%s\n", (const char *) m_ActivePrj->m_AsmOptions); - fprintf(fd, "LINKOPT=%s\n", (const char *) m_ActivePrj->m_LinkOptions); - fprintf(fd, "TYPE=%s\n", gProjectTypes[m_ActivePrj->m_ProjectType]); - get_model_string(model, m_ActivePrj->m_TargetModel); - fprintf(fd, "TARGET=%s\n", model); - fprintf(fd, "AUTOLOAD=%d\n", m_ActivePrj->m_AutoLoad); - fprintf(fd, "UPDATEHIMEM=%d\n", m_ActivePrj->m_UpdateHIMEM); - fprintf(fd, "\n"); - - // Write group information to the file - count = m_ActivePrj->m_Groups.GetSize(); - for (c = 0; c < count; c++) - { - pGroup = (VT_IdeGroup*) m_ActivePrj->m_Groups[c]; - fprintf(fd, "GROUP=%s\n", (const char *) pGroup->m_Name); - fprintf(fd, "FILESPEC=%s\n", (const char *) pGroup->m_Filespec); - - // Write objects - objs = pGroup->m_Objects.GetSize(); - for (x = 0; x < objs; x++) - { - pObj = (VT_IdeSource*) pGroup->m_Objects[x]; - fprintf(fd, "SOURCE=%s\n", (const char *) pObj->m_Name); - } - - // End the group - fprintf(fd, "ENDGROUP\n\n"); - } - - m_ActivePrj->m_Dirty = 0; - - // Close the file - fclose(fd); } /* @@ -1564,10 +2019,12 @@ load the project. void VT_Ide::OpenProject(void) { MString filename; - Fl_File_Chooser *FileWin; + Flu_File_Chooser *FileWin; int count; - FileWin = new Fl_File_Chooser("./Projects","*.prj",1,"Open Project file"); + fl_cursor(FL_CURSOR_WAIT); + FileWin = new Flu_File_Chooser("./Projects","*.prj",1,"Open Project file"); + fl_cursor(FL_CURSOR_DEFAULT); FileWin->preview(0); FileWin->show(); @@ -1582,12 +2039,13 @@ void VT_Ide::OpenProject(void) } // Get Filename - if (FileWin->value(1) == 0) + if (FileWin->value(0) == 0) { delete FileWin; return; } - filename = FileWin->value(1); + filename = FileWin->value(0); + filename.Replace('\\', '/'); delete FileWin; // Check if there is an active project @@ -1609,14 +2067,235 @@ void VT_Ide::OpenProject(void) m_ActivePrj = 0; } + OpenProject((const char *) filename); +} + +/* +============================================================= +The BuildTreeControl routine builds / rebuilds the Project +Tree control from the active Project structure. +============================================================= +*/ +void VT_Ide::OpenProject(const char *filename) +{ // Try to parse the file if (ParsePrjFile(filename)) + { BuildTreeControl(); + add_recent_project_to_menu(filename); + ReadProjectIdeSettings(); + gRootpath = m_ActivePrj->m_RootPath; + m_LastDir = gRootpath; + } else { // Report parse error } - gRootpath = m_ActivePrj->m_RootPath; +} + +/* +============================================================= +This routine saves the project's current file tabs and the +status of open Tree Browser items. +============================================================= +*/ +void VT_Ide::SaveProjectIdeSettings() +{ + FILE* fd; + char fullPath[512]; + Flu_Tree_Browser::Node* pNode; + Fl_Multi_Edit_Window* mw; + Fl_Multi_Edit_Window* mw_selected = NULL; + int count, c; + + // Check if m_ActiveProj is valid + if (m_ActivePrj == NULL) + return; + + // Create the path + sprintf(fullPath, "%s/%s.ide", (const char *) m_ActivePrj->m_RootPath, + (const char *) m_ActivePrj->m_Name); + + // Try to open the file for write mode + if ((fd = fopen(fullPath, "w+")) == NULL) + { + // Error opening file!! + fl_alert("Error opening project IDE file for write mode!"); + return; + } + + // Write open tree broweser information + pNode = this->m_ProjTree->get_root(); + if (pNode != NULL) + { + pNode = pNode->next(); + while (pNode) + { + if (pNode->is_branch() && pNode->open()) + { + fprintf(fd, "OPEN_TREE=%s\n", pNode->find_path()); + } + pNode = pNode->next(); + } + } + + // Write open file tabs information + count = m_EditTabs->children(); + for (c = 0; c < count; c++) + { + mw = (Fl_Multi_Edit_Window *) m_EditTabs->child(c); + MString filename = mw->Filename(); + if (filename.GetLength() == 0) + continue; + fprintf(fd, "OPEN_FILE=%s\t%d\n", (const char *) filename, + mw->insert_position()); + if (m_EditTabs->value() == mw) + mw_selected = mw; + } + + // Save the selected tab + if (mw_selected != NULL) + { + MString filename = mw_selected->Filename(); + fprintf(fd, "SELECTED=%s\n", (const char *) filename); + } + + // Close the IDE file + fclose(fd); +} + +/* +============================================================= +This routine restores the project's current file tabs and the +status of open Tree Browser items. +============================================================= +*/ +void VT_Ide::ReadProjectIdeSettings() +{ + char line[300]; + char *param, *value; + FILE* fd; + int c, tabloc, count; + MString sParam, sSelected; + const char * sPtr; + int pos; + + // Create the path + sprintf(line, "%s/%s.ide", (const char *) m_ActivePrj->m_RootPath, + (const char *) m_ActivePrj->m_Name); + + // Try to open the file for write mode + if ((fd = fopen(line, "r")) == NULL) + { + // Error opening file!! + return; + } + + // Loop through all lines in file + while (fgets(line, 512, fd) != 0) + { + // Skip comments and blank lines + if ((line[0] == '#') || (line[0] == '\n') || (line[0] == '\x0d')) + continue; + + // Parse the line - find the first '=' + for (c = 0; (line[c] != 0) && (line[c] != '=') && (line[c] != '\n') && (line[c] != 13) ; c++) + ; + param = line; + if (line[c] == '=') + { + line[c] = 0; + value = &line[c+1]; + for (c++; (line[c] != 0) && (line[c] != '\n') && (line[c] != 13); c++) + ; + line[c] = 0; + } + else + { + line[c] = 0; + value = (char *) ""; + } + + // Check for error in line + if (value == 0) + { + // Report error + continue; + } + + sParam = param; + sParam.MakeUpper(); + sPtr = (const char *) sParam; + if (strcmp(sPtr, "OPEN_TREE") == 0) + { + Flu_Tree_Browser::Node* n = m_ProjTree->find(value); + if (n) + { + n->open(true); + } + } + else if (strcmp(sPtr, "OPEN_FILE") == 0) + { + // Search for tab separator for insertion line number + tabloc = 0; + for (c = strlen(value) - 1; c > 0; c--) + { + if (value[c] == '\t') + { + tabloc = c; + break; + } + } + + // If a tab was found, get the insertion point and terminate file + if (tabloc != 0) + { + pos = atoi(&value[tabloc + 1]); + value[tabloc] = '\0'; + } + + // Try to open the file + MString file = value; + MString title = MakeTitle(file); + Fl_Multi_Edit_Window* mw = NewEditWindow(title, file, FALSE); + + // Position the file to the last location + if (tabloc) + { + mw->insert_position(pos); + mw->show_insert_position(); + mw->take_focus(); + mw->show_cursor(); + } + } + else if (strcmp(sPtr, "SELECTED") == 0) + { + // Save the name of the selected file until all files loaded + sSelected = value; + } + } + + // Re-select the selcted file + if (sSelected.GetLength() != 0) + { + count = m_EditTabs->children(); + for (c = 0; c < count; c++) + { +// Fl_Multi_Edit_Window* mw = (Fl_Multi_Edit_Window *) +// ((Fl_Group *) m_EditTabs->child(c))->child(0); + Fl_Multi_Edit_Window* mw = (Fl_Multi_Edit_Window *) + m_EditTabs->child(c); + if (mw->Filename() == sSelected) + { +// m_EditTabs->value(mw->parent()); + m_EditTabs->value(mw); + mw->take_focus(); + break; + } + } + } + + fclose(fd); } /* @@ -1639,6 +2318,8 @@ void VT_Ide::BuildTreeControl(void) if (m_ActivePrj == 0) return; + m_ProjTree->clear(); + // set the default leaf icon to be a blue dot m_ProjTree->leaf_icon( &gTextDoc ); m_ProjTree->insertion_mode( FLU_INSERT_SORTED ); @@ -1677,6 +2358,8 @@ void VT_Ide::BuildTreeControl(void) if (n) { n->user_data(pGroup); + n->label_color(hl_plain); + n->label_size(text_size); pGroup->m_Node = n; } @@ -1709,6 +2392,8 @@ void VT_Ide::BuildTreeControl(void) { n->leaf_icon( &gTextDoc ); n->user_data(pSource); + n->label_color(hl_plain); + n->label_size(text_size); pSource->m_Node = n; } } @@ -1716,6 +2401,7 @@ void VT_Ide::BuildTreeControl(void) m_ProjTree->open(TRUE); m_ProjTree->show(); + m_ProjTree->redraw(); } /* @@ -1745,6 +2431,7 @@ void VT_Ide::AddGroupToTree(VTObject *pObj, const char *fmt) { n->user_data(pGroup); pGroup->m_Node = n; + n->label_size(text_size); } addStr += (char *) "%s"; @@ -1776,6 +2463,7 @@ void VT_Ide::AddGroupToTree(VTObject *pObj, const char *fmt) { n->leaf_icon( &gTextDoc ); n->user_data(pSource); + n->label_size(text_size); pSource->m_Node = n; } } @@ -1807,8 +2495,21 @@ int VT_Ide::ParsePrjFile(const char *name) return 0; // Ensure active project not null - if (m_ActivePrj == 0) - m_ActivePrj = new VT_Project; + if (m_ActivePrj != 0) + delete m_ActivePrj; + + m_ActivePrj = new VT_Project; + + // Set the RootPath + temp = name; + // Get just the path + index = temp.ReverseFind((char *) "/"); + if (index == 0) + m_ActivePrj->m_RootPath = path; + else + m_ActivePrj->m_RootPath = temp.Left(index); + + index = 0; // Loop through all lines in file while (fgets(line, 512, fd) != 0) @@ -1884,6 +2585,7 @@ int VT_Ide::ParsePrjFile(const char *name) // Assign name to new group newgrp->m_Name = value; + newgrp->m_pParent = pGroup; // Insert groups alphabetically before sources len = pGroup->m_Objects.GetSize(); @@ -1894,7 +2596,7 @@ int VT_Ide::ParsePrjFile(const char *name) if (strcmp(pIns->GetClass()->m_ClassName, "VT_IdeSource") == 0) break; - if (pSource->m_Name < ((VT_IdeGroup *) pIns)->m_Name) + if (newgrp->m_Name < ((VT_IdeGroup *) pIns)->m_Name) break; } pGroup->m_Objects.InsertAt(c, newgrp); @@ -1993,15 +2695,10 @@ int VT_Ide::ParsePrjFile(const char *name) if (value != 0) m_ActivePrj->m_LinkOptions = value; } - else if (strcmp(sPtr, "DSEG") == 0) - { - if (value != 0) - m_ActivePrj->m_DataAddr = value; - } - else if (strcmp(sPtr, "CSEG") == 0) + else if (strcmp(sPtr, "LINKSCRIPT") == 0) { if (value != 0) - m_ActivePrj->m_CodeAddr = value; + m_ActivePrj->m_LinkScript = value; } } @@ -2096,13 +2793,29 @@ void VT_Ide::DeleteItem(Flu_Tree_Browser::Node* n) m_ProjTree->remove(pGroup->m_Node); // Now find the group entry in the active project - count = m_ActivePrj->m_Groups.GetSize(); - for (int c = 0; c < count; c++) + if (pGroup->m_pParent != NULL) { - if (pGroup == (VT_IdeGroup*) m_ActivePrj->m_Groups[c]) + VT_IdeGroup* pParentGroup = pGroup->m_pParent; + count = pParentGroup->m_Objects.GetSize(); + for (int c = 0; c < count; c++) { - m_ActivePrj->m_Groups.RemoveAt(c, 1); - break; + if (pGroup == (VT_IdeGroup*) pParentGroup->m_Objects[c]) + { + pParentGroup->m_Objects.RemoveAt(c, 1); + break; + } + } + } + else + { + count = m_ActivePrj->m_Groups.GetSize(); + for (int c = 0; c < count; c++) + { + if (pGroup == (VT_IdeGroup*) m_ActivePrj->m_Groups[c]) + { + m_ActivePrj->m_Groups.RemoveAt(c, 1); + break; + } } } delete pGroup; @@ -2114,9 +2827,12 @@ void VT_Ide::DeleteItem(Flu_Tree_Browser::Node* n) else { VT_IdeSource* pSrc = (VT_IdeSource*) pObj; + Flu_Tree_Browser::Node* pNext = pSrc->m_Node->next(); // Delete the source from the tree m_ProjTree->remove(pSrc->m_Node); + if (pNext != NULL) + m_ProjTree->set_hilighted(pNext); // Delete the source from the parent Group int count = pSrc->m_ParentGroup->m_Objects.GetSize(); @@ -2145,8 +2861,13 @@ The routine displays a pop-up menu */ void VT_Ide::RightClick(Flu_Tree_Browser::Node* n) { + int c, count; + if (n->is_root()) { + count = sizeof(gRootMenu) / sizeof(Fl_Menu_Item); + for (c = 0; c < count; c++) + gRootMenu[c].user_data_ = n; gPopup->menu(gRootMenu); } else @@ -2160,22 +2881,24 @@ void VT_Ide::RightClick(Flu_Tree_Browser::Node* n) if (strcmp(pObj->GetClass()->m_ClassName, "VT_IdeGroup") == 0) { // Select group popup menu - gGroupMenu[0].user_data_ = n; - gGroupMenu[1].user_data_ = n; - gGroupMenu[2].user_data_ = n; + count = sizeof(gGroupMenu) / sizeof(Fl_Menu_Item); + for (c = 0; c < count; c++) + gGroupMenu[c].user_data_ = n; gPopup->menu(gGroupMenu); } else { // Select source popup menu - gSourceMenu[0].user_data_ = n; - gSourceMenu[1].user_data_ = n; - gSourceMenu[2].user_data_ = n; + count = sizeof(gSourceMenu) / sizeof(Fl_Menu_Item); + for (c = 0; c < count; c++) + gSourceMenu[c].user_data_ = n; gPopup->menu(gSourceMenu); } } // Add label to popup menu & display - gPopup->label(n->label()); + make_current(); +// gPopup->label(n->label()); + gPopup->label(NULL); gPopup->popup(); } @@ -2220,6 +2943,8 @@ void VT_Ide::NewFolder(Flu_Tree_Browser::Node* n) root = 1; n = m_ProjTree->get_root(); } + else if (n->parent() == NULL) + root = 1; else root = 0; @@ -2273,6 +2998,7 @@ void VT_Ide::NewFolder(Flu_Tree_Browser::Node* n) newNode = m_ProjTree->insert_at(n, i, name); newNode->user_data(pNewGrp); + newNode->label_size(text_size); pNewGrp->m_Node = newNode; // Add new node to active project @@ -2289,6 +3015,7 @@ void VT_Ide::NewFolder(Flu_Tree_Browser::Node* n) pGroup->m_Objects.Add(pNewGrp); else pGroup->m_Objects.InsertAt(c, pNewGrp); + pNewGrp->m_pParent = pGroup; } // Set Dirty flag @@ -2305,7 +3032,7 @@ requested folder. */ void VT_Ide::AddFilesToFolder(Flu_Tree_Browser::Node* n) { - Fl_File_Chooser *fc; /* File Chooser */ + Flu_File_Chooser *fc; /* File Chooser */ int count, c; int len, index, x; MString filename, relPath; @@ -2316,8 +3043,10 @@ void VT_Ide::AddFilesToFolder(Flu_Tree_Browser::Node* n) VTObject* pIns; /* Create a new File Chooser object */ - fc = new Fl_File_Chooser((const char *) m_LastDir, "Source Files (*.{asm,inc,h})", - Fl_File_Chooser::MULTI, "Add Files to Project"); + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser((const char *) m_LastDir, "Source Files (*.{asm,inc,h})", + Flu_File_Chooser::MULTI, "Add Files to Project"); + fl_cursor(FL_CURSOR_DEFAULT); fc->preview(0); fc->show(); @@ -2339,7 +3068,9 @@ void VT_Ide::AddFilesToFolder(Flu_Tree_Browser::Node* n) pGroup = (VT_IdeGroup*) n->user_data(); // Get the current directory and save for future use - m_LastDir = fc->directory(); + m_LastDir = fc->get_current_directory(); + if (m_LastDir[m_LastDir.GetLength() - 1] == '/') + m_LastDir = m_LastDir.Left(m_LastDir.GetLength() - 1); // Calculate relative path for files @@ -2347,7 +3078,8 @@ void VT_Ide::AddFilesToFolder(Flu_Tree_Browser::Node* n) for (c = 0; c < count; c++) { // Get next filename from the FileChooser - filename = fc->value(c+1); + filename = fc->value(c); + filename.Replace('\\', '/'); // Get just the filename index = filename.ReverseFind('/'); @@ -2357,7 +3089,8 @@ void VT_Ide::AddFilesToFolder(Flu_Tree_Browser::Node* n) temp = filename.Right(filename.GetLength() - index - 1); // Check if entry aleady exists - if (n->find((const char *) temp) != NULL) + if (m_ActivePrj->TestIfFileInProject(filename)) +// if (n->find((const char *) temp) != NULL) { // Add file to list of "error" files errFiles.Add(temp); @@ -2388,13 +3121,36 @@ void VT_Ide::AddFilesToFolder(Flu_Tree_Browser::Node* n) if (pSource->m_Node == NULL) printf("Error inserting node!\n"); else + { pSource->m_Node->user_data(pSource); + n->open(true); + } m_ActivePrj->m_Dirty = 1; } + m_ProjTree->redraw(); /* Delete the file chooser */ delete fc; + + // Test for errors during insertion + if (errFiles.GetSize() > 0) + { + MString err; + MString files; + for (x = 0; x < errFiles.GetSize(); x++) + { + if (x == errFiles.GetSize() - 1) + files += errFiles[x]; + else + files += errFiles[x] + (char *) ", "; + } + if (errFiles.GetSize() > 1) + err.Format("Files %s already in project!", (const char *) files); + else + err.Format("File %s already in project!", (const char *) files); + fl_alert((const char *) err); + } return; } @@ -2402,6 +3158,11 @@ void VT_Ide::FolderProperties(Flu_Tree_Browser::Node* n) { } +/* +============================================================= +Open the tree item in the edit window +============================================================= +*/ void VT_Ide::OpenTreeFile(Flu_Tree_Browser::Node* n) { VT_IdeSource* pSource; @@ -2420,16 +3181,18 @@ void VT_Ide::OpenTreeFile(Flu_Tree_Browser::Node* n) file = pSource->m_Name.Right(pSource->m_Name.GetLength()-2); else file = pSource->m_Name; - title = MakePathRelative(file, m_ActivePrj->m_RootPath); + title = MakeTitle(file); // Check if the file is already open - children = m_EditWindow->children(); + children = m_EditTabs->children(); for (c = 0; c < children; c++) { - pWidget = (Fl_Widget*) m_EditWindow->child(c); + pWidget = (Fl_Widget*) m_EditTabs->child(c); if (strcmp((const char *) title, pWidget->label()) == 0) { // File already open...bring file to foreground + m_EditTabs->value(pWidget); + pWidget->take_focus(); return; } } @@ -2445,40 +3208,50 @@ NewEditWindow: This routine creates a new edit window with the specified window is loaded from the file. =============================================================================== */ -void VT_Ide::NewEditWindow(const MString& title, const MString& file) +Fl_Multi_Edit_Window* VT_Ide::NewEditWindow(const MString& title, const MString& file, + int addToRecentFiles) { - int x = 1; - int y = 1; - int w = 400; - int h = 300; - int count = 6; + int x, y, w, h; /* Calculate location of next window */ - if (m_EditWindow->h() < 550) - count = 5; - h = m_EditWindow->h() - 28 * count; - w = m_EditWindow->w() - 28 * count; - x = y = m_OpenLocation++ * 28; - if (m_OpenLocation >= count) - m_OpenLocation = 0; - - /* Create window */ - Fl_Multi_Edit_Window* mw = new Fl_Multi_Edit_Window(x, y, w, h, (const char *) title); + x = 0; + y = TAB_HEIGHT; + h = m_EditTabs->h() - TAB_HEIGHT; + w = m_EditTabs->w(); + + /* Create a group tab */ +// Fl_Group* g = new Fl_Group(x, y, w, h, (const char *) title); + + /* Now Create window */ + Fl_Multi_Edit_Window* mw = new Fl_Multi_Edit_Window(x, y, w, h, + (const char *) title); if (file != "") + { mw->OpenFile((const char *) file); + if (addToRecentFiles) + add_recent_file_to_menu((const char *) file); + } mw->end(); // Insert new window in EditWindow - Fl_Widget* prev = m_EditWindow->child(m_EditWindow->children()-1); - m_EditWindow->insert(*mw, m_EditWindow->children()); + m_EditTabs->insert(*mw, m_EditTabs->children()); + m_EditTabs->resizable(m_EditTabs->child(m_EditWindow->children()-1)); + mw->add_status_bar(&m_StatusBar); + mw->color(background_color); + mw->mCursor_color = hl_plain; + mw->textsize(text_size); + mw->textcolor(hl_plain); + mw->selection_color(FL_DARK_BLUE); +// mw->tooltip((const char *) mw->Filename()); mw->show(); + m_EditTabs->value(m_EditTabs->child(m_EditTabs->children()-1)); + if (m_EditTabs->children() == 1) + m_EditTabs->show(); - // Redraw current window to show it as inactive - if (prev != 0) - prev->redraw(); // Call show again to bring window to front - mw->show(); mw->take_focus(); + + return mw; } void VT_Ide::AssembleTreeFile(Flu_Tree_Browser::Node* n) @@ -2489,6 +3262,25 @@ void VT_Ide::TreeFileProperties(Flu_Tree_Browser::Node* n) { } +/* +============================================================================= +Standard output support for echo messages from assembler / linker +============================================================================= +*/ +void ideStdoutProc(void *pContext, const char *msg) +{ + VT_Ide* pIde = (VT_Ide*) pContext; + + if ((pIde != NULL) && (msg != NULL)) + pIde->Stdout(msg); +} + +void VT_Ide::Stdout(const char *msg) +{ + m_BuildTextBuf->append(msg); + Fl::check(); +} + /* ============================================================================= BuildProjet: This routine is the reason for all this mess! Try to assemble @@ -2508,6 +3300,8 @@ void VT_Ide::BuildProject(void) int assemblyNeeded; MStringArray errors; MString filename; + MString linkerFiles; + VTLinker linker; // Be sure we have an active project if (m_ActivePrj == NULL) @@ -2515,14 +3309,18 @@ void VT_Ide::BuildProject(void) // Clear the Build tab at the bottom m_BuildTextBuf ->remove(0, m_BuildTextBuf->length()); + Fl::check(); // Configure the assembler assembler.SetRootPath(m_ActivePrj->m_RootPath); assembler.SetAsmOptions(m_ActivePrj->m_AsmOptions); assembler.SetIncludeDirs(m_ActivePrj->m_IncludePath); assembler.SetDefines(m_ActivePrj->m_Defines); + assembler.SetProjectType(m_ActivePrj->m_ProjectType); + assembler.SetStdoutFunction(this, ideStdoutProc); m_BuildTextBuf->append("Assembling...\n"); + Fl::check(); // Loop through each group and look for files to assemble errorCount = 0; @@ -2552,6 +3350,10 @@ void VT_Ide::BuildProject(void) assemblyNeeded = TRUE; // Delete old .obj file + + // Add this file to the list of files to be linked + temp = pSource->m_Name.Left(pSource->m_Name.GetLength() - 4) + (char *) ".obj"; + linkerFiles += temp + (char *) ","; } // Try to assemble the file @@ -2562,9 +3364,11 @@ void VT_Ide::BuildProject(void) temp = pSource->m_Name.Right(pSource->m_Name.GetLength()-index-1); text.Format("%s\n", (const char *) temp); m_BuildTextBuf->append((const char *) text); + Fl::check(); // Try to assemble this file filename = MakePathAbsolute(pSource->m_Name, m_ActivePrj->m_RootPath); + assembler.ResetContent(); assembler.Parse(filename); // Check if any errors occurred & report them @@ -2590,8 +3394,30 @@ void VT_Ide::BuildProject(void) else { m_BuildTextBuf->append("Linking...\n"); - } + Fl::check(); + + // Setup the linker + linker.SetRootPath(m_ActivePrj->m_RootPath); + linker.SetLinkOptions(m_ActivePrj->m_LinkOptions); + linker.SetObjDirs(m_ActivePrj->m_LinkPath); + linker.SetProjectType(m_ActivePrj->m_ProjectType); + linker.SetLinkerScript(m_ActivePrj->m_LinkScript); + linkerFiles = linkerFiles + (char *) "," + m_ActivePrj->m_LinkLibs; + linker.SetObjFiles(linkerFiles); + linker.SetStdoutFunction(this, ideStdoutProc); + + // Now finally perform the link operation + linker.Link(); + errors = linker.GetErrors(); + errorCount = errors.GetSize(); + totalErrors += errorCount; + for (err = 0; err < errorCount; err++) + { + m_BuildTextBuf->append((const char *) errors[err]); + m_BuildTextBuf->append("\n"); + } + } } void VT_Ide::CleanProject(void) @@ -2615,6 +3441,26 @@ void VT_Ide::ShowProjectSettings(void) } +/* +=============================================================================== +This routine returns a string which is the relative form of the given path +realtive to the relTo path. The routine detects both relativeness in bot +directions and uses '..' as necessary in the returned string. +=============================================================================== +*/ +MString VT_Ide::MakeTitle(const MString& path) +{ + MString temp; + int index; + + // Search for the last directory separator token + index = path.ReverseFind('/'); + if (index == -1) + return path; + + return path.Right(path.GetLength() - index - 1); +} + /* =============================================================================== This routine returns a string which is the relative form of the given path @@ -2652,8 +3498,13 @@ MString VT_Ide::MakePathRelative(const MString& path, const MString& relTo) while ((c != lenPath) && (c != lenRel)) { // Test +#ifdef WIN32 + if (tolower(path[c]) != tolower(relTo[c])) + break; +#else if (path[c] != relTo[c]) break; +#endif if (path[c] == '/') lastMatch = c; c++; @@ -2725,6 +3576,14 @@ MString VT_Ide::MakePathAbsolute(const MString& path, const MString& relTo) index = newRel.ReverseFind('/'); if (index != -1) newRel = newRel.Left(index - 1); + else + { + index = newRel.ReverseFind('\\'); + if (index != -1) + newRel = newRel.Left(index - 1); + else + break; + } } temp = newRel + '/' + temp; @@ -2750,6 +3609,7 @@ void cb_replace_cancel(Fl_Widget* w, void* v) VT_ReplaceDlg* pDlg = (VT_ReplaceDlg*) v; pDlg->m_pReplaceDlg->hide(); + gpIde->show(); } /* @@ -2788,23 +3648,46 @@ VT_FindDlg routines below. */ VT_FindDlg::VT_FindDlg(class VT_Ide* pParent) { - m_pFindDlg = new Fl_Window(300, 105, "Find"); - m_pFind = new Fl_Input(40, 10, 250, 25, "Find:"); + // Create Find What combo list + m_pFindDlg = new Fl_Window(400, 300, "Find"); + Fl_Box *o = new Fl_Box(20, 10, 100, 25, "Find what:"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pFind = new Flu_Combo_List(20, 35, 360, 25, ""); m_pFind->align(FL_ALIGN_LEFT); - - m_pForward = new Fl_Round_Button(80, 40, 90, 25, "Forward"); - m_pForward->value(1); - m_pBackward = new Fl_Round_Button(200, 40, 90, 25, "Backward"); - - m_pNext = new Fl_Return_Button(105, 70, 100, 25, "Find Next"); - m_pNext->callback(cb_replace_next, this); - - m_pCancel = new Fl_Button(230, 70, 60, 25, "Cancel"); + m_pFindDlg->resizable(m_pFind); + + // Create Find In choice box + o = new Fl_Box(20, 70, 100, 20, "Find in:"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pFindIn = new Fl_Choice(20, 95, 360, 25, ""); + m_pFindIn->add("Current Window"); + m_pFindIn->add("Current Selection"); + m_pFindIn->value(0); + m_pFindDlg->resizable(m_pFindIn); + + o = new Fl_Box(20, 135, 360, 110, "Find options"); + o->box(FL_ENGRAVED_BOX); + o->labeltype(FL_ENGRAVED_LABEL); + o->align(FL_ALIGN_TOP_LEFT | FL_ALIGN_INSIDE); + m_pFindDlg->resizable(o); + + m_pBackward = new Fl_Check_Button(40, 160, 120, 25, "Search backward"); + m_pMatchCase = new Fl_Check_Button(40, 185, 100, 25, "Match case"); + m_pWholeWord = new Fl_Check_Button(40, 210, 140, 25, "Match whole word"); + + o = new Fl_Box(20, 250, 50, 45, ""); + m_pFindDlg->resizable(o); + + m_pNext = new Flu_Return_Button(160, 255, 100, 25, "Find Next"); + m_pNext->callback(cb_find_next, this); + + m_pCancel = new Flu_Button(280, 255, 100, 25, "Close"); m_pCancel->callback(cb_replace_cancel, this); + o = new Fl_Box(20, 295, 360, 2, ""); + m_pFindDlg->resizable(o); m_pFindDlg->end(); m_pFindDlg->set_non_modal(); m_pParent = pParent; } - diff --git a/src/ide.h b/src/ide.h index 8318b9f..0a6cdb8 100644 --- a/src/ide.h +++ b/src/ide.h @@ -31,9 +31,17 @@ #ifndef _IDE_H_ #define _IDE_H_ +#include +#include +#include "FLU/Flu_Combo_List.h" +#include "FLU/Flu_Return_Button.h" +#include "FLU/Flu_Button.h" + #include "MString.h" #include "vtobj.h" #include "project.h" +#include "My_Text_Editor.h" +#include "idetabs.h" void cb_Ide(Fl_Widget* w, void*) ; @@ -58,20 +66,20 @@ class VT_IdeGroup : public VTObject DECLARE_DYNCREATE(VT_IdeGroup); public: - VT_IdeGroup() {}; + VT_IdeGroup() {m_Node = NULL; m_pParent = NULL; }; ~VT_IdeGroup(); MString m_Name; MString m_Filespec; VTObArray m_Objects; Flu_Tree_Browser::Node* m_Node; + VT_IdeGroup* m_pParent; }; class VT_ReplaceDlg { public: VT_ReplaceDlg(class VT_Ide* pParent); - ~VT_ReplaceDlg(); Fl_Window* m_pReplaceDlg; Fl_Input* m_pFind; @@ -89,14 +97,15 @@ class VT_FindDlg { public: VT_FindDlg(class VT_Ide* pParent); - ~VT_FindDlg(); Fl_Window* m_pFindDlg; - Fl_Input* m_pFind; - Fl_Round_Button* m_pForward; - Fl_Round_Button* m_pBackward; - Fl_Button* m_pNext; - Fl_Button* m_pCancel; + Flu_Combo_List* m_pFind; + Fl_Choice* m_pFindIn; + Fl_Check_Button* m_pBackward; + Fl_Check_Button* m_pMatchCase; + Fl_Check_Button* m_pWholeWord; + Flu_Button* m_pNext; + Flu_Button* m_pCancel; class VT_Ide* m_pParent; @@ -107,6 +116,7 @@ class VT_Ide : public Fl_Window { public: VT_Ide(int x, int y, int w, int h, const char *title = 0); + ~VT_Ide(); // Methods virtual void show(); @@ -114,7 +124,10 @@ class VT_Ide : public Fl_Window void NewProject(void); void OpenProject(void); + void OpenProject(const char *filename); void SaveProject(void); + void SaveProjectIdeSettings(void); + void ReadProjectIdeSettings(void); void BuildTreeControl(void); int ParsePrjFile(const char *name); void RightClick(Flu_Tree_Browser::Node* n); @@ -123,9 +136,11 @@ class VT_Ide : public Fl_Window void SaveFile(void); void SaveAs(void); void OpenFile(void); + void OpenFile(const char *file); void Copy(void); void Cut(void); void Paste(void); + void Undo(void); void Find(void); void FindNext(void); void Replace(void); @@ -139,27 +154,34 @@ class VT_Ide : public Fl_Window void TreeFileProperties(Flu_Tree_Browser::Node* n); void BuildProject(void); void CleanProject(void); + void SetColors(int fg, int bg); void ShowProjectSettings(void); + void LoadPrefs(void); + void SavePrefs(void); MString MakePathRelative(const MString& path, const MString& relTo); MString MakePathAbsolute(const MString& path, const MString& relTo); + MString MakeTitle(const MString& path); MString ProjectName(void); + void Stdout(const char *msg); int ProjectDirty(void); Fl_Window* m_EditWindow; + Fl_Ide_Tabs* m_EditTabs; VT_ReplaceDlg* m_pReplaceDlg; VT_FindDlg* m_pFindDlg; protected: virtual void draw(); void AddGroupToTree(VTObject *pObj, const char *fmt); - void NewEditWindow(const MString& title, const MString& file); + class Fl_Multi_Edit_Window* NewEditWindow(const MString& title, const MString& file, + int addToRecentFiles = TRUE); Fl_Window* m_ProjWindow; Flu_Tree_Browser* m_ProjTree; Fl_Window* m_TabWindow; Fl_Tabs* m_Tabs; Fl_Group* m_BuildTab; - Fl_Text_Display* m_BuildTextDisp; + My_Text_Display* m_BuildTextDisp; Fl_Text_Buffer* m_BuildTextBuf; Fl_Group* m_DebugTab; Fl_Group* m_WatchTab; @@ -167,6 +189,8 @@ class VT_Ide : public Fl_Window VT_Project* m_ActivePrj; MString m_LastDir; int m_OpenLocation; + StatusBar_t m_StatusBar; + MString m_Search; }; #endif diff --git a/src/idetabs.cpp b/src/idetabs.cpp new file mode 100644 index 0000000..108ab37 --- /dev/null +++ b/src/idetabs.cpp @@ -0,0 +1,429 @@ +/* multiwin.cpp */ + +/* $Id$ */ + +/* + * Copyright 2006 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "VirtualT.h" +#include "m100emu.h" +#include "multiwin_icons.h" +#include "idetabs.h" + +#define BORDER 3 +#define EXTRASPACE 16 +enum {LEFT, RIGHT, SELECTED}; + +IMPLEMENT_DYNCREATE(Fl_Ide_Tabs, VTObject) + +void cb_idetabs(Fl_Widget* w, void *args) +{ + Fl_Ide_Tabs* pTabs; + + // Test for closure event + if (args == (void *) FL_IDE_TABS_CLOSE) + { + // Find the widget being closed and remove it from the group + pTabs = (Fl_Ide_Tabs *) w->parent(); + if (pTabs->children() == 1) + pTabs->hide(); + + pTabs->remove(w); + Fl::delete_widget(w); + if (pTabs->children() != 0) + { + pTabs->parent()->redraw(); + pTabs->redraw(); + int count = pTabs->children(); + for (int c = 0; c < count; c++) + pTabs->resizable(pTabs->child(c)); + } + } +} + +Fl_Ide_Tabs::Fl_Ide_Tabs(int x, int y, int w, int h, const char* title) +: Fl_Tabs(x, y, w, h, title) +{ + m_prevInRect = FALSE; + m_pushInRect = FALSE; + + callback(cb_idetabs); +} + +Fl_Ide_Tabs::~Fl_Ide_Tabs() +{ +} + +/* +=============================================================== +Redraw routine +=============================================================== +*/ +void Fl_Ide_Tabs::draw() { + Fl_Widget *v = value(); + int H = tab_height(); + + if (damage() & FL_DAMAGE_ALL) { // redraw the entire thing: + Fl_Color c = v ? v->color() : color(); + + draw_box(box(), x(), y()+(H>=0?H:0), w(), h()-(H>=0?H:-H), c); + + if (selection_color() != c) { + // Draw the top 5 lines of the tab pane in the selection color so + // that the user knows which tab is selected... + if (H >= 0) fl_push_clip(x(), y() + H, w(), 5); + else fl_push_clip(x(), y() + h() - H - 4, w(), 5); + + draw_box(box(), x(), y()+(H>=0?H:0), w(), h()-(H>=0?H:-H), + selection_color()); + + fl_pop_clip(); + + } + if (v) draw_child(*v); + } else { // redraw the child + if (v) update_child(*v); + } + + // Draw the close box + if (H >= 0) + m_closeRect = VT_Rect(x() + w() - H, 0, H, H); + else + m_closeRect = VT_Rect(x() + w() - H, y() + h() - H, H, H); + + draw_box(box(), x() + w() - H, 0, H, H, + selection_color()); + fl_color(FL_BLACK); + + int rx1 = m_closeRect.x() + 8; + int ry1 = m_closeRect.y(); + int rx2 = m_closeRect.x1() - 8; + int ry2 = m_closeRect.y1(); + fl_line(rx1, ry1 + 7, rx2, ry2 - 9); + fl_line(rx1, ry1 + 8, rx2, ry2 - 8); + fl_line(rx1, ry1 + 9, rx2, ry2 - 7); + fl_line(rx1, ry2 - 7, rx2, ry1 + 9); + fl_line(rx1, ry2 - 8, rx2, ry1 + 8); + fl_line(rx1, ry2 - 9, rx2, ry1 + 7); + + if (damage() & (FL_DAMAGE_SCROLL|FL_DAMAGE_ALL)) { + int p[128]; int wp[128]; + int selected = tab_positions(p,wp); + int i; + Fl_Widget*const* a = array(); + for (i=0; i selected; i--) + draw_tab(x()+p[i], x()+p[i+1], wp[i], H, a[i], RIGHT); + if (v) { + i = selected; + draw_tab(x()+p[i], x()+p[i+1], wp[i], H, a[i], SELECTED); + } + + // Draw the close box + } +} + +/* +=============================================================== +Calculates the position of all tabs based on the children in +the tab group. +=============================================================== +*/ +int Fl_Ide_Tabs::tab_positions(int* p, int* wp) { + int selected = 0; + Fl_Widget*const* a = array(); + int i; + char prev_draw_shortcut = fl_draw_shortcut; + + fl_draw_shortcut = 1; + p[0] = Fl::box_dx(box()); + for (i=0; ivisible()) + selected = i; + + int wt = 0; int ht = 0; + const char *pLabel = o->label(); + o->measure_label(wt,ht); + if (pLabel[strlen(pLabel)-1] != '*') + { + int ah = 0; int aw = 0; + fl_font(o->labelfont(), o->labelsize()); + fl_measure("*", aw, ah); + wt += aw; + } + + wp[i] = wt+EXTRASPACE; + p[i+1] = p[i]+wp[i]+BORDER; + } + fl_draw_shortcut = prev_draw_shortcut; + + int r = w() - m_closeRect.w(); + if (p[i] <= r) return selected; + // uh oh, they are too big: + // pack them against right edge: + p[i] = r; + for (i = children(); i--;) + { + int l = r-wp[i]; + if (p[i+1] < l) + l = p[i+1]; + if (p[i] <= l) + break; + p[i] = l; + r -= EXTRASPACE; + } + // pack them against left edge and truncate width if they still don't fit: + for (i = 0; i= i*EXTRASPACE) + break; + p[i] = i*EXTRASPACE; + int W = w()-1-m_closeRect.w()-EXTRASPACE*(children()-i) - p[i]; + if (wp[i] > W) + wp[i] = W; + } + // adjust edges according to visiblity: + for (i = children(); i > selected; i--) + { + p[i] = p[i-1]+wp[i-1]; + } + return selected; +} + +/* +=============================================================== +return space needed for tabs. Negative to put them on the bottom: +=============================================================== +*/ +int Fl_Ide_Tabs::tab_height() { + int H = h(); + int H2 = y(); + Fl_Widget*const* a = array(); + for (int i=children(); i--;) { + Fl_Widget* o = *a++; + if (o->y() < y()+H) H = o->y()-y(); + if (o->y()+o->h() > H2) H2 = o->y()+o->h(); + } + H2 = y()+h()-H2; + if (H2 > H) return (H2 <= 0) ? 0 : -H2; + else return (H <= 0) ? 0 : H; +} + +/* +=============================================================== +Draws a single tab +=============================================================== +*/ +void Fl_Ide_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) { + int sel = (what == SELECTED); + int dh = Fl::box_dh(box()); + int dy = Fl::box_dy(box()); + char prev_draw_shortcut = fl_draw_shortcut; + fl_draw_shortcut = 1; + + Fl_Boxtype bt = (o==push() &&!sel) ? fl_down(box()) : box(); + + // compute offsets to make selected tab look bigger + int yofs = sel ? 0 : BORDER; + + if ((x2 < x1+W) && what == RIGHT) x1 = x2 - W; + + if (H >= 0) { + if (sel) fl_clip(x1, y(), x2 - x1, H + dh - dy); + else fl_clip(x1, y(), x2 - x1, H); + + H += dh; + +// Fl_Color c = sel ? selection_color() : o->selection_color(); + Fl_Color c = selection_color(); + + draw_box(bt, x1, y() + yofs, W, H + 10 - yofs, c); + + // Save the previous label color + Fl_Color oc = o->labelcolor(); + + // Draw the label using the current color... + if (sel) o->labelfont(o->labelfont() + 1); + o->labeltype(FL_NORMAL_LABEL); + o->labelcolor(sel ? labelcolor() : o->labelcolor()); + o->draw_label(x1, y() + yofs, W, H - yofs, FL_ALIGN_CENTER); + if (sel) o->labelfont(o->labelfont() - 1); + + // Restore the original label color... + o->labelcolor(oc); + + if (Fl::focus() == this && o->visible()) + draw_focus(box(), x1, y(), W, H); + + fl_pop_clip(); + } else { + H = -H; + + if (sel) fl_clip(x1, y() + h() - H - dy, x2 - x1, H + dy); + else fl_clip(x1, y() + h() - H, x2 - x1, H); + + H += dh; + +/// Fl_Color c = sel ? selection_color() : o->selection_color(); + Fl_Color c = selection_color(); + + draw_box(bt, x1, y() + h() - H - 10, W, H + 10 - yofs, c); + + // Save the previous label color + Fl_Color oc = o->color(); + + // Draw the label using the current color... + if (sel) o->labelfont(o->labelfont() + 1); + o->labelcolor(sel ? labelcolor() : o->labelcolor()); + o->draw_label(x1, y() + h() - H, W, H - yofs, FL_ALIGN_CENTER); + if (sel) o->labelfont(o->labelfont() - 1); + + // Restore the original label color... + o->labelcolor(oc); + + if (Fl::focus() == this && o->visible()) + draw_focus(box(), x1, y() + h() - H, W, H); + + fl_pop_clip(); + } + fl_draw_shortcut = prev_draw_shortcut; +} + +/* +=============================================================== +Handle events +=============================================================== +*/ +int Fl_Ide_Tabs::handle(int e) +{ + int drawbox = FALSE; + int ret; + Fl_Widget* w; + + switch (e) + { + case FL_MOVE: + // If the mouse was pressed in the close rect, just exit + if (m_pushInRect) + return 1; + + + // Test if mouse is in our close rect + if (m_closeRect.PointInRect(Fl::event_x(), Fl::event_y())) + { + if (m_prevInRect) + return 0; + + window()->make_current(); + // Draw the activity box + fl_color(FL_BLACK); + drawbox = TRUE; + m_prevInRect = TRUE; + } + else + { + if (!m_prevInRect) + return Fl_Tabs::handle(e); + window()->make_current(); + fl_color(selection_color()); + drawbox = TRUE; + m_prevInRect = FALSE; + } + + if (drawbox) + { + int rx1 = m_closeRect.x() + x(); + int ry1 = m_closeRect.y() + y(); + window()->make_current(); + fl_rect(rx1 + 4, ry1 + 4, m_closeRect.w() - 8, m_closeRect.h() - 8); + } + break; + + case FL_LEAVE: + if (m_prevInRect && !m_pushInRect) + { + fl_color(selection_color()); + m_prevInRect = FALSE; + int rx1 = m_closeRect.x() + x(); + int ry1 = m_closeRect.y() + y(); + fl_rect(rx1 + 4, ry1 + 4, m_closeRect.w() - 8, m_closeRect.h() - 8); + } + break; + + case FL_PUSH: + // If the mouse is in the close rect, indicate a push in rect event + if (m_prevInRect) + { + m_pushInRect = TRUE; + return 1; + } + + w = value(); + ret = Fl_Tabs::handle(e); + if (w != value()) + { + if (w != NULL) + w->hide(); + if (value() != NULL) + value()->show(); + } + + return ret; + + case FL_RELEASE: + // If the mouse was previously pused in the close box, then test for closure + if (m_pushInRect) + { + window()->make_current(); + + // Test if mouse still in rect + if (m_closeRect.PointInRect(Fl::event_x(), Fl::event_y())) + { + value()->do_callback(value(), FL_IDE_TABS_CLOSE); + } + m_pushInRect = FALSE; + } + + break; + } + + return Fl_Tabs::handle(e); +} + diff --git a/src/idetabs.h b/src/idetabs.h new file mode 100644 index 0000000..341969a --- /dev/null +++ b/src/idetabs.h @@ -0,0 +1,59 @@ +/* idetabs.h */ + +/* $Id$ */ + +/* + * Copyright 2009 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _IDETABS_H_ +#define _IDETABS_H_ + +#include +#include "vtobj.h" + +#define FL_IDE_TABS_CLOSE (0xDEADD00D) + +class Fl_Ide_Tabs : public Fl_Tabs, public VTObject +{ +public: + Fl_Ide_Tabs(int x=0, int y=0, int w=600, int h=500, const char *label = 0); + ~Fl_Ide_Tabs(); + + DECLARE_DYNCREATE(Fl_Ide_Tabs) + +protected: + VT_Rect m_closeRect; + int m_prevInRect; + int m_pushInRect; + + virtual int handle(int e); + void draw(void); + int tab_positions(int* p, int* wp); + int tab_height(); + void draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what); +}; + +#endif + diff --git a/src/intelhex.c b/src/intelhex.c index 94ed8bb..dc9d168 100644 --- a/src/intelhex.c +++ b/src/intelhex.c @@ -227,6 +227,23 @@ void save_hex_file(int begin, int end, FILE* fd) hexout(fd, 0, 0, 1); } +/* the command string format is "S begin end filename" where */ +/* "begin" and "end" are the locations to dump to the intel */ +/* hex file, specified in hexidecimal. */ + +void save_hex_file_buf(char *buf, int begin, int end, FILE* fd) +{ + int addr; + + if (begin > end) { + return; + } + for (addr=begin; addr <= end; addr++) + hexout(fd, buf[(unsigned short) addr], addr, 0); + hexout(fd, 0, 0, 1); +} + + /* produce intel hex file output... call this routine with */ /* each byte to output and it's memory location. The file */ diff --git a/src/intelhex.h b/src/intelhex.h index bf15e86..24ff266 100644 --- a/src/intelhex.h +++ b/src/intelhex.h @@ -36,6 +36,6 @@ int load_hex_file(char *filename, char *buffer, unsigned short *start_addr); /* this writes a part of memory[] to an intel hex file */ void save_hex_file(int begin, int end, FILE* fd); void save_hex_file_ext(int begin, int end, int region, FILE* fd); - +void save_hex_file_buf(char *buf, int begin, int end, FILE* fd); #endif diff --git a/src/io.c b/src/io.c index a1a2fe6..e3e85f9 100644 --- a/src/io.c +++ b/src/io.c @@ -49,6 +49,8 @@ uchar lcd[10][256]; uchar lcdpointers[10]={0,0,0,0,0,0,0,0,0,0}; uchar lcddriver=0; uchar lcd_fresh_ptr[10] = {1,1,1,1,1,1,1,1,1,1 }; +uchar io21; /* Real-time milisecond countdown */ +double gPort21Time; /* Starting time for io21 from previous out */ uchar io90; uchar ioA1; uchar ioBA; @@ -60,8 +62,10 @@ uchar ioD0; /* D0-DF io for T200 */ uchar t200_ir; /* Instruction register */ uchar t200_mcr; /* Mode Control Register */ uchar t200_uart_state = 0; +int gInMsPlanROM = FALSE; uchar keyscan[9] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; char keyin[9]; +extern int sound_enable; uint lcdbits=0; unsigned long gSpecialKeys = 0; @@ -71,7 +75,37 @@ int gDelayCount = 0; extern uchar clock_serial_out; extern int gRomBank; extern RomDescription_t *gStdRomDesc; +void handle_wheel_keys(void); +/* +============================================================================= +This routine supplies an OS independant high-resolution timer for use with +emulation speed calculations and throttling. +============================================================================= +*/ +#ifdef _WIN32 +double hirestimer(void) +{ + static LARGE_INTEGER pcount, pcfreq; + static int initflag = 0; + + if (!initflag) + { + QueryPerformanceFrequency(&pcfreq); + initflag++; + } + + QueryPerformanceCounter(&pcount); + return (double)pcount.QuadPart / (double)pcfreq.QuadPart; +} +#else +__inline double hirestimer(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (double)tv.tv_sec + (double)tv.tv_usec / 1000000; +} +#endif void update_keys(void) { @@ -85,6 +119,7 @@ void update_keys(void) buf_index = gStdRomDesc->sKeyscan; + equal = 1; /* Insure keystroke was recgonized by the system */ for (c = 0; c < 9; c++) { @@ -227,7 +262,7 @@ void update_keys(void) gDelayUpdateKeys = 0; gDelayCount = 0; - + handle_wheel_keys(); } void init_io(void) @@ -251,6 +286,8 @@ void init_io(void) /* Setup callback for serial I/O */ ser_set_callback(cb_int65); + io21 = 0; + gPort21Time = 0.0; ioA1 = 0; io90 = 0; ioA1 = 0; @@ -274,7 +311,7 @@ void show_remem_mode(void) char temp[20]; /* Update Display map if output to Mode Port */ - if (gReMem) + if (gReMem && !gRex) { if (inport(REMEM_MODE_PORT) & 0x01) { @@ -297,6 +334,27 @@ void out(uchar port, uchar val) unsigned char flags; switch(port) { + /* + ========================================================== + Extended I/O - Real-time Delay port set value + ========================================================== + */ + case 0x21: /* Delay port */ + io21 = val; + gPort21Time = hirestimer(); + break; + case 0x22: + sound_enable = val; + break; + + /* + ========================================================== + Extended I/O - Debug log + ========================================================== + */ + case 0x23: + break; + case REMEM_MODE_PORT: /* ReMem Mode port */ case REMEM_SECTOR_PORT: /* ReMem Sector access port */ case REMEM_DATA_PORT: /* ReMem Data Port */ @@ -646,6 +704,9 @@ void out(uchar port, uchar val) if ((ioD0 & 0x03) != (val & 0x03)) { set_rom_bank((uchar) (val & 0x03)); + // Test if in MSPLAN rom for mouse events + if ((val & 0x03) == 1) + gInMsPlanROM = 10; } ioD0 = val; @@ -667,7 +728,8 @@ void out(uchar port, uchar val) case 0xEC: case 0xED: case 0xEE: - case 0xEF: + case + 0xEF: /* Bits: 0 - ROM select (0-Standard ROM, 1-Option ROM) @@ -701,19 +763,12 @@ void out(uchar port, uchar val) return; case 0xF0: /* LCD display data bus (F0H-FFH same) */ - case 0xF1: case 0xF2: - case 0xF3: case 0xF4: - case 0xF5: case 0xF6: - case 0xF7: case 0xF8: - case 0xF9: case 0xFA: - case 0xFB: case 0xFC: - case 0xFD: case 0xFE: /* Row select */ if (gModel != MODEL_T200) { @@ -738,6 +793,13 @@ void out(uchar port, uchar val) t200_command(t200_ir, val); } return; + case 0xF1: + case 0xF3: + case 0xF5: + case 0xF7: + case 0xF9: + case 0xFB: + case 0xFD: case 0xFF: /* Data output */ if (gModel != MODEL_T200) { @@ -745,17 +807,22 @@ void out(uchar port, uchar val) { if (lcdbits & (1 << c)) { + int maxPixels = 50; + if ((c == 4) || (c == 9)) + maxPixels = 40; + if ((lcdpointers[c]&0x3f) < 50) { /* Save Byte in LCD memory */ lcd[c][lcdpointers[c]]=A; /* Draw the byte on the display */ - drawbyte(c,lcdpointers[c],A); + if ((lcdpointers[c]&0x3f) < maxPixels) + drawbyte(c,lcdpointers[c],A); /* Update the pointer if */ lcdpointers[c]++; - if ((lcdpointers[c] & 0x3F) >= 50) + if ((lcdpointers[c] & 0x3F) > 50) lcdpointers[c] &= 0xC0; /* We just changed the pointer so it isn't fresh any more */ @@ -781,8 +848,36 @@ int inport(uchar port) int c; unsigned char ret; unsigned char flags; + double timeNow, timeLeft; switch(port) { + + /* Special VirtualT emulation ports */ + case 0x20: + return 'V'; /* Tell host app it's running on VirtualT */ + + case 0x21: /* Real-time timing support */ + /* If the io21 value is zero, then timeing is done */ + if (io21 == 0) + return 0; + + /* Get the timeNow so we can test if time has expired */ + timeNow = hirestimer(); + timeLeft = timeNow - gPort21Time; + + /* Convert timeLeft (in ms) to int */ + c = (char) (timeLeft * 1000.0); + + /* Test if time has expired and clear io21 if it has */ + if (c >= io21) + { + io21 = 0; + return 0; + } + + /* Return number of ms remaining */ + return io21 - c; + case REMEM_SECTOR_PORT: /* ReMem Sector access port */ case REMEM_DATA_PORT: /* ReMem Data Port */ case REMEM_MODE_PORT: /* ReMem Mode port */ diff --git a/src/kc85rom.c b/src/kc85rom.c index 0c85fc4..9ddc90c 100644 --- a/src/kc85rom.c +++ b/src/kc85rom.c @@ -971,6 +971,8 @@ RomDescription_t gKC85_Desc = { 0xFF5A, /* KP Keyscan location */ 0x73BF, /* Character generator table */ 0xF934, /* KP Location of Year storage */ + 0xFE00, /* LCD Buffer Area */ + 0xF644, /* Label line enable flag */ 24, /* Number of directory entries */ 6, /* Index of first Dir entry */ diff --git a/src/linker.cpp b/src/linker.cpp new file mode 100644 index 0000000..3bb5b35 --- /dev/null +++ b/src/linker.cpp @@ -0,0 +1,1501 @@ +/* +======================================================================== +VTLinker: This class implements an 8085 Linker for the + VirtualT project. + +Written: 11/13/09 Kenneth D. Pettit + +======================================================================== +*/ + +#include "VirtualT.h" +#include "linker.h" +#include "elf.h" +#include "project.h" +#include +#include +#include +#include +#include + +extern "C" +{ +#include "intelhex.h" +char path[512]; +} + +static const char *gsEdl = "Error during linking: "; + +/* +============================================================================ +Construtor / destructor for the linker +============================================================================ +*/ +VTLinker::VTLinker() +{ + m_Hex = 0; + m_FileIndex = -1; + m_DebugInfo = 0; +} + +VTLinker::~VTLinker() +{ + ResetContent(); +} + +/* +============================================================================ +Sets the standard output "printf" function to write error messages to +============================================================================ +*/ +void VTLinker::SetStdoutFunction(void *pContext, stdOutFunc_t pFunc) +{ + m_pStdoutFunc = pFunc; + m_pStdoutContext = pContext; +} + +/* +============================================================================ +This routine free's all memory and initializes all variables for a new +link operation. +============================================================================ +*/ +void VTLinker::ResetContent(void) +{ + MString key; + CObjSegment* pSeg; + CLinkRgn* pLinkRgn; + MStringArray* pStrArray; + POSITION pos; + + // Loop through each segment + pos = m_ObjFiles.GetStartPosition(); + while (pos != NULL) + { + // Get the next module + m_ObjFiles.GetNextAssoc(pos, key, (VTObject *&) pSeg); + delete pSeg; + } + m_ObjFiles.RemoveAll(); + + // Loop through all LinkRgn objects and delete them + pos = m_LinkRegions.GetStartPosition(); + while (pos != NULL) + { + m_LinkRegions.GetNextAssoc(pos, key, (VTObject *&) pLinkRgn); + delete pLinkRgn; + } + m_LinkRegions.RemoveAll(); + + // Loop through all Order string arrays and delete them + pos = m_LinkOrderList.GetStartPosition(); + while (pos != NULL) + { + m_LinkOrderList.GetNextAssoc(pos, key, (VTObject *&) pStrArray); + pStrArray->RemoveAll(); + delete pStrArray; + } + m_LinkOrderList.RemoveAll(); + + // Loop through all Order string arrays and delete them + pos = m_LinkContainsList.GetStartPosition(); + while (pos != NULL) + { + m_LinkContainsList.GetNextAssoc(pos, key, (VTObject *&) pStrArray); + pStrArray->RemoveAll(); + delete pStrArray; + } + m_LinkContainsList.RemoveAll(); + + // Loop through all Order string arrays and delete them + pos = m_LinkEndsWithList.GetStartPosition(); + while (pos != NULL) + { + m_LinkEndsWithList.GetNextAssoc(pos, key, (VTObject *&) pStrArray); + pStrArray->RemoveAll(); + delete pStrArray; + } + m_LinkEndsWithList.RemoveAll(); + + // Delete all undefined symbols + m_UndefSymbols.RemoveAll(); + + // Delete all errors + m_Errors.RemoveAll(); + + // Delete filenames parsed + m_LinkFiles.RemoveAll(); + m_FileIndex = -1; + m_ObjDirs.RemoveAll(); + + // Assign active assembly pointers + m_Hex = FALSE; + m_DebugInfo = FALSE; + m_Map = FALSE; +} + +/* +============================================================================ +This function processes the argument list that was passed in +============================================================================ +*/ +void VTLinker::ProcessArgs(MString &str, const char *pDelim) +{ + char* pStr; + char* pTok; + MString optStr; + + pStr = new char[str.GetLength() + 1]; + strcpy(pStr, (const char *) str); + + pTok = strtok(pStr, pDelim); + + while (pTok != NULL) + { + // Ensure this is an option + if (*pTok == '-') + { + // Skip the hyphen + pTok++; + + // Test if map file requested + if (*pTok == 'm') + m_Map = TRUE; + + // Test if map file requested + else if (*pTok == 'g') + m_DebugInfo = TRUE; + + // Test for hex file generation + else if (*pTok == 'h') + m_Hex = TRUE; + + // Test for include library + else if (*pTok == 'l') + { + // Extract the library to includein linking + optStr = pTok + 1; + m_LinkFiles.Add(optStr); + } + + // Test for include lib path + else if (*pTok == 'L') + { + // Extract the library name + optStr = pTok + 1; + m_ObjDirs.Add(optStr); + } + + // Test for output name definition + else if (*pTok == 'o') + { + // Set the output filename + m_OutputName = pTok + 1; + } + + // Test for linker script definition + else if (*pTok == 's') + { + // Set the linker script filename + m_LinkerScript = pTok + 1; + } + } + else + { + // Anything that isn't an option must be an input file + m_LinkFiles.Add(pTok); + } + + // Get pointer to next token + pTok = strtok(NULL, pDelim); + } + + // Free the memory + delete pStr; +} + +/* +============================================================================ +This routine maps the input string which is a command field from the +linker script into a script command number. +============================================================================ +*/ +int VTLinker::MapScriptCommand(const char *pStr, int lineNo) +{ + int command; + MString err; + + command = LKR_CMD_NONE; + + // Test for CODE specification + if (strcmp(pStr, "CODE") == 0) + command = LKR_CMD_CODE; + + // Test for DATA specification + else if (strcmp(pStr, "DATA") == 0) + command = LKR_CMD_DATA; + + // Test for OBJPATH specification + else if (strcmp(pStr, "OBJPATH") == 0) + command = LKR_CMD_OBJPATH; + + // Test for FILES specification + else if (strcmp(pStr, "OBJFILE") == 0) + command = LKR_CMD_OBJFILE; + + // Test for FILES specification + else if (strcmp(pStr, "ORDER") == 0) + command = LKR_CMD_ORDER; + + // Test for FILES specification + else if (strcmp(pStr, "CONTAINS") == 0) + command = LKR_CMD_CONTAINS; + + // Test for FILES specification + else if (strcmp(pStr, "ENDSWITH") == 0) + command = LKR_CMD_ENDSWITH; + + else + { + // Syntax error + err.Format("Error during linking: Parser syntax error on line %d", + lineNo); + m_Errors.Add(err); + } + + return command; +} + +/* +============================================================================ +This routine processes the 2nd field from the current line o the linker +script. It performs operations based on the current m_Command. +============================================================================ +*/ +void VTLinker::ProcScriptField2(const char *pStr, int lineNo, MString &segname) +{ + MString err, temp; + + // Process 1st field of CODE or DATA command + if ((m_Command == LKR_CMD_CODE) || (m_Command == LKR_CMD_DATA)) + { + if (strncmp(pStr, "NAME=", 5) != 0) + { + err.Format("%sExpected segment name on line %d", gsEdl, lineNo); + m_Errors.Add(err); + m_Command = LKR_CMD_ERROR; + } + else + { + // Skip the NAME= keyword + segname = pStr + 5; + } + } + + // Test if command is FILES and process filename + else if (m_Command == LKR_CMD_OBJFILE) + { + m_LinkFiles.Add(pStr); + m_Command = LKR_CMD_COMPLETE; + } + + // Test if command is OBJPATH and add path to array + else if (m_Command == LKR_CMD_OBJPATH) + { + temp = PreprocessDirectory(pStr); + m_ObjDirs.Add(temp); + m_Command = LKR_CMD_COMPLETE; + } + + // Test if command is LKR_CMD_ORDER and save segment name + else if ((m_Command == LKR_CMD_ORDER) || (m_Command == LKR_CMD_CONTAINS) || + (m_Command == LKR_CMD_ENDSWITH)) + { + segname = pStr; + } +} + +/* +============================================================================ +This routine evaluates the string provided and returns it's value. The +string can be decimal, hex, etc. and can contain simple math. +============================================================================ +*/ +int VTLinker::EvaluateScriptAddress(const char *pStr, int lineNo) +{ + int len = strlen(pStr); + int hex = 0; + int address; + + // Test for Hex conversion + if (*pStr == '$') + { + hex = 1; // Indicate HEX conversion + pStr++; // Skip the '$' hex delimiter + } + else if ((*pStr == '0') && (*(pStr + 1) == 'x')) + { + hex = 1; + pStr += 2; // Skip the "0x" hex delimiter + } + else if ((pStr[len-1] == 'h') || (pStr[len-1] == 'H')) + { + hex = 1; + } + + // Perform the conversion + if (hex) + sscanf(pStr, "%x", &address); + else + sscanf(pStr, "%d", &address); + + return address; +} + +/* +============================================================================ +This routine processes the 2nd field from the current line o the linker +script. It performs operations based on the current m_Command. +============================================================================ +*/ +void VTLinker::ProcScriptField3(const char *pStr, int lineNo, int& startAddr) +{ + MString err; + + // Initialize startAddr in case error or ORDER command + startAddr = -1; + + // Test if CODE or DATA command + if ((m_Command == LKR_CMD_CODE) || (m_Command == LKR_CMD_DATA)) + { + if (strncmp(pStr, "START=", 6) == 0) + { + // Evaluate the starting address + if (strcmp(pStr + 6, "codeend") == 0) + startAddr = START_ADDR_CODEEND; + else + startAddr = EvaluateScriptAddress(pStr + 6, lineNo); + } + else + { + err.Format("%sExpected START address in linker script on line %d", + gsEdl, lineNo); + m_Errors.Add(err); + m_Command = LKR_CMD_ERROR; + } + } + + // Test if ORDER, CONTAINS or ENDSWITH command + else if ((m_Command == LKR_CMD_ORDER) || (m_Command == LKR_CMD_CONTAINS) || + (m_Command == LKR_CMD_ENDSWITH)) + { + if (strcmp(pStr, "{") != 0) + { + err.Format("%sExpected open brace in linker script on line %d", + gsEdl, lineNo); + m_Errors.Add(err); + m_Command = LKR_CMD_ERROR; + } + else + { + m_ActiveLinkOrder = new MStringArray; + } + } + + // Other commands don't have more than 2 fields + else + { + err.Format("%sTo many linker script arguments in line %d", gsEdl, lineNo); + m_Errors.Add(err); + m_Command = LKR_CMD_ERROR; + } +} + +/* +============================================================================ +This routine processes the 2nd field from the current line o the linker +script. It performs operations based on the current m_Command. +============================================================================ +*/ +void VTLinker::ProcScriptField4(const char *pStr, int lineNo, int& endAddr) +{ + MString err; + + // Initialize startAddr in case error or ORDER command + endAddr = -1; + + // Test if CODE or DATA command + if ((m_Command == LKR_CMD_CODE) || (m_Command == LKR_CMD_DATA)) + { + if (strncmp(pStr, "END=", 4) == 0) + { + endAddr = EvaluateScriptAddress(pStr + 4, lineNo); + m_Command |= LKR_CMD_CD_DONE; + } + else + { + err.Format("%sExpected END address in linker script on line %d", + gsEdl, lineNo); + m_Errors.Add(err); + m_Command = LKR_CMD_ERROR; + } + } + + // Test if ORDER command + else if (m_Command == LKR_CMD_ORDER) + AddOrderedSegment(pStr, lineNo); + else if (m_Command == LKR_CMD_CONTAINS) + AddContainsSegment(pStr, lineNo); + else if (m_Command == LKR_CMD_ENDSWITH) + AddEndsWithSegment(pStr, lineNo); +} + +/* +============================================================================ +This routine adds the specified label as an ordered label for the acive +LinkOrder. It checks to see if the label is the terminating brace and +completes the LinkOrder processing. +============================================================================ +*/ +void VTLinker::AddOrderedSegment(const char *pStr, int lineNo) +{ + MStringArray *pOrder; + MString err; + + // Test for terminating brace + if (strcmp(pStr, "}") == 0) + { + // Test if this segment has already been defined as ordered + if (m_LinkOrderList.Lookup(m_SegName, (VTObject *&) pOrder)) + { + err.Format("%sOrder already specified for %s on line %d", + gsEdl, (const char *) m_SegName, lineNo); + m_Errors.Add(err); + delete m_ActiveLinkOrder; + m_ActiveLinkOrder = NULL; + return; + } + m_LinkOrderList[m_SegName] = (VTObject *) m_ActiveLinkOrder; + m_ActiveLinkOrder = NULL; + m_Command = LKR_CMD_COMPLETE; + } + else + { + if (m_ActiveLinkOrder != NULL) + m_ActiveLinkOrder->Add(pStr); + } +} + +/* +============================================================================ +This routine adds the specified label as an ordered label for the acive +LinkOrder. It checks to see if the label is the terminating brace and +completes the LinkOrder processing. +============================================================================ +*/ +void VTLinker::AddContainsSegment(const char *pStr, int lineNo) +{ + MStringArray *pOrder; + MString err; + + // Test for terminating brace + if (strcmp(pStr, "}") == 0) + { + // Test if this segment has already been defined as ordered + if (m_LinkContainsList.Lookup(m_SegName, (VTObject *&) pOrder)) + { + err.Format("%sContainment already specified for %s on line %d", + gsEdl, (const char *) m_SegName, lineNo); + m_Errors.Add(err); + delete m_ActiveLinkOrder; + m_ActiveLinkOrder = NULL; + return; + } + m_LinkContainsList[m_SegName] = (VTObject *) m_ActiveLinkOrder; + m_ActiveLinkOrder = NULL; + m_Command = LKR_CMD_COMPLETE; + } + else + { + if (m_ActiveLinkOrder != NULL) + m_ActiveLinkOrder->Add(pStr); + } +} + +/* +============================================================================ +This routine adds the specified label as an ordered label for the acive +LinkOrder. It checks to see if the label is the terminating brace and +completes the LinkOrder processing. +============================================================================ +*/ +void VTLinker::AddEndsWithSegment(const char *pStr, int lineNo) +{ + MStringArray *pOrder; + MString err; + + // Test for terminating brace + if (strcmp(pStr, "}") == 0) + { + // Test if this segment has already been defined as ordered + if (m_LinkEndsWithList.Lookup(m_SegName, (VTObject *&) pOrder)) + { + err.Format("%sENDSWITH already specified for %s on line %d", + gsEdl, (const char *) m_SegName, lineNo); + m_Errors.Add(err); + delete m_ActiveLinkOrder; + m_ActiveLinkOrder = NULL; + return; + } + m_LinkEndsWithList[m_SegName] = (VTObject *) m_ActiveLinkOrder; + m_ActiveLinkOrder = NULL; + m_Command = LKR_CMD_COMPLETE; + } + else + { + if (m_ActiveLinkOrder != NULL) + m_ActiveLinkOrder->Add(pStr); + } +} + +/* +============================================================================ +This routine processes the 2nd field from the current line o the linker +script. It performs operations based on the current m_Command. +============================================================================ +*/ +void VTLinker::ProcScriptField5(const char *pStr, int lineNo, int& prot) +{ + MString err; + + // Initialize startAddr in case error or ORDER command + prot = FALSE; + + // Test if CODE or DATA command with PROTECTED option + if (m_Command & LKR_CMD_CD_DONE) + { + if (strcmp(pStr, "PROTECTED") == 0) + { + prot = TRUE; + } + else + { + err.Format("%sExpected argument in linker script on line %d", + gsEdl, lineNo); + m_Errors.Add(err); + m_Command = LKR_CMD_ERROR; + } + } + + // Test if ORDER command + else if (m_Command == LKR_CMD_ORDER) + AddOrderedSegment(pStr, lineNo); + else if (m_Command == LKR_CMD_CONTAINS) + AddContainsSegment(pStr, lineNo); + else if (m_Command == LKR_CMD_ENDSWITH) + AddEndsWithSegment(pStr, lineNo); +} + +/* +============================================================================ +This routine adds a new link region processed from the linker script. It +adds the region to the m_SegName segment and checks for overlapping +address definitions. +============================================================================ +*/ +void VTLinker::NewLinkRegion(int type, int lineNo, int startAddr, + int endAddr, int prot) +{ + MString err, key; + CLinkRgn *pLinkRgn; + LinkAddrRange* pAddrRange; + LinkAddrRange* pPrevRange; + LinkAddrRange* pThisRange; + POSITION pos; + + // Validate this region hasn't already been defined (no overlapping regions) + pos = m_LinkRegions.GetStartPosition(); + while (pos != NULL) + { + m_LinkRegions.GetNextAssoc(pos, key, (VTObject *&) pLinkRgn); + pThisRange = pLinkRgn->m_pFirstAddrRange; + while (pThisRange != NULL) + { + // Test if this region overlaps with new region + if ((startAddr >= pThisRange->startAddr) && ( + (startAddr <= pThisRange->endAddr)) || + ((endAddr >= pThisRange->startAddr) && + (endAddr <= pThisRange->endAddr)) || + ((startAddr <= pThisRange->startAddr) && + (endAddr >= pThisRange->endAddr)) && + (startAddr != START_ADDR_CODEEND)) + { + err.Format("%sLinker script address ranges cannot overlap at line %d", + gsEdl, lineNo); + m_Errors.Add(err); + m_Command = LKR_CMD_ERROR; + return; + } + + pThisRange = pThisRange->pNext; + } + } + + // Test if this link region already defined + if (m_LinkRegions.Lookup((const char *) m_SegName, (VTObject *&) pLinkRgn)) + { + // Ensure the type and protected bits are the same + if (prot != pLinkRgn->m_Protected) + { + err.Format("%sLinker script region protection doesn't match previous definition on line %d", + gsEdl, lineNo); + m_Errors.Add(err); + m_Command = LKR_CMD_ERROR; + return; + } + + if (m_Command != pLinkRgn->m_Type) + { + err.Format("%sLinker script region type doesn't match previous definition on line %d", + gsEdl, lineNo); + m_Errors.Add(err); + m_Command = LKR_CMD_ERROR; + return; + } + } + else + pLinkRgn = NULL; + + // Create a new link region + if (pLinkRgn == NULL) + { + pLinkRgn = new CLinkRgn(m_Command, m_SegName, startAddr, endAddr, prot); + m_LinkRegions[(const char *) m_SegName] = pLinkRgn; + } + else + { + // Add a new region to the existing object + pAddrRange = new LinkAddrRange; + pAddrRange->startAddr = startAddr; + pAddrRange->endAddr = endAddr; + pAddrRange->pNext = NULL; + + // Insert this address range into the list + pPrevRange = NULL; + pThisRange = pLinkRgn->m_pFirstAddrRange; + while ((pThisRange != NULL) && (pAddrRange->startAddr < + pThisRange->startAddr)) + { + pPrevRange = pThisRange; + pThisRange = pThisRange->pNext; + } + + // Test if new region should be inserted at beginning or in middle + if (pThisRange == pLinkRgn->m_pFirstAddrRange) + { + pAddrRange->pNext = pThisRange; + pLinkRgn->m_pFirstAddrRange = pAddrRange; + } + else + { + pAddrRange->pNext = pThisRange; + pPrevRange->pNext = pAddrRange; + } + } + m_Command = LKR_CMD_COMPLETE; +} + +/* +============================================================================ +This routine attempts to open and parse the linker script to be used during +the link operation. If the file cannot be opened or contains an erro, the +routine returns FALSE, otherwise it configures internal structures and +returns TRUE. +============================================================================ +*/ +int VTLinker::ReadLinkerScript() +{ + MString filePath, err, orderSeg, segname; + int lineNo; + FILE *fd; + char lineBuf[256]; + char *pRead, *pTok; + int field, startAddr, endAddr, prot; + + // Test if linker script was supplied + if (m_LinkerScript.GetLength() == 0) + { + err.Format("%sNo linker script specified", gsEdl); + m_Errors.Add(err); + return FALSE; + } + + // Attpempt to open the file with no special path extension + fd = fopen((const char *) m_LinkerScript, "rb"); + + // If linker script file not found in current directory, search in the + // project root path + if (fd == NULL) + { + filePath = m_RootPath + (char *) "/" + m_LinkerScript; + fd = fopen((const char *) filePath, "rb"); + } + + // Test for error opening linker script file + if (fd == NULL) + { + err.Format("%sUnable to locate linker script file %s", gsEdl, + (const char *) m_LinkerScript); + m_Errors.Add(err); + return FALSE; + } + + // The linker script file is open. Read lines and process each + // Read lines from the input file and locate them + m_Command = LKR_CMD_NONE; + lineNo = 0; + field = 0; + prot = 0; + while (TRUE) + { + // Read the line from the file + pRead = fgets(lineBuf, sizeof(lineBuf), fd); + if (pRead == NULL) + { + break; + } + lineNo++; + + // Test for comment line + if (lineBuf[0] == ';') + continue; + + // Separate the line into tokens + pTok = strtok(lineBuf, " ,\t\n\r"); + if ((m_Command == LKR_CMD_ERROR) || (m_Command == LKR_CMD_COMPLETE)) + { + field = 0; + m_Command = LKR_CMD_NONE; + startAddr = endAddr = prot = 0; + } + + // Loop for all fields on the line + while (pTok != NULL) + { + // Test for comment in the line + if (*pTok == ';') + { + // Comment only allowd on line if all args processed + if ((m_Command != LKR_CMD_NONE) && (m_Command != LKR_CMD_COMPLETE) && + !(m_Command & LKR_CMD_CD_DONE)) + { + err.Format("%sIncomplete linker script command on line %d", + gsEdl, lineNo); + m_Errors.Add(err); + } + break; + } + + // Parse based on field number + switch (field) + { + case 0: + m_Command = MapScriptCommand(pTok, lineNo); + break; + + case 1: + ProcScriptField2(pTok, lineNo, segname); + m_SegName = segname; + break; + + case 2: + ProcScriptField3(pTok, lineNo, startAddr); + break; + + case 3: + ProcScriptField4(pTok, lineNo, endAddr); + break; + + case 4: + ProcScriptField5(pTok, lineNo, prot); + break; + + default: + // Keep processing arguments to the ORDER command + if (m_Command == LKR_CMD_ORDER) + AddOrderedSegment(pTok, lineNo); + else if (m_Command == LKR_CMD_CONTAINS) + AddContainsSegment(pTok, lineNo); + else if (m_Command == LKR_CMD_ENDSWITH) + AddEndsWithSegment(pTok, lineNo); + break; + } + + // Increment the field number + field++; + if ((m_Command == LKR_CMD_NONE) || (m_Command == LKR_CMD_ERROR)) + break; + pTok = strtok(NULL, " ,\t\n\r"); + } + + // If this was a DATA or CODE command that completed, process the + // information + if (m_Command & LKR_CMD_CD_DONE) + { + // Clear the CMD_CD_DONE bit + m_Command &= ~LKR_CMD_CD_DONE; + NewLinkRegion(m_Command, lineNo, startAddr, endAddr, prot); + } + } + + // Close the linker script file + fclose(fd); + + // Check for errors during processing + if (m_Errors.GetSize() != 0) + return FALSE; + + return TRUE; +} + +/* +============================================================================ +This routine reads the ELF header data from the opened file given. +============================================================================ +*/ +int VTLinker::ReadElfHeaders(FILE* fd, MString& filename) +{ + Elf32_Ehdr ehdr; + CObjFileSection* pFileSection; + CObjFile* pObjFile; + int bytes, c; + MString err; + + // Write ELF header to file + bytes = fread(&ehdr, 1, sizeof(ehdr), fd); + if ((bytes != sizeof(ehdr)) || (ehdr.e_ident[EI_MAG0] != ELFMAG0) || + (ehdr.e_ident[EI_MAG1] != ELFMAG1) || (ehdr.e_ident[EI_MAG2] != ELFMAG2) || + (ehdr.e_ident[EI_MAG3] != ELFMAG3)) + { + fclose(fd); + err.Format("Error during linking: Object file %s is not ELF format", + (const char *) filename); + m_Errors.Add(err); + return FALSE; + } + + // Ensure the ELF file is the right type + if ((ehdr.e_ident[EI_CLASS] != ELFCLASS32) || (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) || + (ehdr.e_ident[EI_VERSION] < EV_CURRENT) || (ehdr.e_type != ET_REL) || + (ehdr.e_machine != EM_8085) || (ehdr.e_version < EV_CURRENT) || + (ehdr.e_shoff == 0)) + { + fclose(fd); + err.Format("%sObject file %s has invalid ELF format", gsEdl, + (const char *) filename); + m_Errors.Add(err); + return FALSE; + } + + // Read all the section headers from the header table + if (fseek(fd, ehdr.e_shoff, SEEK_SET)) + { + fclose(fd); + err.Format("%sObject file %s has invalid ELF format", gsEdl, + (const char *) filename); + m_Errors.Add(err); + return FALSE; + } + + // Okay, now create a new CObjFile object for this file + pObjFile = new CObjFile(filename); + if (pObjFile == NULL) + { + fclose(fd); + err.Format("%sunable to allocate memory for section header", gsEdl); + m_Errors.Add(err); + return FALSE; + } + memcpy(&pObjFile->m_Ehdr, &ehdr, sizeof(ehdr)); + + // Loop for all reported headers + for (c = 0; c < ehdr.e_shnum; c++) + { + // Allocate a new section header structure + if ((pFileSection = new CObjFileSection) == NULL) + { + fclose(fd); + delete pObjFile; + err.Format("%sUnable to allocate memory for section header", gsEdl); + m_Errors.Add(err); + return FALSE; + } + if (fread(&pFileSection->m_ElfHeader, 1, sizeof(Elf32_Shdr), fd) != + sizeof(Elf32_Shdr)) + { + fclose(fd); + delete pObjFile; + err.Format("%sEnd of file reading section header %d from %s", + gsEdl, c, (const char *) filename); + m_Errors.Add(err); + return FALSE; + } + + // Add this section header to the array + pObjFile->m_FileSections.Add(pFileSection); + } + + // Loop for all reported headers + for (c = 0; c < ehdr.e_shnum; c++) + { + // Now read this section's data + if (!ReadSectionData(fd, pObjFile, (CObjFileSection *) pObjFile->m_FileSections[c])) + { + fclose(fd); + delete pObjFile; + return FALSE; + } + } + + return TRUE; +} + +/* +============================================================================ +This routine reads the ELF section specified by the Elf32_Shdr into the +CObjFile object provided. +============================================================================ +*/ +int VTLinker::ReadSectionData(FILE* fd, CObjFile* pObjFile, + CObjFileSection* pFileSection) +{ + int bytes = 0, count, c; + MString err; + Elf32_Shdr* pHdr = &pFileSection->m_ElfHeader; + Elf32_Sym* pSym; + Elf32_Rel* pRel; + + + if (pHdr->sh_offset != 0) + fseek(fd, pHdr->sh_offset, SEEK_SET); + + // Test for null header + switch (pHdr->sh_type) + { + case SHT_NULL: + // Nothing to do for NULL header + return TRUE; + + // String table section + case SHT_STRTAB: + // Allocate space for the string table + pFileSection->m_pStrTab = new char[pHdr->sh_size]; + + // Read the string table from the file + if (pFileSection->m_pStrTab != NULL) + bytes = fread(pFileSection->m_pStrTab, 1, pHdr->sh_size, fd); + + // Test for error + if (bytes != pHdr->sh_size) + { + err.Format("%sUnable to allocate memory for string table for %s", + gsEdl, (const char *) pObjFile->m_Name); + m_Errors.Add(err); + return FALSE; + } + break; + + case SHT_SYMTAB: + count = pHdr->sh_size / sizeof(Elf32_Sym); + for (c = 0; c < count; c++) + { + // Allocate new symbol and rezd data from the file + pSym = new Elf32_Sym; + if (pSym != NULL) + bytes = fread(pSym, 1, sizeof(Elf32_Sym), fd); + + // Test for error during read or allocate + if (bytes != sizeof(Elf32_Sym)) + { + err.Format("%sUnable to read symbol table for %s", + gsEdl, (const char *) pObjFile->m_Name); + m_Errors.Add(err); + if (pSym != NULL) + delete pSym; + return FALSE; + } + + // Add the symbol to the array + pFileSection->m_Symbols.Add((VTObject *) pSym); + } + break; + + case SHT_PROGBITS: + // Allocate space for bytes and read from file + pFileSection->m_pProgBytes = new char[pHdr->sh_size]; + if (pFileSection->m_pProgBytes != NULL) + bytes = fread(pFileSection->m_pProgBytes, 1, pHdr->sh_size, fd); + + // Test for error during read + if (bytes != pHdr->sh_size) + { + err.Format("%sUnable to segment data for %s", + gsEdl, (const char *) pObjFile->m_Name); + m_Errors.Add(err); + return FALSE; + } + break; + + case SHT_REL: + count = pHdr->sh_size / sizeof(Elf32_Rel); + for (c = 0; c < count; c++) + { + // Allocate new symbol and read data from the file + pRel = new Elf32_Rel; + if (pRel != NULL) + bytes = fread(pRel, 1, sizeof(Elf32_Rel), fd); + + // Test for error during read or allocate + if (bytes != sizeof(Elf32_Rel)) + { + err.Format("%sUnable to read relocation table for %s", + gsEdl, (const char *) pObjFile->m_Name); + m_Errors.Add(err); + if (pRel != NULL) + delete pRel; + return FALSE; + } + + // Add the symbol to the array + pFileSection->m_Reloc.Add((VTObject *) pRel); + } + break; + } + + return TRUE; +} + +/* +============================================================================ +This routine attempts to open and read each of the files to be linked. +During reading, the routine builds control structures based on the contents +of the OBJ file to be used during the link operation, such as symbol and +segment names, relocation objects, etc. +============================================================================ +*/ +int VTLinker::ReadObjFiles() +{ + int count, c; + int dirs, x; + FILE* fd; + const char *pFile; + MString temp, err; + + // Exit if eror has occurred + if (m_Errors.GetSize() != 0) + return FALSE; + + count = m_LinkFiles.GetSize(); + for (c = 0; c < count; c++) + { + // Read each file and create a lists of segments, publics, externs + // and reloc objects + pFile = (const char *) m_LinkFiles[c]; + + // First try to open the file with none of the known directory prefixes + temp = pFile; + fd = fopen(pFile, "rb"); + if (fd == NULL) + { + // Loop through all known library directory prefixes + dirs = m_ObjDirs.GetSize(); + for (x = 0; x < dirs; x++) + { + // Prepend the next object directory + temp = m_ObjDirs[c] + pFile; + fd = fopen((const char *) temp, "rb"); + if (fd != NULL) + break; + } + } + + // Test if file could be opened + if (fd == NULL) + { + err.Format("%sUnable to locate object file %s", gsEdl, pFile); + m_Errors.Add(err); + continue; + } + + // Read the Elf data + ReadElfHeaders(fd, temp); + } + + if (m_Errors.GetSize() != 0) + return FALSE; + + return TRUE; +} + +/* +============================================================================ +This function locates segments from the input files as per the linker script +regions that have been defined. +============================================================================ +*/ +int VTLinker::LocateSegments() +{ + POSITION pos; +// CObjSegement* pSeg; + CObjFile* pObjFile; + CObjFileSection* pFileSect; + int sect, sectCount; + MString err, filename; + + // Loop for all object files loaded + pos = m_ObjFiles.GetStartPosition(); + while (pos != NULL) + { + // Get pointer to this object file's data + m_ObjFiles.GetNextAssoc(pos, filename, (VTObject *&) pObjFile); + + // Loop through all segments and find a place to locate them + sectCount = pObjFile->m_FileSections.GetSize(); + for (sect = 0; sect < sectCount; sect++) + { + // Get pointer to next file section for this file + pFileSect = (CObjFileSection *) pObjFile->m_FileSections[sect]; + + // Test if file section is a segment + if ((pFileSect->m_ElfHeader.sh_type != SHT_PROGBITS) && + (pFileSect->m_ElfHeader.sh_type != SHT_NOBITS)) + { + continue; + } + + // Test if segment is ASEG + if ((pFileSect->m_ElfHeader.sh_flags & SHF_8085_ABSOLUTE) && + (pFileSect->m_ElfHeader.sh_type == SHT_PROGBITS)) + { + LocateAsegSegment(pFileSect); + } + + // Test if segment is CSEG + else if ((pFileSect->m_ElfHeader.sh_flags & (SHF_ALLOC | SHF_EXECINSTR | + SHF_WRITE)) == (SHF_ALLOC | SHF_EXECINSTR)) + { + LocateCsegSegment(pFileSect); + } + + // Test if segment is DSEG + else if ((pFileSect->m_ElfHeader.sh_flags & (SHF_ALLOC | SHF_EXECINSTR | + SHF_WRITE)) == SHF_WRITE) + { + LocateDsegSegment(pFileSect); + } + + // Unknown segment type + else + { + // Report error of unknown segment type + err.Format("%sUnknown segment type in %s", gsEdl, (const char *) filename); + m_Errors.Add(err); + } + } + } + + return TRUE; +} + +/* +============================================================================ +Tries to locate the given ASEG segment +============================================================================ +*/ +int VTLinker::LocateAsegSegment(CObjFileSection* pFileSect) +{ + return TRUE; +} + +/* +============================================================================ +Tries to locate the given CSEG segment +============================================================================ +*/ +int VTLinker::LocateCsegSegment(CObjFileSection* pFileSect) +{ + return TRUE; +} + +/* +============================================================================ +Tries to locate the given DSEG segment +============================================================================ +*/ +int VTLinker::LocateDsegSegment(CObjFileSection* pFileSect) +{ + return TRUE; +} + +/* +============================================================================ +The parser calls this function when it detects a list output pragma. +============================================================================ +*/ +int VTLinker::Link() +{ + // Process any input arguments + ProcessArgs(m_LinkOptions, " "); + + // Calculate any additional directories from the IDE + CalcObjDirs(); + + // Process the input filename list from the IDE + ProcessArgs(m_ObjFileList, ",;"); + + // Read the linker script + ReadLinkerScript(); + + // Loop through all files to be linked + ReadObjFiles(); + + // Locate segments based on commands in the Linker Script + LocateSegments(); + + // Resolve static (local) symbols for each segment + + // Resolve segment extern symbols + + // Test for unresolved symbols + + // Generate output file + + // Generate debug information + + // Generate hex file + + // Generate map file + + // Back annotate Listing files with actual addresses + + return m_Errors.GetSize() == 0; +} + +/* +============================================================================ +Set's the linker options. Called from either the IDE or command line mode. +============================================================================ +*/ +void VTLinker::SetLinkOptions(const MString& options) +{ + // Set the options string in case we need it later + m_LinkOptions = options; + + // Parse the options later during assembly +} + +/* +============================================================================ +Set's the linker script when running from the IDE. +============================================================================ +*/ +void VTLinker::SetLinkerScript(const MString& script) +{ + // Set the linker script filename for processing later + m_LinkerScript = script; + + // Parse the options later during assembly +} + +/* +============================================================================ +Sets a comma delimeted list of object directories when running from the IDE +============================================================================ +*/ +void VTLinker::SetObjDirs(const MString& dirs) +{ + // Save the string in case we need it later + m_ObjPath = dirs; + + // Recalculate the include directories + CalcObjDirs(); +} + +/* +============================================================================ +Sets the root project path +============================================================================ +*/ +void VTLinker::SetRootPath(const MString& path) +{ + // Save the string in case we need it later + m_RootPath = path; + + // Recalculate the include directories + CalcObjDirs(); +} + +/* +============================================================================ +Sets the root project path +============================================================================ +*/ +void VTLinker::SetObjFiles(const MString& objFiles) +{ + // Save the string in case we need it later + m_ObjFileList = objFiles; +} + +/* +============================================================================ +Sets the root project path +============================================================================ +*/ +void VTLinker::SetProjectType(int type) +{ + // Save the project type + m_ProjectType = type; +} + +/* +============================================================================ +Parses the comma delimeted object filename list and splits it into an array +of filenames to be linked. +============================================================================ +*/ +void VTLinker::CalcObjDirs(void) +{ + char* pStr; + char* pToken; + MString temp; + + m_ObjDirs.RemoveAll(); + + // Add the root directory to the ObjDirs + m_ObjDirs.Add(m_RootPath); + + // Check if there is an include path + if (m_ObjPath.GetLength() == 0) + return; + + // Copy path to a char array so we can tokenize + pStr = new char[m_ObjPath.GetLength() + 1]; + strcpy(pStr, (const char *) m_ObjPath); + + pToken = strtok(pStr, ",;"); + while (pToken != NULL) + { + // Preprocess the directory by searching for $VT_ROOT and $VT_PROJ + temp = PreprocessDirectory(pToken); + + // Now add it to the array + m_ObjDirs.Add(temp); + + // Get next token + pToken = strtok(NULL, ",;"); + } + + delete pStr; +} + +/* +============================================================================ +Parses the provided directory name and substitutes {$VT_ROOT} and {$VT_PROJ} +with actual path's. Returns the resultant string. +============================================================================ +*/ +MString VTLinker::PreprocessDirectory(const char *pDir) +{ + MString temp; + + if (strncmp(pDir, "{$VT_ROOT}", 10) == 0) + { + // Substitute the VirtualT path + temp = path; + temp += pDir[10]; + } + else if (strncmp(pDir, "{$VT_PROJ}", 10) == 0) + { + // Generate a projet relative path + temp = pDir[10]; + temp.Trim(); + temp += (char *) "/"; + temp = m_RootPath + (char *) "/" + temp; + } + else + temp = pDir; + + return temp; +} + +/* +============================================================================ +Constructor for the CLinkRgn object. This object is used to keep track of +regions defined in the linker script. +============================================================================ +*/ +CLinkRgn::CLinkRgn(int type, MString& name, int startAddr, int endAddr, int prot) +{ + m_Type = type; + m_Name = name; + m_Protected = prot; + m_pFirstAddrRange = new LinkAddrRange; + m_pFirstAddrRange->startAddr = startAddr; + m_pFirstAddrRange->endAddr = endAddr; + m_pFirstAddrRange->pNext = NULL; +} + +CLinkRgn::~CLinkRgn() +{ + LinkAddrRange *pRange; + LinkAddrRange *pNextRange; + + pRange = m_pFirstAddrRange; + while (pRange != NULL) + { + pNextRange = pRange->pNext; + delete pRange; + pRange = pNextRange; + } +} + +CObjFile::~CObjFile() +{ + int count, c; + + count = m_FileSections.GetSize(); + for (c = 0; c < count; c++) + { + delete (CObjFileSection *) m_FileSections[c]; + } + m_FileSections.RemoveAll(); +} + +CObjFileSection::~CObjFileSection() +{ + int count, c; + + if (m_pStrTab != NULL) + delete m_pStrTab; + + if (m_pObjSegment != NULL) + delete m_pObjSegment; + + count = m_Symbols.GetSize(); + for (c = 0; c < count; c++) + { + delete (Elf32_Sym *) m_Symbols[c]; + } + m_Symbols.RemoveAll(); + + count = m_Reloc.GetSize(); + for (c = 0; c < count; c++) + { + delete (Elf32_Rel *) m_Reloc[c]; + } + m_Symbols.RemoveAll(); + + // Delete program bytes pointer if not NULL + if (m_pProgBytes != NULL) + delete m_pProgBytes; +} diff --git a/src/linker.h b/src/linker.h new file mode 100644 index 0000000..71e091c --- /dev/null +++ b/src/linker.h @@ -0,0 +1,237 @@ +#ifndef _VTLinkerer_ +#define _VTLinkerer_ + +#include "vtobj.h" +#include "rpn_eqn.h" +#include "elf.h" +#include + +#define SYM_LABEL 1 +#define SYM_EQUATE 2 +#define SYM_SET 3 +#define SYM_EXTERN 4 +#define SYM_DEFINE 5 +#define SYM_CSEG 0x0100 +#define SYM_DSEG 0x0200 +#define SYM_8BIT 0x0400 +#define SYM_16BIT 0x0800 +#define SYM_PUBLIC 0x1000 +#define SYM_ISREG 0x2000 +#define SYM_ISEQ 0x4000 +#define SYM_HASVALUE 0x8000 + +#define LKR_CMD_NONE 0 +#define LKR_CMD_CODE 1 +#define LKR_CMD_DATA 2 +#define LKR_CMD_OBJPATH 3 +#define LKR_CMD_OBJFILE 4 +#define LKR_CMD_ORDER 5 +#define LKR_CMD_CONTAINS 6 +#define LKR_CMD_ENDSWITH 7 +#define LKR_CMD_CD_DONE 0x80 +#define LKR_CMD_ERROR 98 +#define LKR_CMD_COMPLETE 99 + +#define START_ADDR_CODEEND -2 + +#define PAGE 1 +#define INPAGE 2 + +#define ASEG 0 +#define CSEG 1 +#define DSEG 2 + +#define VT_ISDIGIT(x) (((x) >= '0') && ((x) <= '9')) + +#ifdef WIN32 +#define LINE_ENDING "\r\n" +#else +#define LINE_ENDING "\n" +#endif +// Support classes for VTAssembler objects... + +typedef struct sLinkAddrRange { + int startAddr; + int endAddr; + struct sLinkAddrRange* pNext; +} LinkAddrRange; + +class CObjSegment : public VTObject +{ +public: + CObjSegment(const char *name, int type); + ~CObjSegment(); + + MString m_Name; // Name of segment + int m_Type; // ASEG, CSEG or DSEG type + int m_Page; + int m_Index; // Current index for listing + int m_Count; // Instruction count for listing + int m_sh_offset; // Offset in .obj file of segment name + unsigned short m_Address; // Address counter for each segment + VTObArray m_Reloc; +}; + +class CObjExtern : public VTObject +{ +public: + CObjExtern() { m_Address = 0; }; + + MString m_Name; + unsigned short m_Address; + unsigned short m_Segment; + unsigned short m_SymIdx; + unsigned char m_Size; +}; + +class CObjRelocation : public VTObject +{ +public: + CObjRelocation() { m_Address = 0; m_Segment = 0;}; + + unsigned short m_Address; + CObjSegment* m_Segment; +}; + +class CObjSymbol : public VTObject +{ +public: + CObjSymbol() { m_Line = -1; m_Value = -1; m_SymType = 0; + m_StrtabOffset = 0; m_Segment = NULL; } + +// Attributes + + MString m_Name; + long m_Line; + long m_Value; + CObjSegment* m_Segment; + unsigned short m_SymType; + unsigned short m_FileIndex; + long m_StrtabOffset; + unsigned long m_Off8; + unsigned long m_Off16; +}; + +class CObjFileSection : public VTObject +{ +public: + CObjFileSection() { m_pStrTab = NULL; m_pObjSegment = NULL; m_pProgBytes = NULL; }; + ~CObjFileSection(); + + Elf32_Shdr m_ElfHeader; // The ELF header as read from the file + char* m_pStrTab; // Pointer to the string table, if any + CObjSegment* m_pObjSegment; // Pointer to the Segment data + VTObArray m_Symbols; // Symbols from the symbol table + VTObArray m_Reloc; // Relocation entries + char* m_pProgBytes; // Pointer to program bytes +}; + +class CLinkRgn : public VTObject +{ +public: + CLinkRgn(int type, MString& name, int startAddr, int endAddr, int prot); + ~CLinkRgn(); + +// Attributes + MString m_Name; + LinkAddrRange* m_pFirstAddrRange; + int m_Type; + int m_Protected; +}; + +typedef void (*stdOutFunc_t)(void *pContext, const char *msg); + +class CObjFile : public VTObject +{ +public: + CObjFile(const char* name) { m_Name = name; }; + ~CObjFile(); + +// Attributes + MString m_Name; // Filename + VTObArray m_FileSections; // Array of file sections + Elf32_Ehdr m_Ehdr; // The main ELF header +}; + + +class VTLinker : public VTObject +{ +public: + VTLinker(); + ~VTLinker(); + +// Attributes + + VTMapStringToOb m_UndefSymbols; // Map of undefined symbols + VTMapStringToOb m_Symbols; // Map of Symbols + VTMapStringToOb m_ObjFiles; // Array of CObjFile objects + VTMapStringToOb m_LinkRegions; // Map of CLinkRgn objects where we can link to + MStringArray m_LinkFiles; // Array of filenames to be linked + MStringArray m_Errors; // Array of error messages during parsing + MStringArray* m_ActiveLinkOrder; // Array of error messages during parsing + VTMapStringToOb m_LinkOrderList; // List of link order arrays per segment + VTMapStringToOb m_LinkContainsList; // List of link order arrays per segment + VTMapStringToOb m_LinkEndsWithList; // List of link order arrays per segment + MString m_SegName; // Active segment name + stdOutFunc_t m_pStdoutFunc; // Standard out message routine + void* m_pStdoutContext; // Opaque context for stdout + int m_Map; // Create a map file? + int m_Hex; // Create a HEX file? + int m_DebugInfo; // Include debug info in .obj? + int m_ProjectType; + int m_FileIndex; + int m_Command; // Script command during file parsing + MString m_OutputName; // Name of output file + MString m_ObjFileList; // Comma separated list of files + MString m_ObjPath; // Comma separated list of directories + MString m_LinkOptions; // Linker options + MString m_RootPath; // Root path of project. + MString m_LinkerScript; // Name of the linker script + MStringArray m_ObjDirs; // Array of '/' terminated object dirs + +// Operations + int GetValue(MString & string, int & value); + int LookupSymbol(MString& name, CObjSymbol *& symbol); + CObjSymbol* LookupSymOtherFile(MString& name, CObjSegment** pSeg = NULL); + void ResetContent(void); + int CreateObjFile(const char *filename); + void MakeBinary(int val, int length, MString& binary); + void CreateHex(MString& filename); + void CreateMap(MString& filename, MString& asmFilename); + void CalcObjDirs(); + MString PreprocessDirectory(const char *pDir); + int MapScriptCommand(const char *pStr, int lineNo); + void ProcScriptField2(const char *pStr, int lineNo, MString &segname); + void ProcScriptField3(const char *pStr, int lineNo, int& startAddr); + void ProcScriptField4(const char *pStr, int lineNo, int& endAddr); + void ProcScriptField5(const char *pStr, int lineNo, int& prot); + void AddOrderedSegment(const char *pStr, int lineNo); + void AddContainsSegment(const char *pStr, int lineNo); + void AddEndsWithSegment(const char *pStr, int lineNo); + void NewLinkRegion(int type, int lineNo, int startAddr, + int endAddr, int prot); + int EvaluateScriptAddress(const char *pStr, int lineNo); + void ProcessArgs(MString &str, const char *pDelim); + int ReadLinkerScript(void); + int ReadObjFiles(void); + int ReadElfHeaders(FILE* fd, MString& filename); + int ReadSectionData(FILE* fd, CObjFile* pFile, + CObjFileSection* pFileSection); + int LocateSegments(void); + int LocateAsegSegment(CObjFileSection* pFileSect); + int LocateCsegSegment(CObjFileSection* pFileSect); + int LocateDsegSegment(CObjFileSection* pFileSect); + +// Public Access functions + int Link(); + void SetLinkOptions(const MString& options); + void SetObjFiles(const MString& options); + void SetLinkerScript(const MString& script); + void SetObjDirs(const MString& dirs); + void SetRootPath(const MString& rootPath); + void SetProjectType(int type); + void SetStdoutFunction(void *pContext, stdOutFunc_t pFunc); + const MStringArray& GetErrors() { return m_Errors; }; +}; + +#endif diff --git a/src/m100emu.c b/src/m100emu.c index a87918b..295a47d 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -35,11 +35,14 @@ #ifdef _WIN32 #include #include +#include #endif #ifdef __unix__ #include #include +#include +#include #endif #include "VirtualT.h" @@ -61,46 +64,64 @@ #include "clock.h" #include "fileview.h" -int fullspeed=0; -int gModel = MODEL_M100; +int gModel = MODEL_M100; -uchar cpu[14]; +volatile uchar cpu[14]; extern uchar *gMemory[64]; extern uchar gMsplanROM[32768]; extern uchar gOptROM[32768]; +extern int gInMsPlanROM; mem_monitor_cb gMemMonitor1 = NULL; mem_monitor_cb gMemMonitor2 = NULL; -char op[26]; -UINT64 cycles=0; -int cycle_delta; -UINT64 instructs=0; -static UINT64 last_isr_cycle=0; -int trace=0; -int starttime; -FILE *tracefile; -DWORD rst7cycles = 9830; -DWORD one_sec_cycle_count; -DWORD one_sec_time; -DWORD gLptTime; -UINT64 one_sec_cycles; -DWORD update_secs = 0; -float cpu_speed; -volatile int gExitApp = 0; -volatile int gExitLoop = 0; -char gsOptRomFile[256]; -int gShowVersion = 0; -DWORD last_one_sec_time; -int gMaintCount = 65536; -int gOsDelay = 0; -int gNoGUI = 0; -int gSocketPort = 0; -int gTelnet = FALSE; -int gRemoteSwitchModel = -1; +char op[26]; +int fullspeed = 0; +volatile UINT64 cycles=0; +volatile int cycle_delta; +volatile UINT64 instructs = 0; +volatile UINT64 gThrottleCycles = 0; +DWORD gThrottleDelta = 0; +unsigned int gThrottlePeriod = 0; +int gThrottlePeriodCount = 0; +int gThrottleTerminalCount = 0; +DWORD gTargetFrequency = 2457600; +unsigned int gThrottleId = 0; -//Added J. VERNET +#ifdef WIN32 +static HANDLE gThrottleEvent; +static CRITICAL_SECTION gThrottleCritSect; +#else +int gThrottleExit = 0; +pthread_t gThrottleThread; // The remote control thread +pthread_mutex_t gThrottleLock; // Lock to access emulation +sem_t gThrottleEvent; // Throttle event semaphore +#endif +double last_instruct = 0; +static volatile UINT64 last_isr_cycle = 0; +int trace=0; +int starttime; +FILE *tracefile; +volatile DWORD rst7cycles = 9830; +static time_t gLptTime; +static UINT64 one_sec_cycles; +static DWORD one_sec_cycle_count; +static time_t one_sec_time; +static DWORD last_one_sec_time; +float cpu_speed; +float gCpuSpeedAvg[4]; +int gCpuSpeedAvgIndex = 0; +volatile int gExitApp = 0; +volatile int gExitLoop = 0; +char gsOptRomFile[256]; +int gShowVersion = 0; +int gMaintCount = 65536; +int gOsDelay = 0; +int gNoGUI = 0; +int gRemoteSwitchModel = -1; + +//Added J. VERNET char path[512]; char file[512]; @@ -108,8 +129,6 @@ extern RomDescription_t gM100_Desc; extern RomDescription_t gM200_Desc; extern RomDescription_t gN8201_Desc; extern RomDescription_t gM10_Desc; -//JV -//extern RomDescription_t gN8300_Desc; extern RomDescription_t gKC85_Desc; @@ -130,35 +149,158 @@ debug_monitor_callback gpDebugMonitors[3] = { NULL, NULL, NULL }; void periph_mon_update_lpt_log(void); +#ifdef WIN32 +void CALLBACK ThrottleProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) +{ + /* Update the cycles counter */ + EnterCriticalSection(&gThrottleCritSect); + + /* Update the gThrotleCycles count to allow the emulation to run + a little during this timer tick. We want to limit the amount + gThrottleCycels is allowed to race beyond cycles in case the + emulation is running slower than we think, like during window + redraws or menu events + */ + if ((gThrottleCycles - (gThrottleDelta << 1) <= cycles) || (fullspeed == 3)) + { + gThrottleCycles += gThrottleDelta; + } + gThrottlePeriodCount++; + LeaveCriticalSection(&gThrottleCritSect); + + /* Now pulse the event to allow the emulation to run */ + PulseEvent(gThrottleEvent); +} + +#else /* WIN32 */ + +void * ThrottlePeriodProc(void *pParams) +{ + int sleepUs = 1000 / gThrottlePeriod * 1000; + + /* Loop until time to exit the app */ + while (!gThrottleExit) + { + /* Update the gThrotleCycles count to allow the emulation to run + a little during this timer tick. We want to limit the amount + gThrottleCycels is allowed to race beyond cycles in case the + emulation is running slower than we think, like during window + redraws or menu events + */ + pthread_mutex_lock(&gThrottleLock); + if ((gThrottleCycles - (gThrottleDelta << 1) <= cycles) || (fullspeed == 3)) + { + gThrottleCycles += gThrottleDelta; + } + gThrottlePeriodCount++; + pthread_mutex_unlock(&gThrottleLock); + + /* Post the event semaphore to wake up the emulation thread */ + sem_post(&gThrottleEvent); + + /* Sleep the perscribed number of microseconds */ + if(fullspeed != 3) + usleep(sleepUs); + else + usleep(sleepUs * 2); + } +} + +#endif + /* ============================================================================= -This routine supplies an OS independant high-resolution timer for use with -emulation speed calculations and throttling. +This routine intializes the system timer used for throttling the emulation +speed. ============================================================================= */ -#ifdef _WIN32 -__inline double hirestimer(void) +int init_throttle_timer(void) { - static LARGE_INTEGER pcount, pcfreq; - static int initflag = 0; +#ifdef WIN32 + TIMECAPS tc; + + /* Get the system's multimedia timer capabilties */ + timeGetDevCaps(&tc, sizeof(tc)); - if (!initflag) + /* On older systems, the minimum may be 55ms. In this case, we just use 55ms as the tick */ + if (tc.wPeriodMin > 50) { - QueryPerformanceFrequency(&pcfreq); - initflag++; - } + gThrottlePeriod = tc.wPeriodMin; + gThrottleTerminalCount = 1000 / gThrottlePeriod; + } + else if (tc.wPeriodMin <= 10) + { + /* We don't need 10ms of resolution. Let's use 20ms instead */ + gThrottlePeriod = 50; - QueryPerformanceCounter(&pcount); - return (double)pcount.QuadPart / (double)pcfreq.QuadPart; -} + /* Set TC for 50 counts = 1sec */ + gThrottleTerminalCount = 20; + } + + /* Setup the throttle event for signalling */ + gThrottleEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + InitializeCriticalSection(&gThrottleCritSect); + + /* Calculate the period, Throttle Delta time and setup the timer */ + gThrottleDelta = gTargetFrequency * gThrottlePeriod / 1000; + if (timeBeginPeriod(gThrottlePeriod) == TIMERR_NOCANDO) + return FALSE; + gThrottleId = timeSetEvent(gThrottlePeriod, tc.wPeriodMin, ThrottleProc, + 0, TIME_PERIODIC ); #else -__inline double hirestimer(void) + + /* We don't need 10ms of resolution. Let's use 20ms instead */ + gThrottlePeriod = 40; + + /* Set TC for 50 counts = 1sec */ + gThrottleTerminalCount = 25; + gThrottlePeriodCount = 0; + gThrottleDelta = gTargetFrequency * gThrottlePeriod / 1000; + gThrottleCycles = cycles + (gThrottleDelta << 1); + + // Initialize thread processing + pthread_mutex_init(&gThrottleLock, NULL); + pthread_create(&gThrottleThread, NULL, ThrottlePeriodProc, NULL); + sem_init(&gThrottleEvent, 0, 0); + +#endif + + return 1; +} + +void set_target_frequency(int frequency) { - struct timeval tv; - gettimeofday(&tv, NULL); - return (double)tv.tv_sec + (double)tv.tv_usec / 1000000; + gTargetFrequency = frequency; + gThrottleDelta = gTargetFrequency * gThrottlePeriod / 1000; + gThrottleCycles = cycles + gThrottleDelta; } + +/* +============================================================================= +This routine de-intializes the system timer used for throttling the emulation +speed. +============================================================================= +*/ +void deinit_throttle_timer(void) +{ +#ifdef WIN32 + /* Kill the timer event */ + if (gThrottleId != 0) + timeKillEvent(gThrottleId); + + /* End the timer period */ + timeEndPeriod(gThrottlePeriod); + + /* Destory the triggering event */ + CloseHandle(gThrottleEvent); +#else + /* Instruct the throttle thread to terminate */ + gThrottleExit = 1; + + /* Join our throttle thread to ensure a clean shutdown */ + pthread_join(gThrottleThread, NULL); #endif +} /* ============================================================================= @@ -166,35 +308,46 @@ This routine "throttles" the emulation speed based on the instruction cycle count. This is used for 2.4 Mhz emulation speed. ============================================================================= */ -double last_instruct=0; void throttle(int cy) { - double hires; - if(!fullspeed) + /* Update cycles counter */ + cycles+=cy; + cycle_delta=0; + + if(fullspeed != 3) { +#ifdef WIN32 + if (cycles >= gThrottleCycles) + { +// process_windows_event(); + WaitForSingleObject(gThrottleEvent, INFINITE); + } +#else + if (cycles >= gThrottleCycles) + { + sem_wait(&gThrottleEvent); + } +#if 0 + double hires; + if(last_instruct==0) last_instruct=hirestimer(); last_instruct+=cy*0.000000416666666667; - while((hires = hirestimer()) last_hires + .05) + static int rst7UpdateCnt = 0; + DWORD new_rst7cycles; + static int lpt_update = 0; + int count; + static int secsPeriod = 0; + static int secsCycles = 0; + DWORD deltaCycles, oneSecCycleEstimate; + static UINT64 lastDeltaCycles = 0; + + /* Adjust the background tick cycle estimate 25 times a second */ + if (gThrottlePeriodCount > 0) { - // Update the last_hires timer for next comparison - last_hires = hires; - one_sec_cycle_count = (DWORD) (cycles - one_sec_cycles) / 100; - one_sec_cycles = cycles; - new_rst7cycles = (DWORD) (0.39998 * 20 * one_sec_cycle_count); /* 0.39998 = 9830 / 24576 */ + /* Get and reset the period count */ + #ifdef WIN32 + EnterCriticalSection(&gThrottleCritSect); + #else + pthread_mutex_lock(&gThrottleLock); + #endif + + count = gThrottlePeriodCount; + gThrottlePeriodCount = 0; + + #ifdef WIN32 + LeaveCriticalSection(&gThrottleCritSect); + #else + pthread_mutex_unlock(&gThrottleLock); + #endif + + // Calculate the delta in cycles since the last time we checked + deltaCycles = (DWORD) (cycles - lastDeltaCycles); + lastDeltaCycles = cycles; + oneSecCycleEstimate = (DWORD) ((UINT64) deltaCycles * gThrottleTerminalCount / count); + secsPeriod += count; + secsCycles += deltaCycles; + if (secsPeriod >= gThrottleTerminalCount) + { + one_sec_cycles = cycles; + + /* Every second we want to update the CPU frequencey and do some maintenance */ + gCpuSpeedAvg[gCpuSpeedAvgIndex++] = (float) secsCycles / (float) 1000000.0; + gCpuSpeedAvgIndex %= 4; + cpu_speed = (gCpuSpeedAvg[0] + gCpuSpeedAvg[1] + gCpuSpeedAvg[2] + gCpuSpeedAvg[3]) / (float) 4.0; + display_cpu_speed(); + + /* Check for errors on the LPT port and update the Peripherial Display if visible */ + lpt_check_errors(); + periph_mon_update_lpt_log(); + time(&one_sec_time); + + /* Clear variables so we only enter here once a second */ + secsCycles = 0; + secsPeriod = 0; + } + +#ifdef WIN32 + new_rst7cycles = (DWORD) (0.0039998 * oneSecCycleEstimate); /* 0.0039998 = 9830 / 2457600 */ +#else + if (fullspeed == 3) + new_rst7cycles = (DWORD) (oneSecCycleEstimate / 256); /* Fullspeed sleeps twice as long */ + else + new_rst7cycles = (DWORD) (oneSecCycleEstimate / 128); +#endif // Check if the rst7cycles needs to be updated. We only update this every 3rd time through // The rst7cycles value is what controls the keyboard-timer interrupt rate and it // changes based on host CPU speed to try to match the M100 scan rate - if ((new_rst7cycles > (rst7cycles * 0.8)) || (twice_flag == 2)) + if ((new_rst7cycles > (rst7cycles * 0.8)) || (rst7UpdateCnt == 2)) { rst7cycles = new_rst7cycles; if (rst7cycles < 9830) rst7cycles = 9830; - time(&systime); - if (systime != (time_t) one_sec_time) - { - cpu_speed = (float) (.000097656 * 20 * one_sec_cycle_count); /* 2.4 Mhz / 24576 */ - display_cpu_speed(); - lpt_check_errors(); - periph_mon_update_lpt_log(); - } - twice_flag = 0; + rst7UpdateCnt = 0; // Check if we need to update the Memory Editor monitor if (gMemMonitor1 != NULL) @@ -808,7 +1010,7 @@ void maint(void) gMemMonitor2(); } else - twice_flag++; + rst7UpdateCnt++; // Check if we need to do lpt animation if (++lpt_update >= 7) @@ -817,14 +1019,11 @@ void maint(void) lpt_update = 0; } - // Update the last one_sec_time value to keep track of seconds for emulated speed reporting - last_one_sec_time = one_sec_time; - one_sec_time = (unsigned long) systime; + // Test if socket interface simulating a key press + handle_simkey(); + process_windows_event(); } - // Do CPU throttling for 2.4Mhz mode - throttle(cycle_delta); - // Test if socket interface requested model switch if (gRemoteSwitchModel != -1) { @@ -832,16 +1031,15 @@ void maint(void) gRemoteSwitchModel = -1; } - // Test if socket interface simulating a key press - handle_simkey(); - process_windows_event(); - // Handle LPT Timeout Activity if (one_sec_time != gLptTime) { gLptTime = one_sec_time; - handle_lpt_timeout(one_sec_time); + handle_lpt_timeout((DWORD) one_sec_time); } + + if (gInMsPlanROM) + gInMsPlanROM--; } @@ -888,6 +1086,7 @@ void emulate(void) { unsigned int i,j; unsigned int v; + int top=0; int nxtmaint=1; int ins; @@ -911,7 +1110,8 @@ void emulate(void) #include "do_instruct.h" // Check if next inst is SIM - if (get_memory8(PC) == 0xF3) + if ((get_memory8(PC) == 0xF3) || ((IM & 0x2A) == 0x20) || + ((IM & 0x4C) == 0x40)) { check_interrupts(); } @@ -937,6 +1137,7 @@ void emulate(void) { unlock_remote(); gOsDelay = nxtmaint == 0; + throttle(cycle_delta); maint(); ser_poll(); check_interrupts(); @@ -963,8 +1164,9 @@ void emulate(void) #include "cpu.h" #include "do_instruct.h" - // Check if next inst is SIM - if (get_memory8(PC) == 0xF3) + // Check if next inst is SIM or RS-232 waiting + if ((get_memory8(PC) == 0xF3) || ((IM & 0x2A) == 0x20) || + ((IM & 0x4C) == 0x40)) { check_interrupts(); } @@ -990,6 +1192,7 @@ void emulate(void) { unlock_remote(); gOsDelay = nxtmaint == 0; + throttle(cycle_delta); maint(); ser_poll(); check_interrupts(); @@ -1041,7 +1244,7 @@ int process_args(int argc, char **argv) gNoGUI = 1; if (!strcmp(argv[i], "-t")) - gTelnet = TRUE; + set_remote_cmdline_telnet(TRUE); // Search for Socket Port flag if (!strncmp(argv[i], "-p", 2)) @@ -1049,7 +1252,7 @@ int process_args(int argc, char **argv) // Check if port number is part of flag if (strlen(argv[i]) != 2) { - gSocketPort = atoi(&argv[i][2]); + set_remote_cmdline_port(atoi(&argv[i][2])); } else { @@ -1061,7 +1264,7 @@ int process_args(int argc, char **argv) } else { - gSocketPort = atoi(argv[i+1]); + set_remote_cmdline_port(atoi(argv[i+1])); i++; } } @@ -1168,6 +1371,7 @@ int main(int argc, char **argv) init_pref(); /* load user Menu preferences */ load_setup_preferences(); /* Load user Peripheral setup preferences */ load_memory_preferences(); /* Load user Memory setup preferences */ + load_remote_preferences(); /* Load user Remote Socket preferences */ /* Perform initialization */ init_mem(); /* Initialize Memory */ @@ -1175,6 +1379,7 @@ int main(int argc, char **argv) init_sound(); /* Initialize Sound system */ init_display(); /* Initialize the Display */ init_cpu(); /* Initialize the CPU */ + init_throttle_timer(); /* Initialize the throttle timer */ init_remote(); /* Initialize the remote control */ init_lpt(); /* Initialize the printer subsystem */ get_model_time(); /* Load the emulated time for current model */ @@ -1190,6 +1395,8 @@ int main(int argc, char **argv) deinit_io(); /* Deinitialize I/O */ deinit_sound(); /* Deinitialize sound */ deinit_lpt(); /* Deinitialize the printer */ + deinit_throttle_timer(); /* Deinitialize the throttle timer */ + deinit_display(); /* Deinitialze and free the main window */ free_mem(); /* Free memory used by ReMem and/or Rampac */ return 0; diff --git a/src/m100emu.h b/src/m100emu.h index aa6a5b9..bfeb79a 100644 --- a/src/m100emu.h +++ b/src/m100emu.h @@ -89,7 +89,7 @@ void get_rom_path(char* file, int model); void init_cpu(void); //void cpu_delay(int cy); void resetcpu(void); -void cb_int65(void); +void cb_int65(int pinLevel); #ifdef __cplusplus } diff --git a/src/m100rom.c b/src/m100rom.c index b3dc8df..1952eb8 100644 --- a/src/m100rom.c +++ b/src/m100rom.c @@ -1001,6 +1001,8 @@ RomDescription_t gM100_Desc = { 0xFF9A, /* Keyscan location */ 0x7711, /* Character generator table */ 0xF92D, /* Loacation of Year storage */ + 0xFE00, /* LCD Buffer storage area */ + 0xf63d, /* Label line enable flag */ 24, /* Number of directory entries */ 8, /* Index of first Dir entry */ diff --git a/src/m10rom.c b/src/m10rom.c index 250edbc..a5da6ee 100644 --- a/src/m10rom.c +++ b/src/m10rom.c @@ -983,6 +983,8 @@ RomDescription_t gM10_Desc = { 0xFF5C, /* Keyscan array */ 0x742B, /* Character generator table */ 0xF934, /* Location of Year storage */ + 0xFE00, /* LCD Buffer storage area */ + 0xF644, /* Label line enable flag */ 24, /* Number of directory entries */ 8, /* Index of first Dir entry */ diff --git a/src/m200rom.c b/src/m200rom.c index f5c07b4..3d04ab9 100644 --- a/src/m200rom.c +++ b/src/m200rom.c @@ -277,6 +277,7 @@ Std_ROM_Addresses_t gM200_Vars[] = { { 0xF7C9, R_MENU_TO_RAM_MAP }, { 0xF848, R_CUR_MENU_DIR_LOC }, { 0xF849, R_MAX_MENU_DIR_LOC }, + { 0xFA30, R_LCD_CHAR_BUF }, { 0xFCF0, R_XON_XOFF_CTRL }, { 0xFCF1, R_XON_XOFF_CTRL }, { 0xFCF2, R_XON_XOFF_ENABLE }, @@ -986,6 +987,8 @@ RomDescription_t gM200_Desc = { 0xFD0E, /* Keyscan array */ 0x9063, /* Character generator array */ 0x0000, /* Location of Year - not used for T200 */ + 0xFA30, /* Location of LCD buffer area */ + 0xEF0A, /* Label line enable flag */ 52, /* Number of directory entries */ 9, /* Index of first dir entry */ diff --git a/src/memedit.cpp b/src/memedit.cpp index c64ce68..4f7bb2d 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -39,6 +39,9 @@ #include #include #include +#include + +#include "FLU/Flu_File_Chooser.h" #if defined(WIN32) #include @@ -323,7 +326,7 @@ void load_file_to_mem(const char *filename, int address) { // Open file as binary FILE* fd; - if ((fd = fopen(filename, "r")) != NULL) + if ((fd = fopen(filename, "rb")) != NULL) { int read_len; @@ -335,6 +338,11 @@ void load_file_to_mem(const char *filename, int address) while (len != 0) { read_len = fread(buffer, 1, len, fd); + if (read_len == 0) + { + fl_alert("Error reading file!"); + break; + } set_memory8_ext(region, address, read_len, buffer); len -= read_len; address += read_len; @@ -393,17 +401,24 @@ void load_browseButton_cb(Fl_Widget* w, void*) int count; const char * filename; - Fl_File_Chooser file(".","*.{bin,hex}",1,"Select File to Open"); - file.show(); + fl_cursor(FL_CURSOR_WAIT); + Flu_File_Chooser file(".","*.{bin,hex}",1,"Select File to Open"); + gDialog.pWin->set_non_modal(); + file.set_modal(); + fl_cursor(FL_CURSOR_DEFAULT); + file.show(); while (file.visible()) Fl::wait(); // Get filename count = file.count(); if (count != 1) + { + gDialog.pWin->set_modal(); return; - filename = file.value(1); + } + filename = file.value(); if (filename == 0) return; @@ -426,21 +441,32 @@ void save_browseButton_cb(Fl_Widget* w, void*) strcpy(filespec, "*.hex"); else strcpy(filespec, "*.bin"); - Fl_File_Chooser file(".", filespec, Fl_File_Chooser::CREATE, "Select File to Open"); + fl_cursor(FL_CURSOR_WAIT); + Flu_File_Chooser file(".", filespec, 1, "Select File to Open"); + fl_cursor(FL_CURSOR_DEFAULT); + gDialog.pWin->set_non_modal(); + file.set_modal(); while (1) { file.show(); + file.take_focus(); while (file.visible()) Fl::wait(); // Get filename count = file.count(); if (count != 1) + { + gDialog.pWin->set_modal(); return; - filename = file.value(1); + } + filename = file.value(); if (filename == 0) + { + gDialog.pWin->set_modal(); return; + } // Try to open the ouput file fd = fopen(filename, "rb+"); @@ -453,12 +479,16 @@ void save_browseButton_cb(Fl_Widget* w, void*) // Test if Cancel selected if (c == 0) + { + gDialog.pWin->set_modal(); return; + } if (c == 1) break; } } + gDialog.pWin->set_modal(); // Check if filename ends with ".hex" len = strlen(filename); @@ -552,6 +582,9 @@ void cb_load(Fl_Widget* w, void*) while (gDialog.pWin->visible()) Fl::wait(); + gmew->take_focus(); + gmew->show(); + // Check if OK button was pressed if (gDialog.iOk) { @@ -565,7 +598,6 @@ void cb_load(Fl_Widget* w, void*) } delete gDialog.pWin; - gmew->take_focus(); } /* @@ -776,11 +808,17 @@ void cb_MemoryEditor (Fl_Widget* w, void*) return; // Create Peripheral Setup window +#ifdef WIN32 gmew = new Fl_Window(585, 400, "Memory Editor"); - gmew->callback(cb_memeditwin); - // Create a menu for the new window. memedit_ctrl.pMenu = new Fl_Menu_Bar(0, 0, 585, MENU_HEIGHT-2); +#else + gmew = new Fl_Window(735, 400, "Memory Editor"); + // Create a menu for the new window. + memedit_ctrl.pMenu = new Fl_Menu_Bar(0, 0, 735, MENU_HEIGHT-2); +#endif + + gmew->callback(cb_memeditwin); memedit_ctrl.pMenu->menu(gMemEdit_menuitems); // Create static text boxes @@ -798,9 +836,14 @@ void cb_MemoryEditor (Fl_Widget* w, void*) memedit_ctrl.pMemRange->callback(cb_memory_range); // memedit_ctrl.pMemRange->deactivate(); +#ifdef WIN32 memedit_ctrl.pMemEdit = new T100_MemEditor(10, 40+MENU_HEIGHT, 545, 350-MENU_HEIGHT); - memedit_ctrl.pScroll = new Fl_Scrollbar(555, 40+MENU_HEIGHT, 15, 350-MENU_HEIGHT, ""); +#else + memedit_ctrl.pMemEdit = new T100_MemEditor(10, 40+MENU_HEIGHT, 695, 350-MENU_HEIGHT); + memedit_ctrl.pScroll = new Fl_Scrollbar(705, 40+MENU_HEIGHT, 15, 350-MENU_HEIGHT, ""); +#endif + memedit_ctrl.pScroll->type(FL_VERTICAL); memedit_ctrl.pScroll->linesize(2); memedit_ctrl.pScroll->maximum(2); @@ -864,6 +907,11 @@ T100_MemEditor::T100_MemEditor(int x, int y, int w, int h) : m_SelActive = 0; m_SelEndRow = 0; m_SelEndCol = 0; +#ifdef WIN32 + m_FontSize = 12; +#else + m_FontSize = 14; +#endif SetRegionOptions(); } @@ -878,10 +926,33 @@ void T100_MemEditor::SetRegionOptions(void) // Update the Regions control with appropriate options if (gReMem) { - memedit_ctrl.pRegion->add("RAM"); - memedit_ctrl.pRegion->add("Flash 1"); - memedit_ctrl.pRegion->add("Flash 2"); - memedit_ctrl.pRegion->value(0); + if (gRex) + { + if (gModel == MODEL_T200) + { + memedit_ctrl.pRegion->add("RAM 1"); + memedit_ctrl.pRegion->add("RAM 2"); + memedit_ctrl.pRegion->add("RAM 3"); + } + else + { + memedit_ctrl.pRegion->add("RAM"); + } + memedit_ctrl.pRegion->add("ROM"); + if (gModel == MODEL_T200) + memedit_ctrl.pRegion->add("ROM 2"); + memedit_ctrl.pRegion->add("Flash"); + if (gRex == REX2) + memedit_ctrl.pRegion->add("128K SRAM"); + memedit_ctrl.pRegion->value(0); + } + else + { + memedit_ctrl.pRegion->add("RAM"); + memedit_ctrl.pRegion->add("Flash 1"); + memedit_ctrl.pRegion->add("Flash 2"); + memedit_ctrl.pRegion->value(0); + } } else { @@ -930,8 +1001,48 @@ void T100_MemEditor::SetScrollSize(void) // Test for ReMem emulation mode if (gReMem) { - // All ReMem blocks are 2Meg = 128K lines * 16 bytes - m_Max = 1024 * 2048 / 16; + /* Test if the ReMem emulation is really REX */ + if (gRex) + { + region = memedit_ctrl.pRegion->value(); + if (gModel == MODEL_T200) + { + switch (region) + { + case 0: + case 1: + case 2: + m_Max = RAMSIZE / 16; + break; + case 3: + case 4: + m_Max = ROMSIZE / 16; + break; + case 5: + m_Max = 1024 * 1024 / 16; + break; + case 6: + m_Max = 128 * 1024 / 16; + break; + } + } + else + { + if (region == 0) + m_Max = RAMSIZE / 16; + else if (region == 1) + m_Max = ROMSIZE / 16; + else if (region == 2) + m_Max = 1024 * 1024 / 16; + else if (region == 3) + m_Max = 128 * 1024 / 16; + } + } + else + { + // All ReMem blocks are 2Meg = 128K lines * 16 bytes + m_Max = 1024 * 2048 / 16; + } } else { @@ -963,7 +1074,7 @@ void T100_MemEditor::SetScrollSize(void) m_Max = 1024 * 256 / 16; // Select 12 point Courier font - fl_font(FL_COURIER, 12); + fl_font(FL_COURIER, m_FontSize); // Get character width & height m_Height = fl_height(); @@ -989,7 +1100,7 @@ int T100_MemEditor::GetRegionEnum(void) // Test if RAM region is selected if (strcmp(reg_text, "RAM") == 0) { - if (gReMem) + if (gReMem && !gRex) m_Region = REGION_REMEM_RAM; else m_Region = REGION_RAM; @@ -1031,6 +1142,14 @@ int T100_MemEditor::GetRegionEnum(void) if (strcmp(reg_text, "Flash 2") == 0) m_Region = REGION_FLASH2; + // Test if REX Flash region is selected + if (strcmp(reg_text, "Flash") == 0) + m_Region = REGION_REX_FLASH; + + // Test if REX Flash region is selected + if (strcmp(reg_text, "128K SRAM") == 0) + m_Region = REGION_REX2_RAM; + return m_Region; } @@ -1053,7 +1172,7 @@ void T100_MemEditor::UpdateDispMem(void) window()->make_current(); // Select 12 point Courier font - fl_font(FL_COURIER, 12); + fl_font(FL_COURIER, m_FontSize); // Check for changes for (c = 0; c < count; c++) @@ -1107,7 +1226,7 @@ void T100_MemEditor::draw() int region; // Region where memory is being drawn from // Select 12 point Courier font - fl_font(FL_COURIER, 12); + fl_font(FL_COURIER, m_FontSize); // Get character width & height m_Width = fl_width("W", 1); @@ -1293,7 +1412,7 @@ int T100_MemEditor::handle(int event) window()->make_current(); // Select 12 point Courier font - fl_font(FL_COURIER, 12); + fl_font(FL_COURIER, m_FontSize); // Erase current cursor EraseCursor(); @@ -1444,7 +1563,7 @@ int T100_MemEditor::handle(int event) else { // Select 12 point Courier font - fl_font(FL_COURIER, 12); + fl_font(FL_COURIER, m_FontSize); // Get character width & height m_Height = fl_height(); @@ -1478,7 +1597,7 @@ int T100_MemEditor::handle(int event) else { // Select 12 point Courier font - fl_font(FL_COURIER, 12); + fl_font(FL_COURIER, m_FontSize); // Get character width & height m_Height = fl_height(); @@ -1794,7 +1913,7 @@ int T100_MemEditor::handle(int event) // Display new text // Select 12 point Courier font - fl_font(FL_COURIER, 12); + fl_font(FL_COURIER, m_FontSize); sprintf(string, "%02X", data); @@ -1848,7 +1967,7 @@ int T100_MemEditor::handle(int event) // Cursor at bottom of screen. Need to scroll // Select 12 point Courier font - fl_font(FL_COURIER, 12); + fl_font(FL_COURIER, m_FontSize); // Get character width & height m_Height = fl_height(); @@ -1897,7 +2016,7 @@ int T100_MemEditor::handle(int event) // Display new text // Select 12 point Courier font - fl_font(FL_COURIER, 12); + fl_font(FL_COURIER, m_FontSize); sprintf(string, "%02X", data); @@ -1944,7 +2063,7 @@ int T100_MemEditor::handle(int event) // Cursor at bottom of screen. Need to scroll // Select 12 point Courier font - fl_font(FL_COURIER, 12); + fl_font(FL_COURIER, m_FontSize); // Get character width & height m_Height = fl_height(); @@ -1974,6 +2093,9 @@ int T100_MemEditor::handle(int event) } break; + case FL_MOUSEWHEEL: + return memedit_ctrl.pScroll->handle(event); + default: Fl_Widget::handle(event); break; @@ -2003,7 +2125,7 @@ void T100_MemEditor::ScrollUp(int lines) // Select 12 point Courier font - fl_font(FL_COURIER, 12); + fl_font(FL_COURIER, m_FontSize); // Get height of screen in lines m_Height = fl_height(); @@ -2045,7 +2167,7 @@ void T100_MemEditor::MoveTo(int address) EraseCursor(); // Select 12 point Courier font - fl_font(FL_COURIER, 12); + fl_font(FL_COURIER, m_FontSize); // Get height of screen in lines m_Height = fl_height(); diff --git a/src/memedit.h b/src/memedit.h index b542180..c814ba6 100644 --- a/src/memedit.h +++ b/src/memedit.h @@ -73,6 +73,7 @@ class T100_MemEditor : public Fl_Widget double m_Height; double m_Width; int m_FirstAddress; + int m_FontSize; int m_CursorAddress; int m_CursorCol; diff --git a/src/memory.c b/src/memory.c index 2b5e1f3..858f5d0 100644 --- a/src/memory.c +++ b/src/memory.c @@ -48,17 +48,11 @@ unsigned char *gReMemSectPtr = 0; /* Pointer to current Sector memory */ unsigned short gReMemMap[64]; /* Map of 1K blocks - 64 total */ unsigned int gReMemMapLower = 0; /* Lower address of actively mapped MMU Map */ unsigned int gReMemMapUpper = 0; /* Upper address of actively mapped MMU Map */ -int gReMemFlash1State = FLASH_STATE_RO; -int gReMemFlash2State = FLASH_STATE_RO; -UINT64 gReMemFlash1Time = 0; -UINT64 gReMemFlash2Time = 0; -int gReMemFlash1Busy = FALSE; -int gReMemFlash2Busy = FALSE; int gReMemFlashReady = TRUE; +amd_flash_t gReMemFlash1 = { FLASH_STATE_RO, 0, FALSE, 0 }; +amd_flash_t gReMemFlash2 = { FLASH_STATE_RO, 0, FALSE, 0 }; uchar *gReMemRam = 0; /* Pointer to ReMem RAM space */ -uchar *gReMemFlash1 = 0; /* Pointer to ReMem Flash1 space */ -uchar *gReMemFlash2 = 0; /* Pointer to ReMem Flash2 space */ int gRampac = 0; /* Rampac Enable flag */ unsigned char *gRampacRam = 0; /* Rampac RAM pointer */ @@ -70,9 +64,17 @@ int gRampacSaveCounter = 0; /* Rampac emulation Counter */ unsigned char *gRampacSaveSectPtr = 0;/* Pointer to current Sector memory */ int gRampacEmulation = 0;/* ReMem's Rampac emulation active? */ -int gRex; /* Rex Emulation Enable flag */ -unsigned char *gRexRam; /* Rex RAM pointer */ - +int gRex = 0; /* Rex Emulation Enable flag */ +unsigned char *gRex2Ram = NULL; /* Rex2 RAM pointer */ +int gRexSector = 0; /* Active sector */ +int gRexState = 7; /* Rex Command State */ +unsigned char gRexReturn = 0; /* Return value for Status & HW reads */ +unsigned char gRexModel = 0; /* Rex model */ +unsigned char gRexFlashSel = 1; /* Rex Flash enable signal */ +int gRexKeyState = 0; /* Rex Key State */ +int gRexFlashPA = 0; /* REX Flash Address Line during programing */ +amd_flash_t gRexFlash = { FLASH_STATE_RO, 0, FALSE, 0 }; +unsigned char gRexKeyTable[6] = { 184, 242, 52, 176, 49, 191 }; int gIndex[65536]; extern RomDescription_t gM100_Desc; @@ -84,6 +86,7 @@ extern RomDescription_t gKC85_Desc; extern int gShowVersion; extern UINT64 cycles; +extern int cycle_delta; uchar gFlashCFIData[] = { 0x51, 0x52, 0x59, 0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x36, 0x00, 0x00, 0x04, @@ -96,10 +99,15 @@ unsigned char get_memory8(unsigned short address) { if (gReMem) { - if (gReMemFlashReady) - return gMemory[address >> 10][address & 0x3FF]; - /* Process Flash state machine and return the value */ - return remem_flash_sm_read(address); + if (gRex) + return rex_read(address); + else + { + if (gReMemFlashReady) + return gMemory[address >> 10][address & 0x3FF]; + /* Process Flash state machine and return the value */ + return remem_flash_sm_read(address); + } } else return gBaseMemory[address]; @@ -108,7 +116,11 @@ unsigned char get_memory8(unsigned short address) unsigned short get_memory16(unsigned short address) { if (gReMem) + { + if (gRex) + return rex_read(address) | (rex_read(address+1) << 8); return gMemory[address>>10][address&0x3FF] + (gMemory[(address+1)>>10][(address+1)&0x3FF] << 8); + } else return gBaseMemory[address] + (gBaseMemory[address+1] << 8); } @@ -116,7 +128,12 @@ unsigned short get_memory16(unsigned short address) void set_memory8(unsigned short address, unsigned char data) { if (gReMem) - remem_set8(address, data); + { + if (gRex) + rex_set8(address, data); + else + remem_set8(address, data); + } else gBaseMemory[address] = data; } @@ -146,7 +163,7 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) addr = RAMSTART + address; for (c = 0; c < count; c++) { - if (gReMem) + if (gReMem && !gRex) data[c] = gMemory[addr>>10][addr&0x3FF]; else data[c] = gBaseMemory[addr]; @@ -158,7 +175,7 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) addr = address; for (c = 0; c < count; c++) { - if (gReMem) + if (gReMem && !gRex) data[c] = gMemory[addr>>10][addr&0x3FF]; else data[c] = gBaseMemory[addr]; @@ -185,7 +202,7 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) addr = address + RAMSTART; for (c = 0; c < count; c++) { - if (gReMem) + if (gReMem && !gRex) data[c] = gMemory[addr>>10][addr&0x3FF]; else data[c] = gBaseMemory[addr]; @@ -207,7 +224,7 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) addr = address + RAMSTART; for (c = 0; c < count; c++) { - if (gReMem) + if (gReMem && !gRex) data[c] = gMemory[addr>>10][addr&0x3FF]; else data[c] = gBaseMemory[addr]; @@ -232,7 +249,7 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) addr = address + RAMSTART; for (c = 0; c < count; c++) { - if (gReMem) + if (gReMem && !gRex) data[c] = gMemory[addr>>10][addr&0x3FF]; else data[c] = gBaseMemory[addr]; @@ -273,7 +290,7 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) case REGION_FLASH1: case REGION_FLASH2: // First check that the ReMem RAM has been allocated - if ((gReMemRam == NULL) || (gReMemFlash1 == NULL) || (gReMemFlash2 == NULL)) + if ((gReMemRam == NULL) || (gReMemFlash1.pFlash == NULL) || (gReMemFlash2.pFlash == NULL)) break; // Indicate zero bytes copied so far @@ -283,9 +300,31 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) if (region == REGION_REMEM_RAM) ptr = gReMemRam; else if (region == REGION_FLASH1) - ptr = gReMemFlash1; + ptr = gReMemFlash1.pFlash; else - ptr = gReMemFlash2; + ptr = gReMemFlash2.pFlash; + + // Block is not mapped -- copy from 2Meg Region (RAM or FLASH) + addr = address; + for (;(cp_ptr < count); cp_ptr++) + data[cp_ptr] = ptr[addr++]; + break; + + /* + ================================================================ + The following deals with REX emulation of FLASH. + ================================================================ + */ + case REGION_REX_FLASH: + // First check that the ReMem RAM has been allocated + if (gRexFlash.pFlash == NULL) + break; + + // Indicate zero bytes copied so far + cp_ptr = 0; + + // Determine which location to copy memory from + ptr = gRexFlash.pFlash; // Block is not mapped -- copy from 2Meg Region (RAM or FLASH) addr = address; @@ -316,7 +355,7 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) addr = RAMSTART + address; for (c = 0; c < count; c++) { - if (gReMem) + if (gReMem && !gRex) gMemory[addr>>10][addr&0x3FF] = data[c]; else gBaseMemory[addr] = data[c]; @@ -355,7 +394,7 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) addr = address + RAMSTART; for (c = 0; c < count; c++) { - if (gReMem) + if (gReMem && !gRex) gMemory[addr>>10][addr&0x3FF] = data[c]; else gBaseMemory[addr] = data[c]; @@ -377,7 +416,7 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) addr = address + RAMSTART; for (c = 0; c < count; c++) { - if (gReMem) + if (gReMem && !gRex) gMemory[addr>>10][addr&0x3FF] = data[c]; else gBaseMemory[addr] = data[c]; @@ -402,7 +441,7 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) addr = address + RAMSTART; for (c = 0; c < count; c++) { - if (gReMem) + if (gReMem && !gRex) gMemory[addr>>10][addr&0x3FF] = data[c]; else gBaseMemory[addr] = data[c]; @@ -443,8 +482,9 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) case REGION_FLASH1: case REGION_FLASH2: // First check that the ReMem RAM has been allocated - if ((gReMemRam == NULL) || (gReMemFlash1 == NULL) || (gReMemFlash2 == NULL)) - break; + if ((gReMemRam == NULL) || (gReMemFlash1.pFlash == NULL) || + (gReMemFlash2.pFlash == NULL)) + break; // Check ReMem emulation mode // If REMEM_MODE_NORMAL bit is set then ReMem is mapping 1K @@ -485,9 +525,9 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) if (region == REGION_REMEM_RAM) ptr = gReMemRam; else if (region == REGION_FLASH1) - ptr = gReMemFlash1; + ptr = gReMemFlash1.pFlash; else if (region == REGION_FLASH2) - ptr = gReMemFlash2; + ptr = gReMemFlash2.pFlash; addr = address; @@ -496,7 +536,146 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) ptr[addr++] = data[cp_ptr]; } break; + + /* + ================================================================ + The following deals with REX emulation of FLASH. + ================================================================ + */ + case REGION_REX_FLASH: + /* Do sanity check on the pointer */ + if (gRexFlash.pFlash == NULL) + return; + + /* Get pointer to the REX flash */ + ptr = gRexFlash.pFlash; + + /* Setup to copy */ + addr = address; + + // Copy bytes up to the limit to allocation + for (cp_ptr = 0; cp_ptr < count; cp_ptr++) + ptr[addr++] = data[cp_ptr]; + + break; + } +} + +/* +======================================================================== +amd_flash_init: This routine initializes an amd_flash_t structure + and allocates memory of the specified size. +======================================================================== +*/ +void amd_flash_init(amd_flash_t *pFlash, int size, int type) +{ + int c; + + /* Allocate RAM for the flash and initiaize its state */ + if (pFlash->pFlash == NULL) + { + pFlash->pFlash = malloc(size); + } + pFlash->iFlashState = FLASH_STATE_RO; + pFlash->iFlashBusy = FALSE; + pFlash->iFlashTime = 0; + pFlash->iFlashType = type; + pFlash->iFlashSize = size; + + /* Initialize memory to zero */ + if (pFlash->pFlash != NULL) + { + for (c = 0; c < size; c++) + { + pFlash->pFlash[c] = 0xff; + } + } +} + +/* +============================================================================= +amd_flash_read_sm: This routine processes FLASH read events while a timer + is active, such as during a write or erase operation. +============================================================================= +*/ +int amd_flash_read_sm(amd_flash_t *pFlash, unsigned short address) +{ + int index; + + /* The flash is busy during a read - process as State Machine */ + if (pFlash->iFlashBusy && (pFlash->iFlashState == FLASH_STATE_RO)) + { + /* Waiting for timeout of erase / program */ + if (pFlash->iFlashTime > 0) + { + if (cycles + cycle_delta >= pFlash->iFlashTime) + pFlash->iFlashTime = 0; + } + + /* Test if timeout expired */ + if (pFlash->iFlashTime == 0) + { + pFlash->iFlashBusy = FALSE; + return -1; + } + } + else if (pFlash->iFlashState == FLASH_STATE_AUTOSELECT) + { + if ((address & 0xFF) == 0) + return FLASH_MANUF_ID; + else if ((address & 0xFF) == 1) + return FLASH_PRODUCT_ID; + else + return 0; + } + else if (pFlash->iFlashState == FLASH_STATE_CFI_QUERY) + { + /* Test Query address */ + if ((address < 32) || (address > 0x98)) + return 0xFF; + + /* Calculate index for CFI address */ + index = (address - 0x20) >> 1; + return gFlashCFIData[index]; + } + + /* Test for failed command sequence */ + if (pFlash->iFlashState != FLASH_STATE_RO) + { + /* Reset back to read state */ + pFlash->iFlashState = FLASH_STATE_RO; + pFlash->iFlashBusy = FALSE; + pFlash->iFlashTime = 0; + return -1; + } + + return 0xFF; +} + +/* +======================================================================== +amd_flash_proc_timer: This routine processes timed events, such as + write and erase to determine when they are + complete. +======================================================================== +*/ +int amd_flash_proc_timer(amd_flash_t *pFlash) +{ + /* Check if FLASH1 is busy */ + if (pFlash->iFlashTime > 0) + { + if (cycles + cycle_delta >= pFlash->iFlashTime) + { + /* Clear busy bit for Flash1 */ + pFlash->iFlashTime = 0; + pFlash->iFlashBusy = FALSE; + return AMD_ACTION_DEVICE_READY; + } + + return AMD_ACTION_BUSY; } + + return AMD_ACTION_DEVICE_READY; } /* @@ -513,6 +692,12 @@ void init_mem(void) /* Set gReMem and gRampac based on preferences */ gReMem = (mem_setup.mem_mode == SETUP_MEM_REMEM) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC); gRampac = (mem_setup.mem_mode == SETUP_MEM_RAMPAC) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC); + gRex = (mem_setup.mem_mode == SETUP_MEM_REX) ? REX : (mem_setup.mem_mode == SETUP_MEM_REX2) ? REX2 : 0; + if (gRex) + { + gRexModel = REX | gRex; + gReMem = 1; + } gRampacEmulation = 0; gRampacSectPtr = NULL; @@ -533,16 +718,15 @@ void init_mem(void) /* Allocate space for RAM and FLASH */ gReMemRam = malloc(size); - gReMemFlash1 = malloc(size); - gReMemFlash2 = malloc(size); /* Initialize memory to zero */ for (c = 0; c < size; c++) { gReMemRam[c] = 0; - gReMemFlash1[c] = 0; - gReMemFlash2[c] = 0; } + + amd_flash_init(&gReMemFlash1, size, AMD_FLASH_TYPE_REMEM); + amd_flash_init(&gReMemFlash2, size, AMD_FLASH_TYPE_REMEM); } remem_copy_normal_to_system(); @@ -570,6 +754,34 @@ void init_mem(void) gMemory[c] = &gBaseMemory[next++ * 1024]; } + /* Test if Rex emulation enabled */ + if (gRex) + { + /* Allocate memory only if not already allocated */ + if (gRexFlash.pFlash == 0) + { + /* Size of allocation for RAM and FLASH */ + size = 1024 * 1024; + + /* Allocate space for Rex FLASH */ + amd_flash_init(&gRexFlash, size, AMD_FLASH_TYPE_REX); + } + + /* Test if Rex2 enabled and allocate RAM */ + if ((gRex == REX2) && (gRex2Ram == 0)) + { + /* Size of allocation for RAM and FLASH */ + size = 1024 * 128; + + /* Allocate space for Rex2 RAM */ + gRex2Ram = malloc(size); + + /* Initialize memory to zero */ + for (c = 0; c < size; c++) + gRex2Ram[c] = 0; + } + } + /* Test if Rampac emulation enabled */ if (gRampac) { @@ -615,10 +827,25 @@ void reinit_mem(void) memcpy(gBaseMemory,gSysROM,ROMSIZE); } + /* Test if Rex needs to be reinitialized */ + if (gRex) + { + /* Initialize Rex state varialbles */ + gRexState = 7; + gRexFlash.iFlashState = FLASH_STATE_RO; + gRexSector = 0; + gRexKeyState = 0; + } + + // Clear the RAM +// for (x = ROMSIZE; x < 65536; x++) +// set_memory8(x, 0); + gRamBank = 0; gRomBank = 0; } + /* ============================================================================ Clear RAM to emulate a cold-boot based on Memory mode selected. @@ -648,13 +875,13 @@ void free_remem_mem(void) { /* Delete memory allocated for RAM and FLASH */ free(gReMemRam); - free(gReMemFlash1); - free(gReMemFlash2); + free(gReMemFlash1.pFlash); + free(gReMemFlash2.pFlash); /* Set memory pointers to NULL */ gReMemRam = 0; - gReMemFlash1 = 0; - gReMemFlash2 = 0; + gReMemFlash1.pFlash = 0; + gReMemFlash2.pFlash = 0; gReMemMapLower = 0; gReMemMapLower = 0; @@ -675,6 +902,22 @@ void free_rampac_mem(void) gRampacRam = 0; } +/* +======================================================================== +free_rex_mem: This routine frees the memory used by the Rex + emulation and resets the pointers to zero. +======================================================================== +*/ +void free_rex_mem(void) +{ + /* Delete memory allocated for RAM and FLASH */ + if (gRexFlash.pFlash != NULL) + free(gRexFlash.pFlash); + + /* Set memory pointers to NULL */ + gRexFlash.pFlash = 0; +} + /* ======================================================================== free_mem: This routine frees ReMem and/or Rampac memory allocated @@ -690,6 +933,9 @@ void free_mem(void) /* Test if Rampac RAM currently allocated */ if (gRampacRam != 0) free_rampac_mem(); + + if (gRex != 0) + free_rex_mem(); } /* @@ -715,8 +961,8 @@ void save_remem_ram(void) fwrite(gReMemRam, 1, size, fd); /* Now write Flash */ - fwrite(gReMemFlash1, 1, size, fd); - fwrite(gReMemFlash2, 1, size, fd); + fwrite(gReMemFlash1.pFlash, 1, size, fd); + fwrite(gReMemFlash2.pFlash, 1, size, fd); /* Close the file */ fclose(fd); @@ -750,6 +996,63 @@ void save_rampac_ram(void) } } +/* +======================================================================== +save_rex2_ram: This routine saves the Rex2 emulation RAM to the Rex2 + AM file. +======================================================================== +*/ +void save_rex2_ram(void) +{ + FILE *fd; + int size; + + if (gRex != REX2) + return; + + /* Open ReMem file */ + fd = fopen(mem_setup.rex2_ram_file, "wb+"); + + /* Check if file opened successfully */ + if (fd != 0) + { + size = 1024 * 128; /* Copy 256K of RAM + + /* Write ReMem RAM first */ + fwrite(gRex2Ram, 1, size, fd); + + /* Close the file */ + fclose(fd); + } +} + +/* +======================================================================== +save_rex_flash: This routine saves the Rex emulation flash to the Rex + flash file. +======================================================================== +*/ +void save_rex_flash(void) +{ + FILE *fd; + int size; + + /* Open ReMem file */ + fd = fopen(mem_setup.rex_flash_file, "wb+"); + + /* Check if file opened successfully */ + if (fd != 0) + { + size = 1024 * 1024; /* Copy 1 Meg of flash + + /* Write ReMem RAM first */ + fwrite(gRexFlash.pFlash, 1, size, fd); + + /* Close the file */ + fclose(fd); + } +} + /* ======================================================================== save_ram: This routine saves the contens of the RAM after @@ -769,7 +1072,7 @@ void save_ram(void) FILE *fd; /* Check if ReMem emulation enabled or Base Memory emulation */ - if (gReMem) + if (gReMem & !gRex) { save_remem_ram(); /* Save ReMem data to file */ } @@ -836,6 +1139,17 @@ void save_ram(void) { save_rampac_ram(); /* Save Rampac RAM to file */ } + + /* + =========================================== + Save Rex Flash & RAM if enabled + =========================================== + */ + if (gRex) + { + save_rex_flash(); /* Save the flash */ + save_rex2_ram(); /* Save Rex2 RAM to file */ + } } /* @@ -854,7 +1168,7 @@ void load_remem_ram(void) fd = fopen(mem_setup.remem_file, "rb+"); /* Check if file opened successfully */ - if (fd != 0) + if ((fd != 0) && (gReMemFlash1.pFlash != NULL) && (gReMemFlash2.pFlash != NULL)) { size = 1024 * 2048; /* Copy 2 meg of RAM & FLASH */ @@ -862,35 +1176,38 @@ void load_remem_ram(void) fread(gReMemRam, 1, size, fd); /* Now read Flash */ - fread(gReMemFlash1, 1, size, fd); - fread(gReMemFlash2, 1, size, fd); + fread(gReMemFlash1.pFlash, 1, size, fd); + fread(gReMemFlash2.pFlash, 1, size, fd); /* Close the file */ fclose(fd); /* Now update the VirtualT version if needed */ - patch_vt_version(gReMemFlash1, ROMSIZE); + patch_vt_version(gReMemFlash1.pFlash, ROMSIZE); } /* Test if ReMem FLASH "Normal" region is empty */ - for (x = 0; x < 10; x++) + if (gReMemFlash1.pFlash != NULL) { - /* Check for any non-zero bytes in normal ROM area */ - if (gReMemFlash1[x] != 0) - empty = 0; + for (x = 0; x < 10; x++) + { + /* Check for any non-zero bytes in normal ROM area */ + if (gReMemFlash1.pFlash[x] != 0) + empty = 0; + } } if (empty) { /* Rom area is empty - initialize with SYSROM */ for (x = 0; x < ROMSIZE; x++) - gReMemFlash1[x] = gSysROM[x]; + gReMemFlash1.pFlash[x] = gSysROM[x]; } /* Initalize MsplanROM area */ if (gModel == MODEL_T200) for (x = 0; x < sizeof(gMsplanROM); x++) - gReMemFlash1[0x10000 + x] = gMsplanROM[x]; + gReMemFlash1.pFlash[0x10000 + x] = gMsplanROM[x]; } void reload_sys_rom(void) @@ -898,7 +1215,7 @@ void reload_sys_rom(void) int x; for (x = 0; x < ROMSIZE; x++) - gReMemFlash1[x] = gSysROM[x]; + gReMemFlash1.pFlash[x] = gSysROM[x]; } /* @@ -928,6 +1245,65 @@ void load_rampac_ram(void) } } +/* +======================================================================== +load_rex_flash: This routine loads the Rex emulation flash from the + Rex flash file. +======================================================================== +*/ +void load_rex_flash(void) +{ + FILE *fd; + int size; + int empty = 1; + + /* Open ReMem file */ + fd = fopen(mem_setup.rex_flash_file, "rb+"); + + /* Check if file opened successfully */ + if ((fd != 0) && (gRexFlash.pFlash != NULL)) + { + size = 1024 * 1024; /* Copy 1 meg of FLASH + + /* Read Rex Flash first */ + fread(gRexFlash.pFlash, 1, size, fd); + + /* Close the file */ + fclose(fd); + + /* Now update the VirtualT version if needed */ + patch_vt_version(gRexFlash.pFlash, ROMSIZE); + } +} + +/* +======================================================================== +load_rex2_ram: This routine loads the Rex2 emulation RAM from the + Rex2 RAM file. +======================================================================== +*/ +void load_rex2_ram(void) +{ + FILE *fd; + int size; + int empty = 1; + + /* Open ReMem file */ + fd = fopen(mem_setup.rex2_ram_file, "rb+"); + + /* Check if file opened successfully */ + if (fd != 0) + { + size = 1024 * 128; /* Copy 128K of RAM + + /* Read Rex2 RAM */ + fread(gRex2Ram, 1, size, fd); + + /* Close the file */ + fclose(fd); + } +} + /* ======================================================================== load_ram: This routine loads the contens of the RAM in preparation @@ -948,8 +1324,9 @@ void load_ram(void) int x; /* Check if ReMem emulation enabled or Base Memory emulation */ - if (gReMem) + if (gReMem & !gRex) { + /* In ReMem mode - load RAM */ load_remem_ram(); /* Call routine to load ReMem */ remem_copy_normal_to_system(); } @@ -1035,9 +1412,22 @@ void load_ram(void) { load_rampac_ram(); /* Call routine to load Rampac */ } -} -/* + /* + =========================================== + Load Rex Flash and RAM if enabled + =========================================== + */ + if (gRex) + { + /* Load Rex Flash and RAM if needed */ + load_rex_flash(); + if (gRex == REX2) + load_rex2_ram(); + } +} + +/* ============================================================================= patch_vt_version: This function patches the VirtualT verison in the ROM memory space specified. It searches for M**soft and @@ -1074,7 +1464,7 @@ void patch_vt_version(char* pMem, int size) address = gStdRomDesc->sMSCopyright; /* Check if the address contains a (possibly previous version) VT string */ - if (strncmp((char*) &pMem[address], "VirtualT", strlen("VirtualT")) == 0) + if (strncmp((char*) &pMem[address], "VirtualT ", strlen("VirtualT ")) == 0) found = TRUE; /* Check if the copyright string is where we expect it to be */ @@ -1098,7 +1488,7 @@ void patch_vt_version(char* pMem, int size) break; } /* Search for VirtualT string */ - if (strncmp((char*) &pMem[c], "VirtualT", strlen("VirtualT")) == 0) + if (strncmp((char*) &pMem[c], "VirtualT ", strlen("VirtualT ")) == 0) { address = (unsigned short) c; break; @@ -1208,10 +1598,10 @@ void load_opt_rom(void) { if (gModel == MODEL_T200) for (c = 0; c < len; c++) - gReMemFlash1[0x18000 + c] = buf[c]; + gReMemFlash1.pFlash[0x18000 + c] = buf[c]; else for (c = 0; c < len; c++) - gReMemFlash1[0x8000 + c] = buf[c]; + gReMemFlash1.pFlash[0x8000 + c] = buf[c]; } } @@ -1229,10 +1619,10 @@ void load_opt_rom(void) { if (gModel == MODEL_T200) for (c = 0; c < OPTROMSIZE; c++) - gReMemFlash1[0x18000 + c] = gOptROM[c]; + gReMemFlash1.pFlash[0x18000 + c] = gOptROM[c]; else for (c = 0; c < OPTROMSIZE; c++) - gReMemFlash1[0x8000 + c] = gOptROM[c]; + gReMemFlash1.pFlash[0x8000 + c] = gOptROM[c]; } } } @@ -1248,7 +1638,7 @@ void set_ram_bank(unsigned char bank) { int block; - if (!gReMem) + if (!(gReMem && !gRex)) { /* Deal with Non-Remem Banks */ switch (gModel) @@ -1318,7 +1708,7 @@ void set_rom_bank(unsigned char bank) { int block, blocks; - if (!gReMem) + if (!(gReMem && !gRex)) { /* Deal with non-ReMem emulation */ switch (gModel) @@ -1428,6 +1818,249 @@ void set_rom_bank(unsigned char bank) } } +/* +============================================================================= +amd_flash_write: This function processes 8-bit write operatsions to the + AMD flash and manages portions of the FLASH state machine + for controlling Erase Read Only modes, etc. +============================================================================= +*/ +int amd_flash_write(amd_flash_t *pFlash, unsigned int address, unsigned char data) +{ + int sectOffset; + int sectSize, c; + int sector; + int retval = AMD_ACTION_RESET; + char *ptr; + + /* Look for Reset command. If it's reset, set the FLASH to Read Only mode and clear BUSY */ + if ((data == FLASH_CMD_RESET) && (pFlash->iFlashState != FLASH_STATE_PROG)) + { + pFlash->iFlashState = FLASH_STATE_RO; + pFlash->iFlashTime = 0; + pFlash->iFlashBusy = FALSE; + return AMD_ACTION_RESET; + } + + /* Switch on the current flash state and operate on data appropriatey */ + switch (pFlash->iFlashState) + { + case FLASH_STATE_RO: + /* Proocess write as command */ + if ((data == FLASH_CMD_CFI_QUERY) && (address == 0xAA)) + { + pFlash->iFlashState = FLASH_STATE_CFI_QUERY; + pFlash->iFlashBusy = TRUE; + } + + /* Test for transition to UNLK1 State */ + else if ((data == 0xAA) && ((address & 0xFF) == 0xAA)) + pFlash->iFlashState = FLASH_STATE_UNLK1; + + retval = AMD_ACTION_CMD; + break; + + case FLASH_STATE_UNLK1: + // Check for 2nd byte of unlock sequence + if ((data == 0x55) && ((address & 0xFF) == 0x55)) + pFlash->iFlashState = FLASH_STATE_CMD; + else + pFlash->iFlashState = FLASH_STATE_RO; + retval = AMD_ACTION_CMD; + break; + + case FLASH_STATE_UNLK2: + // Get 1st byte of 2nd Unlock + if ((data == 0xAA) && ((address & 0xFF) == 0xAA)) + pFlash->iFlashState = FLASH_STATE_UNLK3; + else + pFlash->iFlashState = FLASH_STATE_RO; + retval = AMD_ACTION_CMD; + break; + + case FLASH_STATE_UNLK3: + // Check for double unlock 2nd byte + if ((data == 0x55) && ((address & 0xFF) == 0x55)) + pFlash->iFlashState = FLASH_STATE_CMD2; + else + pFlash->iFlashState = FLASH_STATE_RO; + retval = AMD_ACTION_CMD; + break; + + case FLASH_STATE_UNLK_BYPASS: + /* We are in Unlock Bypass mode. We only accept 0xA0 and 0x90 in this mode */ + /* Test for transition to program state */ + if (data == FLASH_CMD_PROG) + pFlash->iFlashState = FLASH_STATE_UB_PROG; + else if (data == FLASH_CMD_AUTOSELECT) + pFlash->iFlashState = FLASH_STATE_UB_EXIT; + retval = AMD_ACTION_CMD; + break; + + case FLASH_STATE_UB_EXIT: + /* Look for 2nd byte of exit sequence from Unlock Bypass */ + if (data == 0) + { + pFlash->iFlashState = FLASH_STATE_RO; + } + else + { + pFlash->iFlashState = FLASH_STATE_UNLK_BYPASS; + } + retval = AMD_ACTION_CMD; + break; + + case FLASH_STATE_UB_PROG: + /* Program in Unlock Bypass mode. Allow write and go back to UNLK_BYPASS state */ + pFlash->iFlashState = FLASH_STATE_UNLK_BYPASS; + pFlash->iFlashBusy = TRUE; + pFlash->iFlashTime = cycles + cycle_delta + FLASH_CYCLES_PROG; + + /* May need to add code here to write to the FLASH */ + if (pFlash->iFlashType == AMD_FLASH_TYPE_REX) + { + /* Write data to the flash */ + pFlash->pFlash[address] &= data; + + /* If trying to change a 1 to a 0, then go to BUSY until reset */ + if (pFlash->pFlash[address] != data) + pFlash->iFlashBusy = TRUE; + } + + retval = AMD_ACTION_ALLOW_WRITE; + break; + + + case FLASH_STATE_PROG: + /* Change state back to Read Only and return code indicating write allowed */ + pFlash->iFlashState = FLASH_STATE_RO; + pFlash->iFlashBusy = TRUE; + pFlash->iFlashTime = cycles + cycle_delta + FLASH_CYCLES_PROG; + + /* May need to add code here to write to the FLASH */ + if (pFlash->iFlashType == AMD_FLASH_TYPE_REX) + { + /* Write data to the flash */ + pFlash->pFlash[address] &= data; + + /* If trying to change a 1 to a 0, then go to BUSY until reset */ + if (pFlash->pFlash[address] != data) + pFlash->iFlashBusy = TRUE; + } + + retval = AMD_ACTION_ALLOW_WRITE; + break; + + case FLASH_STATE_CMD: + if ((address & 0xFF) == 0xAA) + { + // Get the command + if (data == FLASH_CMD_PROG) + pFlash->iFlashState = FLASH_STATE_PROG; + else if (data == FLASH_CMD_UNLK_BYPASS) + pFlash->iFlashState = FLASH_STATE_UNLK_BYPASS; + else if (data == FLASH_CMD_UNLK2) + pFlash->iFlashState = FLASH_STATE_UNLK2; + else if (data == FLASH_CMD_AUTOSELECT) + pFlash->iFlashState = FLASH_STATE_AUTOSELECT; + else + pFlash->iFlashState = FLASH_STATE_RO; + } + else + { + pFlash->iFlashState = FLASH_STATE_RO; + retval = AMD_ACTION_RESET; + break; + } + retval = AMD_ACTION_CMD; + break; + + case FLASH_STATE_CMD2: + // Test for Erase Chip command + if ((data == FLASH_CMD_CHIP_ERASE) && ((address & 0xFF) == 0xAA)) + { + pFlash->iFlashState = FLASH_STATE_RO; + pFlash->iFlashTime = cycles + cycle_delta + FLASH_CYCLES_CHIP_ERASE; + pFlash->iFlashBusy = TRUE; + + /* Erase the Flash */ + ptr = pFlash->pFlash; + for (c = 0; c < 2048 * 1024; c++) + *ptr++ = 0xFF; + + retval = AMD_ACTION_ERASING; + break; + } + + /* Test if data is a Sect Erase command */ + else if (data != FLASH_CMD_SECT_ERASE) + { + pFlash->iFlashState = FLASH_STATE_RO; + retval = AMD_ACTION_RESET; + break; + } + + /* Process Sector erase */ + sector = address >> 16; + + /* Calculate sector offset and size */ + if (sector == 0) + { + /* Test for sector zero */ + if ((address & 0xFFC000) == 0) + { + /* Sector zero is 16K */ + sectOffset = 0; + sectSize = 16384; + } + else if ((address & 0xFF8000) != 0) + { + /* Sector 3 is a 32K sector */ + sectOffset = 0x8000; + sectSize = 32768; + } + else + { + sectOffset = address & 0xFFF000; + sectSize = 8192; + } + } + else + { + /* Setup for 64K sector */ + sectOffset = address & 0xFF0000; + sectSize = 0x10000; + } + + /* Point to the correct memory space */ + ptr = pFlash->pFlash + sectOffset; + + /* Erase the sector */ + for (c = 0; c < sectSize; c++) + *ptr++ = 0xFF; + + /* Update state and set busy flag */ + pFlash->iFlashState = FLASH_STATE_RO; + pFlash->iFlashBusy = TRUE; + pFlash->iFlashTime = cycles + cycle_delta + FLASH_CYCLES_SECT_ERASE; + retval = AMD_ACTION_ERASING; + break; + + case FLASH_STATE_CHIP_ERASE: + case FLASH_STATE_SECT_ERASE: + retval = AMD_ACTION_BUSY; + + default: + pFlash->iFlashState = FLASH_STATE_RO; + pFlash->iFlashTime = 0; + pFlash->iFlashBusy = FALSE; + retval = AMD_ACTION_RESET; + break; + } + + return retval; +} + /* ============================================================================= remem_set8: This function services memory writes while in ReMem emulation @@ -1444,10 +2077,6 @@ void remem_set8(unsigned int address, unsigned char data) int bank; /* Bank with map that is being modified */ int romBank; /* The currently mapped romBank within the Map */ int ramBank; /* The currently mapped ramBank within the Map */ - int sectOffset; - int sectSize, c; - int sector; - uchar *ptr; /* Calculate which block is being accessed */ block = gIndex[address]; @@ -1504,119 +2133,48 @@ void remem_set8(unsigned int address, unsigned char data) /* Do FLASH state machine management */ if ((gReMemMode & REMEM_MODE_NORMAL) && - (gReMemMap[block] & (REMEM_VCTR_FLASH1_CS | REMEM_VCTR_FLASH2_CS)) != 0x1800) + ((gReMemMap[block] & (REMEM_VCTR_FLASH1_CS | REMEM_VCTR_FLASH2_CS)) != 0x1800)) { - int *pFlashState; - UINT64 *pFlashTime; - int *pFlashBusy; - uchar mask; + amd_flash_t *pFlash; + uchar mask; + int iFlashAction; + unsigned int flashAddress; /* Writing to FLASH. Do FLASH State machine processing */ if (!(gReMemMap[block] & REMEM_VCTR_FLASH1_CS)) { - pFlashState = &gReMemFlash1State; - pFlashTime = &gReMemFlash1Time; - pFlashBusy = &gReMemFlash1Busy; + pFlash = &gReMemFlash1; mask = REMEM_MODE_FLASH1_RDY; } else { - pFlashState = &gReMemFlash2State; - pFlashTime = &gReMemFlash2Time; - pFlashBusy = &gReMemFlash2Busy; + pFlash = &gReMemFlash2; mask = REMEM_MODE_FLASH2_RDY; } - /* Look for Reset command */ - if ((data == FLASH_CMD_RESET) && (*pFlashState != FLASH_STATE_PROG)) - { - *pFlashState = FLASH_STATE_RO; - *pFlashTime = 0; - *pFlashBusy = FALSE; - gReMemFlashReady = !gReMemFlash1Busy | !gReMemFlash2Busy; - return; - } + /* Call into the amd_flash_t object and issue the write. Let the amd_flash_t + state manager take care of state transitions within the FALSH + */ + flashAddress = ((gReMemMap[block] & REMEM_VCTR_ADDRESS) << 10) + (address & 0x3FF); + iFlashAction = amd_flash_write(pFlash, flashAddress, data); - switch (*pFlashState) + /* If the amd_flash indicates a write is allowd, or that an erase is in progress */ + /* then update our global ReMemMode variable to indicate FLASH not ready. */ + if ((iFlashAction == AMD_ACTION_ALLOW_WRITE) || (iFlashAction == AMD_ACTION_ERASING)) { - case FLASH_STATE_RO: - /* Proocess write as command */ - if ((data == FLASH_CMD_CFI_QUERY) && (address == 0xAA)) - { - *pFlashState = FLASH_STATE_CFI_QUERY; - *pFlashBusy = TRUE; - gReMemFlashReady = FALSE; - } - return; - - case FLASH_STATE_PROG: - /* Change state back to Read Only and break to perform the write */ - *pFlashState = FLASH_STATE_RO; - *pFlashBusy = TRUE; - *pFlashTime = cycles + FLASH_CYCLES_PROG; gReMemMode &= ~mask; - gReMemFlashReady = FALSE; - break; - - case FLASH_STATE_CMD2: - /* Test if data is a Sect Erase command */ - if (data != FLASH_CMD_SECT_ERASE) - { - *pFlashState = FLASH_STATE_RO; - return; - } - /* Process Sector erase */ - sector = address >> 15; - - /* Calculate sector offset and size */ - if (sector == 0) - { - /* Test for sector zero */ - if ((address & 0xFE000) == 0) - { - /* Sector zero is 16K */ - sectOffset = 0; - sectSize = 16384; - } - else if ((address & 0xFC00) != 0) - { - /* Sector 3 is a 32K sector */ - sectOffset = 0x4000; - sectSize = 32768; - } - else - { - sectOffset = address & 0xFF000; - sectSize = 8192; - } - } - else - { - /* Setup for 64K sector */ - sectOffset = address & 0xF8000; - sectSize = 0x10000; - } - - /* Point to the correct memory space */ - if (pFlashState == &gReMemFlash1State) - ptr = gReMemFlash1 + sectOffset; - else - ptr = gReMemFlash2 + sectOffset; - - /* Erase the sector */ - for (c = 0; c < sectSize; c++) - *ptr++ = 0xFF; - - /* Update state and set busy flag */ - *pFlashState = FLASH_STATE_RO; - *pFlashBusy = TRUE; - *pFlashTime = cycles + FLASH_CYCLES_SECT_ERASE; - gReMemMode &= ~mask; + /* Set our local FlashReady variable to FALSE so we know flash is busy */ gReMemFlashReady = FALSE; + } + /* If writing to FLASH is allowed, then break to allow write to global memory */ + if (iFlashAction != AMD_ACTION_ALLOW_WRITE) + { + /* Writes to memory not allowed ... return */ return; } + gMemory[block][address & 0x3FF] = data; } /* Update memory with data */ @@ -1735,9 +2293,8 @@ int remem_out(unsigned char port, unsigned char data) int romSector, ramSector; int bank, block, mmuBlock; int map; - int *pFlashState; - uchar *ptr; - int c; + amd_flash_t *pFlash; + int action; /* Test if ReMem emulation is enabled */ if (!(gReMem | gRampac)) @@ -2009,105 +2566,53 @@ int remem_out(unsigned char port, unsigned char data) case REMEM_FLASH1_AAA_PORT: case REMEM_FLASH2_AAA_PORT: if (port == REMEM_FLASH1_AAA_PORT) - pFlashState = &gReMemFlash1State; + pFlash = &gReMemFlash1; else - pFlashState = &gReMemFlash2State; + pFlash = &gReMemFlash2; - switch (*pFlashState) - { - case FLASH_STATE_RO: - if (data == 0xAA) - *pFlashState = FLASH_STATE_UNLK1; - - // Check for other states, such as Erase Pause, etc. + /* Simulate a write to address 0xAA */ + action = amd_flash_write(pFlash, 0xAA, data); - break; - - case FLASH_STATE_CMD: - // Get the command - if (data == FLASH_CMD_PROG) - *pFlashState = FLASH_STATE_PROG; - else if (data == FLASH_CMD_UNLK_BYPASS) - *pFlashState = FLASH_STATE_UNLK_BYPASS; - else if (data == FLASH_CMD_UNLK2) - *pFlashState = FLASH_STATE_UNLK2; - else if (data == FLASH_CMD_AUTOSELECT) - *pFlashState = FLASH_STATE_AUTOSELECT; - else - *pFlashState = FLASH_STATE_RO; - break; - - case FLASH_STATE_UNLK2: - // Get 1st byte of 2nd Unlock - if (data == 0xAA) - *pFlashState = FLASH_STATE_UNLK3; + if ((action == AMD_ACTION_ERASING) || (action == AMD_ACTION_ALLOW_WRITE)) + { + if (port == REMEM_FLASH1_AAA_PORT) + { + gReMemMode &= ~REMEM_MODE_FLASH1_RDY; + } else - *pFlashState = FLASH_STATE_RO; - break; - - case FLASH_STATE_CMD2: - // Test for Erase Chip command - if (data == FLASH_CMD_CHIP_ERASE) { - *pFlashState = FLASH_STATE_RO; - if (port == REMEM_FLASH1_AAA_PORT) - { - gReMemFlash1Time = cycles + FLASH_CYCLES_CHIP_ERASE; - gReMemMode &= ~REMEM_MODE_FLASH1_RDY; - gReMemFlashReady = FALSE; - gReMemFlash1Busy = TRUE; - ptr = gReMemFlash1; - } - else - { - gReMemFlash2Time = cycles + FLASH_CYCLES_CHIP_ERASE; - gReMemMode &= ~REMEM_MODE_FLASH2_RDY; - gReMemFlashReady = FALSE; - gReMemFlash2Busy = TRUE; - ptr = gReMemFlash2; - } - /* Erase the Flash */ - for (c = 0; c < 2048 * 1024; c++) - *ptr++ = 0xFF; + gReMemMode &= ~REMEM_MODE_FLASH2_RDY; } - break; - default: - *pFlashState = FLASH_STATE_RO; - break; + /* Set our local FlashReady variable to FALSE so we know flash is busy */ + gReMemFlashReady = FALSE; } break; case REMEM_FLASH1_555_PORT: case REMEM_FLASH2_555_PORT: if (port == REMEM_FLASH1_555_PORT) - pFlashState = &gReMemFlash1State; + pFlash = &gReMemFlash1; else - pFlashState = &gReMemFlash2State; + pFlash = &gReMemFlash2; - switch (*pFlashState) - { - case FLASH_STATE_UNLK1: - // Check for 2nd byte of unlock sequence - if (data == 0x55) - *pFlashState = FLASH_STATE_CMD; - else - *pFlashState = FLASH_STATE_RO; - break; + /* Write to the FLASH and let it manage the state machine */ + action = amd_flash_write(pFlash, 0x55, data); - case FLASH_STATE_UNLK3: - // Check for double unlock 2nd byte - if (data == 0x55) - *pFlashState = FLASH_STATE_CMD2; + if ((action == AMD_ACTION_ERASING) || (action == AMD_ACTION_ALLOW_WRITE)) + { + if (port == REMEM_FLASH1_AAA_PORT) + { + gReMemMode &= ~REMEM_MODE_FLASH1_RDY; + } else - *pFlashState = FLASH_STATE_RO; - break; + { + gReMemMode &= ~REMEM_MODE_FLASH2_RDY; + } - default: - *pFlashState = FLASH_STATE_RO; - break; + /* Set our local FlashReady variable to FALSE so we know flash is busy */ + gReMemFlashReady = FALSE; } - break; /* Other Ports not supported */ @@ -2206,9 +2711,10 @@ void remem_copy_normal_to_system(void) /* First copy ROM to system memory */ blocks = gModel == MODEL_T200 ? 40 : 32; if (gModel != MODEL_T200) - pSrc = (gReMemBoot ? gReMemFlash2 : gReMemFlash1) + 0x8000 * gRomBank; + pSrc = (gReMemBoot ? gReMemFlash2.pFlash : gReMemFlash1.pFlash) + 0x8000 * gRomBank; else - pSrc = (gReMemBoot ? gReMemFlash2 : gReMemFlash1) + (gRomBank == 0 ? 0 : 0x10000 + 0x8000 * (gRomBank - 1)); + pSrc = (gReMemBoot ? gReMemFlash2.pFlash : gReMemFlash1.pFlash) + (gRomBank == 0 ? 0 : + 0x10000 + 0x8000 * (gRomBank - 1)); dest = 0; /* Copy the ROM bytes */ @@ -2258,9 +2764,9 @@ void remem_copy_mmu_to_block(int block) if ((gReMemMap[block] & REMEM_VCTR_RAM_CS) == 0) pSrc = gReMemRam; else if ((gReMemMap[block] & REMEM_VCTR_FLASH1_CS) == 0) - pSrc = gReMemFlash1; + pSrc = gReMemFlash1.pFlash; else if ((gReMemMap[block] & REMEM_VCTR_FLASH2_CS) == 0) - pSrc = gReMemFlash2; + pSrc = gReMemFlash2.pFlash; else return; @@ -2282,11 +2788,9 @@ remem_flash_sm_read: This routine performs a read operation when there is unsigned char remem_flash_sm_read(unsigned short address) { int block; - int *pFlashState; - UINT64 *pFlashTime; - int *pFlashBusy; + amd_flash_t *pFlash; unsigned char mask; - int index; + int action; /* Calculate block number */ block = address >> 10; @@ -2294,75 +2798,29 @@ unsigned char remem_flash_sm_read(unsigned short address) /* Test if this is the flash that is not ready */ if ((gReMemMap[block] & REMEM_VCTR_FLASH1_CS) == 0) { - if (!gReMemFlash1Busy && (gReMemFlash1State == FLASH_STATE_RO)) + if (!gReMemFlash1.iFlashBusy && (gReMemFlash1.iFlashState == FLASH_STATE_RO)) return gMemory[block][address & 0x3FF]; /* Set variables for state machine processing */ - pFlashState = &gReMemFlash1State; - pFlashTime = &gReMemFlash1Time; - pFlashBusy = &gReMemFlash1Busy; + pFlash = &gReMemFlash1; mask = REMEM_MODE_FLASH1_RDY; } else { - if (!gReMemFlash2Busy && (gReMemFlash2State == FLASH_STATE_RO)) + if (!gReMemFlash2.iFlashBusy && (gReMemFlash2.iFlashState == FLASH_STATE_RO)) return gMemory[block][address & 0x3FF]; /* Set variables for state machine processing */ - pFlashState = &gReMemFlash2State; - pFlashTime = &gReMemFlash2Time; - pFlashBusy = &gReMemFlash2Busy; + pFlash = &gReMemFlash2; mask = REMEM_MODE_FLASH2_RDY; } - /* The flash is busy during a read - process as State Machine */ - if (*pFlashBusy && (*pFlashState == FLASH_STATE_RO)) - { - /* Waiting for timeout of erase / program */ - if (*pFlashTime > 0) - { - if (cycles >= *pFlashTime) - *pFlashTime = 0; - } + action = amd_flash_read_sm(pFlash, address); - /* Test if timeout expired */ - if (*pFlashTime == 0) - { - *pFlashBusy = FALSE; - gReMemFlashReady = !gReMemFlash1Busy | !gReMemFlash2Busy; - gReMemMode |= mask; - return gMemory[block][address & 0x3FF]; - } - } - else if (*pFlashState == FLASH_STATE_AUTOSELECT) - { - if ((address & 0xFF) == 0) - return FLASH_MANUF_ID; - else if ((address & 0xFF) == 1) - return FLASH_PRODUCT_ID; - else - return 0; - } - else if (*pFlashState == FLASH_STATE_CFI_QUERY) + if (action == -1) { - /* Test Query address */ - if ((address < 32) || (address > 0x98)) - return 0xFF; - - /* Calculate index for CFI address */ - index = (address - 0x20) >> 1; - return gFlashCFIData[index]; - } - - /* Test for failed command sequence */ - if (*pFlashState != FLASH_STATE_RO) - { - /* Reset back to read state */ - *pFlashState = FLASH_STATE_RO; + gReMemFlashReady = !gReMemFlash1.iFlashBusy | !gReMemFlash2.iFlashBusy; gReMemMode |= mask; - *pFlashBusy = FALSE; - *pFlashTime = 0; - gReMemFlashReady = !gReMemFlash1Busy | !gReMemFlash2Busy; return gMemory[block][address & 0x3FF]; } @@ -2377,53 +2835,185 @@ remem_flash_proc_timer: This routine processes FLASH timers. void remem_flash_proc_timer(void) { /* Check if FLASH1 is busy */ - if (gReMemFlash1Time > 0) + if (amd_flash_proc_timer(&gReMemFlash1) == AMD_ACTION_DEVICE_READY) { - if (cycles >= gReMemFlash1Time) - { - /* Clear busy bit for Flash1 */ - gReMemMode |= REMEM_MODE_FLASH1_RDY; - gReMemFlash1Time = 0; - gReMemFlash1Busy = FALSE; - } + /* Clear busy bit for Flash1 */ + gReMemMode |= REMEM_MODE_FLASH1_RDY; } /* Check if FLASH2 is busy */ - if (gReMemFlash2Time > 0) + if (amd_flash_proc_timer(&gReMemFlash2) == AMD_ACTION_DEVICE_READY) { - if (cycles >= gReMemFlash2Time) - { - /* Clear busy bit for Flash1 */ - gReMemMode |= REMEM_MODE_FLASH2_RDY; - gReMemFlash2Time = 0; - gReMemFlash2Busy = FALSE; - } + /* Clear busy bit for Flash1 */ + gReMemMode |= REMEM_MODE_FLASH2_RDY; } /* Check if either flash is busy */ - if (gReMemFlash1Busy || gReMemFlash2Busy) + if (gReMemFlash1.iFlashBusy || gReMemFlash2.iFlashBusy) gReMemFlashReady = FALSE; else gReMemFlashReady = TRUE; } - -void rex_set8(unsigned short address, unsigned char val) +/* +============================================================================= +rex_read: This routine processes reads during REX emulation mode. +============================================================================= +*/ +unsigned char rex_read(unsigned short address) { -} + /* Reads from primary ROM are processed as usual */ + if ((gRomBank == 0) || ((gRomBank == 1) && (gModel == MODEL_T200))) + { + return gBaseMemory[address]; + } + else + { + if (address & 0x8000) + return gBaseMemory[address]; + } -void load_rex2_ram(void) -{ -} + // If the RexFlash is busy, we need to process the timer + if (gRexFlash.iFlashTime > 0) + amd_flash_proc_timer(&gRexFlash); -void save_rex2_ram(void) -{ -} + // Process read as a REX State machine read + switch (gRexState) + { + case 7: /* Read State */ + if ((address & 0xFF) == gRexKeyTable[gRexKeyState]) + { + if (++gRexKeyState == 6) + { + /* Key sequence detected - switch to state zero */ + gRexState = 0; + } + } + else + /* Key state not detected - clear keystate */ + gRexKeyState = 0; + return gRexFlash.pFlash[gRexSector | address]; -void load_rex_flash(void) -{ + case 0: /* Command mode */ + switch (address & 0x07) + { + case 3: /* Read Status CMD */ + gRexReturn =(gRexFlash.iFlashBusy ? 0 : 0x80) | + (gRexFlashSel ? 0x40 : 0) | + (gRexSector >> 15); + gRexState = address & 0x07; + return gRexReturn; + + case 1: /* Set Sector CMD */ + case 2: /* Send AAA,AA CMD */ + case 4: /* Read from flash */ + case 5: /* Send 555,55 CMD */ + case 6: /* Send PA, PD */ + gRexState = address & 0x07; + gRexFlashPA = address & 0xFF; + break; + + case 7: /* Read FW/HW ID */ + gRexReturn = (gRex == REX2 ? 0x40 : 0) | + (0x10) | gRexModel; + gRexState = 3; + return gRexReturn; + + default: + gRexState = 7; + break; + } + break; + + case 1: /* Set Sector state */ + /* Test if RAM mode is enabled and set sector based on result */ + if (gModel && REX2_RAM_MODE) + gRexSector = (address & 0x3F) << 15; + else + gRexSector = (address & 0x1F) << 15; + + /* Save Flash Select bit */ + gRexFlashSel = address & 0x40 ? 0 : 1; + + /* Back to state 0 for next command */ + gRexState = 0; + break; + + case 2: /* Send AAA, AD to Flash */ + /* Write to the REX Flash object. LSB of address is actually data */ + amd_flash_write(&gRexFlash, gRexSector | gRexFlashPA, address & 0xFF); + + /* Back to state 0 for next command */ + gRexState = 0; + break; + + case 3: + /* Switch back to state 0 */ + gRexState = 0; + return gRexReturn; + + case 4: /* Read from flash */ + /* Test if reading from RAM sector */ + gRexState = 8; /* Holding state */ + + /* Read from either RAM for Flash */ + if (gRexSector & 0x100000) + { + /* Read from RAM if REX2 */ + if (gRex == REX2) + gRexReturn = gRex2Ram[(gRexSector & 0x18000) | (address & 0x7FFF)]; + else + gRexReturn = 0xFF; + } + else + { + /* Read from Flash if enabled */ + if (gRexFlashSel) + gRexReturn = gRexFlash.pFlash[gRexSector | (address & 0x7FFF)]; + else + gRexReturn = 0xFF; + } + return gRexReturn; + + case 8: /* Temp holding state for state 4 */ + gRexState = 0; /* Back to state 0 */ + return gRexReturn; + + case 5: /* Send 555,data to flash */ + gRexState = 0; /* Back to state 0 */ + + /* Send 555,data to flash */ + amd_flash_write(&gRexFlash, 0x55, 0x55); + + break; + + case 6: /* Send PA,PD to flash, first we receive PA */ + /* Save the address from this read as our Flash PA */ + gRexFlashPA = address & 0x7FFF; + + /* Go to State 2 to await the data */ + gRexState = 2; + break; + } + return (unsigned char) (address & 0xFF); } -void save_rex_flash(void) +/* +============================================================================= +rex_set8: This routine processes writes during REX emulation mode. +============================================================================= +*/ +void rex_set8(unsigned short address, unsigned char val) { + if (address >= ROMSIZE) + gBaseMemory[address] = val; + else + { + if (gRex == REX2) + { + /* Add logic here to write to the selected RAM sector */ + gBaseMemory[address] = val; + } + } } + diff --git a/src/memory.h b/src/memory.h index 407e115..24b6aa6 100644 --- a/src/memory.h +++ b/src/memory.h @@ -75,6 +75,7 @@ extern "C" { #define FLASH_STATE_CMD2 10 #define FLASH_STATE_CFI_QUERY 11 #define FLASH_STATE_AUTOSELECT 12 +#define FLASH_STATE_UB_EXIT 13 #define FLASH_CMD_PROG 0xA0 #define FLASH_CMD_UNLK_BYPASS 0x20 @@ -114,12 +115,24 @@ extern "C" { #include "gen_defs.h" typedef struct { - int gFlashState; - UINT64 gFlashTime; - int gFlashBusy; + int iFlashState; + UINT64 iFlashTime; + int iFlashBusy; char* pFlash; + int iFlashType; + int iFlashSize; } amd_flash_t; +#define AMD_ACTION_RESET 0 +#define AMD_ACTION_ALLOW_WRITE 1 +#define AMD_ACTION_CMD 2 +#define AMD_ACTION_ERASING 3 +#define AMD_ACTION_DEVICE_READY 4 +#define AMD_ACTION_BUSY 5 + +#define AMD_FLASH_TYPE_REMEM 1 +#define AMD_FLASH_TYPE_REX 2 + extern unsigned char *gMemory[64]; extern unsigned char gSysROM[65536]; extern unsigned char gOptROM[32768]; diff --git a/src/multieditwin.cpp b/src/multieditwin.cpp index 7984d26..eab1bdf 100644 --- a/src/multieditwin.cpp +++ b/src/multieditwin.cpp @@ -41,13 +41,45 @@ #include #include +#include "FLU/Flu_File_Chooser.h" + #include "VirtualT.h" #include "m100emu.h" #include "multieditwin.h" +#include "highlight.h" +#include "idetabs.h" extern MString gRootpath; - -IMPLEMENT_DYNCREATE(Fl_Multi_Edit_Window, Fl_Multi_Window) +extern int gDisableHl; + +//Editor colors +extern Fl_Color hl_plain; +extern Fl_Color hl_linecomment; +extern Fl_Color hl_blockcomment ; +extern Fl_Color hl_string ; +extern Fl_Color hl_directive ; +extern Fl_Color hl_type ; +extern Fl_Color hl_keyword ; +extern Fl_Color hl_character ; +extern Fl_Color hl_label ; +extern Fl_Color background_color ; + +My_Text_Display::Style_Table_Entry + gStyleTable[] = { // Style table + { hl_plain, FL_COURIER, TEXTSIZE }, // A - Plain + { hl_linecomment, FL_COURIER_ITALIC, TEXTSIZE }, // B - Line comments + { hl_blockcomment, FL_COURIER_ITALIC, TEXTSIZE }, // C - Block comments + { hl_string, FL_COURIER, TEXTSIZE }, // D - Strings + { hl_directive, FL_COURIER, TEXTSIZE }, // E - Directives + { hl_type, FL_COURIER_BOLD, TEXTSIZE }, // F - Types + { hl_keyword, FL_COURIER_BOLD, TEXTSIZE }, // G - Keywords + { hl_character, FL_COURIER, TEXTSIZE }, // H - Character + { hl_label, FL_COURIER, TEXTSIZE } // H - Character + }; + + +IMPLEMENT_DYNCREATE(Fl_Multi_Edit_Window, VTObject) +//IMPLEMENT_DYNCREATE(Fl_Multi_Edit_Window, Fl_Multi_Window) void multiEditModCB(int pos, int nInserted, int nDeleted, int nRestyled, const char* deletedText, void* cbArg) @@ -57,10 +89,16 @@ void multiEditModCB(int pos, int nInserted, int nDeleted, int nRestyled, mw->ModifedCB(pos, nInserted, nDeleted, nRestyled, deletedText); } -void cb_multieditwin(Fl_Widget* w, void *) +void cb_multieditwin(Fl_Widget* w, void *args) { Fl_Multi_Edit_Window* mw = (Fl_Multi_Edit_Window*) w; int ans; + int event; + + event = Fl::event(); + + if ((args != (void *) FL_IDE_TABS_CLOSE) && (event != FL_HIDE)) + return; // Check if buffer is modified & ask to close if it is if (mw->IsModified()) @@ -71,29 +109,92 @@ void cb_multieditwin(Fl_Widget* w, void *) if (ans == 1) mw->SaveFile(gRootpath); } - + mw->hide(); - delete mw; + mw->parent()->do_callback(mw, FL_IDE_TABS_CLOSE); +// delete mw; } Fl_Multi_Edit_Window::Fl_Multi_Edit_Window(int x, int y, int w, int h, const char* title) -: Fl_Multi_Window(x, y, w, h, title) + : My_Text_Editor(x, y, w, h, title) { /* Create window */ - m_te = new Fl_Text_Editor(15, 0, ClientArea()->w()-15, - ClientArea()->h(), (const char *) title); m_tb = new Fl_Text_Buffer(); + buffer(m_tb); m_tb->add_modify_callback(multiEditModCB, this); - m_te->buffer(m_tb); - m_te->textfont(FL_COURIER); - m_te->end(); - ClientArea()->resizable(m_te); + + m_pHlCtrl = new HighlightCtrl_t; + if (m_pHlCtrl != NULL) + { + m_pHlCtrl->textbuf = m_tb; + m_pHlCtrl->te = this; + m_pHlCtrl->cppfile = TRUE; + m_pHlCtrl->stylebuf = NULL; + } + + mStyleTable = gStyleTable; + mNStyles = sizeof(gStyleTable) / sizeof(My_Text_Display::Style_Table_Entry); + m_tb->add_modify_callback(style_update, m_pHlCtrl); + + if (!gDisableHl) + { + style_init(m_pHlCtrl); + mStyleBuffer = m_pHlCtrl->stylebuf; + } + + callback(cb_multieditwin); + when(FL_WHEN_RELEASE); + + textfont(FL_COURIER); +#ifndef WIN32 + textsize(14); +#endif m_Modified = 0; m_Title = title; + this->label((const char *) m_Title); } + Fl_Multi_Edit_Window::~Fl_Multi_Edit_Window() { + // Free the Highlight control struct + if (m_pHlCtrl != NULL) + { + if (m_pHlCtrl->stylebuf != NULL) + delete m_pHlCtrl->stylebuf; + + delete m_pHlCtrl; + } + + // Delete the text buffer +/* if (m_tb != NULL) + { + delete m_tb; + m_tb = NULL; + } */ +} + +void Fl_Multi_Edit_Window::DisableHl(void) +{ + if (mStyleBuffer == NULL) + return; + + mStyleBuffer = NULL; + if (m_pHlCtrl != NULL) + { + if (m_pHlCtrl->stylebuf != NULL) + delete m_pHlCtrl->stylebuf; + m_pHlCtrl->stylebuf = NULL; + } +} + +void Fl_Multi_Edit_Window::EnableHl(void) +{ + if (mStyleBuffer != NULL) + return; + + style_init(m_pHlCtrl); + mStyleBuffer = m_pHlCtrl->stylebuf; } /* @@ -157,14 +258,16 @@ Routine to draw the border and title bar of the window */ void Fl_Multi_Edit_Window::SaveAs(const MString& rootpath) { - Fl_File_Chooser* fc; + Flu_File_Chooser* fc; int count; // Validate the Text Buffer is valid if (m_tb == NULL) return; - fc = new Fl_File_Chooser((const char *) rootpath, "*.asm,*.a85", Fl_File_Chooser::CREATE, "Save File As"); + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser((const char *) rootpath, "*.asm,*.a85", Fl_File_Chooser::CREATE, "Save File As"); + fl_cursor(FL_CURSOR_DEFAULT); fc->preview(0); fc->show(); @@ -179,7 +282,7 @@ void Fl_Multi_Edit_Window::SaveAs(const MString& rootpath) return; } - m_FileName = fc->value(1); + m_FileName = fc->value(); m_tb->savefile((const char *) m_FileName); delete fc; @@ -194,6 +297,9 @@ Routine to handle modifications to the text buffer void Fl_Multi_Edit_Window::ModifedCB(int pos, int nInserted, int nDeleted, int nRestyled, const char* deletedText) { + if ((nInserted == 0) && (nDeleted == 0)) + return; + // Check if buffer had already been modified before if (m_Modified) return; @@ -255,12 +361,12 @@ int Fl_Multi_Edit_Window::ReplaceAll(const char* pFind, int replacement = 0; // Start at the beginning of the buffer - m_te->insert_position(0); + insert_position(0); // Loop while text found for (int found = 1; found; ) { - int pos = m_te->insert_position(); + int pos = insert_position(); found = m_tb->search_forward(pos, pFind, &pos); if (found) @@ -271,8 +377,8 @@ int Fl_Multi_Edit_Window::ReplaceAll(const char* pFind, m_tb->remove_selection(); m_tb->insert(pos, pReplace); m_tb->select(pos, pos+strlen(pReplace)); - m_te->insert_position(pos+strlen(pReplace)); - m_te->show_insert_position(); + insert_position(pos+strlen(pReplace)); + show_insert_position(); } } @@ -291,10 +397,10 @@ int Fl_Multi_Edit_Window::ReplaceNext(const char* pFind, int replacement = 0; // Start at the beginning of the buffer - m_te->insert_position(0); + insert_position(0); // Search for the pFind text - int pos = m_te->insert_position(); + int pos = insert_position(); int found = m_tb->search_forward(pos, pFind, &pos); if (found) @@ -305,10 +411,32 @@ int Fl_Multi_Edit_Window::ReplaceNext(const char* pFind, m_tb->remove_selection(); m_tb->insert(pos, pReplace); m_tb->select(pos, pos+strlen(pReplace)); - m_te->insert_position(pos+strlen(pReplace)); - m_te->show_insert_position(); + insert_position(pos+strlen(pReplace)); + show_insert_position(); } return replacement; } +int Fl_Multi_Edit_Window::ForwardSearch(const char *pFind, int caseSensitive) +{ + int pos = insert_position(); + int found = m_tb->search_forward(pos, pFind, &pos, caseSensitive); + if (found) + { + insert_position(pos+strlen(pFind)); + show_insert_position(); + take_focus(); + m_tb->select(pos, pos+strlen(pFind)); + } + else + return FALSE; + + return TRUE; +} + +void Fl_Multi_Edit_Window::show(void) +{ + My_Text_Display::show(); + redraw(); +} diff --git a/src/multieditwin.h b/src/multieditwin.h index add4ef4..dde71c7 100644 --- a/src/multieditwin.h +++ b/src/multieditwin.h @@ -32,8 +32,11 @@ #define _MULTIEDITWIN_H_ #include "multiwin.h" +#include "My_Text_Editor.h" +#include "highlight.h" -class Fl_Multi_Edit_Window : public Fl_Multi_Window +//class Fl_Multi_Edit_Window : public Fl_Multi_Window +class Fl_Multi_Edit_Window : public My_Text_Editor, public VTObject { public: Fl_Multi_Edit_Window(int x=0, int y=0, int w=600, int h=500, const char *label = 0); @@ -54,10 +57,16 @@ class Fl_Multi_Edit_Window : public Fl_Multi_Window void ModifedCB(int, int, int, int, const char *); const MString& Filename(void) { return m_FileName; } void Title(const MString& title); + MString& Title(void) { return m_Title; } + void DisableHl(void); + void EnableHl(void); + int ForwardSearch(const char *pFind, int caseSensitive = TRUE); + virtual void show(void); - Fl_Text_Editor* m_te; +// Fl_Text_Editor* m_te; protected: Fl_Text_Buffer* m_tb; + HighlightCtrl_t *m_pHlCtrl; MString m_FileName; MString m_Title; int m_Modified; diff --git a/src/multiwin.cpp b/src/multiwin.cpp index 75af7a0..2f71358 100644 --- a/src/multiwin.cpp +++ b/src/multiwin.cpp @@ -74,7 +74,7 @@ Fl_Multi_Window::Fl_Multi_Window(int x, int y, int w, int h, const char* title) m_pClientArea = new Fl_Window(MW_BORDER_WIDTH, MW_TITLE_HEIGHT, w - MW_BORDER_WIDTH*2, h - MW_BORDER_WIDTH - MW_TITLE_HEIGHT); - resizable(m_pClientArea); +// resizable(m_pClientArea); m_pLabel = new char[strlen(title) + 1]; strcpy(m_pLabel, title); label(m_pLabel); diff --git a/src/multiwin.h b/src/multiwin.h index cf41afe..51b579a 100644 --- a/src/multiwin.h +++ b/src/multiwin.h @@ -35,6 +35,7 @@ #define MW_BORDER_WIDTH 4 #define MW_MINIMIZE_WIDTH 150 +#include #include #include #include @@ -48,8 +49,8 @@ class Fl_Multi_Window : public Fl_Double_Window, public VTObject Fl_Multi_Window(int x=0, int y=0, int w=600, int h=500, const char *label = 0); ~Fl_Multi_Window(); -// Fl_Window* ClientArea() { return m_pClientArea; }; - Fl_Window* ClientArea() { return this; }; + Fl_Window* ClientArea() { return m_pClientArea; }; +// Fl_Window* ClientArea() { return this; }; int m_NoResize; diff --git a/src/multiwin_icons.h b/src/multiwin_icons.h index e399c0c..105a763 100644 --- a/src/multiwin_icons.h +++ b/src/multiwin_icons.h @@ -48,7 +48,7 @@ extern Fl_Pixmap gRestoreIcon; extern Fl_Pixmap gRestoreIconSelected; extern Fl_Pixmap gRestoreIconInactive; -extern char * gMultiWinDoc_xpm[]; +extern const char * gMultiWinDoc_xpm[]; #endif diff --git a/src/n8201rom.c b/src/n8201rom.c index 88075c3..f4eb81a 100644 --- a/src/n8201rom.c +++ b/src/n8201rom.c @@ -167,6 +167,8 @@ Std_ROM_Addresses_t gN8201_Vars[] = { { 0xF45B, R_CUR_BASIC_LINE_NUM }, { 0xF45D, R_START_BASIC_PGM_PTR }, { 0xF461, R_END_OF_STMT_MARKER }, + { 0xF590, R_CUR_MENU_DIR_LOC }, + { 0xF591, R_MAX_MENU_DIR_LOC }, { 0xF5A1, R_KEYBOARD_BUF }, { 0xF6A4, R_CURSOR_H_POS }, { 0xF6A5, R_FKEY_DEF_BUF }, @@ -232,7 +234,7 @@ Std_ROM_Addresses_t gN8201_Vars[] = { { 0xFB78, R_BASIC_FILENAME }, { 0xFB81, R_LAST_LOAD_FILENAME }, { 0xFBC0, R_ALT_LCD_CHAR_BUF }, -// { 0xFDEF, R_MAX_MENU_DIR_LOC }, + { 0xFD00, R_LCD_CHAR_BUF }, { 0xFE40, R_XON_XOFF_CTRL }, { 0xFE41, R_XON_XOFF_CTRL }, { 0xFE42, R_XON_XOFF_ENABLE }, @@ -912,6 +914,8 @@ RomDescription_t gN8201_Desc = { 0xFE58, /* Keyscan array */ 0x78B7, /* Character generator array */ 0xF83C, /* Location of Year storage */ + 0xFD00, /* LCD Buffer storage area */ + 0xF3E9, /* Label line enable flag (not defined) */ 24, /* Number of directory entries */ 8, /* Index of first Dir entry */ diff --git a/src/periph.cpp b/src/periph.cpp index 104cec3..9332dfc 100644 --- a/src/periph.cpp +++ b/src/periph.cpp @@ -40,6 +40,7 @@ #include #include +#include "FLU/Flu_File_Chooser.h" #if defined(WIN32) #include @@ -227,7 +228,7 @@ Callback routine for saving the LPT log */ void cb_lpt_save (Fl_Widget* w, void*) { - Fl_File_Chooser* fc; + Flu_File_Chooser* fc; const char * pText; // Check if there is text in the buffer @@ -242,8 +243,10 @@ void cb_lpt_save (Fl_Widget* w, void*) free((void*) pText); // Create a file chooser - fc = new Fl_File_Chooser(".", "*.*", Fl_File_Chooser::CREATE, + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser(".", "*.*", Fl_File_Chooser::CREATE, "Choose file for Hex Log"); + fl_cursor(FL_CURSOR_DEFAULT); while (1) { @@ -674,6 +677,7 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) periph_ctrl.com.pDSR->color(FL_BLACK); periph_ctrl.com.pLog = new T100_ComMon(20, 200, 495, 190-MENU_HEIGHT); + periph_ctrl.com.g->resizable(periph_ctrl.com.pLog); // periph_ctrl.com.pLog->color(FL_WHITE); periph_ctrl.com.pScroll = new Fl_Scrollbar(515, 200, 20, 190-MENU_HEIGHT, ""); @@ -707,6 +711,7 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) periph_ctrl.com.g->end(); + periph_ctrl.pTabs->resizable(periph_ctrl.com.g); update_com_port_settings(); } @@ -738,6 +743,7 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) periph_ctrl.lpt.pHexLogDisplay->buffer(periph_ctrl.lpt.pHexLogBuffer); periph_ctrl.lpt.pHexLogDisplay->wrap_mode(1, 48); periph_ctrl.lpt.pHexLogDisplay->textfont(FL_COURIER); + periph_ctrl.lpt.g->resizable(periph_ctrl.lpt.pHexLogDisplay); // Create control for enabling capture periph_ctrl.lpt.pEnable = new Fl_Check_Button(20, 357, 130, 20, "Enable Hex Log"); @@ -762,6 +768,7 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) // End of control for this tab periph_ctrl.lpt.g->end(); + periph_ctrl.pTabs->resizable(periph_ctrl.lpt.g); } // Modem Port Tab @@ -776,6 +783,7 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) // End of control for this tab periph_ctrl.mdm.g->end(); + periph_ctrl.pTabs->resizable(periph_ctrl.mdm.g); } // Cassette Port Tab @@ -789,6 +797,7 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) // End of control for this tab periph_ctrl.cas.g->end(); + periph_ctrl.pTabs->resizable(periph_ctrl.cas.g); } // BCR Port Tab @@ -802,6 +811,7 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) // End of control for this tab periph_ctrl.bcr.g->end(); + periph_ctrl.pTabs->resizable(periph_ctrl.bcr.g); } periph_ctrl.pTabs->value(periph_ctrl.com.g); @@ -831,6 +841,7 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) // End the tab pDev->pTab->end(); pDev->pTab->hide(); + periph_ctrl.pTabs->resizable(pDev->pTab); // Add the tab to list so we can hide / show it periph_ctrl.lptDevices.Add(pDev); @@ -1578,14 +1589,16 @@ void T100_ComMon::SaveLog(void) TcomLogBlock *clb; int index; char string[4], outLine[90]; - Fl_File_Chooser *fc; + Flu_File_Chooser *fc; const char *filename; FILE* fd; unsigned char bytes[16]; // Create a file chooser - fc = new Fl_File_Chooser(".","*.{txt,log}", Fl_File_Chooser::CREATE, + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser(".","*.{txt,log}", Fl_File_Chooser::CREATE, "Choose file for Serial Log"); + fl_cursor(FL_CURSOR_DEFAULT); while (1) { diff --git a/src/pref_form.cpp b/src/pref_form.cpp new file mode 100644 index 0000000..47d2996 --- /dev/null +++ b/src/pref_form.cpp @@ -0,0 +1,270 @@ +// generated by Fast Light User Interface Designer (fluid) version 1.0104 + +#include "pref_form.h" +void load_lang_cb(char *file); +int text_size; +int save_window_size; +int auto_brace_mode; +int auto_hide; +int delbak; +int backup_file; +extern int gDisableHl; +extern int gSmartIndent; +extern int gReloadProject; + +Fl_Double_Window *pref_window=(Fl_Double_Window *)0; + +Fl_Button *pref_ok_btn=(Fl_Button *)0; + +static void cb_pref_ok_btn(Fl_Button*, void*) +{ + text_size = text_size_choice->value() * 2 + 6; + auto_brace_mode = auto_brace_check->value(); + save_window_size = save_wsoe_check->value(); + auto_hide = hide_output_check->value(); + hl_plain = plain_btn->color(); + hl_linecomment = line_btn->color(); + hl_blockcomment = block_btn->color(); + hl_string = string_btn->color(); + hl_directive = directive_btn->color(); + hl_type = type_btn->color(); + hl_keyword = keyword_btn->color(); + hl_character = character_btn->color(); + hl_label = label_btn->color(); + background_color = bg_btn->color(); + sprintf(usrdocdir,"%s",usrdoc_input->value()); + backup_file = bak_check->value(); + delbak = delbak_check->value(); + gDisableHl = disable_hl_check->value(); + gSmartIndent = smart_indent_check->value(); + gReloadProject = rec_pr_check->value(); + pref_window->hide(); +} + +Fl_Button *pref_cancel_btn=(Fl_Button *)0; + +static void cb_pref_cancel_btn(Fl_Button*, void*) { + pref_window->hide(); +} + +Fl_Tabs *pref_tabs=(Fl_Tabs *)0; + +Fl_Group *ed_group=(Fl_Group *)0; + +Fl_Choice *text_size_choice=(Fl_Choice *)0; + +Fl_Check_Button *smart_indent_check=(Fl_Check_Button *)0; + +Fl_Check_Button *save_wsoe_check=(Fl_Check_Button *)0; + +Fl_Check_Button *hide_output_check=(Fl_Check_Button *)0; + +Fl_Check_Button *rec_pr_check=(Fl_Check_Button *)0; + +Fl_Box *pref_highlight_label=(Fl_Box *)0; + +Fl_Button *plain_btn=(Fl_Button *)0; + +static void cb_plain_btn(Fl_Button*, void*) { + plain_btn->color(fl_show_colormap(plain_btn->color())); +} + +Fl_Button *line_btn=(Fl_Button *)0; + +static void cb_line_btn(Fl_Button*, void*) { + line_btn->color(fl_show_colormap(line_btn->color())); +} + +Fl_Button *block_btn=(Fl_Button *)0; + +static void cb_block_btn(Fl_Button*, void*) { + block_btn->color(fl_show_colormap(block_btn->color())); +} + +Fl_Button *string_btn=(Fl_Button *)0; + +static void cb_string_btn(Fl_Button*, void*) { + string_btn->color(fl_show_colormap(string_btn->color())); +} + +Fl_Button *directive_btn=(Fl_Button *)0; + +static void cb_directive_btn(Fl_Button*, void*) { + directive_btn->color(fl_show_colormap(directive_btn->color())); +} + +Fl_Button *type_btn=(Fl_Button *)0; + +static void cb_type_btn(Fl_Button*, void*) { + type_btn->color(fl_show_colormap(type_btn->color())); +} + +Fl_Button *keyword_btn=(Fl_Button *)0; + +static void cb_keyword_btn(Fl_Button*, void*) { + keyword_btn->color(fl_show_colormap(keyword_btn->color())); +} + +Fl_Button *character_btn=(Fl_Button *)0; + +static void cb_character_btn(Fl_Button*, void*) { + character_btn->color(fl_show_colormap(character_btn->color())); +} + +Fl_Button *label_btn=(Fl_Button *)0; + +static void cb_label_btn(Fl_Button*, void*) { + label_btn->color(fl_show_colormap(label_btn->color())); +} + +Fl_Button *bg_btn=(Fl_Button *)0; + +static void cb_bg_btn(Fl_Button*, void*) { + bg_btn->color(fl_show_colormap(bg_btn->color())); +} + +Fl_Check_Button *auto_brace_check=(Fl_Check_Button *)0; + +Fl_Check_Button *bak_check=(Fl_Check_Button *)0; + +Fl_Check_Button *delbak_check=(Fl_Check_Button *)0; + +Fl_Check_Button *disable_hl_check=(Fl_Check_Button *)0; + +Fl_Group *env_group=(Fl_Group *)0; + +Fl_Input *usrdoc_input=(Fl_Input *)0; + +Fl_Button *lang_btn=(Fl_Button *)0; + +static void cb_lang_btn(Fl_Button*, void*) { + char *fname = fl_file_chooser("","*.lng",""); +if(fname==NULL) return; +//load_lang_cb(fname); +} + +Fl_Output *cur_lang_output=(Fl_Output *)0; + +Fl_Button *def_lang_btn=(Fl_Button *)0; + +static void cb_def_lang_btn(Fl_Button*, void*) { + //load_lang_cb(NULL); +} + +Fl_Double_Window* make_pref_form() { + Fl_Double_Window* w; + + if (pref_window != (Fl_Double_Window *) 0) + return pref_window; + + { Fl_Double_Window* o = pref_window = new Fl_Double_Window(525, 355, "Preferences"); + w = o; + o->align(FL_ALIGN_TOP_LEFT); + { Fl_Button* o = pref_ok_btn = new Fl_Button(345, 320, 85, 25, "OK"); + o->callback((Fl_Callback*)cb_pref_ok_btn); + } + { Fl_Button* o = pref_cancel_btn = new Fl_Button(435, 320, 80, 25, "Cancel"); + o->callback((Fl_Callback*)cb_pref_cancel_btn); + } + { Fl_Tabs* o = pref_tabs = new Fl_Tabs(5, 5, 515, 310); + { Fl_Group* o = ed_group = new Fl_Group(10, 40, 510, 275, "Editor"); + { Fl_Box* o = new Fl_Box(20, 85, 260, 215); + o->box(FL_ENGRAVED_BOX); + o->labeltype(FL_ENGRAVED_LABEL); + o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE); + } + { Fl_Choice* o = text_size_choice = new Fl_Choice(130, 45, 60, 25, "Text Size"); + o->down_box(FL_BORDER_BOX); + text_size_choice->add("6");text_size_choice->add("8");text_size_choice->add("10");text_size_choice->add("12");text_size_choice->add("14");text_size_choice->add("16");text_size_choice->add("18");text_size_choice->add("20"); + text_size_choice->value(3); + } + { Fl_Check_Button* o = smart_indent_check = new Fl_Check_Button(30, 95, 180, 25, "Use Auto-Indent Option"); + o->down_box(FL_DOWN_BOX); + } + { Fl_Check_Button* o = save_wsoe_check = new Fl_Check_Button(30, 145, 195, 25, "Save Window Size On Exit"); + o->down_box(FL_DOWN_BOX); + } + { Fl_Check_Button* o = hide_output_check = new Fl_Check_Button(30, 170, 195, 25, "Auto-hide Output Window"); + o->down_box(FL_DOWN_BOX); + } + { Fl_Check_Button* o = rec_pr_check = new Fl_Check_Button(30, 195, 235, 25, "Open previous project on startup"); + o->down_box(FL_DOWN_BOX); + } + { Fl_Box* o = pref_highlight_label = new Fl_Box(290, 40, 220, 260, "Highlight Colors"); + o->box(FL_ENGRAVED_BOX); + o->labeltype(FL_ENGRAVED_LABEL); + o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE); + } + { Fl_Button* o = plain_btn = new Fl_Button(320, 70, 15, 15, "Plain Text"); + o->callback((Fl_Callback*)cb_plain_btn); + o->align(FL_ALIGN_RIGHT); + } + { Fl_Button* o = line_btn = new Fl_Button(320, 90, 15, 15, "Line Comments"); + o->callback((Fl_Callback*)cb_line_btn); + o->align(FL_ALIGN_RIGHT); + } + { Fl_Button* o = block_btn = new Fl_Button(320, 110, 15, 15, "Block Comments"); + o->callback((Fl_Callback*)cb_block_btn); + o->align(FL_ALIGN_RIGHT); + } + { Fl_Button* o = string_btn = new Fl_Button(320, 130, 15, 15, "Strings"); + o->callback((Fl_Callback*)cb_string_btn); + o->align(FL_ALIGN_RIGHT); + } + { Fl_Button* o = directive_btn = new Fl_Button(320, 150, 15, 15, "Directives"); + o->callback((Fl_Callback*)cb_directive_btn); + o->align(FL_ALIGN_RIGHT); + } + { Fl_Button* o = type_btn = new Fl_Button(320, 170, 15, 15, "Keywords"); + o->callback((Fl_Callback*)cb_type_btn); + o->align(FL_ALIGN_RIGHT); + } + { Fl_Button* o = keyword_btn = new Fl_Button(320, 190, 15, 15, "Instructions"); + o->callback((Fl_Callback*)cb_keyword_btn); + o->align(FL_ALIGN_RIGHT); + } + { Fl_Button* o = character_btn = new Fl_Button(320, 210, 15, 15, "Characters"); + o->callback((Fl_Callback*)cb_character_btn); + o->align(FL_ALIGN_RIGHT); + } + { Fl_Button* o = label_btn = new Fl_Button(320, 230, 15, 15, "Labels"); + o->callback((Fl_Callback*)cb_label_btn); + o->align(FL_ALIGN_RIGHT); + } + { Fl_Button* o = bg_btn = new Fl_Button(320, 250, 15, 15, "Background"); + o->callback((Fl_Callback*)cb_bg_btn); + o->align(FL_ALIGN_RIGHT); + } + { Fl_Check_Button* o = auto_brace_check = new Fl_Check_Button(30, 120, 180, 25, "Use Auto-Brace Option"); + o->down_box(FL_DOWN_BOX); + } + { Fl_Check_Button* o = bak_check = new Fl_Check_Button(30, 220, 235, 25, "Create backup when loading file"); + o->down_box(FL_DOWN_BOX); + } + { Fl_Check_Button* o = delbak_check = new Fl_Check_Button(30, 245, 235, 25, "Delete backup files on exit"); + o->down_box(FL_DOWN_BOX); + } + { Fl_Check_Button* o = disable_hl_check = new Fl_Check_Button(30, 270, 235, 25, "Disable syntax highlighting"); + o->down_box(FL_DOWN_BOX); + } + o->end(); + } + { Fl_Group* o = env_group = new Fl_Group(15, 30, 505, 255, "Environment"); + o->hide(); + usrdoc_input = new Fl_Input(155, 55, 345, 25, "Path to FLTK Docs"); + { Fl_Button* o = lang_btn = new Fl_Button(155, 145, 180, 25, "Load Language File"); + o->callback((Fl_Callback*)cb_lang_btn); + } + cur_lang_output = new Fl_Output(155, 115, 180, 25, "Current Language"); + { Fl_Button* o = def_lang_btn = new Fl_Button(355, 115, 145, 25, "Restore Default"); + o->callback((Fl_Callback*)cb_def_lang_btn); + } + o->end(); + } + o->end(); + } + o->set_modal(); + o->end(); + } + return w; +} diff --git a/src/pref_form.h b/src/pref_form.h new file mode 100644 index 0000000..8f49f41 --- /dev/null +++ b/src/pref_form.h @@ -0,0 +1,67 @@ +// generated by Fast Light User Interface Designer (fluid) version 1.0104 + +#ifndef pref_form_h +#define pref_form_h +#include +#include +#include +#include +extern void load_lang_cb(char *file); +extern int text_size; +extern Fl_Color hl_plain; +extern Fl_Color hl_linecomment; +extern Fl_Color hl_blockcomment; +extern Fl_Color hl_string; +extern Fl_Color hl_directive; +extern Fl_Color hl_type; +extern Fl_Color hl_keyword; +extern Fl_Color hl_character; +extern Fl_Color hl_label; +extern Fl_Color background_color; +extern char usrdocdir[256]; +extern int save_window_size; +extern int auto_brace_mode; +extern int auto_hide; +extern int delbak; +extern int backup_file; +#include +extern Fl_Double_Window *pref_window; +#include +extern Fl_Button *pref_ok_btn; +extern Fl_Button *pref_cancel_btn; +#include +extern Fl_Tabs *pref_tabs; +#include +extern Fl_Group *ed_group; +#include +#include +extern Fl_Choice *text_size_choice; +#include +extern Fl_Check_Button *smart_indent_check; +extern Fl_Check_Button *save_wsoe_check; +extern Fl_Check_Button *hide_output_check; +extern Fl_Check_Button *rec_pr_check; +extern Fl_Box *pref_highlight_label; +extern Fl_Button *plain_btn; +extern Fl_Button *line_btn; +extern Fl_Button *block_btn; +extern Fl_Button *string_btn; +extern Fl_Button *directive_btn; +extern Fl_Button *type_btn; +extern Fl_Button *keyword_btn; +extern Fl_Button *character_btn; +extern Fl_Button *label_btn; +extern Fl_Button *bg_btn; +extern Fl_Check_Button *auto_brace_check; +extern Fl_Check_Button *bak_check; +extern Fl_Check_Button *delbak_check; +extern Fl_Check_Button *disable_hl_check; +extern Fl_Group *env_group; +#include +extern Fl_Input *usrdoc_input; +extern Fl_Button *lang_btn; +#include +extern Fl_Output *cur_lang_output; +extern Fl_Button *def_lang_btn; +Fl_Double_Window* make_pref_form(); +#endif diff --git a/src/project.cpp b/src/project.cpp index 61a430e..2363be1 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -32,21 +32,28 @@ #include #include #include +#include +#include #include #include #include +#include "FLU/Flu_File_Chooser.h" + #include "VirtualT.h" +#include "ide.h" #include "project.h" +#include "m100emu.h" #ifdef _WIN32 extern "C" #endif extern char path[]; +extern char gProjectTypes[][6]; void cb_SelLocation(Fl_Widget* w, void*) { - Fl_File_Chooser *fileWin; + Flu_File_Chooser *fileWin; int count; Fl_Round_Button* pButton; VT_NewProject* pNewProj; @@ -58,8 +65,10 @@ void cb_SelLocation(Fl_Widget* w, void*) pNewProj = (VT_NewProject*) pButton->user_data(); // Create a File chooser - fileWin = new Fl_File_Chooser(pNewProj->getLocation(), "", - Fl_File_Chooser::DIRECTORY, "Choose Project Location"); + fl_cursor(FL_CURSOR_WAIT); + fileWin = new Flu_File_Chooser(pNewProj->getLocation(), "", + Flu_File_Chooser::DIRECTORY, "Choose Project Location"); + fl_cursor(FL_CURSOR_DEFAULT); fileWin->preview(0); fileWin->show(); @@ -76,7 +85,7 @@ void cb_SelLocation(Fl_Widget* w, void*) } // Get the path of the new location - pNewLoc = fileWin->value(1); + pNewLoc = fileWin->value(); printf("Path = %s\n", path); printf("New = %s\n", pNewLoc); @@ -284,7 +293,7 @@ int VT_NewProject::getProjType(void) if (m_pProjType == NULL) return 0; - return m_pProjType->value(); + return m_pProjType->value() - 1; } int VT_NewProject::visible(void) @@ -377,8 +386,7 @@ void cb_settings_ok(Fl_Widget* w, void*) pProject->IgnoreStdLibs(pProj->getIgnoreStdLibs()); pProject->m_LinkPath = pProj->getLinkPath(); pProject->m_LinkLibs = pProj->getLinkObjs(); - pProject->m_CodeAddr = pProj->getCodeAddr(); - pProject->m_DataAddr = pProj->getDataAddr(); + pProject->m_LinkScript = pProj->getLinkScript(); // Hide the window to end the session pProj->m_pProject->m_Dirty = 1; @@ -424,7 +432,7 @@ VT_ProjectSettings::VT_ProjectSettings(VT_Project *pProj) m_pProjType->add("Assembly ROM"); m_pProjType->add("BASIC"); m_pProjType->callback(browse_cb); - m_pProjType->value(m_pProject->m_ProjectType); + m_pProjType->value(m_pProject->m_ProjectType+1); // Text for target device o = new Fl_Box(180, 50, 100, 20, "Target Model"); @@ -502,40 +510,33 @@ VT_ProjectSettings::VT_ProjectSettings(VT_Project *pProj) m_pLinkDebugInfo->value(m_pProject->LinkDebugInfo()); m_pMapFile = new Fl_Check_Button(20, 75, 170, 20, "Generate Map File"); m_pMapFile->value(m_pProject->MapFile()); - m_pIgnoreStdLibs = new Fl_Check_Button(20, 100, 165, 20, "Ingore Std Libraries"); + m_pIgnoreStdLibs = new Fl_Check_Button(200, 50, 165, 20, "Ingore Std Libraries"); m_pIgnoreStdLibs->value(m_pProject->IgnoreStdLibs()); + // Add edit fields for Code and Data segment addresses + o = new Fl_Box(20, 95, 100, 20, "Linker Script"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pLinkScript = new Fl_Input(20, 115, 320, 20, ""); + m_pLinkScript->value((const char *) m_pProject->m_LinkScript); + // Create Edit field for Output Name - o = new Fl_Box(20, 125, 100, 20, "Output Name"); + o = new Fl_Box(20, 135, 100, 20, "Output Name"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); - m_pOutputName = new Fl_Input(20, 145, 320, 20, ""); + m_pOutputName = new Fl_Input(20, 155, 320, 20, ""); m_pOutputName->value(m_pProject->m_Name); // Create Edit field for Link libs - o = new Fl_Box(20, 170, 100, 20, "Additional Link Objects"); + o = new Fl_Box(20, 180, 100, 20, "Additional Link Objects"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); - m_pLinkObjs = new Fl_Input(20, 190, 320, 20, ""); + m_pLinkObjs = new Fl_Input(20, 200, 320, 20, ""); m_pLinkObjs->value(m_pProject->m_LinkLibs); // Create Edit field for Link Dirs - o = new Fl_Box(20, 215, 100, 20, "Additional Object Directories"); + o = new Fl_Box(20, 220, 100, 20, "Additional Object Directories"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); - m_pObjPath = new Fl_Input(20, 235, 320, 20, ""); + m_pObjPath = new Fl_Input(20, 240, 320, 20, ""); m_pObjPath->value(m_pProject->m_LinkPath); - // Add edit fields for Code and Data segment addresses - o = new Fl_Box(235, 50, 100, 20, "Segment Address"); - o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); - o = new Fl_Box(200, 75, 40, 20, "Code"); - o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); - o = new Fl_Box(200, 100, 40, 20, "Data"); - o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); - - m_pCodeAddr = new Fl_Input(250, 75, 90, 20, ""); - m_pCodeAddr->value("test"); - m_pCodeAddr->value((const char *) m_pProject->m_CodeAddr); - m_pDataAddr = new Fl_Input(250, 100, 90, 20, ""); - m_pDataAddr->value((const char *) m_pProject->m_DataAddr); // End the Linker tab g->end(); @@ -577,7 +578,7 @@ int VT_ProjectSettings::getProjType(void) if (m_pProjType == NULL) return 0; - return m_pProjType->value(); + return m_pProjType->value() - 1; } int VT_ProjectSettings::getTargetModel() @@ -700,20 +701,12 @@ MString VT_ProjectSettings::getLinkObjs(void) return m_pLinkObjs->value(); } -MString VT_ProjectSettings::getCodeAddr(void) +MString VT_ProjectSettings::getLinkScript(void) { - if (m_pCodeAddr == NULL) + if (m_pLinkScript == NULL) return ""; - return m_pCodeAddr->value(); -} - -MString VT_ProjectSettings::getDataAddr(void) -{ - if (m_pDataAddr == NULL) - return ""; - - return m_pDataAddr->value(); + return m_pLinkScript->value(); } void VT_ProjectSettings::EnableUpdateHIMEM(int enable) @@ -749,14 +742,14 @@ int VT_Project::AsmDebugInfo(void) const void VT_Project::AsmListing(int enable) { if (enable) - AddAsmOption((char *) "-l"); + AddAsmOption((char *) "-t"); else - RemoveAsmOption((char *) "-l"); + RemoveAsmOption((char *) "-t"); } int VT_Project::AsmListing(void) const { - return m_AsmOptions.Find((char *) "-l", 0) != -1; + return m_AsmOptions.Find((char *) "-t", 0) != -1; } void VT_Project::BrowseInfo(int enable) @@ -890,3 +883,244 @@ int VT_Project::IgnoreStdLibs(void) const return m_LinkOptions.Find((char *) "-i", 0) != -1; } +/* +======================================================================== +Saves the project to the project file. +======================================================================== +*/ +void VT_Project::SaveProject(void) +{ + FILE* fd; + char fullPath[512]; + char model[10]; + int count, c; + VT_IdeGroup* pGroup; + + // Create the path + sprintf(fullPath, "%s/%s.prj", (const char *) m_RootPath, + (const char *) m_Name); + + // Try to open the file for write mode + if ((fd = fopen(fullPath, "w+")) == NULL) + { + // Error opening file!! + fl_alert("Error opening project file for write mode!"); + return; + } + + // Write header information + fprintf(fd, "NAME=%s\n", (const char *) m_Name); + fprintf(fd, "INCLPATH=%s\n", (const char *) m_IncludePath); + fprintf(fd, "DEFINES=%s\n", (const char *) m_Defines); + fprintf(fd, "LINKPATH=%s\n", (const char *) m_LinkPath); + fprintf(fd, "LINKLIBS=%s\n", (const char *) m_LinkLibs); + fprintf(fd, "LINKSCRIPT=%s\n", (const char *) m_LinkScript); + fprintf(fd, "ASMOPT=%s\n", (const char *) m_AsmOptions); + fprintf(fd, "LINKOPT=%s\n", (const char *) m_LinkOptions); + fprintf(fd, "TYPE=%s\n", gProjectTypes[m_ProjectType]); + get_model_string(model, m_TargetModel); + fprintf(fd, "TARGET=%s\n", model); + fprintf(fd, "AUTOLOAD=%d\n", m_AutoLoad); + fprintf(fd, "UPDATEHIMEM=%d\n", m_UpdateHIMEM); + fprintf(fd, "\n"); + + // Write group information to the file + count = m_Groups.GetSize(); + for (c = 0; c < count; c++) + { + pGroup = (VT_IdeGroup*) m_Groups[c]; + WriteGroupToFile(pGroup, fd); + } + + m_Dirty = 0; + fclose(fd); +} + +/* +======================================================================== +Write a VT_Group to the file along with all childreen. Called +recursively. +======================================================================== +*/ +void VT_Project::WriteGroupToFile(VT_IdeGroup* pGroup, FILE* fd) +{ + int x, objs; + VT_IdeSource* pObj; + MString temp; + + fprintf(fd, "GROUP=%s\n", (const char *) pGroup->m_Name); + fprintf(fd, "FILESPEC=%s\n", (const char *) pGroup->m_Filespec); + + // Write objects + objs = pGroup->m_Objects.GetSize(); + for (x = 0; x < objs; x++) + { + pObj = (VT_IdeSource*) pGroup->m_Objects[x]; + if (strcmp(pObj->GetClass()->m_ClassName, "VT_IdeGroup") == 0) + WriteGroupToFile((VT_IdeGroup *) pObj, fd); + else + { + pObj->m_Name.Replace('\\', '/'); + temp = MakePathRelative(pObj->m_Name, m_RootPath); + fprintf(fd, "SOURCE=%s\n", (const char *) temp); + } + } + + // End the group + fprintf(fd, "ENDGROUP\n\n"); +} + +/* +=============================================================================== +This routine returns a string which is the relative form of the given path +realtive to the relTo path. The routine detects both relativeness in bot +directions and uses '..' as necessary in the returned string. +=============================================================================== +*/ +MString VT_Project::MakePathRelative(const MString& path, const MString& relTo) +{ + int c; + int lenPath, lenRel; // Length of each string + int lastRelBranch; // Index of last '/' in relTo + int lastMatch; + MString temp; + int slashIndex = 0; + + // Determine if path is already relative + if ((path.Left(2) == "./") || (path.Left(3) == "../")) + return path; + if (path.Find((char *) "/", 0) == -1) + return path; + if (path[1] == ':') + slashIndex = 2; + if (path[slashIndex] != '/') + return path; + + // Find the location of the last '/' in each string + lastRelBranch = relTo.ReverseFind('/'); + lenPath = path.GetLength(); + lenRel = relTo.GetLength(); + + // Start at beginning of string and compare each path segment + // to find the first location where they don't match + c = lastMatch = 0; + while ((c != lenPath) && (c != lenRel)) + { + // Test +#ifdef WIN32 + if (tolower(path[c]) != tolower(relTo[c])) + break; +#else + if (path[c] != relTo[c]) + break; +#endif + if (path[c] == '/') + lastMatch = c; + c++; + } + // Determine if the last branch is identical. This must be done because + // the loop could have exited simply becuase we came to the end of one of + // the 2 strings: + if (((c == lenPath) && (relTo[c] == '/')) || ((path[c] == '/') && (c == lenRel))) + lastMatch = c; + + // Okay, now we know where the path's are different, scan through the + // relTo path to determine how many '../' entries we need, if any + c = lastMatch; + while (c != lenRel) + { + if (c == lastRelBranch) + { + temp += (char *) "../"; // Add another 'prev dir' indicator + break; // At last branch...exit + } + // Check for a directory specifier + if (relTo[c] == '/') + { + temp += (char *) "../"; + } + c++; + } + + // Now append the remainder of the path from the lastMatch point + c = lastMatch; + if (path[c] == '/') + c++; + while (c < lenPath) + { + temp += path[c++]; + } + + return temp; +} + +/* +======================================================================== +Tests if the specified filename is in the project under any group or +subgroup. +======================================================================== +*/ +int VT_Project::TestIfFileInProject(MString& filename) +{ + int c, count; + VT_IdeGroup* pGroup; + + // Loop for all the parent group entries + count = m_Groups.GetSize(); + for (c = 0; c < count; c++) + { + pGroup = (VT_IdeGroup *) m_Groups[c]; + if (TestIfFileInGroup(pGroup, filename)) + return TRUE; + } + + return FALSE; +// return m_LinkOptions.Find((char *) "-i", 0) != -1; +} + +/* +======================================================================== +Tests if the specified filename is in the group specified or in any +subgroups. +======================================================================== +*/ +int VT_Project::TestIfFileInGroup(VT_IdeGroup* pGroup, MString& filename) +{ + int c, count; + VT_IdeGroup* pSubGroup; + VT_IdeSource* pSource; + MString file; + + // Convert filename to lowercase if WIN32 + file = MakePathRelative(filename, m_RootPath); +#ifdef WIN32 + file.MakeLower(); + file.Replace('\\', '/'); +#endif + // Loop for all the parent group entries + count = pGroup->m_Objects.GetSize(); + for (c = 0; c < count; c++) + { + if (strcmp(pGroup->m_Objects[c]->GetClass()->m_ClassName, "VT_IdeGroup") == 0) + { + // Item is a sub group. Search the subgroup + pSubGroup = (VT_IdeGroup *) pGroup->m_Objects[c]; + if (TestIfFileInGroup(pSubGroup, filename)) + return TRUE; + } + else + { + // Item is a source. Test for match + pSource = (VT_IdeSource *) pGroup->m_Objects[c]; + MString temp = pSource->m_Name; + +#ifdef WIN32 + temp.MakeLower(); +#endif + if (temp == file) + return TRUE; + } + } + + return FALSE; +} diff --git a/src/project.h b/src/project.h index 2291e6c..ae5cc35 100644 --- a/src/project.h +++ b/src/project.h @@ -46,12 +46,16 @@ void cb_NewProject (Fl_Widget* w, void*); +#define VT_PROJ_TYPE_CO 0 +#define VT_PROJ_TYPE_OBJ 1 +#define VT_PROJ_TYPE_ROM 2 +#define VT_PROJ_TYPE_BA 3 + class VT_Project { public: VT_Project() { m_Dirty = 0; m_AutoLoad = 0; m_ProjectType = 0; - m_TargetModel = 0; m_UpdateHIMEM = 0; m_CodeAddr = "auto"; - m_DataAddr = "auto"; }; + m_TargetModel = 0; m_UpdateHIMEM = 0; m_LinkScript = ""; } ~VT_Project(); void AsmDebugInfo(int enable); @@ -76,6 +80,13 @@ class VT_Project void AddLinkOption(char *pOpt); void RemoveLinkOption(char *pOpt); + void SaveProject(void); + void LoadProject(void); + void WriteGroupToFile(class VT_IdeGroup* pGroup, FILE* fd); + MString MakePathRelative(const MString& path, const MString& relTo); + int TestIfFileInProject(MString& filename); + int TestIfFileInGroup(VT_IdeGroup* pGroup, MString& filename); + MString m_Name; // Project name MString m_RootPath; MString m_IncludePath; @@ -84,8 +95,7 @@ class VT_Project MString m_LinkLibs; MString m_AsmOptions; MString m_LinkOptions; - MString m_CodeAddr; - MString m_DataAddr; + MString m_LinkScript; VTObArray m_Groups; int m_Dirty; // Set true when project settings change int m_ProjectType; // Type of project @@ -158,8 +168,7 @@ class VT_ProjectSettings MString getLinkPath(void); MString getOutputName(void); MString getLinkObjs(void); - MString getCodeAddr(void); - MString getDataAddr(void); + MString getLinkScript(void); void EnableUpdateHIMEM(int enable); @@ -194,8 +203,7 @@ class VT_ProjectSettings Fl_Input* m_pObjPath; Fl_Input* m_pOutputName; Fl_Input* m_pLinkObjs; - Fl_Input* m_pCodeAddr; - Fl_Input* m_pDataAddr; + Fl_Input* m_pLinkScript; Fl_Button* m_pOk; Fl_Button* m_pCancel; diff --git a/src/remote.cpp b/src/remote.cpp index c8d0a31..9589c24 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -29,8 +29,12 @@ #include #include +#include #include #include +#include + +using namespace std; #include @@ -77,8 +81,6 @@ int gLcdTimeoutCycles; // Number of cycles for the string timeout int gLcdRow = -1; // Current LCD update row int gLcdCol = -1; // Current LCD update col int gLcdColStart = -1; // Column where current string started -ServerSocket gOpenSock; -int gSocketOpened = FALSE; lcd_rect_t gIgnoreRects[10]; int gIgnoreCount = 0; int gLastDisAddress = 0; @@ -89,11 +91,38 @@ int gTraceActive = 0; std::string gTraceFile; FILE* gTraceFileFd; VTDis gTraceDis; +char gTelnetCR; std::string gLineTerm = "\n"; std::string gOk = "Ok"; std::string gParamError = "Parameter Error\nOk"; std::string gTelnetCmd; +// Socket interface management structure +typedef struct +{ + ServerSocket *serverSock; + unsigned char socketShutdown; + unsigned char socketOpened; + unsigned char socketError; + unsigned char socketInitDone; + unsigned char telnet; + unsigned char cmdLineTelnet; + unsigned char enabled; + unsigned char termMode; + unsigned char iacState; + unsigned char sbState; + unsigned char sbOption; + unsigned char closeSocket; + int listenPort; + int socketPort; + int cmdLinePort; + ServerSocket openSock; + std::string socketErrorMsg; +} socket_ctrl_t; + +static socket_ctrl_t gSocket = { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +char gTelnetTerminal[256]; + int remote_cpureg_stop(void); int remote_cpureg_run(void); int remote_cpureg_step(void); @@ -107,6 +136,7 @@ extern int fullspeed; extern int fl_wait(double); extern void simulate_keydown(int key); extern void simulate_keyup(int key); +extern Fl_Preferences virtualt_prefs; extern "C" { @@ -126,10 +156,12 @@ Help command: Send list of supported commands std::string cmd_help(ServerSocket& sock) { sock << "Help" << gLineTerm << "====" << gLineTerm; + sock << " bye" << gLineTerm; sock << " clear_break(cb) address" << gLineTerm; sock << " cold_boot" << gLineTerm; sock << " debug_isr(isr) [on off]" << gLineTerm; sock << " dis address [lines]" << gLineTerm; + sock << " exit" << gLineTerm; sock << " flags [all S Z ac P=1 s=0 ...]" << gLineTerm; sock << " halt" << gLineTerm; sock << " in port" << gLineTerm; @@ -146,6 +178,7 @@ std::string cmd_help(ServerSocket& sock) sock << " read_reg(rr) [all A B h m DE ...]" << gLineTerm; sock << " reset" << gLineTerm; sock << " run" << gLineTerm; + sock << " screen_dump(sd)" << gLineTerm; sock << " set_break(sb) address [main opt mplan ram ram2 ram3 read write]" << gLineTerm; sock << " speed [2.4 friendly max]" << gLineTerm; sock << " status" << gLineTerm; @@ -176,8 +209,8 @@ void handle_lcd_timeout() gLcdString.c_str(), gLineTerm.c_str()); if ((gLcdRow != -1) && (gLcdColStart != -1)) - if (gSocketOpened) - gOpenSock << str; + if (gSocket.socketOpened) + gSocket.openSock << str; gLcdUpdateCycle = (UINT64) -1; gLcdRow = -1; gLcdColStart = -1; @@ -226,8 +259,8 @@ void handle_lcd_trap() // New string being written. Send the old one sprintf(str, "event, lcdwrite, (%d,%d),%s%s", gLcdRow, gLcdColStart, gLcdString.c_str(), gLineTerm.c_str()); - if (gSocketOpened) - gOpenSock << str; + if (gSocket.socketOpened) + gSocket.openSock << str; } // Start a new string @@ -475,13 +508,13 @@ void cb_remote_debug(int reason) // Report break to client socket if (gStopped) { - if (gSocketOpened) + if (gSocket.socketOpened) { if (gRadix == 10) sprintf(str, "event, break, PC=%d%s", PC, gLineTerm.c_str()); else sprintf(str, "event, break, PC=%04X%s", PC, gLineTerm.c_str()); - gOpenSock << str; + gSocket.openSock << str; } } } @@ -494,13 +527,13 @@ void cb_remote_debug(int reason) gStopped = 1; // Report breakpoint to socket interface - if (gSocketOpened) + if (gSocket.socketOpened) { if (gRadix == 10) sprintf(str, "event, break, PC=%d%s", PC, gLineTerm.c_str()); else sprintf(str, "event, break, PC=%04X%s", PC, gLineTerm.c_str()); - gOpenSock << str; + gSocket.openSock << str; } } } @@ -576,7 +609,7 @@ Status command: Report status of CPU and any async */ std::string cmd_status(ServerSocket& sock) { - char modelStr[10]; + char modelStr[15]; char retStr[80]; get_model_string(modelStr, gModel); @@ -873,7 +906,7 @@ std::string cmd_read_mem(ServerSocket& sock, std::string& args) std::string next_arg; std::string more_args; std::string ret; - char str[10]; + char str[20]; // Separate arguments more_args = args; @@ -897,10 +930,10 @@ std::string cmd_read_mem(ServerSocket& sock, std::string& args) else sprintf(str, "%02X ", get_memory8(address++)); - ret += str; + ret = ret + str; } unlock_remote(); - ret += gLineTerm; + ret = ret + gLineTerm; return ret + gOk; } @@ -958,77 +991,77 @@ std::string cmd_read_reg(ServerSocket& sock, std::string& args) if (next_arg == "a") { sprintf(reg_str, format_str.c_str(), A); - ret += reg_str; + ret = ret + reg_str; } else if (next_arg == "b") { sprintf(reg_str, format_str.c_str(), B); - ret += reg_str; + ret = ret + reg_str; } else if (next_arg == "c") { sprintf(reg_str, format_str.c_str(), C); - ret += reg_str; + ret = ret + reg_str; } else if (next_arg == "d") { sprintf(reg_str, format_str.c_str(), D); - ret += reg_str; + ret = ret + reg_str; } else if (next_arg == "e") { sprintf(reg_str, format_str.c_str(), E); - ret += reg_str; + ret = ret + reg_str; } else if (next_arg == "h") { sprintf(reg_str, format_str.c_str(), H); - ret += reg_str; + ret = ret + reg_str; } else if (next_arg == "l") { sprintf(reg_str, format_str.c_str(), L); - ret += reg_str; + ret = ret + reg_str; } else if (next_arg == "f") { sprintf(reg_str, format_str.c_str(), F); - ret += reg_str; + ret = ret + reg_str; } else if (next_arg == "m") { sprintf(reg_str, format_str.c_str(), get_memory8(HL)); - ret += reg_str; + ret = ret + reg_str; } else if (next_arg == "bc") { sprintf(reg_str, format_str16.c_str(), BC); - ret += reg_str; + ret = ret + reg_str; } else if (next_arg == "de") { sprintf(reg_str, format_str16.c_str(), DE); - ret += reg_str; + ret = ret + reg_str; } else if (next_arg == "hl") { sprintf(reg_str, format_str16.c_str(), HL); - ret += reg_str; + ret = ret + reg_str; } else if (next_arg == "pc") { sprintf(reg_str, format_str16.c_str(), PC); - ret += reg_str; + ret = ret + reg_str; } else if (next_arg == "sp") { sprintf(reg_str, format_str16.c_str(), SP); - ret += reg_str; + ret = ret + reg_str; } else { - ret += "xx "; + ret = ret + "xx "; } } unlock_remote(); @@ -1190,7 +1223,7 @@ Radix command: Changes the radix */ std::string cmd_radix(ServerSocket& sock, std::string& args) { - char str[10]; + char str[15]; if (args == "") { @@ -1244,22 +1277,22 @@ std::string cmd_flags(ServerSocket& sock, std::string& args) std::string str; int pos; int value; - char cstr[10]; + char cstr[20]; // Test if flags should be set or printed lock_remote(); if (args == "") { // Print all flags that are set - if (ZF) str += "Z "; - if (SF) str += "S "; - if (CF) str += "C "; - if (PF) str += "P "; - if (OV) str += "OV "; - if (AC) str += "AC "; - if (TS) str += "TS "; + if (ZF) str = str + "Z "; + if (SF) str = str + "S "; + if (CF) str = str + "C "; + if (PF) str = str + "P "; + if (OV) str = str + "OV "; + if (AC) str = str + "AC "; + if (TS) str = str + "TS "; if (str == "") str = "(none)"; - str += gLineTerm; + str = str + gLineTerm; } else { @@ -1282,13 +1315,13 @@ std::string cmd_flags(ServerSocket& sock, std::string& args) { // Report the status of this flag cstr[0] = 0; - if ((next_arg == "z") || (next_arg == "all")) {sprintf(cstr, "Z=%d ", ZF);str+=cstr;} - if ((next_arg == "s") || (next_arg == "all")) {sprintf(cstr, "S=%d ", SF);str+=cstr;} - if ((next_arg == "c") || (next_arg == "all")) {sprintf(cstr, "C=%d ", CF);str+=cstr;} - if ((next_arg == "p") || (next_arg == "all")) {sprintf(cstr, "P=%d ", PF);str+=cstr;} - if ((next_arg == "ov") || (next_arg == "all")) {sprintf(cstr, "OV=%d ", OV);str+=cstr;} - if ((next_arg == "ac") || (next_arg == "all")) {sprintf(cstr, "AC=%d ", AC);str+=cstr;} - if ((next_arg == "ts") || (next_arg == "all")) {sprintf(cstr, "TS=%d ", TS);str+=cstr;} + if ((next_arg == "z") || (next_arg == "all")) {sprintf(cstr, "Z=%d ", ZF);str= str +cstr;} + if ((next_arg == "s") || (next_arg == "all")) {sprintf(cstr, "S=%d ", SF);str= str +cstr;} + if ((next_arg == "c") || (next_arg == "all")) {sprintf(cstr, "C=%d ", CF);str= str +cstr;} + if ((next_arg == "p") || (next_arg == "all")) {sprintf(cstr, "P=%d ", PF);str= str +cstr;} + if ((next_arg == "ov") || (next_arg == "all")) {sprintf(cstr, "OV=%d ", OV);str= str +cstr;} + if ((next_arg == "ac") || (next_arg == "all")) {sprintf(cstr, "AC=%d ", AC);str= str +cstr;} + if ((next_arg == "ts") || (next_arg == "all")) {sprintf(cstr, "TS=%d ", TS);str= str +cstr;} } else { @@ -1328,9 +1361,9 @@ std::string cmd_flags(ServerSocket& sock, std::string& args) } } } - str += gLineTerm; + str = str + gLineTerm; } - str += gOk; + str = str + gOk; unlock_remote(); return str; @@ -1885,7 +1918,7 @@ Model command: Sets the emulation model std::string cmd_model(ServerSocket& sock, std::string& args) { char str[30]; - char model[10]; + char model[20]; std::string more_args = args; if (args == "") @@ -2098,7 +2131,7 @@ Show reg command: Outputs the specified value */ std::string cmd_show_reg(ServerSocket& sock, int value, int size) { - char str[10]; + char str[20]; if (gRadix == 10) sprintf(str, "%d%s%s", value, gLineTerm.c_str(), gOk.c_str()); @@ -2112,6 +2145,27 @@ std::string cmd_show_reg(ServerSocket& sock, int value, int size) return str; } + + +/* +======================================================= +Read IM command: Outputs the current interrupt mask +======================================================= +*/ +std::string cmd_rim(ServerSocket& sock, std::string& args) +{ + char str[20]; + + if (gRadix == 10) + sprintf(str, "%d%s%s", IM, gLineTerm.c_str(), gOk.c_str()); + else + { + sprintf(str, "%02X%s%s", IM, gLineTerm.c_str(), gOk.c_str()); + } + + return str; +} + /* ======================================================= Lcd_mon command: Enables or disables LCD monitoring. @@ -2254,7 +2308,7 @@ std::string cmd_string(ServerSocket& sock, std::string& args) { int address; int ch; - char build[10]; + char build[20]; std::string str; address = get_address(args); @@ -2266,14 +2320,14 @@ std::string cmd_string(ServerSocket& sock, std::string& args) sprintf(build, "<%d>", ch); else sprintf(build,"<%02X>", ch); - str += build; + str = str + build; } else str += ch; address++; } - str += gLineTerm + gOk; + str = str + gLineTerm + gOk; return str; } @@ -2327,6 +2381,73 @@ std::string cmd_disassemble(ServerSocket& sock, std::string& args) return gOk; } +/* +======================================================= +Trace command: Enables instruction tracing for all or + specific address ranges. +======================================================= +*/ +std::string cmd_screen_dump(ServerSocket& sock, std::string& args) +{ + int lines, col, line, first_line = 0; + unsigned short lcdAddr, curAddr; + + lines = gModel == MODEL_T200 ? 16 : 8; + + // For Model 200, the 1st byte of the LCD character buffer isn't + // always the first row on the LCD. There is a 1st row offset + // variable at FEAEh that tells which row is the 1st row + if (gModel == MODEL_T200) + first_line = get_memory8(0xFEAE); + + // Now find the address of the LCD Row storage +#if 0 + for (c = 0; ;c++) + { + // Test for end of table + if (gStdRomDesc->pVars[c].strnum == -1) + { + std::string ret = "Couldn't locate LCD buffer" + gLineTerm + gOk; + return ret; + } + + // Search for the Level 6 plotting function + if (gStdRomDesc->pVars[c].strnum == R_LCD_CHAR_BUF) + { + lcdAddr = gStdRomDesc->pVars[c].addr; + break; + } + } +#endif + + lcdAddr = gStdRomDesc->sLcdBuf; + + // Now loop through each row and build a string to send + curAddr = lcdAddr + first_line * 40; + unsigned short maxAddr = lcdAddr + lines * 40; + for (line = 0; line < lines; line++) + { + std::string line_buf = ""; + unsigned char ch; + for (col = 0; col < 40; col++) + { + ch = get_memory8(curAddr++); + if ((ch < ' ') || (ch > '~')) + ch = ' '; + line_buf += ch; + } + + // Terminate this line and send to the socket + line_buf += gLineTerm; + sock << line_buf; + + if (curAddr >= maxAddr) + curAddr = lcdAddr; + } + + return gOk; +} + /* ======================================================= Trace command: Enables instruction tracing for all or @@ -2455,43 +2576,196 @@ std::string cmd_trace(ServerSocket& sock, std::string& args) return gOk; } +/* +======================================================= +Routine to process TELNET bytes during subnegotiation. +======================================================= +*/ +void handle_telnet_sb(unsigned char ch) +{ + char temp[10]; + + switch (gSocket.sbState) + { + // Handle first entry into SB state. The first byte is + // The option code being negotiatied + case 0: + // Just save the TELNET option byte and exit + gSocket.sbOption = ch; + gSocket.sbState = 1; + + // If TERMINAL-TYPE option, clear the terminal type + if (ch == TELNET_TERMTYPE) + gTelnetTerminal[0] = 0; + + break; + + // Now we have the option byte, check for IS, etc + case 1: + switch (ch) + { + // We receive the TELNET_IS byte. Go get the parameter + case TELNET_IS: + gSocket.sbState = 2; + break; + + // Unknown...go back to non-telnet IAC mode + default: + gSocket.sbState = 0; + gSocket.iacState = 0; + break; + } + + // Receiving the option parameter + case 2: + switch (gSocket.sbOption) + { + // For TERMTYPE option, save terminal type to global string + case TELNET_TERMTYPE: + // Test if TELNET_IAC code during reception of terminal type + if (ch == TELNET_IAC) + { + printf("Term-type: %s\n", gTelnetTerminal); + gSocket.sbState = 0; + gSocket.iacState = ch; + break; + } + + // Not TELNET_IAC, save to terminal-type + strcat(gTelnetTerminal, temp); + break; + + // Other options not supported + default: + gSocket.sbState = 0; + gSocket.iacState = 0; + break; + } + + // Unknown case...abort back to non IAC mode + default: + gSocket.sbState = 0; + gSocket.iacState = 0; + break; + } +} + /* ======================================================= Routine to process remote commands ======================================================= */ -int telnet_command_ready(ServerSocket& sock, std::string &cmd) +int telnet_command_ready(ServerSocket& sock, std::string &cmd, char* sockData, int len) { - int len, x, cmd_term; + int x, cmd_term; + char temp[10]; - len = cmd.length(); cmd_term = FALSE; for (x = 0; x < len; x++) { - char ch = cmd.c_str()[x]; - printf("<%02Xh> ", ch); + unsigned char ch = sockData[x]; - /* Test for 0x0D and ignore it */ - if (ch == 0x0D) + /* Test if we are in an IAC mode */ + if (gSocket.iacState != 0) + { + switch (gSocket.iacState) + { + case TELNET_IAC: + switch (ch) + { + case TELNET_DO: + case TELNET_DONT: + case TELNET_WILL: + case TELNET_WONT: + gSocket.iacState = ch; + continue; + case TELNET_SB: + gSocket.iacState = ch; + gSocket.sbState = 0; + continue; + case TELNET_AYT: + sprintf(temp, "%c%c", TELNET_IAC, TELNET_GA); + sock << temp; + gSocket.iacState = ch; + continue; + + default: + gSocket.iacState = 0; + } + continue; + + case TELNET_WILL: + switch (ch) + { + // Process response from our IAC DO TERMINAL_TYPE query + case TELNET_TERMTYPE: + sprintf(temp, "%c%c%c%c%c%c", TELNET_IAC, TELNET_SB, TELNET_TERMTYPE, + TELNET_SEND, TELNET_IAC, TELNET_SE); + sock << temp; + gSocket.iacState = 0; + continue; + + default: + gSocket.iacState = 0; + continue; + } + case TELNET_SB: + handle_telnet_sb(ch); + continue; + + default: + gSocket.iacState = 0; + continue; + } + } + else if (ch == TELNET_IAC) + { + gSocket.iacState = TELNET_IAC; continue; + } + /* Test for 0x0a command line terminaor */ - if (ch == 0x0A) + if (ch == gTelnetCR) { + char temp[2]; cmd_term = TRUE; cmd = gTelnetCmd; gTelnetCmd = ""; + temp[0] = ch; + temp[1] = 0; +#ifdef WIN32 + sock << temp; + temp[0] = 0x0A; + sock << temp; +#endif break; } + /* Test for 0x0D and ignore it */ + if (ch == 0x0D) + { + char temp[2]; + temp[0] = ch; + temp[1] = 0; + temp[1] = 0; +#ifdef WIN32 + sock << temp; +#endif + continue; + } // Test for backspace if (ch == 0x08) { if (gTelnetCmd.length() == 0) { +#ifdef WIN32 sock << " "; +#endif continue; } gTelnetCmd = gTelnetCmd.substr(0, gTelnetCmd.length()-1); - sock << " \x08"; +#ifdef WIN32 + sock << "\x08 \x08"; +#endif continue; } @@ -2502,10 +2776,13 @@ int telnet_command_ready(ServerSocket& sock, std::string &cmd) temp[0] = ch; temp[1] = 0; gTelnetCmd = gTelnetCmd + temp; +#ifdef WIN32 + sock << temp; +#endif } else { - // TODO: Process telnet out-of band characters + // we don't need these chars in our command line } } @@ -2517,17 +2794,32 @@ int telnet_command_ready(ServerSocket& sock, std::string &cmd) Routine to process remote commands ======================================================= */ -std::string process_command(ServerSocket& sock, std::string cmd) +void send_telnet_greeting(ServerSocket& sock) +{ + sock << gLineTerm << "Welcome to the VirtualT v" << VERSION << " TELNET interface." << gLineTerm; + sock << "Use decimal, C hex (0x2a) or Asm hex (14h) for input." << gLineTerm; + sock << "Return data reported according to specified radix." << gLineTerm; + sock << "Type 'help' for a list of supported comands." << gLineTerm; + sock << gOk; +} + +/* +======================================================= +Routine to process remote commands +======================================================= +*/ +std::string process_command(ServerSocket& sock, char *sockdata, int len) { std::string ret = "Syntax error"; std::string cmd_word; std::string args; + std::string cmd = sockdata; // Test for telnet protocol bytes - if (gTelnet) + if (gSocket.telnet) { - ret += gLineTerm + gOk; - if (!telnet_command_ready(sock, cmd)) + ret = ret + gLineTerm + gOk; + if (!telnet_command_ready(sock, cmd, sockdata, len)) return ""; if (cmd == "") { @@ -2553,7 +2845,7 @@ std::string process_command(ServerSocket& sock, std::string cmd) if (cmd == "help") // Check for help ret = cmd_help(sock); - else if (cmd == "run") // Check for run + else if ((cmd == "run") || (cmd == "go")) // Check for run ret = cmd_run(sock); else if (cmd == "reset") // Check for reset @@ -2562,10 +2854,17 @@ std::string process_command(ServerSocket& sock, std::string cmd) else if (cmd == "terminate") // Check for terminate ret = cmd_terminate(sock); + else if ((cmd == "exit") || (cmd == "bye")) // Check for terminate + { + sock << "Thank you for contacting VirtualT v" << VERSION << ". Bye." << gLineTerm; + ret = ""; + gSocket.closeSocket = TRUE; + } + else if (cmd == "cold_boot") // Check for terminate ret = cmd_cold_boot(sock); - else if (cmd == "halt") // Check for halt + else if ((cmd == "halt") || (cmd == "stop")) // Check for halt ret = cmd_halt(sock); else if (cmd == "status") // Report status and any events @@ -2583,6 +2882,12 @@ std::string process_command(ServerSocket& sock, std::string cmd) else if ((cmd_word == "read_reg") || (cmd_word == "rr")) ret = cmd_read_reg(sock, args); + else if (cmd_word == "regs") + { + args = "all"; + ret = cmd_read_reg(sock, args); + } + else if ((cmd_word == "write_reg") || (cmd_word == "wr")) ret = cmd_write_reg(sock, args); @@ -2689,6 +2994,12 @@ std::string process_command(ServerSocket& sock, std::string cmd) else if ((cmd_word == "debug_isr") || (cmd_word == "isr")) ret = cmd_debug_isr(sock, args); + else if ((cmd_word == "screen_dump") || (cmd_word == "sd")) + ret = cmd_screen_dump(sock, args); + + else if (cmd_word == "rim") + ret = cmd_rim(sock, args); + else if (cmd_word == "x") { args = "pc " + args; @@ -2696,12 +3007,22 @@ std::string process_command(ServerSocket& sock, std::string cmd) gLastCmdDis = TRUE; return ret; } + else if (cmd_word.find('=') != -1) + ret = cmd_write_reg(sock, cmd); gLastCmdDis = FALSE; return ret; } +void initiate_termtype_negotiation(ServerSocket& sock) +{ + char buf[4]; + + sprintf(buf, "%c%c%c", TELNET_IAC ,TELNET_DO, TELNET_TERMTYPE); + sock << buf; + gSocket.termMode = REMOTE_TERM_INIT; +} /* ======================================================= @@ -2711,50 +3032,147 @@ Routine that will become the remote control thread. void* remote_control(void* arg) { std::string ret; - - gSocketOpened = FALSE; + char errmsg[80]; + char sockData[128]; + int len; + + // Create a listener socket on the desired port number + gSocket.listenPort = 0; + gSocket.socketOpened = FALSE; + gSocket.closeSocket = FALSE; + gSocket.serverSock = new ServerSocket(gSocket.socketPort); + gSocket.socketErrorMsg = ""; + if (gSocket.serverSock == NULL) + { + gSocket.socketError = TRUE; + sprintf(errmsg, "Unable to open port %d", gSocket.socketPort); + gSocket.socketErrorMsg = errmsg; + return NULL; + } + gSocket.listenPort = gSocket.socketPort; + + // Now listen on the listener port for connections try { - ServerSocket server(gSocketPort); - while (!gExitApp) + while (!gExitApp && !gSocket.socketShutdown) { - server.accept(gOpenSock); + gSocket.serverSock->accept(gSocket.openSock); try { - gSocketOpened = TRUE; - while (!gExitApp) + gSocket.socketError = FALSE; + gSocket.socketErrorMsg = ""; + gSocket.socketOpened = TRUE; + gSocket.closeSocket = FALSE; + + // Negotiate for the terminal type +// initiate_termtype_negotiation(gSocket.openSock); + + // Send greeting if in telnet mode + if (gSocket.telnet) + send_telnet_greeting(gSocket.openSock); + + while (!gExitApp && !gSocket.socketShutdown && !gSocket.closeSocket) { std::string data; - gOpenSock >> data; - ret = process_command(gOpenSock, data); - if (gTelnet) +// gSocket.openSock >> data; + + len = gSocket.openSock.recv(sockData, sizeof(sockData)); + + if (gSocket.socketShutdown) + break; + ret = process_command(gSocket.openSock, sockData, len); + + /* Test for exit / bye command to close the socket */ + if (gSocket.closeSocket) + { + gSocket.openSock << ret; + gSocket.openSock.shutdown(); + } + else if (gSocket.telnet) { if (ret != "") - gOpenSock << ret; + gSocket.openSock << ret; } else - gOpenSock << ret; + gSocket.openSock << ret; } } catch (SocketException&) { - gSocketOpened = FALSE; + gSocket.socketOpened = FALSE; } } } catch (SocketException& e) { - printf("Exception was caught: %s\nExiting thread\n",e.description().c_str()); + if (!gSocket.socketShutdown) + { + gSocket.socketError = TRUE; + gSocket.socketErrorMsg = e.description(); + } } - gSocketOpened = FALSE; - // Unhook from the debug callback processor debug_clear_monitor_callback(cb_remote_debug); + + // Shutdown and close the server listener socket + gSocket.socketOpened = FALSE; + delete gSocket.serverSock; + gSocket.serverSock = NULL; + gSocket.listenPort = 0; + gSocket.enabled = FALSE; return NULL; } +/* +======================================================= +Tears down the remote control socket inerface. +======================================================= +*/ +void deinit_remote(void) +{ + // First teardown the listener socket so we don't accept anything new + gSocket.socketShutdown = TRUE; + if (gSocket.serverSock != NULL) + { + // Just shutdown the socket. The remote thread will delete it + try { + gSocket.serverSock->shutdown(); + gSocket.listenPort = 0; + } + catch (SocketException &e) + { + gSocket.socketError = TRUE; + gSocket.socketErrorMsg = e.description(); + } + } + + // Now check for an opened socket. If none opened, then we are done + if (gSocket.socketOpened == FALSE) + return; + + // Try to shutdown the open socket + try { + gSocket.openSock.shutdown(); + } + catch (SocketException &e) + { + gSocket.socketError = TRUE; + gSocket.socketErrorMsg = e.description(); + gSocket.socketOpened = FALSE; + } + + // Wait for the thread to report shutdown + int retry = 0; + while (retry < 200) + { + if (gSocket.socketOpened == FALSE) + break; + Fl::wait(.01); + } +} + /* ======================================================= Configure remote control using sockets inerface. @@ -2764,12 +3182,26 @@ void init_remote(void) { int c; + /* + Test if we need to override the preferences settings + with the command line settings during the 1st + invocation of init_remote + */ + if (gSocket.cmdLinePort) + { + gSocket.socketPort = gSocket.cmdLinePort; + gSocket.telnet = gSocket.cmdLineTelnet; + gSocket.cmdLinePort = 0; + gSocket.cmdLineTelnet = 0; + gSocket.enabled = TRUE; + } + // Check if Remote Socket interface enabled - if (gSocketPort == 0) + if ((gSocket.socketPort == 0) || (gSocket.enabled == FALSE)) return; // Initialize breakpoints - for (c = 0; c < 32768; c++) + for (c = 0; c < 65536; c++) { // Zero all breakpoints gRemoteBreak[c] = 0; @@ -2779,63 +3211,84 @@ void init_remote(void) debug_set_monitor_callback(cb_remote_debug); // Setup the line termination for \r\n if in telnet mode - if (gTelnet) + if (gSocket.telnet) { gLineTerm = "\r\n"; gOk = "Ok> "; gParamError = "Parameter Error" + gLineTerm + "Ok> "; +#ifdef WIN32 + gTelnetCR = '\r'; +#else + gTelnetCR = '\n'; +#endif } + // Clear the shutdown flag + gSocket.socketShutdown = FALSE; + // Create the thread #ifdef WIN32 DWORD id; - gRemoteLock = CreateMutex(NULL, FALSE, NULL); WORD wVersionRequested; WSADATA wsaData; int err; - wVersionRequested = MAKEWORD( 1, 1 ); - - err = WSAStartup( wVersionRequested, &wsaData ); - if ( err != 0 ) - { - /* Tell the user that we couldn't find a useable */ - /* winsock.dll. */ - return; - } - - /* Confirm that the Windows Sockets DLL supports 1.1.*/ - /* Note that if the DLL supports versions greater */ - /* than 1.1 in addition to 1.1, it will still return */ - /* 1.1 in wVersion since that is the version we */ - /* requested. */ - - if ( LOBYTE( wsaData.wVersion ) != 1 || - HIBYTE( wsaData.wVersion ) != 1 ) - { - /* Tell the user that we couldn't find a useable */ - /* winsock.dll. */ - WSACleanup( ); - return; - } + if (!gSocket.socketInitDone) + { + gRemoteLock = CreateMutex(NULL, FALSE, NULL); + + wVersionRequested = MAKEWORD( 1, 1 ); + + err = WSAStartup( wVersionRequested, &wsaData ); + if ( err != 0 ) + { + /* Tell the user that we couldn't find a useable */ + /* winsock.dll. */ + return; + } + + /* Confirm that the Windows Sockets DLL supports 1.1.*/ + /* Note that if the DLL supports versions greater */ + /* than 1.1 in addition to 1.1, it will still return */ + /* 1.1 in wVersion since that is the version we */ + /* requested. */ + + if ( LOBYTE( wsaData.wVersion ) != 1 || + HIBYTE( wsaData.wVersion ) != 1 ) + { + /* Tell the user that we couldn't find a useable */ + /* winsock.dll. */ + WSACleanup( ); + return; + } + } gRemoteThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) remote_control, NULL, 0, &id); #else - // Initialize thread processing - pthread_mutex_init(&gRemoteLock, NULL); + if (!gSocket.socketInitDone) + { + // Initialize thread processing + pthread_mutex_init(&gRemoteLock, NULL); + } pthread_create(&gRemoteThread, NULL, remote_control, NULL); #endif + + // Set Init flag so we only init once + gSocket.socketInitDone = TRUE; } +volatile long gRemoteThreadId = 0L; + void lock_remote(void) { - if (gSocketPort != 0) + if (gSocket.socketPort != 0) #ifdef WIN32 - WaitForSingleObject(gRemoteLock, INFINITE); +// WaitForSingleObject(gRemoteLock, INFINITE); + InterlockedCompareExchange(&gRemoteThreadId, GetCurrentThreadId(), 0); #else pthread_mutex_lock(&gRemoteLock); #endif @@ -2843,11 +3296,167 @@ void lock_remote(void) void unlock_remote(void) { - if (gSocketPort != 0) + if (gSocket.socketPort != 0) #ifdef WIN32 - ReleaseMutex(gRemoteLock); +// ReleaseMutex(gRemoteLock); + InterlockedCompareExchange(&gRemoteThreadId, 0, GetCurrentThreadId()); #else pthread_mutex_unlock(&gRemoteLock); #endif } + +/* +======================================================= +Set socket port from command line. Overrides initial +setting from preferences. +======================================================= +*/ +void set_remote_cmdline_port(int port) +{ + gSocket.cmdLinePort = port; + gSocket.enabled = TRUE; +} + +/* +======================================================= +Set socket telnet from command line. Overrides initial +setting from preferences. +======================================================= +*/ +void set_remote_cmdline_telnet(int telnet) +{ + gSocket.cmdLineTelnet = telnet; +} + +/* +======================================================= +Set socket port from preferences. +======================================================= +*/ +void set_remote_port(int port) +{ + gSocket.socketPort = port; +} + +/* +======================================================= +Set socket telnet from preferences. +======================================================= +*/ +void set_remote_telnet(int telnet) +{ + gSocket.telnet = telnet; +} + +/* +======================================================= +Get the socket listening port. This will return zero +if the listener port is not open. +======================================================= +*/ +int get_remote_listen_port(void) +{ + return gSocket.listenPort; +} + +/* +======================================================= +Get the socket telnet enable status +======================================================= +*/ +int get_remote_telnet(void) +{ + return gSocket.telnet; +} + +/* +======================================================= +Get the socket error status. If this returns TRUE, then +the error string will contain the error message. +======================================================= +*/ +int get_remote_error_status(void) +{ + return gSocket.socketError; +} + +/* +======================================================= +Get the socket error message. +======================================================= +*/ +std::string get_remote_error(void) +{ + return gSocket.socketErrorMsg; +} + +/* +======================================================= +Get the socket connection status. This will return +TRUE if a client is connected. +======================================================= +*/ +int get_remote_connect_status(void) +{ + return gSocket.socketOpened; +} + +/* +======================================================= +Get the telnet enable status. +======================================================= +*/ +int get_remote_connect_telnet(void) +{ + return gSocket.telnet; +} + +/* +======================================================= +Get the target listener port. This may be different +than the listen port if the port cannot be opened. +======================================================= +*/ +int get_remote_port(void) +{ + return gSocket.socketPort; +} + +/* +======================================================= +Gets the user preference for the socket enabled setting +======================================================= +*/ +int get_remote_enabled(void) +{ + return gSocket.enabled; +} + +/* +======================================================= +Gets the user preference for the socket enabled setting +======================================================= +*/ +void enable_remote(int enabled) +{ + gSocket.enabled = enabled; +} + +/* +======================================================= +Loads the user preferences for the socket interface. +======================================================= +*/ +void load_remote_preferences() +{ + int enabled, telnet; + + virtualt_prefs.get("SocketPort", gSocket.socketPort, get_remote_port()); + virtualt_prefs.get("SocketTelnetMode", telnet, get_remote_telnet()); + int default_enabled = gSocket.cmdLinePort != 0; + virtualt_prefs.get("SocketEnabled", enabled, default_enabled); + + gSocket.enabled = enabled; + gSocket.telnet = telnet; +} diff --git a/src/remote.h b/src/remote.h index 731e377..9098c8c 100644 --- a/src/remote.h +++ b/src/remote.h @@ -32,15 +32,34 @@ #define _REMOTE_H_ #ifdef __cplusplus + +#include + extern "C" { #endif void init_remote(void); +void deinit_remote(void); void lock_remote(void); void unlock_remote(void); +void enable_remote(int enabled); +void set_remote_cmdline_port(int port); +void set_remote_cmdline_telnet(int telnet); +int get_remote_listen_port(); +int get_remote_connect_status(); +int get_remote_error_status(void); +int get_remote_telnet(void); +int get_remote_port(void); +int get_remote_enabled(void); +void set_remote_port(int port); +void set_remote_telnet(int telnet); +void load_remote_preferences(); #ifdef __cplusplus } + +std::string get_remote_error(); + #endif #define BPTYPE_MAIN 0x01 @@ -60,4 +79,30 @@ typedef struct int bottom_col; } lcd_rect_t; +#define REMOTE_TERM_INIT 1 + +/* Define TELNET option codes */ +#define TELNET_IS 0 +#define TELNET_SEND 1 /* Send */ +#define TELNET_ECHO 1 /* Send and echo are the same */ +#define TELNET_SUPPRESS_GA 3 /* Suppres go ahead */ +#define TELNET_TERMTYPE 24 /* Terminal-type option */ +#define TELNET_WINDOW_SIZE 31 /* Window size negotiation */ + +/* Define TELNET Command Codes */ +#define TELNET_SE 240 /* End of sub-negotiation parameters */ +#define TELNET_DM 242 /* Data Mark */ +#define TELNET_IP 244 +#define TELNET_AO 245 +#define TELNET_AYT 246 /* Are You There */ +#define TELNET_EC 247 /* Erase Character */ +#define TELNET_EL 248 /* Erase Line */ +#define TELNET_GA 249 /* Go Ahead */ +#define TELNET_SB 250 /* Subnegotiation */ +#define TELNET_WILL 251 /* Will send */ +#define TELNET_WONT 252 /* Won't send (not willing) */ +#define TELNET_DO 253 /* Do support receive */ +#define TELNET_DONT 254 /* Don't support receive */ +#define TELNET_IAC 255 /* Intrepret As Command */ + #endif diff --git a/src/roms.h b/src/roms.h index 3c6e7bd..75d8114 100644 --- a/src/roms.h +++ b/src/roms.h @@ -78,6 +78,8 @@ typedef struct RomDescription { unsigned short sKeyscan; /* Location of Keyscan array */ unsigned short sCharTable; /* Location of Charater generator table */ unsigned short sYear; /* Location of Year storage */ + unsigned short sLcdBuf; /* Lccation of LCD buffer */ + unsigned short sLabelEn; /* Label line enable flag */ unsigned short sDirCount; /* Number of entries in Directory */ unsigned short sFirstDirEntry; /* Index of first available enry */ diff --git a/src/rpn_eqn.cpp b/src/rpn_eqn.cpp index 75278ce..0453998 100644 --- a/src/rpn_eqn.cpp +++ b/src/rpn_eqn.cpp @@ -25,6 +25,18 @@ void CRpnEquation::Add(int operation) m_OperationArray.Add(op); } +void CRpnEquation::Add(int operation, const char *var) +{ + CRpnOperation* op = new CRpnOperation; + + // Fill operation with operation code + op->m_Operation = operation; + op->m_Variable = var; + + // Add operation to array + m_OperationArray.Add(op); +} + void CRpnEquation::Add(double value) { CRpnOperation* op = new CRpnOperation; @@ -48,3 +60,16 @@ void CRpnEquation::Add(const char *var) // Add operation to array m_OperationArray.Add(op); } + +void CRpnEquation::Add(VTObject* pMacro) +{ + CRpnOperation* op = new CRpnOperation; + + // Fill operation with operation code + op->m_Operation = RPN_MACRO; + op->m_Macro = pMacro; + + // Add operation to array + m_OperationArray.Add(op); +} + diff --git a/src/rpn_eqn.h b/src/rpn_eqn.h index 741f0bd..158c9d1 100644 --- a/src/rpn_eqn.h +++ b/src/rpn_eqn.h @@ -1,5 +1,8 @@ // RpnEquation.h: This file defines the CRpnEquation class +#ifndef _RPN_EQUATION_H_ +#define _RPN_EQUATION_H_ + #include "MString.h" #include "MStringArray.h" @@ -28,16 +31,23 @@ const int RPN_SQRT = 21; const int RPN_LAST = 22; const int RPN_NOT = 23; const int RPN_BITNOT = 24; +const int RPN_HIGH = 25; +const int RPN_LOW = 26; +const int RPN_DEFINED = 27; +const int RPN_NEGATE = 28; +const int RPN_MACRO = 29; class CRpnOperation : public VTObject { public: - CRpnOperation() { m_Value = 0.0; m_Operation = 0; }; + CRpnOperation() { m_Value = 0.0; m_Operation = 0; m_Macro = NULL; }; + ~CRpnOperation() { if (m_Macro != NULL) delete m_Macro; } // Attributes int m_Operation; MString m_Variable; // Used only for variable operations double m_Value; + VTObject* m_Macro; // Used to save macros in the code }; class CRpnOpArray : public VTObArray @@ -61,8 +71,13 @@ class CRpnEquation : public VTObject void Add(const char * var); void Add(double value); void Add(int operation); + void Add(int operation, const char *var); + void Add(VTObject *macro); // Attributes CRpnOpArray m_OperationArray; int m_EqPtr; }; + +#endif /* _RPN_EQUATION_H_ */ + diff --git a/src/serial.c b/src/serial.c index 7256e08..d1f664b 100644 --- a/src/serial.c +++ b/src/serial.c @@ -59,7 +59,11 @@ ser_params_t sp; extern int gModel; -#ifndef WIN32 +#ifdef WIN32 + +void read_port_flags(ser_params_t *sp); + +#else /* =========================================================================== ser_tx_remaining: Get # bytes remaining to transmit @@ -108,6 +112,9 @@ int ser_init(void) sp.rxOut = 0; sp.txIn = 0; // Initialize TX buffer sp.txOut = 0; + sp.flags = 0; + read_port_flags(&sp); + // Create overlapped read event. Must be closed before exiting // to avoid a handle leak. @@ -333,6 +340,74 @@ void ErrorReporter(char* text) // show_error(text); } +/* +=========================================================================== +read_port_flags: Reads the serial port's CTS, RTS, etc flags and updates + the flags variable within the structure. This is called + at initialization and fromt the ReadProc when a change + in state is detected. This prevents the emulation from + having to call the very expensive GetCommmModemStatus + routine from the main ROM's menu routine. +=========================================================================== +*/ +void read_port_flags(ser_params_t *sp) +{ + long modem_status; + + if (!GetCommModemStatus(sp->hComm, &modem_status)) + { + sp->flags = 0; + if (sp->tx_empty) + sp->flags |= SER_FLAG_TX_EMPTY; + } + else + { + sp->flags = 0; + if (setup.com_ignore_flow) + { + if (sp->dtrState == DTR_CONTROL_ENABLE); + sp->flags |= SER_FLAG_CTS; + if (sp->rtsState == RTS_CONTROL_ENABLE) + sp->flags |= SER_FLAG_CTS; + } + + // Set CTS flag + if (gModel == MODEL_T200) + { + if (modem_status & MS_CTS_ON) + sp->flags |= SER_FLAG_CTS; + } + else + { + if ((modem_status & MS_CTS_ON) == 0) + sp->flags |= SER_FLAG_CTS; + } + + // Set DSR flag + if (gModel == MODEL_T200) + { + if (modem_status & MS_DSR_ON) + sp->flags |= SER_FLAG_DSR; + } + else + { + if ((modem_status & MS_DSR_ON) == 0) + sp->flags |= SER_FLAG_DSR; + } + } + + // RING flag + if (modem_status & MS_RING_ON) + sp->flags |= SER_FLAG_RING; + + // TX_EMPTY flag + if (sp->tx_empty) + sp->flags |= SER_FLAG_TX_EMPTY; + + // OVERRUN flag + + // FRAMING Error flag +} /* =========================================================================== process_read_byte: Called when a byte is received by the COM port. This @@ -357,7 +432,7 @@ void process_read_byte(ser_params_t *sp, char byte) // Call callback to indicate receipt of data if (sp->pCallback != NULL) { - sp->pCallback(); + sp->pCallback(TRUE); sp->fIntPending = TRUE; } @@ -474,8 +549,12 @@ DWORD ReadProc(LPVOID lpv) sp->pMonCallback(SER_MON_COM_SIGNAL, 0); ResetEvent(osStatus.hEvent); } - } + if (dwCommEvent & (EV_CTS | EV_DSR | EV_RING)) + { + read_port_flags(sp); + } + } // wait for pending operations to complete if ( fWaitingOnRead || fWaitingOnStat ) @@ -601,8 +680,14 @@ DWORD WINAPI WriteProc(LPVOID lpv) } sp->tx_empty = TRUE; + sp->flags |= SER_FLAG_TX_EMPTY; } } + else + { + sp->tx_empty = TRUE; + sp->flags |= SER_FLAG_TX_EMPTY; + } break; @@ -1263,60 +1348,7 @@ int ser_get_flags(unsigned char *flags) } #ifdef WIN32 - if (!GetCommModemStatus(sp.hComm, &modem_status)) - { - *flags = 0; - if (sp.tx_empty) - *flags |= SER_FLAG_TX_EMPTY; - return SER_IO_ERROR; - } - - *flags = 0; - - if (setup.com_ignore_flow) - { - if (sp.dtrState == DTR_CONTROL_ENABLE); - *flags |= SER_FLAG_CTS; - if (sp.rtsState == RTS_CONTROL_ENABLE) - *flags |= SER_FLAG_CTS; - } - { - // Set CTS flag - if (gModel == MODEL_T200) - { - if (modem_status & MS_CTS_ON) - *flags |= SER_FLAG_CTS; - } - else - { - if ((modem_status & MS_CTS_ON) == 0) - *flags |= SER_FLAG_CTS; - } - - // Set DSR flag - if (gModel == MODEL_T200) - { - if (modem_status & MS_DSR_ON) - *flags |= SER_FLAG_DSR; - } - else - { - if ((modem_status & MS_DSR_ON) == 0) - *flags |= SER_FLAG_DSR; - } - } - - // RING flag - if (modem_status & MS_RING_ON) - *flags |= SER_FLAG_RING - ; - // TX_EMPTY flag - if (sp.tx_empty) - *flags |= SER_FLAG_TX_EMPTY; - - // OVERRUN flag - - // FRAMING Error flag + *flags = sp.flags; WaitForSingleObject(sp.hReadMutex, 2000); @@ -1324,7 +1356,7 @@ int ser_get_flags(unsigned char *flags) { if (sp.pCallback != NULL) { - sp.pCallback(); + sp.pCallback(TRUE); sp.fIntPending = TRUE; } } @@ -1482,6 +1514,8 @@ int ser_read_byte(char* data) // Check if any bytes in RX buffer if (sp.rxIn == sp.rxOut) { + if (sp.pCallback != NULL) + sp.pCallback(FALSE); /* Clear the INT6.5 input pin */ ReleaseMutex(sp.hReadMutex); // No data in buffer! *data = 0; @@ -1499,7 +1533,12 @@ int ser_read_byte(char* data) sp.rxOut = new_rxOut; ReleaseMutex(sp.hReadMutex); - sp.fIntPending = FALSE; + if (sp.rxIn == sp.rxOut) + { + if (sp.pCallback != NULL) + sp.pCallback(FALSE); /* Clear the INT6.5 input pin */ + sp.fIntPending = FALSE; + } #else { @@ -1512,6 +1551,8 @@ int ser_read_byte(char* data) return SER_NO_DATA; } + /* Perform a ser_poll to test for more bytes and maybe clear INT6.5 */ + ser_poll(); } #endif } @@ -1548,6 +1589,7 @@ int ser_write_byte(char data) // Update tx_empy flag indicating byte to write sp.tx_empty = FALSE; + sp.flags &= ~SER_FLAG_TX_EMPTY; ReleaseMutex(sp.hWriteMutex); @@ -1588,8 +1630,9 @@ int ser_poll () ioctl(sp.fd, FIONREAD, &bytes); - if (bytes && sp.pCallback) { - sp.pCallback(); + if (sp.pCallback) + { + sp.pCallback(bytes); } return 0; diff --git a/src/serial.h b/src/serial.h index 820d8a2..7338686 100644 --- a/src/serial.h +++ b/src/serial.h @@ -76,7 +76,7 @@ enum { extern "C" { #endif -typedef void (*ser_callback)(); +typedef void (*ser_callback)(int pinLevel); typedef void (*ser_monitor_cb)(int fMonType, unsigned char data); /* Configuration functions */ @@ -148,6 +148,7 @@ typedef struct ser_params int txIn; // Read buffer input location int txOut; // Read buffer output location int tx_empty; // Flag to indicate when TX is done + char flags; // Current COMM port state flags #else int fd; // fd of open serial port diff --git a/src/serversocket.cpp b/src/serversocket.cpp index ff9601e..309ef18 100644 --- a/src/serversocket.cpp +++ b/src/serversocket.cpp @@ -57,3 +57,16 @@ void ServerSocket::accept ( ServerSocket& sock ) throw SocketException ( "Could not accept socket." ); } } + +int ServerSocket::recv ( char* rxBuf, int rxLen ) const +{ + int ret; + + ret = Socket::recv(rxBuf, rxLen); + + if (!ret) + { + throw SocketException ( "Could not read from socket."); + } + return ret; +} diff --git a/src/serversocket.h b/src/serversocket.h index 4e393a6..3b9a74e 100644 --- a/src/serversocket.h +++ b/src/serversocket.h @@ -16,8 +16,11 @@ class ServerSocket : private Socket const ServerSocket& operator << ( const std::string& ) const; const ServerSocket& operator >> ( std::string& ) const; + void accept ( ServerSocket& ); + bool shutdown (void) { return Socket::shutdown(); }; + int recv ( char* rxBuf, int rxLen ) const; }; diff --git a/src/setup.cpp b/src/setup.cpp index 2e62360..f2497d6 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -47,6 +47,8 @@ #include #include +#include "FLU/Flu_File_Chooser.h" + #include "m100emu.h" #include "serial.h" #include "setup.h" @@ -144,6 +146,11 @@ memory_ctrl_t mem_ctrl; // Memory setup window peripheral_setup_t setup; // Setup options memory_setup_t mem_setup; // Memory setup options +extern "C" +{ +extern int sound_enable; // C-style variable to enable sound +} + /* ============================================================================ Routines to load and save setup structure to the user preferences @@ -168,6 +175,7 @@ void save_setup_preferences(void) // Save BCR emulation settings // Save Sound emulation settings + virtualt_prefs.set("SoundEnable", setup.sound_enable); // Save Clock preference settings save_clock_preferences(&virtualt_prefs); @@ -199,6 +207,7 @@ void load_setup_preferences(void) // Load BCR emulation settings // Load Sound emulation settings + virtualt_prefs.get("SoundEnable", setup.sound_enable, 0); // Load Clock emulation settings load_clock_preferences(&virtualt_prefs); @@ -211,7 +220,7 @@ void load_setup_preferences(void) { ret=ChooseWorkDir(); // return the directory if(ret==NULL) - exit(-1); //nothing choose: do nothing.... + return; //nothing choose: do nothing.... else { strcpy(path,ret); @@ -921,7 +930,7 @@ void cb_memory_OK(Fl_Widget* w, void*) void cb_remem_browse(Fl_Widget* w, void*) { int count; - Fl_File_Chooser *fc; + Flu_File_Chooser *fc; const char *filename; const char *filename_name; int len; @@ -932,7 +941,9 @@ void cb_remem_browse(Fl_Widget* w, void*) // Create chooser window to pick file strcpy(path, mem_ctrl.pReMemFile->value()); - fc = new Fl_File_Chooser(path,"Binary Files (*.bin)",2,"Choose ReMem File"); + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser(path,"Binary Files (*.bin)",2,"Choose ReMem File"); + fl_cursor(FL_CURSOR_DEFAULT); fc->preview(0); fc->show(); @@ -978,7 +989,7 @@ void cb_remem_browse(Fl_Widget* w, void*) void cb_rex_browse(Fl_Widget* w, void*) { int count; - Fl_File_Chooser *fc; + Flu_File_Chooser *fc; const char *filename; const char *filename_name; int len; @@ -989,7 +1000,9 @@ void cb_rex_browse(Fl_Widget* w, void*) // Create chooser window to pick file strcpy(path, mem_ctrl.pRexFlashFile->value()); - fc = new Fl_File_Chooser(path,"Binary Files (*.bin)",2,"Choose Rex Flash File"); + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser(path,"Binary Files (*.bin)",2,"Choose Rex Flash File"); + fl_cursor(FL_CURSOR_DEFAULT); fc->preview(0); fc->show(); @@ -1035,7 +1048,7 @@ void cb_rex_browse(Fl_Widget* w, void*) void cb_rex2_browse(Fl_Widget* w, void*) { int count; - Fl_File_Chooser *fc; + Flu_File_Chooser *fc; const char *filename; const char *filename_name; int len; @@ -1046,7 +1059,9 @@ void cb_rex2_browse(Fl_Widget* w, void*) // Create chooser window to pick file strcpy(path, mem_ctrl.pRex2RamFile->value()); - fc = new Fl_File_Chooser(path,"Binary Files (*.bin)",2,"Choose Rex2 RAM File"); + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser(path,"Binary Files (*.bin)",2,"Choose Rex2 RAM File"); + fl_cursor(FL_CURSOR_DEFAULT); fc->preview(0); fc->show(); @@ -1182,7 +1197,7 @@ void cb_memory_cancel (Fl_Widget* w, void*) void cb_rampac_browse (Fl_Widget* w, void*) { int count; - Fl_File_Chooser *fc; + Flu_File_Chooser *fc; const char *filename; const char *filename_name; int len; @@ -1193,7 +1208,9 @@ void cb_rampac_browse (Fl_Widget* w, void*) // Create chooser window to pick file strcpy(path, mem_ctrl.pRampacFile->value()); - fc = new Fl_File_Chooser(path,"Binary Files (*.bin)",2,"Choose Rampac File"); + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser(path,"Binary Files (*.bin)",2,"Choose Rampac File"); + fl_cursor(FL_CURSOR_DEFAULT); fc->preview(0); fc->show(); @@ -1312,14 +1329,14 @@ void cb_MemorySetup (Fl_Widget* w, void*) } // Create Rex radio button - mem_ctrl.pRex = new Fl_Round_Button(20, 210, 270, 20, "Rex (1 Meg Flash Option ROM)"); + mem_ctrl.pRex = new Fl_Round_Button(20, 210, 270, 20, "Rex (1M Flash Option ROM)"); mem_ctrl.pRex->type(FL_RADIO_BUTTON); mem_ctrl.pRex->callback(cb_radio_rex); if (mem_setup.mem_mode == SETUP_MEM_REX) mem_ctrl.pRex->value(1); // Create Rex radio button - mem_ctrl.pRex2 = new Fl_Round_Button(20, 235, 270, 20, "Rex2 (1 Meg Opt ROM + 256K SRAM)"); + mem_ctrl.pRex2 = new Fl_Round_Button(20, 235, 270, 20, "Rex2 (1M Opt ROM + 128K SRAM)"); mem_ctrl.pRex2->type(FL_RADIO_BUTTON); mem_ctrl.pRex2->callback(cb_radio_rex2); if (mem_setup.mem_mode == SETUP_MEM_REX2) diff --git a/src/setup.h b/src/setup.h index fc15526..fd58d5e 100644 --- a/src/setup.h +++ b/src/setup.h @@ -34,6 +34,7 @@ #ifdef __cplusplus void cb_PeripheralSetup (Fl_Widget* w, void*); void cb_MemorySetup (Fl_Widget* w, void*); +void cb_SocketSetup (Fl_Widget* w, void*); extern "C" { #endif @@ -60,6 +61,7 @@ typedef struct peripheral_setup // BCR port emulation settings // Sound emulation settings + int sound_enable; // Set TRUE when sound is enabled } peripheral_setup_t; diff --git a/src/socket.cpp b/src/socket.cpp index 8659696..7da2281 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -3,6 +3,7 @@ #include "socket.h" #include "string.h" +#include #include #include #include @@ -162,6 +163,20 @@ int Socket::recv ( std::string& s ) const } } +int Socket::recv ( char* rxBuf, int rxLen ) const +{ + memset ( rxBuf, 0, rxLen ); + + int status = ::recv ( m_sock, rxBuf, rxLen, 0 ); + + if ( status == -1 ) + { + printf("status == -1 errno == %d in Socket::recv\n", errno); + return 0; + } + + return status; +} bool Socket::connect ( const std::string host, const int port ) @@ -183,6 +198,18 @@ bool Socket::connect ( const std::string host, const int port ) return false; } +bool Socket::shutdown() +{ + if (!is_valid()) + return false; +#ifdef WIN32 + ::closesocket ( m_sock ); +#else + ::close ( m_sock ); +#endif + return true; +} + /*void Socket::set_non_blocking ( const bool b ) { diff --git a/src/socket.h b/src/socket.h index 3985291..bbe39df 100644 --- a/src/socket.h +++ b/src/socket.h @@ -35,6 +35,7 @@ class Socket // Server initialization bool create(); + bool shutdown(); bool bind ( const int port ); bool listen() const; bool accept ( Socket& ) const; @@ -45,6 +46,7 @@ class Socket // Data Transimission bool send ( const std::string ) const; int recv ( std::string& ) const; + int recv ( char* rxBuf, int rxLen ) const; // void set_non_blocking ( const bool ); diff --git a/src/socketdlg.cpp b/src/socketdlg.cpp new file mode 100644 index 0000000..63cff51 --- /dev/null +++ b/src/socketdlg.cpp @@ -0,0 +1,283 @@ +/* socketdlg.cpp */ + +/* $Id$ */ + +/* + * Copyright 2009 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "genwrap.h" +#include "m100emu.h" +#include "setup.h" +#include "memedit.h" +#include "remote.h" + +extern Fl_Preferences virtualt_prefs; + +typedef struct sockdlg_ctrl_struct +{ + Fl_Input* pPortNumber; + Fl_Check_Button* pTelnet; + Fl_Check_Button* pEnable; + Fl_Box* pStatus; + Fl_Button* pApply; + char sPortNumber[20]; + char sStatus[256]; +} sockdlg_ctrl_t; + +static Fl_Window *gsdw; // SocketDlg window +static sockdlg_ctrl_t sockdlg_ctrl; // SocketDlg window controls + +/* +============================================================================ +Callback routines for the Setup Window +============================================================================ +*/ +static void cb_sockdlg_cancel (Fl_Widget* w, void*) +{ + gsdw->hide(); + delete gsdw; + gsdw = NULL; +} + +/* +============================================================================ +This routine updates the status line of the dialog box based on the current +remote socket connection status. +============================================================================ +*/ +void update_port_status(void) +{ + if (get_remote_error_status()) + strcpy(sockdlg_ctrl.sStatus, get_remote_error().c_str()); + else if (get_remote_connect_status()) + strcpy(sockdlg_ctrl.sStatus, "Connected with client"); + else if (get_remote_listen_port() != 0) + sprintf(sockdlg_ctrl.sStatus, "Listening on port %d", get_remote_listen_port()); + else + strcpy(sockdlg_ctrl.sStatus, "Sockets not active"); + sockdlg_ctrl.pStatus->label(sockdlg_ctrl.sStatus); +} + +/* +============================================================================ +This routine applies the current settings in the dialog box and calls the +remote API functions to setup and teardown the socket interface. It is +called by the OK button also. +============================================================================ +*/ +static void cb_sockdlg_apply(Fl_Widget* w, void*) +{ + int port_num = 0, listen_port; + int telnet; + int enabled; + + // ============================================== + // Get Port Number & telnet flag + // ============================================== + if (sockdlg_ctrl.pPortNumber->value() != NULL) + port_num = atoi(sockdlg_ctrl.pPortNumber->value()); + telnet = sockdlg_ctrl.pTelnet->value(); + enabled = sockdlg_ctrl.pEnable->value(); + + // Test if the socket is enabled but the port is invalid + if (enabled && ((port_num <= 0) || (port_num >= 65536))) + { + fl_alert("Please provide a port number between 1 and 65535"); + return; + } + + // Get the remote socket status + listen_port = get_remote_listen_port(); + + // Test if the socket is enabled and the user want's it disabled + if (!enabled) + { + // Check if the socket is currently active and shutdown if it is + if (listen_port != 0) + deinit_remote(); + } + + // Test if we are enabling the socket for a different port number + if (enabled && listen_port && (listen_port != port_num)) + deinit_remote(); + + // Set the new port parameters + set_remote_telnet(telnet); + if (enabled) + set_remote_port(port_num); + else + set_remote_port(0); + enable_remote(enabled); + + // Update preferences + virtualt_prefs.set("SocketPort", port_num); + virtualt_prefs.set("SocketTelnetMode", telnet); + virtualt_prefs.set("SocketEnabled", enabled); + + // Now enable the socket if the socket number is different + if (enabled && (listen_port != port_num)) + { + init_remote(); + } + + // If the apply button was pressed, then wait a bit for the port + // status to change in the remote thread, then update the + // port status + if (w == sockdlg_ctrl.pApply) + { + SLEEP(500); + update_port_status(); + } +} + +/* +============================================================================ +Okay button handler. This calls the apply handler and closes the window. +============================================================================ +*/ +static void cb_sockdlg_OK(Fl_Widget* w, void*) +{ + // Call the apply functionality + cb_sockdlg_apply(w, NULL); + + // Destroy the window + gsdw->hide(); + delete gsdw; +} + +/* +============================================================================ +Routine to create the PeripheralSetup Window and tabs +============================================================================ +*/ +static void cb_sockdlg_enable (Fl_Widget* w, void*) +{ + if (sockdlg_ctrl.pEnable->value()) + { + sockdlg_ctrl.pPortNumber->activate(); + sockdlg_ctrl.pTelnet->activate(); + } + else + { + sockdlg_ctrl.pPortNumber->deactivate(); + sockdlg_ctrl.pTelnet->deactivate(); + } +} + +/* +============================================================================ +Callback to close the Socket Dialog window +============================================================================ +*/ +static void cb_sockdlg_win (Fl_Widget* w, void*) +{ + gsdw->hide(); + delete gsdw; + gsdw = NULL; +} + +/* +============================================================================ +Routine to create the PeripheralSetup Window and tabs +============================================================================ +*/ +void cb_SocketSetup (Fl_Widget* w, void*) +{ + Fl_Box* b; + int port_num, enabled, telnet; + + // Get socket interface preferences + virtualt_prefs.get("SocketPort", port_num, get_remote_port()); + telnet = get_remote_telnet(); + enabled = get_remote_enabled(); + + // Create Peripheral Setup window + gsdw = new Fl_Window(300, 260, "Socket Configuration"); + gsdw->callback(cb_sockdlg_win); + + /* Create enable checkbox */ + sockdlg_ctrl.pEnable = new Fl_Check_Button(20, 20, 190, 20, "Enable Socket Interface"); + sockdlg_ctrl.pEnable->callback(cb_sockdlg_enable); + sockdlg_ctrl.pEnable->value(enabled); + + /* Create input field for for port number */ + b = new Fl_Box(50, 50, 70, 20, "Port Number"); + b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + sockdlg_ctrl.pPortNumber = new Fl_Input(160, 50, 60, 20, ""); + sockdlg_ctrl.pPortNumber->align(FL_ALIGN_LEFT); + sprintf(sockdlg_ctrl.sPortNumber, "%d", port_num); + sockdlg_ctrl.pPortNumber->value(sockdlg_ctrl.sPortNumber); + + // Create checkbox for telnet mode + sockdlg_ctrl.pTelnet = new Fl_Check_Button(50, 80, 200, 20, "Telnet Mode (std port is 23)"); + sockdlg_ctrl.pTelnet->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + sockdlg_ctrl.pTelnet->value(telnet); + + // Deactivate port number and telnet mode if socket interface inactive + if (!enabled) + { + sockdlg_ctrl.pPortNumber->deactivate(); + sockdlg_ctrl.pTelnet->deactivate(); + } + + b = new Fl_Box(20, 130, 120, 20, "Socket Port Status"); + b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + sockdlg_ctrl.pStatus = new Fl_Box(50, 160, 200, 20, ""); + sockdlg_ctrl.pStatus->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + update_port_status(); + + + // Cancel button + { Fl_Button* o = new Fl_Button(40, 200, 60, 30, "Cancel"); + o->callback((Fl_Callback*) cb_sockdlg_cancel); + } + + // Apply button + sockdlg_ctrl.pApply = new Fl_Button(120, 200, 60, 30, "Apply"); + sockdlg_ctrl.pApply->callback((Fl_Callback*) cb_sockdlg_apply); + + // OK button + { Fl_Return_Button* o = new Fl_Return_Button(200, 200, 60, 30, "OK"); + o->callback((Fl_Callback*)cb_sockdlg_OK); + } + + gsdw->show(); +} diff --git a/src/sound.c b/src/sound.c index c55327e..3c6496d 100644 --- a/src/sound.c +++ b/src/sound.c @@ -53,32 +53,35 @@ #pragma comment(lib, "winmm.lib") -#define snd_Buffers 2 -#define cwSizel 128 +//#define BLOCK_SIZE 2048 +//#define BLOCK_COUNT 4 +#define BLOCK_SIZE 1024 +#define BLOCK_COUNT 8 +#define SAMPLING_RATE 22050 +#define NUM_CHANNELS 2 +#define BITS_PER_SAMPLE 16 + +#define TONE_STOPPED 0 +#define TONE_START 1 +#define TONE_PLAYING 2 +#define TONE_STOP 3 /* * module static data */ -unsigned int g_FrameSize ; -unsigned int g_Blocks ; -unsigned int g_BufSize ; -const unsigned int g_Buffers = 2 ; - -unsigned int NextBuf, fDone [snd_Buffers] ; -unsigned int Index ; -unsigned short readbuf [2 * cwSizel] ; /* input buffer */ -short int tmpbuf [2 * cwSizel] ; -unsigned short *gpOneHertz = NULL; -int m_Channels = 2 , - m_SamplingRate = 22050, - SamplesPerFrame = cwSizel; -short *pcmbuf; -short *tmppcmbuf; -int frameCount=0; -int cwSize = 2*cwSizel; - -int gPlayTone = 0; +static int gReqFreq[16]; +static int gReqIn = 0; +static int gReqOut = 0; +static int gReqLastFreq = 0; +static int gDecaySample = 0; + +unsigned short readbuf [BLOCK_SIZE >> 1] ; /* input buffer */ +unsigned short gpOneHertz[SAMPLING_RATE]; +//unsigned short *gpOneHertz = NULL; + +int gPlayTone = TONE_STOPPED; int gToneFreq = 0; +volatile int gNewToneFreq = 0; int gFlushBuffers = 0; int gExit = 0; int gBeepOn = 0; @@ -86,252 +89,402 @@ int gOneHzPtr = 0; extern UINT64 cycles; extern int cycle_delta; static UINT64 spkr_cycle = 0; +int sound_enable = 1; +FILE* gFd; #ifdef _WIN32 -HANDLE g_hEquThread; -DWORD dwThreadID; -WAVEFORMATEX wf ; -HWAVEOUT hOutput ; -WAVEHDR wh [snd_Buffers] ; -#endif +static HANDLE g_hEquThread; +static HANDLE gSoundEvent; +static DWORD dwThreadID; +static WAVEFORMATEX wf ; +static HWAVEOUT hOutput; + +/* +* function prototypes +*/ +static void CALLBACK sound_waveout_proc(HWAVEOUT, UINT, DWORD, DWORD, DWORD); +static WAVEHDR* sound_allocate_blocks(int size, int count); +static void sound_free_blocks(WAVEHDR* blockArray); +static void sound_write_audio(HWAVEOUT hWaveOut, LPSTR data, int size); +static void sound_flush_buffers(void); + +/* +* module level variables +*/ +static CRITICAL_SECTION reqCriticalSection; +static CRITICAL_SECTION waveCriticalSection; +static WAVEHDR* waveBlocks; +static volatile int waveFreeBlockCount; +static int waveCurrentBlock = 0; +static int waveLastQueueBlock = 0; +static int waveLastProcBlock = 0; +#endif #ifdef _WIN32 -void APIENTRY sndCallback (HWAVEOUT hWaveOut, UINT wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) +/* +======================================================================== +sound_waveout_proc: Callback routine called when a buffer is done being + played. +======================================================================== +*/ +static void CALLBACK sound_waveout_proc(HWAVEOUT hWaveOut, UINT uMsg, + DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) { - if (wMsg == WOM_DONE) - fDone [((LPWAVEHDR) dwParam1)->dwUser] = TRUE ; + WAVEHDR* current; + + /* pointer to free block counter */ + int* freeBlockCounter = (int*)dwInstance; + + /* + * ignore calls that occur due to openining and closing the + * device. + */ + if((uMsg != WOM_DONE) || (dwInstance == 0)) + return; + + /* Get pointer to the block processed */ +// current = &waveBlocks[waveLastProcBlock++]; +// if (waveLastProcBlock > BLOCK_COUNT) +// waveLastProcBlock = 0; + + EnterCriticalSection(&waveCriticalSection); + (*freeBlockCounter)++; +// current->dwUser = -1; + LeaveCriticalSection(&waveCriticalSection); } -BOOL sndOpenOutput (unsigned int chan, unsigned int freq, unsigned int framesize) +/* +======================================================================== +sound_allocate_blocks: Allocate from heap for all sound buffers +======================================================================== +*/ +WAVEHDR* sound_allocate_blocks(int size, int count) { - UINT i; - UINT n; - UINT id = WAVE_MAPPER; - UINT devs = waveOutGetNumDevs (); - WAVEOUTCAPS caps ; - MMRESULT err; - - // we're not using wavemapper, since soundblaster probably is - // preferred device --> look for the multichannel card - if (chan > 2) + unsigned char* buffer; + int i; + WAVEHDR* blocks; + DWORD totalBufferSize = (size + sizeof(WAVEHDR)) * count; + + /* allocate memory for the entire set in one go */ + if((buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + totalBufferSize)) == NULL) { - /* Loop through all devices looking for multi-channel support */ - for (id = 0 ; id < devs ; id++) - { - err = waveOutGetDevCaps (id, &caps, sizeof (WAVEOUTCAPS)) ; - if ((err == MMSYSERR_NOERROR) && (caps.wChannels >= chan)) - break ; - } + fprintf(stderr, "Memory allocation error\n"); + return NULL; + } + + /* Setup the pointers to each block */ + blocks = (WAVEHDR*) buffer; + buffer += sizeof(WAVEHDR) * count; + for (i = 0; i < count; i++) + { + blocks[i].dwBufferLength = size; + blocks[i].lpData = buffer; + buffer += size; + } - /* Check if no output devices found */ - if (id == devs) - return FALSE ; + return blocks; +} - g_FrameSize = 8 * framesize ; - g_Blocks = 10 ; - } - else +/* +======================================================================== +sound_free_blocks: Free the heap for all sound buffers / headers +======================================================================== +*/ +void sound_free_blocks(WAVEHDR* blockArray) +{ + /* Free the memory for all blocks */ + HeapFree(GetProcessHeap(), 0, blockArray); +} + +/* +======================================================================== +sound_write_audio: Writes a block of sound data to the audio device +======================================================================== +*/ +void sound_write_audio(HWAVEOUT hWaveOut, LPSTR data, int size) +{ + WAVEHDR* current; + int remain; + current = &waveBlocks[waveCurrentBlock]; + current->dwBufferLength = BLOCK_SIZE; + + while (size > 0) { - /* Configure for up to 2 channel support */ - g_FrameSize = chan * framesize ; - g_Blocks = 22 ; - } + /* + * first make sure the header we're going to use is unprepared + */ + if(current->dwFlags & WHDR_PREPARED) + waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR)); + + remain = size < BLOCK_SIZE ? size : BLOCK_SIZE; + current->dwUser = size; + memcpy(current->lpData, data, BLOCK_SIZE); + current->dwBufferLength = BLOCK_SIZE; + size -= remain; + data += remain; + waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR)); + waveOutWrite(hWaveOut, current, sizeof(WAVEHDR)); + EnterCriticalSection(&waveCriticalSection); + waveFreeBlockCount--; + LeaveCriticalSection(&waveCriticalSection); + + /* wait for a block to become free */ + while(!waveFreeBlockCount) + Sleep(3); + + /* point to the next block */ + waveLastQueueBlock = waveCurrentBlock; + waveCurrentBlock++; + waveCurrentBlock %= BLOCK_COUNT; + current = &waveBlocks[waveCurrentBlock]; + } +} +/* +======================================================================== +sound_open_output: Open the output sound device +======================================================================== +*/ +BOOL sound_open_output(void) +{ +// gFd = fopen("beep.txt", "w+"); /* Calculate buffer size */ - g_BufSize = 2 * g_Blocks * g_FrameSize ; + waveBlocks = sound_allocate_blocks(BLOCK_SIZE, BLOCK_COUNT); + waveFreeBlockCount = BLOCK_COUNT; + waveCurrentBlock = 0; + InitializeCriticalSection(&waveCriticalSection); + InitializeCriticalSection(&reqCriticalSection); /* Prepare to open the Wave Device */ - wf.nSamplesPerSec = freq ; + wf.nSamplesPerSec = SAMPLING_RATE; wf.wFormatTag = WAVE_FORMAT_PCM ; - wf.nChannels = chan ; - wf.nBlockAlign = 2 * wf.nChannels ; + wf.wBitsPerSample = BITS_PER_SAMPLE; + wf.nChannels = NUM_CHANNELS; + wf.nBlockAlign = (wf.wBitsPerSample * wf.nChannels) >> 3; wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign ; - wf.wBitsPerSample = 16 ; /* Try to open the Wave output device */ - waveOutOpen (&hOutput, id, &wf, (DWORD) sndCallback, 0, /* WAVE_FORMAT_DIRECT | */ CALLBACK_FUNCTION) ; + waveOutOpen (&hOutput, WAVE_MAPPER, &wf, (DWORD) sound_waveout_proc, + (DWORD_PTR) &waveFreeBlockCount, CALLBACK_FUNCTION) ; if (hOutput == NULL) return FALSE ; - /* Initialize buffers for the device */ - for ( i = 0 ; i < g_Buffers ; i++) - { - ZeroMemory (&wh [i], sizeof (WAVEHDR)) ; - - wh [i].dwBufferLength = g_BufSize ; - wh [i].lpData = (LPSTR) VirtualAlloc (NULL, g_BufSize, MEM_COMMIT, PAGE_READWRITE) ; - if (wh [i].lpData == NULL) - { - for (n = 0 ; n < i ; n++) - VirtualFree (wh [n].lpData, 0, MEM_RELEASE) ; - waveOutClose (hOutput) ; - return FALSE ; - } - - ZeroMemory (wh [i].lpData, g_BufSize) ; - - wh [i].dwUser = i ; - fDone [i] = TRUE ; - NextBuf = 0 ; - } - - Index = 0 ; - return TRUE ; } - - -BOOL sndCloseOutput (void) +/* +======================================================================== +sound_close_output: Close the output device and free buffer memory. +======================================================================== +*/ +BOOL sound_close_output (void) { - UINT i; - + /* Ensure sound device was opened */ if (hOutput == NULL) return FALSE ; - waveOutReset (hOutput) ; +// fclose(gFd); + /* Wait for all buffers to finish playing */ + sound_flush_buffers(); - for (i = 0 ; i < g_Buffers ; i++) - { - if (wh [i].dwFlags & WHDR_PREPARED) - waveOutUnprepareHeader (hOutput, &wh [i], sizeof (WAVEHDR)) ; - VirtualFree (wh [i].lpData, 0, MEM_RELEASE) ; - } + /* Pulse the sound thread thread so it will release */ +// PulseEvent(gSoundEvent); + /* Now reset and close the output device and free buffers */ + waveOutReset (hOutput); + sound_free_blocks(waveBlocks); waveOutClose (hOutput) ; hOutput = NULL ; return TRUE ; } -short *sndGetBuffer (void) -{ - short *wbuf; - - if (hOutput == NULL) - return NULL ; - - wbuf = (short *) wh [NextBuf].lpData ; - wbuf = &wbuf [g_FrameSize * Index++] ; - - if (Index <= g_Blocks) - return wbuf ; - - Index = 1 ; /* i.e. Index = 0++ */ - - fDone [NextBuf] = FALSE ; - waveOutPrepareHeader (hOutput, &wh [NextBuf], sizeof (WAVEHDR)) ; - waveOutWrite (hOutput, &wh [NextBuf], sizeof (WAVEHDR)) ; - - NextBuf = ++NextBuf % g_Buffers ; - - while (fDone [NextBuf] == FALSE) - Sleep (60) ; - /* if (WaitForSingleObject (hStopNow, 40) == WAIT_OBJECT_0) return FALSE ; */ +void sound_reset_output(void) +{ + DWORD volume; + DWORD newVol; + + /* Before resetting the output device cold turkey, we need to + reduce the volume in an "Attack" fassion so we don't get + clicks on the output + */ + waveOutGetVolume(hOutput,&volume); + + waveOutSetVolume(hOutput, 0); +/* newVol = ((volume >> 1) & 0xFFFF0000) | ((volume & 0xFFFF) >> 1); + while (newVol > 0) + { + waveOutSetVolume(hOutput, newVol); +// Sleep(3); + newVol = ((newVol >> 1) & 0xFFFF0000) | ((newVol & 0xFFFF) >> 1); + } +*/ + if (hOutput != NULL) + waveOutReset (hOutput); + gOneHzPtr = 0; - if (wh [NextBuf].dwFlags & WHDR_PREPARED) - waveOutUnprepareHeader (hOutput, &wh [NextBuf], sizeof (WAVEHDR)) ; + /* Wait for all buffers to be complete */ +// sound_flush_buffers(); - return (short *) wh [NextBuf].lpData ; + /* Restore the original volume */ + waveOutSetVolume(hOutput, volume); +// waveFreeBlockCount = BLOCK_COUNT; } -void sndFlushBuffers (void) +/* +======================================================================== +sound_flush_buffers: Waits for all buffers to be played then returnss +======================================================================== +*/ +void sound_flush_buffers (void) { - UINT i; - - /* Zero the memory in all buffers */ - for (i = Index ; i <= g_Blocks ; i++) - { - PBYTE buf; - buf = (PBYTE) sndGetBuffer () ; - if (!buf) - return ; - - ZeroMemory (buf, g_FrameSize * sizeof (short)) ; - } - /* Wait for all buffers to be done */ - for (i = 0 ; i < g_Buffers ; i++) - { - while (fDone [i] == FALSE) - Sleep (20) ; - } + while(waveFreeBlockCount < BLOCK_COUNT) + Sleep(10); } -//;============================================================= -void playback() +/* +======================================================================== +sound_play_tome: Creates and plays a tone of the frequency specified + in the global variable gToneFreq. +======================================================================== +*/ +void sound_play_tone() { - int i; - BOOL fWantPlayback; + int i, zero_cross, zero_cross_point; + int samples = BLOCK_SIZE >> 1; + int tone = gPlayTone; + int toneFreq = gToneFreq; +// int decay_samples = samples; + int decay_time = samples; + double divisor = (double) decay_time / 7; - - for (i = 0; i < cwSize; i++) + /* Create a buffer with the specified frequency */ +// zero_cross = 0; + for (i = 0; i < samples; i += 2) { - readbuf[i] = gpOneHertz[gOneHzPtr]; + if (tone == TONE_START) + { + unsigned short val = (unsigned short) (((double) (signed short) gpOneHertz[gOneHzPtr]) * + exp(- (double) (decay_time*2 - gDecaySample++) / divisor)); + readbuf[i] = val; + readbuf[i + 1] = val; + } + else if (tone == TONE_PLAYING) + { + readbuf[i] = gpOneHertz[gOneHzPtr]; + readbuf[i + 1] = gpOneHertz[gOneHzPtr]; + } + else if (tone == TONE_STOP) + { + unsigned short val = (unsigned short) (((double) (signed short) gpOneHertz[gOneHzPtr]) * + exp(- (double) i / (divisor) )); + readbuf[i] = val; + readbuf[i + 1] = val; + } + + /* Update pointer in the 1 Hz waveform based on frequency */ gOneHzPtr += gToneFreq; - if (gOneHzPtr >= m_SamplingRate) - gOneHzPtr -= m_SamplingRate; - } - fWantPlayback = TRUE; + if (gOneHzPtr >= SAMPLING_RATE) + { + // Zero crossing occurred +// zero_cross = i + 1; + gOneHzPtr -= SAMPLING_RATE; +// zero_cross_point = gOneHzPtr; + } - /* get an output buffer and do decoding work */ - pcmbuf = (fWantPlayback && frameCount) ? sndGetBuffer () : tmpbuf ; - tmppcmbuf = pcmbuf; +// readbuf[i] = 200; +// readbuf[i + 1] = 200; +// fprintf(gFd, "%d\n", (int) (signed short) readbuf[i]); + } - for (i=0;i= BLOCK_SIZE)) { - if (!sndOpenOutput (m_Channels , m_SamplingRate, SamplesPerFrame)) - exit(0); + gDecaySample = 0; + gPlayTone = TONE_PLAYING; } + /* Write the buffer to the output device */ + sound_write_audio(hOutput, (LPSTR) readbuf, BLOCK_SIZE); + return; } DWORD WINAPI EquProc(LPVOID lpParam) { - static creatflag; - while (1) { // If no active tone being played, wait for event so we don't // consume processor time - if (!gPlayTone && !gBeepOn) + if (!gPlayTone && !gBeepOn && (gReqIn == gReqOut)) { + WaitForSingleObject(gSoundEvent, INFINITE); } - // Check if tone being generated - if (gPlayTone) - playback(); + /* Test if exiting the application */ + if (gExit) + break; - if (gFlushBuffers) + /* Test for new tone frequency changes only if stopped or playing */ + if ((gPlayTone == TONE_STOPPED) || (gPlayTone == TONE_PLAYING)) { - sndFlushBuffers(); - gFlushBuffers = 0; + /* Test for new request */ + if (gReqIn != gReqOut) + { + int newFreq = gReqFreq[gReqOut++]; + if (gReqOut >= 16) + gReqOut = 0; + + if ((newFreq == 0) && (gPlayTone == TONE_PLAYING)) + { + /* Stop the currently playing tone */ + if (gReqIn == gReqOut) + gPlayTone = TONE_STOP; + } + else if ((newFreq > 0) && (gPlayTone == TONE_STOPPED)) + { + /* Start new tone */ + gToneFreq = newFreq; + gPlayTone = TONE_START; + } + else + { + /* Change the tone frequency */ + gToneFreq = newFreq; + + /* Probably need to change the unplayed buffers here */ + } + } } + /* Check if tone being generated */ + if (gPlayTone)// && (gToneFreq = gNewToneFreq)) + sound_play_tone(); + + /* Test if the "beep" command is active */ if (gBeepOn) { - if (cycles + cycle_delta - spkr_cycle > 0.001) + UINT64 dc = cycles - spkr_cycle; + + /* Wait for the "beep" time to expire and turn it off */ + if (dc > 15000) { - gPlayTone = 0; + gPlayTone = TONE_STOP; gBeepOn = 0; - sndFlushBuffers(); + gReqLastFreq = 0; } } - if (gExit) - break; } - sndCloseOutput (); _endthreadex(0); return 0; @@ -351,25 +504,30 @@ void init_sound(void) int x; double w; - gExit = 0; - // Create sin table - gpOneHertz = (unsigned short *)malloc(m_SamplingRate * sizeof(unsigned short)); - w = 2.0 * 3.14159 / (double) m_SamplingRate; - for (x = 0; x < m_SamplingRate; x++) + w = 2.0 * 3.1415926536 / (double) SAMPLING_RATE; + for (x = 0; x < SAMPLING_RATE; x++) { gpOneHertz[x] = (unsigned short) (sin(w * (double) x) * 32767.0); } + + /* Initialize the emulation cycles count for speaker frequency calcs */ spkr_cycle = cycles; + gExit = 0; - return; + /* Open the sound card / output device */ +#ifdef WIN32 + sound_open_output(); -#ifdef _WIN32 - // Start thread to handle Sound I/O + /* Start thread to handle Sound I/O and create an event for triggering */ + gSoundEvent = CreateEvent(NULL, TRUE, FALSE, NULL); g_hEquThread = (HANDLE)_beginthreadex(0,0,EquProc,0,0,&dwThreadID); +#else + + /* TODO: Add Linux support */ #endif -} +} /* ================================================================== @@ -379,11 +537,17 @@ deinit_sound: This routine deinitializes the sound output device(s) */ void deinit_sound(void) { + /* Set the exit variable */ gExit = 1; - free(gpOneHertz); + /* Close the output device */ #ifdef _WIN32 - sndCloseOutput(); + sound_close_output(); + + CloseHandle(gSoundEvent); +#else + + /* TODO: Add Linux support for closing the sound system */ #endif } @@ -395,11 +559,24 @@ start_tone: This routine starts a tone of specified frequency */ void sound_start_tone(int freq) { - if (freq < m_SamplingRate / 2.0) + /* Validate sound is enabled */ + if (!sound_enable) + return; + + if ((freq < SAMPLING_RATE / 2.0) && (freq != gReqLastFreq)) { -// printf("Playing tone of frequency %d\n", freq); - gToneFreq = freq; - gPlayTone = 1; + gReqLastFreq = freq; + /* Issue request for new frequency generation */ +#ifdef WIN32 + EnterCriticalSection(&reqCriticalSection); +#endif + gReqFreq[gReqIn++] = freq; + if (gReqIn >= 16) + gReqIn = 0; +#ifdef WIN32 + LeaveCriticalSection(&reqCriticalSection); + PulseEvent(gSoundEvent); +#endif } } @@ -410,16 +587,35 @@ stop_tone: This routine stops playing of tones */ void sound_stop_tone(void) { - -// printf("Stop playing tone\n"); -#ifdef _WIN32 -// waveOutReset (hOutput) ; -#endif - gPlayTone = 0; -// gFlushBuffers = 1; + /* Validate sound is enabled */ + if (!sound_enable) + return; + + /* Issue a request for a frequency of zero */ + sound_start_tone(0); + + /* + WAVEHDR* current; + unsigned short *sData; + int c; + + EnterCriticalSection(&reqCriticalSection); + gReqFreq[gReqFreqIn++] = 0; + if (gReqFreqIn > 16) + gReqFreqIn = 0; + LeaveCriticalSection(&reqCriticalSection); +*/ + /* Go to the last queued block and clear the data past the zero-crossing */ +/* current = &waveBlocks[waveLastQueueBlock]; + if (current->dwUser != -1) + { + sData = (unsigned short *) current->lpData; + c = ((int) current->lpData) >> 1; + for (; c < BLOCK_SIZE >> 1; c++) + sData[c] = 0; + } */\ } - /* ================================================================== toggle_speaker: This routine handles toggling of the I/O bit that @@ -432,6 +628,10 @@ void sound_toggle_speaker(int bitVal) { UINT64 delta; + /* Validate sound is enabled */ + if (!sound_enable) + return; + /* Calculate delta between current cycle and last cycle */ delta = cycles + cycle_delta - spkr_cycle; spkr_cycle = cycles + cycle_delta; @@ -439,10 +639,8 @@ void sound_toggle_speaker(int bitVal) /* Test if delta is within a valid range */ if ((delta < 5000) && (delta != 0)) { + /* Indicate the "Beep" is on and set the frequency */ gBeepOn = 1; - sound_start_tone((int) (60000.0 / delta)); + sound_start_tone((int) (2400000.0 / delta / 2)); } - } - - diff --git a/src/tpddclient.cpp b/src/tpddclient.cpp new file mode 100644 index 0000000..5dd3e64 --- /dev/null +++ b/src/tpddclient.cpp @@ -0,0 +1,579 @@ +/* tpddclient.cpp */ + +/* $Id$ */ + +/* + * Copyright 2008 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define TPDD_CLIENT_MAIN + +#include +#include +#include +#ifdef _WIN32 +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "roms.h" +#include "fl_usage_box.h" +#include "display.h" +#include "cpuregs.h" +#include "disassemble.h" +#include "periph.h" +#include "memedit.h" +#include "file.h" +#include "tpddclient.h" +#include "fileview.h" + +// =============================================== +// Extern "C" linkage items +// =============================================== +extern "C" +{ +#include "memory.h" +#include "m100emu.h" + +extern RomDescription_t *gStdRomDesc; +} + +// =============================================== +// Extern and global variables +// =============================================== +extern Fl_Preferences virtualt_prefs; +extern Fl_Menu_Item gCpuRegs_menuitems[]; +extern char *gKeywordTable[]; +static Fl_Window* gtcw = NULL; +tpddclient_ctrl_t gTcCtrl; + +void cb_Ide(Fl_Widget* w, void*) ; +void cb_view_refreseh(Fl_Widget*w, void*); + +// Menu items for the disassembler +Fl_Menu_Item gTpddClient_menuitems[] = { + { "&View", 0, 0, 0, FL_SUBMENU }, + { "Refresh", 0, cb_view_refreseh, 0, 0 }, + { 0 }, + { "&Tools", 0, 0, 0, FL_SUBMENU }, + { "CPU Registers", 0, cb_CpuRegs }, + { "Assembler / IDE", 0, cb_Ide }, + { "Disassembler", 0, disassembler_cb }, + { "Memory Editor", 0, cb_MemoryEditor }, + { "Peripheral Devices", 0, cb_PeripheralDevices }, + { "Model T File Viewer", 0, cb_FileView }, + { 0 }, + { 0 } +}; + +/* +============================================================================ +Callback routine for the File Viewer window +============================================================================ +*/ +void cb_tcwin (Fl_Widget* w, void*) +{ + // Hide the window + gtcw->hide(); + + // Delete the window and set to NULL + delete gtcw; + gtcw = NULL; +} + +/* +============================================================================ +Callback routine when a file is selected +============================================================================ +*/ +static void display_file(int index) +{ + int addr1, addr2, c, x, y, lineno, maxline; + char line[1000], substr[10], linefmt[6], fill[7]; + unsigned char ch; + tpdd_client_files_t *pfile; + + // First clear the text buffer +// gTcCtrl.pTb->remove(0, gTcCtrl.pTb->length()); + gTcCtrl.pView->clear(); + + // Populate with data based on file type + pfile = &gTcCtrl.tFiles[index]; + switch (pfile->type) + { + case TYPE_BA: + // Get first BASIC line pointer + addr1 = pfile->address; + + // Calculate the maximum linenumber length + while (get_memory16(addr1) != 0) + { + addr2 = addr1; + addr1 = get_memory16(addr1); + } + maxline = get_memory16(addr2+2); + if (maxline > 9999) + { + strcpy(linefmt, "%5u "); + strcpy(fill, " "); + } + else if (maxline > 999) + { + strcpy(linefmt, "%4u "); + strcpy(fill, " "); + } + else if (maxline > 99) + { + strcpy(linefmt, "%3u "); + strcpy(fill, " "); + } + else if (maxline > 9) + { + strcpy(linefmt, "%2u "); + strcpy(fill, " "); + } + else + { + strcpy(linefmt, "%1u "); + strcpy(fill, " "); + } + + // Restore pointer to beginning of file + addr1 = pfile->address; + + // Get BASIC lines until NULL + while ((addr2 = get_memory16(addr1)) != 0) + { + // Detokenize the line and save as ASCII + addr1 += 2; + line[0] = 0; + + // Print line number + lineno = get_memory16(addr1); + addr1 += 2; + sprintf(substr, linefmt, lineno); + strcat(line, substr); + + // Read remaining data & detokenize + while (addr1 < addr2) + { + // Get next byte + ch = get_memory8(addr1++); + + // Check if byte is ':' + if (ch == ':') + { + // Get next character + ch = get_memory8(addr1); + + // Check for REM tick + if (ch == 0x8E) + { + if (get_memory8(addr1+1) == 0xFF) + { + ch = '\''; + line[strlen(line)+1] = 0; + line[strlen(line)] = ch; + if (strlen(line) > 54) + { + strcat(line, "\n"); + gTcCtrl.pView->add(line); +// gTcCtrl.pTb->append(line); + strcpy(line, fill); + } + addr1 += 2; + continue; + } + } + + // Check for ELSE + if (ch == 0x91) + continue; + + ch = ':'; + line[strlen(line)+1] = 0; + line[strlen(line)] = ch; + if (strlen(line) > 54) + { + strcat(line, "\n"); + gTcCtrl.pView->add(line); +// gTcCtrl.pTb->append(line); + strcpy(line, fill); + } + } + else if (ch > 0x7F) + { + if (strlen(line) + strlen(gKeywordTable[ch & 0x7F]) > 54) + { + strcat(line, "\n"); + gTcCtrl.pView->add(line); +// gTcCtrl.pTb->append(line); + strcpy(line, fill); + } + sprintf(substr, "%s", gKeywordTable[ch & 0x7F]); + strcat(line, substr); + } + else if (ch == 0) + { + if (strlen(line) != strlen(fill)) + strcat(line, "\n"); + } + else + { + line[strlen(line)+1] = 0; + line[strlen(line)] = ch; + if (strlen(line) > 54) + { + strcat(line, "\n"); + gTcCtrl.pView->add(line); +// gTcCtrl.pTb->append(line); + strcpy(line, fill); + } + } + } +// gTcCtrl.pTb->append(line); + if (strlen(line) != strlen(fill)) + gTcCtrl.pView->add(line); + } + break; + + case TYPE_DO: + // Start at beginning of file + c = 0; + while (c < pfile->size) + { + // Y is the line input location (we skip CR) + y = 0; + // Copy up to 999 bytes into temp line storage + for (x = 0; x < 999; x++) + { + // Test if past end of file + if (x + c > pfile->size) + break; + + // Get next byte from file + line[y] = get_memory8(pfile->address + x + c); + line[y+1] = 0; + + // Write line if newline received + if (line[y] == 0x0A) + { + line[y+1] = 0; + gTcCtrl.pView->add(line); +// gTcCtrl.pTb->append(line); + y = 0; + line[0] = 0; + continue; + } + + if (strlen(line) > 55) + { + line[y+1] = '\n'; + line[y+2] = 0; +// gTcCtrl.pTb->append(line); + gTcCtrl.pView->add(line); + y = 0; + line[0] = 0; + continue; + } + + // Test for end of file + if (line[y] == 0x1A) + break; + + // If byte isn't CR, increment input location + if (line[y] != 0x0D) + y++; + } + + // Terminate the string add add to buffer + line[y] = 0; +// gTcCtrl.pTb->append(line); + gTcCtrl.pView->add(line); + + // Add this block to length processed + c += x; + } + break; + + case TYPE_CO: + x = 0; + while (x < pfile->size) + { + // Start new line + sprintf(line, "%04X: ", pfile->address + x); + + // Add up to 16 bytes to line + for (c = 0; c < 16; c++) + { + // Test if at end of line + if (x + c > pfile->size) + break; + + // Add next byte to line + sprintf(substr, "%02X ", get_memory8(pfile->address + c + x)); + strcat(line, substr); + } + + // Add line to text buffer + strcat(line, "\n"); +// gTcCtrl.pTb->append(line); + gTcCtrl.pView->add(line); + x += c; + } + break; + } +} + +/* +============================================================================ +Callback routine when a file is selected +============================================================================ +*/ +static void cb_FileSelect(Fl_Widget* w, void*) +{ + int index; + tpdd_client_files_t *pfile; + + // Get selection from Hold Browser + index = ((Fl_Browser*)w)->value()-1; + if ((index < 0) || (index > gTcCtrl.tCount)) + { + // Clear the Directry Entry text + gTcCtrl.sDirEntry[0] = 0; + gTcCtrl.sAddress[0] = 0; + gTcCtrl.pAddress->label(gTcCtrl.sAddress); + gTcCtrl.pDirEntry->label(gTcCtrl.sDirEntry); +// gTcCtrl.pTb->remove(0, gTcCtrl.pTb->length()); + gTcCtrl.pView->clear(); + return; + } +} + +/* +============================================================================ +Get list of files in tFiles structure and update SelectBrowser +============================================================================ +*/ +static void get_file_list(void) +{ + int dir_index, addr1, addr2; + unsigned char file_type; + int c, x; + char mt_file[40], fdata; + + // Initialize variables + dir_index = 0; + gTcCtrl.tCount = 0; + gTcCtrl.pFileSelect->clear(); + gTcCtrl.selectIndex = -1; + + // Check for Unsved BASIC program + addr2 = get_memory16(gStdRomDesc->sFilePtrBA); +// addr2 = get_memory16(addr2); + if ((get_memory16(addr2) != 0) && (addr2 != 0)) + { + // Add entry for unsaved BASIC program + strcpy(gTcCtrl.tFiles[0].name, "Unsaved BA"); + gTcCtrl.tFiles[0].dir_address = gStdRomDesc->sFilePtrBA; + gTcCtrl.tFiles[0].address = addr2; + gTcCtrl.tFiles[0].type = TYPE_BA; + addr1 = get_memory16(addr2); + if (addr1 == 0) + { + gTcCtrl.tFiles[0].size = addr2 - get_memory16(gStdRomDesc->sFilePtrBA); + } + else + { + while ((get_memory16(addr1) != 0) && (addr1 != 0)) + { + // Point to next BASIC line + addr1 = get_memory16(addr1); + } + gTcCtrl.tFiles[0].size = addr1 - addr2; + } + + // Add file to Hold Browser + sprintf(mt_file, "%-11s %d", gTcCtrl.tFiles[gTcCtrl.tCount].name, + gTcCtrl.tFiles[gTcCtrl.tCount].size); + gTcCtrl.pFileSelect->add(mt_file); + + // Increment file count + gTcCtrl.tCount++; + } + + // Now point to the file directory + addr1 = gStdRomDesc->sDirectory; + while (dir_index < gStdRomDesc->sDirCount) + { + file_type = get_memory8(addr1); + if ((file_type != TYPE_BA) && (file_type != TYPE_DO) && + (file_type != TYPE_CO)) + { + dir_index++; + addr1 += 11; + continue; + } + + // Get the 1st part of the filename + c = 0; + for (x = 0; x < 6; x++) + { + if (get_memory8(addr1+3+x) != ' ') + mt_file[c++] = get_memory8(addr1+3+x); + } + + // Check for extension and add to mt_file + if (get_memory8(addr1+3+x) != ' ') + mt_file[c++] = '.'; + mt_file[c++] = get_memory8(addr1+3+x++); + mt_file[c++] = get_memory8(addr1+3+x); + mt_file[c] = '\0'; + + // Add filename to tFiles structure + strcpy(gTcCtrl.tFiles[gTcCtrl.tCount].name, mt_file); + gTcCtrl.tFiles[gTcCtrl.tCount].type = file_type; + + // Get address of file + gTcCtrl.tFiles[gTcCtrl.tCount].address = get_memory16(addr1+1); + gTcCtrl.tFiles[gTcCtrl.tCount].dir_address = addr1; + + // Calculate file size + if (file_type == TYPE_CO) + { + // Get file size from the .CO file + gTcCtrl.tFiles[gTcCtrl.tCount].size = + get_memory16(gTcCtrl.tFiles[gTcCtrl.tCount].address + 2) + 6; + } + else if (file_type == TYPE_DO) + { + // Start at beginning of file + x = 0; + fdata = get_memory8(gTcCtrl.tFiles[gTcCtrl.tCount].address); + + // Search through the file until 0x1A found + while (fdata != 0x1A) + { + x++; + fdata = get_memory8(gTcCtrl.tFiles[gTcCtrl.tCount].address + x); + } + + // Set size + gTcCtrl.tFiles[gTcCtrl.tCount].size = x; + } + else if (file_type == TYPE_BA) + { + // Scan through BASIC file until NULL pointer reached + addr2 = get_memory16(gTcCtrl.tFiles[gTcCtrl.tCount].address); + while (get_memory16(addr2) != 0) + { + // Get line pointer of the next line + addr2 = get_memory16(addr2); + } + gTcCtrl.tFiles[gTcCtrl.tCount].size = addr2 - gTcCtrl.tFiles[gTcCtrl.tCount].address; + } + + // Space pad the filename + sprintf(mt_file, "%-11s %d", gTcCtrl.tFiles[gTcCtrl.tCount].name, + gTcCtrl.tFiles[gTcCtrl.tCount].size); + + // Add file to Hold Browser and increment for next file + gTcCtrl.pFileSelect->add(mt_file); + gTcCtrl.tCount++; + dir_index++; + addr1 += 11; + } +} + +/* +============================================================================ +Callback routine to read TPDD / NADSBox directory +============================================================================ +*/ +static void cb_TpddDir(Fl_Widget* w, void*) +{ +} + +/* +============================================================================ +Routine to create the TPDD Client window +============================================================================ +*/ +void cb_TpddClient(Fl_Widget* w, void*) +{ + Fl_Box* o; + + if (gtcw != NULL) + return; + + // Create File Viewer window + gtcw = new Fl_Double_Window(650, 480, "TPDD / NADSBox Client"); + gtcw->callback(cb_tcwin); + + // Create a menu for the new window. + gTcCtrl.pMenu = new Fl_Menu_Bar(0, 0, 700, MENU_HEIGHT-2); + gTcCtrl.pMenu->menu(gTpddClient_menuitems); + + o = new Fl_Box(20, 40, 80, 20, "File Directory"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + // Create a browser for the files + gTcCtrl.pFileSelect = new Fl_Hold_Browser(20, 65, 170, 270, 0); + gTcCtrl.pFileSelect->textfont(FL_COURIER); + gTcCtrl.pFileSelect->has_scrollbar(Fl_Browser_::VERTICAL); + gTcCtrl.pFileSelect->callback(cb_FileSelect); + + // Create a Text Editor / Text Buffer for the file display + gTcCtrl.pView = new Fl_Hold_Browser(200, 65, 420, 270, ""); + gTcCtrl.pView->has_scrollbar(Fl_Browser_::VERTICAL ); + gTcCtrl.pView->textfont(FL_COURIER); + gTcCtrl.pView->textsize(12); + + // Create a button to Read the TPDD / NADSBox Directory + gTcCtrl.pTpddDir = new Fl_Button(20, 350, 120, 20, "TPDD Directory"); + gTcCtrl.pTpddDir->callback(cb_TpddDir); + + // Create a button to copy files to the TPDD / NADSBox + + // Create a button to copy files from the TPDD / NADSBox + + // Create a static box showing the COM port being used (from the Setup page) + + gtcw->show(); +} diff --git a/src/tpddclient.h b/src/tpddclient.h new file mode 100644 index 0000000..d5910a0 --- /dev/null +++ b/src/tpddclient.h @@ -0,0 +1,69 @@ +/* tpddclient.h */ + +/* $Id$ */ + +/* +* Copyright 2008 Ken Pettit +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +*/ + +#ifndef TPDDCLIENT_H +#define TPDDCLIENT_H + +void cb_TpddClient(Fl_Widget* w, void*); + +#ifdef TPDD_CLIENT_MAIN + +typedef struct { + char name[12]; + unsigned short address; + unsigned short dir_address; + unsigned short size; + unsigned char type; +} tpdd_client_files_t; + +typedef struct tpddclient_ctrl_struct +{ + Fl_Menu_Bar* pMenu; // Pointer to Menu bar + + Fl_Box* pDirAddress; // Pointer to Dir star taddress + char sDirAddr[20]; + Fl_Box* pDirEntry; // DirEntry information box + char sDirEntry[100]; // Text for directory entry + Fl_Box* pAddress; // Address information box + char sAddress[100]; // Text for Address entry + Fl_Hold_Browser* pFileSelect; // Pointer to Directory Table files + Fl_Hold_Browser* pView; // Pointer to Browser for file contents + tpdd_client_files_t tFiles[512]; // Storage for up to 512 files + int tCount; + Fl_Button* pTpddDir; // Create TPDD directory listing + + int selectIndex; // Index of active selection + Fl_Group* g; + +} tpddclient_ctrl_t; + +#endif + +#endif + diff --git a/src/vt_client_main.cpp b/src/vt_client_main.cpp index 08c05c4..7422b84 100644 --- a/src/vt_client_main.cpp +++ b/src/vt_client_main.cpp @@ -2,6 +2,7 @@ #include "socketexception.h" #include #include +#include #include #include @@ -10,11 +11,55 @@ using namespace std; int main ( int argc, char* argv[] ) { - fstream filestr; + fstream filestr; + char *hostArg, *portArg; + size_t x, len; - if (argc != 2) + hostArg = portArg = NULL; + if (argc < 2) { - printf("usage: %s port#\n", argv[0]); + printf("usage: %s [hostname] port#\n", argv[0]); + return 1; + } + + /* Determine if argv[1] is the port number */ + len = strlen(argv[1]); + for (x = 0; x < len; x++) + { + if ((argv[1][x] < '0') || (argv[1][x] > '9')) + { + hostArg = argv[1]; + break; + } + } + /* If we reached the end of argv[1] and found all numbers, its port */ + if (x == len) + { + portArg = argv[1]; + } + + /* Determine if argv[2] is the port number */ + if (argc > 2) + { + len = strlen(argv[2]); + for (x = 0; x < len; x++) + { + if ((argv[2][x] < '0') || (argv[2][x] > '9')) + { + hostArg = argv[2]; + break; + } + } + /* If we reached the end of argv[1] and found all numbers, its port */ + if (x == len) + { + portArg = argv[2]; + } + } + + if (portArg == NULL) + { + printf("%s: must specifiy valid port number\n", argv[0]); return 1; } @@ -55,13 +100,15 @@ int main ( int argc, char* argv[] ) try { + if (hostArg == NULL) + hostArg = (char *) "localhost"; - ClientSocket client_socket ( "localhost", atoi(argv[1]) ); + ClientSocket client_socket ( hostArg , atoi(portArg) ); std::string reply; std::string cmd; std::string outfile; - int pos,c; + size_t pos,c; std::cout << "Ok> "; while (true) @@ -117,7 +164,7 @@ int main ( int argc, char* argv[] ) } // Check if response is "Ok" or contains "Ok" at the end - int len = reply.length(); + size_t len = reply.length(); if ((reply[len-1] == 'k') && (reply[len-2] == 'O')) { // Check if output goes to a file diff --git a/src/vtobj.cpp b/src/vtobj.cpp index ff0ab78..f5b41db 100644 --- a/src/vtobj.cpp +++ b/src/vtobj.cpp @@ -29,6 +29,7 @@ #include #include +#include #include "VirtualT.h" #include "vtobj.h" @@ -77,7 +78,7 @@ VTObArray::VTObArray() VTObArray::~VTObArray() { if (m_pData != 0) - delete (char*) m_pData; + delete[] (char*) m_pData; m_pData = 0; } @@ -172,11 +173,12 @@ void VTObArray::SetSize(int nNewSize, int nGrowBy) if (nNewSize == m_Size) return; - pNew = (void *) malloc(nNewSize * sizeof(VTObject*)); + pNew = (void *) new char[nNewSize * sizeof(VTObject*)]; memcpy(pNew, m_pData, m_Count * sizeof(VTObject*)); // Delete old data - delete (char *)m_pData; + if (m_pData != NULL) + delete[] (char *)m_pData; // Assign new data m_pData = pNew; @@ -241,6 +243,49 @@ int VTMapStringToOb::Lookup(const char *key, VTObject *&rValue) return 0; } +void VTMapStringToOb::RemoveAt(MString &rKey) +{ + POSITION iter, iterPrev; + unsigned char hash; + const char *key; + + // Calculate hash and get pointer to first entry in hash array + key = (const char *) rKey; + hash = HashKey(key); + iter = m_HashPtrs[hash]; + // Save previous iter so we can delete + iterPrev = iter; + + // Iterate through all items which have this hash + while (iter != 0) + { + // Test if this is the item to be deleted + if (strcmp(iter->pKey, key) == 0) + { + // First remove this item from the list + if (iterPrev == m_HashPtrs[hash]) + { + // Assign new head pointer + m_HashPtrs[hash] = iter->pNext; + } + else + { + // Remove from list + iterPrev->pNext = iter->pNext; + } + + // Free the resouces for this entry + free(iter->pKey); + delete iter; + return; + } + + // Save previous iter so we can delete + iterPrev = iter; + iter = iter->pNext; + } +} + VTObject*& VTMapStringToOb::operator[](const char *key) { POSITION iter; diff --git a/src/vtobj.h b/src/vtobj.h index af78f90..e8b937c 100644 --- a/src/vtobj.h +++ b/src/vtobj.h @@ -143,6 +143,7 @@ class VTMapStringToOb : public VTObject int Lookup(const char *key, VTObject*& rValue); VTObject*& operator[](const char *key); void RemoveAll(); + void RemoveAt(MString& rKey); int Size() { return m_Count; }; void GetNextAssoc(POSITION& rNextPosition, MString& rKey, VTObject*& rValue) const; @@ -172,6 +173,13 @@ class VT_Rect { int x1() { return m_X + m_W; }; int y1() { return m_Y + m_H; }; + int PointInRect(int x, int y) + { + if ((x >= m_X) && (x <= m_X + m_W) && + (y >= m_Y) && (y <= m_Y + m_H)) return 1; + else return 0; + } + private: int m_X; int m_Y; diff --git a/src/vtpaper.cpp b/src/vtpaper.cpp index 0f8aabe..5f19bb1 100644 --- a/src/vtpaper.cpp +++ b/src/vtpaper.cpp @@ -68,7 +68,7 @@ VTVirtualPaper: This is the class construcor for the VTVirtualPaper class. ================================================================================ */ VTVirtualPaper::VTVirtualPaper() : - Fl_Double_Window(985, 500, "Virtual Paper Output") + Fl_Double_Window(1015, 500, "Virtual Paper Output") { // Initialize pointers m_pLineCnts = NULL; // Line count storage not allocated @@ -81,7 +81,7 @@ VTVirtualPaper::VTVirtualPaper() : callback(cb_VirtualPaperWin, this); // Create a scrollbar - m_pScroll = new Fl_Scrollbar(970, 0, 15, 500, ""); + m_pScroll = new Fl_Scrollbar(1000, 0, 15, 500, ""); m_pScroll->type(FL_VERTICAL); //m_pScroll->maximum(200); //m_pScroll->slider_size(10); @@ -220,7 +220,7 @@ void VTVirtualPaper::DrawPage(int pageNum) { if (data & mask) { - xpos = (c<<3) + b; + xpos = (c<<3) + b + 15; fl_point(xpos, ypos); fl_point(xpos+1, ypos); fl_point(xpos, ypos+1); @@ -246,17 +246,25 @@ void VTVirtualPaper::draw(void) { int pages, page; double offset; - VTVirtualPage* pVPage; + VTVirtualPage* pVPage= NULL; int pageBottom; // Draw child objects, etc Fl_Double_Window::draw(); + // Draw left border + fl_color(FL_GRAY); + fl_rectf(0, 0, 10, h()); + fl_rectf(w()-25, 0, 10, h()); + fl_color(FL_DARK3); + fl_rectf(w()-30, 0, 5, h()); + // Check if page separator needs to be drawn at top if (m_topPixel < 9) { fl_color(FL_GRAY); fl_rectf(0, -m_topPixel, w()-15, 9); + fl_rectf(w()-30, -m_topPixel+9, 5, 5); } // Determine in which page m_topPixel falls @@ -273,7 +281,7 @@ void VTVirtualPaper::draw(void) DrawPage(page); // Draw pages until window is full - while (TRUE) + while (pages) { pageBottom = (int) ((pVPage->m_topOffset + pVPage->m_pageHeight) * 144.0); @@ -283,7 +291,9 @@ void VTVirtualPaper::draw(void) fl_color(FL_GRAY); fl_rectf(0, pageBottom- m_topPixel, w()-15, 18); fl_color(FL_DARK3); - fl_rectf(4, pageBottom- m_topPixel+1, w()-19, 5); + fl_rectf(15, pageBottom- m_topPixel, w()-40, 5); + fl_color(FL_GRAY); + fl_rectf(w()-30, pageBottom - m_topPixel + 18, 5, 5); } // Check if next page needs to be drawn @@ -1593,8 +1603,6 @@ Initialize the page with preferences. */ void VTWinPrintPaper::Init(Fl_Preferences* pPref) { - char temp[512]; - m_pPref = pPref; // Load preferences From 122fc053ccbbd6c95178f445b6e390f68dfc0957 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 9 Jul 2011 21:11:51 +0000 Subject: [PATCH 179/327] Modifications to compile under OSX and remove warnings when building in Windows, Linux and OSX. Still some depricated strdup warnings in Windows. Also fixed File Browser dialog box initialization so the width and height are sane. --- GNUmakefile | 26 ++++++----------------- VirtualT.suo | Bin 352768 -> 353280 bytes src/FLU/Flu_Tree_Browser.h | 7 +++++-- src/Flu_File_Chooser.cpp | 12 ++++++----- src/Flu_Tree_Browser.cpp | 6 +++--- src/Flu_Wrap_Group.cpp | 4 ++-- src/assemble.cpp | 5 ++++- src/chargen.cpp | 2 +- src/clock.cpp | 23 ++++++++++++--------- src/display.cpp | 28 +++++++++++++++++-------- src/file.cpp | 41 +++++++++++++++++++++++++++++-------- src/file.h | 7 +++++-- src/genwrap.h | 2 ++ src/ide.cpp | 10 +++------ src/inet_pton.c | 2 +- src/io.c | 3 +++ src/lpt.cpp | 6 +++--- src/memedit.cpp | 8 ++++---- src/memory.c | 32 ++++++++++++++++------------- src/periph.cpp | 4 ++-- src/project.cpp | 2 +- src/rememcfg.cpp | 6 ++---- src/remote.cpp | 33 +++++++++++++++-------------- src/serial.c | 6 +++--- src/setup.cpp | 5 +++-- 25 files changed, 160 insertions(+), 120 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 656bf70..e1bedb6 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -18,13 +18,14 @@ EXECUTABLE = virtualt CLIENT = vt_client FLTKCONFIG = $(FLTKDIR)/fltk-config -FLTKLIB = $(FLTKDIR)/lib/libfltk.a +FLTKLIB = $(shell $(FLTKCONFIG) --libs) +#FLTKLIB = $(FLTKDIR)/lib/libfltk.a VPATH = src:obj LDFLAGS += -g -L/usr/X11R6/lib -L$(FLTKDIR)/lib LIBFILES = -lstdc++ -lfltk_images -lfltk_jpeg -lfltk_png -lfltk_z -lfltk -lm -lc -lX11 -lpthread -MACLDFLAGS = -L$(FLTKDIR)/lib +MACLDFLAGS = $(shell $(FLTKCONFIG) --ldflags) MACLIBFILES = -lstdc++ `$(FLTKCONFIG) --ldstaticflags --use-images` --lm -lpthread OBJECTS = $(SOURCES:.c=.o) @@ -62,8 +63,8 @@ all: virtualt vt_client # ======================== # Rule to build VirtualT # ======================== -$(EXECUTABLE): $(OBJECTS) $(OBJECTSCPP) $(FLTKLIBS)/libfltk.a \ - $(FLTKLIBS)/libfltk_z.a $(FLTKLIBS)/libfltk_jpeg.a $(FLTKLIBS)/libfltk_png.a +$(EXECUTABLE): $(OBJECTS) $(OBJECTSCPP) + ifndef FLTKDIR @echo "FLTKDIR environment variable must be set first!" exit 1 @@ -128,21 +129,6 @@ else endif -# ========================================== -# Declare dependencies on FLTK libs -# ========================================== -$(FLTKLIBS)/libfltk.a: - $(MAKE) -C $(FLTKDIR) - -$(FLTKLIBS)/libfltk_z.a: - $(MAKE) -C $(FLTKDIR)/zlib - -$(FLTKLIBS)/libfltk_jpeg.a: - $(MAKE) -C $(FLTKDIR)/jpeg - -$(FLTKLIBS)/libfltk_png.a: - $(MAKE) -C $(FLTKDIR)/png - # ========================================== # Declare dependencies on header files below # ========================================== @@ -164,7 +150,7 @@ serial.o: serial.h setup.h display.h rememcfg.o: rememcfg.h setup.h display.h fl_usage_box.o: fl_usage_box.h setup.o: setup.h io.h serial.h memory.h memedit.h lpt.h clock.h -sound.c: sound.h +sound.o: sound.h m100rom.o m102rom.o m200rom.o n8201rom.o romstrings.o m10rom.o kc85rom.o: roms.h romstrings.h remote.o: remote.cpp m100emu.h socket.h serversocket.h socketexception.h socket.o: socket.h diff --git a/VirtualT.suo b/VirtualT.suo index c657bb41ab296e79291749cd0be893ece6a1c85c..afe678d8b7b7f5fc5fc2a1d6b81f9fb19751bedf 100644 GIT binary patch delta 10324 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 delta 5401 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 #include #include +#ifndef WIN32 +#include +#endif #define USE_FLU_DND @@ -940,8 +943,8 @@ class FLU_EXPORT Flu_Tree_Browser : public Fl_Double_Window //! Remove the entry identified by path \b fullpath from this node /*! \return the unique id of the removed entry, or \c 0 if no matching entry was found */ - inline unsigned int remove( const char *fullpath ) - { return( (unsigned int)modify( fullpath, REMOVE, tree->rdata ) ); } + inline intptr_t remove( const char *fullpath ) + { return( (intptr_t)modify( fullpath, REMOVE, tree->rdata ) ); } //! Remove the entry identified by unique id \b id from this node /*! \return the unique id of the removed entry, or \c 0 if no matching entry was found */ diff --git a/src/Flu_File_Chooser.cpp b/src/Flu_File_Chooser.cpp index 0192d35..0d05046 100644 --- a/src/Flu_File_Chooser.cpp +++ b/src/Flu_File_Chooser.cpp @@ -566,6 +566,8 @@ Flu_File_Chooser :: Flu_File_Chooser( const char *pathname, const char *pat, int configFilename = userHome + ".Flu_File_Chooser.favorites"; int neww, newh; + neww = 800; + newh = 600; // try to load the favorites { FILE *f = fopen( configFilename.c_str(), "r" ); @@ -902,12 +904,12 @@ void Flu_File_Chooser :: trashCB( int recycle ) { if( recycle ) { - if( !fl_ask( "Really send '%s' to the Recycle Bin?", first ) ) + if( fl_choice( "Really send '%s' to the Recycle Bin?", "Yes", "No", NULL, first ) ) return; } else { - if( !fl_ask( "Really delete '%s'?", first ) ) + if( fl_choice( "Really delete '%s'?", "Yes", "No", NULL, first ) ) return; } } @@ -915,12 +917,12 @@ void Flu_File_Chooser :: trashCB( int recycle ) { if( recycle ) { - if( !fl_ask( "Really send these %d files to the Recycle Bin?", selected ) ) + if( fl_choice( "Really send these %d files to the Recycle Bin?", "Yes", "No", NULL, selected ) ) return; } else { - if( !fl_ask( "Really delete these %d files?", selected ) ) + if( fl_choice( "Really delete these %d files?", "Yes", "No", NULL, selected ) ) return; } } @@ -2923,7 +2925,7 @@ int Flu_File_Chooser :: stripPatterns( FluSimpleString s, StringVector* patterns void Flu_File_Chooser :: cd( const char *localpath ) { Entry *entry; - char cwd[1024]; +// char cwd[1024]; if( !localpath || localpath[0] == '\0' ) { diff --git a/src/Flu_Tree_Browser.cpp b/src/Flu_Tree_Browser.cpp index 12c790a..7334f0c 100644 --- a/src/Flu_Tree_Browser.cpp +++ b/src/Flu_Tree_Browser.cpp @@ -2351,11 +2351,11 @@ int Flu_Tree_Browser :: Node :: recurse( RData &rdata, int type, int event ) int which = open(); if( _parent==0 ) inExpander = Fl::event_inside( rdata.x, rdata.y+(currentH>>1)-(cIcon[which]->h()>>1), - cIcon[which]->w(), cIcon[which]->h() ); + cIcon[which]->w(), cIcon[which]->h() ) != 0; else inExpander = Fl::event_inside( rdata.x+(rdata.branchIconW>>1)-(cIcon[which]->w()>>1), rdata.y+(currentH>>1)-(cIcon[which]->h()>>1), - cIcon[which]->w(), cIcon[which]->h() ); + cIcon[which]->w(), cIcon[which]->h() ) != 0; } if( event == FL_PUSH ) @@ -2790,7 +2790,7 @@ Flu_Tree_Browser::Node* Flu_Tree_Browser :: add( const char* path, const char* t unsigned int Flu_Tree_Browser :: remove( const char *fullpath ) { - return( (unsigned int)root.modify( fullpath, Node::REMOVE, rdata ) ); + return( (intptr_t)root.modify( fullpath, Node::REMOVE, rdata ) ); } unsigned int Flu_Tree_Browser :: remove( const char *path, const char *text ) diff --git a/src/Flu_Wrap_Group.cpp b/src/Flu_Wrap_Group.cpp index dab28e3..a7be089 100644 --- a/src/Flu_Wrap_Group.cpp +++ b/src/Flu_Wrap_Group.cpp @@ -265,10 +265,10 @@ void Flu_Wrap_Group :: draw() if( scrollbar.value() > scrollbar.maximum() ) { ((Fl_Valuator*)&scrollbar)->value( scrollbar.maximum() ); - layout( scrollbar.visible(), scrollTo!=NULL ); + layout( scrollbar.visible()!=0, scrollTo!=NULL ); } else if( scrollTo ) - layout( scrollbar.visible(), true ); + layout( scrollbar.visible()!=0, true ); scrollTo = NULL; diff --git a/src/assemble.cpp b/src/assemble.cpp index 4eeb785..7862f21 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -40,6 +40,9 @@ #include #include #include +#ifndef WIN32 +#include +#endif extern "C" { @@ -2880,7 +2883,7 @@ int VTAssembler::Assemble() break; case OPCODE_2REG: - opcode |= (int) pInst->m_Group - '0'; + opcode |= (intptr_t) pInst->m_Group - '0'; opcode |= atoi(*pInst->m_Operand1) << 3; break; } diff --git a/src/chargen.cpp b/src/chargen.cpp index be9bbfd..dfac50b 100644 --- a/src/chargen.cpp +++ b/src/chargen.cpp @@ -119,7 +119,7 @@ void cb_CharGenLoad(Fl_Widget* w, void *) void cb_CharGenSave(Fl_Widget* w, void * format) { if (gpCharGen != NULL) - gpCharGen->Save((int) format); + gpCharGen->Save((intptr_t) format); } /* diff --git a/src/clock.cpp b/src/clock.cpp index 644b572..6271d13 100644 --- a/src/clock.cpp +++ b/src/clock.cpp @@ -177,20 +177,23 @@ void pd1990ac_chip_cmd(uchar val) clock_sr_save[x] = clock_sr[x]; // clock_sr_index = 0; - if (gModel == MODEL_PC8201) + if (gStdRomDesc != NULL) { - if ((get_memory8(gStdRomDesc->sYear+1) == '8') && (get_memory8(gStdRomDesc->sYear) == '3')) + if (gModel == MODEL_PC8201) { - set_memory8(gStdRomDesc->sYear, (unsigned char) (mytime->tm_year % 10) + '0'); - set_memory8(gStdRomDesc->sYear+1, (unsigned char) ((mytime->tm_year % 100) / 10) + '0'); + if ((get_memory8(gStdRomDesc->sYear+1) == '8') && (get_memory8(gStdRomDesc->sYear) == '3')) + { + set_memory8(gStdRomDesc->sYear, (unsigned char) (mytime->tm_year % 10) + '0'); + set_memory8(gStdRomDesc->sYear+1, (unsigned char) ((mytime->tm_year % 100) / 10) + '0'); + } } - } - else - { - if ((get_memory8(gStdRomDesc->sYear+1) == 0) && (get_memory8(gStdRomDesc->sYear) == 0)) + else { - set_memory8(gStdRomDesc->sYear, (unsigned char) (mytime->tm_year % 10)); - set_memory8(gStdRomDesc->sYear+1, (unsigned char) ((mytime->tm_year % 100) / 10)); + if ((get_memory8(gStdRomDesc->sYear+1) == 0) && (get_memory8(gStdRomDesc->sYear) == 0)) + { + set_memory8(gStdRomDesc->sYear, (unsigned char) (mytime->tm_year % 10)); + set_memory8(gStdRomDesc->sYear+1, (unsigned char) ((mytime->tm_year % 100) / 10)); + } } } } diff --git a/src/display.cpp b/src/display.cpp index 983f2a6..96b7523 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -47,6 +47,9 @@ #include #include +#ifndef WIN32 +#include +#endif #include "VirtualT.h" #include "display.h" @@ -66,6 +69,7 @@ #include "romstrings.h" //#include "tpddclient.h" + extern "C" { extern RomDescription_t gM100_Desc; extern RomDescription_t gM200_Desc; @@ -519,13 +523,13 @@ void show_error (const char *st) return; } - fl_alert(st); + fl_alert("%s", st); } void show_message (const char *st) { - fl_message(st); + fl_message("%s", st); } @@ -744,21 +748,23 @@ void cb_KC85(Fl_Widget* w, void*) void cb_choosewkdir(Fl_Widget* w, void*) { /* Choose the working directory (ROM, RAM Files... */ - char *ret; + const char *ret; /* Get working directory from chooser */ - ret=ChooseWorkDir(); - if(ret==NULL) + ret = ChooseWorkDir(); + if (ret == NULL) return; else { - strcpy(path,ret); + strcpy(path, ret); //#ifdef __unix__ //strcat(path,"/"); //#else //strcat(path,"\\"); //#endif - virtualt_prefs.set("Path",path); + virtualt_prefs.set("Path", path); + load_sys_rom(); + resetcpu(); } } //--JV @@ -1100,7 +1106,7 @@ void cb_select_cancel (Fl_Widget* w, void*) void cb_menu_fkey (Fl_Widget* w, void* key) { - int fkey = (int) key; + int fkey = (intptr_t) key; if (gpDisp != NULL) { @@ -2156,7 +2162,7 @@ void init_display(void) /* ...and display it now if any */ if (strlen(gDelayedError) != 0) { - fl_alert(gDelayedError); + fl_alert("%s", gDelayedError); gDelayedError[0] = '\0'; } @@ -2533,6 +2539,10 @@ int T100_Disp::IsInMenu(void) unsigned short lcdAddr, curAddr; char lcdStr[21]; + // Validate the gStdRomDesc is valid + if (gStdRomDesc == NULL) + return FALSE; + lines = gModel == MODEL_T200 ? 16 : 8; // For Model 200, the 1st byte of the LCD character buffer isn't diff --git a/src/file.cpp b/src/file.cpp index eca6561..d5f57d6 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -250,7 +250,7 @@ int relocate(unsigned char* in, unsigned char* out, unsigned short addr) if (in[c] + (in[c+1] << 8) <= line_number) { - fl_message(gIllformedBasic); + fl_message("%s", gIllformedBasic); return 0; } @@ -285,7 +285,7 @@ int relocate(unsigned char* in, unsigned char* out, unsigned short addr) addr1 = in[this_line] + (in[this_line+1] << 8); if (addr1 != base + line_len) { - fl_message(gIllformedBasic); + fl_message("%s", gIllformedBasic); return 0; } } @@ -356,7 +356,7 @@ int tokenize(unsigned char* in, unsigned char* out, unsigned short addr) // Check for characters with no line number else if (line_num_len == 0) { - fl_message(gIllformedBasic); + fl_message("%s", gIllformedBasic); return 0; } @@ -659,7 +659,7 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) { fclose(fd); if (w != NULL) - fl_message(gTooLargeMsg); + fl_message("%s", gTooLargeMsg); else gLoadError = 1; if (fc != NULL) @@ -701,7 +701,7 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) if (x >= 32768) { if (w != NULL) - fl_message(gTooLargeMsg); + fl_message("%s", gTooLargeMsg); else gLoadError = 1; if (fc != NULL) @@ -777,7 +777,7 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) if (addr3 - addr2 < len) { if (w != NULL) - fl_message(gTooLargeMsg); + fl_message("%s", gTooLargeMsg); else gLoadError = 1; if (fc != NULL) @@ -1290,11 +1290,34 @@ void cb_SaveToHost(Fl_Widget* w, void*) #ifdef __APPLE__ //JV 08/10/05: add a function to choose the working directory (where are the ROMs files) -char* ChooseWorkDir() +const char* ChooseWorkDir() { - char *ret=NULL; + Flu_File_Chooser *fileWin; + int count; + const char *ret = NULL; - ret = fl_dir_chooser("Choose Working Directory",path,0); + // Create a File chooser + fl_cursor(FL_CURSOR_WAIT); + fileWin = new Flu_File_Chooser(path, "", + Flu_File_Chooser::DIRECTORY, "Choose Working Directory - Should be the PARENT of ROMs dir"); + fl_cursor(FL_CURSOR_DEFAULT); + fileWin->preview(0); + fileWin->show(); + + // Wait until selection is made or cancel + while (fileWin->visible()) + Fl::wait(); + + // Determine if selection made + count = fileWin->count(); + if (count == 0) + { + delete fileWin; + return NULL; + } + + // Get the path of the new location + ret = fileWin->value(); return ret; } diff --git a/src/file.h b/src/file.h index fff4cc0..108a72e 100644 --- a/src/file.h +++ b/src/file.h @@ -54,12 +54,15 @@ extern int COSaveMode; #ifdef __APPLE__ //JV 10/08/05 -char* ChooseWorkDir(); +const char* ChooseWorkDir(); #ifdef __cplusplus -extern "C" +extern "C" { #endif extern char path[255]; +#ifdef __cplusplus +} +#endif //JV #endif diff --git a/src/genwrap.h b/src/genwrap.h index d9c8397..619fe53 100644 --- a/src/genwrap.h +++ b/src/genwrap.h @@ -145,7 +145,9 @@ extern "C" { /* String Functionss */ /*********************/ +#ifndef __APPLE__ #define snprintf safe_snprintf +#endif #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__DMC__) #define vsnprintf _vsnprintf diff --git a/src/ide.cpp b/src/ide.cpp index 8f62b40..b816a66 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -250,7 +250,6 @@ Callback routine for the close box of the IDE window void close_ide_cb(Fl_Widget* w, void*) { int ans; - MString question; if (gpIde != NULL) { @@ -258,8 +257,7 @@ void close_ide_cb(Fl_Widget* w, void*) if (gpIde->ProjectDirty()) { // Ask if project should be saved - question.Format("Save changes to project %s?", (const char *) gpIde->ProjectName()); - ans = fl_choice((const char *) question, "Cancel", "Yes", "No"); + ans = fl_choice("Save changes to project %s?", "Cancel", "Yes", "No", (const char *) gpIde->ProjectName()); if (ans == 0) return; if (ans == 1) @@ -2756,7 +2754,6 @@ a specific item in the tree. void VT_Ide::DeleteItem(Flu_Tree_Browser::Node* n) { int ans; - MString question; if (!n->is_root()) { @@ -2770,8 +2767,7 @@ void VT_Ide::DeleteItem(Flu_Tree_Browser::Node* n) { // For groups, ask before deleting the entire group VT_IdeGroup* pGroup = (VT_IdeGroup*) pObj; - question.Format("Delete group %s and all its members?", (const char *) pGroup->m_Name); - ans = fl_choice((const char *) question, "No", "Yes", NULL); + ans = fl_choice("Delete gropu %s and all its members?", "No", "Yes", NULL, (const char *) pGroup->m_Name); if (ans == 1) { // First delete all subitems from the group @@ -3149,7 +3145,7 @@ void VT_Ide::AddFilesToFolder(Flu_Tree_Browser::Node* n) err.Format("Files %s already in project!", (const char *) files); else err.Format("File %s already in project!", (const char *) files); - fl_alert((const char *) err); + fl_alert("%s", (const char *) err); } return; } diff --git a/src/inet_pton.c b/src/inet_pton.c index a71b0c8..b562807 100644 --- a/src/inet_pton.c +++ b/src/inet_pton.c @@ -98,7 +98,7 @@ int inet_pton4(char *src, u_char *dst, int pton) { u_int val; u_int digit; - int base, n; + u_int base, n; unsigned char c; u_int parts[4]; register u_int *pp = parts; diff --git a/src/io.c b/src/io.c index e3e85f9..ca90127 100644 --- a/src/io.c +++ b/src/io.c @@ -29,6 +29,9 @@ #include +#ifdef __APPLE__ +#include +#endif #include #include "VirtualT.h" diff --git a/src/lpt.cpp b/src/lpt.cpp index 919e637..fbe3a63 100644 --- a/src/lpt.cpp +++ b/src/lpt.cpp @@ -941,7 +941,7 @@ void VTLpt::HandleTimeouts(unsigned long time) } else { - sprintf(m_TimeStr, "%d", m_PortTimeout + timeout - time); + sprintf(m_TimeStr, "%ld", m_PortTimeout + timeout - time); gpPrint->label(m_TimeStr); } @@ -1001,7 +1001,7 @@ void VTLpt::HandleTimeouts(unsigned long time) } else { - sprintf(m_TimeStr, "%d", m_PortActivity + timeout - time); + sprintf(m_TimeStr, "%ld", m_PortActivity + timeout - time); gpPrint->label(m_TimeStr); } } @@ -1402,7 +1402,7 @@ void VTLpt::ShowErrors(void) if (count == 1) { - fl_message((const char *) m_pActivePrinter->GetError(0)); + fl_message("%s", (const char *) m_pActivePrinter->GetError(0)); } else { diff --git a/src/memedit.cpp b/src/memedit.cpp index 4f7bb2d..2e9d992 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -2276,16 +2276,16 @@ void T100_MemEditor::UpdateAddressText() (region == REGION_RAM3) || region == REGION_RAM1) { if (gReMem) - sprintf(string, "0x%06X", address + RAMSTART); + sprintf(string, "0x%06X", (unsigned int) (address + RAMSTART)); else - sprintf(string, "0x%04X", address + RAMSTART); + sprintf(string, "0x%04X", (unsigned int) (address + RAMSTART)); } else { if (gReMem) - sprintf(string, "0x%06X", address); + sprintf(string, "0x%06X", (unsigned int) address); else - sprintf(string, "0x%04X", address); + sprintf(string, "0x%04X", (unsigned int) address); } memedit_ctrl.pMemRange->value(string); } diff --git a/src/memory.c b/src/memory.c index 858f5d0..52d7873 100644 --- a/src/memory.c +++ b/src/memory.c @@ -1443,6 +1443,10 @@ void patch_vt_version(char* pMem, int size) int c, srchLen, strLen; int found = FALSE; + /* Validate the ROM was found and we have a good pointer */ + if (gStdRomDesc == NULL) + return; + /* Test if VirtulalT version should replace (C) Micro***t text */ if (gShowVersion) { @@ -1512,6 +1516,20 @@ void load_sys_rom(void) FILE* fd; //int fd; + /* Set pointer to ROM Description */ + if (gModel == MODEL_T200) + gStdRomDesc = &gM200_Desc; + else if (gModel == MODEL_PC8201) + gStdRomDesc = &gN8201_Desc; + else if (gModel == MODEL_M10) + gStdRomDesc = &gM10_Desc; + else if (gModel == MODEL_KC85) + gStdRomDesc = &gKC85_Desc; +// else if (gModel == MODEL_PC8300) +// gStdRomDesc = &gN8300_Desc; + else + gStdRomDesc = &gM100_Desc; + /* Get Path to ROM based on current Model selection */ get_rom_path(file, gModel); @@ -1539,20 +1557,6 @@ void load_sys_rom(void) /* Close the ROM file */ fclose(fd); - /* Set pointer to ROM Description */ - if (gModel == MODEL_T200) - gStdRomDesc = &gM200_Desc; - else if (gModel == MODEL_PC8201) - gStdRomDesc = &gN8201_Desc; - else if (gModel == MODEL_M10) - gStdRomDesc = &gM10_Desc; - else if (gModel == MODEL_KC85) - gStdRomDesc = &gKC85_Desc; -// else if (gModel == MODEL_PC8300) -// gStdRomDesc = &gN8300_Desc; - else - gStdRomDesc = &gM100_Desc; - /* Patch the ROM with VirtualT version if requested */ patch_vt_version(gSysROM, ROMSIZE); diff --git a/src/periph.cpp b/src/periph.cpp index 9332dfc..f34f268 100644 --- a/src/periph.cpp +++ b/src/periph.cpp @@ -1694,7 +1694,7 @@ void T100_ComMon::SaveLog(void) } outLine[col + fill] = 0; strcat(outLine, "\n"); - fprintf(fd, outLine); + fprintf(fd, "%s", outLine); outLine[0] = 0; // Clear RXTX so we will start a new line below @@ -1753,7 +1753,7 @@ void T100_ComMon::SaveLog(void) // Terminate the line, append \n and print to file outLine[col + fill] = 0; strcat(outLine, "\n"); - fprintf(fd, outLine); + fprintf(fd, "%s", outLine); // Next line of same packet strcpy(outLine, " "); diff --git a/src/project.cpp b/src/project.cpp index 2363be1..3a6c883 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -152,7 +152,7 @@ void cb_okNewProject(Fl_Widget* w, void*) { fclose(fd); sprintf(projPath, "Project %s already exists!", projName); - fl_alert(projPath); + fl_alert("%s", projPath); return; } diff --git a/src/rememcfg.cpp b/src/rememcfg.cpp index cd9a25a..f6fe58e 100644 --- a/src/rememcfg.cpp +++ b/src/rememcfg.cpp @@ -430,15 +430,13 @@ Callback routine for the RememCfg window void cb_rememcfgwin (Fl_Widget* w, void*) { int ret; - char temp[40]; // Test if current map was modified save_vector_edits(); if (gMapModified) { - sprintf(temp, "Save Map %d changes to ReMem RAM?", gMap); // Ask user if map should be saved - ret = fl_choice(temp, "Cancel", "Yes", "No"); + ret = fl_choice("Save Map %d changes to ReMem RAM?", "Cancel", "Yes", "No", gMap); // Test for Cancel if (ret == 0) @@ -479,7 +477,7 @@ void cb_mapselect (Fl_Widget* w, void*) sprintf(temp, "Save Map %d changes to ReMem RAM?", gMap); // Ask user if map should be saved - ret = fl_choice(temp, "Cancel", "Yes", "No"); + ret = fl_choice("Save Map %d changes to ReMem RAM?", "Cancel", "Yes", "No", gMap); // Test for Cancel if (ret == 0) diff --git a/src/remote.cpp b/src/remote.cpp index 9589c24..c5c47c4 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -3036,24 +3036,26 @@ void* remote_control(void* arg) char sockData[128]; int len; - // Create a listener socket on the desired port number - gSocket.listenPort = 0; - gSocket.socketOpened = FALSE; - gSocket.closeSocket = FALSE; - gSocket.serverSock = new ServerSocket(gSocket.socketPort); - gSocket.socketErrorMsg = ""; - if (gSocket.serverSock == NULL) + try { - gSocket.socketError = TRUE; - sprintf(errmsg, "Unable to open port %d", gSocket.socketPort); + // Create a listener socket on the desired port number + gSocket.listenPort = 0; + gSocket.socketOpened = FALSE; + gSocket.closeSocket = FALSE; + gSocket.serverSock = new ServerSocket(gSocket.socketPort); + gSocket.socketErrorMsg = ""; + if (gSocket.serverSock == NULL) + { + gSocket.socketError = TRUE; + sprintf(errmsg, "Unable to open port %d", gSocket.socketPort); + gSocket.socketErrorMsg = errmsg; + return NULL; + } + gSocket.listenPort = gSocket.socketPort; + sprintf(errmsg, "Listening on port %d", gSocket.socketPort); gSocket.socketErrorMsg = errmsg; - return NULL; - } - gSocket.listenPort = gSocket.socketPort; - // Now listen on the listener port for connections - try - { + // Now listen on the listener port for connections while (!gExitApp && !gSocket.socketShutdown) { gSocket.serverSock->accept(gSocket.openSock); @@ -3096,6 +3098,7 @@ void* remote_control(void* arg) else gSocket.openSock << ret; } + } catch (SocketException&) { diff --git a/src/serial.c b/src/serial.c index d1f664b..540a9ba 100644 --- a/src/serial.c +++ b/src/serial.c @@ -1318,8 +1318,7 @@ int ser_set_signals(unsigned char flags) // Check for a monitor window and report change if (sp.pMonCallback != NULL) - sp.pMonCallback(SER_MON_COM_SIGNAL, (char)((flags>>8) | - (flags & (SER_FLAG_DSR | SER_FLAG_CTS)))); + sp.pMonCallback(SER_MON_COM_SIGNAL, flags & (SER_FLAG_DSR | SER_FLAG_CTS)); return SER_NO_ERROR; } @@ -1362,6 +1361,7 @@ int ser_get_flags(unsigned char *flags) } ReleaseMutex(sp.hReadMutex); + (void *) modem_status; #else { @@ -1410,7 +1410,7 @@ int ser_get_signals(unsigned char *flags) { #ifdef WIN32 - long modem_status; + long modem_status=0; #endif if ((setup.com_mode == SETUP_COM_HOST) || diff --git a/src/setup.cpp b/src/setup.cpp index f2497d6..a74c380 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -186,7 +186,7 @@ void load_setup_preferences(void) #ifdef __APPLE__ //JV 10/08/05 int ex; - char *ret; + const char *ret; //---------JV #endif @@ -218,7 +218,7 @@ void load_setup_preferences(void) ex=virtualt_prefs.get("Path",path,".",256); if(ex==0) // no path in the pref file or pref file nonexistent { - ret=ChooseWorkDir(); // return the directory + ret = ChooseWorkDir(); // return the directory if(ret==NULL) return; //nothing choose: do nothing.... else @@ -226,6 +226,7 @@ void load_setup_preferences(void) strcpy(path,ret); strcat(path,"/"); virtualt_prefs.set("Path",path); // set pref path + load_sys_rom(); } } //JV From 44ca9def3f307974faa0332fed0c3f7b62cf5d7c Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 9 Jul 2011 21:35:44 +0000 Subject: [PATCH 180/327] Updated release notes for v1.5 --- release.txt | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/release.txt b/release.txt index 500f110..c1ac41b 100644 --- a/release.txt +++ b/release.txt @@ -5,10 +5,58 @@ VirtualT Release.txt This file lists the changes and additions for each of the versions of VirtualT since v0.3 +==================== +v1.5 July 9th, 2011 +==================== -======================= -v1.4 Not released yet -======================= +1. Added REX memory module emulation. + +2. Added ability to set custome LCD / Bezel colors. + +3. Updated makefile to compile properly under Mac OSX. The FLTK library must be built + separately and installed (via 'make install') prior to compiling VirtualT + +4. Added new File Browse dialog boxes with nicer look and more features. + +5. Modified the directory structure organization under Mac OSX to be the same as the + Linux and Windows versions: + + Working Dir + | + +--M10 + +--M100 + +--M102 + +--ROMs + etc. + +6. Updated emulation timing control to provide more accurate timing to support sound + generation routines. + +7. Added sound support under Windows. This is still very early stage and needs work as + the sound is "choppy". This is caused by rapid changes to the sound that occur during + the middle of a "sound buffer" being played. The code needs to be updated to detect + these changes and deal with already-queued buffers. + +8. Added mouse detection events to main window to allow point and click, double click, + and right-click actions. + +9. Reworked Assembler / IDE interface. IDE doesn't seem to work under OSX yet. + +10. Completed the Assembler and have about 90% of the linker done. The assembler will + actually geneate output files given a single input file. + +11. Added Socket Interface configuration dialog box. + +12. Added telnet interface mode to socket interface. + +13. Added a shortcut to the socket interface to allow setting register values using a simple + "a=4", "hl=12h" syntax. + +14. Added detection of hex values via trailing 'H' or 'h' to socket interface. + +=============================== +v1.4 Never officially released +=============================== 1. The COM data log on the Peripherals Window was not allowing selection of data to show time delta between 2 bytes when the top line in the window was not the first line of From 306ff0c8e7dc075ef4567fd025ed6000a42fef28 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 10 Jul 2011 06:58:52 +0000 Subject: [PATCH 181/327] Updated Makefile for OSX build to generate universal build for i386 and ppc architectures. Also fixed issue with frequency scaling on OSX. --- GNUmakefile | 7 ++++++- VirtualT.sln | 6 ++++++ VirtualT.suo | Bin 353280 -> 347648 bytes src/m100emu.c | 9 ++++++++- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index e1bedb6..dec0e01 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -17,6 +17,11 @@ CPPFLAGS += -I $(FLTKDIR) -I src -g EXECUTABLE = virtualt CLIENT = vt_client +HOST = $(shell uname) +ifeq ($(HOST),Darwin) +CFLAGS += -arch i386 -arch ppc /Developer/SDKs/MacOSX10.5.sdk/ +endif + FLTKCONFIG = $(FLTKDIR)/fltk-config FLTKLIB = $(shell $(FLTKCONFIG) --libs) #FLTKLIB = $(FLTKDIR)/lib/libfltk.a @@ -25,7 +30,7 @@ VPATH = src:obj LDFLAGS += -g -L/usr/X11R6/lib -L$(FLTKDIR)/lib LIBFILES = -lstdc++ -lfltk_images -lfltk_jpeg -lfltk_png -lfltk_z -lfltk -lm -lc -lX11 -lpthread -MACLDFLAGS = $(shell $(FLTKCONFIG) --ldflags) +MACLDFLAGS = $(shell $(FLTKCONFIG) --ldflags) -arch i386 -arch ppc MACLIBFILES = -lstdc++ `$(FLTKCONFIG) --ldstaticflags --use-images` --lm -lpthread OBJECTS = $(SOURCES:.c=.o) diff --git a/VirtualT.sln b/VirtualT.sln index 7f5f4d0..8f3c390 100644 --- a/VirtualT.sln +++ b/VirtualT.sln @@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VirtualT", "VirtualT.vcproj", "{4B62EF01-B8D4-4C99-BC7B-661B97684568}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vt_client", "vt_client_src\vt_client.vcproj", "{2EE29331-FFC1-46AF-96AB-AA0643DF918E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -13,6 +15,10 @@ Global {4B62EF01-B8D4-4C99-BC7B-661B97684568}.Debug|Win32.Build.0 = Debug|Win32 {4B62EF01-B8D4-4C99-BC7B-661B97684568}.Release|Win32.ActiveCfg = Release|Win32 {4B62EF01-B8D4-4C99-BC7B-661B97684568}.Release|Win32.Build.0 = Release|Win32 + {2EE29331-FFC1-46AF-96AB-AA0643DF918E}.Debug|Win32.ActiveCfg = Debug|Win32 + {2EE29331-FFC1-46AF-96AB-AA0643DF918E}.Debug|Win32.Build.0 = Debug|Win32 + {2EE29331-FFC1-46AF-96AB-AA0643DF918E}.Release|Win32.ActiveCfg = Release|Win32 + {2EE29331-FFC1-46AF-96AB-AA0643DF918E}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/VirtualT.suo b/VirtualT.suo index afe678d8b7b7f5fc5fc2a1d6b81f9fb19751bedf..2a9454de93edae02bbc681ae485a75c7499714e7 100644 GIT binary patch delta 26171 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 Sc4WAEg`ZieU_x-Rd@t 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 gThrottleCycles) + while (cycles >= gThrottleCycles) { sem_wait(&gThrottleEvent); } From 44559382ffd035bd457960e73c0d9769abcb7cf9 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Mon, 11 Jul 2011 06:17:23 +0000 Subject: [PATCH 182/327] Updates to fix working directory management on Mac OSX when running from Finder, to remove warnings from all platforms, updates to GNUMakefile to detect installed FLTK libraries and remove dependency on FLTKDIR environment variable, updated release.txt. --- Darwin.mk | 7 ++- GNUmakefile | 83 +++++++++++++++++++------- VirtualT.suo | Bin 347648 -> 347648 bytes src/FluSimpleString.cpp | 22 ++++--- src/Flu_DND.cpp | 15 +++-- src/Flu_File_Chooser.cpp | 5 +- src/Flu_Tree_Browser.cpp | 17 ++++-- src/MStringArray.cpp | 1 - src/My_Text_Display.cpp | 2 +- src/assemble.cpp | 11 +--- src/clock.cpp | 1 - src/disassemble.cpp | 1 - src/display.cpp | 69 +++++++++++++++++----- src/do_instruct.h | 3 + src/file.cpp | 4 +- src/genwrap.c | 3 +- src/ide.cpp | 1 - src/inet_pton.c | 2 +- src/m100emu.c | 122 ++++++++++++++++++++++++++++++--------- src/memedit.cpp | 2 - src/memory.c | 24 ++++---- src/setup.cpp | 32 +++++++++- src/socket.cpp | 6 +- src/sound.c | 11 ++-- src/vt_client_main.cpp | 2 +- src/vtpaper.cpp | 1 + 26 files changed, 319 insertions(+), 128 deletions(-) diff --git a/Darwin.mk b/Darwin.mk index 1cb7261..9bde65e 100644 --- a/Darwin.mk +++ b/Darwin.mk @@ -1 +1,6 @@ -CFLAGS += -D__unix__ +CFLAGS += -D__unix__ -I/usr/include/malloc/ -arch i386 -arch ppc +CPPFLAGS += -D__unix__ -I/usr/include/malloc/ -arch i386 -arch ppc +FLTKDIR ?= /usr/local/bin + +#post: +# /usr/local/bin/fltk-config --post virtualt diff --git a/GNUmakefile b/GNUmakefile index dec0e01..613821a 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -12,33 +12,43 @@ -include $(shell uname).mk -CFLAGS += -I $(FLTKDIR) -I src/FLU -g -CPPFLAGS += -I $(FLTKDIR) -I src -g +CFLAGS += -I src/FLU -O2 +CPPFLAGS += -I src -O2 EXECUTABLE = virtualt CLIENT = vt_client -HOST = $(shell uname) -ifeq ($(HOST),Darwin) -CFLAGS += -arch i386 -arch ppc /Developer/SDKs/MacOSX10.5.sdk/ +# ============================= +# Find the FLTK libs +# ============================= +FLTKCONFIG = $(shell which fltk-config) +ifneq ($(FLTKCONFIG),) +FLTKLIB = $(shell $(FLTKCONFIG) --libs) endif +POSTBUILD = $(FLTKCONFIG) --post -FLTKCONFIG = $(FLTKDIR)/fltk-config -FLTKLIB = $(shell $(FLTKCONFIG) --libs) -#FLTKLIB = $(FLTKDIR)/lib/libfltk.a -VPATH = src:obj +ifeq ($(FLTKLIB),) +ifneq ($(FLTKDIR),) +FLTKLIB = $(FLTKDIR)/lib/libfltk.a +endif +endif -LDFLAGS += -g -L/usr/X11R6/lib -L$(FLTKDIR)/lib +VPATH = src:obj +LDFLAGS += -L/usr/X11R6/lib LIBFILES = -lstdc++ -lfltk_images -lfltk_jpeg -lfltk_png -lfltk_z -lfltk -lm -lc -lX11 -lpthread +# ============================= +# Defines for MacOSX builds +# ============================= MACLDFLAGS = $(shell $(FLTKCONFIG) --ldflags) -arch i386 -arch ppc MACLIBFILES = -lstdc++ `$(FLTKCONFIG) --ldstaticflags --use-images` --lm -lpthread +# ============================= +# General make rules +# ============================= OBJECTS = $(SOURCES:.c=.o) OBJECTSCPP = $(SOURCESCPP:.cpp=.o) CLIENT_OBJS = $(CLIENT_SRC:.cpp=.o) OBJDIR = obj -POSTBUILD = $(FLTKCONFIG) --post -FLTKLIBS = $(FLTKDIR)/lib # ============================= @@ -70,8 +80,9 @@ all: virtualt vt_client # ======================== $(EXECUTABLE): $(OBJECTS) $(OBJECTSCPP) -ifndef FLTKDIR +ifndef FLTKLIB @echo "FLTKDIR environment variable must be set first!" + @echo "Or install the FLTK libraries" exit 1 else # Test if FLTK libraries built @@ -97,8 +108,9 @@ endif # Rule to build vt_client # ======================== $(CLIENT): $(CLIENT_OBJS) -ifndef FLTKDIR +ifndef FLTKLIB @echo "FLTKDIR environment variable must be set first!" + @echo "Or install the FLTK libraries" exit 1 else @echo "Linking" $(CLIENT) @@ -116,8 +128,9 @@ endif # Rule for compiling source files # =============================== .cpp.o: -ifndef FLTKDIR +ifndef FLTKLIB @echo "FLTKDIR environment variable must be set first!" + @echo "Or install the FLTK libraries" exit 1 else @echo "Compiling" $< @@ -125,8 +138,9 @@ else endif .c.o: -ifndef FLTKDIR +ifndef FLTKLIB @echo "FLTKDIR environment variable must be set first!" + @echo "Or install the FLTK libraries" exit 1 else @echo "Compiling" $< @@ -206,10 +220,35 @@ vt_client_main.o: clientsocket.h socket.h # Rule to clean all build files # ============================= clean: - echo "=== cleaning ==="; - cd obj; rm *.o; cd ..; \ - rm virtualt - rm vt_client - - + @echo "=== cleaning ==="; + @echo "Objects..." + cd obj; rm -f *.o; cd ..; + @echo "Executables..." + rm -f virtualt + rm -f vt_client + +# ================================================ +# Provide info for building FLTK, Tiger, Leopard versions +# Windows, Linux, etc. +# ================================================ +info: + @echo + @echo "Virtual T make Info" + @echo "===================" + @echo " To build VirtualT, you must first build the FLTK libraries" + @echo " and the FLTK sub-components zlib, png and jpeg. For MacOSX" + @echo " if you are tyring to build a universal build, you should" + @echo " configure fltk with" + @echo + @echo " ./configure --with-archflags=\"-arch i386 -arch ppc\"" + @echo + @echo " When compiling FLTK for a version of OSX earlier than the" + @echo " running version, us a configure line something smilar to:" + @echo + @echo " MACOSX_DEPLOYMENT_TARGET=10.4 ./configure CXX=\"/usr/bin/g++-4.0\" \\" + @echo " CC=\"/usr/bin/gcc-4.0\" \\" + @echo " CPP=\"/usr/bin/cpp-4.0\" \\" + @echo " CFLAGS=\"-isysroot /Developer/SDKs/MacOSX10.4u.sdk\" \\" + @echo " --with-archflags=\"-arch i386 -arch ppc\"" + @echo diff --git a/VirtualT.suo b/VirtualT.suo index 2a9454de93edae02bbc681ae485a75c7499714e7..5084ad758d39edb7a38c03aa3091e9fb37a04284 100644 GIT binary patch delta 1684 zcmYk6Urbw79LM{+y=`HFGD@i{vjS@gf818kZGmbjF#lzYO2%GXALgPNDq9RT3dKo7 zNXX{mG&l2XW^0IUK4_xGM(>L_9K=OUrs2u>U<~oWhsBiyn3<9K{g%_jZ~E!^-tYOH zd+s^+w3$o3%q8FFBc^*cI5+x0cW%_Y8J%=MKL7*V1Om#yFJKG!6)@`tKLKhDFr(H1 z$KC~{>|glpU_)p0{{YH|qEcP0IC9tG7wgQwF_V={Cd)Pog~DxIgW}tEEjq|Ids0+_|DgdAjsHJ%S!*_E*ByCogDwUv8J)m)J4*7fz+t>l(pfKpg?h!XOE#=K->qqY35(CeR7M!pFc#K)nH& z@wlA=)M>yho}0VlG}NC3>CG8;d)?OJO5}V>o+<9g@!}4Axhg-qUHehoU%XbU9vPC} zO`j^0Y2!6hr9Bc-!E$MpzG8=+Dwjm1Tez_UdRVO_tOc{(eHJfyNvw1}q_TbqyQK&B z9@0gA>6fRJTroOTdP7Fky#)!#v(~r$ohlKLdK|(Z-=58?quXTrt_qCX3Ti<$;DTJh z3w)pkFbe^{gKs>rXNS&s3Yk+afOUK`t$^AMm~qD=R)guaG8-v76OhbQ51!u(~KBEQvlT?dr%4XPtWIvOLmo0zF*8NnP!PKMj9B+B3|o z@o?A&*7Tq>RnyS)gObWuIh|W_%VDP+D~-G)qbSwZt0A__csAm%INdx=RMYR z9e3J;0H+}4sDR;pxYd>LjcD)F8Ml3%osd^&^fmDKIJVhyvvR}P$%*R`@DF5%uH*ee z@I0qYI`hK^;Hg$-YHN$RPyN;oe^DV#}p4dAp>UUPV_$v;s0_ovO}oyr(9V`_ffjN9=sb4rwv zHe*$1Fp#_4H|=b@)qM(8{9rdII7irO z`(ZH_Cny0u>WPjrgfaAkikSw4O12^@ZbOTpBFG&0$q#KI&Q)gP^Srq}^w)dtxj*ma z-n%z_u|9pV{?iHN+kEd8k%{Nds9U|kN+HD0pc?!NBB1W3H%4x zjs9Pu$Nmo01W{*1MRN0r_qVFGQmLeq$z-&v~8bzfMlQ_a`reldwg)s&0AmmKZ7 ziLo5=BT7!=0c$W^ibMmmAXub#;grI z3#f6x>;O0ksIvfB+`R_p+(?L5%b~lF8JqD?y1(4Et@n8p^_krKKOV=Vv+9uz>WXM+^v3Ilt1{qkD)&3)=jZOj>>~&pQ@BI&hyGlRmi9b zSIG{OSdcsOsVX^C!(BDS207%D{TO}R9pQV^5#l4sZ8md_GFI-?CD4RxjLu&z554dA{K?9&31k8Bq!+>f9 z%=q>=o@xioV&;#a3-z@xJkM)RLdSB){?O=M1gLcw~9kIBO%|U8UM>M&AL?csDas+phMR z-+N?3zWTEKVxouZ+m9B01$x*6C9^(wKC$0s+u--WQ@qGhn5mCtG#{>W+N5_BX~sPR z7g7NSc=D-$I=NTf!)HE!`-r-;OJ84#o5DGj$R{RMMjB^Qq5iT;bUcpfI5WQmd^{P2 s=Z_q>8JF^uqfcKAHN9jbUbQpu)N3f+TYvjS6*0$p #include "FLU/FluSimpleString.h" +#ifdef WIN32 +#define STRDUP _strdup +#else +#define STRDUP strdup +#endif + FluSimpleString :: FluSimpleString() { - str = strdup(""); + str = STRDUP(""); } FluSimpleString :: FluSimpleString( unsigned int len ) @@ -25,18 +31,18 @@ FluSimpleString :: FluSimpleString( unsigned int len ) if( len > 0 ) str = (char*)malloc( len ); else - str = strdup(""); + str = STRDUP(""); } FluSimpleString :: FluSimpleString( const char *s ) { - str = strdup(""); + str = STRDUP(""); *this = s; } FluSimpleString :: FluSimpleString( const FluSimpleString& s ) { - str = strdup(""); + str = STRDUP(""); *this = s.str; } @@ -121,9 +127,9 @@ FluSimpleString& FluSimpleString :: operator =( const char *s ) { char* tmp; if(s==0) - tmp = strdup(""); + tmp = STRDUP(""); else - tmp = strdup(s); + tmp = STRDUP(s); if(str) free(str); str = tmp; @@ -134,7 +140,7 @@ FluSimpleString& FluSimpleString :: operator +=( const char *s ) { if( s==0 ) s = ""; - char *old = strdup(str); + char *old = STRDUP(str); int lold = strlen(old), ls = strlen(s); free(str); str = (char*)malloc( lold + ls + 1 ); diff --git a/src/Flu_DND.cpp b/src/Flu_DND.cpp index 98b853f..316f53f 100644 --- a/src/Flu_DND.cpp +++ b/src/Flu_DND.cpp @@ -14,8 +14,15 @@ #include +#include #include "FLU/Flu_DND.h" +#ifdef WIN32 +#define STRDUP _strdup +#else +#define STRDUP strdup +#endif + Flu_DND_Event :: Flu_DND_Event() { _text = _dataType = 0; @@ -45,7 +52,7 @@ Flu_DND :: Flu_DND( const char *thisType ) { // initialize everything nTypes = 0; - _thisType = strdup( thisType ); + _thisType = STRDUP( thisType ); dnd_allow_text( false ); dnd_callback( 0 ); allowDragging = allowDropping = true; @@ -64,7 +71,7 @@ void Flu_DND :: dnd_allow_type( const char *t ) { if( nTypes >= FLU_DND_MAX_TYPES ) return; - allowedTypes[nTypes++] = strdup( t ); + allowedTypes[nTypes++] = STRDUP( t ); } bool Flu_DND :: dnd_type_allowed( const char *t ) const @@ -86,7 +93,7 @@ void Flu_DND :: dnd_grab( void *data, const char *type ) dndEvent.exit = false; dndEvent.objUnderMouse = this; dndEvent._data = data; - dndEvent._dataType = strdup( type ); + dndEvent._dataType = STRDUP( type ); dndEvent._grab_x = Fl::event_x(); dndEvent._grab_y = Fl::event_y(); @@ -213,7 +220,7 @@ int Flu_DND :: dnd_handle( int event ) if( !dndEvent.data() ) { dndEvent.clear(); - dndEvent._text = strdup( Fl::event_text() ); + dndEvent._text = STRDUP( Fl::event_text() ); } dndEvent._drop_x = Fl::event_x(); dndEvent._drop_y = Fl::event_y(); diff --git a/src/Flu_File_Chooser.cpp b/src/Flu_File_Chooser.cpp index 0d05046..ddfdfc5 100644 --- a/src/Flu_File_Chooser.cpp +++ b/src/Flu_File_Chooser.cpp @@ -26,8 +26,11 @@ #include #include #include +#define STRDUP _strdup +#pragma warning( disable : 4355) #else #include +#define STRDUP strdup #endif #include @@ -2266,7 +2269,7 @@ int Flu_File_Chooser :: popupContextMenu( Entry *entry ) ext = (char *) strrchr( filename, '.' ); if( ext ) { - ext = strdup( ext+1 ); // skip the '.' + ext = STRDUP( ext+1 ); // skip the '.' for( unsigned int i = 0; i < strlen(ext); i++ ) ext[i] = tolower( ext[i] ); } diff --git a/src/Flu_Tree_Browser.cpp b/src/Flu_Tree_Browser.cpp index 7334f0c..7d300f0 100644 --- a/src/Flu_Tree_Browser.cpp +++ b/src/Flu_Tree_Browser.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "FLU/Flu_Tree_Browser.h" #include "FLU/flu_pixmaps.h" @@ -26,6 +27,12 @@ #define ABS( x ) ( (x)>0 ? (x) : -(x) ) #define LERP( t, x0, x1 ) ( (x0) + (t)*( (x1) - (x0) ) ) +#ifdef WIN32 +#define STRDUP _strdup +#else +#define STRDUP strdup +#endif + #ifdef USE_FLU_DND Flu_Tree_Browser :: DND_Object :: DND_Object() : Flu_DND( "DND_Object" ) { @@ -2968,7 +2975,7 @@ bool Flu_Tree_Browser :: Node :: findPath( unsigned int id, RData &rdata ) if( is_leaf() ) return false; - char *oldPath = strdup( rdata.path.c_str() ); + char *oldPath = STRDUP( rdata.path.c_str() ); if( _parent != 0 ) { rdata.path += text; @@ -3008,7 +3015,7 @@ bool Flu_Tree_Browser :: Node :: findPath( Fl_Widget *w, RData &rdata ) if( is_leaf() ) return false; - char *oldPath = strdup( rdata.path.c_str() ); + char *oldPath = STRDUP( rdata.path.c_str() ); if( _parent != 0 ) { rdata.path += text; @@ -3054,7 +3061,7 @@ const char* Flu_Tree_Browser :: find_path( Fl_Widget *w ) char* remove_escape_chars( const char *str ) { // remove any escape characters - char *text = strdup( str ); + char *text = STRDUP( str ); int tIndex = 0; for( int pIndex = 0; pIndex < (int)strlen( str ); pIndex++ ) { @@ -3148,7 +3155,7 @@ Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: modify( const char* path, in if( slash == NULL ) { branchNode = false; - char *name = strdup( path ); // copy the path + char *name = STRDUP( path ); // copy the path nodeName = remove_escape_chars( name ); // remove the escape characters free( name ); lastNode = true; @@ -3355,7 +3362,7 @@ Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: insert_at( Node* p, Node* i, if( slash == NULL ) { branchNode = false; - char *name = strdup( path ); // copy the path + char *name = STRDUP( path ); // copy the path nodeName = remove_escape_chars( name ); // remove the escape characters free( name ); lastNode = true; diff --git a/src/MStringArray.cpp b/src/MStringArray.cpp index 63f73f5..175a6f9 100644 --- a/src/MStringArray.cpp +++ b/src/MStringArray.cpp @@ -168,7 +168,6 @@ void MStringArray::test() { MArrayNode *tmp = headMNode; - int count = 0; // cout << "Head = " << headMNode << endl; while (tmp) { diff --git a/src/My_Text_Display.cpp b/src/My_Text_Display.cpp index d24efea..ac235ce 100644 --- a/src/My_Text_Display.cpp +++ b/src/My_Text_Display.cpp @@ -2844,7 +2844,7 @@ void My_Text_Display::draw(void) { // draw the non-text, non-scrollbar areas. if (damage() & FL_DAMAGE_ALL) { - Fl_Region r = XRectangleRegion(0, 0, w(), h()); +// Fl_Region r = XRectangleRegion(0, 0, w(), h()); fl_push_clip(0, 0, w(), h()); // fl_clip_region(r); diff --git a/src/assemble.cpp b/src/assemble.cpp index 7862f21..75cc2c8 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -117,8 +117,6 @@ void cb_assembler(class Fl_Widget* w, void*) { VTAssembler* pAsm = new VTAssembler; - int x = sizeof(CInstruction); - pAsm->Parse("test.asm"); delete pAsm; @@ -1761,8 +1759,6 @@ This function is called when a fill directive is encountered void VTAssembler::directive_fill() { int c, len; - int fillToAddr = -1; - unsigned char fillByte = 0xFF; double value; MString string; @@ -2538,7 +2534,6 @@ int VTAssembler::preproc_macro() count = pMacro->m_ParamList->GetSize(); for (c = 0; c < count; c++) { - int atEnd = FALSE; int pos = 0; CExpression* paramExp = (CExpression *) pMacro->m_ParamList->GetAt(c); MString param = paramExp->m_Literal; @@ -3292,9 +3287,9 @@ int VTAssembler::CreateObjFile(const char *filename) const int aseg_off = 17; const int cseg_off = 23; const int dseg_off = 29; - const int relcseg_off = 35; - const int reldseg_off = 44; - const int extern_off = 53; +// const int relcseg_off = 35; +// const int reldseg_off = 44; +// const int extern_off = 53; int len, strtab_start; int first_aseg_idx, first_cseg_idx, first_dseg_idx; int shidx, type, bind; diff --git a/src/clock.cpp b/src/clock.cpp index 6271d13..cb77e0c 100644 --- a/src/clock.cpp +++ b/src/clock.cpp @@ -83,7 +83,6 @@ other than T200. */ void pd1990ac_chip_cmd(uchar val) { - static int clk_cnt = 1; time_t time_delta; struct tm when; int x; diff --git a/src/disassemble.cpp b/src/disassemble.cpp index 13b8633..51c1f3e 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -611,7 +611,6 @@ void VTDis::Disassemble() int next; int last = c + m_pRom->pTables[x].size; int str_active = 0; - int quote_active = 0; for (next = c; next < last; next++) { if ((m_memory[next] > 0x7E) && (str_active)) diff --git a/src/display.cpp b/src/display.cpp index 96b7523..c96c1c9 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -47,7 +47,9 @@ #include #include +#include #ifndef WIN32 +#include #include #endif @@ -749,6 +751,8 @@ void cb_choosewkdir(Fl_Widget* w, void*) { /* Choose the working directory (ROM, RAM Files... */ const char *ret; + char rompath[512]; + struct stat romStat; /* Get working directory from chooser */ ret = ChooseWorkDir(); @@ -756,15 +760,33 @@ void cb_choosewkdir(Fl_Widget* w, void*) return; else { + // When changing directory, we must preserve RAM if the + // emulation is running. + get_rom_path(rompath, gModel); + if (stat(rompath, &romStat) == 0) + { + save_ram(); + save_model_time(); + } + + free_mem(); strcpy(path, ret); - //#ifdef __unix__ - //strcat(path,"/"); - //#else - //strcat(path,"\\"); - //#endif virtualt_prefs.set("Path", path); - load_sys_rom(); - resetcpu(); + + // Re-initialize emulation from new directory + init_pref(); + load_memory_preferences(); + init_mem(); + get_model_time(); + + /* Re-initialize the CPU */ + init_cpu(); + + /* Update Memory Editor window if any */ + cb_MemoryEditorUpdate(); + + // Update the File View window if it is open + fileview_model_changed(); } } //--JV @@ -1821,15 +1843,33 @@ void init_pref(void) gMaintCount = 4096; break; #else - case 0: gMaintCount = 4096; break; - case 1: gMaintCount = 8192; break; - case 2: gMaintCount = 16384; break; + case 0: + set_target_frequency(VT_SPEED0_FREQ); + gMaintCount = 4096; + break; + case 1: + set_target_frequency(VT_SPEED1_FREQ); + gMaintCount = 8192; + break; + case 2: + set_target_frequency(VT_SPEED2_FREQ); + gMaintCount = 16384; + break; #ifdef __APPLE__ - case 3: gMaintCount = 65536; break; + case 3: + set_target_frequency(VT_SPEED3_FREQ); + gMaintCount = 65536; + break; #else - case 3: gMaintCount = 131072; break; + case 3: + set_target_frequency(VT_SPEED3_FREQ); + gMaintCount = 131072; + break; #endif - default: gMaintCount = 4096; break; + default: + set_target_frequency(VT_SPEED0_FREQ); + gMaintCount = 4096; + break; #endif } @@ -3093,7 +3133,6 @@ drag selection and word drag selection. */ int T100_Disp::MouseMoveInText(int mx, int my) { - int lines = gModel == MODEL_T200 ? 16 : 8; int cursorRow, cursorCol; int newCol, newRow, pos; @@ -3267,8 +3306,6 @@ int T100_Disp::handle(int event) { int mx = Fl::event_x(); int my = Fl::event_y(); - int wx = x(); - int wy = y(); int procFkey = FALSE; int whichMenu; if ((mx >= m_BezelLeft + m_BezelLeftW) && (mx <= m_BezelRight) && diff --git a/src/do_instruct.h b/src/do_instruct.h index a77145b..9cdd754 100644 --- a/src/do_instruct.h +++ b/src/do_instruct.h @@ -27,6 +27,8 @@ * SUCH DAMAGE. */ +#ifndef INST_8085 +#define INST_8085 #define LXI(rp,h,l,rps) { \ INCPC; \ @@ -299,6 +301,7 @@ INCPC2; \ cycle_delta+=(7); \ } +#endif { // if(trace) diff --git a/src/file.cpp b/src/file.cpp index d5f57d6..08cc404 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -1189,7 +1189,7 @@ void cb_SaveToHost(Fl_Widget* w, void*) int dir_index; unsigned char file_type; int x, c; - int col_widths[] = {120, 100,100, 0}; +// int col_widths[] = {120, 100,100, 0}; model_t_files_t tFiles[100]; int tCount; @@ -1299,7 +1299,7 @@ const char* ChooseWorkDir() // Create a File chooser fl_cursor(FL_CURSOR_WAIT); fileWin = new Flu_File_Chooser(path, "", - Flu_File_Chooser::DIRECTORY, "Choose Working Directory - Should be the PARENT of ROMs dir"); + Flu_File_Chooser::DIRECTORY, "Choose Working Directory"); fl_cursor(FL_CURSOR_DEFAULT); fileWin->preview(0); fileWin->show(); diff --git a/src/genwrap.c b/src/genwrap.c index 3db7187..177397a 100644 --- a/src/genwrap.c +++ b/src/genwrap.c @@ -211,7 +211,6 @@ char* strrev(char* str) /****************************************************************************/ void DLLCALL unix_beep(int freq, int dur) { - static int console_fd=-1; #if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) int speaker_fd=-1; @@ -228,6 +227,8 @@ void DLLCALL unix_beep(int freq, int dur) #endif #if !defined(__GNU__) && !defined(__QNX__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__APPLE__) + static int console_fd=-1; + if(console_fd == -1) console_fd = open("/dev/console", O_NOCTTY); diff --git a/src/ide.cpp b/src/ide.cpp index b816a66..c526802 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -3165,7 +3165,6 @@ void VT_Ide::OpenTreeFile(Flu_Tree_Browser::Node* n) MString file; MString title; int children, c; - int count = 6; Fl_Widget* pWidget; pSource = (VT_IdeSource *) n->user_data(); diff --git a/src/inet_pton.c b/src/inet_pton.c index b562807..0b2c996 100644 --- a/src/inet_pton.c +++ b/src/inet_pton.c @@ -165,7 +165,7 @@ int inet_pton4(char *src, u_char *dst, int pton) * Concoct the address according to * the number of parts specified. */ - n = pp - parts + 1; + n = (u_int) (pp - parts + 1); /* inet_pton() takes dotted-quad only. it does not take shorthand. */ if (pton && n != 4) return (0); diff --git a/src/m100emu.c b/src/m100emu.c index 746d609..be792ec 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -106,9 +106,7 @@ FILE *tracefile; volatile DWORD rst7cycles = 9830; static time_t gLptTime; static UINT64 one_sec_cycles; -static DWORD one_sec_cycle_count; static time_t one_sec_time; -static DWORD last_one_sec_time; float cpu_speed; float gCpuSpeedAvg[4]; int gCpuSpeedAvgIndex = 0; @@ -124,6 +122,9 @@ int gRemoteSwitchModel = -1; //Added J. VERNET char path[512]; char file[512]; +#ifdef __APPLE__ +char gOsxBundlePath[512]; +#endif extern RomDescription_t gM100_Desc; extern RomDescription_t gM200_Desc; @@ -211,6 +212,8 @@ void * ThrottlePeriodProc(void *pParams) else usleep(sleepUs * 2); } + + return NULL; } #endif @@ -609,6 +612,7 @@ int check_model_support(int model) fclose(fd); return TRUE; } + /* ============================================================================= check_installation: This routine checks that VirtualT is properly installed @@ -626,6 +630,13 @@ void check_installation(void) char errors[256]; FILE *fd, *fd2; + /* Test if Mac OSX and no path specified */ +#ifdef __APPLE__ + struct stat romStat; + if (strlen(path) == 0) + return; +#endif + errors[0] = 0; /* Check each model */ @@ -639,6 +650,16 @@ void check_installation(void) get_rom_path(localpath, model); #if defined(__APPLE__) sprintf(roms_path, "%sROMs%s", path, strrchr(localpath, '/')); + + /* Test if the ROM file exists in the working directory */ + if (stat(roms_path, &romStat) != 0) + { + /* Test if running from a bundle & get the bundle path */ + if (strlen(gOsxBundlePath) > 0) + { + sprintf(roms_path, "%s/Resources%s", gOsxBundlePath, strrchr(localpath, '/')); + } + } #else sprintf(roms_path, "ROMs%s", strrchr(localpath, '/')); #endif @@ -1093,7 +1114,6 @@ void emulate(void) { unsigned int i,j; unsigned int v; - int top=0; int nxtmaint=1; int ins; @@ -1298,7 +1318,7 @@ void setup_unix_signals(void) /* ======================================================================== -This routine sets the working path. On Linus and MacOS platforms, this +This routine sets the working path. On Linux and MacOS platforms, this is done by looking at the argv[0] argument and removing the app name. ======================================================================== */ @@ -1311,48 +1331,96 @@ void setup_working_path(char **argv) int found; char temp[512]; struct stat romStat; + char* pContents, *pStr; #endif getcwd(path, sizeof(path)); - //J. VERNET: Get Absolute Path, as getcwd doesn't return anything when launch from finder #if defined(__APPLE__) + /* On MacOSX, getcwd returns nothing when launched from the Finder. So + we must perform an intelligent search for the working directory + based on argv[0]. + */ found = FALSE; - /* Recursively search up the path until we find the ROMs directory */ - i = strlen(argv[0])-1; - strcpy(temp, argv[0]); - while (!found) + /* Search for the /VirtualT.app/Contents directory */ + pContents = strstr(argv[0], "/VirtualT.app/Contents"); + + // First search for "/VT Emulation" folder in the same directory as the VirtualT.app + if (pContents != NULL) + { + for (i = 0, pStr = argv[0]; pStr != pContents; pStr++) + path[i++] = *pStr; + path[i++] = '/'; + path[i] = '\0'; + + /* Save a copy of the bundle path */ + strcpy(gOsxBundlePath, path); + strcat(gOsxBundlePath, "/VirtualT.app/Contents"); + + strcat(path, "/VT Emulation"); + if (stat(path, &romStat) == 0) + found = TRUE; + else + path[0] = '\0'; + } + + // Search in the User's Home/Documents directory if not found + if (!found) { - // Find last '/' in path to remove app name from the path - while ((argv[0][i] != '/') && (i > 0)) - i--; - if (i < 0) - break; - temp[i+1] = 0; - - /* Now append "ROMs" and check if the directory exists */ - strcat(temp, "ROMs"); - if (stat(temp, &romStat) == 0) + // Get the HOME directory from the environement + char* ptr = getenv("HOME"); + if (ptr != NULL) { - if (S_ISDIR(romStat.st_mode)) + strcpy(temp, ptr); + strcat(temp, "/Documents/VT Emulation"); + if (stat(temp, &romStat) == 0) { found = TRUE; - strncpy(path, argv[0], i+1); - path[i+1] = 0; + strcpy(path, temp); } } - else + } + + // Search for a ROMs directory + if (!found) + { + /* Recursively search up the path looking for a ROMs directory */ + i = strlen(argv[0])-1; + strcpy(temp, argv[0]); + while (!found) { - /* Not this directory segment...skip the '/' and find next higher */ - i--; + // Find last '/' in path to remove app name from the path + while ((argv[0][i] != '/') && (i > 0)) + i--; + if (i < 0) + break; + temp[i+1] = 0; + + /* Now append "ROMs" and check if the directory exists */ + strcat(temp, "ROMs"); + if (stat(temp, &romStat) == 0) + { + if (S_ISDIR(romStat.st_mode)) + { + found = TRUE; + strncpy(path, argv[0], i+1); + path[i+1] = 0; + } + i--; + } + else + { + /* Not this directory segment...skip the '/' and find next higher */ + i--; + } } } #endif // Check if the last character is '/' i = strlen(path); - if (path[i-1] != '/') + if ((i > 0) && (path[i-1] != '/')) strcat(path, "/"); # else _getcwd(path, sizeof(path)); @@ -1371,11 +1439,11 @@ int main(int argc, char **argv) return 1; setup_working_path(argv); /* Create a working dir path */ - check_installation(); /* Test if install needs to be performed */ setup_unix_signals(); /* Setup Unix signal handling */ // Added by JV for prefs init_pref(); /* load user Menu preferences */ + check_installation(); /* Test if install needs to be performed */ load_setup_preferences(); /* Load user Peripheral setup preferences */ load_memory_preferences(); /* Load user Memory setup preferences */ load_remote_preferences(); /* Load user Remote Socket preferences */ diff --git a/src/memedit.cpp b/src/memedit.cpp index 2e9d992..d1d3f94 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -169,8 +169,6 @@ Callback routine for the Region choice box */ void cb_region(Fl_Widget* w, void*) { - int size = memedit_ctrl.pRegion->value(); - // Set new region here memedit_ctrl.pMemEdit->SetScrollSize(); memedit_ctrl.pMemEdit->redraw(); diff --git a/src/memory.c b/src/memory.c index 52d7873..38e4abd 100644 --- a/src/memory.c +++ b/src/memory.c @@ -300,9 +300,9 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) if (region == REGION_REMEM_RAM) ptr = gReMemRam; else if (region == REGION_FLASH1) - ptr = gReMemFlash1.pFlash; + ptr = (uchar *) gReMemFlash1.pFlash; else - ptr = gReMemFlash2.pFlash; + ptr = (uchar *) gReMemFlash2.pFlash; // Block is not mapped -- copy from 2Meg Region (RAM or FLASH) addr = address; @@ -324,7 +324,7 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) cp_ptr = 0; // Determine which location to copy memory from - ptr = gRexFlash.pFlash; + ptr = (uchar *) gRexFlash.pFlash; // Block is not mapped -- copy from 2Meg Region (RAM or FLASH) addr = address; @@ -525,9 +525,9 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) if (region == REGION_REMEM_RAM) ptr = gReMemRam; else if (region == REGION_FLASH1) - ptr = gReMemFlash1.pFlash; + ptr = (uchar *) gReMemFlash1.pFlash; else if (region == REGION_FLASH2) - ptr = gReMemFlash2.pFlash; + ptr = (uchar *) gReMemFlash2.pFlash; addr = address; @@ -548,7 +548,7 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) return; /* Get pointer to the REX flash */ - ptr = gRexFlash.pFlash; + ptr = (uchar *) gRexFlash.pFlash; /* Setup to copy */ addr = address; @@ -1255,7 +1255,6 @@ void load_rex_flash(void) { FILE *fd; int size; - int empty = 1; /* Open ReMem file */ fd = fopen(mem_setup.rex_flash_file, "rb+"); @@ -1286,7 +1285,6 @@ void load_rex2_ram(void) { FILE *fd; int size; - int empty = 1; /* Open ReMem file */ fd = fopen(mem_setup.rex2_ram_file, "rb+"); @@ -1558,7 +1556,7 @@ void load_sys_rom(void) fclose(fd); /* Patch the ROM with VirtualT version if requested */ - patch_vt_version(gSysROM, ROMSIZE); + patch_vt_version((char *) gSysROM, ROMSIZE); /* Copy ROM into system memory */ memcpy(gBaseMemory, gSysROM, ROMSIZE); @@ -2715,9 +2713,9 @@ void remem_copy_normal_to_system(void) /* First copy ROM to system memory */ blocks = gModel == MODEL_T200 ? 40 : 32; if (gModel != MODEL_T200) - pSrc = (gReMemBoot ? gReMemFlash2.pFlash : gReMemFlash1.pFlash) + 0x8000 * gRomBank; + pSrc = (uchar *) (gReMemBoot ? gReMemFlash2.pFlash : gReMemFlash1.pFlash) + 0x8000 * gRomBank; else - pSrc = (gReMemBoot ? gReMemFlash2.pFlash : gReMemFlash1.pFlash) + (gRomBank == 0 ? 0 : + pSrc = (uchar *) (gReMemBoot ? gReMemFlash2.pFlash : gReMemFlash1.pFlash) + (gRomBank == 0 ? 0 : 0x10000 + 0x8000 * (gRomBank - 1)); dest = 0; @@ -2768,9 +2766,9 @@ void remem_copy_mmu_to_block(int block) if ((gReMemMap[block] & REMEM_VCTR_RAM_CS) == 0) pSrc = gReMemRam; else if ((gReMemMap[block] & REMEM_VCTR_FLASH1_CS) == 0) - pSrc = gReMemFlash1.pFlash; + pSrc = (uchar *) gReMemFlash1.pFlash; else if ((gReMemMap[block] & REMEM_VCTR_FLASH2_CS) == 0) - pSrc = gReMemFlash2.pFlash; + pSrc = (uchar *) gReMemFlash2.pFlash; else return; diff --git a/src/setup.cpp b/src/setup.cpp index a74c380..2f0ac65 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -46,6 +46,9 @@ #include #include #include +#ifdef __APPLE__ +#include +#endif #include "FLU/Flu_File_Chooser.h" @@ -213,10 +216,15 @@ void load_setup_preferences(void) load_clock_preferences(&virtualt_prefs); #ifdef __APPLE__ + char temp_path[512]; + struct stat pathStat; + //JV 08/10/05 // Load Path Preferences - ex=virtualt_prefs.get("Path",path,".",256); - if(ex==0) // no path in the pref file or pref file nonexistent + ex = virtualt_prefs.get("Path", temp_path, ".", 512); + + // Test if path exists in the pref file + if ((ex == 0) && (strlen(path) == 0)) { ret = ChooseWorkDir(); // return the directory if(ret==NULL) @@ -227,9 +235,27 @@ void load_setup_preferences(void) strcat(path,"/"); virtualt_prefs.set("Path",path); // set pref path load_sys_rom(); + resetcpu(); + } + } + + // Override a program guessed path with the user's preference + else if ((ex != 0) && (strlen(temp_path) > 0)) + { + // Override the path only if we can stat the directory + if (stat(temp_path, &pathStat) == 0) + { + strcpy(path, temp_path); } } - //JV +#if 0 + if (strcmp(path, "./") == 0) + { + getcwd(path, sizeof(path)); + strcat(path, "/"); + } +#endif + #endif } diff --git a/src/socket.cpp b/src/socket.cpp index 7da2281..826abf8 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -33,7 +33,7 @@ Socket::~Socket() bool Socket::create() { - m_sock = socket ( AF_INET, + m_sock = (int) socket ( AF_INET, SOCK_STREAM, 0 ); @@ -106,7 +106,7 @@ bool Socket::listen() const bool Socket::accept ( Socket& new_socket ) const { int addr_length = sizeof ( m_addr ); - new_socket.m_sock = ::accept ( m_sock, ( sockaddr * ) &m_addr, ( socklen_t * ) &addr_length ); + new_socket.m_sock = (int) ::accept ( m_sock, ( sockaddr * ) &m_addr, ( socklen_t * ) &addr_length ); if ( new_socket.m_sock <= 0 ) return false; @@ -125,7 +125,7 @@ bool Socket::send ( const std::string s ) const #else flags = MSG_NOSIGNAL; #endif - int status = ::send ( m_sock, s.c_str(), s.size(), flags ); + int status = ::send ( m_sock, s.c_str(), (int) s.size(), flags ); if ( status == -1 ) { return false; diff --git a/src/sound.c b/src/sound.c index 3c6496d..f03e23f 100644 --- a/src/sound.c +++ b/src/sound.c @@ -71,9 +71,12 @@ */ static int gReqFreq[16]; static int gReqIn = 0; -static int gReqOut = 0; static int gReqLastFreq = 0; + +#ifdef _WIN32 +static int gReqOut = 0; static int gDecaySample = 0; +#endif unsigned short readbuf [BLOCK_SIZE >> 1] ; /* input buffer */ unsigned short gpOneHertz[SAMPLING_RATE]; @@ -132,8 +135,6 @@ sound_waveout_proc: Callback routine called when a buffer is done being static void CALLBACK sound_waveout_proc(HWAVEOUT hWaveOut, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) { - WAVEHDR* current; - /* pointer to free block counter */ int* freeBlockCounter = (int*)dwInstance; @@ -305,7 +306,6 @@ BOOL sound_close_output (void) void sound_reset_output(void) { DWORD volume; - DWORD newVol; /* Before resetting the output device cold turkey, we need to reduce the volume in an "Attack" fassion so we don't get @@ -354,7 +354,8 @@ sound_play_tome: Creates and plays a tone of the frequency specified */ void sound_play_tone() { - int i, zero_cross, zero_cross_point; + int i; +// int zero_cross, zero_cross_point; int samples = BLOCK_SIZE >> 1; int tone = gPlayTone; int toneFreq = gToneFreq; diff --git a/src/vt_client_main.cpp b/src/vt_client_main.cpp index 7422b84..7bf20f0 100644 --- a/src/vt_client_main.cpp +++ b/src/vt_client_main.cpp @@ -160,7 +160,7 @@ int main ( int argc, char* argv[] ) } catch ( SocketException& e) { - std::cout << "Exception!\n"; + std::cout << "Exception - " << e.description() << "\n"; } // Check if response is "Ok" or contains "Ok" at the end diff --git a/src/vtpaper.cpp b/src/vtpaper.cpp index 5f19bb1..2cb4e26 100644 --- a/src/vtpaper.cpp +++ b/src/vtpaper.cpp @@ -1560,6 +1560,7 @@ int VTlprPaper::Print(void) pclose(pFD); //exit(0); } + return 0; } #else From 9493d0afb9214bba8832e6b006ab7ed8dc109ec6 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Mon, 11 Jul 2011 15:03:44 +0000 Subject: [PATCH 183/327] Updated GNUmakefile to fix an issue locating the FLTK header files on some Linux systems. --- GNUmakefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/GNUmakefile b/GNUmakefile index 613821a..5e002ee 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -23,12 +23,16 @@ CLIENT = vt_client FLTKCONFIG = $(shell which fltk-config) ifneq ($(FLTKCONFIG),) FLTKLIB = $(shell $(FLTKCONFIG) --libs) +CFLAGS += $(shell $(FLTKCONFIG) --cflags) +CPPFLAGS += $(shell $(FLTKCONFIG) --cxxflags) endif POSTBUILD = $(FLTKCONFIG) --post ifeq ($(FLTKLIB),) ifneq ($(FLTKDIR),) FLTKLIB = $(FLTKDIR)/lib/libfltk.a +CFLAGS += -I$(FLTKDIR) +CPPFLAGS += -I$(FLTKDIR) endif endif From 82d2d652cd506651878bf99cfb6cc818af7e63de Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Mon, 11 Jul 2011 15:07:15 +0000 Subject: [PATCH 184/327] Updating Visual C++ .suo file --- VirtualT.suo | Bin 347648 -> 347648 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/VirtualT.suo b/VirtualT.suo index 5084ad758d39edb7a38c03aa3091e9fb37a04284..49ea4fa3c65be8f2ec9f20eca6f23dabf5ab8b2d 100644 GIT binary patch delta 18391 zcmeI42b2_5zQ(J%t0%ya8D^LPre}uCkR*wOi6A*hkQ|Ie1snw=^oXD9w$w|m%!Yjioz-cw?=}mqvU*a>22dlZj zDI0BNhS%kc@vWG$+qtZvl@@-d`T4ktZ1YY;?1G>2*`Kt{^1W%;<=XX$I|A~RVUKEe zm#?20{;}Quz=}unR_w@I5y`VlX6A)=cV6fVO+e+S#JCPA+d#ho+K+U)7!qS8{;(md z!~)Qc*lIE6c^tYe(#>KldmD6nq&q!vPetR}8cz!%G1l=9?0^_6c^KQeD_%9EPSH5##1x@uwTo_r%!F_rpI82qe^g52eq8AArw?FM#tD(QUi-h~`Zl zkd^RN@E^(<#%iQ@!ta9L4POJl2YxSnojr3z6EkdY7}2Emc5Lr}N8mf*yWoF;KLLNz zJ~bkx=3c0M@Mq!A!S};i?~8WrksYiP*s@2AtYv*hF?(d)Hr)3)HokzLgme2#q+h{L z!@q`q13v@jzHgZ>pW0-_sDjWj9Xe0PQT7S!LosfCfE~jp&?lg2 zUy4zG1&ykVQnC8b-zx4$mlZkpcQCuyaigE?JPeUF5ik;|_w)l94~R8@-oO%Jo5gxU zZ}Dv%Q)t@ztd?;-fY(&Ee;iXceDBx~eRf_^-qw>PKD*>xo>LMqn};92c4VA2_T_W! zdC3mtfMRWI6)y{R0|y)#50$qMIyqSo&Q{Xuz{xV<8E{%QoUC?u&ULq%<_LRFuMT#{ z8?&q`Ge&>G8hMvV$Y*u6;Vd>*469=?tS$&=G0ot0rP+IAY;tz^nJM{JC<Nz zIE@(@+!x*)PHO`vYXWZzr}3g8n+)#&r*(ysT?D@rP8$j*WBJ42v@3%6Lzn}<5>A@{ zCu3tKI&Hd|*`1+`oA?Jd9nRf6iF4s;a2$rqILv0iX}80paa(UH@#h)FF>Dd!!?#hu z{zI%a^k-r}it)gH5-aZu@1A+kv~F5IdTn^wtQr2K&u=+CfF82aCVKiTe#HzeK}H_( zQaBq|0RID==D^7~pjX3b8{lMJ;19xSVK`YFd?)-0_%3)XZW}ahFPseRGoFK|BWwOL z(;s@#v*UGWHs}ox%RnxUk04SOzy|Gu(;A8mhHk{2ux4T-p__}f7GopZLvxT{5@q2% z_PmO`R_)^Z2AZ|hJNGRyLu^PbI9lpf%qxQ1HQ>BjSauaSpU$)(oQzjYCY;tDPR6T- zV}LdY9*bkcY2)Bz9H-;qu#i!Vzl6NRI1+i8&V-Yt!f%GN@>y^)HgGnaYz~}^SICWU z+Cn%P?+Sl}(;k46@haQ^r}31T#%RO9I5f7Czz)C}$VME5vnO7Lld{o;}U2Nzs_Rp!(3?E`0z82F7Ue-OHExYoBP?%rnhiPGW?eP!{&p5 zdI-yk?kn9=)ha)}QVZTf?GGMF3OC+**q>(@m#L~zNGW;xM~hu4#xb}IdMMK6Vm+X* zGVQz_yV>Qi_1bY2^nK8@uo!QIPeOALKPAS)dLKF~oExcW`93!7VNbLT@aftpyz+@F zCI=&U$}krty;fsoO>&ns*J7y{pK4@0 zVv|jW#ZFE`Xr3HeWySIQR}rf%#)fr=W|1SsGI)EhqreG*9E}sjrg_*6VmFJil38N& zJnUAnJH#$V+(NOXp15T$L;tT7WD6gK4kFzy#@6nD=J1V(K^kYF@t<+d!^)r;?~jl6 z7JGFSgJ4&SwS>L~nsx&j?-UKgp)a2`oqd)47jg3nd*o$A(RcBv{*~ZMX z&wl+vs95Uy}gy=!@cpE|Umfu*cAN04;%tnzIhf~u;!>EX~1yXLaydr4)XABVIfee9W zxkFusGseI<*x;>yt^#@X#zC_OSBo+3C1}3(AM~&$<)SPHX{_SQpbHQ;K#UcZKzBhp zPplVomk^GC_LyK0dJ{BltA~Zf_K01J{d>jU6uTPiEwQ)7I)eRG?6}wsU>}NwP73li za7yrNvEE?ci2WqS+sZjHLvsTjsj0a^4Y77$DPrkjtfQ7#>nIDkuOw{*J1DR_0y~Oz z5gP^8RjiNLaIn5&L&P}y8!C2%7%!eH#jX|W2{x`ghcs-aU>@|%3Y;s}4J;(KRICTs zGO-=ySA4gZ!`yfZLxdxM&3~H11@@vCZ!j;3y(-2`uaVhh-|Y)E!sujfj=dacUj0R4 z4WJuC(=PSI^?>HsS|Y|;x+!jjCvGJ)FOECK8bRBNTN7m=x8k+f;BmdHKwgdaDDapV z8~7nKFNBZ8AdMQhTB;#ULCOPRwp!4f&({{?(Kdx{h_snl6X*~8xDshg1$pCM22EQj z#v}bRG;arwde~-Yj>|1#h0v>@X*06LIuq$j9(D+tb4-4mV?K_6BXJnRy&j$*v~#6#11iZy}mB{s+tH(2ZjGLFLj@M6I^3giQHuGmsBo|0u^tC4aN z59HcUXgH6G7YQ5Q7;Y*yb}-x>2gbN^iu2VmR-7xz!$qiI9xV%?RaS6yu`IA;#ntr0 zrBw*;J~!WQ7bUe=S!@n8hqzDv?WN`-D>qtQhN6QgA*d4SdP=AV&1N+cqip^7 z6lZRlnHFhL)vRX4xmEU#4!+_VxB~iWAl5Kn3-m$0e(tt;Rpi?gvwTDMrps5kDJqgP zBvuoI7sF}O;bgpx%z)Eo!^wCk92{-o^WbEB`rQs^5Bvd6#s}CU_;~mdI2k--tbyS8 zxKEIQN8p3t?|9f5=mzjoF+SD!Rf={V&H`CZ8Jt!Lz&*{-+{Yo)0Ij8Nt~7&99b)e( z?i4COXI_B{ZZJk5rEZ3Nz7E1w}B^DCn z0hEZ{pCFj-9J|J!5qeCU9BZ2t!}Su@oeAf<3H1ve7MpIp;$gAr)*-PV^1La1R4Lp0 zw)A_^G~|9Fcpn?I6WYm&KN91D3>#1x&V?DCwG?zF87&Q(p>@P~<}#pZ*`Bz%ifbsw z$x$OeqhU=wfz1?nkysA)w{kMin;GucBIfIaU9@~pwgP4AD%KSHIg6zA^u+a2Tt6`m z_5RLdSNhVO7Ug{jEjg5@Dqo2w-!00wK#Vtw+o+u_y{u}ZcQaQPEuV@dl*MN1FWMpwIcL|J2QnW} z(J0i|0L|()im`+K?A&pSFMCiG$WmZl9^Y#>PuLI8L8NEJvYG%_f$3R&1bI^WLenl6qaI>K&aXG;nYat3yEmhUc-3z~%6u$uD|B6?+r;>RI{Ntom!uewu^*c4d&$FIhvwYukQnzL zfzCquPL$c9dKr;Ao6I_a-+UU4bPJn1EBY$OIZw~`WsP9th9d)CYDTCqHjW>Ic!o!b zvC#{l*#WnS)rPJMO^bckq2_lTHYifE*IX2IN8t&xV{C;O8+aQuD_$c8Y3zgM2s#j-7d<-m z^dZ5w6iD`!*w-G$?>o#KKx!J1^JmSye)l0<5rEfTRd+|U;B>JJ4{Iov<6&*Y+KcfB zJ3!|lEfC|;6pHl_V{l@7hXs)nzyPUw{Qcj5>&&O!4c|5=Pj z`s06L?2+?e9J^(TV?)1(ro~~<^Pu=5k-!T8)>Vv0cWIRQjIQ>cM(rXy+xU9a zH=ejNiu+zH6LCKz>Nb#AE_$?JMmcC6Sw%6o|Dk!ms_kL*pbNq3i?QNL(6r8C)Va_s zuTZQpbP+UdXgSP(SpjXB0!Jy31&&tWTrtLl6nCo_2kU&rt?lgX7H3_AO1C1dEKZ#xzXf#~asSN;}zokN7zMNwhgS`-m*s z=!8o zXJ8-8oQag%e6JhJco=^yMMhf-O&t664<8B}oWy`HJ96H!ta3GXD^qNa&rF=-`<&x_ z%oOvuGd3xZ9%v2vsa<dvzdL%f@*yF8vL%xVq@P`n?v8_n9Y1C95=?tDup`Uie7n%NZG2! z@K3Ox)=7-IGc@B1#5i3lbne`5rDyS*CbM!kzh&}5enQNhSX<7`dA>AXrGQ=1H0T5$ zus>&8%a#wELIKbat;b6U=Mf7vDf;d5mgj>Ox=7$g>-)j+V6uWjfYIE2rsFs3qKj zFM}_KuYlX|Kfz}iN-<)~ z&pdUp<>#5o%Q&ugGH$LI%e)(!BPq80%y~)(3^vM$t!HwJ>zT~F)03I&nauoxSQhjy zXxecx>JOorm+P6VlwUVKb;j>8vqPOB@q1I(Qjl^tEftzsYKirN=1L{4qbIJD;_^KV z-@e?Ree@S&vkIVT13htr;_!W*l?)Z+2_I(XW~aB|8YP>;qnod+k9)Fm63?8m340KF zyPa8(9(qqvtn_{5Y^Zq}kkJU5Ih%?Fp_@U|I2(<1z$nFGHtMn<_Ft*ERh~FUad$^q zoO_R0W6vy1uW(plb&>Um)97|zdd1kvU?$MF@y@2Ifg0}1Qj+Euyn-rdevv5#WMo0J z)%C@Atv66yo+mC}ab3hX6uT;Jm?v(y;xPLQxrfI_lP?j}#%bj8gQ3nFf|;z~Smw&oyU07@B(GmOx8_T0tSl}i> zcH%Z@PJy6F5SFV?69?vGHOoi2oRX4ZO({H&bzQJ?tK_^)ZI}jg8n~=06LvwV&dY&~}MY z{{@<7HujGJ$leCy#E?I>kDWUHnw({v^00&o(bH4`DdT8q&>^0?I)dz)0_Z}du>~3i za~+Ry{S-&WWe>*B@~}hDO~H^U1oX=VM}rBtLln-Z$}{LJ z+O=ZT5aZ}5WLLm0^~7~kTraU^9PhmqIK>knO(koy59S#dXduWLaGW#~|fr_!Y;luuo64c9?-)X6WhxxnD77tiP#w_$|e7 zF}bUEWIT#kTwiFmwx1a9B0b==*h(MuaQ=b)0nWTE?+!R0l?&NRg!SPzoVFbvt7L~u zFi#f?BK=hQOQpP;&cIXP--@Lo{SMA<`d*AT&mZ75;Ah2xJWKB31DqFRfqt}rfdQm! z3^T_;R7c9?Q!);mGB_z}(o|*#b9!j&pdh%t3 z6<(&46S4u){HIXd$IQc}M=Ry<9|KMMpRA{v_eXwC50tl@53ljp`uA$8+n@jMS5w`O zalctjb()5(^a}s0E1ng8S@A@ty33uRf4tloy$UbTN@sKi{|}Zr-77ALCjZO-Nkzcv zc+{Wv?|)N)zO95A9PezrzyA~erXt?`z@}y05Hnq zYybW_F`iiLI?fa>z(O%f#q&HqS_k#ttP}HzdEpj{qZRW2e{Y>Q)CN0$f1x;9zy(|* zj?Oqa3;CTzV)y;-!mSMF;1^){gvXc2-&q=V#|P(cS{ZidIKRI#Y#2er{j&d^`;#J#9EOJDr3+Xz6rOB0EL ztfVdUB}gw8YXMyjns%2M_1(~nUn|CnAA)X=^bxU(pw~guPKi-}3C+CUl*fx6Gt!c9 zIr3{s1*BxG_>8^u(ezM9k!B#Bc+tWpi&69cEW!^0#bPX)zm?|FavsuH4c9@lHB-cR zL)r=580juC-o&1U=G}Bpl!e^y)BK*rSDXn*Ss*KU1?|m8`YKYgApAx(@TeG&@isK$ z-xq5KeGHlw`&vZ(sp3v5t~uB#es-dr5zK`yRpzSt$in^ApjkXj(H*Tyw>> z7UQe$7HA&aRu9_?%@@LbAwhmCX#-7rON{z3G%NnAm_>;5!JoavA!W~SQu40yRu$u{ zsW~*?&0C1E+gn1j;#OkrFV(7HgO)4EM{b^2FEQ@#4b8?35@RKkq4}ZUIx$vqJ#;;! iQ^j~K4Th#ILdvg7(JjMSyvpCoDOu>tday;H&VK?^j!oJC delta 11418 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 X=&sO=ap`Vkp|6Z@gzZ+A_*?%MN)|T5 From 7da17d0993045420f7dabe696204e2d775f7089e Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Mon, 11 Jul 2011 16:52:31 +0000 Subject: [PATCH 185/327] Minor updates to IDE and hex file generation from the assembler to write only the assembled code vs. the entire memory space. --- VirtualT.suo | Bin 347648 -> 347648 bytes VirtualT.vcproj | 4 ++++ src/assemble.cpp | 37 +++++++++++++++++++++++++++++++------ src/file.cpp | 2 +- src/ide.cpp | 17 +++++++++++++++-- src/intelhex.c | 26 +++++++++++++------------- src/intelhex.h | 6 +++--- src/memedit.cpp | 2 +- src/project.cpp | 2 +- 9 files changed, 69 insertions(+), 27 deletions(-) diff --git a/VirtualT.suo b/VirtualT.suo index 49ea4fa3c65be8f2ec9f20eca6f23dabf5ab8b2d..20a4c4f86dd3eafd787314c6ae109e516a534242 100644 GIT binary patch delta 372 zcmZpeBib-WbVCjctAIq>=@**|S%TQu7)2Qv7$l}U9%j_u{Do_g6N^)v=gr9ih9aBS z`DzKMerIA}_yNTK{{R2~3rPP4;y*zA7bFJ6|3UQTzp>0k6ALRgS6m1%U`z!Yw)G1m zpTl%ED@Lu!2V8`v+c`4IuuL+G-ZwqYkx_|p&Sb_v-qZI5vINOrs{g(o=mZ9!1^*cs z&I8S31oAFJX@%+ct(eWH>sT`i@aZumGZX+J14CYcR2j&P+tZ#fN-<79ki%rK{ev^( z6&BVQplmeQ0o%WLFkTRyeq$V}WvUP`P5p6_UIlE8$@J%3en2i47v# z`WO!jurWjc6{mp}bAJQ6Wet!E1k?Y!Gs;hwo6o2^*_p?X`zKIl1IW2hnf7_}8G)Dy Nh?%#~o6nN84gj8Nfg1n- delta 367 zcmYMuJxjw-6b9gX;!TB$k|6=5q9PPT7u#7SwSq2!Itkhgf}gllJ2+UapY@}u)~Hu7 zG|)*wiV#d!G5&zg{sJeb&gyF^c;SJ2-@`rUWNa;CYtQRkX5o*gdpF5v0s*Em#@a>9 zrvbMXERFK)r+#NC5!EeE_A7-{U&+`=>~Y5S;Q$Wd2#z5OCvXa9a1J>zArBXD2?e+U z3$Eb?Zb86zAsKSFs#AkBTi@cPMs2$FmKqWxG3w-Y&YTuTjC#duNY=d`S(m&qdgpQi zd(YK>RB97c)#N1v^NqluswyucFdD%oJ#@6LVB9LK{f!lmCdJilT+^@vyO04dPrf32 qgCZ@ + + diff --git a/src/assemble.cpp b/src/assemble.cpp index 75cc2c8..485f5d7 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -4429,7 +4429,9 @@ This function creates an Intel HEX output file of the assembled file */ void VTAssembler::CreateHex(MString& filename) { - unsigned short start, len; + unsigned short start, len, end; + int x; + char* ptr; MString outfile; FILE* fd; CSegment* pSeg; @@ -4440,7 +4442,10 @@ void VTAssembler::CreateHex(MString& filename) // No ASEG Hex output requested...return return; } - + + // Get a pointer to the .aseg segment + m_Segments.Lookup(".aseg", (VTObject *&) pSeg); + if (m_ProjectType == VT_PROJ_TYPE_ROM) { start = 0; @@ -4448,8 +4453,25 @@ void VTAssembler::CreateHex(MString& filename) } else { - start = 32768; - len = 16384; + // Calculate start and length of non-zero bytes in .aseg + start = 0; + end = 0; + len = 0; + + // Loop through bytes in RAM area & find non-zeros + for (x = 0, ptr = (char *) pSeg->m_AsmBytes; x < 65536; x++, ptr++) + { + if (*ptr != 0) + { + if (start == 0) + start = x; + end = x; + } + } + + // Calculate the length of the data + if (start > 0) + len = end - start + 1; } // Open the output listing file @@ -4457,8 +4479,7 @@ void VTAssembler::CreateHex(MString& filename) return; // Save the Intel Hex file - m_Segments.Lookup(".aseg", (VTObject *&) pSeg); - save_hex_file_buf((char *) pSeg->m_AsmBytes, start, start + len, fd); + save_hex_file_buf((char *) pSeg->m_AsmBytes, start, start + len, start, fd); fclose(fd); } @@ -4612,6 +4633,8 @@ void VTAssembler::CalcIncludeDirs(void) CSegment::CSegment(const char *name, int type, CModule* initialMod) { + int x; + m_Name = name; m_Type = type; m_InitialMod = initialMod; @@ -4621,6 +4644,8 @@ CSegment::CSegment(const char *name, int type, CModule* initialMod) m_Address = 0; m_UsedAddr = new AddrRange; m_Index = m_Count = 0; + for (x = 0; x < sizeof(m_AsmBytes); x++) + m_AsmBytes[x] = 0; // Initialize the active Addr range to the first in the list m_ActiveAddr = m_UsedAddr; diff --git a/src/file.cpp b/src/file.cpp index 08cc404..9f3f971 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -1162,7 +1162,7 @@ void save_file(model_t_files_t *pFile) len = get_memory16(addr1+2) + 6; if (COSaveMode == 1) { - save_hex_file(addr1, addr1+len, fd); + save_hex_file(addr1, addr1+len, 0, fd); } else { diff --git a/src/ide.cpp b/src/ide.cpp index c526802..8c0fabb 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -1057,6 +1057,14 @@ void cb_Ide(Fl_Widget* widget, void*) virtualt_prefs.get("IdeY", gIdeY, 40); virtualt_prefs.get("IdeW", gIdeW, 800); virtualt_prefs.get("IdeH", gIdeH, 600); + if (gIdeX < 0) + gIdeX = 0; + if (gIdeY < 0) + gIdeY = 0; + if (gIdeW+6 >= Fl::w()) + gIdeW = Fl::w()-6; + if (gIdeH+35 >= Fl::h()) + gIdeH = Fl::h()-35; make_pref_form(); @@ -1073,7 +1081,7 @@ void cb_Ide(Fl_Widget* widget, void*) if ((gIdeW >= maxW) && (gIdeX < 0)) gIdeW = maxW - 50; if ((gIdeH >= maxH) && (gIdeY < 0)) - gIdeH = maxH - 50; + gIdeH = maxH - 60; if (gIdeY < 0) gIdeY = 0; if (gIdeX < 0) @@ -1887,6 +1895,11 @@ void VT_Ide::NewProject(void) pGroup->m_Filespec = "*.h;*.inc"; m_ActivePrj->m_Groups.Add(pGroup); + pGroup = new VT_IdeGroup; + pGroup->m_Name = "Linker Script"; + pGroup->m_Filespec = "*.lkr"; + m_ActivePrj->m_Groups.Add(pGroup); + pGroup = new VT_IdeGroup; pGroup->m_Name = "Object Files"; pGroup->m_Filespec = "*.obj"; @@ -3402,7 +3415,7 @@ void VT_Ide::BuildProject(void) linker.SetStdoutFunction(this, ideStdoutProc); // Now finally perform the link operation - linker.Link(); +// linker.Link(); errors = linker.GetErrors(); errorCount = errors.GetSize(); diff --git a/src/intelhex.c b/src/intelhex.c index dc9d168..f8476bd 100644 --- a/src/intelhex.c +++ b/src/intelhex.c @@ -54,7 +54,7 @@ int parse_hex_line(char *theline, int bytes[], int *addr, int *num, int *code); /* caution, static buffering is used, so it is necessary */ /* to call it with end=1 when finsihed to flush the buffer */ /* and close the file */ -void hexout(FILE *fhex, int byte, int memory_location, int end); +void hexout(FILE *fhex, int byte, int memory_location, int end, int base_address); //extern char memory[65536]; /* the memory is global */ @@ -175,7 +175,7 @@ int load_hex_file(char *filename, char *buffer, unsigned short *start_addr) /* "begin" and "end" are the locations to dump to the intel */ /* hex file, specified in hexidecimal. */ -void save_hex_file_ext(int begin, int end, int region, FILE* fd) +void save_hex_file_ext(int begin, int end, int region, int base_address, FILE* fd) { int addr; char buffer[16384]; @@ -198,7 +198,7 @@ void save_hex_file_ext(int begin, int end, int region, FILE* fd) // Output all bytes in the buffer for (x = 0; x < len; x++) - hexout(fd, buffer[x], addr + x - begin, 0); + hexout(fd, buffer[x], addr + x - begin, 0, base_address); // Update count count -= len; @@ -207,7 +207,7 @@ void save_hex_file_ext(int begin, int end, int region, FILE* fd) // Update len for next loop len = count > sizeof(buffer) ? sizeof(buffer) : count; } - hexout(fd, 0, 0, 1); + hexout(fd, 0, 0, 1, 0); } @@ -215,7 +215,7 @@ void save_hex_file_ext(int begin, int end, int region, FILE* fd) /* "begin" and "end" are the locations to dump to the intel */ /* hex file, specified in hexidecimal. */ -void save_hex_file(int begin, int end, FILE* fd) +void save_hex_file(int begin, int end, int base_address, FILE* fd) { int addr; @@ -223,15 +223,15 @@ void save_hex_file(int begin, int end, FILE* fd) return; } for (addr=begin; addr <= end; addr++) - hexout(fd, get_memory8((unsigned short) addr), addr, 0); - hexout(fd, 0, 0, 1); + hexout(fd, get_memory8((unsigned short) addr), addr, 0, base_address); + hexout(fd, 0, 0, 1, 0); } /* the command string format is "S begin end filename" where */ /* "begin" and "end" are the locations to dump to the intel */ /* hex file, specified in hexidecimal. */ -void save_hex_file_buf(char *buf, int begin, int end, FILE* fd) +void save_hex_file_buf(char *buf, int begin, int end, int base_address, FILE* fd) { int addr; @@ -239,8 +239,8 @@ void save_hex_file_buf(char *buf, int begin, int end, FILE* fd) return; } for (addr=begin; addr <= end; addr++) - hexout(fd, buf[(unsigned short) addr], addr, 0); - hexout(fd, 0, 0, 1); + hexout(fd, buf[(unsigned short) addr], addr, 0, base_address); + hexout(fd, 0, 0, 1, 0); } @@ -253,7 +253,7 @@ void save_hex_file_buf(char *buf, int begin, int end, FILE* fd) #define MAXHEXLINE 32 /* the maximum number of bytes to put in one line */ -void hexout(FILE *fhex, int byte, int memory_location, int end) +void hexout(FILE *fhex, int byte, int memory_location, int end, int base_address) { static int byte_buffer[MAXHEXLINE]; static int last_mem, buffer_pos, buffer_addr; @@ -271,8 +271,8 @@ void hexout(FILE *fhex, int byte, int memory_location, int end) if ( (memory_location != (last_mem+1)) || (buffer_pos >= MAXHEXLINE) || ((end) && (buffer_pos > 0)) ) { /* it's time to dump the buffer to a line in the file */ - fprintf(fhex, ":%02X%04X00", buffer_pos, buffer_addr); - sum = buffer_pos + ((buffer_addr>>8)&255) + (buffer_addr&255); + fprintf(fhex, ":%02X%04X00", buffer_pos, buffer_addr + base_address); + sum = buffer_pos + (((buffer_addr + base_address)>>8)&255) + ((buffer_addr+base_address)&255); for (i=0; i < buffer_pos; i++) { fprintf(fhex, "%02X", byte_buffer[i]&255); sum += byte_buffer[i]&255; diff --git a/src/intelhex.h b/src/intelhex.h index 24ff266..50b91cd 100644 --- a/src/intelhex.h +++ b/src/intelhex.h @@ -34,8 +34,8 @@ int load_hex_file(char *filename, char *buffer, unsigned short *start_addr); /* this writes a part of memory[] to an intel hex file */ -void save_hex_file(int begin, int end, FILE* fd); -void save_hex_file_ext(int begin, int end, int region, FILE* fd); -void save_hex_file_buf(char *buf, int begin, int end, FILE* fd); +void save_hex_file(int begin, int end, int base_address, FILE* fd); +void save_hex_file_ext(int begin, int end, int region, int base_address, FILE* fd); +void save_hex_file_buf(char *buf, int begin, int end, int base_address, FILE* fd); #endif diff --git a/src/memedit.cpp b/src/memedit.cpp index d1d3f94..4f7ec80 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -373,7 +373,7 @@ void save_mem_to_file(const char *filename, int address, int count, int save_as_ if (fd == NULL) return; - save_hex_file_ext(address, address+count-1, region, fd); + save_hex_file_ext(address, address+count-1, region, 0, fd); fclose(fd); } diff --git a/src/project.cpp b/src/project.cpp index 3a6c883..393ca3f 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -139,7 +139,7 @@ void cb_okNewProject(Fl_Widget* w, void*) } // Check if project type provided - if (pNewProject->getProjType() == 0) + if (pNewProject->getProjType() < 0) { fl_alert("Project type must be specified!"); return; From 8d837e0370a49774ca190a8d42d43dbfb7b30bdb Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 22 Jan 2013 22:29:01 +0000 Subject: [PATCH 186/327] Updated IDE with nicer tabs, finished the linker, made updates to the assembler, added "extended opcodes" for the experimental FPGA based 8085 enhanced CPU, added an LCD data capture hot key "GRPH + CODE + SHIFT" to dump data to a file, added cursor blinking in the IDE editor. --- src/Flu_Combo_Box.cpp | 8 + src/My_Text_Display.cpp | 174 +- src/My_Text_Display.h | 25 +- src/My_Text_Editor.cpp | 9 +- src/My_Text_Editor.h | 2 +- src/VirtualT.h | 2 +- src/a85parse.cpp | 10044 +++++++++++++++++++++----------------- src/a85parse.h | 50 +- src/a85parse.syn | 49 +- src/assemble.cpp | 909 +++- src/assemble.h | 103 +- src/do_instruct.h | 64 +- src/doins.c | 6 +- src/doins.h | 2 +- src/elf.h | 14 +- src/highlight.cpp | 23 + src/ide.cpp | 368 +- src/ide.h | 7 +- src/idetabs.cpp | 425 +- src/idetabs.h | 14 +- src/io.c | 31 + src/linker.cpp | 1573 +++++- src/linker.h | 75 +- src/project.cpp | 63 +- src/project.h | 5 +- src/rpn_eqn.h | 1 + 26 files changed, 8839 insertions(+), 5207 deletions(-) diff --git a/src/Flu_Combo_Box.cpp b/src/Flu_Combo_Box.cpp index 406abed..f70be13 100644 --- a/src/Flu_Combo_Box.cpp +++ b/src/Flu_Combo_Box.cpp @@ -137,6 +137,14 @@ void Flu_Combo_Box :: selected( const char *v ) do_callback(); } +void Flu_Combo_Box :: selectall(void) +{ + const char *v = input.value(); + if (v) + input.position(0, strlen(v)); + input.redraw(); +} + int Flu_Combo_Box::Popup :: handle( int event ) { // FL_MOVE is generated while window is moving diff --git a/src/My_Text_Display.cpp b/src/My_Text_Display.cpp index ac235ce..ee858e7 100644 --- a/src/My_Text_Display.cpp +++ b/src/My_Text_Display.cpp @@ -42,7 +42,7 @@ // there is some room for the overhanging parts of the cursor! #define TOP_MARGIN 1 #define BOTTOM_MARGIN 1 -#define LEFT_MARGIN 18 +#define LEFT_MARGIN 10 #define RIGHT_MARGIN 3 #define NO_HINT -1 @@ -67,6 +67,27 @@ static int countlines( const char *string ); // CET - FIXME #define TMPFONTWIDTH 6 +void cb_cursor_blink(void *pOpaque) +{ + My_Text_Display* pDisp = (My_Text_Display *) pOpaque; + + pDisp->blink_cursor(); +} + +void My_Text_Display::blink_cursor(void) +{ + if (++mBlinkCount == 2) + { + mBlinkCount = 0; + mBlinkOn = mCursorOn; + show_cursor(0); + } + else + show_cursor(mBlinkOn); + + Fl::add_timeout(0.6, cb_cursor_blink, this); +} + My_Text_Display::My_Text_Display(int X, int Y, int W, int H, const char* l) : Fl_Double_Window(X, Y, W, H, l) { int i; @@ -74,6 +95,10 @@ My_Text_Display::My_Text_Display(int X, int Y, int W, int H, const char* l) border(0); mMaxsize = 0; mCurrentCol = 0; + mBlinkCount = 0; + mLeftMargin = LEFT_MARGIN; + bHasUtilityMargin = 0; + mUtilityMarginColor = FL_BLACK; damage_range1_start = damage_range1_end = -1; damage_range2_start = damage_range2_end = -1; dragPos = dragType = dragging = 0; @@ -140,6 +165,9 @@ My_Text_Display::My_Text_Display(int X, int Y, int W, int H, const char* l) mContinuousWrap = 0; mWrapMargin = 0; mSuppressResync = mNLinesDeleted = mModifyingTabDistance = 0; + + m_pErrorFunc = NULL; + m_pErrorOpaque = NULL; } /* @@ -148,10 +176,33 @@ My_Text_Display::My_Text_Display(int X, int Y, int W, int H, const char* l) ** freed, nor are the style buffer or style table. */ My_Text_Display::~My_Text_Display() { + Fl::remove_timeout(cb_cursor_blink, this); if (mBuffer) mBuffer->remove_modify_callback(buffer_modified_cb, this); if (mLineStarts) delete[] mLineStarts; } +/* +** Returns the position of the specified line, or -1 if it doesn't exist) +*/ +int My_Text_Display::get_line_pos(int line) +{ + int startPos, lineEnd, nextLineStart, lineCount; + int bufLen = mBuffer->length(); + + startPos = 0; + /* Loop searching for ends of lines and storing the positions of the + start of the next line in lineStarts */ + for ( lineCount = 1; lineCount < line; lineCount++ ) { + find_line_end(startPos, true, &lineEnd, &nextLineStart); + startPos = nextLineStart; + if ( startPos >= bufLen ) { + return -1; + } + } + + return startPos; +} + /* ** Attach a text buffer to display, replacing the current buffer (if any) */ @@ -173,6 +224,8 @@ void My_Text_Display::buffer( Fl_Text_Buffer *buf ) { /* Update the display */ buffer_modified_cb( 0, buf->length(), 0, 0, 0, this ); + Fl::add_timeout(0.33f, cb_cursor_blink, this); + /* Resize the widget to update the screen... */ resize(x(), y(), w(), h()); } @@ -354,14 +407,14 @@ void My_Text_Display::resize(int X, int Y, int W, int H) W -= Fl::box_dw(box()); H -= Fl::box_dh(box()); - text_area.x = X+LEFT_MARGIN; + text_area.x = X+LEFT_MARGIN+mLeftMargin; text_area.y = Y+TOP_MARGIN; - text_area.w = W-LEFT_MARGIN-RIGHT_MARGIN; + text_area.w = W-LEFT_MARGIN-RIGHT_MARGIN*2-mLeftMargin; text_area.h = H-TOP_MARGIN-BOTTOM_MARGIN; int i; /* Find the new maximum font height for this text display */ - for (i = 0, mMaxsize = fl_height(textfont(), textsize()); i < mNStyles; i++) + for (i = 0, mMaxsize = 2+fl_height(textfont(), textsize()); i < mNStyles; i++) mMaxsize = max(mMaxsize, fl_height(mStyleTable[i].font, mStyleTable[i].size)); // did we have scrollbars initially? @@ -405,14 +458,14 @@ void My_Text_Display::resize(int X, int Y, int W, int H) { mVScrollBar->set_visible(); if (scrollbar_align() & FL_ALIGN_LEFT) { - text_area.x = X+scrollbar_width()+LEFT_MARGIN; - text_area.w = W-scrollbar_width()-LEFT_MARGIN-RIGHT_MARGIN; + text_area.x = X+scrollbar_width()+LEFT_MARGIN+mLeftMargin; + text_area.w = W-scrollbar_width()-LEFT_MARGIN-RIGHT_MARGIN*2-mLeftMargin; mVScrollBar->resize(X, text_area.y-TOP_MARGIN, scrollbar_width(), text_area.h+TOP_MARGIN+BOTTOM_MARGIN); } else { - text_area.x = X+LEFT_MARGIN; - text_area.w = W-scrollbar_width()-LEFT_MARGIN-RIGHT_MARGIN; - mVScrollBar->resize(X+W-scrollbar_width(), text_area.y-TOP_MARGIN, + text_area.x = X+LEFT_MARGIN+mLeftMargin; + text_area.w = W-scrollbar_width()-LEFT_MARGIN-RIGHT_MARGIN*2-mLeftMargin-2; + mVScrollBar->resize(X+W-1-scrollbar_width(), text_area.y-TOP_MARGIN, scrollbar_width(), text_area.h+TOP_MARGIN+BOTTOM_MARGIN); } } @@ -448,13 +501,13 @@ void My_Text_Display::resize(int X, int Y, int W, int H) if (scrollbar_align() & FL_ALIGN_TOP) { text_area.y = Y + scrollbar_width()+TOP_MARGIN; text_area.h = H - scrollbar_width()-TOP_MARGIN-BOTTOM_MARGIN; - mHScrollBar->resize(text_area.x-LEFT_MARGIN, Y, - text_area.w+LEFT_MARGIN+RIGHT_MARGIN, scrollbar_width()); + mHScrollBar->resize(text_area.x-LEFT_MARGIN-mLeftMargin, Y, + text_area.w+LEFT_MARGIN+RIGHT_MARGIN*2+mLeftMargin, scrollbar_width()); } else { text_area.y = Y+TOP_MARGIN; text_area.h = H - scrollbar_width()-TOP_MARGIN-BOTTOM_MARGIN; - mHScrollBar->resize(text_area.x-LEFT_MARGIN, Y+H-scrollbar_width(), - text_area.w+LEFT_MARGIN+RIGHT_MARGIN, scrollbar_width()); + mHScrollBar->resize(text_area.x-LEFT_MARGIN-mLeftMargin, Y+H-scrollbar_width(), + text_area.w+LEFT_MARGIN+RIGHT_MARGIN*2+mLeftMargin, scrollbar_width()); } } } @@ -757,27 +810,17 @@ int My_Text_Display::position_to_xy( int pos, int* X, int* Y ) { char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ]; const char *lineStr; -// printf("position_to_xy(pos=%d, X=%p, Y=%p)\n", pos, X, Y); - /* If position is not displayed, return false */ if (pos < mFirstChar || (pos > mLastChar && !empty_vlines())) { -// printf(" returning 0\n" -// " mFirstChar=%d, mLastChar=%d, empty_vlines()=0\n", -// mFirstChar, mLastChar); return 0; } /* Calculate Y coordinate */ if (!position_to_line(pos, &visLineNum)) { -// puts(" returning 0\n" -// " position_to_line()=0"); return 0; } if (visLineNum < 0 || visLineNum > mNBufferLines) { -// printf(" returning 0\n" -// " visLineNum=%d, mNBufferLines=%d\n", -// visLineNum, mNBufferLines); return 0; } @@ -910,13 +953,14 @@ void My_Text_Display::display_insert() { // FIXME: I don't understand this well enough to know if it is correct // it is different than nedit 5.3 if (insert_position() < mFirstChar) { - topLine -= count_lines(insert_position(), mFirstChar, false); + topLine -= count_lines(insert_position(), mFirstChar, false) + + mNVisibleLines/2; } else if (mLineStarts[mNVisibleLines-2] != -1) { int lastChar = buffer()->line_end(mLineStarts[mNVisibleLines-2]); if (insert_position() >= lastChar) topLine += count_lines(lastChar - (wrap_uses_character(mLastChar) ? 0 : 1), - insert_position(), false); + insert_position(), false) + mNVisibleLines/2; } /* Find the new setting for horizontal offset (this is a bit ungraceful). @@ -1420,10 +1464,6 @@ void My_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip, char *outPtr; const char *lineStr; -// printf("draw_vline(visLineNum=%d, leftClip=%d, rightClip=%d, leftCharIndex=%d, rightCharIndex=%d)\n", -// visLineNum, leftClip, rightClip, leftCharIndex, rightCharIndex); -// printf("nNVisibleLines=%d\n", mNVisibleLines); - /* If line is not displayed, skip it */ if ( visLineNum < 0 || visLineNum >= mNVisibleLines ) return; @@ -1434,7 +1474,6 @@ void My_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip, /* Get the text, length, and buffer position of the line to display */ lineStartPos = mLineStarts[ visLineNum ]; -// printf("lineStartPos=%d\n", lineStartPos); if ( lineStartPos == -1 ) { lineLen = 0; lineStr = NULL; @@ -1600,7 +1639,8 @@ void My_Text_Display::draw_string( int style, int X, int Y, int toX, font = styleRec->font; fsize = styleRec->size; - if ( style & (HIGHLIGHT_MASK | PRIMARY_MASK) && Fl::focus() == this) + if (( style & (HIGHLIGHT_MASK | PRIMARY_MASK) && Fl::focus() == this) || + ( style & SECONDARY_MASK)) { background = selection_color(); foreground = fl_contrast(styleRec->color, background); @@ -1609,7 +1649,9 @@ void My_Text_Display::draw_string( int style, int X, int Y, int toX, background = color(); foreground = styleRec->color; } - } else if ( style & (HIGHLIGHT_MASK | PRIMARY_MASK) && Fl::focus() == this ) { + } else if (( style & (HIGHLIGHT_MASK | PRIMARY_MASK) && Fl::focus() == this ) || + ( style & SECONDARY_MASK)) + { background = selection_color(); //foreground = fl_contrast(textcolor(), background); foreground = textcolor(); @@ -2848,7 +2890,6 @@ void My_Text_Display::draw(void) { fl_push_clip(0, 0, w(), h()); // fl_clip_region(r); -// printf("drawing all (box = %d)\n", box()); // draw the box() int W = w(), H = h(); @@ -2859,8 +2900,16 @@ void My_Text_Display::draw(void) { draw_box(box(), x(), y(), w(), h(), color()); // left margin - fl_rectf(text_area.x-LEFT_MARGIN, text_area.y-TOP_MARGIN, - LEFT_MARGIN, text_area.h+TOP_MARGIN+BOTTOM_MARGIN, color()); + if (bHasUtilityMargin) + { + fl_rectf(text_area.x-mLeftMargin - LEFT_MARGIN-1, text_area.y-TOP_MARGIN-1, + mLeftMargin, text_area.h+TOP_MARGIN+BOTTOM_MARGIN, mUtilityMarginColor); + fl_rectf(text_area.x - LEFT_MARGIN, text_area.y-1, + LEFT_MARGIN, text_area.h+2, color()); + } + else + fl_rectf(text_area.x-mLeftMargin, text_area.y-TOP_MARGIN, + mLeftMargin, text_area.h+TOP_MARGIN+BOTTOM_MARGIN, color()); // right margin fl_rectf(text_area.x+text_area.w, text_area.y-TOP_MARGIN, @@ -2886,15 +2935,22 @@ void My_Text_Display::draw(void) { fl_pop_clip(); } else if (damage() & (FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE)) { -// printf("blanking previous cursor extrusions at Y: %d\n", mCursorOldY); // CET - FIXME - save old cursor position instead and just draw side needed? fl_push_clip(0, 0, w(), text_area.h + scrollbar_width()); Fl_Region r = XRectangleRegion(0, 0, w(), text_area.h + scrollbar_width()); fl_clip_region(r); fl_rectf(text_area.x, text_area.y-TOP_MARGIN, w(), TOP_MARGIN, color()); - fl_rectf(text_area.x-LEFT_MARGIN, text_area.y, - LEFT_MARGIN, text_area.h, color()); + if (bHasUtilityMargin) + { + fl_rectf(0, text_area.y-TOP_MARGIN-1, + mLeftMargin, text_area.h+TOP_MARGIN+BOTTOM_MARGIN, mUtilityMarginColor); + fl_rectf(text_area.x - LEFT_MARGIN, text_area.y-1, + LEFT_MARGIN, text_area.h+2, color()); + } + else + fl_rectf(text_area.x-mLeftMargin, text_area.y-TOP_MARGIN, + mLeftMargin, text_area.h+TOP_MARGIN+BOTTOM_MARGIN, color()); fl_rectf(text_area.x+text_area.w, text_area.y, RIGHT_MARGIN, text_area.h, color()); fl_pop_clip(); @@ -2910,7 +2966,6 @@ void My_Text_Display::draw(void) { // draw all of the text if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_EXPOSE)) { - //printf("drawing all text\n"); int X, Y, W, H; if (fl_clip_box(text_area.x, text_area.y, text_area.w, text_area.h, X, Y, W, H)) { @@ -2929,10 +2984,8 @@ void My_Text_Display::draw(void) { Fl_Region r = XRectangleRegion(text_area.x, text_area.y, text_area.w, text_area.h); fl_clip_region(r); - //printf("drawing text from %d to %d\n", damage_range1_start, damage_range1_end); draw_range(damage_range1_start, damage_range1_end); if (damage_range2_end != -1) { - //printf("drawing text from %d to %d\n", damage_range2_start, damage_range2_end); draw_range(damage_range2_start, damage_range2_end); } damage_range1_start = damage_range1_end = -1; @@ -2954,8 +3007,6 @@ void My_Text_Display::draw(void) { int X, Y; if (position_to_xy(mCursorPos, &X, &Y)) draw_cursor(X, Y); -// else puts("position_to_xy() failed - unable to draw cursor!"); - //printf("drew cursor at pos: %d (%d,%d)\n", mCursorPos, X, Y); mCursorOldY = Y; fl_pop_clip(); } @@ -3007,6 +3058,15 @@ int My_Text_Display::handle(int event) position_to_linecol(insert_position(), &line, &mCurrentCol); } + // Reset the blink count so we don't hide the cursor when there is + // activity + if (event != FL_ENTER && event != FL_MOVE) + { + mBlinkCount = 0; + if (mBlinkCount == 0) + show_cursor(mBlinkOn); + } + switch (event) { case FL_ENTER: case FL_MOVE: @@ -3049,7 +3109,33 @@ int My_Text_Display::handle(int event) if (dragType == DRAG_CHAR) buffer()->unselect(); else if (dragType == DRAG_WORD) - buffer()->select(word_start(pos), word_end(pos)); + { + buffer()->secondary_unselect(); + position_to_linecol(pos, &line, &mCurrentCol); + if (strcmp(buffer()->text_range(buffer()->line_start(pos), buffer()->line_start(pos) + 14), "Error in line ") == 0) + { + /* Determine line number and filename of error */ + int errNumPos = buffer()->word_start(buffer()->line_start(pos) + 14); + int errNumEndPos = buffer()->word_end(errNumPos); + int errLine = atoi(buffer()->text_range(errNumPos, errNumEndPos)); + int fileNameStart = errNumEndPos + 1; + int foundPos; + int fileNameEnd = buffer()->search_forward(fileNameStart, ")", &foundPos, 0); + char *pFile = buffer()->text_range(fileNameStart, foundPos); + + // Now call the IDE with the filename and line number instructing it to display the errored line + if (m_pErrorFunc != NULL) + { + buffer()->secondary_select(buffer()->line_start(pos), buffer()->line_end(pos)+1); + redraw(); + m_pErrorFunc(errLine, pFile, m_pErrorOpaque); + /* Perform Secondary selection on this line */ + return 1; + } + } + else + buffer()->select(word_start(pos), word_end(pos)); + } else if (dragType == DRAG_LINE) buffer()->select(buffer()->line_start(pos), buffer()->line_end(pos)+1); diff --git a/src/My_Text_Display.h b/src/My_Text_Display.h index ac13745..fc41b62 100644 --- a/src/My_Text_Display.h +++ b/src/My_Text_Display.h @@ -36,6 +36,8 @@ #include +typedef void (*MyTextDisplay_ReportError_t)(int lineNo, char* file, void* opaque); + class FL_EXPORT My_Text_Display: public Fl_Double_Window { public: enum { @@ -107,7 +109,8 @@ class FL_EXPORT My_Text_Display: public Fl_Double_Window { int word_start(int pos) { return buffer()->word_start(pos); } int word_end(int pos) { return buffer()->word_end(pos); } int current_column(void) { return mCurrentCol; } - + void register_error_report(MyTextDisplay_ReportError_t pFunc, void* pOpaque) + { m_pErrorFunc = pFunc, m_pErrorOpaque = pOpaque; } void highlight_data(Fl_Text_Buffer *styleBuffer, const Style_Table_Entry *styleTable, @@ -128,8 +131,18 @@ class FL_EXPORT My_Text_Display: public Fl_Double_Window { int wrapped_column(int row, int column); int wrapped_row(int row); void wrap_mode(int wrap, int wrap_margin); + int get_line_pos(int line); + int top_line(void) { return mTopLineNum; } + int num_visible_lines(void) { return mNVisibleLines; } virtual void resize(int X, int Y, int W, int H); + + void blink_cursor(void); + + void utility_margin_color(int margin_size, Fl_Color c) + { bHasUtilityMargin = 1; mLeftMargin = margin_size, mUtilityMarginColor = c; + resize(x(), y(), w(), h()); } + //text_area.x += margin_size; text_area.w -= margin_size; } Fl_Color mCursor_color; @@ -217,6 +230,8 @@ class FL_EXPORT My_Text_Display: public Fl_Double_Window { int mCurrentCol; /* Current column number */ int mCursorPos; int mCursorOn; + int mBlinkCount; + int mBlinkOn; int mCursorOldY; /* Y pos. of cursor for blanking */ int mCursorToHint; /* Tells the buffer modified callback where to move the cursor, to reduce @@ -235,6 +250,12 @@ class FL_EXPORT My_Text_Display: public Fl_Double_Window { int mContinuousWrap; /* Wrap long lines when displaying */ int mWrapMargin; /* Margin in # of char positions for wrapping in continuousWrap mode */ + int mLeftMargin; /* The left margin for this window */ + int bHasUtilityMargin; /* Flag indicating if the left margin is used + for displaying utility icons, such as + breakpoints, current execution line, etc. */ + Fl_Color mUtilityMarginColor; + int* mLineStarts; int mTopLineNum; /* Line number of top displayed line of file (first line of file is 1) */ @@ -270,6 +291,8 @@ class FL_EXPORT My_Text_Display: public Fl_Double_Window { int mModifyingTabDistance; /* Whether tab distance is being modified */ + MyTextDisplay_ReportError_t m_pErrorFunc; + void* m_pErrorOpaque; Fl_Scrollbar* mHScrollBar; Fl_Scrollbar* mVScrollBar; diff --git a/src/My_Text_Editor.cpp b/src/My_Text_Editor.cpp index b211294..3eccfa2 100644 --- a/src/My_Text_Editor.cpp +++ b/src/My_Text_Editor.cpp @@ -399,9 +399,12 @@ int My_Text_Editor::kf_undo(int , My_Text_Editor* e) { e->buffer()->unselect(); int crsr; int ret = e->buffer()->undo(&crsr); - e->insert_position(crsr); - e->show_insert_position(); - if (e->when()&FL_WHEN_CHANGED) e->do_callback(); else e->set_changed(); + if (ret) + { + e->insert_position(crsr); + e->show_insert_position(); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); else e->set_changed(); + } return ret; } diff --git a/src/My_Text_Editor.h b/src/My_Text_Editor.h index 65e74fa..a4a34ee 100644 --- a/src/My_Text_Editor.h +++ b/src/My_Text_Editor.h @@ -82,6 +82,7 @@ class FL_EXPORT My_Text_Editor : public My_Text_Display { Key_Func bound_key_function(int key, int state) { return bound_key_function(key, state, key_bindings); } void default_key_function(Key_Func f) { default_key_function_ = f; } + void UpdateStatusBar(void); // functions for the built in default bindings static int kf_default(int c, My_Text_Editor* e); @@ -117,7 +118,6 @@ class FL_EXPORT My_Text_Editor : public My_Text_Display { Key_Binding* key_bindings; static Key_Binding* global_key_bindings; Key_Func default_key_function_; - void UpdateStatusBar(void); }; #endif diff --git a/src/VirtualT.h b/src/VirtualT.h index 55b8f6d..a687c1b 100644 --- a/src/VirtualT.h +++ b/src/VirtualT.h @@ -31,7 +31,7 @@ #ifndef _VIRTUALT_H_ #define _VIRTUALT_H_ -#define VERSION "1.5" +#define VERSION "1.6" enum { MODEL_M100 diff --git a/src/a85parse.cpp b/src/a85parse.cpp index bc94b77..39605ee 100644 --- a/src/a85parse.cpp +++ b/src/a85parse.cpp @@ -17,11 +17,11 @@ */ -#ifndef A85PARSE_H_1277850585 +#ifndef A85PARSE_H_1357391036 #include "a85parse.h" #endif -#ifndef A85PARSE_H_1277850585 +#ifndef A85PARSE_H_1357391036 #error Mismatched header file #endif @@ -39,7 +39,7 @@ a85parse_pcb_type a85parse_pcb; #define PCB a85parse_pcb -/* Line 648, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 695, C:/Projects/VirtualT/src/a85parse.syn */ // Embedded C #include "MString.h" // Include MString header @@ -487,27 +487,33 @@ static int agConvertCase(int c) { #define ag_rp_12() (gAsm->pragma_hex()) -#define ag_rp_13() (gAsm->preproc_ifdef(ss[ss_idx--])) +#define ag_rp_13() (gAsm->pragma_entry(ss[ss_idx--])) -#define ag_rp_14() (gAsm->preproc_if()) +#define ag_rp_14() (gAsm->pragma_verilog()) -#define ag_rp_15() (gAsm->preproc_elif()) +#define ag_rp_15() (gAsm->pragma_extended()) -#define ag_rp_16() (gAsm->preproc_ifndef(ss[ss_idx--])) +#define ag_rp_16() (gAsm->preproc_ifdef(ss[ss_idx--])) -#define ag_rp_17() (gAsm->preproc_else()) +#define ag_rp_17() (gAsm->preproc_if()) -#define ag_rp_18() (gAsm->preproc_endif()) +#define ag_rp_18() (gAsm->preproc_elif()) -static void ag_rp_19(void) { -/* Line 122, C:/Projects/VirtualT/src/a85parse.syn */ +#define ag_rp_19() (gAsm->preproc_ifndef(ss[ss_idx--])) + +#define ag_rp_20() (gAsm->preproc_else()) + +#define ag_rp_21() (gAsm->preproc_endif()) + +static void ag_rp_22(void) { +/* Line 125, C:/Projects/VirtualT/src/a85parse.syn */ if (gAsm->preproc_error(ss[ss_idx--])) gAbort = TRUE; } -#define ag_rp_20() (gAsm->preproc_undef(ss[ss_idx--])) +#define ag_rp_23() (gAsm->preproc_undef(ss[ss_idx--])) -static void ag_rp_21(void) { -/* Line 125, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_24(void) { +/* Line 128, C:/Projects/VirtualT/src/a85parse.syn */ if (gMacroStack[ms_idx] != 0) { delete gMacroStack[ms_idx]; \ gMacroStack[ms_idx] = 0; } \ gMacro = gMacroStack[--ms_idx]; \ @@ -516,20 +522,20 @@ static void ag_rp_21(void) { gMacroStack[ms_idx] = 0; gDefine = 0; } -static void ag_rp_22(void) { -/* Line 133, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_25(void) { +/* Line 136, C:/Projects/VirtualT/src/a85parse.syn */ if (gAsm->preproc_macro()) \ PCB.reduction_token = a85parse_WS_token; } -static void ag_rp_23(void) { -/* Line 135, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_26(void) { +/* Line 138, C:/Projects/VirtualT/src/a85parse.syn */ if (gAsm->preproc_macro()) \ PCB.reduction_token = a85parse_WS_token; } -static void ag_rp_24(void) { -/* Line 139, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_27(void) { +/* Line 142, C:/Projects/VirtualT/src/a85parse.syn */ gMacro->m_ParamList = gExpList; \ gMacro->m_Name = ss[ss_idx--]; \ gExpList = new VTObArray; \ @@ -539,293 +545,305 @@ static void ag_rp_24(void) { gMacro = new CMacro; } -static void ag_rp_25(void) { -/* Line 146, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_28(void) { +/* Line 149, C:/Projects/VirtualT/src/a85parse.syn */ gMacro->m_Name = ss[ss_idx--]; gMacroStack[ms_idx++] = gMacro; \ if (gAsm->preproc_macro()) \ PCB.reduction_token = a85parse_WS_token; \ gMacro = new CMacro; } -static void ag_rp_26(int c) { -/* Line 152, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_29(int c) { +/* Line 155, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_27(int c) { -/* Line 153, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_30(int c) { +/* Line 156, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_28(void) { -/* Line 154, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_31(void) { +/* Line 157, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '\n'; ss[ss_idx][ss_len] = 0; } -static void ag_rp_29(void) { -/* Line 157, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_32(void) { +/* Line 160, C:/Projects/VirtualT/src/a85parse.syn */ page = 0; seg = CSEG; } -static void ag_rp_30(void) { -/* Line 158, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_33(void) { +/* Line 161, C:/Projects/VirtualT/src/a85parse.syn */ page = 0; seg = DSEG; } -#define ag_rp_31(p) (page = p) +#define ag_rp_34(p) (page = p) + +#define ag_rp_35() (gAsm->pragma_list()) -#define ag_rp_32() (gAsm->pragma_list()) +#define ag_rp_36() (gAsm->pragma_hex()) -#define ag_rp_33() (gAsm->pragma_hex()) +#define ag_rp_37() (gAsm->pragma_verilog()) -#define ag_rp_34() (gAsm->directive_org()) +#define ag_rp_38() (gAsm->pragma_entry(ss[ss_idx--])) -#define ag_rp_35() (gAsm->directive_aseg()) +#define ag_rp_39() (gAsm->pragma_extended()) -#define ag_rp_36() (gAsm->directive_ds()) +#define ag_rp_40() (gAsm->directive_org()) -#define ag_rp_37() (gAsm->directive_db()) +#define ag_rp_41() (gAsm->directive_aseg()) -#define ag_rp_38() (gAsm->directive_dw()) +#define ag_rp_42() (gAsm->directive_ds()) -#define ag_rp_39() (gAsm->directive_public()) +#define ag_rp_43() (gAsm->directive_db()) -#define ag_rp_40() (gAsm->directive_extern()) +#define ag_rp_44() (gAsm->directive_dw()) -#define ag_rp_41() (gAsm->directive_extern()) +#define ag_rp_45() (gAsm->directive_public()) -#define ag_rp_42() (gAsm->directive_module(ss[ss_idx--])) +#define ag_rp_46() (gAsm->directive_extern()) -#define ag_rp_43() (gAsm->directive_name(ss[ss_idx--])) +#define ag_rp_47() (gAsm->directive_extern()) -#define ag_rp_44() (gAsm->directive_stkln()) +#define ag_rp_48() (gAsm->directive_module(ss[ss_idx--])) -#define ag_rp_45() (gAsm->directive_echo()) +#define ag_rp_49() (gAsm->directive_name(ss[ss_idx--])) -#define ag_rp_46() (gAsm->directive_echo(ss[ss_idx--])) +#define ag_rp_50() (gAsm->directive_stkln()) -#define ag_rp_47() (gAsm->directive_fill()) +#define ag_rp_51() (gAsm->directive_echo()) -#define ag_rp_48() (gAsm->directive_printf(ss[ss_idx--])) +#define ag_rp_52() (gAsm->directive_echo(ss[ss_idx--])) -#define ag_rp_49() (gAsm->directive_end("")) +#define ag_rp_53() (gAsm->directive_fill()) -#define ag_rp_50() (gAsm->directive_end(ss[ss_idx--])) +#define ag_rp_54() (gAsm->directive_printf(ss[ss_idx--])) -#define ag_rp_51() (gAsm->directive_if()) +#define ag_rp_55() (gAsm->directive_end("")) -#define ag_rp_52() (gAsm->directive_else()) +#define ag_rp_56() (gAsm->directive_end(ss[ss_idx--])) -#define ag_rp_53() (gAsm->directive_endif()) +#define ag_rp_57() (gAsm->directive_if()) -#define ag_rp_54() (gAsm->directive_endian(1)) +#define ag_rp_58() (gAsm->directive_else()) -#define ag_rp_55() (gAsm->directive_endian(0)) +#define ag_rp_59() (gAsm->directive_endif()) -#define ag_rp_56() (gAsm->directive_title(ss[ss_idx--])) +#define ag_rp_60() (gAsm->directive_endian(1)) -#define ag_rp_57() (gAsm->directive_title(ss[ss_idx--])) +#define ag_rp_61() (gAsm->directive_endian(0)) -#define ag_rp_58() (gAsm->directive_page(-1)) +#define ag_rp_62() (gAsm->directive_title(ss[ss_idx--])) -#define ag_rp_59() (gAsm->directive_sym()) +#define ag_rp_63() (gAsm->directive_title(ss[ss_idx--])) -#define ag_rp_60() (gAsm->directive_link(ss[ss_idx--])) +#define ag_rp_64() (gAsm->directive_page(-1)) -#define ag_rp_61() (gAsm->directive_maclib(ss[ss_idx--])) +#define ag_rp_65() (gAsm->directive_sym()) -#define ag_rp_62() (gAsm->directive_page(page)) +#define ag_rp_66() (gAsm->directive_link(ss[ss_idx--])) -#define ag_rp_63() (page = 60) +#define ag_rp_67() (gAsm->directive_maclib(ss[ss_idx--])) -#define ag_rp_64(n) (page = n) +#define ag_rp_68() (gAsm->directive_page(page)) -#define ag_rp_65() (expression_list_literal()) +#define ag_rp_69() (page = 60) -#define ag_rp_66() (expression_list_literal()) +#define ag_rp_70(n) (page = n) -#define ag_rp_67() (expression_list_equation()) +#define ag_rp_71() (expression_list_literal()) -#define ag_rp_68() (expression_list_equation()) +#define ag_rp_72() (expression_list_literal()) -#define ag_rp_69() (expression_list_literal()) +#define ag_rp_73() (expression_list_equation()) -#define ag_rp_70() (expression_list_literal()) +#define ag_rp_74() (expression_list_equation()) -#define ag_rp_71() (gNameList->Add(ss[ss_idx--])) +#define ag_rp_75() (expression_list_literal()) -#define ag_rp_72() (gNameList->Add(ss[ss_idx--])) +#define ag_rp_76() (expression_list_literal()) -static void ag_rp_73(void) { -/* Line 236, C:/Projects/VirtualT/src/a85parse.syn */ +#define ag_rp_77() (gNameList->Add(ss[ss_idx--])) + +#define ag_rp_78() (gNameList->Add(ss[ss_idx--])) + +static void ag_rp_79(void) { +/* Line 242, C:/Projects/VirtualT/src/a85parse.syn */ strcpy(ss[++ss_idx], "$"); ss_len = 1; } -static void ag_rp_74(void) { -/* Line 237, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_80(void) { +/* Line 243, C:/Projects/VirtualT/src/a85parse.syn */ strcpy(ss[++ss_idx], "&"); ss_len = 1; } -static void ag_rp_75(int c) { -/* Line 240, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_81(int c) { +/* Line 246, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; \ if (PCB.column == 2) ss_addr = gAsm->m_ActiveSeg->m_Address; } -static void ag_rp_76(int c) { -/* Line 242, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_82(int c) { +/* Line 248, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_77(int c) { -/* Line 243, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_83(int c) { +/* Line 249, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_78(int c) { -/* Line 246, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_84(int c) { +/* Line 252, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_79(int c) { -/* Line 247, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_85(int c) { +/* Line 253, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_80(int ch1, int ch2) { -/* Line 253, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_86(int ch1, int ch2) { +/* Line 259, C:/Projects/VirtualT/src/a85parse.syn */ ss_idx++; ss_len = 2; sprintf(ss[ss_idx], "%c%c", ch1, ch2); } -static void ag_rp_81(int c) { -/* Line 254, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_87(int c) { +/* Line 260, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_82(void) { -/* Line 261, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_88(void) { +/* Line 267, C:/Projects/VirtualT/src/a85parse.syn */ ss_idx++; ss_len = 0; } -static void ag_rp_83(int c) { -/* Line 262, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_89(int c) { +/* Line 268, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -#define ag_rp_84(n) (n) +#define ag_rp_90(n) (n) -#define ag_rp_85() ('\\') +#define ag_rp_91() ('\\') -#define ag_rp_86() ('\n') +#define ag_rp_92() ('\n') -#define ag_rp_87() ('\t') +#define ag_rp_93() ('\t') -#define ag_rp_88() ('\r') +#define ag_rp_94() ('\r') -#define ag_rp_89() ('\0') +#define ag_rp_95() ('\0') -#define ag_rp_90() ('"') +#define ag_rp_96() ('"') -#define ag_rp_91() (0x08) +#define ag_rp_97() (0x08) -#define ag_rp_92() (0x0C) +#define ag_rp_98() (0x0C) -#define ag_rp_93(n1, n2, n3) ((n1-'0') * 64 + (n2-'0') * 8 + n3-'0') +#define ag_rp_99(n1, n2, n3) ((n1-'0') * 64 + (n2-'0') * 8 + n3-'0') -#define ag_rp_94(n1, n2) (chtoh(n1) * 16 + chtoh(n2)) +#define ag_rp_100(n1, n2) (chtoh(n1) * 16 + chtoh(n2)) -#define ag_rp_95(n1) (chtoh(n1)) +#define ag_rp_101(n1) (chtoh(n1)) -static void ag_rp_96(void) { -/* Line 282, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_102(void) { +/* Line 288, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '>'; ss[ss_idx][ss_len] = 0; } -static void ag_rp_97(void) { -/* Line 285, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_103(void) { +/* Line 291, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = '<'; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_98(int c) { -/* Line 286, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_104(int c) { +/* Line 292, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_99(int c) { -/* Line 287, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_105(int c) { +/* Line 293, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '\\'; ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -#define ag_rp_100() (gAsm->label(ss[ss_idx--])) +#define ag_rp_106() (gAsm->label(ss[ss_idx--])) + +#define ag_rp_107() (gAsm->label(ss[ss_idx--])) -#define ag_rp_101() (gAsm->label(ss[ss_idx--])) +#define ag_rp_108() (gAsm->label(".bss")) -#define ag_rp_102() (PAGE) +#define ag_rp_109() (gAsm->label(".text")) -#define ag_rp_103() (INPAGE) +#define ag_rp_110() (gAsm->label(".data")) -#define ag_rp_104() (condition(-1)) +#define ag_rp_111() (PAGE) -#define ag_rp_105() (condition(COND_NOCMP)) +#define ag_rp_112() (INPAGE) -#define ag_rp_106() (condition(COND_EQ)) +#define ag_rp_113() (condition(-1)) -#define ag_rp_107() (condition(COND_NE)) +#define ag_rp_114() (condition(COND_NOCMP)) -#define ag_rp_108() (condition(COND_GE)) +#define ag_rp_115() (condition(COND_EQ)) -#define ag_rp_109() (condition(COND_LE)) +#define ag_rp_116() (condition(COND_NE)) -#define ag_rp_110() (condition(COND_GT)) +#define ag_rp_117() (condition(COND_GE)) -#define ag_rp_111() (condition(COND_LT)) +#define ag_rp_118() (condition(COND_LE)) -#define ag_rp_112() (gEq->Add(RPN_BITOR)) +#define ag_rp_119() (condition(COND_GT)) -#define ag_rp_113() (gEq->Add(RPN_BITOR)) +#define ag_rp_120() (condition(COND_LT)) -#define ag_rp_114() (gEq->Add(RPN_BITXOR)) +#define ag_rp_121() (gEq->Add(RPN_BITOR)) -#define ag_rp_115() (gEq->Add(RPN_BITXOR)) +#define ag_rp_122() (gEq->Add(RPN_BITOR)) -#define ag_rp_116() (gEq->Add(RPN_BITAND)) +#define ag_rp_123() (gEq->Add(RPN_BITXOR)) -#define ag_rp_117() (gEq->Add(RPN_BITAND)) +#define ag_rp_124() (gEq->Add(RPN_BITXOR)) -#define ag_rp_118() (gEq->Add(RPN_LEFTSHIFT)) +#define ag_rp_125() (gEq->Add(RPN_BITAND)) -#define ag_rp_119() (gEq->Add(RPN_LEFTSHIFT)) +#define ag_rp_126() (gEq->Add(RPN_BITAND)) -#define ag_rp_120() (gEq->Add(RPN_RIGHTSHIFT)) +#define ag_rp_127() (gEq->Add(RPN_LEFTSHIFT)) -#define ag_rp_121() (gEq->Add(RPN_RIGHTSHIFT)) +#define ag_rp_128() (gEq->Add(RPN_LEFTSHIFT)) -#define ag_rp_122() (gEq->Add(RPN_ADD)) +#define ag_rp_129() (gEq->Add(RPN_RIGHTSHIFT)) -#define ag_rp_123() (gEq->Add(RPN_SUBTRACT)) +#define ag_rp_130() (gEq->Add(RPN_RIGHTSHIFT)) -#define ag_rp_124() (gEq->Add(RPN_MULTIPLY)) +#define ag_rp_131() (gEq->Add(RPN_ADD)) -#define ag_rp_125() (gEq->Add(RPN_DIVIDE)) +#define ag_rp_132() (gEq->Add(RPN_SUBTRACT)) -#define ag_rp_126() (gEq->Add(RPN_MODULUS)) +#define ag_rp_133() (gEq->Add(RPN_MULTIPLY)) -#define ag_rp_127() (gEq->Add(RPN_MODULUS)) +#define ag_rp_134() (gEq->Add(RPN_DIVIDE)) -#define ag_rp_128() (gEq->Add(RPN_EXPONENT)) +#define ag_rp_135() (gEq->Add(RPN_MODULUS)) -#define ag_rp_129() (gEq->Add(RPN_NOT)) +#define ag_rp_136() (gEq->Add(RPN_MODULUS)) -#define ag_rp_130() (gEq->Add(RPN_NOT)) +#define ag_rp_137() (gEq->Add(RPN_EXPONENT)) -#define ag_rp_131() (gEq->Add(RPN_BITNOT)) +#define ag_rp_138() (gEq->Add(RPN_NOT)) -#define ag_rp_132() (gEq->Add(RPN_NEGATE)) +#define ag_rp_139() (gEq->Add(RPN_NOT)) -#define ag_rp_133(n) (gEq->Add((double) n)) +#define ag_rp_140() (gEq->Add(RPN_BITNOT)) -static void ag_rp_134(void) { -/* Line 375, C:/Projects/VirtualT/src/a85parse.syn */ +#define ag_rp_141() (gEq->Add(RPN_NEGATE)) + +#define ag_rp_142(n) (gEq->Add((double) n)) + +static void ag_rp_143(void) { +/* Line 384, C:/Projects/VirtualT/src/a85parse.syn */ delete gMacro; gMacro = gMacroStack[ms_idx-1]; \ gMacroStack[ms_idx--] = 0; if (gMacro->m_ParamList == 0) \ {\ @@ -835,369 +853,427 @@ static void ag_rp_134(void) { } } -#define ag_rp_135() (gEq->Add(RPN_FLOOR)) +#define ag_rp_144() (gEq->Add(RPN_FLOOR)) + +#define ag_rp_145() (gEq->Add(RPN_CEIL)) -#define ag_rp_136() (gEq->Add(RPN_CEIL)) +#define ag_rp_146() (gEq->Add(RPN_LN)) -#define ag_rp_137() (gEq->Add(RPN_LN)) +#define ag_rp_147() (gEq->Add(RPN_LOG)) -#define ag_rp_138() (gEq->Add(RPN_LOG)) +#define ag_rp_148() (gEq->Add(RPN_SQRT)) -#define ag_rp_139() (gEq->Add(RPN_SQRT)) +#define ag_rp_149() (gEq->Add(RPN_IP)) -#define ag_rp_140() (gEq->Add(RPN_IP)) +#define ag_rp_150() (gEq->Add(RPN_FP)) -#define ag_rp_141() (gEq->Add(RPN_FP)) +#define ag_rp_151() (gEq->Add(RPN_HIGH)) -#define ag_rp_142() (gEq->Add(RPN_HIGH)) +#define ag_rp_152() (gEq->Add(RPN_LOW)) -#define ag_rp_143() (gEq->Add(RPN_LOW)) +#define ag_rp_153() (gEq->Add(RPN_PAGE)) -#define ag_rp_144() (gEq->Add(RPN_DEFINED, ss[ss_idx--])) +#define ag_rp_154() (gEq->Add(RPN_DEFINED, ss[ss_idx--])) -#define ag_rp_145(n) (n) +#define ag_rp_155(n) (n) -#define ag_rp_146(r) (r) +#define ag_rp_156(r) (r) -#define ag_rp_147(n) (n) +#define ag_rp_157(n) (n) -#define ag_rp_148() (conv_to_dec()) +#define ag_rp_158() (conv_to_dec()) -#define ag_rp_149() (conv_to_hex()) +#define ag_rp_159() (conv_to_hex()) -#define ag_rp_150() (conv_to_bin()) +#define ag_rp_160() (conv_to_bin()) -#define ag_rp_151() (conv_to_oct()) +#define ag_rp_161() (conv_to_oct()) -#define ag_rp_152() (conv_to_hex()) +#define ag_rp_162() (conv_to_hex()) -#define ag_rp_153() (conv_to_hex()) +#define ag_rp_163() (conv_to_hex()) -#define ag_rp_154() (conv_to_bin()) +#define ag_rp_164() (conv_to_bin()) -#define ag_rp_155() (conv_to_oct()) +#define ag_rp_165() (conv_to_oct()) -#define ag_rp_156() (conv_to_dec()) +#define ag_rp_166() (conv_to_dec()) -static void ag_rp_157(int n) { -/* Line 421, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_167(int n) { +/* Line 431, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_158(int n) { -/* Line 422, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_168(int n) { +/* Line 432, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 2; integer[0] = '-', integer[1] = n; integer[2] = 0; } -static void ag_rp_159(int n) { -/* Line 423, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_169(int n) { +/* Line 433, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_160(int n) { -/* Line 424, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_170(int n) { +/* Line 434, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_161(int n) { -/* Line 429, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_171(int n) { +/* Line 439, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_162(int n) { -/* Line 430, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_172(int n) { +/* Line 440, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_163(int n) { -/* Line 431, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_173(int n) { +/* Line 441, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_164(int n) { -/* Line 434, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_174(int n) { +/* Line 444, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_165(int n) { -/* Line 435, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_175(int n) { +/* Line 445, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_166(int n) { -/* Line 438, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_176(int n) { +/* Line 448, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_167(int n) { -/* Line 439, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_177(int n) { +/* Line 449, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_168(int n) { -/* Line 442, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_178(int n) { +/* Line 452, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_169(int n) { -/* Line 443, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_179(int n) { +/* Line 453, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -#define ag_rp_170(n) (n) +#define ag_rp_180(n) (n) -#define ag_rp_171(n1, n2) ((n1 << 8) | n2) +#define ag_rp_181(n1, n2) ((n1 << 8) | n2) -#define ag_rp_172() ('\\') +#define ag_rp_182() ('\\') -#define ag_rp_173(n) (n) +#define ag_rp_183(n) (n) -#define ag_rp_174() ('\\') +#define ag_rp_184() ('\\') -#define ag_rp_175() ('\n') +#define ag_rp_185() ('\n') -#define ag_rp_176() ('\t') +#define ag_rp_186() ('\t') -#define ag_rp_177() ('\r') +#define ag_rp_187() ('\r') -#define ag_rp_178() ('\0') +#define ag_rp_188() ('\0') -#define ag_rp_179() ('\'') +#define ag_rp_189() ('\'') -#define ag_rp_180() ('\'') +#define ag_rp_190() ('\'') -static double ag_rp_181(void) { -/* Line 464, C:/Projects/VirtualT/src/a85parse.syn */ +static double ag_rp_191(void) { +/* Line 474, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor = 1.0; return (double) conv_to_dec(); } -static double ag_rp_182(int d) { -/* Line 465, C:/Projects/VirtualT/src/a85parse.syn */ +static double ag_rp_192(int d) { +/* Line 475, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor = 10.0; return ((double) (d - '0') / gDivisor); } -static double ag_rp_183(double r, int d) { -/* Line 466, C:/Projects/VirtualT/src/a85parse.syn */ +static double ag_rp_193(double r, int d) { +/* Line 476, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor *= 10.0; return (r + (double) (d - '0') / gDivisor); } -#define ag_rp_184() (reg[reg_cnt++] = '0') +#define ag_rp_194() (reg[reg_cnt++] = '0') + +#define ag_rp_195() (reg[reg_cnt++] = '1') + +#define ag_rp_196() (reg[reg_cnt++] = '2') + +#define ag_rp_197() (reg[reg_cnt++] = '3') + +#define ag_rp_198() (reg[reg_cnt++] = '4') + +#define ag_rp_199() (reg[reg_cnt++] = '5') + +#define ag_rp_200() (reg[reg_cnt++] = '6') + +#define ag_rp_201() (reg[reg_cnt++] = '7') + +#define ag_rp_202() (reg[reg_cnt++] = '0') + +#define ag_rp_203() (reg[reg_cnt++] = '1') + +#define ag_rp_204() (reg[reg_cnt++] = '2') + +#define ag_rp_205() (reg[reg_cnt++] = '3') + +#define ag_rp_206() (reg[reg_cnt++] = '0') + +#define ag_rp_207() (reg[reg_cnt++] = '1') + +#define ag_rp_208() (reg[reg_cnt++] = '2') + +#define ag_rp_209() (reg[reg_cnt++] = '3') -#define ag_rp_185() (reg[reg_cnt++] = '1') +#define ag_rp_210() (reg[reg_cnt++] = '3') -#define ag_rp_186() (reg[reg_cnt++] = '2') +#define ag_rp_211() (reg[reg_cnt++] = '0') -#define ag_rp_187() (reg[reg_cnt++] = '3') +#define ag_rp_212() (reg[reg_cnt++] = '1') -#define ag_rp_188() (reg[reg_cnt++] = '4') +#define ag_rp_213() (reg[reg_cnt++] = '0') -#define ag_rp_189() (reg[reg_cnt++] = '5') +#define ag_rp_214() (reg[reg_cnt++] = '1') -#define ag_rp_190() (reg[reg_cnt++] = '6') +#define ag_rp_215() (reg[reg_cnt++] = '2') -#define ag_rp_191() (reg[reg_cnt++] = '7') +#define ag_rp_216() (reg[reg_cnt++] = '3') -#define ag_rp_192() (reg[reg_cnt++] = '0') +#define ag_rp_217() (reg[reg_cnt++] = '4') -#define ag_rp_193() (reg[reg_cnt++] = '1') +#define ag_rp_218() (reg[reg_cnt++] = '5') -#define ag_rp_194() (reg[reg_cnt++] = '2') +#define ag_rp_219() (gAsm->opcode_arg_0 (OPCODE_ASHR)) -#define ag_rp_195() (reg[reg_cnt++] = '3') +#define ag_rp_220() (gAsm->opcode_arg_0 (OPCODE_CMA)) -#define ag_rp_196() (reg[reg_cnt++] = '0') +#define ag_rp_221() (gAsm->opcode_arg_0 (OPCODE_CMC)) -#define ag_rp_197() (reg[reg_cnt++] = '1') +#define ag_rp_222() (gAsm->opcode_arg_0 (OPCODE_DAA)) -#define ag_rp_198() (reg[reg_cnt++] = '2') +#define ag_rp_223() (gAsm->opcode_arg_0 (OPCODE_DI)) -#define ag_rp_199() (reg[reg_cnt++] = '3') +#define ag_rp_224() (gAsm->opcode_arg_0 (OPCODE_DSUB)) -#define ag_rp_200() (reg[reg_cnt++] = '3') +#define ag_rp_225() (gAsm->opcode_arg_0 (OPCODE_EI)) -#define ag_rp_201() (reg[reg_cnt++] = '0') +#define ag_rp_226() (gAsm->opcode_arg_0 (OPCODE_HLT)) -#define ag_rp_202() (reg[reg_cnt++] = '1') +#define ag_rp_227() (gAsm->opcode_arg_0 (OPCODE_LHLX)) -#define ag_rp_203() (gAsm->opcode_arg_0 (OPCODE_ASHR)) +#define ag_rp_228() (gAsm->opcode_arg_0 (OPCODE_NOP)) -#define ag_rp_204() (gAsm->opcode_arg_0 (OPCODE_CMA)) +#define ag_rp_229() (gAsm->opcode_arg_0 (OPCODE_PCHL)) -#define ag_rp_205() (gAsm->opcode_arg_0 (OPCODE_CMC)) +#define ag_rp_230() (gAsm->opcode_arg_0 (OPCODE_RAL)) -#define ag_rp_206() (gAsm->opcode_arg_0 (OPCODE_DAA)) +#define ag_rp_231() (gAsm->opcode_arg_0 (OPCODE_RAR)) -#define ag_rp_207() (gAsm->opcode_arg_0 (OPCODE_DI)) +#define ag_rp_232() (gAsm->opcode_arg_0 (OPCODE_RC)) -#define ag_rp_208() (gAsm->opcode_arg_0 (OPCODE_DSUB)) +#define ag_rp_233() (gAsm->opcode_arg_0 (OPCODE_RET)) -#define ag_rp_209() (gAsm->opcode_arg_0 (OPCODE_EI)) +#define ag_rp_234() (gAsm->opcode_arg_0 (OPCODE_RIM)) -#define ag_rp_210() (gAsm->opcode_arg_0 (OPCODE_HLT)) +#define ag_rp_235() (gAsm->opcode_arg_0 (OPCODE_RLC)) -#define ag_rp_211() (gAsm->opcode_arg_0 (OPCODE_LHLX)) +#define ag_rp_236() (gAsm->opcode_arg_0 (OPCODE_RLDE)) -#define ag_rp_212() (gAsm->opcode_arg_0 (OPCODE_NOP)) +#define ag_rp_237() (gAsm->opcode_arg_0 (OPCODE_RM)) -#define ag_rp_213() (gAsm->opcode_arg_0 (OPCODE_PCHL)) +#define ag_rp_238() (gAsm->opcode_arg_0 (OPCODE_RNC)) -#define ag_rp_214() (gAsm->opcode_arg_0 (OPCODE_RAL)) +#define ag_rp_239() (gAsm->opcode_arg_0 (OPCODE_RNZ)) -#define ag_rp_215() (gAsm->opcode_arg_0 (OPCODE_RAR)) +#define ag_rp_240() (gAsm->opcode_arg_0 (OPCODE_RP)) -#define ag_rp_216() (gAsm->opcode_arg_0 (OPCODE_RC)) +#define ag_rp_241() (gAsm->opcode_arg_0 (OPCODE_RPE)) -#define ag_rp_217() (gAsm->opcode_arg_0 (OPCODE_RET)) +#define ag_rp_242() (gAsm->opcode_arg_0 (OPCODE_RPO)) -#define ag_rp_218() (gAsm->opcode_arg_0 (OPCODE_RIM)) +#define ag_rp_243() (gAsm->opcode_arg_0 (OPCODE_RRC)) -#define ag_rp_219() (gAsm->opcode_arg_0 (OPCODE_RLC)) +#define ag_rp_244() (gAsm->opcode_arg_0 (OPCODE_RSTV)) -#define ag_rp_220() (gAsm->opcode_arg_0 (OPCODE_RLDE)) +#define ag_rp_245() (gAsm->opcode_arg_0 (OPCODE_RZ)) -#define ag_rp_221() (gAsm->opcode_arg_0 (OPCODE_RM)) +#define ag_rp_246() (gAsm->opcode_arg_0 (OPCODE_SHLX)) -#define ag_rp_222() (gAsm->opcode_arg_0 (OPCODE_RNC)) +#define ag_rp_247() (gAsm->opcode_arg_0 (OPCODE_SIM)) -#define ag_rp_223() (gAsm->opcode_arg_0 (OPCODE_RNZ)) +#define ag_rp_248() (gAsm->opcode_arg_0 (OPCODE_SPHL)) -#define ag_rp_224() (gAsm->opcode_arg_0 (OPCODE_RP)) +#define ag_rp_249() (gAsm->opcode_arg_0 (OPCODE_STC)) -#define ag_rp_225() (gAsm->opcode_arg_0 (OPCODE_RPE)) +#define ag_rp_250() (gAsm->opcode_arg_0 (OPCODE_XCHG)) -#define ag_rp_226() (gAsm->opcode_arg_0 (OPCODE_RPO)) +#define ag_rp_251() (gAsm->opcode_arg_0 (OPCODE_XTHL)) -#define ag_rp_227() (gAsm->opcode_arg_0 (OPCODE_RRC)) +#define ag_rp_252() (gAsm->opcode_arg_0 (OPCODE_LRET)) -#define ag_rp_228() (gAsm->opcode_arg_0 (OPCODE_RSTV)) +#define ag_rp_253() (gAsm->opcode_arg_1reg (OPCODE_STAX)) -#define ag_rp_229() (gAsm->opcode_arg_0 (OPCODE_RZ)) +#define ag_rp_254() (gAsm->opcode_arg_1reg (OPCODE_LDAX)) -#define ag_rp_230() (gAsm->opcode_arg_0 (OPCODE_SHLX)) +#define ag_rp_255() (gAsm->opcode_arg_1reg (OPCODE_POP)) -#define ag_rp_231() (gAsm->opcode_arg_0 (OPCODE_SIM)) +#define ag_rp_256() (gAsm->opcode_arg_1reg (OPCODE_PUSH)) -#define ag_rp_232() (gAsm->opcode_arg_0 (OPCODE_SPHL)) +#define ag_rp_257() (gAsm->opcode_arg_1reg_2byte (OPCODE_LPOP)) -#define ag_rp_233() (gAsm->opcode_arg_0 (OPCODE_STC)) +#define ag_rp_258() (gAsm->opcode_arg_1reg_2byte (OPCODE_LPUSH)) -#define ag_rp_234() (gAsm->opcode_arg_0 (OPCODE_XCHG)) +#define ag_rp_259() (gAsm->opcode_arg_1reg (OPCODE_ADC)) -#define ag_rp_235() (gAsm->opcode_arg_0 (OPCODE_XTHL)) +#define ag_rp_260() (gAsm->opcode_arg_1reg (OPCODE_ADD)) -#define ag_rp_236() (gAsm->opcode_arg_1reg (OPCODE_STAX)) +#define ag_rp_261() (gAsm->opcode_arg_1reg (OPCODE_ANA)) -#define ag_rp_237() (gAsm->opcode_arg_1reg (OPCODE_LDAX)) +#define ag_rp_262() (gAsm->opcode_arg_1reg (OPCODE_CMP)) -#define ag_rp_238() (gAsm->opcode_arg_1reg (OPCODE_POP)) +#define ag_rp_263() (gAsm->opcode_arg_1reg (OPCODE_DCR)) -#define ag_rp_239() (gAsm->opcode_arg_1reg (OPCODE_PUSH)) +#define ag_rp_264() (gAsm->opcode_arg_1reg (OPCODE_INR)) -#define ag_rp_240() (gAsm->opcode_arg_1reg (OPCODE_ADC)) +#define ag_rp_265() (gAsm->opcode_arg_2reg (OPCODE_MOV)) -#define ag_rp_241() (gAsm->opcode_arg_1reg (OPCODE_ADD)) +#define ag_rp_266() (gAsm->opcode_arg_1reg (OPCODE_ORA)) -#define ag_rp_242() (gAsm->opcode_arg_1reg (OPCODE_ANA)) +#define ag_rp_267() (gAsm->opcode_arg_1reg (OPCODE_SBB)) -#define ag_rp_243() (gAsm->opcode_arg_1reg (OPCODE_CMP)) +#define ag_rp_268() (gAsm->opcode_arg_1reg (OPCODE_SUB)) -#define ag_rp_244() (gAsm->opcode_arg_1reg (OPCODE_DCR)) +#define ag_rp_269() (gAsm->opcode_arg_1reg (OPCODE_XRA)) -#define ag_rp_245() (gAsm->opcode_arg_1reg (OPCODE_INR)) +#define ag_rp_270() (gAsm->opcode_arg_1reg_2byte (OPCODE_SPG)) -#define ag_rp_246() (gAsm->opcode_arg_2reg (OPCODE_MOV)) +#define ag_rp_271() (gAsm->opcode_arg_1reg_2byte (OPCODE_RPG)) -#define ag_rp_247() (gAsm->opcode_arg_1reg (OPCODE_ORA)) +#define ag_rp_272() (gAsm->opcode_arg_1reg (OPCODE_DAD)) -#define ag_rp_248() (gAsm->opcode_arg_1reg (OPCODE_SBB)) +#define ag_rp_273() (gAsm->opcode_arg_1reg (OPCODE_DCX)) -#define ag_rp_249() (gAsm->opcode_arg_1reg (OPCODE_SUB)) +#define ag_rp_274() (gAsm->opcode_arg_1reg (OPCODE_INX)) -#define ag_rp_250() (gAsm->opcode_arg_1reg (OPCODE_XRA)) +#define ag_rp_275() (gAsm->opcode_arg_1reg_equ16(OPCODE_LXI)) -#define ag_rp_251() (gAsm->opcode_arg_1reg (OPCODE_DAD)) +#define ag_rp_276() (gAsm->opcode_arg_1reg_equ8(OPCODE_MVI)) -#define ag_rp_252() (gAsm->opcode_arg_1reg (OPCODE_DCX)) +#define ag_rp_277() (gAsm->opcode_arg_1reg_equ16(OPCODE_SPI)) -#define ag_rp_253() (gAsm->opcode_arg_1reg (OPCODE_INX)) +#define ag_rp_278(c) (gAsm->opcode_arg_imm (OPCODE_RST, c)) -#define ag_rp_254() (gAsm->opcode_arg_1reg_equ16(OPCODE_LXI)) +#define ag_rp_279() (gAsm->opcode_arg_equ8 (OPCODE_ACI)) -#define ag_rp_255() (gAsm->opcode_arg_1reg_equ8(OPCODE_MVI)) +#define ag_rp_280() (gAsm->opcode_arg_equ8 (OPCODE_ADI)) -#define ag_rp_256(c) (gAsm->opcode_arg_imm (OPCODE_RST, c)) +#define ag_rp_281() (gAsm->opcode_arg_equ8 (OPCODE_ANI)) -#define ag_rp_257() (gAsm->opcode_arg_equ8 (OPCODE_ACI)) +#define ag_rp_282() (gAsm->opcode_arg_equ16 (OPCODE_CALL)) -#define ag_rp_258() (gAsm->opcode_arg_equ8 (OPCODE_ADI)) +#define ag_rp_283() (gAsm->opcode_arg_equ16 (OPCODE_CC)) -#define ag_rp_259() (gAsm->opcode_arg_equ8 (OPCODE_ANI)) +#define ag_rp_284() (gAsm->opcode_arg_equ16 (OPCODE_CM)) -#define ag_rp_260() (gAsm->opcode_arg_equ16 (OPCODE_CALL)) +#define ag_rp_285() (gAsm->opcode_arg_equ16 (OPCODE_CNC)) -#define ag_rp_261() (gAsm->opcode_arg_equ16 (OPCODE_CC)) +#define ag_rp_286() (gAsm->opcode_arg_equ16 (OPCODE_CNZ)) -#define ag_rp_262() (gAsm->opcode_arg_equ16 (OPCODE_CM)) +#define ag_rp_287() (gAsm->opcode_arg_equ16 (OPCODE_CP)) -#define ag_rp_263() (gAsm->opcode_arg_equ16 (OPCODE_CNC)) +#define ag_rp_288() (gAsm->opcode_arg_equ16 (OPCODE_CPE)) -#define ag_rp_264() (gAsm->opcode_arg_equ16 (OPCODE_CNZ)) +#define ag_rp_289() (gAsm->opcode_arg_equ8 (OPCODE_CPI)) -#define ag_rp_265() (gAsm->opcode_arg_equ16 (OPCODE_CP)) +#define ag_rp_290() (gAsm->opcode_arg_equ16 (OPCODE_CPO)) -#define ag_rp_266() (gAsm->opcode_arg_equ16 (OPCODE_CPE)) +#define ag_rp_291() (gAsm->opcode_arg_equ16 (OPCODE_CZ)) -#define ag_rp_267() (gAsm->opcode_arg_equ8 (OPCODE_CPI)) +#define ag_rp_292() (gAsm->opcode_arg_equ8 (OPCODE_IN)) -#define ag_rp_268() (gAsm->opcode_arg_equ16 (OPCODE_CPO)) +#define ag_rp_293() (gAsm->opcode_arg_equ16 (OPCODE_JC)) -#define ag_rp_269() (gAsm->opcode_arg_equ16 (OPCODE_CZ)) +#define ag_rp_294() (gAsm->opcode_arg_equ16 (OPCODE_JD)) -#define ag_rp_270() (gAsm->opcode_arg_equ8 (OPCODE_IN)) +#define ag_rp_295() (gAsm->opcode_arg_equ16 (OPCODE_JM)) -#define ag_rp_271() (gAsm->opcode_arg_equ16 (OPCODE_JC)) +#define ag_rp_296() (gAsm->opcode_arg_equ16 (OPCODE_JMP)) -#define ag_rp_272() (gAsm->opcode_arg_equ16 (OPCODE_JD)) +#define ag_rp_297() (gAsm->opcode_arg_equ16 (OPCODE_JNC)) -#define ag_rp_273() (gAsm->opcode_arg_equ16 (OPCODE_JM)) +#define ag_rp_298() (gAsm->opcode_arg_equ16 (OPCODE_JND)) -#define ag_rp_274() (gAsm->opcode_arg_equ16 (OPCODE_JMP)) +#define ag_rp_299() (gAsm->opcode_arg_equ16 (OPCODE_JNZ)) -#define ag_rp_275() (gAsm->opcode_arg_equ16 (OPCODE_JNC)) +#define ag_rp_300() (gAsm->opcode_arg_equ16 (OPCODE_JP)) -#define ag_rp_276() (gAsm->opcode_arg_equ16 (OPCODE_JND)) +#define ag_rp_301() (gAsm->opcode_arg_equ16 (OPCODE_JPE)) -#define ag_rp_277() (gAsm->opcode_arg_equ16 (OPCODE_JNZ)) +#define ag_rp_302() (gAsm->opcode_arg_equ16 (OPCODE_JPO)) -#define ag_rp_278() (gAsm->opcode_arg_equ16 (OPCODE_JP)) +#define ag_rp_303() (gAsm->opcode_arg_equ16 (OPCODE_JZ)) -#define ag_rp_279() (gAsm->opcode_arg_equ16 (OPCODE_JPE)) +#define ag_rp_304() (gAsm->opcode_arg_equ16 (OPCODE_LDA)) -#define ag_rp_280() (gAsm->opcode_arg_equ16 (OPCODE_JPO)) +#define ag_rp_305() (gAsm->opcode_arg_equ8 (OPCODE_LDEH)) -#define ag_rp_281() (gAsm->opcode_arg_equ16 (OPCODE_JZ)) +#define ag_rp_306() (gAsm->opcode_arg_equ8 (OPCODE_LDES)) -#define ag_rp_282() (gAsm->opcode_arg_equ16 (OPCODE_LDA)) +#define ag_rp_307() (gAsm->opcode_arg_equ16 (OPCODE_LHLD)) -#define ag_rp_283() (gAsm->opcode_arg_equ8 (OPCODE_LDEH)) +#define ag_rp_308() (gAsm->opcode_arg_equ8 (OPCODE_ORI)) -#define ag_rp_284() (gAsm->opcode_arg_equ8 (OPCODE_LDES)) +#define ag_rp_309() (gAsm->opcode_arg_equ8 (OPCODE_OUT)) -#define ag_rp_285() (gAsm->opcode_arg_equ16 (OPCODE_LHLD)) +#define ag_rp_310() (gAsm->opcode_arg_equ8 (OPCODE_SBI)) -#define ag_rp_286() (gAsm->opcode_arg_equ8 (OPCODE_ORI)) +#define ag_rp_311() (gAsm->opcode_arg_equ16 (OPCODE_SHLD)) -#define ag_rp_287() (gAsm->opcode_arg_equ8 (OPCODE_OUT)) +#define ag_rp_312() (gAsm->opcode_arg_equ16 (OPCODE_STA)) -#define ag_rp_288() (gAsm->opcode_arg_equ8 (OPCODE_SBI)) +#define ag_rp_313() (gAsm->opcode_arg_equ8 (OPCODE_SUI)) -#define ag_rp_289() (gAsm->opcode_arg_equ16 (OPCODE_SHLD)) +#define ag_rp_314() (gAsm->opcode_arg_equ8 (OPCODE_XRI)) -#define ag_rp_290() (gAsm->opcode_arg_equ16 (OPCODE_STA)) +#define ag_rp_315() (gAsm->opcode_arg_equ8 (OPCODE_BR)) -#define ag_rp_291() (gAsm->opcode_arg_equ8 (OPCODE_SUI)) +#define ag_rp_316() (gAsm->opcode_arg_equ16 (OPCODE_BRA)) -#define ag_rp_292() (gAsm->opcode_arg_equ8 (OPCODE_XRI)) +#define ag_rp_317() (gAsm->opcode_arg_equ16 (OPCODE_BZ)) + +#define ag_rp_318() (gAsm->opcode_arg_equ16 (OPCODE_BNZ)) + +#define ag_rp_319() (gAsm->opcode_arg_equ16 (OPCODE_BC)) + +#define ag_rp_320() (gAsm->opcode_arg_equ16 (OPCODE_BNC)) + +#define ag_rp_321() (gAsm->opcode_arg_equ16 (OPCODE_BM)) + +#define ag_rp_322() (gAsm->opcode_arg_equ16 (OPCODE_BP)) + +#define ag_rp_323() (gAsm->opcode_arg_equ16 (OPCODE_BPE)) + +#define ag_rp_324() (gAsm->opcode_arg_equ16 (OPCODE_RCALL)) + +#define ag_rp_325() (gAsm->opcode_arg_equ8 (OPCODE_SBZ)) + +#define ag_rp_326() (gAsm->opcode_arg_equ8 (OPCODE_SBNZ)) + +#define ag_rp_327() (gAsm->opcode_arg_equ8 (OPCODE_SBC)) + +#define ag_rp_328() (gAsm->opcode_arg_equ8 (OPCODE_SBNC)) + +#define ag_rp_329() (gAsm->opcode_arg_equ24 (OPCODE_LCALL)) + +#define ag_rp_330() (gAsm->opcode_arg_equ24 (OPCODE_LJMP)) #define READ_COUNTS @@ -1236,28 +1312,30 @@ static a85parse_vs_type const ag_null_value NULL_VALUE_INITIALIZER; static const unsigned short ag_rpx[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 3, 4, 5, 6, - 7, 8, 0, 0, 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 0, 31, 0, 32, 33, 0, 0, 0, - 34, 35, 0, 0, 36, 0, 0, 0, 37, 0, 0, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 0, 0, 73, 74, 75, 76, 77, - 78, 79, 0, 80, 81, 0, 82, 83, 0, 84, 85, 86, 87, 88, 89, 90, 91, 92, - 93, 0, 0, 94, 95, 96, 97, 98, 99, 0,100,101,102,103,104,105, 0, 0, - 0,106, 0, 0,107, 0, 0,108, 0, 0,109, 0, 0,110, 0, 0,111, 0, - 0,112,113, 0,114,115, 0,116,117, 0,118,119,120,121, 0,122,123, 0, - 124,125,126,127,128, 0,129,130,131,132,133,134, 0, 0,135,136,137,138, - 139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154, 0, 0, - 155,156,157,158,159,160, 0, 0,161,162,163,164,165,166,167,168,169,170, - 171,172,173,174,175,176,177,178,179,180, 0,181,182,183,184,185,186,187, - 188,189, 0, 0,190,191, 0, 0,192, 0, 0,193, 0, 0,194,195,196,197, - 198,199,200,201,202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,203,204,205,206,207, 0, 0,208,209,210, 0, 0, 0,211,212,213, - 214,215,216,217,218,219, 0, 0,220,221,222,223,224,225,226,227,228,229, - 0, 0, 0,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244, - 245,246,247,248,249,250,251,252,253, 0,254, 0,255,256,257,258,259,260, - 261,262,263,264,265,266,267,268,269,270,271, 0, 0, 0, 0, 0,272,273, - 274,275, 0, 0, 0, 0, 0,276,277,278,279,280,281,282, 0, 0, 0,283, - 0, 0,284,285,286,287,288,289,290,291,292 + 7, 8, 0, 0, 9, 10, 11, 12, 13, 14, 15, 0, 0, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 0, 34, 0, 35, 36, + 37, 38, 39, 0, 0, 0, 40, 41, 0, 0, 42, 0, 0, 0, 43, 0, 0, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 0, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 0, + 0, 79, 80, 81, 82, 83, 84, 85, 0, 86, 87, 0, 88, 89, 0, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 0, 0,100,101,102,103,104,105, 0,106,107, + 108,109,110,111,112,113,114, 0, 0, 0,115, 0, 0,116, 0, 0,117, 0, + 0,118, 0, 0,119, 0, 0,120, 0, 0,121,122, 0,123,124, 0,125,126, + 0,127,128,129,130, 0,131,132, 0,133,134,135,136,137, 0,138,139,140, + 141,142,143, 0, 0,144,145,146,147,148,149,150,151,152,153,154,155,156, + 157,158,159,160,161,162,163,164, 0, 0,165,166,167,168,169,170, 0, 0, + 171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188, + 189,190, 0,191,192,193,194,195,196,197,198,199, 0, 0,200,201, 0, 0, + 202, 0, 0,203, 0, 0,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,219,220,221,222,223, 0, 0,224,225,226, 0, 0, 0,227,228,229,230, + 231,232,233,234,235, 0, 0,236,237,238,239,240,241,242,243,244,245, 0, + 0, 0,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261, + 262,263,264,265,266,267,268,269,270,271,272,273,274, 0,275, 0,276, 0, + 277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293, 0, + 0, 0, 0, 0,294,295,296,297, 0, 0, 0, 0, 0,298,299,300,301,302, + 303,304, 0, 0, 0,305, 0, 0, 0,306,307,308,309,310,311,312,313,314, + 315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330 }; static const unsigned char ag_key_itt[] = { @@ -1276,576 +1354,645 @@ static const unsigned char ag_key_itt[] = { }; static const unsigned short ag_key_pt[] = { - 1,399, 1,400, 1,401, 1,402, 1,408, 1,407, 1,409, 1,411, - 1,412, 1,413, 1,414, 1,415, 1,416, 1,417, 1,418, 1,419, - 1,424, 1,425, 1,426, 1,429, 1,430, 1,431, 1,432, 1,433, - 1,434, 1,435, 1,436, 1,437, 1,438, 1,439, 1,440, 1,441, - 1,442, 1,443, 1,444, 1,446, 1,447, 1,448, 1,449, 1,451, - 1,452, 1,453, 1,454, 1,455, 1,456, 1,131, 1,459, 1,460, - 1,463, 1,465, 1,467, 1,469, 1,471, 1,474, 1,476, 1,478, - 1,480, 1,482, 1,488, 1,491, 1,493, 1,494, 1,495, 1,496, - 1,497, 1,498, 1,499, 1,500, 1,501, 1,503, 1,216, 1,217, - 1,229, 1,230, 1,231, 1,232, 1,233, 1,234, 1,235, 1,506, - 1,239, 1,241, 1,243, 1,245, 1,505, 1,507, 1,508, 1,509, - 1,510, 1,511, 1,512, 1,513, 1,514, 1,515, 1,516, 1,517, - 1,518, 1,519, 1,520, 1,521, 1,522, 1,523, 1,524, 1,525, - 1,526, 1,527, 1,528, 1,529, 1,530, 1,531, 1,532, 1,533, - 1,534, 1,535, 1,536, 1,537, 1,538, 1,539, 1,540, 1,541, - 1,542, 1,543, 1,544, 1,545, 1,546, 1,547, 1,548, 1,549, - 1,550, 1,551, 1,552, 1,553, 1,555, 1,556, 1,557, 1,558, - 1,559, 1,560, 1,561, 1,562, 1,563, 1,564, 1,565, 1,567, + 1,432, 1,433, 1,434, 1,435, 1,441, 1,440, 1,442, 1,444, + 1,445, 1,446, 1,447, 1,448, 1,449, 1,450, 1,451, 1,452, + 1,453, 1,454, 1,455, 1,460, 1,461, 1,462, 1,465, 1,466, + 1,467, 1,468, 1,469, 1,470, 1,471, 1,472, 1,473, 1,474, + 1,475, 1,476, 1,477, 1,478, 1,479, 1,480, 1,482, 1,483, + 1,484, 1,485, 1,487, 1,488, 1,489, 1,490, 1,491, 1,492, + 1,134, 1,495, 1,496, 1,499, 1,501, 1,503, 1,505, 1,507, + 1,510, 1,512, 1,514, 1,516, 1,518, 1,524, 1,527, 1,529, + 1,530, 1,531, 1,532, 1,533, 1,534, 1,535, 1,536, 1,537, + 1,539, 1,222, 1,223, 1,235, 1,236, 1,237, 1,238, 1,239, + 1,240, 1,241, 1,542, 1,670, 1,247, 1,249, 1,545, 1,541, + 1,543, 1,544, 1,546, 1,547, 1,548, 1,549, 1,550, 1,551, + 1,552, 1,553, 1,554, 1,555, 1,556, 1,557, 1,558, 1,559, + 1,560, 1,561, 1,562, 1,563, 1,564, 1,565, 1,566, 1,567, 1,568, 1,569, 1,570, 1,571, 1,572, 1,573, 1,574, 1,575, 1,576, 1,577, 1,578, 1,579, 1,580, 1,581, 1,582, 1,583, 1,584, 1,585, 1,586, 1,587, 1,588, 1,589, 1,590, 1,591, - 1,592, 1,593, 1,594, 1,595, 1,596, 1,597, 1,598, 1,599, - 1,600, 1,601, 1,602, 1,603, 1,604, 1,605, 1,606, 1,607, - 1,608, 1,609, 1,610, 1,611, 1,612, 1,613, 1,614, 1,615, - 1,616, 1,617, 1,618, 1,619,0 + 1,592, 1,593, 1,594, 1,595, 1,597, 1,598, 1,599, 1,600, + 1,601, 1,602, 1,603, 1,604, 1,605, 1,606, 1,607, 1,608, + 1,609, 1,611, 1,612, 1,613, 1,614, 1,615, 1,616, 1,617, + 1,618, 1,619, 1,620, 1,621, 1,622, 1,623, 1,624, 1,625, + 1,626, 1,627, 1,628, 1,629, 1,630, 1,631, 1,632, 1,633, + 1,634, 1,635, 1,636, 1,637, 1,638, 1,639, 1,640, 1,641, + 1,642, 1,643, 1,644, 1,645, 1,646, 1,647, 1,648, 1,649, + 1,650, 1,651, 1,652, 1,653, 1,654, 1,655, 1,656, 1,657, + 1,658, 1,659, 1,660, 1,661, 1,662, 1,663, 1,664, 1,665, + 1,666, 1,667, 1,668, 1,669, 1,671, 1,672, 1,673, 1,674, + 1,675, 1,676, 1,677, 1,678, 1,679, 1,680, 1,681,0 }; static const unsigned char ag_key_ch[] = { - 0, 42, 47,255, 85,255, 76,255, 67,255, 78,255, 35, 36, 38, 47, 73,255, - 61,255, 61,255, 42, 47, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, 62, - 255, 67, 68, 73,255, 65, 68, 73,255, 69, 72,255, 67, 68, 78, 82, 83,255, - 67, 76, 89,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 69, - 77, 78, 80, 83, 90,255, 65, 68,255, 82, 88,255, 68,255, 69,255, 78,255, - 73,255, 70, 72, 83,255, 69, 85,255, 65, 66, 67, 69, 73, 83, 87,255, 73, - 83,255, 73,255, 68,255, 85,255, 69, 82,255, 84,255, 67, 73, 76, 78, 81, - 82, 88,255, 73, 76, 80,255, 69, 84,255, 77, 84,255, 69, 73, 76,255, 68, - 78,255, 85,255, 76,255, 67, 80, 82, 88,255, 70, 78, 80,255, 80,255, 53, - 255, 67, 68, 75, 88, 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, - 77, 78, 80, 84, 88, 90,255, 88,255, 72, 83,255, 65, 69, 72,255, 69,255, - 68, 73, 88,255, 76,255, 78, 83,255, 71, 87,255, 68, 69, 72, 73, 78, 79, - 83, 84, 88,255, 85,255, 68, 86,255, 65, 79, 83, 86,255, 65,255, 80, 84, - 255, 65, 69, 79,255, 65, 71, 73,255, 82, 85,255, 65, 73,255, 66, 83,255, - 65, 67, 79, 82, 83, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, 79, - 255, 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, - 83, 90,255, 66, 73,255, 69,255, 68, 73, 82, 88,255, 76, 82,255, 72,255, - 88,255, 65, 67, 75,255, 66, 73,255, 66, 69, 72, 73, 80, 81, 84, 85, 89, - 255, 69, 73,255, 65, 73,255, 67, 79, 82, 84,255, 33, 35, 36, 38, 39, 40, - 42, 44, 47, 60, 61, 62, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, - 78, 79, 80, 82, 83, 84, 85, 87, 88, 92,255, 42, 47,255, 35, 36, 38, 47, + 0, 66, 68, 84,255, 42, 47,255, 85,255, 76,255, 67,255, 78,255, 35, 36, + 38, 46, 47, 73,255, 61,255, 61,255, 42, 47, 61,255, 66, 68, 84,255, 42, + 47,255, 60, 61,255, 61,255, 61, 62,255, 67, 68, 73,255, 65, 68, 73,255, + 69, 72,255, 67, 68, 78, 82, 83,255, 67, 90,255, 69,255, 65,255, 67, 76, + 77, 78, 80, 82, 89, 90,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, + 65, 67, 69, 77, 78, 80, 83, 90,255, 65, 68,255, 82, 88,255, 68,255, 69, + 255, 78,255, 73,255, 70, 72, 83,255, 69, 85,255, 65, 66, 67, 69, 73, 83, + 87, 88,255, 73, 83,255, 73,255, 68, 84,255, 85,255, 78, 82,255, 69, 82, + 255, 84,255, 67, 73, 76, 78, 81, 82, 88,255, 73, 76, 80,255, 69, 84,255, + 77, 84,255, 69, 73, 76,255, 68, 78,255, 85,255, 76,255, 67, 80, 82, 88, + 255, 70, 78, 80,255, 80,255, 53,255, 67, 68, 75, 88, 90,255, 69, 79,255, + 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, 88, 90,255, 88,255, 72, + 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, 88,255, 76,255, 78, 83,255, + 71, 87,255, 79, 85,255, 67, 68, 69, 72, 73, 74, 78, 79, 80, 82, 83, 84, + 88,255, 85,255, 68, 86,255, 65, 79, 83, 86,255, 65,255, 80, 84,255, 65, + 69, 79,255, 65, 71, 73,255, 82, 85,255, 72,255, 65, 73,255, 66, 83,255, + 65, 67, 79, 82, 83, 85,255, 76, 82,255, 65,255, 67, 68,255, 67, 90,255, + 69, 71, 79,255, 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, + 78, 80, 82, 83, 90,255, 67, 90,255, 66, 67, 73, 78, 90,255, 69,255, 68, + 73, 82, 88,255, 76, 82,255, 71, 72, 73,255, 88,255, 65, 67, 75,255, 66, + 73,255, 66, 69, 72, 73, 80, 81, 84, 85, 89,255, 69, 73,255, 65, 73,255, + 67, 79, 82, 84,255, 33, 35, 36, 38, 39, 40, 42, 44, 46, 47, 60, 61, 62, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, + 85, 86, 87, 88, 92,255, 66, 68, 84,255, 42, 47,255, 35, 36, 38, 46, 47, 255, 73, 83,255, 76, 78, 82,255, 68, 78,255, 70, 78,255, 68, 69, 73, 80, 85,255, 42, 47,255, 38, 42, 47, 58,255, 61,255, 42, 47,255, 67, 68, 73, - 255, 65, 73,255, 69, 72,255, 67, 68, 78, 82, 83,255, 76, 89,255, 65, 67, - 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 83, 90,255, 65, - 68,255, 82, 88,255, 72, 83,255, 69, 85,255, 65, 66, 67, 69, 73, 83, 87, - 255, 73,255, 68,255, 69, 82,255, 84,255, 67, 73, 76, 78, 81, 88,255, 77, - 84,255, 69, 76,255, 82, 88,255, 70, 78,255, 80,255, 53,255, 67, 68, 75, - 88, 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, - 88, 90,255, 88,255, 72, 83,255, 65, 69, 72,255, 69,255, 68, 73, 88,255, - 76,255, 78, 83,255, 68, 72, 73, 83, 88,255, 68, 86,255, 65, 79, 83, 86, - 255, 65,255, 80,255, 65, 79,255, 65, 71, 73,255, 82, 85,255, 66, 83,255, - 65, 67, 79, 82, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, 79,255, - 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, - 90,255, 66, 73,255, 69,255, 68, 73, 82, 88,255, 76,255, 88,255, 65, 67, - 75,255, 66, 73,255, 66, 69, 72, 73, 80, 84, 85, 89,255, 69, 73,255, 65, - 73,255, 67, 82, 84,255, 36, 38, 42, 47, 65, 66, 67, 68, 69, 70, 72, 73, - 74, 76, 77, 78, 79, 80, 82, 83, 84, 87, 88,255, 42, 47,255, 85,255, 76, - 255, 67,255, 78,255, 47, 73,255, 61,255, 42, 47,255, 67, 68, 73,255, 65, - 73,255, 69, 72,255, 67, 68, 78, 82, 83,255, 76, 89,255, 65, 67, 80,255, - 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 83, 90,255, 65, 68,255, - 82, 88,255, 72, 83,255, 69, 85,255, 65, 66, 67, 69, 73, 83, 87,255, 73, - 255, 68,255, 69, 82,255, 84,255, 67, 73, 76, 78, 88,255, 77, 84,255, 69, - 76,255, 85,255, 76,255, 67, 82, 88,255, 70, 78,255, 80,255, 53,255, 67, - 68, 75, 88, 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, - 80, 84, 88, 90,255, 88,255, 72, 83,255, 65, 69, 72,255, 69,255, 68, 73, - 88,255, 76,255, 78, 83,255, 68, 72, 73, 83, 88,255, 68, 86,255, 65, 79, - 83, 86,255, 65,255, 80,255, 65, 79,255, 65, 71, 73,255, 82, 85,255, 66, - 83,255, 65, 67, 79, 82, 85,255, 76, 82,255, 67, 68,255, 67, 90,255, 69, - 79,255, 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, - 82, 83, 90,255, 66, 73,255, 69,255, 68, 73, 82, 88,255, 76,255, 88,255, - 65, 67, 75,255, 66, 73,255, 66, 72, 73, 80, 84, 85, 89,255, 69, 73,255, - 65, 73,255, 67, 82, 84,255, 36, 38, 42, 47, 65, 66, 67, 68, 69, 70, 72, - 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, 87, 88,255, 36, 38,255, 42, 47, - 255, 47,255, 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, 67, 68, 70, - 72, 73, 76, 78, 83,255, 72, 76,255, 42, 47,255, 85,255, 76,255, 67,255, - 78,255, 35, 36, 38, 42, 47, 73,255, 47, 61,255, 42, 47,255, 76, 89,255, - 69,255, 66, 83, 87,255, 69, 82,255, 84,255, 67, 78, 81, 88,255, 85,255, - 76,255, 67,255, 78,255, 78, 83,255, 73, 83,255, 65, 79, 83,255, 65, 79, - 255, 65, 82, 85,255, 69, 84, 89,255, 69, 73,255, 36, 42, 47, 65, 66, 67, - 68, 69, 70, 72, 73, 76, 77, 78, 79, 80, 83, 84, 87, 92,255, 85,255, 76, - 255, 67,255, 78,255, 73,255, 42, 47,255, 42, 47,255, 42, 47, 92,255, 42, - 47,255, 47, 73, 80,255, 42, 47,255, 33, 47,255, 40, 65, 66, 67, 68, 69, - 72, 76, 77,255, 67,255, 69,255, 76,255, 66, 68, 72, 83,255, 67,255, 69, - 255, 76,255, 65, 66, 68, 72, 80,255, 67,255, 69,255, 66, 68,255, 61,255, - 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 33, 42, 44, 47, 60, 61, 62, - 255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, - 84,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 65, 69, 71, 76, - 77, 78, 79, 83, 88,255, 76, 89,255, 69,255, 66, 83, 87,255, 69, 82,255, - 84,255, 67, 78, 88,255, 78, 83,255, 73, 83,255, 65, 79, 83,255, 65, 79, - 255, 65, 82, 85,255, 84, 89,255, 69, 73,255, 36, 42, 65, 66, 67, 68, 69, - 70, 72, 76, 77, 78, 79, 80, 83, 84, 87,255, 42, 47,255, 44, 47,255, 61, - 255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, - 82,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 65, 69, 71, 76, - 77, 78, 79, 81, 83, 88,255, 39,255, 61,255, 42, 47,255, 60, 61,255, 61, - 255, 61, 62,255, 69, 84,255, 69, 84,255, 82,255, 76, 82,255, 72,255, 33, - 42, 44, 47, 60, 61, 62, 71, 76, 77, 78, 79, 81, 83, 88,255, 42, 47,255, - 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, 42, 47, 67, 68, 70, 72, - 73, 76, 78, 83, 92,255, 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, - 67, 68, 70, 72, 73, 76, 83,255, 42, 47,255, 76, 80,255, 71, 87,255, 78, - 79,255, 36, 38, 39, 42, 47, 67, 68, 70, 72, 73, 76, 83, 92,255, 61,255, - 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72, - 255, 33, 42, 44, 60, 61, 62, 65, 69, 71, 76, 77, 78, 79, 83, 88,255, 61, + 255, 65, 73,255, 69, 72,255, 67, 68, 78, 82, 83,255, 67, 90,255, 69,255, + 65,255, 67, 76, 77, 78, 80, 82, 89, 90,255, 65, 67, 80,255, 67, 90,255, + 69, 73, 79,255, 65, 67, 77, 78, 80, 83, 90,255, 65, 68,255, 82, 88,255, + 72, 83,255, 69, 85,255, 65, 66, 67, 69, 73, 83, 87,255, 73,255, 68, 84, + 255, 78, 82,255, 69, 82,255, 84,255, 67, 73, 76, 78, 81, 88,255, 77, 84, + 255, 69, 76,255, 82, 88,255, 70, 78,255, 80,255, 53,255, 67, 68, 75, 88, + 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, 88, + 90,255, 88,255, 72, 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, 88,255, + 76,255, 78, 83,255, 79, 85,255, 67, 68, 72, 73, 74, 80, 82, 83, 88,255, + 68, 86,255, 65, 79, 83, 86,255, 65,255, 80,255, 65, 79,255, 65, 71, 73, + 255, 82, 85,255, 66, 83,255, 65, 67, 79, 82, 85,255, 76, 82,255, 65,255, + 67, 68,255, 67, 90,255, 69, 71, 79,255, 67, 72,255, 86,255, 84,255, 65, + 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 67, 90,255, 66, 67, 73, + 78, 90,255, 69,255, 68, 73, 82, 88,255, 76,255, 71, 72, 73,255, 88,255, + 65, 67, 75,255, 66, 73,255, 66, 69, 72, 73, 80, 84, 85, 89,255, 69, 73, + 255, 65, 73,255, 67, 82, 84,255, 36, 38, 42, 47, 65, 66, 67, 68, 69, 70, + 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, 86, 87, 88,255, 42, 47,255, + 85,255, 76,255, 67,255, 78,255, 47, 73,255, 61,255, 42, 47,255, 67, 68, + 73,255, 65, 73,255, 69, 72,255, 67, 68, 78, 82, 83,255, 67, 90,255, 69, + 255, 65,255, 67, 76, 77, 78, 80, 82, 89, 90,255, 65, 67, 80,255, 67, 90, + 255, 69, 73, 79,255, 65, 67, 77, 78, 80, 83, 90,255, 65, 68,255, 82, 88, + 255, 72, 83,255, 69, 85,255, 65, 66, 67, 69, 73, 83, 87,255, 73,255, 68, + 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 73, 76, 78, 88,255, 77, 84, + 255, 69, 76,255, 85,255, 76,255, 67, 82, 88,255, 70, 78,255, 80,255, 53, + 255, 67, 68, 75, 88, 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, + 77, 78, 80, 84, 88, 90,255, 88,255, 72, 83,255, 65, 69, 72, 83,255, 69, + 255, 68, 73, 88,255, 76,255, 78, 83,255, 79, 85,255, 67, 68, 72, 73, 74, + 80, 82, 83, 88,255, 68, 86,255, 65, 79, 83, 86,255, 65,255, 80,255, 65, + 79,255, 65, 71, 73,255, 82, 85,255, 66, 83,255, 65, 67, 79, 82, 85,255, + 76, 82,255, 65,255, 67, 68,255, 67, 90,255, 69, 71, 79,255, 67, 72,255, + 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 67, + 90,255, 66, 67, 73, 78, 90,255, 69,255, 68, 73, 82, 88,255, 76,255, 71, + 72, 73,255, 88,255, 65, 67, 75,255, 66, 73,255, 66, 72, 73, 80, 84, 85, + 89,255, 69, 73,255, 65, 73,255, 67, 82, 84,255, 36, 38, 42, 47, 65, 66, + 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, 86, 87, 88, + 255, 36, 38,255, 42, 47,255, 47,255, 76, 80,255, 71, 87,255, 78, 79,255, + 36, 38, 39, 67, 68, 70, 72, 73, 76, 78, 80, 83,255, 78, 88,255, 69, 72, + 76, 86,255, 66, 68, 84,255, 42, 47,255, 85,255, 76,255, 67,255, 78,255, + 35, 36, 38, 42, 46, 47, 73,255, 47, 61,255, 42, 47,255, 76, 89,255, 69, + 255, 66, 83, 87,255, 68, 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 78, + 81, 88,255, 85,255, 76,255, 67,255, 78,255, 78, 83,255, 73, 83,255, 65, + 79, 83,255, 65, 79,255, 65, 82, 85,255, 69, 84, 89,255, 69, 73,255, 36, + 42, 47, 65, 66, 67, 68, 69, 70, 72, 73, 76, 77, 78, 79, 80, 83, 84, 86, + 87, 92,255, 85,255, 76,255, 67,255, 78,255, 73,255, 42, 47,255, 42, 47, + 255, 42, 47, 92,255, 42, 47,255, 47, 73, 80,255, 42, 47,255, 33, 47,255, + 67,255, 69, 88,255, 76,255, 66, 68, 72, 80, 83,255, 40, 65, 66, 67, 68, + 69, 72, 76, 77,255, 67,255, 69,255, 76,255, 66, 68, 72, 83,255, 67,255, + 69,255, 76,255, 65, 66, 68, 72, 80,255, 67,255, 69,255, 66, 68,255, 61, + 255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 33, 42, 44, 47, 60, 61, + 62,255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, + 69, 84,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 65, 69, 71, + 76, 77, 78, 79, 83, 88,255, 76, 89,255, 69,255, 66, 83, 87,255, 68, 84, + 255, 78, 82,255, 69, 82,255, 84,255, 67, 78, 88,255, 78, 83,255, 73, 83, + 255, 65, 79, 83,255, 65, 79,255, 65, 82, 85,255, 84, 89,255, 69, 73,255, + 36, 42, 65, 66, 67, 68, 69, 70, 72, 76, 77, 78, 79, 80, 83, 84, 86, 87, + 255, 42, 47,255, 44, 47,255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, + 62,255, 69, 84,255, 69, 84,255, 82,255, 76, 82,255, 72,255, 33, 42, 44, + 47, 60, 61, 62, 65, 69, 71, 76, 77, 78, 79, 81, 83, 88,255, 39,255, 61, 255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, - 76, 82,255, 72,255, 33, 44, 47, 60, 61, 62, 65, 69, 71, 76, 78, 79, 83, + 82,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 71, 76, 77, 78, + 79, 81, 83, 88,255, 42, 47,255, 76, 80,255, 71, 87,255, 78, 79,255, 36, + 38, 39, 42, 47, 67, 68, 70, 72, 73, 76, 78, 80, 83, 92,255, 76, 80,255, + 71, 87,255, 78, 79,255, 36, 38, 39, 67, 68, 70, 72, 73, 76, 80, 83,255, + 42, 47,255, 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, 42, 47, 67, + 68, 70, 72, 73, 76, 80, 83, 92,255, 61,255, 60, 61,255, 61,255, 61, 62, + 255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 42, 44, 60, 61, 62, + 65, 69, 71, 76, 77, 78, 79, 83, 88,255, 61,255, 42, 47,255, 60, 61,255, + 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 44, + 47, 60, 61, 62, 65, 69, 71, 76, 78, 79, 83, 88,255, 61,255, 42, 47,255, + 61,255, 61,255, 61,255, 69, 84,255, 69, 84,255, 33, 44, 47, 60, 61, 62, + 65, 69, 71, 76, 78, 79, 88,255, 61,255, 42, 47,255, 61,255, 61,255, 61, + 255, 69, 84,255, 69, 84,255, 33, 44, 47, 60, 61, 62, 69, 71, 76, 78, 79, 88,255, 61,255, 42, 47,255, 61,255, 61,255, 61,255, 69, 84,255, 69, 84, - 255, 33, 44, 47, 60, 61, 62, 65, 69, 71, 76, 78, 79, 88,255, 61,255, 42, - 47,255, 61,255, 61,255, 61,255, 69, 84,255, 69, 84,255, 33, 44, 47, 60, - 61, 62, 69, 71, 76, 78, 79, 88,255, 61,255, 42, 47,255, 61,255, 61,255, - 61,255, 69, 84,255, 69, 84,255, 33, 44, 47, 60, 61, 62, 69, 71, 76, 78, - 79,255, 42, 47,255, 61,255, 61,255, 61,255, 69, 84,255, 69, 84,255, 33, - 47, 60, 61, 62, 69, 71, 76, 78,255, 61,255, 42, 47,255, 42, 47,255, 60, - 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, - 33, 42, 44, 47, 60, 61, 62, 65, 69, 71, 76, 77, 78, 79, 83, 88, 92,255, - 76, 89,255, 69,255, 66, 83, 87,255, 69, 82,255, 84,255, 67, 78, 81, 88, - 255, 78, 83,255, 73, 83,255, 65, 79, 83,255, 65, 79,255, 65, 82, 85,255, - 69, 84, 89,255, 69, 73,255, 36, 42, 65, 66, 67, 68, 69, 70, 72, 76, 77, - 78, 79, 80, 83, 84, 87,255, 39,255, 67, 68, 73,255, 65, 73,255, 67, 68, - 78, 82, 83,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, - 78, 80, 90,255, 65, 68,255, 82, 88,255, 72, 83,255, 65, 67, 69, 73, 83, - 255, 77, 84,255, 76,255, 82, 88,255, 78,255, 80,255, 53,255, 67, 68, 75, - 88, 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, - 88, 90,255, 88,255, 72, 83,255, 65, 69, 72,255, 69,255, 68, 73, 88,255, - 76,255, 68, 72, 88,255, 79, 86,255, 65, 73,255, 82, 85,255, 67, 79, 85, - 255, 76, 82,255, 67, 68,255, 67, 90,255, 69, 79,255, 67, 72,255, 86,255, - 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 66, 73,255, - 69,255, 68, 73, 82, 88,255, 76,255, 88,255, 65, 67,255, 66, 73,255, 66, - 72, 73, 80, 84, 85,255, 65, 73,255, 67, 82, 84,255, 65, 67, 68, 69, 72, + 255, 33, 44, 47, 60, 61, 62, 69, 71, 76, 78, 79,255, 42, 47,255, 61,255, + 61,255, 61,255, 69, 84,255, 69, 84,255, 33, 47, 60, 61, 62, 69, 71, 76, + 78,255, 61,255, 42, 47,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, + 69, 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, + 65, 69, 71, 76, 77, 78, 79, 83, 88, 92,255, 76, 89,255, 69,255, 66, 83, + 87,255, 68, 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 78, 81, 88,255, + 78, 83,255, 73, 83,255, 65, 79, 83,255, 65, 79,255, 65, 82, 85,255, 69, + 84, 89,255, 69, 73,255, 36, 42, 65, 66, 67, 68, 69, 70, 72, 76, 77, 78, + 79, 80, 83, 84, 86, 87,255, 39,255, 67, 68, 73,255, 65, 73,255, 67, 68, + 78, 82, 83,255, 67, 90,255, 69,255, 65,255, 67, 77, 78, 80, 82, 90,255, + 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 90,255, + 65, 68,255, 82, 88,255, 72, 83,255, 65, 67, 69, 73, 83,255, 77, 84,255, + 76,255, 82, 88,255, 78,255, 80,255, 53,255, 67, 68, 75, 88, 90,255, 69, + 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, 88, 90,255, 88, + 255, 72, 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, 88,255, 76,255, 79, + 85,255, 67, 68, 72, 74, 80, 82, 88,255, 79, 86,255, 65, 73,255, 82, 85, + 255, 67, 79, 85,255, 76, 82,255, 65,255, 67, 68,255, 67, 90,255, 69, 71, + 79,255, 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, + 82, 83, 90,255, 67, 90,255, 66, 67, 73, 78, 90,255, 69,255, 68, 73, 82, + 88,255, 76,255, 71, 72, 73,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, + 73, 80, 84, 85,255, 65, 73,255, 67, 82, 84,255, 65, 66, 67, 68, 69, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 42, 47,255, 36, 38, 47,255, 42, 47,255, 33, 44, 47,255, 44,255, 42, 47,255, 47, 79, 81,255, 92,255, 69,255, 69,255, 76, 80,255, 73,255, 71, 87,255, 78, 79,255, 36, 38, 39, - 40, 65, 66, 67, 68, 69, 70, 72, 73, 76, 77, 78, 83,255, 33,255, 42, 47, - 255, 47, 92,255 + 40, 65, 66, 67, 68, 69, 70, 72, 73, 76, 77, 78, 80, 83,255, 33,255, 42, + 47,255, 47, 92,255 }; static const unsigned char ag_key_act[] = { - 0,0,0,4,7,4,6,4,2,4,2,4,0,5,0,2,2,4,0,4,0,4,0,0,0,4,0,0,4,0,0,4,0,4,0, - 0,4,5,5,5,4,5,5,5,4,7,7,4,7,2,2,7,2,4,5,7,7,4,5,5,5,4,5,5,4,5,5,5,4,7, - 5,7,6,2,6,7,5,4,5,5,4,5,5,4,5,4,6,4,2,4,2,4,2,7,7,4,7,7,4,2,5,2,6,5,6, - 5,4,7,7,4,7,4,6,4,5,4,7,7,4,2,4,7,5,2,2,6,7,2,4,7,7,5,4,5,5,4,7,5,4,7, - 7,6,4,7,7,4,7,4,6,4,2,7,5,5,4,6,6,5,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4, - 5,4,5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,4,5,4,6,5,5,4,2,4,7,7,4,5,5,4, - 2,5,2,2,5,2,7,5,7,4,7,4,6,5,4,7,2,7,7,4,7,4,6,5,4,7,5,2,4,5,5,5,4,6,7, - 4,7,7,4,7,7,4,7,7,7,2,7,2,4,5,5,4,5,7,4,5,5,4,5,5,4,5,7,4,5,4,6,4,2,5, - 7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,4,6,5,5,5,4,6,5,4,7,4,5,4,6,5,7,4,5,5,4, - 2,7,2,7,6,7,2,2,7,4,7,7,4,5,5,4,7,7,2,7,4,6,0,6,0,3,3,2,0,2,1,1,1,6,6, - 6,6,6,2,2,6,2,2,6,6,2,2,2,2,2,2,7,7,2,3,4,0,0,4,0,5,0,2,4,7,7,4,2,7,7, - 4,7,7,4,6,7,4,7,2,2,7,7,4,0,0,4,0,3,2,0,4,0,4,0,0,4,5,5,5,4,5,5,4,7,7, - 4,7,2,2,7,2,4,7,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5,4,5,5,4,5,5,4, - 7,7,4,7,7,4,2,5,2,2,5,6,5,4,7,4,6,4,7,7,4,2,4,7,5,7,2,7,2,4,7,5,4,7,2, - 4,5,5,4,5,6,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5,4, - 5,4,5,5,4,6,2,7,4,5,4,6,5,5,4,2,4,7,7,4,2,2,2,7,7,4,7,5,4,7,2,7,7,4,7, - 4,6,4,7,2,4,5,5,5,4,2,7,4,7,7,4,7,7,7,7,2,4,5,5,4,5,7,4,5,5,4,5,5,4,5, - 7,4,5,4,6,4,2,5,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,4,6,5,5,5,4,2,4,5,4,6,5, - 7,4,5,5,4,2,7,2,7,7,2,2,7,4,7,7,4,5,5,4,7,2,7,4,6,0,3,2,2,2,2,2,2,7,2, - 2,2,2,2,2,2,2,2,2,2,7,2,4,0,0,4,7,4,6,4,2,4,2,4,2,2,4,0,4,0,0,4,5,5,5, - 4,5,5,4,7,7,4,7,2,2,7,2,4,7,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5,4, - 5,5,4,5,5,4,7,7,4,7,7,4,2,5,2,2,5,6,5,4,7,4,6,4,7,7,4,2,4,7,5,7,2,2,4, - 7,5,4,7,2,4,7,4,6,4,2,5,5,4,5,6,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4, - 5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,4,5,4,6,5,5,4,2,4,7,7,4,2,2,2,7,7, - 4,7,5,4,7,2,7,7,4,7,4,6,4,7,2,4,5,5,5,4,2,7,4,7,7,4,7,7,7,7,2,4,5,5,4, - 5,7,4,5,5,4,5,5,4,5,7,4,5,4,6,4,2,5,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,4,6, - 5,5,5,4,2,4,5,4,6,5,7,4,5,5,4,2,2,7,7,2,2,7,4,7,7,4,5,5,4,7,2,7,4,6,0, - 3,2,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,7,2,4,5,0,4,0,0,4,2,4,7,5,4,5,5, - 4,5,2,4,5,0,3,7,7,2,7,7,2,7,7,4,7,7,4,0,0,4,7,4,6,4,2,4,2,4,0,5,0,3,2, - 2,4,0,0,4,0,0,4,7,7,4,7,4,5,6,5,4,7,7,4,2,4,7,7,7,2,4,7,4,6,4,2,4,2,4, - 7,7,4,2,7,4,7,7,7,4,7,7,4,7,7,7,4,7,7,7,4,7,7,4,3,2,2,7,2,7,2,2,7,7,2, - 2,2,2,7,2,2,2,7,3,4,7,4,6,4,2,4,2,4,2,4,3,3,4,0,0,4,3,2,3,4,0,0,4,2,7, - 7,4,0,0,4,5,2,4,3,5,5,5,5,5,5,5,5,4,5,4,5,4,5,4,6,6,6,7,4,5,4,5,4,5,4, - 5,6,6,6,7,4,5,4,5,4,6,6,4,0,4,0,0,4,0,0,4,0,4,0,0,4,6,3,0,2,1,1,1,4,0, - 4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,3,0,2,1,1,1,7,7,2,2,7, - 7,7,2,7,4,7,7,4,7,4,5,6,5,4,7,7,4,2,4,7,7,2,4,7,7,4,2,7,4,7,7,7,4,7,7, - 4,7,7,7,4,7,7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2,2,7,2,2,2,7,4,0,0,4,0,2,4, - 0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,4,5,5,4,2,4,6,3,0,2,1,1,1,7,7, - 2,2,7,7,6,5,2,7,4,3,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,4,5,5,4, - 2,4,6,3,0,2,1,1,1,2,2,7,7,6,5,2,7,4,0,0,4,7,5,4,5,5,4,5,2,4,5,0,3,3,2, - 7,7,2,7,7,2,7,7,3,4,7,5,4,5,5,4,5,2,4,5,0,3,7,7,2,7,7,2,7,4,0,0,4,7,5, - 4,5,5,4,5,2,4,5,0,3,3,2,7,7,2,7,7,2,7,3,4,0,4,0,0,4,0,4,0,0,4,5,5,4,5, - 5,4,5,5,4,2,4,6,3,0,1,1,1,7,7,2,2,7,7,7,2,7,4,0,4,0,0,4,0,0,4,0,4,0,0, - 4,5,5,4,5,5,4,5,5,4,2,4,6,0,2,1,1,1,7,7,2,2,7,7,2,7,4,0,4,0,0,4,0,4,0, - 4,0,4,5,5,4,5,5,4,6,0,2,1,1,1,7,7,2,2,7,7,7,4,0,4,0,0,4,0,4,0,4,0,4,5, - 5,4,5,5,4,6,0,2,1,1,1,7,2,2,7,7,7,4,0,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4, - 6,0,2,1,1,1,7,2,2,7,7,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,3,2,1,1,1,7,2,2, - 7,4,0,4,0,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,2,0,2,1,1, - 1,7,7,2,2,7,7,7,2,7,3,4,7,7,4,7,4,5,6,5,4,7,7,4,2,4,7,7,7,2,4,7,7,4,2, - 7,4,7,7,7,4,7,7,4,7,7,7,4,7,7,7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2,2,7,2,2, - 2,7,4,3,4,5,5,5,4,5,5,4,7,2,2,7,7,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,5, - 4,5,5,4,5,5,4,7,7,4,2,2,2,5,7,4,7,5,4,2,4,5,5,4,6,4,5,4,5,4,5,5,5,6,5, - 4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,4,5,4,6,5,5,4,2, - 4,2,2,7,4,7,7,4,5,5,4,2,7,4,7,7,7,4,5,5,4,5,7,4,5,5,4,5,5,4,5,7,4,5,4, - 6,4,2,5,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,4,6,5,5,5,4,2,4,5,4,6,5,4,5,5,4, - 2,2,7,7,2,2,4,5,5,4,7,2,7,4,2,2,2,7,2,2,2,2,2,7,2,2,2,2,2,4,0,0,4,5,0, - 2,4,0,0,4,5,0,2,4,0,4,0,0,4,2,5,5,4,3,4,7,4,7,4,7,5,4,7,4,5,5,4,5,2,4, - 5,0,3,3,5,5,6,6,5,2,6,7,6,5,7,7,4,5,4,0,0,4,2,3,4 + 0,3,3,3,4,0,0,4,7,4,6,4,2,4,2,4,0,5,0,2,2,2,4,0,4,0,4,0,0,0,4,3,3,3,4, + 0,0,4,0,0,4,0,4,0,0,4,5,5,5,4,5,5,5,4,7,7,4,7,2,2,7,2,4,5,5,4,5,4,5,4, + 5,7,5,2,6,6,7,5,4,5,5,5,4,5,5,4,5,5,5,4,7,5,7,6,2,6,7,5,4,5,5,4,5,5,4, + 5,4,6,4,2,4,2,4,2,7,7,4,7,7,4,2,5,2,6,5,6,5,5,4,7,7,4,7,4,6,7,4,5,4,7, + 7,4,2,7,4,2,4,7,5,2,2,6,7,2,4,7,7,5,4,5,5,4,7,5,4,7,7,6,4,7,7,4,7,4,6, + 4,2,7,5,5,4,6,6,5,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2, + 6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4,2,4,7,7,4,5,5,4,7,7,4,7,2,5,2,2, + 7,5,2,2,7,7,5,7,4,7,4,6,5,4,7,2,7,7,4,7,4,6,5,4,7,5,2,4,5,5,5,4,6,7,4, + 7,4,7,7,4,7,7,4,7,6,7,2,7,2,4,5,5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4, + 6,4,2,6,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5,5,5,4,6,5,4,5, + 7,5,4,5,4,6,5,7,4,5,5,4,2,7,2,7,6,7,2,2,7,4,7,7,4,5,5,4,7,7,2,7,4,6,0, + 6,0,3,3,2,0,2,2,1,1,1,6,6,6,6,6,2,2,6,2,2,6,6,2,2,2,2,2,2,7,7,7,2,3,4, + 3,3,3,4,0,0,4,0,5,0,2,2,4,7,7,4,2,7,7,4,7,7,4,6,7,4,7,2,2,7,7,4,0,0,4, + 0,3,2,0,4,0,4,0,0,4,5,5,5,4,5,5,4,7,7,4,7,2,2,7,2,4,5,5,4,5,4,5,4,5,7, + 5,2,6,6,7,5,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5,4,5,5,4,5,5,4,7,7,4, + 7,7,4,2,5,2,2,5,6,5,4,7,4,6,7,4,7,7,4,2,7,4,2,4,7,5,7,2,7,2,4,7,5,4,7, + 2,4,5,5,4,5,6,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5, + 4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4,2,4,7,7,4,7,7,4,7,2,2,2,7,2,7,7,7,4, + 7,5,4,7,2,7,7,4,7,4,6,4,7,2,4,5,5,5,4,2,7,4,7,7,4,7,7,7,7,2,4,5,5,4,7, + 4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4,6,4,2,6,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5, + 5,5,2,5,4,5,4,6,5,5,5,4,2,4,5,7,5,4,5,4,6,5,7,4,5,5,4,2,7,2,7,2,2,2,7, + 4,7,7,4,5,5,4,7,2,7,4,6,0,3,2,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,7,7,2, + 4,0,0,4,7,4,6,4,2,4,2,4,2,2,4,0,4,0,0,4,5,5,5,4,5,5,4,7,7,4,7,2,2,7,2, + 4,5,5,4,5,4,5,4,5,7,5,2,6,6,7,5,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5, + 4,5,5,4,5,5,4,7,7,4,7,7,4,2,5,2,2,5,6,5,4,7,4,6,7,4,7,7,4,2,7,4,2,4,7, + 5,7,2,2,4,7,5,4,7,2,4,7,4,6,4,2,5,5,4,5,6,4,5,4,5,4,5,5,5,6,5,4,5,5,4, + 5,5,4,5,4,5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4,2,4,7,7, + 4,7,7,4,7,2,2,2,7,2,7,7,7,4,7,5,4,7,2,7,7,4,7,4,6,4,7,2,4,5,5,5,4,2,7, + 4,7,7,4,7,7,7,7,2,4,5,5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4,6,4,2,6,7, + 7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5,5,5,4,2,4,5,7,5,4,5,4,6, + 5,7,4,5,5,4,2,2,7,2,2,2,7,4,7,7,4,5,5,4,7,2,7,4,6,0,3,2,2,2,2,2,2,7,2, + 2,2,2,2,2,2,2,2,2,2,7,7,2,4,5,0,4,0,0,4,2,4,7,5,4,5,5,4,5,2,4,5,0,3,7, + 7,2,7,7,2,7,7,7,4,7,7,4,2,7,7,7,4,3,3,3,4,0,0,4,7,4,6,4,2,4,2,4,0,5,0, + 3,2,2,2,4,0,0,4,0,0,4,7,7,4,7,4,5,6,5,4,5,7,4,7,7,4,2,7,4,2,4,7,2,7,2, + 4,7,4,6,4,2,4,2,4,7,7,4,2,7,4,7,7,7,4,7,7,4,7,7,7,4,7,7,7,4,7,7,4,3,2, + 2,7,2,7,2,2,7,7,2,2,2,2,7,2,2,2,7,7,3,4,7,4,6,4,2,4,2,4,2,4,3,3,4,0,0, + 4,3,2,3,4,0,0,4,2,7,7,4,0,0,4,5,2,4,5,4,5,5,4,5,4,6,6,6,7,7,4,3,5,5,5, + 5,5,5,5,5,4,5,4,5,4,5,4,6,6,6,7,4,5,4,5,4,5,4,5,6,6,6,7,4,5,4,5,4,6,6, + 4,0,4,0,0,4,0,0,4,0,4,0,0,4,6,3,0,2,1,1,1,4,0,4,0,0,4,0,0,4,0,4,0,0,4, + 5,5,4,5,5,4,5,5,4,2,4,6,3,0,2,1,1,1,7,7,2,2,7,7,7,2,7,4,7,7,4,7,4,5,6, + 5,4,5,7,4,7,7,4,2,7,4,2,4,7,2,2,4,7,7,4,2,7,4,7,7,7,4,7,7,4,7,7,7,4,7, + 7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2,2,7,2,2,2,7,7,4,0,0,4,0,2,4,0,4,0,0,4, + 0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,4,5,5,4,2,4,6,3,0,2,1,1,1,7,7,2,2,7,7,6, + 5,2,7,4,3,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,4,5,5,4,2,4,6,3,0, + 2,1,1,1,2,2,7,7,6,5,2,7,4,0,0,4,7,5,4,5,5,4,5,2,4,5,0,3,3,2,7,7,2,7,7, + 2,7,7,7,3,4,7,5,4,5,5,4,5,2,4,5,0,3,7,7,2,7,7,2,7,7,4,0,0,4,7,5,4,5,5, + 4,5,2,4,5,0,3,3,2,7,7,2,7,7,2,7,7,3,4,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4, + 5,5,4,2,4,6,3,0,1,1,1,7,7,2,2,7,7,7,2,7,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5, + 5,4,5,5,4,5,5,4,2,4,6,0,2,1,1,1,7,7,2,2,7,7,2,7,4,0,4,0,0,4,0,4,0,4,0, + 4,5,5,4,5,5,4,6,0,2,1,1,1,7,7,2,2,7,7,7,4,0,4,0,0,4,0,4,0,4,0,4,5,5,4, + 5,5,4,6,0,2,1,1,1,7,2,2,7,7,7,4,0,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,6,0, + 2,1,1,1,7,2,2,7,7,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,3,2,1,1,1,7,2,2,7,4, + 0,4,0,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,2,0,2,1,1,1,7, + 7,2,2,7,7,7,2,7,3,4,7,7,4,7,4,5,6,5,4,5,7,4,7,7,4,2,7,4,2,4,7,2,7,2,4, + 7,7,4,2,7,4,7,7,7,4,7,7,4,7,7,7,4,7,7,7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2, + 2,7,2,2,2,7,7,4,3,4,5,5,5,4,5,5,4,7,2,2,7,7,4,5,5,4,5,4,5,4,5,5,2,6,6, + 5,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,7,7,4,2,2,2,5,7,4, + 7,5,4,2,4,5,5,4,6,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2, + 6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4,2,4,7,7,4,7,2,2,7,2,7,7,4,7,7,4, + 5,5,4,2,7,4,7,7,7,4,5,5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4,6,4,2,6,7, + 7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5,5,5,4,2,4,5,7,5,4,5,4,6, + 5,4,5,5,4,2,2,7,2,2,2,4,5,5,4,7,2,7,4,2,2,2,2,7,2,2,2,2,2,7,2,2,2,2,2, + 4,0,0,4,5,0,2,4,0,0,4,5,0,2,4,0,4,0,0,4,2,5,5,4,3,4,7,4,7,4,7,5,4,7,4, + 5,5,4,5,2,4,5,0,3,3,5,5,6,6,5,2,6,7,6,5,7,7,7,4,5,4,0,0,4,2,3,4 }; static const unsigned short ag_key_parm[] = { - 0,396,393, 0, 4, 0, 6, 0, 0, 0, 0, 0,406, 90,132, 0, 0, 0, - 464, 0,427, 0,489,395,428, 0,396,393, 0,479,468, 0,461, 0,466,481, - 0,264,266,300, 0,268,110,302, 0, 38,172, 0,298, 0, 0,176, 0, 0, - 160, 42, 46, 0,180,182,270, 0,310,312, 0,316,318,320, 0,304,306,122, - 308, 0,314, 32,322, 0,184,286, 0,272,288, 0,138, 0, 30, 0, 0, 0, - 0, 0, 0,368,374, 0, 34,188, 0, 0, 44, 0,162,186, 40, 50, 0, 18, - 22, 0, 24, 0, 72, 0, 0, 0, 58, 56, 0, 0, 0, 66,192, 0, 0, 94, - 26, 0, 0, 68,120,132, 0, 98,102, 0,190,194, 0, 12,134,164, 0, 14, - 20, 0, 4, 0, 6, 0, 0, 92,274,290, 0, 16,324,130, 0,340, 0,346, - 0,342,352,350,344,354, 0,358,360, 0,332,348, 0,330, 0,326,336,334, - 338, 0,356, 0,328,362, 0,258, 0,366,372, 0,364, 0,370, 0,200, 0, - 376,198,196, 0, 0, 0, 84, 10, 0,126,136, 0, 0,100, 0, 0,124, 0, - 76,104,292, 0, 60, 0,116,276, 0, 86, 0, 74,294, 0, 80, 0,202,118, - 0, 62, 96, 0, 0,278, 36,378, 0,106,380, 0, 8, 70, 0, 54,262, 0, - 88,204,260, 0,168, 0, 0,206,208, 0,216,218, 0,224,226, 0,230,232, - 0,234,178, 0,236, 0,296, 0, 0,210,220,212,214, 0,222, 0,228, 0, - 0,238, 0,280,382, 0,244, 0,384,242,174,240, 0,112,114, 0,248, 0, - 256, 0,386,250, 64, 0,282,388, 0, 0, 2, 0,246,166,128, 0, 0, 82, - 0, 48, 78, 0,284,390, 0,252,108, 0,254, 0,170,406, 90,132,226,236, - 0,458, 0,472,462,470,158,144,146,148,150, 0, 0,152, 0, 0,154,156, - 0, 0, 0, 0, 0, 0, 28, 52, 0,423, 0,396,393, 0,406, 90,132, 0, - 0, 18, 22, 0, 0, 24, 26, 0, 14, 20, 0, 16, 4, 0, 30, 0, 0, 8, - 28, 0,396,393, 0,132,428, 0,158, 0,427, 0,396,393, 0,264,266,300, - 0,268,302, 0, 38,172, 0,298, 0, 0,176, 0, 0, 42, 46, 0,180,182, - 270, 0,310,312, 0,316,318,320, 0,304,306,308, 0,314, 32,322, 0,184, - 286, 0,272,288, 0,368,374, 0, 34,188, 0, 0, 44, 0, 0,186, 40, 50, - 0, 24, 0, 72, 0, 58, 56, 0, 0, 0, 66,192, 22, 0, 0, 0, 0,190, - 194, 0, 12, 0, 0,274,290, 0, 16,324, 0,340, 0,346, 0,342,352,350, - 344,354, 0,358,360, 0,332,348, 0,330, 0,326,336,334,338, 0,356, 0, - 328,362, 0,258, 0,366,372, 0,364, 0,370, 0,200, 0,376,198,196, 0, - 0, 0, 84, 10, 0, 0, 0, 0, 76,292, 0, 60,276, 0, 86, 0, 74,294, - 0, 80, 0,202, 0, 62, 0, 0,278, 36,378, 0, 0,380, 0, 54,262, 0, - 88,204,260, 70, 0, 0,206,208, 0,216,218, 0,224,226, 0,230,232, 0, - 234,178, 0,236, 0,296, 0, 0,210,220,212,214, 0,222, 0,228, 0, 0, - 238, 0,280,382, 0,244, 0,384,242,174,240, 0, 0, 0,256, 0,386,250, - 64, 0,282,388, 0, 0, 2, 0,246,248, 0, 0, 82, 0, 48, 78, 0,284, - 390, 0,252, 0,254, 0, 90,132,428, 0, 0, 0, 0, 0, 0, 68, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0,396,393, 0, 4, 0, 6, - 0, 0, 0, 0, 0, 0, 0, 0,427, 0,396,393, 0,264,266,300, 0,268, - 302, 0, 38,172, 0,298, 0, 0,176, 0, 0, 42, 46, 0,180,182,270, 0, - 310,312, 0,316,318,320, 0,304,306,308, 0,314, 32,322, 0,184,286, 0, - 272,288, 0,368,374, 0, 34,188, 0, 0, 44, 0, 0,186, 40, 50, 0, 24, - 0, 72, 0, 58, 56, 0, 0, 0, 66,192, 22, 0, 0, 0,190,194, 0, 12, - 0, 0, 4, 0, 6, 0, 0,274,290, 0, 16,324, 0,340, 0,346, 0,342, - 352,350,344,354, 0,358,360, 0,332,348, 0,330, 0,326,336,334,338, 0, - 356, 0,328,362, 0,258, 0,366,372, 0,364, 0,370, 0,200, 0,376,198, - 196, 0, 0, 0, 84, 10, 0, 0, 0, 0, 76,292, 0, 60,276, 0, 86, 0, - 74,294, 0, 80, 0,202, 0, 62, 0, 0,278, 36,378, 0, 0,380, 0, 54, - 262, 0, 88,204,260, 70, 0, 0,206,208, 0,216,218, 0,224,226, 0,230, - 232, 0,234,178, 0,236, 0,296, 0, 0,210,220,212,214, 0,222, 0,228, - 0, 0,238, 0,280,382, 0,244, 0,384,242,174,240, 0, 0, 0,256, 0, - 386,250, 64, 0,282,388, 0, 0, 0,246,248, 0, 0, 82, 0, 48, 78, 0, - 284,390, 0,252, 0,254, 0, 90,132,428, 0, 0, 0, 0, 0, 0, 68, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 90,132, 0,396,393, - 0, 0, 0,120,132, 0,126,136, 0,124, 0, 0, 90,132,226,122,138, 0, - 134,130, 0,118,128, 0, 12, 10, 0,396,393, 0, 4, 0, 6, 0, 0, 0, - 0, 0,406, 90,132,395, 0, 0, 0,395,428, 0,396,393, 0, 42, 46, 0, - 34, 0, 44, 40, 50, 0, 58, 56, 0, 0, 0, 66, 72, 0, 0, 0, 4, 0, - 6, 0, 0, 0, 0, 0, 84, 10, 0, 0, 76, 0, 86, 60, 74, 0, 62, 80, - 0, 88, 70, 54, 0, 2, 64, 82, 0, 48, 78, 0,427, 0, 0, 38, 0, 32, - 0, 0, 68, 12, 0, 0, 0, 0, 36, 0, 0, 0, 52,423, 0, 4, 0, 6, - 0, 0, 0, 0, 0, 0, 0,395,396, 0,396,393, 0,395, 0,423, 0,396, - 393, 0, 0, 92, 88, 0,396,393, 0,170, 0, 0,236,158,144,146,148,150, - 152,154,156, 0,160, 0,162, 0,164, 0,144,148,152,166, 0,160, 0,162, - 0,164, 0,158,144,148,152,168, 0,160, 0,162, 0,144,148, 0,464, 0, - 396,393, 0,479,468, 0,461, 0,466,481, 0,170,489,458, 0,472,462,470, - 0,464, 0,396,393, 0,479,468, 0,461, 0,466,481, 0, 98,102, 0,100, - 104, 0,112,114, 0, 0, 0,170,489,458, 0,472,462,470,110, 94, 0, 0, - 116, 96,106, 0,108, 0, 42, 46, 0, 34, 0, 44, 40, 50, 0, 58, 56, 0, - 0, 0, 66, 72, 0, 0, 84, 10, 0, 0, 76, 0, 86, 60, 74, 0, 62, 80, - 0, 88, 70, 54, 0, 64, 82, 0, 48, 78, 0,427,428, 38, 0, 32, 0, 0, - 68, 12, 0, 0, 0, 36, 0, 0, 0, 52, 0,396,393, 0,458, 0, 0,464, - 0,396,393, 0,479,468, 0,461, 0,466,481, 0, 98,102, 0,100,104, 0, - 106, 0,112,114, 0, 0, 0,170,489,458, 0,472,462,470,110, 94, 0, 0, - 116, 96,142,140, 0,108, 0,228, 0,464, 0,396,393, 0,479,468, 0,461, - 0,466,481, 0, 98,102, 0,100,104, 0,106, 0,112,114, 0, 0, 0,170, - 489,458, 0,472,462,470, 0, 0,116, 96,142,140, 0,108, 0,396,393, 0, - 120,132, 0,126,136, 0,124, 0, 0, 90,132,226,395, 0,122,138, 0,134, - 130, 0,118,128,423, 0,120,132, 0,126,136, 0,124, 0, 0, 90,132,226, - 122,138, 0,134,130, 0,128, 0,396,393, 0,120,132, 0,126,136, 0,124, - 0, 0, 90,132,226,395, 0,122,138, 0,134,130, 0,128,423, 0,464, 0, - 479,468, 0,461, 0,466,481, 0, 98,102, 0,100,104, 0,112,114, 0, 0, - 0,170,489,458,472,462,470,110, 94, 0, 0,116, 96,106, 0,108, 0,464, - 0,396,393, 0,479,468, 0,461, 0,466,481, 0, 98,102, 0,100,104, 0, - 112,114, 0, 0, 0,170,458, 0,472,462,470,110, 94, 0, 0, 96,106, 0, - 108, 0,464, 0,396,393, 0,468, 0,461, 0,466, 0, 98,102, 0,100,104, - 0,170,458, 0,472,462,470,110, 94, 0, 0, 96,106,108, 0,464, 0,396, - 393, 0,468, 0,461, 0,466, 0, 98,102, 0,100,104, 0,170,458, 0,472, - 462,470, 94, 0, 0, 96,106,108, 0,464, 0,396,393, 0,468, 0,461, 0, - 466, 0, 98,102, 0,100,104, 0,170,458, 0,472,462,470, 94, 0, 0, 96, - 106, 0,396,393, 0,468, 0,461, 0,466, 0, 98,102, 0,100,104, 0,464, - 0,472,462,470, 94, 0, 0, 96, 0,464, 0,489,395, 0,396,393, 0,479, - 468, 0,461, 0,466,481, 0, 98,102, 0,100,104, 0,112,114, 0, 0, 0, - 170, 0,458, 0,472,462,470,110, 94, 0, 0,116, 96,106, 0,108,423, 0, - 42, 46, 0, 34, 0, 44, 40, 50, 0, 58, 56, 0, 0, 0, 66, 72, 0, 0, - 0, 84, 10, 0, 0, 76, 0, 86, 60, 74, 0, 62, 80, 0, 88, 70, 54, 0, - 2, 64, 82, 0, 48, 78, 0,427,428, 38, 0, 32, 0, 0, 68, 12, 0, 0, - 0, 36, 0, 0, 0, 52, 0,226, 0,264,266,300, 0,268,302, 0,298, 0, - 0,176,172, 0,180,182,270, 0,310,312, 0,316,318,320, 0,304,306,308, - 0,314,322, 0,184,286, 0,272,288, 0,368,374, 0, 0, 0, 0,186,188, - 0,190,194, 0, 0, 0,274,290, 0,324, 0,340, 0,346, 0,342,352,350, - 344,354, 0,358,360, 0,332,348, 0,330, 0,326,336,334,338, 0,356, 0, - 328,362, 0,258, 0,366,372, 0,364, 0,370, 0,200, 0,376,198,196, 0, - 0, 0, 0, 0,292, 0,276,294, 0,278,378, 0, 0,380, 0,204,260,262, - 0,206,208, 0,216,218, 0,224,226, 0,230,232, 0,234,178, 0,236, 0, - 296, 0, 0,210,220,212,214, 0,222, 0,228, 0, 0,238, 0,280,382, 0, - 244, 0,384,242,174,240, 0, 0, 0,256, 0,386,250, 0,282,388, 0, 0, - 0,246,248, 0, 0, 0,284,390, 0,252, 0,254, 0, 0, 0, 0,192, 0, - 0, 0, 0, 0,202, 0, 0, 0, 0, 0, 0,396,393, 0, 90,132, 0, 0, - 396,393, 0,170,458, 0, 0,458, 0,396,393, 0, 0,142,140, 0,423, 0, - 122, 0,138, 0,120,132, 0,134, 0,126,136, 0,124, 0, 0, 90,132,226, - 236,158,144,146,148,150, 0,152,130,154,156,118,128, 0,170, 0,396,393, - 0, 0,423, 0 + 0,162,164,163, 0,429,426, 0, 4, 0, 6, 0, 0, 0, 0, 0,439, 96, + 135, 0, 0, 0, 0,500, 0,463, 0,525,428,464, 0,162,164,163, 0,429, + 426, 0,515,504, 0,497, 0,502,517, 0,280,282,322, 0,284,116,324, 0, + 44,182, 0,320, 0, 0,186, 0, 0,424,422, 0,430, 0,418, 0,166, 48, + 426, 0,428,416, 52,420, 0,190,192,286, 0,332,334, 0,338,340,342, 0, + 326,328,128,330, 0,336, 38,344, 0,194,306, 0,288,308, 0,144, 0, 36, + 0, 0, 0, 0, 0, 0,390,396, 0, 40,198, 0, 0, 50, 0,168,196, 46, + 56,176, 0, 24, 28, 0, 30, 0, 78, 14, 0, 0, 0, 18, 64, 0, 0, 62, + 0, 0, 0, 72,202, 0, 0,100, 32, 0, 0, 74,126,138, 0,104,108, 0, + 200,204, 0, 12,140,170, 0, 20, 26, 0, 4, 0, 6, 0, 0, 98,290,310, + 0, 22,346,136, 0,362, 0,368, 0,364,374,372,366,376, 0,380,382, 0, + 354,370, 0,352, 0,348,358,356,360, 0,378, 0,350,384, 0,270, 0,388, + 394, 0,386, 0,392,398, 0,210, 0,400,208,206, 0, 0, 0, 90, 10, 0, + 132,142, 0,276,278, 0,442, 0,106, 0, 0,444,130, 0, 0,266, 82,110, + 312, 0, 66, 0,122,292, 0, 92, 0, 80,314, 0, 86, 0,212,124, 0, 68, + 102, 0, 0,294, 42,402, 0,112,404, 0,214, 0, 8, 76, 0, 60,274, 0, + 94,178,272, 0,174, 0, 0,216,218, 0,432, 0,226,228, 0,234,236, 0, + 240,304,242, 0,244,188, 0,246, 0,318, 0, 0,220,230,222,224, 0,232, + 0,238, 0, 0,248, 0,440,436, 0,296,438,406, 0,434, 0,254, 0,408, + 252,184,250, 0,118,120, 0,302,258,316, 0,268, 0,410,260, 70, 0,298, + 412, 0, 0, 2, 0,256,172,134, 0, 0, 88, 0, 54, 84, 0,300,414, 0, + 262,114, 0,264, 0,180,439, 96,135,232,242, 0,494, 0, 0,508,498,506, + 164,150,152,154,156, 0, 0,158, 0, 0,160,162, 0, 0, 0, 0, 0, 0, + 34, 16, 58, 0,459, 0,162,164,163, 0,429,426, 0,439, 96,135, 0, 0, + 0, 24, 28, 0, 0, 30, 32, 0, 20, 26, 0, 22, 4, 0, 36, 0, 0, 8, + 34, 0,429,426, 0,135,464, 0,161, 0,463, 0,429,426, 0,280,282,322, + 0,284,324, 0, 44,182, 0,320, 0, 0,186, 0, 0,424,422, 0,430, 0, + 418, 0,166, 48,426, 0,428,416, 52,420, 0,190,192,286, 0,332,334, 0, + 338,340,342, 0,326,328,330, 0,336, 38,344, 0,194,306, 0,288,308, 0, + 390,396, 0, 40,198, 0, 0, 50, 0, 0,196, 46, 56, 0, 30, 0, 78, 14, + 0, 18, 64, 0, 0, 62, 0, 0, 0, 72,202, 28, 0, 0, 0, 0,200,204, + 0, 12, 0, 0,290,310, 0, 22,346, 0,362, 0,368, 0,364,374,372,366, + 376, 0,380,382, 0,354,370, 0,352, 0,348,358,356,360, 0,378, 0,350, + 384, 0,270, 0,388,394, 0,386, 0,392,398, 0,210, 0,400,208,206, 0, + 0, 0, 90, 10, 0,276,278, 0,442, 0, 0, 0,444, 0,266, 82,312, 0, + 66,292, 0, 92, 0, 80,314, 0, 86, 0,212, 0, 68, 0, 0,294, 42,402, + 0, 0,404, 0, 60,274, 0, 94,214,272, 76, 0, 0,216,218, 0,432, 0, + 226,228, 0,234,236, 0,240,304,242, 0,244,188, 0,246, 0,318, 0, 0, + 220,230,222,224, 0,232, 0,238, 0, 0,248, 0,440,436, 0,296,438,406, + 0,434, 0,254, 0,408,252,184,250, 0, 0, 0,302,258,316, 0,268, 0, + 410,260, 70, 0,298,412, 0, 0, 2, 0,256, 0, 0, 0, 88, 0, 54, 84, + 0,300,414, 0,262, 0,264, 0, 96,135,464, 0, 0, 0, 0, 0, 0, 74, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 58, 0, 0,429,426, 0, + 4, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0,463, 0,429,426, 0,280,282, + 322, 0,284,324, 0, 44,182, 0,320, 0, 0,186, 0, 0,424,422, 0,430, + 0,418, 0,166, 48,426, 0,428,416, 52,420, 0,190,192,286, 0,332,334, + 0,338,340,342, 0,326,328,330, 0,336, 38,344, 0,194,306, 0,288,308, + 0,390,396, 0, 40,198, 0, 0, 50, 0, 0,196, 46, 56, 0, 30, 0, 78, + 14, 0, 18, 64, 0, 0, 62, 0, 0, 0, 72,202, 28, 0, 0, 0,200,204, + 0, 12, 0, 0, 4, 0, 6, 0, 0,290,310, 0, 22,346, 0,362, 0,368, + 0,364,374,372,366,376, 0,380,382, 0,354,370, 0,352, 0,348,358,356, + 360, 0,378, 0,350,384, 0,270, 0,388,394, 0,386, 0,392,398, 0,210, + 0,400,208,206, 0, 0, 0, 90, 10, 0,276,278, 0,442, 0, 0, 0,444, + 0,266, 82,312, 0, 66,292, 0, 92, 0, 80,314, 0, 86, 0,212, 0, 68, + 0, 0,294, 42,402, 0, 0,404, 0, 60,274, 0, 94,214,272, 76, 0, 0, + 216,218, 0,432, 0,226,228, 0,234,236, 0,240,304,242, 0,244,188, 0, + 246, 0,318, 0, 0,220,230,222,224, 0,232, 0,238, 0, 0,248, 0,440, + 436, 0,296,438,406, 0,434, 0,254, 0,408,252,184,250, 0, 0, 0,302, + 258,316, 0,268, 0,410,260, 70, 0,298,412, 0, 0, 0,256, 0, 0, 0, + 88, 0, 54, 84, 0,300,414, 0,262, 0,264, 0, 96,135,464, 0, 0, 0, + 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 58, 0, + 0, 96,135, 0,429,426, 0, 0, 0,126,138, 0,132,142, 0,130, 0, 0, + 96,135,232,128,144, 0,140,136, 0,124, 94,134, 0, 14, 18, 0, 0, 12, + 10, 16, 0,162,164,163, 0,429,426, 0, 4, 0, 6, 0, 0, 0, 0, 0, + 439, 96,135,428, 0, 0, 0, 0,428,464, 0,429,426, 0, 48, 52, 0, 40, + 0, 50, 46, 56, 0, 78, 14, 0, 18, 64, 0, 0, 62, 0, 0, 0, 72, 0, + 0, 0, 0, 4, 0, 6, 0, 0, 0, 0, 0, 90, 10, 0, 0, 82, 0, 92, + 66, 80, 0, 68, 86, 0, 94, 76, 60, 0, 2, 70, 88, 0, 54, 84, 0,463, + 0, 0, 44, 0, 38, 0, 0, 74, 12, 0, 0, 0, 0, 42, 0, 0, 0, 16, + 58,459, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0,428,429, 0,429,426, + 0,428, 0,459, 0,429,426, 0, 0, 98, 94, 0,429,426, 0,180, 0, 0, + 166, 0,168,176, 0,170, 0,150,154,158,178,172, 0,242,164,150,152,154, + 156,158,160,162, 0,166, 0,168, 0,170, 0,150,154,158,172, 0,166, 0, + 168, 0,170, 0,164,150,154,158,174, 0,166, 0,168, 0,150,154, 0,500, + 0,429,426, 0,515,504, 0,497, 0,502,517, 0,180,525,494, 0,508,498, + 506, 0,500, 0,429,426, 0,515,504, 0,497, 0,502,517, 0,104,108, 0, + 106,110, 0,118,120, 0, 0, 0,180,525,494, 0,508,498,506,116,100, 0, + 0,122,102,112, 0,114, 0, 48, 52, 0, 40, 0, 50, 46, 56, 0, 78, 14, + 0, 18, 64, 0, 0, 62, 0, 0, 0, 72, 0, 0, 0, 90, 10, 0, 0, 82, + 0, 92, 66, 80, 0, 68, 86, 0, 94, 76, 60, 0, 70, 88, 0, 54, 84, 0, + 463,464, 44, 0, 38, 0, 0, 74, 12, 0, 0, 0, 42, 0, 0, 0, 16, 58, + 0,429,426, 0,494, 0, 0,500, 0,429,426, 0,515,504, 0,497, 0,502, + 517, 0,104,108, 0,106,110, 0,112, 0,118,120, 0, 0, 0,180,525,494, + 0,508,498,506,116,100, 0, 0,122,102,148,146, 0,114, 0,234, 0,500, + 0,429,426, 0,515,504, 0,497, 0,502,517, 0,104,108, 0,106,110, 0, + 112, 0,118,120, 0, 0, 0,180,525,494, 0,508,498,506, 0, 0,122,102, + 148,146, 0,114, 0,429,426, 0,126,138, 0,132,142, 0,130, 0, 0, 96, + 135,232,428, 0,128,144, 0,140,136, 0,124, 94,134,459, 0,126,138, 0, + 132,142, 0,130, 0, 0, 96,135,232,128,144, 0,140,136, 0, 94,134, 0, + 429,426, 0,126,138, 0,132,142, 0,130, 0, 0, 96,135,232,428, 0,128, + 144, 0,140,136, 0, 94,134,459, 0,500, 0,515,504, 0,497, 0,502,517, + 0,104,108, 0,106,110, 0,118,120, 0, 0, 0,180,525,494,508,498,506, + 116,100, 0, 0,122,102,112, 0,114, 0,500, 0,429,426, 0,515,504, 0, + 497, 0,502,517, 0,104,108, 0,106,110, 0,118,120, 0, 0, 0,180,494, + 0,508,498,506,116,100, 0, 0,102,112, 0,114, 0,500, 0,429,426, 0, + 504, 0,497, 0,502, 0,104,108, 0,106,110, 0,180,494, 0,508,498,506, + 116,100, 0, 0,102,112,114, 0,500, 0,429,426, 0,504, 0,497, 0,502, + 0,104,108, 0,106,110, 0,180,494, 0,508,498,506,100, 0, 0,102,112, + 114, 0,500, 0,429,426, 0,504, 0,497, 0,502, 0,104,108, 0,106,110, + 0,180,494, 0,508,498,506,100, 0, 0,102,112, 0,429,426, 0,504, 0, + 497, 0,502, 0,104,108, 0,106,110, 0,500, 0,508,498,506,100, 0, 0, + 102, 0,500, 0,525,428, 0,429,426, 0,515,504, 0,497, 0,502,517, 0, + 104,108, 0,106,110, 0,118,120, 0, 0, 0,180, 0,494, 0,508,498,506, + 116,100, 0, 0,122,102,112, 0,114,459, 0, 48, 52, 0, 40, 0, 50, 46, + 56, 0, 78, 14, 0, 18, 64, 0, 0, 62, 0, 0, 0, 72, 0, 0, 0, 0, + 90, 10, 0, 0, 82, 0, 92, 66, 80, 0, 68, 86, 0, 94, 76, 60, 0, 2, + 70, 88, 0, 54, 84, 0,463,464, 44, 0, 38, 0, 0, 74, 12, 0, 0, 0, + 42, 0, 0, 0, 16, 58, 0,232, 0,280,282,322, 0,284,324, 0,320, 0, + 0,186,182, 0,424,422, 0,430, 0,418, 0,166,426, 0,428,416,420, 0, + 190,192,286, 0,332,334, 0,338,340,342, 0,326,328,330, 0,336,344, 0, + 194,306, 0,288,308, 0,390,396, 0, 0, 0, 0,196,198, 0,200,204, 0, + 0, 0,290,310, 0,346, 0,362, 0,368, 0,364,374,372,366,376, 0,380, + 382, 0,354,370, 0,352, 0,348,358,356,360, 0,378, 0,350,384, 0,270, + 0,388,394, 0,386, 0,392,398, 0,210, 0,400,208,206, 0, 0, 0,276, + 278, 0,442, 0, 0,444, 0,266,312, 0,292,314, 0,294,402, 0, 0,404, + 0,214,272,274, 0,216,218, 0,432, 0,226,228, 0,234,236, 0,240,304, + 242, 0,244,188, 0,246, 0,318, 0, 0,220,230,222,224, 0,232, 0,238, + 0, 0,248, 0,440,436, 0,296,438,406, 0,434, 0,254, 0,408,252,184, + 250, 0, 0, 0,302,258,316, 0,268, 0,410,260, 0,298,412, 0, 0, 0, + 256, 0, 0, 0, 0,300,414, 0,262, 0,264, 0, 0, 0, 0, 0,202, 0, + 0, 0, 0, 0,212, 0, 0, 0, 0, 0, 0,429,426, 0, 96,135, 0, 0, + 429,426, 0,180,494, 0, 0,494, 0,429,426, 0, 0,148,146, 0,459, 0, + 128, 0,144, 0,126,138, 0,140, 0,132,142, 0,130, 0, 0, 96,135,232, + 242,164,150,152,154,156, 0,158,136,160,162,124, 94,134, 0,180, 0,429, + 426, 0, 0,459, 0 }; static const unsigned short ag_key_jmp[] = { - 0, 0, 0, 0, 0, 0, 4, 0, 6, 0, 8, 0, 0, 0, 0, 1, 10, 0, + 0, 0, 3, 7, 0, 0, 0, 0, 11, 0, 8, 0, 10, 0, 12, 0, 0, 0, + 0, 1, 5, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 24, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 17, 0, 10, 37, 41, 12, 45, 0, - 0, 19, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 29, - 58, 62, 65, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 0, 86, 0, - 88, 0, 90, 35, 37, 0, 39, 41, 0, 78, 0, 81, 92, 0, 96, 0, 0, 46, - 48, 0, 50, 0,110, 0, 0, 0, 56, 59, 0,116, 0, 43, 0,107,112,114, - 52,119, 0, 61, 64, 0, 0, 0, 0, 0, 73, 0, 0, 68, 70,136, 0, 76, - 79, 0, 83, 0,146, 0,148, 86, 0, 0, 0,143,150, 0, 0, 0, 0, 0, - 0, 0, 0, 0,161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 159,163,169,172,175, 0, 0, 0, 0, 0, 0, 0,187,189, 90, 0, 0, 0, - 196, 0, 0, 0,198, 0, 92, 94, 0, 0, 0, 0,192, 0,202,204, 0,207, - 96, 0,102, 0,109, 0,220, 0, 0,104,222,112,118, 0,123, 0,230, 0, - 0,120, 0,232, 0, 0, 0, 0, 0,239,126, 0,136,140, 0,146,150, 0, - 128,131,134,246,144,249, 0, 0, 0, 0, 0,159, 0, 0, 0, 0, 0, 0, - 0, 0,161, 0, 0, 0,274, 0,259, 0,152,155,157,262, 0,265,268,271, - 276, 0, 0, 0, 0, 0, 0, 0,294, 0, 0, 0, 0,296, 0, 0,167, 0, - 0, 0,306, 0,172, 0, 0, 0, 0,291,163,301,165,304,169,308,312,175, - 0,177,180, 0, 0, 0, 0,193,196,328,198, 0, 18, 0, 20, 0, 3, 6, - 22, 0, 26, 29, 32, 34, 48, 54, 69, 99,121,129,133,139,155,177,210,225, - 235,243,252,278,315,325,184,189,331,201, 0, 0, 0, 0, 0, 0, 0,371, - 0,209,211, 0,379,213,217, 0,221,224, 0,386,228, 0,203,382,389,234, - 240, 0, 0, 0, 0, 0,245,398, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,254,256, 0,249,411,415,251,418, 0,258,262, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,265, 0,430,434,437,268, 0, 0, 0, - 0, 0, 0, 0, 0,271,273, 0,275,277, 0,449, 0,452,455, 0,458, 0, - 0,285, 0,469, 0,289,292, 0,473, 0,279, 0,282,471,287,476, 0,300, - 0, 0,298,485, 0, 0, 0, 0, 0,491, 0, 0, 0, 0, 0, 0, 0, 0, - 499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,497,501,507,510, - 513, 0, 0, 0, 0, 0, 0, 0,525,527,303, 0, 0, 0,534, 0, 0, 0, - 536, 0,305,307, 0,530,540,542,309,315, 0,322, 0, 0,317,551,326,332, - 0,337, 0,559, 0,334,561, 0, 0, 0, 0, 0,566,340, 0,355,359, 0, - 342,345,348,350,573, 0, 0, 0, 0, 0,368, 0, 0, 0, 0, 0, 0, 0, - 0,370, 0, 0, 0,597, 0,582, 0,361,364,366,585, 0,588,591,594,599, - 0, 0, 0, 0, 0, 0, 0,617, 0, 0, 0, 0,619, 0, 0, 0,626, 0, - 379, 0, 0, 0, 0,614,372,624,374,376,628,632,382, 0,384,387, 0, 0, - 0, 0,395,647,398, 0,406, 0,247,408,421,427,441,461,478,294,488,494, - 515,545,554,563,570,576,601,635,644,391,650, 0, 0, 0, 0,401, 0,681, - 0,683, 0,685, 0,678,687, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,411,413, 0,406,697,701,408,704, 0,415,419, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,422, 0,716,720,723,425, 0, 0, 0, 0, 0, - 0, 0, 0,428,430, 0,432,434, 0,735, 0,738,741, 0,744, 0, 0,442, - 0,755, 0,444,447, 0,759, 0,436, 0,439,757,762, 0,455, 0, 0,453, - 770, 0,458, 0,776, 0,778, 0, 0, 0, 0,780, 0, 0, 0, 0, 0, 0, - 0, 0,789, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,787,791, - 797,800,803, 0, 0, 0, 0, 0, 0, 0,815,817,461, 0, 0, 0,824, 0, - 0, 0,826, 0,463,465, 0,820,830,832,467,473, 0,480, 0, 0,475,841, - 484,490, 0,495, 0,849, 0,492,851, 0, 0, 0, 0, 0,856,498, 0,513, - 517, 0,500,503,506,508,863, 0, 0, 0, 0, 0,526, 0, 0, 0, 0, 0, - 0, 0, 0,528, 0, 0, 0,887, 0,872, 0,519,522,524,875, 0,878,881, - 884,889, 0, 0, 0, 0, 0, 0, 0,907, 0, 0, 0, 0,909, 0, 0, 0, - 916, 0,535, 0, 0, 0, 0,904,914,530,532,918,922,538, 0,540,543, 0, - 0, 0, 0,551,936,554, 0,692, 0,404,694,707,713,727,747,764,449,773, - 784,805,835,844,853,860,866,891,925,933,547,939, 0, 0, 0, 0, 0, 0, - 0,970, 0,571, 0, 0, 0, 0, 0, 0,978, 0, 0, 0,557,560,564,975, - 575,579,981,581,584, 0,588,591, 0, 0, 0, 0,597, 0,1002, 0,1004, - 0,1006, 0, 0, 0, 0,595,999,1008, 0, 0, 0, 0, 0, 0, 0,606, - 610, 0,617, 0, 0,1026, 0, 0,626,629, 0,1032, 0,619,622,624,1035, - 0,638, 0,1042, 0,1044, 0,1046, 0,641,643, 0,1050,645, 0,651,656, - 661, 0,667,670, 0,678,681,686, 0,691,693,697, 0,699,702, 0,600,1017, - 1020,602,1023,613,1028,1037,631,635,1048,1053,1056,1060,675,1063,1067, - 1071,706,710, 0,712, 0,1095, 0,1097, 0,1099, 0,1101, 0,715,717, 0, - 0, 0, 0,719,1108,721, 0, 0, 0, 0,1115,723,729, 0, 0, 0, 0, - 0,1122, 0,733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0,1138,1140,1142,737, 0, 0, 0, 0, 0, 0, 0, 0,1149,1151,1153, - 739, 0, 0, 0, 0, 0,1161,1163, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,1168,742, 0,1170,1173,1176,1178, 0, 0, 0, 0, 0, + 37, 39, 0, 32, 46, 50, 34, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, + 0, 63, 66, 68, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 0, 51, 79, 83, 86, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, + 0,107, 0,109, 0,111, 57, 59, 0, 61, 63, 0, 99, 0,102,113, 0,117, + 0, 0, 0, 68, 70, 0, 72, 0,132, 74, 0, 0, 0, 81, 85, 0,139, 87, + 0,142, 0, 65, 0,129,134,137, 77,145, 0, 89, 92, 0, 0, 0, 0, 0, + 101, 0, 0, 96, 98,162, 0,104,107, 0,111, 0,172, 0,174,114, 0, 0, + 0,169,176, 0, 0, 0, 0, 0, 0, 0, 0, 0,187, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,185,189,195,198,201, 0, 0, 0, 0, 0, + 0, 0,213,215,122,124, 0, 0, 0,223, 0, 0, 0,225, 0,126,128, 0, + 0, 0, 0,133,135, 0,118,218, 0,229,231,130, 0,234,237,138,141, 0, + 147, 0,154, 0,254, 0, 0,149,256,157,163, 0,168, 0,264, 0, 0,165, + 0,266, 0, 0, 0, 0, 0,273,171, 0,176, 0,180,184, 0,190,194, 0, + 173,280,178,282,188,285, 0, 0, 0, 0,196, 0, 0,206, 0, 0, 0, 0, + 0, 0, 0, 0, 0,208, 0, 0, 0,313, 0,295,298,199,202,204,300, 0, + 303,306,310,315, 0, 0, 0, 0, 0, 0, 0, 0,330, 0, 0, 0, 0,339, + 0, 0, 0, 0,341, 0, 0, 0,214, 0, 0, 0, 0,353, 0,219, 0, 0, + 0, 0,333,210,346,212,349,216,355,359,222, 0,224,227, 0, 0, 0, 0, + 247,250,375,252, 0, 23, 0, 25, 0, 14, 17, 27, 0, 31, 35, 38, 41, 43, + 57, 70, 90,120,147,155,159,165,181,203,240,259,269,277,288,317,362,372, + 231,236,243,378,255, 0,257,260,264, 0, 0, 0, 0, 0, 0, 0,420,424, + 0,274,276, 0,433,278,282, 0,286,289, 0,440,293, 0,268,436,443,299, + 305, 0, 0, 0, 0, 0,310,452, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,319,321, 0,314,465,469,316,472, 0, 0, 0, 0, 0, 0, + 0, 0, 0,323, 0,481,484,486,327, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,330, 0,497,501,504,333, 0, 0, 0, 0, 0, 0, 0, 0, + 336,338, 0,340,342, 0,516, 0,519,522, 0,525, 0, 0,350, 0,536,352, + 0,357,361, 0,541,363, 0,544, 0,344, 0,347,538,355,547, 0,371, 0, + 0,369,556, 0, 0, 0, 0, 0,562, 0, 0, 0, 0, 0, 0, 0, 0,570, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,568,572,578,581,584, + 0, 0, 0, 0, 0, 0, 0,596,598,378,380, 0, 0, 0,606, 0, 0, 0, + 608, 0,382,384, 0,389,391, 0,374,601,612,614,386,617,394,397,403, 0, + 410, 0, 0,405,630,414,420, 0,425, 0,638, 0,422,640, 0, 0, 0, 0, + 0,645,428, 0,443,447, 0,430,433,436,438,652, 0, 0, 0, 0,449, 0, + 0,459, 0, 0, 0, 0, 0, 0, 0, 0, 0,461, 0, 0, 0,679, 0,661, + 664,452,455,457,666, 0,669,672,676,681, 0, 0, 0, 0, 0, 0, 0, 0, + 696, 0, 0, 0, 0,705, 0, 0, 0, 0,707, 0, 0,467, 0, 0, 0, 0, + 718, 0,469, 0, 0, 0, 0,699,463,712,465,714,720,724,472, 0,474,477, + 0, 0, 0, 0,492,739,495, 0,460, 0,312,462,475,488,508,528,549,365, + 559,565,586,620,633,642,649,655,683,727,736,481,488,742, 0, 0, 0, 0, + 498, 0,774, 0,776, 0,778, 0,771,780, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,508,510, 0,503,790,794,505,797, 0, 0, 0, 0, 0, + 0, 0, 0, 0,512, 0,806,809,811,516, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,519, 0,822,826,829,522, 0, 0, 0, 0, 0, 0, 0, + 0,525,527, 0,529,531, 0,841, 0,844,847, 0,850, 0, 0,539, 0,861, + 541, 0,544,548, 0,866,550, 0,869, 0,533, 0,536,863,872, 0,558, 0, + 0,556,880, 0,561, 0,886, 0,888, 0, 0, 0, 0,890, 0, 0, 0, 0, + 0, 0, 0, 0,899, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 897,901,907,910,913, 0, 0, 0, 0, 0, 0, 0,925,927,568,570, 0, 0, + 0,935, 0, 0, 0,937, 0,572,574, 0,579,581, 0,564,930,941,943,576, + 946,584,587,593, 0,600, 0, 0,595,959,604,610, 0,615, 0,967, 0,612, + 969, 0, 0, 0, 0, 0,974,618, 0,633,637, 0,620,623,626,628,981, 0, + 0, 0, 0,639, 0, 0,649, 0, 0, 0, 0, 0, 0, 0, 0, 0,651, 0, + 0, 0,1008, 0,990,993,642,645,647,995, 0,998,1001,1005,1010, 0, 0, + 0, 0, 0, 0, 0, 0,1025, 0, 0, 0, 0,1034, 0, 0, 0, 0,1036, + 0, 0,655, 0, 0, 0, 0,1047, 0,657, 0, 0, 0, 0,1028,1041,653, + 1043,1049,1053,660, 0,662,665, 0, 0, 0, 0,680,1067,683, 0,785, 0, + 501,787,800,813,833,853,874,552,883,894,915,949,962,971,978,984,1012,1056, + 1064,669,676,1070, 0, 0, 0, 0, 0, 0, 0,1102, 0,700, 0, 0, 0, + 0, 0, 0,1110, 0, 0, 0,686,689,693,1107,704,708,1113,710,713,717, + 0,721,725, 0,1129,732,735,739, 0,748,751,755, 0, 0, 0, 0,759, 0, + 1144, 0,1146, 0,1148, 0, 0, 0, 0,746,1137,1141,1150, 0, 0, 0, + 0, 0, 0, 0,768,772, 0,779, 0, 0,1169, 0, 0, 0,784, 0,789,793, + 0,1178,795, 0,1181, 0,781,1175,787,1184, 0,804, 0,1191, 0,1193, + 0,1195, 0,807,809, 0,1199,811, 0,817,822,827, 0,833,836, 0,844, + 847,852, 0,857,859,863, 0,865,868, 0,762,1160,1163,764,1166,775,1171, + 1186,797,801,1197,1202,1205,1209,841,1212,1216,1220,872,879,883, 0,885, + 0,1245, 0,1247, 0,1249, 0,1251, 0,888,890, 0, 0, 0, 0,892,1258, + 894, 0, 0, 0, 0,1265,896,902, 0, 0, 0, 0, 0,1272, 0, 0, 0, + 0, 0, 0, 0, 0,1278,1280,1283,906,908, 0,910, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1301,1303,1305,914, 0, 0, 0, + 0, 0, 0, 0, 0,1312,1314,1316,916, 0, 0, 0, 0, 0,1324,1326, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1331,919, 0,1333, + 1336,1339,1341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1371, 0,1352,921, 0,1354,1357,1360, + 1362,923,926,1365,1368,928,931,933,1374,935, 0,946,950, 0,957, 0, 0, + 1396, 0, 0, 0,962, 0,965,969, 0,1405,971, 0,1408, 0,959,1402,1411, + 0,980,982, 0,1417,984, 0,990,995,1000, 0,1006,1009, 0,1017,1020, + 1025, 0,1030,1034, 0,1036,1039, 0,938,940,942,1393,953,1398,1413,973, + 977,1420,1423,1427,1014,1430,1434,1437,1043,1050, 0, 0, 0, 0, 0,1459, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1208, 0,1189,744, 0,1191,1194,1197,1199,746,749,1202,1205,751,754,756, - 1211,758, 0,769,773, 0,780, 0, 0,1233, 0, 0,787,790, 0,1239, 0, - 782,785,1242, 0,799,801, 0,1248,803, 0,809,814,819, 0,825,828, 0, - 836,839,844, 0,849,853, 0,855,858, 0,761,763,765,1230,776,1235,1244, - 792,796,1251,1254,1258,833,1261,1265,1268,862, 0, 0, 0, 0, 0,1289, + 0, 0, 0, 0, 0, 0, 0,1486, 0,1465,1054, 0,1467,1470,1473,1475, + 1056,1059,1478,1481,1061,1064,1484, 0,1489,1066, 0,1069, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,1316, 0,1295,866, 0,1297,1300,1303,1305, - 868,871,1308,1311,873,876,1314, 0,1319,878, 0,881, 0, 0, 0, 0, 0, + 0, 0, 0, 0,1532, 0,1511,1071, 0,1513,1516,1519,1521,1524,1527,1073, + 1076,1530, 0,1535,1078, 0, 0, 0, 0,1097, 0, 0, 0, 0, 0, 0,1559, + 0, 0, 0,1081,1084,1553,1086,1090,1556,1101,1105,1562,1107,1110,1114, + 1118, 0,1134, 0, 0, 0, 0, 0, 0,1584, 0, 0, 0,1120,1123,1127, + 1581,1138,1142,1587,1144,1148, 0, 0, 0, 0,1168, 0, 0, 0, 0, 0, + 0,1608, 0, 0, 0,1152,1155,1602,1157,1161,1605,1172,1176,1611,1178, + 1182,1186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,1645, 0,1629,1188, 0,1631,1634,1636,1190,1193,1639, + 1642,1195,1198,1200,1648,1202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1685, 0,1666, 0, + 1668,1671,1674,1676,1205,1208,1679,1682,1210,1212,1688,1214, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1705, 0,1707, + 1710,1712,1714,1217,1220,1716,1719,1222,1224,1226, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1736, 0,1738,1741, + 1743,1745,1229,1747,1750,1231,1233,1235, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1766, 0,1768,1771,1773,1775,1238, + 1777,1780,1240,1242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1244,1795,1798,1800,1802,1246,1804,1807,1248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,1362, 0,1341,883, 0,1343,1346,1349,1351,1354,1357,885,888,1360, - 0,1365,890, 0, 0, 0, 0,909, 0, 0, 0, 0, 0, 0,1389, 0, 0, - 0,893,896,1383,898,902,1386,913,917,1392,919,922,926, 0,942, 0, 0, - 0, 0, 0, 0,1413, 0, 0, 0,928,931,935,1410,946,950,1416,952, 0, - 0, 0, 0,972, 0, 0, 0, 0, 0, 0,1436, 0, 0, 0,956,959,1430, - 961,965,1433,976,980,1439,982,986, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1472, 0,1456,988, 0,1458, - 1461,1463,990,993,1466,1469,995,998,1000,1475,1002, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1512, 0,1493, 0,1495,1498,1501,1503,1005,1008,1506,1509,1010,1012,1515, - 1014, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0,1532, 0,1534,1537,1539,1541,1017,1020,1543,1546,1022,1024,1026, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1563, - 0,1565,1568,1570,1572,1029,1574,1577,1031,1033,1035, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1593, 0,1595, - 1598,1600,1602,1038,1604,1607,1040,1042, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1044,1622,1625,1627,1629,1046,1631,1634, - 1048, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1669, 0,1647,1649, 0,1652,1655,1658, - 1660,1050,1053,1663,1666,1055,1058,1060,1672,1062,1065, 0,1075,1079, 0, - 1086, 0, 0,1695, 0, 0,1095,1098, 0,1701, 0,1088,1091,1093,1704, 0, - 1107,1109, 0,1711,1111, 0,1117,1122,1127, 0,1133,1136, 0,1144,1147, - 1152, 0,1157,1159,1163, 0,1165,1168, 0,1067,1069,1071,1692,1082,1697, - 1706,1100,1104,1714,1717,1721,1141,1724,1728,1732,1172, 0,1176, 0, 0, - 0, 0, 0, 0, 0, 0,1179,1755,1759,1181,1184, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1187, 0,1768,1772,1775, 0, 0, 0, 0, 0, 0, - 0, 0,1190,1192, 0,1786,1789,1792, 0,1194, 0,1199, 0, 0,1801, 0, - 0, 0, 0,1806, 0, 0, 0, 0, 0, 0, 0, 0,1813, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1811,1815,1821,1824,1827, 0, 0, 0, - 0, 0, 0, 0,1839,1841,1202, 0, 0, 0,1848, 0, 0, 0,1850, 0,1844, - 1854,1204, 0,1206,1208, 0, 0, 0, 0,1863,1213, 0,1215,1218,1220, 0, - 0, 0, 0, 0,1230, 0, 0, 0, 0, 0, 0, 0, 0,1232, 0, 0, 0, - 1888, 0,1873, 0,1223,1226,1228,1876, 0,1879,1882,1885,1890, 0, 0, - 0, 0, 0, 0, 0,1908, 0, 0, 0, 0,1910, 0, 0, 0,1917, 0, 0, - 0, 0, 0,1905,1915,1234,1236,1919,1922, 0, 0, 0, 0,1239,1932,1242, - 0,1762,1779,1795,1197,1804,1809,1829,1856,1860,1210,1866,1869,1892,1925, - 1935, 0, 0, 0, 0, 0, 0,1955, 0, 0, 0, 0, 0, 0,1962, 0, 0, - 0, 0, 0, 0,1971, 0, 0, 0,1245, 0,1254, 0,1257, 0,1263, 0, 0, - 1267, 0, 0, 0, 0, 0,1989, 0, 0, 0,1247,1250, 0, 0,1980,1982, - 0,1984,1987,1270,1992, 0,1272,1275, 0, 0, 0, 0, 0, 0,2014,1279, - 0 + 0, 0, 0, 0,1842, 0,1820,1822, 0,1825,1828,1831,1833,1250,1253,1836, + 1839,1255,1258,1260,1845,1262,1265, 0,1275,1279, 0,1286, 0, 0,1868, + 0, 0, 0,1291, 0,1296,1300, 0,1877,1302, 0,1880, 0,1288,1874,1294, + 1883, 0,1311,1313, 0,1890,1315, 0,1321,1326,1331, 0,1337,1340, 0, + 1348,1351,1356, 0,1361,1363,1367, 0,1369,1372, 0,1267,1269,1271,1865, + 1282,1870,1885,1304,1308,1893,1896,1900,1345,1903,1907,1911,1376,1383, + 0,1387, 0, 0, 0, 0, 0, 0, 0, 0,1390,1935,1939,1392,1395, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1948,1951,1953, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1398, 0,1962,1966,1969, 0, 0, 0, 0, + 0, 0, 0, 0,1401,1403, 0,1980,1983,1986, 0,1405, 0,1410, 0, 0, + 1995, 0, 0, 0, 0,2000, 0, 0, 0, 0, 0, 0, 0, 0,2007, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2005,2009,2015,2018,2021, 0, + 0, 0, 0, 0, 0, 0,2033,2035,1417,1419, 0, 0, 0,2043, 0, 0, 0, + 2045, 0,1424,1426, 0,1413,2038,2049,1421,2051,1429,1432, 0,1434,1436, + 0, 0, 0, 0,2065,1441, 0,1443,1446,1448, 0, 0, 0, 0,1451, 0, + 0,1461, 0, 0, 0, 0, 0, 0, 0, 0, 0,1463, 0, 0, 0,2093, 0, + 2075,2078,1454,1457,1459,2080, 0,2083,2086,2090,2095, 0, 0, 0, 0, + 0, 0, 0, 0,2110, 0, 0, 0, 0,2119, 0, 0, 0, 0,2121, 0, 0, + 1467, 0, 0, 0, 0,2132, 0, 0, 0, 0, 0,2113,2126,1465,2128,2134, + 2137, 0, 0, 0, 0,1469,2147,1472, 0,1942,1955,1973,1989,1408,1998, + 2003,2023,2054,2062,1438,2068,2071,2097,2140,2150, 0, 0, 0, 0, 0, + 0,2171, 0, 0, 0, 0, 0, 0,2178, 0, 0, 0, 0, 0, 0,2187, 0, + 0, 0,1475, 0,1484, 0,1487, 0,1493, 0, 0,1497, 0, 0, 0, 0, 0, + 2205, 0, 0, 0,1477,1480, 0, 0,2196,2198, 0,2200,2203,1500,2208, 0, + 1502,1505,1509, 0, 0, 0, 0, 0, 0,2231,1513, 0 }; static const unsigned short ag_key_index[] = { - 12,336,374,392,401,392,654, 0,689,654,943,374,967,967, 0,973,973,967, - 984,984,967,996, 0,967,967, 0,973,973,967,984,984,967,996, 0,1010,1074, - 1103,1105,1111, 0,1105, 0, 0,654,1118,1125,1125,1125,1125,1125,1125, - 1125,1125,1125,1125,1125,1125,1125,1125,1128,1144,984,984,984,984,984, - 984,984,984,984,984,984,984,984,984,984,1125,1125,1125,1125,1125,1125, - 1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125, - 1125,1125,1125,1125,1125,1125,1125,1125, 0,1128,1144,984,984,984,984, - 984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984, - 984,984,984,984,984,984,984,984,984,984,1155,1155,1165,1165,1144,1144, - 1144,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128, 0, 0, 0, - 984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984, - 984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984, - 1155,1155,1165,1165,1144,1144,1144,1128,1128,1128,1128,1128,1128,1128, - 1128,1128,1128,1128,1181,1125,1213,973,1125,984,1271,973, 0, 0,973, 0, - 1292,973,973,973,973, 0, 0, 0,1213,1321, 0,1339,1213, 0,1213,1213, - 1213,1367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1213,1213,1395, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1419,1442,1419,1442,984,1419,1419,1419, - 1419,1213,1477,1517,1517,1549,1580,1610,1637,984,973,973,973,973,973,973, - 973, 0,973,973,973, 0, 0,1111,1395,1111,1395,1105,1111,1111,1111,1111, - 1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111, - 1111,1442,1395,1395,1395,1442,1674,1111,1395,1442,1111,1105,1111,1111, - 1010, 0, 0, 0,1735,973,1118,1128,1144, 0, 0, 0,984,984,984,984,984, - 984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984, - 984,984,984,984,984,984,984,984,984,984,984,984,984,1155,1155,1165,1165, - 1144,1144,1144,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128, - 984,1753,1939,1939,973,967,967, 0, 0,973,973, 0, 0,973,973,1958,1958, - 0, 0,984,984,984,984,984,984,967,967,967,967,967,967,967,967,967,967, - 984,984,984,984,984,984,984,984,984,984,973,984,984,984,984,1118,1118, - 973, 0, 0,973, 0,973,973, 0, 0,1339,1213,1213, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,984, 0,1419,1419,1419,1419,1419,1419,1419,984,984, - 984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984,984, - 984,984,984,984,984,984,984,984,984,984,984,984,973,973,973,973,973, 0, - 973,973, 0,973,973,973,984,984,984,984,973,973,973,1965,1125,984,984, - 1125,1125,1969,1339,1339,1292,1969, 0,1974,1939,1339, 0,984,1292,1292, - 1292,1292,1292, 0, 0,1978, 0, 0, 0, 0,967,984,984,984,984,984,984, - 984,984,984, 0,1419,1419,1419,1419,1419,984,984,984,984,984,984,984,984, - 984,984,984,984,973,973,973,973,973,973,984,984,1969,1339,1995,984,2012, - 1125,1339,984,1292,967,2017,2017,973, 0, 0,967, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,1477,1477,1517,1517,1517,1517,1517,1517,1549,1549,1580, - 1580,973,973,1128,1339,984,984,967, 0, 0, 0,1128, 0 + 16,383,427,446,455,446,746, 0,782,746,1074,427,1099,1099, 0,1105,1105, + 1099,1116,1116,1099,1132, 0,1099,1099, 0,1105,1105,1099,1116,1116,1099, + 1132, 0,1152,1223,1253,1255,1261, 0,1255, 0, 0,746,1268,1275,1275, + 1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1285,1291, + 1307,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, + 1116,1116,1116,1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1275, + 1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1275, + 1275,1275,1275,1275, 0,1285,1291,1307,1116,1116,1116,1116,1116,1116,1116, + 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, + 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, + 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1318, + 1318,1318,1318,1328,1328,1307,1307,1307,1285,1285,1291,1291,1291,1291, + 1291,1291,1291,1291,1291,1291,1291, 0, 0, 0, 0,1116,1116,1116,1116, + 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, + 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, + 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, + 1116,1116,1116,1116,1116,1116,1318,1318,1318,1318,1328,1328,1307,1307, + 1307,1285,1285,1291,1291,1291,1291,1291,1291,1291,1291,1291,1291,1291, + 1344,1275,1376,1105,1275,1116,1440,1105, 0, 0,1105, 0,1462,1105,1105, + 1105,1105, 0, 0, 0,1376,1491, 0,1509,1376, 0,1376,1376,1376,1537, + 0,1105, 0, 0, 0, 0, 0, 0, 0, 0, 0,1376,1376,1565, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1590,1614,1590,1614,1116,1590,1590,1590, + 1590,1376,1650,1690,1690,1722,1753,1783,1810,1116,1105,1105,1105,1105, + 1105,1105,1105,1099,1099,1105,1105,1105,1105, 0,1105,1105,1105, 0, 0, + 1261,1565,1261,1565,1255,1261,1261,1261,1261,1261,1261,1261,1261,1261, + 1261,1261,1261,1261,1261,1261,1261,1261,1261,1261,1614,1565,1565,1565, + 1614,1847,1261,1565,1614,1261,1255,1261,1261,1152, 0, 0, 0,1914,1105, + 1268,1285,1291,1307, 0, 0, 0, 0,1116,1116,1116,1116,1116,1116,1116, + 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, + 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, + 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, + 1116,1116,1116,1318,1318,1318,1318,1328,1328,1307,1307,1307,1285,1285, + 1291,1291,1291,1291,1291,1291,1291,1291,1291,1291,1291,1116,1933,2154, + 2154,1099,1099, 0, 0,1105,1105, 0, 0,1105,1105,2174,2174, 0, 0,1116, + 1116,1116,1116,1116,1116,1099,1099,1099,1099,1099,1099,1099,1099,1099, + 1099,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1105,1116,1116, + 1116,1116,1099,1268,1268,1105, 0, 0,1105, 0,1105,1105, 0, 0,1509, + 1376,1376, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1116, 0,1590,1590, + 1590,1590,1590,1590,1590,1116,1116,1116,1116,1116,1116,1116,1116,1116, + 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, + 1116,1116,1116,1116,1116,1116,1116,1116,1116,1105,1105,1105,1105,1105, + 1099,1105,1105, 0,1105,1105, 0,1105,1105,1105,1116,1116,1116,1116,1105, + 1105,1105,1275,1275,1275,2181,1275,1116,1116,1116,1275,1275,2185,1509, + 1509,1462,2185, 0,2190,2154,1509, 0,1116,1462,1462,1462,1462,1462, 0, + 0,2194, 0, 0, 0, 0,1099,1116,1116,1116,1116,1116,1116,1116,1116, + 1116,1116, 0,1590,1590,1590,1590,1590,1116,1116,1116,1116,1116,1116,1116, + 1116,1116,1116,1116,1116,1105,1105,1105,1105,1105,1105,1105,1116,1116, + 1116,2185,1509,2211,1116,2229,1275,1509,1116,1462,1099,2234,2234,1105, + 0, 0,1099, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1650,1650,1690, + 1690,1690,1690,1690,1690,1722,1722,1753,1753,1105,1105,1105,1291,1509, + 1116,1116,1099, 0, 0, 0,1291, 0 }; static const unsigned char ag_key_ends[] = { -68,69,0, 92,39,0, 72,76,41,0, 73,0, 72,76,0, 71,0, 82,0, +83,83,0, 65,84,65,0, 69,88,84,0, 68,69,0, 92,39,0, 72,76,41,0, +83,83,0, 65,84,65,0, 69,88,84,0, 73,0, 72,76,0, 71,0, 82,0, 79,67,75,0, 84,69,0, 76,76,0, 73,76,0, 69,71,0, 76,0, 80,0, -71,0, 66,0, 72,79,0, 70,0, 69,0, 70,0, 82,79,82,0, 82,78,0, -78,0, 76,76,0, 79,79,82,0, 88,0, 71,72,0, 66,67,0, 69,70,0, -68,69,70,0, 68,69,0, 65,71,69,0, 73,0, 75,0, 84,0, +71,0, 66,0, 72,79,0, 70,0, 69,0, 70,0, 82,89,0, 82,79,82,0, +68,69,68,0, 78,0, 78,0, 76,76,0, 79,79,82,0, 88,0, 71,72,0, +66,67,0, 69,70,0, 68,69,70,0, 68,69,0, 65,71,69,0, 65,76,76,0, +73,0, 73,0, 75,0, 84,0, 77,80,0, 80,0, 83,72,0, 69,84,0, 70,73,82,83,84,0, 73,0, 67,76,73,66,0, 76,69,0, 70,73,82,83,84,0, -73,0, 77,69,0, 71,69,0, 84,0, 71,69,0, 72,76,0, 80,0, -71,77,65,0, 78,84,70,0, 87,0, 76,73,67,0, 72,0, 69,76,0, 84,0, +73,0, 77,69,0, 71,69,0, 84,0, 71,69,0, 76,0, 80,0, 71,77,65,0, +78,84,70,0, 87,0, 76,73,67,0, 72,0, 76,76,0, 69,76,0, 84,0, 77,0, 69,0, 76,0, 84,0, 77,0, 76,0, 82,84,0, 76,78,0, 77,0, -88,84,0, 84,76,69,0, 78,68,69,70,0, 79,82,68,0, 72,71,0, 82,0, -72,76,0, 10,0, 69,70,73,78,69,0, 70,0, 69,0, 68,73,70,0, +88,84,0, 84,76,69,0, 78,68,69,70,0, 69,82,73,76,79,71,0, +79,82,68,0, 72,71,0, 82,0, 72,76,0, 10,0, 83,83,0, 65,84,65,0, +69,88,84,0, 69,70,73,78,69,0, 70,0, 69,0, 68,73,70,0, 82,79,82,0, 69,70,0, 68,69,70,0, 67,76,85,68,69,0, 82,65,71,77,65,0, 78,68,69,70,0, 61,0, 61,0, 73,0, 72,76,0, 71,0, 82,0, 79,67,75,0, 84,69,0, 76,76,0, 69,71,0, 76,0, 80,0, -71,0, 66,0, 72,79,0, 83,69,0, 70,0, 85,0, 82,78,0, 78,0, -73,76,76,0, 88,0, 66,67,0, 73,0, 75,0, 84,0, 70,73,82,83,84,0, +71,0, 66,0, 72,79,0, 83,69,0, 70,0, 82,89,0, 85,0, 68,69,68,0, +78,0, 78,0, 73,76,76,0, 88,0, 66,67,0, 65,76,76,0, 73,0, 73,0, +75,0, 84,0, 77,80,0, 80,0, 83,72,0, 69,84,0, 70,73,82,83,84,0, 73,0, 67,76,73,66,0, 85,76,69,0, 70,73,82,83,84,0, 73,0, 77,69,0, 71,69,0, 84,0, 71,69,0, 72,76,0, 80,0, 73,78,84,70,0, -76,73,67,0, 72,0, 69,76,0, 84,0, 77,0, 69,0, 76,0, 84,0, -77,0, 72,76,0, 76,78,0, 77,0, 88,84,0, 84,76,69,0, 79,82,68,0, -72,71,0, 72,76,0, 68,69,0, 61,0, 73,0, 72,76,0, 71,0, 82,0, -79,67,75,0, 84,69,0, 76,76,0, 69,71,0, 76,0, 80,0, 71,0, 66,0, -72,79,0, 83,69,0, 70,0, 82,78,0, 78,0, 73,76,76,0, 88,0, -66,67,0, 68,69,0, 73,0, 75,0, 84,0, 70,73,82,83,84,0, 73,0, -67,76,73,66,0, 85,76,69,0, 70,73,82,83,84,0, 73,0, 77,69,0, -71,69,0, 84,0, 71,69,0, 72,76,0, 80,0, 73,78,84,70,0, -76,73,67,0, 72,0, 69,76,0, 84,0, 77,0, 69,0, 76,0, 77,0, -72,76,0, 76,78,0, 77,0, 88,84,0, 84,76,69,0, 79,82,68,0, -72,71,0, 72,76,0, 92,39,0, 69,73,76,0, 69,70,73,78,69,68,0, -79,79,82,0, 73,71,72,0, 80,0, 79,84,0, 81,82,84,0, 69,88,0, -73,83,84,0, 47,0, 68,69,0, 61,0, 83,69,71,0, 79,67,75,0, -84,69,0, 83,69,71,0, 71,0, 72,79,0, 68,0, 85,0, 82,78,0, 78,0, -73,76,76,0, 69,88,0, 68,69,0, 75,0, 84,0, 70,73,82,83,84,0, -67,76,73,66,0, 68,85,76,69,0, 70,73,82,83,84,0, 77,69,0, -80,65,71,69,0, 82,71,0, 71,69,0, 73,78,84,70,0, 66,76,73,67,0, -84,0, 75,76,78,0, 77,0, 88,84,0, 84,76,69,0, 79,82,68,0, 10,0, -68,69,0, 47,0, 42,0, 47,0, 10,0, 78,80,65,71,69,0, 65,71,69,0, +76,73,67,0, 72,0, 76,76,0, 69,76,0, 84,0, 77,0, 69,0, 76,0, +84,0, 77,0, 76,0, 76,78,0, 77,0, 88,84,0, 84,76,69,0, +69,82,73,76,79,71,0, 79,82,68,0, 72,71,0, 72,76,0, 68,69,0, +61,0, 73,0, 72,76,0, 71,0, 82,0, 79,67,75,0, 84,69,0, 76,76,0, +69,71,0, 76,0, 80,0, 71,0, 66,0, 72,79,0, 83,69,0, 70,0, +82,89,0, 68,69,68,0, 78,0, 78,0, 73,76,76,0, 88,0, 66,67,0, +68,69,0, 65,76,76,0, 73,0, 73,0, 75,0, 84,0, 77,80,0, 80,0, +83,72,0, 69,84,0, 70,73,82,83,84,0, 73,0, 67,76,73,66,0, +85,76,69,0, 70,73,82,83,84,0, 73,0, 77,69,0, 71,69,0, 84,0, +71,69,0, 72,76,0, 80,0, 73,78,84,70,0, 76,73,67,0, 72,0, +76,76,0, 69,76,0, 84,0, 77,0, 69,0, 76,0, 77,0, 76,0, +76,78,0, 77,0, 88,84,0, 84,76,69,0, 69,82,73,76,79,71,0, +79,82,68,0, 72,71,0, 72,76,0, 92,39,0, 69,73,76,0, +69,70,73,78,69,68,0, 79,79,82,0, 73,71,72,0, 80,0, 79,84,0, +65,71,69,0, 81,82,84,0, 84,82,89,0, 84,69,78,68,69,68,0, 69,88,0, +73,83,84,0, 69,82,73,76,79,71,0, 47,0, 83,83,0, 65,84,65,0, +69,88,84,0, 68,69,0, 61,0, 83,69,71,0, 79,67,75,0, 84,69,0, +83,69,71,0, 71,0, 72,79,0, 82,89,0, 85,0, 68,69,68,0, 78,0, +78,0, 73,76,76,0, 69,88,0, 68,69,0, 75,0, 84,0, +70,73,82,83,84,0, 67,76,73,66,0, 68,85,76,69,0, 70,73,82,83,84,0, +77,69,0, 80,65,71,69,0, 82,71,0, 71,69,0, 73,78,84,70,0, +66,76,73,67,0, 84,0, 75,76,78,0, 77,0, 88,84,0, 84,76,69,0, +69,82,73,76,79,71,0, 79,82,68,0, 10,0, 68,69,0, 47,0, 42,0, +47,0, 10,0, 78,80,65,71,69,0, 65,71,69,0, 67,0, 80,0, 72,76,41,0, 80,0, 83,87,0, 42,0, 42,0, 78,68,0, 81,0, 79,68,0, 69,0, 82,0, 79,82,0, 61,0, 61,0, 83,69,71,0, 79,67,75,0, -84,69,0, 83,69,71,0, 71,0, 72,79,0, 68,0, 82,78,0, 78,0, -73,76,76,0, 69,88,0, 75,0, 84,0, 70,73,82,83,84,0, +84,69,0, 83,69,71,0, 71,0, 72,79,0, 82,89,0, 68,69,68,0, 78,0, +78,0, 73,76,76,0, 69,88,0, 75,0, 84,0, 70,73,82,83,84,0, 67,76,73,66,0, 68,85,76,69,0, 70,73,82,83,84,0, 77,69,0, 80,65,71,69,0, 82,71,0, 71,69,0, 73,78,84,70,0, 66,76,73,67,0, -75,76,78,0, 77,0, 88,84,0, 84,76,69,0, 79,82,68,0, 42,0, -78,68,0, 81,0, 79,68,0, 69,0, 79,82,0, 39,0, 42,0, 79,68,0, -69,0, 79,82,0, 92,39,0, 47,0, 69,73,76,0, 69,70,73,78,69,68,0, -79,79,82,0, 73,71,72,0, 80,0, 79,84,0, 81,82,84,0, 10,0, -92,39,0, 69,73,76,0, 69,70,73,78,69,68,0, 79,79,82,0, 73,71,72,0, -80,0, 81,82,84,0, 92,39,0, 47,0, 69,73,76,0, -69,70,73,78,69,68,0, 79,79,82,0, 73,71,72,0, 80,0, 81,82,84,0, -10,0, 42,0, 78,68,0, 81,0, 79,68,0, 69,0, 82,0, 79,82,0, -78,68,0, 81,0, 69,0, 82,0, 79,82,0, 78,68,0, 81,0, 69,0, -82,0, 79,82,0, 81,0, 69,0, 82,0, 79,82,0, 81,0, 69,0, 82,0, -61,0, 81,0, 69,0, 78,68,0, 81,0, 79,68,0, 69,0, 82,0, -79,82,0, 10,0, 61,0, 61,0, 83,69,71,0, 79,67,75,0, 84,69,0, -83,69,71,0, 71,0, 72,79,0, 68,0, 85,0, 82,78,0, 78,0, +75,76,78,0, 77,0, 88,84,0, 84,76,69,0, 69,82,73,76,79,71,0, +79,82,68,0, 42,0, 78,68,0, 81,0, 79,68,0, 69,0, 79,82,0, 39,0, +42,0, 79,68,0, 69,0, 79,82,0, 92,39,0, 47,0, 69,73,76,0, +69,70,73,78,69,68,0, 79,79,82,0, 73,71,72,0, 80,0, 79,84,0, +65,71,69,0, 81,82,84,0, 10,0, 92,39,0, 69,73,76,0, +69,70,73,78,69,68,0, 79,79,82,0, 73,71,72,0, 80,0, 65,71,69,0, +81,82,84,0, 92,39,0, 47,0, 69,73,76,0, 69,70,73,78,69,68,0, +79,79,82,0, 73,71,72,0, 80,0, 65,71,69,0, 81,82,84,0, 10,0, +42,0, 78,68,0, 81,0, 79,68,0, 69,0, 82,0, 79,82,0, 78,68,0, +81,0, 69,0, 82,0, 79,82,0, 78,68,0, 81,0, 69,0, 82,0, +79,82,0, 81,0, 69,0, 82,0, 79,82,0, 81,0, 69,0, 82,0, 61,0, +81,0, 69,0, 78,68,0, 81,0, 79,68,0, 69,0, 82,0, 79,82,0, +10,0, 61,0, 61,0, 83,69,71,0, 79,67,75,0, 84,69,0, 83,69,71,0, +71,0, 72,79,0, 82,89,0, 85,0, 68,69,68,0, 78,0, 78,0, 73,76,76,0, 69,88,0, 75,0, 84,0, 70,73,82,83,84,0, 67,76,73,66,0, 68,85,76,69,0, 70,73,82,83,84,0, 77,69,0, 80,65,71,69,0, 82,71,0, 71,69,0, 73,78,84,70,0, 66,76,73,67,0, -84,0, 75,76,78,0, 77,0, 88,84,0, 84,76,69,0, 79,82,68,0, -92,39,0, 73,0, 72,76,0, 72,82,0, 76,76,0, 76,0, 80,0, 85,66,0, -73,0, 66,67,0, 73,0, 73,0, 86,0, 73,0, 79,80,0, 84,0, -72,76,0, 80,0, 83,72,0, 69,76,0, 84,0, 77,0, 69,0, 76,0, -77,0, 72,76,0, 72,71,0, 72,76,0, 10,0, 92,39,0, 72,76,41,0, -73,76,0, 70,73,78,69,68,0, 79,79,82,0, 71,72,0, 80,0, 79,84,0, -81,82,84,0, 10,0, +84,0, 75,76,78,0, 77,0, 88,84,0, 84,76,69,0, +69,82,73,76,79,71,0, 79,82,68,0, 92,39,0, 73,0, 72,76,0, +72,82,0, 76,76,0, 76,0, 80,0, 85,66,0, 73,0, 66,67,0, +65,76,76,0, 73,0, 73,0, 77,80,0, 80,0, 83,72,0, 69,84,0, 73,0, +86,0, 73,0, 79,80,0, 84,0, 72,76,0, 80,0, 83,72,0, 76,76,0, +69,76,0, 84,0, 77,0, 69,0, 76,0, 77,0, 76,0, 72,71,0, +72,76,0, 10,0, 92,39,0, 72,76,41,0, 73,76,0, 70,73,78,69,68,0, +79,79,82,0, 71,72,0, 80,0, 79,84,0, 65,71,69,0, 81,82,84,0, +10,0, }; #define AG_TCV(x) (((int)(x) >= -1 && (int)(x) <= 255) ? ag_tcv[(x) + 1] : 0) static const unsigned short ag_tcv[] = { - 38, 38,620,620,620,620,620,620,620,620, 1,392,620,620,620,620,620,620, - 620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, 1,490,621, - 622,623,487,477,624,422,420,485,483,445,484,398,486,625,626,627,627,628, - 628,628,628,629,629,620,394,630,620,631,632,633,634,635,634,636,634,637, - 638,639,638,638,638,638,638,640,638,638,638,641,638,642,638,638,638,643, - 638,638,620,644,620,475,645,633,634,635,634,636,634,637,638,639,638,638, - 638,638,638,640,638,638,638,641,638,642,638,638,638,643,638,638,632,473, - 632,492,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646, - 646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646, - 646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646, - 646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646, - 646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646, - 646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646, - 646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646, - 646,646,646,646,646 + 38, 38,682,682,682,682,682,682,682,682, 1,425,682,682,682,682,682,682, + 682,682,682,682,682,682,682,682,682,682,682,682,682,682,682, 1,526,683, + 684,685,523,513,686,458,456,521,519,481,520,431,522,687,688,689,689,690, + 690,690,690,691,691,682,427,692,682,693,694,695,696,697,696,698,696,699, + 700,701,700,700,700,700,700,702,700,700,700,703,700,704,700,700,700,705, + 700,700,682,706,682,511,707,695,696,697,696,698,696,699,700,701,700,700, + 700,700,700,702,700,700,700,703,700,704,700,700,700,705,700,700,694,509, + 694,528,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, + 708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, + 708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, + 708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, + 708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, + 708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, + 708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, + 708,708,708,708,708 }; #ifndef SYNTAX_ERROR @@ -2032,1850 +2179,2167 @@ static void ag_undo(void) { static const unsigned short ag_tstt[] = { -645,643,642,641,640,639,638,637,636,635,634,632,623,406,402,401,398,396,394, - 393,392,132,131,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,439,435,434,431,429,427, + 426,425,164,163,162,135,134,1,0,51,52, 1,0, -645,643,642,641,640,639,638,637,636,635,634,632,623,406,398,396,394,393,392, - 132,131,63,1,0,11,34,35,36,37,51,52,53,64,65,130,397,410, -419,418,417,416,415,414,413,412,411,408,401,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,632,629,628,627,626,625,623,428, - 398,396,394,393,392,158,132,1,0,135, -419,418,417,416,415,414,413,412,411,408,401,0,59,66,67,70,72,74,75,76,77,78, - 79,80, -645,643,642,641,640,639,638,637,636,635,634,632,623,619,618,617,616,615,614, - 613,612,611,610,609,608,607,606,605,604,603,602,601,600,599,598,597,596, - 595,594,593,592,591,590,589,588,587,586,585,584,583,582,581,580,579,578, - 577,576,575,574,573,572,571,570,569,568,567,565,564,563,562,561,560,559, - 558,557,556,555,553,552,551,550,549,548,547,546,545,544,543,542,541,540, - 539,538,537,536,535,534,533,532,531,530,529,528,527,526,525,524,523,522, - 521,520,519,518,517,516,515,514,513,512,511,510,509,508,456,455,454,453, - 452,451,449,448,447,446,444,443,442,441,440,439,438,437,436,435,434,433, - 432,431,430,429,428,427,426,425,424,416,415,412,409,407,400,399,398,396, - 394,393,392,132,131,1,0,51,52, -392,0,45, -402,401,398,396,394,393,392,0,39,40,41,45,46,47,49,54,55, -645,643,642,641,640,639,638,637,636,635,634,632,623,619,618,617,616,615,614, - 613,612,611,610,609,608,607,606,605,604,603,602,601,600,599,598,597,596, - 595,594,593,592,591,590,589,588,587,586,585,584,583,582,581,580,579,578, - 577,576,575,574,573,572,571,570,569,568,567,565,564,563,562,561,560,559, - 558,557,556,555,553,552,551,550,549,548,547,546,545,544,543,542,541,540, - 539,538,537,536,535,534,533,532,531,530,529,528,527,526,525,524,523,522, - 521,520,519,518,517,516,515,514,513,512,511,510,509,508,456,455,454,453, - 452,451,449,448,447,446,444,443,442,441,440,439,438,437,436,435,434,433, - 432,431,430,429,428,427,426,425,424,416,415,412,409,407,400,399,398,396, - 394,393,392,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,632,623,619,618,617,616,615,614, - 613,612,611,610,609,608,607,606,605,604,603,602,601,600,599,598,597,596, - 595,594,593,592,591,590,589,588,587,586,585,584,583,582,581,580,579,578, - 577,576,575,574,573,572,571,570,569,568,567,565,564,563,562,561,560,559, - 558,557,556,555,553,552,551,550,549,548,547,546,545,544,543,542,541,540, - 539,538,537,536,535,534,533,532,531,530,529,528,527,526,525,524,523,522, - 521,520,519,518,517,516,515,514,513,512,511,510,509,508,456,455,454,453, - 452,451,449,448,447,446,444,443,442,441,440,439,438,437,436,435,434,433, - 432,431,430,429,428,427,426,425,424,416,415,412,409,407,402,401,398,396, - 394,393,392,132,131,1,0,21,30,31,32,33,54,55,62,72,76,77,86,91,130,249, - 250,251,252,253,254,255,256,257,259,260,261,262,263,264,265,266,267,268, +707,705,704,703,702,701,700,699,698,697,696,694,685,439,431,429,427,426,425, + 164,163,162,135,134,63,1,0,11,34,35,36,37,51,52,53,64,65,133,430,443, +455,454,453,452,451,450,449,448,447,441,434,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,691,690,689,688,687,685,464, + 431,429,427,426,425,161,135,1,0,138, +455,454,453,452,451,450,449,448,447,441,434,0,59,66,67,73,75,77,78,79,80,81, + 82,83, +707,705,704,703,702,701,700,699,698,697,696,694,685,681,680,679,678,677,676, + 675,674,673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658, + 657,656,655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640, + 639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622, + 621,620,619,618,617,616,615,614,613,612,611,609,608,607,606,605,604,603, + 602,601,600,599,598,597,595,594,593,592,591,590,589,588,587,586,585,584, + 583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566, + 565,564,563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548, + 547,492,491,490,489,488,487,485,484,483,482,480,479,478,477,476,475,474, + 473,472,471,470,469,468,467,466,465,464,463,462,461,460,452,451,448,446, + 445,444,442,440,433,432,431,429,427,426,425,135,134,1,0,51,52, +425,0,45, +435,434,431,429,427,426,425,0,39,40,41,45,46,47,49,54,55, +707,705,704,703,702,701,700,699,698,697,696,694,685,681,680,679,678,677,676, + 675,674,673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658, + 657,656,655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640, + 639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622, + 621,620,619,618,617,616,615,614,613,612,611,609,608,607,606,605,604,603, + 602,601,600,599,598,597,595,594,593,592,591,590,589,588,587,586,585,584, + 583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566, + 565,564,563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548, + 547,492,491,490,489,488,487,485,484,483,482,480,479,478,477,476,475,474, + 473,472,471,470,469,468,467,466,465,464,463,462,461,460,452,451,448,446, + 445,444,442,440,433,432,431,429,427,426,425,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,681,680,679,678,677,676, + 675,674,673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658, + 657,656,655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640, + 639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622, + 621,620,619,618,617,616,615,614,613,612,611,609,608,607,606,605,604,603, + 602,601,600,599,598,597,595,594,593,592,591,590,589,588,587,586,585,584, + 583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566, + 565,564,563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548, + 547,492,491,490,489,488,487,485,484,483,482,480,479,478,477,476,475,474, + 473,472,471,470,469,468,467,466,465,464,463,462,461,460,452,451,448,446, + 445,444,442,440,435,434,431,429,427,426,425,135,134,1,0,21,30,31,32,33, + 54,55,62,75,79,80,89,94,133,245,258,259,260,261,262,263,264,265,266,267, 269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286, 287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304, 305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322, - 323,324,325,326,327,328,330,331,332,333,334,335,336,337,338,339,340,341, - 342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359, + 323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340, + 341,342,343,344,345,347,348,349,350,351,352,353,354,355,356,357,358,359, 360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377, - 378,379,380,410, -645,643,642,641,640,639,638,637,636,635,634,632,623,406,398,396,394,393,392, - 132,131,63,38,1,0,11,35,36,51,52,53,64,65,130,397,410, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, -621,1,0,51,52, -396,394,393,392,1,0,51,52, -396,394,393,392,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, -409,407,1,0,51,52, -645,644,643,642,641,640,639,638,637,636,635,634,630,629,628,627,626,625,621, - 486,398,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,81,130,410, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,130,410, -621,0,10,12,403, -396,394,393,392,1,0,51,52, -396,394,393,392,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,130,410, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,73,83,86, - 130,160,191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211, - 212,213,214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,73,83,86, - 130,160,191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211, - 212,213,214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,130,410, -409,407,0,68,69, -630,621,0,10,12,13,14,403,404, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,422,420,406,402,401,398,396,395,394,393,392,132,131,38,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 456,455,454,453,452,451,449,448,447,446,445,444,443,442,441,440,439,438, - 437,436,435,434,433,432,431,430,429,428,427,426,425,424,423,422,420,409, - 407,402,401,400,399,398,396,395,394,393,392,1,0,51,52, -402,401,0,59,60,61, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,422,420,398,396,395,394,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,422,420,398,394,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,422,420,398,396,395,394,392,1,0,40,45,46,47,48,49,54,83,85,119,137, - 138,140,142,143,144,145,146,147,151,154,155,180,182,184,190,191,192,194, - 195,198,200,215,219,220,224,381,382,383,384,385,386,387,388,389,390,391, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,422,420,398,394,392,1,0,43,44,46,54,83,85,119,137,138,140,142,143, - 144,145,146,147,151,154,155,180,182,184,190,191,192,194,195,198,200,215, - 219,220,224,381,382,383,384,385,386,387,388,389,390,391, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,422,420,398,394,392,1,0,43,44,46,54,83,85,119,137,138,140,142,143, - 144,145,146,147,151,154,155,180,182,184,190,191,192,194,195,198,200,215, - 219,220,224,381,382,383,384,385,386,387,388,389,390,391, -645,643,642,641,640,639,638,637,636,635,634,632,623,619,618,617,616,615,614, - 613,612,611,610,609,608,607,606,605,604,603,602,601,600,599,598,597,596, - 595,594,593,592,591,590,589,588,587,586,585,584,583,582,581,580,579,578, - 577,576,575,574,573,572,571,570,569,568,567,565,564,563,562,561,560,559, - 558,557,556,555,553,552,551,550,549,548,547,546,545,544,543,542,541,540, - 539,538,537,536,535,534,533,532,531,530,529,528,527,526,525,524,523,522, - 521,520,519,518,517,516,515,514,513,512,511,510,509,508,456,455,454,453, - 452,451,449,448,447,446,444,443,442,441,440,439,438,437,436,435,434,433, - 432,431,430,429,428,427,426,425,424,416,415,412,409,407,400,399,398,396, - 394,393,392,132,131,0,21,30,31,32,33,39,40,41,45,46,47,49,54,55,62,72, - 76,77,86,91,130,249,250,251,252,253,254,255,256,257,259,260,261,262,263, - 264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281, + 378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395, + 396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413, + 443, +707,705,704,703,702,701,700,699,698,697,696,694,685,439,431,429,427,426,425, + 164,163,162,135,134,63,38,1,0,11,35,36,51,52,53,64,65,133,430,443, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, +683,1,0,51,52, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, +446,445,444,442,440,1,0,51,52, +707,706,705,704,703,702,701,700,699,698,697,696,692,691,690,689,688,687,683, + 522,431,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,84,133,443, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, +683,0,10,12,436, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,76,86, + 89,131,133,166,197,199,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,76,86, + 89,131,133,166,197,199,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, +446,445,444,442,440,0,68,69,70,71,72, +692,683,0,10,12,13,14,436,437, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,458,456,439,435,434,431,429,428,427,426,425,164,163,162,135,134,38, + 1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 492,491,490,489,488,487,485,484,483,482,481,480,479,478,477,476,475,474, + 473,472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,456,446, + 445,444,442,440,435,434,433,432,431,429,428,427,426,425,1,0,51,52, +435,434,0,59,60,61, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,458,456,431,429,428,427,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,458,456,431,427,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,458,456,431,429,428,427,425,1,0,40,45,46,47,48,49,54,86,88,122,140, + 141,143,145,146,147,148,149,150,154,157,158,186,188,190,196,197,198,200, + 201,204,206,221,225,226,230,414,415,416,417,418,419,420,421,422,423,424, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,458,456,431,427,425,1,0,43,44,46,54,86,88,122,140,141,143,145,146, + 147,148,149,150,154,157,158,186,188,190,196,197,198,200,201,204,206,221, + 225,226,230,414,415,416,417,418,419,420,421,422,423,424, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,458,456,431,427,425,1,0,43,44,46,54,86,88,122,140,141,143,145,146, + 147,148,149,150,154,157,158,186,188,190,196,197,198,200,201,204,206,221, + 225,226,230,414,415,416,417,418,419,420,421,422,423,424, +707,705,704,703,702,701,700,699,698,697,696,694,685,681,680,679,678,677,676, + 675,674,673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658, + 657,656,655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640, + 639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622, + 621,620,619,618,617,616,615,614,613,612,611,609,608,607,606,605,604,603, + 602,601,600,599,598,597,595,594,593,592,591,590,589,588,587,586,585,584, + 583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566, + 565,564,563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548, + 547,492,491,490,489,488,487,485,484,483,482,480,479,478,477,476,475,474, + 473,472,471,470,469,468,467,466,465,464,463,462,461,460,452,451,448,446, + 445,444,442,440,433,432,431,429,427,426,425,135,134,0,21,30,31,32,33,39, + 40,41,45,46,47,49,54,55,62,75,79,80,89,94,133,245,258,259,260,261,262, + 263,264,265,266,267,269,270,271,272,273,274,275,276,277,278,279,280,281, 282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299, 300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317, - 318,319,320,321,322,323,324,325,326,327,328,330,331,332,333,334,335,336, - 337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354, + 318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335, + 336,337,338,339,340,341,342,343,344,345,347,348,349,350,351,352,353,354, 355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372, - 373,374,375,376,377,378,379,380,410, -459,456,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -245,243,241,239,233,231,229,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -628,627,626,625,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -245,243,241,239,233,231,229,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -506,505,243,241,239,233,231,229,1,0,51,52, -506,505,243,241,239,233,231,229,1,0,51,52, -241,239,231,229,1,0,51,52, -241,239,231,229,1,0,51,52, -245,243,241,239,233,231,229,1,0,51,52, -245,243,241,239,233,231,229,1,0,51,52, -245,243,241,239,233,231,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -628,627,626,625,1,0,51,52, -445,1,0,51,52, -445,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -506,505,243,241,239,233,231,229,1,0,51,52, -506,505,243,241,239,233,231,229,1,0,51,52, -241,239,231,229,1,0,51,52, -241,239,231,229,1,0,51,52, -245,243,241,239,233,231,229,1,0,51,52, -245,243,241,239,233,231,229,1,0,51,52, -245,243,241,239,233,231,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -506,236,235,234,233,232,231,230,229,1,0,51,52, -646,645,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,621,620,507,492,490,489,487,486,485,484,483,481,479,477, - 475,473,472,470,468,466,464,462,461,458,445,422,420,398,396,394,393,392, - 1,0,51,52,135, -507,396,394,393,392,1,0,51,52, -507,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,460,458,422,420,396,394,393, - 392,1,0,83, -396,394,393,392,1,0,51, -507,0,258, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,73,83,86, - 130,160,191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211, - 212,213,214,410,457,504, -456,455,454,453,452,451,449,448,447,446,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,409,407,0,68,69,92,93, - 94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,111,112,113, - 114,115,116,117,118,120,121,122,123,124,125,126,127,128, -396,394,393,392,1,0,51,52, -646,645,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,621,620,492,490,487,486,485,484,483,477,475,473,445,422, - 420,398,394,1,0,83, -646,645,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,621,620,492,490,487,486,485,484,483,477,475,473,445,422, - 420,398,394,1,0,51,52, -396,394,393,392,1,0,51,52, -645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445, - 422,420,398,394,392,1,0,139, -458,445,420,396,394,393,392,1,0,51,52, -396,394,393,392,1,0,51,52, -396,394,393,392,0,39,40,41,45,46,47,49, -396,394,393,392,0,39,40,41,45,46,47,49, -396,394,393,392,1,0,51,52, -629,628,627,626,625,0, -628,627,626,625,0, -626,625,0, -645,643,642,641,640,639,638,637,636,635,634,632,629,628,627,626,625,623,507, - 489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,460,458,422,420,398,396,394, - 393,392,1,0, -645,643,639,637,636,635,634,629,628,627,626,625,623,507,489,488,487,486,485, - 484,483,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467, - 466,465,464,463,462,461,460,458,420,398,396,394,393,392,217,216,1,0, -629,628,627,626,625,0, -645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445,422, - 420,398,394,392,228,1,0,16, -629,628,627,626,625,0, -639,637,636,635,634,629,628,627,626,625,0, -628,627,626,625,507,489,488,487,486,485,484,483,482,481,480,479,478,477,476, - 475,474,473,472,471,470,469,468,467,466,465,464,463,462,461,460,458,420, - 396,394,393,392,1,0, -626,625,507,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474, - 473,472,471,470,469,468,467,466,465,464,463,462,461,460,458,420,396,394, - 393,392,1,0, -637,636,635,634,629,628,627,626,625,507,489,488,487,486,485,484,483,482,481, - 480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465,464,463, - 462,461,460,458,420,396,394,393,392,1,0, -645,639,637,636,635,634,629,628,627,626,625,623,507,489,488,487,486,485,484, - 483,482,481,480,479,477,476,475,474,473,472,471,470,469,468,467,466,465, - 464,463,462,461,458,420,398,396,394,393,392,217,216,1,0,218, -422,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -507,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,460,458,420,396,394,393,392, + 373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390, + 391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408, + 409,410,411,412,413,443, +495,492,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +670,545,544,543,249,247,239,237,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +670,545,249,247,239,237,235,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +690,689,688,687,1,0,51,52, +670,545,544,543,249,247,239,237,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +670,545,249,247,239,237,235,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +670,542,541,249,247,239,237,235,1,0,51,52, +670,542,541,249,247,239,237,235,1,0,51,52, +670,542,541,249,247,239,237,235,1,0,51,52, +670,542,541,249,247,239,237,235,1,0,51,52, +670,247,237,235,1,0,51,52, +670,247,237,235,1,0,51,52, +670,545,249,247,239,237,235,1,0,51,52, +670,545,249,247,239,237,235,1,0,51,52, +670,545,249,247,239,237,235,1,0,51,52, +670,545,544,543,249,247,239,237,235,1,0,51,52, +670,545,544,543,249,247,239,237,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +690,689,688,687,1,0,51,52, +481,1,0,51,52, +481,1,0,51,52, +481,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +670,542,541,249,247,239,237,235,1,0,51,52, +670,542,541,249,247,239,237,235,1,0,51,52, +670,542,541,249,247,239,237,235,1,0,51,52, +670,542,541,249,247,239,237,235,1,0,51,52, +670,247,237,235,1,0,51,52, +670,247,237,235,1,0,51,52, +670,545,249,247,239,237,235,1,0,51,52, +670,545,249,247,239,237,235,1,0,51,52, +670,545,249,247,239,237,235,1,0,51,52, +670,545,544,543,249,247,239,237,235,1,0,51,52, +670,545,544,543,249,247,239,237,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +542,242,241,240,239,238,237,236,235,1,0,51,52, +708,707,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,686,685,683,682,546,528,526,525,523,522,521,520,519,517,515,513, + 511,509,508,506,504,502,500,498,497,494,481,458,456,431,429,427,426,425, + 1,0,51,52,138, +546,429,427,426,425,1,0,51,52, +546,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, + 507,506,505,504,503,502,501,500,499,498,497,496,494,458,456,429,427,426, + 425,1,0,86, +429,427,426,425,1,0,51, +546,0,268, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,76,86, + 89,131,133,166,197,199,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,219,220,443,493,540, +492,491,490,489,488,487,485,484,483,482,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,460,446,445,444,442,440,0, + 68,69,70,71,72,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109, + 110,111,112,114,115,116,117,118,119,120,121,123,124,125,126,127,128,129, + 130,131, +429,427,426,425,1,0,51,52, +708,707,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,686,685,683,682,528,526,523,522,521,520,519,513,511,509,481,458, + 456,431,427,1,0,86, +708,707,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,686,685,683,682,528,526,523,522,521,520,519,513,511,509,481,458, + 456,431,427,1,0,51,52, +429,427,426,425,1,0,51,52, +707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481, + 458,456,431,427,425,1,0,142, +494,481,456,429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +429,427,426,425,0,39,40,41,45,46,47,49, +429,427,426,425,0,39,40,41,45,46,47,49, +429,427,426,425,1,0,51,52, +691,690,689,688,687,0, +690,689,688,687,0, +688,687,0, +707,705,704,703,702,701,700,699,698,697,696,694,691,690,689,688,687,685,546, + 525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, + 507,506,505,504,503,502,501,500,499,498,497,496,494,458,456,431,429,427, + 426,425,1,0, +707,705,701,699,698,697,696,691,690,689,688,687,685,546,525,524,523,522,521, + 520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503, + 502,501,500,499,498,497,496,494,456,431,429,427,426,425,223,222,1,0, +691,690,689,688,687,0, +707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481,458, + 456,431,427,425,234,1,0,16, +691,690,689,688,687,0, +701,699,698,697,696,691,690,689,688,687,0, +690,689,688,687,546,525,524,523,522,521,520,519,518,517,516,515,514,513,512, + 511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,494,456, + 429,427,426,425,1,0, +688,687,546,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510, + 509,508,507,506,505,504,503,502,501,500,499,498,497,496,494,456,429,427, + 426,425,1,0, +699,698,697,696,691,690,689,688,687,546,525,524,523,522,521,520,519,518,517, + 516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499, + 498,497,496,494,456,429,427,426,425,1,0, +707,701,699,698,697,696,691,690,689,688,687,685,546,525,524,523,522,521,520, + 519,518,517,516,515,513,512,511,510,509,508,507,506,505,504,503,502,501, + 500,499,498,497,494,456,431,429,427,426,425,223,222,1,0,224, +458,1,0,51,52, +458,429,427,426,425,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +546,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, + 507,506,505,504,503,502,501,500,499,498,497,496,494,456,429,427,426,425, 1,0,51,52, -507,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,460,458,420,396,394,393,392, +546,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, + 507,506,505,504,503,502,501,500,499,498,497,496,494,456,429,427,426,425, 1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, - 492,491,490,487,486,485,484,483,477,475,473,445,423,422,421,420,398,396, - 395,394,393,392,226,132,131,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -422,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, - 492,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395,394, - 393,392,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, - 492,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395,394, - 393,392,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, - 209,210,211,212,213,214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, - 209,210,211,212,213,214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, - 209,210,211,212,213,214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, - 209,210,211,212,213,214,410,457,504, -507,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,460,458,420,396,394,393,392, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, + 528,527,526,523,522,521,520,519,513,511,509,492,481,459,458,457,456,431, + 429,428,427,426,425,232,135,134,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +458,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, + 528,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429,428, + 427,426,425,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, + 528,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429,428, + 427,426,425,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, + 213,214,215,216,217,218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, + 213,214,215,216,217,218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, + 213,214,215,216,217,218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, + 213,214,215,216,217,218,219,220,443,493,540, +546,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, + 507,506,505,504,503,502,501,500,499,498,497,496,494,456,429,427,426,425, 1,0,51,52, -507,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,460,458,420,394,392,1,0,51, - 52,192,194,195,196,197, -507,484,483,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467, - 466,465,464,463,462,461,460,458,420,396,394,393,392,1,0,51,52,190,191, -507,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465, - 464,463,462,461,460,458,420,396,394,393,392,1,0,51,52,186,187,188,189, -507,478,477,476,475,474,473,472,471,470,469,468,467,466,465,464,463,462,461, - 460,458,420,396,394,393,392,1,0,51,52,184,185, -507,476,475,474,473,472,471,470,469,468,467,466,465,464,463,462,461,460,458, - 420,396,394,393,392,1,0,51,52,182,183, -474,473,0,180,181, -472,471,470,469,468,467,466,465,464,463,462,461,460,396,394,393,392,1,0,161, - 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -396,394,393,392,1,0,51,52, -396,394,393,392,1,0,51,52, -396,394,393,392,1,0,71, -396,394,393,392,1,0,51,52, -396,394,393,392,1,0,51,52, -396,394,393,392,1,0,51,52, -396,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,620,492,490,487,486,485,484,483,477,475,473,445, - 422,420,398,394,1,0, -396,394,393,392,1,0,51,52, -396,394,393,392,1,0,51,52, -396,394,393,392,1,0,51,52, -645,644,643,642,641,640,639,638,637,636,635,634,630,629,628,627,626,625,621, - 486,398,1,0,51,52, -645,644,643,642,641,640,639,638,637,636,635,634,630,629,628,627,626,625,621, - 486,398,0,10,12,13,14,19,403,404,405, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, - 492,491,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395, - 394,393,392,226,132,131,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, - 492,491,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395, - 394,393,392,226,132,131,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,422,420,398,396,395,394,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, - 492,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395,394, - 393,392,226,132,131,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, - 492,491,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395, - 394,393,392,226,132,131,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, - 492,491,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395, - 394,393,392,226,132,131,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, - 492,491,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395, - 394,393,392,226,132,131,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, - 492,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395,394, - 393,392,226,132,131,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,507,492,490,489,488,487,486,485,484,483, - 482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465, - 464,463,462,461,460,458,445,423,422,420,398,396,395,394,393,392,1,0,51, +546,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, + 507,506,505,504,503,502,501,500,499,498,497,496,494,456,427,425,1,0,51, + 52,198,200,201,202,203, +546,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503, + 502,501,500,499,498,497,496,494,456,429,427,426,425,1,0,51,52,196,197, +546,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, + 500,499,498,497,496,494,456,429,427,426,425,1,0,51,52,192,193,194,195, +546,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, + 496,494,456,429,427,426,425,1,0,51,52,190,191, +546,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,494, + 456,429,427,426,425,1,0,51,52,188,189, +510,509,0,186,187, +508,507,506,505,504,503,502,501,500,499,498,497,496,429,427,426,425,1,0,167, + 168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,74, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,682,528,526,523,522,521,520,519,513,511,509,481, + 458,456,431,427,1,0, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +707,706,705,704,703,702,701,700,699,698,697,696,692,691,690,689,688,687,683, + 522,431,1,0,51,52, +707,706,705,704,703,702,701,700,699,698,697,696,692,691,690,689,688,687,683, + 522,431,0,10,12,13,14,19,436,437,438, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, + 528,527,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429, + 428,427,426,425,232,135,134,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, + 528,527,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429, + 428,427,426,425,232,135,134,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,458,456,431,429,428,427,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, + 528,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429,428, + 427,426,425,232,135,134,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, + 528,527,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429, + 428,427,426,425,232,135,134,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, + 528,527,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429, + 428,427,426,425,232,135,134,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, + 528,527,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429, + 428,427,426,425,232,135,134,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, + 528,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429,428, + 427,426,425,232,135,134,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,546,528,526,525,524,523,522,521,520,519, + 518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, + 500,499,498,497,496,494,481,459,458,456,431,429,428,427,426,425,1,0,51, 52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, - 492,491,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395, - 394,393,392,226,132,131,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,503,501,500,499,498,497,496,495,494,493, - 492,490,487,486,485,484,483,477,475,473,445,423,422,420,398,396,395,394, - 393,392,226,132,131,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,422,420,398,396,395,394,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,423,422,420,398,396,395,394,393,392,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,422,420,406,402,401,398,396,395,394,393,392,132,131,38,1,0,51,52, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,422,420,398,394,1,0,46,54,83,85,119,137,138,140,142,143,144,145,146, - 147,151,154,155,180,182,184,190,191,192,194,195,198,200,215,219,220,224, - 381,382,383,384,385,386,387,388,389,390,391, -392,0,45, -392,0,45, -456,455,454,453,452,451,449,448,447,446,444,443,442,441,440,439,438,437,436, - 435,434,433,432,431,430,429,428,427,426,425,424,409,407,400,399,0,56,58, - 68,69,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109, - 111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128, -396,394,393,392,1,0,51,52, -459,456,396,394,393,392,0,22,39,40,41,45,46,47,49,128,159, -506,236,235,234,233,232,231,230,229,0,4,237,554, -245,243,241,239,233,231,229,0,5,240,242,244,566, -628,627,626,625,0,329, -445,0,119, -445,0,119, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -506,505,243,241,239,233,231,229,0,238,240,242,244,246,247, -506,505,243,241,239,233,231,229,0,238,240,242,244,246,247, -241,239,231,229,0,240,242,248, -241,239,231,229,0,240,242,248, -245,243,241,239,233,231,229,0,5,240,242,244,566, -245,243,241,239,233,231,229,0,5,240,242,244,566, -245,243,241,239,233,231,229,0,5,240,242,244,566, -506,236,235,234,233,232,231,230,229,0,4,237,554, -506,236,235,234,233,232,231,230,229,0,4,237,554, -506,236,235,234,233,232,231,230,229,0,4,237,554, -506,236,235,234,233,232,231,230,229,0,4,237,554, -506,236,235,234,233,232,231,230,229,0,4,237,554, -506,236,235,234,233,232,231,230,229,0,4,237,554, -506,236,235,234,233,232,231,230,229,0,4,237,554, -506,236,235,234,233,232,231,230,229,0,4,237,554, -506,236,235,234,233,232,231,230,229,0,4,237,554, -506,236,235,234,233,232,231,230,229,0,4,237,554, -506,236,235,234,233,232,231,230,229,0,4,237,554, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, - 422,398,226,132,131,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27,28, - 29,57,83,86,87,130,191,193,198,199,200,201,202,203,204,205,206,207,208, - 209,210,211,212,213,214,403,410,450,457,504, -633,629,628,627,626,625,624,623,487,484,483,226,1,0,2,6,7,15,17,213,214,457, -619,618,617,616,615,614,613,612,611,610,609,608,607,606,605,604,603,602,601, - 600,599,598,597,596,595,594,593,592,591,590,589,588,587,586,585,584,583, - 582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,565,564, - 563,562,561,560,559,558,557,556,555,553,552,551,550,549,548,547,546,545, - 544,543,542,541,540,539,538,537,536,535,534,533,532,531,530,529,528,527, - 526,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509, - 508,1,0,51,52, -619,618,617,616,615,614,613,612,611,610,609,608,607,606,605,604,603,602,601, - 600,599,598,597,596,595,594,593,592,591,590,589,588,587,586,585,584,583, - 582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,565,564, - 563,562,561,560,559,558,557,556,555,553,552,551,550,549,548,547,546,545, - 544,543,542,541,540,539,538,537,536,535,534,533,532,531,530,529,528,527, - 526,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509, - 508,1,0,51,52, -396,394,393,392,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,130,410, -645,644,643,642,641,640,639,638,637,636,635,634,629,628,627,626,625,486,398, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, + 528,527,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429, + 428,427,426,425,232,135,134,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, + 528,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429,428, + 427,426,425,232,135,134,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,458,456,431,429,428,427,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,459,458,456,431,429,428,427,426,425,1,0,51,52, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,458,456,439,435,434,431,429,428,427,426,425,164,163,162,135,134,38, 1,0,51,52, -645,644,643,642,641,640,639,638,637,636,635,634,629,628,627,626,625,486,398, - 0,19,405, -396,394,393,392,1,0,51,52, -396,394,393,392,1,0,51,52, -624,621,1,0,51,52, -624,621,0,10,12,18,20,403,450, -396,394,393,392,1,0,51,52, -396,394,393,392,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,632,623,396,394,393,392,132,131, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,458,456,431,427,1,0,46,54,86,88,122,140,141,143,145,146,147,148,149, + 150,154,157,158,186,188,190,196,197,198,200,201,204,206,221,225,226,230, + 414,415,416,417,418,419,420,421,422,423,424, +425,0,45, +425,0,45, +492,491,490,489,488,487,485,484,483,482,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,460,446,445,444,442,440,433, + 432,0,56,58,68,69,70,71,72,95,96,97,98,99,100,101,102,103,104,105,106, + 107,108,109,110,111,112,114,115,116,117,118,119,120,121,123,124,125,126, + 127,128,129,130,131, +429,427,426,425,1,0,51,52, +495,492,429,427,426,425,0,22,39,40,41,45,46,47,49,131,165, +670,545,544,543,249,247,239,237,235,0,246,248,250,251,255,256,257, +542,242,241,240,239,238,237,236,235,0,4,243,596, +670,545,249,247,239,237,235,0,5,246,248,250,610, +690,689,688,687,0,346, +481,0,122, +481,0,122, +481,0,122, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +670,542,541,249,247,239,237,235,0,244,246,248,250,252,253, +670,542,541,249,247,239,237,235,0,244,246,248,250,252,253, +670,542,541,249,247,239,237,235,0,244,246,248,250,252,253, +670,542,541,249,247,239,237,235,0,244,246,248,250,252,253, +670,247,237,235,0,246,248,254, +670,247,237,235,0,246,248,254, +670,545,249,247,239,237,235,0,5,246,248,250,610, +670,545,249,247,239,237,235,0,5,246,248,250,610, +670,545,249,247,239,237,235,0,5,246,248,250,610, +670,545,544,543,249,247,239,237,235,0,246,248,250,251,255,256,257, +670,545,544,543,249,247,239,237,235,0,246,248,250,251,255,256,257, +542,242,241,240,239,238,237,236,235,0,4,243,596, +542,242,241,240,239,238,237,236,235,0,4,243,596, +542,242,241,240,239,238,237,236,235,0,4,243,596, +542,242,241,240,239,238,237,236,235,0,4,243,596, +542,242,241,240,239,238,237,236,235,0,4,243,596, +542,242,241,240,239,238,237,236,235,0,4,243,596, +542,242,241,240,239,238,237,236,235,0,4,243,596, +542,242,241,240,239,238,237,236,235,0,4,243,596, +542,242,241,240,239,238,237,236,235,0,4,243,596, +542,242,241,240,239,238,237,236,235,0,4,243,596, +542,242,241,240,239,238,237,236,235,0,4,243,596, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, + 492,458,431,232,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,86,89,90,131,133,197,199,204,205,206,207,208,209,210,211,212, + 213,214,215,216,217,218,219,220,436,443,486,493,540, +695,691,690,689,688,687,686,685,523,520,519,232,1,0,2,6,7,15,17,219,220,493, +681,680,679,678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663, + 662,661,660,659,658,657,656,655,654,653,652,651,650,649,648,647,646,645, + 644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,622,621,620,619,618,617,616,615,614,613,612,611,609,608, + 607,606,605,604,603,602,601,600,599,598,597,595,594,593,592,591,590,589, + 588,587,586,585,584,583,582,581,580,579,578,577,576,575,574,573,572,571, + 570,569,568,567,566,565,564,563,562,561,560,559,558,557,556,555,554,553, + 552,551,550,549,548,547,1,0,51,52, +681,680,679,678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663, + 662,661,660,659,658,657,656,655,654,653,652,651,650,649,648,647,646,645, + 644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,622,621,620,619,618,617,616,615,614,613,612,611,609,608, + 607,606,605,604,603,602,601,600,599,598,597,595,594,593,592,591,590,589, + 588,587,586,585,584,583,582,581,580,579,578,577,576,575,574,573,572,571, + 570,569,568,567,566,565,564,563,562,561,560,559,558,557,556,555,554,553, + 552,551,550,549,548,547,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, +707,706,705,704,703,702,701,700,699,698,697,696,691,690,689,688,687,522,431, 1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,632,623,396,394,393,392,132,131, - 1,0,21,130,410, -621,1,0,51,52, -621,0,10,12,403, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, - 422,398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, - 422,398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, - 422,398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, - 422,398,226,132,131,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28,29,57, - 83,86,130,191,193,198,199,200,201,202,203,204,205,206,207,208,209,210, - 211,212,213,214,403,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,130,410, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,130,410, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,110,130, - 410, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,110,130, - 410, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,110,130, - 410, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, - 422,398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, - 422,398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, - 422,398,226,132,131,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27,28, - 29,57,83,86,87,130,191,193,198,199,200,201,202,203,204,205,206,207,208, - 209,210,211,212,213,214,403,410,450,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, - 422,398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, - 422,398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, - 422,398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, - 422,398,226,132,131,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27,28, - 29,57,83,86,87,130,191,193,198,199,200,201,202,203,204,205,206,207,208, - 209,210,211,212,213,214,403,410,450,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -396,394,393,392,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -459,456,396,394,393,392,1,0,51,52, -459,456,396,394,393,392,1,0,51,52, -396,394,393,392,0,39,40,41,45,46,47,49, -421,0,84, -646,645,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,621,620,492,490,487,486,485,484,483,477,475,473,445,422, - 420,398,394,0,46,54,82,83,85,119,137,138,142,143,144,145,146,147,151, - 154,155,180,182,184,190,191,192,194,195,198,200,215,219,220,224,381,382, - 384,385,386,387,388,389,390,391, -396,394,393,392,0,39,40,41,45,46,47,49, -644,643,642,641,640,637,635,627,626,625,623,621,392,0,152, -396,394,393,392,0,39,40,41,45,46,47,49, -396,394,393,392,0,39,40,41,45,46,47,49, -637,636,635,634,629,628,627,626,625,0, -644,642,641,640,625,624,0, -645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445, - 422,420,398,394,392,228,1,0,16, -639,637,636,635,634,629,628,627,626,625,507,489,488,487,486,485,484,483,482, - 481,480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465,464, - 463,462,461,460,458,420,396,394,393,392,1,0, -639,637,636,635,634,629,628,627,626,625,507,489,488,487,486,485,484,483,482, - 481,480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465,464, - 463,462,461,460,458,420,396,394,393,392,1,0, -422,0,83, -422,0,83, -422,0,83, -422,0,83, -422,0,83, -422,0,83, -422,0,83, -422,0,83, -422,0,83, -422,0,83, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -629,628,627,626,625,0, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -396,394,393,392,0,39,40,41,45,46,47,49, -396,394,393,392,0,39,40,41,45,46,47,49, -396,394,393,392,0,39,40,41,45,46,47,49, -396,394,393,392,0,39,40,41,45,46,47,49, -396,394,393,392,0,39,40,41,45,46,47,49, -646,645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628, - 627,626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473, - 445,422,420,398,394,392,1,0, -396,394,393,392,0,39,40,41,45,46,47,49, -396,394,393,392,0,39,40,41,45,46,47,49, -645,644,643,642,641,640,639,638,637,636,635,634,629,628,627,626,625,486,398, - 394,392,1,0,51,52, -396,394,393,392,1,0,51,52, -396,394,393,392,1,0,51,52, -396,394,393,392,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -396,394,393,392,0,39,40,41,45,46,47,49, -396,394,393,392,1,0,51,52, -396,394,393,392,1,0,51,52, -507,458,445,396,394,393,392,1,0,51,52, -507,445,396,394,393,392,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -507,396,394,393,392,1,0,51,52, -507,396,394,393,392,1,0,51,52, -458,1,0,51,52, -645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445,422, - 420,398,394,392,228,1,0,16, -645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445, - 422,420,398,394,392,228,1,0,16, -458,420,396,394,393,392,1,0,51,52, -458,420,0,85,129, -637,636,635,634,629,628,627,626,625,0, -645,639,637,636,635,634,629,628,627,626,625,623,396,394,393,392,217,216,1,0, - 218, -619,618,617,616,615,614,613,612,611,610,609,608,607,606,605,604,603,602,601, - 600,599,598,597,596,595,594,593,592,591,590,589,588,587,586,585,584,583, - 582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,565,564, - 563,562,561,560,559,558,557,556,555,553,552,551,550,549,548,547,546,545, - 544,543,542,541,540,539,538,537,536,535,534,533,532,531,530,529,528,527, - 526,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509, - 508,0,31,32,249,250,251,252,253,254,255,256,257,259,260,261,262,263,264, - 265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282, - 283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300, - 301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318, - 319,320,321,322,323,324,325,326,327,328,330,331,332,333,334,335,336,337, - 338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355, - 356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373, - 374,375,376,377,378,379,380, -645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445,422, - 420,398,394,392,228,1,0,16, -445,0,119, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, - 422,398,226,132,131,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27,28, - 29,57,83,86,87,130,191,193,198,199,200,201,202,203,204,205,206,207,208, - 209,210,211,212,213,214,403,410,450,457,504, -458,396,394,393,392,1,0,129, -458,396,394,393,392,1,0,129, -458,396,394,393,392,1,0,129, -458,396,394,393,392,1,0,129, -458,396,394,393,392,1,0,129, -420,1,0,51,52, -420,0,85, -646,645,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,621,620,492,490,487,486,485,484,483,477,475,473,445,423, - 422,420,398,394,392,1,0,46,51,52,54,83,85,90,119,137,138,142,143,144, - 145,146,147,151,154,155,180,182,184,190,191,192,194,195,198,200,215,219, - 220,224,381,382,384,385,386,387,388,389,390,391, -637,636,635,634,629,628,627,626,625,0, -629,628,627,626,625,0, -645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445, - 422,420,398,394,392,1,0, -624,0, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -420,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, - 209,210,211,212,213,214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, - 209,210,211,212,213,214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, - 209,210,211,212,213,214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, - 209,210,211,212,213,214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,487,484,483,422,398,226,132, - 131,0,2,6,7,8,9,15,17,21,83,86,130,193,201,202,203,204,205,206,207,208, - 209,210,211,212,213,214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,25,29,83,86,130,191,193,198,199, - 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,25,29,83,86,130,191,193,198,199, - 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,25,27,29,83,86,130,191,193,198,199, - 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,25,27,29,83,86,130,191,193,198,199, - 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,25,27,29,83,86,130,191,193,198,199, - 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,25,27,29,83,86,130,191,193,198,199, - 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,24,25,27,29,83,86,130,191,193,198, - 199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410,457, - 504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,24,25,27,29,83,86,130,191,193,198, - 199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410,457, - 504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,27,29,83,86,130,191,193, - 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410, - 457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,27,29,83,86,130,191,193, - 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,410, - 457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,83,86,130,191, - 193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214, - 410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,83,86,130,191, - 193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214, - 410,457,504, -396,394,393,392,0,39,40,41,45,46,47,49, -396,394,393,392,0,39,40,41,45,46,47,49, -396,394,393,392,0,39,40,41,45,46,47,49, -396,394,393,392,1,0,51,52, -396,394,393,392,1,0,51,52, -396,394,393,392,0,39,40,41,45,46,47,49, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -458,0,129, -645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445, - 422,420,398,394,392,228,1,0,16, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,621,506,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484, - 483,422,398,236,235,234,233,232,231,230,229,226,132,131,1,0,51,52, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, - 422,398,226,132,131,1,0,51,52, -507,0,258, -507,396,394,393,392,1,0,51,52, -645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445,422, - 420,398,394,392,228,1,0,16, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,1,0,51,52, -458,396,394,393,392,1,0,129, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,1,0,51,52, -646,645,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,621,620,492,490,487,486,485,484,483,477,475,473,445,423, - 422,420,398,396,394,393,392,1,0,51,52, -646,645,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,621,620,492,490,487,486,485,484,483,477,475,473,445,423, - 422,420,398,396,394,393,392,1,0, -396,394,393,392,0,39,40,41,45,46,47,49, -645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445, - 422,420,398,394,392,1,0, -629,628,627,626,625,0, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,3,130,410,502, -420,0,85, -420,0,85, -420,0,85, -420,0,85, -420,0,85, -420,0,85, -420,0,85, -420,0,85, -420,0,85, -420,0,85, -507,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,460,458,420,394,392,1,0,192, - 194,195,196,197, -507,489,488,487,486,485,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,460,458,420,394,392,1,0,192, - 194,195,196,197, -507,484,483,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467, - 466,465,464,463,462,461,460,458,420,396,394,393,392,1,0,190,191, -507,484,483,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467, - 466,465,464,463,462,461,460,458,420,396,394,393,392,1,0,190,191, -507,484,483,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467, - 466,465,464,463,462,461,460,458,420,396,394,393,392,1,0,190,191, -507,484,483,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467, - 466,465,464,463,462,461,460,458,420,396,394,393,392,1,0,190,191, -507,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465, - 464,463,462,461,460,458,420,396,394,393,392,1,0,186,187,188,189, -507,482,481,480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465, - 464,463,462,461,460,458,420,396,394,393,392,1,0,186,187,188,189, -507,478,477,476,475,474,473,472,471,470,469,468,467,466,465,464,463,462,461, - 460,458,420,396,394,393,392,1,0,184,185, -507,478,477,476,475,474,473,472,471,470,469,468,467,466,465,464,463,462,461, - 460,458,420,396,394,393,392,1,0,184,185, -507,476,475,474,473,472,471,470,469,468,467,466,465,464,463,462,461,460,458, - 420,396,394,393,392,1,0,182,183, -507,476,475,474,473,472,471,470,469,468,467,466,465,464,463,462,461,460,458, - 420,396,394,393,392,1,0,182,183, -396,394,393,392,0,39,40,41,45,46,47,49, -396,394,393,392,0,39,40,41,45,46,47,49, -506,236,235,234,233,232,231,230,229,1,0,51,52, -645,644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,622,621,620,492,490,487,486,485,484,483,477,475,473,445, - 422,420,398,394,392,228,1,0, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,621,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483, - 422,398,226,132,131,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27,28, - 29,57,83,86,130,191,193,198,199,200,201,202,203,204,205,206,207,208,209, - 210,211,212,213,214,403,410,450,457,504, -645,643,642,641,640,639,638,637,636,635,634,633,632,629,628,627,626,625,624, - 623,503,501,500,499,498,497,496,495,494,493,492,491,490,487,484,483,422, - 398,226,132,131,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,83,86,130, - 191,193,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213, - 214,410,457,504, -645,643,642,641,640,639,638,637,636,635,634,632,623,132,131,0,21,130,410, -645,643,642,641,640,639,638,637,636,635,634,632,629,628,627,626,625,623,420, - 398,1,0,51,52,135, -420,1,0,51,52, -420,1,0,51,52, -506,236,235,234,233,232,231,230,229,0,4,237,554, -420,0,85, +707,706,705,704,703,702,701,700,699,698,697,696,691,690,689,688,687,522,431, + 0,19,438, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +686,683,1,0,51,52, +686,683,0,10,12,18,20,436,486, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,429,427,426,425,135,134, + 1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,429,427,426,425,135,134, + 1,0,21,133,443, +683,1,0,51,52, +683,0,10,12,436, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, + 492,458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, + 492,458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, + 492,458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, + 492,458,431,232,135,134,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28,29, + 57,86,89,131,133,197,199,204,205,206,207,208,209,210,211,212,213,214, + 215,216,217,218,219,220,436,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,113,133, + 443, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,113,133, + 443, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,113,133, + 443, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, + 492,458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, + 492,458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, + 492,458,431,232,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,86,89,90,131,133,197,199,204,205,206,207,208,209,210,211,212, + 213,214,215,216,217,218,219,220,436,443,486,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, + 492,458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, + 492,458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, + 492,458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, + 492,458,431,232,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,86,89,90,131,133,197,199,204,205,206,207,208,209,210,211,212, + 213,214,215,216,217,218,219,220,436,443,486,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +429,427,426,425,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, +495,492,429,427,426,425,1,0,51,52, +495,492,429,427,426,425,1,0,51,52, +429,427,426,425,0,39,40,41,45,46,47,49, +457,0,87, +708,707,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,686,685,683,682,528,526,523,522,521,520,519,513,511,509,481,458, + 456,431,427,0,46,54,85,86,88,122,140,141,145,146,147,148,149,150,154, + 157,158,186,188,190,196,197,198,200,201,204,206,221,225,226,230,414,415, + 417,418,419,420,421,422,423,424, +429,427,426,425,0,39,40,41,45,46,47,49, +706,705,704,703,702,699,697,689,688,687,685,683,425,0,155, +429,427,426,425,0,39,40,41,45,46,47,49, +429,427,426,425,0,39,40,41,45,46,47,49, +699,698,697,696,691,690,689,688,687,0, +706,704,703,702,687,686,0, +707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481, + 458,456,431,427,425,234,1,0,16, +701,699,698,697,696,691,690,689,688,687,546,525,524,523,522,521,520,519,518, + 517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, + 499,498,497,496,494,456,429,427,426,425,1,0, +701,699,698,697,696,691,690,689,688,687,546,525,524,523,522,521,520,519,518, + 517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, + 499,498,497,496,494,456,429,427,426,425,1,0, +458,0,86, +458,0,86, +458,0,86, +458,0,86, +458,0,86, +458,0,86, +458,0,86, +458,0,86, +458,0,86, +458,0,86, +458,0,86, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +691,690,689,688,687,0, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +429,427,426,425,0,39,40,41,45,46,47,49, +429,427,426,425,0,39,40,41,45,46,47,49, +429,427,426,425,0,39,40,41,45,46,47,49, +429,427,426,425,0,39,40,41,45,46,47,49, +429,427,426,425,0,39,40,41,45,46,47,49, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, +429,427,426,425,0,39,40,41,45,46,47,49, +429,427,426,425,0,39,40,41,45,46,47,49, +708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, + 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, + 481,458,456,431,427,425,1,0, +429,427,426,425,0,39,40,41,45,46,47,49, +429,427,426,425,0,39,40,41,45,46,47,49, +707,706,705,704,703,702,701,700,699,698,697,696,691,690,689,688,687,522,431, + 427,425,1,0,51,52, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +429,427,426,425,0,39,40,41,45,46,47,49, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +546,481,429,427,426,425,1,0,51,52, +546,481,429,427,426,425,1,0,51,52, +546,481,429,427,426,425,1,0,51,52, +546,494,481,429,427,426,425,1,0,51,52, +546,481,429,427,426,425,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +546,429,427,426,425,1,0,51,52, +546,429,427,426,425,1,0,51,52, +494,1,0,51,52, +707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481,458, + 456,431,427,425,234,1,0,16, +707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481, + 458,456,431,427,425,234,1,0,16, +494,456,429,427,426,425,1,0,51,52, +494,456,0,88,132, +699,698,697,696,691,690,689,688,687,0, +707,701,699,698,697,696,691,690,689,688,687,685,429,427,426,425,223,222,1,0, + 224, +681,680,679,678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663, + 662,661,660,659,658,657,656,655,654,653,652,651,650,649,648,647,646,645, + 644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, + 626,625,624,623,622,621,620,619,618,617,616,615,614,613,612,611,609,608, + 607,606,605,604,603,602,601,600,599,598,597,595,594,593,592,591,590,589, + 588,587,586,585,584,583,582,581,580,579,578,577,576,575,574,573,572,571, + 570,569,568,567,566,565,564,563,562,561,560,559,558,557,556,555,554,553, + 552,551,550,549,548,547,0,31,32,245,258,259,260,261,262,263,264,265,266, + 267,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285, + 286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303, + 304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321, + 322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339, + 340,341,342,343,344,345,347,348,349,350,351,352,353,354,355,356,357,358, + 359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376, + 377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394, + 395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412, + 413, +707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481,458, + 456,431,427,425,234,1,0,16, +481,0,122, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, + 492,458,431,232,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,86,89,90,131,133,197,199,204,205,206,207,208,209,210,211,212, + 213,214,215,216,217,218,219,220,436,443,486,493,540, +494,429,427,426,425,1,0,132, +494,429,427,426,425,1,0,132, +494,429,427,426,425,1,0,132, +494,429,427,426,425,1,0,132, +494,429,427,426,425,1,0,132, +456,1,0,51,52, +456,0,88, +708,707,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,686,685,683,682,528,526,523,522,521,520,519,513,511,509,481,459, + 458,456,431,427,425,1,0,46,51,52,54,86,88,93,122,140,141,145,146,147, + 148,149,150,154,157,158,186,188,190,196,197,198,200,201,204,206,221,225, + 226,230,414,415,417,418,419,420,421,422,423,424, +699,698,697,696,691,690,689,688,687,0, +691,690,689,688,687,0, +707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481, + 458,456,431,427,425,1,0, +686,0, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +456,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, + 213,214,215,216,217,218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, + 213,214,215,216,217,218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, + 213,214,215,216,217,218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, + 213,214,215,216,217,218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, + 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, + 213,214,215,216,217,218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,25,29,86,89,131,133,197,199, + 204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,443, + 493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,25,29,86,89,131,133,197,199, + 204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,443, + 493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,25,27,29,86,89,131,133,197,199, + 204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,443, + 493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,25,27,29,86,89,131,133,197,199, + 204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,443, + 493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,25,27,29,86,89,131,133,197,199, + 204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,443, + 493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,25,27,29,86,89,131,133,197,199, + 204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,443, + 493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,24,25,27,29,86,89,131,133,197, + 199,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, + 443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,24,25,27,29,86,89,131,133,197, + 199,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, + 443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,29,86,89,131,133, + 197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219, + 220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,29,86,89,131,133, + 197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219, + 220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,86,89,131, + 133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, + 219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,86,89,131, + 133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, + 219,220,443,493,540, +429,427,426,425,1,0,51,52, +429,427,426,425,0,39,40,41,45,46,47,49, +429,427,426,425,0,39,40,41,45,46,47,49, +429,427,426,425,0,39,40,41,45,46,47,49, +429,427,426,425,1,0,51,52, +429,427,426,425,1,0,51,52, +429,427,426,425,0,39,40,41,45,46,47,49, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +494,0,132, +707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481, + 458,456,431,427,425,234,1,0,16, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,683,542,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520, + 519,492,458,431,242,241,240,239,238,237,236,235,232,135,134,1,0,51,52, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, + 492,458,431,232,135,134,1,0,51,52, +546,0,268, +546,429,427,426,425,1,0,51,52, +707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481,458, + 456,431,427,425,234,1,0,16, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,1,0,51,52, +494,429,427,426,425,1,0,132, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, +708,707,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,686,685,683,682,528,526,523,522,521,520,519,513,511,509,481,459, + 458,456,431,429,427,426,425,1,0,51,52, +708,707,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,686,685,683,682,528,526,523,522,521,520,519,513,511,509,481,459, + 458,456,431,429,427,426,425,1,0, +429,427,426,425,0,39,40,41,45,46,47,49, +707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481, + 458,456,431,427,425,1,0, +691,690,689,688,687,0, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,3,133,443,538, +456,0,88, +456,0,88, +456,0,88, +456,0,88, +456,0,88, +456,0,88, +456,0,88, +456,0,88, +456,0,88, +456,0,88, +456,0,88, +546,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, + 507,506,505,504,503,502,501,500,499,498,497,496,494,456,427,425,1,0,198, + 200,201,202,203, +546,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, + 507,506,505,504,503,502,501,500,499,498,497,496,494,456,427,425,1,0,198, + 200,201,202,203, +546,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503, + 502,501,500,499,498,497,496,494,456,429,427,426,425,1,0,196,197, +546,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503, + 502,501,500,499,498,497,496,494,456,429,427,426,425,1,0,196,197, +546,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503, + 502,501,500,499,498,497,496,494,456,429,427,426,425,1,0,196,197, +546,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503, + 502,501,500,499,498,497,496,494,456,429,427,426,425,1,0,196,197, +546,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, + 500,499,498,497,496,494,456,429,427,426,425,1,0,192,193,194,195, +546,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, + 500,499,498,497,496,494,456,429,427,426,425,1,0,192,193,194,195, +546,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, + 496,494,456,429,427,426,425,1,0,190,191, +546,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, + 496,494,456,429,427,426,425,1,0,190,191, +546,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,494, + 456,429,427,426,425,1,0,188,189, +546,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,494, + 456,429,427,426,425,1,0,188,189, +429,427,426,425,0,39,40,41,45,46,47,49, +429,427,426,425,0,39,40,41,45,46,47,49, +429,427,426,425,0,39,40,41,45,46,47,49, +542,242,241,240,239,238,237,236,235,1,0,51,52, +707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, + 688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481, + 458,456,431,427,425,234,1,0, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, + 492,458,431,232,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,86,89,131,133,197,199,204,205,206,207,208,209,210,211,212,213, + 214,215,216,217,218,219,220,436,443,486,493,540, +707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, + 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, + 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, + 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,443,493,540, +707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, +707,705,704,703,702,701,700,699,698,697,696,694,691,690,689,688,687,685,456, + 431,1,0,51,52,138, +456,1,0,51,52, +456,1,0,51,52, +542,242,241,240,239,238,237,236,235,0,4,243,596, +456,0,88, }; -static unsigned const char ag_astt[23459] = { - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,7,1,1,9,5,2,2,2,2,2,2,2,2, - 2,2,2,2,2,1,8,8,8,8,8,2,2,1,1,7,1,0,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5, - 5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,4,4,4,4,2,4,4,7,2,1, - 1,1,1,1,1,1,1,1,1,1,7,1,3,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +static unsigned const char ag_astt[27588] = { + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,7,1,1,9,5,2,2,2,2,2, + 2,2,2,2,2,2,2,2,1,8,8,8,8,8,2,2,2,2,2,1,1,7,1,0,1,1,1,1,1,1,1,1,1,1,1,5,5, + 5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,4,4,4,4, + 2,4,4,7,2,1,1,1,1,1,1,1,1,1,1,1,7,1,3,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,7,1,3,1,7,2,8,8,1,1,1,1,1,7,3,3,1,3,1,1,1,1,1,8,8,8,8,8,8,8, + 5,1,7,1,3,1,7,2,8,8,1,1,1,1,1,7,3,3,1,3,1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,5,5,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,5,5,8,8,8,8,8,8,8,1,7,1, + 1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,1,1,8,8,5,5,1,5,5,5,5,2,2, - 9,7,1,1,1,1,1,1,1,2,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,1,1,8,8,8,8, + 8,5,5,1,5,5,5,5,2,2,9,7,1,1,1,1,1,1,1,2,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,2,2,2,2,2,2,2,2,2,2,1,8,8,8,8,8,2,2,1,3,1,7,1,3,3,1,1,3,1,1,1,1,1,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5, - 1,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7, - 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 2,2,2,2,2,2,2,2,2,2,1,8,8,8,8,8,2,2,2,2,2,1,3,1,7,1,3,3,1,1,3,1,1,1,1,1,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, - 5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,7,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,2,7,1,1, - 1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,2, - 2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7, - 1,1,1,1,1,7,1,1,2,2,7,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, + 5,1,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, + 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, + 7,1,3,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1, + 1,1,2,7,1,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,7,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,1,7,1,1,1,1,1,2,2,7,1,1,1,1,1,1,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,7,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1, + 7,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,7,3,3,3,1,3,1,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 7,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,9,7,3,3,3,1,3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,8,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, - 2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 1,1,1,8,8,8,8,1,1,1,1,1,2,2,7,1,1,1,1,1,3,3,1,3,1,1,1,1,1,2,1,2,2,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,1,1,1,8,8,8,8,8,8,8,1,1,1,1,1,2,2,7,1,1,1,1,1,3,3,1,3,1,1, + 1,1,1,2,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1, - 3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3, 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5, 5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5, - 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, - 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7, + 5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, 1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1, 3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3, 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5, 5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5, 5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5, 5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5, - 5,7,1,3,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5, + 5,7,1,3,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1, + 1,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3, - 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7, - 1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3, - 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7, - 1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, - 5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, - 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1, - 7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3,5, + 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1, + 3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5, + 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1, + 3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, + 7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, + 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, + 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, 1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1, + 7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, + 1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, - 1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8, - 8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, - 1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, - 8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, - 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, - 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,5,2,2,2,2,2,2,2,2,2,2,2,5,2, - 5,5,2,2,2,2,2,5,2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,2, - 5,5,5,5,1,7,1,3,2,5,5,5,5,5,1,7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,1,4,4,4,4,4,4,7,1,4,4,4,4,1,7,1,1,5,1,2,2,2,2,2, - 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, - 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, + 1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8, + 8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1, + 7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, + 8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, + 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, + 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, + 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,5,2,2,2,2,2,2,2,2,2,2,2,5, + 2,5,5,2,2,2,2,2,5,2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 2,5,5,5,5,1,7,1,3,2,5,5,5,5,5,1,7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,4,4,4,4,4,4,7,1,4,4,4,4,1,7,1,1,5,1,2,2,2,2, + 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,7,2,2,2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,2,2, - 1,1,2,8,8,8,8,1,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,1,4,4,4,4,7,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,2,1,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,7,2,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1, - 1,7,2,2,1,2,1,1,1,8,8,8,8,1,7,1,1,2,2,2,2,2,7,2,2,2,2,7,2,2,7,4,4,4,4,4,4, - 4,2,2,2,2,4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,4,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2, - 2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,7,1,10,10,10,10,10,5,2,10,10,10,10,10,10,10,10,10,7,10, - 10,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,7,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,7,10,10,10,10,10,10,10,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,9,2,2,1,1,2,10,10,10, - 10,10,9,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4, - 4,4,4,2,2,4,7,2,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1, - 3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5, + 1,1,1,1,1,1,1,1,7,2,2,1,2,2,2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,1,2,2,1,1,2,8,8,8,8,1,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,4,4,4,4,7,1,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, + 1,7,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,1,1,1,1,7,2, + 2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,8,8,8,8,1,7,1,1,2,2,2,2,2,7,2,2,2,2,7, + 2,2,7,4,4,4,4,4,4,4,2,2,2,2,4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,4,1,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,7,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,10,10,10,10,10,5,2,10,10,10,10,10, + 10,10,10,10,7,10,10,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,10,10,10,10,10,10,10,10,10,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,9,2, + 2,1,1,2,10,10,10,10,10,9,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,2,4,4,4,4,2,2,4,7,2,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,7,1,3,5,5, + 7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1, + 8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,2,2,2,2, + 2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8, - 1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,5,5,5, - 5,5,5,5,5,5,5,5,5,5,2,2,2,2,2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7, - 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2, - 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, - 2,1,2,1,1,1,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, - 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, - 2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,2,2,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,2,2,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,1,7,1,3,5,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,5,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,1,7,1,3,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,7,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, + 5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1, + 1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,1,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,1,2,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,1,7,1,3,5,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,5,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,1,7,1,3,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,7,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1, - 2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1, - 7,1,1,8,8,8,8,1,7,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,8,8,8, - 8,1,7,1,1,10,10,1,10,10,10,10,10,10,10,10,10,10,10,10,2,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,7,5,5,5,5,5,7, - 1,3,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,1,5, + 2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,1,7,1,1,8,8,8,8, + 1,7,1,1,8,8,8,8,1,7,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,8,8, + 8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7, + 1,1,10,10,1,10,10,10,10,10,10,10,10,10,10,10,10,2,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,7,5,5,5,5,5,7,1,3,8, + 8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, + 7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,1,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, @@ -3893,384 +4357,429 @@ static unsigned const char ag_astt[23459] = { 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,7,3,1,7,3,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,2,2,2,2,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,1,1,2,8,8,8,8,1, - 7,1,1,1,1,1,1,1,1,7,1,3,3,1,3,1,1,1,2,2,2,2,2,2,2,2,2,2,2,7,3,2,1,2,2,2,2, - 2,2,2,7,3,2,2,2,1,2,2,2,2,7,2,1,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, - 1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, - 2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1, - 1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,5,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,7,3, + 1,7,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,7,1,1,2,2,1,2,2,2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,1,2,2,1,1,2,8,8,8,8,1,7,1,1,1,1,1,1,1,1,7,1,3,3,1,3,1,1,1,2,2,2,1, + 1,1,2,2,2,2,2,7,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,7,3,2,1,2,2,2,2,2,2,2,7,3, + 2,2,2,1,2,2,2,2,7,2,1,7,1,1,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1, - 1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, - 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, - 2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1, - 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, - 1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, - 2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2, - 1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, + 2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2, + 1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2, + 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, + 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, + 2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1, + 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, + 1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1, 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1, - 1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, - 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, - 2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, + 1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1, + 1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1, + 2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, + 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, + 1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, 2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, - 2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, - 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, - 1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2, - 1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, - 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, - 1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, + 1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1, - 2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2, - 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, - 1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, - 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1, + 1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, + 2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, + 2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2, + 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2, + 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, + 1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, + 1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, + 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, + 2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, + 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2, + 1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1, 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, - 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, - 1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, - 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, - 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, + 1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1, + 1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, + 2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2, + 1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1, + 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2, + 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, + 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, + 2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1, 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, - 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, - 1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, - 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2, - 1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, + 1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, + 1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1, + 1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,7,2,2,2,2,2,2,1,1,2,2,2,2,2,2,7,2, - 2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2,1,2,2,2, - 2,2,2,2,7,2,2,2,2,1,2,2,2,2,2,2,2,7,2,2,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2, - 2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2, - 1,2,2,2,2,2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7, - 2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2, - 2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1, - 1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,2,1,1,1,1,1,1,2,9,7,2,1,1,2,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1, + 2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, + 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, + 1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,1,1,2,2,2,2,2, + 7,2,2,2,2,2,2,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,7,2,2, + 2,2,2,2,2,2,2,2,7,2,2,2,2,1,2,2,2,2,2,2,2,7,2,2,2,2,1,2,2,2,2,2,2,2,7,2,2, + 2,2,1,2,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2, + 2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2, + 7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2, + 2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,2,9,7,2,1,1,2,1,1,1,1,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,7,2,1,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,1,7,1,3,1,2,7,2,1,1,2,1,1, - 5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, - 1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2,2,4,7,2,1,1,5,1,7,1,3,2,7,1,1,1,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2, - 1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, - 2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1, - 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1, - 3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7, - 1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, - 7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1, + 3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,5,5,5,5,5,7,1,3,5,5,5,5,5,7, + 1,3,5,5,1,7,1,3,1,2,7,2,1,1,2,1,1,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2, + 2,4,7,2,1,1,5,1,7,1,3,2,7,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,1,2,1, - 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5, + 5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1, + 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2, + 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2, + 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1, - 1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, - 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, + 5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2, + 1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1, - 2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,7,1,3,5,5,5, - 5,5,5,5,7,1,3,1,1,1,1,7,3,3,1,3,1,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,2,1,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,7,2,2, - 1,2,1,1,1,2,1,2,2,2,2,2,1,1,1,1,2,3,7,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7, - 2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,4,4,4,4, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1, + 1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,1,1,1,1,7, + 3,3,1,3,1,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,7,2,2,1,2,1,1,1,2,1,2,2,2,2,2, + 1,1,1,1,2,3,7,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,2,2,2,2,2, + 2,2,2,2,7,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,4,4,4,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,7,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7, - 1,1,7,1,1,7,1,1,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,7,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, - 1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 4,4,4,4,4,4,4,7,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7, + 1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,7,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1, - 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1, + 7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,7,2,2,1,2,1,1,1,1,1, - 1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1, - 1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,7,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1, - 2,1,1,1,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,7,1, - 3,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2, - 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,3,3,1,3,1,1,1,5,5,5, - 5,5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,8,8,8, + 5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2, + 1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1, + 2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1, + 1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,7,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2, + 1,2,1,1,1,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,7, + 1,3,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2, + 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, + 1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,3,3,1, + 3,1,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, + 7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,8,1,7,1,1,2, - 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,7,1,3,1,1,7,2,1,2,2,2,2,2,2, - 2,2,2,7,9,2,2,1,1,2,10,10,10,10,10,9,4,4,4,4,2,2,4,7,2,1,1,1,1,1,1,1,1,1,1, + 8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,5,5,5,5, + 5,5,7,1,3,8,1,7,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,7,1,3, + 1,1,7,2,1,2,2,2,2,2,2,2,2,2,7,9,2,2,1,1,2,10,10,10,10,10,9,4,4,4,4,2,2,4,7, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, - 2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1, - 1,2,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,1,4,4, - 4,4,4,7,1,5,1,7,1,3,1,7,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,7,1, - 1,1,1,1,7,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,7,2,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2, - 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,1,2,1, + 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,7,1,1,4,4, + 4,4,4,7,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,5,1,7,1,3,1,7,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,8,1,7,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,7,1,1,1,1,1,7,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2, + 7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, + 1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, + 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, + 1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, + 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2, + 1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1, 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, - 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, - 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, - 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, - 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, + 1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2, + 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2, + 1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,1,2,2, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,1,2,2,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,1,2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, - 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, - 1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, - 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2, - 1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, - 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1, - 1,2,1,2,1,1,1,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, - 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, - 1,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,2,2,2, + 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, + 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, + 2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 7,2,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, - 1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, - 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, - 1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, - 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, - 2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, - 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, - 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, - 1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, - 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, - 2,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,8,8, - 8,8,1,7,1,1,8,8,8,8,1,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2, - 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, - 1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, + 1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, + 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,1,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7, + 2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,1,1, + 1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, + 1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,1,7,1,1,1,7,1,5,5,5,5,5,1,7,1,3,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, - 1,4,4,4,4,4,7,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, - 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,5,5,5,5,5,7,1,1,1,1,7,2,2,1,2,1,1,1,4,4,4,4,4,4,4,4,2,2,2,2,4,4,4, - 4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,7,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1, - 7,2,1,7,2,1,7,2,1,7,3,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1, - 1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7, - 2,2,1,2,1,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2, - 2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, - 2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,5,2,1,7,1,3,2,5,5,7,1,3,8,1,7,1,1,2,2,2,2, - 2,2,2,2,2,7,2,2,1,1,7,2 + 8,8,8,8,8,8,1,7,1,1,1,7,1,5,5,5,5,5,1,7,1,3,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, + 1,1,1,4,4,4,4,4,7,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,5,5,5,5,5,7,1,1,1,1,7,2,2,1,2,1,1,1,4,4,4,4,4,4,4,4,2,2,2,2,4, + 4,4,4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,7, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7, + 2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,3,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,4,1,1,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1, + 1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,1,2, + 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, + 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, + 2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 5,2,1,7,1,3,2,5,5,7,1,3,8,1,7,1,1,2,2,2,2,2,2,2,2,2,7,2,2,1,1,7,2 }; static const unsigned short ag_pstt[] = { -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,1,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,1,2, 18,20, -123,123,123,123,123,123,123,123,123,123,123,123,123,3,8,8,8,8,8,122,121,7, - 10,2,9,0,11,11,11,10,8,11,5,5,4,6,4, -19,19,19,19,19,19,19,19,19,19,19,1,3,1,849, -124,124,124,124,124,124,124,124,124,124,124,124,125,125,125,125,125,124,155, - 124,155,155,155,155,154,155,155,4,125, +129,129,129,129,129,129,129,129,129,129,129,129,129,3,8,8,8,8,8,164,163,162, + 128,127,7,10,2,9,0,11,11,11,10,8,11,5,5,4,6,4, +19,19,19,19,19,19,19,19,19,19,19,1,3,1,890, +130,130,130,130,130,130,130,130,130,130,130,130,131,131,131,131,131,130,161, + 130,161,161,161,161,160,161,161,4,131, 12,13,14,15,16,17,18,19,20,21,22,5,33,39,32,31,30,29,28,27,26,25,24,23, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, @@ -4278,8 +4787,9 @@ static const unsigned short ag_pstt[] = { 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1, - 6,1,840, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,1,6,1,881, 34,7,37, 36,36,35,37,38,39,34,8,24,24,42,24,41,40,40,36,36, 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, @@ -4288,1578 +4798,1823 @@ static const unsigned short ag_pstt[] = { 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, - 43,43,43,43,43,43,43,43,43,43,43,43,43,43,19,19,43,43,43,43,43,43,43,1, - 9,1,43, -123,123,123,123,123,123,123,123,123,123,123,123,123,107,108,109,110,111,112, - 113,114,61,62,63,64,65,115,116,117,118,119,120,66,67,68,69,70,121,122, - 123,71,72,73,74,75,124,125,126,127,128,129,130,131,132,133,134,135,136, - 137,138,104,59,60,143,144,145,146,147,148,149,150,151,152,153,154,155, - 156,139,140,141,142,76,77,78,79,80,45,46,47,81,82,83,84,85,86,87,88,89, - 48,49,90,91,92,93,94,95,96,97,50,51,52,98,99,53,54,100,101,102,103,55, - 56,57,58,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, - 220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,15,16, - 19,220,220,20,20,35,20,20,20,20,122,121,18,10,216,217,218,215,221,220, - 220,35,219,97,98,221,44,214,215,215,215,215,215,215,215,215,215,308,308, - 308,308,308,309,310,311,312,315,315,315,316,317,321,321,321,321,322,323, - 324,325,326,327,328,329,332,332,332,333,334,335,336,337,338,339,340,341, - 345,345,345,345,346,347,348,349,350,199,198,197,196,213,212,211,210,209, - 208,207,206,205,204,203,202,201,200,159,106,158,105,157,195,194,193,192, - 191,190,189,188,187,186,185,184,183,182,181,180,180,180,180,180,180,179, - 178,177,176,176,176,176,176,176,175,174,173,172,171,170,169,169,169,169, - 168,168,168,167,166,165,164,163,162,161,160,214, -123,123,123,123,123,123,123,123,123,123,123,123,123,3,8,8,8,8,8,122,121,7,4, - 10,11,9,3,3,10,8,3,5,5,4,6,4, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,12,1,862, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,13,1,861, -19,1,14,1,860, -19,19,19,19,19,15,1,859, -19,19,19,19,19,16,1,858, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,17,1,857, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,18,1,856, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,19,1,855, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,20,1,854, -19,19,1,21,1,851, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,22,1,844, -123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,23,222,223,214, - 214, -123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,24,224,214,214, -132,25,227,225,226, -228,228,228,228,1,26,1,228, -229,229,229,229,1,27,1,229, -123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,28,230,214,214, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,29,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,283,285,271,209,214,284,272,276,275,274,273,208,276,266,265,264, - 263,262,261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,30,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,283,286,271,209,214,284,272,276,275,274,273,208,276,266,265,264, - 263,262,261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,31,287,214,214, -288,290,32,291,289, -150,132,33,295,225,294,292,226,293, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,19,19,43,43,43,43,43,43, + 43,1,9,1,43, +129,129,129,129,129,129,129,129,129,129,129,129,129,111,112,113,114,115,116, + 117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134, + 62,63,64,65,66,67,135,136,137,138,139,140,68,69,70,71,72,141,142,143,73, + 74,75,76,77,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158, + 107,59,60,61,165,166,167,168,169,170,171,172,173,174,175,176,177,178, + 179,180,159,160,161,162,163,164,78,79,80,81,82,83,45,46,47,84,85,86,87, + 88,89,90,91,92,48,49,93,94,95,96,97,98,99,100,50,51,52,101,102,53,54, + 103,104,105,106,55,56,57,58,265,265,265,265,265,265,265,265,265,265,265, + 265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265, + 265,265,15,16,19,265,265,265,265,265,20,20,35,20,20,20,20,128,127,18,10, + 261,262,263,260,266,265,265,35,264,103,104,266,44,259,196,260,260,260, + 260,260,260,260,260,260,260,325,325,325,325,325,326,327,328,329,332,332, + 332,333,334,338,338,338,338,339,340,341,342,343,344,345,346,349,349,349, + 350,351,352,353,354,355,356,357,358,362,362,362,362,363,364,365,366,367, + 368,242,241,240,239,238,237,258,257,256,255,254,253,252,251,250,249,248, + 247,246,245,244,243,184,110,183,109,182,108,181,236,235,234,233,232,231, + 230,229,228,227,226,225,224,223,222,221,221,221,221,221,221,220,219,218, + 217,217,217,217,217,217,216,215,214,213,212,211,210,210,210,210,209,209, + 209,209,208,207,206,205,204,203,202,201,200,199,198,197,195,194,193,192, + 191,190,189,188,187,186,185,259, +129,129,129,129,129,129,129,129,129,129,129,129,129,3,8,8,8,8,8,164,163,162, + 128,127,7,4,10,11,9,3,3,10,8,3,5,5,4,6,4, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,12,1,906, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,13,1,905, +19,1,14,1,904, +19,19,19,19,19,15,1,903, +19,19,19,19,19,16,1,902, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,17,1,901, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,18,1,900, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,19,1,899, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,20,1,898, +19,19,19,19,19,1,21,1,892, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,22,1,885, +129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,23,267,268,259, + 259, +129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,24,269,259,259, +138,25,272,270,271, +273,273,273,273,1,26,1,273, +274,274,274,274,1,27,1,274, +129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,28,275,259,259, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,29,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,330,332,318,218,304,259,331,319,323,322,321,320,217,323,313, + 312,311,310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,30,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,330,333,318,218,304,259,331,319,323,322,321,320,217,323,313, + 312,311,310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,31,334,259,259, +335,337,339,341,343,32,344,342,340,338,336, +156,138,33,348,270,347,345,271,346, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,34,1,835, + 19,19,19,19,19,19,19,34,1,876, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,35,1,841, -296,22,36,297,297,297, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,35,1,882, +349,22,36,350,350,350, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,37,1,839, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,37,1,880, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,38, - 1,837, + 1,878, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,39,1,836, -298,300,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318, - 319,320,321,328,331,332,333,334,268,270,330,322,326,323,325,329,301,299, - 324,256,327,35,37,335,38,34,15,40,16,15,15,40,13,40,15,15,15,15,15,15, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,39,1,877, +351,353,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371, + 372,373,374,381,384,385,386,387,315,317,383,375,379,376,378,382,354,352, + 377,302,380,35,37,388,38,34,15,40,16,15,15,40,13,40,15,15,15,15,15,15, 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, 15,15,15,15,15,15,15,15,15,15,15, -298,300,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318, - 319,320,321,328,331,332,333,334,268,270,330,322,326,323,325,329,301,299, - 324,256,327,35,38,337,336,41,336,337,336,336,336,336,336,336,336,336, - 336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, - 336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, -298,300,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318, - 319,320,321,328,331,332,333,334,268,270,330,322,326,323,325,329,301,299, - 324,256,327,35,38,338,336,42,336,338,336,336,336,336,336,336,336,336, - 336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, - 336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, -123,123,123,123,123,123,123,123,123,123,123,123,123,107,108,109,110,111,112, - 113,114,61,62,63,64,65,115,116,117,118,119,120,66,67,68,69,70,121,122, - 123,71,72,73,74,75,124,125,126,127,128,129,130,131,132,133,134,135,136, - 137,138,104,59,60,143,144,145,146,147,148,149,150,151,152,153,154,155, - 156,139,140,141,142,76,77,78,79,80,45,46,47,81,82,83,84,85,86,87,88,89, - 48,49,90,91,92,93,94,95,96,97,50,51,52,98,99,53,54,100,101,102,103,55, - 56,57,58,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339, - 339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,15,16, - 19,339,339,339,339,35,37,38,39,34,122,121,43,216,217,218,215,340,23,23, - 42,23,41,40,40,339,339,36,219,97,98,340,44,214,215,215,215,215,215,215, - 215,215,215,308,308,308,308,308,309,310,311,312,315,315,315,316,317,321, - 321,321,321,322,323,324,325,326,327,328,329,332,332,332,333,334,335,336, - 337,338,339,340,341,345,345,345,345,346,347,348,349,350,199,198,197,196, - 213,212,211,210,209,208,207,206,205,204,203,202,201,200,159,106,158,105, - 157,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,180, - 180,180,180,180,179,178,177,176,176,176,176,176,176,175,174,173,172,171, - 170,169,169,169,169,168,168,168,167,166,165,164,163,162,161,160,214, -341,341,341,341,341,341,1,44,1,341, -19,19,19,19,19,19,45,1,987, -19,19,19,19,19,19,46,1,986, -19,19,19,19,19,19,47,1,985, -19,19,19,19,19,19,48,1,975, -19,19,19,19,19,19,49,1,974, -19,19,19,19,19,19,50,1,965, -19,19,19,19,19,19,51,1,964, -19,19,19,19,19,19,52,1,963, -19,19,19,19,19,19,53,1,960, -19,19,19,19,19,19,54,1,959, -19,19,19,19,19,19,55,1,954, -19,19,19,19,19,19,56,1,953, -19,19,19,19,19,19,57,1,952, -19,19,19,19,19,19,58,1,951, -19,19,19,19,19,19,19,19,19,19,59,1,1014, -19,19,19,19,19,19,19,19,60,1,1013, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,61,1,1054, +351,353,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371, + 372,373,374,381,384,385,386,387,315,317,383,375,379,376,378,382,354,352, + 377,302,380,35,38,390,389,41,389,390,389,389,389,389,389,389,389,389, + 389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389, + 389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389, +351,353,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371, + 372,373,374,381,384,385,386,387,315,317,383,375,379,376,378,382,354,352, + 377,302,380,35,38,391,389,42,389,391,389,389,389,389,389,389,389,389, + 389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389, + 389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389, +129,129,129,129,129,129,129,129,129,129,129,129,129,111,112,113,114,115,116, + 117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134, + 62,63,64,65,66,67,135,136,137,138,139,140,68,69,70,71,72,141,142,143,73, + 74,75,76,77,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158, + 107,59,60,61,165,166,167,168,169,170,171,172,173,174,175,176,177,178, + 179,180,159,160,161,162,163,164,78,79,80,81,82,83,45,46,47,84,85,86,87, + 88,89,90,91,92,48,49,93,94,95,96,97,98,99,100,50,51,52,101,102,53,54, + 103,104,105,106,55,56,57,58,392,392,392,392,392,392,392,392,392,392,392, + 392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392, + 392,392,15,16,19,392,392,392,392,392,392,392,35,37,38,39,34,128,127,43, + 261,262,263,260,393,23,23,42,23,41,40,40,392,392,36,264,103,104,393,44, + 259,196,260,260,260,260,260,260,260,260,260,260,325,325,325,325,325,326, + 327,328,329,332,332,332,333,334,338,338,338,338,339,340,341,342,343,344, + 345,346,349,349,349,350,351,352,353,354,355,356,357,358,362,362,362,362, + 363,364,365,366,367,368,242,241,240,239,238,237,258,257,256,255,254,253, + 252,251,250,249,248,247,246,245,244,243,184,110,183,109,182,108,181,236, + 235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,221,221,221, + 221,221,220,219,218,217,217,217,217,217,217,216,215,214,213,212,211,210, + 210,210,210,209,209,209,209,208,207,206,205,204,203,202,201,200,199,198, + 197,195,194,193,192,191,190,189,188,187,186,185,259, +394,394,394,394,394,394,1,44,1,394, +19,19,19,19,19,19,45,1,1034, +19,19,19,19,19,19,46,1,1033, +19,19,19,19,19,19,47,1,1032, +19,19,19,19,19,19,48,1,1022, +19,19,19,19,19,19,49,1,1021, +19,19,19,19,19,19,50,1,1012, +19,19,19,19,19,19,51,1,1011, +19,19,19,19,19,19,52,1,1010, +19,19,19,19,19,19,53,1,1007, +19,19,19,19,19,19,54,1,1006, +19,19,19,19,19,19,55,1,1001, +19,19,19,19,19,19,56,1,1000, +19,19,19,19,19,19,57,1,999, +19,19,19,19,19,19,58,1,998, +19,19,19,19,19,19,19,19,19,19,59,1,1067, +19,19,19,19,19,19,19,19,19,19,60,1,1066, +19,19,19,19,19,19,19,19,61,1,1065, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,62,1,1108, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,63,1,1107, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,64,1,1106, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,65,1,1105, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,66,1,1104, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,67,1,1103, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,68,1,1096, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,69,1,1095, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,70,1,1094, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,71,1,1093, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,72,1,1092, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,73,1,1088, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,74,1,1087, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,75,1,1086, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,76,1,1085, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,77,1,1084, +19,19,19,19,19,19,78,1,1040, +19,19,19,19,19,19,79,1,1039, +19,19,19,19,19,19,80,1,1038, +19,19,19,19,19,19,81,1,1037, +19,19,19,19,19,19,82,1,1036, +19,19,19,19,19,19,83,1,1035, +19,19,19,19,19,19,84,1,1031, +19,19,19,19,19,19,85,1,1030, +19,19,19,19,19,19,86,1,1029, +19,19,19,19,19,19,87,1,1028, +19,19,19,19,19,19,88,1,1027, +19,19,19,19,19,19,89,1,1026, +19,19,19,19,19,19,90,1,1025, +19,19,19,19,19,19,91,1,1024, +19,19,19,19,19,19,92,1,1023, +19,19,19,19,19,19,93,1,1020, +19,19,19,19,19,19,94,1,1019, +19,19,19,19,19,19,95,1,1018, +19,19,19,19,19,19,96,1,1017, +19,19,19,19,19,19,97,1,1016, +19,19,19,19,19,19,98,1,1015, +19,19,19,19,19,19,99,1,1014, +19,19,19,19,19,19,100,1,1013, +19,19,19,19,19,19,101,1,1009, +19,19,19,19,19,19,102,1,1008, +19,19,19,19,19,19,103,1,1005, +19,19,19,19,19,19,104,1,1004, +19,19,19,19,19,19,105,1,1003, +19,19,19,19,19,19,106,1,1002, +19,19,19,19,19,107,1,1068, +395,395,395,395,395,395,395,395,395,1,108,1,395, +396,396,396,396,396,396,396,396,396,1,109,1,396, +397,397,397,397,397,397,397,1,110,1,397, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,62,1,1053, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,111,1,1132, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,63,1,1052, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,112,1,1131, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,64,1,1051, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,113,1,1130, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,65,1,1050, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,114,1,1129, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,66,1,1043, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,115,1,1128, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,67,1,1042, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,116,1,1127, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,68,1,1041, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,117,1,1126, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,69,1,1040, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,118,1,1125, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,70,1,1039, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,119,1,1124, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,71,1,1035, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,120,1,1123, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,72,1,1034, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,121,1,1122, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,73,1,1033, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,122,1,1121, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,74,1,1032, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,123,1,1120, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,75,1,1031, -19,19,19,19,19,19,76,1,992, -19,19,19,19,19,19,77,1,991, -19,19,19,19,19,19,78,1,990, -19,19,19,19,19,19,79,1,989, -19,19,19,19,19,19,80,1,988, -19,19,19,19,19,19,81,1,984, -19,19,19,19,19,19,82,1,983, -19,19,19,19,19,19,83,1,982, -19,19,19,19,19,19,84,1,981, -19,19,19,19,19,19,85,1,980, -19,19,19,19,19,19,86,1,979, -19,19,19,19,19,19,87,1,978, -19,19,19,19,19,19,88,1,977, -19,19,19,19,19,19,89,1,976, -19,19,19,19,19,19,90,1,973, -19,19,19,19,19,19,91,1,972, -19,19,19,19,19,19,92,1,971, -19,19,19,19,19,19,93,1,970, -19,19,19,19,19,19,94,1,969, -19,19,19,19,19,19,95,1,968, -19,19,19,19,19,19,96,1,967, -19,19,19,19,19,19,97,1,966, -19,19,19,19,19,19,98,1,962, -19,19,19,19,19,19,99,1,961, -19,19,19,19,19,19,100,1,958, -19,19,19,19,19,19,101,1,957, -19,19,19,19,19,19,102,1,956, -19,19,19,19,19,19,103,1,955, -19,19,19,19,19,104,1,1015, -342,342,342,342,342,342,342,342,342,1,105,1,342, -343,343,343,343,343,343,343,1,106,1,343, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,107,1,1062, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,108,1,1061, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,109,1,1060, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,110,1,1059, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,111,1,1058, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,112,1,1057, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,113,1,1056, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,114,1,1055, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,115,1,1049, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,116,1,1048, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,117,1,1047, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,118,1,1046, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,119,1,1045, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,120,1,1044, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,121,1,1038, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,122,1,1037, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,123,1,1036, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,124,1,1030, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,125,1,1029, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,126,1,1028, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,127,1,1027, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,128,1,1026, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,129,1,1025, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,130,1,1024, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,131,1,1023, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,132,1,1022, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,133,1,1021, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,134,1,1020, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,135,1,1019, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,136,1,1018, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,137,1,1017, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,138,1,1016, -19,19,19,19,19,19,19,19,19,139,1,996, -19,19,19,19,19,19,19,19,19,140,1,995, -19,19,19,19,19,141,1,994, -19,19,19,19,19,142,1,993, -19,19,19,19,19,19,19,19,143,1,1012, -19,19,19,19,19,19,19,19,144,1,1011, -19,19,19,19,19,19,19,19,145,1,1010, -19,19,19,19,19,19,19,19,19,19,146,1,1008, -19,19,19,19,19,19,19,19,19,19,147,1,1007, -19,19,19,19,19,19,19,19,19,19,148,1,1006, -19,19,19,19,19,19,19,19,19,19,149,1,1005, -19,19,19,19,19,19,19,19,19,19,150,1,1004, -19,19,19,19,19,19,19,19,19,19,151,1,1003, -19,19,19,19,19,19,19,19,19,19,152,1,1002, -19,19,19,19,19,19,19,19,19,19,153,1,1001, -19,19,19,19,19,19,19,19,19,19,154,1,1000, -19,19,19,19,19,19,19,19,19,19,155,1,999, -19,19,19,19,19,19,19,19,19,19,156,1,998, -344,344,344,344,1,157,1,344, -345,1,158,1,345, -346,1,159,1,346, -347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347, - 347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347, - 347,347,347,347,1,160,1,347, -348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348, - 348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348, - 348,348,348,348,1,161,1,348, -349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349, - 349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349, - 349,349,349,349,1,162,1,349, -350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350, - 350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350, - 350,350,350,350,1,163,1,350, -351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351, - 351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351, - 351,351,351,351,1,164,1,351, -352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352, - 352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352, - 352,352,352,352,1,165,1,352, -353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353, - 353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353, - 353,353,353,353,1,166,1,353, -354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354, - 354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354, - 354,354,354,354,1,167,1,354, -355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355, - 355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355, - 355,355,355,355,1,168,1,355, -356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, - 356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, - 356,356,356,356,1,169,1,356, -357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357, - 357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357, - 357,357,357,357,1,170,1,357, -358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, - 358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, - 358,358,358,358,1,171,1,358, -359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, - 359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, - 359,359,359,359,1,172,1,359, -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, - 360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, - 360,360,360,360,1,173,1,360, -361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361, - 361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361, - 361,361,361,361,1,174,1,361, -362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362, - 362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362, - 362,362,362,362,1,175,1,362, -363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363, - 363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363, - 363,363,363,363,1,176,1,363, -364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364, - 364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364, - 364,364,364,364,1,177,1,364, -365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365, - 365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365, - 365,365,365,365,1,178,1,365, -366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366, - 366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366, - 366,366,366,366,1,179,1,366, -367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367, - 367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367, - 367,367,367,367,1,180,1,367, -368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, - 368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, - 368,368,368,368,1,181,1,368, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, - 369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, - 369,369,369,369,1,182,1,369, -370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, - 370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, - 370,370,370,370,1,183,1,370, -371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371, - 371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371, - 371,371,371,371,1,184,1,371, -372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372, - 372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372, - 372,372,372,372,1,185,1,372, -373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373, - 373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373, - 373,373,373,373,1,186,1,373, -374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374, - 374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374, - 374,374,374,374,1,187,1,374, -375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375, - 375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375, - 375,375,375,375,1,188,1,375, -376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376, - 376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376, - 376,376,376,376,1,189,1,376, -377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377, - 377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377, - 377,377,377,377,1,190,1,377, -378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378, - 378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378, - 378,378,378,378,1,191,1,378, -379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379, - 379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379, - 379,379,379,379,1,192,1,379, -380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380, - 380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380, - 380,380,380,380,1,193,1,380, -381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381, - 381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381, - 381,381,381,381,1,194,1,381, -382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382, - 382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382, - 382,382,382,382,1,195,1,382, -383,383,383,383,383,383,383,383,1,196,1,383, -384,384,384,384,384,384,384,384,1,197,1,384, -385,385,385,385,1,198,1,385, -386,386,386,386,1,199,1,386, -387,387,387,387,387,387,387,1,200,1,387, -388,388,388,388,388,388,388,1,201,1,388, -389,389,389,389,389,389,389,1,202,1,389, -390,390,390,390,390,390,390,390,390,1,203,1,390, -391,391,391,391,391,391,391,391,391,1,204,1,391, -392,392,392,392,392,392,392,392,392,1,205,1,392, -393,393,393,393,393,393,393,393,393,1,206,1,393, -394,394,394,394,394,394,394,394,394,1,207,1,394, -395,395,395,395,395,395,395,395,395,1,208,1,395, -396,396,396,396,396,396,396,396,396,1,209,1,396, -397,397,397,397,397,397,397,397,397,1,210,1,397, -398,398,398,398,398,398,398,398,398,1,211,1,398, -399,399,399,399,399,399,399,399,399,1,212,1,399, -400,400,400,400,400,400,400,400,400,1,213,1,400, -19,124,124,124,124,124,124,124,124,124,124,124,19,124,19,19,125,125,125,125, - 125,19,124,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,124,19,19,19,19,1,214,1,853,125, -19,19,19,19,19,1,215,1,293, -58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58, - 58,58,58,58,58,58,58,256,58,58,58,58,58,58,216,401, -108,108,108,108,402,217,402, -403,107,404, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,219,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,283,96,271,209,214,284,272,276,275,274,273,208,276,266,265,264, - 263,262,261,260,259,258,257,241,240,214,255,254, -405,406,408,410,411,412,414,415,416,418,420,422,424,426,428,430,432,434,436, - 437,439,440,441,443,444,446,447,448,449,451,452,288,290,220,67,68,62,63, - 450,450,450,450,73,445,445,445,442,442,442,442,438,438,438,435,433,431, - 429,427,425,423,421,419,417,99,100,413,103,104,409,407,109, -453,453,453,453,1,221,1,453, -56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56, - 56,56,56,56,56,56,56,56,56,56,56,256,56,56,56,56,222,454, -455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455, - 455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455, - 455,455,455,1,223,1,455, -456,456,456,456,1,224,1,456, -135,457,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, - 135,135,135,135,135,131,135,135,135,135,135,135,135,135,135,135,135,135, - 135,135,135,135,135,135,225,133, -19,19,19,19,19,19,19,19,226,1,846, -458,458,458,458,1,227,1,458, -37,38,39,34,228,51,51,42,51,41,40,40, -37,38,39,34,229,50,50,42,50,41,40,40, -459,459,459,459,1,230,1,459, -264,264,264,264,264,231, -249,249,249,249,232, -247,247,233, -123,123,123,123,123,123,123,243,243,243,243,123,243,243,243,243,243,123,123, - 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, - 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, - 123,123,123,234, -238,460,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,124,1,1119, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,125,1,1118, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,126,1,1117, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,127,1,1116, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,128,1,1115, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,129,1,1114, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,130,1,1113, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,131,1,1112, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,132,1,1111, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,133,1,1110, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,134,1,1109, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,135,1,1102, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,136,1,1101, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,137,1,1100, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,138,1,1099, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,139,1,1098, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,140,1,1097, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,141,1,1091, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,142,1,1090, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,143,1,1089, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,144,1,1083, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,145,1,1082, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,146,1,1081, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,147,1,1080, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,148,1,1079, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,149,1,1078, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,150,1,1077, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,151,1,1076, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,152,1,1075, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,153,1,1074, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,154,1,1073, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,155,1,1072, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,156,1,1071, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,157,1,1070, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,158,1,1069, +19,19,19,19,19,19,19,19,19,159,1,1046, +19,19,19,19,19,19,19,19,19,160,1,1045, +19,19,19,19,19,19,19,19,19,161,1,1044, +19,19,19,19,19,19,19,19,19,162,1,1043, +19,19,19,19,19,163,1,1042, +19,19,19,19,19,164,1,1041, +19,19,19,19,19,19,19,19,165,1,1064, +19,19,19,19,19,19,19,19,166,1,1063, +19,19,19,19,19,19,19,19,167,1,1062, +19,19,19,19,19,19,19,19,19,19,168,1,1060, +19,19,19,19,19,19,19,19,19,19,169,1,1059, +19,19,19,19,19,19,19,19,19,19,170,1,1058, +19,19,19,19,19,19,19,19,19,19,171,1,1057, +19,19,19,19,19,19,19,19,19,19,172,1,1056, +19,19,19,19,19,19,19,19,19,19,173,1,1055, +19,19,19,19,19,19,19,19,19,19,174,1,1054, +19,19,19,19,19,19,19,19,19,19,175,1,1053, +19,19,19,19,19,19,19,19,19,19,176,1,1052, +19,19,19,19,19,19,19,19,19,19,177,1,1051, +19,19,19,19,19,19,19,19,19,19,178,1,1050, +19,19,19,19,19,19,19,19,19,19,179,1,1049, +19,19,19,19,19,19,19,19,19,19,180,1,1048, +398,398,398,398,1,181,1,398, +399,1,182,1,399, +400,1,183,1,400, +401,1,184,1,401, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, + 402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, + 402,402,402,402,402,1,185,1,402, +403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403, + 403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403, + 403,403,403,403,403,1,186,1,403, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, + 404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, + 404,404,404,404,404,1,187,1,404, +405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405, + 405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405, + 405,405,405,405,405,1,188,1,405, +406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406, + 406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406, + 406,406,406,406,406,1,189,1,406, +407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407, + 407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407, + 407,407,407,407,407,1,190,1,407, +408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408, + 408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408, + 408,408,408,408,408,1,191,1,408, +409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409, + 409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409, + 409,409,409,409,409,1,192,1,409, +410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, + 410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, + 410,410,410,410,410,1,193,1,410, +411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411, + 411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411, + 411,411,411,411,411,1,194,1,411, +412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412, + 412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412, + 412,412,412,412,412,1,195,1,412, +413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, + 413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, + 413,413,413,413,413,1,196,1,413, +414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, + 414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, + 414,414,414,414,414,1,197,1,414, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, + 415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, + 415,415,415,415,415,1,198,1,415, +416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, + 416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, + 416,416,416,416,416,1,199,1,416, +417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417, + 417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417, + 417,417,417,417,417,1,200,1,417, +418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, + 418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, + 418,418,418,418,418,1,201,1,418, +419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419, + 419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419, + 419,419,419,419,419,1,202,1,419, +420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420, + 420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420, + 420,420,420,420,420,1,203,1,420, +421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421, + 421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421, + 421,421,421,421,421,1,204,1,421, +422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, + 422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, + 422,422,422,422,422,1,205,1,422, +423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423, + 423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423, + 423,423,423,423,423,1,206,1,423, +424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424, + 424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424, + 424,424,424,424,424,1,207,1,424, +425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425, + 425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425, + 425,425,425,425,425,1,208,1,425, +426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, + 426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, + 426,426,426,426,426,1,209,1,426, +427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427, + 427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427, + 427,427,427,427,427,1,210,1,427, +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, + 428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, + 428,428,428,428,428,1,211,1,428, +429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, + 429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, + 429,429,429,429,429,1,212,1,429, +430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430, + 430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430, + 430,430,430,430,430,1,213,1,430, +431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431, + 431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431, + 431,431,431,431,431,1,214,1,431, +432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432, + 432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432, + 432,432,432,432,432,1,215,1,432, +433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433, + 433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433, + 433,433,433,433,433,1,216,1,433, +434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434, + 434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434, + 434,434,434,434,434,1,217,1,434, +435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435, + 435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435, + 435,435,435,435,435,1,218,1,435, +436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, + 436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, + 436,436,436,436,436,1,219,1,436, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, + 437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, + 437,437,437,437,437,1,220,1,437, +438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, + 438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, + 438,438,438,438,438,1,221,1,438, +439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, + 439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, + 439,439,439,439,439,1,222,1,439, +440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, + 440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, + 440,440,440,440,440,1,223,1,440, +441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441, + 441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441, + 441,441,441,441,441,1,224,1,441, +442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442, + 442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442, + 442,442,442,442,442,1,225,1,442, +443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443, + 443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443, + 443,443,443,443,443,1,226,1,443, +444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444, + 444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444, + 444,444,444,444,444,1,227,1,444, +445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445, + 445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445, + 445,445,445,445,445,1,228,1,445, +446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446, + 446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446, + 446,446,446,446,446,1,229,1,446, +447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447, + 447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447, + 447,447,447,447,447,1,230,1,447, +448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448, + 448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448, + 448,448,448,448,448,1,231,1,448, +449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, + 449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, + 449,449,449,449,449,1,232,1,449, +450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, + 450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, + 450,450,450,450,450,1,233,1,450, +451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, + 451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, + 451,451,451,451,451,1,234,1,451, +452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452, + 452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452, + 452,452,452,452,452,1,235,1,452, +453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453, + 453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453, + 453,453,453,453,453,1,236,1,453, +454,454,454,454,454,454,454,454,1,237,1,454, +455,455,455,455,455,455,455,455,1,238,1,455, +456,456,456,456,456,456,456,456,1,239,1,456, +457,457,457,457,457,457,457,457,1,240,1,457, +458,458,458,458,1,241,1,458, +459,459,459,459,1,242,1,459, +460,460,460,460,460,460,460,1,243,1,460, +461,461,461,461,461,461,461,1,244,1,461, +462,462,462,462,462,462,462,1,245,1,462, +463,463,463,463,463,463,463,463,463,1,246,1,463, +464,464,464,464,464,464,464,464,464,1,247,1,464, +465,465,465,465,465,465,465,465,465,1,248,1,465, +466,466,466,466,466,466,466,466,466,1,249,1,466, +467,467,467,467,467,467,467,467,467,1,250,1,467, +468,468,468,468,468,468,468,468,468,1,251,1,468, +469,469,469,469,469,469,469,469,469,1,252,1,469, +470,470,470,470,470,470,470,470,470,1,253,1,470, +471,471,471,471,471,471,471,471,471,1,254,1,471, +472,472,472,472,472,472,472,472,472,1,255,1,472, +473,473,473,473,473,473,473,473,473,1,256,1,473, +474,474,474,474,474,474,474,474,474,1,257,1,474, +475,475,475,475,475,475,475,475,475,1,258,1,475, +19,130,130,130,130,130,130,130,130,130,130,130,19,130,19,19,131,131,131,131, + 131,19,130,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,130,19,19,19,19,1,259,1,894,131, +19,19,19,19,19,1,260,1,309, +61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,302,61,61,61,61,61,61,261,476, +114,114,114,114,477,262,477, +478,113,479, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,264,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,330,102,318,218,304,259,331,319,323,322,321,320,217,323,313, + 312,311,310,309,308,307,306,305,303,286,285,259,301,300, +290,480,482,484,485,486,488,489,490,492,494,496,498,500,502,504,506,508,510, + 511,513,514,515,517,518,520,521,522,523,526,527,335,337,339,341,343,265, + 70,71,525,72,74,65,66,524,524,524,524,79,519,519,519,516,516,516,516, + 512,512,512,509,507,505,503,501,499,497,495,493,491,105,106,487,109,110, + 483,481,115, +528,528,528,528,1,266,1,528, +59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59, + 59,59,59,59,59,59,59,59,59,59,59,302,59,59,59,59,267,529, +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, + 530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, + 530,530,530,1,268,1,530, +531,531,531,531,1,269,1,531, +141,532,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, + 141,141,141,141,141,137,141,141,141,141,141,141,141,141,141,141,141,141, + 141,141,141,141,141,141,270,139, +19,19,19,19,19,19,19,19,271,1,887, +533,533,533,533,1,272,1,533, +37,38,39,34,273,54,54,42,54,41,40,40, +37,38,39,34,274,53,53,42,53,41,40,40, +534,534,534,534,1,275,1,534, +274,274,274,274,274,276, +259,259,259,259,277, +257,257,278, +129,129,129,129,129,129,129,253,253,253,253,129,253,253,253,253,253,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,279, +248,535,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, + 248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, + 248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,280, +246,246,246,246,246,281, +264,536,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, + 264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, + 264,264,264,264,270,264,282,537, +275,275,275,275,275,272, +239,256,256,256,256,256,256,256,256,256,284, +260,260,260,260,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, 238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, - 238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,235, -236,236,236,236,236,236, -254,461,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, - 254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, - 254,254,254,254,260,254,237,462, -265,265,265,265,265,262, -229,246,246,246,246,246,246,246,246,246,239, -250,250,250,250,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, - 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228, - 228,228,228,228,228,240, -248,248,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, - 227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, - 227,227,227,241, -244,244,244,244,244,244,244,244,244,226,226,226,226,226,226,226,226,226,226, - 226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, - 226,226,226,226,226,226,226,226,226,226,242, -240,230,245,463,464,245,239,239,239,239,239,241,225,225,225,225,225,225,225, - 225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, - 225,225,225,225,225,225,263,225,225,225,225,234,234,225,243,234, -19,19,244,1,946, -19,19,245,1,944, -19,19,246,1,943, -19,19,247,1,942, -19,19,248,1,941, -19,19,249,1,940, -19,19,250,1,939, -19,19,251,1,938, -19,19,252,1,937, -19,19,253,1,936, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,254,1,947, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,1,255,1,900, + 238,238,238,238,238,285, +258,258,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, + 237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, + 237,237,237,286, +254,254,254,254,254,254,254,254,254,236,236,236,236,236,236,236,236,236,236, + 236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, + 236,236,236,236,236,236,236,236,236,236,287, +250,240,255,538,539,255,249,249,249,249,249,251,235,235,235,235,235,235,235, + 235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, + 235,235,235,235,235,235,273,235,235,235,235,244,244,235,288,244, +19,19,289,1,990, +19,19,19,19,19,19,290,1,943, +19,19,291,1,988, +19,19,292,1,987, +19,19,293,1,986, +19,19,294,1,985, +19,19,295,1,984, +19,19,296,1,983, +19,19,297,1,982, +19,19,298,1,981, +19,19,299,1,980, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,300,1,991, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,1,301,1,944, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,256,1,865, -465,1,257,1,465, -466,1,258,1,466, -467,1,259,1,467, -468,1,260,1,468, -469,1,261,1,469, -470,1,262,1,470, -471,1,263,1,471, -472,1,264,1,472, -473,1,265,1,473, -474,1,266,1,474, -19,19,19,19,19,19,19,19,19,19,19,19,19,237,237,237,237,237,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,267,1,927, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,302,1,909, +540,1,303,1,540, +541,1,304,1,541, +542,1,305,1,542, +543,1,306,1,543, +544,1,307,1,544, +545,1,308,1,545, +546,1,309,1,546, +547,1,310,1,547, +548,1,311,1,548, +549,1,312,1,549, +550,1,313,1,550, +19,19,19,19,19,19,19,19,19,19,19,19,19,247,247,247,247,247,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,314,1,971, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,268,1,935, + 19,19,19,19,19,19,19,19,19,19,19,19,19,315,1,979, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,1,269,1,934, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,316,1,978, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,270,1,933, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, - 475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, - 475,475,475,475,1,271,1,475, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, - 121,272,222,242,243,223,238,224,239,216,271,209,214,207,208,207,266,265, - 264,263,262,261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, - 121,273,222,242,243,223,238,224,239,216,271,209,214,206,208,206,266,265, - 264,263,262,261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, - 121,274,222,242,243,223,238,224,239,216,271,209,214,205,208,205,266,265, - 264,263,262,261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, - 121,275,222,242,243,223,238,224,239,216,271,209,214,204,208,204,266,265, - 264,263,262,261,260,259,258,257,241,240,214,255,254, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,1,276,1,197, -19,477,479,330,322,326,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,1,277,1,194,483,482,481,480,478, -19,323,325,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,1,278,1,189,485,484, -19,486,488,490,492,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,1,279,1,186,493,491,489,487, -19,494,329,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,1,280,1,183,496,495, -19,497,301,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1, - 281,1,180,499,498, -500,299,179,502,501, -503,504,505,506,507,508,509,510,511,512,513,514,515,159,159,159,159,159,283, - 163,163,163,163,166,166,166,169,169,169,172,172,172,175,175,175,178,178, - 178, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,284,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,158,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -516,516,516,516,1,285,1,516, -517,517,517,517,1,286,1,517, -518,518,518,518,518,287,518, -19,19,19,19,19,288,1,852, -519,519,519,519,1,289,1,519, -19,19,19,19,19,290,1,850, -520,520,520,520,1,291,1,520, -151,151,521,151,151,151,151,151,151,151,151,151,151,151,151,149,151,151,151, - 151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, - 151,151,151,151,151,292, -19,19,19,19,19,293,1,847, -522,522,522,522,1,294,1,522, -523,523,523,523,1,295,1,523, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,296,1,845, -126,126,126,126,126,126,126,126,126,126,126,126,150,126,126,126,126,126,132, - 126,126,297,527,225,526,292,525,226,293,524, + 19,19,19,19,19,19,19,19,19,19,19,19,19,317,1,977, +551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, + 551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, + 551,551,551,551,551,1,318,1,551, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, + 128,127,319,232,287,288,233,283,234,284,261,318,218,304,259,216,217,216, + 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, + 128,127,320,232,287,288,233,283,234,284,261,318,218,304,259,215,217,215, + 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, + 128,127,321,232,287,288,233,283,234,284,261,318,218,304,259,214,217,214, + 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, + 128,127,322,232,287,288,233,283,234,284,261,318,218,304,259,213,217,213, + 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,1,323,1,206, +19,553,555,383,375,379,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,1,324,1,203,559,558,557,556,554, +19,376,378,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,1,325,1,198,561,560, +19,562,564,566,568,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,1,326,1,195,569,567,565,563, +19,570,382,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,1,327,1,192,572,571, +19,573,354,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1, + 328,1,189,575,574, +576,352,188,578,577, +579,580,581,582,583,584,585,586,587,588,589,590,591,168,168,168,168,168,330, + 172,172,172,172,175,175,175,178,178,178,181,181,181,184,184,184,187,187, + 187, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,331,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,167,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +592,592,592,592,1,332,1,592, +593,593,593,593,1,333,1,593, +594,594,594,594,594,334,594, +19,19,19,19,19,335,1,897, +595,595,595,595,1,336,1,595, +19,19,19,19,19,337,1,896, +596,596,596,596,1,338,1,596, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,339,1,895, +597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,1,340,1,597, +19,19,19,19,19,341,1,893, +598,598,598,598,1,342,1,598, +19,19,19,19,19,343,1,891, +599,599,599,599,1,344,1,599, +157,157,600,157,157,157,157,157,157,157,157,157,157,157,157,155,157,157,157, + 157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, + 157,157,157,157,157,345, +19,19,19,19,19,346,1,888, +601,601,601,601,1,347,1,601, +602,602,602,602,1,348,1,602, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,349,1,886, +132,132,132,132,132,132,132,132,132,132,132,132,156,132,132,132,132,132,138, + 132,132,350,606,270,605,345,604,271,346,603, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 298,1,1089, + 351,1,1159, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,299,1,916, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,352,1,960, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 300,1,1088, + 353,1,1158, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,301,1,918, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,354,1,962, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,302,1, - 1087, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,355,1, + 1157, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 303,1,1086, + 356,1,1156, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 304,1,1085, + 357,1,1155, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 305,1,1084, + 358,1,1154, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 306,1,1083, + 359,1,1153, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 307,1,1082, + 360,1,1152, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 308,1,1081, + 361,1,1151, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 309,1,1080, + 362,1,1150, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 310,1,1079, + 363,1,1149, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 311,1,1078, + 364,1,1148, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 312,1,1077, + 365,1,1147, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 313,1,1076, + 366,1,1146, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 314,1,1075, + 367,1,1145, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 315,1,1074, + 368,1,1144, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 316,1,1073, + 369,1,1143, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 317,1,1072, + 370,1,1142, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 318,1,1071, + 371,1,1141, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 319,1,1070, + 372,1,1140, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 320,1,1069, + 373,1,1139, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 321,1,1068, + 374,1,1138, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,322,1,929, + 19,19,19,19,19,19,19,19,19,19,19,19,19,375,1,973, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,323,1,927, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,376,1,971, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,324,1,888, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,377,1,932, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,325,1,926, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,378,1,970, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,326,1,928, + 19,19,19,19,19,19,19,19,19,19,19,19,19,379,1,972, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 327,1,863, + 380,1,907, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 328,1,1067, + 381,1,1137, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,329,1,920, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,382,1,964, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,330,1,930, + 19,19,19,19,19,19,19,19,19,19,19,19,19,383,1,974, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 331,1,1066, + 384,1,1136, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,332,1, - 1065, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,385,1, + 1135, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 333,1,1064, + 386,1,1134, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 334,1,1063, + 387,1,1133, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,335,1,838, -298,300,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318, - 319,320,321,328,331,332,333,334,268,270,330,322,326,323,325,329,301,299, - 324,256,327,35,38,7,9,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 19,19,19,19,19,19,19,388,1,879, +351,353,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371, + 372,373,374,381,384,385,386,387,315,317,383,375,379,376,378,382,354,352, + 377,302,380,35,38,7,9,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, -34,337,11, -34,338,10, -405,406,408,410,411,412,414,415,416,418,420,422,424,426,428,430,432,434,436, - 437,439,440,441,443,444,446,447,448,449,451,452,288,290,528,530,339,531, - 529,67,68,62,63,450,450,450,450,73,445,445,445,442,442,442,442,438,438, - 438,435,433,431,429,427,425,423,421,419,417,99,100,413,103,104,409,407, - 109, -532,532,532,532,1,340,1,532, -533,405,37,38,39,34,341,534,64,64,42,64,41,40,40,156,157, -275,274,274,271,270,269,268,267,266,342,371,274,535, -285,284,281,278,284,281,278,343,369,278,281,284,536, -373,373,373,373,344,373, -324,345,537, -324,346,538, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,347,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,424,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,348,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,423,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,349,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,422,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,350,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,421,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,351,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,420,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,352,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,419,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,353,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,418,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,354,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,417,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,355,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,416,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,356,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,413,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,357,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,409,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,358,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,408,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,359,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,407,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,360,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,406,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,361,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,405,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,362,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,404,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,363,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,403,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,364,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,397,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,365,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,396,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,366,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,395,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,367,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,394,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,368,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,388,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,369,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,387,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,370,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,386,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,371,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,385,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,372,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,384,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,373,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,383,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,374,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,382,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,375,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,381,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,376,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,380,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,377,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,379,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,378,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,378,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,379,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,377,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,380,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,376,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,381,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,375,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,382,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,374,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -539,540,288,287,286,288,287,286,383,290,286,287,288,354,289, -539,540,288,287,286,288,287,286,384,290,286,287,288,353,289, -292,291,292,291,385,291,292,352, -292,291,292,291,386,291,292,351, -285,284,281,278,284,281,278,387,368,278,281,284,536, -285,284,281,278,284,281,278,388,367,278,281,284,536, -285,284,281,278,284,281,278,389,366,278,281,284,536, -275,274,274,271,270,269,268,267,266,390,365,274,535, -275,274,274,271,270,269,268,267,266,391,364,274,535, -275,274,274,271,270,269,268,267,266,392,363,274,535, -275,274,274,271,270,269,268,267,266,393,362,274,535, -275,274,274,271,270,269,268,267,266,394,541,274,535, -275,274,274,271,270,269,268,267,266,395,360,274,535, -275,274,274,271,270,269,268,267,266,396,359,274,535, -275,274,274,271,270,269,268,267,266,397,358,274,535, -275,274,274,271,270,269,268,267,266,398,357,274,535, -275,274,274,271,270,269,268,267,266,399,356,274,535, -275,274,274,271,270,269,268,267,266,400,355,274,535, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,542, - 234,132,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236, - 256,231,253,122,121,401,222,242,243,223,238,111,225,224,239,543,112,216, - 280,279,277,282,278,281,276,113,271,209,545,214,272,276,275,274,273,208, - 276,266,265,264,263,262,261,260,259,258,257,241,240,226,214,544,255,254, -232,238,238,238,238,235,237,546,233,476,236,253,18,402,110,242,547,224,239, - 241,240,255, +34,390,11, +34,391,10, +290,480,482,484,485,486,488,489,490,492,494,496,498,500,502,504,506,508,510, + 511,513,514,515,517,518,520,521,522,523,526,527,335,337,339,341,343,607, + 609,392,610,608,70,71,525,72,74,65,66,524,524,524,524,79,519,519,519, + 516,516,516,516,512,512,512,509,507,505,503,501,499,497,495,493,491,105, + 106,487,109,110,483,481,115, +611,611,611,611,1,393,1,611, +612,290,37,38,39,34,394,613,67,67,42,67,41,40,40,165,166, +303,614,615,616,305,304,305,304,303,395,303,304,305,308,395,306,307, +285,284,284,281,280,279,278,277,276,396,393,284,617, +288,295,294,291,294,291,288,397,391,288,291,294,618, +397,397,397,397,398,397, +377,399,619, +377,400,620, +377,401,621, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,402,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,465,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,403,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,464,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,404,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,463,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,405,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,462,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,406,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,461,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,407,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,460,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,408,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,459,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,409,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,458,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,410,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,457,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,411,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,456,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,412,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,455,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,413,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,454,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,414,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,453,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,415,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,452,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,416,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,451,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,417,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,450,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,418,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,449,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,419,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,448,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,420,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,447,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,421,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,446,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,422,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,445,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,423,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,444,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,424,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,443,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,425,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,442,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,426,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,441,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,427,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,437,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,428,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,433,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,429,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,432,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,430,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,431,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,431,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,430,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,432,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,429,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,433,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,428,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,434,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,427,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,435,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,421,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,436,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,420,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,437,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,419,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,438,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,418,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,439,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,412,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,440,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,411,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,441,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,410,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,442,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,409,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,443,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,408,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,444,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,407,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,445,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,406,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,446,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,405,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,447,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,404,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,448,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,403,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,449,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,402,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,450,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,401,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,451,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,400,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,452,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,399,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,453,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,398,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +296,622,623,298,297,298,297,296,454,300,296,297,298,374,299, +296,622,623,298,297,298,297,296,455,300,296,297,298,373,299, +296,622,623,298,297,298,297,296,456,300,296,297,298,372,299, +296,622,623,298,297,298,297,296,457,300,296,297,298,371,299, +301,302,302,301,458,301,302,370, +301,302,302,301,459,301,302,369, +288,295,294,291,294,291,288,460,390,288,291,294,618, +288,295,294,291,294,291,288,461,389,288,291,294,618, +288,295,294,291,294,291,288,462,388,288,291,294,618, +303,614,615,616,305,304,305,304,303,463,303,304,305,308,387,306,307, +303,614,615,616,305,304,305,304,303,464,303,304,305,308,386,306,307, +285,284,284,281,280,279,278,277,276,465,385,284,617, +285,284,284,281,280,279,278,277,276,466,384,284,617, +285,284,284,281,280,279,278,277,276,467,383,284,617, +285,284,284,281,280,279,278,277,276,468,382,284,617, +285,284,284,281,280,279,278,277,276,469,624,284,617, +285,284,284,281,280,279,278,277,276,470,380,284,617, +285,284,284,281,280,279,278,277,276,471,379,284,617, +285,284,284,281,280,279,278,277,276,472,378,284,617, +285,284,284,281,280,279,278,277,276,473,377,284,617, +285,284,284,281,280,279,278,277,276,474,376,284,617, +285,284,284,281,280,279,278,277,276,475,375,284,617, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,625, + 279,138,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281, + 290,302,276,263,128,127,476,232,287,288,233,283,117,270,234,284,626,118, + 261,327,326,324,329,325,328,323,119,318,218,628,304,259,319,323,322,321, + 320,217,323,313,312,311,310,309,308,307,306,305,303,286,285,271,259,627, + 301,300, +277,248,248,248,248,280,282,629,278,552,281,263,18,477,116,287,630,234,284, + 286,285,301, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,403,1,950, -548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548, - 548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548, - 548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548, - 548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548, - 548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548, - 548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548, - 548,1,404,1,548, -19,19,19,19,19,405,1,899, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,406,1,898, -123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,407,106,214,214, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,408,1,897, -126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, - 409,105,524, -19,19,19,19,19,410,1,896, -19,19,19,19,19,411,1,895, -19,19,1,412,1,894, -549,132,413,102,225,543,101,226,544, -19,19,19,19,19,414,1,892, -19,19,19,19,19,415,1,891, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,416,1,890, -123,123,123,123,123,123,123,123,123,123,123,123,123,94,94,94,94,122,121,94, - 417,95,214,214, -19,1,418,1,889, -132,419,550,225,226, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,420,1,887, -551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, - 551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, - 551,551,551,551,551,1,421,1,551, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,422,1,886, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,132,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236, - 256,231,253,122,121,423,222,242,243,223,238,91,225,224,239,216,280,279, - 277,282,278,281,276,90,271,209,214,272,276,275,274,273,208,276,266,265, - 264,263,262,261,260,259,258,257,241,240,226,214,255,254, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,424,1,885, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,425,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,89,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,426,1,884, -123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,427,88,214,214, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,428,1,883, -123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,429,87,214,214, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,430,1,882, -123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,431,117,552,214, - 214, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,432,1,881, -123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,433,117,553,214, - 214, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,434,1,880, -123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,435,117,554,214, - 214, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,436,1,879, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,437,1,878, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,542, - 234,132,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236, - 256,231,253,122,121,438,222,242,243,223,238,111,225,224,239,543,112,216, - 280,279,277,282,278,281,276,113,271,209,555,214,272,276,275,274,273,208, - 276,266,265,264,263,262,261,260,259,258,257,241,240,226,214,544,255,254, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,439,1,877, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,440,1,876, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,441,1,875, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,542, - 234,132,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236, - 256,231,253,122,121,442,222,242,243,223,238,111,225,224,239,543,112,216, - 280,279,277,282,278,281,276,113,271,209,556,214,272,276,275,274,273,208, - 276,266,265,264,263,262,261,260,259,258,257,241,240,226,214,544,255,254, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,443,1,874, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,444,1,873, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,445,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,76,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -19,19,19,19,19,446,1,872, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,447,1,871, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,448,1,870, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,449,1,869, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,450,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,72,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -19,19,19,19,19,19,19,451,1,868, -19,19,19,19,19,19,19,452,1,867, -37,38,39,34,453,21,21,42,21,41,40,40, -557,454,558, -298,300,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319, - 320,321,328,331,333,334,268,270,330,322,326,323,325,329,301,299,324,256, - 327,35,38,455,59,59,559,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59, - 59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59, -37,38,39,34,456,53,53,42,53,41,40,40, -136,560,138,139,137,143,142,561,561,562,560,141,134,457,560, -37,38,39,34,458,52,52,42,52,41,40,40, -37,38,39,34,459,49,49,42,49,41,40,40, -242,242,242,242,242,242,242,242,242,460, -255,257,258,256,259,261,461, -254,461,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, - 254,254,251,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, - 254,254,254,254,254,260,254,462,563, -245,245,245,245,245,245,245,245,245,245,235,235,235,235,235,235,235,235,235, - 235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, - 235,235,235,235,235,235,235,235,235,235,235,463, -245,245,245,245,245,245,245,245,245,245,231,231,231,231,231,231,231,231,231, - 231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, - 231,231,231,231,231,231,231,231,231,231,231,464, -256,465,564, -256,466,565, -256,467,566, -256,468,567, -256,469,568, -256,470,569, -256,471,570, -256,472,571, -256,473,572, -256,474,573, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,475,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,574,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -237,237,237,237,237,476, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,477,1,932, -575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575, - 575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575, - 575,1,478,1,575, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,479,1,931, -576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576, - 576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576, - 576,1,480,1,576, -577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577, - 577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577, - 577,1,481,1,577, -578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578, - 578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578, - 578,1,482,1,578, -579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579, - 579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579, - 579,1,483,1,579, -580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580, - 580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580, - 580,580,580,580,1,484,1,580, -581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, - 581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, - 581,581,581,581,1,485,1,581, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,486,1,925, -582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582, - 582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582, - 582,582,582,582,1,487,1,582, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,488,1,924, -583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583, - 583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583, - 583,583,583,583,1,489,1,583, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,490,1,923, -584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584, - 584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584, - 584,584,584,584,1,491,1,584, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,492,1,922, -585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585, - 585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585, - 585,585,585,585,1,493,1,585, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,494,1,921, -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, - 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, - 586,586,586,586,1,495,1,586, -587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, - 587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, - 587,587,587,587,1,496,1,587, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,497,1,919, -588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588, - 588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588, - 588,588,588,588,1,498,1,588, -589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, - 589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, - 589,589,589,589,1,499,1,589, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,500,1,917, -590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590, - 590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590, - 590,590,590,590,1,501,1,590, -591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591, - 591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591, - 591,591,591,591,1,502,1,591, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,503,1,915, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,504,1,914, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,505,1,913, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,506,1,912, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,507,1,911, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,508,1,910, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,509,1,909, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,510,1,908, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,511,1,907, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,512,1,906, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,513,1,905, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,514,1,904, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,515,1,903, -37,38,39,34,516,48,48,42,48,41,40,40, -37,38,39,34,517,47,47,42,47,41,40,40, -37,38,39,34,518,46,46,42,46,41,40,40, -37,38,39,34,519,43,43,42,43,41,40,40, -37,38,39,34,520,42,42,42,42,41,40,40, -152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, - 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, - 152,152,152,152,152,153,152,521, -37,38,39,34,522,41,41,42,41,41,40,40, -37,38,39,34,523,40,40,42,40,41,40,40, -127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, - 19,19,19,524,1,848, -592,592,592,592,1,525,1,592, -593,593,593,593,1,526,1,593, -594,594,594,594,1,527,1,594, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,528,1,843, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,529,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,595,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,530,1,842, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,531,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,596,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -37,38,39,34,532,22,22,42,22,41,40,40, -19,19,19,19,19,533,1,902, -597,597,597,597,1,534,1,597, -19,19,19,19,19,19,19,19,535,1,997, -19,19,19,19,19,19,19,536,1,1009, -598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598, - 598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598, - 598,598,598,598,1,537,1,598, -599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599, - 599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599, - 599,599,599,599,1,538,1,599, -19,19,19,19,19,19,539,1,949, -19,19,19,19,19,19,540,1,948, -600,1,541,1,600, -254,461,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, - 254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, - 254,254,254,254,260,254,542,601, -254,461,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, - 254,254,128,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, - 254,254,254,254,254,260,254,543,130, -19,19,19,19,19,19,19,544,1,893, -602,327,545,57,603, -243,243,243,243,243,243,243,243,243,546, -240,230,245,463,464,245,239,239,239,239,239,241,225,225,225,225,234,234,225, - 547,234, -107,108,109,110,111,112,113,114,61,62,63,64,65,115,116,117,118,119,120,66, - 67,68,69,70,121,122,123,71,72,73,74,75,124,125,126,127,128,129,130,131, - 132,133,134,135,136,137,138,104,59,60,143,144,145,146,147,148,149,150, - 151,152,153,154,155,156,139,140,141,142,76,77,78,79,80,45,46,47,81,82, - 83,84,85,86,87,88,89,48,49,90,91,92,93,94,95,96,97,50,51,52,98,99,53,54, - 100,101,102,103,55,56,57,58,548,604,605,605,605,605,605,605,605,605,605, - 605,308,308,308,308,308,309,310,311,312,315,315,315,316,317,321,321,321, - 321,322,323,324,325,326,327,328,329,332,332,332,333,334,335,336,337,338, - 339,340,341,345,345,345,345,346,347,348,349,350,199,198,197,196,213,212, - 211,210,209,208,207,206,205,204,203,202,201,200,159,106,158,105,157,195, - 194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,180,180,180, - 180,180,179,178,177,176,176,176,176,176,176,175,174,173,172,171,170,169, - 169,169,169,168,168,168,167,166,165,164,163,162,161,160, -254,461,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, - 254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, - 254,254,254,254,260,254,549,606, -324,550,607, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,542, - 234,132,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236, - 256,231,253,122,121,551,222,242,243,223,238,111,225,224,239,543,112,216, - 280,279,277,282,278,281,276,113,271,209,608,214,272,276,275,274,273,208, - 276,266,265,264,263,262,261,260,259,258,257,241,240,226,214,544,255,254, -602,86,86,86,86,86,552,609, -602,85,85,85,85,85,553,609, -602,84,84,84,84,84,554,609, -602,83,83,83,83,83,555,603, -602,80,80,80,80,80,556,603, -19,1,557,1,864, -327,558,55, -298,300,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319, - 320,321,328,331,333,334,268,270,330,322,326,323,325,329,301,299,324,610, - 256,327,35,38,612,611,559,60,1,612,60,60,60,61,60,60,60,60,60,60,60,60, - 60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60, - 60,60,60,60, -613,613,613,613,613,613,613,613,613,560, -614,614,614,614,614,561, -140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,614,614,614, - 614,614,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, - 140,140,140,140,140,140,562, -252,563, -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,1,564,1,615, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,565,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,616,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,566,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,617,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,567,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,618,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,568,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,619,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,569,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,620,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,570,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,621,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,571,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,622,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,572,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,623,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,573,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,624,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -625,1,574,1,625, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, - 121,575,222,242,243,223,238,224,239,216,271,209,214,202,208,202,266,265, - 264,263,262,261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, - 121,576,222,242,243,223,238,224,239,216,271,209,214,201,208,201,266,265, - 264,263,262,261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, - 121,577,222,242,243,223,238,224,239,216,271,209,214,200,208,200,266,265, - 264,263,262,261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, - 121,578,222,242,243,223,238,224,239,216,271,209,214,199,208,199,266,265, - 264,263,262,261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,233,476,236,256,231,253,122, - 121,579,222,242,243,223,238,224,239,216,271,209,214,198,208,198,266,265, - 264,263,262,261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,580,222,242,243,223,238,224,239,216,626,276,271,209,214, - 272,276,275,274,273,208,276,266,265,264,263,262,261,260,259,258,257,241, - 240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,581,222,242,243,223,238,224,239,216,627,276,271,209,214, - 272,276,275,274,273,208,276,266,265,264,263,262,261,260,259,258,257,241, - 240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,582,222,242,243,223,238,224,239,216,277,628,276,271,209, - 214,272,276,275,274,273,208,276,266,265,264,263,262,261,260,259,258,257, - 241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,583,222,242,243,223,238,224,239,216,277,629,276,271,209, - 214,272,276,275,274,273,208,276,266,265,264,263,262,261,260,259,258,257, - 241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,584,222,242,243,223,238,224,239,216,277,630,276,271,209, - 214,272,276,275,274,273,208,276,266,265,264,263,262,261,260,259,258,257, - 241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,585,222,242,243,223,238,224,239,216,277,631,276,271,209, - 214,272,276,275,274,273,208,276,266,265,264,263,262,261,260,259,258,257, - 241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,586,222,242,243,223,238,224,239,216,632,277,278,276,271, - 209,214,272,276,275,274,273,208,276,266,265,264,263,262,261,260,259,258, - 257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,587,222,242,243,223,238,224,239,216,633,277,278,276,271, - 209,214,272,276,275,274,273,208,276,266,265,264,263,262,261,260,259,258, - 257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,588,222,242,243,223,238,224,239,216,634,279,277,278,276, - 271,209,214,272,276,275,274,273,208,276,266,265,264,263,262,261,260,259, - 258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,589,222,242,243,223,238,224,239,216,635,279,277,278,276, - 271,209,214,272,276,275,274,273,208,276,266,265,264,263,262,261,260,259, - 258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,590,222,242,243,223,238,224,239,216,280,279,277,278,636, - 276,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262,261,260, - 259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,591,222,242,243,223,238,224,239,216,280,279,277,278,637, - 276,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262,261,260, - 259,258,257,241,240,214,255,254, -37,38,39,34,592,34,34,42,34,41,40,40, -37,38,39,34,593,33,33,42,33,41,40,40, -37,38,39,34,594,32,32,42,32,41,40,40, -638,638,638,638,1,595,1,638, -639,639,639,639,1,596,1,639, -37,38,39,34,597,65,65,42,65,41,40,40, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,598,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,372,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,599,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,370,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -602,600,640, -254,461,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, - 254,254,251,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, - 254,254,254,254,254,260,254,601,641, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,478,1,997, +631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, + 631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, + 631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, + 631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, + 631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, + 631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, + 631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, + 631,631,631,631,631,631,1,479,1,631, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,480,1,942, +129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,481,112,259,259, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,482,1,941, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, + 483,111,603, +19,19,19,19,19,484,1,940, +19,19,19,19,19,485,1,939, +19,19,1,486,1,938, +632,138,487,108,270,626,107,271,627, +19,19,19,19,19,488,1,936, +19,19,19,19,19,489,1,935, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,490,1,934, +129,129,129,129,129,129,129,129,129,129,129,129,129,100,100,100,100,128,127, + 100,491,101,259,259, +19,1,492,1,933, +138,493,633,270,271, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,494,1,931, +634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634, + 634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634, + 634,634,634,634,634,634,1,495,1,634, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,496,1,930, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,138,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281, + 290,302,276,263,128,127,497,232,287,288,233,283,97,270,234,284,261,327, + 326,324,329,325,328,323,96,318,218,304,259,319,323,322,321,320,217,323, + 313,312,311,310,309,308,307,306,305,303,286,285,271,259,301,300, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,498,1,929, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,499,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,95,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,500,1,928, +129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,501,94,259,259, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,502,1,927, +129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,503,93,259,259, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,504,1,926, +129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,505,123,635,259, + 259, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,506,1,925, +129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,507,123,636,259, + 259, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,508,1,924, +129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,509,123,637,259, + 259, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,510,1,923, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,511,1,922, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,625, + 279,138,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281, + 290,302,276,263,128,127,512,232,287,288,233,283,117,270,234,284,626,118, + 261,327,326,324,329,325,328,323,119,318,218,638,304,259,319,323,322,321, + 320,217,323,313,312,311,310,309,308,307,306,305,303,286,285,271,259,627, + 301,300, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,513,1,921, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,514,1,920, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,515,1,919, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,625, + 279,138,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281, + 290,302,276,263,128,127,516,232,287,288,233,283,117,270,234,284,626,118, + 261,327,326,324,329,325,328,323,119,318,218,639,304,259,319,323,322,321, + 320,217,323,313,312,311,310,309,308,307,306,305,303,286,285,271,259,627, + 301,300, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,517,1,918, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,518,1,917, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,519,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,82,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +19,19,19,19,19,520,1,916, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,521,1,915, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,522,1,914, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,523,1,913, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,524,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,78,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,525,73,259,259, +19,19,19,19,19,19,19,526,1,912, +19,19,19,19,19,19,19,527,1,911, +37,38,39,34,528,21,21,42,21,41,40,40, +640,529,641, +351,353,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372, + 373,374,381,384,386,387,315,317,383,375,379,376,378,382,354,352,377,302, + 380,35,38,530,62,62,642,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62, + 62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62, +37,38,39,34,531,56,56,42,56,41,40,40, +142,643,144,145,143,149,148,644,644,645,643,147,140,532,643, +37,38,39,34,533,55,55,42,55,41,40,40, +37,38,39,34,534,52,52,42,52,41,40,40, +252,252,252,252,252,252,252,252,252,535, +265,267,268,266,269,271,536, +264,536,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, + 264,264,261,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, + 264,264,264,264,264,270,264,537,646, +255,255,255,255,255,255,255,255,255,255,245,245,245,245,245,245,245,245,245, + 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, + 245,245,245,245,245,245,245,245,245,245,245,538, +255,255,255,255,255,255,255,255,255,255,241,241,241,241,241,241,241,241,241, + 241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, + 241,241,241,241,241,241,241,241,241,241,241,539, +302,540,647, +302,541,648, +302,542,649, +302,543,650, +302,544,651, +302,545,652, +302,546,653, +302,547,654, +302,548,655, +302,549,656, +302,550,657, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,551,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,658,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +247,247,247,247,247,552, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,553,1,976, +659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659, + 659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659, + 659,659,1,554,1,659, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,555,1,975, +660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660, + 660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660, + 660,660,1,556,1,660, +661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661, + 661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661, + 661,661,1,557,1,661, +662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662, + 662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662, + 662,662,1,558,1,662, +663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663, + 663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663, + 663,663,1,559,1,663, +664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664, + 664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664, + 664,664,664,664,664,1,560,1,664, +665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665, + 665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665, + 665,665,665,665,665,1,561,1,665, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,562,1,969, +666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666, + 666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666, + 666,666,666,666,666,1,563,1,666, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,564,1,968, +667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667, + 667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667, + 667,667,667,667,667,1,565,1,667, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,566,1,967, +668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668, + 668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668, + 668,668,668,668,668,1,567,1,668, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,568,1,966, +669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669, + 669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669, + 669,669,669,669,669,1,569,1,669, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,570,1,965, +670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, + 670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, + 670,670,670,670,670,1,571,1,670, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, + 671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, + 671,671,671,671,671,1,572,1,671, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,573,1,963, +672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, + 672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, + 672,672,672,672,672,1,574,1,672, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, + 673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, + 673,673,673,673,673,1,575,1,673, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,576,1,961, +674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674, + 674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674, + 674,674,674,674,674,1,577,1,674, +675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675, + 675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675, + 675,675,675,675,675,1,578,1,675, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,579,1,959, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,580,1,958, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,581,1,957, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,582,1,956, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,583,1,955, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,584,1,954, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,585,1,953, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,586,1,952, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,587,1,951, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,588,1,950, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,589,1,949, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,590,1,948, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,591,1,947, +37,38,39,34,592,51,51,42,51,41,40,40, +37,38,39,34,593,50,50,42,50,41,40,40, +37,38,39,34,594,49,49,42,49,41,40,40, +37,38,39,34,595,46,46,42,46,41,40,40, +37,38,39,34,596,45,45,42,45,41,40,40, +129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,597,676,259,259, +37,38,39,34,598,43,43,42,43,41,40,40, +37,38,39,34,599,42,42,42,42,41,40,40, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, + 158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, + 158,158,158,158,158,159,158,600, +37,38,39,34,601,41,41,42,41,41,40,40, +37,38,39,34,602,40,40,42,40,41,40,40, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, + 19,19,19,603,1,889, +677,677,677,677,1,604,1,677, +678,678,678,678,1,605,1,678, +679,679,679,679,1,606,1,679, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,607,1,884, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,608,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,680,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,609,1,883, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,610,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,681,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +37,38,39,34,611,22,22,42,22,41,40,40, +19,19,19,19,19,612,1,946, +682,682,682,682,1,613,1,682, +19,19,19,19,19,19,19,614,1,996, +19,19,19,19,19,19,19,615,1,995, +19,19,19,19,19,19,19,616,1,994, +19,19,19,19,19,19,19,19,617,1,1047, +19,19,19,19,19,19,19,618,1,1061, +683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683, + 683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683, + 683,683,683,683,683,1,619,1,683, +684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684, + 684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684, + 684,684,684,684,684,1,620,1,684, +685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685, + 685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685, + 685,685,685,685,685,1,621,1,685, +19,19,19,19,19,19,622,1,993, +19,19,19,19,19,19,623,1,992, +686,1,624,1,686, +264,536,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, + 264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, + 264,264,264,264,270,264,625,687, +264,536,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, + 264,264,134,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, + 264,264,264,264,264,270,264,626,136, +19,19,19,19,19,19,19,627,1,937, +688,380,628,60,689, +253,253,253,253,253,253,253,253,253,629, +250,240,255,538,539,255,249,249,249,249,249,251,235,235,235,235,244,244,235, + 630,244, +111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129, + 130,131,132,133,134,62,63,64,65,66,67,135,136,137,138,139,140,68,69,70, + 71,72,141,142,143,73,74,75,76,77,144,145,146,147,148,149,150,151,152, + 153,154,155,156,157,158,107,59,60,61,165,166,167,168,169,170,171,172, + 173,174,175,176,177,178,179,180,159,160,161,162,163,164,78,79,80,81,82, + 83,45,46,47,84,85,86,87,88,89,90,91,92,48,49,93,94,95,96,97,98,99,100, + 50,51,52,101,102,53,54,103,104,105,106,55,56,57,58,631,690,691,196,691, + 691,691,691,691,691,691,691,691,691,325,325,325,325,325,326,327,328,329, + 332,332,332,333,334,338,338,338,338,339,340,341,342,343,344,345,346,349, + 349,349,350,351,352,353,354,355,356,357,358,362,362,362,362,363,364,365, + 366,367,368,242,241,240,239,238,237,258,257,256,255,254,253,252,251,250, + 249,248,247,246,245,244,243,184,110,183,109,182,108,181,236,235,234,233, + 232,231,230,229,228,227,226,225,224,223,222,221,221,221,221,221,221,220, + 219,218,217,217,217,217,217,217,216,215,214,213,212,211,210,210,210,210, + 209,209,209,209,208,207,206,205,204,203,202,201,200,199,198,197,195,194, + 193,192,191,190,189,188,187,186,185, +264,536,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, + 264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, + 264,264,264,264,270,264,632,692, +377,633,693, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,625, + 279,138,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281, + 290,302,276,263,128,127,634,232,287,288,233,283,117,270,234,284,626,118, + 261,327,326,324,329,325,328,323,119,318,218,694,304,259,319,323,322,321, + 320,217,323,313,312,311,310,309,308,307,306,305,303,286,285,271,259,627, + 301,300, +688,92,92,92,92,92,635,695, +688,91,91,91,91,91,636,695, +688,90,90,90,90,90,637,695, +688,89,89,89,89,89,638,689, +688,86,86,86,86,86,639,689, +19,1,640,1,908, +380,641,58, +351,353,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372, + 373,374,381,384,386,387,315,317,383,375,379,376,378,382,354,352,377,696, + 302,380,35,38,698,697,642,63,1,698,63,63,63,64,63,63,63,63,63,63,63,63, + 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63, +699,699,699,699,699,699,699,699,699,643, +700,700,700,700,700,644, +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,700,700,700, + 700,700,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, + 146,146,146,146,146,146,645, +262,646, +701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,1,647,1,701, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,648,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,702,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,649,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,703,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,650,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,704,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,651,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,705,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,652,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,706,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,653,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,707,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,654,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,708,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,655,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,709,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,656,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,710,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,657,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,711,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +712,1,658,1,712, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, + 128,127,659,232,287,288,233,283,234,284,261,318,218,304,259,211,217,211, + 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, + 128,127,660,232,287,288,233,283,234,284,261,318,218,304,259,210,217,210, + 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, + 128,127,661,232,287,288,233,283,234,284,261,318,218,304,259,209,217,209, + 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, + 128,127,662,232,287,288,233,283,234,284,261,318,218,304,259,208,217,208, + 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, + 128,127,663,232,287,288,233,283,234,284,261,318,218,304,259,207,217,207, + 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,664,232,287,288,233,283,234,284,261,713,323,318,218, + 304,259,319,323,322,321,320,217,323,313,312,311,310,309,308,307,306,305, + 303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,665,232,287,288,233,283,234,284,261,714,323,318,218, + 304,259,319,323,322,321,320,217,323,313,312,311,310,309,308,307,306,305, + 303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,666,232,287,288,233,283,234,284,261,324,715,323,318, + 218,304,259,319,323,322,321,320,217,323,313,312,311,310,309,308,307,306, + 305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,667,232,287,288,233,283,234,284,261,324,716,323,318, + 218,304,259,319,323,322,321,320,217,323,313,312,311,310,309,308,307,306, + 305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,668,232,287,288,233,283,234,284,261,324,717,323,318, + 218,304,259,319,323,322,321,320,217,323,313,312,311,310,309,308,307,306, + 305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,669,232,287,288,233,283,234,284,261,324,718,323,318, + 218,304,259,319,323,322,321,320,217,323,313,312,311,310,309,308,307,306, + 305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,670,232,287,288,233,283,234,284,261,719,324,325,323, + 318,218,304,259,319,323,322,321,320,217,323,313,312,311,310,309,308,307, + 306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,671,232,287,288,233,283,234,284,261,720,324,325,323, + 318,218,304,259,319,323,322,321,320,217,323,313,312,311,310,309,308,307, + 306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,672,232,287,288,233,283,234,284,261,721,326,324,325, + 323,318,218,304,259,319,323,322,321,320,217,323,313,312,311,310,309,308, + 307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,673,232,287,288,233,283,234,284,261,722,326,324,325, + 323,318,218,304,259,319,323,322,321,320,217,323,313,312,311,310,309,308, + 307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,674,232,287,288,233,283,234,284,261,327,326,324,325, + 723,323,318,218,304,259,319,323,322,321,320,217,323,313,312,311,310,309, + 308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,675,232,287,288,233,283,234,284,261,327,326,324,325, + 724,323,318,218,304,259,319,323,322,321,320,217,323,313,312,311,310,309, + 308,307,306,305,303,286,285,259,301,300, +725,725,725,725,1,676,1,725, +37,38,39,34,677,34,34,42,34,41,40,40, +37,38,39,34,678,33,33,42,33,41,40,40, +37,38,39,34,679,32,32,42,32,41,40,40, +726,726,726,726,1,680,1,726, +727,727,727,727,1,681,1,727, +37,38,39,34,682,68,68,42,68,41,40,40, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,683,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,396,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,684,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,394,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,685,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,392,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +688,686,728, +264,536,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, + 264,264,261,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, + 264,264,264,264,264,270,264,687,729, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,602,1,901, -642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, - 642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, - 642,642,642,642,642,1,603,1,642, -403,604,404, -19,303,303,303,303,1,605,1,293, -254,461,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, - 254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, - 254,254,254,254,260,254,606,129, -643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643, - 643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643, - 643,643,643,643,1,607,1,643, -602,92,92,92,92,92,608,603, -644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,1,609,1,644, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,610,1,866, -60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60, - 60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,17,17,17,17,17,611, -37,38,39,34,612,54,54,42,54,41,40,40, -148,148,148,148,148,148,148,148,147,147,147,147,148,148,148,148,147,147,147, - 147,147,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, - 148,148,148,148,148,148,613, -144,144,144,144,144,614, -123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,615,647,645,645, - 646, -327,616,220, -327,617,219, -327,618,218, -327,619,217, -327,620,216, -327,621,215, -327,622,214, -327,623,213, -327,624,212, -327,625,211, -196,477,479,330,322,326,196,196,196,196,196,196,196,196,196,196,196,196,196, - 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,626, - 483,482,481,480,478, -195,477,479,330,322,326,195,195,195,195,195,195,195,195,195,195,195,195,195, - 195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,627, - 483,482,481,480,478, -193,323,325,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, - 193,193,193,193,193,193,193,193,193,193,193,193,193,193,628,485,484, -192,323,325,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, - 192,192,192,192,192,192,192,192,192,192,192,192,192,192,629,485,484, -191,323,325,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, - 191,191,191,191,191,191,191,191,191,191,191,191,191,191,630,485,484, -190,323,325,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, - 190,190,190,190,190,190,190,190,190,190,190,190,190,190,631,485,484, -188,486,488,490,492,188,188,188,188,188,188,188,188,188,188,188,188,188,188, - 188,188,188,188,188,188,188,188,188,188,188,188,632,493,491,489,487, -187,486,488,490,492,187,187,187,187,187,187,187,187,187,187,187,187,187,187, - 187,187,187,187,187,187,187,187,187,187,187,187,633,493,491,489,487, -185,494,329,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, - 185,185,185,185,185,185,185,185,634,496,495, -184,494,329,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, - 184,184,184,184,184,184,184,184,635,496,495, -182,497,301,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, - 182,182,182,182,182,182,636,499,498, -181,497,301,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181, - 181,181,181,181,181,181,637,499,498, -37,38,39,34,638,29,29,42,29,41,40,40, -37,38,39,34,639,28,28,42,28,41,40,40, -648,648,648,648,648,648,648,648,648,1,640,1,648, -129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, - 129,129,252,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, - 129,129,129,129,129,129,129,641, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,542, - 234,132,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236, - 256,231,253,122,121,642,222,242,243,223,238,115,225,224,239,543,116,216, - 280,279,277,282,278,281,276,114,271,209,214,272,276,275,274,273,208,276, - 266,265,264,263,262,261,260,259,258,257,241,240,226,214,544,255,254, -123,123,123,123,123,123,123,123,123,123,123,232,123,238,238,238,238,235,237, - 234,244,245,246,247,248,249,250,251,252,253,268,269,270,233,267,236,256, - 231,253,122,121,643,222,242,243,223,238,224,239,216,280,279,277,282,278, - 281,276,93,271,209,214,272,276,275,274,273,208,276,266,265,264,263,262, - 261,260,259,258,257,241,240,214,255,254, -123,123,123,123,123,123,123,123,123,123,123,123,123,122,121,644,118,214,214, -124,124,124,124,124,124,124,124,124,124,124,124,125,125,125,125,125,124,19, - 124,1,645,1,119,125, -19,19,646,1,945, -649,1,647,1,649, -275,274,274,271,270,269,268,267,266,648,361,274,535, -327,649,221, + 19,19,19,19,688,1,945, +730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730, + 730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730, + 730,730,730,730,730,730,1,689,1,730, +478,690,479, +19,320,320,320,320,1,691,1,309, +264,536,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, + 264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, + 264,264,264,264,270,264,692,135, +731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731, + 731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731, + 731,731,731,731,731,1,693,1,731, +688,98,98,98,98,98,694,689, +732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,1,695,1,732, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,696,1,910, +63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,17,17,17,17,17,697, +37,38,39,34,698,57,57,42,57,41,40,40, +154,154,154,154,154,154,154,154,153,153,153,153,154,154,154,154,153,153,153, + 153,153,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, + 154,154,154,154,154,154,699, +150,150,150,150,150,700, +129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,701,735,733,733, + 734, +380,702,230, +380,703,229, +380,704,228, +380,705,227, +380,706,226, +380,707,225, +380,708,224, +380,709,223, +380,710,222, +380,711,221, +380,712,220, +205,553,555,383,375,379,205,205,205,205,205,205,205,205,205,205,205,205,205, + 205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,713, + 559,558,557,556,554, +204,553,555,383,375,379,204,204,204,204,204,204,204,204,204,204,204,204,204, + 204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,714, + 559,558,557,556,554, +202,376,378,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, + 202,202,202,202,202,202,202,202,202,202,202,202,202,202,715,561,560, +201,376,378,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, + 201,201,201,201,201,201,201,201,201,201,201,201,201,201,716,561,560, +200,376,378,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, + 200,200,200,200,200,200,200,200,200,200,200,200,200,200,717,561,560, +199,376,378,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, + 199,199,199,199,199,199,199,199,199,199,199,199,199,199,718,561,560, +197,562,564,566,568,197,197,197,197,197,197,197,197,197,197,197,197,197,197, + 197,197,197,197,197,197,197,197,197,197,197,197,719,569,567,565,563, +196,562,564,566,568,196,196,196,196,196,196,196,196,196,196,196,196,196,196, + 196,196,196,196,196,196,196,196,196,196,196,196,720,569,567,565,563, +194,570,382,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, + 194,194,194,194,194,194,194,194,721,572,571, +193,570,382,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, + 193,193,193,193,193,193,193,193,722,572,571, +191,573,354,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, + 191,191,191,191,191,191,723,575,574, +190,573,354,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, + 190,190,190,190,190,190,724,575,574, +37,38,39,34,725,44,44,42,44,41,40,40, +37,38,39,34,726,29,29,42,29,41,40,40, +37,38,39,34,727,28,28,42,28,41,40,40, +736,736,736,736,736,736,736,736,736,1,728,1,736, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, + 135,135,262,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, + 135,135,135,135,135,135,135,729, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,625, + 279,138,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281, + 290,302,276,263,128,127,730,232,287,288,233,283,121,270,234,284,626,122, + 261,327,326,324,329,325,328,323,120,318,218,304,259,319,323,322,321,320, + 217,323,313,312,311,310,309,308,307,306,305,303,286,285,271,259,627,301, + 300, +129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, + 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, + 302,276,263,128,127,731,232,287,288,233,283,234,284,261,327,326,324,329, + 325,328,323,99,318,218,304,259,319,323,322,321,320,217,323,313,312,311, + 310,309,308,307,306,305,303,286,285,259,301,300, +129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,732,124,259,259, +130,130,130,130,130,130,130,130,130,130,130,130,131,131,131,131,131,130,19, + 130,1,733,1,125,131, +19,19,734,1,989, +737,1,735,1,737, +285,284,284,281,280,279,278,277,276,736,381,284,617, +380,737,231, }; static const unsigned short ag_sbt[] = { - 0, 27, 29, 66, 81, 110, 134, 306, 309, 326, 498, 813, 849, 868, - 887, 892, 900, 908, 927, 972,1017,1036,1042,1067,1087,1106,1111,1119, - 1127,1146,1231,1316,1335,1340,1349,1405,1493,1499,1548,1599,1646,1740, - 1829,1918,2239,2249,2258,2267,2276,2285,2294,2303,2312,2321,2330,2339, - 2348,2357,2366,2375,2388,2399,2444,2489,2534,2579,2624,2669,2714,2759, - 2804,2849,2894,2939,2984,3029,3074,3083,3092,3101,3110,3119,3128,3137, - 3146,3155,3164,3173,3182,3191,3200,3209,3218,3227,3236,3245,3254,3263, - 3272,3281,3290,3299,3308,3317,3326,3334,3347,3358,3403,3448,3493,3538, - 3583,3628,3673,3718,3763,3808,3853,3898,3943,3988,4033,4078,4123,4168, - 4213,4258,4303,4348,4393,4438,4483,4528,4573,4618,4663,4708,4753,4798, - 4810,4822,4830,4838,4849,4860,4871,4884,4897,4910,4923,4936,4949,4962, - 4975,4988,5001,5014,5022,5027,5032,5077,5122,5167,5212,5257,5302,5347, - 5392,5437,5482,5527,5572,5617,5662,5707,5752,5797,5842,5887,5932,5977, - 6022,6067,6112,6157,6202,6247,6292,6337,6382,6427,6472,6517,6562,6607, - 6652,6664,6676,6684,6692,6703,6714,6725,6738,6751,6764,6777,6790,6803, - 6816,6829,6842,6855,6868,6928,6937,6978,6985,6988,7073,7144,7152,7195, - 7239,7247,7292,7303,7311,7323,7335,7343,7349,7354,7357,7416,7471,7477, - 7522,7528,7539,7582,7623,7671,7724,7729,7734,7739,7744,7749,7754,7759, - 7764,7769,7774,7815,7856,7922,7927,7932,7937,7942,7947,7952,7957,7962, - 7967,7972,8014,8078,8120,8184,8229,8297,8365,8433,8501,8542,8586,8624, - 8662,8694,8724,8729,8767,8850,8858,8866,8873,8881,8889,8897,8905,8948, - 8956,8964,8972,8997,9027,9078,9143,9194,9259,9308,9359,9410,9461,9512, - 9563,9614,9665,9716,9767,9818,9869,9920,9971,10022,10073,10124,10175, - 10226,10277,10341,10406,10471,10536,10600,10675,10726,10791,10855,10906, - 10955,11006,11057,11113,11199,11202,11205,11280,11288,11305,11318,11331, - 11337,11340,11343,11426,11509,11592,11675,11758,11841,11924,12007,12090, - 12173,12256,12339,12422,12505,12588,12671,12754,12837,12920,13003,13086, - 13169,13252,13335,13418,13501,13584,13667,13750,13833,13916,13999,14082, - 14165,14248,14331,14346,14361,14369,14377,14390,14403,14416,14429,14442, - 14455,14468,14481,14494,14507,14520,14533,14546,14559,14650,14672,14786, - 14900,14908,14927,14946,14969,14991,14999,15007,15013,15022,15030,15038, - 15061,15085,15090,15095,15141,15187,15233,15320,15365,15448,15467,15486, - 15505,15524,15543,15563,15582,15602,15621,15641,15687,15733,15824,15870, - 15916,15962,16053,16098,16143,16226,16234,16279,16324,16369,16452,16462, - 16472,16484,16487,16569,16581,16596,16608,16620,16630,16637,16683,16732, - 16781,16784,16787,16790,16793,16796,16799,16802,16805,16808,16811,16894, - 16900,16942,16984,17026,17068,17110,17152,17194,17239,17284,17329,17374, - 17419,17464,17509,17554,17599,17644,17689,17734,17779,17824,17869,17914, - 17959,18004,18049,18094,18139,18184,18229,18274,18319,18364,18409,18454, - 18499,18544,18589,18634,18646,18658,18670,18682,18694,18739,18751,18763, - 18788,18796,18804,18812,18857,18940,18985,19068,19080,19088,19096,19107, - 19117,19162,19207,19216,19225,19230,19275,19321,19331,19336,19346,19367, - 19610,19655,19658,19749,19757,19765,19773,19781,19789,19794,19797,19884, - 19894,19900,19944,19946,19965,20048,20131,20214,20297,20380,20463,20546, - 20629,20712,20717,20785,20853,20921,20989,21057,21134,21211,21289,21367, - 21445,21523,21602,21681,21761,21841,21922,22003,22015,22027,22039,22047, - 22055,22067,22150,22233,22236,22282,22337,22383,22386,22395,22440,22485, - 22493,22512,22560,22606,22618,22662,22668,22688,22691,22694,22697,22700, - 22703,22706,22709,22712,22715,22718,22760,22802,22838,22874,22910,22946, - 22982,23018,23048,23078,23106,23134,23146,23158,23171,23216,23306,23389, - 23408,23433,23438,23443,23456,23459 + 0, 30, 32, 72, 87, 116, 140, 338, 341, 358, 556, 922, 961, 980, + 999,1004,1012,1020,1039,1085,1131,1150,1159,1184,1204,1223,1228,1236, + 1244,1263,1350,1437,1456,1467,1476,1535,1626,1632,1681,1732,1779,1873, + 1962,2051,2423,2433,2442,2451,2460,2469,2478,2487,2496,2505,2514,2523, + 2532,2541,2550,2559,2572,2585,2596,2642,2688,2734,2780,2826,2872,2918, + 2964,3010,3056,3102,3148,3194,3240,3286,3332,3341,3350,3359,3368,3377, + 3386,3395,3404,3413,3422,3431,3440,3449,3458,3467,3476,3485,3494,3503, + 3512,3521,3530,3539,3548,3557,3566,3575,3584,3593,3601,3614,3627,3638, + 3684,3730,3776,3822,3868,3914,3960,4006,4052,4098,4144,4190,4236,4282, + 4328,4374,4420,4466,4512,4558,4604,4650,4696,4742,4788,4834,4880,4926, + 4972,5018,5064,5110,5156,5202,5248,5294,5340,5386,5432,5478,5524,5570, + 5616,5662,5708,5754,5800,5846,5858,5870,5882,5894,5902,5910,5921,5932, + 5943,5956,5969,5982,5995,6008,6021,6034,6047,6060,6073,6086,6099,6112, + 6120,6125,6130,6135,6181,6227,6273,6319,6365,6411,6457,6503,6549,6595, + 6641,6687,6733,6779,6825,6871,6917,6963,7009,7055,7101,7147,7193,7239, + 7285,7331,7377,7423,7469,7515,7561,7607,7653,7699,7745,7791,7837,7883, + 7929,7975,8021,8067,8113,8159,8205,8251,8297,8343,8389,8435,8481,8527, + 8539,8551,8563,8575,8583,8591,8602,8613,8624,8637,8650,8663,8676,8689, + 8702,8715,8728,8741,8754,8767,8780,8793,8853,8862,8903,8910,8913,9000, + 9077,9085,9128,9172,9180,9225,9236,9244,9256,9268,9276,9282,9287,9290, + 9349,9404,9410,9455,9461,9472,9515,9556,9604,9657,9662,9671,9676,9681, + 9686,9691,9696,9701,9706,9711,9716,9757,9798,9865,9870,9875,9880,9885, + 9890,9895,9900,9905,9910,9915,9920,9963,10028,10071,10136,10182,10252, + 10322,10392,10462,10503,10547,10585,10623,10655,10685,10690,10728,10813, + 10821,10829,10836,10844,10852,10860,10868,10887,10906,10914,10922,10930, + 10938,10981,10989,10997,11005,11030,11060,11111,11177,11228,11294,11343, + 11394,11445,11496,11547,11598,11649,11700,11751,11802,11853,11904,11955, + 12006,12057,12108,12159,12210,12261,12312,12377,12443,12509,12575,12640, + 12715,12766,12832,12897,12948,12997,13048,13099,13158,13244,13247,13250, + 13331,13339,13356,13373,13386,13399,13405,13408,13411,13414,13499,13584, + 13669,13754,13839,13924,14009,14094,14179,14264,14349,14434,14519,14604, + 14689,14774,14859,14944,15029,15114,15199,15284,15369,15454,15539,15624, + 15709,15794,15879,15964,16049,16134,16219,16304,16389,16474,16559,16644, + 16729,16814,16899,16984,17069,17154,17239,17324,17409,17494,17579,17664, + 17749,17834,17849,17864,17879,17894,17902,17910,17923,17936,17949,17966, + 17983,17996,18009,18022,18035,18048,18061,18074,18087,18100,18113,18126, + 18219,18241,18378,18515,18534,18553,18576,18598,18606,18614,18620,18629, + 18637,18645,18668,18692,18697,18702,18749,18796,18843,18932,18978,19063, + 19082,19101,19120,19139,19158,19178,19197,19217,19236,19256,19303,19350, + 19443,19490,19537,19584,19677,19723,19769,19854,19862,19908,19954,20000, + 20085,20104,20114,20124,20136,20139,20221,20233,20248,20260,20272,20282, + 20289,20335,20384,20433,20436,20439,20442,20445,20448,20451,20454,20457, + 20460,20463,20466,20551,20557,20600,20643,20686,20729,20772,20815,20858, + 20904,20950,20996,21042,21088,21134,21180,21226,21272,21318,21364,21410, + 21456,21502,21548,21594,21640,21686,21732,21778,21824,21870,21916,21962, + 22008,22054,22100,22146,22192,22238,22284,22330,22342,22354,22366,22378, + 22390,22409,22421,22433,22478,22490,22502,22527,22535,22543,22551,22597, + 22682,22728,22813,22825,22833,22841,22851,22861,22871,22882,22892,22938, + 22984,23030,23039,23048,23053,23098,23144,23154,23159,23169,23190,23481, + 23526,23529,23622,23630,23638,23646,23654,23662,23667,23670,23757,23767, + 23773,23817,23819,23838,23923,24008,24093,24178,24263,24348,24433,24518, + 24603,24688,24693,24763,24833,24903,24973,25043,25122,25201,25281,25361, + 25441,25521,25602,25683,25765,25847,25930,26013,26021,26033,26045,26057, + 26065,26073,26085,26170,26255,26340,26343,26389,26445,26492,26495,26504, + 26549,26595,26603,26622,26670,26716,26728,26772,26778,26798,26801,26804, + 26807,26810,26813,26816,26819,26822,26825,26828,26831,26873,26915,26951, + 26987,27023,27059,27095,27131,27161,27191,27219,27247,27259,27271,27283, + 27296,27341,27433,27518,27537,27562,27567,27572,27585,27588 }; static const unsigned short ag_sbe[] = { - 24, 28, 52, 78, 108, 121, 303, 307, 316, 495, 667, 837, 865, 884, - 889, 897, 905, 924, 969,1014,1033,1039,1064,1082,1102,1107,1116,1124, - 1142,1187,1272,1331,1337,1342,1402,1490,1495,1545,1596,1643,1692,1784, - 1873,2086,2246,2255,2264,2273,2282,2291,2300,2309,2318,2327,2336,2345, - 2354,2363,2372,2385,2396,2441,2486,2531,2576,2621,2666,2711,2756,2801, - 2846,2891,2936,2981,3026,3071,3080,3089,3098,3107,3116,3125,3134,3143, - 3152,3161,3170,3179,3188,3197,3206,3215,3224,3233,3242,3251,3260,3269, - 3278,3287,3296,3305,3314,3323,3331,3344,3355,3400,3445,3490,3535,3580, - 3625,3670,3715,3760,3805,3850,3895,3940,3985,4030,4075,4120,4165,4210, - 4255,4300,4345,4390,4435,4480,4525,4570,4615,4660,4705,4750,4795,4807, - 4819,4827,4835,4846,4857,4868,4881,4894,4907,4920,4933,4946,4959,4972, - 4985,4998,5011,5019,5024,5029,5074,5119,5164,5209,5254,5299,5344,5389, - 5434,5479,5524,5569,5614,5659,5704,5749,5794,5839,5884,5929,5974,6019, - 6064,6109,6154,6199,6244,6289,6334,6379,6424,6469,6514,6559,6604,6649, - 6661,6673,6681,6689,6700,6711,6722,6735,6748,6761,6774,6787,6800,6813, - 6826,6839,6852,6865,6924,6934,6976,6983,6986,7029,7106,7149,7193,7236, - 7244,7290,7300,7308,7315,7327,7340,7348,7353,7356,7415,7470,7476,7520, - 7527,7538,7581,7622,7670,7722,7726,7731,7736,7741,7746,7751,7756,7761, - 7766,7771,7812,7853,7919,7924,7929,7934,7939,7944,7949,7954,7959,7964, - 7969,8011,8075,8117,8181,8226,8267,8335,8403,8471,8539,8578,8619,8655, - 8689,8719,8726,8747,8808,8855,8863,8871,8878,8886,8894,8902,8947,8953, - 8961,8969,8994,9018,9075,9140,9191,9256,9305,9356,9407,9458,9509,9560, - 9611,9662,9713,9764,9815,9866,9917,9968,10019,10070,10121,10172,10223, - 10274,10338,10403,10468,10533,10597,10672,10723,10788,10852,10903,10952, - 11003,11054,11110,11156,11200,11203,11240,11285,11294,11314,11325,11335, - 11338,11341,11384,11467,11550,11633,11716,11799,11882,11965,12048,12131, - 12214,12297,12380,12463,12546,12629,12712,12795,12878,12961,13044,13127, - 13210,13293,13376,13459,13542,13625,13708,13791,13874,13957,14040,14123, - 14206,14289,14339,14354,14365,14373,14384,14397,14410,14425,14438,14451, - 14464,14477,14490,14503,14516,14529,14542,14555,14601,14663,14783,14897, - 14905,14924,14942,14966,14988,14996,15004,15010,15015,15027,15035,15058, - 15081,15087,15091,15138,15184,15230,15275,15362,15406,15464,15482,15502, - 15520,15540,15558,15579,15597,15618,15636,15684,15730,15775,15867,15913, - 15959,16004,16095,16140,16184,16231,16276,16321,16366,16410,16459,16469, - 16476,16485,16527,16573,16594,16600,16612,16629,16636,16681,16731,16780, - 16782,16785,16788,16791,16794,16797,16800,16803,16806,16809,16852,16899, - 16939,16981,17023,17065,17107,17149,17191,17236,17281,17326,17371,17416, - 17461,17506,17551,17596,17641,17686,17731,17776,17821,17866,17911,17956, - 18001,18046,18091,18136,18181,18226,18271,18316,18361,18406,18451,18496, - 18541,18586,18631,18638,18650,18662,18674,18686,18738,18743,18755,18785, - 18793,18801,18809,18854,18898,18982,19026,19072,19085,19093,19104,19114, - 19159,19204,19213,19222,19227,19273,19319,19328,19333,19345,19365,19477, - 19653,19656,19700,19755,19763,19771,19779,19787,19791,19795,19840,19893, - 19899,19943,19945,19962,20006,20089,20172,20255,20338,20421,20504,20587, - 20670,20714,20755,20823,20891,20959,21027,21098,21175,21252,21330,21408, - 21486,21564,21643,21722,21802,21882,21963,22007,22019,22031,22044,22052, - 22059,22108,22191,22234,22280,22334,22380,22384,22392,22438,22482,22491, - 22509,22557,22605,22610,22661,22667,22683,22689,22692,22695,22698,22701, - 22704,22707,22710,22713,22716,22754,22796,22835,22871,22907,22943,22977, - 23013,23045,23075,23103,23131,23138,23150,23168,23215,23258,23347,23404, - 23429,23435,23440,23452,23457,23459 + 27, 31, 58, 84, 114, 127, 335, 339, 348, 553, 751, 949, 977, 996, + 1001,1009,1017,1036,1082,1128,1147,1156,1181,1199,1219,1224,1233,1241, + 1259,1305,1392,1452,1461,1469,1532,1623,1628,1678,1729,1776,1825,1917, + 2006,2245,2430,2439,2448,2457,2466,2475,2484,2493,2502,2511,2520,2529, + 2538,2547,2556,2569,2582,2593,2639,2685,2731,2777,2823,2869,2915,2961, + 3007,3053,3099,3145,3191,3237,3283,3329,3338,3347,3356,3365,3374,3383, + 3392,3401,3410,3419,3428,3437,3446,3455,3464,3473,3482,3491,3500,3509, + 3518,3527,3536,3545,3554,3563,3572,3581,3590,3598,3611,3624,3635,3681, + 3727,3773,3819,3865,3911,3957,4003,4049,4095,4141,4187,4233,4279,4325, + 4371,4417,4463,4509,4555,4601,4647,4693,4739,4785,4831,4877,4923,4969, + 5015,5061,5107,5153,5199,5245,5291,5337,5383,5429,5475,5521,5567,5613, + 5659,5705,5751,5797,5843,5855,5867,5879,5891,5899,5907,5918,5929,5940, + 5953,5966,5979,5992,6005,6018,6031,6044,6057,6070,6083,6096,6109,6117, + 6122,6127,6132,6178,6224,6270,6316,6362,6408,6454,6500,6546,6592,6638, + 6684,6730,6776,6822,6868,6914,6960,7006,7052,7098,7144,7190,7236,7282, + 7328,7374,7420,7466,7512,7558,7604,7650,7696,7742,7788,7834,7880,7926, + 7972,8018,8064,8110,8156,8202,8248,8294,8340,8386,8432,8478,8524,8536, + 8548,8560,8572,8580,8588,8599,8610,8621,8634,8647,8660,8673,8686,8699, + 8712,8725,8738,8751,8764,8777,8790,8849,8859,8901,8908,8911,8955,9036, + 9082,9126,9169,9177,9223,9233,9241,9248,9260,9273,9281,9286,9289,9348, + 9403,9409,9453,9460,9471,9514,9555,9603,9655,9659,9668,9673,9678,9683, + 9688,9693,9698,9703,9708,9713,9754,9795,9862,9867,9872,9877,9882,9887, + 9892,9897,9902,9907,9912,9917,9960,10025,10068,10133,10179,10221,10291, + 10361,10431,10500,10539,10580,10616,10650,10680,10687,10708,10770,10818, + 10826,10834,10841,10849,10857,10865,10884,10903,10911,10919,10927,10935, + 10980,10986,10994,11002,11027,11051,11108,11174,11225,11291,11340,11391, + 11442,11493,11544,11595,11646,11697,11748,11799,11850,11901,11952,12003, + 12054,12105,12156,12207,12258,12309,12374,12440,12506,12572,12637,12712, + 12763,12829,12894,12945,12994,13045,13096,13155,13201,13245,13248,13288, + 13336,13345,13365,13382,13393,13403,13406,13409,13412,13456,13541,13626, + 13711,13796,13881,13966,14051,14136,14221,14306,14391,14476,14561,14646, + 14731,14816,14901,14986,15071,15156,15241,15326,15411,15496,15581,15666, + 15751,15836,15921,16006,16091,16176,16261,16346,16431,16516,16601,16686, + 16771,16856,16941,17026,17111,17196,17281,17366,17451,17536,17621,17706, + 17791,17842,17857,17872,17887,17898,17906,17917,17930,17943,17958,17975, + 17992,18005,18018,18031,18044,18057,18070,18083,18096,18109,18122,18169, + 18232,18375,18512,18531,18549,18573,18595,18603,18611,18617,18622,18634, + 18642,18665,18688,18694,18698,18746,18793,18840,18886,18975,19020,19079, + 19097,19117,19135,19155,19173,19194,19212,19233,19251,19300,19347,19393, + 19487,19534,19581,19627,19720,19766,19811,19859,19905,19951,19997,20042, + 20100,20111,20121,20128,20137,20179,20225,20246,20252,20264,20281,20288, + 20333,20383,20432,20434,20437,20440,20443,20446,20449,20452,20455,20458, + 20461,20464,20508,20556,20597,20640,20683,20726,20769,20812,20855,20901, + 20947,20993,21039,21085,21131,21177,21223,21269,21315,21361,21407,21453, + 21499,21545,21591,21637,21683,21729,21775,21821,21867,21913,21959,22005, + 22051,22097,22143,22189,22235,22281,22327,22334,22346,22358,22370,22382, + 22405,22413,22425,22477,22482,22494,22524,22532,22540,22548,22594,22639, + 22725,22770,22817,22830,22838,22848,22858,22868,22879,22889,22935,22981, + 23027,23036,23045,23050,23096,23142,23151,23156,23168,23188,23323,23524, + 23527,23572,23628,23636,23644,23652,23660,23664,23668,23713,23766,23772, + 23816,23818,23835,23880,23965,24050,24135,24220,24305,24390,24475,24560, + 24645,24690,24732,24802,24872,24942,25012,25085,25164,25243,25323,25403, + 25483,25563,25644,25725,25807,25889,25972,26018,26025,26037,26049,26062, + 26070,26077,26127,26212,26297,26341,26387,26442,26489,26493,26501,26547, + 26592,26601,26619,26667,26715,26720,26771,26777,26793,26799,26802,26805, + 26808,26811,26814,26817,26820,26823,26826,26829,26867,26909,26948,26984, + 27020,27056,27090,27126,27158,27188,27216,27244,27251,27263,27275,27293, + 27340,27384,27475,27533,27558,27564,27569,27581,27586,27588 }; static const unsigned char ag_fl[] = { 2,1,1,2,2,1,1,2,0,1,3,3,1,2,1,2,2,1,2,0,1,4,5,3,2,1,0,1,7,7,1,1,6,6,6, - 2,3,2,1,2,4,4,4,4,0,1,4,4,4,4,3,3,4,4,6,4,1,4,1,1,2,2,2,2,3,5,1,2,2,1, - 1,1,3,2,1,1,3,1,1,1,3,1,1,3,3,3,3,3,3,3,3,3,4,6,2,3,2,1,1,2,2,3,3,2,2, - 3,3,1,1,2,3,1,1,1,4,4,4,1,4,2,1,1,1,1,2,2,1,2,2,3,2,2,1,2,3,1,2,2,2,2, - 2,2,2,2,4,1,1,4,3,2,1,2,3,3,2,1,1,1,2,1,1,1,1,2,1,1,2,1,1,2,1,1,2,1,1, - 2,1,1,2,1,2,4,4,2,4,4,2,4,4,2,4,4,4,4,2,4,4,2,4,4,4,4,4,1,2,2,2,2,1,1, - 1,5,5,5,5,5,5,5,5,5,5,7,1,1,1,1,1,1,1,2,2,2,1,1,2,2,2,2,1,2,2,2,3,2,2, - 2,2,2,2,2,2,3,4,1,1,2,2,2,2,2,1,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1, + 2,3,2,1,2,4,4,4,4,6,4,4,0,1,4,4,4,4,3,3,4,4,6,4,1,4,1,1,2,2,2,2,3,5,1, + 2,2,2,3,2,1,1,1,3,2,1,1,3,1,1,1,3,1,1,3,3,3,3,3,3,3,3,3,4,6,2,3,2,1,1, + 2,2,3,3,2,2,3,3,1,1,2,3,1,1,1,4,4,4,1,4,2,1,1,1,1,2,2,1,2,2,3,2,2,1,2, + 3,1,2,2,2,2,2,2,2,2,4,1,1,4,3,2,1,2,3,3,2,1,1,1,1,1,1,2,1,1,1,1,2,1,1, + 2,1,1,2,1,1,2,1,1,2,1,1,2,1,2,4,4,2,4,4,2,4,4,2,4,4,4,4,2,4,4,2,4,4,4, + 4,4,1,2,2,2,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,7,1,1,1,1,1,1,1,2,2,2,1,1,2, + 2,2,2,1,2,2,2,3,2,2,2,2,2,2,2,2,3,4,1,1,2,2,2,2,2,1,2,1,2,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,7,3,3,3, + 3,3,3,3,3,3,3,5,3,5,3,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,3,3, + 3,3,1,1,1,1,1,3,3,3,3,3,3,3,1,1,1,3,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,3,3,3,3,3,3,3,3,3,3,7,3,3,3,3,3,3,3,3,5,3,5,3,3,3,3,3,3,3,3,3,3,3,3, - 3,3,3,3,1,1,1,1,1,3,3,3,3,1,1,1,1,1,3,3,3,3,3,3,3,1,1,1,3,1,1,3,3,3,3, - 3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -5870,7 +6625,7 @@ static const unsigned char ag_fl[] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, @@ -5884,65 +6639,69 @@ static const unsigned char ag_fl[] = { static const unsigned short ag_ptt[] = { 0, 36, 37, 37, 34, 39, 43, 43, 44, 44, 39, 39, 39, 40, 47, 47, 47, 51, 51, 52, 52, 35, 35, 35, 35, 35, 55, 55, 35, 35, 61, 61, 35, 35, 35, 35, - 35, 35, 64, 53, 66, 66, 66, 66, 71, 71, 66, 66, 66, 66, 66, 66, 66, 66, - 66, 81, 81, 86, 86, 82, 82, 82, 91, 91, 62, 62, 33, 33, 33, 97, 97, 97, - 33, 33,101,101, 33,105,105,105, 33,108,108, 33, 33, 33, 33, 33, 33, 33, + 35, 35, 64, 53, 66, 66, 66, 66, 66, 66, 66, 74, 74, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 84, 84, 89, 89, 85, 85, 85, 94, 94, 62, 62, 33, 33, 33, + 33, 33, 33,100,100,100, 33, 33,104,104, 33,108,108,108, 33,111,111, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 30, 30, 87, 87, 87, 87, 87, 87,110,110,502,410,410,410,130,130,130, - 405,405,450, 18, 18,403, 12, 12, 12,139,139,139,139,139,139,139,139,139, - 139,152,152,139,139,404, 14, 14, 14, 14,397,397, 22, 22, 73, 73,164,164, - 164,160,167,167,160,170,170,160,173,173,160,176,176,160,179,179,160, 57, - 26, 26, 26, 28, 28, 28, 23, 23, 23, 24, 24, 24, 24, 24, 27, 27, 27, 25, - 25, 25, 25, 25, 25, 29, 29, 29, 29, 29,193,193,193,193,202,202,202,202, - 202,202,202,202,202,202,201,201,457,457,457,457,457,457,457,457,218,218, - 457,457, 7, 7, 7, 7, 7, 7, 6, 6, 6, 17, 17,213,213,214,214, 15, - 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,504, 9, 9, 9,554,554,554,554, - 554,554,237,237,554,554,240,240,566,242,242,566,244,244,566,566,246,246, - 246,246,246,248,248, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,263,263, - 263,263,257,257,257,257,257,270,270,257,257,257,276,276,276,257,257,257, - 257,257,257,257,257,257,287,287,257,257,257,257,257,257,257,257,257,257, - 300,300,300,257,257,257,257,257,257,251,251,252,252,249,249,249,249,249, - 249,249,249,249,249,249,250,250,250,324,254,326,255,256,253,253,253,253, - 253,253,253,253,253,253,253,253,253,253,253,350,350,350,350,350,253,253, - 253,253,359,359,359,359,359,253,253,253,253,253,253,253,369,369,369,253, - 372,372,253,253,253,253,253,253,253,253,253,135,329,150,221, 42, 42, 42, + 33, 33, 33, 33, 33, 33, 33, 30, 30, 90, 90, 90, 90, 90, 90,113,113,538, + 443,443,443,133,133,133,438,438,486, 18, 18,436, 12, 12, 12,142,142,142, + 142,142,142,142,142,142,142,155,155,142,142,437, 14, 14, 14, 14,430,430, + 430,430,430, 22, 22, 76, 76,170,170,170,166,173,173,166,176,176,166,179, + 179,166,182,182,166,185,185,166, 57, 26, 26, 26, 28, 28, 28, 23, 23, 23, + 24, 24, 24, 24, 24, 27, 27, 27, 25, 25, 25, 25, 25, 25, 29, 29, 29, 29, + 29,199,199,199,199,208,208,208,208,208,208,208,208,208,208,208,207,207, + 493,493,493,493,493,493,493,493,224,224,493,493, 7, 7, 7, 7, 7, 7, + 6, 6, 6, 17, 17,219,219,220,220, 15, 15, 15, 16, 16, 16, 16, 16, 16, + 16, 16,540, 9, 9, 9,596,596,596,596,596,596,243,243,596,596,246,246, + 610,248,248,610,250,250,610,610,252,252,252,252,252,254,254,255,255,255, + 255,255,255, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,273,273,273, + 273,267,267,267,267,267,280,280,267,267,267,286,286,286,267,267,267,267, + 267,267,267,267,267,297,297,267,267,267,267,267,267,267,267,267,267,310, + 310,310,267,267,267,267,267,267,267,260,260,261,261,261,261,258,258,258, + 258,258,258,258,258,258,258,258,258,258,259,259,259,339,263,341,264,343, + 265,266,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,367, + 367,367,367,367,262,262,262,262,376,376,376,376,376,262,262,262,262,262, + 262,262,386,386,386,262,390,390,390,262,262,262,262,262,262,262,262,262, + 262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,138,346, + 153,227, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89,133,133,133,133,133,133,133,133,133,133,133,133,133,134,134, - 134,134,134,134,134,134,134,134,134,134,134,134,136,136,136,136,136,136, - 136,136,136,136,136,136,136,136,136,136,136,136,136,141,141,141,141,141, - 141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, - 141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, - 148,148,148,149,149,149,149,149,153,153,153,153,153,153,153,153,153,156, - 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, - 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, - 156,156,156,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, - 157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, - 157,157,157,157,157,157,157,157,157,157,222,222,222,222,223,223,225,225, - 225,225,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, - 227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227, - 227,227,227,227,227,227,227, 45, 41, 46, 48, 49, 11, 54, 56, 58, 59, 60, - 10, 13, 19, 65, 68, 67, 69, 21, 70, 72, 74, 75, 76, 77, 78, 79, 80, 85, - 84, 83, 90, 92, 93, 94, 95, 96, 98, 99,100,102,103,104,106,107,109,111, - 112,113,114,115,116,117,119,118,120,121,122, 20,123,124,125,126,127,128, - 2,129,159,161,162,163,165,166,168,169,171,172,174,175,177,178,180,181, - 182,183,184,185,186,187,188,189,190,191,192,194,195,196,197,198,199,200, - 203,204,205,206,207,208,209,210,211, 3,212, 8,247,238,258,259,260,261, - 262,264,265,266,267,268,269,271,272,273,274,275,277,278,279,280,281,282, - 283,284,285,286,288,289,290,291,292,293,294,295,296,297,298,299,301,302, - 303,304,305,306,307,308,309, 4,310,311,312,313,314,315,316,317,318,319, - 320, 5,321,322,323,325,327,328,330,331,332,333,334,335,336,337,338,339, - 340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358, - 360,361,362,363,364,365,366,367,368,370,371,373,374,375,376,377,378,379, - 380,382,138,383,151,137,145,384,385,386,387,155,154,388,224,389,146,219, - 147,390,215,142,144,143,381,140,220,391 + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92,136,136,136,136,136,136,136,136,136,136, + 136,136,136,137,137,137,137,137,137,137,137,137,137,137,137,137,137,139, + 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, + 144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, + 144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, + 144,144,144,144,144,151,151,151,152,152,152,152,152,156,156,156,156,156, + 156,156,156,156,159,159,159,159,159,159,159,159,159,159,159,159,159,159, + 159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, + 159,159,159,159,159,159,159,159,160,160,160,160,160,160,160,160,160,160, + 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, + 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,228,228,228, + 228,229,229,231,231,231,231,233,233,233,233,233,233,233,233,233,233,233, + 233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, + 233,233,233,233,233,233,233,233,233,233,233,233, 45, 41, 46, 48, 49, 11, + 54, 56, 58, 59, 60, 10, 13, 19, 65, 68, 67, 69, 21, 70, 71, 72, 73, 75, + 77, 78, 79, 80, 81, 82, 83, 88, 87, 86, 93, 95, 96, 97, 98, 99,101,102, + 103,105,106,107,109,110,112,114,115,116,117,118,119,120,122,121,123,124, + 125, 20,126,127,128,129,130,131, 2,132,165,167,168,169,171,172,174,175, + 177,178,180,181,183,184,186,187,188,189,190,191,192,193,194,195,196,197, + 198,200,201,202,203,204,205,206,209,210,211,212,213,214,215,216,217, 3, + 218, 8,253,244,256,257,251,268,269,270,271,272,274,275,276,277,278,279, + 281,282,283,284,285,287,288,289,290,291,292,293,294,295,296,298,299,300, + 301,302,303,304,305,306,307,308,309,311,312,313,314,315,316,317,318,319, + 320,321,322, 4,323,324,325,326,327,328,329,330,331,332,333,334,335, 5, + 336,337,338,340,342,344,345,347,348,349,350,351,352,353,354,355,356,357, + 358,359,360,361,362,363,364,365,366,368,369,370,371,372,373,374,375,377, + 378,379,380,381,382,383,384,385,387,388,389,391,392,393,394,395,396,397, + 398,399,400,401,402,245,403,404,405,406,407,408,409,410,411,412,413,415, + 141,416,154,140,148,417,418,419,420,158,157,421,230,422,149,225,150,423, + 221,145,147,146,414,143,226,424 }; @@ -5974,15 +6733,15 @@ static void ag_ra(void) case 23: ag_rp_23(); break; case 24: ag_rp_24(); break; case 25: ag_rp_25(); break; - case 26: ag_rp_26(V(0,int)); break; - case 27: ag_rp_27(V(1,int)); break; + case 26: ag_rp_26(); break; + case 27: ag_rp_27(); break; case 28: ag_rp_28(); break; - case 29: ag_rp_29(); break; - case 30: ag_rp_30(); break; - case 31: ag_rp_31(V(2,int)); break; + case 29: ag_rp_29(V(0,int)); break; + case 30: ag_rp_30(V(1,int)); break; + case 31: ag_rp_31(); break; case 32: ag_rp_32(); break; case 33: ag_rp_33(); break; - case 34: ag_rp_34(); break; + case 34: ag_rp_34(V(2,int)); break; case 35: ag_rp_35(); break; case 36: ag_rp_36(); break; case 37: ag_rp_37(); break; @@ -6012,55 +6771,55 @@ static void ag_ra(void) case 61: ag_rp_61(); break; case 62: ag_rp_62(); break; case 63: ag_rp_63(); break; - case 64: ag_rp_64(V(2,int)); break; + case 64: ag_rp_64(); break; case 65: ag_rp_65(); break; case 66: ag_rp_66(); break; case 67: ag_rp_67(); break; case 68: ag_rp_68(); break; case 69: ag_rp_69(); break; - case 70: ag_rp_70(); break; + case 70: ag_rp_70(V(2,int)); break; case 71: ag_rp_71(); break; case 72: ag_rp_72(); break; case 73: ag_rp_73(); break; case 74: ag_rp_74(); break; - case 75: ag_rp_75(V(0,int)); break; - case 76: ag_rp_76(V(1,int)); break; - case 77: ag_rp_77(V(1,int)); break; - case 78: ag_rp_78(V(0,int)); break; - case 79: ag_rp_79(V(1,int)); break; - case 80: ag_rp_80(V(1,int), V(2,int)); break; - case 81: ag_rp_81(V(1,int)); break; - case 82: ag_rp_82(); break; + case 75: ag_rp_75(); break; + case 76: ag_rp_76(); break; + case 77: ag_rp_77(); break; + case 78: ag_rp_78(); break; + case 79: ag_rp_79(); break; + case 80: ag_rp_80(); break; + case 81: ag_rp_81(V(0,int)); break; + case 82: ag_rp_82(V(1,int)); break; case 83: ag_rp_83(V(1,int)); break; - case 84: V(0,int) = ag_rp_84(V(0,int)); break; - case 85: V(0,int) = ag_rp_85(); break; - case 86: V(0,int) = ag_rp_86(); break; - case 87: V(0,int) = ag_rp_87(); break; - case 88: V(0,int) = ag_rp_88(); break; - case 89: V(0,int) = ag_rp_89(); break; - case 90: V(0,int) = ag_rp_90(); break; + case 84: ag_rp_84(V(0,int)); break; + case 85: ag_rp_85(V(1,int)); break; + case 86: ag_rp_86(V(1,int), V(2,int)); break; + case 87: ag_rp_87(V(1,int)); break; + case 88: ag_rp_88(); break; + case 89: ag_rp_89(V(1,int)); break; + case 90: V(0,int) = ag_rp_90(V(0,int)); break; case 91: V(0,int) = ag_rp_91(); break; case 92: V(0,int) = ag_rp_92(); break; - case 93: V(0,int) = ag_rp_93(V(1,int), V(2,int), V(3,int)); break; - case 94: V(0,int) = ag_rp_94(V(2,int), V(3,int)); break; - case 95: V(0,int) = ag_rp_95(V(2,int)); break; - case 96: ag_rp_96(); break; - case 97: ag_rp_97(); break; - case 98: ag_rp_98(V(1,int)); break; - case 99: ag_rp_99(V(2,int)); break; - case 100: ag_rp_100(); break; - case 101: ag_rp_101(); break; - case 102: V(0,int) = ag_rp_102(); break; - case 103: V(0,int) = ag_rp_103(); break; - case 104: ag_rp_104(); break; - case 105: ag_rp_105(); break; + case 93: V(0,int) = ag_rp_93(); break; + case 94: V(0,int) = ag_rp_94(); break; + case 95: V(0,int) = ag_rp_95(); break; + case 96: V(0,int) = ag_rp_96(); break; + case 97: V(0,int) = ag_rp_97(); break; + case 98: V(0,int) = ag_rp_98(); break; + case 99: V(0,int) = ag_rp_99(V(1,int), V(2,int), V(3,int)); break; + case 100: V(0,int) = ag_rp_100(V(2,int), V(3,int)); break; + case 101: V(0,int) = ag_rp_101(V(2,int)); break; + case 102: ag_rp_102(); break; + case 103: ag_rp_103(); break; + case 104: ag_rp_104(V(1,int)); break; + case 105: ag_rp_105(V(2,int)); break; case 106: ag_rp_106(); break; case 107: ag_rp_107(); break; case 108: ag_rp_108(); break; case 109: ag_rp_109(); break; case 110: ag_rp_110(); break; - case 111: ag_rp_111(); break; - case 112: ag_rp_112(); break; + case 111: V(0,int) = ag_rp_111(); break; + case 112: V(0,int) = ag_rp_112(); break; case 113: ag_rp_113(); break; case 114: ag_rp_114(); break; case 115: ag_rp_115(); break; @@ -6081,7 +6840,7 @@ static void ag_ra(void) case 130: ag_rp_130(); break; case 131: ag_rp_131(); break; case 132: ag_rp_132(); break; - case 133: ag_rp_133(V(0,double)); break; + case 133: ag_rp_133(); break; case 134: ag_rp_134(); break; case 135: ag_rp_135(); break; case 136: ag_rp_136(); break; @@ -6090,58 +6849,58 @@ static void ag_ra(void) case 139: ag_rp_139(); break; case 140: ag_rp_140(); break; case 141: ag_rp_141(); break; - case 142: ag_rp_142(); break; + case 142: ag_rp_142(V(0,double)); break; case 143: ag_rp_143(); break; case 144: ag_rp_144(); break; - case 145: V(0,double) = ag_rp_145(V(0,int)); break; - case 146: V(0,double) = ag_rp_146(V(0,double)); break; - case 147: V(0,int) = ag_rp_147(V(0,int)); break; - case 148: V(0,int) = ag_rp_148(); break; - case 149: V(0,int) = ag_rp_149(); break; - case 150: V(0,int) = ag_rp_150(); break; - case 151: V(0,int) = ag_rp_151(); break; - case 152: V(0,int) = ag_rp_152(); break; - case 153: V(0,int) = ag_rp_153(); break; - case 154: V(0,int) = ag_rp_154(); break; - case 155: V(0,int) = ag_rp_155(); break; - case 156: V(0,int) = ag_rp_156(); break; - case 157: ag_rp_157(V(1,int)); break; - case 158: ag_rp_158(V(1,int)); break; - case 159: ag_rp_159(V(0,int)); break; - case 160: ag_rp_160(V(1,int)); break; - case 161: ag_rp_161(V(2,int)); break; - case 162: ag_rp_162(V(1,int)); break; - case 163: ag_rp_163(V(1,int)); break; - case 164: ag_rp_164(V(1,int)); break; - case 165: ag_rp_165(V(1,int)); break; - case 166: ag_rp_166(V(1,int)); break; + case 145: ag_rp_145(); break; + case 146: ag_rp_146(); break; + case 147: ag_rp_147(); break; + case 148: ag_rp_148(); break; + case 149: ag_rp_149(); break; + case 150: ag_rp_150(); break; + case 151: ag_rp_151(); break; + case 152: ag_rp_152(); break; + case 153: ag_rp_153(); break; + case 154: ag_rp_154(); break; + case 155: V(0,double) = ag_rp_155(V(0,int)); break; + case 156: V(0,double) = ag_rp_156(V(0,double)); break; + case 157: V(0,int) = ag_rp_157(V(0,int)); break; + case 158: V(0,int) = ag_rp_158(); break; + case 159: V(0,int) = ag_rp_159(); break; + case 160: V(0,int) = ag_rp_160(); break; + case 161: V(0,int) = ag_rp_161(); break; + case 162: V(0,int) = ag_rp_162(); break; + case 163: V(0,int) = ag_rp_163(); break; + case 164: V(0,int) = ag_rp_164(); break; + case 165: V(0,int) = ag_rp_165(); break; + case 166: V(0,int) = ag_rp_166(); break; case 167: ag_rp_167(V(1,int)); break; case 168: ag_rp_168(V(1,int)); break; - case 169: ag_rp_169(V(1,int)); break; - case 170: V(0,int) = ag_rp_170(V(1,int)); break; - case 171: V(0,int) = ag_rp_171(V(1,int), V(2,int)); break; - case 172: V(0,int) = ag_rp_172(); break; - case 173: V(0,int) = ag_rp_173(V(0,int)); break; - case 174: V(0,int) = ag_rp_174(); break; - case 175: V(0,int) = ag_rp_175(); break; - case 176: V(0,int) = ag_rp_176(); break; - case 177: V(0,int) = ag_rp_177(); break; - case 178: V(0,int) = ag_rp_178(); break; - case 179: V(0,int) = ag_rp_179(); break; - case 180: V(0,int) = ag_rp_180(); break; - case 181: V(0,double) = ag_rp_181(); break; - case 182: V(0,double) = ag_rp_182(V(1,int)); break; - case 183: V(0,double) = ag_rp_183(V(0,double), V(1,int)); break; - case 184: ag_rp_184(); break; - case 185: ag_rp_185(); break; - case 186: ag_rp_186(); break; - case 187: ag_rp_187(); break; - case 188: ag_rp_188(); break; - case 189: ag_rp_189(); break; - case 190: ag_rp_190(); break; - case 191: ag_rp_191(); break; - case 192: ag_rp_192(); break; - case 193: ag_rp_193(); break; + case 169: ag_rp_169(V(0,int)); break; + case 170: ag_rp_170(V(1,int)); break; + case 171: ag_rp_171(V(2,int)); break; + case 172: ag_rp_172(V(1,int)); break; + case 173: ag_rp_173(V(1,int)); break; + case 174: ag_rp_174(V(1,int)); break; + case 175: ag_rp_175(V(1,int)); break; + case 176: ag_rp_176(V(1,int)); break; + case 177: ag_rp_177(V(1,int)); break; + case 178: ag_rp_178(V(1,int)); break; + case 179: ag_rp_179(V(1,int)); break; + case 180: V(0,int) = ag_rp_180(V(1,int)); break; + case 181: V(0,int) = ag_rp_181(V(1,int), V(2,int)); break; + case 182: V(0,int) = ag_rp_182(); break; + case 183: V(0,int) = ag_rp_183(V(0,int)); break; + case 184: V(0,int) = ag_rp_184(); break; + case 185: V(0,int) = ag_rp_185(); break; + case 186: V(0,int) = ag_rp_186(); break; + case 187: V(0,int) = ag_rp_187(); break; + case 188: V(0,int) = ag_rp_188(); break; + case 189: V(0,int) = ag_rp_189(); break; + case 190: V(0,int) = ag_rp_190(); break; + case 191: V(0,double) = ag_rp_191(); break; + case 192: V(0,double) = ag_rp_192(V(1,int)); break; + case 193: V(0,double) = ag_rp_193(V(0,double), V(1,int)); break; case 194: ag_rp_194(); break; case 195: ag_rp_195(); break; case 196: ag_rp_196(); break; @@ -6204,7 +6963,7 @@ static void ag_ra(void) case 253: ag_rp_253(); break; case 254: ag_rp_254(); break; case 255: ag_rp_255(); break; - case 256: ag_rp_256(V(2,int)); break; + case 256: ag_rp_256(); break; case 257: ag_rp_257(); break; case 258: ag_rp_258(); break; case 259: ag_rp_259(); break; @@ -6226,7 +6985,7 @@ static void ag_ra(void) case 275: ag_rp_275(); break; case 276: ag_rp_276(); break; case 277: ag_rp_277(); break; - case 278: ag_rp_278(); break; + case 278: ag_rp_278(V(2,int)); break; case 279: ag_rp_279(); break; case 280: ag_rp_280(); break; case 281: ag_rp_281(); break; @@ -6241,11 +7000,49 @@ static void ag_ra(void) case 290: ag_rp_290(); break; case 291: ag_rp_291(); break; case 292: ag_rp_292(); break; + case 293: ag_rp_293(); break; + case 294: ag_rp_294(); break; + case 295: ag_rp_295(); break; + case 296: ag_rp_296(); break; + case 297: ag_rp_297(); break; + case 298: ag_rp_298(); break; + case 299: ag_rp_299(); break; + case 300: ag_rp_300(); break; + case 301: ag_rp_301(); break; + case 302: ag_rp_302(); break; + case 303: ag_rp_303(); break; + case 304: ag_rp_304(); break; + case 305: ag_rp_305(); break; + case 306: ag_rp_306(); break; + case 307: ag_rp_307(); break; + case 308: ag_rp_308(); break; + case 309: ag_rp_309(); break; + case 310: ag_rp_310(); break; + case 311: ag_rp_311(); break; + case 312: ag_rp_312(); break; + case 313: ag_rp_313(); break; + case 314: ag_rp_314(); break; + case 315: ag_rp_315(); break; + case 316: ag_rp_316(); break; + case 317: ag_rp_317(); break; + case 318: ag_rp_318(); break; + case 319: ag_rp_319(); break; + case 320: ag_rp_320(); break; + case 321: ag_rp_321(); break; + case 322: ag_rp_322(); break; + case 323: ag_rp_323(); break; + case 324: ag_rp_324(); break; + case 325: ag_rp_325(); break; + case 326: ag_rp_326(); break; + case 327: ag_rp_327(); break; + case 328: ag_rp_328(); break; + case 329: ag_rp_329(); break; + case 330: ag_rp_330(); break; } } #define TOKEN_NAMES a85parse_token_names -const char *const a85parse_token_names[647] = { +const char *const a85parse_token_names[709] = { "a85parse", "WS", "integer", @@ -6316,6 +7113,9 @@ const char *const a85parse_token_names[647] = { "\"PRAGMA\"", "\"LIST\"", "\"HEX\"", + "\"ENTRY\"", + "\"VERILOG\"", + "\"EXTENDED\"", "\"IFDEF\"", "", "\"IF\"", @@ -6405,6 +7205,9 @@ const char *const a85parse_token_names[647] = { "", "", "\":\"", + "\".BSS\"", + "\".TEXT\"", + "\".DATA\"", "\"INPAGE\"", "", "\"EQ\"", @@ -6495,6 +7298,9 @@ const char *const a85parse_token_names[647] = { "stack register", "\"PSW\"", "bd register", + "page register", + "\"DX\"", + "\"PC\"", "eight bit reg inst", "sixteen bit reg inst", "bd reg inst", @@ -6502,6 +7308,7 @@ const char *const a85parse_token_names[647] = { "immediate operand inst", "lxi inst", "mvi inst", + "spi inst", "rst inst", "no arg inst", "\"!\"", @@ -6552,10 +7359,13 @@ const char *const a85parse_token_names[647] = { "\"STC\"", "\"XCHG\"", "\"XTHL\"", + "\"LRET\"", "\"STAX\"", "\"LDAX\"", "\"POP\"", "\"PUSH\"", + "\"LPOP\"", + "\"LPUSH\"", "\"ADC\"", "\"ADD\"", "\"ANA\"", @@ -6567,6 +7377,8 @@ const char *const a85parse_token_names[647] = { "\"SBB\"", "\"SUB\"", "\"XRA\"", + "\"SPG\"", + "\"RPG\"", "\"DAD\"", "\"DCX\"", "\"INX\"", @@ -6574,6 +7386,8 @@ const char *const a85parse_token_names[647] = { "\"LXI\"", "mvi inst start", "\"MVI\"", + "spi inst start", + "\"SPI\"", "\"RST\"", "rst arg", "\"ACI\"", @@ -6618,6 +7432,7 @@ const char *const a85parse_token_names[647] = { "", "\"LDES\"", "\"DESP\"", + "\"LDSI\"", "", "\"LHLD\"", "\"ORI\"", @@ -6627,6 +7442,21 @@ const char *const a85parse_token_names[647] = { "\"STA\"", "\"SUI\"", "\"XRI\"", + "\"BR\"", + "\"BRA\"", + "\"BZ\"", + "\"BNZ\"", + "\"BNC\"", + "\"BM\"", + "\"BP\"", + "\"BPE\"", + "\"RCALL\"", + "\"SBZ\"", + "\"SBNZ\"", + "\"SBC\"", + "\"SBNC\"", + "\"LCALL\"", + "\"LJMP\"", "", "", "", @@ -6657,6 +7487,9 @@ const char *const a85parse_token_names[647] = { "\"PRAGMA\"", "\"HEX\"", "literal name nows", + "\"ENTRY\"", + "\"VERILOG\"", + "\"EXTENDED\"", "\"IFDEF\"", "\"IF\"", "\"ELIF\"", @@ -6753,6 +7586,9 @@ const char *const a85parse_token_names[647] = { "real", "\"PSW\"", "\"A\"", + "\"DX\"", + "\"PC\"", + "\"SP\"", "\"!\"", "\"ASHR\"", "\"SHLR\"", @@ -6796,10 +7632,13 @@ const char *const a85parse_token_names[647] = { "\"STC\"", "\"XCHG\"", "\"XTHL\"", + "\"LRET\"", "\"STAX\"", "\"LDAX\"", "\"POP\"", "\"PUSH\"", + "\"LPOP\"", + "\"LPUSH\"", "register 8 bit", "\"ADC\"", "\"ADD\"", @@ -6812,12 +7651,15 @@ const char *const a85parse_token_names[647] = { "\"SBB\"", "\"SUB\"", "\"XRA\"", + "\"SPG\"", + "\"RPG\"", "register 16 bit", "\"DAD\"", "\"DCX\"", "\"INX\"", "\"LXI\"", "\"MVI\"", + "\"SPI\"", "\"RST\"", "\"ACI\"", "\"ADI\"", @@ -6858,6 +7700,7 @@ const char *const a85parse_token_names[647] = { "\"LDHI\"", "\"LDES\"", "\"DESP\"", + "\"LDSI\"", "\"LHLD\"", "\"ORI\"", "\"OUT\"", @@ -6866,6 +7709,22 @@ const char *const a85parse_token_names[647] = { "\"STA\"", "\"SUI\"", "\"XRI\"", + "\"BR\"", + "\"BRA\"", + "\"BZ\"", + "\"BNZ\"", + "\"BC\"", + "\"BNC\"", + "\"BM\"", + "\"BP\"", + "\"BPE\"", + "\"RCALL\"", + "\"SBZ\"", + "\"SBNZ\"", + "\"SBC\"", + "\"SBNC\"", + "\"LCALL\"", + "\"LJMP\"", "", "'\\\"'", "", @@ -6898,61 +7757,68 @@ const char *const a85parse_token_names[647] = { static const unsigned short ag_ctn[] = { - 0,0, 0,0, 0,0, 64,1,397,1, 53,1, 35,1, 35,1, 35,1, 35,1, 35,1, 0,0, + 0,0, 0,0, 0,0, 64,1,430,1, 53,1, 35,1, 35,1, 35,1, 35,1, 35,1, 0,0, 66,1, 66,1, 66,1, 0,0, 0,0, 66,1, 66,1, 0,0, 66,1, 66,1, 0,0, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 0,0, 0,0, - 35,2, 47,1, 0,0, 39,1, 40,1, 39,1, 39,1, 35,2, 62,1,257,1,257,1,257,1, - 257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,326,1, - 324,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1, - 253,1,253,1,253,1,253,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1, - 257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1, - 257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,256,1,326,1,324,1,253,1, - 253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1, - 253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1, - 253,1,253,1,253,1,253,1,253,1,253,1,253,1,252,1,252,1,251,1,251,1,250,1, - 250,1,250,1,249,1,249,1,249,1,249,1,249,1,249,1,249,1,249,1,249,1,249,1, - 249,1,256,1,255,1,254,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1, - 253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1, - 253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1,253,1, - 253,1,253,1,253,1,253,1,252,1,252,1,251,1,251,1,250,1,250,1,250,1,249,1, - 249,1,249,1,249,1,249,1,249,1,249,1,249,1,249,1,249,1,249,1, 0,0, 32,1, - 86,1, 30,1, 32,1, 33,1, 33,1, 35,2, 81,1, 66,2, 66,2,403,1, 0,0, 66,2, - 66,2, 66,2, 66,2,504,1,214,1,213,1, 6,1, 6,1, 7,1, 15,1,504,1,457,1, - 214,1,213,1, 6,1,201,1,202,1,202,1,202,1,202,1,202,1,202,1,202,1,202,1, - 202,1,202,1,201,1, 0,0, 0,0,202,1,202,1,202,1,202,1,202,1,202,1,202,1, - 202,1,202,1,202,1, 29,1, 0,0, 29,1, 0,0,193,1, 29,1, 29,1, 29,1, 29,1, - 25,1, 27,1, 24,1, 23,1, 28,1, 26,1, 26,1, 73,1, 73,1, 66,2, 66,2, 66,2, - 0,0, 66,2, 0,0, 66,2,404,1, 0,0, 66,2, 66,2, 0,0, 35,3, 0,0, 0,0, + 35,2, 47,1, 0,0, 39,1, 40,1, 39,1, 39,1, 35,2, 62,1,267,1,267,1,267,1, + 267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,343,1, + 341,1,339,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, + 262,1,262,1,262,1,262,1,262,1,262,1,267,1,267,1,267,1,267,1,267,1,267,1, + 267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1, + 267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,266,1, + 343,1,341,1,339,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, + 262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, + 262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, + 262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, + 262,1,262,1,262,1,261,1,261,1,261,1,261,1,260,1,260,1,259,1,259,1,259,1, + 258,1,258,1,258,1,258,1,258,1,258,1,258,1,258,1,258,1,258,1,258,1,258,1, + 258,1,266,1,265,1,264,1,263,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, + 262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, + 262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, + 262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, + 262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,261,1,261,1,261,1, + 261,1,260,1,260,1,259,1,259,1,259,1,258,1,258,1,258,1,258,1,258,1,258,1, + 258,1,258,1,258,1,258,1,258,1,258,1,258,1, 0,0, 32,1, 89,1, 30,1, 32,1, + 33,1, 33,1, 35,2, 84,1, 66,2, 66,2,436,1, 0,0, 66,2, 66,2, 66,2, 66,2, + 540,1,220,1,219,1, 6,1, 6,1, 7,1, 15,1,540,1,493,1,220,1,219,1, 6,1, + 207,1,208,1, 0,0,208,1,208,1,208,1,208,1,208,1,208,1,208,1,208,1,208,1, + 207,1, 0,0, 0,0,208,1,208,1,208,1,208,1,208,1,208,1,208,1,208,1,208,1, + 208,1,208,1, 29,1, 0,0, 29,1, 0,0,199,1, 29,1, 29,1, 29,1, 29,1, 25,1, + 27,1, 24,1, 23,1, 28,1, 26,1, 26,1, 76,1, 76,1, 66,2, 66,2, 66,2, 0,0, + 66,2, 0,0, 66,2, 0,0, 66,2, 0,0, 66,2, 0,0, 66,2,437,1, 0,0, 66,2, + 66,2, 0,0, 35,3, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, - 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, - 0,0, 39,2, 39,2, 33,1, 35,3, 62,2,326,2,324,2,256,2,255,2,254,2,253,2, - 253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2, - 253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2, - 253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,253,2,252,2, - 252,2,251,2,251,2,250,2,250,2,250,2,249,2,249,2,249,2,249,2,249,2,249,2, - 249,2,249,2,249,2,249,2,249,2, 86,2, 0,0, 0,0, 32,2, 0,0, 0,0, 33,2, - 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, 33,2, + 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 39,2, 39,2, 33,1, 35,3, 62,2,343,2, + 341,2,339,2,266,2,265,2,264,2,263,2,262,2,262,2,262,2,262,2,262,2,262,2, + 262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2, + 262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2, + 262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2, + 262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,261,2,261,2, + 261,2,261,2,260,2,260,2,259,2,259,2,259,2,258,2,258,2,258,2,258,2,258,2, + 258,2,258,2,258,2,258,2,258,2,258,2,258,2,258,2, 89,2, 0,0, 0,0, 32,2, + 0,0, 33,2, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, - 0,0, 33,2, 0,0, 33,2, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, - 0,0, 33,2, 0,0, 0,0, 0,0, 0,0, 33,2, 0,0, 0,0, 35,3, 81,2, 66,3, - 66,3, 0,0, 66,3, 66,3, 6,2, 16,1, 15,2, 0,0, 0,0,202,2,202,2,202,2, - 202,2,202,2,202,2,202,2,202,2,202,2,202,2,193,2, 7,1, 0,0, 25,2, 0,0, - 25,2, 25,2, 25,2, 25,2, 27,2, 27,2, 0,0, 24,2, 0,0, 24,2, 0,0, 24,2, - 0,0, 24,2, 0,0, 23,2, 23,2, 0,0, 28,2, 28,2, 0,0, 26,2, 26,2, 0,0, - 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, - 66,3, 66,3, 66,3, 66,3, 66,3,404,2, 66,3, 66,3, 0,0, 35,4, 35,4, 35,4, - 0,0, 35,4, 0,0, 35,4, 35,4, 22,1, 62,3, 0,0, 0,0,255,3,254,3,246,1, - 246,1,249,3, 0,0,450,1, 0,0, 0,0, 6,1,457,1, 32,3,450,1, 33,3, 33,3, - 110,1,110,1,110,1, 0,0, 0,0, 0,0, 81,3, 82,1, 0,0, 0,0, 0,0, 15,3, - 202,3,202,3,202,3,202,3,202,3,202,3,202,3,202,3,202,3,202,3,193,3, 25,3, + 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, + 33,2, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 0,0, 33,2, 33,2, 0,0, 0,0, + 35,3, 84,2, 66,3, 66,3, 0,0, 66,3, 66,3, 6,2, 16,1, 15,2, 0,0, 0,0, + 208,2,208,2,208,2,208,2,208,2,208,2,208,2,208,2,208,2,208,2,208,2,199,2, + 7,1, 0,0, 25,2, 0,0, 25,2, 25,2, 25,2, 25,2, 27,2, 27,2, 0,0, 24,2, + 0,0, 24,2, 0,0, 24,2, 0,0, 24,2, 0,0, 23,2, 23,2, 0,0, 28,2, 28,2, + 0,0, 26,2, 26,2, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0,0, 0,0, 0,0, 0,0, 66,3, 66,3, 66,3, 66,3, 66,3, 66,3, 66,3, 66,3, + 437,2, 66,3, 66,3, 0,0, 35,4, 35,4, 35,4, 0,0, 35,4, 0,0, 35,4, 35,4, + 22,1, 62,3,255,1,255,1,255,1, 0,0, 0,0,265,3,264,3,263,3,252,1,252,1, + 258,3, 0,0,486,1, 0,0, 0,0, 6,1,493,1, 32,3,486,1, 33,3, 33,3,113,1, + 113,1,113,1, 0,0, 0,0, 0,0, 84,3, 85,1, 0,0, 0,0, 0,0, 15,3,208,3, + 208,3,208,3,208,3,208,3,208,3,208,3,208,3,208,3,208,3,208,3,199,3, 25,3, 25,3, 25,3, 25,3, 25,3, 27,3, 27,3, 24,3, 24,3, 24,3, 24,3, 23,3, 23,3, - 28,3, 28,3, 26,3, 26,3, 35,5, 35,5, 35,5, 35,5, 35,5, 62,4,255,4,254,4, - 249,4, 0,0, 0,0, 0,0, 32,1, 32,1,450,2, 33,4, 0,0,110,2, 0,0, 0,0, - 66,5, 0,0, 0,0,202,4,202,4,202,4,202,4,202,4,202,4,202,4,202,4,202,4, - 202,4,193,4, 25,1, 25,1, 27,1, 27,1, 27,1, 27,1, 24,1, 24,1, 23,1, 23,1, - 28,1, 28,1, 35,6, 35,6,249,5, 15,3, 0,0, 33,5,110,3,502,1, 0,0,202,5, - 249,6,202,6 + 28,3, 28,3, 26,3, 26,3, 66,4, 35,5, 35,5, 35,5, 35,5, 35,5, 62,4,265,4, + 264,4,263,4,258,4, 0,0, 0,0, 0,0, 32,1, 32,1,486,2, 33,4, 0,0,113,2, + 0,0, 0,0, 66,5, 0,0, 0,0,208,4,208,4,208,4,208,4,208,4,208,4,208,4, + 208,4,208,4,208,4,208,4,199,4, 25,1, 25,1, 27,1, 27,1, 27,1, 27,1, 24,1, + 24,1, 23,1, 23,1, 28,1, 28,1, 66,5, 35,6, 35,6,258,5, 15,3, 0,0, 33,5, + 113,3,538,1, 0,0,208,5,258,6,208,6 }; #ifndef MISSING_FORMAT diff --git a/src/a85parse.h b/src/a85parse.h index 43960cf..55bf36f 100644 --- a/src/a85parse.h +++ b/src/a85parse.h @@ -1,5 +1,5 @@ -#ifndef A85PARSE_H_1277850585 -#define A85PARSE_H_1277850585 +#ifndef A85PARSE_H_1357391036 +#define A85PARSE_H_1357391036 typedef union { long alignment; @@ -25,30 +25,32 @@ typedef enum { a85parse_cstyle_comment_head_token = 47, a85parse_preproc_inst_token = 53, a85parse_equation_token = 57, a85parse_cdseg_statement_token = 62, a85parse_error_token, a85parse_preproc_start_token, - a85parse_preprocessor_directive_token = 66, a85parse_condition_token = 73, - a85parse_macro_definition_token = 81, a85parse_macro_expansion_token, - a85parse_macro_token = 86, a85parse_expression_list_token, - a85parse_define_chars_token = 89, - a85parse_cdseg_statement_start_token = 91, a85parse_name_list_token = 110, - a85parse_literal_alpha_token = 130, a85parse_digit_token = 135, - a85parse_asm_incl_char_token, a85parse_str_escape_char_token = 139, - a85parse_hex_digit_token = 153, a85parse_condition_start_token = 160, - a85parse_primary_exp_token = 193, a85parse_value_token = 201, - a85parse_function_token, a85parse_binary_integer_token = 213, - a85parse_octal_integer_token, a85parse_stack_register_token = 246, - a85parse_bd_register_token = 248, a85parse_eight_bit_reg_inst_token, + a85parse_preprocessor_directive_token = 66, a85parse_condition_token = 76, + a85parse_macro_definition_token = 84, a85parse_macro_expansion_token, + a85parse_macro_token = 89, a85parse_expression_list_token, + a85parse_define_chars_token = 92, + a85parse_cdseg_statement_start_token = 94, a85parse_name_list_token = 113, + a85parse_literal_alpha_token = 133, a85parse_digit_token = 138, + a85parse_asm_incl_char_token, a85parse_str_escape_char_token = 142, + a85parse_hex_digit_token = 156, a85parse_condition_start_token = 166, + a85parse_primary_exp_token = 199, a85parse_value_token = 207, + a85parse_function_token, a85parse_binary_integer_token = 219, + a85parse_octal_integer_token, a85parse_stack_register_token = 252, + a85parse_bd_register_token = 254, a85parse_page_register_token, + a85parse_eight_bit_reg_inst_token = 258, a85parse_sixteen_bit_reg_inst_token, a85parse_bd_reg_inst_token, a85parse_stack_reg_inst_token, a85parse_immediate_operand_inst_token, - a85parse_lxi_inst_token, a85parse_mvi_inst_token, a85parse_rst_inst_token, - a85parse_no_arg_inst_token, a85parse_lxi_inst_start_token = 324, - a85parse_mvi_inst_start_token = 326, a85parse_rst_arg_token = 329, - a85parse_label_token = 397, a85parse_literal_string_token = 403, + a85parse_lxi_inst_token, a85parse_mvi_inst_token, a85parse_spi_inst_token, + a85parse_rst_inst_token, a85parse_no_arg_inst_token, + a85parse_lxi_inst_start_token = 339, a85parse_mvi_inst_start_token = 341, + a85parse_spi_inst_start_token = 343, a85parse_rst_arg_token = 346, + a85parse_label_token = 430, a85parse_literal_string_token = 436, a85parse_include_string_token, a85parse_asm_include_token, - a85parse_literal_name_nows_token = 410, - a85parse_parameter_list_token = 421, - a85parse_singlequote_string_token = 450, a85parse_integer_token = 457, - a85parse_literal_name_token = 502, a85parse_real_token = 504, - a85parse_register_8_bit_token = 554, a85parse_register_16_bit_token = 566 + a85parse_literal_name_nows_token = 443, + a85parse_parameter_list_token = 457, + a85parse_singlequote_string_token = 486, a85parse_integer_token = 493, + a85parse_literal_name_token = 538, a85parse_real_token = 540, + a85parse_register_8_bit_token = 596, a85parse_register_16_bit_token = 610 } a85parse_token_type; typedef struct a85parse_pcb_struct{ @@ -65,7 +67,7 @@ typedef struct a85parse_pcb_struct{ char read_flag; char exit_flag; int bts[128], btsx; - int lab[8], rx, fx; + int lab[9], rx, fx; const unsigned char *key_sp; int save_index, key_state; char ag_msg[82]; diff --git a/src/a85parse.syn b/src/a85parse.syn index 156310e..048ed61 100644 --- a/src/a85parse.syn +++ b/src/a85parse.syn @@ -113,6 +113,9 @@ preprocessor directive -> "include", include string, WS?..., comment = gAsm->include(ss[ss_idx--]); -> "pragma", "list", WS?..., comment = gAsm->pragma_list(); -> "pragma", "hex", WS?..., comment = gAsm->pragma_hex(); + -> "pragma", "entry", WS?..., literal name nows, WS?..., comment = gAsm->pragma_entry(ss[ss_idx--]); + -> "pragma", "verilog", WS?..., comment = gAsm->pragma_verilog(); + -> "pragma", "extended", WS?..., comment = gAsm->pragma_extended(); -> "ifdef", literal name nows, WS?, comment = gAsm->preproc_ifdef(ss[ss_idx--]); -> "if", condition, WS?..., comment = gAsm->preproc_if(); -> "elif", condition, WS?..., comment = gAsm->preproc_elif(); @@ -166,6 +169,9 @@ expression -> macro -> '.'?, "list" = gAsm->pragma_list(); -> '.'?, "hex" = gAsm->pragma_hex(); + -> '.'?, "verilog" = gAsm->pragma_verilog(); + -> '.'?, "entry", literal name nows = gAsm->pragma_entry(ss[ss_idx--]); + -> '.'?, "extended" = gAsm->pragma_extended(); -> '.'?, {"org" | "$=" | "*="}, equation = gAsm->directive_org(); -> '.'?, "aseg" = gAsm->directive_aseg(); -> '.'?, {"ds" | "block"}, equation = gAsm->directive_ds(); @@ -291,6 +297,9 @@ include chars label -> literal name nows, ":" = gAsm->label(ss[ss_idx--]); -> literal name nows = gAsm->label(ss[ss_idx--]); + -> ".bss" = gAsm->label(".bss"); + -> ".text" = gAsm->label(".text"); + -> ".data" = gAsm->label(".data"); (int) pagespec -> "page" = PAGE; @@ -392,6 +401,7 @@ primary exp -> "fp", WS?..., '(', equation, ')' = gEq->Add(RPN_FP); -> "high", WS?..., '(', equation, ')' = gEq->Add(RPN_HIGH); -> "low", WS?..., '(', equation, ')' = gEq->Add(RPN_LOW); + -> "page", WS?..., '(', equation, ')' = gEq->Add(RPN_PAGE); -> "defined", WS?..., '(', WS?..., literal name, WS?..., ')' = gEq->Add(RPN_DEFINED, ss[ss_idx--]); @@ -500,6 +510,14 @@ bd register -> {"b" | "bc" } = reg[reg_cnt++] = '0'; -> {"d" | "de" } = reg[reg_cnt++] = '1'; +page register + -> {"b" | "bc" } = reg[reg_cnt++] = '0'; + -> {"d" | "de" } = reg[reg_cnt++] = '1'; + -> {"h" | "hl" } = reg[reg_cnt++] = '2'; + -> "dx" = reg[reg_cnt++] = '3'; + -> "pc" = reg[reg_cnt++] = '4'; + -> "sp" = reg[reg_cnt++] = '5'; + /* ============================================================================ Define the 8085 instruction set @@ -522,6 +540,7 @@ instruction -> immediate operand inst -> lxi inst -> mvi inst + -> spi inst -> rst inst -> no arg inst -> instruction list, "!", WS?..., instruction @@ -561,6 +580,7 @@ no arg inst -> "stc" = gAsm->opcode_arg_0 (OPCODE_STC); -> "xchg" = gAsm->opcode_arg_0 (OPCODE_XCHG); -> "xthl" = gAsm->opcode_arg_0 (OPCODE_XTHL); + -> "lret" = gAsm->opcode_arg_0 (OPCODE_LRET); bd reg inst -> "stax", WS?..., bd register = gAsm->opcode_arg_1reg (OPCODE_STAX); @@ -569,6 +589,8 @@ bd reg inst stack reg inst -> "pop", WS?..., stack register = gAsm->opcode_arg_1reg (OPCODE_POP); -> "push", WS?..., stack register = gAsm->opcode_arg_1reg (OPCODE_PUSH); + -> "lpop", WS?..., stack register = gAsm->opcode_arg_1reg_2byte (OPCODE_LPOP); + -> "lpush", WS?..., stack register = gAsm->opcode_arg_1reg_2byte (OPCODE_LPUSH); eight bit reg inst -> "adc", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_ADC); @@ -583,6 +605,8 @@ eight bit reg inst -> "sbb", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_SBB); -> "sub", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_SUB); -> "xra", WS?..., register 8 bit = gAsm->opcode_arg_1reg (OPCODE_XRA); + -> "spg", WS?..., page register = gAsm->opcode_arg_1reg_2byte (OPCODE_SPG); + -> "rpg", WS?..., page register = gAsm->opcode_arg_1reg_2byte (OPCODE_RPG); sixteen bit reg inst -> "dad", WS?..., register 16 bit = gAsm->opcode_arg_1reg (OPCODE_DAD); @@ -601,6 +625,12 @@ mvi inst start mvi inst -> mvi inst start, WS?..., ',', WS?..., equation = gAsm->opcode_arg_1reg_equ8(OPCODE_MVI); +spi inst start + -> "spi", WS?..., page register + +spi inst + -> spi inst start, WS?..., ',', WS?..., equation = gAsm->opcode_arg_1reg_equ16(OPCODE_SPI); + rst inst -> "rst", WS?..., rst arg:c = gAsm->opcode_arg_imm (OPCODE_RST, c); @@ -634,7 +664,7 @@ immediate operand inst -> "jz", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_JZ); -> "lda", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_LDA); -> {"ldeh" | "dehl" | "ldhi"}, WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_LDEH); - -> {"ldes" | "desp"}, WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_LDES); + -> {"ldes" | "desp" | "ldsi"}, WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_LDES); -> "lhld", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_LHLD); -> "ori", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_ORI); -> "out", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_OUT); @@ -644,6 +674,23 @@ immediate operand inst -> "sui", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_SUI); -> "xri", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_XRI); +// Extended instructions + -> "br", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_BR); + -> "bra", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_BRA); + -> "bz", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_BZ); + -> "bnz", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_BNZ); + -> "bc", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_BC); + -> "bnc", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_BNC); + -> "bm", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_BM); + -> "bp", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_BP); + -> "bpe", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_BPE); + -> "rcall", WS?..., equation = gAsm->opcode_arg_equ16 (OPCODE_RCALL); + -> "sbz", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_SBZ); + -> "sbnz", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_SBNZ); + -> "sbc", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_SBC); + -> "sbnc", WS?..., equation = gAsm->opcode_arg_equ8 (OPCODE_SBNC); + -> "lcall", WS?..., equation = gAsm->opcode_arg_equ24 (OPCODE_LCALL); + -> "ljmp", WS?..., equation = gAsm->opcode_arg_equ24 (OPCODE_LJMP); { // Embedded C diff --git a/src/assemble.cpp b/src/assemble.cpp index 485f5d7..1e0552b 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -86,7 +86,15 @@ unsigned char gOpcodeType[INST_ORG] = { 0, OPCODE_EQU16, OPCODE_EQU8, OPCODE_EQU8, OPCODE_EQU8, // 77-80 OPCODE_EQU8, OPCODE_EQU8, OPCODE_EQU8, OPCODE_EQU8, // 81-84 OPCODE_EQU8, OPCODE_IMM, OPCODE_EQU16, OPCODE_NOARG, // 85-88 - OPCODE_NOARG, OPCODE_NOARG // 89 + OPCODE_NOARG, OPCODE_NOARG, // 89-90 + + // Extended opcodes + OPCODE_NOARG, OPCODE_EQU24, // 91-92 (LRET, LCALL) + OPCODE_EQU24, OPCODE_LPP, OPCODE_LPP, OPCODE_EQU16, // 93-96 (LJMP, LPUSH, LPOP, BR) + OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, // 97-100 (BRA, BZ, BNZ, BC) + OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, // 101-104 (BNC, BM, BP, BPE) + OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, OPCODE_EQU16, // 105-108 (SBZ, SBNZ, SBC, SBNC) + OPCODE_EQU16, OPCODE_PGI, OPCODE_PG, OPCODE_PG // 109-112 (RCALL, SPI, SPG, RPG) }; unsigned char gOpcodeBase[INST_ORG] = { 0, @@ -101,7 +109,13 @@ unsigned char gOpcodeBase[INST_ORG] = { 0, 0xC4, 0xCC, 0xD4, 0xDC, 0xE4, 0xEC, 0xF4, 0xFC, // 65-72 0x22, 0xCD, 0xDD, 0xED, 0xFD, 0xC6, 0xCE, 0xD6, // 73-80 0xDE, 0xE6, 0xEE, 0xF6, 0xFE, 0xC7, 0xC3, 0xC9, // 81-88 - 0x76, 0xCB // 89 + 0x76, 0xCB, // 90 + + // Extended opcodes + 0x64, 0x5B, 0x52, 0x18, 0x20, 0x40, // 91-96 (LRET, LCALL, LJMP, LPUSH, LPOP, BR) + 0x80, 0x20, 0x00, 0x60, 0x40, 0xE0, 0xC0, 0xA0, // 97-104 (BRA, BZ, BNZ, BC, BNC, BM, BP, BPE) + 0x40, 0x00, 0xC0, 0x80, 0x7F, 0x00, 0x08, 0x10 // 105-112 (SBZ, SBNZ, SBC, SBNC, RCALL, SPI, SPG, RPG) + }; unsigned char gShift[20] = { 0, @@ -112,20 +126,12 @@ unsigned char gShift[20] = { 0, const char* types[5] = { "", "a label", "an equate", "a set", "an extern" }; - -void cb_assembler(class Fl_Widget* w, void*) -{ - VTAssembler* pAsm = new VTAssembler; - - pAsm->Parse("test.asm"); - - delete pAsm; -} - VTAssembler::VTAssembler() { m_List = 0; m_Hex = 0; + m_Extended = 0; + m_Verilog = 0; m_IncludeDepth = 0; m_FileIndex = -1; m_DebugInfo = 0; @@ -265,6 +271,8 @@ void VTAssembler::ResetContent(void) m_SegLines.Add(m_ActiveSegLines); m_Hex = 0; + m_Verilog = 0; + m_Extended = 0; m_List = 0; m_Address = 0; m_DebugInfo = 0; @@ -292,6 +300,17 @@ void VTAssembler::pragma_list() m_List = 1; } +/* +============================================================================ +The parser calls this function when it detects a programentry pragma. +============================================================================ +*/ +void VTAssembler::pragma_entry(const char * pName) +{ + if (m_IfStat[m_IfDepth] == IF_STAT_ASSEMBLE) + m_EntryLabel = pName; +} + /* ============================================================================ The parser calls this function when it detects a hex output pragma. @@ -303,6 +322,28 @@ void VTAssembler::pragma_hex() m_Hex = 1; } +/* +============================================================================ +The parser calls this function when it detects the "extended" pragma. +============================================================================ +*/ +void VTAssembler::pragma_extended() +{ + if (m_IfStat[m_IfDepth] == IF_STAT_ASSEMBLE) + m_Extended = 1; +} + +/* +============================================================================ +The parser calls this function when it detects a hex output pragma. +============================================================================ +*/ +void VTAssembler::pragma_verilog() +{ + if (m_IfStat[m_IfDepth] == IF_STAT_ASSEMBLE) + m_Verilog = 1; +} + /* ============================================================================ This function evaluates equations and attempts to determine a numeric value @@ -552,6 +593,11 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, stack[stk++] = log(s1); break; + case RPN_PAGE: + s1 = stack[--stk]; + stack[stk++] = ((unsigned int) s1 >> 16) & 0xFF; + break; + case RPN_HIGH: s1 = stack[--stk]; stack[stk++] = ((unsigned int) s1 >> 8) & 0xFF; @@ -813,7 +859,38 @@ void VTAssembler::opcode_arg_1reg_equ8(int opcode) // Increment Address again to account for 8-bit value m_ActiveSeg->m_Address++; - m_ActiveAddr->length += 2; // Update add range length + m_ActiveAddr->length += 1; // Update add range length + } +} + +/* +=========================================================================================== +Function to process opcodes that take a single register argument and an equation that +results in an 16-bit value +=========================================================================================== +*/ +void VTAssembler::opcode_arg_1reg_2byte(int opcode) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + reg_cnt--; // Pop unused reg operand from stack + delete gEq; // Delete the unused equaiton + gEq = new CRpnEquation; // Allocate new equation for parser + return; + } + + // Read operands (register & equation) from parser + CInstruction* pInst = AddInstruction(opcode); + if (pInst != NULL) + { + // Append instruction with operands + pInst->m_Operand1 = new MString; // Allocte operand object + pInst->m_Operand1->Format("%c", reg[--reg_cnt]); // Get register operand + + // Add 1 to address to account for 2-byte opcode + m_ActiveSeg->m_Address++; + m_ActiveAddr->length++; // Update add range length } } @@ -848,7 +925,7 @@ void VTAssembler::opcode_arg_1reg_equ16(int opcode) // Add 2 to address to account for 16-bit argument m_ActiveSeg->m_Address += 2; - m_ActiveAddr->length += 3; // Update add range length + m_ActiveAddr->length += 2; // Update add range length } } @@ -880,7 +957,7 @@ void VTAssembler::opcode_arg_equ8(int opcode) // Increment Address again to account for 8-bit value m_ActiveSeg->m_Address++; - m_ActiveAddr->length += 2; // Update add range length + m_ActiveAddr->length += 1; // Update add range length } } @@ -911,6 +988,37 @@ void VTAssembler::opcode_arg_equ16(int opcode) // Increment Address to account for 16-bit value m_ActiveSeg->m_Address += 2; + m_ActiveAddr->length += 2; // Update add range length + } +} + +/* +=========================================================================================== +Function to process opcodes that take a 24 bit equation argument +=========================================================================================== +*/ +void VTAssembler::opcode_arg_equ24(int opcode) +{ + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + { + delete gEq; // Delete the unused equaiton + gEq = new CRpnEquation; // Allocate new equation for parser + return; + } + + // Read operand (register) from string accumulator + CInstruction* pInst = AddInstruction(opcode); + if (pInst != NULL) + { + // Append instruction with operand + pInst->m_Group = gEq; // Get equation + + // Allocate new equation for the parser + gEq = new CRpnEquation; + + // Increment Address to account for 24-bit value + m_ActiveSeg->m_Address += 3; m_ActiveAddr->length += 3; // Update add range length } } @@ -1126,6 +1234,7 @@ void VTAssembler::label(const char *label, int address) pSymbol->m_FileIndex = m_FileIndex; // Save index of the current file pSymbol->m_SymType = SYM_LABEL | SYM_HASVALUE; pSymbol->m_pRange = m_ActiveAddr; + pSymbol->m_Segment = m_ActiveSeg; if (m_ActiveSeg->m_Type == CSEG) pSymbol->m_SymType |= SYM_CSEG; else if (m_ActiveSeg->m_Type == DSEG) @@ -1323,15 +1432,20 @@ void VTAssembler::directive_org() // Try to calculate new address if (Evaluate(gEq, &value, 0)) { - m_ActiveSeg->m_Address = (unsigned short) value; - pInst->m_Address = m_ActiveSeg->m_Address; + // Save the ORGed address + m_ActiveSeg->m_Address = (unsigned int) value; + pInst->m_Address = (unsigned int) value; + // Check if the previously allocated AddrRange struct was used. If it was, + // then allocate a new one and add to the linked list if (m_ActiveAddr->length != 0) { // Allocate a new AddrRange object for this ORG newRange = new AddrRange; newRange->address = m_ActiveSeg->m_Address; newRange->length = 0; + newRange->shidx = 0; + newRange->line = m_Line; // Find location to insert this object thisRange = m_ActiveSeg->m_UsedAddr; @@ -2803,9 +2917,9 @@ int VTAssembler::Assemble() CSymbol* pSymbol; AddrRange* pRange; unsigned char opcode; - unsigned char op1 = 0xCC, op2 = 0xCC; + unsigned char op1 = 0xCC, op2 = 0xCC, op3 = 0xCC; unsigned char type; - unsigned short address; + unsigned int address; double value; char rel_mask; int valid, extern_label; @@ -2864,6 +2978,16 @@ int VTAssembler::Assemble() valid = 1; extern_label = 0; + // Remap opcode for 2-byte OPCODES + if ((pInst->m_ID == OPCODE_LPUSH) || (pInst->m_ID == OPCODE_LPOP) || + (pInst->m_ID == OPCODE_SPI) || (pInst->m_ID == OPCODE_SPG) || + (pInst->m_ID == OPCODE_RPG)) + { + // Remap the opcode to the 1st operand byte & fill in actual 1st opcode byte + op1 = opcode; + opcode = 0xCB; + } + // Modifiy base opcode based on opcode type switch (type) { @@ -2881,79 +3005,86 @@ int VTAssembler::Assemble() opcode |= (intptr_t) pInst->m_Group - '0'; opcode |= atoi(*pInst->m_Operand1) << 3; break; + + case OPCODE_PGI: + case OPCODE_PG: + case OPCODE_LPP: + op1 |= atoi(*pInst->m_Operand1) & 0x07; } // Now determine operand bytes - if ((type == OPCODE_EQU8) || (type == OPCODE_EQU16) || - (type == OPCODE_REG_IMM) || (type == OPCODE_REG_EQU16)) + if ((type == OPCODE_EQU8) || (type == OPCODE_EQU16) || (type == OPCODE_EQU24) || + (type == OPCODE_REG_IMM) || (type == OPCODE_REG_EQU16) || + (type == OPCODE_PGI)) { + if ((type == OPCODE_EQU8) || (type == OPCODE_REG_IMM)) + size = 1; + else if (type == OPCODE_EQU24) + size = 3; + else + size = 2; + // Try to get value of the equation if (Evaluate((CRpnEquation *) pInst->m_Group, &value, 1)) { - // Equation evaluated to a value.check if it is + // Equation evaluated to a value. Check if it is // relative to a relocatable segment if (InvalidRelocation((CRpnEquation *) pInst->m_Group, rel_mask, relSeg)) { - // Error, equation cannot be evaluted -// err.Format("Error in line %d(%s): Equation depends on multiple segments", -// pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); -// m_Errors.Add(err); valid = 0; } - op1 = (int) value & 0xFF; - op2 = ((int) value >> 8) & 0xFF; + if (type == OPCODE_PGI) + op2 = (int) value & 0xFF; + else + { + op1 = (int) value & 0xFF; + op2 = ((int) value >> 8) & 0xFF; + op3 = ((int) value >> 16) & 0xFF; + } } else - { - if ((type == OPCODE_EQU8) || (type == OPCODE_REG_IMM)) - size = 1; - else - size = 2; - + { // Equation does not evaluate. Check if it is an extern if (EquationIsExtern((CRpnEquation *) pInst->m_Group, size)) { // Add a dummy value (0) with relocation op1 = 0; op2 = 0; + op3 = 0; value = 0.0; extern_label = 1; } else { - // Error, equation cannot be evaluted -// err.Format("Error in line %d(%s): Equation cannot be evaluated", -// pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); -// m_Errors.Add(err); valid = 0; } } } - // Add opcode and operands to array - m_ActiveSeg->m_AsmBytes[m_Address++] = opcode; - // Check if operand is PC relative if ((rel_mask > 1) && valid) { // Add relocation information pRel = new CRelocation; - pRel->m_Address = m_Address; + pRel->m_Address = m_Address + 1; pRel->m_pSourceRange = m_ActiveAddr; pRel->m_Segment = relSeg; pRange = m_ActiveSeg->m_UsedAddr; + if (relSeg != NULL) + pRange = relSeg->m_UsedAddr; while ((pRange != 0) && (pRel->m_pTargetRange == 0)) { - if ((pRange->address <= (int) value) && - (pRange->address + pRange->length > (int) value)) + if ((pRange->address <= (unsigned int) value) && + (pRange->address + pRange->length > (unsigned int) value)) { pRel->m_pTargetRange = pRange; } pRange = pRange->pNext; } - m_ActiveSeg->m_Reloc.Add(pRel); + relSeg->m_Reloc.Add(pRel); +// m_ActiveSeg->m_Reloc.Add(pRel); } // Check if operand is extern @@ -2961,7 +3092,7 @@ int VTAssembler::Assemble() { // Add extern linkage information pExt = new CExtern; - pExt->m_Address = m_Address; + pExt->m_Address = m_Address + 1; pExt->m_Name = ((CRpnEquation *) pInst->m_Group)->m_OperationArray[0].m_Variable; pExt->m_Segment = m_ActiveSeg->m_Type; @@ -2969,21 +3100,119 @@ int VTAssembler::Assemble() pExt->m_pRange = m_ActiveAddr; m_Externs.Add(pExt); } + // Test for relative branch instruction + else if ((pInst->m_ID >= OPCODE_BR) && (pInst->m_ID <= OPCODE_RCALL)) + { + if ((pInst->m_ID >= OPCODE_BRA) && (pInst->m_ID <= OPCODE_BPE) || + (pInst->m_ID == OPCODE_RCALL)) + size = 3; + + // Convert value (address) to a relative offset from PC (after the opcode) + int diff = (int) value - (pInst->m_Address + size); + + op1 = diff & 0xFF; + op2 = (diff >> 8) & 0xFF; + + // Validate diff range based on opcode + if (pInst->m_ID == OPCODE_BR) + { + if ((diff > 127) || (diff < -128)) + { + // Error - branch out of range + err.Format("Error in line %d(%s): Branch (%d) out of range +127/-128", + pInst->m_Line, (const char *) m_Filenames[m_FileIndex], diff); + m_Errors.Add(err); + valid = 0; + } + type = OPCODE_EQU8; // Change to 8-bit value + } else if ((pInst->m_ID >= OPCODE_SBZ) && (pInst->m_ID <= OPCODE_SBNC)) + { + if ((diff >= 31) || (diff <= -32)) + { + // Error - branch out of range + err.Format("Error in line %d(%s): Branch (%d) out of range +31/-32", + pInst->m_Line, (const char *) m_Filenames[m_FileIndex], diff); + m_Errors.Add(err); + valid = 0; + } + } else if (pInst->m_ID == OPCODE_RCALL) + { + // RCALL opcode + if ((diff >= 32767) || (diff <= -32768)) + { + // Error - branch out of range + err.Format("Error in line %d(%s): RCALL (%d) out of range +32768/-32768", + pInst->m_Line, (const char *) m_Filenames[m_FileIndex], diff); + m_Errors.Add(err); + valid = 0; + } + } else + { + // BRx opcode + if ((diff > 4095) || (diff < -4096)) + { + // Error - branch out of range + err.Format("Error in line %d(%s): Branch (%d) out of range +4095/-4096", + pInst->m_Line, (const char *) m_Filenames[m_FileIndex], diff); + m_Errors.Add(err); + valid = 0; + } + } + } + + // Test for SBcc instruction + if ((pInst->m_ID >= OPCODE_SBZ) && (pInst->m_ID <= OPCODE_SBNC)) + { + // The opcode is actually the upper bits of the op2 byte + op1 = (op1 & 0x3F) | opcode; + opcode = 0x6d; // Assign the actual opcode value + type = OPCODE_EQU8; // Change tpyp so we only write 1 operand byte + } + + // Test for BRx instruction + if ((pInst->m_ID >= OPCODE_BRA) && (pInst->m_ID <= OPCODE_BPE)) + { + // The opcode is actually the upper bits of the operand byte + op2 = (op2 & 0x1f) | opcode; + opcode = 0x49; // Assign the actual opcode value + } + + // Add opcode and operands to array + if (m_Address > MAX_SEG_SIZE) + { + // Error - Segment size too big + err.Format("Error in line %d(%s): Address too big - Max segment size is %d (0x%06X)", + pInst->m_Line, (const char *) m_Filenames[m_FileIndex], MAX_SEG_SIZE, MAX_SEG_SIZE); + m_Errors.Add(err); + valid = 0; + break; + } + + m_ActiveSeg->m_AsmBytes[m_Address++] = opcode; // Add operands to output if ((type == OPCODE_REG_IMM) || (type == OPCODE_EQU8) || - (type == OPCODE_EQU16) || (type == OPCODE_REG_EQU16)) + (type == OPCODE_EQU16) || (type == OPCODE_REG_EQU16) || + (type == OPCODE_EQU24) || (type == OPCODE_PGI) || + (type == OPCODE_PG) || (type == OPCODE_SBCC) || + (type == OPCODE_BRX) || (type == OPCODE_LPP)) { m_ActiveSeg->m_AsmBytes[m_Address++] = op1; } - if ((type == OPCODE_EQU16) || (type == OPCODE_REG_EQU16)) + if ((type == OPCODE_EQU16) || (type == OPCODE_REG_EQU16) || + (type == OPCODE_EQU24) || (type == OPCODE_BRX) || + (type == OPCODE_PGI)) { m_ActiveSeg->m_AsmBytes[m_Address++] = op2; } + + if (type == OPCODE_EQU24) + { + m_ActiveSeg->m_AsmBytes[m_Address++] = op3; + } } - /* ==================================================================== An ORG instruciton has no FBI portion, so process it separately. @@ -3090,12 +3319,6 @@ int VTAssembler::Assemble() { if (Evaluate(pExp->m_Equation, &value, 1)) m_ActiveSeg->m_AsmBytes[m_Address++] = (unsigned char) value; - else - { -// err.Format("Error in line %d(%s): Equation cannot be evaluated", -// pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); -// m_Errors.Add(err); - } } else { @@ -3128,8 +3351,18 @@ int VTAssembler::Assemble() // If expression has an equation, try to evaluate it if (pExp->m_Equation != NULL) { + valid = 1; + rel_mask = 0; + extern_label = 0; if (Evaluate(pExp->m_Equation, &value, 1)) { + // Equation evaluated to a value. Check if it is + // relative to a relocatable segment + if (InvalidRelocation(pExp->m_Equation, rel_mask, relSeg)) + { + valid = 0; + } + // Test operand1 to check if MSFIRST is on or not if (*pInst->m_Operand1 == "1") { @@ -3144,9 +3377,60 @@ int VTAssembler::Assemble() } else { -// err.Format("Error in line %d(%s): Equation cannot be evaluated", -// pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); -// m_Errors.Add(err); + // Equation does not evaluate. Check if it is an extern + if (EquationIsExtern(pExp->m_Equation, size)) + { + // Add a dummy value (0) with relocation + op1 = 0; + op2 = 0; + op3 = 0; + value = 0.0; + extern_label = 1; + } + else + { + err.Format("Error in line %d(%s): Equation cannot be evaluated", + pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Errors.Add(err); + valid = 0; + } + } + + // Check if DW is relative to a relocatable section + if ((rel_mask > 1) && valid) + { + // Add relocation information + pRel = new CRelocation; + pRel->m_Address = m_Address-2; + pRel->m_pSourceRange = m_ActiveAddr; + pRel->m_Segment = relSeg; + pRange = m_ActiveSeg->m_UsedAddr; + if (relSeg != NULL) + pRange = relSeg->m_UsedAddr; + while ((pRange != 0) && (pRel->m_pTargetRange == 0)) + { + if ((pRange->address <= (unsigned int) value) && + (pRange->address + pRange->length > (unsigned int) value)) + { + pRel->m_pTargetRange = pRange; + } + pRange = pRange->pNext; + } + relSeg->m_Reloc.Add(pRel); +// m_ActiveSeg->m_Reloc.Add(pRel); + } + + // Check if operand is extern + else if (extern_label) + { + // Add extern linkage information + pExt = new CExtern; + pExt->m_Address = m_Address - 2; + pExt->m_Name = pExp->m_Equation->m_OperationArray[0].m_Variable; + pExt->m_Segment = m_ActiveSeg->m_Type; + pExt->m_Size = size; + pExt->m_pRange = m_ActiveAddr; + m_Externs.Add(pExt); } } else @@ -3278,18 +3562,17 @@ int VTAssembler::CreateObjFile(const char *filename) CExtern* pExt; MString key, modname; POSITION pos, modPos; - char sectString[] = "\0.strtab\0.symtab\0.aseg\0.text\0.data\0"; - char relString[] = ".relcseg\0.reldseg\0"; - char debugString[] = ".debug\0"; + const char sectString[] = "\0.shstrtab\0.strtab\0.aseg\0.text\0.data\0"; + const char relString[] = ".relcseg\0.reldseg\0"; + const char debugString[] = ".debug\0"; + const char symString[] = ".symtab\0"; + int symtab_off, symtab_idx; const int debugStrSize = 7; - const int strtab_off = 1; - const int symtab_off = 9; - const int aseg_off = 17; - const int cseg_off = 23; - const int dseg_off = 29; -// const int relcseg_off = 35; -// const int reldseg_off = 44; -// const int extern_off = 53; + const int shstrtab_off = 1; + const int strtab_off = 11; + const int aseg_off = 19; + const int cseg_off = 25; + const int dseg_off = 31; int len, strtab_start; int first_aseg_idx, first_cseg_idx, first_dseg_idx; int shidx, type, bind; @@ -3353,16 +3636,18 @@ int VTAssembler::CreateObjFile(const char *filename) /* =================================== - Create STRTAB section for .OBJ file + Create SHSTRTAB section for .OBJ file. This is a section + called ".shstrtab" and is the string table for section header + names. =================================== */ // Create section header for string table - strhdr.sh_name = strtab_off; // Put ".strtab" as first entry in table + strhdr.sh_name = shstrtab_off; // Put ".shstrtab" as first entry in table strhdr.sh_type = SHT_STRTAB; // Make section a string table strhdr.sh_flags = SHF_STRINGS; // This section contains NULL terminated strings strhdr.sh_addr = 0; // No address data for string table strhdr.sh_offset = ftell(fd); - strhdr.sh_link = 0; // Set link data to zero + strhdr.sh_link = 1; // Set link data to point to the .shstrtab section strhdr.sh_info = 0; // Set info byte to zero strhdr.sh_addralign = 0; // Set allignment data to zero strhdr.sh_entsize = 0; // String table does not have equal size entries @@ -3401,6 +3686,11 @@ int VTAssembler::CreateObjFile(const char *filename) } } + // Set offset for Symbol Table string + symtab_off = ftell(fd) - strtab_start; + fwrite(symString, sizeof(symString), 1, fd); + strhdr.sh_size += sizeof(symString); + /* ========================================================= Now create a STRTAB section for EXTERN and PUBLIC symbols @@ -3413,7 +3703,7 @@ int VTAssembler::CreateObjFile(const char *filename) str2hdr.sh_addr = 0; // No address data for string table str2hdr.sh_offset = ftell(fd); str2hdr.sh_size = 1; // Initialize size to zero -- fill in later - str2hdr.sh_link = 0; // Set link data to zero + str2hdr.sh_link = 1; // Set link data to point to the .shstrtab section str2hdr.sh_info = 0; // Set info byte to zero str2hdr.sh_addralign = 0; // Set allignment data to zero str2hdr.sh_entsize = 0; // String table does not have equal size entries @@ -3436,6 +3726,10 @@ int VTAssembler::CreateObjFile(const char *filename) m_ActiveMod->m_Symbols->GetNextAssoc(pos, key, (VTObject *&) pSymbol); if ((pSymbol->m_SymType & SYM_PUBLIC) || (pSymbol->m_SymType & SYM_EXTERN)) { + // Don't add global defines to Object file + if ((pSymbol->m_SymType & 0xFF) == SYM_DEFINE) + continue; + // Add string for this symbol pSymbol->m_StrtabOffset = ftell(fd) - strtab_start; len = strlen(pSymbol->m_Name) + 1; @@ -3445,98 +3739,6 @@ int VTAssembler::CreateObjFile(const char *filename) } } - /* - ========================================== - Create SYMTAB header section to .OBJ file - ========================================== - */ - symhdr.sh_name = symtab_off; // Put ".strtab" as first entry in table - symhdr.sh_type = SHT_SYMTAB; // Make section a symbol table - symhdr.sh_flags = 0; // No flags for this section - symhdr.sh_addr = 0; // No address data for symbol table - symhdr.sh_offset = ftell(fd); - symhdr.sh_size = 0; // Initialize size to zero -- fill in later - symhdr.sh_link = 0; // Set link data to zero - symhdr.sh_info = 0; // Set info byte to zero - symhdr.sh_addralign = 0; // Set allignment data to zero - symhdr.sh_entsize = sizeof(Elf32_Sym);// Symbol table has equal size items - ehdr.e_shnum++; // Increment Section Header count - - // Now add all EXTERN and PUBLIC symbols to string table - idx = 0; - modPos = m_Modules.GetStartPosition(); - while (modPos != NULL) - { - // Get the pointer to this module - m_Modules.GetNextAssoc(modPos, modname, (VTObject *&) m_ActiveMod); - - pos = m_ActiveMod->m_Symbols->GetStartPosition(); - while (pos != 0) - { - // Get next symbol - m_ActiveMod->m_Symbols->GetNextAssoc(pos, key, (VTObject *&) pSymbol); - if ((pSymbol->m_SymType & SYM_PUBLIC) || (pSymbol->m_SymType & SYM_EXTERN)) - { - // Add Elf32_Sym entry for this symbol - sym.st_name = pSymbol->m_StrtabOffset; - sym.st_value = pSymbol->m_Value; - - // Determine symbol Bind and type - if (pSymbol->m_SymType & SYM_PUBLIC) - bind = STB_GLOBAL; - else - bind = STB_EXTERN; - if ((pSymbol->m_SymType & 0xFF) == SYM_LABEL) - type = STT_FUNC; - else - type = STT_OBJECT; - - sym.st_info = ELF32_ST_INFO(bind, type); - sym.st_other = 0; - sym.st_shndx = 2; - - if ((pSymbol->m_SymType & (SYM_8BIT | SYM_16BIT)) == 0) - { - sym.st_size = 0; - pSymbol->m_Off16 = idx; - } - if (pSymbol->m_SymType & SYM_8BIT) - { - sym.st_size = 1; - pSymbol->m_Off8 = idx; - } - if (pSymbol->m_SymType & SYM_16BIT) - { - sym.st_size = 2; - pSymbol->m_Off16 = idx; - } - - fwrite(&sym, sizeof(sym), 1, fd); - idx++; - - // If symbol is EXTERN, find all m_Externs and update index - if (bind == STB_EXTERN) - { - len = m_Externs.GetSize(); - for (c = 0; c < len; c++) - { - pExt = (CExtern *) m_Externs[c]; - pStr = pExt->m_Name; - if (pSymbol->m_Name == pExt->m_Name) - { - if (pExt->m_Size == 1) - pExt->m_SymIdx = (unsigned short) pSymbol->m_Off8; - else - pExt->m_SymIdx = (unsigned short) pSymbol->m_Off16; - } - } - } - } - } - } - // Set the symbol table size in bytes - symhdr.sh_size = idx * sizeof(Elf32_Sym); - /* ========================================== Create section for ASEG code @@ -3554,6 +3756,7 @@ int VTAssembler::CreateObjFile(const char *filename) // Allocate pointers for aseg_section headers aseg_hdr = (Elf32_Shdr *) malloc(aseg_sections * sizeof(Elf32_Shdr)); + // Now add segments to the output object file pRange = m_ActiveSeg->m_UsedAddr; idx = 0; first_aseg_idx = ehdr.e_shnum; @@ -3576,7 +3779,7 @@ int VTAssembler::CreateObjFile(const char *filename) aseg_hdr[idx].sh_offset = ftell(fd); aseg_hdr[idx].sh_size = pRange->length; // Get size from AddrRange aseg_hdr[idx].sh_link = 0; // Set link data to zero - aseg_hdr[idx].sh_info = 0; // Set info byte to zero + aseg_hdr[idx].sh_info = pRange->line;// Set info byte to lineNo where range starts aseg_hdr[idx].sh_addralign = 0; // Set allignment data to zero aseg_hdr[idx].sh_entsize = 0; // Symbol table has equal size items @@ -3652,7 +3855,7 @@ int VTAssembler::CreateObjFile(const char *filename) cseg_hdr[idx].sh_offset = ftell(fd); cseg_hdr[idx].sh_size = pRange->length; // Get size from AddrRange cseg_hdr[idx].sh_link = 0; // Set link data to zero - cseg_hdr[idx].sh_info = 0; // Set info byte to zero + cseg_hdr[idx].sh_info = pRange->line;// Set info byte to lineNo where range starts cseg_hdr[idx].sh_addralign = 0; // Set allignment data to zero cseg_hdr[idx].sh_entsize = 0; // Symbol table has equal size items @@ -3723,7 +3926,7 @@ int VTAssembler::CreateObjFile(const char *filename) dseg_hdr[idx].sh_offset = ftell(fd); dseg_hdr[idx].sh_size = pRange->length; // Get size from AddrRange dseg_hdr[idx].sh_link = 0; // Set link data to zero - dseg_hdr[idx].sh_info = 0; // Set info byte to zero + dseg_hdr[idx].sh_info = pRange->line;// Set info byte to lineNo where range starts dseg_hdr[idx].sh_addralign = 0; // Set allignment data to zero dseg_hdr[idx].sh_entsize = 0; // Symbol table has equal size items @@ -3741,20 +3944,116 @@ int VTAssembler::CreateObjFile(const char *filename) } } + /* + ========================================== + Create SYMTAB header section to .OBJ file + ========================================== + */ + symhdr.sh_name = symtab_off; // Put ".strtab" as first entry in table + symhdr.sh_type = SHT_SYMTAB; // Make section a symbol table + symhdr.sh_flags = 0; // No flags for this section + symhdr.sh_addr = 0; // No address data for symbol table + symhdr.sh_offset = ftell(fd); // Get the offset of this header's data + symhdr.sh_size = 0; // Initialize size to zero -- fill in later + symhdr.sh_link = 0; // Set link data to zero + symhdr.sh_info = 0; // Set info byte to zero + symhdr.sh_addralign = 0; // Set allignment data to zero + symhdr.sh_entsize = sizeof(Elf32_Sym);// Symbol table has equal size items + symtab_idx = ehdr.e_shnum++; // Save and imcrement Section Header count + + // Now add all EXTERN and PUBLIC symbols to string table + idx = 0; + modPos = m_Modules.GetStartPosition(); + while (modPos != NULL) + { + // Get the pointer to this module + m_Modules.GetNextAssoc(modPos, modname, (VTObject *&) m_ActiveMod); + + pos = m_ActiveMod->m_Symbols->GetStartPosition(); + while (pos != 0) + { + // Get next symbol + m_ActiveMod->m_Symbols->GetNextAssoc(pos, key, (VTObject *&) pSymbol); + if ((pSymbol->m_SymType & SYM_PUBLIC) || (pSymbol->m_SymType & SYM_EXTERN)) + { + // Don't add global defines to Object file + if ((pSymbol->m_SymType & 0xFF) == SYM_DEFINE) + continue; + + // Add Elf32_Sym entry for this symbol + sym.st_name = pSymbol->m_StrtabOffset; + sym.st_value = pSymbol->m_Value; + + // Determine symbol Bind and type + if (pSymbol->m_SymType & SYM_PUBLIC) + bind = STB_GLOBAL; + else + bind = STB_EXTERN; + if ((pSymbol->m_SymType & 0xFF) == SYM_LABEL) + type = STT_FUNC; + else + type = STT_OBJECT; + + sym.st_info = ELF32_ST_INFO(bind, type); + sym.st_other = 0; + sym.st_shndx = 0; + if (pSymbol->m_pRange) + sym.st_shndx = pSymbol->m_pRange->shidx; + + if ((pSymbol->m_SymType & (SYM_8BIT | SYM_16BIT)) == 0) + { + sym.st_size = 0; + pSymbol->m_Off16 = idx; + } + if (pSymbol->m_SymType & SYM_8BIT) + { + sym.st_size = 1; + pSymbol->m_Off8 = idx; + } + if (pSymbol->m_SymType & SYM_16BIT) + { + sym.st_size = 2; + pSymbol->m_Off16 = idx; + } + + fwrite(&sym, sizeof(sym), 1, fd); + idx++; + + // If symbol is EXTERN, find all m_Externs and update index + if (bind == STB_EXTERN) + { + len = m_Externs.GetSize(); + for (c = 0; c < len; c++) + { + pExt = (CExtern *) m_Externs[c]; + pStr = pExt->m_Name; + if (pSymbol->m_Name == pExt->m_Name) + { + if (pExt->m_Size == 1) + pExt->m_SymIdx = (unsigned short) pSymbol->m_Off8; + else + pExt->m_SymIdx = (unsigned short) pSymbol->m_Off16; + } + } + } + } + } + } + // Set the symbol table size in bytes + symhdr.sh_size = idx * sizeof(Elf32_Sym); + /* ======================================= Add relocation sections to .OBJ file ======================================= */ - rel_hdrs = (Elf32_Shdr *) malloc((dseg_sections + + rel_hdrs = (Elf32_Shdr *) malloc((aseg_sections + dseg_sections + cseg_sections) * sizeof(Elf32_Shdr)); idx = 0; pos = m_Segments.GetStartPosition(); while (pos != NULL) { m_Segments.GetNextAssoc(pos, key, (VTObject *&) m_ActiveSeg); - if (m_ActiveSeg->m_Type == ASEG) - continue; pRange = m_ActiveSeg->m_UsedAddr; while (pRange != NULL) @@ -3764,50 +4063,53 @@ int VTAssembler::CreateObjFile(const char *filename) rel_hdrs[idx].sh_type = SHT_REL; // Make section a relocation section rel_hdrs[idx].sh_flags = 0; // No flag bits for relocation section rel_hdrs[idx].sh_addr = 0; // No address specifier for relocaton section - rel_hdrs[idx].sh_offset = ftell(fd);// Fill in offset later + rel_hdrs[idx].sh_offset = ftell(fd);// Set the offset of this header's data rel_hdrs[idx].sh_size = 0; // Fill in size later - rel_hdrs[idx].sh_link = 3; // Point to symtab section + rel_hdrs[idx].sh_link = symtab_idx; // Point to symtab section rel_hdrs[idx].sh_info = pRange->shidx; rel_hdrs[idx].sh_addralign = 0; // No alignment requirements rel_hdrs[idx].sh_entsize = sizeof(Elf32_Rel); - // Generage Elf32_Rel object for each relocation relative to this section - len = m_ActiveSeg->m_Reloc.GetSize(); - - // Loop through all relocation items in seg - for (c = 0; c < len; c++) + // Generate Elf32_Rel object for each relocation relative to this section + if (m_ActiveSeg->m_Type != ASEG) { - // Check if this relocation relative to current section - pReloc = (CRelocation *) m_ActiveSeg->m_Reloc[c]; - if (pReloc->m_pTargetRange == pRange) - { - if (pReloc->m_pSourceRange->shidx >= first_dseg_idx) - { - shidx = pReloc->m_pSourceRange->shidx - first_dseg_idx; - rel.r_offset = pReloc->m_Address - dseg_hdr[shidx].sh_addr + - dseg_hdr[shidx].sh_offset; - rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); - } - else if (pReloc->m_pSourceRange->shidx >= first_cseg_idx) - { - shidx = pReloc->m_pSourceRange->shidx - first_cseg_idx; - rel.r_offset = pReloc->m_Address - cseg_hdr[shidx].sh_addr + - cseg_hdr[shidx].sh_offset; - rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); - } - else - { - shidx = pReloc->m_pSourceRange->shidx - first_aseg_idx; - rel.r_offset = pReloc->m_Address - aseg_hdr[shidx].sh_addr + - aseg_hdr[shidx].sh_offset; - rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); - } + len = m_ActiveSeg->m_Reloc.GetSize(); - // Update size of header - rel_hdrs[idx].sh_size += sizeof(Elf32_Rel); + // Loop through all relocation items in seg + for (c = 0; c < len; c++) + { + // Check if this relocation relative to current section + pReloc = (CRelocation *) m_ActiveSeg->m_Reloc[c]; + if (pReloc->m_pTargetRange == pRange) + { + if (pReloc->m_pSourceRange->shidx >= first_dseg_idx) + { + shidx = pReloc->m_pSourceRange->shidx - first_dseg_idx; + rel.r_offset = pReloc->m_Address - dseg_hdr[shidx].sh_addr + + dseg_hdr[shidx].sh_offset; + rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); + } + else if (pReloc->m_pSourceRange->shidx >= first_cseg_idx) + { + shidx = pReloc->m_pSourceRange->shidx - first_cseg_idx; + rel.r_offset = pReloc->m_Address - cseg_hdr[shidx].sh_addr + + cseg_hdr[shidx].sh_offset; + rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); + } + else + { + shidx = pReloc->m_pSourceRange->shidx - first_aseg_idx; + rel.r_offset = pReloc->m_Address - aseg_hdr[shidx].sh_addr + + aseg_hdr[shidx].sh_offset; + rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); + } - // Write entry to file - fwrite(&rel, sizeof(Elf32_Rel), 1, fd); + // Update size of header + rel_hdrs[idx].sh_size += sizeof(Elf32_Rel); + + // Write entry to file + fwrite(&rel, sizeof(Elf32_Rel), 1, fd); + } } } @@ -3822,7 +4124,7 @@ int VTAssembler::CreateObjFile(const char *filename) if (pExt->m_pRange == pRange) { // Set address for this relocation - rel.r_offset = pExt->m_Address; + rel.r_offset = pExt->m_Address - pExt->m_pRange->address; rel.r_info = ELF32_R_INFO(pExt->m_SymIdx, SR_EXTERN); // Update size of header @@ -3890,9 +4192,6 @@ int VTAssembler::CreateObjFile(const char *filename) // Write String Table 2 header fwrite(&str2hdr, sizeof(str2hdr), 1, fd); - // Write Symbol Table header - fwrite(&symhdr, sizeof(symhdr), 1, fd); - // Write ASEG headers for (c = 0; c < aseg_sections; c++) { @@ -3914,8 +4213,11 @@ int VTAssembler::CreateObjFile(const char *filename) fwrite(&dseg_hdr[c], sizeof(Elf32_Shdr), 1, fd); } + // Write Symbol Table header + fwrite(&symhdr, sizeof(symhdr), 1, fd); + // Write Relocation section headers - for (c = 0; c < cseg_sections + dseg_sections; c++) + for (c = 0; c < aseg_sections + cseg_sections + dseg_sections; c++) { // Skip writing empty headers if (rel_hdrs[c].sh_size == 0) @@ -3969,8 +4271,24 @@ int VTAssembler::InvalidRelocation(CRpnEquation *pEq, char &rel_mask, // Check if operation type is a variable if (pEq->m_OperationArray[c].m_Operation == RPN_VARIABLE) { + MString temp = pEq->m_OperationArray[c].m_Variable; + if (temp.GetLength() > 1) + { + // Check if label is local to the last label only + if (temp[0] == '&') + { + // Prepend the last label to make this a local symbol + temp = m_LastLabel + (char *) "%%" + pEq->m_OperationArray[c].m_Variable; + } + else if (temp[0] == m_LocalModuleChar) + { + // Prepend the last label to make this a local symbol + temp = m_ActiveMod->m_Name + (char *) "%%" + pEq->m_OperationArray[c].m_Variable; + } + } + // Find the symbol - if (LookupSymbol(pEq->m_OperationArray[c].m_Variable, pSym)) + if (LookupSymbol(temp, pSym)) { if ((pSym->m_SymType & 0x00FF) == SYM_LABEL) { @@ -4022,7 +4340,7 @@ int VTAssembler::EquationIsExtern(CRpnEquation* pEq, int size) if (LookupSymbol(pEq->m_OperationArray[0].m_Variable, pSym)) { // Check if variable type s EXTERN - if (pSym->m_SymType == SYM_EXTERN) + if ((pSym->m_SymType & 0xFF) == SYM_EXTERN) { if (size == 1) pSym->m_SymType |= SYM_8BIT; @@ -4103,7 +4421,7 @@ void VTAssembler::ParseExternalDefines(void) /* ============================================================================ This function is called to parse an input file. If there are no errors -during parsing, the routine calls the routines to assemlbe and generate +during parsing, the routine calls the routines to assemble and generate output files for .obj, .lst, .hex, etc. ============================================================================ */ @@ -4172,6 +4490,14 @@ void VTAssembler::Parse(MString filename) // Generate a hex file if requested outfile = temp + (char *) ".hex"; CreateHex(outfile); + + // Generate a .CO file if needed + outfile = temp + (char *) ".co"; + CreateCO(outfile); + + // Generate a verilog file if requested + outfile = temp + (char *) ".dat"; + CreateVerilog(outfile); } } } @@ -4394,6 +4720,7 @@ void VTAssembler::CreateList(MString& filename, MString& asmFilename) // Get the pInst for this module if (pSeg->m_Index < pSeg->m_Count) { + pInst = (CInstruction*) (*pSeg->m_Instructions)[0]; while ((pInst != NULL) && (pInst->m_ID == INST_LABEL)) { if (++pSeg->m_Index < pSeg->m_Count) @@ -4459,7 +4786,7 @@ void VTAssembler::CreateHex(MString& filename) len = 0; // Loop through bytes in RAM area & find non-zeros - for (x = 0, ptr = (char *) pSeg->m_AsmBytes; x < 65536; x++, ptr++) + for (x = 0, ptr = (char *) pSeg->m_AsmBytes; x < MAX_SEG_SIZE; x++, ptr++) { if (*ptr != 0) { @@ -4484,6 +4811,151 @@ void VTAssembler::CreateHex(MString& filename) fclose(fd); } +/* +============================================================================ +This function creates a Verilog $readmemh output file of the assembled file +============================================================================ +*/ +void VTAssembler::CreateVerilog(MString& filename) +{ + int start, len, end; + int x; + char* ptr; + MString outfile; + FILE* fd; + CSegment* pSeg; + int zeroCount = 0; + + // Test if HEX output requested + if (!((m_AsmOptions.Find((char *) "-v") != -1) || (m_Verilog))) + { + // No ASEG Hex output requested...return + return; + } + + // Get a pointer to the .aseg segment + m_Segments.Lookup(".aseg", (VTObject *&) pSeg); + + if (m_ProjectType == VT_PROJ_TYPE_ROM) + { + start = 0; + len = 32768; + } + else + { + // Calculate start and length of non-zero bytes in .aseg + start = -1; + end = 0; + len = 0; + + // Loop through bytes in RAM area & find non-zeros + for (x = 0, ptr = (char *) pSeg->m_AsmBytes; x < MAX_SEG_SIZE; x++, ptr++) + { + if (*ptr != 0) + { + if (start == -1) + start = x; + end = x; + } + } + + // Calculate the length of the data + if (start >= 0) + len = end - start + 1; + } + + // Open the output listing file + if ((fd = fopen(filename, "wb+")) == NULL) + return; + + // Save the Intel Hex file + fprintf(fd, "@%d\n", start); + for (x = start; x <= start+len; x++) + { + if (pSeg->m_AsmBytes[x] == 0) + { + if (++zeroCount < 10) + fprintf(fd, "%02x\n", pSeg->m_AsmBytes[x]); + } + else + { + if (zeroCount >= 10) + fprintf(fd, "@%X\n", x); + zeroCount = 0; + fprintf(fd, "%02x\n", pSeg->m_AsmBytes[x]); + } + } + + fclose(fd); +} + +/* +============================================================================ +This function creates a Model T .CO format file +============================================================================ +*/ +void VTAssembler::CreateCO(MString& filename) +{ + unsigned short start, len, end, entry; + int x; + char* ptr; + MString outfile; + FILE* fd; + CSegment* pSeg; + + // Test if HEX output requested + if (m_ProjectType != VT_PROJ_TYPE_CO) + { + // Not a .CO project type ... return + return; + } + + // Get a pointer to the .aseg segment + m_Segments.Lookup(".aseg", (VTObject *&) pSeg); + + // Calculate start and length of non-zero bytes in .aseg + start = 0; + end = 0; + len = 0; + + // Loop through bytes in RAM area & find non-zeros + for (x = 0, ptr = (char *) pSeg->m_AsmBytes; x < MAX_SEG_SIZE; x++, ptr++) + { + if (*ptr != 0) + { + if (start == 0) + start = x; + end = x; + } + } + + // Calculate the length of the data + if (start > 0) + len = end - start + 1; + + // Test for definition of the entry point for the .CO file + // If none exists, use the address of the first code found. + entry = start; + + // Open the output listing file + if ((fd = fopen(filename, "wb+")) == NULL) + return; + + // First write the .CO 6-byte header to the file + // The format of the .CO header is: + // 0-1: Start address for load + // 2-3: Length of CO (not including header) + // 4-5: Entry address + fwrite(&start, sizeof(short), 1, fd); + fwrite(&len, sizeof(short), 1, fd); + fwrite(&entry, sizeof(short), 1, fd); + + // Now write the data in binary forma`t + fwrite(&pSeg->m_AsmBytes[start], 1, len, fd); + + fclose(fd); +} + /* ===================================================================== Implement the CModule class. This class is used to keep track of @@ -4643,6 +5115,11 @@ CSegment::CSegment(const char *name, int type, CModule* initialMod) m_Instructions = new VTObArray; m_Address = 0; m_UsedAddr = new AddrRange; + m_UsedAddr->address = 0; + m_UsedAddr->length = 0; + m_UsedAddr->shidx = 0; + m_UsedAddr->pNext = NULL; + m_Index = m_Count = 0; for (x = 0; x < sizeof(m_AsmBytes); x++) m_AsmBytes[x] = 0; diff --git a/src/assemble.h b/src/assemble.h index d38472e..bd6b5ad 100644 --- a/src/assemble.h +++ b/src/assemble.h @@ -98,29 +98,53 @@ #define OPCODE_HLT 89 #define OPCODE_RSTV 90 -#define INST_ORG 91 -#define INST_DS 92 -#define INST_DB 93 -#define INST_DW 94 -#define INST_STKLN 95 -#define INST_END 96 -#define INST_PUBLIC 97 -#define INST_EXTERN 98 -#define INST_IF 99 -#define INST_ELSE 100 -#define INST_ENDIF 101 -#define INST_LINK 102 -#define INST_MACLIB 103 -#define INST_PAGE 104 -#define INST_SYM 105 -#define INST_LABEL 106 -#define INST_FILL 107 -#define INST_ENDIAN 108 -#define INST_ELIF 109 -#define INST_MODULE 110 -#define INST_DEFINE 111 -#define INST_UNDEFINE 112 -#define INST_MACRO 113 +// Extended OPCODES +#define OPCODE_LRET 91 +#define OPCODE_LCALL 92 +#define OPCODE_LJMP 93 +#define OPCODE_LPUSH 94 +#define OPCODE_LPOP 95 +#define OPCODE_BR 96 +#define OPCODE_BRA 97 +#define OPCODE_BZ 98 +#define OPCODE_BNZ 99 +#define OPCODE_BC 100 +#define OPCODE_BNC 101 +#define OPCODE_BM 102 +#define OPCODE_BP 103 +#define OPCODE_BPE 104 +#define OPCODE_SBZ 105 +#define OPCODE_SBNZ 106 +#define OPCODE_SBC 107 +#define OPCODE_SBNC 108 +#define OPCODE_RCALL 109 +#define OPCODE_SPI 110 +#define OPCODE_SPG 111 +#define OPCODE_RPG 112 + +#define INST_ORG 113 +#define INST_DS 114 +#define INST_DB 115 +#define INST_DW 116 +#define INST_STKLN 117 +#define INST_END 118 +#define INST_PUBLIC 119 +#define INST_EXTERN 120 +#define INST_IF 121 +#define INST_ELSE 122 +#define INST_ENDIF 123 +#define INST_LINK 124 +#define INST_MACLIB 125 +#define INST_PAGE 126 +#define INST_SYM 127 +#define INST_LABEL 128 +#define INST_FILL 129 +#define INST_ENDIAN 130 +#define INST_ELIF 131 +#define INST_MODULE 132 +#define INST_DEFINE 133 +#define INST_UNDEFINE 134 +#define INST_MACRO 135 #define SYM_LABEL 1 #define SYM_EQUATE 2 @@ -144,6 +168,12 @@ #define OPCODE_EQU8 5 #define OPCODE_EQU16 6 #define OPCODE_REG_EQU16 7 +#define OPCODE_PG 8 +#define OPCODE_PGI 9 +#define OPCODE_SBCC 10 +#define OPCODE_BRX 11 +#define OPCODE_EQU24 12 +#define OPCODE_LPP 13 #define PAGE 1 #define INPAGE 2 @@ -165,6 +195,8 @@ #define CSEG 1 #define DSEG 2 +#define MAX_SEG_SIZE (4*1024*1024) + #define VT_ISDIGIT(x) (((x) >= '0') && ((x) <= '9')) #ifdef WIN32 @@ -175,10 +207,11 @@ // Support classes for VTAssembler objects... typedef struct sAddrRange { - unsigned short address; + unsigned int address; unsigned short length; unsigned short shidx; struct sAddrRange* pNext; + unsigned int line; // Line No in file where this range starts } AddrRange; class CInstruction : public VTObject @@ -193,7 +226,7 @@ class CInstruction : public VTObject // Attributes unsigned char m_ID; unsigned char m_FileIndex; - unsigned short m_Address; + unsigned int m_Address; long m_Line; int m_Bytes; MString* m_Operand1; @@ -229,9 +262,9 @@ class CSegment : public VTObject int m_Count; // Instruction count for listing int m_sh_offset; // Offset in .obj file of segment name VTObArray* m_Instructions; // Array of Instructions for each segment - unsigned short m_Address; // Address counter for each segment + unsigned int m_Address; // Address counter for each segment VTObArray m_Reloc; - unsigned char m_AsmBytes[65536]; + unsigned char m_AsmBytes[MAX_SEG_SIZE]; AddrRange* m_UsedAddr; // List of used address ranges AddrRange* m_ActiveAddr; // Pointer to active address range }; @@ -265,7 +298,7 @@ class CExtern : public VTObject CExtern() { m_Address = 0; m_pRange = 0; }; MString m_Name; - unsigned short m_Address; + unsigned int m_Address; unsigned short m_Segment; unsigned short m_SymIdx; AddrRange* m_pRange; @@ -290,7 +323,7 @@ class CRelocation : public VTObject public: CRelocation() { m_Address = 0; m_Segment = 0; m_pSourceRange = 0; m_pTargetRange = 0; }; - unsigned short m_Address; + unsigned int m_Address; CSegment* m_Segment; AddrRange* m_pSourceRange; AddrRange* m_pTargetRange; @@ -353,6 +386,9 @@ class VTAssembler : public VTObject // Define Pragma functions void pragma_list(); void pragma_hex(); + void pragma_verilog(); + void pragma_extended(); + void pragma_entry(const char *pName); // Define directive functions void directive_set(const char *name); @@ -391,9 +427,11 @@ class VTAssembler : public VTObject void opcode_arg_imm(int opcode, char c); void opcode_arg_2reg(int opcode); void opcode_arg_1reg_equ8(int opcode); + void opcode_arg_1reg_2byte(int opcode); void opcode_arg_1reg_equ16(int opcode); void opcode_arg_equ8(int opcode); void opcode_arg_equ16(int opcode); + void opcode_arg_equ24(int opcode); // Attributes // MString m_Filename; // Filename that design was parsed from @@ -417,9 +455,10 @@ class VTAssembler : public VTObject VTObArray m_Defines; // Array of preprocessor defines VTObArray m_SegLines; // Array of segment line objects - unsigned short m_Address; + unsigned int m_Address; MStringArray m_Filenames; // Array of filenames parsed during assembly MString m_LastLabel; // Save value of last label parsed + MString m_EntryLabel; // Label of program entry location CSymbol* m_LastLabelSym; // Pointer to CSymbol object for last label int m_LastLabelAdded; char m_LocalModuleChar; // Module local label starting character @@ -431,6 +470,8 @@ class VTAssembler : public VTObject VTMapStringToOb m_UndefSymbols; int m_List; // Create a list file? int m_Hex; // Create a HEX file? + int m_Verilog; // Create a Verilog $readmem file + int m_Extended; // Indicated extended instructions valid int m_DebugInfo; // Include debug info in .obj? int m_MsbFirst; // Output WORDS MSB first instead of LSB MString m_IncludeName[32]; @@ -462,6 +503,8 @@ class VTAssembler : public VTObject int EquationIsExtern(CRpnEquation* pEq, int size); void MakeBinary(int val, int length, MString& binary); void CreateHex(MString& filename); + void CreateCO(MString& filename); + void CreateVerilog(MString& filename); void CreateList(MString& filename, MString& asmFilename); void CalcIncludeDirs(); void ParseExternalDefines(void); diff --git a/src/do_instruct.h b/src/do_instruct.h index 9cdd754..90c72f4 100644 --- a/src/do_instruct.h +++ b/src/do_instruct.h @@ -65,7 +65,7 @@ j=1; \ else \ j=0; \ - setflags(r,-1,-1,j,-1,-2, (r==0x80) || (r==0), -2); \ + setflags(r,-1,-1,j,-1,-2, (r==0x80) || (r==0)); \ cycle_delta+=(4); \ } @@ -76,7 +76,7 @@ j=1; \ else \ j=0; \ - setflags(r,-1,-1,j,-1,-2, (r==0xFF) || (r==0x7F), -2); \ + setflags(r,-1,-1,j,-1,-2, (r==0xFF) || (r==0x7F)); \ cycle_delta+=(4); \ } @@ -100,7 +100,7 @@ i=0; \ if (j) \ j = (HL&0x8000) != (rp&0x8000); \ - setflags(0,-2,-2,-2,-2,i,j,-2 ); \ + setflags(0,-2,-2,-2,-2,i,j); \ cycle_delta+=(10); \ } @@ -148,7 +148,7 @@ i=0; \ if (v) \ v = (A&0x80) != (r&0x80); \ - setflags(A,-1,-1,j,-1,i,v,-2); \ + setflags(A,-1,-1,j,-1,i,v); \ cycle_delta+=(4); \ } @@ -166,7 +166,7 @@ i=0; \ if (v) \ v = (A&0x80) != (r&0x80); \ - setflags(A,-1,-1,j,-1,i,v,-2); \ + setflags(A,-1,-1,j,-1,i,v); \ cycle_delta+=(4); \ } @@ -183,7 +183,7 @@ i=0; \ if (v) \ v = (A&0x80) != (r&0x80); \ - setflags(A,-1,-1,j,-1,i,v,-2); \ + setflags(A,-1,-1,j,-1,i,v); \ cycle_delta+=(4); \ } @@ -201,28 +201,28 @@ i = 0; \ if (v) \ v = (A&0x80) != (r&0x80); \ - setflags(A,-1,-1,j,-1,i,v,-2); \ + setflags(A,-1,-1,j,-1,i,v); \ cycle_delta+=(4); \ } #define ANA(r,rs) { \ INCPC; \ A&=r; \ - setflags(A,-1,-1,1,-1,0,-2,-2); \ + setflags(A,-1,-1,1,-1,0,-2); \ cycle_delta+=(4); \ } #define XRA(r,rs) { \ INCPC; \ A^=r; \ - setflags(A,-1,-1,0,-1,0,-2,-2); \ + setflags(A,-1,-1,0,-1,0,-2); \ cycle_delta+=(4); \ } #define ORA(r,rs) { \ INCPC; \ A|=r; \ - setflags(A,-1,-1,0,-1,0,-2,-2); \ + setflags(A,-1,-1,0,-1,0,-2); \ cycle_delta+=(4); \ } @@ -239,7 +239,7 @@ v = (A&0x80) != (r&0x80); \ else \ v = 0; \ - setflags(A-r,-1,-1,j,-1,i,v,-2); \ + setflags(A-r,-1,-1,j,-1,i,v); \ cycle_delta+=(4); \ } @@ -357,7 +357,7 @@ ins = INS; INCPC; i=A>>7; A=(A<<1)|i; - setflags(A,-2,-2,-2,-2,i,-2,-2); + setflags(A,-2,-2,-2,-2,i,-2); cycle_delta+=(4); /* return; */ } @@ -373,11 +373,13 @@ ins = INS; i = HL < BC;// - (CF?1:0); j = HL - BC;// - (CF?1:0); v = (HL&0x8000) == (BC&0x8000); + if (BC > HL) + F |= XF_BIT; L=j&0xFF; H=(j >> 8) & 0xFF; if (v) v = (HL&0x8000) != (BC&0x8000); - setflags(H | L,H&0x80,-1,-2,-2,i,v,-2); + setflags(H | L,H&0x80,-1,-2,H^L,i,v); cycle_delta+=(10); /* return; */ } @@ -419,7 +421,7 @@ ins = INS; i=A<<7&0x80; A=(A>>1)|i; i>>=7; - setflags(A,-2,-2,-2,-2,i,-2,-2); + setflags(A,-2,-2,-2,-2,i,-2); cycle_delta+=(4); /* return; */ } @@ -438,7 +440,7 @@ ins = INS; j = HL >> 1; L = j & 0xFF; H = (H & 0x80) | ((j >> 8) & 0xFF); - setflags(0,-2,-2,-2,-2,i,-2,-2); + setflags(0,-2,-2,-2,-2,i,-2); cycle_delta+=(7); /* return; */ } @@ -480,7 +482,7 @@ ins = INS; i=A>>7; A<<=1; A|=(CF?1:0); - setflags(A,-2,-2,-2,-2,i,-2,-2); + setflags(A,-2,-2,-2,-2,i,-2); cycle_delta+=(4); /* return; */ } @@ -497,7 +499,7 @@ ins = INS; j = DE << 1; E = (j & 0xFF) | (CF ? 1 : 0); D = (j >> 8) & 0xFF; - setflags(0,-2,-2,-2,-2,i,-2,-2); + setflags(0,-2,-2,-2,-2,i,-2); cycle_delta+=(10); /* return; */ } @@ -539,7 +541,7 @@ ins = INS; i=(A&0x01); A>>=1; A|=CF?0x80:0; - setflags(A,-2,-2,-2,-2,i,-2,-2); + setflags(A,-2,-2,-2,-2,i,-2); cycle_delta+=(4); /* return; */ } @@ -615,7 +617,7 @@ ins = INS; if((((A>>4)+j) > 9) || CF) i|=0x60;/* Add 6 to upper nibble */ A+=i; - setflags(A,-1,-1,j,-1,i>>4?1:0,-2,-2); + setflags(A,-1,-1,j,-1,i>>4?1:0,-2); cycle_delta+=(4); /* return; */ /* Huh? */ } @@ -727,7 +729,7 @@ ins = INS; j=1; else j=0; - setflags(M,-1,-1,j,-1,-2, (M==0x80) || (M==0), -2); + setflags(M,-1,-1,j,-1,-2, (M==0x80) || (M==0)); cycle_delta+=(10); } else { @@ -738,7 +740,7 @@ ins = INS; j=1; else j=0; - setflags(M,-1,-1,j,-1,-2, (M==0xFF) || (M==0x7F), -2); + setflags(M,-1,-1,j,-1,-2, (M==0xFF) || (M==0x7F)); cycle_delta+=(10); } } @@ -753,7 +755,7 @@ ins = INS; else { /* case 0x37: STC */ INCPC; - setflags(0,-2,-2,-2,-2,1,-2,-2); + setflags(0,-2,-2,-2,-2,1,-2); cycle_delta+=(4); /* return; */ } @@ -812,7 +814,7 @@ ins = INS; else { /* case 0x3F: CMC */ INCPC; - setflags(A,-2,-2,-2,-2,CF?0:1,-2,-2); + setflags(A,-2,-2,-2,-2,CF?0:1,-2); cycle_delta+=(4); /* return; */ } @@ -1663,7 +1665,7 @@ ins = INS; i=0; if (v) v = (A&0x80) != (INS&0x80); - setflags(A,-1,-1,j,-1,i,v,-2); + setflags(A,-1,-1,j,-1,i,v); cycle_delta+=(7); INCPC; /* return; */ @@ -1727,7 +1729,7 @@ ins = INS; i=0; if (v) v = (A&0x80) != (INS&0x80); - setflags(A,-1,-1,j,-1,i,v,-2); + setflags(A,-1,-1,j,-1,i,v); cycle_delta+=(7); INCPC; /* return; */ @@ -1794,7 +1796,7 @@ ins = INS; i = 0; if (v) v = (A&0x80) != (INS&0x80); - setflags(A,-1,-1,j,-1,i,v,-2); + setflags(A,-1,-1,j,-1,i,v); cycle_delta+=(7); INCPC; /* return; */ @@ -1864,7 +1866,7 @@ ins = INS; i = 0; if (v) v = (A&0x80) != (INS&0x80); - setflags(A,-1,-1,j,-1,i,v,-2); + setflags(A,-1,-1,j,-1,i,v); INCPC; cycle_delta+=(7); /* return; */ @@ -1930,7 +1932,7 @@ ins = INS; INCPC; A=A&INS; INCPC; - setflags(A,-1,-1,1,-1,0,-2,-2); + setflags(A,-1,-1,1,-1,0,-2); cycle_delta+=(7); /* return; */ } @@ -2000,7 +2002,7 @@ ins = INS; INCPC; A=A^INS; INCPC; - setflags(A,-1,-1,0,-1,0,-2,-2); + setflags(A,-1,-1,0,-1,0,-2); cycle_delta+=(4); /* return; */ } @@ -2056,7 +2058,7 @@ ins = INS; INCPC; A=A|INS; INCPC; - setflags(A,-1,-1,0,-1,0,-2,-2); + setflags(A,-1,-1,0,-1,0,-2); cycle_delta+=(7); /* return; */ } @@ -2124,7 +2126,7 @@ ins = INS; v = (A&0x80) != (INS&0x80); else v = 0; - setflags(A-INS,-1,-1,j,-1,i,v,-2); + setflags(A-INS,-1,-1,j,-1,i,v); INCPC; cycle_delta+=(7); /* return; */ diff --git a/src/doins.c b/src/doins.c index 4a1de92..2086960 100644 --- a/src/doins.c +++ b/src/doins.c @@ -55,7 +55,7 @@ static char paritybits[256]={ }; #if defined(WIN32) -void setflags(int regval, int sign, int zero, int auxcarry, int parity, int carry, int ov, int ts) +void setflags(int regval, int sign, int zero, int auxcarry, int parity, int carry, int ov) #else __inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry, char ov, char ts) #endif @@ -82,7 +82,7 @@ __inline void setflags(unsigned char regval, char sign, char zero, char auxcarry if (parity != -2) { if(parity>=0) - F=(F&~PF_BIT)|(parity?PF_BIT:0); + F=(F&~PF_BIT)|paritybits[parity & 0xFF]; else /* Table Lookup */ F=(F&~PF_BIT)|paritybits[regval & 0xFF]; @@ -93,8 +93,6 @@ __inline void setflags(unsigned char regval, char sign, char zero, char auxcarry if (ov >= 0) F=(F&~OV_BIT)|(ov?OV_BIT:0); - if (ts >= 0) - F=(F&~TS_BIT)|(ts?TS_BIT:0); } /* inline void do_instruct(void) diff --git a/src/doins.h b/src/doins.h index 1fbfd99..c1f7a2a 100644 --- a/src/doins.h +++ b/src/doins.h @@ -32,7 +32,7 @@ #define _DOINS_H_ #if defined(WIN32) -void setflags(int regval, int sign, int zero, int auxcarry, int parity, int carry, int ov, int ts); +void setflags(int regval, int sign, int zero, int auxcarry, int parity, int carry, int ov); #else __inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry, char ov, char ts); #endif diff --git a/src/elf.h b/src/elf.h index 865d961..952a23f 100644 --- a/src/elf.h +++ b/src/elf.h @@ -80,8 +80,10 @@ typedef struct { #define EM_MIPS 8 // MIPS RS3000 #define EM_S370 9 // IBM System/370 Processor #define EM_MIPS_RS4_BE 10 // MIPS RS4000 -// Codes 11-14 reserved for future use, so we use #12 + +// Codes 11-14 reserved for future use, so we use #12 for 8085 #define EM_8085 12 // Model T - 8085 + #define EM_PARISC 15 // HP PA-RISC #define EM_VPP500 17 // Fujitsu VPP500 #define EM_SPARC32PLUS 18 // Enhanced instruction set SPARC @@ -134,7 +136,6 @@ typedef struct { #define EM_HAUNY 81 // Harvard University machine-independent object files #define EM_PRISM 82 // SiTera Prism - // Define version #define EV_NONE 0 // Invalid version #define EV_CURRENT 1 // Current version @@ -273,10 +274,11 @@ typedef struct { #define ELF32_R_TYPE(i) ((Elf32_Char)(i)) #define ELF32_R_INFO(s,t) (((s)<<8)+(Elf32_Char)(t)) -#define SR_UNDEF 0 -#define SR_ADDR_XLATE 1 -#define SR_EXTERN 2 -#define SR_PUBLIC 3 +#define SR_UNDEF 0 +#define SR_ADDR_XLATE 1 +#define SR_EXTERN 2 +#define SR_PUBLIC 3 +#define SR_ADDR_PROCESSED 0x81 // Define program header information typedef struct { diff --git a/src/highlight.cpp b/src/highlight.cpp index c4fe680..0fcfe28 100644 --- a/src/highlight.cpp +++ b/src/highlight.cpp @@ -95,6 +95,15 @@ const char *asm_code_keywords[] = { "ani", "arhl", "ashr", + "bc", + "bm", + "bnc", + "bnz", + "bp", + "bpe", + "br", + "bra", + "bz", "call", "cc", "cm", @@ -140,15 +149,21 @@ const char *asm_code_keywords[] = { "jx", "jx5", "jz", + "lcall", "lda", "ldax", "ldeh", "ldes", "ldhi", + "ldsi", "lhld", "lhlde", "lhli", "lhlx", + "ljmp", + "lpop", + "lpush", + "lret", "lxi", "mov", "mvi", @@ -162,6 +177,7 @@ const char *asm_code_keywords[] = { "ral", "rar", "rc", + "rcall", "rdel", "ret", "rim", @@ -172,6 +188,7 @@ const char *asm_code_keywords[] = { "rnz", "rp", "rpe", + "rpg", "rpo", "rrc", "rrhl", @@ -179,14 +196,20 @@ const char *asm_code_keywords[] = { "rstv", "rz", "sbb", + "sbc", // Short Branch Carry "sbi", + "sbnc", // Short Branch No Carry + "sbnz", // Short Branch No zero + "sbz", // Short Branch if Zero "shld", "shlde", "shli", "shlr", "shlx", "sim", + "spg", "sphl", + "spi", "sta", "stax", "stc", diff --git a/src/ide.cpp b/src/ide.cpp index 8c0fabb..0115276 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -271,6 +271,10 @@ void close_ide_cb(Fl_Widget* w, void*) virtualt_prefs.set("IdeY", gpIde->y()); virtualt_prefs.set("IdeW", gpIde->w()); virtualt_prefs.set("IdeH", gpIde->h()); + int ideTabHeight = gpIde->h() - gpIde->SpliterHeight(); + int ideTreeWidth = gpIde->SpliterWidth(); + virtualt_prefs.set("IdeTabheight", ideTabHeight); + virtualt_prefs.set("IdeTreeWidth", ideTreeWidth); } gpIde->SavePrefs(); @@ -379,8 +383,11 @@ Callback for opening recent projects char *slash; slash = strrchr(path, '/'); *slash = '\0'; - gpIde->OpenProject(newfile); - add_recent_project_to_menu(newfile); + if (gpIde->CloseAllFiles()) + { + gpIde->OpenProject(newfile); + add_recent_project_to_menu(newfile); + } } } } @@ -1169,6 +1176,52 @@ void projtree_callback( Fl_Widget* w, void* ) } } +void ide_error_report(int lineNo, char* pFilename, void* pOpaque) +{ + VT_Ide* pIde = (VT_Ide *) pOpaque; + + /* Report the error callback to the IDE so it can display the file / line */ + pIde->ErrorReport(lineNo, pFilename); +} + +/* +============================================================================== +Display the errored file, position to the errored line, and highlight it. +============================================================================== +*/ +void VT_Ide::ErrorReport(int lineNo, char* pFilename) +{ + MString path = pFilename; + //Fl_Multi_Edit_Window* mw; + My_Text_Editor* mte; + + /* Convert filename to an absolute path */ + MString absPath = MakePathAbsolute(path, m_ActivePrj->m_RootPath); + + /* Open the file if it isn't already */ + OpenFile(absPath); + + /* Position the file to the proper line */ + mte = (My_Text_Editor*) m_EditTabs->value(); + mte->insert_position(mte->get_line_pos(lineNo)); + + /* Ensure the line is on the display */ + int topLine = mte->top_line(); + int numLines = mte->num_visible_lines(); + if ((lineNo - topLine < 5) || (topLine + numLines - lineNo < 5)) + { + topLine = lineNo - (numLines >> 1); + if (topLine < 1) + topLine = 1; + if (topLine + numLines > mte->count_lines(0, -1, true)) + topLine = mte->count_lines(0, -1, true) - numLines+2; + + mte->scroll(topLine, 0); + } + + /* Update the status bar */ + mte->UpdateStatusBar(); +} /* ============================================================================== @@ -1178,6 +1231,8 @@ VT_Ide constructor. This routine creates a new VT_Ide window VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) : Fl_Window(x, y, w, h, title) { + int ideTreeWidth; + // Parent window has no box, only child regions box(FL_NO_BOX); callback(close_ide_cb); @@ -1188,25 +1243,28 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) // Create a menu for the new window. Fl_Menu_Bar *m = gMenuBar = new Fl_Menu_Bar(0, 0, w, MENU_HEIGHT-2); m->menu(gIde_menuitems); + m->color(fl_rgb_color(240,239,228)); // Create a tiled window to support Project, Edit, and debug regions - Fl_Tile* tile = new Fl_Tile(0,MENU_HEIGHT-2,w,h-MENU_HEIGHT); + Fl_Tile* tile = new Fl_Tile(0,MENU_HEIGHT-2,w,h-MENU_HEIGHT-2); + + virtualt_prefs.get("IdeTreeWidth", ideTreeWidth, 198); /* ============================================ Create region for Project tree ============================================ */ - m_ProjWindow = new Fl_Window(2,MENU_HEIGHT-2,198,h-75,""); + m_ProjWindow = new Fl_Window(2,MENU_HEIGHT-2,ideTreeWidth,h-75,""); m_ProjWindow->box(FL_DOWN_BOX); m_ProjWindow->color(background_color); // Create Tree control - m_ProjTree = new Flu_Tree_Browser( 0, 0, 198, h-75 ); + m_ProjTree = new Flu_Tree_Browser( 0, 0, ideTreeWidth, h-75 ); m_ProjTree->box( FL_DOWN_FRAME ); m_ProjTree->callback( projtree_callback ); m_ProjTree->selection_mode( FLU_SINGLE_SELECT ); -// m_ProjTree->animate(TRUE); + m_ProjTree->animate(TRUE); m_ProjTree->leaf_text(hl_plain, m_ProjTree->leaf_font(), text_size); m_ProjTree->branch_text(hl_plain, m_ProjTree->branch_font(), text_size); Fl_Window* b = new Fl_Window(40, 20, 10, 10, ""); @@ -1214,7 +1272,8 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) gPopup = new Fl_Menu_Button(0,0,100,400,"Popup"); gPopup->type(Fl_Menu_Button::POPUP3); gPopup->menu(gGroupMenu); - gPopup->selection_color(FL_LIGHT3); + gPopup->selection_color(fl_rgb_color(80,80,255)); + gPopup->color(fl_rgb_color(240,239,228)); gPopup->hide(); b->end(); m_ProjTree->hide(); @@ -1227,15 +1286,15 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) Create region and Child Window for editing files ================================================= */ - m_EditWindow = new Fl_Window(200,MENU_HEIGHT-2,w-200,h - 75,"Edit"); + m_EditWindow = new Fl_Window(ideTreeWidth+2,MENU_HEIGHT-2,w-(ideTreeWidth+2),h - 75,"Edit"); m_EditWindow->box(FL_DOWN_BOX); -// m_EditWindow->color(background_color); - m_EditTabs = new Fl_Ide_Tabs(0, 0, m_EditWindow->w(), m_EditWindow->h()); + m_EditTabs = new Fl_Ide_Tabs(0, 0, m_EditWindow->w(), m_EditWindow->h()-1); m_EditTabs->hide(); + m_EditTabs->selection_color(fl_rgb_color(253, 252, 251)); + m_EditTabs->has_close_button(TRUE); m_EditTabs->end(); m_EditWindow->resizable(m_EditTabs); m_EditWindow->end(); -// tile->resizable(m_EditWindow); /* ================================================= @@ -1244,32 +1303,36 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) */ m_TabWindow = new Fl_Window(0,MENU_HEIGHT-2+h-75,w,75-MENU_HEIGHT+2,"Tab"); m_TabWindow->box(FL_DOWN_BOX); -// m_TabWindow->color(background_color); // Create a tab control - m_Tabs = new Fl_Tabs(0, 1, w, 75-MENU_HEIGHT); +// m_Tabs = new Fl_Tabs(0, 1, w, 75-MENU_HEIGHT); + m_Tabs = new Fl_Ide_Tabs(0, 1, w, 75-MENU_HEIGHT+3); + m_Tabs->selection_color(fl_rgb_color(253, 252, 251)); /* ==================== Create build tab ==================== */ - m_BuildTab = new Fl_Group(2, 0, w-3, 75-MENU_HEIGHT-20, " Build "); + m_BuildTab = new Fl_Group(2, 0, w-3, 75-MENU_HEIGHT-22, " Build "); m_BuildTab->box(FL_DOWN_BOX); m_BuildTab->selection_color(FL_LIGHT2); m_BuildTab->color(background_color); // Create a Text Editor to show the disassembled text - m_BuildTextDisp = new My_Text_Display(0, 0, w-3, 75-MENU_HEIGHT-20); + m_BuildTextDisp = new My_Text_Display(0, 0, w-3, 75-MENU_HEIGHT-22); m_BuildTextDisp->box(FL_DOWN_BOX); -// m_BuildTextDisp->selection_color(FL_WHITE); m_BuildTextDisp->textcolor(hl_plain); m_BuildTextDisp->color(background_color); + m_BuildTextDisp->selection_color(FL_DARK_BLUE); // Create a Text Buffer for the Text Editor to work with m_BuildTextBuf = new Fl_Text_Buffer(); m_BuildTextDisp->buffer(m_BuildTextBuf); + // Setup a callback for the text display to report errors + m_BuildTextDisp->register_error_report(ide_error_report, this); + // Show the Disassembling text to indicate activity if (text_size == 0) text_size = 12; @@ -1277,6 +1340,7 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) m_BuildTextDisp->textsize(text_size); m_BuildTextDisp->end(); m_BuildTab->end(); + m_Tabs->insert(*m_BuildTab, 0); m_Tabs->resizable(m_BuildTab); /* @@ -1284,12 +1348,30 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) Create Debug tab ==================== */ - m_DebugTab = new Fl_Group(2, 0, w-3, 75-MENU_HEIGHT-20, " Debug "); + m_DebugTab = new Fl_Group(2, 0, w-3, 75-MENU_HEIGHT-22, " Debug "); m_DebugTab->box(FL_DOWN_BOX); m_DebugTab->selection_color(FL_LIGHT2); m_DebugTab->color(background_color); -// m_DebugTab->labelcolor(hl_plain); + + My_Text_Display* md = new My_Text_Display(0, 0, w-3, 75-MENU_HEIGHT-22); + md->box(FL_DOWN_BOX); + md->textcolor(hl_plain); + md->color(background_color); + md->selection_color(FL_DARK_BLUE); + + // Create a Text Buffer for the Text Editor to work with + Fl_Text_Buffer *tb = new Fl_Text_Buffer(); + md->buffer(tb); + + // Show the Disassembling text to indicate activity + if (text_size == 0) + text_size = 12; + md->textfont(FL_COURIER); + md->textsize(text_size); + md->end(); m_DebugTab->end(); + + m_Tabs->insert(*m_DebugTab,1); m_Tabs->resizable(m_DebugTab); /* @@ -1297,31 +1379,66 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) Create watch tab ==================== */ - m_WatchTab = new Fl_Group(2, 0, w-3, 75-MENU_HEIGHT-20, " Watch "); + m_WatchTab = new Fl_Group(2, 0, w-3, 75-MENU_HEIGHT-22, " Watch "); m_WatchTab->box(FL_NO_BOX); m_WatchTab->selection_color(FL_LIGHT2); m_WatchTab->color(background_color); // Create tiled window for auto and watch variables - Fl_Tile* tile2 = new Fl_Tile(2, 0,w,75-MENU_HEIGHT-20); - - Fl_Box* box0 = new Fl_Box(2, 0,w/2-2,75-MENU_HEIGHT-20,"1"); - box0->box(FL_DOWN_BOX); - box0->color(background_color); - box0->labelcolor(hl_plain); - box0->labelsize(36); - box0->align(FL_ALIGN_CLIP); - Fl_Box* box1 = new Fl_Box(w/2, 0,w/2,75-MENU_HEIGHT-20,"2"); + Fl_Tile* tile2 = new Fl_Tile(2, 0,w,75-MENU_HEIGHT-22); + + Fl_Box* box0 = new Fl_Box(2, 0,w/2-2,75-MENU_HEIGHT-22,"1"); + + // Create a text display for this pane + md = new My_Text_Display(0, 0, w-3, 75-MENU_HEIGHT-22); + md->box(FL_DOWN_BOX); + md->textcolor(hl_plain); + md->color(background_color); + md->selection_color(FL_DARK_BLUE); + + // Create a Text Buffer for the Text Editor to work with + tb = new Fl_Text_Buffer(); + md->buffer(tb); + + // Show the Disassembling text to indicate activity + if (text_size == 0) + text_size = 12; + md->textfont(FL_COURIER); + md->textsize(text_size); + md->end(); + + Fl_Box* box1 = new Fl_Box(w/2, 0,w/2,75-MENU_HEIGHT-22,"2"); box1->box(FL_DOWN_BOX); box1->color(background_color); box1->labelcolor(hl_plain); box1->labelsize(36); box1->align(FL_ALIGN_CLIP); - Fl_Box* r2 = new Fl_Box(0,0,w,75-MENU_HEIGHT-20); + // Create a text display for this pane + md = new My_Text_Display(0, 0, w-3, 75-MENU_HEIGHT-22); + md->box(FL_DOWN_BOX); + md->textcolor(hl_plain); + md->color(background_color); + md->selection_color(FL_DARK_BLUE); + + // Create a Text Buffer for the Text Editor to work with + tb = new Fl_Text_Buffer(); + md->buffer(tb); + + // Show the Disassembling text to indicate activity + if (text_size == 0) + text_size = 12; + md->textfont(FL_COURIER); + md->textsize(text_size); + md->end(); + + box0->show(); + box1->show(); + Fl_Box* r2 = new Fl_Box(0,0,w,75-MENU_HEIGHT-22); tile2->resizable(r2); tile2->end(); m_WatchTab->resizable(tile2); m_WatchTab->end(); + m_Tabs->insert(*m_WatchTab,2); m_Tabs->resizable(m_WatchTab); m_Tabs->end(); @@ -1330,7 +1447,6 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) // Create a line display box Fl_Group* g = new Fl_Group(0, 0, m_TabWindow->w(), m_TabWindow->h()); Fl_Box* b1 = new Fl_Box(0, 0, m_TabWindow->w(), m_TabWindow->h() - 25); -// b1->box(FL_BOX_NONE); m_StatusBar.m_pLineBox = new Fl_Box(m_TabWindow->w() - 250, m_TabWindow->h() - 21, 100, 20, ""); m_StatusBar.m_pColBox = new Fl_Box(m_TabWindow->w() - 150, m_TabWindow->h() - 21, 100, 20, ""); m_StatusBar.m_pInsBox = new Fl_Box(m_TabWindow->w() - 50, m_TabWindow->h() - 21, 50, 20, ""); @@ -1340,7 +1456,6 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) m_TabWindow->end(); - // Set resize region Fl_Box* r = new Fl_Box(50,MENU_HEIGHT-2,w-50,h-75); r->hide(); @@ -1349,8 +1464,11 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) resizable(m); resizable(tile); + int ideTabHeight; + virtualt_prefs.get("IdeTabheight", ideTabHeight, 75); + // Reposition the tile separators to be a little bigger than the minimum - tile->position(150,MENU_HEIGHT-2+h-75, 150,MENU_HEIGHT-2+h-170); + tile->position(ideTreeWidth,MENU_HEIGHT-2+h-75, ideTreeWidth,MENU_HEIGHT-2+h-(ideTabHeight)); SetColors(hl_plain, background_color); @@ -1562,7 +1680,9 @@ void VT_Ide::OpenFile(void) fl_cursor(FL_CURSOR_WAIT); - fc = new Flu_File_Chooser((const char *) m_LastDir, "*.asm,*.a85", 1, "Open File"); + fc = new Flu_File_Chooser((const char *) m_LastDir, + "Assembly Files (*.asm,*.a85)|Header Files (*.inc,*.h)|Listing Files (*.lst)|Map Files (*.map)", + 1, "Open File"); fl_cursor(FL_CURSOR_DEFAULT); fc->preview(0); fc->show(); @@ -1611,6 +1731,8 @@ void VT_Ide::OpenFile(const char *file) if (strcmp((const char *) title, pWidget->label()) == 0) { // File already open...bring file to foreground + m_EditTabs->value((Fl_Group *) pWidget); + pWidget->take_focus(); return; } } @@ -1712,6 +1834,7 @@ void VT_Ide::Find(void) m_pFindDlg->m_pFindDlg->show(); m_pFindDlg->m_pFind->take_focus(); + m_pFindDlg->m_pFind->selectall(); } /* @@ -1744,12 +1867,21 @@ void VT_Ide::FindNext(void) m_Search = pFind; if (!mw->ForwardSearch(pFind, m_pFindDlg->m_pMatchCase->value())) { - fl_alert("Search string %s not found", pFind); - mw->take_focus(); + // Save the current position and search from beginning of file + int pos = mw->insert_position(); + mw->insert_position(0); + if (!mw->ForwardSearch(pFind, m_pFindDlg->m_pMatchCase->value())) + { + // If still not found, report not found + mw->insert_position(pos); + fl_alert("Search string %s not found", pFind); + m_pFindDlg->m_pFind->take_focus(); + } } // Hide the dialog box -// m_pFindDlg->m_pFindDlg->hide(); + mw->take_focus(); + m_pFindDlg->m_pFindDlg->hide(); } /* @@ -1875,10 +2007,17 @@ void VT_Ide::NewProject(void) if (c == 1) SaveProject(); } + } - // Delete existing project + // Close all opened files + if (!CloseAllFiles()) + return; + + // Delete the active project + if (m_ActivePrj != NULL) + { delete m_ActivePrj; - m_ActivePrj = 0; + m_ActivePrj = NULL; } // Create new project @@ -1945,11 +2084,25 @@ void VT_Ide::NewProject(void) // Save the project type m_ActivePrj->m_ProjectType = pProj->getProjType(); - if (m_ActivePrj->m_ProjectType == 0) - m_ActivePrj->m_AutoLoad = 1; + if (m_ActivePrj->m_ProjectType == VT_PROJ_TYPE_CO || + m_ActivePrj->m_ProjectType == VT_PROJ_TYPE_ROM) + m_ActivePrj->m_AutoLoad = 1; else m_ActivePrj->m_AutoLoad = 0; + // Set the output anme based on project type + MString newExt; + switch (m_ActivePrj->m_ProjectType) + { + case VT_PROJ_TYPE_CO: newExt = ".co"; break; + case VT_PROJ_TYPE_OBJ: newExt = ".obj"; break; + case VT_PROJ_TYPE_ROM: newExt = ".hex"; break; + case VT_PROJ_TYPE_LIB: newExt = ".lib"; break; + case VT_PROJ_TYPE_BA: newExt = ".bas"; break; + default: newExt = ""; break; + } + m_ActivePrj->m_OutputName = m_ActivePrj->m_Name + newExt; + // Save the target model m_ActivePrj->m_TargetModel = pProj->getTargetModel(); gRootpath = m_ActivePrj->m_RootPath; @@ -1967,6 +2120,54 @@ void VT_Ide::NewProject(void) delete pProj; } +/* +============================================================= +Closes all files, asking to save if any are dirty. Returns +TRUE if all files closed, FALSE if CANCEL selected. +============================================================= +*/ +int VT_Ide::CloseAllFiles(void) +{ + int c, count; + int saveAll = FALSE; + Fl_Multi_Edit_Window* mw; + + // Loop through all opened tabs + count = m_EditTabs->children(); + for (c = count-1; c >= 0; c--) + { + mw = (Fl_Multi_Edit_Window *) m_EditTabs->child(c); + if (mw->IsModified()) + { + // Check if closeAll already selected + if (saveAll) + { + // Save teh file + mw->SaveFile(gRootpath); + } + else + { + // Ask if we should save the file + MString q; + q.Format("Save file %s?", mw->Title()); + int ans = fl_choice("Save file %s?", "Cancel", "Yes", "No", (const char *) mw->Title()); + + // Test for CANCEL + if (ans == 0) + return FALSE; + + if (ans == 1) + mw->SaveFile(gRootpath); + } + } + + // Hide the tab + mw->hide(); + mw->parent()->do_callback(mw, FL_IDE_TABS_CLOSE); + } + return TRUE; +} + /* ============================================================= The ProjectDirty routine returns TRUE if there is an active @@ -2072,7 +2273,14 @@ void VT_Ide::OpenProject(void) if (c == 1) SaveProject(); } + } + + // Close any opened files + if (!CloseAllFiles()) + return; + if (m_ActivePrj != NULL) + { // Delete existing project delete m_ActivePrj; m_ActivePrj = 0; @@ -2092,8 +2300,11 @@ void VT_Ide::OpenProject(const char *filename) // Try to parse the file if (ParsePrjFile(filename)) { + // Now build the TreeControl BuildTreeControl(); add_recent_project_to_menu(filename); + + // Now open the project files ReadProjectIdeSettings(); gRootpath = m_ActivePrj->m_RootPath; m_LastDir = gRootpath; @@ -2706,6 +2917,11 @@ int VT_Ide::ParsePrjFile(const char *name) if (value != 0) m_ActivePrj->m_LinkOptions = value; } + else if (strcmp(sPtr, "OUTPUTNAME") == 0) + { + if (value != 0) + m_ActivePrj->m_OutputName = value; + } else if (strcmp(sPtr, "LINKSCRIPT") == 0) { if (value != 0) @@ -3219,20 +3435,34 @@ NewEditWindow: This routine creates a new edit window with the specified Fl_Multi_Edit_Window* VT_Ide::NewEditWindow(const MString& title, const MString& file, int addToRecentFiles) { - int x, y, w, h; + int x, y, w, h; + int c; + Fl_Multi_Edit_Window* mw; + + // Test if this file already opened in a tab + for (c = m_EditTabs->children()-1; c >= 0; c--) + { + mw = (Fl_Multi_Edit_Window *) m_EditTabs->child(c); + if (mw->Title() == title) + { + mw->take_focus(); + return mw; + } + } /* Calculate location of next window */ - x = 0; + x = 1; y = TAB_HEIGHT; h = m_EditTabs->h() - TAB_HEIGHT; - w = m_EditTabs->w(); + w = m_EditTabs->w()-1; /* Create a group tab */ // Fl_Group* g = new Fl_Group(x, y, w, h, (const char *) title); /* Now Create window */ - Fl_Multi_Edit_Window* mw = new Fl_Multi_Edit_Window(x, y, w, h, + mw = new Fl_Multi_Edit_Window(x, y, w, h, (const char *) title); + mw->buffer()->tab_distance(4); if (file != "") { mw->OpenFile((const char *) file); @@ -3249,8 +3479,8 @@ Fl_Multi_Edit_Window* VT_Ide::NewEditWindow(const MString& title, const MString& mw->mCursor_color = hl_plain; mw->textsize(text_size); mw->textcolor(hl_plain); - mw->selection_color(FL_DARK_BLUE); -// mw->tooltip((const char *) mw->Filename()); + mw->selection_color(fl_color_average(FL_DARK_BLUE, FL_WHITE, .85f)); + mw->utility_margin_color(20, fl_rgb_color(253, 252, 251)); mw->show(); m_EditTabs->value(m_EditTabs->child(m_EditTabs->children()-1)); if (m_EditTabs->children() == 1) @@ -3310,6 +3540,8 @@ void VT_Ide::BuildProject(void) MString filename; MString linkerFiles; VTLinker linker; + MString linkerScript; + int linkerScriptFound = false; // Be sure we have an active project if (m_ActivePrj == NULL) @@ -3389,6 +3621,16 @@ void VT_Ide::BuildProject(void) m_BuildTextBuf->append("\n"); } } + + // Look for linker scripts while we are looping through the tree + if (temp == ".lkr") + { + if (pSource->m_Name[0] == '/' || pSource->m_Name[1] == ':') + linkerScript = pSource->m_Name; + else + linkerScript = m_ActivePrj->m_RootPath + "/" + pSource->m_Name; + linkerScriptFound = true; + } } } @@ -3409,13 +3651,17 @@ void VT_Ide::BuildProject(void) linker.SetLinkOptions(m_ActivePrj->m_LinkOptions); linker.SetObjDirs(m_ActivePrj->m_LinkPath); linker.SetProjectType(m_ActivePrj->m_ProjectType); - linker.SetLinkerScript(m_ActivePrj->m_LinkScript); + linker.SetOutputFile(m_ActivePrj->m_OutputName); + if (linkerScriptFound) + linker.SetLinkerScript(linkerScript); + else + linker.SetLinkerScript(m_ActivePrj->m_LinkScript); linkerFiles = linkerFiles + (char *) "," + m_ActivePrj->m_LinkLibs; linker.SetObjFiles(linkerFiles); linker.SetStdoutFunction(this, ideStdoutProc); // Now finally perform the link operation -// linker.Link(); + linker.Link(); errors = linker.GetErrors(); errorCount = errors.GetSize(); @@ -3425,6 +3671,19 @@ void VT_Ide::BuildProject(void) m_BuildTextBuf->append((const char *) errors[err]); m_BuildTextBuf->append("\n"); } + + // If success, print a success message + if (totalErrors == 0) + { + // Print the message + temp.Format("Success, code size=%d, data size=%d\n", + linker.TotalCodeSpace(), linker.TotalDataSpace()); + m_BuildTextBuf->append((const char *) temp); + + // Check if we generated a MAP file and the MAP file is opened + + // Now check if auto-reload of the generated file is enabled + } } } @@ -3617,6 +3876,12 @@ void cb_replace_cancel(Fl_Widget* w, void* v) VT_ReplaceDlg* pDlg = (VT_ReplaceDlg*) v; pDlg->m_pReplaceDlg->hide(); + Fl_Multi_Edit_Window* mw; + + // First get a pointer to the active (topmost) window + mw = (Fl_Multi_Edit_Window*) gpIde->m_EditTabs->value(); + if (mw != NULL) + mw->take_focus(); gpIde->show(); } @@ -3649,6 +3914,11 @@ VT_ReplaceDlg::VT_ReplaceDlg(class VT_Ide* pParent) m_pParent = pParent; } +void cb_find_edit(Fl_Widget* w, void *opaque) +{ + printf("Edit callback\n"); +} + /* ================================================================================ VT_FindDlg routines below. @@ -3662,6 +3932,7 @@ VT_FindDlg::VT_FindDlg(class VT_Ide* pParent) o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); m_pFind = new Flu_Combo_List(20, 35, 360, 25, ""); m_pFind->align(FL_ALIGN_LEFT); + m_pFind->input_callback(cb_find_next, this); m_pFindDlg->resizable(m_pFind); // Create Find In choice box @@ -3694,6 +3965,7 @@ VT_FindDlg::VT_FindDlg(class VT_Ide* pParent) o = new Fl_Box(20, 295, 360, 2, ""); m_pFindDlg->resizable(o); + m_pFindDlg->callback(cb_replace_cancel, this); m_pFindDlg->end(); m_pFindDlg->set_non_modal(); diff --git a/src/ide.h b/src/ide.h index 0a6cdb8..b63711b 100644 --- a/src/ide.h +++ b/src/ide.h @@ -126,6 +126,7 @@ class VT_Ide : public Fl_Window void OpenProject(void); void OpenProject(const char *filename); void SaveProject(void); + int CloseAllFiles(void); void SaveProjectIdeSettings(void); void ReadProjectIdeSettings(void); void BuildTreeControl(void); @@ -164,6 +165,9 @@ class VT_Ide : public Fl_Window MString ProjectName(void); void Stdout(const char *msg); int ProjectDirty(void); + void ErrorReport(int lineNo, char* pFilename); + int SpliterHeight(void) { return m_ProjWindow->h(); } + int SpliterWidth(void) { return m_ProjWindow->w(); } Fl_Window* m_EditWindow; Fl_Ide_Tabs* m_EditTabs; @@ -179,7 +183,8 @@ class VT_Ide : public Fl_Window Fl_Window* m_ProjWindow; Flu_Tree_Browser* m_ProjTree; Fl_Window* m_TabWindow; - Fl_Tabs* m_Tabs; + Fl_Ide_Tabs* m_Tabs; +// Fl_Tabs* m_Tabs; Fl_Group* m_BuildTab; My_Text_Display* m_BuildTextDisp; Fl_Text_Buffer* m_BuildTextBuf; diff --git a/src/idetabs.cpp b/src/idetabs.cpp index 108ab37..abc2262 100644 --- a/src/idetabs.cpp +++ b/src/idetabs.cpp @@ -46,6 +46,10 @@ #define BORDER 3 #define EXTRASPACE 16 +#ifndef TAB_HEIGHT +#define TAB_HEIGHT 24 +#endif + enum {LEFT, RIGHT, SELECTED}; IMPLEMENT_DYNCREATE(Fl_Ide_Tabs, VTObject) @@ -76,10 +80,13 @@ void cb_idetabs(Fl_Widget* w, void *args) } Fl_Ide_Tabs::Fl_Ide_Tabs(int x, int y, int w, int h, const char* title) -: Fl_Tabs(x, y, w, h, title) +: Fl_Group(x, y, w, h, title) { m_prevInRect = FALSE; m_pushInRect = FALSE; + m_hasCloseButton = FALSE; + box(FL_THIN_UP_BOX); + push_ = 0; callback(cb_idetabs); } @@ -97,6 +104,7 @@ void Fl_Ide_Tabs::draw() { Fl_Widget *v = value(); int H = tab_height(); +#if 0 if (damage() & FL_DAMAGE_ALL) { // redraw the entire thing: Fl_Color c = v ? v->color() : color(); @@ -112,50 +120,74 @@ void Fl_Ide_Tabs::draw() { selection_color()); fl_pop_clip(); - - } + } if (v) draw_child(*v); } else { // redraw the child if (v) update_child(*v); } +#endif - // Draw the close box - if (H >= 0) - m_closeRect = VT_Rect(x() + w() - H, 0, H, H); - else - m_closeRect = VT_Rect(x() + w() - H, y() + h() - H, H, H); - - draw_box(box(), x() + w() - H, 0, H, H, - selection_color()); - fl_color(FL_BLACK); - - int rx1 = m_closeRect.x() + 8; - int ry1 = m_closeRect.y(); - int rx2 = m_closeRect.x1() - 8; - int ry2 = m_closeRect.y1(); - fl_line(rx1, ry1 + 7, rx2, ry2 - 9); - fl_line(rx1, ry1 + 8, rx2, ry2 - 8); - fl_line(rx1, ry1 + 9, rx2, ry2 - 7); - fl_line(rx1, ry2 - 7, rx2, ry1 + 9); - fl_line(rx1, ry2 - 8, rx2, ry1 + 8); - fl_line(rx1, ry2 - 9, rx2, ry1 + 7); - - if (damage() & (FL_DAMAGE_SCROLL|FL_DAMAGE_ALL)) { - int p[128]; int wp[128]; - int selected = tab_positions(p,wp); - int i; - Fl_Widget*const* a = array(); - for (i=0; i selected; i--) - draw_tab(x()+p[i], x()+p[i+1], wp[i], H, a[i], RIGHT); - if (v) { - i = selected; - draw_tab(x()+p[i], x()+p[i+1], wp[i], H, a[i], SELECTED); - } + int H2 = H < 0 ? -H : H; + + // Draw the background rectangle + fl_clip(x(), y(), w(), h()+2); + draw_box(box(), x(), y(), w(), h()+2, fl_rgb_color(228,226,213)); + fl_pop_clip(); // Draw the close box - } + if (m_hasCloseButton) + { + if (H >= 0) + m_closeRect = VT_Rect(x() + w() - H2, 0, H2, H2); + else + m_closeRect = VT_Rect(x() + w() - H2, y() + h() - H2, H2, H2); + draw_box(box(), x() + w() - H2, 0, H2, H2, selection_color()); + } + + // Draw the bottom border line for the "TAB" + if (H >= 0) + draw_box(box(), x()+1, H2-3, w(), H2, selection_color()); + else + draw_box(box(), x()+1, h()-H2-4, w(), 5, selection_color()); + fl_color(fl_rgb_color(127,157,184)); + if (H<0) + fl_line(x()+1, h()-H2, w(), h()-H2); + else + fl_line(x()+1, H-4, w()-H-1, H-4); + + // Draw the 'X' in the close box + if (m_hasCloseButton) + { + fl_color(FL_BLACK); + + int rx1 = m_closeRect.x() + 8; + int ry1 = m_closeRect.y(); + int rx2 = m_closeRect.x1() - 8; + int ry2 = m_closeRect.y1(); + + fl_line(rx1, ry1 + 7, rx2, ry2 - 9); + fl_line(rx1, ry1 + 8, rx2, ry2 - 8); + fl_line(rx1, ry1 + 9, rx2, ry2 - 7); + fl_line(rx1, ry2 - 7, rx2, ry1 + 9); + fl_line(rx1, ry2 - 8, rx2, ry1 + 8); + fl_line(rx1, ry2 - 9, rx2, ry1 + 7); + } + // Draw the tabs + if (damage() & (FL_DAMAGE_SCROLL|FL_DAMAGE_ALL)) + { + int p[128]; int wp[128]; + int selected = tab_positions(p,wp); + int i; + Fl_Widget*const* a = array(); + for (i=children()-1; i > selected; i--) + draw_tab(x()+H2+p[i], x()+H2/2+3+p[i+1], wp[i], H, a[i], RIGHT); + for (i=selected - 1; i>=0; i--) + draw_tab(x()+H2+p[i], x()+H2/2+3+p[i+1], wp[i], H, a[i], LEFT); + if (v) { + i = selected; + draw_tab(x()+H2+p[i], x()+H2/2+3+p[i+1], wp[i], H, a[i], SELECTED); + } + } } /* @@ -168,6 +200,7 @@ int Fl_Ide_Tabs::tab_positions(int* p, int* wp) { int selected = 0; Fl_Widget*const* a = array(); int i; + int H = tab_height(); char prev_draw_shortcut = fl_draw_shortcut; fl_draw_shortcut = 1; @@ -235,6 +268,8 @@ return space needed for tabs. Negative to put them on the bottom: int Fl_Ide_Tabs::tab_height() { int H = h(); int H2 = y(); + int ret; + Fl_Widget*const* a = array(); for (int i=children(); i--;) { Fl_Widget* o = *a++; @@ -242,8 +277,19 @@ int Fl_Ide_Tabs::tab_height() { if (o->y()+o->h() > H2) H2 = o->y()+o->h(); } H2 = y()+h()-H2; - if (H2 > H) return (H2 <= 0) ? 0 : -H2; - else return (H <= 0) ? 0 : H; + if (H2 > H) + { + ret = (H2 <= 0) ? 0 : -H2; + if (ret < -24) + ret = -24; + } + else + { + ret = (H <= 0) ? 0 : H; + if (ret > 24) + ret = 24; + } + return ret; } /* @@ -255,15 +301,14 @@ void Fl_Ide_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) int sel = (what == SELECTED); int dh = Fl::box_dh(box()); int dy = Fl::box_dy(box()); + int i; char prev_draw_shortcut = fl_draw_shortcut; fl_draw_shortcut = 1; Fl_Boxtype bt = (o==push() &&!sel) ? fl_down(box()) : box(); // compute offsets to make selected tab look bigger - int yofs = sel ? 0 : BORDER; - - if ((x2 < x1+W) && what == RIGHT) x1 = x2 - W; + int yofs = sel ? BORDER + 1 : BORDER; if (H >= 0) { if (sel) fl_clip(x1, y(), x2 - x1, H + dh - dy); @@ -271,57 +316,112 @@ void Fl_Ide_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) H += dh; -// Fl_Color c = sel ? selection_color() : o->selection_color(); - Fl_Color c = selection_color(); - - draw_box(bt, x1, y() + yofs, W, H + 10 - yofs, c); + Fl_Color c = sel ? fl_lighter(selection_color()) : selection_color(); // Save the previous label color Fl_Color oc = o->labelcolor(); - // Draw the label using the current color... + fl_pop_clip(); + fl_clip(x1-H-10, y()-2, W+H+5, H+2); + + // Draw TAB left curved portion + fl_color(c); + int y2 = y() + BORDER; + fl_line(x1, y2, x2, y2); + fl_line(x1-2, y2+1, x2, y2+1); + fl_line(x1-4, y2+2, x2, y2+2); + for (i=3; i < H-BORDER-5; i++) + { + if (!sel) + { + c = fl_color_average(c, FL_BLACK, .985f); + fl_color(c); + } + fl_line(x1-(2+i), y2+i, x2, y2+i); + } + + // Draw the label using the current color... if (sel) o->labelfont(o->labelfont() + 1); o->labeltype(FL_NORMAL_LABEL); o->labelcolor(sel ? labelcolor() : o->labelcolor()); - o->draw_label(x1, y() + yofs, W, H - yofs, FL_ALIGN_CENTER); + o->draw_label(x1, y() + yofs-3, W, H - yofs, FL_ALIGN_LEFT); if (sel) o->labelfont(o->labelfont() - 1); // Restore the original label color... o->labelcolor(oc); - if (Fl::focus() == this && o->visible()) - draw_focus(box(), x1, y(), W, H); + // Draw TAB Border +// fl_color(FL_BLACK); + if (sel) + fl_color(fl_rgb_color(127,157,184)); + else + fl_color(fl_rgb_color(172,168,153)); + i+=4; + fl_line(x1-(3+i-5), y2+i-5, x1-5,y2+2); + fl_line(x1-4,y2+1, x1-3,y2+1); + fl_line(x1-2,y2, x1-1,y2); + fl_line(x1,y2-1, x2,y2-1); + fl_line(x2,y2-1, x2,y2+i-5); + if (!sel) + { + fl_color(fl_rgb_color(127,157,184)); + fl_line(x1-(3+i-2), y2+i-5, x2,y2+i-5); + } - fl_pop_clip(); + fl_pop_clip(); } else { H = -H; - - if (sel) fl_clip(x1, y() + h() - H - dy, x2 - x1, H + dy); - else fl_clip(x1, y() + h() - H, x2 - x1, H); - H += dh; -/// Fl_Color c = sel ? selection_color() : o->selection_color(); - Fl_Color c = selection_color(); - - draw_box(bt, x1, y() + h() - H - 10, W, H + 10 - yofs, c); - // Save the previous label color - Fl_Color oc = o->color(); + Fl_Color c = sel ? fl_lighter(selection_color()) : selection_color(); + Fl_Color oc = o->labelcolor(); + fl_clip(x(), y(), w()+5, h()); + + // Draw TAB left curved portion + fl_color(c); + int y2 = y() + h() -6; + fl_line(x1, y2, x2, y2); + fl_line(x1-2, y2-1, x2, y2-1); + fl_line(x1-4, y2-2, x2, y2-2); + for (i=3; i < H-BORDER-3; i++) + { + if (!sel) + { + c = fl_color_average(c, FL_BLACK, .985f); + fl_color(c); + } + fl_line(x1-(2+i), y2-i, x2, y2-i); + } - // Draw the label using the current color... + // Draw the label using the current color... if (sel) o->labelfont(o->labelfont() + 1); - o->labelcolor(sel ? labelcolor() : o->labelcolor()); - o->draw_label(x1, y() + h() - H, W, H - yofs, FL_ALIGN_CENTER); + o->labeltype(FL_NORMAL_LABEL); + o->labelcolor(sel ? labelcolor() : o->labelcolor()); + o->draw_label(x1, y() +h()-H+ yofs-3, W, H - yofs, FL_ALIGN_LEFT); if (sel) o->labelfont(o->labelfont() - 1); // Restore the original label color... o->labelcolor(oc); - if (Fl::focus() == this && o->visible()) - draw_focus(box(), x1, y() + h() - H, W, H); + // Draw TAB Border + if (sel) + fl_color(fl_rgb_color(127,157,184)); + else + fl_color(fl_rgb_color(172,168,153)); + i+=4; + fl_line(x1-(3+i-5), y2-i+5, x1-5,y2-2); + fl_line(x1-4,y2-1, x1-3,y2-1); + fl_line(x1-2,y2, x1-1,y2); + fl_line(x1,y2+1, x2,y2+1); + fl_line(x2,y2+1, x2,y2-i+5); + if (!sel) + { + fl_color(fl_rgb_color(127,157,184)); + fl_line(x1-(3+i-2), y2-i+5, x2,y2-i+5); + } - fl_pop_clip(); + fl_pop_clip(); } fl_draw_shortcut = prev_draw_shortcut; } @@ -360,7 +460,7 @@ int Fl_Ide_Tabs::handle(int e) else { if (!m_prevInRect) - return Fl_Tabs::handle(e); + return orig_handle(e); window()->make_current(); fl_color(selection_color()); drawbox = TRUE; @@ -394,9 +494,9 @@ int Fl_Ide_Tabs::handle(int e) m_pushInRect = TRUE; return 1; } - + break; w = value(); - ret = Fl_Tabs::handle(e); + ret = orig_handle(e); if (w != value()) { if (w != NULL) @@ -424,6 +524,187 @@ int Fl_Ide_Tabs::handle(int e) break; } - return Fl_Tabs::handle(e); + return orig_handle(e); +} + +// this is used by fluid to pick tabs: +Fl_Widget *Fl_Ide_Tabs::which(int event_x, int event_y) { + int H = tab_height(); + if (H < 0) { + if (event_y > y()+h() || event_y < y()+h()+H) return 0; + } else { + if (event_y > y()+H || event_y < y()) return 0; + } + if (H<0) H=-H; + if (event_x < x()) return 0; + int p[128], wp[128]; + tab_positions(p, wp); + for (int i=0; i= 0) { + H += Fl::box_dy(box()); + damage(FL_DAMAGE_SCROLL, x(), y(), w(), H); + } else { + H = Fl::box_dy(box()) - H; + damage(FL_DAMAGE_SCROLL, x(), y() + h() - H, w(), H); + } +} + +int Fl_Ide_Tabs::orig_handle(int event) { + + Fl_Widget *o; + int i; + + switch (event) { + + case FL_PUSH: { + int H = tab_height(); + if (H >= 0) { + if (Fl::event_y() > y()+H) return Fl_Group::handle(event); + } else { + if (Fl::event_y() < y()+h()+H) return Fl_Group::handle(event); + }} + case FL_DRAG: + case FL_RELEASE: + o = which(Fl::event_x(), Fl::event_y()); + if (event == FL_RELEASE) { + push(0); + if (o && Fl::visible_focus() && Fl::focus()!=this) { + Fl::focus(this); + redraw_tabs(); + } + if (o && value(o)) { + set_changed(); + do_callback(); + } + Fl_Tooltip::current(o); + } else { + push(o); + } + return 1; + case FL_MOVE: { + int ret = Fl_Group::handle(event); + Fl_Widget *o = Fl_Tooltip::current(), *n = o; + int H = tab_height(); + if ( (H>=0) && (Fl::event_y()>y()+H) ) + return ret; + else if ( (H<0) && (Fl::event_y() < y()+h()+H) ) + return ret; + else { + n = which(Fl::event_x(), Fl::event_y()); + if (!n) n = this; + } + if (n!=o) + Fl_Tooltip::enter(n); + return ret; } + case FL_FOCUS: + case FL_UNFOCUS: + if (!Fl::visible_focus()) return Fl_Group::handle(event); + if (Fl::event() == FL_RELEASE || + Fl::event() == FL_SHORTCUT || + Fl::event() == FL_KEYBOARD || + Fl::event() == FL_FOCUS || + Fl::event() == FL_UNFOCUS) { + redraw_tabs(); + if (Fl::event() == FL_FOCUS || Fl::event() == FL_UNFOCUS) return 0; + else return 1; + } else return Fl_Group::handle(event); + case FL_KEYBOARD: + switch (Fl::event_key()) { + case FL_Left: + if (child(0)->visible()) return 0; + for (i = 1; i < children(); i ++) + if (child(i)->visible()) break; + value(child(i - 1)); + set_changed(); + do_callback(); + return 1; + case FL_Right: + if (child(children() - 1)->visible()) return 0; + for (i = 0; i < children(); i ++) + if (child(i)->visible()) break; + value(child(i + 1)); + set_changed(); + do_callback(); + return 1; + case FL_Down: + redraw(); + return Fl_Group::handle(FL_FOCUS); + default: + break; + } + return Fl_Group::handle(event); + case FL_SHORTCUT: + for (i = 0; i < children(); ++i) { + Fl_Widget *c = child(i); + if (c->test_shortcut(c->label())) { + char sc = !c->visible(); + value(c); + if (sc) set_changed(); + do_callback(); + return 1; + } + } + return Fl_Group::handle(event); + case FL_SHOW: + value(); // update visibilities and fall through + default: + return Fl_Group::handle(event); + + } +} + +int Fl_Ide_Tabs::push(Fl_Widget *o) { + if (push_ == o) return 0; + if (push_ && !push_->visible() || o && !o->visible()) + { + if (push_) + push_->hide(); + if (o) + o->show(); + redraw_tabs(); + } + push_ = o; + return 1; +} + +// The value() is the first visible child (or the last child if none +// are visible) and this also hides any other children. +// This allows the tabs to be deleted, moved to other groups, and +// show()/hide() called without it screwing up. +Fl_Widget* Fl_Ide_Tabs::value() { + Fl_Widget* v = 0; + Fl_Widget*const* a = array(); + for (int i=children(); i--;) { + Fl_Widget* o = *a++; + if (v) o->hide(); + else if (o->visible()) v = o; + else if (!i) {o->show(); v = o;} + } + return v; +} + +// Setting the value hides all other children, and makes this one +// visible, iff it is really a child: +int Fl_Ide_Tabs::value(Fl_Widget *newvalue) { + Fl_Widget*const* a = array(); + int ret = 0; + for (int i=children(); i--;) { + Fl_Widget* o = *a++; + if (o == newvalue) { + if (!o->visible()) ret = 1; + o->show(); + } else { + o->hide(); + } + } + return ret; } diff --git a/src/idetabs.h b/src/idetabs.h index 341969a..cae4b75 100644 --- a/src/idetabs.h +++ b/src/idetabs.h @@ -35,7 +35,7 @@ #define FL_IDE_TABS_CLOSE (0xDEADD00D) -class Fl_Ide_Tabs : public Fl_Tabs, public VTObject +class Fl_Ide_Tabs : public Fl_Group, public VTObject { public: Fl_Ide_Tabs(int x=0, int y=0, int w=600, int h=500, const char *label = 0); @@ -43,12 +43,24 @@ class Fl_Ide_Tabs : public Fl_Tabs, public VTObject DECLARE_DYNCREATE(Fl_Ide_Tabs) + Fl_Widget *value(); + int value(Fl_Widget *); + Fl_Widget *push() const {return push_;} + int push(Fl_Widget *); + Fl_Widget *which(int event_x, int event_y); + void has_close_button(int bHasCloseButton) { m_hasCloseButton = bHasCloseButton; } + protected: VT_Rect m_closeRect; int m_prevInRect; int m_pushInRect; + int m_hasCloseButton; + Fl_Widget *value_; + Fl_Widget *push_; virtual int handle(int e); + virtual int orig_handle(int e); + void redraw_tabs(); void draw(void); int tab_positions(int* p, int* wp); int tab_height(); diff --git a/src/io.c b/src/io.c index ca90127..0f503cc 100644 --- a/src/io.c +++ b/src/io.c @@ -80,6 +80,7 @@ extern int gRomBank; extern RomDescription_t *gStdRomDesc; void handle_wheel_keys(void); +int gCapture = FALSE; /* ============================================================================= This routine supplies an OS independant high-resolution timer for use with @@ -263,6 +264,36 @@ void update_keys(void) } } + if (gSpecialKeys & (MT_GRAPH | MT_CODE | MT_SHIFT) && !gCapture) + { + FILE* fd; + int d, col, row; + gCapture = TRUE; + + fd = fopen("lcd_cap.txt", "w"); + if (fd != NULL) + { + // Set start page for all drivers to 0 + fprintf(fd, "f 0 3e\n"); + fprintf(fd, "f 0 3b\n"); + + for (d = 0; d < 10; d++) + { + for (row = 0; row < 4; row++) + { + // Set the X/Y address + fprintf(fd, "%x 0 %02x\n", d, row<<6); + for(col = 0; col < 50; col++) + { + fprintf(fd, "%x 1 %02x\n", d, lcd[d][(row<<2) + col]); + } + } + } + fclose(fd); + } + } + else + gCapture = FALSE; gDelayUpdateKeys = 0; gDelayCount = 0; handle_wheel_keys(); diff --git a/src/linker.cpp b/src/linker.cpp index 3bb5b35..2ce265b 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -33,9 +33,17 @@ Construtor / destructor for the linker */ VTLinker::VTLinker() { + int x; + m_Hex = 0; m_FileIndex = -1; m_DebugInfo = 0; + m_TotalCodeSpace = 0; + m_TotalDataSpace = 0; + + // Clear out the Segment assignement map + for (x = 0; x < sizeof(m_SegMap) / sizeof(CObjSegment *); x++) + m_SegMap[x] = NULL; } VTLinker::~VTLinker() @@ -54,6 +62,16 @@ void VTLinker::SetStdoutFunction(void *pContext, stdOutFunc_t pFunc) m_pStdoutContext = pContext; } +/* +============================================================================ +Sets the standard output "printf" function to write error messages to +============================================================================ +*/ +void VTLinker::SetOutputFile(const MString& outFile) +{ + m_OutputName = outFile; +} + /* ============================================================================ This routine free's all memory and initializes all variables for a new @@ -66,6 +84,7 @@ void VTLinker::ResetContent(void) CObjSegment* pSeg; CLinkRgn* pLinkRgn; MStringArray* pStrArray; + CObjSymFile* pObjSymFile; POSITION pos; // Loop through each segment @@ -117,6 +136,15 @@ void VTLinker::ResetContent(void) } m_LinkEndsWithList.RemoveAll(); + // Loop through all Symbols and delete them + pos = m_Symbols.GetStartPosition(); + while (pos != NULL) + { + m_Symbols.GetNextAssoc(pos, key, (VTObject *&) pObjSymFile); + delete pObjSymFile; + } + m_Symbols.RemoveAll(); + // Delete all undefined symbols m_UndefSymbols.RemoveAll(); @@ -235,6 +263,10 @@ int VTLinker::MapScriptCommand(const char *pStr, int lineNo) else if (strcmp(pStr, "DATA") == 0) command = LKR_CMD_DATA; + // Test for DATA specification + else if (strcmp(pStr, "MIXED") == 0) + command = LKR_CMD_MIXED; + // Test for OBJPATH specification else if (strcmp(pStr, "OBJPATH") == 0) command = LKR_CMD_OBJPATH; @@ -254,12 +286,20 @@ int VTLinker::MapScriptCommand(const char *pStr, int lineNo) // Test for FILES specification else if (strcmp(pStr, "ENDSWITH") == 0) command = LKR_CMD_ENDSWITH; + + // Test for ENTRY specification + else if (strcmp(pStr, "ENTRY") == 0) + command = LKR_CMD_ENTRY; + + // Test for ENTRY specification + else if (strcmp(pStr, "DEFINE") == 0) + command = LKR_CMD_DEFINE; else { // Syntax error - err.Format("Error during linking: Parser syntax error on line %d", - lineNo); + err.Format("Error in line %d(%s): Parser syntax error", lineNo, + (const char *) m_LinkerScript); m_Errors.Add(err); } @@ -277,11 +317,13 @@ void VTLinker::ProcScriptField2(const char *pStr, int lineNo, MString &segname) MString err, temp; // Process 1st field of CODE or DATA command - if ((m_Command == LKR_CMD_CODE) || (m_Command == LKR_CMD_DATA)) + if ((m_Command == LKR_CMD_CODE) || (m_Command == LKR_CMD_DATA) || + (m_Command == LKR_CMD_MIXED)) { if (strncmp(pStr, "NAME=", 5) != 0) { - err.Format("%sExpected segment name on line %d", gsEdl, lineNo); + err.Format("Error in line %d(%s): Expected segment name", lineNo, + (const char *) m_LinkerScript); m_Errors.Add(err); m_Command = LKR_CMD_ERROR; } @@ -313,6 +355,18 @@ void VTLinker::ProcScriptField2(const char *pStr, int lineNo, MString &segname) { segname = pStr; } + + // Test if command is OBJPATH and add path to array + else if (m_Command == LKR_CMD_ENTRY) + { + m_EntryLabel = pStr; + m_Command = LKR_CMD_COMPLETE; + } + + // Test if command is DEFINE and add the symbol + else if (m_Command == LKR_CMD_DEFINE) + { + } } /* @@ -358,28 +412,49 @@ This routine processes the 2nd field from the current line o the linker script. It performs operations based on the current m_Command. ============================================================================ */ -void VTLinker::ProcScriptField3(const char *pStr, int lineNo, int& startAddr) +void VTLinker::ProcScriptField3(char *pStr, int lineNo, int& startAddr, + char* &pSectName) { MString err; // Initialize startAddr in case error or ORDER command startAddr = -1; + pSectName = NULL; // Test if CODE or DATA command - if ((m_Command == LKR_CMD_CODE) || (m_Command == LKR_CMD_DATA)) + if ((m_Command == LKR_CMD_CODE) || (m_Command == LKR_CMD_DATA) || + (m_Command == LKR_CMD_MIXED)) { if (strncmp(pStr, "START=", 6) == 0) { // Evaluate the starting address - if (strcmp(pStr + 6, "codeend") == 0) + if (strncmp(pStr + 6, "atend(", 6) == 0) + { + // Set the START address to indicate atend of a region startAddr = START_ADDR_CODEEND; + + // Parse the region name from the string + if (pStr[strlen(pStr)-1] == ')') + { + pStr[strlen(pStr)-1] = '\0'; + pSectName = pStr + 12; + } + else + { + // Parse error! Expected ')' + err.Format("Error in line %d(%s): Expected ')'", lineNo, + (const char *) m_LinkerScript); + m_Errors.Add(err); + m_Command = LKR_CMD_ERROR; + } + } else startAddr = EvaluateScriptAddress(pStr + 6, lineNo); } else { - err.Format("%sExpected START address in linker script on line %d", - gsEdl, lineNo); + err.Format("Error in line %d(%s): Expected START address", lineNo, + (const char *) m_LinkerScript); m_Errors.Add(err); m_Command = LKR_CMD_ERROR; } @@ -391,8 +466,8 @@ void VTLinker::ProcScriptField3(const char *pStr, int lineNo, int& startAddr) { if (strcmp(pStr, "{") != 0) { - err.Format("%sExpected open brace in linker script on line %d", - gsEdl, lineNo); + err.Format("Error in line %d(%s): Expected open brace", lineNo, + (const char *) m_LinkerScript); m_Errors.Add(err); m_Command = LKR_CMD_ERROR; } @@ -405,7 +480,8 @@ void VTLinker::ProcScriptField3(const char *pStr, int lineNo, int& startAddr) // Other commands don't have more than 2 fields else { - err.Format("%sTo many linker script arguments in line %d", gsEdl, lineNo); + err.Format("Error in line %d(%s): To many arguments", lineNo, + (const char *) m_LinkerScript); m_Errors.Add(err); m_Command = LKR_CMD_ERROR; } @@ -425,7 +501,8 @@ void VTLinker::ProcScriptField4(const char *pStr, int lineNo, int& endAddr) endAddr = -1; // Test if CODE or DATA command - if ((m_Command == LKR_CMD_CODE) || (m_Command == LKR_CMD_DATA)) + if ((m_Command == LKR_CMD_CODE) || (m_Command == LKR_CMD_DATA) || + (m_Command == LKR_CMD_MIXED)) { if (strncmp(pStr, "END=", 4) == 0) { @@ -434,8 +511,8 @@ void VTLinker::ProcScriptField4(const char *pStr, int lineNo, int& endAddr) } else { - err.Format("%sExpected END address in linker script on line %d", - gsEdl, lineNo); + err.Format("Error in line %d(%s): Expected END address in linker script", + lineNo, (const char *) m_LinkerScript); m_Errors.Add(err); m_Command = LKR_CMD_ERROR; } @@ -468,8 +545,8 @@ void VTLinker::AddOrderedSegment(const char *pStr, int lineNo) // Test if this segment has already been defined as ordered if (m_LinkOrderList.Lookup(m_SegName, (VTObject *&) pOrder)) { - err.Format("%sOrder already specified for %s on line %d", - gsEdl, (const char *) m_SegName, lineNo); + err.Format("Error in line %d(%s): Order already specified for %s", + lineNo, (const char *) m_LinkerScript, (const char *) m_SegName); m_Errors.Add(err); delete m_ActiveLinkOrder; m_ActiveLinkOrder = NULL; @@ -504,8 +581,8 @@ void VTLinker::AddContainsSegment(const char *pStr, int lineNo) // Test if this segment has already been defined as ordered if (m_LinkContainsList.Lookup(m_SegName, (VTObject *&) pOrder)) { - err.Format("%sContainment already specified for %s on line %d", - gsEdl, (const char *) m_SegName, lineNo); + err.Format("Error in line %d(%s): Containment already specified for %s", lineNo, + (const char *) m_LinkerScript, (const char *) m_SegName); m_Errors.Add(err); delete m_ActiveLinkOrder; m_ActiveLinkOrder = NULL; @@ -540,8 +617,8 @@ void VTLinker::AddEndsWithSegment(const char *pStr, int lineNo) // Test if this segment has already been defined as ordered if (m_LinkEndsWithList.Lookup(m_SegName, (VTObject *&) pOrder)) { - err.Format("%sENDSWITH already specified for %s on line %d", - gsEdl, (const char *) m_SegName, lineNo); + err.Format("Error in line %d(%s): ENDSWITH already specified for %s", lineNo, + (const char *) m_LinkerScript, (const char *) m_SegName); m_Errors.Add(err); delete m_ActiveLinkOrder; m_ActiveLinkOrder = NULL; @@ -564,26 +641,56 @@ This routine processes the 2nd field from the current line o the linker script. It performs operations based on the current m_Command. ============================================================================ */ -void VTLinker::ProcScriptField5(const char *pStr, int lineNo, int& prot) +void VTLinker::ProcScriptField5(const char *pStr, int lineNo, int& prot, int& atend) { MString err; + const char *pToken, *ptr; + int tokLen; // Initialize startAddr in case error or ORDER command prot = FALSE; + atend = FALSE; - // Test if CODE or DATA command with PROTECTED option + // Test if CODE, DATA or MIXED command with PROTECTED or ATEND option if (m_Command & LKR_CMD_CD_DONE) { - if (strcmp(pStr, "PROTECTED") == 0) + pToken = pStr; + while (pToken != NULL && *pToken != '\0') { - prot = TRUE; - } - else - { - err.Format("%sExpected argument in linker script on line %d", - gsEdl, lineNo); - m_Errors.Add(err); - m_Command = LKR_CMD_ERROR; + // Find token length + tokLen = 0; + ptr = pToken; + while (*ptr != '+' && *ptr != '\0') + { + tokLen++; + ptr++; + } + + if (strncmp(pToken, "PROTECTED", tokLen) == 0) + { + prot = TRUE; + } + else if (strncmp(pToken, "ATEND", tokLen) == 0) + { + atend = TRUE; + } + else + { + char temp[128]; + if (tokLen >= sizeof(temp) - 1) + tokLen = sizeof(temp) - 1; + strncpy(temp, pToken, tokLen); + temp[tokLen] = '\0'; + err.Format("Error in line %d(%s): Unknown region attribute %s", lineNo, + (const char *) m_LinkerScript, temp); + m_Errors.Add(err); + m_Command = LKR_CMD_ERROR; + } + + // Advance to next tokan + pToken += tokLen; + if (*pToken == '+') + pToken++; } } @@ -604,7 +711,7 @@ address definitions. ============================================================================ */ void VTLinker::NewLinkRegion(int type, int lineNo, int startAddr, - int endAddr, int prot) + int endAddr, int prot, const char *pAtEndName, int atend) { MString err, key; CLinkRgn *pLinkRgn; @@ -622,16 +729,17 @@ void VTLinker::NewLinkRegion(int type, int lineNo, int startAddr, while (pThisRange != NULL) { // Test if this region overlaps with new region - if ((startAddr >= pThisRange->startAddr) && ( + if (((startAddr >= pThisRange->startAddr) && ( (startAddr <= pThisRange->endAddr)) || ((endAddr >= pThisRange->startAddr) && (endAddr <= pThisRange->endAddr)) || ((startAddr <= pThisRange->startAddr) && - (endAddr >= pThisRange->endAddr)) && - (startAddr != START_ADDR_CODEEND)) + (endAddr >= pThisRange->endAddr))) && + (startAddr != START_ADDR_CODEEND) && + (startAddr != START_ADDR_DATAEND)) { - err.Format("%sLinker script address ranges cannot overlap at line %d", - gsEdl, lineNo); + err.Format("Error in line %d(%s): Linker script address ranges cannot overlap", + lineNo, (const char *) m_LinkerScript); m_Errors.Add(err); m_Command = LKR_CMD_ERROR; return; @@ -669,7 +777,9 @@ void VTLinker::NewLinkRegion(int type, int lineNo, int startAddr, // Create a new link region if (pLinkRgn == NULL) { - pLinkRgn = new CLinkRgn(m_Command, m_SegName, startAddr, endAddr, prot); + pLinkRgn = new CLinkRgn(m_Command, m_SegName, startAddr, endAddr, prot, pAtEndName, atend); + pLinkRgn->m_NextLocateAddr = startAddr; + pLinkRgn->m_EndLocateAddr = endAddr; m_LinkRegions[(const char *) m_SegName] = pLinkRgn; } else @@ -678,29 +788,47 @@ void VTLinker::NewLinkRegion(int type, int lineNo, int startAddr, pAddrRange = new LinkAddrRange; pAddrRange->startAddr = startAddr; pAddrRange->endAddr = endAddr; + pAddrRange->nextLocateAddr = startAddr; + pAddrRange->endLocateAddr = endAddr; pAddrRange->pNext = NULL; + pAddrRange->pPrev = NULL; // Insert this address range into the list pPrevRange = NULL; pThisRange = pLinkRgn->m_pFirstAddrRange; - while ((pThisRange != NULL) && (pAddrRange->startAddr < - pThisRange->startAddr)) + while ((pThisRange != NULL) && (pThisRange->startAddr < + pAddrRange->startAddr)) { pPrevRange = pThisRange; pThisRange = pThisRange->pNext; } + // Update the LinkRgn's NextLocate and EndLocate addresses + if (pAddrRange->startAddr < pLinkRgn->m_NextLocateAddr) + pLinkRgn->m_NextLocateAddr = pAddrRange->startAddr; + if (pAddrRange->endAddr > pLinkRgn->m_EndLocateAddr) + pLinkRgn->m_EndLocateAddr = pAddrRange->endAddr; + // Test if new region should be inserted at beginning or in middle if (pThisRange == pLinkRgn->m_pFirstAddrRange) { + // Insert as first item pAddrRange->pNext = pThisRange; pLinkRgn->m_pFirstAddrRange = pAddrRange; } else { + // Insert into linked list pAddrRange->pNext = pThisRange; pPrevRange->pNext = pAddrRange; } + + // Update LinkRgn's LastAddrRange if this is the last item + pAddrRange->pPrev = pPrevRange; + if (pAddrRange->pNext == NULL) + pLinkRgn->m_pLastAddrRange = pAddrRange; + else + pAddrRange->pNext->pPrev = pAddrRange; } m_Command = LKR_CMD_COMPLETE; } @@ -720,7 +848,8 @@ int VTLinker::ReadLinkerScript() FILE *fd; char lineBuf[256]; char *pRead, *pTok; - int field, startAddr, endAddr, prot; + int field, startAddr, endAddr, prot, atend; + char *pSectName; // Test if linker script was supplied if (m_LinkerScript.GetLength() == 0) @@ -756,6 +885,7 @@ int VTLinker::ReadLinkerScript() lineNo = 0; field = 0; prot = 0; + atend = 0; while (TRUE) { // Read the line from the file @@ -789,8 +919,8 @@ int VTLinker::ReadLinkerScript() if ((m_Command != LKR_CMD_NONE) && (m_Command != LKR_CMD_COMPLETE) && !(m_Command & LKR_CMD_CD_DONE)) { - err.Format("%sIncomplete linker script command on line %d", - gsEdl, lineNo); + err.Format("Error in line %d(%s): Incomplete linker script command", lineNo, + (const char *) m_LinkerScript); m_Errors.Add(err); } break; @@ -809,7 +939,7 @@ int VTLinker::ReadLinkerScript() break; case 2: - ProcScriptField3(pTok, lineNo, startAddr); + ProcScriptField3(pTok, lineNo, startAddr, pSectName); break; case 3: @@ -817,7 +947,7 @@ int VTLinker::ReadLinkerScript() break; case 4: - ProcScriptField5(pTok, lineNo, prot); + ProcScriptField5(pTok, lineNo, prot, atend); break; default: @@ -844,7 +974,7 @@ int VTLinker::ReadLinkerScript() { // Clear the CMD_CD_DONE bit m_Command &= ~LKR_CMD_CD_DONE; - NewLinkRegion(m_Command, lineNo, startAddr, endAddr, prot); + NewLinkRegion(m_Command, lineNo, startAddr, endAddr, prot, pSectName, atend); } } @@ -871,14 +1001,14 @@ int VTLinker::ReadElfHeaders(FILE* fd, MString& filename) int bytes, c; MString err; - // Write ELF header to file + // Read ELF header from file bytes = fread(&ehdr, 1, sizeof(ehdr), fd); if ((bytes != sizeof(ehdr)) || (ehdr.e_ident[EI_MAG0] != ELFMAG0) || (ehdr.e_ident[EI_MAG1] != ELFMAG1) || (ehdr.e_ident[EI_MAG2] != ELFMAG2) || (ehdr.e_ident[EI_MAG3] != ELFMAG3)) { fclose(fd); - err.Format("Error during linking: Object file %s is not ELF format", + err.Format("%sObject file %s is not ELF format", gsEdl, (const char *) filename); m_Errors.Add(err); return FALSE; @@ -942,6 +1072,7 @@ int VTLinker::ReadElfHeaders(FILE* fd, MString& filename) } // Add this section header to the array + pFileSection->m_Index = c; pObjFile->m_FileSections.Add(pFileSection); } @@ -957,9 +1088,31 @@ int VTLinker::ReadElfHeaders(FILE* fd, MString& filename) } } + m_ObjFiles[filename] = pObjFile; + return TRUE; } +/* +=============================================================================== +This routine returns a string which is the relative form of the given path +realtive to the relTo path. The routine detects both relativeness in bot +directions and uses '..' as necessary in the returned string. +=============================================================================== +*/ +MString VTLinker::MakeTitle(const MString& path) +{ + MString temp; + int index; + + // Search for the last directory separator token + index = path.ReverseFind('/'); + if (index == -1) + return path; + + return path.Right(path.GetLength() - index - 1); +} + /* ============================================================================ This routine reads the ELF section specified by the Elf32_Shdr into the @@ -969,16 +1122,20 @@ CObjFile object provided. int VTLinker::ReadSectionData(FILE* fd, CObjFile* pObjFile, CObjFileSection* pFileSection) { - int bytes = 0, count, c; - MString err; - Elf32_Shdr* pHdr = &pFileSection->m_ElfHeader; - Elf32_Sym* pSym; - Elf32_Rel* pRel; - + int bytes = 0, count, c; + MString err; + Elf32_Shdr* pHdr = &pFileSection->m_ElfHeader; + Elf32_Sym* pSym; + Elf32_Rel* pRel; + CObjSymFile* pSymFile; if (pHdr->sh_offset != 0) fseek(fd, pHdr->sh_offset, SEEK_SET); + // Set the Section type, size, etc. + pFileSection->m_Type = pHdr->sh_type; + pFileSection->m_Size = pHdr->sh_size; + // Test for null header switch (pHdr->sh_type) { @@ -1003,13 +1160,34 @@ int VTLinker::ReadSectionData(FILE* fd, CObjFile* pObjFile, m_Errors.Add(err); return FALSE; } + + // Test if the section link points to itself + if (pFileSection->m_Index == pHdr->sh_link) + { + if (strcmp(&pFileSection->m_pStrTab[pHdr->sh_name], ".shstrtab") == 0) + if (pObjFile->m_pShStrTab == NULL) + pObjFile->m_pShStrTab = pFileSection->m_pStrTab; + } + + // Search for the symbol string table + if (pObjFile->m_pStrTab == NULL) + { + if (pObjFile->m_pShStrTab != NULL) + if (strcmp(&pObjFile->m_pShStrTab[pHdr->sh_name], ".strtab") == 0) + { + pObjFile->m_pStrTab = pFileSection->m_pStrTab; + } + } break; case SHT_SYMTAB: + if (pObjFile->m_pSymSect == NULL) + pObjFile->m_pSymSect = pFileSection; + count = pHdr->sh_size / sizeof(Elf32_Sym); for (c = 0; c < count; c++) { - // Allocate new symbol and rezd data from the file + // Allocate new symbol and read data from the file pSym = new Elf32_Sym; if (pSym != NULL) bytes = fread(pSym, 1, sizeof(Elf32_Sym), fd); @@ -1027,15 +1205,65 @@ int VTLinker::ReadSectionData(FILE* fd, CObjFile* pObjFile, // Add the symbol to the array pFileSection->m_Symbols.Add((VTObject *) pSym); + + // Add PUBLIC symbols to the global symbol table + if ((pObjFile->m_pStrTab != NULL) && (ELF32_ST_BIND(pSym->st_info) == STB_GLOBAL)) + { + // Test if it already exists + if (m_Symbols.Lookup(&pObjFile->m_pStrTab[pSym->st_name], (VTObject *&) pSymFile)) + { + // Error! Duplicate global symbol + MString title1 = MakeTitle(pObjFile->m_Name); + MString title2 = MakeTitle(pSymFile->m_pObjFile->m_Name); + err.Format("%sPUBLIC symbol %s duplicated in file %s. First encountered in %s", + gsEdl, &pObjFile->m_pStrTab[pSym->st_name], (const char *) title1, + (const char *) title2); + m_Errors.Add(err); + continue; + } + + // Add the symbol to our table + pSymFile = new CObjSymFile(); + pSymFile->m_pObjFile = pObjFile; + pSymFile->m_pObjSection = pFileSection; + pSymFile->m_pSym = pSym; + pSymFile->m_pName = &pObjFile->m_pStrTab[pSym->st_name]; + m_Symbols[&pObjFile->m_pStrTab[pSym->st_name]] = pSymFile; + } } break; case SHT_PROGBITS: // Allocate space for bytes and read from file pFileSection->m_pProgBytes = new char[pHdr->sh_size]; + pFileSection->m_Size = pHdr->sh_size; if (pFileSection->m_pProgBytes != NULL) bytes = fread(pFileSection->m_pProgBytes, 1, pHdr->sh_size, fd); + // Assign the section type + if ((pHdr->sh_flags & SHF_8085_ABSOLUTE) && + (pHdr->sh_type == SHT_PROGBITS)) + { + // Type is ASEG + pFileSection->m_Type = ASEG; + } + + // Test if segment is CSEG + else if ((pHdr->sh_flags & (SHF_ALLOC | SHF_EXECINSTR | + SHF_WRITE)) == (SHF_ALLOC | SHF_EXECINSTR)) + { + // Type is CSEG + pFileSection->m_Type = CSEG; + } + + // Test if segment is DSEG + else if ((pHdr->sh_flags & (SHF_ALLOC | SHF_EXECINSTR | + SHF_WRITE)) == SHF_WRITE) + { + // Type is DSEG + pFileSection->m_Type = DSEG; + } + // Test for error during read if (bytes != pHdr->sh_size) { @@ -1047,6 +1275,7 @@ int VTLinker::ReadSectionData(FILE* fd, CObjFile* pObjFile, break; case SHT_REL: + // Now loop through all all relocation elements count = pHdr->sh_size / sizeof(Elf32_Rel); for (c = 0; c < count; c++) { @@ -1075,6 +1304,52 @@ int VTLinker::ReadSectionData(FILE* fd, CObjFile* pObjFile, return TRUE; } +/* +============================================================================ +This routine loops through all sections of all object files and assignes +the m_Name variable based on the sections name index into the string +table read from the file. +============================================================================ +*/ +int VTLinker::AssignSectionNames() +{ + CObjFile* pObjFile; + int count, c; + CObjFileSection* pFileSection; + bool segmentFound = false; + char * pName; + POSITION pos; + MString fileName; + + // Find the segment to be located. Loop through each objFile... + pos = m_ObjFiles.GetStartPosition(); + while (pos != NULL) + { + // Get next ObjectFile pointer + m_ObjFiles.GetNextAssoc(pos, fileName, (VTObject *&) pObjFile); + + if (pObjFile->m_pShStrTab == NULL) + continue; + + // Loop through this file's obj sections and search for each segment + count = pObjFile->m_FileSections.GetSize(); + for (c = 0; c < count; c++) + { + // Get a pointer to the segment data so we know which index it is + pFileSection = (CObjFileSection *) pObjFile->m_FileSections[c]; + + // Point to start of string table and loop to find the correct index + pName = &pObjFile->m_pShStrTab[pFileSection->m_ElfHeader.sh_name]; + + // Finally, assign the name to the segment + if (*pName != '\0') + pFileSection->m_Name = pName; + } + } + + return TRUE; +} + /* ============================================================================ This routine attempts to open and read each of the files to be linked. @@ -1112,7 +1387,7 @@ int VTLinker::ReadObjFiles() for (x = 0; x < dirs; x++) { // Prepend the next object directory - temp = m_ObjDirs[c] + pFile; + temp = m_ObjDirs[x] + pFile; fd = fopen((const char *) temp, "rb"); if (fd != NULL) break; @@ -1131,6 +1406,9 @@ int VTLinker::ReadObjFiles() ReadElfHeaders(fd, temp); } + // Assign Section Names + AssignSectionNames(); + if (m_Errors.GetSize() != 0) return FALSE; @@ -1139,107 +1417,1157 @@ int VTLinker::ReadObjFiles() /* ============================================================================ -This function locates segments from the input files as per the linker script -regions that have been defined. +This function locates a specific named segment into a named region. ============================================================================ */ -int VTLinker::LocateSegments() +int VTLinker::LocateSegmentIntoRegion(MString& region, MString& segment, bool atEnd) { - POSITION pos; -// CObjSegement* pSeg; + MString err; CObjFile* pObjFile; - CObjFileSection* pFileSect; - int sect, sectCount; - MString err, filename; + int count, c; + CObjFileSection* pFileSection; + bool segmentFound = false; + POSITION pos; + MString fileName; - // Loop for all object files loaded + // Find the segment to be located. Loop through each objFile... pos = m_ObjFiles.GetStartPosition(); while (pos != NULL) { - // Get pointer to this object file's data - m_ObjFiles.GetNextAssoc(pos, filename, (VTObject *&) pObjFile); + // Get next ObjectFile pointer + m_ObjFiles.GetNextAssoc(pos, fileName, (VTObject *&) pObjFile); + segmentFound = false; - // Loop through all segments and find a place to locate them - sectCount = pObjFile->m_FileSections.GetSize(); - for (sect = 0; sect < sectCount; sect++) + // Loop through this file's obj sections and search for the segment + count = pObjFile->m_FileSections.GetSize(); + for (c = 0; c < count; c++) { - // Get pointer to next file section for this file - pFileSect = (CObjFileSection *) pObjFile->m_FileSections[sect]; + pFileSection = (CObjFileSection *) pObjFile->m_FileSections[c]; + if (pFileSection->m_Name == segment && pFileSection->m_ElfHeader.sh_type == SHT_PROGBITS) + { + // Segment found + segmentFound = true; + break; + } + } + if (!segmentFound) + continue; - // Test if file section is a segment - if ((pFileSect->m_ElfHeader.sh_type != SHT_PROGBITS) && - (pFileSect->m_ElfHeader.sh_type != SHT_NOBITS)) + if (!LocateSegmentIntoRegion(region, pFileSection, atEnd)) + return FALSE; + } + + return TRUE; +} + +/* +============================================================================ +This function locates a specific named segment into a named region. +============================================================================ +*/ +int VTLinker::LocateSegmentIntoRegion(MString& region, CObjFileSection* pFileSection, + bool atEnd) +{ + CLinkRgn* pLinkRgn; + MString err; + int c, locateAddr, segSize; + bool segmentFound = false; + MString fileName; + LinkAddrRange* pAddrRange; + static const char* sSegType[] = { "ASEG", "CSEG", "DSEG" }; + MString segment = pFileSection->m_Name; + + // Find the region where we will locate the segment + if (!m_LinkRegions.Lookup((const char *) region, (VTObject *&) pLinkRgn)) + { + // Report error of unknown segment type + err.Format("%sLink region %s not defined trying to locate segment %s", gsEdl, (const char *) region, + (const char *) pFileSection->m_Name); + m_Errors.Add(err); + return FALSE; + } + + // Check if location into this region is complete and simply exit if it is + if (pLinkRgn->m_LocateComplete) + return TRUE; + + // Check if region is valid yet (it may have a START with an "atend" specification + // that hasn't been met yet). + if (pLinkRgn->m_pFirstAddrRange->startAddr < 0) + return TRUE; + + // Validate the segment isn't already located + if (pFileSection->m_Located) + { + err.Format("%sSegment %s specified in multiple locations in linker script", gsEdl, + (const char *) segment); + m_Errors.Add(err); + return FALSE; + } + + // Validate the segment is the proper type for the region + if (((((pFileSection->m_Type == ASEG) || (pFileSection->m_Type == CSEG)) && (pLinkRgn->m_Type != LKR_CMD_CODE)) || + ((pFileSection->m_Type == DSEG) && (pLinkRgn->m_Type != LKR_CMD_DATA))) && (pLinkRgn->m_Type != LKR_CMD_MIXED)) + { + err.Format("%sSegment %s type (%s) does not match region %s", gsEdl, (const char *) segment, + sSegType[pFileSection->m_Type], (const char *) region); + m_Errors.Add(err); + return FALSE; + } + + // If the Link Region is protected, ensure the Segment name and Link Region name match + if (pLinkRgn->m_Protected && (pFileSection->m_Name != pLinkRgn->m_Name)) + { + err.Format("%sCannot place segment %s into protected region %s", gsEdl, (const char *) segment, + (const char *) region); + m_Errors.Add(err); + return FALSE; + } + + // Get the size of the segment to be located + segSize = pFileSection->m_Size; + + // If segment has the ATEND attribte, then force the atend parameter + if (pLinkRgn->m_AtEnd) + atEnd = TRUE; + + if (pFileSection->m_Type == ASEG) + { + // Place at an absolute location + // Get pointer to Link Rgn's first AddrRange + pAddrRange = pLinkRgn->m_pFirstAddrRange; + locateAddr = pFileSection->m_ElfHeader.sh_addr; + + // Find the first region where this segment is supposed to live + while (pAddrRange && (pAddrRange->endAddr < locateAddr)) + { + // Get pointer to next AddrRange + pAddrRange = pAddrRange->pNext; + } + + // Validate the range was found + if ((pAddrRange == NULL) || (pAddrRange->startAddr > locateAddr) || + (locateAddr + segSize > pAddrRange->endAddr)) + { + err.Format("%sNo Link Range found for ASEG %s (addr=%d, size=%d)", gsEdl, + (const char *) segment, locateAddr, segSize); + m_Errors.Add(err); + return FALSE; + } + + // Validate we don't have overlapping ASEGs + for (c = locateAddr; c < locateAddr + segSize; c++) + { + if (m_SegMap[c] != NULL) { - continue; + err.Format("%sSegment %s overlaps segment %s at address %d", gsEdl, + (const char *) segment, (const char *) m_SegMap[c]->m_Name, c); + m_Errors.Add(err); + return FALSE; } + } + } + else + { + // Locate the segment into the region anywhere. Find the address where it will live + if (atEnd) + { + // Get pointer to Link Rgn's first AddrRange + pAddrRange = pLinkRgn->m_pLastAddrRange; - // Test if segment is ASEG - if ((pFileSect->m_ElfHeader.sh_flags & SHF_8085_ABSOLUTE) && - (pFileSect->m_ElfHeader.sh_type == SHT_PROGBITS)) + // Find the first region with enough space to hold the segment + while (pAddrRange && (pAddrRange->endLocateAddr - pAddrRange->nextLocateAddr < segSize)) { - LocateAsegSegment(pFileSect); + // Get pointer to next AddrRange + pAddrRange = pAddrRange->pPrev; } - // Test if segment is CSEG - else if ((pFileSect->m_ElfHeader.sh_flags & (SHF_ALLOC | SHF_EXECINSTR | - SHF_WRITE)) == (SHF_ALLOC | SHF_EXECINSTR)) + // Test if a segment large enough was found + if (pAddrRange == NULL) { - LocateCsegSegment(pFileSect); + err.Format("%sLink Range %s too small for segment %s", gsEdl, (const char *) region, + (const char *) segment); + m_Errors.Add(err); + return FALSE; } - // Test if segment is DSEG - else if ((pFileSect->m_ElfHeader.sh_flags & (SHF_ALLOC | SHF_EXECINSTR | - SHF_WRITE)) == SHF_WRITE) + // Update region's nextLocateAddr + locateAddr = pAddrRange->endLocateAddr - segSize; + pAddrRange->endLocateAddr -= segSize; + } + else + { + // Get pointer to Link Rgn's first AddrRange + pAddrRange = pLinkRgn->m_pFirstAddrRange; + + // Find the first region with enough space to hold the segment + while (pAddrRange && (pAddrRange->endLocateAddr - pAddrRange->nextLocateAddr < segSize)) { - LocateDsegSegment(pFileSect); + // Get pointer to next AddrRange + pAddrRange = pAddrRange->pNext; } - // Unknown segment type - else + // Test if a segment large enough was found + if (pAddrRange == NULL) { - // Report error of unknown segment type - err.Format("%sUnknown segment type in %s", gsEdl, (const char *) filename); + err.Format("%sLink Range %s too small for segment %s", gsEdl, (const char *) region, + (const char *) segment); m_Errors.Add(err); + return FALSE; } + + // Update region's nextLocateAddr + locateAddr = pAddrRange->nextLocateAddr; + pAddrRange->nextLocateAddr += segSize; } } - return TRUE; -} + // Finally, locate the segment + for (c = locateAddr; c < locateAddr + segSize; c++) + { + // Mark the Segment map as being allocated to this file section + m_SegMap[c] = pFileSection; + } + + // Mark the segment as located + pFileSection->m_LocateAddr = locateAddr; + pFileSection->m_Located = true; + + if (pFileSection->m_Type == DSEG) + m_TotalDataSpace += segSize; + else + m_TotalCodeSpace += segSize; -/* -============================================================================ -Tries to locate the given ASEG segment -============================================================================ -*/ -int VTLinker::LocateAsegSegment(CObjFileSection* pFileSect) -{ return TRUE; } /* ============================================================================ -Tries to locate the given CSEG segment +This function locates segments based on ORDER. ============================================================================ */ -int VTLinker::LocateCsegSegment(CObjFileSection* pFileSect) +int VTLinker::LocateOrderedSegments() { - return TRUE; + POSITION pos; + MString name; + MStringArray* pSegmentNames; + int count, c; + int success = TRUE; + + pos = m_LinkOrderList.GetStartPosition(); + while (pos != NULL) + { + // Get pointer to this entry's data + m_LinkOrderList.GetNextAssoc(pos, name, (VTObject *&) pSegmentNames); + + // Loop through each entry and locate that segment + count = pSegmentNames->GetSize(); + for (c = 0; c < count; c++) + { + // Now locate this segment into the named region + if (!LocateSegmentIntoRegion(name, pSegmentNames->GetAt(c))) + success = FALSE; + } + } + + return success; } /* ============================================================================ -Tries to locate the given DSEG segment +This function locates segments based on ENDSWITH. ============================================================================ */ -int VTLinker::LocateDsegSegment(CObjFileSection* pFileSect) +int VTLinker::LocateEndsWithSegments() { - return TRUE; -} + POSITION pos; + MString name; + MStringArray* pSegmentNames; + int count, c; + int success = TRUE; + + pos = m_LinkEndsWithList.GetStartPosition(); + while (pos != NULL) + { + // Get pointer to this entry's data + m_LinkEndsWithList.GetNextAssoc(pos, name, (VTObject *&) pSegmentNames); + + // Loop through each entry and locate that segment + count = pSegmentNames->GetSize(); + for (c = count-1; c >= 0; c--) + { + printf("Locating ENDSWITH segment %s\n", (const char *) pSegmentNames->GetAt(c)); + // Now locate this segment into the named region + if (!LocateSegmentIntoRegion(name, pSegmentNames->GetAt(c), true)) + success = FALSE; + } + } + + return success; +} + +/* +============================================================================ +This function locates segments based on CONTAINS. +============================================================================ +*/ +int VTLinker::LocateContainsSegments() +{ + POSITION pos; + MString name; + MStringArray* pSegmentNames; + int count, c; + int success = TRUE; + + pos = m_LinkContainsList.GetStartPosition(); + while (pos != NULL) + { + // Get pointer to this entry's data + m_LinkContainsList.GetNextAssoc(pos, name, (VTObject *&) pSegmentNames); + + // Loop through each entry and locate that segment + count = pSegmentNames->GetSize(); + for (c = 0; c < count; c++) + { + // Now locate this segment into the named region + if (!LocateSegmentIntoRegion(name, pSegmentNames->GetAt(c))) + success = FALSE; + } + } + + return success; +} + +/* +============================================================================ +This function locates segments from the input files as per the linker script +regions that have been defined. +============================================================================ +*/ +int VTLinker::LocateNondependantSegments() +{ + POSITION pos; + CObjFile* pObjFile; + CObjFileSection* pFileSect; + int sect, sectCount; + MString err, filename; + int success = TRUE; + MString aseg = ".aseg"; + MString data = ".data"; + MString text = ".text"; + + // Exit if error has occurred + if (m_Errors.GetSize() != 0) + return FALSE; + + // Locate segments based on ORDER from the Linker Script + success = LocateOrderedSegments(); + + // Locate segments based on ENDSWITH from the Linker Script + if (!LocateEndsWithSegments()) + success = FALSE; + + // Locate segments based on CONTAINS from the Linker Script + if (!LocateContainsSegments()) + success = FALSE; + + // Loop for all object files loaded and locate any that have not been located yet + pos = m_ObjFiles.GetStartPosition(); + while (pos != NULL) + { + // Get pointer to this object file's data + m_ObjFiles.GetNextAssoc(pos, filename, (VTObject *&) pObjFile); + + // Loop through all segments and find a place to locate them + sectCount = pObjFile->m_FileSections.GetSize(); + for (sect = 0; sect < sectCount; sect++) + { + CLinkRgn* pLinkRgn; + + // Get pointer to next file section for this file + pFileSect = (CObjFileSection *) pObjFile->m_FileSections[sect]; + + // Test if file section is a segment + if ((pFileSect->m_ElfHeader.sh_type != SHT_PROGBITS) && + (pFileSect->m_ElfHeader.sh_type != SHT_NOBITS)) + { + continue; + } + + // Test if this segment has already been located + if (pFileSect->m_Located) + { + continue; + } + + printf("Locating segment %s from file %s\n", (const char *) pFileSect->m_Name, + (const char *) pObjFile->m_Name); + + // Test if the segment has a named link region + if (m_LinkRegions.Lookup((const char *) pFileSect->m_Name, (VTObject *&) pLinkRgn)) + { + // Locate the segment into the region with the same name + LocateSegmentIntoRegion(pLinkRgn->m_Name, pFileSect); + } + + // Test if segment is ASEG + else if ((pFileSect->m_ElfHeader.sh_flags & SHF_8085_ABSOLUTE) && + (pFileSect->m_ElfHeader.sh_type == SHT_PROGBITS)) + { + // Locate ASEGs into the .aseg linker region + LocateSegmentIntoRegion(aseg, pFileSect); + } + + // Test if segment is CSEG + else if ((pFileSect->m_ElfHeader.sh_flags & (SHF_ALLOC | SHF_EXECINSTR | + SHF_WRITE)) == (SHF_ALLOC | SHF_EXECINSTR)) + { + // Locate CSEGs into the .text linker region + LocateSegmentIntoRegion(text, pFileSect); + } + + // Test if segment is DSEG + else if ((pFileSect->m_ElfHeader.sh_flags & (SHF_ALLOC | SHF_EXECINSTR | + SHF_WRITE)) == SHF_WRITE) + { + // Locate DSEGs into the .data linker region + LocateSegmentIntoRegion(data, pFileSect); + } + + // Unknown segment type + else + { + // Report error of unknown segment type + err.Format("%sUnknown segment type in %s", gsEdl, (const char *) filename); + m_Errors.Add(err); + } + } + } + + return TRUE; +} + +/* +============================================================================ +This function locates segments from the input files as per the linker script +regions that have been defined. It calls the LocateDependantSegments function +repeated, progressively resolving segment dependencies until all dependencies +have been resolved. This takes care of regions whose START address is relative +to the end ("atend") of another segment. +============================================================================ +*/ +int VTLinker::LocateSegments() +{ + int allDependenciesMet = FALSE; + int newResolve; + unsigned short lastAddr; + int c; + CLinkRgn* pLinkRgn; + POSITION pos; + MString name; + + // Loop until all segment dependencies resolved + while (!allDependenciesMet) + { + // Locate segments into non-dependant regions + LocateNondependantSegments(); + + // Mark all non-dependant regions as located + pos = m_LinkRegions.GetStartPosition(); + while (pos) + { + // Get next link region + m_LinkRegions.GetNextAssoc(pos, name, (VTObject *&) pLinkRgn); + if (pLinkRgn->m_pFirstAddrRange->startAddr >= 0) + pLinkRgn->m_LocateComplete = TRUE; + } + + // Check if any more dependencies to resolve. We will stop at the + // first resolved dependency and locate segments again. This takes + // care of the case when multiple regions are dependent on the same + // "atend(.regionname)". + newResolve = FALSE; + pos = m_LinkRegions.GetStartPosition(); + while (pos) + { + // Get next link region + m_LinkRegions.GetNextAssoc(pos, name, (VTObject *&) pLinkRgn); + + // Test if this region has been located completely + if (pLinkRgn->m_pFirstAddrRange->startAddr < 0) + { + // This region has a dependency still. Test if it's dependant + // region has been located (and has a valid start / end address) + CLinkRgn* pDepLinkRgn; + if (m_LinkRegions.Lookup((const char *) pLinkRgn->m_AtEndRgn, (VTObject *&) pDepLinkRgn)) + { + // Test if the dependant link region has been located + if (pDepLinkRgn->m_LocateComplete) + { + // Resolve the dependency by locating the link region at the + // end of the dependant region + lastAddr = pDepLinkRgn->m_pLastAddrRange->endAddr+1; + for (c = pDepLinkRgn->m_pLastAddrRange->endAddr; c >= + pDepLinkRgn->m_pLastAddrRange->startAddr; c--) + { + // Find the last address used by the last address range + if (m_SegMap[c] != NULL) + break; + lastAddr--; + } + + pLinkRgn->m_pFirstAddrRange->startAddr = lastAddr; + pLinkRgn->m_pFirstAddrRange->nextLocateAddr = lastAddr; + + // Test if the link region linked-list needs to be re-ordered + + // Indiacate a new dependency has been resolved and exit the while loop + newResolve = TRUE; + break; + } + } + } + } + + // Check if any new dependencies resolved + if (newResolve == FALSE) + allDependenciesMet = TRUE; + } + + return TRUE; +} + +/* +============================================================================ +Now that all segments have been located, this function assigns physical +addresses to local values, such as data, jump and call addresses, etc. +============================================================================ +*/ +CObjFileSection* VTLinker::FindRelSection(CObjFile* pObjFile, Elf32_Rel* pRel) +{ + int sectCount, sect; + CObjFileSection* pFileSect; + CObjFileSection* pRelSect; + + pRelSect = NULL; + sectCount = pObjFile->m_FileSections.GetSize(); + for (sect = 0; sect < sectCount; sect++) + { + // Loop through relocation segments + pFileSect = (CObjFileSection *) pObjFile->m_FileSections[sect]; + if (pFileSect->m_ElfHeader.sh_offset < pRel->r_offset) + { + // Validate the section type + if ((ELF32_R_TYPE(pRel->r_info) == SR_ADDR_XLATE) && + (pFileSect->m_ElfHeader.sh_type != SHT_PROGBITS)) + continue; + + // If no rel section assigned yet, just assign it + if (pRelSect == NULL) + pRelSect = pFileSect; + + // Else find the nearest section to the offset + else if (pRel->r_offset - pFileSect->m_ElfHeader.sh_offset < + pRel->r_offset - pRelSect->m_ElfHeader.sh_offset) + pRelSect = pFileSect; + } + } + + return pRelSect; +} + +/* +============================================================================ +Now that all segments have been located, this function assigns physical +addresses to local values, such as data, jump and call addresses, etc. +============================================================================ +*/ +int VTLinker::ResolveLocals() +{ + POSITION pos; + CObjFile* pObjFile; + CObjFileSection* pFileSect; + CObjFileSection* pRelSect; + int sect, sectCount, rel, relCount; + MString err, filename; + + // Exit if error has occurred + if (m_Errors.GetSize() != 0) + return FALSE; + + // Loop for all object files loaded + pos = m_ObjFiles.GetStartPosition(); + while (pos != NULL) + { + // Get pointer to this object file's data + m_ObjFiles.GetNextAssoc(pos, filename, (VTObject *&) pObjFile); + + // Loop through all segments and look for relocation info + sectCount = pObjFile->m_FileSections.GetSize(); + for (sect = 0; sect < sectCount; sect++) + { + // Loop through relocation segments + pFileSect = (CObjFileSection *) pObjFile->m_FileSections[sect]; + relCount = pFileSect->m_Reloc.GetSize(); + for (rel = 0; rel < relCount; rel++) + { + // Process this relocation item + Elf32_Rel* pRel = (Elf32_Rel *) pFileSect->m_Reloc[rel]; + if (ELF32_R_TYPE(pRel->r_info) == SR_ADDR_XLATE) + { + CObjFileSection* pRefSect = (CObjFileSection *) pObjFile->m_FileSections[pFileSect->m_ElfHeader.sh_info]; + pRelSect = FindRelSection(pObjFile, pRel); + if (pRelSect != NULL) + { + // calculate the offset into the section + int offset = pRel->r_offset - pRelSect->m_ElfHeader.sh_offset; + + // Get the relative jump address from the program bits + unsigned short addr = (((unsigned short) pRelSect->m_pProgBytes[offset]) & 0xFF) | (pRelSect->m_pProgBytes[offset+1] << 8); + + // Update the address based on the segments locate address +// addr += pRelSect->m_LocateAddr; + addr += pRefSect->m_LocateAddr; + + // Update the translated address in the ProgBits + pRelSect->m_pProgBytes[offset] = addr & 0xFF; + pRelSect->m_pProgBytes[offset + 1] = addr >> 8; + + // Change the relocation type so we know we have translated this item + pRel->r_info = ELF32_R_INFO(0, SR_ADDR_PROCESSED); + } + else + { + err.Format("%sInvalid relocation at offset %d", gsEdl, pRel->r_offset); + m_Errors.Add(err); + } + } + } + } + } + + return TRUE; +} + +/* +============================================================================ +Now resolved all extern symbols. +============================================================================ +*/ +int VTLinker::ResolveExterns() +{ + POSITION pos; + CObjFile* pObjFile; + CObjFileSection* pFileSect; + int sect, sectCount, rel, relCount; + MString err, filename; + + // Exit if error has occurred + if (m_Errors.GetSize() != 0) + return FALSE; + + // Loop for all object files loaded + pos = m_ObjFiles.GetStartPosition(); + while (pos != NULL) + { + // Get pointer to this object file's data + m_ObjFiles.GetNextAssoc(pos, filename, (VTObject *&) pObjFile); + + // Loop through all segments and look for relocation info + sectCount = pObjFile->m_FileSections.GetSize(); + for (sect = 0; sect < sectCount; sect++) + { + // Loop through relocation segments + pFileSect = (CObjFileSection *) pObjFile->m_FileSections[sect]; + + if (pFileSect->m_Type != SHT_REL) + continue; + + CObjFileSection* pObjSect = (CObjFileSection *) pObjFile->m_FileSections[pFileSect->m_ElfHeader.sh_info]; + relCount = pFileSect->m_Reloc.GetSize(); + for (rel = 0; rel < relCount; rel++) + { + // Process this relocation item + Elf32_Rel* pRel = (Elf32_Rel *) pFileSect->m_Reloc[rel]; + + // Test if this is an EXTERN relocation type + if (ELF32_R_TYPE(pRel->r_info) == SR_EXTERN) + { + // Get the EXTERN symbol name + if (pObjFile->m_pStrTab != NULL) + { + // First get symbol index from relocation item + int index = ELF32_R_SYM(pRel->r_info); + + // Now get pointer to symbol data + Elf32_Sym* pSym = (Elf32_Sym *) pObjFile->m_pSymSect->m_Symbols[index]; + + // Next lookup symbol name in string table + const char *pSymName = &pObjFile->m_pStrTab[pSym->st_name]; + + // Search for the symbol name in the global map + CObjSymFile* pSymFile; + if (m_Symbols.Lookup(pSymName, (VTObject *&) pSymFile)) + { + // PUBLIC symbol found! Now perform the link + // First get a pointer to the section referenced by the symbol + CObjFileSection* pSymSect = (CObjFileSection *) pSymFile->m_pObjFile->m_FileSections[pSymFile->m_pSym->st_shndx]; + + // Calculate the value of the EXTERN symbol + unsigned short value = (unsigned short) pSymFile->m_pSym->st_value; + if (pSymSect->m_Type != ASEG) + value +=(unsigned short) pSymSect->m_LocateAddr; + + // Calculate the address where we update with the symbol's value + if (pRel->r_offset + 1 >= (unsigned short) pObjSect->m_Size) + { + err.Format("Invalid relocation offset for section %s, symbol = %s, offset = %d, size = %d\n", + (const char *) pObjSect->m_Name, (const char *) pSymName, pRel->r_offset, pObjSect->m_Size); + m_Errors.Add(err); + } + else + { + char * pAddr = pObjSect->m_pProgBytes + pRel->r_offset; + + // Update the code + *pAddr++ = value & 0xFF; + *pAddr = value >> 8; + } + } + else + { + MString title = MakeTitle(pObjFile->m_Name); + err.Format("%sUnresolved EXTERN symbol %s referenced in file %s", gsEdl, + pSymName, (const char *) title); + m_Errors.Add(err); + } + } + else + { + MString title = MakeTitle(pObjFile->m_Name); + err.Format("%sFile %s has no string table", gsEdl, (const char *) title); + m_Errors.Add(err); + } + } + } + } + } + + return TRUE; +} /* ============================================================================ -The parser calls this function when it detects a list output pragma. +Generate the output file(s). For .CO projects, this will be the .CO file, +for library files, a .lib, and for ROM projects, it will be a HEX file. +============================================================================ +*/ +int VTLinker::GenerateOutputFile() +{ + int startAddr, endAddr, entryAddr; + int c; + unsigned char temp; + const int addrSize = sizeof(m_SegMap) / sizeof(void *); + MString err; + CObjSymFile* pSymFile; + MString filename = m_RootPath + "/" + m_OutputName; + + // Exit if error has occurred + if (m_Errors.GetSize() != 0) + return FALSE; + + // Find first address of output + for (startAddr = 0; startAddr < addrSize; startAddr++) + if (m_SegMap[startAddr] != NULL) + break; + + // Find last address of output + for (endAddr = addrSize - 1; endAddr >= 0; endAddr--) + { + if (m_SegMap[endAddr] != NULL) + { + // Test if this is the ".bss" segemnt - it doesn't get written + // to the output file + if (m_SegMap[endAddr]->m_Name == ".bss") + continue; + break; + } + } + + // If build type is .CO, then create the .CO file + if (m_ProjectType == VT_PROJ_TYPE_CO) + { + // Determine the entry address. If an ENTRY specification was given + // in the linker script, then find that symbol, otherwise use the + // first address of the program + entryAddr = startAddr; + if (!m_EntryLabel.IsEmpty()) + { + // Search the global symbol table for the PUBLIC label + if (m_Symbols.Lookup((const char *) m_EntryLabel, (VTObject *&) pSymFile)) + { + // PUBLIC symbol found! Now perform the link + // First get a pointer to the section referenced by the symbol + CObjFileSection* pSymSect = (CObjFileSection *) pSymFile->m_pObjFile->m_FileSections[pSymFile->m_pSym->st_shndx]; + + // Calculate the value of the EXTERN symbol + entryAddr = (unsigned short) (pSymFile->m_pSym->st_value + pSymSect->m_LocateAddr); + } + else + { + err.Format("%sUnresolved entry address %s - not defined by any object file", gsEdl, (const char *) m_EntryLabel); + m_Errors.Add(err); + return FALSE; + } + } + + // Report that we are generating the output file + if (m_pStdoutFunc != NULL) + { + MString msg; + msg.Format("Generating file %s, start=0x%0X, entry=0x%0X, length=%d\n", (const char *) m_OutputName, startAddr, entryAddr, endAddr - startAddr + 1); + m_pStdoutFunc(m_pStdoutContext, (const char *) msg); + } + + // Open the output file for output + FILE* fd; + if ((fd = fopen((const char *) filename, "wb")) == NULL) + { + err.Format("%sUnable to open output file %s", gsEdl, (const char *) m_OutputName); + m_Errors.Add(err); + return FALSE; + } + + // Write the .CO header + temp = (unsigned char) (startAddr & 0xFF); + fwrite(&temp, 1, sizeof(temp), fd); + temp = (unsigned char) (startAddr >> 8); + fwrite(&temp, 1, sizeof(temp), fd); + + // Write the length + temp = (unsigned char) ((endAddr - startAddr + 1) & 0xFF); + fwrite(&temp, 1, sizeof(temp), fd); + temp = (unsigned char) ((endAddr - startAddr + 1) >> 8); + fwrite(&temp, 1, sizeof(temp), fd); + + // Write the entry address + temp = (unsigned char) (entryAddr & 0xFF); + fwrite(&temp, 1, sizeof(temp), fd); + temp = (unsigned char) (entryAddr >> 8); + fwrite(&temp, 1, sizeof(temp), fd); + + // Finally write the output data to the file + unsigned char zero = 0; + for (c = startAddr; c <= endAddr; ) + { + // Write the next block of bytes + CObjFileSection *pSect = m_SegMap[c]; + fwrite(pSect->m_pProgBytes, 1, pSect->m_Size, fd); + + // Update to the next byte to write + c += pSect->m_Size; + + while ((m_SegMap[c] == NULL || m_SegMap[endAddr]->m_Name == ".bss") && + c <= endAddr) + { + fwrite(&zero, 1, 1, fd); + c++; + } + } + + // Close the output file + fclose(fd); + } + + // Test if project type is Assembly ROM and create HEX output if it is + else if (m_ProjectType == VT_PROJ_TYPE_ROM) + { + // Report that we are generating the output file + if (m_pStdoutFunc != NULL) + { + MString msg; + msg.Format("Generating HEX file %s\n", (const char *) m_OutputName); + m_pStdoutFunc(m_pStdoutContext, (const char *) msg); + } + + // Open the output file for output + FILE* fd; + if ((fd = fopen((const char *) filename, "wb")) == NULL) + { + err.Format("%sUnable to open output file %s", gsEdl, (const char *) filename); + m_Errors.Add(err); + return FALSE; + } + + // Allocate a 32K memory region to hold the ROM contents + char * pRom = new char[32768]; + + // Fill contents with zero + for (c = 0; c < 32767; c++) + pRom[c] = 0; + + // Copy the output data to the ROM storage + for (c = 0; c < 32768; ) + { + // Skip empty space in the link map + while (m_SegMap[c] == NULL && c < 32768) + c++; + + // Write the next block of bytes + CObjFileSection *pSect = m_SegMap[c]; + if (pSect != NULL) + { + memcpy(&pRom[c], pSect->m_pProgBytes, pSect->m_Size); + + // Update to the next byte to write + c += pSect->m_Size; + } + } + + // Write the ROM data to the HEX file + save_hex_file_buf(pRom, 0, 32768, 0, fd); + + // Close the file + fclose(fd); + + // Write the data out as a REX .BX file also... + int dot = m_OutputName.ReverseFind('.'); + MString bxFile = m_OutputName.Left(dot) + ".bx"; + + // Report that we are generating the output file + if (m_pStdoutFunc != NULL) + { + MString msg; + msg.Format("Generating REX file %s\n", (const char *) bxFile); + m_pStdoutFunc(m_pStdoutContext, (const char *) msg); + } + filename = m_RootPath + "/" + bxFile; + + // Open the output file for output + if ((fd = fopen((const char *) filename, "wb")) == NULL) + { + err.Format("%sUnable to open output file %s", gsEdl, (const char *) filename); + m_Errors.Add(err); + return FALSE; + } + + // The REX BX file is a simple binary dump of the ROM contents + fwrite(pRom, 1, 32768, fd); + fclose(fd); + + // Delete the ROM memory + delete pRom; + } + + // We don't support Library output yet, but soon... + else if (m_ProjectType == VT_PROJ_TYPE_LIB) + { + } + return TRUE; +} + +/* +============================================================================ +Generates a map file if one was requested and no errors exist during the +assemble / link. +============================================================================ +*/ +int VTLinker::GenerateMapFile(void) +{ + MString err, filename; + FILE* fd; + int c, count; + int codeSize = 0, dataSize = 0; + VTObArray m_Sorted; + + // Exit if error has occurred + if (m_Errors.GetSize() != 0) + return FALSE; + + // Test if MAP file generation requested + if (m_LinkOptions.Find("-m") == -1) + return FALSE; + + // Okay, generate the map file, replacing any old one found + int dot = m_OutputName.ReverseFind('.'); + MString mapFile = m_OutputName.Left(dot) + ".map"; + + // Report that we are generating the output file + if (m_pStdoutFunc != NULL) + { + MString msg; + msg.Format("Generating MAP file %s\n", (const char *) mapFile); + m_pStdoutFunc(m_pStdoutContext, (const char *) msg); + } + filename = m_RootPath + "/" + mapFile; + + // Open the output file for output + if ((fd = fopen((const char *) filename, "wb")) == NULL) + { + err.Format("%sUnable to open output file %s", gsEdl, (const char *) filename); + m_Errors.Add(err); + return FALSE; + } + + fprintf(fd, " VirtualT %s, Linker\n", VERSION); + fprintf(fd, " Linker Map File - %s\n\n", (const char *) mapFile); + fprintf(fd, " Section Info\n"); + fprintf(fd, " Section Type Address End Addr Size(Bytes)\n"); + fprintf(fd, " --------- ------ ------- -------- ----------\n"); + + // Loop through the segment map and report the location of all segments + for (c = 0; c < 65536; ) + { + // Skip empty space in the link map + while (m_SegMap[c] == NULL && c < 65536) + c++; + + if (c == 65536) + break; + + // Write the next block of bytes + CObjFileSection *pSect = m_SegMap[c]; + if (pSect != NULL) + { + const char *pType; + if (pSect->m_Type == DSEG) + pType = "data"; + else + pType = "code"; + int size = pSect->m_Size; + + // Check segments after this one for the same name and concatenate them + // together in the map listing + CObjFileSection *pNextSect = m_SegMap[c + pSect->m_Size]; + int next = c + pSect->m_Size; + while (pNextSect != NULL) + { + if (pNextSect->m_Name == pSect->m_Name) + { + size += pNextSect->m_Size; + next += pNextSect->m_Size; + pNextSect = m_SegMap[next]; + } + else + break; + } + + fprintf(fd, "%25s %6s 0x%04x 0x%04x 0x%04x\n", (const char *) pSect->m_Name, + pType, pSect->m_LocateAddr, pSect->m_LocateAddr + size - 1, size); + + // Keep track of total code and data size + if (pSect->m_Type == DSEG) + dataSize += size; + else + codeSize += size; + + c += size; + } + } + + // Report the code and data usage + fprintf(fd, "\n\n Code size = %d, Data size = %d, Total = %d\n\n\n\n", + m_TotalCodeSpace, m_TotalDataSpace, m_TotalCodeSpace + m_TotalDataSpace); + + // Now report the symbols and their values + POSITION pos; + CObjSymFile* pObjSymFile; + MString key; + + fprintf(fd, " Symbols - Sorted by Name\n"); + fprintf(fd, " Name Address Type File\n"); + fprintf(fd, " --------- ------- --------- ---------\n"); + + // Loop through all Symbols and delete them + pos = m_Symbols.GetStartPosition(); + while (pos != NULL) + { + m_Symbols.GetNextAssoc(pos, key, (VTObject *&) pObjSymFile); + CObjSymFile* pComp; + + count = m_Sorted.GetSize(); + for (c = 0; c < count; c++) + { + pComp = (CObjSymFile *) m_Sorted[c]; + if (strcmp(pComp->m_pName, pObjSymFile->m_pName) > 0) + break; + } + m_Sorted.InsertAt(c, pObjSymFile); + } + + // Now print the sorted array + count = m_Sorted.GetSize(); + for (c = 0; c < count; c++) + { + pObjSymFile = (CObjSymFile *) m_Sorted[c]; + + CObjFileSection* pSymSect = (CObjFileSection *) pObjSymFile->m_pObjFile->m_FileSections[ + pObjSymFile->m_pSym->st_shndx]; + + fprintf(fd, "%25s 0x%04x %9s %s\n", pObjSymFile->m_pName, + pObjSymFile->m_pSym->st_value + pSymSect->m_LocateAddr, + ELF32_ST_TYPE(pObjSymFile->m_pSym->st_info) == STT_OBJECT ? "data" : "function", + (const char *) pObjSymFile->m_pObjFile->m_Name); + } + + // Remove all items from the sort array and re-sort by address + m_Sorted.RemoveAll(); + + fprintf(fd, "\n\n\n Symbols - Sorted by Address\n"); + fprintf(fd, " Name Address Type File\n"); + fprintf(fd, " --------- ------- --------- ---------\n"); + + // Loop through all Symbols and delete them + pos = m_Symbols.GetStartPosition(); + while (pos != NULL) + { + m_Symbols.GetNextAssoc(pos, key, (VTObject *&) pObjSymFile); + CObjFileSection* pSymSect = (CObjFileSection *) pObjSymFile->m_pObjFile->m_FileSections[ + pObjSymFile->m_pSym->st_shndx]; + CObjSymFile* pComp; + + count = m_Sorted.GetSize(); + for (c = 0; c < count; c++) + { + pComp = (CObjSymFile *) m_Sorted[c]; + CObjFileSection* pCompSect = (CObjFileSection *) pComp->m_pObjFile->m_FileSections[ + pComp->m_pSym->st_shndx]; + if (pComp->m_pSym->st_value + pCompSect->m_LocateAddr > + pObjSymFile->m_pSym->st_value + pSymSect->m_LocateAddr) + break; + } + m_Sorted.InsertAt(c, pObjSymFile); + } + + // Now print the sorted array + count = m_Sorted.GetSize(); + for (c = 0; c < count; c++) + { + pObjSymFile = (CObjSymFile *) m_Sorted[c]; + CObjFileSection* pSymSect = (CObjFileSection *) pObjSymFile->m_pObjFile->m_FileSections[ + pObjSymFile->m_pSym->st_shndx]; + + fprintf(fd, "%25s 0x%04x %9s %s\n", pObjSymFile->m_pName, + pObjSymFile->m_pSym->st_value + pSymSect->m_LocateAddr, + ELF32_ST_TYPE(pObjSymFile->m_pSym->st_info) == STT_OBJECT ? "data" : "function", + (const char *) pObjSymFile->m_pObjFile->m_Name); + } + + // Remove all entries from the Sorted array + m_Sorted.RemoveAll(); + + fprintf(fd, "\n\n"); + + // Close the map file + fclose(fd); + + return TRUE; +} + +/* +============================================================================ +The parser calls this function to perform the link operation after all +files have been assembled. ============================================================================ */ int VTLinker::Link() @@ -1256,25 +2584,25 @@ int VTLinker::Link() // Read the linker script ReadLinkerScript(); - // Loop through all files to be linked + // Load all files to be linked ReadObjFiles(); // Locate segments based on commands in the Linker Script LocateSegments(); // Resolve static (local) symbols for each segment + ResolveLocals(); // Resolve segment extern symbols - - // Test for unresolved symbols + ResolveExterns(); // Generate output file + GenerateOutputFile(); // Generate debug information - // Generate hex file - // Generate map file + GenerateMapFile(); // Back annotate Listing files with actual addresses @@ -1372,7 +2700,7 @@ void VTLinker::CalcObjDirs(void) m_ObjDirs.RemoveAll(); // Add the root directory to the ObjDirs - m_ObjDirs.Add(m_RootPath); + m_ObjDirs.Add(m_RootPath+"/"); // Check if there is an include path if (m_ObjPath.GetLength() == 0) @@ -1434,15 +2762,26 @@ Constructor for the CLinkRgn object. This object is used to keep track of regions defined in the linker script. ============================================================================ */ -CLinkRgn::CLinkRgn(int type, MString& name, int startAddr, int endAddr, int prot) +CLinkRgn::CLinkRgn(int type, MString& name, int startAddr, int endAddr, int prot, + const char* pAtEndName, int atend) { m_Type = type; m_Name = name; + if (pAtEndName != NULL) + m_AtEndRgn = pAtEndName; m_Protected = prot; + m_AtEnd = atend; + m_LocateComplete = FALSE; m_pFirstAddrRange = new LinkAddrRange; + m_pLastAddrRange = m_pFirstAddrRange; m_pFirstAddrRange->startAddr = startAddr; m_pFirstAddrRange->endAddr = endAddr; m_pFirstAddrRange->pNext = NULL; + m_pFirstAddrRange->pPrev = NULL; + m_pFirstAddrRange->nextLocateAddr = startAddr; + m_pFirstAddrRange->endLocateAddr = endAddr; + m_NextLocateAddr = startAddr; + m_EndLocateAddr = endAddr; } CLinkRgn::~CLinkRgn() diff --git a/src/linker.h b/src/linker.h index 71e091c..d077942 100644 --- a/src/linker.h +++ b/src/linker.h @@ -28,11 +28,15 @@ #define LKR_CMD_ORDER 5 #define LKR_CMD_CONTAINS 6 #define LKR_CMD_ENDSWITH 7 +#define LKR_CMD_ENTRY 8 +#define LKR_CMD_DEFINE 9 +#define LKR_CMD_MIXED 10 #define LKR_CMD_CD_DONE 0x80 #define LKR_CMD_ERROR 98 #define LKR_CMD_COMPLETE 99 #define START_ADDR_CODEEND -2 +#define START_ADDR_DATAEND -3 #define PAGE 1 #define INPAGE 2 @@ -53,7 +57,10 @@ typedef struct sLinkAddrRange { int startAddr; int endAddr; + int nextLocateAddr; + int endLocateAddr; struct sLinkAddrRange* pNext; + struct sLinkAddrRange* pPrev; } LinkAddrRange; class CObjSegment : public VTObject @@ -115,7 +122,8 @@ class CObjSymbol : public VTObject class CObjFileSection : public VTObject { public: - CObjFileSection() { m_pStrTab = NULL; m_pObjSegment = NULL; m_pProgBytes = NULL; }; + CObjFileSection() { m_pStrTab = NULL; m_pObjSegment = NULL; m_pProgBytes = NULL; m_Located = false; + m_LocateAddr = -1; m_Size = 0; m_Index = -1; }; ~CObjFileSection(); Elf32_Shdr m_ElfHeader; // The ELF header as read from the file @@ -124,19 +132,31 @@ class CObjFileSection : public VTObject VTObArray m_Symbols; // Symbols from the symbol table VTObArray m_Reloc; // Relocation entries char* m_pProgBytes; // Pointer to program bytes + int m_Size; // Size of the ProgBytes + int m_Index; // Index of this section in the object file + bool m_Located; // Indicates if this section has been located + int m_LocateAddr; // Address where the segment was located by linker + MString m_Name; // Name of the section + int m_Type; // Segment type for segment sections }; class CLinkRgn : public VTObject { public: - CLinkRgn(int type, MString& name, int startAddr, int endAddr, int prot); + CLinkRgn(int type, MString& name, int startAddr, int endAddr, int prot, const char* pAtEndName, int atend); ~CLinkRgn(); // Attributes MString m_Name; LinkAddrRange* m_pFirstAddrRange; + LinkAddrRange* m_pLastAddrRange; + MString m_AtEndRgn; int m_Type; int m_Protected; + int m_AtEnd; + int m_NextLocateAddr; + int m_EndLocateAddr; + int m_LocateComplete; }; typedef void (*stdOutFunc_t)(void *pContext, const char *msg); @@ -144,15 +164,30 @@ typedef void (*stdOutFunc_t)(void *pContext, const char *msg); class CObjFile : public VTObject { public: - CObjFile(const char* name) { m_Name = name; }; + CObjFile(const char* name) { m_Name = name; m_pShStrTab = NULL; m_pStrTab = NULL; + m_pSymSect = NULL; } ~CObjFile(); // Attributes MString m_Name; // Filename VTObArray m_FileSections; // Array of file sections Elf32_Ehdr m_Ehdr; // The main ELF header + char* m_pStrTab; // Pointer to the string table, if any (not alloced or freed by CObjFile) + char* m_pShStrTab; // Pointer to the string table, if any (not alloced or freed by CObjFile) + CObjFileSection* m_pSymSect; // Object file Symbol Table section pointer }; +class CObjSymFile : public VTObject +{ +public: + CObjSymFile() { m_pObjFile = NULL; m_pObjSection = NULL; } + +// Attributes + CObjFile* m_pObjFile; // Pointer to the ObjFile where the symbol came from + CObjFileSection* m_pObjSection; // Pointer to the File Section + Elf32_Sym* m_pSym; // Pointer to the symbol data + const char * m_pName; // Pointer to the name string +}; class VTLinker : public VTObject { @@ -161,7 +196,7 @@ class VTLinker : public VTObject ~VTLinker(); // Attributes - +private: VTMapStringToOb m_UndefSymbols; // Map of undefined symbols VTMapStringToOb m_Symbols; // Map of Symbols VTMapStringToOb m_ObjFiles; // Array of CObjFile objects @@ -181,13 +216,17 @@ class VTLinker : public VTObject int m_ProjectType; int m_FileIndex; int m_Command; // Script command during file parsing + int m_TotalCodeSpace; // Total space used by code + int m_TotalDataSpace; // Total space used for data MString m_OutputName; // Name of output file MString m_ObjFileList; // Comma separated list of files MString m_ObjPath; // Comma separated list of directories MString m_LinkOptions; // Linker options MString m_RootPath; // Root path of project. MString m_LinkerScript; // Name of the linker script + MString m_EntryLabel; // Label or address of program entry MStringArray m_ObjDirs; // Array of '/' terminated object dirs + CObjFileSection* m_SegMap[65536]; // Map of Segment assignements // Operations int GetValue(MString & string, int & value); @@ -202,26 +241,39 @@ class VTLinker : public VTObject MString PreprocessDirectory(const char *pDir); int MapScriptCommand(const char *pStr, int lineNo); void ProcScriptField2(const char *pStr, int lineNo, MString &segname); - void ProcScriptField3(const char *pStr, int lineNo, int& startAddr); + void ProcScriptField3(char *pStr, int lineNo, int& startAddr, char*& pSectName); void ProcScriptField4(const char *pStr, int lineNo, int& endAddr); - void ProcScriptField5(const char *pStr, int lineNo, int& prot); + void ProcScriptField5(const char *pStr, int lineNo, int& prot, int& atend); void AddOrderedSegment(const char *pStr, int lineNo); void AddContainsSegment(const char *pStr, int lineNo); void AddEndsWithSegment(const char *pStr, int lineNo); void NewLinkRegion(int type, int lineNo, int startAddr, - int endAddr, int prot); + int endAddr, int prot, const char* pAtEndName, int atend); int EvaluateScriptAddress(const char *pStr, int lineNo); void ProcessArgs(MString &str, const char *pDelim); int ReadLinkerScript(void); int ReadObjFiles(void); + int AssignSectionNames(void); int ReadElfHeaders(FILE* fd, MString& filename); int ReadSectionData(FILE* fd, CObjFile* pFile, CObjFileSection* pFileSection); int LocateSegments(void); - int LocateAsegSegment(CObjFileSection* pFileSect); - int LocateCsegSegment(CObjFileSection* pFileSect); - int LocateDsegSegment(CObjFileSection* pFileSect); + int LocateNondependantSegments(void); + int LocateOrderedSegments(void); + int LocateEndsWithSegments(void); + int LocateContainsSegments(void); + int LocateSegmentIntoRegion(MString& region, MString& segment, + bool atEnd = FALSE); + int LocateSegmentIntoRegion(MString& region, CObjFileSection* pFileSection, + bool atEnd = FALSE); + CObjFileSection* FindRelSection(CObjFile* pObjFile, Elf32_Rel* pRel); + int ResolveLocals(); + int ResolveExterns(); + MString MakeTitle(const MString& path); + int GenerateOutputFile(void); + int GenerateMapFile(void); +public: // Public Access functions int Link(); void SetLinkOptions(const MString& options); @@ -232,6 +284,9 @@ class VTLinker : public VTObject void SetProjectType(int type); void SetStdoutFunction(void *pContext, stdOutFunc_t pFunc); const MStringArray& GetErrors() { return m_Errors; }; + void SetOutputFile(const MString& outFile ); + int TotalCodeSpace(void) { return m_TotalCodeSpace; } + int TotalDataSpace(void) { return m_TotalDataSpace; } }; #endif diff --git a/src/project.cpp b/src/project.cpp index 393ca3f..1d07ed7 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -161,7 +161,7 @@ void cb_okNewProject(Fl_Widget* w, void*) pNewProject->m_makeProj = TRUE; } -void browse_cb(Fl_Widget* w, void*) +void browse_cb(Fl_Widget* w, void* pOpaque) { int sel; int c; @@ -190,6 +190,14 @@ void browse_cb(Fl_Widget* w, void*) newtxt[0] = '@'; newtxt[1] = 'b'; pB->text(sel, newtxt); + + // Change the Output Type if the opaque is given + if (pOpaque != NULL) + { + VT_ProjectSettings* pProj = (VT_ProjectSettings *) pOpaque; + + pProj->ProjTypeChanged(); + } } VT_NewProject::VT_NewProject() @@ -219,6 +227,7 @@ VT_NewProject::VT_NewProject() m_pProjType->add("@bAssembly .CO"); m_pProjType->add("Assembly .obj"); m_pProjType->add("Assembly ROM"); + m_pProjType->add("Library .lib"); m_pProjType->add("BASIC"); m_pProjType->callback(browse_cb); m_pProjType->value(1); @@ -247,7 +256,7 @@ VT_NewProject::VT_NewProject() m_pPC8201 = new Fl_Round_Button(200, 110, 100, 20, "Model PC-8201"); m_pPC8201->type(FL_RADIO_BUTTON); //JV - m_pKC85 = new Fl_Round_Button(200, 125, 100, 20, "Model KC85"); + m_pKC85 = new Fl_Round_Button(200, 135, 100, 20, "Model KC85"); m_pKC85->type(FL_RADIO_BUTTON); // Create an Ok button m_pOk = new Fl_Button(60, 265, 90, 30, "OK"); @@ -387,6 +396,7 @@ void cb_settings_ok(Fl_Widget* w, void*) pProject->m_LinkPath = pProj->getLinkPath(); pProject->m_LinkLibs = pProj->getLinkObjs(); pProject->m_LinkScript = pProj->getLinkScript(); + pProject->m_OutputName = pProj->getOutputName(); // Hide the window to end the session pProj->m_pProject->m_Dirty = 1; @@ -430,8 +440,9 @@ VT_ProjectSettings::VT_ProjectSettings(VT_Project *pProj) m_pProjType->add("Assembly .CO"); m_pProjType->add("Assembly .obj"); m_pProjType->add("Assembly ROM"); + m_pProjType->add("Library .lib"); m_pProjType->add("BASIC"); - m_pProjType->callback(browse_cb); + m_pProjType->callback(browse_cb, this); m_pProjType->value(m_pProject->m_ProjectType+1); // Text for target device @@ -451,7 +462,7 @@ VT_ProjectSettings::VT_ProjectSettings(VT_Project *pProj) m_pT200->type(FL_RADIO_BUTTON); if (m_pProject->m_TargetModel == MODEL_T200) m_pT200->value(1); - m_pPC8201 = new Fl_Round_Button(210, 150, 100, 20, "Model PC-8201"); + m_pPC8201 = new Fl_Round_Button(210, 150, 150, 20, "Model PC-8201"); m_pPC8201->type(FL_RADIO_BUTTON); if (m_pProject->m_TargetModel == MODEL_PC8201) m_pPC8201->value(1); @@ -523,7 +534,9 @@ VT_ProjectSettings::VT_ProjectSettings(VT_Project *pProj) o = new Fl_Box(20, 135, 100, 20, "Output Name"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); m_pOutputName = new Fl_Input(20, 155, 320, 20, ""); - m_pOutputName->value(m_pProject->m_Name); + if (m_pProject->m_OutputName.IsEmpty()) + m_pProject->m_OutputName = m_pProject->m_Name; + m_pOutputName->value(m_pProject->m_OutputName); // Create Edit field for Link libs o = new Fl_Box(20, 180, 100, 20, "Additional Link Objects"); @@ -556,6 +569,37 @@ VT_ProjectSettings::VT_ProjectSettings(VT_Project *pProj) } } +void VT_ProjectSettings::ProjTypeChanged(void) +{ + // Get the new project type + int projType = getProjType(); + MString newExt; + + switch (projType) + { + case VT_PROJ_TYPE_CO: newExt = ".co"; break; + case VT_PROJ_TYPE_OBJ: newExt = ".obj"; break; + case VT_PROJ_TYPE_ROM: newExt = ".hex"; break; + case VT_PROJ_TYPE_LIB: newExt = ".lib"; break; + case VT_PROJ_TYPE_BA: newExt = ".bas"; break; + default: newExt = ""; break; + } + + // Get current name from dialog box + const char * pCurrentName = m_pOutputName->value(); + int len = strlen(pCurrentName); + char * pNewName = new char[len+1]; + strcpy(pNewName, pCurrentName); + + // Search for an extension marker and remove the old extension if it exists + char * pOldExt = strrchr(pNewName, '.'); + if (pOldExt != NULL) + *pOldExt = '\0'; + m_pProject->m_OutputName = pNewName + newExt; + m_pOutputName->value(m_pProject->m_OutputName); + delete pNewName; +} + void VT_ProjectSettings::show(void) { if (m_pWnd != NULL) @@ -701,6 +745,14 @@ MString VT_ProjectSettings::getLinkObjs(void) return m_pLinkObjs->value(); } +MString VT_ProjectSettings::getOutputName(void) +{ + if (m_pOutputName == NULL) + return ""; + + return m_pOutputName->value(); +} + MString VT_ProjectSettings::getLinkScript(void) { if (m_pLinkScript == NULL) @@ -917,6 +969,7 @@ void VT_Project::SaveProject(void) fprintf(fd, "LINKSCRIPT=%s\n", (const char *) m_LinkScript); fprintf(fd, "ASMOPT=%s\n", (const char *) m_AsmOptions); fprintf(fd, "LINKOPT=%s\n", (const char *) m_LinkOptions); + fprintf(fd, "OUTPUTNAME=%s\n", (const char *) m_OutputName); fprintf(fd, "TYPE=%s\n", gProjectTypes[m_ProjectType]); get_model_string(model, m_TargetModel); fprintf(fd, "TARGET=%s\n", model); diff --git a/src/project.h b/src/project.h index ae5cc35..3902b7e 100644 --- a/src/project.h +++ b/src/project.h @@ -49,7 +49,8 @@ void cb_NewProject (Fl_Widget* w, void*); #define VT_PROJ_TYPE_CO 0 #define VT_PROJ_TYPE_OBJ 1 #define VT_PROJ_TYPE_ROM 2 -#define VT_PROJ_TYPE_BA 3 +#define VT_PROJ_TYPE_LIB 3 +#define VT_PROJ_TYPE_BA 4 class VT_Project { @@ -96,6 +97,7 @@ class VT_Project MString m_AsmOptions; MString m_LinkOptions; MString m_LinkScript; + MString m_OutputName; VTObArray m_Groups; int m_Dirty; // Set true when project settings change int m_ProjectType; // Type of project @@ -170,6 +172,7 @@ class VT_ProjectSettings MString getLinkObjs(void); MString getLinkScript(void); + void ProjTypeChanged(void); void EnableUpdateHIMEM(int enable); protected: diff --git a/src/rpn_eqn.h b/src/rpn_eqn.h index 158c9d1..7418fc6 100644 --- a/src/rpn_eqn.h +++ b/src/rpn_eqn.h @@ -36,6 +36,7 @@ const int RPN_LOW = 26; const int RPN_DEFINED = 27; const int RPN_NEGATE = 28; const int RPN_MACRO = 29; +const int RPN_PAGE = 30; class CRpnOperation : public VTObject { From 849fae1ae71ce164b08193783ea15f8e83e12162 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 22 Jan 2013 22:52:23 +0000 Subject: [PATCH 187/327] Updated rpn_eqn.h to define NULL if not already defined. Linux builds complain and this fixes it. --- src/rpn_eqn.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/rpn_eqn.h b/src/rpn_eqn.h index 7418fc6..6c127fe 100644 --- a/src/rpn_eqn.h +++ b/src/rpn_eqn.h @@ -6,6 +6,9 @@ #include "MString.h" #include "MStringArray.h" +#ifndef NULL +#define NULL 0 +#endif // Define operation codes const int RPN_VALUE = 1; From 9a1eb529a6189d1f19132b9ca9b1626b0267a7cd Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 22 Jan 2013 22:53:25 +0000 Subject: [PATCH 188/327] Removed unused flag from doins in non-Windows builds. --- src/doins.c | 2 +- src/doins.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doins.c b/src/doins.c index 2086960..67c455d 100644 --- a/src/doins.c +++ b/src/doins.c @@ -57,7 +57,7 @@ static char paritybits[256]={ #if defined(WIN32) void setflags(int regval, int sign, int zero, int auxcarry, int parity, int carry, int ov) #else -__inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry, char ov, char ts) +__inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry, char ov) #endif { if (sign!=-2) diff --git a/src/doins.h b/src/doins.h index c1f7a2a..bf5d694 100644 --- a/src/doins.h +++ b/src/doins.h @@ -34,7 +34,7 @@ #if defined(WIN32) void setflags(int regval, int sign, int zero, int auxcarry, int parity, int carry, int ov); #else -__inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry, char ov, char ts); +__inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry, char ov); #endif #endif From 3977632e8198b75e664d5dcb90198ae779bafb48 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 22 Jan 2013 23:01:24 +0000 Subject: [PATCH 189/327] Checking in updated FLU header file that was ommited in last checkin. --- src/FLU/Flu_Combo_Box.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/FLU/Flu_Combo_Box.h b/src/FLU/Flu_Combo_Box.h index cfad6ca..87ebdce 100644 --- a/src/FLU/Flu_Combo_Box.h +++ b/src/FLU/Flu_Combo_Box.h @@ -63,6 +63,8 @@ class FLU_EXPORT Flu_Combo_Box : public Fl_Group //! Override of Fl_Group::resize() void resize( int X, int Y, int W, int H ); + void selectall(void); + //! Set the function that will be called when the input area is interacted with inline void input_callback( void (*cb)(Fl_Widget*,void*), void* cbd = NULL ) { _inputCB = cb; _inputCBD = cbd; } From 821eb79b25a8fb0f36254bd859b4b34a46989849 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 22 Jan 2013 23:04:28 +0000 Subject: [PATCH 190/327] Changed getcwd to (void) getcwd to stop compiler complaining about ignoring return value. --- src/m100emu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m100emu.c b/src/m100emu.c index be792ec..27db487 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -1334,7 +1334,7 @@ void setup_working_path(char **argv) char* pContents, *pStr; #endif - getcwd(path, sizeof(path)); + (void) getcwd(path, sizeof(path)); #if defined(__APPLE__) /* On MacOSX, getcwd returns nothing when launched from the Finder. So @@ -1423,7 +1423,7 @@ void setup_working_path(char **argv) if ((i > 0) && (path[i-1] != '/')) strcat(path, "/"); # else - _getcwd(path, sizeof(path)); + (void) _getcwd(path, sizeof(path)); strcat(path,"\\"); #endif } From 5df3247f4eb5cc28a3755bdefa31f30e71b96640 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 22 Jan 2013 23:08:54 +0000 Subject: [PATCH 191/327] Fixed compile errors in linux caused by depreicated functionality. --- src/ide.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ide.cpp b/src/ide.cpp index 0115276..696d3ea 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -2148,8 +2148,6 @@ int VT_Ide::CloseAllFiles(void) else { // Ask if we should save the file - MString q; - q.Format("Save file %s?", mw->Title()); int ans = fl_choice("Save file %s?", "Cancel", "Yes", "No", (const char *) mw->Title()); // Test for CANCEL @@ -3628,7 +3626,9 @@ void VT_Ide::BuildProject(void) if (pSource->m_Name[0] == '/' || pSource->m_Name[1] == ':') linkerScript = pSource->m_Name; else - linkerScript = m_ActivePrj->m_RootPath + "/" + pSource->m_Name; + { + linkerScript = m_ActivePrj->m_RootPath + "/"; + linkerScript += pSource->m_Name; linkerScriptFound = true; } } From 937b13587e6909d718743ba3ccfa66d34ae8e50b Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 22 Jan 2013 23:18:51 +0000 Subject: [PATCH 192/327] Fixed Linux compile issue with passing by reference from return from function. --- src/ide.cpp | 1 + src/linker.cpp | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/ide.cpp b/src/ide.cpp index 696d3ea..631706a 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -3629,6 +3629,7 @@ void VT_Ide::BuildProject(void) { linkerScript = m_ActivePrj->m_RootPath + "/"; linkerScript += pSource->m_Name; + } linkerScriptFound = true; } } diff --git a/src/linker.cpp b/src/linker.cpp index 2ce265b..7d8f155 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -1665,7 +1665,8 @@ int VTLinker::LocateOrderedSegments() for (c = 0; c < count; c++) { // Now locate this segment into the named region - if (!LocateSegmentIntoRegion(name, pSegmentNames->GetAt(c))) + MString segmentName = pSegmentNames->GetAt(c); + if (!LocateSegmentIntoRegion(name, segmentName)) success = FALSE; } } @@ -1698,7 +1699,8 @@ int VTLinker::LocateEndsWithSegments() { printf("Locating ENDSWITH segment %s\n", (const char *) pSegmentNames->GetAt(c)); // Now locate this segment into the named region - if (!LocateSegmentIntoRegion(name, pSegmentNames->GetAt(c), true)) + MString segName = pSegmentNames->GetAt(c); + if (!LocateSegmentIntoRegion(name, segName, true)) success = FALSE; } } @@ -1730,7 +1732,8 @@ int VTLinker::LocateContainsSegments() for (c = 0; c < count; c++) { // Now locate this segment into the named region - if (!LocateSegmentIntoRegion(name, pSegmentNames->GetAt(c))) + MString segName = pSegmentNames->GetAt(c); + if (!LocateSegmentIntoRegion(name, segName)) success = FALSE; } } From 437acd56d427d94c0f729fee00b29c13fcde0fa7 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 23 Jan 2013 01:00:07 +0000 Subject: [PATCH 193/327] Modifications to remove warnings in Linux build. --- src/Flu_File_Chooser.cpp | 9 +++++---- src/Flu_Tree_Browser.cpp | 2 +- src/assemble.cpp | 2 +- src/chargen.cpp | 2 +- src/file.cpp | 2 +- src/fx80print.cpp | 5 +++-- src/hostprint.cpp | 5 ++++- src/ide.cpp | 5 ++--- src/linker.cpp | 22 +++++++++++----------- src/m100emu.c | 4 +++- src/memory.c | 35 +++++++++++++++++++++-------------- 11 files changed, 53 insertions(+), 40 deletions(-) diff --git a/src/Flu_File_Chooser.cpp b/src/Flu_File_Chooser.cpp index ddfdfc5..88e72be 100644 --- a/src/Flu_File_Chooser.cpp +++ b/src/Flu_File_Chooser.cpp @@ -577,11 +577,12 @@ Flu_File_Chooser :: Flu_File_Chooser( const char *pathname, const char *pat, int //printf( "load: %s %X\n", buf, f ); if( f ) { - fscanf(f, "%d, %d\n", &neww, &newh); + int scanLen = fscanf(f, "%d, %d\n", &neww, &newh); buf[0] = '\0'; while( !feof(f) ) { - fgets( buf, 1024, f ); + char *ptr = fgets( buf, 1024, f ); + (void) ptr; char *newline = strrchr( buf, '\n' ); if( newline ) *newline = '\0'; @@ -2315,7 +2316,7 @@ int Flu_File_Chooser :: popupContextMenu( Entry *entry ) if( type == ENTRY_FILE ) if( contextHandlers[i].ext.size() && contextHandlers[i].ext != ext ) continue; - entryPopup.add( contextHandlers[i].name.c_str(), 0, 0, (void*)i ); + entryPopup.add( contextHandlers[i].name.c_str(), 0, 0, (void*) (intptr_t) i ); } if( ext ) free( ext ); @@ -2324,7 +2325,7 @@ int Flu_File_Chooser :: popupContextMenu( Entry *entry ) const Fl_Menu_Item *selection = entryPopup.popup(); if( selection ) { - int handler = (int)selection->user_data(); + int handler = (int) (intptr_t) selection->user_data(); switch( handler ) { case ACTION_NEW_FOLDER: diff --git a/src/Flu_Tree_Browser.cpp b/src/Flu_Tree_Browser.cpp index 7d300f0..4c4b6b1 100644 --- a/src/Flu_Tree_Browser.cpp +++ b/src/Flu_Tree_Browser.cpp @@ -3251,7 +3251,7 @@ Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: modify( const char* path, in int ID = n->id(); _children.erase( n ); delete n; - retNode = (Node*)ID; // non-null return value means remove was successful + retNode = (Node*)(intptr_t) ID; // non-null return value means remove was successful rdata.forceResize = true; rdata.visibilityChanged = true; } diff --git a/src/assemble.cpp b/src/assemble.cpp index 1e0552b..fcd6657 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -822,7 +822,7 @@ void VTAssembler::opcode_arg_2reg(int opcode) if (pInst != NULL) { // Append instruction with operands - pInst->m_Group = (VTObject *) (int) reg[--reg_cnt]; // Get register operand + pInst->m_Group = (VTObject *) (intptr_t) reg[--reg_cnt]; // Get register operand pInst->m_Operand1 = new MString; // Allocte operand object pInst->m_Operand1->Format("%c", reg[--reg_cnt]); // Get register operand } diff --git a/src/chargen.cpp b/src/chargen.cpp index dfac50b..efac274 100644 --- a/src/chargen.cpp +++ b/src/chargen.cpp @@ -721,7 +721,7 @@ void VTCharacterGen::Load(void) // Loop through all character in the chartable for (index = 0; index < 256; index++) { - fread(data, 1, sizeof(data), fd); + int readlen = fread(data, 1, sizeof(data), fd); /* if (data[0] == 0) data[0] = 0x80; else diff --git a/src/file.cpp b/src/file.cpp index 9f3f971..3529781 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -669,7 +669,7 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) // Read contents to buffer fseek(fd, 0, SEEK_SET); - fread(data, 1, len, fd); + int readlen = fread(data, 1, len, fd); // Close the file fclose(fd); diff --git a/src/fx80print.cpp b/src/fx80print.cpp index 85f1a50..305ff71 100644 --- a/src/fx80print.cpp +++ b/src/fx80print.cpp @@ -1026,6 +1026,7 @@ void VTFX80Print::ResetPrinter(void) int c, r; int fileLoaded; FILE* fd; + int readlen; // Reset the print and protocol mode ResetMode(); @@ -1051,7 +1052,7 @@ void VTFX80Print::ResetPrinter(void) if (fd != NULL) { // Read data from File into charRam buffer - fread(m_charRom, 1, sizeof(m_charRom), fd); + readlen = fread(m_charRom, 1, sizeof(m_charRom), fd); fclose(fd); // Indicate ROM loaded @@ -1078,7 +1079,7 @@ void VTFX80Print::ResetPrinter(void) if (fd != NULL) { // Read data from File into charRam buffer - fread(m_charRam, 1, sizeof(m_charRam), fd); + readlen = fread(m_charRam, 1, sizeof(m_charRam), fd); fclose(fd); // Indicate RAM loaded diff --git a/src/hostprint.cpp b/src/hostprint.cpp index 458aaa1..aa2230b 100644 --- a/src/hostprint.cpp +++ b/src/hostprint.cpp @@ -92,7 +92,10 @@ void VTHostPrint::PrintByte(unsigned char byte) #else // Write byte to the host if (m_OutFd != -1) - write(m_OutFd, &byte, 1); + { + int size = write(m_OutFd, &byte, 1); + (void) size; + } #endif // Save byte so we know if we should do an AFF diff --git a/src/ide.cpp b/src/ide.cpp index 631706a..afb7c65 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -2412,7 +2412,7 @@ void VT_Ide::ReadProjectIdeSettings() } // Loop through all lines in file - while (fgets(line, 512, fd) != 0) + while (fgets(line, sizeof(line), fd) != 0) { // Skip comments and blank lines if ((line[0] == '#') || (line[0] == '\n') || (line[0] == '\x0d')) @@ -3627,8 +3627,7 @@ void VT_Ide::BuildProject(void) linkerScript = pSource->m_Name; else { - linkerScript = m_ActivePrj->m_RootPath + "/"; - linkerScript += pSource->m_Name; + linkerScript = m_ActivePrj->m_RootPath + (char *) "/"+ pSource->m_Name; } linkerScriptFound = true; } diff --git a/src/linker.cpp b/src/linker.cpp index 7d8f155..943a6c7 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -2173,7 +2173,7 @@ int VTLinker::GenerateOutputFile() const int addrSize = sizeof(m_SegMap) / sizeof(void *); MString err; CObjSymFile* pSymFile; - MString filename = m_RootPath + "/" + m_OutputName; + MString filename = m_RootPath + (char *) "/" + m_OutputName; // Exit if error has occurred if (m_Errors.GetSize() != 0) @@ -2335,7 +2335,7 @@ int VTLinker::GenerateOutputFile() // Write the data out as a REX .BX file also... int dot = m_OutputName.ReverseFind('.'); - MString bxFile = m_OutputName.Left(dot) + ".bx"; + MString bxFile = m_OutputName.Left(dot) + (char *) ".bx"; // Report that we are generating the output file if (m_pStdoutFunc != NULL) @@ -2344,7 +2344,7 @@ int VTLinker::GenerateOutputFile() msg.Format("Generating REX file %s\n", (const char *) bxFile); m_pStdoutFunc(m_pStdoutContext, (const char *) msg); } - filename = m_RootPath + "/" + bxFile; + filename = m_RootPath + (char *) "/" + bxFile; // Open the output file for output if ((fd = fopen((const char *) filename, "wb")) == NULL) @@ -2388,12 +2388,12 @@ int VTLinker::GenerateMapFile(void) return FALSE; // Test if MAP file generation requested - if (m_LinkOptions.Find("-m") == -1) + if (m_LinkOptions.Find((char *) "-m") == -1) return FALSE; // Okay, generate the map file, replacing any old one found int dot = m_OutputName.ReverseFind('.'); - MString mapFile = m_OutputName.Left(dot) + ".map"; + MString mapFile = m_OutputName.Left(dot) + (char *) ".map"; // Report that we are generating the output file if (m_pStdoutFunc != NULL) @@ -2402,7 +2402,7 @@ int VTLinker::GenerateMapFile(void) msg.Format("Generating MAP file %s\n", (const char *) mapFile); m_pStdoutFunc(m_pStdoutContext, (const char *) msg); } - filename = m_RootPath + "/" + mapFile; + filename = m_RootPath + (char *) "/" + mapFile; // Open the output file for output if ((fd = fopen((const char *) filename, "wb")) == NULL) @@ -2508,8 +2508,8 @@ int VTLinker::GenerateMapFile(void) pObjSymFile->m_pSym->st_shndx]; fprintf(fd, "%25s 0x%04x %9s %s\n", pObjSymFile->m_pName, - pObjSymFile->m_pSym->st_value + pSymSect->m_LocateAddr, - ELF32_ST_TYPE(pObjSymFile->m_pSym->st_info) == STT_OBJECT ? "data" : "function", + (int) (pObjSymFile->m_pSym->st_value + pSymSect->m_LocateAddr), + ELF32_ST_TYPE(pObjSymFile->m_pSym->st_info) == STT_OBJECT ? (char *) "data" : (char *) "function", (const char *) pObjSymFile->m_pObjFile->m_Name); } @@ -2551,8 +2551,8 @@ int VTLinker::GenerateMapFile(void) pObjSymFile->m_pSym->st_shndx]; fprintf(fd, "%25s 0x%04x %9s %s\n", pObjSymFile->m_pName, - pObjSymFile->m_pSym->st_value + pSymSect->m_LocateAddr, - ELF32_ST_TYPE(pObjSymFile->m_pSym->st_info) == STT_OBJECT ? "data" : "function", + (int) (pObjSymFile->m_pSym->st_value + pSymSect->m_LocateAddr), + ELF32_ST_TYPE(pObjSymFile->m_pSym->st_info) == STT_OBJECT ? (char *) "data" : (char *) "function", (const char *) pObjSymFile->m_pObjFile->m_Name); } @@ -2703,7 +2703,7 @@ void VTLinker::CalcObjDirs(void) m_ObjDirs.RemoveAll(); // Add the root directory to the ObjDirs - m_ObjDirs.Add(m_RootPath+"/"); + m_ObjDirs.Add(m_RootPath+(char *) "/"); // Check if there is an include path if (m_ObjPath.GetLength() == 0) diff --git a/src/m100emu.c b/src/m100emu.c index 27db487..ad3ecb9 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -1326,6 +1326,7 @@ void setup_working_path(char **argv) { #if defined(__unix__) || defined(__APPLE__) int i; + char* pCwd; #if defined(__APPLE__) int found; @@ -1334,7 +1335,8 @@ void setup_working_path(char **argv) char* pContents, *pStr; #endif - (void) getcwd(path, sizeof(path)); + pCwd = getcwd(path, sizeof(path)); + (void) pCwd; #if defined(__APPLE__) /* On MacOSX, getcwd returns nothing when launched from the Finder. So diff --git a/src/memory.c b/src/memory.c index 38e4abd..1bb2f36 100644 --- a/src/memory.c +++ b/src/memory.c @@ -1163,6 +1163,7 @@ void load_remem_ram(void) FILE *fd; int size, x; int empty = 1; + int readlen; /* Open ReMem file */ fd = fopen(mem_setup.remem_file, "rb+"); @@ -1173,11 +1174,11 @@ void load_remem_ram(void) size = 1024 * 2048; /* Copy 2 meg of RAM & FLASH */ /* Read ReMem RAM first */ - fread(gReMemRam, 1, size, fd); + readlen = fread(gReMemRam, 1, size, fd); /* Now read Flash */ - fread(gReMemFlash1.pFlash, 1, size, fd); - fread(gReMemFlash2.pFlash, 1, size, fd); + readlen = fread(gReMemFlash1.pFlash, 1, size, fd); + readlen = fread(gReMemFlash2.pFlash, 1, size, fd); /* Close the file */ fclose(fd); @@ -1228,6 +1229,7 @@ void load_rampac_ram(void) { FILE *fd; int size; + int readlen; /* Open Rampac file */ fd = fopen(mem_setup.rampac_file, "rb+"); @@ -1238,7 +1240,7 @@ void load_rampac_ram(void) size = 1024 * 256; /* Copy 256 K of RAM */ /* Write ReMem RAM first */ - fread(gRampacRam, 1, size, fd); + readlen = fread(gRampacRam, 1, size, fd); /* Close the file */ fclose(fd); @@ -1255,6 +1257,7 @@ void load_rex_flash(void) { FILE *fd; int size; + int readlen; /* Open ReMem file */ fd = fopen(mem_setup.rex_flash_file, "rb+"); @@ -1265,7 +1268,7 @@ void load_rex_flash(void) size = 1024 * 1024; /* Copy 1 meg of FLASH /* Read Rex Flash first */ - fread(gRexFlash.pFlash, 1, size, fd); + readlen = fread(gRexFlash.pFlash, 1, size, fd); /* Close the file */ fclose(fd); @@ -1285,6 +1288,7 @@ void load_rex2_ram(void) { FILE *fd; int size; + int readlen; /* Open ReMem file */ fd = fopen(mem_setup.rex2_ram_file, "rb+"); @@ -1295,7 +1299,7 @@ void load_rex2_ram(void) size = 1024 * 128; /* Copy 128K of RAM /* Read Rex2 RAM */ - fread(gRex2Ram, 1, size, fd); + readlen = fread(gRex2Ram, 1, size, fd); /* Close the file */ fclose(fd); @@ -1320,6 +1324,7 @@ void load_ram(void) char file[256]; FILE *fd; int x; + int readlen; /* Check if ReMem emulation enabled or Base Memory emulation */ if (gReMem & !gRex) @@ -1351,15 +1356,15 @@ void load_ram(void) case MODEL_M10: /* M100 & M102 have single bank */ case MODEL_KC85: case MODEL_M102: - fread(gBaseMemory+RAMSTART, 1, RAMSIZE, fd); + readlen = fread(gBaseMemory+RAMSTART, 1, RAMSIZE, fd); break; case MODEL_T200: /* Read all ram into rambanks array */ - fread(rambanks, 1, 3*RAMSIZE, fd); + readlen = fread(rambanks, 1, 3*RAMSIZE, fd); /* Read bank number to file */ - fread(&gRamBank, 1, 1, fd); + readlen = fread(&gRamBank, 1, 1, fd); /* Test bank number for bounds */ if (gRamBank > 2) @@ -1376,11 +1381,11 @@ void load_ram(void) case MODEL_PC8201: case MODEL_PC8300: /* Read all ram into rambanks array */ - fread(rambanks, 1, 3*RAMSIZE, fd); + readlen = fread(rambanks, 1, 3*RAMSIZE, fd); /* Read bank number to file */ - fread(&gRamBank, 1, 1, fd); - fread(&gRomBank, 1, 1, fd); + readlen = fread(&gRamBank, 1, 1, fd); + readlen = fread(&gRomBank, 1, 1, fd); /* Test bank number for bounds */ if (gRamBank > 2) @@ -1513,6 +1518,7 @@ void load_sys_rom(void) { FILE* fd; //int fd; + int readlen; /* Set pointer to ROM Description */ if (gModel == MODEL_T200) @@ -1550,7 +1556,7 @@ void load_sys_rom(void) /* If Model = T200 then read the 2nd ROM (MSPLAN) */ if (gModel == MODEL_T200) - fread(gMsplanROM, 1, 32768, fd); + readlen = fread(gMsplanROM, 1, 32768, fd); /* Close the ROM file */ fclose(fd); @@ -1572,6 +1578,7 @@ void load_opt_rom(void) FILE *fd; unsigned short start_addr; char buf[65536]; + int readlen; // Clear the option ROM memory memset(gOptROM,0,OPTROMSIZE); @@ -1613,7 +1620,7 @@ void load_opt_rom(void) fd=fopen(gsOptRomFile,"rb"); if(fd!=0) { - fread(gOptROM,1, OPTROMSIZE, fd); + readlen = fread(gOptROM,1, OPTROMSIZE, fd); fclose(fd); } From 8d4b3f10b6e8a79bc2a8f9102a26a32f971ec112 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 26 Jan 2013 03:51:20 +0000 Subject: [PATCH 194/327] Updates to IDE edit windows to fix blinking cursor not actualy blinking. Also updated remote.cpp and display.cpp to fix issue with simulated keystrokes from the remote interface. --- release.txt | 16 ++++++++++++++++ src/My_Text_Display.cpp | 12 +++++++++--- src/My_Text_Display.h | 2 ++ src/display.cpp | 3 +++ src/ide.cpp | 4 ++++ src/idetabs.cpp | 12 +++++++----- src/linker.cpp | 28 ++++++++++++---------------- src/remote.cpp | 8 ++++++-- 8 files changed, 59 insertions(+), 26 deletions(-) diff --git a/release.txt b/release.txt index c1ac41b..41f25aa 100644 --- a/release.txt +++ b/release.txt @@ -5,6 +5,22 @@ VirtualT Release.txt This file lists the changes and additions for each of the versions of VirtualT since v0.3 +==================== +v1.6 +==================== + +1. Fixed issue with remote interface simulated keystokes where the keys wouldn't + always be regconized. There was a race condition between the remote thread + and the simulation thread. + +2. Completed the 8085 relocating linker!! This was the primary reason for this + release in fact. Many, many changes to get to this point. + +3. Modified the IDE with new tabs for selecting the file to edit. The old tabs used + the standard FLTK tab control and were really ugly, plus had an issue with tab + width calculations with regard to mouse presses to select the tab. + + ==================== v1.5 July 9th, 2011 ==================== diff --git a/src/My_Text_Display.cpp b/src/My_Text_Display.cpp index ee858e7..db19a68 100644 --- a/src/My_Text_Display.cpp +++ b/src/My_Text_Display.cpp @@ -76,14 +76,16 @@ void cb_cursor_blink(void *pOpaque) void My_Text_Display::blink_cursor(void) { - if (++mBlinkCount == 2) + if (++mBlinkCount >= 2) { mBlinkCount = 0; mBlinkOn = mCursorOn; show_cursor(0); } else + { show_cursor(mBlinkOn); + } Fl::add_timeout(0.6, cb_cursor_blink, this); } @@ -96,6 +98,8 @@ My_Text_Display::My_Text_Display(int X, int Y, int W, int H, const char* l) mMaxsize = 0; mCurrentCol = 0; mBlinkCount = 0; + mBlinkOn = 1; + mBlinkEnabled = 1; mLeftMargin = LEFT_MARGIN; bHasUtilityMargin = 0; mUtilityMarginColor = FL_BLACK; @@ -224,7 +228,8 @@ void My_Text_Display::buffer( Fl_Text_Buffer *buf ) { /* Update the display */ buffer_modified_cb( 0, buf->length(), 0, 0, 0, this ); - Fl::add_timeout(0.33f, cb_cursor_blink, this); + if (mBlinkEnabled) + Fl::add_timeout(0.33f, cb_cursor_blink, this); /* Resize the widget to update the screen... */ resize(x(), y(), w(), h()); @@ -1555,6 +1560,7 @@ void My_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip, charStyle = position_style( lineStartPos, lineLen, charIndex, outIndex + dispIndexOffset ); if ( charStyle != style ) { + if (strcmp(outStr, "") != 0) draw_string( style, startX, Y, X, outStr, outPtr - outStr ); outPtr = outStr; startX = X; @@ -3060,7 +3066,7 @@ int My_Text_Display::handle(int event) // Reset the blink count so we don't hide the cursor when there is // activity - if (event != FL_ENTER && event != FL_MOVE) + if (event != FL_ENTER && event != FL_MOVE && event != 0) { mBlinkCount = 0; if (mBlinkCount == 0) diff --git a/src/My_Text_Display.h b/src/My_Text_Display.h index fc41b62..6d5a9ba 100644 --- a/src/My_Text_Display.h +++ b/src/My_Text_Display.h @@ -138,6 +138,7 @@ class FL_EXPORT My_Text_Display: public Fl_Double_Window { virtual void resize(int X, int Y, int W, int H); void blink_cursor(void); + void blink_enable(int bEnabled = 1) { mBlinkEnabled = bEnabled; } void utility_margin_color(int margin_size, Fl_Color c) { bHasUtilityMargin = 1; mLeftMargin = margin_size, mUtilityMarginColor = c; @@ -231,6 +232,7 @@ class FL_EXPORT My_Text_Display: public Fl_Double_Window { int mCursorPos; int mCursorOn; int mBlinkCount; + int mBlinkEnabled; int mBlinkOn; int mCursorOldY; /* Y pos. of cursor for blanking */ int mCursorToHint; /* Tells the buffer modified callback diff --git a/src/display.cpp b/src/display.cpp index c96c1c9..4237d86 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -86,6 +86,7 @@ extern int gRomSize; extern int gMaintCount; extern int gOsDelay; extern int gInMsPlanROM; +extern int gDelayUpdateKeys; void set_target_frequency(int freq); } @@ -2442,6 +2443,7 @@ void T100_Disp::SimulateKeydown(int key) } m_simEventKey = key; gSimKey = VT_SIM_KEYDOWN; + gDelayUpdateKeys = 1; } /* @@ -2465,6 +2467,7 @@ void T100_Disp::SimulateKeyup(int key) m_simEventKey = key; gSimKey = VT_SIM_KEYUP; + gDelayUpdateKeys = 1; } /* diff --git a/src/ide.cpp b/src/ide.cpp index afb7c65..8ff948c 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -1325,6 +1325,7 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) m_BuildTextDisp->textcolor(hl_plain); m_BuildTextDisp->color(background_color); m_BuildTextDisp->selection_color(FL_DARK_BLUE); + m_BuildTextDisp->blink_enable(0); // Create a Text Buffer for the Text Editor to work with m_BuildTextBuf = new Fl_Text_Buffer(); @@ -1358,6 +1359,7 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) md->textcolor(hl_plain); md->color(background_color); md->selection_color(FL_DARK_BLUE); + md->blink_enable(0); // Create a Text Buffer for the Text Editor to work with Fl_Text_Buffer *tb = new Fl_Text_Buffer(); @@ -1395,6 +1397,7 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) md->textcolor(hl_plain); md->color(background_color); md->selection_color(FL_DARK_BLUE); + md->blink_enable(0); // Create a Text Buffer for the Text Editor to work with tb = new Fl_Text_Buffer(); @@ -1419,6 +1422,7 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) md->textcolor(hl_plain); md->color(background_color); md->selection_color(FL_DARK_BLUE); + md->blink_enable(0); // Create a Text Buffer for the Text Editor to work with tb = new Fl_Text_Buffer(); diff --git a/src/idetabs.cpp b/src/idetabs.cpp index abc2262..ebf51c7 100644 --- a/src/idetabs.cpp +++ b/src/idetabs.cpp @@ -508,7 +508,7 @@ int Fl_Ide_Tabs::handle(int e) return ret; case FL_RELEASE: - // If the mouse was previously pused in the close box, then test for closure + // If the mouse was previously pushed in the close box, then test for closure if (m_pushInRect) { window()->make_current(); @@ -582,8 +582,10 @@ int Fl_Ide_Tabs::orig_handle(int event) { } if (o && value(o)) { set_changed(); - do_callback(); + do_callback(); } + if (o) + Fl::focus(o); Fl_Tooltip::current(o); } else { push(o); @@ -613,7 +615,8 @@ int Fl_Ide_Tabs::orig_handle(int event) { Fl::event() == FL_FOCUS || Fl::event() == FL_UNFOCUS) { redraw_tabs(); - if (Fl::event() == FL_FOCUS || Fl::event() == FL_UNFOCUS) return 0; + if (Fl::event() == FL_FOCUS || Fl::event() == FL_UNFOCUS) + return 0; else return 1; } else return Fl_Group::handle(event); case FL_KEYBOARD: @@ -636,8 +639,7 @@ int Fl_Ide_Tabs::orig_handle(int event) { return 1; case FL_Down: redraw(); - return Fl_Group::handle(FL_FOCUS); - default: + return Fl_Group::handle(FL_FOCUS); default: break; } return Fl_Group::handle(event); diff --git a/src/linker.cpp b/src/linker.cpp index 943a6c7..8c292c8 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -1697,7 +1697,6 @@ int VTLinker::LocateEndsWithSegments() count = pSegmentNames->GetSize(); for (c = count-1; c >= 0; c--) { - printf("Locating ENDSWITH segment %s\n", (const char *) pSegmentNames->GetAt(c)); // Now locate this segment into the named region MString segName = pSegmentNames->GetAt(c); if (!LocateSegmentIntoRegion(name, segName, true)) @@ -1803,9 +1802,6 @@ int VTLinker::LocateNondependantSegments() continue; } - printf("Locating segment %s from file %s\n", (const char *) pFileSect->m_Name, - (const char *) pObjFile->m_Name); - // Test if the segment has a named link region if (m_LinkRegions.Lookup((const char *) pFileSect->m_Name, (VTObject *&) pLinkRgn)) { @@ -2306,7 +2302,7 @@ int VTLinker::GenerateOutputFile() char * pRom = new char[32768]; // Fill contents with zero - for (c = 0; c < 32767; c++) + for (c = 0; c < 32768; c++) pRom[c] = 0; // Copy the output data to the ROM storage @@ -2317,21 +2313,21 @@ int VTLinker::GenerateOutputFile() c++; // Write the next block of bytes - CObjFileSection *pSect = m_SegMap[c]; - if (pSect != NULL) + if (c < 32768) { - memcpy(&pRom[c], pSect->m_pProgBytes, pSect->m_Size); - - // Update to the next byte to write - c += pSect->m_Size; + CObjFileSection *pSect = m_SegMap[c]; + if (pSect != NULL) + { + memcpy(&pRom[c], pSect->m_pProgBytes, pSect->m_Size); + + // Update to the next byte to write + c += pSect->m_Size; + } } } - // Write the ROM data to the HEX file - save_hex_file_buf(pRom, 0, 32768, 0, fd); - - // Close the file - fclose(fd); + // Write the ROM data to the HEX file. File is closed by the routine + save_hex_file_buf(pRom, 0, 32767, 0, fd); // Write the data out as a REX .BX file also... int dot = m_OutputName.ReverseFind('.'); diff --git a/src/remote.cpp b/src/remote.cpp index c5c47c4..78634a4 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -137,6 +137,7 @@ extern int fl_wait(double); extern void simulate_keydown(int key); extern void simulate_keyup(int key); extern Fl_Preferences virtualt_prefs; +extern int gSimKey; extern "C" { @@ -1606,10 +1607,13 @@ std::string cmd_list_break(ServerSocket& sock, std::string& args) void key_delay(void) { - fl_wait(0.01); + //fl_wait(0.01); + while (gSimKey != 0) + fl_wait(0.001); + while (gDelayUpdateKeys) fl_wait(0.001); - fl_wait(0.01); + //fl_wait(0.01); } /* ======================================================= From 556090227dfb4cf3ff4afc9ee1d8721c8b35d470 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 26 Jan 2013 21:30:22 +0000 Subject: [PATCH 195/327] Started implementation of listing back annotation in linker and modified assembler parser to get input from preprocessor instead of directly from input file. Preprocessor only a shell at the moment which reads from the file, but will be extended to perform macro substitution. --- src/a85parse.cpp | 8504 +++++++++++++++++++++++----------------------- src/a85parse.h | 42 +- src/a85parse.syn | 20 +- src/assemble.cpp | 60 + src/assemble.h | 2 + src/linker.cpp | 34 + src/linker.h | 1 + 7 files changed, 4368 insertions(+), 4295 deletions(-) diff --git a/src/a85parse.cpp b/src/a85parse.cpp index 39605ee..d9e43e8 100644 --- a/src/a85parse.cpp +++ b/src/a85parse.cpp @@ -17,11 +17,11 @@ */ -#ifndef A85PARSE_H_1357391036 +#ifndef A85PARSE_H_1359224795 #include "a85parse.h" #endif -#ifndef A85PARSE_H_1357391036 +#ifndef A85PARSE_H_1359224795 #error Mismatched header file #endif @@ -316,15 +316,17 @@ void syntax_error(const char *token_name) #define TAB_SPACING gTabSize #define GET_INPUT {(PCB).input_code = (gAsm->m_fd != 0 && !gAbort) ? \ - fgetc(gAsm->m_fd) : 0; if ((PCB).input_code == 13) (PCB).input_code = fgetc(gAsm->m_fd);\ - } + gAsm->preprocessor() : 0; } + +// fgetc(gAsm->m_fd) : 0; if ((PCB).input_code == 13) (PCB).input_code = fgetc(gAsm->m_fd);\ +// } #define SYNTAX_ERROR { syntax_error(TOKEN_NAMES[(PCB).error_frame_token]); } /* #define SYNTAX_ERROR {MString string; if ((PCB).error_frame_token != 0) \ string.Format("Error in line %d(%s), column%d: Malformed %s - %s", \ - (PCB).line, gFilename, (PCB).column, \ + (PCB).line, gFilename, (PCB).column, \* TOKEN_NAMES[(PCB).error_frame_token], (PCB).error_message); \ else if (strcmp("Unexpected '\\n'", (PCB).error_message) == 0) \ string.Format("Error in line %d(%s), column %d: Unexpected end of line", \ @@ -523,18 +525,6 @@ static void ag_rp_24(void) { } static void ag_rp_25(void) { -/* Line 136, C:/Projects/VirtualT/src/a85parse.syn */ - if (gAsm->preproc_macro()) \ - PCB.reduction_token = a85parse_WS_token; -} - -static void ag_rp_26(void) { -/* Line 138, C:/Projects/VirtualT/src/a85parse.syn */ - if (gAsm->preproc_macro()) \ - PCB.reduction_token = a85parse_WS_token; -} - -static void ag_rp_27(void) { /* Line 142, C:/Projects/VirtualT/src/a85parse.syn */ gMacro->m_ParamList = gExpList; \ gMacro->m_Name = ss[ss_idx--]; \ @@ -545,7 +535,7 @@ static void ag_rp_27(void) { gMacro = new CMacro; } -static void ag_rp_28(void) { +static void ag_rp_26(void) { /* Line 149, C:/Projects/VirtualT/src/a85parse.syn */ gMacro->m_Name = ss[ss_idx--]; gMacroStack[ms_idx++] = gMacro; \ if (gAsm->preproc_macro()) \ @@ -553,296 +543,296 @@ static void ag_rp_28(void) { gMacro = new CMacro; } -static void ag_rp_29(int c) { +static void ag_rp_27(int c) { /* Line 155, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_30(int c) { +static void ag_rp_28(int c) { /* Line 156, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_31(void) { +static void ag_rp_29(void) { /* Line 157, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '\n'; ss[ss_idx][ss_len] = 0; } -static void ag_rp_32(void) { +static void ag_rp_30(void) { /* Line 160, C:/Projects/VirtualT/src/a85parse.syn */ page = 0; seg = CSEG; } -static void ag_rp_33(void) { +static void ag_rp_31(void) { /* Line 161, C:/Projects/VirtualT/src/a85parse.syn */ page = 0; seg = DSEG; } -#define ag_rp_34(p) (page = p) +#define ag_rp_32(p) (page = p) -#define ag_rp_35() (gAsm->pragma_list()) +#define ag_rp_33() (gAsm->pragma_list()) -#define ag_rp_36() (gAsm->pragma_hex()) +#define ag_rp_34() (gAsm->pragma_hex()) -#define ag_rp_37() (gAsm->pragma_verilog()) +#define ag_rp_35() (gAsm->pragma_verilog()) -#define ag_rp_38() (gAsm->pragma_entry(ss[ss_idx--])) +#define ag_rp_36() (gAsm->pragma_entry(ss[ss_idx--])) -#define ag_rp_39() (gAsm->pragma_extended()) +#define ag_rp_37() (gAsm->pragma_extended()) -#define ag_rp_40() (gAsm->directive_org()) +#define ag_rp_38() (gAsm->directive_org()) -#define ag_rp_41() (gAsm->directive_aseg()) +#define ag_rp_39() (gAsm->directive_aseg()) -#define ag_rp_42() (gAsm->directive_ds()) +#define ag_rp_40() (gAsm->directive_ds()) -#define ag_rp_43() (gAsm->directive_db()) +#define ag_rp_41() (gAsm->directive_db()) -#define ag_rp_44() (gAsm->directive_dw()) +#define ag_rp_42() (gAsm->directive_dw()) -#define ag_rp_45() (gAsm->directive_public()) +#define ag_rp_43() (gAsm->directive_public()) -#define ag_rp_46() (gAsm->directive_extern()) +#define ag_rp_44() (gAsm->directive_extern()) -#define ag_rp_47() (gAsm->directive_extern()) +#define ag_rp_45() (gAsm->directive_extern()) -#define ag_rp_48() (gAsm->directive_module(ss[ss_idx--])) +#define ag_rp_46() (gAsm->directive_module(ss[ss_idx--])) -#define ag_rp_49() (gAsm->directive_name(ss[ss_idx--])) +#define ag_rp_47() (gAsm->directive_name(ss[ss_idx--])) -#define ag_rp_50() (gAsm->directive_stkln()) +#define ag_rp_48() (gAsm->directive_stkln()) -#define ag_rp_51() (gAsm->directive_echo()) +#define ag_rp_49() (gAsm->directive_echo()) -#define ag_rp_52() (gAsm->directive_echo(ss[ss_idx--])) +#define ag_rp_50() (gAsm->directive_echo(ss[ss_idx--])) -#define ag_rp_53() (gAsm->directive_fill()) +#define ag_rp_51() (gAsm->directive_fill()) -#define ag_rp_54() (gAsm->directive_printf(ss[ss_idx--])) +#define ag_rp_52() (gAsm->directive_printf(ss[ss_idx--])) -#define ag_rp_55() (gAsm->directive_end("")) +#define ag_rp_53() (gAsm->directive_end("")) -#define ag_rp_56() (gAsm->directive_end(ss[ss_idx--])) +#define ag_rp_54() (gAsm->directive_end(ss[ss_idx--])) -#define ag_rp_57() (gAsm->directive_if()) +#define ag_rp_55() (gAsm->directive_if()) -#define ag_rp_58() (gAsm->directive_else()) +#define ag_rp_56() (gAsm->directive_else()) -#define ag_rp_59() (gAsm->directive_endif()) +#define ag_rp_57() (gAsm->directive_endif()) -#define ag_rp_60() (gAsm->directive_endian(1)) +#define ag_rp_58() (gAsm->directive_endian(1)) -#define ag_rp_61() (gAsm->directive_endian(0)) +#define ag_rp_59() (gAsm->directive_endian(0)) -#define ag_rp_62() (gAsm->directive_title(ss[ss_idx--])) +#define ag_rp_60() (gAsm->directive_title(ss[ss_idx--])) -#define ag_rp_63() (gAsm->directive_title(ss[ss_idx--])) +#define ag_rp_61() (gAsm->directive_title(ss[ss_idx--])) -#define ag_rp_64() (gAsm->directive_page(-1)) +#define ag_rp_62() (gAsm->directive_page(-1)) -#define ag_rp_65() (gAsm->directive_sym()) +#define ag_rp_63() (gAsm->directive_sym()) -#define ag_rp_66() (gAsm->directive_link(ss[ss_idx--])) +#define ag_rp_64() (gAsm->directive_link(ss[ss_idx--])) -#define ag_rp_67() (gAsm->directive_maclib(ss[ss_idx--])) +#define ag_rp_65() (gAsm->directive_maclib(ss[ss_idx--])) -#define ag_rp_68() (gAsm->directive_page(page)) +#define ag_rp_66() (gAsm->directive_page(page)) -#define ag_rp_69() (page = 60) +#define ag_rp_67() (page = 60) -#define ag_rp_70(n) (page = n) +#define ag_rp_68(n) (page = n) -#define ag_rp_71() (expression_list_literal()) +#define ag_rp_69() (expression_list_literal()) -#define ag_rp_72() (expression_list_literal()) +#define ag_rp_70() (expression_list_literal()) -#define ag_rp_73() (expression_list_equation()) +#define ag_rp_71() (expression_list_equation()) -#define ag_rp_74() (expression_list_equation()) +#define ag_rp_72() (expression_list_equation()) -#define ag_rp_75() (expression_list_literal()) +#define ag_rp_73() (expression_list_literal()) -#define ag_rp_76() (expression_list_literal()) +#define ag_rp_74() (expression_list_literal()) -#define ag_rp_77() (gNameList->Add(ss[ss_idx--])) +#define ag_rp_75() (gNameList->Add(ss[ss_idx--])) -#define ag_rp_78() (gNameList->Add(ss[ss_idx--])) +#define ag_rp_76() (gNameList->Add(ss[ss_idx--])) -static void ag_rp_79(void) { +static void ag_rp_77(void) { /* Line 242, C:/Projects/VirtualT/src/a85parse.syn */ strcpy(ss[++ss_idx], "$"); ss_len = 1; } -static void ag_rp_80(void) { +static void ag_rp_78(void) { /* Line 243, C:/Projects/VirtualT/src/a85parse.syn */ strcpy(ss[++ss_idx], "&"); ss_len = 1; } -static void ag_rp_81(int c) { +static void ag_rp_79(int c) { /* Line 246, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; \ if (PCB.column == 2) ss_addr = gAsm->m_ActiveSeg->m_Address; } -static void ag_rp_82(int c) { +static void ag_rp_80(int c) { /* Line 248, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_83(int c) { +static void ag_rp_81(int c) { /* Line 249, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_84(int c) { +static void ag_rp_82(int c) { /* Line 252, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_85(int c) { +static void ag_rp_83(int c) { /* Line 253, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_86(int ch1, int ch2) { +static void ag_rp_84(int ch1, int ch2) { /* Line 259, C:/Projects/VirtualT/src/a85parse.syn */ ss_idx++; ss_len = 2; sprintf(ss[ss_idx], "%c%c", ch1, ch2); } -static void ag_rp_87(int c) { +static void ag_rp_85(int c) { /* Line 260, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_88(void) { +static void ag_rp_86(void) { /* Line 267, C:/Projects/VirtualT/src/a85parse.syn */ ss_idx++; ss_len = 0; } -static void ag_rp_89(int c) { +static void ag_rp_87(int c) { /* Line 268, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -#define ag_rp_90(n) (n) +#define ag_rp_88(n) (n) -#define ag_rp_91() ('\\') +#define ag_rp_89() ('\\') -#define ag_rp_92() ('\n') +#define ag_rp_90() ('\n') -#define ag_rp_93() ('\t') +#define ag_rp_91() ('\t') -#define ag_rp_94() ('\r') +#define ag_rp_92() ('\r') -#define ag_rp_95() ('\0') +#define ag_rp_93() ('\0') -#define ag_rp_96() ('"') +#define ag_rp_94() ('"') -#define ag_rp_97() (0x08) +#define ag_rp_95() (0x08) -#define ag_rp_98() (0x0C) +#define ag_rp_96() (0x0C) -#define ag_rp_99(n1, n2, n3) ((n1-'0') * 64 + (n2-'0') * 8 + n3-'0') +#define ag_rp_97(n1, n2, n3) ((n1-'0') * 64 + (n2-'0') * 8 + n3-'0') -#define ag_rp_100(n1, n2) (chtoh(n1) * 16 + chtoh(n2)) +#define ag_rp_98(n1, n2) (chtoh(n1) * 16 + chtoh(n2)) -#define ag_rp_101(n1) (chtoh(n1)) +#define ag_rp_99(n1) (chtoh(n1)) -static void ag_rp_102(void) { +static void ag_rp_100(void) { /* Line 288, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '>'; ss[ss_idx][ss_len] = 0; } -static void ag_rp_103(void) { +static void ag_rp_101(void) { /* Line 291, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = '<'; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_104(int c) { +static void ag_rp_102(int c) { /* Line 292, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_105(int c) { +static void ag_rp_103(int c) { /* Line 293, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '\\'; ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -#define ag_rp_106() (gAsm->label(ss[ss_idx--])) +#define ag_rp_104() (gAsm->label(ss[ss_idx--])) -#define ag_rp_107() (gAsm->label(ss[ss_idx--])) +#define ag_rp_105() (gAsm->label(ss[ss_idx--])) -#define ag_rp_108() (gAsm->label(".bss")) +#define ag_rp_106() (gAsm->label(".bss")) -#define ag_rp_109() (gAsm->label(".text")) +#define ag_rp_107() (gAsm->label(".text")) -#define ag_rp_110() (gAsm->label(".data")) +#define ag_rp_108() (gAsm->label(".data")) -#define ag_rp_111() (PAGE) +#define ag_rp_109() (PAGE) -#define ag_rp_112() (INPAGE) +#define ag_rp_110() (INPAGE) -#define ag_rp_113() (condition(-1)) +#define ag_rp_111() (condition(-1)) -#define ag_rp_114() (condition(COND_NOCMP)) +#define ag_rp_112() (condition(COND_NOCMP)) -#define ag_rp_115() (condition(COND_EQ)) +#define ag_rp_113() (condition(COND_EQ)) -#define ag_rp_116() (condition(COND_NE)) +#define ag_rp_114() (condition(COND_NE)) -#define ag_rp_117() (condition(COND_GE)) +#define ag_rp_115() (condition(COND_GE)) -#define ag_rp_118() (condition(COND_LE)) +#define ag_rp_116() (condition(COND_LE)) -#define ag_rp_119() (condition(COND_GT)) +#define ag_rp_117() (condition(COND_GT)) -#define ag_rp_120() (condition(COND_LT)) +#define ag_rp_118() (condition(COND_LT)) -#define ag_rp_121() (gEq->Add(RPN_BITOR)) +#define ag_rp_119() (gEq->Add(RPN_BITOR)) -#define ag_rp_122() (gEq->Add(RPN_BITOR)) +#define ag_rp_120() (gEq->Add(RPN_BITOR)) -#define ag_rp_123() (gEq->Add(RPN_BITXOR)) +#define ag_rp_121() (gEq->Add(RPN_BITXOR)) -#define ag_rp_124() (gEq->Add(RPN_BITXOR)) +#define ag_rp_122() (gEq->Add(RPN_BITXOR)) -#define ag_rp_125() (gEq->Add(RPN_BITAND)) +#define ag_rp_123() (gEq->Add(RPN_BITAND)) -#define ag_rp_126() (gEq->Add(RPN_BITAND)) +#define ag_rp_124() (gEq->Add(RPN_BITAND)) -#define ag_rp_127() (gEq->Add(RPN_LEFTSHIFT)) +#define ag_rp_125() (gEq->Add(RPN_LEFTSHIFT)) -#define ag_rp_128() (gEq->Add(RPN_LEFTSHIFT)) +#define ag_rp_126() (gEq->Add(RPN_LEFTSHIFT)) -#define ag_rp_129() (gEq->Add(RPN_RIGHTSHIFT)) +#define ag_rp_127() (gEq->Add(RPN_RIGHTSHIFT)) -#define ag_rp_130() (gEq->Add(RPN_RIGHTSHIFT)) +#define ag_rp_128() (gEq->Add(RPN_RIGHTSHIFT)) -#define ag_rp_131() (gEq->Add(RPN_ADD)) +#define ag_rp_129() (gEq->Add(RPN_ADD)) -#define ag_rp_132() (gEq->Add(RPN_SUBTRACT)) +#define ag_rp_130() (gEq->Add(RPN_SUBTRACT)) -#define ag_rp_133() (gEq->Add(RPN_MULTIPLY)) +#define ag_rp_131() (gEq->Add(RPN_MULTIPLY)) -#define ag_rp_134() (gEq->Add(RPN_DIVIDE)) +#define ag_rp_132() (gEq->Add(RPN_DIVIDE)) -#define ag_rp_135() (gEq->Add(RPN_MODULUS)) +#define ag_rp_133() (gEq->Add(RPN_MODULUS)) -#define ag_rp_136() (gEq->Add(RPN_MODULUS)) +#define ag_rp_134() (gEq->Add(RPN_MODULUS)) -#define ag_rp_137() (gEq->Add(RPN_EXPONENT)) +#define ag_rp_135() (gEq->Add(RPN_EXPONENT)) -#define ag_rp_138() (gEq->Add(RPN_NOT)) +#define ag_rp_136() (gEq->Add(RPN_NOT)) -#define ag_rp_139() (gEq->Add(RPN_NOT)) +#define ag_rp_137() (gEq->Add(RPN_NOT)) -#define ag_rp_140() (gEq->Add(RPN_BITNOT)) +#define ag_rp_138() (gEq->Add(RPN_BITNOT)) -#define ag_rp_141() (gEq->Add(RPN_NEGATE)) +#define ag_rp_139() (gEq->Add(RPN_NEGATE)) -#define ag_rp_142(n) (gEq->Add((double) n)) +#define ag_rp_140(n) (gEq->Add((double) n)) -static void ag_rp_143(void) { +static void ag_rp_141(void) { /* Line 384, C:/Projects/VirtualT/src/a85parse.syn */ delete gMacro; gMacro = gMacroStack[ms_idx-1]; \ gMacroStack[ms_idx--] = 0; if (gMacro->m_ParamList == 0) \ @@ -853,427 +843,427 @@ static void ag_rp_143(void) { } } -#define ag_rp_144() (gEq->Add(RPN_FLOOR)) +#define ag_rp_142() (gEq->Add(RPN_FLOOR)) -#define ag_rp_145() (gEq->Add(RPN_CEIL)) +#define ag_rp_143() (gEq->Add(RPN_CEIL)) -#define ag_rp_146() (gEq->Add(RPN_LN)) +#define ag_rp_144() (gEq->Add(RPN_LN)) -#define ag_rp_147() (gEq->Add(RPN_LOG)) +#define ag_rp_145() (gEq->Add(RPN_LOG)) -#define ag_rp_148() (gEq->Add(RPN_SQRT)) +#define ag_rp_146() (gEq->Add(RPN_SQRT)) -#define ag_rp_149() (gEq->Add(RPN_IP)) +#define ag_rp_147() (gEq->Add(RPN_IP)) -#define ag_rp_150() (gEq->Add(RPN_FP)) +#define ag_rp_148() (gEq->Add(RPN_FP)) -#define ag_rp_151() (gEq->Add(RPN_HIGH)) +#define ag_rp_149() (gEq->Add(RPN_HIGH)) -#define ag_rp_152() (gEq->Add(RPN_LOW)) +#define ag_rp_150() (gEq->Add(RPN_LOW)) -#define ag_rp_153() (gEq->Add(RPN_PAGE)) +#define ag_rp_151() (gEq->Add(RPN_PAGE)) -#define ag_rp_154() (gEq->Add(RPN_DEFINED, ss[ss_idx--])) +#define ag_rp_152() (gEq->Add(RPN_DEFINED, ss[ss_idx--])) -#define ag_rp_155(n) (n) +#define ag_rp_153(n) (n) -#define ag_rp_156(r) (r) +#define ag_rp_154(r) (r) -#define ag_rp_157(n) (n) +#define ag_rp_155(n) (n) -#define ag_rp_158() (conv_to_dec()) +#define ag_rp_156() (conv_to_dec()) -#define ag_rp_159() (conv_to_hex()) +#define ag_rp_157() (conv_to_hex()) -#define ag_rp_160() (conv_to_bin()) +#define ag_rp_158() (conv_to_bin()) -#define ag_rp_161() (conv_to_oct()) +#define ag_rp_159() (conv_to_oct()) -#define ag_rp_162() (conv_to_hex()) +#define ag_rp_160() (conv_to_hex()) -#define ag_rp_163() (conv_to_hex()) +#define ag_rp_161() (conv_to_hex()) -#define ag_rp_164() (conv_to_bin()) +#define ag_rp_162() (conv_to_bin()) -#define ag_rp_165() (conv_to_oct()) +#define ag_rp_163() (conv_to_oct()) -#define ag_rp_166() (conv_to_dec()) +#define ag_rp_164() (conv_to_dec()) -static void ag_rp_167(int n) { +static void ag_rp_165(int n) { /* Line 431, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_168(int n) { +static void ag_rp_166(int n) { /* Line 432, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 2; integer[0] = '-', integer[1] = n; integer[2] = 0; } -static void ag_rp_169(int n) { +static void ag_rp_167(int n) { /* Line 433, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_170(int n) { +static void ag_rp_168(int n) { /* Line 434, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_171(int n) { +static void ag_rp_169(int n) { /* Line 439, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_172(int n) { +static void ag_rp_170(int n) { /* Line 440, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_173(int n) { +static void ag_rp_171(int n) { /* Line 441, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_174(int n) { +static void ag_rp_172(int n) { /* Line 444, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_175(int n) { +static void ag_rp_173(int n) { /* Line 445, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_176(int n) { +static void ag_rp_174(int n) { /* Line 448, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_177(int n) { +static void ag_rp_175(int n) { /* Line 449, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_178(int n) { +static void ag_rp_176(int n) { /* Line 452, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_179(int n) { +static void ag_rp_177(int n) { /* Line 453, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -#define ag_rp_180(n) (n) +#define ag_rp_178(n) (n) -#define ag_rp_181(n1, n2) ((n1 << 8) | n2) +#define ag_rp_179(n1, n2) ((n1 << 8) | n2) -#define ag_rp_182() ('\\') +#define ag_rp_180() ('\\') -#define ag_rp_183(n) (n) +#define ag_rp_181(n) (n) -#define ag_rp_184() ('\\') +#define ag_rp_182() ('\\') -#define ag_rp_185() ('\n') +#define ag_rp_183() ('\n') -#define ag_rp_186() ('\t') +#define ag_rp_184() ('\t') -#define ag_rp_187() ('\r') +#define ag_rp_185() ('\r') -#define ag_rp_188() ('\0') +#define ag_rp_186() ('\0') -#define ag_rp_189() ('\'') +#define ag_rp_187() ('\'') -#define ag_rp_190() ('\'') +#define ag_rp_188() ('\'') -static double ag_rp_191(void) { +static double ag_rp_189(void) { /* Line 474, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor = 1.0; return (double) conv_to_dec(); } -static double ag_rp_192(int d) { +static double ag_rp_190(int d) { /* Line 475, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor = 10.0; return ((double) (d - '0') / gDivisor); } -static double ag_rp_193(double r, int d) { +static double ag_rp_191(double r, int d) { /* Line 476, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor *= 10.0; return (r + (double) (d - '0') / gDivisor); } -#define ag_rp_194() (reg[reg_cnt++] = '0') +#define ag_rp_192() (reg[reg_cnt++] = '0') -#define ag_rp_195() (reg[reg_cnt++] = '1') +#define ag_rp_193() (reg[reg_cnt++] = '1') -#define ag_rp_196() (reg[reg_cnt++] = '2') +#define ag_rp_194() (reg[reg_cnt++] = '2') -#define ag_rp_197() (reg[reg_cnt++] = '3') +#define ag_rp_195() (reg[reg_cnt++] = '3') -#define ag_rp_198() (reg[reg_cnt++] = '4') +#define ag_rp_196() (reg[reg_cnt++] = '4') -#define ag_rp_199() (reg[reg_cnt++] = '5') +#define ag_rp_197() (reg[reg_cnt++] = '5') -#define ag_rp_200() (reg[reg_cnt++] = '6') +#define ag_rp_198() (reg[reg_cnt++] = '6') -#define ag_rp_201() (reg[reg_cnt++] = '7') +#define ag_rp_199() (reg[reg_cnt++] = '7') -#define ag_rp_202() (reg[reg_cnt++] = '0') +#define ag_rp_200() (reg[reg_cnt++] = '0') -#define ag_rp_203() (reg[reg_cnt++] = '1') +#define ag_rp_201() (reg[reg_cnt++] = '1') -#define ag_rp_204() (reg[reg_cnt++] = '2') +#define ag_rp_202() (reg[reg_cnt++] = '2') -#define ag_rp_205() (reg[reg_cnt++] = '3') +#define ag_rp_203() (reg[reg_cnt++] = '3') -#define ag_rp_206() (reg[reg_cnt++] = '0') +#define ag_rp_204() (reg[reg_cnt++] = '0') -#define ag_rp_207() (reg[reg_cnt++] = '1') +#define ag_rp_205() (reg[reg_cnt++] = '1') -#define ag_rp_208() (reg[reg_cnt++] = '2') +#define ag_rp_206() (reg[reg_cnt++] = '2') -#define ag_rp_209() (reg[reg_cnt++] = '3') +#define ag_rp_207() (reg[reg_cnt++] = '3') -#define ag_rp_210() (reg[reg_cnt++] = '3') +#define ag_rp_208() (reg[reg_cnt++] = '3') -#define ag_rp_211() (reg[reg_cnt++] = '0') +#define ag_rp_209() (reg[reg_cnt++] = '0') -#define ag_rp_212() (reg[reg_cnt++] = '1') +#define ag_rp_210() (reg[reg_cnt++] = '1') -#define ag_rp_213() (reg[reg_cnt++] = '0') +#define ag_rp_211() (reg[reg_cnt++] = '0') -#define ag_rp_214() (reg[reg_cnt++] = '1') +#define ag_rp_212() (reg[reg_cnt++] = '1') -#define ag_rp_215() (reg[reg_cnt++] = '2') +#define ag_rp_213() (reg[reg_cnt++] = '2') -#define ag_rp_216() (reg[reg_cnt++] = '3') +#define ag_rp_214() (reg[reg_cnt++] = '3') -#define ag_rp_217() (reg[reg_cnt++] = '4') +#define ag_rp_215() (reg[reg_cnt++] = '4') -#define ag_rp_218() (reg[reg_cnt++] = '5') +#define ag_rp_216() (reg[reg_cnt++] = '5') -#define ag_rp_219() (gAsm->opcode_arg_0 (OPCODE_ASHR)) +#define ag_rp_217() (gAsm->opcode_arg_0 (OPCODE_ASHR)) -#define ag_rp_220() (gAsm->opcode_arg_0 (OPCODE_CMA)) +#define ag_rp_218() (gAsm->opcode_arg_0 (OPCODE_CMA)) -#define ag_rp_221() (gAsm->opcode_arg_0 (OPCODE_CMC)) +#define ag_rp_219() (gAsm->opcode_arg_0 (OPCODE_CMC)) -#define ag_rp_222() (gAsm->opcode_arg_0 (OPCODE_DAA)) +#define ag_rp_220() (gAsm->opcode_arg_0 (OPCODE_DAA)) -#define ag_rp_223() (gAsm->opcode_arg_0 (OPCODE_DI)) +#define ag_rp_221() (gAsm->opcode_arg_0 (OPCODE_DI)) -#define ag_rp_224() (gAsm->opcode_arg_0 (OPCODE_DSUB)) +#define ag_rp_222() (gAsm->opcode_arg_0 (OPCODE_DSUB)) -#define ag_rp_225() (gAsm->opcode_arg_0 (OPCODE_EI)) +#define ag_rp_223() (gAsm->opcode_arg_0 (OPCODE_EI)) -#define ag_rp_226() (gAsm->opcode_arg_0 (OPCODE_HLT)) +#define ag_rp_224() (gAsm->opcode_arg_0 (OPCODE_HLT)) -#define ag_rp_227() (gAsm->opcode_arg_0 (OPCODE_LHLX)) +#define ag_rp_225() (gAsm->opcode_arg_0 (OPCODE_LHLX)) -#define ag_rp_228() (gAsm->opcode_arg_0 (OPCODE_NOP)) +#define ag_rp_226() (gAsm->opcode_arg_0 (OPCODE_NOP)) -#define ag_rp_229() (gAsm->opcode_arg_0 (OPCODE_PCHL)) +#define ag_rp_227() (gAsm->opcode_arg_0 (OPCODE_PCHL)) -#define ag_rp_230() (gAsm->opcode_arg_0 (OPCODE_RAL)) +#define ag_rp_228() (gAsm->opcode_arg_0 (OPCODE_RAL)) -#define ag_rp_231() (gAsm->opcode_arg_0 (OPCODE_RAR)) +#define ag_rp_229() (gAsm->opcode_arg_0 (OPCODE_RAR)) -#define ag_rp_232() (gAsm->opcode_arg_0 (OPCODE_RC)) +#define ag_rp_230() (gAsm->opcode_arg_0 (OPCODE_RC)) -#define ag_rp_233() (gAsm->opcode_arg_0 (OPCODE_RET)) +#define ag_rp_231() (gAsm->opcode_arg_0 (OPCODE_RET)) -#define ag_rp_234() (gAsm->opcode_arg_0 (OPCODE_RIM)) +#define ag_rp_232() (gAsm->opcode_arg_0 (OPCODE_RIM)) -#define ag_rp_235() (gAsm->opcode_arg_0 (OPCODE_RLC)) +#define ag_rp_233() (gAsm->opcode_arg_0 (OPCODE_RLC)) -#define ag_rp_236() (gAsm->opcode_arg_0 (OPCODE_RLDE)) +#define ag_rp_234() (gAsm->opcode_arg_0 (OPCODE_RLDE)) -#define ag_rp_237() (gAsm->opcode_arg_0 (OPCODE_RM)) +#define ag_rp_235() (gAsm->opcode_arg_0 (OPCODE_RM)) -#define ag_rp_238() (gAsm->opcode_arg_0 (OPCODE_RNC)) +#define ag_rp_236() (gAsm->opcode_arg_0 (OPCODE_RNC)) -#define ag_rp_239() (gAsm->opcode_arg_0 (OPCODE_RNZ)) +#define ag_rp_237() (gAsm->opcode_arg_0 (OPCODE_RNZ)) -#define ag_rp_240() (gAsm->opcode_arg_0 (OPCODE_RP)) +#define ag_rp_238() (gAsm->opcode_arg_0 (OPCODE_RP)) -#define ag_rp_241() (gAsm->opcode_arg_0 (OPCODE_RPE)) +#define ag_rp_239() (gAsm->opcode_arg_0 (OPCODE_RPE)) -#define ag_rp_242() (gAsm->opcode_arg_0 (OPCODE_RPO)) +#define ag_rp_240() (gAsm->opcode_arg_0 (OPCODE_RPO)) -#define ag_rp_243() (gAsm->opcode_arg_0 (OPCODE_RRC)) +#define ag_rp_241() (gAsm->opcode_arg_0 (OPCODE_RRC)) -#define ag_rp_244() (gAsm->opcode_arg_0 (OPCODE_RSTV)) +#define ag_rp_242() (gAsm->opcode_arg_0 (OPCODE_RSTV)) -#define ag_rp_245() (gAsm->opcode_arg_0 (OPCODE_RZ)) +#define ag_rp_243() (gAsm->opcode_arg_0 (OPCODE_RZ)) -#define ag_rp_246() (gAsm->opcode_arg_0 (OPCODE_SHLX)) +#define ag_rp_244() (gAsm->opcode_arg_0 (OPCODE_SHLX)) -#define ag_rp_247() (gAsm->opcode_arg_0 (OPCODE_SIM)) +#define ag_rp_245() (gAsm->opcode_arg_0 (OPCODE_SIM)) -#define ag_rp_248() (gAsm->opcode_arg_0 (OPCODE_SPHL)) +#define ag_rp_246() (gAsm->opcode_arg_0 (OPCODE_SPHL)) -#define ag_rp_249() (gAsm->opcode_arg_0 (OPCODE_STC)) +#define ag_rp_247() (gAsm->opcode_arg_0 (OPCODE_STC)) -#define ag_rp_250() (gAsm->opcode_arg_0 (OPCODE_XCHG)) +#define ag_rp_248() (gAsm->opcode_arg_0 (OPCODE_XCHG)) -#define ag_rp_251() (gAsm->opcode_arg_0 (OPCODE_XTHL)) +#define ag_rp_249() (gAsm->opcode_arg_0 (OPCODE_XTHL)) -#define ag_rp_252() (gAsm->opcode_arg_0 (OPCODE_LRET)) +#define ag_rp_250() (gAsm->opcode_arg_0 (OPCODE_LRET)) -#define ag_rp_253() (gAsm->opcode_arg_1reg (OPCODE_STAX)) +#define ag_rp_251() (gAsm->opcode_arg_1reg (OPCODE_STAX)) -#define ag_rp_254() (gAsm->opcode_arg_1reg (OPCODE_LDAX)) +#define ag_rp_252() (gAsm->opcode_arg_1reg (OPCODE_LDAX)) -#define ag_rp_255() (gAsm->opcode_arg_1reg (OPCODE_POP)) +#define ag_rp_253() (gAsm->opcode_arg_1reg (OPCODE_POP)) -#define ag_rp_256() (gAsm->opcode_arg_1reg (OPCODE_PUSH)) +#define ag_rp_254() (gAsm->opcode_arg_1reg (OPCODE_PUSH)) -#define ag_rp_257() (gAsm->opcode_arg_1reg_2byte (OPCODE_LPOP)) +#define ag_rp_255() (gAsm->opcode_arg_1reg_2byte (OPCODE_LPOP)) -#define ag_rp_258() (gAsm->opcode_arg_1reg_2byte (OPCODE_LPUSH)) +#define ag_rp_256() (gAsm->opcode_arg_1reg_2byte (OPCODE_LPUSH)) -#define ag_rp_259() (gAsm->opcode_arg_1reg (OPCODE_ADC)) +#define ag_rp_257() (gAsm->opcode_arg_1reg (OPCODE_ADC)) -#define ag_rp_260() (gAsm->opcode_arg_1reg (OPCODE_ADD)) +#define ag_rp_258() (gAsm->opcode_arg_1reg (OPCODE_ADD)) -#define ag_rp_261() (gAsm->opcode_arg_1reg (OPCODE_ANA)) +#define ag_rp_259() (gAsm->opcode_arg_1reg (OPCODE_ANA)) -#define ag_rp_262() (gAsm->opcode_arg_1reg (OPCODE_CMP)) +#define ag_rp_260() (gAsm->opcode_arg_1reg (OPCODE_CMP)) -#define ag_rp_263() (gAsm->opcode_arg_1reg (OPCODE_DCR)) +#define ag_rp_261() (gAsm->opcode_arg_1reg (OPCODE_DCR)) -#define ag_rp_264() (gAsm->opcode_arg_1reg (OPCODE_INR)) +#define ag_rp_262() (gAsm->opcode_arg_1reg (OPCODE_INR)) -#define ag_rp_265() (gAsm->opcode_arg_2reg (OPCODE_MOV)) +#define ag_rp_263() (gAsm->opcode_arg_2reg (OPCODE_MOV)) -#define ag_rp_266() (gAsm->opcode_arg_1reg (OPCODE_ORA)) +#define ag_rp_264() (gAsm->opcode_arg_1reg (OPCODE_ORA)) -#define ag_rp_267() (gAsm->opcode_arg_1reg (OPCODE_SBB)) +#define ag_rp_265() (gAsm->opcode_arg_1reg (OPCODE_SBB)) -#define ag_rp_268() (gAsm->opcode_arg_1reg (OPCODE_SUB)) +#define ag_rp_266() (gAsm->opcode_arg_1reg (OPCODE_SUB)) -#define ag_rp_269() (gAsm->opcode_arg_1reg (OPCODE_XRA)) +#define ag_rp_267() (gAsm->opcode_arg_1reg (OPCODE_XRA)) -#define ag_rp_270() (gAsm->opcode_arg_1reg_2byte (OPCODE_SPG)) +#define ag_rp_268() (gAsm->opcode_arg_1reg_2byte (OPCODE_SPG)) -#define ag_rp_271() (gAsm->opcode_arg_1reg_2byte (OPCODE_RPG)) +#define ag_rp_269() (gAsm->opcode_arg_1reg_2byte (OPCODE_RPG)) -#define ag_rp_272() (gAsm->opcode_arg_1reg (OPCODE_DAD)) +#define ag_rp_270() (gAsm->opcode_arg_1reg (OPCODE_DAD)) -#define ag_rp_273() (gAsm->opcode_arg_1reg (OPCODE_DCX)) +#define ag_rp_271() (gAsm->opcode_arg_1reg (OPCODE_DCX)) -#define ag_rp_274() (gAsm->opcode_arg_1reg (OPCODE_INX)) +#define ag_rp_272() (gAsm->opcode_arg_1reg (OPCODE_INX)) -#define ag_rp_275() (gAsm->opcode_arg_1reg_equ16(OPCODE_LXI)) +#define ag_rp_273() (gAsm->opcode_arg_1reg_equ16(OPCODE_LXI)) -#define ag_rp_276() (gAsm->opcode_arg_1reg_equ8(OPCODE_MVI)) +#define ag_rp_274() (gAsm->opcode_arg_1reg_equ8(OPCODE_MVI)) -#define ag_rp_277() (gAsm->opcode_arg_1reg_equ16(OPCODE_SPI)) +#define ag_rp_275() (gAsm->opcode_arg_1reg_equ16(OPCODE_SPI)) -#define ag_rp_278(c) (gAsm->opcode_arg_imm (OPCODE_RST, c)) +#define ag_rp_276(c) (gAsm->opcode_arg_imm (OPCODE_RST, c)) -#define ag_rp_279() (gAsm->opcode_arg_equ8 (OPCODE_ACI)) +#define ag_rp_277() (gAsm->opcode_arg_equ8 (OPCODE_ACI)) -#define ag_rp_280() (gAsm->opcode_arg_equ8 (OPCODE_ADI)) +#define ag_rp_278() (gAsm->opcode_arg_equ8 (OPCODE_ADI)) -#define ag_rp_281() (gAsm->opcode_arg_equ8 (OPCODE_ANI)) +#define ag_rp_279() (gAsm->opcode_arg_equ8 (OPCODE_ANI)) -#define ag_rp_282() (gAsm->opcode_arg_equ16 (OPCODE_CALL)) +#define ag_rp_280() (gAsm->opcode_arg_equ16 (OPCODE_CALL)) -#define ag_rp_283() (gAsm->opcode_arg_equ16 (OPCODE_CC)) +#define ag_rp_281() (gAsm->opcode_arg_equ16 (OPCODE_CC)) -#define ag_rp_284() (gAsm->opcode_arg_equ16 (OPCODE_CM)) +#define ag_rp_282() (gAsm->opcode_arg_equ16 (OPCODE_CM)) -#define ag_rp_285() (gAsm->opcode_arg_equ16 (OPCODE_CNC)) +#define ag_rp_283() (gAsm->opcode_arg_equ16 (OPCODE_CNC)) -#define ag_rp_286() (gAsm->opcode_arg_equ16 (OPCODE_CNZ)) +#define ag_rp_284() (gAsm->opcode_arg_equ16 (OPCODE_CNZ)) -#define ag_rp_287() (gAsm->opcode_arg_equ16 (OPCODE_CP)) +#define ag_rp_285() (gAsm->opcode_arg_equ16 (OPCODE_CP)) -#define ag_rp_288() (gAsm->opcode_arg_equ16 (OPCODE_CPE)) +#define ag_rp_286() (gAsm->opcode_arg_equ16 (OPCODE_CPE)) -#define ag_rp_289() (gAsm->opcode_arg_equ8 (OPCODE_CPI)) +#define ag_rp_287() (gAsm->opcode_arg_equ8 (OPCODE_CPI)) -#define ag_rp_290() (gAsm->opcode_arg_equ16 (OPCODE_CPO)) +#define ag_rp_288() (gAsm->opcode_arg_equ16 (OPCODE_CPO)) -#define ag_rp_291() (gAsm->opcode_arg_equ16 (OPCODE_CZ)) +#define ag_rp_289() (gAsm->opcode_arg_equ16 (OPCODE_CZ)) -#define ag_rp_292() (gAsm->opcode_arg_equ8 (OPCODE_IN)) +#define ag_rp_290() (gAsm->opcode_arg_equ8 (OPCODE_IN)) -#define ag_rp_293() (gAsm->opcode_arg_equ16 (OPCODE_JC)) +#define ag_rp_291() (gAsm->opcode_arg_equ16 (OPCODE_JC)) -#define ag_rp_294() (gAsm->opcode_arg_equ16 (OPCODE_JD)) +#define ag_rp_292() (gAsm->opcode_arg_equ16 (OPCODE_JD)) -#define ag_rp_295() (gAsm->opcode_arg_equ16 (OPCODE_JM)) +#define ag_rp_293() (gAsm->opcode_arg_equ16 (OPCODE_JM)) -#define ag_rp_296() (gAsm->opcode_arg_equ16 (OPCODE_JMP)) +#define ag_rp_294() (gAsm->opcode_arg_equ16 (OPCODE_JMP)) -#define ag_rp_297() (gAsm->opcode_arg_equ16 (OPCODE_JNC)) +#define ag_rp_295() (gAsm->opcode_arg_equ16 (OPCODE_JNC)) -#define ag_rp_298() (gAsm->opcode_arg_equ16 (OPCODE_JND)) +#define ag_rp_296() (gAsm->opcode_arg_equ16 (OPCODE_JND)) -#define ag_rp_299() (gAsm->opcode_arg_equ16 (OPCODE_JNZ)) +#define ag_rp_297() (gAsm->opcode_arg_equ16 (OPCODE_JNZ)) -#define ag_rp_300() (gAsm->opcode_arg_equ16 (OPCODE_JP)) +#define ag_rp_298() (gAsm->opcode_arg_equ16 (OPCODE_JP)) -#define ag_rp_301() (gAsm->opcode_arg_equ16 (OPCODE_JPE)) +#define ag_rp_299() (gAsm->opcode_arg_equ16 (OPCODE_JPE)) -#define ag_rp_302() (gAsm->opcode_arg_equ16 (OPCODE_JPO)) +#define ag_rp_300() (gAsm->opcode_arg_equ16 (OPCODE_JPO)) -#define ag_rp_303() (gAsm->opcode_arg_equ16 (OPCODE_JZ)) +#define ag_rp_301() (gAsm->opcode_arg_equ16 (OPCODE_JZ)) -#define ag_rp_304() (gAsm->opcode_arg_equ16 (OPCODE_LDA)) +#define ag_rp_302() (gAsm->opcode_arg_equ16 (OPCODE_LDA)) -#define ag_rp_305() (gAsm->opcode_arg_equ8 (OPCODE_LDEH)) +#define ag_rp_303() (gAsm->opcode_arg_equ8 (OPCODE_LDEH)) -#define ag_rp_306() (gAsm->opcode_arg_equ8 (OPCODE_LDES)) +#define ag_rp_304() (gAsm->opcode_arg_equ8 (OPCODE_LDES)) -#define ag_rp_307() (gAsm->opcode_arg_equ16 (OPCODE_LHLD)) +#define ag_rp_305() (gAsm->opcode_arg_equ16 (OPCODE_LHLD)) -#define ag_rp_308() (gAsm->opcode_arg_equ8 (OPCODE_ORI)) +#define ag_rp_306() (gAsm->opcode_arg_equ8 (OPCODE_ORI)) -#define ag_rp_309() (gAsm->opcode_arg_equ8 (OPCODE_OUT)) +#define ag_rp_307() (gAsm->opcode_arg_equ8 (OPCODE_OUT)) -#define ag_rp_310() (gAsm->opcode_arg_equ8 (OPCODE_SBI)) +#define ag_rp_308() (gAsm->opcode_arg_equ8 (OPCODE_SBI)) -#define ag_rp_311() (gAsm->opcode_arg_equ16 (OPCODE_SHLD)) +#define ag_rp_309() (gAsm->opcode_arg_equ16 (OPCODE_SHLD)) -#define ag_rp_312() (gAsm->opcode_arg_equ16 (OPCODE_STA)) +#define ag_rp_310() (gAsm->opcode_arg_equ16 (OPCODE_STA)) -#define ag_rp_313() (gAsm->opcode_arg_equ8 (OPCODE_SUI)) +#define ag_rp_311() (gAsm->opcode_arg_equ8 (OPCODE_SUI)) -#define ag_rp_314() (gAsm->opcode_arg_equ8 (OPCODE_XRI)) +#define ag_rp_312() (gAsm->opcode_arg_equ8 (OPCODE_XRI)) -#define ag_rp_315() (gAsm->opcode_arg_equ8 (OPCODE_BR)) +#define ag_rp_313() (gAsm->opcode_arg_equ8 (OPCODE_BR)) -#define ag_rp_316() (gAsm->opcode_arg_equ16 (OPCODE_BRA)) +#define ag_rp_314() (gAsm->opcode_arg_equ16 (OPCODE_BRA)) -#define ag_rp_317() (gAsm->opcode_arg_equ16 (OPCODE_BZ)) +#define ag_rp_315() (gAsm->opcode_arg_equ16 (OPCODE_BZ)) -#define ag_rp_318() (gAsm->opcode_arg_equ16 (OPCODE_BNZ)) +#define ag_rp_316() (gAsm->opcode_arg_equ16 (OPCODE_BNZ)) -#define ag_rp_319() (gAsm->opcode_arg_equ16 (OPCODE_BC)) +#define ag_rp_317() (gAsm->opcode_arg_equ16 (OPCODE_BC)) -#define ag_rp_320() (gAsm->opcode_arg_equ16 (OPCODE_BNC)) +#define ag_rp_318() (gAsm->opcode_arg_equ16 (OPCODE_BNC)) -#define ag_rp_321() (gAsm->opcode_arg_equ16 (OPCODE_BM)) +#define ag_rp_319() (gAsm->opcode_arg_equ16 (OPCODE_BM)) -#define ag_rp_322() (gAsm->opcode_arg_equ16 (OPCODE_BP)) +#define ag_rp_320() (gAsm->opcode_arg_equ16 (OPCODE_BP)) -#define ag_rp_323() (gAsm->opcode_arg_equ16 (OPCODE_BPE)) +#define ag_rp_321() (gAsm->opcode_arg_equ16 (OPCODE_BPE)) -#define ag_rp_324() (gAsm->opcode_arg_equ16 (OPCODE_RCALL)) +#define ag_rp_322() (gAsm->opcode_arg_equ16 (OPCODE_RCALL)) -#define ag_rp_325() (gAsm->opcode_arg_equ8 (OPCODE_SBZ)) +#define ag_rp_323() (gAsm->opcode_arg_equ8 (OPCODE_SBZ)) -#define ag_rp_326() (gAsm->opcode_arg_equ8 (OPCODE_SBNZ)) +#define ag_rp_324() (gAsm->opcode_arg_equ8 (OPCODE_SBNZ)) -#define ag_rp_327() (gAsm->opcode_arg_equ8 (OPCODE_SBC)) +#define ag_rp_325() (gAsm->opcode_arg_equ8 (OPCODE_SBC)) -#define ag_rp_328() (gAsm->opcode_arg_equ8 (OPCODE_SBNC)) +#define ag_rp_326() (gAsm->opcode_arg_equ8 (OPCODE_SBNC)) -#define ag_rp_329() (gAsm->opcode_arg_equ24 (OPCODE_LCALL)) +#define ag_rp_327() (gAsm->opcode_arg_equ24 (OPCODE_LCALL)) -#define ag_rp_330() (gAsm->opcode_arg_equ24 (OPCODE_LJMP)) +#define ag_rp_328() (gAsm->opcode_arg_equ24 (OPCODE_LJMP)) #define READ_COUNTS @@ -1313,29 +1303,29 @@ static const unsigned short ag_rpx[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 3, 4, 5, 6, 7, 8, 0, 0, 9, 10, 11, 12, 13, 14, 15, 0, 0, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 0, 34, 0, 35, 36, - 37, 38, 39, 0, 0, 0, 40, 41, 0, 0, 42, 0, 0, 0, 43, 0, 0, 44, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 32, 0, 33, 34, 35, 36, + 37, 0, 0, 0, 38, 39, 0, 0, 40, 0, 0, 0, 41, 0, 0, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 0, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 0, - 0, 79, 80, 81, 82, 83, 84, 85, 0, 86, 87, 0, 88, 89, 0, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 0, 0,100,101,102,103,104,105, 0,106,107, - 108,109,110,111,112,113,114, 0, 0, 0,115, 0, 0,116, 0, 0,117, 0, - 0,118, 0, 0,119, 0, 0,120, 0, 0,121,122, 0,123,124, 0,125,126, - 0,127,128,129,130, 0,131,132, 0,133,134,135,136,137, 0,138,139,140, - 141,142,143, 0, 0,144,145,146,147,148,149,150,151,152,153,154,155,156, - 157,158,159,160,161,162,163,164, 0, 0,165,166,167,168,169,170, 0, 0, + 63, 64, 65, 0, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 0, 0, 77, + 78, 79, 80, 81, 82, 83, 0, 84, 85, 0, 86, 87, 0, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 0, 0, 98, 99,100,101,102,103, 0,104,105,106,107, + 108,109,110,111,112, 0, 0, 0,113, 0, 0,114, 0, 0,115, 0, 0,116, + 0, 0,117, 0, 0,118, 0, 0,119,120, 0,121,122, 0,123,124, 0,125, + 126,127,128, 0,129,130, 0,131,132,133,134,135, 0,136,137,138,139,140, + 141, 0, 0,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156, + 157,158,159,160,161,162, 0, 0,163,164,165,166,167,168, 0, 0,169,170, 171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188, - 189,190, 0,191,192,193,194,195,196,197,198,199, 0, 0,200,201, 0, 0, - 202, 0, 0,203, 0, 0,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0,219,220,221,222,223, 0, 0,224,225,226, 0, 0, 0,227,228,229,230, - 231,232,233,234,235, 0, 0,236,237,238,239,240,241,242,243,244,245, 0, - 0, 0,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261, - 262,263,264,265,266,267,268,269,270,271,272,273,274, 0,275, 0,276, 0, - 277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293, 0, - 0, 0, 0, 0,294,295,296,297, 0, 0, 0, 0, 0,298,299,300,301,302, - 303,304, 0, 0, 0,305, 0, 0, 0,306,307,308,309,310,311,312,313,314, - 315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330 + 0,189,190,191,192,193,194,195,196,197, 0, 0,198,199, 0, 0,200, 0, + 0,201, 0, 0,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,217, + 218,219,220,221, 0, 0,222,223,224, 0, 0, 0,225,226,227,228,229,230, + 231,232,233, 0, 0,234,235,236,237,238,239,240,241,242,243, 0, 0, 0, + 244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261, + 262,263,264,265,266,267,268,269,270,271,272, 0,273, 0,274, 0,275,276, + 277,278,279,280,281,282,283,284,285,286,287,288,289,290,291, 0, 0, 0, + 0, 0,292,293,294,295, 0, 0, 0, 0, 0,296,297,298,299,300,301,302, + 0, 0, 0,303, 0, 0, 0,304,305,306,307,308,309,310,311,312,313,314, + 315,316,317,318,319,320,321,322,323,324,325,326,327,328 }; static const unsigned char ag_key_itt[] = { @@ -1354,34 +1344,34 @@ static const unsigned char ag_key_itt[] = { }; static const unsigned short ag_key_pt[] = { - 1,432, 1,433, 1,434, 1,435, 1,441, 1,440, 1,442, 1,444, - 1,445, 1,446, 1,447, 1,448, 1,449, 1,450, 1,451, 1,452, - 1,453, 1,454, 1,455, 1,460, 1,461, 1,462, 1,465, 1,466, - 1,467, 1,468, 1,469, 1,470, 1,471, 1,472, 1,473, 1,474, - 1,475, 1,476, 1,477, 1,478, 1,479, 1,480, 1,482, 1,483, - 1,484, 1,485, 1,487, 1,488, 1,489, 1,490, 1,491, 1,492, - 1,134, 1,495, 1,496, 1,499, 1,501, 1,503, 1,505, 1,507, - 1,510, 1,512, 1,514, 1,516, 1,518, 1,524, 1,527, 1,529, - 1,530, 1,531, 1,532, 1,533, 1,534, 1,535, 1,536, 1,537, - 1,539, 1,222, 1,223, 1,235, 1,236, 1,237, 1,238, 1,239, - 1,240, 1,241, 1,542, 1,670, 1,247, 1,249, 1,545, 1,541, - 1,543, 1,544, 1,546, 1,547, 1,548, 1,549, 1,550, 1,551, - 1,552, 1,553, 1,554, 1,555, 1,556, 1,557, 1,558, 1,559, - 1,560, 1,561, 1,562, 1,563, 1,564, 1,565, 1,566, 1,567, - 1,568, 1,569, 1,570, 1,571, 1,572, 1,573, 1,574, 1,575, - 1,576, 1,577, 1,578, 1,579, 1,580, 1,581, 1,582, 1,583, - 1,584, 1,585, 1,586, 1,587, 1,588, 1,589, 1,590, 1,591, - 1,592, 1,593, 1,594, 1,595, 1,597, 1,598, 1,599, 1,600, - 1,601, 1,602, 1,603, 1,604, 1,605, 1,606, 1,607, 1,608, - 1,609, 1,611, 1,612, 1,613, 1,614, 1,615, 1,616, 1,617, - 1,618, 1,619, 1,620, 1,621, 1,622, 1,623, 1,624, 1,625, - 1,626, 1,627, 1,628, 1,629, 1,630, 1,631, 1,632, 1,633, - 1,634, 1,635, 1,636, 1,637, 1,638, 1,639, 1,640, 1,641, - 1,642, 1,643, 1,644, 1,645, 1,646, 1,647, 1,648, 1,649, - 1,650, 1,651, 1,652, 1,653, 1,654, 1,655, 1,656, 1,657, - 1,658, 1,659, 1,660, 1,661, 1,662, 1,663, 1,664, 1,665, - 1,666, 1,667, 1,668, 1,669, 1,671, 1,672, 1,673, 1,674, - 1,675, 1,676, 1,677, 1,678, 1,679, 1,680, 1,681,0 + 1,430, 1,431, 1,432, 1,433, 1,439, 1,438, 1,440, 1,442, + 1,443, 1,444, 1,445, 1,446, 1,447, 1,448, 1,449, 1,450, + 1,451, 1,452, 1,453, 1,457, 1,458, 1,459, 1,462, 1,463, + 1,464, 1,465, 1,466, 1,467, 1,468, 1,469, 1,470, 1,471, + 1,472, 1,473, 1,474, 1,475, 1,476, 1,477, 1,479, 1,480, + 1,481, 1,482, 1,484, 1,485, 1,486, 1,487, 1,488, 1,489, + 1,132, 1,492, 1,493, 1,496, 1,498, 1,500, 1,502, 1,504, + 1,507, 1,509, 1,511, 1,513, 1,515, 1,521, 1,524, 1,526, + 1,527, 1,528, 1,529, 1,530, 1,531, 1,532, 1,533, 1,534, + 1,536, 1,220, 1,221, 1,233, 1,234, 1,235, 1,236, 1,237, + 1,238, 1,239, 1,539, 1,667, 1,245, 1,247, 1,542, 1,538, + 1,540, 1,541, 1,543, 1,544, 1,545, 1,546, 1,547, 1,548, + 1,549, 1,550, 1,551, 1,552, 1,553, 1,554, 1,555, 1,556, + 1,557, 1,558, 1,559, 1,560, 1,561, 1,562, 1,563, 1,564, + 1,565, 1,566, 1,567, 1,568, 1,569, 1,570, 1,571, 1,572, + 1,573, 1,574, 1,575, 1,576, 1,577, 1,578, 1,579, 1,580, + 1,581, 1,582, 1,583, 1,584, 1,585, 1,586, 1,587, 1,588, + 1,589, 1,590, 1,591, 1,592, 1,594, 1,595, 1,596, 1,597, + 1,598, 1,599, 1,600, 1,601, 1,602, 1,603, 1,604, 1,605, + 1,606, 1,608, 1,609, 1,610, 1,611, 1,612, 1,613, 1,614, + 1,615, 1,616, 1,617, 1,618, 1,619, 1,620, 1,621, 1,622, + 1,623, 1,624, 1,625, 1,626, 1,627, 1,628, 1,629, 1,630, + 1,631, 1,632, 1,633, 1,634, 1,635, 1,636, 1,637, 1,638, + 1,639, 1,640, 1,641, 1,642, 1,643, 1,644, 1,645, 1,646, + 1,647, 1,648, 1,649, 1,650, 1,651, 1,652, 1,653, 1,654, + 1,655, 1,656, 1,657, 1,658, 1,659, 1,660, 1,661, 1,662, + 1,663, 1,664, 1,665, 1,666, 1,668, 1,669, 1,670, 1,671, + 1,672, 1,673, 1,674, 1,675, 1,676, 1,677, 1,678,0 }; static const unsigned char ag_key_ch[] = { @@ -1580,9 +1570,9 @@ static const unsigned char ag_key_act[] = { }; static const unsigned short ag_key_parm[] = { - 0,162,164,163, 0,429,426, 0, 4, 0, 6, 0, 0, 0, 0, 0,439, 96, - 135, 0, 0, 0, 0,500, 0,463, 0,525,428,464, 0,162,164,163, 0,429, - 426, 0,515,504, 0,497, 0,502,517, 0,280,282,322, 0,284,116,324, 0, + 0,160,162,161, 0,427,424, 0, 4, 0, 6, 0, 0, 0, 0, 0,437, 96, + 133, 0, 0, 0, 0,497, 0,460, 0,522,426,461, 0,160,162,161, 0,427, + 424, 0,512,501, 0,494, 0,499,514, 0,280,282,322, 0,284,116,324, 0, 44,182, 0,320, 0, 0,186, 0, 0,424,422, 0,430, 0,418, 0,166, 48, 426, 0,428,416, 52,420, 0,190,192,286, 0,332,334, 0,338,340,342, 0, 326,328,128,330, 0,336, 38,344, 0,194,306, 0,288,308, 0,144, 0, 36, @@ -1601,11 +1591,11 @@ static const unsigned short ag_key_parm[] = { 0,238, 0, 0,248, 0,440,436, 0,296,438,406, 0,434, 0,254, 0,408, 252,184,250, 0,118,120, 0,302,258,316, 0,268, 0,410,260, 70, 0,298, 412, 0, 0, 2, 0,256,172,134, 0, 0, 88, 0, 54, 84, 0,300,414, 0, - 262,114, 0,264, 0,180,439, 96,135,232,242, 0,494, 0, 0,508,498,506, + 262,114, 0,264, 0,180,437, 96,133,230,240, 0,491, 0, 0,505,495,503, 164,150,152,154,156, 0, 0,158, 0, 0,160,162, 0, 0, 0, 0, 0, 0, - 34, 16, 58, 0,459, 0,162,164,163, 0,429,426, 0,439, 96,135, 0, 0, + 34, 16, 58, 0,456, 0,160,162,161, 0,427,424, 0,437, 96,133, 0, 0, 0, 24, 28, 0, 0, 30, 32, 0, 20, 26, 0, 22, 4, 0, 36, 0, 0, 8, - 34, 0,429,426, 0,135,464, 0,161, 0,463, 0,429,426, 0,280,282,322, + 34, 0,427,424, 0,133,461, 0,159, 0,460, 0,427,424, 0,280,282,322, 0,284,324, 0, 44,182, 0,320, 0, 0,186, 0, 0,424,422, 0,430, 0, 418, 0,166, 48,426, 0,428,416, 52,420, 0,190,192,286, 0,332,334, 0, 338,340,342, 0,326,328,330, 0,336, 38,344, 0,194,306, 0,288,308, 0, @@ -1621,9 +1611,9 @@ static const unsigned short ag_key_parm[] = { 220,230,222,224, 0,232, 0,238, 0, 0,248, 0,440,436, 0,296,438,406, 0,434, 0,254, 0,408,252,184,250, 0, 0, 0,302,258,316, 0,268, 0, 410,260, 70, 0,298,412, 0, 0, 2, 0,256, 0, 0, 0, 88, 0, 54, 84, - 0,300,414, 0,262, 0,264, 0, 96,135,464, 0, 0, 0, 0, 0, 0, 74, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 58, 0, 0,429,426, 0, - 4, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0,463, 0,429,426, 0,280,282, + 0,300,414, 0,262, 0,264, 0, 96,133,461, 0, 0, 0, 0, 0, 0, 74, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 58, 0, 0,427,424, 0, + 4, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0,460, 0,427,424, 0,280,282, 322, 0,284,324, 0, 44,182, 0,320, 0, 0,186, 0, 0,424,422, 0,430, 0,418, 0,166, 48,426, 0,428,416, 52,420, 0,190,192,286, 0,332,334, 0,338,340,342, 0,326,328,330, 0,336, 38,344, 0,194,306, 0,288,308, @@ -1639,55 +1629,55 @@ static const unsigned short ag_key_parm[] = { 246, 0,318, 0, 0,220,230,222,224, 0,232, 0,238, 0, 0,248, 0,440, 436, 0,296,438,406, 0,434, 0,254, 0,408,252,184,250, 0, 0, 0,302, 258,316, 0,268, 0,410,260, 70, 0,298,412, 0, 0, 0,256, 0, 0, 0, - 88, 0, 54, 84, 0,300,414, 0,262, 0,264, 0, 96,135,464, 0, 0, 0, + 88, 0, 54, 84, 0,300,414, 0,262, 0,264, 0, 96,133,461, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 58, 0, - 0, 96,135, 0,429,426, 0, 0, 0,126,138, 0,132,142, 0,130, 0, 0, - 96,135,232,128,144, 0,140,136, 0,124, 94,134, 0, 14, 18, 0, 0, 12, - 10, 16, 0,162,164,163, 0,429,426, 0, 4, 0, 6, 0, 0, 0, 0, 0, - 439, 96,135,428, 0, 0, 0, 0,428,464, 0,429,426, 0, 48, 52, 0, 40, + 0, 96,133, 0,427,424, 0, 0, 0,126,138, 0,132,142, 0,130, 0, 0, + 96,133,230,128,144, 0,140,136, 0,124, 94,134, 0, 14, 18, 0, 0, 12, + 10, 16, 0,160,162,161, 0,427,424, 0, 4, 0, 6, 0, 0, 0, 0, 0, + 437, 96,133,426, 0, 0, 0, 0,426,461, 0,427,424, 0, 48, 52, 0, 40, 0, 50, 46, 56, 0, 78, 14, 0, 18, 64, 0, 0, 62, 0, 0, 0, 72, 0, 0, 0, 0, 4, 0, 6, 0, 0, 0, 0, 0, 90, 10, 0, 0, 82, 0, 92, - 66, 80, 0, 68, 86, 0, 94, 76, 60, 0, 2, 70, 88, 0, 54, 84, 0,463, + 66, 80, 0, 68, 86, 0, 94, 76, 60, 0, 2, 70, 88, 0, 54, 84, 0,460, 0, 0, 44, 0, 38, 0, 0, 74, 12, 0, 0, 0, 0, 42, 0, 0, 0, 16, - 58,459, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0,428,429, 0,429,426, - 0,428, 0,459, 0,429,426, 0, 0, 98, 94, 0,429,426, 0,180, 0, 0, - 166, 0,168,176, 0,170, 0,150,154,158,178,172, 0,242,164,150,152,154, + 58,456, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0,426,427, 0,427,424, + 0,426, 0,456, 0,427,424, 0, 0, 98, 94, 0,427,424, 0,180, 0, 0, + 166, 0,168,176, 0,170, 0,150,154,158,178,172, 0,240,164,150,152,154, 156,158,160,162, 0,166, 0,168, 0,170, 0,150,154,158,172, 0,166, 0, - 168, 0,170, 0,164,150,154,158,174, 0,166, 0,168, 0,150,154, 0,500, - 0,429,426, 0,515,504, 0,497, 0,502,517, 0,180,525,494, 0,508,498, - 506, 0,500, 0,429,426, 0,515,504, 0,497, 0,502,517, 0,104,108, 0, - 106,110, 0,118,120, 0, 0, 0,180,525,494, 0,508,498,506,116,100, 0, + 168, 0,170, 0,164,150,154,158,174, 0,166, 0,168, 0,150,154, 0,497, + 0,427,424, 0,512,501, 0,494, 0,499,514, 0,180,522,491, 0,505,495, + 503, 0,497, 0,427,424, 0,512,501, 0,494, 0,499,514, 0,104,108, 0, + 106,110, 0,118,120, 0, 0, 0,180,522,491, 0,505,495,503,116,100, 0, 0,122,102,112, 0,114, 0, 48, 52, 0, 40, 0, 50, 46, 56, 0, 78, 14, 0, 18, 64, 0, 0, 62, 0, 0, 0, 72, 0, 0, 0, 90, 10, 0, 0, 82, 0, 92, 66, 80, 0, 68, 86, 0, 94, 76, 60, 0, 70, 88, 0, 54, 84, 0, - 463,464, 44, 0, 38, 0, 0, 74, 12, 0, 0, 0, 42, 0, 0, 0, 16, 58, - 0,429,426, 0,494, 0, 0,500, 0,429,426, 0,515,504, 0,497, 0,502, - 517, 0,104,108, 0,106,110, 0,112, 0,118,120, 0, 0, 0,180,525,494, - 0,508,498,506,116,100, 0, 0,122,102,148,146, 0,114, 0,234, 0,500, - 0,429,426, 0,515,504, 0,497, 0,502,517, 0,104,108, 0,106,110, 0, - 112, 0,118,120, 0, 0, 0,180,525,494, 0,508,498,506, 0, 0,122,102, - 148,146, 0,114, 0,429,426, 0,126,138, 0,132,142, 0,130, 0, 0, 96, - 135,232,428, 0,128,144, 0,140,136, 0,124, 94,134,459, 0,126,138, 0, - 132,142, 0,130, 0, 0, 96,135,232,128,144, 0,140,136, 0, 94,134, 0, - 429,426, 0,126,138, 0,132,142, 0,130, 0, 0, 96,135,232,428, 0,128, - 144, 0,140,136, 0, 94,134,459, 0,500, 0,515,504, 0,497, 0,502,517, - 0,104,108, 0,106,110, 0,118,120, 0, 0, 0,180,525,494,508,498,506, - 116,100, 0, 0,122,102,112, 0,114, 0,500, 0,429,426, 0,515,504, 0, - 497, 0,502,517, 0,104,108, 0,106,110, 0,118,120, 0, 0, 0,180,494, - 0,508,498,506,116,100, 0, 0,102,112, 0,114, 0,500, 0,429,426, 0, - 504, 0,497, 0,502, 0,104,108, 0,106,110, 0,180,494, 0,508,498,506, - 116,100, 0, 0,102,112,114, 0,500, 0,429,426, 0,504, 0,497, 0,502, - 0,104,108, 0,106,110, 0,180,494, 0,508,498,506,100, 0, 0,102,112, - 114, 0,500, 0,429,426, 0,504, 0,497, 0,502, 0,104,108, 0,106,110, - 0,180,494, 0,508,498,506,100, 0, 0,102,112, 0,429,426, 0,504, 0, - 497, 0,502, 0,104,108, 0,106,110, 0,500, 0,508,498,506,100, 0, 0, - 102, 0,500, 0,525,428, 0,429,426, 0,515,504, 0,497, 0,502,517, 0, - 104,108, 0,106,110, 0,118,120, 0, 0, 0,180, 0,494, 0,508,498,506, - 116,100, 0, 0,122,102,112, 0,114,459, 0, 48, 52, 0, 40, 0, 50, 46, + 460,461, 44, 0, 38, 0, 0, 74, 12, 0, 0, 0, 42, 0, 0, 0, 16, 58, + 0,427,424, 0,491, 0, 0,497, 0,427,424, 0,512,501, 0,494, 0,499, + 514, 0,104,108, 0,106,110, 0,112, 0,118,120, 0, 0, 0,180,522,491, + 0,505,495,503,116,100, 0, 0,122,102,148,146, 0,114, 0,232, 0,497, + 0,427,424, 0,512,501, 0,494, 0,499,514, 0,104,108, 0,106,110, 0, + 112, 0,118,120, 0, 0, 0,180,522,491, 0,505,495,503, 0, 0,122,102, + 148,146, 0,114, 0,427,424, 0,126,138, 0,132,142, 0,130, 0, 0, 96, + 133,230,426, 0,128,144, 0,140,136, 0,124, 94,134,456, 0,126,138, 0, + 132,142, 0,130, 0, 0, 96,133,230,128,144, 0,140,136, 0, 94,134, 0, + 427,424, 0,126,138, 0,132,142, 0,130, 0, 0, 96,133,230,426, 0,128, + 144, 0,140,136, 0, 94,134,456, 0,497, 0,512,501, 0,494, 0,499,514, + 0,104,108, 0,106,110, 0,118,120, 0, 0, 0,180,522,491,505,495,503, + 116,100, 0, 0,122,102,112, 0,114, 0,497, 0,427,424, 0,512,501, 0, + 494, 0,499,514, 0,104,108, 0,106,110, 0,118,120, 0, 0, 0,180,491, + 0,505,495,503,116,100, 0, 0,102,112, 0,114, 0,497, 0,427,424, 0, + 501, 0,494, 0,499, 0,104,108, 0,106,110, 0,180,491, 0,505,495,503, + 116,100, 0, 0,102,112,114, 0,497, 0,427,424, 0,501, 0,494, 0,499, + 0,104,108, 0,106,110, 0,180,491, 0,505,495,503,100, 0, 0,102,112, + 114, 0,497, 0,427,424, 0,501, 0,494, 0,499, 0,104,108, 0,106,110, + 0,180,491, 0,505,495,503,100, 0, 0,102,112, 0,427,424, 0,501, 0, + 494, 0,499, 0,104,108, 0,106,110, 0,497, 0,505,495,503,100, 0, 0, + 102, 0,497, 0,522,426, 0,427,424, 0,512,501, 0,494, 0,499,514, 0, + 104,108, 0,106,110, 0,118,120, 0, 0, 0,180, 0,491, 0,505,495,503, + 116,100, 0, 0,122,102,112, 0,114,456, 0, 48, 52, 0, 40, 0, 50, 46, 56, 0, 78, 14, 0, 18, 64, 0, 0, 62, 0, 0, 0, 72, 0, 0, 0, 0, 90, 10, 0, 0, 82, 0, 92, 66, 80, 0, 68, 86, 0, 94, 76, 60, 0, 2, - 70, 88, 0, 54, 84, 0,463,464, 44, 0, 38, 0, 0, 74, 12, 0, 0, 0, - 42, 0, 0, 0, 16, 58, 0,232, 0,280,282,322, 0,284,324, 0,320, 0, + 70, 88, 0, 54, 84, 0,460,461, 44, 0, 38, 0, 0, 74, 12, 0, 0, 0, + 42, 0, 0, 0, 16, 58, 0,230, 0,280,282,322, 0,284,324, 0,320, 0, 0,186,182, 0,424,422, 0,430, 0,418, 0,166,426, 0,428,416,420, 0, 190,192,286, 0,332,334, 0,338,340,342, 0,326,328,330, 0,336,344, 0, 194,306, 0,288,308, 0,390,396, 0, 0, 0, 0,196,198, 0,200,204, 0, @@ -1700,11 +1690,11 @@ static const unsigned short ag_key_parm[] = { 0, 0,248, 0,440,436, 0,296,438,406, 0,434, 0,254, 0,408,252,184, 250, 0, 0, 0,302,258,316, 0,268, 0,410,260, 0,298,412, 0, 0, 0, 256, 0, 0, 0, 0,300,414, 0,262, 0,264, 0, 0, 0, 0, 0,202, 0, - 0, 0, 0, 0,212, 0, 0, 0, 0, 0, 0,429,426, 0, 96,135, 0, 0, - 429,426, 0,180,494, 0, 0,494, 0,429,426, 0, 0,148,146, 0,459, 0, - 128, 0,144, 0,126,138, 0,140, 0,132,142, 0,130, 0, 0, 96,135,232, - 242,164,150,152,154,156, 0,158,136,160,162,124, 94,134, 0,180, 0,429, - 426, 0, 0,459, 0 + 0, 0, 0, 0,212, 0, 0, 0, 0, 0, 0,427,424, 0, 96,133, 0, 0, + 427,424, 0,180,491, 0, 0,491, 0,427,424, 0, 0,148,146, 0,456, 0, + 128, 0,144, 0,126,138, 0,140, 0,132,142, 0,130, 0, 0, 96,133,230, + 240,164,150,152,154,156, 0,158,136,160,162,124, 94,134, 0,180, 0,427, + 424, 0, 0,456, 0 }; static const unsigned short ag_key_jmp[] = { @@ -1860,39 +1850,39 @@ static const unsigned short ag_key_index[] = { 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, 1116,1116,1116,1116,1116,1116,1318,1318,1318,1318,1328,1328,1307,1307, 1307,1285,1285,1291,1291,1291,1291,1291,1291,1291,1291,1291,1291,1291, - 1344,1275,1376,1105,1275,1116,1440,1105, 0, 0,1105, 0,1462,1105,1105, - 1105,1105, 0, 0, 0,1376,1491, 0,1509,1376, 0,1376,1376,1376,1537, - 0,1105, 0, 0, 0, 0, 0, 0, 0, 0, 0,1376,1376,1565, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1590,1614,1590,1614,1116,1590,1590,1590, - 1590,1376,1650,1690,1690,1722,1753,1783,1810,1116,1105,1105,1105,1105, - 1105,1105,1105,1099,1099,1105,1105,1105,1105, 0,1105,1105,1105, 0, 0, - 1261,1565,1261,1565,1255,1261,1261,1261,1261,1261,1261,1261,1261,1261, - 1261,1261,1261,1261,1261,1261,1261,1261,1261,1261,1614,1565,1565,1565, - 1614,1847,1261,1565,1614,1261,1255,1261,1261,1152, 0, 0, 0,1914,1105, - 1268,1285,1291,1307, 0, 0, 0, 0,1116,1116,1116,1116,1116,1116,1116, + 1344,1275,1376,1105,1275,1116,1440,1105, 0,1105, 0,1462,1105,1105,1105, + 1105, 0, 0, 0,1376,1491, 0,1509,1376, 0,1376,1376,1376,1537, 0,1105, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1376,1376,1565, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1590,1614,1590,1614,1116,1590,1590,1590,1590,1376, + 1650,1690,1690,1722,1753,1783,1810,1116,1105,1105,1105,1105,1105,1105, + 1105,1099,1099,1105,1105,1105,1105, 0,1105,1105,1105, 0, 0,1261,1565, + 1261,1565,1255,1261,1261,1261,1261,1261,1261,1261,1261,1261,1261,1261, + 1261,1261,1261,1261,1261,1261,1261,1261,1614,1565,1565,1565,1614,1847, + 1261,1565,1614,1261,1255,1261,1261,1152, 0, 0, 0,1914,1105,1268,1285, + 1291,1307, 0, 0, 0, 0,1116,1116,1116,1116,1116,1116,1116,1116,1116, 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, - 1116,1116,1116,1318,1318,1318,1318,1328,1328,1307,1307,1307,1285,1285, - 1291,1291,1291,1291,1291,1291,1291,1291,1291,1291,1291,1116,1933,2154, - 2154,1099,1099, 0, 0,1105,1105, 0, 0,1105,1105,2174,2174, 0, 0,1116, - 1116,1116,1116,1116,1116,1099,1099,1099,1099,1099,1099,1099,1099,1099, - 1099,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1105,1116,1116, - 1116,1116,1099,1268,1268,1105, 0, 0,1105, 0,1105,1105, 0, 0,1509, - 1376,1376, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1116, 0,1590,1590, - 1590,1590,1590,1590,1590,1116,1116,1116,1116,1116,1116,1116,1116,1116, + 1116,1318,1318,1318,1318,1328,1328,1307,1307,1307,1285,1285,1291,1291, + 1291,1291,1291,1291,1291,1291,1291,1291,1291,1116,1933,2154,2154,1099, + 1099, 0, 0,1105,1105, 0, 0,1105,1105,2174,2174, 0, 0,1116,1116,1116, + 1116,1116,1116,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1116, + 1116,1116,1116,1116,1116,1116,1116,1116,1116,1105,1116,1116,1116,1116, + 1099,1268,1268,1105, 0,1105, 0,1105,1105, 0, 0,1509,1376,1376, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1116, 0,1590,1590,1590,1590,1590, + 1590,1590,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, - 1116,1116,1116,1116,1116,1116,1116,1116,1116,1105,1105,1105,1105,1105, - 1099,1105,1105, 0,1105,1105, 0,1105,1105,1105,1116,1116,1116,1116,1105, - 1105,1105,1275,1275,1275,2181,1275,1116,1116,1116,1275,1275,2185,1509, - 1509,1462,2185, 0,2190,2154,1509, 0,1116,1462,1462,1462,1462,1462, 0, - 0,2194, 0, 0, 0, 0,1099,1116,1116,1116,1116,1116,1116,1116,1116, - 1116,1116, 0,1590,1590,1590,1590,1590,1116,1116,1116,1116,1116,1116,1116, - 1116,1116,1116,1116,1116,1105,1105,1105,1105,1105,1105,1105,1116,1116, - 1116,2185,1509,2211,1116,2229,1275,1509,1116,1462,1099,2234,2234,1105, - 0, 0,1099, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1650,1650,1690, - 1690,1690,1690,1690,1690,1722,1722,1753,1753,1105,1105,1105,1291,1509, - 1116,1116,1099, 0, 0, 0,1291, 0 + 1116,1116,1116,1116,1116,1116,1105,1105,1105,1105,1105,1099,1105,1105, + 0,1105,1105, 0,1105,1105,1105,1116,1116,1116,1116,1105,1105,1105,1275, + 1275,1275,2181,1275,1116,1116,1116,1275,1275,2185,1509,1509,1462,2185, + 0,2190,2154,1509, 0,1116,1462,1462,1462,1462,1462,2194, 0, 0, 0, + 0,1099,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, 0,1590,1590, + 1590,1590,1590,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, + 1116,1105,1105,1105,1105,1105,1105,1105,1116,1116,1116,2185,1509,2211, + 1116,2229,1275,1509,1116,1462,1099,2234,2234,1105, 0, 0,1099, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1650,1650,1690,1690,1690,1690,1690, + 1690,1722,1722,1753,1753,1105,1105,1105,1291,1509,1116,1116,1099, 0, 0, + 0,1291, 0 }; static const unsigned char ag_key_ends[] = { @@ -1978,21 +1968,21 @@ static const unsigned char ag_key_ends[] = { #define AG_TCV(x) (((int)(x) >= -1 && (int)(x) <= 255) ? ag_tcv[(x) + 1] : 0) static const unsigned short ag_tcv[] = { - 38, 38,682,682,682,682,682,682,682,682, 1,425,682,682,682,682,682,682, - 682,682,682,682,682,682,682,682,682,682,682,682,682,682,682, 1,526,683, - 684,685,523,513,686,458,456,521,519,481,520,431,522,687,688,689,689,690, - 690,690,690,691,691,682,427,692,682,693,694,695,696,697,696,698,696,699, - 700,701,700,700,700,700,700,702,700,700,700,703,700,704,700,700,700,705, - 700,700,682,706,682,511,707,695,696,697,696,698,696,699,700,701,700,700, - 700,700,700,702,700,700,700,703,700,704,700,700,700,705,700,700,694,509, - 694,528,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, - 708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, - 708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, - 708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, - 708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, - 708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, - 708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, - 708,708,708,708,708 + 38, 38,679,679,679,679,679,679,679,679, 1,423,679,679,679,679,679,679, + 679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, 1,523,680, + 681,682,520,510,683,455,454,518,516,478,517,429,519,684,685,686,686,687, + 687,687,687,688,688,679,425,689,679,690,691,692,693,694,693,695,693,696, + 697,698,697,697,697,697,697,699,697,697,697,700,697,701,697,697,697,702, + 697,697,679,703,679,508,704,692,693,694,693,695,693,696,697,698,697,697, + 697,697,697,699,697,697,697,700,697,701,697,697,697,702,697,697,691,506, + 691,525,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, + 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, + 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, + 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, + 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, + 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, + 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, + 705,705,705,705,705 }; #ifndef SYNTAX_ERROR @@ -2179,1849 +2169,1844 @@ static void ag_undo(void) { static const unsigned short ag_tstt[] = { -707,705,704,703,702,701,700,699,698,697,696,694,685,439,435,434,431,429,427, - 426,425,164,163,162,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,437,433,432,429,427,425, + 424,423,162,161,160,133,132,1,0,51,52, 1,0, -707,705,704,703,702,701,700,699,698,697,696,694,685,439,431,429,427,426,425, - 164,163,162,135,134,63,1,0,11,34,35,36,37,51,52,53,64,65,133,430,443, -455,454,453,452,451,450,449,448,447,441,434,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,691,690,689,688,687,685,464, - 431,429,427,426,425,161,135,1,0,138, -455,454,453,452,451,450,449,448,447,441,434,0,59,66,67,73,75,77,78,79,80,81, +704,702,701,700,699,698,697,696,695,694,693,691,682,437,429,427,425,424,423, + 162,161,160,133,132,63,1,0,11,34,35,36,37,51,52,53,64,65,131,428,441, +453,452,451,450,449,448,447,446,445,439,432,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,461, + 429,427,425,424,423,159,133,1,0,136, +453,452,451,450,449,448,447,446,445,439,432,0,59,66,67,73,75,77,78,79,80,81, 82,83, -707,705,704,703,702,701,700,699,698,697,696,694,685,681,680,679,678,677,676, - 675,674,673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658, - 657,656,655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640, - 639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622, - 621,620,619,618,617,616,615,614,613,612,611,609,608,607,606,605,604,603, - 602,601,600,599,598,597,595,594,593,592,591,590,589,588,587,586,585,584, - 583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566, - 565,564,563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548, - 547,492,491,490,489,488,487,485,484,483,482,480,479,478,477,476,475,474, - 473,472,471,470,469,468,467,466,465,464,463,462,461,460,452,451,448,446, - 445,444,442,440,433,432,431,429,427,426,425,135,134,1,0,51,52, -425,0,45, -435,434,431,429,427,426,425,0,39,40,41,45,46,47,49,54,55, -707,705,704,703,702,701,700,699,698,697,696,694,685,681,680,679,678,677,676, - 675,674,673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658, - 657,656,655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640, - 639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622, - 621,620,619,618,617,616,615,614,613,612,611,609,608,607,606,605,604,603, - 602,601,600,599,598,597,595,594,593,592,591,590,589,588,587,586,585,584, - 583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566, - 565,564,563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548, - 547,492,491,490,489,488,487,485,484,483,482,480,479,478,477,476,475,474, - 473,472,471,470,469,468,467,466,465,464,463,462,461,460,452,451,448,446, - 445,444,442,440,433,432,431,429,427,426,425,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,681,680,679,678,677,676, - 675,674,673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658, - 657,656,655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640, - 639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622, - 621,620,619,618,617,616,615,614,613,612,611,609,608,607,606,605,604,603, - 602,601,600,599,598,597,595,594,593,592,591,590,589,588,587,586,585,584, - 583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566, - 565,564,563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548, - 547,492,491,490,489,488,487,485,484,483,482,480,479,478,477,476,475,474, - 473,472,471,470,469,468,467,466,465,464,463,462,461,460,452,451,448,446, - 445,444,442,440,435,434,431,429,427,426,425,135,134,1,0,21,30,31,32,33, - 54,55,62,75,79,80,89,94,133,245,258,259,260,261,262,263,264,265,266,267, - 269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286, - 287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304, - 305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322, - 323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340, - 341,342,343,344,345,347,348,349,350,351,352,353,354,355,356,357,358,359, - 360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377, - 378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395, - 396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413, - 443, -707,705,704,703,702,701,700,699,698,697,696,694,685,439,431,429,427,426,425, - 164,163,162,135,134,63,38,1,0,11,35,36,51,52,53,64,65,133,430,443, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, -683,1,0,51,52, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, -446,445,444,442,440,1,0,51,52, -707,706,705,704,703,702,701,700,699,698,697,696,692,691,690,689,688,687,683, - 522,431,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,84,133,443, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, -683,0,10,12,436, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,76,86, - 89,131,133,166,197,199,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,76,86, - 89,131,133,166,197,199,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, -446,445,444,442,440,0,68,69,70,71,72, -692,683,0,10,12,13,14,436,437, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,458,456,439,435,434,431,429,428,427,426,425,164,163,162,135,134,38, +704,702,701,700,699,698,697,696,695,694,693,691,682,678,677,676,675,674,673, + 672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656,655, + 654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638,637, + 636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620,619, + 618,617,616,615,614,613,612,611,610,609,608,606,605,604,603,602,601,600, + 599,598,597,596,595,594,592,591,590,589,588,587,586,585,584,583,582,581, + 580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564,563, + 562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546,545, + 544,489,488,487,486,485,484,482,481,480,479,477,476,475,474,473,472,471, + 470,469,468,467,466,465,464,463,462,461,460,459,458,457,450,449,446,444, + 443,442,440,438,431,430,429,427,425,424,423,133,132,1,0,51,52, +423,0,45, +433,432,429,427,425,424,423,0,39,40,41,45,46,47,49,54,55, +704,702,701,700,699,698,697,696,695,694,693,691,682,678,677,676,675,674,673, + 672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656,655, + 654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638,637, + 636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620,619, + 618,617,616,615,614,613,612,611,610,609,608,606,605,604,603,602,601,600, + 599,598,597,596,595,594,592,591,590,589,588,587,586,585,584,583,582,581, + 580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564,563, + 562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546,545, + 544,489,488,487,486,485,484,482,481,480,479,477,476,475,474,473,472,471, + 470,469,468,467,466,465,464,463,462,461,460,459,458,457,450,449,446,444, + 443,442,440,438,431,430,429,427,425,424,423,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,678,677,676,675,674,673, + 672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656,655, + 654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638,637, + 636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620,619, + 618,617,616,615,614,613,612,611,610,609,608,606,605,604,603,602,601,600, + 599,598,597,596,595,594,592,591,590,589,588,587,586,585,584,583,582,581, + 580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564,563, + 562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546,545, + 544,489,488,487,486,485,484,482,481,480,479,477,476,475,474,473,472,471, + 470,469,468,467,466,465,464,463,462,461,460,459,458,457,450,449,446,444, + 443,442,440,438,433,432,429,427,425,424,423,133,132,1,0,21,30,31,32,33, + 54,55,62,75,79,80,84,92,131,243,256,257,258,259,260,261,262,263,264,265, + 267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284, + 285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302, + 303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320, + 321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338, + 339,340,341,342,343,345,346,347,348,349,350,351,352,353,354,355,356,357, + 358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375, + 376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393, + 394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411, + 441, +704,702,701,700,699,698,697,696,695,694,693,691,682,437,429,427,425,424,423, + 162,161,160,133,132,63,38,1,0,11,35,36,51,52,53,64,65,131,428,441, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, +680,1,0,51,52, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, +444,443,442,440,438,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,689,688,687,686,685,684,680, + 519,429,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,84,131,441, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, +680,0,10,12,434, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,76,84, + 86,129,131,164,195,197,202,203,204,205,206,207,208,209,210,211,212,213, + 214,215,216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,76,84, + 86,129,131,164,195,197,202,203,204,205,206,207,208,209,210,211,212,213, + 214,215,216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, +444,443,442,440,438,0,68,69,70,71,72, +689,680,0,10,12,13,14,434,435, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,455,454,437,433,432,429,427,426,425,424,423,162,161,160,133,132,38, 1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 492,491,490,489,488,487,485,484,483,482,481,480,479,478,477,476,475,474, - 473,472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,456,446, - 445,444,442,440,435,434,433,432,431,429,428,427,426,425,1,0,51,52, -435,434,0,59,60,61, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,458,456,431,429,428,427,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,458,456,431,427,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,458,456,431,429,428,427,425,1,0,40,45,46,47,48,49,54,86,88,122,140, - 141,143,145,146,147,148,149,150,154,157,158,186,188,190,196,197,198,200, - 201,204,206,221,225,226,230,414,415,416,417,418,419,420,421,422,423,424, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,458,456,431,427,425,1,0,43,44,46,54,86,88,122,140,141,143,145,146, - 147,148,149,150,154,157,158,186,188,190,196,197,198,200,201,204,206,221, - 225,226,230,414,415,416,417,418,419,420,421,422,423,424, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,458,456,431,427,425,1,0,43,44,46,54,86,88,122,140,141,143,145,146, - 147,148,149,150,154,157,158,186,188,190,196,197,198,200,201,204,206,221, - 225,226,230,414,415,416,417,418,419,420,421,422,423,424, -707,705,704,703,702,701,700,699,698,697,696,694,685,681,680,679,678,677,676, - 675,674,673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658, - 657,656,655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640, - 639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622, - 621,620,619,618,617,616,615,614,613,612,611,609,608,607,606,605,604,603, - 602,601,600,599,598,597,595,594,593,592,591,590,589,588,587,586,585,584, - 583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566, - 565,564,563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548, - 547,492,491,490,489,488,487,485,484,483,482,480,479,478,477,476,475,474, - 473,472,471,470,469,468,467,466,465,464,463,462,461,460,452,451,448,446, - 445,444,442,440,433,432,431,429,427,426,425,135,134,0,21,30,31,32,33,39, - 40,41,45,46,47,49,54,55,62,75,79,80,89,94,133,245,258,259,260,261,262, - 263,264,265,266,267,269,270,271,272,273,274,275,276,277,278,279,280,281, - 282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299, - 300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317, - 318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335, - 336,337,338,339,340,341,342,343,344,345,347,348,349,350,351,352,353,354, - 355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372, - 373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390, - 391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408, - 409,410,411,412,413,443, -495,492,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -670,545,544,543,249,247,239,237,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -670,545,249,247,239,237,235,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -690,689,688,687,1,0,51,52, -670,545,544,543,249,247,239,237,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -670,545,249,247,239,237,235,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -670,542,541,249,247,239,237,235,1,0,51,52, -670,542,541,249,247,239,237,235,1,0,51,52, -670,542,541,249,247,239,237,235,1,0,51,52, -670,542,541,249,247,239,237,235,1,0,51,52, -670,247,237,235,1,0,51,52, -670,247,237,235,1,0,51,52, -670,545,249,247,239,237,235,1,0,51,52, -670,545,249,247,239,237,235,1,0,51,52, -670,545,249,247,239,237,235,1,0,51,52, -670,545,544,543,249,247,239,237,235,1,0,51,52, -670,545,544,543,249,247,239,237,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -690,689,688,687,1,0,51,52, -481,1,0,51,52, -481,1,0,51,52, -481,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -670,542,541,249,247,239,237,235,1,0,51,52, -670,542,541,249,247,239,237,235,1,0,51,52, -670,542,541,249,247,239,237,235,1,0,51,52, -670,542,541,249,247,239,237,235,1,0,51,52, -670,247,237,235,1,0,51,52, -670,247,237,235,1,0,51,52, -670,545,249,247,239,237,235,1,0,51,52, -670,545,249,247,239,237,235,1,0,51,52, -670,545,249,247,239,237,235,1,0,51,52, -670,545,544,543,249,247,239,237,235,1,0,51,52, -670,545,544,543,249,247,239,237,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -542,242,241,240,239,238,237,236,235,1,0,51,52, -708,707,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,686,685,683,682,546,528,526,525,523,522,521,520,519,517,515,513, - 511,509,508,506,504,502,500,498,497,494,481,458,456,431,429,427,426,425, - 1,0,51,52,138, -546,429,427,426,425,1,0,51,52, -546,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, - 507,506,505,504,503,502,501,500,499,498,497,496,494,458,456,429,427,426, - 425,1,0,86, -429,427,426,425,1,0,51, -546,0,268, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,76,86, - 89,131,133,166,197,199,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,219,220,443,493,540, -492,491,490,489,488,487,485,484,483,482,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,460,446,445,444,442,440,0, - 68,69,70,71,72,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109, - 110,111,112,114,115,116,117,118,119,120,121,123,124,125,126,127,128,129, - 130,131, -429,427,426,425,1,0,51,52, -708,707,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,686,685,683,682,528,526,523,522,521,520,519,513,511,509,481,458, - 456,431,427,1,0,86, -708,707,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,686,685,683,682,528,526,523,522,521,520,519,513,511,509,481,458, - 456,431,427,1,0,51,52, -429,427,426,425,1,0,51,52, -707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481, - 458,456,431,427,425,1,0,142, -494,481,456,429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -429,427,426,425,0,39,40,41,45,46,47,49, -429,427,426,425,0,39,40,41,45,46,47,49, -429,427,426,425,1,0,51,52, -691,690,689,688,687,0, -690,689,688,687,0, -688,687,0, -707,705,704,703,702,701,700,699,698,697,696,694,691,690,689,688,687,685,546, - 525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, - 507,506,505,504,503,502,501,500,499,498,497,496,494,458,456,431,429,427, - 426,425,1,0, -707,705,701,699,698,697,696,691,690,689,688,687,685,546,525,524,523,522,521, - 520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503, - 502,501,500,499,498,497,496,494,456,431,429,427,426,425,223,222,1,0, -691,690,689,688,687,0, -707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481,458, - 456,431,427,425,234,1,0,16, -691,690,689,688,687,0, -701,699,698,697,696,691,690,689,688,687,0, -690,689,688,687,546,525,524,523,522,521,520,519,518,517,516,515,514,513,512, - 511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,494,456, - 429,427,426,425,1,0, -688,687,546,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510, - 509,508,507,506,505,504,503,502,501,500,499,498,497,496,494,456,429,427, - 426,425,1,0, -699,698,697,696,691,690,689,688,687,546,525,524,523,522,521,520,519,518,517, - 516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499, - 498,497,496,494,456,429,427,426,425,1,0, -707,701,699,698,697,696,691,690,689,688,687,685,546,525,524,523,522,521,520, - 519,518,517,516,515,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,494,456,431,429,427,426,425,223,222,1,0,224, -458,1,0,51,52, -458,429,427,426,425,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -546,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, - 507,506,505,504,503,502,501,500,499,498,497,496,494,456,429,427,426,425, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 489,488,487,486,485,484,482,481,480,479,478,477,476,475,474,473,472,471, + 470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,444, + 443,442,440,438,433,432,431,430,429,427,426,425,424,423,1,0,51,52, +433,432,0,59,60,61, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,455,454,429,427,426,425,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,455,454,429,425,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,455,454,429,427,426,425,423,1,0,40,45,46,47,48,49,54,86,88,120,138, + 139,141,143,144,145,146,147,148,152,155,156,184,186,188,194,195,196,198, + 199,202,204,219,223,224,228,412,413,414,415,416,417,418,419,420,421,422, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,455,454,429,425,423,1,0,43,44,46,54,86,88,120,138,139,141,143,144, + 145,146,147,148,152,155,156,184,186,188,194,195,196,198,199,202,204,219, + 223,224,228,412,413,414,415,416,417,418,419,420,421,422, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,455,454,429,425,423,1,0,43,44,46,54,86,88,120,138,139,141,143,144, + 145,146,147,148,152,155,156,184,186,188,194,195,196,198,199,202,204,219, + 223,224,228,412,413,414,415,416,417,418,419,420,421,422, +704,702,701,700,699,698,697,696,695,694,693,691,682,678,677,676,675,674,673, + 672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656,655, + 654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638,637, + 636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620,619, + 618,617,616,615,614,613,612,611,610,609,608,606,605,604,603,602,601,600, + 599,598,597,596,595,594,592,591,590,589,588,587,586,585,584,583,582,581, + 580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564,563, + 562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546,545, + 544,489,488,487,486,485,484,482,481,480,479,477,476,475,474,473,472,471, + 470,469,468,467,466,465,464,463,462,461,460,459,458,457,450,449,446,444, + 443,442,440,438,431,430,429,427,425,424,423,133,132,0,21,30,31,32,33,39, + 40,41,45,46,47,49,54,55,62,75,79,80,84,92,131,243,256,257,258,259,260, + 261,262,263,264,265,267,268,269,270,271,272,273,274,275,276,277,278,279, + 280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297, + 298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315, + 316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333, + 334,335,336,337,338,339,340,341,342,343,345,346,347,348,349,350,351,352, + 353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370, + 371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388, + 389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406, + 407,408,409,410,411,441, +492,489,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +667,542,541,540,247,245,237,235,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +667,542,247,245,237,235,233,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +687,686,685,684,1,0,51,52, +667,542,541,540,247,245,237,235,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +667,542,247,245,237,235,233,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +667,539,538,247,245,237,235,233,1,0,51,52, +667,539,538,247,245,237,235,233,1,0,51,52, +667,539,538,247,245,237,235,233,1,0,51,52, +667,539,538,247,245,237,235,233,1,0,51,52, +667,245,235,233,1,0,51,52, +667,245,235,233,1,0,51,52, +667,542,247,245,237,235,233,1,0,51,52, +667,542,247,245,237,235,233,1,0,51,52, +667,542,247,245,237,235,233,1,0,51,52, +667,542,541,540,247,245,237,235,233,1,0,51,52, +667,542,541,540,247,245,237,235,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +687,686,685,684,1,0,51,52, +478,1,0,51,52, +478,1,0,51,52, +478,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +667,539,538,247,245,237,235,233,1,0,51,52, +667,539,538,247,245,237,235,233,1,0,51,52, +667,539,538,247,245,237,235,233,1,0,51,52, +667,539,538,247,245,237,235,233,1,0,51,52, +667,245,235,233,1,0,51,52, +667,245,235,233,1,0,51,52, +667,542,247,245,237,235,233,1,0,51,52, +667,542,247,245,237,235,233,1,0,51,52, +667,542,247,245,237,235,233,1,0,51,52, +667,542,541,540,247,245,237,235,233,1,0,51,52, +667,542,541,540,247,245,237,235,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +539,240,239,238,237,236,235,234,233,1,0,51,52, +705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,680,679,543,525,523,522,520,519,518,517,516,514,512,510, + 508,506,505,503,501,499,497,495,494,491,478,455,454,429,427,425,424,423, + 1,0,51,52,136, +543,427,425,424,423,1,0,51,52, +705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,680,679,543,525,523,522,521,520,519,518,517,516,515,514, + 513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496, + 495,494,493,491,478,455,454,429,427,425,424,423,1,0,86, +427,425,424,423,1,0,51, +543,0,266, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,76,84, + 86,129,131,164,195,197,202,203,204,205,206,207,208,209,210,211,212,213, + 214,215,216,217,218,441,490,537, +489,488,487,486,485,484,482,481,480,479,477,476,475,474,473,472,471,470,469, + 468,467,466,465,464,463,462,461,460,459,458,457,444,443,442,440,438,0, + 68,69,70,71,72,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108, + 109,110,112,113,114,115,116,117,118,119,121,122,123,124,125,126,127,128, + 129, +427,425,424,423,1,0,51,52, +705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,680,679,525,523,520,519,518,517,516,510,508,506,478,455, + 454,429,425,1,0,51,52, +427,425,424,423,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478, + 455,454,429,425,423,1,0,140, +491,478,454,427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,1,0,51,52, +688,687,686,685,684,0, +687,686,685,684,0, +685,684,0, +704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,543, + 522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, + 504,503,502,501,500,499,498,497,496,495,494,493,491,455,454,429,427,425, + 424,423,1,0, +704,702,698,696,695,694,693,688,687,686,685,684,682,543,522,521,520,519,518, + 517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, + 499,498,497,496,495,494,493,491,454,429,427,425,424,423,221,220,1,0, +688,687,686,685,684,0, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478,455, + 454,429,425,423,232,1,0,16, +688,687,686,685,684,0, +698,696,695,694,693,688,687,686,685,684,0, +687,686,685,684,543,522,521,520,519,518,517,516,515,514,513,512,511,510,509, + 508,507,506,505,504,503,502,501,500,499,498,497,496,495,494,493,491,454, + 427,425,424,423,1,0, +685,684,543,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507, + 506,505,504,503,502,501,500,499,498,497,496,495,494,493,491,454,427,425, + 424,423,1,0, +696,695,694,693,688,687,686,685,684,543,522,521,520,519,518,517,516,515,514, + 513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496, + 495,494,493,491,454,427,425,424,423,1,0, +704,698,696,695,694,693,688,687,686,685,684,682,543,522,521,520,519,518,517, + 516,515,514,513,512,510,509,508,507,506,505,504,503,502,501,500,499,498, + 497,496,495,494,491,454,429,427,425,424,423,221,220,1,0,222, +455,1,0,51,52, +455,427,425,424,423,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +543,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, + 504,503,502,501,500,499,498,497,496,495,494,493,491,454,427,425,424,423, 1,0,51,52, -546,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, - 507,506,505,504,503,502,501,500,499,498,497,496,494,456,429,427,426,425, +543,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, + 504,503,502,501,500,499,498,497,496,495,494,493,491,454,427,425,424,423, 1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, - 528,527,526,523,522,521,520,519,513,511,509,492,481,459,458,457,456,431, - 429,428,427,426,425,232,135,134,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -458,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, - 528,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429,428, - 427,426,425,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, - 528,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429,428, - 427,426,425,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, - 213,214,215,216,217,218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, - 213,214,215,216,217,218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, - 213,214,215,216,217,218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, - 213,214,215,216,217,218,219,220,443,493,540, -546,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, - 507,506,505,504,503,502,501,500,499,498,497,496,494,456,429,427,426,425, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, + 525,524,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427, + 426,425,424,423,230,133,132,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, + 525,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427,426, + 425,424,423,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, + 525,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427,426, + 425,424,423,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,490,537, +543,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, + 504,503,502,501,500,499,498,497,496,495,494,493,491,454,427,425,424,423, 1,0,51,52, -546,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, - 507,506,505,504,503,502,501,500,499,498,497,496,494,456,427,425,1,0,51, - 52,198,200,201,202,203, -546,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503, - 502,501,500,499,498,497,496,494,456,429,427,426,425,1,0,51,52,196,197, -546,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,496,494,456,429,427,426,425,1,0,51,52,192,193,194,195, -546,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, - 496,494,456,429,427,426,425,1,0,51,52,190,191, -546,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,494, - 456,429,427,426,425,1,0,51,52,188,189, -510,509,0,186,187, -508,507,506,505,504,503,502,501,500,499,498,497,496,429,427,426,425,1,0,167, - 168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,74, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,682,528,526,523,522,521,520,519,513,511,509,481, - 458,456,431,427,1,0, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -707,706,705,704,703,702,701,700,699,698,697,696,692,691,690,689,688,687,683, - 522,431,1,0,51,52, -707,706,705,704,703,702,701,700,699,698,697,696,692,691,690,689,688,687,683, - 522,431,0,10,12,13,14,19,436,437,438, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, - 528,527,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429, - 428,427,426,425,232,135,134,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, - 528,527,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429, - 428,427,426,425,232,135,134,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,458,456,431,429,428,427,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, - 528,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429,428, - 427,426,425,232,135,134,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, - 528,527,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429, - 428,427,426,425,232,135,134,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, - 528,527,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429, - 428,427,426,425,232,135,134,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, - 528,527,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429, - 428,427,426,425,232,135,134,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, - 528,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429,428, - 427,426,425,232,135,134,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,546,528,526,525,524,523,522,521,520,519, - 518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,496,494,481,459,458,456,431,429,428,427,426,425,1,0,51, +543,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, + 504,503,502,501,500,499,498,497,496,495,494,493,491,454,425,423,1,0,51, + 52,196,198,199,200,201, +543,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, + 499,498,497,496,495,494,493,491,454,427,425,424,423,1,0,51,52,194,195, +543,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, + 497,496,495,494,493,491,454,427,425,424,423,1,0,51,52,190,191,192,193, +543,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494, + 493,491,454,427,425,424,423,1,0,51,52,188,189, +543,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494,493,491, + 454,427,425,424,423,1,0,51,52,186,187, +507,506,0,184,185, +505,504,503,502,501,500,499,498,497,496,495,494,493,427,425,424,423,1,0,165, + 166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,74, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,679,525,523,520,519,518,517,516,510,508,506,478, + 455,454,429,425,1,0, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,689,688,687,686,685,684,680, + 519,429,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,689,688,687,686,685,684,680, + 519,429,0,10,12,13,14,19,434,435,436, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, + 525,524,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427, + 426,425,424,423,230,133,132,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, + 525,524,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427, + 426,425,424,423,230,133,132,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,455,454,429,427,426,425,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, + 525,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427,426, + 425,424,423,230,133,132,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, + 525,524,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427, + 426,425,424,423,230,133,132,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, + 525,524,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427, + 426,425,424,423,230,133,132,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, + 525,524,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427, + 426,425,424,423,230,133,132,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, + 525,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427,426, + 425,424,423,230,133,132,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,543,525,523,522,521,520,519,518,517,516, + 515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, + 497,496,495,494,493,491,478,456,455,454,429,427,426,425,424,423,1,0,51, 52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, - 528,527,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429, - 428,427,426,425,232,135,134,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,539,537,536,535,534,533,532,531,530,529, - 528,526,523,522,521,520,519,513,511,509,492,481,459,458,456,431,429,428, - 427,426,425,232,135,134,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,458,456,431,429,428,427,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,459,458,456,431,429,428,427,426,425,1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,458,456,439,435,434,431,429,428,427,426,425,164,163,162,135,134,38, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, + 525,524,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427, + 426,425,424,423,230,133,132,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, + 525,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427,426, + 425,424,423,230,133,132,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,455,454,429,427,426,425,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,456,455,454,429,427,426,425,424,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,455,454,437,433,432,429,427,426,425,424,423,162,161,160,133,132,38, 1,0,51,52, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,458,456,431,427,1,0,46,54,86,88,122,140,141,143,145,146,147,148,149, - 150,154,157,158,186,188,190,196,197,198,200,201,204,206,221,225,226,230, - 414,415,416,417,418,419,420,421,422,423,424, -425,0,45, -425,0,45, -492,491,490,489,488,487,485,484,483,482,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,460,446,445,444,442,440,433, - 432,0,56,58,68,69,70,71,72,95,96,97,98,99,100,101,102,103,104,105,106, - 107,108,109,110,111,112,114,115,116,117,118,119,120,121,123,124,125,126, - 127,128,129,130,131, -429,427,426,425,1,0,51,52, -495,492,429,427,426,425,0,22,39,40,41,45,46,47,49,131,165, -670,545,544,543,249,247,239,237,235,0,246,248,250,251,255,256,257, -542,242,241,240,239,238,237,236,235,0,4,243,596, -670,545,249,247,239,237,235,0,5,246,248,250,610, -690,689,688,687,0,346, -481,0,122, -481,0,122, -481,0,122, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -670,542,541,249,247,239,237,235,0,244,246,248,250,252,253, -670,542,541,249,247,239,237,235,0,244,246,248,250,252,253, -670,542,541,249,247,239,237,235,0,244,246,248,250,252,253, -670,542,541,249,247,239,237,235,0,244,246,248,250,252,253, -670,247,237,235,0,246,248,254, -670,247,237,235,0,246,248,254, -670,545,249,247,239,237,235,0,5,246,248,250,610, -670,545,249,247,239,237,235,0,5,246,248,250,610, -670,545,249,247,239,237,235,0,5,246,248,250,610, -670,545,544,543,249,247,239,237,235,0,246,248,250,251,255,256,257, -670,545,544,543,249,247,239,237,235,0,246,248,250,251,255,256,257, -542,242,241,240,239,238,237,236,235,0,4,243,596, -542,242,241,240,239,238,237,236,235,0,4,243,596, -542,242,241,240,239,238,237,236,235,0,4,243,596, -542,242,241,240,239,238,237,236,235,0,4,243,596, -542,242,241,240,239,238,237,236,235,0,4,243,596, -542,242,241,240,239,238,237,236,235,0,4,243,596, -542,242,241,240,239,238,237,236,235,0,4,243,596, -542,242,241,240,239,238,237,236,235,0,4,243,596, -542,242,241,240,239,238,237,236,235,0,4,243,596, -542,242,241,240,239,238,237,236,235,0,4,243,596, -542,242,241,240,239,238,237,236,235,0,4,243,596, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, - 492,458,431,232,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,86,89,90,131,133,197,199,204,205,206,207,208,209,210,211,212, - 213,214,215,216,217,218,219,220,436,443,486,493,540, -695,691,690,689,688,687,686,685,523,520,519,232,1,0,2,6,7,15,17,219,220,493, -681,680,679,678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663, - 662,661,660,659,658,657,656,655,654,653,652,651,650,649,648,647,646,645, - 644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,622,621,620,619,618,617,616,615,614,613,612,611,609,608, - 607,606,605,604,603,602,601,600,599,598,597,595,594,593,592,591,590,589, - 588,587,586,585,584,583,582,581,580,579,578,577,576,575,574,573,572,571, - 570,569,568,567,566,565,564,563,562,561,560,559,558,557,556,555,554,553, - 552,551,550,549,548,547,1,0,51,52, -681,680,679,678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663, - 662,661,660,659,658,657,656,655,654,653,652,651,650,649,648,647,646,645, - 644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,622,621,620,619,618,617,616,615,614,613,612,611,609,608, - 607,606,605,604,603,602,601,600,599,598,597,595,594,593,592,591,590,589, - 588,587,586,585,584,583,582,581,580,579,578,577,576,575,574,573,572,571, - 570,569,568,567,566,565,564,563,562,561,560,559,558,557,556,555,554,553, - 552,551,550,549,548,547,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, -707,706,705,704,703,702,701,700,699,698,697,696,691,690,689,688,687,522,431, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,455,454,429,425,1,0,46,54,86,88,120,138,139,141,143,144,145,146,147, + 148,152,155,156,184,186,188,194,195,196,198,199,202,204,219,223,224,228, + 412,413,414,415,416,417,418,419,420,421,422, +423,0,45, +423,0,45, +489,488,487,486,485,484,482,481,480,479,477,476,475,474,473,472,471,470,469, + 468,467,466,465,464,463,462,461,460,459,458,457,444,443,442,440,438,431, + 430,0,56,58,68,69,70,71,72,93,94,95,96,97,98,99,100,101,102,103,104,105, + 106,107,108,109,110,112,113,114,115,116,117,118,119,121,122,123,124,125, + 126,127,128,129, +427,425,424,423,1,0,51,52, +492,489,427,425,424,423,0,22,39,40,41,45,46,47,49,129,163, +667,542,541,540,247,245,237,235,233,0,244,246,248,249,253,254,255, +539,240,239,238,237,236,235,234,233,0,4,241,593, +667,542,247,245,237,235,233,0,5,244,246,248,607, +687,686,685,684,0,344, +478,0,120, +478,0,120, +478,0,120, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +667,539,538,247,245,237,235,233,0,242,244,246,248,250,251, +667,539,538,247,245,237,235,233,0,242,244,246,248,250,251, +667,539,538,247,245,237,235,233,0,242,244,246,248,250,251, +667,539,538,247,245,237,235,233,0,242,244,246,248,250,251, +667,245,235,233,0,244,246,252, +667,245,235,233,0,244,246,252, +667,542,247,245,237,235,233,0,5,244,246,248,607, +667,542,247,245,237,235,233,0,5,244,246,248,607, +667,542,247,245,237,235,233,0,5,244,246,248,607, +667,542,541,540,247,245,237,235,233,0,244,246,248,249,253,254,255, +667,542,541,540,247,245,237,235,233,0,244,246,248,249,253,254,255, +539,240,239,238,237,236,235,234,233,0,4,241,593, +539,240,239,238,237,236,235,234,233,0,4,241,593, +539,240,239,238,237,236,235,234,233,0,4,241,593, +539,240,239,238,237,236,235,234,233,0,4,241,593, +539,240,239,238,237,236,235,234,233,0,4,241,593, +539,240,239,238,237,236,235,234,233,0,4,241,593, +539,240,239,238,237,236,235,234,233,0,4,241,593, +539,240,239,238,237,236,235,234,233,0,4,241,593, +539,240,239,238,237,236,235,234,233,0,4,241,593, +539,240,239,238,237,236,235,234,233,0,4,241,593, +539,240,239,238,237,236,235,234,233,0,4,241,593, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 489,455,429,230,133,132,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,84,86,87,129,131,195,197,202,203,204,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,434,441,483,490,537, +692,688,687,686,685,684,683,682,520,517,516,230,1,0,2,6,7,15,17,217,218,490, +678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663,662,661,660, + 659,658,657,656,655,654,653,652,651,650,649,648,647,646,645,644,643,642, + 641,640,639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624, + 623,622,621,620,619,618,617,616,615,614,613,612,611,610,609,608,606,605, + 604,603,602,601,600,599,598,597,596,595,594,592,591,590,589,588,587,586, + 585,584,583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568, + 567,566,565,564,563,562,561,560,559,558,557,556,555,554,553,552,551,550, + 549,548,547,546,545,544,1,0,51,52, +678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663,662,661,660, + 659,658,657,656,655,654,653,652,651,650,649,648,647,646,645,644,643,642, + 641,640,639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624, + 623,622,621,620,619,618,617,616,615,614,613,612,611,610,609,608,606,605, + 604,603,602,601,600,599,598,597,596,595,594,592,591,590,589,588,587,586, + 585,584,583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568, + 567,566,565,564,563,562,561,560,559,558,557,556,555,554,553,552,551,550, + 549,548,547,546,545,544,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, +704,703,702,701,700,699,698,697,696,695,694,693,688,687,686,685,684,519,429, 1,0,51,52, -707,706,705,704,703,702,701,700,699,698,697,696,691,690,689,688,687,522,431, - 0,19,438, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -686,683,1,0,51,52, -686,683,0,10,12,18,20,436,486, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,429,427,426,425,135,134, +704,703,702,701,700,699,698,697,696,695,694,693,688,687,686,685,684,519,429, + 0,19,436, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +683,680,1,0,51,52, +683,680,0,10,12,18,20,434,483, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,427,425,424,423,133,132, 1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,429,427,426,425,135,134, - 1,0,21,133,443, -683,1,0,51,52, -683,0,10,12,436, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, - 492,458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, - 492,458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, - 492,458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, - 492,458,431,232,135,134,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28,29, - 57,86,89,131,133,197,199,204,205,206,207,208,209,210,211,212,213,214, - 215,216,217,218,219,220,436,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,113,133, - 443, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,113,133, - 443, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,113,133, - 443, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, - 492,458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, - 492,458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, - 492,458,431,232,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,86,89,90,131,133,197,199,204,205,206,207,208,209,210,211,212, - 213,214,215,216,217,218,219,220,436,443,486,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, - 492,458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, - 492,458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, - 492,458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, - 492,458,431,232,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,86,89,90,131,133,197,199,204,205,206,207,208,209,210,211,212, - 213,214,215,216,217,218,219,220,436,443,486,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -429,427,426,425,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, -495,492,429,427,426,425,1,0,51,52, -495,492,429,427,426,425,1,0,51,52, -429,427,426,425,0,39,40,41,45,46,47,49, -457,0,87, -708,707,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,686,685,683,682,528,526,523,522,521,520,519,513,511,509,481,458, - 456,431,427,0,46,54,85,86,88,122,140,141,145,146,147,148,149,150,154, - 157,158,186,188,190,196,197,198,200,201,204,206,221,225,226,230,414,415, - 417,418,419,420,421,422,423,424, -429,427,426,425,0,39,40,41,45,46,47,49, -706,705,704,703,702,699,697,689,688,687,685,683,425,0,155, -429,427,426,425,0,39,40,41,45,46,47,49, -429,427,426,425,0,39,40,41,45,46,47,49, -699,698,697,696,691,690,689,688,687,0, -706,704,703,702,687,686,0, -707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481, - 458,456,431,427,425,234,1,0,16, -701,699,698,697,696,691,690,689,688,687,546,525,524,523,522,521,520,519,518, - 517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, - 499,498,497,496,494,456,429,427,426,425,1,0, -701,699,698,697,696,691,690,689,688,687,546,525,524,523,522,521,520,519,518, - 517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, - 499,498,497,496,494,456,429,427,426,425,1,0, -458,0,86, -458,0,86, -458,0,86, -458,0,86, -458,0,86, -458,0,86, -458,0,86, -458,0,86, -458,0,86, -458,0,86, -458,0,86, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -691,690,689,688,687,0, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -429,427,426,425,0,39,40,41,45,46,47,49, -429,427,426,425,0,39,40,41,45,46,47,49, -429,427,426,425,0,39,40,41,45,46,47,49, -429,427,426,425,0,39,40,41,45,46,47,49, -429,427,426,425,0,39,40,41,45,46,47,49, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, -429,427,426,425,0,39,40,41,45,46,47,49, -429,427,426,425,0,39,40,41,45,46,47,49, -708,707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690, - 689,688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509, - 481,458,456,431,427,425,1,0, -429,427,426,425,0,39,40,41,45,46,47,49, -429,427,426,425,0,39,40,41,45,46,47,49, -707,706,705,704,703,702,701,700,699,698,697,696,691,690,689,688,687,522,431, - 427,425,1,0,51,52, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -429,427,426,425,0,39,40,41,45,46,47,49, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -546,481,429,427,426,425,1,0,51,52, -546,481,429,427,426,425,1,0,51,52, -546,481,429,427,426,425,1,0,51,52, -546,494,481,429,427,426,425,1,0,51,52, -546,481,429,427,426,425,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -546,429,427,426,425,1,0,51,52, -546,429,427,426,425,1,0,51,52, -494,1,0,51,52, -707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481,458, - 456,431,427,425,234,1,0,16, -707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481, - 458,456,431,427,425,234,1,0,16, -494,456,429,427,426,425,1,0,51,52, -494,456,0,88,132, -699,698,697,696,691,690,689,688,687,0, -707,701,699,698,697,696,691,690,689,688,687,685,429,427,426,425,223,222,1,0, - 224, -681,680,679,678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663, - 662,661,660,659,658,657,656,655,654,653,652,651,650,649,648,647,646,645, - 644,643,642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627, - 626,625,624,623,622,621,620,619,618,617,616,615,614,613,612,611,609,608, - 607,606,605,604,603,602,601,600,599,598,597,595,594,593,592,591,590,589, - 588,587,586,585,584,583,582,581,580,579,578,577,576,575,574,573,572,571, - 570,569,568,567,566,565,564,563,562,561,560,559,558,557,556,555,554,553, - 552,551,550,549,548,547,0,31,32,245,258,259,260,261,262,263,264,265,266, - 267,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285, - 286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303, - 304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321, - 322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339, - 340,341,342,343,344,345,347,348,349,350,351,352,353,354,355,356,357,358, - 359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376, - 377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394, - 395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412, - 413, -707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481,458, - 456,431,427,425,234,1,0,16, -481,0,122, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, - 492,458,431,232,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,86,89,90,131,133,197,199,204,205,206,207,208,209,210,211,212, - 213,214,215,216,217,218,219,220,436,443,486,493,540, -494,429,427,426,425,1,0,132, -494,429,427,426,425,1,0,132, -494,429,427,426,425,1,0,132, -494,429,427,426,425,1,0,132, -494,429,427,426,425,1,0,132, -456,1,0,51,52, -456,0,88, -708,707,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,686,685,683,682,528,526,523,522,521,520,519,513,511,509,481,459, - 458,456,431,427,425,1,0,46,51,52,54,86,88,93,122,140,141,145,146,147, - 148,149,150,154,157,158,186,188,190,196,197,198,200,201,204,206,221,225, - 226,230,414,415,417,418,419,420,421,422,423,424, -699,698,697,696,691,690,689,688,687,0, -691,690,689,688,687,0, -707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481, - 458,456,431,427,425,1,0, -686,0, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -456,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, - 213,214,215,216,217,218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, - 213,214,215,216,217,218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, - 213,214,215,216,217,218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, - 213,214,215,216,217,218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,523,520,519,492,458,431,232, - 135,134,0,2,6,7,8,9,15,17,21,86,89,131,133,199,207,208,209,210,211,212, - 213,214,215,216,217,218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,25,29,86,89,131,133,197,199, - 204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,443, - 493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,25,29,86,89,131,133,197,199, - 204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,443, - 493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,25,27,29,86,89,131,133,197,199, - 204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,443, - 493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,25,27,29,86,89,131,133,197,199, - 204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,443, - 493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,25,27,29,86,89,131,133,197,199, - 204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,443, - 493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,25,27,29,86,89,131,133,197,199, - 204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,443, - 493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,24,25,27,29,86,89,131,133,197, - 199,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, - 443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,24,25,27,29,86,89,131,133,197, - 199,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, - 443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,29,86,89,131,133, - 197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219, - 220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,29,86,89,131,133, - 197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219, - 220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,86,89,131, - 133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, - 219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,86,89,131, - 133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, - 219,220,443,493,540, -429,427,426,425,1,0,51,52, -429,427,426,425,0,39,40,41,45,46,47,49, -429,427,426,425,0,39,40,41,45,46,47,49, -429,427,426,425,0,39,40,41,45,46,47,49, -429,427,426,425,1,0,51,52, -429,427,426,425,1,0,51,52, -429,427,426,425,0,39,40,41,45,46,47,49, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -494,0,132, -707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481, - 458,456,431,427,425,234,1,0,16, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,683,542,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520, - 519,492,458,431,242,241,240,239,238,237,236,235,232,135,134,1,0,51,52, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, - 492,458,431,232,135,134,1,0,51,52, -546,0,268, -546,429,427,426,425,1,0,51,52, -707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481,458, - 456,431,427,425,234,1,0,16, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,1,0,51,52, -494,429,427,426,425,1,0,132, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,1,0,51,52, -708,707,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,686,685,683,682,528,526,523,522,521,520,519,513,511,509,481,459, - 458,456,431,429,427,426,425,1,0,51,52, -708,707,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,686,685,683,682,528,526,523,522,521,520,519,513,511,509,481,459, - 458,456,431,429,427,426,425,1,0, -429,427,426,425,0,39,40,41,45,46,47,49, -707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481, - 458,456,431,427,425,1,0, -691,690,689,688,687,0, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,3,133,443,538, -456,0,88, -456,0,88, -456,0,88, -456,0,88, -456,0,88, -456,0,88, -456,0,88, -456,0,88, -456,0,88, -456,0,88, -456,0,88, -546,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, - 507,506,505,504,503,502,501,500,499,498,497,496,494,456,427,425,1,0,198, - 200,201,202,203, -546,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, - 507,506,505,504,503,502,501,500,499,498,497,496,494,456,427,425,1,0,198, - 200,201,202,203, -546,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503, - 502,501,500,499,498,497,496,494,456,429,427,426,425,1,0,196,197, -546,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503, - 502,501,500,499,498,497,496,494,456,429,427,426,425,1,0,196,197, -546,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503, - 502,501,500,499,498,497,496,494,456,429,427,426,425,1,0,196,197, -546,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503, - 502,501,500,499,498,497,496,494,456,429,427,426,425,1,0,196,197, -546,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,496,494,456,429,427,426,425,1,0,192,193,194,195, -546,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,496,494,456,429,427,426,425,1,0,192,193,194,195, -546,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, - 496,494,456,429,427,426,425,1,0,190,191, -546,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, - 496,494,456,429,427,426,425,1,0,190,191, -546,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,494, - 456,429,427,426,425,1,0,188,189, -546,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,494, - 456,429,427,426,425,1,0,188,189, -429,427,426,425,0,39,40,41,45,46,47,49, -429,427,426,425,0,39,40,41,45,46,47,49, -429,427,426,425,0,39,40,41,45,46,47,49, -542,242,241,240,239,238,237,236,235,1,0,51,52, -707,706,705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689, - 688,687,686,685,684,683,682,528,526,523,522,521,520,519,513,511,509,481, - 458,456,431,427,425,234,1,0, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,683,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519, - 492,458,431,232,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,86,89,131,133,197,199,204,205,206,207,208,209,210,211,212,213, - 214,215,216,217,218,219,220,436,443,486,493,540, -707,705,704,703,702,701,700,699,698,697,696,695,694,691,690,689,688,687,686, - 685,539,537,536,535,534,533,532,531,530,529,528,527,526,523,520,519,492, - 458,431,232,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,86,89, - 131,133,197,199,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,220,443,493,540, -707,705,704,703,702,701,700,699,698,697,696,694,685,135,134,0,21,133,443, -707,705,704,703,702,701,700,699,698,697,696,694,691,690,689,688,687,685,456, - 431,1,0,51,52,138, -456,1,0,51,52, -456,1,0,51,52, -542,242,241,240,239,238,237,236,235,0,4,243,596, -456,0,88, +704,702,701,700,699,698,697,696,695,694,693,691,682,427,425,424,423,133,132, + 1,0,21,131,441, +680,1,0,51,52, +680,0,10,12,434, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 489,455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 489,455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 489,455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 489,455,429,230,133,132,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28,29, + 57,84,86,129,131,195,197,202,203,204,205,206,207,208,209,210,211,212, + 213,214,215,216,217,218,434,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,111,131, + 441, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,111,131, + 441, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,111,131, + 441, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 489,455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 489,455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 489,455,429,230,133,132,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,84,86,87,129,131,195,197,202,203,204,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,434,441,483,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 489,455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 489,455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 489,455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 489,455,429,230,133,132,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,84,86,87,129,131,195,197,202,203,204,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,434,441,483,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +427,425,424,423,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, +492,489,427,425,424,423,1,0,51,52, +492,489,427,425,424,423,1,0,51,52, +427,425,424,423,0,39,40,41,45,46,47,49, +705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,680,679,525,523,520,519,518,517,516,510,508,506,478,455, + 454,429,425,0,46,54,85,86,88,120,138,139,143,144,145,146,147,148,152, + 155,156,184,186,188,194,195,196,198,199,202,204,219,223,224,228,412,413, + 415,416,417,418,419,420,421,422, +427,425,424,423,0,39,40,41,45,46,47,49, +703,702,701,700,699,696,694,686,685,684,682,680,423,0,153, +427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,0,39,40,41,45,46,47,49, +696,695,694,693,688,687,686,685,684,0, +703,701,700,699,684,683,0, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478, + 455,454,429,425,423,232,1,0,16, +698,696,695,694,693,688,687,686,685,684,543,522,521,520,519,518,517,516,515, + 514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, + 496,495,494,493,491,454,427,425,424,423,1,0, +698,696,695,694,693,688,687,686,685,684,543,522,521,520,519,518,517,516,515, + 514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, + 496,495,494,493,491,454,427,425,424,423,1,0, +455,0,86, +455,0,86, +455,0,86, +455,0,86, +455,0,86, +455,0,86, +455,0,86, +455,0,86, +455,0,86, +455,0,86, +455,0,86, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +688,687,686,685,684,0, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,0,39,40,41,45,46,47,49, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, +427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,0,39,40,41,45,46,47,49, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, + 478,455,454,429,425,423,1,0, +427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,0,39,40,41,45,46,47,49, +704,703,702,701,700,699,698,697,696,695,694,693,688,687,686,685,684,519,429, + 425,423,1,0,51,52, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +543,478,427,425,424,423,1,0,51,52, +543,478,427,425,424,423,1,0,51,52, +543,478,427,425,424,423,1,0,51,52, +543,491,478,427,425,424,423,1,0,51,52, +543,478,427,425,424,423,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +543,427,425,424,423,1,0,51,52, +543,427,425,424,423,1,0,51,52, +491,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478,455, + 454,429,425,423,232,1,0,16, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478, + 455,454,429,425,423,232,1,0,16, +491,454,427,425,424,423,1,0,51,52, +491,454,0,88,130, +696,695,694,693,688,687,686,685,684,0, +704,698,696,695,694,693,688,687,686,685,684,682,427,425,424,423,221,220,1,0, + 222, +678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663,662,661,660, + 659,658,657,656,655,654,653,652,651,650,649,648,647,646,645,644,643,642, + 641,640,639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624, + 623,622,621,620,619,618,617,616,615,614,613,612,611,610,609,608,606,605, + 604,603,602,601,600,599,598,597,596,595,594,592,591,590,589,588,587,586, + 585,584,583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568, + 567,566,565,564,563,562,561,560,559,558,557,556,555,554,553,552,551,550, + 549,548,547,546,545,544,0,31,32,243,256,257,258,259,260,261,262,263,264, + 265,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283, + 284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301, + 302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319, + 320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337, + 338,339,340,341,342,343,345,346,347,348,349,350,351,352,353,354,355,356, + 357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374, + 375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392, + 393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410, + 411, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478,455, + 454,429,425,423,232,1,0,16, +478,0,120, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 489,455,429,230,133,132,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,84,86,87,129,131,195,197,202,203,204,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,434,441,483,490,537, +491,427,425,424,423,1,0,130, +491,427,425,424,423,1,0,130, +491,427,425,424,423,1,0,130, +491,427,425,424,423,1,0,130, +491,427,425,424,423,1,0,130, +705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,680,679,525,523,520,519,518,517,516,510,508,506,478,456, + 455,454,429,425,423,1,0,46,51,52,54,86,88,91,120,138,139,143,144,145, + 146,147,148,152,155,156,184,186,188,194,195,196,198,199,202,204,219,223, + 224,228,412,413,415,416,417,418,419,420,421,422, +696,695,694,693,688,687,686,685,684,0, +688,687,686,685,684,0, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478, + 455,454,429,425,423,1,0, +683,0, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +454,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, + 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,25,29,84,86,129,131,195,197, + 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, + 490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,25,29,84,86,129,131,195,197, + 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, + 490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,25,27,29,84,86,129,131,195,197, + 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, + 490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,25,27,29,84,86,129,131,195,197, + 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, + 490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,25,27,29,84,86,129,131,195,197, + 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, + 490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,25,27,29,84,86,129,131,195,197, + 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, + 490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,24,25,27,29,84,86,129,131,195, + 197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, + 441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,24,25,27,29,84,86,129,131,195, + 197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, + 441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,27,29,84,86,129,131, + 195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,27,29,84,86,129,131, + 195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,84,86,129, + 131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,84,86,129, + 131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,441,490,537, +427,425,424,423,1,0,51,52, +427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, +427,425,424,423,0,39,40,41,45,46,47,49, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +491,0,130, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478, + 455,454,429,425,423,232,1,0,16, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,680,539,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517, + 516,489,455,429,240,239,238,237,236,235,234,233,230,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 489,455,429,230,133,132,1,0,51,52, +543,0,266, +543,427,425,424,423,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478,455, + 454,429,425,423,232,1,0,16, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,1,0,51,52, +491,427,425,424,423,1,0,130, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, +705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,680,679,525,523,520,519,518,517,516,510,508,506,478,456, + 455,454,429,427,425,424,423,1,0,51,52, +705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,680,679,525,523,520,519,518,517,516,510,508,506,478,456, + 455,454,429,427,425,424,423,1,0, +427,425,424,423,0,39,40,41,45,46,47,49, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478, + 455,454,429,425,423,1,0, +688,687,686,685,684,0, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,3,131,441,535, +454,0,88, +454,0,88, +454,0,88, +454,0,88, +454,0,88, +454,0,88, +454,0,88, +454,0,88, +454,0,88, +454,0,88, +454,0,88, +543,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, + 504,503,502,501,500,499,498,497,496,495,494,493,491,454,425,423,1,0,196, + 198,199,200,201, +543,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, + 504,503,502,501,500,499,498,497,496,495,494,493,491,454,425,423,1,0,196, + 198,199,200,201, +543,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, + 499,498,497,496,495,494,493,491,454,427,425,424,423,1,0,194,195, +543,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, + 499,498,497,496,495,494,493,491,454,427,425,424,423,1,0,194,195, +543,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, + 499,498,497,496,495,494,493,491,454,427,425,424,423,1,0,194,195, +543,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, + 499,498,497,496,495,494,493,491,454,427,425,424,423,1,0,194,195, +543,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, + 497,496,495,494,493,491,454,427,425,424,423,1,0,190,191,192,193, +543,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, + 497,496,495,494,493,491,454,427,425,424,423,1,0,190,191,192,193, +543,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494, + 493,491,454,427,425,424,423,1,0,188,189, +543,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494, + 493,491,454,427,425,424,423,1,0,188,189, +543,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494,493,491, + 454,427,425,424,423,1,0,186,187, +543,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494,493,491, + 454,427,425,424,423,1,0,186,187, +427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,0,39,40,41,45,46,47,49, +539,240,239,238,237,236,235,234,233,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478, + 455,454,429,425,423,232,1,0, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 489,455,429,230,133,132,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,84,86,129,131,195,197,202,203,204,205,206,207,208,209,210,211, + 212,213,214,215,216,217,218,434,441,483,490,537, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, + 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, + 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, +704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,454, + 429,1,0,51,52,136, +454,1,0,51,52, +454,1,0,51,52, +539,240,239,238,237,236,235,234,233,0,4,241,593, +454,0,88, }; -static unsigned const char ag_astt[27588] = { +static unsigned const char ag_astt[27562] = { 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,7,1,1,9,5,2,2,2,2,2, 2,2,2,2,2,2,2,2,1,8,8,8,8,8,2,2,2,2,2,1,1,7,1,0,1,1,1,1,1,1,1,1,1,1,1,5,5, 5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,4,4,4,4, @@ -4057,10 +4042,10 @@ static unsigned const char ag_astt[27588] = { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1, 1,1,2,7,1,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,7,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,1,7,1,1,1,1,1,2,2,7,1,1,1,1,1,1,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, @@ -4262,73 +4247,85 @@ static unsigned const char ag_astt[27588] = { 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,5,2,2,2,2,2,2,2,2,2,2,2,5, 2,5,5,2,2,2,2,2,5,2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 2,5,5,5,5,1,7,1,3,2,5,5,5,5,5,1,7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,4,4,4,4,4,4,7,1,4,4,4,4,1,7,1,1,5,1,2,2,2,2, - 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,1,4,4,4,4,4,4,4,7,1,4,4,4,4,1,7,1,1,5,1,2,2,2,2,2,2,2,2,2,2,2,1, + 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, + 1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,7,2,2,1,2,2,2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,2,1,2,2,1,1,2,8,8,8,8,1,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,4,4,4,4,7,1,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, - 1,7,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,1,1,1,1,7,2, - 2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,8,8,8,8,1,7,1,1,2,2,2,2,2,7,2,2,2,2,7, - 2,2,7,4,4,4,4,4,4,4,2,2,2,2,4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,4,1,4,4,4,4,4,4,4,4,4,4, + 7,2,2,1,2,2,2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,2, + 2,1,1,2,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,2,1,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5, + 5,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1, + 2,1,1,1,8,8,8,8,1,7,1,1,2,2,2,2,2,7,2,2,2,2,7,2,2,7,4,4,4,4,4,4,4,2,2,2,2, + 4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,7,4,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,7,2,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,7,1,10,10,10,10,10,5,2,10,10,10,10,10,10,10,10,10,7,10,10,10,10,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,7,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,10,10,10,10,10,5,2,10,10,10,10,10, - 10,10,10,10,7,10,10,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,10,10,10,10,10,10,10,10,10,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,9,2, - 2,1,1,2,10,10,10,10,10,9,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,2,4,4,4,4,2,2,4,7,2,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,7,1,3,5,5, - 7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1, - 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 7,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,7,10,10,10,10,10,10,10,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,9,2,2,1,1,2,10,10,10,10,10,9,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4,2,2,4, + 7,2,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5, + 5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,1,7,1,1,8,1,7,1,1,8,1,7, + 1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1, + 8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,2,2,2,2,2,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, - 1,3,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1, - 8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,2,2,2,2, - 2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2, + 1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,1,1,1, + 1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1, + 1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7, + 1,3,1,1,5,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1, + 3,1,1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1, + 5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,5,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,5,5,5,5, + 5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3, + 8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,10,10,1,10,10,10,10,10,10, + 10,10,10,10,10,10,2,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,7,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, - 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1, - 1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,1,2,2,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,1,2,2,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,1,7,1,3,5,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,5,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,1,7,1,3,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,7,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1, - 2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,1,7,1,1,8,8,8,8, - 1,7,1,1,8,8,8,8,1,7,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,8,8, - 8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7, - 1,1,10,10,1,10,10,10,10,10,10,10,10,10,10,10,10,2,10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,7,5,5,5,5,5,7,1,3,8, - 8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, - 7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,1,5,5,5,5, + 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, - 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, @@ -4344,250 +4341,240 @@ static unsigned const char ag_astt[27588] = { 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, - 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, + 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,5,3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,7,3, - 1,7,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,7,1,1,2,2,1,2,2,2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,1,2,2,1,1,2,8,8,8,8,1,7,1,1,1,1,1,1,1,1,7,1,3,3,1,3,1,1,1,2,2,2,1, - 1,1,2,2,2,2,2,7,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,7,3,2,1,2,2,2,2,2,2,2,7,3, - 2,2,2,1,2,2,2,2,7,2,1,7,1,1,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1, - 1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, - 2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2, - 1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1, + 5,5,5,5,7,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,9,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,7,3,1,7,3,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,2,2,1,2,2,2,2,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,1,1,2,8,8,8,8,1, + 7,1,1,1,1,1,1,1,1,7,1,3,3,1,3,1,1,1,2,2,2,1,1,1,2,2,2,2,2,7,2,2,2,2,3,2,2, + 2,2,2,2,2,2,2,2,2,7,3,2,1,2,2,2,2,2,2,2,7,3,2,2,2,1,2,2,2,2,7,2,1,7,1,1,7, + 1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2, - 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, + 2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, - 2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1, 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, - 1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, + 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1, 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, - 1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1, - 1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1, - 2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2, + 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, - 1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, 2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1, 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, - 1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1, 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1, - 1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, + 1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, 2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, - 2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1, 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2, 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, - 1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1, 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, - 1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, - 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, - 2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, + 2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2, - 1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1, + 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1, 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, - 1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, + 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1, 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1, - 1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, + 1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, 2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2, - 1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2, - 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, + 2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, - 2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1, 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, - 1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, + 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1, 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, - 1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1, - 1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1, - 2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2, + 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, - 1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2, 1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,1,1,2,2,2,2,2, - 7,2,2,2,2,2,2,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,7,2,2, - 2,2,2,2,2,2,2,2,7,2,2,2,2,1,2,2,2,2,2,2,2,7,2,2,2,2,1,2,2,2,2,2,2,2,7,2,2, - 2,2,1,2,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2, - 2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2, - 7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2, - 2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2, - 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,2,9,7,2,1,1,2,1,1,1,1,5, + 7,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2,1,2, + 2,2,2,2,2,2,7,2,2,2,2,1,2,2,2,2,2,2,2,7,2,2,2,2,1,2,1,1,1,2,2,2,2,2,7,2,2, + 2,2,2,2,2,2,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2, + 2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1, + 2,2,2,2,2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2, + 2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2, + 7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1, + 1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,1,1,1,1,1,1,2,9,7,2,1,1,2,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1, - 3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,5,5,5,5,5,7,1,3,5,5,5,5,5,7, - 1,3,5,5,1,7,1,3,1,2,7,2,1,1,2,1,1,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2, - 2,4,7,2,1,1,5,1,7,1,3,2,7,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,7,2,1,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,1,7,1,3,1,2,7,2,1,1,2, + 1,1,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2,2,4,7,2,1,1,5,1,7,1,3,2,7,1,1, + 1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2, + 2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 7,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, + 1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1, - 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2, - 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2, - 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2, - 1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1, - 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1, - 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1, - 1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,1,1,1,1,7, - 3,3,1,3,1,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,7,2,2,1,2,1,1,1,2,1,2,2,2,2,2, - 1,1,1,1,2,3,7,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,2,2,2,2,2, - 2,2,2,2,7,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,7,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7, - 1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,7,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, - 1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1, + 2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,1,1,1,1,7,3,3,1,3,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,2,1,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 1,1,1,1,7,2,2,1,2,1,1,1,2,1,2,2,2,2,2,1,1,1,1,2,3,7,1,1,1,1,1,7,2,2,1,2,1, + 1,1,1,1,1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,7,2,1,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,7,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,7,1,1,7,1,1,7,1,1, + 7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, + 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 2,2,7,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, + 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, @@ -4599,18 +4586,18 @@ static unsigned const char ag_astt[27588] = { 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1, - 7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, + 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7, @@ -4624,162 +4611,160 @@ static unsigned const char ag_astt[27588] = { 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2, - 1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1, - 2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1, - 1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,7,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2, - 1,2,1,1,1,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,7, - 1,3,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2, - 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,3,3,1, - 3,1,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, - 7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,8,8,8, + 1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1, + 1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,7,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,7, + 1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,5,5,5,7,1,3,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1, + 8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1, + 1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, + 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,3,3,1,3,1,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7, + 1,1,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,5,5,5,5, - 5,5,7,1,3,8,1,7,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,7,1,3, - 1,1,7,2,1,2,2,2,2,2,2,2,2,2,7,9,2,2,1,1,2,10,10,10,10,10,9,4,4,4,4,2,2,4,7, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,8,1,7,1,1,2,1,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1, + 2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,7,1,3,1,1,7,2,1,2,2,2,2,2,2,2,2,2,7,9,2,2, + 1,1,2,10,10,10,10,10,9,4,4,4,4,2,2,4,7,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,1,2,1, - 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,7,1,1,4,4, - 4,4,4,7,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,5,1,7,1,3,1,7,2, + 1,1,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,8,1,7,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,7,1,1,1,1,1,7,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2, - 7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, - 1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2, + 1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2, + 1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,1,4,4,4,4, + 4,7,1,1,4,4,4,4,4,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,7,1,1,1, + 1,1,7,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,7,2,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2, 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, - 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, - 1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, + 1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2, - 1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1, + 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1, 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, - 1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, - 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2, - 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2, - 1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,1,2,2, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,1,2,2,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,1,2,2,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, - 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, - 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, - 2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, - 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, + 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1, + 1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1,1,2,2, + 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, + 2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, + 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, + 1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1, + 1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, - 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, - 1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,2,1,1,1,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,2, + 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, + 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, - 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,1,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7, - 2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,1,1, - 1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, + 2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1, + 2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, + 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, + 2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,1,7,1,1,1,1,1,1,7,2, + 2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,8,8,8,8,1,7,1, + 1,8,8,8,8,1,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, - 1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,1,7,1,1,1,7,1,5,5,5,5,5,1,7,1,3,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, - 1,1,1,4,4,4,4,4,7,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5, + 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,5,5,5,5,5,7,1,1,1,1,7,2,2,1,2,1,1,1,4,4,4,4,4,4,4,4,2,2,2,2,4, - 4,4,4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,7, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7, - 2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,3,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,4,1,1,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,1,7,1,5,5,5,5,5,1,7,1,3,2,1,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,7,2,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,1,7,1,1,1,4,4,4,4,4,7,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1, + 7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,7,1,1,1,1,7,2,2,1,2,1,1,1,4,4, + 4,4,4,4,4,4,2,2,2,2,4,4,4,4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,7,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,7,2,1,7,2, + 1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,3,4,1,1,1,1,1,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,4,1,1,1,1, + 1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1, + 4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4, + 1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1, + 1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,1, + 1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,4,1,1,1,1, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,4,1,1,4,4,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1, - 1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,1,2, - 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, - 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, - 2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 5,2,1,7,1,3,2,5,5,7,1,3,8,1,7,1,1,2,2,2,2,2,2,2,2,2,7,2,2,1,1,7,2 + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1, + 1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,8,8, + 8,8,8,8,8,8,8,1,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2, + 1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,5,2,1,7,1,3,2,5,5,7,1,3,8,1,7,1,1,2,2,2,2,2,2,2,2,2, + 7,2,2,1,1,7,2 }; static const unsigned short ag_pstt[] = { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,1,2, 18,20, -129,129,129,129,129,129,129,129,129,129,129,129,129,3,8,8,8,8,8,164,163,162, - 128,127,7,10,2,9,0,11,11,11,10,8,11,5,5,4,6,4, -19,19,19,19,19,19,19,19,19,19,19,1,3,1,890, -130,130,130,130,130,130,130,130,130,130,130,130,131,131,131,131,131,130,161, - 130,161,161,161,161,160,161,161,4,131, +127,127,127,127,127,127,127,127,127,127,127,127,127,3,8,8,8,8,8,162,161,160, + 126,125,7,10,2,9,0,11,11,11,10,8,11,5,5,4,6,4, +19,19,19,19,19,19,19,19,19,19,19,1,3,1,888, +128,128,128,128,128,128,128,128,128,128,128,128,129,129,129,129,129,128,159, + 128,159,159,159,159,158,159,159,4,129, 12,13,14,15,16,17,18,19,20,21,22,5,33,39,32,31,30,29,28,27,26,25,24,23, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, @@ -4789,7 +4774,7 @@ static const unsigned short ag_pstt[] = { 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,1,6,1,881, + 19,1,6,1,879, 34,7,37, 36,36,35,37,38,39,34,8,24,24,42,24,41,40,40,36,36, 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, @@ -4801,7 +4786,7 @@ static const unsigned short ag_pstt[] = { 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,19,19,43,43,43,43,43,43, 43,1,9,1,43, -129,129,129,129,129,129,129,129,129,129,129,129,129,111,112,113,114,115,116, +127,127,127,127,127,127,127,127,127,127,127,127,127,111,112,113,114,115,116, 117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134, 62,63,64,65,66,67,135,136,137,138,139,140,68,69,70,71,72,141,142,143,73, 74,75,76,77,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158, @@ -4810,1667 +4795,1663 @@ static const unsigned short ag_pstt[] = { 88,89,90,91,92,48,49,93,94,95,96,97,98,99,100,50,51,52,101,102,53,54, 103,104,105,106,55,56,57,58,265,265,265,265,265,265,265,265,265,265,265, 265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265, - 265,265,15,16,19,265,265,265,265,265,20,20,35,20,20,20,20,128,127,18,10, - 261,262,263,260,266,265,265,35,264,103,104,266,44,259,196,260,260,260, - 260,260,260,260,260,260,260,325,325,325,325,325,326,327,328,329,332,332, - 332,333,334,338,338,338,338,339,340,341,342,343,344,345,346,349,349,349, - 350,351,352,353,354,355,356,357,358,362,362,362,362,363,364,365,366,367, - 368,242,241,240,239,238,237,258,257,256,255,254,253,252,251,250,249,248, + 265,265,15,16,19,265,265,265,265,265,20,20,35,20,20,20,20,126,125,18,10, + 261,262,263,260,266,265,265,35,264,101,102,266,44,259,196,260,260,260, + 260,260,260,260,260,260,260,323,323,323,323,323,324,325,326,327,330,330, + 330,331,332,336,336,336,336,337,338,339,340,341,342,343,344,347,347,347, + 348,349,350,351,352,353,354,355,356,360,360,360,360,361,362,363,364,365, + 366,242,241,240,239,238,237,258,257,256,255,254,253,252,251,250,249,248, 247,246,245,244,243,184,110,183,109,182,108,181,236,235,234,233,232,231, 230,229,228,227,226,225,224,223,222,221,221,221,221,221,221,220,219,218, 217,217,217,217,217,217,216,215,214,213,212,211,210,210,210,210,209,209, 209,209,208,207,206,205,204,203,202,201,200,199,198,197,195,194,193,192, 191,190,189,188,187,186,185,259, -129,129,129,129,129,129,129,129,129,129,129,129,129,3,8,8,8,8,8,164,163,162, - 128,127,7,4,10,11,9,3,3,10,8,3,5,5,4,6,4, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,12,1,906, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,13,1,905, -19,1,14,1,904, -19,19,19,19,19,15,1,903, -19,19,19,19,19,16,1,902, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,17,1,901, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,18,1,900, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,19,1,899, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,20,1,898, -19,19,19,19,19,1,21,1,892, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,22,1,885, -129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,23,267,268,259, +127,127,127,127,127,127,127,127,127,127,127,127,127,3,8,8,8,8,8,162,161,160, + 126,125,7,4,10,11,9,3,3,10,8,3,5,5,4,6,4, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,12,1,904, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,13,1,903, +19,1,14,1,902, +19,19,19,19,19,15,1,901, +19,19,19,19,19,16,1,900, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,17,1,899, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,18,1,898, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,19,1,897, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,20,1,896, +19,19,19,19,19,1,21,1,890, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,22,1,883, +127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,23,261,267,259, 259, -129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,24,269,259,259, -138,25,272,270,271, -273,273,273,273,1,26,1,273, -274,274,274,274,1,27,1,274, -129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,28,275,259,259, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,29,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,330,332,318,218,304,259,331,319,323,322,321,320,217,323,313, - 312,311,310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,30,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,330,333,318,218,304,259,331,319,323,322,321,320,217,323,313, - 312,311,310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,31,334,259,259, -335,337,339,341,343,32,344,342,340,338,336, -156,138,33,348,270,347,345,271,346, +127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,24,268,259,259, +136,25,271,269,270, +272,272,272,272,1,26,1,272, +273,273,273,273,1,27,1,273, +127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,28,274,259,259, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,29,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,329,331,216,317,303,259,330,318,322,321,320,319,215,322,312, + 311,310,309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,30,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,329,332,216,317,303,259,330,318,322,321,320,319,215,322,312, + 311,310,309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,31,333,259,259, +334,336,338,340,342,32,343,341,339,337,335, +154,136,33,347,269,346,344,270,345, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,34,1,876, + 19,19,19,19,19,19,19,34,1,874, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,35,1,882, -349,22,36,350,350,350, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,35,1,880, +348,22,36,349,349,349, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,37,1,880, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,37,1,878, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,38, - 1,878, + 1,876, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,39,1,877, -351,353,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371, - 372,373,374,381,384,385,386,387,315,317,383,375,379,376,378,382,354,352, - 377,302,380,35,37,388,38,34,15,40,16,15,15,40,13,40,15,15,15,15,15,15, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,39,1,875, +350,352,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370, + 371,372,373,380,383,384,385,386,314,316,382,374,378,375,377,381,353,351, + 376,301,379,35,37,387,38,34,15,40,16,15,15,40,13,40,15,15,15,15,15,15, 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, 15,15,15,15,15,15,15,15,15,15,15, -351,353,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371, - 372,373,374,381,384,385,386,387,315,317,383,375,379,376,378,382,354,352, - 377,302,380,35,38,390,389,41,389,390,389,389,389,389,389,389,389,389, - 389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389, - 389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389, -351,353,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371, - 372,373,374,381,384,385,386,387,315,317,383,375,379,376,378,382,354,352, - 377,302,380,35,38,391,389,42,389,391,389,389,389,389,389,389,389,389, - 389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389, - 389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389, -129,129,129,129,129,129,129,129,129,129,129,129,129,111,112,113,114,115,116, +350,352,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370, + 371,372,373,380,383,384,385,386,314,316,382,374,378,375,377,381,353,351, + 376,301,379,35,38,389,388,41,388,389,388,388,388,388,388,388,388,388, + 388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388, + 388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388, +350,352,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370, + 371,372,373,380,383,384,385,386,314,316,382,374,378,375,377,381,353,351, + 376,301,379,35,38,390,388,42,388,390,388,388,388,388,388,388,388,388, + 388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388, + 388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388, +127,127,127,127,127,127,127,127,127,127,127,127,127,111,112,113,114,115,116, 117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134, 62,63,64,65,66,67,135,136,137,138,139,140,68,69,70,71,72,141,142,143,73, 74,75,76,77,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158, 107,59,60,61,165,166,167,168,169,170,171,172,173,174,175,176,177,178, 179,180,159,160,161,162,163,164,78,79,80,81,82,83,45,46,47,84,85,86,87, 88,89,90,91,92,48,49,93,94,95,96,97,98,99,100,50,51,52,101,102,53,54, - 103,104,105,106,55,56,57,58,392,392,392,392,392,392,392,392,392,392,392, - 392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392, - 392,392,15,16,19,392,392,392,392,392,392,392,35,37,38,39,34,128,127,43, - 261,262,263,260,393,23,23,42,23,41,40,40,392,392,36,264,103,104,393,44, - 259,196,260,260,260,260,260,260,260,260,260,260,325,325,325,325,325,326, - 327,328,329,332,332,332,333,334,338,338,338,338,339,340,341,342,343,344, - 345,346,349,349,349,350,351,352,353,354,355,356,357,358,362,362,362,362, - 363,364,365,366,367,368,242,241,240,239,238,237,258,257,256,255,254,253, + 103,104,105,106,55,56,57,58,391,391,391,391,391,391,391,391,391,391,391, + 391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, + 391,391,15,16,19,391,391,391,391,391,391,391,35,37,38,39,34,126,125,43, + 261,262,263,260,392,23,23,42,23,41,40,40,391,391,36,264,101,102,392,44, + 259,196,260,260,260,260,260,260,260,260,260,260,323,323,323,323,323,324, + 325,326,327,330,330,330,331,332,336,336,336,336,337,338,339,340,341,342, + 343,344,347,347,347,348,349,350,351,352,353,354,355,356,360,360,360,360, + 361,362,363,364,365,366,242,241,240,239,238,237,258,257,256,255,254,253, 252,251,250,249,248,247,246,245,244,243,184,110,183,109,182,108,181,236, 235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,221,221,221, 221,221,220,219,218,217,217,217,217,217,217,216,215,214,213,212,211,210, 210,210,210,209,209,209,209,208,207,206,205,204,203,202,201,200,199,198, 197,195,194,193,192,191,190,189,188,187,186,185,259, -394,394,394,394,394,394,1,44,1,394, -19,19,19,19,19,19,45,1,1034, -19,19,19,19,19,19,46,1,1033, -19,19,19,19,19,19,47,1,1032, -19,19,19,19,19,19,48,1,1022, -19,19,19,19,19,19,49,1,1021, -19,19,19,19,19,19,50,1,1012, -19,19,19,19,19,19,51,1,1011, -19,19,19,19,19,19,52,1,1010, -19,19,19,19,19,19,53,1,1007, -19,19,19,19,19,19,54,1,1006, -19,19,19,19,19,19,55,1,1001, -19,19,19,19,19,19,56,1,1000, -19,19,19,19,19,19,57,1,999, -19,19,19,19,19,19,58,1,998, -19,19,19,19,19,19,19,19,19,19,59,1,1067, -19,19,19,19,19,19,19,19,19,19,60,1,1066, -19,19,19,19,19,19,19,19,61,1,1065, +393,393,393,393,393,393,1,44,1,393, +19,19,19,19,19,19,45,1,1031, +19,19,19,19,19,19,46,1,1030, +19,19,19,19,19,19,47,1,1029, +19,19,19,19,19,19,48,1,1019, +19,19,19,19,19,19,49,1,1018, +19,19,19,19,19,19,50,1,1009, +19,19,19,19,19,19,51,1,1008, +19,19,19,19,19,19,52,1,1007, +19,19,19,19,19,19,53,1,1004, +19,19,19,19,19,19,54,1,1003, +19,19,19,19,19,19,55,1,998, +19,19,19,19,19,19,56,1,997, +19,19,19,19,19,19,57,1,996, +19,19,19,19,19,19,58,1,995, +19,19,19,19,19,19,19,19,19,19,59,1,1064, +19,19,19,19,19,19,19,19,19,19,60,1,1063, +19,19,19,19,19,19,19,19,61,1,1062, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,62,1,1108, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,62,1,1105, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,63,1,1107, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,63,1,1104, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,64,1,1106, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,64,1,1103, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,65,1,1105, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,65,1,1102, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,66,1,1104, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,66,1,1101, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,67,1,1103, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,67,1,1100, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,68,1,1096, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,68,1,1093, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,69,1,1095, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,69,1,1092, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,70,1,1094, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,70,1,1091, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,71,1,1093, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,71,1,1090, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,72,1,1092, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,72,1,1089, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,73,1,1088, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,73,1,1085, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,74,1,1087, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,74,1,1084, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,75,1,1086, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,75,1,1083, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,76,1,1085, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,76,1,1082, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,77,1,1084, -19,19,19,19,19,19,78,1,1040, -19,19,19,19,19,19,79,1,1039, -19,19,19,19,19,19,80,1,1038, -19,19,19,19,19,19,81,1,1037, -19,19,19,19,19,19,82,1,1036, -19,19,19,19,19,19,83,1,1035, -19,19,19,19,19,19,84,1,1031, -19,19,19,19,19,19,85,1,1030, -19,19,19,19,19,19,86,1,1029, -19,19,19,19,19,19,87,1,1028, -19,19,19,19,19,19,88,1,1027, -19,19,19,19,19,19,89,1,1026, -19,19,19,19,19,19,90,1,1025, -19,19,19,19,19,19,91,1,1024, -19,19,19,19,19,19,92,1,1023, -19,19,19,19,19,19,93,1,1020, -19,19,19,19,19,19,94,1,1019, -19,19,19,19,19,19,95,1,1018, -19,19,19,19,19,19,96,1,1017, -19,19,19,19,19,19,97,1,1016, -19,19,19,19,19,19,98,1,1015, -19,19,19,19,19,19,99,1,1014, -19,19,19,19,19,19,100,1,1013, -19,19,19,19,19,19,101,1,1009, -19,19,19,19,19,19,102,1,1008, -19,19,19,19,19,19,103,1,1005, -19,19,19,19,19,19,104,1,1004, -19,19,19,19,19,19,105,1,1003, -19,19,19,19,19,19,106,1,1002, -19,19,19,19,19,107,1,1068, -395,395,395,395,395,395,395,395,395,1,108,1,395, -396,396,396,396,396,396,396,396,396,1,109,1,396, -397,397,397,397,397,397,397,1,110,1,397, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,77,1,1081, +19,19,19,19,19,19,78,1,1037, +19,19,19,19,19,19,79,1,1036, +19,19,19,19,19,19,80,1,1035, +19,19,19,19,19,19,81,1,1034, +19,19,19,19,19,19,82,1,1033, +19,19,19,19,19,19,83,1,1032, +19,19,19,19,19,19,84,1,1028, +19,19,19,19,19,19,85,1,1027, +19,19,19,19,19,19,86,1,1026, +19,19,19,19,19,19,87,1,1025, +19,19,19,19,19,19,88,1,1024, +19,19,19,19,19,19,89,1,1023, +19,19,19,19,19,19,90,1,1022, +19,19,19,19,19,19,91,1,1021, +19,19,19,19,19,19,92,1,1020, +19,19,19,19,19,19,93,1,1017, +19,19,19,19,19,19,94,1,1016, +19,19,19,19,19,19,95,1,1015, +19,19,19,19,19,19,96,1,1014, +19,19,19,19,19,19,97,1,1013, +19,19,19,19,19,19,98,1,1012, +19,19,19,19,19,19,99,1,1011, +19,19,19,19,19,19,100,1,1010, +19,19,19,19,19,19,101,1,1006, +19,19,19,19,19,19,102,1,1005, +19,19,19,19,19,19,103,1,1002, +19,19,19,19,19,19,104,1,1001, +19,19,19,19,19,19,105,1,1000, +19,19,19,19,19,19,106,1,999, +19,19,19,19,19,107,1,1065, +394,394,394,394,394,394,394,394,394,1,108,1,394, +395,395,395,395,395,395,395,395,395,1,109,1,395, +396,396,396,396,396,396,396,1,110,1,396, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,111,1,1132, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,111,1,1129, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,112,1,1131, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,112,1,1128, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,113,1,1130, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,113,1,1127, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,114,1,1129, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,114,1,1126, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,115,1,1128, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,115,1,1125, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,116,1,1127, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,116,1,1124, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,117,1,1126, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,117,1,1123, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,118,1,1125, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,118,1,1122, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,119,1,1124, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,119,1,1121, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,120,1,1123, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,120,1,1120, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,121,1,1122, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,121,1,1119, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,122,1,1121, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,122,1,1118, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,123,1,1120, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,123,1,1117, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,124,1,1119, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,124,1,1116, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,125,1,1118, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,125,1,1115, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,126,1,1117, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,126,1,1114, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,127,1,1116, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,127,1,1113, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,128,1,1115, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,128,1,1112, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,129,1,1114, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,129,1,1111, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,130,1,1113, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,130,1,1110, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,131,1,1112, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,131,1,1109, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,132,1,1111, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,132,1,1108, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,133,1,1110, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,133,1,1107, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,134,1,1109, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,134,1,1106, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,135,1,1102, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,135,1,1099, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,136,1,1101, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,136,1,1098, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,137,1,1100, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,137,1,1097, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,138,1,1099, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,138,1,1096, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,139,1,1098, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,139,1,1095, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,140,1,1097, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,140,1,1094, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,141,1,1091, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,141,1,1088, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,142,1,1090, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,142,1,1087, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,143,1,1089, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,143,1,1086, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,144,1,1083, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,144,1,1080, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,145,1,1082, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,145,1,1079, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,146,1,1081, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,146,1,1078, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,147,1,1080, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,147,1,1077, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,148,1,1079, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,148,1,1076, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,149,1,1078, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,149,1,1075, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,150,1,1077, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,150,1,1074, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,151,1,1076, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,151,1,1073, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,152,1,1075, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,152,1,1072, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,153,1,1074, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,153,1,1071, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,154,1,1073, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,154,1,1070, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,155,1,1072, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,155,1,1069, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,156,1,1071, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,156,1,1068, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,157,1,1070, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,157,1,1067, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,158,1,1069, -19,19,19,19,19,19,19,19,19,159,1,1046, -19,19,19,19,19,19,19,19,19,160,1,1045, -19,19,19,19,19,19,19,19,19,161,1,1044, -19,19,19,19,19,19,19,19,19,162,1,1043, -19,19,19,19,19,163,1,1042, -19,19,19,19,19,164,1,1041, -19,19,19,19,19,19,19,19,165,1,1064, -19,19,19,19,19,19,19,19,166,1,1063, -19,19,19,19,19,19,19,19,167,1,1062, -19,19,19,19,19,19,19,19,19,19,168,1,1060, -19,19,19,19,19,19,19,19,19,19,169,1,1059, -19,19,19,19,19,19,19,19,19,19,170,1,1058, -19,19,19,19,19,19,19,19,19,19,171,1,1057, -19,19,19,19,19,19,19,19,19,19,172,1,1056, -19,19,19,19,19,19,19,19,19,19,173,1,1055, -19,19,19,19,19,19,19,19,19,19,174,1,1054, -19,19,19,19,19,19,19,19,19,19,175,1,1053, -19,19,19,19,19,19,19,19,19,19,176,1,1052, -19,19,19,19,19,19,19,19,19,19,177,1,1051, -19,19,19,19,19,19,19,19,19,19,178,1,1050, -19,19,19,19,19,19,19,19,19,19,179,1,1049, -19,19,19,19,19,19,19,19,19,19,180,1,1048, -398,398,398,398,1,181,1,398, -399,1,182,1,399, -400,1,183,1,400, -401,1,184,1,401, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,158,1,1066, +19,19,19,19,19,19,19,19,19,159,1,1043, +19,19,19,19,19,19,19,19,19,160,1,1042, +19,19,19,19,19,19,19,19,19,161,1,1041, +19,19,19,19,19,19,19,19,19,162,1,1040, +19,19,19,19,19,163,1,1039, +19,19,19,19,19,164,1,1038, +19,19,19,19,19,19,19,19,165,1,1061, +19,19,19,19,19,19,19,19,166,1,1060, +19,19,19,19,19,19,19,19,167,1,1059, +19,19,19,19,19,19,19,19,19,19,168,1,1057, +19,19,19,19,19,19,19,19,19,19,169,1,1056, +19,19,19,19,19,19,19,19,19,19,170,1,1055, +19,19,19,19,19,19,19,19,19,19,171,1,1054, +19,19,19,19,19,19,19,19,19,19,172,1,1053, +19,19,19,19,19,19,19,19,19,19,173,1,1052, +19,19,19,19,19,19,19,19,19,19,174,1,1051, +19,19,19,19,19,19,19,19,19,19,175,1,1050, +19,19,19,19,19,19,19,19,19,19,176,1,1049, +19,19,19,19,19,19,19,19,19,19,177,1,1048, +19,19,19,19,19,19,19,19,19,19,178,1,1047, +19,19,19,19,19,19,19,19,19,19,179,1,1046, +19,19,19,19,19,19,19,19,19,19,180,1,1045, +397,397,397,397,1,181,1,397, +398,1,182,1,398, +399,1,183,1,399, +400,1,184,1,400, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, + 401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, + 401,401,401,401,401,1,185,1,401, 402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, 402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, - 402,402,402,402,402,1,185,1,402, + 402,402,402,402,402,1,186,1,402, 403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403, 403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403, - 403,403,403,403,403,1,186,1,403, + 403,403,403,403,403,1,187,1,403, 404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, 404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, - 404,404,404,404,404,1,187,1,404, + 404,404,404,404,404,1,188,1,404, 405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405, 405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405, - 405,405,405,405,405,1,188,1,405, + 405,405,405,405,405,1,189,1,405, 406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406, 406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406, - 406,406,406,406,406,1,189,1,406, + 406,406,406,406,406,1,190,1,406, 407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407, 407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407, - 407,407,407,407,407,1,190,1,407, + 407,407,407,407,407,1,191,1,407, 408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408, 408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408, - 408,408,408,408,408,1,191,1,408, + 408,408,408,408,408,1,192,1,408, 409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409, 409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409, - 409,409,409,409,409,1,192,1,409, + 409,409,409,409,409,1,193,1,409, 410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, 410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, - 410,410,410,410,410,1,193,1,410, + 410,410,410,410,410,1,194,1,410, 411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411, 411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411, - 411,411,411,411,411,1,194,1,411, + 411,411,411,411,411,1,195,1,411, 412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412, 412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412, - 412,412,412,412,412,1,195,1,412, + 412,412,412,412,412,1,196,1,412, 413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, 413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, - 413,413,413,413,413,1,196,1,413, + 413,413,413,413,413,1,197,1,413, 414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, 414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, - 414,414,414,414,414,1,197,1,414, + 414,414,414,414,414,1,198,1,414, 415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, 415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, - 415,415,415,415,415,1,198,1,415, + 415,415,415,415,415,1,199,1,415, 416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, 416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, - 416,416,416,416,416,1,199,1,416, + 416,416,416,416,416,1,200,1,416, 417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417, 417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417, - 417,417,417,417,417,1,200,1,417, + 417,417,417,417,417,1,201,1,417, 418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, 418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, - 418,418,418,418,418,1,201,1,418, + 418,418,418,418,418,1,202,1,418, 419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419, 419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419, - 419,419,419,419,419,1,202,1,419, + 419,419,419,419,419,1,203,1,419, 420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420, 420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420, - 420,420,420,420,420,1,203,1,420, + 420,420,420,420,420,1,204,1,420, 421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421, 421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421, - 421,421,421,421,421,1,204,1,421, + 421,421,421,421,421,1,205,1,421, 422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, 422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, - 422,422,422,422,422,1,205,1,422, + 422,422,422,422,422,1,206,1,422, 423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423, 423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423, - 423,423,423,423,423,1,206,1,423, + 423,423,423,423,423,1,207,1,423, 424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424, 424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424, - 424,424,424,424,424,1,207,1,424, + 424,424,424,424,424,1,208,1,424, 425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425, 425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425, - 425,425,425,425,425,1,208,1,425, + 425,425,425,425,425,1,209,1,425, 426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, 426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, - 426,426,426,426,426,1,209,1,426, + 426,426,426,426,426,1,210,1,426, 427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427, 427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427, - 427,427,427,427,427,1,210,1,427, + 427,427,427,427,427,1,211,1,427, 428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, 428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, - 428,428,428,428,428,1,211,1,428, + 428,428,428,428,428,1,212,1,428, 429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, 429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, - 429,429,429,429,429,1,212,1,429, + 429,429,429,429,429,1,213,1,429, 430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430, 430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430, - 430,430,430,430,430,1,213,1,430, + 430,430,430,430,430,1,214,1,430, 431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431, 431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431, - 431,431,431,431,431,1,214,1,431, + 431,431,431,431,431,1,215,1,431, 432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432, 432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432, - 432,432,432,432,432,1,215,1,432, + 432,432,432,432,432,1,216,1,432, 433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433, 433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433, - 433,433,433,433,433,1,216,1,433, + 433,433,433,433,433,1,217,1,433, 434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434, 434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434, - 434,434,434,434,434,1,217,1,434, + 434,434,434,434,434,1,218,1,434, 435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435, 435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435, - 435,435,435,435,435,1,218,1,435, + 435,435,435,435,435,1,219,1,435, 436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, 436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, - 436,436,436,436,436,1,219,1,436, + 436,436,436,436,436,1,220,1,436, 437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, 437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, - 437,437,437,437,437,1,220,1,437, + 437,437,437,437,437,1,221,1,437, 438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, 438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, - 438,438,438,438,438,1,221,1,438, + 438,438,438,438,438,1,222,1,438, 439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, 439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, - 439,439,439,439,439,1,222,1,439, + 439,439,439,439,439,1,223,1,439, 440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, 440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, - 440,440,440,440,440,1,223,1,440, + 440,440,440,440,440,1,224,1,440, 441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441, 441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441, - 441,441,441,441,441,1,224,1,441, + 441,441,441,441,441,1,225,1,441, 442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442, 442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442, - 442,442,442,442,442,1,225,1,442, + 442,442,442,442,442,1,226,1,442, 443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443, 443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443, - 443,443,443,443,443,1,226,1,443, + 443,443,443,443,443,1,227,1,443, 444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444, 444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444, - 444,444,444,444,444,1,227,1,444, + 444,444,444,444,444,1,228,1,444, 445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445, 445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445, - 445,445,445,445,445,1,228,1,445, + 445,445,445,445,445,1,229,1,445, 446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446, 446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446, - 446,446,446,446,446,1,229,1,446, + 446,446,446,446,446,1,230,1,446, 447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447, 447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447, - 447,447,447,447,447,1,230,1,447, + 447,447,447,447,447,1,231,1,447, 448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448, 448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448, - 448,448,448,448,448,1,231,1,448, + 448,448,448,448,448,1,232,1,448, 449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, 449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, - 449,449,449,449,449,1,232,1,449, + 449,449,449,449,449,1,233,1,449, 450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, 450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, - 450,450,450,450,450,1,233,1,450, + 450,450,450,450,450,1,234,1,450, 451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, 451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, - 451,451,451,451,451,1,234,1,451, + 451,451,451,451,451,1,235,1,451, 452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452, 452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452, - 452,452,452,452,452,1,235,1,452, -453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453, - 453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453, - 453,453,453,453,453,1,236,1,453, -454,454,454,454,454,454,454,454,1,237,1,454, -455,455,455,455,455,455,455,455,1,238,1,455, -456,456,456,456,456,456,456,456,1,239,1,456, -457,457,457,457,457,457,457,457,1,240,1,457, -458,458,458,458,1,241,1,458, -459,459,459,459,1,242,1,459, -460,460,460,460,460,460,460,1,243,1,460, -461,461,461,461,461,461,461,1,244,1,461, -462,462,462,462,462,462,462,1,245,1,462, -463,463,463,463,463,463,463,463,463,1,246,1,463, -464,464,464,464,464,464,464,464,464,1,247,1,464, -465,465,465,465,465,465,465,465,465,1,248,1,465, -466,466,466,466,466,466,466,466,466,1,249,1,466, -467,467,467,467,467,467,467,467,467,1,250,1,467, -468,468,468,468,468,468,468,468,468,1,251,1,468, -469,469,469,469,469,469,469,469,469,1,252,1,469, -470,470,470,470,470,470,470,470,470,1,253,1,470, -471,471,471,471,471,471,471,471,471,1,254,1,471, -472,472,472,472,472,472,472,472,472,1,255,1,472, -473,473,473,473,473,473,473,473,473,1,256,1,473, -474,474,474,474,474,474,474,474,474,1,257,1,474, -475,475,475,475,475,475,475,475,475,1,258,1,475, -19,130,130,130,130,130,130,130,130,130,130,130,19,130,19,19,131,131,131,131, - 131,19,130,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,130,19,19,19,19,1,259,1,894,131, -19,19,19,19,19,1,260,1,309, -61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,302,61,61,61,61,61,61,261,476, -114,114,114,114,477,262,477, -478,113,479, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,264,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,330,102,318,218,304,259,331,319,323,322,321,320,217,323,313, - 312,311,310,309,308,307,306,305,303,286,285,259,301,300, -290,480,482,484,485,486,488,489,490,492,494,496,498,500,502,504,506,508,510, - 511,513,514,515,517,518,520,521,522,523,526,527,335,337,339,341,343,265, - 70,71,525,72,74,65,66,524,524,524,524,79,519,519,519,516,516,516,516, - 512,512,512,509,507,505,503,501,499,497,495,493,491,105,106,487,109,110, - 483,481,115, -528,528,528,528,1,266,1,528, + 452,452,452,452,452,1,236,1,452, +453,453,453,453,453,453,453,453,1,237,1,453, +454,454,454,454,454,454,454,454,1,238,1,454, +455,455,455,455,455,455,455,455,1,239,1,455, +456,456,456,456,456,456,456,456,1,240,1,456, +457,457,457,457,1,241,1,457, +458,458,458,458,1,242,1,458, +459,459,459,459,459,459,459,1,243,1,459, +460,460,460,460,460,460,460,1,244,1,460, +461,461,461,461,461,461,461,1,245,1,461, +462,462,462,462,462,462,462,462,462,1,246,1,462, +463,463,463,463,463,463,463,463,463,1,247,1,463, +464,464,464,464,464,464,464,464,464,1,248,1,464, +465,465,465,465,465,465,465,465,465,1,249,1,465, +466,466,466,466,466,466,466,466,466,1,250,1,466, +467,467,467,467,467,467,467,467,467,1,251,1,467, +468,468,468,468,468,468,468,468,468,1,252,1,468, +469,469,469,469,469,469,469,469,469,1,253,1,469, +470,470,470,470,470,470,470,470,470,1,254,1,470, +471,471,471,471,471,471,471,471,471,1,255,1,471, +472,472,472,472,472,472,472,472,472,1,256,1,472, +473,473,473,473,473,473,473,473,473,1,257,1,473, +474,474,474,474,474,474,474,474,474,1,258,1,474, +19,128,128,128,128,128,128,128,128,128,128,128,19,128,19,19,129,129,129,129, + 129,19,128,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,128,19,19,19,19,1,259,1,892,129, +19,19,19,19,19,1,260,1,307, 59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59, - 59,59,59,59,59,59,59,59,59,59,59,302,59,59,59,59,267,529, -530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, - 530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, - 530,530,530,1,268,1,530, -531,531,531,531,1,269,1,531, -141,532,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, - 141,141,141,141,141,137,141,141,141,141,141,141,141,141,141,141,141,141, - 141,141,141,141,141,141,270,139, -19,19,19,19,19,19,19,19,271,1,887, -533,533,533,533,1,272,1,533, -37,38,39,34,273,54,54,42,54,41,40,40, -37,38,39,34,274,53,53,42,53,41,40,40, -534,534,534,534,1,275,1,534, -274,274,274,274,274,276, -259,259,259,259,277, -257,257,278, -129,129,129,129,129,129,129,253,253,253,253,129,253,253,253,253,253,129,129, - 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, - 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, - 129,129,129,279, -248,535,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, - 248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, - 248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,280, -246,246,246,246,246,281, -264,536,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, - 264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, - 264,264,264,264,270,264,282,537, -275,275,275,275,275,272, -239,256,256,256,256,256,256,256,256,256,284, -260,260,260,260,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, - 238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, - 238,238,238,238,238,285, -258,258,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, - 237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, - 237,237,237,286, -254,254,254,254,254,254,254,254,254,236,236,236,236,236,236,236,236,236,236, + 59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59, + 59,59,59,59,59,59,59,59,59,59,59,301,59,59,59,59,59,59,59,261,475, +112,112,112,112,476,262,476, +477,111,478, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,264,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,329,100,216,317,303,259,330,318,322,321,320,319,215,322,312, + 311,310,309,308,307,306,305,304,302,285,284,259,300,299, +289,479,481,483,484,485,487,488,489,491,493,495,497,499,501,503,505,507,509, + 510,512,513,514,516,517,519,520,521,522,525,526,334,336,338,340,342,265, + 68,69,524,70,72,63,64,523,523,523,523,77,518,518,518,515,515,515,515, + 511,511,511,508,506,504,502,500,498,496,494,492,490,103,104,486,107,108, + 482,480,113, +527,527,527,527,1,266,1,527, +528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528, + 528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528, + 528,528,528,1,267,1,528, +529,529,529,529,1,268,1,529, +139,530,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, + 139,139,139,139,139,135,139,139,139,139,139,139,139,139,139,139,139,139, + 139,139,139,139,139,139,269,137, +19,19,19,19,19,19,19,19,270,1,885, +531,531,531,531,1,271,1,531, +37,38,39,34,272,54,54,42,54,41,40,40, +37,38,39,34,273,53,53,42,53,41,40,40, +532,532,532,532,1,274,1,532, +272,272,272,272,272,275, +257,257,257,257,276, +255,255,277, +127,127,127,127,127,127,127,251,251,251,251,127,251,251,251,251,251,127,127, + 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, + 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, + 127,127,127,278, +246,533,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, + 246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, + 246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,279, +244,244,244,244,244,280, +262,534,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, + 262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, + 262,262,262,262,268,262,281,535, +273,273,273,273,273,270, +237,254,254,254,254,254,254,254,254,254,283, +258,258,258,258,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, 236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, - 236,236,236,236,236,236,236,236,236,236,287, -250,240,255,538,539,255,249,249,249,249,249,251,235,235,235,235,235,235,235, + 236,236,236,236,236,284, +256,256,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, 235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, - 235,235,235,235,235,235,273,235,235,235,235,244,244,235,288,244, -19,19,289,1,990, -19,19,19,19,19,19,290,1,943, -19,19,291,1,988, -19,19,292,1,987, -19,19,293,1,986, -19,19,294,1,985, -19,19,295,1,984, -19,19,296,1,983, -19,19,297,1,982, -19,19,298,1,981, -19,19,299,1,980, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,300,1,991, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,1,301,1,944, + 235,235,235,285, +252,252,252,252,252,252,252,252,252,234,234,234,234,234,234,234,234,234,234, + 234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, + 234,234,234,234,234,234,234,234,234,234,286, +248,238,253,536,537,253,247,247,247,247,247,249,233,233,233,233,233,233,233, + 233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, + 233,233,233,233,233,233,271,233,233,233,233,242,242,233,287,242, +19,19,288,1,987, +19,19,19,19,19,19,289,1,940, +19,19,290,1,985, +19,19,291,1,984, +19,19,292,1,983, +19,19,293,1,982, +19,19,294,1,981, +19,19,295,1,980, +19,19,296,1,979, +19,19,297,1,978, +19,19,298,1,977, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,299,1,988, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,1,300,1,941, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,302,1,909, -540,1,303,1,540, -541,1,304,1,541, -542,1,305,1,542, -543,1,306,1,543, -544,1,307,1,544, -545,1,308,1,545, -546,1,309,1,546, -547,1,310,1,547, -548,1,311,1,548, -549,1,312,1,549, -550,1,313,1,550, -19,19,19,19,19,19,19,19,19,19,19,19,19,247,247,247,247,247,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,314,1,971, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,301,1,906, +538,1,302,1,538, +539,1,303,1,539, +540,1,304,1,540, +541,1,305,1,541, +542,1,306,1,542, +543,1,307,1,543, +544,1,308,1,544, +545,1,309,1,545, +546,1,310,1,546, +547,1,311,1,547, +548,1,312,1,548, +19,19,19,19,19,19,19,19,19,19,19,19,19,245,245,245,245,245,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,313,1,968, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,315,1,979, + 19,19,19,19,19,19,19,19,19,19,19,19,19,314,1,976, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,316,1,978, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,315,1,975, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,317,1,977, -551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, - 551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, - 551,551,551,551,551,1,318,1,551, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, - 128,127,319,232,287,288,233,283,234,284,261,318,218,304,259,216,217,216, - 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, - 128,127,320,232,287,288,233,283,234,284,261,318,218,304,259,215,217,215, - 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, - 128,127,321,232,287,288,233,283,234,284,261,318,218,304,259,214,217,214, - 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, - 128,127,322,232,287,288,233,283,234,284,261,318,218,304,259,213,217,213, - 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,1,323,1,206, -19,553,555,383,375,379,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,1,324,1,203,559,558,557,556,554, -19,376,378,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,1,325,1,198,561,560, -19,562,564,566,568,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,1,326,1,195,569,567,565,563, -19,570,382,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,1,327,1,192,572,571, -19,573,354,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1, - 328,1,189,575,574, -576,352,188,578,577, -579,580,581,582,583,584,585,586,587,588,589,590,591,168,168,168,168,168,330, - 172,172,172,172,175,175,175,178,178,178,181,181,181,184,184,184,187,187, - 187, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,331,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,167,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -592,592,592,592,1,332,1,592, -593,593,593,593,1,333,1,593, -594,594,594,594,594,334,594, -19,19,19,19,19,335,1,897, -595,595,595,595,1,336,1,595, -19,19,19,19,19,337,1,896, -596,596,596,596,1,338,1,596, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,339,1,895, -597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,1,340,1,597, -19,19,19,19,19,341,1,893, -598,598,598,598,1,342,1,598, -19,19,19,19,19,343,1,891, -599,599,599,599,1,344,1,599, -157,157,600,157,157,157,157,157,157,157,157,157,157,157,157,155,157,157,157, - 157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, - 157,157,157,157,157,345, -19,19,19,19,19,346,1,888, -601,601,601,601,1,347,1,601, -602,602,602,602,1,348,1,602, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,349,1,886, -132,132,132,132,132,132,132,132,132,132,132,132,156,132,132,132,132,132,138, - 132,132,350,606,270,605,345,604,271,346,603, + 19,19,19,19,19,19,19,19,19,19,19,19,19,316,1,974, +549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549, + 549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549, + 549,549,549,549,549,1,317,1,549, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, + 126,125,318,230,286,287,231,282,232,283,261,216,317,303,259,214,215,214, + 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, + 126,125,319,230,286,287,231,282,232,283,261,216,317,303,259,213,215,213, + 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, + 126,125,320,230,286,287,231,282,232,283,261,216,317,303,259,212,215,212, + 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, + 126,125,321,230,286,287,231,282,232,283,261,216,317,303,259,211,215,211, + 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,1,322,1,204, +19,551,553,382,374,378,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,1,323,1,201,557,556,555,554,552, +19,375,377,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,1,324,1,196,559,558, +19,560,562,564,566,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,1,325,1,193,567,565,563,561, +19,568,381,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,1,326,1,190,570,569, +19,571,353,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1, + 327,1,187,573,572, +574,351,186,576,575, +577,578,579,580,581,582,583,584,585,586,587,588,589,166,166,166,166,166,329, + 170,170,170,170,173,173,173,176,176,176,179,179,179,182,182,182,185,185, + 185, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,330,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,165,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +590,590,590,590,1,331,1,590, +591,591,591,591,1,332,1,591, +592,592,592,592,592,333,592, +19,19,19,19,19,334,1,895, +593,593,593,593,1,335,1,593, +19,19,19,19,19,336,1,894, +594,594,594,594,1,337,1,594, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,338,1,893, +595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,1,339,1,595, +19,19,19,19,19,340,1,891, +596,596,596,596,1,341,1,596, +19,19,19,19,19,342,1,889, +597,597,597,597,1,343,1,597, +155,155,598,155,155,155,155,155,155,155,155,155,155,155,155,153,155,155,155, + 155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, + 155,155,155,155,155,344, +19,19,19,19,19,345,1,886, +599,599,599,599,1,346,1,599, +600,600,600,600,1,347,1,600, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,348,1,884, +130,130,130,130,130,130,130,130,130,130,130,130,154,130,130,130,130,130,136, + 130,130,349,604,269,603,344,602,270,345,601, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 351,1,1159, + 350,1,1156, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,352,1,960, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,351,1,957, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 353,1,1158, + 352,1,1155, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,354,1,962, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,353,1,959, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,355,1, - 1157, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,354,1, + 1154, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 356,1,1156, + 355,1,1153, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 357,1,1155, + 356,1,1152, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 358,1,1154, + 357,1,1151, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 359,1,1153, + 358,1,1150, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 360,1,1152, + 359,1,1149, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 361,1,1151, + 360,1,1148, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 362,1,1150, + 361,1,1147, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 363,1,1149, + 362,1,1146, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 364,1,1148, + 363,1,1145, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 365,1,1147, + 364,1,1144, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 366,1,1146, + 365,1,1143, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 367,1,1145, + 366,1,1142, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 368,1,1144, + 367,1,1141, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 369,1,1143, + 368,1,1140, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 370,1,1142, + 369,1,1139, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 371,1,1141, + 370,1,1138, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 372,1,1140, + 371,1,1137, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 373,1,1139, + 372,1,1136, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 374,1,1138, + 373,1,1135, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,375,1,973, + 19,19,19,19,19,19,19,19,19,19,19,19,19,374,1,970, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,376,1,971, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,375,1,968, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,377,1,932, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,376,1,929, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,378,1,970, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,377,1,967, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,379,1,972, + 19,19,19,19,19,19,19,19,19,19,19,19,19,378,1,969, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 380,1,907, + 379,1,905, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 381,1,1137, + 380,1,1134, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,382,1,964, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,381,1,961, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,383,1,974, + 19,19,19,19,19,19,19,19,19,19,19,19,19,382,1,971, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 384,1,1136, + 383,1,1133, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,385,1, - 1135, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,384,1, + 1132, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 386,1,1134, + 385,1,1131, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 387,1,1133, + 386,1,1130, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,388,1,879, -351,353,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371, - 372,373,374,381,384,385,386,387,315,317,383,375,379,376,378,382,354,352, - 377,302,380,35,38,7,9,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 19,19,19,19,19,19,19,387,1,877, +350,352,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370, + 371,372,373,380,383,384,385,386,314,316,382,374,378,375,377,381,353,351, + 376,301,379,35,38,7,9,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, -34,390,11, -34,391,10, -290,480,482,484,485,486,488,489,490,492,494,496,498,500,502,504,506,508,510, - 511,513,514,515,517,518,520,521,522,523,526,527,335,337,339,341,343,607, - 609,392,610,608,70,71,525,72,74,65,66,524,524,524,524,79,519,519,519, - 516,516,516,516,512,512,512,509,507,505,503,501,499,497,495,493,491,105, - 106,487,109,110,483,481,115, -611,611,611,611,1,393,1,611, -612,290,37,38,39,34,394,613,67,67,42,67,41,40,40,165,166, -303,614,615,616,305,304,305,304,303,395,303,304,305,308,395,306,307, -285,284,284,281,280,279,278,277,276,396,393,284,617, -288,295,294,291,294,291,288,397,391,288,291,294,618, -397,397,397,397,398,397, -377,399,619, -377,400,620, -377,401,621, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,402,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,465,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,403,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,464,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,404,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,463,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,405,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,462,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,406,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,461,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,407,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,460,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,408,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,459,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,409,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,458,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,410,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,457,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,411,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,456,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,412,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,455,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,413,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,454,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,414,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,453,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,415,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,452,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,416,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,451,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,417,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,450,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,418,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,449,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,419,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,448,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,420,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,447,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,421,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,446,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,422,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,445,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,423,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,444,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,424,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,443,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,425,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,442,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,426,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,441,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,427,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,437,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,428,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,433,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,429,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,432,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,430,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,431,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,431,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,430,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,432,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,429,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,433,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,428,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,434,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,427,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,435,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,421,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,436,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,420,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,437,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,419,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,438,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,418,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,439,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,412,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,440,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,411,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,441,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,410,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,442,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,409,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,443,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,408,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,444,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,407,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,445,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,406,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,446,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,405,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,447,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,404,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,448,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,403,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,449,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,402,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,450,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,401,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,451,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,400,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,452,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,399,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,453,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,398,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -296,622,623,298,297,298,297,296,454,300,296,297,298,374,299, -296,622,623,298,297,298,297,296,455,300,296,297,298,373,299, -296,622,623,298,297,298,297,296,456,300,296,297,298,372,299, -296,622,623,298,297,298,297,296,457,300,296,297,298,371,299, -301,302,302,301,458,301,302,370, -301,302,302,301,459,301,302,369, -288,295,294,291,294,291,288,460,390,288,291,294,618, -288,295,294,291,294,291,288,461,389,288,291,294,618, -288,295,294,291,294,291,288,462,388,288,291,294,618, -303,614,615,616,305,304,305,304,303,463,303,304,305,308,387,306,307, -303,614,615,616,305,304,305,304,303,464,303,304,305,308,386,306,307, -285,284,284,281,280,279,278,277,276,465,385,284,617, -285,284,284,281,280,279,278,277,276,466,384,284,617, -285,284,284,281,280,279,278,277,276,467,383,284,617, -285,284,284,281,280,279,278,277,276,468,382,284,617, -285,284,284,281,280,279,278,277,276,469,624,284,617, -285,284,284,281,280,279,278,277,276,470,380,284,617, -285,284,284,281,280,279,278,277,276,471,379,284,617, -285,284,284,281,280,279,278,277,276,472,378,284,617, -285,284,284,281,280,279,278,277,276,473,377,284,617, -285,284,284,281,280,279,278,277,276,474,376,284,617, -285,284,284,281,280,279,278,277,276,475,375,284,617, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,625, - 279,138,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281, - 290,302,276,263,128,127,476,232,287,288,233,283,117,270,234,284,626,118, - 261,327,326,324,329,325,328,323,119,318,218,628,304,259,319,323,322,321, - 320,217,323,313,312,311,310,309,308,307,306,305,303,286,285,271,259,627, - 301,300, -277,248,248,248,248,280,282,629,278,552,281,263,18,477,116,287,630,234,284, - 286,285,301, +34,389,11, +34,390,10, +289,479,481,483,484,485,487,488,489,491,493,495,497,499,501,503,505,507,509, + 510,512,513,514,516,517,519,520,521,522,525,526,334,336,338,340,342,605, + 607,391,608,606,68,69,524,70,72,63,64,523,523,523,523,77,518,518,518, + 515,515,515,515,511,511,511,508,506,504,502,500,498,496,494,492,490,103, + 104,486,107,108,482,480,113, +609,609,609,609,1,392,1,609, +610,289,37,38,39,34,393,611,65,65,42,65,41,40,40,163,164, +301,612,613,614,303,302,303,302,301,394,301,302,303,306,393,304,305, +283,282,282,279,278,277,276,275,274,395,391,282,615, +286,293,292,289,292,289,286,396,389,286,289,292,616, +395,395,395,395,397,395, +376,398,617, +376,399,618, +376,400,619, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,401,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,463,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,402,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,462,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,403,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,461,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,404,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,460,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,405,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,459,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,406,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,458,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,407,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,457,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,408,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,456,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,409,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,455,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,410,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,454,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,411,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,453,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,412,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,452,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,413,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,451,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,414,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,450,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,415,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,449,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,416,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,448,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,417,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,447,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,418,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,446,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,419,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,445,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,420,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,444,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,421,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,443,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,422,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,442,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,423,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,441,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,424,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,440,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,425,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,439,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,426,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,435,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,427,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,431,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,428,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,430,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,429,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,429,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,430,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,428,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,431,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,427,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,432,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,426,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,433,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,425,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,434,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,419,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,435,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,418,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,436,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,417,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,437,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,416,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,438,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,410,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,439,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,409,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,440,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,408,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,441,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,407,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,442,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,406,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,443,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,405,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,444,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,404,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,445,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,403,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,446,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,402,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,447,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,401,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,448,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,400,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,449,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,399,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,450,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,398,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,451,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,397,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,452,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,396,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +294,620,621,296,295,296,295,294,453,298,294,295,296,372,297, +294,620,621,296,295,296,295,294,454,298,294,295,296,371,297, +294,620,621,296,295,296,295,294,455,298,294,295,296,370,297, +294,620,621,296,295,296,295,294,456,298,294,295,296,369,297, +299,300,300,299,457,299,300,368, +299,300,300,299,458,299,300,367, +286,293,292,289,292,289,286,459,388,286,289,292,616, +286,293,292,289,292,289,286,460,387,286,289,292,616, +286,293,292,289,292,289,286,461,386,286,289,292,616, +301,612,613,614,303,302,303,302,301,462,301,302,303,306,385,304,305, +301,612,613,614,303,302,303,302,301,463,301,302,303,306,384,304,305, +283,282,282,279,278,277,276,275,274,464,383,282,615, +283,282,282,279,278,277,276,275,274,465,382,282,615, +283,282,282,279,278,277,276,275,274,466,381,282,615, +283,282,282,279,278,277,276,275,274,467,380,282,615, +283,282,282,279,278,277,276,275,274,468,622,282,615, +283,282,282,279,278,277,276,275,274,469,378,282,615, +283,282,282,279,278,277,276,275,274,470,377,282,615, +283,282,282,279,278,277,276,275,274,471,376,282,615, +283,282,282,279,278,277,276,275,274,472,375,282,615, +283,282,282,279,278,277,276,275,274,473,374,282,615, +283,282,282,279,278,277,276,275,274,474,373,282,615, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,623, + 278,136,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280, + 289,301,275,261,126,125,475,230,286,287,231,282,115,269,232,283,624,116, + 261,326,325,323,328,324,327,322,117,216,317,626,303,259,318,322,321,320, + 319,215,322,312,311,310,309,308,307,306,305,304,302,285,284,270,259,625, + 300,299, +276,246,246,246,246,279,281,627,277,550,280,261,18,476,114,286,628,232,283, + 285,284,300, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,478,1,997, -631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, - 631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, - 631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, - 631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, - 631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, - 631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, - 631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, - 631,631,631,631,631,631,1,479,1,631, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,480,1,942, -129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,481,112,259,259, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,482,1,941, -132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, - 483,111,603, -19,19,19,19,19,484,1,940, -19,19,19,19,19,485,1,939, -19,19,1,486,1,938, -632,138,487,108,270,626,107,271,627, -19,19,19,19,19,488,1,936, -19,19,19,19,19,489,1,935, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,490,1,934, -129,129,129,129,129,129,129,129,129,129,129,129,129,100,100,100,100,128,127, - 100,491,101,259,259, -19,1,492,1,933, -138,493,633,270,271, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,494,1,931, -634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634, - 634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634, - 634,634,634,634,634,634,1,495,1,634, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,496,1,930, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,138,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281, - 290,302,276,263,128,127,497,232,287,288,233,283,97,270,234,284,261,327, - 326,324,329,325,328,323,96,318,218,304,259,319,323,322,321,320,217,323, - 313,312,311,310,309,308,307,306,305,303,286,285,271,259,301,300, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,498,1,929, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,499,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,95,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,500,1,928, -129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,501,94,259,259, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,502,1,927, -129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,503,93,259,259, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,504,1,926, -129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,505,123,635,259, + 19,19,19,19,19,19,19,19,19,19,19,19,19,477,1,994, +629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, + 629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, + 629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, + 629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, + 629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, + 629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, + 629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, + 629,629,629,629,629,629,1,478,1,629, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,479,1,939, +127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,480,110,259,259, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,481,1,938, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, + 482,109,601, +19,19,19,19,19,483,1,937, +19,19,19,19,19,484,1,936, +19,19,1,485,1,935, +630,136,486,106,269,624,105,270,625, +19,19,19,19,19,487,1,933, +19,19,19,19,19,488,1,932, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,489,1,931, +127,127,127,127,127,127,127,127,127,127,127,127,127,98,98,98,98,126,125,98, + 490,99,259,259, +19,1,491,1,930, +136,492,631,269,270, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,493,1,928, +632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632, + 632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632, + 632,632,632,632,632,632,1,494,1,632, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,495,1,927, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,136,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280, + 289,301,275,261,126,125,496,230,286,287,231,282,95,269,232,283,261,326, + 325,323,328,324,327,322,94,216,317,303,259,318,322,321,320,319,215,322, + 312,311,310,309,308,307,306,305,304,302,285,284,270,259,300,299, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,497,1,926, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,498,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,93,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,499,1,925, +127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,500,92,259,259, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,501,1,924, +127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,502,91,259,259, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,503,1,923, +127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,504,121,633,259, 259, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,506,1,925, -129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,507,123,636,259, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,505,1,922, +127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,506,121,634,259, 259, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,508,1,924, -129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,509,123,637,259, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,507,1,921, +127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,508,121,635,259, 259, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,510,1,923, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,511,1,922, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,625, - 279,138,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281, - 290,302,276,263,128,127,512,232,287,288,233,283,117,270,234,284,626,118, - 261,327,326,324,329,325,328,323,119,318,218,638,304,259,319,323,322,321, - 320,217,323,313,312,311,310,309,308,307,306,305,303,286,285,271,259,627, - 301,300, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,513,1,921, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,514,1,920, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,515,1,919, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,625, - 279,138,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281, - 290,302,276,263,128,127,516,232,287,288,233,283,117,270,234,284,626,118, - 261,327,326,324,329,325,328,323,119,318,218,639,304,259,319,323,322,321, - 320,217,323,313,312,311,310,309,308,307,306,305,303,286,285,271,259,627, - 301,300, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,517,1,918, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,518,1,917, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,519,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,82,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -19,19,19,19,19,520,1,916, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,521,1,915, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,522,1,914, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,523,1,913, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,524,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,78,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,525,73,259,259, -19,19,19,19,19,19,19,526,1,912, -19,19,19,19,19,19,19,527,1,911, -37,38,39,34,528,21,21,42,21,41,40,40, -640,529,641, -351,353,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372, - 373,374,381,384,386,387,315,317,383,375,379,376,378,382,354,352,377,302, - 380,35,38,530,62,62,642,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62, - 62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62, -37,38,39,34,531,56,56,42,56,41,40,40, -142,643,144,145,143,149,148,644,644,645,643,147,140,532,643, -37,38,39,34,533,55,55,42,55,41,40,40, -37,38,39,34,534,52,52,42,52,41,40,40, -252,252,252,252,252,252,252,252,252,535, -265,267,268,266,269,271,536, -264,536,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, - 264,264,261,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, - 264,264,264,264,264,270,264,537,646, -255,255,255,255,255,255,255,255,255,255,245,245,245,245,245,245,245,245,245, - 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, - 245,245,245,245,245,245,245,245,245,245,245,538, -255,255,255,255,255,255,255,255,255,255,241,241,241,241,241,241,241,241,241, - 241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241, - 241,241,241,241,241,241,241,241,241,241,241,539, -302,540,647, -302,541,648, -302,542,649, -302,543,650, -302,544,651, -302,545,652, -302,546,653, -302,547,654, -302,548,655, -302,549,656, -302,550,657, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,551,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,658,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -247,247,247,247,247,552, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,553,1,976, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,509,1,920, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,510,1,919, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,623, + 278,136,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280, + 289,301,275,261,126,125,511,230,286,287,231,282,115,269,232,283,624,116, + 261,326,325,323,328,324,327,322,117,216,317,636,303,259,318,322,321,320, + 319,215,322,312,311,310,309,308,307,306,305,304,302,285,284,270,259,625, + 300,299, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,512,1,918, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,513,1,917, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,514,1,916, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,623, + 278,136,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280, + 289,301,275,261,126,125,515,230,286,287,231,282,115,269,232,283,624,116, + 261,326,325,323,328,324,327,322,117,216,317,637,303,259,318,322,321,320, + 319,215,322,312,311,310,309,308,307,306,305,304,302,285,284,270,259,625, + 300,299, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,516,1,915, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,517,1,914, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,518,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,80,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +19,19,19,19,19,519,1,913, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,520,1,912, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,521,1,911, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,522,1,910, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,523,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,76,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,524,71,259,259, +19,19,19,19,19,19,19,525,1,909, +19,19,19,19,19,19,19,526,1,908, +37,38,39,34,527,21,21,42,21,41,40,40, +350,352,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371, + 372,373,380,383,385,386,314,316,382,374,378,375,377,381,353,351,376,301, + 379,35,38,528,60,60,638,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60, + 60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60, +37,38,39,34,529,56,56,42,56,41,40,40, +140,639,142,143,141,147,146,640,640,641,639,145,138,530,639, +37,38,39,34,531,55,55,42,55,41,40,40, +37,38,39,34,532,52,52,42,52,41,40,40, +250,250,250,250,250,250,250,250,250,533, +263,265,266,264,267,269,534, +262,534,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, + 262,262,259,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, + 262,262,262,262,262,268,262,535,642, +253,253,253,253,253,253,253,253,253,253,243,243,243,243,243,243,243,243,243, + 243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, + 243,243,243,243,243,243,243,243,243,243,243,536, +253,253,253,253,253,253,253,253,253,253,239,239,239,239,239,239,239,239,239, + 239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, + 239,239,239,239,239,239,239,239,239,239,239,537, +301,538,643, +301,539,644, +301,540,645, +301,541,646, +301,542,647, +301,543,648, +301,544,649, +301,545,650, +301,546,651, +301,547,652, +301,548,653, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,549,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,654,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +245,245,245,245,245,550, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,551,1,973, +655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655, + 655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655, + 655,655,1,552,1,655, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,553,1,972, +656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656, + 656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656, + 656,656,1,554,1,656, +657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657, + 657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657, + 657,657,1,555,1,657, +658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658, + 658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658, + 658,658,1,556,1,658, 659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659, 659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659, - 659,659,1,554,1,659, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,555,1,975, + 659,659,1,557,1,659, 660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660, 660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660, - 660,660,1,556,1,660, + 660,660,660,660,660,1,558,1,660, 661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661, 661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661, - 661,661,1,557,1,661, + 661,661,661,661,661,1,559,1,661, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,560,1,966, 662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662, 662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662, - 662,662,1,558,1,662, + 662,662,662,662,662,1,561,1,662, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,562,1,965, 663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663, 663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663, - 663,663,1,559,1,663, + 663,663,663,663,663,1,563,1,663, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,564,1,964, 664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664, 664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664, - 664,664,664,664,664,1,560,1,664, + 664,664,664,664,664,1,565,1,664, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,566,1,963, 665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665, 665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665, - 665,665,665,665,665,1,561,1,665, + 665,665,665,665,665,1,567,1,665, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,562,1,969, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,568,1,962, 666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666, 666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666, - 666,666,666,666,666,1,563,1,666, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,564,1,968, + 666,666,666,666,666,1,569,1,666, 667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667, 667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667, - 667,667,667,667,667,1,565,1,667, + 667,667,667,667,667,1,570,1,667, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,566,1,967, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,571,1,960, 668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668, 668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668, - 668,668,668,668,668,1,567,1,668, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,568,1,966, + 668,668,668,668,668,1,572,1,668, 669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669, 669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669, - 669,669,669,669,669,1,569,1,669, + 669,669,669,669,669,1,573,1,669, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,570,1,965, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,574,1,958, 670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, 670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, - 670,670,670,670,670,1,571,1,670, + 670,670,670,670,670,1,575,1,670, 671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, 671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, - 671,671,671,671,671,1,572,1,671, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,573,1,963, -672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, - 672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, - 672,672,672,672,672,1,574,1,672, -673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, - 673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, - 673,673,673,673,673,1,575,1,673, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,576,1,961, -674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674, - 674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674, - 674,674,674,674,674,1,577,1,674, -675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675, - 675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675, - 675,675,675,675,675,1,578,1,675, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,579,1,959, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,580,1,958, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,581,1,957, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,582,1,956, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,583,1,955, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,584,1,954, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,585,1,953, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,586,1,952, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,587,1,951, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,588,1,950, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,589,1,949, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,590,1,948, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,591,1,947, -37,38,39,34,592,51,51,42,51,41,40,40, -37,38,39,34,593,50,50,42,50,41,40,40, -37,38,39,34,594,49,49,42,49,41,40,40, -37,38,39,34,595,46,46,42,46,41,40,40, -37,38,39,34,596,45,45,42,45,41,40,40, -129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,597,676,259,259, -37,38,39,34,598,43,43,42,43,41,40,40, -37,38,39,34,599,42,42,42,42,41,40,40, -158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, - 158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, - 158,158,158,158,158,159,158,600, -37,38,39,34,601,41,41,42,41,41,40,40, -37,38,39,34,602,40,40,42,40,41,40,40, -133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, - 19,19,19,603,1,889, -677,677,677,677,1,604,1,677, -678,678,678,678,1,605,1,678, -679,679,679,679,1,606,1,679, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,607,1,884, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,608,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,680,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,609,1,883, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,610,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,681,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -37,38,39,34,611,22,22,42,22,41,40,40, -19,19,19,19,19,612,1,946, -682,682,682,682,1,613,1,682, -19,19,19,19,19,19,19,614,1,996, -19,19,19,19,19,19,19,615,1,995, -19,19,19,19,19,19,19,616,1,994, -19,19,19,19,19,19,19,19,617,1,1047, -19,19,19,19,19,19,19,618,1,1061, -683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683, - 683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683, - 683,683,683,683,683,1,619,1,683, -684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684, - 684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684, - 684,684,684,684,684,1,620,1,684, -685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685, - 685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685, - 685,685,685,685,685,1,621,1,685, -19,19,19,19,19,19,622,1,993, -19,19,19,19,19,19,623,1,992, -686,1,624,1,686, -264,536,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, - 264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, - 264,264,264,264,270,264,625,687, -264,536,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, - 264,264,134,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, - 264,264,264,264,264,270,264,626,136, -19,19,19,19,19,19,19,627,1,937, -688,380,628,60,689, -253,253,253,253,253,253,253,253,253,629, -250,240,255,538,539,255,249,249,249,249,249,251,235,235,235,235,244,244,235, - 630,244, + 671,671,671,671,671,1,576,1,671, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,577,1,956, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,578,1,955, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,579,1,954, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,580,1,953, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,581,1,952, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,582,1,951, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,583,1,950, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,584,1,949, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,585,1,948, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,586,1,947, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,587,1,946, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,588,1,945, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,589,1,944, +37,38,39,34,590,51,51,42,51,41,40,40, +37,38,39,34,591,50,50,42,50,41,40,40, +37,38,39,34,592,49,49,42,49,41,40,40, +37,38,39,34,593,46,46,42,46,41,40,40, +37,38,39,34,594,45,45,42,45,41,40,40, +127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,595,672,259,259, +37,38,39,34,596,43,43,42,43,41,40,40, +37,38,39,34,597,42,42,42,42,41,40,40, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, + 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, + 156,156,156,156,156,157,156,598, +37,38,39,34,599,41,41,42,41,41,40,40, +37,38,39,34,600,40,40,42,40,41,40,40, +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, + 19,19,19,601,1,887, +673,673,673,673,1,602,1,673, +674,674,674,674,1,603,1,674, +675,675,675,675,1,604,1,675, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,605,1,882, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,606,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,676,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,607,1,881, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,608,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,677,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +37,38,39,34,609,22,22,42,22,41,40,40, +19,19,19,19,19,610,1,943, +678,678,678,678,1,611,1,678, +19,19,19,19,19,19,19,612,1,993, +19,19,19,19,19,19,19,613,1,992, +19,19,19,19,19,19,19,614,1,991, +19,19,19,19,19,19,19,19,615,1,1044, +19,19,19,19,19,19,19,616,1,1058, +679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, + 679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, + 679,679,679,679,679,1,617,1,679, +680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680, + 680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680, + 680,680,680,680,680,1,618,1,680, +681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681, + 681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681, + 681,681,681,681,681,1,619,1,681, +19,19,19,19,19,19,620,1,990, +19,19,19,19,19,19,621,1,989, +682,1,622,1,682, +262,534,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, + 262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, + 262,262,262,262,268,262,623,683, +262,534,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, + 262,262,132,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, + 262,262,262,262,262,268,262,624,134, +19,19,19,19,19,19,19,625,1,934, +684,379,626,58,685, +251,251,251,251,251,251,251,251,251,627, +248,238,253,536,537,253,247,247,247,247,247,249,233,233,233,233,242,242,233, + 628,242, 111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129, 130,131,132,133,134,62,63,64,65,66,67,135,136,137,138,139,140,68,69,70, 71,72,141,142,143,73,74,75,76,77,144,145,146,147,148,149,150,151,152, 153,154,155,156,157,158,107,59,60,61,165,166,167,168,169,170,171,172, 173,174,175,176,177,178,179,180,159,160,161,162,163,164,78,79,80,81,82, 83,45,46,47,84,85,86,87,88,89,90,91,92,48,49,93,94,95,96,97,98,99,100, - 50,51,52,101,102,53,54,103,104,105,106,55,56,57,58,631,690,691,196,691, - 691,691,691,691,691,691,691,691,691,325,325,325,325,325,326,327,328,329, - 332,332,332,333,334,338,338,338,338,339,340,341,342,343,344,345,346,349, - 349,349,350,351,352,353,354,355,356,357,358,362,362,362,362,363,364,365, - 366,367,368,242,241,240,239,238,237,258,257,256,255,254,253,252,251,250, + 50,51,52,101,102,53,54,103,104,105,106,55,56,57,58,629,686,687,196,687, + 687,687,687,687,687,687,687,687,687,323,323,323,323,323,324,325,326,327, + 330,330,330,331,332,336,336,336,336,337,338,339,340,341,342,343,344,347, + 347,347,348,349,350,351,352,353,354,355,356,360,360,360,360,361,362,363, + 364,365,366,242,241,240,239,238,237,258,257,256,255,254,253,252,251,250, 249,248,247,246,245,244,243,184,110,183,109,182,108,181,236,235,234,233, 232,231,230,229,228,227,226,225,224,223,222,221,221,221,221,221,221,220, 219,218,217,217,217,217,217,217,216,215,214,213,212,211,210,210,210,210, 209,209,209,209,208,207,206,205,204,203,202,201,200,199,198,197,195,194, 193,192,191,190,189,188,187,186,185, -264,536,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, - 264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, - 264,264,264,264,270,264,632,692, -377,633,693, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,625, - 279,138,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281, - 290,302,276,263,128,127,634,232,287,288,233,283,117,270,234,284,626,118, - 261,327,326,324,329,325,328,323,119,318,218,694,304,259,319,323,322,321, - 320,217,323,313,312,311,310,309,308,307,306,305,303,286,285,271,259,627, - 301,300, -688,92,92,92,92,92,635,695, -688,91,91,91,91,91,636,695, -688,90,90,90,90,90,637,695, -688,89,89,89,89,89,638,689, -688,86,86,86,86,86,639,689, -19,1,640,1,908, -380,641,58, -351,353,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372, - 373,374,381,384,386,387,315,317,383,375,379,376,378,382,354,352,377,696, - 302,380,35,38,698,697,642,63,1,698,63,63,63,64,63,63,63,63,63,63,63,63, - 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, - 63,63,63,63, -699,699,699,699,699,699,699,699,699,643, -700,700,700,700,700,644, -146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,700,700,700, - 700,700,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, - 146,146,146,146,146,146,645, -262,646, -701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,1,647,1,701, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,648,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,702,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,649,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,703,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,650,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,704,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,651,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,705,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,652,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,706,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,653,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,707,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,654,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,708,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,655,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,709,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,656,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,710,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,657,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,711,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -712,1,658,1,712, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, - 128,127,659,232,287,288,233,283,234,284,261,318,218,304,259,211,217,211, - 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, - 128,127,660,232,287,288,233,283,234,284,261,318,218,304,259,210,217,210, - 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, - 128,127,661,232,287,288,233,283,234,284,261,318,218,304,259,209,217,209, - 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, - 128,127,662,232,287,288,233,283,234,284,261,318,218,304,259,208,217,208, - 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,278,552,281,290,302,276,263, - 128,127,663,232,287,288,233,283,234,284,261,318,218,304,259,207,217,207, - 313,312,311,310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,664,232,287,288,233,283,234,284,261,713,323,318,218, - 304,259,319,323,322,321,320,217,323,313,312,311,310,309,308,307,306,305, - 303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,665,232,287,288,233,283,234,284,261,714,323,318,218, - 304,259,319,323,322,321,320,217,323,313,312,311,310,309,308,307,306,305, - 303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,666,232,287,288,233,283,234,284,261,324,715,323,318, - 218,304,259,319,323,322,321,320,217,323,313,312,311,310,309,308,307,306, - 305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,667,232,287,288,233,283,234,284,261,324,716,323,318, - 218,304,259,319,323,322,321,320,217,323,313,312,311,310,309,308,307,306, - 305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,668,232,287,288,233,283,234,284,261,324,717,323,318, - 218,304,259,319,323,322,321,320,217,323,313,312,311,310,309,308,307,306, - 305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,669,232,287,288,233,283,234,284,261,324,718,323,318, - 218,304,259,319,323,322,321,320,217,323,313,312,311,310,309,308,307,306, - 305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,670,232,287,288,233,283,234,284,261,719,324,325,323, - 318,218,304,259,319,323,322,321,320,217,323,313,312,311,310,309,308,307, - 306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,671,232,287,288,233,283,234,284,261,720,324,325,323, - 318,218,304,259,319,323,322,321,320,217,323,313,312,311,310,309,308,307, - 306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,672,232,287,288,233,283,234,284,261,721,326,324,325, - 323,318,218,304,259,319,323,322,321,320,217,323,313,312,311,310,309,308, - 307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,673,232,287,288,233,283,234,284,261,722,326,324,325, - 323,318,218,304,259,319,323,322,321,320,217,323,313,312,311,310,309,308, - 307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,674,232,287,288,233,283,234,284,261,327,326,324,325, - 723,323,318,218,304,259,319,323,322,321,320,217,323,313,312,311,310,309, - 308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,675,232,287,288,233,283,234,284,261,327,326,324,325, - 724,323,318,218,304,259,319,323,322,321,320,217,323,313,312,311,310,309, - 308,307,306,305,303,286,285,259,301,300, -725,725,725,725,1,676,1,725, -37,38,39,34,677,34,34,42,34,41,40,40, -37,38,39,34,678,33,33,42,33,41,40,40, -37,38,39,34,679,32,32,42,32,41,40,40, -726,726,726,726,1,680,1,726, -727,727,727,727,1,681,1,727, -37,38,39,34,682,68,68,42,68,41,40,40, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,683,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,396,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,684,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,394,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,685,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,392,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -688,686,728, -264,536,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, - 264,264,261,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, - 264,264,264,264,264,270,264,687,729, +262,534,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, + 262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, + 262,262,262,262,268,262,630,688, +376,631,689, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,623, + 278,136,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280, + 289,301,275,261,126,125,632,230,286,287,231,282,115,269,232,283,624,116, + 261,326,325,323,328,324,327,322,117,216,317,690,303,259,318,322,321,320, + 319,215,322,312,311,310,309,308,307,306,305,304,302,285,284,270,259,625, + 300,299, +684,90,90,90,90,90,633,691, +684,89,89,89,89,89,634,691, +684,88,88,88,88,88,635,691, +684,87,87,87,87,87,636,685, +684,84,84,84,84,84,637,685, +350,352,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371, + 372,373,380,383,385,386,314,316,382,374,378,375,377,381,353,351,376,692, + 301,379,35,38,694,693,638,61,1,694,61,61,61,62,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61, +695,695,695,695,695,695,695,695,695,639, +696,696,696,696,696,640, +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,696,696,696, + 696,696,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, + 144,144,144,144,144,144,641, +260,642, +697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,1,643,1,697, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,644,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,698,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,645,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,699,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,646,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,700,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,647,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,701,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,648,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,702,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,649,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,703,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,650,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,704,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,651,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,705,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,652,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,706,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,653,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,707,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +708,1,654,1,708, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, + 126,125,655,230,286,287,231,282,232,283,261,216,317,303,259,209,215,209, + 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, + 126,125,656,230,286,287,231,282,232,283,261,216,317,303,259,208,215,208, + 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, + 126,125,657,230,286,287,231,282,232,283,261,216,317,303,259,207,215,207, + 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, + 126,125,658,230,286,287,231,282,232,283,261,216,317,303,259,206,215,206, + 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, + 126,125,659,230,286,287,231,282,232,283,261,216,317,303,259,205,215,205, + 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,660,230,286,287,231,282,232,283,261,709,322,216,317, + 303,259,318,322,321,320,319,215,322,312,311,310,309,308,307,306,305,304, + 302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,661,230,286,287,231,282,232,283,261,710,322,216,317, + 303,259,318,322,321,320,319,215,322,312,311,310,309,308,307,306,305,304, + 302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,662,230,286,287,231,282,232,283,261,323,711,322,216, + 317,303,259,318,322,321,320,319,215,322,312,311,310,309,308,307,306,305, + 304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,663,230,286,287,231,282,232,283,261,323,712,322,216, + 317,303,259,318,322,321,320,319,215,322,312,311,310,309,308,307,306,305, + 304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,664,230,286,287,231,282,232,283,261,323,713,322,216, + 317,303,259,318,322,321,320,319,215,322,312,311,310,309,308,307,306,305, + 304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,665,230,286,287,231,282,232,283,261,323,714,322,216, + 317,303,259,318,322,321,320,319,215,322,312,311,310,309,308,307,306,305, + 304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,666,230,286,287,231,282,232,283,261,715,323,324,322, + 216,317,303,259,318,322,321,320,319,215,322,312,311,310,309,308,307,306, + 305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,667,230,286,287,231,282,232,283,261,716,323,324,322, + 216,317,303,259,318,322,321,320,319,215,322,312,311,310,309,308,307,306, + 305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,668,230,286,287,231,282,232,283,261,717,325,323,324, + 322,216,317,303,259,318,322,321,320,319,215,322,312,311,310,309,308,307, + 306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,669,230,286,287,231,282,232,283,261,718,325,323,324, + 322,216,317,303,259,318,322,321,320,319,215,322,312,311,310,309,308,307, + 306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,670,230,286,287,231,282,232,283,261,326,325,323,324, + 719,322,216,317,303,259,318,322,321,320,319,215,322,312,311,310,309,308, + 307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,671,230,286,287,231,282,232,283,261,326,325,323,324, + 720,322,216,317,303,259,318,322,321,320,319,215,322,312,311,310,309,308, + 307,306,305,304,302,285,284,259,300,299, +721,721,721,721,1,672,1,721, +37,38,39,34,673,34,34,42,34,41,40,40, +37,38,39,34,674,33,33,42,33,41,40,40, +37,38,39,34,675,32,32,42,32,41,40,40, +722,722,722,722,1,676,1,722, +723,723,723,723,1,677,1,723, +37,38,39,34,678,66,66,42,66,41,40,40, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,679,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,394,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,680,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,392,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,681,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,390,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +684,682,724, +262,534,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, + 262,262,259,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, + 262,262,262,262,262,268,262,683,725, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,688,1,945, -730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730, - 730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730, - 730,730,730,730,730,730,1,689,1,730, -478,690,479, -19,320,320,320,320,1,691,1,309, -264,536,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, - 264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, - 264,264,264,264,270,264,692,135, -731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731, - 731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731, - 731,731,731,731,731,1,693,1,731, -688,98,98,98,98,98,694,689, -732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,1,695,1,732, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,696,1,910, -63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, - 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,17,17,17,17,17,697, -37,38,39,34,698,57,57,42,57,41,40,40, -154,154,154,154,154,154,154,154,153,153,153,153,154,154,154,154,153,153,153, - 153,153,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, - 154,154,154,154,154,154,699, -150,150,150,150,150,700, -129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,701,735,733,733, - 734, -380,702,230, -380,703,229, -380,704,228, -380,705,227, -380,706,226, -380,707,225, -380,708,224, -380,709,223, -380,710,222, -380,711,221, -380,712,220, -205,553,555,383,375,379,205,205,205,205,205,205,205,205,205,205,205,205,205, - 205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,713, - 559,558,557,556,554, -204,553,555,383,375,379,204,204,204,204,204,204,204,204,204,204,204,204,204, - 204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,714, - 559,558,557,556,554, -202,376,378,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, - 202,202,202,202,202,202,202,202,202,202,202,202,202,202,715,561,560, -201,376,378,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, - 201,201,201,201,201,201,201,201,201,201,201,201,201,201,716,561,560, -200,376,378,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, - 200,200,200,200,200,200,200,200,200,200,200,200,200,200,717,561,560, -199,376,378,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, - 199,199,199,199,199,199,199,199,199,199,199,199,199,199,718,561,560, -197,562,564,566,568,197,197,197,197,197,197,197,197,197,197,197,197,197,197, - 197,197,197,197,197,197,197,197,197,197,197,197,719,569,567,565,563, -196,562,564,566,568,196,196,196,196,196,196,196,196,196,196,196,196,196,196, - 196,196,196,196,196,196,196,196,196,196,196,196,720,569,567,565,563, -194,570,382,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, - 194,194,194,194,194,194,194,194,721,572,571, -193,570,382,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, - 193,193,193,193,193,193,193,193,722,572,571, -191,573,354,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, - 191,191,191,191,191,191,723,575,574, -190,573,354,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, - 190,190,190,190,190,190,724,575,574, -37,38,39,34,725,44,44,42,44,41,40,40, -37,38,39,34,726,29,29,42,29,41,40,40, -37,38,39,34,727,28,28,42,28,41,40,40, -736,736,736,736,736,736,736,736,736,1,728,1,736, -135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, - 135,135,262,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, - 135,135,135,135,135,135,135,729, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,625, - 279,138,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281, - 290,302,276,263,128,127,730,232,287,288,233,283,121,270,234,284,626,122, - 261,327,326,324,329,325,328,323,120,318,218,304,259,319,323,322,321,320, - 217,323,313,312,311,310,309,308,307,306,305,303,286,285,271,259,627,301, - 300, -129,129,129,129,129,129,129,129,129,129,129,277,129,248,248,248,248,280,282, - 279,289,291,292,293,294,295,296,297,298,299,315,316,317,278,314,281,290, - 302,276,263,128,127,731,232,287,288,233,283,234,284,261,327,326,324,329, - 325,328,323,99,318,218,304,259,319,323,322,321,320,217,323,313,312,311, - 310,309,308,307,306,305,303,286,285,259,301,300, -129,129,129,129,129,129,129,129,129,129,129,129,129,128,127,732,124,259,259, -130,130,130,130,130,130,130,130,130,130,130,130,131,131,131,131,131,130,19, - 130,1,733,1,125,131, -19,19,734,1,989, -737,1,735,1,737, -285,284,284,281,280,279,278,277,276,736,381,284,617, -380,737,231, + 19,19,19,19,684,1,942, +726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, + 726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, + 726,726,726,726,726,726,1,685,1,726, +477,686,478, +19,318,318,318,318,1,687,1,307, +262,534,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, + 262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, + 262,262,262,262,268,262,688,133, +727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727, + 727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727, + 727,727,727,727,727,1,689,1,727, +684,96,96,96,96,96,690,685, +728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,1,691,1,728, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,692,1,907, +61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,17,17,17,17,17,693, +37,38,39,34,694,57,57,42,57,41,40,40, +152,152,152,152,152,152,152,152,151,151,151,151,152,152,152,152,151,151,151, + 151,151,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, + 152,152,152,152,152,152,695, +148,148,148,148,148,696, +127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,697,731,729,729, + 730, +379,698,228, +379,699,227, +379,700,226, +379,701,225, +379,702,224, +379,703,223, +379,704,222, +379,705,221, +379,706,220, +379,707,219, +379,708,218, +203,551,553,382,374,378,203,203,203,203,203,203,203,203,203,203,203,203,203, + 203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,709, + 557,556,555,554,552, +202,551,553,382,374,378,202,202,202,202,202,202,202,202,202,202,202,202,202, + 202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,710, + 557,556,555,554,552, +200,375,377,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, + 200,200,200,200,200,200,200,200,200,200,200,200,200,200,711,559,558, +199,375,377,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, + 199,199,199,199,199,199,199,199,199,199,199,199,199,199,712,559,558, +198,375,377,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, + 198,198,198,198,198,198,198,198,198,198,198,198,198,198,713,559,558, +197,375,377,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, + 197,197,197,197,197,197,197,197,197,197,197,197,197,197,714,559,558, +195,560,562,564,566,195,195,195,195,195,195,195,195,195,195,195,195,195,195, + 195,195,195,195,195,195,195,195,195,195,195,195,715,567,565,563,561, +194,560,562,564,566,194,194,194,194,194,194,194,194,194,194,194,194,194,194, + 194,194,194,194,194,194,194,194,194,194,194,194,716,567,565,563,561, +192,568,381,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, + 192,192,192,192,192,192,192,192,717,570,569, +191,568,381,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, + 191,191,191,191,191,191,191,191,718,570,569, +189,571,353,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, + 189,189,189,189,189,189,719,573,572, +188,571,353,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, + 188,188,188,188,188,188,720,573,572, +37,38,39,34,721,44,44,42,44,41,40,40, +37,38,39,34,722,29,29,42,29,41,40,40, +37,38,39,34,723,28,28,42,28,41,40,40, +732,732,732,732,732,732,732,732,732,1,724,1,732, +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, + 133,133,260,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, + 133,133,133,133,133,133,133,725, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,623, + 278,136,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280, + 289,301,275,261,126,125,726,230,286,287,231,282,119,269,232,283,624,120, + 261,326,325,323,328,324,327,322,118,216,317,303,259,318,322,321,320,319, + 215,322,312,311,310,309,308,307,306,305,304,302,285,284,270,259,625,300, + 299, +127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, + 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, + 301,275,261,126,125,727,230,286,287,231,282,232,283,261,326,325,323,328, + 324,327,322,97,216,317,303,259,318,322,321,320,319,215,322,312,311,310, + 309,308,307,306,305,304,302,285,284,259,300,299, +127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,728,122,259,259, +128,128,128,128,128,128,128,128,128,128,128,128,129,129,129,129,129,128,19, + 128,1,729,1,123,129, +19,19,730,1,986, +733,1,731,1,733, +283,282,282,279,278,277,276,275,274,732,379,282,615, +379,733,229, }; @@ -6494,46 +6475,46 @@ static const unsigned short ag_sbt[] = { 7285,7331,7377,7423,7469,7515,7561,7607,7653,7699,7745,7791,7837,7883, 7929,7975,8021,8067,8113,8159,8205,8251,8297,8343,8389,8435,8481,8527, 8539,8551,8563,8575,8583,8591,8602,8613,8624,8637,8650,8663,8676,8689, - 8702,8715,8728,8741,8754,8767,8780,8793,8853,8862,8903,8910,8913,9000, - 9077,9085,9128,9172,9180,9225,9236,9244,9256,9268,9276,9282,9287,9290, - 9349,9404,9410,9455,9461,9472,9515,9556,9604,9657,9662,9671,9676,9681, - 9686,9691,9696,9701,9706,9711,9716,9757,9798,9865,9870,9875,9880,9885, - 9890,9895,9900,9905,9910,9915,9920,9963,10028,10071,10136,10182,10252, - 10322,10392,10462,10503,10547,10585,10623,10655,10685,10690,10728,10813, - 10821,10829,10836,10844,10852,10860,10868,10887,10906,10914,10922,10930, - 10938,10981,10989,10997,11005,11030,11060,11111,11177,11228,11294,11343, - 11394,11445,11496,11547,11598,11649,11700,11751,11802,11853,11904,11955, - 12006,12057,12108,12159,12210,12261,12312,12377,12443,12509,12575,12640, - 12715,12766,12832,12897,12948,12997,13048,13099,13158,13244,13247,13250, - 13331,13339,13356,13373,13386,13399,13405,13408,13411,13414,13499,13584, - 13669,13754,13839,13924,14009,14094,14179,14264,14349,14434,14519,14604, - 14689,14774,14859,14944,15029,15114,15199,15284,15369,15454,15539,15624, - 15709,15794,15879,15964,16049,16134,16219,16304,16389,16474,16559,16644, - 16729,16814,16899,16984,17069,17154,17239,17324,17409,17494,17579,17664, - 17749,17834,17849,17864,17879,17894,17902,17910,17923,17936,17949,17966, - 17983,17996,18009,18022,18035,18048,18061,18074,18087,18100,18113,18126, - 18219,18241,18378,18515,18534,18553,18576,18598,18606,18614,18620,18629, - 18637,18645,18668,18692,18697,18702,18749,18796,18843,18932,18978,19063, - 19082,19101,19120,19139,19158,19178,19197,19217,19236,19256,19303,19350, - 19443,19490,19537,19584,19677,19723,19769,19854,19862,19908,19954,20000, - 20085,20104,20114,20124,20136,20139,20221,20233,20248,20260,20272,20282, - 20289,20335,20384,20433,20436,20439,20442,20445,20448,20451,20454,20457, - 20460,20463,20466,20551,20557,20600,20643,20686,20729,20772,20815,20858, - 20904,20950,20996,21042,21088,21134,21180,21226,21272,21318,21364,21410, - 21456,21502,21548,21594,21640,21686,21732,21778,21824,21870,21916,21962, - 22008,22054,22100,22146,22192,22238,22284,22330,22342,22354,22366,22378, - 22390,22409,22421,22433,22478,22490,22502,22527,22535,22543,22551,22597, - 22682,22728,22813,22825,22833,22841,22851,22861,22871,22882,22892,22938, - 22984,23030,23039,23048,23053,23098,23144,23154,23159,23169,23190,23481, - 23526,23529,23622,23630,23638,23646,23654,23662,23667,23670,23757,23767, - 23773,23817,23819,23838,23923,24008,24093,24178,24263,24348,24433,24518, - 24603,24688,24693,24763,24833,24903,24973,25043,25122,25201,25281,25361, - 25441,25521,25602,25683,25765,25847,25930,26013,26021,26033,26045,26057, - 26065,26073,26085,26170,26255,26340,26343,26389,26445,26492,26495,26504, - 26549,26595,26603,26622,26670,26716,26728,26772,26778,26798,26801,26804, - 26807,26810,26813,26816,26819,26822,26825,26828,26831,26873,26915,26951, - 26987,27023,27059,27095,27131,27161,27191,27219,27247,27259,27271,27283, - 27296,27341,27433,27518,27537,27562,27567,27572,27585,27588 + 8702,8715,8728,8741,8754,8767,8780,8793,8853,8862,8932,8939,8942,9029, + 9106,9114,9158,9166,9211,9222,9230,9242,9254,9262,9268,9273,9276,9335, + 9390,9396,9441,9447,9458,9501,9542,9590,9643,9648,9657,9662,9667,9672, + 9677,9682,9687,9692,9697,9702,9743,9784,9850,9855,9860,9865,9870,9875, + 9880,9885,9890,9895,9900,9905,9948,10013,10056,10121,10167,10237,10307, + 10377,10447,10488,10532,10570,10608,10640,10670,10675,10713,10798,10806, + 10814,10821,10829,10837,10845,10853,10872,10891,10899,10907,10915,10923, + 10966,10974,10982,10990,11015,11045,11096,11162,11213,11279,11328,11379, + 11430,11481,11532,11583,11634,11685,11736,11787,11838,11889,11940,11991, + 12042,12093,12144,12195,12246,12297,12362,12428,12494,12560,12625,12700, + 12751,12817,12882,12933,12982,13033,13084,13143,13229,13232,13235,13316, + 13324,13341,13358,13371,13384,13390,13393,13396,13399,13484,13569,13654, + 13739,13824,13909,13994,14079,14164,14249,14334,14419,14504,14589,14674, + 14759,14844,14929,15014,15099,15184,15269,15354,15439,15524,15609,15694, + 15779,15864,15949,16034,16119,16204,16289,16374,16459,16544,16629,16714, + 16799,16884,16969,17054,17139,17224,17309,17394,17479,17564,17649,17734, + 17819,17834,17849,17864,17879,17887,17895,17908,17921,17934,17951,17968, + 17981,17994,18007,18020,18033,18046,18059,18072,18085,18098,18111,18204, + 18226,18363,18500,18519,18538,18561,18583,18591,18599,18605,18614,18622, + 18630,18653,18677,18682,18687,18734,18781,18828,18917,18963,19048,19067, + 19086,19105,19124,19143,19163,19182,19202,19221,19241,19288,19335,19428, + 19475,19522,19569,19662,19708,19754,19839,19847,19893,19939,19985,20070, + 20089,20099,20109,20121,20203,20215,20230,20242,20254,20264,20271,20317, + 20366,20415,20418,20421,20424,20427,20430,20433,20436,20439,20442,20445, + 20448,20533,20539,20582,20625,20668,20711,20754,20797,20840,20886,20932, + 20978,21024,21070,21116,21162,21208,21254,21300,21346,21392,21438,21484, + 21530,21576,21622,21668,21714,21760,21806,21852,21898,21944,21990,22036, + 22082,22128,22174,22220,22266,22312,22324,22336,22348,22360,22372,22391, + 22403,22415,22460,22472,22484,22509,22517,22525,22533,22579,22664,22710, + 22795,22807,22815,22823,22833,22843,22853,22864,22874,22920,22966,23012, + 23021,23030,23035,23080,23126,23136,23141,23151,23172,23463,23508,23511, + 23604,23612,23620,23628,23636,23644,23731,23741,23747,23791,23793,23812, + 23897,23982,24067,24152,24237,24322,24407,24492,24577,24662,24667,24737, + 24807,24877,24947,25017,25096,25175,25255,25335,25415,25495,25576,25657, + 25739,25821,25904,25987,25995,26007,26019,26031,26039,26047,26059,26144, + 26229,26314,26317,26363,26419,26466,26469,26478,26523,26569,26577,26596, + 26644,26690,26702,26746,26752,26772,26775,26778,26781,26784,26787,26790, + 26793,26796,26799,26802,26805,26847,26889,26925,26961,26997,27033,27069, + 27105,27135,27165,27193,27221,27233,27245,27257,27270,27315,27407,27492, + 27511,27536,27541,27546,27559,27562 }; @@ -6556,64 +6537,64 @@ static const unsigned short ag_sbe[] = { 7328,7374,7420,7466,7512,7558,7604,7650,7696,7742,7788,7834,7880,7926, 7972,8018,8064,8110,8156,8202,8248,8294,8340,8386,8432,8478,8524,8536, 8548,8560,8572,8580,8588,8599,8610,8621,8634,8647,8660,8673,8686,8699, - 8712,8725,8738,8751,8764,8777,8790,8849,8859,8901,8908,8911,8955,9036, - 9082,9126,9169,9177,9223,9233,9241,9248,9260,9273,9281,9286,9289,9348, - 9403,9409,9453,9460,9471,9514,9555,9603,9655,9659,9668,9673,9678,9683, - 9688,9693,9698,9703,9708,9713,9754,9795,9862,9867,9872,9877,9882,9887, - 9892,9897,9902,9907,9912,9917,9960,10025,10068,10133,10179,10221,10291, - 10361,10431,10500,10539,10580,10616,10650,10680,10687,10708,10770,10818, - 10826,10834,10841,10849,10857,10865,10884,10903,10911,10919,10927,10935, - 10980,10986,10994,11002,11027,11051,11108,11174,11225,11291,11340,11391, - 11442,11493,11544,11595,11646,11697,11748,11799,11850,11901,11952,12003, - 12054,12105,12156,12207,12258,12309,12374,12440,12506,12572,12637,12712, - 12763,12829,12894,12945,12994,13045,13096,13155,13201,13245,13248,13288, - 13336,13345,13365,13382,13393,13403,13406,13409,13412,13456,13541,13626, - 13711,13796,13881,13966,14051,14136,14221,14306,14391,14476,14561,14646, - 14731,14816,14901,14986,15071,15156,15241,15326,15411,15496,15581,15666, - 15751,15836,15921,16006,16091,16176,16261,16346,16431,16516,16601,16686, - 16771,16856,16941,17026,17111,17196,17281,17366,17451,17536,17621,17706, - 17791,17842,17857,17872,17887,17898,17906,17917,17930,17943,17958,17975, - 17992,18005,18018,18031,18044,18057,18070,18083,18096,18109,18122,18169, - 18232,18375,18512,18531,18549,18573,18595,18603,18611,18617,18622,18634, - 18642,18665,18688,18694,18698,18746,18793,18840,18886,18975,19020,19079, - 19097,19117,19135,19155,19173,19194,19212,19233,19251,19300,19347,19393, - 19487,19534,19581,19627,19720,19766,19811,19859,19905,19951,19997,20042, - 20100,20111,20121,20128,20137,20179,20225,20246,20252,20264,20281,20288, - 20333,20383,20432,20434,20437,20440,20443,20446,20449,20452,20455,20458, - 20461,20464,20508,20556,20597,20640,20683,20726,20769,20812,20855,20901, - 20947,20993,21039,21085,21131,21177,21223,21269,21315,21361,21407,21453, - 21499,21545,21591,21637,21683,21729,21775,21821,21867,21913,21959,22005, - 22051,22097,22143,22189,22235,22281,22327,22334,22346,22358,22370,22382, - 22405,22413,22425,22477,22482,22494,22524,22532,22540,22548,22594,22639, - 22725,22770,22817,22830,22838,22848,22858,22868,22879,22889,22935,22981, - 23027,23036,23045,23050,23096,23142,23151,23156,23168,23188,23323,23524, - 23527,23572,23628,23636,23644,23652,23660,23664,23668,23713,23766,23772, - 23816,23818,23835,23880,23965,24050,24135,24220,24305,24390,24475,24560, - 24645,24690,24732,24802,24872,24942,25012,25085,25164,25243,25323,25403, - 25483,25563,25644,25725,25807,25889,25972,26018,26025,26037,26049,26062, - 26070,26077,26127,26212,26297,26341,26387,26442,26489,26493,26501,26547, - 26592,26601,26619,26667,26715,26720,26771,26777,26793,26799,26802,26805, - 26808,26811,26814,26817,26820,26823,26826,26829,26867,26909,26948,26984, - 27020,27056,27090,27126,27158,27188,27216,27244,27251,27263,27275,27293, - 27340,27384,27475,27533,27558,27564,27569,27581,27586,27588 + 8712,8725,8738,8751,8764,8777,8790,8849,8859,8930,8937,8940,8984,9065, + 9111,9155,9163,9209,9219,9227,9234,9246,9259,9267,9272,9275,9334,9389, + 9395,9439,9446,9457,9500,9541,9589,9641,9645,9654,9659,9664,9669,9674, + 9679,9684,9689,9694,9699,9740,9781,9847,9852,9857,9862,9867,9872,9877, + 9882,9887,9892,9897,9902,9945,10010,10053,10118,10164,10206,10276,10346, + 10416,10485,10524,10565,10601,10635,10665,10672,10693,10755,10803,10811, + 10819,10826,10834,10842,10850,10869,10888,10896,10904,10912,10920,10965, + 10971,10979,10987,11012,11036,11093,11159,11210,11276,11325,11376,11427, + 11478,11529,11580,11631,11682,11733,11784,11835,11886,11937,11988,12039, + 12090,12141,12192,12243,12294,12359,12425,12491,12557,12622,12697,12748, + 12814,12879,12930,12979,13030,13081,13140,13186,13230,13233,13273,13321, + 13330,13350,13367,13378,13388,13391,13394,13397,13441,13526,13611,13696, + 13781,13866,13951,14036,14121,14206,14291,14376,14461,14546,14631,14716, + 14801,14886,14971,15056,15141,15226,15311,15396,15481,15566,15651,15736, + 15821,15906,15991,16076,16161,16246,16331,16416,16501,16586,16671,16756, + 16841,16926,17011,17096,17181,17266,17351,17436,17521,17606,17691,17776, + 17827,17842,17857,17872,17883,17891,17902,17915,17928,17943,17960,17977, + 17990,18003,18016,18029,18042,18055,18068,18081,18094,18107,18154,18217, + 18360,18497,18516,18534,18558,18580,18588,18596,18602,18607,18619,18627, + 18650,18673,18679,18683,18731,18778,18825,18871,18960,19005,19064,19082, + 19102,19120,19140,19158,19179,19197,19218,19236,19285,19332,19378,19472, + 19519,19566,19612,19705,19751,19796,19844,19890,19936,19982,20027,20085, + 20096,20106,20113,20161,20207,20228,20234,20246,20263,20270,20315,20365, + 20414,20416,20419,20422,20425,20428,20431,20434,20437,20440,20443,20446, + 20490,20538,20579,20622,20665,20708,20751,20794,20837,20883,20929,20975, + 21021,21067,21113,21159,21205,21251,21297,21343,21389,21435,21481,21527, + 21573,21619,21665,21711,21757,21803,21849,21895,21941,21987,22033,22079, + 22125,22171,22217,22263,22309,22316,22328,22340,22352,22364,22387,22395, + 22407,22459,22464,22476,22506,22514,22522,22530,22576,22621,22707,22752, + 22799,22812,22820,22830,22840,22850,22861,22871,22917,22963,23009,23018, + 23027,23032,23078,23124,23133,23138,23150,23170,23305,23506,23509,23554, + 23610,23618,23626,23634,23642,23687,23740,23746,23790,23792,23809,23854, + 23939,24024,24109,24194,24279,24364,24449,24534,24619,24664,24706,24776, + 24846,24916,24986,25059,25138,25217,25297,25377,25457,25537,25618,25699, + 25781,25863,25946,25992,25999,26011,26023,26036,26044,26051,26101,26186, + 26271,26315,26361,26416,26463,26467,26475,26521,26566,26575,26593,26641, + 26689,26694,26745,26751,26767,26773,26776,26779,26782,26785,26788,26791, + 26794,26797,26800,26803,26841,26883,26922,26958,26994,27030,27064,27100, + 27132,27162,27190,27218,27225,27237,27249,27267,27314,27358,27449,27507, + 27532,27538,27543,27555,27560,27562 }; static const unsigned char ag_fl[] = { 2,1,1,2,2,1,1,2,0,1,3,3,1,2,1,2,2,1,2,0,1,4,5,3,2,1,0,1,7,7,1,1,6,6,6, - 2,3,2,1,2,4,4,4,4,6,4,4,0,1,4,4,4,4,3,3,4,4,6,4,1,4,1,1,2,2,2,2,3,5,1, - 2,2,2,3,2,1,1,1,3,2,1,1,3,1,1,1,3,1,1,3,3,3,3,3,3,3,3,3,4,6,2,3,2,1,1, - 2,2,3,3,2,2,3,3,1,1,2,3,1,1,1,4,4,4,1,4,2,1,1,1,1,2,2,1,2,2,3,2,2,1,2, - 3,1,2,2,2,2,2,2,2,2,4,1,1,4,3,2,1,2,3,3,2,1,1,1,1,1,1,2,1,1,1,1,2,1,1, - 2,1,1,2,1,1,2,1,1,2,1,1,2,1,2,4,4,2,4,4,2,4,4,2,4,4,4,4,2,4,4,2,4,4,4, - 4,4,1,2,2,2,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,7,1,1,1,1,1,1,1,2,2,2,1,1,2, - 2,2,2,1,2,2,2,3,2,2,2,2,2,2,2,2,3,4,1,1,2,2,2,2,2,1,2,1,2,2,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, - 1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,7,3,3,3, - 3,3,3,3,3,3,3,5,3,5,3,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,3,3, - 3,3,1,1,1,1,1,3,3,3,3,3,3,3,1,1,1,3,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,3,2,1,2,4,4,4,4,6,4,4,0,1,4,4,4,4,3,3,4,4,6,4,1,1,2,2,2,2,3,5,1,2,2, + 2,3,2,1,1,1,3,2,1,1,3,1,1,1,3,1,1,3,3,3,3,3,3,3,3,3,4,6,2,3,2,1,1,2,2, + 3,3,2,2,3,3,1,1,2,3,1,1,1,4,4,4,1,4,2,1,1,1,1,2,2,1,2,2,3,2,2,1,2,3,1, + 2,2,2,2,2,2,2,2,4,1,1,4,3,2,1,2,3,3,2,1,1,1,1,1,1,2,1,1,1,1,2,1,1,2,1, + 1,2,1,1,2,1,1,2,1,1,2,1,2,4,4,2,4,4,2,4,4,2,4,4,4,4,2,4,4,2,4,4,4,4,4, + 1,2,2,2,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,7,1,1,1,1,1,1,1,2,2,2,1,1,2,2,2, + 2,1,2,2,2,3,2,2,2,2,2,2,2,2,3,4,1,1,2,2,2,2,2,1,2,1,2,2,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,7,3,3,3,3,3, + 3,3,3,3,3,5,3,5,3,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,3,3,3,3, + 1,1,1,1,1,3,3,3,3,3,3,3,1,1,1,3,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -6624,8 +6605,8 @@ static const unsigned char ag_fl[] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, @@ -6633,75 +6614,75 @@ static const unsigned char ag_fl[] = { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2 + 2,2 }; static const unsigned short ag_ptt[] = { 0, 36, 37, 37, 34, 39, 43, 43, 44, 44, 39, 39, 39, 40, 47, 47, 47, 51, 51, 52, 52, 35, 35, 35, 35, 35, 55, 55, 35, 35, 61, 61, 35, 35, 35, 35, 35, 35, 64, 53, 66, 66, 66, 66, 66, 66, 66, 74, 74, 66, 66, 66, 66, 66, - 66, 66, 66, 66, 84, 84, 89, 89, 85, 85, 85, 94, 94, 62, 62, 33, 33, 33, - 33, 33, 33,100,100,100, 33, 33,104,104, 33,108,108,108, 33,111,111, 33, + 66, 66, 66, 66, 84, 84, 85, 85, 85, 92, 92, 62, 62, 33, 33, 33, 33, 33, + 33, 98, 98, 98, 33, 33,102,102, 33,106,106,106, 33,109,109, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 30, 30, 90, 90, 90, 90, 90, 90,113,113,538, - 443,443,443,133,133,133,438,438,486, 18, 18,436, 12, 12, 12,142,142,142, - 142,142,142,142,142,142,142,155,155,142,142,437, 14, 14, 14, 14,430,430, - 430,430,430, 22, 22, 76, 76,170,170,170,166,173,173,166,176,176,166,179, - 179,166,182,182,166,185,185,166, 57, 26, 26, 26, 28, 28, 28, 23, 23, 23, - 24, 24, 24, 24, 24, 27, 27, 27, 25, 25, 25, 25, 25, 25, 29, 29, 29, 29, - 29,199,199,199,199,208,208,208,208,208,208,208,208,208,208,208,207,207, - 493,493,493,493,493,493,493,493,224,224,493,493, 7, 7, 7, 7, 7, 7, - 6, 6, 6, 17, 17,219,219,220,220, 15, 15, 15, 16, 16, 16, 16, 16, 16, - 16, 16,540, 9, 9, 9,596,596,596,596,596,596,243,243,596,596,246,246, - 610,248,248,610,250,250,610,610,252,252,252,252,252,254,254,255,255,255, - 255,255,255, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,273,273,273, - 273,267,267,267,267,267,280,280,267,267,267,286,286,286,267,267,267,267, - 267,267,267,267,267,297,297,267,267,267,267,267,267,267,267,267,267,310, - 310,310,267,267,267,267,267,267,267,260,260,261,261,261,261,258,258,258, - 258,258,258,258,258,258,258,258,258,258,259,259,259,339,263,341,264,343, - 265,266,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,367, - 367,367,367,367,262,262,262,262,376,376,376,376,376,262,262,262,262,262, - 262,262,386,386,386,262,390,390,390,262,262,262,262,262,262,262,262,262, - 262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,138,346, - 153,227, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 33, 33, 33, 33, 33, 30, 30, 87, 87, 87, 87, 87, 87,111,111,535,441,441, + 441,131,131,131,436,436,483, 18, 18,434, 12, 12, 12,140,140,140,140,140, + 140,140,140,140,140,153,153,140,140,435, 14, 14, 14, 14,428,428,428,428, + 428, 22, 22, 76, 76,168,168,168,164,171,171,164,174,174,164,177,177,164, + 180,180,164,183,183,164, 57, 26, 26, 26, 28, 28, 28, 23, 23, 23, 24, 24, + 24, 24, 24, 27, 27, 27, 25, 25, 25, 25, 25, 25, 29, 29, 29, 29, 29,197, + 197,197,197,206,206,206,206,206,206,206,206,206,206,206,205,205,490,490, + 490,490,490,490,490,490,222,222,490,490, 7, 7, 7, 7, 7, 7, 6, 6, + 6, 17, 17,217,217,218,218, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, + 537, 9, 9, 9,593,593,593,593,593,593,241,241,593,593,244,244,607,246, + 246,607,248,248,607,607,250,250,250,250,250,252,252,253,253,253,253,253, + 253, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,271,271,271,271,265, + 265,265,265,265,278,278,265,265,265,284,284,284,265,265,265,265,265,265, + 265,265,265,295,295,265,265,265,265,265,265,265,265,265,265,308,308,308, + 265,265,265,265,265,265,265,258,258,259,259,259,259,256,256,256,256,256, + 256,256,256,256,256,256,256,256,257,257,257,337,261,339,262,341,263,264, + 260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,365,365,365, + 365,365,260,260,260,260,374,374,374,374,374,260,260,260,260,260,260,260, + 384,384,384,260,388,388,388,260,260,260,260,260,260,260,260,260,260,260, + 260,260,260,260,260,260,260,260,260,260,260,260,260,260,136,344,151,225, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 91, - 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, - 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, - 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 92,136,136,136,136,136,136,136,136,136,136, - 136,136,136,137,137,137,137,137,137,137,137,137,137,137,137,137,137,139, - 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, - 144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, - 144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, - 144,144,144,144,144,151,151,151,152,152,152,152,152,156,156,156,156,156, - 156,156,156,156,159,159,159,159,159,159,159,159,159,159,159,159,159,159, - 159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, - 159,159,159,159,159,159,159,159,160,160,160,160,160,160,160,160,160,160, - 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, - 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,228,228,228, - 228,229,229,231,231,231,231,233,233,233,233,233,233,233,233,233,233,233, - 233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, - 233,233,233,233,233,233,233,233,233,233,233,233, 45, 41, 46, 48, 49, 11, - 54, 56, 58, 59, 60, 10, 13, 19, 65, 68, 67, 69, 21, 70, 71, 72, 73, 75, - 77, 78, 79, 80, 81, 82, 83, 88, 87, 86, 93, 95, 96, 97, 98, 99,101,102, - 103,105,106,107,109,110,112,114,115,116,117,118,119,120,122,121,123,124, - 125, 20,126,127,128,129,130,131, 2,132,165,167,168,169,171,172,174,175, - 177,178,180,181,183,184,186,187,188,189,190,191,192,193,194,195,196,197, - 198,200,201,202,203,204,205,206,209,210,211,212,213,214,215,216,217, 3, - 218, 8,253,244,256,257,251,268,269,270,271,272,274,275,276,277,278,279, - 281,282,283,284,285,287,288,289,290,291,292,293,294,295,296,298,299,300, - 301,302,303,304,305,306,307,308,309,311,312,313,314,315,316,317,318,319, - 320,321,322, 4,323,324,325,326,327,328,329,330,331,332,333,334,335, 5, - 336,337,338,340,342,344,345,347,348,349,350,351,352,353,354,355,356,357, - 358,359,360,361,362,363,364,365,366,368,369,370,371,372,373,374,375,377, - 378,379,380,381,382,383,384,385,387,388,389,391,392,393,394,395,396,397, - 398,399,400,401,402,245,403,404,405,406,407,408,409,410,411,412,413,415, - 141,416,154,140,148,417,418,419,420,158,157,421,230,422,149,225,150,423, - 221,145,147,146,414,143,226,424 + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90,134,134,134,134,134,134,134,134,134,134,134,134, + 134,135,135,135,135,135,135,135,135,135,135,135,135,135,135,137,137,137, + 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,142,142, + 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, + 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, + 142,142,142,149,149,149,150,150,150,150,150,154,154,154,154,154,154,154, + 154,154,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, + 157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, + 157,157,157,157,157,157,158,158,158,158,158,158,158,158,158,158,158,158, + 158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, + 158,158,158,158,158,158,158,158,158,158,158,158,158,226,226,226,226,227, + 227,229,229,229,229,231,231,231,231,231,231,231,231,231,231,231,231,231, + 231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, + 231,231,231,231,231,231,231,231,231,231, 45, 41, 46, 48, 49, 11, 54, 56, + 58, 59, 60, 10, 13, 19, 65, 68, 67, 69, 21, 70, 71, 72, 73, 75, 77, 78, + 79, 80, 81, 82, 83, 88, 86, 91, 93, 94, 95, 96, 97, 99,100,101,103,104, + 105,107,108,110,112,113,114,115,116,117,118,120,119,121,122,123, 20,124, + 125,126,127,128,129, 2,130,163,165,166,167,169,170,172,173,175,176,178, + 179,181,182,184,185,186,187,188,189,190,191,192,193,194,195,196,198,199, + 200,201,202,203,204,207,208,209,210,211,212,213,214,215, 3,216, 8,251, + 242,254,255,249,266,267,268,269,270,272,273,274,275,276,277,279,280,281, + 282,283,285,286,287,288,289,290,291,292,293,294,296,297,298,299,300,301, + 302,303,304,305,306,307,309,310,311,312,313,314,315,316,317,318,319,320, + 4,321,322,323,324,325,326,327,328,329,330,331,332,333, 5,334,335,336, + 338,340,342,343,345,346,347,348,349,350,351,352,353,354,355,356,357,358, + 359,360,361,362,363,364,366,367,368,369,370,371,372,373,375,376,377,378, + 379,380,381,382,383,385,386,387,389,390,391,392,393,394,395,396,397,398, + 399,400,243,401,402,403,404,405,406,407,408,409,410,411,413,139,414,152, + 138,146,415,416,417,418,156,155,419,228,420,147,223,148,421,219,143,145, + 144,412,141,224,422 }; @@ -6734,14 +6715,14 @@ static void ag_ra(void) case 24: ag_rp_24(); break; case 25: ag_rp_25(); break; case 26: ag_rp_26(); break; - case 27: ag_rp_27(); break; - case 28: ag_rp_28(); break; - case 29: ag_rp_29(V(0,int)); break; - case 30: ag_rp_30(V(1,int)); break; + case 27: ag_rp_27(V(0,int)); break; + case 28: ag_rp_28(V(1,int)); break; + case 29: ag_rp_29(); break; + case 30: ag_rp_30(); break; case 31: ag_rp_31(); break; - case 32: ag_rp_32(); break; + case 32: ag_rp_32(V(2,int)); break; case 33: ag_rp_33(); break; - case 34: ag_rp_34(V(2,int)); break; + case 34: ag_rp_34(); break; case 35: ag_rp_35(); break; case 36: ag_rp_36(); break; case 37: ag_rp_37(); break; @@ -6775,9 +6756,9 @@ static void ag_ra(void) case 65: ag_rp_65(); break; case 66: ag_rp_66(); break; case 67: ag_rp_67(); break; - case 68: ag_rp_68(); break; + case 68: ag_rp_68(V(2,int)); break; case 69: ag_rp_69(); break; - case 70: ag_rp_70(V(2,int)); break; + case 70: ag_rp_70(); break; case 71: ag_rp_71(); break; case 72: ag_rp_72(); break; case 73: ag_rp_73(); break; @@ -6786,40 +6767,40 @@ static void ag_ra(void) case 76: ag_rp_76(); break; case 77: ag_rp_77(); break; case 78: ag_rp_78(); break; - case 79: ag_rp_79(); break; - case 80: ag_rp_80(); break; - case 81: ag_rp_81(V(0,int)); break; - case 82: ag_rp_82(V(1,int)); break; + case 79: ag_rp_79(V(0,int)); break; + case 80: ag_rp_80(V(1,int)); break; + case 81: ag_rp_81(V(1,int)); break; + case 82: ag_rp_82(V(0,int)); break; case 83: ag_rp_83(V(1,int)); break; - case 84: ag_rp_84(V(0,int)); break; + case 84: ag_rp_84(V(1,int), V(2,int)); break; case 85: ag_rp_85(V(1,int)); break; - case 86: ag_rp_86(V(1,int), V(2,int)); break; + case 86: ag_rp_86(); break; case 87: ag_rp_87(V(1,int)); break; - case 88: ag_rp_88(); break; - case 89: ag_rp_89(V(1,int)); break; - case 90: V(0,int) = ag_rp_90(V(0,int)); break; + case 88: V(0,int) = ag_rp_88(V(0,int)); break; + case 89: V(0,int) = ag_rp_89(); break; + case 90: V(0,int) = ag_rp_90(); break; case 91: V(0,int) = ag_rp_91(); break; case 92: V(0,int) = ag_rp_92(); break; case 93: V(0,int) = ag_rp_93(); break; case 94: V(0,int) = ag_rp_94(); break; case 95: V(0,int) = ag_rp_95(); break; case 96: V(0,int) = ag_rp_96(); break; - case 97: V(0,int) = ag_rp_97(); break; - case 98: V(0,int) = ag_rp_98(); break; - case 99: V(0,int) = ag_rp_99(V(1,int), V(2,int), V(3,int)); break; - case 100: V(0,int) = ag_rp_100(V(2,int), V(3,int)); break; - case 101: V(0,int) = ag_rp_101(V(2,int)); break; - case 102: ag_rp_102(); break; - case 103: ag_rp_103(); break; - case 104: ag_rp_104(V(1,int)); break; - case 105: ag_rp_105(V(2,int)); break; + case 97: V(0,int) = ag_rp_97(V(1,int), V(2,int), V(3,int)); break; + case 98: V(0,int) = ag_rp_98(V(2,int), V(3,int)); break; + case 99: V(0,int) = ag_rp_99(V(2,int)); break; + case 100: ag_rp_100(); break; + case 101: ag_rp_101(); break; + case 102: ag_rp_102(V(1,int)); break; + case 103: ag_rp_103(V(2,int)); break; + case 104: ag_rp_104(); break; + case 105: ag_rp_105(); break; case 106: ag_rp_106(); break; case 107: ag_rp_107(); break; case 108: ag_rp_108(); break; - case 109: ag_rp_109(); break; - case 110: ag_rp_110(); break; - case 111: V(0,int) = ag_rp_111(); break; - case 112: V(0,int) = ag_rp_112(); break; + case 109: V(0,int) = ag_rp_109(); break; + case 110: V(0,int) = ag_rp_110(); break; + case 111: ag_rp_111(); break; + case 112: ag_rp_112(); break; case 113: ag_rp_113(); break; case 114: ag_rp_114(); break; case 115: ag_rp_115(); break; @@ -6847,9 +6828,9 @@ static void ag_ra(void) case 137: ag_rp_137(); break; case 138: ag_rp_138(); break; case 139: ag_rp_139(); break; - case 140: ag_rp_140(); break; + case 140: ag_rp_140(V(0,double)); break; case 141: ag_rp_141(); break; - case 142: ag_rp_142(V(0,double)); break; + case 142: ag_rp_142(); break; case 143: ag_rp_143(); break; case 144: ag_rp_144(); break; case 145: ag_rp_145(); break; @@ -6860,11 +6841,11 @@ static void ag_ra(void) case 150: ag_rp_150(); break; case 151: ag_rp_151(); break; case 152: ag_rp_152(); break; - case 153: ag_rp_153(); break; - case 154: ag_rp_154(); break; - case 155: V(0,double) = ag_rp_155(V(0,int)); break; - case 156: V(0,double) = ag_rp_156(V(0,double)); break; - case 157: V(0,int) = ag_rp_157(V(0,int)); break; + case 153: V(0,double) = ag_rp_153(V(0,int)); break; + case 154: V(0,double) = ag_rp_154(V(0,double)); break; + case 155: V(0,int) = ag_rp_155(V(0,int)); break; + case 156: V(0,int) = ag_rp_156(); break; + case 157: V(0,int) = ag_rp_157(); break; case 158: V(0,int) = ag_rp_158(); break; case 159: V(0,int) = ag_rp_159(); break; case 160: V(0,int) = ag_rp_160(); break; @@ -6872,35 +6853,35 @@ static void ag_ra(void) case 162: V(0,int) = ag_rp_162(); break; case 163: V(0,int) = ag_rp_163(); break; case 164: V(0,int) = ag_rp_164(); break; - case 165: V(0,int) = ag_rp_165(); break; - case 166: V(0,int) = ag_rp_166(); break; - case 167: ag_rp_167(V(1,int)); break; + case 165: ag_rp_165(V(1,int)); break; + case 166: ag_rp_166(V(1,int)); break; + case 167: ag_rp_167(V(0,int)); break; case 168: ag_rp_168(V(1,int)); break; - case 169: ag_rp_169(V(0,int)); break; + case 169: ag_rp_169(V(2,int)); break; case 170: ag_rp_170(V(1,int)); break; - case 171: ag_rp_171(V(2,int)); break; + case 171: ag_rp_171(V(1,int)); break; case 172: ag_rp_172(V(1,int)); break; case 173: ag_rp_173(V(1,int)); break; case 174: ag_rp_174(V(1,int)); break; case 175: ag_rp_175(V(1,int)); break; case 176: ag_rp_176(V(1,int)); break; case 177: ag_rp_177(V(1,int)); break; - case 178: ag_rp_178(V(1,int)); break; - case 179: ag_rp_179(V(1,int)); break; - case 180: V(0,int) = ag_rp_180(V(1,int)); break; - case 181: V(0,int) = ag_rp_181(V(1,int), V(2,int)); break; + case 178: V(0,int) = ag_rp_178(V(1,int)); break; + case 179: V(0,int) = ag_rp_179(V(1,int), V(2,int)); break; + case 180: V(0,int) = ag_rp_180(); break; + case 181: V(0,int) = ag_rp_181(V(0,int)); break; case 182: V(0,int) = ag_rp_182(); break; - case 183: V(0,int) = ag_rp_183(V(0,int)); break; + case 183: V(0,int) = ag_rp_183(); break; case 184: V(0,int) = ag_rp_184(); break; case 185: V(0,int) = ag_rp_185(); break; case 186: V(0,int) = ag_rp_186(); break; case 187: V(0,int) = ag_rp_187(); break; case 188: V(0,int) = ag_rp_188(); break; - case 189: V(0,int) = ag_rp_189(); break; - case 190: V(0,int) = ag_rp_190(); break; - case 191: V(0,double) = ag_rp_191(); break; - case 192: V(0,double) = ag_rp_192(V(1,int)); break; - case 193: V(0,double) = ag_rp_193(V(0,double), V(1,int)); break; + case 189: V(0,double) = ag_rp_189(); break; + case 190: V(0,double) = ag_rp_190(V(1,int)); break; + case 191: V(0,double) = ag_rp_191(V(0,double), V(1,int)); break; + case 192: ag_rp_192(); break; + case 193: ag_rp_193(); break; case 194: ag_rp_194(); break; case 195: ag_rp_195(); break; case 196: ag_rp_196(); break; @@ -6983,9 +6964,9 @@ static void ag_ra(void) case 273: ag_rp_273(); break; case 274: ag_rp_274(); break; case 275: ag_rp_275(); break; - case 276: ag_rp_276(); break; + case 276: ag_rp_276(V(2,int)); break; case 277: ag_rp_277(); break; - case 278: ag_rp_278(V(2,int)); break; + case 278: ag_rp_278(); break; case 279: ag_rp_279(); break; case 280: ag_rp_280(); break; case 281: ag_rp_281(); break; @@ -7036,13 +7017,11 @@ static void ag_ra(void) case 326: ag_rp_326(); break; case 327: ag_rp_327(); break; case 328: ag_rp_328(); break; - case 329: ag_rp_329(); break; - case 330: ag_rp_330(); break; } } #define TOKEN_NAMES a85parse_token_names -const char *const a85parse_token_names[709] = { +const char *const a85parse_token_names[706] = { "a85parse", "WS", "integer", @@ -7127,13 +7106,11 @@ const char *const a85parse_token_names[709] = { "\"ERROR\"", "\"UNDEF\"", "\"DEFINE\"", - "macro definition", + "macro", "macro expansion", "'('", - "parameter list", - "')'", - "macro", "", + "')'", "", "define chars", "\"\\\\\\n\"", @@ -7500,7 +7477,6 @@ const char *const a85parse_token_names[709] = { "\"UNDEF\"", "\"DEFINE\"", "')'", - "parameter list", "'('", "\"\\\\\\n\"", "\"CSEG\"", @@ -7757,68 +7733,68 @@ const char *const a85parse_token_names[709] = { static const unsigned short ag_ctn[] = { - 0,0, 0,0, 0,0, 64,1,430,1, 53,1, 35,1, 35,1, 35,1, 35,1, 35,1, 0,0, + 0,0, 0,0, 0,0, 64,1,428,1, 53,1, 35,1, 35,1, 35,1, 35,1, 35,1, 0,0, 66,1, 66,1, 66,1, 0,0, 0,0, 66,1, 66,1, 0,0, 66,1, 66,1, 0,0, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 0,0, 0,0, - 35,2, 47,1, 0,0, 39,1, 40,1, 39,1, 39,1, 35,2, 62,1,267,1,267,1,267,1, - 267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,343,1, - 341,1,339,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, - 262,1,262,1,262,1,262,1,262,1,262,1,267,1,267,1,267,1,267,1,267,1,267,1, - 267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1, - 267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,267,1,266,1, - 343,1,341,1,339,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, - 262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, - 262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, - 262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, - 262,1,262,1,262,1,261,1,261,1,261,1,261,1,260,1,260,1,259,1,259,1,259,1, - 258,1,258,1,258,1,258,1,258,1,258,1,258,1,258,1,258,1,258,1,258,1,258,1, - 258,1,266,1,265,1,264,1,263,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, - 262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, - 262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, - 262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1, - 262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,262,1,261,1,261,1,261,1, - 261,1,260,1,260,1,259,1,259,1,259,1,258,1,258,1,258,1,258,1,258,1,258,1, - 258,1,258,1,258,1,258,1,258,1,258,1,258,1, 0,0, 32,1, 89,1, 30,1, 32,1, - 33,1, 33,1, 35,2, 84,1, 66,2, 66,2,436,1, 0,0, 66,2, 66,2, 66,2, 66,2, - 540,1,220,1,219,1, 6,1, 6,1, 7,1, 15,1,540,1,493,1,220,1,219,1, 6,1, - 207,1,208,1, 0,0,208,1,208,1,208,1,208,1,208,1,208,1,208,1,208,1,208,1, - 207,1, 0,0, 0,0,208,1,208,1,208,1,208,1,208,1,208,1,208,1,208,1,208,1, - 208,1,208,1, 29,1, 0,0, 29,1, 0,0,199,1, 29,1, 29,1, 29,1, 29,1, 25,1, - 27,1, 24,1, 23,1, 28,1, 26,1, 26,1, 76,1, 76,1, 66,2, 66,2, 66,2, 0,0, - 66,2, 0,0, 66,2, 0,0, 66,2, 0,0, 66,2, 0,0, 66,2,437,1, 0,0, 66,2, - 66,2, 0,0, 35,3, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 35,2, 47,1, 0,0, 39,1, 40,1, 39,1, 39,1, 35,2, 62,1,265,1,265,1,265,1, + 265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,341,1, + 339,1,337,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,265,1,265,1,265,1,265,1,265,1,265,1, + 265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1, + 265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,264,1, + 341,1,339,1,337,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,259,1,259,1,259,1,259,1,258,1,258,1,257,1,257,1,257,1, + 256,1,256,1,256,1,256,1,256,1,256,1,256,1,256,1,256,1,256,1,256,1,256,1, + 256,1,264,1,263,1,262,1,261,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,259,1,259,1,259,1, + 259,1,258,1,258,1,257,1,257,1,257,1,256,1,256,1,256,1,256,1,256,1,256,1, + 256,1,256,1,256,1,256,1,256,1,256,1,256,1, 0,0, 32,1, 84,1, 30,1, 32,1, + 33,1, 33,1, 35,2, 66,2, 66,2,434,1, 0,0, 66,2, 66,2, 66,2, 66,2,537,1, + 218,1,217,1, 6,1, 6,1, 7,1, 15,1,537,1,490,1,218,1,217,1, 6,1,205,1, + 206,1, 0,0,206,1,206,1,206,1,206,1,206,1,206,1,206,1,206,1,206,1,205,1, + 0,0, 0,0,206,1,206,1,206,1,206,1,206,1,206,1,206,1,206,1,206,1,206,1, + 206,1, 29,1, 0,0, 29,1, 0,0,197,1, 29,1, 29,1, 29,1, 29,1, 25,1, 27,1, + 24,1, 23,1, 28,1, 26,1, 26,1, 76,1, 76,1, 66,2, 66,2, 66,2, 0,0, 66,2, + 0,0, 66,2, 0,0, 66,2, 0,0, 66,2, 0,0, 66,2,435,1, 0,0, 66,2, 66,2, + 0,0, 35,3, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, - 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 39,2, 39,2, 33,1, 35,3, 62,2,343,2, - 341,2,339,2,266,2,265,2,264,2,263,2,262,2,262,2,262,2,262,2,262,2,262,2, - 262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2, - 262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2, - 262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2, - 262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,262,2,261,2,261,2, - 261,2,261,2,260,2,260,2,259,2,259,2,259,2,258,2,258,2,258,2,258,2,258,2, - 258,2,258,2,258,2,258,2,258,2,258,2,258,2,258,2, 89,2, 0,0, 0,0, 32,2, - 0,0, 33,2, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, - 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, - 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, - 33,2, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 0,0, 33,2, 33,2, 0,0, 0,0, - 35,3, 84,2, 66,3, 66,3, 0,0, 66,3, 66,3, 6,2, 16,1, 15,2, 0,0, 0,0, - 208,2,208,2,208,2,208,2,208,2,208,2,208,2,208,2,208,2,208,2,208,2,199,2, - 7,1, 0,0, 25,2, 0,0, 25,2, 25,2, 25,2, 25,2, 27,2, 27,2, 0,0, 24,2, - 0,0, 24,2, 0,0, 24,2, 0,0, 24,2, 0,0, 23,2, 23,2, 0,0, 28,2, 28,2, - 0,0, 26,2, 26,2, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, - 0,0, 0,0, 0,0, 0,0, 66,3, 66,3, 66,3, 66,3, 66,3, 66,3, 66,3, 66,3, - 437,2, 66,3, 66,3, 0,0, 35,4, 35,4, 35,4, 0,0, 35,4, 0,0, 35,4, 35,4, - 22,1, 62,3,255,1,255,1,255,1, 0,0, 0,0,265,3,264,3,263,3,252,1,252,1, - 258,3, 0,0,486,1, 0,0, 0,0, 6,1,493,1, 32,3,486,1, 33,3, 33,3,113,1, - 113,1,113,1, 0,0, 0,0, 0,0, 84,3, 85,1, 0,0, 0,0, 0,0, 15,3,208,3, - 208,3,208,3,208,3,208,3,208,3,208,3,208,3,208,3,208,3,208,3,199,3, 25,3, - 25,3, 25,3, 25,3, 25,3, 27,3, 27,3, 24,3, 24,3, 24,3, 24,3, 23,3, 23,3, - 28,3, 28,3, 26,3, 26,3, 66,4, 35,5, 35,5, 35,5, 35,5, 35,5, 62,4,265,4, - 264,4,263,4,258,4, 0,0, 0,0, 0,0, 32,1, 32,1,486,2, 33,4, 0,0,113,2, - 0,0, 0,0, 66,5, 0,0, 0,0,208,4,208,4,208,4,208,4,208,4,208,4,208,4, - 208,4,208,4,208,4,208,4,199,4, 25,1, 25,1, 27,1, 27,1, 27,1, 27,1, 24,1, - 24,1, 23,1, 23,1, 28,1, 28,1, 66,5, 35,6, 35,6,258,5, 15,3, 0,0, 33,5, - 113,3,538,1, 0,0,208,5,258,6,208,6 + 0,0, 0,0, 0,0, 0,0, 0,0, 39,2, 39,2, 33,1, 35,3, 62,2,341,2,339,2, + 337,2,264,2,263,2,262,2,261,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2, + 260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2, + 260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2, + 260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2, + 260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,259,2,259,2,259,2, + 259,2,258,2,258,2,257,2,257,2,257,2,256,2,256,2,256,2,256,2,256,2,256,2, + 256,2,256,2,256,2,256,2,256,2,256,2,256,2, 84,2, 0,0, 0,0, 32,2, 0,0, + 33,2, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, + 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, + 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, + 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 0,0, 33,2, 33,2, 0,0, 0,0, 35,3, + 66,3, 66,3, 0,0, 66,3, 66,3, 6,2, 16,1, 15,2, 0,0, 0,0,206,2,206,2, + 206,2,206,2,206,2,206,2,206,2,206,2,206,2,206,2,206,2,197,2, 7,1, 0,0, + 25,2, 0,0, 25,2, 25,2, 25,2, 25,2, 27,2, 27,2, 0,0, 24,2, 0,0, 24,2, + 0,0, 24,2, 0,0, 24,2, 0,0, 23,2, 23,2, 0,0, 28,2, 28,2, 0,0, 26,2, + 26,2, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0,0, 0,0, 66,3, 66,3, 66,3, 66,3, 66,3, 66,3, 66,3, 66,3,435,2, 66,3, + 66,3, 0,0, 35,4, 35,4, 35,4, 0,0, 35,4, 0,0, 35,4, 35,4, 22,1, 62,3, + 253,1,253,1,253,1, 0,0, 0,0,263,3,262,3,261,3,250,1,250,1,256,3, 0,0, + 483,1, 0,0, 0,0, 6,1,490,1, 32,3,483,1, 33,3, 33,3,111,1,111,1,111,1, + 0,0, 0,0, 85,1, 0,0, 0,0, 0,0, 15,3,206,3,206,3,206,3,206,3,206,3, + 206,3,206,3,206,3,206,3,206,3,206,3,197,3, 25,3, 25,3, 25,3, 25,3, 25,3, + 27,3, 27,3, 24,3, 24,3, 24,3, 24,3, 23,3, 23,3, 28,3, 28,3, 26,3, 26,3, + 66,4, 35,5, 35,5, 35,5, 35,5, 35,5, 62,4,263,4,262,4,261,4,256,4, 0,0, + 0,0, 0,0, 32,1, 32,1,483,2, 33,4, 0,0,111,2, 0,0, 0,0, 66,5, 0,0, + 0,0,206,4,206,4,206,4,206,4,206,4,206,4,206,4,206,4,206,4,206,4,206,4, + 197,4, 25,1, 25,1, 27,1, 27,1, 27,1, 27,1, 24,1, 24,1, 23,1, 23,1, 28,1, + 28,1, 66,5, 35,6, 35,6,256,5, 15,3, 0,0, 33,5,111,3,535,1, 0,0,206,5, + 256,6,206,6 }; #ifndef MISSING_FORMAT diff --git a/src/a85parse.h b/src/a85parse.h index 55bf36f..5fc294f 100644 --- a/src/a85parse.h +++ b/src/a85parse.h @@ -1,5 +1,5 @@ -#ifndef A85PARSE_H_1357391036 -#define A85PARSE_H_1357391036 +#ifndef A85PARSE_H_1359224795 +#define A85PARSE_H_1359224795 typedef union { long alignment; @@ -26,31 +26,29 @@ typedef enum { a85parse_equation_token = 57, a85parse_cdseg_statement_token = 62, a85parse_error_token, a85parse_preproc_start_token, a85parse_preprocessor_directive_token = 66, a85parse_condition_token = 76, - a85parse_macro_definition_token = 84, a85parse_macro_expansion_token, - a85parse_macro_token = 89, a85parse_expression_list_token, - a85parse_define_chars_token = 92, - a85parse_cdseg_statement_start_token = 94, a85parse_name_list_token = 113, - a85parse_literal_alpha_token = 133, a85parse_digit_token = 138, - a85parse_asm_incl_char_token, a85parse_str_escape_char_token = 142, - a85parse_hex_digit_token = 156, a85parse_condition_start_token = 166, - a85parse_primary_exp_token = 199, a85parse_value_token = 207, - a85parse_function_token, a85parse_binary_integer_token = 219, - a85parse_octal_integer_token, a85parse_stack_register_token = 252, - a85parse_bd_register_token = 254, a85parse_page_register_token, - a85parse_eight_bit_reg_inst_token = 258, + a85parse_macro_token = 84, a85parse_macro_expansion_token, + a85parse_expression_list_token = 87, a85parse_define_chars_token = 90, + a85parse_cdseg_statement_start_token = 92, a85parse_name_list_token = 111, + a85parse_literal_alpha_token = 131, a85parse_digit_token = 136, + a85parse_asm_incl_char_token, a85parse_str_escape_char_token = 140, + a85parse_hex_digit_token = 154, a85parse_condition_start_token = 164, + a85parse_primary_exp_token = 197, a85parse_value_token = 205, + a85parse_function_token, a85parse_binary_integer_token = 217, + a85parse_octal_integer_token, a85parse_stack_register_token = 250, + a85parse_bd_register_token = 252, a85parse_page_register_token, + a85parse_eight_bit_reg_inst_token = 256, a85parse_sixteen_bit_reg_inst_token, a85parse_bd_reg_inst_token, a85parse_stack_reg_inst_token, a85parse_immediate_operand_inst_token, a85parse_lxi_inst_token, a85parse_mvi_inst_token, a85parse_spi_inst_token, a85parse_rst_inst_token, a85parse_no_arg_inst_token, - a85parse_lxi_inst_start_token = 339, a85parse_mvi_inst_start_token = 341, - a85parse_spi_inst_start_token = 343, a85parse_rst_arg_token = 346, - a85parse_label_token = 430, a85parse_literal_string_token = 436, + a85parse_lxi_inst_start_token = 337, a85parse_mvi_inst_start_token = 339, + a85parse_spi_inst_start_token = 341, a85parse_rst_arg_token = 344, + a85parse_label_token = 428, a85parse_literal_string_token = 434, a85parse_include_string_token, a85parse_asm_include_token, - a85parse_literal_name_nows_token = 443, - a85parse_parameter_list_token = 457, - a85parse_singlequote_string_token = 486, a85parse_integer_token = 493, - a85parse_literal_name_token = 538, a85parse_real_token = 540, - a85parse_register_8_bit_token = 596, a85parse_register_16_bit_token = 610 + a85parse_literal_name_nows_token = 441, + a85parse_singlequote_string_token = 483, a85parse_integer_token = 490, + a85parse_literal_name_token = 535, a85parse_real_token = 537, + a85parse_register_8_bit_token = 593, a85parse_register_16_bit_token = 607 } a85parse_token_type; typedef struct a85parse_pcb_struct{ diff --git a/src/a85parse.syn b/src/a85parse.syn index 048ed61..fbee7a9 100644 --- a/src/a85parse.syn +++ b/src/a85parse.syn @@ -124,7 +124,7 @@ preprocessor directive -> "endif", WS?..., comment = gAsm->preproc_endif(); -> "error", literal string, WS?..., comment = {if (gAsm->preproc_error(ss[ss_idx--])) gAbort = TRUE;} -> "undef", literal name nows, WS?..., comment = gAsm->preproc_undef(ss[ss_idx--]); - -> "define", macro definition, WS?..., + -> "define", macro, WS?..., macro expansion, WS?..., comment = { if (gMacroStack[ms_idx] != 0) { delete gMacroStack[ms_idx]; \ gMacroStack[ms_idx] = 0; } \ gMacro = gMacroStack[--ms_idx]; \ @@ -132,11 +132,11 @@ preprocessor directive gAsm->preproc_define(); \ gMacroStack[ms_idx] = 0; gDefine = 0; } -macro definition - -> literal name nows, '(', parameter list, ')' = { if (gAsm->preproc_macro()) \ - PCB.reduction_token = a85parse_WS_token; } - -> literal name nows = { if (gAsm->preproc_macro()) \ - PCB.reduction_token = a85parse_WS_token; } +//macro definition +// -> literal name nows, '(', parameter list, ')' = { if (gAsm->preproc_macro()) \ +// PCB.reduction_token = a85parse_WS_token; } +// -> literal name nows = { if (gAsm->preproc_macro()) \ +// PCB.reduction_token = a85parse_WS_token; } macro -> literal name nows, '(', expression list, ')' = { gMacro->m_ParamList = gExpList; \ @@ -968,15 +968,17 @@ void syntax_error(const char *token_name) #define TAB_SPACING gTabSize #define GET_INPUT {(PCB).input_code = (gAsm->m_fd != 0 && !gAbort) ? \ - fgetc(gAsm->m_fd) : 0; if ((PCB).input_code == 13) (PCB).input_code = fgetc(gAsm->m_fd);\ - } + gAsm->preprocessor() : 0; } + +// fgetc(gAsm->m_fd) : 0; if ((PCB).input_code == 13) (PCB).input_code = fgetc(gAsm->m_fd);\ +// } #define SYNTAX_ERROR { syntax_error(TOKEN_NAMES[(PCB).error_frame_token]); } /* #define SYNTAX_ERROR {MString string; if ((PCB).error_frame_token != 0) \ string.Format("Error in line %d(%s), column%d: Malformed %s - %s", \ - (PCB).line, gFilename, (PCB).column, \ + (PCB).line, gFilename, (PCB).column, \* TOKEN_NAMES[(PCB).error_frame_token], (PCB).error_message); \ else if (strcmp("Unexpected '\\n'", (PCB).error_message) == 0) \ string.Format("Error in line %d(%s), column %d: Unexpected end of line", \ diff --git a/src/assemble.cpp b/src/assemble.cpp index fcd6657..c3c63ac 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -172,6 +172,21 @@ VTAssembler::~VTAssembler() delete m_ActiveSegLines; } +/* +============================================================================ +Implement a pre-processor to handle macro substitution. +============================================================================ +*/ +int VTAssembler::preprocessor(void) +{ + int ch; + + ch = fgetc(m_fd); + if (ch == 13) + ch = fgetc(m_fd); + return ch; +} + void VTAssembler::SetStdoutFunction(void *pContext, stdOutFunc_t pFunc) { m_pStdoutFunc = pFunc; @@ -2562,6 +2577,8 @@ This is the preprocessor function to handle conditional DEFINE statements */ void VTAssembler::preproc_define() { + int count, c; + // Update line number m_Line = (PCB).line; @@ -2577,9 +2594,52 @@ void VTAssembler::preproc_define() pInst->m_Address = m_ActiveSeg->m_Address; pInst->m_FileIndex = m_FileIndex; // Save index of the current file + // Convert equations with a single variable into a simple literal + if (gMacro->m_ParamList != NULL) + { + count = gMacro->m_ParamList->GetSize(); + for (c =0; c < count; c++) + { + CExpression* pExp = (CExpression *) gMacro->m_ParamList->GetAt(c); + if (pExp->m_Equation != NULL && pExp->m_Equation->m_OperationArray.GetSize() == 1) + { + // Okay, we have an equation with a single operation. Check if it's a variable + if (pExp->m_Equation->m_OperationArray[0].m_Operation == RPN_VARIABLE) + { + // Convert the variable into a literal expression + pExp->m_Literal = pExp->m_Equation->m_OperationArray[0].m_Variable; + + // Now delete the equation + delete pExp->m_Equation; + pExp->m_Equation = NULL; + } + } + } + } + // Add the macro to our array of defines m_Defines.Add(gMacro); + if (gMacro->m_ParamList == NULL) + printf("Macro %s = '%s'\n", (const char *) gMacro->m_Name, (const char *) gMacro->m_DefString); + else + { + printf("Macro %s(", (const char *) gMacro->m_Name); + count = gMacro->m_ParamList->GetSize(); + for (c =0; c < count; c++) + { + CExpression* pExp = (CExpression *) gMacro->m_ParamList->GetAt(c); + if (pExp->m_Literal != "") + { + if (c == count-1) + printf("%s", (const char *) pExp->m_Literal); + else + printf("%s, ", (const char *) pExp->m_Literal); + } + } + printf(") = '%s'\n", (const char *) gMacro->m_DefString); + } + // Add new instruction to the instruction list and create new expression list gMacro = new CMacro; // Create a new macro object m_Instructions->Add(pInst); diff --git a/src/assemble.h b/src/assemble.h index bd6b5ad..ed9ce57 100644 --- a/src/assemble.h +++ b/src/assemble.h @@ -371,6 +371,8 @@ class VTAssembler : public VTObject VTAssembler(); ~VTAssembler(); + int preprocessor(void); + // Define Preprocessor functions void preproc_endif(void); void preproc_ifndef(const char *name); diff --git a/src/linker.cpp b/src/linker.cpp index 8c292c8..a618a43 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -2563,6 +2563,39 @@ int VTLinker::GenerateMapFile(void) return TRUE; } +/* +============================================================================ +Back annotate listing files with actual addresses from the link. +============================================================================ +*/ +int VTLinker::BackAnnotateListingFiles(void) +{ + POSITION pos; + CObjFile* pObjFile; +// CObjFileSection* pFileSect; + MString err, filename; + + // Exit if error has occurred + if (m_Errors.GetSize() != 0) + return FALSE; + + // Test if list file generation requested + if (m_LinkOptions.Find((char *) "-t") == -1) + return FALSE; + + // Loop for all object files loaded and locate any that have not been located yet + pos = m_ObjFiles.GetStartPosition(); + while (pos != NULL) + { + // Get pointer to this object file's data + m_ObjFiles.GetNextAssoc(pos, filename, (VTObject *&) pObjFile); + + // Get the path of the source file for this object file + } + + return TRUE; +} + /* ============================================================================ The parser calls this function to perform the link operation after all @@ -2604,6 +2637,7 @@ int VTLinker::Link() GenerateMapFile(); // Back annotate Listing files with actual addresses + BackAnnotateListingFiles(); return m_Errors.GetSize() == 0; } diff --git a/src/linker.h b/src/linker.h index d077942..23cf11f 100644 --- a/src/linker.h +++ b/src/linker.h @@ -272,6 +272,7 @@ class VTLinker : public VTObject MString MakeTitle(const MString& path); int GenerateOutputFile(void); int GenerateMapFile(void); + int BackAnnotateListingFiles(void); public: // Public Access functions From c366b56eff5df06ec296748b9317c111831b0693 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 29 Jan 2013 17:45:48 +0000 Subject: [PATCH 196/327] Removed ancient Makefile that hasn't been updated since the stone age (we use GNUMakefile). --- Makefile | 53 ----------------------------------------------------- 1 file changed, 53 deletions(-) delete mode 100644 Makefile diff --git a/Makefile b/Makefile deleted file mode 100644 index 78a2b9c..0000000 --- a/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -#-include $(shell uname).mk -CFLAGS += -O6 -#CFLAGS += -g - -FLTKCONFIG ?= fltk-config -CFLAGS += `$(FLTKCONFIG) --cflags --use-images` -LDFLAGS += `$(FLTKCONFIG) --ldstaticflags --use-images` - -m100emu: doins.o io.o genwrap.o display.o m100emu.o disassemble.o file.o memory.o m100rom.o intelhex.o setup.o serial.o periph.o GNUmakefile - gcc -o m100emu doins.o genwrap.o io.o display.o m100emu.o disassemble.o file.o memory.o m100rom.o intelhex.o setup.o serial.o periph.o $(LDFLAGS) - -m100emu.o: m100emu.c cpu.h doins.h display.h genwrap.h do_instruct.h GNUmakefile - gcc $(CFLAGS) -c m100emu.c -o m100emu.o - -doins.o: doins.c doins.h cpu.h io.h m100emu.h GNUmakefile - gcc $(CFLAGS) -c doins.c -o doins.o - -genwrap.o: genwrap.c genwrap.h gen_defs.h GNUmakefile - gcc $(CFLAGS) -c genwrap.c -o genwrap.o - -io.o: cpu.h gen_defs.h io.h io.c GNUmakefile - gcc $(CFLAGS) -c io.c -o io.o - -display.o: display.cpp display.h io.h m100emu.h GNUmakefile - g++ $(CFLAGS) -c display.cpp -o display.o - -disassemble.o: disassemble.cpp m100emu.h disassemble.h m100rom.h io.h GNUmakefile - g++ $(CFLAGS) -c disassemble.cpp -o disassemble.o - -file.o: file.cpp memory.h roms.h intelhex.h m100emu.h GNUmakefile - gcc $(CFLAGS) -c file.cpp -o file.o - -memory.o: memory.c genwrap.h GNUmakefile - gcc $(CFLAGS) -c memory.c -o memory.o - -m100rom.o: m100rom.c roms.h GNUmakefile - gcc $(CFLAGS) -c m100rom.c -o m100rom.o - -intelhex.o: intelhex.c intelhex.h GNUmakefile - gcc $(CFLAGS) -c intelhex.c -o intelhex.o - -setup.o: setup.cpp setup.h m100emu.h io.h serial.h GNUmakefile - gcc $(CFLAGS) -c setup.cpp -o setup.o - -serial.o: serial.c serial.h setup.h display.h m100emu.h GNUmakefile - gcc $(CFLAGS) -c serial.c -o serial.o - -periph.o: periph.cpp periph.h serial.h setup.h display.h m100emu.h disassemble.h GNUmakefile - gcc $(CFLAGS) -c periph.cpp -o periph.o - -clean: - rm *.o - rm m100emu From c155635b9063ef57486d5af08f982f34a3eb1dcd Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 30 Jan 2013 14:26:26 +0000 Subject: [PATCH 197/327] Modified GNUmakefile to remove manual dependenies and calculate them automatically, plus switched to wildcard searches for selection of source files for virtualt target. --- GNUmakefile | 188 +++++++++++++++++++--------------------------------- 1 file changed, 68 insertions(+), 120 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 5e002ee..556a2e7 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -12,10 +12,17 @@ -include $(shell uname).mk -CFLAGS += -I src/FLU -O2 -CPPFLAGS += -I src -O2 -EXECUTABLE = virtualt -CLIENT = vt_client +# ==================================== +# Define base gcc compiler environment +# ==================================== +SRCDIR = src +OBJDIR = obj +DEPDIR = .dep +CFLAGS += -I $(SRCDIR)/FLU -O2 $(DEBUG) +CPPFLAGS += -I $(SRCDIR) -O2 $(DEBUG) +VIRTUALT = virtualt +CLIENT = vt_client +CC = $(CROSS_COMPILE)gcc # ============================= # Find the FLTK libs @@ -36,7 +43,9 @@ CPPFLAGS += -I$(FLTKDIR) endif endif -VPATH = src:obj +# ================================ +# Define our linker flags and libs +# ================================ LDFLAGS += -L/usr/X11R6/lib LIBFILES = -lstdc++ -lfltk_images -lfltk_jpeg -lfltk_png -lfltk_z -lfltk -lm -lc -lX11 -lpthread @@ -46,44 +55,51 @@ LIBFILES = -lstdc++ -lfltk_images -lfltk_jpeg -lfltk_png -lfltk_z -lfltk -lm -lc MACLDFLAGS = $(shell $(FLTKCONFIG) --ldflags) -arch i386 -arch ppc MACLIBFILES = -lstdc++ `$(FLTKCONFIG) --ldstaticflags --use-images` --lm -lpthread -# ============================= -# General make rules -# ============================= -OBJECTS = $(SOURCES:.c=.o) -OBJECTSCPP = $(SOURCESCPP:.cpp=.o) -CLIENT_OBJS = $(CLIENT_SRC:.cpp=.o) -OBJDIR = obj +# ==================================== +# Define all source files for VirtualT +# ==================================== +VT_SOURCES = $(wildcard $(SRCDIR)/*.c) $(wildcard $(SRCDIR)/*.cpp) +VT_EXCLUDES = inet_pton.c clientsocket.cpp vt_client_main.cpp +SOURCES = $(filter-out $(VT_EXCLUDES),$(patsubst $(SRCDIR)/%,%,$(VT_SOURCES))) +# ================================= +# Define source files for vt_client +# ================================= +CLIENT_SRC = clientsocket.cpp vt_client_main.cpp socket.cpp # ============================= -# Define all source files below +# Define the object files # ============================= -SOURCES = m100emu.c doins.c genwrap.c serial.c intelhex.c memory.c m100rom.c \ - m200rom.c n8201rom.c romstrings.c sound.c io.c m10rom.c kc85rom.c -SOURCESCPP = display.cpp setup.cpp periph.cpp disassemble.cpp file.cpp memedit.cpp cpuregs.cpp \ - a85parse.cpp assemble.cpp MString.cpp MStringArray.cpp rpn_eqn.cpp vtobj.cpp \ - Flu_DND.cpp flu_pixmaps.cpp Flu_Tree_Browser.cpp FluSimpleString.cpp ide.cpp \ - multiwin.cpp multiwin_icons.cpp project.cpp multieditwin.cpp rememcfg.cpp \ - fl_usage_box.cpp remote.cpp socket.cpp serversocket.cpp lpt.cpp printer.cpp \ - fileprint.cpp hostprint.cpp fx80print.cpp chargen.cpp fl_action_icon.cpp fx80rom.cpp \ - vtpaper.cpp autofile.cpp clock.cpp fileview.cpp Flu_Wrap_Group.cpp \ - Flu_Button.cpp Flu_Combo_Box.cpp Flu_Combo_List.cpp Flu_Combo_Tree.cpp Flu_File_Chooser.cpp \ - flu_file_chooser_pixmaps.cpp Flu_Label.cpp Flu_Return_Button.cpp Flu_Separator.cpp \ - highlight.cpp idetabs.cpp linker.cpp My_Text_Display.cpp My_Text_Editor.cpp \ - socketdlg.cpp tpddclient.cpp pref_form.cpp +OBJTMP = $(SOURCES:.c=.o) +OBJTMP2 = $(OBJTMP:.cpp=.o) +OBJECTS = $(patsubst %,$(OBJDIR)/%,$(OBJTMP2)) -CLIENT_SRC = clientsocket.cpp vt_client_main.cpp socket.cpp +# Objects for the vt_client +CLIENT_OTMP = $(CLIENT_SRC:.cpp=.o) +CLIENT_OBJS = $(patsubst %,$(OBJDIR)/%,$(CLIENT_OTMP)) + +# ========================================== +# Declare auto-generated dependencies rules +# ========================================== +OTMP = $(OBJECTS) $(CLIENT_OBJS) +DEPS = $(patsubst $(OBJDIR)/%.o,$(DEPDIR)/%.d,$(OTMP)) + +# =========================================================== +# Rule for building all exectuables. Must be the 1st target. +# =========================================================== +all: init $(VIRTUALT) $(CLIENT) -# =============================== -# Rule for building 2 exectuables -# =============================== -all: virtualt vt_client +init: + @mkdir -p $(DEPDIR) + @mkdir -p $(OBJDIR) + +#Include our built dependencies +-include $(DEPS) # ======================== # Rule to build VirtualT # ======================== -$(EXECUTABLE): $(OBJECTS) $(OBJECTSCPP) - +$(VIRTUALT): $(OBJECTS) ifndef FLTKLIB @echo "FLTKDIR environment variable must be set first!" @echo "Or install the FLTK libraries" @@ -94,17 +110,17 @@ else echo "Please ensure the FLTK, JPEG, PNG and ZLIB libraries and run make again"; \ exit 1; \ fi; - @echo "Linking" $(EXECUTABLE) + @echo "Linking" $(VIRTUALT) if test -f /Developer/Tools/Rez; then \ - cd obj; g++ $(MACLDFLAGS) $(OBJECTS) $(OBJECTSCPP) $(MACLIBFILES) -o ../$@ ; \ + g++ $(MACLDFLAGS) $(OBJECTS) $(MACLIBFILES) -o $@ ; \ else \ - cd obj; gcc $(LDFLAGS) $(OBJECTS) $(OBJECTSCPP) $(LIBFILES) -o ../$@ ; \ + $(CC) $(LDFLAGS) $(OBJECTS) $(LIBFILES) -o $@ ; \ fi; cd .. # If bulding on MacOS, post the resource file to the executable if test -f /Developer/Tools/Rez; then \ - $(POSTBUILD) $(EXECUTABLE); \ + $(POSTBUILD) $(VIRTUALT); \ fi; endif @@ -118,115 +134,47 @@ ifndef FLTKLIB exit 1 else @echo "Linking" $(CLIENT) -# cd obj; gcc $(LDFLAGS) $(OBJECTS) $(OBJECTSCPP) $(LIBFILES) -o ../$@ if test -f /Developer/Tools/Rez; then \ - cd obj; g++ $(MACLDFLAGS) $(CLIENT_OBJS) $(MACLIBFILES) -o ../$@ ; \ + g++ $(MACLDFLAGS) $(CLIENT_OBJS) $(MACLIBFILES) -o $@ ; \ else \ - cd obj; gcc $(LDFLAGS) $(CLIENT_OBJS) $(LIBFILES) -o ../$@ ; \ + $(CC) $(LDFLAGS) $(CLIENT_OBJS) $(LIBFILES) -o $@ ; \ fi cd .. endif - -# =============================== -# Rule for compiling source files -# =============================== -.cpp.o: +# ============================================================ +# Rule for compiling source files. Define rule for CPP first. +# ============================================================ +$(OBJDIR)/%.o: $(SRCDIR)/%.cpp ifndef FLTKLIB @echo "FLTKDIR environment variable must be set first!" @echo "Or install the FLTK libraries" exit 1 else - @echo "Compiling" $< - -mkdir -p obj; g++ $(CPPFLAGS) -c $< -o obj/$@ + @echo "Compiling" $*.cpp + $(CC) $(CPPFLAGS) -c $< -o $@ + @$(CC) -MM -MT $(OBJDIR)/$*.o $(CPPFLAGS) $(SRCDIR)/$*.cpp > $(DEPDIR)/$*.d endif -.c.o: +# Now the rule for C files +$(OBJDIR)/%.o: $(SRCDIR)/%.c ifndef FLTKLIB @echo "FLTKDIR environment variable must be set first!" @echo "Or install the FLTK libraries" exit 1 else - @echo "Compiling" $< - -mkdir -p obj; gcc $(CFLAGS) -c $< -o obj/$@ + @echo "Compiling" $*.c + $(CC) $(CFLAGS) -c $< -o $@ + @$(CC) -MM -MT $(OBJDIR)/$*.o $(CFLAGS) $(SRCDIR)/$*.c > $(DEPDIR)/$*.d endif - -# ========================================== -# Declare dependencies on header files below -# ========================================== -$(OBJECTS) $(OBJECTSCPP): m100emu.h GNUmakefile VirtualT.h -$(CLIENT_OBJS): socket.h - -disassemble.o: disassemble.h io.h cpu.h periph.h memedit.h romstrings.h -display.o: display.h io.h file.h setup.h periph.h memory.h memedit.h lpt.h clock.h -doins.o: cpu.h io.h -file.o: memory.h roms.h intelhex.h -io.o: cpu.h gen_defs.h io.h serial.h display.h setup.h memory.h lpt.h clock.h -intelhex.o: intelhex.h -m100emu.o: io.h cpu.h doins.h display.h genwrap.h filewrap.h roms.h \ - intelhex.h setup.h memory.h do_instruct.h lpt.h clock.h -memedit.o: memedit.h disassemble.h memory.h cpu.h -memory.o: memory.h cpu.h io.h intelhex.h setup.h -periph.o: periph.h serial.h setup.h display.h disassemble.h lpt.h -serial.o: serial.h setup.h display.h -rememcfg.o: rememcfg.h setup.h display.h -fl_usage_box.o: fl_usage_box.h -setup.o: setup.h io.h serial.h memory.h memedit.h lpt.h clock.h -sound.o: sound.h -m100rom.o m102rom.o m200rom.o n8201rom.o romstrings.o m10rom.o kc85rom.o: roms.h romstrings.h -remote.o: remote.cpp m100emu.h socket.h serversocket.h socketexception.h -socket.o: socket.h -serversocket.o: serversocket.h -lpt.o: lpt.h printer.h fileprint.h hostprint.h fx80print.h vtpaper.h -printer.o: printer.h -fileprint.o: printer.h fileprint.h vtobj.h MString.h -hostprint.o: printer.h hostprint.h vtobj.h MString.h -fx80print.o: printer.h fx80print.h vtpaper.h vtobj.h MString.h -chargen.o: chargen.h -fl_action_icon.o:fl_action_icon.h -fx80rom.o: -vtpaper.o: printer.h vtpaper.h autofile.h -autofile.o: autofile.h -clock.o: clock.h -fileview.o: display.h cpuregs.h disassemble.h fileview.h periph.h memedit.h file.h - -# ========== -# asm files -# ========== -a85parse.o: a85parse.h assemble.h -assemble.o: assemble.h -MString.o: MString.h -MStringArray.o: MStringArray.h MString.h -rpn_eqn.o: rpn_eqn.h -vtobj.o: vtobj.h - -# ========== -# ide files -# ========== -Flu_DND.o: FLU/Flu_DND.h -flu_pixmaps.o: FLU/flu_pixmaps.h -Flu_Tree_Browser.o: FLU/Flu_Tree_Browser.h -FluSimpleString.o: FLU/FluSimpleString.h -ide.o: ide.h vtobj.h multiwin.h multieditwin.h -multiwin.o: multiwin.h vtobj.h -multiwin.o: multieditwin.h multiwin.h vtobj.h -multiwin_icons.o: multiwin_icons.h -project.o: project.h - -# ========== -# client files -# ========== -clientsocket.o: clientsocket.h socket.h -vt_client_main.o: clientsocket.h socket.h - # ============================= # Rule to clean all build files # ============================= clean: @echo "=== cleaning ==="; @echo "Objects..." - cd obj; rm -f *.o; cd ..; + @rm -rf $(OBJDIR) $(DEPDIR) @echo "Executables..." rm -f virtualt rm -f vt_client From dc3a4f2e0de23ef3a0cf686f0c6976f9f9bd9f3e Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 30 Jan 2013 16:14:33 +0000 Subject: [PATCH 198/327] Added auto-wrap at EOL to FX80 printer emulation. --- src/fx80print.cpp | 31 ++++++++++++++++++++++++++++--- src/fx80print.h | 2 ++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/fx80print.cpp b/src/fx80print.cpp index 305ff71..51c5842 100644 --- a/src/fx80print.cpp +++ b/src/fx80print.cpp @@ -97,6 +97,7 @@ VTFX80Print::VTFX80Print(void) m_useRomFile = FALSE; m_useRamFile = FALSE; + m_autoWrap = FALSE; m_marksMade = FALSE; m_defSkipPerf = TRUE; m_defCompressed = FALSE; @@ -580,13 +581,19 @@ void VTFX80Print::BuildPropertyDialog(Fl_Window* pParent) g->end(); // Create control for setting the Top of Form - o = new Fl_Box(400, 270, 60, 20, "Top of Form"); + o = new Fl_Box(400, 250, 60, 20, "Top of Form"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); - m_pTopOfForm = new Fl_Input(510, 270, 60, 20, ""); + m_pTopOfForm = new Fl_Input(510, 250, 60, 20, ""); m_pTopOfForm->value(m_topOfFormStr); - o = new Fl_Box(575, 270, 60, 20, "inches from top"); + o = new Fl_Box(575, 250, 60, 20, "inches from top"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + // Create checkbox for auto-word wrap (not a feature of original FX-80) + m_pAutoWrap = new Fl_Check_Button(400, 280, 230, 20, "Auto wrap (CR/LF at end of line)"); + m_pAutoWrap->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pAutoWrap->value(m_autoWrap); + + // Button for Character Generator b = new Fl_Button(360, 310, 120, 30, "Char Generator"); b->callback(cb_CreateNewCharGen); } @@ -669,6 +676,7 @@ void VTFX80Print::Init(void) m_sRamFile = temp; m_pPref->get("FX80Print_PaperName", temp, "", 512); m_paperName = temp; + m_pPref->get("FX80Print_AutoWrap", m_autoWrap, 0); // Get DIP switch settings m_pPref->get("FX80Print_AutoCR", c, 0); @@ -812,6 +820,7 @@ int VTFX80Print::GetProperties(void) // Get values from the dialog controls m_useRomFile = m_pUseRomFile->value(); m_useRamFile = m_pUseRamFile->value(); + m_autoWrap = m_pAutoWrap->value(); if (m_pRomFile->value() != 0) m_sRomFile = m_pRomFile->value(); @@ -842,6 +851,7 @@ int VTFX80Print::GetProperties(void) m_pPref->set("FX80Print_RamFile", (const char *) m_sRamFile); m_pPref->set("FX80Print_PaperName", (const char *) m_paperName); c = m_defCharSet; + m_pPref->set("FX80Print_AutoWrap", m_autoWrap); m_pPref->set("FX80Print_IntlCharSet", c); c = m_autoCR; m_pPref->set("FX80Print_AutoCR", c); @@ -1215,6 +1225,7 @@ void VTFX80Print::RenderChar(unsigned char byte) int xpos2; // Used for locating enhanced dots double scalar; int proportionAdjust; + int charWidth; // Indicate marks made on the page m_marksMade = TRUE; @@ -1261,6 +1272,20 @@ void VTFX80Print::RenderChar(unsigned char byte) // For expanded mode, we must expand the pins out twice as far dotsPerPin = (m_expanded || m_expandedOneLine) ? 2 : 1; + // Calculate the width of this character + charWidth = (int) ((double) ((last - first + 1 + proportionAdjust) * dotsPerPin) * scalar); + + // Test if auto-wrap is enabled and we need to wrap + if (m_autoWrap && (m_curX + charWidth >= m_horizDots)) + { + // Update X and Y locations + m_curX = m_leftMarginX; + m_curY += (int) (m_lineSpacing * m_vertDpi + 0.25); + + // Check for new page + ProcessLineFeed(); + } + // Loop through all bytes to be rendered for (c = first; c <= last; c++) { diff --git a/src/fx80print.h b/src/fx80print.h index 4083bb8..ad9aaa2 100644 --- a/src/fx80print.h +++ b/src/fx80print.h @@ -90,6 +90,7 @@ class VTFX80Print : public VTPrinter Fl_Input* m_pRamFile; // File to initialize CharRAM from Fl_Check_Button* m_pUseRomFile; // Checkbox to use ROM initialization Fl_Check_Button* m_pUseRamFile; // Checkbox to use RAM initialization + Fl_Check_Button* m_pAutoWrap; // Checkbox for auto-wrap at last col Fl_Button* m_pRomBrowse; // Browse button for ROM file Fl_Button* m_pRamBrowse; // Browse button for RAM file Fl_Choice* m_pPaperChoice; // Control to select the paper source @@ -170,6 +171,7 @@ class VTFX80Print : public VTPrinter MString m_sRamFile; // File to load Char RAM MString m_paperName; // Name of seleted paper int m_selectedPaper; + int m_autoWrap; // TRUE if auto-wrap at last col enabled // Define functions used for handling the FX-80 protocol virtual void ResetMode(void); // Resets the FX-80 "printer" settings From dd9e9413f7117079a4ba383a45341461e43a4e5d Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 30 Jan 2013 16:29:16 +0000 Subject: [PATCH 199/327] Modified CPU speed indicator to show 2 decimal places if speed < 10 Mhz. --- src/display.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/display.cpp b/src/display.cpp index 4237d86..ed2112c 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -2248,7 +2248,10 @@ static char mapStr[40]; void display_cpu_speed(void) { - sprintf(label, "%4.1f Mhz", cpu_speed + .05); + if (cpu_speed + 0.5 < 10.0) + sprintf(label, "%4.2f Mhz", cpu_speed); + else + sprintf(label, "%4.1f Mhz", cpu_speed + .05); Fl::check(); gpSpeed->label(label); } @@ -3255,7 +3258,6 @@ int T100_Disp::handle(int event) case FL_DND_RELEASE: return 1; case FL_PASTE: - printf("PASTE: %s", Fl::event_text()); if (IsInMenu() == 1) remote_load_from_host(Fl::event_text()); return 1; From 5e6ed44849ea65a8a7faa9290c3793ec06a4a816 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 30 Jan 2013 17:27:34 +0000 Subject: [PATCH 200/327] Fixed issue with newly added (debug) logic which captures LCD driver data to a file via CODE+GRAPH+SHIFT keystroke. --- src/io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/io.c b/src/io.c index 0f503cc..c2f3702 100644 --- a/src/io.c +++ b/src/io.c @@ -264,12 +264,13 @@ void update_keys(void) } } - if (gSpecialKeys & (MT_GRAPH | MT_CODE | MT_SHIFT) && !gCapture) + if ((gSpecialKeys & (MT_GRAPH | MT_CODE | MT_SHIFT) == 0) && !gCapture) { FILE* fd; int d, col, row; gCapture = TRUE; + printf("capture 0x%0x\n", gSpecialKeys); fd = fopen("lcd_cap.txt", "w"); if (fd != NULL) { From 926c9f3fc4f842352687fadfbdbc8651441b59a2 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 30 Jan 2013 18:04:18 +0000 Subject: [PATCH 201/327] Removed debug print in io.c that was left behind accidentally. --- src/io.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/io.c b/src/io.c index c2f3702..66451b8 100644 --- a/src/io.c +++ b/src/io.c @@ -270,7 +270,6 @@ void update_keys(void) int d, col, row; gCapture = TRUE; - printf("capture 0x%0x\n", gSpecialKeys); fd = fopen("lcd_cap.txt", "w"); if (fd != NULL) { From 8bf43f8515d5e17c332cbbe7da3c63e10c3caccb Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 30 Jan 2013 19:00:59 +0000 Subject: [PATCH 202/327] Made the FX80 Virtual Paper display resizable. --- src/vtpaper.cpp | 24 +++++++++++++++++------- src/vtpaper.h | 1 + 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/vtpaper.cpp b/src/vtpaper.cpp index 2cb4e26..ecab919 100644 --- a/src/vtpaper.cpp +++ b/src/vtpaper.cpp @@ -88,6 +88,9 @@ VTVirtualPaper::VTVirtualPaper() : m_pScroll->linesize(12); m_pScroll->callback(cb_VTPaperScroll, this); m_topPixel = 0; + Fl_Button* o = new Fl_Button(0, 0, 1, 1, ""); + o->hide(); + resizable(o); } /* @@ -220,7 +223,7 @@ void VTVirtualPaper::DrawPage(int pageNum) { if (data & mask) { - xpos = (c<<3) + b + 15; + xpos = (c<<3) + b + m_leftPixel+5; fl_point(xpos, ypos); fl_point(xpos+1, ypos); fl_point(xpos, ypos+1); @@ -248,23 +251,30 @@ void VTVirtualPaper::draw(void) double offset; VTVirtualPage* pVPage= NULL; int pageBottom; + int rightPixel; // Draw child objects, etc Fl_Double_Window::draw(); + // Calculate the left edge of the page + m_leftPixel = ((w()-1015)>>1) + 10; + rightPixel = m_leftPixel+975; + // Draw left border fl_color(FL_GRAY); - fl_rectf(0, 0, 10, h()); - fl_rectf(w()-25, 0, 10, h()); + fl_rectf(0, 0, m_leftPixel, h()); + //fl_rectf(w()-25, 0, 10, h()); + fl_rectf(rightPixel+5, 0, w()-(rightPixel+20), h()); fl_color(FL_DARK3); - fl_rectf(w()-30, 0, 5, h()); + //fl_rectf(30, 0, 5, h()); + fl_rectf(rightPixel, 0, 5, h()); // Check if page separator needs to be drawn at top if (m_topPixel < 9) { fl_color(FL_GRAY); fl_rectf(0, -m_topPixel, w()-15, 9); - fl_rectf(w()-30, -m_topPixel+9, 5, 5); + fl_rectf(rightPixel, -m_topPixel+9, 5, 5); } // Determine in which page m_topPixel falls @@ -291,9 +301,9 @@ void VTVirtualPaper::draw(void) fl_color(FL_GRAY); fl_rectf(0, pageBottom- m_topPixel, w()-15, 18); fl_color(FL_DARK3); - fl_rectf(15, pageBottom- m_topPixel, w()-40, 5); + fl_rectf(m_leftPixel+5, pageBottom- m_topPixel, rightPixel-m_leftPixel, 5); fl_color(FL_GRAY); - fl_rectf(w()-30, pageBottom - m_topPixel + 18, 5, 5); + fl_rectf(rightPixel, pageBottom - m_topPixel + 18, 5, 5); } // Check if next page needs to be drawn diff --git a/src/vtpaper.h b/src/vtpaper.h index e66e55d..b9307d4 100644 --- a/src/vtpaper.h +++ b/src/vtpaper.h @@ -133,6 +133,7 @@ class VTVirtualPaper : public VTPaper, public Fl_Double_Window char* m_pLineCnts; // Pointer to m_height byte counts int m_pageNum; // Active page number int m_topPixel; // Top pixel on window + int m_leftPixel; // Pixel number of left edge of page Fl_Scrollbar* m_pScroll; }; From 009a87df4c52bb5ee2bcc18dae9294d1726b6b7f Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 30 Jan 2013 19:01:50 +0000 Subject: [PATCH 203/327] Added PHONY targets to GNUmakefile for clean, info, etc. --- GNUmakefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index 556a2e7..e2aaf28 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -89,7 +89,8 @@ DEPS = $(patsubst $(OBJDIR)/%.o,$(DEPDIR)/%.d,$(OTMP)) # =========================================================== all: init $(VIRTUALT) $(CLIENT) -init: +.PHONY: init +init: @mkdir -p $(DEPDIR) @mkdir -p $(OBJDIR) @@ -171,6 +172,7 @@ endif # ============================= # Rule to clean all build files # ============================= +.PHONY: clean clean: @echo "=== cleaning ==="; @echo "Objects..." @@ -183,6 +185,7 @@ clean: # Provide info for building FLTK, Tiger, Leopard versions # Windows, Linux, etc. # ================================================ +.PHONY: info info: @echo @echo "Virtual T make Info" From 349acade3a51c94692516167a2194cfa9d71d31f Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 30 Jan 2013 21:03:05 +0000 Subject: [PATCH 204/327] Updated release.txt file with new additions in version 1.6 (not yet released). --- release.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/release.txt b/release.txt index 41f25aa..239b1dd 100644 --- a/release.txt +++ b/release.txt @@ -20,6 +20,16 @@ v1.6 the standard FLTK tab control and were really ugly, plus had an issue with tab width calculations with regard to mouse presses to select the tab. +4. Updated GNUmakefile to auto-generate dependencies and use wildcard search for + selecting source files vs. specifying everything manually. + +5. Added feature to FX80 printer emulation to perform auto word-wrap selectable via + the printer setup page. + +6. Modified CPU speed indicator to show 2 decimal places precision for speeds less than + 10 MHz. + +7. Made the FX80 Virtual Paper display resizeable. ==================== v1.5 July 9th, 2011 From 6637cf6c4bb3550cd531f92a8dc3bc6c54f21a5e Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 2 Feb 2013 13:43:08 +0000 Subject: [PATCH 205/327] Modified GNUMakefile to prevent -O2 optimization if make called with DEBUG flag set. --- GNUmakefile | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index e2aaf28..620642f 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -18,8 +18,14 @@ SRCDIR = src OBJDIR = obj DEPDIR = .dep -CFLAGS += -I $(SRCDIR)/FLU -O2 $(DEBUG) -CPPFLAGS += -I $(SRCDIR) -O2 $(DEBUG) + +# Optimize only if not debug mode +ifeq ($(DEBUG),) +OPTIMIZE = -O2 +endif + +CFLAGS += -I $(SRCDIR)/FLU $(OPTIMIZE) $(DEBUG) +CPPFLAGS += -I $(SRCDIR) $(OPTIMIZE) $(DEBUG) VIRTUALT = virtualt CLIENT = vt_client CC = $(CROSS_COMPILE)gcc From c58e3a5f7e37e66e1b923c18f4d4375c444b81bb Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 2 Feb 2013 13:44:31 +0000 Subject: [PATCH 206/327] Completed C style macro expansion in assembler. Previously, this was supported by the parser, but no code was present to handle it on the back end. --- src/assemble.cpp | 397 ++++++++++++++++++++++++++++++++++++++++++++--- src/assemble.h | 12 ++ 2 files changed, 387 insertions(+), 22 deletions(-) diff --git a/src/assemble.cpp b/src/assemble.cpp index c3c63ac..675a3ac 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -141,6 +141,9 @@ VTAssembler::VTAssembler() m_MsbFirst = FALSE; m_LocalModuleChar = '_'; m_ActiveSeg = ASEG; + m_pInPtr = NULL; + m_InLineCount = 4096; + m_pInLine = new char[m_InLineCount]; // Create a new symbol module m_ActiveMod = new CModule("basemod"); @@ -167,11 +170,327 @@ VTAssembler::~VTAssembler() { ResetContent(); + delete m_pInLine; delete m_ActiveMod; delete m_ActiveSeg; delete m_ActiveSegLines; } +/* +============================================================================ +Perform macro substitution of the specified Macro at the location specified +within the m_pInLine string. +============================================================================ +*/ +int VTAssembler::PerformSubstitution(CMacro* pMacro, const char *pLoc) +{ + int args_needed, args_found, c; + const char *pEndName, *pEnd, *ptr; + const char *pArgs[64]; + int argLen[64], len, paren, quote, subst; + char *pNewLine, *pNew; + char quoteChar, ch, lastCh; + MString err; + CExpression *pExp; + + // Calculate some control variables + args_needed = args_found = 0; + if (pMacro->m_ParamList != NULL) + args_needed = pMacro->m_ParamList->GetSize(); + pEndName = pLoc + pMacro->m_Name.GetLength(); + + // Allocate storage for a new line and copy bytes up to the macro text + pNewLine = new char[m_InLineCount]; + for (pNew = pNewLine, ptr = m_pInLine; ptr != pLoc; ptr++, pNew++) + *pNew = *ptr; + + // Find all arguments in the macro invocation. First skip white space + len = paren = quote = 0; + ptr = pEndName; + while (*ptr == ' ' || *ptr == '\t') + ptr++; + if (*ptr == '(') + { + // Skip the opening '(' + ptr++; + + // Keep looping until we reach the terminating paren or EOL + while (*ptr != ')' && *ptr != '\n' && *ptr != '\0') + { + // Save pointer to next arg + pArgs[args_found] = ptr; + + // Test for end of argument + while ((*ptr != ',' && *ptr != ')') || ((quote || paren) && + (*ptr != '\n' && *ptr != '\0'))) + { + // Increment argument length + len++; + + // Test for parenthesis within arg + if (*ptr == '(') + { + // If not in a quote, increment the paren depth + if (!quote) + paren++; + } + else if (*ptr == ')') + { + // If not in a quote, decrement the paren depth + if (!quote) + paren--; + } + else if (*ptr == '"') + { + // Test if we are in a quote block or not + if (!quote) + { + quote = TRUE; + quoteChar = '"'; + } + else if (quoteChar == '"') + quote = FALSE; + } + else if (*ptr == '\'') + { + // Test if we are in a quoted block or not + if (!quote) + { + quote = TRUE; + quoteChar = '\''; + } + else if (quoteChar == '\'') + quote = FALSE; + } + else if (*ptr == '\\') + { + // Escape character. Just skip past the escaped char + ptr++; + len++; + } + + // Increment to next character + ptr++; + } + + // Save length of this argument and increment args_found + argLen[args_found++] = len; + len = 0; + + // If not ')', skip to next non-white and save ptr to next arg + if (*ptr == ',') + { + // Advance to byte after ',' + ptr++; + } + } + + // Validate we found the terminating ')' + if (*ptr != ')') + { + // Error, no terminating ')' in macro invocation + err.Format("Error in line %d(%s): Expected terminating ')' for macro %s", + m_Line, gFilename, (const char *) pMacro->m_Name); + m_Errors.Add(err); + + delete[] pNewLine; + return PREPROC_STAT_ERROR; + } + + // Set the end of the macro based on the ptr + pEnd = ptr + 1; + } + else + { + // Set the macro end to the end of the name (no args) + pEnd = pEndName; + } + + // Check if macro invocation has correct number of arguments + if (args_found != args_needed) + { + // Incorrect number of arguments + if (args_found < args_needed) + err.Format("Error in line %d(%s): Too few arguments for macro %s", + m_Line, gFilename, (const char *) pMacro->m_Name); + else + err.Format("Error in line %d(%s): Too many arguments for macro %s", + m_Line, gFilename, (const char *) pMacro->m_Name); + m_Errors.Add(err); + + // Return an error code indicating we should skip processing on this line + delete[] pNewLine; + return PREPROC_STAT_ERROR; + } + + // Test if the character before the macro name is '#' and remove if it is + if (pNew != pNewLine) + { + if (*(pNew-1) == '#') + pNew--; + } + + // Now scan the macro's DefString and copy performing substitutions + ptr = (const char *) pMacro->m_DefString; + lastCh = ' '; + if (pMacro->m_ParamList == NULL) + { + // Perform simple substitution + while (*ptr != '\0') + *pNew++ = *ptr++; + } + else + { + // Perform parameterized replacement + while (*ptr != '\0') + { + subst = FALSE; + + // Test if any of the parameters match at the current pointer + for (c = 0; c < args_needed; c++) + { + // Test next parameter + pExp = (CExpression *) pMacro->m_ParamList->GetAt(c); + if (strncmp(ptr, (const char *) pExp->m_Literal, pExp->m_Literal.GetLength()) == 0) + { + // We found a match. Test for sub-string match + ch = *(ptr + pExp->m_Literal.GetLength()); + if ((ch >= 'A' && ch <= 'a') || (ch >= 'a' && ch <= 'z') || (ch == '_')) + continue; + + // Match found. Test for '#' before param and remove from dest + if (lastCh == '#') + pNew--; + + // Advance the pointer past the parameter + ptr += pExp->m_Literal.GetLength(); + + // Copy the replacement text to the new string + strcpy(pNew, pArgs[c]); + pNew += argLen[c]; + subst = TRUE; + + // Break the for loop ... we found the arg + break; + } + } + + // If we didn't perform substitution above, then copy the char to the new line as-is + if (!subst) + *pNew++ = *ptr++; + } + } + + // Copy the remaining text to the new buffer + ptr = pEnd; + while (*ptr != '\0') + *pNew++ = *ptr++; + *pNew = '\0'; + + //printf("New line = %s", pNewLine); + + // Delete the old m_pInLine and replace with the new one + delete[] m_pInLine; + m_pInLine = pNewLine; + + return PREPROC_STAT_SUBST; +} + +/* +============================================================================ +Perform macro substitution on the text in m_pInLine +============================================================================ +*/ +int VTAssembler::MacroSubstitution(void) +{ + int count, c, len, quotes, comment; + char ch_l, ch_r, quote_ch; + CMacro* pMacro; + const char *pStr, *pQstr; + + // Loop through all known macros and search for that name in the line + count = m_Defines.GetSize(); + for (c = 0; c < count; c++) + { + // Get pointer to next macro + pMacro = (CMacro *) m_Defines[c]; + len = pMacro->m_Name.GetLength(); + + // Test if this macro name found in the current line + if ((pStr = strstr(m_pInLine, (const char *) pMacro->m_Name)) != NULL) + { + ch_l = ' '; + + // Okay, this macro name was found. Now check if it is actually + // a macro substitution or not. It could be enclosed in quotes or + // just a sub-string match, etc. + if (pStr != m_pInLine) + { + // Test for sub-string matches + ch_l = *(pStr - 1); + if ((ch_l >= 'A' && ch_l <= 'Z') || (ch_l >= 'a' && ch_l <= 'z')) + continue; + if ((ch_l >= '0' && ch_l <= '9') || (ch_l == '_')) + continue; + } + + // Get character to the right of the string and test for sub-string match + ch_r = *(pStr + len); + if ((ch_r >= 'A' && ch_r <= 'Z') || (ch_r >= 'a' && ch_r <= 'z')) + continue; + if ((ch_r >= '0' && ch_r <= '9') || (ch_r == '_')) + continue; + + // Not a sub-string match. Test if it's a quoted string + comment = FALSE; + for (quotes = FALSE, pQstr = m_pInLine; pQstr != pStr; pQstr++) + { + // Check for an escaped quote + if (quotes && *pQstr == '\\') + { + pQstr++; + continue; + } + + // Test for end of quotes + if (quotes && *pQstr == quote_ch) + { + quotes = FALSE; + continue; + } + + // Test for beginning of quotes + if (*pQstr == '"' || *pQstr == '\'') + { + quotes = TRUE; + quote_ch = *pQstr; + } + + // Test for assembly style comment + if (!quotes && *pQstr == ';') + { + comment = TRUE; + break; + } + + // Test for C++ style comment + if (!quotes && *pQstr == '/' && *(pQstr+1) == '/') + { + comment = TRUE; + break; + } + } + if (quotes || comment) + continue; + + // Okay, time to do a substitution + return PerformSubstitution(pMacro, pStr); + } + } + + return FALSE; +} + /* ============================================================================ Implement a pre-processor to handle macro substitution. @@ -179,12 +498,45 @@ Implement a pre-processor to handle macro substitution. */ int VTAssembler::preprocessor(void) { - int ch; + int ret; - ch = fgetc(m_fd); - if (ch == 13) - ch = fgetc(m_fd); - return ch; + // Test if any chars left in current expanded line + if (m_pInPtr) + { + // filter out cr characters + if (*m_pInPtr == 13) + m_pInPtr++; + + // If not at end of line, return the next char + if (*m_pInPtr != '\0') + return *m_pInPtr++; + } + + // Read next line from input file + if (fgets(m_pInLine, m_InLineCount, m_fd) == NULL) + { + // Zero out the line + m_pInPtr = NULL; + return 0; + } + + // Perform macro substitution on the line until no more substitutions left + while ((ret = MacroSubstitution()) == PREPROC_STAT_SUBST) + ; + + // Test for error during macro substitution + if (ret == PREPROC_STAT_ERROR) + { + } + + // Return the 1st char from the expanded line + m_pInPtr = m_pInLine; + + // filter out cr characters + if (*m_pInPtr == 13) + m_pInPtr++; + + return *m_pInPtr++; } void VTAssembler::SetStdoutFunction(void *pContext, stdOutFunc_t pFunc) @@ -292,6 +644,7 @@ void VTAssembler::ResetContent(void) m_Address = 0; m_DebugInfo = 0; m_LastLabelAdded = 0; + m_pInPtr = NULL; // Clean up include stack while (m_IncludeDepth != 0) @@ -1092,10 +1445,16 @@ void VTAssembler::include(const char *filename) memcpy(&m_ParserPCBs[m_IncludeDepth], &a85parse_pcb, sizeof(a85parse_pcb_type)); m_IncludeIndex[m_IncludeDepth] = m_FileIndex; + m_IncludeInLine[m_IncludeDepth] = m_pInLine; + m_IncludeInLineCount[m_IncludeDepth] = m_InLineCount; + m_IncludeInPtr[m_IncludeDepth] = m_pInPtr; m_IncludeStack[m_IncludeDepth++] = m_fd; - // Check if this file already in the m_Filenames list! + m_InLineCount = 4096; + m_pInLine = new char[4096]; + m_pInPtr = NULL; + // TODO: Check if this file already in the m_Filenames list! m_FileIndex = m_Filenames.Add(filename); @@ -1105,8 +1464,14 @@ void VTAssembler::include(const char *filename) a85parse(); fclose(m_fd); + // Delete the m_pInLine + delete m_pInLine; + // Restore the previous FD m_fd = m_IncludeStack[--m_IncludeDepth]; + m_pInPtr = m_IncludeInPtr[m_IncludeDepth]; + m_pInLine = m_IncludeInLine[m_IncludeDepth]; + m_InLineCount = m_IncludeInLineCount[m_IncludeDepth]; m_FileIndex = m_IncludeIndex[m_IncludeDepth]; gFilename = (const char *) m_Filenames[m_FileIndex]; memcpy(&a85parse_pcb, &m_ParserPCBs[m_IncludeDepth], @@ -1742,7 +2107,6 @@ void VTAssembler::directive_aseg() // Set segment of current module m_Segments.Lookup(".aseg", (VTObject *&) pSeg); -// pSeg = (CSegment *) m_Segments[".aseg"]; // Activate the new segment ActivateSegment(pSeg); @@ -2620,6 +2984,8 @@ void VTAssembler::preproc_define() // Add the macro to our array of defines m_Defines.Add(gMacro); + // Test code to print the macros we find +#if 0 if (gMacro->m_ParamList == NULL) printf("Macro %s = '%s'\n", (const char *) gMacro->m_Name, (const char *) gMacro->m_DefString); else @@ -2639,6 +3005,7 @@ void VTAssembler::preproc_define() } printf(") = '%s'\n", (const char *) gMacro->m_DefString); } +#endif // Add new instruction to the instruction list and create new expression list gMacro = new CMacro; // Create a new macro object @@ -3144,7 +3511,6 @@ int VTAssembler::Assemble() pRange = pRange->pNext; } relSeg->m_Reloc.Add(pRel); -// m_ActiveSeg->m_Reloc.Add(pRel); } // Check if operand is extern @@ -3305,12 +3671,6 @@ int VTAssembler::Assemble() pRange = pRange->pNext; } } - else - { -// err.Format("Error in line %d(%s): Equation cannot be evaluated", -// pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); -// m_Errors.Add(err); - } } /* @@ -3477,7 +3837,6 @@ int VTAssembler::Assemble() pRange = pRange->pNext; } relSeg->m_Reloc.Add(pRel); -// m_ActiveSeg->m_Reloc.Add(pRel); } // Check if operand is extern @@ -3527,13 +3886,6 @@ int VTAssembler::Assemble() // Increment address counter based on equation m_Address += (int) value; } - else - { - // Report error -// err.Format("Error in line %d(%s): Equation cannot be evaluated", -// pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); -// m_Errors.Add(err); - } } /* ==================================================================== @@ -5264,3 +5616,4 @@ CMacro::~CMacro() delete m_ParamList; } } + diff --git a/src/assemble.h b/src/assemble.h index ed9ce57..53bda8f 100644 --- a/src/assemble.h +++ b/src/assemble.h @@ -195,6 +195,10 @@ #define CSEG 1 #define DSEG 2 +#define PREPROC_STAT_NO_SUBST 0 +#define PREPROC_STAT_SUBST 1 +#define PREPROC_STAT_ERROR 2 + #define MAX_SEG_SIZE (4*1024*1024) #define VT_ISDIGIT(x) (((x) >= '0') && ((x) <= '9')) @@ -371,6 +375,8 @@ class VTAssembler : public VTObject VTAssembler(); ~VTAssembler(); + int PerformSubstitution(CMacro* pMacro, const char* pLoc); + int MacroSubstitution(void); int preprocessor(void); // Define Preprocessor functions @@ -440,6 +446,9 @@ class VTAssembler : public VTObject MString m_FileDir; FILE* m_fd; // File descriptor of open file int m_Line; + char* m_pInLine; // Pointer to expanded unput line + char* m_pInPtr; // Pointer to next char to process + int m_InLineCount; // Size of m_pInLine buffer int m_LastLabelLine; // Line number of last label int m_FileIndex; int m_ProjectType; @@ -479,6 +488,9 @@ class VTAssembler : public VTObject MString m_IncludeName[32]; FILE* m_IncludeStack[32]; int m_IncludeIndex[32]; + char* m_IncludeInLine[32]; + char* m_IncludeInPtr[32]; + int m_IncludeInLineCount[32]; a85parse_pcb_struct m_ParserPCBs[32]; int m_IncludeDepth; MString m_AsmOptions; // Assembler options From 6bc1541c1791573ba323ba052dabfd2e900aff03 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 2 Feb 2013 15:29:02 +0000 Subject: [PATCH 207/327] Modified assembler parser to accept "label = equation" syntax for the 'set' directive. Also fixed a build warning under Windows with io.c. --- src/a85parse.cpp | 9359 +++++++++++++++++++++++----------------------- src/a85parse.h | 44 +- src/a85parse.syn | 7 +- src/assemble.cpp | 36 +- src/assemble.h | 2 +- src/io.c | 2 +- 6 files changed, 4767 insertions(+), 4683 deletions(-) diff --git a/src/a85parse.cpp b/src/a85parse.cpp index d9e43e8..4b100e7 100644 --- a/src/a85parse.cpp +++ b/src/a85parse.cpp @@ -17,11 +17,11 @@ */ -#ifndef A85PARSE_H_1359224795 +#ifndef A85PARSE_H_1359807348 #include "a85parse.h" #endif -#ifndef A85PARSE_H_1359224795 +#ifndef A85PARSE_H_1359807348 #error Mismatched header file #endif @@ -39,7 +39,7 @@ a85parse_pcb_type a85parse_pcb; #define PCB a85parse_pcb -/* Line 695, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 700, C:/Projects/VirtualT/src/a85parse.syn */ // Embedded C #include "MString.h" // Include MString header @@ -469,53 +469,59 @@ static int agConvertCase(int c) { #define ag_rp_2() (gAsm->directive_set((const char *) -1)) -#define ag_rp_3() (gAsm->include(ss[ss_idx--])) +#define ag_rp_3() (gAsm->directive_set((const char *) -1)) #define ag_rp_4() (gAsm->include(ss[ss_idx--])) #define ag_rp_5() (gAsm->include(ss[ss_idx--])) -#define ag_rp_6() (gAsm->directive_cdseg(seg, page)) +#define ag_rp_6() (gAsm->include(ss[ss_idx--])) #define ag_rp_7() (gAsm->directive_cdseg(seg, page)) -#define ag_rp_8() (handle_error()) +#define ag_rp_8() (gAsm->directive_cdseg(seg, page)) -#define ag_rp_9() (gAsm->include(ss[ss_idx--])) +#define ag_rp_9() (handle_error()) #define ag_rp_10() (gAsm->include(ss[ss_idx--])) -#define ag_rp_11() (gAsm->pragma_list()) +#define ag_rp_11() (gAsm->include(ss[ss_idx--])) -#define ag_rp_12() (gAsm->pragma_hex()) +#define ag_rp_12() (gAsm->pragma_list()) -#define ag_rp_13() (gAsm->pragma_entry(ss[ss_idx--])) +#define ag_rp_13() (gAsm->pragma_hex()) -#define ag_rp_14() (gAsm->pragma_verilog()) +#define ag_rp_14() (gAsm->pragma_entry(ss[ss_idx--])) -#define ag_rp_15() (gAsm->pragma_extended()) +#define ag_rp_15() (gAsm->pragma_verilog()) -#define ag_rp_16() (gAsm->preproc_ifdef(ss[ss_idx--])) +#define ag_rp_16() (gAsm->pragma_extended()) -#define ag_rp_17() (gAsm->preproc_if()) +#define ag_rp_17() (gAsm->preproc_ifdef(ss[ss_idx--])) -#define ag_rp_18() (gAsm->preproc_elif()) +#define ag_rp_18() (gAsm->preproc_if()) -#define ag_rp_19() (gAsm->preproc_ifndef(ss[ss_idx--])) +#define ag_rp_19() (gAsm->preproc_elif()) -#define ag_rp_20() (gAsm->preproc_else()) +#define ag_rp_20() (gAsm->preproc_ifndef(ss[ss_idx--])) -#define ag_rp_21() (gAsm->preproc_endif()) +#define ag_rp_21() (gAsm->preproc_else()) -static void ag_rp_22(void) { -/* Line 125, C:/Projects/VirtualT/src/a85parse.syn */ +#define ag_rp_22() (gAsm->preproc_endif()) + +static void ag_rp_23(void) { +/* Line 126, C:/Projects/VirtualT/src/a85parse.syn */ if (gAsm->preproc_error(ss[ss_idx--])) gAbort = TRUE; } -#define ag_rp_23() (gAsm->preproc_undef(ss[ss_idx--])) +#define ag_rp_24() (gAsm->directive_printf(ss[ss_idx--], FALSE)) + +#define ag_rp_25() (gAsm->directive_printf(ss[ss_idx--])) + +#define ag_rp_26() (gAsm->preproc_undef(ss[ss_idx--])) -static void ag_rp_24(void) { -/* Line 128, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_27(void) { +/* Line 132, C:/Projects/VirtualT/src/a85parse.syn */ if (gMacroStack[ms_idx] != 0) { delete gMacroStack[ms_idx]; \ gMacroStack[ms_idx] = 0; } \ gMacro = gMacroStack[--ms_idx]; \ @@ -524,8 +530,8 @@ static void ag_rp_24(void) { gMacroStack[ms_idx] = 0; gDefine = 0; } -static void ag_rp_25(void) { -/* Line 142, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_28(void) { +/* Line 146, C:/Projects/VirtualT/src/a85parse.syn */ gMacro->m_ParamList = gExpList; \ gMacro->m_Name = ss[ss_idx--]; \ gExpList = new VTObArray; \ @@ -535,305 +541,307 @@ static void ag_rp_25(void) { gMacro = new CMacro; } -static void ag_rp_26(void) { -/* Line 149, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_29(void) { +/* Line 153, C:/Projects/VirtualT/src/a85parse.syn */ gMacro->m_Name = ss[ss_idx--]; gMacroStack[ms_idx++] = gMacro; \ if (gAsm->preproc_macro()) \ PCB.reduction_token = a85parse_WS_token; \ gMacro = new CMacro; } -static void ag_rp_27(int c) { -/* Line 155, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_30(int c) { +/* Line 159, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_28(int c) { -/* Line 156, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_31(int c) { +/* Line 160, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_29(void) { -/* Line 157, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_32(void) { +/* Line 161, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '\n'; ss[ss_idx][ss_len] = 0; } -static void ag_rp_30(void) { -/* Line 160, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_33(void) { +/* Line 164, C:/Projects/VirtualT/src/a85parse.syn */ page = 0; seg = CSEG; } -static void ag_rp_31(void) { -/* Line 161, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_34(void) { +/* Line 165, C:/Projects/VirtualT/src/a85parse.syn */ page = 0; seg = DSEG; } -#define ag_rp_32(p) (page = p) +#define ag_rp_35(p) (page = p) -#define ag_rp_33() (gAsm->pragma_list()) +#define ag_rp_36() (gAsm->pragma_list()) -#define ag_rp_34() (gAsm->pragma_hex()) +#define ag_rp_37() (gAsm->pragma_hex()) -#define ag_rp_35() (gAsm->pragma_verilog()) +#define ag_rp_38() (gAsm->pragma_verilog()) -#define ag_rp_36() (gAsm->pragma_entry(ss[ss_idx--])) +#define ag_rp_39() (gAsm->pragma_entry(ss[ss_idx--])) -#define ag_rp_37() (gAsm->pragma_extended()) +#define ag_rp_40() (gAsm->pragma_extended()) -#define ag_rp_38() (gAsm->directive_org()) +#define ag_rp_41() (gAsm->directive_org()) -#define ag_rp_39() (gAsm->directive_aseg()) +#define ag_rp_42() (gAsm->directive_aseg()) -#define ag_rp_40() (gAsm->directive_ds()) +#define ag_rp_43() (gAsm->directive_ds()) -#define ag_rp_41() (gAsm->directive_db()) +#define ag_rp_44() (gAsm->directive_db()) -#define ag_rp_42() (gAsm->directive_dw()) +#define ag_rp_45() (gAsm->directive_dw()) -#define ag_rp_43() (gAsm->directive_public()) +#define ag_rp_46() (gAsm->directive_public()) -#define ag_rp_44() (gAsm->directive_extern()) +#define ag_rp_47() (gAsm->directive_extern()) -#define ag_rp_45() (gAsm->directive_extern()) +#define ag_rp_48() (gAsm->directive_extern()) -#define ag_rp_46() (gAsm->directive_module(ss[ss_idx--])) +#define ag_rp_49() (gAsm->directive_module(ss[ss_idx--])) -#define ag_rp_47() (gAsm->directive_name(ss[ss_idx--])) +#define ag_rp_50() (gAsm->directive_name(ss[ss_idx--])) -#define ag_rp_48() (gAsm->directive_stkln()) +#define ag_rp_51() (gAsm->directive_stkln()) -#define ag_rp_49() (gAsm->directive_echo()) +#define ag_rp_52() (gAsm->directive_echo()) -#define ag_rp_50() (gAsm->directive_echo(ss[ss_idx--])) +#define ag_rp_53() (gAsm->directive_echo(ss[ss_idx--])) -#define ag_rp_51() (gAsm->directive_fill()) +#define ag_rp_54() (gAsm->directive_fill()) -#define ag_rp_52() (gAsm->directive_printf(ss[ss_idx--])) +#define ag_rp_55() (gAsm->directive_printf(ss[ss_idx--], FALSE)) -#define ag_rp_53() (gAsm->directive_end("")) +#define ag_rp_56() (gAsm->directive_printf(ss[ss_idx--])) -#define ag_rp_54() (gAsm->directive_end(ss[ss_idx--])) +#define ag_rp_57() (gAsm->directive_end("")) -#define ag_rp_55() (gAsm->directive_if()) +#define ag_rp_58() (gAsm->directive_end(ss[ss_idx--])) -#define ag_rp_56() (gAsm->directive_else()) +#define ag_rp_59() (gAsm->directive_if()) -#define ag_rp_57() (gAsm->directive_endif()) +#define ag_rp_60() (gAsm->directive_else()) -#define ag_rp_58() (gAsm->directive_endian(1)) +#define ag_rp_61() (gAsm->directive_endif()) -#define ag_rp_59() (gAsm->directive_endian(0)) +#define ag_rp_62() (gAsm->directive_endian(1)) -#define ag_rp_60() (gAsm->directive_title(ss[ss_idx--])) +#define ag_rp_63() (gAsm->directive_endian(0)) -#define ag_rp_61() (gAsm->directive_title(ss[ss_idx--])) +#define ag_rp_64() (gAsm->directive_title(ss[ss_idx--])) -#define ag_rp_62() (gAsm->directive_page(-1)) +#define ag_rp_65() (gAsm->directive_title(ss[ss_idx--])) -#define ag_rp_63() (gAsm->directive_sym()) +#define ag_rp_66() (gAsm->directive_page(-1)) -#define ag_rp_64() (gAsm->directive_link(ss[ss_idx--])) +#define ag_rp_67() (gAsm->directive_sym()) -#define ag_rp_65() (gAsm->directive_maclib(ss[ss_idx--])) +#define ag_rp_68() (gAsm->directive_link(ss[ss_idx--])) -#define ag_rp_66() (gAsm->directive_page(page)) +#define ag_rp_69() (gAsm->directive_maclib(ss[ss_idx--])) -#define ag_rp_67() (page = 60) +#define ag_rp_70() (gAsm->directive_page(page)) -#define ag_rp_68(n) (page = n) +#define ag_rp_71() (page = 60) -#define ag_rp_69() (expression_list_literal()) +#define ag_rp_72(n) (page = n) -#define ag_rp_70() (expression_list_literal()) +#define ag_rp_73() (expression_list_literal()) -#define ag_rp_71() (expression_list_equation()) +#define ag_rp_74() (expression_list_literal()) -#define ag_rp_72() (expression_list_equation()) +#define ag_rp_75() (expression_list_equation()) -#define ag_rp_73() (expression_list_literal()) +#define ag_rp_76() (expression_list_equation()) -#define ag_rp_74() (expression_list_literal()) +#define ag_rp_77() (expression_list_literal()) + +#define ag_rp_78() (expression_list_literal()) -#define ag_rp_75() (gNameList->Add(ss[ss_idx--])) +#define ag_rp_79() (gNameList->Add(ss[ss_idx--])) -#define ag_rp_76() (gNameList->Add(ss[ss_idx--])) +#define ag_rp_80() (gNameList->Add(ss[ss_idx--])) -static void ag_rp_77(void) { -/* Line 242, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_81(void) { +/* Line 247, C:/Projects/VirtualT/src/a85parse.syn */ strcpy(ss[++ss_idx], "$"); ss_len = 1; } -static void ag_rp_78(void) { -/* Line 243, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_82(void) { +/* Line 248, C:/Projects/VirtualT/src/a85parse.syn */ strcpy(ss[++ss_idx], "&"); ss_len = 1; } -static void ag_rp_79(int c) { -/* Line 246, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_83(int c) { +/* Line 251, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; \ if (PCB.column == 2) ss_addr = gAsm->m_ActiveSeg->m_Address; } -static void ag_rp_80(int c) { -/* Line 248, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_84(int c) { +/* Line 253, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_81(int c) { -/* Line 249, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_85(int c) { +/* Line 254, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_82(int c) { -/* Line 252, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_86(int c) { +/* Line 257, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_83(int c) { -/* Line 253, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_87(int c) { +/* Line 258, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_84(int ch1, int ch2) { -/* Line 259, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_88(int ch1, int ch2) { +/* Line 264, C:/Projects/VirtualT/src/a85parse.syn */ ss_idx++; ss_len = 2; sprintf(ss[ss_idx], "%c%c", ch1, ch2); } -static void ag_rp_85(int c) { -/* Line 260, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_89(int c) { +/* Line 265, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_86(void) { -/* Line 267, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_90(void) { +/* Line 272, C:/Projects/VirtualT/src/a85parse.syn */ ss_idx++; ss_len = 0; } -static void ag_rp_87(int c) { -/* Line 268, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_91(int c) { +/* Line 273, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -#define ag_rp_88(n) (n) +#define ag_rp_92(n) (n) -#define ag_rp_89() ('\\') +#define ag_rp_93() ('\\') -#define ag_rp_90() ('\n') +#define ag_rp_94() ('\n') -#define ag_rp_91() ('\t') +#define ag_rp_95() ('\t') -#define ag_rp_92() ('\r') +#define ag_rp_96() ('\r') -#define ag_rp_93() ('\0') +#define ag_rp_97() ('\0') -#define ag_rp_94() ('"') +#define ag_rp_98() ('"') -#define ag_rp_95() (0x08) +#define ag_rp_99() (0x08) -#define ag_rp_96() (0x0C) +#define ag_rp_100() (0x0C) -#define ag_rp_97(n1, n2, n3) ((n1-'0') * 64 + (n2-'0') * 8 + n3-'0') +#define ag_rp_101(n1, n2, n3) ((n1-'0') * 64 + (n2-'0') * 8 + n3-'0') -#define ag_rp_98(n1, n2) (chtoh(n1) * 16 + chtoh(n2)) +#define ag_rp_102(n1, n2) (chtoh(n1) * 16 + chtoh(n2)) -#define ag_rp_99(n1) (chtoh(n1)) +#define ag_rp_103(n1) (chtoh(n1)) -static void ag_rp_100(void) { -/* Line 288, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_104(void) { +/* Line 293, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '>'; ss[ss_idx][ss_len] = 0; } -static void ag_rp_101(void) { -/* Line 291, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_105(void) { +/* Line 296, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = '<'; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_102(int c) { -/* Line 292, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_106(int c) { +/* Line 297, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_103(int c) { -/* Line 293, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_107(int c) { +/* Line 298, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '\\'; ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -#define ag_rp_104() (gAsm->label(ss[ss_idx--])) +#define ag_rp_108() (gAsm->label(ss[ss_idx--])) -#define ag_rp_105() (gAsm->label(ss[ss_idx--])) +#define ag_rp_109() (gAsm->label(ss[ss_idx--])) -#define ag_rp_106() (gAsm->label(".bss")) +#define ag_rp_110() (gAsm->label(".bss")) -#define ag_rp_107() (gAsm->label(".text")) +#define ag_rp_111() (gAsm->label(".text")) -#define ag_rp_108() (gAsm->label(".data")) +#define ag_rp_112() (gAsm->label(".data")) -#define ag_rp_109() (PAGE) +#define ag_rp_113() (PAGE) -#define ag_rp_110() (INPAGE) +#define ag_rp_114() (INPAGE) -#define ag_rp_111() (condition(-1)) +#define ag_rp_115() (condition(-1)) -#define ag_rp_112() (condition(COND_NOCMP)) +#define ag_rp_116() (condition(COND_NOCMP)) -#define ag_rp_113() (condition(COND_EQ)) +#define ag_rp_117() (condition(COND_EQ)) -#define ag_rp_114() (condition(COND_NE)) +#define ag_rp_118() (condition(COND_NE)) -#define ag_rp_115() (condition(COND_GE)) +#define ag_rp_119() (condition(COND_GE)) -#define ag_rp_116() (condition(COND_LE)) +#define ag_rp_120() (condition(COND_LE)) -#define ag_rp_117() (condition(COND_GT)) +#define ag_rp_121() (condition(COND_GT)) -#define ag_rp_118() (condition(COND_LT)) +#define ag_rp_122() (condition(COND_LT)) -#define ag_rp_119() (gEq->Add(RPN_BITOR)) +#define ag_rp_123() (gEq->Add(RPN_BITOR)) -#define ag_rp_120() (gEq->Add(RPN_BITOR)) +#define ag_rp_124() (gEq->Add(RPN_BITOR)) -#define ag_rp_121() (gEq->Add(RPN_BITXOR)) +#define ag_rp_125() (gEq->Add(RPN_BITXOR)) -#define ag_rp_122() (gEq->Add(RPN_BITXOR)) +#define ag_rp_126() (gEq->Add(RPN_BITXOR)) -#define ag_rp_123() (gEq->Add(RPN_BITAND)) +#define ag_rp_127() (gEq->Add(RPN_BITAND)) -#define ag_rp_124() (gEq->Add(RPN_BITAND)) +#define ag_rp_128() (gEq->Add(RPN_BITAND)) -#define ag_rp_125() (gEq->Add(RPN_LEFTSHIFT)) +#define ag_rp_129() (gEq->Add(RPN_LEFTSHIFT)) -#define ag_rp_126() (gEq->Add(RPN_LEFTSHIFT)) +#define ag_rp_130() (gEq->Add(RPN_LEFTSHIFT)) -#define ag_rp_127() (gEq->Add(RPN_RIGHTSHIFT)) +#define ag_rp_131() (gEq->Add(RPN_RIGHTSHIFT)) -#define ag_rp_128() (gEq->Add(RPN_RIGHTSHIFT)) +#define ag_rp_132() (gEq->Add(RPN_RIGHTSHIFT)) -#define ag_rp_129() (gEq->Add(RPN_ADD)) +#define ag_rp_133() (gEq->Add(RPN_ADD)) -#define ag_rp_130() (gEq->Add(RPN_SUBTRACT)) +#define ag_rp_134() (gEq->Add(RPN_SUBTRACT)) -#define ag_rp_131() (gEq->Add(RPN_MULTIPLY)) +#define ag_rp_135() (gEq->Add(RPN_MULTIPLY)) -#define ag_rp_132() (gEq->Add(RPN_DIVIDE)) +#define ag_rp_136() (gEq->Add(RPN_DIVIDE)) -#define ag_rp_133() (gEq->Add(RPN_MODULUS)) +#define ag_rp_137() (gEq->Add(RPN_MODULUS)) -#define ag_rp_134() (gEq->Add(RPN_MODULUS)) +#define ag_rp_138() (gEq->Add(RPN_MODULUS)) -#define ag_rp_135() (gEq->Add(RPN_EXPONENT)) +#define ag_rp_139() (gEq->Add(RPN_EXPONENT)) -#define ag_rp_136() (gEq->Add(RPN_NOT)) +#define ag_rp_140() (gEq->Add(RPN_NOT)) -#define ag_rp_137() (gEq->Add(RPN_NOT)) +#define ag_rp_141() (gEq->Add(RPN_NOT)) -#define ag_rp_138() (gEq->Add(RPN_BITNOT)) +#define ag_rp_142() (gEq->Add(RPN_BITNOT)) -#define ag_rp_139() (gEq->Add(RPN_NEGATE)) +#define ag_rp_143() (gEq->Add(RPN_NEGATE)) -#define ag_rp_140(n) (gEq->Add((double) n)) +#define ag_rp_144(n) (gEq->Add((double) n)) -static void ag_rp_141(void) { -/* Line 384, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_145(void) { +/* Line 389, C:/Projects/VirtualT/src/a85parse.syn */ delete gMacro; gMacro = gMacroStack[ms_idx-1]; \ gMacroStack[ms_idx--] = 0; if (gMacro->m_ParamList == 0) \ {\ @@ -843,177 +851,169 @@ static void ag_rp_141(void) { } } -#define ag_rp_142() (gEq->Add(RPN_FLOOR)) +#define ag_rp_146() (gEq->Add(RPN_FLOOR)) -#define ag_rp_143() (gEq->Add(RPN_CEIL)) +#define ag_rp_147() (gEq->Add(RPN_CEIL)) -#define ag_rp_144() (gEq->Add(RPN_LN)) +#define ag_rp_148() (gEq->Add(RPN_LN)) -#define ag_rp_145() (gEq->Add(RPN_LOG)) +#define ag_rp_149() (gEq->Add(RPN_LOG)) -#define ag_rp_146() (gEq->Add(RPN_SQRT)) +#define ag_rp_150() (gEq->Add(RPN_SQRT)) -#define ag_rp_147() (gEq->Add(RPN_IP)) +#define ag_rp_151() (gEq->Add(RPN_IP)) -#define ag_rp_148() (gEq->Add(RPN_FP)) +#define ag_rp_152() (gEq->Add(RPN_FP)) -#define ag_rp_149() (gEq->Add(RPN_HIGH)) +#define ag_rp_153() (gEq->Add(RPN_HIGH)) -#define ag_rp_150() (gEq->Add(RPN_LOW)) +#define ag_rp_154() (gEq->Add(RPN_LOW)) -#define ag_rp_151() (gEq->Add(RPN_PAGE)) +#define ag_rp_155() (gEq->Add(RPN_PAGE)) -#define ag_rp_152() (gEq->Add(RPN_DEFINED, ss[ss_idx--])) +#define ag_rp_156() (gEq->Add(RPN_DEFINED, ss[ss_idx--])) -#define ag_rp_153(n) (n) +#define ag_rp_157(n) (n) -#define ag_rp_154(r) (r) +#define ag_rp_158(r) (r) -#define ag_rp_155(n) (n) +#define ag_rp_159(n) (n) -#define ag_rp_156() (conv_to_dec()) +#define ag_rp_160() (conv_to_dec()) -#define ag_rp_157() (conv_to_hex()) +#define ag_rp_161() (conv_to_hex()) -#define ag_rp_158() (conv_to_bin()) +#define ag_rp_162() (conv_to_bin()) -#define ag_rp_159() (conv_to_oct()) +#define ag_rp_163() (conv_to_oct()) -#define ag_rp_160() (conv_to_hex()) +#define ag_rp_164() (conv_to_hex()) -#define ag_rp_161() (conv_to_hex()) +#define ag_rp_165() (conv_to_hex()) -#define ag_rp_162() (conv_to_bin()) +#define ag_rp_166() (conv_to_bin()) -#define ag_rp_163() (conv_to_oct()) +#define ag_rp_167() (conv_to_oct()) -#define ag_rp_164() (conv_to_dec()) +#define ag_rp_168() (conv_to_dec()) -static void ag_rp_165(int n) { -/* Line 431, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_169(int n) { +/* Line 436, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_166(int n) { -/* Line 432, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_170(int n) { +/* Line 437, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 2; integer[0] = '-', integer[1] = n; integer[2] = 0; } -static void ag_rp_167(int n) { -/* Line 433, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_171(int n) { +/* Line 438, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_168(int n) { -/* Line 434, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_172(int n) { +/* Line 439, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_169(int n) { -/* Line 439, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_173(int n) { +/* Line 444, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_170(int n) { -/* Line 440, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_174(int n) { +/* Line 445, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_171(int n) { -/* Line 441, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_175(int n) { +/* Line 446, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_172(int n) { -/* Line 444, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_176(int n) { +/* Line 449, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_173(int n) { -/* Line 445, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_177(int n) { +/* Line 450, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_174(int n) { -/* Line 448, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_178(int n) { +/* Line 453, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_175(int n) { -/* Line 449, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_179(int n) { +/* Line 454, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_176(int n) { -/* Line 452, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_180(int n) { +/* Line 457, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_177(int n) { -/* Line 453, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_181(int n) { +/* Line 458, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -#define ag_rp_178(n) (n) +#define ag_rp_182(n) (n) -#define ag_rp_179(n1, n2) ((n1 << 8) | n2) +#define ag_rp_183(n1, n2) ((n1 << 8) | n2) -#define ag_rp_180() ('\\') +#define ag_rp_184() ('\\') -#define ag_rp_181(n) (n) +#define ag_rp_185(n) (n) -#define ag_rp_182() ('\\') +#define ag_rp_186() ('\\') -#define ag_rp_183() ('\n') +#define ag_rp_187() ('\n') -#define ag_rp_184() ('\t') +#define ag_rp_188() ('\t') -#define ag_rp_185() ('\r') +#define ag_rp_189() ('\r') -#define ag_rp_186() ('\0') +#define ag_rp_190() ('\0') -#define ag_rp_187() ('\'') +#define ag_rp_191() ('\'') -#define ag_rp_188() ('\'') +#define ag_rp_192() ('\'') -static double ag_rp_189(void) { -/* Line 474, C:/Projects/VirtualT/src/a85parse.syn */ +static double ag_rp_193(void) { +/* Line 479, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor = 1.0; return (double) conv_to_dec(); } -static double ag_rp_190(int d) { -/* Line 475, C:/Projects/VirtualT/src/a85parse.syn */ +static double ag_rp_194(int d) { +/* Line 480, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor = 10.0; return ((double) (d - '0') / gDivisor); } -static double ag_rp_191(double r, int d) { -/* Line 476, C:/Projects/VirtualT/src/a85parse.syn */ +static double ag_rp_195(double r, int d) { +/* Line 481, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor *= 10.0; return (r + (double) (d - '0') / gDivisor); } -#define ag_rp_192() (reg[reg_cnt++] = '0') - -#define ag_rp_193() (reg[reg_cnt++] = '1') +#define ag_rp_196() (reg[reg_cnt++] = '0') -#define ag_rp_194() (reg[reg_cnt++] = '2') +#define ag_rp_197() (reg[reg_cnt++] = '1') -#define ag_rp_195() (reg[reg_cnt++] = '3') +#define ag_rp_198() (reg[reg_cnt++] = '2') -#define ag_rp_196() (reg[reg_cnt++] = '4') +#define ag_rp_199() (reg[reg_cnt++] = '3') -#define ag_rp_197() (reg[reg_cnt++] = '5') +#define ag_rp_200() (reg[reg_cnt++] = '4') -#define ag_rp_198() (reg[reg_cnt++] = '6') +#define ag_rp_201() (reg[reg_cnt++] = '5') -#define ag_rp_199() (reg[reg_cnt++] = '7') +#define ag_rp_202() (reg[reg_cnt++] = '6') -#define ag_rp_200() (reg[reg_cnt++] = '0') - -#define ag_rp_201() (reg[reg_cnt++] = '1') - -#define ag_rp_202() (reg[reg_cnt++] = '2') - -#define ag_rp_203() (reg[reg_cnt++] = '3') +#define ag_rp_203() (reg[reg_cnt++] = '7') #define ag_rp_204() (reg[reg_cnt++] = '0') @@ -1023,247 +1023,255 @@ static double ag_rp_191(double r, int d) { #define ag_rp_207() (reg[reg_cnt++] = '3') -#define ag_rp_208() (reg[reg_cnt++] = '3') +#define ag_rp_208() (reg[reg_cnt++] = '0') + +#define ag_rp_209() (reg[reg_cnt++] = '1') -#define ag_rp_209() (reg[reg_cnt++] = '0') +#define ag_rp_210() (reg[reg_cnt++] = '2') -#define ag_rp_210() (reg[reg_cnt++] = '1') +#define ag_rp_211() (reg[reg_cnt++] = '3') -#define ag_rp_211() (reg[reg_cnt++] = '0') +#define ag_rp_212() (reg[reg_cnt++] = '3') -#define ag_rp_212() (reg[reg_cnt++] = '1') +#define ag_rp_213() (reg[reg_cnt++] = '0') -#define ag_rp_213() (reg[reg_cnt++] = '2') +#define ag_rp_214() (reg[reg_cnt++] = '1') -#define ag_rp_214() (reg[reg_cnt++] = '3') +#define ag_rp_215() (reg[reg_cnt++] = '0') -#define ag_rp_215() (reg[reg_cnt++] = '4') +#define ag_rp_216() (reg[reg_cnt++] = '1') -#define ag_rp_216() (reg[reg_cnt++] = '5') +#define ag_rp_217() (reg[reg_cnt++] = '2') -#define ag_rp_217() (gAsm->opcode_arg_0 (OPCODE_ASHR)) +#define ag_rp_218() (reg[reg_cnt++] = '3') -#define ag_rp_218() (gAsm->opcode_arg_0 (OPCODE_CMA)) +#define ag_rp_219() (reg[reg_cnt++] = '4') -#define ag_rp_219() (gAsm->opcode_arg_0 (OPCODE_CMC)) +#define ag_rp_220() (reg[reg_cnt++] = '5') -#define ag_rp_220() (gAsm->opcode_arg_0 (OPCODE_DAA)) +#define ag_rp_221() (gAsm->opcode_arg_0 (OPCODE_ASHR)) -#define ag_rp_221() (gAsm->opcode_arg_0 (OPCODE_DI)) +#define ag_rp_222() (gAsm->opcode_arg_0 (OPCODE_CMA)) -#define ag_rp_222() (gAsm->opcode_arg_0 (OPCODE_DSUB)) +#define ag_rp_223() (gAsm->opcode_arg_0 (OPCODE_CMC)) -#define ag_rp_223() (gAsm->opcode_arg_0 (OPCODE_EI)) +#define ag_rp_224() (gAsm->opcode_arg_0 (OPCODE_DAA)) -#define ag_rp_224() (gAsm->opcode_arg_0 (OPCODE_HLT)) +#define ag_rp_225() (gAsm->opcode_arg_0 (OPCODE_DI)) -#define ag_rp_225() (gAsm->opcode_arg_0 (OPCODE_LHLX)) +#define ag_rp_226() (gAsm->opcode_arg_0 (OPCODE_DSUB)) -#define ag_rp_226() (gAsm->opcode_arg_0 (OPCODE_NOP)) +#define ag_rp_227() (gAsm->opcode_arg_0 (OPCODE_EI)) -#define ag_rp_227() (gAsm->opcode_arg_0 (OPCODE_PCHL)) +#define ag_rp_228() (gAsm->opcode_arg_0 (OPCODE_HLT)) -#define ag_rp_228() (gAsm->opcode_arg_0 (OPCODE_RAL)) +#define ag_rp_229() (gAsm->opcode_arg_0 (OPCODE_LHLX)) -#define ag_rp_229() (gAsm->opcode_arg_0 (OPCODE_RAR)) +#define ag_rp_230() (gAsm->opcode_arg_0 (OPCODE_NOP)) -#define ag_rp_230() (gAsm->opcode_arg_0 (OPCODE_RC)) +#define ag_rp_231() (gAsm->opcode_arg_0 (OPCODE_PCHL)) -#define ag_rp_231() (gAsm->opcode_arg_0 (OPCODE_RET)) +#define ag_rp_232() (gAsm->opcode_arg_0 (OPCODE_RAL)) -#define ag_rp_232() (gAsm->opcode_arg_0 (OPCODE_RIM)) +#define ag_rp_233() (gAsm->opcode_arg_0 (OPCODE_RAR)) -#define ag_rp_233() (gAsm->opcode_arg_0 (OPCODE_RLC)) +#define ag_rp_234() (gAsm->opcode_arg_0 (OPCODE_RC)) -#define ag_rp_234() (gAsm->opcode_arg_0 (OPCODE_RLDE)) +#define ag_rp_235() (gAsm->opcode_arg_0 (OPCODE_RET)) -#define ag_rp_235() (gAsm->opcode_arg_0 (OPCODE_RM)) +#define ag_rp_236() (gAsm->opcode_arg_0 (OPCODE_RIM)) -#define ag_rp_236() (gAsm->opcode_arg_0 (OPCODE_RNC)) +#define ag_rp_237() (gAsm->opcode_arg_0 (OPCODE_RLC)) -#define ag_rp_237() (gAsm->opcode_arg_0 (OPCODE_RNZ)) +#define ag_rp_238() (gAsm->opcode_arg_0 (OPCODE_RLDE)) -#define ag_rp_238() (gAsm->opcode_arg_0 (OPCODE_RP)) +#define ag_rp_239() (gAsm->opcode_arg_0 (OPCODE_RM)) -#define ag_rp_239() (gAsm->opcode_arg_0 (OPCODE_RPE)) +#define ag_rp_240() (gAsm->opcode_arg_0 (OPCODE_RNC)) -#define ag_rp_240() (gAsm->opcode_arg_0 (OPCODE_RPO)) +#define ag_rp_241() (gAsm->opcode_arg_0 (OPCODE_RNZ)) -#define ag_rp_241() (gAsm->opcode_arg_0 (OPCODE_RRC)) +#define ag_rp_242() (gAsm->opcode_arg_0 (OPCODE_RP)) -#define ag_rp_242() (gAsm->opcode_arg_0 (OPCODE_RSTV)) +#define ag_rp_243() (gAsm->opcode_arg_0 (OPCODE_RPE)) -#define ag_rp_243() (gAsm->opcode_arg_0 (OPCODE_RZ)) +#define ag_rp_244() (gAsm->opcode_arg_0 (OPCODE_RPO)) -#define ag_rp_244() (gAsm->opcode_arg_0 (OPCODE_SHLX)) +#define ag_rp_245() (gAsm->opcode_arg_0 (OPCODE_RRC)) -#define ag_rp_245() (gAsm->opcode_arg_0 (OPCODE_SIM)) +#define ag_rp_246() (gAsm->opcode_arg_0 (OPCODE_RSTV)) -#define ag_rp_246() (gAsm->opcode_arg_0 (OPCODE_SPHL)) +#define ag_rp_247() (gAsm->opcode_arg_0 (OPCODE_RZ)) -#define ag_rp_247() (gAsm->opcode_arg_0 (OPCODE_STC)) +#define ag_rp_248() (gAsm->opcode_arg_0 (OPCODE_SHLX)) -#define ag_rp_248() (gAsm->opcode_arg_0 (OPCODE_XCHG)) +#define ag_rp_249() (gAsm->opcode_arg_0 (OPCODE_SIM)) -#define ag_rp_249() (gAsm->opcode_arg_0 (OPCODE_XTHL)) +#define ag_rp_250() (gAsm->opcode_arg_0 (OPCODE_SPHL)) -#define ag_rp_250() (gAsm->opcode_arg_0 (OPCODE_LRET)) +#define ag_rp_251() (gAsm->opcode_arg_0 (OPCODE_STC)) -#define ag_rp_251() (gAsm->opcode_arg_1reg (OPCODE_STAX)) +#define ag_rp_252() (gAsm->opcode_arg_0 (OPCODE_XCHG)) -#define ag_rp_252() (gAsm->opcode_arg_1reg (OPCODE_LDAX)) +#define ag_rp_253() (gAsm->opcode_arg_0 (OPCODE_XTHL)) -#define ag_rp_253() (gAsm->opcode_arg_1reg (OPCODE_POP)) +#define ag_rp_254() (gAsm->opcode_arg_0 (OPCODE_LRET)) -#define ag_rp_254() (gAsm->opcode_arg_1reg (OPCODE_PUSH)) +#define ag_rp_255() (gAsm->opcode_arg_1reg (OPCODE_STAX)) -#define ag_rp_255() (gAsm->opcode_arg_1reg_2byte (OPCODE_LPOP)) +#define ag_rp_256() (gAsm->opcode_arg_1reg (OPCODE_LDAX)) -#define ag_rp_256() (gAsm->opcode_arg_1reg_2byte (OPCODE_LPUSH)) +#define ag_rp_257() (gAsm->opcode_arg_1reg (OPCODE_POP)) -#define ag_rp_257() (gAsm->opcode_arg_1reg (OPCODE_ADC)) +#define ag_rp_258() (gAsm->opcode_arg_1reg (OPCODE_PUSH)) -#define ag_rp_258() (gAsm->opcode_arg_1reg (OPCODE_ADD)) +#define ag_rp_259() (gAsm->opcode_arg_1reg_2byte (OPCODE_LPOP)) -#define ag_rp_259() (gAsm->opcode_arg_1reg (OPCODE_ANA)) +#define ag_rp_260() (gAsm->opcode_arg_1reg_2byte (OPCODE_LPUSH)) -#define ag_rp_260() (gAsm->opcode_arg_1reg (OPCODE_CMP)) +#define ag_rp_261() (gAsm->opcode_arg_1reg (OPCODE_ADC)) -#define ag_rp_261() (gAsm->opcode_arg_1reg (OPCODE_DCR)) +#define ag_rp_262() (gAsm->opcode_arg_1reg (OPCODE_ADD)) -#define ag_rp_262() (gAsm->opcode_arg_1reg (OPCODE_INR)) +#define ag_rp_263() (gAsm->opcode_arg_1reg (OPCODE_ANA)) -#define ag_rp_263() (gAsm->opcode_arg_2reg (OPCODE_MOV)) +#define ag_rp_264() (gAsm->opcode_arg_1reg (OPCODE_CMP)) -#define ag_rp_264() (gAsm->opcode_arg_1reg (OPCODE_ORA)) +#define ag_rp_265() (gAsm->opcode_arg_1reg (OPCODE_DCR)) -#define ag_rp_265() (gAsm->opcode_arg_1reg (OPCODE_SBB)) +#define ag_rp_266() (gAsm->opcode_arg_1reg (OPCODE_INR)) -#define ag_rp_266() (gAsm->opcode_arg_1reg (OPCODE_SUB)) +#define ag_rp_267() (gAsm->opcode_arg_2reg (OPCODE_MOV)) -#define ag_rp_267() (gAsm->opcode_arg_1reg (OPCODE_XRA)) +#define ag_rp_268() (gAsm->opcode_arg_1reg (OPCODE_ORA)) -#define ag_rp_268() (gAsm->opcode_arg_1reg_2byte (OPCODE_SPG)) +#define ag_rp_269() (gAsm->opcode_arg_1reg (OPCODE_SBB)) -#define ag_rp_269() (gAsm->opcode_arg_1reg_2byte (OPCODE_RPG)) +#define ag_rp_270() (gAsm->opcode_arg_1reg (OPCODE_SUB)) -#define ag_rp_270() (gAsm->opcode_arg_1reg (OPCODE_DAD)) +#define ag_rp_271() (gAsm->opcode_arg_1reg (OPCODE_XRA)) -#define ag_rp_271() (gAsm->opcode_arg_1reg (OPCODE_DCX)) +#define ag_rp_272() (gAsm->opcode_arg_1reg_2byte (OPCODE_SPG)) -#define ag_rp_272() (gAsm->opcode_arg_1reg (OPCODE_INX)) +#define ag_rp_273() (gAsm->opcode_arg_1reg_2byte (OPCODE_RPG)) -#define ag_rp_273() (gAsm->opcode_arg_1reg_equ16(OPCODE_LXI)) +#define ag_rp_274() (gAsm->opcode_arg_1reg (OPCODE_DAD)) -#define ag_rp_274() (gAsm->opcode_arg_1reg_equ8(OPCODE_MVI)) +#define ag_rp_275() (gAsm->opcode_arg_1reg (OPCODE_DCX)) -#define ag_rp_275() (gAsm->opcode_arg_1reg_equ16(OPCODE_SPI)) +#define ag_rp_276() (gAsm->opcode_arg_1reg (OPCODE_INX)) -#define ag_rp_276(c) (gAsm->opcode_arg_imm (OPCODE_RST, c)) +#define ag_rp_277() (gAsm->opcode_arg_1reg_equ16(OPCODE_LXI)) -#define ag_rp_277() (gAsm->opcode_arg_equ8 (OPCODE_ACI)) +#define ag_rp_278() (gAsm->opcode_arg_1reg_equ8(OPCODE_MVI)) -#define ag_rp_278() (gAsm->opcode_arg_equ8 (OPCODE_ADI)) +#define ag_rp_279() (gAsm->opcode_arg_1reg_equ16(OPCODE_SPI)) -#define ag_rp_279() (gAsm->opcode_arg_equ8 (OPCODE_ANI)) +#define ag_rp_280(c) (gAsm->opcode_arg_imm (OPCODE_RST, c)) -#define ag_rp_280() (gAsm->opcode_arg_equ16 (OPCODE_CALL)) +#define ag_rp_281() (gAsm->opcode_arg_equ8 (OPCODE_ACI)) -#define ag_rp_281() (gAsm->opcode_arg_equ16 (OPCODE_CC)) +#define ag_rp_282() (gAsm->opcode_arg_equ8 (OPCODE_ADI)) -#define ag_rp_282() (gAsm->opcode_arg_equ16 (OPCODE_CM)) +#define ag_rp_283() (gAsm->opcode_arg_equ8 (OPCODE_ANI)) -#define ag_rp_283() (gAsm->opcode_arg_equ16 (OPCODE_CNC)) +#define ag_rp_284() (gAsm->opcode_arg_equ16 (OPCODE_CALL)) -#define ag_rp_284() (gAsm->opcode_arg_equ16 (OPCODE_CNZ)) +#define ag_rp_285() (gAsm->opcode_arg_equ16 (OPCODE_CC)) -#define ag_rp_285() (gAsm->opcode_arg_equ16 (OPCODE_CP)) +#define ag_rp_286() (gAsm->opcode_arg_equ16 (OPCODE_CM)) -#define ag_rp_286() (gAsm->opcode_arg_equ16 (OPCODE_CPE)) +#define ag_rp_287() (gAsm->opcode_arg_equ16 (OPCODE_CNC)) -#define ag_rp_287() (gAsm->opcode_arg_equ8 (OPCODE_CPI)) +#define ag_rp_288() (gAsm->opcode_arg_equ16 (OPCODE_CNZ)) -#define ag_rp_288() (gAsm->opcode_arg_equ16 (OPCODE_CPO)) +#define ag_rp_289() (gAsm->opcode_arg_equ16 (OPCODE_CP)) -#define ag_rp_289() (gAsm->opcode_arg_equ16 (OPCODE_CZ)) +#define ag_rp_290() (gAsm->opcode_arg_equ16 (OPCODE_CPE)) -#define ag_rp_290() (gAsm->opcode_arg_equ8 (OPCODE_IN)) +#define ag_rp_291() (gAsm->opcode_arg_equ8 (OPCODE_CPI)) -#define ag_rp_291() (gAsm->opcode_arg_equ16 (OPCODE_JC)) +#define ag_rp_292() (gAsm->opcode_arg_equ16 (OPCODE_CPO)) -#define ag_rp_292() (gAsm->opcode_arg_equ16 (OPCODE_JD)) +#define ag_rp_293() (gAsm->opcode_arg_equ16 (OPCODE_CZ)) -#define ag_rp_293() (gAsm->opcode_arg_equ16 (OPCODE_JM)) +#define ag_rp_294() (gAsm->opcode_arg_equ8 (OPCODE_IN)) -#define ag_rp_294() (gAsm->opcode_arg_equ16 (OPCODE_JMP)) +#define ag_rp_295() (gAsm->opcode_arg_equ16 (OPCODE_JC)) -#define ag_rp_295() (gAsm->opcode_arg_equ16 (OPCODE_JNC)) +#define ag_rp_296() (gAsm->opcode_arg_equ16 (OPCODE_JD)) -#define ag_rp_296() (gAsm->opcode_arg_equ16 (OPCODE_JND)) +#define ag_rp_297() (gAsm->opcode_arg_equ16 (OPCODE_JM)) -#define ag_rp_297() (gAsm->opcode_arg_equ16 (OPCODE_JNZ)) +#define ag_rp_298() (gAsm->opcode_arg_equ16 (OPCODE_JMP)) -#define ag_rp_298() (gAsm->opcode_arg_equ16 (OPCODE_JP)) +#define ag_rp_299() (gAsm->opcode_arg_equ16 (OPCODE_JNC)) -#define ag_rp_299() (gAsm->opcode_arg_equ16 (OPCODE_JPE)) +#define ag_rp_300() (gAsm->opcode_arg_equ16 (OPCODE_JND)) -#define ag_rp_300() (gAsm->opcode_arg_equ16 (OPCODE_JPO)) +#define ag_rp_301() (gAsm->opcode_arg_equ16 (OPCODE_JNZ)) -#define ag_rp_301() (gAsm->opcode_arg_equ16 (OPCODE_JZ)) +#define ag_rp_302() (gAsm->opcode_arg_equ16 (OPCODE_JP)) -#define ag_rp_302() (gAsm->opcode_arg_equ16 (OPCODE_LDA)) +#define ag_rp_303() (gAsm->opcode_arg_equ16 (OPCODE_JPE)) -#define ag_rp_303() (gAsm->opcode_arg_equ8 (OPCODE_LDEH)) +#define ag_rp_304() (gAsm->opcode_arg_equ16 (OPCODE_JPO)) -#define ag_rp_304() (gAsm->opcode_arg_equ8 (OPCODE_LDES)) +#define ag_rp_305() (gAsm->opcode_arg_equ16 (OPCODE_JZ)) -#define ag_rp_305() (gAsm->opcode_arg_equ16 (OPCODE_LHLD)) +#define ag_rp_306() (gAsm->opcode_arg_equ16 (OPCODE_LDA)) -#define ag_rp_306() (gAsm->opcode_arg_equ8 (OPCODE_ORI)) +#define ag_rp_307() (gAsm->opcode_arg_equ8 (OPCODE_LDEH)) -#define ag_rp_307() (gAsm->opcode_arg_equ8 (OPCODE_OUT)) +#define ag_rp_308() (gAsm->opcode_arg_equ8 (OPCODE_LDES)) -#define ag_rp_308() (gAsm->opcode_arg_equ8 (OPCODE_SBI)) +#define ag_rp_309() (gAsm->opcode_arg_equ16 (OPCODE_LHLD)) -#define ag_rp_309() (gAsm->opcode_arg_equ16 (OPCODE_SHLD)) +#define ag_rp_310() (gAsm->opcode_arg_equ8 (OPCODE_ORI)) -#define ag_rp_310() (gAsm->opcode_arg_equ16 (OPCODE_STA)) +#define ag_rp_311() (gAsm->opcode_arg_equ8 (OPCODE_OUT)) -#define ag_rp_311() (gAsm->opcode_arg_equ8 (OPCODE_SUI)) +#define ag_rp_312() (gAsm->opcode_arg_equ8 (OPCODE_SBI)) -#define ag_rp_312() (gAsm->opcode_arg_equ8 (OPCODE_XRI)) +#define ag_rp_313() (gAsm->opcode_arg_equ16 (OPCODE_SHLD)) -#define ag_rp_313() (gAsm->opcode_arg_equ8 (OPCODE_BR)) +#define ag_rp_314() (gAsm->opcode_arg_equ16 (OPCODE_STA)) -#define ag_rp_314() (gAsm->opcode_arg_equ16 (OPCODE_BRA)) +#define ag_rp_315() (gAsm->opcode_arg_equ8 (OPCODE_SUI)) -#define ag_rp_315() (gAsm->opcode_arg_equ16 (OPCODE_BZ)) +#define ag_rp_316() (gAsm->opcode_arg_equ8 (OPCODE_XRI)) -#define ag_rp_316() (gAsm->opcode_arg_equ16 (OPCODE_BNZ)) +#define ag_rp_317() (gAsm->opcode_arg_equ8 (OPCODE_BR)) -#define ag_rp_317() (gAsm->opcode_arg_equ16 (OPCODE_BC)) +#define ag_rp_318() (gAsm->opcode_arg_equ16 (OPCODE_BRA)) -#define ag_rp_318() (gAsm->opcode_arg_equ16 (OPCODE_BNC)) +#define ag_rp_319() (gAsm->opcode_arg_equ16 (OPCODE_BZ)) -#define ag_rp_319() (gAsm->opcode_arg_equ16 (OPCODE_BM)) +#define ag_rp_320() (gAsm->opcode_arg_equ16 (OPCODE_BNZ)) -#define ag_rp_320() (gAsm->opcode_arg_equ16 (OPCODE_BP)) +#define ag_rp_321() (gAsm->opcode_arg_equ16 (OPCODE_BC)) -#define ag_rp_321() (gAsm->opcode_arg_equ16 (OPCODE_BPE)) +#define ag_rp_322() (gAsm->opcode_arg_equ16 (OPCODE_BNC)) -#define ag_rp_322() (gAsm->opcode_arg_equ16 (OPCODE_RCALL)) +#define ag_rp_323() (gAsm->opcode_arg_equ16 (OPCODE_BM)) -#define ag_rp_323() (gAsm->opcode_arg_equ8 (OPCODE_SBZ)) +#define ag_rp_324() (gAsm->opcode_arg_equ16 (OPCODE_BP)) -#define ag_rp_324() (gAsm->opcode_arg_equ8 (OPCODE_SBNZ)) +#define ag_rp_325() (gAsm->opcode_arg_equ16 (OPCODE_BPE)) -#define ag_rp_325() (gAsm->opcode_arg_equ8 (OPCODE_SBC)) +#define ag_rp_326() (gAsm->opcode_arg_equ16 (OPCODE_RCALL)) -#define ag_rp_326() (gAsm->opcode_arg_equ8 (OPCODE_SBNC)) +#define ag_rp_327() (gAsm->opcode_arg_equ8 (OPCODE_SBZ)) -#define ag_rp_327() (gAsm->opcode_arg_equ24 (OPCODE_LCALL)) +#define ag_rp_328() (gAsm->opcode_arg_equ8 (OPCODE_SBNZ)) -#define ag_rp_328() (gAsm->opcode_arg_equ24 (OPCODE_LJMP)) +#define ag_rp_329() (gAsm->opcode_arg_equ8 (OPCODE_SBC)) + +#define ag_rp_330() (gAsm->opcode_arg_equ8 (OPCODE_SBNC)) + +#define ag_rp_331() (gAsm->opcode_arg_equ24 (OPCODE_LCALL)) + +#define ag_rp_332() (gAsm->opcode_arg_equ24 (OPCODE_LJMP)) #define READ_COUNTS @@ -1301,31 +1309,31 @@ static a85parse_vs_type const ag_null_value NULL_VALUE_INITIALIZER; static const unsigned short ag_rpx[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 3, 4, 5, 6, - 7, 8, 0, 0, 9, 10, 11, 12, 13, 14, 15, 0, 0, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 32, 0, 33, 34, 35, 36, - 37, 0, 0, 0, 38, 39, 0, 0, 40, 0, 0, 0, 41, 0, 0, 42, 43, 44, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 4, 5, 6, + 7, 8, 9, 0, 0, 10, 11, 12, 13, 14, 15, 16, 0, 0, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 0, 35, 0, 36, + 37, 38, 39, 40, 0, 0, 0, 41, 42, 0, 0, 43, 0, 0, 0, 44, 0, 0, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 0, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 0, 0, 77, - 78, 79, 80, 81, 82, 83, 0, 84, 85, 0, 86, 87, 0, 88, 89, 90, 91, 92, - 93, 94, 95, 96, 97, 0, 0, 98, 99,100,101,102,103, 0,104,105,106,107, - 108,109,110,111,112, 0, 0, 0,113, 0, 0,114, 0, 0,115, 0, 0,116, - 0, 0,117, 0, 0,118, 0, 0,119,120, 0,121,122, 0,123,124, 0,125, - 126,127,128, 0,129,130, 0,131,132,133,134,135, 0,136,137,138,139,140, - 141, 0, 0,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156, - 157,158,159,160,161,162, 0, 0,163,164,165,166,167,168, 0, 0,169,170, - 171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188, - 0,189,190,191,192,193,194,195,196,197, 0, 0,198,199, 0, 0,200, 0, - 0,201, 0, 0,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,217, - 218,219,220,221, 0, 0,222,223,224, 0, 0, 0,225,226,227,228,229,230, - 231,232,233, 0, 0,234,235,236,237,238,239,240,241,242,243, 0, 0, 0, - 244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261, - 262,263,264,265,266,267,268,269,270,271,272, 0,273, 0,274, 0,275,276, - 277,278,279,280,281,282,283,284,285,286,287,288,289,290,291, 0, 0, 0, - 0, 0,292,293,294,295, 0, 0, 0, 0, 0,296,297,298,299,300,301,302, - 0, 0, 0,303, 0, 0, 0,304,305,306,307,308,309,310,311,312,313,314, - 315,316,317,318,319,320,321,322,323,324,325,326,327,328 + 63, 64, 65, 66, 67, 68, 69, 0, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 0, 0, 81, 82, 83, 84, 85, 86, 87, 0, 88, 89, 0, 90, 91, 0, 92, + 93, 94, 95, 96, 97, 98, 99,100,101, 0, 0,102,103,104,105,106,107, 0, + 108,109,110,111,112,113,114,115,116, 0, 0, 0,117, 0, 0,118, 0, 0, + 119, 0, 0,120, 0, 0,121, 0, 0,122, 0, 0,123,124, 0,125,126, 0, + 127,128, 0,129,130,131,132, 0,133,134, 0,135,136,137,138,139, 0,140, + 141,142,143,144,145, 0, 0,146,147,148,149,150,151,152,153,154,155,156, + 157,158,159,160,161,162,163,164,165,166, 0, 0,167,168,169,170,171,172, + 0, 0,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188, + 189,190,191,192, 0,193,194,195,196,197,198,199,200,201, 0, 0,202,203, + 0, 0,204, 0, 0,205, 0, 0,206,207,208,209,210,211,212,213,214,215, + 216,217,218,219,220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,221,222,223,224,225, 0, 0,226,227,228, 0, 0, 0,229,230, + 231,232,233,234,235,236,237, 0, 0,238,239,240,241,242,243,244,245,246, + 247, 0, 0, 0,248,249,250,251,252,253,254,255,256,257,258,259,260,261, + 262,263,264,265,266,267,268,269,270,271,272,273,274,275,276, 0,277, 0, + 278, 0,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294, + 295, 0, 0, 0, 0, 0,296,297,298,299, 0, 0, 0, 0, 0,300,301,302, + 303,304,305,306, 0, 0, 0,307, 0, 0, 0,308,309,310,311,312,313,314, + 315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332 }; static const unsigned char ag_key_itt[] = { @@ -1344,34 +1352,35 @@ static const unsigned char ag_key_itt[] = { }; static const unsigned short ag_key_pt[] = { - 1,430, 1,431, 1,432, 1,433, 1,439, 1,438, 1,440, 1,442, - 1,443, 1,444, 1,445, 1,446, 1,447, 1,448, 1,449, 1,450, - 1,451, 1,452, 1,453, 1,457, 1,458, 1,459, 1,462, 1,463, - 1,464, 1,465, 1,466, 1,467, 1,468, 1,469, 1,470, 1,471, - 1,472, 1,473, 1,474, 1,475, 1,476, 1,477, 1,479, 1,480, - 1,481, 1,482, 1,484, 1,485, 1,486, 1,487, 1,488, 1,489, - 1,132, 1,492, 1,493, 1,496, 1,498, 1,500, 1,502, 1,504, - 1,507, 1,509, 1,511, 1,513, 1,515, 1,521, 1,524, 1,526, + 1,430, 1,431, 1,433, 1,434, 1,440, 1,439, 1,441, 1,443, + 1,444, 1,445, 1,446, 1,447, 1,448, 1,449, 1,450, 1,451, + 1,452, 1,453, 1,455, 1,456, 1,457, 1,461, 1,462, 1,463, + 1,466, 1,467, 1,468, 1,469, 1,470, 1,471, 1,472, 1,473, + 1,474, 1,475, 1,476, 1,477, 1,478, 1,479, 1,480, 1,481, + 1,482, 1,483, 1,484, 1,486, 1,487, 1,488, 1,489, 1,490, + 1,491, 1,134, 1,494, 1,495, 1,497, 1,499, 1,501, 1,503, + 1,505, 1,508, 1,510, 1,512, 1,514, 1,516, 1,522, 1,525, 1,527, 1,528, 1,529, 1,530, 1,531, 1,532, 1,533, 1,534, - 1,536, 1,220, 1,221, 1,233, 1,234, 1,235, 1,236, 1,237, - 1,238, 1,239, 1,539, 1,667, 1,245, 1,247, 1,542, 1,538, - 1,540, 1,541, 1,543, 1,544, 1,545, 1,546, 1,547, 1,548, + 1,535, 1,537, 1,221, 1,222, 1,234, 1,235, 1,236, 1,237, + 1,238, 1,239, 1,240, 1,540, 1,668, 1,246, 1,248, 1,543, + 1,539, 1,541, 1,542, 1,544, 1,545, 1,546, 1,547, 1,548, 1,549, 1,550, 1,551, 1,552, 1,553, 1,554, 1,555, 1,556, 1,557, 1,558, 1,559, 1,560, 1,561, 1,562, 1,563, 1,564, 1,565, 1,566, 1,567, 1,568, 1,569, 1,570, 1,571, 1,572, 1,573, 1,574, 1,575, 1,576, 1,577, 1,578, 1,579, 1,580, 1,581, 1,582, 1,583, 1,584, 1,585, 1,586, 1,587, 1,588, - 1,589, 1,590, 1,591, 1,592, 1,594, 1,595, 1,596, 1,597, + 1,589, 1,590, 1,591, 1,592, 1,593, 1,595, 1,596, 1,597, 1,598, 1,599, 1,600, 1,601, 1,602, 1,603, 1,604, 1,605, - 1,606, 1,608, 1,609, 1,610, 1,611, 1,612, 1,613, 1,614, + 1,606, 1,607, 1,609, 1,610, 1,611, 1,612, 1,613, 1,614, 1,615, 1,616, 1,617, 1,618, 1,619, 1,620, 1,621, 1,622, 1,623, 1,624, 1,625, 1,626, 1,627, 1,628, 1,629, 1,630, 1,631, 1,632, 1,633, 1,634, 1,635, 1,636, 1,637, 1,638, 1,639, 1,640, 1,641, 1,642, 1,643, 1,644, 1,645, 1,646, 1,647, 1,648, 1,649, 1,650, 1,651, 1,652, 1,653, 1,654, 1,655, 1,656, 1,657, 1,658, 1,659, 1,660, 1,661, 1,662, - 1,663, 1,664, 1,665, 1,666, 1,668, 1,669, 1,670, 1,671, - 1,672, 1,673, 1,674, 1,675, 1,676, 1,677, 1,678,0 + 1,663, 1,664, 1,665, 1,666, 1,667, 1,669, 1,670, 1,671, + 1,672, 1,673, 1,674, 1,675, 1,676, 1,677, 1,678, 1,679, +0 }; static const unsigned char ag_key_ch[] = { @@ -1390,17 +1399,18 @@ static const unsigned char ag_key_ch[] = { 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, 88,255, 76,255, 78, 83,255, 71, 87,255, 79, 85,255, 67, 68, 69, 72, 73, 74, 78, 79, 80, 82, 83, 84, 88,255, 85,255, 68, 86,255, 65, 79, 83, 86,255, 65,255, 80, 84,255, 65, - 69, 79,255, 65, 71, 73,255, 82, 85,255, 72,255, 65, 73,255, 66, 83,255, - 65, 67, 79, 82, 83, 85,255, 76, 82,255, 65,255, 67, 68,255, 67, 90,255, - 69, 71, 79,255, 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, - 78, 80, 82, 83, 90,255, 67, 90,255, 66, 67, 73, 78, 90,255, 69,255, 68, - 73, 82, 88,255, 76, 82,255, 71, 72, 73,255, 88,255, 65, 67, 75,255, 66, - 73,255, 66, 69, 72, 73, 80, 81, 84, 85, 89,255, 69, 73,255, 65, 73,255, - 67, 79, 82, 84,255, 33, 35, 36, 38, 39, 40, 42, 44, 46, 47, 60, 61, 62, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, - 85, 86, 87, 88, 92,255, 66, 68, 84,255, 42, 47,255, 35, 36, 38, 46, 47, - 255, 73, 83,255, 76, 78, 82,255, 68, 78,255, 70, 78,255, 68, 69, 73, 80, - 85,255, 42, 47,255, 38, 42, 47, 58,255, 61,255, 42, 47,255, 67, 68, 73, + 69, 79,255, 65, 71, 73,255, 82, 85,255, 72,255, 70,255, 84,255, 78,255, + 65, 73,255, 66, 83,255, 65, 67, 79, 82, 83, 85,255, 76, 82,255, 65,255, + 67, 68,255, 67, 90,255, 69, 71, 79,255, 67, 72,255, 86,255, 84,255, 65, + 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 67, 90,255, 66, 67, 73, + 78, 90,255, 69,255, 68, 73, 82, 88,255, 76, 82,255, 71, 72, 73,255, 88, + 255, 65, 67, 75,255, 66, 73,255, 66, 69, 72, 73, 80, 81, 84, 85, 89,255, + 69, 73,255, 65, 73,255, 67, 79, 82, 84,255, 33, 35, 36, 38, 39, 40, 42, + 44, 46, 47, 60, 61, 62, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, + 78, 79, 80, 82, 83, 84, 85, 86, 87, 88, 92,255, 66, 68, 84,255, 42, 47, + 255, 35, 36, 38, 46, 47,255, 73, 83,255, 76, 78, 82,255, 68, 78,255, 70, + 78,255, 70,255, 84,255, 78,255, 65, 73,255, 82,255, 68, 69, 73, 80, 85, + 255, 42, 47,255, 38, 42, 47, 58, 61,255, 61,255, 42, 47,255, 67, 68, 73, 255, 65, 73,255, 69, 72,255, 67, 68, 78, 82, 83,255, 67, 90,255, 69,255, 65,255, 67, 76, 77, 78, 80, 82, 89, 90,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 83, 90,255, 65, 68,255, 82, 88,255, @@ -1411,95 +1421,97 @@ static const unsigned char ag_key_ch[] = { 90,255, 88,255, 72, 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, 88,255, 76,255, 78, 83,255, 79, 85,255, 67, 68, 72, 73, 74, 80, 82, 83, 88,255, 68, 86,255, 65, 79, 83, 86,255, 65,255, 80,255, 65, 79,255, 65, 71, 73, - 255, 82, 85,255, 66, 83,255, 65, 67, 79, 82, 85,255, 76, 82,255, 65,255, - 67, 68,255, 67, 90,255, 69, 71, 79,255, 67, 72,255, 86,255, 84,255, 65, - 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 67, 90,255, 66, 67, 73, - 78, 90,255, 69,255, 68, 73, 82, 88,255, 76,255, 71, 72, 73,255, 88,255, - 65, 67, 75,255, 66, 73,255, 66, 69, 72, 73, 80, 84, 85, 89,255, 69, 73, - 255, 65, 73,255, 67, 82, 84,255, 36, 38, 42, 47, 65, 66, 67, 68, 69, 70, - 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, 86, 87, 88,255, 42, 47,255, - 85,255, 76,255, 67,255, 78,255, 47, 73,255, 61,255, 42, 47,255, 67, 68, - 73,255, 65, 73,255, 69, 72,255, 67, 68, 78, 82, 83,255, 67, 90,255, 69, - 255, 65,255, 67, 76, 77, 78, 80, 82, 89, 90,255, 65, 67, 80,255, 67, 90, - 255, 69, 73, 79,255, 65, 67, 77, 78, 80, 83, 90,255, 65, 68,255, 82, 88, - 255, 72, 83,255, 69, 85,255, 65, 66, 67, 69, 73, 83, 87,255, 73,255, 68, - 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 73, 76, 78, 88,255, 77, 84, - 255, 69, 76,255, 85,255, 76,255, 67, 82, 88,255, 70, 78,255, 80,255, 53, - 255, 67, 68, 75, 88, 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, - 77, 78, 80, 84, 88, 90,255, 88,255, 72, 83,255, 65, 69, 72, 83,255, 69, - 255, 68, 73, 88,255, 76,255, 78, 83,255, 79, 85,255, 67, 68, 72, 73, 74, - 80, 82, 83, 88,255, 68, 86,255, 65, 79, 83, 86,255, 65,255, 80,255, 65, - 79,255, 65, 71, 73,255, 82, 85,255, 66, 83,255, 65, 67, 79, 82, 85,255, - 76, 82,255, 65,255, 67, 68,255, 67, 90,255, 69, 71, 79,255, 67, 72,255, - 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 67, - 90,255, 66, 67, 73, 78, 90,255, 69,255, 68, 73, 82, 88,255, 76,255, 71, - 72, 73,255, 88,255, 65, 67, 75,255, 66, 73,255, 66, 72, 73, 80, 84, 85, - 89,255, 69, 73,255, 65, 73,255, 67, 82, 84,255, 36, 38, 42, 47, 65, 66, - 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, 86, 87, 88, - 255, 36, 38,255, 42, 47,255, 47,255, 76, 80,255, 71, 87,255, 78, 79,255, - 36, 38, 39, 67, 68, 70, 72, 73, 76, 78, 80, 83,255, 78, 88,255, 69, 72, - 76, 86,255, 66, 68, 84,255, 42, 47,255, 85,255, 76,255, 67,255, 78,255, - 35, 36, 38, 42, 46, 47, 73,255, 47, 61,255, 42, 47,255, 76, 89,255, 69, + 255, 82, 85,255, 70,255, 84,255, 78,255, 73,255, 66, 83,255, 65, 67, 79, + 82, 85,255, 76, 82,255, 65,255, 67, 68,255, 67, 90,255, 69, 71, 79,255, + 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, + 90,255, 67, 90,255, 66, 67, 73, 78, 90,255, 69,255, 68, 73, 82, 88,255, + 76,255, 71, 72, 73,255, 88,255, 65, 67, 75,255, 66, 73,255, 66, 69, 72, + 73, 80, 84, 85, 89,255, 69, 73,255, 65, 73,255, 67, 82, 84,255, 36, 38, + 42, 47, 61, 65, 66, 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 80, 82, + 83, 84, 86, 87, 88,255, 42, 47,255, 85,255, 76,255, 67,255, 78,255, 47, + 73,255, 61,255, 42, 47,255, 67, 68, 73,255, 65, 73,255, 69, 72,255, 67, + 68, 78, 82, 83,255, 67, 90,255, 69,255, 65,255, 67, 76, 77, 78, 80, 82, + 89, 90,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, + 80, 83, 90,255, 65, 68,255, 82, 88,255, 72, 83,255, 69, 85,255, 65, 66, + 67, 69, 73, 83, 87,255, 73,255, 68, 84,255, 78, 82,255, 69, 82,255, 84, + 255, 67, 73, 76, 78, 88,255, 77, 84,255, 69, 76,255, 85,255, 76,255, 67, + 82, 88,255, 70, 78,255, 80,255, 53,255, 67, 68, 75, 88, 90,255, 69, 79, + 255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, 88, 90,255, 88,255, + 72, 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, 88,255, 76,255, 78, 83, + 255, 79, 85,255, 67, 68, 72, 73, 74, 80, 82, 83, 88,255, 68, 86,255, 65, + 79, 83, 86,255, 65,255, 80,255, 65, 79,255, 65, 71, 73,255, 82, 85,255, + 70,255, 84,255, 78,255, 73,255, 66, 83,255, 65, 67, 79, 82, 85,255, 76, + 82,255, 65,255, 67, 68,255, 67, 90,255, 69, 71, 79,255, 67, 72,255, 86, + 255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 67, 90, + 255, 66, 67, 73, 78, 90,255, 69,255, 68, 73, 82, 88,255, 76,255, 71, 72, + 73,255, 88,255, 65, 67, 75,255, 66, 73,255, 66, 72, 73, 80, 84, 85, 89, + 255, 69, 73,255, 65, 73,255, 67, 82, 84,255, 36, 38, 42, 47, 65, 66, 67, + 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, 86, 87, 88,255, + 36, 38,255, 42, 47,255, 47,255, 76, 80,255, 71, 87,255, 78, 79,255, 36, + 38, 39, 67, 68, 70, 72, 73, 76, 78, 80, 83,255, 78, 88,255, 69, 72, 76, + 86,255, 66, 68, 84,255, 42, 47,255, 85,255, 76,255, 67,255, 78,255, 35, + 36, 38, 42, 46, 47, 73,255, 47, 61,255, 42, 47,255, 76, 89,255, 69,255, + 66, 83, 87,255, 68, 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 78, 81, + 88,255, 85,255, 76,255, 67,255, 78,255, 78, 83,255, 73, 83,255, 65, 79, + 83,255, 65, 79,255, 70,255, 84,255, 78,255, 73,255, 65, 82, 85,255, 69, + 84, 89,255, 69, 73,255, 36, 42, 47, 65, 66, 67, 68, 69, 70, 72, 73, 76, + 77, 78, 79, 80, 83, 84, 86, 87, 92,255, 85,255, 76,255, 67,255, 78,255, + 73,255, 42, 47,255, 42, 47,255, 42, 47, 92,255, 42, 47,255, 47, 73, 80, + 255, 42, 47,255, 33, 47,255, 67,255, 69, 88,255, 76,255, 66, 68, 72, 80, + 83,255, 40, 65, 66, 67, 68, 69, 72, 76, 77,255, 67,255, 69,255, 76,255, + 66, 68, 72, 83,255, 67,255, 69,255, 76,255, 65, 66, 68, 72, 80,255, 67, + 255, 69,255, 66, 68,255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, 62, + 255, 33, 42, 44, 47, 60, 61, 62,255, 61,255, 42, 47,255, 60, 61,255, 61, + 255, 61, 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 42, 44, + 47, 60, 61, 62, 65, 69, 71, 76, 77, 78, 79, 83, 88,255, 76, 89,255, 69, 255, 66, 83, 87,255, 68, 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 78, - 81, 88,255, 85,255, 76,255, 67,255, 78,255, 78, 83,255, 73, 83,255, 65, - 79, 83,255, 65, 79,255, 65, 82, 85,255, 69, 84, 89,255, 69, 73,255, 36, - 42, 47, 65, 66, 67, 68, 69, 70, 72, 73, 76, 77, 78, 79, 80, 83, 84, 86, - 87, 92,255, 85,255, 76,255, 67,255, 78,255, 73,255, 42, 47,255, 42, 47, - 255, 42, 47, 92,255, 42, 47,255, 47, 73, 80,255, 42, 47,255, 33, 47,255, - 67,255, 69, 88,255, 76,255, 66, 68, 72, 80, 83,255, 40, 65, 66, 67, 68, - 69, 72, 76, 77,255, 67,255, 69,255, 76,255, 66, 68, 72, 83,255, 67,255, - 69,255, 76,255, 65, 66, 68, 72, 80,255, 67,255, 69,255, 66, 68,255, 61, - 255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 33, 42, 44, 47, 60, 61, - 62,255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, + 88,255, 78, 83,255, 73, 83,255, 65, 79, 83,255, 65, 79,255, 70,255, 84, + 255, 78,255, 73,255, 65, 82, 85,255, 84, 89,255, 69, 73,255, 36, 42, 65, + 66, 67, 68, 69, 70, 72, 76, 77, 78, 79, 80, 83, 84, 86, 87,255, 42, 47, + 255, 44, 47,255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, + 84,255, 69, 84,255, 82,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, + 62, 65, 69, 71, 76, 77, 78, 79, 81, 83, 88,255, 39,255, 61,255, 42, 47, + 255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 82,255, 76, + 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 71, 76, 77, 78, 79, 81, 83, + 88,255, 42, 47,255, 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, 42, + 47, 67, 68, 70, 72, 73, 76, 78, 80, 83, 92,255, 76, 80,255, 71, 87,255, + 78, 79,255, 36, 38, 39, 67, 68, 70, 72, 73, 76, 80, 83,255, 42, 47,255, + 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, 42, 47, 67, 68, 70, 72, + 73, 76, 80, 83, 92,255, 61,255, 60, 61,255, 61,255, 61, 62,255, 69, 84, + 255, 69, 84,255, 76, 82,255, 72,255, 33, 42, 44, 60, 61, 62, 65, 69, 71, + 76, 77, 78, 79, 83, 88,255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, + 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 44, 47, 60, 61, + 62, 65, 69, 71, 76, 78, 79, 83, 88,255, 61,255, 42, 47,255, 61,255, 61, + 255, 61,255, 69, 84,255, 69, 84,255, 33, 44, 47, 60, 61, 62, 65, 69, 71, + 76, 78, 79, 88,255, 61,255, 42, 47,255, 61,255, 61,255, 61,255, 69, 84, + 255, 69, 84,255, 33, 44, 47, 60, 61, 62, 69, 71, 76, 78, 79, 88,255, 61, + 255, 42, 47,255, 61,255, 61,255, 61,255, 69, 84,255, 69, 84,255, 33, 44, + 47, 60, 61, 62, 69, 71, 76, 78, 79,255, 42, 47,255, 61,255, 61,255, 61, + 255, 69, 84,255, 69, 84,255, 33, 47, 60, 61, 62, 69, 71, 76, 78,255, 61, + 255, 42, 47,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 65, 69, 71, - 76, 77, 78, 79, 83, 88,255, 76, 89,255, 69,255, 66, 83, 87,255, 68, 84, - 255, 78, 82,255, 69, 82,255, 84,255, 67, 78, 88,255, 78, 83,255, 73, 83, - 255, 65, 79, 83,255, 65, 79,255, 65, 82, 85,255, 84, 89,255, 69, 73,255, - 36, 42, 65, 66, 67, 68, 69, 70, 72, 76, 77, 78, 79, 80, 83, 84, 86, 87, - 255, 42, 47,255, 44, 47,255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, - 62,255, 69, 84,255, 69, 84,255, 82,255, 76, 82,255, 72,255, 33, 42, 44, - 47, 60, 61, 62, 65, 69, 71, 76, 77, 78, 79, 81, 83, 88,255, 39,255, 61, - 255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, - 82,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 71, 76, 77, 78, - 79, 81, 83, 88,255, 42, 47,255, 76, 80,255, 71, 87,255, 78, 79,255, 36, - 38, 39, 42, 47, 67, 68, 70, 72, 73, 76, 78, 80, 83, 92,255, 76, 80,255, - 71, 87,255, 78, 79,255, 36, 38, 39, 67, 68, 70, 72, 73, 76, 80, 83,255, - 42, 47,255, 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, 42, 47, 67, - 68, 70, 72, 73, 76, 80, 83, 92,255, 61,255, 60, 61,255, 61,255, 61, 62, - 255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 42, 44, 60, 61, 62, - 65, 69, 71, 76, 77, 78, 79, 83, 88,255, 61,255, 42, 47,255, 60, 61,255, - 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 44, - 47, 60, 61, 62, 65, 69, 71, 76, 78, 79, 83, 88,255, 61,255, 42, 47,255, - 61,255, 61,255, 61,255, 69, 84,255, 69, 84,255, 33, 44, 47, 60, 61, 62, - 65, 69, 71, 76, 78, 79, 88,255, 61,255, 42, 47,255, 61,255, 61,255, 61, - 255, 69, 84,255, 69, 84,255, 33, 44, 47, 60, 61, 62, 69, 71, 76, 78, 79, - 88,255, 61,255, 42, 47,255, 61,255, 61,255, 61,255, 69, 84,255, 69, 84, - 255, 33, 44, 47, 60, 61, 62, 69, 71, 76, 78, 79,255, 42, 47,255, 61,255, - 61,255, 61,255, 69, 84,255, 69, 84,255, 33, 47, 60, 61, 62, 69, 71, 76, - 78,255, 61,255, 42, 47,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, - 69, 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, - 65, 69, 71, 76, 77, 78, 79, 83, 88, 92,255, 76, 89,255, 69,255, 66, 83, - 87,255, 68, 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 78, 81, 88,255, - 78, 83,255, 73, 83,255, 65, 79, 83,255, 65, 79,255, 65, 82, 85,255, 69, - 84, 89,255, 69, 73,255, 36, 42, 65, 66, 67, 68, 69, 70, 72, 76, 77, 78, - 79, 80, 83, 84, 86, 87,255, 39,255, 67, 68, 73,255, 65, 73,255, 67, 68, - 78, 82, 83,255, 67, 90,255, 69,255, 65,255, 67, 77, 78, 80, 82, 90,255, - 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 90,255, - 65, 68,255, 82, 88,255, 72, 83,255, 65, 67, 69, 73, 83,255, 77, 84,255, - 76,255, 82, 88,255, 78,255, 80,255, 53,255, 67, 68, 75, 88, 90,255, 69, - 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, 88, 90,255, 88, - 255, 72, 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, 88,255, 76,255, 79, - 85,255, 67, 68, 72, 74, 80, 82, 88,255, 79, 86,255, 65, 73,255, 82, 85, - 255, 67, 79, 85,255, 76, 82,255, 65,255, 67, 68,255, 67, 90,255, 69, 71, - 79,255, 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, - 82, 83, 90,255, 67, 90,255, 66, 67, 73, 78, 90,255, 69,255, 68, 73, 82, - 88,255, 76,255, 71, 72, 73,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, - 73, 80, 84, 85,255, 65, 73,255, 67, 82, 84,255, 65, 66, 67, 68, 69, 72, - 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 42, 47,255, 36, 38, 47,255, - 42, 47,255, 33, 44, 47,255, 44,255, 42, 47,255, 47, 79, 81,255, 92,255, - 69,255, 69,255, 76, 80,255, 73,255, 71, 87,255, 78, 79,255, 36, 38, 39, - 40, 65, 66, 67, 68, 69, 70, 72, 73, 76, 77, 78, 80, 83,255, 33,255, 42, - 47,255, 47, 92,255 + 76, 77, 78, 79, 83, 88, 92,255, 76, 89,255, 69,255, 66, 83, 87,255, 68, + 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 78, 81, 88,255, 78, 83,255, + 73, 83,255, 65, 79, 83,255, 65, 79,255, 70,255, 84,255, 78,255, 73,255, + 65, 82, 85,255, 69, 84, 89,255, 69, 73,255, 36, 42, 65, 66, 67, 68, 69, + 70, 72, 76, 77, 78, 79, 80, 83, 84, 86, 87,255, 39,255, 67, 68, 73,255, + 65, 73,255, 67, 68, 78, 82, 83,255, 67, 90,255, 69,255, 65,255, 67, 77, + 78, 80, 82, 90,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, + 77, 78, 80, 90,255, 65, 68,255, 82, 88,255, 72, 83,255, 65, 67, 69, 73, + 83,255, 77, 84,255, 76,255, 82, 88,255, 78,255, 80,255, 53,255, 67, 68, + 75, 88, 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, + 84, 88, 90,255, 88,255, 72, 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, + 88,255, 76,255, 79, 85,255, 67, 68, 72, 74, 80, 82, 88,255, 79, 86,255, + 65, 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 65,255, 67, 68,255, + 67, 90,255, 69, 71, 79,255, 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, + 73, 76, 77, 78, 80, 82, 83, 90,255, 67, 90,255, 66, 67, 73, 78, 90,255, + 69,255, 68, 73, 82, 88,255, 76,255, 71, 72, 73,255, 88,255, 65, 67,255, + 66, 73,255, 66, 72, 73, 80, 84, 85,255, 65, 73,255, 67, 82, 84,255, 65, + 66, 67, 68, 69, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 42, 47, + 255, 36, 38, 47,255, 42, 47,255, 33, 44, 47,255, 44,255, 42, 47,255, 47, + 79, 81,255, 92,255, 69,255, 69,255, 76, 80,255, 73,255, 71, 87,255, 78, + 79,255, 36, 38, 39, 40, 65, 66, 67, 68, 69, 70, 72, 73, 76, 77, 78, 80, + 83,255, 33,255, 42, 47,255, 47, 92,255 }; static const unsigned char ag_key_act[] = { @@ -1511,190 +1523,195 @@ static const unsigned char ag_key_act[] = { 4,2,7,5,5,4,6,6,5,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2, 6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4,2,4,7,7,4,5,5,4,7,7,4,7,2,5,2,2, 7,5,2,2,7,7,5,7,4,7,4,6,5,4,7,2,7,7,4,7,4,6,5,4,7,5,2,4,5,5,5,4,6,7,4, - 7,4,7,7,4,7,7,4,7,6,7,2,7,2,4,5,5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4, - 6,4,2,6,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5,5,5,4,6,5,4,5, - 7,5,4,5,4,6,5,7,4,5,5,4,2,7,2,7,6,7,2,2,7,4,7,7,4,5,5,4,7,7,2,7,4,6,0, - 6,0,3,3,2,0,2,2,1,1,1,6,6,6,6,6,2,2,6,2,2,6,6,2,2,2,2,2,2,7,7,7,2,3,4, - 3,3,3,4,0,0,4,0,5,0,2,2,4,7,7,4,2,7,7,4,7,7,4,6,7,4,7,2,2,7,7,4,0,0,4, - 0,3,2,0,4,0,4,0,0,4,5,5,5,4,5,5,4,7,7,4,7,2,2,7,2,4,5,5,4,5,4,5,4,5,7, - 5,2,6,6,7,5,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5,4,5,5,4,5,5,4,7,7,4, - 7,7,4,2,5,2,2,5,6,5,4,7,4,6,7,4,7,7,4,2,7,4,2,4,7,5,7,2,7,2,4,7,5,4,7, - 2,4,5,5,4,5,6,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5, - 4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4,2,4,7,7,4,7,7,4,7,2,2,2,7,2,7,7,7,4, - 7,5,4,7,2,7,7,4,7,4,6,4,7,2,4,5,5,5,4,2,7,4,7,7,4,7,7,7,7,2,4,5,5,4,7, - 4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4,6,4,2,6,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5, - 5,5,2,5,4,5,4,6,5,5,5,4,2,4,5,7,5,4,5,4,6,5,7,4,5,5,4,2,7,2,7,2,2,2,7, - 4,7,7,4,5,5,4,7,2,7,4,6,0,3,2,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,7,7,2, - 4,0,0,4,7,4,6,4,2,4,2,4,2,2,4,0,4,0,0,4,5,5,5,4,5,5,4,7,7,4,7,2,2,7,2, - 4,5,5,4,5,4,5,4,5,7,5,2,6,6,7,5,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5, - 4,5,5,4,5,5,4,7,7,4,7,7,4,2,5,2,2,5,6,5,4,7,4,6,7,4,7,7,4,2,7,4,2,4,7, - 5,7,2,2,4,7,5,4,7,2,4,7,4,6,4,2,5,5,4,5,6,4,5,4,5,4,5,5,5,6,5,4,5,5,4, - 5,5,4,5,4,5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4,2,4,7,7, - 4,7,7,4,7,2,2,2,7,2,7,7,7,4,7,5,4,7,2,7,7,4,7,4,6,4,7,2,4,5,5,5,4,2,7, - 4,7,7,4,7,7,7,7,2,4,5,5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4,6,4,2,6,7, + 7,4,5,4,6,4,2,4,7,2,4,7,7,4,7,6,7,2,7,2,4,5,5,4,7,4,5,7,4,5,5,4,5,5,5, + 4,5,7,4,5,4,6,4,2,6,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5,5, + 5,4,6,5,4,5,7,5,4,5,4,6,5,7,4,5,5,4,2,7,2,7,6,7,2,2,7,4,7,7,4,5,5,4,7, + 7,2,7,4,6,0,6,0,3,3,2,0,2,2,1,1,1,6,6,6,6,6,2,2,6,2,2,6,6,2,2,2,2,2,2, + 7,7,7,2,3,4,3,3,3,4,0,0,4,0,5,0,2,2,4,7,7,4,2,7,7,4,7,7,4,6,7,4,5,4,6, + 4,2,4,7,2,4,2,4,7,2,2,2,7,4,0,0,4,0,3,2,0,0,4,0,4,0,0,4,5,5,5,4,5,5,4, + 7,7,4,7,2,2,7,2,4,5,5,4,5,4,5,4,5,7,5,2,6,6,7,5,4,5,5,5,4,5,5,4,5,5,5, + 4,7,5,6,2,6,7,5,4,5,5,4,5,5,4,7,7,4,7,7,4,2,5,2,2,5,6,5,4,7,4,6,7,4,7, + 7,4,2,7,4,2,4,7,5,7,2,7,2,4,7,5,4,7,2,4,5,5,4,5,6,4,5,4,5,4,5,5,5,6,5, + 4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4, + 2,4,7,7,4,7,7,4,7,2,2,2,7,2,7,7,7,4,7,5,4,7,2,7,7,4,7,4,6,4,7,2,4,5,5, + 5,4,2,7,4,5,4,6,4,2,4,2,4,7,7,4,7,7,7,2,2,4,5,5,4,7,4,5,7,4,5,5,4,5,5, + 5,4,5,7,4,5,4,6,4,2,6,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5, + 5,5,4,2,4,5,7,5,4,5,4,6,5,7,4,5,5,4,2,7,2,7,2,2,2,7,4,7,7,4,5,5,4,7,2, + 7,4,6,0,3,2,0,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,7,7,2,4,0,0,4,7,4,6,4, + 2,4,2,4,2,2,4,0,4,0,0,4,5,5,5,4,5,5,4,7,7,4,7,2,2,7,2,4,5,5,4,5,4,5,4, + 5,7,5,2,6,6,7,5,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5,4,5,5,4,5,5,4,7, + 7,4,7,7,4,2,5,2,2,5,6,5,4,7,4,6,7,4,7,7,4,2,7,4,2,4,7,5,7,2,2,4,7,5,4, + 7,2,4,7,4,6,4,2,5,5,4,5,6,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5, + 6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4,2,4,7,7,4,7,7,4,7,2,2,2, + 7,2,7,7,7,4,7,5,4,7,2,7,7,4,7,4,6,4,7,2,4,5,5,5,4,2,7,4,5,4,6,4,2,4,2, + 4,7,7,4,7,7,7,2,2,4,5,5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4,6,4,2,6,7, 7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5,5,5,4,2,4,5,7,5,4,5,4,6, 5,7,4,5,5,4,2,2,7,2,2,2,7,4,7,7,4,5,5,4,7,2,7,4,6,0,3,2,2,2,2,2,2,7,2, 2,2,2,2,2,2,2,2,2,2,7,7,2,4,5,0,4,0,0,4,2,4,7,5,4,5,5,4,5,2,4,5,0,3,7, 7,2,7,7,2,7,7,7,4,7,7,4,2,7,7,7,4,3,3,3,4,0,0,4,7,4,6,4,2,4,2,4,0,5,0, 3,2,2,2,4,0,0,4,0,0,4,7,7,4,7,4,5,6,5,4,5,7,4,7,7,4,2,7,4,2,4,7,2,7,2, - 4,7,4,6,4,2,4,2,4,7,7,4,2,7,4,7,7,7,4,7,7,4,7,7,7,4,7,7,7,4,7,7,4,3,2, - 2,7,2,7,2,2,7,7,2,2,2,2,7,2,2,2,7,7,3,4,7,4,6,4,2,4,2,4,2,4,3,3,4,0,0, - 4,3,2,3,4,0,0,4,2,7,7,4,0,0,4,5,2,4,5,4,5,5,4,5,4,6,6,6,7,7,4,3,5,5,5, - 5,5,5,5,5,4,5,4,5,4,5,4,6,6,6,7,4,5,4,5,4,5,4,5,6,6,6,7,4,5,4,5,4,6,6, - 4,0,4,0,0,4,0,0,4,0,4,0,0,4,6,3,0,2,1,1,1,4,0,4,0,0,4,0,0,4,0,4,0,0,4, - 5,5,4,5,5,4,5,5,4,2,4,6,3,0,2,1,1,1,7,7,2,2,7,7,7,2,7,4,7,7,4,7,4,5,6, - 5,4,5,7,4,7,7,4,2,7,4,2,4,7,2,2,4,7,7,4,2,7,4,7,7,7,4,7,7,4,7,7,7,4,7, - 7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2,2,7,2,2,2,7,7,4,0,0,4,0,2,4,0,4,0,0,4, - 0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,4,5,5,4,2,4,6,3,0,2,1,1,1,7,7,2,2,7,7,6, - 5,2,7,4,3,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,4,5,5,4,2,4,6,3,0, - 2,1,1,1,2,2,7,7,6,5,2,7,4,0,0,4,7,5,4,5,5,4,5,2,4,5,0,3,3,2,7,7,2,7,7, - 2,7,7,7,3,4,7,5,4,5,5,4,5,2,4,5,0,3,7,7,2,7,7,2,7,7,4,0,0,4,7,5,4,5,5, - 4,5,2,4,5,0,3,3,2,7,7,2,7,7,2,7,7,3,4,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4, - 5,5,4,2,4,6,3,0,1,1,1,7,7,2,2,7,7,7,2,7,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5, - 5,4,5,5,4,5,5,4,2,4,6,0,2,1,1,1,7,7,2,2,7,7,2,7,4,0,4,0,0,4,0,4,0,4,0, - 4,5,5,4,5,5,4,6,0,2,1,1,1,7,7,2,2,7,7,7,4,0,4,0,0,4,0,4,0,4,0,4,5,5,4, - 5,5,4,6,0,2,1,1,1,7,2,2,7,7,7,4,0,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,6,0, - 2,1,1,1,7,2,2,7,7,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,3,2,1,1,1,7,2,2,7,4, - 0,4,0,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,2,0,2,1,1,1,7, - 7,2,2,7,7,7,2,7,3,4,7,7,4,7,4,5,6,5,4,5,7,4,7,7,4,2,7,4,2,4,7,2,7,2,4, - 7,7,4,2,7,4,7,7,7,4,7,7,4,7,7,7,4,7,7,7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2, - 2,7,2,2,2,7,7,4,3,4,5,5,5,4,5,5,4,7,2,2,7,7,4,5,5,4,5,4,5,4,5,5,2,6,6, - 5,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,7,7,4,2,2,2,5,7,4, - 7,5,4,2,4,5,5,4,6,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2, - 6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4,2,4,7,7,4,7,2,2,7,2,7,7,4,7,7,4, - 5,5,4,2,7,4,7,7,7,4,5,5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4,6,4,2,6,7, - 7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5,5,5,4,2,4,5,7,5,4,5,4,6, - 5,4,5,5,4,2,2,7,2,2,2,4,5,5,4,7,2,7,4,2,2,2,2,7,2,2,2,2,2,7,2,2,2,2,2, - 4,0,0,4,5,0,2,4,0,0,4,5,0,2,4,0,4,0,0,4,2,5,5,4,3,4,7,4,7,4,7,5,4,7,4, - 5,5,4,5,2,4,5,0,3,3,5,5,6,6,5,2,6,7,6,5,7,7,7,4,5,4,0,0,4,2,3,4 + 4,7,4,6,4,2,4,2,4,7,7,4,2,7,4,7,7,7,4,7,7,4,5,4,6,4,2,4,2,4,7,2,7,4,7, + 7,7,4,7,7,4,3,2,2,7,2,7,2,2,7,7,2,2,2,2,7,2,2,2,7,7,3,4,7,4,6,4,2,4,2, + 4,2,4,3,3,4,0,0,4,3,2,3,4,0,0,4,2,7,7,4,0,0,4,5,2,4,5,4,5,5,4,5,4,6,6, + 6,7,7,4,3,5,5,5,5,5,5,5,5,4,5,4,5,4,5,4,6,6,6,7,4,5,4,5,4,5,4,5,6,6,6, + 7,4,5,4,5,4,6,6,4,0,4,0,0,4,0,0,4,0,4,0,0,4,6,3,0,2,1,1,1,4,0,4,0,0,4, + 0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,3,0,2,1,1,1,7,7,2,2,7,7,7,2,7, + 4,7,7,4,7,4,5,6,5,4,5,7,4,7,7,4,2,7,4,2,4,7,2,2,4,7,7,4,2,7,4,7,7,7,4, + 7,7,4,5,4,6,4,2,4,2,4,7,2,7,4,7,7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2,2,7,2, + 2,2,7,7,4,0,0,4,0,2,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,4,5,5,4, + 2,4,6,3,0,2,1,1,1,7,7,2,2,7,7,6,5,2,7,4,3,4,0,4,0,0,4,0,0,4,0,4,0,0,4, + 5,5,4,5,5,4,5,4,5,5,4,2,4,6,3,0,2,1,1,1,2,2,7,7,6,5,2,7,4,0,0,4,7,5,4, + 5,5,4,5,2,4,5,0,3,3,2,7,7,2,7,7,2,7,7,7,3,4,7,5,4,5,5,4,5,2,4,5,0,3,7, + 7,2,7,7,2,7,7,4,0,0,4,7,5,4,5,5,4,5,2,4,5,0,3,3,2,7,7,2,7,7,2,7,7,3,4, + 0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,3,0,1,1,1,7,7,2,2,7,7,7,2, + 7,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,0,2,1,1,1,7,7,2, + 2,7,7,2,7,4,0,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,6,0,2,1,1,1,7,7,2,2,7,7, + 7,4,0,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,6,0,2,1,1,1,7,2,2,7,7,7,4,0,4,0, + 0,4,0,4,0,4,0,4,5,5,4,5,5,4,6,0,2,1,1,1,7,2,2,7,7,4,0,0,4,0,4,0,4,0,4, + 5,5,4,5,5,4,3,2,1,1,1,7,2,2,7,4,0,4,0,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4, + 5,5,4,5,5,4,2,4,6,2,0,2,1,1,1,7,7,2,2,7,7,7,2,7,3,4,7,7,4,7,4,5,6,5,4, + 5,7,4,7,7,4,2,7,4,2,4,7,2,7,2,4,7,7,4,2,7,4,7,7,7,4,7,7,4,5,4,6,4,2,4, + 2,4,7,2,7,4,7,7,7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2,2,7,2,2,2,7,7,4,3,4,5, + 5,5,4,5,5,4,7,2,2,7,7,4,5,5,4,5,4,5,4,5,5,2,6,6,5,4,5,5,5,4,5,5,4,5,5, + 5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,7,7,4,2,2,2,5,7,4,7,5,4,2,4,5,5,4,6,4,5, + 4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7, + 7,4,5,4,6,5,5,4,2,4,7,7,4,7,2,2,7,2,7,7,4,7,7,4,5,5,4,2,7,4,7,7,7,4,5, + 5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4,6,4,2,6,7,7,7,2,5,2,6,2,2,5,4,5, + 5,4,5,5,5,2,5,4,5,4,6,5,5,5,4,2,4,5,7,5,4,5,4,6,5,4,5,5,4,2,2,7,2,2,2, + 4,5,5,4,7,2,7,4,2,2,2,2,7,2,2,2,2,2,7,2,2,2,2,2,4,0,0,4,5,0,2,4,0,0,4, + 5,0,2,4,0,4,0,0,4,2,5,5,4,3,4,7,4,7,4,7,5,4,7,4,5,5,4,5,2,4,5,0,3,3,5, + 5,6,6,5,2,6,7,6,5,7,7,7,4,5,4,0,0,4,2,3,4 }; static const unsigned short ag_key_parm[] = { - 0,160,162,161, 0,427,424, 0, 4, 0, 6, 0, 0, 0, 0, 0,437, 96, - 133, 0, 0, 0, 0,497, 0,460, 0,522,426,461, 0,160,162,161, 0,427, - 424, 0,512,501, 0,494, 0,499,514, 0,280,282,322, 0,284,116,324, 0, - 44,182, 0,320, 0, 0,186, 0, 0,424,422, 0,430, 0,418, 0,166, 48, - 426, 0,428,416, 52,420, 0,190,192,286, 0,332,334, 0,338,340,342, 0, - 326,328,128,330, 0,336, 38,344, 0,194,306, 0,288,308, 0,144, 0, 36, - 0, 0, 0, 0, 0, 0,390,396, 0, 40,198, 0, 0, 50, 0,168,196, 46, - 56,176, 0, 24, 28, 0, 30, 0, 78, 14, 0, 0, 0, 18, 64, 0, 0, 62, - 0, 0, 0, 72,202, 0, 0,100, 32, 0, 0, 74,126,138, 0,104,108, 0, - 200,204, 0, 12,140,170, 0, 20, 26, 0, 4, 0, 6, 0, 0, 98,290,310, - 0, 22,346,136, 0,362, 0,368, 0,364,374,372,366,376, 0,380,382, 0, - 354,370, 0,352, 0,348,358,356,360, 0,378, 0,350,384, 0,270, 0,388, - 394, 0,386, 0,392,398, 0,210, 0,400,208,206, 0, 0, 0, 90, 10, 0, - 132,142, 0,276,278, 0,442, 0,106, 0, 0,444,130, 0, 0,266, 82,110, - 312, 0, 66, 0,122,292, 0, 92, 0, 80,314, 0, 86, 0,212,124, 0, 68, - 102, 0, 0,294, 42,402, 0,112,404, 0,214, 0, 8, 76, 0, 60,274, 0, - 94,178,272, 0,174, 0, 0,216,218, 0,432, 0,226,228, 0,234,236, 0, - 240,304,242, 0,244,188, 0,246, 0,318, 0, 0,220,230,222,224, 0,232, - 0,238, 0, 0,248, 0,440,436, 0,296,438,406, 0,434, 0,254, 0,408, - 252,184,250, 0,118,120, 0,302,258,316, 0,268, 0,410,260, 70, 0,298, - 412, 0, 0, 2, 0,256,172,134, 0, 0, 88, 0, 54, 84, 0,300,414, 0, - 262,114, 0,264, 0,180,437, 96,133,230,240, 0,491, 0, 0,505,495,503, - 164,150,152,154,156, 0, 0,158, 0, 0,160,162, 0, 0, 0, 0, 0, 0, - 34, 16, 58, 0,456, 0,160,162,161, 0,427,424, 0,437, 96,133, 0, 0, - 0, 24, 28, 0, 0, 30, 32, 0, 20, 26, 0, 22, 4, 0, 36, 0, 0, 8, - 34, 0,427,424, 0,133,461, 0,159, 0,460, 0,427,424, 0,280,282,322, - 0,284,324, 0, 44,182, 0,320, 0, 0,186, 0, 0,424,422, 0,430, 0, - 418, 0,166, 48,426, 0,428,416, 52,420, 0,190,192,286, 0,332,334, 0, - 338,340,342, 0,326,328,330, 0,336, 38,344, 0,194,306, 0,288,308, 0, - 390,396, 0, 40,198, 0, 0, 50, 0, 0,196, 46, 56, 0, 30, 0, 78, 14, - 0, 18, 64, 0, 0, 62, 0, 0, 0, 72,202, 28, 0, 0, 0, 0,200,204, - 0, 12, 0, 0,290,310, 0, 22,346, 0,362, 0,368, 0,364,374,372,366, - 376, 0,380,382, 0,354,370, 0,352, 0,348,358,356,360, 0,378, 0,350, - 384, 0,270, 0,388,394, 0,386, 0,392,398, 0,210, 0,400,208,206, 0, - 0, 0, 90, 10, 0,276,278, 0,442, 0, 0, 0,444, 0,266, 82,312, 0, - 66,292, 0, 92, 0, 80,314, 0, 86, 0,212, 0, 68, 0, 0,294, 42,402, - 0, 0,404, 0, 60,274, 0, 94,214,272, 76, 0, 0,216,218, 0,432, 0, - 226,228, 0,234,236, 0,240,304,242, 0,244,188, 0,246, 0,318, 0, 0, - 220,230,222,224, 0,232, 0,238, 0, 0,248, 0,440,436, 0,296,438,406, - 0,434, 0,254, 0,408,252,184,250, 0, 0, 0,302,258,316, 0,268, 0, - 410,260, 70, 0,298,412, 0, 0, 2, 0,256, 0, 0, 0, 88, 0, 54, 84, - 0,300,414, 0,262, 0,264, 0, 96,133,461, 0, 0, 0, 0, 0, 0, 74, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 58, 0, 0,427,424, 0, - 4, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0,460, 0,427,424, 0,280,282, - 322, 0,284,324, 0, 44,182, 0,320, 0, 0,186, 0, 0,424,422, 0,430, - 0,418, 0,166, 48,426, 0,428,416, 52,420, 0,190,192,286, 0,332,334, - 0,338,340,342, 0,326,328,330, 0,336, 38,344, 0,194,306, 0,288,308, - 0,390,396, 0, 40,198, 0, 0, 50, 0, 0,196, 46, 56, 0, 30, 0, 78, - 14, 0, 18, 64, 0, 0, 62, 0, 0, 0, 72,202, 28, 0, 0, 0,200,204, - 0, 12, 0, 0, 4, 0, 6, 0, 0,290,310, 0, 22,346, 0,362, 0,368, - 0,364,374,372,366,376, 0,380,382, 0,354,370, 0,352, 0,348,358,356, - 360, 0,378, 0,350,384, 0,270, 0,388,394, 0,386, 0,392,398, 0,210, - 0,400,208,206, 0, 0, 0, 90, 10, 0,276,278, 0,442, 0, 0, 0,444, - 0,266, 82,312, 0, 66,292, 0, 92, 0, 80,314, 0, 86, 0,212, 0, 68, - 0, 0,294, 42,402, 0, 0,404, 0, 60,274, 0, 94,214,272, 76, 0, 0, - 216,218, 0,432, 0,226,228, 0,234,236, 0,240,304,242, 0,244,188, 0, - 246, 0,318, 0, 0,220,230,222,224, 0,232, 0,238, 0, 0,248, 0,440, - 436, 0,296,438,406, 0,434, 0,254, 0,408,252,184,250, 0, 0, 0,302, - 258,316, 0,268, 0,410,260, 70, 0,298,412, 0, 0, 0,256, 0, 0, 0, - 88, 0, 54, 84, 0,300,414, 0,262, 0,264, 0, 96,133,461, 0, 0, 0, - 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 58, 0, - 0, 96,133, 0,427,424, 0, 0, 0,126,138, 0,132,142, 0,130, 0, 0, - 96,133,230,128,144, 0,140,136, 0,124, 94,134, 0, 14, 18, 0, 0, 12, - 10, 16, 0,160,162,161, 0,427,424, 0, 4, 0, 6, 0, 0, 0, 0, 0, - 437, 96,133,426, 0, 0, 0, 0,426,461, 0,427,424, 0, 48, 52, 0, 40, - 0, 50, 46, 56, 0, 78, 14, 0, 18, 64, 0, 0, 62, 0, 0, 0, 72, 0, - 0, 0, 0, 4, 0, 6, 0, 0, 0, 0, 0, 90, 10, 0, 0, 82, 0, 92, - 66, 80, 0, 68, 86, 0, 94, 76, 60, 0, 2, 70, 88, 0, 54, 84, 0,460, - 0, 0, 44, 0, 38, 0, 0, 74, 12, 0, 0, 0, 0, 42, 0, 0, 0, 16, - 58,456, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0,426,427, 0,427,424, - 0,426, 0,456, 0,427,424, 0, 0, 98, 94, 0,427,424, 0,180, 0, 0, - 166, 0,168,176, 0,170, 0,150,154,158,178,172, 0,240,164,150,152,154, - 156,158,160,162, 0,166, 0,168, 0,170, 0,150,154,158,172, 0,166, 0, - 168, 0,170, 0,164,150,154,158,174, 0,166, 0,168, 0,150,154, 0,497, - 0,427,424, 0,512,501, 0,494, 0,499,514, 0,180,522,491, 0,505,495, - 503, 0,497, 0,427,424, 0,512,501, 0,494, 0,499,514, 0,104,108, 0, - 106,110, 0,118,120, 0, 0, 0,180,522,491, 0,505,495,503,116,100, 0, - 0,122,102,112, 0,114, 0, 48, 52, 0, 40, 0, 50, 46, 56, 0, 78, 14, - 0, 18, 64, 0, 0, 62, 0, 0, 0, 72, 0, 0, 0, 90, 10, 0, 0, 82, - 0, 92, 66, 80, 0, 68, 86, 0, 94, 76, 60, 0, 70, 88, 0, 54, 84, 0, - 460,461, 44, 0, 38, 0, 0, 74, 12, 0, 0, 0, 42, 0, 0, 0, 16, 58, - 0,427,424, 0,491, 0, 0,497, 0,427,424, 0,512,501, 0,494, 0,499, - 514, 0,104,108, 0,106,110, 0,112, 0,118,120, 0, 0, 0,180,522,491, - 0,505,495,503,116,100, 0, 0,122,102,148,146, 0,114, 0,232, 0,497, - 0,427,424, 0,512,501, 0,494, 0,499,514, 0,104,108, 0,106,110, 0, - 112, 0,118,120, 0, 0, 0,180,522,491, 0,505,495,503, 0, 0,122,102, - 148,146, 0,114, 0,427,424, 0,126,138, 0,132,142, 0,130, 0, 0, 96, - 133,230,426, 0,128,144, 0,140,136, 0,124, 94,134,456, 0,126,138, 0, - 132,142, 0,130, 0, 0, 96,133,230,128,144, 0,140,136, 0, 94,134, 0, - 427,424, 0,126,138, 0,132,142, 0,130, 0, 0, 96,133,230,426, 0,128, - 144, 0,140,136, 0, 94,134,456, 0,497, 0,512,501, 0,494, 0,499,514, - 0,104,108, 0,106,110, 0,118,120, 0, 0, 0,180,522,491,505,495,503, - 116,100, 0, 0,122,102,112, 0,114, 0,497, 0,427,424, 0,512,501, 0, - 494, 0,499,514, 0,104,108, 0,106,110, 0,118,120, 0, 0, 0,180,491, - 0,505,495,503,116,100, 0, 0,102,112, 0,114, 0,497, 0,427,424, 0, - 501, 0,494, 0,499, 0,104,108, 0,106,110, 0,180,491, 0,505,495,503, - 116,100, 0, 0,102,112,114, 0,497, 0,427,424, 0,501, 0,494, 0,499, - 0,104,108, 0,106,110, 0,180,491, 0,505,495,503,100, 0, 0,102,112, - 114, 0,497, 0,427,424, 0,501, 0,494, 0,499, 0,104,108, 0,106,110, - 0,180,491, 0,505,495,503,100, 0, 0,102,112, 0,427,424, 0,501, 0, - 494, 0,499, 0,104,108, 0,106,110, 0,497, 0,505,495,503,100, 0, 0, - 102, 0,497, 0,522,426, 0,427,424, 0,512,501, 0,494, 0,499,514, 0, - 104,108, 0,106,110, 0,118,120, 0, 0, 0,180, 0,491, 0,505,495,503, - 116,100, 0, 0,122,102,112, 0,114,456, 0, 48, 52, 0, 40, 0, 50, 46, - 56, 0, 78, 14, 0, 18, 64, 0, 0, 62, 0, 0, 0, 72, 0, 0, 0, 0, - 90, 10, 0, 0, 82, 0, 92, 66, 80, 0, 68, 86, 0, 94, 76, 60, 0, 2, - 70, 88, 0, 54, 84, 0,460,461, 44, 0, 38, 0, 0, 74, 12, 0, 0, 0, - 42, 0, 0, 0, 16, 58, 0,230, 0,280,282,322, 0,284,324, 0,320, 0, - 0,186,182, 0,424,422, 0,430, 0,418, 0,166,426, 0,428,416,420, 0, - 190,192,286, 0,332,334, 0,338,340,342, 0,326,328,330, 0,336,344, 0, - 194,306, 0,288,308, 0,390,396, 0, 0, 0, 0,196,198, 0,200,204, 0, - 0, 0,290,310, 0,346, 0,362, 0,368, 0,364,374,372,366,376, 0,380, - 382, 0,354,370, 0,352, 0,348,358,356,360, 0,378, 0,350,384, 0,270, - 0,388,394, 0,386, 0,392,398, 0,210, 0,400,208,206, 0, 0, 0,276, - 278, 0,442, 0, 0,444, 0,266,312, 0,292,314, 0,294,402, 0, 0,404, - 0,214,272,274, 0,216,218, 0,432, 0,226,228, 0,234,236, 0,240,304, - 242, 0,244,188, 0,246, 0,318, 0, 0,220,230,222,224, 0,232, 0,238, - 0, 0,248, 0,440,436, 0,296,438,406, 0,434, 0,254, 0,408,252,184, - 250, 0, 0, 0,302,258,316, 0,268, 0,410,260, 0,298,412, 0, 0, 0, - 256, 0, 0, 0, 0,300,414, 0,262, 0,264, 0, 0, 0, 0, 0,202, 0, - 0, 0, 0, 0,212, 0, 0, 0, 0, 0, 0,427,424, 0, 96,133, 0, 0, - 427,424, 0,180,491, 0, 0,491, 0,427,424, 0, 0,148,146, 0,456, 0, - 128, 0,144, 0,126,138, 0,140, 0,132,142, 0,130, 0, 0, 96,133,230, - 240,164,150,152,154,156, 0,158,136,160,162,124, 94,134, 0,180, 0,427, - 424, 0, 0,456, 0 + 0,162,164,163, 0,427,424, 0, 4, 0, 6, 0, 0, 0, 0, 0,438, 98, + 135, 0, 0, 0, 0,498, 0,464, 0,523,426,465, 0,162,164,163, 0,427, + 424, 0,513,502, 0,496, 0,500,515, 0,282,284,324, 0,286,118,326, 0, + 48,184, 0,322, 0, 0,188, 0, 0,426,424, 0,432, 0,420, 0,168, 52, + 428, 0,430,418, 56,422, 0,192,194,288, 0,334,336, 0,340,342,344, 0, + 328,330,130,332, 0,338, 42,346, 0,196,308, 0,290,310, 0,146, 0, 40, + 0, 0, 0, 0, 0, 0,392,398, 0, 44,200, 0, 0, 54, 0,170,198, 50, + 60,178, 0, 24, 28, 0, 30, 0, 80, 14, 0, 0, 0, 18, 68, 0, 0, 66, + 0, 0, 0, 76,204, 0, 0,102, 32, 0, 0, 78,128,140, 0,106,110, 0, + 202,206, 0, 12,142,172, 0, 20, 26, 0, 4, 0, 6, 0, 0,100,292,312, + 0, 22,348,138, 0,364, 0,370, 0,366,376,374,368,378, 0,382,384, 0, + 356,372, 0,354, 0,350,360,358,362, 0,380, 0,352,386, 0,272, 0,390, + 396, 0,388, 0,394,400, 0,212, 0,402,210,208, 0, 0, 0, 92, 10, 0, + 134,144, 0,278,280, 0,444, 0,108, 0, 0,446,132, 0, 0,268, 84,112, + 314, 0, 70, 0,124,294, 0, 94, 0, 82,316, 0, 88, 0,214,126, 0, 72, + 104, 0, 0,296, 46,404, 0,114,406, 0,216, 0, 36, 0, 34, 0, 0, 0, + 8, 0, 0, 64,276, 0, 96,180,274, 0,176, 0, 0,218,220, 0,434, 0, + 228,230, 0,236,238, 0,242,306,244, 0,246,190, 0,248, 0,320, 0, 0, + 222,232,224,226, 0,234, 0,240, 0, 0,250, 0,442,438, 0,298,440,408, + 0,436, 0,256, 0,410,254,186,252, 0,120,122, 0,304,260,318, 0,270, + 0,412,262, 74, 0,300,414, 0, 0, 2, 0,258,174,136, 0, 0, 90, 0, + 58, 86, 0,302,416, 0,264,116, 0,266, 0,182,438, 98,135,231,241, 0, + 493, 0, 0,506,432,504,166,152,154,156,158, 0, 0,160, 0, 0,162,164, + 0, 0, 0, 0, 0, 0, 38, 16, 62, 0,460, 0,162,164,163, 0,427,424, + 0,438, 98,135, 0, 0, 0, 24, 28, 0, 0, 30, 32, 0, 20, 26, 0, 22, + 4, 0, 36, 0, 34, 0, 0, 0, 8, 0, 0, 0, 0, 40, 0, 0, 0, 38, + 0,427,424, 0,135,465, 0,161,432, 0,464, 0,427,424, 0,282,284,324, + 0,286,326, 0, 48,184, 0,322, 0, 0,188, 0, 0,426,424, 0,432, 0, + 420, 0,168, 52,428, 0,430,418, 56,422, 0,192,194,288, 0,334,336, 0, + 340,342,344, 0,328,330,332, 0,338, 42,346, 0,196,308, 0,290,310, 0, + 392,398, 0, 44,200, 0, 0, 54, 0, 0,198, 50, 60, 0, 30, 0, 80, 14, + 0, 18, 68, 0, 0, 66, 0, 0, 0, 76,204, 28, 0, 0, 0, 0,202,206, + 0, 12, 0, 0,292,312, 0, 22,348, 0,364, 0,370, 0,366,376,374,368, + 378, 0,382,384, 0,356,372, 0,354, 0,350,360,358,362, 0,380, 0,352, + 386, 0,272, 0,390,396, 0,388, 0,394,400, 0,212, 0,402,210,208, 0, + 0, 0, 92, 10, 0,278,280, 0,444, 0, 0, 0,446, 0,268, 84,314, 0, + 70,294, 0, 94, 0, 82,316, 0, 88, 0,214, 0, 72, 0, 0,296, 46,404, + 0, 0,406, 0, 36, 0, 34, 0, 0, 0, 0, 0, 64,276, 0, 96,216,274, + 0, 0, 0,218,220, 0,434, 0,228,230, 0,236,238, 0,242,306,244, 0, + 246,190, 0,248, 0,320, 0, 0,222,232,224,226, 0,234, 0,240, 0, 0, + 250, 0,442,438, 0,298,440,408, 0,436, 0,256, 0,410,254,186,252, 0, + 0, 0,304,260,318, 0,270, 0,412,262, 74, 0,300,414, 0, 0, 2, 0, + 258, 0, 0, 0, 90, 0, 58, 86, 0,302,416, 0,264, 0,266, 0, 98,135, + 465, 0,432, 0, 0, 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 16, 62, 0, 0,427,424, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, + 0, 0,464, 0,427,424, 0,282,284,324, 0,286,326, 0, 48,184, 0,322, + 0, 0,188, 0, 0,426,424, 0,432, 0,420, 0,168, 52,428, 0,430,418, + 56,422, 0,192,194,288, 0,334,336, 0,340,342,344, 0,328,330,332, 0, + 338, 42,346, 0,196,308, 0,290,310, 0,392,398, 0, 44,200, 0, 0, 54, + 0, 0,198, 50, 60, 0, 30, 0, 80, 14, 0, 18, 68, 0, 0, 66, 0, 0, + 0, 76,204, 28, 0, 0, 0,202,206, 0, 12, 0, 0, 4, 0, 6, 0, 0, + 292,312, 0, 22,348, 0,364, 0,370, 0,366,376,374,368,378, 0,382,384, + 0,356,372, 0,354, 0,350,360,358,362, 0,380, 0,352,386, 0,272, 0, + 390,396, 0,388, 0,394,400, 0,212, 0,402,210,208, 0, 0, 0, 92, 10, + 0,278,280, 0,444, 0, 0, 0,446, 0,268, 84,314, 0, 70,294, 0, 94, + 0, 82,316, 0, 88, 0,214, 0, 72, 0, 0,296, 46,404, 0, 0,406, 0, + 36, 0, 34, 0, 0, 0, 0, 0, 64,276, 0, 96,216,274, 0, 0, 0,218, + 220, 0,434, 0,228,230, 0,236,238, 0,242,306,244, 0,246,190, 0,248, + 0,320, 0, 0,222,232,224,226, 0,234, 0,240, 0, 0,250, 0,442,438, + 0,298,440,408, 0,436, 0,256, 0,410,254,186,252, 0, 0, 0,304,260, + 318, 0,270, 0,412,262, 74, 0,300,414, 0, 0, 0,258, 0, 0, 0, 90, + 0, 58, 86, 0,302,416, 0,264, 0,266, 0, 98,135,465, 0, 0, 0, 0, + 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 62, 0, 0, + 98,135, 0,427,424, 0, 0, 0,128,140, 0,134,144, 0,132, 0, 0, 98, + 135,231,130,146, 0,142,138, 0,126, 96,136, 0, 14, 18, 0, 0, 12, 10, + 16, 0,162,164,163, 0,427,424, 0, 4, 0, 6, 0, 0, 0, 0, 0,438, + 98,135,426, 0, 0, 0, 0,426,465, 0,427,424, 0, 52, 56, 0, 44, 0, + 54, 50, 60, 0, 80, 14, 0, 18, 68, 0, 0, 66, 0, 0, 0, 76, 0, 0, + 0, 0, 4, 0, 6, 0, 0, 0, 0, 0, 92, 10, 0, 0, 84, 0, 94, 70, + 82, 0, 72, 88, 0, 36, 0, 34, 0, 0, 0, 0, 0, 96, 0, 64, 0, 2, + 74, 90, 0, 58, 86, 0,464, 0, 0, 48, 0, 42, 0, 0, 78, 12, 0, 0, + 0, 0, 46, 0, 0, 0, 16, 62,460, 0, 4, 0, 6, 0, 0, 0, 0, 0, + 0, 0,426,427, 0,427,424, 0,426, 0,460, 0,427,424, 0, 0,100, 96, + 0,427,424, 0,182, 0, 0,168, 0,170,178, 0,172, 0,152,156,160,180, + 174, 0,241,166,152,154,156,158,160,162,164, 0,168, 0,170, 0,172, 0, + 152,156,160,174, 0,168, 0,170, 0,172, 0,166,152,156,160,176, 0,168, + 0,170, 0,152,156, 0,498, 0,427,424, 0,513,502, 0,496, 0,500,515, + 0,182,523,493, 0,506,432,504, 0,498, 0,427,424, 0,513,502, 0,496, + 0,500,515, 0,106,110, 0,108,112, 0,120,122, 0, 0, 0,182,523,493, + 0,506,432,504,118,102, 0, 0,124,104,114, 0,116, 0, 52, 56, 0, 44, + 0, 54, 50, 60, 0, 80, 14, 0, 18, 68, 0, 0, 66, 0, 0, 0, 76, 0, + 0, 0, 92, 10, 0, 0, 84, 0, 94, 70, 82, 0, 72, 88, 0, 36, 0, 34, + 0, 0, 0, 0, 0, 96, 0, 64, 0, 74, 90, 0, 58, 86, 0,464,465, 48, + 0, 42, 0, 0, 78, 12, 0, 0, 0, 46, 0, 0, 0, 16, 62, 0,427,424, + 0,493, 0, 0,498, 0,427,424, 0,513,502, 0,496, 0,500,515, 0,106, + 110, 0,108,112, 0,114, 0,120,122, 0, 0, 0,182,523,493, 0,506,432, + 504,118,102, 0, 0,124,104,150,148, 0,116, 0,233, 0,498, 0,427,424, + 0,513,502, 0,496, 0,500,515, 0,106,110, 0,108,112, 0,114, 0,120, + 122, 0, 0, 0,182,523,493, 0,506,432,504, 0, 0,124,104,150,148, 0, + 116, 0,427,424, 0,128,140, 0,134,144, 0,132, 0, 0, 98,135,231,426, + 0,130,146, 0,142,138, 0,126, 96,136,460, 0,128,140, 0,134,144, 0, + 132, 0, 0, 98,135,231,130,146, 0,142,138, 0, 96,136, 0,427,424, 0, + 128,140, 0,134,144, 0,132, 0, 0, 98,135,231,426, 0,130,146, 0,142, + 138, 0, 96,136,460, 0,498, 0,513,502, 0,496, 0,500,515, 0,106,110, + 0,108,112, 0,120,122, 0, 0, 0,182,523,493,506,432,504,118,102, 0, + 0,124,104,114, 0,116, 0,498, 0,427,424, 0,513,502, 0,496, 0,500, + 515, 0,106,110, 0,108,112, 0,120,122, 0, 0, 0,182,493, 0,506,432, + 504,118,102, 0, 0,104,114, 0,116, 0,498, 0,427,424, 0,502, 0,496, + 0,500, 0,106,110, 0,108,112, 0,182,493, 0,506,432,504,118,102, 0, + 0,104,114,116, 0,498, 0,427,424, 0,502, 0,496, 0,500, 0,106,110, + 0,108,112, 0,182,493, 0,506,432,504,102, 0, 0,104,114,116, 0,498, + 0,427,424, 0,502, 0,496, 0,500, 0,106,110, 0,108,112, 0,182,493, + 0,506,432,504,102, 0, 0,104,114, 0,427,424, 0,502, 0,496, 0,500, + 0,106,110, 0,108,112, 0,498, 0,506,432,504,102, 0, 0,104, 0,498, + 0,523,426, 0,427,424, 0,513,502, 0,496, 0,500,515, 0,106,110, 0, + 108,112, 0,120,122, 0, 0, 0,182, 0,493, 0,506,432,504,118,102, 0, + 0,124,104,114, 0,116,460, 0, 52, 56, 0, 44, 0, 54, 50, 60, 0, 80, + 14, 0, 18, 68, 0, 0, 66, 0, 0, 0, 76, 0, 0, 0, 0, 92, 10, 0, + 0, 84, 0, 94, 70, 82, 0, 72, 88, 0, 36, 0, 34, 0, 0, 0, 0, 0, + 96, 0, 64, 0, 2, 74, 90, 0, 58, 86, 0,464,465, 48, 0, 42, 0, 0, + 78, 12, 0, 0, 0, 46, 0, 0, 0, 16, 62, 0,231, 0,282,284,324, 0, + 286,326, 0,322, 0, 0,188,184, 0,426,424, 0,432, 0,420, 0,168,428, + 0,430,418,422, 0,192,194,288, 0,334,336, 0,340,342,344, 0,328,330, + 332, 0,338,346, 0,196,308, 0,290,310, 0,392,398, 0, 0, 0, 0,198, + 200, 0,202,206, 0, 0, 0,292,312, 0,348, 0,364, 0,370, 0,366,376, + 374,368,378, 0,382,384, 0,356,372, 0,354, 0,350,360,358,362, 0,380, + 0,352,386, 0,272, 0,390,396, 0,388, 0,394,400, 0,212, 0,402,210, + 208, 0, 0, 0,278,280, 0,444, 0, 0,446, 0,268,314, 0,294,316, 0, + 296,404, 0, 0,406, 0,216,274,276, 0,218,220, 0,434, 0,228,230, 0, + 236,238, 0,242,306,244, 0,246,190, 0,248, 0,320, 0, 0,222,232,224, + 226, 0,234, 0,240, 0, 0,250, 0,442,438, 0,298,440,408, 0,436, 0, + 256, 0,410,254,186,252, 0, 0, 0,304,260,318, 0,270, 0,412,262, 0, + 300,414, 0, 0, 0,258, 0, 0, 0, 0,302,416, 0,264, 0,266, 0, 0, + 0, 0, 0,204, 0, 0, 0, 0, 0,214, 0, 0, 0, 0, 0, 0,427,424, + 0, 98,135, 0, 0,427,424, 0,182,493, 0, 0,493, 0,427,424, 0, 0, + 150,148, 0,460, 0,130, 0,146, 0,128,140, 0,142, 0,134,144, 0,132, + 0, 0, 98,135,231,241,166,152,154,156,158, 0,160,138,162,164,126, 96, + 136, 0,182, 0,427,424, 0, 0,460, 0 }; static const unsigned short ag_key_jmp[] = { @@ -1713,176 +1730,180 @@ static const unsigned short ag_key_jmp[] = { 0, 0,213,215,122,124, 0, 0, 0,223, 0, 0, 0,225, 0,126,128, 0, 0, 0, 0,133,135, 0,118,218, 0,229,231,130, 0,234,237,138,141, 0, 147, 0,154, 0,254, 0, 0,149,256,157,163, 0,168, 0,264, 0, 0,165, - 0,266, 0, 0, 0, 0, 0,273,171, 0,176, 0,180,184, 0,190,194, 0, - 173,280,178,282,188,285, 0, 0, 0, 0,196, 0, 0,206, 0, 0, 0, 0, - 0, 0, 0, 0, 0,208, 0, 0, 0,313, 0,295,298,199,202,204,300, 0, - 303,306,310,315, 0, 0, 0, 0, 0, 0, 0, 0,330, 0, 0, 0, 0,339, - 0, 0, 0, 0,341, 0, 0, 0,214, 0, 0, 0, 0,353, 0,219, 0, 0, - 0, 0,333,210,346,212,349,216,355,359,222, 0,224,227, 0, 0, 0, 0, - 247,250,375,252, 0, 23, 0, 25, 0, 14, 17, 27, 0, 31, 35, 38, 41, 43, - 57, 70, 90,120,147,155,159,165,181,203,240,259,269,277,288,317,362,372, - 231,236,243,378,255, 0,257,260,264, 0, 0, 0, 0, 0, 0, 0,420,424, - 0,274,276, 0,433,278,282, 0,286,289, 0,440,293, 0,268,436,443,299, - 305, 0, 0, 0, 0, 0,310,452, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,319,321, 0,314,465,469,316,472, 0, 0, 0, 0, 0, 0, - 0, 0, 0,323, 0,481,484,486,327, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,330, 0,497,501,504,333, 0, 0, 0, 0, 0, 0, 0, 0, - 336,338, 0,340,342, 0,516, 0,519,522, 0,525, 0, 0,350, 0,536,352, - 0,357,361, 0,541,363, 0,544, 0,344, 0,347,538,355,547, 0,371, 0, - 0,369,556, 0, 0, 0, 0, 0,562, 0, 0, 0, 0, 0, 0, 0, 0,570, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,568,572,578,581,584, - 0, 0, 0, 0, 0, 0, 0,596,598,378,380, 0, 0, 0,606, 0, 0, 0, - 608, 0,382,384, 0,389,391, 0,374,601,612,614,386,617,394,397,403, 0, - 410, 0, 0,405,630,414,420, 0,425, 0,638, 0,422,640, 0, 0, 0, 0, - 0,645,428, 0,443,447, 0,430,433,436,438,652, 0, 0, 0, 0,449, 0, - 0,459, 0, 0, 0, 0, 0, 0, 0, 0, 0,461, 0, 0, 0,679, 0,661, - 664,452,455,457,666, 0,669,672,676,681, 0, 0, 0, 0, 0, 0, 0, 0, - 696, 0, 0, 0, 0,705, 0, 0, 0, 0,707, 0, 0,467, 0, 0, 0, 0, - 718, 0,469, 0, 0, 0, 0,699,463,712,465,714,720,724,472, 0,474,477, - 0, 0, 0, 0,492,739,495, 0,460, 0,312,462,475,488,508,528,549,365, - 559,565,586,620,633,642,649,655,683,727,736,481,488,742, 0, 0, 0, 0, - 498, 0,774, 0,776, 0,778, 0,771,780, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,508,510, 0,503,790,794,505,797, 0, 0, 0, 0, 0, - 0, 0, 0, 0,512, 0,806,809,811,516, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,519, 0,822,826,829,522, 0, 0, 0, 0, 0, 0, 0, - 0,525,527, 0,529,531, 0,841, 0,844,847, 0,850, 0, 0,539, 0,861, - 541, 0,544,548, 0,866,550, 0,869, 0,533, 0,536,863,872, 0,558, 0, - 0,556,880, 0,561, 0,886, 0,888, 0, 0, 0, 0,890, 0, 0, 0, 0, - 0, 0, 0, 0,899, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 897,901,907,910,913, 0, 0, 0, 0, 0, 0, 0,925,927,568,570, 0, 0, - 0,935, 0, 0, 0,937, 0,572,574, 0,579,581, 0,564,930,941,943,576, - 946,584,587,593, 0,600, 0, 0,595,959,604,610, 0,615, 0,967, 0,612, - 969, 0, 0, 0, 0, 0,974,618, 0,633,637, 0,620,623,626,628,981, 0, - 0, 0, 0,639, 0, 0,649, 0, 0, 0, 0, 0, 0, 0, 0, 0,651, 0, - 0, 0,1008, 0,990,993,642,645,647,995, 0,998,1001,1005,1010, 0, 0, - 0, 0, 0, 0, 0, 0,1025, 0, 0, 0, 0,1034, 0, 0, 0, 0,1036, - 0, 0,655, 0, 0, 0, 0,1047, 0,657, 0, 0, 0, 0,1028,1041,653, - 1043,1049,1053,660, 0,662,665, 0, 0, 0, 0,680,1067,683, 0,785, 0, - 501,787,800,813,833,853,874,552,883,894,915,949,962,971,978,984,1012,1056, - 1064,669,676,1070, 0, 0, 0, 0, 0, 0, 0,1102, 0,700, 0, 0, 0, - 0, 0, 0,1110, 0, 0, 0,686,689,693,1107,704,708,1113,710,713,717, - 0,721,725, 0,1129,732,735,739, 0,748,751,755, 0, 0, 0, 0,759, 0, - 1144, 0,1146, 0,1148, 0, 0, 0, 0,746,1137,1141,1150, 0, 0, 0, - 0, 0, 0, 0,768,772, 0,779, 0, 0,1169, 0, 0, 0,784, 0,789,793, - 0,1178,795, 0,1181, 0,781,1175,787,1184, 0,804, 0,1191, 0,1193, - 0,1195, 0,807,809, 0,1199,811, 0,817,822,827, 0,833,836, 0,844, - 847,852, 0,857,859,863, 0,865,868, 0,762,1160,1163,764,1166,775,1171, - 1186,797,801,1197,1202,1205,1209,841,1212,1216,1220,872,879,883, 0,885, - 0,1245, 0,1247, 0,1249, 0,1251, 0,888,890, 0, 0, 0, 0,892,1258, - 894, 0, 0, 0, 0,1265,896,902, 0, 0, 0, 0, 0,1272, 0, 0, 0, - 0, 0, 0, 0, 0,1278,1280,1283,906,908, 0,910, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1301,1303,1305,914, 0, 0, 0, - 0, 0, 0, 0, 0,1312,1314,1316,916, 0, 0, 0, 0, 0,1324,1326, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1331,919, 0,1333, - 1336,1339,1341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1371, 0,1352,921, 0,1354,1357,1360, - 1362,923,926,1365,1368,928,931,933,1374,935, 0,946,950, 0,957, 0, 0, - 1396, 0, 0, 0,962, 0,965,969, 0,1405,971, 0,1408, 0,959,1402,1411, - 0,980,982, 0,1417,984, 0,990,995,1000, 0,1006,1009, 0,1017,1020, - 1025, 0,1030,1034, 0,1036,1039, 0,938,940,942,1393,953,1398,1413,973, - 977,1420,1423,1427,1014,1430,1434,1437,1043,1050, 0, 0, 0, 0, 0,1459, + 0,266, 0, 0, 0, 0, 0,273,171, 0,176, 0, 0, 0,282, 0,284, 0, + 180,286, 0,186,190, 0,173,280,178,288,184,291, 0, 0, 0, 0,192, 0, + 0,202, 0, 0, 0, 0, 0, 0, 0, 0, 0,204, 0, 0, 0,319, 0,301, + 304,195,198,200,306, 0,309,312,316,321, 0, 0, 0, 0, 0, 0, 0, 0, + 336, 0, 0, 0, 0,345, 0, 0, 0, 0,347, 0, 0, 0,210, 0, 0, 0, + 0,359, 0,215, 0, 0, 0, 0,339,206,352,208,355,212,361,365,218, 0, + 220,223, 0, 0, 0, 0,243,246,381,248, 0, 23, 0, 25, 0, 14, 17, 27, + 0, 31, 35, 38, 41, 43, 57, 70, 90,120,147,155,159,165,181,203,240,259, + 269,277,294,323,368,378,227,232,239,384,251, 0,253,256,260, 0, 0, 0, + 0, 0, 0, 0,426,430, 0,270,272, 0,439,274,278, 0,282,285, 0,446, + 289, 0, 0, 0,452, 0,454, 0,295,456, 0,458, 0,264,442,449,461,299, + 0, 0, 0, 0, 0,304,469, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,313,315, 0,308,483,487,310,490, 0, 0, 0, 0, 0, 0, + 0, 0, 0,317, 0,499,502,504,321, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,324, 0,515,519,522,327, 0, 0, 0, 0, 0, 0, 0, 0, + 330,332, 0,334,336, 0,534, 0,537,540, 0,543, 0, 0,344, 0,554,346, + 0,351,355, 0,559,357, 0,562, 0,338, 0,341,556,349,565, 0,365, 0, + 0,363,574, 0, 0, 0, 0, 0,580, 0, 0, 0, 0, 0, 0, 0, 0,588, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,586,590,596,599,602, + 0, 0, 0, 0, 0, 0, 0,614,616,372,374, 0, 0, 0,624, 0, 0, 0, + 626, 0,376,378, 0,383,385, 0,368,619,630,632,380,635,388,391,397, 0, + 404, 0, 0,399,648,408,414, 0,419, 0,656, 0,416,658, 0, 0, 0, 0, + 0,663,422, 0, 0, 0,670, 0,672, 0,674, 0,432,436, 0,424,427,430, + 676,678, 0, 0, 0, 0,438, 0, 0,448, 0, 0, 0, 0, 0, 0, 0, 0, + 0,450, 0, 0, 0,705, 0,687,690,441,444,446,692, 0,695,698,702,707, + 0, 0, 0, 0, 0, 0, 0, 0,722, 0, 0, 0, 0,731, 0, 0, 0, 0, + 733, 0, 0,456, 0, 0, 0, 0,744, 0,458, 0, 0, 0, 0,725,452,738, + 454,740,746,750,461, 0,463,466, 0, 0, 0, 0,481,765,484, 0,478, 0, + 306,480, 0,493,506,526,546,567,359,577,583,604,638,651,660,667,681,709, + 753,762,470,477,768, 0, 0, 0, 0,487, 0,801, 0,803, 0,805, 0,798, + 807, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,497,499, 0,492, + 817,821,494,824, 0, 0, 0, 0, 0, 0, 0, 0, 0,501, 0,833,836,838, + 505, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,508, 0,849,853, + 856,511, 0, 0, 0, 0, 0, 0, 0, 0,514,516, 0,518,520, 0,868, 0, + 871,874, 0,877, 0, 0,528, 0,888,530, 0,533,537, 0,893,539, 0,896, + 0,522, 0,525,890,899, 0,547, 0, 0,545,907, 0,550, 0,913, 0,915, + 0, 0, 0, 0,917, 0, 0, 0, 0, 0, 0, 0, 0,926, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,924,928,934,937,940, 0, 0, 0, 0, + 0, 0, 0,952,954,557,559, 0, 0, 0,962, 0, 0, 0,964, 0,561,563, + 0,568,570, 0,553,957,968,970,565,973,573,576,582, 0,589, 0, 0,584, + 986,593,599, 0,604, 0,994, 0,601,996, 0, 0, 0, 0, 0,1001,607, 0, + 0, 0,1008, 0,1010, 0,1012, 0,617,621, 0,609,612,615,1014,1016, 0, + 0, 0, 0,623, 0, 0,633, 0, 0, 0, 0, 0, 0, 0, 0, 0,635, 0, + 0, 0,1043, 0,1025,1028,626,629,631,1030, 0,1033,1036,1040,1045, 0, + 0, 0, 0, 0, 0, 0, 0,1060, 0, 0, 0, 0,1069, 0, 0, 0, 0, + 1071, 0, 0,639, 0, 0, 0, 0,1082, 0,641, 0, 0, 0, 0,1063,1076, + 637,1078,1084,1088,644, 0,646,649, 0, 0, 0, 0,664,1102,667, 0,812, + 0,490,814,827,840,860,880,901,541,910,921,942,976,989,998,1005,1019, + 1047,1091,1099,653,660,1105, 0, 0, 0, 0, 0, 0, 0,1137, 0,684, 0, + 0, 0, 0, 0, 0,1145, 0, 0, 0,670,673,677,1142,688,692,1148,694, + 697,701, 0,705,709, 0,1164,716,719,723, 0,732,735,739, 0, 0, 0, 0, + 743, 0,1179, 0,1181, 0,1183, 0, 0, 0, 0,730,1172,1176,1185, 0, + 0, 0, 0, 0, 0, 0,752,756, 0,763, 0, 0,1204, 0, 0, 0,768, 0, + 773,777, 0,1213,779, 0,1216, 0,765,1210,771,1219, 0,788, 0,1226, 0, + 1228, 0,1230, 0,791,793, 0,1234,795, 0,801,806,811, 0,817,820, 0, + 0, 0,1247, 0,1249, 0,1251, 0,828,1253,831, 0,836,838,842, 0,844, + 847, 0,746,1195,1198,748,1201,759,1206,1221,781,785,1232,1237,1240,1244, + 825,1255,1259,1263,851,858,862, 0,864, 0,1288, 0,1290, 0,1292, 0, + 1294, 0,867,869, 0, 0, 0, 0,871,1301,873, 0, 0, 0, 0,1308,875, + 881, 0, 0, 0, 0, 0,1315, 0, 0, 0, 0, 0, 0, 0, 0,1321,1323, + 1326,885,887, 0,889, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,1344,1346,1348,893, 0, 0, 0, 0, 0, 0, 0, 0,1355,1357,1359, + 895, 0, 0, 0, 0, 0,1367,1369, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,1374,898, 0,1376,1379,1382,1384, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1414, 0,1395,900, 0,1397,1400,1403,1405,902,905,1408,1411,907,910,912, + 1417,914, 0,925,929, 0,936, 0, 0,1439, 0, 0, 0,941, 0,944,948, + 0,1448,950, 0,1451, 0,938,1445,1454, 0,959,961, 0,1460,963, 0,969, + 974,979, 0,985,988, 0, 0, 0,1473, 0,1475, 0,1477, 0,996,1479,999, + 0,1004,1008, 0,1010,1013, 0,917,919,921,1436,932,1441,1456,952,956, + 1463,1466,1470,993,1481,1485,1488,1017,1024, 0, 0, 0, 0, 0,1510, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,1486, 0,1465,1054, 0,1467,1470,1473,1475, - 1056,1059,1478,1481,1061,1064,1484, 0,1489,1066, 0,1069, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1537, 0,1516,1028, 0,1518,1521,1524,1526,1030, + 1033,1529,1532,1035,1038,1535, 0,1540,1040, 0,1043, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,1532, 0,1511,1071, 0,1513,1516,1519,1521,1524,1527,1073, - 1076,1530, 0,1535,1078, 0, 0, 0, 0,1097, 0, 0, 0, 0, 0, 0,1559, - 0, 0, 0,1081,1084,1553,1086,1090,1556,1101,1105,1562,1107,1110,1114, - 1118, 0,1134, 0, 0, 0, 0, 0, 0,1584, 0, 0, 0,1120,1123,1127, - 1581,1138,1142,1587,1144,1148, 0, 0, 0, 0,1168, 0, 0, 0, 0, 0, - 0,1608, 0, 0, 0,1152,1155,1602,1157,1161,1605,1172,1176,1611,1178, - 1182,1186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,1645, 0,1629,1188, 0,1631,1634,1636,1190,1193,1639, - 1642,1195,1198,1200,1648,1202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1685, 0,1666, 0, - 1668,1671,1674,1676,1205,1208,1679,1682,1210,1212,1688,1214, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1705, 0,1707, - 1710,1712,1714,1217,1220,1716,1719,1222,1224,1226, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1736, 0,1738,1741, - 1743,1745,1229,1747,1750,1231,1233,1235, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1766, 0,1768,1771,1773,1775,1238, - 1777,1780,1240,1242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,1244,1795,1798,1800,1802,1246,1804,1807,1248, 0, 0, 0, 0, + 0, 0,1583, 0,1562,1045, 0,1564,1567,1570,1572,1575,1578,1047,1050, + 1581, 0,1586,1052, 0, 0, 0, 0,1071, 0, 0, 0, 0, 0, 0,1610, 0, + 0, 0,1055,1058,1604,1060,1064,1607,1075,1079,1613,1081,1084,1088,1092, + 0,1108, 0, 0, 0, 0, 0, 0,1635, 0, 0, 0,1094,1097,1101,1632, + 1112,1116,1638,1118,1122, 0, 0, 0, 0,1142, 0, 0, 0, 0, 0, 0, + 1659, 0, 0, 0,1126,1129,1653,1131,1135,1656,1146,1150,1662,1152,1156, + 1160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1696, 0,1680,1162, 0,1682,1685,1687,1164,1167,1690,1693, + 1169,1172,1174,1699,1176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1736, 0,1717, 0,1719,1722, + 1725,1727,1179,1182,1730,1733,1184,1186,1739,1188, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1756, 0,1758,1761, + 1763,1765,1191,1194,1767,1770,1196,1198,1200, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1787, 0,1789,1792,1794,1796, + 1203,1798,1801,1205,1207,1209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1817, 0,1819,1822,1824,1826,1212,1828, + 1831,1214,1216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,1218,1846,1849,1851,1853,1220,1855,1858,1222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,1842, 0,1820,1822, 0,1825,1828,1831,1833,1250,1253,1836, - 1839,1255,1258,1260,1845,1262,1265, 0,1275,1279, 0,1286, 0, 0,1868, - 0, 0, 0,1291, 0,1296,1300, 0,1877,1302, 0,1880, 0,1288,1874,1294, - 1883, 0,1311,1313, 0,1890,1315, 0,1321,1326,1331, 0,1337,1340, 0, - 1348,1351,1356, 0,1361,1363,1367, 0,1369,1372, 0,1267,1269,1271,1865, - 1282,1870,1885,1304,1308,1893,1896,1900,1345,1903,1907,1911,1376,1383, - 0,1387, 0, 0, 0, 0, 0, 0, 0, 0,1390,1935,1939,1392,1395, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1948,1951,1953, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1398, 0,1962,1966,1969, 0, 0, 0, 0, - 0, 0, 0, 0,1401,1403, 0,1980,1983,1986, 0,1405, 0,1410, 0, 0, - 1995, 0, 0, 0, 0,2000, 0, 0, 0, 0, 0, 0, 0, 0,2007, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2005,2009,2015,2018,2021, 0, - 0, 0, 0, 0, 0, 0,2033,2035,1417,1419, 0, 0, 0,2043, 0, 0, 0, - 2045, 0,1424,1426, 0,1413,2038,2049,1421,2051,1429,1432, 0,1434,1436, - 0, 0, 0, 0,2065,1441, 0,1443,1446,1448, 0, 0, 0, 0,1451, 0, - 0,1461, 0, 0, 0, 0, 0, 0, 0, 0, 0,1463, 0, 0, 0,2093, 0, - 2075,2078,1454,1457,1459,2080, 0,2083,2086,2090,2095, 0, 0, 0, 0, - 0, 0, 0, 0,2110, 0, 0, 0, 0,2119, 0, 0, 0, 0,2121, 0, 0, - 1467, 0, 0, 0, 0,2132, 0, 0, 0, 0, 0,2113,2126,1465,2128,2134, - 2137, 0, 0, 0, 0,1469,2147,1472, 0,1942,1955,1973,1989,1408,1998, - 2003,2023,2054,2062,1438,2068,2071,2097,2140,2150, 0, 0, 0, 0, 0, - 0,2171, 0, 0, 0, 0, 0, 0,2178, 0, 0, 0, 0, 0, 0,2187, 0, - 0, 0,1475, 0,1484, 0,1487, 0,1493, 0, 0,1497, 0, 0, 0, 0, 0, - 2205, 0, 0, 0,1477,1480, 0, 0,2196,2198, 0,2200,2203,1500,2208, 0, - 1502,1505,1509, 0, 0, 0, 0, 0, 0,2231,1513, 0 + 0, 0, 0,1893, 0,1871,1873, 0,1876,1879,1882,1884,1224,1227,1887, + 1890,1229,1232,1234,1896,1236,1239, 0,1249,1253, 0,1260, 0, 0,1919, + 0, 0, 0,1265, 0,1270,1274, 0,1928,1276, 0,1931, 0,1262,1925,1268, + 1934, 0,1285,1287, 0,1941,1289, 0,1295,1300,1305, 0,1311,1314, 0, + 0, 0,1954, 0,1956, 0,1958, 0,1322,1960,1325, 0,1330,1332,1336, 0, + 1338,1341, 0,1241,1243,1245,1916,1256,1921,1936,1278,1282,1944,1947,1951, + 1319,1962,1966,1970,1345,1352, 0,1356, 0, 0, 0, 0, 0, 0, 0, 0, + 1359,1994,1998,1361,1364, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2007, + 2010,2012, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1367, 0, + 2021,2025,2028, 0, 0, 0, 0, 0, 0, 0, 0,1370,1372, 0,2039,2042, + 2045, 0,1374, 0,1379, 0, 0,2054, 0, 0, 0, 0,2059, 0, 0, 0, 0, + 0, 0, 0, 0,2066, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2064,2068,2074,2077,2080, 0, 0, 0, 0, 0, 0, 0,2092,2094,1386,1388, + 0, 0, 0,2102, 0, 0, 0,2104, 0,1393,1395, 0,1382,2097,2108,1390, + 2110,1398,1401, 0,1403,1405, 0, 0, 0, 0,2124,1410, 0,1412,1415,1417, + 0, 0, 0, 0,1420, 0, 0,1430, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1432, 0, 0, 0,2152, 0,2134,2137,1423,1426,1428,2139, 0,2142,2145, + 2149,2154, 0, 0, 0, 0, 0, 0, 0, 0,2169, 0, 0, 0, 0,2178, 0, + 0, 0, 0,2180, 0, 0,1436, 0, 0, 0, 0,2191, 0, 0, 0, 0, 0, + 2172,2185,1434,2187,2193,2196, 0, 0, 0, 0,1438,2206,1441, 0,2001, + 2014,2032,2048,1377,2057,2062,2082,2113,2121,1407,2127,2130,2156,2199, + 2209, 0, 0, 0, 0, 0, 0,2230, 0, 0, 0, 0, 0, 0,2237, 0, 0, + 0, 0, 0, 0,2246, 0, 0, 0,1444, 0,1453, 0,1456, 0,1462, 0, 0, + 1466, 0, 0, 0, 0, 0,2264, 0, 0, 0,1446,1449, 0, 0,2255,2257, + 0,2259,2262,1469,2267, 0,1471,1474,1478, 0, 0, 0, 0, 0, 0,2290, + 1482, 0 }; static const unsigned short ag_key_index[] = { - 16,383,427,446,455,446,746, 0,782,746,1074,427,1099,1099, 0,1105,1105, - 1099,1116,1116,1099,1132, 0,1099,1099, 0,1105,1105,1099,1116,1116,1099, - 1132, 0,1152,1223,1253,1255,1261, 0,1255, 0, 0,746,1268,1275,1275, - 1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1285,1291, - 1307,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, - 1116,1116,1116,1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1275, - 1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1275, - 1275,1275,1275,1275, 0,1285,1291,1307,1116,1116,1116,1116,1116,1116,1116, - 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, - 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, - 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1318, - 1318,1318,1318,1328,1328,1307,1307,1307,1285,1285,1291,1291,1291,1291, - 1291,1291,1291,1291,1291,1291,1291, 0, 0, 0, 0,1116,1116,1116,1116, - 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, - 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, - 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, - 1116,1116,1116,1116,1116,1116,1318,1318,1318,1318,1328,1328,1307,1307, - 1307,1285,1285,1291,1291,1291,1291,1291,1291,1291,1291,1291,1291,1291, - 1344,1275,1376,1105,1275,1116,1440,1105, 0,1105, 0,1462,1105,1105,1105, - 1105, 0, 0, 0,1376,1491, 0,1509,1376, 0,1376,1376,1376,1537, 0,1105, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1376,1376,1565, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1590,1614,1590,1614,1116,1590,1590,1590,1590,1376, - 1650,1690,1690,1722,1753,1783,1810,1116,1105,1105,1105,1105,1105,1105, - 1105,1099,1099,1105,1105,1105,1105, 0,1105,1105,1105, 0, 0,1261,1565, - 1261,1565,1255,1261,1261,1261,1261,1261,1261,1261,1261,1261,1261,1261, - 1261,1261,1261,1261,1261,1261,1261,1261,1614,1565,1565,1565,1614,1847, - 1261,1565,1614,1261,1255,1261,1261,1152, 0, 0, 0,1914,1105,1268,1285, - 1291,1307, 0, 0, 0, 0,1116,1116,1116,1116,1116,1116,1116,1116,1116, - 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, - 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, - 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, - 1116,1318,1318,1318,1318,1328,1328,1307,1307,1307,1285,1285,1291,1291, - 1291,1291,1291,1291,1291,1291,1291,1291,1291,1116,1933,2154,2154,1099, - 1099, 0, 0,1105,1105, 0, 0,1105,1105,2174,2174, 0, 0,1116,1116,1116, - 1116,1116,1116,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1116, - 1116,1116,1116,1116,1116,1116,1116,1116,1116,1105,1116,1116,1116,1116, - 1099,1268,1268,1105, 0,1105, 0,1105,1105, 0, 0,1509,1376,1376, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1116, 0,1590,1590,1590,1590,1590, - 1590,1590,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, - 1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, - 1116,1116,1116,1116,1116,1116,1105,1105,1105,1105,1105,1099,1105,1105, - 0,1105,1105, 0,1105,1105,1105,1116,1116,1116,1116,1105,1105,1105,1275, - 1275,1275,2181,1275,1116,1116,1116,1275,1275,2185,1509,1509,1462,2185, - 0,2190,2154,1509, 0,1116,1462,1462,1462,1462,1462,2194, 0, 0, 0, - 0,1099,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, 0,1590,1590, - 1590,1590,1590,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, - 1116,1105,1105,1105,1105,1105,1105,1105,1116,1116,1116,2185,1509,2211, - 1116,2229,1275,1509,1116,1462,1099,2234,2234,1105, 0, 0,1099, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1650,1650,1690,1690,1690,1690,1690, - 1690,1722,1722,1753,1753,1105,1105,1105,1291,1509,1116,1116,1099, 0, 0, - 0,1291, 0 + 16,389,433,463,472,463,772, 0,809,772,1109,433,1134,1134, 0, 0, 0, + 1140,1140,1134,1151,1151,1134,1167, 0,1134,1134, 0, 0, 0,1140,1140, + 1134,1151,1151,1134,1167, 0,1187,1266,1296,1298,1304, 0,1298, 0, 0, + 772,1311,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318, + 1318,1328,1334,1350,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, + 1151,1151,1151,1151,1151,1151,1318,1318,1318,1318,1318,1318,1318,1318, + 1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318, + 1318,1318,1318,1318,1318,1318,1318, 0,1328,1334,1350,1151,1151,1151,1151, + 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, + 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, + 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, + 1151,1151,1361,1361,1361,1361,1371,1371,1350,1350,1350,1328,1328,1334, + 1334,1334,1334,1334,1334,1334,1334,1334,1334,1334, 0, 0, 0, 0,1151, + 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, + 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, + 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, + 1151,1151,1151,1151,1151,1151,1151,1151,1151,1361,1361,1361,1361,1371, + 1371,1350,1350,1350,1328,1328,1334,1334,1334,1334,1334,1334,1334,1334, + 1334,1334,1334,1387,1318,1419,1140,1318,1151,1491,1140, 0,1140, 0,1513, + 0,1140,1140,1140,1140,1140, 0, 0, 0,1419,1542, 0,1560,1419, 0,1419, + 1419,1419,1588, 0,1140, 0, 0, 0, 0, 0, 0, 0, 0, 0,1419,1419, + 1616, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1641,1665,1641,1665,1151, + 1641,1641,1641,1641,1419,1701,1741,1741,1773,1804,1834,1861,1151,1140, + 1140,1140,1140,1140,1140,1140,1134,1134,1140,1140,1140,1140, 0,1140,1140, + 1140, 0, 0,1304,1616,1304,1616,1298,1304,1304,1304,1304,1304,1304,1304, + 1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1665,1616, + 1616,1616,1665,1898,1304,1616,1665,1304,1304,1304,1187, 0, 0, 0,1151, + 1151,1973,1140,1311,1328,1334,1350, 0, 0, 0, 0,1151,1151,1151,1151, + 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, + 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, + 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, + 1151,1151,1151,1151,1151,1151,1361,1361,1361,1361,1371,1371,1350,1350, + 1350,1328,1328,1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,1334, + 1151,1992,2213,2213,1134,1134, 0, 0,1140,1140, 0, 0,1140,1140,2233, + 2233, 0, 0,1151,1151,1151,1151,1151,1151,1134,1134,1134,1134,1134,1134, + 1134,1134,1134,1134,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, + 1140,1151,1151,1151,1151,1134,1311,1311,1140, 0,1140, 0,1151,1140,1140, + 1140, 0, 0,1560,1419,1419, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1151, 0,1641,1641,1641,1641,1641,1641,1641,1151,1151,1151,1151,1151,1151, + 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, + 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1140,1140,1140, + 1140,1140,1134,1140,1140, 0,1140,1140, 0,1140,1140,1140,1140,1151,1151, + 1151,1151,1140,1140,1140,1318,1318,1318,2240,1318,1151,1151,1151,1318, + 1318,2244,1560,1560,1513,2244, 0,2249,2213,1560, 0,1151,1513,1513,1513, + 1513,1513,2253, 0, 0, 0,1151, 0,1134,1151,1151,1151,1151,1151,1151, + 1151,1151,1151,1151, 0,1641,1641,1641,1641,1641,1151,1151,1151,1151,1151, + 1151,1151,1151,1151,1151,1151,1151,1140,1140,1140,1140,1140,1140,1140, + 1140,1151,1151,1151,2244,1560,2270,1151,2288,1318,1560,1151,1513,1134, + 2293,2293,1140, 0, 0,1140,1134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,1701,1701,1741,1741,1741,1741,1741,1741,1773,1773,1804,1804,1140,1140, + 1140,1334,1560,1151,1151,1134,1140, 0, 0, 0,1334, 0 }; static const unsigned char ag_key_ends[] = { @@ -1895,29 +1916,28 @@ static const unsigned char ag_key_ends[] = { 73,0, 73,0, 75,0, 84,0, 77,80,0, 80,0, 83,72,0, 69,84,0, 70,73,82,83,84,0, 73,0, 67,76,73,66,0, 76,69,0, 70,73,82,83,84,0, 73,0, 77,69,0, 71,69,0, 84,0, 71,69,0, 76,0, 80,0, 71,77,65,0, -78,84,70,0, 87,0, 76,73,67,0, 72,0, 76,76,0, 69,76,0, 84,0, -77,0, 69,0, 76,0, 84,0, 77,0, 76,0, 82,84,0, 76,78,0, 77,0, -88,84,0, 84,76,69,0, 78,68,69,70,0, 69,82,73,76,79,71,0, -79,82,68,0, 72,71,0, 82,0, 72,76,0, 10,0, 83,83,0, 65,84,65,0, -69,88,84,0, 69,70,73,78,69,0, 70,0, 69,0, 68,73,70,0, -82,79,82,0, 69,70,0, 68,69,70,0, 67,76,85,68,69,0, -82,65,71,77,65,0, 78,68,69,70,0, 61,0, 61,0, 73,0, 72,76,0, -71,0, 82,0, 79,67,75,0, 84,69,0, 76,76,0, 69,71,0, 76,0, 80,0, -71,0, 66,0, 72,79,0, 83,69,0, 70,0, 82,89,0, 85,0, 68,69,68,0, -78,0, 78,0, 73,76,76,0, 88,0, 66,67,0, 65,76,76,0, 73,0, 73,0, -75,0, 84,0, 77,80,0, 80,0, 83,72,0, 69,84,0, 70,73,82,83,84,0, -73,0, 67,76,73,66,0, 85,76,69,0, 70,73,82,83,84,0, 73,0, -77,69,0, 71,69,0, 84,0, 71,69,0, 72,76,0, 80,0, 73,78,84,70,0, -76,73,67,0, 72,0, 76,76,0, 69,76,0, 84,0, 77,0, 69,0, 76,0, -84,0, 77,0, 76,0, 76,78,0, 77,0, 88,84,0, 84,76,69,0, -69,82,73,76,79,71,0, 79,82,68,0, 72,71,0, 72,76,0, 68,69,0, +87,0, 76,73,67,0, 72,0, 76,76,0, 69,76,0, 84,0, 77,0, 69,0, +76,0, 84,0, 77,0, 76,0, 82,84,0, 76,78,0, 77,0, 88,84,0, +84,76,69,0, 78,68,69,70,0, 69,82,73,76,79,71,0, 79,82,68,0, +72,71,0, 82,0, 72,76,0, 10,0, 83,83,0, 65,84,65,0, 69,88,84,0, +69,70,73,78,69,0, 70,0, 69,0, 68,73,70,0, 82,79,82,0, 69,70,0, +68,69,70,0, 67,76,85,68,69,0, 71,77,65,0, 78,68,69,70,0, 61,0, 61,0, 73,0, 72,76,0, 71,0, 82,0, 79,67,75,0, 84,69,0, 76,76,0, 69,71,0, 76,0, 80,0, 71,0, 66,0, 72,79,0, 83,69,0, 70,0, -82,89,0, 68,69,68,0, 78,0, 78,0, 73,76,76,0, 88,0, 66,67,0, -68,69,0, 65,76,76,0, 73,0, 73,0, 75,0, 84,0, 77,80,0, 80,0, +82,89,0, 85,0, 68,69,68,0, 78,0, 78,0, 73,76,76,0, 88,0, +66,67,0, 65,76,76,0, 73,0, 73,0, 75,0, 84,0, 77,80,0, 80,0, 83,72,0, 69,84,0, 70,73,82,83,84,0, 73,0, 67,76,73,66,0, 85,76,69,0, 70,73,82,83,84,0, 73,0, 77,69,0, 71,69,0, 84,0, -71,69,0, 72,76,0, 80,0, 73,78,84,70,0, 76,73,67,0, 72,0, +71,69,0, 72,76,0, 80,0, 76,73,67,0, 72,0, 76,76,0, 69,76,0, +84,0, 77,0, 69,0, 76,0, 84,0, 77,0, 76,0, 76,78,0, 77,0, +88,84,0, 84,76,69,0, 69,82,73,76,79,71,0, 79,82,68,0, 72,71,0, +72,76,0, 68,69,0, 61,0, 73,0, 72,76,0, 71,0, 82,0, 79,67,75,0, +84,69,0, 76,76,0, 69,71,0, 76,0, 80,0, 71,0, 66,0, 72,79,0, +83,69,0, 70,0, 82,89,0, 68,69,68,0, 78,0, 78,0, 73,76,76,0, +88,0, 66,67,0, 68,69,0, 65,76,76,0, 73,0, 73,0, 75,0, 84,0, +77,80,0, 80,0, 83,72,0, 69,84,0, 70,73,82,83,84,0, 73,0, +67,76,73,66,0, 85,76,69,0, 70,73,82,83,84,0, 73,0, 77,69,0, +71,69,0, 84,0, 71,69,0, 72,76,0, 80,0, 76,73,67,0, 72,0, 76,76,0, 69,76,0, 84,0, 77,0, 69,0, 76,0, 77,0, 76,0, 76,78,0, 77,0, 88,84,0, 84,76,69,0, 69,82,73,76,79,71,0, 79,82,68,0, 72,71,0, 72,76,0, 92,39,0, 69,73,76,0, @@ -1928,19 +1948,19 @@ static const unsigned char ag_key_ends[] = { 83,69,71,0, 71,0, 72,79,0, 82,89,0, 85,0, 68,69,68,0, 78,0, 78,0, 73,76,76,0, 69,88,0, 68,69,0, 75,0, 84,0, 70,73,82,83,84,0, 67,76,73,66,0, 68,85,76,69,0, 70,73,82,83,84,0, -77,69,0, 80,65,71,69,0, 82,71,0, 71,69,0, 73,78,84,70,0, -66,76,73,67,0, 84,0, 75,76,78,0, 77,0, 88,84,0, 84,76,69,0, -69,82,73,76,79,71,0, 79,82,68,0, 10,0, 68,69,0, 47,0, 42,0, -47,0, 10,0, 78,80,65,71,69,0, 65,71,69,0, 67,0, 80,0, -72,76,41,0, 80,0, 83,87,0, 42,0, 42,0, 78,68,0, 81,0, 79,68,0, -69,0, 82,0, 79,82,0, 61,0, 61,0, 83,69,71,0, 79,67,75,0, -84,69,0, 83,69,71,0, 71,0, 72,79,0, 82,89,0, 68,69,68,0, 78,0, -78,0, 73,76,76,0, 69,88,0, 75,0, 84,0, 70,73,82,83,84,0, -67,76,73,66,0, 68,85,76,69,0, 70,73,82,83,84,0, 77,69,0, -80,65,71,69,0, 82,71,0, 71,69,0, 73,78,84,70,0, 66,76,73,67,0, +77,69,0, 80,65,71,69,0, 82,71,0, 71,69,0, 66,76,73,67,0, 84,0, 75,76,78,0, 77,0, 88,84,0, 84,76,69,0, 69,82,73,76,79,71,0, -79,82,68,0, 42,0, 78,68,0, 81,0, 79,68,0, 69,0, 79,82,0, 39,0, -42,0, 79,68,0, 69,0, 79,82,0, 92,39,0, 47,0, 69,73,76,0, +79,82,68,0, 10,0, 68,69,0, 47,0, 42,0, 47,0, 10,0, +78,80,65,71,69,0, 65,71,69,0, 67,0, 80,0, 72,76,41,0, 80,0, +83,87,0, 42,0, 42,0, 78,68,0, 81,0, 79,68,0, 69,0, 82,0, +79,82,0, 61,0, 61,0, 83,69,71,0, 79,67,75,0, 84,69,0, +83,69,71,0, 71,0, 72,79,0, 82,89,0, 68,69,68,0, 78,0, 78,0, +73,76,76,0, 69,88,0, 75,0, 84,0, 70,73,82,83,84,0, +67,76,73,66,0, 68,85,76,69,0, 70,73,82,83,84,0, 77,69,0, +80,65,71,69,0, 82,71,0, 71,69,0, 66,76,73,67,0, 75,76,78,0, +77,0, 88,84,0, 84,76,69,0, 69,82,73,76,79,71,0, 79,82,68,0, +42,0, 78,68,0, 81,0, 79,68,0, 69,0, 79,82,0, 39,0, 42,0, +79,68,0, 69,0, 79,82,0, 92,39,0, 47,0, 69,73,76,0, 69,70,73,78,69,68,0, 79,79,82,0, 73,71,72,0, 80,0, 79,84,0, 65,71,69,0, 81,82,84,0, 10,0, 92,39,0, 69,73,76,0, 69,70,73,78,69,68,0, 79,79,82,0, 73,71,72,0, 80,0, 65,71,69,0, @@ -1954,28 +1974,27 @@ static const unsigned char ag_key_ends[] = { 71,0, 72,79,0, 82,89,0, 85,0, 68,69,68,0, 78,0, 78,0, 73,76,76,0, 69,88,0, 75,0, 84,0, 70,73,82,83,84,0, 67,76,73,66,0, 68,85,76,69,0, 70,73,82,83,84,0, 77,69,0, -80,65,71,69,0, 82,71,0, 71,69,0, 73,78,84,70,0, 66,76,73,67,0, -84,0, 75,76,78,0, 77,0, 88,84,0, 84,76,69,0, -69,82,73,76,79,71,0, 79,82,68,0, 92,39,0, 73,0, 72,76,0, -72,82,0, 76,76,0, 76,0, 80,0, 85,66,0, 73,0, 66,67,0, -65,76,76,0, 73,0, 73,0, 77,80,0, 80,0, 83,72,0, 69,84,0, 73,0, -86,0, 73,0, 79,80,0, 84,0, 72,76,0, 80,0, 83,72,0, 76,76,0, -69,76,0, 84,0, 77,0, 69,0, 76,0, 77,0, 76,0, 72,71,0, -72,76,0, 10,0, 92,39,0, 72,76,41,0, 73,76,0, 70,73,78,69,68,0, -79,79,82,0, 71,72,0, 80,0, 79,84,0, 65,71,69,0, 81,82,84,0, -10,0, +80,65,71,69,0, 82,71,0, 71,69,0, 66,76,73,67,0, 84,0, +75,76,78,0, 77,0, 88,84,0, 84,76,69,0, 69,82,73,76,79,71,0, +79,82,68,0, 92,39,0, 73,0, 72,76,0, 72,82,0, 76,76,0, 76,0, +80,0, 85,66,0, 73,0, 66,67,0, 65,76,76,0, 73,0, 73,0, 77,80,0, +80,0, 83,72,0, 69,84,0, 73,0, 86,0, 73,0, 79,80,0, 84,0, +72,76,0, 80,0, 83,72,0, 76,76,0, 69,76,0, 84,0, 77,0, 69,0, +76,0, 77,0, 76,0, 72,71,0, 72,76,0, 10,0, 92,39,0, 72,76,41,0, +73,76,0, 70,73,78,69,68,0, 79,79,82,0, 71,72,0, 80,0, 79,84,0, +65,71,69,0, 81,82,84,0, 10,0, }; #define AG_TCV(x) (((int)(x) >= -1 && (int)(x) <= 255) ? ag_tcv[(x) + 1] : 0) static const unsigned short ag_tcv[] = { - 38, 38,679,679,679,679,679,679,679,679, 1,423,679,679,679,679,679,679, - 679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, 1,523,680, - 681,682,520,510,683,455,454,518,516,478,517,429,519,684,685,686,686,687, - 687,687,687,688,688,679,425,689,679,690,691,692,693,694,693,695,693,696, + 38, 38,680,680,680,680,680,680,680,680, 1,423,680,680,680,680,680,680, + 680,680,680,680,680,680,680,680,680,680,680,680,680,680,680, 1,524,681, + 680,682,521,511,683,459,458,519,517,454,518,429,520,684,685,686,686,687, + 687,687,687,688,688,680,425,689,680,690,691,692,693,694,693,695,693,696, 697,698,697,697,697,697,697,699,697,697,697,700,697,701,697,697,697,702, - 697,697,679,703,679,508,704,692,693,694,693,695,693,696,697,698,697,697, - 697,697,697,699,697,697,697,700,697,701,697,697,697,702,697,697,691,506, - 691,525,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, + 697,697,680,703,680,509,704,692,693,694,693,695,693,696,697,698,697,697, + 697,697,697,699,697,697,697,700,697,701,697,697,697,702,697,697,691,507, + 691,526,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, @@ -2169,630 +2188,636 @@ static void ag_undo(void) { static const unsigned short ag_tstt[] = { -704,702,701,700,699,698,697,696,695,694,693,691,682,437,433,432,429,427,425, - 424,423,162,161,160,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,438,434,433,429,427,425, + 424,423,164,163,162,135,134,1,0,51,52, 1,0, -704,702,701,700,699,698,697,696,695,694,693,691,682,437,429,427,425,424,423, - 162,161,160,133,132,63,1,0,11,34,35,36,37,51,52,53,64,65,131,428,441, -453,452,451,450,449,448,447,446,445,439,432,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,461, - 429,427,425,424,423,159,133,1,0,136, -453,452,451,450,449,448,447,446,445,439,432,0,59,66,67,73,75,77,78,79,80,81, - 82,83, -704,702,701,700,699,698,697,696,695,694,693,691,682,678,677,676,675,674,673, - 672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656,655, - 654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638,637, - 636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620,619, - 618,617,616,615,614,613,612,611,610,609,608,606,605,604,603,602,601,600, - 599,598,597,596,595,594,592,591,590,589,588,587,586,585,584,583,582,581, - 580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564,563, - 562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546,545, - 544,489,488,487,486,485,484,482,481,480,479,477,476,475,474,473,472,471, - 470,469,468,467,466,465,464,463,462,461,460,459,458,457,450,449,446,444, - 443,442,440,438,431,430,429,427,425,424,423,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,438,429,427,425,424,423, + 164,163,162,135,134,64,1,0,11,34,35,36,37,51,52,53,65,66,133,428,442, +457,456,455,453,452,451,450,449,448,447,446,440,433,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,465, + 432,429,427,425,424,423,161,135,1,0,138, +457,456,455,453,452,451,450,449,448,447,446,440,433,0,60,67,68,74,76,78,79, + 80,81,82,83,84,86,87, +704,702,701,700,699,698,697,696,695,694,693,691,682,679,678,677,676,675,674, + 673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656, + 655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638, + 637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620, + 619,618,617,616,615,614,613,612,611,610,609,607,606,605,604,603,602,601, + 600,599,598,597,596,595,593,592,591,590,589,588,587,586,585,584,583,582, + 581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564, + 563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546, + 545,491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474, + 473,472,471,470,469,468,467,466,465,464,463,462,461,455,453,451,450,447, + 445,444,443,441,439,432,431,430,429,427,425,424,423,135,134,1,0,51,52, 423,0,45, -433,432,429,427,425,424,423,0,39,40,41,45,46,47,49,54,55, -704,702,701,700,699,698,697,696,695,694,693,691,682,678,677,676,675,674,673, - 672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656,655, - 654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638,637, - 636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620,619, - 618,617,616,615,614,613,612,611,610,609,608,606,605,604,603,602,601,600, - 599,598,597,596,595,594,592,591,590,589,588,587,586,585,584,583,582,581, - 580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564,563, - 562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546,545, - 544,489,488,487,486,485,484,482,481,480,479,477,476,475,474,473,472,471, - 470,469,468,467,466,465,464,463,462,461,460,459,458,457,450,449,446,444, - 443,442,440,438,431,430,429,427,425,424,423,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,678,677,676,675,674,673, - 672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656,655, - 654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638,637, - 636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620,619, - 618,617,616,615,614,613,612,611,610,609,608,606,605,604,603,602,601,600, - 599,598,597,596,595,594,592,591,590,589,588,587,586,585,584,583,582,581, - 580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564,563, - 562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546,545, - 544,489,488,487,486,485,484,482,481,480,479,477,476,475,474,473,472,471, - 470,469,468,467,466,465,464,463,462,461,460,459,458,457,450,449,446,444, - 443,442,440,438,433,432,429,427,425,424,423,133,132,1,0,21,30,31,32,33, - 54,55,62,75,79,80,84,92,131,243,256,257,258,259,260,261,262,263,264,265, - 267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284, +434,433,429,427,425,424,423,0,39,40,41,45,46,47,49,54,55, +704,702,701,700,699,698,697,696,695,694,693,691,682,679,678,677,676,675,674, + 673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656, + 655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638, + 637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620, + 619,618,617,616,615,614,613,612,611,610,609,607,606,605,604,603,602,601, + 600,599,598,597,596,595,593,592,591,590,589,588,587,586,585,584,583,582, + 581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564, + 563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546, + 545,491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474, + 473,472,471,470,469,468,467,466,465,464,463,462,461,455,453,451,450,447, + 445,444,443,441,439,432,431,430,429,427,425,424,423,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,679,678,677,676,675,674, + 673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656, + 655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638, + 637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620, + 619,618,617,616,615,614,613,612,611,610,609,607,606,605,604,603,602,601, + 600,599,598,597,596,595,593,592,591,590,589,588,587,586,585,584,583,582, + 581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564, + 563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546, + 545,491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474, + 473,472,471,470,469,468,467,466,465,464,463,462,461,455,453,451,450,447, + 445,444,443,441,439,434,433,429,427,425,424,423,135,134,1,0,21,30,31,32, + 33,54,55,63,76,80,81,88,96,133,244,257,258,259,260,261,262,263,264,265, + 266,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284, 285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302, 303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320, 321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338, - 339,340,341,342,343,345,346,347,348,349,350,351,352,353,354,355,356,357, + 339,340,341,342,343,344,346,347,348,349,350,351,352,353,354,355,356,357, 358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375, 376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393, 394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411, - 441, -704,702,701,700,699,698,697,696,695,694,693,691,682,437,429,427,425,424,423, - 162,161,160,133,132,63,38,1,0,11,35,36,51,52,53,64,65,131,428,441, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, -680,1,0,51,52, + 412,442, +704,702,701,700,699,698,697,696,695,694,693,691,682,438,429,427,425,424,423, + 164,163,162,135,134,64,38,1,0,11,35,36,51,52,53,65,66,133,428,442, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, +681,1,0,51,52, +681,1,0,51,52, +681,1,0,51,52, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, -444,443,442,440,438,1,0,51,52, -704,703,702,701,700,699,698,697,696,695,694,693,689,688,687,686,685,684,680, - 519,429,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,84,131,441, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, -680,0,10,12,434, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, +445,444,443,441,439,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,689,688,687,686,685,684,681, + 520,429,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,88,133,442, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, +681,0,10,12,435, +681,0,10,12,435, +681,0,10,12,435, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,76,84, - 86,129,131,164,195,197,202,203,204,205,206,207,208,209,210,211,212,213, - 214,215,216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,76,84, - 86,129,131,164,195,197,202,203,204,205,206,207,208,209,210,211,212,213, - 214,215,216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, -444,443,442,440,438,0,68,69,70,71,72, -689,680,0,10,12,13,14,434,435, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,77,88, + 90,131,133,166,196,198,203,204,205,206,207,208,209,210,211,212,213,214, + 215,216,217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,77,88, + 90,131,133,166,196,198,203,204,205,206,207,208,209,210,211,212,213,214, + 215,216,217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, +445,444,443,441,439,0,69,70,71,72,73, +689,681,0,10,12,13,14,435,436, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,455,454,437,433,432,429,427,426,425,424,423,162,161,160,133,132,38, - 1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, + 458,454,438,434,433,429,427,426,425,424,423,164,163,162,135,134,38,1,0, + 51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 489,488,487,486,485,484,482,481,480,479,478,477,476,475,474,473,472,471, - 470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454,444, - 443,442,440,438,433,432,431,430,429,427,426,425,424,423,1,0,51,52, -433,432,0,59,60,61, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,491, + 490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,460,459,458,455,454,453,445, + 444,443,441,439,434,433,431,430,429,427,426,425,424,423,1,0,51,52, +434,433,0,60,61,62, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,455,454,429,427,426,425,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, + 458,454,429,427,426,425,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,455,454,429,425,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, + 458,454,429,425,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,455,454,429,427,426,425,423,1,0,40,45,46,47,48,49,54,86,88,120,138, - 139,141,143,144,145,146,147,148,152,155,156,184,186,188,194,195,196,198, - 199,202,204,219,223,224,228,412,413,414,415,416,417,418,419,420,421,422, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, + 458,454,429,427,426,425,423,1,0,40,45,46,47,48,49,54,85,90,92,140,141, + 143,145,146,147,148,149,150,154,157,158,185,187,189,195,196,197,199,200, + 203,205,220,224,225,229,413,414,415,416,417,418,419,420,421,422, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,455,454,429,425,423,1,0,43,44,46,54,86,88,120,138,139,141,143,144, - 145,146,147,148,152,155,156,184,186,188,194,195,196,198,199,202,204,219, - 223,224,228,412,413,414,415,416,417,418,419,420,421,422, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, + 458,454,429,425,423,1,0,43,44,46,54,85,90,92,140,141,143,145,146,147, + 148,149,150,154,157,158,185,187,189,195,196,197,199,200,203,205,220,224, + 225,229,413,414,415,416,417,418,419,420,421,422, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,455,454,429,425,423,1,0,43,44,46,54,86,88,120,138,139,141,143,144, - 145,146,147,148,152,155,156,184,186,188,194,195,196,198,199,202,204,219, - 223,224,228,412,413,414,415,416,417,418,419,420,421,422, -704,702,701,700,699,698,697,696,695,694,693,691,682,678,677,676,675,674,673, - 672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656,655, - 654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638,637, - 636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620,619, - 618,617,616,615,614,613,612,611,610,609,608,606,605,604,603,602,601,600, - 599,598,597,596,595,594,592,591,590,589,588,587,586,585,584,583,582,581, - 580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564,563, - 562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546,545, - 544,489,488,487,486,485,484,482,481,480,479,477,476,475,474,473,472,471, - 470,469,468,467,466,465,464,463,462,461,460,459,458,457,450,449,446,444, - 443,442,440,438,431,430,429,427,425,424,423,133,132,0,21,30,31,32,33,39, - 40,41,45,46,47,49,54,55,62,75,79,80,84,92,131,243,256,257,258,259,260, - 261,262,263,264,265,267,268,269,270,271,272,273,274,275,276,277,278,279, - 280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297, - 298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315, - 316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333, - 334,335,336,337,338,339,340,341,342,343,345,346,347,348,349,350,351,352, - 353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370, - 371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388, - 389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406, - 407,408,409,410,411,441, -492,489,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -667,542,541,540,247,245,237,235,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -667,542,247,245,237,235,233,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, + 458,454,429,425,423,1,0,43,44,46,54,85,90,92,140,141,143,145,146,147, + 148,149,150,154,157,158,185,187,189,195,196,197,199,200,203,205,220,224, + 225,229,413,414,415,416,417,418,419,420,421,422, +704,702,701,700,699,698,697,696,695,694,693,691,682,679,678,677,676,675,674, + 673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656, + 655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638, + 637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620, + 619,618,617,616,615,614,613,612,611,610,609,607,606,605,604,603,602,601, + 600,599,598,597,596,595,593,592,591,590,589,588,587,586,585,584,583,582, + 581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564, + 563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546, + 545,491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474, + 473,472,471,470,469,468,467,466,465,464,463,462,461,455,453,451,450,447, + 445,444,443,441,439,432,431,430,429,427,425,424,423,135,134,0,21,30,31, + 32,33,39,40,41,45,46,47,49,54,55,59,63,76,80,81,88,96,133,244,257,258, + 259,260,261,262,263,264,265,266,268,269,270,271,272,273,274,275,276,277, + 278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295, + 296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313, + 314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331, + 332,333,334,335,336,337,338,339,340,341,342,343,344,346,347,348,349,350, + 351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368, + 369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386, + 387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404, + 405,406,407,408,409,410,411,412,442, +494,491,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +668,543,542,541,248,246,238,236,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +668,543,248,246,238,236,234,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, 687,686,685,684,1,0,51,52, -667,542,541,540,247,245,237,235,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -667,542,247,245,237,235,233,1,0,51,52, +668,543,542,541,248,246,238,236,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +668,543,248,246,238,236,234,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -667,539,538,247,245,237,235,233,1,0,51,52, -667,539,538,247,245,237,235,233,1,0,51,52, -667,539,538,247,245,237,235,233,1,0,51,52, -667,539,538,247,245,237,235,233,1,0,51,52, -667,245,235,233,1,0,51,52, -667,245,235,233,1,0,51,52, -667,542,247,245,237,235,233,1,0,51,52, -667,542,247,245,237,235,233,1,0,51,52, -667,542,247,245,237,235,233,1,0,51,52, -667,542,541,540,247,245,237,235,233,1,0,51,52, -667,542,541,540,247,245,237,235,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +668,540,539,248,246,238,236,234,1,0,51,52, +668,540,539,248,246,238,236,234,1,0,51,52, +668,540,539,248,246,238,236,234,1,0,51,52, +668,540,539,248,246,238,236,234,1,0,51,52, +668,246,236,234,1,0,51,52, +668,246,236,234,1,0,51,52, +668,543,248,246,238,236,234,1,0,51,52, +668,543,248,246,238,236,234,1,0,51,52, +668,543,248,246,238,236,234,1,0,51,52, +668,543,542,541,248,246,238,236,234,1,0,51,52, +668,543,542,541,248,246,238,236,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, 687,686,685,684,1,0,51,52, -478,1,0,51,52, -478,1,0,51,52, -478,1,0,51,52, +454,1,0,51,52, +454,1,0,51,52, +454,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -667,539,538,247,245,237,235,233,1,0,51,52, -667,539,538,247,245,237,235,233,1,0,51,52, -667,539,538,247,245,237,235,233,1,0,51,52, -667,539,538,247,245,237,235,233,1,0,51,52, -667,245,235,233,1,0,51,52, -667,245,235,233,1,0,51,52, -667,542,247,245,237,235,233,1,0,51,52, -667,542,247,245,237,235,233,1,0,51,52, -667,542,247,245,237,235,233,1,0,51,52, -667,542,541,540,247,245,237,235,233,1,0,51,52, -667,542,541,540,247,245,237,235,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, -539,240,239,238,237,236,235,234,233,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +668,540,539,248,246,238,236,234,1,0,51,52, +668,540,539,248,246,238,236,234,1,0,51,52, +668,540,539,248,246,238,236,234,1,0,51,52, +668,540,539,248,246,238,236,234,1,0,51,52, +668,246,236,234,1,0,51,52, +668,246,236,234,1,0,51,52, +668,543,248,246,238,236,234,1,0,51,52, +668,543,248,246,238,236,234,1,0,51,52, +668,543,248,246,238,236,234,1,0,51,52, +668,543,542,541,248,246,238,236,234,1,0,51,52, +668,543,542,541,248,246,238,236,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, 705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,680,679,543,525,523,522,520,519,518,517,516,514,512,510, - 508,506,505,503,501,499,497,495,494,491,478,455,454,429,427,425,424,423, - 1,0,51,52,136, -543,427,425,424,423,1,0,51,52, + 685,684,683,682,681,680,544,526,524,523,521,520,519,518,517,515,513,511, + 509,507,506,504,502,500,498,496,493,459,458,454,432,429,427,425,424,423, + 1,0,51,52,138, +544,427,425,424,423,1,0,51,52, 705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,680,679,543,525,523,522,521,520,519,518,517,516,515,514, - 513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496, - 495,494,493,491,478,455,454,429,427,425,424,423,1,0,86, + 685,684,683,682,681,680,544,526,524,523,522,521,520,519,518,517,516,515, + 514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, + 496,495,493,459,458,454,432,429,427,425,424,423,1,0,90, 427,425,424,423,1,0,51, -543,0,266, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,76,84, - 86,129,131,164,195,197,202,203,204,205,206,207,208,209,210,211,212,213, - 214,215,216,217,218,441,490,537, -489,488,487,486,485,484,482,481,480,479,477,476,475,474,473,472,471,470,469, - 468,467,466,465,464,463,462,461,460,459,458,457,444,443,442,440,438,0, - 68,69,70,71,72,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108, - 109,110,112,113,114,115,116,117,118,119,121,122,123,124,125,126,127,128, - 129, +544,0,267, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,77,88, + 90,131,133,166,196,198,203,204,205,206,207,208,209,210,211,212,213,214, + 215,216,217,218,219,442,492,538, +491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,455,453,445,444,443,441,439, + 0,69,70,71,72,73,83,84,97,98,99,100,101,102,103,104,105,106,107,108,109, + 110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128, + 129,130,131, 427,425,424,423,1,0,51,52, 705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,680,679,525,523,520,519,518,517,516,510,508,506,478,455, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, 454,429,425,1,0,51,52, 427,425,424,423,1,0,51,52, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478, - 455,454,429,425,423,1,0,140, -491,478,454,427,425,424,423,1,0,51,52, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, + 454,429,425,423,1,0,142, +493,458,454,427,425,424,423,1,0,51,52, +454,0,85, +427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, 427,425,424,423,0,39,40,41,45,46,47,49, 427,425,424,423,0,39,40,41,45,46,47,49, @@ -2800,1315 +2825,1304 @@ static const unsigned short ag_tstt[] = { 688,687,686,685,684,0, 687,686,685,684,0, 685,684,0, -704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,543, - 522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, - 504,503,502,501,500,499,498,497,496,495,494,493,491,455,454,429,427,425, +704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,544, + 523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, + 505,504,503,502,501,500,499,498,497,496,495,493,459,458,432,429,427,425, 424,423,1,0, -704,702,698,696,695,694,693,688,687,686,685,684,682,543,522,521,520,519,518, - 517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, - 499,498,497,496,495,494,493,491,454,429,427,425,424,423,221,220,1,0, +704,702,698,696,695,694,693,688,687,686,685,684,682,544,523,522,521,520,519, + 518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, + 500,499,498,497,496,495,493,458,432,429,427,425,424,423,222,221,1,0, 688,687,686,685,684,0, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478,455, - 454,429,425,423,232,1,0,16, + 685,684,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458,454, + 429,425,423,233,1,0,16, 688,687,686,685,684,0, 698,696,695,694,693,688,687,686,685,684,0, -687,686,685,684,543,522,521,520,519,518,517,516,515,514,513,512,511,510,509, - 508,507,506,505,504,503,502,501,500,499,498,497,496,495,494,493,491,454, +687,686,685,684,544,523,522,521,520,519,518,517,516,515,514,513,512,511,510, + 509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,493,458,432, 427,425,424,423,1,0, -685,684,543,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507, - 506,505,504,503,502,501,500,499,498,497,496,495,494,493,491,454,427,425, +685,684,544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, + 507,506,505,504,503,502,501,500,499,498,497,496,495,493,458,432,427,425, 424,423,1,0, -696,695,694,693,688,687,686,685,684,543,522,521,520,519,518,517,516,515,514, - 513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496, - 495,494,493,491,454,427,425,424,423,1,0, -704,698,696,695,694,693,688,687,686,685,684,682,543,522,521,520,519,518,517, - 516,515,514,513,512,510,509,508,507,506,505,504,503,502,501,500,499,498, - 497,496,495,494,491,454,429,427,425,424,423,221,220,1,0,222, -455,1,0,51,52, -455,427,425,424,423,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -543,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, - 504,503,502,501,500,499,498,497,496,495,494,493,491,454,427,425,424,423, +696,695,694,693,688,687,686,685,684,544,523,522,521,520,519,518,517,516,515, + 514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, + 496,495,493,458,432,427,425,424,423,1,0, +704,698,696,695,694,693,688,687,686,685,684,682,544,523,522,521,520,519,518, + 517,516,515,514,513,511,510,509,508,507,506,505,504,503,502,501,500,499, + 498,497,496,493,458,432,429,427,425,424,423,222,221,1,0,223, +459,1,0,51,52, +459,427,425,424,423,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, + 505,504,503,502,501,500,499,498,497,496,495,493,458,432,427,425,424,423, 1,0,51,52, -543,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, - 504,503,502,501,500,499,498,497,496,495,494,493,491,454,427,425,424,423, +544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, + 505,504,503,502,501,500,499,498,497,496,495,493,458,432,427,425,424,423, 1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, - 525,524,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427, - 426,425,424,423,230,133,132,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,1,0,51,52, + 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, + 525,524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426, + 425,424,423,231,135,134,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, - 525,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427,426, - 425,424,423,230,133,132,1,0,51,52, + 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, + 524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426,425, + 424,423,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, - 525,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427,426, - 425,424,423,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, - 211,212,213,214,215,216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, - 211,212,213,214,215,216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, - 211,212,213,214,215,216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, - 211,212,213,214,215,216,217,218,441,490,537, -543,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, - 504,503,502,501,500,499,498,497,496,495,494,493,491,454,427,425,424,423, + 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, + 524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426,425, + 424,423,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 212,213,214,215,216,217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 212,213,214,215,216,217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 212,213,214,215,216,217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 212,213,214,215,216,217,218,219,442,492,538, +544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, + 505,504,503,502,501,500,499,498,497,496,495,493,458,432,427,425,424,423, 1,0,51,52, -543,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, - 504,503,502,501,500,499,498,497,496,495,494,493,491,454,425,423,1,0,51, - 52,196,198,199,200,201, -543,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, - 499,498,497,496,495,494,493,491,454,427,425,424,423,1,0,51,52,194,195, -543,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, - 497,496,495,494,493,491,454,427,425,424,423,1,0,51,52,190,191,192,193, -543,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494, - 493,491,454,427,425,424,423,1,0,51,52,188,189, -543,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494,493,491, - 454,427,425,424,423,1,0,51,52,186,187, -507,506,0,184,185, -505,504,503,502,501,500,499,498,497,496,495,494,493,427,425,424,423,1,0,165, - 166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, +544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, + 505,504,503,502,501,500,499,498,497,496,495,493,458,432,425,423,1,0,51, + 52,197,199,200,201,202, +544,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, + 500,499,498,497,496,495,493,458,432,427,425,424,423,1,0,51,52,195,196, +544,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499, + 498,497,496,495,493,458,432,427,425,424,423,1,0,51,52,191,192,193,194, +544,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495, + 493,458,432,427,425,424,423,1,0,51,52,189,190, +544,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,493,458, + 432,427,425,424,423,1,0,51,52,187,188, +508,507,0,185,186, +506,505,504,503,502,501,500,499,498,497,496,495,432,427,425,424,423,1,0,59, + 167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, -427,425,424,423,1,0,74, +427,425,424,423,1,0,75, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,679,525,523,520,519,518,517,516,510,508,506,478, - 455,454,429,425,1,0, + 686,685,684,683,682,680,526,524,521,520,519,518,517,511,509,507,459,458, + 454,429,425,1,0, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, -704,703,702,701,700,699,698,697,696,695,694,693,689,688,687,686,685,684,680, - 519,429,1,0,51,52, -704,703,702,701,700,699,698,697,696,695,694,693,689,688,687,686,685,684,680, - 519,429,0,10,12,13,14,19,434,435,436, +704,703,702,701,700,699,698,697,696,695,694,693,689,688,687,686,685,684,681, + 520,429,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,689,688,687,686,685,684,681, + 520,429,0,10,12,13,14,19,435,436,437, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, - 525,524,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427, - 426,425,424,423,230,133,132,1,0,51,52, + 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, + 525,524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426, + 425,424,423,231,135,134,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, - 525,524,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427, - 426,425,424,423,230,133,132,1,0,51,52, + 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, + 525,524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426, + 425,424,423,231,135,134,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,455,454,429,427,426,425,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, + 458,454,429,427,426,425,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, - 525,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427,426, - 425,424,423,230,133,132,1,0,51,52, + 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, + 524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426,425, + 424,423,231,135,134,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, - 525,524,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427, - 426,425,424,423,230,133,132,1,0,51,52, + 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, + 525,524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426, + 425,424,423,231,135,134,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, - 525,524,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427, - 426,425,424,423,230,133,132,1,0,51,52, + 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, + 525,524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426, + 425,424,423,231,135,134,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, - 525,524,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427, - 426,425,424,423,230,133,132,1,0,51,52, + 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, + 525,524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426, + 425,424,423,231,135,134,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, - 525,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427,426, - 425,424,423,230,133,132,1,0,51,52, + 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, + 524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426,425, + 424,423,231,135,134,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,543,525,523,522,521,520,519,518,517,516, + 686,685,684,683,682,681,680,544,526,524,523,522,521,520,519,518,517,516, 515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, - 497,496,495,494,493,491,478,456,455,454,429,427,426,425,424,423,1,0,51, - 52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 497,496,495,493,460,459,458,454,432,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, - 525,524,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427, - 426,425,424,423,230,133,132,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,536,534,533,532,531,530,529,528,527,526, - 525,523,520,519,518,517,516,510,508,506,489,478,456,455,454,429,427,426, - 425,424,423,230,133,132,1,0,51,52, + 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, + 525,524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426, + 425,424,423,231,135,134,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, + 524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426,425, + 424,423,231,135,134,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,455,454,429,427,426,425,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,456,455,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,458,454,429,427,426,425,424,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,455,454,437,433,432,429,427,426,425,424,423,162,161,160,133,132,38, - 1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, + 458,454,438,434,433,429,427,426,425,424,423,164,163,162,135,134,38,1,0, + 51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,455,454,429,425,1,0,46,54,86,88,120,138,139,141,143,144,145,146,147, - 148,152,155,156,184,186,188,194,195,196,198,199,202,204,219,223,224,228, - 412,413,414,415,416,417,418,419,420,421,422, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, + 458,454,429,425,1,0,46,54,85,90,92,140,141,143,145,146,147,148,149,150, + 154,157,158,185,187,189,195,196,197,199,200,203,205,220,224,225,229,413, + 414,415,416,417,418,419,420,421,422, 423,0,45, 423,0,45, -489,488,487,486,485,484,482,481,480,479,477,476,475,474,473,472,471,470,469, - 468,467,466,465,464,463,462,461,460,459,458,457,444,443,442,440,438,431, - 430,0,56,58,68,69,70,71,72,93,94,95,96,97,98,99,100,101,102,103,104,105, - 106,107,108,109,110,112,113,114,115,116,117,118,119,121,122,123,124,125, - 126,127,128,129, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,455,453,445,444,443,441,439, + 431,430,0,56,58,69,70,71,72,73,83,84,97,98,99,100,101,102,103,104,105, + 106,107,108,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124, + 125,126,127,128,129,130,131, 427,425,424,423,1,0,51,52, -492,489,427,425,424,423,0,22,39,40,41,45,46,47,49,129,163, -667,542,541,540,247,245,237,235,233,0,244,246,248,249,253,254,255, -539,240,239,238,237,236,235,234,233,0,4,241,593, -667,542,247,245,237,235,233,0,5,244,246,248,607, -687,686,685,684,0,344, -478,0,120, -478,0,120, -478,0,120, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -667,539,538,247,245,237,235,233,0,242,244,246,248,250,251, -667,539,538,247,245,237,235,233,0,242,244,246,248,250,251, -667,539,538,247,245,237,235,233,0,242,244,246,248,250,251, -667,539,538,247,245,237,235,233,0,242,244,246,248,250,251, -667,245,235,233,0,244,246,252, -667,245,235,233,0,244,246,252, -667,542,247,245,237,235,233,0,5,244,246,248,607, -667,542,247,245,237,235,233,0,5,244,246,248,607, -667,542,247,245,237,235,233,0,5,244,246,248,607, -667,542,541,540,247,245,237,235,233,0,244,246,248,249,253,254,255, -667,542,541,540,247,245,237,235,233,0,244,246,248,249,253,254,255, -539,240,239,238,237,236,235,234,233,0,4,241,593, -539,240,239,238,237,236,235,234,233,0,4,241,593, -539,240,239,238,237,236,235,234,233,0,4,241,593, -539,240,239,238,237,236,235,234,233,0,4,241,593, -539,240,239,238,237,236,235,234,233,0,4,241,593, -539,240,239,238,237,236,235,234,233,0,4,241,593, -539,240,239,238,237,236,235,234,233,0,4,241,593, -539,240,239,238,237,236,235,234,233,0,4,241,593, -539,240,239,238,237,236,235,234,233,0,4,241,593, -539,240,239,238,237,236,235,234,233,0,4,241,593, -539,240,239,238,237,236,235,234,233,0,4,241,593, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, - 489,455,429,230,133,132,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,84,86,87,129,131,195,197,202,203,204,205,206,207,208,209,210, - 211,212,213,214,215,216,217,218,434,441,483,490,537, -692,688,687,686,685,684,683,682,520,517,516,230,1,0,2,6,7,15,17,217,218,490, -678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663,662,661,660, - 659,658,657,656,655,654,653,652,651,650,649,648,647,646,645,644,643,642, - 641,640,639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624, - 623,622,621,620,619,618,617,616,615,614,613,612,611,610,609,608,606,605, - 604,603,602,601,600,599,598,597,596,595,594,592,591,590,589,588,587,586, - 585,584,583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568, - 567,566,565,564,563,562,561,560,559,558,557,556,555,554,553,552,551,550, - 549,548,547,546,545,544,1,0,51,52, -678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663,662,661,660, - 659,658,657,656,655,654,653,652,651,650,649,648,647,646,645,644,643,642, - 641,640,639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624, - 623,622,621,620,619,618,617,616,615,614,613,612,611,610,609,608,606,605, - 604,603,602,601,600,599,598,597,596,595,594,592,591,590,589,588,587,586, - 585,584,583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568, - 567,566,565,564,563,562,561,560,559,558,557,556,555,554,553,552,551,550, - 549,548,547,546,545,544,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, -704,703,702,701,700,699,698,697,696,695,694,693,688,687,686,685,684,519,429, +494,491,427,425,424,423,0,22,39,40,41,45,46,47,49,131,165, +668,543,542,541,248,246,238,236,234,0,245,247,249,250,254,255,256, +540,241,240,239,238,237,236,235,234,0,4,242,594, +668,543,248,246,238,236,234,0,5,245,247,249,608, +687,686,685,684,0,345, +454,0,85, +454,0,85, +454,0,85, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +668,540,539,248,246,238,236,234,0,243,245,247,249,251,252, +668,540,539,248,246,238,236,234,0,243,245,247,249,251,252, +668,540,539,248,246,238,236,234,0,243,245,247,249,251,252, +668,540,539,248,246,238,236,234,0,243,245,247,249,251,252, +668,246,236,234,0,245,247,253, +668,246,236,234,0,245,247,253, +668,543,248,246,238,236,234,0,5,245,247,249,608, +668,543,248,246,238,236,234,0,5,245,247,249,608, +668,543,248,246,238,236,234,0,5,245,247,249,608, +668,543,542,541,248,246,238,236,234,0,245,247,249,250,254,255,256, +668,543,542,541,248,246,238,236,234,0,245,247,249,250,254,255,256, +540,241,240,239,238,237,236,235,234,0,4,242,594, +540,241,240,239,238,237,236,235,234,0,4,242,594, +540,241,240,239,238,237,236,235,234,0,4,242,594, +540,241,240,239,238,237,236,235,234,0,4,242,594, +540,241,240,239,238,237,236,235,234,0,4,242,594, +540,241,240,239,238,237,236,235,234,0,4,242,594, +540,241,240,239,238,237,236,235,234,0,4,242,594, +540,241,240,239,238,237,236,235,234,0,4,242,594, +540,241,240,239,238,237,236,235,234,0,4,242,594, +540,241,240,239,238,237,236,235,234,0,4,242,594, +540,241,240,239,238,237,236,235,234,0,4,242,594, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,459,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,88,90,91,131,133,196,198,203,204,205,206,207,208,209,210,211, + 212,213,214,215,216,217,218,219,435,442,485,492,538, +692,688,687,686,685,684,683,682,521,518,517,231,1,0,2,6,7,15,17,218,219,492, +679,678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663,662,661, + 660,659,658,657,656,655,654,653,652,651,650,649,648,647,646,645,644,643, + 642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627,626,625, + 624,623,622,621,620,619,618,617,616,615,614,613,612,611,610,609,607,606, + 605,604,603,602,601,600,599,598,597,596,595,593,592,591,590,589,588,587, + 586,585,584,583,582,581,580,579,578,577,576,575,574,573,572,571,570,569, + 568,567,566,565,564,563,562,561,560,559,558,557,556,555,554,553,552,551, + 550,549,548,547,546,545,1,0,51,52, +679,678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663,662,661, + 660,659,658,657,656,655,654,653,652,651,650,649,648,647,646,645,644,643, + 642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627,626,625, + 624,623,622,621,620,619,618,617,616,615,614,613,612,611,610,609,607,606, + 605,604,603,602,601,600,599,598,597,596,595,593,592,591,590,589,588,587, + 586,585,584,583,582,581,580,579,578,577,576,575,574,573,572,571,570,569, + 568,567,566,565,564,563,562,561,560,559,558,557,556,555,554,553,552,551, + 550,549,548,547,546,545,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, +704,703,702,701,700,699,698,697,696,695,694,693,688,687,686,685,684,520,429, 1,0,51,52, -704,703,702,701,700,699,698,697,696,695,694,693,688,687,686,685,684,519,429, - 0,19,436, +704,703,702,701,700,699,698,697,696,695,694,693,688,687,686,685,684,520,429, + 0,19,437, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, -683,680,1,0,51,52, -683,680,0,10,12,18,20,434,483, +683,681,1,0,51,52, +683,681,0,10,12,18,20,435,485, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,427,425,424,423,133,132, +704,702,701,700,699,698,697,696,695,694,693,691,682,427,425,424,423,135,134, 1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,427,425,424,423,133,132, - 1,0,21,131,441, -680,1,0,51,52, -680,0,10,12,434, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, - 489,455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, - 489,455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, - 489,455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, - 489,455,429,230,133,132,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28,29, - 57,84,86,129,131,195,197,202,203,204,205,206,207,208,209,210,211,212, - 213,214,215,216,217,218,434,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,111,131, - 441, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,111,131, - 441, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,111,131, - 441, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, - 489,455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, - 489,455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, - 489,455,429,230,133,132,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,84,86,87,129,131,195,197,202,203,204,205,206,207,208,209,210, - 211,212,213,214,215,216,217,218,434,441,483,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, - 489,455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, - 489,455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, - 489,455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, - 489,455,429,230,133,132,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,84,86,87,129,131,195,197,202,203,204,205,206,207,208,209,210, - 211,212,213,214,215,216,217,218,434,441,483,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, +704,702,701,700,699,698,697,696,695,694,693,691,682,427,425,424,423,135,134, + 1,0,21,133,442, +681,0,10,12,435, +681,0,10,12,435, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,459,429,231,135,134,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28,29, + 57,88,90,131,133,196,198,203,204,205,206,207,208,209,210,211,212,213, + 214,215,216,217,218,219,435,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,115,133, + 442, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,115,133, + 442, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,115,133, + 442, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,459,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,88,90,91,131,133,196,198,203,204,205,206,207,208,209,210,211, + 212,213,214,215,216,217,218,219,435,442,485,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,459,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,88,90,91,131,133,196,198,203,204,205,206,207,208,209,210,211, + 212,213,214,215,216,217,218,219,435,442,485,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, 427,425,424,423,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, -492,489,427,425,424,423,1,0,51,52, -492,489,427,425,424,423,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, +494,491,427,425,424,423,1,0,51,52, +494,491,427,425,424,423,1,0,51,52, 427,425,424,423,0,39,40,41,45,46,47,49, 705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,680,679,525,523,520,519,518,517,516,510,508,506,478,455, - 454,429,425,0,46,54,85,86,88,120,138,139,143,144,145,146,147,148,152, - 155,156,184,186,188,194,195,196,198,199,202,204,219,223,224,228,412,413, - 415,416,417,418,419,420,421,422, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, + 454,429,425,0,46,54,85,89,90,92,140,141,145,146,147,148,149,150,154,157, + 158,185,187,189,195,196,197,199,200,203,205,220,224,225,229,413,414,415, + 416,417,418,419,420,421,422, +427,425,424,423,0,39,40,41,45,46,47,49, +703,702,701,700,699,696,694,686,685,684,682,681,423,0,155, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 427,425,424,423,0,39,40,41,45,46,47,49, -703,702,701,700,699,696,694,686,685,684,682,680,423,0,153, 427,425,424,423,0,39,40,41,45,46,47,49, 427,425,424,423,0,39,40,41,45,46,47,49, 696,695,694,693,688,687,686,685,684,0, 703,701,700,699,684,683,0, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478, - 455,454,429,425,423,232,1,0,16, -698,696,695,694,693,688,687,686,685,684,543,522,521,520,519,518,517,516,515, - 514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, - 496,495,494,493,491,454,427,425,424,423,1,0, -698,696,695,694,693,688,687,686,685,684,543,522,521,520,519,518,517,516,515, - 514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, - 496,495,494,493,491,454,427,425,424,423,1,0, -455,0,86, -455,0,86, -455,0,86, -455,0,86, -455,0,86, -455,0,86, -455,0,86, -455,0,86, -455,0,86, -455,0,86, -455,0,86, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, + 454,429,425,423,233,1,0,16, +698,696,695,694,693,688,687,686,685,684,544,523,522,521,520,519,518,517,516, + 515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, + 497,496,495,493,458,432,427,425,424,423,1,0, +698,696,695,694,693,688,687,686,685,684,544,523,522,521,520,519,518,517,516, + 515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, + 497,496,495,493,458,432,427,425,424,423,1,0, +459,0,90, +459,0,90, +459,0,90, +459,0,90, +459,0,90, +459,0,90, +459,0,90, +459,0,90, +459,0,90, +459,0,90, +459,0,90, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, 688,687,686,685,684,0, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 427,425,424,423,0,39,40,41,45,46,47,49, 427,425,424,423,0,39,40,41,45,46,47,49, 427,425,424,423,0,39,40,41,45,46,47,49, 427,425,424,423,0,39,40,41,45,46,47,49, 427,425,424,423,0,39,40,41,45,46,47,49, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, 427,425,424,423,0,39,40,41,45,46,47,49, 427,425,424,423,0,39,40,41,45,46,47,49, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506, - 478,455,454,429,425,423,1,0, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, + 458,454,429,425,423,1,0, 427,425,424,423,0,39,40,41,45,46,47,49, 427,425,424,423,0,39,40,41,45,46,47,49, -704,703,702,701,700,699,698,697,696,695,694,693,688,687,686,685,684,519,429, +704,703,702,701,700,699,698,697,696,695,694,693,688,687,686,685,684,520,429, 425,423,1,0,51,52, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, +427,425,424,423,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, 427,425,424,423,0,39,40,41,45,46,47,49, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, -543,478,427,425,424,423,1,0,51,52, -543,478,427,425,424,423,1,0,51,52, -543,478,427,425,424,423,1,0,51,52, -543,491,478,427,425,424,423,1,0,51,52, -543,478,427,425,424,423,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -543,427,425,424,423,1,0,51,52, -543,427,425,424,423,1,0,51,52, -491,1,0,51,52, +544,454,427,425,424,423,1,0,51,52, +544,454,427,425,424,423,1,0,51,52, +544,454,427,425,424,423,1,0,51,52, +544,493,454,427,425,424,423,1,0,51,52, +544,454,427,425,424,423,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +544,427,425,424,423,1,0,51,52, +544,427,425,424,423,1,0,51,52, +493,1,0,51,52, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478,455, - 454,429,425,423,232,1,0,16, + 685,684,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458,454, + 429,425,423,233,1,0,16, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478, - 455,454,429,425,423,232,1,0,16, -491,454,427,425,424,423,1,0,51,52, -491,454,0,88,130, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, + 454,429,425,423,233,1,0,16, +493,458,427,425,424,423,1,0,51,52, +493,458,0,92,132, 696,695,694,693,688,687,686,685,684,0, -704,698,696,695,694,693,688,687,686,685,684,682,427,425,424,423,221,220,1,0, - 222, -678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663,662,661,660, - 659,658,657,656,655,654,653,652,651,650,649,648,647,646,645,644,643,642, - 641,640,639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624, - 623,622,621,620,619,618,617,616,615,614,613,612,611,610,609,608,606,605, - 604,603,602,601,600,599,598,597,596,595,594,592,591,590,589,588,587,586, - 585,584,583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568, - 567,566,565,564,563,562,561,560,559,558,557,556,555,554,553,552,551,550, - 549,548,547,546,545,544,0,31,32,243,256,257,258,259,260,261,262,263,264, - 265,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283, - 284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301, - 302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319, - 320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337, - 338,339,340,341,342,343,345,346,347,348,349,350,351,352,353,354,355,356, - 357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374, - 375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392, - 393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410, - 411, +704,698,696,695,694,693,688,687,686,685,684,682,427,425,424,423,222,221,1,0, + 223, +679,678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663,662,661, + 660,659,658,657,656,655,654,653,652,651,650,649,648,647,646,645,644,643, + 642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627,626,625, + 624,623,622,621,620,619,618,617,616,615,614,613,612,611,610,609,607,606, + 605,604,603,602,601,600,599,598,597,596,595,593,592,591,590,589,588,587, + 586,585,584,583,582,581,580,579,578,577,576,575,574,573,572,571,570,569, + 568,567,566,565,564,563,562,561,560,559,558,557,556,555,554,553,552,551, + 550,549,548,547,546,545,0,31,32,244,257,258,259,260,261,262,263,264,265, + 266,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284, + 285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302, + 303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320, + 321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338, + 339,340,341,342,343,344,346,347,348,349,350,351,352,353,354,355,356,357, + 358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375, + 376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393, + 394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411, + 412, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478,455, - 454,429,425,423,232,1,0,16, -478,0,120, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, - 489,455,429,230,133,132,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,84,86,87,129,131,195,197,202,203,204,205,206,207,208,209,210, - 211,212,213,214,215,216,217,218,434,441,483,490,537, -491,427,425,424,423,1,0,130, -491,427,425,424,423,1,0,130, -491,427,425,424,423,1,0,130, -491,427,425,424,423,1,0,130, -491,427,425,424,423,1,0,130, + 685,684,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458,454, + 429,425,423,233,1,0,16, +454,0,85, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,459,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,88,90,91,131,133,196,198,203,204,205,206,207,208,209,210,211, + 212,213,214,215,216,217,218,219,435,442,485,492,538, +493,427,425,424,423,1,0,132, +493,427,425,424,423,1,0,132, +493,427,425,424,423,1,0,132, +493,427,425,424,423,1,0,132, +493,427,425,424,423,1,0,132, 705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,680,679,525,523,520,519,518,517,516,510,508,506,478,456, - 455,454,429,425,423,1,0,46,51,52,54,86,88,91,120,138,139,143,144,145, - 146,147,148,152,155,156,184,186,188,194,195,196,198,199,202,204,219,223, - 224,228,412,413,415,416,417,418,419,420,421,422, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, + 458,454,429,425,423,1,0,46,51,52,54,85,90,92,95,140,141,145,146,147,148, + 149,150,154,157,158,185,187,189,195,196,197,199,200,203,205,220,224,225, + 229,413,414,415,416,417,418,419,420,421,422, 696,695,694,693,688,687,686,685,684,0, 688,687,686,685,684,0, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478, - 455,454,429,425,423,1,0, -683,0, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -454,1,0,51,52, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, + 454,429,425,423,1,0, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, - 211,212,213,214,215,216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, - 211,212,213,214,215,216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, - 211,212,213,214,215,216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, - 211,212,213,214,215,216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,520,517,516,489,455,429,230, - 133,132,0,2,6,7,8,9,15,17,21,84,86,129,131,197,205,206,207,208,209,210, - 211,212,213,214,215,216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,25,29,84,86,129,131,195,197, - 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, - 490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,25,29,84,86,129,131,195,197, - 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, - 490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,25,27,29,84,86,129,131,195,197, - 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, - 490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,25,27,29,84,86,129,131,195,197, - 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, - 490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,25,27,29,84,86,129,131,195,197, - 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, - 490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,25,27,29,84,86,129,131,195,197, - 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, - 490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,24,25,27,29,84,86,129,131,195, - 197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, - 441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,24,25,27,29,84,86,129,131,195, - 197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, - 441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,27,29,84,86,129,131, - 195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,27,29,84,86,129,131, - 195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,84,86,129, - 131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,84,86,129, - 131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,441,490,537, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +683,0, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +458,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 212,213,214,215,216,217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 212,213,214,215,216,217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 212,213,214,215,216,217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 212,213,214,215,216,217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 212,213,214,215,216,217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,25,29,88,90,131,133,196,198, + 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, + 492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,25,29,88,90,131,133,196,198, + 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, + 492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,25,27,29,88,90,131,133,196,198, + 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, + 492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,25,27,29,88,90,131,133,196,198, + 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, + 492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,25,27,29,88,90,131,133,196,198, + 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, + 492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,25,27,29,88,90,131,133,196,198, + 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, + 492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,24,25,27,29,88,90,131,133,196, + 198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219, + 442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,24,25,27,29,88,90,131,133,196, + 198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219, + 442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,29,88,90,131,133, + 196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, + 219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,29,88,90,131,133, + 196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, + 219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,88,90,131, + 133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,88,90,131, + 133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,442,492,538, 427,425,424,423,1,0,51,52, 427,425,424,423,0,39,40,41,45,46,47,49, 427,425,424,423,0,39,40,41,45,46,47,49, 427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,0,39,40,41,45,46,47,49, 427,425,424,423,1,0,51,52, 427,425,424,423,1,0,51,52, 427,425,424,423,0,39,40,41,45,46,47,49, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -491,0,130, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +493,0,132, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478, - 455,454,429,425,423,232,1,0,16, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, + 454,429,425,423,233,1,0,16, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,680,539,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517, - 516,489,455,429,240,239,238,237,236,235,234,233,230,133,132,1,0,51,52, + 682,681,540,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518, + 517,491,459,429,241,240,239,238,237,236,235,234,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, - 489,455,429,230,133,132,1,0,51,52, -543,0,266, -543,427,425,424,423,1,0,51,52, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,459,429,231,135,134,1,0,51,52, +544,0,267, +544,427,425,424,423,1,0,51,52, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478,455, - 454,429,425,423,232,1,0,16, + 685,684,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458,454, + 429,425,423,233,1,0,16, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,1,0,51,52, -491,427,425,424,423,1,0,130, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,1,0,51,52, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,1,0,51,52, +493,427,425,424,423,1,0,132, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, 705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,680,679,525,523,520,519,518,517,516,510,508,506,478,456, - 455,454,429,427,425,424,423,1,0,51,52, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, + 458,454,429,427,425,424,423,1,0,51,52, 705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,680,679,525,523,520,519,518,517,516,510,508,506,478,456, - 455,454,429,427,425,424,423,1,0, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, + 458,454,429,427,425,424,423,1,0, 427,425,424,423,0,39,40,41,45,46,47,49, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478, - 455,454,429,425,423,1,0, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, + 454,429,425,423,1,0, 688,687,686,685,684,0, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,3,131,441,535, -454,0,88, -454,0,88, -454,0,88, -454,0,88, -454,0,88, -454,0,88, -454,0,88, -454,0,88, -454,0,88, -454,0,88, -454,0,88, -543,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, - 504,503,502,501,500,499,498,497,496,495,494,493,491,454,425,423,1,0,196, - 198,199,200,201, -543,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, - 504,503,502,501,500,499,498,497,496,495,494,493,491,454,425,423,1,0,196, - 198,199,200,201, -543,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, - 499,498,497,496,495,494,493,491,454,427,425,424,423,1,0,194,195, -543,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, - 499,498,497,496,495,494,493,491,454,427,425,424,423,1,0,194,195, -543,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, - 499,498,497,496,495,494,493,491,454,427,425,424,423,1,0,194,195, -543,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, - 499,498,497,496,495,494,493,491,454,427,425,424,423,1,0,194,195, -543,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, - 497,496,495,494,493,491,454,427,425,424,423,1,0,190,191,192,193, -543,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, - 497,496,495,494,493,491,454,427,425,424,423,1,0,190,191,192,193, -543,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494, - 493,491,454,427,425,424,423,1,0,188,189, -543,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494, - 493,491,454,427,425,424,423,1,0,188,189, -543,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494,493,491, - 454,427,425,424,423,1,0,186,187, -543,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494,493,491, - 454,427,425,424,423,1,0,186,187, +427,425,424,423,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,3,133,442,536, +458,0,92, +458,0,92, +458,0,92, +458,0,92, +458,0,92, +458,0,92, +458,0,92, +458,0,92, +458,0,92, +458,0,92, +458,0,92, +544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, + 505,504,503,502,501,500,499,498,497,496,495,493,458,432,425,423,1,0,197, + 199,200,201,202, +544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, + 505,504,503,502,501,500,499,498,497,496,495,493,458,432,425,423,1,0,197, + 199,200,201,202, +544,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, + 500,499,498,497,496,495,493,458,432,427,425,424,423,1,0,195,196, +544,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, + 500,499,498,497,496,495,493,458,432,427,425,424,423,1,0,195,196, +544,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, + 500,499,498,497,496,495,493,458,432,427,425,424,423,1,0,195,196, +544,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, + 500,499,498,497,496,495,493,458,432,427,425,424,423,1,0,195,196, +544,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499, + 498,497,496,495,493,458,432,427,425,424,423,1,0,191,192,193,194, +544,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499, + 498,497,496,495,493,458,432,427,425,424,423,1,0,191,192,193,194, +544,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495, + 493,458,432,427,425,424,423,1,0,189,190, +544,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495, + 493,458,432,427,425,424,423,1,0,189,190, +544,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,493,458, + 432,427,425,424,423,1,0,187,188, +544,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,493,458, + 432,427,425,424,423,1,0,187,188, 427,425,424,423,0,39,40,41,45,46,47,49, 427,425,424,423,0,39,40,41,45,46,47,49, 427,425,424,423,0,39,40,41,45,46,47,49, -539,240,239,238,237,236,235,234,233,1,0,51,52, +540,241,240,239,238,237,236,235,234,1,0,51,52, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,679,525,523,520,519,518,517,516,510,508,506,478, - 455,454,429,425,423,232,1,0, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,680,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, - 489,455,429,230,133,132,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,84,86,129,131,195,197,202,203,204,205,206,207,208,209,210,211, - 212,213,214,215,216,217,218,434,441,483,490,537, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,536,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,489, - 455,429,230,133,132,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,84,86, - 129,131,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,441,490,537, -704,702,701,700,699,698,697,696,695,694,693,691,682,133,132,0,21,131,441, -704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,454, - 429,1,0,51,52,136, -454,1,0,51,52, -454,1,0,51,52, -539,240,239,238,237,236,235,234,233,0,4,241,593, -454,0,88, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, + 454,429,425,423,233,1,0, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,459,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,88,90,131,133,196,198,203,204,205,206,207,208,209,210,211,212, + 213,214,215,216,217,218,219,435,442,485,492,538, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, +427,425,424,423,0,39,40,41,45,46,47,49, +704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,458, + 429,1,0,51,52,138, +458,1,0,51,52, +458,1,0,51,52, +540,241,240,239,238,237,236,235,234,0,4,242,594, +458,0,92, }; -static unsigned const char ag_astt[27562] = { +static unsigned const char ag_astt[27766] = { 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,7,1,1,9,5,2,2,2,2,2, 2,2,2,2,2,2,2,2,1,8,8,8,8,8,2,2,2,2,2,1,1,7,1,0,1,1,1,1,1,1,1,1,1,1,1,5,5, - 5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,4,4,4,4, - 2,4,4,7,2,1,1,1,1,1,1,1,1,1,1,1,7,1,3,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,2,4, + 4,4,4,2,4,4,7,2,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,3,1,1,1,1,1,1,1,1,1,1,1,1,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,1,7,1,3,1,7,2,8,8,1,1,1,1,1,7,3,3,1,3,1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8, + 5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,7,2,8,8,1,1,1,1,1,7,3,3,1,3,1,1,1,1,1,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,5,5,8,8,8,8,8,8,8,1,7,1, - 1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,5, + 5,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,1,1,8,8,8,8, - 8,5,5,1,5,5,5,5,2,2,9,7,1,1,1,1,1,1,1,2,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 2,2,2,2,2,2,2,2,2,2,1,8,8,8,8,8,2,2,2,2,2,1,3,1,7,1,3,3,1,1,3,1,1,1,1,1,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, - 5,1,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, - 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, - 7,1,3,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1, - 1,1,2,7,1,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,7,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,1,7,1,1,1,1,1,2,2,7,1,1,1,1,1,1,5,5,5,5, + 1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,1,1,1,8,8,8,8,8,5,5,1,5,5,5,5,2,2,9,7,1,1,1,1,1,1,1,2,1,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,8,8,8,8,8,2,2,2,2,2,1,3,1,7, + 1,3,3,1,1,3,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,1,7,1,3,5,1,7,1,3,5,1,7,1,3,5,1,7,1,3,5,5,5,5,5,7,1,3,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,1,7,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 7,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,2,7,1,1,1,2,7,1,1,1,2,7,1, + 1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,7,1,1,1,1,1,1,1,1,7,1,1,1,1,1,2,2,7,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1, - 7,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,7,1,1,1,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 7,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,9,7,3,3,3,1,3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1,1,1,1,1,1, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,9,7,3,3,3,1,3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,8,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,1,1,1,8,8,8,8,8,8,8,1,1,1,1,1,2,2,7,1,1,1,1,1,3,3,1,3,1,1, - 1,1,1,2,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,1,1,8,8,8, + 8,8,1,8,8,1,1,1,1,1,2,2,7,1,1,1,1,1,3,3,1,3,1,1,1,1,1,1,2,1,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3, - 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5, - 5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5, - 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, - 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 1,1,1,1,1,1,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5, + 5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5, + 5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, - 1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1, - 3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3, - 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5, - 5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5, - 5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5, - 5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5, - 5,7,1,3,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1, - 1,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, @@ -4122,6 +4136,18 @@ static unsigned const char ag_astt[27562] = { 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5, + 5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5, + 5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3, + 8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, @@ -4165,28 +4191,28 @@ static unsigned const char ag_astt[27562] = { 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3, 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3,5, - 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1, - 3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5, - 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1, - 3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, - 7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, - 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, - 5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, - 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, - 1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, + 5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,1, + 7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, @@ -4237,179 +4263,155 @@ static unsigned const char ag_astt[27562] = { 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, - 1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8, - 8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1, - 7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, - 8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, - 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, - 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, - 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,5,2,2,2,2,2,2,2,2,2,2,2,5, - 2,5,5,2,2,2,2,2,5,2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 2,5,5,5,5,1,7,1,3,2,5,5,5,5,5,1,7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,1,4,4,4,4,4,4,4,7,1,4,4,4,4,1,7,1,1,5,1,2,2,2,2,2,2,2,2,2,2,2,1, - 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, - 1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 7,2,2,1,2,2,2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,2, - 2,1,1,2,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,2,1,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5, - 5,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1, + 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, + 1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8, + 8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, + 1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, + 8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, + 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, + 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8, + 8,8,8,8,8,8,8,8,1,7,1,1,5,2,2,2,2,2,2,2,2,2,2,2,5,2,5,5,2,2,2,2,2,5,2,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,2,5,5,5,5,1,7,1,3,2,5,5, + 5,5,5,1,7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,4,4,4,4,4,4,4,4, + 4,7,1,4,4,4,4,1,7,1,1,5,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,2, + 1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,2,1,2,2,1,1,2,2,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,1,1,2,8,8,8,8,1,7, + 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,5,7,1,3,1,7, + 1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1, 2,1,1,1,8,8,8,8,1,7,1,1,2,2,2,2,2,7,2,2,2,2,7,2,2,7,4,4,4,4,4,4,4,2,2,2,2, 4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4,4,4,7,4,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,7,2,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,7,1,10,10,10,10,10,5,2,10,10,10,10,10,10,10,10,10,7,10,10,10,10,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 7,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,7,10,10,10,10,10,10,10,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,9,2,2,1,1,2,10,10,10,10,10,9,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4,2,2,4, - 7,2,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5, - 5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5, + 2,2,2,7,1,10,10,10,10,10,5,2,10,10,10,10,10,10,10,10,10,7,10,10,10,10,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7, + 10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,7,10,10,10,10,10,10,10,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,9,2,2,1,1,2,10,10,10,10,10,9,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4,2,2,4,7, + 2,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5, + 7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,1,7,1,1,8,1,7,1,1,8,1,7, - 1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1, - 8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,2,2,2,2,2,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, - 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1, + 8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1, + 7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,2,2,2,2,2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, 2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2, - 1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,1,1,1, + 1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, + 2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,1,1,1,1,1,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,1,5, 1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1, - 1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7, - 1,3,1,1,5,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1, - 3,1,1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1, - 5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,5,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,5,5,5,5, - 5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3, - 8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,10,10,1,10,10,10,10,10,10, - 10,10,10,10,10,10,2,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10,7,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, - 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, + 5,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1, + 1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,5,1,1,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,5,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,5,5,5,5,5,7,1,3, + 8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,8,8,8,8, + 1,7,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,10,10,1,10,10,10,10,10,10,10,10,10, + 10,10,10,2,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,7,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,7,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, - 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, + 5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,7,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,9,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,7,3,1,7,3,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,2,2,1,2,2,2,2,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,1,1,2,8,8,8,8,1, - 7,1,1,1,1,1,1,1,1,7,1,3,3,1,3,1,1,1,2,2,2,1,1,1,2,2,2,2,2,7,2,2,2,2,3,2,2, - 2,2,2,2,2,2,2,2,2,7,3,2,1,2,2,2,2,2,2,2,7,3,2,2,2,1,2,2,2,2,7,2,1,7,1,1,7, - 1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2, - 2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, - 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, - 2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1, - 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, - 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, - 1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, - 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, - 1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, - 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1, - 1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2, - 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, - 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, - 1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, - 1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, - 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,5,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1, + 7,3,1,7,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,2,2,1,2,2,1,1, + 2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,1,1,2,8,8,8, + 8,1,7,1,1,1,1,1,1,1,1,7,1,3,3,1,3,1,1,1,2,2,2,1,1,1,2,2,2,2,2,7,2,2,2,2,3, + 2,2,2,2,2,2,2,2,2,2,2,7,3,2,1,2,2,2,2,2,2,2,7,3,2,2,2,1,2,2,2,2,7,2,1,7,1, + 1,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1, 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1, @@ -4489,241 +4491,283 @@ static unsigned const char ag_astt[27562] = { 1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2, - 1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,1,1,2,2,2,2,2, - 7,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2,1,2, - 2,2,2,2,2,2,7,2,2,2,2,1,2,2,2,2,2,2,2,7,2,2,2,2,1,2,1,1,1,2,2,2,2,2,7,2,2, - 2,2,2,2,2,2,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2, - 2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1, - 2,2,2,2,2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2, - 2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2, - 7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1, - 1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,1,1,1,1,1,1,2,9,7,2,1,1,2,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, + 1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1, + 1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, + 2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, + 2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1, + 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2, + 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, + 1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, + 1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, + 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, + 2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, + 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2, + 1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1, + 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,2,2,2,2,2,7,2,2,2,2,2, + 2,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,1,1,2,2,2, + 2,2,7,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2, + 1,2,2,2,2,2,2,2,7,2,2,2,2,1,2,2,2,2,2,2,2,7,2,2,2,2,1,2,1,1,1,2,2,2,2,2,7, + 2,2,2,2,2,2,2,2,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,2,1, + 2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2, + 2,1,2,2,2,2,2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2, + 7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2, + 2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2, + 1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,2,1,1,1,1,1,1,2,9,7,2,1,1,2,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,7,2,1,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,1,7,1,3,1,2,7,2,1,1,2, - 1,1,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2,2,4,7,2,1,1,5,1,7,1,3,2,7,1,1, - 1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2, - 2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, - 1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, + 1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2, + 1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,7,2,1,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,1,7,1,3,1,2,7,2,1, + 1,2,1,1,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2,2,4,7,2,1,1,2,7,1,1,1,2,7, + 2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2, + 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,7,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, + 1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1, - 2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1, 1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2, - 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2, - 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, + 2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2, + 1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2, + 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2, + 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5, - 5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,1,1,1,1,7,3,3,1,3,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,2,1,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 1,1,1,1,7,2,2,1,2,1,1,1,2,1,2,2,2,2,2,1,1,1,1,2,3,7,1,1,1,1,1,7,2,2,1,2,1, - 1,1,1,1,1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,7,2,1,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,7,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,7,1,1,7,1,1,7,1,1, - 7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, - 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, - 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 2,2,7,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, + 5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,1,1,1,1,7,3,3,1,3,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,2, + 2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,1,1,1,1,7,2,2,1,2,1,1,1,2,1,2,2,2,2,2,1,1,1,1,2,3,7,1,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, + 1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1, + 2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,7,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1, + 7,1,1,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,7,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, + 3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, - 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7, - 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1, - 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, - 1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1, - 1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,7,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,7, - 1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,10,10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10,10,10,5,5,5,7,1,3,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1, - 8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1, - 1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5, + 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1, + 1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2, + 1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,3,2,7,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,7,1,3,8,8,8,8, + 1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,3,3,1,3,1,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7, - 1,1,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, - 5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, + 1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,3, + 3,1,3,1,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, + 5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,8,1,7,1,1,2,1,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1, - 2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,7,1,3,1,1,7,2,1,2,2,2,2,2,2,2,2,2,7,9,2,2, - 1,1,2,10,10,10,10,10,9,4,4,4,4,2,2,4,7,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,5,5, + 5,5,5,5,7,1,3,8,1,7,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,7,1,3, + 1,1,7,2,1,2,2,2,2,2,2,2,2,2,7,9,2,2,1,1,2,10,10,10,10,10,9,4,4,4,4,2,2,4,7, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2, - 1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2, - 1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,1,4,4,4,4, - 4,7,1,1,4,4,4,4,4,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,7,1,1,1, - 1,1,7,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,7,2,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2, - 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, - 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1, + 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,7,1,1,4,4,4, + 4,4,7,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,2,1, + 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,1,1,1,1,1,1,1,1,1,7,1,1,1,1,1,7,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1, + 1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2,2, + 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, + 2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, + 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1, + 1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, + 2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, + 2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2, + 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, + 1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1, + 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2, + 1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, 1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2, - 1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1, - 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, + 1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2, + 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, + 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,1,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1, + 7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,8,8,8,8,1, + 7,1,1,8,8,8,8,1,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, - 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, + 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, - 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1,1,2,2, - 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, - 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, - 2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, - 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, - 1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, - 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1, - 1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,2,1,1,1,1,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,2, - 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, - 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, - 1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, - 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, - 2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1, - 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1, - 2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, - 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, - 2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1, - 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,1,7,1,1,1,1,1,1,7,2, - 2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,8,8,8,8,1,7,1, - 1,8,8,8,8,1,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, - 1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, - 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,5,5,5,5,5,5,5,5, + 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,1,7,1,5,5,5,5,5,1,7,1,3,2,1,2,2, + 5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,1,7,1,5,5,5,5,5,1,7,1,3,2,1,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,7,2,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,1,7,1,1,1,4,4,4,4,4,7,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1, @@ -4731,41 +4775,42 @@ static unsigned const char ag_astt[27562] = { 5,5,5,5,5,5,5,5,5,5,5,7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,7,1,1,1,1,7,2,2,1,2,1,1,1,4,4, 4,4,4,4,4,4,2,2,2,2,4,4,4,4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,7,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,7,2,1,7,2, - 1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,3,4,1,1,1,1,1,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,4,1,1,1,1, - 1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1, - 4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4, - 1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1, - 1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,1, - 1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,4,1,1,1,1, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,4,1,1,4,4,4, + 4,4,4,7,2,2,2,2,2,7,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1, + 1,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,3,4,1,1, + 1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1, + 1,1,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,7,1,1,1,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 7,1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1, + 1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1, + 1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1, - 1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,8,8, - 8,8,8,8,8,8,8,1,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, - 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2, - 1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,5,2,1,7,1,3,2,5,5,7,1,3,8,1,7,1,1,2,2,2,2,2,2,2,2,2, - 7,2,2,1,1,7,2 + 4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2, + 1,2,1,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2,2,1, + 2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, + 2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1, + 1,1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,5,2,1,7,1,3,2,5, + 5,7,1,3,8,1,7,1,1,2,2,2,2,2,2,2,2,2,7,2,2,1,1,7,2 }; static const unsigned short ag_pstt[] = { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,1,2, 18,20, -127,127,127,127,127,127,127,127,127,127,127,127,127,3,8,8,8,8,8,162,161,160, - 126,125,7,10,2,9,0,11,11,11,10,8,11,5,5,4,6,4, -19,19,19,19,19,19,19,19,19,19,19,1,3,1,888, -128,128,128,128,128,128,128,128,128,128,128,128,129,129,129,129,129,128,159, - 128,159,159,159,159,158,159,159,4,129, -12,13,14,15,16,17,18,19,20,21,22,5,33,39,32,31,30,29,28,27,26,25,24,23, +131,131,131,131,131,131,131,131,131,131,131,131,131,3,8,8,8,8,8,166,165,164, + 130,129,7,10,2,9,0,11,11,11,10,8,11,5,5,4,6,4, +19,19,19,19,19,19,19,19,19,19,19,19,19,1,3,1,887, +132,132,132,132,132,132,132,132,132,132,132,132,133,133,133,133,133,132,163, + 163,132,163,163,163,163,162,163,163,4,133, +12,13,14,15,16,17,18,19,20,21,22,23,24,5,37,40,36,35,34,33,32,31,30,29,28, + 27,26,25, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, @@ -4774,1827 +4819,1849 @@ static const unsigned short ag_pstt[] = { 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,1,6,1,879, -34,7,37, -36,36,35,37,38,39,34,8,24,24,42,24,41,40,40,36,36, -43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, - 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, - 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, - 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, - 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, - 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, - 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, - 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,19,19,43,43,43,43,43,43, - 43,1,9,1,43, -127,127,127,127,127,127,127,127,127,127,127,127,127,111,112,113,114,115,116, - 117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134, - 62,63,64,65,66,67,135,136,137,138,139,140,68,69,70,71,72,141,142,143,73, - 74,75,76,77,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158, - 107,59,60,61,165,166,167,168,169,170,171,172,173,174,175,176,177,178, - 179,180,159,160,161,162,163,164,78,79,80,81,82,83,45,46,47,84,85,86,87, - 88,89,90,91,92,48,49,93,94,95,96,97,98,99,100,50,51,52,101,102,53,54, - 103,104,105,106,55,56,57,58,265,265,265,265,265,265,265,265,265,265,265, - 265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265, - 265,265,15,16,19,265,265,265,265,265,20,20,35,20,20,20,20,126,125,18,10, - 261,262,263,260,266,265,265,35,264,101,102,266,44,259,196,260,260,260, - 260,260,260,260,260,260,260,323,323,323,323,323,324,325,326,327,330,330, - 330,331,332,336,336,336,336,337,338,339,340,341,342,343,344,347,347,347, - 348,349,350,351,352,353,354,355,356,360,360,360,360,361,362,363,364,365, - 366,242,241,240,239,238,237,258,257,256,255,254,253,252,251,250,249,248, - 247,246,245,244,243,184,110,183,109,182,108,181,236,235,234,233,232,231, - 230,229,228,227,226,225,224,223,222,221,221,221,221,221,221,220,219,218, - 217,217,217,217,217,217,216,215,214,213,212,211,210,210,210,210,209,209, - 209,209,208,207,206,205,204,203,202,201,200,199,198,197,195,194,193,192, - 191,190,189,188,187,186,185,259, -127,127,127,127,127,127,127,127,127,127,127,127,127,3,8,8,8,8,8,162,161,160, - 126,125,7,4,10,11,9,3,3,10,8,3,5,5,4,6,4, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,12,1,904, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,13,1,903, -19,1,14,1,902, -19,19,19,19,19,15,1,901, -19,19,19,19,19,16,1,900, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,17,1,899, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,18,1,898, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,19,1,897, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,20,1,896, -19,19,19,19,19,1,21,1,890, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,22,1,883, -127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,23,261,267,259, - 259, -127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,24,268,259,259, -136,25,271,269,270, -272,272,272,272,1,26,1,272, -273,273,273,273,1,27,1,273, -127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,28,274,259,259, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,29,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,329,331,216,317,303,259,330,318,322,321,320,319,215,322,312, - 311,310,309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,30,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,329,332,216,317,303,259,330,318,322,321,320,319,215,322,312, - 311,310,309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,31,333,259,259, -334,336,338,340,342,32,343,341,339,337,335, -154,136,33,347,269,346,344,270,345, + 19,19,19,1,6,1,877, +38,7,38, +40,40,39,41,42,43,38,8,24,24,46,24,45,44,44,40,40, +47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,19,19,47,47,47,47, + 47,47,47,1,9,1,47, +131,131,131,131,131,131,131,131,131,131,131,131,131,115,116,117,118,119,120, + 121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138, + 66,67,68,69,70,71,139,140,141,142,143,144,72,73,74,75,76,145,146,147,77, + 78,79,80,81,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162, + 111,63,64,65,169,170,171,172,173,174,175,176,177,178,179,180,181,182, + 183,184,163,164,165,166,167,168,82,83,84,85,86,87,49,50,51,88,89,90,91, + 92,93,94,95,96,52,53,97,98,99,100,101,102,103,104,54,55,56,105,106,57, + 58,107,108,109,110,59,60,61,62,269,269,269,269,269,269,269,269,269,269, + 269,269,269,269,269,269,269,269,269,269,269,269,269,269,269,269,269,269, + 269,269,269,269,17,18,21,269,269,269,269,269,20,20,39,20,20,20,20,130, + 129,18,10,265,266,267,264,270,269,269,36,268,105,106,270,48,263,200,264, + 264,264,264,264,264,264,264,264,264,327,327,327,327,327,328,329,330,331, + 334,334,334,335,336,340,340,340,340,341,342,343,344,345,346,347,348,351, + 351,351,352,353,354,355,356,357,358,359,360,364,364,364,364,365,366,367, + 368,369,370,246,245,244,243,242,241,262,261,260,259,258,257,256,255,254, + 253,252,251,250,249,248,247,188,114,187,113,186,112,185,240,239,238,237, + 236,235,234,233,232,231,230,229,228,227,226,225,225,225,225,225,225,224, + 223,222,221,221,221,221,221,221,220,219,218,217,216,215,214,214,214,214, + 213,213,213,213,212,211,210,209,208,207,206,205,204,203,202,201,199,198, + 197,196,195,194,193,192,191,190,189,263, +131,131,131,131,131,131,131,131,131,131,131,131,131,3,8,8,8,8,8,166,165,164, + 130,129,7,4,10,11,9,3,3,10,8,3,5,5,4,6,4, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,12,1,906, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,13,1,905, +19,1,14,1,904, +19,1,15,1,902, +19,1,16,1,901, +19,19,19,19,19,17,1,900, +19,19,19,19,19,18,1,899, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,19,1,898, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,20,1,897, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,21,1,896, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,22,1,895, +19,19,19,19,19,1,23,1,889, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,24,1,882, +131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,25,265,271,263, + 263, +131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,26,272,263,263, +140,27,275,273,274, +140,28,276,273,274, +140,29,277,273,274, +278,278,278,278,1,30,1,278, +279,279,279,279,1,31,1,279, +131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,32,280,263,263, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,33,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,335,337,220,323,309,263,336,324,328,327,326,325,219,328,318, + 317,316,315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,34,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,335,338,220,323,309,263,336,324,328,327,326,325,219,328,318, + 317,316,315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,35,339,263,263, +340,342,344,346,348,36,349,347,345,343,341, +158,140,37,353,273,352,350,274,351, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,34,1,874, + 19,19,19,19,19,19,38,1,872, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,35,1,880, -348,22,36,349,349,349, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,39,1,878, +354,24,40,355,355,355, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,37,1,878, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,41,1,876, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,38, - 1,876, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,42,1, + 874, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,39,1,875, -350,352,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370, - 371,372,373,380,383,384,385,386,314,316,382,374,378,375,377,381,353,351, - 376,301,379,35,37,387,38,34,15,40,16,15,15,40,13,40,15,15,15,15,15,15, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,43,1,873, +356,358,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376, + 377,378,379,386,389,390,391,320,322,388,380,384,381,383,387,359,357,307, + 385,382,39,41,392,42,38,15,44,16,15,15,44,13,44,15,15,15,15,15,15,15,15, 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, - 15,15,15,15,15,15,15,15,15,15,15, -350,352,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370, - 371,372,373,380,383,384,385,386,314,316,382,374,378,375,377,381,353,351, - 376,301,379,35,38,389,388,41,388,389,388,388,388,388,388,388,388,388, - 388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388, - 388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388, -350,352,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370, - 371,372,373,380,383,384,385,386,314,316,382,374,378,375,377,381,353,351, - 376,301,379,35,38,390,388,42,388,390,388,388,388,388,388,388,388,388, - 388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388, - 388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388, -127,127,127,127,127,127,127,127,127,127,127,127,127,111,112,113,114,115,116, - 117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134, - 62,63,64,65,66,67,135,136,137,138,139,140,68,69,70,71,72,141,142,143,73, - 74,75,76,77,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158, - 107,59,60,61,165,166,167,168,169,170,171,172,173,174,175,176,177,178, - 179,180,159,160,161,162,163,164,78,79,80,81,82,83,45,46,47,84,85,86,87, - 88,89,90,91,92,48,49,93,94,95,96,97,98,99,100,50,51,52,101,102,53,54, - 103,104,105,106,55,56,57,58,391,391,391,391,391,391,391,391,391,391,391, - 391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, - 391,391,15,16,19,391,391,391,391,391,391,391,35,37,38,39,34,126,125,43, - 261,262,263,260,392,23,23,42,23,41,40,40,391,391,36,264,101,102,392,44, - 259,196,260,260,260,260,260,260,260,260,260,260,323,323,323,323,323,324, - 325,326,327,330,330,330,331,332,336,336,336,336,337,338,339,340,341,342, - 343,344,347,347,347,348,349,350,351,352,353,354,355,356,360,360,360,360, - 361,362,363,364,365,366,242,241,240,239,238,237,258,257,256,255,254,253, - 252,251,250,249,248,247,246,245,244,243,184,110,183,109,182,108,181,236, - 235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,221,221,221, - 221,221,220,219,218,217,217,217,217,217,217,216,215,214,213,212,211,210, - 210,210,210,209,209,209,209,208,207,206,205,204,203,202,201,200,199,198, - 197,195,194,193,192,191,190,189,188,187,186,185,259, -393,393,393,393,393,393,1,44,1,393, -19,19,19,19,19,19,45,1,1031, -19,19,19,19,19,19,46,1,1030, -19,19,19,19,19,19,47,1,1029, -19,19,19,19,19,19,48,1,1019, -19,19,19,19,19,19,49,1,1018, -19,19,19,19,19,19,50,1,1009, -19,19,19,19,19,19,51,1,1008, -19,19,19,19,19,19,52,1,1007, -19,19,19,19,19,19,53,1,1004, -19,19,19,19,19,19,54,1,1003, -19,19,19,19,19,19,55,1,998, -19,19,19,19,19,19,56,1,997, -19,19,19,19,19,19,57,1,996, -19,19,19,19,19,19,58,1,995, -19,19,19,19,19,19,19,19,19,19,59,1,1064, -19,19,19,19,19,19,19,19,19,19,60,1,1063, -19,19,19,19,19,19,19,19,61,1,1062, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,62,1,1105, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,63,1,1104, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,64,1,1103, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,65,1,1102, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,66,1,1101, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,67,1,1100, + 15,15,15,15,15,15,15,15, +356,358,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376, + 377,378,379,386,389,390,391,320,322,388,380,384,381,383,387,359,357,307, + 385,382,39,42,394,393,45,393,394,393,393,393,393,393,393,393,393,393, + 393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393, + 393,393,393,393,393,393,393,393,393,393,393,393,393,393, +356,358,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376, + 377,378,379,386,389,390,391,320,322,388,380,384,381,383,387,359,357,307, + 385,382,39,42,395,393,46,393,395,393,393,393,393,393,393,393,393,393, + 393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393, + 393,393,393,393,393,393,393,393,393,393,393,393,393,393, +131,131,131,131,131,131,131,131,131,131,131,131,131,115,116,117,118,119,120, + 121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138, + 66,67,68,69,70,71,139,140,141,142,143,144,72,73,74,75,76,145,146,147,77, + 78,79,80,81,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162, + 111,63,64,65,169,170,171,172,173,174,175,176,177,178,179,180,181,182, + 183,184,163,164,165,166,167,168,82,83,84,85,86,87,49,50,51,88,89,90,91, + 92,93,94,95,96,52,53,97,98,99,100,101,102,103,104,54,55,56,105,106,57, + 58,107,108,109,110,59,60,61,62,398,398,398,398,398,398,398,398,398,398, + 398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398, + 398,398,398,398,17,18,21,398,398,398,398,398,396,398,398,39,41,42,43,38, + 130,129,47,265,266,267,264,399,23,23,46,23,45,44,44,398,398,397,37,268, + 105,106,399,48,263,200,264,264,264,264,264,264,264,264,264,264,327,327, + 327,327,327,328,329,330,331,334,334,334,335,336,340,340,340,340,341,342, + 343,344,345,346,347,348,351,351,351,352,353,354,355,356,357,358,359,360, + 364,364,364,364,365,366,367,368,369,370,246,245,244,243,242,241,262,261, + 260,259,258,257,256,255,254,253,252,251,250,249,248,247,188,114,187,113, + 186,112,185,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226, + 225,225,225,225,225,225,224,223,222,221,221,221,221,221,221,220,219,218, + 217,216,215,214,214,214,214,213,213,213,213,212,211,210,209,208,207,206, + 205,204,203,202,201,199,198,197,196,195,194,193,192,191,190,189,263, +400,400,400,400,400,400,1,48,1,400, +19,19,19,19,19,19,49,1,1030, +19,19,19,19,19,19,50,1,1029, +19,19,19,19,19,19,51,1,1028, +19,19,19,19,19,19,52,1,1018, +19,19,19,19,19,19,53,1,1017, +19,19,19,19,19,19,54,1,1008, +19,19,19,19,19,19,55,1,1007, +19,19,19,19,19,19,56,1,1006, +19,19,19,19,19,19,57,1,1003, +19,19,19,19,19,19,58,1,1002, +19,19,19,19,19,19,59,1,997, +19,19,19,19,19,19,60,1,996, +19,19,19,19,19,19,61,1,995, +19,19,19,19,19,19,62,1,994, +19,19,19,19,19,19,19,19,19,19,63,1,1063, +19,19,19,19,19,19,19,19,19,19,64,1,1062, +19,19,19,19,19,19,19,19,65,1,1061, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,66,1,1104, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,67,1,1103, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,68,1,1102, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,69,1,1101, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,70,1,1100, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,71,1,1099, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,68,1,1093, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,72,1,1092, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,69,1,1092, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,73,1,1091, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,70,1,1091, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,74,1,1090, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,71,1,1090, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,75,1,1089, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,72,1,1089, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,76,1,1088, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,73,1,1085, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,77,1,1084, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,74,1,1084, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,78,1,1083, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,75,1,1083, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,79,1,1082, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,76,1,1082, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,80,1,1081, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,77,1,1081, -19,19,19,19,19,19,78,1,1037, -19,19,19,19,19,19,79,1,1036, -19,19,19,19,19,19,80,1,1035, -19,19,19,19,19,19,81,1,1034, -19,19,19,19,19,19,82,1,1033, -19,19,19,19,19,19,83,1,1032, -19,19,19,19,19,19,84,1,1028, -19,19,19,19,19,19,85,1,1027, -19,19,19,19,19,19,86,1,1026, -19,19,19,19,19,19,87,1,1025, -19,19,19,19,19,19,88,1,1024, -19,19,19,19,19,19,89,1,1023, -19,19,19,19,19,19,90,1,1022, -19,19,19,19,19,19,91,1,1021, -19,19,19,19,19,19,92,1,1020, -19,19,19,19,19,19,93,1,1017, -19,19,19,19,19,19,94,1,1016, -19,19,19,19,19,19,95,1,1015, -19,19,19,19,19,19,96,1,1014, -19,19,19,19,19,19,97,1,1013, -19,19,19,19,19,19,98,1,1012, -19,19,19,19,19,19,99,1,1011, -19,19,19,19,19,19,100,1,1010, -19,19,19,19,19,19,101,1,1006, -19,19,19,19,19,19,102,1,1005, -19,19,19,19,19,19,103,1,1002, -19,19,19,19,19,19,104,1,1001, -19,19,19,19,19,19,105,1,1000, -19,19,19,19,19,19,106,1,999, -19,19,19,19,19,107,1,1065, -394,394,394,394,394,394,394,394,394,1,108,1,394, -395,395,395,395,395,395,395,395,395,1,109,1,395, -396,396,396,396,396,396,396,1,110,1,396, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,81,1,1080, +19,19,19,19,19,19,82,1,1036, +19,19,19,19,19,19,83,1,1035, +19,19,19,19,19,19,84,1,1034, +19,19,19,19,19,19,85,1,1033, +19,19,19,19,19,19,86,1,1032, +19,19,19,19,19,19,87,1,1031, +19,19,19,19,19,19,88,1,1027, +19,19,19,19,19,19,89,1,1026, +19,19,19,19,19,19,90,1,1025, +19,19,19,19,19,19,91,1,1024, +19,19,19,19,19,19,92,1,1023, +19,19,19,19,19,19,93,1,1022, +19,19,19,19,19,19,94,1,1021, +19,19,19,19,19,19,95,1,1020, +19,19,19,19,19,19,96,1,1019, +19,19,19,19,19,19,97,1,1016, +19,19,19,19,19,19,98,1,1015, +19,19,19,19,19,19,99,1,1014, +19,19,19,19,19,19,100,1,1013, +19,19,19,19,19,19,101,1,1012, +19,19,19,19,19,19,102,1,1011, +19,19,19,19,19,19,103,1,1010, +19,19,19,19,19,19,104,1,1009, +19,19,19,19,19,19,105,1,1005, +19,19,19,19,19,19,106,1,1004, +19,19,19,19,19,19,107,1,1001, +19,19,19,19,19,19,108,1,1000, +19,19,19,19,19,19,109,1,999, +19,19,19,19,19,19,110,1,998, +19,19,19,19,19,111,1,1064, +401,401,401,401,401,401,401,401,401,1,112,1,401, +402,402,402,402,402,402,402,402,402,1,113,1,402, +403,403,403,403,403,403,403,1,114,1,403, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,111,1,1129, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,115,1,1128, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,112,1,1128, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,116,1,1127, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,113,1,1127, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,117,1,1126, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,114,1,1126, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,118,1,1125, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,115,1,1125, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,119,1,1124, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,116,1,1124, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,120,1,1123, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,117,1,1123, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,121,1,1122, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,118,1,1122, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,122,1,1121, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,119,1,1121, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,123,1,1120, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,120,1,1120, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,124,1,1119, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,121,1,1119, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,125,1,1118, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,122,1,1118, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,126,1,1117, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,123,1,1117, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,127,1,1116, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,124,1,1116, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,128,1,1115, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,125,1,1115, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,129,1,1114, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,126,1,1114, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,130,1,1113, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,127,1,1113, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,131,1,1112, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,128,1,1112, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,132,1,1111, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,129,1,1111, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,133,1,1110, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,130,1,1110, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,134,1,1109, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,131,1,1109, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,135,1,1108, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,132,1,1108, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,136,1,1107, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,133,1,1107, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,137,1,1106, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,134,1,1106, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,138,1,1105, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,135,1,1099, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,139,1,1098, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,136,1,1098, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,140,1,1097, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,137,1,1097, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,141,1,1096, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,138,1,1096, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,142,1,1095, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,139,1,1095, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,143,1,1094, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,140,1,1094, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,144,1,1093, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,141,1,1088, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,145,1,1087, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,142,1,1087, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,146,1,1086, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,143,1,1086, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,147,1,1085, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,144,1,1080, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,148,1,1079, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,145,1,1079, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,149,1,1078, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,146,1,1078, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,150,1,1077, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,147,1,1077, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,151,1,1076, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,148,1,1076, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,152,1,1075, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,149,1,1075, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,153,1,1074, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,150,1,1074, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,154,1,1073, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,151,1,1073, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,155,1,1072, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,152,1,1072, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,156,1,1071, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,153,1,1071, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,157,1,1070, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,154,1,1070, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,158,1,1069, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,155,1,1069, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,159,1,1068, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,156,1,1068, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,160,1,1067, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,157,1,1067, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,161,1,1066, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,158,1,1066, -19,19,19,19,19,19,19,19,19,159,1,1043, -19,19,19,19,19,19,19,19,19,160,1,1042, -19,19,19,19,19,19,19,19,19,161,1,1041, -19,19,19,19,19,19,19,19,19,162,1,1040, -19,19,19,19,19,163,1,1039, -19,19,19,19,19,164,1,1038, -19,19,19,19,19,19,19,19,165,1,1061, -19,19,19,19,19,19,19,19,166,1,1060, -19,19,19,19,19,19,19,19,167,1,1059, -19,19,19,19,19,19,19,19,19,19,168,1,1057, -19,19,19,19,19,19,19,19,19,19,169,1,1056, -19,19,19,19,19,19,19,19,19,19,170,1,1055, -19,19,19,19,19,19,19,19,19,19,171,1,1054, -19,19,19,19,19,19,19,19,19,19,172,1,1053, -19,19,19,19,19,19,19,19,19,19,173,1,1052, -19,19,19,19,19,19,19,19,19,19,174,1,1051, -19,19,19,19,19,19,19,19,19,19,175,1,1050, -19,19,19,19,19,19,19,19,19,19,176,1,1049, -19,19,19,19,19,19,19,19,19,19,177,1,1048, -19,19,19,19,19,19,19,19,19,19,178,1,1047, -19,19,19,19,19,19,19,19,19,19,179,1,1046, -19,19,19,19,19,19,19,19,19,19,180,1,1045, -397,397,397,397,1,181,1,397, -398,1,182,1,398, -399,1,183,1,399, -400,1,184,1,400, -401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, - 401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, - 401,401,401,401,401,1,185,1,401, -402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, - 402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, - 402,402,402,402,402,1,186,1,402, -403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403, - 403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403, - 403,403,403,403,403,1,187,1,403, -404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, - 404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, - 404,404,404,404,404,1,188,1,404, -405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405, - 405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405, - 405,405,405,405,405,1,189,1,405, -406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406, - 406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406, - 406,406,406,406,406,1,190,1,406, -407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407, - 407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407, - 407,407,407,407,407,1,191,1,407, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,162,1,1065, +19,19,19,19,19,19,19,19,19,163,1,1042, +19,19,19,19,19,19,19,19,19,164,1,1041, +19,19,19,19,19,19,19,19,19,165,1,1040, +19,19,19,19,19,19,19,19,19,166,1,1039, +19,19,19,19,19,167,1,1038, +19,19,19,19,19,168,1,1037, +19,19,19,19,19,19,19,19,169,1,1060, +19,19,19,19,19,19,19,19,170,1,1059, +19,19,19,19,19,19,19,19,171,1,1058, +19,19,19,19,19,19,19,19,19,19,172,1,1056, +19,19,19,19,19,19,19,19,19,19,173,1,1055, +19,19,19,19,19,19,19,19,19,19,174,1,1054, +19,19,19,19,19,19,19,19,19,19,175,1,1053, +19,19,19,19,19,19,19,19,19,19,176,1,1052, +19,19,19,19,19,19,19,19,19,19,177,1,1051, +19,19,19,19,19,19,19,19,19,19,178,1,1050, +19,19,19,19,19,19,19,19,19,19,179,1,1049, +19,19,19,19,19,19,19,19,19,19,180,1,1048, +19,19,19,19,19,19,19,19,19,19,181,1,1047, +19,19,19,19,19,19,19,19,19,19,182,1,1046, +19,19,19,19,19,19,19,19,19,19,183,1,1045, +19,19,19,19,19,19,19,19,19,19,184,1,1044, +404,404,404,404,1,185,1,404, +405,1,186,1,405, +406,1,187,1,406, +407,1,188,1,407, 408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408, 408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408, - 408,408,408,408,408,1,192,1,408, + 408,408,408,408,408,1,189,1,408, 409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409, 409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409, - 409,409,409,409,409,1,193,1,409, + 409,409,409,409,409,1,190,1,409, 410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, 410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, - 410,410,410,410,410,1,194,1,410, + 410,410,410,410,410,1,191,1,410, 411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411, 411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411, - 411,411,411,411,411,1,195,1,411, + 411,411,411,411,411,1,192,1,411, 412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412, 412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412, - 412,412,412,412,412,1,196,1,412, + 412,412,412,412,412,1,193,1,412, 413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, 413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, - 413,413,413,413,413,1,197,1,413, + 413,413,413,413,413,1,194,1,413, 414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, 414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, - 414,414,414,414,414,1,198,1,414, + 414,414,414,414,414,1,195,1,414, 415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, 415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, - 415,415,415,415,415,1,199,1,415, + 415,415,415,415,415,1,196,1,415, 416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, 416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, - 416,416,416,416,416,1,200,1,416, + 416,416,416,416,416,1,197,1,416, 417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417, 417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417, - 417,417,417,417,417,1,201,1,417, + 417,417,417,417,417,1,198,1,417, 418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, 418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, - 418,418,418,418,418,1,202,1,418, + 418,418,418,418,418,1,199,1,418, 419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419, 419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419, - 419,419,419,419,419,1,203,1,419, + 419,419,419,419,419,1,200,1,419, 420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420, 420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420, - 420,420,420,420,420,1,204,1,420, + 420,420,420,420,420,1,201,1,420, 421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421, 421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421, - 421,421,421,421,421,1,205,1,421, + 421,421,421,421,421,1,202,1,421, 422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, 422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, - 422,422,422,422,422,1,206,1,422, + 422,422,422,422,422,1,203,1,422, 423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423, 423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423, - 423,423,423,423,423,1,207,1,423, + 423,423,423,423,423,1,204,1,423, 424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424, 424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424, - 424,424,424,424,424,1,208,1,424, + 424,424,424,424,424,1,205,1,424, 425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425, 425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425, - 425,425,425,425,425,1,209,1,425, + 425,425,425,425,425,1,206,1,425, 426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, 426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, - 426,426,426,426,426,1,210,1,426, + 426,426,426,426,426,1,207,1,426, 427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427, 427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427, - 427,427,427,427,427,1,211,1,427, + 427,427,427,427,427,1,208,1,427, 428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, 428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, - 428,428,428,428,428,1,212,1,428, + 428,428,428,428,428,1,209,1,428, 429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, 429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, - 429,429,429,429,429,1,213,1,429, + 429,429,429,429,429,1,210,1,429, 430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430, 430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430, - 430,430,430,430,430,1,214,1,430, + 430,430,430,430,430,1,211,1,430, 431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431, 431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431, - 431,431,431,431,431,1,215,1,431, + 431,431,431,431,431,1,212,1,431, 432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432, 432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432, - 432,432,432,432,432,1,216,1,432, + 432,432,432,432,432,1,213,1,432, 433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433, 433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433, - 433,433,433,433,433,1,217,1,433, + 433,433,433,433,433,1,214,1,433, 434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434, 434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434, - 434,434,434,434,434,1,218,1,434, + 434,434,434,434,434,1,215,1,434, 435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435, 435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435, - 435,435,435,435,435,1,219,1,435, + 435,435,435,435,435,1,216,1,435, 436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, 436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, - 436,436,436,436,436,1,220,1,436, + 436,436,436,436,436,1,217,1,436, 437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, 437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, - 437,437,437,437,437,1,221,1,437, + 437,437,437,437,437,1,218,1,437, 438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, 438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, - 438,438,438,438,438,1,222,1,438, + 438,438,438,438,438,1,219,1,438, 439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, 439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, - 439,439,439,439,439,1,223,1,439, + 439,439,439,439,439,1,220,1,439, 440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, 440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, - 440,440,440,440,440,1,224,1,440, + 440,440,440,440,440,1,221,1,440, 441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441, 441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441, - 441,441,441,441,441,1,225,1,441, + 441,441,441,441,441,1,222,1,441, 442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442, 442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442, - 442,442,442,442,442,1,226,1,442, + 442,442,442,442,442,1,223,1,442, 443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443, 443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443, - 443,443,443,443,443,1,227,1,443, + 443,443,443,443,443,1,224,1,443, 444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444, 444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444, - 444,444,444,444,444,1,228,1,444, + 444,444,444,444,444,1,225,1,444, 445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445, 445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445, - 445,445,445,445,445,1,229,1,445, + 445,445,445,445,445,1,226,1,445, 446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446, 446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446, - 446,446,446,446,446,1,230,1,446, + 446,446,446,446,446,1,227,1,446, 447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447, 447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447, - 447,447,447,447,447,1,231,1,447, + 447,447,447,447,447,1,228,1,447, 448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448, 448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448, - 448,448,448,448,448,1,232,1,448, + 448,448,448,448,448,1,229,1,448, 449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, 449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, - 449,449,449,449,449,1,233,1,449, + 449,449,449,449,449,1,230,1,449, 450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, 450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, - 450,450,450,450,450,1,234,1,450, + 450,450,450,450,450,1,231,1,450, 451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, 451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, - 451,451,451,451,451,1,235,1,451, + 451,451,451,451,451,1,232,1,451, 452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452, 452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452, - 452,452,452,452,452,1,236,1,452, -453,453,453,453,453,453,453,453,1,237,1,453, -454,454,454,454,454,454,454,454,1,238,1,454, -455,455,455,455,455,455,455,455,1,239,1,455, -456,456,456,456,456,456,456,456,1,240,1,456, -457,457,457,457,1,241,1,457, -458,458,458,458,1,242,1,458, -459,459,459,459,459,459,459,1,243,1,459, -460,460,460,460,460,460,460,1,244,1,460, -461,461,461,461,461,461,461,1,245,1,461, -462,462,462,462,462,462,462,462,462,1,246,1,462, -463,463,463,463,463,463,463,463,463,1,247,1,463, -464,464,464,464,464,464,464,464,464,1,248,1,464, -465,465,465,465,465,465,465,465,465,1,249,1,465, -466,466,466,466,466,466,466,466,466,1,250,1,466, -467,467,467,467,467,467,467,467,467,1,251,1,467, -468,468,468,468,468,468,468,468,468,1,252,1,468, -469,469,469,469,469,469,469,469,469,1,253,1,469, -470,470,470,470,470,470,470,470,470,1,254,1,470, -471,471,471,471,471,471,471,471,471,1,255,1,471, -472,472,472,472,472,472,472,472,472,1,256,1,472, -473,473,473,473,473,473,473,473,473,1,257,1,473, -474,474,474,474,474,474,474,474,474,1,258,1,474, -19,128,128,128,128,128,128,128,128,128,128,128,19,128,19,19,129,129,129,129, - 129,19,128,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,128,19,19,19,19,1,259,1,892,129, -19,19,19,19,19,1,260,1,307, -59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59, - 59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59, - 59,59,59,59,59,59,59,59,59,59,59,301,59,59,59,59,59,59,59,261,475, -112,112,112,112,476,262,476, -477,111,478, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,264,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,329,100,216,317,303,259,330,318,322,321,320,319,215,322,312, - 311,310,309,308,307,306,305,304,302,285,284,259,300,299, -289,479,481,483,484,485,487,488,489,491,493,495,497,499,501,503,505,507,509, - 510,512,513,514,516,517,519,520,521,522,525,526,334,336,338,340,342,265, - 68,69,524,70,72,63,64,523,523,523,523,77,518,518,518,515,515,515,515, - 511,511,511,508,506,504,502,500,498,496,494,492,490,103,104,486,107,108, - 482,480,113, -527,527,527,527,1,266,1,527, -528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528, - 528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528, - 528,528,528,1,267,1,528, -529,529,529,529,1,268,1,529, -139,530,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, - 139,139,139,139,139,135,139,139,139,139,139,139,139,139,139,139,139,139, - 139,139,139,139,139,139,269,137, -19,19,19,19,19,19,19,19,270,1,885, -531,531,531,531,1,271,1,531, -37,38,39,34,272,54,54,42,54,41,40,40, -37,38,39,34,273,53,53,42,53,41,40,40, -532,532,532,532,1,274,1,532, -272,272,272,272,272,275, -257,257,257,257,276, -255,255,277, -127,127,127,127,127,127,127,251,251,251,251,127,251,251,251,251,251,127,127, - 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, - 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, - 127,127,127,278, -246,533,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, - 246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, - 246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,279, -244,244,244,244,244,280, -262,534,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, - 262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, - 262,262,262,262,268,262,281,535, -273,273,273,273,273,270, -237,254,254,254,254,254,254,254,254,254,283, -258,258,258,258,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, - 236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, - 236,236,236,236,236,284, -256,256,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, - 235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, - 235,235,235,285, -252,252,252,252,252,252,252,252,252,234,234,234,234,234,234,234,234,234,234, - 234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, - 234,234,234,234,234,234,234,234,234,234,286, -248,238,253,536,537,253,247,247,247,247,247,249,233,233,233,233,233,233,233, - 233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, - 233,233,233,233,233,233,271,233,233,233,233,242,242,233,287,242, -19,19,288,1,987, -19,19,19,19,19,19,289,1,940, -19,19,290,1,985, -19,19,291,1,984, -19,19,292,1,983, -19,19,293,1,982, -19,19,294,1,981, -19,19,295,1,980, -19,19,296,1,979, -19,19,297,1,978, -19,19,298,1,977, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,299,1,988, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,1,300,1,941, + 452,452,452,452,452,1,233,1,452, +453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453, + 453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453, + 453,453,453,453,453,1,234,1,453, +454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454, + 454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454, + 454,454,454,454,454,1,235,1,454, +455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455, + 455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455, + 455,455,455,455,455,1,236,1,455, +456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456, + 456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456, + 456,456,456,456,456,1,237,1,456, +457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457, + 457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457, + 457,457,457,457,457,1,238,1,457, +458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458, + 458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458, + 458,458,458,458,458,1,239,1,458, +459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459, + 459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459, + 459,459,459,459,459,1,240,1,459, +460,460,460,460,460,460,460,460,1,241,1,460, +461,461,461,461,461,461,461,461,1,242,1,461, +462,462,462,462,462,462,462,462,1,243,1,462, +463,463,463,463,463,463,463,463,1,244,1,463, +464,464,464,464,1,245,1,464, +465,465,465,465,1,246,1,465, +466,466,466,466,466,466,466,1,247,1,466, +467,467,467,467,467,467,467,1,248,1,467, +468,468,468,468,468,468,468,1,249,1,468, +469,469,469,469,469,469,469,469,469,1,250,1,469, +470,470,470,470,470,470,470,470,470,1,251,1,470, +471,471,471,471,471,471,471,471,471,1,252,1,471, +472,472,472,472,472,472,472,472,472,1,253,1,472, +473,473,473,473,473,473,473,473,473,1,254,1,473, +474,474,474,474,474,474,474,474,474,1,255,1,474, +475,475,475,475,475,475,475,475,475,1,256,1,475, +476,476,476,476,476,476,476,476,476,1,257,1,476, +477,477,477,477,477,477,477,477,477,1,258,1,477, +478,478,478,478,478,478,478,478,478,1,259,1,478, +479,479,479,479,479,479,479,479,479,1,260,1,479, +480,480,480,480,480,480,480,480,480,1,261,1,480, +481,481,481,481,481,481,481,481,481,1,262,1,481, +19,132,132,132,132,132,132,132,132,132,132,132,19,132,19,19,133,133,133,133, + 133,19,132,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,132,19,19,19,19,1,263,1,891,133, +19,19,19,19,19,1,264,1,311, +62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62, + 62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62, + 62,62,62,62,62,62,62,62,62,307,62,62,62,62,62,62,62,62,62,265,482, +116,116,116,116,483,266,483, +484,115,485, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,268,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,335,104,220,323,309,263,336,324,328,327,326,325,219,328,318, + 317,316,315,314,313,312,311,310,308,291,290,263,306,305, +295,486,488,490,491,492,494,495,496,500,502,504,506,508,510,512,514,516,517, + 519,520,521,523,524,526,527,528,529,532,533,14,15,340,342,344,346,348, + 269,71,72,531,73,75,499,498,66,67,530,530,530,530,80,525,525,525,522, + 522,522,522,518,518,518,515,513,511,509,507,505,503,501,497,107,108,493, + 111,112,489,487,117, +534,534,534,534,1,270,1,534, +535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535, + 535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535, + 535,535,535,1,271,1,535, +536,536,536,536,1,272,1,536, +143,537,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, + 143,143,143,143,139,143,143,143,143,143,143,143,143,143,143,143,143,143, + 143,143,143,143,143,273,141, +19,19,19,19,19,19,19,19,274,1,884, +382,275,538, +539,539,539,539,1,276,1,539, +540,540,540,540,1,277,1,540, +41,42,43,38,278,55,55,46,55,45,44,44, +41,42,43,38,279,54,54,46,54,45,44,44, +541,541,541,541,1,280,1,541, +276,276,276,276,276,281, +261,261,261,261,282, +259,259,283, +131,131,131,131,131,131,131,255,255,255,255,131,255,255,255,255,255,131,131, + 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, + 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, + 131,131,131,284, +250,542,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, + 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, + 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,285, +248,248,248,248,248,286, +266,543,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, + 266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, + 266,266,266,272,266,287,544, +277,277,277,277,277,274, +241,258,258,258,258,258,258,258,258,258,289, +262,262,262,262,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, + 240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, + 240,240,240,240,240,290, +260,260,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, + 239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, + 239,239,239,291, +256,256,256,256,256,256,256,256,256,238,238,238,238,238,238,238,238,238,238, + 238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, + 238,238,238,238,238,238,238,238,238,238,292, +252,242,257,545,546,257,251,251,251,251,251,253,237,237,237,237,237,237,237, + 237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, + 237,237,237,237,237,237,275,237,237,237,237,246,246,237,293,246, +19,19,294,1,986, +19,19,19,19,19,19,295,1,940, +19,19,296,1,984, +19,19,297,1,983, +19,19,298,1,982, +19,19,299,1,981, +19,19,300,1,980, +19,19,301,1,979, +19,19,302,1,978, +19,19,303,1,977, +19,19,304,1,976, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,305,1,987, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,1,306,1,941, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,301,1,906, -538,1,302,1,538, -539,1,303,1,539, -540,1,304,1,540, -541,1,305,1,541, -542,1,306,1,542, -543,1,307,1,543, -544,1,308,1,544, -545,1,309,1,545, -546,1,310,1,546, -547,1,311,1,547, -548,1,312,1,548, -19,19,19,19,19,19,19,19,19,19,19,19,19,245,245,245,245,245,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,313,1,968, + 19,19,19,19,19,19,19,19,19,19,19,19,19,307,1,908, +547,1,308,1,547, +548,1,309,1,548, +549,1,310,1,549, +550,1,311,1,550, +551,1,312,1,551, +552,1,313,1,552, +553,1,314,1,553, +554,1,315,1,554, +555,1,316,1,555, +556,1,317,1,556, +557,1,318,1,557, +19,19,19,19,19,19,19,19,19,19,19,19,19,249,249,249,249,249,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,319,1,967, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,314,1,976, + 19,19,19,19,19,19,19,19,19,19,19,19,320,1,975, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,315,1,975, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,321,1,974, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,316,1,974, -549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549, - 549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549, - 549,549,549,549,549,1,317,1,549, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, - 126,125,318,230,286,287,231,282,232,283,261,216,317,303,259,214,215,214, - 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, - 126,125,319,230,286,287,231,282,232,283,261,216,317,303,259,213,215,213, - 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, - 126,125,320,230,286,287,231,282,232,283,261,216,317,303,259,212,215,212, - 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, - 126,125,321,230,286,287,231,282,232,283,261,216,317,303,259,211,215,211, - 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,1,322,1,204, -19,551,553,382,374,378,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,1,323,1,201,557,556,555,554,552, -19,375,377,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,1,324,1,196,559,558, -19,560,562,564,566,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,1,325,1,193,567,565,563,561, -19,568,381,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,1,326,1,190,570,569, -19,571,353,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1, - 327,1,187,573,572, -574,351,186,576,575, -577,578,579,580,581,582,583,584,585,586,587,588,589,166,166,166,166,166,329, - 170,170,170,170,173,173,173,176,176,176,179,179,179,182,182,182,185,185, - 185, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,330,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,165,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -590,590,590,590,1,331,1,590, -591,591,591,591,1,332,1,591, -592,592,592,592,592,333,592, -19,19,19,19,19,334,1,895, -593,593,593,593,1,335,1,593, -19,19,19,19,19,336,1,894, -594,594,594,594,1,337,1,594, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,338,1,893, -595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,1,339,1,595, -19,19,19,19,19,340,1,891, -596,596,596,596,1,341,1,596, -19,19,19,19,19,342,1,889, -597,597,597,597,1,343,1,597, -155,155,598,155,155,155,155,155,155,155,155,155,155,155,155,153,155,155,155, - 155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, - 155,155,155,155,155,344, -19,19,19,19,19,345,1,886, -599,599,599,599,1,346,1,599, -600,600,600,600,1,347,1,600, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,348,1,884, -130,130,130,130,130,130,130,130,130,130,130,130,154,130,130,130,130,130,136, - 130,130,349,604,269,603,344,602,270,345,601, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 350,1,1156, + 19,19,19,19,19,19,19,19,19,19,19,19,322,1,973, +558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558, + 558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558, + 558,558,558,558,558,1,323,1,558, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, + 130,129,324,234,292,293,235,288,236,289,265,220,323,309,263,218,219,218, + 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, + 130,129,325,234,292,293,235,288,236,289,265,220,323,309,263,217,219,217, + 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, + 130,129,326,234,292,293,235,288,236,289,265,220,323,309,263,216,219,216, + 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, + 130,129,327,234,292,293,235,288,236,289,265,220,323,309,263,215,219,215, + 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,1,328,1,208, +19,560,562,388,380,384,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,1,329,1,205,566,565,564,563,561, +19,381,383,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,1,330,1,200,568,567, +19,569,571,573,575,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,1,331,1,197,576,574,572,570, +19,577,387,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,1,332,1,194,579,578, +19,580,359,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1, + 333,1,191,582,581, +583,357,190,585,584, +586,587,588,589,590,591,592,593,594,595,596,597,396,170,170,170,170,170,335, + 174,174,174,174,177,177,177,180,180,180,183,183,183,186,186,186,189,189, + 189, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,336,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,169,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +598,598,598,598,1,337,1,598, +599,599,599,599,1,338,1,599, +600,600,600,600,600,339,600, +19,19,19,19,19,340,1,894, +601,601,601,601,1,341,1,601, +19,19,19,19,19,342,1,893, +602,602,602,602,1,343,1,602, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,344,1,892, +603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,1,345,1,603, +19,19,19,19,19,346,1,890, +604,604,604,604,1,347,1,604, +19,19,19,19,19,348,1,888, +605,605,605,605,1,349,1,605, +159,159,606,159,159,159,159,159,159,159,159,159,159,159,159,157,159,159,159, + 159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, + 159,159,159,159,350, +19,19,19,19,19,351,1,885, +607,607,607,607,1,352,1,607, +608,608,608,608,1,353,1,608, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,354,1,883, +134,134,134,134,134,134,134,134,134,134,134,134,158,134,134,134,134,134,140, + 134,134,355,612,273,611,350,610,274,351,609, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,356,1, + 1154, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,351,1,957, + 19,19,19,19,19,19,19,19,19,19,19,19,19,357,1,956, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 352,1,1155, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,358,1, + 1153, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,353,1,959, + 19,19,19,19,19,19,19,19,19,19,19,19,19,359,1,958, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,354,1, - 1154, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,360,1,1152, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 355,1,1153, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,361,1, + 1151, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 356,1,1152, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,362,1, + 1150, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 357,1,1151, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,363,1, + 1149, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 358,1,1150, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,364,1, + 1148, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 359,1,1149, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,365,1, + 1147, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 360,1,1148, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,366,1, + 1146, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 361,1,1147, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,367,1, + 1145, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 362,1,1146, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,368,1, + 1144, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 363,1,1145, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,369,1, + 1143, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 364,1,1144, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,370,1, + 1142, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 365,1,1143, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,371,1, + 1141, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 366,1,1142, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,372,1, + 1140, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 367,1,1141, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,373,1, + 1139, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 368,1,1140, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,374,1, + 1138, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 369,1,1139, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,375,1, + 1137, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 370,1,1138, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,376,1, + 1136, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 371,1,1137, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,377,1, + 1135, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 372,1,1136, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,378,1, + 1134, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 373,1,1135, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,379,1, + 1133, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,374,1,970, + 19,19,19,19,19,19,19,19,19,19,19,19,380,1,969, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,375,1,968, + 19,19,19,19,19,19,19,19,19,19,19,19,19,381,1,967, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,376,1,929, + 19,19,19,19,19,19,19,19,19,19,19,19,19,382,1,903, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,377,1,967, + 19,19,19,19,19,19,19,19,19,19,19,19,19,383,1,966, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,378,1,969, + 19,19,19,19,19,19,19,19,19,19,19,19,384,1,968, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 379,1,905, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,385,1, + 907, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 380,1,1134, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,386,1, + 1132, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,381,1,961, + 19,19,19,19,19,19,19,19,19,19,19,19,19,387,1,960, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,382,1,971, + 19,19,19,19,19,19,19,19,19,19,19,19,388,1,970, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 383,1,1133, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,384,1, - 1132, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,389,1, + 1131, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 385,1,1131, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,390,1, + 1130, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 386,1,1130, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,391,1, + 1129, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,387,1,877, -350,352,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370, - 371,372,373,380,383,384,385,386,314,316,382,374,378,375,377,381,353,351, - 376,301,379,35,38,7,9,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, -34,389,11, -34,390,10, -289,479,481,483,484,485,487,488,489,491,493,495,497,499,501,503,505,507,509, - 510,512,513,514,516,517,519,520,521,522,525,526,334,336,338,340,342,605, - 607,391,608,606,68,69,524,70,72,63,64,523,523,523,523,77,518,518,518, - 515,515,515,515,511,511,511,508,506,504,502,500,498,496,494,492,490,103, - 104,486,107,108,482,480,113, -609,609,609,609,1,392,1,609, -610,289,37,38,39,34,393,611,65,65,42,65,41,40,40,163,164, -301,612,613,614,303,302,303,302,301,394,301,302,303,306,393,304,305, -283,282,282,279,278,277,276,275,274,395,391,282,615, -286,293,292,289,292,289,286,396,389,286,289,292,616, -395,395,395,395,397,395, -376,398,617, -376,399,618, -376,400,619, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,401,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,463,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,402,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,462,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,403,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,461,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,404,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,460,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,405,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,459,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,406,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,458,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,407,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,457,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,408,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,456,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,409,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,455,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,410,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,454,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,411,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,453,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,412,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,452,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,413,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,451,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,414,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,450,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,415,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,449,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,416,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,448,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,417,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,447,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,418,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,446,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,419,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,445,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,420,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,444,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,421,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,443,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,422,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,442,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,423,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,441,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,424,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,440,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,425,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,439,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,426,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,435,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,427,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,431,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,428,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,430,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,429,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,429,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,430,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,428,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,431,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,427,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,432,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,426,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,433,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,425,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,434,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,419,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,435,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,418,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,436,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,417,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,437,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,416,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,438,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,410,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,439,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,409,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,440,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,408,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,441,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,407,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,442,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,406,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,443,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,405,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,444,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,404,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,445,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,403,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,446,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,402,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,447,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,401,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,448,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,400,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,449,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,399,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,450,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,398,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,451,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,397,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,452,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,396,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -294,620,621,296,295,296,295,294,453,298,294,295,296,372,297, -294,620,621,296,295,296,295,294,454,298,294,295,296,371,297, -294,620,621,296,295,296,295,294,455,298,294,295,296,370,297, -294,620,621,296,295,296,295,294,456,298,294,295,296,369,297, -299,300,300,299,457,299,300,368, -299,300,300,299,458,299,300,367, -286,293,292,289,292,289,286,459,388,286,289,292,616, -286,293,292,289,292,289,286,460,387,286,289,292,616, -286,293,292,289,292,289,286,461,386,286,289,292,616, -301,612,613,614,303,302,303,302,301,462,301,302,303,306,385,304,305, -301,612,613,614,303,302,303,302,301,463,301,302,303,306,384,304,305, -283,282,282,279,278,277,276,275,274,464,383,282,615, -283,282,282,279,278,277,276,275,274,465,382,282,615, -283,282,282,279,278,277,276,275,274,466,381,282,615, -283,282,282,279,278,277,276,275,274,467,380,282,615, -283,282,282,279,278,277,276,275,274,468,622,282,615, -283,282,282,279,278,277,276,275,274,469,378,282,615, -283,282,282,279,278,277,276,275,274,470,377,282,615, -283,282,282,279,278,277,276,275,274,471,376,282,615, -283,282,282,279,278,277,276,275,274,472,375,282,615, -283,282,282,279,278,277,276,275,274,473,374,282,615, -283,282,282,279,278,277,276,275,274,474,373,282,615, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,623, - 278,136,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280, - 289,301,275,261,126,125,475,230,286,287,231,282,115,269,232,283,624,116, - 261,326,325,323,328,324,327,322,117,216,317,626,303,259,318,322,321,320, - 319,215,322,312,311,310,309,308,307,306,305,304,302,285,284,270,259,625, - 300,299, -276,246,246,246,246,279,281,627,277,550,280,261,18,476,114,286,628,232,283, - 285,284,300, + 19,19,19,19,19,19,392,1,875, +356,358,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376, + 377,378,379,386,389,390,391,320,322,388,380,384,381,383,387,359,357,307, + 385,382,39,42,7,9,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7, +38,394,11, +38,395,10, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,396,1,881, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,397,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,613,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +295,486,488,490,491,492,494,495,496,500,502,504,506,508,510,512,514,516,517, + 519,520,521,523,524,526,527,528,529,532,533,14,15,340,342,344,346,348, + 614,616,398,617,615,71,72,531,73,75,499,498,66,67,530,530,530,530,80, + 525,525,525,522,522,522,522,518,518,518,515,513,511,509,507,505,503,501, + 497,107,108,493,111,112,489,487,117, +618,618,618,618,1,399,1,618, +619,295,41,42,43,38,400,620,68,68,46,68,45,44,44,167,168, +305,621,622,623,307,306,307,306,305,401,305,306,307,310,397,308,309, +287,286,286,283,282,281,280,279,278,402,395,286,624, +290,297,296,293,296,293,290,403,393,290,293,296,625, +399,399,399,399,404,399, +382,405,626, +382,406,627, +382,407,628, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,408,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,467,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,409,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,466,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,410,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,465,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,411,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,464,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,412,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,463,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,413,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,462,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,414,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,461,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,415,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,460,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,416,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,459,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,417,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,458,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,418,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,457,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,419,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,456,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,420,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,455,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,421,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,454,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,422,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,453,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,423,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,452,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,424,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,451,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,425,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,450,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,426,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,449,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,427,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,448,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,428,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,447,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,429,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,446,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,430,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,445,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,431,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,444,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,432,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,443,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,433,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,439,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,434,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,435,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,435,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,434,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,436,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,433,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,437,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,432,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,438,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,431,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,439,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,430,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,440,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,429,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,441,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,423,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,442,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,422,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,443,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,421,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,444,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,420,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,445,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,414,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,446,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,413,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,447,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,412,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,448,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,411,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,449,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,410,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,450,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,409,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,451,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,408,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,452,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,407,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,453,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,406,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,454,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,405,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,455,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,404,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,456,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,403,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,457,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,402,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,458,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,401,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,459,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,400,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +298,629,630,300,299,300,299,298,460,302,298,299,300,376,301, +298,629,630,300,299,300,299,298,461,302,298,299,300,375,301, +298,629,630,300,299,300,299,298,462,302,298,299,300,374,301, +298,629,630,300,299,300,299,298,463,302,298,299,300,373,301, +303,304,304,303,464,303,304,372, +303,304,304,303,465,303,304,371, +290,297,296,293,296,293,290,466,392,290,293,296,625, +290,297,296,293,296,293,290,467,391,290,293,296,625, +290,297,296,293,296,293,290,468,390,290,293,296,625, +305,621,622,623,307,306,307,306,305,469,305,306,307,310,389,308,309, +305,621,622,623,307,306,307,306,305,470,305,306,307,310,388,308,309, +287,286,286,283,282,281,280,279,278,471,387,286,624, +287,286,286,283,282,281,280,279,278,472,386,286,624, +287,286,286,283,282,281,280,279,278,473,385,286,624, +287,286,286,283,282,281,280,279,278,474,384,286,624, +287,286,286,283,282,281,280,279,278,475,631,286,624, +287,286,286,283,282,281,280,279,278,476,382,286,624, +287,286,286,283,282,281,280,279,278,477,381,286,624, +287,286,286,283,282,281,280,279,278,478,380,286,624, +287,286,286,283,282,281,280,279,278,479,379,286,624, +287,286,286,283,282,281,280,279,278,480,378,286,624, +287,286,286,283,282,281,280,279,278,481,377,286,624, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,632, + 284,140,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286, + 295,307,281,265,130,129,482,234,292,293,235,288,119,273,236,289,633,120, + 265,332,331,329,334,330,333,328,121,220,323,635,309,263,324,328,327,326, + 325,219,328,318,317,316,315,314,313,312,311,310,308,291,290,274,263,634, + 306,305, +282,250,250,250,250,285,287,636,283,559,286,265,18,483,118,292,637,236,289, + 291,290,306, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,477,1,994, -629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, - 629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, - 629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, - 629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, - 629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, - 629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, - 629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, - 629,629,629,629,629,629,1,478,1,629, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,479,1,939, -127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,480,110,259,259, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,481,1,938, -130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, - 482,109,601, -19,19,19,19,19,483,1,937, -19,19,19,19,19,484,1,936, -19,19,1,485,1,935, -630,136,486,106,269,624,105,270,625, -19,19,19,19,19,487,1,933, -19,19,19,19,19,488,1,932, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,489,1,931, -127,127,127,127,127,127,127,127,127,127,127,127,127,98,98,98,98,126,125,98, - 490,99,259,259, -19,1,491,1,930, -136,492,631,269,270, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,493,1,928, -632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632, - 632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632, - 632,632,632,632,632,632,1,494,1,632, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,495,1,927, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,136,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280, - 289,301,275,261,126,125,496,230,286,287,231,282,95,269,232,283,261,326, - 325,323,328,324,327,322,94,216,317,303,259,318,322,321,320,319,215,322, - 312,311,310,309,308,307,306,305,304,302,285,284,270,259,300,299, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,497,1,926, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,498,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,93,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,499,1,925, -127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,500,92,259,259, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,501,1,924, -127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,502,91,259,259, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,503,1,923, -127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,504,121,633,259, - 259, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,505,1,922, -127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,506,121,634,259, - 259, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,507,1,921, -127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,508,121,635,259, - 259, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,509,1,920, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,510,1,919, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,623, - 278,136,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280, - 289,301,275,261,126,125,511,230,286,287,231,282,115,269,232,283,624,116, - 261,326,325,323,328,324,327,322,117,216,317,636,303,259,318,322,321,320, - 319,215,322,312,311,310,309,308,307,306,305,304,302,285,284,270,259,625, - 300,299, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,512,1,918, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,513,1,917, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,514,1,916, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,623, - 278,136,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280, - 289,301,275,261,126,125,515,230,286,287,231,282,115,269,232,283,624,116, - 261,326,325,323,328,324,327,322,117,216,317,637,303,259,318,322,321,320, - 319,215,322,312,311,310,309,308,307,306,305,304,302,285,284,270,259,625, - 300,299, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,516,1,915, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,517,1,914, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,518,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,80,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -19,19,19,19,19,519,1,913, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,520,1,912, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,521,1,911, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,522,1,910, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,523,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,76,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,524,71,259,259, -19,19,19,19,19,19,19,525,1,909, -19,19,19,19,19,19,19,526,1,908, -37,38,39,34,527,21,21,42,21,41,40,40, -350,352,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371, - 372,373,380,383,385,386,314,316,382,374,378,375,377,381,353,351,376,301, - 379,35,38,528,60,60,638,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60, - 60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60, -37,38,39,34,529,56,56,42,56,41,40,40, -140,639,142,143,141,147,146,640,640,641,639,145,138,530,639, -37,38,39,34,531,55,55,42,55,41,40,40, -37,38,39,34,532,52,52,42,52,41,40,40, -250,250,250,250,250,250,250,250,250,533, -263,265,266,264,267,269,534, -262,534,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, - 262,262,259,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, - 262,262,262,262,262,268,262,535,642, -253,253,253,253,253,253,253,253,253,253,243,243,243,243,243,243,243,243,243, + 19,19,19,19,19,19,19,19,19,19,19,19,19,484,1,993, +638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, + 638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, + 638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, + 638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, + 638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, + 638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, + 638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, + 638,638,638,638,638,638,1,485,1,638, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,486,1,939, +131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,487,114,263,263, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,488,1,938, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, + 489,113,609, +19,19,19,19,19,490,1,937, +19,19,19,19,19,491,1,936, +19,19,1,492,1,935, +639,140,493,110,273,633,109,274,634, +19,19,19,19,19,494,1,933, +19,19,19,19,19,495,1,932, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,496,1,931, +131,131,131,131,131,131,131,131,131,131,131,131,131,102,102,102,102,130,129, + 102,497,103,263,263, +140,498,640,273,274, +140,499,100,273,274, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,500,1,930, +641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641, + 641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641, + 641,641,641,641,641,641,1,501,1,641, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,502,1,929, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,140,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286, + 295,307,281,265,130,129,503,234,292,293,235,288,98,273,236,289,265,332, + 331,329,334,330,333,328,97,220,323,309,263,324,328,327,326,325,219,328, + 318,317,316,315,314,313,312,311,310,308,291,290,274,263,306,305, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,504,1,928, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,505,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,96,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,506,1,927, +131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,507,95,263,263, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,508,1,926, +131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,509,94,263,263, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,510,1,925, +131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,511,125,642,263, + 263, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,512,1,924, +131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,513,125,643,263, + 263, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,514,1,923, +131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,515,125,644,263, + 263, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,516,1,922, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,517,1,921, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,632, + 284,140,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286, + 295,307,281,265,130,129,518,234,292,293,235,288,119,273,236,289,633,120, + 265,332,331,329,334,330,333,328,121,220,323,645,309,263,324,328,327,326, + 325,219,328,318,317,316,315,314,313,312,311,310,308,291,290,274,263,634, + 306,305, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,519,1,920, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,520,1,919, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,521,1,918, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,632, + 284,140,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286, + 295,307,281,265,130,129,522,234,292,293,235,288,119,273,236,289,633,120, + 265,332,331,329,334,330,333,328,121,220,323,646,309,263,324,328,327,326, + 325,219,328,318,317,316,315,314,313,312,311,310,308,291,290,274,263,634, + 306,305, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,523,1,917, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,524,1,916, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,525,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,83,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +19,19,19,19,19,526,1,915, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,527,1,914, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,528,1,913, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,529,1,912, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,530,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,79,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,531,74,263,263, +19,19,19,19,19,19,19,532,1,911, +19,19,19,19,19,19,19,533,1,910, +41,42,43,38,534,21,21,46,21,45,44,44, +356,358,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377, + 378,379,386,389,390,391,320,322,388,380,384,381,383,387,359,357,307,385, + 382,39,42,535,63,63,63,647,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, +41,42,43,38,536,59,59,46,59,45,44,44, +144,648,146,147,145,151,150,649,649,650,648,149,142,537,648, +651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651, + 651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651, + 651,651,651,651,651,1,538,1,651, +41,42,43,38,539,57,57,46,57,45,44,44, +41,42,43,38,540,56,56,46,56,45,44,44, +41,42,43,38,541,53,53,46,53,45,44,44, +254,254,254,254,254,254,254,254,254,542, +267,269,270,268,271,273,543, +266,543,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, + 266,266,263,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, + 266,266,266,266,272,266,544,652, +257,257,257,257,257,257,257,257,257,257,247,247,247,247,247,247,247,247,247, + 247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, + 247,247,247,247,247,247,247,247,247,247,247,545, +257,257,257,257,257,257,257,257,257,257,243,243,243,243,243,243,243,243,243, 243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, - 243,243,243,243,243,243,243,243,243,243,243,536, -253,253,253,253,253,253,253,253,253,253,239,239,239,239,239,239,239,239,239, - 239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, - 239,239,239,239,239,239,239,239,239,239,239,537, -301,538,643, -301,539,644, -301,540,645, -301,541,646, -301,542,647, -301,543,648, -301,544,649, -301,545,650, -301,546,651, -301,547,652, -301,548,653, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,549,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,654,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -245,245,245,245,245,550, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,551,1,973, -655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655, - 655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655, - 655,655,1,552,1,655, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,553,1,972, -656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656, - 656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656, - 656,656,1,554,1,656, -657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657, - 657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657, - 657,657,1,555,1,657, -658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658, - 658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658, - 658,658,1,556,1,658, -659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659, - 659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659, - 659,659,1,557,1,659, -660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660, - 660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660, - 660,660,660,660,660,1,558,1,660, -661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661, - 661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661, - 661,661,661,661,661,1,559,1,661, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,560,1,966, -662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662, - 662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662, - 662,662,662,662,662,1,561,1,662, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,562,1,965, -663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663, - 663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663, - 663,663,663,663,663,1,563,1,663, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,564,1,964, -664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664, - 664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664, - 664,664,664,664,664,1,565,1,664, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,566,1,963, + 243,243,243,243,243,243,243,243,243,243,243,546, +307,547,653, +307,548,654, +307,549,655, +307,550,656, +307,551,657, +307,552,658, +307,553,659, +307,554,660, +307,555,661, +307,556,662, +307,557,663, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,558,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,664,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +249,249,249,249,249,559, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,560,1,972, 665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665, 665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665, - 665,665,665,665,665,1,567,1,665, + 665,665,1,561,1,665, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,568,1,962, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,562,1,971, 666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666, 666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666, - 666,666,666,666,666,1,569,1,666, + 666,666,1,563,1,666, 667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667, 667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667, - 667,667,667,667,667,1,570,1,667, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,571,1,960, + 667,667,1,564,1,667, 668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668, 668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668, - 668,668,668,668,668,1,572,1,668, + 668,668,1,565,1,668, 669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669, 669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669, - 669,669,669,669,669,1,573,1,669, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,574,1,958, + 669,669,1,566,1,669, 670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, 670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, - 670,670,670,670,670,1,575,1,670, + 670,670,670,670,670,1,567,1,670, 671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, 671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, - 671,671,671,671,671,1,576,1,671, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,577,1,956, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,578,1,955, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,579,1,954, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,580,1,953, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,581,1,952, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,582,1,951, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,583,1,950, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,584,1,949, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,585,1,948, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,586,1,947, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,587,1,946, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,588,1,945, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,589,1,944, -37,38,39,34,590,51,51,42,51,41,40,40, -37,38,39,34,591,50,50,42,50,41,40,40, -37,38,39,34,592,49,49,42,49,41,40,40, -37,38,39,34,593,46,46,42,46,41,40,40, -37,38,39,34,594,45,45,42,45,41,40,40, -127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,595,672,259,259, -37,38,39,34,596,43,43,42,43,41,40,40, -37,38,39,34,597,42,42,42,42,41,40,40, -156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, - 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, - 156,156,156,156,156,157,156,598, -37,38,39,34,599,41,41,42,41,41,40,40, -37,38,39,34,600,40,40,42,40,41,40,40, -131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, - 19,19,19,601,1,887, -673,673,673,673,1,602,1,673, -674,674,674,674,1,603,1,674, -675,675,675,675,1,604,1,675, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,605,1,882, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,606,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,676,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,607,1,881, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,608,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,677,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -37,38,39,34,609,22,22,42,22,41,40,40, -19,19,19,19,19,610,1,943, -678,678,678,678,1,611,1,678, -19,19,19,19,19,19,19,612,1,993, -19,19,19,19,19,19,19,613,1,992, -19,19,19,19,19,19,19,614,1,991, -19,19,19,19,19,19,19,19,615,1,1044, -19,19,19,19,19,19,19,616,1,1058, + 671,671,671,671,671,1,568,1,671, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,569,1,965, +672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, + 672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, + 672,672,672,672,672,1,570,1,672, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,571,1,964, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, + 673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, + 673,673,673,673,673,1,572,1,673, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,573,1,963, +674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674, + 674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674, + 674,674,674,674,674,1,574,1,674, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,575,1,962, +675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675, + 675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675, + 675,675,675,675,675,1,576,1,675, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,577,1,961, +676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676, + 676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676, + 676,676,676,676,676,1,578,1,676, +677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677, + 677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677, + 677,677,677,677,677,1,579,1,677, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,580,1,959, +678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678, + 678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678, + 678,678,678,678,678,1,581,1,678, 679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, 679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, - 679,679,679,679,679,1,617,1,679, + 679,679,679,679,679,1,582,1,679, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,583,1,957, 680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680, 680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680, - 680,680,680,680,680,1,618,1,680, + 680,680,680,680,680,1,584,1,680, 681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681, 681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681, - 681,681,681,681,681,1,619,1,681, -19,19,19,19,19,19,620,1,990, -19,19,19,19,19,19,621,1,989, -682,1,622,1,682, -262,534,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, - 262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, - 262,262,262,262,268,262,623,683, -262,534,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, - 262,262,132,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, - 262,262,262,262,262,268,262,624,134, -19,19,19,19,19,19,19,625,1,934, -684,379,626,58,685, -251,251,251,251,251,251,251,251,251,627, -248,238,253,536,537,253,247,247,247,247,247,249,233,233,233,233,242,242,233, - 628,242, -111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129, - 130,131,132,133,134,62,63,64,65,66,67,135,136,137,138,139,140,68,69,70, - 71,72,141,142,143,73,74,75,76,77,144,145,146,147,148,149,150,151,152, - 153,154,155,156,157,158,107,59,60,61,165,166,167,168,169,170,171,172, - 173,174,175,176,177,178,179,180,159,160,161,162,163,164,78,79,80,81,82, - 83,45,46,47,84,85,86,87,88,89,90,91,92,48,49,93,94,95,96,97,98,99,100, - 50,51,52,101,102,53,54,103,104,105,106,55,56,57,58,629,686,687,196,687, - 687,687,687,687,687,687,687,687,687,323,323,323,323,323,324,325,326,327, - 330,330,330,331,332,336,336,336,336,337,338,339,340,341,342,343,344,347, - 347,347,348,349,350,351,352,353,354,355,356,360,360,360,360,361,362,363, - 364,365,366,242,241,240,239,238,237,258,257,256,255,254,253,252,251,250, - 249,248,247,246,245,244,243,184,110,183,109,182,108,181,236,235,234,233, - 232,231,230,229,228,227,226,225,224,223,222,221,221,221,221,221,221,220, - 219,218,217,217,217,217,217,217,216,215,214,213,212,211,210,210,210,210, - 209,209,209,209,208,207,206,205,204,203,202,201,200,199,198,197,195,194, - 193,192,191,190,189,188,187,186,185, -262,534,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, - 262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, - 262,262,262,262,268,262,630,688, -376,631,689, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,623, - 278,136,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280, - 289,301,275,261,126,125,632,230,286,287,231,282,115,269,232,283,624,116, - 261,326,325,323,328,324,327,322,117,216,317,690,303,259,318,322,321,320, - 319,215,322,312,311,310,309,308,307,306,305,304,302,285,284,270,259,625, - 300,299, -684,90,90,90,90,90,633,691, -684,89,89,89,89,89,634,691, -684,88,88,88,88,88,635,691, -684,87,87,87,87,87,636,685, -684,84,84,84,84,84,637,685, -350,352,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371, - 372,373,380,383,385,386,314,316,382,374,378,375,377,381,353,351,376,692, - 301,379,35,38,694,693,638,61,1,694,61,61,61,62,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61, -695,695,695,695,695,695,695,695,695,639, -696,696,696,696,696,640, -144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,696,696,696, - 696,696,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, - 144,144,144,144,144,144,641, -260,642, -697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,1,643,1,697, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,644,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,698,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,645,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,699,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,646,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,700,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,647,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,701,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,648,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,702,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,649,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,703,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,650,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,704,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,651,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,705,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,652,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,706,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,653,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,707,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -708,1,654,1,708, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, - 126,125,655,230,286,287,231,282,232,283,261,216,317,303,259,209,215,209, - 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, - 126,125,656,230,286,287,231,282,232,283,261,216,317,303,259,208,215,208, - 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, - 126,125,657,230,286,287,231,282,232,283,261,216,317,303,259,207,215,207, - 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, - 126,125,658,230,286,287,231,282,232,283,261,216,317,303,259,206,215,206, - 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,277,550,280,289,301,275,261, - 126,125,659,230,286,287,231,282,232,283,261,216,317,303,259,205,215,205, - 312,311,310,309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,660,230,286,287,231,282,232,283,261,709,322,216,317, - 303,259,318,322,321,320,319,215,322,312,311,310,309,308,307,306,305,304, - 302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,661,230,286,287,231,282,232,283,261,710,322,216,317, - 303,259,318,322,321,320,319,215,322,312,311,310,309,308,307,306,305,304, - 302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,662,230,286,287,231,282,232,283,261,323,711,322,216, - 317,303,259,318,322,321,320,319,215,322,312,311,310,309,308,307,306,305, - 304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,663,230,286,287,231,282,232,283,261,323,712,322,216, - 317,303,259,318,322,321,320,319,215,322,312,311,310,309,308,307,306,305, - 304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,664,230,286,287,231,282,232,283,261,323,713,322,216, - 317,303,259,318,322,321,320,319,215,322,312,311,310,309,308,307,306,305, - 304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,665,230,286,287,231,282,232,283,261,323,714,322,216, - 317,303,259,318,322,321,320,319,215,322,312,311,310,309,308,307,306,305, - 304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,666,230,286,287,231,282,232,283,261,715,323,324,322, - 216,317,303,259,318,322,321,320,319,215,322,312,311,310,309,308,307,306, - 305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,667,230,286,287,231,282,232,283,261,716,323,324,322, - 216,317,303,259,318,322,321,320,319,215,322,312,311,310,309,308,307,306, - 305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,668,230,286,287,231,282,232,283,261,717,325,323,324, - 322,216,317,303,259,318,322,321,320,319,215,322,312,311,310,309,308,307, - 306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,669,230,286,287,231,282,232,283,261,718,325,323,324, - 322,216,317,303,259,318,322,321,320,319,215,322,312,311,310,309,308,307, - 306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,670,230,286,287,231,282,232,283,261,326,325,323,324, - 719,322,216,317,303,259,318,322,321,320,319,215,322,312,311,310,309,308, - 307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,671,230,286,287,231,282,232,283,261,326,325,323,324, - 720,322,216,317,303,259,318,322,321,320,319,215,322,312,311,310,309,308, - 307,306,305,304,302,285,284,259,300,299, -721,721,721,721,1,672,1,721, -37,38,39,34,673,34,34,42,34,41,40,40, -37,38,39,34,674,33,33,42,33,41,40,40, -37,38,39,34,675,32,32,42,32,41,40,40, -722,722,722,722,1,676,1,722, -723,723,723,723,1,677,1,723, -37,38,39,34,678,66,66,42,66,41,40,40, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,679,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,394,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,680,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,392,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,681,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,390,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -684,682,724, -262,534,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, - 262,262,259,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, - 262,262,262,262,262,268,262,683,725, + 681,681,681,681,681,1,585,1,681, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,586,1,955, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,587,1,954, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,588,1,953, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,589,1,952, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,590,1,951, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,591,1,950, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,592,1,949, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,593,1,948, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,594,1,947, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,595,1,946, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,596,1,945, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,597,1,944, +41,42,43,38,598,52,52,46,52,45,44,44, +41,42,43,38,599,51,51,46,51,45,44,44, +41,42,43,38,600,50,50,46,50,45,44,44, +41,42,43,38,601,47,47,46,47,45,44,44, +41,42,43,38,602,46,46,46,46,45,44,44, +131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,603,682,263,263, +41,42,43,38,604,44,44,46,44,45,44,44, +41,42,43,38,605,43,43,46,43,45,44,44, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, + 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, + 160,160,160,160,161,160,606, +41,42,43,38,607,42,42,46,42,45,44,44, +41,42,43,38,608,41,41,46,41,45,44,44, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, + 19,19,19,609,1,886, +683,683,683,683,1,610,1,683, +684,684,684,684,1,611,1,684, +685,685,685,685,1,612,1,685, +686,686,686,686,1,613,1,686, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,614,1,880, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,615,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,687,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,616,1,879, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,617,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,688,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +41,42,43,38,618,22,22,46,22,45,44,44, +19,19,19,19,19,619,1,943, +689,689,689,689,1,620,1,689, +19,19,19,19,19,19,19,621,1,992, +19,19,19,19,19,19,19,622,1,991, +19,19,19,19,19,19,19,623,1,990, +19,19,19,19,19,19,19,19,624,1,1043, +19,19,19,19,19,19,19,625,1,1057, +690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690, + 690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690, + 690,690,690,690,690,1,626,1,690, +691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, + 691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, + 691,691,691,691,691,1,627,1,691, +692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692, + 692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692, + 692,692,692,692,692,1,628,1,692, +19,19,19,19,19,19,629,1,989, +19,19,19,19,19,19,630,1,988, +693,1,631,1,693, +266,543,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, + 266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, + 266,266,266,272,266,632,694, +266,543,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, + 266,266,136,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, + 266,266,266,266,272,266,633,138, +19,19,19,19,19,19,19,634,1,934, +695,385,635,61,696, +255,255,255,255,255,255,255,255,255,636, +252,242,257,545,546,257,251,251,251,251,251,253,237,237,237,237,246,246,237, + 637,246, +115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133, + 134,135,136,137,138,66,67,68,69,70,71,139,140,141,142,143,144,72,73,74, + 75,76,145,146,147,77,78,79,80,81,148,149,150,151,152,153,154,155,156, + 157,158,159,160,161,162,111,63,64,65,169,170,171,172,173,174,175,176, + 177,178,179,180,181,182,183,184,163,164,165,166,167,168,82,83,84,85,86, + 87,49,50,51,88,89,90,91,92,93,94,95,96,52,53,97,98,99,100,101,102,103, + 104,54,55,56,105,106,57,58,107,108,109,110,59,60,61,62,638,697,698,200, + 698,698,698,698,698,698,698,698,698,698,327,327,327,327,327,328,329,330, + 331,334,334,334,335,336,340,340,340,340,341,342,343,344,345,346,347,348, + 351,351,351,352,353,354,355,356,357,358,359,360,364,364,364,364,365,366, + 367,368,369,370,246,245,244,243,242,241,262,261,260,259,258,257,256,255, + 254,253,252,251,250,249,248,247,188,114,187,113,186,112,185,240,239,238, + 237,236,235,234,233,232,231,230,229,228,227,226,225,225,225,225,225,225, + 224,223,222,221,221,221,221,221,221,220,219,218,217,216,215,214,214,214, + 214,213,213,213,213,212,211,210,209,208,207,206,205,204,203,202,201,199, + 198,197,196,195,194,193,192,191,190,189, +266,543,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, + 266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, + 266,266,266,272,266,639,699, +382,640,700, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,632, + 284,140,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286, + 295,307,281,265,130,129,641,234,292,293,235,288,119,273,236,289,633,120, + 265,332,331,329,334,330,333,328,121,220,323,701,309,263,324,328,327,326, + 325,219,328,318,317,316,315,314,313,312,311,310,308,291,290,274,263,634, + 306,305, +695,93,93,93,93,93,642,702, +695,92,92,92,92,92,643,702, +695,91,91,91,91,91,644,702, +695,90,90,90,90,90,645,696, +695,87,87,87,87,87,646,696, +356,358,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377, + 378,379,386,389,390,391,320,322,388,380,384,381,383,387,359,357,703,307, + 385,382,39,42,705,704,647,64,1,705,64,64,64,64,65,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, + 64,64,64,64, +706,706,706,706,706,706,706,706,706,648, +707,707,707,707,707,649, +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,707,707,707, + 707,707,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, + 148,148,148,148,148,650, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,651,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,708,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +264,652, +709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,1,653,1,709, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,654,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,710,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,655,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,711,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,656,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,712,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,657,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,713,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,658,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,714,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,659,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,715,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,660,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,716,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,661,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,717,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,662,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,718,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,663,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,719,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +720,1,664,1,720, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, + 130,129,665,234,292,293,235,288,236,289,265,220,323,309,263,213,219,213, + 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, + 130,129,666,234,292,293,235,288,236,289,265,220,323,309,263,212,219,212, + 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, + 130,129,667,234,292,293,235,288,236,289,265,220,323,309,263,211,219,211, + 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, + 130,129,668,234,292,293,235,288,236,289,265,220,323,309,263,210,219,210, + 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, + 130,129,669,234,292,293,235,288,236,289,265,220,323,309,263,209,219,209, + 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,670,234,292,293,235,288,236,289,265,721,328,220,323, + 309,263,324,328,327,326,325,219,328,318,317,316,315,314,313,312,311,310, + 308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,671,234,292,293,235,288,236,289,265,722,328,220,323, + 309,263,324,328,327,326,325,219,328,318,317,316,315,314,313,312,311,310, + 308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,672,234,292,293,235,288,236,289,265,329,723,328,220, + 323,309,263,324,328,327,326,325,219,328,318,317,316,315,314,313,312,311, + 310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,673,234,292,293,235,288,236,289,265,329,724,328,220, + 323,309,263,324,328,327,326,325,219,328,318,317,316,315,314,313,312,311, + 310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,674,234,292,293,235,288,236,289,265,329,725,328,220, + 323,309,263,324,328,327,326,325,219,328,318,317,316,315,314,313,312,311, + 310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,675,234,292,293,235,288,236,289,265,329,726,328,220, + 323,309,263,324,328,327,326,325,219,328,318,317,316,315,314,313,312,311, + 310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,676,234,292,293,235,288,236,289,265,727,329,330,328, + 220,323,309,263,324,328,327,326,325,219,328,318,317,316,315,314,313,312, + 311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,677,234,292,293,235,288,236,289,265,728,329,330,328, + 220,323,309,263,324,328,327,326,325,219,328,318,317,316,315,314,313,312, + 311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,678,234,292,293,235,288,236,289,265,729,331,329,330, + 328,220,323,309,263,324,328,327,326,325,219,328,318,317,316,315,314,313, + 312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,679,234,292,293,235,288,236,289,265,730,331,329,330, + 328,220,323,309,263,324,328,327,326,325,219,328,318,317,316,315,314,313, + 312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,680,234,292,293,235,288,236,289,265,332,331,329,330, + 731,328,220,323,309,263,324,328,327,326,325,219,328,318,317,316,315,314, + 313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,681,234,292,293,235,288,236,289,265,332,331,329,330, + 732,328,220,323,309,263,324,328,327,326,325,219,328,318,317,316,315,314, + 313,312,311,310,308,291,290,263,306,305, +733,733,733,733,1,682,1,733, +41,42,43,38,683,35,35,46,35,45,44,44, +41,42,43,38,684,34,34,46,34,45,44,44, +41,42,43,38,685,33,33,46,33,45,44,44, +41,42,43,38,686,30,30,46,30,45,44,44, +734,734,734,734,1,687,1,734, +735,735,735,735,1,688,1,735, +41,42,43,38,689,69,69,46,69,45,44,44, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,690,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,398,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,691,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,396,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,692,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,394,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +695,693,736, +266,543,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, + 266,266,263,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, + 266,266,266,266,272,266,694,737, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,684,1,942, -726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, - 726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, - 726,726,726,726,726,726,1,685,1,726, -477,686,478, -19,318,318,318,318,1,687,1,307, -262,534,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, - 262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, - 262,262,262,262,268,262,688,133, -727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727, - 727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727, - 727,727,727,727,727,1,689,1,727, -684,96,96,96,96,96,690,685, -728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,1,691,1,728, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,692,1,907, -61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, - 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,17,17,17,17,17,693, -37,38,39,34,694,57,57,42,57,41,40,40, -152,152,152,152,152,152,152,152,151,151,151,151,152,152,152,152,151,151,151, - 151,151,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, - 152,152,152,152,152,152,695, -148,148,148,148,148,696, -127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,697,731,729,729, - 730, -379,698,228, -379,699,227, -379,700,226, -379,701,225, -379,702,224, -379,703,223, -379,704,222, -379,705,221, -379,706,220, -379,707,219, -379,708,218, -203,551,553,382,374,378,203,203,203,203,203,203,203,203,203,203,203,203,203, - 203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,709, - 557,556,555,554,552, -202,551,553,382,374,378,202,202,202,202,202,202,202,202,202,202,202,202,202, - 202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,710, - 557,556,555,554,552, -200,375,377,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, - 200,200,200,200,200,200,200,200,200,200,200,200,200,200,711,559,558, -199,375,377,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, - 199,199,199,199,199,199,199,199,199,199,199,199,199,199,712,559,558, -198,375,377,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, - 198,198,198,198,198,198,198,198,198,198,198,198,198,198,713,559,558, -197,375,377,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, - 197,197,197,197,197,197,197,197,197,197,197,197,197,197,714,559,558, -195,560,562,564,566,195,195,195,195,195,195,195,195,195,195,195,195,195,195, - 195,195,195,195,195,195,195,195,195,195,195,195,715,567,565,563,561, -194,560,562,564,566,194,194,194,194,194,194,194,194,194,194,194,194,194,194, - 194,194,194,194,194,194,194,194,194,194,194,194,716,567,565,563,561, -192,568,381,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, - 192,192,192,192,192,192,192,192,717,570,569, -191,568,381,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191, - 191,191,191,191,191,191,191,191,718,570,569, -189,571,353,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189, - 189,189,189,189,189,189,719,573,572, -188,571,353,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188, - 188,188,188,188,188,188,720,573,572, -37,38,39,34,721,44,44,42,44,41,40,40, -37,38,39,34,722,29,29,42,29,41,40,40, -37,38,39,34,723,28,28,42,28,41,40,40, -732,732,732,732,732,732,732,732,732,1,724,1,732, -133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, - 133,133,260,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, - 133,133,133,133,133,133,133,725, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,623, - 278,136,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280, - 289,301,275,261,126,125,726,230,286,287,231,282,119,269,232,283,624,120, - 261,326,325,323,328,324,327,322,118,216,317,303,259,318,322,321,320,319, - 215,322,312,311,310,309,308,307,306,305,304,302,285,284,270,259,625,300, - 299, -127,127,127,127,127,127,127,127,127,127,127,276,127,246,246,246,246,279,281, - 278,288,290,291,292,293,294,295,296,297,298,314,315,316,277,313,280,289, - 301,275,261,126,125,727,230,286,287,231,282,232,283,261,326,325,323,328, - 324,327,322,97,216,317,303,259,318,322,321,320,319,215,322,312,311,310, - 309,308,307,306,305,304,302,285,284,259,300,299, -127,127,127,127,127,127,127,127,127,127,127,127,127,126,125,728,122,259,259, -128,128,128,128,128,128,128,128,128,128,128,128,129,129,129,129,129,128,19, - 128,1,729,1,123,129, -19,19,730,1,986, -733,1,731,1,733, -283,282,282,279,278,277,276,275,274,732,379,282,615, -379,733,229, + 19,19,19,19,695,1,942, +738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738, + 738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738, + 738,738,738,738,738,738,1,696,1,738, +484,697,485, +19,322,322,322,322,1,698,1,311, +266,543,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, + 266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, + 266,266,266,272,266,699,137, +739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, + 739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, + 739,739,739,739,739,1,700,1,739, +695,99,99,99,99,99,701,696, +740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,1,702,1,740, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,703,1,909, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,17,17,17,17,17,704, +41,42,43,38,705,60,60,46,60,45,44,44, +156,156,156,156,156,156,156,156,155,155,155,155,156,156,156,156,155,155,155, + 155,155,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, + 156,156,156,156,156,706, +152,152,152,152,152,707, +741,741,741,741,1,708,1,741, +131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,709,744,742,742, + 743, +385,710,232, +385,711,231, +385,712,230, +385,713,229, +385,714,228, +385,715,227, +385,716,226, +385,717,225, +385,718,224, +385,719,223, +385,720,222, +207,560,562,388,380,384,207,207,207,207,207,207,207,207,207,207,207,207,207, + 207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,721, + 566,565,564,563,561, +206,560,562,388,380,384,206,206,206,206,206,206,206,206,206,206,206,206,206, + 206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,722, + 566,565,564,563,561, +204,381,383,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, + 204,204,204,204,204,204,204,204,204,204,204,204,204,204,723,568,567, +203,381,383,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, + 203,203,203,203,203,203,203,203,203,203,203,203,203,203,724,568,567, +202,381,383,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, + 202,202,202,202,202,202,202,202,202,202,202,202,202,202,725,568,567, +201,381,383,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, + 201,201,201,201,201,201,201,201,201,201,201,201,201,201,726,568,567, +199,569,571,573,575,199,199,199,199,199,199,199,199,199,199,199,199,199,199, + 199,199,199,199,199,199,199,199,199,199,199,199,727,576,574,572,570, +198,569,571,573,575,198,198,198,198,198,198,198,198,198,198,198,198,198,198, + 198,198,198,198,198,198,198,198,198,198,198,198,728,576,574,572,570, +196,577,387,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, + 196,196,196,196,196,196,196,196,729,579,578, +195,577,387,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, + 195,195,195,195,195,195,195,195,730,579,578, +193,580,359,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, + 193,193,193,193,193,193,731,582,581, +192,580,359,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, + 192,192,192,192,192,192,732,582,581, +41,42,43,38,733,45,45,46,45,45,44,44, +41,42,43,38,734,29,29,46,29,45,44,44, +41,42,43,38,735,28,28,46,28,45,44,44, +745,745,745,745,745,745,745,745,745,1,736,1,745, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, + 137,137,264,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, + 137,137,137,137,137,137,737, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,632, + 284,140,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286, + 295,307,281,265,130,129,738,234,292,293,235,288,123,273,236,289,633,124, + 265,332,331,329,334,330,333,328,122,220,323,309,263,324,328,327,326,325, + 219,328,318,317,316,315,314,313,312,311,310,308,291,290,274,263,634,306, + 305, +131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, + 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, + 307,281,265,130,129,739,234,292,293,235,288,236,289,265,332,331,329,334, + 330,333,328,101,220,323,309,263,324,328,327,326,325,219,328,318,317,316, + 315,314,313,312,311,310,308,291,290,263,306,305, +131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,740,126,263,263, +41,42,43,38,741,58,58,46,58,45,44,44, +132,132,132,132,132,132,132,132,132,132,132,132,133,133,133,133,133,132,19, + 132,1,742,1,127,133, +19,19,743,1,985, +746,1,744,1,746, +287,286,286,283,282,281,280,279,278,745,383,286,624, +385,746,233, }; static const unsigned short ag_sbt[] = { - 0, 30, 32, 72, 87, 116, 140, 338, 341, 358, 556, 922, 961, 980, - 999,1004,1012,1020,1039,1085,1131,1150,1159,1184,1204,1223,1228,1236, - 1244,1263,1350,1437,1456,1467,1476,1535,1626,1632,1681,1732,1779,1873, - 1962,2051,2423,2433,2442,2451,2460,2469,2478,2487,2496,2505,2514,2523, - 2532,2541,2550,2559,2572,2585,2596,2642,2688,2734,2780,2826,2872,2918, - 2964,3010,3056,3102,3148,3194,3240,3286,3332,3341,3350,3359,3368,3377, - 3386,3395,3404,3413,3422,3431,3440,3449,3458,3467,3476,3485,3494,3503, - 3512,3521,3530,3539,3548,3557,3566,3575,3584,3593,3601,3614,3627,3638, - 3684,3730,3776,3822,3868,3914,3960,4006,4052,4098,4144,4190,4236,4282, - 4328,4374,4420,4466,4512,4558,4604,4650,4696,4742,4788,4834,4880,4926, - 4972,5018,5064,5110,5156,5202,5248,5294,5340,5386,5432,5478,5524,5570, - 5616,5662,5708,5754,5800,5846,5858,5870,5882,5894,5902,5910,5921,5932, - 5943,5956,5969,5982,5995,6008,6021,6034,6047,6060,6073,6086,6099,6112, - 6120,6125,6130,6135,6181,6227,6273,6319,6365,6411,6457,6503,6549,6595, - 6641,6687,6733,6779,6825,6871,6917,6963,7009,7055,7101,7147,7193,7239, - 7285,7331,7377,7423,7469,7515,7561,7607,7653,7699,7745,7791,7837,7883, - 7929,7975,8021,8067,8113,8159,8205,8251,8297,8343,8389,8435,8481,8527, - 8539,8551,8563,8575,8583,8591,8602,8613,8624,8637,8650,8663,8676,8689, - 8702,8715,8728,8741,8754,8767,8780,8793,8853,8862,8932,8939,8942,9029, - 9106,9114,9158,9166,9211,9222,9230,9242,9254,9262,9268,9273,9276,9335, - 9390,9396,9441,9447,9458,9501,9542,9590,9643,9648,9657,9662,9667,9672, - 9677,9682,9687,9692,9697,9702,9743,9784,9850,9855,9860,9865,9870,9875, - 9880,9885,9890,9895,9900,9905,9948,10013,10056,10121,10167,10237,10307, - 10377,10447,10488,10532,10570,10608,10640,10670,10675,10713,10798,10806, - 10814,10821,10829,10837,10845,10853,10872,10891,10899,10907,10915,10923, - 10966,10974,10982,10990,11015,11045,11096,11162,11213,11279,11328,11379, - 11430,11481,11532,11583,11634,11685,11736,11787,11838,11889,11940,11991, - 12042,12093,12144,12195,12246,12297,12362,12428,12494,12560,12625,12700, - 12751,12817,12882,12933,12982,13033,13084,13143,13229,13232,13235,13316, - 13324,13341,13358,13371,13384,13390,13393,13396,13399,13484,13569,13654, - 13739,13824,13909,13994,14079,14164,14249,14334,14419,14504,14589,14674, - 14759,14844,14929,15014,15099,15184,15269,15354,15439,15524,15609,15694, - 15779,15864,15949,16034,16119,16204,16289,16374,16459,16544,16629,16714, - 16799,16884,16969,17054,17139,17224,17309,17394,17479,17564,17649,17734, - 17819,17834,17849,17864,17879,17887,17895,17908,17921,17934,17951,17968, - 17981,17994,18007,18020,18033,18046,18059,18072,18085,18098,18111,18204, - 18226,18363,18500,18519,18538,18561,18583,18591,18599,18605,18614,18622, - 18630,18653,18677,18682,18687,18734,18781,18828,18917,18963,19048,19067, - 19086,19105,19124,19143,19163,19182,19202,19221,19241,19288,19335,19428, - 19475,19522,19569,19662,19708,19754,19839,19847,19893,19939,19985,20070, - 20089,20099,20109,20121,20203,20215,20230,20242,20254,20264,20271,20317, - 20366,20415,20418,20421,20424,20427,20430,20433,20436,20439,20442,20445, - 20448,20533,20539,20582,20625,20668,20711,20754,20797,20840,20886,20932, - 20978,21024,21070,21116,21162,21208,21254,21300,21346,21392,21438,21484, - 21530,21576,21622,21668,21714,21760,21806,21852,21898,21944,21990,22036, - 22082,22128,22174,22220,22266,22312,22324,22336,22348,22360,22372,22391, - 22403,22415,22460,22472,22484,22509,22517,22525,22533,22579,22664,22710, - 22795,22807,22815,22823,22833,22843,22853,22864,22874,22920,22966,23012, - 23021,23030,23035,23080,23126,23136,23141,23151,23172,23463,23508,23511, - 23604,23612,23620,23628,23636,23644,23731,23741,23747,23791,23793,23812, - 23897,23982,24067,24152,24237,24322,24407,24492,24577,24662,24667,24737, - 24807,24877,24947,25017,25096,25175,25255,25335,25415,25495,25576,25657, - 25739,25821,25904,25987,25995,26007,26019,26031,26039,26047,26059,26144, - 26229,26314,26317,26363,26419,26466,26469,26478,26523,26569,26577,26596, - 26644,26690,26702,26746,26752,26772,26775,26778,26781,26784,26787,26790, - 26793,26796,26799,26802,26805,26847,26889,26925,26961,26997,27033,27069, - 27105,27135,27165,27193,27221,27233,27245,27257,27270,27315,27407,27492, - 27511,27536,27541,27546,27559,27562 + 0, 30, 32, 72, 89, 119, 147, 347, 350, 367, 567, 934, 973, 992, + 1011,1016,1021,1026,1034,1042,1061,1107,1153,1172,1181,1206,1226,1245, + 1250,1255,1260,1268,1276,1295,1382,1469,1488,1499,1508,1566,1657,1663, + 1711,1761,1807,1899,1986,2073,2448,2458,2467,2476,2485,2494,2503,2512, + 2521,2530,2539,2548,2557,2566,2575,2584,2597,2610,2621,2667,2713,2759, + 2805,2851,2897,2943,2989,3035,3081,3127,3173,3219,3265,3311,3357,3366, + 3375,3384,3393,3402,3411,3420,3429,3438,3447,3456,3465,3474,3483,3492, + 3501,3510,3519,3528,3537,3546,3555,3564,3573,3582,3591,3600,3609,3618, + 3626,3639,3652,3663,3709,3755,3801,3847,3893,3939,3985,4031,4077,4123, + 4169,4215,4261,4307,4353,4399,4445,4491,4537,4583,4629,4675,4721,4767, + 4813,4859,4905,4951,4997,5043,5089,5135,5181,5227,5273,5319,5365,5411, + 5457,5503,5549,5595,5641,5687,5733,5779,5825,5871,5883,5895,5907,5919, + 5927,5935,5946,5957,5968,5981,5994,6007,6020,6033,6046,6059,6072,6085, + 6098,6111,6124,6137,6145,6150,6155,6160,6206,6252,6298,6344,6390,6436, + 6482,6528,6574,6620,6666,6712,6758,6804,6850,6896,6942,6988,7034,7080, + 7126,7172,7218,7264,7310,7356,7402,7448,7494,7540,7586,7632,7678,7724, + 7770,7816,7862,7908,7954,8000,8046,8092,8138,8184,8230,8276,8322,8368, + 8414,8460,8506,8552,8564,8576,8588,8600,8608,8616,8627,8638,8649,8662, + 8675,8688,8701,8714,8727,8740,8753,8766,8779,8792,8805,8818,8878,8887, + 8957,8964,8967,9054,9133,9141,9185,9193,9237,9248,9251,9259,9267,9279, + 9291,9299,9305,9310,9313,9372,9427,9433,9477,9483,9494,9537,9578,9626, + 9679,9684,9693,9698,9703,9708,9713,9718,9723,9728,9733,9738,9779,9820, + 9885,9890,9895,9900,9905,9910,9915,9920,9925,9930,9935,9940,9983,10047, + 10090,10154,10200,10270,10340,10410,10480,10521,10565,10603,10641,10673, + 10703,10708,10746,10831,10839,10847,10854,10862,10870,10878,10886,10905, + 10924,10932,10940,10948,10956,10998,11006,11014,11022,11047,11077,11127, + 11192,11242,11307,11355,11405,11455,11505,11555,11605,11655,11705,11755, + 11805,11855,11905,11955,12005,12055,12105,12155,12205,12255,12305,12369, + 12434,12499,12564,12628,12702,12752,12817,12881,12931,12981,13031,13089, + 13173,13176,13179,13225,13310,13393,13401,13418,13435,13448,13461,13467, + 13470,13473,13476,13561,13646,13731,13816,13901,13986,14071,14156,14241, + 14326,14411,14496,14581,14666,14751,14836,14921,15006,15091,15176,15261, + 15346,15431,15516,15601,15686,15771,15856,15941,16026,16111,16196,16281, + 16366,16451,16536,16621,16706,16791,16876,16961,17046,17131,17216,17301, + 17386,17471,17556,17641,17726,17811,17896,17911,17926,17941,17956,17964, + 17972,17985,17998,18011,18028,18045,18058,18071,18084,18097,18110,18123, + 18136,18149,18162,18175,18188,18281,18303,18440,18577,18596,18615,18638, + 18660,18668,18676,18682,18691,18699,18707,18730,18754,18759,18764,18811, + 18858,18905,18994,19040,19125,19144,19163,19182,19201,19220,19240,19259, + 19279,19298,19318,19365,19412,19505,19552,19599,19646,19739,19785,19831, + 19916,19924,19970,20016,20062,20147,20166,20176,20186,20198,20280,20292, + 20307,20353,20365,20377,20389,20399,20406,20451,20500,20549,20552,20555, + 20558,20561,20564,20567,20570,20573,20576,20579,20582,20667,20673,20716, + 20759,20802,20845,20888,20931,20974,21020,21066,21112,21158,21204,21250, + 21296,21342,21388,21434,21480,21526,21572,21618,21664,21710,21756,21802, + 21848,21894,21940,21986,22032,22078,22124,22170,22216,22262,22308,22354, + 22400,22412,22424,22436,22448,22460,22479,22491,22503,22547,22559,22571, + 22596,22604,22612,22620,22628,22674,22759,22805,22890,22902,22910,22918, + 22928,22938,22948,22959,22969,23015,23061,23107,23116,23125,23130,23174, + 23219,23229,23234,23244,23265,23556,23600,23603,23696,23704,23712,23720, + 23728,23736,23823,23833,23839,23882,23967,23969,23988,24073,24158,24243, + 24328,24413,24498,24583,24668,24753,24838,24843,24913,24983,25053,25123, + 25193,25272,25351,25431,25511,25591,25671,25752,25833,25915,25997,26080, + 26163,26171,26183,26195,26207,26219,26227,26235,26247,26332,26417,26502, + 26505,26550,26606,26653,26656,26665,26709,26755,26763,26782,26830,26876, + 26888,26931,26937,26945,26965,26968,26971,26974,26977,26980,26983,26986, + 26989,26992,26995,26998,27040,27082,27118,27154,27190,27226,27262,27298, + 27328,27358,27386,27414,27426,27438,27450,27463,27507,27599,27684,27703, + 27715,27740,27745,27750,27763,27766 }; static const unsigned short ag_sbe[] = { - 27, 31, 58, 84, 114, 127, 335, 339, 348, 553, 751, 949, 977, 996, - 1001,1009,1017,1036,1082,1128,1147,1156,1181,1199,1219,1224,1233,1241, - 1259,1305,1392,1452,1461,1469,1532,1623,1628,1678,1729,1776,1825,1917, - 2006,2245,2430,2439,2448,2457,2466,2475,2484,2493,2502,2511,2520,2529, - 2538,2547,2556,2569,2582,2593,2639,2685,2731,2777,2823,2869,2915,2961, - 3007,3053,3099,3145,3191,3237,3283,3329,3338,3347,3356,3365,3374,3383, - 3392,3401,3410,3419,3428,3437,3446,3455,3464,3473,3482,3491,3500,3509, - 3518,3527,3536,3545,3554,3563,3572,3581,3590,3598,3611,3624,3635,3681, - 3727,3773,3819,3865,3911,3957,4003,4049,4095,4141,4187,4233,4279,4325, - 4371,4417,4463,4509,4555,4601,4647,4693,4739,4785,4831,4877,4923,4969, - 5015,5061,5107,5153,5199,5245,5291,5337,5383,5429,5475,5521,5567,5613, - 5659,5705,5751,5797,5843,5855,5867,5879,5891,5899,5907,5918,5929,5940, - 5953,5966,5979,5992,6005,6018,6031,6044,6057,6070,6083,6096,6109,6117, - 6122,6127,6132,6178,6224,6270,6316,6362,6408,6454,6500,6546,6592,6638, - 6684,6730,6776,6822,6868,6914,6960,7006,7052,7098,7144,7190,7236,7282, - 7328,7374,7420,7466,7512,7558,7604,7650,7696,7742,7788,7834,7880,7926, - 7972,8018,8064,8110,8156,8202,8248,8294,8340,8386,8432,8478,8524,8536, - 8548,8560,8572,8580,8588,8599,8610,8621,8634,8647,8660,8673,8686,8699, - 8712,8725,8738,8751,8764,8777,8790,8849,8859,8930,8937,8940,8984,9065, - 9111,9155,9163,9209,9219,9227,9234,9246,9259,9267,9272,9275,9334,9389, - 9395,9439,9446,9457,9500,9541,9589,9641,9645,9654,9659,9664,9669,9674, - 9679,9684,9689,9694,9699,9740,9781,9847,9852,9857,9862,9867,9872,9877, - 9882,9887,9892,9897,9902,9945,10010,10053,10118,10164,10206,10276,10346, - 10416,10485,10524,10565,10601,10635,10665,10672,10693,10755,10803,10811, - 10819,10826,10834,10842,10850,10869,10888,10896,10904,10912,10920,10965, - 10971,10979,10987,11012,11036,11093,11159,11210,11276,11325,11376,11427, - 11478,11529,11580,11631,11682,11733,11784,11835,11886,11937,11988,12039, - 12090,12141,12192,12243,12294,12359,12425,12491,12557,12622,12697,12748, - 12814,12879,12930,12979,13030,13081,13140,13186,13230,13233,13273,13321, - 13330,13350,13367,13378,13388,13391,13394,13397,13441,13526,13611,13696, - 13781,13866,13951,14036,14121,14206,14291,14376,14461,14546,14631,14716, - 14801,14886,14971,15056,15141,15226,15311,15396,15481,15566,15651,15736, - 15821,15906,15991,16076,16161,16246,16331,16416,16501,16586,16671,16756, - 16841,16926,17011,17096,17181,17266,17351,17436,17521,17606,17691,17776, - 17827,17842,17857,17872,17883,17891,17902,17915,17928,17943,17960,17977, - 17990,18003,18016,18029,18042,18055,18068,18081,18094,18107,18154,18217, - 18360,18497,18516,18534,18558,18580,18588,18596,18602,18607,18619,18627, - 18650,18673,18679,18683,18731,18778,18825,18871,18960,19005,19064,19082, - 19102,19120,19140,19158,19179,19197,19218,19236,19285,19332,19378,19472, - 19519,19566,19612,19705,19751,19796,19844,19890,19936,19982,20027,20085, - 20096,20106,20113,20161,20207,20228,20234,20246,20263,20270,20315,20365, - 20414,20416,20419,20422,20425,20428,20431,20434,20437,20440,20443,20446, - 20490,20538,20579,20622,20665,20708,20751,20794,20837,20883,20929,20975, - 21021,21067,21113,21159,21205,21251,21297,21343,21389,21435,21481,21527, - 21573,21619,21665,21711,21757,21803,21849,21895,21941,21987,22033,22079, - 22125,22171,22217,22263,22309,22316,22328,22340,22352,22364,22387,22395, - 22407,22459,22464,22476,22506,22514,22522,22530,22576,22621,22707,22752, - 22799,22812,22820,22830,22840,22850,22861,22871,22917,22963,23009,23018, - 23027,23032,23078,23124,23133,23138,23150,23170,23305,23506,23509,23554, - 23610,23618,23626,23634,23642,23687,23740,23746,23790,23792,23809,23854, - 23939,24024,24109,24194,24279,24364,24449,24534,24619,24664,24706,24776, - 24846,24916,24986,25059,25138,25217,25297,25377,25457,25537,25618,25699, - 25781,25863,25946,25992,25999,26011,26023,26036,26044,26051,26101,26186, - 26271,26315,26361,26416,26463,26467,26475,26521,26566,26575,26593,26641, - 26689,26694,26745,26751,26767,26773,26776,26779,26782,26785,26788,26791, - 26794,26797,26800,26803,26841,26883,26922,26958,26994,27030,27064,27100, - 27132,27162,27190,27218,27225,27237,27249,27267,27314,27358,27449,27507, - 27532,27538,27543,27555,27560,27562 + 27, 31, 58, 86, 117, 132, 344, 348, 357, 564, 763, 961, 989,1008, + 1013,1018,1023,1031,1039,1058,1104,1150,1169,1178,1203,1221,1241,1246, + 1251,1256,1265,1273,1291,1337,1424,1484,1493,1501,1563,1654,1659,1708, + 1758,1804,1852,1942,2029,2269,2455,2464,2473,2482,2491,2500,2509,2518, + 2527,2536,2545,2554,2563,2572,2581,2594,2607,2618,2664,2710,2756,2802, + 2848,2894,2940,2986,3032,3078,3124,3170,3216,3262,3308,3354,3363,3372, + 3381,3390,3399,3408,3417,3426,3435,3444,3453,3462,3471,3480,3489,3498, + 3507,3516,3525,3534,3543,3552,3561,3570,3579,3588,3597,3606,3615,3623, + 3636,3649,3660,3706,3752,3798,3844,3890,3936,3982,4028,4074,4120,4166, + 4212,4258,4304,4350,4396,4442,4488,4534,4580,4626,4672,4718,4764,4810, + 4856,4902,4948,4994,5040,5086,5132,5178,5224,5270,5316,5362,5408,5454, + 5500,5546,5592,5638,5684,5730,5776,5822,5868,5880,5892,5904,5916,5924, + 5932,5943,5954,5965,5978,5991,6004,6017,6030,6043,6056,6069,6082,6095, + 6108,6121,6134,6142,6147,6152,6157,6203,6249,6295,6341,6387,6433,6479, + 6525,6571,6617,6663,6709,6755,6801,6847,6893,6939,6985,7031,7077,7123, + 7169,7215,7261,7307,7353,7399,7445,7491,7537,7583,7629,7675,7721,7767, + 7813,7859,7905,7951,7997,8043,8089,8135,8181,8227,8273,8319,8365,8411, + 8457,8503,8549,8561,8573,8585,8597,8605,8613,8624,8635,8646,8659,8672, + 8685,8698,8711,8724,8737,8750,8763,8776,8789,8802,8815,8874,8884,8955, + 8962,8965,9009,9091,9138,9182,9190,9235,9245,9249,9256,9264,9271,9283, + 9296,9304,9309,9312,9371,9426,9432,9475,9482,9493,9536,9577,9625,9677, + 9681,9690,9695,9700,9705,9710,9715,9720,9725,9730,9735,9776,9817,9882, + 9887,9892,9897,9902,9907,9912,9917,9922,9927,9932,9937,9980,10044,10087, + 10151,10197,10239,10309,10379,10449,10518,10557,10598,10634,10668,10698, + 10705,10726,10788,10836,10844,10852,10859,10867,10875,10883,10902,10921, + 10929,10937,10945,10953,10997,11003,11011,11019,11044,11068,11124,11189, + 11239,11304,11352,11402,11452,11502,11552,11602,11652,11702,11752,11802, + 11852,11902,11952,12002,12052,12102,12152,12202,12252,12302,12366,12431, + 12496,12561,12625,12699,12749,12814,12878,12928,12978,13028,13086,13131, + 13174,13177,13222,13267,13349,13398,13407,13427,13444,13455,13465,13468, + 13471,13474,13518,13603,13688,13773,13858,13943,14028,14113,14198,14283, + 14368,14453,14538,14623,14708,14793,14878,14963,15048,15133,15218,15303, + 15388,15473,15558,15643,15728,15813,15898,15983,16068,16153,16238,16323, + 16408,16493,16578,16663,16748,16833,16918,17003,17088,17173,17258,17343, + 17428,17513,17598,17683,17768,17853,17904,17919,17934,17949,17960,17968, + 17979,17992,18005,18020,18037,18054,18067,18080,18093,18106,18119,18132, + 18145,18158,18171,18184,18231,18294,18437,18574,18593,18611,18635,18657, + 18665,18673,18679,18684,18696,18704,18727,18750,18755,18760,18808,18855, + 18902,18948,19037,19082,19141,19159,19179,19197,19217,19235,19256,19274, + 19295,19313,19362,19409,19455,19549,19596,19643,19689,19782,19828,19873, + 19921,19967,20013,20059,20104,20162,20173,20183,20190,20238,20284,20305, + 20350,20357,20369,20381,20398,20405,20449,20499,20548,20550,20553,20556, + 20559,20562,20565,20568,20571,20574,20577,20580,20624,20672,20713,20756, + 20799,20842,20885,20928,20971,21017,21063,21109,21155,21201,21247,21293, + 21339,21385,21431,21477,21523,21569,21615,21661,21707,21753,21799,21845, + 21891,21937,21983,22029,22075,22121,22167,22213,22259,22305,22351,22397, + 22404,22416,22428,22440,22452,22475,22483,22495,22546,22551,22563,22593, + 22601,22609,22617,22625,22671,22716,22802,22847,22894,22907,22915,22925, + 22935,22945,22956,22966,23012,23058,23104,23113,23122,23127,23172,23217, + 23226,23231,23243,23263,23398,23598,23601,23646,23702,23710,23718,23726, + 23734,23779,23832,23838,23881,23924,23968,23985,24030,24115,24200,24285, + 24370,24455,24540,24625,24710,24795,24840,24882,24952,25022,25092,25162, + 25235,25314,25393,25473,25553,25633,25713,25794,25875,25957,26039,26122, + 26168,26175,26187,26199,26211,26224,26232,26239,26289,26374,26459,26503, + 26548,26603,26650,26654,26662,26707,26752,26761,26779,26827,26875,26880, + 26930,26936,26942,26960,26966,26969,26972,26975,26978,26981,26984,26987, + 26990,26993,26996,27034,27076,27115,27151,27187,27223,27257,27293,27325, + 27355,27383,27411,27418,27430,27442,27460,27506,27550,27641,27699,27707, + 27736,27742,27747,27759,27764,27766 }; static const unsigned char ag_fl[] = { - 2,1,1,2,2,1,1,2,0,1,3,3,1,2,1,2,2,1,2,0,1,4,5,3,2,1,0,1,7,7,1,1,6,6,6, - 2,3,2,1,2,4,4,4,4,6,4,4,0,1,4,4,4,4,3,3,4,4,6,4,1,1,2,2,2,2,3,5,1,2,2, - 2,3,2,1,1,1,3,2,1,1,3,1,1,1,3,1,1,3,3,3,3,3,3,3,3,3,4,6,2,3,2,1,1,2,2, - 3,3,2,2,3,3,1,1,2,3,1,1,1,4,4,4,1,4,2,1,1,1,1,2,2,1,2,2,3,2,2,1,2,3,1, - 2,2,2,2,2,2,2,2,4,1,1,4,3,2,1,2,3,3,2,1,1,1,1,1,1,2,1,1,1,1,2,1,1,2,1, - 1,2,1,1,2,1,1,2,1,1,2,1,2,4,4,2,4,4,2,4,4,2,4,4,4,4,2,4,4,2,4,4,4,4,4, - 1,2,2,2,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,7,1,1,1,1,1,1,1,2,2,2,1,1,2,2,2, - 2,1,2,2,2,3,2,2,2,2,2,2,2,2,3,4,1,1,2,2,2,2,2,1,2,1,2,2,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,7,3,3,3,3,3, - 3,3,3,3,3,5,3,5,3,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,3,3,3,3, - 1,1,1,1,1,3,3,3,3,3,3,3,1,1,1,3,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,1,1,2,2,1,1,2,0,1,3,3,1,2,1,2,2,1,2,0,1,4,5,3,2,1,0,1,7,7,6,1,1,6,6, + 6,2,3,2,1,2,4,4,4,4,6,4,4,0,1,4,4,4,4,3,3,4,4,7,4,6,4,1,1,2,2,2,2,3,5, + 1,2,2,2,3,2,1,1,1,3,2,1,1,3,1,1,1,3,1,1,3,3,3,3,3,3,3,3,3,4,3,6,2,3,2, + 1,1,2,2,3,3,2,2,3,3,1,1,2,3,1,1,1,4,4,4,1,4,2,1,1,1,1,2,2,1,2,2,3,2,2, + 1,2,3,1,2,2,2,2,2,2,2,2,4,1,1,4,3,2,1,2,3,3,2,1,1,1,1,1,1,2,1,1,1,1,2, + 1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,2,4,4,2,4,4,2,4,4,2,4,4,4,4,2,4,4,2,4, + 4,4,4,4,1,2,2,2,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,7,1,1,1,1,1,1,1,2,2,2,1, + 1,2,2,2,2,1,2,2,2,3,2,2,2,2,2,2,2,2,3,4,1,1,2,2,2,2,2,1,2,1,2,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,7,3, + 3,3,3,3,3,3,3,3,3,5,3,5,3,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1, + 3,3,3,3,1,1,1,1,1,3,3,3,3,3,3,3,1,1,1,3,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -6605,7 +6672,7 @@ static const unsigned char ag_fl[] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, @@ -6613,76 +6680,75 @@ static const unsigned char ag_fl[] = { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2 + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 }; static const unsigned short ag_ptt[] = { 0, 36, 37, 37, 34, 39, 43, 43, 44, 44, 39, 39, 39, 40, 47, 47, 47, 51, - 51, 52, 52, 35, 35, 35, 35, 35, 55, 55, 35, 35, 61, 61, 35, 35, 35, 35, - 35, 35, 64, 53, 66, 66, 66, 66, 66, 66, 66, 74, 74, 66, 66, 66, 66, 66, - 66, 66, 66, 66, 84, 84, 85, 85, 85, 92, 92, 62, 62, 33, 33, 33, 33, 33, - 33, 98, 98, 98, 33, 33,102,102, 33,106,106,106, 33,109,109, 33, 33, 33, + 51, 52, 52, 35, 35, 35, 35, 35, 55, 55, 35, 35, 35, 62, 62, 35, 35, 35, + 35, 35, 35, 65, 53, 67, 67, 67, 67, 67, 67, 67, 75, 75, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 88, 88, 89, 89, 89, 96, 96, 63, 63, 33, 33, + 33, 33, 33, 33,102,102,102, 33, 33,106,106, 33,110,110,110, 33,113,113, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 30, 30, 87, 87, 87, 87, 87, 87,111,111,535,441,441, - 441,131,131,131,436,436,483, 18, 18,434, 12, 12, 12,140,140,140,140,140, - 140,140,140,140,140,153,153,140,140,435, 14, 14, 14, 14,428,428,428,428, - 428, 22, 22, 76, 76,168,168,168,164,171,171,164,174,174,164,177,177,164, - 180,180,164,183,183,164, 57, 26, 26, 26, 28, 28, 28, 23, 23, 23, 24, 24, - 24, 24, 24, 27, 27, 27, 25, 25, 25, 25, 25, 25, 29, 29, 29, 29, 29,197, - 197,197,197,206,206,206,206,206,206,206,206,206,206,206,205,205,490,490, - 490,490,490,490,490,490,222,222,490,490, 7, 7, 7, 7, 7, 7, 6, 6, - 6, 17, 17,217,217,218,218, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, - 537, 9, 9, 9,593,593,593,593,593,593,241,241,593,593,244,244,607,246, - 246,607,248,248,607,607,250,250,250,250,250,252,252,253,253,253,253,253, - 253, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,271,271,271,271,265, - 265,265,265,265,278,278,265,265,265,284,284,284,265,265,265,265,265,265, - 265,265,265,295,295,265,265,265,265,265,265,265,265,265,265,308,308,308, - 265,265,265,265,265,265,265,258,258,259,259,259,259,256,256,256,256,256, - 256,256,256,256,256,256,256,256,257,257,257,337,261,339,262,341,263,264, - 260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,365,365,365, - 365,365,260,260,260,260,374,374,374,374,374,260,260,260,260,260,260,260, - 384,384,384,260,388,388,388,260,260,260,260,260,260,260,260,260,260,260, - 260,260,260,260,260,260,260,260,260,260,260,260,260,260,136,344,151,225, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 30, 30, 91, 91, 91, 91, 91, 91,115, + 115,536,442,442,442,133,133,133,437,437,485, 18, 18,435, 12, 12, 12,142, + 142,142,142,142,142,142,142,142,142,155,155,142,142,436, 14, 14, 14, 14, + 428,428,428,428,428, 22, 22, 77, 77,169,169,169,166,172,172,166,175,175, + 166,178,178,166,181,181,166,184,184,166, 57, 26, 26, 26, 28, 28, 28, 23, + 23, 23, 24, 24, 24, 24, 24, 27, 27, 27, 25, 25, 25, 25, 25, 25, 29, 29, + 29, 29, 29,198,198,198,198,207,207,207,207,207,207,207,207,207,207,207, + 206,206,492,492,492,492,492,492,492,492,223,223,492,492, 7, 7, 7, 7, + 7, 7, 6, 6, 6, 17, 17,218,218,219,219, 15, 15, 15, 16, 16, 16, 16, + 16, 16, 16, 16,538, 9, 9, 9,594,594,594,594,594,594,242,242,594,594, + 245,245,608,247,247,608,249,249,608,608,251,251,251,251,251,253,253,254, + 254,254,254,254,254, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,272, + 272,272,272,266,266,266,266,266,279,279,266,266,266,285,285,285,266,266, + 266,266,266,266,266,266,266,296,296,266,266,266,266,266,266,266,266,266, + 266,309,309,309,266,266,266,266,266,266,266,259,259,260,260,260,260,257, + 257,257,257,257,257,257,257,257,257,257,257,257,258,258,258,338,262,340, + 263,342,264,265,261,261,261,261,261,261,261,261,261,261,261,261,261,261, + 261,366,366,366,366,366,261,261,261,261,375,375,375,375,375,261,261,261, + 261,261,261,261,385,385,385,261,389,389,389,261,261,261,261,261,261,261, + 261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, + 138,345,153,226, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, - 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, - 90, 90, 90, 90, 90, 90,134,134,134,134,134,134,134,134,134,134,134,134, - 134,135,135,135,135,135,135,135,135,135,135,135,135,135,135,137,137,137, - 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,142,142, - 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, - 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, - 142,142,142,149,149,149,150,150,150,150,150,154,154,154,154,154,154,154, - 154,154,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, - 157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, - 157,157,157,157,157,157,158,158,158,158,158,158,158,158,158,158,158,158, - 158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, - 158,158,158,158,158,158,158,158,158,158,158,158,158,226,226,226,226,227, - 227,229,229,229,229,231,231,231,231,231,231,231,231,231,231,231,231,231, - 231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, - 231,231,231,231,231,231,231,231,231,231, 45, 41, 46, 48, 49, 11, 54, 56, - 58, 59, 60, 10, 13, 19, 65, 68, 67, 69, 21, 70, 71, 72, 73, 75, 77, 78, - 79, 80, 81, 82, 83, 88, 86, 91, 93, 94, 95, 96, 97, 99,100,101,103,104, - 105,107,108,110,112,113,114,115,116,117,118,120,119,121,122,123, 20,124, - 125,126,127,128,129, 2,130,163,165,166,167,169,170,172,173,175,176,178, - 179,181,182,184,185,186,187,188,189,190,191,192,193,194,195,196,198,199, - 200,201,202,203,204,207,208,209,210,211,212,213,214,215, 3,216, 8,251, - 242,254,255,249,266,267,268,269,270,272,273,274,275,276,277,279,280,281, - 282,283,285,286,287,288,289,290,291,292,293,294,296,297,298,299,300,301, - 302,303,304,305,306,307,309,310,311,312,313,314,315,316,317,318,319,320, - 4,321,322,323,324,325,326,327,328,329,330,331,332,333, 5,334,335,336, - 338,340,342,343,345,346,347,348,349,350,351,352,353,354,355,356,357,358, - 359,360,361,362,363,364,366,367,368,369,370,371,372,373,375,376,377,378, - 379,380,381,382,383,385,386,387,389,390,391,392,393,394,395,396,397,398, - 399,400,243,401,402,403,404,405,406,407,408,409,410,411,413,139,414,152, - 138,146,415,416,417,418,156,155,419,228,420,147,223,148,421,219,143,145, - 144,412,141,224,422 + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94,136,136,136,136,136,136,136,136,136,136, + 136,136,136,137,137,137,137,137,137,137,137,137,137,137,137,137,137,139, + 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, + 144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, + 144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, + 144,144,144,144,151,151,151,152,152,152,152,152,156,156,156,156,156,156, + 156,156,156,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, + 159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, + 159,159,159,159,159,159,160,160,160,160,160,160,160,160,160,160,160,160, + 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, + 160,160,160,160,160,160,160,160,160,160,160,160,227,227,227,227,228,228, + 230,230,230,230,232,232,232,232,232,232,232,232,232,232,232,232,232,232, + 232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, + 232,232,232,232,232,232,232,232, 45, 41, 46, 48, 49, 11, 54, 56, 58, 59, + 60, 61, 10, 13, 19, 66, 69, 68, 70, 21, 71, 72, 73, 74, 76, 78, 79, 80, + 81, 82, 83, 85, 84, 86, 87, 92, 90, 95, 97, 98, 99,100,101,103,104,105, + 107,108,109,111,112,114,116,117,118,119,120,121,122,123,124,125, 20,126, + 127,128,129,130,131, 2,132,165,167,168,170,171,173,174,176,177,179,180, + 182,183,185,186,187,188,189,190,191,192,193,194,195,196,197,199,200,201, + 202,203,204,205,208,209,210,211,212,213,214,215,216, 3,217, 8,252,243, + 255,256,250,267,268,269,270,271,273,274,275,276,277,278,280,281,282,283, + 284,286,287,288,289,290,291,292,293,294,295,297,298,299,300,301,302,303, + 304,305,306,307,308,310,311,312,313,314,315,316,317,318,319,320,321, 4, + 322,323,324,325,326,327,328,329,330,331,332,333,334, 5,335,336,337,339, + 341,343,344,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360, + 361,362,363,364,365,367,368,369,370,371,372,373,374,376,377,378,379,380, + 381,382,383,384,386,387,388,390,391,392,393,394,395,396,397,398,399,400, + 401,244,402,403,404,405,406,407,408,409,410,411,412,414,141,154,140,148, + 415,416,417,418,158,157,419,229,420,149,224,150,421,220,145,147,146,413, + 143,225,422 }; @@ -6715,15 +6781,15 @@ static void ag_ra(void) case 24: ag_rp_24(); break; case 25: ag_rp_25(); break; case 26: ag_rp_26(); break; - case 27: ag_rp_27(V(0,int)); break; - case 28: ag_rp_28(V(1,int)); break; + case 27: ag_rp_27(); break; + case 28: ag_rp_28(); break; case 29: ag_rp_29(); break; - case 30: ag_rp_30(); break; - case 31: ag_rp_31(); break; - case 32: ag_rp_32(V(2,int)); break; + case 30: ag_rp_30(V(0,int)); break; + case 31: ag_rp_31(V(1,int)); break; + case 32: ag_rp_32(); break; case 33: ag_rp_33(); break; case 34: ag_rp_34(); break; - case 35: ag_rp_35(); break; + case 35: ag_rp_35(V(2,int)); break; case 36: ag_rp_36(); break; case 37: ag_rp_37(); break; case 38: ag_rp_38(); break; @@ -6756,53 +6822,53 @@ static void ag_ra(void) case 65: ag_rp_65(); break; case 66: ag_rp_66(); break; case 67: ag_rp_67(); break; - case 68: ag_rp_68(V(2,int)); break; + case 68: ag_rp_68(); break; case 69: ag_rp_69(); break; case 70: ag_rp_70(); break; case 71: ag_rp_71(); break; - case 72: ag_rp_72(); break; + case 72: ag_rp_72(V(2,int)); break; case 73: ag_rp_73(); break; case 74: ag_rp_74(); break; case 75: ag_rp_75(); break; case 76: ag_rp_76(); break; case 77: ag_rp_77(); break; case 78: ag_rp_78(); break; - case 79: ag_rp_79(V(0,int)); break; - case 80: ag_rp_80(V(1,int)); break; - case 81: ag_rp_81(V(1,int)); break; - case 82: ag_rp_82(V(0,int)); break; - case 83: ag_rp_83(V(1,int)); break; - case 84: ag_rp_84(V(1,int), V(2,int)); break; + case 79: ag_rp_79(); break; + case 80: ag_rp_80(); break; + case 81: ag_rp_81(); break; + case 82: ag_rp_82(); break; + case 83: ag_rp_83(V(0,int)); break; + case 84: ag_rp_84(V(1,int)); break; case 85: ag_rp_85(V(1,int)); break; - case 86: ag_rp_86(); break; + case 86: ag_rp_86(V(0,int)); break; case 87: ag_rp_87(V(1,int)); break; - case 88: V(0,int) = ag_rp_88(V(0,int)); break; - case 89: V(0,int) = ag_rp_89(); break; - case 90: V(0,int) = ag_rp_90(); break; - case 91: V(0,int) = ag_rp_91(); break; - case 92: V(0,int) = ag_rp_92(); break; + case 88: ag_rp_88(V(1,int), V(2,int)); break; + case 89: ag_rp_89(V(1,int)); break; + case 90: ag_rp_90(); break; + case 91: ag_rp_91(V(1,int)); break; + case 92: V(0,int) = ag_rp_92(V(0,int)); break; case 93: V(0,int) = ag_rp_93(); break; case 94: V(0,int) = ag_rp_94(); break; case 95: V(0,int) = ag_rp_95(); break; case 96: V(0,int) = ag_rp_96(); break; - case 97: V(0,int) = ag_rp_97(V(1,int), V(2,int), V(3,int)); break; - case 98: V(0,int) = ag_rp_98(V(2,int), V(3,int)); break; - case 99: V(0,int) = ag_rp_99(V(2,int)); break; - case 100: ag_rp_100(); break; - case 101: ag_rp_101(); break; - case 102: ag_rp_102(V(1,int)); break; - case 103: ag_rp_103(V(2,int)); break; + case 97: V(0,int) = ag_rp_97(); break; + case 98: V(0,int) = ag_rp_98(); break; + case 99: V(0,int) = ag_rp_99(); break; + case 100: V(0,int) = ag_rp_100(); break; + case 101: V(0,int) = ag_rp_101(V(1,int), V(2,int), V(3,int)); break; + case 102: V(0,int) = ag_rp_102(V(2,int), V(3,int)); break; + case 103: V(0,int) = ag_rp_103(V(2,int)); break; case 104: ag_rp_104(); break; case 105: ag_rp_105(); break; - case 106: ag_rp_106(); break; - case 107: ag_rp_107(); break; + case 106: ag_rp_106(V(1,int)); break; + case 107: ag_rp_107(V(2,int)); break; case 108: ag_rp_108(); break; - case 109: V(0,int) = ag_rp_109(); break; - case 110: V(0,int) = ag_rp_110(); break; + case 109: ag_rp_109(); break; + case 110: ag_rp_110(); break; case 111: ag_rp_111(); break; case 112: ag_rp_112(); break; - case 113: ag_rp_113(); break; - case 114: ag_rp_114(); break; + case 113: V(0,int) = ag_rp_113(); break; + case 114: V(0,int) = ag_rp_114(); break; case 115: ag_rp_115(); break; case 116: ag_rp_116(); break; case 117: ag_rp_117(); break; @@ -6828,11 +6894,11 @@ static void ag_ra(void) case 137: ag_rp_137(); break; case 138: ag_rp_138(); break; case 139: ag_rp_139(); break; - case 140: ag_rp_140(V(0,double)); break; + case 140: ag_rp_140(); break; case 141: ag_rp_141(); break; case 142: ag_rp_142(); break; case 143: ag_rp_143(); break; - case 144: ag_rp_144(); break; + case 144: ag_rp_144(V(0,double)); break; case 145: ag_rp_145(); break; case 146: ag_rp_146(); break; case 147: ag_rp_147(); break; @@ -6841,49 +6907,49 @@ static void ag_ra(void) case 150: ag_rp_150(); break; case 151: ag_rp_151(); break; case 152: ag_rp_152(); break; - case 153: V(0,double) = ag_rp_153(V(0,int)); break; - case 154: V(0,double) = ag_rp_154(V(0,double)); break; - case 155: V(0,int) = ag_rp_155(V(0,int)); break; - case 156: V(0,int) = ag_rp_156(); break; - case 157: V(0,int) = ag_rp_157(); break; - case 158: V(0,int) = ag_rp_158(); break; - case 159: V(0,int) = ag_rp_159(); break; + case 153: ag_rp_153(); break; + case 154: ag_rp_154(); break; + case 155: ag_rp_155(); break; + case 156: ag_rp_156(); break; + case 157: V(0,double) = ag_rp_157(V(0,int)); break; + case 158: V(0,double) = ag_rp_158(V(0,double)); break; + case 159: V(0,int) = ag_rp_159(V(0,int)); break; case 160: V(0,int) = ag_rp_160(); break; case 161: V(0,int) = ag_rp_161(); break; case 162: V(0,int) = ag_rp_162(); break; case 163: V(0,int) = ag_rp_163(); break; case 164: V(0,int) = ag_rp_164(); break; - case 165: ag_rp_165(V(1,int)); break; - case 166: ag_rp_166(V(1,int)); break; - case 167: ag_rp_167(V(0,int)); break; - case 168: ag_rp_168(V(1,int)); break; - case 169: ag_rp_169(V(2,int)); break; + case 165: V(0,int) = ag_rp_165(); break; + case 166: V(0,int) = ag_rp_166(); break; + case 167: V(0,int) = ag_rp_167(); break; + case 168: V(0,int) = ag_rp_168(); break; + case 169: ag_rp_169(V(1,int)); break; case 170: ag_rp_170(V(1,int)); break; - case 171: ag_rp_171(V(1,int)); break; + case 171: ag_rp_171(V(0,int)); break; case 172: ag_rp_172(V(1,int)); break; - case 173: ag_rp_173(V(1,int)); break; + case 173: ag_rp_173(V(2,int)); break; case 174: ag_rp_174(V(1,int)); break; case 175: ag_rp_175(V(1,int)); break; case 176: ag_rp_176(V(1,int)); break; case 177: ag_rp_177(V(1,int)); break; - case 178: V(0,int) = ag_rp_178(V(1,int)); break; - case 179: V(0,int) = ag_rp_179(V(1,int), V(2,int)); break; - case 180: V(0,int) = ag_rp_180(); break; - case 181: V(0,int) = ag_rp_181(V(0,int)); break; - case 182: V(0,int) = ag_rp_182(); break; - case 183: V(0,int) = ag_rp_183(); break; + case 178: ag_rp_178(V(1,int)); break; + case 179: ag_rp_179(V(1,int)); break; + case 180: ag_rp_180(V(1,int)); break; + case 181: ag_rp_181(V(1,int)); break; + case 182: V(0,int) = ag_rp_182(V(1,int)); break; + case 183: V(0,int) = ag_rp_183(V(1,int), V(2,int)); break; case 184: V(0,int) = ag_rp_184(); break; - case 185: V(0,int) = ag_rp_185(); break; + case 185: V(0,int) = ag_rp_185(V(0,int)); break; case 186: V(0,int) = ag_rp_186(); break; case 187: V(0,int) = ag_rp_187(); break; case 188: V(0,int) = ag_rp_188(); break; - case 189: V(0,double) = ag_rp_189(); break; - case 190: V(0,double) = ag_rp_190(V(1,int)); break; - case 191: V(0,double) = ag_rp_191(V(0,double), V(1,int)); break; - case 192: ag_rp_192(); break; - case 193: ag_rp_193(); break; - case 194: ag_rp_194(); break; - case 195: ag_rp_195(); break; + case 189: V(0,int) = ag_rp_189(); break; + case 190: V(0,int) = ag_rp_190(); break; + case 191: V(0,int) = ag_rp_191(); break; + case 192: V(0,int) = ag_rp_192(); break; + case 193: V(0,double) = ag_rp_193(); break; + case 194: V(0,double) = ag_rp_194(V(1,int)); break; + case 195: V(0,double) = ag_rp_195(V(0,double), V(1,int)); break; case 196: ag_rp_196(); break; case 197: ag_rp_197(); break; case 198: ag_rp_198(); break; @@ -6964,11 +7030,11 @@ static void ag_ra(void) case 273: ag_rp_273(); break; case 274: ag_rp_274(); break; case 275: ag_rp_275(); break; - case 276: ag_rp_276(V(2,int)); break; + case 276: ag_rp_276(); break; case 277: ag_rp_277(); break; case 278: ag_rp_278(); break; case 279: ag_rp_279(); break; - case 280: ag_rp_280(); break; + case 280: ag_rp_280(V(2,int)); break; case 281: ag_rp_281(); break; case 282: ag_rp_282(); break; case 283: ag_rp_283(); break; @@ -7017,6 +7083,10 @@ static void ag_ra(void) case 326: ag_rp_326(); break; case 327: ag_rp_327(); break; case 328: ag_rp_328(); break; + case 329: ag_rp_329(); break; + case 330: ag_rp_330(); break; + case 331: ag_rp_331(); break; + case 332: ag_rp_332(); break; } } @@ -7081,6 +7151,7 @@ const char *const a85parse_token_names[706] = { "\"EQU\"", "equation", "\"SET\"", + "\"=\"", "\"INCLUDE\"", "\"INCL\"", "", @@ -7104,6 +7175,9 @@ const char *const a85parse_token_names[706] = { "\"ELSE\"", "\"ENDIF\"", "\"ERROR\"", + "\"PRINT\"", + "\"PRINTF\"", + "','", "\"UNDEF\"", "\"DEFINE\"", "macro", @@ -7141,8 +7215,6 @@ const char *const a85parse_token_names[706] = { "\"STKLN\"", "\"ECHO\"", "\"FILL\"", - "\"PRINTF\"", - "','", "\"END\"", "\"MSFIRST\"", "\"LSFIRST\"", @@ -7189,7 +7261,6 @@ const char *const a85parse_token_names[706] = { "", "\"EQ\"", "\"==\"", - "\"=\"", "", "\"NE\"", "\"!=\"", @@ -7444,7 +7515,6 @@ const char *const a85parse_token_names[706] = { "", "", "", - "", "'\\n'", "\"//\"", "';'", @@ -7454,6 +7524,7 @@ const char *const a85parse_token_names[706] = { "'.'", "\"EQU\"", "\"SET\"", + "\"=\"", "\"INCLUDE\"", "\"INCL\"", "literal string", @@ -7474,6 +7545,9 @@ const char *const a85parse_token_names[706] = { "\"ELSE\"", "\"ENDIF\"", "\"ERROR\"", + "\"PRINT\"", + "','", + "\"PRINTF\"", "\"UNDEF\"", "\"DEFINE\"", "')'", @@ -7500,8 +7574,6 @@ const char *const a85parse_token_names[706] = { "\"STKLN\"", "\"ECHO\"", "\"FILL\"", - "','", - "\"PRINTF\"", "\"END\"", "\"MSFIRST\"", "\"LSFIRST\"", @@ -7517,7 +7589,6 @@ const char *const a85parse_token_names[706] = { "\"INPAGE\"", "\"EQ\"", "\"==\"", - "\"=\"", "\"NE\"", "\"!=\"", "\"GE\"", @@ -7703,7 +7774,6 @@ const char *const a85parse_token_names[706] = { "\"LJMP\"", "", "'\\\"'", - "", "'$'", "'\\''", "'0'", @@ -7733,68 +7803,69 @@ const char *const a85parse_token_names[706] = { static const unsigned short ag_ctn[] = { - 0,0, 0,0, 0,0, 64,1,428,1, 53,1, 35,1, 35,1, 35,1, 35,1, 35,1, 0,0, - 66,1, 66,1, 66,1, 0,0, 0,0, 66,1, 66,1, 0,0, 66,1, 66,1, 0,0, 66,1, - 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 66,1, 0,0, 0,0, - 35,2, 47,1, 0,0, 39,1, 40,1, 39,1, 39,1, 35,2, 62,1,265,1,265,1,265,1, - 265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,341,1, - 339,1,337,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, - 260,1,260,1,260,1,260,1,260,1,260,1,265,1,265,1,265,1,265,1,265,1,265,1, - 265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1, - 265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,264,1, - 341,1,339,1,337,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, - 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, - 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, - 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, - 260,1,260,1,260,1,259,1,259,1,259,1,259,1,258,1,258,1,257,1,257,1,257,1, - 256,1,256,1,256,1,256,1,256,1,256,1,256,1,256,1,256,1,256,1,256,1,256,1, - 256,1,264,1,263,1,262,1,261,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, - 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, - 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, - 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, - 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,259,1,259,1,259,1, - 259,1,258,1,258,1,257,1,257,1,257,1,256,1,256,1,256,1,256,1,256,1,256,1, - 256,1,256,1,256,1,256,1,256,1,256,1,256,1, 0,0, 32,1, 84,1, 30,1, 32,1, - 33,1, 33,1, 35,2, 66,2, 66,2,434,1, 0,0, 66,2, 66,2, 66,2, 66,2,537,1, - 218,1,217,1, 6,1, 6,1, 7,1, 15,1,537,1,490,1,218,1,217,1, 6,1,205,1, - 206,1, 0,0,206,1,206,1,206,1,206,1,206,1,206,1,206,1,206,1,206,1,205,1, - 0,0, 0,0,206,1,206,1,206,1,206,1,206,1,206,1,206,1,206,1,206,1,206,1, - 206,1, 29,1, 0,0, 29,1, 0,0,197,1, 29,1, 29,1, 29,1, 29,1, 25,1, 27,1, - 24,1, 23,1, 28,1, 26,1, 26,1, 76,1, 76,1, 66,2, 66,2, 66,2, 0,0, 66,2, - 0,0, 66,2, 0,0, 66,2, 0,0, 66,2, 0,0, 66,2,435,1, 0,0, 66,2, 66,2, - 0,0, 35,3, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0,0, 0,0, 0,0, 65,1,428,1, 53,1, 35,1, 35,1, 35,1, 35,1, 35,1, 0,0, + 67,1, 67,1, 0,0, 0,0, 67,1, 0,0, 0,0, 67,1, 67,1, 0,0, 67,1, 67,1, + 0,0, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, + 67,1, 67,1, 0,0, 0,0, 35,2, 47,1, 0,0, 39,1, 40,1, 39,1, 39,1, 35,2, + 63,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1, + 266,1,266,1,266,1,342,1,340,1,338,1,261,1,261,1,261,1,261,1,261,1,261,1, + 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,266,1,266,1, + 266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1, + 266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1, + 266,1,266,1,266,1,265,1,342,1,340,1,338,1,261,1,261,1,261,1,261,1,261,1, + 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, + 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, + 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, + 261,1,261,1,261,1,261,1,261,1,261,1,261,1,260,1,260,1,260,1,260,1,259,1, + 259,1,258,1,258,1,258,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1, + 257,1,257,1,257,1,257,1,257,1,265,1,264,1,263,1,262,1,261,1,261,1,261,1, + 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, + 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, + 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, + 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, + 261,1,260,1,260,1,260,1,260,1,259,1,259,1,258,1,258,1,258,1,257,1,257,1, + 257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1, 0,0, + 32,1, 88,1, 30,1, 32,1, 33,1, 33,1, 35,2, 67,2, 67,2,435,1, 0,0, 67,2, + 67,2, 67,2, 67,2, 67,2, 67,2,538,1,219,1,218,1, 6,1, 6,1, 7,1, 15,1, + 538,1,492,1,219,1,218,1, 6,1,206,1,207,1, 0,0,207,1,207,1,207,1,207,1, + 207,1,207,1,207,1,207,1,207,1,206,1, 0,0, 0,0,207,1,207,1,207,1,207,1, + 207,1,207,1,207,1,207,1,207,1,207,1,207,1, 29,1, 0,0, 29,1, 0,0,198,1, + 29,1, 29,1, 29,1, 29,1, 25,1, 27,1, 24,1, 23,1, 28,1, 26,1, 26,1, 77,1, + 77,1, 67,2, 67,2, 67,2, 0,0, 67,2, 0,0, 67,2, 0,0, 67,2, 0,0, 67,2, + 0,0, 67,2,436,1, 0,0, 67,2, 67,2, 0,0, 35,3, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, - 0,0, 0,0, 0,0, 0,0, 0,0, 39,2, 39,2, 33,1, 35,3, 62,2,341,2,339,2, - 337,2,264,2,263,2,262,2,261,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2, - 260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2, - 260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2, - 260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2, - 260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,259,2,259,2,259,2, - 259,2,258,2,258,2,257,2,257,2,257,2,256,2,256,2,256,2,256,2,256,2,256,2, - 256,2,256,2,256,2,256,2,256,2,256,2,256,2, 84,2, 0,0, 0,0, 32,2, 0,0, - 33,2, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, - 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, - 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, - 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 0,0, 33,2, 33,2, 0,0, 0,0, 35,3, - 66,3, 66,3, 0,0, 66,3, 66,3, 6,2, 16,1, 15,2, 0,0, 0,0,206,2,206,2, - 206,2,206,2,206,2,206,2,206,2,206,2,206,2,206,2,206,2,197,2, 7,1, 0,0, - 25,2, 0,0, 25,2, 25,2, 25,2, 25,2, 27,2, 27,2, 0,0, 24,2, 0,0, 24,2, - 0,0, 24,2, 0,0, 24,2, 0,0, 23,2, 23,2, 0,0, 28,2, 28,2, 0,0, 26,2, - 26,2, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, - 0,0, 0,0, 66,3, 66,3, 66,3, 66,3, 66,3, 66,3, 66,3, 66,3,435,2, 66,3, - 66,3, 0,0, 35,4, 35,4, 35,4, 0,0, 35,4, 0,0, 35,4, 35,4, 22,1, 62,3, - 253,1,253,1,253,1, 0,0, 0,0,263,3,262,3,261,3,250,1,250,1,256,3, 0,0, - 483,1, 0,0, 0,0, 6,1,490,1, 32,3,483,1, 33,3, 33,3,111,1,111,1,111,1, - 0,0, 0,0, 85,1, 0,0, 0,0, 0,0, 15,3,206,3,206,3,206,3,206,3,206,3, - 206,3,206,3,206,3,206,3,206,3,206,3,197,3, 25,3, 25,3, 25,3, 25,3, 25,3, - 27,3, 27,3, 24,3, 24,3, 24,3, 24,3, 23,3, 23,3, 28,3, 28,3, 26,3, 26,3, - 66,4, 35,5, 35,5, 35,5, 35,5, 35,5, 62,4,263,4,262,4,261,4,256,4, 0,0, - 0,0, 0,0, 32,1, 32,1,483,2, 33,4, 0,0,111,2, 0,0, 0,0, 66,5, 0,0, - 0,0,206,4,206,4,206,4,206,4,206,4,206,4,206,4,206,4,206,4,206,4,206,4, - 197,4, 25,1, 25,1, 27,1, 27,1, 27,1, 27,1, 24,1, 24,1, 23,1, 23,1, 28,1, - 28,1, 66,5, 35,6, 35,6,256,5, 15,3, 0,0, 33,5,111,3,535,1, 0,0,206,5, - 256,6,206,6 + 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 39,2, 39,2, + 0,0, 35,3, 33,1, 35,3, 63,2,342,2,340,2,338,2,265,2,264,2,263,2,262,2, + 261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2, + 261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2, + 261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2, + 261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2, + 261,2,261,2,261,2,261,2,260,2,260,2,260,2,260,2,259,2,259,2,258,2,258,2, + 258,2,257,2,257,2,257,2,257,2,257,2,257,2,257,2,257,2,257,2,257,2,257,2, + 257,2,257,2, 88,2, 0,0, 0,0, 32,2, 0,0, 33,2, 0,0, 33,2, 0,0, 0,0, + 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 33,2, 33,2, 0,0, 33,2, 0,0, 33,2, + 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, + 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, 0,0, 33,2, 0,0, 0,0, + 0,0, 0,0, 33,2, 33,2, 0,0, 0,0, 35,3, 67,3, 67,3, 0,0, 67,3, 67,3, + 67,3, 67,3, 6,2, 16,1, 15,2, 0,0, 0,0,207,2,207,2,207,2,207,2,207,2, + 207,2,207,2,207,2,207,2,207,2,207,2,198,2, 7,1, 0,0, 25,2, 0,0, 25,2, + 25,2, 25,2, 25,2, 27,2, 27,2, 0,0, 24,2, 0,0, 24,2, 0,0, 24,2, 0,0, + 24,2, 0,0, 23,2, 23,2, 0,0, 28,2, 28,2, 0,0, 26,2, 26,2, 0,0, 0,0, + 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 67,3, 67,3, + 67,3, 67,3, 67,3, 67,3, 67,3, 67,3,436,2, 67,3, 67,3, 0,0, 35,4, 35,4, + 35,4, 35,4, 0,0, 35,4, 0,0, 35,4, 35,4, 22,1, 63,3,254,1,254,1,254,1, + 0,0, 0,0,264,3,263,3,262,3,251,1,251,1,257,3, 0,0,485,1, 0,0, 0,0, + 6,1,492,1, 32,3,485,1, 33,3, 33,3,115,1,115,1,115,1, 0,0, 0,0, 89,1, + 0,0, 0,0, 0,0, 67,4, 15,3,207,3,207,3,207,3,207,3,207,3,207,3,207,3, + 207,3,207,3,207,3,207,3,198,3, 25,3, 25,3, 25,3, 25,3, 25,3, 27,3, 27,3, + 24,3, 24,3, 24,3, 24,3, 23,3, 23,3, 28,3, 28,3, 26,3, 26,3, 67,4, 35,5, + 35,5, 35,5, 35,5, 35,5, 35,5, 63,4,264,4,263,4,262,4,257,4, 0,0, 0,0, + 0,0, 32,1, 32,1,485,2, 33,4, 0,0,115,2, 0,0, 0,0, 67,5, 0,0, 0,0, + 67,5,207,4,207,4,207,4,207,4,207,4,207,4,207,4,207,4,207,4,207,4,207,4, + 198,4, 25,1, 25,1, 27,1, 27,1, 27,1, 27,1, 24,1, 24,1, 23,1, 23,1, 28,1, + 28,1, 67,5, 35,6, 35,6,257,5, 15,3, 0,0, 33,5,115,3, 67,6,536,1, 0,0, + 207,5,257,6,207,6 }; #ifndef MISSING_FORMAT @@ -7928,7 +7999,7 @@ static void ag_error_resynch(void) { if ((PCB).exit_flag != AG_RUNNING_CODE) return; while (1) { ag_k = ag_sbt[(PCB).sn]; - while (ag_tstt[ag_k] != 63 && ag_tstt[ag_k]) ag_k++; + while (ag_tstt[ag_k] != 64 && ag_tstt[ag_k]) ag_k++; if (ag_tstt[ag_k] || (PCB).ssx == 0) break; (PCB).sn = (PCB).ss[--(PCB).ssx]; } @@ -7938,7 +8009,7 @@ static void ag_error_resynch(void) { return; } ag_k = ag_sbt[(PCB).sn]; - while (ag_tstt[ag_k] != 63 && ag_tstt[ag_k]) ag_k++; + while (ag_tstt[ag_k] != 64 && ag_tstt[ag_k]) ag_k++; (PCB).ag_ap = ag_pstt[ag_k]; (ag_er_procs_scan[ag_astt[ag_k]])(); while (1) { @@ -8156,7 +8227,7 @@ static int ag_action_3_proc(void) { static int ag_action_8_proc(void) { int ag_k = ag_sbt[(PCB).sn]; - while (ag_tstt[ag_k] != 63 && ag_tstt[ag_k]) ag_k++; + while (ag_tstt[ag_k] != 64 && ag_tstt[ag_k]) ag_k++; if (ag_tstt[ag_k] == 0) ag_undo(); (PCB).rx = 0; ag_error_resynch(); diff --git a/src/a85parse.h b/src/a85parse.h index 5fc294f..603aa23 100644 --- a/src/a85parse.h +++ b/src/a85parse.h @@ -1,5 +1,5 @@ -#ifndef A85PARSE_H_1359224795 -#define A85PARSE_H_1359224795 +#ifndef A85PARSE_H_1359807348 +#define A85PARSE_H_1359807348 typedef union { long alignment; @@ -23,32 +23,32 @@ typedef enum { a85parse_eof_token = 38, a85parse_comment_token, a85parse_cstyle_comment_token, a85parse_any_text_char_token = 42, a85parse_cstyle_comment_head_token = 47, a85parse_preproc_inst_token = 53, - a85parse_equation_token = 57, a85parse_cdseg_statement_token = 62, + a85parse_equation_token = 57, a85parse_cdseg_statement_token = 63, a85parse_error_token, a85parse_preproc_start_token, - a85parse_preprocessor_directive_token = 66, a85parse_condition_token = 76, - a85parse_macro_token = 84, a85parse_macro_expansion_token, - a85parse_expression_list_token = 87, a85parse_define_chars_token = 90, - a85parse_cdseg_statement_start_token = 92, a85parse_name_list_token = 111, - a85parse_literal_alpha_token = 131, a85parse_digit_token = 136, - a85parse_asm_incl_char_token, a85parse_str_escape_char_token = 140, - a85parse_hex_digit_token = 154, a85parse_condition_start_token = 164, - a85parse_primary_exp_token = 197, a85parse_value_token = 205, - a85parse_function_token, a85parse_binary_integer_token = 217, - a85parse_octal_integer_token, a85parse_stack_register_token = 250, - a85parse_bd_register_token = 252, a85parse_page_register_token, - a85parse_eight_bit_reg_inst_token = 256, + a85parse_preprocessor_directive_token = 67, a85parse_condition_token = 77, + a85parse_macro_token = 88, a85parse_macro_expansion_token, + a85parse_expression_list_token = 91, a85parse_define_chars_token = 94, + a85parse_cdseg_statement_start_token = 96, a85parse_name_list_token = 115, + a85parse_literal_alpha_token = 133, a85parse_digit_token = 138, + a85parse_asm_incl_char_token, a85parse_str_escape_char_token = 142, + a85parse_hex_digit_token = 156, a85parse_condition_start_token = 166, + a85parse_primary_exp_token = 198, a85parse_value_token = 206, + a85parse_function_token, a85parse_binary_integer_token = 218, + a85parse_octal_integer_token, a85parse_stack_register_token = 251, + a85parse_bd_register_token = 253, a85parse_page_register_token, + a85parse_eight_bit_reg_inst_token = 257, a85parse_sixteen_bit_reg_inst_token, a85parse_bd_reg_inst_token, a85parse_stack_reg_inst_token, a85parse_immediate_operand_inst_token, a85parse_lxi_inst_token, a85parse_mvi_inst_token, a85parse_spi_inst_token, a85parse_rst_inst_token, a85parse_no_arg_inst_token, - a85parse_lxi_inst_start_token = 337, a85parse_mvi_inst_start_token = 339, - a85parse_spi_inst_start_token = 341, a85parse_rst_arg_token = 344, - a85parse_label_token = 428, a85parse_literal_string_token = 434, + a85parse_lxi_inst_start_token = 338, a85parse_mvi_inst_start_token = 340, + a85parse_spi_inst_start_token = 342, a85parse_rst_arg_token = 345, + a85parse_label_token = 428, a85parse_literal_string_token = 435, a85parse_include_string_token, a85parse_asm_include_token, - a85parse_literal_name_nows_token = 441, - a85parse_singlequote_string_token = 483, a85parse_integer_token = 490, - a85parse_literal_name_token = 535, a85parse_real_token = 537, - a85parse_register_8_bit_token = 593, a85parse_register_16_bit_token = 607 + a85parse_literal_name_nows_token = 442, + a85parse_singlequote_string_token = 485, a85parse_integer_token = 492, + a85parse_literal_name_token = 536, a85parse_real_token = 538, + a85parse_register_8_bit_token = 594, a85parse_register_16_bit_token = 608 } a85parse_token_type; typedef struct a85parse_pcb_struct{ diff --git a/src/a85parse.syn b/src/a85parse.syn index fbee7a9..db9ae5b 100644 --- a/src/a85parse.syn +++ b/src/a85parse.syn @@ -41,7 +41,7 @@ label char = '$' + '?' + '{' + '}' string char = ~eof - ('"' + '\\' + '\n') rst arg = '0-7' asm incl char = 'a-z' + 'A-Z' + '0-9' + '_' + '.' + '\\' + '/' -define chars = ~eof - newline - '\\' - '#' +define chars = ~eof - newline - '\\' PLUS = '+' MINUS = '-' @@ -92,6 +92,7 @@ statement -> preproc inst -> label, WS?..., '.'?, "equ", equation, WS?..., comment = gAsm->equate((const char *) -1); -> label, WS?..., '.'?, "set", equation, WS?..., comment = gAsm->directive_set((const char *) -1); + -> label, WS?..., "=", equation, WS?..., comment = gAsm->directive_set((const char *) -1); -> WS?..., '.'?, {"include" | "incl"}, literal string, WS?..., comment = gAsm->include(ss[ss_idx--]); -> WS?..., '.'?, {"include" | "incl"}, include string, @@ -123,6 +124,9 @@ preprocessor directive -> "else", WS?..., comment = gAsm->preproc_else(); -> "endif", WS?..., comment = gAsm->preproc_endif(); -> "error", literal string, WS?..., comment = {if (gAsm->preproc_error(ss[ss_idx--])) gAbort = TRUE;} + -> "print", literal string, WS?..., comment = gAsm->directive_printf(ss[ss_idx--], FALSE); + -> "printf", literal string, + ',', WS?..., equation, WS?..., comment = gAsm->directive_printf(ss[ss_idx--]); -> "undef", literal name nows, WS?..., comment = gAsm->preproc_undef(ss[ss_idx--]); -> "define", macro, WS?..., macro expansion, WS?..., comment = { if (gMacroStack[ms_idx] != 0) { delete gMacroStack[ms_idx]; \ @@ -188,6 +192,7 @@ expression -> '.'?, "echo", equation = gAsm->directive_echo(); -> '.'?, "echo", literal string = gAsm->directive_echo(ss[ss_idx--]); -> '.'?, "fill", WS?..., expression list = gAsm->directive_fill(); + -> '.'?, "print", literal string = gAsm->directive_printf(ss[ss_idx--], FALSE); -> '.'?, "printf", literal string, ',', WS?..., equation = gAsm->directive_printf(ss[ss_idx--]); -> '.'?, "end" = gAsm->directive_end(""); diff --git a/src/assemble.cpp b/src/assemble.cpp index 675a3ac..6947ade 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -1899,7 +1899,7 @@ void VTAssembler::directive_echo(const char *string) This function is called when a printf directive is encountered ============================================================================ */ -void VTAssembler::directive_printf(const char *string) +void VTAssembler::directive_printf(const char *string, int hasEquation) { char str[256]; double value = 0.0; @@ -1916,7 +1916,7 @@ void VTAssembler::directive_printf(const char *string) return; } - // Find the locaiton of the format specifier + // Find the location of the format specifier ptr = string; while ((*ptr != '%') && (*ptr != '\0')) ptr++; @@ -1930,26 +1930,34 @@ void VTAssembler::directive_printf(const char *string) // Try to evaluate the equation. Note that we may not be able to // successfully evaluate it at this point because it may contain // a forward reference, so don't report any errors yet. - if (Evaluate(gEq, &value, 0)) + if (hasEquation) { - if (fmtCh == 'f') - sprintf(str, string, value); + if (Evaluate(gEq, &value, 0)) + { + if (fmtCh == 'f') + sprintf(str, string, value); + else + { + lval = (int) value; + sprintf(str, string, lval); + } + } else { - lval = (int) value; - sprintf(str, string, lval); + strncpy(str, string, (int) (ptr - string)); + strcat(str, "#UNDEFINED"); + if (*ptr != '\0') + strcat(str, ptr + 2 + fmtDigits); } + + if (m_pStdoutFunc != NULL) + m_pStdoutFunc(m_pStdoutContext, (const char *) str); } else { - strncpy(str, string, (int) (ptr - string)); - strcat(str, "#UNDEFINED"); - if (*ptr != '\0') - strcat(str, ptr + 2 + fmtDigits); + if (m_pStdoutFunc != NULL) + m_pStdoutFunc(m_pStdoutContext, string); } - - if (m_pStdoutFunc != NULL) - m_pStdoutFunc(m_pStdoutContext, (const char *) str); } /* diff --git a/src/assemble.h b/src/assemble.h index 53bda8f..cd70798 100644 --- a/src/assemble.h +++ b/src/assemble.h @@ -408,7 +408,7 @@ class VTAssembler : public VTObject void directive_echo(void); void directive_echo(const char *msg); void directive_fill(void); - void directive_printf(const char *fmt); + void directive_printf(const char *fmt, int hasEquation = 1); void directive_extern(void); void directive_endian(int msbFirst); void directive_org(); diff --git a/src/io.c b/src/io.c index 66451b8..1bd6597 100644 --- a/src/io.c +++ b/src/io.c @@ -264,7 +264,7 @@ void update_keys(void) } } - if ((gSpecialKeys & (MT_GRAPH | MT_CODE | MT_SHIFT) == 0) && !gCapture) + if (((gSpecialKeys & (MT_GRAPH | MT_CODE | MT_SHIFT)) == 0) && !gCapture) { FILE* fd; int d, col, row; From c039ddc9b55b0f5c2e49503f5f0e62f84720ddc0 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 2 Feb 2013 17:41:21 +0000 Subject: [PATCH 208/327] Added support for REX3 state machine for PC8201. --- src/memory.c | 75 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/src/memory.c b/src/memory.c index 1bb2f36..2f9dce4 100644 --- a/src/memory.c +++ b/src/memory.c @@ -73,6 +73,8 @@ unsigned char gRexModel = 0; /* Rex model */ unsigned char gRexFlashSel = 1; /* Rex Flash enable signal */ int gRexKeyState = 0; /* Rex Key State */ int gRexFlashPA = 0; /* REX Flash Address Line during programing */ +unsigned char gRex3Data = 0; /* REX3 data to write for commands 2,5 and 6 */ +unsigned char gRex3Cmd = 0; /* REX3 command saved for state 6 */ amd_flash_t gRexFlash = { FLASH_STATE_RO, 0, FALSE, 0 }; unsigned char gRexKeyTable[6] = { 184, 242, 52, 176, 49, 191 }; int gIndex[65536]; @@ -2913,11 +2915,24 @@ unsigned char rex_read(unsigned short address) gRexState = address & 0x07; return gRexReturn; - case 1: /* Set Sector CMD */ case 2: /* Send AAA,AA CMD */ - case 4: /* Read from flash */ case 5: /* Send 555,55 CMD */ case 6: /* Send PA, PD */ + /* For REX2 (PC8201), the state machine had to change because of no ALE. + In this case, we transition to state 2 to await the data, then to state + 6 to await the address. */ + if (gModel == MODEL_PC8201) + { + // Go to state 2 + gRexState = 2; + gRex3Cmd = address & 0x07; + break; + } + + // Fall through + + case 1: /* Set Sector CMD */ + case 4: /* Read from flash */ gRexState = address & 0x07; gRexFlashPA = address & 0xFF; break; @@ -2949,11 +2964,21 @@ unsigned char rex_read(unsigned short address) break; case 2: /* Send AAA, AD to Flash */ - /* Write to the REX Flash object. LSB of address is actually data */ - amd_flash_write(&gRexFlash, gRexSector | gRexFlashPA, address & 0xFF); + if (gModel == MODEL_PC8201) + { + /* For REX3 (PC8201), we save the write data during state 2, then go to + state 6 to await the address */ + gRex3Data = address & 0xFF; + gRexState = 6; + } + else + { + /* Write to the REX Flash object. LSB of address is actually data */ + amd_flash_write(&gRexFlash, gRexSector | gRexFlashPA, address & 0xFF); - /* Back to state 0 for next command */ - gRexState = 0; + /* Back to state 0 for next command */ + gRexState = 0; + } break; case 3: @@ -2997,11 +3022,41 @@ unsigned char rex_read(unsigned short address) break; case 6: /* Send PA,PD to flash, first we receive PA */ - /* Save the address from this read as our Flash PA */ - gRexFlashPA = address & 0x7FFF; + /* Test for REX3 (PC8201) */ + if (gModel == MODEL_PC8201) + { + /* For REX3, we perform the write during state 6 */ + switch (gRex3Cmd) + { + case 2: + gRexFlashPA = gRexSector | (address & 0xFF); + break; + case 5: + gRexFlashPA = address & 0xFF; + break; + case 6: + gRexFlashPA = gRexSector | (address & 0x7FFF); + break; + default: + gRexFlashPA = 0; + break; + } + + /* Write to the REX Flash object. LSB of address is actually data */ + amd_flash_write(&gRexFlash, gRexFlashPA, gRex3Data); + + /* Back to state 0 for next command */ + gRexState = 0; + } + else + { + /* Save the address from this read as our Flash PA */ + gRexFlashPA = address & 0x7FFF; + + /* Go to State 2 to await the data */ + gRexState = 2; + } - /* Go to State 2 to await the data */ - gRexState = 2; break; } return (unsigned char) (address & 0xFF); From 4838e9e9cf530162de64832350f17235560661d7 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 5 Feb 2013 01:20:58 +0000 Subject: [PATCH 209/327] MAJOR modifications to CPU Registers window to implement program tracing with scrolling, configurable font sizes and trace depths, auto-redraw vs manual redraw button, saving of breakpoints and window position when VirtualT terminates, resizeable window, saving trace data to a file, keyboard shortcuts. Added saving and restoring of opened windows when VirtualT is shutdown and restarted. --- release.txt | 9 + src/a85parse.cpp | 7868 ++++++++++++++++++++++--------------------- src/a85parse.h | 10 +- src/a85parse.syn | 10 +- src/cpuregs.cpp | 2740 ++++++++++----- src/cpuregs.h | 277 +- src/disassemble.cpp | 38 + src/disassemble.h | 1 + src/display.cpp | 69 +- src/display.h | 1 + src/ide.cpp | 36 +- src/ide.h | 3 + src/m100emu.c | 1 + src/memedit.cpp | 48 +- src/memedit.h | 4 +- src/memory.c | 74 +- 16 files changed, 6311 insertions(+), 4878 deletions(-) diff --git a/release.txt b/release.txt index 239b1dd..d478a92 100644 --- a/release.txt +++ b/release.txt @@ -31,6 +31,15 @@ v1.6 7. Made the FX80 Virtual Paper display resizeable. +8. MAJOR modifications to CPU Registers window to implement program tracing with + scrolling, configurable font sizes and trace depths, auto-redraw vs manual + redraw button, saving of breakpoints and window position when VirtualT terminates, + resizeable window, saving trace data to a file, keyboard shortcuts. + +9. Added saving and restoring of opened windows when VirtualT is shutdown and restarted. + +10. Now reports error if REX / ReMem memory cannot be loaded / saved. + ==================== v1.5 July 9th, 2011 ==================== diff --git a/src/a85parse.cpp b/src/a85parse.cpp index 4b100e7..6b25138 100644 --- a/src/a85parse.cpp +++ b/src/a85parse.cpp @@ -17,11 +17,11 @@ */ -#ifndef A85PARSE_H_1359807348 +#ifndef A85PARSE_H_1359819567 #include "a85parse.h" #endif -#ifndef A85PARSE_H_1359807348 +#ifndef A85PARSE_H_1359819567 #error Mismatched header file #endif @@ -39,7 +39,7 @@ a85parse_pcb_type a85parse_pcb; #define PCB a85parse_pcb -/* Line 700, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 706, C:/Projects/VirtualT/src/a85parse.syn */ // Embedded C #include "MString.h" // Include MString header @@ -510,18 +510,22 @@ static int agConvertCase(int c) { #define ag_rp_22() (gAsm->preproc_endif()) static void ag_rp_23(void) { -/* Line 126, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 128, C:/Projects/VirtualT/src/a85parse.syn */ if (gAsm->preproc_error(ss[ss_idx--])) gAbort = TRUE; } #define ag_rp_24() (gAsm->directive_printf(ss[ss_idx--], FALSE)) -#define ag_rp_25() (gAsm->directive_printf(ss[ss_idx--])) +#define ag_rp_25() (gAsm->directive_printf("%d")) -#define ag_rp_26() (gAsm->preproc_undef(ss[ss_idx--])) +#define ag_rp_26() (gAsm->directive_printf(ss[ss_idx--], FALSE)) -static void ag_rp_27(void) { -/* Line 132, C:/Projects/VirtualT/src/a85parse.syn */ +#define ag_rp_27() (gAsm->directive_printf(ss[ss_idx--])) + +#define ag_rp_28() (gAsm->preproc_undef(ss[ss_idx--])) + +static void ag_rp_29(void) { +/* Line 136, C:/Projects/VirtualT/src/a85parse.syn */ if (gMacroStack[ms_idx] != 0) { delete gMacroStack[ms_idx]; \ gMacroStack[ms_idx] = 0; } \ gMacro = gMacroStack[--ms_idx]; \ @@ -530,8 +534,8 @@ static void ag_rp_27(void) { gMacroStack[ms_idx] = 0; gDefine = 0; } -static void ag_rp_28(void) { -/* Line 146, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_30(void) { +/* Line 150, C:/Projects/VirtualT/src/a85parse.syn */ gMacro->m_ParamList = gExpList; \ gMacro->m_Name = ss[ss_idx--]; \ gExpList = new VTObArray; \ @@ -541,307 +545,311 @@ static void ag_rp_28(void) { gMacro = new CMacro; } -static void ag_rp_29(void) { -/* Line 153, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_31(void) { +/* Line 157, C:/Projects/VirtualT/src/a85parse.syn */ gMacro->m_Name = ss[ss_idx--]; gMacroStack[ms_idx++] = gMacro; \ if (gAsm->preproc_macro()) \ PCB.reduction_token = a85parse_WS_token; \ gMacro = new CMacro; } -static void ag_rp_30(int c) { -/* Line 159, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_32(int c) { +/* Line 163, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_31(int c) { -/* Line 160, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_33(int c) { +/* Line 164, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_32(void) { -/* Line 161, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_34(void) { +/* Line 165, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '\n'; ss[ss_idx][ss_len] = 0; } -static void ag_rp_33(void) { -/* Line 164, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_35(void) { +/* Line 168, C:/Projects/VirtualT/src/a85parse.syn */ page = 0; seg = CSEG; } -static void ag_rp_34(void) { -/* Line 165, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_36(void) { +/* Line 169, C:/Projects/VirtualT/src/a85parse.syn */ page = 0; seg = DSEG; } -#define ag_rp_35(p) (page = p) - -#define ag_rp_36() (gAsm->pragma_list()) - -#define ag_rp_37() (gAsm->pragma_hex()) +#define ag_rp_37(p) (page = p) -#define ag_rp_38() (gAsm->pragma_verilog()) +#define ag_rp_38() (gAsm->pragma_list()) -#define ag_rp_39() (gAsm->pragma_entry(ss[ss_idx--])) +#define ag_rp_39() (gAsm->pragma_hex()) -#define ag_rp_40() (gAsm->pragma_extended()) +#define ag_rp_40() (gAsm->pragma_verilog()) -#define ag_rp_41() (gAsm->directive_org()) +#define ag_rp_41() (gAsm->pragma_entry(ss[ss_idx--])) -#define ag_rp_42() (gAsm->directive_aseg()) +#define ag_rp_42() (gAsm->pragma_extended()) -#define ag_rp_43() (gAsm->directive_ds()) +#define ag_rp_43() (gAsm->directive_org()) -#define ag_rp_44() (gAsm->directive_db()) +#define ag_rp_44() (gAsm->directive_aseg()) -#define ag_rp_45() (gAsm->directive_dw()) +#define ag_rp_45() (gAsm->directive_ds()) -#define ag_rp_46() (gAsm->directive_public()) +#define ag_rp_46() (gAsm->directive_db()) -#define ag_rp_47() (gAsm->directive_extern()) +#define ag_rp_47() (gAsm->directive_dw()) -#define ag_rp_48() (gAsm->directive_extern()) +#define ag_rp_48() (gAsm->directive_public()) -#define ag_rp_49() (gAsm->directive_module(ss[ss_idx--])) +#define ag_rp_49() (gAsm->directive_extern()) -#define ag_rp_50() (gAsm->directive_name(ss[ss_idx--])) +#define ag_rp_50() (gAsm->directive_extern()) -#define ag_rp_51() (gAsm->directive_stkln()) +#define ag_rp_51() (gAsm->directive_module(ss[ss_idx--])) -#define ag_rp_52() (gAsm->directive_echo()) +#define ag_rp_52() (gAsm->directive_name(ss[ss_idx--])) -#define ag_rp_53() (gAsm->directive_echo(ss[ss_idx--])) +#define ag_rp_53() (gAsm->directive_stkln()) -#define ag_rp_54() (gAsm->directive_fill()) +#define ag_rp_54() (gAsm->directive_echo()) -#define ag_rp_55() (gAsm->directive_printf(ss[ss_idx--], FALSE)) +#define ag_rp_55() (gAsm->directive_echo(ss[ss_idx--])) -#define ag_rp_56() (gAsm->directive_printf(ss[ss_idx--])) +#define ag_rp_56() (gAsm->directive_fill()) -#define ag_rp_57() (gAsm->directive_end("")) +#define ag_rp_57() (gAsm->directive_printf(ss[ss_idx--], FALSE)) -#define ag_rp_58() (gAsm->directive_end(ss[ss_idx--])) +#define ag_rp_58() (gAsm->directive_printf("%d")) -#define ag_rp_59() (gAsm->directive_if()) +#define ag_rp_59() (gAsm->directive_printf(ss[ss_idx--], FALSE)) -#define ag_rp_60() (gAsm->directive_else()) +#define ag_rp_60() (gAsm->directive_printf(ss[ss_idx--])) -#define ag_rp_61() (gAsm->directive_endif()) +#define ag_rp_61() (gAsm->directive_end("")) -#define ag_rp_62() (gAsm->directive_endian(1)) +#define ag_rp_62() (gAsm->directive_end(ss[ss_idx--])) -#define ag_rp_63() (gAsm->directive_endian(0)) +#define ag_rp_63() (gAsm->directive_if()) -#define ag_rp_64() (gAsm->directive_title(ss[ss_idx--])) +#define ag_rp_64() (gAsm->directive_else()) -#define ag_rp_65() (gAsm->directive_title(ss[ss_idx--])) +#define ag_rp_65() (gAsm->directive_endif()) -#define ag_rp_66() (gAsm->directive_page(-1)) +#define ag_rp_66() (gAsm->directive_endian(1)) -#define ag_rp_67() (gAsm->directive_sym()) +#define ag_rp_67() (gAsm->directive_endian(0)) -#define ag_rp_68() (gAsm->directive_link(ss[ss_idx--])) +#define ag_rp_68() (gAsm->directive_title(ss[ss_idx--])) -#define ag_rp_69() (gAsm->directive_maclib(ss[ss_idx--])) +#define ag_rp_69() (gAsm->directive_title(ss[ss_idx--])) -#define ag_rp_70() (gAsm->directive_page(page)) +#define ag_rp_70() (gAsm->directive_page(-1)) -#define ag_rp_71() (page = 60) +#define ag_rp_71() (gAsm->directive_sym()) -#define ag_rp_72(n) (page = n) +#define ag_rp_72() (gAsm->directive_link(ss[ss_idx--])) -#define ag_rp_73() (expression_list_literal()) +#define ag_rp_73() (gAsm->directive_maclib(ss[ss_idx--])) -#define ag_rp_74() (expression_list_literal()) +#define ag_rp_74() (gAsm->directive_page(page)) -#define ag_rp_75() (expression_list_equation()) +#define ag_rp_75() (page = 60) -#define ag_rp_76() (expression_list_equation()) +#define ag_rp_76(n) (page = n) #define ag_rp_77() (expression_list_literal()) #define ag_rp_78() (expression_list_literal()) -#define ag_rp_79() (gNameList->Add(ss[ss_idx--])) +#define ag_rp_79() (expression_list_equation()) + +#define ag_rp_80() (expression_list_equation()) + +#define ag_rp_81() (expression_list_literal()) + +#define ag_rp_82() (expression_list_literal()) + +#define ag_rp_83() (gNameList->Add(ss[ss_idx--])) -#define ag_rp_80() (gNameList->Add(ss[ss_idx--])) +#define ag_rp_84() (gNameList->Add(ss[ss_idx--])) -static void ag_rp_81(void) { -/* Line 247, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_85(void) { +/* Line 253, C:/Projects/VirtualT/src/a85parse.syn */ strcpy(ss[++ss_idx], "$"); ss_len = 1; } -static void ag_rp_82(void) { -/* Line 248, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_86(void) { +/* Line 254, C:/Projects/VirtualT/src/a85parse.syn */ strcpy(ss[++ss_idx], "&"); ss_len = 1; } -static void ag_rp_83(int c) { -/* Line 251, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_87(int c) { +/* Line 257, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; \ if (PCB.column == 2) ss_addr = gAsm->m_ActiveSeg->m_Address; } -static void ag_rp_84(int c) { -/* Line 253, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_88(int c) { +/* Line 259, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_85(int c) { -/* Line 254, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_89(int c) { +/* Line 260, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_86(int c) { -/* Line 257, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_90(int c) { +/* Line 263, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_87(int c) { -/* Line 258, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_91(int c) { +/* Line 264, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_88(int ch1, int ch2) { -/* Line 264, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_92(int ch1, int ch2) { +/* Line 270, C:/Projects/VirtualT/src/a85parse.syn */ ss_idx++; ss_len = 2; sprintf(ss[ss_idx], "%c%c", ch1, ch2); } -static void ag_rp_89(int c) { -/* Line 265, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_93(int c) { +/* Line 271, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_90(void) { -/* Line 272, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_94(void) { +/* Line 278, C:/Projects/VirtualT/src/a85parse.syn */ ss_idx++; ss_len = 0; } -static void ag_rp_91(int c) { -/* Line 273, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_95(int c) { +/* Line 279, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -#define ag_rp_92(n) (n) +#define ag_rp_96(n) (n) -#define ag_rp_93() ('\\') +#define ag_rp_97() ('\\') -#define ag_rp_94() ('\n') +#define ag_rp_98() ('\n') -#define ag_rp_95() ('\t') +#define ag_rp_99() ('\t') -#define ag_rp_96() ('\r') +#define ag_rp_100() ('\r') -#define ag_rp_97() ('\0') +#define ag_rp_101() ('\0') -#define ag_rp_98() ('"') +#define ag_rp_102() ('"') -#define ag_rp_99() (0x08) +#define ag_rp_103() (0x08) -#define ag_rp_100() (0x0C) +#define ag_rp_104() (0x0C) -#define ag_rp_101(n1, n2, n3) ((n1-'0') * 64 + (n2-'0') * 8 + n3-'0') +#define ag_rp_105(n1, n2, n3) ((n1-'0') * 64 + (n2-'0') * 8 + n3-'0') -#define ag_rp_102(n1, n2) (chtoh(n1) * 16 + chtoh(n2)) +#define ag_rp_106(n1, n2) (chtoh(n1) * 16 + chtoh(n2)) -#define ag_rp_103(n1) (chtoh(n1)) +#define ag_rp_107(n1) (chtoh(n1)) -static void ag_rp_104(void) { -/* Line 293, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_108(void) { +/* Line 299, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '>'; ss[ss_idx][ss_len] = 0; } -static void ag_rp_105(void) { -/* Line 296, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_109(void) { +/* Line 302, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = '<'; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_106(int c) { -/* Line 297, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_110(int c) { +/* Line 303, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_107(int c) { -/* Line 298, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_111(int c) { +/* Line 304, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '\\'; ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -#define ag_rp_108() (gAsm->label(ss[ss_idx--])) +#define ag_rp_112() (gAsm->label(ss[ss_idx--])) -#define ag_rp_109() (gAsm->label(ss[ss_idx--])) +#define ag_rp_113() (gAsm->label(ss[ss_idx--])) -#define ag_rp_110() (gAsm->label(".bss")) +#define ag_rp_114() (gAsm->label(".bss")) -#define ag_rp_111() (gAsm->label(".text")) +#define ag_rp_115() (gAsm->label(".text")) -#define ag_rp_112() (gAsm->label(".data")) +#define ag_rp_116() (gAsm->label(".data")) -#define ag_rp_113() (PAGE) +#define ag_rp_117() (PAGE) -#define ag_rp_114() (INPAGE) +#define ag_rp_118() (INPAGE) -#define ag_rp_115() (condition(-1)) +#define ag_rp_119() (condition(-1)) -#define ag_rp_116() (condition(COND_NOCMP)) +#define ag_rp_120() (condition(COND_NOCMP)) -#define ag_rp_117() (condition(COND_EQ)) +#define ag_rp_121() (condition(COND_EQ)) -#define ag_rp_118() (condition(COND_NE)) +#define ag_rp_122() (condition(COND_NE)) -#define ag_rp_119() (condition(COND_GE)) +#define ag_rp_123() (condition(COND_GE)) -#define ag_rp_120() (condition(COND_LE)) +#define ag_rp_124() (condition(COND_LE)) -#define ag_rp_121() (condition(COND_GT)) +#define ag_rp_125() (condition(COND_GT)) -#define ag_rp_122() (condition(COND_LT)) +#define ag_rp_126() (condition(COND_LT)) -#define ag_rp_123() (gEq->Add(RPN_BITOR)) +#define ag_rp_127() (gEq->Add(RPN_BITOR)) -#define ag_rp_124() (gEq->Add(RPN_BITOR)) +#define ag_rp_128() (gEq->Add(RPN_BITOR)) -#define ag_rp_125() (gEq->Add(RPN_BITXOR)) +#define ag_rp_129() (gEq->Add(RPN_BITXOR)) -#define ag_rp_126() (gEq->Add(RPN_BITXOR)) +#define ag_rp_130() (gEq->Add(RPN_BITXOR)) -#define ag_rp_127() (gEq->Add(RPN_BITAND)) +#define ag_rp_131() (gEq->Add(RPN_BITAND)) -#define ag_rp_128() (gEq->Add(RPN_BITAND)) +#define ag_rp_132() (gEq->Add(RPN_BITAND)) -#define ag_rp_129() (gEq->Add(RPN_LEFTSHIFT)) +#define ag_rp_133() (gEq->Add(RPN_LEFTSHIFT)) -#define ag_rp_130() (gEq->Add(RPN_LEFTSHIFT)) +#define ag_rp_134() (gEq->Add(RPN_LEFTSHIFT)) -#define ag_rp_131() (gEq->Add(RPN_RIGHTSHIFT)) +#define ag_rp_135() (gEq->Add(RPN_RIGHTSHIFT)) -#define ag_rp_132() (gEq->Add(RPN_RIGHTSHIFT)) +#define ag_rp_136() (gEq->Add(RPN_RIGHTSHIFT)) -#define ag_rp_133() (gEq->Add(RPN_ADD)) +#define ag_rp_137() (gEq->Add(RPN_ADD)) -#define ag_rp_134() (gEq->Add(RPN_SUBTRACT)) +#define ag_rp_138() (gEq->Add(RPN_SUBTRACT)) -#define ag_rp_135() (gEq->Add(RPN_MULTIPLY)) +#define ag_rp_139() (gEq->Add(RPN_MULTIPLY)) -#define ag_rp_136() (gEq->Add(RPN_DIVIDE)) +#define ag_rp_140() (gEq->Add(RPN_DIVIDE)) -#define ag_rp_137() (gEq->Add(RPN_MODULUS)) +#define ag_rp_141() (gEq->Add(RPN_MODULUS)) -#define ag_rp_138() (gEq->Add(RPN_MODULUS)) +#define ag_rp_142() (gEq->Add(RPN_MODULUS)) -#define ag_rp_139() (gEq->Add(RPN_EXPONENT)) +#define ag_rp_143() (gEq->Add(RPN_EXPONENT)) -#define ag_rp_140() (gEq->Add(RPN_NOT)) +#define ag_rp_144() (gEq->Add(RPN_NOT)) -#define ag_rp_141() (gEq->Add(RPN_NOT)) +#define ag_rp_145() (gEq->Add(RPN_NOT)) -#define ag_rp_142() (gEq->Add(RPN_BITNOT)) +#define ag_rp_146() (gEq->Add(RPN_BITNOT)) -#define ag_rp_143() (gEq->Add(RPN_NEGATE)) +#define ag_rp_147() (gEq->Add(RPN_NEGATE)) -#define ag_rp_144(n) (gEq->Add((double) n)) +#define ag_rp_148(n) (gEq->Add((double) n)) -static void ag_rp_145(void) { -/* Line 389, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_149(void) { +/* Line 395, C:/Projects/VirtualT/src/a85parse.syn */ delete gMacro; gMacro = gMacroStack[ms_idx-1]; \ gMacroStack[ms_idx--] = 0; if (gMacro->m_ParamList == 0) \ {\ @@ -851,177 +859,169 @@ static void ag_rp_145(void) { } } -#define ag_rp_146() (gEq->Add(RPN_FLOOR)) +#define ag_rp_150() (gEq->Add(RPN_FLOOR)) -#define ag_rp_147() (gEq->Add(RPN_CEIL)) +#define ag_rp_151() (gEq->Add(RPN_CEIL)) -#define ag_rp_148() (gEq->Add(RPN_LN)) +#define ag_rp_152() (gEq->Add(RPN_LN)) -#define ag_rp_149() (gEq->Add(RPN_LOG)) +#define ag_rp_153() (gEq->Add(RPN_LOG)) -#define ag_rp_150() (gEq->Add(RPN_SQRT)) +#define ag_rp_154() (gEq->Add(RPN_SQRT)) -#define ag_rp_151() (gEq->Add(RPN_IP)) +#define ag_rp_155() (gEq->Add(RPN_IP)) -#define ag_rp_152() (gEq->Add(RPN_FP)) +#define ag_rp_156() (gEq->Add(RPN_FP)) -#define ag_rp_153() (gEq->Add(RPN_HIGH)) +#define ag_rp_157() (gEq->Add(RPN_HIGH)) -#define ag_rp_154() (gEq->Add(RPN_LOW)) +#define ag_rp_158() (gEq->Add(RPN_LOW)) -#define ag_rp_155() (gEq->Add(RPN_PAGE)) +#define ag_rp_159() (gEq->Add(RPN_PAGE)) -#define ag_rp_156() (gEq->Add(RPN_DEFINED, ss[ss_idx--])) +#define ag_rp_160() (gEq->Add(RPN_DEFINED, ss[ss_idx--])) -#define ag_rp_157(n) (n) +#define ag_rp_161(n) (n) -#define ag_rp_158(r) (r) +#define ag_rp_162(r) (r) -#define ag_rp_159(n) (n) +#define ag_rp_163(n) (n) -#define ag_rp_160() (conv_to_dec()) +#define ag_rp_164() (conv_to_dec()) -#define ag_rp_161() (conv_to_hex()) +#define ag_rp_165() (conv_to_hex()) -#define ag_rp_162() (conv_to_bin()) +#define ag_rp_166() (conv_to_bin()) -#define ag_rp_163() (conv_to_oct()) +#define ag_rp_167() (conv_to_oct()) -#define ag_rp_164() (conv_to_hex()) +#define ag_rp_168() (conv_to_hex()) -#define ag_rp_165() (conv_to_hex()) +#define ag_rp_169() (conv_to_hex()) -#define ag_rp_166() (conv_to_bin()) +#define ag_rp_170() (conv_to_bin()) -#define ag_rp_167() (conv_to_oct()) +#define ag_rp_171() (conv_to_oct()) -#define ag_rp_168() (conv_to_dec()) +#define ag_rp_172() (conv_to_dec()) -static void ag_rp_169(int n) { -/* Line 436, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_173(int n) { +/* Line 442, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_170(int n) { -/* Line 437, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_174(int n) { +/* Line 443, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 2; integer[0] = '-', integer[1] = n; integer[2] = 0; } -static void ag_rp_171(int n) { -/* Line 438, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_175(int n) { +/* Line 444, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_172(int n) { -/* Line 439, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_176(int n) { +/* Line 445, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_173(int n) { -/* Line 444, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_177(int n) { +/* Line 450, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_174(int n) { -/* Line 445, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_178(int n) { +/* Line 451, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } -static void ag_rp_175(int n) { -/* Line 446, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_179(int n) { +/* Line 452, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_176(int n) { -/* Line 449, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_180(int n) { +/* Line 455, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_177(int n) { -/* Line 450, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_181(int n) { +/* Line 456, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_178(int n) { -/* Line 453, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_182(int n) { +/* Line 459, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_179(int n) { -/* Line 454, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_183(int n) { +/* Line 460, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_180(int n) { -/* Line 457, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_184(int n) { +/* Line 463, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -static void ag_rp_181(int n) { -/* Line 458, C:/Projects/VirtualT/src/a85parse.syn */ +static void ag_rp_185(int n) { +/* Line 464, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } -#define ag_rp_182(n) (n) +#define ag_rp_186(n) (n) -#define ag_rp_183(n1, n2) ((n1 << 8) | n2) +#define ag_rp_187(n1, n2) ((n1 << 8) | n2) -#define ag_rp_184() ('\\') +#define ag_rp_188() ('\\') -#define ag_rp_185(n) (n) +#define ag_rp_189(n) (n) -#define ag_rp_186() ('\\') +#define ag_rp_190() ('\\') -#define ag_rp_187() ('\n') +#define ag_rp_191() ('\n') -#define ag_rp_188() ('\t') +#define ag_rp_192() ('\t') -#define ag_rp_189() ('\r') +#define ag_rp_193() ('\r') -#define ag_rp_190() ('\0') +#define ag_rp_194() ('\0') -#define ag_rp_191() ('\'') +#define ag_rp_195() ('\'') -#define ag_rp_192() ('\'') +#define ag_rp_196() ('\'') -static double ag_rp_193(void) { -/* Line 479, C:/Projects/VirtualT/src/a85parse.syn */ +static double ag_rp_197(void) { +/* Line 485, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor = 1.0; return (double) conv_to_dec(); } -static double ag_rp_194(int d) { -/* Line 480, C:/Projects/VirtualT/src/a85parse.syn */ +static double ag_rp_198(int d) { +/* Line 486, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor = 10.0; return ((double) (d - '0') / gDivisor); } -static double ag_rp_195(double r, int d) { -/* Line 481, C:/Projects/VirtualT/src/a85parse.syn */ +static double ag_rp_199(double r, int d) { +/* Line 487, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor *= 10.0; return (r + (double) (d - '0') / gDivisor); } -#define ag_rp_196() (reg[reg_cnt++] = '0') - -#define ag_rp_197() (reg[reg_cnt++] = '1') - -#define ag_rp_198() (reg[reg_cnt++] = '2') - -#define ag_rp_199() (reg[reg_cnt++] = '3') - -#define ag_rp_200() (reg[reg_cnt++] = '4') +#define ag_rp_200() (reg[reg_cnt++] = '0') -#define ag_rp_201() (reg[reg_cnt++] = '5') +#define ag_rp_201() (reg[reg_cnt++] = '1') -#define ag_rp_202() (reg[reg_cnt++] = '6') +#define ag_rp_202() (reg[reg_cnt++] = '2') -#define ag_rp_203() (reg[reg_cnt++] = '7') +#define ag_rp_203() (reg[reg_cnt++] = '3') -#define ag_rp_204() (reg[reg_cnt++] = '0') +#define ag_rp_204() (reg[reg_cnt++] = '4') -#define ag_rp_205() (reg[reg_cnt++] = '1') +#define ag_rp_205() (reg[reg_cnt++] = '5') -#define ag_rp_206() (reg[reg_cnt++] = '2') +#define ag_rp_206() (reg[reg_cnt++] = '6') -#define ag_rp_207() (reg[reg_cnt++] = '3') +#define ag_rp_207() (reg[reg_cnt++] = '7') #define ag_rp_208() (reg[reg_cnt++] = '0') @@ -1031,247 +1031,255 @@ static double ag_rp_195(double r, int d) { #define ag_rp_211() (reg[reg_cnt++] = '3') -#define ag_rp_212() (reg[reg_cnt++] = '3') +#define ag_rp_212() (reg[reg_cnt++] = '0') -#define ag_rp_213() (reg[reg_cnt++] = '0') +#define ag_rp_213() (reg[reg_cnt++] = '1') -#define ag_rp_214() (reg[reg_cnt++] = '1') +#define ag_rp_214() (reg[reg_cnt++] = '2') -#define ag_rp_215() (reg[reg_cnt++] = '0') +#define ag_rp_215() (reg[reg_cnt++] = '3') -#define ag_rp_216() (reg[reg_cnt++] = '1') +#define ag_rp_216() (reg[reg_cnt++] = '3') -#define ag_rp_217() (reg[reg_cnt++] = '2') +#define ag_rp_217() (reg[reg_cnt++] = '0') -#define ag_rp_218() (reg[reg_cnt++] = '3') +#define ag_rp_218() (reg[reg_cnt++] = '1') -#define ag_rp_219() (reg[reg_cnt++] = '4') +#define ag_rp_219() (reg[reg_cnt++] = '0') -#define ag_rp_220() (reg[reg_cnt++] = '5') +#define ag_rp_220() (reg[reg_cnt++] = '1') -#define ag_rp_221() (gAsm->opcode_arg_0 (OPCODE_ASHR)) +#define ag_rp_221() (reg[reg_cnt++] = '2') -#define ag_rp_222() (gAsm->opcode_arg_0 (OPCODE_CMA)) +#define ag_rp_222() (reg[reg_cnt++] = '3') -#define ag_rp_223() (gAsm->opcode_arg_0 (OPCODE_CMC)) +#define ag_rp_223() (reg[reg_cnt++] = '4') -#define ag_rp_224() (gAsm->opcode_arg_0 (OPCODE_DAA)) +#define ag_rp_224() (reg[reg_cnt++] = '5') -#define ag_rp_225() (gAsm->opcode_arg_0 (OPCODE_DI)) +#define ag_rp_225() (gAsm->opcode_arg_0 (OPCODE_ASHR)) -#define ag_rp_226() (gAsm->opcode_arg_0 (OPCODE_DSUB)) +#define ag_rp_226() (gAsm->opcode_arg_0 (OPCODE_CMA)) -#define ag_rp_227() (gAsm->opcode_arg_0 (OPCODE_EI)) +#define ag_rp_227() (gAsm->opcode_arg_0 (OPCODE_CMC)) -#define ag_rp_228() (gAsm->opcode_arg_0 (OPCODE_HLT)) +#define ag_rp_228() (gAsm->opcode_arg_0 (OPCODE_DAA)) -#define ag_rp_229() (gAsm->opcode_arg_0 (OPCODE_LHLX)) +#define ag_rp_229() (gAsm->opcode_arg_0 (OPCODE_DI)) -#define ag_rp_230() (gAsm->opcode_arg_0 (OPCODE_NOP)) +#define ag_rp_230() (gAsm->opcode_arg_0 (OPCODE_DSUB)) -#define ag_rp_231() (gAsm->opcode_arg_0 (OPCODE_PCHL)) +#define ag_rp_231() (gAsm->opcode_arg_0 (OPCODE_EI)) -#define ag_rp_232() (gAsm->opcode_arg_0 (OPCODE_RAL)) +#define ag_rp_232() (gAsm->opcode_arg_0 (OPCODE_HLT)) -#define ag_rp_233() (gAsm->opcode_arg_0 (OPCODE_RAR)) +#define ag_rp_233() (gAsm->opcode_arg_0 (OPCODE_LHLX)) -#define ag_rp_234() (gAsm->opcode_arg_0 (OPCODE_RC)) +#define ag_rp_234() (gAsm->opcode_arg_0 (OPCODE_NOP)) -#define ag_rp_235() (gAsm->opcode_arg_0 (OPCODE_RET)) +#define ag_rp_235() (gAsm->opcode_arg_0 (OPCODE_PCHL)) -#define ag_rp_236() (gAsm->opcode_arg_0 (OPCODE_RIM)) +#define ag_rp_236() (gAsm->opcode_arg_0 (OPCODE_RAL)) -#define ag_rp_237() (gAsm->opcode_arg_0 (OPCODE_RLC)) +#define ag_rp_237() (gAsm->opcode_arg_0 (OPCODE_RAR)) -#define ag_rp_238() (gAsm->opcode_arg_0 (OPCODE_RLDE)) +#define ag_rp_238() (gAsm->opcode_arg_0 (OPCODE_RC)) -#define ag_rp_239() (gAsm->opcode_arg_0 (OPCODE_RM)) +#define ag_rp_239() (gAsm->opcode_arg_0 (OPCODE_RET)) -#define ag_rp_240() (gAsm->opcode_arg_0 (OPCODE_RNC)) +#define ag_rp_240() (gAsm->opcode_arg_0 (OPCODE_RIM)) -#define ag_rp_241() (gAsm->opcode_arg_0 (OPCODE_RNZ)) +#define ag_rp_241() (gAsm->opcode_arg_0 (OPCODE_RLC)) -#define ag_rp_242() (gAsm->opcode_arg_0 (OPCODE_RP)) +#define ag_rp_242() (gAsm->opcode_arg_0 (OPCODE_RLDE)) -#define ag_rp_243() (gAsm->opcode_arg_0 (OPCODE_RPE)) +#define ag_rp_243() (gAsm->opcode_arg_0 (OPCODE_RM)) -#define ag_rp_244() (gAsm->opcode_arg_0 (OPCODE_RPO)) +#define ag_rp_244() (gAsm->opcode_arg_0 (OPCODE_RNC)) -#define ag_rp_245() (gAsm->opcode_arg_0 (OPCODE_RRC)) +#define ag_rp_245() (gAsm->opcode_arg_0 (OPCODE_RNZ)) -#define ag_rp_246() (gAsm->opcode_arg_0 (OPCODE_RSTV)) +#define ag_rp_246() (gAsm->opcode_arg_0 (OPCODE_RP)) -#define ag_rp_247() (gAsm->opcode_arg_0 (OPCODE_RZ)) +#define ag_rp_247() (gAsm->opcode_arg_0 (OPCODE_RPE)) -#define ag_rp_248() (gAsm->opcode_arg_0 (OPCODE_SHLX)) +#define ag_rp_248() (gAsm->opcode_arg_0 (OPCODE_RPO)) -#define ag_rp_249() (gAsm->opcode_arg_0 (OPCODE_SIM)) +#define ag_rp_249() (gAsm->opcode_arg_0 (OPCODE_RRC)) -#define ag_rp_250() (gAsm->opcode_arg_0 (OPCODE_SPHL)) +#define ag_rp_250() (gAsm->opcode_arg_0 (OPCODE_RSTV)) -#define ag_rp_251() (gAsm->opcode_arg_0 (OPCODE_STC)) +#define ag_rp_251() (gAsm->opcode_arg_0 (OPCODE_RZ)) -#define ag_rp_252() (gAsm->opcode_arg_0 (OPCODE_XCHG)) +#define ag_rp_252() (gAsm->opcode_arg_0 (OPCODE_SHLX)) -#define ag_rp_253() (gAsm->opcode_arg_0 (OPCODE_XTHL)) +#define ag_rp_253() (gAsm->opcode_arg_0 (OPCODE_SIM)) -#define ag_rp_254() (gAsm->opcode_arg_0 (OPCODE_LRET)) +#define ag_rp_254() (gAsm->opcode_arg_0 (OPCODE_SPHL)) -#define ag_rp_255() (gAsm->opcode_arg_1reg (OPCODE_STAX)) +#define ag_rp_255() (gAsm->opcode_arg_0 (OPCODE_STC)) -#define ag_rp_256() (gAsm->opcode_arg_1reg (OPCODE_LDAX)) +#define ag_rp_256() (gAsm->opcode_arg_0 (OPCODE_XCHG)) -#define ag_rp_257() (gAsm->opcode_arg_1reg (OPCODE_POP)) +#define ag_rp_257() (gAsm->opcode_arg_0 (OPCODE_XTHL)) -#define ag_rp_258() (gAsm->opcode_arg_1reg (OPCODE_PUSH)) +#define ag_rp_258() (gAsm->opcode_arg_0 (OPCODE_LRET)) -#define ag_rp_259() (gAsm->opcode_arg_1reg_2byte (OPCODE_LPOP)) +#define ag_rp_259() (gAsm->opcode_arg_1reg (OPCODE_STAX)) -#define ag_rp_260() (gAsm->opcode_arg_1reg_2byte (OPCODE_LPUSH)) +#define ag_rp_260() (gAsm->opcode_arg_1reg (OPCODE_LDAX)) -#define ag_rp_261() (gAsm->opcode_arg_1reg (OPCODE_ADC)) +#define ag_rp_261() (gAsm->opcode_arg_1reg (OPCODE_POP)) -#define ag_rp_262() (gAsm->opcode_arg_1reg (OPCODE_ADD)) +#define ag_rp_262() (gAsm->opcode_arg_1reg (OPCODE_PUSH)) -#define ag_rp_263() (gAsm->opcode_arg_1reg (OPCODE_ANA)) +#define ag_rp_263() (gAsm->opcode_arg_1reg_2byte (OPCODE_LPOP)) -#define ag_rp_264() (gAsm->opcode_arg_1reg (OPCODE_CMP)) +#define ag_rp_264() (gAsm->opcode_arg_1reg_2byte (OPCODE_LPUSH)) -#define ag_rp_265() (gAsm->opcode_arg_1reg (OPCODE_DCR)) +#define ag_rp_265() (gAsm->opcode_arg_1reg (OPCODE_ADC)) -#define ag_rp_266() (gAsm->opcode_arg_1reg (OPCODE_INR)) +#define ag_rp_266() (gAsm->opcode_arg_1reg (OPCODE_ADD)) -#define ag_rp_267() (gAsm->opcode_arg_2reg (OPCODE_MOV)) +#define ag_rp_267() (gAsm->opcode_arg_1reg (OPCODE_ANA)) -#define ag_rp_268() (gAsm->opcode_arg_1reg (OPCODE_ORA)) +#define ag_rp_268() (gAsm->opcode_arg_1reg (OPCODE_CMP)) -#define ag_rp_269() (gAsm->opcode_arg_1reg (OPCODE_SBB)) +#define ag_rp_269() (gAsm->opcode_arg_1reg (OPCODE_DCR)) -#define ag_rp_270() (gAsm->opcode_arg_1reg (OPCODE_SUB)) +#define ag_rp_270() (gAsm->opcode_arg_1reg (OPCODE_INR)) -#define ag_rp_271() (gAsm->opcode_arg_1reg (OPCODE_XRA)) +#define ag_rp_271() (gAsm->opcode_arg_2reg (OPCODE_MOV)) -#define ag_rp_272() (gAsm->opcode_arg_1reg_2byte (OPCODE_SPG)) +#define ag_rp_272() (gAsm->opcode_arg_1reg (OPCODE_ORA)) -#define ag_rp_273() (gAsm->opcode_arg_1reg_2byte (OPCODE_RPG)) +#define ag_rp_273() (gAsm->opcode_arg_1reg (OPCODE_SBB)) -#define ag_rp_274() (gAsm->opcode_arg_1reg (OPCODE_DAD)) +#define ag_rp_274() (gAsm->opcode_arg_1reg (OPCODE_SUB)) -#define ag_rp_275() (gAsm->opcode_arg_1reg (OPCODE_DCX)) +#define ag_rp_275() (gAsm->opcode_arg_1reg (OPCODE_XRA)) -#define ag_rp_276() (gAsm->opcode_arg_1reg (OPCODE_INX)) +#define ag_rp_276() (gAsm->opcode_arg_1reg_2byte (OPCODE_SPG)) -#define ag_rp_277() (gAsm->opcode_arg_1reg_equ16(OPCODE_LXI)) +#define ag_rp_277() (gAsm->opcode_arg_1reg_2byte (OPCODE_RPG)) -#define ag_rp_278() (gAsm->opcode_arg_1reg_equ8(OPCODE_MVI)) +#define ag_rp_278() (gAsm->opcode_arg_1reg (OPCODE_DAD)) -#define ag_rp_279() (gAsm->opcode_arg_1reg_equ16(OPCODE_SPI)) +#define ag_rp_279() (gAsm->opcode_arg_1reg (OPCODE_DCX)) -#define ag_rp_280(c) (gAsm->opcode_arg_imm (OPCODE_RST, c)) +#define ag_rp_280() (gAsm->opcode_arg_1reg (OPCODE_INX)) -#define ag_rp_281() (gAsm->opcode_arg_equ8 (OPCODE_ACI)) +#define ag_rp_281() (gAsm->opcode_arg_1reg_equ16(OPCODE_LXI)) -#define ag_rp_282() (gAsm->opcode_arg_equ8 (OPCODE_ADI)) +#define ag_rp_282() (gAsm->opcode_arg_1reg_equ8(OPCODE_MVI)) -#define ag_rp_283() (gAsm->opcode_arg_equ8 (OPCODE_ANI)) +#define ag_rp_283() (gAsm->opcode_arg_1reg_equ16(OPCODE_SPI)) -#define ag_rp_284() (gAsm->opcode_arg_equ16 (OPCODE_CALL)) +#define ag_rp_284(c) (gAsm->opcode_arg_imm (OPCODE_RST, c)) -#define ag_rp_285() (gAsm->opcode_arg_equ16 (OPCODE_CC)) +#define ag_rp_285() (gAsm->opcode_arg_equ8 (OPCODE_ACI)) -#define ag_rp_286() (gAsm->opcode_arg_equ16 (OPCODE_CM)) +#define ag_rp_286() (gAsm->opcode_arg_equ8 (OPCODE_ADI)) -#define ag_rp_287() (gAsm->opcode_arg_equ16 (OPCODE_CNC)) +#define ag_rp_287() (gAsm->opcode_arg_equ8 (OPCODE_ANI)) -#define ag_rp_288() (gAsm->opcode_arg_equ16 (OPCODE_CNZ)) +#define ag_rp_288() (gAsm->opcode_arg_equ16 (OPCODE_CALL)) -#define ag_rp_289() (gAsm->opcode_arg_equ16 (OPCODE_CP)) +#define ag_rp_289() (gAsm->opcode_arg_equ16 (OPCODE_CC)) -#define ag_rp_290() (gAsm->opcode_arg_equ16 (OPCODE_CPE)) +#define ag_rp_290() (gAsm->opcode_arg_equ16 (OPCODE_CM)) -#define ag_rp_291() (gAsm->opcode_arg_equ8 (OPCODE_CPI)) +#define ag_rp_291() (gAsm->opcode_arg_equ16 (OPCODE_CNC)) -#define ag_rp_292() (gAsm->opcode_arg_equ16 (OPCODE_CPO)) +#define ag_rp_292() (gAsm->opcode_arg_equ16 (OPCODE_CNZ)) -#define ag_rp_293() (gAsm->opcode_arg_equ16 (OPCODE_CZ)) +#define ag_rp_293() (gAsm->opcode_arg_equ16 (OPCODE_CP)) -#define ag_rp_294() (gAsm->opcode_arg_equ8 (OPCODE_IN)) +#define ag_rp_294() (gAsm->opcode_arg_equ16 (OPCODE_CPE)) -#define ag_rp_295() (gAsm->opcode_arg_equ16 (OPCODE_JC)) +#define ag_rp_295() (gAsm->opcode_arg_equ8 (OPCODE_CPI)) -#define ag_rp_296() (gAsm->opcode_arg_equ16 (OPCODE_JD)) +#define ag_rp_296() (gAsm->opcode_arg_equ16 (OPCODE_CPO)) -#define ag_rp_297() (gAsm->opcode_arg_equ16 (OPCODE_JM)) +#define ag_rp_297() (gAsm->opcode_arg_equ16 (OPCODE_CZ)) -#define ag_rp_298() (gAsm->opcode_arg_equ16 (OPCODE_JMP)) +#define ag_rp_298() (gAsm->opcode_arg_equ8 (OPCODE_IN)) -#define ag_rp_299() (gAsm->opcode_arg_equ16 (OPCODE_JNC)) +#define ag_rp_299() (gAsm->opcode_arg_equ16 (OPCODE_JC)) -#define ag_rp_300() (gAsm->opcode_arg_equ16 (OPCODE_JND)) +#define ag_rp_300() (gAsm->opcode_arg_equ16 (OPCODE_JD)) -#define ag_rp_301() (gAsm->opcode_arg_equ16 (OPCODE_JNZ)) +#define ag_rp_301() (gAsm->opcode_arg_equ16 (OPCODE_JM)) -#define ag_rp_302() (gAsm->opcode_arg_equ16 (OPCODE_JP)) +#define ag_rp_302() (gAsm->opcode_arg_equ16 (OPCODE_JMP)) -#define ag_rp_303() (gAsm->opcode_arg_equ16 (OPCODE_JPE)) +#define ag_rp_303() (gAsm->opcode_arg_equ16 (OPCODE_JNC)) -#define ag_rp_304() (gAsm->opcode_arg_equ16 (OPCODE_JPO)) +#define ag_rp_304() (gAsm->opcode_arg_equ16 (OPCODE_JND)) -#define ag_rp_305() (gAsm->opcode_arg_equ16 (OPCODE_JZ)) +#define ag_rp_305() (gAsm->opcode_arg_equ16 (OPCODE_JNZ)) -#define ag_rp_306() (gAsm->opcode_arg_equ16 (OPCODE_LDA)) +#define ag_rp_306() (gAsm->opcode_arg_equ16 (OPCODE_JP)) -#define ag_rp_307() (gAsm->opcode_arg_equ8 (OPCODE_LDEH)) +#define ag_rp_307() (gAsm->opcode_arg_equ16 (OPCODE_JPE)) -#define ag_rp_308() (gAsm->opcode_arg_equ8 (OPCODE_LDES)) +#define ag_rp_308() (gAsm->opcode_arg_equ16 (OPCODE_JPO)) -#define ag_rp_309() (gAsm->opcode_arg_equ16 (OPCODE_LHLD)) +#define ag_rp_309() (gAsm->opcode_arg_equ16 (OPCODE_JZ)) -#define ag_rp_310() (gAsm->opcode_arg_equ8 (OPCODE_ORI)) +#define ag_rp_310() (gAsm->opcode_arg_equ16 (OPCODE_LDA)) -#define ag_rp_311() (gAsm->opcode_arg_equ8 (OPCODE_OUT)) +#define ag_rp_311() (gAsm->opcode_arg_equ8 (OPCODE_LDEH)) -#define ag_rp_312() (gAsm->opcode_arg_equ8 (OPCODE_SBI)) +#define ag_rp_312() (gAsm->opcode_arg_equ8 (OPCODE_LDES)) -#define ag_rp_313() (gAsm->opcode_arg_equ16 (OPCODE_SHLD)) +#define ag_rp_313() (gAsm->opcode_arg_equ16 (OPCODE_LHLD)) -#define ag_rp_314() (gAsm->opcode_arg_equ16 (OPCODE_STA)) +#define ag_rp_314() (gAsm->opcode_arg_equ8 (OPCODE_ORI)) -#define ag_rp_315() (gAsm->opcode_arg_equ8 (OPCODE_SUI)) +#define ag_rp_315() (gAsm->opcode_arg_equ8 (OPCODE_OUT)) -#define ag_rp_316() (gAsm->opcode_arg_equ8 (OPCODE_XRI)) +#define ag_rp_316() (gAsm->opcode_arg_equ8 (OPCODE_SBI)) -#define ag_rp_317() (gAsm->opcode_arg_equ8 (OPCODE_BR)) +#define ag_rp_317() (gAsm->opcode_arg_equ16 (OPCODE_SHLD)) -#define ag_rp_318() (gAsm->opcode_arg_equ16 (OPCODE_BRA)) +#define ag_rp_318() (gAsm->opcode_arg_equ16 (OPCODE_STA)) -#define ag_rp_319() (gAsm->opcode_arg_equ16 (OPCODE_BZ)) +#define ag_rp_319() (gAsm->opcode_arg_equ8 (OPCODE_SUI)) -#define ag_rp_320() (gAsm->opcode_arg_equ16 (OPCODE_BNZ)) +#define ag_rp_320() (gAsm->opcode_arg_equ8 (OPCODE_XRI)) -#define ag_rp_321() (gAsm->opcode_arg_equ16 (OPCODE_BC)) +#define ag_rp_321() (gAsm->opcode_arg_equ8 (OPCODE_BR)) -#define ag_rp_322() (gAsm->opcode_arg_equ16 (OPCODE_BNC)) +#define ag_rp_322() (gAsm->opcode_arg_equ16 (OPCODE_BRA)) -#define ag_rp_323() (gAsm->opcode_arg_equ16 (OPCODE_BM)) +#define ag_rp_323() (gAsm->opcode_arg_equ16 (OPCODE_BZ)) -#define ag_rp_324() (gAsm->opcode_arg_equ16 (OPCODE_BP)) +#define ag_rp_324() (gAsm->opcode_arg_equ16 (OPCODE_BNZ)) -#define ag_rp_325() (gAsm->opcode_arg_equ16 (OPCODE_BPE)) +#define ag_rp_325() (gAsm->opcode_arg_equ16 (OPCODE_BC)) -#define ag_rp_326() (gAsm->opcode_arg_equ16 (OPCODE_RCALL)) +#define ag_rp_326() (gAsm->opcode_arg_equ16 (OPCODE_BNC)) -#define ag_rp_327() (gAsm->opcode_arg_equ8 (OPCODE_SBZ)) +#define ag_rp_327() (gAsm->opcode_arg_equ16 (OPCODE_BM)) -#define ag_rp_328() (gAsm->opcode_arg_equ8 (OPCODE_SBNZ)) +#define ag_rp_328() (gAsm->opcode_arg_equ16 (OPCODE_BP)) -#define ag_rp_329() (gAsm->opcode_arg_equ8 (OPCODE_SBC)) +#define ag_rp_329() (gAsm->opcode_arg_equ16 (OPCODE_BPE)) -#define ag_rp_330() (gAsm->opcode_arg_equ8 (OPCODE_SBNC)) +#define ag_rp_330() (gAsm->opcode_arg_equ16 (OPCODE_RCALL)) -#define ag_rp_331() (gAsm->opcode_arg_equ24 (OPCODE_LCALL)) +#define ag_rp_331() (gAsm->opcode_arg_equ8 (OPCODE_SBZ)) -#define ag_rp_332() (gAsm->opcode_arg_equ24 (OPCODE_LJMP)) +#define ag_rp_332() (gAsm->opcode_arg_equ8 (OPCODE_SBNZ)) + +#define ag_rp_333() (gAsm->opcode_arg_equ8 (OPCODE_SBC)) + +#define ag_rp_334() (gAsm->opcode_arg_equ8 (OPCODE_SBNC)) + +#define ag_rp_335() (gAsm->opcode_arg_equ24 (OPCODE_LCALL)) + +#define ag_rp_336() (gAsm->opcode_arg_equ24 (OPCODE_LJMP)) #define READ_COUNTS @@ -1309,31 +1317,32 @@ static a85parse_vs_type const ag_null_value NULL_VALUE_INITIALIZER; static const unsigned short ag_rpx[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 4, 5, 6, - 7, 8, 9, 0, 0, 10, 11, 12, 13, 14, 15, 16, 0, 0, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 0, 35, 0, 36, - 37, 38, 39, 40, 0, 0, 0, 41, 42, 0, 0, 43, 0, 0, 0, 44, 0, 0, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 0, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 0, 0, 81, 82, 83, 84, 85, 86, 87, 0, 88, 89, 0, 90, 91, 0, 92, - 93, 94, 95, 96, 97, 98, 99,100,101, 0, 0,102,103,104,105,106,107, 0, - 108,109,110,111,112,113,114,115,116, 0, 0, 0,117, 0, 0,118, 0, 0, - 119, 0, 0,120, 0, 0,121, 0, 0,122, 0, 0,123,124, 0,125,126, 0, - 127,128, 0,129,130,131,132, 0,133,134, 0,135,136,137,138,139, 0,140, - 141,142,143,144,145, 0, 0,146,147,148,149,150,151,152,153,154,155,156, - 157,158,159,160,161,162,163,164,165,166, 0, 0,167,168,169,170,171,172, - 0, 0,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188, - 189,190,191,192, 0,193,194,195,196,197,198,199,200,201, 0, 0,202,203, - 0, 0,204, 0, 0,205, 0, 0,206,207,208,209,210,211,212,213,214,215, - 216,217,218,219,220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,221,222,223,224,225, 0, 0,226,227,228, 0, 0, 0,229,230, - 231,232,233,234,235,236,237, 0, 0,238,239,240,241,242,243,244,245,246, - 247, 0, 0, 0,248,249,250,251,252,253,254,255,256,257,258,259,260,261, - 262,263,264,265,266,267,268,269,270,271,272,273,274,275,276, 0,277, 0, - 278, 0,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294, - 295, 0, 0, 0, 0, 0,296,297,298,299, 0, 0, 0, 0, 0,300,301,302, - 303,304,305,306, 0, 0, 0,307, 0, 0, 0,308,309,310,311,312,313,314, - 315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 4, 5, + 6, 7, 8, 9, 0, 0, 0, 10, 11, 12, 13, 14, 15, 16, 0, 0, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 0, 37, 0, 38, 39, 40, 41, 42, 0, 0, 0, 43, 44, 0, 0, 45, 0, 0, + 0, 46, 0, 0, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 0, 0, 85, 86, 87, 88, 89, 90, 91, 0, 92, + 93, 0, 94, 95, 0, 96, 97, 98, 99,100,101,102,103,104,105, 0, 0,106, + 107,108,109,110,111, 0,112,113,114,115,116,117,118,119,120, 0, 0, 0, + 121, 0, 0,122, 0, 0,123, 0, 0,124, 0, 0,125, 0, 0,126, 0, 0, + 127,128, 0,129,130, 0,131,132, 0,133,134,135,136, 0,137,138, 0,139, + 140,141,142,143, 0,144,145,146,147,148,149, 0, 0,150,151,152,153,154, + 155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170, 0, 0, + 171,172,173,174,175,176, 0, 0,177,178,179,180,181,182,183,184,185,186, + 187,188,189,190,191,192,193,194,195,196, 0,197,198,199,200,201,202,203, + 204,205, 0, 0,206,207, 0, 0,208, 0, 0,209, 0, 0,210,211,212,213, + 214,215,216,217,218,219,220,221,222,223,224, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,225,226,227,228,229, 0, 0,230,231, + 232, 0, 0, 0,233,234,235,236,237,238,239,240,241, 0, 0,242,243,244, + 245,246,247,248,249,250,251, 0, 0, 0,252,253,254,255,256,257,258,259, + 260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277, + 278,279,280, 0,281, 0,282, 0,283,284,285,286,287,288,289,290,291,292, + 293,294,295,296,297,298,299, 0, 0, 0, 0, 0,300,301,302,303, 0, 0, + 0, 0, 0,304,305,306,307,308,309,310, 0, 0, 0,311, 0, 0, 0,312, + 313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330, + 331,332,333,334,335,336 }; static const unsigned char ag_key_itt[] = { @@ -1354,8 +1363,8 @@ static const unsigned char ag_key_itt[] = { static const unsigned short ag_key_pt[] = { 1,430, 1,431, 1,433, 1,434, 1,440, 1,439, 1,441, 1,443, 1,444, 1,445, 1,446, 1,447, 1,448, 1,449, 1,450, 1,451, - 1,452, 1,453, 1,455, 1,456, 1,457, 1,461, 1,462, 1,463, - 1,466, 1,467, 1,468, 1,469, 1,470, 1,471, 1,472, 1,473, + 1,452, 1,453, 1,454, 1,456, 1,457, 1,458, 1,462, 1,463, + 1,464, 1,467, 1,468, 1,469, 1,470, 1,471, 1,472, 1,473, 1,474, 1,475, 1,476, 1,477, 1,478, 1,479, 1,480, 1,481, 1,482, 1,483, 1,484, 1,486, 1,487, 1,488, 1,489, 1,490, 1,491, 1,134, 1,494, 1,495, 1,497, 1,499, 1,501, 1,503, @@ -1408,110 +1417,110 @@ static const unsigned char ag_key_ch[] = { 69, 73,255, 65, 73,255, 67, 79, 82, 84,255, 33, 35, 36, 38, 39, 40, 42, 44, 46, 47, 60, 61, 62, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, 85, 86, 87, 88, 92,255, 66, 68, 84,255, 42, 47, - 255, 35, 36, 38, 46, 47,255, 73, 83,255, 76, 78, 82,255, 68, 78,255, 70, - 78,255, 70,255, 84,255, 78,255, 65, 73,255, 82,255, 68, 69, 73, 80, 85, - 255, 42, 47,255, 38, 42, 47, 58, 61,255, 61,255, 42, 47,255, 67, 68, 73, - 255, 65, 73,255, 69, 72,255, 67, 68, 78, 82, 83,255, 67, 90,255, 69,255, - 65,255, 67, 76, 77, 78, 80, 82, 89, 90,255, 65, 67, 80,255, 67, 90,255, - 69, 73, 79,255, 65, 67, 77, 78, 80, 83, 90,255, 65, 68,255, 82, 88,255, - 72, 83,255, 69, 85,255, 65, 66, 67, 69, 73, 83, 87,255, 73,255, 68, 84, - 255, 78, 82,255, 69, 82,255, 84,255, 67, 73, 76, 78, 81, 88,255, 77, 84, - 255, 69, 76,255, 82, 88,255, 70, 78,255, 80,255, 53,255, 67, 68, 75, 88, - 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, 88, - 90,255, 88,255, 72, 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, 88,255, - 76,255, 78, 83,255, 79, 85,255, 67, 68, 72, 73, 74, 80, 82, 83, 88,255, - 68, 86,255, 65, 79, 83, 86,255, 65,255, 80,255, 65, 79,255, 65, 71, 73, - 255, 82, 85,255, 70,255, 84,255, 78,255, 73,255, 66, 83,255, 65, 67, 79, - 82, 85,255, 76, 82,255, 65,255, 67, 68,255, 67, 90,255, 69, 71, 79,255, - 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, - 90,255, 67, 90,255, 66, 67, 73, 78, 90,255, 69,255, 68, 73, 82, 88,255, - 76,255, 71, 72, 73,255, 88,255, 65, 67, 75,255, 66, 73,255, 66, 69, 72, - 73, 80, 84, 85, 89,255, 69, 73,255, 65, 73,255, 67, 82, 84,255, 36, 38, - 42, 47, 61, 65, 66, 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 80, 82, - 83, 84, 86, 87, 88,255, 42, 47,255, 85,255, 76,255, 67,255, 78,255, 47, - 73,255, 61,255, 42, 47,255, 67, 68, 73,255, 65, 73,255, 69, 72,255, 67, - 68, 78, 82, 83,255, 67, 90,255, 69,255, 65,255, 67, 76, 77, 78, 80, 82, - 89, 90,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, - 80, 83, 90,255, 65, 68,255, 82, 88,255, 72, 83,255, 69, 85,255, 65, 66, - 67, 69, 73, 83, 87,255, 73,255, 68, 84,255, 78, 82,255, 69, 82,255, 84, - 255, 67, 73, 76, 78, 88,255, 77, 84,255, 69, 76,255, 85,255, 76,255, 67, - 82, 88,255, 70, 78,255, 80,255, 53,255, 67, 68, 75, 88, 90,255, 69, 79, - 255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, 88, 90,255, 88,255, - 72, 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, 88,255, 76,255, 78, 83, - 255, 79, 85,255, 67, 68, 72, 73, 74, 80, 82, 83, 88,255, 68, 86,255, 65, - 79, 83, 86,255, 65,255, 80,255, 65, 79,255, 65, 71, 73,255, 82, 85,255, - 70,255, 84,255, 78,255, 73,255, 66, 83,255, 65, 67, 79, 82, 85,255, 76, - 82,255, 65,255, 67, 68,255, 67, 90,255, 69, 71, 79,255, 67, 72,255, 86, - 255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 67, 90, - 255, 66, 67, 73, 78, 90,255, 69,255, 68, 73, 82, 88,255, 76,255, 71, 72, - 73,255, 88,255, 65, 67, 75,255, 66, 73,255, 66, 72, 73, 80, 84, 85, 89, - 255, 69, 73,255, 65, 73,255, 67, 82, 84,255, 36, 38, 42, 47, 65, 66, 67, - 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, 86, 87, 88,255, - 36, 38,255, 42, 47,255, 47,255, 76, 80,255, 71, 87,255, 78, 79,255, 36, - 38, 39, 67, 68, 70, 72, 73, 76, 78, 80, 83,255, 78, 88,255, 69, 72, 76, - 86,255, 66, 68, 84,255, 42, 47,255, 85,255, 76,255, 67,255, 78,255, 35, - 36, 38, 42, 46, 47, 73,255, 47, 61,255, 42, 47,255, 76, 89,255, 69,255, - 66, 83, 87,255, 68, 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 78, 81, - 88,255, 85,255, 76,255, 67,255, 78,255, 78, 83,255, 73, 83,255, 65, 79, - 83,255, 65, 79,255, 70,255, 84,255, 78,255, 73,255, 65, 82, 85,255, 69, - 84, 89,255, 69, 73,255, 36, 42, 47, 65, 66, 67, 68, 69, 70, 72, 73, 76, - 77, 78, 79, 80, 83, 84, 86, 87, 92,255, 85,255, 76,255, 67,255, 78,255, - 73,255, 42, 47,255, 42, 47,255, 42, 47, 92,255, 42, 47,255, 47, 73, 80, - 255, 42, 47,255, 33, 47,255, 67,255, 69, 88,255, 76,255, 66, 68, 72, 80, - 83,255, 40, 65, 66, 67, 68, 69, 72, 76, 77,255, 67,255, 69,255, 76,255, - 66, 68, 72, 83,255, 67,255, 69,255, 76,255, 65, 66, 68, 72, 80,255, 67, - 255, 69,255, 66, 68,255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, 62, - 255, 33, 42, 44, 47, 60, 61, 62,255, 61,255, 42, 47,255, 60, 61,255, 61, - 255, 61, 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 42, 44, - 47, 60, 61, 62, 65, 69, 71, 76, 77, 78, 79, 83, 88,255, 76, 89,255, 69, + 255, 35, 36, 38, 46, 47,255, 73, 83,255, 67, 76, 78, 82,255, 68, 78,255, + 70, 78,255, 70,255, 84,255, 78,255, 65, 73,255, 82,255, 68, 69, 73, 80, + 85,255, 42, 47,255, 38, 42, 47, 58, 61,255, 61,255, 42, 47,255, 67, 68, + 73,255, 65, 73,255, 69, 72,255, 67, 68, 78, 82, 83,255, 67, 90,255, 69, + 255, 65,255, 67, 76, 77, 78, 80, 82, 89, 90,255, 65, 67, 80,255, 67, 90, + 255, 69, 73, 79,255, 65, 67, 77, 78, 80, 83, 90,255, 65, 68,255, 82, 88, + 255, 72, 83,255, 69, 85,255, 65, 66, 67, 69, 73, 83, 87,255, 73,255, 68, + 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 73, 76, 78, 81, 88,255, 77, + 84,255, 69, 76,255, 82, 88,255, 70, 78,255, 80,255, 53,255, 67, 68, 75, + 88, 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, + 88, 90,255, 88,255, 72, 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, 88, + 255, 76,255, 78, 83,255, 79, 85,255, 67, 68, 72, 73, 74, 80, 82, 83, 88, + 255, 68, 86,255, 65, 79, 83, 86,255, 65,255, 80,255, 65, 79,255, 65, 71, + 73,255, 82, 85,255, 70,255, 84,255, 78,255, 73,255, 66, 83,255, 65, 67, + 79, 82, 85,255, 76, 82,255, 65,255, 67, 68,255, 67, 90,255, 69, 71, 79, + 255, 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, + 83, 90,255, 67, 90,255, 66, 67, 73, 78, 90,255, 69,255, 68, 73, 82, 88, + 255, 76,255, 71, 72, 73,255, 88,255, 65, 67, 75,255, 66, 73,255, 66, 69, + 72, 73, 80, 84, 85, 89,255, 69, 73,255, 65, 73,255, 67, 82, 84,255, 36, + 38, 42, 47, 61, 65, 66, 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 80, + 82, 83, 84, 86, 87, 88,255, 42, 47,255, 85,255, 76,255, 67,255, 78,255, + 47, 73,255, 61,255, 42, 47,255, 67, 68, 73,255, 65, 73,255, 69, 72,255, + 67, 68, 78, 82, 83,255, 67, 90,255, 69,255, 65,255, 67, 76, 77, 78, 80, + 82, 89, 90,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, + 78, 80, 83, 90,255, 65, 68,255, 82, 88,255, 72, 83,255, 69, 85,255, 65, + 66, 67, 69, 73, 83, 87,255, 73,255, 68, 84,255, 78, 82,255, 69, 82,255, + 84,255, 67, 73, 76, 78, 88,255, 77, 84,255, 69, 76,255, 85,255, 76,255, + 67, 82, 88,255, 70, 78,255, 80,255, 53,255, 67, 68, 75, 88, 90,255, 69, + 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, 88, 90,255, 88, + 255, 72, 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, 88,255, 76,255, 78, + 83,255, 79, 85,255, 67, 68, 72, 73, 74, 80, 82, 83, 88,255, 68, 86,255, + 65, 79, 83, 86,255, 65,255, 80,255, 65, 79,255, 65, 71, 73,255, 82, 85, + 255, 70,255, 84,255, 78,255, 73,255, 66, 83,255, 65, 67, 79, 82, 85,255, + 76, 82,255, 65,255, 67, 68,255, 67, 90,255, 69, 71, 79,255, 67, 72,255, + 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 67, + 90,255, 66, 67, 73, 78, 90,255, 69,255, 68, 73, 82, 88,255, 76,255, 71, + 72, 73,255, 88,255, 65, 67, 75,255, 66, 73,255, 66, 72, 73, 80, 84, 85, + 89,255, 69, 73,255, 65, 73,255, 67, 82, 84,255, 36, 38, 42, 47, 65, 66, + 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, 86, 87, 88, + 255, 36, 38,255, 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, 67, 68, + 70, 72, 73, 76, 78, 80, 83,255, 42, 47,255, 47,255, 78, 88,255, 69, 72, + 76, 86,255, 66, 68, 84,255, 42, 47,255, 85,255, 76,255, 67,255, 78,255, + 35, 36, 38, 42, 46, 47, 73,255, 47, 61,255, 42, 47,255, 76, 89,255, 69, 255, 66, 83, 87,255, 68, 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 78, - 88,255, 78, 83,255, 73, 83,255, 65, 79, 83,255, 65, 79,255, 70,255, 84, - 255, 78,255, 73,255, 65, 82, 85,255, 84, 89,255, 69, 73,255, 36, 42, 65, - 66, 67, 68, 69, 70, 72, 76, 77, 78, 79, 80, 83, 84, 86, 87,255, 42, 47, - 255, 44, 47,255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, - 84,255, 69, 84,255, 82,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, - 62, 65, 69, 71, 76, 77, 78, 79, 81, 83, 88,255, 39,255, 61,255, 42, 47, - 255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 82,255, 76, - 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 71, 76, 77, 78, 79, 81, 83, - 88,255, 42, 47,255, 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, 42, - 47, 67, 68, 70, 72, 73, 76, 78, 80, 83, 92,255, 76, 80,255, 71, 87,255, - 78, 79,255, 36, 38, 39, 67, 68, 70, 72, 73, 76, 80, 83,255, 42, 47,255, - 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, 42, 47, 67, 68, 70, 72, - 73, 76, 80, 83, 92,255, 61,255, 60, 61,255, 61,255, 61, 62,255, 69, 84, - 255, 69, 84,255, 76, 82,255, 72,255, 33, 42, 44, 60, 61, 62, 65, 69, 71, - 76, 77, 78, 79, 83, 88,255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, - 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 44, 47, 60, 61, - 62, 65, 69, 71, 76, 78, 79, 83, 88,255, 61,255, 42, 47,255, 61,255, 61, - 255, 61,255, 69, 84,255, 69, 84,255, 33, 44, 47, 60, 61, 62, 65, 69, 71, - 76, 78, 79, 88,255, 61,255, 42, 47,255, 61,255, 61,255, 61,255, 69, 84, - 255, 69, 84,255, 33, 44, 47, 60, 61, 62, 69, 71, 76, 78, 79, 88,255, 61, - 255, 42, 47,255, 61,255, 61,255, 61,255, 69, 84,255, 69, 84,255, 33, 44, - 47, 60, 61, 62, 69, 71, 76, 78, 79,255, 42, 47,255, 61,255, 61,255, 61, - 255, 69, 84,255, 69, 84,255, 33, 47, 60, 61, 62, 69, 71, 76, 78,255, 61, - 255, 42, 47,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, - 69, 84,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 65, 69, 71, - 76, 77, 78, 79, 83, 88, 92,255, 76, 89,255, 69,255, 66, 83, 87,255, 68, - 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 78, 81, 88,255, 78, 83,255, - 73, 83,255, 65, 79, 83,255, 65, 79,255, 70,255, 84,255, 78,255, 73,255, - 65, 82, 85,255, 69, 84, 89,255, 69, 73,255, 36, 42, 65, 66, 67, 68, 69, - 70, 72, 76, 77, 78, 79, 80, 83, 84, 86, 87,255, 39,255, 67, 68, 73,255, - 65, 73,255, 67, 68, 78, 82, 83,255, 67, 90,255, 69,255, 65,255, 67, 77, - 78, 80, 82, 90,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, - 77, 78, 80, 90,255, 65, 68,255, 82, 88,255, 72, 83,255, 65, 67, 69, 73, - 83,255, 77, 84,255, 76,255, 82, 88,255, 78,255, 80,255, 53,255, 67, 68, - 75, 88, 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, - 84, 88, 90,255, 88,255, 72, 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, - 88,255, 76,255, 79, 85,255, 67, 68, 72, 74, 80, 82, 88,255, 79, 86,255, - 65, 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 65,255, 67, 68,255, - 67, 90,255, 69, 71, 79,255, 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, - 73, 76, 77, 78, 80, 82, 83, 90,255, 67, 90,255, 66, 67, 73, 78, 90,255, - 69,255, 68, 73, 82, 88,255, 76,255, 71, 72, 73,255, 88,255, 65, 67,255, - 66, 73,255, 66, 72, 73, 80, 84, 85,255, 65, 73,255, 67, 82, 84,255, 65, - 66, 67, 68, 69, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 42, 47, - 255, 36, 38, 47,255, 42, 47,255, 33, 44, 47,255, 44,255, 42, 47,255, 47, - 79, 81,255, 92,255, 69,255, 69,255, 76, 80,255, 73,255, 71, 87,255, 78, - 79,255, 36, 38, 39, 40, 65, 66, 67, 68, 69, 70, 72, 73, 76, 77, 78, 80, - 83,255, 33,255, 42, 47,255, 47, 92,255 + 81, 88,255, 85,255, 76,255, 67,255, 78,255, 78, 83,255, 73, 83,255, 65, + 79, 83,255, 65, 79,255, 70,255, 84,255, 78,255, 73,255, 65, 82, 85,255, + 69, 84, 89,255, 69, 73,255, 36, 42, 47, 65, 66, 67, 68, 69, 70, 72, 73, + 76, 77, 78, 79, 80, 83, 84, 86, 87, 92,255, 85,255, 76,255, 67,255, 78, + 255, 73,255, 42, 47,255, 42, 47,255, 42, 47, 92,255, 42, 47,255, 47, 73, + 80,255, 42, 47,255, 33, 47,255, 67,255, 69, 88,255, 76,255, 66, 68, 72, + 80, 83,255, 40, 65, 66, 67, 68, 69, 72, 76, 77,255, 67,255, 69,255, 76, + 255, 66, 68, 72, 83,255, 67,255, 69,255, 76,255, 65, 66, 68, 72, 80,255, + 67,255, 69,255, 66, 68,255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, + 62,255, 33, 42, 44, 47, 60, 61, 62,255, 61,255, 42, 47,255, 60, 61,255, + 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 42, + 44, 47, 60, 61, 62, 65, 69, 71, 76, 77, 78, 79, 83, 88,255, 76, 89,255, + 69,255, 66, 83, 87,255, 68, 84,255, 78, 82,255, 69, 82,255, 84,255, 67, + 78, 88,255, 78, 83,255, 73, 83,255, 65, 79, 83,255, 65, 79,255, 70,255, + 84,255, 78,255, 73,255, 65, 82, 85,255, 84, 89,255, 69, 73,255, 36, 42, + 65, 66, 67, 68, 69, 70, 72, 76, 77, 78, 79, 80, 83, 84, 86, 87,255, 42, + 47,255, 44, 47,255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, + 69, 84,255, 69, 84,255, 82,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, + 61, 62, 65, 69, 71, 76, 77, 78, 79, 81, 83, 88,255, 39,255, 61,255, 42, + 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 82,255, + 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 71, 76, 77, 78, 79, 81, + 83, 88,255, 42, 47,255, 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, + 42, 47, 67, 68, 70, 72, 73, 76, 78, 80, 83, 92,255, 76, 80,255, 71, 87, + 255, 78, 79,255, 36, 38, 39, 67, 68, 70, 72, 73, 76, 80, 83,255, 42, 47, + 255, 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, 42, 47, 67, 68, 70, + 72, 73, 76, 80, 83, 92,255, 61,255, 60, 61,255, 61,255, 61, 62,255, 69, + 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 42, 44, 60, 61, 62, 65, 69, + 71, 76, 77, 78, 79, 83, 88,255, 61,255, 42, 47,255, 60, 61,255, 61,255, + 61, 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 44, 47, 60, + 61, 62, 65, 69, 71, 76, 78, 79, 83, 88,255, 61,255, 42, 47,255, 61,255, + 61,255, 61,255, 69, 84,255, 69, 84,255, 33, 44, 47, 60, 61, 62, 65, 69, + 71, 76, 78, 79, 88,255, 61,255, 42, 47,255, 61,255, 61,255, 61,255, 69, + 84,255, 69, 84,255, 33, 44, 47, 60, 61, 62, 69, 71, 76, 78, 79, 88,255, + 61,255, 42, 47,255, 61,255, 61,255, 61,255, 69, 84,255, 69, 84,255, 33, + 44, 47, 60, 61, 62, 69, 71, 76, 78, 79,255, 42, 47,255, 61,255, 61,255, + 61,255, 69, 84,255, 69, 84,255, 33, 47, 60, 61, 62, 69, 71, 76, 78,255, + 61,255, 42, 47,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84, + 255, 69, 84,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 65, 69, + 71, 76, 77, 78, 79, 83, 88, 92,255, 76, 89,255, 69,255, 66, 83, 87,255, + 68, 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 78, 81, 88,255, 78, 83, + 255, 73, 83,255, 65, 79, 83,255, 65, 79,255, 70,255, 84,255, 78,255, 73, + 255, 65, 82, 85,255, 69, 84, 89,255, 69, 73,255, 36, 42, 65, 66, 67, 68, + 69, 70, 72, 76, 77, 78, 79, 80, 83, 84, 86, 87,255, 39,255, 67, 68, 73, + 255, 65, 73,255, 67, 68, 78, 82, 83,255, 67, 90,255, 69,255, 65,255, 67, + 77, 78, 80, 82, 90,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, + 67, 77, 78, 80, 90,255, 65, 68,255, 82, 88,255, 72, 83,255, 65, 67, 69, + 73, 83,255, 77, 84,255, 76,255, 82, 88,255, 78,255, 80,255, 53,255, 67, + 68, 75, 88, 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, + 80, 84, 88, 90,255, 88,255, 72, 83,255, 65, 69, 72, 83,255, 69,255, 68, + 73, 88,255, 76,255, 79, 85,255, 67, 68, 72, 74, 80, 82, 88,255, 79, 86, + 255, 65, 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 65,255, 67, 68, + 255, 67, 90,255, 69, 71, 79,255, 67, 72,255, 86,255, 84,255, 65, 67, 68, + 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 67, 90,255, 66, 67, 73, 78, 90, + 255, 69,255, 68, 73, 82, 88,255, 76,255, 71, 72, 73,255, 88,255, 65, 67, + 255, 66, 73,255, 66, 72, 73, 80, 84, 85,255, 65, 73,255, 67, 82, 84,255, + 65, 66, 67, 68, 69, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 42, + 47,255, 36, 38, 47,255, 42, 47,255, 33, 44, 47,255, 44,255, 42, 47,255, + 47, 79, 81,255, 92,255, 69,255, 69,255, 76, 80,255, 73,255, 71, 87,255, + 78, 79,255, 36, 38, 39, 40, 65, 66, 67, 68, 69, 70, 72, 73, 76, 77, 78, + 80, 83,255, 33,255, 42, 47,255, 47, 92,255 }; static const unsigned char ag_key_act[] = { @@ -1527,191 +1536,191 @@ static const unsigned char ag_key_act[] = { 4,5,7,4,5,4,6,4,2,6,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5,5, 5,4,6,5,4,5,7,5,4,5,4,6,5,7,4,5,5,4,2,7,2,7,6,7,2,2,7,4,7,7,4,5,5,4,7, 7,2,7,4,6,0,6,0,3,3,2,0,2,2,1,1,1,6,6,6,6,6,2,2,6,2,2,6,6,2,2,2,2,2,2, - 7,7,7,2,3,4,3,3,3,4,0,0,4,0,5,0,2,2,4,7,7,4,2,7,7,4,7,7,4,6,7,4,5,4,6, - 4,2,4,7,2,4,2,4,7,2,2,2,7,4,0,0,4,0,3,2,0,0,4,0,4,0,0,4,5,5,5,4,5,5,4, - 7,7,4,7,2,2,7,2,4,5,5,4,5,4,5,4,5,7,5,2,6,6,7,5,4,5,5,5,4,5,5,4,5,5,5, - 4,7,5,6,2,6,7,5,4,5,5,4,5,5,4,7,7,4,7,7,4,2,5,2,2,5,6,5,4,7,4,6,7,4,7, - 7,4,2,7,4,2,4,7,5,7,2,7,2,4,7,5,4,7,2,4,5,5,4,5,6,4,5,4,5,4,5,5,5,6,5, - 4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4, - 2,4,7,7,4,7,7,4,7,2,2,2,7,2,7,7,7,4,7,5,4,7,2,7,7,4,7,4,6,4,7,2,4,5,5, - 5,4,2,7,4,5,4,6,4,2,4,2,4,7,7,4,7,7,7,2,2,4,5,5,4,7,4,5,7,4,5,5,4,5,5, - 5,4,5,7,4,5,4,6,4,2,6,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5, - 5,5,4,2,4,5,7,5,4,5,4,6,5,7,4,5,5,4,2,7,2,7,2,2,2,7,4,7,7,4,5,5,4,7,2, - 7,4,6,0,3,2,0,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,7,7,2,4,0,0,4,7,4,6,4, - 2,4,2,4,2,2,4,0,4,0,0,4,5,5,5,4,5,5,4,7,7,4,7,2,2,7,2,4,5,5,4,5,4,5,4, - 5,7,5,2,6,6,7,5,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5,4,5,5,4,5,5,4,7, - 7,4,7,7,4,2,5,2,2,5,6,5,4,7,4,6,7,4,7,7,4,2,7,4,2,4,7,5,7,2,2,4,7,5,4, - 7,2,4,7,4,6,4,2,5,5,4,5,6,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5, - 6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4,2,4,7,7,4,7,7,4,7,2,2,2, - 7,2,7,7,7,4,7,5,4,7,2,7,7,4,7,4,6,4,7,2,4,5,5,5,4,2,7,4,5,4,6,4,2,4,2, - 4,7,7,4,7,7,7,2,2,4,5,5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4,6,4,2,6,7, - 7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5,5,5,4,2,4,5,7,5,4,5,4,6, - 5,7,4,5,5,4,2,2,7,2,2,2,7,4,7,7,4,5,5,4,7,2,7,4,6,0,3,2,2,2,2,2,2,7,2, - 2,2,2,2,2,2,2,2,2,2,7,7,2,4,5,0,4,0,0,4,2,4,7,5,4,5,5,4,5,2,4,5,0,3,7, - 7,2,7,7,2,7,7,7,4,7,7,4,2,7,7,7,4,3,3,3,4,0,0,4,7,4,6,4,2,4,2,4,0,5,0, - 3,2,2,2,4,0,0,4,0,0,4,7,7,4,7,4,5,6,5,4,5,7,4,7,7,4,2,7,4,2,4,7,2,7,2, - 4,7,4,6,4,2,4,2,4,7,7,4,2,7,4,7,7,7,4,7,7,4,5,4,6,4,2,4,2,4,7,2,7,4,7, - 7,7,4,7,7,4,3,2,2,7,2,7,2,2,7,7,2,2,2,2,7,2,2,2,7,7,3,4,7,4,6,4,2,4,2, - 4,2,4,3,3,4,0,0,4,3,2,3,4,0,0,4,2,7,7,4,0,0,4,5,2,4,5,4,5,5,4,5,4,6,6, - 6,7,7,4,3,5,5,5,5,5,5,5,5,4,5,4,5,4,5,4,6,6,6,7,4,5,4,5,4,5,4,5,6,6,6, - 7,4,5,4,5,4,6,6,4,0,4,0,0,4,0,0,4,0,4,0,0,4,6,3,0,2,1,1,1,4,0,4,0,0,4, - 0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,3,0,2,1,1,1,7,7,2,2,7,7,7,2,7, - 4,7,7,4,7,4,5,6,5,4,5,7,4,7,7,4,2,7,4,2,4,7,2,2,4,7,7,4,2,7,4,7,7,7,4, - 7,7,4,5,4,6,4,2,4,2,4,7,2,7,4,7,7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2,2,7,2, - 2,2,7,7,4,0,0,4,0,2,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,4,5,5,4, - 2,4,6,3,0,2,1,1,1,7,7,2,2,7,7,6,5,2,7,4,3,4,0,4,0,0,4,0,0,4,0,4,0,0,4, - 5,5,4,5,5,4,5,4,5,5,4,2,4,6,3,0,2,1,1,1,2,2,7,7,6,5,2,7,4,0,0,4,7,5,4, - 5,5,4,5,2,4,5,0,3,3,2,7,7,2,7,7,2,7,7,7,3,4,7,5,4,5,5,4,5,2,4,5,0,3,7, - 7,2,7,7,2,7,7,4,0,0,4,7,5,4,5,5,4,5,2,4,5,0,3,3,2,7,7,2,7,7,2,7,7,3,4, - 0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,3,0,1,1,1,7,7,2,2,7,7,7,2, - 7,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,0,2,1,1,1,7,7,2, - 2,7,7,2,7,4,0,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,6,0,2,1,1,1,7,7,2,2,7,7, - 7,4,0,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,6,0,2,1,1,1,7,2,2,7,7,7,4,0,4,0, - 0,4,0,4,0,4,0,4,5,5,4,5,5,4,6,0,2,1,1,1,7,2,2,7,7,4,0,0,4,0,4,0,4,0,4, - 5,5,4,5,5,4,3,2,1,1,1,7,2,2,7,4,0,4,0,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4, - 5,5,4,5,5,4,2,4,6,2,0,2,1,1,1,7,7,2,2,7,7,7,2,7,3,4,7,7,4,7,4,5,6,5,4, - 5,7,4,7,7,4,2,7,4,2,4,7,2,7,2,4,7,7,4,2,7,4,7,7,7,4,7,7,4,5,4,6,4,2,4, - 2,4,7,2,7,4,7,7,7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2,2,7,2,2,2,7,7,4,3,4,5, - 5,5,4,5,5,4,7,2,2,7,7,4,5,5,4,5,4,5,4,5,5,2,6,6,5,4,5,5,5,4,5,5,4,5,5, - 5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,7,7,4,2,2,2,5,7,4,7,5,4,2,4,5,5,4,6,4,5, - 4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7, - 7,4,5,4,6,5,5,4,2,4,7,7,4,7,2,2,7,2,7,7,4,7,7,4,5,5,4,2,7,4,7,7,7,4,5, - 5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4,6,4,2,6,7,7,7,2,5,2,6,2,2,5,4,5, - 5,4,5,5,5,2,5,4,5,4,6,5,5,5,4,2,4,5,7,5,4,5,4,6,5,4,5,5,4,2,2,7,2,2,2, - 4,5,5,4,7,2,7,4,2,2,2,2,7,2,2,2,2,2,7,2,2,2,2,2,4,0,0,4,5,0,2,4,0,0,4, - 5,0,2,4,0,4,0,0,4,2,5,5,4,3,4,7,4,7,4,7,5,4,7,4,5,5,4,5,2,4,5,0,3,3,5, - 5,6,6,5,2,6,7,6,5,7,7,7,4,5,4,0,0,4,2,3,4 + 7,7,7,2,3,4,3,3,3,4,0,0,4,0,5,0,2,2,4,7,7,4,7,2,7,7,4,7,7,4,6,7,4,5,4, + 6,4,2,4,7,2,4,2,4,7,2,2,2,7,4,0,0,4,0,3,2,0,0,4,0,4,0,0,4,5,5,5,4,5,5, + 4,7,7,4,7,2,2,7,2,4,5,5,4,5,4,5,4,5,7,5,2,6,6,7,5,4,5,5,5,4,5,5,4,5,5, + 5,4,7,5,6,2,6,7,5,4,5,5,4,5,5,4,7,7,4,7,7,4,2,5,2,2,5,6,5,4,7,4,6,7,4, + 7,7,4,2,7,4,2,4,7,5,7,2,7,2,4,7,5,4,7,2,4,5,5,4,5,6,4,5,4,5,4,5,5,5,6, + 5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5, + 4,2,4,7,7,4,7,7,4,7,2,2,2,7,2,7,7,7,4,7,5,4,7,2,7,7,4,7,4,6,4,7,2,4,5, + 5,5,4,2,7,4,5,4,6,4,2,4,2,4,7,7,4,7,7,7,2,2,4,5,5,4,7,4,5,7,4,5,5,4,5, + 5,5,4,5,7,4,5,4,6,4,2,6,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6, + 5,5,5,4,2,4,5,7,5,4,5,4,6,5,7,4,5,5,4,2,7,2,7,2,2,2,7,4,7,7,4,5,5,4,7, + 2,7,4,6,0,3,2,0,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,7,7,2,4,0,0,4,7,4,6, + 4,2,4,2,4,2,2,4,0,4,0,0,4,5,5,5,4,5,5,4,7,7,4,7,2,2,7,2,4,5,5,4,5,4,5, + 4,5,7,5,2,6,6,7,5,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5,4,5,5,4,5,5,4, + 7,7,4,7,7,4,2,5,2,2,5,6,5,4,7,4,6,7,4,7,7,4,2,7,4,2,4,7,5,7,2,2,4,7,5, + 4,7,2,4,7,4,6,4,2,5,5,4,5,6,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5, + 5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4,2,4,7,7,4,7,7,4,7,2,2, + 2,7,2,7,7,7,4,7,5,4,7,2,7,7,4,7,4,6,4,7,2,4,5,5,5,4,2,7,4,5,4,6,4,2,4, + 2,4,7,7,4,7,7,7,2,2,4,5,5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4,6,4,2,6, + 7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5,5,5,4,2,4,5,7,5,4,5,4, + 6,5,7,4,5,5,4,2,2,7,2,2,2,7,4,7,7,4,5,5,4,7,2,7,4,6,0,3,2,2,2,2,2,2,7, + 2,2,2,2,2,2,2,2,2,2,2,7,7,2,4,5,0,4,7,5,4,5,5,4,5,2,4,5,0,3,7,7,2,7,7, + 2,7,7,7,4,0,0,4,2,4,7,7,4,2,7,7,7,4,3,3,3,4,0,0,4,7,4,6,4,2,4,2,4,0,5, + 0,3,2,2,2,4,0,0,4,0,0,4,7,7,4,7,4,5,6,5,4,5,7,4,7,7,4,2,7,4,2,4,7,2,7, + 2,4,7,4,6,4,2,4,2,4,7,7,4,2,7,4,7,7,7,4,7,7,4,5,4,6,4,2,4,2,4,7,2,7,4, + 7,7,7,4,7,7,4,3,2,2,7,2,7,2,2,7,7,2,2,2,2,7,2,2,2,7,7,3,4,7,4,6,4,2,4, + 2,4,2,4,3,3,4,0,0,4,3,2,3,4,0,0,4,2,7,7,4,0,0,4,5,2,4,5,4,5,5,4,5,4,6, + 6,6,7,7,4,3,5,5,5,5,5,5,5,5,4,5,4,5,4,5,4,6,6,6,7,4,5,4,5,4,5,4,5,6,6, + 6,7,4,5,4,5,4,6,6,4,0,4,0,0,4,0,0,4,0,4,0,0,4,6,3,0,2,1,1,1,4,0,4,0,0, + 4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,3,0,2,1,1,1,7,7,2,2,7,7,7,2, + 7,4,7,7,4,7,4,5,6,5,4,5,7,4,7,7,4,2,7,4,2,4,7,2,2,4,7,7,4,2,7,4,7,7,7, + 4,7,7,4,5,4,6,4,2,4,2,4,7,2,7,4,7,7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2,2,7, + 2,2,2,7,7,4,0,0,4,0,2,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,4,5,5, + 4,2,4,6,3,0,2,1,1,1,7,7,2,2,7,7,6,5,2,7,4,3,4,0,4,0,0,4,0,0,4,0,4,0,0, + 4,5,5,4,5,5,4,5,4,5,5,4,2,4,6,3,0,2,1,1,1,2,2,7,7,6,5,2,7,4,0,0,4,7,5, + 4,5,5,4,5,2,4,5,0,3,3,2,7,7,2,7,7,2,7,7,7,3,4,7,5,4,5,5,4,5,2,4,5,0,3, + 7,7,2,7,7,2,7,7,4,0,0,4,7,5,4,5,5,4,5,2,4,5,0,3,3,2,7,7,2,7,7,2,7,7,3, + 4,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,3,0,1,1,1,7,7,2,2,7,7,7, + 2,7,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,0,2,1,1,1,7,7, + 2,2,7,7,2,7,4,0,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,6,0,2,1,1,1,7,7,2,2,7, + 7,7,4,0,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,6,0,2,1,1,1,7,2,2,7,7,7,4,0,4, + 0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,6,0,2,1,1,1,7,2,2,7,7,4,0,0,4,0,4,0,4,0, + 4,5,5,4,5,5,4,3,2,1,1,1,7,2,2,7,4,0,4,0,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5, + 4,5,5,4,5,5,4,2,4,6,2,0,2,1,1,1,7,7,2,2,7,7,7,2,7,3,4,7,7,4,7,4,5,6,5, + 4,5,7,4,7,7,4,2,7,4,2,4,7,2,7,2,4,7,7,4,2,7,4,7,7,7,4,7,7,4,5,4,6,4,2, + 4,2,4,7,2,7,4,7,7,7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2,2,7,2,2,2,7,7,4,3,4, + 5,5,5,4,5,5,4,7,2,2,7,7,4,5,5,4,5,4,5,4,5,5,2,6,6,5,4,5,5,5,4,5,5,4,5, + 5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,7,7,4,2,2,2,5,7,4,7,5,4,2,4,5,5,4,6,4, + 5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2, + 7,7,4,5,4,6,5,5,4,2,4,7,7,4,7,2,2,7,2,7,7,4,7,7,4,5,5,4,2,7,4,7,7,7,4, + 5,5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4,6,4,2,6,7,7,7,2,5,2,6,2,2,5,4, + 5,5,4,5,5,5,2,5,4,5,4,6,5,5,5,4,2,4,5,7,5,4,5,4,6,5,4,5,5,4,2,2,7,2,2, + 2,4,5,5,4,7,2,7,4,2,2,2,2,7,2,2,2,2,2,7,2,2,2,2,2,4,0,0,4,5,0,2,4,0,0, + 4,5,0,2,4,0,4,0,0,4,2,5,5,4,3,4,7,4,7,4,7,5,4,7,4,5,5,4,5,2,4,5,0,3,3, + 5,5,6,6,5,2,6,7,6,5,7,7,7,4,5,4,0,0,4,2,3,4 }; static const unsigned short ag_key_parm[] = { 0,162,164,163, 0,427,424, 0, 4, 0, 6, 0, 0, 0, 0, 0,438, 98, - 135, 0, 0, 0, 0,498, 0,464, 0,523,426,465, 0,162,164,163, 0,427, + 135, 0, 0, 0, 0,498, 0,465, 0,523,426,466, 0,162,164,163, 0,427, 424, 0,513,502, 0,496, 0,500,515, 0,282,284,324, 0,286,118,326, 0, - 48,184, 0,322, 0, 0,188, 0, 0,426,424, 0,432, 0,420, 0,168, 52, - 428, 0,430,418, 56,422, 0,192,194,288, 0,334,336, 0,340,342,344, 0, - 328,330,130,332, 0,338, 42,346, 0,196,308, 0,290,310, 0,146, 0, 40, - 0, 0, 0, 0, 0, 0,392,398, 0, 44,200, 0, 0, 54, 0,170,198, 50, - 60,178, 0, 24, 28, 0, 30, 0, 80, 14, 0, 0, 0, 18, 68, 0, 0, 66, - 0, 0, 0, 76,204, 0, 0,102, 32, 0, 0, 78,128,140, 0,106,110, 0, + 50,184, 0,322, 0, 0,188, 0, 0,426,424, 0,432, 0,420, 0,168, 54, + 428, 0,430,418, 58,422, 0,192,194,288, 0,334,336, 0,340,342,344, 0, + 328,330,130,332, 0,338, 44,346, 0,196,308, 0,290,310, 0,146, 0, 42, + 0, 0, 0, 0, 0, 0,392,398, 0, 46,200, 0, 0, 56, 0,170,198, 52, + 62,178, 0, 24, 28, 0, 30, 0, 80, 14, 0, 0, 0, 18, 70, 0, 0, 68, + 0, 0, 0, 34,204, 0, 0,102, 32, 0, 0, 78,128,140, 0,106,110, 0, 202,206, 0, 12,142,172, 0, 20, 26, 0, 4, 0, 6, 0, 0,100,292,312, 0, 22,348,138, 0,364, 0,370, 0,366,376,374,368,378, 0,382,384, 0, 356,372, 0,354, 0,350,360,358,362, 0,380, 0,352,386, 0,272, 0,390, 396, 0,388, 0,394,400, 0,212, 0,402,210,208, 0, 0, 0, 92, 10, 0, 134,144, 0,278,280, 0,444, 0,108, 0, 0,446,132, 0, 0,268, 84,112, - 314, 0, 70, 0,124,294, 0, 94, 0, 82,316, 0, 88, 0,214,126, 0, 72, - 104, 0, 0,296, 46,404, 0,114,406, 0,216, 0, 36, 0, 34, 0, 0, 0, - 8, 0, 0, 64,276, 0, 96,180,274, 0,176, 0, 0,218,220, 0,434, 0, + 314, 0, 72, 0,124,294, 0, 94, 0, 82,316, 0, 88, 0,214,126, 0, 74, + 104, 0, 0,296, 48,404, 0,114,406, 0,216, 0, 38, 0, 36, 0, 0, 0, + 8, 0, 0, 66,276, 0, 96,180,274, 0,176, 0, 0,218,220, 0,434, 0, 228,230, 0,236,238, 0,242,306,244, 0,246,190, 0,248, 0,320, 0, 0, 222,232,224,226, 0,234, 0,240, 0, 0,250, 0,442,438, 0,298,440,408, 0,436, 0,256, 0,410,254,186,252, 0,120,122, 0,304,260,318, 0,270, - 0,412,262, 74, 0,300,414, 0, 0, 2, 0,258,174,136, 0, 0, 90, 0, - 58, 86, 0,302,416, 0,264,116, 0,266, 0,182,438, 98,135,231,241, 0, + 0,412,262, 76, 0,300,414, 0, 0, 2, 0,258,174,136, 0, 0, 90, 0, + 60, 86, 0,302,416, 0,264,116, 0,266, 0,182,438, 98,135,231,241, 0, 493, 0, 0,506,432,504,166,152,154,156,158, 0, 0,160, 0, 0,162,164, - 0, 0, 0, 0, 0, 0, 38, 16, 62, 0,460, 0,162,164,163, 0,427,424, - 0,438, 98,135, 0, 0, 0, 24, 28, 0, 0, 30, 32, 0, 20, 26, 0, 22, - 4, 0, 36, 0, 34, 0, 0, 0, 8, 0, 0, 0, 0, 40, 0, 0, 0, 38, - 0,427,424, 0,135,465, 0,161,432, 0,464, 0,427,424, 0,282,284,324, - 0,286,326, 0, 48,184, 0,322, 0, 0,188, 0, 0,426,424, 0,432, 0, - 420, 0,168, 52,428, 0,430,418, 56,422, 0,192,194,288, 0,334,336, 0, - 340,342,344, 0,328,330,332, 0,338, 42,346, 0,196,308, 0,290,310, 0, - 392,398, 0, 44,200, 0, 0, 54, 0, 0,198, 50, 60, 0, 30, 0, 80, 14, - 0, 18, 68, 0, 0, 66, 0, 0, 0, 76,204, 28, 0, 0, 0, 0,202,206, - 0, 12, 0, 0,292,312, 0, 22,348, 0,364, 0,370, 0,366,376,374,368, - 378, 0,382,384, 0,356,372, 0,354, 0,350,360,358,362, 0,380, 0,352, - 386, 0,272, 0,390,396, 0,388, 0,394,400, 0,212, 0,402,210,208, 0, - 0, 0, 92, 10, 0,278,280, 0,444, 0, 0, 0,446, 0,268, 84,314, 0, - 70,294, 0, 94, 0, 82,316, 0, 88, 0,214, 0, 72, 0, 0,296, 46,404, - 0, 0,406, 0, 36, 0, 34, 0, 0, 0, 0, 0, 64,276, 0, 96,216,274, - 0, 0, 0,218,220, 0,434, 0,228,230, 0,236,238, 0,242,306,244, 0, - 246,190, 0,248, 0,320, 0, 0,222,232,224,226, 0,234, 0,240, 0, 0, - 250, 0,442,438, 0,298,440,408, 0,436, 0,256, 0,410,254,186,252, 0, - 0, 0,304,260,318, 0,270, 0,412,262, 74, 0,300,414, 0, 0, 2, 0, - 258, 0, 0, 0, 90, 0, 58, 86, 0,302,416, 0,264, 0,266, 0, 98,135, - 465, 0,432, 0, 0, 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 16, 62, 0, 0,427,424, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, - 0, 0,464, 0,427,424, 0,282,284,324, 0,286,326, 0, 48,184, 0,322, - 0, 0,188, 0, 0,426,424, 0,432, 0,420, 0,168, 52,428, 0,430,418, - 56,422, 0,192,194,288, 0,334,336, 0,340,342,344, 0,328,330,332, 0, - 338, 42,346, 0,196,308, 0,290,310, 0,392,398, 0, 44,200, 0, 0, 54, - 0, 0,198, 50, 60, 0, 30, 0, 80, 14, 0, 18, 68, 0, 0, 66, 0, 0, - 0, 76,204, 28, 0, 0, 0,202,206, 0, 12, 0, 0, 4, 0, 6, 0, 0, - 292,312, 0, 22,348, 0,364, 0,370, 0,366,376,374,368,378, 0,382,384, - 0,356,372, 0,354, 0,350,360,358,362, 0,380, 0,352,386, 0,272, 0, - 390,396, 0,388, 0,394,400, 0,212, 0,402,210,208, 0, 0, 0, 92, 10, - 0,278,280, 0,444, 0, 0, 0,446, 0,268, 84,314, 0, 70,294, 0, 94, - 0, 82,316, 0, 88, 0,214, 0, 72, 0, 0,296, 46,404, 0, 0,406, 0, - 36, 0, 34, 0, 0, 0, 0, 0, 64,276, 0, 96,216,274, 0, 0, 0,218, - 220, 0,434, 0,228,230, 0,236,238, 0,242,306,244, 0,246,190, 0,248, - 0,320, 0, 0,222,232,224,226, 0,234, 0,240, 0, 0,250, 0,442,438, - 0,298,440,408, 0,436, 0,256, 0,410,254,186,252, 0, 0, 0,304,260, - 318, 0,270, 0,412,262, 74, 0,300,414, 0, 0, 0,258, 0, 0, 0, 90, - 0, 58, 86, 0,302,416, 0,264, 0,266, 0, 98,135,465, 0, 0, 0, 0, - 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 62, 0, 0, - 98,135, 0,427,424, 0, 0, 0,128,140, 0,134,144, 0,132, 0, 0, 98, - 135,231,130,146, 0,142,138, 0,126, 96,136, 0, 14, 18, 0, 0, 12, 10, - 16, 0,162,164,163, 0,427,424, 0, 4, 0, 6, 0, 0, 0, 0, 0,438, - 98,135,426, 0, 0, 0, 0,426,465, 0,427,424, 0, 52, 56, 0, 44, 0, - 54, 50, 60, 0, 80, 14, 0, 18, 68, 0, 0, 66, 0, 0, 0, 76, 0, 0, - 0, 0, 4, 0, 6, 0, 0, 0, 0, 0, 92, 10, 0, 0, 84, 0, 94, 70, - 82, 0, 72, 88, 0, 36, 0, 34, 0, 0, 0, 0, 0, 96, 0, 64, 0, 2, - 74, 90, 0, 58, 86, 0,464, 0, 0, 48, 0, 42, 0, 0, 78, 12, 0, 0, - 0, 0, 46, 0, 0, 0, 16, 62,460, 0, 4, 0, 6, 0, 0, 0, 0, 0, - 0, 0,426,427, 0,427,424, 0,426, 0,460, 0,427,424, 0, 0,100, 96, - 0,427,424, 0,182, 0, 0,168, 0,170,178, 0,172, 0,152,156,160,180, - 174, 0,241,166,152,154,156,158,160,162,164, 0,168, 0,170, 0,172, 0, - 152,156,160,174, 0,168, 0,170, 0,172, 0,166,152,156,160,176, 0,168, - 0,170, 0,152,156, 0,498, 0,427,424, 0,513,502, 0,496, 0,500,515, - 0,182,523,493, 0,506,432,504, 0,498, 0,427,424, 0,513,502, 0,496, - 0,500,515, 0,106,110, 0,108,112, 0,120,122, 0, 0, 0,182,523,493, - 0,506,432,504,118,102, 0, 0,124,104,114, 0,116, 0, 52, 56, 0, 44, - 0, 54, 50, 60, 0, 80, 14, 0, 18, 68, 0, 0, 66, 0, 0, 0, 76, 0, - 0, 0, 92, 10, 0, 0, 84, 0, 94, 70, 82, 0, 72, 88, 0, 36, 0, 34, - 0, 0, 0, 0, 0, 96, 0, 64, 0, 74, 90, 0, 58, 86, 0,464,465, 48, - 0, 42, 0, 0, 78, 12, 0, 0, 0, 46, 0, 0, 0, 16, 62, 0,427,424, - 0,493, 0, 0,498, 0,427,424, 0,513,502, 0,496, 0,500,515, 0,106, - 110, 0,108,112, 0,114, 0,120,122, 0, 0, 0,182,523,493, 0,506,432, - 504,118,102, 0, 0,124,104,150,148, 0,116, 0,233, 0,498, 0,427,424, - 0,513,502, 0,496, 0,500,515, 0,106,110, 0,108,112, 0,114, 0,120, - 122, 0, 0, 0,182,523,493, 0,506,432,504, 0, 0,124,104,150,148, 0, - 116, 0,427,424, 0,128,140, 0,134,144, 0,132, 0, 0, 98,135,231,426, - 0,130,146, 0,142,138, 0,126, 96,136,460, 0,128,140, 0,134,144, 0, - 132, 0, 0, 98,135,231,130,146, 0,142,138, 0, 96,136, 0,427,424, 0, - 128,140, 0,134,144, 0,132, 0, 0, 98,135,231,426, 0,130,146, 0,142, - 138, 0, 96,136,460, 0,498, 0,513,502, 0,496, 0,500,515, 0,106,110, - 0,108,112, 0,120,122, 0, 0, 0,182,523,493,506,432,504,118,102, 0, - 0,124,104,114, 0,116, 0,498, 0,427,424, 0,513,502, 0,496, 0,500, - 515, 0,106,110, 0,108,112, 0,120,122, 0, 0, 0,182,493, 0,506,432, - 504,118,102, 0, 0,104,114, 0,116, 0,498, 0,427,424, 0,502, 0,496, - 0,500, 0,106,110, 0,108,112, 0,182,493, 0,506,432,504,118,102, 0, - 0,104,114,116, 0,498, 0,427,424, 0,502, 0,496, 0,500, 0,106,110, - 0,108,112, 0,182,493, 0,506,432,504,102, 0, 0,104,114,116, 0,498, - 0,427,424, 0,502, 0,496, 0,500, 0,106,110, 0,108,112, 0,182,493, - 0,506,432,504,102, 0, 0,104,114, 0,427,424, 0,502, 0,496, 0,500, - 0,106,110, 0,108,112, 0,498, 0,506,432,504,102, 0, 0,104, 0,498, - 0,523,426, 0,427,424, 0,513,502, 0,496, 0,500,515, 0,106,110, 0, - 108,112, 0,120,122, 0, 0, 0,182, 0,493, 0,506,432,504,118,102, 0, - 0,124,104,114, 0,116,460, 0, 52, 56, 0, 44, 0, 54, 50, 60, 0, 80, - 14, 0, 18, 68, 0, 0, 66, 0, 0, 0, 76, 0, 0, 0, 0, 92, 10, 0, - 0, 84, 0, 94, 70, 82, 0, 72, 88, 0, 36, 0, 34, 0, 0, 0, 0, 0, - 96, 0, 64, 0, 2, 74, 90, 0, 58, 86, 0,464,465, 48, 0, 42, 0, 0, - 78, 12, 0, 0, 0, 46, 0, 0, 0, 16, 62, 0,231, 0,282,284,324, 0, - 286,326, 0,322, 0, 0,188,184, 0,426,424, 0,432, 0,420, 0,168,428, - 0,430,418,422, 0,192,194,288, 0,334,336, 0,340,342,344, 0,328,330, - 332, 0,338,346, 0,196,308, 0,290,310, 0,392,398, 0, 0, 0, 0,198, - 200, 0,202,206, 0, 0, 0,292,312, 0,348, 0,364, 0,370, 0,366,376, - 374,368,378, 0,382,384, 0,356,372, 0,354, 0,350,360,358,362, 0,380, - 0,352,386, 0,272, 0,390,396, 0,388, 0,394,400, 0,212, 0,402,210, - 208, 0, 0, 0,278,280, 0,444, 0, 0,446, 0,268,314, 0,294,316, 0, - 296,404, 0, 0,406, 0,216,274,276, 0,218,220, 0,434, 0,228,230, 0, - 236,238, 0,242,306,244, 0,246,190, 0,248, 0,320, 0, 0,222,232,224, - 226, 0,234, 0,240, 0, 0,250, 0,442,438, 0,298,440,408, 0,436, 0, - 256, 0,410,254,186,252, 0, 0, 0,304,260,318, 0,270, 0,412,262, 0, - 300,414, 0, 0, 0,258, 0, 0, 0, 0,302,416, 0,264, 0,266, 0, 0, - 0, 0, 0,204, 0, 0, 0, 0, 0,214, 0, 0, 0, 0, 0, 0,427,424, - 0, 98,135, 0, 0,427,424, 0,182,493, 0, 0,493, 0,427,424, 0, 0, - 150,148, 0,460, 0,130, 0,146, 0,128,140, 0,142, 0,134,144, 0,132, - 0, 0, 98,135,231,241,166,152,154,156,158, 0,160,138,162,164,126, 96, - 136, 0,182, 0,427,424, 0, 0,460, 0 + 0, 0, 0, 0, 0, 0, 40, 16, 64, 0,461, 0,162,164,163, 0,427,424, + 0,438, 98,135, 0, 0, 0, 24, 28, 0, 34, 0, 30, 32, 0, 20, 26, 0, + 22, 4, 0, 38, 0, 36, 0, 0, 0, 8, 0, 0, 0, 0, 42, 0, 0, 0, + 40, 0,427,424, 0,135,466, 0,161,432, 0,465, 0,427,424, 0,282,284, + 324, 0,286,326, 0, 50,184, 0,322, 0, 0,188, 0, 0,426,424, 0,432, + 0,420, 0,168, 54,428, 0,430,418, 58,422, 0,192,194,288, 0,334,336, + 0,340,342,344, 0,328,330,332, 0,338, 44,346, 0,196,308, 0,290,310, + 0,392,398, 0, 46,200, 0, 0, 56, 0, 0,198, 52, 62, 0, 30, 0, 80, + 14, 0, 18, 70, 0, 0, 68, 0, 0, 0, 34,204, 28, 0, 0, 0, 0,202, + 206, 0, 12, 0, 0,292,312, 0, 22,348, 0,364, 0,370, 0,366,376,374, + 368,378, 0,382,384, 0,356,372, 0,354, 0,350,360,358,362, 0,380, 0, + 352,386, 0,272, 0,390,396, 0,388, 0,394,400, 0,212, 0,402,210,208, + 0, 0, 0, 92, 10, 0,278,280, 0,444, 0, 0, 0,446, 0,268, 84,314, + 0, 72,294, 0, 94, 0, 82,316, 0, 88, 0,214, 0, 74, 0, 0,296, 48, + 404, 0, 0,406, 0, 38, 0, 36, 0, 0, 0, 0, 0, 66,276, 0, 96,216, + 274, 0, 0, 0,218,220, 0,434, 0,228,230, 0,236,238, 0,242,306,244, + 0,246,190, 0,248, 0,320, 0, 0,222,232,224,226, 0,234, 0,240, 0, + 0,250, 0,442,438, 0,298,440,408, 0,436, 0,256, 0,410,254,186,252, + 0, 0, 0,304,260,318, 0,270, 0,412,262, 76, 0,300,414, 0, 0, 2, + 0,258, 0, 0, 0, 90, 0, 60, 86, 0,302,416, 0,264, 0,266, 0, 98, + 135,466, 0,432, 0, 0, 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 16, 64, 0, 0,427,424, 0, 4, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 0,465, 0,427,424, 0,282,284,324, 0,286,326, 0, 50,184, 0, + 322, 0, 0,188, 0, 0,426,424, 0,432, 0,420, 0,168, 54,428, 0,430, + 418, 58,422, 0,192,194,288, 0,334,336, 0,340,342,344, 0,328,330,332, + 0,338, 44,346, 0,196,308, 0,290,310, 0,392,398, 0, 46,200, 0, 0, + 56, 0, 0,198, 52, 62, 0, 30, 0, 80, 14, 0, 18, 70, 0, 0, 68, 0, + 0, 0, 34,204, 28, 0, 0, 0,202,206, 0, 12, 0, 0, 4, 0, 6, 0, + 0,292,312, 0, 22,348, 0,364, 0,370, 0,366,376,374,368,378, 0,382, + 384, 0,356,372, 0,354, 0,350,360,358,362, 0,380, 0,352,386, 0,272, + 0,390,396, 0,388, 0,394,400, 0,212, 0,402,210,208, 0, 0, 0, 92, + 10, 0,278,280, 0,444, 0, 0, 0,446, 0,268, 84,314, 0, 72,294, 0, + 94, 0, 82,316, 0, 88, 0,214, 0, 74, 0, 0,296, 48,404, 0, 0,406, + 0, 38, 0, 36, 0, 0, 0, 0, 0, 66,276, 0, 96,216,274, 0, 0, 0, + 218,220, 0,434, 0,228,230, 0,236,238, 0,242,306,244, 0,246,190, 0, + 248, 0,320, 0, 0,222,232,224,226, 0,234, 0,240, 0, 0,250, 0,442, + 438, 0,298,440,408, 0,436, 0,256, 0,410,254,186,252, 0, 0, 0,304, + 260,318, 0,270, 0,412,262, 76, 0,300,414, 0, 0, 0,258, 0, 0, 0, + 90, 0, 60, 86, 0,302,416, 0,264, 0,266, 0, 98,135,466, 0, 0, 0, + 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 64, 0, + 0, 98,135, 0,128,140, 0,134,144, 0,132, 0, 0, 98,135,231,130,146, + 0,142,138, 0,126, 96,136, 0,427,424, 0, 0, 0, 14, 18, 0, 0, 12, + 10, 16, 0,162,164,163, 0,427,424, 0, 4, 0, 6, 0, 0, 0, 0, 0, + 438, 98,135,426, 0, 0, 0, 0,426,466, 0,427,424, 0, 54, 58, 0, 46, + 0, 56, 52, 62, 0, 80, 14, 0, 18, 70, 0, 0, 68, 0, 0, 0, 34, 0, + 0, 0, 0, 4, 0, 6, 0, 0, 0, 0, 0, 92, 10, 0, 0, 84, 0, 94, + 72, 82, 0, 74, 88, 0, 38, 0, 36, 0, 0, 0, 0, 0, 96, 0, 66, 0, + 2, 76, 90, 0, 60, 86, 0,465, 0, 0, 50, 0, 44, 0, 0, 78, 12, 0, + 0, 0, 0, 48, 0, 0, 0, 16, 64,461, 0, 4, 0, 6, 0, 0, 0, 0, + 0, 0, 0,426,427, 0,427,424, 0,426, 0,461, 0,427,424, 0, 0,100, + 96, 0,427,424, 0,182, 0, 0,168, 0,170,178, 0,172, 0,152,156,160, + 180,174, 0,241,166,152,154,156,158,160,162,164, 0,168, 0,170, 0,172, + 0,152,156,160,174, 0,168, 0,170, 0,172, 0,166,152,156,160,176, 0, + 168, 0,170, 0,152,156, 0,498, 0,427,424, 0,513,502, 0,496, 0,500, + 515, 0,182,523,493, 0,506,432,504, 0,498, 0,427,424, 0,513,502, 0, + 496, 0,500,515, 0,106,110, 0,108,112, 0,120,122, 0, 0, 0,182,523, + 493, 0,506,432,504,118,102, 0, 0,124,104,114, 0,116, 0, 54, 58, 0, + 46, 0, 56, 52, 62, 0, 80, 14, 0, 18, 70, 0, 0, 68, 0, 0, 0, 34, + 0, 0, 0, 92, 10, 0, 0, 84, 0, 94, 72, 82, 0, 74, 88, 0, 38, 0, + 36, 0, 0, 0, 0, 0, 96, 0, 66, 0, 76, 90, 0, 60, 86, 0,465,466, + 50, 0, 44, 0, 0, 78, 12, 0, 0, 0, 48, 0, 0, 0, 16, 64, 0,427, + 424, 0,493, 0, 0,498, 0,427,424, 0,513,502, 0,496, 0,500,515, 0, + 106,110, 0,108,112, 0,114, 0,120,122, 0, 0, 0,182,523,493, 0,506, + 432,504,118,102, 0, 0,124,104,150,148, 0,116, 0,233, 0,498, 0,427, + 424, 0,513,502, 0,496, 0,500,515, 0,106,110, 0,108,112, 0,114, 0, + 120,122, 0, 0, 0,182,523,493, 0,506,432,504, 0, 0,124,104,150,148, + 0,116, 0,427,424, 0,128,140, 0,134,144, 0,132, 0, 0, 98,135,231, + 426, 0,130,146, 0,142,138, 0,126, 96,136,461, 0,128,140, 0,134,144, + 0,132, 0, 0, 98,135,231,130,146, 0,142,138, 0, 96,136, 0,427,424, + 0,128,140, 0,134,144, 0,132, 0, 0, 98,135,231,426, 0,130,146, 0, + 142,138, 0, 96,136,461, 0,498, 0,513,502, 0,496, 0,500,515, 0,106, + 110, 0,108,112, 0,120,122, 0, 0, 0,182,523,493,506,432,504,118,102, + 0, 0,124,104,114, 0,116, 0,498, 0,427,424, 0,513,502, 0,496, 0, + 500,515, 0,106,110, 0,108,112, 0,120,122, 0, 0, 0,182,493, 0,506, + 432,504,118,102, 0, 0,104,114, 0,116, 0,498, 0,427,424, 0,502, 0, + 496, 0,500, 0,106,110, 0,108,112, 0,182,493, 0,506,432,504,118,102, + 0, 0,104,114,116, 0,498, 0,427,424, 0,502, 0,496, 0,500, 0,106, + 110, 0,108,112, 0,182,493, 0,506,432,504,102, 0, 0,104,114,116, 0, + 498, 0,427,424, 0,502, 0,496, 0,500, 0,106,110, 0,108,112, 0,182, + 493, 0,506,432,504,102, 0, 0,104,114, 0,427,424, 0,502, 0,496, 0, + 500, 0,106,110, 0,108,112, 0,498, 0,506,432,504,102, 0, 0,104, 0, + 498, 0,523,426, 0,427,424, 0,513,502, 0,496, 0,500,515, 0,106,110, + 0,108,112, 0,120,122, 0, 0, 0,182, 0,493, 0,506,432,504,118,102, + 0, 0,124,104,114, 0,116,461, 0, 54, 58, 0, 46, 0, 56, 52, 62, 0, + 80, 14, 0, 18, 70, 0, 0, 68, 0, 0, 0, 34, 0, 0, 0, 0, 92, 10, + 0, 0, 84, 0, 94, 72, 82, 0, 74, 88, 0, 38, 0, 36, 0, 0, 0, 0, + 0, 96, 0, 66, 0, 2, 76, 90, 0, 60, 86, 0,465,466, 50, 0, 44, 0, + 0, 78, 12, 0, 0, 0, 48, 0, 0, 0, 16, 64, 0,231, 0,282,284,324, + 0,286,326, 0,322, 0, 0,188,184, 0,426,424, 0,432, 0,420, 0,168, + 428, 0,430,418,422, 0,192,194,288, 0,334,336, 0,340,342,344, 0,328, + 330,332, 0,338,346, 0,196,308, 0,290,310, 0,392,398, 0, 0, 0, 0, + 198,200, 0,202,206, 0, 0, 0,292,312, 0,348, 0,364, 0,370, 0,366, + 376,374,368,378, 0,382,384, 0,356,372, 0,354, 0,350,360,358,362, 0, + 380, 0,352,386, 0,272, 0,390,396, 0,388, 0,394,400, 0,212, 0,402, + 210,208, 0, 0, 0,278,280, 0,444, 0, 0,446, 0,268,314, 0,294,316, + 0,296,404, 0, 0,406, 0,216,274,276, 0,218,220, 0,434, 0,228,230, + 0,236,238, 0,242,306,244, 0,246,190, 0,248, 0,320, 0, 0,222,232, + 224,226, 0,234, 0,240, 0, 0,250, 0,442,438, 0,298,440,408, 0,436, + 0,256, 0,410,254,186,252, 0, 0, 0,304,260,318, 0,270, 0,412,262, + 0,300,414, 0, 0, 0,258, 0, 0, 0, 0,302,416, 0,264, 0,266, 0, + 0, 0, 0, 0,204, 0, 0, 0, 0, 0,214, 0, 0, 0, 0, 0, 0,427, + 424, 0, 98,135, 0, 0,427,424, 0,182,493, 0, 0,493, 0,427,424, 0, + 0,150,148, 0,461, 0,130, 0,146, 0,128,140, 0,142, 0,134,144, 0, + 132, 0, 0, 98,135,231,241,166,152,154,156,158, 0,160,138,162,164,126, + 96,136, 0,182, 0,427,424, 0, 0,461, 0 }; static const unsigned short ag_key_jmp[] = { @@ -1739,171 +1748,172 @@ static const unsigned short ag_key_jmp[] = { 220,223, 0, 0, 0, 0,243,246,381,248, 0, 23, 0, 25, 0, 14, 17, 27, 0, 31, 35, 38, 41, 43, 57, 70, 90,120,147,155,159,165,181,203,240,259, 269,277,294,323,368,378,227,232,239,384,251, 0,253,256,260, 0, 0, 0, - 0, 0, 0, 0,426,430, 0,270,272, 0,439,274,278, 0,282,285, 0,446, - 289, 0, 0, 0,452, 0,454, 0,295,456, 0,458, 0,264,442,449,461,299, - 0, 0, 0, 0, 0,304,469, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,313,315, 0,308,483,487,310,490, 0, 0, 0, 0, 0, 0, - 0, 0, 0,317, 0,499,502,504,321, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,324, 0,515,519,522,327, 0, 0, 0, 0, 0, 0, 0, 0, - 330,332, 0,334,336, 0,534, 0,537,540, 0,543, 0, 0,344, 0,554,346, - 0,351,355, 0,559,357, 0,562, 0,338, 0,341,556,349,565, 0,365, 0, - 0,363,574, 0, 0, 0, 0, 0,580, 0, 0, 0, 0, 0, 0, 0, 0,588, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,586,590,596,599,602, - 0, 0, 0, 0, 0, 0, 0,614,616,372,374, 0, 0, 0,624, 0, 0, 0, - 626, 0,376,378, 0,383,385, 0,368,619,630,632,380,635,388,391,397, 0, - 404, 0, 0,399,648,408,414, 0,419, 0,656, 0,416,658, 0, 0, 0, 0, - 0,663,422, 0, 0, 0,670, 0,672, 0,674, 0,432,436, 0,424,427,430, - 676,678, 0, 0, 0, 0,438, 0, 0,448, 0, 0, 0, 0, 0, 0, 0, 0, - 0,450, 0, 0, 0,705, 0,687,690,441,444,446,692, 0,695,698,702,707, - 0, 0, 0, 0, 0, 0, 0, 0,722, 0, 0, 0, 0,731, 0, 0, 0, 0, - 733, 0, 0,456, 0, 0, 0, 0,744, 0,458, 0, 0, 0, 0,725,452,738, - 454,740,746,750,461, 0,463,466, 0, 0, 0, 0,481,765,484, 0,478, 0, - 306,480, 0,493,506,526,546,567,359,577,583,604,638,651,660,667,681,709, - 753,762,470,477,768, 0, 0, 0, 0,487, 0,801, 0,803, 0,805, 0,798, - 807, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,497,499, 0,492, - 817,821,494,824, 0, 0, 0, 0, 0, 0, 0, 0, 0,501, 0,833,836,838, - 505, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,508, 0,849,853, - 856,511, 0, 0, 0, 0, 0, 0, 0, 0,514,516, 0,518,520, 0,868, 0, - 871,874, 0,877, 0, 0,528, 0,888,530, 0,533,537, 0,893,539, 0,896, - 0,522, 0,525,890,899, 0,547, 0, 0,545,907, 0,550, 0,913, 0,915, - 0, 0, 0, 0,917, 0, 0, 0, 0, 0, 0, 0, 0,926, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,924,928,934,937,940, 0, 0, 0, 0, - 0, 0, 0,952,954,557,559, 0, 0, 0,962, 0, 0, 0,964, 0,561,563, - 0,568,570, 0,553,957,968,970,565,973,573,576,582, 0,589, 0, 0,584, - 986,593,599, 0,604, 0,994, 0,601,996, 0, 0, 0, 0, 0,1001,607, 0, - 0, 0,1008, 0,1010, 0,1012, 0,617,621, 0,609,612,615,1014,1016, 0, - 0, 0, 0,623, 0, 0,633, 0, 0, 0, 0, 0, 0, 0, 0, 0,635, 0, - 0, 0,1043, 0,1025,1028,626,629,631,1030, 0,1033,1036,1040,1045, 0, - 0, 0, 0, 0, 0, 0, 0,1060, 0, 0, 0, 0,1069, 0, 0, 0, 0, - 1071, 0, 0,639, 0, 0, 0, 0,1082, 0,641, 0, 0, 0, 0,1063,1076, - 637,1078,1084,1088,644, 0,646,649, 0, 0, 0, 0,664,1102,667, 0,812, - 0,490,814,827,840,860,880,901,541,910,921,942,976,989,998,1005,1019, - 1047,1091,1099,653,660,1105, 0, 0, 0, 0, 0, 0, 0,1137, 0,684, 0, - 0, 0, 0, 0, 0,1145, 0, 0, 0,670,673,677,1142,688,692,1148,694, - 697,701, 0,705,709, 0,1164,716,719,723, 0,732,735,739, 0, 0, 0, 0, - 743, 0,1179, 0,1181, 0,1183, 0, 0, 0, 0,730,1172,1176,1185, 0, - 0, 0, 0, 0, 0, 0,752,756, 0,763, 0, 0,1204, 0, 0, 0,768, 0, - 773,777, 0,1213,779, 0,1216, 0,765,1210,771,1219, 0,788, 0,1226, 0, - 1228, 0,1230, 0,791,793, 0,1234,795, 0,801,806,811, 0,817,820, 0, - 0, 0,1247, 0,1249, 0,1251, 0,828,1253,831, 0,836,838,842, 0,844, - 847, 0,746,1195,1198,748,1201,759,1206,1221,781,785,1232,1237,1240,1244, - 825,1255,1259,1263,851,858,862, 0,864, 0,1288, 0,1290, 0,1292, 0, - 1294, 0,867,869, 0, 0, 0, 0,871,1301,873, 0, 0, 0, 0,1308,875, - 881, 0, 0, 0, 0, 0,1315, 0, 0, 0, 0, 0, 0, 0, 0,1321,1323, - 1326,885,887, 0,889, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,1344,1346,1348,893, 0, 0, 0, 0, 0, 0, 0, 0,1355,1357,1359, - 895, 0, 0, 0, 0, 0,1367,1369, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,1374,898, 0,1376,1379,1382,1384, 0, 0, 0, 0, 0, + 0, 0, 0, 0,426,430, 0,273,275, 0,270,439,277,281, 0,285,288, 0, + 447,292, 0, 0, 0,453, 0,455, 0,298,457, 0,459, 0,264,442,450,462, + 302, 0, 0, 0, 0, 0,307,470, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,316,318, 0,311,484,488,313,491, 0, 0, 0, 0, 0, + 0, 0, 0, 0,320, 0,500,503,505,324, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,327, 0,516,520,523,330, 0, 0, 0, 0, 0, 0, 0, + 0,333,335, 0,337,339, 0,535, 0,538,541, 0,544, 0, 0,347, 0,555, + 349, 0,354,358, 0,560,360, 0,563, 0,341, 0,344,557,352,566, 0,368, + 0, 0,366,575, 0, 0, 0, 0, 0,581, 0, 0, 0, 0, 0, 0, 0, 0, + 589, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,587,591,597,600, + 603, 0, 0, 0, 0, 0, 0, 0,615,617,375,377, 0, 0, 0,625, 0, 0, + 0,627, 0,379,381, 0,386,388, 0,371,620,631,633,383,636,391,394,400, + 0,407, 0, 0,402,649,411,417, 0,422, 0,657, 0,419,659, 0, 0, 0, + 0, 0,664,425, 0, 0, 0,671, 0,673, 0,675, 0,435,439, 0,427,430, + 433,677,679, 0, 0, 0, 0,441, 0, 0,451, 0, 0, 0, 0, 0, 0, 0, + 0, 0,453, 0, 0, 0,706, 0,688,691,444,447,449,693, 0,696,699,703, + 708, 0, 0, 0, 0, 0, 0, 0, 0,723, 0, 0, 0, 0,732, 0, 0, 0, + 0,734, 0, 0,459, 0, 0, 0, 0,745, 0,461, 0, 0, 0, 0,726,455, + 739,457,741,747,751,464, 0,466,469, 0, 0, 0, 0,484,766,487, 0,479, + 0,309,481, 0,494,507,527,547,568,362,578,584,605,639,652,661,668,682, + 710,754,763,473,480,769, 0, 0, 0, 0,490, 0,802, 0,804, 0,806, 0, + 799,808, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,500,502, 0, + 495,818,822,497,825, 0, 0, 0, 0, 0, 0, 0, 0, 0,504, 0,834,837, + 839,508, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,511, 0,850, + 854,857,514, 0, 0, 0, 0, 0, 0, 0, 0,517,519, 0,521,523, 0,869, + 0,872,875, 0,878, 0, 0,531, 0,889,533, 0,536,540, 0,894,542, 0, + 897, 0,525, 0,528,891,900, 0,550, 0, 0,548,908, 0,553, 0,914, 0, + 916, 0, 0, 0, 0,918, 0, 0, 0, 0, 0, 0, 0, 0,927, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,925,929,935,938,941, 0, 0, 0, + 0, 0, 0, 0,953,955,560,562, 0, 0, 0,963, 0, 0, 0,965, 0,564, + 566, 0,571,573, 0,556,958,969,971,568,974,576,579,585, 0,592, 0, 0, + 587,987,596,602, 0,607, 0,995, 0,604,997, 0, 0, 0, 0, 0,1002,610, + 0, 0, 0,1009, 0,1011, 0,1013, 0,620,624, 0,612,615,618,1015,1017, + 0, 0, 0, 0,626, 0, 0,636, 0, 0, 0, 0, 0, 0, 0, 0, 0,638, + 0, 0, 0,1044, 0,1026,1029,629,632,634,1031, 0,1034,1037,1041,1046, + 0, 0, 0, 0, 0, 0, 0, 0,1061, 0, 0, 0, 0,1070, 0, 0, 0, + 0,1072, 0, 0,642, 0, 0, 0, 0,1083, 0,644, 0, 0, 0, 0,1064, + 1077,640,1079,1085,1089,647, 0,649,652, 0, 0, 0, 0,667,1103,670, 0, + 813, 0,493,815,828,841,861,881,902,544,911,922,943,977,990,999,1006,1020, + 1048,1092,1100,656,663,1106, 0, 0, 0, 0,687, 0, 0, 0, 0, 0, 0, + 1141, 0, 0, 0,673,676,680,1138,691,695,1144,697,700,704, 0, 0, 0, + 0,1160, 0,708,712, 0,1165,719,722,726, 0,735,738,742, 0, 0, 0, + 0,746, 0,1180, 0,1182, 0,1184, 0, 0, 0, 0,733,1173,1177,1186, + 0, 0, 0, 0, 0, 0, 0,755,759, 0,766, 0, 0,1205, 0, 0, 0,771, + 0,776,780, 0,1214,782, 0,1217, 0,768,1211,774,1220, 0,791, 0,1227, + 0,1229, 0,1231, 0,794,796, 0,1235,798, 0,804,809,814, 0,820,823, + 0, 0, 0,1248, 0,1250, 0,1252, 0,831,1254,834, 0,839,841,845, 0, + 847,850, 0,749,1196,1199,751,1202,762,1207,1222,784,788,1233,1238,1241, + 1245,828,1256,1260,1264,854,861,865, 0,867, 0,1289, 0,1291, 0,1293, + 0,1295, 0,870,872, 0, 0, 0, 0,874,1302,876, 0, 0, 0, 0,1309, + 878,884, 0, 0, 0, 0, 0,1316, 0, 0, 0, 0, 0, 0, 0, 0,1322, + 1324,1327,888,890, 0,892, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,1345,1347,1349,896, 0, 0, 0, 0, 0, 0, 0, 0,1356, + 1358,1360,898, 0, 0, 0, 0, 0,1368,1370, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,1375,901, 0,1377,1380,1383,1385, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1414, 0,1395,900, 0,1397,1400,1403,1405,902,905,1408,1411,907,910,912, - 1417,914, 0,925,929, 0,936, 0, 0,1439, 0, 0, 0,941, 0,944,948, - 0,1448,950, 0,1451, 0,938,1445,1454, 0,959,961, 0,1460,963, 0,969, - 974,979, 0,985,988, 0, 0, 0,1473, 0,1475, 0,1477, 0,996,1479,999, - 0,1004,1008, 0,1010,1013, 0,917,919,921,1436,932,1441,1456,952,956, - 1463,1466,1470,993,1481,1485,1488,1017,1024, 0, 0, 0, 0, 0,1510, 0, + 0, 0,1415, 0,1396,903, 0,1398,1401,1404,1406,905,908,1409,1412,910, + 913,915,1418,917, 0,928,932, 0,939, 0, 0,1440, 0, 0, 0,944, 0, + 947,951, 0,1449,953, 0,1452, 0,941,1446,1455, 0,962,964, 0,1461,966, + 0,972,977,982, 0,988,991, 0, 0, 0,1474, 0,1476, 0,1478, 0,999, + 1480,1002, 0,1007,1011, 0,1013,1016, 0,920,922,924,1437,935,1442,1457, + 955,959,1464,1467,1471,996,1482,1486,1489,1020,1027, 0, 0, 0, 0, 0, + 1511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1538, 0,1517,1031, 0,1519,1522,1525, + 1527,1033,1036,1530,1533,1038,1041,1536, 0,1541,1043, 0,1046, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1537, 0,1516,1028, 0,1518,1521,1524,1526,1030, - 1033,1529,1532,1035,1038,1535, 0,1540,1040, 0,1043, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,1584, 0,1563,1048, 0,1565,1568,1571,1573,1576,1579, + 1050,1053,1582, 0,1587,1055, 0, 0, 0, 0,1074, 0, 0, 0, 0, 0, + 0,1611, 0, 0, 0,1058,1061,1605,1063,1067,1608,1078,1082,1614,1084, + 1087,1091,1095, 0,1111, 0, 0, 0, 0, 0, 0,1636, 0, 0, 0,1097, + 1100,1104,1633,1115,1119,1639,1121,1125, 0, 0, 0, 0,1145, 0, 0, 0, + 0, 0, 0,1660, 0, 0, 0,1129,1132,1654,1134,1138,1657,1149,1153,1663, + 1155,1159,1163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1697, 0,1681,1165, 0,1683,1686,1688,1167,1170, + 1691,1694,1172,1175,1177,1700,1179, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1737, 0,1718, + 0,1720,1723,1726,1728,1182,1185,1731,1734,1187,1189,1740,1191, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1757, 0, + 1759,1762,1764,1766,1194,1197,1768,1771,1199,1201,1203, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1788, 0,1790, + 1793,1795,1797,1206,1799,1802,1208,1210,1212, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1818, 0,1820,1823,1825,1827, + 1215,1829,1832,1217,1219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,1221,1847,1850,1852,1854,1223,1856,1859,1225, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,1583, 0,1562,1045, 0,1564,1567,1570,1572,1575,1578,1047,1050, - 1581, 0,1586,1052, 0, 0, 0, 0,1071, 0, 0, 0, 0, 0, 0,1610, 0, - 0, 0,1055,1058,1604,1060,1064,1607,1075,1079,1613,1081,1084,1088,1092, - 0,1108, 0, 0, 0, 0, 0, 0,1635, 0, 0, 0,1094,1097,1101,1632, - 1112,1116,1638,1118,1122, 0, 0, 0, 0,1142, 0, 0, 0, 0, 0, 0, - 1659, 0, 0, 0,1126,1129,1653,1131,1135,1656,1146,1150,1662,1152,1156, - 1160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,1696, 0,1680,1162, 0,1682,1685,1687,1164,1167,1690,1693, - 1169,1172,1174,1699,1176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1736, 0,1717, 0,1719,1722, - 1725,1727,1179,1182,1730,1733,1184,1186,1739,1188, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1756, 0,1758,1761, - 1763,1765,1191,1194,1767,1770,1196,1198,1200, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1787, 0,1789,1792,1794,1796, - 1203,1798,1801,1205,1207,1209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1817, 0,1819,1822,1824,1826,1212,1828, - 1831,1214,1216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,1218,1846,1849,1851,1853,1220,1855,1858,1222, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,1893, 0,1871,1873, 0,1876,1879,1882,1884,1224,1227,1887, - 1890,1229,1232,1234,1896,1236,1239, 0,1249,1253, 0,1260, 0, 0,1919, - 0, 0, 0,1265, 0,1270,1274, 0,1928,1276, 0,1931, 0,1262,1925,1268, - 1934, 0,1285,1287, 0,1941,1289, 0,1295,1300,1305, 0,1311,1314, 0, - 0, 0,1954, 0,1956, 0,1958, 0,1322,1960,1325, 0,1330,1332,1336, 0, - 1338,1341, 0,1241,1243,1245,1916,1256,1921,1936,1278,1282,1944,1947,1951, - 1319,1962,1966,1970,1345,1352, 0,1356, 0, 0, 0, 0, 0, 0, 0, 0, - 1359,1994,1998,1361,1364, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2007, - 2010,2012, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1367, 0, - 2021,2025,2028, 0, 0, 0, 0, 0, 0, 0, 0,1370,1372, 0,2039,2042, - 2045, 0,1374, 0,1379, 0, 0,2054, 0, 0, 0, 0,2059, 0, 0, 0, 0, - 0, 0, 0, 0,2066, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2064,2068,2074,2077,2080, 0, 0, 0, 0, 0, 0, 0,2092,2094,1386,1388, - 0, 0, 0,2102, 0, 0, 0,2104, 0,1393,1395, 0,1382,2097,2108,1390, - 2110,1398,1401, 0,1403,1405, 0, 0, 0, 0,2124,1410, 0,1412,1415,1417, - 0, 0, 0, 0,1420, 0, 0,1430, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1432, 0, 0, 0,2152, 0,2134,2137,1423,1426,1428,2139, 0,2142,2145, - 2149,2154, 0, 0, 0, 0, 0, 0, 0, 0,2169, 0, 0, 0, 0,2178, 0, - 0, 0, 0,2180, 0, 0,1436, 0, 0, 0, 0,2191, 0, 0, 0, 0, 0, - 2172,2185,1434,2187,2193,2196, 0, 0, 0, 0,1438,2206,1441, 0,2001, - 2014,2032,2048,1377,2057,2062,2082,2113,2121,1407,2127,2130,2156,2199, - 2209, 0, 0, 0, 0, 0, 0,2230, 0, 0, 0, 0, 0, 0,2237, 0, 0, - 0, 0, 0, 0,2246, 0, 0, 0,1444, 0,1453, 0,1456, 0,1462, 0, 0, - 1466, 0, 0, 0, 0, 0,2264, 0, 0, 0,1446,1449, 0, 0,2255,2257, - 0,2259,2262,1469,2267, 0,1471,1474,1478, 0, 0, 0, 0, 0, 0,2290, - 1482, 0 + 0, 0, 0, 0, 0,1894, 0,1872,1874, 0,1877,1880,1883,1885,1227,1230, + 1888,1891,1232,1235,1237,1897,1239,1242, 0,1252,1256, 0,1263, 0, 0, + 1920, 0, 0, 0,1268, 0,1273,1277, 0,1929,1279, 0,1932, 0,1265,1926, + 1271,1935, 0,1288,1290, 0,1942,1292, 0,1298,1303,1308, 0,1314,1317, + 0, 0, 0,1955, 0,1957, 0,1959, 0,1325,1961,1328, 0,1333,1335,1339, + 0,1341,1344, 0,1244,1246,1248,1917,1259,1922,1937,1281,1285,1945,1948, + 1952,1322,1963,1967,1971,1348,1355, 0,1359, 0, 0, 0, 0, 0, 0, 0, + 0,1362,1995,1999,1364,1367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2008, + 2011,2013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1370, 0, + 2022,2026,2029, 0, 0, 0, 0, 0, 0, 0, 0,1373,1375, 0,2040,2043, + 2046, 0,1377, 0,1382, 0, 0,2055, 0, 0, 0, 0,2060, 0, 0, 0, 0, + 0, 0, 0, 0,2067, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2065,2069,2075,2078,2081, 0, 0, 0, 0, 0, 0, 0,2093,2095,1389,1391, + 0, 0, 0,2103, 0, 0, 0,2105, 0,1396,1398, 0,1385,2098,2109,1393, + 2111,1401,1404, 0,1406,1408, 0, 0, 0, 0,2125,1413, 0,1415,1418,1420, + 0, 0, 0, 0,1423, 0, 0,1433, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1435, 0, 0, 0,2153, 0,2135,2138,1426,1429,1431,2140, 0,2143,2146, + 2150,2155, 0, 0, 0, 0, 0, 0, 0, 0,2170, 0, 0, 0, 0,2179, 0, + 0, 0, 0,2181, 0, 0,1439, 0, 0, 0, 0,2192, 0, 0, 0, 0, 0, + 2173,2186,1437,2188,2194,2197, 0, 0, 0, 0,1441,2207,1444, 0,2002, + 2015,2033,2049,1380,2058,2063,2083,2114,2122,1410,2128,2131,2157,2200, + 2210, 0, 0, 0, 0, 0, 0,2231, 0, 0, 0, 0, 0, 0,2238, 0, 0, + 0, 0, 0, 0,2247, 0, 0, 0,1447, 0,1456, 0,1459, 0,1465, 0, 0, + 1469, 0, 0, 0, 0, 0,2265, 0, 0, 0,1449,1452, 0, 0,2256,2258, + 0,2260,2263,1472,2268, 0,1474,1477,1481, 0, 0, 0, 0, 0, 0,2291, + 1485, 0 }; static const unsigned short ag_key_index[] = { - 16,389,433,463,472,463,772, 0,809,772,1109,433,1134,1134, 0, 0, 0, - 1140,1140,1134,1151,1151,1134,1167, 0,1134,1134, 0, 0, 0,1140,1140, - 1134,1151,1151,1134,1167, 0,1187,1266,1296,1298,1304, 0,1298, 0, 0, - 772,1311,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318, - 1318,1328,1334,1350,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, - 1151,1151,1151,1151,1151,1151,1318,1318,1318,1318,1318,1318,1318,1318, - 1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318, - 1318,1318,1318,1318,1318,1318,1318, 0,1328,1334,1350,1151,1151,1151,1151, - 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, - 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, - 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, - 1151,1151,1361,1361,1361,1361,1371,1371,1350,1350,1350,1328,1328,1334, - 1334,1334,1334,1334,1334,1334,1334,1334,1334,1334, 0, 0, 0, 0,1151, - 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, - 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, - 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, - 1151,1151,1151,1151,1151,1151,1151,1151,1151,1361,1361,1361,1361,1371, - 1371,1350,1350,1350,1328,1328,1334,1334,1334,1334,1334,1334,1334,1334, - 1334,1334,1334,1387,1318,1419,1140,1318,1151,1491,1140, 0,1140, 0,1513, - 0,1140,1140,1140,1140,1140, 0, 0, 0,1419,1542, 0,1560,1419, 0,1419, - 1419,1419,1588, 0,1140, 0, 0, 0, 0, 0, 0, 0, 0, 0,1419,1419, - 1616, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1641,1665,1641,1665,1151, - 1641,1641,1641,1641,1419,1701,1741,1741,1773,1804,1834,1861,1151,1140, - 1140,1140,1140,1140,1140,1140,1134,1134,1140,1140,1140,1140, 0,1140,1140, - 1140, 0, 0,1304,1616,1304,1616,1298,1304,1304,1304,1304,1304,1304,1304, - 1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1665,1616, - 1616,1616,1665,1898,1304,1616,1665,1304,1304,1304,1187, 0, 0, 0,1151, - 1151,1973,1140,1311,1328,1334,1350, 0, 0, 0, 0,1151,1151,1151,1151, - 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, - 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, - 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, - 1151,1151,1151,1151,1151,1151,1361,1361,1361,1361,1371,1371,1350,1350, - 1350,1328,1328,1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,1334, - 1151,1992,2213,2213,1134,1134, 0, 0,1140,1140, 0, 0,1140,1140,2233, - 2233, 0, 0,1151,1151,1151,1151,1151,1151,1134,1134,1134,1134,1134,1134, - 1134,1134,1134,1134,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, - 1140,1151,1151,1151,1151,1134,1311,1311,1140, 0,1140, 0,1151,1140,1140, - 1140, 0, 0,1560,1419,1419, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1151, 0,1641,1641,1641,1641,1641,1641,1641,1151,1151,1151,1151,1151,1151, - 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151, - 1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1151,1140,1140,1140, - 1140,1140,1134,1140,1140, 0,1140,1140, 0,1140,1140,1140,1140,1151,1151, - 1151,1151,1140,1140,1140,1318,1318,1318,2240,1318,1151,1151,1151,1318, - 1318,2244,1560,1560,1513,2244, 0,2249,2213,1560, 0,1151,1513,1513,1513, - 1513,1513,2253, 0, 0, 0,1151, 0,1134,1151,1151,1151,1151,1151,1151, - 1151,1151,1151,1151, 0,1641,1641,1641,1641,1641,1151,1151,1151,1151,1151, - 1151,1151,1151,1151,1151,1151,1151,1140,1140,1140,1140,1140,1140,1140, - 1140,1151,1151,1151,2244,1560,2270,1151,2288,1318,1560,1151,1513,1134, - 2293,2293,1140, 0, 0,1140,1134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0,1701,1701,1741,1741,1741,1741,1741,1741,1773,1773,1804,1804,1140,1140, - 1140,1334,1560,1151,1151,1134,1140, 0, 0, 0,1334, 0 + 16,389,433,464,473,464,773, 0,810,773,1110,433,1135,1135, 0, 0,1147, + 0,1163,1163,1135,1147,1147,1135,1168, 0,1135,1135, 0, 0,1147, 0, + 1163,1163,1135,1147,1147,1135,1168, 0,1188,1267,1297,1299,1305, 0,1299, + 0, 0,773,1312,1319,1319,1319,1319,1319,1319,1319,1319,1319,1319,1319, + 1319,1319,1319,1329,1335,1351,1147,1147,1147,1147,1147,1147,1147,1147, + 1147,1147,1147,1147,1147,1147,1147,1147,1319,1319,1319,1319,1319,1319, + 1319,1319,1319,1319,1319,1319,1319,1319,1319,1319,1319,1319,1319,1319, + 1319,1319,1319,1319,1319,1319,1319,1319,1319, 0,1329,1335,1351,1147,1147, + 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, + 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, + 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, + 1147,1147,1147,1147,1362,1362,1362,1362,1372,1372,1351,1351,1351,1329, + 1329,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335, 0, 0, 0, + 0,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, + 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, + 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, + 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1362,1362,1362,1362, + 1372,1372,1351,1351,1351,1329,1329,1335,1335,1335,1335,1335,1335,1335, + 1335,1335,1335,1335,1388,1319,1420,1163,1319,1147,1492,1163, 0,1163, 0, + 0,1147, 0,1514,1163,1163,1163,1163, 0, 0, 0,1420,1543, 0,1561,1420, + 0,1420,1420,1420,1589, 0,1163, 0, 0, 0, 0, 0, 0, 0, 0, 0,1420, + 1420,1617, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1642,1666,1642,1666, + 1147,1642,1642,1642,1642,1420,1702,1742,1742,1774,1805,1835,1862,1147, + 1163,1163,1163,1163,1163,1163,1163,1135,1135,1163,1163,1163,1163, 0,1163, + 1163,1163, 0, 0,1305,1617,1305,1617,1299,1305,1305,1305,1305,1305,1305, + 1305,1305,1305,1305,1305,1305,1305,1305,1305,1305,1305,1305,1305,1666, + 1617,1617,1617,1666,1899,1305,1617,1666,1305,1305,1305,1188, 0, 0, 0, + 1147,1147,1974,1163,1312,1329,1335,1351, 0, 0, 0, 0,1147,1147,1147, + 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, + 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, + 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, + 1147,1147,1147,1147,1147,1147,1147,1362,1362,1362,1362,1372,1372,1351, + 1351,1351,1329,1329,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335, + 1335,1147,1993,2214,2214,1135,1135, 0, 0,1163,1163, 0, 0,1163,1163, + 2234,2234, 0, 0,1147,1147,1147,1147,1147,1135,1135,1135,1135,1135,1135, + 1135,1135,1135,1135,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, + 1163,1147,1147,1147,1147,1135,1312,1312,1163, 0,1163, 0,1163,1163,1163, + 0,1163,1163, 0, 0,1561,1420,1420, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,1147, 0,1642,1642,1642,1642,1642,1642,1642,1147,1147,1147,1147, + 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, + 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1163, + 1163,1163,1163,1163,1135,1163,1163, 0,1163,1163, 0,1163,1163,1163,1163, + 1147,1147,1147,1147,1163,1163,1163,1319,1319,1319,2241,1319,1147,1147, + 1147,1319,1319,2245,1561,1561,1514,2245, 0,2250,2214,1561, 0,1147,1147, + 1514,1514,1514,1514,1514,2254,1147,1163,1163,1163, 0, 0, 0, 0,1135, + 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, 0,1642,1642,1642,1642, + 1642,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1163, + 1163,1163,1163,1163,1163,1163,1163,1147,1147,1147,2245,1561,2271,1147, + 2289,1319,1561,1147,1514,1135,2294,2294,1163,1147, 0, 0,1135, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1702,1702,1742,1742,1742,1742,1742, + 1742,1774,1774,1805,1805,1163,1163,1163,1335,1561,1147,1147,1135,1163, + 0, 0, 0,1335,1163, 0 }; static const unsigned char ag_key_ends[] = { @@ -1920,11 +1930,11 @@ static const unsigned char ag_key_ends[] = { 76,0, 84,0, 77,0, 76,0, 82,84,0, 76,78,0, 77,0, 88,84,0, 84,76,69,0, 78,68,69,70,0, 69,82,73,76,79,71,0, 79,82,68,0, 72,71,0, 82,0, 72,76,0, 10,0, 83,83,0, 65,84,65,0, 69,88,84,0, -69,70,73,78,69,0, 70,0, 69,0, 68,73,70,0, 82,79,82,0, 69,70,0, -68,69,70,0, 67,76,85,68,69,0, 71,77,65,0, 78,68,69,70,0, 61,0, -61,0, 73,0, 72,76,0, 71,0, 82,0, 79,67,75,0, 84,69,0, 76,76,0, -69,71,0, 76,0, 80,0, 71,0, 66,0, 72,79,0, 83,69,0, 70,0, -82,89,0, 85,0, 68,69,68,0, 78,0, 78,0, 73,76,76,0, 88,0, +69,70,73,78,69,0, 72,79,0, 70,0, 69,0, 68,73,70,0, 82,79,82,0, +69,70,0, 68,69,70,0, 67,76,85,68,69,0, 71,77,65,0, 78,68,69,70,0, +61,0, 61,0, 73,0, 72,76,0, 71,0, 82,0, 79,67,75,0, 84,69,0, +76,76,0, 69,71,0, 76,0, 80,0, 71,0, 66,0, 72,79,0, 83,69,0, +70,0, 82,89,0, 85,0, 68,69,68,0, 78,0, 78,0, 73,76,76,0, 88,0, 66,67,0, 65,76,76,0, 73,0, 73,0, 75,0, 84,0, 77,80,0, 80,0, 83,72,0, 69,84,0, 70,73,82,83,84,0, 73,0, 67,76,73,66,0, 85,76,69,0, 70,73,82,83,84,0, 73,0, 77,69,0, 71,69,0, 84,0, @@ -1989,7 +1999,7 @@ static const unsigned char ag_key_ends[] = { static const unsigned short ag_tcv[] = { 38, 38,680,680,680,680,680,680,680,680, 1,423,680,680,680,680,680,680, 680,680,680,680,680,680,680,680,680,680,680,680,680,680,680, 1,524,681, - 680,682,521,511,683,459,458,519,517,454,518,429,520,684,685,686,686,687, + 680,682,521,511,683,460,459,519,517,455,518,429,520,684,685,686,686,687, 687,687,687,688,688,680,425,689,680,690,691,692,693,694,693,695,693,696, 697,698,697,697,697,697,697,699,697,697,697,700,697,701,697,697,697,702, 697,697,680,703,680,509,704,692,693,694,693,695,693,696,697,698,697,697, @@ -2189,15 +2199,15 @@ static void ag_undo(void) { static const unsigned short ag_tstt[] = { 704,702,701,700,699,698,697,696,695,694,693,691,682,438,434,433,429,427,425, - 424,423,164,163,162,135,134,1,0,51,52, + 424,423,164,163,162,135,134,38,1,0,51,52, 1,0, 704,702,701,700,699,698,697,696,695,694,693,691,682,438,429,427,425,424,423, - 164,163,162,135,134,64,1,0,11,34,35,36,37,51,52,53,65,66,133,428,442, -457,456,455,453,452,451,450,449,448,447,446,440,433,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,465, - 432,429,427,425,424,423,161,135,1,0,138, -457,456,455,453,452,451,450,449,448,447,446,440,433,0,60,67,68,74,76,78,79, - 80,81,82,83,84,86,87, + 164,163,162,135,134,64,38,1,0,11,34,35,36,37,51,52,53,65,66,133,428,442, +458,457,456,454,453,452,451,450,449,448,447,446,440,433,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,466, + 432,429,427,425,424,423,161,135,38,1,0,138, +458,457,456,454,453,452,451,450,449,448,447,446,440,433,0,60,67,68,74,76,78, + 79,80,81,82,83,84,85,87,88, 704,702,701,700,699,698,697,696,695,694,693,691,682,679,678,677,676,675,674, 673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656, 655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638, @@ -2207,10 +2217,11 @@ static const unsigned short ag_tstt[] = { 581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564, 563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546, 545,491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474, - 473,472,471,470,469,468,467,466,465,464,463,462,461,455,453,451,450,447, - 445,444,443,441,439,432,431,430,429,427,425,424,423,135,134,1,0,51,52, + 473,472,471,470,469,468,467,466,465,464,463,462,456,454,453,451,450,447, + 445,444,443,441,439,432,431,430,429,427,425,424,423,135,134,38,1,0,51, + 52, 423,0,45, -434,433,429,427,425,424,423,0,39,40,41,45,46,47,49,54,55, +434,433,429,427,425,424,423,38,0,39,40,41,45,46,47,49,54,55, 704,702,701,700,699,698,697,696,695,694,693,691,682,679,678,677,676,675,674, 673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656, 655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638, @@ -2220,8 +2231,9 @@ static const unsigned short ag_tstt[] = { 581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564, 563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546, 545,491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474, - 473,472,471,470,469,468,467,466,465,464,463,462,461,455,453,451,450,447, - 445,444,443,441,439,432,431,430,429,427,425,424,423,135,134,1,0,51,52, + 473,472,471,470,469,468,467,466,465,464,463,462,456,454,453,451,450,447, + 445,444,443,441,439,432,431,430,429,427,425,424,423,135,134,38,1,0,51, + 52, 704,702,701,700,699,698,697,696,695,694,693,691,682,679,678,677,676,675,674, 673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656, 655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638, @@ -2231,91 +2243,97 @@ static const unsigned short ag_tstt[] = { 581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564, 563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546, 545,491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474, - 473,472,471,470,469,468,467,466,465,464,463,462,461,455,453,451,450,447, - 445,444,443,441,439,434,433,429,427,425,424,423,135,134,1,0,21,30,31,32, - 33,54,55,63,76,80,81,88,96,133,244,257,258,259,260,261,262,263,264,265, - 266,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284, - 285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302, - 303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320, - 321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338, - 339,340,341,342,343,344,346,347,348,349,350,351,352,353,354,355,356,357, - 358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375, - 376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393, - 394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411, - 412,442, + 473,472,471,470,469,468,467,466,465,464,463,462,456,454,453,451,450,447, + 445,444,443,441,439,434,433,429,427,425,424,423,135,134,38,1,0,21,30,31, + 32,33,45,54,55,63,76,80,81,89,97,133,244,257,258,259,260,261,262,263, + 264,265,266,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282, + 283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300, + 301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318, + 319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336, + 337,338,339,340,341,342,343,344,346,347,348,349,350,351,352,353,354,355, + 356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373, + 374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391, + 392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409, + 410,411,412,442, 704,702,701,700,699,698,697,696,695,694,693,691,682,438,429,427,425,424,423, 164,163,162,135,134,64,38,1,0,11,35,36,51,52,53,65,66,133,428,442, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, 681,1,0,51,52, 681,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,460,429,231,135,134,1,0,51,52, 681,1,0,51,52, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, 445,444,443,441,439,1,0,51,52, 704,703,702,701,700,699,698,697,696,695,694,693,689,688,687,686,685,684,681, 520,429,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,88,133,442, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,89,133,442, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, +681,1,0,51,52, +681,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,460,429,231,135,134,1,0,51,52, 681,0,10,12,435, -681,0,10,12,435, -681,0,10,12,435, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,77,88, - 90,131,133,166,196,198,203,204,205,206,207,208,209,210,211,212,213,214, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,77,89, + 91,131,133,166,196,198,203,204,205,206,207,208,209,210,211,212,213,214, 215,216,217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,77,88, - 90,131,133,166,196,198,203,204,205,206,207,208,209,210,211,212,213,214, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,77,89, + 91,131,133,166,196,198,203,204,205,206,207,208,209,210,211,212,213,214, 215,216,217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, 445,444,443,441,439,0,69,70,71,72,73, 689,681,0,10,12,13,14,435,436, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, - 458,454,438,434,433,429,427,426,425,424,423,164,163,162,135,134,38,1,0, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,455,438,434,433,429,427,426,425,424,423,164,163,162,135,134,38,1,0, 51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,491, 490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,460,459,458,455,454,453,445, - 444,443,441,439,434,433,431,430,429,427,426,425,424,423,1,0,51,52, + 471,470,469,468,467,466,465,464,463,462,461,460,459,456,455,454,453,445, + 444,443,441,439,434,433,431,430,429,427,426,425,424,423,38,1,0,51,52, 434,433,0,60,61,62, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, - 458,454,429,427,426,425,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 459,455,429,427,426,425,423,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, - 458,454,429,425,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,455,429,425,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, - 458,454,429,427,426,425,423,1,0,40,45,46,47,48,49,54,85,90,92,140,141, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,455,429,427,426,425,423,1,0,40,45,46,47,48,49,54,86,91,93,140,141, 143,145,146,147,148,149,150,154,157,158,185,187,189,195,196,197,199,200, 203,205,220,224,225,229,413,414,415,416,417,418,419,420,421,422, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, - 458,454,429,425,423,1,0,43,44,46,54,85,90,92,140,141,143,145,146,147, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,455,429,425,423,1,0,43,44,46,54,86,91,93,140,141,143,145,146,147, 148,149,150,154,157,158,185,187,189,195,196,197,199,200,203,205,220,224, 225,229,413,414,415,416,417,418,419,420,421,422, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, - 458,454,429,425,423,1,0,43,44,46,54,85,90,92,140,141,143,145,146,147, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,455,429,425,423,1,0,43,44,46,54,86,91,93,140,141,143,145,146,147, 148,149,150,154,157,158,185,187,189,195,196,197,199,200,203,205,220,224, 225,229,413,414,415,416,417,418,419,420,421,422, 704,702,701,700,699,698,697,696,695,694,693,691,682,679,678,677,676,675,674, @@ -2327,261 +2345,261 @@ static const unsigned short ag_tstt[] = { 581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564, 563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546, 545,491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474, - 473,472,471,470,469,468,467,466,465,464,463,462,461,455,453,451,450,447, - 445,444,443,441,439,432,431,430,429,427,425,424,423,135,134,0,21,30,31, - 32,33,39,40,41,45,46,47,49,54,55,59,63,76,80,81,88,96,133,244,257,258, - 259,260,261,262,263,264,265,266,268,269,270,271,272,273,274,275,276,277, - 278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295, - 296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313, - 314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331, - 332,333,334,335,336,337,338,339,340,341,342,343,344,346,347,348,349,350, - 351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368, - 369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386, - 387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404, - 405,406,407,408,409,410,411,412,442, -494,491,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, + 473,472,471,470,469,468,467,466,465,464,463,462,456,454,453,451,450,447, + 445,444,443,441,439,432,431,430,429,427,425,424,423,135,134,38,0,21,30, + 31,32,33,39,40,41,45,46,47,49,54,55,59,63,76,80,81,89,97,133,244,257, + 258,259,260,261,262,263,264,265,266,268,269,270,271,272,273,274,275,276, + 277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294, + 295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312, + 313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330, + 331,332,333,334,335,336,337,338,339,340,341,342,343,344,346,347,348,349, + 350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367, + 368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385, + 386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403, + 404,405,406,407,408,409,410,411,412,442, +494,491,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, 668,543,542,541,248,246,238,236,234,1,0,51,52, 540,241,240,239,238,237,236,235,234,1,0,51,52, 668,543,248,246,238,236,234,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, + 460,429,231,135,134,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, 687,686,685,684,1,0,51,52, 668,543,542,541,248,246,238,236,234,1,0,51,52, 540,241,240,239,238,237,236,235,234,1,0,51,52, 668,543,248,246,238,236,234,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 668,540,539,248,246,238,236,234,1,0,51,52, 668,540,539,248,246,238,236,234,1,0,51,52, 668,540,539,248,246,238,236,234,1,0,51,52, @@ -2605,165 +2623,165 @@ static const unsigned short ag_tstt[] = { 540,241,240,239,238,237,236,235,234,1,0,51,52, 540,241,240,239,238,237,236,235,234,1,0,51,52, 687,686,685,684,1,0,51,52, -454,1,0,51,52, -454,1,0,51,52, -454,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, +455,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 668,540,539,248,246,238,236,234,1,0,51,52, 668,540,539,248,246,238,236,234,1,0,51,52, 668,540,539,248,246,238,236,234,1,0,51,52, @@ -2788,587 +2806,596 @@ static const unsigned short ag_tstt[] = { 540,241,240,239,238,237,236,235,234,1,0,51,52, 705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, 685,684,683,682,681,680,544,526,524,523,521,520,519,518,517,515,513,511, - 509,507,506,504,502,500,498,496,493,459,458,454,432,429,427,425,424,423, - 1,0,51,52,138, -544,427,425,424,423,1,0,51,52, + 509,507,506,504,502,500,498,496,493,460,459,455,432,429,427,425,424,423, + 38,1,0,51,52,138, +544,427,425,424,423,38,1,0,51,52, 705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, 685,684,683,682,681,680,544,526,524,523,522,521,520,519,518,517,516,515, 514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, - 496,495,493,459,458,454,432,429,427,425,424,423,1,0,90, -427,425,424,423,1,0,51, + 496,495,493,460,459,455,432,429,427,425,424,423,38,1,0,91, +427,425,424,423,38,1,0,51, 544,0,267, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,77,88, - 90,131,133,166,196,198,203,204,205,206,207,208,209,210,211,212,213,214, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,77,89, + 91,131,133,166,196,198,203,204,205,206,207,208,209,210,211,212,213,214, 215,216,217,218,219,442,492,538, 491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,455,453,445,444,443,441,439, - 0,69,70,71,72,73,83,84,97,98,99,100,101,102,103,104,105,106,107,108,109, - 110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128, + 471,470,469,468,467,466,465,464,463,462,456,454,453,445,444,443,441,439, + 0,69,70,71,72,73,83,84,85,98,99,100,101,102,103,104,105,106,107,108,109, + 110,111,112,113,114,115,117,118,119,120,121,122,123,124,125,126,127,128, 129,130,131, -427,425,424,423,1,0,51,52, +427,425,424,423,38,1,0,51,52, 705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, - 454,429,425,1,0,51,52, -427,425,424,423,1,0,51,52, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, + 455,429,425,1,0,51,52, +427,425,424,423,38,1,0,51,52, +681,0,10,12,435, +681,0,10,12,435, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,460,429,231,135,134,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28,29, + 57,89,91,131,133,196,198,203,204,205,206,207,208,209,210,211,212,213, + 214,215,216,217,218,219,435,442,492,538, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, - 454,429,425,423,1,0,142, -493,458,454,427,425,424,423,1,0,51,52, -454,0,85, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,1,0,51,52, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, + 455,429,425,423,1,0,142, +493,459,455,427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,1,0,51,52, 688,687,686,685,684,0, 687,686,685,684,0, 685,684,0, 704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,544, 523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, - 505,504,503,502,501,500,499,498,497,496,495,493,459,458,432,429,427,425, - 424,423,1,0, + 505,504,503,502,501,500,499,498,497,496,495,493,460,459,432,429,427,425, + 424,423,38,1,0, 704,702,698,696,695,694,693,688,687,686,685,684,682,544,523,522,521,520,519, 518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,496,495,493,458,432,429,427,425,424,423,222,221,1,0, + 500,499,498,497,496,495,493,459,432,429,427,425,424,423,222,221,38,1,0, 688,687,686,685,684,0, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458,454, + 685,684,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459,455, 429,425,423,233,1,0,16, 688,687,686,685,684,0, 698,696,695,694,693,688,687,686,685,684,0, 687,686,685,684,544,523,522,521,520,519,518,517,516,515,514,513,512,511,510, - 509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,493,458,432, - 427,425,424,423,1,0, + 509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,493,459,432, + 427,425,424,423,38,1,0, 685,684,544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, - 507,506,505,504,503,502,501,500,499,498,497,496,495,493,458,432,427,425, - 424,423,1,0, + 507,506,505,504,503,502,501,500,499,498,497,496,495,493,459,432,427,425, + 424,423,38,1,0, 696,695,694,693,688,687,686,685,684,544,523,522,521,520,519,518,517,516,515, 514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, - 496,495,493,458,432,427,425,424,423,1,0, + 496,495,493,459,432,427,425,424,423,38,1,0, 704,698,696,695,694,693,688,687,686,685,684,682,544,523,522,521,520,519,518, 517,516,515,514,513,511,510,509,508,507,506,505,504,503,502,501,500,499, - 498,497,496,493,458,432,429,427,425,424,423,222,221,1,0,223, -459,1,0,51,52, -459,427,425,424,423,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, + 498,497,496,493,459,432,429,427,425,424,423,222,221,38,1,0,223, +460,1,0,51,52, +460,427,425,424,423,38,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, 544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, - 505,504,503,502,501,500,499,498,497,496,495,493,458,432,427,425,424,423, - 1,0,51,52, + 505,504,503,502,501,500,499,498,497,496,495,493,459,432,427,425,424,423, + 38,1,0,51,52, 544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, - 505,504,503,502,501,500,499,498,497,496,495,493,458,432,427,425,424,423, - 1,0,51,52, + 505,504,503,502,501,500,499,498,497,496,495,493,459,432,427,425,424,423, + 38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 525,524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426, - 425,424,423,231,135,134,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -459,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 525,524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426, + 425,424,423,231,135,134,38,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +460,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, 135,134,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426,425, - 424,423,231,135,134,1,0,51,52, + 524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426,425, + 424,423,231,135,134,38,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, 135,134,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426,425, - 424,423,231,135,134,1,0,51,52, + 524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426,425, + 424,423,231,135,134,38,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, - 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, + 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, 212,213,214,215,216,217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, - 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, + 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, 212,213,214,215,216,217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, - 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, + 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, 212,213,214,215,216,217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, - 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, + 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, 212,213,214,215,216,217,218,219,442,492,538, 544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, - 505,504,503,502,501,500,499,498,497,496,495,493,458,432,427,425,424,423, - 1,0,51,52, + 505,504,503,502,501,500,499,498,497,496,495,493,459,432,427,425,424,423, + 38,1,0,51,52, 544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, - 505,504,503,502,501,500,499,498,497,496,495,493,458,432,425,423,1,0,51, - 52,197,199,200,201,202, + 505,504,503,502,501,500,499,498,497,496,495,493,459,432,425,423,38,1,0, + 51,52,197,199,200,201,202, 544,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,496,495,493,458,432,427,425,424,423,1,0,51,52,195,196, + 500,499,498,497,496,495,493,459,432,427,425,424,423,38,1,0,51,52,195, + 196, 544,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499, - 498,497,496,495,493,458,432,427,425,424,423,1,0,51,52,191,192,193,194, + 498,497,496,495,493,459,432,427,425,424,423,38,1,0,51,52,191,192,193, + 194, 544,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495, - 493,458,432,427,425,424,423,1,0,51,52,189,190, -544,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,493,458, - 432,427,425,424,423,1,0,51,52,187,188, + 493,459,432,427,425,424,423,38,1,0,51,52,189,190, +544,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,493,459, + 432,427,425,424,423,38,1,0,51,52,187,188, 508,507,0,185,186, -506,505,504,503,502,501,500,499,498,497,496,495,432,427,425,424,423,1,0,59, - 167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184, +506,505,504,503,502,501,500,499,498,497,496,495,432,427,425,424,423,38,1,0, + 59,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183, + 184, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,75, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,75, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,680,526,524,521,520,519,518,517,511,509,507,459,458, - 454,429,425,1,0, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, + 686,685,684,683,682,680,526,524,521,520,519,518,517,511,509,507,460,459, + 455,429,425,1,0, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, 704,703,702,701,700,699,698,697,696,695,694,693,689,688,687,686,685,684,681, 520,429,1,0,51,52, 704,703,702,701,700,699,698,697,696,695,694,693,689,688,687,686,685,684,681, 520,429,0,10,12,13,14,19,435,436,437, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 525,524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426, - 425,424,423,231,135,134,1,0,51,52, + 525,524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426, + 425,424,423,231,135,134,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 525,524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426, - 425,424,423,231,135,134,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, - 458,454,429,427,426,425,423,1,0,51,52, + 525,524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426, + 425,424,423,231,135,134,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 459,455,429,427,426,425,423,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, +705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426,425, - 424,423,231,135,134,1,0,51,52, + 524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426,425, + 424,423,231,135,134,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 525,524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426, - 425,424,423,231,135,134,1,0,51,52, + 525,524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426, + 425,424,423,231,135,134,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 525,524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426, - 425,424,423,231,135,134,1,0,51,52, + 525,524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426, + 425,424,423,231,135,134,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 525,524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426, - 425,424,423,231,135,134,1,0,51,52, + 525,524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426, + 425,424,423,231,135,134,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426,425, - 424,423,231,135,134,1,0,51,52, + 524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426,425, + 424,423,231,135,134,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, 686,685,684,683,682,681,680,544,526,524,523,522,521,520,519,518,517,516, 515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, - 497,496,495,493,460,459,458,454,432,429,427,426,425,424,423,1,0,51,52, + 497,496,495,493,461,460,459,455,432,429,427,426,425,424,423,38,1,0,51, + 52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 525,524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426, - 425,424,423,231,135,134,1,0,51,52, + 525,524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426, + 425,424,423,231,135,134,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 524,521,520,519,518,517,511,509,507,491,460,459,458,454,429,427,426,425, - 424,423,231,135,134,1,0,51,52, + 524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426,425, + 424,423,231,135,134,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,458,454,429,427,426,425,424,423,1,0,51,52, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, + 460,459,455,429,427,426,425,424,423,38,1,0,51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, - 458,454,438,434,433,429,427,426,425,424,423,164,163,162,135,134,38,1,0, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,455,438,434,433,429,427,426,425,424,423,164,163,162,135,134,38,1,0, 51,52, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, - 458,454,429,425,1,0,46,54,85,90,92,140,141,143,145,146,147,148,149,150, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,455,429,425,1,0,46,54,86,91,93,140,141,143,145,146,147,148,149,150, 154,157,158,185,187,189,195,196,197,199,200,203,205,220,224,225,229,413, 414,415,416,417,418,419,420,421,422, 423,0,45, 423,0,45, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,455,453,445,444,443,441,439, - 431,430,0,56,58,69,70,71,72,73,83,84,97,98,99,100,101,102,103,104,105, - 106,107,108,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124, + 471,470,469,468,467,466,465,464,463,462,456,454,453,445,444,443,441,439, + 431,430,0,56,58,69,70,71,72,73,83,84,85,98,99,100,101,102,103,104,105, + 106,107,108,109,110,111,112,113,114,115,117,118,119,120,121,122,123,124, 125,126,127,128,129,130,131, -427,425,424,423,1,0,51,52, -494,491,427,425,424,423,0,22,39,40,41,45,46,47,49,131,165, +427,425,424,423,38,1,0,51,52, +494,491,427,425,424,423,38,0,22,39,40,41,45,46,47,49,131,165, 668,543,542,541,248,246,238,236,234,0,245,247,249,250,254,255,256, 540,241,240,239,238,237,236,235,234,0,4,242,594, 668,543,248,246,238,236,234,0,5,245,247,249,608, 687,686,685,684,0,345, -454,0,85, -454,0,85, -454,0,85, +455,0,86, +455,0,86, +455,0,86, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 668,540,539,248,246,238,236,234,0,243,245,247,249,251,252, @@ -3395,8 +3422,8 @@ static const unsigned short ag_tstt[] = { 540,241,240,239,238,237,236,235,234,0,4,242,594, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,459,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,88,90,91,131,133,196,198,203,204,205,206,207,208,209,210,211, + 491,460,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,89,91,92,131,133,196,198,203,204,205,206,207,208,209,210,211, 212,213,214,215,216,217,218,219,435,442,485,492,538, 692,688,687,686,685,684,683,682,521,518,517,231,1,0,2,6,7,15,17,218,219,492, 679,678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663,662,661, @@ -3421,38 +3448,35 @@ static const unsigned short ag_tstt[] = { 1,0,51,52, 704,703,702,701,700,699,698,697,696,695,694,693,688,687,686,685,684,520,429, 0,19,437, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, 683,681,1,0,51,52, 683,681,0,10,12,18,20,435,485, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,691,682,427,425,424,423,135,134, - 1,0,51,52, + 38,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,691,682,427,425,424,423,135,134, - 1,0,21,133,442, + 38,1,0,21,133,442, 681,0,10,12,435, 681,0,10,12,435, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,459,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,459,429,231,135,134,1,0,51,52, + 491,460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,459,429,231,135,134,1,0,51,52, + 491,460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,459,429,231,135,134,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28,29, - 57,88,90,131,133,196,198,203,204,205,206,207,208,209,210,211,212,213, - 214,215,216,217,218,219,435,442,492,538, + 491,460,429,231,135,134,1,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28, + 29,51,52,57,89,91,131,133,196,198,203,204,205,206,207,208,209,210,211, + 212,213,214,215,216,217,218,219,435,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, @@ -3460,290 +3484,290 @@ static const unsigned short ag_tstt[] = { 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,115,133, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,116,133, 442, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,115,133, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,116,133, 442, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,115,133, +704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,116,133, 442, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,459,429,231,135,134,1,0,51,52, + 491,460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,459,429,231,135,134,1,0,51,52, + 491,460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,459,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,88,90,91,131,133,196,198,203,204,205,206,207,208,209,210,211, + 491,460,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,89,91,92,131,133,196,198,203,204,205,206,207,208,209,210,211, 212,213,214,215,216,217,218,219,435,442,485,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,459,429,231,135,134,1,0,51,52, + 491,460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,459,429,231,135,134,1,0,51,52, + 491,460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,459,429,231,135,134,1,0,51,52, + 491,460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,459,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,88,90,91,131,133,196,198,203,204,205,206,207,208,209,210,211, + 491,460,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,89,91,92,131,133,196,198,203,204,205,206,207,208,209,210,211, 212,213,214,215,216,217,218,219,435,442,485,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, -427,425,424,423,1,0,51,52, +427,425,424,423,38,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, -494,491,427,425,424,423,1,0,51,52, -494,491,427,425,424,423,1,0,51,52, -427,425,424,423,0,39,40,41,45,46,47,49, +494,491,427,425,424,423,38,1,0,51,52, +494,491,427,425,424,423,38,1,0,51,52, +427,425,424,423,38,0,39,40,41,45,46,47,49, 705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, - 454,429,425,0,46,54,85,89,90,92,140,141,145,146,147,148,149,150,154,157, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, + 455,429,425,0,46,54,86,90,91,93,140,141,145,146,147,148,149,150,154,157, 158,185,187,189,195,196,197,199,200,203,205,220,224,225,229,413,414,415, 416,417,418,419,420,421,422, -427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, +455,0,86, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, 703,702,701,700,699,696,694,686,685,684,682,681,423,0,155, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, 696,695,694,693,688,687,686,685,684,0, 703,701,700,699,684,683,0, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, - 454,429,425,423,233,1,0,16, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, + 455,429,425,423,233,1,0,16, 698,696,695,694,693,688,687,686,685,684,544,523,522,521,520,519,518,517,516, 515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, - 497,496,495,493,458,432,427,425,424,423,1,0, + 497,496,495,493,459,432,427,425,424,423,38,1,0, 698,696,695,694,693,688,687,686,685,684,544,523,522,521,520,519,518,517,516, 515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, - 497,496,495,493,458,432,427,425,424,423,1,0, -459,0,90, -459,0,90, -459,0,90, -459,0,90, -459,0,90, -459,0,90, -459,0,90, -459,0,90, -459,0,90, -459,0,90, -459,0,90, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 497,496,495,493,459,432,427,425,424,423,38,1,0, +460,0,91, +460,0,91, +460,0,91, +460,0,91, +460,0,91, +460,0,91, +460,0,91, +460,0,91, +460,0,91, +460,0,91, +460,0,91, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 688,687,686,685,684,0, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, 135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, 135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, 135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, 135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, 135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, 135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, 135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,0,39,40,41,45,46,47,49, + 460,429,231,135,134,1,0,51,52, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, 705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459, - 458,454,429,425,423,1,0, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,0,39,40,41,45,46,47,49, + 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, + 459,455,429,425,423,1,0, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, 704,703,702,701,700,699,698,697,696,695,694,693,688,687,686,685,684,520,429, - 425,423,1,0,51,52, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, + 425,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, -544,454,427,425,424,423,1,0,51,52, -544,454,427,425,424,423,1,0,51,52, -544,454,427,425,424,423,1,0,51,52, -544,493,454,427,425,424,423,1,0,51,52, -544,454,427,425,424,423,1,0,51,52, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, +544,455,427,425,424,423,38,1,0,51,52, +544,455,427,425,424,423,38,1,0,51,52, +544,455,427,425,424,423,38,1,0,51,52, +544,493,455,427,425,424,423,38,1,0,51,52, +544,455,427,425,424,423,38,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, + 460,429,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, -544,427,425,424,423,1,0,51,52, -544,427,425,424,423,1,0,51,52, + 460,429,231,135,134,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, 493,1,0,51,52, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458,454, + 685,684,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459,455, 429,425,423,233,1,0,16, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, - 454,429,425,423,233,1,0,16, -493,458,427,425,424,423,1,0,51,52, -493,458,0,92,132, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, + 455,429,425,423,233,1,0,16, +493,459,427,425,424,423,38,1,0,51,52, +493,459,0,93,132, 696,695,694,693,688,687,686,685,684,0, -704,698,696,695,694,693,688,687,686,685,684,682,427,425,424,423,222,221,1,0, - 223, +704,698,696,695,694,693,688,687,686,685,684,682,427,425,424,423,222,221,38, + 1,0,223, 679,678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663,662,661, 660,659,658,657,656,655,654,653,652,651,650,649,648,647,646,645,644,643, 642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627,626,625, @@ -3762,337 +3786,351 @@ static const unsigned short ag_tstt[] = { 394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411, 412, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458,454, + 685,684,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459,455, 429,425,423,233,1,0,16, -454,0,85, +455,0,86, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,459,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,88,90,91,131,133,196,198,203,204,205,206,207,208,209,210,211, + 491,460,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,89,91,92,131,133,196,198,203,204,205,206,207,208,209,210,211, 212,213,214,215,216,217,218,219,435,442,485,492,538, -493,427,425,424,423,1,0,132, -493,427,425,424,423,1,0,132, -493,427,425,424,423,1,0,132, -493,427,425,424,423,1,0,132, -493,427,425,424,423,1,0,132, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, + 491,460,429,231,135,134,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28,29, + 57,89,91,131,133,196,198,203,204,205,206,207,208,209,210,211,212,213, + 214,215,216,217,218,219,435,442,492,538, +493,427,425,424,423,38,1,0,132, +493,427,425,424,423,38,1,0,132, +493,427,425,424,423,38,1,0,132, +493,427,425,424,423,38,1,0,132, +493,427,425,424,423,38,1,0,132, 705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, - 458,454,429,425,423,1,0,46,51,52,54,85,90,92,95,140,141,145,146,147,148, - 149,150,154,157,158,185,187,189,195,196,197,199,200,203,205,220,224,225, - 229,413,414,415,416,417,418,419,420,421,422, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461,460, + 459,455,429,425,423,38,1,0,46,51,52,54,86,91,93,96,140,141,145,146,147, + 148,149,150,154,157,158,185,187,189,195,196,197,199,200,203,205,220,224, + 225,229,413,414,415,416,417,418,419,420,421,422, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 460,429,231,135,134,1,0,51,52, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, 696,695,694,693,688,687,686,685,684,0, 688,687,686,685,684,0, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, - 454,429,425,423,1,0, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, + 455,429,425,423,1,0, 683,0, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, -458,1,0,51,52, +459,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, - 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, + 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, 212,213,214,215,216,217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, - 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, + 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, 212,213,214,215,216,217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, - 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, + 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, 212,213,214,215,216,217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, - 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, + 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, 212,213,214,215,216,217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,459,429,231, - 135,134,0,2,6,7,8,9,15,17,21,88,90,131,133,198,206,207,208,209,210,211, + 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, + 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, 212,213,214,215,216,217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,25,29,88,90,131,133,196,198, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,25,29,89,91,131,133,196,198, 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, 492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,25,29,88,90,131,133,196,198, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,25,29,89,91,131,133,196,198, 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, 492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,25,27,29,88,90,131,133,196,198, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,25,27,29,89,91,131,133,196,198, 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, 492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,25,27,29,88,90,131,133,196,198, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,25,27,29,89,91,131,133,196,198, 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, 492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,25,27,29,88,90,131,133,196,198, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,25,27,29,89,91,131,133,196,198, 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, 492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,25,27,29,88,90,131,133,196,198, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,25,27,29,89,91,131,133,196,198, 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, 492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,24,25,27,29,88,90,131,133,196, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,24,25,27,29,89,91,131,133,196, 198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219, 442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,24,25,27,29,88,90,131,133,196, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,24,25,27,29,89,91,131,133,196, 198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219, 442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,29,88,90,131,133, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,29,89,91,131,133, 196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, 219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,29,88,90,131,133, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,29,89,91,131,133, 196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, 219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,88,90,131, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,89,91,131, 133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, 218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,88,90,131, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,89,91,131, 133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, 218,219,442,492,538, -427,425,424,423,1,0,51,52, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,1,0,51,52, -427,425,424,423,1,0,51,52, -427,425,424,423,0,39,40,41,45,46,47,49, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,1,0,51,52, +427,425,424,423,38,0,39,40,41,45,46,47,49, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 493,0,132, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, - 454,429,425,423,233,1,0,16, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, + 455,429,425,423,233,1,0,16, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,681,540,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518, - 517,491,459,429,241,240,239,238,237,236,235,234,231,135,134,1,0,51,52, + 517,491,460,429,241,240,239,238,237,236,235,234,231,135,134,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,459,429,231,135,134,1,0,51,52, + 491,460,429,231,135,134,1,0,51,52, 544,0,267, -544,427,425,424,423,1,0,51,52, +544,427,425,424,423,38,1,0,51,52, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458,454, + 685,684,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459,455, 429,425,423,233,1,0,16, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,1,0,51,52, -493,427,425,424,423,1,0,132, + 460,429,231,135,134,1,0,51,52, +493,427,425,424,423,38,1,0,132, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, 705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, - 458,454,429,427,425,424,423,1,0,51,52, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461,460, + 459,455,429,427,425,424,423,38,1,0,51,52, 705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, - 458,454,429,427,425,424,423,1,0, -427,425,424,423,0,39,40,41,45,46,47,49, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461,460, + 459,455,429,427,425,424,423,38,1,0, +427,425,424,423,38,0,39,40,41,45,46,47,49, +704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, + 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, + 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,219,442,492,538, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, - 454,429,425,423,1,0, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, + 455,429,425,423,1,0, 688,687,686,685,684,0, -427,425,424,423,1,0,51,52, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,3,133,442,536, -458,0,92, -458,0,92, -458,0,92, -458,0,92, -458,0,92, -458,0,92, -458,0,92, -458,0,92, -458,0,92, -458,0,92, -458,0,92, +459,0,93, +459,0,93, +459,0,93, +459,0,93, +459,0,93, +459,0,93, +459,0,93, +459,0,93, +459,0,93, +459,0,93, +459,0,93, 544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, - 505,504,503,502,501,500,499,498,497,496,495,493,458,432,425,423,1,0,197, - 199,200,201,202, + 505,504,503,502,501,500,499,498,497,496,495,493,459,432,425,423,38,1,0, + 197,199,200,201,202, 544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, - 505,504,503,502,501,500,499,498,497,496,495,493,458,432,425,423,1,0,197, - 199,200,201,202, + 505,504,503,502,501,500,499,498,497,496,495,493,459,432,425,423,38,1,0, + 197,199,200,201,202, 544,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,496,495,493,458,432,427,425,424,423,1,0,195,196, + 500,499,498,497,496,495,493,459,432,427,425,424,423,38,1,0,195,196, 544,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,496,495,493,458,432,427,425,424,423,1,0,195,196, + 500,499,498,497,496,495,493,459,432,427,425,424,423,38,1,0,195,196, 544,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,496,495,493,458,432,427,425,424,423,1,0,195,196, + 500,499,498,497,496,495,493,459,432,427,425,424,423,38,1,0,195,196, 544,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,496,495,493,458,432,427,425,424,423,1,0,195,196, + 500,499,498,497,496,495,493,459,432,427,425,424,423,38,1,0,195,196, 544,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499, - 498,497,496,495,493,458,432,427,425,424,423,1,0,191,192,193,194, + 498,497,496,495,493,459,432,427,425,424,423,38,1,0,191,192,193,194, 544,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499, - 498,497,496,495,493,458,432,427,425,424,423,1,0,191,192,193,194, + 498,497,496,495,493,459,432,427,425,424,423,38,1,0,191,192,193,194, 544,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495, - 493,458,432,427,425,424,423,1,0,189,190, + 493,459,432,427,425,424,423,38,1,0,189,190, 544,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495, - 493,458,432,427,425,424,423,1,0,189,190, -544,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,493,458, - 432,427,425,424,423,1,0,187,188, -544,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,493,458, - 432,427,425,424,423,1,0,187,188, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,0,39,40,41,45,46,47,49, -427,425,424,423,0,39,40,41,45,46,47,49, + 493,459,432,427,425,424,423,38,1,0,189,190, +544,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,493,459, + 432,427,425,424,423,38,1,0,187,188, +544,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,493,459, + 432,427,425,424,423,38,1,0,187,188, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, +427,425,424,423,38,0,39,40,41,45,46,47,49, 540,241,240,239,238,237,236,235,234,1,0,51,52, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,459,458, - 454,429,425,423,233,1,0, + 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, + 455,429,425,423,233,1,0, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,459,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,88,90,131,133,196,198,203,204,205,206,207,208,209,210,211,212, + 491,460,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, + 28,29,57,89,91,131,133,196,198,203,204,205,206,207,208,209,210,211,212, 213,214,215,216,217,218,219,435,442,485,492,538, 704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 459,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,88,90, + 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, 217,218,219,442,492,538, 704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, -427,425,424,423,0,39,40,41,45,46,47,49, -704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,458, +427,425,424,423,38,1,0,51,52, +704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,459, 429,1,0,51,52,138, -458,1,0,51,52, -458,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, 540,241,240,239,238,237,236,235,234,0,4,242,594, -458,0,92, +427,425,424,423,38,0,39,40,41,45,46,47,49, +459,0,93, }; -static unsigned const char ag_astt[27766] = { - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,7,1,1,9,5,2,2,2,2,2, - 2,2,2,2,2,2,2,2,1,8,8,8,8,8,2,2,2,2,2,1,1,7,1,0,1,1,1,1,1,1,1,1,1,1,1,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,2,4, - 4,4,4,2,4,4,7,2,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,3,1,1,1,1,1,1,1,1,1,1,1,1,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +static unsigned const char ag_astt[28270] = { + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,7,1,1,9,5,2,2,2,2, + 2,2,2,2,2,2,2,2,2,1,8,8,8,8,8,2,2,2,2,2,1,8,1,7,1,0,1,1,1,1,1,1,1,1,1,1,1, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4, + 4,2,4,4,4,4,2,4,4,4,7,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,3,1,1,1,1,1,1,1,1, + 1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,7,2,8,8,1,1,1,1,1,7,3,3,1,3,1,1,1,1,1,8,8,8, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,7,2,8,8,1,1,1,1,1,3,7,3,3,1,3, + 1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,5, - 5,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, + 8,8,8,8,8,8,8,5,5,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,1,1,1,8,8,8,8,8,5,5,1,5,5,5,5,2,2,9,7,1,1,1,1,1,1,1,2,1,2,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,1,1,8,8,8,8,8,5,5,1,5,5,5,1,2,2,5,9,7,1,1,1, + 1,1,3,1,1,2,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,8,8,8,8,8,2,2,2,2,2,1,3,1,7, - 1,3,3,1,1,3,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,1,7,1,3,5,1,7,1,3,5,1,7,1,3,5,1,7,1,3,5,5,5,5,5,7,1,3,5,5, - 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,8,8,8, + 8,8,2,2,2,2,2,1,3,1,7,1,3,3,1,1,3,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,1,7,1,3,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 7,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,2,7,1,1,1,2,7,1,1,1,2,7,1, - 1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,7,1,1,1,1,1,1,1,1,7,1,1,1,1,1,2,2,7,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5, + 5,5,5,7,1,3,5,1,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,7,1,1,1,8,1,7,1,1,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,7,1,1,1,8,8, + 8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,2,2, + 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,7,1,1,1,1,1,1,1,1,7,1,1,1,1,1,2,2,7,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,7,1,1,1,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,7,1,1,1,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -4107,28 +4145,16 @@ static unsigned const char ag_astt[27766] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,1,1,8,8,8, - 8,8,1,8,8,1,1,1,1,1,2,2,7,1,1,1,1,1,3,3,1,3,1,1,1,1,1,1,2,1,2,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 8,8,1,8,8,1,1,1,1,1,2,2,3,7,1,1,1,1,1,3,3,1,3,1,1,1,1,1,1,2,1,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5, - 5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5, - 5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5, - 5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, - 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, - 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, - 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,1,1,1,1,1,1,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1, + 3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5, 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, @@ -4136,18 +4162,6 @@ static unsigned const char ag_astt[27766] = { 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5, - 5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5, - 5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5, - 5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5, - 5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, - 7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7, - 1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3, - 8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, @@ -4161,6 +4175,25 @@ static unsigned const char ag_astt[27766] = { 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, + 5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1, + 3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, + 8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, @@ -4204,21 +4237,21 @@ static unsigned const char ag_astt[27766] = { 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3, - 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3,5, - 5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3, - 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3, - 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7, - 1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, - 5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, - 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,1, - 7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, + 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5, + 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1, + 3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, + 7,1,3,8,8,8,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, @@ -4277,177 +4310,151 @@ static unsigned const char ag_astt[27766] = { 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, - 1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,8, - 8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, - 1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, - 8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, - 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, - 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8, - 8,8,8,8,8,8,8,8,1,7,1,1,5,2,2,2,2,2,2,2,2,2,2,2,5,2,5,5,2,2,2,2,2,5,2,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,2,5,5,5,5,1,7,1,3,2,5,5, - 5,5,5,1,7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,4,4,4,4,4,4,4,4, - 4,7,1,4,4,4,4,1,7,1,1,5,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,2, - 1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,2,1,2,2,1,1,2,2,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,1,1,2,8,8,8,8,1,7, - 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,5,7,1,3,1,7, - 1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1, - 2,1,1,1,8,8,8,8,1,7,1,1,2,2,2,2,2,7,2,2,2,2,7,2,2,7,4,4,4,4,4,4,4,2,2,2,2, - 4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,7,4,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,7,2,1, + 8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1, + 8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1, + 7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8, + 8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1, + 1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1, + 7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, + 8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, + 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,5,2,2,2,2,2,2,2,2,2,2,2,5,2,5,5,2, + 2,2,2,2,5,2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,2,5,5,5, + 5,5,1,7,1,3,2,5,5,5,5,5,5,1,7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,1,4,4,4,4,4,4,4,4,4,4,7,1,4,4,4,4,4,1,7,1,1,5,1,2,2,2,2,2,2,2,2,2,2,2,1, + 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, + 1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,7,2,2,1,2,2,1,1,1,2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 1,2,2,1,1,2,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,2,7,1,1,1,2, + 7,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,5,5,7,1, + 3,8,8,8,8,8,1,7,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,8, + 8,8,8,8,1,7,1,1,2,2,2,2,2,7,2,2,2,2,7,2,2,7,4,4,4,4,4,4,4,2,2,2,2,4,2,2,2, + 2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,7,4,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,7,2,1,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,7,1,10,10,10,10,10,5,2,10,10,10,10,10,10,10,10,10,7,10,10,10,10,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7, - 10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,7,10,10,10,10,10,10,10,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 2,7,1,10,10,10,10,10,5,2,10,10,10,10,10,10,10,10,10,7,10,10,10,10,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,10, + 10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,7,10,10,10,10,10,10,10,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,9,2,2,1,1,2,10,10,10,10,10,9,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4,2,2,4,7, - 2,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5, - 7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4,2,2,4,4, + 7,2,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3, + 5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,1,7,1,1,8,1,7,1,1, 8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1, - 7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,2,2,2,2,2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, - 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2, - 1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, - 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, - 2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,1,1,1,1,1,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,1,5, - 1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1, - 5,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1, - 1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,5,1,1,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,5,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,5,5,5,5,5,7,1,3, - 8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,7,1,3,8,8,8,8, - 1,7,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,10,10,1,10,10,10,10,10,10,10,10,10, - 10,10,10,2,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, - 10,10,10,10,7,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,7,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 7,1,1,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,2,2,2,2,2,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, + 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, + 5,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, + 7,1,3,1,1,1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,1,7,1,3,1,1,5,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,1,7,1,3,1,1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,1,7,1,3,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, + 1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1, + 1,8,8,8,8,8,1,7,1,5,5,5,5,5,5,7,1,3,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,8, + 8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,8, + 8,8,8,8,1,7,1,1,10,10,1,10,10,10,10,10,10,10,10,10,10,10,10,2,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,7,5,5,5,5,5, + 5,7,1,3,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1, + 1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, + 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, - 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,5,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1, - 7,3,1,7,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,2,2,1,2,2,1,1, - 2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,1,1,2,8,8,8, - 8,1,7,1,1,1,1,1,1,1,1,7,1,3,3,1,3,1,1,1,2,2,2,1,1,1,2,2,2,2,2,7,2,2,2,2,3, - 2,2,2,2,2,2,2,2,2,2,2,7,3,2,1,2,2,2,2,2,2,2,7,3,2,2,2,1,2,2,2,2,7,2,1,7,1, - 1,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1, - 1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, - 2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, - 2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1, - 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2, - 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, - 1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, - 1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, - 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, - 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, - 2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, - 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2, - 1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1, - 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, - 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, - 1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,7,3,1,7,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, + 7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,2,2,1,2,2,1,1,1,2,2,1,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,1,1,2,8,8,8,8,8,1,7,1,1,1,1,1,1,1, + 1,3,7,1,3,3,1,3,1,1,1,2,2,2,1,1,1,2,2,2,2,2,7,2,2,2,2,3,2,2,2,2,2,2,2,2,2, + 2,2,7,3,2,1,2,2,2,2,2,2,2,7,3,2,2,2,1,2,2,2,2,7,2,1,7,1,1,7,1,1,7,1,2,2,2, 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, @@ -4530,120 +4537,149 @@ static unsigned const char ag_astt[27766] = { 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1, - 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,2,2,2,2,2,7,2,2,2,2,2, - 2,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,1,1,2,2,2, - 2,2,7,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2, - 1,2,2,2,2,2,2,2,7,2,2,2,2,1,2,2,2,2,2,2,2,7,2,2,2,2,1,2,1,1,1,2,2,2,2,2,7, - 2,2,2,2,2,2,2,2,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,2,1, - 2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2, - 2,1,2,2,2,2,2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2, + 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, + 1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1, + 1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, + 2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2, + 1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2, + 2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, + 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, + 2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, + 1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, + 1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1, + 1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,1,1,2,2,2,2,2, + 7,2,2,2,2,2,2,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2, + 2,2,2,2,7,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2,1,2,2,2,2,2,2,2,7, + 2,2,2,2,1,2,2,2,2,2,2,2,7,2,2,2,2,1,2,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,1, + 1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2, 7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2, - 2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, - 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2, - 1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,2,1,1,1,1,1,1,2,9,7,2,1,1,2,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2, + 2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2, + 2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2, + 2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,1,1,1, + 1,1,1,2,9,7,2,1,1,2,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, - 1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2, - 1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,7,2,1,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,1,7,1,3,1,2,7,2,1, - 1,2,1,1,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2,2,4,7,2,1,1,2,7,1,1,1,2,7, - 2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2, - 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,7,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, - 1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1, - 1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, - 2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2, - 1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2, + 1,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,1,7,1,3,1,2,7,2,1,1,2,1,1,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2,2,4,4,7,2,1,1,2,7,1,1,1,2,7,2,1,1, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,7,2,1,1,2,1,2,1,2,1, + 1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, + 7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1, + 1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2, - 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2, + 2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, + 1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2, + 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, + 1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2, 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5, - 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,1,1,1,1,7,3,3,1,3,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,2, - 2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,1,1,1,1,7,2,2,1,2,1,1,1,2,1,2,2,2,2,2,1,1,1,1,2,3,7,1,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, - 1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1, - 2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7, + 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,7,1, + 3,5,5,5,5,5,5,5,5,7,1,3,1,1,1,1,3,7,3,3,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,2,2,1,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1, + 2,7,2,2,1,2,1,1,1,1,7,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7, + 1,1,2,1,2,2,2,2,2,1,1,1,1,2,3,7,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2, + 2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,4,4,4,4,4,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,7,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1, - 7,1,1,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, - 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,7,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8, + 4,4,4,4,4,4,7,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7, + 1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,7,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, + 1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, - 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, - 3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, + 5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5, + 8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, @@ -4652,61 +4688,59 @@ static unsigned const char ag_astt[27766] = { 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1, - 1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2, - 1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,3,2,7,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,10, - 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,7,1,3,8,8,8,8, - 1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, - 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, - 1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,3, - 3,1,3,1,1,1,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, - 5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,5,5, - 5,5,5,5,7,1,3,8,1,7,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,7,1,3, - 1,1,7,2,1,2,2,2,2,2,2,2,2,2,7,9,2,2,1,1,2,10,10,10,10,10,9,4,4,4,4,2,2,4,7, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, + 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1, + 1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1, + 1,1,1,2,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,2,7, + 2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,7,1,1,1,1,2,7,2,2,1,2, + 1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,5,5,5,5,7,1,3,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8, + 1,7,1,1,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, + 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,7,3,3,1,3,1,1,1,5,5,5,5,5,5,7,1, + 3,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, + 1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7, + 1,3,8,1,7,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,5,7,1,3,1,1,7,2, + 1,2,2,2,2,2,2,2,2,2,7,9,2,2,1,1,2,10,10,10,10,10,9,4,4,4,4,2,2,4,4,7,2,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1, - 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,7,1,1,4,4,4, - 4,4,7,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,1,4,4,4,4,4,7,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,2,1, - 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,1,1,1,1,1,1,1,1,1,7,1,1,1,1,1,7,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1, - 1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2,2, - 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, - 2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, - 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, - 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1, - 1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, - 2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, - 2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1, + 1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, + 2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2, + 1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,4,4,4,4,4,4,7,1,1,4,4,4,4,4,4,7,1,1,4,4,4,4,4,4,7,1,1,4,4,4,4,4,4,7,1,1, + 4,4,4,4,4,4,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,8,8,1,7,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,1,1,1,1,2,7, + 2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,7,1,1,1,1,1,7,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, @@ -4718,1950 +4752,1990 @@ static unsigned const char ag_astt[27766] = { 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1, - 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2, - 1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2, - 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, + 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, 1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2, - 1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, + 2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, + 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, + 1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, + 1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, + 2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, + 2,1,2,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, 2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2, - 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, - 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, - 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,1,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1, - 7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,8,8,8,8,1, - 7,1,1,8,8,8,8,1,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, + 1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, + 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2, + 1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,1, + 7,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2, + 1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,1, + 1,1,1,2,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1, + 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, 1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1, - 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,5,5,5,5,5,5,5, + 1,1,1,1,1,1,1,1,1,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, + 3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,1,7,1,1,1,7,1,5,5,5,5,5,5,1,7,1,3,2,1,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1, + 7,1,1,1,4,4,4,4,4,4,7,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,1,7,1,5,5,5,5,5,1,7,1,3,2,1,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,7,2,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,1,7,1,1,1,4,4,4,4,4,7,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1, - 7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,7,1,1,1,1,7,2,2,1,2,1,1,1,4,4, - 4,4,4,4,4,4,2,2,2,2,4,4,4,4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,7,2,2,2,2,2,7,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1, - 1,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,3,4,1,1, - 1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1, - 1,1,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,7,1,1,1,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,7,1,1,1,1,2,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2, + 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1, + 1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,4,4,4,4,4,4,4,4,2,2,2,2,4,4,4,4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,7,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,7, + 2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,3,4,1,1,1,1,1, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1, + 4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 7,1,1,1,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 7,1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1, - 1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1, - 1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,7,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,7,2,2, - 1,2,1,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2,2,1, - 2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, - 2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1, - 1,1,1,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,5,2,1,7,1,3,2,5, - 5,7,1,3,8,1,7,1,1,2,2,2,2,2,2,2,2,2,7,2,2,1,1,7,2 + 4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,7,1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,7,1,1,1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,7,1,1,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1, + 4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1, + 2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7, + 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, + 1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,7,2,1,1,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,5,2,1,7,1,3,2,5,5,7,1,3,8,1,7,1,1,2,2,2,2,2,2,2,2,2,7,2,2,1,1,1,1,1,2,7, + 2,2,1,2,1,1,1,1,7,2 }; static const unsigned short ag_pstt[] = { -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,1,2, -18,20, -131,131,131,131,131,131,131,131,131,131,131,131,131,3,8,8,8,8,8,166,165,164, - 130,129,7,10,2,9,0,11,11,11,10,8,11,5,5,4,6,4, -19,19,19,19,19,19,19,19,19,19,19,19,19,1,3,1,887, -132,132,132,132,132,132,132,132,132,132,132,132,133,133,133,133,133,132,163, - 163,132,163,163,163,163,162,163,163,4,133, -12,13,14,15,16,17,18,19,20,21,22,23,24,5,37,40,36,35,34,33,32,31,30,29,28, - 27,26,25, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,1,6,1,877, -38,7,38, -40,40,39,41,42,43,38,8,24,24,46,24,45,44,44,40,40, -47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, - 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, - 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, - 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, - 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, - 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, - 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47, - 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,19,19,47,47,47,47, - 47,47,47,1,9,1,47, -131,131,131,131,131,131,131,131,131,131,131,131,131,115,116,117,118,119,120, - 121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138, - 66,67,68,69,70,71,139,140,141,142,143,144,72,73,74,75,76,145,146,147,77, - 78,79,80,81,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162, - 111,63,64,65,169,170,171,172,173,174,175,176,177,178,179,180,181,182, - 183,184,163,164,165,166,167,168,82,83,84,85,86,87,49,50,51,88,89,90,91, - 92,93,94,95,96,52,53,97,98,99,100,101,102,103,104,54,55,56,105,106,57, - 58,107,108,109,110,59,60,61,62,269,269,269,269,269,269,269,269,269,269, - 269,269,269,269,269,269,269,269,269,269,269,269,269,269,269,269,269,269, - 269,269,269,269,17,18,21,269,269,269,269,269,20,20,39,20,20,20,20,130, - 129,18,10,265,266,267,264,270,269,269,36,268,105,106,270,48,263,200,264, - 264,264,264,264,264,264,264,264,264,327,327,327,327,327,328,329,330,331, - 334,334,334,335,336,340,340,340,340,341,342,343,344,345,346,347,348,351, - 351,351,352,353,354,355,356,357,358,359,360,364,364,364,364,365,366,367, - 368,369,370,246,245,244,243,242,241,262,261,260,259,258,257,256,255,254, - 253,252,251,250,249,248,247,188,114,187,113,186,112,185,240,239,238,237, - 236,235,234,233,232,231,230,229,228,227,226,225,225,225,225,225,225,224, - 223,222,221,221,221,221,221,221,220,219,218,217,216,215,214,214,214,214, - 213,213,213,213,212,211,210,209,208,207,206,205,204,203,202,201,199,198, - 197,196,195,194,193,192,191,190,189,263, -131,131,131,131,131,131,131,131,131,131,131,131,131,3,8,8,8,8,8,166,165,164, - 130,129,7,4,10,11,9,3,3,10,8,3,5,5,4,6,4, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,12,1,906, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,13,1,905, -19,1,14,1,904, -19,1,15,1,902, -19,1,16,1,901, -19,19,19,19,19,17,1,900, -19,19,19,19,19,18,1,899, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,19,1,898, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,20,1,897, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,21,1,896, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,22,1,895, -19,19,19,19,19,1,23,1,889, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,24,1,882, -131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,25,265,271,263, - 263, -131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,26,272,263,263, -140,27,275,273,274, -140,28,276,273,274, -140,29,277,273,274, -278,278,278,278,1,30,1,278, -279,279,279,279,1,31,1,279, -131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,32,280,263,263, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,33,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,335,337,220,323,309,263,336,324,328,327,326,325,219,328,318, - 317,316,315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,34,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,335,338,220,323,309,263,336,324,328,327,326,325,219,328,318, - 317,316,315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,35,339,263,263, -340,342,344,346,348,36,349,347,345,343,341, -158,140,37,353,273,352,350,274,351, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,38,1,872, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,39,1,878, -354,24,40,355,355,355, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,41,1,876, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,42,1, - 874, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,43,1,873, -356,358,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376, - 377,378,379,386,389,390,391,320,322,388,380,384,381,383,387,359,357,307, - 385,382,39,41,392,42,38,15,44,16,15,15,44,13,44,15,15,15,15,15,15,15,15, - 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, - 15,15,15,15,15,15,15,15, -356,358,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376, - 377,378,379,386,389,390,391,320,322,388,380,384,381,383,387,359,357,307, - 385,382,39,42,394,393,45,393,394,393,393,393,393,393,393,393,393,393, - 393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393, - 393,393,393,393,393,393,393,393,393,393,393,393,393,393, -356,358,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376, - 377,378,379,386,389,390,391,320,322,388,380,384,381,383,387,359,357,307, - 385,382,39,42,395,393,46,393,395,393,393,393,393,393,393,393,393,393, - 393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393, - 393,393,393,393,393,393,393,393,393,393,393,393,393,393, -131,131,131,131,131,131,131,131,131,131,131,131,131,115,116,117,118,119,120, - 121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138, - 66,67,68,69,70,71,139,140,141,142,143,144,72,73,74,75,76,145,146,147,77, - 78,79,80,81,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162, - 111,63,64,65,169,170,171,172,173,174,175,176,177,178,179,180,181,182, - 183,184,163,164,165,166,167,168,82,83,84,85,86,87,49,50,51,88,89,90,91, - 92,93,94,95,96,52,53,97,98,99,100,101,102,103,104,54,55,56,105,106,57, - 58,107,108,109,110,59,60,61,62,398,398,398,398,398,398,398,398,398,398, - 398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398, - 398,398,398,398,17,18,21,398,398,398,398,398,396,398,398,39,41,42,43,38, - 130,129,47,265,266,267,264,399,23,23,46,23,45,44,44,398,398,397,37,268, - 105,106,399,48,263,200,264,264,264,264,264,264,264,264,264,264,327,327, - 327,327,327,328,329,330,331,334,334,334,335,336,340,340,340,340,341,342, - 343,344,345,346,347,348,351,351,351,352,353,354,355,356,357,358,359,360, - 364,364,364,364,365,366,367,368,369,370,246,245,244,243,242,241,262,261, - 260,259,258,257,256,255,254,253,252,251,250,249,248,247,188,114,187,113, - 186,112,185,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226, - 225,225,225,225,225,225,224,223,222,221,221,221,221,221,221,220,219,218, - 217,216,215,214,214,214,214,213,213,213,213,212,211,210,209,208,207,206, - 205,204,203,202,201,199,198,197,196,195,194,193,192,191,190,189,263, -400,400,400,400,400,400,1,48,1,400, -19,19,19,19,19,19,49,1,1030, -19,19,19,19,19,19,50,1,1029, -19,19,19,19,19,19,51,1,1028, -19,19,19,19,19,19,52,1,1018, -19,19,19,19,19,19,53,1,1017, -19,19,19,19,19,19,54,1,1008, -19,19,19,19,19,19,55,1,1007, -19,19,19,19,19,19,56,1,1006, -19,19,19,19,19,19,57,1,1003, -19,19,19,19,19,19,58,1,1002, -19,19,19,19,19,19,59,1,997, -19,19,19,19,19,19,60,1,996, -19,19,19,19,19,19,61,1,995, -19,19,19,19,19,19,62,1,994, -19,19,19,19,19,19,19,19,19,19,63,1,1063, -19,19,19,19,19,19,19,19,19,19,64,1,1062, -19,19,19,19,19,19,19,19,65,1,1061, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,66,1,1104, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,67,1,1103, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,68,1,1102, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,69,1,1101, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,70,1,1100, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,71,1,1099, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,72,1,1092, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,73,1,1091, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,74,1,1090, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,75,1,1089, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,76,1,1088, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,77,1,1084, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,78,1,1083, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,79,1,1082, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,80,1,1081, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,81,1,1080, -19,19,19,19,19,19,82,1,1036, -19,19,19,19,19,19,83,1,1035, -19,19,19,19,19,19,84,1,1034, -19,19,19,19,19,19,85,1,1033, -19,19,19,19,19,19,86,1,1032, -19,19,19,19,19,19,87,1,1031, -19,19,19,19,19,19,88,1,1027, -19,19,19,19,19,19,89,1,1026, -19,19,19,19,19,19,90,1,1025, -19,19,19,19,19,19,91,1,1024, -19,19,19,19,19,19,92,1,1023, -19,19,19,19,19,19,93,1,1022, -19,19,19,19,19,19,94,1,1021, -19,19,19,19,19,19,95,1,1020, -19,19,19,19,19,19,96,1,1019, -19,19,19,19,19,19,97,1,1016, -19,19,19,19,19,19,98,1,1015, -19,19,19,19,19,19,99,1,1014, -19,19,19,19,19,19,100,1,1013, -19,19,19,19,19,19,101,1,1012, -19,19,19,19,19,19,102,1,1011, -19,19,19,19,19,19,103,1,1010, -19,19,19,19,19,19,104,1,1009, -19,19,19,19,19,19,105,1,1005, -19,19,19,19,19,19,106,1,1004, -19,19,19,19,19,19,107,1,1001, -19,19,19,19,19,19,108,1,1000, -19,19,19,19,19,19,109,1,999, -19,19,19,19,19,19,110,1,998, -19,19,19,19,19,111,1,1064, -401,401,401,401,401,401,401,401,401,1,112,1,401, -402,402,402,402,402,402,402,402,402,1,113,1,402, -403,403,403,403,403,403,403,1,114,1,403, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,115,1,1128, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,116,1,1127, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,117,1,1126, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,118,1,1125, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,119,1,1124, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,120,1,1123, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,121,1,1122, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,122,1,1121, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,123,1,1120, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,124,1,1119, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,125,1,1118, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,126,1,1117, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,127,1,1116, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,128,1,1115, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,129,1,1114, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,130,1,1113, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,131,1,1112, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,132,1,1111, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,133,1,1110, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,134,1,1109, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,135,1,1108, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,136,1,1107, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,137,1,1106, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,138,1,1105, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,139,1,1098, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,140,1,1097, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,141,1,1096, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,142,1,1095, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,143,1,1094, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,144,1,1093, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,145,1,1087, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,146,1,1086, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,147,1,1085, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,148,1,1079, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,149,1,1078, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,150,1,1077, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,151,1,1076, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,152,1,1075, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,153,1,1074, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,154,1,1073, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,155,1,1072, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,156,1,1071, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,157,1,1070, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,158,1,1069, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,159,1,1068, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,160,1,1067, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,161,1,1066, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,162,1,1065, -19,19,19,19,19,19,19,19,19,163,1,1042, -19,19,19,19,19,19,19,19,19,164,1,1041, -19,19,19,19,19,19,19,19,19,165,1,1040, -19,19,19,19,19,19,19,19,19,166,1,1039, -19,19,19,19,19,167,1,1038, -19,19,19,19,19,168,1,1037, -19,19,19,19,19,19,19,19,169,1,1060, -19,19,19,19,19,19,19,19,170,1,1059, -19,19,19,19,19,19,19,19,171,1,1058, -19,19,19,19,19,19,19,19,19,19,172,1,1056, -19,19,19,19,19,19,19,19,19,19,173,1,1055, -19,19,19,19,19,19,19,19,19,19,174,1,1054, -19,19,19,19,19,19,19,19,19,19,175,1,1053, -19,19,19,19,19,19,19,19,19,19,176,1,1052, -19,19,19,19,19,19,19,19,19,19,177,1,1051, -19,19,19,19,19,19,19,19,19,19,178,1,1050, -19,19,19,19,19,19,19,19,19,19,179,1,1049, -19,19,19,19,19,19,19,19,19,19,180,1,1048, -19,19,19,19,19,19,19,19,19,19,181,1,1047, -19,19,19,19,19,19,19,19,19,19,182,1,1046, -19,19,19,19,19,19,19,19,19,19,183,1,1045, -19,19,19,19,19,19,19,19,19,19,184,1,1044, -404,404,404,404,1,185,1,404, -405,1,186,1,405, -406,1,187,1,406, -407,1,188,1,407, -408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408, - 408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408, - 408,408,408,408,408,1,189,1,408, -409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409, - 409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409, - 409,409,409,409,409,1,190,1,409, -410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, - 410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, - 410,410,410,410,410,1,191,1,410, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,1,2, +19,21, +137,137,137,137,137,137,137,137,137,137,137,137,137,3,8,8,8,8,8,172,171,170, + 136,135,7,8,10,2,9,0,11,11,11,10,8,11,5,5,4,6,4, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,3,1,893, +138,138,138,138,138,138,138,138,138,138,138,138,139,139,139,139,139,138,169, + 169,138,169,169,169,169,168,169,169,169,4,139, +12,13,14,15,16,17,18,19,20,21,22,23,24,25,5,39,42,38,37,36,35,34,33,32,31, + 30,29,28,27,26, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,1,6,1,883, +40,7,39, +42,42,41,43,44,45,40,25,8,25,25,48,25,47,46,46,42,42, +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, + 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, + 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, + 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, + 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, + 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, + 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, + 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,20,20,49,49,49,49, + 49,49,49,49,1,9,1,49, +137,137,137,137,137,137,137,137,137,137,137,137,137,117,118,119,120,121,122, + 123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140, + 68,69,70,71,72,73,141,142,143,144,145,146,74,75,76,77,78,147,148,149,79, + 80,81,82,83,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164, + 113,65,66,67,171,172,173,174,175,176,177,178,179,180,181,182,183,184, + 185,186,165,166,167,168,169,170,84,85,86,87,88,89,51,52,53,90,91,92,93, + 94,95,96,97,98,54,55,99,100,101,102,103,104,105,106,56,57,58,107,108,59, + 60,109,110,111,112,61,62,63,64,271,271,271,271,271,271,271,271,271,271, + 271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, + 271,271,271,271,18,19,22,271,271,271,271,271,21,21,41,21,21,21,40,136, + 135,21,19,10,267,268,269,266,272,40,271,271,37,270,111,112,272,50,265, + 202,266,266,266,266,266,266,266,266,266,266,333,333,333,333,333,334,335, + 336,337,340,340,340,341,342,346,346,346,346,347,348,349,350,351,352,353, + 354,357,357,357,358,359,360,361,362,363,364,365,366,370,370,370,370,371, + 372,373,374,375,376,248,247,246,245,244,243,264,263,262,261,260,259,258, + 257,256,255,254,253,252,251,250,249,190,116,189,115,188,114,187,242,241, + 240,239,238,237,236,235,234,233,232,231,230,229,228,227,227,227,227,227, + 227,226,225,224,223,223,223,223,223,223,222,221,220,219,218,217,216,216, + 216,216,215,215,215,215,214,213,212,211,210,209,208,207,206,205,204,203, + 201,200,199,198,197,196,195,194,193,192,191,265, +137,137,137,137,137,137,137,137,137,137,137,137,137,3,8,8,8,8,8,172,171,170, + 136,135,7,4,10,11,9,3,3,10,8,3,5,5,4,6,4, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,12,1,913, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,13,1,912, +20,20,14,1,911, +20,20,15,1,909, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,16,1,908, +20,1,17,1,907, +20,20,20,20,20,20,18,1,906, +20,20,20,20,20,20,19,1,905, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,20,1,904, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,21,1,903, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,22,1,902, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,23,1,901, +20,20,20,20,20,1,24,1,895, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,25,1,888, +137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,26,267,273,265, + 265, +137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,27,274,265,265, +275,1,28,1,275, +276,1,29,1,276, +277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277, + 277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277, + 277,277,277,277,277,277,1,30,1,277, +146,31,280,278,279, +281,281,281,281,281,1,32,1,281, +282,282,282,282,282,1,33,1,282, +137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,34,283,265,265, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,35,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,338,340,226,326,312,265,339,327,331,330,329,328,225,331,321, + 320,319,318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,36,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,338,341,226,326,312,265,339,327,331,330,329,328,225,331,321, + 320,319,318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,37,342,265,265, +343,345,347,349,351,38,352,350,348,346,344, +164,146,39,356,278,355,353,279,354, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,40,1,878, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,41,1,884, +357,25,42,358,358,358, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,43,1,882, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,44, + 1,880, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,45,1,879, +359,361,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379, + 380,381,382,389,392,393,394,323,325,391,383,387,384,386,390,362,360,310, + 388,385,41,43,395,44,40,16,46,17,16,16,46,14,46,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16, +359,361,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379, + 380,381,382,389,392,393,394,323,325,391,383,387,384,386,390,362,360,310, + 388,385,41,44,397,396,47,396,397,396,396,396,396,396,396,396,396,396, + 396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396, + 396,396,396,396,396,396,396,396,396,396,396,396,396,396, +359,361,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379, + 380,381,382,389,392,393,394,323,325,391,383,387,384,386,390,362,360,310, + 388,385,41,44,398,396,48,396,398,396,396,396,396,396,396,396,396,396, + 396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396, + 396,396,396,396,396,396,396,396,396,396,396,396,396,396, +137,137,137,137,137,137,137,137,137,137,137,137,137,117,118,119,120,121,122, + 123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140, + 68,69,70,71,72,73,141,142,143,144,145,146,74,75,76,77,78,147,148,149,79, + 80,81,82,83,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164, + 113,65,66,67,171,172,173,174,175,176,177,178,179,180,181,182,183,184, + 185,186,165,166,167,168,169,170,84,85,86,87,88,89,51,52,53,90,91,92,93, + 94,95,96,97,98,54,55,99,100,101,102,103,104,105,106,56,57,58,107,108,59, + 60,109,110,111,112,61,62,63,64,401,401,401,401,401,401,401,401,401,401, + 401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, + 401,401,401,401,18,19,22,401,401,401,401,401,399,401,401,41,43,44,45,40, + 136,135,24,49,267,268,269,266,402,24,24,48,24,47,46,46,401,401,400,38, + 270,111,112,402,50,265,202,266,266,266,266,266,266,266,266,266,266,333, + 333,333,333,333,334,335,336,337,340,340,340,341,342,346,346,346,346,347, + 348,349,350,351,352,353,354,357,357,357,358,359,360,361,362,363,364,365, + 366,370,370,370,370,371,372,373,374,375,376,248,247,246,245,244,243,264, + 263,262,261,260,259,258,257,256,255,254,253,252,251,250,249,190,116,189, + 115,188,114,187,242,241,240,239,238,237,236,235,234,233,232,231,230,229, + 228,227,227,227,227,227,227,226,225,224,223,223,223,223,223,223,222,221, + 220,219,218,217,216,216,216,216,215,215,215,215,214,213,212,211,210,209, + 208,207,206,205,204,203,201,200,199,198,197,196,195,194,193,192,191,265, +403,403,403,403,403,403,403,1,50,1,403, +20,20,20,20,20,20,20,51,1,1036, +20,20,20,20,20,20,20,52,1,1035, +20,20,20,20,20,20,20,53,1,1034, +20,20,20,20,20,20,20,54,1,1024, +20,20,20,20,20,20,20,55,1,1023, +20,20,20,20,20,20,20,56,1,1014, +20,20,20,20,20,20,20,57,1,1013, +20,20,20,20,20,20,20,58,1,1012, +20,20,20,20,20,20,20,59,1,1009, +20,20,20,20,20,20,20,60,1,1008, +20,20,20,20,20,20,20,61,1,1003, +20,20,20,20,20,20,20,62,1,1002, +20,20,20,20,20,20,20,63,1,1001, +20,20,20,20,20,20,20,64,1,1000, +20,20,20,20,20,20,20,20,20,20,65,1,1069, +20,20,20,20,20,20,20,20,20,20,66,1,1068, +20,20,20,20,20,20,20,20,67,1,1067, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,68,1,1110, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,69,1,1109, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,70,1,1108, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,71,1,1107, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,72,1,1106, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,73,1,1105, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,74,1,1098, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,75,1,1097, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,76,1,1096, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,77,1,1095, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,78,1,1094, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,79,1,1090, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,80,1,1089, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,81,1,1088, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,82,1,1087, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,83,1,1086, +20,20,20,20,20,20,20,84,1,1042, +20,20,20,20,20,20,20,85,1,1041, +20,20,20,20,20,20,20,86,1,1040, +20,20,20,20,20,20,20,87,1,1039, +20,20,20,20,20,20,20,88,1,1038, +20,20,20,20,20,20,20,89,1,1037, +20,20,20,20,20,20,20,90,1,1033, +20,20,20,20,20,20,20,91,1,1032, +20,20,20,20,20,20,20,92,1,1031, +20,20,20,20,20,20,20,93,1,1030, +20,20,20,20,20,20,20,94,1,1029, +20,20,20,20,20,20,20,95,1,1028, +20,20,20,20,20,20,20,96,1,1027, +20,20,20,20,20,20,20,97,1,1026, +20,20,20,20,20,20,20,98,1,1025, +20,20,20,20,20,20,20,99,1,1022, +20,20,20,20,20,20,20,100,1,1021, +20,20,20,20,20,20,20,101,1,1020, +20,20,20,20,20,20,20,102,1,1019, +20,20,20,20,20,20,20,103,1,1018, +20,20,20,20,20,20,20,104,1,1017, +20,20,20,20,20,20,20,105,1,1016, +20,20,20,20,20,20,20,106,1,1015, +20,20,20,20,20,20,20,107,1,1011, +20,20,20,20,20,20,20,108,1,1010, +20,20,20,20,20,20,20,109,1,1007, +20,20,20,20,20,20,20,110,1,1006, +20,20,20,20,20,20,20,111,1,1005, +20,20,20,20,20,20,20,112,1,1004, +20,20,20,20,20,113,1,1070, +404,404,404,404,404,404,404,404,404,1,114,1,404, +405,405,405,405,405,405,405,405,405,1,115,1,405, +406,406,406,406,406,406,406,1,116,1,406, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,117,1,1134, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,118,1,1133, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,119,1,1132, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,120,1,1131, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,121,1,1130, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,122,1,1129, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,123,1,1128, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,124,1,1127, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,125,1,1126, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,126,1,1125, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,127,1,1124, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,128,1,1123, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,129,1,1122, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,130,1,1121, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,131,1,1120, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,132,1,1119, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,133,1,1118, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,134,1,1117, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,135,1,1116, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,136,1,1115, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,137,1,1114, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,138,1,1113, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,139,1,1112, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,140,1,1111, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,141,1,1104, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,142,1,1103, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,143,1,1102, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,144,1,1101, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,145,1,1100, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,146,1,1099, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,147,1,1093, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,148,1,1092, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,149,1,1091, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,150,1,1085, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,151,1,1084, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,152,1,1083, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,153,1,1082, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,154,1,1081, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,155,1,1080, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,156,1,1079, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,157,1,1078, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,158,1,1077, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,159,1,1076, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,160,1,1075, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,161,1,1074, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,162,1,1073, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,163,1,1072, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,164,1,1071, +20,20,20,20,20,20,20,20,20,165,1,1048, +20,20,20,20,20,20,20,20,20,166,1,1047, +20,20,20,20,20,20,20,20,20,167,1,1046, +20,20,20,20,20,20,20,20,20,168,1,1045, +20,20,20,20,20,169,1,1044, +20,20,20,20,20,170,1,1043, +20,20,20,20,20,20,20,20,171,1,1066, +20,20,20,20,20,20,20,20,172,1,1065, +20,20,20,20,20,20,20,20,173,1,1064, +20,20,20,20,20,20,20,20,20,20,174,1,1062, +20,20,20,20,20,20,20,20,20,20,175,1,1061, +20,20,20,20,20,20,20,20,20,20,176,1,1060, +20,20,20,20,20,20,20,20,20,20,177,1,1059, +20,20,20,20,20,20,20,20,20,20,178,1,1058, +20,20,20,20,20,20,20,20,20,20,179,1,1057, +20,20,20,20,20,20,20,20,20,20,180,1,1056, +20,20,20,20,20,20,20,20,20,20,181,1,1055, +20,20,20,20,20,20,20,20,20,20,182,1,1054, +20,20,20,20,20,20,20,20,20,20,183,1,1053, +20,20,20,20,20,20,20,20,20,20,184,1,1052, +20,20,20,20,20,20,20,20,20,20,185,1,1051, +20,20,20,20,20,20,20,20,20,20,186,1,1050, +407,407,407,407,1,187,1,407, +408,1,188,1,408, +409,1,189,1,409, +410,1,190,1,410, 411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411, 411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411, - 411,411,411,411,411,1,192,1,411, + 411,411,411,411,411,1,191,1,411, 412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412, 412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412, - 412,412,412,412,412,1,193,1,412, + 412,412,412,412,412,1,192,1,412, 413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, 413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, - 413,413,413,413,413,1,194,1,413, + 413,413,413,413,413,1,193,1,413, 414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, 414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, - 414,414,414,414,414,1,195,1,414, + 414,414,414,414,414,1,194,1,414, 415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, 415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, - 415,415,415,415,415,1,196,1,415, + 415,415,415,415,415,1,195,1,415, 416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, 416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, - 416,416,416,416,416,1,197,1,416, + 416,416,416,416,416,1,196,1,416, 417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417, 417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417, - 417,417,417,417,417,1,198,1,417, + 417,417,417,417,417,1,197,1,417, 418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, 418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, - 418,418,418,418,418,1,199,1,418, + 418,418,418,418,418,1,198,1,418, 419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419, 419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419, - 419,419,419,419,419,1,200,1,419, + 419,419,419,419,419,1,199,1,419, 420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420, 420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420, - 420,420,420,420,420,1,201,1,420, + 420,420,420,420,420,1,200,1,420, 421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421, 421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421, - 421,421,421,421,421,1,202,1,421, + 421,421,421,421,421,1,201,1,421, 422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, 422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, - 422,422,422,422,422,1,203,1,422, + 422,422,422,422,422,1,202,1,422, 423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423, 423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423, - 423,423,423,423,423,1,204,1,423, + 423,423,423,423,423,1,203,1,423, 424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424, 424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424, - 424,424,424,424,424,1,205,1,424, + 424,424,424,424,424,1,204,1,424, 425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425, 425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425, - 425,425,425,425,425,1,206,1,425, + 425,425,425,425,425,1,205,1,425, 426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, 426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, - 426,426,426,426,426,1,207,1,426, + 426,426,426,426,426,1,206,1,426, 427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427, 427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427, - 427,427,427,427,427,1,208,1,427, + 427,427,427,427,427,1,207,1,427, 428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, 428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, - 428,428,428,428,428,1,209,1,428, + 428,428,428,428,428,1,208,1,428, 429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, 429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, - 429,429,429,429,429,1,210,1,429, + 429,429,429,429,429,1,209,1,429, 430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430, 430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430, - 430,430,430,430,430,1,211,1,430, + 430,430,430,430,430,1,210,1,430, 431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431, 431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431, - 431,431,431,431,431,1,212,1,431, + 431,431,431,431,431,1,211,1,431, 432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432, 432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432, - 432,432,432,432,432,1,213,1,432, + 432,432,432,432,432,1,212,1,432, 433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433, 433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433, - 433,433,433,433,433,1,214,1,433, + 433,433,433,433,433,1,213,1,433, 434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434, 434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434, - 434,434,434,434,434,1,215,1,434, + 434,434,434,434,434,1,214,1,434, 435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435, 435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435, - 435,435,435,435,435,1,216,1,435, + 435,435,435,435,435,1,215,1,435, 436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, 436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, - 436,436,436,436,436,1,217,1,436, + 436,436,436,436,436,1,216,1,436, 437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, 437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, - 437,437,437,437,437,1,218,1,437, + 437,437,437,437,437,1,217,1,437, 438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, 438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, - 438,438,438,438,438,1,219,1,438, + 438,438,438,438,438,1,218,1,438, 439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, 439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, - 439,439,439,439,439,1,220,1,439, + 439,439,439,439,439,1,219,1,439, 440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, 440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, - 440,440,440,440,440,1,221,1,440, + 440,440,440,440,440,1,220,1,440, 441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441, 441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441, - 441,441,441,441,441,1,222,1,441, + 441,441,441,441,441,1,221,1,441, 442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442, 442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442, - 442,442,442,442,442,1,223,1,442, + 442,442,442,442,442,1,222,1,442, 443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443, 443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443, - 443,443,443,443,443,1,224,1,443, + 443,443,443,443,443,1,223,1,443, 444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444, 444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444, - 444,444,444,444,444,1,225,1,444, + 444,444,444,444,444,1,224,1,444, 445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445, 445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445, - 445,445,445,445,445,1,226,1,445, + 445,445,445,445,445,1,225,1,445, 446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446, 446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446, - 446,446,446,446,446,1,227,1,446, + 446,446,446,446,446,1,226,1,446, 447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447, 447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447, - 447,447,447,447,447,1,228,1,447, + 447,447,447,447,447,1,227,1,447, 448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448, 448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448, - 448,448,448,448,448,1,229,1,448, + 448,448,448,448,448,1,228,1,448, 449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, 449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, - 449,449,449,449,449,1,230,1,449, + 449,449,449,449,449,1,229,1,449, 450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, 450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, - 450,450,450,450,450,1,231,1,450, + 450,450,450,450,450,1,230,1,450, 451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, 451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, - 451,451,451,451,451,1,232,1,451, + 451,451,451,451,451,1,231,1,451, 452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452, 452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452, - 452,452,452,452,452,1,233,1,452, + 452,452,452,452,452,1,232,1,452, 453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453, 453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453, - 453,453,453,453,453,1,234,1,453, + 453,453,453,453,453,1,233,1,453, 454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454, 454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454, - 454,454,454,454,454,1,235,1,454, + 454,454,454,454,454,1,234,1,454, 455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455, 455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455, - 455,455,455,455,455,1,236,1,455, + 455,455,455,455,455,1,235,1,455, 456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456, 456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456, - 456,456,456,456,456,1,237,1,456, + 456,456,456,456,456,1,236,1,456, 457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457, 457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457, - 457,457,457,457,457,1,238,1,457, + 457,457,457,457,457,1,237,1,457, 458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458, 458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458, - 458,458,458,458,458,1,239,1,458, + 458,458,458,458,458,1,238,1,458, 459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459, 459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459, - 459,459,459,459,459,1,240,1,459, -460,460,460,460,460,460,460,460,1,241,1,460, -461,461,461,461,461,461,461,461,1,242,1,461, -462,462,462,462,462,462,462,462,1,243,1,462, -463,463,463,463,463,463,463,463,1,244,1,463, -464,464,464,464,1,245,1,464, -465,465,465,465,1,246,1,465, -466,466,466,466,466,466,466,1,247,1,466, -467,467,467,467,467,467,467,1,248,1,467, -468,468,468,468,468,468,468,1,249,1,468, -469,469,469,469,469,469,469,469,469,1,250,1,469, -470,470,470,470,470,470,470,470,470,1,251,1,470, -471,471,471,471,471,471,471,471,471,1,252,1,471, -472,472,472,472,472,472,472,472,472,1,253,1,472, -473,473,473,473,473,473,473,473,473,1,254,1,473, -474,474,474,474,474,474,474,474,474,1,255,1,474, -475,475,475,475,475,475,475,475,475,1,256,1,475, -476,476,476,476,476,476,476,476,476,1,257,1,476, -477,477,477,477,477,477,477,477,477,1,258,1,477, -478,478,478,478,478,478,478,478,478,1,259,1,478, -479,479,479,479,479,479,479,479,479,1,260,1,479, -480,480,480,480,480,480,480,480,480,1,261,1,480, -481,481,481,481,481,481,481,481,481,1,262,1,481, -19,132,132,132,132,132,132,132,132,132,132,132,19,132,19,19,133,133,133,133, - 133,19,132,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,132,19,19,19,19,1,263,1,891,133, -19,19,19,19,19,1,264,1,311, -62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62, - 62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62, - 62,62,62,62,62,62,62,62,62,307,62,62,62,62,62,62,62,62,62,265,482, -116,116,116,116,483,266,483, -484,115,485, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,268,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,335,104,220,323,309,263,336,324,328,327,326,325,219,328,318, - 317,316,315,314,313,312,311,310,308,291,290,263,306,305, -295,486,488,490,491,492,494,495,496,500,502,504,506,508,510,512,514,516,517, - 519,520,521,523,524,526,527,528,529,532,533,14,15,340,342,344,346,348, - 269,71,72,531,73,75,499,498,66,67,530,530,530,530,80,525,525,525,522, - 522,522,522,518,518,518,515,513,511,509,507,505,503,501,497,107,108,493, - 111,112,489,487,117, -534,534,534,534,1,270,1,534, -535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535, - 535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535, - 535,535,535,1,271,1,535, -536,536,536,536,1,272,1,536, -143,537,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, - 143,143,143,143,139,143,143,143,143,143,143,143,143,143,143,143,143,143, - 143,143,143,143,143,273,141, -19,19,19,19,19,19,19,19,274,1,884, -382,275,538, -539,539,539,539,1,276,1,539, -540,540,540,540,1,277,1,540, -41,42,43,38,278,55,55,46,55,45,44,44, -41,42,43,38,279,54,54,46,54,45,44,44, -541,541,541,541,1,280,1,541, -276,276,276,276,276,281, -261,261,261,261,282, -259,259,283, -131,131,131,131,131,131,131,255,255,255,255,131,255,255,255,255,255,131,131, - 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, - 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, - 131,131,131,284, -250,542,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, - 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, - 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,285, -248,248,248,248,248,286, -266,543,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, - 266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, - 266,266,266,272,266,287,544, -277,277,277,277,277,274, -241,258,258,258,258,258,258,258,258,258,289, -262,262,262,262,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, - 240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, - 240,240,240,240,240,290, -260,260,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, - 239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, - 239,239,239,291, -256,256,256,256,256,256,256,256,256,238,238,238,238,238,238,238,238,238,238, - 238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, - 238,238,238,238,238,238,238,238,238,238,292, -252,242,257,545,546,257,251,251,251,251,251,253,237,237,237,237,237,237,237, - 237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237, - 237,237,237,237,237,237,275,237,237,237,237,246,246,237,293,246, -19,19,294,1,986, -19,19,19,19,19,19,295,1,940, -19,19,296,1,984, -19,19,297,1,983, -19,19,298,1,982, -19,19,299,1,981, -19,19,300,1,980, -19,19,301,1,979, -19,19,302,1,978, -19,19,303,1,977, -19,19,304,1,976, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,305,1,987, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,1,306,1,941, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,307,1,908, -547,1,308,1,547, -548,1,309,1,548, -549,1,310,1,549, -550,1,311,1,550, -551,1,312,1,551, -552,1,313,1,552, -553,1,314,1,553, -554,1,315,1,554, -555,1,316,1,555, -556,1,317,1,556, -557,1,318,1,557, -19,19,19,19,19,19,19,19,19,19,19,19,19,249,249,249,249,249,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,319,1,967, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,320,1,975, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,321,1,974, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,322,1,973, -558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558, - 558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558, - 558,558,558,558,558,1,323,1,558, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, - 130,129,324,234,292,293,235,288,236,289,265,220,323,309,263,218,219,218, - 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, - 130,129,325,234,292,293,235,288,236,289,265,220,323,309,263,217,219,217, - 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, - 130,129,326,234,292,293,235,288,236,289,265,220,323,309,263,216,219,216, - 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, - 130,129,327,234,292,293,235,288,236,289,265,220,323,309,263,215,219,215, - 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,1,328,1,208, -19,560,562,388,380,384,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,1,329,1,205,566,565,564,563,561, -19,381,383,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,1,330,1,200,568,567, -19,569,571,573,575,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,1,331,1,197,576,574,572,570, -19,577,387,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,1,332,1,194,579,578, -19,580,359,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1, - 333,1,191,582,581, -583,357,190,585,584, -586,587,588,589,590,591,592,593,594,595,596,597,396,170,170,170,170,170,335, - 174,174,174,174,177,177,177,180,180,180,183,183,183,186,186,186,189,189, - 189, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,336,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,169,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -598,598,598,598,1,337,1,598, -599,599,599,599,1,338,1,599, -600,600,600,600,600,339,600, -19,19,19,19,19,340,1,894, -601,601,601,601,1,341,1,601, -19,19,19,19,19,342,1,893, -602,602,602,602,1,343,1,602, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,344,1,892, -603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,1,345,1,603, -19,19,19,19,19,346,1,890, -604,604,604,604,1,347,1,604, -19,19,19,19,19,348,1,888, -605,605,605,605,1,349,1,605, -159,159,606,159,159,159,159,159,159,159,159,159,159,159,159,157,159,159,159, - 159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, - 159,159,159,159,350, -19,19,19,19,19,351,1,885, -607,607,607,607,1,352,1,607, -608,608,608,608,1,353,1,608, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,354,1,883, -134,134,134,134,134,134,134,134,134,134,134,134,158,134,134,134,134,134,140, - 134,134,355,612,273,611,350,610,274,351,609, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,356,1, - 1154, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,357,1,956, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,358,1, - 1153, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,359,1,958, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,360,1,1152, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,361,1, - 1151, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,362,1, - 1150, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,363,1, - 1149, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,364,1, - 1148, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,365,1, - 1147, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,366,1, - 1146, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,367,1, - 1145, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,368,1, - 1144, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,369,1, - 1143, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,370,1, - 1142, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,371,1, - 1141, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,372,1, - 1140, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,373,1, - 1139, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,374,1, - 1138, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,375,1, - 1137, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,376,1, - 1136, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,377,1, - 1135, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,378,1, - 1134, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,379,1, - 1133, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,380,1,969, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,381,1,967, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,382,1,903, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,383,1,966, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,384,1,968, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,385,1, - 907, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,386,1, - 1132, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,387,1,960, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,388,1,970, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,389,1, - 1131, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,390,1, - 1130, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,391,1, - 1129, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,392,1,875, -356,358,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376, - 377,378,379,386,389,390,391,320,322,388,380,384,381,383,387,359,357,307, - 385,382,39,42,7,9,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7, -38,394,11, -38,395,10, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,396,1,881, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,397,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,613,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -295,486,488,490,491,492,494,495,496,500,502,504,506,508,510,512,514,516,517, - 519,520,521,523,524,526,527,528,529,532,533,14,15,340,342,344,346,348, - 614,616,398,617,615,71,72,531,73,75,499,498,66,67,530,530,530,530,80, - 525,525,525,522,522,522,522,518,518,518,515,513,511,509,507,505,503,501, - 497,107,108,493,111,112,489,487,117, -618,618,618,618,1,399,1,618, -619,295,41,42,43,38,400,620,68,68,46,68,45,44,44,167,168, -305,621,622,623,307,306,307,306,305,401,305,306,307,310,397,308,309, -287,286,286,283,282,281,280,279,278,402,395,286,624, -290,297,296,293,296,293,290,403,393,290,293,296,625, -399,399,399,399,404,399, -382,405,626, -382,406,627, -382,407,628, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,408,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,467,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,409,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,466,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,410,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,465,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,411,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,464,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,412,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,463,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,413,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,462,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,414,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,461,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,415,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,460,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,416,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,459,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,417,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,458,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,418,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,457,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,419,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,456,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,420,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,455,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,421,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,454,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,422,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,453,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,423,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,452,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,424,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,451,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,425,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,450,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,426,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,449,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,427,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,448,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,428,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,447,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,429,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,446,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,430,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,445,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,431,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,444,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,432,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,443,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,433,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,439,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,434,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,435,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,435,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,434,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,436,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,433,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,437,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,432,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,438,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,431,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,439,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,430,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,440,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,429,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,441,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,423,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,442,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,422,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,443,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,421,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,444,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,420,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,445,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,414,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,446,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,413,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,447,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,412,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,448,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,411,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,449,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,410,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,450,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,409,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,451,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,408,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,452,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,407,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,453,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,406,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,454,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,405,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,455,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,404,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,456,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,403,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,457,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,402,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,458,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,401,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,459,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,400,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -298,629,630,300,299,300,299,298,460,302,298,299,300,376,301, -298,629,630,300,299,300,299,298,461,302,298,299,300,375,301, -298,629,630,300,299,300,299,298,462,302,298,299,300,374,301, -298,629,630,300,299,300,299,298,463,302,298,299,300,373,301, -303,304,304,303,464,303,304,372, -303,304,304,303,465,303,304,371, -290,297,296,293,296,293,290,466,392,290,293,296,625, -290,297,296,293,296,293,290,467,391,290,293,296,625, -290,297,296,293,296,293,290,468,390,290,293,296,625, -305,621,622,623,307,306,307,306,305,469,305,306,307,310,389,308,309, -305,621,622,623,307,306,307,306,305,470,305,306,307,310,388,308,309, -287,286,286,283,282,281,280,279,278,471,387,286,624, -287,286,286,283,282,281,280,279,278,472,386,286,624, -287,286,286,283,282,281,280,279,278,473,385,286,624, -287,286,286,283,282,281,280,279,278,474,384,286,624, -287,286,286,283,282,281,280,279,278,475,631,286,624, -287,286,286,283,282,281,280,279,278,476,382,286,624, -287,286,286,283,282,281,280,279,278,477,381,286,624, -287,286,286,283,282,281,280,279,278,478,380,286,624, -287,286,286,283,282,281,280,279,278,479,379,286,624, -287,286,286,283,282,281,280,279,278,480,378,286,624, -287,286,286,283,282,281,280,279,278,481,377,286,624, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,632, - 284,140,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286, - 295,307,281,265,130,129,482,234,292,293,235,288,119,273,236,289,633,120, - 265,332,331,329,334,330,333,328,121,220,323,635,309,263,324,328,327,326, - 325,219,328,318,317,316,315,314,313,312,311,310,308,291,290,274,263,634, - 306,305, -282,250,250,250,250,285,287,636,283,559,286,265,18,483,118,292,637,236,289, - 291,290,306, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,484,1,993, -638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, - 638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, - 638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, - 638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, - 638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, - 638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, - 638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, - 638,638,638,638,638,638,1,485,1,638, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,486,1,939, -131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,487,114,263,263, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,488,1,938, -134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, - 489,113,609, -19,19,19,19,19,490,1,937, -19,19,19,19,19,491,1,936, -19,19,1,492,1,935, -639,140,493,110,273,633,109,274,634, -19,19,19,19,19,494,1,933, -19,19,19,19,19,495,1,932, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,496,1,931, -131,131,131,131,131,131,131,131,131,131,131,131,131,102,102,102,102,130,129, - 102,497,103,263,263, -140,498,640,273,274, -140,499,100,273,274, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,500,1,930, -641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641, - 641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641, - 641,641,641,641,641,641,1,501,1,641, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,502,1,929, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,140,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286, - 295,307,281,265,130,129,503,234,292,293,235,288,98,273,236,289,265,332, - 331,329,334,330,333,328,97,220,323,309,263,324,328,327,326,325,219,328, - 318,317,316,315,314,313,312,311,310,308,291,290,274,263,306,305, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,504,1,928, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,505,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,96,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,506,1,927, -131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,507,95,263,263, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,508,1,926, -131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,509,94,263,263, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,510,1,925, -131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,511,125,642,263, - 263, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,512,1,924, -131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,513,125,643,263, - 263, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,514,1,923, -131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,515,125,644,263, - 263, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,516,1,922, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,517,1,921, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,632, - 284,140,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286, - 295,307,281,265,130,129,518,234,292,293,235,288,119,273,236,289,633,120, - 265,332,331,329,334,330,333,328,121,220,323,645,309,263,324,328,327,326, - 325,219,328,318,317,316,315,314,313,312,311,310,308,291,290,274,263,634, - 306,305, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,519,1,920, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,520,1,919, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,521,1,918, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,632, - 284,140,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286, - 295,307,281,265,130,129,522,234,292,293,235,288,119,273,236,289,633,120, - 265,332,331,329,334,330,333,328,121,220,323,646,309,263,324,328,327,326, - 325,219,328,318,317,316,315,314,313,312,311,310,308,291,290,274,263,634, - 306,305, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,523,1,917, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,524,1,916, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,525,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,83,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -19,19,19,19,19,526,1,915, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,527,1,914, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,528,1,913, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,529,1,912, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,530,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,79,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,531,74,263,263, -19,19,19,19,19,19,19,532,1,911, -19,19,19,19,19,19,19,533,1,910, -41,42,43,38,534,21,21,46,21,45,44,44, -356,358,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377, - 378,379,386,389,390,391,320,322,388,380,384,381,383,387,359,357,307,385, - 382,39,42,535,63,63,63,647,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, - 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, -41,42,43,38,536,59,59,46,59,45,44,44, -144,648,146,147,145,151,150,649,649,650,648,149,142,537,648, -651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651, - 651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651, - 651,651,651,651,651,1,538,1,651, -41,42,43,38,539,57,57,46,57,45,44,44, -41,42,43,38,540,56,56,46,56,45,44,44, -41,42,43,38,541,53,53,46,53,45,44,44, -254,254,254,254,254,254,254,254,254,542, -267,269,270,268,271,273,543, -266,543,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, - 266,266,263,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, - 266,266,266,266,272,266,544,652, -257,257,257,257,257,257,257,257,257,257,247,247,247,247,247,247,247,247,247, - 247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, - 247,247,247,247,247,247,247,247,247,247,247,545, -257,257,257,257,257,257,257,257,257,257,243,243,243,243,243,243,243,243,243, + 459,459,459,459,459,1,239,1,459, +460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460, + 460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460, + 460,460,460,460,460,1,240,1,460, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, + 461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, + 461,461,461,461,461,1,241,1,461, +462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462, + 462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462, + 462,462,462,462,462,1,242,1,462, +463,463,463,463,463,463,463,463,1,243,1,463, +464,464,464,464,464,464,464,464,1,244,1,464, +465,465,465,465,465,465,465,465,1,245,1,465, +466,466,466,466,466,466,466,466,1,246,1,466, +467,467,467,467,1,247,1,467, +468,468,468,468,1,248,1,468, +469,469,469,469,469,469,469,1,249,1,469, +470,470,470,470,470,470,470,1,250,1,470, +471,471,471,471,471,471,471,1,251,1,471, +472,472,472,472,472,472,472,472,472,1,252,1,472, +473,473,473,473,473,473,473,473,473,1,253,1,473, +474,474,474,474,474,474,474,474,474,1,254,1,474, +475,475,475,475,475,475,475,475,475,1,255,1,475, +476,476,476,476,476,476,476,476,476,1,256,1,476, +477,477,477,477,477,477,477,477,477,1,257,1,477, +478,478,478,478,478,478,478,478,478,1,258,1,478, +479,479,479,479,479,479,479,479,479,1,259,1,479, +480,480,480,480,480,480,480,480,480,1,260,1,480, +481,481,481,481,481,481,481,481,481,1,261,1,481, +482,482,482,482,482,482,482,482,482,1,262,1,482, +483,483,483,483,483,483,483,483,483,1,263,1,483, +484,484,484,484,484,484,484,484,484,1,264,1,484, +20,138,138,138,138,138,138,138,138,138,138,138,20,138,20,20,139,139,139,139, + 139,20,138,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,138,20,20,20,20,20,1,265,1,897,139, +20,20,20,20,20,20,1,266,1,317, +66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66, + 66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66, + 66,66,66,66,66,66,66,66,66,310,66,66,66,66,66,66,66,66,66,66,267,485, +122,122,122,122,122,486,268,486, +487,121,488, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,270,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,338,110,226,326,312,265,339,327,331,330,329,328,225,331,321, + 320,319,318,317,316,315,314,313,311,294,293,265,309,308, +298,489,491,493,494,495,497,498,499,503,506,508,510,512,514,516,518,519,521, + 522,523,525,526,528,529,530,531,534,535,14,15,16,343,345,347,349,351, + 271,75,76,533,77,79,505,502,501,70,71,532,532,532,532,84,527,527,527, + 524,524,524,524,520,520,520,517,515,513,511,509,507,504,500,113,114,496, + 117,118,492,490,123, +536,536,536,536,536,1,272,1,536, +537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, + 537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, + 537,537,537,1,273,1,537, +538,538,538,538,538,1,274,1,538, +146,275,539,278,279, +146,276,540,278,279, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,146,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289, + 298,310,284,271,136,135,277,240,295,296,241,291,542,278,242,292,267,335, + 334,332,337,333,336,331,541,226,326,312,265,327,331,330,329,328,225,331, + 321,320,319,318,317,316,315,314,313,311,294,293,279,265,309,308, +149,543,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, + 149,149,149,149,145,149,149,149,149,149,149,149,149,149,149,149,149,149, + 149,149,149,149,149,278,147, +20,20,20,20,20,20,20,20,20,279,1,890, +544,544,544,544,544,1,280,1,544, +43,44,45,40,57,281,57,57,48,57,47,46,46, +43,44,45,40,56,282,56,56,48,56,47,46,46, +545,545,545,545,545,1,283,1,545, +282,282,282,282,282,284, +267,267,267,267,285, +265,265,286, +137,137,137,137,137,137,137,261,261,261,261,137,261,261,261,261,261,137,137, + 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, + 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, + 137,137,137,137,287, +256,546,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256, + 256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256, + 256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256, + 288, +254,254,254,254,254,289, +272,547,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, + 272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, + 272,272,272,278,272,290,548, +283,283,283,283,283,280, +247,264,264,264,264,264,264,264,264,264,292, +268,268,268,268,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, + 246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, + 246,246,246,246,246,246,293, +266,266,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, + 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, + 245,245,245,245,294, +262,262,262,262,262,262,262,262,262,244,244,244,244,244,244,244,244,244,244, + 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, + 244,244,244,244,244,244,244,244,244,244,244,295, +258,248,263,549,550,263,257,257,257,257,257,259,243,243,243,243,243,243,243, 243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, - 243,243,243,243,243,243,243,243,243,243,243,546, -307,547,653, -307,548,654, -307,549,655, -307,550,656, -307,551,657, -307,552,658, -307,553,659, -307,554,660, -307,555,661, -307,556,662, -307,557,663, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,558,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,664,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -249,249,249,249,249,559, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,560,1,972, -665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665, - 665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665, - 665,665,1,561,1,665, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,562,1,971, -666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666, - 666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666, - 666,666,1,563,1,666, -667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667, - 667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667, - 667,667,1,564,1,667, -668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668, - 668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668, - 668,668,1,565,1,668, -669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669, - 669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669, - 669,669,1,566,1,669, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, - 670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, - 670,670,670,670,670,1,567,1,670, -671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, - 671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, - 671,671,671,671,671,1,568,1,671, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,569,1,965, -672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, - 672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, - 672,672,672,672,672,1,570,1,672, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,571,1,964, + 243,243,243,243,243,243,281,243,243,243,243,252,252,243,243,296,252, +20,20,297,1,992, +20,20,20,20,20,20,20,298,1,946, +20,20,299,1,990, +20,20,300,1,989, +20,20,301,1,988, +20,20,302,1,987, +20,20,303,1,986, +20,20,304,1,985, +20,20,305,1,984, +20,20,306,1,983, +20,20,307,1,982, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,308,1,993, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,1,309,1,947, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,310,1,915, +551,1,311,1,551, +552,1,312,1,552, +553,1,313,1,553, +554,1,314,1,554, +555,1,315,1,555, +556,1,316,1,556, +557,1,317,1,557, +558,1,318,1,558, +559,1,319,1,559, +560,1,320,1,560, +561,1,321,1,561, +20,20,20,20,20,20,20,20,20,20,20,20,20,255,255,255,255,255,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,322,1,973, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,323,1,981, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,324,1,980, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,325,1,979, +562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562, + 562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562, + 562,562,562,562,562,1,326,1,562, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, + 136,135,327,240,295,296,241,291,242,292,267,226,326,312,265,224,225,224, + 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, + 136,135,328,240,295,296,241,291,242,292,267,226,326,312,265,223,225,223, + 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, + 136,135,329,240,295,296,241,291,242,292,267,226,326,312,265,222,225,222, + 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, + 136,135,330,240,295,296,241,291,242,292,267,226,326,312,265,221,225,221, + 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,1,331,1,214, +20,564,566,391,383,387,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,1,332,1,211,570,569,568,567,565, +20,384,386,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,1,333,1,206,572,571, +20,573,575,577,579,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,1,334,1,203,580,578,576,574, +20,581,390,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,1,335,1,200,583,582, +20,584,362,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,1,336,1,197,586,585, +587,360,196,589,588, +590,591,592,593,594,595,596,597,598,599,600,601,399,176,176,176,176,176,176, + 338,180,180,180,180,183,183,183,186,186,186,189,189,189,192,192,192,195, + 195,195, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,339,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,175,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +602,602,602,602,602,1,340,1,602, +603,603,603,603,603,1,341,1,603, +604,604,604,604,604,604,342,604, +20,20,20,20,20,20,343,1,900, +605,605,605,605,605,1,344,1,605, +20,20,20,20,20,20,345,1,899, +606,606,606,606,606,1,346,1,606, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,347,1,898, +607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,1,348,1,607, +20,20,20,20,20,20,349,1,896, +608,608,608,608,608,1,350,1,608, +20,20,20,20,20,20,351,1,894, +609,609,609,609,609,1,352,1,609, +165,165,610,165,165,165,165,165,165,165,165,165,165,165,165,163,165,165,165, + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, + 165,165,165,165,353, +20,20,20,20,20,20,354,1,891, +611,611,611,611,611,1,355,1,611, +612,612,612,612,612,1,356,1,612, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,357,1,889, +140,140,140,140,140,140,140,140,140,140,140,140,164,140,140,140,140,140,146, + 140,140,358,616,278,615,353,614,279,354,613, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 359,1,1160, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,360,1,962, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 361,1,1159, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,362,1,964, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,363,1,1158, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 364,1,1157, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 365,1,1156, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 366,1,1155, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 367,1,1154, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 368,1,1153, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 369,1,1152, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 370,1,1151, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 371,1,1150, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 372,1,1149, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 373,1,1148, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 374,1,1147, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 375,1,1146, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 376,1,1145, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 377,1,1144, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 378,1,1143, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 379,1,1142, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 380,1,1141, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 381,1,1140, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 382,1,1139, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,383,1,975, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,384,1,973, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,385,1,910, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,386,1,972, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,387,1,974, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 388,1,914, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 389,1,1138, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,390,1,966, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,391,1,976, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 392,1,1137, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 393,1,1136, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 394,1,1135, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,395,1,881, +359,361,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379, + 380,381,382,389,392,393,394,323,325,391,383,387,384,386,390,362,360,310, + 388,385,41,44,7,9,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7, +40,397,11, +40,398,10, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,399,1,887, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,400,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,617,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +298,489,491,493,494,495,497,498,499,503,506,508,510,512,514,516,518,519,521, + 522,523,525,526,528,529,530,531,534,535,14,15,16,343,345,347,349,351, + 618,620,401,621,619,75,76,533,77,79,505,502,501,70,71,532,532,532,532, + 84,527,527,527,524,524,524,524,520,520,520,517,515,513,511,509,507,504, + 500,113,114,496,117,118,492,490,123, +622,622,622,622,622,1,402,1,622, +623,298,43,44,45,40,72,403,624,72,72,48,72,47,46,46,173,174, +311,625,626,627,313,312,313,312,311,404,311,312,313,316,403,314,315, +293,292,292,289,288,287,286,285,284,405,401,292,628, +296,303,302,299,302,299,296,406,399,296,299,302,629, +405,405,405,405,407,405, +385,408,630, +385,409,631, +385,410,632, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,411,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,473,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,412,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,472,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,413,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,471,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,414,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,470,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,415,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,469,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,416,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,468,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,417,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,467,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,418,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,466,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,419,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,465,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,420,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,464,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,421,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,463,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,422,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,462,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,423,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,461,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,424,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,460,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,425,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,459,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,426,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,458,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,427,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,457,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,428,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,456,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,429,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,455,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,430,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,454,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,431,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,453,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,432,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,452,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,433,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,451,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,434,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,450,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,435,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,449,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,436,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,445,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,437,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,441,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,438,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,440,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,439,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,439,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,440,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,438,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,441,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,437,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,442,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,436,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,443,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,435,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,444,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,429,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,445,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,428,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,446,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,427,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,447,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,426,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,448,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,420,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,449,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,419,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,450,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,418,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,451,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,417,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,452,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,416,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,453,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,415,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,454,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,414,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,455,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,413,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,456,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,412,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,457,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,411,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,458,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,410,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,459,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,409,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,460,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,408,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,461,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,407,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,462,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,406,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +304,633,634,306,305,306,305,304,463,308,304,305,306,382,307, +304,633,634,306,305,306,305,304,464,308,304,305,306,381,307, +304,633,634,306,305,306,305,304,465,308,304,305,306,380,307, +304,633,634,306,305,306,305,304,466,308,304,305,306,379,307, +309,310,310,309,467,309,310,378, +309,310,310,309,468,309,310,377, +296,303,302,299,302,299,296,469,398,296,299,302,629, +296,303,302,299,302,299,296,470,397,296,299,302,629, +296,303,302,299,302,299,296,471,396,296,299,302,629, +311,625,626,627,313,312,313,312,311,472,311,312,313,316,395,314,315, +311,625,626,627,313,312,313,312,311,473,311,312,313,316,394,314,315, +293,292,292,289,288,287,286,285,284,474,393,292,628, +293,292,292,289,288,287,286,285,284,475,392,292,628, +293,292,292,289,288,287,286,285,284,476,391,292,628, +293,292,292,289,288,287,286,285,284,477,390,292,628, +293,292,292,289,288,287,286,285,284,478,635,292,628, +293,292,292,289,288,287,286,285,284,479,388,292,628, +293,292,292,289,288,287,286,285,284,480,387,292,628, +293,292,292,289,288,287,286,285,284,481,386,292,628, +293,292,292,289,288,287,286,285,284,482,385,292,628, +293,292,292,289,288,287,286,285,284,483,384,292,628, +293,292,292,289,288,287,286,285,284,484,383,292,628, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,636, + 287,146,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289, + 298,310,284,271,136,135,485,240,295,296,241,291,125,278,242,292,637,126, + 267,335,334,332,337,333,336,331,127,226,326,639,312,265,327,331,330,329, + 328,225,331,321,320,319,318,317,316,315,314,313,311,294,293,279,265,638, + 309,308, +285,256,256,256,256,288,290,640,286,563,289,271,19,486,124,295,641,242,292, + 294,293,309, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,487,1,999, +642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, + 642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, + 642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, + 642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, + 642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, + 642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, + 642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, + 642,642,642,642,642,642,1,488,1,642, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,489,1,945, +137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,490,120,265,265, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,491,1,944, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, + 492,119,613, +20,20,20,20,20,20,493,1,943, +20,20,20,20,20,20,494,1,942, +20,20,1,495,1,941, +643,146,496,116,278,637,115,279,638, +20,20,20,20,20,20,497,1,939, +20,20,20,20,20,20,498,1,938, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,499,1,937, +137,137,137,137,137,137,137,137,137,137,137,137,137,108,108,108,108,136,135, + 108,108,500,109,265,265, +146,501,644,278,279, +146,502,106,278,279, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,503,1,936, +645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645, + 645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645, + 645,645,645,645,645,645,1,504,1,645, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,146,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289, + 298,310,284,271,136,135,1,505,240,295,296,241,291,102,278,242,292,267, + 335,334,332,337,333,336,331,1,646,101,226,326,312,265,327,331,330,329, + 328,225,331,321,320,319,318,317,316,315,314,313,311,294,293,279,265,309, + 308, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,506,1,935, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,507,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,100,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,508,1,934, +137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,509,99,265,265, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,510,1,933, +137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,511,98,265,265, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,512,1,932, +137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,513,131,647,265, + 265, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,514,1,931, +137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,515,131,648,265, + 265, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,516,1,930, +137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,517,131,649,265, + 265, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,518,1,929, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,519,1,928, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,636, + 287,146,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289, + 298,310,284,271,136,135,520,240,295,296,241,291,125,278,242,292,637,126, + 267,335,334,332,337,333,336,331,127,226,326,650,312,265,327,331,330,329, + 328,225,331,321,320,319,318,317,316,315,314,313,311,294,293,279,265,638, + 309,308, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,521,1,927, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,522,1,926, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,523,1,925, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,636, + 287,146,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289, + 298,310,284,271,136,135,524,240,295,296,241,291,125,278,242,292,637,126, + 267,335,334,332,337,333,336,331,127,226,326,651,312,265,327,331,330,329, + 328,225,331,321,320,319,318,317,316,315,314,313,311,294,293,279,265,638, + 309,308, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,525,1,924, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,526,1,923, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,527,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,87,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +20,20,20,20,20,20,528,1,922, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,529,1,921, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,530,1,920, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,531,1,919, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,532,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,83,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,533,78,265,265, +20,20,20,20,20,20,20,20,534,1,918, +20,20,20,20,20,20,20,20,535,1,917, +43,44,45,40,22,536,22,22,48,22,47,46,46, +359,361,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380, + 381,382,389,392,393,394,323,325,391,383,387,384,386,390,362,360,310,388, + 385,41,44,537,67,67,67,652,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, +43,44,45,40,63,538,63,63,48,63,47,46,46, +385,539,653, +654,654,654,654,654,1,540,1,654, +655,655,655,655,655,1,541,1,655, +656,656,656,656,656,1,542,1,656, +150,657,152,153,151,157,156,658,658,659,657,155,148,543,657, +43,44,45,40,58,544,58,58,48,58,47,46,46, +43,44,45,40,55,545,55,55,48,55,47,46,46, +260,260,260,260,260,260,260,260,260,546, +273,275,276,274,277,279,547, +272,547,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, + 272,272,269,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, + 272,272,272,272,278,272,548,660, +263,263,263,263,263,263,263,263,263,263,253,253,253,253,253,253,253,253,253, + 253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, + 253,253,253,253,253,253,253,253,253,253,253,253,549, +263,263,263,263,263,263,263,263,263,263,249,249,249,249,249,249,249,249,249, + 249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, + 249,249,249,249,249,249,249,249,249,249,249,249,550, +310,551,661, +310,552,662, +310,553,663, +310,554,664, +310,555,665, +310,556,666, +310,557,667, +310,558,668, +310,559,669, +310,560,670, +310,561,671, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,562,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,672,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +255,255,255,255,255,563, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,564,1,978, 673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, 673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, - 673,673,673,673,673,1,572,1,673, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,573,1,963, + 673,673,1,565,1,673, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,566,1,977, 674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674, 674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674, - 674,674,674,674,674,1,574,1,674, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,575,1,962, + 674,674,1,567,1,674, 675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675, 675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675, - 675,675,675,675,675,1,576,1,675, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,577,1,961, + 675,675,1,568,1,675, 676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676, 676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676, - 676,676,676,676,676,1,578,1,676, + 676,676,1,569,1,676, 677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677, 677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677, - 677,677,677,677,677,1,579,1,677, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,580,1,959, + 677,677,1,570,1,677, 678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678, 678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678, - 678,678,678,678,678,1,581,1,678, + 678,678,678,678,678,1,571,1,678, 679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, 679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, - 679,679,679,679,679,1,582,1,679, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,583,1,957, + 679,679,679,679,679,1,572,1,679, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,573,1,971, 680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680, 680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680, - 680,680,680,680,680,1,584,1,680, + 680,680,680,680,680,1,574,1,680, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,575,1,970, 681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681, 681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681, - 681,681,681,681,681,1,585,1,681, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,586,1,955, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,587,1,954, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,588,1,953, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,589,1,952, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,590,1,951, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,591,1,950, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,592,1,949, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,593,1,948, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,594,1,947, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,595,1,946, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,596,1,945, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,597,1,944, -41,42,43,38,598,52,52,46,52,45,44,44, -41,42,43,38,599,51,51,46,51,45,44,44, -41,42,43,38,600,50,50,46,50,45,44,44, -41,42,43,38,601,47,47,46,47,45,44,44, -41,42,43,38,602,46,46,46,46,45,44,44, -131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,603,682,263,263, -41,42,43,38,604,44,44,46,44,45,44,44, -41,42,43,38,605,43,43,46,43,45,44,44, -160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, - 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, - 160,160,160,160,161,160,606, -41,42,43,38,607,42,42,46,42,45,44,44, -41,42,43,38,608,41,41,46,41,45,44,44, -135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, - 19,19,19,609,1,886, -683,683,683,683,1,610,1,683, -684,684,684,684,1,611,1,684, -685,685,685,685,1,612,1,685, -686,686,686,686,1,613,1,686, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,614,1,880, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,615,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,687,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,616,1,879, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,617,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,688,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -41,42,43,38,618,22,22,46,22,45,44,44, -19,19,19,19,19,619,1,943, -689,689,689,689,1,620,1,689, -19,19,19,19,19,19,19,621,1,992, -19,19,19,19,19,19,19,622,1,991, -19,19,19,19,19,19,19,623,1,990, -19,19,19,19,19,19,19,19,624,1,1043, -19,19,19,19,19,19,19,625,1,1057, -690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690, - 690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690, - 690,690,690,690,690,1,626,1,690, -691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, - 691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, - 691,691,691,691,691,1,627,1,691, -692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692, - 692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692, - 692,692,692,692,692,1,628,1,692, -19,19,19,19,19,19,629,1,989, -19,19,19,19,19,19,630,1,988, -693,1,631,1,693, -266,543,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, - 266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, - 266,266,266,272,266,632,694, -266,543,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, - 266,266,136,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, - 266,266,266,266,272,266,633,138, -19,19,19,19,19,19,19,634,1,934, -695,385,635,61,696, -255,255,255,255,255,255,255,255,255,636, -252,242,257,545,546,257,251,251,251,251,251,253,237,237,237,237,246,246,237, - 637,246, -115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133, - 134,135,136,137,138,66,67,68,69,70,71,139,140,141,142,143,144,72,73,74, - 75,76,145,146,147,77,78,79,80,81,148,149,150,151,152,153,154,155,156, - 157,158,159,160,161,162,111,63,64,65,169,170,171,172,173,174,175,176, - 177,178,179,180,181,182,183,184,163,164,165,166,167,168,82,83,84,85,86, - 87,49,50,51,88,89,90,91,92,93,94,95,96,52,53,97,98,99,100,101,102,103, - 104,54,55,56,105,106,57,58,107,108,109,110,59,60,61,62,638,697,698,200, - 698,698,698,698,698,698,698,698,698,698,327,327,327,327,327,328,329,330, - 331,334,334,334,335,336,340,340,340,340,341,342,343,344,345,346,347,348, - 351,351,351,352,353,354,355,356,357,358,359,360,364,364,364,364,365,366, - 367,368,369,370,246,245,244,243,242,241,262,261,260,259,258,257,256,255, - 254,253,252,251,250,249,248,247,188,114,187,113,186,112,185,240,239,238, - 237,236,235,234,233,232,231,230,229,228,227,226,225,225,225,225,225,225, - 224,223,222,221,221,221,221,221,221,220,219,218,217,216,215,214,214,214, - 214,213,213,213,213,212,211,210,209,208,207,206,205,204,203,202,201,199, - 198,197,196,195,194,193,192,191,190,189, -266,543,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, - 266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, - 266,266,266,272,266,639,699, -382,640,700, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,632, - 284,140,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286, - 295,307,281,265,130,129,641,234,292,293,235,288,119,273,236,289,633,120, - 265,332,331,329,334,330,333,328,121,220,323,701,309,263,324,328,327,326, - 325,219,328,318,317,316,315,314,313,312,311,310,308,291,290,274,263,634, - 306,305, -695,93,93,93,93,93,642,702, -695,92,92,92,92,92,643,702, -695,91,91,91,91,91,644,702, -695,90,90,90,90,90,645,696, -695,87,87,87,87,87,646,696, -356,358,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377, - 378,379,386,389,390,391,320,322,388,380,384,381,383,387,359,357,703,307, - 385,382,39,42,705,704,647,64,1,705,64,64,64,64,65,64,64,64,64,64,64,64, - 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, - 64,64,64,64, -706,706,706,706,706,706,706,706,706,648, -707,707,707,707,707,649, -148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,707,707,707, - 707,707,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, - 148,148,148,148,148,650, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,651,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,708,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -264,652, -709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,1,653,1,709, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,654,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,710,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,655,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,711,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,656,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,712,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,657,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,713,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,658,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,714,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,659,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,715,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,660,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,716,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,661,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,717,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,662,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,718,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,663,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,719,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -720,1,664,1,720, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, - 130,129,665,234,292,293,235,288,236,289,265,220,323,309,263,213,219,213, - 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, - 130,129,666,234,292,293,235,288,236,289,265,220,323,309,263,212,219,212, - 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, - 130,129,667,234,292,293,235,288,236,289,265,220,323,309,263,211,219,211, - 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, - 130,129,668,234,292,293,235,288,236,289,265,220,323,309,263,210,219,210, - 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,283,559,286,295,307,281,265, - 130,129,669,234,292,293,235,288,236,289,265,220,323,309,263,209,219,209, - 318,317,316,315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,670,234,292,293,235,288,236,289,265,721,328,220,323, - 309,263,324,328,327,326,325,219,328,318,317,316,315,314,313,312,311,310, - 308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,671,234,292,293,235,288,236,289,265,722,328,220,323, - 309,263,324,328,327,326,325,219,328,318,317,316,315,314,313,312,311,310, - 308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,672,234,292,293,235,288,236,289,265,329,723,328,220, - 323,309,263,324,328,327,326,325,219,328,318,317,316,315,314,313,312,311, - 310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,673,234,292,293,235,288,236,289,265,329,724,328,220, - 323,309,263,324,328,327,326,325,219,328,318,317,316,315,314,313,312,311, - 310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,674,234,292,293,235,288,236,289,265,329,725,328,220, - 323,309,263,324,328,327,326,325,219,328,318,317,316,315,314,313,312,311, - 310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,675,234,292,293,235,288,236,289,265,329,726,328,220, - 323,309,263,324,328,327,326,325,219,328,318,317,316,315,314,313,312,311, - 310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,676,234,292,293,235,288,236,289,265,727,329,330,328, - 220,323,309,263,324,328,327,326,325,219,328,318,317,316,315,314,313,312, - 311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,677,234,292,293,235,288,236,289,265,728,329,330,328, - 220,323,309,263,324,328,327,326,325,219,328,318,317,316,315,314,313,312, - 311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,678,234,292,293,235,288,236,289,265,729,331,329,330, - 328,220,323,309,263,324,328,327,326,325,219,328,318,317,316,315,314,313, - 312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,679,234,292,293,235,288,236,289,265,730,331,329,330, - 328,220,323,309,263,324,328,327,326,325,219,328,318,317,316,315,314,313, - 312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,680,234,292,293,235,288,236,289,265,332,331,329,330, - 731,328,220,323,309,263,324,328,327,326,325,219,328,318,317,316,315,314, - 313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,681,234,292,293,235,288,236,289,265,332,331,329,330, - 732,328,220,323,309,263,324,328,327,326,325,219,328,318,317,316,315,314, - 313,312,311,310,308,291,290,263,306,305, -733,733,733,733,1,682,1,733, -41,42,43,38,683,35,35,46,35,45,44,44, -41,42,43,38,684,34,34,46,34,45,44,44, -41,42,43,38,685,33,33,46,33,45,44,44, -41,42,43,38,686,30,30,46,30,45,44,44, -734,734,734,734,1,687,1,734, -735,735,735,735,1,688,1,735, -41,42,43,38,689,69,69,46,69,45,44,44, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,690,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,398,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,691,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,396,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,692,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,394,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -695,693,736, -266,543,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, - 266,266,263,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, - 266,266,266,266,272,266,694,737, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,695,1,942, -738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738, - 738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738, - 738,738,738,738,738,738,1,696,1,738, -484,697,485, -19,322,322,322,322,1,698,1,311, -266,543,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, - 266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266, - 266,266,266,272,266,699,137, -739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, - 739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, - 739,739,739,739,739,1,700,1,739, -695,99,99,99,99,99,701,696, -740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,1,702,1,740, -19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,703,1,909, -64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, - 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,17,17,17,17,17,704, -41,42,43,38,705,60,60,46,60,45,44,44, -156,156,156,156,156,156,156,156,155,155,155,155,156,156,156,156,155,155,155, - 155,155,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, - 156,156,156,156,156,706, -152,152,152,152,152,707, -741,741,741,741,1,708,1,741, -131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,709,744,742,742, - 743, -385,710,232, -385,711,231, -385,712,230, -385,713,229, -385,714,228, -385,715,227, -385,716,226, -385,717,225, -385,718,224, -385,719,223, -385,720,222, -207,560,562,388,380,384,207,207,207,207,207,207,207,207,207,207,207,207,207, - 207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,721, - 566,565,564,563,561, -206,560,562,388,380,384,206,206,206,206,206,206,206,206,206,206,206,206,206, - 206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,722, - 566,565,564,563,561, -204,381,383,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, - 204,204,204,204,204,204,204,204,204,204,204,204,204,204,723,568,567, -203,381,383,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, - 203,203,203,203,203,203,203,203,203,203,203,203,203,203,724,568,567, -202,381,383,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, - 202,202,202,202,202,202,202,202,202,202,202,202,202,202,725,568,567, -201,381,383,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, - 201,201,201,201,201,201,201,201,201,201,201,201,201,201,726,568,567, -199,569,571,573,575,199,199,199,199,199,199,199,199,199,199,199,199,199,199, - 199,199,199,199,199,199,199,199,199,199,199,199,727,576,574,572,570, -198,569,571,573,575,198,198,198,198,198,198,198,198,198,198,198,198,198,198, - 198,198,198,198,198,198,198,198,198,198,198,198,728,576,574,572,570, -196,577,387,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, - 196,196,196,196,196,196,196,196,729,579,578, -195,577,387,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195, - 195,195,195,195,195,195,195,195,730,579,578, -193,580,359,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, - 193,193,193,193,193,193,731,582,581, -192,580,359,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, - 192,192,192,192,192,192,732,582,581, -41,42,43,38,733,45,45,46,45,45,44,44, -41,42,43,38,734,29,29,46,29,45,44,44, -41,42,43,38,735,28,28,46,28,45,44,44, -745,745,745,745,745,745,745,745,745,1,736,1,745, -137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, - 137,137,264,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, - 137,137,137,137,137,137,737, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,632, - 284,140,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286, - 295,307,281,265,130,129,738,234,292,293,235,288,123,273,236,289,633,124, - 265,332,331,329,334,330,333,328,122,220,323,309,263,324,328,327,326,325, - 219,328,318,317,316,315,314,313,312,311,310,308,291,290,274,263,634,306, - 305, -131,131,131,131,131,131,131,131,131,131,131,282,131,250,250,250,250,285,287, - 284,294,296,297,298,299,300,301,302,303,304,320,321,322,283,319,286,295, - 307,281,265,130,129,739,234,292,293,235,288,236,289,265,332,331,329,334, - 330,333,328,101,220,323,309,263,324,328,327,326,325,219,328,318,317,316, - 315,314,313,312,311,310,308,291,290,263,306,305, -131,131,131,131,131,131,131,131,131,131,131,131,131,130,129,740,126,263,263, -41,42,43,38,741,58,58,46,58,45,44,44, -132,132,132,132,132,132,132,132,132,132,132,132,133,133,133,133,133,132,19, - 132,1,742,1,127,133, -19,19,743,1,985, -746,1,744,1,746, -287,286,286,283,282,281,280,279,278,745,383,286,624, -385,746,233, + 681,681,681,681,681,1,576,1,681, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,577,1,969, +682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682, + 682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682, + 682,682,682,682,682,1,578,1,682, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,579,1,968, +683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683, + 683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683, + 683,683,683,683,683,1,580,1,683, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,581,1,967, +684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684, + 684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684, + 684,684,684,684,684,1,582,1,684, +685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685, + 685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685, + 685,685,685,685,685,1,583,1,685, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,584,1,965, +686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686, + 686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686, + 686,686,686,686,686,1,585,1,686, +687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687, + 687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687, + 687,687,687,687,687,1,586,1,687, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,587,1,963, +688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688, + 688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688, + 688,688,688,688,688,1,588,1,688, +689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689, + 689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689, + 689,689,689,689,689,1,589,1,689, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,590,1,961, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,591,1,960, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,592,1,959, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,593,1,958, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,594,1,957, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,595,1,956, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,596,1,955, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,597,1,954, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,598,1,953, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,599,1,952, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,600,1,951, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,601,1,950, +43,44,45,40,54,602,54,54,48,54,47,46,46, +43,44,45,40,53,603,53,53,48,53,47,46,46, +43,44,45,40,52,604,52,52,48,52,47,46,46, +43,44,45,40,49,605,49,49,48,49,47,46,46, +43,44,45,40,48,606,48,48,48,48,47,46,46, +137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,607,690,265,265, +43,44,45,40,46,608,46,46,48,46,47,46,46, +43,44,45,40,45,609,45,45,48,45,47,46,46, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, + 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, + 166,166,166,166,167,166,610, +43,44,45,40,44,611,44,44,48,44,47,46,46, +43,44,45,40,43,612,43,43,48,43,47,46,46, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, + 20,20,20,20,613,1,892, +691,691,691,691,691,1,614,1,691, +692,692,692,692,692,1,615,1,692, +693,693,693,693,693,1,616,1,693, +694,694,694,694,694,1,617,1,694, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,618,1,886, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,619,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,695,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,620,1,885, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,621,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,696,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +43,44,45,40,23,622,23,23,48,23,47,46,46, +20,20,20,20,20,20,623,1,949, +697,697,697,697,697,1,624,1,697, +20,20,20,20,20,20,20,20,625,1,998, +20,20,20,20,20,20,20,20,626,1,997, +20,20,20,20,20,20,20,20,627,1,996, +20,20,20,20,20,20,20,20,20,628,1,1049, +20,20,20,20,20,20,20,20,629,1,1063, +698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698, + 698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698, + 698,698,698,698,698,1,630,1,698, +699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699, + 699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699, + 699,699,699,699,699,1,631,1,699, +700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700, + 700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700, + 700,700,700,700,700,1,632,1,700, +20,20,20,20,20,20,20,633,1,995, +20,20,20,20,20,20,20,634,1,994, +701,1,635,1,701, +272,547,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, + 272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, + 272,272,272,278,272,636,702, +272,547,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, + 272,272,142,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, + 272,272,272,272,278,272,637,144, +20,20,20,20,20,20,20,20,638,1,940, +703,388,639,65,704, +261,261,261,261,261,261,261,261,261,640, +258,248,263,549,550,263,257,257,257,257,257,259,243,243,243,243,252,252,243, + 243,641,252, +117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135, + 136,137,138,139,140,68,69,70,71,72,73,141,142,143,144,145,146,74,75,76, + 77,78,147,148,149,79,80,81,82,83,150,151,152,153,154,155,156,157,158, + 159,160,161,162,163,164,113,65,66,67,171,172,173,174,175,176,177,178, + 179,180,181,182,183,184,185,186,165,166,167,168,169,170,84,85,86,87,88, + 89,51,52,53,90,91,92,93,94,95,96,97,98,54,55,99,100,101,102,103,104,105, + 106,56,57,58,107,108,59,60,109,110,111,112,61,62,63,64,642,705,706,202, + 706,706,706,706,706,706,706,706,706,706,333,333,333,333,333,334,335,336, + 337,340,340,340,341,342,346,346,346,346,347,348,349,350,351,352,353,354, + 357,357,357,358,359,360,361,362,363,364,365,366,370,370,370,370,371,372, + 373,374,375,376,248,247,246,245,244,243,264,263,262,261,260,259,258,257, + 256,255,254,253,252,251,250,249,190,116,189,115,188,114,187,242,241,240, + 239,238,237,236,235,234,233,232,231,230,229,228,227,227,227,227,227,227, + 226,225,224,223,223,223,223,223,223,222,221,220,219,218,217,216,216,216, + 216,215,215,215,215,214,213,212,211,210,209,208,207,206,205,204,203,201, + 200,199,198,197,196,195,194,193,192,191, +272,547,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, + 272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, + 272,272,272,278,272,643,707, +385,644,708, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,636, + 287,146,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289, + 298,310,284,271,136,135,645,240,295,296,241,291,125,278,242,292,637,126, + 267,335,334,332,337,333,336,331,127,226,326,709,312,265,327,331,330,329, + 328,225,331,321,320,319,318,317,316,315,314,313,311,294,293,279,265,638, + 309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,146,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289, + 298,310,284,271,136,135,646,240,295,296,241,291,104,278,242,292,267,335, + 334,332,337,333,336,331,105,226,326,312,265,327,331,330,329,328,225,331, + 321,320,319,318,317,316,315,314,313,311,294,293,279,265,309,308, +703,97,97,97,97,97,97,647,710, +703,96,96,96,96,96,96,648,710, +703,95,95,95,95,95,95,649,710, +703,94,94,94,94,94,94,650,704, +703,91,91,91,91,91,91,651,704, +359,361,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380, + 381,382,389,392,393,394,323,325,391,383,387,384,386,390,362,360,711,310, + 388,385,41,44,713,713,712,652,68,1,713,68,68,68,68,69,68,68,68,68,68,68, + 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68, + 68,68,68,68,68, +714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714, + 714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714, + 714,714,714,714,714,1,653,1,714, +43,44,45,40,61,654,61,61,48,61,47,46,46, +43,44,45,40,60,655,60,60,48,60,47,46,46, +43,44,45,40,59,656,59,59,48,59,47,46,46, +715,715,715,715,715,715,715,715,715,657, +716,716,716,716,716,658, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,716,716,716, + 716,716,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, + 154,154,154,154,154,659, +270,660, +717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,1,661,1,717, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,662,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,718,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,663,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,719,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,664,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,720,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,665,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,721,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,666,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,722,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,667,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,723,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,668,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,724,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,669,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,725,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,670,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,726,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,671,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,727,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +728,1,672,1,728, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, + 136,135,673,240,295,296,241,291,242,292,267,226,326,312,265,219,225,219, + 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, + 136,135,674,240,295,296,241,291,242,292,267,226,326,312,265,218,225,218, + 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, + 136,135,675,240,295,296,241,291,242,292,267,226,326,312,265,217,225,217, + 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, + 136,135,676,240,295,296,241,291,242,292,267,226,326,312,265,216,225,216, + 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, + 136,135,677,240,295,296,241,291,242,292,267,226,326,312,265,215,225,215, + 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,678,240,295,296,241,291,242,292,267,729,331,226,326, + 312,265,327,331,330,329,328,225,331,321,320,319,318,317,316,315,314,313, + 311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,679,240,295,296,241,291,242,292,267,730,331,226,326, + 312,265,327,331,330,329,328,225,331,321,320,319,318,317,316,315,314,313, + 311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,680,240,295,296,241,291,242,292,267,332,731,331,226, + 326,312,265,327,331,330,329,328,225,331,321,320,319,318,317,316,315,314, + 313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,681,240,295,296,241,291,242,292,267,332,732,331,226, + 326,312,265,327,331,330,329,328,225,331,321,320,319,318,317,316,315,314, + 313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,682,240,295,296,241,291,242,292,267,332,733,331,226, + 326,312,265,327,331,330,329,328,225,331,321,320,319,318,317,316,315,314, + 313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,683,240,295,296,241,291,242,292,267,332,734,331,226, + 326,312,265,327,331,330,329,328,225,331,321,320,319,318,317,316,315,314, + 313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,684,240,295,296,241,291,242,292,267,735,332,333,331, + 226,326,312,265,327,331,330,329,328,225,331,321,320,319,318,317,316,315, + 314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,685,240,295,296,241,291,242,292,267,736,332,333,331, + 226,326,312,265,327,331,330,329,328,225,331,321,320,319,318,317,316,315, + 314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,686,240,295,296,241,291,242,292,267,737,334,332,333, + 331,226,326,312,265,327,331,330,329,328,225,331,321,320,319,318,317,316, + 315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,687,240,295,296,241,291,242,292,267,738,334,332,333, + 331,226,326,312,265,327,331,330,329,328,225,331,321,320,319,318,317,316, + 315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,688,240,295,296,241,291,242,292,267,335,334,332,333, + 739,331,226,326,312,265,327,331,330,329,328,225,331,321,320,319,318,317, + 316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,689,240,295,296,241,291,242,292,267,335,334,332,333, + 740,331,226,326,312,265,327,331,330,329,328,225,331,321,320,319,318,317, + 316,315,314,313,311,294,293,265,309,308, +741,741,741,741,741,1,690,1,741, +43,44,45,40,36,691,36,36,48,36,47,46,46, +43,44,45,40,35,692,35,35,48,35,47,46,46, +43,44,45,40,34,693,34,34,48,34,47,46,46, +43,44,45,40,31,694,31,31,48,31,47,46,46, +742,742,742,742,742,1,695,1,742, +743,743,743,743,743,1,696,1,743, +43,44,45,40,73,697,73,73,48,73,47,46,46, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,698,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,404,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,699,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,402,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,700,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,400,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +703,701,744, +272,547,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, + 272,272,269,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, + 272,272,272,272,278,272,702,745, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,703,1,948, +746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746, + 746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746, + 746,746,746,746,746,746,1,704,1,746, +487,705,488, +20,328,328,328,328,328,1,706,1,317, +272,547,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, + 272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, + 272,272,272,278,272,707,143, +747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747, + 747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747, + 747,747,747,747,747,1,708,1,747, +703,103,103,103,103,103,103,709,704, +748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,1,710,1,748, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,711,1, + 916, +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68, + 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,18,18,18,18,18,18,712, +43,44,45,40,64,713,64,64,48,64,47,46,46, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,714,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,749,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +162,162,162,162,162,162,162,162,161,161,161,161,162,162,162,162,161,161,161, + 161,161,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, + 162,162,162,162,162,715, +158,158,158,158,158,716, +137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,717,752,750,750, + 751, +388,718,238, +388,719,237, +388,720,236, +388,721,235, +388,722,234, +388,723,233, +388,724,232, +388,725,231, +388,726,230, +388,727,229, +388,728,228, +213,564,566,391,383,387,213,213,213,213,213,213,213,213,213,213,213,213,213, + 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, + 729,570,569,568,567,565, +212,564,566,391,383,387,212,212,212,212,212,212,212,212,212,212,212,212,212, + 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, + 730,570,569,568,567,565, +210,384,386,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, + 210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,731,572,571, +209,384,386,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, + 209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,732,572,571, +208,384,386,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, + 208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,733,572,571, +207,384,386,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, + 207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,734,572,571, +205,573,575,577,579,205,205,205,205,205,205,205,205,205,205,205,205,205,205, + 205,205,205,205,205,205,205,205,205,205,205,205,205,735,580,578,576,574, +204,573,575,577,579,204,204,204,204,204,204,204,204,204,204,204,204,204,204, + 204,204,204,204,204,204,204,204,204,204,204,204,204,736,580,578,576,574, +202,581,390,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, + 202,202,202,202,202,202,202,202,202,737,583,582, +201,581,390,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, + 201,201,201,201,201,201,201,201,201,738,583,582, +199,584,362,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, + 199,199,199,199,199,199,199,739,586,585, +198,584,362,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, + 198,198,198,198,198,198,198,740,586,585, +43,44,45,40,47,741,47,47,48,47,47,46,46, +43,44,45,40,30,742,30,30,48,30,47,46,46, +43,44,45,40,29,743,29,29,48,29,47,46,46, +753,753,753,753,753,753,753,753,753,1,744,1,753, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, + 143,143,270,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, + 143,143,143,143,143,143,745, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,636, + 287,146,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289, + 298,310,284,271,136,135,746,240,295,296,241,291,129,278,242,292,637,130, + 267,335,334,332,337,333,336,331,128,226,326,312,265,327,331,330,329,328, + 225,331,321,320,319,318,317,316,315,314,313,311,294,293,279,265,638,309, + 308, +137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, + 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, + 310,284,271,136,135,747,240,295,296,241,291,242,292,267,335,334,332,337, + 333,336,331,107,226,326,312,265,327,331,330,329,328,225,331,321,320,319, + 318,317,316,315,314,313,311,294,293,265,309,308, +137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,748,132,265,265, +754,754,754,754,754,1,749,1,754, +138,138,138,138,138,138,138,138,138,138,138,138,139,139,139,139,139,138,20, + 138,1,750,1,133,139, +20,20,751,1,991, +755,1,752,1,755, +293,292,292,289,288,287,286,285,284,753,389,292,628, +43,44,45,40,62,754,62,62,48,62,47,46,46, +388,755,239, }; static const unsigned short ag_sbt[] = { - 0, 30, 32, 72, 89, 119, 147, 347, 350, 367, 567, 934, 973, 992, - 1011,1016,1021,1026,1034,1042,1061,1107,1153,1172,1181,1206,1226,1245, - 1250,1255,1260,1268,1276,1295,1382,1469,1488,1499,1508,1566,1657,1663, - 1711,1761,1807,1899,1986,2073,2448,2458,2467,2476,2485,2494,2503,2512, - 2521,2530,2539,2548,2557,2566,2575,2584,2597,2610,2621,2667,2713,2759, - 2805,2851,2897,2943,2989,3035,3081,3127,3173,3219,3265,3311,3357,3366, - 3375,3384,3393,3402,3411,3420,3429,3438,3447,3456,3465,3474,3483,3492, - 3501,3510,3519,3528,3537,3546,3555,3564,3573,3582,3591,3600,3609,3618, - 3626,3639,3652,3663,3709,3755,3801,3847,3893,3939,3985,4031,4077,4123, - 4169,4215,4261,4307,4353,4399,4445,4491,4537,4583,4629,4675,4721,4767, - 4813,4859,4905,4951,4997,5043,5089,5135,5181,5227,5273,5319,5365,5411, - 5457,5503,5549,5595,5641,5687,5733,5779,5825,5871,5883,5895,5907,5919, - 5927,5935,5946,5957,5968,5981,5994,6007,6020,6033,6046,6059,6072,6085, - 6098,6111,6124,6137,6145,6150,6155,6160,6206,6252,6298,6344,6390,6436, - 6482,6528,6574,6620,6666,6712,6758,6804,6850,6896,6942,6988,7034,7080, - 7126,7172,7218,7264,7310,7356,7402,7448,7494,7540,7586,7632,7678,7724, - 7770,7816,7862,7908,7954,8000,8046,8092,8138,8184,8230,8276,8322,8368, - 8414,8460,8506,8552,8564,8576,8588,8600,8608,8616,8627,8638,8649,8662, - 8675,8688,8701,8714,8727,8740,8753,8766,8779,8792,8805,8818,8878,8887, - 8957,8964,8967,9054,9133,9141,9185,9193,9237,9248,9251,9259,9267,9279, - 9291,9299,9305,9310,9313,9372,9427,9433,9477,9483,9494,9537,9578,9626, - 9679,9684,9693,9698,9703,9708,9713,9718,9723,9728,9733,9738,9779,9820, - 9885,9890,9895,9900,9905,9910,9915,9920,9925,9930,9935,9940,9983,10047, - 10090,10154,10200,10270,10340,10410,10480,10521,10565,10603,10641,10673, - 10703,10708,10746,10831,10839,10847,10854,10862,10870,10878,10886,10905, - 10924,10932,10940,10948,10956,10998,11006,11014,11022,11047,11077,11127, - 11192,11242,11307,11355,11405,11455,11505,11555,11605,11655,11705,11755, - 11805,11855,11905,11955,12005,12055,12105,12155,12205,12255,12305,12369, - 12434,12499,12564,12628,12702,12752,12817,12881,12931,12981,13031,13089, - 13173,13176,13179,13225,13310,13393,13401,13418,13435,13448,13461,13467, - 13470,13473,13476,13561,13646,13731,13816,13901,13986,14071,14156,14241, - 14326,14411,14496,14581,14666,14751,14836,14921,15006,15091,15176,15261, - 15346,15431,15516,15601,15686,15771,15856,15941,16026,16111,16196,16281, - 16366,16451,16536,16621,16706,16791,16876,16961,17046,17131,17216,17301, - 17386,17471,17556,17641,17726,17811,17896,17911,17926,17941,17956,17964, - 17972,17985,17998,18011,18028,18045,18058,18071,18084,18097,18110,18123, - 18136,18149,18162,18175,18188,18281,18303,18440,18577,18596,18615,18638, - 18660,18668,18676,18682,18691,18699,18707,18730,18754,18759,18764,18811, - 18858,18905,18994,19040,19125,19144,19163,19182,19201,19220,19240,19259, - 19279,19298,19318,19365,19412,19505,19552,19599,19646,19739,19785,19831, - 19916,19924,19970,20016,20062,20147,20166,20176,20186,20198,20280,20292, - 20307,20353,20365,20377,20389,20399,20406,20451,20500,20549,20552,20555, - 20558,20561,20564,20567,20570,20573,20576,20579,20582,20667,20673,20716, - 20759,20802,20845,20888,20931,20974,21020,21066,21112,21158,21204,21250, - 21296,21342,21388,21434,21480,21526,21572,21618,21664,21710,21756,21802, - 21848,21894,21940,21986,22032,22078,22124,22170,22216,22262,22308,22354, - 22400,22412,22424,22436,22448,22460,22479,22491,22503,22547,22559,22571, - 22596,22604,22612,22620,22628,22674,22759,22805,22890,22902,22910,22918, - 22928,22938,22948,22959,22969,23015,23061,23107,23116,23125,23130,23174, - 23219,23229,23234,23244,23265,23556,23600,23603,23696,23704,23712,23720, - 23728,23736,23823,23833,23839,23882,23967,23969,23988,24073,24158,24243, - 24328,24413,24498,24583,24668,24753,24838,24843,24913,24983,25053,25123, - 25193,25272,25351,25431,25511,25591,25671,25752,25833,25915,25997,26080, - 26163,26171,26183,26195,26207,26219,26227,26235,26247,26332,26417,26502, - 26505,26550,26606,26653,26656,26665,26709,26755,26763,26782,26830,26876, - 26888,26931,26937,26945,26965,26968,26971,26974,26977,26980,26983,26986, - 26989,26992,26995,26998,27040,27082,27118,27154,27190,27226,27262,27298, - 27328,27358,27386,27414,27426,27438,27450,27463,27507,27599,27684,27703, - 27715,27740,27745,27750,27763,27766 + 0, 31, 33, 74, 92, 123, 153, 354, 357, 375, 576, 945, 984,1003, + 1022,1027,1032,1079,1084,1093,1102,1121,1167,1213,1232,1241,1266,1286, + 1305,1310,1315,1362,1367,1376,1385,1404,1491,1578,1597,1608,1617,1675, + 1767,1773,1821,1872,1918,2010,2097,2184,2560,2571,2581,2591,2601,2611, + 2621,2631,2641,2651,2661,2671,2681,2691,2701,2711,2724,2737,2748,2794, + 2840,2886,2932,2978,3024,3070,3116,3162,3208,3254,3300,3346,3392,3438, + 3484,3494,3504,3514,3524,3534,3544,3554,3564,3574,3584,3594,3604,3614, + 3624,3634,3644,3654,3664,3674,3684,3694,3704,3714,3724,3734,3744,3754, + 3764,3774,3782,3795,3808,3819,3865,3911,3957,4003,4049,4095,4141,4187, + 4233,4279,4325,4371,4417,4463,4509,4555,4601,4647,4693,4739,4785,4831, + 4877,4923,4969,5015,5061,5107,5153,5199,5245,5291,5337,5383,5429,5475, + 5521,5567,5613,5659,5705,5751,5797,5843,5889,5935,5981,6027,6039,6051, + 6063,6075,6083,6091,6102,6113,6124,6137,6150,6163,6176,6189,6202,6215, + 6228,6241,6254,6267,6280,6293,6301,6306,6311,6316,6362,6408,6454,6500, + 6546,6592,6638,6684,6730,6776,6822,6868,6914,6960,7006,7052,7098,7144, + 7190,7236,7282,7328,7374,7420,7466,7512,7558,7604,7650,7696,7742,7788, + 7834,7880,7926,7972,8018,8064,8110,8156,8202,8248,8294,8340,8386,8432, + 8478,8524,8570,8616,8662,8708,8720,8732,8744,8756,8764,8772,8783,8794, + 8805,8818,8831,8844,8857,8870,8883,8896,8909,8922,8935,8948,8961,8974, + 9035,9045,9116,9124,9127,9214,9293,9302,9346,9355,9360,9365,9454,9498, + 9510,9519,9532,9545,9554,9560,9565,9568,9628,9684,9690,9734,9740,9751, + 9795,9837,9886,9940,9945,9955,9960,9965,9970,9975,9980,9985,9990,9995, + 10000,10042,10084,10150,10155,10160,10165,10170,10175,10180,10185,10190, + 10195,10200,10205,10248,10313,10356,10421,10467,10537,10607,10677,10747, + 10789,10834,10873,10912,10945,10976,10981,11020,11105,11114,11123,11131, + 11140,11149,11158,11167,11186,11205,11214,11223,11232,11241,11283,11292, + 11301,11310,11335,11365,11416,11482,11533,11599,11647,11698,11749,11800, + 11851,11902,11953,12004,12055,12106,12157,12208,12259,12310,12361,12412, + 12463,12514,12565,12616,12681,12747,12813,12879,12944,13019,13070,13136, + 13201,13252,13303,13354,13412,13496,13499,13502,13548,13633,13716,13725, + 13743,13760,13773,13786,13792,13795,13798,13801,13886,13971,14056,14141, + 14226,14311,14396,14481,14566,14651,14736,14821,14906,14991,15076,15161, + 15246,15331,15416,15501,15586,15671,15756,15841,15926,16011,16096,16181, + 16266,16351,16436,16521,16606,16691,16776,16861,16946,17031,17116,17201, + 17286,17371,17456,17541,17626,17711,17796,17881,17966,18051,18136,18221, + 18236,18251,18266,18281,18289,18297,18310,18323,18336,18353,18370,18383, + 18396,18409,18422,18435,18448,18461,18474,18487,18500,18513,18606,18628, + 18765,18902,18921,18940,18963,18985,18994,19003,19009,19018,19027,19036, + 19060,19085,19090,19095,19142,19189,19281,19327,19412,19431,19450,19469, + 19488,19507,19527,19546,19566,19585,19605,19652,19699,19792,19839,19886, + 19933,20026,20072,20118,20203,20212,20258,20304,20350,20435,20454,20465, + 20476,20489,20571,20584,20587,20596,20605,20614,20629,20642,20655,20665, + 20672,20717,20767,20817,20820,20823,20826,20829,20832,20835,20838,20841, + 20844,20847,20850,20935,20941,20984,21027,21070,21113,21156,21199,21242, + 21288,21334,21380,21426,21472,21518,21564,21610,21656,21702,21748,21794, + 21840,21886,21932,21978,22024,22070,22116,22162,22208,22254,22300,22346, + 22392,22438,22484,22530,22576,22622,22668,22681,22694,22707,22720,22733, + 22752,22765,22778,22822,22835,22848,22874,22883,22892,22901,22910,22956, + 23041,23087,23172,23185,23194,23203,23214,23225,23236,23248,23259,23305, + 23351,23397,23407,23417,23422,23466,23511,23522,23527,23537,23559,23850, + 23894,23897,23990,24079,24088,24097,24106,24115,24124,24212,24258,24271, + 24284,24297,24307,24313,24356,24358,24377,24462,24547,24632,24717,24802, + 24887,24972,25057,25142,25227,25232,25302,25372,25442,25512,25582,25661, + 25740,25820,25900,25980,26060,26141,26222,26304,26386,26469,26552,26561, + 26574,26587,26600,26613,26622,26631,26644,26729,26814,26899,26902,26947, + 27003,27050,27053,27063,27107,27153,27162,27181,27230,27277,27290,27375, + 27418,27424,27444,27447,27450,27453,27456,27459,27462,27465,27468,27471, + 27474,27477,27520,27563,27600,27637,27674,27711,27748,27785,27816,27847, + 27876,27905,27918,27931,27944,27957,28001,28093,28178,28197,28206,28231, + 28236,28241,28254,28267,28270 }; static const unsigned short ag_sbe[] = { - 27, 31, 58, 86, 117, 132, 344, 348, 357, 564, 763, 961, 989,1008, - 1013,1018,1023,1031,1039,1058,1104,1150,1169,1178,1203,1221,1241,1246, - 1251,1256,1265,1273,1291,1337,1424,1484,1493,1501,1563,1654,1659,1708, - 1758,1804,1852,1942,2029,2269,2455,2464,2473,2482,2491,2500,2509,2518, - 2527,2536,2545,2554,2563,2572,2581,2594,2607,2618,2664,2710,2756,2802, - 2848,2894,2940,2986,3032,3078,3124,3170,3216,3262,3308,3354,3363,3372, - 3381,3390,3399,3408,3417,3426,3435,3444,3453,3462,3471,3480,3489,3498, - 3507,3516,3525,3534,3543,3552,3561,3570,3579,3588,3597,3606,3615,3623, - 3636,3649,3660,3706,3752,3798,3844,3890,3936,3982,4028,4074,4120,4166, - 4212,4258,4304,4350,4396,4442,4488,4534,4580,4626,4672,4718,4764,4810, - 4856,4902,4948,4994,5040,5086,5132,5178,5224,5270,5316,5362,5408,5454, - 5500,5546,5592,5638,5684,5730,5776,5822,5868,5880,5892,5904,5916,5924, - 5932,5943,5954,5965,5978,5991,6004,6017,6030,6043,6056,6069,6082,6095, - 6108,6121,6134,6142,6147,6152,6157,6203,6249,6295,6341,6387,6433,6479, - 6525,6571,6617,6663,6709,6755,6801,6847,6893,6939,6985,7031,7077,7123, - 7169,7215,7261,7307,7353,7399,7445,7491,7537,7583,7629,7675,7721,7767, - 7813,7859,7905,7951,7997,8043,8089,8135,8181,8227,8273,8319,8365,8411, - 8457,8503,8549,8561,8573,8585,8597,8605,8613,8624,8635,8646,8659,8672, - 8685,8698,8711,8724,8737,8750,8763,8776,8789,8802,8815,8874,8884,8955, - 8962,8965,9009,9091,9138,9182,9190,9235,9245,9249,9256,9264,9271,9283, - 9296,9304,9309,9312,9371,9426,9432,9475,9482,9493,9536,9577,9625,9677, - 9681,9690,9695,9700,9705,9710,9715,9720,9725,9730,9735,9776,9817,9882, - 9887,9892,9897,9902,9907,9912,9917,9922,9927,9932,9937,9980,10044,10087, - 10151,10197,10239,10309,10379,10449,10518,10557,10598,10634,10668,10698, - 10705,10726,10788,10836,10844,10852,10859,10867,10875,10883,10902,10921, - 10929,10937,10945,10953,10997,11003,11011,11019,11044,11068,11124,11189, - 11239,11304,11352,11402,11452,11502,11552,11602,11652,11702,11752,11802, - 11852,11902,11952,12002,12052,12102,12152,12202,12252,12302,12366,12431, - 12496,12561,12625,12699,12749,12814,12878,12928,12978,13028,13086,13131, - 13174,13177,13222,13267,13349,13398,13407,13427,13444,13455,13465,13468, - 13471,13474,13518,13603,13688,13773,13858,13943,14028,14113,14198,14283, - 14368,14453,14538,14623,14708,14793,14878,14963,15048,15133,15218,15303, - 15388,15473,15558,15643,15728,15813,15898,15983,16068,16153,16238,16323, - 16408,16493,16578,16663,16748,16833,16918,17003,17088,17173,17258,17343, - 17428,17513,17598,17683,17768,17853,17904,17919,17934,17949,17960,17968, - 17979,17992,18005,18020,18037,18054,18067,18080,18093,18106,18119,18132, - 18145,18158,18171,18184,18231,18294,18437,18574,18593,18611,18635,18657, - 18665,18673,18679,18684,18696,18704,18727,18750,18755,18760,18808,18855, - 18902,18948,19037,19082,19141,19159,19179,19197,19217,19235,19256,19274, - 19295,19313,19362,19409,19455,19549,19596,19643,19689,19782,19828,19873, - 19921,19967,20013,20059,20104,20162,20173,20183,20190,20238,20284,20305, - 20350,20357,20369,20381,20398,20405,20449,20499,20548,20550,20553,20556, - 20559,20562,20565,20568,20571,20574,20577,20580,20624,20672,20713,20756, - 20799,20842,20885,20928,20971,21017,21063,21109,21155,21201,21247,21293, - 21339,21385,21431,21477,21523,21569,21615,21661,21707,21753,21799,21845, - 21891,21937,21983,22029,22075,22121,22167,22213,22259,22305,22351,22397, - 22404,22416,22428,22440,22452,22475,22483,22495,22546,22551,22563,22593, - 22601,22609,22617,22625,22671,22716,22802,22847,22894,22907,22915,22925, - 22935,22945,22956,22966,23012,23058,23104,23113,23122,23127,23172,23217, - 23226,23231,23243,23263,23398,23598,23601,23646,23702,23710,23718,23726, - 23734,23779,23832,23838,23881,23924,23968,23985,24030,24115,24200,24285, - 24370,24455,24540,24625,24710,24795,24840,24882,24952,25022,25092,25162, - 25235,25314,25393,25473,25553,25633,25713,25794,25875,25957,26039,26122, - 26168,26175,26187,26199,26211,26224,26232,26239,26289,26374,26459,26503, - 26548,26603,26650,26654,26662,26707,26752,26761,26779,26827,26875,26880, - 26930,26936,26942,26960,26966,26969,26972,26975,26978,26981,26984,26987, - 26990,26993,26996,27034,27076,27115,27151,27187,27223,27257,27293,27325, - 27355,27383,27411,27418,27430,27442,27460,27506,27550,27641,27699,27707, - 27736,27742,27747,27759,27764,27766 + 28, 32, 60, 89, 121, 137, 351, 355, 365, 573, 773, 972,1000,1019, + 1024,1029,1076,1081,1090,1099,1118,1164,1210,1229,1238,1263,1281,1301, + 1307,1312,1359,1363,1373,1382,1400,1446,1533,1593,1602,1610,1672,1764, + 1769,1818,1869,1915,1963,2053,2140,2381,2568,2578,2588,2598,2608,2618, + 2628,2638,2648,2658,2668,2678,2688,2698,2708,2721,2734,2745,2791,2837, + 2883,2929,2975,3021,3067,3113,3159,3205,3251,3297,3343,3389,3435,3481, + 3491,3501,3511,3521,3531,3541,3551,3561,3571,3581,3591,3601,3611,3621, + 3631,3641,3651,3661,3671,3681,3691,3701,3711,3721,3731,3741,3751,3761, + 3771,3779,3792,3805,3816,3862,3908,3954,4000,4046,4092,4138,4184,4230, + 4276,4322,4368,4414,4460,4506,4552,4598,4644,4690,4736,4782,4828,4874, + 4920,4966,5012,5058,5104,5150,5196,5242,5288,5334,5380,5426,5472,5518, + 5564,5610,5656,5702,5748,5794,5840,5886,5932,5978,6024,6036,6048,6060, + 6072,6080,6088,6099,6110,6121,6134,6147,6160,6173,6186,6199,6212,6225, + 6238,6251,6264,6277,6290,6298,6303,6308,6313,6359,6405,6451,6497,6543, + 6589,6635,6681,6727,6773,6819,6865,6911,6957,7003,7049,7095,7141,7187, + 7233,7279,7325,7371,7417,7463,7509,7555,7601,7647,7693,7739,7785,7831, + 7877,7923,7969,8015,8061,8107,8153,8199,8245,8291,8337,8383,8429,8475, + 8521,8567,8613,8659,8705,8717,8729,8741,8753,8761,8769,8780,8791,8802, + 8815,8828,8841,8854,8867,8880,8893,8906,8919,8932,8945,8958,8971,9031, + 9042,9114,9122,9125,9169,9251,9299,9343,9352,9356,9361,9408,9496,9507, + 9516,9524,9537,9551,9559,9564,9567,9627,9683,9689,9732,9739,9750,9794, + 9836,9885,9938,9942,9952,9957,9962,9967,9972,9977,9982,9987,9992,9997, + 10039,10081,10147,10152,10157,10162,10167,10172,10177,10182,10187,10192, + 10197,10202,10245,10310,10353,10418,10464,10506,10576,10646,10716,10786, + 10826,10868,10905,10940,10971,10978,11000,11062,11111,11120,11129,11137, + 11146,11155,11164,11183,11202,11211,11220,11229,11238,11282,11289,11298, + 11307,11332,11356,11413,11479,11530,11596,11644,11695,11746,11797,11848, + 11899,11950,12001,12052,12103,12154,12205,12256,12307,12358,12409,12460, + 12511,12562,12613,12678,12744,12810,12876,12941,13016,13067,13133,13198, + 13249,13300,13351,13409,13454,13497,13500,13545,13590,13672,13722,13732, + 13752,13769,13780,13790,13793,13796,13799,13843,13928,14013,14098,14183, + 14268,14353,14438,14523,14608,14693,14778,14863,14948,15033,15118,15203, + 15288,15373,15458,15543,15628,15713,15798,15883,15968,16053,16138,16223, + 16308,16393,16478,16563,16648,16733,16818,16903,16988,17073,17158,17243, + 17328,17413,17498,17583,17668,17753,17838,17923,18008,18093,18178,18229, + 18244,18259,18274,18285,18293,18304,18317,18330,18345,18362,18379,18392, + 18405,18418,18431,18444,18457,18470,18483,18496,18509,18556,18619,18762, + 18899,18918,18936,18960,18982,18991,19000,19006,19011,19024,19033,19057, + 19081,19086,19091,19139,19186,19233,19324,19369,19428,19446,19466,19484, + 19504,19522,19543,19561,19582,19600,19649,19696,19742,19836,19883,19930, + 19976,20069,20115,20160,20209,20255,20301,20347,20392,20450,20462,20473, + 20481,20529,20576,20585,20593,20602,20611,20627,20634,20647,20664,20671, + 20715,20766,20816,20818,20821,20824,20827,20830,20833,20836,20839,20842, + 20845,20848,20892,20940,20981,21024,21067,21110,21153,21196,21239,21285, + 21331,21377,21423,21469,21515,21561,21607,21653,21699,21745,21791,21837, + 21883,21929,21975,22021,22067,22113,22159,22205,22251,22297,22343,22389, + 22435,22481,22527,22573,22619,22665,22673,22686,22699,22712,22725,22748, + 22757,22770,22821,22827,22840,22871,22880,22889,22898,22907,22953,22998, + 23084,23129,23177,23191,23200,23211,23222,23233,23245,23256,23302,23348, + 23394,23404,23414,23419,23464,23509,23519,23524,23536,23557,23692,23892, + 23895,23940,24033,24086,24095,24104,24113,24122,24168,24255,24263,24276, + 24289,24306,24312,24355,24357,24374,24419,24504,24589,24674,24759,24844, + 24929,25014,25099,25184,25229,25271,25341,25411,25481,25551,25624,25703, + 25782,25862,25942,26022,26102,26183,26264,26346,26428,26511,26558,26566, + 26579,26592,26605,26619,26628,26636,26686,26771,26856,26900,26945,27000, + 27047,27051,27060,27105,27150,27160,27178,27227,27276,27282,27332,27417, + 27423,27439,27445,27448,27451,27454,27457,27460,27463,27466,27469,27472, + 27475,27514,27557,27597,27634,27671,27708,27743,27780,27813,27844,27873, + 27902,27910,27923,27936,27954,28000,28044,28135,28193,28203,28227,28233, + 28238,28250,28259,28268,28270 }; static const unsigned char ag_fl[] = { - 2,1,1,2,2,1,1,2,0,1,3,3,1,2,1,2,2,1,2,0,1,4,5,3,2,1,0,1,7,7,6,1,1,6,6, - 6,2,3,2,1,2,4,4,4,4,6,4,4,0,1,4,4,4,4,3,3,4,4,7,4,6,4,1,1,2,2,2,2,3,5, - 1,2,2,2,3,2,1,1,1,3,2,1,1,3,1,1,1,3,1,1,3,3,3,3,3,3,3,3,3,4,3,6,2,3,2, - 1,1,2,2,3,3,2,2,3,3,1,1,2,3,1,1,1,4,4,4,1,4,2,1,1,1,1,2,2,1,2,2,3,2,2, - 1,2,3,1,2,2,2,2,2,2,2,2,4,1,1,4,3,2,1,2,3,3,2,1,1,1,1,1,1,2,1,1,1,1,2, - 1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,2,4,4,2,4,4,2,4,4,2,4,4,4,4,2,4,4,2,4, - 4,4,4,4,1,2,2,2,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,7,1,1,1,1,1,1,1,2,2,2,1, - 1,2,2,2,2,1,2,2,2,3,2,2,2,2,2,2,2,2,3,4,1,1,2,2,2,2,2,1,2,1,2,2,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1, - 1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,7,3, - 3,3,3,3,3,3,3,3,3,5,3,5,3,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1, - 3,3,3,3,1,1,1,1,1,3,3,3,3,3,3,3,1,1,1,3,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,1,1,2,2,1,1,2,0,1,3,3,1,1,2,1,2,2,1,2,0,1,4,5,3,2,1,0,1,7,7,6,1,1,6, + 6,6,2,3,2,2,1,2,4,4,4,4,6,4,4,0,1,4,4,4,4,3,3,4,5,5,5,8,4,6,4,1,1,2,2, + 2,2,3,5,1,2,2,2,3,2,1,1,1,3,2,1,1,3,1,1,1,3,1,1,3,3,3,3,3,3,3,3,3,4,4, + 4,3,6,2,3,2,1,1,2,2,3,3,2,2,3,3,1,1,2,3,1,1,1,4,4,4,1,4,2,1,1,1,1,2,2, + 1,2,2,3,2,2,1,2,3,1,2,2,2,2,2,2,2,2,4,1,1,4,3,2,1,2,3,3,2,1,1,1,1,1,1, + 2,1,1,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,2,4,4,2,4,4,2,4,4,2,4,4,4, + 4,2,4,4,2,4,4,4,4,4,1,2,2,2,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,7,1,1,1,1,1, + 1,1,2,2,2,1,1,2,2,2,2,1,2,2,2,3,2,2,2,2,2,2,2,2,3,4,1,1,2,2,2,2,2,1,2, + 1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3, + 3,3,3,3,7,3,3,3,3,3,3,3,3,3,3,5,3,5,3,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,1,1,1,1,1,3,3,3,3,1,1,1,1,1,3,3,3,3,3,3,3,1,1,1,3,1,1,1,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -6672,7 +6746,7 @@ static const unsigned char ag_fl[] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, @@ -6680,75 +6754,75 @@ static const unsigned char ag_fl[] = { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 + 2,2,2,2,2,2 }; static const unsigned short ag_ptt[] = { - 0, 36, 37, 37, 34, 39, 43, 43, 44, 44, 39, 39, 39, 40, 47, 47, 47, 51, - 51, 52, 52, 35, 35, 35, 35, 35, 55, 55, 35, 35, 35, 62, 62, 35, 35, 35, - 35, 35, 35, 65, 53, 67, 67, 67, 67, 67, 67, 67, 75, 75, 67, 67, 67, 67, - 67, 67, 67, 67, 67, 67, 67, 88, 88, 89, 89, 89, 96, 96, 63, 63, 33, 33, - 33, 33, 33, 33,102,102,102, 33, 33,106,106, 33,110,110,110, 33,113,113, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 30, 30, 91, 91, 91, 91, 91, 91,115, - 115,536,442,442,442,133,133,133,437,437,485, 18, 18,435, 12, 12, 12,142, - 142,142,142,142,142,142,142,142,142,155,155,142,142,436, 14, 14, 14, 14, - 428,428,428,428,428, 22, 22, 77, 77,169,169,169,166,172,172,166,175,175, - 166,178,178,166,181,181,166,184,184,166, 57, 26, 26, 26, 28, 28, 28, 23, - 23, 23, 24, 24, 24, 24, 24, 27, 27, 27, 25, 25, 25, 25, 25, 25, 29, 29, - 29, 29, 29,198,198,198,198,207,207,207,207,207,207,207,207,207,207,207, - 206,206,492,492,492,492,492,492,492,492,223,223,492,492, 7, 7, 7, 7, - 7, 7, 6, 6, 6, 17, 17,218,218,219,219, 15, 15, 15, 16, 16, 16, 16, - 16, 16, 16, 16,538, 9, 9, 9,594,594,594,594,594,594,242,242,594,594, - 245,245,608,247,247,608,249,249,608,608,251,251,251,251,251,253,253,254, - 254,254,254,254,254, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,272, - 272,272,272,266,266,266,266,266,279,279,266,266,266,285,285,285,266,266, - 266,266,266,266,266,266,266,296,296,266,266,266,266,266,266,266,266,266, - 266,309,309,309,266,266,266,266,266,266,266,259,259,260,260,260,260,257, - 257,257,257,257,257,257,257,257,257,257,257,257,258,258,258,338,262,340, - 263,342,264,265,261,261,261,261,261,261,261,261,261,261,261,261,261,261, - 261,366,366,366,366,366,261,261,261,261,375,375,375,375,375,261,261,261, - 261,261,261,261,385,385,385,261,389,389,389,261,261,261,261,261,261,261, + 0, 36, 37, 37, 34, 39, 43, 43, 44, 44, 39, 39, 39, 39, 40, 47, 47, 47, + 51, 51, 52, 52, 35, 35, 35, 35, 35, 55, 55, 35, 35, 35, 62, 62, 35, 35, + 35, 35, 35, 35, 35, 65, 53, 67, 67, 67, 67, 67, 67, 67, 75, 75, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 89, 89, 90, 90, 90, 97, 97, + 63, 63, 33, 33, 33, 33, 33, 33,103,103,103, 33, 33,107,107, 33,111,111, + 111, 33,114,114, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 30, 30, 92, + 92, 92, 92, 92, 92,116,116,536,442,442,442,133,133,133,437,437,485, 18, + 18,435, 12, 12, 12,142,142,142,142,142,142,142,142,142,142,155,155,142, + 142,436, 14, 14, 14, 14,428,428,428,428,428, 22, 22, 77, 77,169,169,169, + 166,172,172,166,175,175,166,178,178,166,181,181,166,184,184,166, 57, 26, + 26, 26, 28, 28, 28, 23, 23, 23, 24, 24, 24, 24, 24, 27, 27, 27, 25, 25, + 25, 25, 25, 25, 29, 29, 29, 29, 29,198,198,198,198,207,207,207,207,207, + 207,207,207,207,207,207,206,206,492,492,492,492,492,492,492,492,223,223, + 492,492, 7, 7, 7, 7, 7, 7, 6, 6, 6, 17, 17,218,218,219,219, 15, + 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,538, 9, 9, 9,594,594,594,594, + 594,594,242,242,594,594,245,245,608,247,247,608,249,249,608,608,251,251, + 251,251,251,253,253,254,254,254,254,254,254, 31, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32,272,272,272,272,266,266,266,266,266,279,279,266,266, + 266,285,285,285,266,266,266,266,266,266,266,266,266,296,296,266,266,266, + 266,266,266,266,266,266,266,309,309,309,266,266,266,266,266,266,266,259, + 259,260,260,260,260,257,257,257,257,257,257,257,257,257,257,257,257,257, + 258,258,258,338,262,340,263,342,264,265,261,261,261,261,261,261,261,261, + 261,261,261,261,261,261,261,366,366,366,366,366,261,261,261,261,375,375, + 375,375,375,261,261,261,261,261,261,261,385,385,385,261,389,389,389,261, 261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, - 138,345,153,226, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 261,261,261,261,261,261,138,345,153,226, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 50, 50, 50, 50, 50, 50, 50, 50, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 93, - 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, - 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, - 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 94,136,136,136,136,136,136,136,136,136,136, - 136,136,136,137,137,137,137,137,137,137,137,137,137,137,137,137,137,139, - 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, - 144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,136,136,136,136, + 136,136,136,136,136,136,136,136,136,137,137,137,137,137,137,137,137,137, + 137,137,137,137,137,139,139,139,139,139,139,139,139,139,139,139,139,139, + 139,139,139,139,139,139,144,144,144,144,144,144,144,144,144,144,144,144, 144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, - 144,144,144,144,151,151,151,152,152,152,152,152,156,156,156,156,156,156, - 156,156,156,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, + 144,144,144,144,144,144,144,144,144,144,151,151,151,152,152,152,152,152, + 156,156,156,156,156,156,156,156,156,159,159,159,159,159,159,159,159,159, 159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, - 159,159,159,159,159,159,160,160,160,160,160,160,160,160,160,160,160,160, + 159,159,159,159,159,159,159,159,159,159,159,159,160,160,160,160,160,160, 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, - 160,160,160,160,160,160,160,160,160,160,160,160,227,227,227,227,228,228, - 230,230,230,230,232,232,232,232,232,232,232,232,232,232,232,232,232,232, + 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, + 227,227,227,227,228,228,230,230,230,230,232,232,232,232,232,232,232,232, 232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, - 232,232,232,232,232,232,232,232, 45, 41, 46, 48, 49, 11, 54, 56, 58, 59, - 60, 61, 10, 13, 19, 66, 69, 68, 70, 21, 71, 72, 73, 74, 76, 78, 79, 80, - 81, 82, 83, 85, 84, 86, 87, 92, 90, 95, 97, 98, 99,100,101,103,104,105, - 107,108,109,111,112,114,116,117,118,119,120,121,122,123,124,125, 20,126, - 127,128,129,130,131, 2,132,165,167,168,170,171,173,174,176,177,179,180, - 182,183,185,186,187,188,189,190,191,192,193,194,195,196,197,199,200,201, - 202,203,204,205,208,209,210,211,212,213,214,215,216, 3,217, 8,252,243, - 255,256,250,267,268,269,270,271,273,274,275,276,277,278,280,281,282,283, - 284,286,287,288,289,290,291,292,293,294,295,297,298,299,300,301,302,303, - 304,305,306,307,308,310,311,312,313,314,315,316,317,318,319,320,321, 4, - 322,323,324,325,326,327,328,329,330,331,332,333,334, 5,335,336,337,339, - 341,343,344,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360, - 361,362,363,364,365,367,368,369,370,371,372,373,374,376,377,378,379,380, - 381,382,383,384,386,387,388,390,391,392,393,394,395,396,397,398,399,400, - 401,244,402,403,404,405,406,407,408,409,410,411,412,414,141,154,140,148, - 415,416,417,418,158,157,419,229,420,149,224,150,421,220,145,147,146,413, - 143,225,422 + 232,232,232,232,232,232,232,232,232,232,232,232,232,232, 45, 41, 46, 48, + 49, 11, 54, 56, 58, 59, 60, 61, 10, 13, 19, 66, 69, 68, 70, 21, 71, 72, + 73, 74, 76, 78, 79, 80, 81, 82, 83, 84, 86, 85, 87, 88, 93, 91, 96, 98, + 99,100,101,102,104,105,106,108,109,110,112,113,115,117,118,119,120,121, + 122,123,124,125, 20,126,127,128,129,130,131, 2,132,165,167,168,170,171, + 173,174,176,177,179,180,182,183,185,186,187,188,189,190,191,192,193,194, + 195,196,197,199,200,201,202,203,204,205,208,209,210,211,212,213,214,215, + 216, 3,217, 8,252,243,255,256,250,267,268,269,270,271,273,274,275,276, + 277,278,280,281,282,283,284,286,287,288,289,290,291,292,293,294,295,297, + 298,299,300,301,302,303,304,305,306,307,308,310,311,312,313,314,315,316, + 317,318,319,320,321, 4,322,323,324,325,326,327,328,329,330,331,332,333, + 334, 5,335,336,337,339,341,343,344,346,347,348,349,350,351,352,353,354, + 355,356,357,358,359,360,361,362,363,364,365,367,368,369,370,371,372,373, + 374,376,377,378,379,380,381,382,383,384,386,387,388,390,391,392,393,394, + 395,396,397,398,399,400,401,244,402,403,404,405,406,407,408,409,410,411, + 412,414,141,154,140,148,415,416,417,418,158,157,419,229,420,149,224,150, + 421,220,145,147,146,413,143,225,422 }; @@ -6784,14 +6858,14 @@ static void ag_ra(void) case 27: ag_rp_27(); break; case 28: ag_rp_28(); break; case 29: ag_rp_29(); break; - case 30: ag_rp_30(V(0,int)); break; - case 31: ag_rp_31(V(1,int)); break; - case 32: ag_rp_32(); break; - case 33: ag_rp_33(); break; + case 30: ag_rp_30(); break; + case 31: ag_rp_31(); break; + case 32: ag_rp_32(V(0,int)); break; + case 33: ag_rp_33(V(1,int)); break; case 34: ag_rp_34(); break; - case 35: ag_rp_35(V(2,int)); break; + case 35: ag_rp_35(); break; case 36: ag_rp_36(); break; - case 37: ag_rp_37(); break; + case 37: ag_rp_37(V(2,int)); break; case 38: ag_rp_38(); break; case 39: ag_rp_39(); break; case 40: ag_rp_40(); break; @@ -6826,53 +6900,53 @@ static void ag_ra(void) case 69: ag_rp_69(); break; case 70: ag_rp_70(); break; case 71: ag_rp_71(); break; - case 72: ag_rp_72(V(2,int)); break; + case 72: ag_rp_72(); break; case 73: ag_rp_73(); break; case 74: ag_rp_74(); break; case 75: ag_rp_75(); break; - case 76: ag_rp_76(); break; + case 76: ag_rp_76(V(2,int)); break; case 77: ag_rp_77(); break; case 78: ag_rp_78(); break; case 79: ag_rp_79(); break; case 80: ag_rp_80(); break; case 81: ag_rp_81(); break; case 82: ag_rp_82(); break; - case 83: ag_rp_83(V(0,int)); break; - case 84: ag_rp_84(V(1,int)); break; - case 85: ag_rp_85(V(1,int)); break; - case 86: ag_rp_86(V(0,int)); break; - case 87: ag_rp_87(V(1,int)); break; - case 88: ag_rp_88(V(1,int), V(2,int)); break; + case 83: ag_rp_83(); break; + case 84: ag_rp_84(); break; + case 85: ag_rp_85(); break; + case 86: ag_rp_86(); break; + case 87: ag_rp_87(V(0,int)); break; + case 88: ag_rp_88(V(1,int)); break; case 89: ag_rp_89(V(1,int)); break; - case 90: ag_rp_90(); break; + case 90: ag_rp_90(V(0,int)); break; case 91: ag_rp_91(V(1,int)); break; - case 92: V(0,int) = ag_rp_92(V(0,int)); break; - case 93: V(0,int) = ag_rp_93(); break; - case 94: V(0,int) = ag_rp_94(); break; - case 95: V(0,int) = ag_rp_95(); break; - case 96: V(0,int) = ag_rp_96(); break; + case 92: ag_rp_92(V(1,int), V(2,int)); break; + case 93: ag_rp_93(V(1,int)); break; + case 94: ag_rp_94(); break; + case 95: ag_rp_95(V(1,int)); break; + case 96: V(0,int) = ag_rp_96(V(0,int)); break; case 97: V(0,int) = ag_rp_97(); break; case 98: V(0,int) = ag_rp_98(); break; case 99: V(0,int) = ag_rp_99(); break; case 100: V(0,int) = ag_rp_100(); break; - case 101: V(0,int) = ag_rp_101(V(1,int), V(2,int), V(3,int)); break; - case 102: V(0,int) = ag_rp_102(V(2,int), V(3,int)); break; - case 103: V(0,int) = ag_rp_103(V(2,int)); break; - case 104: ag_rp_104(); break; - case 105: ag_rp_105(); break; - case 106: ag_rp_106(V(1,int)); break; - case 107: ag_rp_107(V(2,int)); break; + case 101: V(0,int) = ag_rp_101(); break; + case 102: V(0,int) = ag_rp_102(); break; + case 103: V(0,int) = ag_rp_103(); break; + case 104: V(0,int) = ag_rp_104(); break; + case 105: V(0,int) = ag_rp_105(V(1,int), V(2,int), V(3,int)); break; + case 106: V(0,int) = ag_rp_106(V(2,int), V(3,int)); break; + case 107: V(0,int) = ag_rp_107(V(2,int)); break; case 108: ag_rp_108(); break; case 109: ag_rp_109(); break; - case 110: ag_rp_110(); break; - case 111: ag_rp_111(); break; + case 110: ag_rp_110(V(1,int)); break; + case 111: ag_rp_111(V(2,int)); break; case 112: ag_rp_112(); break; - case 113: V(0,int) = ag_rp_113(); break; - case 114: V(0,int) = ag_rp_114(); break; + case 113: ag_rp_113(); break; + case 114: ag_rp_114(); break; case 115: ag_rp_115(); break; case 116: ag_rp_116(); break; - case 117: ag_rp_117(); break; - case 118: ag_rp_118(); break; + case 117: V(0,int) = ag_rp_117(); break; + case 118: V(0,int) = ag_rp_118(); break; case 119: ag_rp_119(); break; case 120: ag_rp_120(); break; case 121: ag_rp_121(); break; @@ -6898,11 +6972,11 @@ static void ag_ra(void) case 141: ag_rp_141(); break; case 142: ag_rp_142(); break; case 143: ag_rp_143(); break; - case 144: ag_rp_144(V(0,double)); break; + case 144: ag_rp_144(); break; case 145: ag_rp_145(); break; case 146: ag_rp_146(); break; case 147: ag_rp_147(); break; - case 148: ag_rp_148(); break; + case 148: ag_rp_148(V(0,double)); break; case 149: ag_rp_149(); break; case 150: ag_rp_150(); break; case 151: ag_rp_151(); break; @@ -6911,49 +6985,49 @@ static void ag_ra(void) case 154: ag_rp_154(); break; case 155: ag_rp_155(); break; case 156: ag_rp_156(); break; - case 157: V(0,double) = ag_rp_157(V(0,int)); break; - case 158: V(0,double) = ag_rp_158(V(0,double)); break; - case 159: V(0,int) = ag_rp_159(V(0,int)); break; - case 160: V(0,int) = ag_rp_160(); break; - case 161: V(0,int) = ag_rp_161(); break; - case 162: V(0,int) = ag_rp_162(); break; - case 163: V(0,int) = ag_rp_163(); break; + case 157: ag_rp_157(); break; + case 158: ag_rp_158(); break; + case 159: ag_rp_159(); break; + case 160: ag_rp_160(); break; + case 161: V(0,double) = ag_rp_161(V(0,int)); break; + case 162: V(0,double) = ag_rp_162(V(0,double)); break; + case 163: V(0,int) = ag_rp_163(V(0,int)); break; case 164: V(0,int) = ag_rp_164(); break; case 165: V(0,int) = ag_rp_165(); break; case 166: V(0,int) = ag_rp_166(); break; case 167: V(0,int) = ag_rp_167(); break; case 168: V(0,int) = ag_rp_168(); break; - case 169: ag_rp_169(V(1,int)); break; - case 170: ag_rp_170(V(1,int)); break; - case 171: ag_rp_171(V(0,int)); break; - case 172: ag_rp_172(V(1,int)); break; - case 173: ag_rp_173(V(2,int)); break; + case 169: V(0,int) = ag_rp_169(); break; + case 170: V(0,int) = ag_rp_170(); break; + case 171: V(0,int) = ag_rp_171(); break; + case 172: V(0,int) = ag_rp_172(); break; + case 173: ag_rp_173(V(1,int)); break; case 174: ag_rp_174(V(1,int)); break; - case 175: ag_rp_175(V(1,int)); break; + case 175: ag_rp_175(V(0,int)); break; case 176: ag_rp_176(V(1,int)); break; - case 177: ag_rp_177(V(1,int)); break; + case 177: ag_rp_177(V(2,int)); break; case 178: ag_rp_178(V(1,int)); break; case 179: ag_rp_179(V(1,int)); break; case 180: ag_rp_180(V(1,int)); break; case 181: ag_rp_181(V(1,int)); break; - case 182: V(0,int) = ag_rp_182(V(1,int)); break; - case 183: V(0,int) = ag_rp_183(V(1,int), V(2,int)); break; - case 184: V(0,int) = ag_rp_184(); break; - case 185: V(0,int) = ag_rp_185(V(0,int)); break; - case 186: V(0,int) = ag_rp_186(); break; - case 187: V(0,int) = ag_rp_187(); break; + case 182: ag_rp_182(V(1,int)); break; + case 183: ag_rp_183(V(1,int)); break; + case 184: ag_rp_184(V(1,int)); break; + case 185: ag_rp_185(V(1,int)); break; + case 186: V(0,int) = ag_rp_186(V(1,int)); break; + case 187: V(0,int) = ag_rp_187(V(1,int), V(2,int)); break; case 188: V(0,int) = ag_rp_188(); break; - case 189: V(0,int) = ag_rp_189(); break; + case 189: V(0,int) = ag_rp_189(V(0,int)); break; case 190: V(0,int) = ag_rp_190(); break; case 191: V(0,int) = ag_rp_191(); break; case 192: V(0,int) = ag_rp_192(); break; - case 193: V(0,double) = ag_rp_193(); break; - case 194: V(0,double) = ag_rp_194(V(1,int)); break; - case 195: V(0,double) = ag_rp_195(V(0,double), V(1,int)); break; - case 196: ag_rp_196(); break; - case 197: ag_rp_197(); break; - case 198: ag_rp_198(); break; - case 199: ag_rp_199(); break; + case 193: V(0,int) = ag_rp_193(); break; + case 194: V(0,int) = ag_rp_194(); break; + case 195: V(0,int) = ag_rp_195(); break; + case 196: V(0,int) = ag_rp_196(); break; + case 197: V(0,double) = ag_rp_197(); break; + case 198: V(0,double) = ag_rp_198(V(1,int)); break; + case 199: V(0,double) = ag_rp_199(V(0,double), V(1,int)); break; case 200: ag_rp_200(); break; case 201: ag_rp_201(); break; case 202: ag_rp_202(); break; @@ -7034,11 +7108,11 @@ static void ag_ra(void) case 277: ag_rp_277(); break; case 278: ag_rp_278(); break; case 279: ag_rp_279(); break; - case 280: ag_rp_280(V(2,int)); break; + case 280: ag_rp_280(); break; case 281: ag_rp_281(); break; case 282: ag_rp_282(); break; case 283: ag_rp_283(); break; - case 284: ag_rp_284(); break; + case 284: ag_rp_284(V(2,int)); break; case 285: ag_rp_285(); break; case 286: ag_rp_286(); break; case 287: ag_rp_287(); break; @@ -7087,6 +7161,10 @@ static void ag_ra(void) case 330: ag_rp_330(); break; case 331: ag_rp_331(); break; case 332: ag_rp_332(); break; + case 333: ag_rp_333(); break; + case 334: ag_rp_334(); break; + case 335: ag_rp_335(); break; + case 336: ag_rp_336(); break; } } @@ -7175,6 +7253,7 @@ const char *const a85parse_token_names[706] = { "\"ELSE\"", "\"ENDIF\"", "\"ERROR\"", + "\"ECHO\"", "\"PRINT\"", "\"PRINTF\"", "','", @@ -7213,7 +7292,6 @@ const char *const a85parse_token_names[706] = { "\"MODULE\"", "\"NAME\"", "\"STKLN\"", - "\"ECHO\"", "\"FILL\"", "\"END\"", "\"MSFIRST\"", @@ -7545,6 +7623,7 @@ const char *const a85parse_token_names[706] = { "\"ELSE\"", "\"ENDIF\"", "\"ERROR\"", + "\"ECHO\"", "\"PRINT\"", "','", "\"PRINTF\"", @@ -7572,7 +7651,6 @@ const char *const a85parse_token_names[706] = { "\"MODULE\"", "\"NAME\"", "\"STKLN\"", - "\"ECHO\"", "\"FILL\"", "\"END\"", "\"MSFIRST\"", @@ -7804,68 +7882,68 @@ const char *const a85parse_token_names[706] = { static const unsigned short ag_ctn[] = { 0,0, 0,0, 0,0, 65,1,428,1, 53,1, 35,1, 35,1, 35,1, 35,1, 35,1, 0,0, - 67,1, 67,1, 0,0, 0,0, 67,1, 0,0, 0,0, 67,1, 67,1, 0,0, 67,1, 67,1, - 0,0, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, - 67,1, 67,1, 0,0, 0,0, 35,2, 47,1, 0,0, 39,1, 40,1, 39,1, 39,1, 35,2, - 63,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1, - 266,1,266,1,266,1,342,1,340,1,338,1,261,1,261,1,261,1,261,1,261,1,261,1, - 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,266,1,266,1, + 67,1, 67,1, 0,0, 0,0, 0,0, 67,1, 0,0, 0,0, 67,1, 67,1, 0,0, 67,1, + 67,1, 0,0, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, + 67,1, 67,1, 67,1, 67,1, 0,0, 0,0, 35,2, 47,1, 0,0, 39,1, 40,1, 39,1, + 39,1, 35,2, 63,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1, + 266,1,266,1,266,1,266,1,266,1,342,1,340,1,338,1,261,1,261,1,261,1,261,1, + 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, 266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1, 266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1, - 266,1,266,1,266,1,265,1,342,1,340,1,338,1,261,1,261,1,261,1,261,1,261,1, + 266,1,266,1,266,1,266,1,266,1,265,1,342,1,340,1,338,1,261,1,261,1,261,1, 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, - 261,1,261,1,261,1,261,1,261,1,261,1,261,1,260,1,260,1,260,1,260,1,259,1, - 259,1,258,1,258,1,258,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1, - 257,1,257,1,257,1,257,1,257,1,265,1,264,1,263,1,262,1,261,1,261,1,261,1, + 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,260,1,260,1,260,1, + 260,1,259,1,259,1,258,1,258,1,258,1,257,1,257,1,257,1,257,1,257,1,257,1, + 257,1,257,1,257,1,257,1,257,1,257,1,257,1,265,1,264,1,263,1,262,1,261,1, 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, - 261,1,260,1,260,1,260,1,260,1,259,1,259,1,258,1,258,1,258,1,257,1,257,1, - 257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1, 0,0, - 32,1, 88,1, 30,1, 32,1, 33,1, 33,1, 35,2, 67,2, 67,2,435,1, 0,0, 67,2, - 67,2, 67,2, 67,2, 67,2, 67,2,538,1,219,1,218,1, 6,1, 6,1, 7,1, 15,1, - 538,1,492,1,219,1,218,1, 6,1,206,1,207,1, 0,0,207,1,207,1,207,1,207,1, - 207,1,207,1,207,1,207,1,207,1,206,1, 0,0, 0,0,207,1,207,1,207,1,207,1, - 207,1,207,1,207,1,207,1,207,1,207,1,207,1, 29,1, 0,0, 29,1, 0,0,198,1, - 29,1, 29,1, 29,1, 29,1, 25,1, 27,1, 24,1, 23,1, 28,1, 26,1, 26,1, 77,1, - 77,1, 67,2, 67,2, 67,2, 0,0, 67,2, 0,0, 67,2, 0,0, 67,2, 0,0, 67,2, - 0,0, 67,2,436,1, 0,0, 67,2, 67,2, 0,0, 35,3, 0,0, 0,0, 0,0, 0,0, + 261,1,261,1,261,1,260,1,260,1,260,1,260,1,259,1,259,1,258,1,258,1,258,1, + 257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1, + 257,1, 0,0, 32,1, 89,1, 30,1, 32,1, 33,1, 33,1, 35,2, 67,2, 67,2, 67,2, + 67,2, 67,2,435,1, 0,0, 67,2, 67,2, 67,2, 67,2,538,1,219,1,218,1, 6,1, + 6,1, 7,1, 15,1,538,1,492,1,219,1,218,1, 6,1,206,1,207,1, 0,0,207,1, + 207,1,207,1,207,1,207,1,207,1,207,1,207,1,207,1,206,1, 0,0, 0,0,207,1, + 207,1,207,1,207,1,207,1,207,1,207,1,207,1,207,1,207,1,207,1, 29,1, 0,0, + 29,1, 0,0,198,1, 29,1, 29,1, 29,1, 29,1, 25,1, 27,1, 24,1, 23,1, 28,1, + 26,1, 26,1, 77,1, 77,1, 67,2, 67,2, 67,2, 0,0, 67,2, 0,0, 67,2, 0,0, + 67,2, 0,0, 67,2, 0,0, 67,2,436,1, 0,0, 67,2, 67,2, 0,0, 35,3, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, - 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 39,2, 39,2, - 0,0, 35,3, 33,1, 35,3, 63,2,342,2,340,2,338,2,265,2,264,2,263,2,262,2, - 261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2, + 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0,0, 39,2, 39,2, 0,0, 35,3, 33,1, 35,3, 63,2,342,2,340,2,338,2,265,2, + 264,2,263,2,262,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2, 261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2, 261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2, 261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2, - 261,2,261,2,261,2,261,2,260,2,260,2,260,2,260,2,259,2,259,2,258,2,258,2, - 258,2,257,2,257,2,257,2,257,2,257,2,257,2,257,2,257,2,257,2,257,2,257,2, - 257,2,257,2, 88,2, 0,0, 0,0, 32,2, 0,0, 33,2, 0,0, 33,2, 0,0, 0,0, - 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 33,2, 33,2, 0,0, 33,2, 0,0, 33,2, - 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, - 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, 0,0, 33,2, 0,0, 0,0, - 0,0, 0,0, 33,2, 33,2, 0,0, 0,0, 35,3, 67,3, 67,3, 0,0, 67,3, 67,3, - 67,3, 67,3, 6,2, 16,1, 15,2, 0,0, 0,0,207,2,207,2,207,2,207,2,207,2, - 207,2,207,2,207,2,207,2,207,2,207,2,198,2, 7,1, 0,0, 25,2, 0,0, 25,2, - 25,2, 25,2, 25,2, 27,2, 27,2, 0,0, 24,2, 0,0, 24,2, 0,0, 24,2, 0,0, - 24,2, 0,0, 23,2, 23,2, 0,0, 28,2, 28,2, 0,0, 26,2, 26,2, 0,0, 0,0, - 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 67,3, 67,3, - 67,3, 67,3, 67,3, 67,3, 67,3, 67,3,436,2, 67,3, 67,3, 0,0, 35,4, 35,4, - 35,4, 35,4, 0,0, 35,4, 0,0, 35,4, 35,4, 22,1, 63,3,254,1,254,1,254,1, - 0,0, 0,0,264,3,263,3,262,3,251,1,251,1,257,3, 0,0,485,1, 0,0, 0,0, - 6,1,492,1, 32,3,485,1, 33,3, 33,3,115,1,115,1,115,1, 0,0, 0,0, 89,1, - 0,0, 0,0, 0,0, 67,4, 15,3,207,3,207,3,207,3,207,3,207,3,207,3,207,3, - 207,3,207,3,207,3,207,3,198,3, 25,3, 25,3, 25,3, 25,3, 25,3, 27,3, 27,3, - 24,3, 24,3, 24,3, 24,3, 23,3, 23,3, 28,3, 28,3, 26,3, 26,3, 67,4, 35,5, - 35,5, 35,5, 35,5, 35,5, 35,5, 63,4,264,4,263,4,262,4,257,4, 0,0, 0,0, - 0,0, 32,1, 32,1,485,2, 33,4, 0,0,115,2, 0,0, 0,0, 67,5, 0,0, 0,0, - 67,5,207,4,207,4,207,4,207,4,207,4,207,4,207,4,207,4,207,4,207,4,207,4, - 198,4, 25,1, 25,1, 27,1, 27,1, 27,1, 27,1, 24,1, 24,1, 23,1, 23,1, 28,1, - 28,1, 67,5, 35,6, 35,6,257,5, 15,3, 0,0, 33,5,115,3, 67,6,536,1, 0,0, - 207,5,257,6,207,6 + 261,2,261,2,261,2,261,2,261,2,261,2,261,2,260,2,260,2,260,2,260,2,259,2, + 259,2,258,2,258,2,258,2,257,2,257,2,257,2,257,2,257,2,257,2,257,2,257,2, + 257,2,257,2,257,2,257,2,257,2, 89,2, 0,0, 0,0, 32,2, 0,0, 33,2, 0,0, + 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 33,2, 33,2, 0,0, + 33,2, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, + 0,0, 33,2, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, 0,0, 33,2, + 0,0, 0,0, 0,0, 0,0, 33,2, 33,2, 0,0, 0,0, 35,3, 67,3, 67,3, 67,3, + 67,3, 67,3, 67,3, 0,0, 67,3, 67,3, 6,2, 16,1, 15,2, 0,0, 0,0,207,2, + 207,2,207,2,207,2,207,2,207,2,207,2,207,2,207,2,207,2,207,2,198,2, 7,1, + 0,0, 25,2, 0,0, 25,2, 25,2, 25,2, 25,2, 27,2, 27,2, 0,0, 24,2, 0,0, + 24,2, 0,0, 24,2, 0,0, 24,2, 0,0, 23,2, 23,2, 0,0, 28,2, 28,2, 0,0, + 26,2, 26,2, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0,0, 0,0, 67,3, 67,3, 67,3, 67,3, 67,3, 67,3, 67,3, 67,3,436,2, 67,3, + 67,3, 0,0, 35,4, 35,4, 35,4, 35,4, 0,0, 35,4, 0,0, 35,4, 35,4, 22,1, + 63,3,254,1,254,1,254,1, 0,0, 0,0,264,3,263,3,262,3,251,1,251,1,257,3, + 0,0,485,1, 0,0, 0,0, 6,1,492,1, 32,3,485,1, 33,3, 33,3, 33,3,116,1, + 116,1,116,1, 0,0, 0,0, 90,1, 67,4, 67,4, 67,4, 67,4, 0,0, 0,0, 0,0, + 15,3,207,3,207,3,207,3,207,3,207,3,207,3,207,3,207,3,207,3,207,3,207,3, + 198,3, 25,3, 25,3, 25,3, 25,3, 25,3, 27,3, 27,3, 24,3, 24,3, 24,3, 24,3, + 23,3, 23,3, 28,3, 28,3, 26,3, 26,3, 67,4, 35,5, 35,5, 35,5, 35,5, 35,5, + 35,5, 63,4,264,4,263,4,262,4,257,4, 0,0, 0,0, 0,0, 32,1, 32,1,485,2, + 33,4, 0,0,116,2, 0,0, 0,0, 67,5, 67,5, 0,0, 0,0,207,4,207,4,207,4, + 207,4,207,4,207,4,207,4,207,4,207,4,207,4,207,4,198,4, 25,1, 25,1, 27,1, + 27,1, 27,1, 27,1, 24,1, 24,1, 23,1, 23,1, 28,1, 28,1, 67,5, 35,6, 35,6, + 257,5, 15,3, 0,0, 33,5,116,3, 67,6,536,1, 0,0,207,5,257,6, 67,7,207,6 }; #ifndef MISSING_FORMAT diff --git a/src/a85parse.h b/src/a85parse.h index 603aa23..91d43d4 100644 --- a/src/a85parse.h +++ b/src/a85parse.h @@ -1,5 +1,5 @@ -#ifndef A85PARSE_H_1359807348 -#define A85PARSE_H_1359807348 +#ifndef A85PARSE_H_1359819567 +#define A85PARSE_H_1359819567 typedef union { long alignment; @@ -26,9 +26,9 @@ typedef enum { a85parse_equation_token = 57, a85parse_cdseg_statement_token = 63, a85parse_error_token, a85parse_preproc_start_token, a85parse_preprocessor_directive_token = 67, a85parse_condition_token = 77, - a85parse_macro_token = 88, a85parse_macro_expansion_token, - a85parse_expression_list_token = 91, a85parse_define_chars_token = 94, - a85parse_cdseg_statement_start_token = 96, a85parse_name_list_token = 115, + a85parse_macro_token = 89, a85parse_macro_expansion_token, + a85parse_expression_list_token = 92, a85parse_define_chars_token = 95, + a85parse_cdseg_statement_start_token = 97, a85parse_name_list_token = 116, a85parse_literal_alpha_token = 133, a85parse_digit_token = 138, a85parse_asm_incl_char_token, a85parse_str_escape_char_token = 142, a85parse_hex_digit_token = 156, a85parse_condition_start_token = 166, diff --git a/src/a85parse.syn b/src/a85parse.syn index db9ae5b..766fa33 100644 --- a/src/a85parse.syn +++ b/src/a85parse.syn @@ -69,6 +69,7 @@ comment -> ';', any text char?..., '\n' // -> ',', any text char?..., '\n' -> '\n' + -> eof cstyle comment -> cstyle comment head, "*/" @@ -102,6 +103,7 @@ statement -> WS..., cdseg statement = gAsm->directive_cdseg(seg, page); -> label, WS?..., cdseg statement = gAsm->directive_cdseg(seg, page); -> error, '\n' = handle_error(); + -> WS..., '\n' preproc start -> "#" @@ -124,8 +126,10 @@ preprocessor directive -> "else", WS?..., comment = gAsm->preproc_else(); -> "endif", WS?..., comment = gAsm->preproc_endif(); -> "error", literal string, WS?..., comment = {if (gAsm->preproc_error(ss[ss_idx--])) gAbort = TRUE;} - -> "print", literal string, WS?..., comment = gAsm->directive_printf(ss[ss_idx--], FALSE); - -> "printf", literal string, + -> "echo", WS?..., literal string, WS?..., comment = gAsm->directive_printf(ss[ss_idx--], FALSE); + -> "echo", WS?..., equation, WS?..., comment = gAsm->directive_printf("%d"); + -> "print", WS?..., literal string, WS?..., comment= gAsm->directive_printf(ss[ss_idx--], FALSE); + -> "printf", WS?..., literal string, ',', WS?..., equation, WS?..., comment = gAsm->directive_printf(ss[ss_idx--]); -> "undef", literal name nows, WS?..., comment = gAsm->preproc_undef(ss[ss_idx--]); -> "define", macro, WS?..., @@ -192,6 +196,8 @@ expression -> '.'?, "echo", equation = gAsm->directive_echo(); -> '.'?, "echo", literal string = gAsm->directive_echo(ss[ss_idx--]); -> '.'?, "fill", WS?..., expression list = gAsm->directive_fill(); + -> '.'?, "echo", WS?..., literal string = gAsm->directive_printf(ss[ss_idx--], FALSE); + -> '.'?, "echo", WS?..., equation = gAsm->directive_printf("%d"); -> '.'?, "print", literal string = gAsm->directive_printf(ss[ss_idx--], FALSE); -> '.'?, "printf", literal string, ',', WS?..., equation = gAsm->directive_printf(ss[ss_idx--]); diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index 4f8e6a5..83f8793 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -29,10 +29,11 @@ #include #include -#include #include #include +#include "FLU/Flu_File_Chooser.h" + #if defined(WIN32) #include #endif @@ -49,45 +50,64 @@ #include "memory.h" #include "fileview.h" -#define MENU_HEIGHT 32 - -void cb_Ide(Fl_Widget* w, void*) ; +#define MENU_HEIGHT 32 -VTDis cpu_dis; /* ============================================================================ Global variables ============================================================================ */ -cpuregs_ctrl_t cpuregs_ctrl; -Fl_Window *gcpuw = NULL; +VTCpuRegs *gcpuw = NULL; int gStopCountdown = 0; int gSaveFreq = 0; int gDisableRealtimeTrace = 0; -int gDebugCount = 0;; -int gDebugMonitorFreq = 8192; +int gDebugCount = 0; +int gDebugMonitorFreq = 32768; +VTDis cpu_dis; + +extern Fl_Preferences virtualt_prefs; +extern volatile UINT64 cycles=0; + +// Menu item callback definitions +void cb_save_trace(Fl_Widget* w, void*); +void cb_clear_trace(Fl_Widget* w, void*); +void cb_menu_run(Fl_Widget* w, void*); +void cb_menu_stop(Fl_Widget* w, void*); +void cb_menu_step(Fl_Widget* w, void*); +void cb_menu_step_over(Fl_Widget* w, void*); +void cb_setup_trace(Fl_Widget* w, void*); + +// Other prototypes +void debug_cpuregs_cb (int); +void cb_Ide(Fl_Widget* w, void*) ; // Menu items for the disassembler Fl_Menu_Item gCpuRegs_menuitems[] = { + { "T&race", 0, 0, 0, FL_SUBMENU }, + { "Save", FL_CTRL + 's', cb_save_trace }, + { "Clear", 0, cb_clear_trace, 0, FL_MENU_DIVIDER }, + { "Run", FL_F + 5, cb_menu_run }, + { "Stop", FL_F + 6, cb_menu_stop }, + { "Step", FL_F + 8, cb_menu_step }, + { "Step Over ", FL_F + 10, cb_menu_step_over, 0, FL_MENU_DIVIDER }, + { "Setup...", 0, cb_setup_trace }, + { 0 }, { "&Tools", 0, 0, 0, FL_SUBMENU }, { "Assembler / IDE", 0, cb_Ide }, { "Disassembler", 0, disassembler_cb }, { "Memory Editor", 0, cb_MemoryEditor }, { "Peripheral Devices", 0, cb_PeripheralDevices }, -// { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, cb_FileView }, { 0 }, { 0 } }; -void debug_cpuregs_cb (int); - /* ============================================================================ Callback routine for the CPU Regs window ============================================================================ */ -void cb_cpuregswin (Fl_Widget* w, void*) +void cb_cpuregswin (Fl_Widget* w, void* pOpaque) { // Hide the window gcpuw->hide(); @@ -104,12 +124,14 @@ void cb_cpuregswin (Fl_Widget* w, void*) // Remove ourselves as a debug monitor debug_clear_monitor_callback(debug_cpuregs_cb); + // Save the user preferences + gcpuw->SavePrefs(); + // Delete the window and set to NULL delete gcpuw; gcpuw = NULL; } - /* ============================================================================ str_to_i: This routine converts a hex or decimal string to an integer. @@ -165,20 +187,95 @@ int str_to_i(const char *pStr) return val; } +/* +============================================================================ +Check the breakpoint entries +============================================================================ +*/ +void VTCpuRegs::check_breakpoint_entries(void) +{ + const char* pStr; + int val; + int x; + + // Get value of Breakpoint 1 + pStr = m_pBreak1->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + m_breakAddr[0] = val; + } + else + m_breakAddr[0] = -1; + + // Get value of Breakpoint 2 + pStr = m_pBreak2->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + m_breakAddr[1] = val; + } + else + m_breakAddr[1] = -1; + + // Get value of Breakpoint 3 + pStr = m_pBreak3->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + m_breakAddr[2] = val; + } + else + m_breakAddr[2] = -1; + + // Get value of Breakpoint 4 + pStr = m_pBreak4->value(); + if (pStr[0] != 0) + { + val = str_to_i(pStr); + m_breakAddr[3] = val; + } + else + m_breakAddr[3] = -1; + + // Check if any breakpoints set + for (x = 0; x < 4; x++) + if (m_breakAddr[x] != -1) + break; + + // If no breakpoints set, restore old monitor frequency + if (x == 4) + { + if (m_breakMonitorFreq != 0) + gSaveFreq = m_breakMonitorFreq; + } + else + { + if (m_breakMonitorFreq == 0) + m_breakMonitorFreq = gSaveFreq; + gSaveFreq = 1; + gDebugMonitorFreq = 1; + } + + m_breakEnable[0] = !m_pBreakDisable1->value(); + m_breakEnable[1] = !m_pBreakDisable2->value(); + m_breakEnable[2] = !m_pBreakDisable3->value(); + m_breakEnable[3] = !m_pBreakDisable4->value(); +} + /* ============================================================================ get_reg_edits: This routine reads all register input fields and updates the CPU registers accordingly. ============================================================================ */ -void get_reg_edits(void) +void VTCpuRegs::get_reg_edits(void) { const char* pStr; int val, flags; - int x; // Get value of PC - pStr = cpuregs_ctrl.pRegPC->value(); + pStr = m_pRegPC->value(); if (pStr[0] != 0) { val = str_to_i(pStr); @@ -186,7 +283,7 @@ void get_reg_edits(void) } // Get value of SP - pStr = cpuregs_ctrl.pRegSP->value(); + pStr = m_pRegSP->value(); if (pStr[0] != 0) { val = str_to_i(pStr); @@ -194,7 +291,7 @@ void get_reg_edits(void) } // Get value of A - pStr = cpuregs_ctrl.pRegA->value(); + pStr = m_pRegA->value(); if (pStr[0] != 0) { val = str_to_i(pStr); @@ -202,7 +299,7 @@ void get_reg_edits(void) } // Get value of M - pStr = cpuregs_ctrl.pRegM->value(); + pStr = m_pRegM->value(); if (pStr[0] != 0) { val = str_to_i(pStr); @@ -210,7 +307,7 @@ void get_reg_edits(void) } // Get value of BC - pStr = cpuregs_ctrl.pRegBC->value(); + pStr = m_pRegBC->value(); if (pStr[0] != 0) { val = str_to_i(pStr); @@ -223,14 +320,14 @@ void get_reg_edits(void) else { // BC didn't change - test B and C individually - pStr = cpuregs_ctrl.pRegB->value(); + pStr = m_pRegB->value(); if (pStr[0] != 0) { val = str_to_i(pStr); B = val; } // Now get new value for C - pStr = cpuregs_ctrl.pRegC->value(); + pStr = m_pRegC->value(); if (pStr[0] != 0) { val = str_to_i(pStr); @@ -240,7 +337,7 @@ void get_reg_edits(void) } // Get value of DE - pStr = cpuregs_ctrl.pRegDE->value(); + pStr = m_pRegDE->value(); if (pStr[0] != 0) { val = str_to_i(pStr); @@ -253,14 +350,14 @@ void get_reg_edits(void) else { // DE didn't change - test D and E individually - pStr = cpuregs_ctrl.pRegD->value(); + pStr = m_pRegD->value(); if (pStr[0] != 0) { val = str_to_i(pStr); D = val; } // Now get new value for E - pStr = cpuregs_ctrl.pRegE->value(); + pStr = m_pRegE->value(); if (pStr[0] != 0) { val = str_to_i(pStr); @@ -270,7 +367,7 @@ void get_reg_edits(void) } // Get value of HL - pStr = cpuregs_ctrl.pRegHL->value(); + pStr = m_pRegHL->value(); if (pStr[0] != 0) { val = str_to_i(pStr); @@ -283,14 +380,14 @@ void get_reg_edits(void) else { // HL didn't change - test H and L individually - pStr = cpuregs_ctrl.pRegH->value(); + pStr = m_pRegH->value(); if (pStr[0] != 0) { val = str_to_i(pStr); H = val; } // Now get new value for L - pStr = cpuregs_ctrl.pRegL->value(); + pStr = m_pRegL->value(); if (pStr[0] != 0) { val = str_to_i(pStr); @@ -301,86 +398,59 @@ void get_reg_edits(void) // Finally get updates to the flags flags = 0; - if (cpuregs_ctrl.pSFlag->value()) + if (m_pSFlag->value()) flags |= 0x80; - if (cpuregs_ctrl.pZFlag->value()) + if (m_pZFlag->value()) flags |= 0x40; - if (cpuregs_ctrl.pTSFlag->value()) + if (m_pTSFlag->value()) flags |= 0x20; - if (cpuregs_ctrl.pACFlag->value()) + if (m_pACFlag->value()) flags |= 0x10; - if (cpuregs_ctrl.pPFlag->value()) + if (m_pPFlag->value()) flags |= 0x04; - if (cpuregs_ctrl.pOVFlag->value()) + if (m_pOVFlag->value()) flags |= 0x02; - if (cpuregs_ctrl.pCFlag->value()) + if (m_pCFlag->value()) flags |= 0x01; F = flags; - // Get value of Breakpoint 1 - pStr = cpuregs_ctrl.pBreak1->value(); - if (pStr[0] != 0) - { - val = str_to_i(pStr); - cpuregs_ctrl.breakAddr[0] = val; - } - else - cpuregs_ctrl.breakAddr[0] = -1; + check_breakpoint_entries(); +} - // Get value of Breakpoint 2 - pStr = cpuregs_ctrl.pBreak2->value(); - if (pStr[0] != 0) - { - val = str_to_i(pStr); - cpuregs_ctrl.breakAddr[1] = val; - } - else - cpuregs_ctrl.breakAddr[1] = -1; +/* +============================================================================ +Callback routine to redraw the trace and stack areas +============================================================================ +*/ +int build_trace_line(int line, char* lineStr) +{ + char str[100], flags[20]; + int y, len, last_pc; + cpu_trace_data_t* pTrace = &gcpuw->m_pTraceData[line]; - // Get value of Breakpoint 3 - pStr = cpuregs_ctrl.pBreak3->value(); - if (pStr[0] != 0) - { - val = str_to_i(pStr); - cpuregs_ctrl.breakAddr[2] = val; - } - else - cpuregs_ctrl.breakAddr[2] = -1; + // Disassemble the opcode + last_pc = pTrace->pc + cpu_dis.DisassembleLine(pTrace->pc, (unsigned char) + pTrace->opcode, pTrace->operand, lineStr); - // Get value of Breakpoint 4 - pStr = cpuregs_ctrl.pBreak4->value(); - if (pStr[0] != 0) - { - val = str_to_i(pStr); - cpuregs_ctrl.breakAddr[3] = val; - } - else - cpuregs_ctrl.breakAddr[3] = -1; + // Append spaces after opcode + len = 20 - strlen(lineStr); + for (y = 0; y < len; y++) + strcat(lineStr, " "); - // Check if any breakpoints set - for (x = 0; x < 4; x++) - if (cpuregs_ctrl.breakAddr[x] != -1) - break; + // Format flags string + unsigned char fl = pTrace->af & 0xFF; + sprintf(flags, "%c%c%c%c%c%c%c%c", fl & SF_BIT ?'S':' ', fl & ZF_BIT ?'Z':' ', fl & TS_BIT ?'T':' ', + fl & AC_BIT ? 'A':' ', fl & PF_BIT ? 'P':' ', fl & OV_BIT ? 'O':' ', fl & XF_BIT ? 'X':' ', + fl & CF_BIT ? 'C':' '); - // If no breakpoints set, restore old monitor frequency - if (x == 4) - { - if (cpuregs_ctrl.breakMonitorFreq != 0) - gSaveFreq = cpuregs_ctrl.breakMonitorFreq; - } - else - { - if (cpuregs_ctrl.breakMonitorFreq == 0) - cpuregs_ctrl.breakMonitorFreq = gSaveFreq; - gSaveFreq = 1; - gDebugMonitorFreq = 1; - } + // Append regs after opcode + sprintf(str, "A:%02X %s B:%02X C:%02X D:%02X E:%02X H:%02X L:%02X SP:%02X", + pTrace->af >> 8, flags, pTrace->bc >> 8, pTrace->bc & 0xFF, pTrace->de >> 8, + pTrace->de & 0xFF, pTrace->hl >> 8, pTrace->de & 0xFF, pTrace->sp); + strcat(lineStr, str); - cpuregs_ctrl.breakEnable[0] = !cpuregs_ctrl.pBreakDisable1->value(); - cpuregs_ctrl.breakEnable[1] = !cpuregs_ctrl.pBreakDisable2->value(); - cpuregs_ctrl.breakEnable[2] = !cpuregs_ctrl.pBreakDisable3->value(); - cpuregs_ctrl.breakEnable[3] = !cpuregs_ctrl.pBreakDisable4->value(); + return last_pc; } /* @@ -388,40 +458,222 @@ void get_reg_edits(void) Callback routine to redraw the trace and stack areas ============================================================================ */ -void cb_redraw_trace(Fl_Widget* w, void*) +void cb_redraw_trace(Fl_Widget* w, void* pOpaque) { - int x, draw; - char str[10]; + int x, draw, lines, last_pc, last_sp; + char lineStr[120], str[100]; + int trace_top = gcpuw->m_pTraceBox->y() + gcpuw->m_fontHeight - 4; + int lookahead = 0; + // Make our window current for drawing gcpuw->make_current(); // Clear rectangle fl_color(FL_GRAY); - fl_rectf(25, 205+MENU_HEIGHT, 510, 115); - fl_rectf(555, 205+MENU_HEIGHT, 54, 115); + fl_rectf(gcpuw->m_pTraceBox->x()+3, gcpuw->m_pTraceBox->y()+3, + gcpuw->m_pTraceBox->w()-6, gcpuw->m_pTraceBox->h()-6); + fl_rectf(gcpuw->m_pStackBox->x()+3, gcpuw->m_pStackBox->y()+3, + gcpuw->m_pStackBox->w()-6, gcpuw->m_pStackBox->h()-6); + + lines = gcpuw->m_pTraceBox->h() / gcpuw->m_fontHeight; // Select 11 point Courier font - fl_font(FL_COURIER,11); + fl_font(FL_COURIER, gcpuw->m_fontSize); fl_color(FL_BLACK); - // Determine first trace to draw - draw = cpuregs_ctrl.iInstTraceHead; - for (x = 0; x < 8; x++) + // Initialize last_sp and last_pc in case trace is clear + last_sp = SP; + last_pc = PC; + + // Draw either real-time (sampled every so often) data if stopped + // or actual address-by-address data if we are stopped + if (!gStopped) + { + // Determine first trace to draw + draw = gcpuw->m_iInstTraceHead - lines; + if (draw < 0) + draw += 64; + for (x = 0; x < lines; x++) + { + // Draw the Stack + sprintf(str, "0x%02X", get_memory8(SP+x)); + fl_draw(str, gcpuw->m_pStackBox->x()+10, trace_top+x*gcpuw->m_fontHeight); + + // Now draw the Instruction Trace + if (x == lines-1) + fl_font(FL_COURIER_BOLD, gcpuw->m_fontSize); + fl_push_clip(gcpuw->m_pTraceBox->x(), gcpuw->m_pTraceBox->y(), + gcpuw->m_pTraceBox->w()-3, gcpuw->m_pTraceBox->h()); + fl_draw(gcpuw->m_sInstTrace[draw], 25, trace_top+x*gcpuw->m_fontHeight); + fl_pop_clip(); + if (++draw >= 64) + draw = 0; + } + } + else { - // Draw the Stack - sprintf(str, "0x%02X", get_memory8(SP+x)); - fl_draw(str, 560, 212+MENU_HEIGHT+x*15); + // Draw actual trace information + int firstLine = gcpuw->m_pScroll->value(); + if (firstLine < 0) + firstLine = 0; + int draw = gcpuw->m_iTraceHead + firstLine; + if (draw >= gcpuw->m_traceAvail) + draw -= gcpuw->m_traceAvail; + last_sp = SP; + + for (x = 0; x < lines; x++) + { + // Draw the Stack + sprintf(str, "0x%02X", get_memory8(SP+x)); + fl_draw(str, gcpuw->m_pStackBox->x()+10, trace_top+x*gcpuw->m_fontHeight); - // Now draw the Instruction Trace - if (x == 7) - fl_font(FL_COURIER_BOLD, 11); - fl_draw(cpuregs_ctrl.sInstTrace[draw], 25, 212+MENU_HEIGHT+x*15); - if (++draw >= 8) - draw = 0; + // Now draw the Instruction Trace + if (x + firstLine < gcpuw->m_traceAvail) + { + cpu_trace_data_t* pTrace = &gcpuw->m_pTraceData[draw]; + unsigned char fl = pTrace->af & 0xFF; + + /* Build the trace text */ + last_pc = build_trace_line(draw, &lineStr[0]); + + /* If on the execution line, make the font bold */ + if (x+firstLine == gcpuw->m_traceAvail-1) + fl_font(FL_COURIER_BOLD, gcpuw->m_fontSize); + + // Finally, draw the trace on the window + fl_push_clip(gcpuw->m_pTraceBox->x(), gcpuw->m_pTraceBox->y(), + gcpuw->m_pTraceBox->w()-3, gcpuw->m_pTraceBox->h()); + fl_draw(lineStr, 25, trace_top+x*gcpuw->m_fontHeight); + fl_pop_clip(); + if (++draw >= gcpuw->m_traceAvail) + draw = 0; + + // If we just drew the execution line, do special processing + if (x+firstLine == gcpuw->m_traceAvail-1) + { + // Change back to normal font + fl_font(FL_COURIER, gcpuw->m_fontSize); + + // Search opcode for conditional branching + if (((strncmp(&lineStr[7], "JZ", 2) == 0) || + (strncmp(&lineStr[7], "CZ", 2) == 0)) && + (fl & ZF_BIT)) + last_pc = str_to_i(&lineStr[10]); + else if (((strncmp(&lineStr[7], "JNZ", 3) == 0) || + (strncmp(&lineStr[7], "CNZ", 3) == 0)) && + !(fl & ZF_BIT)) + last_pc = str_to_i(&lineStr[11]); + else if (((strncmp(&lineStr[7], "JC", 2) == 0) || + (strncmp(&lineStr[7], "CC", 2) == 0)) && + (fl & CF_BIT)) + last_pc = str_to_i(&lineStr[10]); + else if (((strncmp(&lineStr[7], "JNC", 3) == 0) || + (strncmp(&lineStr[7], "CNC", 3) == 0)) && + !(fl & CF_BIT)) + last_pc = str_to_i(&lineStr[11]); + else if (((strncmp(&lineStr[7], "JP", 2) == 0) || + (strncmp(&lineStr[7], "CP", 2) == 0)) && + (fl & SF_BIT)) + last_pc = str_to_i(&lineStr[10]); + else if (((strncmp(&lineStr[7], "JM ", 3) == 0) || + (strncmp(&lineStr[7], "CM ", 3) == 0)) && + !(fl & SF_BIT)) + last_pc = str_to_i(&lineStr[10]); + else if (((strncmp(&lineStr[7], "JPE", 3) == 0) || + (strncmp(&lineStr[7], "CPE", 3) == 0)) && + (fl & PF_BIT)) + last_pc = str_to_i(&lineStr[11]); + else if (((strncmp(&lineStr[7], "JPO", 3) == 0) || + (strncmp(&lineStr[7], "CPO", 3) == 0)) && + !(fl & PF_BIT)) + last_pc = str_to_i(&lineStr[11]); + + // Conditional RETurns + else if ((strncmp(&lineStr[7], "RC", 2) == 0) && (fl & CF_BIT)) + last_pc = get_memory16(pTrace->sp); + else if ((strncmp(&lineStr[7], "RNC", 3) == 0) && !(fl & CF_BIT)) + last_pc = get_memory16(pTrace->sp); + else if ((strncmp(&lineStr[7], "RZ", 2) == 0) && (fl & ZF_BIT)) + last_pc = get_memory16(pTrace->sp); + else if ((strncmp(&lineStr[7], "RNZ", 3) == 0) && !(fl & ZF_BIT)) + last_pc = get_memory16(pTrace->sp); + else if ((strncmp(&lineStr[7], "RP", 2) == 0) && (fl & SF_BIT)) + last_pc = get_memory16(pTrace->sp); + else if ((strncmp(&lineStr[7], "RM", 2) == 0) && !(fl & SF_BIT)) + last_pc = get_memory16(pTrace->sp); + else if ((strncmp(&lineStr[7], "RPE", 3) == 0) && (fl & PF_BIT)) + last_pc = get_memory16(pTrace->sp); + else if ((strncmp(&lineStr[7], "RPO", 3) == 0) && !(fl & PF_BIT)) + last_pc = get_memory16(pTrace->sp); + + else if (strncmp(&lineStr[7], "PCHL", 4) == 0) + last_pc = HL; + } + } + else + { + // Check opcode for various changes to the PC + if (strncmp(&lineStr[7], "CALL", 4) == 0) + last_pc = str_to_i(&lineStr[12]); + else if (strncmp(&lineStr[7], "JMP", 3) == 0) + last_pc = str_to_i(&lineStr[11]); + else if (strncmp(&lineStr[7], "POP", 3) == 0) + last_sp += 2; + else if (strncmp(&lineStr[7], "RET", 3) == 0) + { + last_pc = get_memory16(last_sp); + last_sp += 2; + } + else if (strncmp(&lineStr[7], "RST", 3) == 0) + { + last_sp -= 2; + last_pc = str_to_i(&lineStr[11]) * 8; + } + + // If trace is empty, then make 1st (current) inst bold + if (x == 0) + fl_font(FL_COURIER_BOLD, gcpuw->m_fontSize); + // Disassemble the next line that hasn't executed yet + last_pc += cpu_dis.DisassembleLine(last_pc, lineStr); + if (lookahead++ < 4) + fl_draw(lineStr, 25, trace_top+x*gcpuw->m_fontHeight); + + if (x == 0) + fl_font(FL_COURIER, gcpuw->m_fontSize); + } + } } } +/* +============================================================================ +Callback for the trace scroll bar +============================================================================ +*/ +void cb_scrollbar (Fl_Widget* w, void*) +{ + int size = (int) (gcpuw->m_pScroll->h() / gcpuw->m_fontHeight); + int max_size = gcpuw->m_traceAvail-size+4; + + // Update the max size of the scrollbar + if (gcpuw->m_traceAvail < gcpuw->m_traceCount) + max_size++; + if (max_size < 0) + max_size = 4; + gcpuw->m_pScroll->maximum(max_size); + gcpuw->m_pScroll->linesize(1); + if (gcpuw->m_traceAvail > 0) + { + gcpuw->m_pScroll->step(size / gcpuw->m_traceAvail); + gcpuw->m_pScroll->slider_size((double) size/ (double) gcpuw->m_traceAvail); + } + else + gcpuw->m_pScroll->slider_size(1.0); + + cb_redraw_trace(NULL, NULL); +} + /* ============================================================================ Callback routine for receiving serial port status updates @@ -436,7 +688,7 @@ void debug_monitor_cb(int fMonType, unsigned char data) unsigned char get_m() { - if (gReMem) + if (gReMem & !gRex) return (gMemory[gIndex[HL]][HL & 0x3FF]); else return gBaseMemory[HL]; @@ -448,49 +700,49 @@ activate_controls: This routine activates all the CPU controls except the STOP button, which it deactivates. ============================================================================ */ -void activate_controls() +void VTCpuRegs::activate_controls(void) { // Change activation state of processor controls - cpuregs_ctrl.pStop->deactivate(); - cpuregs_ctrl.pStep->activate(); - cpuregs_ctrl.pStepOver->activate(); - cpuregs_ctrl.pRun->activate(); - cpuregs_ctrl.pRedraw->activate(); + m_pStop->deactivate(); + m_pStep->activate(); + m_pStepOver->activate(); + m_pRun->activate(); + m_pScroll->activate(); // Activate the edit fields to allow register updates - cpuregs_ctrl.pRegA->activate(); - cpuregs_ctrl.pRegB->activate(); - cpuregs_ctrl.pRegC->activate(); - cpuregs_ctrl.pRegD->activate(); - cpuregs_ctrl.pRegE->activate(); - cpuregs_ctrl.pRegH->activate(); - cpuregs_ctrl.pRegL->activate(); - cpuregs_ctrl.pRegPC->activate(); - cpuregs_ctrl.pRegSP->activate(); - cpuregs_ctrl.pRegBC->activate(); - cpuregs_ctrl.pRegDE->activate(); - cpuregs_ctrl.pRegHL->activate(); - cpuregs_ctrl.pRegM->activate(); + m_pRegA->activate(); + m_pRegB->activate(); + m_pRegC->activate(); + m_pRegD->activate(); + m_pRegE->activate(); + m_pRegH->activate(); + m_pRegL->activate(); + m_pRegPC->activate(); + m_pRegSP->activate(); + m_pRegBC->activate(); + m_pRegDE->activate(); + m_pRegHL->activate(); + m_pRegM->activate(); // Activate Flags - cpuregs_ctrl.pSFlag->activate(); - cpuregs_ctrl.pZFlag->activate(); - cpuregs_ctrl.pCFlag->activate(); - cpuregs_ctrl.pTSFlag->activate(); - cpuregs_ctrl.pACFlag->activate(); - cpuregs_ctrl.pPFlag->activate(); - cpuregs_ctrl.pOVFlag->activate(); - cpuregs_ctrl.pXFlag->activate(); + m_pSFlag->activate(); + m_pZFlag->activate(); + m_pCFlag->activate(); + m_pTSFlag->activate(); + m_pACFlag->activate(); + m_pPFlag->activate(); + m_pOVFlag->activate(); + m_pXFlag->activate(); // Activate Breakpoints - cpuregs_ctrl.pBreak1->activate(); - cpuregs_ctrl.pBreak2->activate(); - cpuregs_ctrl.pBreak3->activate(); - cpuregs_ctrl.pBreak4->activate(); - cpuregs_ctrl.pBreakDisable1->activate(); - cpuregs_ctrl.pBreakDisable2->activate(); - cpuregs_ctrl.pBreakDisable3->activate(); - cpuregs_ctrl.pBreakDisable4->activate(); + m_pBreak1->activate(); + m_pBreak2->activate(); + m_pBreak3->activate(); + m_pBreak4->activate(); + m_pBreakDisable1->activate(); + m_pBreakDisable2->activate(); + m_pBreakDisable3->activate(); + m_pBreakDisable4->activate(); } void clear_trace(void) @@ -498,7 +750,29 @@ void clear_trace(void) int x; for (x = 0; x < 8; x++) - cpuregs_ctrl.sInstTrace[x][0] = 0; + gcpuw->m_sInstTrace[x][0] = 0; +} + +void inline trace_instruction(void) +{ + if (gcpuw->m_pTraceData != NULL) + { + int idx = gcpuw->m_iTraceHead++; + if (gcpuw->m_iTraceHead >= gcpuw->m_traceCount) + gcpuw->m_iTraceHead = 0; + gcpuw->m_pTraceData[idx].pc = PC; + gcpuw->m_pTraceData[idx].sp = SP; + gcpuw->m_pTraceData[idx].hl = HL; + gcpuw->m_pTraceData[idx].de = DE; + gcpuw->m_pTraceData[idx].bc = BC; + gcpuw->m_pTraceData[idx].af = AF; + gcpuw->m_pTraceData[idx].opcode = get_memory8(PC); + gcpuw->m_pTraceData[idx].operand = get_memory16(PC+1); + } + + /* Increment the available trace count until it reaches the max */ + if (gcpuw->m_traceAvail < gcpuw->m_traceCount) + gcpuw->m_traceAvail++; } /* @@ -519,23 +793,30 @@ void debug_cpuregs_cb (int reason) { for (x = 0; x < 5; x++) { - if ((PC == cpuregs_ctrl.breakAddr[x]) && (cpuregs_ctrl.breakEnable[x])) + if ((PC == gcpuw->m_breakAddr[x]) && (gcpuw->m_breakEnable[x])) { - activate_controls(); + gcpuw->activate_controls(); gStopped = 1; // Clear 'step over' breakpoint if (x == 4) - cpuregs_ctrl.breakAddr[x] = -1; + gcpuw->m_breakAddr[x] = -1; else clear_trace(); + + // Scroll to bottom of window if needed + if (gcpuw->m_autoScroll) + gcpuw->ScrollToBottom(); } } } + /* Trace this instruction */ + trace_instruction(); + if (!gStopped) { - if (cpuregs_ctrl.breakAddr[4] != -1) + if (gcpuw->m_breakAddr[4] != -1) return; if (++gDebugCount < gDebugMonitorFreq) return; @@ -544,76 +825,76 @@ void debug_cpuregs_cb (int reason) gDebugCount = 0; // Update PC edit box - sprintf(str, cpuregs_ctrl.sPCfmt, PC); - cpuregs_ctrl.pRegPC->value(str); + sprintf(str, gcpuw->m_sPCfmt, PC); + gcpuw->m_pRegPC->value(str); // Update SP edit box - sprintf(str, cpuregs_ctrl.sSPfmt, SP); - cpuregs_ctrl.pRegSP->value(str); + sprintf(str, gcpuw->m_sSPfmt, SP); + gcpuw->m_pRegSP->value(str); // Update A edit box - sprintf(str, cpuregs_ctrl.sAfmt, A); - cpuregs_ctrl.pRegA->value(str); + sprintf(str, gcpuw->m_sAfmt, A); + gcpuw->m_pRegA->value(str); // Update B edit box - sprintf(str, cpuregs_ctrl.sBfmt, B); - cpuregs_ctrl.pRegB->value(str); + sprintf(str, gcpuw->m_sBfmt, B); + gcpuw->m_pRegB->value(str); // Update C edit box - sprintf(str, cpuregs_ctrl.sCfmt, C); - cpuregs_ctrl.pRegC->value(str); + sprintf(str, gcpuw->m_sCfmt, C); + gcpuw->m_pRegC->value(str); // Update D edit box - sprintf(str, cpuregs_ctrl.sDfmt, D); - cpuregs_ctrl.pRegD->value(str); + sprintf(str, gcpuw->m_sDfmt, D); + gcpuw->m_pRegD->value(str); // Update E edit box - sprintf(str, cpuregs_ctrl.sEfmt, E); - cpuregs_ctrl.pRegE->value(str); + sprintf(str, gcpuw->m_sEfmt, E); + gcpuw->m_pRegE->value(str); // Update H edit box - sprintf(str, cpuregs_ctrl.sHfmt, H); - cpuregs_ctrl.pRegH->value(str); + sprintf(str, gcpuw->m_sHfmt, H); + gcpuw->m_pRegH->value(str); // Update L edit box - sprintf(str, cpuregs_ctrl.sLfmt, L); - cpuregs_ctrl.pRegL->value(str); + sprintf(str, gcpuw->m_sLfmt, L); + gcpuw->m_pRegL->value(str); // Update BC edit box - sprintf(str, cpuregs_ctrl.sBCfmt, BC); - cpuregs_ctrl.pRegBC->value(str); + sprintf(str, gcpuw->m_sBCfmt, BC); + gcpuw->m_pRegBC->value(str); // Update DE edit box - sprintf(str, cpuregs_ctrl.sDEfmt, DE); - cpuregs_ctrl.pRegDE->value(str); + sprintf(str, gcpuw->m_sDEfmt, DE); + gcpuw->m_pRegDE->value(str); // Update HL edit box - sprintf(str, cpuregs_ctrl.sHLfmt, HL); - cpuregs_ctrl.pRegHL->value(str); + sprintf(str, gcpuw->m_sHLfmt, HL); + gcpuw->m_pRegHL->value(str); // Update M edit box - sprintf(str, cpuregs_ctrl.sMfmt, get_m()); - cpuregs_ctrl.pRegM->value(str); + sprintf(str, gcpuw->m_sMfmt, get_m()); + gcpuw->m_pRegM->value(str); // Update flags - cpuregs_ctrl.pSFlag->value(SF); - cpuregs_ctrl.pZFlag->value(ZF); - cpuregs_ctrl.pTSFlag->value(TS); - cpuregs_ctrl.pACFlag->value(AC); - cpuregs_ctrl.pPFlag->value(PF); - cpuregs_ctrl.pOVFlag->value(OV); - cpuregs_ctrl.pXFlag->value(XF); - cpuregs_ctrl.pCFlag->value(CF); + gcpuw->m_pSFlag->value(SF); + gcpuw->m_pZFlag->value(ZF); + gcpuw->m_pTSFlag->value(TS); + gcpuw->m_pACFlag->value(AC); + gcpuw->m_pPFlag->value(PF); + gcpuw->m_pOVFlag->value(OV); + gcpuw->m_pXFlag->value(XF); + gcpuw->m_pCFlag->value(CF); if (!gDisableRealtimeTrace || (gStopCountdown != 0) || gStopped) { // Disassemble 1 instruction - cpu_dis.DisassembleLine(PC, cpuregs_ctrl.sInstTrace[cpuregs_ctrl.iInstTraceHead]); + cpu_dis.DisassembleLine(PC, gcpuw->m_sInstTrace[gcpuw->m_iInstTraceHead]); // Append spaces after opcode - len = 20 - strlen(cpuregs_ctrl.sInstTrace[cpuregs_ctrl.iInstTraceHead]); + len = 20 - strlen(gcpuw->m_sInstTrace[gcpuw->m_iInstTraceHead]); for (x = 0; x < len; x++) - strcat(cpuregs_ctrl.sInstTrace[cpuregs_ctrl.iInstTraceHead], " "); + strcat(gcpuw->m_sInstTrace[gcpuw->m_iInstTraceHead], " "); // Format flags string sprintf(flags, "%c%c%c%c%c%c%c%c", SF?'S':' ', ZF?'Z':' ', TS?'T':' ',AC?'A':' ', @@ -622,13 +903,19 @@ void debug_cpuregs_cb (int reason) // Append regs after opcode sprintf(str, "A:%02X %s B:%02X C:%02X D:%02X E:%02X H:%02X L:%02X SP:%02X", A, flags, B, C, D, E, H, L, SP); - strcat(cpuregs_ctrl.sInstTrace[cpuregs_ctrl.iInstTraceHead++], str); + strcat(gcpuw->m_sInstTrace[gcpuw->m_iInstTraceHead++], str); - if (cpuregs_ctrl.iInstTraceHead >= 8) - cpuregs_ctrl.iInstTraceHead= 0; + if (gcpuw->m_iInstTraceHead >= 64) + gcpuw->m_iInstTraceHead= 0; // Update Trace data on window cb_redraw_trace(NULL, NULL); + + // Update monitor frequency based on cpu speed + if (fullspeed == 0) + gDebugMonitorFreq = 8192; + else + gDebugMonitorFreq = 32768; } // Check if processor stop requested @@ -642,6 +929,13 @@ void debug_cpuregs_cb (int reason) gStopped = 1; gDebugMonitorFreq = gSaveFreq; gStopCountdown = 0; + + // Scroll to bottom of window if needed + if (gcpuw->m_autoScroll) + gcpuw->ScrollToBottom(); + + // Redraw the trace window + cb_redraw_trace(NULL, NULL); } } else @@ -655,49 +949,49 @@ void debug_cpuregs_cb (int reason) Routine to deactivate the debugging controls ============================================================================ */ -void deactivate_controls(void) +void VTCpuRegs::deactivate_controls(void) { // Change activation state of processor controls - cpuregs_ctrl.pStop->activate(); - cpuregs_ctrl.pStep->deactivate(); - cpuregs_ctrl.pStepOver->deactivate(); - cpuregs_ctrl.pRun->deactivate(); - cpuregs_ctrl.pRedraw->deactivate(); + m_pStop->activate(); + m_pStep->deactivate(); + m_pStepOver->deactivate(); + m_pRun->deactivate(); + m_pScroll->deactivate(); // Deactivate the edit fields to allow register updates - cpuregs_ctrl.pRegA->deactivate(); - cpuregs_ctrl.pRegB->deactivate(); - cpuregs_ctrl.pRegC->deactivate(); - cpuregs_ctrl.pRegD->deactivate(); - cpuregs_ctrl.pRegE->deactivate(); - cpuregs_ctrl.pRegH->deactivate(); - cpuregs_ctrl.pRegL->deactivate(); - cpuregs_ctrl.pRegPC->deactivate(); - cpuregs_ctrl.pRegSP->deactivate(); - cpuregs_ctrl.pRegBC->deactivate(); - cpuregs_ctrl.pRegDE->deactivate(); - cpuregs_ctrl.pRegHL->deactivate(); - cpuregs_ctrl.pRegM->deactivate(); + m_pRegA->deactivate(); + m_pRegB->deactivate(); + m_pRegC->deactivate(); + m_pRegD->deactivate(); + m_pRegE->deactivate(); + m_pRegH->deactivate(); + m_pRegL->deactivate(); + m_pRegPC->deactivate(); + m_pRegSP->deactivate(); + m_pRegBC->deactivate(); + m_pRegDE->deactivate(); + m_pRegHL->deactivate(); + m_pRegM->deactivate(); // Deactivate Flags - cpuregs_ctrl.pSFlag->deactivate(); - cpuregs_ctrl.pZFlag->deactivate(); - cpuregs_ctrl.pCFlag->deactivate(); - cpuregs_ctrl.pTSFlag->deactivate(); - cpuregs_ctrl.pACFlag->deactivate(); - cpuregs_ctrl.pPFlag->deactivate(); - cpuregs_ctrl.pOVFlag->deactivate(); - cpuregs_ctrl.pXFlag->deactivate(); + m_pSFlag->deactivate(); + m_pZFlag->deactivate(); + m_pCFlag->deactivate(); + m_pTSFlag->deactivate(); + m_pACFlag->deactivate(); + m_pPFlag->deactivate(); + m_pOVFlag->deactivate(); + m_pXFlag->deactivate(); // Deactivate breakpoints - cpuregs_ctrl.pBreak1->deactivate(); - cpuregs_ctrl.pBreak2->deactivate(); - cpuregs_ctrl.pBreak3->deactivate(); - cpuregs_ctrl.pBreak4->deactivate(); - cpuregs_ctrl.pBreakDisable1->deactivate(); - cpuregs_ctrl.pBreakDisable2->deactivate(); - cpuregs_ctrl.pBreakDisable3->deactivate(); - cpuregs_ctrl.pBreakDisable4->deactivate(); + m_pBreak1->deactivate(); + m_pBreak2->deactivate(); + m_pBreak3->deactivate(); + m_pBreak4->deactivate(); + m_pBreakDisable1->deactivate(); + m_pBreakDisable2->deactivate(); + m_pBreakDisable3->deactivate(); + m_pBreakDisable4->deactivate(); } /* @@ -705,35 +999,42 @@ void deactivate_controls(void) Routine to handle 'Step Over' button ============================================================================ */ -void cb_debug_step_over(Fl_Widget* w, void*) +void cb_debug_step_over(Fl_Widget* w, void* pOpaque) { - int inst; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; + int inst; // Get Register updates - get_reg_edits(); + pCpuRegs->get_reg_edits(); // Determine the 'step over' breakpoint location inst = get_memory8(PC); if (((inst & 0xC7) == 0xC4) || (inst == 0xCD)) { - cpuregs_ctrl.breakAddr[4] = PC+3; + pCpuRegs->m_breakAddr[4] = PC+3; } else if ((inst & 0xC7) == 0xC7) { if ((inst == 0xCF) || (inst == 0xFF)) - cpuregs_ctrl.breakAddr[4] = PC+2; + pCpuRegs->m_breakAddr[4] = PC+2; else - cpuregs_ctrl.breakAddr[4] = PC+1; + pCpuRegs->m_breakAddr[4] = PC+1; } else { // Single step the processor gSingleStep = 1; + + // If auto scroll is enabled, then scroll to th bottom + if (pCpuRegs->m_autoScroll) + pCpuRegs->ScrollToBottom(); + return; } - // Deactivate the controls -// deactivate_controls(); + // If auto scroll is enabled, then scroll to th bottom + if (pCpuRegs->m_autoScroll) + pCpuRegs->ScrollToBottom(); // Start the processor gStopped = 0; @@ -744,12 +1045,22 @@ void cb_debug_step_over(Fl_Widget* w, void*) Routine to handle Stop button ============================================================================ */ -void cb_debug_stop(Fl_Widget* w, void*) +void cb_debug_stop(Fl_Widget* w, void* pOpaque) { - activate_controls(); + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; + + // Activate the controls + pCpuRegs->activate_controls(); + + // Update the scrollbar + cb_scrollbar(pCpuRegs->m_pScroll, pOpaque); + + // If auto scroll is enabled, then scroll to the bottom + if (pCpuRegs->m_autoScroll) + pCpuRegs->ScrollToBottom(); // Stop the processor - gStopCountdown = 8; + gStopCountdown = 1; gSaveFreq = gDebugMonitorFreq; gDebugMonitorFreq = 1; } @@ -759,10 +1070,16 @@ void cb_debug_stop(Fl_Widget* w, void*) Routine to handle Step button ============================================================================ */ -void cb_debug_step(Fl_Widget* w, void*) +void cb_debug_step(Fl_Widget* w, void* pOpaque) { + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; + // Get Register updates - get_reg_edits(); + pCpuRegs->get_reg_edits(); + + // If auto scroll is enabled, then scroll to th bottom + if (pCpuRegs->m_autoScroll) + pCpuRegs->ScrollToBottom(); // Single step the processor gSingleStep = 1; @@ -773,16 +1090,21 @@ void cb_debug_step(Fl_Widget* w, void*) Routine to handle Run button ============================================================================ */ -void cb_debug_run(Fl_Widget* w, void*) +void cb_debug_run(Fl_Widget* w, void* pOpaque) { + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; + // Deactivate the debug controls - deactivate_controls(); + pCpuRegs->deactivate_controls(); // Get Register updates - get_reg_edits(); + pCpuRegs->get_reg_edits(); // Start the processor gStopped = 0; + + // Redraw the trace in case real-time trace is off + gcpuw->redraw(); } /* @@ -823,27 +1145,28 @@ int remote_cpureg_step(void) Routine to handle Change to PC edit field ============================================================================ */ -void cb_reg_pc_changed(Fl_Widget* w, void*) +void cb_reg_pc_changed(Fl_Widget* w, void* pOpaque) { int new_pc; const char *pStr; int trace_tail; char str[120], flags[20]; int len, x; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - pStr = cpuregs_ctrl.pRegPC->value(); + pStr = pCpuRegs->m_pRegPC->value(); new_pc = str_to_i(pStr); - trace_tail = cpuregs_ctrl.iInstTraceHead - 1; + trace_tail = pCpuRegs->m_iInstTraceHead - 1; if (trace_tail < 0) trace_tail = 7; // Disassemble 1 instruction - cpu_dis.DisassembleLine(new_pc, cpuregs_ctrl.sInstTrace[trace_tail]); + cpu_dis.DisassembleLine(new_pc, pCpuRegs->m_sInstTrace[trace_tail]); // Append spaces after opcode - len = 20 - strlen(cpuregs_ctrl.sInstTrace[trace_tail]); + len = 20 - strlen(pCpuRegs->m_sInstTrace[trace_tail]); for (x = 0; x < len; x++) - strcat(cpuregs_ctrl.sInstTrace[trace_tail], " "); + strcat(pCpuRegs->m_sInstTrace[trace_tail], " "); // Format flags string sprintf(flags, "%c%c%c%c%c%c%c%c", SF?'S':' ', ZF?'Z':' ', TS?'T':' ',AC?'A':' ', @@ -852,7 +1175,7 @@ void cb_reg_pc_changed(Fl_Widget* w, void*) // Append regs after opcode sprintf(str, "A:%02X %s B:%02X C:%02X D:%02X E:%02X H:%02X L:%02X SP:%02X", A, flags, B, C, D, E, H, L, SP); - strcat(cpuregs_ctrl.sInstTrace[trace_tail], str); + strcat(pCpuRegs->m_sInstTrace[trace_tail], str); // Update Trace data on window cb_redraw_trace(NULL, NULL); @@ -863,25 +1186,26 @@ void cb_reg_pc_changed(Fl_Widget* w, void*) Routine to handle Change to BC edit field ============================================================================ */ -void cb_reg_bc_changed(Fl_Widget* w, void*) +void cb_reg_bc_changed(Fl_Widget* w, void* pOpaque) { int new_bc; const char *pStr; char str[20]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - pStr = cpuregs_ctrl.pRegBC->value(); + pStr = pCpuRegs->m_pRegBC->value(); new_bc = str_to_i(pStr); B = (new_bc >> 8) & 0xFF; C = new_bc & 0xFF; // Update B edit box - sprintf(str, cpuregs_ctrl.sBfmt, B); - cpuregs_ctrl.pRegB->value(str); + sprintf(str, pCpuRegs->m_sBfmt, B); + pCpuRegs->m_pRegB->value(str); // Update C edit box - sprintf(str, cpuregs_ctrl.sCfmt, C); - cpuregs_ctrl.pRegC->value(str); + sprintf(str, pCpuRegs->m_sCfmt, C); + pCpuRegs->m_pRegC->value(str); } /* @@ -889,21 +1213,22 @@ void cb_reg_bc_changed(Fl_Widget* w, void*) Routine to handle Change to B edit field ============================================================================ */ -void cb_reg_b_changed(Fl_Widget* w, void*) +void cb_reg_b_changed(Fl_Widget* w, void* pOpaque) { const char *pStr; char str[20]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - pStr = cpuregs_ctrl.pRegB->value(); + pStr = pCpuRegs->m_pRegB->value(); B = str_to_i(pStr); // Update B edit box - sprintf(str, cpuregs_ctrl.sBfmt, B); - cpuregs_ctrl.pRegB->value(str); + sprintf(str, pCpuRegs->m_sBfmt, B); + pCpuRegs->m_pRegB->value(str); // Update BC edit box - sprintf(str, cpuregs_ctrl.sBCfmt, BC); - cpuregs_ctrl.pRegBC->value(str); + sprintf(str, pCpuRegs->m_sBCfmt, BC); + pCpuRegs->m_pRegBC->value(str); } /* @@ -911,21 +1236,22 @@ void cb_reg_b_changed(Fl_Widget* w, void*) Routine to handle Change to C edit field ============================================================================ */ -void cb_reg_c_changed(Fl_Widget* w, void*) +void cb_reg_c_changed(Fl_Widget* w, void* pOpaque) { const char *pStr; char str[20]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - pStr = cpuregs_ctrl.pRegC->value(); + pStr = pCpuRegs->m_pRegC->value(); C = str_to_i(pStr); // Update C edit box - sprintf(str, cpuregs_ctrl.sCfmt, C); - cpuregs_ctrl.pRegC->value(str); + sprintf(str, pCpuRegs->m_sCfmt, C); + pCpuRegs->m_pRegC->value(str); // Update BC edit box - sprintf(str, cpuregs_ctrl.sBCfmt, BC); - cpuregs_ctrl.pRegBC->value(str); + sprintf(str, pCpuRegs->m_sBCfmt, BC); + pCpuRegs->m_pRegBC->value(str); } /* @@ -933,25 +1259,26 @@ void cb_reg_c_changed(Fl_Widget* w, void*) Routine to handle Change to DE edit field ============================================================================ */ -void cb_reg_de_changed(Fl_Widget* w, void*) +void cb_reg_de_changed(Fl_Widget* w, void* pOpaque) { int new_de; const char *pStr; char str[20]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - pStr = cpuregs_ctrl.pRegDE->value(); + pStr = pCpuRegs->m_pRegDE->value(); new_de = str_to_i(pStr); D = (new_de >> 8) & 0xFF; E = new_de & 0xFF; // Update D edit box - sprintf(str, cpuregs_ctrl.sDfmt, D); - cpuregs_ctrl.pRegD->value(str); + sprintf(str, pCpuRegs->m_sDfmt, D); + pCpuRegs->m_pRegD->value(str); // Update E edit box - sprintf(str, cpuregs_ctrl.sEfmt, E); - cpuregs_ctrl.pRegE->value(str); + sprintf(str, pCpuRegs->m_sEfmt, E); + pCpuRegs->m_pRegE->value(str); } /* @@ -959,21 +1286,22 @@ void cb_reg_de_changed(Fl_Widget* w, void*) Routine to handle Change to D edit field ============================================================================ */ -void cb_reg_d_changed(Fl_Widget* w, void*) +void cb_reg_d_changed(Fl_Widget* w, void* pOpaque) { const char *pStr; char str[20]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - pStr = cpuregs_ctrl.pRegD->value(); + pStr = pCpuRegs->m_pRegD->value(); D = str_to_i(pStr); // Update B edit box - sprintf(str, cpuregs_ctrl.sDfmt, D); - cpuregs_ctrl.pRegD->value(str); + sprintf(str, pCpuRegs->m_sDfmt, D); + pCpuRegs->m_pRegD->value(str); // Update BC edit box - sprintf(str, cpuregs_ctrl.sDEfmt, DE); - cpuregs_ctrl.pRegDE->value(str); + sprintf(str, pCpuRegs->m_sDEfmt, DE); + pCpuRegs->m_pRegDE->value(str); } /* @@ -981,21 +1309,22 @@ void cb_reg_d_changed(Fl_Widget* w, void*) Routine to handle Change to E edit field ============================================================================ */ -void cb_reg_e_changed(Fl_Widget* w, void*) +void cb_reg_e_changed(Fl_Widget* w, void* pOpaque) { const char *pStr; char str[20]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - pStr = cpuregs_ctrl.pRegE->value(); + pStr = pCpuRegs->m_pRegE->value(); E = str_to_i(pStr); // Update C edit box - sprintf(str, cpuregs_ctrl.sEfmt, E); - cpuregs_ctrl.pRegE->value(str); + sprintf(str, pCpuRegs->m_sEfmt, E); + pCpuRegs->m_pRegE->value(str); // Update DE edit box - sprintf(str, cpuregs_ctrl.sDEfmt, DE); - cpuregs_ctrl.pRegDE->value(str); + sprintf(str, pCpuRegs->m_sDEfmt, DE); + pCpuRegs->m_pRegDE->value(str); } /* @@ -1003,29 +1332,30 @@ void cb_reg_e_changed(Fl_Widget* w, void*) Routine to handle Change to HL edit field ============================================================================ */ -void cb_reg_hl_changed(Fl_Widget* w, void*) +void cb_reg_hl_changed(Fl_Widget* w, void* pOpaque) { int new_hl; const char *pStr; char str[20]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - pStr = cpuregs_ctrl.pRegHL->value(); + pStr = pCpuRegs->m_pRegHL->value(); new_hl = str_to_i(pStr); H = (new_hl >> 8) & 0xFF; L = new_hl & 0xFF; // Update H edit box - sprintf(str, cpuregs_ctrl.sHfmt, H); - cpuregs_ctrl.pRegH->value(str); + sprintf(str, pCpuRegs->m_sHfmt, H); + pCpuRegs->m_pRegH->value(str); // Update L edit box - sprintf(str, cpuregs_ctrl.sLfmt, L); - cpuregs_ctrl.pRegL->value(str); + sprintf(str, pCpuRegs->m_sLfmt, L); + pCpuRegs->m_pRegL->value(str); // Update M edit box - sprintf(str, cpuregs_ctrl.sMfmt, get_m()); - cpuregs_ctrl.pRegM->value(str); + sprintf(str, pCpuRegs->m_sMfmt, get_m()); + pCpuRegs->m_pRegM->value(str); } @@ -1034,25 +1364,26 @@ void cb_reg_hl_changed(Fl_Widget* w, void*) Routine to handle Change to H edit field ============================================================================ */ -void cb_reg_h_changed(Fl_Widget* w, void*) +void cb_reg_h_changed(Fl_Widget* w, void* pOpaque) { const char *pStr; char str[20]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - pStr = cpuregs_ctrl.pRegH->value(); + pStr = pCpuRegs->m_pRegH->value(); H = str_to_i(pStr); // Update H edit box - sprintf(str, cpuregs_ctrl.sHfmt, H); - cpuregs_ctrl.pRegH->value(str); + sprintf(str, pCpuRegs->m_sHfmt, H); + pCpuRegs->m_pRegH->value(str); // Update HL edit box - sprintf(str, cpuregs_ctrl.sHLfmt, HL); - cpuregs_ctrl.pRegHL->value(str); + sprintf(str, pCpuRegs->m_sHLfmt, HL); + pCpuRegs->m_pRegHL->value(str); // Update M edit box - sprintf(str, cpuregs_ctrl.sMfmt, get_m()); - cpuregs_ctrl.pRegM->value(str); + sprintf(str, pCpuRegs->m_sMfmt, get_m()); + pCpuRegs->m_pRegM->value(str); } @@ -1061,25 +1392,26 @@ void cb_reg_h_changed(Fl_Widget* w, void*) Routine to handle Change to L edit field ============================================================================ */ -void cb_reg_l_changed(Fl_Widget* w, void*) +void cb_reg_l_changed(Fl_Widget* w, void* pOpaque) { const char *pStr; char str[20]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - pStr = cpuregs_ctrl.pRegL->value(); + pStr = pCpuRegs->m_pRegL->value(); L = str_to_i(pStr); // Update H edit box - sprintf(str, cpuregs_ctrl.sLfmt, L); - cpuregs_ctrl.pRegL->value(str); + sprintf(str, pCpuRegs->m_sLfmt, L); + pCpuRegs->m_pRegL->value(str); // Update HL edit box - sprintf(str, cpuregs_ctrl.sHLfmt, HL); - cpuregs_ctrl.pRegHL->value(str); + sprintf(str, pCpuRegs->m_sHLfmt, HL); + pCpuRegs->m_pRegHL->value(str); // Update M edit box - sprintf(str, cpuregs_ctrl.sMfmt, get_m()); - cpuregs_ctrl.pRegM->value(str); + sprintf(str, pCpuRegs->m_sMfmt, get_m()); + pCpuRegs->m_pRegM->value(str); } @@ -1088,13 +1420,14 @@ void cb_reg_l_changed(Fl_Widget* w, void*) Routine to handle Change to SP edit field ============================================================================ */ -void cb_reg_sp_changed(Fl_Widget* w, void*) +void cb_reg_sp_changed(Fl_Widget* w, void* pOpaque) { const char *pStr; int val; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; // Get value of SP - pStr = cpuregs_ctrl.pRegSP->value(); + pStr = pCpuRegs->m_pRegSP->value(); if (pStr[0] != 0) { val = str_to_i(pStr); @@ -1110,18 +1443,15 @@ void cb_reg_sp_changed(Fl_Widget* w, void*) Routine to handle disabling realtime trace ============================================================================ */ -void cb_disable_realtime_trace(Fl_Widget* w, void*) +void cb_disable_realtime_trace(Fl_Widget* w, void* pOpaque) { - gDisableRealtimeTrace = cpuregs_ctrl.pDisableTrace->value(); + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; + + gDisableRealtimeTrace = pCpuRegs->m_pDisableTrace->value(); if (gDisableRealtimeTrace) { - gcpuw->make_current(); - - // Clear rectangle - fl_color(FL_GRAY); - fl_rectf(25, 205+MENU_HEIGHT, 510, 115); - fl_rectf(555, 205+MENU_HEIGHT, 54, 115); + pCpuRegs->redraw(); } } @@ -1130,16 +1460,17 @@ void cb_disable_realtime_trace(Fl_Widget* w, void*) Routine to handle Reg A Hex display mode ============================================================================ */ -void cb_reg_a_hex(Fl_Widget* w, void*) +void cb_reg_a_hex(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sAfmt, "0x%02X"); - sprintf(str, cpuregs_ctrl.sAfmt, A); - cpuregs_ctrl.pRegA->value(str); + strcpy(pCpuRegs->m_sAfmt, "0x%02X"); + sprintf(str, pCpuRegs->m_sAfmt, A); + pCpuRegs->m_pRegA->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1147,16 +1478,17 @@ void cb_reg_a_hex(Fl_Widget* w, void*) Routine to handle Reg A Dec display mode ============================================================================ */ -void cb_reg_a_dec(Fl_Widget* w, void*) +void cb_reg_a_dec(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sAfmt, "%d"); - sprintf(str, cpuregs_ctrl.sAfmt, A); - cpuregs_ctrl.pRegA->value(str); + strcpy(pCpuRegs->m_sAfmt, "%d"); + sprintf(str, pCpuRegs->m_sAfmt, A); + pCpuRegs->m_pRegA->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1164,16 +1496,17 @@ void cb_reg_a_dec(Fl_Widget* w, void*) Routine to handle Reg B Hex display mode ============================================================================ */ -void cb_reg_b_hex(Fl_Widget* w, void*) +void cb_reg_b_hex(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sBfmt, "0x%02X"); - sprintf(str, cpuregs_ctrl.sBfmt, B); - cpuregs_ctrl.pRegB->value(str); + strcpy(pCpuRegs->m_sBfmt, "0x%02X"); + sprintf(str, pCpuRegs->m_sBfmt, B); + pCpuRegs->m_pRegB->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1181,16 +1514,17 @@ void cb_reg_b_hex(Fl_Widget* w, void*) Routine to handle Reg B Dec display mode ============================================================================ */ -void cb_reg_b_dec(Fl_Widget* w, void*) +void cb_reg_b_dec(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sBfmt, "%d"); - sprintf(str, cpuregs_ctrl.sBfmt, B); - cpuregs_ctrl.pRegB->value(str); + strcpy(pCpuRegs->m_sBfmt, "%d"); + sprintf(str, pCpuRegs->m_sBfmt, B); + pCpuRegs->m_pRegB->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1198,16 +1532,17 @@ void cb_reg_b_dec(Fl_Widget* w, void*) Routine to handle Reg C Hex display mode ============================================================================ */ -void cb_reg_c_hex(Fl_Widget* w, void*) +void cb_reg_c_hex(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sCfmt, "0x%02X"); - sprintf(str, cpuregs_ctrl.sCfmt, C); - cpuregs_ctrl.pRegC->value(str); + strcpy(pCpuRegs->m_sCfmt, "0x%02X"); + sprintf(str, pCpuRegs->m_sCfmt, C); + pCpuRegs->m_pRegC->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1215,16 +1550,17 @@ void cb_reg_c_hex(Fl_Widget* w, void*) Routine to handle Reg C Dec display mode ============================================================================ */ -void cb_reg_c_dec(Fl_Widget* w, void*) +void cb_reg_c_dec(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sCfmt, "%d"); - sprintf(str, cpuregs_ctrl.sCfmt, C); - cpuregs_ctrl.pRegC->value(str); + strcpy(pCpuRegs->m_sCfmt, "%d"); + sprintf(str, pCpuRegs->m_sCfmt, C); + pCpuRegs->m_pRegC->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1232,16 +1568,17 @@ void cb_reg_c_dec(Fl_Widget* w, void*) Routine to handle Reg D Hex display mode ============================================================================ */ -void cb_reg_d_hex(Fl_Widget* w, void*) +void cb_reg_d_hex(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sDfmt, "0x%02X"); - sprintf(str, cpuregs_ctrl.sDfmt, D); - cpuregs_ctrl.pRegD->value(str); + strcpy(pCpuRegs->m_sDfmt, "0x%02X"); + sprintf(str, pCpuRegs->m_sDfmt, D); + pCpuRegs->m_pRegD->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1249,16 +1586,17 @@ void cb_reg_d_hex(Fl_Widget* w, void*) Routine to handle Reg D Dec display mode ============================================================================ */ -void cb_reg_d_dec(Fl_Widget* w, void*) +void cb_reg_d_dec(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sDfmt, "%d"); - sprintf(str, cpuregs_ctrl.sDfmt, D); - cpuregs_ctrl.pRegD->value(str); + strcpy(pCpuRegs->m_sDfmt, "%d"); + sprintf(str, pCpuRegs->m_sDfmt, D); + pCpuRegs->m_pRegD->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1266,16 +1604,17 @@ void cb_reg_d_dec(Fl_Widget* w, void*) Routine to handle Reg E Hex display mode ============================================================================ */ -void cb_reg_e_hex(Fl_Widget* w, void*) +void cb_reg_e_hex(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sEfmt, "0x%02X"); - sprintf(str, cpuregs_ctrl.sEfmt, E); - cpuregs_ctrl.pRegE->value(str); + strcpy(pCpuRegs->m_sEfmt, "0x%02X"); + sprintf(str, pCpuRegs->m_sEfmt, E); + pCpuRegs->m_pRegE->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1283,16 +1622,17 @@ void cb_reg_e_hex(Fl_Widget* w, void*) Routine to handle Reg E Dec display mode ============================================================================ */ -void cb_reg_e_dec(Fl_Widget* w, void*) +void cb_reg_e_dec(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sEfmt, "%d"); - sprintf(str, cpuregs_ctrl.sEfmt, E); - cpuregs_ctrl.pRegE->value(str); + strcpy(pCpuRegs->m_sEfmt, "%d"); + sprintf(str, pCpuRegs->m_sEfmt, E); + pCpuRegs->m_pRegE->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1300,16 +1640,17 @@ void cb_reg_e_dec(Fl_Widget* w, void*) Routine to handle Reg H Hex display mode ============================================================================ */ -void cb_reg_h_hex(Fl_Widget* w, void*) +void cb_reg_h_hex(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sHfmt, "0x%02X"); - sprintf(str, cpuregs_ctrl.sHfmt, H); - cpuregs_ctrl.pRegH->value(str); + strcpy(pCpuRegs->m_sHfmt, "0x%02X"); + sprintf(str, pCpuRegs->m_sHfmt, H); + pCpuRegs->m_pRegH->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1317,16 +1658,17 @@ void cb_reg_h_hex(Fl_Widget* w, void*) Routine to handle Reg H Dec display mode ============================================================================ */ -void cb_reg_h_dec(Fl_Widget* w, void*) +void cb_reg_h_dec(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sHfmt, "%d"); - sprintf(str, cpuregs_ctrl.sHfmt, H); - cpuregs_ctrl.pRegH->value(str); + strcpy(pCpuRegs->m_sHfmt, "%d"); + sprintf(str, pCpuRegs->m_sHfmt, H); + pCpuRegs->m_pRegH->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1334,16 +1676,17 @@ void cb_reg_h_dec(Fl_Widget* w, void*) Routine to handle Reg L Hex display mode ============================================================================ */ -void cb_reg_l_hex(Fl_Widget* w, void*) +void cb_reg_l_hex(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sLfmt, "0x%02X"); - sprintf(str, cpuregs_ctrl.sLfmt, L); - cpuregs_ctrl.pRegL->value(str); + strcpy(pCpuRegs->m_sLfmt, "0x%02X"); + sprintf(str, pCpuRegs->m_sLfmt, L); + pCpuRegs->m_pRegL->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1351,16 +1694,17 @@ void cb_reg_l_hex(Fl_Widget* w, void*) Routine to handle Reg L Dec display mode ============================================================================ */ -void cb_reg_l_dec(Fl_Widget* w, void*) +void cb_reg_l_dec(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sLfmt, "%d"); - sprintf(str, cpuregs_ctrl.sLfmt, L); - cpuregs_ctrl.pRegL->value(str); + strcpy(pCpuRegs->m_sLfmt, "%d"); + sprintf(str, pCpuRegs->m_sLfmt, L); + pCpuRegs->m_pRegL->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1368,16 +1712,17 @@ void cb_reg_l_dec(Fl_Widget* w, void*) Routine to handle Reg PC Hex display mode ============================================================================ */ -void cb_reg_pc_hex(Fl_Widget* w, void*) +void cb_reg_pc_hex(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sPCfmt, "0x%04X"); - sprintf(str, cpuregs_ctrl.sPCfmt, PC); - cpuregs_ctrl.pRegPC->value(str); + strcpy(pCpuRegs->m_sPCfmt, "0x%04X"); + sprintf(str, pCpuRegs->m_sPCfmt, PC); + pCpuRegs->m_pRegPC->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1385,16 +1730,17 @@ void cb_reg_pc_hex(Fl_Widget* w, void*) Routine to handle Reg PC Dec display mode ============================================================================ */ -void cb_reg_pc_dec(Fl_Widget* w, void*) +void cb_reg_pc_dec(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sPCfmt, "%d"); - sprintf(str, cpuregs_ctrl.sPCfmt, PC); - cpuregs_ctrl.pRegPC->value(str); + strcpy(pCpuRegs->m_sPCfmt, "%d"); + sprintf(str, pCpuRegs->m_sPCfmt, PC); + pCpuRegs->m_pRegPC->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1402,16 +1748,17 @@ void cb_reg_pc_dec(Fl_Widget* w, void*) Routine to handle Reg SP Hex display mode ============================================================================ */ -void cb_reg_sp_hex(Fl_Widget* w, void*) +void cb_reg_sp_hex(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sSPfmt, "0x%04X"); - sprintf(str, cpuregs_ctrl.sSPfmt, SP); - cpuregs_ctrl.pRegSP->value(str); + strcpy(pCpuRegs->m_sSPfmt, "0x%04X"); + sprintf(str, pCpuRegs->m_sSPfmt, SP); + pCpuRegs->m_pRegSP->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1419,16 +1766,17 @@ void cb_reg_sp_hex(Fl_Widget* w, void*) Routine to handle Reg SP Dec display mode ============================================================================ */ -void cb_reg_sp_dec(Fl_Widget* w, void*) +void cb_reg_sp_dec(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sSPfmt, "%d"); - sprintf(str, cpuregs_ctrl.sSPfmt, SP); - cpuregs_ctrl.pRegSP->value(str); + strcpy(pCpuRegs->m_sSPfmt, "%d"); + sprintf(str, pCpuRegs->m_sSPfmt, SP); + pCpuRegs->m_pRegSP->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1436,16 +1784,17 @@ void cb_reg_sp_dec(Fl_Widget* w, void*) Routine to handle Reg BC Hex display mode ============================================================================ */ -void cb_reg_bc_hex(Fl_Widget* w, void*) +void cb_reg_bc_hex(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sBCfmt, "0x%04X"); - sprintf(str, cpuregs_ctrl.sBCfmt, BC); - cpuregs_ctrl.pRegBC->value(str); + strcpy(pCpuRegs->m_sBCfmt, "0x%04X"); + sprintf(str, pCpuRegs->m_sBCfmt, BC); + pCpuRegs->m_pRegBC->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1453,16 +1802,17 @@ void cb_reg_bc_hex(Fl_Widget* w, void*) Routine to handle Reg BC Dec display mode ============================================================================ */ -void cb_reg_bc_dec(Fl_Widget* w, void*) +void cb_reg_bc_dec(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sBCfmt, "%d"); - sprintf(str, cpuregs_ctrl.sBCfmt, BC); - cpuregs_ctrl.pRegBC->value(str); + strcpy(pCpuRegs->m_sBCfmt, "%d"); + sprintf(str, pCpuRegs->m_sBCfmt, BC); + pCpuRegs->m_pRegBC->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1470,16 +1820,17 @@ void cb_reg_bc_dec(Fl_Widget* w, void*) Routine to handle Reg DE Hex display mode ============================================================================ */ -void cb_reg_de_hex(Fl_Widget* w, void*) +void cb_reg_de_hex(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sDEfmt, "0x%04X"); - sprintf(str, cpuregs_ctrl.sDEfmt, DE); - cpuregs_ctrl.pRegDE->value(str); + strcpy(pCpuRegs->m_sDEfmt, "0x%04X"); + sprintf(str, pCpuRegs->m_sDEfmt, DE); + pCpuRegs->m_pRegDE->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1487,16 +1838,17 @@ void cb_reg_de_hex(Fl_Widget* w, void*) Routine to handle Reg DE Dec display mode ============================================================================ */ -void cb_reg_de_dec(Fl_Widget* w, void*) +void cb_reg_de_dec(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sDEfmt, "%d"); - sprintf(str, cpuregs_ctrl.sDEfmt, DE); - cpuregs_ctrl.pRegDE->value(str); + strcpy(pCpuRegs->m_sDEfmt, "%d"); + sprintf(str, pCpuRegs->m_sDEfmt, DE); + pCpuRegs->m_pRegDE->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1504,16 +1856,17 @@ void cb_reg_de_dec(Fl_Widget* w, void*) Routine to handle Reg HL Hex display mode ============================================================================ */ -void cb_reg_hl_hex(Fl_Widget* w, void*) +void cb_reg_hl_hex(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sHLfmt, "0x%04X"); - sprintf(str, cpuregs_ctrl.sHLfmt, HL); - cpuregs_ctrl.pRegHL->value(str); + strcpy(pCpuRegs->m_sHLfmt, "0x%04X"); + sprintf(str, pCpuRegs->m_sHLfmt, HL); + pCpuRegs->m_pRegHL->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1521,16 +1874,17 @@ void cb_reg_hl_hex(Fl_Widget* w, void*) Routine to handle Reg HL Dec display mode ============================================================================ */ -void cb_reg_hl_dec(Fl_Widget* w, void*) +void cb_reg_hl_dec(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sHLfmt, "%d"); - sprintf(str, cpuregs_ctrl.sHLfmt, HL); - cpuregs_ctrl.pRegHL->value(str); + strcpy(pCpuRegs->m_sHLfmt, "%d"); + sprintf(str, pCpuRegs->m_sHLfmt, HL); + pCpuRegs->m_pRegHL->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1538,16 +1892,17 @@ void cb_reg_hl_dec(Fl_Widget* w, void*) Routine to handle Reg M Hex display mode ============================================================================ */ -void cb_reg_m_hex(Fl_Widget* w, void*) +void cb_reg_m_hex(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sMfmt, "0x%02X"); - sprintf(str, cpuregs_ctrl.sMfmt, get_m()); - cpuregs_ctrl.pRegM->value(str); + strcpy(pCpuRegs->m_sMfmt, "0x%02X"); + sprintf(str, pCpuRegs->m_sMfmt, get_m()); + pCpuRegs->m_pRegM->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1555,16 +1910,17 @@ void cb_reg_m_hex(Fl_Widget* w, void*) Routine to handle Reg M Dec display mode ============================================================================ */ -void cb_reg_m_dec(Fl_Widget* w, void*) +void cb_reg_m_dec(Fl_Widget* w, void* pOpaque) { - char str[8]; + char str[8]; + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; - strcpy(cpuregs_ctrl.sMfmt, "%d"); - sprintf(str, cpuregs_ctrl.sMfmt, get_m()); - cpuregs_ctrl.pRegM->value(str); + strcpy(pCpuRegs->m_sMfmt, "%d"); + sprintf(str, pCpuRegs->m_sMfmt, get_m()); + pCpuRegs->m_pRegM->value(str); - cpuregs_ctrl.pAllHex->value(0); - cpuregs_ctrl.pAllDec->value(0); + pCpuRegs->m_pAllHex->value(0); + pCpuRegs->m_pAllDec->value(0); } /* @@ -1572,55 +1928,61 @@ void cb_reg_m_dec(Fl_Widget* w, void*) Routine to handle Reg All Hex display mode ============================================================================ */ -void cb_reg_all_hex(Fl_Widget* w, void*) +void cb_reg_all_hex(Fl_Widget* w, void* pOpaque) +{ + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; + pCpuRegs->RegAllHex(); +} + +void VTCpuRegs::RegAllHex(void) { // Change format to "Hex" for all - cb_reg_a_hex(w, NULL); - cb_reg_b_hex(w, NULL); - cb_reg_c_hex(w, NULL); - cb_reg_d_hex(w, NULL); - cb_reg_e_hex(w, NULL); - cb_reg_h_hex(w, NULL); - cb_reg_l_hex(w, NULL); - cb_reg_pc_hex(w, NULL); - cb_reg_sp_hex(w, NULL); - cb_reg_bc_hex(w, NULL); - cb_reg_de_hex(w, NULL); - cb_reg_hl_hex(w, NULL); - cb_reg_m_hex(w, NULL); + cb_reg_a_hex(NULL, this); + cb_reg_b_hex(NULL, this); + cb_reg_c_hex(NULL, this); + cb_reg_d_hex(NULL, this); + cb_reg_e_hex(NULL, this); + cb_reg_h_hex(NULL, this); + cb_reg_l_hex(NULL, this); + cb_reg_pc_hex(NULL, this); + cb_reg_sp_hex(NULL, this); + cb_reg_bc_hex(NULL, this); + cb_reg_de_hex(NULL, this); + cb_reg_hl_hex(NULL, this); + cb_reg_m_hex(NULL, this); // Deselect all "Dec" buttons - cpuregs_ctrl.pADec->value(0); - cpuregs_ctrl.pBDec->value(0); - cpuregs_ctrl.pCDec->value(0); - cpuregs_ctrl.pDDec->value(0); - cpuregs_ctrl.pEDec->value(0); - cpuregs_ctrl.pHDec->value(0); - cpuregs_ctrl.pLDec->value(0); - cpuregs_ctrl.pPCDec->value(0); - cpuregs_ctrl.pSPDec->value(0); - cpuregs_ctrl.pBCDec->value(0); - cpuregs_ctrl.pDEDec->value(0); - cpuregs_ctrl.pHLDec->value(0); - cpuregs_ctrl.pMDec->value(0); + m_pADec->value(0); + m_pBDec->value(0); + m_pCDec->value(0); + m_pDDec->value(0); + m_pEDec->value(0); + m_pHDec->value(0); + m_pLDec->value(0); + m_pPCDec->value(0); + m_pSPDec->value(0); + m_pBCDec->value(0); + m_pDEDec->value(0); + m_pHLDec->value(0); + m_pMDec->value(0); // Select all "Hex" buttons - cpuregs_ctrl.pAHex->value(1); - cpuregs_ctrl.pBHex->value(1); - cpuregs_ctrl.pCHex->value(1); - cpuregs_ctrl.pDHex->value(1); - cpuregs_ctrl.pEHex->value(1); - cpuregs_ctrl.pHHex->value(1); - cpuregs_ctrl.pLHex->value(1); - cpuregs_ctrl.pPCHex->value(1); - cpuregs_ctrl.pSPHex->value(1); - cpuregs_ctrl.pBCHex->value(1); - cpuregs_ctrl.pDEHex->value(1); - cpuregs_ctrl.pHLHex->value(1); - cpuregs_ctrl.pMHex->value(1); + m_pAHex->value(1); + m_pBHex->value(1); + m_pCHex->value(1); + m_pDHex->value(1); + m_pEHex->value(1); + m_pHHex->value(1); + m_pLHex->value(1); + m_pPCHex->value(1); + m_pSPHex->value(1); + m_pBCHex->value(1); + m_pDEHex->value(1); + m_pHLHex->value(1); + m_pMHex->value(1); // reselect the "All Hex" button - cpuregs_ctrl.pAllHex->value(1); + m_pAllHex->value(1); } /* @@ -1628,55 +1990,107 @@ void cb_reg_all_hex(Fl_Widget* w, void*) Routine to handle Reg All Dec display mode ============================================================================ */ -void cb_reg_all_dec(Fl_Widget* w, void*) +void cb_reg_all_dec(Fl_Widget* w, void* pOpaque) +{ + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; + pCpuRegs->RegAllDec(); +} + +void VTCpuRegs::RegAllDec(void) { // Change format of all items to Dec - cb_reg_a_dec(w, NULL); - cb_reg_b_dec(w, NULL); - cb_reg_c_dec(w, NULL); - cb_reg_d_dec(w, NULL); - cb_reg_e_dec(w, NULL); - cb_reg_h_dec(w, NULL); - cb_reg_l_dec(w, NULL); - cb_reg_pc_dec(w, NULL); - cb_reg_sp_dec(w, NULL); - cb_reg_bc_dec(w, NULL); - cb_reg_de_dec(w, NULL); - cb_reg_hl_dec(w, NULL); - cb_reg_m_dec(w, NULL); + cb_reg_a_dec(NULL, this); + cb_reg_b_dec(NULL, this); + cb_reg_c_dec(NULL, this); + cb_reg_d_dec(NULL, this); + cb_reg_e_dec(NULL, this); + cb_reg_h_dec(NULL, this); + cb_reg_l_dec(NULL, this); + cb_reg_pc_dec(NULL, this); + cb_reg_sp_dec(NULL, this); + cb_reg_bc_dec(NULL, this); + cb_reg_de_dec(NULL, this); + cb_reg_hl_dec(NULL, this); + cb_reg_m_dec(NULL, this); // Deselect all "Hex" buttons - cpuregs_ctrl.pAHex->value(0); - cpuregs_ctrl.pBHex->value(0); - cpuregs_ctrl.pCHex->value(0); - cpuregs_ctrl.pDHex->value(0); - cpuregs_ctrl.pEHex->value(0); - cpuregs_ctrl.pHHex->value(0); - cpuregs_ctrl.pLHex->value(0); - cpuregs_ctrl.pPCHex->value(0); - cpuregs_ctrl.pSPHex->value(0); - cpuregs_ctrl.pBCHex->value(0); - cpuregs_ctrl.pDEHex->value(0); - cpuregs_ctrl.pHLHex->value(0); - cpuregs_ctrl.pMHex->value(0); + m_pAHex->value(0); + m_pBHex->value(0); + m_pCHex->value(0); + m_pDHex->value(0); + m_pEHex->value(0); + m_pHHex->value(0); + m_pLHex->value(0); + m_pPCHex->value(0); + m_pSPHex->value(0); + m_pBCHex->value(0); + m_pDEHex->value(0); + m_pHLHex->value(0); + m_pMHex->value(0); // Select all "Dec" buttons - cpuregs_ctrl.pADec->value(1); - cpuregs_ctrl.pBDec->value(1); - cpuregs_ctrl.pCDec->value(1); - cpuregs_ctrl.pDDec->value(1); - cpuregs_ctrl.pEDec->value(1); - cpuregs_ctrl.pHDec->value(1); - cpuregs_ctrl.pLDec->value(1); - cpuregs_ctrl.pPCDec->value(1); - cpuregs_ctrl.pSPDec->value(1); - cpuregs_ctrl.pBCDec->value(1); - cpuregs_ctrl.pDEDec->value(1); - cpuregs_ctrl.pHLDec->value(1); - cpuregs_ctrl.pMDec->value(1); + m_pADec->value(1); + m_pBDec->value(1); + m_pCDec->value(1); + m_pDDec->value(1); + m_pEDec->value(1); + m_pHDec->value(1); + m_pLDec->value(1); + m_pPCDec->value(1); + m_pSPDec->value(1); + m_pBCDec->value(1); + m_pDEDec->value(1); + m_pHLDec->value(1); + m_pMDec->value(1); // Reselect "All" Dec button - cpuregs_ctrl.pAllDec->value(1); + m_pAllDec->value(1); +} + +/* +============================================================================ +Routine to handle debugInts checkbox clicks +============================================================================ +*/ +void cb_debugInts(Fl_Widget* w, void* pOpaque) +{ + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; + + gDebugInts = pCpuRegs->m_pDebugInts->value(); +} + +/* +============================================================================ +Routine to handle autoScroll checkbox clicks +============================================================================ +*/ +void cb_autoscroll(Fl_Widget* w, void* pOpaque) +{ + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; + + pCpuRegs->m_autoScroll = pCpuRegs->m_pAutoScroll->value(); +} + +/* +============================================================================ +Routine to handle saveBreak checkbox clicks +============================================================================ +*/ +void cb_saveBreakpoints(Fl_Widget* w, void* pOpaque) +{ + VTCpuRegs* pCpuRegs = (VTCpuRegs *) pOpaque; + + pCpuRegs->m_saveBreakpoints = pCpuRegs->m_pSaveBreak->value(); +} + +/* +============================================================================ +This routine is the timout callback for enabling debug monitoring. +============================================================================ +*/ +void cb_enable_monitor(void *pOpaque) +{ + debug_set_monitor_callback(debug_cpuregs_cb); } /* @@ -1686,20 +2100,80 @@ Routine to create the PeripheralSetup Window and tabs */ void cb_CpuRegs (Fl_Widget* w, void*) { - Fl_Box* o; - if (gcpuw != NULL) return; // Create Peripheral Setup window - gcpuw = new Fl_Window(630, 480, "CPU Registers"); - gcpuw->callback(cb_cpuregswin); + gcpuw = new VTCpuRegs(640, 480, "CPU Registers"); + gcpuw->callback(cb_cpuregswin, gcpuw); + + // Show the new window + gcpuw->show(); + + // Resize if user preferences have been set + if (gcpuw->m_x != -1 && gcpuw->m_y != -1 && gcpuw->m_w != -1 && gcpuw->m_h != -1) + { + int newx, newy, neww, newh; + + newx = gcpuw->m_x; + newy = gcpuw->m_y; + neww = gcpuw->m_w; + newh = gcpuw->m_h; + + gcpuw->resize(newx, newy, neww, newh); + } + + // Check if VirtualT has had time to initialize yet. If not, we set a + // timeout callback to enable monitoring, otherwise we just enable it directly + if (cycles < 10000000) + Fl::add_timeout(1.0, cb_enable_monitor, gcpuw); + else + debug_set_monitor_callback(debug_cpuregs_cb); + + // Indicate an active debug window + gDebugActive++; +} + +/* +============================================================================ +CpuRegisters class constructor. Creates all controls within the window. +============================================================================ +*/ +VTCpuRegs::VTCpuRegs(int x, int y, const char *title) : + Fl_Double_Window(x, y, title) +{ + Fl_Box* o; + int c; + + /* Load the user preferences for window size, etc. */ + LoadPrefs(); + + // Allocate the trace buffer + m_pTraceData = new cpu_trace_data_t[m_traceCount]; + + // Clear debugging data + m_traceAvail = 0; + m_breakMonitorFreq = 0; + for (c = 0; c < 5; c++) + { + m_breakAddr[c] = -1; + m_breakEnable[c] = 1; + } + + for (c = 0; c < 64; c++) + m_sInstTrace[c][0] = '\0'; + m_lastH = 0; + + fl_font(FL_COURIER, m_fontSize); + m_fontHeight = fl_height() + 1; // Create a menu for the new window. - cpuregs_ctrl.pMenu = new Fl_Menu_Bar(0, 0, 630, MENU_HEIGHT-2); - cpuregs_ctrl.pMenu->menu(gCpuRegs_menuitems); + m_pMenu = new Fl_Menu_Bar(0, 0, x, MENU_HEIGHT-2); + m_pMenu->menu(gCpuRegs_menuitems); // Create static text boxes + Fl_Group* g1 = new Fl_Group(0, 20+MENU_HEIGHT, x, 170+MENU_HEIGHT-20); + o = new Fl_Box(FL_NO_BOX, 20, 20+MENU_HEIGHT, 50, 15, "PC"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); o = new Fl_Box(FL_NO_BOX, 20, 45+MENU_HEIGHT, 50, 15, "SP"); @@ -1731,478 +2205,1038 @@ void cb_CpuRegs (Fl_Widget* w, void*) // Program Counter edit box - cpuregs_ctrl.pRegPC = new Fl_Input(50, 19+MENU_HEIGHT, 60, 20, ""); - cpuregs_ctrl.pRegPC->deactivate(); - cpuregs_ctrl.pRegPC->callback(cb_reg_pc_changed); - cpuregs_ctrl.pRegPC->value("0x0000"); + m_pRegPC = new Fl_Input(50, 19+MENU_HEIGHT, 60, 20, ""); + m_pRegPC->deactivate(); + m_pRegPC->callback(cb_reg_pc_changed, this); + m_pRegPC->value("0x0000"); // Accumulator Edit Box - cpuregs_ctrl.pRegA = new Fl_Input(150, 19+MENU_HEIGHT, 60, 20, ""); - cpuregs_ctrl.pRegA->deactivate(); - cpuregs_ctrl.pRegA->value("0x00"); + m_pRegA = new Fl_Input(150, 19+MENU_HEIGHT, 60, 20, ""); + m_pRegA->deactivate(); + m_pRegA->value("0x00"); // Stack Pointer edit box - cpuregs_ctrl.pRegSP = new Fl_Input(50, 44+MENU_HEIGHT, 60, 20, ""); - cpuregs_ctrl.pRegSP->deactivate(); - cpuregs_ctrl.pRegSP->callback(cb_reg_sp_changed); - cpuregs_ctrl.pRegSP->value("0x0000"); + m_pRegSP = new Fl_Input(50, 44+MENU_HEIGHT, 60, 20, ""); + m_pRegSP->deactivate(); + m_pRegSP->callback(cb_reg_sp_changed, this); + m_pRegSP->value("0x0000"); // Create Flag checkboxes // Sign flag - cpuregs_ctrl.pSFlag = new Fl_Check_Button(223, 19+MENU_HEIGHT, 30, 20, "S"); - cpuregs_ctrl.pSFlag->deactivate(); + m_pSFlag = new Fl_Check_Button(223, 19+MENU_HEIGHT, 30, 20, "S"); + m_pSFlag->deactivate(); // Zero flag - cpuregs_ctrl.pZFlag = new Fl_Check_Button(253, 19+MENU_HEIGHT, 30, 20, "Z"); - cpuregs_ctrl.pZFlag->deactivate(); + m_pZFlag = new Fl_Check_Button(253, 19+MENU_HEIGHT, 30, 20, "Z"); + m_pZFlag->deactivate(); // Carry flag - cpuregs_ctrl.pCFlag = new Fl_Check_Button(290, 19+MENU_HEIGHT, 30, 20, "C"); - cpuregs_ctrl.pCFlag->deactivate(); + m_pCFlag = new Fl_Check_Button(290, 19+MENU_HEIGHT, 30, 20, "C"); + m_pCFlag->deactivate(); // TS flag - cpuregs_ctrl.pTSFlag = new Fl_Check_Button(148, 44+MENU_HEIGHT, 40, 20, "TS"); - cpuregs_ctrl.pTSFlag->deactivate(); + m_pTSFlag = new Fl_Check_Button(148, 44+MENU_HEIGHT, 40, 20, "TS"); + m_pTSFlag->deactivate(); // AC flag - cpuregs_ctrl.pACFlag = new Fl_Check_Button(185, 44+MENU_HEIGHT, 40, 20, "AC"); - cpuregs_ctrl.pACFlag->deactivate(); + m_pACFlag = new Fl_Check_Button(185, 44+MENU_HEIGHT, 40, 20, "AC"); + m_pACFlag->deactivate(); // Parity flag - cpuregs_ctrl.pPFlag = new Fl_Check_Button(223, 44+MENU_HEIGHT, 30, 20, "P"); - cpuregs_ctrl.pPFlag->deactivate(); + m_pPFlag = new Fl_Check_Button(223, 44+MENU_HEIGHT, 30, 20, "P"); + m_pPFlag->deactivate(); // Overflow flag - cpuregs_ctrl.pOVFlag = new Fl_Check_Button(253, 44+MENU_HEIGHT, 40, 20, "OV"); - cpuregs_ctrl.pOVFlag->deactivate(); + m_pOVFlag = new Fl_Check_Button(253, 44+MENU_HEIGHT, 40, 20, "OV"); + m_pOVFlag->deactivate(); // X flag - cpuregs_ctrl.pXFlag = new Fl_Check_Button(290, 44+MENU_HEIGHT, 30, 20, "X"); - cpuregs_ctrl.pXFlag->deactivate(); + m_pXFlag = new Fl_Check_Button(290, 44+MENU_HEIGHT, 30, 20, "X"); + m_pXFlag->deactivate(); // Register B Edit Box - cpuregs_ctrl.pRegB = new Fl_Input(50, 69+MENU_HEIGHT, 60, 20, ""); - cpuregs_ctrl.pRegB->deactivate(); - cpuregs_ctrl.pRegB->callback(cb_reg_b_changed); - cpuregs_ctrl.pRegB->value("0x00"); + m_pRegB = new Fl_Input(50, 69+MENU_HEIGHT, 60, 20, ""); + m_pRegB->deactivate(); + m_pRegB->callback(cb_reg_b_changed, this); + m_pRegB->value("0x00"); // Register C Edit Box - cpuregs_ctrl.pRegC = new Fl_Input(150, 69+MENU_HEIGHT, 60, 20, ""); - cpuregs_ctrl.pRegC->deactivate(); - cpuregs_ctrl.pRegC->callback(cb_reg_c_changed); - cpuregs_ctrl.pRegC->value("0x00"); + m_pRegC = new Fl_Input(150, 69+MENU_HEIGHT, 60, 20, ""); + m_pRegC->deactivate(); + m_pRegC->callback(cb_reg_c_changed, this); + m_pRegC->value("0x00"); // Register BC Edit Box - cpuregs_ctrl.pRegBC = new Fl_Input(250, 69+MENU_HEIGHT, 60, 20, ""); - cpuregs_ctrl.pRegBC->deactivate(); - cpuregs_ctrl.pRegBC->callback(cb_reg_bc_changed); - cpuregs_ctrl.pRegBC->value("0x0000"); + m_pRegBC = new Fl_Input(250, 69+MENU_HEIGHT, 60, 20, ""); + m_pRegBC->deactivate(); + m_pRegBC->callback(cb_reg_bc_changed, this); + m_pRegBC->value("0x0000"); // Register D Edit Box - cpuregs_ctrl.pRegD = new Fl_Input(50, 94+MENU_HEIGHT, 60, 20, ""); - cpuregs_ctrl.pRegD->deactivate(); - cpuregs_ctrl.pRegD->callback(cb_reg_d_changed); - cpuregs_ctrl.pRegD->value("0x00"); + m_pRegD = new Fl_Input(50, 94+MENU_HEIGHT, 60, 20, ""); + m_pRegD->deactivate(); + m_pRegD->callback(cb_reg_d_changed, this); + m_pRegD->value("0x00"); // Register E Edit Box - cpuregs_ctrl.pRegE = new Fl_Input(150, 94+MENU_HEIGHT, 60, 20, ""); - cpuregs_ctrl.pRegE->deactivate(); - cpuregs_ctrl.pRegE->callback(cb_reg_e_changed); - cpuregs_ctrl.pRegE->value("0x00"); + m_pRegE = new Fl_Input(150, 94+MENU_HEIGHT, 60, 20, ""); + m_pRegE->deactivate(); + m_pRegE->callback(cb_reg_e_changed, this); + m_pRegE->value("0x00"); // Register DE Edit Box - cpuregs_ctrl.pRegDE = new Fl_Input(250, 94+MENU_HEIGHT, 60, 20, ""); - cpuregs_ctrl.pRegDE->deactivate(); - cpuregs_ctrl.pRegDE->callback(cb_reg_de_changed); - cpuregs_ctrl.pRegDE->value("0x0000"); + m_pRegDE = new Fl_Input(250, 94+MENU_HEIGHT, 60, 20, ""); + m_pRegDE->deactivate(); + m_pRegDE->callback(cb_reg_de_changed, this); + m_pRegDE->value("0x0000"); // Register H Edit Box - cpuregs_ctrl.pRegH = new Fl_Input(50, 119+MENU_HEIGHT, 60, 20, ""); - cpuregs_ctrl.pRegH->deactivate(); - cpuregs_ctrl.pRegH->callback(cb_reg_h_changed); - cpuregs_ctrl.pRegH->value("0x00"); + m_pRegH = new Fl_Input(50, 119+MENU_HEIGHT, 60, 20, ""); + m_pRegH->deactivate(); + m_pRegH->callback(cb_reg_h_changed, this); + m_pRegH->value("0x00"); // Register L Edit Box - cpuregs_ctrl.pRegL = new Fl_Input(150, 119+MENU_HEIGHT, 60, 20, ""); - cpuregs_ctrl.pRegL->deactivate(); - cpuregs_ctrl.pRegL->callback(cb_reg_l_changed); - cpuregs_ctrl.pRegL->value("0x00"); + m_pRegL = new Fl_Input(150, 119+MENU_HEIGHT, 60, 20, ""); + m_pRegL->deactivate(); + m_pRegL->callback(cb_reg_l_changed, this); + m_pRegL->value("0x00"); // Register HL Edit Box - cpuregs_ctrl.pRegHL = new Fl_Input(250, 119+MENU_HEIGHT, 60, 20, ""); - cpuregs_ctrl.pRegHL->deactivate(); - cpuregs_ctrl.pRegHL->callback(cb_reg_hl_changed); - cpuregs_ctrl.pRegHL->value("0x0000"); + m_pRegHL = new Fl_Input(250, 119+MENU_HEIGHT, 60, 20, ""); + m_pRegHL->deactivate(); + m_pRegHL->callback(cb_reg_hl_changed, this); + m_pRegHL->value("0x0000"); // Register M Edit Box - cpuregs_ctrl.pRegM = new Fl_Input(250, 144+MENU_HEIGHT, 60, 20, ""); - cpuregs_ctrl.pRegM->deactivate(); - cpuregs_ctrl.pRegM->value("0x00"); - - - strcpy(cpuregs_ctrl.sPCfmt, "0x%04X"); - strcpy(cpuregs_ctrl.sSPfmt, "0x%04X"); - strcpy(cpuregs_ctrl.sBCfmt, "0x%04X"); - strcpy(cpuregs_ctrl.sDEfmt, "0x%04X"); - strcpy(cpuregs_ctrl.sHLfmt, "0x%04X"); - strcpy(cpuregs_ctrl.sAfmt, "0x%02X"); - strcpy(cpuregs_ctrl.sBfmt, "0x%02X"); - strcpy(cpuregs_ctrl.sCfmt, "0x%02X"); - strcpy(cpuregs_ctrl.sDfmt, "0x%02X"); - strcpy(cpuregs_ctrl.sEfmt, "0x%02X"); - strcpy(cpuregs_ctrl.sHfmt, "0x%02X"); - strcpy(cpuregs_ctrl.sLfmt, "0x%02X"); - strcpy(cpuregs_ctrl.sMfmt, "0x%02X"); + m_pRegM = new Fl_Input(250, 144+MENU_HEIGHT, 60, 20, ""); + m_pRegM->deactivate(); + m_pRegM->value("0x00"); + + + strcpy(m_sPCfmt, "0x%04X"); + strcpy(m_sSPfmt, "0x%04X"); + strcpy(m_sBCfmt, "0x%04X"); + strcpy(m_sDEfmt, "0x%04X"); + strcpy(m_sHLfmt, "0x%04X"); + strcpy(m_sAfmt, "0x%02X"); + strcpy(m_sBfmt, "0x%02X"); + strcpy(m_sCfmt, "0x%02X"); + strcpy(m_sDfmt, "0x%02X"); + strcpy(m_sEfmt, "0x%02X"); + strcpy(m_sHfmt, "0x%02X"); + strcpy(m_sLfmt, "0x%02X"); + strcpy(m_sMfmt, "0x%02X"); // Group the Reg "All" radio buttons together { - cpuregs_ctrl.g = new Fl_Group(440, 10 + MENU_HEIGHT, 100, 20, ""); + m_g = new Fl_Group(440, 10 + MENU_HEIGHT, 100, 20, ""); // Display format for Reg A o = new Fl_Box(FL_NO_BOX, 410, 11+MENU_HEIGHT, 50, 15, "All"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - cpuregs_ctrl.pAllHex = new Fl_Round_Button(440, 10 + MENU_HEIGHT, 50, 20, "Hex"); - cpuregs_ctrl.pAllHex->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pAllHex->callback(cb_reg_all_hex); - cpuregs_ctrl.pAllHex->value(1); + m_pAllHex = new Fl_Round_Button(440, 10 + MENU_HEIGHT, 50, 20, "Hex"); + m_pAllHex->type(FL_RADIO_BUTTON); + m_pAllHex->callback(cb_reg_all_hex, this); + m_pAllHex->value(1); - cpuregs_ctrl.pAllDec = new Fl_Round_Button(490, 10 + MENU_HEIGHT, 50, 20, "Dec"); - cpuregs_ctrl.pAllDec->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pAllDec->callback(cb_reg_all_dec); - cpuregs_ctrl.g->end(); + m_pAllDec = new Fl_Round_Button(490, 10 + MENU_HEIGHT, 50, 20, "Dec"); + m_pAllDec->type(FL_RADIO_BUTTON); + m_pAllDec->callback(cb_reg_all_dec, this); + m_g->end(); } // Group the Reg A radio buttons together { - cpuregs_ctrl.g = new Fl_Group(370, 30 + MENU_HEIGHT, 100, 20, ""); + m_g = new Fl_Group(370, 30 + MENU_HEIGHT, 100, 20, ""); // Display format for Reg A o = new Fl_Box(FL_NO_BOX, 340, 31+MENU_HEIGHT, 50, 15, "A"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - cpuregs_ctrl.pAHex = new Fl_Round_Button(370, 30 + MENU_HEIGHT, 50, 20, "Hex"); - cpuregs_ctrl.pAHex->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pAHex->callback(cb_reg_a_hex); - cpuregs_ctrl.pAHex->value(1); + m_pAHex = new Fl_Round_Button(370, 30 + MENU_HEIGHT, 50, 20, "Hex"); + m_pAHex->type(FL_RADIO_BUTTON); + m_pAHex->callback(cb_reg_a_hex, this); + m_pAHex->value(1); - cpuregs_ctrl.pADec = new Fl_Round_Button(420, 30 + MENU_HEIGHT, 50, 20, "Dec"); - cpuregs_ctrl.pADec->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pADec->callback(cb_reg_a_dec); - cpuregs_ctrl.g->end(); + m_pADec = new Fl_Round_Button(420, 30 + MENU_HEIGHT, 50, 20, "Dec"); + m_pADec->type(FL_RADIO_BUTTON); + m_pADec->callback(cb_reg_a_dec, this); + m_g->end(); } // Group the Reg B radio buttons togther { - cpuregs_ctrl.g = new Fl_Group(370, 50 + MENU_HEIGHT, 100, 20, ""); + m_g = new Fl_Group(370, 50 + MENU_HEIGHT, 100, 20, ""); // Display format for Reg B o = new Fl_Box(FL_NO_BOX, 340, 51+MENU_HEIGHT, 50, 15, "B"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - cpuregs_ctrl.pBHex = new Fl_Round_Button(370, 50 + MENU_HEIGHT, 50, 20, "Hex"); - cpuregs_ctrl.pBHex->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pBHex->callback(cb_reg_b_hex); - cpuregs_ctrl.pBHex->value(1); + m_pBHex = new Fl_Round_Button(370, 50 + MENU_HEIGHT, 50, 20, "Hex"); + m_pBHex->type(FL_RADIO_BUTTON); + m_pBHex->callback(cb_reg_b_hex, this); + m_pBHex->value(1); - cpuregs_ctrl.pBDec = new Fl_Round_Button(420, 50 + MENU_HEIGHT, 50, 20, "Dec"); - cpuregs_ctrl.pBDec->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pBDec->callback(cb_reg_b_dec); - cpuregs_ctrl.g->end(); + m_pBDec = new Fl_Round_Button(420, 50 + MENU_HEIGHT, 50, 20, "Dec"); + m_pBDec->type(FL_RADIO_BUTTON); + m_pBDec->callback(cb_reg_b_dec, this); + m_g->end(); } // Group the Reg C radio buttons togther { - cpuregs_ctrl.g = new Fl_Group(370, 70 + MENU_HEIGHT, 100, 20, ""); + m_g = new Fl_Group(370, 70 + MENU_HEIGHT, 100, 20, ""); // Display format for Reg C o = new Fl_Box(FL_NO_BOX, 340, 71+MENU_HEIGHT, 50, 15, "C"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - cpuregs_ctrl.pCHex = new Fl_Round_Button(370, 70 + MENU_HEIGHT, 50, 20, "Hex"); - cpuregs_ctrl.pCHex->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pCHex->callback(cb_reg_c_hex); - cpuregs_ctrl.pCHex->value(1); + m_pCHex = new Fl_Round_Button(370, 70 + MENU_HEIGHT, 50, 20, "Hex"); + m_pCHex->type(FL_RADIO_BUTTON); + m_pCHex->callback(cb_reg_c_hex, this); + m_pCHex->value(1); - cpuregs_ctrl.pCDec = new Fl_Round_Button(420, 70 + MENU_HEIGHT, 50, 20, "Dec"); - cpuregs_ctrl.pCDec->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pCDec->callback(cb_reg_c_dec); - cpuregs_ctrl.g->end(); + m_pCDec = new Fl_Round_Button(420, 70 + MENU_HEIGHT, 50, 20, "Dec"); + m_pCDec->type(FL_RADIO_BUTTON); + m_pCDec->callback(cb_reg_c_dec, this); + m_g->end(); } // Group the Reg D radio buttons togther { - cpuregs_ctrl.g = new Fl_Group(370, 90 + MENU_HEIGHT, 100, 20, ""); + m_g = new Fl_Group(370, 90 + MENU_HEIGHT, 100, 20, ""); // Display format for Reg D o = new Fl_Box(FL_NO_BOX, 340, 91+MENU_HEIGHT, 50, 15, "D"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - cpuregs_ctrl.pDHex = new Fl_Round_Button(370, 90 + MENU_HEIGHT, 50, 20, "Hex"); - cpuregs_ctrl.pDHex->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pDHex->callback(cb_reg_d_hex); - cpuregs_ctrl.pDHex->value(1); + m_pDHex = new Fl_Round_Button(370, 90 + MENU_HEIGHT, 50, 20, "Hex"); + m_pDHex->type(FL_RADIO_BUTTON); + m_pDHex->callback(cb_reg_d_hex, this); + m_pDHex->value(1); - cpuregs_ctrl.pDDec = new Fl_Round_Button(420, 90 + MENU_HEIGHT, 50, 20, "Dec"); - cpuregs_ctrl.pDDec->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pDDec->callback(cb_reg_d_dec); - cpuregs_ctrl.g->end(); + m_pDDec = new Fl_Round_Button(420, 90 + MENU_HEIGHT, 50, 20, "Dec"); + m_pDDec->type(FL_RADIO_BUTTON); + m_pDDec->callback(cb_reg_d_dec, this); + m_g->end(); } // Group the Reg E radio buttons togther { - cpuregs_ctrl.g = new Fl_Group(370, 110 + MENU_HEIGHT, 100, 20, ""); + m_g = new Fl_Group(370, 110 + MENU_HEIGHT, 100, 20, ""); // Display format for Reg E o = new Fl_Box(FL_NO_BOX, 340, 111+MENU_HEIGHT, 50, 15, "E"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - cpuregs_ctrl.pEHex = new Fl_Round_Button(370, 110 + MENU_HEIGHT, 50, 20, "Hex"); - cpuregs_ctrl.pEHex->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pEHex->callback(cb_reg_e_hex); - cpuregs_ctrl.pEHex->value(1); + m_pEHex = new Fl_Round_Button(370, 110 + MENU_HEIGHT, 50, 20, "Hex"); + m_pEHex->type(FL_RADIO_BUTTON); + m_pEHex->callback(cb_reg_e_hex, this); + m_pEHex->value(1); - cpuregs_ctrl.pEDec = new Fl_Round_Button(420, 110 + MENU_HEIGHT, 50, 20, "Dec"); - cpuregs_ctrl.pEDec->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pEDec->callback(cb_reg_e_dec); - cpuregs_ctrl.g->end(); + m_pEDec = new Fl_Round_Button(420, 110 + MENU_HEIGHT, 50, 20, "Dec"); + m_pEDec->type(FL_RADIO_BUTTON); + m_pEDec->callback(cb_reg_e_dec, this); + m_g->end(); } // Group the Reg H radio buttons togther { - cpuregs_ctrl.g = new Fl_Group(370, 130 + MENU_HEIGHT, 100, 20, ""); + m_g = new Fl_Group(370, 130 + MENU_HEIGHT, 100, 20, ""); // Display format for Reg H o = new Fl_Box(FL_NO_BOX, 340, 131+MENU_HEIGHT, 50, 15, "H"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - cpuregs_ctrl.pHHex = new Fl_Round_Button(370, 130 + MENU_HEIGHT, 50, 20, "Hex"); - cpuregs_ctrl.pHHex->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pHHex->callback(cb_reg_h_hex); - cpuregs_ctrl.pHHex->value(1); + m_pHHex = new Fl_Round_Button(370, 130 + MENU_HEIGHT, 50, 20, "Hex"); + m_pHHex->type(FL_RADIO_BUTTON); + m_pHHex->callback(cb_reg_h_hex, this); + m_pHHex->value(1); - cpuregs_ctrl.pHDec = new Fl_Round_Button(420, 130 + MENU_HEIGHT, 50, 20, "Dec"); - cpuregs_ctrl.pHDec->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pHDec->callback(cb_reg_h_dec); - cpuregs_ctrl.g->end(); + m_pHDec = new Fl_Round_Button(420, 130 + MENU_HEIGHT, 50, 20, "Dec"); + m_pHDec->type(FL_RADIO_BUTTON); + m_pHDec->callback(cb_reg_h_dec, this); + m_g->end(); } // Group the Reg L radio buttons togther { - cpuregs_ctrl.g = new Fl_Group(370, 150 + MENU_HEIGHT, 100, 20, ""); + m_g = new Fl_Group(370, 150 + MENU_HEIGHT, 100, 20, ""); // Display format for Reg L o = new Fl_Box(FL_NO_BOX, 340, 151+MENU_HEIGHT, 50, 15, "L"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - cpuregs_ctrl.pLHex = new Fl_Round_Button(370, 150 + MENU_HEIGHT, 50, 20, "Hex"); - cpuregs_ctrl.pLHex->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pLHex->callback(cb_reg_l_hex); - cpuregs_ctrl.pLHex->value(1); + m_pLHex = new Fl_Round_Button(370, 150 + MENU_HEIGHT, 50, 20, "Hex"); + m_pLHex->type(FL_RADIO_BUTTON); + m_pLHex->callback(cb_reg_l_hex, this); + m_pLHex->value(1); - cpuregs_ctrl.pLDec = new Fl_Round_Button(420, 150 + MENU_HEIGHT, 50, 20, "Dec"); - cpuregs_ctrl.pLDec->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pLDec->callback(cb_reg_l_dec); - cpuregs_ctrl.g->end(); + m_pLDec = new Fl_Round_Button(420, 150 + MENU_HEIGHT, 50, 20, "Dec"); + m_pLDec->type(FL_RADIO_BUTTON); + m_pLDec->callback(cb_reg_l_dec, this); + m_g->end(); } // Group the Reg PC radio buttons togther { - cpuregs_ctrl.g = new Fl_Group(520, 30 + MENU_HEIGHT, 100, 20, ""); + m_g = new Fl_Group(520, 30 + MENU_HEIGHT, 100, 20, ""); // Display format for Reg L o = new Fl_Box(FL_NO_BOX, 490, 31+MENU_HEIGHT, 50, 15, "PC"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - cpuregs_ctrl.pPCHex = new Fl_Round_Button(520, 30 + MENU_HEIGHT, 50, 20, "Hex"); - cpuregs_ctrl.pPCHex->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pPCHex->callback(cb_reg_pc_hex); - cpuregs_ctrl.pPCHex->value(1); + m_pPCHex = new Fl_Round_Button(520, 30 + MENU_HEIGHT, 50, 20, "Hex"); + m_pPCHex->type(FL_RADIO_BUTTON); + m_pPCHex->callback(cb_reg_pc_hex, this); + m_pPCHex->value(1); - cpuregs_ctrl.pPCDec = new Fl_Round_Button(570, 30 + MENU_HEIGHT, 50, 20, "Dec"); - cpuregs_ctrl.pPCDec->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pPCDec->callback(cb_reg_pc_dec); - cpuregs_ctrl.g->end(); + m_pPCDec = new Fl_Round_Button(570, 30 + MENU_HEIGHT, 50, 20, "Dec"); + m_pPCDec->type(FL_RADIO_BUTTON); + m_pPCDec->callback(cb_reg_pc_dec, this); + m_g->end(); } // Group the Reg SP radio buttons togther { - cpuregs_ctrl.g = new Fl_Group(520, 50 + MENU_HEIGHT, 100, 20, ""); + m_g = new Fl_Group(520, 50 + MENU_HEIGHT, 100, 20, ""); // Display format for Reg L o = new Fl_Box(FL_NO_BOX, 490, 51+MENU_HEIGHT, 50, 15, "SP"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - cpuregs_ctrl.pSPHex = new Fl_Round_Button(520, 50 + MENU_HEIGHT, 50, 20, "Hex"); - cpuregs_ctrl.pSPHex->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pSPHex->callback(cb_reg_sp_hex); - cpuregs_ctrl.pSPHex->value(1); + m_pSPHex = new Fl_Round_Button(520, 50 + MENU_HEIGHT, 50, 20, "Hex"); + m_pSPHex->type(FL_RADIO_BUTTON); + m_pSPHex->callback(cb_reg_sp_hex, this); + m_pSPHex->value(1); - cpuregs_ctrl.pSPDec = new Fl_Round_Button(570, 50 + MENU_HEIGHT, 50, 20, "Dec"); - cpuregs_ctrl.pSPDec->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pSPDec->callback(cb_reg_sp_dec); - cpuregs_ctrl.g->end(); + m_pSPDec = new Fl_Round_Button(570, 50 + MENU_HEIGHT, 50, 20, "Dec"); + m_pSPDec->type(FL_RADIO_BUTTON); + m_pSPDec->callback(cb_reg_sp_dec, this); + m_g->end(); } // Group the Reg BC radio buttons togther { - cpuregs_ctrl.g = new Fl_Group(520, 70 + MENU_HEIGHT, 100, 20, ""); + m_g = new Fl_Group(520, 70 + MENU_HEIGHT, 100, 20, ""); // Display format for Reg L o = new Fl_Box(FL_NO_BOX, 490, 71+MENU_HEIGHT, 50, 15, "BC"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - cpuregs_ctrl.pBCHex = new Fl_Round_Button(520, 70 + MENU_HEIGHT, 50, 20, "Hex"); - cpuregs_ctrl.pBCHex->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pBCHex->callback(cb_reg_bc_hex); - cpuregs_ctrl.pBCHex->value(1); + m_pBCHex = new Fl_Round_Button(520, 70 + MENU_HEIGHT, 50, 20, "Hex"); + m_pBCHex->type(FL_RADIO_BUTTON); + m_pBCHex->callback(cb_reg_bc_hex, this); + m_pBCHex->value(1); - cpuregs_ctrl.pBCDec = new Fl_Round_Button(570, 70 + MENU_HEIGHT, 50, 20, "Dec"); - cpuregs_ctrl.pBCDec->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pBCDec->callback(cb_reg_bc_dec); - cpuregs_ctrl.g->end(); + m_pBCDec = new Fl_Round_Button(570, 70 + MENU_HEIGHT, 50, 20, "Dec"); + m_pBCDec->type(FL_RADIO_BUTTON); + m_pBCDec->callback(cb_reg_bc_dec, this); + m_g->end(); } // Group the Reg DE radio buttons togther { - cpuregs_ctrl.g = new Fl_Group(520, 90 + MENU_HEIGHT, 100, 20, ""); + m_g = new Fl_Group(520, 90 + MENU_HEIGHT, 100, 20, ""); // Display format for Reg L o = new Fl_Box(FL_NO_BOX, 490, 91+MENU_HEIGHT, 50, 15, "DE"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - cpuregs_ctrl.pDEHex = new Fl_Round_Button(520, 90 + MENU_HEIGHT, 50, 20, "Hex"); - cpuregs_ctrl.pDEHex->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pDEHex->callback(cb_reg_de_hex); - cpuregs_ctrl.pDEHex->value(1); + m_pDEHex = new Fl_Round_Button(520, 90 + MENU_HEIGHT, 50, 20, "Hex"); + m_pDEHex->type(FL_RADIO_BUTTON); + m_pDEHex->callback(cb_reg_de_hex, this); + m_pDEHex->value(1); - cpuregs_ctrl.pDEDec = new Fl_Round_Button(570, 90 + MENU_HEIGHT, 50, 20, "Dec"); - cpuregs_ctrl.pDEDec->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pDEDec->callback(cb_reg_de_dec); - cpuregs_ctrl.g->end(); + m_pDEDec = new Fl_Round_Button(570, 90 + MENU_HEIGHT, 50, 20, "Dec"); + m_pDEDec->type(FL_RADIO_BUTTON); + m_pDEDec->callback(cb_reg_de_dec, this); + m_g->end(); } // Group the Reg HL radio buttons togther { - cpuregs_ctrl.g = new Fl_Group(520, 110 + MENU_HEIGHT, 100, 20, ""); + m_g = new Fl_Group(520, 110 + MENU_HEIGHT, 100, 20, ""); // Display format for Reg HL o = new Fl_Box(FL_NO_BOX, 490, 111+MENU_HEIGHT, 50, 15, "HL"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - cpuregs_ctrl.pHLHex = new Fl_Round_Button(520, 110 + MENU_HEIGHT, 50, 20, "Hex"); - cpuregs_ctrl.pHLHex->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pHLHex->callback(cb_reg_hl_hex); - cpuregs_ctrl.pHLHex->value(1); + m_pHLHex = new Fl_Round_Button(520, 110 + MENU_HEIGHT, 50, 20, "Hex"); + m_pHLHex->type(FL_RADIO_BUTTON); + m_pHLHex->callback(cb_reg_hl_hex, this); + m_pHLHex->value(1); - cpuregs_ctrl.pHLDec = new Fl_Round_Button(570, 110 + MENU_HEIGHT, 50, 20, "Dec"); - cpuregs_ctrl.pHLDec->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pHLDec->callback(cb_reg_hl_dec); - cpuregs_ctrl.g->end(); + m_pHLDec = new Fl_Round_Button(570, 110 + MENU_HEIGHT, 50, 20, "Dec"); + m_pHLDec->type(FL_RADIO_BUTTON); + m_pHLDec->callback(cb_reg_hl_dec, this); + m_g->end(); } // Group the Reg M radio buttons togther { - cpuregs_ctrl.g = new Fl_Group(520, 130 + MENU_HEIGHT, 100, 20, ""); + m_g = new Fl_Group(520, 130 + MENU_HEIGHT, 100, 20, ""); // Display format for Reg HL o = new Fl_Box(FL_NO_BOX, 490, 131+MENU_HEIGHT, 50, 15, "M"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - cpuregs_ctrl.pMHex = new Fl_Round_Button(520, 130 + MENU_HEIGHT, 50, 20, "Hex"); - cpuregs_ctrl.pMHex->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pMHex->callback(cb_reg_m_hex); - cpuregs_ctrl.pMHex->value(1); + m_pMHex = new Fl_Round_Button(520, 130 + MENU_HEIGHT, 50, 20, "Hex"); + m_pMHex->type(FL_RADIO_BUTTON); + m_pMHex->callback(cb_reg_m_hex, this); + m_pMHex->value(1); - cpuregs_ctrl.pMDec = new Fl_Round_Button(570, 130 + MENU_HEIGHT, 50, 20, "Dec"); - cpuregs_ctrl.pMDec->type(FL_RADIO_BUTTON); - cpuregs_ctrl.pMDec->callback(cb_reg_m_dec); - cpuregs_ctrl.g->end(); + m_pMDec = new Fl_Round_Button(570, 130 + MENU_HEIGHT, 50, 20, "Dec"); + m_pMDec->type(FL_RADIO_BUTTON); + m_pMDec->callback(cb_reg_m_dec, this); + m_g->end(); } + o = new Fl_Box(FL_NO_BOX, x-5, 170+MENU_HEIGHT, 5, 5, ""); + o->hide(); + g1->resizable(o); + g1->end(); + // Create Instruction Trace Text Boxes o = new Fl_Box(FL_NO_BOX, 20, 180+MENU_HEIGHT, 50, 15, "Instruction Trace"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - o = new Fl_Box(FL_DOWN_BOX, 20, 200+MENU_HEIGHT, 520, 124, ""); - cpuregs_ctrl.iInstTraceHead = 0; + m_pTraceBox = new Fl_Box(FL_DOWN_BOX, 20, 200+MENU_HEIGHT, 530-CPUREGS_TRACE_SCROLL_W, 124, ""); - // Create checkbox to disable realtime trace - cpuregs_ctrl.pDisableTrace = new Fl_Check_Button(200, 180+MENU_HEIGHT, 180, 20, "Disable Real-time Trace"); - cpuregs_ctrl.pDisableTrace->callback(cb_disable_realtime_trace); + // Create scroll bar for trace data + m_pScroll = new Fl_Scrollbar(550-CPUREGS_TRACE_SCROLL_W, 200+MENU_HEIGHT, CPUREGS_TRACE_SCROLL_W, 124); + m_pScroll->deactivate(); + // Set maximum value of scroll + int size = (int) (m_pScroll->h() / m_fontHeight); + m_pScroll->value(m_traceAvail - size+4, m_traceAvail/size, 0, 4); + m_pScroll->linesize(1); + m_pScroll->slider_size(1.0); + m_pScroll->callback(cb_scrollbar); + + Fl_Box* resize_box = new Fl_Box(FL_DOWN_BOX, 500, 200+MENU_HEIGHT, 5, 5, ""); + resize_box->hide(); + m_iInstTraceHead = 0; + m_iTraceHead = 0; + + // Create checkbox to disable realtime trace + m_pDisableTrace = new Fl_Check_Button(200, 180+MENU_HEIGHT, 180, 20, "Disable Real-time Trace"); + m_pDisableTrace->value(gDisableRealtimeTrace); + m_pDisableTrace->callback(cb_disable_realtime_trace, this); // Create Stack Box - o = new Fl_Box(FL_NO_BOX, 550, 180+MENU_HEIGHT, 50, 15, "Stack"); + o = new Fl_Box(FL_NO_BOX, 560, 180+MENU_HEIGHT, 50, 15, "Stack"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - o = new Fl_Box(FL_DOWN_BOX, 550, 200+MENU_HEIGHT, 60, 124, ""); + m_pStackBox = new Fl_Box(FL_DOWN_BOX, 560, 200+MENU_HEIGHT, 60, 124, ""); // Create Breakpoint edit boxes - o = new Fl_Box(FL_NO_BOX, 20, 375, 100, 15, "Breakpoints:"); + o = new Fl_Box(FL_NO_BOX, 20, 380, 100, 15, "Breakpoints:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - cpuregs_ctrl.pBreak1 = new Fl_Input(120, 375, 60, 20, ""); - cpuregs_ctrl.pBreak1->deactivate(); - cpuregs_ctrl.pBreak1->value(""); - cpuregs_ctrl.pBreakDisable1 = new Fl_Check_Button(125, 395, 40, 20, "Off"); - cpuregs_ctrl.pBreakDisable1->deactivate(); - cpuregs_ctrl.pBreak2 = new Fl_Input(200, 375, 60, 20, ""); - cpuregs_ctrl.pBreak2->deactivate(); - cpuregs_ctrl.pBreak2->value(""); - cpuregs_ctrl.pBreakDisable2 = new Fl_Check_Button(205, 395, 40, 20, "Off"); - cpuregs_ctrl.pBreakDisable2->deactivate(); - cpuregs_ctrl.pBreak3 = new Fl_Input(280, 375, 60, 20, ""); - cpuregs_ctrl.pBreak3->deactivate(); - cpuregs_ctrl.pBreak3->value(""); - cpuregs_ctrl.pBreakDisable3 = new Fl_Check_Button(285, 395, 40, 20, "Off"); - cpuregs_ctrl.pBreakDisable3->deactivate(); - cpuregs_ctrl.pBreak4 = new Fl_Input(360, 375, 60, 20, ""); - cpuregs_ctrl.pBreak4->deactivate(); - cpuregs_ctrl.pBreak4->value(""); - cpuregs_ctrl.pBreakDisable4 = new Fl_Check_Button(365, 395, 40, 20, "Off"); - cpuregs_ctrl.pBreakDisable4->deactivate(); - - cpuregs_ctrl.pDebugInts = new Fl_Check_Button(465, 375, 40, 20, "Debug ISRs"); - cpuregs_ctrl.pDebugInts->value(gDebugInts); + + // Breakpoint 1 + o = new Fl_Box(FL_NO_BOX, 120, 365, 60, 15, "F1"); + o->align(FL_ALIGN_INSIDE); + m_pBreak1 = new Fl_Input(120, 380, 60, 20, ""); + m_pBreak1->deactivate(); + m_pBreak1->value(""); + m_pBreakDisable1 = new Fl_Check_Button(125, 400, 40, 20, "Off"); + m_pBreakDisable1->deactivate(); + + // Breakpoint 2 + o = new Fl_Box(FL_NO_BOX, 200, 365, 60, 15, "F2"); + o->align(FL_ALIGN_INSIDE); + m_pBreak2 = new Fl_Input(200, 380, 60, 20, ""); + m_pBreak2->deactivate(); + m_pBreak2->value(""); + m_pBreakDisable2 = new Fl_Check_Button(205, 400, 40, 20, "Off"); + m_pBreakDisable2->deactivate(); + + // Breakpoint 3 + o = new Fl_Box(FL_NO_BOX, 280, 365, 60, 15, "F3"); + o->align(FL_ALIGN_INSIDE); + m_pBreak3 = new Fl_Input(280, 380, 60, 20, ""); + m_pBreak3->deactivate(); + m_pBreak3->value(""); + m_pBreakDisable3 = new Fl_Check_Button(285, 400, 40, 20, "Off"); + m_pBreakDisable3->deactivate(); + + // Breakpoint 4 + o = new Fl_Box(FL_NO_BOX, 360, 365, 60, 15, "F4"); + o->align(FL_ALIGN_INSIDE); + m_pBreak4 = new Fl_Input(360, 380, 60, 20, ""); + m_pBreak4->deactivate(); + m_pBreak4->value(""); + m_pBreakDisable4 = new Fl_Check_Button(365, 400, 40, 20, "Off"); + m_pBreakDisable4->deactivate(); + + if (m_saveBreakpoints) + { + // Set breakpoint values from user preferences + m_pBreak1->value((const char *) m_sBreak1); + m_pBreakDisable1->value(m_iBreakDis1); + m_pBreak2->value((const char *) m_sBreak2); + m_pBreakDisable2->value(m_iBreakDis2); + m_pBreak3->value((const char *) m_sBreak3); + m_pBreakDisable3->value(m_iBreakDis3); + m_pBreak4->value((const char *) m_sBreak4); + m_pBreakDisable4->value(m_iBreakDis4); + } + + m_pDebugInts = new Fl_Check_Button(465, 375, 90, 20, "Debug ISRs"); + m_pDebugInts->value(gDebugInts); + m_pDebugInts->callback(cb_debugInts, this); + + m_pAutoScroll = new Fl_Check_Button(465, 395, 80, 20, "Auto Scroll"); + m_pAutoScroll->value(m_autoScroll); + m_pAutoScroll->callback(cb_autoscroll, this); + + m_pSaveBreak = new Fl_Check_Button(465, 415, 120, 20, "Save Breakpoints"); + m_pSaveBreak->value(m_saveBreakpoints); + m_pSaveBreak->callback(cb_saveBreakpoints, this); // Create Stop button - cpuregs_ctrl.pStop = new Fl_Button(30, 445, 80, 25, "Stop"); - cpuregs_ctrl.pStop->callback(cb_debug_stop); + m_pStop = new Fl_Button(30, 445, 80, 25, "Stop"); + m_pStop->callback(cb_debug_stop, this); // Create Step button - cpuregs_ctrl.pStep = new Fl_Button(130, 445, 80, 25, "Step"); - cpuregs_ctrl.pStep->deactivate(); - cpuregs_ctrl.pStep->callback(cb_debug_step); + m_pStep = new Fl_Button(130, 445, 80, 25, "Step"); + m_pStep->deactivate(); + m_pStep->callback(cb_debug_step, this); // Create Step button - cpuregs_ctrl.pStepOver = new Fl_Button(230, 445, 100, 25, "Step Over"); - cpuregs_ctrl.pStepOver->deactivate(); - cpuregs_ctrl.pStepOver->callback(cb_debug_step_over); + m_pStepOver = new Fl_Button(230, 445, 100, 25, "Step Over"); + m_pStepOver->deactivate(); + m_pStepOver->callback(cb_debug_step_over, this); // Create Run button - cpuregs_ctrl.pRun = new Fl_Button(350, 445, 80, 25, "Run"); - cpuregs_ctrl.pRun->deactivate(); - cpuregs_ctrl.pRun->callback(cb_debug_run); + m_pRun = new Fl_Button(350, 445, 80, 25, "Run"); + m_pRun->deactivate(); + m_pRun->callback(cb_debug_run, this); - // Create Redraw button - cpuregs_ctrl.pRedraw = new Fl_Button(450, 445, 80, 25, "Redraw"); - cpuregs_ctrl.pRedraw->deactivate(); - cpuregs_ctrl.pRedraw->callback(cb_redraw_trace); + resizable(resize_box); - // Set Debug callback - debug_set_monitor_callback(debug_cpuregs_cb); + check_breakpoint_entries(); +} - // Show the new window - gcpuw->show(); +/* +============================================================================ +CpuRegisters class destructor. +============================================================================ +*/ +VTCpuRegs::~VTCpuRegs() +{ + // Delete the trace data buffer + if (m_pTraceData != NULL) + { + delete m_pTraceData; + m_pTraceData = NULL; + } +} - // Indicate an active debug window - gDebugActive++; - cpuregs_ctrl.breakMonitorFreq = 0; - for (int x = 0; x < 5; x++) +void VTCpuRegs::draw(void) +{ + static int drawcount = 0; + Fl_Double_Window::draw(); + + // Select 12 point Courier font + fl_font(FL_COURIER, m_fontSize); + m_fontHeight = fl_height() + 1; + + // Test for a change in height + if (m_lastH != m_pTraceBox->h()) + { + // Save the current trace box height + m_lastH = m_pTraceBox->h(); + + int current_val = m_pScroll->value(); + int size = (int) (m_pScroll->h() / m_fontHeight); + if (current_val + size + 4 > m_traceAvail) + current_val = m_traceAvail - size + 4; + int max_size = m_traceAvail-size+4; + if (max_size < 0) + max_size = 4; + m_pScroll->value(current_val, m_traceAvail/size, 0, max_size); + } + + if (gDisableRealtimeTrace && !gStopped) + { + // Make our window current for drawing + make_current(); + + // Clear rectangle + fl_color(FL_GRAY); + fl_rectf(m_pTraceBox->x()+3, m_pTraceBox->y()+3, + m_pTraceBox->w()-6, m_pTraceBox->h()-6); + fl_rectf(m_pStackBox->x()+3, m_pStackBox->y()+3, + m_pStackBox->w()-6, m_pStackBox->h()-6); + + // Select 11 point Courier font + fl_font(FL_COURIER,18); + fl_color(FL_BLACK); + + fl_draw("Realtime trace disabled", 55, 212+MENU_HEIGHT+3*m_fontHeight); + } + else + cb_redraw_trace(NULL, this); +} + +/* +============================================================================ +Load user preferences +============================================================================ +*/ +void VTCpuRegs::LoadPrefs(void) +{ + int temp; + char str[100]; + + virtualt_prefs.get("CpuRegs_autoScroll", m_autoScroll, 1); + virtualt_prefs.get("CpuRegs_x", m_x, -1); + virtualt_prefs.get("CpuRegs_y", m_y, -1); + virtualt_prefs.get("CpuRegs_w", m_w, -1); + virtualt_prefs.get("CpuRegs_h", m_h, -1); + virtualt_prefs.get("CpuRegs_traceCount", m_traceCount, CPUREGS_TRACE_COUNT); + virtualt_prefs.get("CpuRegs_fontSize", m_fontSize, 12); + virtualt_prefs.get("CpuRegs_disableTrace", gDisableRealtimeTrace, 0); + virtualt_prefs.get("CpuRegs_debugInts", temp, 1); + gDebugInts = temp; + virtualt_prefs.get("CpuRegs_rememberBreakpoints", m_saveBreakpoints, 1); + + if (m_saveBreakpoints) { - cpuregs_ctrl.breakAddr[x] = -1; - cpuregs_ctrl.breakEnable[x] = 1; + virtualt_prefs.get("CpuRegs_break1", str, "", sizeof(str)); + m_sBreak1 = str; + virtualt_prefs.get("CpuRegs_break2", str, "", sizeof(str)); + m_sBreak2 = str; + virtualt_prefs.get("CpuRegs_break3", str, "", sizeof(str)); + m_sBreak3 = str; + virtualt_prefs.get("CpuRegs_break4", str, "", sizeof(str)); + m_sBreak4 = str; + virtualt_prefs.get("CpuRegs_break1_disable", m_iBreakDis1, 0); + virtualt_prefs.get("CpuRegs_break2_disable", m_iBreakDis2, 0); + virtualt_prefs.get("CpuRegs_break3_disable", m_iBreakDis3, 0); + virtualt_prefs.get("CpuRegs_break4_disable", m_iBreakDis4, 0); } } +/* +============================================================================ +Load user preferences +============================================================================ +*/ +void VTCpuRegs::SavePrefs(void) +{ + virtualt_prefs.set("CpuRegs_autoScroll", m_autoScroll); + virtualt_prefs.set("CpuRegs_x", x()); + virtualt_prefs.set("CpuRegs_y", y()); + virtualt_prefs.set("CpuRegs_w", w()); + virtualt_prefs.set("CpuRegs_h", h()); + virtualt_prefs.set("CpuRegs_traceCount", m_traceCount); + virtualt_prefs.set("CpuRegs_fontSize", m_fontSize); + virtualt_prefs.set("CpuRegs_disableTrace", gDisableRealtimeTrace); + virtualt_prefs.set("CpuRegs_debugInts", gDebugInts); + virtualt_prefs.set("CpuRegs_rememberBreakpoints", m_saveBreakpoints); + if (m_saveBreakpoints) + { + virtualt_prefs.set("CpuRegs_break1", m_pBreak1->value()); + virtualt_prefs.set("CpuRegs_break2", m_pBreak2->value()); + virtualt_prefs.set("CpuRegs_break3", m_pBreak3->value()); + virtualt_prefs.set("CpuRegs_break4", m_pBreak4->value()); + virtualt_prefs.set("CpuRegs_break1_disable", m_pBreakDisable1->value()); + virtualt_prefs.set("CpuRegs_break2_disable", m_pBreakDisable2->value()); + virtualt_prefs.set("CpuRegs_break3_disable", m_pBreakDisable3->value()); + virtualt_prefs.set("CpuRegs_break4_disable", m_pBreakDisable4->value()); + } +} +/* +============================================================================ +Scroll to bottom of trace window +============================================================================ +*/ +void VTCpuRegs::ScrollToBottom(void) +{ + // Update the value to the bottom of the scroll window + int size = (int) (m_pScroll->h() / m_fontHeight); + int max_size = m_traceAvail-size+4; + int new_value = m_traceAvail - size+4; + + // Test if we have less than a screen of data to display + if (m_traceAvail < m_traceCount) + new_value++; + if (max_size < 0) + max_size = 4; + if (new_value < 0) + new_value = 0; + m_pScroll->value(new_value, m_traceAvail/size, 0, max_size); + m_pScroll->linesize(1); + if (m_traceAvail > 0) + { + m_pScroll->step(size / m_traceAvail); + m_pScroll->slider_size((double) size/ (double) m_traceAvail); + } + else + m_pScroll->slider_size(1.0); +} + +/* +============================================================================ +Our FLTK event handler. Capture key-strokes here and don't allow ESC to +close our window, which is the default. +============================================================================ +*/ +int VTCpuRegs::handle(int eventId) +{ + unsigned int key; + + switch (eventId) + { + case FL_KEYDOWN: + key = Fl::event_key(); + + if (key == FL_Escape) + return 1; + else if (key == FL_F + 1) + { + m_pBreak1->take_focus(); + m_pBreak1->position(0, m_pBreak1->size()); + } + else if (key == FL_F + 2) + { + m_pBreak2->take_focus(); + m_pBreak2->position(0, m_pBreak2->size()); + } + else if (key == FL_F + 3) + { + m_pBreak3->take_focus(); + m_pBreak3->position(0, m_pBreak3->size()); + } + else if (key == FL_F + 4) + { + m_pBreak4->take_focus(); + m_pBreak4->position(0, m_pBreak4->size()); + } + + break; + + default: + break; + } + + return Fl_Double_Window::handle(eventId); +} + +/* +============================================================================ +Menu callback for saving trace data +============================================================================ +*/ +void cb_save_trace(Fl_Widget* w, void* pOpaque) +{ + FILE *fd; + Flu_File_Chooser *fc; + int c, idx; + char lineStr[120]; + + fl_cursor(FL_CURSOR_WAIT); +#ifdef __APPLE__ + fc = new Flu_File_Chooser(path,"*.txt",Fl_File_Chooser::CREATE,"Save trace as"); +#else + fc = new Flu_File_Chooser(".","*.txt",Fl_File_Chooser::CREATE,"Save trace as"); +#endif + fl_cursor(FL_CURSOR_DEFAULT); + fc->preview(0); + // FileWin.value(0)="RAM.bin" + fc->show(); + + while (fc->visible()) + Fl::wait(); + + // Check if a file was selected + if (fc->value() == 0) + { + delete fc; + return; + } + if (strlen(fc->value()) == 0) + { + delete fc; + return; + } + // Try to open the ouput file + fd = fopen(fc->value(), "rb+"); + if (fd != NULL) + { + // File already exists! Check for overwrite! + fclose(fd); + + c = fl_choice("Overwrite existing file?", "Cancel", "Yes", "No"); + + if ((c == 0) || (c == 2)) + { + delete fc; + return; + } + } + + fd = fopen(fc->value(), "wb+"); + if (fd == NULL) + { + fl_message("Error opening %s for write", fc->value()); + delete fc; + return; + } + + delete fc; + + // Now write trace data to the file + idx = gcpuw->m_iTraceHead; + for (c = 0; c < gcpuw->m_traceAvail; c++) + { + build_trace_line(idx, lineStr); + fprintf(fd, "%s\n", lineStr); + if (++idx >= gcpuw->m_traceCount) + idx = 0; + } + + // Finally,close the file + fclose(fd); +} + +/* +============================================================================ +Menu callback for clearing trace data +============================================================================ +*/ +void cb_clear_trace(Fl_Widget* w, void* pOpaque) +{ + // Set availalbe trace items to zero + gcpuw->m_traceAvail = 0; + gcpuw->m_iTraceHead = 0; + + // Trace the current instruction + trace_instruction(); + + // Update the scrollbar and redraw + cb_scrollbar(gcpuw->m_pScroll, gcpuw); + int size = (int) (gcpuw->m_pScroll->h() / gcpuw->m_fontHeight); + gcpuw->m_pScroll->value(0, gcpuw->m_traceAvail/size, 0, 4); + gcpuw->redraw(); +} + +/* +============================================================================ +Menu callback for run +============================================================================ +*/ +static void cb_menu_run(Fl_Widget* w, void* pOpaque) +{ + if (gStopped) + cb_debug_run(w, gcpuw); +} + +/* +============================================================================ +Menu callback for stop +============================================================================ +*/ +static void cb_menu_stop(Fl_Widget* w, void* pOpaque) +{ + if (!gStopped) + cb_debug_stop(w, gcpuw); +} + +/* +============================================================================ +Menu callback for step +============================================================================ +*/ +static void cb_menu_step(Fl_Widget* w, void* pOpaque) +{ + if (gStopped) + cb_debug_step(w, gcpuw); +} + +/* +============================================================================ +Menu callback for step over +============================================================================ +*/ +static void cb_menu_step_over(Fl_Widget* w, void* pOpaque) +{ + if (gStopped) + cb_debug_step_over(w, gcpuw); +} + +/* +============================================================================ +Define a local struct for the setup parameters. +============================================================================ +*/ +typedef struct trace_setup_params +{ + Fl_Input* pTraceDepth; + Fl_Input* pFontSize; + char sDepth[20]; + char sFontSize[20]; +} trace_setup_params_t; + +/* +============================================================================ +Callback for Trace Setup dialog +============================================================================ +*/ +static void cb_setupdlg_win(Fl_Widget* w, void* pOpaque) +{ +} + +/* +============================================================================ +Callback for Trace Setup Ok button +============================================================================ +*/ +static void cb_setupdlg_OK(Fl_Widget* w, void* pOpaque) +{ + trace_setup_params_t* p = (trace_setup_params_t *) pOpaque; + cpu_trace_data_t* pData; + int newDepth, copyLen; + int srcIdx, dstIdx; + + // Save values + if (strlen(p->pFontSize->value()) > 0) + { + // update the font size + gcpuw->m_fontSize = atoi(p->pFontSize->value()); + if (gcpuw->m_fontSize < 6) + gcpuw->m_fontSize = 6; + + // Upate the font height base on the font size + fl_font(FL_COURIER, gcpuw->m_fontSize); + gcpuw->m_fontHeight = fl_height() + 1; + } + + // Get the updated trace depth + newDepth = atoi(p->pTraceDepth->value()); + if (newDepth > 0 && newDepth != gcpuw->m_traceCount) + { + if (newDepth > 64000000) + { + show_error("Come on, seriously? That's over a Gig of RAM! The max I'm willing to do is 64,000,000."); + return; + } + // Allocate a new buffer for trace data + pData = new cpu_trace_data_t[newDepth]; + + if (pData == NULL) + { + MString err; + + err.Format("Unable to allocate %d bytes!\n", newDepth * sizeof(cpu_trace_data_t)); + show_error((const char *) err); + return; + } + + // Calculate length of new copy + copyLen = newDepth; + if (copyLen > gcpuw->m_traceAvail) + copyLen = gcpuw->m_traceAvail; + + // Copy data from old buffer to new buffer + srcIdx = gcpuw->m_iTraceHead; + for (dstIdx = 0; dstIdx < copyLen; dstIdx++) + { + // Check if srcIdx has rolled over + if (srcIdx >= gcpuw->m_traceAvail) + srcIdx =0; + + // Copy the data + pData[dstIdx] = gcpuw->m_pTraceData[srcIdx++]; + } + + // Test for overflow during copy + if (srcIdx >= newDepth) + srcIdx = 0; + + // Now replace the old buffer with the new one and update the count + delete gcpuw->m_pTraceData; + gcpuw->m_pTraceData = pData; + gcpuw->m_iTraceHead = srcIdx; + gcpuw->m_traceCount = newDepth; + gcpuw->m_traceAvail = copyLen; + + // Redraw the window + gcpuw->ScrollToBottom(); + } + + // Redraw the window + cb_redraw_trace(NULL, NULL); + + // Now hide the parent dialog + w->parent()->hide(); +} + +/* +============================================================================ +Callback for Trace Setup Cancel button +============================================================================ +*/ +static void cb_setupdlg_cancel(Fl_Widget* w, void* pOpaque) +{ + // Hide the parent dialog so we cancel out + w->parent()->hide(); +} + +/* +============================================================================ +Menu callback for setup trace +============================================================================ +*/ +void cb_setup_trace(Fl_Widget* w, void* pOpaque) +{ + Fl_Box* b; + Fl_Window* pWin; + trace_setup_params_t p; + + // Get socket interface preferences + // Create Peripheral Setup window + pWin = new Fl_Window(300, 160, "Trace Configuration"); + + /* Create input field for trace depth */ + b = new Fl_Box(20, 20, 100, 20, "Trace Depth"); + b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + p.pTraceDepth = new Fl_Input(120, 20, 80, 20, ""); + p.pTraceDepth->align(FL_ALIGN_LEFT); + sprintf(p.sDepth, "%d", gcpuw->m_traceCount); + p.pTraceDepth->value(p.sDepth); + b = new Fl_Box(210, 20, 100, 20, "64M max"); + b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + + /* Create input field for font size */ + b = new Fl_Box(20, 50, 100, 20, "Font Size"); + b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + p.pFontSize = new Fl_Input(120, 50, 60, 20, ""); + p.pFontSize->align(FL_ALIGN_LEFT); + sprintf(p.sFontSize, "%d", gcpuw->m_fontSize); + p.pFontSize->value(p.sFontSize); + + // Cancel button + { Fl_Button* o = new Fl_Button(80, 120, 60, 30, "Cancel"); + o->callback((Fl_Callback*) cb_setupdlg_cancel); + } + + // OK button + { Fl_Return_Button* o = new Fl_Return_Button(160, 120, 60, 30, "OK"); + o->callback((Fl_Callback*) cb_setupdlg_OK, &p); + } + + // Loop until user presses OK or Cancel + pWin->show(); + while (pWin->visible()) + Fl::wait(); + + // Delete the window + delete pWin; +} diff --git a/src/cpuregs.h b/src/cpuregs.h index f9b82c7..a20bdd7 100644 --- a/src/cpuregs.h +++ b/src/cpuregs.h @@ -36,115 +36,184 @@ #include #include #include +#include +#include + +#include "MString.h" void cb_CpuRegs(Fl_Widget* w, void*); -typedef struct cpuregs_ctrl_struct +/* +================================================ +Structure to keep track of CPU instruction trace +================================================ +*/ +typedef struct cpu_trace_data { - Fl_Menu_Bar* pMenu; - - Fl_Check_Button* pEnable; - - Fl_Input* pRegA; - Fl_Input* pRegF; - Fl_Input* pRegB; - Fl_Input* pRegC; - Fl_Input* pRegD; - Fl_Input* pRegE; - Fl_Input* pRegH; - Fl_Input* pRegL; - Fl_Input* pRegBC; - Fl_Input* pRegDE; - Fl_Input* pRegHL; - Fl_Input* pRegPC; - Fl_Input* pRegSP; - Fl_Input* pRegM; - - Fl_Input* pBreak1; - Fl_Input* pBreak2; - Fl_Input* pBreak3; - Fl_Input* pBreak4; - Fl_Check_Button* pBreakDisable1; - Fl_Check_Button* pBreakDisable2; - Fl_Check_Button* pBreakDisable3; - Fl_Check_Button* pBreakDisable4; - - Fl_Check_Button* pDebugInts; - - Fl_Check_Button* pSFlag; - Fl_Check_Button* pZFlag; - Fl_Check_Button* pTSFlag; - Fl_Check_Button* pACFlag; - Fl_Check_Button* pPFlag; - Fl_Check_Button* pOVFlag; - Fl_Check_Button* pXFlag; - Fl_Check_Button* pCFlag; - - Fl_Round_Button* pAllHex; - Fl_Round_Button* pAllDec; - Fl_Round_Button* pAHex; - Fl_Round_Button* pADec; - Fl_Round_Button* pBHex; - Fl_Round_Button* pBDec; - Fl_Round_Button* pCHex; - Fl_Round_Button* pCDec; - Fl_Round_Button* pDHex; - Fl_Round_Button* pDDec; - Fl_Round_Button* pEHex; - Fl_Round_Button* pEDec; - Fl_Round_Button* pHHex; - Fl_Round_Button* pHDec; - Fl_Round_Button* pLHex; - Fl_Round_Button* pLDec; - Fl_Round_Button* pPCHex; - Fl_Round_Button* pPCDec; - Fl_Round_Button* pSPHex; - Fl_Round_Button* pSPDec; - Fl_Round_Button* pBCHex; - Fl_Round_Button* pBCDec; - Fl_Round_Button* pDEHex; - Fl_Round_Button* pDEDec; - Fl_Round_Button* pHLHex; - Fl_Round_Button* pHLDec; - Fl_Round_Button* pMHex; - Fl_Round_Button* pMDec; - Fl_Round_Button* pBreakHex; - Fl_Round_Button* pBreakDec; - - Fl_Box* pInstTrace[8]; - char sInstTrace[8][120]; - int iInstTraceHead; - Fl_Check_Button* pDisableTrace; - - int breakAddr[5]; - int breakEnable[5]; - int breakMonitorFreq; - - Fl_Button* pStop; - Fl_Button* pStep; - Fl_Button* pStepOver; - Fl_Button* pRun; - Fl_Button* pRedraw; - - char sPCfmt[8]; - char sSPfmt[8]; - char sAfmt[8]; - char sBfmt[8]; - char sCfmt[8]; - char sDfmt[8]; - char sEfmt[8]; - char sHfmt[8]; - char sLfmt[8]; - char sBCfmt[8]; - char sDEfmt[8]; - char sHLfmt[8]; - char sMfmt[8]; - char sBreakfmt[8]; - - Fl_Group* g; - -} cpuregs_ctrl_t; + unsigned short pc; + unsigned short sp; + unsigned short hl; + unsigned short de; + unsigned short bc; + unsigned short af; + unsigned short opcode; + unsigned short operand; +} cpu_trace_data_t; + +#define CPUREGS_TRACE_COUNT 1024 +#define CPUREGS_TRACE_SCROLL_W 15 +/* +================================================ +The CPU Registers Window +================================================ +*/ +class VTCpuRegs : public Fl_Double_Window +{ +public: + VTCpuRegs(int x, int y, const char* title); + ~VTCpuRegs(); + + void RegAllDec(void); + void RegAllHex(void); + + void activate_controls(void); + void deactivate_controls(void); + void get_reg_edits(void); + void check_breakpoint_entries(void); + void LoadPrefs(void); + void SavePrefs(void); + void ScrollToBottom(void); + + virtual void draw(void); + virtual int handle(int event); + + Fl_Menu_Bar* m_pMenu; + Fl_Check_Button* m_pEnable; + + Fl_Input* m_pRegA; + Fl_Input* m_pRegF; + Fl_Input* m_pRegB; + Fl_Input* m_pRegC; + Fl_Input* m_pRegD; + Fl_Input* m_pRegE; + Fl_Input* m_pRegH; + Fl_Input* m_pRegL; + Fl_Input* m_pRegBC; + Fl_Input* m_pRegDE; + Fl_Input* m_pRegHL; + Fl_Input* m_pRegPC; + Fl_Input* m_pRegSP; + Fl_Input* m_pRegM; + + Fl_Input* m_pBreak1; + Fl_Input* m_pBreak2; + Fl_Input* m_pBreak3; + Fl_Input* m_pBreak4; + Fl_Check_Button* m_pBreakDisable1; + Fl_Check_Button* m_pBreakDisable2; + Fl_Check_Button* m_pBreakDisable3; + Fl_Check_Button* m_pBreakDisable4; + + Fl_Check_Button* m_pDebugInts; + + Fl_Check_Button* m_pSFlag; + Fl_Check_Button* m_pZFlag; + Fl_Check_Button* m_pTSFlag; + Fl_Check_Button* m_pACFlag; + Fl_Check_Button* m_pPFlag; + Fl_Check_Button* m_pOVFlag; + Fl_Check_Button* m_pXFlag; + Fl_Check_Button* m_pCFlag; + + Fl_Round_Button* m_pAllHex; + Fl_Round_Button* m_pAllDec; + Fl_Round_Button* m_pAHex; + Fl_Round_Button* m_pADec; + Fl_Round_Button* m_pBHex; + Fl_Round_Button* m_pBDec; + Fl_Round_Button* m_pCHex; + Fl_Round_Button* m_pCDec; + Fl_Round_Button* m_pDHex; + Fl_Round_Button* m_pDDec; + Fl_Round_Button* m_pEHex; + Fl_Round_Button* m_pEDec; + Fl_Round_Button* m_pHHex; + Fl_Round_Button* m_pHDec; + Fl_Round_Button* m_pLHex; + Fl_Round_Button* m_pLDec; + Fl_Round_Button* m_pPCHex; + Fl_Round_Button* m_pPCDec; + Fl_Round_Button* m_pSPHex; + Fl_Round_Button* m_pSPDec; + Fl_Round_Button* m_pBCHex; + Fl_Round_Button* m_pBCDec; + Fl_Round_Button* m_pDEHex; + Fl_Round_Button* m_pDEDec; + Fl_Round_Button* m_pHLHex; + Fl_Round_Button* m_pHLDec; + Fl_Round_Button* m_pMHex; + Fl_Round_Button* m_pMDec; + Fl_Round_Button* m_pBreakHex; + Fl_Round_Button* m_pBreakDec; + + Fl_Box* m_pTraceBox; + Fl_Box* m_pStackBox; + char m_sInstTrace[64][120]; + int m_iInstTraceHead; + Fl_Check_Button* m_pDisableTrace; + + cpu_trace_data_t* m_pTraceData; + int m_iTraceHead; + int m_traceCount; + int m_traceAvail; + + int m_breakAddr[5]; + int m_breakEnable[5]; + int m_breakMonitorFreq; + + Fl_Button* m_pStop; + Fl_Button* m_pStep; + Fl_Button* m_pStepOver; + Fl_Button* m_pRun; + + char m_sPCfmt[8]; + char m_sSPfmt[8]; + char m_sAfmt[8]; + char m_sBfmt[8]; + char m_sCfmt[8]; + char m_sDfmt[8]; + char m_sEfmt[8]; + char m_sHfmt[8]; + char m_sLfmt[8]; + char m_sBCfmt[8]; + char m_sDEfmt[8]; + char m_sHLfmt[8]; + char m_sMfmt[8]; + char m_sBreakfmt[8]; + + MString m_sBreak1; + MString m_sBreak2; + MString m_sBreak3; + MString m_sBreak4; + int m_iBreakDis1; + int m_iBreakDis2; + int m_iBreakDis3; + int m_iBreakDis4; + + Fl_Scrollbar* m_pScroll; // Trace buffer scroll bar + Fl_Group* m_g; + + Fl_Check_Button* m_pAutoScroll; + Fl_Check_Button* m_pSaveBreak; + + // Preferences + int m_autoScroll; + int m_saveBreakpoints; + int m_x, m_y, m_h, m_w; + int m_lastH; + int m_fontSize, m_fontHeight; +}; #endif diff --git a/src/disassemble.cpp b/src/disassemble.cpp index 51c1f3e..b39fe02 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -926,3 +926,41 @@ int VTDis::DisassembleLine(int address, char* line) return 1+op_len; } + +int VTDis::DisassembleLine(int address, unsigned char opcode, unsigned short operand, char* line) +{ + char arg[60]; + unsigned char op_len; + + // Determine length of this opcode + op_len = gLenTable[opcode] & 0x03; + + // Print the address and opcode value to the temporary line buffer + sprintf(line, "%04XH ", address); + + // Print the opcode text to the temp line buffer + strcat(line, gStrTable[opcode]); + + // Check if this opcode has a single byte argument + if (op_len == 1) + { + // Single byte argument + sprintf(arg, "%02XH", operand & 0xFF); + strcat(line, arg); + } + + // Check if this opcode as a 2 byte argument + else if (op_len == 2) + { + // Double byte argument + sprintf(arg, "%04XH", operand); + strcat(line, arg); + + if (m_WantComments) + { + AppendComments(line, opcode, operand); + } + } + + return 1+op_len; +} diff --git a/src/disassemble.h b/src/disassemble.h index b211c27..c617615 100644 --- a/src/disassemble.h +++ b/src/disassemble.h @@ -51,6 +51,7 @@ class VTDis void SetTextViewer(class Fl_Text_Editor* pTextViewer); void CopyIntoMem(unsigned char * ptr, int len); int DisassembleLine(int address, char* line); + int DisassembleLine(int address, unsigned char opcode, unsigned short operand, char* line); void SetBaseAddress(int address); void AppendComments(char* line, int opcode, int address); diff --git a/src/display.cpp b/src/display.cpp index ed2112c..4727da6 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include //Added by J. VERNET for pref files // see also cb_xxxxxx @@ -124,10 +123,16 @@ Fl_Button* gFrameButton; Fl_Button* gDetailButton; Fl_Button* gFkeyLabelsButton; +class VT_Ide; + extern char* print_xpm[]; extern Fl_Menu_Item gPrintMenu[]; +extern void Ide_SavePrefs(void); -extern Fl_Pixmap gPrinterIcon; +extern Fl_Pixmap gPrinterIcon; +extern VTCpuRegs* gcpuw; +extern Fl_Window* gmew; +extern VT_Ide * gpIde; void switch_model(int model); void key_delay(void); @@ -286,6 +291,39 @@ void close_disp_cb(Fl_Widget* w, void*) { if (gpDisp != NULL) { + int cpuregs_was_open = FALSE; + int ide_was_open = FALSE; + int memedit_was_open = FALSE; + + // Check if there is a CpuRegs window open and tell it to + // save user preferences if there is + if (gcpuw != NULL) + { + gcpuw->SavePrefs(); + cpuregs_was_open = TRUE; + } + + // Check if there is a Memory Edit window open and tell it to + // save user preferences is there is + if (gmew != NULL) + { + MemoryEditor_SavePrefs(); + memedit_was_open = TRUE; + } + + // Check if the IDE is opened and tell it to save user + // preferences if it is + if (gpIde != NULL) + { + Ide_SavePrefs(); + ide_was_open = TRUE; + } + + // Save open status + virtualt_prefs.set("WindowState_MemEdit", memedit_was_open); + virtualt_prefs.set("WindowState_CpuRegs", cpuregs_was_open); + virtualt_prefs.set("WindowState_IDE", ide_was_open); + gExitApp = 1; gExitLoop = 1; } @@ -4751,3 +4789,30 @@ void T200_Disp::redraw_active() } } +/* +================================================================= +Initialize (open) other windows that were previously opened the +last time the application closed. +================================================================= +*/ +void init_other_windows(void) +{ + int memedit_was_open, cpuregs_was_open, ide_was_open; + + /* Load the open state of various windows */ + virtualt_prefs.get("WindowState_MemEdit", memedit_was_open, 0); + virtualt_prefs.get("WindowState_CpuRegs", cpuregs_was_open, 0); + virtualt_prefs.get("WindowState_IDE", ide_was_open, 0); + + // If the Memory Editor was opened previously, then re-open it + if (memedit_was_open && (gmew == NULL)) + cb_MemoryEditor(NULL, NULL); + + // If the CpuRegs window was opened previously, then re-open it + if (cpuregs_was_open && (gcpuw == NULL)) + cb_CpuRegs(NULL, NULL); + + // Give the focus back to the main VirtualT window + MainWin->show(); +} + diff --git a/src/display.h b/src/display.h index dbdf61a..c9e9847 100644 --- a/src/display.h +++ b/src/display.h @@ -52,6 +52,7 @@ void t200_command(unsigned char ir, unsigned char data); unsigned char t200_readport(unsigned char port); void handle_simkey(void); void switch_model(int); +void init_other_windows(void); typedef int (*get_key_t)(int); typedef int (*event_key_t)(void); diff --git a/src/ide.cpp b/src/ide.cpp index 8ff948c..2c4aacc 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -242,6 +242,28 @@ Fl_Menu_Item gRootMenu[] = { Fl_Pixmap gTextDoc( textdoc_xpm ), gComputer( computer_xpm ); +/* +======================================================= +Save the user's preferences for IDE window size. +======================================================= +*/ +void Ide_SavePrefs(void) +{ + // Save window parameters to preferences + if (save_window_size) + { + virtualt_prefs.set("IdeX", gpIde->x()); + virtualt_prefs.set("IdeY", gpIde->y()); + virtualt_prefs.set("IdeW", gpIde->w()); + virtualt_prefs.set("IdeH", gpIde->h()); + int ideTabHeight = gpIde->h() - gpIde->SpliterHeight(); + int ideTreeWidth = gpIde->SpliterWidth(); + virtualt_prefs.set("IdeTabheight", ideTabHeight); + virtualt_prefs.set("IdeTreeWidth", ideTreeWidth); + } + gpIde->SavePrefs(); +} + /* ======================================================= Callback routine for the close box of the IDE window @@ -264,19 +286,7 @@ void close_ide_cb(Fl_Widget* w, void*) gpIde->SaveProject(); } - // Save window parameters to preferences - if (save_window_size) - { - virtualt_prefs.set("IdeX", gpIde->x()); - virtualt_prefs.set("IdeY", gpIde->y()); - virtualt_prefs.set("IdeW", gpIde->w()); - virtualt_prefs.set("IdeH", gpIde->h()); - int ideTabHeight = gpIde->h() - gpIde->SpliterHeight(); - int ideTreeWidth = gpIde->SpliterWidth(); - virtualt_prefs.set("IdeTabheight", ideTabHeight); - virtualt_prefs.set("IdeTreeWidth", ideTreeWidth); - } - gpIde->SavePrefs(); + Ide_SavePrefs(); // Okay, close the window setMonitorWindow(0); diff --git a/src/ide.h b/src/ide.h index b63711b..79f0492 100644 --- a/src/ide.h +++ b/src/ide.h @@ -36,6 +36,9 @@ #include "FLU/Flu_Combo_List.h" #include "FLU/Flu_Return_Button.h" #include "FLU/Flu_Button.h" +#include "FLU/Flu_Tree_Browser.h" +#include "FLU/flu_pixmaps.h" +#include "FLU/Flu_File_Chooser.h" #include "MString.h" #include "vtobj.h" diff --git a/src/m100emu.c b/src/m100emu.c index ad3ecb9..14fd7ae 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -1459,6 +1459,7 @@ int main(int argc, char **argv) init_throttle_timer(); /* Initialize the throttle timer */ init_remote(); /* Initialize the remote control */ init_lpt(); /* Initialize the printer subsystem */ + init_other_windows(); /* Initialize other windows that were opened (memedit, regs, etc. */ get_model_time(); /* Load the emulated time for current model */ /* Perform Emulation */ diff --git a/src/memedit.cpp b/src/memedit.cpp index 4f7ec80..3d657e6 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -136,8 +136,9 @@ Fl_Menu_Item gMemEdit_menuitems[] = { memedit_ctrl_t memedit_ctrl; memedit_dialog_t gDialog; -Fl_Window *gmew; // Global Memory Edit Window -unsigned char gDispMemory[8192]; +Fl_Window *gmew; // Global Memory Edit Window +unsigned char gDispMemory[8192]; +extern Fl_Preferences virtualt_prefs; /* ============================================================================ @@ -148,6 +149,8 @@ void cb_memeditwin (Fl_Widget* w, void*) { gmew->hide(); mem_clear_monitor_callback(memory_monitor_cb); + MemoryEditor_SavePrefs(); + delete gmew; gmew = NULL; } @@ -858,6 +861,23 @@ void cb_MemoryEditor (Fl_Widget* w, void*) // Set Memory Monitor callback mem_set_monitor_callback(memory_monitor_cb); + // Get the user preferences for the memory editor + MemoryEditor_LoadPrefs(); + + // Resize if user preferences have been set + if (memedit_ctrl.pMemEdit->m_x != -1 && memedit_ctrl.pMemEdit->m_y != -1 && + memedit_ctrl.pMemEdit->m_w != -1 && memedit_ctrl.pMemEdit->m_h != -1) + { + int newx, newy, neww, newh; + + newx = memedit_ctrl.pMemEdit->m_x; + newy = memedit_ctrl.pMemEdit->m_y; + neww = memedit_ctrl.pMemEdit->m_w; + newh = memedit_ctrl.pMemEdit->m_h; + + gmew->resize(newx, newy, neww, newh); + } + gmew->show(); } @@ -2288,4 +2308,28 @@ void T100_MemEditor::UpdateAddressText() memedit_ctrl.pMemRange->value(string); } +/* +============================================================================ +Load user preferences +============================================================================ +*/ +void MemoryEditor_LoadPrefs(void) +{ + virtualt_prefs.get("MemEdit_x", memedit_ctrl.pMemEdit->m_x, -1); + virtualt_prefs.get("MemEdit_y", memedit_ctrl.pMemEdit->m_y, -1); + virtualt_prefs.get("MemEdit_w", memedit_ctrl.pMemEdit->m_w, -1); + virtualt_prefs.get("MemEdit_h", memedit_ctrl.pMemEdit->m_h, -1); +} +/* +============================================================================ +Load user preferences +============================================================================ +*/ +void MemoryEditor_SavePrefs(void) +{ + virtualt_prefs.set("MemEdit_x", gmew->x()); + virtualt_prefs.set("MemEdit_y", gmew->y()); + virtualt_prefs.set("MemEdit_w", gmew->w()); + virtualt_prefs.set("MemEdit_h", gmew->h()); +} diff --git a/src/memedit.h b/src/memedit.h index c814ba6..a5de412 100644 --- a/src/memedit.h +++ b/src/memedit.h @@ -37,6 +37,8 @@ void cb_MemoryEditor (Fl_Widget* w, void*); void cb_MemoryEditorUpdate(void); +void MemoryEditor_LoadPrefs(void); +void MemoryEditor_SavePrefs(void); #define MENU_HEIGHT 32 @@ -55,6 +57,7 @@ class T100_MemEditor : public Fl_Widget void UpdateDispMem(void); void MoveTo(int value); int m_FirstLine; + int m_x, m_y, m_w, m_h; // user preferences for window position protected: // virtual int handle(int event); @@ -86,7 +89,6 @@ class T100_MemEditor : public Fl_Widget long m_SelEndCol; Fl_Scrollbar* m_pScroll; - }; #endif diff --git a/src/memory.c b/src/memory.c index 2f9dce4..6076f64 100644 --- a/src/memory.c +++ b/src/memory.c @@ -857,7 +857,7 @@ void cold_boot_mem(void) { int x; - if (gReMem) + if (gReMem && (gRex == 0)) { } else @@ -954,6 +954,15 @@ void save_remem_ram(void) /* Open ReMem file */ fd = fopen(mem_setup.remem_file, "wb+"); + /* Print error if unable to open the file */ + if (fd == NULL) + { + char msg[100]; + sprintf("Could not save Remem file %s", mem_setup.remem_file); + show_error(msg); + return; + } + /* Check if file opened successfully */ if (fd != 0) { @@ -985,6 +994,15 @@ void save_rampac_ram(void) /* Open Rampac file */ fd = fopen(mem_setup.rampac_file, "wb+"); + /* Print error if unable to open the file */ + if (fd == NULL) + { + char msg[100]; + sprintf("Could not save Rampac file %s", mem_setup.rampac_file); + show_error(msg); + return; + } + /* Check if file opened successfully */ if (fd != 0) { @@ -1015,6 +1033,15 @@ void save_rex2_ram(void) /* Open ReMem file */ fd = fopen(mem_setup.rex2_ram_file, "wb+"); + /* Print error if unable to open the file */ + if (fd == NULL) + { + char msg[100]; + sprintf("Could not save REX2 RAM file %s", mem_setup.rex2_ram_file); + show_error(msg); + return; + } + /* Check if file opened successfully */ if (fd != 0) { @@ -1042,6 +1069,15 @@ void save_rex_flash(void) /* Open ReMem file */ fd = fopen(mem_setup.rex_flash_file, "wb+"); + /* Print error if unable to open the file */ + if (fd == NULL) + { + char msg[100]; + sprintf("Could not save REX file %s", mem_setup.rex_flash_file); + show_error(msg); + return; + } + /* Check if file opened successfully */ if (fd != 0) { @@ -1170,6 +1206,15 @@ void load_remem_ram(void) /* Open ReMem file */ fd = fopen(mem_setup.remem_file, "rb+"); + /* Print error if unable to open the file */ + if (fd == NULL) + { + char msg[100]; + sprintf("Could not open Remem file %s", mem_setup.remem_file); + show_error(msg); + return; + } + /* Check if file opened successfully */ if ((fd != 0) && (gReMemFlash1.pFlash != NULL) && (gReMemFlash2.pFlash != NULL)) { @@ -1236,6 +1281,15 @@ void load_rampac_ram(void) /* Open Rampac file */ fd = fopen(mem_setup.rampac_file, "rb+"); + /* Print error if unable to open the file */ + if (fd == NULL) + { + char msg[100]; + sprintf("Could not open Rampac file %s", mem_setup.rampac_file); + show_error(msg); + return; + } + /* Check if file opened successfully */ if (fd != 0) { @@ -1264,6 +1318,15 @@ void load_rex_flash(void) /* Open ReMem file */ fd = fopen(mem_setup.rex_flash_file, "rb+"); + /* Print error if unable to open the file */ + if (fd == NULL) + { + char msg[100]; + sprintf("Could not open REX file %s", mem_setup.rex_flash_file); + show_error(msg); + return; + } + /* Check if file opened successfully */ if ((fd != 0) && (gRexFlash.pFlash != NULL)) { @@ -1295,6 +1358,15 @@ void load_rex2_ram(void) /* Open ReMem file */ fd = fopen(mem_setup.rex2_ram_file, "rb+"); + /* Print error if unable to open the file */ + if (fd == NULL) + { + char msg[100]; + sprintf("Could not open REX2 RAM file %s", mem_setup.rex2_ram_file); + show_error(msg); + return; + } + /* Check if file opened successfully */ if (fd != 0) { From a8a779d4ea6975fa6637d3ce1df9243a614e72fc Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 5 Feb 2013 01:36:11 +0000 Subject: [PATCH 210/327] Fixed Linux compile issues with new changes to CpuRegs window, resolved conflicts with release.txt file, made minor updates to assembler. --- release.txt | 2 ++ src/assemble.cpp | 13 +++++++++---- src/cpuregs.cpp | 28 ++++++++++++++++------------ src/cpuregs.h | 3 ++- src/memory.c | 16 ++++++++-------- 5 files changed, 37 insertions(+), 25 deletions(-) diff --git a/release.txt b/release.txt index d478a92..3ba3287 100644 --- a/release.txt +++ b/release.txt @@ -40,6 +40,8 @@ v1.6 10. Now reports error if REX / ReMem memory cannot be loaded / saved. +11. Updated REX emulation to support REX3 for PC8201 state machine changes. + ==================== v1.5 July 9th, 2011 ==================== diff --git a/src/assemble.cpp b/src/assemble.cpp index 6947ade..afd55ea 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -125,6 +125,7 @@ unsigned char gShift[20] = { 0, }; const char* types[5] = { "", "a label", "an equate", "a set", "an extern" }; +static char local_filename[256]; VTAssembler::VTAssembler() { @@ -366,7 +367,7 @@ int VTAssembler::PerformSubstitution(CMacro* pMacro, const char *pLoc) ptr += pExp->m_Literal.GetLength(); // Copy the replacement text to the new string - strcpy(pNew, pArgs[c]); + strncpy(pNew, pArgs[c], argLen[c]); pNew += argLen[c]; subst = TRUE; @@ -387,7 +388,7 @@ int VTAssembler::PerformSubstitution(CMacro* pMacro, const char *pLoc) *pNew++ = *ptr++; *pNew = '\0'; - //printf("New line = %s", pNewLine); + printf("New line = %s", pNewLine); // Delete the old m_pInLine and replace with the new one delete[] m_pInLine; @@ -1460,7 +1461,8 @@ void VTAssembler::include(const char *filename) // Now loading from a different FD! m_fd = fd; - gFilename = filename; + strcpy(local_filename, filename); + gFilename = local_filename; a85parse(); fclose(m_fd); @@ -1473,7 +1475,8 @@ void VTAssembler::include(const char *filename) m_pInLine = m_IncludeInLine[m_IncludeDepth]; m_InLineCount = m_IncludeInLineCount[m_IncludeDepth]; m_FileIndex = m_IncludeIndex[m_IncludeDepth]; - gFilename = (const char *) m_Filenames[m_FileIndex]; + strcpy(local_filename, (const char *) m_Filenames[m_FileIndex]); + gFilename = local_filename; memcpy(&a85parse_pcb, &m_ParserPCBs[m_IncludeDepth], sizeof(a85parse_pcb_type)); } @@ -1517,6 +1520,8 @@ void VTAssembler::equate(const char *name) pSymbol->m_SymType = SYM_EQUATE; pSymbol->m_pRange = m_ActiveAddr; + printf("EQU: %s\n", (const char *) pSymbol->m_Name); + // Try to evaluate the equation. Note that we may not be able to // successfully evaluate it at this point because it may contain // a forward reference, so don't report any errors yet. diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index 83f8793..ed1c177 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -66,16 +66,16 @@ int gDebugMonitorFreq = 32768; VTDis cpu_dis; extern Fl_Preferences virtualt_prefs; -extern volatile UINT64 cycles=0; +extern volatile UINT64 cycles; // Menu item callback definitions -void cb_save_trace(Fl_Widget* w, void*); -void cb_clear_trace(Fl_Widget* w, void*); -void cb_menu_run(Fl_Widget* w, void*); -void cb_menu_stop(Fl_Widget* w, void*); -void cb_menu_step(Fl_Widget* w, void*); -void cb_menu_step_over(Fl_Widget* w, void*); -void cb_setup_trace(Fl_Widget* w, void*); +static void cb_save_trace(Fl_Widget* w, void*); +static void cb_clear_trace(Fl_Widget* w, void*); +static void cb_menu_run(Fl_Widget* w, void*); +static void cb_menu_stop(Fl_Widget* w, void*); +static void cb_menu_step(Fl_Widget* w, void*); +static void cb_menu_step_over(Fl_Widget* w, void*); +static void cb_setup_trace(Fl_Widget* w, void*); // Other prototypes void debug_cpuregs_cb (int); @@ -2140,7 +2140,8 @@ CpuRegisters class constructor. Creates all controls within the window. ============================================================================ */ VTCpuRegs::VTCpuRegs(int x, int y, const char *title) : - Fl_Double_Window(x, y, title) + //Fl_Double_Window(x, y, title) + Fl_Window(x, y, title) { Fl_Box* o; int c; @@ -2737,8 +2738,8 @@ VTCpuRegs::~VTCpuRegs() void VTCpuRegs::draw(void) { - static int drawcount = 0; - Fl_Double_Window::draw(); + //Fl_Double_Window::draw(); + Fl_Window::draw(); // Select 12 point Courier font fl_font(FL_COURIER, m_fontSize); @@ -2780,6 +2781,7 @@ void VTCpuRegs::draw(void) } else cb_redraw_trace(NULL, this); + } /* @@ -2879,6 +2881,7 @@ void VTCpuRegs::ScrollToBottom(void) } else m_pScroll->slider_size(1.0); + damage(FL_DAMAGE_ALL); } /* @@ -2925,7 +2928,8 @@ int VTCpuRegs::handle(int eventId) break; } - return Fl_Double_Window::handle(eventId); + //return Fl_Double_Window::handle(eventId); + return Fl_Window::handle(eventId); } /* diff --git a/src/cpuregs.h b/src/cpuregs.h index a20bdd7..f5149d7 100644 --- a/src/cpuregs.h +++ b/src/cpuregs.h @@ -68,7 +68,8 @@ typedef struct cpu_trace_data The CPU Registers Window ================================================ */ -class VTCpuRegs : public Fl_Double_Window +//class VTCpuRegs : public Fl_Double_Window +class VTCpuRegs : public Fl_Window { public: VTCpuRegs(int x, int y, const char* title); diff --git a/src/memory.c b/src/memory.c index 6076f64..0e5b438 100644 --- a/src/memory.c +++ b/src/memory.c @@ -958,7 +958,7 @@ void save_remem_ram(void) if (fd == NULL) { char msg[100]; - sprintf("Could not save Remem file %s", mem_setup.remem_file); + sprintf(msg, "Could not save Remem file %s", mem_setup.remem_file); show_error(msg); return; } @@ -998,7 +998,7 @@ void save_rampac_ram(void) if (fd == NULL) { char msg[100]; - sprintf("Could not save Rampac file %s", mem_setup.rampac_file); + sprintf(msg, "Could not save Rampac file %s", mem_setup.rampac_file); show_error(msg); return; } @@ -1037,7 +1037,7 @@ void save_rex2_ram(void) if (fd == NULL) { char msg[100]; - sprintf("Could not save REX2 RAM file %s", mem_setup.rex2_ram_file); + sprintf(msg, "Could not save REX2 RAM file %s", mem_setup.rex2_ram_file); show_error(msg); return; } @@ -1073,7 +1073,7 @@ void save_rex_flash(void) if (fd == NULL) { char msg[100]; - sprintf("Could not save REX file %s", mem_setup.rex_flash_file); + sprintf(msg, "Could not save REX file %s", mem_setup.rex_flash_file); show_error(msg); return; } @@ -1210,7 +1210,7 @@ void load_remem_ram(void) if (fd == NULL) { char msg[100]; - sprintf("Could not open Remem file %s", mem_setup.remem_file); + sprintf(msg, "Could not open Remem file %s", mem_setup.remem_file); show_error(msg); return; } @@ -1285,7 +1285,7 @@ void load_rampac_ram(void) if (fd == NULL) { char msg[100]; - sprintf("Could not open Rampac file %s", mem_setup.rampac_file); + sprintf(msg, "Could not open Rampac file %s", mem_setup.rampac_file); show_error(msg); return; } @@ -1322,7 +1322,7 @@ void load_rex_flash(void) if (fd == NULL) { char msg[100]; - sprintf("Could not open REX file %s", mem_setup.rex_flash_file); + sprintf(msg, "Could not open REX file %s", mem_setup.rex_flash_file); show_error(msg); return; } @@ -1362,7 +1362,7 @@ void load_rex2_ram(void) if (fd == NULL) { char msg[100]; - sprintf("Could not open REX2 RAM file %s", mem_setup.rex2_ram_file); + sprintf(msg, "Could not open REX2 RAM file %s", mem_setup.rex2_ram_file); show_error(msg); return; } From 5e5bdb146c15b9c97e8715ec7cc14b508fe8e258 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 5 Feb 2013 01:39:53 +0000 Subject: [PATCH 211/327] Fixed issue in cpuregs.cpp with extern "C" linker error linking to C variable "cycles". --- src/cpuregs.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index ed1c177..168e323 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -66,6 +66,8 @@ int gDebugMonitorFreq = 32768; VTDis cpu_dis; extern Fl_Preferences virtualt_prefs; + +extern "C" extern volatile UINT64 cycles; // Menu item callback definitions From a760e817697baf970e32573ebc6096613f08ea1a Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 5 Feb 2013 01:41:17 +0000 Subject: [PATCH 212/327] Fixed gcc error with extern "C" extern syntax. --- src/cpuregs.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index 168e323..eadf3ce 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -68,7 +68,9 @@ VTDis cpu_dis; extern Fl_Preferences virtualt_prefs; extern "C" +{ extern volatile UINT64 cycles; +} // Menu item callback definitions static void cb_save_trace(Fl_Widget* w, void*); From da554071561929db78576a27b57e3b15278e3aae Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 5 Feb 2013 03:15:24 +0000 Subject: [PATCH 213/327] Modified CPU Register highlighting to inverse-video and fixed a couple of bugs with look-ahead disassembly. --- src/cpuregs.cpp | 78 ++++++++++++++++++++++++++++++++++++++++--------- src/cpuregs.h | 1 + 2 files changed, 66 insertions(+), 13 deletions(-) diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index eadf3ce..5e02ebe 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -168,6 +168,14 @@ int str_to_i(const char *pStr) hex = TRUE; break; } + if ((pStr[x] == 'h') || (pStr[x] == 'H')) + { + hex = TRUE; + break; + } + + if (pStr[x] == ' ') + break; } } @@ -175,7 +183,7 @@ int str_to_i(const char *pStr) if (hex) { x = 0; val = 0; - while ((pStr[x] != '\0') && (pStr[x] != 'h') && (pStr[x] != 'H')) + while ((pStr[x] != '\0') && (pStr[x] != 'h') && (pStr[x] != 'H') && (pStr[x] != ' ')) { digit = pStr[x] > '9' ? (pStr[x] | 0x60) - 'a' + 10 : pStr[x] - '0'; val = val * 16 + digit; @@ -482,7 +490,10 @@ void cb_redraw_trace(Fl_Widget* w, void* pOpaque) lines = gcpuw->m_pTraceBox->h() / gcpuw->m_fontHeight; // Select 11 point Courier font - fl_font(FL_COURIER, gcpuw->m_fontSize); + if (gcpuw->m_inverseHilight) + fl_font(FL_COURIER_BOLD, gcpuw->m_fontSize); + else + fl_font(FL_COURIER, gcpuw->m_fontSize); fl_color(FL_BLACK); // Initialize last_sp and last_pc in case trace is clear @@ -505,7 +516,12 @@ void cb_redraw_trace(Fl_Widget* w, void* pOpaque) // Now draw the Instruction Trace if (x == lines-1) - fl_font(FL_COURIER_BOLD, gcpuw->m_fontSize); + { + if (gcpuw->m_inverseHilight) + fl_color(FL_DARK_BLUE); + else + fl_font(FL_COURIER_BOLD, gcpuw->m_fontSize); + } fl_push_clip(gcpuw->m_pTraceBox->x(), gcpuw->m_pTraceBox->y(), gcpuw->m_pTraceBox->w()-3, gcpuw->m_pTraceBox->h()); fl_draw(gcpuw->m_sInstTrace[draw], 25, trace_top+x*gcpuw->m_fontHeight); @@ -540,13 +556,25 @@ void cb_redraw_trace(Fl_Widget* w, void* pOpaque) /* Build the trace text */ last_pc = build_trace_line(draw, &lineStr[0]); + // Clip the drawing + fl_push_clip(gcpuw->m_pTraceBox->x()+2, gcpuw->m_pTraceBox->y()+3, + gcpuw->m_pTraceBox->w()-4, gcpuw->m_pTraceBox->h()-6); + /* If on the execution line, make the font bold */ if (x+firstLine == gcpuw->m_traceAvail-1) - fl_font(FL_COURIER_BOLD, gcpuw->m_fontSize); + { + if (gcpuw->m_inverseHilight) + { + fl_color(FL_DARK_BLUE); + fl_rectf(gcpuw->m_pTraceBox->x()+3, trace_top+(x-1)*gcpuw->m_fontHeight+5, + gcpuw->m_pTraceBox->w()-6, gcpuw->m_fontHeight); + fl_color(FL_WHITE); + } + else + fl_font(FL_COURIER_BOLD, gcpuw->m_fontSize); + } // Finally, draw the trace on the window - fl_push_clip(gcpuw->m_pTraceBox->x(), gcpuw->m_pTraceBox->y(), - gcpuw->m_pTraceBox->w()-3, gcpuw->m_pTraceBox->h()); fl_draw(lineStr, 25, trace_top+x*gcpuw->m_fontHeight); fl_pop_clip(); if (++draw >= gcpuw->m_traceAvail) @@ -556,7 +584,10 @@ void cb_redraw_trace(Fl_Widget* w, void* pOpaque) if (x+firstLine == gcpuw->m_traceAvail-1) { // Change back to normal font - fl_font(FL_COURIER, gcpuw->m_fontSize); + if (gcpuw->m_inverseHilight) + fl_color(FL_BLACK); + else + fl_font(FL_COURIER, gcpuw->m_fontSize); // Search opcode for conditional branching if (((strncmp(&lineStr[7], "JZ", 2) == 0) || @@ -636,7 +667,12 @@ void cb_redraw_trace(Fl_Widget* w, void* pOpaque) // If trace is empty, then make 1st (current) inst bold if (x == 0) - fl_font(FL_COURIER_BOLD, gcpuw->m_fontSize); + { + if (gcpuw->m_inverseHilight) + fl_color(FL_DARK_BLUE); + else + fl_font(FL_COURIER_BOLD, gcpuw->m_fontSize); + } // Disassemble the next line that hasn't executed yet last_pc += cpu_dis.DisassembleLine(last_pc, lineStr); @@ -644,7 +680,12 @@ void cb_redraw_trace(Fl_Widget* w, void* pOpaque) fl_draw(lineStr, 25, trace_top+x*gcpuw->m_fontHeight); if (x == 0) - fl_font(FL_COURIER, gcpuw->m_fontSize); + { + if (gcpuw->m_inverseHilight) + fl_color(FL_BLACK); + else + fl_font(FL_COURIER, gcpuw->m_fontSize); + } } } } @@ -2809,6 +2850,7 @@ void VTCpuRegs::LoadPrefs(void) virtualt_prefs.get("CpuRegs_debugInts", temp, 1); gDebugInts = temp; virtualt_prefs.get("CpuRegs_rememberBreakpoints", m_saveBreakpoints, 1); + virtualt_prefs.get("CpuRegs_inversHilight", m_inverseHilight, 1); if (m_saveBreakpoints) { @@ -2844,6 +2886,8 @@ void VTCpuRegs::SavePrefs(void) virtualt_prefs.set("CpuRegs_disableTrace", gDisableRealtimeTrace); virtualt_prefs.set("CpuRegs_debugInts", gDebugInts); virtualt_prefs.set("CpuRegs_rememberBreakpoints", m_saveBreakpoints); + virtualt_prefs.set("CpuRegs_inversHilight", m_inverseHilight); + if (m_saveBreakpoints) { virtualt_prefs.set("CpuRegs_break1", m_pBreak1->value()); @@ -3086,10 +3130,11 @@ Define a local struct for the setup parameters. */ typedef struct trace_setup_params { - Fl_Input* pTraceDepth; - Fl_Input* pFontSize; - char sDepth[20]; - char sFontSize[20]; + Fl_Input* pTraceDepth; + Fl_Input* pFontSize; + Fl_Check_Button* pInverseHilight; + char sDepth[20]; + char sFontSize[20]; } trace_setup_params_t; /* @@ -3126,6 +3171,9 @@ static void cb_setupdlg_OK(Fl_Widget* w, void* pOpaque) gcpuw->m_fontHeight = fl_height() + 1; } + // Get Inverse Highlight selection + gcpuw->m_inverseHilight = p->pInverseHilight->value(); + // Get the updated trace depth newDepth = atoi(p->pTraceDepth->value()); if (newDepth > 0 && newDepth != gcpuw->m_traceCount) @@ -3230,6 +3278,10 @@ void cb_setup_trace(Fl_Widget* w, void* pOpaque) sprintf(p.sFontSize, "%d", gcpuw->m_fontSize); p.pFontSize->value(p.sFontSize); + /* Create checkbox for hilight style */ + p.pInverseHilight = new Fl_Check_Button(20, 80, 190, 20, "Inverse Video Hilight"); + p.pInverseHilight->value(gcpuw->m_inverseHilight); + // Cancel button { Fl_Button* o = new Fl_Button(80, 120, 60, 30, "Cancel"); o->callback((Fl_Callback*) cb_setupdlg_cancel); diff --git a/src/cpuregs.h b/src/cpuregs.h index f5149d7..a4122a2 100644 --- a/src/cpuregs.h +++ b/src/cpuregs.h @@ -214,6 +214,7 @@ class VTCpuRegs : public Fl_Window int m_x, m_y, m_h, m_w; int m_lastH; int m_fontSize, m_fontHeight; + int m_inverseHilight; }; #endif From 51ccb01c2fafcf9b0fa17b22aa867924004b3beb Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 5 Feb 2013 17:23:59 +0000 Subject: [PATCH 214/327] Added color hilighting to CPU Registers trace window and option to display registers as 16-bit in the trace. --- src/cpuregs.cpp | 347 +++++++++++++++++++++++++++++++++++++++++------- src/cpuregs.h | 22 ++- 2 files changed, 318 insertions(+), 51 deletions(-) diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index 5e02ebe..6178c83 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -430,6 +430,176 @@ void VTCpuRegs::get_reg_edits(void) check_breakpoint_entries(); } +/* +============================================================================ +Draws the specified string at the given x,y location using color syntax +hilighting rules. +============================================================================ +*/ +void draw_color_syntax(const char* lineStr, int x, int y, int bold = FALSE) +{ + int curx, idx, c, char_width; + char str[20]; + cpu_trace_colors_t* pColors = &gcpuw->m_traceColors; + + // Start at given x location + curx = x; + char_width = (int) fl_width(" "); + + // Copy and draw the address + strncpy(str, lineStr, 7); + str[7] = '\0'; + idx = 7; + fl_color(pColors->addr); + if (bold && !gcpuw->m_inverseHilight) + fl_font(FL_COURIER_BOLD_ITALIC, gcpuw->m_fontSize); + else if (gcpuw->m_inverseHilight) + fl_font(FL_COURIER_BOLD, gcpuw->m_fontSize); + else + fl_font(FL_COURIER, gcpuw->m_fontSize); + fl_draw(str, curx, y); + curx += (int) fl_width(str); + + // Copy and draw the instruction + c = 0; + while (lineStr[idx] != ' ' && lineStr[idx] != '\0') + str[c++] = lineStr[idx++]; + // Get the space too + if (lineStr[idx] != '\0') + str[c++] = lineStr[idx++]; + str[c] = '\0'; + fl_color(pColors->inst); + if (!bold) + fl_font(FL_COURIER_BOLD, gcpuw->m_fontSize); + fl_draw(str, curx, y); + curx += (int) fl_width(str); + + // Back to the selected font size + if (bold && !gcpuw->m_inverseHilight) + fl_font(FL_COURIER_BOLD_ITALIC, gcpuw->m_fontSize); + else if (gcpuw->m_inverseHilight) + fl_font(FL_COURIER_BOLD, gcpuw->m_fontSize); + else + fl_font(FL_COURIER, gcpuw->m_fontSize); + + // Check for end of string in case this is a look-ahead instruction + if (lineStr[idx] == '\0') + { + // Back to foreground color and return + fl_color(pColors->foreground); + return; + } + + // Determine the operand type. First check for A,blah format + if (lineStr[idx+1] == ',') + { + fl_color(pColors->reg); + str[0] = lineStr[idx]; + str[1] = '\0'; + fl_draw(str, curx, y); + curx += char_width; + fl_color(pColors->foreground); + fl_draw(",", curx, y); + curx += char_width; + idx += 2; + } + + // Now determine any remaining operand type. First look for register A, B, M, PSW, etc. + if (lineStr[idx+1] == ' ' || lineStr[idx+1] == 'S' || lineStr[idx+1] == '\0') + // It's a register operand + fl_color(pColors->reg); + else if (lineStr[idx+2] == 'H') + // It's a numeric value + fl_color(pColors->number); + else + // It's an address + fl_color(pColors->addr); + + // Copy the operand up to the 1st space + c = 0; + while (lineStr[idx] != ' ' && lineStr[idx] != '\0') + str[c++] = lineStr[idx++]; + + // Now copy the spaces + while (lineStr[idx] == ' ') + str[c++] = lineStr[idx++]; + str[c] = '\0'; + + // Draw the operand + fl_draw(str, curx, y); + curx += (int) fl_width(str); + + // Check if we have trace data or if this is a look-ahead instruction + if (lineStr[idx] == '\0') + { + // Back to the default color + fl_color(pColors->foreground); + return; + } + + // Draw the A register + fl_color(pColors->reg); + str[0] = lineStr[idx++]; + str[1] = '\0'; + fl_draw(str, curx, y); + curx += char_width; + fl_color(pColors->foreground); + str[0] = lineStr[idx++]; + fl_draw(str, curx, y); + curx += char_width; + + // Draw the A register value + fl_color(pColors->number); + strncpy(str, &lineStr[idx], 2); + str[2] = '\0'; + fl_draw(str, curx, y); + curx += char_width * 2; + idx += 2; + + // Draw the flags + fl_color(pColors->flags); + strncpy(str, &lineStr[idx], 11); + str[11] = '\0'; + fl_draw(str, curx, y); + curx += (int) fl_width(str); + idx += 11; + + // Now print the registers + while (lineStr[idx] != '\0') + { + // Copy next register to our temp string + c = 0; + while (lineStr[idx] != ':') + str[c++] = lineStr[idx++]; + str[c] = '\0'; + fl_color(pColors->reg); + fl_draw(str, curx, y); + curx += (int) fl_width(str); + + // Copy and draw the ':' and spaces + fl_color(pColors->foreground); + fl_draw(":", curx, y); + curx += char_width; + idx++; + + // Copy the register value + c = 0; + str[c++] = lineStr[idx++]; + while (lineStr[idx] != ' ' && lineStr[idx] != '\0') + str[c++] = lineStr[idx++]; + // Copy the spaces too + while (lineStr[idx] == ' ') + str[c++] = lineStr[idx++]; + str[c] = '\0'; + fl_color(pColors->foreground); + fl_draw(str, curx, y); + curx += (int) fl_width(str); + } + + // Back to the default color + fl_color(pColors->foreground); +} + /* ============================================================================ Callback routine to redraw the trace and stack areas @@ -457,9 +627,13 @@ int build_trace_line(int line, char* lineStr) fl & CF_BIT ? 'C':' '); // Append regs after opcode - sprintf(str, "A:%02X %s B:%02X C:%02X D:%02X E:%02X H:%02X L:%02X SP:%02X", - pTrace->af >> 8, flags, pTrace->bc >> 8, pTrace->bc & 0xFF, pTrace->de >> 8, - pTrace->de & 0xFF, pTrace->hl >> 8, pTrace->de & 0xFF, pTrace->sp); + if (gcpuw->m_showAs16Bit) + sprintf(str, "A:%02X %s BC:%04X DE:%04X HL:%04X SP:%02X", + pTrace->af >> 8, flags, pTrace->bc, pTrace->de, pTrace->hl, pTrace->sp); + else + sprintf(str, "A:%02X %s B:%02X C:%02X D:%02X E:%02X H:%02X L:%02X SP:%02X", + pTrace->af >> 8, flags, pTrace->bc >> 8, pTrace->bc & 0xFF, pTrace->de >> 8, + pTrace->de & 0xFF, pTrace->hl >> 8, pTrace->de & 0xFF, pTrace->sp); strcat(lineStr, str); return last_pc; @@ -470,18 +644,15 @@ int build_trace_line(int line, char* lineStr) Callback routine to redraw the trace and stack areas ============================================================================ */ -void cb_redraw_trace(Fl_Widget* w, void* pOpaque) +void redraw_trace(Fl_Widget* w, void* pOpaque) { int x, draw, lines, last_pc, last_sp; char lineStr[120], str[100]; int trace_top = gcpuw->m_pTraceBox->y() + gcpuw->m_fontHeight - 4; - int lookahead = 0; - - // Make our window current for drawing - gcpuw->make_current(); + int lookahead = 0, bold; // Clear rectangle - fl_color(FL_GRAY); + fl_color(gcpuw->m_traceColors.background); fl_rectf(gcpuw->m_pTraceBox->x()+3, gcpuw->m_pTraceBox->y()+3, gcpuw->m_pTraceBox->w()-6, gcpuw->m_pTraceBox->h()-6); fl_rectf(gcpuw->m_pStackBox->x()+3, gcpuw->m_pStackBox->y()+3, @@ -494,7 +665,7 @@ void cb_redraw_trace(Fl_Widget* w, void* pOpaque) fl_font(FL_COURIER_BOLD, gcpuw->m_fontSize); else fl_font(FL_COURIER, gcpuw->m_fontSize); - fl_color(FL_BLACK); + fl_color(gcpuw->m_traceColors.foreground); // Initialize last_sp and last_pc in case trace is clear last_sp = SP; @@ -511,20 +682,18 @@ void cb_redraw_trace(Fl_Widget* w, void* pOpaque) for (x = 0; x < lines; x++) { // Draw the Stack - sprintf(str, "0x%02X", get_memory8(SP+x)); - fl_draw(str, gcpuw->m_pStackBox->x()+10, trace_top+x*gcpuw->m_fontHeight); + sprintf(str, "0x%04X", get_memory16(SP+x*2)); + fl_draw(str, gcpuw->m_pStackBox->x()+6, trace_top+x*gcpuw->m_fontHeight); - // Now draw the Instruction Trace - if (x == lines-1) - { - if (gcpuw->m_inverseHilight) - fl_color(FL_DARK_BLUE); - else - fl_font(FL_COURIER_BOLD, gcpuw->m_fontSize); - } fl_push_clip(gcpuw->m_pTraceBox->x(), gcpuw->m_pTraceBox->y(), gcpuw->m_pTraceBox->w()-3, gcpuw->m_pTraceBox->h()); - fl_draw(gcpuw->m_sInstTrace[draw], 25, trace_top+x*gcpuw->m_fontHeight); + if (gcpuw->m_colorSyntaxHilight) + { + if (gcpuw->m_sInstTrace[draw][0] != '\0') + draw_color_syntax(gcpuw->m_sInstTrace[draw], 25, trace_top+x*gcpuw->m_fontHeight); + } + else + fl_draw(gcpuw->m_sInstTrace[draw], 25, trace_top+x*gcpuw->m_fontHeight); fl_pop_clip(); if (++draw >= 64) draw = 0; @@ -544,8 +713,8 @@ void cb_redraw_trace(Fl_Widget* w, void* pOpaque) for (x = 0; x < lines; x++) { // Draw the Stack - sprintf(str, "0x%02X", get_memory8(SP+x)); - fl_draw(str, gcpuw->m_pStackBox->x()+10, trace_top+x*gcpuw->m_fontHeight); + sprintf(str, "0x%04X", get_memory16(SP+x*2)); + fl_draw(str, gcpuw->m_pStackBox->x()+6, trace_top+x*gcpuw->m_fontHeight); // Now draw the Instruction Trace if (x + firstLine < gcpuw->m_traceAvail) @@ -563,19 +732,27 @@ void cb_redraw_trace(Fl_Widget* w, void* pOpaque) /* If on the execution line, make the font bold */ if (x+firstLine == gcpuw->m_traceAvail-1) { + bold = TRUE; if (gcpuw->m_inverseHilight) { - fl_color(FL_DARK_BLUE); + fl_color(gcpuw->m_traceColors.hilight); fl_rectf(gcpuw->m_pTraceBox->x()+3, trace_top+(x-1)*gcpuw->m_fontHeight+5, gcpuw->m_pTraceBox->w()-6, gcpuw->m_fontHeight); fl_color(FL_WHITE); } else + { fl_font(FL_COURIER_BOLD, gcpuw->m_fontSize); + } } + else + bold = FALSE; // Finally, draw the trace on the window - fl_draw(lineStr, 25, trace_top+x*gcpuw->m_fontHeight); + if (gcpuw->m_colorSyntaxHilight) + draw_color_syntax(lineStr, 25, trace_top+x*gcpuw->m_fontHeight, bold); + else + fl_draw(lineStr, 25, trace_top+x*gcpuw->m_fontHeight); fl_pop_clip(); if (++draw >= gcpuw->m_traceAvail) draw = 0; @@ -585,7 +762,7 @@ void cb_redraw_trace(Fl_Widget* w, void* pOpaque) { // Change back to normal font if (gcpuw->m_inverseHilight) - fl_color(FL_BLACK); + fl_color(gcpuw->m_traceColors.foreground); else fl_font(FL_COURIER, gcpuw->m_fontSize); @@ -677,12 +854,17 @@ void cb_redraw_trace(Fl_Widget* w, void* pOpaque) // Disassemble the next line that hasn't executed yet last_pc += cpu_dis.DisassembleLine(last_pc, lineStr); if (lookahead++ < 4) - fl_draw(lineStr, 25, trace_top+x*gcpuw->m_fontHeight); + { + if (gcpuw->m_colorSyntaxHilight) + draw_color_syntax(lineStr, 25, trace_top+x*gcpuw->m_fontHeight); + else + fl_draw(lineStr, 25, trace_top+x*gcpuw->m_fontHeight); + } if (x == 0) { if (gcpuw->m_inverseHilight) - fl_color(FL_BLACK); + fl_color(gcpuw->m_traceColors.foreground); else fl_font(FL_COURIER, gcpuw->m_fontSize); } @@ -716,7 +898,7 @@ void cb_scrollbar (Fl_Widget* w, void*) else gcpuw->m_pScroll->slider_size(1.0); - cb_redraw_trace(NULL, NULL); + gcpuw->redraw(); } /* @@ -946,19 +1128,25 @@ void debug_cpuregs_cb (int reason) PF?'P':' ',OV?'O':' ',XF?'X':' ', CF?'C':' '); // Append regs after opcode - sprintf(str, "A:%02X %s B:%02X C:%02X D:%02X E:%02X H:%02X L:%02X SP:%02X", - A, flags, B, C, D, E, H, L, SP); + if (gcpuw->m_showAs16Bit) + sprintf(str, "A:%02X %s BC:%04X DE:%04X HL:%04X SP:%02X", + A, flags, BC, DE, HL, SP); + else + sprintf(str, "A:%02X %s B:%02X C:%02X D:%02X E:%02X H:%02X L:%02X SP:%02X", + A, flags, B, C, D, E, H, L, SP); strcat(gcpuw->m_sInstTrace[gcpuw->m_iInstTraceHead++], str); if (gcpuw->m_iInstTraceHead >= 64) gcpuw->m_iInstTraceHead= 0; // Update Trace data on window - cb_redraw_trace(NULL, NULL); + gcpuw->redraw(); // Update monitor frequency based on cpu speed if (fullspeed == 0) gDebugMonitorFreq = 8192; + else if (fullspeed == 3) + gDebugMonitorFreq = 65536; else gDebugMonitorFreq = 32768; } @@ -980,7 +1168,7 @@ void debug_cpuregs_cb (int reason) gcpuw->ScrollToBottom(); // Redraw the trace window - cb_redraw_trace(NULL, NULL); + gcpuw->redraw(); } } else @@ -1223,7 +1411,7 @@ void cb_reg_pc_changed(Fl_Widget* w, void* pOpaque) strcat(pCpuRegs->m_sInstTrace[trace_tail], str); // Update Trace data on window - cb_redraw_trace(NULL, NULL); + gcpuw->redraw(); } /* @@ -1480,7 +1668,7 @@ void cb_reg_sp_changed(Fl_Widget* w, void* pOpaque) } // Update Trace data on window - cb_redraw_trace(NULL, NULL); + gcpuw->redraw(); } /* @@ -2179,20 +2367,51 @@ void cb_CpuRegs (Fl_Widget* w, void*) gDebugActive++; } +/* +============================================================================ +CpuRegisters class constructor. Creates all controls within the window. +============================================================================ +*/ +void VTCpuRegs::SetTraceColors(void) +{ + /* Setup some trace colors */ + if (m_colorSyntaxHilight) + { + m_traceColors.addr = FL_WHITE; + m_traceColors.inst = (Fl_Color) 221; + m_traceColors.number = (Fl_Color) 166; + m_traceColors.flags = FL_DARK_GREEN; + m_traceColors.reg = (Fl_Color) 95; + m_traceColors.reg_val = (Fl_Color) 166; + m_traceColors.foreground = FL_WHITE; + m_traceColors.background = FL_BLACK; + m_traceColors.hilight = FL_DARK_BLUE; + } + else + { + m_traceColors.foreground = FL_BLACK; + m_traceColors.background = FL_GRAY; + } +} + /* ============================================================================ CpuRegisters class constructor. Creates all controls within the window. ============================================================================ */ VTCpuRegs::VTCpuRegs(int x, int y, const char *title) : - //Fl_Double_Window(x, y, title) +#ifdef WIN32 + Fl_Double_Window(x, y, title) +#else Fl_Window(x, y, title) +#endif { Fl_Box* o; int c; /* Load the user preferences for window size, etc. */ LoadPrefs(); + SetTraceColors(); // Allocate the trace buffer m_pTraceData = new cpu_trace_data_t[m_traceCount]; @@ -2218,7 +2437,7 @@ VTCpuRegs::VTCpuRegs(int x, int y, const char *title) : m_pMenu->menu(gCpuRegs_menuitems); // Create static text boxes - Fl_Group* g1 = new Fl_Group(0, 20+MENU_HEIGHT, x, 170+MENU_HEIGHT-20); + Fl_Group* g1 = new Fl_Group(0, 2+MENU_HEIGHT, x, 170+MENU_HEIGHT-2); o = new Fl_Box(FL_NO_BOX, 20, 20+MENU_HEIGHT, 50, 15, "PC"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); @@ -2673,9 +2892,9 @@ VTCpuRegs::VTCpuRegs(int x, int y, const char *title) : m_pDisableTrace->callback(cb_disable_realtime_trace, this); // Create Stack Box - o = new Fl_Box(FL_NO_BOX, 560, 180+MENU_HEIGHT, 50, 15, "Stack"); + o = new Fl_Box(FL_NO_BOX, 560, 180+MENU_HEIGHT, 50, 20, "Stack"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - m_pStackBox = new Fl_Box(FL_DOWN_BOX, 560, 200+MENU_HEIGHT, 60, 124, ""); + m_pStackBox = new Fl_Box(FL_DOWN_BOX, 560, 200+MENU_HEIGHT, 65, 124, ""); // Create Breakpoint edit boxes o = new Fl_Box(FL_NO_BOX, 20, 380, 100, 15, "Breakpoints:"); @@ -2783,8 +3002,13 @@ VTCpuRegs::~VTCpuRegs() void VTCpuRegs::draw(void) { - //Fl_Double_Window::draw(); + make_current(); + +#ifdef WIN32 + Fl_Double_Window::draw(); +#else Fl_Window::draw(); +#endif // Select 12 point Courier font fl_font(FL_COURIER, m_fontSize); @@ -2812,7 +3036,7 @@ void VTCpuRegs::draw(void) make_current(); // Clear rectangle - fl_color(FL_GRAY); + fl_color(m_traceColors.background); fl_rectf(m_pTraceBox->x()+3, m_pTraceBox->y()+3, m_pTraceBox->w()-6, m_pTraceBox->h()-6); fl_rectf(m_pStackBox->x()+3, m_pStackBox->y()+3, @@ -2820,12 +3044,12 @@ void VTCpuRegs::draw(void) // Select 11 point Courier font fl_font(FL_COURIER,18); - fl_color(FL_BLACK); + fl_color(m_traceColors.foreground); fl_draw("Realtime trace disabled", 55, 212+MENU_HEIGHT+3*m_fontHeight); } else - cb_redraw_trace(NULL, this); + redraw_trace(NULL, this); } @@ -2850,7 +3074,9 @@ void VTCpuRegs::LoadPrefs(void) virtualt_prefs.get("CpuRegs_debugInts", temp, 1); gDebugInts = temp; virtualt_prefs.get("CpuRegs_rememberBreakpoints", m_saveBreakpoints, 1); - virtualt_prefs.get("CpuRegs_inversHilight", m_inverseHilight, 1); + virtualt_prefs.get("CpuRegs_inverseHilight", m_inverseHilight, 1); + virtualt_prefs.get("CpuRegs_showAs16Bit", m_showAs16Bit, 0); + virtualt_prefs.get("CpuRegs_colorSyntaxHilight", m_colorSyntaxHilight, 1); if (m_saveBreakpoints) { @@ -2886,7 +3112,8 @@ void VTCpuRegs::SavePrefs(void) virtualt_prefs.set("CpuRegs_disableTrace", gDisableRealtimeTrace); virtualt_prefs.set("CpuRegs_debugInts", gDebugInts); virtualt_prefs.set("CpuRegs_rememberBreakpoints", m_saveBreakpoints); - virtualt_prefs.set("CpuRegs_inversHilight", m_inverseHilight); + virtualt_prefs.set("CpuRegs_inverseHilight", m_inverseHilight); + virtualt_prefs.set("CpuRegs_showAs16Bit", m_showAs16Bit); if (m_saveBreakpoints) { @@ -2976,8 +3203,11 @@ int VTCpuRegs::handle(int eventId) break; } - //return Fl_Double_Window::handle(eventId); +#ifdef WIN32 + return Fl_Double_Window::handle(eventId); +#else return Fl_Window::handle(eventId); +#endif } /* @@ -3133,6 +3363,8 @@ typedef struct trace_setup_params Fl_Input* pTraceDepth; Fl_Input* pFontSize; Fl_Check_Button* pInverseHilight; + Fl_Check_Button* pShowAs16Bit; + Fl_Check_Button* pColorHilight; char sDepth[20]; char sFontSize[20]; } trace_setup_params_t; @@ -3174,6 +3406,13 @@ static void cb_setupdlg_OK(Fl_Widget* w, void* pOpaque) // Get Inverse Highlight selection gcpuw->m_inverseHilight = p->pInverseHilight->value(); + // Get show as 16-bit selection + gcpuw->m_showAs16Bit = p->pShowAs16Bit->value(); + + // Get hilighting option + gcpuw->m_colorSyntaxHilight = p->pColorHilight->value(); + gcpuw->SetTraceColors(); + // Get the updated trace depth newDepth = atoi(p->pTraceDepth->value()); if (newDepth > 0 && newDepth != gcpuw->m_traceCount) @@ -3228,7 +3467,7 @@ static void cb_setupdlg_OK(Fl_Widget* w, void* pOpaque) } // Redraw the window - cb_redraw_trace(NULL, NULL); + gcpuw->redraw(); // Now hide the parent dialog w->parent()->hide(); @@ -3258,7 +3497,7 @@ void cb_setup_trace(Fl_Widget* w, void* pOpaque) // Get socket interface preferences // Create Peripheral Setup window - pWin = new Fl_Window(300, 160, "Trace Configuration"); + pWin = new Fl_Window(300, 200, "Trace Configuration"); /* Create input field for trace depth */ b = new Fl_Box(20, 20, 100, 20, "Trace Depth"); @@ -3282,13 +3521,21 @@ void cb_setup_trace(Fl_Widget* w, void* pOpaque) p.pInverseHilight = new Fl_Check_Button(20, 80, 190, 20, "Inverse Video Hilight"); p.pInverseHilight->value(gcpuw->m_inverseHilight); + /* Create checkbox for 16-bit register style */ + p.pShowAs16Bit = new Fl_Check_Button(20, 100, 200, 20, "Show registers as 16 bit"); + p.pShowAs16Bit->value(gcpuw->m_showAs16Bit); + + /* Create checkbox for 16-bit register style */ + p.pColorHilight = new Fl_Check_Button(20, 120, 200, 20, "Color syntax hilighting"); + p.pColorHilight->value(gcpuw->m_colorSyntaxHilight); + // Cancel button - { Fl_Button* o = new Fl_Button(80, 120, 60, 30, "Cancel"); + { Fl_Button* o = new Fl_Button(80, 160, 60, 30, "Cancel"); o->callback((Fl_Callback*) cb_setupdlg_cancel); } // OK button - { Fl_Return_Button* o = new Fl_Return_Button(160, 120, 60, 30, "OK"); + { Fl_Return_Button* o = new Fl_Return_Button(160, 160, 60, 30, "OK"); o->callback((Fl_Callback*) cb_setupdlg_OK, &p); } diff --git a/src/cpuregs.h b/src/cpuregs.h index a4122a2..928a77d 100644 --- a/src/cpuregs.h +++ b/src/cpuregs.h @@ -60,6 +60,19 @@ typedef struct cpu_trace_data unsigned short operand; } cpu_trace_data_t; +typedef struct cpu_trace_colors +{ + Fl_Color addr; + Fl_Color number; + Fl_Color inst; + Fl_Color reg; + Fl_Color flags; + Fl_Color reg_val; + Fl_Color foreground; + Fl_Color background; + Fl_Color hilight; +} cpu_trace_colors_t; + #define CPUREGS_TRACE_COUNT 1024 #define CPUREGS_TRACE_SCROLL_W 15 @@ -68,8 +81,11 @@ typedef struct cpu_trace_data The CPU Registers Window ================================================ */ -//class VTCpuRegs : public Fl_Double_Window +#ifdef WIN32 +class VTCpuRegs : public Fl_Double_Window +#else class VTCpuRegs : public Fl_Window +#endif { public: VTCpuRegs(int x, int y, const char* title); @@ -77,6 +93,7 @@ class VTCpuRegs : public Fl_Window void RegAllDec(void); void RegAllHex(void); + void SetTraceColors(void); void activate_controls(void); void deactivate_controls(void); @@ -168,6 +185,7 @@ class VTCpuRegs : public Fl_Window int m_iTraceHead; int m_traceCount; int m_traceAvail; + cpu_trace_colors_t m_traceColors; int m_breakAddr[5]; int m_breakEnable[5]; @@ -215,6 +233,8 @@ class VTCpuRegs : public Fl_Window int m_lastH; int m_fontSize, m_fontHeight; int m_inverseHilight; + int m_showAs16Bit; + int m_colorSyntaxHilight; }; #endif From 934a7c793d4a0a7ebc56f9aadfeaaa63d513eedb Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 5 Feb 2013 18:23:34 +0000 Subject: [PATCH 215/327] Modified CPU Register Stack view to display hex values as XXXXH vs 0xXXXX so the are more readable and take less real-estate on the screen. --- src/cpuregs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index 6178c83..6bacaa7 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -682,7 +682,7 @@ void redraw_trace(Fl_Widget* w, void* pOpaque) for (x = 0; x < lines; x++) { // Draw the Stack - sprintf(str, "0x%04X", get_memory16(SP+x*2)); + sprintf(str, "%04XH", get_memory16(SP+x*2)); fl_draw(str, gcpuw->m_pStackBox->x()+6, trace_top+x*gcpuw->m_fontHeight); fl_push_clip(gcpuw->m_pTraceBox->x(), gcpuw->m_pTraceBox->y(), @@ -713,7 +713,7 @@ void redraw_trace(Fl_Widget* w, void* pOpaque) for (x = 0; x < lines; x++) { // Draw the Stack - sprintf(str, "0x%04X", get_memory16(SP+x*2)); + sprintf(str, "%04XH", get_memory16(SP+x*2)); fl_draw(str, gcpuw->m_pStackBox->x()+6, trace_top+x*gcpuw->m_fontHeight); // Now draw the Instruction Trace From 089c5f4635fb81ff0588a7e15a3ef26d5b441a55 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 6 Feb 2013 17:00:22 +0000 Subject: [PATCH 216/327] Fixed bug in VTObject RemoveAt routine that was causing items to not be removed and then causing segmentation faults elsewhere in the code. --- src/vtobj.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/vtobj.cpp b/src/vtobj.cpp index f5b41db..cef4d40 100644 --- a/src/vtobj.cpp +++ b/src/vtobj.cpp @@ -32,6 +32,7 @@ #include #include "VirtualT.h" #include "vtobj.h" +#include const struct VTClass VTObject::classVTObject = { "VTObject", sizeof(VTObject), 0, 0, 0}; @@ -141,7 +142,6 @@ void VTObArray::InsertAt(int nIndex, VTObject *newElement) void VTObArray::RemoveAt(int nIndex, int nCount) { - char* pRemoveLoc; int c; if (m_Count == 0) @@ -151,10 +151,8 @@ void VTObArray::RemoveAt(int nIndex, int nCount) if (nIndex == -1) nIndex = m_Count - 1; - pRemoveLoc = (char *) m_pData + (nIndex * sizeof(VTObject *)); - - for (c = nIndex; c < m_Count; c++) - memcpy(pRemoveLoc + c * sizeof(VTObject *), pRemoveLoc + (c + 1) * sizeof(VTObject *), + for (c = nIndex; c < m_Count-nCount; c++) + memcpy((char *) m_pData + c * sizeof(VTObject *), (char *) m_pData + (c + nCount) * sizeof(VTObject *), sizeof(VTObject *)); // Drecrement count From 0efcc58ea4aed7c2a464c09cda6f4b8a4773b54b Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 6 Feb 2013 17:06:51 +0000 Subject: [PATCH 217/327] Changed IDE project group remove feature so it doesn't ask for confirmation to remove if the group is empty. --- src/ide.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/ide.cpp b/src/ide.cpp index 2c4aacc..cfec55c 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -3008,11 +3008,16 @@ void VT_Ide::DeleteItem(Flu_Tree_Browser::Node* n) { // For groups, ask before deleting the entire group VT_IdeGroup* pGroup = (VT_IdeGroup*) pObj; - ans = fl_choice("Delete gropu %s and all its members?", "No", "Yes", NULL, (const char *) pGroup->m_Name); + int count = pGroup->m_Objects.GetSize(); + + // If group is empty, then don't ask, just delete it + if (count == 0) + ans = 1; + else + ans = fl_choice("Delete group %s and all its members?", "No", "Yes", NULL, (const char *) pGroup->m_Name); if (ans == 1) { // First delete all subitems from the group - int count = pGroup->m_Objects.GetSize(); while (count != 0) { VT_IdeSource* pSrc = (VT_IdeSource*) pGroup->m_Objects[0]; @@ -3063,6 +3068,15 @@ void VT_Ide::DeleteItem(Flu_Tree_Browser::Node* n) } else { + if (strcmp(pObj->GetClass()->m_ClassName, "VT_IdeSource") != 0) + { + MString err; + err.Format("Internal error on line %d of file %s\n", __LINE__, __FILE__); + show_error((const char *) err); + return; + } + + // We are deleting a source entry VT_IdeSource* pSrc = (VT_IdeSource*) pObj; Flu_Tree_Browser::Node* pNext = pSrc->m_Node->next(); From aad7bf672d7393b145e2c7a08d80bbfdbe020473 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 6 Feb 2013 17:08:30 +0000 Subject: [PATCH 218/327] Changed CPU Registers real-time trace so it shows contiguous traces of instructions instead of randomly sampled instructions. --- src/cpuregs.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index 6bacaa7..4da3552 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -1049,7 +1049,8 @@ void debug_cpuregs_cb (int reason) return; } - gDebugCount = 0; + if (gDebugCount >= gDebugMonitorFreq + 64) + gDebugCount = 0; // Update PC edit box sprintf(str, gcpuw->m_sPCfmt, PC); From f54e0806bcc1fa82d2bf4bd93bb04ca5f57be02e Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 6 Feb 2013 17:09:38 +0000 Subject: [PATCH 219/327] Added feature to automatically reopen the IDE if it was opened at the last shutdown of VirtualT. --- src/display.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/display.cpp b/src/display.cpp index 4727da6..a3073fa 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -4812,6 +4812,10 @@ void init_other_windows(void) if (cpuregs_was_open && (gcpuw == NULL)) cb_CpuRegs(NULL, NULL); + // If the IDE window was opened previously, then re-open it + if (ide_was_open && gpIde == NULL) + cb_Ide(NULL, NULL); + // Give the focus back to the main VirtualT window MainWin->show(); } From ae61801962c9cc571852cdbac7d485087d718c0c Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 6 Feb 2013 17:10:33 +0000 Subject: [PATCH 220/327] Added method to MString to extract the filename portion of the string. This will cause a search for '/' or '\' and return only the filename segment. --- src/MString.cpp | 24 ++++++++++++++++++++++++ src/MString.h | 1 + 2 files changed, 25 insertions(+) diff --git a/src/MString.cpp b/src/MString.cpp index 0c4cee0..7b4c7aa 100644 --- a/src/MString.cpp +++ b/src/MString.cpp @@ -20,6 +20,10 @@ ----- $Log$ + Revision 1.2 2013/02/06 17:10:33 kpettit1 + Added method to MString to extract the filename portion of the string. This + will cause a search for '/' or '\' and return only the filename segment. + Revision 1.1 2007/03/31 22:09:17 kpettit1 Fixed issue with Read from HD in normal memory mode. Added many files for IDE & Assember. This is a work in progress and not complete yet. @@ -1534,6 +1538,26 @@ MString MString::SpanExcluding(char* string) const { return tmpStr; } +MString MString::Filename(void) const { //100% + + MString tmp; + int idx = ReverseFind('/'); + + if (idx == -1) + idx = ReverseFind('\\'); + + if (idx == -1) + return *this; + + int length = GetLength(); + tmp = Right(length - idx - 1); + return tmp; + +// MString tmp; +// MakeRightChain(headMNode, nCount, tmp.headMNode); + +} + char* MString::ToChar(int nStart,int nCount) { int length = GetLength(), diff --git a/src/MString.h b/src/MString.h index 056bb1b..d6127a4 100644 --- a/src/MString.h +++ b/src/MString.h @@ -268,6 +268,7 @@ class MString { MString Right(int nCount) const; //Idea from CString MString SpanIncluding(char* string) const; //Idea from CString MString SpanExcluding(char* string) const; //Idea from CString + MString Filename(void) const; char* ToChar(int nStart = 0,int nCount = -1); // PRE: nStart is >0 and < GetLength(). // POST: returns a pointer to a new null-terminated character array From 351a614a596c31f029163acacdd6fd57169c08a4 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 8 Feb 2013 00:05:27 +0000 Subject: [PATCH 221/327] Modified "smart indent" in IDE editor so it isn't so annoying when hitting enter on a line with tabs past the cursor. --- src/My_Text_Editor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/My_Text_Editor.cpp b/src/My_Text_Editor.cpp index 3eccfa2..b31a307 100644 --- a/src/My_Text_Editor.cpp +++ b/src/My_Text_Editor.cpp @@ -439,10 +439,11 @@ int My_Text_Editor::handle_key() { if(Fl::event_key()==FL_Enter && smart_indent) { + int max = insert_position() - buffer()->line_start(insert_position()); char *line = new char[strlen(buffer()->line_text(insert_position()))+1]; strcpy(line, buffer()->line_text(insert_position())); for(unsigned int i = 0; i < strlen(line); i++) { - if(line[i]!=' ' && line[i]!='\t') line[i]='\0'; + if(line[i]!=' ' && line[i]!='\t' || i >= max) line[i]='\0'; } kf_enter(c,this); insert(line); From 9f8297b6b137b109242a13e8eb618810d546887a Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 8 Feb 2013 00:05:57 +0000 Subject: [PATCH 222/327] Removed a few commented out printfs. --- src/m100emu.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/m100emu.c b/src/m100emu.c index 14fd7ae..0f65a7c 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -544,7 +544,6 @@ void get_emulation_path(char* emu, int model) strcat(emu, "PC8300/"); break; } - //printf("emu_path:%s\n",emu); } /* @@ -557,7 +556,6 @@ get_rom_path: This function returns the path of the ROM file for the void get_rom_path(char* file, int model) { strcpy(file, path); /* Copy VirtualT path */ - //printf("Path:%s\n",path); switch (model) { @@ -583,7 +581,6 @@ void get_rom_path(char* file, int model) strcat(file, "PC8300/PC8300rom.bin"); break; } - //printf("Rom_path:%s\n",file); } /* From 0847fece6d55083405f7d67ed40b6083dd256a14 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 8 Feb 2013 00:07:52 +0000 Subject: [PATCH 223/327] Added ability to delete files from the emulated target, automatic loading of .CO files after compiling from the IDE, fixed REX RAM region issue in Memory Editor for PC-8201 mode, added ability to select lines / regions in the trace window of the CPU Regs window. --- src/assemble.cpp | 160 +++++++++++++------ src/assemble.h | 8 +- src/cpuregs.cpp | 145 ++++++++++++++++- src/cpuregs.h | 4 + src/file.cpp | 404 ++++++++++++++++++++++++++++++++++++++--------- src/file.h | 16 +- src/ide.cpp | 40 +++++ src/linker.cpp | 31 ++++ src/linker.h | 4 + src/memedit.cpp | 4 +- src/remote.cpp | 19 +++ 11 files changed, 703 insertions(+), 132 deletions(-) diff --git a/src/assemble.cpp b/src/assemble.cpp index afd55ea..5074538 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -363,6 +363,15 @@ int VTAssembler::PerformSubstitution(CMacro* pMacro, const char *pLoc) if (lastCh == '#') pNew--; + // Test for invalid expression (shouldn't have equation) + if (pExp->m_Equation != NULL) + { + // Try to evaluate the equation + double dval; + Evaluate(pExp->m_Equation, &dval, 0); + break; + } + // Advance the pointer past the parameter ptr += pExp->m_Literal.GetLength(); @@ -388,7 +397,7 @@ int VTAssembler::PerformSubstitution(CMacro* pMacro, const char *pLoc) *pNew++ = *ptr++; *pNew = '\0'; - printf("New line = %s", pNewLine); + //printf("New line = %s", pNewLine); // Delete the old m_pInLine and replace with the new one delete[] m_pInLine; @@ -723,7 +732,7 @@ reportError flag is TRUE. ============================================================================ */ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, - int reportError) + int reportError, MString& errVariable) { double s1, s2; CSymbol* symbol; @@ -766,6 +775,10 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, temp = m_ActiveMod->m_Name + (char *) "%%" + op.m_Variable; local = 1; } + else if (temp[0] == '$' && temp.GetLength() > 1) + { + temp = op.m_Variable.Right(op.m_Variable.GetLength()-1); + } } // Lookup symbol in active module @@ -786,7 +799,10 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, if ((symbol->m_SymType & SYM_HASVALUE) == 0) { if ((symbol->m_SymType & 0xFF) == SYM_EXTERN) + { + errVariable = op.m_Variable; return 0; + } if (GetValue(symbol->m_Name, int_value)) { @@ -798,10 +814,12 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, if (reportError) { errMsg.Format("Error in line %d(%s): Symbol %s has no numeric value", - m_Line, (const char *) m_Filenames[m_FileIndex], + m_Line, (const char *) m_Filenames[m_FileIndex].Filename(), (const char *) op.m_Variable); m_Errors.Add(errMsg); } + else + errVariable = op.m_Variable; return 0; } } @@ -824,7 +842,7 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, if (local) { errMsg.Format("Error in line %d(%s): Local symbol %s undefined", m_Line, - (const char *) m_Filenames[m_FileIndex], (const char *) op.m_Variable); + (const char *) m_Filenames[m_FileIndex].Filename(), (const char *) op.m_Variable); } else { @@ -841,12 +859,14 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, return 0; } errMsg.Format("Error in line %d(%s): Symbol %s undefined", m_Line, - (const char *) m_Filenames[m_FileIndex], (const char *) op.m_Variable); + (const char *) m_Filenames[m_FileIndex].Filename(), (const char *) op.m_Variable); } m_Errors.Add(errMsg); m_UndefSymbols[op.m_Variable] = 0; } } + else + errVariable = op.m_Variable; return 0; } break; @@ -870,7 +890,7 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, if (reportError) { errMsg.Format("Error in line %d(%s): Divide by zero!", - m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Line, (const char *) m_Filenames[m_FileIndex].Filename()); m_Errors.Add(errMsg); } return 0; @@ -1008,6 +1028,7 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, break; } + errVariable = ""; } // Get the result from the equation and return to calling function @@ -1053,6 +1074,12 @@ int VTAssembler::GetValue(MString & string, int & value) { myStr = m_LastLabel + (char *) "%%" + string; } + else if (string[0] == '$' && string.GetLength() > 1) + { + printf("Found %s\n", (const char *) string); + myStr = string.Right(string.GetLength()-1); + printf("New string %s\n", (const char *) myStr); + } // Lookup the symbol in all modules if (!m_ActiveMod->m_Symbols->Lookup(myStr, (VTObject*&) pSymbol)) @@ -1438,7 +1465,7 @@ void VTAssembler::include(const char *filename) { MString errMsg; errMsg.Format("Error in line %d(%s): Unable to open include file %s", - m_Line, (const char *) m_Filenames[m_FileIndex], (const char *) filename); + m_Line, (const char *) m_Filenames[m_FileIndex].Filename(), (const char *) filename); m_Errors.Add(errMsg); return; } else { @@ -1520,7 +1547,6 @@ void VTAssembler::equate(const char *name) pSymbol->m_SymType = SYM_EQUATE; pSymbol->m_pRange = m_ActiveAddr; - printf("EQU: %s\n", (const char *) pSymbol->m_Name); // Try to evaluate the equation. Note that we may not be able to // successfully evaluate it at this point because it may contain @@ -1529,11 +1555,13 @@ void VTAssembler::equate(const char *name) { pSymbol->m_Value = (long) value; pSymbol->m_SymType |= SYM_HASVALUE; + //printf("EQU: %s = %d\n", (const char *) pSymbol->m_Name, (int) value); } else { // Symbol did not evaluate, save as an equation pSymbol->m_SymType |= SYM_ISEQ; + //printf("EQU: %s = equation\n", (const char *) pSymbol->m_Name); } // Save equation @@ -1561,7 +1589,7 @@ void VTAssembler::equate(const char *name) { MString string; string.Format("Error in line %d(%s): Symbol %s already defined as %s", - pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex], + pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex].Filename(), (const char *) pSymbol->m_Name, types[((CSymbol *)dummy)->m_SymType & 0x00FF]); m_Errors.Add(string); @@ -1636,7 +1664,7 @@ void VTAssembler::label(const char *label, int address) if (dummy != NULL) { string.Format("Error in line %d(%s): Label %s already defined as %s", - pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex], + pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex].Filename(), (const char *) pSymbol->m_Name, types[((CSymbol *)dummy)->m_SymType & 0x00FF]); m_Errors.Add(string); @@ -1764,7 +1792,7 @@ void VTAssembler::directive_set(const char *name) { MString string; string.Format("Error in line %d(%s): Symbol %s already defined as %s", - pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex], + pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex].Filename(), (const char *) pSymbol->m_Name, types[symtype]); m_Errors.Add(string); @@ -1949,12 +1977,17 @@ void VTAssembler::directive_printf(const char *string, int hasEquation) } else { - strncpy(str, string, (int) (ptr - string)); + int len = (int) (ptr - string); + strncpy(str, string, len); + str[len] = '\0'; strcat(str, "#UNDEFINED"); if (*ptr != '\0') strcat(str, ptr + 2 + fmtDigits); } + delete gEq; // Delete the unused equaiton + gEq = new CRpnEquation; // Allocate new equation for parser + if (m_pStdoutFunc != NULL) m_pStdoutFunc(m_pStdoutContext, (const char *) str); } @@ -2203,7 +2236,7 @@ void VTAssembler::directive_cdseg(int segType, int page) if (pSeg == NULL) { err.Format("Error in line %d(%s): Error allocating new segment %s", m_Line, - (const char *) m_Filenames[m_FileIndex], name); + (const char *) m_Filenames[m_FileIndex].Filename(), name); m_Errors.Add(err); return; } @@ -2297,7 +2330,7 @@ void VTAssembler::directive_fill() { // Log an error string.Format("Error in line %d(%s): Too many expressions for fill", - m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Line, (const char *) m_Filenames[m_FileIndex].Filename()); m_Errors.Add(string); } else @@ -2318,7 +2351,7 @@ void VTAssembler::directive_fill() { // Log an error string.Format("Error in line %d(%s): Must be able to evaluate fill size on first pass!", - m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Line, (const char *) m_Filenames[m_FileIndex].Filename()); m_Errors.Add(string); } } @@ -2326,7 +2359,7 @@ void VTAssembler::directive_fill() { // Log an error string.Format("Error in line %d(%s): Number of bytes for fill must be an equation", - m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Line, (const char *) m_Filenames[m_FileIndex].Filename()); m_Errors.Add(string); } } @@ -2485,7 +2518,7 @@ void VTAssembler::directive_extern() { MString string; string.Format("Error in line %d(%s): Symbol %s already defined as %s", - pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex], + pSymbol->m_Line, (const char *) m_Filenames[m_FileIndex].Filename(), (const char *) (*gNameList)[c], types[pSymbol->m_SymType & 0x00FF]); m_Errors.Add(string); @@ -2679,7 +2712,7 @@ void VTAssembler::directive_module(const char *name) if (pMod == NULL) { err.Format("Error in line %d(%s): Error creating new module %s", m_Line, - (const char *) m_Filenames[m_FileIndex], name); + (const char *) m_Filenames[m_FileIndex].Filename(), name); m_Errors.Add(err); } @@ -2711,7 +2744,7 @@ void VTAssembler::directive_name(const char *name) MString string; string.Format("Error in line %d(%s): Module name already specified as %s", - m_Line, (const char *) m_Filenames[m_FileIndex], + m_Line, (const char *) m_Filenames[m_FileIndex].Filename(), (const char *) m_ActiveMod->m_Name); m_Errors.Add(string); @@ -2747,7 +2780,7 @@ void VTAssembler::directive_title(const char *name) MString string; string.Format("Error in line %d(%s): Module title already specified as %s", - m_Line, (const char *) m_Filenames[m_FileIndex], + m_Line, (const char *) m_Filenames[m_FileIndex].Filename(), (const char *) m_ActiveMod->m_Title); m_Errors.Add(string); @@ -2844,7 +2877,7 @@ int VTAssembler::preproc_error(const char *string) MString err = string; err.Format("Error in line %d(%s): %s", m_Line, - (const char *) m_Filenames[m_FileIndex], string); + (const char *) m_Filenames[m_FileIndex].Filename(), string); m_Errors.Add(err); return TRUE; @@ -2884,7 +2917,7 @@ void VTAssembler::preproc_ifdef(const char* name, int negate) { m_IfDepth--; err.Format("Error in line %d(%s): Too many nested ifs", m_Line, - (const char *) m_Filenames[m_FileIndex]); + (const char *) m_Filenames[m_FileIndex].Filename()); m_Errors.Add(err); } else if (m_IfStat[m_IfDepth] == IF_STAT_EVAL_ERROR) @@ -3061,7 +3094,7 @@ int VTAssembler::preproc_macro() { // Invalid number of parameters to macro! err.Format("Error in line %d(%s): Macro %s expects %d parameters", m_Line, - (const char *) m_Filenames[m_FileIndex], (const char *) pMacro->m_Name, + (const char *) m_Filenames[m_FileIndex].Filename(), (const char *) pMacro->m_Name, pMacro->m_ParamList->GetSize()); m_Errors.Add(err); return FALSE; @@ -3071,7 +3104,7 @@ int VTAssembler::preproc_macro() { // Invalid number of parameters to macro! err.Format("Error in line %d(%s): Macro %s expects no parameters", m_Line, - (const char *) m_Filenames[m_FileIndex], (const char *) pMacro->m_Name); + (const char *) m_Filenames[m_FileIndex].Filename(), (const char *) pMacro->m_Name); m_Errors.Add(err); return FALSE; } @@ -3141,9 +3174,10 @@ void VTAssembler::directive_if(int inst) { double valuel, valuer; MString err; + MString errVar; // Update line number - m_Line = (PCB).line; + m_Line = (PCB).line - 1; // CInstruction* pInst = new CInstruction; // if (pInst != NULL) @@ -3174,7 +3208,7 @@ void VTAssembler::directive_if(int inst) { m_IfDepth--; err.Format("Error in line %d(%s): Too many nested ifs", m_Line, - (const char *) m_Filenames[m_FileIndex]); + (const char *) m_Filenames[m_FileIndex].Filename()); m_Errors.Add(err); gCond = new CCondition; // m_Instructions->Add(pInst); @@ -3186,7 +3220,7 @@ void VTAssembler::directive_if(int inst) if (m_IfDepth == 0) { err.Format("Error in line %d(%s): ELSE without a matching IF", m_Line, - (const char *) m_Filenames[m_FileIndex]); + (const char *) m_Filenames[m_FileIndex].Filename()); m_Errors.Add(err); return; } @@ -3201,12 +3235,12 @@ void VTAssembler::directive_if(int inst) // Determine if both equations can be evaluated if (m_IfStat[m_IfDepth] == IF_STAT_EVAL_ERROR) { - if (Evaluate(gCond->m_EqLeft, &valuel, 0)) + if (Evaluate(gCond->m_EqLeft, &valuel, 0, errVar)) { // Check if condition contains 2 equations or not if (gCond->m_EqRight != 0) { - if (Evaluate(gCond->m_EqRight, &valuer, 0)) + if (Evaluate(gCond->m_EqRight, &valuer, 0, errVar)) { m_IfStat[m_IfDepth] = IF_STAT_DONT_ASSEMBLE; @@ -3255,6 +3289,13 @@ void VTAssembler::directive_if(int inst) } } } + if (m_IfStat[m_IfDepth] == IF_STAT_EVAL_ERROR || errVar != "") + { + err.Format("Error in line %d(%s): Symbol %s undefined", m_Line, + (const char *) m_Filenames[m_FileIndex].Filename(), (const char *) errVar); + m_Errors.Add(err); + } + gCond = new CCondition; // m_Instructions->Add(pInst); // } @@ -3270,7 +3311,7 @@ void VTAssembler::directive_else() MString err; // Update line number - m_Line = (PCB).line; + m_Line = (PCB).line - 1; // CInstruction* pInst = new CInstruction; // if (pInst != NULL) @@ -3286,7 +3327,7 @@ void VTAssembler::directive_else() if (m_IfDepth == 0) { err.Format("Error in line %d(%s): ELSE without a matching IF", m_Line, - (const char *) m_Filenames[m_FileIndex]); + (const char *) m_Filenames[m_FileIndex].Filename()); m_Errors.Add(err); return; } @@ -3311,7 +3352,7 @@ void VTAssembler::directive_endif() MString err; // Update line number - m_Line = (PCB).line; + m_Line = (PCB).line - 1; // CInstruction* pInst = new CInstruction; // if (pInst != NULL) @@ -3325,7 +3366,7 @@ void VTAssembler::directive_endif() if (m_IfDepth == 0) { err.Format("Error in line %d(%s): ENDIF without a matching IF", m_Line, - (const char *) m_Filenames[m_FileIndex]); + (const char *) m_Filenames[m_FileIndex].Filename()); m_Errors.Add(err); return; } @@ -3364,7 +3405,7 @@ int VTAssembler::Assemble() char rel_mask; int valid, extern_label; POSITION pos; - MString key; + MString key, errSymbol; CSegment* relSeg; /* @@ -3465,7 +3506,7 @@ int VTAssembler::Assemble() size = 2; // Try to get value of the equation - if (Evaluate((CRpnEquation *) pInst->m_Group, &value, 1)) + if (Evaluate((CRpnEquation *) pInst->m_Group, &value, 1, errSymbol)) { // Equation evaluated to a value. Check if it is // relative to a relocatable segment @@ -3498,6 +3539,10 @@ int VTAssembler::Assemble() } else { + err.Format("Error in line %d(%s): Invalid relocation relative to symbol %s", + pInst->m_Line, (const char *) m_Filenames[m_FileIndex].Filename(), + (const char *) errSymbol); + m_Errors.Add(err); valid = 0; } } @@ -3559,7 +3604,7 @@ int VTAssembler::Assemble() { // Error - branch out of range err.Format("Error in line %d(%s): Branch (%d) out of range +127/-128", - pInst->m_Line, (const char *) m_Filenames[m_FileIndex], diff); + pInst->m_Line, (const char *) m_Filenames[m_FileIndex].Filename(), diff); m_Errors.Add(err); valid = 0; } @@ -3570,7 +3615,7 @@ int VTAssembler::Assemble() { // Error - branch out of range err.Format("Error in line %d(%s): Branch (%d) out of range +31/-32", - pInst->m_Line, (const char *) m_Filenames[m_FileIndex], diff); + pInst->m_Line, (const char *) m_Filenames[m_FileIndex].Filename(), diff); m_Errors.Add(err); valid = 0; } @@ -3581,7 +3626,7 @@ int VTAssembler::Assemble() { // Error - branch out of range err.Format("Error in line %d(%s): RCALL (%d) out of range +32768/-32768", - pInst->m_Line, (const char *) m_Filenames[m_FileIndex], diff); + pInst->m_Line, (const char *) m_Filenames[m_FileIndex].Filename(), diff); m_Errors.Add(err); valid = 0; } @@ -3592,7 +3637,7 @@ int VTAssembler::Assemble() { // Error - branch out of range err.Format("Error in line %d(%s): Branch (%d) out of range +4095/-4096", - pInst->m_Line, (const char *) m_Filenames[m_FileIndex], diff); + pInst->m_Line, (const char *) m_Filenames[m_FileIndex].Filename(), diff); m_Errors.Add(err); valid = 0; } @@ -3621,7 +3666,7 @@ int VTAssembler::Assemble() { // Error - Segment size too big err.Format("Error in line %d(%s): Address too big - Max segment size is %d (0x%06X)", - pInst->m_Line, (const char *) m_Filenames[m_FileIndex], MAX_SEG_SIZE, MAX_SEG_SIZE); + pInst->m_Line, (const char *) m_Filenames[m_FileIndex].Filename(), MAX_SEG_SIZE, MAX_SEG_SIZE); m_Errors.Add(err); valid = 0; break; @@ -3823,7 +3868,7 @@ int VTAssembler::Assemble() else { err.Format("Error in line %d(%s): Equation cannot be evaluated", - pInst->m_Line, (const char *) m_Filenames[m_FileIndex]); + pInst->m_Line, (const char *) m_Filenames[m_FileIndex].Filename()); m_Errors.Add(err); valid = 0; } @@ -3928,7 +3973,7 @@ int VTAssembler::Assemble() { // Report error err.Format("Error in line %d(%s): Symbol %s undefined", - pInst->m_Line, (const char *) m_Filenames[m_FileIndex], + pInst->m_Line, (const char *) m_Filenames[m_FileIndex].Filename(), (const char *) (*pNameList)[x]); m_Errors.Add(err); } @@ -4790,7 +4835,8 @@ void VTAssembler::ParseExternalDefines(void) { int startIndex, endIndex; MString def; - int len; + int valIdx, len; + int value = -1; // If zero length then we're done if ((len = m_ExtDefines.GetLength()) == 0) @@ -4811,6 +4857,25 @@ void VTAssembler::ParseExternalDefines(void) // Extract the define from the string def = m_ExtDefines.Mid(startIndex, endIndex - startIndex); + // Test if the define has an embedded '=' + if ((valIdx = def.Find('=')) != -1) + { + MString name = def.Left(valIdx); + + MString val = def.Mid(valIdx+1, endIndex - (valIdx+1)); + if (!GetValue(val, value)) + { + MString errMsg; + + errMsg.Format("Error in invocation: Value for %s cannot be evaluated", + (const char *) name); + m_Errors.Add(errMsg); + } + + // The value was valid. Replace the def name + def = name; + } + // Now assign this define CSymbol* pSymbol = new CSymbol; if (pSymbol != NULL) @@ -4820,6 +4885,9 @@ void VTAssembler::ParseExternalDefines(void) pSymbol->m_SymType = SYM_DEFINE; pSymbol->m_pRange = NULL; pSymbol->m_FileIndex = -1; + pSymbol->m_Value = value; + if (value != -1) + pSymbol->m_SymType |= SYM_HASVALUE; // Assign symbol to active segment const char *pStr = (const char *) pSymbol->m_Name; @@ -4881,10 +4949,10 @@ void VTAssembler::Parse(MString filename) { if (m_LastIfElseIsIf) errMsg.Format("Error in line %d(%s): #ifdef without matching #endif", - m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Line, (const char *) m_Filenames[m_FileIndex].Filename()); else errMsg.Format("Error in line %d(%s): #else without matching #endif", - m_Line, (const char *) m_Filenames[m_FileIndex]); + m_Line, (const char *) m_Filenames[m_FileIndex].Filename()); m_Errors.Add(errMsg); } @@ -5133,7 +5201,7 @@ void VTAssembler::CreateList(MString& filename, MString& asmFilename) { MString err; err.Format("Error in line %d(%s): Internal parse error - Segment line mismatch", - lineNo, (const char *) m_Filenames[m_FileIndex]); + lineNo, (const char *) m_Filenames[m_FileIndex].Filename()); m_Errors.Add(err); break; } diff --git a/src/assemble.h b/src/assemble.h index cd70798..f079f85 100644 --- a/src/assemble.h +++ b/src/assemble.h @@ -505,7 +505,13 @@ class VTAssembler : public VTObject // Operations int Evaluate(class CRpnEquation* eq, double* value, - int reportError); + int reportError, MString& errVariable); + inline int Evaluate(class CRpnEquation* eq, double* value, + int reportError) + { + MString str; + return Evaluate(eq, value, reportError, str); + } int Assemble(); int GetValue(MString & string, int & value); int LookupSymbol(MString& name, CSymbol *& symbol); diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index 4da3552..268330a 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -650,6 +650,7 @@ void redraw_trace(Fl_Widget* w, void* pOpaque) char lineStr[120], str[100]; int trace_top = gcpuw->m_pTraceBox->y() + gcpuw->m_fontHeight - 4; int lookahead = 0, bold; + int selStart, selEnd; // Clear rectangle fl_color(gcpuw->m_traceColors.background); @@ -709,6 +710,13 @@ void redraw_trace(Fl_Widget* w, void* pOpaque) if (draw >= gcpuw->m_traceAvail) draw -= gcpuw->m_traceAvail; last_sp = SP; + selStart = gcpuw->m_selStart; + selEnd = gcpuw->m_selEnd; + if (selStart > selEnd) + { + selStart = gcpuw->m_selEnd; + selEnd = gcpuw->m_selStart; + } for (x = 0; x < lines; x++) { @@ -729,8 +737,18 @@ void redraw_trace(Fl_Widget* w, void* pOpaque) fl_push_clip(gcpuw->m_pTraceBox->x()+2, gcpuw->m_pTraceBox->y()+3, gcpuw->m_pTraceBox->w()-4, gcpuw->m_pTraceBox->h()-6); + // Test if drawing a selected item + if (x+firstLine >= selStart && x+firstLine <= selEnd) + { + // Draw the selection box + fl_color(gcpuw->m_traceColors.select); + fl_rectf(gcpuw->m_pTraceBox->x()+3, trace_top+(x-1)*gcpuw->m_fontHeight+5, + gcpuw->m_pTraceBox->w()-6, gcpuw->m_fontHeight); + fl_color(FL_WHITE); + } + /* If on the execution line, make the font bold */ - if (x+firstLine == gcpuw->m_traceAvail-1) + else if (x+firstLine == gcpuw->m_traceAvail-1) { bold = TRUE; if (gcpuw->m_inverseHilight) @@ -757,8 +775,12 @@ void redraw_trace(Fl_Widget* w, void* pOpaque) if (++draw >= gcpuw->m_traceAvail) draw = 0; + // If we just drew a selected line, then change back to regular font color + if (x+firstLine >= selStart && x+firstLine <= selEnd) + fl_color(gcpuw->m_traceColors.foreground); + // If we just drew the execution line, do special processing - if (x+firstLine == gcpuw->m_traceAvail-1) + else if (x+firstLine == gcpuw->m_traceAvail-1) { // Change back to normal font if (gcpuw->m_inverseHilight) @@ -995,6 +1017,17 @@ void inline trace_instruction(void) gcpuw->m_pTraceData[idx].af = AF; gcpuw->m_pTraceData[idx].opcode = get_memory8(PC); gcpuw->m_pTraceData[idx].operand = get_memory16(PC+1); + + // Update trace selections + if (gcpuw->m_selStart >= 0) + gcpuw->m_selStart--; + if (gcpuw->m_selEnd >= 0) + { + // Decrement selEnd and test if the range needs to update + gcpuw->m_selEnd--; + if (gcpuw->m_selEnd >= 0 && gcpuw->m_selStart == -1) + gcpuw->m_selStart = 0; + } } /* Increment the available trace count until it reaches the max */ @@ -2387,6 +2420,7 @@ void VTCpuRegs::SetTraceColors(void) m_traceColors.foreground = FL_WHITE; m_traceColors.background = FL_BLACK; m_traceColors.hilight = FL_DARK_BLUE; + m_traceColors.select = fl_darker(FL_RED); } else { @@ -2420,6 +2454,9 @@ VTCpuRegs::VTCpuRegs(int x, int y, const char *title) : // Clear debugging data m_traceAvail = 0; m_breakMonitorFreq = 0; + m_selStart = -1; + m_selEnd = -1; + m_haveMouse = FALSE; for (c = 0; c < 5; c++) { m_breakAddr[c] = -1; @@ -3168,7 +3205,9 @@ close our window, which is the default. */ int VTCpuRegs::handle(int eventId) { - unsigned int key; + unsigned int key; + int mx, my; + int tx, ty, th, tw; switch (eventId) { @@ -3200,6 +3239,106 @@ int VTCpuRegs::handle(int eventId) break; + case FL_DRAG: + if (m_haveMouse) + { + // Get the coords + mx = Fl::event_x(); + my = Fl::event_y(); + + // Get coords of the trace box + tx = m_pTraceBox->x(); + ty = m_pTraceBox->y(); + tw = m_pTraceBox->w(); + th = m_pTraceBox->h(); + + // Test if mouse pressed within trace window + if ((mx >= tx) && (mx <= tx+tw) && (my >= ty) && (my <= ty+th)) + { + int firstLine = m_pScroll->value(); + int line = (my-ty-2) / m_fontHeight; + int selection = firstLine + line; + + // Bound selection on bottom + if (selection > m_traceAvail) + selection = m_traceAvail - 1; + m_selEnd = selection; + damage(FL_DAMAGE_EXPOSE, tx, ty, tw, th); + //redraw(); + } + + // Not in window. Test if we are above or below the window and + // do a scroll + else if (mx >= tx && mx <= tx+tw) + { + // We are either above or below the window. Perform scroll + } + } + break; + + case FL_RELEASE: + m_haveMouse = FALSE; + Fl::release(); + + if (m_selStart > m_selEnd) + { + mx = m_selStart; + m_selStart = m_selEnd; + m_selEnd = mx; + } + break; + + case FL_PUSH: + // Get the push coords + mx = Fl::event_x(); + my = Fl::event_y(); + + // Grab the mouse + Fl::grab(); + m_haveMouse = TRUE; + + // Get coords of the trace box + tx = m_pTraceBox->x(); + ty = m_pTraceBox->y(); + tw = m_pTraceBox->w(); + th = m_pTraceBox->h(); + + // Test if mouse pressed within trace window + if ((mx >= tx) && (mx <= tx+tw) && (my >= ty) && (my <= ty+th)) + { + int firstLine = m_pScroll->value(); + int line = (my-ty-2) / m_fontHeight; + int selection = firstLine + line; + + // Check if we clicked within current selection + if (selection >= m_selStart && selection <= m_selEnd) + { + // Click within current selection + } + else if (selection >= m_traceAvail) + { + // Selection below the trace data. De-select + m_selStart = -1; + m_selEnd = -1; + m_haveMouse = FALSE; + Fl::release(); + redraw(); + break; + } + else + { + // Start of new selection + m_selStart = firstLine + line; + m_selEnd = m_selStart; + + // Issue a redraw to show new selection + redraw(); + return 1; + } + + } + break; + default: break; } diff --git a/src/cpuregs.h b/src/cpuregs.h index 928a77d..fa1df56 100644 --- a/src/cpuregs.h +++ b/src/cpuregs.h @@ -71,6 +71,7 @@ typedef struct cpu_trace_colors Fl_Color foreground; Fl_Color background; Fl_Color hilight; + Fl_Color select; } cpu_trace_colors_t; #define CPUREGS_TRACE_COUNT 1024 @@ -235,6 +236,9 @@ class VTCpuRegs : public Fl_Window int m_inverseHilight; int m_showAs16Bit; int m_colorSyntaxHilight; + int m_selStart; + int m_selEnd; + int m_haveMouse; }; #endif diff --git a/src/file.cpp b/src/file.cpp index 3529781..0e08e5b 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -59,6 +59,7 @@ void jump_to_zero(void); int BasicSaveMode = 0; int COSaveMode = 0; +int gLoadError; // Indicates load error (for remote interface) extern Fl_Preferences virtualt_prefs; extern char gsMenuROM[40]; @@ -224,6 +225,12 @@ const char *gKeywordTable[] = { "" }; +/* +======================================================= +This routine relocates BASIC files in the emulation by +updating all the start of line pointers. +======================================================= +*/ int relocate(unsigned char* in, unsigned char* out, unsigned short addr) { int c; @@ -306,6 +313,12 @@ int relocate(unsigned char* in, unsigned char* out, unsigned short addr) return c; } +/* +======================================================= +This is the tokenizer that converts ASCII mode BASIC files +to actual .BA files in the Model 100/102/200 format. +======================================================= +*/ #define STATE_LINENUM 1 #define STATE_WHITE 2 #define STATE_TOKENIZE 3 @@ -528,9 +541,294 @@ int tokenize(unsigned char* in, unsigned char* out, unsigned short addr) return out_len + 2; } +/* +======================================================= +Find the address of directory entry for the specified file. +======================================================= +*/ +unsigned short find_file_in_directory(const char* filename) +{ + unsigned short addr; + int dir_index, x; + + // Determine if file alaready exists in directory + addr = gStdRomDesc->sDirectory; + dir_index = 0; + while (dir_index < gStdRomDesc->sDirCount) + { + // Test if this slot is empty + if ((get_memory8(addr) & 0x80) == 0) + { + addr += 11; + dir_index++; + continue; + } + + // Compare this entry to the file being added + for (x = 0; x < 8; x++) + { + if (get_memory8(addr + 3 + x) != filename[x]) + break; + } + + // Test if we matched the file (i.e. it exists already) + if (x == 8) + { + // File return the address + return addr; + } + + // Advance to next file in directory + addr += 11; + dir_index++; + } + + // File not found, return address of zero + return 0; +} + +/* +======================================================= +Add an offset to all entries in the directory whose +file content is higher in memory than the specified +address. +======================================================= +*/ +void update_file_offsets(unsigned short start_addr, int len) +{ + unsigned short dir_addr; + unsigned short file_addr; + int dir_index; + + // Update existing Directory entry addresses + dir_addr = gStdRomDesc->sDirectory; + dir_index = 0; + while (dir_index < gStdRomDesc->sDirCount) + { + // Check if this entry is active + if (get_memory8(dir_addr) == 0) + { + dir_addr += 11; + dir_index++; + continue; + } + + // Get address of this file + file_addr = get_memory16(dir_addr + 1); + + // Check if file moved + if (file_addr >= start_addr) + set_memory16(dir_addr + 1, file_addr + len); + + dir_addr += 11; + dir_index++; + } +} + +/* +======================================================= +Routine to load files from host into the emulation. +======================================================= +*/ +int delete_file(const char* filename, unsigned short dir_addr) +{ + unsigned short file_addr; // Address of file data + unsigned short len; + unsigned short tmp_addr; + unsigned short reloc_addr; + int file_type, dir_index; + int x, i; + char mt_file[10]; + + // First determine if an address was given. If not, find it + if (dir_addr == 0) + { + // Convert filename to MT format + i = 0; + if (filename[i] == '"') + i++; + for (x = 0; x < 6; x++) + { + if (filename[i] == '.' || filename[i] == '"') + mt_file[x] = ' '; + else + mt_file[x] = toupper(filename[i++]); + } + if (filename[i] == '.') + i++; + for (; x < 8; x++) + { + if (filename[i] == '\0' || filename[i] == '"') + mt_file[x] = ' '; + else + mt_file[x] = toupper(filename[i++]); + } + + // Find the filename in the directory + dir_addr = find_file_in_directory(mt_file); + if (dir_addr == 0) + return 0; + } + + // Get the file address + file_addr = get_memory16(dir_addr + 1); + + // Determine length of file being deleted + len = 0; + tmp_addr = file_addr; + if (get_memory8(dir_addr + 3 + 6) == 'D') + { + // Set the file type to .DO + file_type = TYPE_DO; + + // Find end of .DO file + while (get_memory8(tmp_addr) != 0x1A) + { + len++; + tmp_addr++; + } + // Include terminating 0x1A in length + len++; + } + else if (get_memory8(dir_addr + 3 + 6) == 'C') + { + // Set the file type to .CO + file_type = TYPE_CO; + + // Deleting a binary file + len = get_memory16(file_addr + 2); + } + else + { + // Set the file type to .BA + file_type = TYPE_BA; + + // Must be a BASIC file, but validate that + if (get_memory8(dir_addr + 3 + 6) != 'B') + { + // ERROR! TODO: Report it somehow!! + return 0; + } + + // Yep, it's a BASIC file. Find end of BASIC program + while (get_memory16(tmp_addr) != 0) + tmp_addr = get_memory16(tmp_addr); + + // Be sure to include the terminating 0x0000 in the length + len = tmp_addr - file_addr + 2; + } + + // Delete the file from the directory (mark it invalid) + set_memory8(dir_addr, 0); + + // Move files and variable data after this file (i.e. higher in + // memory space) to delete it from the "file system" + int move_len = get_memory16(gStdRomDesc->sUnusedMem) - (file_addr + len); + for (x = 0; x < move_len; x++) + set_memory8(file_addr + x, get_memory8(file_addr + len + x)); + + // Update existing Directory entry addresses + update_file_offsets(file_addr, -len); + + // Update pointers of all BASIC programs + dir_addr = gStdRomDesc->sDirectory; + dir_index = 0; + while (dir_index < gStdRomDesc->sDirCount) + { + // Check if this entry is active + if (get_memory8(dir_addr) != TYPE_BA) + { + dir_addr += 11; + dir_index++; + continue; + } + + // Get address of this file + reloc_addr = get_memory16(dir_addr + 1); + if (reloc_addr >= file_addr) + { + // Update BASIC pointers for this file + while (get_memory16(reloc_addr) != 0) + { + // Subtract len from current pointer + set_memory16(reloc_addr, get_memory16(reloc_addr) - len); + + // Get pointer to next line + reloc_addr = get_memory16(reloc_addr); + } + } + + // Advance to next entry in directory + dir_addr += 11; + dir_index++; + } + + // If a .BA file was added, renumber the address + // pointers in any "unsaved" BASIC program that + // may exist. + if (file_type == TYPE_BA) + { + // Update BASIC pointers for the Unsaved BASIC program + reloc_addr = get_memory16(gStdRomDesc->sFilePtrBA); + + while (get_memory16(reloc_addr) != 0) + { + set_memory16(reloc_addr, get_memory16(reloc_addr)-len); + reloc_addr = get_memory16(reloc_addr); + } + } + + // Update system pointers + reloc_addr = get_memory16(gStdRomDesc->sBeginArray); + if (reloc_addr >= file_addr) + set_memory16(gStdRomDesc->sBeginArray, reloc_addr - len); + + if ((file_type != TYPE_CO) || (file_type == TYPE_HEX)) + { + reloc_addr = get_memory16(gStdRomDesc->sBeginCO); + if (reloc_addr > file_addr) + set_memory16(gStdRomDesc->sBeginCO, reloc_addr - len); + } + + // If we deleted a BASIC file, then update the beginning of .DO file pointer + if (file_type == TYPE_BA) + { + /* Update beginning of .DO file pointer */ + reloc_addr = get_memory16(gStdRomDesc->sBeginDO); + if (reloc_addr > file_addr) + set_memory16(gStdRomDesc->sBeginDO, reloc_addr - len); + + /* Update BASIC size variable */ + reloc_addr = get_memory16(gStdRomDesc->sBasicSize); + set_memory16(gStdRomDesc->sBasicSize, reloc_addr - (len-2)); + //set_memory16(gStdRomDesc->sBasicSize, reloc_addr - len); + } -int gLoadError; + // Update beginning of variable space pointer + reloc_addr = get_memory16(gStdRomDesc->sBeginVar); + if (reloc_addr >= file_addr) + set_memory16(gStdRomDesc->sBeginVar, reloc_addr - len); + // Update unused memory variable + reloc_addr = get_memory16(gStdRomDesc->sUnusedMem); + if (reloc_addr >= file_addr) + set_memory16(gStdRomDesc->sUnusedMem, reloc_addr - len); + + // Update file view if open + fileview_model_changed(); + + // Reset the system so file will show up + jump_to_zero(); + + // Indicate file deleted successfully + return 1; +} + +/* +======================================================= +Routine to load files from host into the emulation. +======================================================= +*/ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) { int count, i, x; @@ -572,7 +870,7 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) return; } - // Get Filename + // Get Filename filename = fc->value(); if (filename == 0) { @@ -764,6 +1062,7 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) } } + // Dont add zero length files if (len == 0) { if (fc != NULL) @@ -771,53 +1070,47 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) return; } - // Determine if file will fit in memory - addr3 = get_memory16(gStdRomDesc->sBasicStrings); - addr2 = get_memory16(gStdRomDesc->sBeginVar); - if (addr3 - addr2 < len) - { - if (w != NULL) - fl_message("%s", gTooLargeMsg); - else - gLoadError = 1; - if (fc != NULL) - delete fc; - return; - } - // Determine if file alaready exists in directory - addr2 = gStdRomDesc->sDirectory; - dir_index = 0; - while (dir_index < gStdRomDesc->sDirCount) + addr2 = find_file_in_directory(mt_file); + if (addr2 != 0) { - // Test if this slot is empty - if (get_memory8(addr2) == 0) + // File exists. If we are calling from the menu, validate they want to replace + if (w != NULL) { - addr2 += 11; - dir_index++; - continue; - } + int ans = fl_choice("Replace existing file?", "Cancel", "Yes", NULL); - // Compare this entry to the file being added - for (x = 0; x < 8; x++) - { - if (get_memory8(addr2 + 3 + x) != mt_file[x]) - break; + // Test if "Cancel" was selected + if (ans == 0) + { + if (fc != NULL) + delete fc; + return; + } } - if (x == 8) + // Delete the file + if (!delete_file(mt_file, addr2)) { - if (w != NULL) - fl_message("File %s already exists", filename_name); - else - gLoadError = 1; + // Could not delete the file for some reason?? if (fc != NULL) delete fc; + gLoadError = 1; return; } + } - addr2 += 11; - dir_index++; + // Determine if file will fit in memory + addr3 = get_memory16(gStdRomDesc->sBasicStrings); + addr2 = get_memory16(gStdRomDesc->sBeginVar); + if (addr3 - addr2 < len) + { + if (w != NULL) + fl_message("%s", gTooLargeMsg); + else + gLoadError = 1; + if (fc != NULL) + delete fc; + return; } // Determine Directory entry location for new file @@ -845,28 +1138,7 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) set_memory8(addr1+len+x, get_memory8(addr1+x)); // Update existing Directory entry addresses - addr2 = gStdRomDesc->sDirectory; - dir_index = 0; - while (dir_index < gStdRomDesc->sDirCount) - { - // Check if this entry is active - if (get_memory8(addr2) == 0) - { - addr2 += 11; - dir_index++; - continue; - } - - // Get address of this file - addr3 = get_memory16(addr2+1); - - // Check if file moved - if (addr3 >= addr1) - set_memory16(addr2+1, addr3+len); - - addr2 += 11; - dir_index++; - } + update_file_offsets(addr1, len); // Add new Directory entry if (file_type == TYPE_HEX) @@ -877,7 +1149,6 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) for (x = 0; x < 8; x++) set_memory8(addr4+3+x, mt_file[x]); - // If a .BA file was added, renumber the address // pointers in any "unsaved" BASIC program that // may exist. @@ -1189,7 +1460,6 @@ void cb_SaveToHost(Fl_Widget* w, void*) int dir_index; unsigned char file_type; int x, c; -// int col_widths[] = {120, 100,100, 0}; model_t_files_t tFiles[100]; int tCount; @@ -1201,10 +1471,6 @@ void cb_SaveToHost(Fl_Widget* w, void*) fcancel = new Fl_Button(130, 288, 80, 25, "Cancel"); fcancel->callback(cb_cancel); - // Add header & columns for size, address, etc. -// fsb->add("@b@_File\t@b@_Size\t@b@_Address"); -// fsb->column_widths(col_widths); - // Add Model T files to the browser addr1 = gStdRomDesc->sDirectory; dir_index = 0; @@ -1245,14 +1511,6 @@ void cb_SaveToHost(Fl_Widget* w, void*) addr1 += 11; } - // Loop through all tFiles and add to the Browser -/* for (c = 0; c < tCount; c++) - { - // Add filename to Select Browser - sprintf(string, "%s\t%d\t%d", tFiles[c].name, 0, tFiles[c].address); - fsb->add(string); - } -*/ // Show the window gSaveToHost->resizable(fsb); gSaveToHost->show(); diff --git a/src/file.h b/src/file.h index 108a72e..b2679ea 100644 --- a/src/file.h +++ b/src/file.h @@ -38,13 +38,14 @@ #define TYPE_DO 0xC0 #define TYPE_HEX 0x40 -void cb_LoadRam (Fl_Widget* w, void*); -void cb_SaveRam (Fl_Widget* w, void*); -void cb_LoadOptRom (Fl_Widget* w, void*); -void cb_UnloadOptRom (Fl_Widget* w, void*); -void cb_LoadFromHost(Fl_Widget* w, void*); -void cb_SaveToHost(Fl_Widget* w, void*); -int load_optrom_file(const char* filename); +void cb_LoadRam (Fl_Widget* w, void*); +void cb_SaveRam (Fl_Widget* w, void*); +void cb_LoadOptRom (Fl_Widget* w, void*); +void cb_UnloadOptRom (Fl_Widget* w, void*); +void cb_LoadFromHost(Fl_Widget* w, void*); +void cb_SaveToHost(Fl_Widget* w, void*); +int load_optrom_file(const char* filename); +int delete_file(const char* filename, unsigned short addr = 0); #define FILE_ERROR_INVALID_HEX 1 #define FILE_ERROR_FILE_NOT_FOUND 2 @@ -68,3 +69,4 @@ extern char path[255]; #endif #endif + diff --git a/src/ide.cpp b/src/ide.cpp index cfec55c..82fe035 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -67,6 +67,8 @@ #include "multiwin.h" #include "idetabs.h" #include "pref_form.h" +#include "file.h" +#include "memory.h" /* ======================================================= @@ -3711,6 +3713,44 @@ void VT_Ide::BuildProject(void) // Check if we generated a MAP file and the MAP file is opened // Now check if auto-reload of the generated file is enabled + if (m_ActivePrj->m_AutoLoad) + { + switch (m_ActivePrj->m_ProjectType) + { + case VT_PROJ_TYPE_CO: + { + // Test if we should update himem + if (m_ActivePrj->m_UpdateHIMEM) + { + // Set Himem + set_memory16(gStdRomDesc->sHimem, linker.GetStartAddress()); + + // May need to change some other parameters?? + } + + // Load file from host to emulation + MString coPath = m_ActivePrj->m_RootPath + (char *) "/" + + m_ActivePrj->m_OutputName; + cb_LoadFromHost(NULL, (void *) (const char *) coPath); + } + break; + + case VT_PROJ_TYPE_OBJ: + break; + + case VT_PROJ_TYPE_ROM: + break; + + case VT_PROJ_TYPE_LIB: + break; + + case VT_PROJ_TYPE_BA: + break; + + default: + break; + } + } } } } diff --git a/src/linker.cpp b/src/linker.cpp index a618a43..cd06fe2 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -40,6 +40,8 @@ VTLinker::VTLinker() m_DebugInfo = 0; m_TotalCodeSpace = 0; m_TotalDataSpace = 0; + m_EntryAddress = 0; + m_StartAddress = 0; // Clear out the Segment assignement map for (x = 0; x < sizeof(m_SegMap) / sizeof(CObjSegment *); x++) @@ -160,6 +162,8 @@ void VTLinker::ResetContent(void) m_Hex = FALSE; m_DebugInfo = FALSE; m_Map = FALSE; + m_EntryAddress = 0; + m_StartAddress = 0; } /* @@ -2192,6 +2196,10 @@ int VTLinker::GenerateOutputFile() break; } } + + // Save the start address and entry address + m_StartAddress = startAddr; + m_EntryAddress = startAddr; // If build type is .CO, then create the .CO file if (m_ProjectType == VT_PROJ_TYPE_CO) @@ -2220,6 +2228,9 @@ int VTLinker::GenerateOutputFile() } } + // Update the entry address + m_EntryAddress = entryAddr; + // Report that we are generating the output file if (m_pStdoutFunc != NULL) { @@ -2789,6 +2800,26 @@ MString VTLinker::PreprocessDirectory(const char *pDir) return temp; } +/* +============================================================================ +Returns the Start address (lowest address) of the generated code. +============================================================================ +*/ +unsigned short VTLinker::GetStartAddress(void) +{ + return m_StartAddress; +} + +/* +============================================================================ +Returns the Entry address (lowest address) of the generated code. +============================================================================ +*/ +unsigned short VTLinker::GetEntryAddress(void) +{ + return m_EntryAddress; +} + /* ============================================================================ Constructor for the CLinkRgn object. This object is used to keep track of diff --git a/src/linker.h b/src/linker.h index 23cf11f..44dcb14 100644 --- a/src/linker.h +++ b/src/linker.h @@ -218,6 +218,8 @@ class VTLinker : public VTObject int m_Command; // Script command during file parsing int m_TotalCodeSpace; // Total space used by code int m_TotalDataSpace; // Total space used for data + unsigned short m_StartAddress; // Start address of generated code + unsigned short m_EntryAddress; // Entry address of generated code MString m_OutputName; // Name of output file MString m_ObjFileList; // Comma separated list of files MString m_ObjPath; // Comma separated list of directories @@ -277,6 +279,8 @@ class VTLinker : public VTObject public: // Public Access functions int Link(); + unsigned short GetEntryAddress(void); + unsigned short GetStartAddress(void); void SetLinkOptions(const MString& options); void SetObjFiles(const MString& options); void SetLinkerScript(const MString& script); diff --git a/src/memedit.cpp b/src/memedit.cpp index 3d657e6..f5e758d 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -946,7 +946,7 @@ void T100_MemEditor::SetRegionOptions(void) { if (gRex) { - if (gModel == MODEL_T200) + if (gModel == MODEL_T200 || gModel == MODEL_PC8201) { memedit_ctrl.pRegion->add("RAM 1"); memedit_ctrl.pRegion->add("RAM 2"); @@ -1023,7 +1023,7 @@ void T100_MemEditor::SetScrollSize(void) if (gRex) { region = memedit_ctrl.pRegion->value(); - if (gModel == MODEL_T200) + if (gModel == MODEL_T200 || gModel == MODEL_PC8201) { switch (region) { diff --git a/src/remote.cpp b/src/remote.cpp index 78634a4..ff75cd3 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -1177,6 +1177,22 @@ std::string cmd_load(ServerSocket& sock, std::string& args) return gOk; } +/* +======================================================= +Kill command: Kills a file within the target +======================================================= +*/ +std::string cmd_kill(ServerSocket& sock, std::string& args) +{ + if (!delete_file(args.c_str())) + { + std::string ret = "Kill Error" + gLineTerm + gOk; + return ret; + } + + return gOk; +} + /* ======================================================= Load command: Loads a target file from the host @@ -2877,6 +2893,9 @@ std::string process_command(ServerSocket& sock, char *sockdata, int len) else if (cmd_word == "load") ret = cmd_load(sock, args); + else if (cmd_word == "kill") + ret = cmd_kill(sock, args); + else if ((cmd_word == "read_mem") || (cmd_word == "rm")) ret = cmd_read_mem(sock, args); From fe06e13c25c3ec8e41f3a1886947140b4a0c1b88 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Mon, 11 Feb 2013 08:37:17 +0000 Subject: [PATCH 224/327] Changes to the memory editor window to add black background and color coded text, added ability to select regions with the mouse, right click and add markers, added ability to emulate M100/102 with less than 32K RAM for testing purposes. --- src/My_Text_Editor.cpp | 2 +- src/cpu.h | 10 +- src/cpuregs.cpp | 135 ++- src/cpuregs.h | 1 + src/display.cpp | 10 +- src/ide.cpp | 14 + src/linker.cpp | 210 +++++ src/linker.h | 7 + src/m100emu.c | 21 +- src/memedit.cpp | 1869 +++++++++++++++++++++++++++++++++++++--- src/memedit.h | 74 ++ src/memory.c | 14 +- src/memory.h | 1 + src/project.cpp | 47 +- src/project.h | 9 +- src/remote.cpp | 2 +- src/setup.cpp | 78 +- src/setup.h | 1 + 18 files changed, 2305 insertions(+), 200 deletions(-) diff --git a/src/My_Text_Editor.cpp b/src/My_Text_Editor.cpp index b31a307..774d8df 100644 --- a/src/My_Text_Editor.cpp +++ b/src/My_Text_Editor.cpp @@ -443,7 +443,7 @@ int My_Text_Editor::handle_key() { char *line = new char[strlen(buffer()->line_text(insert_position()))+1]; strcpy(line, buffer()->line_text(insert_position())); for(unsigned int i = 0; i < strlen(line); i++) { - if(line[i]!=' ' && line[i]!='\t' || i >= max) line[i]='\0'; + if(line[i]!=' ' && line[i]!='\t' || i >= (unsigned int) max) line[i]='\0'; } kf_enter(c,this); insert(line); diff --git a/src/cpu.h b/src/cpu.h index 16a1b07..09997c6 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -155,15 +155,17 @@ the settings for ReMem support. #undef MEMSET #undef INS_INC +#define RAMBOTTOM gRamBottom + #ifdef NO_REMEM #define SETPCINS16 {int pc=PC; PCL=gBaseMemory[pc++]; PCH=gBaseMemory[pc];} -#define M gBaseMemory[HL] -#define INS gBaseMemory[PC] +#define M ((HL>ROMSIZE&&HLROMSIZE&&PCROMSIZE&&PCROMSIZE&&x=ROMSIZE) gBaseMemory[a] = v; } diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index 268330a..faa0c3d 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -41,6 +41,7 @@ #include #include +#include "VirtualT.h" #include "cpuregs.h" #include "m100emu.h" #include "disassemble.h" @@ -65,7 +66,8 @@ int gDebugCount = 0; int gDebugMonitorFreq = 32768; VTDis cpu_dis; -extern Fl_Preferences virtualt_prefs; +extern Fl_Preferences virtualt_prefs; +extern Fl_Window* gmew; // Global Memory Edit Window extern "C" { @@ -447,9 +449,9 @@ void draw_color_syntax(const char* lineStr, int x, int y, int bold = FALSE) char_width = (int) fl_width(" "); // Copy and draw the address - strncpy(str, lineStr, 7); - str[7] = '\0'; - idx = 7; + strncpy(str, lineStr, 4); + str[4] = '\0'; + idx = 4; fl_color(pColors->addr); if (bold && !gcpuw->m_inverseHilight) fl_font(FL_COURIER_BOLD_ITALIC, gcpuw->m_fontSize); @@ -460,6 +462,14 @@ void draw_color_syntax(const char* lineStr, int x, int y, int bold = FALSE) fl_draw(str, curx, y); curx += (int) fl_width(str); + // Copy and draw the execution location + strncpy(str, &lineStr[4], 3); + str[3] = '\0'; + idx += 3; + fl_color(pColors->number); + fl_draw(str, curx, y); + curx += (int) fl_width(str); + // Copy and draw the instruction c = 0; while (lineStr[idx] != ' ' && lineStr[idx] != '\0') @@ -613,7 +623,15 @@ int build_trace_line(int line, char* lineStr) // Disassemble the opcode last_pc = pTrace->pc + cpu_dis.DisassembleLine(pTrace->pc, (unsigned char) - pTrace->opcode, pTrace->operand, lineStr); + pTrace->opcode & 0xFF, pTrace->operand, lineStr); + + // Replace 'H' in address with execution location ('s'ystem, 'o'pt rom, 'r'am) + if (pTrace->pc > ROMSIZE) + lineStr[4] = 'r'; + else if ((pTrace->opcode >> 8) == 0) + lineStr[4] = 's'; + else + lineStr[4] = 'o'; // Append spaces after opcode len = 20 - strlen(lineStr); @@ -683,8 +701,12 @@ void redraw_trace(Fl_Widget* w, void* pOpaque) for (x = 0; x < lines; x++) { // Draw the Stack - sprintf(str, "%04XH", get_memory16(SP+x*2)); + sprintf(str, "%04X", get_memory16(SP+x*2)); fl_draw(str, gcpuw->m_pStackBox->x()+6, trace_top+x*gcpuw->m_fontHeight); + if (gcpuw->m_colorSyntaxHilight) + fl_color(gcpuw->m_traceColors.number); + fl_draw("H", gcpuw->m_pStackBox->x()+6+4*(int) fl_width(" "), trace_top+x*gcpuw->m_fontHeight); + fl_color(gcpuw->m_traceColors.foreground); fl_push_clip(gcpuw->m_pTraceBox->x(), gcpuw->m_pTraceBox->y(), gcpuw->m_pTraceBox->w()-3, gcpuw->m_pTraceBox->h()); @@ -721,9 +743,14 @@ void redraw_trace(Fl_Widget* w, void* pOpaque) for (x = 0; x < lines; x++) { // Draw the Stack - sprintf(str, "%04XH", get_memory16(SP+x*2)); + sprintf(str, "%04X", get_memory16(SP+x*2)); fl_draw(str, gcpuw->m_pStackBox->x()+6, trace_top+x*gcpuw->m_fontHeight); + if (gcpuw->m_colorSyntaxHilight) + fl_color(gcpuw->m_traceColors.number); + fl_draw("H", gcpuw->m_pStackBox->x()+6+4*(int) fl_width(" "), trace_top+x*gcpuw->m_fontHeight); + fl_color(gcpuw->m_traceColors.foreground); + // Now draw the Instruction Trace if (x + firstLine < gcpuw->m_traceAvail) { @@ -877,6 +904,14 @@ void redraw_trace(Fl_Widget* w, void* pOpaque) last_pc += cpu_dis.DisassembleLine(last_pc, lineStr); if (lookahead++ < 4) { + // Replace 'H' in address with execution location ('s'ystem, 'o'pt rom, 'r'am) + if (last_pc > ROMSIZE) + lineStr[4] = 'r'; + else if (get_rom_bank() == 0) + lineStr[4] = 's'; + else + lineStr[4] = 'o'; + if (gcpuw->m_colorSyntaxHilight) draw_color_syntax(lineStr, 25, trace_top+x*gcpuw->m_fontHeight); else @@ -1015,7 +1050,7 @@ void inline trace_instruction(void) gcpuw->m_pTraceData[idx].de = DE; gcpuw->m_pTraceData[idx].bc = BC; gcpuw->m_pTraceData[idx].af = AF; - gcpuw->m_pTraceData[idx].opcode = get_memory8(PC); + gcpuw->m_pTraceData[idx].opcode = get_memory8(PC) | (get_rom_bank() << 8); gcpuw->m_pTraceData[idx].operand = get_memory16(PC+1); // Update trace selections @@ -1048,6 +1083,13 @@ void debug_cpuregs_cb (int reason) char flags[10]; int x, len; + if (reason == DEBUG_CPU_STEP) + { + if (gmew != NULL) + gmew->redraw(); + return; + } + // Check for breakpoint if (!gStopped) { @@ -1067,6 +1109,10 @@ void debug_cpuregs_cb (int reason) // Scroll to bottom of window if needed if (gcpuw->m_autoScroll) gcpuw->ScrollToBottom(); + + // Ensure the memory window is refreshed if it's open + if (gmew != NULL) + gmew->redraw(); } } } @@ -1147,10 +1193,36 @@ void debug_cpuregs_cb (int reason) gcpuw->m_pXFlag->value(XF); gcpuw->m_pCFlag->value(CF); + // Update RAM bank + if (gModel == MODEL_T200 || gModel == MODEL_PC8201) + { + int bank = get_ram_bank(); + switch (bank) + { + case 0: + gcpuw->m_pRamBank->label("RAM Bank 1"); + break; + case 1: + gcpuw->m_pRamBank->label("RAM Bank 2"); + break; + case 2: + gcpuw->m_pRamBank->label("RAM Bank 3"); + break; + } + } + else + gcpuw->m_pRamBank->label(""); + if (!gDisableRealtimeTrace || (gStopCountdown != 0) || gStopped) { // Disassemble 1 instruction cpu_dis.DisassembleLine(PC, gcpuw->m_sInstTrace[gcpuw->m_iInstTraceHead]); + if (PC > ROMSIZE) + gcpuw->m_sInstTrace[gcpuw->m_iInstTraceHead][4] = 'r'; + else if (get_rom_bank() == 0) + gcpuw->m_sInstTrace[gcpuw->m_iInstTraceHead][4] = 's'; + else + gcpuw->m_sInstTrace[gcpuw->m_iInstTraceHead][4] = 'o'; // Append spaces after opcode len = 20 - strlen(gcpuw->m_sInstTrace[gcpuw->m_iInstTraceHead]); @@ -2934,44 +3006,49 @@ VTCpuRegs::VTCpuRegs(int x, int y, const char *title) : o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); m_pStackBox = new Fl_Box(FL_DOWN_BOX, 560, 200+MENU_HEIGHT, 65, 124, ""); + // Create a text box to show the selected RAM bank + m_pRamBank = new Fl_Box(FL_NO_BOX, 20, 360, 100, 18, ""); + m_pRamBank->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + m_pRamBank->labelfont(FL_HELVETICA_BOLD); + // Create Breakpoint edit boxes - o = new Fl_Box(FL_NO_BOX, 20, 380, 100, 15, "Breakpoints:"); + o = new Fl_Box(FL_NO_BOX, 20, 390, 100, 15, "Breakpoints:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); // Breakpoint 1 - o = new Fl_Box(FL_NO_BOX, 120, 365, 60, 15, "F1"); + o = new Fl_Box(FL_NO_BOX, 120, 375, 60, 15, "F1"); o->align(FL_ALIGN_INSIDE); - m_pBreak1 = new Fl_Input(120, 380, 60, 20, ""); + m_pBreak1 = new Fl_Input(120, 390, 60, 20, ""); m_pBreak1->deactivate(); m_pBreak1->value(""); - m_pBreakDisable1 = new Fl_Check_Button(125, 400, 40, 20, "Off"); + m_pBreakDisable1 = new Fl_Check_Button(125, 410, 40, 20, "Off"); m_pBreakDisable1->deactivate(); // Breakpoint 2 - o = new Fl_Box(FL_NO_BOX, 200, 365, 60, 15, "F2"); + o = new Fl_Box(FL_NO_BOX, 200, 375, 60, 15, "F2"); o->align(FL_ALIGN_INSIDE); - m_pBreak2 = new Fl_Input(200, 380, 60, 20, ""); + m_pBreak2 = new Fl_Input(200, 390, 60, 20, ""); m_pBreak2->deactivate(); m_pBreak2->value(""); - m_pBreakDisable2 = new Fl_Check_Button(205, 400, 40, 20, "Off"); + m_pBreakDisable2 = new Fl_Check_Button(205, 410, 40, 20, "Off"); m_pBreakDisable2->deactivate(); // Breakpoint 3 - o = new Fl_Box(FL_NO_BOX, 280, 365, 60, 15, "F3"); + o = new Fl_Box(FL_NO_BOX, 280, 375, 60, 15, "F3"); o->align(FL_ALIGN_INSIDE); - m_pBreak3 = new Fl_Input(280, 380, 60, 20, ""); + m_pBreak3 = new Fl_Input(280, 390, 60, 20, ""); m_pBreak3->deactivate(); m_pBreak3->value(""); - m_pBreakDisable3 = new Fl_Check_Button(285, 400, 40, 20, "Off"); + m_pBreakDisable3 = new Fl_Check_Button(285, 410, 40, 20, "Off"); m_pBreakDisable3->deactivate(); // Breakpoint 4 - o = new Fl_Box(FL_NO_BOX, 360, 365, 60, 15, "F4"); + o = new Fl_Box(FL_NO_BOX, 360, 375, 60, 15, "F4"); o->align(FL_ALIGN_INSIDE); - m_pBreak4 = new Fl_Input(360, 380, 60, 20, ""); + m_pBreak4 = new Fl_Input(360, 390, 60, 20, ""); m_pBreak4->deactivate(); m_pBreak4->value(""); - m_pBreakDisable4 = new Fl_Check_Button(365, 400, 40, 20, "Off"); + m_pBreakDisable4 = new Fl_Check_Button(365, 410, 40, 20, "Off"); m_pBreakDisable4->deactivate(); if (m_saveBreakpoints) @@ -3263,8 +3340,8 @@ int VTCpuRegs::handle(int eventId) if (selection > m_traceAvail) selection = m_traceAvail - 1; m_selEnd = selection; - damage(FL_DAMAGE_EXPOSE, tx, ty, tw, th); - //redraw(); + //damage(FL_DAMAGE_EXPOSE, tx, ty, tw, th); + redraw(); } // Not in window. Test if we are above or below the window and @@ -3509,15 +3586,6 @@ typedef struct trace_setup_params char sFontSize[20]; } trace_setup_params_t; -/* -============================================================================ -Callback for Trace Setup dialog -============================================================================ -*/ -static void cb_setupdlg_win(Fl_Widget* w, void* pOpaque) -{ -} - /* ============================================================================ Callback for Trace Setup Ok button @@ -3635,8 +3703,7 @@ void cb_setup_trace(Fl_Widget* w, void* pOpaque) Fl_Window* pWin; trace_setup_params_t p; - // Get socket interface preferences - // Create Peripheral Setup window + /* Create a new window for the trace configuration */ pWin = new Fl_Window(300, 200, "Trace Configuration"); /* Create input field for trace depth */ diff --git a/src/cpuregs.h b/src/cpuregs.h index fa1df56..ded71cb 100644 --- a/src/cpuregs.h +++ b/src/cpuregs.h @@ -135,6 +135,7 @@ class VTCpuRegs : public Fl_Window Fl_Check_Button* m_pBreakDisable4; Fl_Check_Button* m_pDebugInts; + Fl_Box* m_pRamBank; Fl_Check_Button* m_pSFlag; Fl_Check_Button* m_pZFlag; diff --git a/src/display.cpp b/src/display.cpp index a3073fa..d06f677 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -684,7 +684,7 @@ void cb_coldBoot (Fl_Widget* w, void*) if (gReMem) { if (w != NULL) - a = fl_choice("Reload OpSys ROM?", "Cancel", "Yes", "No", NULL); + a = fl_choice("Cold Boot. Reload System ROM too?", "Cancel", "Yes", "No", NULL); else a = 2; if (a == 1) @@ -705,11 +705,19 @@ void cb_coldBoot (Fl_Widget* w, void*) show_remem_mode(); + // Reset the main window if (gpDisp != NULL) gpDisp->Reset(); + + // Reset any debug monitor windows if (gpDebugMonitor != 0) gpDebugMonitor->Reset(); fileview_model_changed(); + + // Refresh the memory editor if it is opened + if (gmew != NULL) + gmew->redraw(); + } } diff --git a/src/ide.cpp b/src/ide.cpp index 82fe035..313fe42 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -2881,11 +2881,21 @@ int VT_Ide::ParsePrjFile(const char *name) if (value != 0) m_ActivePrj->m_AutoLoad = atoi(value); } + else if (strcmp(sPtr, "LOADERFILENAME") == 0) + { + if (value != 0) + m_ActivePrj->m_LoaderFilename = value; + } else if (strcmp(sPtr, "UPDATEHIMEM") == 0) { if (value != 0) m_ActivePrj->m_UpdateHIMEM = atoi(value); } + else if (strcmp(sPtr, "CREATELOADER") == 0) + { + if (value != 0) + m_ActivePrj->m_CreateLoader = atoi(value); + } else if (strcmp(sPtr, "TYPE") == 0) { if (value != 0) @@ -3689,6 +3699,10 @@ void VT_Ide::BuildProject(void) linkerFiles = linkerFiles + (char *) "," + m_ActivePrj->m_LinkLibs; linker.SetObjFiles(linkerFiles); linker.SetStdoutFunction(this, ideStdoutProc); + if (m_ActivePrj->m_CreateLoader) + { + linker.SetLoaderFilename(m_ActivePrj->m_LoaderFilename); + } // Now finally perform the link operation linker.Link(); diff --git a/src/linker.cpp b/src/linker.cpp index cd06fe2..786f359 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -24,6 +24,20 @@ extern "C" char path[512]; } +static const char *gLoaderCode[] = { + "89GOTO96\n", + "90V=VARPTR(A$):P=PEEK(V+1)+PEEK(V+2)*M\n", + "91C=PEEK(P):IFC=34THENRETURN\n", + "92V=0:FORX=0TO4:T=PEEK(P):V=V*85+T-35:K=K+T:P=P+1:NEXT\n", + "93H=INT(V/M/M):L=V-H*M*M:POKES,H/M:POKES+1,H-INT(H/M)*M:POKES+2,L/M:POKES+3,L-INT(L/M)*M:S=S+4\n", + "94L=D:D=D+I:IFD>184THEND=184\n", + "95FORX=L+1TOD:PSET(X,27):NEXT:PSET(D,27):PSET(D-1,26):PSET(D-2,25):PSET(D-1,28):PSET(D-2,29):PRESET(L-1,26):PRESET(L-2,25):PRESET(L-1,28):PRESET(L-2,29):GOTO 91\n", + "96CLS:PRINT@56,\"Loading\":PRINT@129,CHR$(245);:PRINT@151,CHR$(245);:D=59:I=%.3f:S=%d:M=256:FORJ%=1TO%d:READA$:GOSUB90:NEXT\n", + "97IFK<>%dTHEN99ELSE PRINT@200,\"Success! Issue command: clear 256,%d\"\n", + "98SAVEM\"%s\",%d,%d,%d:END\n", + "99PRINT@200,\"Chksum error! Need %d, got\";S:END\n" +}; + static const char *gsEdl = "Error during linking: "; /* @@ -2287,6 +2301,15 @@ int VTLinker::GenerateOutputFile() // Close the output file fclose(fd); + + // Now check if we need to generate a loader for the .CO + if (m_LoaderFilename != "") + { + MString msg; + msg.Format("Generating BASIC loader file %s\n", (const char *) m_LoaderFilename); + m_pStdoutFunc(m_pStdoutContext, (const char *) msg); + GenerateLoaderFile(startAddr, endAddr, entryAddr); + } } // Test if project type is Assembly ROM and create HEX output if it is @@ -2376,6 +2399,182 @@ int VTLinker::GenerateOutputFile() return TRUE; } +/* +============================================================================ +Generates a quintuple, base 85 number from the given ascii85 value and +writes it to the file while updating control variables. +============================================================================ +*/ +int VTLinker::CreateQuintuple(FILE* fd, unsigned long& ascii85, int& lineNo, + int& dataCount, int& lastDataFilePos, + int& lineCount, int& checksum) +{ + int q; + char quintuple[5]; + + // Loop for 5 digits of base 85 number + for (q = 4; q >= 0; q--) + { + // Create base 85 number + quintuple[q] = (char) (ascii85 % 85) + '#'; + checksum += quintuple[q]; + ascii85 /= 85; + } + + // Write results to file + if (fwrite(quintuple, 1, 5, fd) != 5) + { + // Error writing to file + return FALSE; + } + + // Add 5 more bytes to line length and check if time for a new line + lineCount += 5; + if (lineCount >= MAX_LOADER_LINE_LEN) + { + // Terminate the current data statement + fprintf(fd, "\"\n"); + lineCount = 0; + + // Start a new data line. First grab the file position + lastDataFilePos = ftell(fd); + fprintf(fd, "%d DATA\"", ++lineNo); + dataCount++; + } + + return TRUE; +} + +/* +============================================================================ +Generates a BASIC loader text file for the generated .CO file. +============================================================================ +*/ +int VTLinker::GenerateLoaderFile(int startAddr, int endAddr, int entryAddr) +{ + MString err; + FILE* fd; + int checksum, lineNo, dataCount, quadtuple, quintupleCount; + int lastDataFilePos, lineCount; + int c, x; + unsigned long ascii85; + MString filePath; + + // Generate file path + filePath = m_RootPath + (char *) "/" + m_LoaderFilename; + + // Open the output file for output + if ((fd = fopen((const char *) filePath, "wb")) == NULL) + { + err.Format("%sUnable to open output file %s", gsEdl, (const char *) m_LoaderFilename); + m_Errors.Add(err); + return FALSE; + } + + // Write the output data to the file + lineNo = checksum = 0; + lineCount = quadtuple = quintupleCount = 0; + ascii85 = 0; + + // Issue the 1st Data statement + lastDataFilePos = ftell(fd); + fprintf(fd, "%d DATA\"", ++lineNo); + dataCount = 1; + + // Loop for all data + for (c = startAddr; c <= endAddr; ) + { + // Write the next block of bytes + CObjFileSection *pSect = m_SegMap[c]; + for (x = 0; x < pSect->m_Size; x++) + { + // Munge next byte into ascii85 calculation + ascii85 = ascii85 * 256 + (unsigned char) pSect->m_pProgBytes[x]; + printf("%02X\t", (unsigned char) pSect->m_pProgBytes[x]); + + // Check if time to output a quintuple from our quadtuple + if (++quadtuple == 4) + { + printf("%d\n", ascii85); + CreateQuintuple(fd, ascii85, lineNo, dataCount, lastDataFilePos, + lineCount, checksum); + + // Reset the quadtuple counter + quadtuple = 0; + ascii85 = 0; + quintupleCount++; + } + } + + // Update to the next byte to write + c += pSect->m_Size; + + while ((m_SegMap[c] == NULL || m_SegMap[endAddr]->m_Name == ".bss") && + c <= endAddr) + { + // We added a zero. Check if time to output a quintuple from our quadtuple + if (++quadtuple == 4) + { + CreateQuintuple(fd, ascii85, lineNo, dataCount, lastDataFilePos, + lineCount, checksum); + + // Reset the quadtuple counter + quadtuple = 0; + ascii85 = 0; + quintupleCount++; + } + c++; + } + } + + // Check if anything left over that didn't get written yet + if (ascii85 != 0) + { + CreateQuintuple(fd, ascii85, lineNo, dataCount, lastDataFilePos, + lineCount, checksum); + quintupleCount++; + } + + // Check if last data statement was empty + if (lineCount == 0) + { + // Rewind file to last data statement to remove the statement + fseek(fd, lastDataFilePos, SEEK_SET); + dataCount--; + } + else + { + // Terminate the last DATA statement + fprintf(fd, "\"\n"); + } + + // Now write the rest of the program to the file + for (x = 0; x < 7; x++) + fwrite(gLoaderCode[x], 1, strlen(gLoaderCode[x]), fd); + + // Calculate increment value for progress indicator + double inc = 128.0; + if (quintupleCount != 0) + inc = (double) 128 / (double) quintupleCount; + + // Print next line with increment, start address, and data count + fprintf(fd, gLoaderCode[7], (float) inc, ((int) startAddr)-65536, dataCount); + + // Print line with checksum validation and CLEAR statement + fprintf(fd, gLoaderCode[8], checksum, startAddr); + + // Print the line with the SAVEM filename command + fprintf(fd, gLoaderCode[9], (const char *) m_LoaderFilename, startAddr, endAddr, entryAddr); + + // Finally print the line reporting the checksum error + fprintf(fd, gLoaderCode[10], checksum); + + // Now close the file and we're all done + fclose(fd); + + return 1; +} + /* ============================================================================ Generates a map file if one was requested and no errors exist during the @@ -2707,6 +2906,17 @@ void VTLinker::SetRootPath(const MString& path) CalcObjDirs(); } +/* +============================================================================ +Sets the name of the BASIC loader file to be generated +============================================================================ +*/ +void VTLinker::SetLoaderFilename(const MString& loaderFilename) +{ + // Save the string in case we need it later + m_LoaderFilename = loaderFilename; +} + /* ============================================================================ Sets the root project path diff --git a/src/linker.h b/src/linker.h index 44dcb14..80ba0e9 100644 --- a/src/linker.h +++ b/src/linker.h @@ -45,6 +45,8 @@ #define CSEG 1 #define DSEG 2 +#define MAX_LOADER_LINE_LEN 220 + #define VT_ISDIGIT(x) (((x) >= '0') && ((x) <= '9')) #ifdef WIN32 @@ -225,6 +227,7 @@ class VTLinker : public VTObject MString m_ObjPath; // Comma separated list of directories MString m_LinkOptions; // Linker options MString m_RootPath; // Root path of project. + MString m_LoaderFilename; // Filename of loader to be generated, if any MString m_LinkerScript; // Name of the linker script MString m_EntryLabel; // Label or address of program entry MStringArray m_ObjDirs; // Array of '/' terminated object dirs @@ -275,6 +278,9 @@ class VTLinker : public VTObject int GenerateOutputFile(void); int GenerateMapFile(void); int BackAnnotateListingFiles(void); + int CreateQuintuple(FILE* fd, unsigned long& ascii85, int& lineNo, + int& dataCount, int& lastDataFilePos, int& lineCount, int& checksum); + int GenerateLoaderFile(int startAddr, int endAddr, int entryAddr); public: // Public Access functions @@ -286,6 +292,7 @@ class VTLinker : public VTObject void SetLinkerScript(const MString& script); void SetObjDirs(const MString& dirs); void SetRootPath(const MString& rootPath); + void SetLoaderFilename(const MString& loaderFilename); void SetProjectType(int type); void SetStdoutFunction(void *pContext, stdOutFunc_t pFunc); const MStringArray& GetErrors() { return m_Errors; }; diff --git a/src/m100emu.c b/src/m100emu.c index 0f65a7c..9c7d3b4 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -68,6 +68,7 @@ int gModel = MODEL_M100; volatile uchar cpu[14]; extern uchar *gMemory[64]; +extern int gRamBottom; extern uchar gMsplanROM[32768]; extern uchar gOptROM[32768]; extern int gInMsPlanROM; @@ -146,6 +147,7 @@ char gIntActive = 0; unsigned short gIntSP = 0; char gStopped = 0; char gSingleStep = 0; +char gLastWasSingleStep = 0; debug_monitor_callback gpDebugMonitors[3] = { NULL, NULL, NULL }; void periph_mon_update_lpt_log(void); @@ -746,7 +748,7 @@ void init_cpu(void) /* Clear the system memory RAM area */ for (i = 0; i < RAMSIZE; i++) gBaseMemory[RAMSTART + i] = 0; - + /* Read RAM from file in emulation directory */ load_ram(); @@ -1088,6 +1090,15 @@ void do_debug_stuff(void) if (gStopped) { + if (gLastWasSingleStep) + { + for (i = 0; i < 3; i++) + { + if (gpDebugMonitors[i] != NULL) + gpDebugMonitors[i](DEBUG_CPU_STEP); + } + } + gOsDelay = 1; /* Loop until not stopped or single step */ while (gStopped && !gSingleStep && !gExitApp) @@ -1095,8 +1106,8 @@ void do_debug_stuff(void) process_windows_event(); } gOsDelay = 0; -// if (!gIntActive) - gSingleStep = 0; + gLastWasSingleStep = gSingleStep; + gSingleStep = 0; } lock_remote(); } @@ -1149,7 +1160,9 @@ void emulate(void) if (gSingleStep) { if (!gIntActive) + { gSingleStep = 0; + } } /* Do maintenance tasks (Windows events, interrupts, etc.) */ @@ -1204,7 +1217,9 @@ void emulate(void) if (gSingleStep) { if (!gIntActive) + { gSingleStep = 0; + } } /* Do maintenance tasks (Windows events, interrupts, etc.) */ diff --git a/src/memedit.cpp b/src/memedit.cpp index f5e758d..5c50c66 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include "FLU/Flu_File_Chooser.h" @@ -62,10 +63,17 @@ extern "C" { #include "intelhex.h" + +extern int gRamBottom; } void cb_Ide(Fl_Widget* w, void*); +/* +================================================================ +Define the structure to hold all memory editor controls +================================================================ +*/ typedef struct memedit_ctrl_struct { Fl_Menu_Bar* pMenu; @@ -104,6 +112,14 @@ void cb_load(Fl_Widget* w, void*); void cb_save_bin(Fl_Widget* w, void*); void cb_save_hex(Fl_Widget* w, void*); void cb_save_memory(Fl_Widget* w, void*); +void cb_setup_memedit(Fl_Widget* w, void*); +void cb_add_marker(Fl_Widget* w, void*); +void cb_goto_next_marker(Fl_Widget* w, void*); +void cb_goto_prev_marker(Fl_Widget* w, void*); +void cb_delete_marker(Fl_Widget* w, void*); +void cb_delete_all_markers(Fl_Widget* w, void*); +void cb_undo_delete_all_markers(Fl_Widget* w, void*); + int str_to_i(const char *pStr); extern "C" @@ -113,12 +129,27 @@ extern uchar gRampac; void memory_monitor_cb(void); } +/* +================================================================ +Some bad bad bad global variables. +================================================================ +*/ +memedit_ctrl_t memedit_ctrl; +memedit_dialog_t gDialog; +Fl_Window *gmew; // Global Memory Edit Window +unsigned char gDispMemory[8192]; +extern Fl_Preferences virtualt_prefs; -// Menu items for the disassembler +/* +================================================================ +Menu items for the Memory Editor +================================================================ +*/ Fl_Menu_Item gMemEdit_menuitems[] = { { "&File", 0, 0, 0, FL_SUBMENU }, { "Load from File...", 0, cb_load, 0 }, - { "Save to File...", 0, cb_save_memory, 0 }, + { "Save to File...", 0, cb_save_memory, 0, FL_MENU_DIVIDER }, + { "Setup...", 0, cb_setup_memedit, 0}, { 0 }, { "&Tools", 0, 0, 0, FL_SUBMENU }, @@ -126,19 +157,29 @@ Fl_Menu_Item gMemEdit_menuitems[] = { { "Assembler / IDE", 0, cb_Ide }, { "Disassembler", 0, disassembler_cb }, { "Peripheral Devices", 0, cb_PeripheralDevices }, -// { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, cb_FileView }, { 0 }, { 0 } }; +Fl_Menu_Item gAddMarkerMenu[] = { + { " Create marker ", 0, cb_add_marker, 0 }, + { " Find next marker ", FL_F+2, cb_goto_next_marker, 0 }, + { " Find prev marker ", FL_SHIFT+FL_F+2, cb_goto_prev_marker, 0, FL_MENU_DIVIDER }, + { " Delete all markers ", 0, cb_delete_all_markers, 0, 0 }, + { 0, 0, cb_undo_delete_all_markers, 0, 0 }, + { 0 } +}; -memedit_ctrl_t memedit_ctrl; -memedit_dialog_t gDialog; -Fl_Window *gmew; // Global Memory Edit Window -unsigned char gDispMemory[8192]; -extern Fl_Preferences virtualt_prefs; +Fl_Menu_Item gDeleteMarkerMenu[] = { + { " Delete Marker ", 0, cb_delete_marker, 0}, + { " Find next marker ", FL_F+2, cb_goto_next_marker, 0 }, + { " Find prev marker ", FL_SHIFT+FL_F+2, cb_goto_prev_marker, 0, FL_MENU_DIVIDER }, + { " Delete All Markers ", 0, cb_delete_all_markers, 0, 0 }, + { 0, 0, cb_undo_delete_all_markers, 0, 0 }, + { 0 } +}; /* ============================================================================ @@ -174,6 +215,7 @@ void cb_region(Fl_Widget* w, void*) { // Set new region here memedit_ctrl.pMemEdit->SetScrollSize(); + memedit_ctrl.pMemEdit->ClearSelection(); memedit_ctrl.pMemEdit->redraw(); memedit_ctrl.pMemEdit->UpdateAddressText(); } @@ -189,13 +231,25 @@ void cb_memory_range(Fl_Widget* w, void*) int address; pStr = memedit_ctrl.pMemRange->value(); - address = str_to_i(pStr); + if (strlen(pStr) != 0) + { + address = str_to_i(pStr); - // Set new region here - memedit_ctrl.pMemEdit->MoveTo(address); + // Set new region here + memedit_ctrl.pMemEdit->MoveTo(address); + } + else + { + memedit_ctrl.pMemEdit->ClearSelection(); + memedit_ctrl.pMemEdit->redraw(); + } } - +/* +============================================================================ +Callback routine the OK button on the load memory dialog +============================================================================ +*/ void load_okButton_cb(Fl_Widget* w, void*) { @@ -233,12 +287,22 @@ void load_okButton_cb(Fl_Widget* w, void*) gDialog.pWin->hide(); } +/* +============================================================================ +Callback routine the Cancel button on the load memory dialog +============================================================================ +*/ void load_cancelButton_cb(Fl_Widget* w, void*) { gDialog.iOk = 0; gDialog.pWin->hide(); } +/* +============================================================================ +Callback routine the length field updates +============================================================================ +*/ void update_length_field(const char *filename) { int len; @@ -757,7 +821,6 @@ void cb_save_memory(Fl_Widget* w, void*) gmew->take_focus(); } - /* ============================================================================ Callback routine for processing memory changes during debug @@ -795,7 +858,6 @@ void cb_MemEditScroll (Fl_Widget* w, void*) memedit_ctrl.pMemEdit->UpdateAddressText(); } - /* ============================================================================ Routine to create the MemoryEditor Window @@ -810,7 +872,8 @@ void cb_MemoryEditor (Fl_Widget* w, void*) // Create Peripheral Setup window #ifdef WIN32 - gmew = new Fl_Window(585, 400, "Memory Editor"); + gmew = new T100_MemEditWin(0, 0, 585, 400, "Memory Editor"); +// gmew = new Fl_Double_Window(585, 400, "Memory Editor"); // Create a menu for the new window. memedit_ctrl.pMenu = new Fl_Menu_Bar(0, 0, 585, MENU_HEIGHT-2); #else @@ -832,10 +895,10 @@ void cb_MemoryEditor (Fl_Widget* w, void*) memedit_ctrl.pRegion = new Fl_Choice(70, 8+MENU_HEIGHT, 100, 20, ""); memedit_ctrl.pRegion->callback(cb_region); - // Create Filename edit field - memedit_ctrl.pMemRange = new Fl_Input(235, 8+MENU_HEIGHT, 210, 20, ""); + // Create edit field for memory search / display field + memedit_ctrl.pMemRange = new Fl_Input(235, 8+MENU_HEIGHT, 80, 20, ""); memedit_ctrl.pMemRange->callback(cb_memory_range); -// memedit_ctrl.pMemRange->deactivate(); + memedit_ctrl.pMemRange->when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED); #ifdef WIN32 memedit_ctrl.pMemEdit = new T100_MemEditor(10, 40+MENU_HEIGHT, 545, 350-MENU_HEIGHT); @@ -863,6 +926,7 @@ void cb_MemoryEditor (Fl_Widget* w, void*) // Get the user preferences for the memory editor MemoryEditor_LoadPrefs(); + memedit_ctrl.pMemEdit->UpdateColors(); // Resize if user preferences have been set if (memedit_ctrl.pMemEdit->m_x != -1 && memedit_ctrl.pMemEdit->m_y != -1 && @@ -907,11 +971,29 @@ void cb_MemoryEditorUpdate(void) memedit_ctrl.pMemEdit->redraw(); } +void cb_popup(Fl_Widget* w, void*) +{ +} + +T100_MemEditWin::T100_MemEditWin(int x, int y, int w, int h, const char *title) : + Fl_Double_Window(w,h, title) +{ +} + +/* +================================================================ +Class constructor for the Memory Editor widget +================================================================ +*/ T100_MemEditor::T100_MemEditor(int x, int y, int w, int h) : Fl_Widget(x, y, w, h) { + int c; + m_MyFocus = 0; m_FirstLine = 0; + m_HaveMouse = FALSE; + m_DragX = m_DragY = 0; m_Cols = 0; m_Lines = 0; m_FirstAddress = 0; @@ -925,18 +1007,50 @@ T100_MemEditor::T100_MemEditor(int x, int y, int w, int h) : m_SelActive = 0; m_SelEndRow = 0; m_SelEndCol = 0; + m_SelStartAddr = -1; + m_SelEndAddr = -1; + m_BlackBackground = 0; + m_ColorSyntaxHilight = 0; + m_Font = FL_COURIER; + m_PopupActive = FALSE; #ifdef WIN32 m_FontSize = 12; #else m_FontSize = 14; #endif SetRegionOptions(); + + // NULL out the region marker pointers + for (c = 0; c < REGION_MAX; c++) + { + m_pRegionMarkers[c] = NULL; + m_pUndoDeleteMarkers[c] = NULL; + } + + // Create a popup-menu for right-clicks + m_pPopupMenu = new Fl_Menu_Button(0,0,100,400,"Popup"); + m_pPopupMenu->type(Fl_Menu_Button::POPUP123); + m_pPopupMenu->menu(gAddMarkerMenu); + m_pPopupMenu->selection_color(fl_rgb_color(80,80,255)); + m_pPopupMenu->color(fl_rgb_color(240,239,228)); + m_pPopupMenu->hide(); + m_pPopupMenu->callback(cb_popup); } T100_MemEditor::~T100_MemEditor() { + // Delete the popup menu + delete m_pPopupMenu; + + // Delete all markers and undo markers + ResetMarkers(); } +/* +================================================================ +Updates the Region list items based on the current model. +================================================================ +*/ void T100_MemEditor::SetRegionOptions(void) { memedit_ctrl.pRegion->clear(); @@ -1010,6 +1124,11 @@ void T100_MemEditor::SetRegionOptions(void) memedit_ctrl.pRegion->add("RamPac"); } +/* +================================================================ +Sets the scroll bar sizes based on current region selection +================================================================ +*/ void T100_MemEditor::SetScrollSize(void) { double size; @@ -1033,9 +1152,14 @@ void T100_MemEditor::SetScrollSize(void) m_Max = RAMSIZE / 16; break; case 3: - case 4: m_Max = ROMSIZE / 16; break; + case 4: + if (gModel == MODEL_T200) + m_Max = ROMSIZE / 16; + else + m_Max = 1024 * 1024 / 16; + break; case 5: m_Max = 1024 * 1024 / 16; break; @@ -1092,7 +1216,7 @@ void T100_MemEditor::SetScrollSize(void) m_Max = 1024 * 256 / 16; // Select 12 point Courier font - fl_font(FL_COURIER, m_FontSize); + fl_font(m_Font, m_FontSize); // Get character width & height m_Height = fl_height(); @@ -1108,6 +1232,11 @@ void T100_MemEditor::SetScrollSize(void) memedit_ctrl.pScroll->linesize(1); } +/* +================================================================ +Returns the ENUM of the currently selected region list +================================================================ +*/ int T100_MemEditor::GetRegionEnum(void) { char reg_text[16]; @@ -1172,30 +1301,44 @@ int T100_MemEditor::GetRegionEnum(void) } +/* +================================================================ +Called when memory changes to redraw any regions which have +changed. +================================================================ +*/ void T100_MemEditor::UpdateDispMem(void) { int count, c; unsigned char mem[8192]; - int xpos, ypos; + int xpos, ypos, selWidth, addrBase; char string[6]; int modified = 0; + int linesVisible; // Calculate # bytes to read count = m_Lines * 16; // Read memory get_memory8_ext(m_Region, m_FirstAddress, count, mem); + addrBase = 0; + if ((m_Region == REGION_RAM) || (m_Region == REGION_RAM2) || + (m_Region == REGION_RAM3) || m_Region == REGION_RAM1) + addrBase = ROMSIZE; // Set the display window()->make_current(); // Select 12 point Courier font - fl_font(FL_COURIER, m_FontSize); + fl_font(m_Font, m_FontSize); + linesVisible = (int) (memedit_ctrl.pScroll->h() / m_Height); // Check for changes for (c = 0; c < count; c++) if (mem[c] != gDispMemory[c]) { + int addr = m_FirstAddress + c; + int actualAddr = addr + addrBase; gDispMemory[c] = mem[c]; // Display new text @@ -1205,11 +1348,37 @@ void T100_MemEditor::UpdateDispMem(void) xpos = (int) (x() + ((c&0x0F)*3+9+((c&0x0F)>7)) * m_Width); ypos = (int) (y() + ((c>>4)+1) * m_Height); - // Draw Address text for line - fl_color(FL_WHITE); - fl_rectf(xpos, ypos - (int) m_Height, (int) m_Width*2, (int) m_Height); - fl_color(FL_BLACK); - fl_draw(string, xpos, ypos-2); + // Erase the old text + fl_color(m_colors.background); + fl_rectf(xpos, ypos+2 - (int) m_Height, (int) m_Width*2, (int) m_Height); + + // Draw as disabled RAM region? + if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) + { + fl_color(fl_darker(FL_GRAY)); + fl_draw(string, xpos, ypos-2); + } + + // Draw as marker / selection? + else if (IsHilighted(addr)) + { + selWidth = 3; + if ((c & 0x0F) == 7 || (c & 0x0F) == 15) + selWidth = 2; + if (!IsHilighted(addr+c+1)) + selWidth = 2; + fl_color(m_colors.hilight_background); + fl_rectf(xpos, ypos+2-(int) m_Height, (int) m_Width * selWidth, (int) m_Height); + fl_color(m_colors.hilight); + fl_draw(string, xpos, ypos-2); + fl_color(m_colors.number); + } + else + { + // Draw HEX value for changed item + fl_color(m_colors.number); + fl_draw(string, xpos, ypos-2); + } // Draw the new ASCII value if ((mem[c] >= ' ') && (mem[c] <= '~')) @@ -1217,10 +1386,43 @@ void T100_MemEditor::UpdateDispMem(void) else strcpy(string, "."); xpos = (int) (x() + (59 + (c&0x0F)) * m_Width); - fl_color(FL_WHITE); - fl_rectf(xpos, ypos - (int) m_Height, (int) m_Width, (int) m_Height); - fl_color(FL_BLACK); - fl_draw(string, xpos, ypos-2); + + // Erase the old text + fl_color(m_colors.background); + fl_rectf(xpos, ypos+2 - (int) m_Height, (int) m_Width, (int) m_Height+3); + + // Erase spill-over text below this field + if (!(actualAddr+16 >= ROMSIZE && actualAddr+16 < gRamBottom)) + { + if (IsHilighted(addr+16)) + fl_color(m_colors.hilight_background); + } + + // Draw spill over region only if not on bottom line + if ((c+16) / 16 < linesVisible) + fl_rectf(xpos, ypos+2, (int) m_Width, 3); + + // Draw as disabled RAM region? + if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) + { + fl_color(fl_darker(FL_GRAY)); + fl_draw(string, xpos, ypos-2); + } + + // Draw as marker / selection? + else if (IsHilighted(addr)) + { + fl_color(m_colors.hilight_background); + fl_rectf(xpos, ypos+2-(int) m_Height, (int) m_Width, (int) m_Height); + fl_color(m_colors.hilight); + fl_draw(string, xpos, ypos-2); + fl_color(m_colors.number); + } + else + { + fl_color(m_colors.ascii); + fl_draw(string, xpos, ypos-2); + } // Set modified flag modified = 1; @@ -1230,26 +1432,25 @@ void T100_MemEditor::UpdateDispMem(void) DrawCursor(); } - -// Redraw the whole LCD +/* +================================================================ +Redraw the whole memory editor widget +================================================================ +*/ void T100_MemEditor::draw() { int lines, cols; int line; unsigned char line_bytes[16]; // Bytes for line being displayed - int addr; + int addr, actualAddr; char string[10]; int xpos, ypos; - int c, max; + int c, max, selWidth; int region; // Region where memory is being drawn from // Select 12 point Courier font - fl_font(FL_COURIER, m_FontSize); + fl_font(m_Font, m_FontSize); - // Get character width & height - m_Width = fl_width("W", 1); - m_Height = fl_height(); - // Calculate max cols and lines lines = (int) (h() / m_Height); cols = (int) (w() / m_Width); @@ -1262,10 +1463,9 @@ void T100_MemEditor::draw() } // Draw white background - fl_color(FL_WHITE); + fl_color(m_colors.background); fl_rectf(x(),y(),w(),h()); - fl_color(FL_BLACK); line = 0; max = (int) m_Max * 16; // Calc maximum address @@ -1282,11 +1482,16 @@ void T100_MemEditor::draw() { // Calculate address to be displayed addr = m_FirstAddress + line * 16; + actualAddr = addr; if (addr >= max) break; + fl_color(m_colors.addr); if ((region == REGION_RAM) || (region == REGION_RAM2) || (region == REGION_RAM3) || region == REGION_RAM1) + { sprintf(string, "%06X ", addr + RAMSTART); + actualAddr += RAMSTART; + } else sprintf(string, "%06X ", addr); @@ -1294,12 +1499,18 @@ void T100_MemEditor::draw() xpos = (int) (x() + m_Width); ypos = (int) (y() + (line+1) * m_Height); + if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) + fl_color(fl_darker(FL_GRAY)); + // Draw Address text for line fl_draw(string, xpos, ypos-2); // Read memory for this line get_memory8_ext(region, addr, 16, line_bytes); + // Set the color for numbers + fl_color(m_colors.number); + // Loop through 16 bytes and display in HEX for (c = 0; c < 16; c++) { @@ -1312,7 +1523,30 @@ void T100_MemEditor::draw() sprintf(string, "%02X", line_bytes[c]); if (xpos + m_Width < w()) - fl_draw(string, xpos, ypos-2); + { + if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) + { + fl_color(fl_darker(FL_GRAY)); + fl_draw(string, xpos, ypos-2); + } + + // Draw selection box + else if (IsHilighted(addr+c)) + { + selWidth = 3; + if (c == 7 || c == 15) + selWidth = 2; + if (!IsHilighted(addr+c+1)) + selWidth = 2; + fl_color(m_colors.hilight_background); + fl_rectf(xpos, ypos+2-(int) m_Height, (int) m_Width * selWidth, (int) m_Height); + fl_color(m_colors.hilight); + fl_draw(string, xpos, ypos-2); + fl_color(m_colors.number); + } + else + fl_draw(string, xpos, ypos-2); + } } // Calculate xpos for first byte @@ -1320,6 +1554,9 @@ void T100_MemEditor::draw() string[1] = 0; + // Set the color for ascii + fl_color(m_colors.ascii); + // Loop through 16 bytes and display as text for (c = 0; c < 16; c++) { @@ -1331,7 +1568,25 @@ void T100_MemEditor::draw() // Print the character if (xpos < w()) - fl_draw(string, xpos, ypos-2); + { + if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) + { + fl_color(fl_darker(FL_GRAY)); + fl_draw(string, xpos, ypos-2); + } + + // Draw selection box + else if (IsHilighted(addr + c)) + { + fl_color(m_colors.hilight_background); + fl_rectf(xpos, ypos+2-(int) m_Height, (int) m_Width, (int) m_Height); + fl_color(m_colors.hilight); + fl_draw(string, xpos, ypos-2); + fl_color(m_colors.ascii); + } + else + fl_draw(string, xpos, ypos-2); + } // Calculate xpos of next byte xpos += (int) m_Width; @@ -1345,7 +1600,11 @@ void T100_MemEditor::draw() DrawCursor(); } -// Handle mouse events, key events, focus events, etc. +/* +================================================================ +Handle mouse events, key events, focus events, etc. +================================================================ +*/ int T100_MemEditor::handle(int event) { int c, xp, yp, shift; @@ -1357,13 +1616,57 @@ int T100_MemEditor::handle(int event) unsigned int key; int first, address; unsigned char data; - int xpos, ypos; + int xpos, ypos, actualAddr; char string[6]; + // Do some common processing before the switch + if (event == FL_PUSH || event == FL_MOVE || event == FL_DRAG) + { + // Get X,Y position of button press + xp = Fl::event_x(); + yp = Fl::event_y(); + + // Check if Shift was depressed during the Mouse Button event + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + shift = 1; + else + shift = 0; + + // Determine line & col of mouse click + col_click = (int) ((xp - x()) / m_Width); + line_click = (int) ((yp - y()) / m_Height); + + // Constrain Column base on geometry + if (col_click < 9) + col_click = 9; + + // Constrain click to 1st column in of value in first field + if (col_click < 24+9) + col_click = (int) ((col_click-9) / 3) * 3 + 9; + else if (col_click < 58) + col_click = (int) ((col_click-25-9) / 3) * 3 + 25+9; + else if (col_click == 58) + col_click = 59; + else if (col_click > 74) + col_click = 74; + } + switch (event) { case FL_FOCUS: m_MyFocus = 1; + if (m_PopupActive) + { + m_PopupActive = FALSE; + break; + } + else if (m_SelStartAddr != -1) + { + m_SelStartAddr = m_SelEndAddr = -1; + redraw(); + } + else if (m_CursorRow != -1 && m_CursorCol != -1) + DrawCursor(); break; case FL_UNFOCUS: @@ -1376,48 +1679,86 @@ int T100_MemEditor::handle(int event) EraseCursor(); break; + case FL_RELEASE: + // Release the pointer + if (m_HaveMouse) + { + Fl::release(); + m_HaveMouse = FALSE; + } + + // Ensure the SelStart less than SelEnd + if (m_SelStartAddr > m_SelEndAddr) + { + // Swap them + address = m_SelStartAddr; + m_SelStartAddr = m_SelEndAddr; + m_SelEndAddr = address; + } + break; + + case FL_MOVE: + case FL_DRAG: + // Cancel any double click operation possibilities + if (xp != m_DblclkX || yp != m_DblclkY) + { + m_DblclkX = -1; + m_DblclkY = -1; + } + + // Done processing if we don't have the mouse + if (!m_HaveMouse) + break; + + // Test if the mouse actually moved from the last position + if ((abs(xp - m_DragX) > 4) || (abs(yp - m_DragY) > 4)) + { + // Test for an active selection. If no active selection, then + // create one. + if (m_SelStartAddr == -1) + m_SelStartAddr = m_CursorAddr; + + // Calculate the address of the new x,y location and set it as + // the selection end address. + if (col_click >= 59) + col = (int) (col_click-59); + else if (col_click > 8+8*3) + col = (int) ((col_click-10) / 3); + else + col = (int) ((col_click-9) / 3); + + // Calculate the address associated with the click + address = memedit_ctrl.pScroll->value() * 16; + address += line_click * 16; + address += col; + + // Set address as the selection end + m_SelEndAddr = address; + + // Perform a redraw to show new selection + redraw(); + } + break; + case FL_PUSH: // Get id of mouse button pressed c = Fl::event_button(); // We must take the focus so keystrokes work properly - take_focus(); + if (Fl::focus() != this) + take_focus(); // Make our window the current window for drawing window()->make_current(); // Check if it was the Left Mouse button - if ((c == FL_LEFT_MOUSE) || (c == FL_RIGHT_MOUSE)) + if (c == FL_LEFT_MOUSE) { - // Get X,Y position of button press - xp = Fl::event_x(); - yp = Fl::event_y(); - - // Check if Shift was depressed during the Mouse Button event - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) - shift = 1; - else - shift = 0; - - - if (c == FL_RIGHT_MOUSE) - shift = 1; - - // Determine line & col of mouse click - col_click = (int) ((xp - x()) / m_Width); - line_click = (int) ((yp - y()) / m_Height); - - // Constrain Column base on geometry - if (col_click < 9) - col_click = 9; - - // Constrain click to 1st column in of value in first field - if (col_click < 24+9) - col_click = (int) ((col_click-9) / 3) * 3 + 9; - else if (col_click < 59) - col_click = (int) ((col_click-25-9) / 3) * 3 + 25+9; - else if (col_click > 74) - col_click = 74; + // Take control of the cursor + Fl::grab(); + m_HaveMouse = TRUE; + m_DragX = xp; + m_DragY = yp; // Get LineStart index lineIndex = (m_FirstLine + line_click) >> 1; @@ -1430,12 +1771,15 @@ int T100_MemEditor::handle(int event) window()->make_current(); // Select 12 point Courier font - fl_font(FL_COURIER, m_FontSize); + fl_font(m_Font, m_FontSize); // Erase current cursor EraseCursor(); // Save new cursor position + int oldCursorCol = m_CursorCol; + int oldCursorRow = m_CursorRow; + m_CursorCol = col_click; m_CursorRow = line_click; if (col_click >= 59) @@ -1443,8 +1787,151 @@ int T100_MemEditor::handle(int event) else m_CursorField = 1; + if (m_CursorField == 1) + { + // Calculate the byte number within the field + if (m_CursorCol > 8+8*3) + { + // Calculate index of byte + col = (int) ((m_CursorCol-10) / 3); + } + else + { + // Calculate index of byte + col = (int) ((m_CursorCol-9) / 3); + } + } + else + { + col = (int) (m_CursorCol-59); + } + + // Calculate the address associated with the click + address = memedit_ctrl.pScroll->value() * 16; + address += m_CursorRow * 16; + address += col; + + // Save this address for future use + m_CursorAddr = address; + + // Process as a double click if the coords are the same + if ((xp == m_DblclkX && yp == m_DblclkY) || shift) + { + // Set the selection to the click upon address + m_SelEndAddr = address; + + // Test for shift click and selStart not set yet + if (shift && m_SelStartAddr == -1) + { + // Set the start address based on old cursor position + if (oldCursorCol >= 59) + col = oldCursorCol - 59; + else if (oldCursorCol > 8+8*3) + col = (int) ((oldCursorCol-10) / 3); + else + col = (int) ((oldCursorCol-9) / 3); + + // Calculate address of last cursor loction + address = memedit_ctrl.pScroll->value() * 16; + address += oldCursorRow * 16; + address += col; + + // Use this address as the SelStart address + m_SelStartAddr = address; + } + else + m_SelStartAddr = address; + + // Ensure start is less than end + if (m_SelStartAddr > m_SelEndAddr) + { + address = m_SelStartAddr; + m_SelStartAddr = m_SelEndAddr; + m_SelEndAddr = address; + } + + // Cancel double click for next click operation + m_DblclkX = -1; + m_DblclkY = -1; + + redraw(); + break; + } + else if (!(address >= m_SelStartAddr && address <= m_SelEndAddr)) + { + // We clicked in a region that wasn't selected. Clear + // the old selection. + m_SelStartAddr = m_SelEndAddr = -1; + redraw(); + } + // Draw new cursor DrawCursor(); + + // Save x and y as the last click location + m_DblclkX = xp; + m_DblclkY = yp; + } + else if (c == FL_RIGHT_MOUSE) + { + // Calculate the address of the new x,y location and set it as + // the selection end address. + if (col_click >= 59) + col = (int) (col_click-59); + else if (col_click > 8+8*3) + col = (int) ((col_click-10) / 3); + else + col = (int) ((col_click-9) / 3); + + // Calculate the address associated with the click + address = memedit_ctrl.pScroll->value() * 16; + address += line_click * 16; + address += col; + + // Test if we right-clicked outside the selection area + if (!(address >= m_SelStartAddr && address <= m_SelEndAddr)) + { + // Create a new selection area at the current address and redraw + m_SelStartAddr = address; + m_SelEndAddr = address; + } + m_CursorCol = col_click; + m_CursorRow = line_click; + m_CursorAddress = address; + redraw(); + + // If we selected inside an existing marker, then show the delete marker menu + if (HasMarker(address)) + // Show the "Remove Marker" menu + m_pPopupMenu->menu(gDeleteMarkerMenu); + else + // Show the "Create Marker" menu + m_pPopupMenu->menu(gAddMarkerMenu); + + // Set or clear the Undo based on availablilty + int count = sizeof(gDeleteMarkerMenu) / sizeof(Fl_Menu_Item); + int region = m_Region; + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + region = REGION_RAM; + if (m_pUndoDeleteMarkers[region] == NULL) + { + gDeleteMarkerMenu[count-2].text = NULL; + gAddMarkerMenu[count-2].text = NULL; + } + else + { + gDeleteMarkerMenu[count-2].text = " Undo Delete all "; + gAddMarkerMenu[count-2].text = " Undo Delete all "; + } + + // Now Popup the menu + m_PopupActive = TRUE; + Fl_Widget *mb = m_pPopupMenu; + const Fl_Menu_Item* m; + Fl::watch_widget_pointer(mb); + m = m_pPopupMenu->menu()->popup(Fl::event_x(), Fl::event_y()+10, NULL, 0, m_pPopupMenu); + m_pPopupMenu->picked(m); + Fl::release_widget_pointer(mb); } break; @@ -1466,10 +1953,28 @@ int T100_MemEditor::handle(int event) switch (key) { - case FL_Left: - // First test if selection active. If active, dactivate the selection - // and place cursor at m_CursorRow,m_CursorCol - if (m_SelActive) + case FL_F+2: + // Calculate the address associated with the click + if (m_CursorCol >= 59) + col = m_CursorCol - 59; + else if (m_CursorCol > 8+8*3) + col = (int) ((m_CursorCol-10) / 3); + else + col = (int) ((m_CursorCol-9) / 3); + + m_CursorAddress = memedit_ctrl.pScroll->value() * 16; + m_CursorAddress += m_CursorRow * 16; + m_CursorAddress += col; + if (shift) + FindPrevMarker(); + else + FindNextMarker(); + break; + + case FL_Left: + // First test if selection active. If active, dactivate the selection + // and place cursor at m_CursorRow,m_CursorCol + if (m_SelActive) { // Call routine to "unhilight" the selection @@ -1581,10 +2086,9 @@ int T100_MemEditor::handle(int event) else { // Select 12 point Courier font - fl_font(FL_COURIER, m_FontSize); + fl_font(m_Font, m_FontSize); // Get character width & height - m_Height = fl_height(); height = memedit_ctrl.pScroll->h(); size = (int) (height / m_Height); if (memedit_ctrl.pScroll->value() != m_Max - size) @@ -1615,10 +2119,9 @@ int T100_MemEditor::handle(int event) else { // Select 12 point Courier font - fl_font(FL_COURIER, m_FontSize); + fl_font(m_Font, m_FontSize); // Get character width & height - m_Height = fl_height(); height = memedit_ctrl.pScroll->h(); size = (int) (height / m_Height); if (memedit_ctrl.pScroll->value() != m_Max - size) @@ -1833,6 +2336,15 @@ int T100_MemEditor::handle(int event) // Erase current cursor EraseCursor(); + // If shift-tab selected, then change focus to Address edit field + if (shift) + { + memedit_ctrl.pMemRange->take_focus(); + memedit_ctrl.pMemRange->position(0); + memedit_ctrl.pMemRange->mark(9999); + return 1; + } + // Change to other field if (m_CursorField == 1) { @@ -1868,6 +2380,17 @@ int T100_MemEditor::handle(int event) break; default: + if (Fl::get_key(FL_Control_L) || Fl::get_key(FL_Control_R)) + { + if (key == 'g' || key=='G') + { + memedit_ctrl.pMemRange->take_focus(); + memedit_ctrl.pMemRange->position(0); + memedit_ctrl.pMemRange->mark(9999); + } + return 1; + } + // Handle changes to the memory if (m_CursorField == 1) { @@ -1907,6 +2430,11 @@ int T100_MemEditor::handle(int event) address += m_CursorRow * 16; address += col; + actualAddr = address; + if ((m_Region == REGION_RAM) || (m_Region == REGION_RAM2) || + (m_Region == REGION_RAM3) || m_Region == REGION_RAM1) + actualAddr += ROMSIZE; + // Determine if this is the first keystroke at this address if (first) { @@ -1931,7 +2459,7 @@ int T100_MemEditor::handle(int event) // Display new text // Select 12 point Courier font - fl_font(FL_COURIER, m_FontSize); + fl_font(m_Font, m_FontSize); sprintf(string, "%02X", data); @@ -1942,23 +2470,48 @@ int T100_MemEditor::handle(int event) // Set the display window()->make_current(); - // Draw Address text for line - fl_color(FL_WHITE); - fl_rectf(xpos, ypos - (int) m_Height, (int) m_Width*2, (int) m_Height); - fl_color(FL_BLACK); + // Erase old HEX value + if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) + fl_color(m_colors.background); + else if (IsHilighted(address)) + fl_color(m_colors.hilight_background); + else + fl_color(m_colors.background); + fl_rectf(xpos, ypos+2 - (int) m_Height, (int) m_Width*2, (int) m_Height-2); + + // Draw Draw the HEX value + if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) + fl_color(fl_darker(FL_GRAY)); + else if (IsHilighted(address)) + fl_color(m_colors.hilight); + else + fl_color(m_colors.number); fl_draw(string, xpos, ypos-2); - // Draw the new ASCII value + // Prepare the new ASCII value to be drawn if ((data >= ' ') && (data <= '~')) sprintf(string, "%c", data); else strcpy(string, "."); xpos = (int) (x() + (59 + col) * m_Width); - fl_color(FL_WHITE); - fl_rectf(xpos, ypos - (int) m_Height, (int) m_Width, (int) m_Height); - fl_color(FL_BLACK); - fl_draw(string, xpos, ypos-2); + // Erase the old ASCII value + if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) + fl_color(m_colors.background); + else if (IsHilighted(address)) + fl_color(m_colors.hilight_background); + else + fl_color(m_colors.background); + fl_rectf(xpos, ypos+2 - (int) m_Height, (int) m_Width, (int) m_Height); + + // Draw the new ASCII value + if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) + fl_color(fl_darker(FL_GRAY)); + else if (IsHilighted(address)) + fl_color(m_colors.hilight); + else + fl_color(m_colors.ascii); + fl_draw(string, xpos, ypos-2); // Update cursor position m_CursorCol++; @@ -1985,10 +2538,9 @@ int T100_MemEditor::handle(int event) // Cursor at bottom of screen. Need to scroll // Select 12 point Courier font - fl_font(FL_COURIER, m_FontSize); + fl_font(m_Font, m_FontSize); // Get character width & height - m_Height = fl_height(); height = memedit_ctrl.pScroll->h(); size = (int) (height / m_Height); @@ -2026,6 +2578,10 @@ int T100_MemEditor::handle(int event) // Get address of first item on screen address = memedit_ctrl.pScroll->value() * 16; address += m_CursorRow * 16; + actualAddr = address; + if ((m_Region == REGION_RAM) || (m_Region == REGION_RAM2) || + (m_Region == REGION_RAM3) || m_Region == REGION_RAM1) + actualAddr += ROMSIZE; address += col; // Write new value to memory @@ -2034,34 +2590,58 @@ int T100_MemEditor::handle(int event) // Display new text // Select 12 point Courier font - fl_font(FL_COURIER, m_FontSize); - - sprintf(string, "%02X", data); + fl_font(m_Font, m_FontSize); // Calculate xpos and ypos of the text xpos = (int) (x() + (col*3+9+(col>7)) * m_Width); ypos = (int) (y() + (m_CursorRow+1) * m_Height); - // Set the display + // Set the display active for drawing window()->make_current(); - // Draw Address text for line - fl_color(FL_WHITE); - fl_rectf(xpos, ypos - (int) m_Height, (int) m_Width*2, (int) m_Height); - fl_color(FL_BLACK); + // Erase old HEX value + if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) + fl_color(m_colors.background); + else if (IsHilighted(address)) + fl_color(m_colors.hilight_background); + else + fl_color(m_colors.background); + fl_rectf(xpos, ypos+2 - (int) m_Height, (int) m_Width*2, (int) m_Height-2); + + // Draw Draw the HEX value + sprintf(string, "%02X", data); + if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) + fl_color(fl_darker(FL_GRAY)); + else if (IsHilighted(address)) + fl_color(m_colors.hilight); + else + fl_color(m_colors.number); fl_draw(string, xpos, ypos-2); - // Draw the new ASCII value + // Prepare the new ASCII value to be drawn if ((data >= ' ') && (data <= '~')) sprintf(string, "%c", data); else strcpy(string, "."); xpos = (int) (x() + (59 + col) * m_Width); - fl_color(FL_WHITE); - fl_rectf(xpos, ypos - (int) m_Height, (int) m_Width, (int) m_Height); - fl_color(FL_BLACK); - fl_draw(string, xpos, ypos-2); + // Erase the old ASCII value + if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) + fl_color(m_colors.background); + else if (IsHilighted(address)) + fl_color(m_colors.hilight_background); + else + fl_color(m_colors.background); + fl_rectf(xpos, ypos+2 - (int) m_Height, (int) m_Width, (int) m_Height); + + // Draw the new ASCII value + if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) + fl_color(fl_darker(FL_GRAY)); + else if (IsHilighted(address)) + fl_color(m_colors.hilight); + else + fl_color(m_colors.ascii); + fl_draw(string, xpos, ypos-2); // Update cursor position m_CursorCol++; @@ -2081,10 +2661,9 @@ int T100_MemEditor::handle(int event) // Cursor at bottom of screen. Need to scroll // Select 12 point Courier font - fl_font(FL_COURIER, m_FontSize); + fl_font(m_Font, m_FontSize); // Get character width & height - m_Height = fl_height(); height = memedit_ctrl.pScroll->h(); size = (int) (height / m_Height); @@ -2143,10 +2722,9 @@ void T100_MemEditor::ScrollUp(int lines) // Select 12 point Courier font - fl_font(FL_COURIER, m_FontSize); + fl_font(m_Font, m_FontSize); // Get height of screen in lines - m_Height = fl_height(); height = memedit_ctrl.pScroll->h(); size = (int) (height / m_Height); @@ -2176,19 +2754,26 @@ MoveTo: This function moves to the specified line void T100_MemEditor::MoveTo(int address) { int height, size, value, col; + int curVal; + + /* If the range selected is RAM, then we need to subtract + the ROM size from the address so we jump to the right + location in the scroll bar */ + if ((m_Region == REGION_RAM) || (m_Region == REGION_RAM2) || + (m_Region == REGION_RAM3) || m_Region == REGION_RAM1) + address -= ROMSIZE; /* Calculate line value */ - value = address / 16; + value = address / 16 - 4; col = address % 16; // Erase the cursor, if any */ EraseCursor(); // Select 12 point Courier font - fl_font(FL_COURIER, m_FontSize); + fl_font(m_Font, m_FontSize); // Get height of screen in lines - m_Height = fl_height(); height = memedit_ctrl.pScroll->h(); size = (int) (height / m_Height); @@ -2200,44 +2785,154 @@ void T100_MemEditor::MoveTo(int address) if (value < 0) value = 0; - // Update scroll bar - memedit_ctrl.pScroll->value(value, 1, 0, (int) m_Max); - memedit_ctrl.pScroll->maximum(m_Max-size); - memedit_ctrl.pScroll->step(size / m_Max); - memedit_ctrl.pScroll->slider_size(size/m_Max); - memedit_ctrl.pScroll->linesize(1); - redraw(); + // Selet the selection region to hilight this location + m_SelStartAddr = address; + m_SelEndAddr = address; + + // Test if selection already displayed + curVal = memedit_ctrl.pScroll->value(); + if (!(value >= curVal && value < curVal+size)) + { + // Update scroll bar + memedit_ctrl.pScroll->value(value, 1, 0, (int) m_Max); + memedit_ctrl.pScroll->maximum(m_Max-size); + memedit_ctrl.pScroll->step(size / m_Max); + memedit_ctrl.pScroll->slider_size(size/m_Max); + memedit_ctrl.pScroll->linesize(1); + } /* Set cursor row and column */ - m_CursorRow = address / 16 - value; + m_CursorRow = address / 16 - memedit_ctrl.pScroll->value(); if (m_CursorField == 0) m_CursorField = 1; if (m_CursorField == 2) m_CursorCol = 59 + col; else - m_CursorCol = 9 + col * 3 + (col > 8 ? 1 : 0); + m_CursorCol = 9 + col * 3 + (col > 7 ? 1 : 0); + + redraw(); +} + +/* +================================================================ +Determine if the given address should be hilighted +================================================================ +*/ +int T100_MemEditor::IsHilighted(int address) +{ + int start, end; + + if (m_SelStartAddr > m_SelEndAddr) + { + start = m_SelEndAddr; + end = m_SelStartAddr; + } + else + { + start = m_SelStartAddr; + end = m_SelEndAddr; + } - DrawCursor(); + // Test if address falls within selection region + if (address >= start && address <= end) + return TRUE; + + return HasMarker(address); } -// Erase the cursor at its current position +/* +================================================================ +Determine if the given address has an associated marker +================================================================ +*/ +int T100_MemEditor::HasMarker(int address) +{ + int region; + memedit_marker_t* pMarkers; + + // Determine which region marker to use. For RAM banks 1,2,3, + // we use the REGION_RAM marker so they all have the same + // set of markers + region = m_Region; + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + region = REGION_RAM; + + // Get pointer to start of marker list + pMarkers = m_pRegionMarkers[region]; + + // Scan through the markers + while (pMarkers != NULL) + { + if (address >= pMarkers->startAddr && address <= pMarkers->endAddr) + return TRUE; + pMarkers = pMarkers->pNext; + } + + return FALSE; +} + +/* +================================================================ +Erase the cursor at its current position +================================================================ +*/ void T100_MemEditor::EraseCursor() { - int x_pos, y_pos; + int x_pos, y_pos, address, col; // Erase current cursor - fl_color(FL_WHITE); + fl_color(m_colors.background); if (m_CursorRow != -1) { x_pos = (int) (m_CursorCol * m_Width + x()); y_pos = (int) (m_CursorRow * m_Height + y()); - fl_line(x_pos-1, y_pos, x_pos-1, y_pos + (int) m_Height); - fl_line(x_pos, y_pos, x_pos, y_pos + (int) m_Height); - } + fl_line(x_pos-1, y_pos+2, x_pos-1, y_pos + (int) m_Height); + fl_line(x_pos, y_pos+2, x_pos, y_pos + (int) m_Height); + + // Now determine if we need to redraw any hilight regions for + // either the current or previous address + if (m_CursorField == 1) + { + // Process keystroke -- first determine address being modified + if (m_CursorCol > 8+8*3) + col = (int) ((m_CursorCol-10) / 3); + else + col = (int) ((m_CursorCol-9) / 3); + } + else + col = (int) m_CursorCol-59; + // Get address of first item on screen + address = memedit_ctrl.pScroll->value() * 16; + address += m_CursorRow * 16; + address += col; + + // If this item is hilighted, then redraw the hilight region + if (IsHilighted(address)) + { + // Select the hilight background color + fl_color(m_colors.hilight_background); + fl_line(x_pos, y_pos+2, x_pos, y_pos + (int) m_Height); + + // If we aren't on col zero, then test the next lower address too + if (m_CursorCol != 9 && m_CursorCol != 59 && m_CursorCol != 34) + { + if (IsHilighted(address-1)) + { + // Select the hilight background color + fl_color(m_colors.hilight_background); + fl_line(x_pos-1, y_pos+2, x_pos-1, y_pos+(int)m_Height); + } + } + } + } } -// Erase the cursor at its current position +/* +================================================================ +Draws the cursor at its current position +================================================================ +*/ void T100_MemEditor::DrawCursor() { int x_pos, y_pos; @@ -2246,19 +2941,23 @@ void T100_MemEditor::DrawCursor() return; // Draw new cursor - fl_color(FL_BLACK); + fl_color(m_colors.cursor); if (m_CursorRow != -1) { x_pos = (int) (m_CursorCol * m_Width + x()); y_pos = (int) (m_CursorRow * m_Height + y()); - fl_line(x_pos-1, y_pos, x_pos-1, y_pos + (int) m_Height-2); - fl_line(x_pos, y_pos, x_pos, y_pos + (int) m_Height-2); + fl_line(x_pos-1, y_pos+2, x_pos-1, y_pos + (int) m_Height-2); + fl_line(x_pos, y_pos+2, x_pos, y_pos + (int) m_Height-2); } UpdateAddressText(); } -// Update the Address edit box base on the position of the cursor +/* +================================================================ +Update the Address edit box base on the position of the cursor +================================================================ +*/ void T100_MemEditor::UpdateAddressText() { char string[10]; @@ -2315,15 +3014,36 @@ Load user preferences */ void MemoryEditor_LoadPrefs(void) { + int temp, bold; + virtualt_prefs.get("MemEdit_x", memedit_ctrl.pMemEdit->m_x, -1); virtualt_prefs.get("MemEdit_y", memedit_ctrl.pMemEdit->m_y, -1); virtualt_prefs.get("MemEdit_w", memedit_ctrl.pMemEdit->m_w, -1); virtualt_prefs.get("MemEdit_h", memedit_ctrl.pMemEdit->m_h, -1); + + // Get font settings + virtualt_prefs.get("MemEdit_FontSize", temp, -1); + virtualt_prefs.get("MemEdit_Bold", bold, 0); + if (temp != -1) + memedit_ctrl.pMemEdit->SetFontSize(temp, bold); + + // Get color settings + virtualt_prefs.get("MemEdit_BlackBackground", temp, 1); + memedit_ctrl.pMemEdit->SetBlackBackground(temp); + virtualt_prefs.get("MemEdit_SyntaxHilight", temp, 1); + memedit_ctrl.pMemEdit->SetSyntaxHilight(temp); + virtualt_prefs.get("MemEdit_MarkerForegroundColor", temp, (int) FL_WHITE); + memedit_ctrl.pMemEdit->SetMarkerForegroundColor((Fl_Color) temp); + virtualt_prefs.get("MemEdit_MarkerBackgroundColor", temp, (int) fl_lighter(FL_RED)); + memedit_ctrl.pMemEdit->SetMarkerBackgroundColor((Fl_Color) temp); + + // Load the region markers + memedit_ctrl.pMemEdit->LoadRegionMarkers(); } /* ============================================================================ -Load user preferences +Save user preferences ============================================================================ */ void MemoryEditor_SavePrefs(void) @@ -2332,4 +3052,873 @@ void MemoryEditor_SavePrefs(void) virtualt_prefs.set("MemEdit_y", gmew->y()); virtualt_prefs.set("MemEdit_w", gmew->w()); virtualt_prefs.set("MemEdit_h", gmew->h()); + virtualt_prefs.set("MemEdit_FontSize", memedit_ctrl.pMemEdit->GetFontSize()); + virtualt_prefs.set("MemEdit_Bold", memedit_ctrl.pMemEdit->GetBold()); + virtualt_prefs.set("MemEdit_BlackBackground", memedit_ctrl.pMemEdit->GetBlackBackground()); + virtualt_prefs.set("MemEdit_SyntaxHilight", memedit_ctrl.pMemEdit->GetSyntaxHilight()); + virtualt_prefs.set("MemEdit_MarkerForegroundColor", (int) memedit_ctrl.pMemEdit->GetMarkerForegroundColor()); + virtualt_prefs.set("MemEdit_MarkerBackgroundColor", (int) memedit_ctrl.pMemEdit->GetMarkerBackgroundColor()); + + // Save the region markers + memedit_ctrl.pMemEdit->SaveRegionMarkers(); +} + +/* +============================================================================ +Set's the memory editor's font size +============================================================================ +*/ +void T100_MemEditor::SaveRegionMarkers() +{ + char str[16], regStr[32]; + char markerText[32]; + char pref[64]; + MString markers; + int region; + memedit_marker_t* pMarkers; + + // Get the model string to save stuff per model + get_model_string(str, gModel); + + // Save region markers + for (region = 0; region < REGION_MAX; region++) + { + // Create region preference string + strcpy(pref, str); + sprintf(regStr, "_Region%d_Markers", region); + strcat(pref, regStr); + + // Now build the region marker text + markers = ""; + + // Get pointer to start of marker list and iterate + pMarkers = m_pRegionMarkers[region]; + while (pMarkers != NULL) + { + // Create next marker text + if (pMarkers->startAddr == pMarkers->endAddr) + sprintf(markerText, "%d", pMarkers->startAddr); + else + sprintf(markerText, "%d-%d", pMarkers->startAddr, pMarkers->endAddr); + + // If there's another marker after this one, append a ',' + if (pMarkers->pNext != NULL) + strcat(markerText, ","); + + // Add to the text + markers += markerText; + + // Point to next marker + pMarkers = pMarkers->pNext; + } + + virtualt_prefs.set(pref, (const char *) markers); + } +} + +/* +============================================================================ +Set's the memory editor's font size +============================================================================ +*/ +void T100_MemEditor::LoadRegionMarkers() +{ + char str[16], regStr[32]; + char* pMarkerText; + char pref[64]; + int region, startAddr, endAddr, c; + + // First reset any old markers + ResetMarkers(); + + // Get the model string to save stuff per model + get_model_string(str, gModel); + + // Allocate a big buffer to read in marker text + pMarkerText = new char[65536]; + + if (pMarkerText != NULL) + { + // Save region markers + for (region = 0; region < REGION_MAX; region++) + { + // Create region preference string + strcpy(pref, str); + sprintf(regStr, "_Region%d_Markers", region); + strcat(pref, regStr); + + // Get the text from preferences + virtualt_prefs.get(pref, pMarkerText, "", 65536); + + // Check if any markers defined + if (pMarkerText[0] != '\0') + { + // Parse the marker list + c = startAddr = endAddr = 0; + + while (pMarkerText[c] != '\0') + { + // Parse the startAddr + while (pMarkerText[c] != '-' && pMarkerText[c] != '\0' && + pMarkerText[c] != ',') + startAddr = startAddr * 10 + pMarkerText[c++] - '0'; + + // Skip the '-' + if (pMarkerText[c] == '-') + c++; + else if(pMarkerText[c] == ',' || pMarkerText[c] == '\0') + endAddr = startAddr; + + // Parse the endAddr + while (pMarkerText[c] != ',' && pMarkerText[c] != '\0') + endAddr = endAddr * 10 + pMarkerText[c++] - '0'; + + // Add this marker to the region + AddMarkerToRegion(startAddr, endAddr, region); + + // Skip the ',' if any + if (pMarkerText[c] == ',') + c++; + + // Clear start and end addr for the next marker + startAddr = endAddr = 0; + } + } + } + + // Delete the marker text + delete pMarkerText; + } +} + +/* +============================================================================ +Set's the memory editor's font size +============================================================================ +*/ +void T100_MemEditor::SetFontSize(int fontsize, int bold) +{ + // Save the font size + m_FontSize = fontsize; + m_Bold = bold; + + if (bold) + m_Font = FL_COURIER_BOLD; + else + m_Font = FL_COURIER; + + // Recalculate width and height + fl_font(m_Font, m_FontSize); + m_Width = fl_width("W", 1); + m_Height = fl_height(); +} + +/* +============================================================================ +Updates the editor's color scheme. +============================================================================ +*/ +void T100_MemEditor::UpdateColors(void) +{ + // Update the colors + if (m_ColorSyntaxHilight) + { + if (m_BlackBackground) + { + m_colors.background = FL_BLACK; + m_colors.foreground = FL_WHITE; + m_colors.addr = fl_lighter((Fl_Color) 166); + m_colors.number = FL_WHITE; + m_colors.ascii = FL_YELLOW; + m_colors.cursor = FL_WHITE; + m_colors.changed = FL_WHITE; + } + else + { + m_colors.background = FL_WHITE; + m_colors.foreground = FL_BLACK; + m_colors.addr = fl_darker(FL_RED); + m_colors.number = FL_BLACK; + m_colors.ascii = fl_darker(FL_BLUE); + m_colors.cursor = FL_BLACK; + m_colors.changed = FL_BLACK; + } + } + else + { + if (m_BlackBackground) + { + m_colors.background = FL_BLACK; + m_colors.foreground = FL_WHITE; + m_colors.addr = FL_WHITE; + m_colors.number = FL_WHITE; + m_colors.ascii = FL_WHITE; + m_colors.cursor = FL_WHITE; + m_colors.changed = FL_WHITE; + } + else + { + m_colors.background = FL_WHITE; + m_colors.foreground = FL_BLACK; + m_colors.addr = FL_BLACK; + m_colors.number = FL_BLACK; + m_colors.ascii = FL_BLACK; + m_colors.cursor = FL_BLACK; + m_colors.changed = FL_BLACK; + } + } + + // Now redraw + redraw(); +} + +/* +============================================================================ +Set's the memory editor's black background selection +============================================================================ +*/ +void T100_MemEditor::SetBlackBackground(int blackBackground) +{ + // Set the selection and update colors + m_BlackBackground = blackBackground; + UpdateColors(); +} + +/* +============================================================================ +Set's the memory editor's color syntax hilight selection +============================================================================ +*/ +void T100_MemEditor::SetSyntaxHilight(int colorSyntaxHilight) +{ + // Set the selection and update colors + m_ColorSyntaxHilight = colorSyntaxHilight; + UpdateColors(); +} + +/* +============================================================================ +Define a local struct for the setup parameters. +============================================================================ +*/ +typedef struct memedit_setup_params +{ + Fl_Input* pFontSize; + Fl_Check_Button* pBold; + Fl_Check_Button* pBlackBackground; + Fl_Check_Button* pColorHilight; + Fl_Button* pMarkerForeground; + Fl_Button* pMarkerBackground; + Fl_Button* pDefaults; + char sFontSize[20]; + Fl_Color origMarkerForeground; + Fl_Color origMarkerBackground; +} memedit_setup_params_t; + +/* +============================================================================ +Callback for Trace Setup Ok button +============================================================================ +*/ +static void cb_setupdlg_OK(Fl_Widget* w, void* pOpaque) +{ + memedit_setup_params_t* p = (memedit_setup_params_t *) pOpaque; + int fontsize; + + // Save values + if (strlen(p->pFontSize->value()) > 0) + { + // update the font size + fontsize = atoi(p->pFontSize->value()); + if (fontsize < 6) + fontsize = 6; + + // Set the new size + if (fontsize > 0) + memedit_ctrl.pMemEdit->SetFontSize(fontsize, p->pBold->value()); + } + + // Get Inverse Highlight selection + memedit_ctrl.pMemEdit->SetBlackBackground(p->pBlackBackground->value()); + + // Get hilighting option + memedit_ctrl.pMemEdit->SetSyntaxHilight(p->pColorHilight->value()); + + // Get Marker colors + memedit_ctrl.pMemEdit->SetMarkerForegroundColor((Fl_Color) p->pMarkerForeground->color()); + memedit_ctrl.pMemEdit->SetMarkerBackgroundColor((Fl_Color) p->pMarkerBackground->color()); + + // Redraw the window + gmew->redraw(); + + // Now hide the parent dialog + w->parent()->hide(); +} + +/* +============================================================================ +Callback for Trace Setup Cancel button +============================================================================ +*/ +static void cb_setupdlg_cancel(Fl_Widget* w, void* pOpaque) +{ + memedit_setup_params_t* p = (memedit_setup_params_t *) pOpaque; + + // Hide the parent dialog so we cancel out + w->parent()->hide(); + + // Restore original marker colors and redraw + memedit_ctrl.pMemEdit->SetMarkerForegroundColor(p->origMarkerForeground); + memedit_ctrl.pMemEdit->SetMarkerBackgroundColor(p->origMarkerBackground); + memedit_ctrl.pMemEdit->redraw(); +} + +/* +============================================================================ +Callback for default marker colors. +============================================================================ +*/ +static void cb_default_colors(Fl_Button*, void* pOpaque) +{ + memedit_setup_params_t* p = (memedit_setup_params_t *) pOpaque; + + p->pMarkerBackground->color(fl_lighter(FL_RED)); + p->pMarkerForeground->color(FL_WHITE); + p->pMarkerBackground->redraw(); + p->pMarkerForeground->redraw(); + memedit_ctrl.pMemEdit->SetMarkerForegroundColor(p->pMarkerForeground->color()); + memedit_ctrl.pMemEdit->SetMarkerBackgroundColor(p->pMarkerBackground->color()); + memedit_ctrl.pMemEdit->redraw(); +} + +/* +============================================================================ +Callback for Marker Foreground color button +============================================================================ +*/ +static void cb_marker_foreground(Fl_Button*, void* pOpaque) +{ + memedit_setup_params_t* p = (memedit_setup_params_t *) pOpaque; + + p->pMarkerForeground->color(fl_show_colormap(p->pMarkerForeground->color())); + memedit_ctrl.pMemEdit->SetMarkerForegroundColor(p->pMarkerForeground->color()); + memedit_ctrl.pMemEdit->redraw(); +} + +/* +============================================================================ +Callback for Marker Background color button +============================================================================ +*/ +static void cb_marker_background(Fl_Button*, void* pOpaque) +{ + memedit_setup_params_t* p = (memedit_setup_params_t *) pOpaque; + + p->pMarkerBackground->color(fl_show_colormap(p->pMarkerBackground->color())); + memedit_ctrl.pMemEdit->SetMarkerBackgroundColor(p->pMarkerBackground->color()); + memedit_ctrl.pMemEdit->redraw(); +} + +/* +============================================================================ +Menu callback for setup memory editor +============================================================================ +*/ +void cb_setup_memedit(Fl_Widget* w, void* pOpaque) +{ + Fl_Box* b; + Fl_Window* pWin; + memedit_setup_params_t p; + + // Save current Marker colors + p.origMarkerForeground = memedit_ctrl.pMemEdit->GetMarkerForegroundColor(); + p.origMarkerBackground = memedit_ctrl.pMemEdit->GetMarkerBackgroundColor(); + + // Create new window for memory editor configuration + pWin = new Fl_Window(300, 200, "Memory Editor Configuration"); + + /* Create input field for font size */ + b = new Fl_Box(20, 20, 100, 20, "Font Size"); + b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + p.pFontSize = new Fl_Input(120, 20, 60, 20, ""); + p.pFontSize->align(FL_ALIGN_LEFT); + sprintf(p.sFontSize, "%d", memedit_ctrl.pMemEdit->GetFontSize()); + p.pFontSize->value(p.sFontSize); + + /* Create checkbox for bold font selection */ + p.pBold = new Fl_Check_Button(200, 20, 60, 20, "Bold"); + p.pBold->value(memedit_ctrl.pMemEdit->GetBold()); + + /* Create checkbox for hilight style */ + p.pBlackBackground = new Fl_Check_Button(20, 50, 190, 20, "Black background"); + p.pBlackBackground->value(memedit_ctrl.pMemEdit->GetBlackBackground()); + + /* Create checkbox for color hilighting */ + p.pColorHilight = new Fl_Check_Button(20, 80, 200, 20, "Color hilighting"); + p.pColorHilight->value(memedit_ctrl.pMemEdit->GetSyntaxHilight()); + + /* Create a button for the marker foreground color */ + p.pMarkerForeground = new Fl_Button(20, 110, 15, 15, "Marker Forground Color"); + p.pMarkerForeground->callback((Fl_Callback*) cb_marker_foreground, &p); + p.pMarkerForeground->align(FL_ALIGN_RIGHT); + p.pMarkerForeground->color(memedit_ctrl.pMemEdit->GetMarkerForegroundColor()); + + /* Create a button for the marker background color */ + p.pMarkerBackground = new Fl_Button(20, 130, 15, 15, "Marker background Color"); + p.pMarkerBackground->callback((Fl_Callback*) cb_marker_background, &p); + p.pMarkerBackground->align(FL_ALIGN_RIGHT); + p.pMarkerBackground->color(memedit_ctrl.pMemEdit->GetMarkerBackgroundColor()); + + p.pDefaults = new Fl_Button(210, 115, 70, 30, "Default"); + p.pDefaults->callback((Fl_Callback *) cb_default_colors, &p); + + // Cancel button + { Fl_Button* o = new Fl_Button(80, 160, 60, 30, "Cancel"); + o->callback((Fl_Callback*) cb_setupdlg_cancel, &p); + } + + // OK button + { Fl_Return_Button* o = new Fl_Return_Button(160, 160, 60, 30, "OK"); + o->callback((Fl_Callback*) cb_setupdlg_OK, &p); + } + + // Loop until user presses OK or Cancel + pWin->show(); + while (pWin->visible()) + Fl::wait(); + + // Delete the window + delete pWin; +} + +/* +============================================================================ +Menu callback for adding a marker +============================================================================ +*/ +void cb_add_marker(Fl_Widget* w, void* pOpaque) +{ + memedit_ctrl.pMemEdit->AddMarker(); +} + +/* +============================================================================ +Adds the current SelStart / SelEnd selection as a new marker +============================================================================ +*/ +void T100_MemEditor::AddMarker(int region) +{ + memedit_marker_t* pMarkers; + memedit_marker_t* pNewMarker; + + // Determine which region marker to use. For RAM banks 1,2,3, + // we use the REGION_RAM marker so they all have the same + // set of markers + if (region == -1) + { + region = m_Region; + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + region = REGION_RAM; + } + + // Get pointer to start of marker list + pMarkers = m_pRegionMarkers[region]; + + // Create a new marker for this selection + pNewMarker = new memedit_marker_t; + pNewMarker->startAddr = m_SelStartAddr; + pNewMarker->endAddr = m_SelEndAddr; + pNewMarker->pNext = NULL; + + // Insert this marker into the list + if (pMarkers == NULL) + { + // This is the head item. Just insert it + m_pRegionMarkers[region] = pNewMarker; + } + else + { + // Find end of marker list + while (pMarkers->pNext != NULL) + pMarkers = pMarkers->pNext; + + // Insert the marker here + pMarkers->pNext = pNewMarker; + } +} + +/* +============================================================================ +Adds the specified marker to the specified region +============================================================================ +*/ +void T100_MemEditor::AddMarkerToRegion(int startAddr, int endAddr, int region) +{ + memedit_marker_t* pMarkers; + memedit_marker_t* pNewMarker; + + // Get pointer to start of marker list + pMarkers = m_pRegionMarkers[region]; + + // Create a new marker for this selection + pNewMarker = new memedit_marker_t; + pNewMarker->startAddr = startAddr; + pNewMarker->endAddr = endAddr; + pNewMarker->pNext = NULL; + + // Insert this marker into the list + if (pMarkers == NULL) + { + // This is the head item. Just insert it + m_pRegionMarkers[region] = pNewMarker; + } + else + { + // Find end of marker list + while (pMarkers->pNext != NULL) + pMarkers = pMarkers->pNext; + + // Insert the marker here + pMarkers->pNext = pNewMarker; + } +} + +/* +============================================================================ +Menu callback for deleting a marker +============================================================================ +*/ +void cb_delete_marker(Fl_Widget* w, void*) +{ + memedit_ctrl.pMemEdit->DeleteMarker(); +} + +/* +============================================================================ +Menu callback for deleting all markers +============================================================================ +*/ +void cb_delete_all_markers(Fl_Widget* w, void*) +{ + memedit_ctrl.pMemEdit->DeleteAllMarkers(); +} + +/* +============================================================================ +Menu callback for deleting all markers +============================================================================ +*/ +void cb_undo_delete_all_markers(Fl_Widget* w, void*) +{ + memedit_ctrl.pMemEdit->UndoDeleteAllMarkers(); +} + +/* +============================================================================ +Menu callback for finding the next marker +============================================================================ +*/ +void cb_goto_next_marker(Fl_Widget* w, void*) +{ + memedit_ctrl.pMemEdit->FindNextMarker(); +} + +/* +============================================================================ +Menu callback for finding the prev marker +============================================================================ +*/ +void cb_goto_prev_marker(Fl_Widget* w, void*) +{ + memedit_ctrl.pMemEdit->FindPrevMarker(); +} + +/* +============================================================================ +Find's the next marker after the current cursor address +============================================================================ +*/ +void T100_MemEditor::FindNextMarker(void) +{ + int region, nextAddr, firstAddr; + memedit_marker_t* pMarkers; + + // Determine which region marker to use. For RAM banks 1,2,3, + // we use the REGION_RAM marker so they all have the same + // set of markers + region = m_Region; + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + region = REGION_RAM; + + // Get pointer to start of marker list + pMarkers = m_pRegionMarkers[region]; + nextAddr = 99999999; + firstAddr = 99999999; + + // Loop through all markers + while (pMarkers != NULL) + { + // Test if this address is greater than the current address + if (pMarkers->startAddr > m_CursorAddress) + { + // Find the lowest address that is greater than current address + if (pMarkers->startAddr < nextAddr) + nextAddr = pMarkers->startAddr; + } + + // Find the address of the lowest marker in case we wrap + if (pMarkers->startAddr < firstAddr) + firstAddr = pMarkers->startAddr; + + // Point to next marker + pMarkers = pMarkers->pNext; + } + + // If no more markers greater than current address, then wrap to 1st + if (nextAddr == 99999999) + nextAddr = firstAddr; + + // If we found a marker, then jump there + if (nextAddr != 99999999) + { + if (region == REGION_RAM) + nextAddr += ROMSIZE; + MoveTo(nextAddr); + UpdateAddressText(); + } +} + +/* +============================================================================ +Find's the next marker after the current cursor address +============================================================================ +*/ +void T100_MemEditor::FindPrevMarker(void) +{ + int region, prevAddr, lastAddr; + memedit_marker_t* pMarkers; + + // Determine which region marker to use. For RAM banks 1,2,3, + // we use the REGION_RAM marker so they all have the same + // set of markers + region = m_Region; + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + region = REGION_RAM; + + // Get pointer to start of marker list + pMarkers = m_pRegionMarkers[region]; + prevAddr = -1; + lastAddr = -1; + + // Loop through all markers + while (pMarkers != NULL) + { + // Test if this address is greater than the current address + if (pMarkers->endAddr < m_CursorAddress) + { + // Find the lowest address that is greater than current address + if (pMarkers->startAddr > prevAddr) + prevAddr = pMarkers->startAddr; + } + + // Find the address of the lowest marker in case we wrap + if (pMarkers->startAddr > lastAddr) + lastAddr = pMarkers->startAddr; + + // Point to next marker + pMarkers = pMarkers->pNext; + } + + // If no more markers greater than current address, then wrap to 1st + if (prevAddr == -1) + prevAddr = lastAddr; + + // If we found a marker, then jump there + if (prevAddr != -1) + { + if (region == REGION_RAM) + prevAddr += ROMSIZE; + MoveTo(prevAddr); + UpdateAddressText(); + } +} + +/* +============================================================================ +Deletes the marker identified by the Cursor. +============================================================================ +*/ +void T100_MemEditor::DeleteMarker(void) +{ + int region; + memedit_marker_t* pMarkers; + memedit_marker_t* pLastMarker; + + // Determine which region marker to use. For RAM banks 1,2,3, + // we use the REGION_RAM marker so they all have the same + // set of markers + region = m_Region; + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + region = REGION_RAM; + + // Get pointer to start of marker list + pMarkers = m_pRegionMarkers[region]; + pLastMarker = NULL; + + // Loop for all markers and search for the one containing + // the current cursor address + while (pMarkers != NULL) + { + if (m_CursorAddress >= pMarkers->startAddr && m_CursorAddress <= + pMarkers->endAddr) + { + // Delete this marker + if (pLastMarker == NULL) + { + // We are deleting the 1st marker + m_pRegionMarkers[region] = pMarkers->pNext; + } + else + // We are deleting in the middle or end + pLastMarker->pNext = pMarkers->pNext; + + // Delete this marker + delete pMarkers; + + // Clear any selection that may exist + m_SelStartAddr = m_SelEndAddr = -1; + redraw(); + + break; + } + + // Get pointer to next marker + pLastMarker = pMarkers; + pMarkers = pMarkers->pNext; + } +} + +/* +============================================================================ +Deletes the marker identified by the Cursor. +============================================================================ +*/ +void T100_MemEditor::DeleteAllMarkers(void) +{ + int region; + memedit_marker_t* pMarkers; + memedit_marker_t* pNextMarker; + + // Determine which region marker to use. For RAM banks 1,2,3, + // we use the REGION_RAM marker so they all have the same + // set of markers + region = m_Region; + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + region = REGION_RAM; + + // First test if we have an existing undo delete all markers list + pMarkers = m_pUndoDeleteMarkers[region]; + while (pMarkers != NULL) + { + // Get pointer to next marker + pNextMarker = pMarkers->pNext; + + // Delete this marker and move on to the next one + delete pMarkers; + pMarkers = pNextMarker; + } + + // Get pointer to start of marker list + pMarkers = m_pRegionMarkers[region]; + + // Save it in the undo delete all markers buffer + if (pMarkers != NULL) + { + m_pUndoDeleteMarkers[region] = pMarkers; + m_pRegionMarkers[region] = NULL; + } + + m_SelStartAddr = m_SelEndAddr = -1; + redraw(); +} + +/* +============================================================================ +Undoes the delete all markers for this region +============================================================================ +*/ +void T100_MemEditor::UndoDeleteAllMarkers(void) +{ + int region; + + // Determine which region marker to use. For RAM banks 1,2,3, + // we use the REGION_RAM marker so they all have the same + // set of markers + region = m_Region; + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + region = REGION_RAM; + + // Check if we have an undo buffer for this region + if (m_pUndoDeleteMarkers[region] != NULL) + { + // Check if we have new markers that have been created + if (m_pRegionMarkers[region] != NULL) + { + // Do something. Should we delete, merge or ask? + } + + // Restore the old marker list + m_pRegionMarkers[region] = m_pUndoDeleteMarkers[region]; + m_pUndoDeleteMarkers[region] = NULL; + + m_SelStartAddr = m_SelEndAddr = -1; + redraw(); + } +} + +/* +============================================================================ +Deletes the marker identified by the Cursor. +============================================================================ +*/ +void T100_MemEditor::ResetMarkers(void) +{ + int region; + memedit_marker_t* pMarkers; + memedit_marker_t* pNextMarker; + + // Determine which region marker to use. For RAM banks 1,2,3, + // we use the REGION_RAM marker so they all have the same + // set of markers + for (region = 0; region < REGION_MAX; region++) + { + // Get pointer to start of marker list + pMarkers = m_pRegionMarkers[region]; + + // Loop for all markers in this region + while (pMarkers != NULL) + { + // Get pointer to next marker + pNextMarker = pMarkers->pNext; + + // Delete this marker + delete pMarkers; + pMarkers = pNextMarker; + } + + // Now delete the undo all markers (if any) + // Get pointer to start of marker list + pMarkers = m_pUndoDeleteMarkers[region]; + + // Loop for all markers in this region + while (pMarkers != NULL) + { + // Get pointer to next marker + pNextMarker = pMarkers->pNext; + + // Delete this marker + delete pMarkers; + pMarkers = pNextMarker; + } + } } diff --git a/src/memedit.h b/src/memedit.h index a5de412..f38ba90 100644 --- a/src/memedit.h +++ b/src/memedit.h @@ -31,8 +31,10 @@ #ifndef MEMEDIT_H #define MEMEDIT_H +#include "memory.h" #include "FL/Fl_File_Chooser.H" +#include void cb_MemoryEditor (Fl_Widget* w, void*); void cb_MemoryEditorUpdate(void); @@ -42,6 +44,33 @@ void MemoryEditor_SavePrefs(void); #define MENU_HEIGHT 32 +typedef struct memedit_colors +{ + Fl_Color addr; + Fl_Color number; + Fl_Color ascii; + Fl_Color changed; + Fl_Color hilight; + Fl_Color hilight_background; + Fl_Color foreground; + Fl_Color background; + Fl_Color cursor; +} memedit_colors_t; + +// Structure to keep track of region markers +typedef struct memedit_marker +{ + int startAddr; + int endAddr; + struct memedit_marker* pNext; +} memedit_marker_t; + +class T100_MemEditWin : public Fl_Double_Window +{ +public: + T100_MemEditWin(int x, int y, int w, int h, const char *title); +}; + class T100_MemEditor : public Fl_Widget { public: @@ -55,7 +84,34 @@ class T100_MemEditor : public Fl_Widget int GetRegionEnum(void); void UpdateAddressText(void); void UpdateDispMem(void); + void ClearSelection(void) { m_SelStartAddr = -1; m_SelEndAddr = -1; } + void SetFontSize(int fontsize, int bold = 0); + void SetBlackBackground(int blackBackground); + void SetSyntaxHilight(int colorSyntaxHilight); + void UpdateColors(void); void MoveTo(int value); + + int GetFontSize(void) { return m_FontSize; } + int GetBold(void) { return m_Bold; } + int GetBlackBackground(void) { return m_BlackBackground; } + int GetSyntaxHilight(void) { return m_ColorSyntaxHilight; } + Fl_Color GetMarkerForegroundColor(void) { return m_colors.hilight; } + Fl_Color GetMarkerBackgroundColor(void) { return m_colors.hilight_background; } + void SetMarkerForegroundColor(Fl_Color c) { m_colors.hilight = c; redraw(); } + void SetMarkerBackgroundColor(Fl_Color c) { m_colors.hilight_background = c; redraw(); } + + int IsHilighted(int address); // Returns TRUE if given address should e hilighted + int HasMarker(int address); // Returns TRUE if given address has a marker + void AddMarker(int region=-1); // Adds marker at current m_SelStart, m_SelEnd address + void DeleteMarker(void); // Delete the marker at the cursor + void DeleteAllMarkers(void); // Delete all markers for this region + void UndoDeleteAllMarkers(void); // Undo Delete all markers for this region + void SaveRegionMarkers(void); // Save region markers to the preferences + void LoadRegionMarkers(void); // Load region markers from preferences + void AddMarkerToRegion(int start, int end, int region); + void FindNextMarker(void); + void FindPrevMarker(void); + int m_FirstLine; int m_x, m_y, m_w, m_h; // user preferences for window position @@ -67,8 +123,10 @@ class T100_MemEditor : public Fl_Widget void EraseCursor(void); void ScrollUp(int lines); void ScrollDown(int lines); + void ResetMarkers(void); int m_MyFocus; + int m_HaveMouse; int m_Region; int m_Cols; int m_Lines; @@ -77,18 +135,34 @@ class T100_MemEditor : public Fl_Widget double m_Width; int m_FirstAddress; int m_FontSize; + int m_Bold; int m_CursorAddress; int m_CursorCol; int m_CursorRow; int m_CursorField; + int m_CursorAddr; + int m_DragX, m_DragY; // Current selection control -- active & start / end addresses int m_SelActive; long m_SelEndRow; long m_SelEndCol; + long m_SelStartAddr; + long m_SelEndAddr; + int m_DblclkX, m_DblclkY; + int m_PopupActive; + Fl_Font m_Font; + + int m_BlackBackground; + int m_ColorSyntaxHilight; + + memedit_colors_t m_colors; + memedit_marker_t* m_pRegionMarkers[REGION_MAX]; + memedit_marker_t* m_pUndoDeleteMarkers[REGION_MAX]; Fl_Scrollbar* m_pScroll; + Fl_Menu_Button* m_pPopupMenu; }; #endif diff --git a/src/memory.c b/src/memory.c index 0e5b438..0f38815 100644 --- a/src/memory.c +++ b/src/memory.c @@ -26,6 +26,7 @@ memory.c #include "filewrap.h" uchar *gMemory[64]; /* CPU Memory space */ +int gRamBottom = 0xa000;/* Defines the amount of RAM installed */ uchar gBaseMemory[65536]; /* System Memory */ uchar gSysROM[65536]; /* System ROM */ uchar gOptROM[32768]; /* Option ROM */ @@ -112,7 +113,7 @@ unsigned char get_memory8(unsigned short address) } } else - return gBaseMemory[address]; + return (address>ROMSIZE&&address>10][address&0x3FF] + (gMemory[(address+1)>>10][(address+1)&0x3FF] << 8); } else - return gBaseMemory[address] + (gBaseMemory[address+1] << 8); + return (address>ROMSIZE&&addressROMSIZE&&address= ROMSIZE) - gBaseMemory[address] = val; + { + if (address>=RAMBOTTOM) + gBaseMemory[address] = val; + } else { if (gRex == REX2) diff --git a/src/memory.h b/src/memory.h index 24b6aa6..769d3b3 100644 --- a/src/memory.h +++ b/src/memory.h @@ -105,6 +105,7 @@ extern "C" { #define REGION_RAMPAC 10 #define REGION_REX_FLASH 11 #define REGION_REX2_RAM 12 +#define REGION_MAX 13 #define REX 1 #define REX2 2 diff --git a/src/project.cpp b/src/project.cpp index 1d07ed7..bb3904f 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -380,6 +380,8 @@ void cb_settings_ok(Fl_Widget* w, void*) pProject->m_TargetModel = pProj->getTargetModel(); pProject->m_AutoLoad = pProj->getAutoLoad(); pProject->m_UpdateHIMEM = pProj->getUpdateHIMEM(); + pProject->m_CreateLoader = pProj->getCreateLoader(); + pProject->m_LoaderFilename = pProj->getLoaderFilename(); // Update the Assembler Options pProject->AsmDebugInfo(pProj->getAsmDebugInfo()); @@ -424,12 +426,12 @@ VT_ProjectSettings::VT_ProjectSettings(VT_Project *pProj) m_pProject = pProj; // Create new window - m_pWnd = new Fl_Double_Window(100, 150, 380,320, "Project Settings"); + m_pWnd = new Fl_Double_Window(100, 150, 380,380, "Project Settings"); - m_pTabs = new Fl_Tabs(10, 10, 360, 260); + m_pTabs = new Fl_Tabs(10, 10, 360, 320); // Create the General tab - g = new Fl_Group(10, 30, 380, 280, "General"); + g = new Fl_Group(10, 30, 380, 340, "General"); // Text for the project type o = new Fl_Box(20, 50, 100, 20, "Project Type"); @@ -483,10 +485,19 @@ VT_ProjectSettings::VT_ProjectSettings(VT_Project *pProj) if (m_pProject->m_AutoLoad == 0) EnableUpdateHIMEM(FALSE); + // Create checkbox for Create BASIC loader + m_pCreateLoader = new Fl_Check_Button(24, 260, 250, 20, "Create BASIC loader"); + m_pCreateLoader->value(m_pProject->m_CreateLoader); + + // Create edit field for loader filename + o = new Fl_Box(44, 280, 200, 20, "BASIC Loader Filename"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pLoaderFilename = new Fl_Input(44, 300, 300, 20, ""); + m_pLoaderFilename->value((const char *) m_pProject->m_LoaderFilename); g->end(); // Create an Assembler tab - g = new Fl_Group(10, 30, 380, 280, "Assembler"); + g = new Fl_Group(10, 30, 380, 340, "Assembler"); // Create checkboxes m_pAsmDebugInfo = new Fl_Check_Button(20, 50, 165, 20, "Generate Debug Info"); @@ -502,19 +513,19 @@ VT_ProjectSettings::VT_ProjectSettings(VT_Project *pProj) o = new Fl_Box(20, 110, 100, 20, "Additional Include Directories"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); m_pIncludeDirs = new Fl_Input(20, 130, 320, 20, ""); - m_pIncludeDirs->value(m_pProject->m_IncludePath); + m_pIncludeDirs->value((const char *) m_pProject->m_IncludePath); // Create edit field for Additional Defines o = new Fl_Box(20, 170, 100, 20, "Additional Assembler Defines"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); m_pDefines = new Fl_Input(20, 190, 320, 20, ""); - m_pDefines->value(m_pProject->m_Defines); + m_pDefines->value((const char *) m_pProject->m_Defines); // End the Assembler tab g->end(); // Create a Linker tab - g = new Fl_Group(10, 30, 380, 280, "Linker"); + g = new Fl_Group(10, 30, 380, 340, "Linker"); // Create checkboxes m_pLinkDebugInfo = new Fl_Check_Button(20, 50, 165, 20, "Generate Debug Info"); @@ -558,12 +569,12 @@ VT_ProjectSettings::VT_ProjectSettings(VT_Project *pProj) // OK button { - Fl_Button* o = new Fl_Button(200, 282, 60, 30, "Cancel"); + Fl_Button* o = new Fl_Button(200, 342, 60, 30, "Cancel"); o->callback((Fl_Callback*)cb_settings_cancel); o->user_data(this); } { - Fl_Return_Button* o = new Fl_Return_Button(280, 282, 60, 30, "OK"); + Fl_Return_Button* o = new Fl_Return_Button(280, 342, 60, 30, "OK"); o->callback((Fl_Callback*)cb_settings_ok); o->user_data(this); } @@ -657,6 +668,22 @@ int VT_ProjectSettings::getUpdateHIMEM() return m_pUpdateHIMEM->value(); } +int VT_ProjectSettings::getCreateLoader() +{ + if (m_pCreateLoader == NULL) + return 0; + + return m_pCreateLoader->value(); +} + +MString VT_ProjectSettings::getLoaderFilename() +{ + if (m_pLoaderFilename == NULL) + return ""; + + return m_pLoaderFilename->value(); +} + MString VT_ProjectSettings::getDefines(void) { if (m_pDefines == NULL) @@ -975,6 +1002,8 @@ void VT_Project::SaveProject(void) fprintf(fd, "TARGET=%s\n", model); fprintf(fd, "AUTOLOAD=%d\n", m_AutoLoad); fprintf(fd, "UPDATEHIMEM=%d\n", m_UpdateHIMEM); + fprintf(fd, "CREATELOADER=%d\n", m_CreateLoader); + fprintf(fd, "LOADERFILENAME=%s\n", (const char *) m_LoaderFilename); fprintf(fd, "\n"); // Write group information to the file diff --git a/src/project.h b/src/project.h index 3902b7e..d0344a9 100644 --- a/src/project.h +++ b/src/project.h @@ -56,7 +56,8 @@ class VT_Project { public: VT_Project() { m_Dirty = 0; m_AutoLoad = 0; m_ProjectType = 0; - m_TargetModel = 0; m_UpdateHIMEM = 0; m_LinkScript = ""; } + m_TargetModel = 0; m_UpdateHIMEM = 0; m_LinkScript = ""; + m_CreateLoader = 0; } ~VT_Project(); void AsmDebugInfo(int enable); @@ -104,6 +105,8 @@ class VT_Project int m_TargetModel; // Target model to assemble for int m_AutoLoad; // Load to emulator after assemble? int m_UpdateHIMEM; // Auto update HIMEM variable? + int m_CreateLoader; // Create BASIC loader for .CO program? + MString m_LoaderFilename; // BASIC loader filename }; class VT_NewProject @@ -156,6 +159,8 @@ class VT_ProjectSettings int getTargetModel(); int getAutoLoad(); int getUpdateHIMEM(); + int getCreateLoader(); + MString getLoaderFilename(void); MString getDefines(void); MString getIncludeDirs(void); @@ -190,6 +195,8 @@ class VT_ProjectSettings Fl_Round_Button* m_pKC85; Fl_Check_Button* m_pAutoLoad; Fl_Check_Button* m_pUpdateHIMEM; + Fl_Check_Button* m_pCreateLoader; + Fl_Input* m_pLoaderFilename; // Define Assembler tab items Fl_Button* m_pAsmDebugInfo; diff --git a/src/remote.cpp b/src/remote.cpp index ff75cd3..30746e7 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -455,7 +455,7 @@ void cb_remote_debug(int reason) char str[40]; // Test if callback is for an interrupt - if (reason == DEBUG_INTERRUPT) + if (reason == DEBUG_INTERRUPT || reason == DEBUG_CPU_STEP) { return; } diff --git a/src/setup.cpp b/src/setup.cpp index 2f0ac65..9d573b1 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -52,6 +52,7 @@ #include "FLU/Flu_File_Chooser.h" +#include "VirtualT.h" #include "m100emu.h" #include "serial.h" #include "setup.h" @@ -112,10 +113,10 @@ typedef struct setup_ctrl_struct } clock; } setup_ctrl_t; - typedef struct memory_ctrl_struct { Fl_Round_Button* pNone; + Fl_Choice* pMemInstalled; Fl_Round_Button* pReMem; Fl_Round_Button* pRampac; Fl_Round_Button* pReMem_Rampac; @@ -138,6 +139,7 @@ typedef struct memory_ctrl_struct extern "C" { extern int gOptRomRW; extern int gShowVersion; +extern int gRamBottom; } @@ -622,6 +624,35 @@ void cb_PeripheralSetup (Fl_Widget* w, void*) gpsw->show(); } +/* +============================================================================ +Sets the current gRamBottom base on model. +============================================================================ +*/ +void set_memory_base(void) +{ + switch (gModel) + { + case MODEL_T200: + break; + + case MODEL_PC8201: + break; + + default: + switch (mem_setup.mem_installed) + { + case 0: gRamBottom = 0x8000; break; + case 1: gRamBottom = 0xA000; break; + case 2: gRamBottom = 0xC000; break; + case 3: gRamBottom = 0xE000; break; + default: gRamBottom = 0x8000; break; + } + + break; + } +} + /* ============================================================================ Routines to load and save setup structure to the user preferences @@ -639,6 +670,10 @@ void save_memory_preferences(void) strcat(pref, "_MemMode"); virtualt_prefs.set(pref, mem_setup.mem_mode); + strcpy(pref, str); + strcat(pref, "_MemInstalled"); + virtualt_prefs.set(pref, mem_setup.mem_installed); + strcpy(pref, str); strcat(pref, "_ReMemOverride"); virtualt_prefs.set(pref, mem_setup.remem_override); @@ -666,6 +701,9 @@ void save_memory_preferences(void) strcpy(pref, str); strcat(pref, "_ShowVersion"); virtualt_prefs.set(pref, gShowVersion); + + // Update the BASE RAM size + set_memory_base(); } void load_memory_preferences(void) @@ -681,6 +719,11 @@ void load_memory_preferences(void) strcat(pref, "_MemMode"); virtualt_prefs.get(pref, mem_setup.mem_mode,0); + // Load mem size installed based on Model + strcpy(pref, str); + strcat(pref, "_MemInstalled"); + virtualt_prefs.get(pref, mem_setup.mem_installed,0); + // Load ReMemOverride setting strcpy(pref, str); strcat(pref, "_ReMemOverride"); @@ -731,6 +774,9 @@ void load_memory_preferences(void) strcpy(pref, str); strcat(pref, "_ShowVersion"); virtualt_prefs.get(pref, gShowVersion, 1); + + // Update the BASE RAM size + set_memory_base(); } /* @@ -818,6 +864,9 @@ void cb_memory_OK(Fl_Widget* w, void*) else if (mem_ctrl.pRex2->value() == 1) mem_setup.mem_mode = SETUP_MEM_REX2; + // Get Memory installed selection + mem_setup.mem_installed = mem_ctrl.pMemInstalled->value(); + // Get OptRom R/W Enable setting gOptRomRW = mem_ctrl.pOptRomRW->value(); @@ -944,6 +993,7 @@ void cb_memory_OK(Fl_Widget* w, void*) load_sys_rom(); /* Reset the CPU */ + init_cpu(); resetcpu(); gExitLoop = 1; @@ -1292,12 +1342,36 @@ void cb_MemorySetup (Fl_Widget* w, void*) gmsw->callback(cb_memorywin); // Create items on the Tab - mem_ctrl.pNone = new Fl_Round_Button(20, 20, 180, 20, "Base Memory"); + mem_ctrl.pNone = new Fl_Round_Button(20, 20, 120, 20, "Base Memory"); mem_ctrl.pNone->type(FL_RADIO_BUTTON); mem_ctrl.pNone->callback(cb_radio_base_memory); if (mem_setup.mem_mode == SETUP_MEM_BASE) mem_ctrl.pNone->value(1); + // Create list box for the amount of installed memory + mem_ctrl.pMemInstalled = new Fl_Choice(280, 20, 60, 20, "Memory Installed:"); + mem_ctrl.pMemInstalled->align(FL_ALIGN_LEFT); + if (gModel == MODEL_T200) + { + mem_ctrl.pMemInstalled->add("72K"); + mem_ctrl.pMemInstalled->add("48K"); + mem_ctrl.pMemInstalled->add("24K"); + } + else if (gModel == MODEL_PC8201) + { + mem_ctrl.pMemInstalled->add("96K"); + mem_ctrl.pMemInstalled->add("64K"); + mem_ctrl.pMemInstalled->add("32K"); + } + else if (gModel != MODEL_T200) + { + mem_ctrl.pMemInstalled->add("32K"); + mem_ctrl.pMemInstalled->add("24K"); + mem_ctrl.pMemInstalled->add("16K"); + mem_ctrl.pMemInstalled->add("8K"); + } + mem_ctrl.pMemInstalled->value(mem_setup.mem_installed); + mem_ctrl.pRampac = new Fl_Round_Button(20, 45, 180, 20, "RamPac (256K RAM)"); mem_ctrl.pRampac->type(FL_RADIO_BUTTON); mem_ctrl.pRampac->callback(cb_radio_rampac); diff --git a/src/setup.h b/src/setup.h index fd58d5e..7fd4f06 100644 --- a/src/setup.h +++ b/src/setup.h @@ -70,6 +70,7 @@ extern peripheral_setup_t setup; typedef struct memory_setup { int mem_mode; // Mode for Memory emulation + int mem_installed; // Amount of memory installed int remem_override; // Override setting for ReMem's Rampac char remem_file[256]; // Filename for ReMem storage char rampac_file[256]; // Filename for RamPac storage From 5ccdab9ba17517d315f034212c64826553892261 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Mon, 11 Feb 2013 08:39:27 +0000 Subject: [PATCH 225/327] Removed a debug print. --- src/linker.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/linker.cpp b/src/linker.cpp index 786f359..e0fd4b9 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -2495,7 +2495,6 @@ int VTLinker::GenerateLoaderFile(int startAddr, int endAddr, int entryAddr) // Check if time to output a quintuple from our quadtuple if (++quadtuple == 4) { - printf("%d\n", ascii85); CreateQuintuple(fd, ascii85, lineNo, dataCount, lastDataFilePos, lineCount, checksum); From e9ff23fe9d5dc33b1404b3aceb0ffd84187c26ec Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 15 Feb 2013 13:03:26 +0000 Subject: [PATCH 226/327] Added Watch Table widget files and added the widget to the Memory Editor window, updated the release.txt file, removed some un-needed header includes from several files. --- VirtualT.suo | Bin 347648 -> 336896 bytes VirtualT.vcproj | 12 +- release.txt | 9 + src/FLU/Flu_Tree_Browser.h | 8 +- src/cpuregs.cpp | 43 +- src/display.cpp | 25 +- src/ide.cpp | 9 - src/memedit.cpp | 846 +++++++++++++--- src/memedit.h | 30 +- src/memory.c | 4 +- src/memory.h | 2 +- src/setup.cpp | 18 +- src/watchtable.cpp | 1942 ++++++++++++++++++++++++++++++++++++ src/watchtable.h | 188 ++++ 14 files changed, 2946 insertions(+), 190 deletions(-) create mode 100644 src/watchtable.cpp create mode 100644 src/watchtable.h diff --git a/VirtualT.suo b/VirtualT.suo index 20a4c4f86dd3eafd787314c6ae109e516a534242..6ebd76867fa96ddbde8f7a76defcbe6c0d5baf3d 100644 GIT binary patch delta 92115 zcmbTf2b>jEw#Hj^&grIs1{!E+qzR`3(Bzy`HyI>@nVckN5D++EPAFJFjfp|UoIq4C zgJ4cD#xY_T!Z`Rw?b^9^)md|GjWy5YZa)xnr+Wuu zT@!yCJ$ls3iLZC(de_IFud@B9d+o}KFS&6?@=nYt`yS~|*m zGILh$XrZCfQz|;naJh>!9LMWZZh9;;?%iE(P{w+3&Ai{sJ?*XkB5^`39i8cna%MPl z<<54d3NO~*`ToJ_@#;GdXAO7#KJO)3D-h?iI^K#3L*2X}y_sBDE5|!hVPK{k6Rwb^ z^92uOdMhdp%ybgMS$1_5N4w?IaB=o9uXkSeD=YQMP@WyF9I*bO>G6bnrMJA&*%_PV zZN<)CDqZ7tEOUB0{hYo|2d9%rvSGe6%$elO6gwkGZgZ!HGshV(o`f%SMmrOoN!|xl z>U&>S$xX$aOs9h5D&t9RJt^|y9qp=p^T*dm;cMvl1ZkbW@MKI&DH63W)^U4j@-KX@ zj_XU2WA-~&<^1Gkj#u`4l)WE6wc`Z|$`5 z&d%+7<@9#t$@0ol*RR?*F(l)ZPB#s8@LJuk^KCrKn^~i#JIyPbROVeYsmGNye~uN# zb{?sj>3UC1T5;o=$*#9%?wXj&)FALp`^>|7v$Pr|NVabH@DE z4x#PBj`j?$o%AHB6I=nAJ4>0{(Vd+x7RwqxAIo&f&Zg=5<;kK#uD@bJqM^67*|rP{ z-G<=Q&c)4ZyNNcf%363ibL;H9yTyDr@zpOyW4*#wea|HW|6iD7K`E2E3J&VoMtgw>aYCy-|0(<{fyll~>xj)GM4(>W}Q^PT5)9<`Q?r z>9WO~@_Gh9GQ~Jrs;S1!HjdV1j&VzkqfF@dI$S8FWxQ0roC4_tDRRFQ4tYR|-9u8iZqkSSs;$A6)oTdmSkS|AB-b?W7b{dBZYxv@w!YlYn7^>5jq>f7=^9iv@%)uo!S_D2D3Zm$R}qyBRq_qg_O+v_$Ptx&bIT*6vU-CXzDs`sy5Z?&;nu z)_R@7XfEb*xm*>ucb+wRj~Ykk`j{~Cve&kBU5_?dX=@B`5T<jo5u- zcHd_CJu0}pyblkx%0DYe#wsA7kaMelSI^RbO51Zl75$+e`em9OW)E~yh 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 delta 103536 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 - - @@ -1094,6 +1090,10 @@ RelativePath=".\src\vtpaper.cpp" > + + + + diff --git a/release.txt b/release.txt index 3ba3287..d2712f8 100644 --- a/release.txt +++ b/release.txt @@ -42,6 +42,15 @@ v1.6 11. Updated REX emulation to support REX3 for PC8201 state machine changes. +12. Created a Watch Variables Widget and added it to the Memory Editor Window. This + will also be used in the IDE debugger. + +13. Added options to Memory Editor Window to use black background with color coded text + and the ability to set the font size. + +14. Started converting the preferences file to use preference groups to help organize + the growing list of entries in the file. + ==================== v1.5 July 9th, 2011 ==================== diff --git a/src/FLU/Flu_Tree_Browser.h b/src/FLU/Flu_Tree_Browser.h index c21a18f..616dc08 100644 --- a/src/FLU/Flu_Tree_Browser.h +++ b/src/FLU/Flu_Tree_Browser.h @@ -196,8 +196,8 @@ class FLU_EXPORT Flu_Tree_Browser : public Fl_Double_Window { _box->color( c ); } //! Set the background color of the browser. Default is FL_WHITE - inline void color( unsigned c ) - { _box->color( (Fl_Color)c ); } +// inline void color( unsigned c ) +// { _box->color( (Fl_Color)c ); } //! Set the color, style, and width of the connector lines. Default is FL_DARK2, FL_DOT, 1 inline void connector_style( Fl_Color color, int style, int width = 1 ) @@ -457,8 +457,8 @@ class FLU_EXPORT Flu_Tree_Browser : public Fl_Double_Window { rdata.defSelectionColor = c; } //! Set the color to use when hilighting selected entries. Default is FL_SELECTION_COLOR - inline void selection_color( unsigned c ) - { selection_color( (Fl_Color)c ); } +// inline void selection_color( unsigned c ) +// { selection_color( (Fl_Color)c ); } //! Set how selection is affected when the mouse is dragged. This can be one of FLU_DRAG_IGNORE, FLU_DRAG_TO_SELECT, FLU_DRAG_TO_MOVE. Default is FLU_DRAG_TO_SELECT. inline void selection_drag_mode( int m ) diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index faa0c3d..0a9e0f1 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -72,17 +72,21 @@ extern Fl_Window* gmew; // Global Memory Edit Window extern "C" { extern volatile UINT64 cycles; +void memory_monitor_cb(void); } // Menu item callback definitions static void cb_save_trace(Fl_Widget* w, void*); static void cb_clear_trace(Fl_Widget* w, void*); -static void cb_menu_run(Fl_Widget* w, void*); -static void cb_menu_stop(Fl_Widget* w, void*); -static void cb_menu_step(Fl_Widget* w, void*); -static void cb_menu_step_over(Fl_Widget* w, void*); +void cb_menu_run(Fl_Widget* w, void*); +void cb_menu_stop(Fl_Widget* w, void*); +void cb_menu_step(Fl_Widget* w, void*); +void cb_menu_step_over(Fl_Widget* w, void*); static void cb_setup_trace(Fl_Widget* w, void*); +void cb_goto_next_marker(Fl_Widget* w, void*); +void cb_goto_prev_marker(Fl_Widget* w, void*); + // Other prototypes void debug_cpuregs_cb (int); void cb_Ide(Fl_Widget* w, void*) ; @@ -1086,7 +1090,7 @@ void debug_cpuregs_cb (int reason) if (reason == DEBUG_CPU_STEP) { if (gmew != NULL) - gmew->redraw(); + memory_monitor_cb(); return; } @@ -1112,7 +1116,7 @@ void debug_cpuregs_cb (int reason) // Ensure the memory window is refreshed if it's open if (gmew != NULL) - gmew->redraw(); + memory_monitor_cb(); } } } @@ -3313,6 +3317,17 @@ int VTCpuRegs::handle(int eventId) m_pBreak4->take_focus(); m_pBreak4->position(0, m_pBreak4->size()); } + else if (key == FL_F + 7) + { + // Find next / prev marker in memory editor + if (gmew != NULL) + { + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + cb_goto_prev_marker(NULL, NULL); + else + cb_goto_next_marker(NULL, NULL); + } + } break; @@ -3531,9 +3546,9 @@ void cb_clear_trace(Fl_Widget* w, void* pOpaque) Menu callback for run ============================================================================ */ -static void cb_menu_run(Fl_Widget* w, void* pOpaque) +void cb_menu_run(Fl_Widget* w, void* pOpaque) { - if (gStopped) + if (gcpuw && gStopped) cb_debug_run(w, gcpuw); } @@ -3542,9 +3557,9 @@ static void cb_menu_run(Fl_Widget* w, void* pOpaque) Menu callback for stop ============================================================================ */ -static void cb_menu_stop(Fl_Widget* w, void* pOpaque) +void cb_menu_stop(Fl_Widget* w, void* pOpaque) { - if (!gStopped) + if (gcpuw && !gStopped) cb_debug_stop(w, gcpuw); } @@ -3553,9 +3568,9 @@ static void cb_menu_stop(Fl_Widget* w, void* pOpaque) Menu callback for step ============================================================================ */ -static void cb_menu_step(Fl_Widget* w, void* pOpaque) +void cb_menu_step(Fl_Widget* w, void* pOpaque) { - if (gStopped) + if (gcpuw && gStopped) cb_debug_step(w, gcpuw); } @@ -3564,9 +3579,9 @@ static void cb_menu_step(Fl_Widget* w, void* pOpaque) Menu callback for step over ============================================================================ */ -static void cb_menu_step_over(Fl_Widget* w, void* pOpaque) +void cb_menu_step_over(Fl_Widget* w, void* pOpaque) { - if (gStopped) + if (gcpuw && gStopped) cb_debug_step_over(w, gcpuw); } diff --git a/src/display.cpp b/src/display.cpp index d06f677..50e9092 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -29,13 +29,10 @@ #include -#include -#include -#include #include -#include #include #include + //Added by J. VERNET for pref files // see also cb_xxxxxx #include @@ -43,6 +40,7 @@ #include "FLU/Flu_Button.h" #include "FLU/Flu_Return_Button.h" +#include "FLU/flu_pixmaps.h" #include #include @@ -87,6 +85,7 @@ extern int gOsDelay; extern int gInMsPlanROM; extern int gDelayUpdateKeys; void set_target_frequency(int freq); +void memory_monitor_cb(void); } void cb_Ide(Fl_Widget* w, void*) ; @@ -130,6 +129,7 @@ extern Fl_Menu_Item gPrintMenu[]; extern void Ide_SavePrefs(void); extern Fl_Pixmap gPrinterIcon; +extern Fl_Pixmap littlehome, little_desktop, little_favorites, ram_drive; extern VTCpuRegs* gcpuw; extern Fl_Window* gmew; extern VT_Ide * gpIde; @@ -138,9 +138,6 @@ void switch_model(int model); void key_delay(void); int remote_load_from_host(const char *filename); -#include "FLU/flu_pixmaps.h" -extern Fl_Pixmap littlehome, little_desktop, little_favorites, ram_drive; - #ifndef WIN32 #define min(a,b) ((a)<(b) ? (a):(b)) #endif @@ -150,7 +147,6 @@ extern Fl_Pixmap littlehome, little_desktop, little_favorites, ram_drive; #define VT_SPEED2_FREQ 20000000 #define VT_SPEED3_FREQ 50000000 - void setMonitorWindow(Fl_Window* pWin) { if (pWin == 0) @@ -227,7 +223,6 @@ const char *gSpKeyText[] = { "DOWN" }; - /* ======================================================= External Menu Item Callbacks @@ -716,7 +711,7 @@ void cb_coldBoot (Fl_Widget* w, void*) // Refresh the memory editor if it is opened if (gmew != NULL) - gmew->redraw(); + memory_monitor_cb(); } } @@ -1369,9 +1364,15 @@ void switch_model(int model) save_ram(); free_mem(); - // Save time for current model + /* Save time for current model */ save_model_time(); + /* Save memory editor region markers and watch variables */ + if (gmew != NULL) + { + MemoryEditor_SavePrefs(); + } + /* Switch to new model */ gModel = model; virtualt_prefs.set("Model",gModel); @@ -1381,6 +1382,8 @@ void switch_model(int model) /* Load Memory preferences */ load_memory_preferences(); init_mem(); + if (gmew != NULL) + MemoryEditor_LoadPrefs(); get_model_time(); gRomSize = 32768; diff --git a/src/ide.cpp b/src/ide.cpp index 313fe42..d311c01 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -28,17 +28,9 @@ */ #include -#include -#include -#include #include -#include -#include -#include -#include #include #include -#include #include "FLU/Flu_Tree_Browser.h" #include "FLU/flu_pixmaps.h" #include "FLU/Flu_File_Chooser.h" @@ -48,7 +40,6 @@ #include #include #include -#include #ifdef _WIN32 #include #endif diff --git a/src/memedit.cpp b/src/memedit.cpp index 5c50c66..c6b572b 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -28,18 +28,7 @@ */ #include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include #include #include "FLU/Flu_File_Chooser.h" @@ -49,7 +38,6 @@ #endif #include #include -#include #include "VirtualT.h" #include "m100emu.h" @@ -59,6 +47,7 @@ #include "cpu.h" #include "cpuregs.h" #include "fileview.h" +#include "watchtable.h" extern "C" { @@ -68,6 +57,10 @@ extern int gRamBottom; } void cb_Ide(Fl_Widget* w, void*); +void cb_menu_run(Fl_Widget* w, void*); +void cb_menu_stop(Fl_Widget* w, void*); +void cb_menu_step(Fl_Widget* w, void*); +void cb_menu_step_over(Fl_Widget* w, void*); /* ================================================================ @@ -78,7 +71,10 @@ typedef struct memedit_ctrl_struct { Fl_Menu_Bar* pMenu; + Fl_Double_Window* pTopPane; + Fl_Double_Window* pBottomPane; T100_MemEditor* pMemEdit; + VT_Watch_Table* pWatchTable; Fl_Scrollbar* pScroll; Fl_Input* pMemRange; Fl_Box* pRegionText; @@ -89,6 +85,12 @@ typedef struct memedit_ctrl_struct int sAddrStart; int sAddrEnd; int sAddrTop; + int iSplitH; + int iCol0W; + int iCol1W; + int iCol2W; + int iCol3W; + int iCol4W; } memedit_ctrl_t; typedef struct memedit_dialog @@ -165,8 +167,8 @@ Fl_Menu_Item gMemEdit_menuitems[] = { Fl_Menu_Item gAddMarkerMenu[] = { { " Create marker ", 0, cb_add_marker, 0 }, - { " Find next marker ", FL_F+2, cb_goto_next_marker, 0 }, - { " Find prev marker ", FL_SHIFT+FL_F+2, cb_goto_prev_marker, 0, FL_MENU_DIVIDER }, + { " Find next marker ", FL_F+7, cb_goto_next_marker, 0 }, + { " Find prev marker ", FL_SHIFT+FL_F+7, cb_goto_prev_marker, 0, FL_MENU_DIVIDER }, { " Delete all markers ", 0, cb_delete_all_markers, 0, 0 }, { 0, 0, cb_undo_delete_all_markers, 0, 0 }, { 0 } @@ -174,8 +176,8 @@ Fl_Menu_Item gAddMarkerMenu[] = { Fl_Menu_Item gDeleteMarkerMenu[] = { { " Delete Marker ", 0, cb_delete_marker, 0}, - { " Find next marker ", FL_F+2, cb_goto_next_marker, 0 }, - { " Find prev marker ", FL_SHIFT+FL_F+2, cb_goto_prev_marker, 0, FL_MENU_DIVIDER }, + { " Find next marker ", FL_F+7, cb_goto_next_marker, 0 }, + { " Find prev marker ", FL_SHIFT+FL_F+7, cb_goto_prev_marker, 0, FL_MENU_DIVIDER }, { " Delete All Markers ", 0, cb_delete_all_markers, 0, 0 }, { 0, 0, cb_undo_delete_all_markers, 0, 0 }, { 0 } @@ -183,7 +185,7 @@ Fl_Menu_Item gDeleteMarkerMenu[] = { /* ============================================================================ -Callback routine for the Peripherial Devices window +Callback routine for the memory editor window ============================================================================ */ void cb_memeditwin (Fl_Widget* w, void*) @@ -833,6 +835,9 @@ void memory_monitor_cb(void) { // Test if any currently displayed memory changed from last time memedit_ctrl.pMemEdit->UpdateDispMem(); + + // Update any visible watch variables too + memedit_ctrl.pWatchTable->UpdateTable(); } } @@ -858,26 +863,65 @@ void cb_MemEditScroll (Fl_Widget* w, void*) memedit_ctrl.pMemEdit->UpdateAddressText(); } +/* +============================================================================ +Callback routine to handle events from the WatchTable +============================================================================ +*/ +void cb_watch_events (int event, void* pOpaque) +{ + switch (event) + { + case WATCH_EVENT_VAL_CHANGED: + memedit_ctrl.pMemEdit->UpdateDispMem(); + break; + + case FL_F + 2: + case FL_F + 7: + // Helper key to find next / prev marker + if (Fl::get_key(FL_Shift_R) || Fl::get_key(FL_Shift_L)) + memedit_ctrl.pMemEdit->FindPrevMarker(); + else + memedit_ctrl.pMemEdit->FindNextMarker(); + break; + + case FL_F + 10: + cb_menu_step_over(NULL, NULL); + break; + case FL_F + 8: + cb_menu_step(NULL, NULL); + break; + case FL_F + 5: + cb_menu_run(NULL, NULL); + break; + case FL_F + 6: + cb_menu_stop(NULL, NULL); + break; + } +} + /* ============================================================================ Routine to create the MemoryEditor Window ============================================================================ */ -void cb_MemoryEditor (Fl_Widget* w, void*) +void cb_MemoryEditor (Fl_Widget* pW, void*) { Fl_Box* o; + int h = 400; + int w = 585; + const int wh = 50; if (gmew != NULL) return; // Create Peripheral Setup window #ifdef WIN32 - gmew = new T100_MemEditWin(0, 0, 585, 400, "Memory Editor"); -// gmew = new Fl_Double_Window(585, 400, "Memory Editor"); + gmew = new Fl_Double_Window(w, h+wh, "Memory Editor"); // Create a menu for the new window. - memedit_ctrl.pMenu = new Fl_Menu_Bar(0, 0, 585, MENU_HEIGHT-2); + memedit_ctrl.pMenu = new Fl_Menu_Bar(0, 0, w, MENU_HEIGHT-2); #else - gmew = new Fl_Window(735, 400, "Memory Editor"); + gmew = new Fl_Window(735, h+wh, "Memory Editor"); // Create a menu for the new window. memedit_ctrl.pMenu = new Fl_Menu_Bar(0, 0, 735, MENU_HEIGHT-2); #endif @@ -885,27 +929,40 @@ void cb_MemoryEditor (Fl_Widget* w, void*) gmew->callback(cb_memeditwin); memedit_ctrl.pMenu->menu(gMemEdit_menuitems); + // Create a tiled window to support Project, Edit, and debug regions + Fl_Tile* tile = new Fl_Tile(0,MENU_HEIGHT,w,h+wh-MENU_HEIGHT-3); + + memedit_ctrl.pTopPane = new Fl_Double_Window(0, MENU_HEIGHT, w, h-MENU_HEIGHT, ""); + + Fl_Group* g = new Fl_Group(0, 10, w, 25, ""); + // Create static text boxes - o = new Fl_Box(FL_NO_BOX, 10, 10+MENU_HEIGHT, 50, 15, "Region"); + o = new Fl_Box(FL_NO_BOX, 10, 10/*+MENU_HEIGHT*/, 50, 15, "Region"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - o = new Fl_Box(FL_NO_BOX, 175, 10+MENU_HEIGHT, 50, 15, "Address"); + o = new Fl_Box(FL_NO_BOX, 175, 10/*+MENU_HEIGHT*/, 50, 15, "Address"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); // Create Region choice box - memedit_ctrl.pRegion = new Fl_Choice(70, 8+MENU_HEIGHT, 100, 20, ""); + memedit_ctrl.pRegion = new Fl_Choice(70, 8/*+MENU_HEIGHT*/, 100, 20, ""); memedit_ctrl.pRegion->callback(cb_region); // Create edit field for memory search / display field - memedit_ctrl.pMemRange = new Fl_Input(235, 8+MENU_HEIGHT, 80, 20, ""); + memedit_ctrl.pMemRange = new Fl_Input(235, 8/*+MENU_HEIGHT*/, 80, 20, ""); memedit_ctrl.pMemRange->callback(cb_memory_range); memedit_ctrl.pMemRange->when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED); + // Create a resize box for the group and end the group + o = new Fl_Box(w-15, 10, 5, 5, ""); + o->hide(); + g->resizable(o); + g->end(); + #ifdef WIN32 - memedit_ctrl.pMemEdit = new T100_MemEditor(10, 40+MENU_HEIGHT, 545, 350-MENU_HEIGHT); - memedit_ctrl.pScroll = new Fl_Scrollbar(555, 40+MENU_HEIGHT, 15, 350-MENU_HEIGHT, ""); + memedit_ctrl.pMemEdit = new T100_MemEditor(10, 40/*+MENU_HEIGHT*/, 545, 350-MENU_HEIGHT+10); + memedit_ctrl.pScroll = new Fl_Scrollbar(555, 40/*+MENU_HEIGHT*/, 15, 350-MENU_HEIGHT+10, ""); #else - memedit_ctrl.pMemEdit = new T100_MemEditor(10, 40+MENU_HEIGHT, 695, 350-MENU_HEIGHT); - memedit_ctrl.pScroll = new Fl_Scrollbar(705, 40+MENU_HEIGHT, 15, 350-MENU_HEIGHT, ""); + memedit_ctrl.pMemEdit = new T100_MemEditor(10, 40/*+MENU_HEIGHT*/, 695, 350-MENU_HEIGHT); + memedit_ctrl.pScroll = new Fl_Scrollbar(705, 40/*+MENU_HEIGHT*/, 15, 350-MENU_HEIGHT, ""); #endif memedit_ctrl.pScroll->type(FL_VERTICAL); @@ -914,10 +971,61 @@ void cb_MemoryEditor (Fl_Widget* w, void*) memedit_ctrl.pScroll->callback(cb_MemEditScroll); memedit_ctrl.pScroll->slider_size(1); - - // Make things resizeable + // Make the menu and edit widget resizeable with the top tile window + memedit_ctrl.pTopPane->resizable(memedit_ctrl.pMemEdit); + memedit_ctrl.pTopPane->end(); + + // Create a window for the watches + memedit_ctrl.pBottomPane = new Fl_Double_Window(0, h, w, wh, ""); + + g = new Fl_Group(0, 0, w, wh, ""); + Fl_Box* b = new Fl_Box(FL_DOWN_FRAME, 9, 2, w-22, wh-5, ""); + + memedit_ctrl.pWatchTable = new VT_Watch_Table(12, 4, w-27, wh-9); + memedit_ctrl.pWatchTable->header_color(fl_rgb_color(253, 252, 251)); + memedit_ctrl.pWatchTable->EventHandler(cb_watch_events); + +#if 0 + MString name = "test_data0"; + MString addr = "0x8003"; + memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); + name = "test_data1"; + memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); + name = "test_data2"; + memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); + name = "test_data3"; + memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); + name = "test_data4"; + memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); + name = "test_data5"; + memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); + name = "test_data6"; + memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); + name = "test_data7"; + memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); + name = "test_data8"; + memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); +#endif + // make the window resizable + b = new Fl_Box(FL_NO_BOX, 12, wh-9, 5, 3, ""); + b->hide(); + g->resizable(b); + g->end(); + + + memedit_ctrl.pBottomPane->resizable(g); + memedit_ctrl.pBottomPane->end(); + + // Make the tile resizable + b = new Fl_Box(10, 0, w-40, h,""); + b->hide(); + tile->resizable(b); + tile->end(); + + // Make the window resizable gmew->resizable(memedit_ctrl.pMenu); - gmew->resizable(memedit_ctrl.pMemEdit); + gmew->resizable(tile); + gmew->end(); memedit_ctrl.pMemEdit->SetScrollSize(); @@ -943,6 +1051,37 @@ void cb_MemoryEditor (Fl_Widget* w, void*) } gmew->show(); + + // Resize top pane if user preference has been set + if (memedit_ctrl.iSplitH != -1) + { + if (memedit_ctrl.iSplitH < 64) + memedit_ctrl.iSplitH = 64; + memedit_ctrl.pTopPane->resize(memedit_ctrl.pTopPane->x(), memedit_ctrl.pTopPane->y(), + memedit_ctrl.pTopPane->w(), memedit_ctrl.iSplitH); + memedit_ctrl.pBottomPane->resize(memedit_ctrl.pBottomPane->x(), + memedit_ctrl.pTopPane->y()+memedit_ctrl.iSplitH, memedit_ctrl.pBottomPane->w(), + tile->h()-memedit_ctrl.iSplitH ); + } + else + { + memedit_ctrl.pTopPane->resize(memedit_ctrl.pTopPane->x(), + memedit_ctrl.pTopPane->y(), memedit_ctrl.pTopPane->w(), + memedit_ctrl.pTopPane->h()-20); + memedit_ctrl.pBottomPane->resize(memedit_ctrl.pBottomPane->x(), + memedit_ctrl.pBottomPane->y()-20, memedit_ctrl.pBottomPane->w(), + memedit_ctrl.pBottomPane->h()+20); + } + + // Resize the column headers if user preferences have been set + if (memedit_ctrl.iCol0W != -1) + { + memedit_ctrl.pWatchTable->HeaderBoxWidth(0, memedit_ctrl.iCol0W); + memedit_ctrl.pWatchTable->HeaderBoxWidth(1, memedit_ctrl.iCol1W); + memedit_ctrl.pWatchTable->HeaderBoxWidth(2, memedit_ctrl.iCol2W); + memedit_ctrl.pWatchTable->HeaderBoxWidth(3, memedit_ctrl.iCol3W); + memedit_ctrl.pWatchTable->HeaderBoxWidth(4, memedit_ctrl.iCol4W); + } } /* @@ -967,17 +1106,44 @@ void cb_MemoryEditorUpdate(void) // Update Region ENUM memedit_ctrl.pMemEdit->GetRegionEnum(); + memedit_ctrl.pMemEdit->LoadRegionMarkers(); + // Redraw the memory editor memedit_ctrl.pMemEdit->redraw(); } void cb_popup(Fl_Widget* w, void*) { + // Test if we need to cancel the selection + memedit_ctrl.pMemEdit->ClearSelection(); + memedit_ctrl.pMemEdit->redraw(); } -T100_MemEditWin::T100_MemEditWin(int x, int y, int w, int h, const char *title) : - Fl_Double_Window(w,h, title) +void T100_MemEditor::resize(int x, int y, int w, int h) { + int size; + + // Do the default resize stuff + Fl_Widget::resize(x, y, w, h); + + // Now check if the cursor is out of bounds + size = h / (int) m_Height; + if (m_CursorRow >= size) + { + window()->make_current(); + EraseCursor(); + m_CursorRow = size-1; + DrawCursor(); + } + if (memedit_ctrl.pScroll != NULL) + { + if (memedit_ctrl.pScroll->value() + size > m_Max) + { + memedit_ctrl.pScroll->value((int) (m_Max - size), 1, 0, (int) m_Max); + SetScrollSize(); + redraw(); + } + } } /* @@ -1013,6 +1179,7 @@ T100_MemEditor::T100_MemEditor(int x, int y, int w, int h) : m_ColorSyntaxHilight = 0; m_Font = FL_COURIER; m_PopupActive = FALSE; + m_Region = 0; #ifdef WIN32 m_FontSize = 12; #else @@ -1333,8 +1500,12 @@ void T100_MemEditor::UpdateDispMem(void) fl_font(m_Font, m_FontSize); linesVisible = (int) (memedit_ctrl.pScroll->h() / m_Height); + // Clip any drawing + fl_push_clip(x(), y(), w(), h()); + // Check for changes for (c = 0; c < count; c++) + { if (mem[c] != gDispMemory[c]) { int addr = m_FirstAddress + c; @@ -1367,9 +1538,15 @@ void T100_MemEditor::UpdateDispMem(void) selWidth = 2; if (!IsHilighted(addr+c+1)) selWidth = 2; - fl_color(m_colors.hilight_background); + if (IsSelected(addr)) + fl_color(m_colors.select_background); + else + fl_color(m_colors.hilight_background); fl_rectf(xpos, ypos+2-(int) m_Height, (int) m_Width * selWidth, (int) m_Height); - fl_color(m_colors.hilight); + if (IsSelected(addr)) + fl_color(m_colors.select); + else + fl_color(m_colors.hilight); fl_draw(string, xpos, ypos-2); fl_color(m_colors.number); } @@ -1395,7 +1572,12 @@ void T100_MemEditor::UpdateDispMem(void) if (!(actualAddr+16 >= ROMSIZE && actualAddr+16 < gRamBottom)) { if (IsHilighted(addr+16)) - fl_color(m_colors.hilight_background); + { + if (IsSelected(addr+16)) + fl_color(m_colors.select_background); + else + fl_color(m_colors.hilight_background); + } } // Draw spill over region only if not on bottom line @@ -1412,9 +1594,15 @@ void T100_MemEditor::UpdateDispMem(void) // Draw as marker / selection? else if (IsHilighted(addr)) { - fl_color(m_colors.hilight_background); + if (IsSelected(addr)) + fl_color(m_colors.select_background); + else + fl_color(m_colors.hilight_background); fl_rectf(xpos, ypos+2-(int) m_Height, (int) m_Width, (int) m_Height); - fl_color(m_colors.hilight); + if (IsSelected(addr)) + fl_color(m_colors.select); + else + fl_color(m_colors.hilight); fl_draw(string, xpos, ypos-2); fl_color(m_colors.number); } @@ -1427,9 +1615,13 @@ void T100_MemEditor::UpdateDispMem(void) // Set modified flag modified = 1; } + } if (modified) DrawCursor(); + + // Pop the clippping region + fl_pop_clip(); } /* @@ -1465,6 +1657,7 @@ void T100_MemEditor::draw() // Draw white background fl_color(m_colors.background); fl_rectf(x(),y(),w(),h()); + fl_push_clip(x(), y(), w(), h()); line = 0; max = (int) m_Max * 16; // Calc maximum address @@ -1538,9 +1731,18 @@ void T100_MemEditor::draw() selWidth = 2; if (!IsHilighted(addr+c+1)) selWidth = 2; - fl_color(m_colors.hilight_background); - fl_rectf(xpos, ypos+2-(int) m_Height, (int) m_Width * selWidth, (int) m_Height); - fl_color(m_colors.hilight); + if (IsSelected(addr+c)) + { + fl_color(m_colors.select_background); + fl_rectf(xpos, ypos+2-(int) m_Height, (int) m_Width * selWidth, (int) m_Height); + fl_color(m_colors.select); + } + else + { + fl_color(m_colors.hilight_background); + fl_rectf(xpos, ypos+2-(int) m_Height, (int) m_Width * selWidth, (int) m_Height); + fl_color(m_colors.hilight); + } fl_draw(string, xpos, ypos-2); fl_color(m_colors.number); } @@ -1578,9 +1780,18 @@ void T100_MemEditor::draw() // Draw selection box else if (IsHilighted(addr + c)) { - fl_color(m_colors.hilight_background); - fl_rectf(xpos, ypos+2-(int) m_Height, (int) m_Width, (int) m_Height); - fl_color(m_colors.hilight); + if (IsSelected(addr+c)) + { + fl_color(m_colors.select_background); + fl_rectf(xpos, ypos+2-(int) m_Height, (int) m_Width, (int) m_Height); + fl_color(m_colors.select); + } + else + { + fl_color(m_colors.hilight_background); + fl_rectf(xpos, ypos+2-(int) m_Height, (int) m_Width, (int) m_Height); + fl_color(m_colors.hilight); + } fl_draw(string, xpos, ypos-2); fl_color(m_colors.ascii); } @@ -1598,6 +1809,9 @@ void T100_MemEditor::draw() if (m_MyFocus) DrawCursor(); + + // Pop the clipping rect + fl_pop_clip(); } /* @@ -1614,7 +1828,7 @@ int T100_MemEditor::handle(int event) int height, size; int value; unsigned int key; - int first, address; + int first, address, prevAddress; unsigned char data; int xpos, ypos, actualAddr; char string[6]; @@ -1635,6 +1849,10 @@ int T100_MemEditor::handle(int event) // Determine line & col of mouse click col_click = (int) ((xp - x()) / m_Width); line_click = (int) ((yp - y()) / m_Height); + height = memedit_ctrl.pScroll->h(); + size = (int) (height / m_Height); + if (line_click >= size) + line_click--; // Constrain Column base on geometry if (col_click < 9) @@ -1651,6 +1869,9 @@ int T100_MemEditor::handle(int event) col_click = 74; } + // Save current cursor address in case the selection changes + prevAddress = m_CursorAddress; + switch (event) { case FL_FOCUS: @@ -1716,7 +1937,7 @@ int T100_MemEditor::handle(int event) // Test for an active selection. If no active selection, then // create one. if (m_SelStartAddr == -1) - m_SelStartAddr = m_CursorAddr; + m_SelStartAddr = m_CursorAddress; // Calculate the address of the new x,y location and set it as // the selection end address. @@ -1812,7 +2033,7 @@ int T100_MemEditor::handle(int event) address += col; // Save this address for future use - m_CursorAddr = address; + m_CursorAddress = address; // Process as a double click if the coords are the same if ((xp == m_DblclkX && yp == m_DblclkY) || shift) @@ -1929,8 +2150,10 @@ int T100_MemEditor::handle(int event) Fl_Widget *mb = m_pPopupMenu; const Fl_Menu_Item* m; Fl::watch_widget_pointer(mb); - m = m_pPopupMenu->menu()->popup(Fl::event_x(), Fl::event_y()+10, NULL, 0, m_pPopupMenu); + m = m_pPopupMenu->menu()->popup(Fl::event_x(), y()+(line_click+1)*(int)m_Height+3, NULL, 0, m_pPopupMenu); m_pPopupMenu->picked(m); + if (m == NULL) + cb_popup(NULL, NULL); Fl::release_widget_pointer(mb); } break; @@ -1953,6 +2176,19 @@ int T100_MemEditor::handle(int event) switch (key) { + case FL_F + 10: + cb_menu_step_over(NULL, NULL); + break; + case FL_F + 8: + cb_menu_step(NULL, NULL); + break; + case FL_F + 5: + cb_menu_run(NULL, NULL); + break; + case FL_F + 6: + cb_menu_stop(NULL, NULL); + break; + case FL_F+7: case FL_F+2: // Calculate the address associated with the click if (m_CursorCol >= 59) @@ -2440,6 +2676,7 @@ int T100_MemEditor::handle(int event) { data = 0; set_memory8_ext(m_Region, address, 1, &data); + gDispMemory[actualAddr] = data; } // Determine value of keystroke (convert from HEX) @@ -2456,6 +2693,7 @@ int T100_MemEditor::handle(int event) // Write new value to memory set_memory8_ext(m_Region, address, 1, &data); + gDispMemory[actualAddr] = data; // Display new text // Select 12 point Courier font @@ -2474,7 +2712,12 @@ int T100_MemEditor::handle(int event) if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) fl_color(m_colors.background); else if (IsHilighted(address)) - fl_color(m_colors.hilight_background); + { + if (IsSelected(address)) + fl_color(m_colors.select_background); + else + fl_color(m_colors.hilight_background); + } else fl_color(m_colors.background); fl_rectf(xpos, ypos+2 - (int) m_Height, (int) m_Width*2, (int) m_Height-2); @@ -2483,7 +2726,12 @@ int T100_MemEditor::handle(int event) if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) fl_color(fl_darker(FL_GRAY)); else if (IsHilighted(address)) - fl_color(m_colors.hilight); + { + if (IsSelected(address)) + fl_color(m_colors.select); + else + fl_color(m_colors.hilight); + } else fl_color(m_colors.number); fl_draw(string, xpos, ypos-2); @@ -2499,7 +2747,12 @@ int T100_MemEditor::handle(int event) if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) fl_color(m_colors.background); else if (IsHilighted(address)) - fl_color(m_colors.hilight_background); + { + if (IsSelected(address)) + fl_color(m_colors.select_background); + else + fl_color(m_colors.hilight_background); + } else fl_color(m_colors.background); fl_rectf(xpos, ypos+2 - (int) m_Height, (int) m_Width, (int) m_Height); @@ -2508,7 +2761,12 @@ int T100_MemEditor::handle(int event) if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) fl_color(fl_darker(FL_GRAY)); else if (IsHilighted(address)) - fl_color(m_colors.hilight); + { + if (IsSelected(address)) + fl_color(m_colors.select); + else + fl_color(m_colors.hilight); + } else fl_color(m_colors.ascii); fl_draw(string, xpos, ypos-2); @@ -2603,7 +2861,12 @@ int T100_MemEditor::handle(int event) if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) fl_color(m_colors.background); else if (IsHilighted(address)) - fl_color(m_colors.hilight_background); + { + if (IsSelected(address)) + fl_color(m_colors.select_background); + else + fl_color(m_colors.hilight_background); + } else fl_color(m_colors.background); fl_rectf(xpos, ypos+2 - (int) m_Height, (int) m_Width*2, (int) m_Height-2); @@ -2613,7 +2876,12 @@ int T100_MemEditor::handle(int event) if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) fl_color(fl_darker(FL_GRAY)); else if (IsHilighted(address)) - fl_color(m_colors.hilight); + { + if (IsSelected(address)) + fl_color(m_colors.select); + else + fl_color(m_colors.hilight); + } else fl_color(m_colors.number); fl_draw(string, xpos, ypos-2); @@ -2629,7 +2897,12 @@ int T100_MemEditor::handle(int event) if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) fl_color(m_colors.background); else if (IsHilighted(address)) - fl_color(m_colors.hilight_background); + { + if (IsSelected(address)) + fl_color(m_colors.select_background); + else + fl_color(m_colors.hilight_background); + } else fl_color(m_colors.background); fl_rectf(xpos, ypos+2 - (int) m_Height, (int) m_Width, (int) m_Height); @@ -2638,7 +2911,12 @@ int T100_MemEditor::handle(int event) if (actualAddr >= ROMSIZE && actualAddr < gRamBottom) fl_color(fl_darker(FL_GRAY)); else if (IsHilighted(address)) - fl_color(m_colors.hilight); + { + if (IsSelected(address)) + fl_color(m_colors.select); + else + fl_color(m_colors.hilight); + } else fl_color(m_colors.ascii); fl_draw(string, xpos, ypos-2); @@ -2685,6 +2963,9 @@ int T100_MemEditor::handle(int event) } } + // Update the Watch window + memedit_ctrl.pWatchTable->UpdateTable(); + break; } @@ -2699,6 +2980,24 @@ int T100_MemEditor::handle(int event) } + // Calculate the address associated with the click + if (m_CursorCol >= 59) + col = m_CursorCol - 59; + else if (m_CursorCol > 8+8*3) + col = (int) ((m_CursorCol-10) / 3); + else + col = (int) ((m_CursorCol-9) / 3); + + m_CursorAddress = memedit_ctrl.pScroll->value() * 16; + m_CursorAddress += m_CursorRow * 16; + m_CursorAddress += col; + + // Test if our a marker selection changed + memedit_marker_t* pOldSel = GetMarker(prevAddress); + memedit_marker_t* pNewSel = GetMarker(m_CursorAddress); + if (pOldSel != pNewSel) + redraw(); + return 1; } @@ -2754,7 +3053,7 @@ MoveTo: This function moves to the specified line void T100_MemEditor::MoveTo(int address) { int height, size, value, col; - int curVal; + int curVal, moveToVal; /* If the range selected is RAM, then we need to subtract the ROM size from the address so we jump to the right @@ -2778,12 +3077,13 @@ void T100_MemEditor::MoveTo(int address) size = (int) (height / m_Height); // Test if at bottom and scrolling down + moveToVal = value; if (value > m_Max - size) - value = (int) (m_Max - size); + moveToVal = (int) (m_Max - size); // Update new value base on scroll distance requested - if (value < 0) - value = 0; + if (moveToVal < 0) + moveToVal = 0; // Selet the selection region to hilight this location m_SelStartAddr = address; @@ -2794,7 +3094,7 @@ void T100_MemEditor::MoveTo(int address) if (!(value >= curVal && value < curVal+size)) { // Update scroll bar - memedit_ctrl.pScroll->value(value, 1, 0, (int) m_Max); + memedit_ctrl.pScroll->value(moveToVal, 1, 0, (int) m_Max); memedit_ctrl.pScroll->maximum(m_Max-size); memedit_ctrl.pScroll->step(size / m_Max); memedit_ctrl.pScroll->slider_size(size/m_Max); @@ -2809,6 +3109,7 @@ void T100_MemEditor::MoveTo(int address) m_CursorCol = 59 + col; else m_CursorCol = 9 + col * 3 + (col > 7 ? 1 : 0); + m_CursorAddress = address; redraw(); } @@ -2880,6 +3181,10 @@ void T100_MemEditor::EraseCursor() { int x_pos, y_pos, address, col; + // Clip the drawing + window()->make_current(); + fl_push_clip(x(), y(), w(), h()); + // Erase current cursor fl_color(m_colors.background); if (m_CursorRow != -1) @@ -2911,7 +3216,10 @@ void T100_MemEditor::EraseCursor() if (IsHilighted(address)) { // Select the hilight background color - fl_color(m_colors.hilight_background); + if (IsSelected(address)) + fl_color(m_colors.select_background); + else + fl_color(m_colors.hilight_background); fl_line(x_pos, y_pos+2, x_pos, y_pos + (int) m_Height); // If we aren't on col zero, then test the next lower address too @@ -2920,12 +3228,18 @@ void T100_MemEditor::EraseCursor() if (IsHilighted(address-1)) { // Select the hilight background color - fl_color(m_colors.hilight_background); + if (IsSelected(address-1)) + fl_color(m_colors.select_background); + else + fl_color(m_colors.hilight_background); fl_line(x_pos-1, y_pos+2, x_pos-1, y_pos+(int)m_Height); } } } } + + // Pop the clipping rect + fl_pop_clip(); } /* @@ -2940,6 +3254,10 @@ void T100_MemEditor::DrawCursor() if (!m_MyFocus) return; + // Clip the drawing + window()->make_current(); + fl_push_clip(x(), y(), w(), h()); + // Draw new cursor fl_color(m_colors.cursor); if (m_CursorRow != -1) @@ -2951,6 +3269,8 @@ void T100_MemEditor::DrawCursor() } UpdateAddressText(); + + fl_pop_clip(); } /* @@ -3014,31 +3334,107 @@ Load user preferences */ void MemoryEditor_LoadPrefs(void) { - int temp, bold; + int temp, bold, size; + char model[16]; + char* pVarText; + Fl_Preferences g(virtualt_prefs, "MemEdit_Group"); + + // Get main window geometry + g.get("x", memedit_ctrl.pMemEdit->m_x, -1); + g.get("y", memedit_ctrl.pMemEdit->m_y, -1); + g.get("w", memedit_ctrl.pMemEdit->m_w, -1); + g.get("h", memedit_ctrl.pMemEdit->m_h, -1); + + // Test for old style preferences + if (memedit_ctrl.pMemEdit->m_x == -1) + { + virtualt_prefs.get("MemEdit_x", memedit_ctrl.pMemEdit->m_x, -1); + virtualt_prefs.get("MemEdit_y", memedit_ctrl.pMemEdit->m_y, -1); + virtualt_prefs.get("MemEdit_w", memedit_ctrl.pMemEdit->m_w, -1); + virtualt_prefs.get("MemEdit_h", memedit_ctrl.pMemEdit->m_h, -1); + } - virtualt_prefs.get("MemEdit_x", memedit_ctrl.pMemEdit->m_x, -1); - virtualt_prefs.get("MemEdit_y", memedit_ctrl.pMemEdit->m_y, -1); - virtualt_prefs.get("MemEdit_w", memedit_ctrl.pMemEdit->m_w, -1); - virtualt_prefs.get("MemEdit_h", memedit_ctrl.pMemEdit->m_h, -1); + // Get watch window geometry + g.get("SplitH", memedit_ctrl.iSplitH, -1); + g.get("Col0_Width", memedit_ctrl.iCol0W, -1); + g.get("Col1_Width", memedit_ctrl.iCol1W, -1); + g.get("Col2_Width", memedit_ctrl.iCol2W, -1); + g.get("Col3_Width", memedit_ctrl.iCol3W, -1); + g.get("Col4_Width", memedit_ctrl.iCol4W, -1); + + // Test if we have saved to the group yet + g.get("FontSize", temp, -1); + if (temp == -1) + { + // We haven't saved to the group yet... use non-group entries + + // Get font settings + virtualt_prefs.get("MemEdit_FontSize", temp, 12); + virtualt_prefs.get("MemEdit_Bold", bold, 0); + memedit_ctrl.pMemEdit->SetFontSize(temp, bold); - // Get font settings - virtualt_prefs.get("MemEdit_FontSize", temp, -1); - virtualt_prefs.get("MemEdit_Bold", bold, 0); - if (temp != -1) + // Get color settings + virtualt_prefs.get("MemEdit_BlackBackground", temp, 1); + memedit_ctrl.pMemEdit->SetBlackBackground(temp); + virtualt_prefs.get("MemEdit_SyntaxHilight", temp, 1); + memedit_ctrl.pMemEdit->SetSyntaxHilight(temp); + virtualt_prefs.get("MemEdit_MarkerForegroundColor", temp, (int) FL_WHITE); + memedit_ctrl.pMemEdit->SetMarkerForegroundColor((Fl_Color) temp); + virtualt_prefs.get("MemEdit_MarkerBackgroundColor", temp, 226); + memedit_ctrl.pMemEdit->SetMarkerBackgroundColor((Fl_Color) temp); + virtualt_prefs.get("MemEdit_SelectedForegroundColor", temp, (int) FL_WHITE); + memedit_ctrl.pMemEdit->SetSelectedForegroundColor((Fl_Color) temp); + virtualt_prefs.get("MemEdit_SelectedBackgroundColor", temp, 81); + memedit_ctrl.pMemEdit->SetSelectedBackgroundColor((Fl_Color) temp); + } + else + { + // Get font settings + g.get("FontSize", temp, 12); + g.get("Bold", bold, 0); memedit_ctrl.pMemEdit->SetFontSize(temp, bold); - // Get color settings - virtualt_prefs.get("MemEdit_BlackBackground", temp, 1); - memedit_ctrl.pMemEdit->SetBlackBackground(temp); - virtualt_prefs.get("MemEdit_SyntaxHilight", temp, 1); - memedit_ctrl.pMemEdit->SetSyntaxHilight(temp); - virtualt_prefs.get("MemEdit_MarkerForegroundColor", temp, (int) FL_WHITE); - memedit_ctrl.pMemEdit->SetMarkerForegroundColor((Fl_Color) temp); - virtualt_prefs.get("MemEdit_MarkerBackgroundColor", temp, (int) fl_lighter(FL_RED)); - memedit_ctrl.pMemEdit->SetMarkerBackgroundColor((Fl_Color) temp); + // Get color settings + g.get("BlackBackground", temp, 1); + memedit_ctrl.pMemEdit->SetBlackBackground(temp); + g.get("SyntaxHilight", temp, 1); + memedit_ctrl.pMemEdit->SetSyntaxHilight(temp); + g.get("MarkerFgColor", temp, (int) FL_WHITE); + memedit_ctrl.pMemEdit->SetMarkerForegroundColor((Fl_Color) temp); + g.get("MarkerBgColor", temp, 226); + memedit_ctrl.pMemEdit->SetMarkerBackgroundColor((Fl_Color) temp); + g.get("SelectedFgColor", temp, (int) FL_WHITE); + memedit_ctrl.pMemEdit->SetSelectedForegroundColor((Fl_Color) temp); + g.get("SelectedBgColor", temp, 81); + memedit_ctrl.pMemEdit->SetSelectedBackgroundColor((Fl_Color) temp); + } // Load the region markers memedit_ctrl.pMemEdit->LoadRegionMarkers(); + + // Load the watch variables + memedit_ctrl.pWatchTable->ResetContent(); + get_model_string(model, gModel); + size = g.size(Fl_Preferences::Name("%s_WatchVars", model)); + if (size > 0) + { + // Allocate the buffer + pVarText = new char[size+1]; + if (pVarText != NULL) + { + // Get the watch variables string + g.get(Fl_Preferences::Name("%s_WatchVars", model), pVarText, "", size+1); + + // And give it to the watch table + memedit_ctrl.pWatchTable->WatchVarsString(pVarText); + + // Now delete the string + delete pVarText; + } + } + + // Redraw the watch table + memedit_ctrl.pWatchTable->redraw(); } /* @@ -3048,19 +3444,57 @@ Save user preferences */ void MemoryEditor_SavePrefs(void) { - virtualt_prefs.set("MemEdit_x", gmew->x()); - virtualt_prefs.set("MemEdit_y", gmew->y()); - virtualt_prefs.set("MemEdit_w", gmew->w()); - virtualt_prefs.set("MemEdit_h", gmew->h()); - virtualt_prefs.set("MemEdit_FontSize", memedit_ctrl.pMemEdit->GetFontSize()); - virtualt_prefs.set("MemEdit_Bold", memedit_ctrl.pMemEdit->GetBold()); - virtualt_prefs.set("MemEdit_BlackBackground", memedit_ctrl.pMemEdit->GetBlackBackground()); - virtualt_prefs.set("MemEdit_SyntaxHilight", memedit_ctrl.pMemEdit->GetSyntaxHilight()); - virtualt_prefs.set("MemEdit_MarkerForegroundColor", (int) memedit_ctrl.pMemEdit->GetMarkerForegroundColor()); - virtualt_prefs.set("MemEdit_MarkerBackgroundColor", (int) memedit_ctrl.pMemEdit->GetMarkerBackgroundColor()); + MString watch_vars, key; + char model[16]; + Fl_Preferences g(virtualt_prefs, "MemEdit_Group"); + + g.set("x", gmew->x()); + g.set("y", gmew->y()); + g.set("w", gmew->w()); + g.set("h", gmew->h()); + + // Save watch variable geometry + g.set("SplitH", memedit_ctrl.pTopPane->h()); + g.set("Col0_Width", memedit_ctrl.pWatchTable->HeaderBoxWidth(0)); + g.set("Col1_Width", memedit_ctrl.pWatchTable->HeaderBoxWidth(1)); + g.set("Col2_Width", memedit_ctrl.pWatchTable->HeaderBoxWidth(2)); + g.set("Col3_Width", memedit_ctrl.pWatchTable->HeaderBoxWidth(3)); + g.set("Col4_Width", memedit_ctrl.pWatchTable->HeaderBoxWidth(4)); + + g.set("FontSize", memedit_ctrl.pMemEdit->GetFontSize()); + g.set("Bold", memedit_ctrl.pMemEdit->GetBold()); + g.set("BlackBackground", memedit_ctrl.pMemEdit->GetBlackBackground()); + g.set("SyntaxHilight", memedit_ctrl.pMemEdit->GetSyntaxHilight()); + g.set("MarkerFgColor", (int) memedit_ctrl.pMemEdit->GetMarkerForegroundColor()); + g.set("MarkerBgColor", (int) memedit_ctrl.pMemEdit->GetMarkerBackgroundColor()); + g.set("SelectedFgColor", (int) memedit_ctrl.pMemEdit->GetSelectedForegroundColor()); + g.set("SelectedBgColor", (int) memedit_ctrl.pMemEdit->GetSelectedBackgroundColor()); // Save the region markers memedit_ctrl.pMemEdit->SaveRegionMarkers(); + + // Save watch variables + get_model_string(model, gModel); + watch_vars = memedit_ctrl.pWatchTable->WatchVarsString(); + g.set(Fl_Preferences::Name("%s_WatchVars", model), (const char *) watch_vars); + + // Delete old keys from the file + virtualt_prefs.deleteEntry("MemEdit_x"); + virtualt_prefs.deleteEntry("MemEdit_y"); + virtualt_prefs.deleteEntry("MemEdit_w"); + virtualt_prefs.deleteEntry("MemEdit_h"); + virtualt_prefs.deleteEntry("MemEdit_FontSize"); + virtualt_prefs.deleteEntry("MemEdit_Bold"); + virtualt_prefs.deleteEntry("MemEdit_BlackBackground"); + virtualt_prefs.deleteEntry("MemEdit_SyntaxHilight"); + virtualt_prefs.deleteEntry("MemEdit_MarkerForegroundColor"); + virtualt_prefs.deleteEntry("MemEdit_MarkerBackgroundColor"); + virtualt_prefs.deleteEntry("MemEdit_SelectedForegroundColor"); + virtualt_prefs.deleteEntry("MemEdit_SelectedBackgroundColor"); + + // Flush the preferences to disk in case we only closed the window + // or changed model, that way we are protected from a crash + virtualt_prefs.flush(); } /* @@ -3070,12 +3504,12 @@ Set's the memory editor's font size */ void T100_MemEditor::SaveRegionMarkers() { - char str[16], regStr[32]; + char str[16]; char markerText[32]; - char pref[64]; MString markers; int region; memedit_marker_t* pMarkers; + Fl_Preferences g(virtualt_prefs, "MemEdit_Group"); // Get the model string to save stuff per model get_model_string(str, gModel); @@ -3083,11 +3517,6 @@ void T100_MemEditor::SaveRegionMarkers() // Save region markers for (region = 0; region < REGION_MAX; region++) { - // Create region preference string - strcpy(pref, str); - sprintf(regStr, "_Region%d_Markers", region); - strcat(pref, regStr); - // Now build the region marker text markers = ""; @@ -3112,7 +3541,15 @@ void T100_MemEditor::SaveRegionMarkers() pMarkers = pMarkers->pNext; } - virtualt_prefs.set(pref, (const char *) markers); + // Test if we even need the setting in the preferences file + if (m_pRegionMarkers[region] == NULL) + g.deleteEntry(Fl_Preferences::Name("%s_Region%d_Markers", str, region)); + else + g.set(Fl_Preferences::Name("%s_Region%d_Markers", str, region), + (const char *) markers); + + // Clean up old style entries + virtualt_prefs.deleteEntry(Fl_Preferences::Name("%s_Region%d_Markers", str, region)); } } @@ -3123,10 +3560,11 @@ Set's the memory editor's font size */ void T100_MemEditor::LoadRegionMarkers() { - char str[16], regStr[32]; + char str[16]; char* pMarkerText; - char pref[64]; - int region, startAddr, endAddr, c; + int region, startAddr, endAddr, c, bufSize; + int size, which; + Fl_Preferences g(virtualt_prefs, "MemEdit_Group"); // First reset any old markers ResetMarkers(); @@ -3136,19 +3574,52 @@ void T100_MemEditor::LoadRegionMarkers() // Allocate a big buffer to read in marker text pMarkerText = new char[65536]; + bufSize = 65536; + // Only if we could allocate the buffer... if (pMarkerText != NULL) { - // Save region markers + // Loop for each region for (region = 0; region < REGION_MAX; region++) { - // Create region preference string - strcpy(pref, str); - sprintf(regStr, "_Region%d_Markers", region); - strcat(pref, regStr); + // Determine the size buffer needed + which = 0; + size = g.size(Fl_Preferences::Name("%s_Region%d_Markers", str, region)); + if (size == 0) + { + size = virtualt_prefs.size(Fl_Preferences::Name("%s_Region%d_Markers", + str, region)); + which = 1; + } + + // If no markers defined, skip to next region + if (size == 0) + continue; + + // Test if our buffer is big enough + if (size > bufSize) + { + // Allocate a bigger buffer + delete pMarkerText; + pMarkerText = new char[size]; + bufSize = size; + if (pMarkerText == NULL) + return; + } - // Get the text from preferences - virtualt_prefs.get(pref, pMarkerText, "", 65536); + // Now get the text + if (which == 0) + { + // Get it from the group + g.get(Fl_Preferences::Name("%s_Region%d_Markers", + str, region), pMarkerText, "", bufSize); + } + else + { + // Get the text from base preferences + virtualt_prefs.get(Fl_Preferences::Name("%s_Region%d_Markers", + str, region), pMarkerText, "", bufSize); + } // Check if any markers defined if (pMarkerText[0] != '\0') @@ -3309,10 +3780,14 @@ typedef struct memedit_setup_params Fl_Check_Button* pColorHilight; Fl_Button* pMarkerForeground; Fl_Button* pMarkerBackground; + Fl_Button* pSelectedForeground; + Fl_Button* pSelectedBackground; Fl_Button* pDefaults; char sFontSize[20]; Fl_Color origMarkerForeground; Fl_Color origMarkerBackground; + Fl_Color origSelectedForeground; + Fl_Color origSelectedBackground; } memedit_setup_params_t; /* @@ -3347,6 +3822,8 @@ static void cb_setupdlg_OK(Fl_Widget* w, void* pOpaque) // Get Marker colors memedit_ctrl.pMemEdit->SetMarkerForegroundColor((Fl_Color) p->pMarkerForeground->color()); memedit_ctrl.pMemEdit->SetMarkerBackgroundColor((Fl_Color) p->pMarkerBackground->color()); + memedit_ctrl.pMemEdit->SetSelectedForegroundColor((Fl_Color) p->pSelectedForeground->color()); + memedit_ctrl.pMemEdit->SetSelectedBackgroundColor((Fl_Color) p->pSelectedBackground->color()); // Redraw the window gmew->redraw(); @@ -3370,6 +3847,8 @@ static void cb_setupdlg_cancel(Fl_Widget* w, void* pOpaque) // Restore original marker colors and redraw memedit_ctrl.pMemEdit->SetMarkerForegroundColor(p->origMarkerForeground); memedit_ctrl.pMemEdit->SetMarkerBackgroundColor(p->origMarkerBackground); + memedit_ctrl.pMemEdit->SetSelectedForegroundColor(p->origSelectedForeground); + memedit_ctrl.pMemEdit->SetSelectedBackgroundColor(p->origSelectedBackground); memedit_ctrl.pMemEdit->redraw(); } @@ -3382,12 +3861,18 @@ static void cb_default_colors(Fl_Button*, void* pOpaque) { memedit_setup_params_t* p = (memedit_setup_params_t *) pOpaque; - p->pMarkerBackground->color(fl_lighter(FL_RED)); + p->pMarkerBackground->color((Fl_Color) 226); p->pMarkerForeground->color(FL_WHITE); + p->pSelectedBackground->color((Fl_Color) 81); + p->pSelectedForeground->color(FL_WHITE); p->pMarkerBackground->redraw(); p->pMarkerForeground->redraw(); + p->pSelectedBackground->redraw(); + p->pSelectedForeground->redraw(); memedit_ctrl.pMemEdit->SetMarkerForegroundColor(p->pMarkerForeground->color()); memedit_ctrl.pMemEdit->SetMarkerBackgroundColor(p->pMarkerBackground->color()); + memedit_ctrl.pMemEdit->SetSelectedForegroundColor(p->pSelectedForeground->color()); + memedit_ctrl.pMemEdit->SetSelectedBackgroundColor(p->pSelectedBackground->color()); memedit_ctrl.pMemEdit->redraw(); } @@ -3419,6 +3904,34 @@ static void cb_marker_background(Fl_Button*, void* pOpaque) memedit_ctrl.pMemEdit->redraw(); } +/* +============================================================================ +Callback for Selected Marker Foreground color button +============================================================================ +*/ +static void cb_selected_foreground(Fl_Button*, void* pOpaque) +{ + memedit_setup_params_t* p = (memedit_setup_params_t *) pOpaque; + + p->pSelectedForeground->color(fl_show_colormap(p->pSelectedForeground->color())); + memedit_ctrl.pMemEdit->SetSelectedForegroundColor(p->pSelectedForeground->color()); + memedit_ctrl.pMemEdit->redraw(); +} + +/* +============================================================================ +Callback for Selected Marker Background color button +============================================================================ +*/ +static void cb_selected_background(Fl_Button*, void* pOpaque) +{ + memedit_setup_params_t* p = (memedit_setup_params_t *) pOpaque; + + p->pSelectedBackground->color(fl_show_colormap(p->pSelectedBackground->color())); + memedit_ctrl.pMemEdit->SetSelectedBackgroundColor(p->pSelectedBackground->color()); + memedit_ctrl.pMemEdit->redraw(); +} + /* ============================================================================ Menu callback for setup memory editor @@ -3433,9 +3946,11 @@ void cb_setup_memedit(Fl_Widget* w, void* pOpaque) // Save current Marker colors p.origMarkerForeground = memedit_ctrl.pMemEdit->GetMarkerForegroundColor(); p.origMarkerBackground = memedit_ctrl.pMemEdit->GetMarkerBackgroundColor(); + p.origSelectedForeground = memedit_ctrl.pMemEdit->GetSelectedForegroundColor(); + p.origSelectedBackground = memedit_ctrl.pMemEdit->GetSelectedBackgroundColor(); // Create new window for memory editor configuration - pWin = new Fl_Window(300, 200, "Memory Editor Configuration"); + pWin = new Fl_Window(330, 240, "Memory Editor Configuration"); /* Create input field for font size */ b = new Fl_Box(20, 20, 100, 20, "Font Size"); @@ -3458,27 +3973,39 @@ void cb_setup_memedit(Fl_Widget* w, void* pOpaque) p.pColorHilight->value(memedit_ctrl.pMemEdit->GetSyntaxHilight()); /* Create a button for the marker foreground color */ - p.pMarkerForeground = new Fl_Button(20, 110, 15, 15, "Marker Forground Color"); + p.pMarkerForeground = new Fl_Button(22, 110, 15, 15, "Marker Forground Color"); p.pMarkerForeground->callback((Fl_Callback*) cb_marker_foreground, &p); p.pMarkerForeground->align(FL_ALIGN_RIGHT); p.pMarkerForeground->color(memedit_ctrl.pMemEdit->GetMarkerForegroundColor()); /* Create a button for the marker background color */ - p.pMarkerBackground = new Fl_Button(20, 130, 15, 15, "Marker background Color"); + p.pMarkerBackground = new Fl_Button(22, 130, 15, 15, "Marker Background Color"); p.pMarkerBackground->callback((Fl_Callback*) cb_marker_background, &p); p.pMarkerBackground->align(FL_ALIGN_RIGHT); p.pMarkerBackground->color(memedit_ctrl.pMemEdit->GetMarkerBackgroundColor()); - p.pDefaults = new Fl_Button(210, 115, 70, 30, "Default"); + /* Create a button for the marker foreground color */ + p.pSelectedForeground = new Fl_Button(22, 150, 15, 15, "Selected Marker Forground"); + p.pSelectedForeground->callback((Fl_Callback*) cb_selected_foreground, &p); + p.pSelectedForeground->align(FL_ALIGN_RIGHT); + p.pSelectedForeground->color(memedit_ctrl.pMemEdit->GetSelectedForegroundColor()); + + /* Create a button for the marker background color */ + p.pSelectedBackground = new Fl_Button(22, 170, 15, 15, "Selected Marker Background"); + p.pSelectedBackground->callback((Fl_Callback*) cb_selected_background, &p); + p.pSelectedBackground->align(FL_ALIGN_RIGHT); + p.pSelectedBackground->color(memedit_ctrl.pMemEdit->GetSelectedBackgroundColor()); + + p.pDefaults = new Fl_Button(240, 135, 70, 30, "Defaults"); p.pDefaults->callback((Fl_Callback *) cb_default_colors, &p); // Cancel button - { Fl_Button* o = new Fl_Button(80, 160, 60, 30, "Cancel"); + { Fl_Button* o = new Fl_Button(80, 200, 60, 30, "Cancel"); o->callback((Fl_Callback*) cb_setupdlg_cancel, &p); } // OK button - { Fl_Return_Button* o = new Fl_Return_Button(160, 160, 60, 30, "OK"); + { Fl_Return_Button* o = new Fl_Return_Button(160, 200, 60, 30, "OK"); o->callback((Fl_Callback*) cb_setupdlg_OK, &p); } @@ -3545,6 +4072,8 @@ void T100_MemEditor::AddMarker(int region) // Insert the marker here pMarkers->pNext = pNewMarker; } + + redraw(); } /* @@ -3743,6 +4272,83 @@ void T100_MemEditor::FindPrevMarker(void) } } +/* +============================================================================ +Determines if address is a marker field in which the cursor is located +============================================================================ +*/ +memedit_marker_t* T100_MemEditor::GetMarker(int address) +{ + int region; + memedit_marker_t* pMarker; + + // Determine which region marker to use. For RAM banks 1,2,3, + // we use the REGION_RAM marker so they all have the same + // set of markers + region = m_Region; + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + region = REGION_RAM; + + // Get pointer to start of marker list + pMarker = m_pRegionMarkers[region]; + + // Loop through all markers until we find one containing address + while (pMarker != NULL) + { + // Test if address is within this marker + if (address >= pMarker->startAddr && address <= pMarker->endAddr) + { + return pMarker; + } + + // Get pointer to next marker + pMarker = pMarker->pNext;; + } + + return NULL; +} + +/* +============================================================================ +Determines if address is a marker field in which the cursor is located +============================================================================ +*/ +int T100_MemEditor::IsSelected(int address) +{ + int region; + memedit_marker_t* pMarker; + + // Determine which region marker to use. For RAM banks 1,2,3, + // we use the REGION_RAM marker so they all have the same + // set of markers + region = m_Region; + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + region = REGION_RAM; + + // Get pointer to start of marker list + pMarker = m_pRegionMarkers[region]; + + // Loop through all markers until we find one containing address + while (pMarker != NULL) + { + // Test if address is within this marker + if (address >= pMarker->startAddr && address <= pMarker->endAddr) + { + // Now test if the current cursor address is also in this marker + if (m_CursorAddress >= pMarker->startAddr && m_CursorAddress <= pMarker->endAddr) + return TRUE; + + // Nope, cursor not in this marker. We're done + return FALSE; + } + + // Point to next marker + pMarker = pMarker->pNext; + } + + return FALSE; +} + /* ============================================================================ Deletes the marker identified by the Cursor. @@ -3920,5 +4526,9 @@ void T100_MemEditor::ResetMarkers(void) delete pMarkers; pMarkers = pNextMarker; } + + // NULL out the head pointers + m_pUndoDeleteMarkers[region] = NULL; + m_pRegionMarkers[region] = NULL; } } diff --git a/src/memedit.h b/src/memedit.h index f38ba90..079eafd 100644 --- a/src/memedit.h +++ b/src/memedit.h @@ -27,14 +27,12 @@ * SUCH DAMAGE. */ - #ifndef MEMEDIT_H #define MEMEDIT_H -#include "memory.h" - -#include "FL/Fl_File_Chooser.H" -#include +#include "vtobj.h" +#include "MString.h" +#include "watchtable.h" void cb_MemoryEditor (Fl_Widget* w, void*); void cb_MemoryEditorUpdate(void); @@ -42,8 +40,11 @@ void cb_MemoryEditorUpdate(void); void MemoryEditor_LoadPrefs(void); void MemoryEditor_SavePrefs(void); -#define MENU_HEIGHT 32 - +/* +============================================================================ +Class definition for Memory Editor +============================================================================ +*/ typedef struct memedit_colors { Fl_Color addr; @@ -52,6 +53,8 @@ typedef struct memedit_colors Fl_Color changed; Fl_Color hilight; Fl_Color hilight_background; + Fl_Color select; + Fl_Color select_background; Fl_Color foreground; Fl_Color background; Fl_Color cursor; @@ -65,12 +68,6 @@ typedef struct memedit_marker struct memedit_marker* pNext; } memedit_marker_t; -class T100_MemEditWin : public Fl_Double_Window -{ -public: - T100_MemEditWin(int x, int y, int w, int h, const char *title); -}; - class T100_MemEditor : public Fl_Widget { public: @@ -97,10 +94,15 @@ class T100_MemEditor : public Fl_Widget int GetSyntaxHilight(void) { return m_ColorSyntaxHilight; } Fl_Color GetMarkerForegroundColor(void) { return m_colors.hilight; } Fl_Color GetMarkerBackgroundColor(void) { return m_colors.hilight_background; } + Fl_Color GetSelectedForegroundColor(void) { return m_colors.select; } + Fl_Color GetSelectedBackgroundColor(void) { return m_colors.select_background; } void SetMarkerForegroundColor(Fl_Color c) { m_colors.hilight = c; redraw(); } void SetMarkerBackgroundColor(Fl_Color c) { m_colors.hilight_background = c; redraw(); } + void SetSelectedForegroundColor(Fl_Color c) { m_colors.select = c; redraw(); } + void SetSelectedBackgroundColor(Fl_Color c) { m_colors.select_background = c; redraw(); } int IsHilighted(int address); // Returns TRUE if given address should e hilighted + int IsSelected(int address); // Returns TRUE if address is a marker region where the cursor is int HasMarker(int address); // Returns TRUE if given address has a marker void AddMarker(int region=-1); // Adds marker at current m_SelStart, m_SelEnd address void DeleteMarker(void); // Delete the marker at the cursor @@ -111,6 +113,7 @@ class T100_MemEditor : public Fl_Widget void AddMarkerToRegion(int start, int end, int region); void FindNextMarker(void); void FindPrevMarker(void); + memedit_marker_t* GetMarker(int address); // Returns a pointer to the marker struct for address int m_FirstLine; int m_x, m_y, m_w, m_h; // user preferences for window position @@ -118,6 +121,7 @@ class T100_MemEditor : public Fl_Widget protected: // virtual int handle(int event); void draw(); + virtual void resize(int x, int y, int w, int h); virtual int handle(int event); void DrawCursor(void); void EraseCursor(void); diff --git a/src/memory.c b/src/memory.c index 0f38815..b4ab730 100644 --- a/src/memory.c +++ b/src/memory.c @@ -26,7 +26,7 @@ memory.c #include "filewrap.h" uchar *gMemory[64]; /* CPU Memory space */ -int gRamBottom = 0xa000;/* Defines the amount of RAM installed */ +int gRamBottom = 0x8000;/* Defines the amount of RAM installed */ uchar gBaseMemory[65536]; /* System Memory */ uchar gSysROM[65536]; /* System ROM */ uchar gOptROM[32768]; /* Option ROM */ @@ -370,7 +370,7 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) addr = address; for (c = 0; c < count; c++) { - if (gReMem) + if (gReMem && !gRex) gMemory[addr>>10][addr&0x3FF] = data[c]; else gBaseMemory[addr] = data[c]; diff --git a/src/memory.h b/src/memory.h index 769d3b3..4bb69ac 100644 --- a/src/memory.h +++ b/src/memory.h @@ -113,7 +113,7 @@ extern "C" { #define REX_ROM_REPLACEMENT 0x01 #define REX2_RAM_MODE 0x02 -#include "gen_defs.h" +//#include "gen_defs.h" typedef struct { int iFlashState; diff --git a/src/setup.cpp b/src/setup.cpp index 9d573b1..4f1b278 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -29,20 +29,9 @@ #include -#include -#include #include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include + #include #include #include @@ -56,12 +45,11 @@ #include "m100emu.h" #include "serial.h" #include "setup.h" -#include "memory.h" #include "memedit.h" #include "io.h" -#include "file.h" #include "lpt.h" #include "clock.h" +#include "cpu.h" extern Fl_Preferences virtualt_prefs; void init_menus(void); @@ -634,9 +622,11 @@ void set_memory_base(void) switch (gModel) { case MODEL_T200: + gRamBottom = ROMSIZE; break; case MODEL_PC8201: + gRamBottom = ROMSIZE; break; default: diff --git a/src/watchtable.cpp b/src/watchtable.cpp new file mode 100644 index 0000000..40cfea2 --- /dev/null +++ b/src/watchtable.cpp @@ -0,0 +1,1942 @@ +/* watchtable.cpp */ + +/* $Id$ */ + +/* + * Copyright 2004 Ken Pettit and Stephen Hurd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(WIN32) +#include +#endif +#include +#include + +#include "VirtualT.h" +#include "memory.h" +#include "cpu.h" +#include "watchtable.h" + +int str_to_i(const char *pStr); + +/* +============================================================================ +Start of implementation for Watch Table Widget +============================================================================ +*/ + +static void cb_watch_item(Fl_Widget* pW, void *pOpaque); + +static Fl_Menu_Item gWatchTypeMenu[] = { + { " U8 ", 0, cb_watch_item, (void *) WATCH_TYPE_UCHAR }, + { " S8 ", 0, cb_watch_item, (void *) WATCH_TYPE_SCHAR }, + { " Hex8 ", 0, cb_watch_item, (void *) WATCH_TYPE_HEXCHAR }, + { " U16 ", 0, cb_watch_item, (void *) WATCH_TYPE_USHORT }, + { " S16 ", 0, cb_watch_item, (void *) WATCH_TYPE_SSHORT }, + { " Hex16 ", 0, cb_watch_item, (void *) WATCH_TYPE_HEXSHORT }, + { " String ", 0, cb_watch_item, (void *) WATCH_TYPE_STRING }, + { 0 } +}; + +static Fl_Menu_Item gWatchRegionMenu[] = { + { " RAM ", 0, cb_watch_item, (void *) REGION_RAM }, + { " ROM ", 0, cb_watch_item, (void *) REGION_ROM }, + { " OptROM ", 0, cb_watch_item, (void *) REGION_OPTROM }, + { " RAM1 ", 0, cb_watch_item, (void *) REGION_RAM1 }, + { " RAM2 ", 0, cb_watch_item, (void *) REGION_RAM2 }, + { " RAM3 ", 0, cb_watch_item, (void *) REGION_RAM3 }, + { " FLASH ", 0, cb_watch_item, (void *) REGION_REX_FLASH }, + { 0 } +}; + +/* +============================================================================ +Callback for the Watch Widget popup menu +============================================================================ +*/ +static void cb_watch_popup(Fl_Widget* pW, void* pOpaque) +{ +} + +/* +============================================================================ +Callback for the Watch Widget popup input +============================================================================ +*/ +static void cb_popup_input(Fl_Widget* pW, void* pOpaque) +{ + // Get pointer to the parent + VT_Watch_Table* pTable = (VT_Watch_Table *) pOpaque; + VT_TableInput* pInput = (VT_TableInput *) pW; + + pTable->PopupInputCallback(pInput->m_reason); +} + +/* +============================================================================ +Callback for the Watch Widget scrollbar +============================================================================ +*/ +static void cb_watch_scroll(Fl_Widget* pW, void* pOpaque) +{ + // Get pointer to the parent + VT_Watch_Table* pTable = (VT_Watch_Table *) pOpaque; + + printf("Scroll\n"); + pTable->ScrollAction(); +} + +/* +============================================================================ +Class constructor for the Watch Table widget. +============================================================================ +*/ +VT_Watch_Table::VT_Watch_Table(int x, int y, int w, int h) : + Fl_Widget(x, y, w, h, "") +{ + int remaining, fontW, c; + + // Initialize class variables + m_FontSize = 14; + m_SelLine = -1; + m_DblclkX = m_DblclkY = -1; + m_PopupSelSave = -1; + m_PopupInputField = 0; + m_pEventHandler = NULL; + m_DoingWidgetResize = FALSE; + m_colors.watch_background = FL_BLACK; + m_colors.watch_lines = fl_lighter(FL_BLACK); + m_colors.watch_lines = fl_color_average(FL_BLACK, FL_WHITE, .85f); + m_colors.name = FL_YELLOW; + m_colors.region = FL_WHITE; + m_colors.address = (Fl_Color)166;//fl_lighter((Fl_Color) 166); + m_colors.type = FL_WHITE; + m_colors.value = FL_WHITE; + m_colors.select = FL_WHITE; + m_colors.select_background = FL_BLUE; + + // Create a tile for the top items + m_pColHeaderTile = new Fl_Tile(x, y, w-15, VT_WATCH_TABLE_HDR_HEIGHT, ""); + + // Set width of each table header box + fl_font(FL_COURIER, m_FontSize); + fontW = (int) fl_width("W"); + m_ColWidth[4] = 5 * fontW; + m_ColWidth[3] = 5 * fontW; + m_ColWidth[2] = 8 * fontW; + remaining = w-15 - (8+5+5) * fontW; + m_ColWidth[1] = remaining >> 1; + remaining -= m_ColWidth[1]; + m_ColWidth[0] = remaining; + + // Set the Start col for each field + m_ColStart[0] = x; + for (c = 1; c < 5; c++) + m_ColStart[c+1] = m_ColStart[c] + m_ColWidth[c]; + + // Create 5 boxes in the tile + m_pColHeaders[0] = new VT_TableHeaderBox(FL_UP_BOX, m_ColStart[0], y, m_ColWidth[0], VT_WATCH_TABLE_HDR_HEIGHT, "Watch Name"); + m_pColHeaders[1] = new VT_TableHeaderBox(FL_UP_BOX, m_ColStart[1], y, m_ColWidth[1], VT_WATCH_TABLE_HDR_HEIGHT, "Value"); + m_pColHeaders[2] = new VT_TableHeaderBox(FL_UP_BOX, m_ColStart[2], y, m_ColWidth[2], VT_WATCH_TABLE_HDR_HEIGHT, "Address"); + m_pColHeaders[3] = new VT_TableHeaderBox(FL_UP_BOX, m_ColStart[3], y, m_ColWidth[3], VT_WATCH_TABLE_HDR_HEIGHT, "Type"); + m_pColHeaders[4] = new VT_TableHeaderBox(FL_UP_BOX, m_ColStart[4], y, m_ColWidth[4], VT_WATCH_TABLE_HDR_HEIGHT, "Rgn"); + + // Setup alignment, etc. + for (c = 0; c < VT_WATCH_TABLE_COL_COUNT; c++) + { + m_pColHeaders[c]->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pColHeaders[c]->user_data(this); + + // Get the width percentage for each column + m_WidthPercentage[c] = (double) m_ColWidth[c] / (double) (w-15); + } + + // End the resizing tile + m_pColHeaderTile->end(); + + // Create a window for the variable space + m_pVarWindow = new Fl_Box(FL_NO_BOX, x, y+VT_WATCH_TABLE_HDR_HEIGHT, w-15, h-VT_WATCH_TABLE_HDR_HEIGHT, ""); + m_pVarWindow->hide(); + + // Create a scrollbar + m_pScroll = new Fl_Scrollbar(x+w-15, y, 15, h,""); + m_pScroll->step(1); + m_pScroll->maximum(50); + m_pScroll->slider_size(.1); + m_pScroll->value(1, 4, 1, 50); + m_pScroll->callback(cb_watch_scroll, this); + + // Create a popup menu + m_pPopupMenu = new Fl_Menu_Button(0,0,100,400,"Popup"); + m_pPopupMenu->type(Fl_Menu_Button::POPUP123); + m_pPopupMenu->menu(gWatchTypeMenu); + m_pPopupMenu->selection_color(fl_rgb_color(80,80,255)); + m_pPopupMenu->color(fl_rgb_color(240,239,228)); + m_pPopupMenu->hide(); + m_pPopupMenu->user_data(this); + m_pPopupMenu->callback(cb_watch_popup); + + m_pPopupBox = new Fl_Box(FL_DOWN_FRAME, 0, 0, 5, 5, ""); + m_pPopupBox->hide(); + + // Create a popup edit box + m_pPopupInput = new VT_TableInput(0, 0, 5, 5, ""); + m_pPopupInput->box(FL_FLAT_BOX); + m_pPopupInput->color(FL_BLACK); + m_pPopupInput->textcolor(FL_WHITE); + m_pPopupInput->cursor_color(FL_WHITE); + m_pPopupInput->selection_color(FL_BLUE); + m_pPopupInput->textfont(FL_COURIER); + m_pPopupInput->labelfont(FL_COURIER); + m_pPopupInput->labelsize(m_FontSize); + m_pPopupInput->callback(cb_popup_input, this); + m_pPopupInput->hide(); +} + +/* +============================================================================ +Class destructor for the Watch Table widget. +============================================================================ +*/ +VT_Watch_Table::~VT_Watch_Table() +{ + ResetContent(); +} + +/* +============================================================================ +Registers an event handler with the watch table +============================================================================ +*/ +void VT_Watch_Table::EventHandler(watch_event_handler_t pHandler) +{ + m_pEventHandler = pHandler; +} + +/* +============================================================================ +Deletes all watches from the array, etc. +============================================================================ +*/ +void VT_Watch_Table::ResetContent(void) +{ + int c, count; + CWatchDef* pVar; + + count = m_WatchVars.GetSize(); + for (c = 0; c < count; c++) + { + pVar = (CWatchDef *) m_WatchVars[c]; + delete pVar; + } + m_WatchVars.RemoveAll(); +} + +/* +============================================================================ +Sets the scrollbar settings based on current geometry and item count. +============================================================================ +*/ +void VT_Watch_Table::SetScrollSizes(void) +{ + int size, height, count, max; + + // Select 12 point Courier font + fl_font(FL_COURIER, m_FontSize); + + // Get character width & height + m_Height = fl_height(); + height = m_pVarWindow->h(); + size = (int) (height / m_Height); + count = m_WatchVars.GetSize(); + + // Set maximum value of scroll + if (m_pScroll->value()+size-2 > count ) + { + int newValue = count-size+2; + if (newValue < 1) + newValue = 1; + m_pScroll->value(newValue, 1, 0, count+2); + } + max = count + 2 - size; + if (max < 1) + max = 1; + m_pScroll->maximum(max); + m_pScroll->minimum(1); + m_pScroll->step((double) size/(double)(count+1)); + m_pScroll->slider_size((double) size/(double)(count+1)); + m_pScroll->linesize(1); + + redraw(); +} + +/* +============================================================================ +Callback for the scrollbar activity +============================================================================ +*/ +void VT_Watch_Table::ScrollAction(void) +{ + redraw(); +} + +/* +============================================================================ +Set the specified variable to the value identified by the string given +============================================================================ +*/ +void VT_Watch_Table::SetVarValue(CWatchDef* pVar, const char *psVal) +{ + short sval16; + unsigned short val16; + unsigned char val8; + const char *ptr; + int regionAddr, i; + + // Get the address within the region + regionAddr = pVar->m_iAddr; + if (pVar->m_Region == REGION_RAM || pVar->m_Region == REGION_RAM1 || + pVar->m_Region == REGION_RAM2 || pVar->m_Region == REGION_RAM3) + regionAddr -= ROMSIZE; + + // Set based on type + switch (pVar->m_Type) + { + case WATCH_TYPE_UCHAR: + case WATCH_TYPE_SCHAR: + case WATCH_TYPE_HEXCHAR: + default: + val8 = str_to_i(psVal); + set_memory8_ext(pVar->m_Region, regionAddr, 1, &val8); + break; + + case WATCH_TYPE_SSHORT: + sval16 = str_to_i(psVal); + val8 = sval16 & 0xFF; + set_memory8_ext(pVar->m_Region, regionAddr, 1, &val8); + val8 = (sval16 >> 8) & 0xFF; + set_memory8_ext(pVar->m_Region, regionAddr+1, 1, &val8); + break; + + case WATCH_TYPE_USHORT: + case WATCH_TYPE_HEXSHORT: + val16 = str_to_i(psVal); + val8 = val16 & 0xFF; + set_memory8_ext(pVar->m_Region, regionAddr, 1, &val8); + val8 = (val16 >> 8) & 0xFF; + set_memory8_ext(pVar->m_Region, regionAddr+1, 1, &val8); + break; + + case WATCH_TYPE_STRING: + ptr = psVal; + i = 0; + // Write bytes until we reach the NULL + while (*ptr != '\0') + { + // Get next value to write + val8 = *ptr++; + set_memory8_ext(pVar->m_Region, regionAddr + i++, 1, &val8); + } + + // Now write the NULL + val8 = *ptr++; + set_memory8_ext(pVar->m_Region, regionAddr + i, 1, &val8); + break; + } + + // Send an event that a value changed + if (m_pEventHandler != NULL) + m_pEventHandler(WATCH_EVENT_VAL_CHANGED, pVar); +} + +/* +============================================================================ +Get the value of the specified variable +============================================================================ +*/ +void VT_Watch_Table::UpdateVarValue(CWatchDef* pVar) +{ + int type = pVar->m_Type; + unsigned char c; + unsigned short s; + int regionAddr; + + // Calculate the region address + regionAddr = pVar->m_iAddr; + if (pVar->m_Region == REGION_RAM || pVar->m_Region == REGION_RAM1 || + pVar->m_Region == REGION_RAM2 || pVar->m_Region == REGION_RAM3) + regionAddr -= ROMSIZE; + + // Get the value based on type + if (type < WATCH_TYPE_USHORT) + { + // Get the memory using extended region access + get_memory8_ext(pVar->m_Region, regionAddr, 1, &c); + pVar->m_Value = c; + } + else if (type != WATCH_TYPE_STRING) + { + // Get the memory using extended region access + get_memory8_ext(pVar->m_Region, regionAddr, 1, &c); + s = c; + get_memory8_ext(pVar->m_Region, regionAddr+1, 1, &c); + s |= ((unsigned short) c) << 8; + pVar->m_Value = s; + } + else + { + int x = 0; + char str[2]; + + str[1] = '\0'; + pVar->m_StrData = ""; + get_memory8_ext(pVar->m_Region, regionAddr, 1, (unsigned char *) str); + while (str[0] != '\0') + { + pVar->m_StrData += (char *) str; + get_memory8_ext(pVar->m_Region, regionAddr + ++x, 1, (unsigned char *) str); + } + } +} + +/* +============================================================================ +Reads the variable's current value and formats it according to the specified +type parameter. +============================================================================ +*/ +void VT_Watch_Table::FormatVarValue(CWatchDef* pVar, char* str, int len) +{ + short shortval; + + // Format the value based on type + switch (pVar->m_Type) + { + case WATCH_TYPE_UCHAR: + default: + if (pVar->m_Value >= ' ' && pVar->m_Value <= '~') + sprintf(str, "%d '%c'", (unsigned char) pVar->m_Value, pVar->m_Value); + else + sprintf(str, "%d", (unsigned char) pVar->m_Value); + break; + case WATCH_TYPE_USHORT: + sprintf(str, "%d", (unsigned short) pVar->m_Value); + break; + case WATCH_TYPE_HEXCHAR: + sprintf(str, "%02XH '%c'", (unsigned char) pVar->m_Value, (char) pVar->m_Value); + break; + case WATCH_TYPE_SCHAR: + if (pVar->m_Value > 127) + sprintf(str, "%d", pVar->m_Value-256); + else + sprintf(str, "%d", pVar->m_Value); + break; + case WATCH_TYPE_SSHORT: + shortval = (short) pVar->m_Value; + sprintf(str, "%d", shortval); + break; + case WATCH_TYPE_HEXSHORT: + sprintf(str, "%04XH", (unsigned short) pVar->m_Value); + break; + + case WATCH_TYPE_STRING: + strcpy(str, "\""); + strncat(str, (const char *) pVar->m_StrData, len-3); + strcat(str, "\""); + break; + } +} + +/* +============================================================================ +Draw the specified watch variable on the specified line +============================================================================ +*/ +void VT_Watch_Table::DrawWatch(CWatchDef* pVar, int line) +{ + int wx, wy, ww, wh; + int xOffset, yOffset; + int fontHeight, lines, topLine; + char str[256]; + + // Get our dimensions + wx = m_pVarWindow->x(); + wy = m_pVarWindow->y(); + ww = m_pVarWindow->w(); + wh = m_pVarWindow->h(); + fontHeight = fl_height(); + lines = wh / fontHeight; + + // Test if line is in the scroll region + topLine = m_pScroll->value() - 1; + if (line < topLine || line-(topLine-1) > lines) + return; + + if (line < 0 || line > m_WatchVars.GetSize()) + return; + + // Offset text within cell + xOffset = 5; + yOffset = -5; + line -= topLine; + + // Draw the variable name + if (line+topLine == m_SelLine) + fl_color(m_colors.select); + else + fl_color(m_colors.name); + fl_draw((const char *) pVar->m_Name, m_ColStart[0]+xOffset, wy + (line+1) * fontHeight+yOffset); + + // Get the current value + UpdateVarValue(pVar); + if (line+topLine != m_SelLine) + fl_color(m_colors.value); + + // Format the value based on type + FormatVarValue(pVar, str, sizeof(str)); + + fl_push_clip(m_ColStart[1]+xOffset, wy + line * fontHeight + 1, m_ColWidth[1]-2-xOffset, fontHeight); + fl_draw(str, m_ColStart[1]+xOffset, wy + (line+1) * fontHeight+yOffset); + fl_pop_clip(); + + // Draw the address + if (line+topLine != m_SelLine) + fl_color(m_colors.address); + if (pVar->m_iAddr > 0xFFFF) + sprintf(str, "%06XH", pVar->m_iAddr); + else + sprintf(str, "%04XH", pVar->m_iAddr); + fl_draw(str, m_ColStart[2]+xOffset, wy + (line+1) * fontHeight+yOffset); + + // Draw the type + if (line+topLine != m_SelLine) + fl_color(m_colors.type); + switch (pVar->m_Type) + { + case WATCH_TYPE_UCHAR: strcpy(str, "U8"); break; + case WATCH_TYPE_SCHAR: strcpy(str, "S8"); break; + case WATCH_TYPE_HEXCHAR: strcpy(str, "H8"); break; + case WATCH_TYPE_USHORT: strcpy(str, "U16"); break; + case WATCH_TYPE_SSHORT: strcpy(str, "S16"); break; + case WATCH_TYPE_HEXSHORT: strcpy(str, "H16"); break; + case WATCH_TYPE_STRING: strcpy(str, "Str"); break; + } + fl_draw(str, m_ColStart[3]+xOffset, wy + (line+1) * fontHeight+yOffset); + + // Draw the region + if (line+topLine != m_SelLine) + fl_color(m_colors.region); + switch (pVar->m_Region) + { + case REGION_RAM: strcpy(str, "RAM"); break; + case REGION_ROM: strcpy(str, "ROM"); break; + case REGION_OPTROM: strcpy(str, "Opt"); break; + case REGION_RAM1: strcpy(str, "RAM1"); break; + case REGION_RAM2: strcpy(str, "RAM2"); break; + case REGION_RAM3: strcpy(str, "RAM3"); break; + case REGION_REX_FLASH: strcpy(str, "FLASH"); break; + default: strcpy(str, "RAM"); break; + } + fl_draw(str, m_ColStart[4]+xOffset, wy + (line+1) * fontHeight+yOffset); +} + +/* +============================================================================ +Routine to update watch table values real-time +============================================================================ +*/ +void VT_Watch_Table::UpdateTable(void) +{ + int c, count, fontHeight; + int wx, wy, ww, wh; + int lines, topItem, xOffset, yOffset; + char str[256]; + CWatchDef* pVar; + + // Do some prep work + window()->make_current(); + fl_font(FL_COURIER, m_FontSize); + fontHeight = fl_height(); + topItem = m_pScroll->value(); + + // Get dimensions of the variable space + wx = m_pVarWindow->x(); + wy = m_pVarWindow->y(); + ww = m_pVarWindow->w(); + wh = m_pVarWindow->h(); + lines = wh / fontHeight; + count = m_WatchVars.GetSize(); + xOffset = 5; + yOffset = -5; + + // Draw the background + fl_push_clip(wx, wy, ww, wh); + fl_color(m_colors.watch_background); + + // Now loop for all visible lines + for (c = 0; c < lines; c++) + { + // Test if no more vars to draw + if (c + topItem-1 >= count) + break; + + // Get next variable and draw it + pVar = (CWatchDef *) m_WatchVars[c+topItem-1]; + + // Test if this value is being edited + if (pVar->m_ValEdit) + continue; + + // Test for a change in the value + if (pVar->m_Type == WATCH_TYPE_STRING) + { + MString temp = pVar->m_StrData; + UpdateVarValue(pVar); + if (temp == pVar->m_StrData) + continue; + } + else + { + int temp = pVar->m_Value; + UpdateVarValue(pVar); + if (temp == pVar->m_Value) + continue; + } + + // Erase the old value + if (c == m_SelLine - topItem + 1) + fl_color(m_colors.select_background); + else + fl_color(m_colors.watch_background); + fl_rectf(m_ColStart[1], m_pVarWindow->y()+c*fontHeight, m_ColWidth[1], fontHeight-1); + + // Redraw the new value + FormatVarValue(pVar, str, sizeof(str)); + fl_color(m_colors.value); + fl_push_clip(m_ColStart[1]+xOffset, wy + c * fontHeight + 1, m_ColWidth[1]-2-xOffset, fontHeight); + fl_draw(str, m_ColStart[1]+xOffset, wy + (c+1) * fontHeight+yOffset); + fl_pop_clip(); + } + + // Pop the clip region + fl_pop_clip(); +} + +/* +============================================================================ +Our Watch Table drawing routine +============================================================================ +*/ +void VT_Watch_Table::draw(void) +{ + int c, count, fontHeight; + int wx, wy, ww, wh; + int lines, topItem; + CWatchDef* pVar; + + window()->make_current(); + + // Do our custom draw stuff + fl_font(FL_COURIER, m_FontSize); + fontHeight = fl_height(); + topItem = m_pScroll->value(); + + // Make our window the drawing window + wx = m_pVarWindow->x(); + wy = m_pVarWindow->y(); + ww = m_pVarWindow->w(); + wh = m_pVarWindow->h(); + lines = wh / fontHeight; + + // Draw the background + fl_push_clip(wx, wy, ww, wh); + fl_color(m_colors.watch_background); + fl_rectf(wx, wy, ww, wh); + + // Draw lines between the watch items + fl_color(m_colors.watch_lines); + for (c = 1; c < lines; c++) + fl_line(wx, wy+c * fontHeight, wx+ww, wy + c * fontHeight); + + // Draw the items + count = m_WatchVars.GetSize(); + for (c = 0; c < lines; c++) + { + // Test if this item is selected + if (c + topItem - 1 == m_SelLine) + { + // Draw the selection rectangle + fl_color(m_colors.select_background); + fl_rectf(m_pVarWindow->x(), m_pVarWindow->y()+c*fontHeight, w(), fontHeight-1); + } + + // Test if no more vars to draw + if (c + topItem-1 == count) + break; + + // Get next variable and draw it + pVar = (CWatchDef *) m_WatchVars[c+topItem-1]; + DrawWatch(pVar, c + topItem - 1); + } + + // Test if we need to draw the NewWatchName + if (c + topItem-1 == count) + { + fl_color(m_colors.name); + fl_draw((const char *) m_NewWatchName, m_ColStart[0]+5, wy + (c + topItem) * fontHeight-5); + } + + // Pop the clip region + fl_pop_clip(); +} + +/* +============================================================================ +Handle events that occur within the variable window. +============================================================================ +*/ +int VT_Watch_Table::handle_variable_events(int event) +{ + int line_click, fontHeight; + int xp, yp, topItem; + int button, x, key; + + // Get some common variables + fl_font(FL_COURIER, m_FontSize); + fontHeight = fl_height(); + m_Height = fontHeight; + topItem = m_pScroll->value(); + + // Get X,Y position of button press + xp = Fl::event_x(); + yp = Fl::event_y(); + + switch (event) + { + case FL_KEYDOWN: + // Get the key that was pressed + key = Fl::event_key(); + + // Process ESC key + if (key == FL_Escape) + { + m_SelLine = -1; + redraw(); + } + + else if (key == FL_Delete) + { + // If there's a selection + if (m_SelLine != -1) + { + if (m_SelLine < m_WatchVars.GetSize()) + { + DeleteWatch(m_SelLine); + if (m_SelLine > m_WatchVars.GetSize()) + m_SelLine--; + redraw(); + } + } + } + + else if (key == FL_Down) + { + // If there's a selection... + if (m_SelLine != -1) + { + // Increment to next line + m_SelLine++; + + // Constrain the selection + if (m_SelLine >= m_WatchVars.GetSize()) + m_SelLine = m_WatchVars.GetSize(); + + // Scroll if at bottom + int size = m_pVarWindow->h() / m_Height; + if (m_SelLine - topItem+1 == size) + { + m_pScroll->value(m_SelLine-2, 1, 0, 0); + SetScrollSizes(); + } + + redraw(); + } + } + + else if (key == FL_Up) + { + // If there's a selection... + if (m_SelLine != -1) + { + // Decrement to previous line + m_SelLine--; + + // Constrain the selection + if (m_SelLine < 0) + m_SelLine = 0; + + // Scroll if at top of window + if (m_SelLine == topItem-2) + { + m_pScroll->value(m_SelLine+1, 1, 0, m_WatchVars.GetSize()+2); + SetScrollSizes(); + } + + redraw(); + } + } + else if (key == FL_Enter) + { + // If there's a selection... + if (m_SelLine != -1) + { + if (m_SelLine < m_WatchVars.GetSize()) + HandleDoubleClick(1, m_SelLine); + else + HandleDoubleClick(0, m_SelLine); + } + } + else if (key >= FL_F + 1 && key <= FL_F + 12) + { + if (m_pEventHandler != NULL) + m_pEventHandler(key, NULL); + } + + return 1; + + case FL_PUSH: + take_focus(); + + line_click = (yp-VT_WATCH_TABLE_HDR_HEIGHT) / fontHeight; + if (line_click < 0) + line_click = 0; + + // Get the mouse button that was pressed + button = Fl::event_button(); + + // Test for right mouse click + if (button == FL_RIGHT_MOUSE) + { + // TODO: add right mouse click processing!!!!! + + return 1; + } + + // Test for double click action + if (xp == m_DblclkX && yp == m_DblclkY) + { + // Calculate which column + for (x = VT_WATCH_TABLE_COL_COUNT - 1; x >= 0; x--) + { + // Test if in this col + if (xp >= m_ColStart[x]) + { + if (line_click + topItem - 1 < m_WatchVars.GetSize()) + HandleDoubleClick(x, line_click); + m_DblclkX = m_DblclkY = -1; + return 1; + } + } + + // Cancel the double click + m_DblclkX = m_DblclkY = -1; + return 1; + } + + // Save the coords to test for double click next time + m_DblclkX = xp; + m_DblclkY = yp; + + // Test for a click in col 0 or 2 of the empty line + if (line_click + topItem - 1 == m_WatchVars.GetSize()) + { + if (xp < m_ColStart[1]) + { + m_SelLine = line_click+topItem-1; + HandleDoubleClick(0, m_SelLine); + return 1; + } else if (xp >= m_ColStart[2] && xp < m_ColStart[3]) + { + // Allow single click edit if a name already defined + if (m_NewWatchName.GetLength() != 0) + { + // Set the selection line and do double click processing + m_SelLine = line_click+topItem-1; + HandleDoubleClick(2, m_SelLine); + return 1; + } + } + } + + // Constrain line_click based on number of watch items + if (line_click + topItem - 1 > m_WatchVars.GetSize()) + { + line_click = m_WatchVars.GetSize() - topItem + 1; + } + + // Setup the window for drawing + window()->make_current(); + fl_push_clip(m_pVarWindow->x(), m_pVarWindow->y(), m_pVarWindow->w(), m_pVarWindow->h()); + + // Erase any previous selection + if (m_SelLine != -1) + { + // Clear this line + fl_color(m_colors.watch_background); + fl_rectf(m_pVarWindow->x(), m_pVarWindow->y()+(m_SelLine-(topItem-1))*fontHeight, w(), fontHeight); + if (m_SelLine - (topItem-1) != 0) + { + fl_color(m_colors.watch_lines); + int temp = m_SelLine-(topItem-1); + fl_line(m_pVarWindow->x(), m_pVarWindow->y()+ temp * fontHeight, + m_pVarWindow->x() + m_pVarWindow->w(), m_pVarWindow->y() + temp * fontHeight); + } + + // Redraw the previously selected item + if (m_SelLine < m_WatchVars.GetSize()) + { + CWatchDef* pVar = (CWatchDef *) m_WatchVars[m_SelLine]; + int oldSel = m_SelLine; + m_SelLine = line_click + topItem - 1; + DrawWatch(pVar, oldSel); + } + } + + // Draw the selection rectangle + fl_color(m_colors.select_background); + fl_rectf(m_pVarWindow->x(), m_pVarWindow->y()+line_click*fontHeight+1, w(), fontHeight-1); + + // Redraw this item + m_SelLine = line_click + topItem - 1; + if (m_SelLine < m_WatchVars.GetSize()) + { + CWatchDef* pVar = (CWatchDef *) m_WatchVars[line_click + topItem - 1]; + DrawWatch(pVar, m_SelLine); + } + fl_pop_clip(); + + return 1; + + case FL_RELEASE: + return 1; + + case FL_FOCUS: + // Indicate that we accept the focus + return 1; + + case FL_UNFOCUS: + // Clear the selection if any + if (m_SelLine != -1) + { + // Save the selection line + int oldSel = m_SelLine; + m_SelLine = -1; + + // Erase the selection line + window()->make_current(); + fl_color(m_colors.watch_background); + fl_push_clip(m_pVarWindow->x(), m_pVarWindow->y(), m_pVarWindow->w(), m_pVarWindow->h()); + fl_rectf(m_pVarWindow->x(), m_pVarWindow->y()+(oldSel-(topItem-1))*fontHeight, w(), fontHeight); + if (oldSel - (topItem-1) != 0) + { + fl_color(m_colors.watch_lines); + line_click = oldSel-(topItem-1); + fl_line(m_pVarWindow->x(), m_pVarWindow->y()+ line_click * fontHeight, + m_pVarWindow->x() + m_pVarWindow->w(), m_pVarWindow->y() + line_click * fontHeight); + } + fl_pop_clip(); + + // Redraw the selection item, if any + if (oldSel < m_WatchVars.GetSize()) + { + CWatchDef* pVar = (CWatchDef *) m_WatchVars[oldSel]; + DrawWatch(pVar, oldSel); + } + } + return 1; + + case FL_ENTER: + case FL_LEAVE: + // Indicate that we accept ENTER / LEAVE + return 1; + + case FL_MOVE: + case FL_DRAG: + if (xp != m_DblclkX || yp != m_DblclkY) + { + m_DblclkX = -1; + m_DblclkY = -1; + } + return 1; + + default: + break; + } + + return 0; +} + +/* +============================================================================ +Resize on of the column header boxes +============================================================================ +*/ +void VT_Watch_Table::HeaderBoxWidth(int col, int w) +{ + if (col < VT_WATCH_TABLE_COL_COUNT) + { + // Set the new width + m_ColWidth[col] = w; + + // If this isn't the 1st col, then set our X location too + if (col != 0) + m_ColStart[col] = m_ColStart[col-1] + m_ColWidth[col-1]; + + // Now resize all the controls + m_DoingWidgetResize = TRUE; + for (col = 0; col < VT_WATCH_TABLE_COL_COUNT; col++) + { + if (col < 2) + { + int remaining = m_pColHeaderTile->w(); + for (int i = 2; i < VT_WATCH_TABLE_COL_COUNT; i++) + remaining -= m_ColWidth[i]; + + m_WidthPercentage[col] = (double) m_ColWidth[col] / (double) remaining; + } + + m_pColHeaders[col]->resize(m_ColStart[col], m_pColHeaders[col]->y(), + m_ColWidth[col], VT_WATCH_TABLE_HDR_HEIGHT); + } + m_DoingWidgetResize = FALSE; + } +} + +/* +============================================================================ +Someone resized us...make sure everything gets resized properly. +============================================================================ +*/ +void VT_Watch_Table::resize(int x, int y, int w, int h) +{ + int remaining; + int c, tx, tw; + + // Disable updating percentages within column resizing + m_DoingWidgetResize = TRUE; + + // Do default widget resize stuff + Fl_Widget::resize(x, y, w, h); + + // We will keep cols 2-4 the same size and only resize 0 & 1 (Name, value) + tx = m_pColHeaderTile->x(); + tw = remaining = m_pColHeaderTile->w(); + + // Slide the last 3 columns to right-align with right of tile + m_ColStart[VT_WATCH_TABLE_COL_COUNT - 1] = tx+tw - + m_ColWidth[VT_WATCH_TABLE_COL_COUNT - 1]; + remaining -= m_ColWidth[VT_WATCH_TABLE_COL_COUNT - 1]; + + for (c = VT_WATCH_TABLE_COL_COUNT-2; c >= 2; c--) + { + m_ColStart[c] = m_ColStart[c+1] - m_ColWidth[c]; + remaining -= m_ColWidth[c]; + } + + // Now adjust cols 0 & 1 based on their percentage and remaining pixels + m_ColWidth[1] = (int) (m_WidthPercentage[1] * (double) remaining); + m_ColStart[1] = m_ColStart[2] - m_ColWidth[1]; + m_ColWidth[0] = m_ColStart[1] - m_ColStart[0]; + + // Now do physical resizing of the boxes + for (c = 0; c < VT_WATCH_TABLE_COL_COUNT; c++) + { + m_pColHeaders[c]->resize(m_ColStart[c], y, m_ColWidth[c], VT_WATCH_TABLE_HDR_HEIGHT); + } + + // Resize the variable window and scroll bar + m_pVarWindow->resize(m_pVarWindow->x(), y+VT_WATCH_TABLE_HDR_HEIGHT, + w-15, h-VT_WATCH_TABLE_HDR_HEIGHT); + m_pScroll->resize(x+w-15, y, 15, h); + + SetScrollSizes(); + + redraw(); +} + +/* +============================================================================ +Our Watch Table Widget event handler. +============================================================================ +*/ +int VT_Watch_Table::handle(int event) +{ + int ret; + + printf("Event %d\n", event); + // Test for events inside the watch window + if (Fl::event_inside(m_pVarWindow)) + { + ret = handle_variable_events(event); + if (ret) + return ret; + } + + switch (event) + { + case FL_HIDE: + return 1; + case FL_UNFOCUS: + case FL_KEYDOWN: + ret = handle_variable_events(event); + if (ret) + return ret; + break; + } + + // Not handled above. Do the default + return Fl_Widget::handle(event); +} + +/* +============================================================================ +Sets the color of the header boxes. +============================================================================ +*/ +void VT_Watch_Table::header_color(Fl_Color c) +{ + int x; + + for (x = 0; x < VT_WATCH_TABLE_COL_COUNT; x++) + m_pColHeaders[x]->color(c); +} + +/* +============================================================================ +Adds a new watch to the widget. +============================================================================ +*/ +int VT_Watch_Table::AddWatch(MString& name, MString& addr, int type, + int region, int need_redraw) +{ + int index; + CWatchDef* pWatch; + + // Create a new watch definition + pWatch = new CWatchDef; + if (pWatch != NULL) + { + // Populate the watch with data + pWatch->m_Name = name; + pWatch->m_Addr = addr; + pWatch->m_iAddr = str_to_i((const char *) addr); + pWatch->m_Type = type; + pWatch->m_Region = region; + + // Add the watch to the list + index = m_WatchVars.Add(pWatch); + + // Now draw the new item if needed + SetScrollSizes(); + if (need_redraw) + redraw(); + + return TRUE; + } + + return FALSE; +} + +/* +============================================================================ +Deletes the specified index watch +============================================================================ +*/ +void VT_Watch_Table::DeleteWatch(int index) +{ + // Get a pointer to the watch var + CWatchDef* pVar = (CWatchDef *) m_WatchVars[index]; + + // Remove it from the list + m_WatchVars.RemoveAt(index, 1); + + // Now delete the item + delete pVar; +} + +/* +============================================================================ +Test the watch string for parse errors. When called, we expect the pointer +to be pointing at a comma vs a semicolon or NULL. +============================================================================ +*/ +int VT_Watch_Table::WatchStringParseError(const char*& ptr) +{ + // Test if we encountered a comma as expected + if (*ptr != ',') + { + // Skip to next entry (next semicolon or NULL) + while (*ptr != ';' && *ptr != '\0') + ptr++; + + // If we found a semicolon, then skip past it + if (*ptr == ';') + ptr++; + + // Indicate we had a parse error + return TRUE; + } + + // Skip past the ',' + ptr++; + + // No parse error + return FALSE; +} + +/* +============================================================================ +Sets up the watch variables from the string from user preferences. +============================================================================ +*/ +void VT_Watch_Table::WatchVarsString(const char *pVarString) +{ + const char* ptr; + const char* regionPtr; + MString name, addr, typeStr; + int region, type; + + // Start at beginning of string + ptr = pVarString; + while (*ptr != '\0') + { + // Parse name + name = addr = typeStr = ""; + while (*ptr != ',' && *ptr != ';' && *ptr != '\0') + { + // Skip escape character + if (*ptr == '\\') + ptr++; + name += *ptr++; + } + + // Test for format error in string + if (WatchStringParseError(ptr)) + continue; + + // Parse address + while (*ptr != ',' && *ptr != ';' && *ptr != '\0') + addr += *ptr++; + + // Test for format error in string + if (WatchStringParseError(ptr)) + continue; + + // Parse the type + while (*ptr != ',' && *ptr != ';' && *ptr != '\0') + typeStr += *ptr++; + + // Test for format error in string + if (WatchStringParseError(ptr)) + continue; + + // Parse the region enum + regionPtr = ptr; + while (*ptr >= '0' && *ptr <= '9') + ptr++; + + // Test for error during parse + if (*ptr != ';' && *ptr != '\0') + { + WatchStringParseError(ptr); + continue; + } + + // Skip past the semicolon + ptr++; + + // Convert the enum ascii to in int + region = atoi(regionPtr); + + // Convert the type string to an int + if (typeStr == "U8") + type = WATCH_TYPE_UCHAR; + else if (typeStr == "S8") + type = WATCH_TYPE_SCHAR; + else if (typeStr == "H8") + type = WATCH_TYPE_HEXCHAR; + else if (typeStr == "U16") + type = WATCH_TYPE_USHORT; + else if (typeStr == "S16") + type = WATCH_TYPE_SSHORT; + else if (typeStr == "H16") + type = WATCH_TYPE_HEXSHORT; + else if (typeStr == "String") + type = WATCH_TYPE_STRING; + else + type = WATCH_TYPE_UCHAR; + + // Add this watch variable, but don't redraw yet + AddWatch(name, addr, type, region, FALSE); + } + + // Now redraw + redraw(); +} + +/* +============================================================================ +Returns the watch vars string for saving our variables to the preferences file. +============================================================================ +*/ +MString VT_Watch_Table::WatchVarsString(void) +{ + int c, count, x, len; + CWatchDef* pVar; + MString ret, fmt, name; + const char *psType; + + // Loop for all watches + count = m_WatchVars.GetSize(); + for (c = 0; c < count; c++) + { + // Get next watch + pVar = (CWatchDef *) m_WatchVars[c]; + + // Format the type in case the enums change at some point + switch (pVar->m_Type) + { + case WATCH_TYPE_UCHAR: psType = "U8"; break; + case WATCH_TYPE_SCHAR: psType = "S8"; break; + case WATCH_TYPE_HEXCHAR: psType = "H8"; break; + case WATCH_TYPE_USHORT: psType = "U16"; break; + case WATCH_TYPE_SSHORT: psType = "S16"; break; + case WATCH_TYPE_HEXSHORT: psType = "H16"; break; + case WATCH_TYPE_STRING: psType = "String"; break; + default: psType = "U8"; break; + } + + // Add escape chars to name if it contains comma, semicolon or '\' + name = ""; + len = pVar->m_Name.GetLength(); + for (x = 0; x < len; x++) + { + if (pVar->m_Name[x] == ',' || pVar->m_Name[x] == ';' || + pVar->m_Name[x] == '\\') + { + name += '\\'; + name += pVar->m_Name[x]; + } + else + name += pVar->m_Name[x]; + } + + // Format a substring for this watch + fmt.Format("%s,%s,%s,%d;", (const char *) name, + (const char *) pVar->m_Addr, psType, pVar->m_Region); + + ret += fmt; + } + + // Return the formatted string + return ret; +} + +/* +============================================================================ +Adds a new watch to the widget. +============================================================================ +*/ +void VT_Watch_Table::HandleDoubleClick(int field, int line) +{ + int show_popup = FALSE; + CWatchDef* pVar; + char str[16]; + + // For field 0, popup the input box + if (field < 3) + { + // Save the current selection line, clear it and redraw + m_PopupSelSave = m_SelLine; + m_SelLine = -1; + redraw(); + + // Resize the popup input field to fit in our cell + m_pPopupInput->resize(m_ColStart[field]+4, m_pVarWindow->y()+ + (m_PopupSelSave-(m_pScroll->value()-1))*(int)m_Height-1, + m_ColWidth[field]-3, m_Height); + if (field == 0) + m_pPopupInput->textcolor(m_colors.name); + else if (field == 1) + m_pPopupInput->textcolor(m_colors.value); + else if (field == 2) + m_pPopupInput->textcolor(m_colors.address); + m_pPopupInput->selection_color(m_colors.select_background); + m_pPopupInput->color(m_colors.watch_background); + m_PopupInputField = field; + + // Test if we are editing a new entry or an existing one + if (m_PopupSelSave >= m_WatchVars.GetSize()) + { + // New entry. Start with a blank page + if (field == 0) + m_pPopupInput->value((const char *) m_NewWatchName); + else + m_pPopupInput->value(""); + } + else + { + // Get the variable being edited and prepare the input field + pVar = (CWatchDef *) m_WatchVars[m_PopupSelSave]; + if (field == 0) + m_pPopupInput->value((const char *) pVar->m_Name); + else if (field == 1) + { + // Format value based on type + if (pVar->m_Type == WATCH_TYPE_STRING) + { + // Populate input with the string data + m_pPopupInput->value((const char *) pVar->m_StrData); + } + else + { + // Format in either HEX or decimal format + if (pVar->m_Type == WATCH_TYPE_HEXCHAR) + sprintf(str, "%02XH", pVar->m_Value); + else if (pVar->m_Type == WATCH_TYPE_HEXSHORT) + sprintf(str, "%04XH", pVar->m_Value); + else if (pVar->m_Type == WATCH_TYPE_SCHAR) + sprintf(str, "%d", pVar->m_Value > 127 ? pVar->m_Value - 256 : pVar->m_Value); + else if (pVar->m_Type == WATCH_TYPE_SSHORT) + sprintf(str, "%d", pVar->m_Value > 32767 ? pVar->m_Value - 65536 : pVar->m_Value); + else + sprintf(str, "%d", pVar->m_Value); + m_pPopupInput->value(str); + } + + // Mark the value as being edited + pVar->m_ValEdit = TRUE; + } else if (field == 2) + { + m_pPopupInput->value((const char *) pVar->m_Addr); + } + } + + // Show the popup input + m_pPopupInput->show(); + m_pPopupInput->take_focus(); + m_pPopupInput->position(0); + m_pPopupInput->mark(999999); + } + + // For field 4, popup the region menu + else if (field == 4) + { + m_pPopupMenu->menu(gWatchRegionMenu); + show_popup = TRUE; + } + + // For field 3, popup the type menu + else if (field == 3) + { + m_pPopupMenu->menu(gWatchTypeMenu); + show_popup = TRUE; + } + + // Did anyone request the popup menu? + if (show_popup) + { + // Save the selected item, clear it and redraw + m_PopupSelSave = m_SelLine; + m_SelLine = -1; + redraw(); + + // Get the screen coordinates + int screenX, screenY, screenW, screenH; + Fl::screen_xywh(screenX, screenY, screenW, screenH); + + // Find the screen coordinate for the Y value of the + // selection to test if the popup will fit below the item or not + int my = m_pVarWindow->y()+(m_PopupSelSave-m_pScroll->value()+1)*(int)m_Height; + Fl_Group *p = parent(); + while (p != NULL) + { + // Translate Y based on parent's Y and get his parent + my += p->y(); + p = p->parent(); + } + + // Resize the popup box frame and show it to indicate we are + // making a selection + m_pPopupBox->resize(m_ColStart[field], m_pVarWindow->y()+ + (m_PopupSelSave - (m_pScroll->value()-1))*(int)m_Height, + m_ColWidth[field]-3, m_Height); + m_pPopupBox->box(FL_EMBOSSED_FRAME); + m_pPopupBox->show(); + + // Count the number of items in the menu + int itemCount; + const Fl_Menu_Item* pM = m_pPopupMenu->menu(); + for (itemCount = 0; pM[itemCount].text != NULL; itemCount++) + ; + + // Now popup the menu + Fl_Widget *mb = m_pPopupMenu; + const Fl_Menu_Item* m; + Fl::watch_widget_pointer(mb); + if (my + itemCount * 19 >= screenH) + m = m_pPopupMenu->menu()->popup(m_ColStart[field]+2, m_pVarWindow->y()+ + (m_PopupSelSave-m_pScroll->value())*(int)m_Height - itemCount*19, NULL, 0, m_pPopupMenu); + else + m = m_pPopupMenu->menu()->popup(m_ColStart[field]+2, m_pVarWindow->y()+ + (m_PopupSelSave-m_pScroll->value()+2)*(int)m_Height+3, NULL, 0, m_pPopupMenu); + + // Hide the popup box showing we are selecting a new item + m_pPopupBox->hide(); + + // Restore the selection and redraw + m_SelLine = m_PopupSelSave; + + // Call the callback item for the selected menu or the cancel callback + m_pPopupMenu->picked(m); + if (m == NULL) + cb_watch_popup(NULL, NULL); + Fl::release_widget_pointer(mb); + + // Redraw the window + m_SelLine = -1; + redraw(); + } +} + +/* +============================================================================ +Adds a new watch to the widget. +============================================================================ +*/ +static void cb_watch_item(Fl_Widget* pW, void *pOpaque) +{ + Fl_Menu_Button* pPopup = (Fl_Menu_Button *) pW; + VT_Watch_Table* pWatch; + + // Restore the selection + pWatch = (VT_Watch_Table *) pPopup->user_data(); + + // Determine which menu is active + if (pPopup->menu() == gWatchTypeMenu) + pWatch->SetSelectedType((int) pOpaque); + else if (pPopup->menu() == gWatchRegionMenu) + pWatch->SetSelectedRegion((int) pOpaque); +} + +/* +============================================================================ +Adds a new watch to the widget. +============================================================================ +*/ +void VT_Watch_Table::SetSelectedType(int type) +{ + CWatchDef* pVar; + + if (m_SelLine < m_WatchVars.GetSize()) + { + // Get the pointe to the variable + pVar = (CWatchDef *) m_WatchVars[m_SelLine]; + + // Update the type and redraw + pVar->m_Type = type; + UpdateVarValue(pVar); + redraw(); + } +} + +/* +============================================================================ +Adds a new watch to the widget. +============================================================================ +*/ +void VT_Watch_Table::SetSelectedRegion(int region) +{ + CWatchDef* pVar; + + if (m_SelLine < m_WatchVars.GetSize()) + { + // Get the pointer to the variable + pVar = (CWatchDef *) m_WatchVars[m_SelLine]; + + // Update the type and redraw + pVar->m_Region = region; + UpdateVarValue(pVar); + redraw(); + } +} + +/* +============================================================================ +Manages resizing of any of the header boxes. +============================================================================ +*/ +void VT_Watch_Table::HeaderResize(VT_TableHeaderBox* pBox, int x, + int y, int cw, int ch) +{ + int c; + + // Determine which column is being resized + for (c = 0; c < VT_WATCH_TABLE_COL_COUNT; c++) + { + // Test if it's this header + if (pBox == m_pColHeaders[c]) + break; + } + + // If not found, then there's a bug somewhere. Just return + if (c == VT_WATCH_TABLE_COL_COUNT) + return; + + + // Get the width percentage for each column + if (!m_DoingWidgetResize) + { + // Save the new start col and width of this column + m_ColStart[c] = x; + m_ColWidth[c] = cw; + + // For 1st two fields, calculate percentage width of remaining + // space after last cols. + if (c < 2) + { + int remaining = m_pColHeaderTile->w(); + for (int i = 2; i < VT_WATCH_TABLE_COL_COUNT; i++) + remaining -= m_ColWidth[i]; + + m_WidthPercentage[c] = (double) m_ColWidth[c] / (double) remaining; + } + } + + // Redraw everything + redraw(); +} + +/* +============================================================================ +Manages resizing of any of the header boxes. +============================================================================ +*/ +void VT_Watch_Table::PopupInputCallback(int reason) +{ + CWatchDef* pVar; + + // Only process callback for reasons we understand + if (reason == 0) + return; + + // Hide the popup + m_pPopupInput->hide(); + window()->take_focus(); + + // Test if escape pressed + if (reason == FL_Escape) + { + // Show the cursor again + fl_cursor(FL_CURSOR_DEFAULT); + + // Restore the old selection line and redraw + m_SelLine = m_PopupSelSave; + + // Test if we need to cancel value editing + if (m_SelLine < m_WatchVars.GetSize()) + { + pVar = (CWatchDef *) m_WatchVars[m_SelLine]; + pVar->m_ValEdit = FALSE; + } + redraw(); + return; + } + + // Upate the variable or do processing to create a new one + if (m_PopupSelSave >= m_WatchVars.GetSize()) + { + // Processing a new watch. Test if we are in field 0 or 2 + if (m_PopupInputField == 0) + { + // If reason was UNFOCUS, then cancel the input + if (reason == FL_UNFOCUS) + { + // Test if we need to cancel value editing + if (m_PopupSelSave < m_WatchVars.GetSize()) + { + pVar = (CWatchDef *) m_WatchVars[m_PopupSelSave]; + pVar->m_ValEdit = FALSE; + } + + // Clear the new watch name, if any + if (Fl::focus() == this) + m_SelLine = m_PopupSelSave; + redraw(); + return; + } + + // Okay, we got a callback during entry of the name. Test if a + // name was actually entered + if (strlen(m_pPopupInput->value()) > 0) + { + // Get the name and save it until we have the address too + m_NewWatchName = m_pPopupInput->value(); + + // Now move the input field to the address cell + m_pPopupInput->resize(m_ColStart[2]+4, m_pVarWindow->y()+ + (m_PopupSelSave-(m_pScroll->value()-1))*(int)m_Height-1, + m_ColWidth[2]-3, m_Height-1); + m_pPopupInput->value(""); + m_pPopupInput->textcolor(m_colors.address); + + // Now redraw to show the new watch name + redraw(); + + // Now show the input in field 2 (address) + m_pPopupInput->show(); + m_pPopupInput->take_focus(); + m_PopupInputField = 2; + fl_cursor(FL_CURSOR_INSERT); + return; + } + else + { + // Just cancel the input + m_SelLine = m_PopupSelSave; + redraw(); + + // Show the cursor again + fl_cursor(FL_CURSOR_DEFAULT); + + return; + } + } + else if (m_PopupInputField == 2) + { + // Okay, check if an address was actually entered + if (strlen(m_pPopupInput->value()) > 0) + { + MString addr = m_pPopupInput->value(); + int iaddr = str_to_i((const char *) addr); + int region; + if (iaddr < ROMSIZE) + region = REGION_ROM; + else + region = REGION_RAM; + AddWatch(m_NewWatchName, addr, WATCH_TYPE_UCHAR, region); + m_NewWatchName = ""; + + // Set this line as the selectionline + redraw(); + m_SelLine = m_PopupSelSave+1; + + // Allow entry of another variable + int lines = m_pVarWindow->h() / m_Height; + if (m_SelLine >= m_pScroll->value() - 1 + lines) + { + // TODO: Deal with scrolling + m_SelLine = -1; + } + else + HandleDoubleClick(0, m_SelLine); + + return; + } + else + { + // Just cancel the input + m_SelLine = m_PopupSelSave; + redraw(); + + // Show the cursor again + fl_cursor(FL_CURSOR_DEFAULT); + return; + } + } + } + else + { + // Validate the input has data + if (strlen(m_pPopupInput->value()) == 0) + { + // Not allowed! Must enter something + m_pPopupInput->show(); + m_pPopupInput->take_focus(); + return; + } + + // We are editing an existing entry. Get the watch variable + pVar = (CWatchDef *) m_WatchVars[m_PopupSelSave]; + + // Get edited data from the input + if (m_PopupInputField == 0) + // Updating the name + pVar->m_Name = m_pPopupInput->value(); + else if (m_PopupInputField == 1) + { + // Updating the value. + SetVarValue(pVar, m_pPopupInput->value()); + pVar->m_ValEdit = FALSE; + } + else if (m_PopupInputField == 2) + { + // Updating the address + pVar->m_Addr = m_pPopupInput->value(); + pVar->m_iAddr = str_to_i((const char *) pVar->m_Addr); + + // Update the variable value + UpdateVarValue(pVar); + } + + // Restore the selection line + m_SelLine = m_PopupSelSave; + redraw(); + } + + // Show the cursor again + fl_cursor(FL_CURSOR_DEFAULT); +} + +/* +============================================================================ +Constructor for Watch Table Header box. +============================================================================ +*/ +VT_TableHeaderBox::VT_TableHeaderBox(int boxType, int x, int y, + int w, int h, const char *title) : Fl_Box((Fl_Boxtype) boxType, x, y, w, h, title) +{ +} + +/* +============================================================================ +Resize routine for Watch Table Header box +============================================================================ +*/ +void VT_TableHeaderBox::resize(int x, int y, int w, int h) +{ + // First do default Fl_Box resizing + Fl_Box::resize(x, y, w, h); + + // Now do our custom stuff + VT_Watch_Table* pTable = (VT_Watch_Table *) user_data(); + pTable->HeaderResize(this, x, y, w, h); +} + +/* +============================================================================ +Event handler for Table Header box +============================================================================ +*/ +int VT_TableHeaderBox::handle(int event) +{ + // Get pointer to the parent + VT_Watch_Table* pTable = (VT_Watch_Table *) user_data(); + + switch (event) + { + case FL_ENTER: + case FL_MOVE: + pTable->m_DoingWidgetResize = FALSE; + break; + } + + return Fl_Box::handle(event); +} + +/* +============================================================================ +Class constructor for Table Input +============================================================================ +*/ +VT_TableInput::VT_TableInput(int x, int y, int w, int h, const char *title) : + Fl_Input(x, y, w, h, title) +{ +} + +/* +============================================================================ +Event handler for Table Input +============================================================================ +*/ +int VT_TableInput::handle(int event) +{ + int key; + + printf("Event %d\n", event); + + // Clear the keypress + m_reason = 0; + + switch (event) + { + case FL_FOCUS: + // On focus, always select the text + position(0); + mark(9999); + break; + + case FL_UNFOCUS: + m_reason = FL_UNFOCUS; + do_callback(); + return 1; + + case FL_KEYDOWN: + // Handle TAB and Enter keys + // Get the Key that was pressed + key = Fl::event_key(); + + if (key == FL_Enter || key == FL_Tab || key == FL_Escape) + { + // Do normal input handling first + Fl_Input::handle(event); + + // Set the user data to indicate which key caused the callback + m_reason = key; + do_callback(); + return 1; + } + break; + + case FL_KEYUP: + return 1; + + default: + break; + } + + // Now do the default thing that Fl_Input would do + return Fl_Input::handle(event); +} + diff --git a/src/watchtable.h b/src/watchtable.h new file mode 100644 index 0000000..350e33a --- /dev/null +++ b/src/watchtable.h @@ -0,0 +1,188 @@ +/* watchtable.h */ + +/* $Id$ */ + +/* + * Copyright 2004 Ken Pettit and Stephen Hurd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef WATCHTABLE_H +#define WATCHTABLE_H + +#include +#include +#include + +#include "memory.h" +#include "vtobj.h" +#include "MString.h" + +/* +============================================================================ +Class definition for Watch Variables +============================================================================ +*/ +#define WATCH_TYPE_UCHAR 0 +#define WATCH_TYPE_SCHAR 1 +#define WATCH_TYPE_HEXCHAR 2 +#define WATCH_TYPE_USHORT 3 +#define WATCH_TYPE_SSHORT 4 +#define WATCH_TYPE_HEXSHORT 5 +#define WATCH_TYPE_STRING 6 + +#define WATCH_EVENT_VAL_CHANGED 50 + +typedef void (*watch_event_handler_t)(int reason, void *pOpaque); + +class CWatchDef : public VTObject +{ +public: + CWatchDef() { m_iAddr = -1; m_Value = -1; m_Type = 0; m_Region = REGION_RAM; + m_ValEdit = 0; } + MString m_Name; + MString m_Addr; // String form of address as given + MString m_StrData; // String data for string format display + + int m_iAddr; // integer form of address + int m_Value; // Current value + int m_Type; // Type of watch + int m_Region; // Region the variable is in + int m_ValEdit; // Set true when value being edited +}; + +/* +============================================================================ +Class definition for Watch Table Column Header boxes +============================================================================ +*/ +class VT_TableHeaderBox : public Fl_Box +{ +public: + VT_TableHeaderBox(int boxType, int x, int y, int w, int h, const char *title); + + virtual void resize(int x, int y, int w, int h); + virtual int handle(int event); +}; + +/* +============================================================================ +Class definition for Table Input +============================================================================ +*/ +class VT_TableInput : public Fl_Input +{ +public: + VT_TableInput(int x, int y, int w, int h, const char *title); + + virtual int handle(int event); + int m_reason; +}; + +/* +============================================================================ +Class definition and definesfor Watch Table Widget +============================================================================ +*/ +typedef struct watchtable_colors +{ + Fl_Color watch_background; + Fl_Color watch_lines; + Fl_Color name; + Fl_Color address; + Fl_Color value; + Fl_Color type; + Fl_Color region; + Fl_Color select; + Fl_Color select_background; +} watchtable_color_t; + +#define VT_WATCH_TABLE_HDR_HEIGHT 20 +#define VT_WATCH_TABLE_COL_COUNT 5 + +class VT_Watch_Table : public Fl_Widget +{ +public: + VT_Watch_Table(int x, int y, int w, int h); + ~VT_Watch_Table(); + + virtual void draw(void); + virtual void resize(int x, int y, int w, int h); + virtual int handle(int event); + + void header_color(Fl_Color c); + void HeaderResize(VT_TableHeaderBox *pBox, int x, int y, int w, int h); + + int AddWatch(MString& name, MString& addr, int type, int region, int redraw = TRUE); + void DeleteWatch(int index); + void ResetContent(void); + void UpdateTable(void); + void SetSelectedType(int type); + void SetSelectedRegion(int region); + void PopupInputCallback(int reason); // The popup input has lost focus or had a keypress + void SetScrollSizes(void); + void ScrollAction(void); + void HeaderBoxWidth(int col, int width); + int HeaderBoxWidth(int col) { return col < VT_WATCH_TABLE_COL_COUNT ? m_ColWidth[col] : 0; } + MString WatchVarsString(void); + void WatchVarsString(const char *pVarsString); + void EventHandler(watch_event_handler_t pHandler); + + int m_DoingWidgetResize; + +protected: + virtual int handle_variable_events(int event); + void SetVarValue(CWatchDef* pVar, const char *psVal); + void UpdateVarValue(CWatchDef* pVar); + void DrawWatch(CWatchDef* pVar, int line); + void HandleDoubleClick(int field, int line); + void FormatVarValue(CWatchDef* pVar, char* str, int len); + int WatchStringParseError(const char*& ptr); + + // FLTK conrols + Fl_Tile* m_pColHeaderTile; + Fl_Box* m_pColHeaders[VT_WATCH_TABLE_COL_COUNT]; + Fl_Box* m_pVarWindow; + Fl_Group* m_pGroup; + Fl_Scrollbar* m_pScroll; + Fl_Menu_Button* m_pPopupMenu; + Fl_Box* m_pPopupBox; + Fl_Input* m_pPopupInput; + + VTObArray m_WatchVars; + watchtable_color_t m_colors; + + int m_FontSize; + int m_ColStart[VT_WATCH_TABLE_COL_COUNT]; + int m_ColWidth[VT_WATCH_TABLE_COL_COUNT]; + double m_WidthPercentage[VT_WATCH_TABLE_COL_COUNT]; + int m_SelLine; + int m_DblclkX, m_DblclkY; + int m_Height; // Font height + int m_PopupSelSave; + int m_PopupInputField; + watch_event_handler_t m_pEventHandler; + MString m_NewWatchName; +}; + +#endif From d5bd721dc6953a404180d056d0b6902074ed1ea2 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 15 Feb 2013 15:05:13 +0000 Subject: [PATCH 227/327] Modifications to make new WatchTable widget work with Linux. --- src/memedit.cpp | 77 +++++++++++++++++++++------------------------- src/memedit.h | 2 ++ src/memory.h | 3 +- src/watchtable.cpp | 14 ++++----- 4 files changed, 46 insertions(+), 50 deletions(-) diff --git a/src/memedit.cpp b/src/memedit.cpp index c6b572b..692825f 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -915,25 +915,21 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) if (gmew != NULL) return; - // Create Peripheral Setup window -#ifdef WIN32 + // Create the Memory Editor Window gmew = new Fl_Double_Window(w, h+wh, "Memory Editor"); // Create a menu for the new window. memedit_ctrl.pMenu = new Fl_Menu_Bar(0, 0, w, MENU_HEIGHT-2); -#else - gmew = new Fl_Window(735, h+wh, "Memory Editor"); - // Create a menu for the new window. - memedit_ctrl.pMenu = new Fl_Menu_Bar(0, 0, 735, MENU_HEIGHT-2); -#endif gmew->callback(cb_memeditwin); memedit_ctrl.pMenu->menu(gMemEdit_menuitems); - // Create a tiled window to support Project, Edit, and debug regions + // Create a tiled window to support Project, Edit, and debug regions Fl_Tile* tile = new Fl_Tile(0,MENU_HEIGHT,w,h+wh-MENU_HEIGHT-3); + // Create a top pane window in the tile for the memory editor controls memedit_ctrl.pTopPane = new Fl_Double_Window(0, MENU_HEIGHT, w, h-MENU_HEIGHT, ""); + // Create a group to manage resizing of just the editor window, not the other controls Fl_Group* g = new Fl_Group(0, 10, w, 25, ""); // Create static text boxes @@ -951,68 +947,48 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) memedit_ctrl.pMemRange->callback(cb_memory_range); memedit_ctrl.pMemRange->when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED); - // Create a resize box for the group and end the group + // Create a resize box for the group and end the group. This resizing box within + // the group causes the region and address edit fields to maintain size / position + // while allowing the editor region to resize with the group. o = new Fl_Box(w-15, 10, 5, 5, ""); o->hide(); g->resizable(o); g->end(); -#ifdef WIN32 + // Create the memory editor widget and scrollbar memedit_ctrl.pMemEdit = new T100_MemEditor(10, 40/*+MENU_HEIGHT*/, 545, 350-MENU_HEIGHT+10); memedit_ctrl.pScroll = new Fl_Scrollbar(555, 40/*+MENU_HEIGHT*/, 15, 350-MENU_HEIGHT+10, ""); -#else - memedit_ctrl.pMemEdit = new T100_MemEditor(10, 40/*+MENU_HEIGHT*/, 695, 350-MENU_HEIGHT); - memedit_ctrl.pScroll = new Fl_Scrollbar(705, 40/*+MENU_HEIGHT*/, 15, 350-MENU_HEIGHT, ""); -#endif + // Set initial values for scrollbar memedit_ctrl.pScroll->type(FL_VERTICAL); memedit_ctrl.pScroll->linesize(2); memedit_ctrl.pScroll->maximum(2); memedit_ctrl.pScroll->callback(cb_MemEditScroll); memedit_ctrl.pScroll->slider_size(1); - // Make the menu and edit widget resizeable with the top tile window + // Make the menu and edit widget resizeable with the top pane window memedit_ctrl.pTopPane->resizable(memedit_ctrl.pMemEdit); memedit_ctrl.pTopPane->end(); - // Create a window for the watches + // Create a bottom pane window for the watch table widget memedit_ctrl.pBottomPane = new Fl_Double_Window(0, h, w, wh, ""); + // Create a group to hold the framing box and the actual watch table widget g = new Fl_Group(0, 0, w, wh, ""); Fl_Box* b = new Fl_Box(FL_DOWN_FRAME, 9, 2, w-22, wh-5, ""); + // Create the Watch Table widget memedit_ctrl.pWatchTable = new VT_Watch_Table(12, 4, w-27, wh-9); memedit_ctrl.pWatchTable->header_color(fl_rgb_color(253, 252, 251)); memedit_ctrl.pWatchTable->EventHandler(cb_watch_events); -#if 0 - MString name = "test_data0"; - MString addr = "0x8003"; - memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); - name = "test_data1"; - memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); - name = "test_data2"; - memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); - name = "test_data3"; - memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); - name = "test_data4"; - memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); - name = "test_data5"; - memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); - name = "test_data6"; - memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); - name = "test_data7"; - memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); - name = "test_data8"; - memedit_ctrl.pWatchTable->AddWatch(name, addr, 0, REGION_RAM, FALSE); -#endif - // make the window resizable + // Make a box to define the window resize region within the group b = new Fl_Box(FL_NO_BOX, 12, wh-9, 5, 3, ""); b->hide(); g->resizable(b); g->end(); - + // Make the bottom pane resizable memedit_ctrl.pBottomPane->resizable(g); memedit_ctrl.pBottomPane->end(); @@ -1022,14 +998,15 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) tile->resizable(b); tile->end(); - // Make the window resizable + // Make the top level window resizable gmew->resizable(memedit_ctrl.pMenu); gmew->resizable(tile); gmew->end(); + // Update the scroll size controls for the editor window memedit_ctrl.pMemEdit->SetScrollSize(); - // Set Memory Monitor callback + // Set Memory Monitor callback. This hooks us for real-time memory updates. mem_set_monitor_callback(memory_monitor_cb); // Get the user preferences for the memory editor @@ -1050,11 +1027,14 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) gmew->resize(newx, newy, neww, newh); } + // Show the window gmew->show(); // Resize top pane if user preference has been set if (memedit_ctrl.iSplitH != -1) { + // User preferences for the watch region have been defined. Resize to + // match the saved geometry. First test for sanity. if (memedit_ctrl.iSplitH < 64) memedit_ctrl.iSplitH = 64; memedit_ctrl.pTopPane->resize(memedit_ctrl.pTopPane->x(), memedit_ctrl.pTopPane->y(), @@ -1065,6 +1045,8 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) } else { + // User preferences not set yet. Make the watch window a small region + // at the bottom of the window memedit_ctrl.pTopPane->resize(memedit_ctrl.pTopPane->x(), memedit_ctrl.pTopPane->y(), memedit_ctrl.pTopPane->w(), memedit_ctrl.pTopPane->h()-20); @@ -1073,9 +1055,14 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) memedit_ctrl.pBottomPane->h()+20); } - // Resize the column headers if user preferences have been set + // Finally resize the column headers if user preferences have been set if (memedit_ctrl.iCol0W != -1) { + // Set the location of all 5 column. NOTE: we are not doing any + // sanity checks here. If the column widths don't add up to + // match the tile width, then there will be problems. Not an + // issue as long as the user doesn't manually changed the widths + // in the preferences file. memedit_ctrl.pWatchTable->HeaderBoxWidth(0, memedit_ctrl.iCol0W); memedit_ctrl.pWatchTable->HeaderBoxWidth(1, memedit_ctrl.iCol1W); memedit_ctrl.pWatchTable->HeaderBoxWidth(2, memedit_ctrl.iCol2W); @@ -1137,12 +1124,18 @@ void T100_MemEditor::resize(int x, int y, int w, int h) } if (memedit_ctrl.pScroll != NULL) { + // Test if making the window larger will leave empty space + // at the bottom of the editor window and adjust the scroll + // to prevent it if (memedit_ctrl.pScroll->value() + size > m_Max) { memedit_ctrl.pScroll->value((int) (m_Max - size), 1, 0, (int) m_Max); SetScrollSize(); redraw(); } + + // Redraw the scrollbar. On Linux, it sometimes disappears?? + memedit_ctrl.pScroll->redraw(); } } diff --git a/src/memedit.h b/src/memedit.h index 079eafd..7786831 100644 --- a/src/memedit.h +++ b/src/memedit.h @@ -30,6 +30,8 @@ #ifndef MEMEDIT_H #define MEMEDIT_H +#include + #include "vtobj.h" #include "MString.h" #include "watchtable.h" diff --git a/src/memory.h b/src/memory.h index 4bb69ac..6f9acff 100644 --- a/src/memory.h +++ b/src/memory.h @@ -13,6 +13,8 @@ memory.h #ifndef MEMORY_H #define MEMORY_H +#include "gen_defs.h" + #ifdef __cplusplus extern "C" { #endif @@ -113,7 +115,6 @@ extern "C" { #define REX_ROM_REPLACEMENT 0x01 #define REX2_RAM_MODE 0x02 -//#include "gen_defs.h" typedef struct { int iFlashState; diff --git a/src/watchtable.cpp b/src/watchtable.cpp index 40cfea2..05ed08e 100644 --- a/src/watchtable.cpp +++ b/src/watchtable.cpp @@ -39,6 +39,8 @@ #if defined(WIN32) #include +#else +#include #endif #include #include @@ -113,7 +115,6 @@ static void cb_watch_scroll(Fl_Widget* pW, void* pOpaque) // Get pointer to the parent VT_Watch_Table* pTable = (VT_Watch_Table *) pOpaque; - printf("Scroll\n"); pTable->ScrollAction(); } @@ -665,7 +666,7 @@ void VT_Watch_Table::draw(void) int lines, topItem; CWatchDef* pVar; - window()->make_current(); + //window()->make_current(); // Do our custom draw stuff fl_font(FL_COURIER, m_FontSize); @@ -987,6 +988,8 @@ int VT_Watch_Table::handle_variable_events(int event) return 1; case FL_ENTER: + // Set the cursor to default for this window + window()->cursor(FL_CURSOR_DEFAULT); case FL_LEAVE: // Indicate that we accept ENTER / LEAVE return 1; @@ -1104,7 +1107,6 @@ int VT_Watch_Table::handle(int event) { int ret; - printf("Event %d\n", event); // Test for events inside the watch window if (Fl::event_inside(m_pVarWindow)) { @@ -1555,9 +1557,9 @@ static void cb_watch_item(Fl_Widget* pW, void *pOpaque) // Determine which menu is active if (pPopup->menu() == gWatchTypeMenu) - pWatch->SetSelectedType((int) pOpaque); + pWatch->SetSelectedType((intptr_t) pOpaque); else if (pPopup->menu() == gWatchRegionMenu) - pWatch->SetSelectedRegion((int) pOpaque); + pWatch->SetSelectedRegion((intptr_t) pOpaque); } /* @@ -1894,8 +1896,6 @@ int VT_TableInput::handle(int event) { int key; - printf("Event %d\n", event); - // Clear the keypress m_reason = 0; From 2b01adaea785f33c13163f9d4761b4745cfab7e1 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 15 Feb 2013 16:22:27 +0000 Subject: [PATCH 228/327] More changes to fix Linux drawing (memory editor cursor drawing issue). --- src/memedit.cpp | 15 +++++++++------ src/watchtable.cpp | 5 ++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/memedit.cpp b/src/memedit.cpp index 692825f..c905b8f 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -917,6 +917,7 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) // Create the Memory Editor Window gmew = new Fl_Double_Window(w, h+wh, "Memory Editor"); + // Create a menu for the new window. memedit_ctrl.pMenu = new Fl_Menu_Bar(0, 0, w, MENU_HEIGHT-2); @@ -1826,6 +1827,10 @@ int T100_MemEditor::handle(int event) int xpos, ypos, actualAddr; char string[6]; + if (event == 0) + return 0; + + //printf("Event %d\n", event); // Do some common processing before the switch if (event == FL_PUSH || event == FL_MOVE || event == FL_DRAG) { @@ -1880,7 +1885,10 @@ int T100_MemEditor::handle(int event) redraw(); } else if (m_CursorRow != -1 && m_CursorCol != -1) + { + window()->make_current(); DrawCursor(); + } break; case FL_UNFOCUS: @@ -1981,9 +1989,6 @@ int T100_MemEditor::handle(int event) col = 0; line = lineIndex << 1; - // "Unselect" previous start or stop char - window()->make_current(); - // Select 12 point Courier font fl_font(m_Font, m_FontSize); @@ -3175,7 +3180,6 @@ void T100_MemEditor::EraseCursor() int x_pos, y_pos, address, col; // Clip the drawing - window()->make_current(); fl_push_clip(x(), y(), w(), h()); // Erase current cursor @@ -3248,8 +3252,7 @@ void T100_MemEditor::DrawCursor() return; // Clip the drawing - window()->make_current(); - fl_push_clip(x(), y(), w(), h()); + fl_push_clip(window()->x(), window()->y(), window()->w(), window()->h()); // Draw new cursor fl_color(m_colors.cursor); diff --git a/src/watchtable.cpp b/src/watchtable.cpp index 05ed08e..bee9fcf 100644 --- a/src/watchtable.cpp +++ b/src/watchtable.cpp @@ -455,7 +455,10 @@ void VT_Watch_Table::FormatVarValue(CWatchDef* pVar, char* str, int len) sprintf(str, "%d", (unsigned short) pVar->m_Value); break; case WATCH_TYPE_HEXCHAR: - sprintf(str, "%02XH '%c'", (unsigned char) pVar->m_Value, (char) pVar->m_Value); + if (pVar->m_Value >= ' ' && pVar->m_Value <= '~') + sprintf(str, "%02XH '%c'", (unsigned char) pVar->m_Value, (char) pVar->m_Value); + else + sprintf(str, "%02XH", (unsigned char) pVar->m_Value); break; case WATCH_TYPE_SCHAR: if (pVar->m_Value > 127) From 791a73a9c49c025e144936b64b4abf1ebe7c0d96 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 16 Feb 2013 20:41:36 +0000 Subject: [PATCH 229/327] Added ability to move watch varibles around in the watch table widget. --- src/m100emu.c | 8 ++++ src/memedit.cpp | 109 ++++++++++++++++++++++++++++++++++++++------- src/watchtable.cpp | 61 ++++++++++++++++++++++--- src/watchtable.h | 1 + 4 files changed, 159 insertions(+), 20 deletions(-) diff --git a/src/m100emu.c b/src/m100emu.c index 9c7d3b4..42508cd 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -1142,6 +1142,8 @@ void emulate(void) } /* Instruction emulation contained in header file */ + #undef NO_REMEM + #include "cpu.h" #include "do_instruct.h" // Check if next inst is SIM @@ -1182,6 +1184,12 @@ void emulate(void) nxtmaint=gMaintCount; lock_remote(); } +#if 0 + exec_remem_instruction(); + + if (gExitLoop) + break; +#endif } if (!gReMem) diff --git a/src/memedit.cpp b/src/memedit.cpp index c905b8f..00f4928 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -80,11 +80,13 @@ typedef struct memedit_ctrl_struct Fl_Box* pRegionText; Fl_Box* pAddressText; Fl_Choice* pRegion; + Fl_Tile* pTile; char sFilename[256]; int sAddrStart; int sAddrEnd; int sAddrTop; + int watchHidden; int iSplitH; int iCol0W; int iCol1W; @@ -121,6 +123,7 @@ void cb_goto_prev_marker(Fl_Widget* w, void*); void cb_delete_marker(Fl_Widget* w, void*); void cb_delete_all_markers(Fl_Widget* w, void*); void cb_undo_delete_all_markers(Fl_Widget* w, void*); +void cb_show_hide_watch(Fl_Widget* w, void*); int str_to_i(const char *pStr); @@ -151,6 +154,7 @@ Fl_Menu_Item gMemEdit_menuitems[] = { { "&File", 0, 0, 0, FL_SUBMENU }, { "Load from File...", 0, cb_load, 0 }, { "Save to File...", 0, cb_save_memory, 0, FL_MENU_DIVIDER }, + { "Hide Watch window", 0, cb_show_hide_watch, 0, FL_MENU_DIVIDER }, { "Setup...", 0, cb_setup_memedit, 0}, { 0 }, @@ -925,7 +929,7 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) memedit_ctrl.pMenu->menu(gMemEdit_menuitems); // Create a tiled window to support Project, Edit, and debug regions - Fl_Tile* tile = new Fl_Tile(0,MENU_HEIGHT,w,h+wh-MENU_HEIGHT-3); + memedit_ctrl.pTile = new Fl_Tile(0,MENU_HEIGHT,w,h+wh-MENU_HEIGHT-3); // Create a top pane window in the tile for the memory editor controls memedit_ctrl.pTopPane = new Fl_Double_Window(0, MENU_HEIGHT, w, h-MENU_HEIGHT, ""); @@ -934,17 +938,17 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) Fl_Group* g = new Fl_Group(0, 10, w, 25, ""); // Create static text boxes - o = new Fl_Box(FL_NO_BOX, 10, 10/*+MENU_HEIGHT*/, 50, 15, "Region"); + o = new Fl_Box(FL_NO_BOX, 10, 10, 50, 15, "Region"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - o = new Fl_Box(FL_NO_BOX, 175, 10/*+MENU_HEIGHT*/, 50, 15, "Address"); + o = new Fl_Box(FL_NO_BOX, 175, 10, 50, 15, "Address"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); // Create Region choice box - memedit_ctrl.pRegion = new Fl_Choice(70, 8/*+MENU_HEIGHT*/, 100, 20, ""); + memedit_ctrl.pRegion = new Fl_Choice(70, 8, 100, 20, ""); memedit_ctrl.pRegion->callback(cb_region); // Create edit field for memory search / display field - memedit_ctrl.pMemRange = new Fl_Input(235, 8/*+MENU_HEIGHT*/, 80, 20, ""); + memedit_ctrl.pMemRange = new Fl_Input(240, 8, 80, 20, ""); memedit_ctrl.pMemRange->callback(cb_memory_range); memedit_ctrl.pMemRange->when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED); @@ -957,8 +961,8 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) g->end(); // Create the memory editor widget and scrollbar - memedit_ctrl.pMemEdit = new T100_MemEditor(10, 40/*+MENU_HEIGHT*/, 545, 350-MENU_HEIGHT+10); - memedit_ctrl.pScroll = new Fl_Scrollbar(555, 40/*+MENU_HEIGHT*/, 15, 350-MENU_HEIGHT+10, ""); + memedit_ctrl.pMemEdit = new T100_MemEditor(10, 40, w-20-15/*545*/, 350-MENU_HEIGHT+10); + memedit_ctrl.pScroll = new Fl_Scrollbar(w-10-15/*555*/, 40, 15, 350-MENU_HEIGHT+10, ""); // Set initial values for scrollbar memedit_ctrl.pScroll->type(FL_VERTICAL); @@ -976,10 +980,10 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) // Create a group to hold the framing box and the actual watch table widget g = new Fl_Group(0, 0, w, wh, ""); - Fl_Box* b = new Fl_Box(FL_DOWN_FRAME, 9, 2, w-22, wh-5, ""); + Fl_Box* b = new Fl_Box(FL_DOWN_FRAME, 9, 2, w-17/*22*/, wh-5, ""); // Create the Watch Table widget - memedit_ctrl.pWatchTable = new VT_Watch_Table(12, 4, w-27, wh-9); + memedit_ctrl.pWatchTable = new VT_Watch_Table(12, 4, w-22, wh-9); memedit_ctrl.pWatchTable->header_color(fl_rgb_color(253, 252, 251)); memedit_ctrl.pWatchTable->EventHandler(cb_watch_events); @@ -996,12 +1000,12 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) // Make the tile resizable b = new Fl_Box(10, 0, w-40, h,""); b->hide(); - tile->resizable(b); - tile->end(); + memedit_ctrl.pTile->resizable(b); + memedit_ctrl.pTile->end(); // Make the top level window resizable gmew->resizable(memedit_ctrl.pMenu); - gmew->resizable(tile); + gmew->resizable(memedit_ctrl.pTile); gmew->end(); // Update the scroll size controls for the editor window @@ -1042,7 +1046,7 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) memedit_ctrl.pTopPane->w(), memedit_ctrl.iSplitH); memedit_ctrl.pBottomPane->resize(memedit_ctrl.pBottomPane->x(), memedit_ctrl.pTopPane->y()+memedit_ctrl.iSplitH, memedit_ctrl.pBottomPane->w(), - tile->h()-memedit_ctrl.iSplitH ); + memedit_ctrl.pTile->h()-memedit_ctrl.iSplitH ); } else { @@ -1056,9 +1060,17 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) memedit_ctrl.pBottomPane->h()+20); } - // Finally resize the column headers if user preferences have been set + // Resize the column headers if user preferences have been set if (memedit_ctrl.iCol0W != -1) { + int remaining = memedit_ctrl.pWatchTable->w() - 15; + + remaining -= memedit_ctrl.iCol4W; + remaining -= memedit_ctrl.iCol3W; + remaining -= memedit_ctrl.iCol2W; + remaining -= memedit_ctrl.iCol1W; + memedit_ctrl.iCol0W = remaining; + // Set the location of all 5 column. NOTE: we are not doing any // sanity checks here. If the column widths don't add up to // match the tile width, then there will be problems. Not an @@ -1070,6 +1082,16 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) memedit_ctrl.pWatchTable->HeaderBoxWidth(3, memedit_ctrl.iCol3W); memedit_ctrl.pWatchTable->HeaderBoxWidth(4, memedit_ctrl.iCol4W); } + + Fl::wait(0.02); + + // Finally test if the watch window should be hidden + if (memedit_ctrl.watchHidden) + { + // Mark it not hidden because the callback will toggle + memedit_ctrl.watchHidden = FALSE; + cb_show_hide_watch(NULL, NULL); + } } /* @@ -3351,6 +3373,7 @@ void MemoryEditor_LoadPrefs(void) } // Get watch window geometry + g.get("WatchHidden", memedit_ctrl.watchHidden, 0); g.get("SplitH", memedit_ctrl.iSplitH, -1); g.get("Col0_Width", memedit_ctrl.iCol0W, -1); g.get("Col1_Width", memedit_ctrl.iCol1W, -1); @@ -3450,7 +3473,14 @@ void MemoryEditor_SavePrefs(void) g.set("h", gmew->h()); // Save watch variable geometry - g.set("SplitH", memedit_ctrl.pTopPane->h()); + g.set("WatchHidden", memedit_ctrl.watchHidden); + // If watch window is hidden, then update SplitH in case the window + // was resized + memedit_ctrl.iSplitH = gmew->h() - MENU_HEIGHT - 3 - + memedit_ctrl.pBottomPane->h(); + if (memedit_ctrl.iSplitH < 128) + memedit_ctrl.iSplitH = gmew->h() >> 1; + g.set("SplitH", memedit_ctrl.iSplitH); g.set("Col0_Width", memedit_ctrl.pWatchTable->HeaderBoxWidth(0)); g.set("Col1_Width", memedit_ctrl.pWatchTable->HeaderBoxWidth(1)); g.set("Col2_Width", memedit_ctrl.pWatchTable->HeaderBoxWidth(2)); @@ -4528,3 +4558,52 @@ void T100_MemEditor::ResetMarkers(void) m_pRegionMarkers[region] = NULL; } } + +void cb_show_hide_watch(Fl_Widget* w, void*) +{ + int sh = memedit_ctrl.pTile->h(); + + if (memedit_ctrl.watchHidden) + { + // Mark the watch pane visible + memedit_ctrl.watchHidden = 0; + + // Update iSplitH in case the window was resized while + // the bottom pane was hidden + memedit_ctrl.iSplitH = memedit_ctrl.pTile->h() - + memedit_ctrl.pBottomPane->h(); + if (memedit_ctrl.pBottomPane->h() < 50) + memedit_ctrl.iSplitH = gmew->h() - MENU_HEIGHT - 96; + + // Resize the top pane to occupy the entire window + memedit_ctrl.pTopPane->resize(memedit_ctrl.pTopPane->x(), + memedit_ctrl.pTopPane->y(), memedit_ctrl.pTopPane->w(), + memedit_ctrl.iSplitH); + + // Restore the position of the bottom pane + memedit_ctrl.pBottomPane->resize(memedit_ctrl.pTopPane->x(), + memedit_ctrl.pTopPane->y() + memedit_ctrl.iSplitH, + memedit_ctrl.pTile->w(), + memedit_ctrl.pTile->h()-memedit_ctrl.iSplitH); + + gMemEdit_menuitems[3].text = "Hide Watch Window"; + } + else + { + // Mark the watch window hidden + memedit_ctrl.watchHidden = 1; + + // Read current positon of the pane + memedit_ctrl.iSplitH = memedit_ctrl.pTopPane->h(); + + // Move the bottom pane out of view + memedit_ctrl.pBottomPane->position(-2000, 0); + + // Resize the top pane to occupy the entire window + memedit_ctrl.pTopPane->resize(memedit_ctrl.pTopPane->x(), + memedit_ctrl.pTopPane->y(), memedit_ctrl.pTopPane->w(), + sh-10); + + gMemEdit_menuitems[3].text = "Show Watch Window"; + } +} diff --git a/src/watchtable.cpp b/src/watchtable.cpp index bee9fcf..1aac377 100644 --- a/src/watchtable.cpp +++ b/src/watchtable.cpp @@ -132,6 +132,7 @@ VT_Watch_Table::VT_Watch_Table(int x, int y, int w, int h) : m_FontSize = 14; m_SelLine = -1; m_DblclkX = m_DblclkY = -1; + m_MoveStartX = m_MoveStartY = -1; m_PopupSelSave = -1; m_PopupInputField = 0; m_pEventHandler = NULL; @@ -669,8 +670,6 @@ void VT_Watch_Table::draw(void) int lines, topItem; CWatchDef* pVar; - //window()->make_current(); - // Do our custom draw stuff fl_font(FL_COURIER, m_FontSize); fontHeight = fl_height(); @@ -732,9 +731,10 @@ Handle events that occur within the variable window. */ int VT_Watch_Table::handle_variable_events(int event) { - int line_click, fontHeight; - int xp, yp, topItem; - int button, x, key; + int line_click, fontHeight, lines; + int xp, yp, topItem; + int button, x, key; + CWatchDef* pVar; // Get some common variables fl_font(FL_COURIER, m_FontSize); @@ -833,6 +833,7 @@ int VT_Watch_Table::handle_variable_events(int event) } else if (key >= FL_F + 1 && key <= FL_F + 12) { + // Pass function keys to the registerd event handler if (m_pEventHandler != NULL) m_pEventHandler(key, NULL); } @@ -840,11 +841,16 @@ int VT_Watch_Table::handle_variable_events(int event) return 1; case FL_PUSH: + // Take the focus for ourselves take_focus(); + // Calculate the line the mouse was clicked on line_click = (yp-VT_WATCH_TABLE_HDR_HEIGHT) / fontHeight; if (line_click < 0) line_click = 0; + lines = this->m_pVarWindow->h() / m_Height; + if (line_click >= lines) + line_click = lines - 1; // Get the mouse button that was pressed button = Fl::event_button(); @@ -947,12 +953,17 @@ int VT_Watch_Table::handle_variable_events(int event) { CWatchDef* pVar = (CWatchDef *) m_WatchVars[line_click + topItem - 1]; DrawWatch(pVar, m_SelLine); + Fl::grab(); + m_MoveStartX = xp; + m_MoveStartY = yp; } fl_pop_clip(); return 1; case FL_RELEASE: + window()->cursor(FL_CURSOR_DEFAULT); + Fl::release(); return 1; case FL_FOCUS: @@ -999,11 +1010,51 @@ int VT_Watch_Table::handle_variable_events(int event) case FL_MOVE: case FL_DRAG: + // Clear any active double-click location if (xp != m_DblclkX || yp != m_DblclkY) { m_DblclkX = -1; m_DblclkY = -1; } + if (event == FL_MOVE) + return 1; + + // Test if we are moving the selected item up or down + if (m_SelLine != -1) + { + if (m_SelLine < m_WatchVars.GetSize()) + { + if (abs(yp - m_MoveStartY) > 4) + window()->cursor(FL_CURSOR_MOVE); + + // Calculate the new line the cursor is on + line_click = (yp-VT_WATCH_TABLE_HDR_HEIGHT) / fontHeight; + if (line_click < 0) + line_click = 0; + + // Constrain line_click based on number of variables defined + if (line_click + topItem - 1 >= m_WatchVars.GetSize()) + { + line_click = m_WatchVars.GetSize() - topItem; + } + + // Test if moving to a different line + if (m_SelLine != line_click) + { + // Get pointer to the variable + pVar = (CWatchDef *) m_WatchVars[m_SelLine]; + m_WatchVars.RemoveAt(m_SelLine, 1); + + // Reinsert at new location + m_WatchVars.InsertAt(line_click, pVar); + + // Set the new SelLine value + m_SelLine = line_click; + redraw(); + } + } + } + return 1; default: diff --git a/src/watchtable.h b/src/watchtable.h index 350e33a..e3ff249 100644 --- a/src/watchtable.h +++ b/src/watchtable.h @@ -178,6 +178,7 @@ class VT_Watch_Table : public Fl_Widget double m_WidthPercentage[VT_WATCH_TABLE_COL_COUNT]; int m_SelLine; int m_DblclkX, m_DblclkY; + int m_MoveStartX, m_MoveStartY; int m_Height; // Font height int m_PopupSelSave; int m_PopupInputField; From 5bdf467e154c1f0870d46d09db0bd3c487d1c3e1 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 17 Feb 2013 01:26:50 +0000 Subject: [PATCH 230/327] Added console control interface under Linux and completed the "-nogui" option. --- release.txt | 3 + src/display.cpp | 135 ++++++++++++----------- src/lpt.cpp | 5 + src/m100emu.c | 50 ++++++++- src/remote.cpp | 247 +++++++++++++++++++++++++++++++++++++++++-- src/remote.h | 1 + src/serversocket.cpp | 27 +++++ src/serversocket.h | 12 ++- 8 files changed, 411 insertions(+), 69 deletions(-) diff --git a/release.txt b/release.txt index d2712f8..f73bee2 100644 --- a/release.txt +++ b/release.txt @@ -51,6 +51,9 @@ v1.6 14. Started converting the preferences file to use preference groups to help organize the growing list of entries in the file. +15. Completed the "-nogui" option under Linux and added console interface control. This + provides an identical interface to the existing socket / telnet control interface. + ==================== v1.5 July 9th, 2011 ==================== diff --git a/src/display.cpp b/src/display.cpp index 50e9092..f0cf9cf 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -2218,7 +2218,9 @@ void init_display(void) /* End the Window and show it */ MainWin->end(); - MainWin->show(); + + if (!gNoGUI) + MainWin->show(); #ifdef WIN32 // On Win32 platforms, the show() routine causes the window to shrink. Reset it if fullscreen. @@ -2297,6 +2299,11 @@ static char mapStr[40]; void display_cpu_speed(void) { + // Test if we are in no GUI mode + if (gNoGUI) + return; + + // If speed is less than 10 Mhz, then show 2 decimal places, else 1 if (cpu_speed + 0.5 < 10.0) sprintf(label, "%4.2f Mhz", cpu_speed); else @@ -2307,7 +2314,7 @@ void display_cpu_speed(void) void display_map_mode(char *str) { - if (gpMap == NULL) + if (gpMap == NULL || gNoGUI) return; strcpy(mapStr, str); @@ -2317,17 +2324,20 @@ void display_map_mode(char *str) void drawbyte(int driver, int column, int value) { + if (gNoGUI) + return; if (gpDisp != NULL) gpDisp->SetByte(driver, column, value); if (gpDebugMonitor != 0) gpDebugMonitor->SetByte(driver, column, value); - return; } void lcdcommand(int driver, int value) { + if (gNoGUI) + return; if (gpDisp != NULL) gpDisp->Command(driver, value); if (gpDebugMonitor != 0) @@ -2338,6 +2348,8 @@ void lcdcommand(int driver, int value) void power_down() { + if (gNoGUI) + return; if (gpDisp != NULL) gpDisp->PowerDown(); if (gpDebugMonitor != 0) @@ -3452,7 +3464,8 @@ int T100_Disp::handle(int event) gSpecialKeys |= MT_ESC; break; case FL_Delete: - if ((Fl::get_key(FL_Shift_L) | Fl::get_key(FL_Shift_R)) == 0) + if ((get_key(FL_Shift_L) | get_key(FL_Shift_R)) == 0) + //if ((Fl::get_key(FL_Shift_L) | Fl::get_key(FL_Shift_R)) == 0) gSpecialKeys |= MT_SHIFT; case FL_BackSpace: gSpecialKeys |= MT_BKSP; @@ -3506,27 +3519,27 @@ int T100_Disp::handle(int event) break; case FL_Insert: case FL_Home: - if ((Fl::get_key(FL_Control_L) | Fl::get_key(FL_Control_R)) == 0) + if ((get_key(FL_Control_L) | get_key(FL_Control_R)) == 0) gSpecialKeys |= MT_CTRL; - if (Fl::get_key(FL_Left) == 0) + if (get_key(FL_Left) == 0) gSpecialKeys |= MT_LEFT; break; case FL_End: - if ((Fl::get_key(FL_Control_L) | Fl::get_key(FL_Control_R)) == 0) + if ((get_key(FL_Control_L) | get_key(FL_Control_R)) == 0) gSpecialKeys |= MT_CTRL; - if (Fl::get_key(FL_Right) == 0) + if (get_key(FL_Right) == 0) gSpecialKeys |= MT_RIGHT; break; case FL_Page_Up: - if ((Fl::get_key(FL_Shift_L) | Fl::get_key(FL_Shift_R)) == 0) + if ((get_key(FL_Shift_L) | get_key(FL_Shift_R)) == 0) gSpecialKeys |= MT_SHIFT; - if (Fl::get_key(FL_Up) == 0) + if (get_key(FL_Up) == 0) gSpecialKeys |= MT_UP; break; case FL_Page_Down: - if ((Fl::get_key(FL_Shift_L) | Fl::get_key(FL_Shift_R)) == 0) + if ((get_key(FL_Shift_L) | get_key(FL_Shift_R)) == 0) gSpecialKeys |= MT_SHIFT; - if (Fl::get_key(FL_Down) == 0) + if (get_key(FL_Down) == 0) gSpecialKeys |= MT_DOWN; break; case FL_F+1: @@ -3579,7 +3592,7 @@ int T100_Disp::handle(int event) // Handle the '^' key (Shift 6) if (key == '6') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys &= ~MT_SHIFT; gKeyStates['6'] = 0; @@ -3594,7 +3607,7 @@ int T100_Disp::handle(int event) // Handle the '"' key (shift ') if (key == '\'') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys &= ~MT_SHIFT; gKeyStates['\''] = 0; @@ -3611,7 +3624,7 @@ int T100_Disp::handle(int event) // Handle the '+' and '=' keys if (key == '=') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys &= ~MT_SHIFT; gKeyStates[';'] = 0; @@ -3629,7 +3642,7 @@ int T100_Disp::handle(int event) { gKeyStates['8'] = 0; gKeyStates['9'] = 0; - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) gSpecialKeys &= ~MT_SHIFT; else gSpecialKeys |= MT_SHIFT; @@ -3639,7 +3652,7 @@ int T100_Disp::handle(int event) { gKeyStates['9'] = 0; gKeyStates['0'] = 0; - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) gSpecialKeys &= ~MT_SHIFT; else gSpecialKeys |= MT_SHIFT; @@ -3649,7 +3662,7 @@ int T100_Disp::handle(int event) { gKeyStates['-'] = 0; gKeyStates['0'] = 0; - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) gSpecialKeys &= ~MT_SHIFT; else gSpecialKeys |= MT_SHIFT; @@ -3659,7 +3672,7 @@ int T100_Disp::handle(int event) { gKeyStates[';'] = 0; gKeyStates[':'] = 0; - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) gSpecialKeys &= ~MT_SHIFT; else gSpecialKeys |= MT_SHIFT; @@ -3669,7 +3682,7 @@ int T100_Disp::handle(int event) { gKeyStates['8'] = 0; gKeyStates[':'] = 0; - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) gSpecialKeys &= ~MT_SHIFT; else gSpecialKeys |= MT_SHIFT; @@ -3679,7 +3692,7 @@ int T100_Disp::handle(int event) { gKeyStates['7'] = 0; gKeyStates['6'] = 0; - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) gSpecialKeys &= ~MT_SHIFT; else gSpecialKeys |= MT_SHIFT; @@ -3689,7 +3702,7 @@ int T100_Disp::handle(int event) { gKeyStates['2'] = 0; gKeyStates['@'] = 0; - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) gSpecialKeys &= ~MT_SHIFT; else gSpecialKeys |= MT_SHIFT; @@ -3713,7 +3726,7 @@ int T100_Disp::handle(int event) // Handle the '^' key (Shift 6) if (key == '6') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys &= ~MT_SHIFT; gKeyStates['6'] = 0; @@ -3735,7 +3748,7 @@ int T100_Disp::handle(int event) { gKeyStates['7'] = 0; gKeyStates['6'] = 0; - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) gSpecialKeys &= ~MT_SHIFT; else gSpecialKeys |= MT_SHIFT; @@ -3745,7 +3758,7 @@ int T100_Disp::handle(int event) { gKeyStates['8'] = 0; gKeyStates['9'] = 0; - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) gSpecialKeys &= ~MT_SHIFT; else gSpecialKeys |= MT_SHIFT; @@ -3755,7 +3768,7 @@ int T100_Disp::handle(int event) { gKeyStates['9'] = 0; gKeyStates['0'] = 0; - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) gSpecialKeys &= ~MT_SHIFT; else gSpecialKeys |= MT_SHIFT; @@ -3765,7 +3778,7 @@ int T100_Disp::handle(int event) { gKeyStates['8'] = 0; gKeyStates[':'] = 0; - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) gSpecialKeys &= ~MT_SHIFT; else gSpecialKeys |= MT_SHIFT; @@ -3773,7 +3786,7 @@ int T100_Disp::handle(int event) // Handle the '_' key if (key == '-') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gKeyStates['-'] = 0; gKeyStates['0'] = 0; @@ -3791,7 +3804,7 @@ int T100_Disp::handle(int event) { gKeyStates[';'] = 0; gKeyStates[':'] = 0; - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) gSpecialKeys &= ~MT_SHIFT; else gSpecialKeys |= MT_SHIFT; @@ -3799,7 +3812,7 @@ int T100_Disp::handle(int event) // Handle the '"' key (shift ') if (key == '\'') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys &= ~MT_SHIFT; gKeyStates['\''] = 0; @@ -3818,7 +3831,7 @@ int T100_Disp::handle(int event) { if (key == ']') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys |= MT_GRAPH; gSpecialKeys &= ~MT_SHIFT; @@ -3833,7 +3846,7 @@ int T100_Disp::handle(int event) } if (key == '[') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys |= MT_GRAPH; gSpecialKeys &= ~MT_SHIFT; @@ -3848,7 +3861,7 @@ int T100_Disp::handle(int event) } if (key == '\\') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys |= MT_GRAPH; gKeyStates[';'] = 0; @@ -4001,7 +4014,7 @@ int T100_Disp::handle(int event) // Handle the '^' key (Shift 6) if (key == '6') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gKeyStates['6'] = 0; gKeyStates['@'] = 1; @@ -4015,7 +4028,7 @@ int T100_Disp::handle(int event) // Handle the '"' key (Shift ') if (key == '\'') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gKeyStates['\''] = 0; gKeyStates['2'] = 1; @@ -4030,7 +4043,7 @@ int T100_Disp::handle(int event) // Handle the '+' and '=' keys if (key == '=') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gKeyStates['='] = 0; gKeyStates[';'] = 1; @@ -4045,7 +4058,7 @@ int T100_Disp::handle(int event) // Handle the '(' key if (key == '9') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gKeyStates['9'] = 0; gKeyStates['8'] = 1; @@ -4054,7 +4067,7 @@ int T100_Disp::handle(int event) // Handle the '(' key if (key == '0') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gKeyStates['0'] = 0; gKeyStates['9'] = 1; @@ -4063,7 +4076,7 @@ int T100_Disp::handle(int event) // Handle the '_' key if (key == '-') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gKeyStates['-'] = 0; gKeyStates['0'] = 1; @@ -4072,7 +4085,7 @@ int T100_Disp::handle(int event) // Handle the ':' key if (key == ';') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys |= MT_SHIFT; gKeyStates[';'] = 0; @@ -4082,7 +4095,7 @@ int T100_Disp::handle(int event) // Handle the '*' key if (key == '8') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gKeyStates['8'] = 0; gKeyStates[':'] = 1; @@ -4091,7 +4104,7 @@ int T100_Disp::handle(int event) // Handle the '&' key if (key == '7') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gKeyStates['7'] = 0; gKeyStates['6'] = 1; @@ -4100,7 +4113,7 @@ int T100_Disp::handle(int event) // Handle the '@' key if (key == '2') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys |= MT_SHIFT; gKeyStates['2'] = 0; @@ -4113,7 +4126,7 @@ int T100_Disp::handle(int event) // Handle the '@' key if (key == '2') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys |= MT_SHIFT; gKeyStates['2'] = 0; @@ -4123,7 +4136,7 @@ int T100_Disp::handle(int event) // Handle the '#' key if (key == '3') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys &= ~MT_GRAPH; gKeyStates['3'] = 0; @@ -4133,7 +4146,7 @@ int T100_Disp::handle(int event) // Handle the '^' key (Shift 6) if (key == '6') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys |= MT_SHIFT; gKeyStates['6'] = 0; @@ -4146,7 +4159,7 @@ int T100_Disp::handle(int event) } if (key == '`') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys &= ~MT_SHIFT; gKeyStates['`'] = 0; @@ -4162,7 +4175,7 @@ int T100_Disp::handle(int event) // Handle the '&' key if (key == '7') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gKeyStates['7'] = 0; gKeyStates['6'] = 1; @@ -4171,7 +4184,7 @@ int T100_Disp::handle(int event) // Handle the '(' key if (key == '9') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gKeyStates['9'] = 0; gKeyStates['8'] = 1; @@ -4180,7 +4193,7 @@ int T100_Disp::handle(int event) // Handle the '(' key if (key == '0') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gKeyStates['0'] = 0; gKeyStates['9'] = 1; @@ -4189,7 +4202,7 @@ int T100_Disp::handle(int event) // Handle the '*' key if (key == '8') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gKeyStates['8'] = 0; gKeyStates[':'] = 1; @@ -4198,7 +4211,7 @@ int T100_Disp::handle(int event) // Handle the '_' key if (key == '-') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gKeyStates['-'] = 0; gKeyStates['0'] = 1; @@ -4206,7 +4219,7 @@ int T100_Disp::handle(int event) } if (key == '=') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys &= ~MT_SHIFT; gKeyStates['='] = 0; @@ -4222,7 +4235,7 @@ int T100_Disp::handle(int event) // Handle the ':' key if (key == ';') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys |= MT_SHIFT; gKeyStates[';'] = 0; @@ -4232,7 +4245,7 @@ int T100_Disp::handle(int event) // Handle the '"' key (Shift ') if (key == '\'') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gKeyStates['\''] = 0; gKeyStates['2'] = 1; @@ -4249,7 +4262,7 @@ int T100_Disp::handle(int event) { if (key == ']') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys &= ~MT_GRAPH; gSpecialKeys |= MT_SHIFT; @@ -4265,7 +4278,7 @@ int T100_Disp::handle(int event) } if (key == '[') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys &= ~MT_GRAPH; gSpecialKeys |= MT_SHIFT; @@ -4275,7 +4288,7 @@ int T100_Disp::handle(int event) } if (key == '`') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys &= ~MT_GRAPH; gSpecialKeys &= ~MT_SHIFT; @@ -4291,7 +4304,7 @@ int T100_Disp::handle(int event) } if (key == '\\') { - if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) + if (get_key(FL_Shift_L) || get_key(FL_Shift_R)) { gSpecialKeys &= ~MT_GRAPH; gSpecialKeys &= ~MT_SHIFT; @@ -4810,6 +4823,10 @@ void init_other_windows(void) { int memedit_was_open, cpuregs_was_open, ide_was_open; + // Test if we are in no GUI mode or not + if (gNoGUI) + return; + /* Load the open state of various windows */ virtualt_prefs.get("WindowState_MemEdit", memedit_was_open, 0); virtualt_prefs.get("WindowState_CpuRegs", cpuregs_was_open, 0); diff --git a/src/lpt.cpp b/src/lpt.cpp index fbe3a63..91ff7cc 100644 --- a/src/lpt.cpp +++ b/src/lpt.cpp @@ -49,6 +49,7 @@ #include #include "VirtualT.h" +#include "m100emu.h" #include "lpt.h" #include "printer.h" #include "fileprint.h" @@ -404,6 +405,10 @@ Initialize the printer subsystem */ void init_lpt(void) { + // Test if we are in No-GUI mode + if (gNoGUI) + return; + // If the LPT object doesn't exist, create it if (gLpt == NULL) { diff --git a/src/m100emu.c b/src/m100emu.c index 42508cd..9e2df9f 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -43,6 +43,7 @@ #include #include #include +#include #endif #include "VirtualT.h" @@ -151,6 +152,8 @@ char gLastWasSingleStep = 0; debug_monitor_callback gpDebugMonitors[3] = { NULL, NULL, NULL }; void periph_mon_update_lpt_log(void); +#define NB_ENABLE 1 +#define NB_DISABLE 2 #ifdef WIN32 void CALLBACK ThrottleProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) @@ -362,6 +365,38 @@ void throttle(int cy) last_instruct = 0; } +/* +======================================================================== +nonblock: Set / disable non-blocking terminal mode +======================================================================== +*/ +#ifdef __unix__ +void nonblock(int state) +{ + struct termios ttystate; + + return; + /* Get the terminal state */ + tcgetattr(STDIN_FILENO, &ttystate); + + if (state == NB_ENABLE) + { + /* Turn off canonical mode */ + ttystate.c_lflag &= ~ICANON; + + /* Minimum input read size */ + ttystate.c_cc[VMIN] = 1; + } + else if (state == NB_DISABLE) + { + ttystate.c_lflag |= ICANON; + } + + /* Set the terminal attributes */ + tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); +} +#endif + /* ============================================================================= This routine bails from the app in case of a panic. @@ -373,10 +408,12 @@ void bail(char *msg) endtime=msclock(); puts(msg); - printf("%-22s A:%02X F:%02X B:%02X C:%02X D:%02X E:%02X H:%02X L:%02X PC:%04X SP:%04X IM:%02X *SP:%04X\n",op,A,F,B,C,D,E,H,L,PC,SP,IM,MEM16(SP)); + printf("A:%02X F:%02X B:%02X C:%02X D:%02X E:%02X H:%02X L:%02X PC:%04X SP:%04X IM:%02X *SP:%04X\n",A,F,B,C,D,E,H,L,PC,SP,IM,MEM16(SP)); printf("Start: %d End: %d\n",starttime,endtime); printf("Time: %f\n",((double)(endtime-starttime))/1000); printf("MHz: %f\n",((UINT64)cycles/(((double)(endtime-starttime))/1000))/1000000); + + nonblock(NB_DISABLE); exit(1); } @@ -1069,7 +1106,6 @@ void maint(void) gInMsPlanROM--; } - /* ======================================================================== This routine checks if there are any active debug monitors and calls @@ -1237,7 +1273,10 @@ void emulate(void) if(!(--nxtmaint & 0x3FF)) #endif { + /* Perform maintenance with remote interface unlocked */ unlock_remote(); + + /* Do normal maintenance stuff */ gOsDelay = nxtmaint == 0; throttle(cycle_delta); maint(); @@ -1333,6 +1372,9 @@ void setup_unix_signals(void) signal(SIGHUP,handle_sig); signal(SIGQUIT,handle_sig); signal(SIGINT,handle_sig); + + /* Enable non-blocking terminal mode */ + nonblock(NB_ENABLE); #endif } @@ -1497,5 +1539,9 @@ int main(int argc, char **argv) deinit_display(); /* Deinitialze and free the main window */ free_mem(); /* Free memory used by ReMem and/or Rampac */ +#ifdef __unix__ + nonblock(NB_DISABLE); +#endif + return 0; } diff --git a/src/remote.cpp b/src/remote.cpp index 30746e7..f5e0523 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -32,7 +32,11 @@ #include #include #include +#include #include +#include +#include +#include using namespace std; @@ -64,6 +68,8 @@ HANDLE gRemoteLock; // Lock to access emulation #else pthread_t gRemoteThread; // The remote control thread pthread_mutex_t gRemoteLock; // Lock to access emulation +pthread_t gConsoleThread; // The console control thread +//pthread_mutex_t gConsoleLock; // Lock to access emulation #endif int gRadix = 10; // Radix used for reporting values @@ -97,6 +103,8 @@ std::string gOk = "Ok"; std::string gParamError = "Parameter Error\nOk"; std::string gTelnetCmd; +ConsoleSocket gConsole; + // Socket interface management structure typedef struct { @@ -167,6 +175,7 @@ std::string cmd_help(ServerSocket& sock) sock << " halt" << gLineTerm; sock << " in port" << gLineTerm; sock << " key(k) [enter cr f1 esc ctrl+c shift+code+a \"Text\" ...]" << gLineTerm; + sock << " kill filename" << gLineTerm; sock << " lcd_ignore(li) [none (row,col)-(row,col)]" << gLineTerm; sock << " lcd_mon(lm) [on off]" << gLineTerm; sock << " list_break(lb)" << gLineTerm; @@ -1989,6 +1998,83 @@ std::string cmd_model(ServerSocket& sock, std::string& args) return gOk; } +//============================================================================= +void DoFormatting(std::string& sF, const char* sformat, va_list marker) +{ + char *s, ch=0; + int n, i=0, m; + long l; + double d; + std::string sf = sformat; + std::stringstream ss; + + m = sf.length(); + while (i 0) + ret = process_command(gConsole, cmdLine, cmdLen, TRUE); + else + { + gConsole << "Ok> "; + } + + // Reset the command length + cmdLen = 0; + + // Test for "bye" command + if (gSocket.closeSocket) + { + gExitLoop = TRUE; + gExitApp = TRUE; + } + + // Display the result on the console` + gConsole << ret; + + if (ret == "Syntax error") + gConsole << "\nOk> "; + } + } + else + { + printf("Command line too long. Terminated\n"); + cmdLen = 0; + } + } + + return NULL; +} + /* ======================================================= Tears down the remote control socket inerface. @@ -3289,6 +3449,7 @@ void init_remote(void) } } + // Create a thread for remote socket control gRemoteThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) remote_control, NULL, 0, &id); @@ -3300,7 +3461,11 @@ void init_remote(void) pthread_mutex_init(&gRemoteLock, NULL); } + // Create a thread for socket control pthread_create(&gRemoteThread, NULL, remote_control, NULL); + + // Create a thread for console control + pthread_create(&gConsoleThread, NULL, console_control, NULL); #endif // Set Init flag so we only init once @@ -3486,3 +3651,73 @@ void load_remote_preferences() gSocket.enabled = enabled; gSocket.telnet = telnet; } + +/* +======================================================= +Handles user input at the console +======================================================= +*/ +void remote_process_console_input(void) +{ + int ch; + static char cmdLine[256]; + static char cmdLen = 0; + std::string ret; + + // Get the character from the console + while (1) + { + // Get next character + ch = fgetc(stdin); + + // Validate command length + if (cmdLen < sizeof(cmdLine)-1) + { + // Append the character to the command line + cmdLine[cmdLen++] = ch; + + // Test for enter + if (ch == '\n') + { + // Remove the \n from the command + cmdLen--; + cmdLine[cmdLen] = '\0'; + + // Process the command line + if (cmdLen > 0) + ret = process_command(gConsole, cmdLine, cmdLen, TRUE); + else + { + gConsole << "Ok> "; + return; + } + + // Reset the command length + cmdLen = 0; + + // Test for "bye" command + if (gSocket.closeSocket) + { + gExitLoop = TRUE; + gExitApp = TRUE; + } + + // Display the result on the console` + gConsole << ret; + + if (ret == "Syntax error") + gConsole << "\nOk> "; + + return; + } + } + else + { + printf("Command line too long. Terminated\n"); + cmdLen = 0; + return; + } + + } +} + diff --git a/src/remote.h b/src/remote.h index 9098c8c..c916f52 100644 --- a/src/remote.h +++ b/src/remote.h @@ -54,6 +54,7 @@ int get_remote_enabled(void); void set_remote_port(int port); void set_remote_telnet(int telnet); void load_remote_preferences(); +void remote_process_console_input(void); #ifdef __cplusplus } diff --git a/src/serversocket.cpp b/src/serversocket.cpp index 309ef18..42b1e09 100644 --- a/src/serversocket.cpp +++ b/src/serversocket.cpp @@ -1,8 +1,11 @@ // Implementation of the ServerSocket class +#include +#include #include "serversocket.h" #include "socketexception.h" +using namespace std; ServerSocket::ServerSocket ( int port ) { @@ -70,3 +73,27 @@ int ServerSocket::recv ( char* rxBuf, int rxLen ) const } return ret; } + +/* +============================================================================== +ConsoleSocket print function +============================================================================== +*/ +const ConsoleSocket& ConsoleSocket::operator << ( const std::string& s ) const +{ + // Print to stdout + printf("%s", s.c_str()); + fflush(stdout); + //cout << s; + + return *this; + +} + + +const ConsoleSocket& ConsoleSocket::operator >> ( std::string& s ) const +{ + cin >> s; + return *this; +} + diff --git a/src/serversocket.h b/src/serversocket.h index 3b9a74e..1efa42f 100644 --- a/src/serversocket.h +++ b/src/serversocket.h @@ -14,8 +14,8 @@ class ServerSocket : private Socket ServerSocket (){}; virtual ~ServerSocket(); - const ServerSocket& operator << ( const std::string& ) const; - const ServerSocket& operator >> ( std::string& ) const; + virtual const ServerSocket& operator << ( const std::string& ) const; + virtual const ServerSocket& operator >> ( std::string& ) const; void accept ( ServerSocket& ); @@ -24,5 +24,13 @@ class ServerSocket : private Socket }; +class ConsoleSocket : public ServerSocket +{ +public: + ConsoleSocket() {} + + virtual const ConsoleSocket& operator << ( const std::string& ) const; + virtual const ConsoleSocket& operator >> ( std::string& ) const; +}; #endif From 25f88fff4a86d867fc949554e1807fa04283483f Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 17 Feb 2013 01:35:55 +0000 Subject: [PATCH 231/327] Removed unused nonblock routine from m100emu.c. --- src/m100emu.c | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/src/m100emu.c b/src/m100emu.c index 9e2df9f..ef4f9d3 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -365,38 +365,6 @@ void throttle(int cy) last_instruct = 0; } -/* -======================================================================== -nonblock: Set / disable non-blocking terminal mode -======================================================================== -*/ -#ifdef __unix__ -void nonblock(int state) -{ - struct termios ttystate; - - return; - /* Get the terminal state */ - tcgetattr(STDIN_FILENO, &ttystate); - - if (state == NB_ENABLE) - { - /* Turn off canonical mode */ - ttystate.c_lflag &= ~ICANON; - - /* Minimum input read size */ - ttystate.c_cc[VMIN] = 1; - } - else if (state == NB_DISABLE) - { - ttystate.c_lflag |= ICANON; - } - - /* Set the terminal attributes */ - tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); -} -#endif - /* ============================================================================= This routine bails from the app in case of a panic. @@ -413,7 +381,6 @@ void bail(char *msg) printf("Time: %f\n",((double)(endtime-starttime))/1000); printf("MHz: %f\n",((UINT64)cycles/(((double)(endtime-starttime))/1000))/1000000); - nonblock(NB_DISABLE); exit(1); } @@ -1373,8 +1340,6 @@ void setup_unix_signals(void) signal(SIGQUIT,handle_sig); signal(SIGINT,handle_sig); - /* Enable non-blocking terminal mode */ - nonblock(NB_ENABLE); #endif } @@ -1539,9 +1504,5 @@ int main(int argc, char **argv) deinit_display(); /* Deinitialze and free the main window */ free_mem(); /* Free memory used by ReMem and/or Rampac */ -#ifdef __unix__ - nonblock(NB_DISABLE); -#endif - return 0; } From 2b552c79e3e23194549a0d3a31c9b6b923027d8c Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 17 Feb 2013 22:13:25 +0000 Subject: [PATCH 232/327] Updates to add command line debugging to Windows build. --- src/cpuregs.cpp | 22 +++++++-- src/display.cpp | 27 ++++++++++++ src/m100emu.c | 12 ++--- src/remote.cpp | 115 ++++++++++++++++++++++++++++++++++++------------ src/remote.h | 3 +- 5 files changed, 139 insertions(+), 40 deletions(-) diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index 0a9e0f1..1b66f05 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -1459,7 +1459,7 @@ int remote_cpureg_stop(void) { if (gcpuw != NULL) { - cb_debug_stop(NULL, NULL); + cb_debug_stop(NULL, gcpuw); return 1; } return 0; @@ -1468,7 +1468,7 @@ int remote_cpureg_run(void) { if (gcpuw != NULL) { - cb_debug_run(NULL, NULL); + cb_debug_run(NULL, gcpuw); return 1; } return 0; @@ -1477,7 +1477,7 @@ int remote_cpureg_step(void) { if (gcpuw != NULL) { - cb_debug_step(NULL, NULL); + cb_debug_step(NULL, gcpuw); return 1; } return 0; @@ -3197,6 +3197,22 @@ void VTCpuRegs::LoadPrefs(void) virtualt_prefs.get("CpuRegs_showAs16Bit", m_showAs16Bit, 0); virtualt_prefs.get("CpuRegs_colorSyntaxHilight", m_colorSyntaxHilight, 1); + // Validate the x,y coords + int screenX, screenY, screenW, screenH; + Fl::screen_xywh(screenX, screenY, screenW, screenH); + if (m_x < 5) + m_x = 30; + if (m_y < 5) + m_y = 30; + if (m_x > screenW) + m_x = screenW - 200; + if (m_y > screenH) + m_y = screenH - 200; + if (m_w > screenW) + m_w = screenW - 100; + if (m_h > screenH) + m_h = screenH - 100; + if (m_saveBreakpoints) { virtualt_prefs.get("CpuRegs_break1", str, "", sizeof(str)); diff --git a/src/display.cpp b/src/display.cpp index f0cf9cf..7124a53 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -66,6 +66,7 @@ #include "clock.h" #include "fileview.h" #include "romstrings.h" +#include "remote.h" //#include "tpddclient.h" @@ -114,6 +115,7 @@ int gDetailColor = FL_WHITE; int gBackgroundColor = FL_GRAY; int gPixelColor = FL_BLACK; int gLabelColor = FL_WHITE; +int gConsoleDebug = FALSE; Fl_Double_Window* gDisplayColors; Fl_Button* gLcdBkButton; @@ -1037,6 +1039,28 @@ void cb_display_colors (Fl_Widget* w, void*) gDisplayColors = NULL; } +#ifdef WIN32 +void cb_ConsoleDebug(Fl_Widget* w, void* pOpaque) +{ + if (!gConsoleDebug) + { +#ifndef _DEBUG + // Allocate a console + AllocConsole(); + freopen("conin$", "r", stdin); + freopen("conout$", "w", stdout); + freopen("conout$", "w", stderr); +#endif + + // Start the console control thread + remote_start_console_thread(); + + // Indicate we have console debugging active + gConsoleDebug = TRUE; + } +} +#endif + /* ======================================================= cb_help: This routine displays the Help Subsystem @@ -1253,6 +1277,9 @@ Fl_Menu_Item menuitems[] = { { "Assembler / IDE", 0, cb_Ide}, { "Disassembler", 0, disassembler_cb }, { "Memory Editor", 0, cb_MemoryEditor }, +#ifdef WIN32 + { "Enable Console Debug", 0, cb_ConsoleDebug }, +#endif { "ReMem Configuration", 0, cb_RememCfg, 0, 0 }, { "Peripheral Devices", 0, cb_PeripheralDevices }, { "Model T File Viewer", 0, cb_FileView }, diff --git a/src/m100emu.c b/src/m100emu.c index ef4f9d3..cd5ebf6 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -43,7 +43,6 @@ #include #include #include -#include #endif #include "VirtualT.h" @@ -152,8 +151,6 @@ char gLastWasSingleStep = 0; debug_monitor_callback gpDebugMonitors[3] = { NULL, NULL, NULL }; void periph_mon_update_lpt_log(void); -#define NB_ENABLE 1 -#define NB_DISABLE 2 #ifdef WIN32 void CALLBACK ThrottleProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) @@ -376,7 +373,7 @@ void bail(char *msg) endtime=msclock(); puts(msg); - printf("A:%02X F:%02X B:%02X C:%02X D:%02X E:%02X H:%02X L:%02X PC:%04X SP:%04X IM:%02X *SP:%04X\n",A,F,B,C,D,E,H,L,PC,SP,IM,MEM16(SP)); + printf("%-22s A:%02X F:%02X B:%02X C:%02X D:%02X E:%02X H:%02X L:%02X PC:%04X SP:%04X IM:%02X *SP:%04X\n",op,A,F,B,C,D,E,H,L,PC,SP,IM,MEM16(SP)); printf("Start: %d End: %d\n",starttime,endtime); printf("Time: %f\n",((double)(endtime-starttime))/1000); printf("MHz: %f\n",((UINT64)cycles/(((double)(endtime-starttime))/1000))/1000000); @@ -1073,6 +1070,7 @@ void maint(void) gInMsPlanROM--; } + /* ======================================================================== This routine checks if there are any active debug monitors and calls @@ -1240,10 +1238,7 @@ void emulate(void) if(!(--nxtmaint & 0x3FF)) #endif { - /* Perform maintenance with remote interface unlocked */ unlock_remote(); - - /* Do normal maintenance stuff */ gOsDelay = nxtmaint == 0; throttle(cycle_delta); maint(); @@ -1339,7 +1334,6 @@ void setup_unix_signals(void) signal(SIGHUP,handle_sig); signal(SIGQUIT,handle_sig); signal(SIGINT,handle_sig); - #endif } @@ -1466,7 +1460,7 @@ int main(int argc, char **argv) { if (process_args(argc, argv)) /* Parse command line args */ return 1; - + setup_working_path(argv); /* Create a working dir path */ setup_unix_signals(); /* Setup Unix signal handling */ diff --git a/src/remote.cpp b/src/remote.cpp index f5e0523..3723f28 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -43,7 +43,9 @@ using namespace std; #include #ifdef WIN32 +#include #include +#include #else #include #endif @@ -64,6 +66,7 @@ using namespace std; #ifdef WIN32 HANDLE gRemoteThread; // The remote control thread +HANDLE gConsoleThread = NULL;// The console control thread HANDLE gRemoteLock; // Lock to access emulation #else pthread_t gRemoteThread; // The remote control thread @@ -3249,9 +3252,9 @@ Handles user input at the console */ void* console_control(void* pArg) { - int ch; static char cmdLine[256]; - static char cmdLen = 0; + static int cmdLen = 0; + static int cmdReady = 0; std::string ret; // Check if no-GUI mode enabled @@ -3260,8 +3263,33 @@ void* console_control(void* pArg) // Get the character from the console while (!gExitApp && !gSocket.socketShutdown && !gSocket.closeSocket) { +#ifdef WIN32 + int kbdlen; + + // Test for input from console + kbdlen = _kbhit(); + + // If no input, sleep + if (!kbdlen) + Sleep(20); + else + { + // Read characters into cmdLine + cin.getline(cmdLine, sizeof(cmdLine)); + cmdReady = TRUE; + cmdLen = strlen(cmdLine); + } + + // Test for enter + if (cmdLine[cmdLen-1] == '\n') + { + // Remove enter from the command line + cmdLine[cmdLen-1] = '\0'; + cmdReady = TRUE; + } +#else // Get next character - ch = fgetc(stdin); + int ch = fgetc(stdin); // Validate command length if (cmdLen < sizeof(cmdLine)-1) @@ -3275,30 +3303,7 @@ void* console_control(void* pArg) // Remove the \n from the command cmdLen--; cmdLine[cmdLen] = '\0'; - - // Process the command line - if (cmdLen > 0) - ret = process_command(gConsole, cmdLine, cmdLen, TRUE); - else - { - gConsole << "Ok> "; - } - - // Reset the command length - cmdLen = 0; - - // Test for "bye" command - if (gSocket.closeSocket) - { - gExitLoop = TRUE; - gExitApp = TRUE; - } - - // Display the result on the console` - gConsole << ret; - - if (ret == "Syntax error") - gConsole << "\nOk> "; + cmdReady = TRUE; } } else @@ -3306,6 +3311,39 @@ void* console_control(void* pArg) printf("Command line too long. Terminated\n"); cmdLen = 0; } +#endif + if (cmdReady) + { + // Process the command line + if (cmdLen > 0) + { + // Process the command + ret = process_command(gConsole, cmdLine, cmdLen, TRUE); + + // Display the result on the console` + gConsole << ret; + } + else + { + gConsole << "Ok> "; + } + + // Reset the command length + cmdLen = 0; + cmdReady = FALSE; + + // Test for "bye" command + if (gSocket.closeSocket) + { + gExitLoop = TRUE; + gExitApp = TRUE; + } + + fflush(stdout); + + if (ret == "Syntax error") + gConsole << "\nOk> "; + } } return NULL; @@ -3349,6 +3387,12 @@ void deinit_remote(void) gSocket.socketOpened = FALSE; } + // Kill the console thread +#if WIN32 + if (gConsoleThread != NULL) + remote_kill_console_thread(); +#endif + // Wait for the thread to report shutdown int retry = 0; while (retry < 200) @@ -3359,6 +3403,23 @@ void deinit_remote(void) } } +#ifdef WIN32 +void remote_start_console_thread(void) +{ + DWORD id; + + // Create a thread for console control + gConsoleThread = CreateThread( NULL, 0, + (LPTHREAD_START_ROUTINE) console_control, + NULL, 0, &id); +} + +void remote_kill_console_thread(void) +{ + TerminateThread(gConsoleThread, 0); +} +#endif + /* ======================================================= Configure remote control using sockets inerface. diff --git a/src/remote.h b/src/remote.h index c916f52..1cc82fb 100644 --- a/src/remote.h +++ b/src/remote.h @@ -54,7 +54,8 @@ int get_remote_enabled(void); void set_remote_port(int port); void set_remote_telnet(int telnet); void load_remote_preferences(); -void remote_process_console_input(void); +void remote_start_console_thread(void); +void remote_kill_console_thread(void); #ifdef __cplusplus } From 12efe6824811f0c1926ad7b9f2f6c31bdf610478 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 20 Feb 2013 20:47:46 +0000 Subject: [PATCH 233/327] Added TPDD Server (NADSBox emulation). Currently only tested under Windows build and only minimal implementation, though functional. --- VirtualT.vcproj | 16 + src/MString.cpp | 207 ++++ src/MString.h | 28 + src/cpuregs.h | 1 + src/display.cpp | 1 - src/fileprint.cpp | 2 +- src/m100emu.c | 6 +- src/m100emu.h | 83 +- src/memory.c | 6 +- src/serial.c | 117 ++- src/serial.h | 9 +- src/setup.cpp | 53 +- src/setup.h | 3 +- src/strcase.c | 76 ++ src/tpddclient.cpp | 554 +---------- src/tpddclient.h | 45 +- src/tpddserver.cpp | 2351 ++++++++++++++++++++++++++++++++++++++++++++ src/tpddserver.h | 302 ++++++ 18 files changed, 3217 insertions(+), 643 deletions(-) create mode 100644 src/strcase.c create mode 100644 src/tpddserver.cpp create mode 100644 src/tpddserver.h diff --git a/VirtualT.vcproj b/VirtualT.vcproj index 27fe1c1..2035acd 100644 --- a/VirtualT.vcproj +++ b/VirtualT.vcproj @@ -677,6 +677,18 @@ /> + + + + + + @@ -1212,6 +1224,10 @@ RelativePath=".\src\tpddclient.h" > + + diff --git a/src/MString.cpp b/src/MString.cpp index 7b4c7aa..0921426 100644 --- a/src/MString.cpp +++ b/src/MString.cpp @@ -20,6 +20,9 @@ ----- $Log$ + Revision 1.3 2013/02/20 20:47:46 kpettit1 + Added TPDD Server (NADSBox emulation). Currently only tested under Windows build and only minimal implementation, though functional. + Revision 1.2 2013/02/06 17:10:33 kpettit1 Added method to MString to extract the filename portion of the string. This will cause a search for '/' or '\' and return only the filename segment. @@ -54,8 +57,14 @@ //#include //#include +#ifdef WINDOWS +#include +#endif + #include #include +#include +#include #include "MString.h" #define MIN(a,b) ((a)<(b) ? (a) : (b)) @@ -2261,5 +2270,203 @@ void MString::UnlockBuffer() { // End of BR additions +/* +========================================================================== +Linux doesn't have _splitpath, so we have to write one. +========================================================================== +*/ +#ifndef WIN32 +#define _MAX_DRIVE 4 +#define _MAX_DIR 512 +#define _MAX_FNAME 256 +#define _MAX_EXT 32 + +void _splitpath(char *path, char* pDrive, char* pDir, char* pFname, char* pExt) +{ + char* ext_ptr; + char* fname_ptr; + int fname_len, dir_len; + + // No drive letter on Linux + pDrive[0] = '\0'; + + // Get the filename + fname_ptr = strrchr(path, '\\'); + if (fname_ptr == NULL) + fname_ptr = path; + else + fname_ptr++; + ext_ptr = strrchr(fname_ptr, '.'); + if (ext_ptr != NULL) + { + fname_len = (int) (ext_ptr - fname_ptr); + strncpy(pFname, fname_ptr, fname_len); + pFname[fname_len] = '\0'; + } + else + strcpy(pFname, fname_ptr); + + // Get the extension + if (ext_ptr != NULL) + { + ext_ptr++; + strcpy(pExt, ext_ptr); + } + else + { + pExt[0] = '\0'; + } + + // Get the directory + if (fname_ptr == path) + pDir[0] = '\0'; + else + { + dir_len = (int) (fname_ptr - path); + strncpy(pDir, path, dir_len); + pDir[dir_len] = '\0'; + } +} +#endif /* WIN32 */ + +/* +========================================================================== +CFileString: Class to deal with file paths in strings +========================================================================== +*/ +MString CFileString::Filename() +{ + MString filename; + + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR*2]; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + + _splitpath( m_String.GetBuffer(m_String.GetLength() + 1), drive, dir, fname, ext ); + m_String.ReleaseBuffer(); + + filename = fname; + filename += ext; + return filename; +} + +MString CFileString::Title() +{ + MString filename; + + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR*2]; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + + _splitpath( m_String.GetBuffer(m_String.GetLength() + 1), drive, dir, fname, ext ); + m_String.ReleaseBuffer(); + + filename = fname; + return filename; +} + +MString CFileString::Ext() +{ + MString filename; + + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR*2]; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + + _splitpath( m_String.GetBuffer(m_String.GetLength() + 1), drive, dir, fname, ext ); + m_String.ReleaseBuffer(); + + filename = ext; + return filename; +} + +MString CFileString::Drive() +{ + MString filename; + + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR*2]; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + + _splitpath( m_String.GetBuffer(m_String.GetLength() + 1), drive, dir, fname, ext ); + m_String.ReleaseBuffer(); + + filename = drive; + return filename; +} + +MString CFileString::Directory() +{ + MString filename; + + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR*2]; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + + _splitpath( m_String.GetBuffer(m_String.GetLength() + 1), drive, dir, fname, ext ); + m_String.ReleaseBuffer(); + + filename = dir; + return filename; +} + +MString CFileString::FirstSubDir() +{ + MString dir = Directory(); + m_SubDirIndex = 0; + + char* ptr = dir.GetBuffer(dir.GetLength() + 1); + char* token; + + // Now find the m_SubDirIndex'th item in the path + for (int c = 0; c <= m_SubDirIndex; c++) + { + token = strtok(ptr, "\\"); + ptr = NULL; + if (token == NULL) + break; + } + MString subDir; + if (token != NULL) + { + subDir = token; + m_SubDirIndex++; + } + dir.ReleaseBuffer(); + + return subDir; +} + +MString CFileString::NextSubDir() +{ + MString dir = Directory(); + + char* ptr = dir.GetBuffer(dir.GetLength() + 1); + char* token; + + // Now find the m_SubDirIndex'th item in the path + for (int c = 0; c <= m_SubDirIndex; c++) + { + token = strtok(ptr, "\\"); + ptr = NULL; + if (token == NULL) + break; + } + MString subDir; + if (token != NULL) + { + subDir = token; + m_SubDirIndex++; + } + dir.ReleaseBuffer(); + + return subDir; +} + //End Buffer Access --------------------------------------- diff --git a/src/MString.h b/src/MString.h index d6127a4..2f8e96a 100644 --- a/src/MString.h +++ b/src/MString.h @@ -376,6 +376,34 @@ class MString { }; +/* +=========================================================================== +CFileString: Class to do special File and Directory manipulation things + with strings (because I'm tired of doing it over and over). +=========================================================================== +*/ +class CFileString +{ +public: + CFileString() { m_SubDirIndex = 0; } + CFileString(MString string) { m_String = string; m_SubDirIndex = 0; }; + + MString Filename(); // C:\DATA\SUBDIR\FILE.TXT -> FILE.TXT + MString Drive(); // C:\DATA\SUBDIR\FILE.TXT -> C: + MString Title(); // C:\DATA\SUBDIR\FILE.TXT -> FILE + MString Directory(); // C:\DATA\SUBDIR\FILE.TXT -> \\DATA\\SUBDIR\\ // + MString Ext(); // C:\DATA\SUBDIR\FILE.TXT -> .TXT + MString FirstSubDir(); // C:\DATA\SUBDIR\FILE.TXT -> DATA + MString NextSubDir(); // C:\DATA\SUBDIR\FILE.TXT -> SUBDIR ... + + MString& operator->() { return m_String; }; + CFileString& operator=(const MString& string) { m_String = string; return *this; }; + +protected: + int m_SubDirIndex; + MString m_String; +}; + #endif // __cplusplus #endif diff --git a/src/cpuregs.h b/src/cpuregs.h index ded71cb..63508dc 100644 --- a/src/cpuregs.h +++ b/src/cpuregs.h @@ -38,6 +38,7 @@ #include #include #include +#include #include "MString.h" diff --git a/src/display.cpp b/src/display.cpp index 7124a53..6fb9b53 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -67,7 +67,6 @@ #include "fileview.h" #include "romstrings.h" #include "remote.h" -//#include "tpddclient.h" extern "C" { diff --git a/src/fileprint.cpp b/src/fileprint.cpp index 9deaa03..3cab243 100644 --- a/src/fileprint.cpp +++ b/src/fileprint.cpp @@ -55,7 +55,7 @@ #include "MStringArray.h" extern "C" struct tm* mytime; -extern "C" char path[255]; + /* ================================================================================ VTFilePrint: This is the class constructor for the FilePrint Printer. diff --git a/src/m100emu.c b/src/m100emu.c index cd5ebf6..786993e 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -121,10 +121,10 @@ int gNoGUI = 0; int gRemoteSwitchModel = -1; //Added J. VERNET -char path[512]; -char file[512]; +char path[512]; +char file[512]; #ifdef __APPLE__ -char gOsxBundlePath[512]; +char gOsxBundlePath[512]; #endif extern RomDescription_t gM100_Desc; diff --git a/src/m100emu.h b/src/m100emu.h index bfeb79a..08b4e93 100644 --- a/src/m100emu.h +++ b/src/m100emu.h @@ -34,41 +34,52 @@ #include "gen_defs.h" #include "roms.h" - #ifdef __cplusplus extern "C" { #endif -extern char op[26]; -extern int trace; -extern int fullspeed; -extern volatile int gExitApp; -extern volatile int gExitLoop; -extern float cpu_speed; -extern uchar *gMemory[64]; -extern RomDescription_t *gStdRomDesc; -extern int gModel; -extern char gsOptRomFile[256]; -double hirestimer(void); -typedef void (*mem_monitor_cb)(void); -typedef void (*debug_monitor_callback)(int reason); -void mem_set_monitor_callback(mem_monitor_cb cb); -void mem_clear_monitor_callback(mem_monitor_cb cb); -int debug_set_monitor_callback(debug_monitor_callback pCallback); -void debug_clear_monitor_callback(debug_monitor_callback pCallback); -void debug_step(void); -void debug_halt(void); -void debug_run(void); -void remote_switch_model(int model); -extern char gDebugActive; -extern char gIntActive; -extern char gDebugInts; -extern char gStopped; -extern char gSingleStep; -extern int gDebugMonitorFreq; -extern int gSocketPort; -extern int gTelnet; -extern int gNoGUI; +/* Define global variables */ +extern char op[26]; +extern int trace; +extern int fullspeed; +extern volatile int gExitApp; +extern volatile int gExitLoop; +extern float cpu_speed; +extern uchar * gMemory[64]; +extern RomDescription_t *gStdRomDesc; +extern int gModel; +extern char gsOptRomFile[256]; +extern char gDebugActive; +extern char gIntActive; +extern char gDebugInts; +extern char gStopped; +extern char gSingleStep; +extern int gDebugMonitorFreq; +extern int gSocketPort; +extern int gTelnet; +extern int gNoGUI; +extern char path[512]; + +/* Define global function prototypes */ +double hirestimer(void); +typedef void (*mem_monitor_cb)(void); +typedef void (*debug_monitor_callback)(int reason); +void mem_set_monitor_callback(mem_monitor_cb cb); +void mem_clear_monitor_callback(mem_monitor_cb cb); +int debug_set_monitor_callback(debug_monitor_callback pCallback); +void debug_clear_monitor_callback(debug_monitor_callback pCallback); +void debug_step(void); +void debug_halt(void); +void debug_run(void); +void remote_switch_model(int model); +int check_model_support(int model); +void get_emulation_path(char* emu, int model); +void get_model_string(char* str, int model); +int get_model_from_string(char* str); +void get_rom_path(char* file, int model); +void init_cpu(void); +void resetcpu(void); +void cb_int65(int pinLevel); #define DEBUG_PC_CHANGED 1 #define DEBUG_CPU_HALTED 2 @@ -81,16 +92,6 @@ extern int gNoGUI; #define SPEED_FRIENDLY2 2 #define SPEED_FULL 3 -int check_model_support(int model); -void get_emulation_path(char* emu, int model); -void get_model_string(char* str, int model); -int get_model_from_string(char* str); -void get_rom_path(char* file, int model); -void init_cpu(void); -//void cpu_delay(int cy); -void resetcpu(void); -void cb_int65(int pinLevel); - #ifdef __cplusplus } #endif diff --git a/src/memory.c b/src/memory.c index b4ab730..abe1605 100644 --- a/src/memory.c +++ b/src/memory.c @@ -31,7 +31,7 @@ uchar gBaseMemory[65536]; /* System Memory */ uchar gSysROM[65536]; /* System ROM */ uchar gOptROM[32768]; /* Option ROM */ uchar gMsplanROM[32768]; /* MSPLAN ROM T200 Only */ -extern char path[255]; +//extern char path[255]; extern char file[255]; int gOptRomRW = 0; /* Flag to make OptROM R/W */ @@ -860,6 +860,10 @@ void cold_boot_mem(void) { int x; + // Reload the system ROM just in case it got over-written + load_sys_rom(); + + // Now zero out the RAM if (gReMem && (gRex == 0)) { } diff --git a/src/serial.c b/src/serial.c index 540a9ba..9b5409c 100644 --- a/src/serial.c +++ b/src/serial.c @@ -54,6 +54,7 @@ #include "serial.h" #include "setup.h" #include "display.h" +#include "tpddserver.h" ser_params_t sp; extern int gModel; @@ -106,6 +107,10 @@ int ser_init(void) sp.stop_bits = 1; // Initialize to 1 stop bit sp.pCmdFile = NULL; // No open command file + // Initialize a TPDD client context + sp.pTpddContext = tpdd_alloc_context(); + tpdd_load_prefs(sp.pTpddContext); + #ifdef WIN32 sp.tx_empty = TRUE; // Indicate no active TX sp.rxIn = 0; // Initialize Read buffer @@ -203,6 +208,9 @@ int ser_deinit(void) #endif + // Free the tpdd context + tpdd_free_context(sp.pTpddContext); + return SER_NO_ERROR; } @@ -799,6 +807,11 @@ int ser_set_baud(int baud) #endif } + else if (setup.com_mode == SETUP_COM_SIM_TPDD) + { + // Pass the simulated baud rate to the tpdd client interface + return tpdd_ser_set_baud(sp.pTpddContext, baud); + } // Check for a monitor window and report change if (sp.pMonCallback != NULL) @@ -853,6 +866,13 @@ int ser_close_port(void) fclose(sp.pCmdFile); sp.pCmdFile = NULL; } + else if (setup.com_mode == SETUP_COM_SIM_TPDD) + { + // ====================== + // Close the TPDD simulation + // ====================== + tpdd_close_serial(sp.pTpddContext); + } // Set flag indicating port not open sp.open_flag = 0; @@ -976,6 +996,14 @@ int ser_open_port(void) // Update flag indicating port open sp.open_flag = TRUE; } + else if (setup.com_mode == SETUP_COM_SIM_TPDD) + { + // Pass the open to the TPDD client interface + int ret = tpdd_open_serial(sp.pTpddContext); + if (ret == SER_NO_ERROR) + sp.open_flag = TRUE; + return ret; + } // Check for a monitor window and report change if (sp.pMonCallback != NULL) @@ -993,7 +1021,7 @@ ser_set_port: Set the active serial port for subsequent calls host serial port where all traffic will be directed. =========================================================================== */ -int ser_set_port(char* port) +int ser_set_port(const char* port) { // Save name of port for later use @@ -1315,6 +1343,22 @@ int ser_set_signals(unsigned char flags) #endif } + else if (setup.com_mode == SETUP_COM_SIM_TPDD) + { + if (flags & SER_SIGNAL_DTR) + sp.dtrState = DTR_CONTROL_ENABLE; + else + sp.dtrState = DTR_CONTROL_DISABLE; + + // Update RTS flag + if (flags & SER_SIGNAL_RTS) + sp.rtsState = RTS_CONTROL_ENABLE; + else + sp.rtsState = RTS_CONTROL_DISABLE; + + return tpdd_ser_set_signals(sp.pTpddContext, flags); + } + // Check for a monitor window and report change if (sp.pMonCallback != NULL) @@ -1397,6 +1441,12 @@ int ser_get_flags(unsigned char *flags) else if (setup.com_mode == SETUP_COM_NONE) return SER_PORT_NOT_OPEN; + // Test for TPDD client simulation + else if (setup.com_mode == SETUP_COM_SIM_TPDD) + { + return tpdd_ser_get_flags(sp.pTpddContext, flags); + } + return SER_NO_ERROR; } @@ -1484,6 +1534,24 @@ int ser_get_signals(unsigned char *flags) #endif } + // Test for TPDD Client simulation + else if (setup.com_mode == SETUP_COM_SIM_TPDD) + { + int ret; + if (sp.open_flag == 0) + { + *flags = 0; + return SER_NO_ERROR; + } + *flags = 0; + ret = tpdd_ser_get_signals(sp.pTpddContext, flags); + if (sp.rtsState == RTS_CONTROL_ENABLE) + *flags |= SER_SIGNAL_CTS; + if (sp.dtrState == DTR_CONTROL_ENABLE) + *flags |= SER_SIGNAL_DSR; + return ret; + } + return SER_NO_ERROR; } @@ -1557,6 +1625,20 @@ int ser_read_byte(char* data) #endif } + // Test for TPDD client simulation + else if (setup.com_mode == SETUP_COM_SIM_TPDD) + { + int ret = tpdd_ser_read_byte(sp.pTpddContext, data); + + // Test if this is the last byte + if (ret == SER_LAST_BYTE) + { + sp.pCallback(0); + return SER_NO_ERROR; + } + return ret; + } + // Check if there is a monitor window open and report the write if (sp.pMonCallback != NULL) sp.pMonCallback(SER_MON_COM_READ, *data); @@ -1601,6 +1683,12 @@ int ser_write_byte(char data) #endif } + // Test for TPDD client simulation + else if (setup.com_mode == SETUP_COM_SIM_TPDD) + { + return tpdd_ser_write_byte(sp.pTpddContext, data); + } + // Check if there is a monitor window open and report the write if (sp.pMonCallback != NULL) sp.pMonCallback(SER_MON_COM_WRITE, data); @@ -1617,8 +1705,23 @@ ser_poll: opportunity to invoke INT6.5 callback int ser_poll () { + // Test if in TPDD Client simulation mode + if (setup.com_mode == SETUP_COM_SIM_TPDD) + { + int ret = tpdd_ser_poll(sp.pTpddContext); + + // Test if any data available + if (ret == SER_NO_DATA) + // Clear the RS-232 interrupt line + sp.pCallback(0); + else + // Set the RS-232 interrupt line + sp.pCallback(1); + + return SER_NO_ERROR; + } - if (setup.com_mode != SETUP_COM_HOST + else if (setup.com_mode != SETUP_COM_HOST && setup.com_mode != SETUP_COM_OTHER) return 0; @@ -1640,6 +1743,16 @@ int ser_poll () return 0; #endif +} + +/* +=========================================================================== +ser_get_tpdd_context: Returns the allocated TPDD Client context +=========================================================================== +*/ +void* ser_get_tpdd_context(void) +{ + return sp.pTpddContext; } diff --git a/src/serial.h b/src/serial.h index 7338686..4d560d2 100644 --- a/src/serial.h +++ b/src/serial.h @@ -39,7 +39,8 @@ enum { SER_PORT_NOT_SELECTED, SER_TIMEOUT, SER_NO_DATA, - SER_PORT_NOT_OPEN + SER_PORT_NOT_OPEN, + SER_LAST_BYTE }; enum { @@ -89,7 +90,7 @@ int ser_set_bit_size(int bit_size); int ser_set_stop_bits(int stop_bits); int ser_set_callback(ser_callback pCallback); int ser_set_monitor_callback(ser_monitor_cb pCallback); -int ser_set_port(char* port); +int ser_set_port(const char* port); int ser_get_port_settings(char* port, int* open_state, int* baud, int* size, int* stop_bits, char* parity); int ser_poll(); @@ -104,6 +105,9 @@ int ser_get_signals(unsigned char *signals); int ser_read_byte(char* data); int ser_write_byte(char data); +/* Tpdd Client interface functions */ +void* ser_get_tpdd_context(void); + #ifdef __cplusplus } #endif @@ -122,6 +126,7 @@ typedef struct ser_params ser_monitor_cb pMonCallback; FILE* pCmdFile; // Command file for Simulated I/O + void* pTpddContext; // The TPDD client context // Host COM port control structures diff --git a/src/setup.cpp b/src/setup.cpp index 4f1b278..69b8979 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -50,6 +50,7 @@ #include "lpt.h" #include "clock.h" #include "cpu.h" +#include "tpddserver.h" extern Fl_Preferences virtualt_prefs; void init_menus(void); @@ -64,6 +65,7 @@ typedef struct setup_ctrl_struct Fl_Round_Button* pNone; Fl_Round_Button* pSim; Fl_Input* pCmd; + Fl_Button* pTpddConfig; Fl_Round_Button* pHost; Fl_Choice* pPort; Fl_Round_Button* pOther; @@ -157,6 +159,8 @@ void save_setup_preferences(void) virtualt_prefs.set("ComPort", setup.com_port); virtualt_prefs.set("ComOther", setup.com_other); virtualt_prefs.set("ComIgnoreFlow", setup.com_ignore_flow); + if (setup.com_mode == SETUP_COM_SIM_TPDD) + tpdd_save_prefs(ser_get_tpdd_context()); // Save LPT emulation settings save_lpt_preferences(&virtualt_prefs); @@ -306,7 +310,10 @@ void cb_setup_OK(Fl_Widget* w, void*) // =========================== // Get COM options // =========================== - strcpy(setup.com_cmd, setup_ctrl.com.pCmd->value()); + if (setup_ctrl.com.pCmd != NULL) + strcpy(setup.com_cmd, setup_ctrl.com.pCmd->value()); + else + setup.com_cmd[0] = '\0'; if (setup_ctrl.com.pPort->text() != NULL) strcpy(setup.com_port, setup_ctrl.com.pPort->text()); else @@ -321,8 +328,9 @@ void cb_setup_OK(Fl_Widget* w, void*) else if (setup_ctrl.com.pSim->value() == 1) { // Open the Script file - ser_set_port(setup.com_cmd); - setup.com_mode = SETUP_COM_SIMULATED; +// ser_set_port(setup.com_cmd); + ser_set_port(tpdd_get_port_name(ser_get_tpdd_context())); + setup.com_mode = SETUP_COM_SIM_TPDD; ser_open_port(); } else if (setup_ctrl.com.pHost->value() == 1) @@ -410,32 +418,45 @@ Callback routines for the COM Tab */ void cb_com_radio_none (Fl_Widget* w, void*) { - setup_ctrl.com.pCmd->deactivate(); + setup_ctrl.com.pTpddConfig->deactivate(); setup_ctrl.com.pPort->deactivate(); setup_ctrl.com.pOtherName->deactivate(); } void cb_com_radio_sim (Fl_Widget* w, void*) { - setup_ctrl.com.pCmd->activate(); + setup_ctrl.com.pTpddConfig->activate(); + setup_ctrl.com.pPort->deactivate(); + setup_ctrl.com.pOtherName->deactivate(); +} + +void cb_com_radio_sim_tpdd (Fl_Widget* w, void*) +{ + setup_ctrl.com.pTpddConfig->activate(); setup_ctrl.com.pPort->deactivate(); setup_ctrl.com.pOtherName->deactivate(); } void cb_com_radio_host (Fl_Widget* w, void*) { - setup_ctrl.com.pCmd->deactivate(); + setup_ctrl.com.pTpddConfig->deactivate(); setup_ctrl.com.pPort->activate(); setup_ctrl.com.pOtherName->deactivate(); } void cb_com_radio_other (Fl_Widget* w, void*) { - setup_ctrl.com.pCmd->deactivate(); + setup_ctrl.com.pTpddConfig->deactivate(); setup_ctrl.com.pPort->deactivate(); setup_ctrl.com.pOtherName->activate(); } +void cb_com_sim_tpdd_config(Fl_Widget* w, void*) +{ + // Call the TPDD server's configure routine + tpdd_server_config(); +} + /* ============================================================================ Routine to create the PeripheralSetup Window and tabs @@ -465,6 +486,20 @@ void cb_PeripheralSetup (Fl_Widget* w, void*) setup_ctrl.com.pNone->type(FL_RADIO_BUTTON); setup_ctrl.com.pNone->callback(cb_com_radio_none); + // Create controls to select simulated TPDD client connection + setup_ctrl.com.pSim = new Fl_Round_Button(20, 65, 220, 20, "Connect to simulated NADSBox"); + setup_ctrl.com.pSim->type(FL_RADIO_BUTTON); + setup_ctrl.com.pSim->callback(cb_com_radio_sim_tpdd); + + setup_ctrl.com.pTpddConfig = new Fl_Button(50, 90, 80, 20, "Configure"); + if (setup.com_mode != SETUP_COM_SIM_TPDD) + setup_ctrl.com.pTpddConfig->deactivate(); + setup_ctrl.com.pTpddConfig->callback(cb_com_sim_tpdd_config); + + setup_ctrl.com.pCmd = NULL; + +#if 0 + // Old simulation file controls... setup_ctrl.com.pSim = new Fl_Round_Button(20, 65, 180, 20, "Use Simulated Port (not supported yet)"); setup_ctrl.com.pSim->type(FL_RADIO_BUTTON); setup_ctrl.com.pSim->callback(cb_com_radio_sim); @@ -473,7 +508,7 @@ void cb_PeripheralSetup (Fl_Widget* w, void*) if (setup.com_mode != SETUP_COM_SIMULATED) setup_ctrl.com.pCmd->deactivate(); setup_ctrl.com.pCmd->value(setup.com_cmd); - +#endif setup_ctrl.com.pHost = new Fl_Round_Button(20, 115, 180, 20, "Use Host Port"); setup_ctrl.com.pHost->type(FL_RADIO_BUTTON); setup_ctrl.com.pHost->callback(cb_com_radio_host); @@ -514,7 +549,7 @@ void cb_PeripheralSetup (Fl_Widget* w, void*) setup_ctrl.com.pNone->value(1); else if (setup.com_mode == SETUP_COM_HOST) setup_ctrl.com.pHost->value(1); - else if (setup.com_mode == SETUP_COM_SIMULATED) + else if (setup.com_mode == SETUP_COM_SIM_TPDD) setup_ctrl.com.pSim->value(1); else if (setup.com_mode == SETUP_COM_OTHER) setup_ctrl.com.pOther->value(1); diff --git a/src/setup.h b/src/setup.h index 7fd4f06..585a5fd 100644 --- a/src/setup.h +++ b/src/setup.h @@ -84,7 +84,8 @@ enum { SETUP_COM_NONE, SETUP_COM_SIMULATED, SETUP_COM_HOST, - SETUP_COM_OTHER + SETUP_COM_OTHER, + SETUP_COM_SIM_TPDD }; enum { diff --git a/src/strcase.c b/src/strcase.c new file mode 100644 index 0000000..4c2a661 --- /dev/null +++ b/src/strcase.c @@ -0,0 +1,76 @@ +/* Compare at most N characters of two strings without taking care for + the case. + Copyright (C) 1992, 1996, 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef WIN32 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#ifndef weak_alias +# define __strcasecmp strcasecmp +# define TOLOWER(Ch) tolower (Ch) +#else +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define __strcasecmp __strcasecmp_l +# define TOLOWER(Ch) __tolower_l ((Ch), loc) +# else +# define TOLOWER(Ch) tolower (Ch) +# endif +#endif + +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define LOCALE_PARAM , loc +# define LOCALE_PARAM_DECL __locale_t loc; +#else +# define LOCALE_PARAM +# define LOCALE_PARAM_DECL +#endif + +/* Compare no more than N characters of S1 and S2, + ignoring case, returning less than, equal to or + greater than zero if S1 is lexicographically less + than, equal to or greater than S2. */ +int +__strcasecmp (s1, s2) + const char *s1; + const char *s2; +{ + const unsigned char *p1 = (const unsigned char *) s1; + const unsigned char *p2 = (const unsigned char *) s2; + int result; + + if (p1 == p2 ) + return 0; + + while ((result = TOLOWER (*p1) - TOLOWER (*p2)) == 0) + if (*p1++ == '\0' || *p2++ == '\0') + break; + + return result; +} +#ifndef __strcasecmp +weak_alias (__strcasecmp, strcasecmp) +#endif + +#endif \ No newline at end of file diff --git a/src/tpddclient.cpp b/src/tpddclient.cpp index 5dd3e64..b4bb6fb 100644 --- a/src/tpddclient.cpp +++ b/src/tpddclient.cpp @@ -27,553 +27,13 @@ * SUCH DAMAGE. */ -#define TPDD_CLIENT_MAIN - -#include -#include -#include -#ifdef _WIN32 -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "roms.h" -#include "fl_usage_box.h" -#include "display.h" -#include "cpuregs.h" -#include "disassemble.h" -#include "periph.h" -#include "memedit.h" -#include "file.h" -#include "tpddclient.h" -#include "fileview.h" - -// =============================================== -// Extern "C" linkage items -// =============================================== -extern "C" -{ -#include "memory.h" -#include "m100emu.h" - -extern RomDescription_t *gStdRomDesc; -} - -// =============================================== -// Extern and global variables -// =============================================== -extern Fl_Preferences virtualt_prefs; -extern Fl_Menu_Item gCpuRegs_menuitems[]; -extern char *gKeywordTable[]; -static Fl_Window* gtcw = NULL; -tpddclient_ctrl_t gTcCtrl; - -void cb_Ide(Fl_Widget* w, void*) ; -void cb_view_refreseh(Fl_Widget*w, void*); - -// Menu items for the disassembler -Fl_Menu_Item gTpddClient_menuitems[] = { - { "&View", 0, 0, 0, FL_SUBMENU }, - { "Refresh", 0, cb_view_refreseh, 0, 0 }, - { 0 }, - { "&Tools", 0, 0, 0, FL_SUBMENU }, - { "CPU Registers", 0, cb_CpuRegs }, - { "Assembler / IDE", 0, cb_Ide }, - { "Disassembler", 0, disassembler_cb }, - { "Memory Editor", 0, cb_MemoryEditor }, - { "Peripheral Devices", 0, cb_PeripheralDevices }, - { "Model T File Viewer", 0, cb_FileView }, - { 0 }, - { 0 } -}; - -/* -============================================================================ -Callback routine for the File Viewer window -============================================================================ -*/ -void cb_tcwin (Fl_Widget* w, void*) -{ - // Hide the window - gtcw->hide(); - - // Delete the window and set to NULL - delete gtcw; - gtcw = NULL; -} - -/* -============================================================================ -Callback routine when a file is selected -============================================================================ -*/ -static void display_file(int index) -{ - int addr1, addr2, c, x, y, lineno, maxline; - char line[1000], substr[10], linefmt[6], fill[7]; - unsigned char ch; - tpdd_client_files_t *pfile; - - // First clear the text buffer -// gTcCtrl.pTb->remove(0, gTcCtrl.pTb->length()); - gTcCtrl.pView->clear(); - - // Populate with data based on file type - pfile = &gTcCtrl.tFiles[index]; - switch (pfile->type) - { - case TYPE_BA: - // Get first BASIC line pointer - addr1 = pfile->address; - - // Calculate the maximum linenumber length - while (get_memory16(addr1) != 0) - { - addr2 = addr1; - addr1 = get_memory16(addr1); - } - maxline = get_memory16(addr2+2); - if (maxline > 9999) - { - strcpy(linefmt, "%5u "); - strcpy(fill, " "); - } - else if (maxline > 999) - { - strcpy(linefmt, "%4u "); - strcpy(fill, " "); - } - else if (maxline > 99) - { - strcpy(linefmt, "%3u "); - strcpy(fill, " "); - } - else if (maxline > 9) - { - strcpy(linefmt, "%2u "); - strcpy(fill, " "); - } - else - { - strcpy(linefmt, "%1u "); - strcpy(fill, " "); - } - - // Restore pointer to beginning of file - addr1 = pfile->address; - - // Get BASIC lines until NULL - while ((addr2 = get_memory16(addr1)) != 0) - { - // Detokenize the line and save as ASCII - addr1 += 2; - line[0] = 0; - - // Print line number - lineno = get_memory16(addr1); - addr1 += 2; - sprintf(substr, linefmt, lineno); - strcat(line, substr); - - // Read remaining data & detokenize - while (addr1 < addr2) - { - // Get next byte - ch = get_memory8(addr1++); - - // Check if byte is ':' - if (ch == ':') - { - // Get next character - ch = get_memory8(addr1); - - // Check for REM tick - if (ch == 0x8E) - { - if (get_memory8(addr1+1) == 0xFF) - { - ch = '\''; - line[strlen(line)+1] = 0; - line[strlen(line)] = ch; - if (strlen(line) > 54) - { - strcat(line, "\n"); - gTcCtrl.pView->add(line); -// gTcCtrl.pTb->append(line); - strcpy(line, fill); - } - addr1 += 2; - continue; - } - } - - // Check for ELSE - if (ch == 0x91) - continue; - - ch = ':'; - line[strlen(line)+1] = 0; - line[strlen(line)] = ch; - if (strlen(line) > 54) - { - strcat(line, "\n"); - gTcCtrl.pView->add(line); -// gTcCtrl.pTb->append(line); - strcpy(line, fill); - } - } - else if (ch > 0x7F) - { - if (strlen(line) + strlen(gKeywordTable[ch & 0x7F]) > 54) - { - strcat(line, "\n"); - gTcCtrl.pView->add(line); -// gTcCtrl.pTb->append(line); - strcpy(line, fill); - } - sprintf(substr, "%s", gKeywordTable[ch & 0x7F]); - strcat(line, substr); - } - else if (ch == 0) - { - if (strlen(line) != strlen(fill)) - strcat(line, "\n"); - } - else - { - line[strlen(line)+1] = 0; - line[strlen(line)] = ch; - if (strlen(line) > 54) - { - strcat(line, "\n"); - gTcCtrl.pView->add(line); -// gTcCtrl.pTb->append(line); - strcpy(line, fill); - } - } - } -// gTcCtrl.pTb->append(line); - if (strlen(line) != strlen(fill)) - gTcCtrl.pView->add(line); - } - break; - - case TYPE_DO: - // Start at beginning of file - c = 0; - while (c < pfile->size) - { - // Y is the line input location (we skip CR) - y = 0; - // Copy up to 999 bytes into temp line storage - for (x = 0; x < 999; x++) - { - // Test if past end of file - if (x + c > pfile->size) - break; - - // Get next byte from file - line[y] = get_memory8(pfile->address + x + c); - line[y+1] = 0; - - // Write line if newline received - if (line[y] == 0x0A) - { - line[y+1] = 0; - gTcCtrl.pView->add(line); -// gTcCtrl.pTb->append(line); - y = 0; - line[0] = 0; - continue; - } - - if (strlen(line) > 55) - { - line[y+1] = '\n'; - line[y+2] = 0; -// gTcCtrl.pTb->append(line); - gTcCtrl.pView->add(line); - y = 0; - line[0] = 0; - continue; - } - - // Test for end of file - if (line[y] == 0x1A) - break; - - // If byte isn't CR, increment input location - if (line[y] != 0x0D) - y++; - } - - // Terminate the string add add to buffer - line[y] = 0; -// gTcCtrl.pTb->append(line); - gTcCtrl.pView->add(line); - - // Add this block to length processed - c += x; - } - break; - - case TYPE_CO: - x = 0; - while (x < pfile->size) - { - // Start new line - sprintf(line, "%04X: ", pfile->address + x); - - // Add up to 16 bytes to line - for (c = 0; c < 16; c++) - { - // Test if at end of line - if (x + c > pfile->size) - break; - - // Add next byte to line - sprintf(substr, "%02X ", get_memory8(pfile->address + c + x)); - strcat(line, substr); - } - - // Add line to text buffer - strcat(line, "\n"); -// gTcCtrl.pTb->append(line); - gTcCtrl.pView->add(line); - x += c; - } - break; - } -} - /* -============================================================================ -Callback routine when a file is selected -============================================================================ +=============================================================== +This file is just a placeholder. It used to incorrectly have +the TpddServer code in it, but that code has been moved to +the tpddserver.cpp file instead. Perhaps someday VirtualT +will include a TPDD Client that can talk with a physical TPDD +device on the serial port... +=============================================================== */ -static void cb_FileSelect(Fl_Widget* w, void*) -{ - int index; - tpdd_client_files_t *pfile; - - // Get selection from Hold Browser - index = ((Fl_Browser*)w)->value()-1; - if ((index < 0) || (index > gTcCtrl.tCount)) - { - // Clear the Directry Entry text - gTcCtrl.sDirEntry[0] = 0; - gTcCtrl.sAddress[0] = 0; - gTcCtrl.pAddress->label(gTcCtrl.sAddress); - gTcCtrl.pDirEntry->label(gTcCtrl.sDirEntry); -// gTcCtrl.pTb->remove(0, gTcCtrl.pTb->length()); - gTcCtrl.pView->clear(); - return; - } -} - -/* -============================================================================ -Get list of files in tFiles structure and update SelectBrowser -============================================================================ -*/ -static void get_file_list(void) -{ - int dir_index, addr1, addr2; - unsigned char file_type; - int c, x; - char mt_file[40], fdata; - - // Initialize variables - dir_index = 0; - gTcCtrl.tCount = 0; - gTcCtrl.pFileSelect->clear(); - gTcCtrl.selectIndex = -1; - - // Check for Unsved BASIC program - addr2 = get_memory16(gStdRomDesc->sFilePtrBA); -// addr2 = get_memory16(addr2); - if ((get_memory16(addr2) != 0) && (addr2 != 0)) - { - // Add entry for unsaved BASIC program - strcpy(gTcCtrl.tFiles[0].name, "Unsaved BA"); - gTcCtrl.tFiles[0].dir_address = gStdRomDesc->sFilePtrBA; - gTcCtrl.tFiles[0].address = addr2; - gTcCtrl.tFiles[0].type = TYPE_BA; - addr1 = get_memory16(addr2); - if (addr1 == 0) - { - gTcCtrl.tFiles[0].size = addr2 - get_memory16(gStdRomDesc->sFilePtrBA); - } - else - { - while ((get_memory16(addr1) != 0) && (addr1 != 0)) - { - // Point to next BASIC line - addr1 = get_memory16(addr1); - } - gTcCtrl.tFiles[0].size = addr1 - addr2; - } - - // Add file to Hold Browser - sprintf(mt_file, "%-11s %d", gTcCtrl.tFiles[gTcCtrl.tCount].name, - gTcCtrl.tFiles[gTcCtrl.tCount].size); - gTcCtrl.pFileSelect->add(mt_file); - - // Increment file count - gTcCtrl.tCount++; - } - - // Now point to the file directory - addr1 = gStdRomDesc->sDirectory; - while (dir_index < gStdRomDesc->sDirCount) - { - file_type = get_memory8(addr1); - if ((file_type != TYPE_BA) && (file_type != TYPE_DO) && - (file_type != TYPE_CO)) - { - dir_index++; - addr1 += 11; - continue; - } - - // Get the 1st part of the filename - c = 0; - for (x = 0; x < 6; x++) - { - if (get_memory8(addr1+3+x) != ' ') - mt_file[c++] = get_memory8(addr1+3+x); - } - - // Check for extension and add to mt_file - if (get_memory8(addr1+3+x) != ' ') - mt_file[c++] = '.'; - mt_file[c++] = get_memory8(addr1+3+x++); - mt_file[c++] = get_memory8(addr1+3+x); - mt_file[c] = '\0'; - - // Add filename to tFiles structure - strcpy(gTcCtrl.tFiles[gTcCtrl.tCount].name, mt_file); - gTcCtrl.tFiles[gTcCtrl.tCount].type = file_type; - - // Get address of file - gTcCtrl.tFiles[gTcCtrl.tCount].address = get_memory16(addr1+1); - gTcCtrl.tFiles[gTcCtrl.tCount].dir_address = addr1; - - // Calculate file size - if (file_type == TYPE_CO) - { - // Get file size from the .CO file - gTcCtrl.tFiles[gTcCtrl.tCount].size = - get_memory16(gTcCtrl.tFiles[gTcCtrl.tCount].address + 2) + 6; - } - else if (file_type == TYPE_DO) - { - // Start at beginning of file - x = 0; - fdata = get_memory8(gTcCtrl.tFiles[gTcCtrl.tCount].address); - - // Search through the file until 0x1A found - while (fdata != 0x1A) - { - x++; - fdata = get_memory8(gTcCtrl.tFiles[gTcCtrl.tCount].address + x); - } - - // Set size - gTcCtrl.tFiles[gTcCtrl.tCount].size = x; - } - else if (file_type == TYPE_BA) - { - // Scan through BASIC file until NULL pointer reached - addr2 = get_memory16(gTcCtrl.tFiles[gTcCtrl.tCount].address); - while (get_memory16(addr2) != 0) - { - // Get line pointer of the next line - addr2 = get_memory16(addr2); - } - gTcCtrl.tFiles[gTcCtrl.tCount].size = addr2 - gTcCtrl.tFiles[gTcCtrl.tCount].address; - } - - // Space pad the filename - sprintf(mt_file, "%-11s %d", gTcCtrl.tFiles[gTcCtrl.tCount].name, - gTcCtrl.tFiles[gTcCtrl.tCount].size); - - // Add file to Hold Browser and increment for next file - gTcCtrl.pFileSelect->add(mt_file); - gTcCtrl.tCount++; - dir_index++; - addr1 += 11; - } -} - -/* -============================================================================ -Callback routine to read TPDD / NADSBox directory -============================================================================ -*/ -static void cb_TpddDir(Fl_Widget* w, void*) -{ -} - -/* -============================================================================ -Routine to create the TPDD Client window -============================================================================ -*/ -void cb_TpddClient(Fl_Widget* w, void*) -{ - Fl_Box* o; - - if (gtcw != NULL) - return; - - // Create File Viewer window - gtcw = new Fl_Double_Window(650, 480, "TPDD / NADSBox Client"); - gtcw->callback(cb_tcwin); - - // Create a menu for the new window. - gTcCtrl.pMenu = new Fl_Menu_Bar(0, 0, 700, MENU_HEIGHT-2); - gTcCtrl.pMenu->menu(gTpddClient_menuitems); - - o = new Fl_Box(20, 40, 80, 20, "File Directory"); - o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - - // Create a browser for the files - gTcCtrl.pFileSelect = new Fl_Hold_Browser(20, 65, 170, 270, 0); - gTcCtrl.pFileSelect->textfont(FL_COURIER); - gTcCtrl.pFileSelect->has_scrollbar(Fl_Browser_::VERTICAL); - gTcCtrl.pFileSelect->callback(cb_FileSelect); - - // Create a Text Editor / Text Buffer for the file display - gTcCtrl.pView = new Fl_Hold_Browser(200, 65, 420, 270, ""); - gTcCtrl.pView->has_scrollbar(Fl_Browser_::VERTICAL ); - gTcCtrl.pView->textfont(FL_COURIER); - gTcCtrl.pView->textsize(12); - - // Create a button to Read the TPDD / NADSBox Directory - gTcCtrl.pTpddDir = new Fl_Button(20, 350, 120, 20, "TPDD Directory"); - gTcCtrl.pTpddDir->callback(cb_TpddDir); - - // Create a button to copy files to the TPDD / NADSBox - - // Create a button to copy files from the TPDD / NADSBox - - // Create a static box showing the COM port being used (from the Setup page) - gtcw->show(); -} diff --git a/src/tpddclient.h b/src/tpddclient.h index d5910a0..78e346e 100644 --- a/src/tpddclient.h +++ b/src/tpddclient.h @@ -30,40 +30,15 @@ #ifndef TPDDCLIENT_H #define TPDDCLIENT_H -void cb_TpddClient(Fl_Widget* w, void*); - -#ifdef TPDD_CLIENT_MAIN - -typedef struct { - char name[12]; - unsigned short address; - unsigned short dir_address; - unsigned short size; - unsigned char type; -} tpdd_client_files_t; - -typedef struct tpddclient_ctrl_struct -{ - Fl_Menu_Bar* pMenu; // Pointer to Menu bar - - Fl_Box* pDirAddress; // Pointer to Dir star taddress - char sDirAddr[20]; - Fl_Box* pDirEntry; // DirEntry information box - char sDirEntry[100]; // Text for directory entry - Fl_Box* pAddress; // Address information box - char sAddress[100]; // Text for Address entry - Fl_Hold_Browser* pFileSelect; // Pointer to Directory Table files - Fl_Hold_Browser* pView; // Pointer to Browser for file contents - tpdd_client_files_t tFiles[512]; // Storage for up to 512 files - int tCount; - Fl_Button* pTpddDir; // Create TPDD directory listing - - int selectIndex; // Index of active selection - Fl_Group* g; - -} tpddclient_ctrl_t; - -#endif +/* +=============================================================== +This file is just a placeholder. It used to incorrectly have +the TpddServer code in it, but that code has been moved to +the tpddserver.cpp file instead. Perhaps someday VirtualT +will include a TPDD Client that can talk with a physical TPDD +device on the serial port... +=============================================================== +*/ -#endif +#endif /* TPDDCLIENT_H */ diff --git a/src/tpddserver.cpp b/src/tpddserver.cpp new file mode 100644 index 0000000..e347494 --- /dev/null +++ b/src/tpddserver.cpp @@ -0,0 +1,2351 @@ +/* tpddserver.cpp */ + +/* $Id$ */ + +/* + * Copyright 2013 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +//#include +#include +#include +#ifdef _WIN32 +#include +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "FLU/Flu_File_Chooser.h" + +#include "VirtualT.h" +#include "m100emu.h" +#include "tpddserver.h" +#include "serial.h" +#include "display.h" +#include "cpuregs.h" +#include "periph.h" +#include "memedit.h" +#include "fileview.h" + +enum { + TPDD_STATE_IDLE = 0, + TPDD_STATE_Z, + TPDD_STATE_OPCODE, + TPDD_STATE_LEN, + TPDD_STATE_READ_BYTES, + TPDD_STATE_READ_CHECKSUM, + TPDD_STATE_M, + TPDD_STATE_M1, + TPDD_STATE_R, + TPDD_STATE_CMDLINE, + TPDD_STATE_EXEC +}; + +// =============================================== +// Extern "C" linkage items +// =============================================== +extern "C" +{ +extern volatile UINT64 cycles; +extern volatile DWORD rst7cycles; + +#ifdef WIN32 +int strcasecmp(const char* s1, const char* s2); +#endif +} + +/* +====================================================== +Structure for the setup GUI controls. +====================================================== +*/ +typedef struct tpddserver_ctrl_struct +{ + Fl_Input* pRootDir; // Pointer to root dir input + char sRootDir[512]; + Fl_Button* pTpddDir; // Create TPDD directory listing +} tpddserver_ctrl_t; + +// =============================================== +// Extern and global variables +// =============================================== +extern Fl_Preferences virtualt_prefs; +static Fl_Window* gtcw = NULL; +tpddserver_ctrl_t gTsCtrl; + +// Define the array of NADSBox commands +VT_NADSCmd_t VTTpddServer::m_Cmds[] = { + { "cd", &VTTpddServer::CmdlineCd }, +// { "copy", &VTTpddServer::CmdlineCopy }, +// { "date", &VTTpddServer::CmdlineDate }, +// { "del", &VTTpddServer::CmdlineDel }, + { "dir", &VTTpddServer::CmdlineDir }, + { "help", &VTTpddServer::CmdlineHelp }, +// { "info", &VTTpddServer::CmdlineInfo }, +// { "mkdir", &VTTpddServer::CmdlineMkdir }, + { "pwd", &VTTpddServer::CmdlinePwd }, +// { "ren", &VTTpddServer::CmdlineRen }, +// { "rmdir", &VTTpddServer::CmdlineRmdir }, +// { "time", &VTTpddServer::CmdlineTime }, +// { "trace", &VTTpddServer::CmdlineTrace }, +// { "type", &VTTpddServer::CmdlineType }, + { "ver", &VTTpddServer::CmdlineVer }, +}; +int VTTpddServer::m_cmdCount = sizeof(VTTpddServer::m_Cmds) / sizeof(VT_NADSCmd_t); + +// Define the array of Linux alias commands +VT_NADSCmd_t VTTpddServer::m_LinuxCmds[] = { + { "cat", &VTTpddServer::CmdlineType }, + { "cp", &VTTpddServer::CmdlineCopy }, + { "ls", &VTTpddServer::CmdlineDir }, + { "ll", &VTTpddServer::CmdlineDir }, + { "more", &VTTpddServer::CmdlineType }, + { "mv", &VTTpddServer::CmdlineRen }, + { "rm", &VTTpddServer::CmdlineDel }, +}; +int VTTpddServer::m_linuxCmdCount = sizeof(VTTpddServer::m_LinuxCmds) / sizeof(VT_NADSCmd_t); + +// Define the array of Linux alias commands +VTTpddOpcodeFunc VTTpddServer::m_tpddOpcodeHandlers[] = { + &VTTpddServer::OpcodeDir, + &VTTpddServer::OpcodeOpen, + &VTTpddServer::OpcodeClose, + &VTTpddServer::OpcodeRead, + &VTTpddServer::OpcodeWrite, + &VTTpddServer::OpcodeDelete, + &VTTpddServer::OpcodeFormat, + &VTTpddServer::OpcodeDriveStatus, + &VTTpddServer::OpcodeId, +}; + +int VTTpddServer::m_tpddOpcodeCount = sizeof(VTTpddServer::m_tpddOpcodeHandlers) / sizeof(VTNADSCmdlineFunc); + +/* +============================================================================ +Callback routine for the File Viewer window +============================================================================ +*/ +void cb_tcwin (Fl_Widget* w, void*) +{ + // Hide the window + gtcw->hide(); + + // Delete the window and set to NULL + delete gtcw; + gtcw = NULL; +} + +/* +============================================================================ +Callback routine to read TPDD / NADSBox directory +============================================================================ +*/ +static void cb_TpddDir(Fl_Widget* w, void*) +{ + Flu_File_Chooser* fc; + char fc_path[256]; + int count; + const char *filename; + + // Create chooser window to pick file + strncpy(fc_path, gTsCtrl.pRootDir->value(), sizeof(fc_path)); + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser(fc_path, "", Flu_File_Chooser::DIRECTORY, "Choose Root Directory"); + fl_cursor(FL_CURSOR_DEFAULT); + fc->preview(0); + fc->show(); + + // Show Chooser window + while (fc->visible()) + Fl::wait(); + + count = fc->count(); + if (count == 0) + { + delete fc; + return; + } + + // Get Filename + filename = fc->value(); + if (filename == 0) + { + delete fc; + return; + } + + // Copy the new root + strncpy(gTsCtrl.sRootDir, filename, sizeof(gTsCtrl.sRootDir)); + gTsCtrl.pRootDir->value(gTsCtrl.sRootDir); + + delete fc; +} + +/* +============================================================================ +Callback routine for the cancel button +============================================================================ +*/ +static void cb_tpdd_cancel(Fl_Widget* w, void*) +{ + // Hide and delete the window + gtcw->hide(); + delete gtcw; + gtcw = NULL; +} + +/* +============================================================================ +Callback routine for the Ok button +============================================================================ +*/ +static void cb_tpdd_ok(Fl_Widget* w, void* pOpaque) +{ + // hide the window + gtcw->hide(); + + // Get the updated root directory + const char *pDir = gTsCtrl.pRootDir->value(); + + VTTpddServer* pServer = (VTTpddServer *) ser_get_tpdd_context(); + strcpy(gTsCtrl.sRootDir, pDir); + pServer->RootDir(pDir); + + // Delete the window + delete gtcw; + gtcw = NULL; +} + +/* +============================================================================ +Routine to create the TPDD Server window +============================================================================ +*/ +void tpdd_server_config(void) +{ + Fl_Box* o; + Fl_Button* b; + + if (gtcw != NULL) + return; + + // Create TPDD Server configuration window + gtcw = new Fl_Double_Window(480, 150, "TPDD / NADSBox Server"); + gtcw->callback(cb_tcwin); + + o = new Fl_Box(20, 20, 80, 20, "Root Directory"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + // Create an input field to edit / show the root directory + gTsCtrl.pRootDir = new Fl_Input(35, 40, 325, 20, ""); + VTTpddServer* pServer = (VTTpddServer *) ser_get_tpdd_context(); + strcpy(gTsCtrl.sRootDir, pServer->RootDir()); + gTsCtrl.pRootDir->value(gTsCtrl.sRootDir); + + // Create a browse button for the root directory + gTsCtrl.pTpddDir = new Fl_Button(380, 40, 80, 20, "Browse"); + gTsCtrl.pTpddDir->callback(cb_TpddDir); + + // Create a Cancel button + b = new Fl_Button(200, 120, 80, 20, "Cancel"); + b->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE); + b->callback(cb_tpdd_cancel); + + // Create an OK button + b = new Fl_Return_Button(300, 120, 80, 20, "OK"); + b->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE); + b->callback(cb_tpdd_ok); + + gtcw->show(); +} + +/* +=========================================================================== +Define Serial port interface "C" routines below +=========================================================================== +*/ +extern "C" +{ + +/* +=========================================================================== +tpdd_alloc_context: Allocates a context to define and control the TPDD + server routines. +=========================================================================== +*/ +void* tpdd_alloc_context(void) +{ + return (void *) new VTTpddServer; +} + +/* +=========================================================================== +tpdd_free_context: Frees the given context. +=========================================================================== +*/ +void tpdd_free_context(void* pContext) +{ + // Validate the context is not null + if (pContext != NULL) + { + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + delete pTpdd; + } +} + +/* +=========================================================================== +tpdd_load_prefs: Loads the tpdd server preferences from the user file. +=========================================================================== +*/ +void tpdd_load_prefs(void* pContext) +{ + char rootDir[512]; + VTTpddServer* pServer; + + virtualt_prefs.get("TpddServer_RootDir", rootDir, path, sizeof(rootDir)); + pServer = (VTTpddServer *) pContext; + pServer->RootDir(rootDir); +} + +/* +=========================================================================== +tpdd_save_prefs: Saves the tpdd server preferences to the user file. +=========================================================================== +*/ +void tpdd_save_prefs(void* pContext) +{ + VTTpddServer* pServer = (VTTpddServer *) pContext; + + virtualt_prefs.set("TpddServer_RootDir", pServer->RootDir()); +} + +/* +=========================================================================== +tpdd_close_serial: Closes the simulated TPDD serial session. +=========================================================================== +*/ +int tpdd_close_serial(void* pContext) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerClosePort(); +} + +/* +=========================================================================== +tpdd_open_serial: Opens the simulated TPDD serial session. +=========================================================================== +*/ +int tpdd_open_serial(void* pContext) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerOpenPort(); +} + +/* +=========================================================================== +tpdd_ser_set_baud: Sets the simulated baudrate for the TPDD server. +=========================================================================== +*/ +int tpdd_ser_set_baud(void* pContext, int baud_rate) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerSetBaud(baud_rate); +} + +/* +=========================================================================== +tpdd_ser_get_flags: Returns the port flags for the TPDD server +=========================================================================== +*/ +int tpdd_ser_get_flags(void* pContext, unsigned char *flags) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerGetFlags(flags); +} + +/* +=========================================================================== +tpdd_ser_set_signals: Sets the simulated port signals for the TPDD server +=========================================================================== +*/ +int tpdd_ser_set_signals(void* pContext, unsigned char signals) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerSetSignals(signals); +} + +/* +=========================================================================== +tpdd_ser_get_signals: Sets the simulated port signals for the TPDD server +=========================================================================== +*/ +int tpdd_ser_get_signals(void* pContext, unsigned char *signals) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerGetSignals(signals); +} + +/* +=========================================================================== +tpdd_ser_read_byte: Reads a byte from the TPDD server +=========================================================================== +*/ +int tpdd_ser_read_byte(void* pContext, char* data) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerReadByte(data); +} + +/* +=========================================================================== +tpdd_ser_write_byte: Writes a byte to the TPDD server +=========================================================================== +*/ +int tpdd_ser_write_byte(void* pContext, char data) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerWriteByte(data); +} + +/* +=========================================================================== +tpdd_get_port_name: Returns a printer to the name of this tpdd port +=========================================================================== +*/ +const char* tpdd_get_port_name(void* pContext) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerGetPortName(); +} + +/* +=========================================================================== +tpdd_ser_poll: Poll the TPDD Server to test if it has data available +=========================================================================== +*/ +int tpdd_ser_poll(void* pContext) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerPoll(); +} + +} /* End of extern "C" block */ + +/* +=========================================================================== +VTTpddServer class function implementaion follows. This is the constructor +=========================================================================== +*/ +VTTpddServer::VTTpddServer(void) +{ + int c; + + // Clear out the rx and tx buffers + m_rxCount = m_txCount = 0; + m_rxIn = m_rxOut = 0; + m_txIn = m_txOut = 0; + for (c = 0; c < TPDD_MAX_FDS; c++) + { + m_refFd[c] = NULL; + m_mode[c] = 0; + } + m_lastWasRx = FALSE; + m_lastOpenWasDir = FALSE; + m_refIsDirectory = FALSE; + m_activeFd = 0; + m_backgroundCmd = NULL; + m_activeDir = NULL; + m_dirDir = NULL; + m_dirCount = m_dirNext = 0; + m_tsdosDmeReq = m_tsdosDmeStart = FALSE; + + // Reset the TPDD to idle state + m_state = TPDD_STATE_IDLE; + + // Initialze the working dir and rootpath + m_curDir = "/"; + m_sRootDir = path; +} + +/* +=========================================================================== +Class destructor +=========================================================================== +*/ +VTTpddServer::~VTTpddServer(void) +{ + int c; + + // Close any open file + for (c = 0; c < TPDD_MAX_FDS; c++) + { + if (m_refFd[c] != NULL) + fclose(m_refFd[c]); + m_refFd[c] = NULL; + } + + // Test if any active dirent list + ResetDirent(); +} + +/* +=========================================================================== +Set the root emulation directory +=========================================================================== +*/ +void VTTpddServer::RootDir(const char *pDir) +{ + int len; + + // Update the root directory + len = strlen(pDir); + m_sRootDir = pDir; + + // Remove trailing '/' or '\' + if (pDir[len-1] == '/' || pDir[len-1] == '\\') + m_sRootDir = m_sRootDir.Left(len - 1); + + // If there are any open files, then they have to be marked to send + // a TPDD_ERR_DISK_CHANGE_ERR error + // TODO: Do this!! +} + +/* +=========================================================================== +Opens the TpddServer port +=========================================================================== +*/ +int VTTpddServer::SerOpenPort(void) +{ + // Clear out the rx and tx buffers + m_txOverflow = m_rxOverflow = FALSE; + m_cycleDelay = 100000; + m_lastReadCycles = cycles; + + return SER_NO_ERROR; +} + +/* +=========================================================================== +Closes the TpddServer port +=========================================================================== +*/ +int VTTpddServer::SerClosePort(void) +{ + return SER_NO_ERROR; +} + +/* +=========================================================================== +Returns the name of the simulated port +=========================================================================== +*/ +const char* VTTpddServer::SerGetPortName(void) +{ + return (const char *) "TPDD"; +} + +/* +=========================================================================== +Sets the baud rate of the simulated TPDD server +=========================================================================== +*/ +int VTTpddServer::SerSetBaud(int baud_rate) +{ + // Save the simulated baud rate + m_baudRate = baud_rate; + + return SER_NO_ERROR; +} + +/* +=========================================================================== +Sets the simulated port flags +=========================================================================== +*/ +int VTTpddServer::SerGetFlags(unsigned char *flags) +{ + // Test if we can receive more data + if (m_rxCount + 1 < sizeof(m_rxBuffer)) + *flags = SER_FLAG_TX_EMPTY; + else + *flags &= ~SER_FLAG_TX_EMPTY; + + return SER_NO_ERROR; +} + +/* +=========================================================================== +Sets the simulated port signals +=========================================================================== +*/ +int VTTpddServer::SerSetSignals(unsigned char signals) +{ + return SER_NO_ERROR; +} + +/* +=========================================================================== +Gets the simulated port signals +=========================================================================== +*/ +int VTTpddServer::SerGetSignals(unsigned char *signals) +{ + *signals = SER_SIGNAL_CTS | SER_SIGNAL_DSR | SER_SIGNAL_DTR | SER_SIGNAL_RTS; + + return SER_NO_ERROR; +} + +/* +=========================================================================== +Reads a byte from the TPDD Server +=========================================================================== +*/ +int VTTpddServer::SerReadByte(char *data) +{ + // Test if any data available + if (m_txCount == 0) + return SER_NO_DATA; + + // "Read" the next byte from the TX buffer + *data = m_txBuffer[m_txOut++]; + if (m_txOut >= sizeof(m_txBuffer)) + m_txOut = 0; + + if (m_lastWasRx) + printf("\nTX: "); + m_lastWasRx = FALSE; + printf("%02X ", (unsigned char) *data); + + // Decrement the count + m_txCount--; + + // "Kick" transmission of the next block of data from background command + if (m_backgroundCmd != NULL) + { + // Continue execution of the command in the background + if ((this->*m_backgroundCmd)(TRUE) == 0) + { + // Background command terminated + m_backgroundCmd = NULL; + SendToHost("> "); + + // Clear out the RX path + m_rxIn = m_rxCount = 0; + m_state = TPDD_STATE_IDLE; + } + } + + // If the count reached zero, then we need to indicate that to the + // serial routines so it will clear the interrupt + if (m_txCount == 0) + return SER_LAST_BYTE; + + // Update the time (cycles) of the last read + m_lastReadCycles = cycles; + + return SER_NO_ERROR; +} + +/* +=========================================================================== +Test if any bytes available to read and return appropriate status code +=========================================================================== +*/ +int VTTpddServer::SerPoll(void) +{ + // Test if any data in the TX buffer + if (m_txCount == 0) + return SER_NO_DATA; + + // Test if enough "time" (i.e. cycles) have elapsed + if (cycles > (UINT64) (m_lastReadCycles + m_cycleDelay)) + return SER_NO_ERROR; + + return SER_NO_DATA; +} + +/* +=========================================================================== +Sends a single character to the host +=========================================================================== +*/ +void VTTpddServer::SendToHost(char data) +{ + // Validate the TX buffer isn't full + if (m_txCount + 1 >= sizeof(m_txBuffer)) + { + m_txOverflow = TRUE; + return; + } + + // Add the byte + m_txBuffer[m_txIn++] = data; + if (m_txIn >= sizeof(m_txBuffer)) + m_txIn = 0; + m_txCount++; +} + +/* +=========================================================================== +Sends a string of characters to the host +=========================================================================== +*/ +void VTTpddServer::SendToHost(const char* data) +{ + while (*data != '\0') + SendToHost(*data++); +} + +/* +=========================================================================== +Processes received bytes while in the command line state +=========================================================================== +*/ +void VTTpddServer::StateCmdline(char data) +{ + // Test for CR + if (data == '\r') + { + // Echo CRLF to host + if (data != 0x1B) + SendToHost("\r\n"); + + // If there's no background command active... + if (m_backgroundCmd == NULL) + { + // Terminate the command and execute it + m_rxBuffer[m_rxIn] = '\0'; + m_cycleDelay = 400000; + ExecuteCmdline(); + } + + // Now reset the rxBuffer and go to idle + m_rxIn = m_rxOut = m_rxCount = 0; + m_state = TPDD_STATE_IDLE; + return; + } + // Test for BKSP + else if (data == 0x08) + { + // Process the backspace + if (m_rxCount > 0) + { + // Erase the line from the host + SendToHost("\x08 \x08"); + m_rxCount--; + m_rxIn--; + } + + return; + } + + // We have received part of a command line and we are looking for a CR, + // but must look for a 'Z' or 'M' after a timeout also + if (m_rxCount + 1 >= sizeof(m_rxBuffer)) + { + // Buffer overflow!!! Go to idle state + m_rxIn = m_rxOut = m_rxCount = 0; + m_state = TPDD_STATE_IDLE; + m_rxOverflow = TRUE; + return; + } + + else + { + // Add the byte to our rx buffer + m_rxBuffer[m_rxIn++] = data; + m_rxCount++; + + // Echo the byte back to the host + if (data != 0x1B) + SendToHost(data); + } +} + +/* +=========================================================================== +Handles the "cd" command +=========================================================================== +*/ +int VTTpddServer::CmdlineCd(int background) +{ + MString dirSave; + MString temp; + MString subDir; + int len, i; + + if (!background) + { + // Test if an arguemnt given + if (m_args.GetSize() == 0) + { + SendToHost("no argument given\r\n"); + return FALSE; + } + + // We could have multiple directories in the arg, such as "../M100" + // Process them one at a time. First save the current directory + // in case of error. + temp = m_args[0]; + len = temp.GetLength(); + dirSave = m_curDir; + + // Test if directory starts with '/' + i = 0; + if (temp[0] == '/') + { + i++; + m_curDir = '/'; + } + + // Get the first subdir specification + while (i < len && temp[i] != '/') + subDir += (char) temp[i++]; + + // Skip the '/' + if (i < len) + i++; + + while (subDir != "") + { + // Try to change to this directory + if (!ChangeDirectory(subDir)) + { + MString fmt; + fmt.Format("Dir '%s' does not exist\r\n", (const char *) subDir); + SendToHost((const char *) fmt); + m_curDir = dirSave; + return FALSE; + } + + // Get next level of subdir + subDir = ""; + + // Get the next subdir spec + while (i < len && temp[i] != '/') + subDir += (char) temp[i++]; + + // Skip the '/' + if (i < len) + i++; + } + } + + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "dir" command +=========================================================================== +*/ +int VTTpddServer::CmdlineDir(int background) +{ + int i, printed; + MString file_path; + int wide = FALSE; + MString fmt; + int len, isDir; + + m_cycleDelay = rst7cycles * 70 ; + if (m_cycleDelay > 1000000) + m_cycleDelay = 1000000; + + // Test if running in background or not + if (background) + { + // Wait for a key from the user before continuing + if (m_rxCount == 0) + return TRUE; + + // Key pressed. Test for ESC or CTRL-C + for (i = 0; i < m_rxCount; i++) + { + // Test if this character is CTRL-C or ESC + if (m_rxBuffer[i] == 0x03 || m_rxBuffer[i] == 0x1B || m_rxBuffer[i] == 'q') + { + // Yep, the user terminated the listing + for( i = 0; i < m_dirDirCount; i++ ) + free((void*) (m_dirDir[i])); + free((void*) m_dirDir); + m_dirDir = NULL; + SendToHost("\r\n"); + return FALSE; + } + } + + // Terminate the message line + m_rxIn = m_rxCount = 0; + SendToHost("\r\n"); + } + else + { + // Get a listing of the current directory + if (m_dirDir != NULL) + { + // Free the directory listing + for( i = 0; i < m_dirDirCount; i++ ) + free((void*) (m_dirDir[i])); + free((void*) m_dirDir); + } + + // Test if any args given + m_backgroundFlags = 0; + if (m_args.GetSize() == 0) + { + Fl_File_Sort_F *sort = fl_casealphasort; + + // Get a listing of files in the current directory + file_path = m_sRootDir + m_curDir; + m_dirDirCount = fl_filename_list((const char *) file_path, &m_dirDir, sort); + } + else + { + SendToHost("Arguments not supported yet\r\n"); + m_rxIn = m_rxCount = 0; + return FALSE; + } + + // Start at beginning of list + m_dirDirNext = 0; + } + + // Display a page of entries + printed = 0; + + for (i = m_dirDirNext; i < m_dirDirCount; i++) + { + const char* name = m_dirDir[i]->d_name; + MString printName; + + // ignore the "." and ".." names + if ( strcmp( name, "." ) == 0 || strcmp( name, ".." ) == 0 || + strcmp( name, "./" ) == 0 || strcmp( name, "../" ) == 0 || + strcmp( name, ".\\" ) == 0 || strcmp( name, "..\\" ) == 0 ) + { + continue; + } + + // Test if this is a directory + isDir = FALSE; + if (name[strlen(name)-1] == '/') + isDir = TRUE; + + // Get length of file + if (!isDir) + { + // Open the file and seek to the end + MString temp = m_sRootDir + m_curDir + name; + FILE* fd = fopen((const char *) temp, "r"); + len = 0; + + // Seek and tell only if file opened + if (fd != NULL) + { + fseek(fd, 0, SEEK_END); + len = ftell(fd); + fclose(fd); + } + } + + // Print this entry + if ((m_backgroundFlags & CMD_DIR_FLAG_WIDE) == 0) + { + // Not in wide display format + if (!isDir) + { + fmt.Format("%-20s%6d\r\n", name, len); + fmt.MakeUpper(); + } + else + { + MString temp = name; + temp = temp.Left(temp.GetLength()-1); + temp.MakeUpper(); + fmt.Format("%-17s

    \r\n", (const char *) temp); + } + SendToHost((const char *) fmt); + printed++; + } + + // Test if a page printed + if (gModel == MODEL_T200) + { + if (printed == 15) + { + i++; + break; + } + } + else if (printed == 7) + { + i++; + break; + } + } + + // Save index for next listing + m_dirDirNext = i; + + // Test if all entries printed + if (i == m_dirDirCount) + { + // Free the directory listing + for( i = 0; i < m_dirDirCount; i++ ) + free((void*) (m_dirDir[i])); + free((void*) m_dirDir); + m_dirDir = NULL; + + // Don't need to execute in the background + return FALSE; + } + + // We have more to display. Present a message + SendToHost("Any key to continue, 'q' to stop..."); + + // Need to execute in the background + return TRUE; +} + +/* +=========================================================================== +Handles the "rmdir" command +=========================================================================== +*/ +int VTTpddServer::CmdlineRmdir(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "Mkdir" command +=========================================================================== +*/ +int VTTpddServer::CmdlineMkdir(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "del" command +=========================================================================== +*/ +int VTTpddServer::CmdlineDel(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "copy" command +=========================================================================== +*/ +int VTTpddServer::CmdlineCopy(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "ren" command +=========================================================================== +*/ +int VTTpddServer::CmdlineRen(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "trace" command +=========================================================================== +*/ +int VTTpddServer::CmdlineTrace(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "type" command +=========================================================================== +*/ +int VTTpddServer::CmdlineType(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "date" command +=========================================================================== +*/ +int VTTpddServer::CmdlineDate(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "time" command +=========================================================================== +*/ +int VTTpddServer::CmdlineTime(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "info" command +=========================================================================== +*/ +int VTTpddServer::CmdlineInfo(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "help" command +=========================================================================== +*/ +int VTTpddServer::CmdlineHelp(int background) +{ + int c, cmdsThisLine; + + // Counts the number of commands printed on this line + cmdsThisLine = 0; + + if (!background) + { + // Loop for all commands + for (c = 0; c < m_cmdCount; c++) + { + SendToHost(m_Cmds[c].pCmd); + if (++cmdsThisLine == 4) + { + // Terminate this line + cmdsThisLine = 0; + SendToHost("\r\n"); + } + else + { + // Send a tab between commands + SendToHost("\t"); + } + } + + // Test if we need a final CRLF + if (cmdsThisLine != 0) + SendToHost("\r\n"); + } + + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "pwd" command +=========================================================================== +*/ +int VTTpddServer::CmdlinePwd(int background) +{ + MString temp = m_curDir; + + if (!background) + { + temp.MakeUpper(); + if (temp.GetLength() > 1) + if (temp[temp.GetLength()-1] == '/') + temp = temp.Left(temp.GetLength()-1); + SendToHost((const char *) temp); + SendToHost("\r\n"); + } + + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "ver" command +=========================================================================== +*/ +int VTTpddServer::CmdlineVer(int background) +{ + // Send our Version information to the host + if (!background) + { + SendToHost("VirtualT's emulated NADSBox\r\n"); + SendToHost("Firmware v1.14 equivalent\r\n"); + SendToHost("Copyright 2013, Kenneth D. Pettit\r\n"); + } + + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Executes the command line command in the m_rxBuffer +=========================================================================== +*/ +void VTTpddServer::ExecuteCmdline(void) +{ + int c; + char* ptr; + MString cmd, arg; + + // Split the m_rxBuffer into command and args + ptr = m_rxBuffer; + + // Remove previous arguments + m_args.RemoveAll(); + + // Get the command + while (*ptr != '\0' && *ptr != ' ') + cmd += *ptr++; + + // Now get the args + while (*ptr == ' ') + ptr++; + while (*ptr != '\0') + { + // Clear out the argument + arg = ""; + while (*ptr != ' ' && *ptr != '\0') + arg += *ptr++; + + // Add to the args array + m_args.Add(arg); + + // Skip whitespace + while (*ptr == ' ') + ptr++; + } + + // Loop through all registered commands and see if we have a match + for (c = 0; c < m_cmdCount; c++) + { + // Test if this command matches + if (strcmp(m_Cmds[c].pCmd, (const char *) cmd) == 0) + { + // This command matches the rxBuffer. Call the command handler + if ((this->*m_Cmds[c].pFunc)(FALSE)) + m_backgroundCmd = this->m_Cmds[c].pFunc; + break; + } + } + + // Test if command not foune + if (c == m_cmdCount) + { + // Search the Linux equivalent commands + for (c = 0; c < m_linuxCmdCount; c++) + { + // Test if this command matches + if (strcmp(m_LinuxCmds[c].pCmd, (const char *) cmd) == 0) + { + // This command matches the rxBuffer. Call the command handler + if ((this->*m_LinuxCmds[c].pFunc)(FALSE)) + m_backgroundCmd = m_Cmds[c].pFunc; + break; + } + } + + // Test if command not found in Linux alias list either + if (c == m_linuxCmdCount) + { + // Test for "flash" command + if (strcmp("flash", (const char *) cmd) == 0) + SendToHost("'flash' not supported in emulation\r\n"); + else if (strcmp("stats", (const char *) cmd) == 0) + SendToHost("'stats' not supported in emulation\r\n"); + else + SendToHost("Unknown command\r\n"); + } + } + + // Send an new prompt + if (m_backgroundCmd == NULL) + SendToHost("> "); +} + +/* +=========================================================================== +Executes the TPDD opcode in the m_rxBuffer +=========================================================================== +*/ +void VTTpddServer::ExecuteTpddOpcode(void) +{ + // Test opcode for mystery31 or mystery23 + if (m_opcode == TPDD_REQ_TSDOS_MYSTERY23) + OpcodeMystery23(); + else if (m_opcode == TPDD_REQ_TSDOS_MYSTERY31) + OpcodeMystery31(); + + // Normal TPDD protocol opcodes + else if (m_opcode <= TPDD_REQ_ID) + { + // Call the handler routine for this opcode +// printf("Executing opcode %d\n", m_opcode); + (this->*m_tpddOpcodeHandlers[m_opcode])(); + } + + // Unknown opcode + else + { + // Send an error condition + SendNormalReturn(TPDD_ERR_PARAM_ERR); + } + + // Reset RX path and go to IDLE state + m_rxIn = m_rxCount = 0; + m_state = TPDD_STATE_IDLE; +} + +/* +=========================================================================== +Writes a byte to the TPDD Server +=========================================================================== +*/ +int VTTpddServer::SerWriteByte(char data) +{ + int c; + + // Record the time of this byte so we can perform timeout + // operations in the state machine + + if (!m_lastWasRx) + printf("\nRX: "); + m_lastWasRx = TRUE; + printf("%02X ", (unsigned char) data); + // Switch based on state. This is the main state machine + switch (m_state) + { + case TPDD_STATE_IDLE: + // We are in idle state. Search for 'Z', 'M', or 'R'. Any lower case + // chars or CR will take us to command line state + if (m_tsdosDmeReq && (data == 0x0D)) + { + // Reset the rx path + m_rxIn = m_rxCount = 0; + m_tsdosDmeStart = FALSE; + if (m_tsdosDmeReq++ == 2) + { + // Clear the DME request flag after the 2nd 0x0D + m_tsdosDmeReq = 0; + } + break; + } + if (m_tsdosDmeReq) + { + // Byte received that wasn't 0x0D. Clear out the DME + m_tsdosDmeReq = m_tsdosDmeStart = 0; + m_rxIn = m_rxCount = 0; + } + + // Test for command line characters + if (data >= 'a' && data <= 'z' || m_backgroundCmd) + { + // Add the byte to our RX buffer + m_rxBuffer[m_rxIn++] = data; + m_rxCount = 1; + + // Add the byte to our TX buffer so we echo it + if (data != 0x1B) + SendToHost(data); + + // Clear out any acive TS-DOS DME activity + m_tsdosDmeStart = FALSE; + + // Goto cmdline state + m_state = TPDD_STATE_CMDLINE; + } + + // Test for empty-line CR + else if (data == '\n' || data == '\r') + { + // Send a prompt to the host + SendToHost("\r\n> "); + } + + // Search for 'Z' + else if (data == 'Z') + { + // Add the byte to our RX buffer + m_rxBuffer[m_rxIn++] = data; + m_rxCount = 1; + m_state = TPDD_STATE_Z; // Goto Z state + } + else if (data == 'M') + { + // Add the byte to our RX buffer + m_rxBuffer[m_rxIn++] = data; + m_rxCount = 1; + m_state = TPDD_STATE_M; // Goto M state + } + else if (data == 'R') + { + // Add the byte to our RX buffer + m_rxBuffer[m_rxIn++] = data; + m_rxCount = 1; + m_state = TPDD_STATE_R; // Goto R state + } + break; + + case TPDD_STATE_Z: + // We expect to see another 'Z', but look for timeout too + if (data == 'Z') + { + // Add the byte to our RX buffer + m_rxBuffer[m_rxIn++] = data; + m_rxCount++; + + // Go to the opcode state, we got the 2nd 'Z' + m_state = TPDD_STATE_OPCODE; + } + else + { + // Goto the IDLE state and reprocess the byte + m_state = TPDD_STATE_IDLE; + m_rxCount = m_rxIn = 0; // Reset the Rx buffer + SerWriteByte(data); + } + break; + + case TPDD_STATE_OPCODE: + // We have received 'ZZ', now we are waiting for the opcode byte + m_opcode = data; + + // Add the byte to our RX buffer + m_rxBuffer[m_rxIn++] = data; + m_rxCount++; + + // Go wait for the LEN byte + m_state = TPDD_STATE_LEN; + break; + + case TPDD_STATE_LEN: + // We have received the opcode, now waiting for the length byte + m_length = (unsigned char) data; + m_bytesRead = 0; + + // Add the byte to our RX buffer + m_rxBuffer[m_rxIn++] = data; + m_rxCount++; + + // Go wait for bytes + if (m_length == 0) + m_state = TPDD_STATE_READ_CHECKSUM; + else + m_state = TPDD_STATE_READ_BYTES; + break; + + case TPDD_STATE_READ_BYTES: + // Add the byte to our RX buffer + m_rxBuffer[m_rxIn++] = data; + + // Test if all bytes read + m_rxCount++; + if (++m_bytesRead == m_length) + { + // Goto state to read the checksum + m_state = TPDD_STATE_READ_CHECKSUM; + } + break; + + case TPDD_STATE_READ_CHECKSUM: + // All bytes read, now read the checksum + m_rxChecksum = data; + + // Now compute the checksum of received data + m_calcChecksum = 0; + for (c = TPDD_PKT_OPCODE_INDEX; c < m_length+4; c++) + { + // Calculate checksum across opcode, length and all data + m_calcChecksum += (unsigned char) m_rxBuffer[c]; + } + + // Compare the checksum + if ((m_calcChecksum ^ 0xFF) != m_rxChecksum) + { + // Error in checksum. Send error packet + SendNormalReturn(TPDD_ERR_ID_CRC_CHK_ERR); + } + else + { + // Execute the TPDD opcode + m_cycleDelay = 100000; + ExecuteTpddOpcode(); + } + + // Now reset RX and go to idle + m_rxIn = m_rxCount = 0; + m_state = TPDD_STATE_IDLE; + break; + + case TPDD_STATE_M: + // We have received 'M' and are waiting for '1' (the 'M1' sequence) + if (data == '1') + { + // Now wait for the 0Dh + m_rxBuffer[m_rxIn++] = data; + m_rxCount = 1; + m_state = TPDD_STATE_M1; + } + else + { + // Reset RX path and goto idle + m_rxIn = m_rxCount = 0; + m_state = TPDD_STATE_IDLE; + } + break; + + case TPDD_STATE_M1: + // We have received 'M1'. This is used for Directory Management Extension + if (data == 0x0D) + { + // TS-DOS DME request initiated. Save the event + m_tsdosDmeStart = TRUE; + } + + // Clear the RX path and goto idle + m_rxIn = m_rxCount = 0; + m_state = TPDD_STATE_IDLE; + break; + + case TPDD_STATE_CMDLINE: + // Process in the cmdline routine + StateCmdline(data); + break; + + default: + // Unknown state. Go to idle. + m_state = TPDD_STATE_IDLE; + + // Reset the RX buffer + m_rxIn = m_rxOut = m_rxCount = 0; + break; + } + return SER_NO_ERROR; +} + +/* +=========================================================================== +Sends the specified file entry to the server +=========================================================================== +*/ +void VTTpddServer::SendDirEntReturn(dirent* e, int dir_entry) +{ + int c, idx; + int send_spaces; + + // Clear the TX checksum + m_txChecksum = 0; + TpddSendByte(TPDD_RET_DIR_REF); // Return code + TpddSendByte(28); // Dir Entry pkt length + + // Now send 24 bytes of filename, space padded + idx = 0; + send_spaces = FALSE; + for (c = 0; c < 24; c++) + { + // Test if we are sending spaces + if (send_spaces) + TpddSendByte(' '); + else if (e == NULL) + { + TpddSendByte(0); + continue; + } + else if ((e->d_name[idx] == '.' || e->d_name[idx] == '/') && c < 6) + { + TpddSendByte(' '); + } + else if ((e->d_name[idx] == '.' && dir_entry) || e->d_name[idx] == '/') + { + // Send the '.' followed by "<>", then send spaces + TpddSendByte('.'); + TpddSendByte('<'); + TpddSendByte('>'); + c += 2; + send_spaces = true; + + // Skip idx ahead to the NULL + while (e->d_name[idx] != '\0') + idx++; + } + else if (e->d_name[idx] == '\0') + { + TpddSendByte(' '); + send_spaces = TRUE; + } + else if (e->d_name[idx] == '.' && c < 6) + TpddSendByte(' '); + else + TpddSendByte(toupper(e->d_name[idx++])); + } + + // Send the Attribute byte 'F' + if (e == NULL) + TpddSendByte(0); + else + TpddSendByte('F'); + + // Send 2-byte length + int file_len = 0; + if (!dir_entry && e) + { + // Open the file to calculate the length + MString file_path = m_sRootDir + m_curDir + e->d_name; + FILE* fd = fopen((const char *) file_path, "r"); + if (fd != NULL) + { + // Seek to end of file + fseek(fd, 0, SEEK_END); + file_len = ftell(fd); + fclose(fd); + + // Truncate file length at 64K + if (file_len > 65535) + file_len = 65535; + } + } + + // Send 2 bytes of length + TpddSendByte((file_len >> 8) & 0xFF); + TpddSendByte(file_len & 0xFF); + + // Send the number of free sectors (255) + TpddSendByte((char) 0x9D); + + // Now send the checksum + TpddSendChecksum(); +} + +/* +=========================================================================== +Finds the specified file and sends the DIR_REF retrun packet to the server. +=========================================================================== +*/ +void VTTpddServer::DirFindFile(const char* pFilename) +{ + // read the directory + dirent** e; + char* name; + int i, num, len, dir_search = FALSE, dir_entry; + MString file_path; + char find_name[16]; + + // Test if accessing the "PARENT.<>" file + if (strcmp(pFilename, "PARENT.<>") == 0) + { + // Just save the reference and exit + m_dirRef = pFilename; + dirent* pParent = (dirent *) "PARENT.<>"; + SendDirEntReturn(pParent, TRUE); + return; + } + + // Construct the path using the current working directory and the root + file_path = m_sRootDir + m_curDir; + num = fl_filename_list((const char *) file_path, &e ); + m_refIsDirectory = FALSE; + + // Test if the given filename is a diretory search. If it is, then + // the filename will look like "DIRNAM.<>" + strcpy(find_name, pFilename); + len = strlen(pFilename); + if (len > 3 && pFilename[len-1] == '>' && pFilename[len-2] == '<') + { + // Indicate we are doing a directory search + dir_search = TRUE; + m_refIsDirectory = TRUE; + + // Terminate the filename at the '.' + find_name[len-3] = '\0'; + } + + // If any files found + if (num > 0) + { + // Loop through all files in the list and perform a + // case insensitive compare + for ( i = 0; i < num; i++ ) + { + name = e[i]->d_name; + + // ignore the "." and ".." names + if ( strcmp( name, "." ) == 0 || strcmp( name, ".." ) == 0 || + strcmp( name, "./" ) == 0 || strcmp( name, "../" ) == 0 || + strcmp( name, ".\\" ) == 0 || strcmp( name, "..\\" ) == 0 ) + { + continue; + } + + // if 'name' ends in '/', remove it + dir_entry = FALSE; + if ( name[strlen(name)-1] == '/' ) + { + dir_entry = TRUE; + name[strlen(name)-1] = '\0'; + } + + // Compare this file with the requested filename + if (strcasecmp(name, find_name) == 0) + { + // Entry found! Send the DIR_ENT return + SendDirEntReturn(e[i], dir_entry); + + // Test if another file was already opened + if (m_refFd[m_activeFd] != NULL) + { + // Close the previously referenced file + fclose(m_refFd[m_activeFd]); + m_refFd[m_activeFd] = NULL; + } + + // Save this reference for future open, delete, etc. + m_dirRef = name; + m_refIsDirectory = dir_entry; + + // Now free the list memory + for( i = 0; i < num; i++ ) + free((void*)(e[i])); + free((void*)e); + + return; + } + } + + // File not found. Create a new dirent and send the reference + SendDirEntReturn(NULL, FALSE); + m_dirRef = pFilename; + + // Now free the list memory + for( i = 0; i < num; i++ ) + free((void*)(e[i])); + free((void*)e); + } + else + { + // Return error + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + } +} + +/* +=========================================================================== +Finds the first entry in the current directory and sends a DirEnt packet +to the server. +=========================================================================== +*/ +void VTTpddServer::DirFindFirst(void) +{ + // read the directory + MString file_path; + + // Construct the path using the current working directory and the root + file_path = m_sRootDir + m_curDir; + if (m_activeDir != NULL) + ResetDirent(); + m_dirCount = fl_filename_list((const char *) file_path, &m_activeDir ); + m_dirNext = 0; + + // Test if we are at the ROOT directory or not. If not at root, then + // the first entry is always "PARENT.<>" + if (m_curDir != "/") + { + // Send the "PARENT.<>" directory entry + dirent* pParent; + pParent = (dirent *) "PARENT/"; + SendDirEntReturn(pParent, TRUE); + } + else + { + // Call the routine to send the next directory entry + DirFindNext(); + } +} + +/* +=========================================================================== +Finds the next entry in the current directory and sends a DirEnt packet +to the server. +=========================================================================== +*/ +void VTTpddServer::DirFindNext(void) +{ + // Don't count the '.' and '..' entries in the count + while (m_dirNext < m_dirCount) + { + const char* name = m_activeDir[m_dirNext]->d_name; + if ( strcmp( name, "." ) == 0 || strcmp( name, ".." ) == 0 || + strcmp( name, "./" ) == 0 || strcmp( name, "../" ) == 0 || + strcmp( name, ".\\" ) == 0 || strcmp( name, "..\\" ) == 0 ) + { + // Subtract this entry f + m_dirNext++; + continue; + } + + // Send first directory entry + SendDirEntReturn(m_activeDir[m_dirNext], FALSE); + m_dirNext++; + break; + } + + // Send the next directory entry or all blank + if (m_dirNext >= m_dirCount) + { + // Send a blank entry + SendDirEntReturn(NULL, FALSE); + } +} + +/* +=========================================================================== +Handles the Dir opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeDir(void) +{ + char* pFilename; + char fat_filename[16]; + int idx, c; + + // Validate the length byte + if (m_length != 26) + { + SendNormalReturn(TPDD_ERR_PARAM_ERR); + return; + } + + // Convert filename from Model T 6.2 format to FAT 8.3 format + pFilename = &m_rxBuffer[TPDD_PKT_DATA_INDEX]; + idx = 0; + for (c = 0; c < 6; c++) + if ((fat_filename[idx] = *pFilename++) != ' ') + idx++; + fat_filename[idx++] = '.'; + if (*pFilename == '.') + pFilename++; + if ((fat_filename[idx] = *pFilename++) != ' ') + idx++; + if ((fat_filename[idx] = *pFilename++) != ' ') + idx++; + fat_filename[idx] = '\0'; + + // Now process the request based on the search type + switch (m_rxBuffer[TPDD_PKT_DATA_INDEX + 25]) + { + case 0: // Dir find file + DirFindFile(fat_filename); + break; + + case 1: // Find first entry + DirFindFirst(); + break; + + case 2: // Find next entry + DirFindNext(); + break; + + default: + // Unknown + SendNormalReturn(TPDD_ERR_PARAM_ERR); + break; + } +} + +/* +=========================================================================== +Handles the Open opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeOpen(void) +{ + MString open_path; + unsigned char open_mode; + + // Try to open the referenced file + open_path = m_sRootDir + m_curDir + m_dirRef; + open_mode = m_rxBuffer[TPDD_PKT_DATA_INDEX]; + + // Check if the referenced file is a directory + if (m_refIsDirectory) + { + // Mark last open as a directory change + m_lastOpenWasDir = TRUE; + + // Test the open_mode. If read mod, then CD + if (open_mode == TPDD_OPEN_MODE_READ) + { + // Perform a "Change directory" operation + if (m_dirRef == "PARENT.<>") + { + // Change to parent directory + ChangeDirectory(".."); + SendNormalReturn(TPDD_ERR_NONE); + } + else + { + // Change to m_dirRef + ChangeDirectory(m_dirRef); + SendNormalReturn(TPDD_ERR_NONE); + } + } + else if (open_mode == TPDD_OPEN_MODE_WRITE) + { + MString temp; + // Test if we need to remove the ".<>" (likely) + if (m_dirRef.Right(3) == ".<>") + temp = m_dirRef.Left(m_dirRef.GetLength()-3); + else + temp = m_dirRef; + + // MKDIR operation + temp.MakeUpper(); + MString dirToMake = m_sRootDir + m_curDir + temp; +#ifdef WIN32 + _mkdir((const char *) dirToMake); +#else + mkdir((const char *) dirToMake, 0755); +#endif + + // Send a normal return code + SendNormalReturn(TPDD_ERR_NONE); + } + } + else + { + // Open the file based on mode + if (open_mode == TPDD_OPEN_MODE_WRITE) + m_refFd[m_activeFd] = fopen((const char *) open_path, "wb"); + else if (open_mode == TPDD_OPEN_MODE_APPEND) + m_refFd[m_activeFd] = fopen((const char *) open_path, "ab"); + else if (open_mode == TPDD_OPEN_MODE_READ) + m_refFd[m_activeFd] = fopen((const char *) open_path, "rb"); + else if (open_mode == TPDD_OPEN_MODE_READ_WRITE) + m_refFd[m_activeFd] = fopen((const char *) open_path, "rb+"); + + // Test if the file was opened successfully + if (m_refFd[m_activeFd] == NULL) + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + else + { + // Save the open mode + m_mode[m_activeFd] = open_mode; + SendNormalReturn(TPDD_ERR_NONE); + } + } +} + +/* +=========================================================================== +Handles the Close opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeClose(void) +{ + // Test if last "open" was a directory open + if (m_lastOpenWasDir) + SendNormalReturn(TPDD_ERR_NONE); + + // Test if the active FD is open + else if (m_refFd[m_activeFd] == NULL) + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + else + { + // Close the file and mark it closed + fclose(m_refFd[m_activeFd]); + m_refFd[m_activeFd] = NULL; + + // Send normal return + SendNormalReturn(TPDD_ERR_NONE); + } +} + +/* +=========================================================================== +Handles the Read opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeRead(void) +{ + char fileData[128]; + int read_len, c; + + // Validate the file is opened and in the right mode + if (m_refFd[m_activeFd] == NULL) + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + else if (m_mode[m_activeFd] != TPDD_OPEN_MODE_READ && + m_mode[m_activeFd] != TPDD_OPEN_MODE_READ_WRITE) + SendNormalReturn(TPDD_ERR_OPEN_FMT_MISMATCH); + else + { + // File is open and in the correct mode. Read up to 128 bytes + read_len = fread(fileData, 1, sizeof(fileData), m_refFd[m_activeFd]); + + // Test for end-of-file + if (read_len == 0) + SendNormalReturn(TPDD_ERR_END_OF_FILE); + else + { + // Send the read file packet + m_txChecksum = 0; + TpddSendByte(TPDD_RET_READ_FILE); + TpddSendByte((unsigned char) read_len); + + // Loop for all data to be sent + for (c = 0; c < read_len; c++) + TpddSendByte(fileData[c]); + + // Send the checksum + TpddSendChecksum(); + } + } +} + +/* +=========================================================================== +Handles the Write opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeWrite(void) +{ + int write_len; + + write_len = m_length; + + // Validate the file is opened and in the right mode + if (m_refFd[m_activeFd] == NULL) + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + else if (m_mode[m_activeFd] == TPDD_OPEN_MODE_READ) + SendNormalReturn(TPDD_ERR_OPEN_FMT_MISMATCH); + else + { + // File is open and in the correct mode. Read up to 128 bytes + write_len = fwrite(&m_rxBuffer[TPDD_PKT_DATA_INDEX], 1, m_length, m_refFd[m_activeFd]); + + // Test for end-of-file + if (write_len == 0) + SendNormalReturn(TPDD_ERR_DISK_FULL); + else + SendNormalReturn(TPDD_ERR_NONE); + } +} + +/* +=========================================================================== +Handles the Delete opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeDelete(void) +{ +} + +/* +=========================================================================== +Handles the Format opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeFormat(void) +{ + // Just send a normal return with no error + SendNormalReturn(TPDD_ERR_NONE); +} + +/* +=========================================================================== +Handles the Drive Status opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeDriveStatus(void) +{ + // Just send a normal return with no error + SendNormalReturn(TPDD_ERR_NONE); +} + +/* +=========================================================================== +Handles the Id opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeId(void) +{ + // Test if a TS-DOS DME request was received previously + if (m_tsdosDmeStart) + { + // Send a DME Response and flag to expect a coule of 0x0D + m_tsdosDmeReq = 1; + SendDmeResponse(); + } + else + { + // Send the drive ID + SendToHost("NADSBox"); + } +} + +/* +=========================================================================== +Handles the Mystery 0x23 opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeMystery23(void) +{ + const char op23Table[] = "\x14\x0F\x41\x10\x01\x00\x50\x05\x00\x02\x00\x28\x00\xE1\x00\x00\x00"; + const char op23Len = sizeof(op23Table)-1; + int c; + + // Send bytes from the table + m_txChecksum = 0; + for (c = 0; c < op23Len; c++) + { + // Send to host and calc checksum + TpddSendByte(op23Table[c]); + } + + // Now send the checksum + TpddSendChecksum(); +} + +/* +=========================================================================== +Handles the Mystery 0x31 opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeMystery31(void) +{ + // Send mystery 31 response + m_txChecksum = 0; + TpddSendByte(0x38); + TpddSendByte(1); + TpddSendByte(0); + + // Now send the checksum + TpddSendChecksum(); +} + +/* +=========================================================================== +Sends a Normal Return packet. This is a packet with 4 bytes and an ID +of 12, length 1 with an error code and checksum. +=========================================================================== +*/ +void VTTpddServer::SendNormalReturn(unsigned char errCode) +{ + // Send a Normal Return + m_txChecksum = 0; + TpddSendByte(TPDD_RET_NORMAL); + TpddSendByte(1); + TpddSendByte(errCode); + + // Now send the checksum + TpddSendChecksum(); +} + +/* +=========================================================================== +Sends the DME response packet to the server +=========================================================================== +*/ +void VTTpddServer::SendDmeResponse(void) +{ + MString dir; + int c, len; + + // Send the start of the DME Resp packet + m_txChecksum = 0; + TpddSendByte(0x12); // Opcode + TpddSendByte(0x0B); // Length + TpddSendByte(0x00); // RESVD + + // Now send the 6-byte directory name + if (m_curDir == "/") + dir = "ROOT "; + else + { + // Find last '/' in the current directory + len = m_curDir.GetLength(); + if (m_curDir[len-1] == '/') + len--; + for (c = len-1; c >= 0; c--) + if (m_curDir[c] == '/') + break; + c++; + + // Now copy up to 6 bytes of the dir name + while (dir.GetLength() < 6 && c < len) + dir += m_curDir[c++]; + // Space pad to 6 characters + while (dir.GetLength() < 6) + dir += ' '; + } + + // Add the ".<>" extension + dir += (char *) ".<> "; + + // Now send the filename + len = dir.GetLength(); + for (c = 0; c < len; c++) + TpddSendByte(dir[c]); + + // Now send the checksum + TpddSendChecksum(); +} + +/* +=========================================================================== +Change directory to the directory specified +=========================================================================== +*/ +int VTTpddServer::ChangeDirectory(MString& sDir) +{ + MString dirName; + int idx = 0; + int len = sDir.GetLength(); + + // Strip any trailing ".<>" + if (sDir.Right(3) == ".<>") + dirName = sDir.Left(len - 3); + else + dirName = sDir; + dirName.Trim(); + + // Now change directory + return ChangeDirectory((const char *) dirName); +} + +/* +=========================================================================== +Change directory to the directory specified +=========================================================================== +*/ +int VTTpddServer::ChangeDirectory(const char *pDir) +{ + int ret; + + // Test if changing to parent directory + if (strcmp(pDir, "..") == 0) + { + // Ensure we aren't at root already + if (m_curDir != "/") + { + // Search backward for the last '/' + int idx = m_curDir.GetLength() - 2; + while (idx >= 0 && m_curDir[idx] != '/') + idx--; + idx++; + m_curDir = m_curDir.Left(idx); + ret = 1; + } + else + ret = 0; + } + else + { + // Test if the directory actually exists + MString testDir = m_sRootDir + m_curDir + pDir; + if (fl_filename_isdir((const char *) testDir)) + { + // Append directory to current directory + m_curDir += pDir; + m_curDir += "/"; + ret = 1; + } + else + ret = 0; + } + + // Delete existing dirent structure + ResetDirent(); + + return ret; +} + +/* +=========================================================================== +Delete all entries in m_activeDir +=========================================================================== +*/ +void VTTpddServer::ResetDirent(void) +{ + int i; + + // Now free the list memory + for( i = 0; i < m_dirCount; i++ ) + free((void*) (m_activeDir[i])); + free((void*) m_activeDir); + + // Clear out the dirent + m_activeDir = NULL; + m_dirCount = 0; +} diff --git a/src/tpddserver.h b/src/tpddserver.h new file mode 100644 index 0000000..a225c9f --- /dev/null +++ b/src/tpddserver.h @@ -0,0 +1,302 @@ +/* tpddserver.h */ + +/* $Id$ */ + +/* +* Copyright 2008 Ken Pettit +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +*/ + +#ifndef TPDDSERVER_H +#define TPDDSERVER_H + +/* +============================================================================ +Define call routines to hook to serial port functionality. +============================================================================ +*/ +// If compiled in cpp file, make declarations extern "C" +#ifdef __cplusplus + +#include +#include "MString.h" +#include "MStringArray.h" + +extern "C" +{ +#endif /* __cplusplus */ + +// Now define the function prototypes +void* tpdd_alloc_context(void); +void tpdd_free_context(void* pContext); +void tpdd_save_prefs(void* pContext); +void tpdd_load_prefs(void* pContext); +int tpdd_close_serial(void* pContext); +int tpdd_open_serial(void* pContext); +int tpdd_ser_set_baud(void* pContext, int baud_rate); +int tpdd_ser_get_flags(void* pContext, unsigned char *flags); +int tpdd_ser_set_signals(void* pContext, unsigned char flags); +int tpdd_ser_get_signals(void* pContext, unsigned char *signals); +int tpdd_ser_read_byte(void* pContext, char* data); +int tpdd_ser_write_byte(void* pContext, char data); +int tpdd_ser_poll(void* pContext); + +const char* tpdd_get_port_name(void* pContext); + +// Close the extern "C" block if compiling a cpp file +#ifdef __cplusplus +} + +// Define CPP only prototypes +void tpdd_server_config(void); + +class VTTpddServer; + +// Typedef for command line and opcode handler +typedef int (VTTpddServer::*VTNADSCmdlineFunc)(int background); +typedef void (VTTpddServer::*VTTpddOpcodeFunc)(void); + +typedef struct VT_NADSCmd +{ + const char* pCmd; + VTNADSCmdlineFunc pFunc; +} VT_NADSCmd_t; + +// Define offsets within m_rxBuffer of various TPDD fields +#define TPDD_PKT_OPCODE_INDEX 2 +#define TPDD_PKT_LEN_INDEX 3 +#define TPDD_PKT_DATA_INDEX 4 // Location in rxBuffer of TPDD packet data + +#define TPDD_MAX_FDS 4 + +// Base TPDD requests +#define TPDD_REQ_DIR_REF 0x00 +#define TPDD_REQ_OPEN_FILE 0x01 +#define TPDD_REQ_CLOSE_FILE 0x02 +#define TPDD_REQ_READ_FILE 0x03 +#define TPDD_REQ_WRITE_FILE 0x04 +#define TPDD_REQ_DELETE_FILE 0x05 +#define TPDD_REQ_FORMAT 0x06 +#define TPDD_REQ_DRIVE_STATUS 0x07 +#define TPDD_REQ_ID 0x08 +#define TPDD_REQ_DRIVE_CONDITION 0x0C +#define TPDD_REQ_RENAME_FILE 0x0D + +#define TPDD_REQ_TSDOS_MYSTERY23 0x23 +#define TPDD_REQ_TSDOS_MYSTERY31 0x31 + +// Expanded requests for potential future Model "T" DOS usage +#define TPDD_REQ_SEEK 0x09 +#define TPDD_REQ_TELL 0x0A +#define TPDD_REQ_SET_EXTENDED 0x0B +#define TPDD_REQ_QUERY_EXTENDED 0x0E +#define TPDD_REQ_CONDENSED_LIST 0x0F +#define TPDD_REQ_LAST_OPCODE 0x0F + +// Define OPEN mode constants here +#define TPDD_OPEN_MODE_WRITE 0x01 +#define TPDD_OPEN_MODE_APPEND 0x02 +#define TPDD_OPEN_MODE_READ 0x03 +#define TPDD_OPEN_MODE_READ_WRITE 0x04 + +// Return commands +#define TPDD_RET_READ_FILE 0x10 +#define TPDD_RET_DIR_REF 0x11 +#define TPDD_RET_NORMAL 0x12 +#define TPDD_RET_TELL 0x13 +#define TPDD_RET_QUERY_EXTENDED 0x14 +#define TPDD_RET_CONDITION 0x15 +#define TPDD_RET_CONDENSED_LIST 0x16 + +// Normal Return Error Codes +#define TPDD_ERR_NONE 0x00 +#define TPDD_ERR_NONEXISTANT_FILE 0x10 +#define TPDD_ERR_FILE_EXISTS 0x11 +#define TPDD_ERR_NO_FILENAME 0x30 +#define TPDD_ERR_DIR_SEARCH_ERR 0x31 +#define TPDD_ERR_BANK_ERR 0x35 +#define TPDD_ERR_PARAM_ERR 0x36 +#define TPDD_ERR_OPEN_FMT_MISMATCH 0x37 +#define TPDD_ERR_END_OF_FILE 0x3f +#define TPDD_ERR_NO_START_MARK 0x40 +#define TPDD_ERR_ID_CRC_CHK_ERR 0x41 +#define TPDD_ERR_SECTOR_LEN_ERR 0x42 +#define TPDD_ERR_FORMAT_VERIF_ERR 0x44 +#define TPDD_ERR_FORMAT_INTERRUPT 0x46 +#define TPDD_ERR_ERASE_OFFSET_ERR 0x47 +#define TPDD_ERR_DATA_CRC_CHK_ERR 0x49 +#define TPDD_ERR_READ_DATA_TIMEOUT 0x4b +#define TPDD_ERR_SECTOR_NUM_ERR 0x4d +#define TPDD_ERR_DISK_WRITE_PROT 0x50 +#define TPDD_ERR_UNINITALIZED_DISK 0x5e +#define TPDD_ERR_DIRECTORY_FULL 0x60 +#define TPDD_ERR_DISK_FULL 0x61 +#define TPDD_ERR_FILE_TOO_LONG 0x6e +#define TPDD_ERR_NO_DISK 0x70 +#define TPDD_ERR_DISK_CHANGE_ERR 0x71 + +// Define CMdline flags +#define CMD_DIR_FLAG_WIDE 0x0001 +#define CMD_DIR_FLAG_DIR 0x0002 + +/* +===================================================================== +Define the TPDD Server class. This will be passed around in C land +as a void* context. +===================================================================== +*/ +class VTTpddServer +{ +public: + VTTpddServer(); + ~VTTpddServer(); + + // Methods + int SerOpenPort(void); + int SerClosePort(void); + const char* SerGetPortName(void); + int SerSetBaud(int baud_rate); + int SerGetFlags(unsigned char *flags); + int SerSetSignals(unsigned char signals); + int SerGetSignals(unsigned char *signals); + int SerReadByte(char *data); + int SerWriteByte(char data); + int SerPoll(void); + + void RootDir(const char *pDir); // Set the root emulation directory + const char* RootDir(void) { return (const char *) m_sRootDir; } + + int ChangeDirectory(const char *pDir); + int ChangeDirectory(MString& sDir); + +private: + void StateCmdline(char data);// Process data while in Cmdline state + void ExecuteCmdline(void); // Executes the command in m_rxBuffer + void ExecuteTpddOpcode(void);// Executes teh opcode in m_rxBuffer (buffer has full packet 'ZZ'+opcode+len+data + + void ResetDirent(void); // Delete all entries in m_activeDir + + // Routines to return data to the server + void SendToHost(char data); // Send a single byte to the host TX buffer + void SendToHost(const char *str); // Send a string to the host + inline void TpddSendByte(char data) { m_txChecksum += (unsigned char) data; SendToHost(data); } + inline void TpddSendChecksum(void) { SendToHost(m_txChecksum ^ 0xFF); } + void SendNormalReturn(unsigned char errCode); + void SendDirEntReturn(dirent* e, int dir_search = FALSE); + void SendDmeResponse(void); + + // TPDD Execution routines + void DirFindFile(const char* pFilename); + void DirFindFirst(void); + void DirFindNext(void); + + MString m_sRootDir; // The path of the root directory + MString m_curDir; // Current subdirectory relative to root + int m_baudRate; // The simulated baud rate + MString m_dirRef; // Directory Reference file within curent directory + int m_refIsDirectory; // Indicates if referenced file is a directory + FILE* m_refFd[TPDD_MAX_FDS]; // Referenced FD + int m_mode[TPDD_MAX_FDS]; // Open mode for each of the FDs + int m_activeFd; // Index of active FD + MStringArray m_args; // Cmdline arguments + VTNADSCmdlineFunc m_backgroundCmd; // Cmdline command executing in the "background" + int m_backgroundFlags; // Argument flags for background command + dirent** m_activeDir; // Active directory listing + dirent** m_dirDir; // Directory listing for 'dir' command + int m_dirCount; // Count of entries in m_activeDir + int m_dirDirCount; // Count of entries in m_dirDir + int m_dirNext; // Next entry in m_activeDir to send to client + int m_dirDirNext; // Next entry in m_dirDir to send to client + int m_tsdosDmeStart; // Indicates start of TS-DOS DME request + int m_tsdosDmeReq; // Indicates 2nd packet of DME request received + int m_lastWasRx; + int m_lastOpenWasDir; // Indicates if last open was a directory change + + int m_rxCount; // Number of bytes in RX buffer (received from Model T) + int m_txCount; // Number of bytes in TX buffer (to be sent to Model T) + char m_rxBuffer[4096]; // Rx Buffer (received from Model T) + char m_txBuffer[4096]; // Tx BUffer (to be sent to Model T) + int m_rxIn; + int m_rxOut; // RX & TX buffer management indices + int m_txIn; + int m_txOut; + int m_txOverflow; // Set true if TX buffer overflows + int m_rxOverflow; // Set true if RX buffer overflows + + int m_state; // The state of the TPDD protocol engine + int m_opcode; // Opcode receivd from client + int m_length; // Length byte received from client + int m_bytesRead; // Number of bytes read from client + unsigned char m_rxChecksum; // Received checksum from client + unsigned char m_calcChecksum; // Calculated checksum + unsigned char m_txChecksum; // Checksum of TX packet + + UINT64 m_lastReadCycles; // Cycle count the last time a byte was sent + UINT64 m_cycleDelay; // Number of cycles to delay between bytes + + // Array of emulated NADSBox cmdline commands + static VT_NADSCmd_t m_Cmds[5]; // Array of our command line commands + static VT_NADSCmd_t m_LinuxCmds[7]; // Array of alias commands for cat, cp, ls, mv, rm + static int m_cmdCount; // Count of commands + static int m_linuxCmdCount; // Count of linux aliases + + // Array of TPDD opcode handler functions (prototype looks like Cmdline func) + static VTTpddOpcodeFunc m_tpddOpcodeHandlers[9/*16*/]; + static int m_tpddOpcodeCount; // Countof opcode handlers + + // Our command line handler functions + int CmdlineHelp(int); // Handler for "help" command + int CmdlineVer(int); // Handler for "ver" command + int CmdlineCd(int); // Handler for "cd" command + int CmdlineDir(int); // Handler for "dir" command + int CmdlinePwd(int); // Handler for "pwd" command + int CmdlineRmdir(int); // Handler for "rmdir" command + int CmdlineMkdir(int); // Handler for "mkdir" command + int CmdlineDel(int); // Handler for "del" command + int CmdlineCopy(int); // Handler for "copy" command + int CmdlineRen(int); // Handler for "ren" command + int CmdlineTrace(int); // Handler for "trace" command + int CmdlineType(int); // Handler for "type" command + int CmdlineDate(int); // Handler for "date" command + int CmdlineTime(int); // Handler for "time" command + int CmdlineInfo(int); // Handler for "info" command + + // Define our TPDD opcode handler functions + virtual void OpcodeDir(void); // Handler for DIR REFERENCE opcode + virtual void OpcodeOpen(void); // Handler for Open opcode + virtual void OpcodeClose(void); // Handler for Close opcode + virtual void OpcodeRead(void); // Handler for Read opcode + virtual void OpcodeWrite(void); // Handler for Write opcode + virtual void OpcodeDelete(void); // Handler for Delete opcode + virtual void OpcodeFormat(void); // Handler for Format opcode + virtual void OpcodeDriveStatus(void);// Handler for Drive Status opcode + virtual void OpcodeId(void); // Handler for ID opcode + virtual void OpcodeMystery23(void); // Handler for the mystery 0x23 opcode + virtual void OpcodeMystery31(void); // Handler for the mystery 0x31 opcode + +}; + +#endif /* __cplusplus */ + +#endif /* TPDDSERVER_H */ + From 2c9c603024ca33ce33e5cc7388ef225f6af8e270 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 20 Feb 2013 21:26:52 +0000 Subject: [PATCH 234/327] Updates in Linux to deal with case sensitive directory names in the NADSBox emulation. Also fixed a couple of compile errors with the newly added code (added from Windows). --- release.txt | 3 +++ src/serial.h | 7 ++++++ src/tpddserver.cpp | 58 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/release.txt b/release.txt index f73bee2..205580b 100644 --- a/release.txt +++ b/release.txt @@ -54,6 +54,9 @@ v1.6 15. Completed the "-nogui" option under Linux and added console interface control. This provides an identical interface to the existing socket / telnet control interface. +16. Added emulated NADSBox (minimal implementation so far) and controls in Peripheral + Setup to connect it to the serial port. + ==================== v1.5 July 9th, 2011 ==================== diff --git a/src/serial.h b/src/serial.h index 4d560d2..cc1e942 100644 --- a/src/serial.h +++ b/src/serial.h @@ -73,6 +73,13 @@ enum { #define SER_SIGNAL_DTR 0x04 #define SER_SIGNAL_RTS 0x08 +#ifndef WIN32 +#define DTR_CONTROL_ENABLE 1 +#define DTR_CONTROL_DISABLE 0 +#define RTS_CONTROL_ENABLE 1 +#define RTS_CONTROL_DISABLE 0 +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/src/tpddserver.cpp b/src/tpddserver.cpp index e347494..b713519 100644 --- a/src/tpddserver.cpp +++ b/src/tpddserver.cpp @@ -34,6 +34,8 @@ #ifdef _WIN32 #include #include +#else +#include #endif #include @@ -661,10 +663,12 @@ int VTTpddServer::SerReadByte(char *data) if (m_txOut >= sizeof(m_txBuffer)) m_txOut = 0; +#if 0 if (m_lastWasRx) printf("\nTX: "); m_lastWasRx = FALSE; printf("%02X ", (unsigned char) *data); +#endif // Decrement the count m_txCount--; @@ -927,7 +931,7 @@ int VTTpddServer::CmdlineDir(int background) // Terminate the message line m_rxIn = m_rxCount = 0; - SendToHost("\r\n"); + SendToHost("\r \r"); } else { @@ -1005,7 +1009,7 @@ int VTTpddServer::CmdlineDir(int background) // Not in wide display format if (!isDir) { - fmt.Format("%-20s%6d\r\n", name, len); + fmt.Format("%-20s%8d\r\n", name, len); fmt.MakeUpper(); } else @@ -1297,7 +1301,7 @@ void VTTpddServer::ExecuteCmdline(void) { // This command matches the rxBuffer. Call the command handler if ((this->*m_Cmds[c].pFunc)(FALSE)) - m_backgroundCmd = this->m_Cmds[c].pFunc; + m_backgroundCmd = m_Cmds[c].pFunc; break; } } @@ -1313,7 +1317,7 @@ void VTTpddServer::ExecuteCmdline(void) { // This command matches the rxBuffer. Call the command handler if ((this->*m_LinuxCmds[c].pFunc)(FALSE)) - m_backgroundCmd = m_Cmds[c].pFunc; + m_backgroundCmd = m_LinuxCmds[c].pFunc; break; } } @@ -1381,10 +1385,13 @@ int VTTpddServer::SerWriteByte(char data) // Record the time of this byte so we can perform timeout // operations in the state machine +#if 0 if (!m_lastWasRx) printf("\nRX: "); m_lastWasRx = TRUE; printf("%02X ", (unsigned char) data); +#endif + // Switch based on state. This is the main state machine switch (m_state) { @@ -2291,7 +2298,8 @@ Change directory to the directory specified */ int VTTpddServer::ChangeDirectory(const char *pDir) { - int ret; + int ret = 0; + MString find_name; // Test if changing to parent directory if (strcmp(pDir, "..") == 0) @@ -2310,19 +2318,57 @@ int VTTpddServer::ChangeDirectory(const char *pDir) else ret = 0; } + else if (strcmp(pDir, ".") == 0) + return 1; else { + MString file_path = m_sRootDir + m_curDir; + dirent** e; + int num = fl_filename_list((const char *) file_path, &e ); + int i; + + // For directories, append the '/' for the search + find_name = pDir; + find_name += '/'; + + // If any files found + if (num > 0) + { + // Loop through all files in the list and perform a + // case insensitive compare + for ( i = 0; i < num; i++ ) + { + const char* name = e[i]->d_name; + + // Compare this file with the requested filename + if (strcasecmp(name, find_name) == 0) + { + // Directory found! Append directory to current directory + m_curDir += name; + ret = 1; + break; + } + } + } + + // Free the directory entries + for (i = 0; i < num; i++) + free((void*) (e[i])); + free((void*) e); + +#if 0 // Test if the directory actually exists MString testDir = m_sRootDir + m_curDir + pDir; if (fl_filename_isdir((const char *) testDir)) { // Append directory to current directory m_curDir += pDir; - m_curDir += "/"; + m_curDir += (char *) "/"; ret = 1; } else ret = 0; +#endif } // Delete existing dirent structure From e5881c67bbd1dbb2d9493b4f9884c636dca70498 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 20 Feb 2013 21:52:32 +0000 Subject: [PATCH 235/327] Minor update to make NADSBox current directory report to TS-DOS all caps. --- src/tpddserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tpddserver.cpp b/src/tpddserver.cpp index b713519..29870bb 100644 --- a/src/tpddserver.cpp +++ b/src/tpddserver.cpp @@ -2251,7 +2251,7 @@ void VTTpddServer::SendDmeResponse(void) // Now copy up to 6 bytes of the dir name while (dir.GetLength() < 6 && c < len) - dir += m_curDir[c++]; + dir += (char) toupper(m_curDir[c++]); // Space pad to 6 characters while (dir.GetLength() < 6) dir += ' '; From e9524c718d2f751c399339b226387d0fc72eda21 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 20 Feb 2013 22:19:45 +0000 Subject: [PATCH 236/327] Fixed issue with dirent structure on Linux when sending "PARENT.<>" --- src/tpddserver.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/tpddserver.cpp b/src/tpddserver.cpp index 29870bb..c36150f 100644 --- a/src/tpddserver.cpp +++ b/src/tpddserver.cpp @@ -1715,7 +1715,13 @@ void VTTpddServer::DirFindFile(const char* pFilename) { // Just save the reference and exit m_dirRef = pFilename; +#ifdef WIN32 dirent* pParent = (dirent *) "PARENT.<>"; +#else + dirent parent; + dirent* pParent = &parent; + strcpy(parent.d_name, "PARENT.<>"); +#endif SendDirEntReturn(pParent, TRUE); return; } @@ -1830,8 +1836,13 @@ void VTTpddServer::DirFindFirst(void) if (m_curDir != "/") { // Send the "PARENT.<>" directory entry - dirent* pParent; - pParent = (dirent *) "PARENT/"; +#ifdef WIN32 + dirent* pParent = (dirent *) "PARENT.<>"; +#else + dirent parent; + dirent* pParent = &parent; + strcpy(parent.d_name, "PARENT.<>"); +#endif SendDirEntReturn(pParent, TRUE); } else From b3255a2d6d0f56800cec6b9aa0961a9fd0b99d7c Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 22 Feb 2013 17:31:49 +0000 Subject: [PATCH 237/327] Added TPDD Sever Log viewer and made updates to the NADSBox server. --- release.txt | 2 + src/display.cpp | 41 +- src/display.h | 39 +- src/serial.c | 2 + src/setup.cpp | 15 +- src/tpddserver.cpp | 586 ++++++++++++++++++--- src/tpddserver.h | 54 +- src/tpddserverlog.cpp | 1132 +++++++++++++++++++++++++++++++++++++++++ src/tpddserverlog.h | 150 ++++++ 9 files changed, 1920 insertions(+), 101 deletions(-) create mode 100644 src/tpddserverlog.cpp create mode 100644 src/tpddserverlog.h diff --git a/release.txt b/release.txt index 205580b..1d5679a 100644 --- a/release.txt +++ b/release.txt @@ -57,6 +57,8 @@ v1.6 16. Added emulated NADSBox (minimal implementation so far) and controls in Peripheral Setup to connect it to the serial port. +17. Added TPDD Server (NADSBox) packet log viewer window to Tools menu. + ==================== v1.5 July 9th, 2011 ==================== diff --git a/src/display.cpp b/src/display.cpp index 6fb9b53..0f07526 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -67,6 +67,7 @@ #include "fileview.h" #include "romstrings.h" #include "remote.h" +#include "tpddserverlog.h" extern "C" { @@ -88,7 +89,9 @@ void set_target_frequency(int freq); void memory_monitor_cb(void); } -void cb_Ide(Fl_Widget* w, void*) ; +// Callback routines to display windows from other modules +void cb_Ide(Fl_Widget* w, void*); +void cb_TpddServerLog(Fl_Widget* w, void*); Fl_Window *MainWin = NULL; T100_Disp *gpDisp; @@ -125,15 +128,16 @@ Fl_Button* gFkeyLabelsButton; class VT_Ide; -extern char* print_xpm[]; -extern Fl_Menu_Item gPrintMenu[]; -extern void Ide_SavePrefs(void); +extern char* print_xpm[]; +extern Fl_Menu_Item gPrintMenu[]; +extern void Ide_SavePrefs(void); extern Fl_Pixmap gPrinterIcon; extern Fl_Pixmap littlehome, little_desktop, little_favorites, ram_drive; extern VTCpuRegs* gcpuw; extern Fl_Window* gmew; extern VT_Ide * gpIde; +extern VTTpddServerLog* gpLog; void switch_model(int model); void key_delay(void); @@ -315,6 +319,10 @@ void close_disp_cb(Fl_Widget* w, void*) ide_was_open = TRUE; } + // Save preferences for TPDD Server Log window + if (gpLog != NULL) + gpLog->SavePreferences(); + // Save open status virtualt_prefs.set("WindowState_MemEdit", memedit_was_open); virtualt_prefs.set("WindowState_CpuRegs", cpuregs_was_open); @@ -1282,6 +1290,7 @@ Fl_Menu_Item menuitems[] = { { "ReMem Configuration", 0, cb_RememCfg, 0, 0 }, { "Peripheral Devices", 0, cb_PeripheralDevices }, { "Model T File Viewer", 0, cb_FileView }, + { "TPDD Server Log", 0, cb_TpddServerLog, 0, FL_MENU_INVISIBLE }, { "Socket Configuration", 0, cb_SocketSetup }, // { "TPDD Client", 0, cb_TpddClient }, { 0 }, @@ -1376,6 +1385,28 @@ void init_menus(void) menuitems[mIndex].flags= remem_menu_flag; } +/* +============================================================================ +Enables or disables the TPDD Packet Log menu item. +============================================================================ +*/ +void enable_tpdd_log_menu(int bEnabled) +{ + int tpdd_menu_flag = FL_MENU_INVISIBLE; + int mIndex; + + if (bEnabled) + { + tpdd_menu_flag = 0; + } + + // Locate the ReMem Configuration menu item + mIndex = 0; + while (menuitems[mIndex].callback_ != cb_TpddServerLog) + mIndex++; + menuitems[mIndex].flags= tpdd_menu_flag; +} + /* ============================================================================ switch_model: This function is called by the menu callback routines that @@ -1969,7 +2000,9 @@ void deinit_display(void) if (MainWin != NULL) { MainWin->hide(); + delete gpDisp; delete MainWin; + gpDisp = NULL; MainWin = NULL; } } diff --git a/src/display.h b/src/display.h index c9e9847..2a48901 100644 --- a/src/display.h +++ b/src/display.h @@ -37,25 +37,26 @@ #ifdef __cplusplus extern "C" { #endif -extern int gDelayUpdateKeys; -void init_pref(void); -void init_display(void); -void deinit_display(void); -void drawbyte(int driver, int column, int value); -void lcdcommand(int driver, int value); -void power_down(); -void process_windows_event(); -void display_cpu_speed(void); -void display_map_mode(char *str); -void show_error(const char*); -void t200_command(unsigned char ir, unsigned char data); -unsigned char t200_readport(unsigned char port); -void handle_simkey(void); -void switch_model(int); -void init_other_windows(void); - -typedef int (*get_key_t)(int); -typedef int (*event_key_t)(void); +extern int gDelayUpdateKeys; +void init_pref(void); +void init_display(void); +void deinit_display(void); +void drawbyte(int driver, int column, int value); +void lcdcommand(int driver, int value); +void power_down(); +void process_windows_event(); +void display_cpu_speed(void); +void display_map_mode(char *str); +void show_error(const char*); +void t200_command(unsigned char ir, unsigned char data); +unsigned char t200_readport(unsigned char port); +void handle_simkey(void); +void switch_model(int); +void init_other_windows(void); +void enable_tpdd_log_menu(int bEnabled); + +typedef int (*get_key_t)(int); +typedef int (*event_key_t)(void); #ifdef __cplusplus diff --git a/src/serial.c b/src/serial.c index 9b5409c..1e12f1d 100644 --- a/src/serial.c +++ b/src/serial.c @@ -110,6 +110,8 @@ int ser_init(void) // Initialize a TPDD client context sp.pTpddContext = tpdd_alloc_context(); tpdd_load_prefs(sp.pTpddContext); + if (setup.com_mode == SETUP_COM_SIM_TPDD) + enable_tpdd_log_menu(TRUE); #ifdef WIN32 sp.tx_empty = TRUE; // Indicate no active TX diff --git a/src/setup.cpp b/src/setup.cpp index 69b8979..6c85882 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -53,7 +53,12 @@ #include "tpddserver.h" extern Fl_Preferences virtualt_prefs; -void init_menus(void); +void init_menus(void); + +extern "C" +{ +void enable_tpdd_log_menu(int bEnabled); +} typedef struct setup_ctrl_struct { @@ -320,6 +325,8 @@ void cb_setup_OK(Fl_Widget* w, void*) strcpy(setup.com_port, ""); strcpy(setup.com_other, setup_ctrl.com.pOtherName->value()); + // Get the com mode + enable_tpdd_log_menu(FALSE); if (setup_ctrl.com.pNone->value() == 1) { ser_set_port((char *) "No Emulation"); @@ -332,6 +339,7 @@ void cb_setup_OK(Fl_Widget* w, void*) ser_set_port(tpdd_get_port_name(ser_get_tpdd_context())); setup.com_mode = SETUP_COM_SIM_TPDD; ser_open_port(); + enable_tpdd_log_menu(TRUE); } else if (setup_ctrl.com.pHost->value() == 1) { @@ -731,6 +739,11 @@ void save_memory_preferences(void) set_memory_base(); } +/* +============================================================================ +Routine to laod the memory preferences from the preferences file. +============================================================================ +*/ void load_memory_preferences(void) { char str[16]; diff --git a/src/tpddserver.cpp b/src/tpddserver.cpp index c36150f..ecb898d 100644 --- a/src/tpddserver.cpp +++ b/src/tpddserver.cpp @@ -36,6 +36,7 @@ #include #else #include +#include #endif #include @@ -50,6 +51,7 @@ #include "VirtualT.h" #include "m100emu.h" #include "tpddserver.h" +#include "tpddserverlog.h" #include "serial.h" #include "display.h" #include "cpuregs.h" @@ -105,47 +107,54 @@ tpddserver_ctrl_t gTsCtrl; // Define the array of NADSBox commands VT_NADSCmd_t VTTpddServer::m_Cmds[] = { - { "cd", &VTTpddServer::CmdlineCd }, + { "cd", &VTTpddServer::CmdlineCd, "cd path - Change Directory" }, // { "copy", &VTTpddServer::CmdlineCopy }, // { "date", &VTTpddServer::CmdlineDate }, // { "del", &VTTpddServer::CmdlineDel }, - { "dir", &VTTpddServer::CmdlineDir }, - { "help", &VTTpddServer::CmdlineHelp }, + { "dir", &VTTpddServer::CmdlineDir, "dir [-dw] [file] - Directory" }, + { "help", &VTTpddServer::CmdlineHelp, "help [command] - Display help" }, // { "info", &VTTpddServer::CmdlineInfo }, // { "mkdir", &VTTpddServer::CmdlineMkdir }, - { "pwd", &VTTpddServer::CmdlinePwd }, + { "pwd", &VTTpddServer::CmdlinePwd, "pwd - Show working directory" }, // { "ren", &VTTpddServer::CmdlineRen }, // { "rmdir", &VTTpddServer::CmdlineRmdir }, // { "time", &VTTpddServer::CmdlineTime }, // { "trace", &VTTpddServer::CmdlineTrace }, // { "type", &VTTpddServer::CmdlineType }, - { "ver", &VTTpddServer::CmdlineVer }, + { "ver", &VTTpddServer::CmdlineVer, "ver - Show emulation version" }, }; int VTTpddServer::m_cmdCount = sizeof(VTTpddServer::m_Cmds) / sizeof(VT_NADSCmd_t); // Define the array of Linux alias commands VT_NADSCmd_t VTTpddServer::m_LinuxCmds[] = { - { "cat", &VTTpddServer::CmdlineType }, - { "cp", &VTTpddServer::CmdlineCopy }, - { "ls", &VTTpddServer::CmdlineDir }, - { "ll", &VTTpddServer::CmdlineDir }, - { "more", &VTTpddServer::CmdlineType }, - { "mv", &VTTpddServer::CmdlineRen }, - { "rm", &VTTpddServer::CmdlineDel }, + { "cat", &VTTpddServer::CmdlineType, "cat - Alias for 'type'" }, + { "cp", &VTTpddServer::CmdlineCopy, "cp - Alias for 'copy'" }, + { "ls", &VTTpddServer::CmdlineDir, "ls - Alias for 'dir -w'" }, + { "ll", &VTTpddServer::CmdlineDir, "ll - Alias for 'dir'" }, + { "more", &VTTpddServer::CmdlineType, "more - Alias for 'type'" }, + { "mv", &VTTpddServer::CmdlineRen, "mv - Alias for 'ren'" }, + { "rm", &VTTpddServer::CmdlineDel, "rm - Alias for 'del'" }, }; int VTTpddServer::m_linuxCmdCount = sizeof(VTTpddServer::m_LinuxCmds) / sizeof(VT_NADSCmd_t); // Define the array of Linux alias commands VTTpddOpcodeFunc VTTpddServer::m_tpddOpcodeHandlers[] = { - &VTTpddServer::OpcodeDir, - &VTTpddServer::OpcodeOpen, - &VTTpddServer::OpcodeClose, - &VTTpddServer::OpcodeRead, - &VTTpddServer::OpcodeWrite, - &VTTpddServer::OpcodeDelete, - &VTTpddServer::OpcodeFormat, - &VTTpddServer::OpcodeDriveStatus, - &VTTpddServer::OpcodeId, + &VTTpddServer::OpcodeDir, // 0x00 + &VTTpddServer::OpcodeOpen, // 0x01 + &VTTpddServer::OpcodeClose, // 0x02 + &VTTpddServer::OpcodeRead, // 0x03 + &VTTpddServer::OpcodeWrite, // 0x04 + &VTTpddServer::OpcodeDelete, // 0x05 + &VTTpddServer::OpcodeFormat, // 0x06 + &VTTpddServer::OpcodeDriveStatus, // 0x07 + &VTTpddServer::OpcodeId, // 0x08 + &VTTpddServer::OpcodeSeek, // 0x09 + &VTTpddServer::OpcodeTell, // 0x0A + &VTTpddServer::OpcodeSetExtended, // 0x0B + &VTTpddServer::OpcodeDriveCond, // 0x0C + &VTTpddServer::OpcodeRename, // 0x0D + &VTTpddServer::OpcodeQueryExtended, // 0x0E + &VTTpddServer::OpcodeCondensedList, // 0x0F }; int VTTpddServer::m_tpddOpcodeCount = sizeof(VTTpddServer::m_tpddOpcodeHandlers) / sizeof(VTNADSCmdlineFunc); @@ -248,7 +257,7 @@ static void cb_tpdd_ok(Fl_Widget* w, void* pOpaque) /* ============================================================================ -Routine to create the TPDD Server window +Routine to create the TPDD Server configuration window ============================================================================ */ void tpdd_server_config(void) @@ -493,7 +502,7 @@ VTTpddServer::VTTpddServer(void) // Clear out the rx and tx buffers m_rxCount = m_txCount = 0; - m_rxIn = m_rxOut = 0; + m_rxIn = 0; m_txIn = m_txOut = 0; for (c = 0; c < TPDD_MAX_FDS; c++) { @@ -507,6 +516,7 @@ VTTpddServer::VTTpddServer(void) m_backgroundCmd = NULL; m_activeDir = NULL; m_dirDir = NULL; + m_logEnabled = FALSE; m_dirCount = m_dirNext = 0; m_tsdosDmeReq = m_tsdosDmeStart = FALSE; @@ -663,12 +673,7 @@ int VTTpddServer::SerReadByte(char *data) if (m_txOut >= sizeof(m_txBuffer)) m_txOut = 0; -#if 0 - if (m_lastWasRx) - printf("\nTX: "); - m_lastWasRx = FALSE; - printf("%02X ", (unsigned char) *data); -#endif + LogData(*data, TPDD_LOG_TX); // Decrement the count m_txCount--; @@ -774,7 +779,7 @@ void VTTpddServer::StateCmdline(char data) } // Now reset the rxBuffer and go to idle - m_rxIn = m_rxOut = m_rxCount = 0; + m_rxIn = m_rxCount = 0; m_state = TPDD_STATE_IDLE; return; } @@ -788,6 +793,10 @@ void VTTpddServer::StateCmdline(char data) SendToHost("\x08 \x08"); m_rxCount--; m_rxIn--; + + // If we backspaced to zero, then go to IDLE state + if (m_rxCount == 0) + m_state = TPDD_STATE_IDLE; } return; @@ -798,7 +807,7 @@ void VTTpddServer::StateCmdline(char data) if (m_rxCount + 1 >= sizeof(m_rxBuffer)) { // Buffer overflow!!! Go to idle state - m_rxIn = m_rxOut = m_rxCount = 0; + m_rxIn = m_rxCount = 0; m_state = TPDD_STATE_IDLE; m_rxOverflow = TRUE; return; @@ -889,6 +898,50 @@ int VTTpddServer::CmdlineCd(int background) return FALSE; } +/* +=========================================================================== +Parses command line option arguments and creates a bitfield based on the +given option string. +=========================================================================== +*/ +int VTTpddServer::ParseOptions(MString& arg, const char* pOptions, int& flags) +{ + int c, x; + int len; + + // Initialize flags to zero + flags = 0; + + // Validate the 1st byte of arg is '-' + if (arg.GetLength() < 2 || arg[0] != '-') + return -1; + + // Start at byte just past '-' + x = 1; + len = strlen(pOptions); + while (x < arg.GetLength()) + { + // Loop through all options + for (c = 0; c < len; c++) + { + if (arg[x] == pOptions[c]) + { + flags |= 1 << c; + break; + } + } + + // Test if an invalid option was given + if (c == len) + return x; + + // Advance to next supplied option + x++; + } + + return -1; +} + /* =========================================================================== Handles the "dir" command @@ -896,7 +949,7 @@ Handles the "dir" command */ int VTTpddServer::CmdlineDir(int background) { - int i, printed; + int i, printed, col; MString file_path; int wide = FALSE; MString fmt; @@ -946,7 +999,35 @@ int VTTpddServer::CmdlineDir(int background) // Test if any args given m_backgroundFlags = 0; - if (m_args.GetSize() == 0) + int options = 0; + int errOption; + if (m_args.GetSize() > 0) + { + // Test if 1st arg is options + if (m_args[0][0] == '-') + { + // Parse the options + if ((errOption = ParseOptions(m_args[0], "wd", m_backgroundFlags)) != -1) + { + // Unknown option given + MString fmt; + fmt.Format("unknown option '%c'\r\n", m_args[0][errOption]); + SendToHost((const char *) fmt); + m_rxIn = m_rxCount = 0; + return FALSE; + } + + // Indicate we used arg0 + options = 1; + } + } + + // Test if this is the 'ls' command and automatically select wide + if (m_cmd == "ls") + m_backgroundFlags |= CMD_DIR_FLAG_WIDE; + + // Test if argument other than options given + if (m_args.GetSize() - options == 0) { Fl_File_Sort_F *sort = fl_casealphasort; @@ -956,7 +1037,7 @@ int VTTpddServer::CmdlineDir(int background) } else { - SendToHost("Arguments not supported yet\r\n"); + SendToHost("arguments not supported yet\r\n"); m_rxIn = m_rxCount = 0; return FALSE; } @@ -967,7 +1048,9 @@ int VTTpddServer::CmdlineDir(int background) // Display a page of entries printed = 0; + col = 0; + // Loop for all directory entries and send the next screen to client for (i = m_dirDirNext; i < m_dirDirCount; i++) { const char* name = m_dirDir[i]->d_name; @@ -986,6 +1069,10 @@ int VTTpddServer::CmdlineDir(int background) if (name[strlen(name)-1] == '/') isDir = TRUE; + // Test if only directories requested + if ((m_backgroundFlags & CMD_DIR_FLAG_DIR) && !isDir) + continue; + // Get length of file if (!isDir) { @@ -1022,6 +1109,43 @@ int VTTpddServer::CmdlineDir(int background) SendToHost((const char *) fmt); printed++; } + else + { + // Printing in wide format... 2 entries per line + + if (!isDir) + { + // Truncate name to 12 places + char temp[13]; + strncpy(temp, name, 12); + temp[12] = '\0'; + if (strlen(name) < 12) + temp[strlen(name)] = '\0'; + + // Max display size is 99999 + if (len < 100000) + fmt.Format("%-13s%6d", temp, len); + else + fmt.Format("%-13>99999", temp); + fmt.MakeUpper(); + } + else + { + MString temp = name; + temp = temp.Left(temp.GetLength()-1); + temp.MakeUpper(); + fmt.Format("%-13s ", (const char *) temp); + } + + SendToHost((const char *) fmt); + if (col++ == 1) + { + col = 0; + printed++; + } + else + SendToHost(" "); + } // Test if a page printed if (gModel == MODEL_T200) @@ -1039,6 +1163,10 @@ int VTTpddServer::CmdlineDir(int background) } } + // Test if we ended on col 1 in a wide format + if ((m_backgroundFlags & CMD_DIR_FLAG_WIDE) && col == 1) + SendToHost("\r\n"); + // Save index for next listing m_dirDirNext = i; @@ -1184,28 +1312,78 @@ int VTTpddServer::CmdlineHelp(int background) // Counts the number of commands printed on this line cmdsThisLine = 0; + m_cycleDelay = rst7cycles * 70 ; + if (m_cycleDelay > 1000000) + m_cycleDelay = 1000000; + if (!background) { - // Loop for all commands - for (c = 0; c < m_cmdCount; c++) + // Test if an argument given + if (m_args.GetSize() == 0) { - SendToHost(m_Cmds[c].pCmd); - if (++cmdsThisLine == 4) + // Loop for all commands + for (c = 0; c < m_cmdCount; c++) { - // Terminate this line - cmdsThisLine = 0; - SendToHost("\r\n"); + SendToHost(m_Cmds[c].pCmd); + if (++cmdsThisLine == 4) + { + // Terminate this line + cmdsThisLine = 0; + SendToHost("\r\n"); + } + else + { + // Send a tab between commands + SendToHost("\t"); + } } - else + + // Test if we need a final CRLF + if (cmdsThisLine != 0) + SendToHost("\r\n"); + } + else + { + // Show help for a specific command + for (c = 0; c < m_cmdCount; c++) { - // Send a tab between commands - SendToHost("\t"); + // Test if this item matches + if (m_args[0] == m_Cmds[c].pCmd) + { + // Display help for this command + SendToHost(m_Cmds[c].pHelp); + SendToHost("\r\n"); + return FALSE; + } + else if (c < m_linuxCmdCount) + { + if (m_args[0] == m_LinuxCmds[c].pCmd) + { + // Display help for this command + SendToHost(m_LinuxCmds[c].pHelp); + SendToHost("\r\n"); + return FALSE; + } + } + + // Test if all commands requested + if (m_args[0] == "all") + { + // Display help for this command + SendToHost(m_Cmds[c].pHelp); + SendToHost("\r\n"); + } } - } - // Test if we need a final CRLF - if (cmdsThisLine != 0) - SendToHost("\r\n"); + // If all commands requested, then return + if (m_args[0] == "all") + return FALSE; + + // Command not found + MString fmt; + fmt.Format("unknown command '%s'\r\n", (const char *) m_args[0]); + SendToHost((const char *) fmt); + } } // Don't need to execute in the background @@ -1300,6 +1478,7 @@ void VTTpddServer::ExecuteCmdline(void) if (strcmp(m_Cmds[c].pCmd, (const char *) cmd) == 0) { // This command matches the rxBuffer. Call the command handler + m_cmd = m_Cmds[c].pCmd; if ((this->*m_Cmds[c].pFunc)(FALSE)) m_backgroundCmd = m_Cmds[c].pFunc; break; @@ -1316,6 +1495,7 @@ void VTTpddServer::ExecuteCmdline(void) if (strcmp(m_LinuxCmds[c].pCmd, (const char *) cmd) == 0) { // This command matches the rxBuffer. Call the command handler + m_cmd = m_LinuxCmds[c].pCmd; if ((this->*m_LinuxCmds[c].pFunc)(FALSE)) m_backgroundCmd = m_LinuxCmds[c].pFunc; break; @@ -1354,10 +1534,9 @@ void VTTpddServer::ExecuteTpddOpcode(void) OpcodeMystery31(); // Normal TPDD protocol opcodes - else if (m_opcode <= TPDD_REQ_ID) + else if (m_opcode <= TPDD_REQ_LAST_OPCODE) { // Call the handler routine for this opcode -// printf("Executing opcode %d\n", m_opcode); (this->*m_tpddOpcodeHandlers[m_opcode])(); } @@ -1373,6 +1552,20 @@ void VTTpddServer::ExecuteTpddOpcode(void) m_state = TPDD_STATE_IDLE; } +/* +=========================================================================== +Logs data to the packet log, either RX or TX data +=========================================================================== +*/ +void VTTpddServer::LogData(char data, int rxTx) +{ + // Log data only if the log is enabled + if (m_logEnabled && m_pServerLog != NULL) + { + m_pServerLog->LogData(data, rxTx); + } +} + /* =========================================================================== Writes a byte to the TPDD Server @@ -1385,12 +1578,8 @@ int VTTpddServer::SerWriteByte(char data) // Record the time of this byte so we can perform timeout // operations in the state machine -#if 0 - if (!m_lastWasRx) - printf("\nRX: "); - m_lastWasRx = TRUE; - printf("%02X ", (unsigned char) data); -#endif + // Log the byte + LogData(data, TPDD_LOG_RX); // Switch based on state. This is the main state machine switch (m_state) @@ -1597,7 +1786,7 @@ int VTTpddServer::SerWriteByte(char data) m_state = TPDD_STATE_IDLE; // Reset the RX buffer - m_rxIn = m_rxOut = m_rxCount = 0; + m_rxIn = m_rxCount = 0; break; } return SER_NO_ERROR; @@ -2127,6 +2316,64 @@ Handles the Delete opcode */ void VTTpddServer::OpcodeDelete(void) { + MString delFile; + int ret; + + // Test if last reference was a directory + if (m_refIsDirectory) + { + // Request to remove a directory. Test if "PARENT.<>" + if (m_dirRef == "PARENT.<>") + { + // Just send normal return + SendNormalReturn(TPDD_ERR_NONE); + return; + } + + // Construct the path of the file to delete + delFile = m_sRootDir + m_curDir + m_dirRef; + +#ifdef WIN32 +#else + ret = rmdir((const char *) delFile); + if (ret == 0) + SendNormalReturn(TPDD_ERR_NONE); + else + { + // Send error based on errno + } +#endif + } + else + { + // Request to delete a file. Construct the path of the file to delete + delFile = m_sRootDir + m_curDir + m_dirRef; +#ifdef WIN32 + ret = DeleteFile((const char *) delFile); + if (ret) + SendNormalReturn(TPDD_ERR_NONE); + else + { + // Send error based on GetLastError() + if (GetLastError() == ERROR_FILE_NOT_FOUND) + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + else + SendNormalReturn(TPDD_ERR_DISK_WRITE_PROT); + } +#else + ret = unlink((const char *) delFile); + if (ret == 0) + SendNormalReturn(TPDD_ERR_NONE); + else + { + // Send error based on errno + if (errno == ENOENT) + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + else + SendNormalReturn(TPDD_ERR_DISK_WRITE_PROT); + } +#endif + } } /* @@ -2172,6 +2419,206 @@ void VTTpddServer::OpcodeId(void) } } +/* +=========================================================================== +Handles the Rename opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeRename(void) +{ + MString old_filename, new_filename; + MString temp; + int ret, idx; + + // Test if last reference was a directory + if (m_refIsDirectory) + { + // Request to rename a directory. Test if "PARENT.<>" + if (m_dirRef == "PARENT.<>") + { + // Just send normal return + SendNormalReturn(TPDD_ERR_NONE); + return; + } + } + + // Validate the length + if (m_length != 25) + { + SendNormalReturn(TPDD_ERR_PARAM_ERR); + return; + } + + // Get the new filename + new_filename = m_sRootDir + m_curDir; + idx = TPDD_PKT_DATA_INDEX; + const int end = TPDD_PKT_DATA_INDEX + 24; // Max filename len + while (m_rxBuffer[idx] != ' ' && m_rxBuffer[idx] != '\0' && idx < end) + new_filename += (char) m_rxBuffer[idx++]; + + // Skip spaces + while (m_rxBuffer[idx] == ' ' && idx < end) + idx++; + + // Now append the extension if not a directory + if (idx < end && m_rxBuffer[idx] == '.') + { + // Test if this is a directory reference or not + if (m_rxBuffer[idx+1] != '<') + { + // Not a directory reference. Append the file extension + new_filename += (char) m_rxBuffer[idx++]; + while (idx != ' ' && idx != '\0' && idx < end) + new_filename += (char) m_rxBuffer[idx++]; + } + } + + // Construct the path of the old filename + old_filename = m_sRootDir + m_curDir + m_dirRef; + +#ifdef WIN32 + ret = Rename((const char *) old_filename, (const char *) new_filename); + if (ret) + SendNormalReturn(TPDD_ERR_NONE); + else + { + // Send error based on GetLastError() + if (GetLastError() == ERROR_FILE_NOT_FOUND) + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + else + SendNormalReturn(TPDD_ERR_DISK_WRITE_PROT); + } +#else + ret = rename((const char *) old_filename, (const char *) new_filename); + if (ret == 0) + SendNormalReturn(TPDD_ERR_NONE); + else + { + // Send error based on errno + if (errno == ENOENT) + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + else + SendNormalReturn(TPDD_ERR_DISK_WRITE_PROT); + } +#endif +} + +/* +=========================================================================== +Handles the Drive Condition opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeDriveCond(void) +{ + // Clear the TX checksum + m_txChecksum = 0; + TpddSendByte(TPDD_RET_CONDITION); + TpddSendByte(1); // Length is 1 + TpddSendByte(0); // Condition - all ok + TpddSendChecksum(); +} + +/* +=========================================================================== +Handles the Seek opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeSeek(void) +{ + int seek_mode, seek_offset; + + // Validate the length and seek mode + if (m_length != 5 || m_rxBuffer[TPDD_PKT_DATA_INDEX] > TPDD_SEEK_END) + { + // Send error condition + SendNormalReturn(TPDD_ERR_PARAM_ERR); + return; + } + + // Validate the file is open and in the right mode + if (m_refFd[m_activeFd] == NULL) + { + // Send error code + SendNormalReturn(TPDD_ERR_OPEN_FMT_MISMATCH); + return; + } + + // Get the seek mode and length + switch (m_rxBuffer[TPDD_PKT_DATA_INDEX]) + { + case TPDD_SEEK_SET: seek_mode = SEEK_SET; break; + case TPDD_SEEK_CUR: seek_mode = SEEK_CUR; break; + case TPDD_SEEK_END: seek_mode = SEEK_END; break; + default: seek_mode = SEEK_SET; break; + } + seek_offset = ((unsigned char) m_rxBuffer[TPDD_PKT_DATA_INDEX+1]) | + ((unsigned char) m_rxBuffer[TPDD_PKT_DATA_INDEX+2] << 8) | + ((unsigned char) m_rxBuffer[TPDD_PKT_DATA_INDEX+3] << 16) | + ((unsigned char) m_rxBuffer[TPDD_PKT_DATA_INDEX+4] << 24); + + // Perform the seek + fseek(m_refFd[m_activeFd], seek_mode, seek_offset); + SendNormalReturn(TPDD_ERR_NONE); +} + +/* +=========================================================================== +Handles the Tell opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeTell(void) +{ + int pos; + + // Validate the file is open and in the right mode + if (m_refFd[m_activeFd] == NULL) + { + // Send error code + SendNormalReturn(TPDD_ERR_OPEN_FMT_MISMATCH); + return; + } + + // Get the current file position + pos = ftell(m_refFd[m_activeFd]); + + // Clear the txChecksum and start the packet + m_txChecksum = 0; + TpddSendByte(TPDD_RET_TELL); + TpddSendByte(4); // Length is 4 bytes offset data + TpddSendByte(pos & 0xFF); // Send LSB + TpddSendByte((pos >> 8) & 0xFF); + TpddSendByte((pos >> 16) & 0xFF); + TpddSendByte((pos >> 24) & 0xFF); // Send MSB + TpddSendChecksum(); +} + +/* +=========================================================================== +Handles the SetExtended opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeSetExtended(void) +{ +} + +/* +=========================================================================== +Handles the QueryExtended opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeQueryExtended(void) +{ +} + +/* +=========================================================================== +Handles the CondensedList opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeCondensedList(void) +{ +} + /* =========================================================================== Handles the Mystery 0x23 opcode @@ -2366,20 +2813,6 @@ int VTTpddServer::ChangeDirectory(const char *pDir) for (i = 0; i < num; i++) free((void*) (e[i])); free((void*) e); - -#if 0 - // Test if the directory actually exists - MString testDir = m_sRootDir + m_curDir + pDir; - if (fl_filename_isdir((const char *) testDir)) - { - // Append directory to current directory - m_curDir += pDir; - m_curDir += (char *) "/"; - ret = 1; - } - else - ret = 0; -#endif } // Delete existing dirent structure @@ -2406,3 +2839,14 @@ void VTTpddServer::ResetDirent(void) m_activeDir = NULL; m_dirCount = 0; } + +/* +=========================================================================== +Delete all entries in m_activeDir +=========================================================================== +*/ +int VTTpddServer::IsCmdlineState(void) +{ + return m_state == TPDD_STATE_CMDLINE; +} + diff --git a/src/tpddserver.h b/src/tpddserver.h index a225c9f..9c884a1 100644 --- a/src/tpddserver.h +++ b/src/tpddserver.h @@ -71,6 +71,7 @@ const char* tpdd_get_port_name(void* pContext); void tpdd_server_config(void); class VTTpddServer; +class VTTpddServerLog; // Typedef for command line and opcode handler typedef int (VTTpddServer::*VTNADSCmdlineFunc)(int background); @@ -80,6 +81,7 @@ typedef struct VT_NADSCmd { const char* pCmd; VTNADSCmdlineFunc pFunc; + const char* pHelp; } VT_NADSCmd_t; // Define offsets within m_rxBuffer of various TPDD fields @@ -102,6 +104,14 @@ typedef struct VT_NADSCmd #define TPDD_REQ_DRIVE_CONDITION 0x0C #define TPDD_REQ_RENAME_FILE 0x0D +// Extended requests for potential future Model "T" DOS usage +#define TPDD_REQ_SEEK 0x09 +#define TPDD_REQ_TELL 0x0A +#define TPDD_REQ_SET_EXTENDED 0x0B +#define TPDD_REQ_QUERY_EXTENDED 0x0E +#define TPDD_REQ_CONDENSED_LIST 0x0F +#define TPDD_REQ_LAST_OPCODE 0x0F + #define TPDD_REQ_TSDOS_MYSTERY23 0x23 #define TPDD_REQ_TSDOS_MYSTERY31 0x31 @@ -155,10 +165,19 @@ typedef struct VT_NADSCmd #define TPDD_ERR_NO_DISK 0x70 #define TPDD_ERR_DISK_CHANGE_ERR 0x71 +// Define Seek codes +#define TPDD_SEEK_SET 1 +#define TPDD_SEEK_CUR 2 +#define TPDD_SEEK_END 3 + // Define CMdline flags #define CMD_DIR_FLAG_WIDE 0x0001 #define CMD_DIR_FLAG_DIR 0x0002 +// Logging defines +#define TPDD_LOG_RX 0 +#define TPDD_LOG_TX 1 + /* ===================================================================== Define the TPDD Server class. This will be passed around in C land @@ -189,12 +208,22 @@ class VTTpddServer int ChangeDirectory(const char *pDir); int ChangeDirectory(MString& sDir); + void RegisterServerLog(VTTpddServerLog* pServerLog) { m_pServerLog = pServerLog; + m_logEnabled = TRUE; } + void UnregisterServerLog(VTTpddServerLog* pServerLog) { m_logEnabled = FALSE; + m_pServerLog = NULL; } + int IsCmdlineState(void); + private: void StateCmdline(char data);// Process data while in Cmdline state void ExecuteCmdline(void); // Executes the command in m_rxBuffer - void ExecuteTpddOpcode(void);// Executes teh opcode in m_rxBuffer (buffer has full packet 'ZZ'+opcode+len+data + void ExecuteTpddOpcode(void);// Executes the opcode in m_rxBuffer + // (buffer has full packet 'ZZ'+opcode+len+data + // General functions void ResetDirent(void); // Delete all entries in m_activeDir + int ParseOptions(MString& args, const char* pOptions, int& flags); + void LogData(char data, int rxTx); // Routines to return data to the server void SendToHost(char data); // Send a single byte to the host TX buffer @@ -218,6 +247,7 @@ class VTTpddServer FILE* m_refFd[TPDD_MAX_FDS]; // Referenced FD int m_mode[TPDD_MAX_FDS]; // Open mode for each of the FDs int m_activeFd; // Index of active FD + MString m_cmd; // The command that is executing MStringArray m_args; // Cmdline arguments VTNADSCmdlineFunc m_backgroundCmd; // Cmdline command executing in the "background" int m_backgroundFlags; // Argument flags for background command @@ -229,15 +259,16 @@ class VTTpddServer int m_dirDirNext; // Next entry in m_dirDir to send to client int m_tsdosDmeStart; // Indicates start of TS-DOS DME request int m_tsdosDmeReq; // Indicates 2nd packet of DME request received - int m_lastWasRx; + int m_lastWasRx; // Indicates if last logged byte was RX + int m_logEnabled; // Set TRUE when logging enabled int m_lastOpenWasDir; // Indicates if last open was a directory change + VTTpddServerLog* m_pServerLog; // Server log object for logging data int m_rxCount; // Number of bytes in RX buffer (received from Model T) int m_txCount; // Number of bytes in TX buffer (to be sent to Model T) - char m_rxBuffer[4096]; // Rx Buffer (received from Model T) + char m_rxBuffer[1024]; // Rx Buffer (received from Model T) char m_txBuffer[4096]; // Tx BUffer (to be sent to Model T) int m_rxIn; - int m_rxOut; // RX & TX buffer management indices int m_txIn; int m_txOut; int m_txOverflow; // Set true if TX buffer overflows @@ -261,7 +292,7 @@ class VTTpddServer static int m_linuxCmdCount; // Count of linux aliases // Array of TPDD opcode handler functions (prototype looks like Cmdline func) - static VTTpddOpcodeFunc m_tpddOpcodeHandlers[9/*16*/]; + static VTTpddOpcodeFunc m_tpddOpcodeHandlers[16]; static int m_tpddOpcodeCount; // Countof opcode handlers // Our command line handler functions @@ -289,8 +320,19 @@ class VTTpddServer virtual void OpcodeWrite(void); // Handler for Write opcode virtual void OpcodeDelete(void); // Handler for Delete opcode virtual void OpcodeFormat(void); // Handler for Format opcode - virtual void OpcodeDriveStatus(void);// Handler for Drive Status opcode virtual void OpcodeId(void); // Handler for ID opcode + virtual void OpcodeDriveStatus(void);// Handler for Drive Status opcode + virtual void OpcodeDriveCond(void); // Handler for Drive Condition opcode + virtual void OpcodeRename(void); // Handler for Rename opcode + + // Extended opcodes + virtual void OpcodeSeek(void); // Handler for Seek opcode + virtual void OpcodeTell(void); // Handler for Tell opcode + virtual void OpcodeSetExtended(void);// Handler for SetExtended opcode + virtual void OpcodeQueryExtended(void);// Handler for QueryExtended opcode + virtual void OpcodeCondensedList(void);// Handler for CondensedList opcode + + // Mystery opcodes virtual void OpcodeMystery23(void); // Handler for the mystery 0x23 opcode virtual void OpcodeMystery31(void); // Handler for the mystery 0x31 opcode diff --git a/src/tpddserverlog.cpp b/src/tpddserverlog.cpp new file mode 100644 index 0000000..4cc9090 --- /dev/null +++ b/src/tpddserverlog.cpp @@ -0,0 +1,1132 @@ +/* tpddserverlog.cpp */ + +/* $Id$ */ + +/* + * Copyright 2013 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include + +#include "FLU/Flu_File_Chooser.h" + +#include "VirtualT.h" +#include "m100emu.h" +#include "tpddserver.h" +#include "tpddserverlog.h" +#include "display.h" +#include "serial.h" + +// =============================================== +// Extern "C" linkage items +// =============================================== +extern "C" +{ +extern volatile UINT64 cycles; +extern volatile DWORD rst7cycles; + +} + +// =============================================== +// Extern and global variables +// =============================================== +extern Fl_Preferences virtualt_prefs; +VTTpddServerLog* gpLog = NULL; + +static void cb_load_log(Fl_Widget* w, void* pOpaque); +static void cb_save_log(Fl_Widget* w, void* pOpaque); +static void cb_setup_log(Fl_Widget* w, void* pOpaque); + +void cb_CpuRegs(Fl_Widget* w, void* pOpaque); +void cb_Ide(Fl_Widget* w, void* pOpaque); +void disassembler_cb(Fl_Widget* w, void* pOpaque); +void cb_PeripheralDevices(Fl_Widget* w, void* pOpaque); +void cb_FileView(Fl_Widget* w, void* pOpaque); + +static Fl_Menu_Item gServerLog_menuitems[] = { + { "&File", 0, 0, 0, FL_SUBMENU }, + { "Load from File...", 0, cb_load_log, 0 }, + { "Save to File...", 0, cb_save_log, 0, 0 /*FL_MENU_DIVIDER*/ }, +// { "Setup...", 0, cb_setup_log, 0}, + { 0 }, + + { "&Tools", 0, 0, 0, FL_SUBMENU }, + { "CPU Registers", 0, cb_CpuRegs }, + { "Assembler / IDE", 0, cb_Ide }, + { "Disassembler", 0, disassembler_cb }, + { "Peripheral Devices", 0, cb_PeripheralDevices }, + { "Model T File Viewer", 0, cb_FileView }, + { 0 }, + + { 0 } +}; + +/* +============================================================================ +Callback routine for the File Viewer window +============================================================================ +*/ +void cb_server_log (Fl_Widget* w, void* pOpaque) +{ + VTTpddServerLog* pLog = (VTTpddServerLog *) pOpaque; + + // Hide the window + pLog->hide(); + + // If we are closing the root window, then save preferences + if (pLog == gpLog) + pLog->SavePreferences(); + + // Delete the window and set to NULL + delete pLog; + + if (pLog == gpLog) + { + VTTpddServer* pServer = (VTTpddServer *) ser_get_tpdd_context(); + pServer->UnregisterServerLog(pLog); + gpLog = NULL; + } +} + +/* +============================================================================ +Callback for disable checkbox +============================================================================ +*/ +static void cb_disable_log(Fl_Widget* w, void* pOpaque) +{ + VTTpddServerLog* pLog = (VTTpddServerLog *) pOpaque; + + pLog->CheckboxCallback(); +} + +/* +============================================================================ +Callback for load log +============================================================================ +*/ +static void cb_load_log(Fl_Widget* w, void* pOpaque) +{ + Flu_File_Chooser* fc; + char fc_path[256]; + int count; + const char *filename; + VTTpddServerLog* pLog; + CFileString fileStr; + MString filePath; + + // Create chooser window to pick file + strcpy(fc_path, path); + strcat(fc_path,"/*.txt"); + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser(fc_path, "Text Files (*.txt)", 0, "Load Log Data From..."); + fl_cursor(FL_CURSOR_DEFAULT); + fc->preview(0); + fc->show(); + + // Show Chooser window + while (fc->visible()) + Fl::wait(); + + count = fc->count(); + if (count == 0) + { + delete fc; + return; + } + + // Get Filename + filename = fc->value(); + if (filename == 0) + { + delete fc; + return; + } + + // Check extension of filename + fileStr = filename; + filePath = filename; + if (fileStr.Ext() == "") + filePath += (char *) ".txt"; + + // Copy the new root + pLog = (VTTpddServerLog *) pOpaque; + if (pLog == NULL) + pLog = gpLog; + if (pLog == NULL) + pLog = gpLog; + pLog->LoadFile((const char *) filePath); + + delete fc; +} + +/* +============================================================================ +Callback for setup dialog +============================================================================ +*/ +static void cb_setup_log(Fl_Widget* w, void* pOpaque) +{ +} + +/* +============================================================================ +Callback for redrawing the window +============================================================================ +*/ +static void cb_redraw(void* pOpaque) +{ + VTTpddServerLog* pLog = (VTTpddServerLog *) pOpaque; + pLog->m_callbackActive = FALSE; + pLog->redraw(); +} + +/* +============================================================================ +Callback for the scrollbar +============================================================================ +*/ +static void cb_scroll_log(Fl_Widget* w, void* pOpaque) +{ + VTTpddServerLog* pLog = (VTTpddServerLog *) pOpaque; + pLog->redraw(); +} + +/* +============================================================================ +Callback for the clear log button +============================================================================ +*/ +static void cb_clear_log(Fl_Widget* w, void* pOpaque) +{ + VTTpddServerLog* pLog = (VTTpddServerLog *) pOpaque; + pLog->ResetContent(); + pLog->resize(pLog->x(), pLog->y(), pLog->w(), pLog->h()); + pLog->redraw(); +} + +/* +============================================================================ +Callback routine to read TPDD / NADSBox directory +============================================================================ +*/ +static void cb_save_log(Fl_Widget* w, void* pOpaque) +{ + Flu_File_Chooser* fc; + char fc_path[256]; + int count; + const char *filename; + VTTpddServerLog* pLog; + CFileString fileStr; + MString filePath; + + // Create chooser window to pick file + strcpy(fc_path, path); + strcat(fc_path,"/*.txt"); + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser(fc_path, "Text Files (*.txt)", 0, "Save Log Data As..."); + fl_cursor(FL_CURSOR_DEFAULT); + fc->preview(0); + fc->show(); + + // Show Chooser window + while (fc->visible()) + Fl::wait(); + + count = fc->count(); + if (count == 0) + { + delete fc; + return; + } + + // Get Filename + filename = fc->value(); + if (filename == 0) + { + delete fc; + return; + } + + // Check extension of filename + fileStr = filename; + filePath = filename; + if (fileStr.Ext() == "") + filePath += (char *) ".txt"; + + // Copy the new root + pLog = (VTTpddServerLog *) pOpaque; + pLog->SaveFile((const char *) filePath); + + delete fc; +} + +/* +============================================================================ +Routine to create the TPDD Server configuration window +============================================================================ +*/ +void cb_TpddServerLog(Fl_Widget* w, void* pOpaque) +{ + VTTpddServerLog* pLog; + + // Test if requesting a 2nd root log window + if (pOpaque == NULL && gpLog != NULL) + { + gpLog->show(); + return; + } + + // Create TPDD Server Log window + pLog = new VTTpddServerLog(470, 300, "TPDD Server Log"); + pLog->callback(cb_server_log, pLog); + pLog->LoadPreferences(); + + // Show the window + pLog->show(); + + // If this is the root log, then assign it + if (pOpaque == NULL) + { + // Save this as the root log + gpLog = pLog; + + VTTpddServer* pServer = (VTTpddServer *) ser_get_tpdd_context(); + pServer->RegisterServerLog(pLog); + pLog->Server(pServer); + + // Now resize if we have saved preferences + pLog->ResizeToPref(); + } +} + +/* +============================================================================ +Class constructor +============================================================================ +*/ +VTTpddServerLog::VTTpddServerLog(int w, int h, const char* title) : + Fl_Double_Window(w, h, title) +{ + Fl_Box* o; + Fl_Button* b; + Fl_Group* g; + + // Initialize everything + m_pServer = NULL; + m_enabled = TRUE; + m_lastWasRx = FALSE; + m_rxCount = m_txCount = 0; + m_maxLogEntries = 8192; + m_nextRef = 1; + m_callbackActive = FALSE; + + // Define our default colors + m_colors.background = FL_BLACK; + m_colors.ref = FL_WHITE; + m_colors.rxLabel = FL_YELLOW; + m_colors.txLabel = (Fl_Color) 221; + m_colors.rxHex = fl_color_average(FL_DARK_GREEN, FL_WHITE, 0.8); + m_colors.txHex = fl_color_average((Fl_Color) 221, FL_WHITE, 0.5); + m_colors.rxAscii = FL_GREEN; + m_colors.txAscii = (Fl_Color) 221; + m_fontSize = 14; + + fl_font(FL_COURIER, m_fontSize); + m_height = fl_height(); + m_width = fl_width("W"); + + // =============================== + // Now create the controls we need + // =============================== + + // Create a menu + m_pMenu = new Fl_Menu_Bar(0, 0, w, MENU_HEIGHT-2); + m_pMenu->menu(gServerLog_menuitems); + + // Create a window for the log + m_pLog = new Fl_Double_Window(10, MENU_HEIGHT+10, w-20-15, h-MENU_HEIGHT-50, ""); + //m_pLog->color(FL_BLACK); + m_pLog->end(); + m_pLog->hide(); + + // Create a scrollbar + m_pScroll = new Fl_Scrollbar(w-10-15, MENU_HEIGHT+10, 15, h-MENU_HEIGHT-50, ""); + m_pScroll->callback(cb_scroll_log, this); + + // Create a resizing group + g = new Fl_Group(0, h-35, w, 35, ""); + + // Create a disable log checkbox + m_pDisable = new Fl_Check_Button(20, h-30, 110, 20, "Disable log"); + m_pDisable->callback(cb_disable_log, this); + + // Create a Save button + b = new Fl_Button(150, h-30, 80, 20, "Save"); + b->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE); + b->callback(cb_save_log, this); + + // Create a Load button + b = new Fl_Button(250, h-30, 80, 20, "Load"); + b->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE); + b->callback(cb_load_log, this); + + // Create a clear button + b = new Fl_Button(350, h-30, 80, 20, "Clear"); + b->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE); + b->callback(cb_clear_log, this); + + // Make the group resizable + o = new Fl_Box(440, 350, 5, 5, ""); + g->resizable(o); + g->end(); + + // Make the window resizable + o = new Fl_Box(20, MENU_HEIGHT + 30, 5, 5, ""); + resizable(o); + + // Set the scrollbar size + SetScrollSizes(); +} + +/* +============================================================================ +Class destructor +============================================================================ +*/ +VTTpddServerLog::~VTTpddServerLog(void) +{ + // Reset all content + ResetContent(); +} + +/* +============================================================================ +Our custom draw routine +============================================================================ +*/ +void VTTpddServerLog::draw(void) +{ + int xMargin = 7; + int topEntry, lines, line, idx; + int dataIdx, x, count, tempRef = m_nextRef; + int wx, wy, dataStart, labelStart, dataX, labelX, asciiX; + char str[10]; + VTTpddLogEntry* pEntry, rxEntry, txEntry; + + // Do default FLTK stuff + Fl_Double_Window::draw(); + + // Push a clipping rect + fl_push_clip(m_pLog->x(), m_pLog->y(), m_pLog->w(), m_pLog->h()); + + // Draw the log background + fl_color(m_colors.background); + fl_font(FL_COURIER, m_fontSize); + fl_rectf(m_pLog->x(), m_pLog->y(), m_pLog->w(), m_pLog->h()); + + // Calculate the number of lines that fit in the window + lines = m_pLog->h() / m_height; + wy = m_pLog->y(); + wx = m_pLog->x(); + + // Get the top entry of the display + topEntry = m_pScroll->value(); + + // Create fake rx and tx entries + rxEntry.m_ref = tempRef; + if (m_rxCount > 0) + tempRef++; + rxEntry.m_pData = m_rxBuffer; + rxEntry.m_rxTx = 0; + rxEntry.m_count = m_rxCount; + + txEntry.m_ref = tempRef; + txEntry.m_pData = m_txBuffer; + txEntry.m_rxTx = 1; + txEntry.m_count = m_txCount; + + // Precalculate x offsets + labelStart = 6; + dataStart = labelStart + 4; + labelX = labelStart * m_width + wx + xMargin; + dataX = dataStart * m_width + wx + xMargin; + asciiX = dataX + (2 + m_bytesPerLine * 3) * m_width; + + // Loop for all lines that can be displayed + line = 1; + idx = 0; + + count = m_log.GetSize(); + while (line <= lines && topEntry + idx < count + 2) + { + // Get the next log item to be displayed + if (topEntry + idx == count) + pEntry = &rxEntry; + else if (topEntry + idx == count+1) + pEntry = &txEntry; + else + pEntry = (VTTpddLogEntry *) m_log[topEntry + idx]; + dataIdx = 0; + + // Draw RX or TX as per the entry + if (pEntry->m_count > 0) + { + // Draw the reference number + if (pEntry->m_ref != -1) + { + // Print the reference number + fl_color(m_colors.ref); + sprintf(str, "%4d:", pEntry->m_ref); + fl_draw(str, wx + xMargin, wy + line * m_height); + } + + // Draw either TX or RX + if (pEntry->m_rxTx) + { + // It's a TX entry + fl_color(m_colors.txLabel); + fl_draw("TX:", labelX, wy + line * m_height); + fl_color(m_colors.txHex); + } + else + { + // It's an RX entry + fl_color(m_colors.rxLabel); + fl_draw("RX:", labelX, wy + line * m_height); + fl_color(m_colors.rxHex); + } + } + + // Loop for all data + while (dataIdx < pEntry->m_count && line <= lines) + { + // Select the proper color + if (pEntry->m_rxTx) + fl_color(m_colors.txHex); + else + fl_color(m_colors.rxHex); + + // Draw bytesPerLine hex values on the current line + int c = 0; + for (x = dataIdx; x < pEntry->m_count && c < m_bytesPerLine; x++) + { + // Format the data to draw the HEX data + sprintf(str, "%02X", (unsigned char) pEntry->m_pData[x]); + fl_draw(str, dataX + c++ * m_width*3, wy + line * m_height); + } + + // Select the proper color + if (pEntry->m_rxTx) + fl_color(m_colors.txAscii); + else + fl_color(m_colors.rxAscii); + + // Draw bytesPerLine ASCII values + c = 0; + for (x = dataIdx; x < pEntry->m_count && c < m_bytesPerLine; x++) + { + // Format the data to draw the HEX data + if (pEntry->m_pData[x] >= ' ' && pEntry->m_pData[x] <= '~') + sprintf(str, "%c", pEntry->m_pData[x]); + else + strcpy(str, "."); + fl_draw(str, asciiX + c++ * m_width, wy + line * m_height); + } + + // Increment to next dataIdx + dataIdx = x; + line++; + } + + // Advance to next entry + idx++; + } + + // Pop the clipping rect + fl_pop_clip(); +} + +/* +============================================================================ +Our custom handle routine +============================================================================ +*/ +int VTTpddServerLog::handle(int event) +{ + // Do default FLTK stuff + return Fl_Double_Window::handle(event); +} + +/* +============================================================================ +Our custom resize routine +============================================================================ +*/ +void VTTpddServerLog::resize(int nx, int ny, int nw, int nh) +{ + // Do default FLTK stuff + Fl_Double_Window::resize(nx, ny, nw, nh); + + int xOffset = 7; + m_bytesPerLine = (m_pLog->w() - xOffset*2 - 12*m_width) / 4 / m_width; + + // Now set the new scrollbar size + SetScrollSizes(); +} + +/* +============================================================================ +Log data to the TPPD Server Log +============================================================================ +*/ +void VTTpddServerLog::LogData(char data, int rxTx) +{ + // Test if logging is enabled + if (m_enabled) + { + int cmdlineState = m_pServer->IsCmdlineState(); + + // Test if logging RX data + if (rxTx == TPDD_LOG_RX) + { + // Test if last logged data was RX or not + if (!m_lastWasRx && !cmdlineState) + { + // We are starting a new RX entry. Save the existing TX entry + // And start a new RX entry + if (m_rxCount > 0) + AddNewEntry(TPDD_LOG_RX, m_rxCount, m_rxBuffer); + if (m_txCount > 0) + AddNewEntry(TPDD_LOG_TX, m_txCount, m_txBuffer); + m_txCount = 0; + m_rxCount = 0; + //printf("\nRX: "); + } + m_lastWasRx = TRUE; + m_rxBuffer[m_rxCount++] = data; + + // Test if the rxBuffer is full + if (m_rxCount == sizeof(m_rxBuffer)) + { + // Need to dump this packet and start a new one + AddNewEntry(TPDD_LOG_RX, m_rxCount, m_rxBuffer); + m_rxCount = 0; + } + + //printf("%02X ", (unsigned char) data); + } + else + { + // Logging TX data test if starting a new TX packet + if (m_lastWasRx && !cmdlineState) + { + // We are starting a new RX entry. Save the existing TX entry + // And start a new RX entry + if (m_rxCount > 0) + AddNewEntry(TPDD_LOG_RX, m_rxCount, m_rxBuffer); + if (m_txCount > 0) + AddNewEntry(TPDD_LOG_TX, m_txCount, m_txBuffer); + m_txCount = m_rxCount = 0; + //printf("\nTX: "); + } + m_lastWasRx = FALSE; + + // Add data to the tx buffer + m_txBuffer[m_txCount++] = data; + + // Test if the TX buffer is full + if (m_txCount == sizeof(m_txBuffer)) + { + // Need to dump this packet and start a new one + AddNewEntry(TPDD_LOG_TX, m_txCount, m_txBuffer); + m_txCount = 0; + } + + //printf("%02X ", (unsigned char) data); + } + } + + + // TODO: Make redrawing smarter and add auto-scroll + if (!m_callbackActive) + { + Fl::add_timeout(0.1, cb_redraw, this); + m_callbackActive = TRUE; + } +} + +/* +============================================================================ +Add a new log entry to the log +============================================================================ +*/ +void VTTpddServerLog::AddNewEntry(int rxTx, int count, char* pBuffer) +{ + VTTpddLogEntry* pEntry = new VTTpddLogEntry; + + // Validate memory was allocated + if (pEntry != NULL) + { + pEntry->m_ref = m_nextRef++; + pEntry->m_count = count; + pEntry->m_rxTx = rxTx; + pEntry->m_pData = new char[count]; + + // Validate memory was allocated + if (pEntry->m_pData == NULL) + { + // Delete this entry and return + delete pEntry; + return; + } + + // Copy memory to the buffer + memcpy(pEntry->m_pData, pBuffer, count); + + // Test if the max number of entries already reached + // and delete the oldest one if full + if (m_log.GetSize() >= m_maxLogEntries) + { + // Get the oldest entry and delete it + VTTpddLogEntry* pDelEntry = (VTTpddLogEntry *) m_log[0]; + delete[] pDelEntry->m_pData; + delete pDelEntry; + + // Now remove it from the log + m_log.RemoveAt(0, 1); + } + + // Add the entry to our log + m_log.Add(pEntry); + + // TODO: Update scrollbar settings + SetScrollSizes(); + } +} + +/* +============================================================================ +Sets the scrollbar settings based on current geometry and item count. +============================================================================ +*/ +void VTTpddServerLog::SetScrollSizes(void) +{ + int size, height, count, max; + int lines, c; + VTTpddLogEntry* pEntry; + + // Select 12 point Courier font + fl_font(FL_COURIER, m_fontSize); + + // Get character width & height + height = m_pLog->h(); + size = (int) (height / m_height); + count = m_log.GetSize(); + + // Count the number of lines that will be disiplayed + if (m_bytesPerLine == 0) + m_bytesPerLine = 1; + lines = 0; + for (c = 0; c < count; c++) + { + // Get next entry + pEntry = (VTTpddLogEntry *) m_log[c]; + lines += (pEntry->m_count+m_bytesPerLine-1) / m_bytesPerLine; + } + lines += (m_rxCount+m_bytesPerLine-1) / m_bytesPerLine; + lines += (m_txCount+m_bytesPerLine-1) / m_bytesPerLine; + + // Set maximum value of scroll + if (m_pScroll->value()+size-1 > count ) + { + int newValue = count-size+1; + if (newValue < 0) + newValue = 0; + m_pScroll->value(newValue, 0, 0, count-2); + } + max = count + 1 - size; + if (max < 1) + max = 1; + m_pScroll->maximum(count-2); + m_pScroll->minimum(0); + if (lines > 1) + { + m_pScroll->step((double) size/(double)(lines-1)); + m_pScroll->slider_size((double) size/(double)(lines-1)); + } + m_pScroll->linesize(1); + + redraw(); +} + +/* +============================================================================ +Resets the content of the log (i.e. clears it out) +============================================================================ +*/ +void VTTpddServerLog::ResetContent(void) +{ + int count, c; + VTTpddLogEntry* pEntry; + + count = m_log.GetSize(); + for(c = 0; c < count; c++) + { + // Get next log entry + pEntry = (VTTpddLogEntry *) m_log[c]; + + // Delete the data memory + delete[] pEntry->m_pData; + delete pEntry; + } + + m_log.RemoveAll(); + + // Reset other vars too + m_rxCount = m_txCount = 0; + m_lastWasRx = FALSE; + m_nextRef = 1; +} + +/* +============================================================================ +Called when the disable log checkbox is modified +============================================================================ +*/ +void VTTpddServerLog::CheckboxCallback(void) +{ + m_enabled = !m_pDisable->value(); +} + +/* +============================================================================ +Called to resize the window and position to user preference settings +============================================================================ +*/ +void VTTpddServerLog::ResizeToPref(void) +{ + if (m_x != -1 && m_y != -1 && m_w != -1 && m_h != -1) + resize(m_x, m_y, m_w, m_h); +} + +/* +============================================================================ +Saves the log data to a file using the current window width +============================================================================ +*/ +void VTTpddServerLog::SaveFile(MString filename) +{ + FILE* fd; + int count, c, i, dataIdx; + VTTpddLogEntry* pEntry; + MString fmt, hexFmt; + + // Validate we have data + if (m_log.GetSize() == 0) + return; + + // Test if the file exists + if ((fd = fopen((const char *) filename, "r")) != NULL) + { + // Close the file + fclose(fd); + int ans = fl_choice("Overwrite existing file %s?", "Ok", "Cancel", NULL, + fl_filename_name((const char *) filename)); + if (ans == 1) + return; + } + + // Try to open the file + if ((fd = fopen((const char *) filename, "w")) == NULL) + { + MString err; + + err.Format("Unable to create file %s\n", (const char *) filename); + fl_message("%s", (const char *) err); + return; + } + + // Test if any leftover RX or TX data not logged to an entry yet + if (m_rxCount > 0) + AddNewEntry(TPDD_LOG_RX, m_rxCount, m_rxBuffer); + if (m_txCount > 0) + AddNewEntry(TPDD_LOG_TX, m_txCount, m_txBuffer); + m_txCount = 0; + m_rxCount = 0; + + // Now loop for all entries + count = m_log.GetSize(); + for (c = 0; c < count; c++) + { + // Get the next entry + pEntry = (VTTpddLogEntry *) m_log[c]; + fmt.Format("%4d: %s: ", pEntry->m_ref, pEntry->m_rxTx ? "TX" : "RX"); + i = 0; + dataIdx = 0; + while (dataIdx < pEntry->m_count) + { + if (dataIdx != 0) + fmt = " "; + // "Print" the HEX data to the line + for (i = 0; i < m_bytesPerLine && dataIdx + i < pEntry->m_count; i++) + { + hexFmt.Format("%02X ", (unsigned char) pEntry->m_pData[dataIdx + i]); + fmt += hexFmt; + } + + // Pad with spaces if less then m_bytesPerLine + for ( ; i < m_bytesPerLine; i++) + fmt += (char *) " "; + + // "Print" the ASCII data to the line + fmt += (char *) " "; + for (i = 0; i < m_bytesPerLine && dataIdx + i < pEntry->m_count; i++) + { + // Test if it's actual ASCII data or not + if (pEntry->m_pData[dataIdx + i] >= ' ' && pEntry->m_pData[dataIdx + i] <= '~') + hexFmt.Format("%c", (unsigned char) pEntry->m_pData[dataIdx + i]); + else + hexFmt = '.'; + fmt += hexFmt; + } + + // Save to the file + fprintf(fd, "%s\n", (const char *) fmt); + dataIdx += i; + } + } + + // Close the file + fclose(fd); +} + +/* +============================================================================ +Loads the log data from a file. +============================================================================ +*/ +int VTTpddServerLog::LoadFile(MString filename) +{ + FILE* fd; + int c, lineNo, rxTx; + //VTTpddLogEntry* pEntry; + //MString fmt, hexFmt; + char line[256]; + char *ptr; + + // Test if we are loading from the root window + if (this == gpLog) + { + // Don't load files from the root window. Create a new window + VTTpddServerLog* pLog = new VTTpddServerLog(w(), h(), "TPDD Log Viewer"); + + // Validate the window was created + if (pLog == NULL) + return FALSE; + + // Let the new window open the log + if (!pLog->LoadFile(filename)) + { + // Load was not successful. Destroy the window + delete pLog; + return FALSE; + } + + // Now show the new window + pLog->show(); + pLog->resize(x()+MENU_HEIGHT, y()+MENU_HEIGHT, w(), h()); + return TRUE; + } + + // Try to open the file + if ((fd = fopen(filename, "r")) == NULL) + { + fl_message("Unable to open file %s", fl_filename_name((const char *) filename)); return FALSE; + } + + // Loop for all data in the file + lineNo = 0; + while (fgets(line, sizeof(line), fd) != NULL) + { + // Start at beginning of line + ptr = line; + c = 0; + lineNo++; + + // Search for a reference. This means we log the existing entry and start a new one + while (*ptr == ' ') + { + // Increment ptr and c + ptr++; + c++; + } + + // Test if a reference found + if (c < 4) + { + // Validate the file format + if (*ptr < '0' || *ptr > '9') + { + // Not a trace file!! + fl_message("This does not appear to be a valid file on line %d", lineNo); + return FALSE; + } + + // Reference found. This entry and start a new one + if (m_rxCount > 0) + AddNewEntry(TPDD_LOG_RX, m_rxCount, m_rxBuffer); + if (m_txCount > 0) + AddNewEntry(TPDD_LOG_TX, m_txCount, m_txBuffer); + m_txCount = 0; + m_rxCount = 0; + + // Skip past the reference and find the ':' + while (*ptr != ':' && c < sizeof(line)) + { + // Increment pointer and index + ptr++; + c++; + } + + // Test if ':' found + if (c >= sizeof(line) || *ptr != ':') + { + // Not a trace file!! + fl_message("This does not appear to be a valid file on line %d", lineNo); + return FALSE; + } + + // Skip the ':' and spaces after it + ptr += 2; + c += 2; + + // Now get RX/TX marker + if (*ptr == 'T') + rxTx = 1; + else if (*ptr == 'R') + rxTx = 0; + else + { + // Not a trace file!! + fl_message("This does not appear to be a valid file on line %d", lineNo); + return FALSE; + } + + // Skip past "RX: " or "TX: " + ptr += 4; + c += 4; + } + + // Now we are pointing at the HEX data. Read all data from this line into + // either the m_rxBuffer or m_txBuffer + while (*ptr != ' ' && *ptr != '\0' && c < sizeof(line)) + { + unsigned char val; + + val = (*ptr > '9' ? *ptr = 'A' + 10 : *ptr - '0') << 4; + ptr++; + val += *ptr > '9' ? *ptr = 'A' + 10 : *ptr - '0'; + ptr += 2; + c += 3; + + // Now save val in either rx or tx buffer + if (rxTx) + { + m_txBuffer[m_txCount++] = val; + if (m_txCount >= sizeof(m_txBuffer)) + { + AddNewEntry(TPDD_LOG_TX, m_txCount, m_txBuffer); + m_txCount = 0; + } + } + else + { + m_rxBuffer[m_rxCount++] = val; + if (m_rxCount >= sizeof(m_rxBuffer)) + { + AddNewEntry(TPDD_LOG_RX, m_rxCount, m_rxBuffer); + m_rxCount = 0; + } + } + } + } + + // Log any remaining data + if (m_rxCount > 0) + AddNewEntry(TPDD_LOG_RX, m_rxCount, m_rxBuffer); + if (m_txCount > 0) + AddNewEntry(TPDD_LOG_TX, m_txCount, m_txBuffer); + m_txCount = 0; + m_rxCount = 0; + + // Close the file + fclose(fd); + return TRUE; +} + +/* +============================================================================ +Loads the user preferences +============================================================================ +*/ +void VTTpddServerLog::LoadPreferences(void) +{ + Fl_Preferences g(virtualt_prefs, "TpddServerLog_Group"); + + // Load window location + g.get("x", m_x, -1); + g.get("y", m_y, -1); + g.get("w", m_w, -1); + g.get("h", m_h, -1); + + // Load selected font size + g.get("FontSize", m_fontSize, 14); +} + +/* +============================================================================ +Saves the user preferences +============================================================================ +*/ +void VTTpddServerLog::SavePreferences(void) +{ + Fl_Preferences g(virtualt_prefs, "TpddServerLog_Group"); + + // Save window location + g.set("x", x()); + g.set("y", y()); + g.set("w", w()); + g.set("h", h()); + + // Save selected font size + g.set("FontSize", m_fontSize); + +} + diff --git a/src/tpddserverlog.h b/src/tpddserverlog.h new file mode 100644 index 0000000..9f93368 --- /dev/null +++ b/src/tpddserverlog.h @@ -0,0 +1,150 @@ +/* tpddserverlog.h */ + +/* $Id$ */ + +/* +* Copyright 2013 Ken Pettit +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +*/ + +#ifndef TPDDSERVERLOG_H +#define TPDDSERVERLOG_H + +/* +============================================================================ +Define call routines to hook to serial port functionality. +============================================================================ +*/ +// If compiled in cpp file, make declarations extern "C" +#ifdef __cplusplus + +#include +#include +#include +#include +#include +#include "MString.h" +#include "MStringArray.h" +#include "tpddserver.h" +#include "vtobj.h" + +/* +===================================================================== +Define the class for a single log entry +===================================================================== +*/ +class VTTpddLogEntry : public VTObject +{ +public: + VTTpddLogEntry() { m_count = 0; m_pData = NULL; } + + int m_ref; // Reference number + int m_rxTx; // Indicates if this is an RX or TX entry + int m_count; // Number of bytes + char* m_pData; // Pointer to the data +}; + +/* +===================================================================== +Define the TPDD Server Log class. +===================================================================== +*/ +class VTTpddServerLog : public Fl_Double_Window +{ +public: + VTTpddServerLog(int w, int h, const char* pTitle); + ~VTTpddServerLog(); + + // Methods + void draw(void); + int handle(int event); + void resize(int x, int y, int w, int h); + + void Server(VTTpddServer* pServer) { m_pServer = pServer; } + void LogData(char data, int rxTx); + void ResetContent(void); + void CheckboxCallback(void); + + void LoadPreferences(void); + void SavePreferences(void); + void ResizeToPref(void); + + void SaveFile(MString filename); + int LoadFile(MString filename); + + int m_callbackActive; // Indicates if redraw timeout call back active + +private: + // Methods + void AddNewEntry(int rxTx, int count, char* buffer); + void SetScrollSizes(void); + + // TPDD Server interface + VTTpddServer* m_pServer; // Pointer to the TpddServer we are logging + int m_enabled; // Indicates if the log is enabled + + // RX and TX buffer control + int m_lastWasRx; // Indicates if last logged data was RX + int m_rxCount; // Count of data in rx buffer + int m_txCount; // Count of data in tx buffer + char m_rxBuffer[256]; // RX accumulation buffer + char m_txBuffer[256]; // TX accumulation buffer + + // The actual log + VTObArray m_log; // Array of log entries + int m_maxLogEntries; // Maximum number of log entries we keep + int m_nextRef; // Reference entry count + + // Drawing parameters + int m_height; // Height of each character + int m_width; // Width of each character + int m_fontSize; // Font size selection + int m_bytesPerLine; // Number of bytes drawn per line + + // Define a structure for our colors + typedef struct log_colors + { + Fl_Color background; // Window background color + Fl_Color ref; // Color for reference number + Fl_Color rxLabel; // Color of RX: label + Fl_Color txLabel; // Color of TX: label + Fl_Color rxHex; // Color of RX HEX values + Fl_Color txHex; // Color of TX HEX values + Fl_Color rxAscii; // Color of RX ASCII data + Fl_Color txAscii; // Color of TX ASCII data + } log_colors_t; + + log_colors_t m_colors; // Color coding for the window + int m_x, m_y, m_w, m_h; // User preference window location + + // FLTK widget stuff + Fl_Menu_Bar* m_pMenu; // Menu bar + Fl_Scrollbar* m_pScroll; // Pointer to our scrollbar + Fl_Check_Button* m_pDisable; // Pointer to disable checkbox + Fl_Double_Window* m_pLog; // Window for the log items +}; + +#endif /* __cplusplus */ + +#endif /* TPDDSERVERLOG_H */ + From 2ec148d956fb5af7c9afae91ec704ac31aa5d71f Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Mon, 25 Feb 2013 00:52:28 +0000 Subject: [PATCH 238/327] Updated sound emulation in Windows to reduce "ticking" and other noises, and added enable checkbox to setup dialog. --- VirtualT.vcproj | 8 + src/setup.cpp | 43 ++++- src/setup.h | 1 + src/sound.c | 359 +++++++++++++++++++++++++----------------- src/sound.h | 2 + src/tpddserver.cpp | 4 +- src/tpddserverlog.cpp | 76 +++++++-- src/tpddserverlog.h | 5 +- 8 files changed, 334 insertions(+), 164 deletions(-) diff --git a/VirtualT.vcproj b/VirtualT.vcproj index 2035acd..8b54798 100644 --- a/VirtualT.vcproj +++ b/VirtualT.vcproj @@ -689,6 +689,10 @@ RelativePath=".\src\tpddserver.cpp" > + + @@ -1228,6 +1232,10 @@ RelativePath=".\src\tpddserver.h" > + + diff --git a/src/setup.cpp b/src/setup.cpp index 6c85882..2cdaaa5 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -58,6 +58,8 @@ void init_menus(void); extern "C" { void enable_tpdd_log_menu(int bEnabled); +void sound_set_tone_control(double tone); +double sound_get_tone_control(void); } typedef struct setup_ctrl_struct @@ -101,6 +103,8 @@ typedef struct setup_ctrl_struct { Fl_Group* g; Fl_Box* pText; + Fl_Check_Button* pEnable; + Fl_Slider* pTone; } sound; struct { @@ -177,7 +181,9 @@ void save_setup_preferences(void) // Save BCR emulation settings // Save Sound emulation settings - virtualt_prefs.set("SoundEnable", setup.sound_enable); + Fl_Preferences g(virtualt_prefs, "SoundGroup"); + g.set("SoundEnable", setup.sound_enable); + g.set("ToneControl", setup.sound_tone); // Save Clock preference settings save_clock_preferences(&virtualt_prefs); @@ -209,7 +215,13 @@ void load_setup_preferences(void) // Load BCR emulation settings // Load Sound emulation settings - virtualt_prefs.get("SoundEnable", setup.sound_enable, 0); + Fl_Preferences g(virtualt_prefs, "SoundGroup"); + g.get("SoundEnable", setup.sound_enable, 0); + g.get("ToneControl", setup.sound_tone, 1.0); + + // Now configure the sound system with the values + sound_enable = setup.sound_enable; + sound_set_tone_control(setup.sound_tone); // Load Clock emulation settings load_clock_preferences(&virtualt_prefs); @@ -390,7 +402,10 @@ void cb_setup_OK(Fl_Widget* w, void*) // =========================== // Get Sound options // =========================== -// get_sound_options(); + setup.sound_enable = setup_ctrl.sound.pEnable->value(); + setup.sound_tone = setup_ctrl.sound.pTone->value(); + sound_set_tone_control(setup.sound_tone); + sound_enable = setup.sound_enable; // =========================== // Get Clock options @@ -615,13 +630,31 @@ void cb_PeripheralSetup (Fl_Widget* w, void*) // setup_ctrl.bcr.g->end(); } - // Speaker Port Tab + // Sound Port Tab { // Create the Group item (the "Tab") setup_ctrl.sound.g = new Fl_Group(10, 30, 300, 260, " Sound "); // Create controls - setup_ctrl.sound.pText = new Fl_Box(120, 60, 60, 80, "Sound not supported yet"); + setup_ctrl.sound.pEnable = new Fl_Check_Button(20, 40, 180, 20, "Enable Sound"); + setup_ctrl.sound.pEnable->value(setup.sound_enable); + + // Create a tone control slider + //Fl_Box* b = new Fl_Box(20, 80, 100, 20, "Tone Control"); + setup_ctrl.sound.pTone = new Fl_Slider(140, 80, 180, 20, ""); + setup_ctrl.sound.pTone->type(FL_HOR_NICE_SLIDER); + setup_ctrl.sound.pTone->slider(FL_NO_BOX); + setup_ctrl.sound.pTone->align(FL_ALIGN_LEFT); + setup_ctrl.sound.pTone->minimum(1); + setup_ctrl.sound.pTone->maximum(5); + double tone = sound_get_tone_control(); + setup_ctrl.sound.pTone->value(tone); + setup_ctrl.sound.pTone->hide(); +// setup_ctrl.sound.pTone->step(1); + + // Create text to describe tone control + //b = new Fl_Box(130, 100, 50, 20, "Agressive"); + //b = new Fl_Box(280, 100, 50, 20, "Soft"); // End of control for this tab setup_ctrl.sound.g->end(); diff --git a/src/setup.h b/src/setup.h index 585a5fd..fa7b1de 100644 --- a/src/setup.h +++ b/src/setup.h @@ -62,6 +62,7 @@ typedef struct peripheral_setup // Sound emulation settings int sound_enable; // Set TRUE when sound is enabled + double sound_tone; // Set the tone control for sound } peripheral_setup_t; diff --git a/src/sound.c b/src/sound.c index f03e23f..8a0962a 100644 --- a/src/sound.c +++ b/src/sound.c @@ -53,48 +53,50 @@ #pragma comment(lib, "winmm.lib") -//#define BLOCK_SIZE 2048 -//#define BLOCK_COUNT 4 -#define BLOCK_SIZE 1024 -#define BLOCK_COUNT 8 -#define SAMPLING_RATE 22050 -#define NUM_CHANNELS 2 -#define BITS_PER_SAMPLE 16 +#define BLOCK_SIZE 1024 +#define BLOCK_COUNT 10 +#define SAMPLING_RATE 22050 +#define NUM_CHANNELS 2 +#define BITS_PER_SAMPLE 16 +#define MAX_TONE_CYCLES 5000000 +#define TONE_TRANSITION_SAMPLES 16 +#define DECAY_MAX_LEVEL 4.5 #define TONE_STOPPED 0 #define TONE_START 1 #define TONE_PLAYING 2 #define TONE_STOP 3 +/* Extern data */ +extern UINT64 cycles; +extern int cycle_delta; + /* * module static data */ -static int gReqFreq[16]; -static int gReqIn = 0; -static int gReqLastFreq = 0; +static int gReqFreq[16]; +static int gReqIn = 0; +static int gReqLastFreq = 0; #ifdef _WIN32 -static int gReqOut = 0; -static int gDecaySample = 0; +static int gReqOut = 0; #endif -unsigned short readbuf [BLOCK_SIZE >> 1] ; /* input buffer */ +unsigned short gToneBuf[BLOCK_SIZE >> 1] ; /* input buffer */ unsigned short gpOneHertz[SAMPLING_RATE]; -//unsigned short *gpOneHertz = NULL; - -int gPlayTone = TONE_STOPPED; -int gToneFreq = 0; -volatile int gNewToneFreq = 0; -int gFlushBuffers = 0; -int gExit = 0; -int gBeepOn = 0; -int gOneHzPtr = 0; -extern UINT64 cycles; -extern int cycle_delta; +static int gPlayTone = TONE_STOPPED; +static int gToneFreq = 0; +static int gExit = 0; +static int gBeepOn = 0; +static int gOneHzPtr = 0; +static double gToneDivisor = 1.0; +static double gDecayLevel = DECAY_MAX_LEVEL; +static double gDecayStep = 0.008; +static int gLastToneFreq = 0; static UINT64 spkr_cycle = 0; +static UINT64 gPlayCycle = 0; int sound_enable = 1; -FILE* gFd; #ifdef _WIN32 static HANDLE g_hEquThread; @@ -145,14 +147,9 @@ static void CALLBACK sound_waveout_proc(HWAVEOUT hWaveOut, UINT uMsg, if((uMsg != WOM_DONE) || (dwInstance == 0)) return; - /* Get pointer to the block processed */ -// current = &waveBlocks[waveLastProcBlock++]; -// if (waveLastProcBlock > BLOCK_COUNT) -// waveLastProcBlock = 0; - + /* Keep track of the last block processed by the audio system */ EnterCriticalSection(&waveCriticalSection); (*freeBlockCounter)++; -// current->dwUser = -1; LeaveCriticalSection(&waveCriticalSection); } @@ -217,16 +214,15 @@ void sound_write_audio(HWAVEOUT hWaveOut, LPSTR data, int size) /* * first make sure the header we're going to use is unprepared */ - if(current->dwFlags & WHDR_PREPARED) + if (current->dwFlags & WHDR_PREPARED) waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR)); remain = size < BLOCK_SIZE ? size : BLOCK_SIZE; - current->dwUser = size; memcpy(current->lpData, data, BLOCK_SIZE); current->dwBufferLength = BLOCK_SIZE; size -= remain; data += remain; - waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR)); + waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR)); waveOutWrite(hWaveOut, current, sizeof(WAVEHDR)); EnterCriticalSection(&waveCriticalSection); waveFreeBlockCount--; @@ -236,6 +232,9 @@ void sound_write_audio(HWAVEOUT hWaveOut, LPSTR data, int size) while(!waveFreeBlockCount) Sleep(3); + EnterCriticalSection(&waveCriticalSection); + LeaveCriticalSection(&waveCriticalSection); + /* point to the next block */ waveLastQueueBlock = waveCurrentBlock; waveCurrentBlock++; @@ -251,11 +250,11 @@ sound_open_output: Open the output sound device */ BOOL sound_open_output(void) { -// gFd = fopen("beep.txt", "w+"); /* Calculate buffer size */ waveBlocks = sound_allocate_blocks(BLOCK_SIZE, BLOCK_COUNT); waveFreeBlockCount = BLOCK_COUNT; waveCurrentBlock = 0; + waveLastProcBlock = 0; InitializeCriticalSection(&waveCriticalSection); InitializeCriticalSection(&reqCriticalSection); @@ -287,13 +286,9 @@ BOOL sound_close_output (void) if (hOutput == NULL) return FALSE ; -// fclose(gFd); /* Wait for all buffers to finish playing */ sound_flush_buffers(); - /* Pulse the sound thread thread so it will release */ -// PulseEvent(gSoundEvent); - /* Now reset and close the output device and free buffers */ waveOutReset (hOutput); sound_free_blocks(waveBlocks); @@ -312,26 +307,13 @@ void sound_reset_output(void) clicks on the output */ waveOutGetVolume(hOutput,&volume); - waveOutSetVolume(hOutput, 0); -/* newVol = ((volume >> 1) & 0xFFFF0000) | ((volume & 0xFFFF) >> 1); - while (newVol > 0) - { - waveOutSetVolume(hOutput, newVol); -// Sleep(3); - newVol = ((newVol >> 1) & 0xFFFF0000) | ((newVol & 0xFFFF) >> 1); - } -*/ if (hOutput != NULL) waveOutReset (hOutput); gOneHzPtr = 0; - /* Wait for all buffers to be complete */ -// sound_flush_buffers(); - /* Restore the original volume */ waveOutSetVolume(hOutput, volume); -// waveFreeBlockCount = BLOCK_COUNT; } /* @@ -352,76 +334,155 @@ sound_play_tome: Creates and plays a tone of the frequency specified in the global variable gToneFreq. ======================================================================== */ -void sound_play_tone() +void sound_play_tone(int tone, int toneFreq) { - int i; -// int zero_cross, zero_cross_point; - int samples = BLOCK_SIZE >> 1; - int tone = gPlayTone; - int toneFreq = gToneFreq; -// int decay_samples = samples; - int decay_time = samples; - double divisor = (double) decay_time / 7; + int i; + const int samples = BLOCK_SIZE >> 1; + const int decay_time = samples; + double divisor = (double) decay_time / (gToneDivisor); + double toneStep = (double) (gToneFreq - gLastToneFreq) / (double) TONE_TRANSITION_SAMPLES; + int stepCount = 0; - /* Create a buffer with the specified frequency */ -// zero_cross = 0; - for (i = 0; i < samples; i += 2) + /* Test for runaway tones */ + if (cycles - gPlayCycle > MAX_TONE_CYCLES) { - if (tone == TONE_START) - { - unsigned short val = (unsigned short) (((double) (signed short) gpOneHertz[gOneHzPtr]) * - exp(- (double) (decay_time*2 - gDecaySample++) / divisor)); - readbuf[i] = val; - readbuf[i + 1] = val; - } - else if (tone == TONE_PLAYING) + /* Shut it down */ + tone = TONE_STOP; + } + + /* If we are playing, then play a buffer of size 1024 (512 samples) */ + if (tone == TONE_PLAYING) + { + // Loop for all samples and create the buffer + for (i = 0; i < samples; i += 2) { - readbuf[i] = gpOneHertz[gOneHzPtr]; - readbuf[i + 1] = gpOneHertz[gOneHzPtr]; + // Create next sample in buffer + gToneBuf[i] = gpOneHertz[gOneHzPtr]; + gToneBuf[i + 1] = gpOneHertz[gOneHzPtr]; + + /* Update pointer in the 1 Hz waveform based on frequency */ + if (gToneFreq != gLastToneFreq && gLastToneFreq != 0) + { + if (++stepCount >= TONE_TRANSITION_SAMPLES) + { + // Set the last tone frequency now that transition is complete + if (gToneFreq != 0) + gLastToneFreq = gToneFreq; + gOneHzPtr += gToneFreq; + } + else + { + gOneHzPtr += gLastToneFreq + (int) (toneStep * (double) stepCount); + } + } + else + { + gOneHzPtr += gToneFreq; + gLastToneFreq = gToneFreq; + } + if (gOneHzPtr >= SAMPLING_RATE) + { + // We wrapped the end of the sample buffer + gOneHzPtr -= SAMPLING_RATE; + } } - else if (tone == TONE_STOP) + } + + /* Create a buffer with the specified frequency */ + else + { + // Loop for all entries in the buffer + for (i = 0; i < samples; i += 2) { + // Set the tone value unsigned short val = (unsigned short) (((double) (signed short) gpOneHertz[gOneHzPtr]) * - exp(- (double) i / (divisor) )); - readbuf[i] = val; - readbuf[i + 1] = val; - } + exp(-gDecayLevel)); + gToneBuf[i] = val; + gToneBuf[i + 1] = val; - /* Update pointer in the 1 Hz waveform based on frequency */ - gOneHzPtr += gToneFreq; - if (gOneHzPtr >= SAMPLING_RATE) - { - // Zero crossing occurred -// zero_cross = i + 1; - gOneHzPtr -= SAMPLING_RATE; -// zero_cross_point = gOneHzPtr; - } + // Test if we are starting a tone. We ramp-up the volume to prevent ticking + if (tone == TONE_START) + { + // Ramping up means decreasing the DecayLevel to zero + gDecayLevel -= gDecayStep; + if (gDecayLevel <= 0.0) + { + // Once we reach level zero, we are done "Decaying" and switch to playing + gDecayLevel = 0.0; + } + } + + // Test if we are stopping a tone and ramp it down in volume to prevent ticking + else if (tone == TONE_STOP) + { + // Ramp the tone down. This mean increasing the decay level until + // it reaches our defined max value + gDecayLevel += gDecayStep * 1.75; + } -// readbuf[i] = 200; -// readbuf[i + 1] = 200; -// fprintf(gFd, "%d\n", (int) (signed short) readbuf[i]); + /* Update pointer in the 1 Hz waveform based on frequency */ + if (gToneFreq != gLastToneFreq && gLastToneFreq != 0) + { + /* There was a frequency change. Filter to new frequency */ + if (++stepCount >= TONE_TRANSITION_SAMPLES) + { + // Set the last tone frequency now that transition is complete + if (gToneFreq != 0) + gLastToneFreq = gToneFreq; + gOneHzPtr += gToneFreq; + } + else + { + /* Change to new frequency in steps */ + gOneHzPtr += gLastToneFreq + (int) (toneStep * (double) stepCount); + } + } + else + { + // No frequency smoothing needed + gOneHzPtr += gToneFreq; + gLastToneFreq = gToneFreq; + } + if (gOneHzPtr >= SAMPLING_RATE) + { + // We wrapped the end of the sample buffer + gOneHzPtr -= SAMPLING_RATE; + } + } } + // If we are stopping the tone, then mark it as stopped if (tone == TONE_STOP) { - gPlayTone = TONE_STOPPED; - gOneHzPtr = 0; + // We only transition to STOPPED if we have decayed enough + if (gDecayLevel >= DECAY_MAX_LEVEL) + { + // Change to STOPPED state + gPlayTone = TONE_STOPPED; + gDecayLevel = DECAY_MAX_LEVEL; + } } - else if ((tone == TONE_START) && (gDecaySample >= BLOCK_SIZE)) + + // Else if we are starting the tone, mark it as PLAYING + else if (tone == TONE_START) { - gDecaySample = 0; - gPlayTone = TONE_PLAYING; + // We only transition to PLAYING once we have ramped up to full volume + if (gDecayLevel <= 0.0) + { + gDecayLevel = 0.0; + gPlayTone = TONE_PLAYING; + } } /* Write the buffer to the output device */ - sound_write_audio(hOutput, (LPSTR) readbuf, BLOCK_SIZE); - + sound_write_audio(hOutput, (LPSTR) gToneBuf, BLOCK_SIZE); return; } DWORD WINAPI EquProc(LPVOID lpParam) { + // Loop forever, or til time to quit. This is the audio driver thread. while (1) { // If no active tone being played, wait for event so we don't @@ -435,41 +496,42 @@ DWORD WINAPI EquProc(LPVOID lpParam) if (gExit) break; - /* Test for new tone frequency changes only if stopped or playing */ - if ((gPlayTone == TONE_STOPPED) || (gPlayTone == TONE_PLAYING)) + /* Test for new request */ + if (gReqIn != gReqOut) { - /* Test for new request */ - if (gReqIn != gReqOut) - { - int newFreq = gReqFreq[gReqOut++]; - if (gReqOut >= 16) - gReqOut = 0; + int newFreq = gReqFreq[gReqOut++]; + if (gReqOut >= 16) + gReqOut = 0; - if ((newFreq == 0) && (gPlayTone == TONE_PLAYING)) - { - /* Stop the currently playing tone */ - if (gReqIn == gReqOut) - gPlayTone = TONE_STOP; - } - else if ((newFreq > 0) && (gPlayTone == TONE_STOPPED)) + if ((newFreq == 0))// && (gPlayTone == TONE_PLAYING)) + { + /* Stop the currently playing tone */ + if (gReqIn == gReqOut) { - /* Start new tone */ - gToneFreq = newFreq; - gPlayTone = TONE_START; + gPlayTone = TONE_STOP; } - else - { - /* Change the tone frequency */ - gToneFreq = newFreq; + } + else if ((newFreq > 0) && (gPlayTone != TONE_PLAYING)) + { + /* Start new tone */ + gToneFreq = newFreq; + gPlayTone = TONE_START; - /* Probably need to change the unplayed buffers here */ - } + /* Keep track of how long a tone is playing + and shut it down if it's too long */ + gPlayCycle = cycles; + } + else + { + /* Change the tone frequency. The play_tone routine will + filter the change from the old frequency to the new. */ + gToneFreq = newFreq; } } /* Check if tone being generated */ - if (gPlayTone)// && (gToneFreq = gNewToneFreq)) - sound_play_tone(); + if (gPlayTone) + sound_play_tone(gPlayTone, gToneFreq); /* Test if the "beep" command is active */ if (gBeepOn) @@ -505,7 +567,7 @@ void init_sound(void) int x; double w; - // Create sin table + // Create sin table for 1Hz w = 2.0 * 3.1415926536 / (double) SAMPLING_RATE; for (x = 0; x < SAMPLING_RATE; x++) { @@ -594,27 +656,6 @@ void sound_stop_tone(void) /* Issue a request for a frequency of zero */ sound_start_tone(0); - - /* - WAVEHDR* current; - unsigned short *sData; - int c; - - EnterCriticalSection(&reqCriticalSection); - gReqFreq[gReqFreqIn++] = 0; - if (gReqFreqIn > 16) - gReqFreqIn = 0; - LeaveCriticalSection(&reqCriticalSection); -*/ - /* Go to the last queued block and clear the data past the zero-crossing */ -/* current = &waveBlocks[waveLastQueueBlock]; - if (current->dwUser != -1) - { - sData = (unsigned short *) current->lpData; - c = ((int) current->lpData) >> 1; - for (; c < BLOCK_SIZE >> 1; c++) - sData[c] = 0; - } */\ } /* @@ -645,3 +686,29 @@ void sound_toggle_speaker(int bitVal) sound_start_tone((int) (2400000.0 / delta / 2)); } } + +/* +================================================================== +This routine sets the tone control divisor +================================================================== +*/ +void sound_set_tone_control(double tone) +{ + // Don't allow tone divisor of zero + if (tone == 0.0) + tone = 1.0; + + // Set the tone divisor + gToneDivisor = tone; + gDecayStep = tone / (double) (BLOCK_SIZE>>3); +} + +/* +================================================================== +This routine gets the tone control divisor +================================================================== +*/ +double sound_get_tone_control(void) +{ + return gToneDivisor; +} diff --git a/src/sound.h b/src/sound.h index 385c0b6..303b322 100644 --- a/src/sound.h +++ b/src/sound.h @@ -36,5 +36,7 @@ void deinit_sound (void); void sound_start_tone (int freq); void sound_stop_tone (void); void sound_toggle_speaker (int bitVal); +void sound_set_tone_control (double tone); +double sound_get_tone_control (void); #endif diff --git a/src/tpddserver.cpp b/src/tpddserver.cpp index ecb898d..fc77ca1 100644 --- a/src/tpddserver.cpp +++ b/src/tpddserver.cpp @@ -2477,8 +2477,8 @@ void VTTpddServer::OpcodeRename(void) old_filename = m_sRootDir + m_curDir + m_dirRef; #ifdef WIN32 - ret = Rename((const char *) old_filename, (const char *) new_filename); - if (ret) + ret = rename((const char *) old_filename, (const char *) new_filename); + if (ret == 0) SendNormalReturn(TPDD_ERR_NONE); else { diff --git a/src/tpddserverlog.cpp b/src/tpddserverlog.cpp index 4cc9090..51b7700 100644 --- a/src/tpddserverlog.cpp +++ b/src/tpddserverlog.cpp @@ -123,7 +123,19 @@ static void cb_disable_log(Fl_Widget* w, void* pOpaque) { VTTpddServerLog* pLog = (VTTpddServerLog *) pOpaque; - pLog->CheckboxCallback(); + pLog->DisableCallback(); +} + +/* +============================================================================ +Callback for auto scroll checkbox +============================================================================ +*/ +static void cb_autoscroll(Fl_Widget* w, void* pOpaque) +{ + VTTpddServerLog* pLog = (VTTpddServerLog *) pOpaque; + + pLog->AutoscrollCallback(); } /* @@ -346,21 +358,22 @@ VTTpddServerLog::VTTpddServerLog(int w, int h, const char* title) : m_maxLogEntries = 8192; m_nextRef = 1; m_callbackActive = FALSE; + m_autoScroll = TRUE; // Define our default colors m_colors.background = FL_BLACK; m_colors.ref = FL_WHITE; m_colors.rxLabel = FL_YELLOW; m_colors.txLabel = (Fl_Color) 221; - m_colors.rxHex = fl_color_average(FL_DARK_GREEN, FL_WHITE, 0.8); - m_colors.txHex = fl_color_average((Fl_Color) 221, FL_WHITE, 0.5); + m_colors.rxHex = fl_color_average(FL_DARK_GREEN, FL_WHITE, (float) 0.8); + m_colors.txHex = fl_color_average((Fl_Color) 221, FL_WHITE, (float) 0.5); m_colors.rxAscii = FL_GREEN; m_colors.txAscii = (Fl_Color) 221; m_fontSize = 14; fl_font(FL_COURIER, m_fontSize); m_height = fl_height(); - m_width = fl_width("W"); + m_width = (int) fl_width("W"); // =============================== // Now create the controls we need @@ -383,8 +396,12 @@ VTTpddServerLog::VTTpddServerLog(int w, int h, const char* title) : // Create a resizing group g = new Fl_Group(0, h-35, w, 35, ""); + // Create an auto scroll checkbox + m_pAutoScroll = new Fl_Check_Button(20, h-37, 110, 20, "Auto scroll"); + m_pAutoScroll->callback(cb_autoscroll, this); + // Create a disable log checkbox - m_pDisable = new Fl_Check_Button(20, h-30, 110, 20, "Disable log"); + m_pDisable = new Fl_Check_Button(20, h-21, 110, 20, "Disable log"); m_pDisable->callback(cb_disable_log, this); // Create a Save button @@ -739,7 +756,8 @@ Sets the scrollbar settings based on current geometry and item count. void VTTpddServerLog::SetScrollSizes(void) { int size, height, count, max; - int lines, c; + int lines, c, curVal, linesPastCur; + int linesThisEntry; VTTpddLogEntry* pEntry; // Select 12 point Courier font @@ -749,33 +767,40 @@ void VTTpddServerLog::SetScrollSizes(void) height = m_pLog->h(); size = (int) (height / m_height); count = m_log.GetSize(); + curVal = m_pScroll->value(); // Count the number of lines that will be disiplayed if (m_bytesPerLine == 0) m_bytesPerLine = 1; lines = 0; + linesPastCur = 0; for (c = 0; c < count; c++) { // Get next entry pEntry = (VTTpddLogEntry *) m_log[c]; - lines += (pEntry->m_count+m_bytesPerLine-1) / m_bytesPerLine; + linesThisEntry = (pEntry->m_count+m_bytesPerLine-1) / m_bytesPerLine; + lines += linesThisEntry; + if (c >= curVal) + linesPastCur += linesThisEntry; } lines += (m_rxCount+m_bytesPerLine-1) / m_bytesPerLine; lines += (m_txCount+m_bytesPerLine-1) / m_bytesPerLine; // Set maximum value of scroll - if (m_pScroll->value()+size-1 > count ) + if (curVal+size-1 > lines ) { - int newValue = count-size+1; + int newValue = count-3; if (newValue < 0) newValue = 0; m_pScroll->value(newValue, 0, 0, count-2); + curVal = newValue; } max = count + 1 - size; if (max < 1) max = 1; m_pScroll->maximum(count-2); m_pScroll->minimum(0); + if (lines > 1) { m_pScroll->step((double) size/(double)(lines-1)); @@ -783,6 +808,23 @@ void VTTpddServerLog::SetScrollSizes(void) } m_pScroll->linesize(1); + // Set the value + if (m_autoScroll) + { + // Test if last entry is on the screen. If not, then put it there + if (linesPastCur >= size) + { + int newValue = count - 3; + if (newValue < 0) + newValue = 0; + + // Set the value + m_pScroll->value(newValue, 0, 0, count-2); + } + } + else + m_pScroll->value(curVal, 0, 0, count-2); + redraw(); } @@ -820,11 +862,21 @@ void VTTpddServerLog::ResetContent(void) Called when the disable log checkbox is modified ============================================================================ */ -void VTTpddServerLog::CheckboxCallback(void) +void VTTpddServerLog::DisableCallback(void) { m_enabled = !m_pDisable->value(); } +/* +============================================================================ +Called when the disable log checkbox is modified +============================================================================ +*/ +void VTTpddServerLog::AutoscrollCallback(void) +{ + m_autoScroll = m_pAutoScroll->value(); +} + /* ============================================================================ Called to resize the window and position to user preference settings @@ -1108,6 +1160,9 @@ void VTTpddServerLog::LoadPreferences(void) // Load selected font size g.get("FontSize", m_fontSize, 14); + g.get("AutoScroll", m_autoScroll, TRUE); + + m_pAutoScroll->value(m_autoScroll); } /* @@ -1127,6 +1182,7 @@ void VTTpddServerLog::SavePreferences(void) // Save selected font size g.set("FontSize", m_fontSize); + g.set("AutoScroll", m_autoScroll); } diff --git a/src/tpddserverlog.h b/src/tpddserverlog.h index 9f93368..85dd1b6 100644 --- a/src/tpddserverlog.h +++ b/src/tpddserverlog.h @@ -83,7 +83,8 @@ class VTTpddServerLog : public Fl_Double_Window void Server(VTTpddServer* pServer) { m_pServer = pServer; } void LogData(char data, int rxTx); void ResetContent(void); - void CheckboxCallback(void); + void DisableCallback(void); + void AutoscrollCallback(void); void LoadPreferences(void); void SavePreferences(void); @@ -120,6 +121,7 @@ class VTTpddServerLog : public Fl_Double_Window int m_width; // Width of each character int m_fontSize; // Font size selection int m_bytesPerLine; // Number of bytes drawn per line + int m_autoScroll; // Indicates if auto-scroll is on // Define a structure for our colors typedef struct log_colors @@ -141,6 +143,7 @@ class VTTpddServerLog : public Fl_Double_Window Fl_Menu_Bar* m_pMenu; // Menu bar Fl_Scrollbar* m_pScroll; // Pointer to our scrollbar Fl_Check_Button* m_pDisable; // Pointer to disable checkbox + Fl_Check_Button* m_pAutoScroll; // Pointer to autoscroll box Fl_Double_Window* m_pLog; // Window for the log items }; From 2dd2eec3f313734c536ffd2a25de275634ba600d Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 5 Mar 2013 20:43:46 +0000 Subject: [PATCH 239/327] Added support for NEC-8300, added color syntax hilighting, find, load, save to Disassembler and started adding support to disassemble things other than the main SysROM. --- VirtualT.vcproj | 4 + release.txt | 7 + src/My_Text_Display.cpp | 2 +- src/My_Text_Display.h | 2 +- src/cpuregs.cpp | 29 +- src/cpuregs.h | 6 +- src/disassemble.cpp | 2479 ++++++++++++++++++++++++++++++++------- src/disassemble.h | 115 +- src/display.cpp | 77 +- src/display.h | 4 + src/file.cpp | 22 +- src/file.h | 7 + src/highlight.cpp | 5 +- src/ide.cpp | 56 +- src/io.c | 13 +- src/linker.cpp | 70 +- src/linker.h | 2 + src/m100emu.c | 4 +- src/m100rom.c | 13 +- src/memedit.cpp | 48 +- src/memory.c | 71 +- src/memory.h | 7 +- src/multieditwin.cpp | 17 + src/multieditwin.h | 6 + src/n8300rom.c | 941 +++++++++++++++ src/remote.cpp | 2 +- src/roms.h | 3 + src/romstrings.c | 1714 +++++++++++++-------------- src/romstrings.h | 16 +- src/sound.c | 5 +- src/tpddserverlog.cpp | 9 +- 31 files changed, 4350 insertions(+), 1406 deletions(-) create mode 100644 src/n8300rom.c diff --git a/VirtualT.vcproj b/VirtualT.vcproj index 8b54798..aadaf8f 100644 --- a/VirtualT.vcproj +++ b/VirtualT.vcproj @@ -547,6 +547,10 @@ /> + + diff --git a/release.txt b/release.txt index 1d5679a..fc6d5ff 100644 --- a/release.txt +++ b/release.txt @@ -59,6 +59,13 @@ v1.6 17. Added TPDD Server (NADSBox) packet log viewer window to Tools menu. +18. Added support for NEC PC-8300 emulation. + +19. Started adding support to Disassembler window to disassemble things other than the + main ROM. + +20. Added color syntax hilighting, Load and Save, and Find operations to Disassembler window. + ==================== v1.5 July 9th, 2011 ==================== diff --git a/src/My_Text_Display.cpp b/src/My_Text_Display.cpp index db19a68..8829382 100644 --- a/src/My_Text_Display.cpp +++ b/src/My_Text_Display.cpp @@ -1820,7 +1820,7 @@ int My_Text_Display::position_style( int lineStartPos, style = ( unsigned char ) styleBuf->character( pos ); if (style == mUnfinishedStyle) { /* encountered "unfinished" style, trigger parsing */ - (mUnfinishedHighlightCB)( pos, mHighlightCBArg); + if (mUnfinishedHighlightCB) (mUnfinishedHighlightCB)( pos, mHighlightCBArg); style = (unsigned char) styleBuf->character( pos); } } diff --git a/src/My_Text_Display.h b/src/My_Text_Display.h index 6d5a9ba..c8e502a 100644 --- a/src/My_Text_Display.h +++ b/src/My_Text_Display.h @@ -77,7 +77,7 @@ class FL_EXPORT My_Text_Display: public Fl_Double_Window { ~My_Text_Display(); virtual int handle(int e); - void buffer(Fl_Text_Buffer* buf); + virtual void buffer(Fl_Text_Buffer* buf); void buffer(Fl_Text_Buffer& buf) { buffer(&buf); } Fl_Text_Buffer* buffer() { return mBuffer; } void redisplay_range(int start, int end); diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index 1b66f05..5fd3467 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -68,6 +68,7 @@ VTDis cpu_dis; extern Fl_Preferences virtualt_prefs; extern Fl_Window* gmew; // Global Memory Edit Window +extern Fl_Window *MainWin; extern "C" { @@ -119,6 +120,12 @@ Callback routine for the CPU Regs window */ void cb_cpuregswin (Fl_Widget* w, void* pOpaque) { + // Save the user preferences + gcpuw->SavePrefs(); + + // Collapse the window + collapse_window(gcpuw); + // Hide the window gcpuw->hide(); @@ -134,9 +141,6 @@ void cb_cpuregswin (Fl_Widget* w, void* pOpaque) // Remove ourselves as a debug monitor debug_clear_monitor_callback(debug_cpuregs_cb); - // Save the user preferences - gcpuw->SavePrefs(); - // Delete the window and set to NULL delete gcpuw; gcpuw = NULL; @@ -2446,9 +2450,10 @@ void cb_CpuRegs (Fl_Widget* w, void*) if (gcpuw != NULL) return; - // Create Peripheral Setup window + // Create a CPU Registers window gcpuw = new VTCpuRegs(640, 480, "CPU Registers"); gcpuw->callback(cb_cpuregswin, gcpuw); + gcpuw->end(); // Show the new window gcpuw->show(); @@ -2456,14 +2461,8 @@ void cb_CpuRegs (Fl_Widget* w, void*) // Resize if user preferences have been set if (gcpuw->m_x != -1 && gcpuw->m_y != -1 && gcpuw->m_w != -1 && gcpuw->m_h != -1) { - int newx, newy, neww, newh; - - newx = gcpuw->m_x; - newy = gcpuw->m_y; - neww = gcpuw->m_w; - newh = gcpuw->m_h; - - gcpuw->resize(newx, newy, neww, newh); + // Expand the window + expand_window(gcpuw, gcpuw->m_x, gcpuw->m_y, gcpuw->m_w, gcpuw->m_h); } // Check if VirtualT has had time to initialize yet. If not, we set a @@ -2523,6 +2522,8 @@ VTCpuRegs::VTCpuRegs(int x, int y, const char *title) : /* Load the user preferences for window size, etc. */ LoadPrefs(); SetTraceColors(); + for (c = 0; c < sizeof(m_pad); c++) + m_pad[c] = '1'; // Allocate the trace buffer m_pTraceData = new cpu_trace_data_t[m_traceCount]; @@ -3114,7 +3115,7 @@ VTCpuRegs::~VTCpuRegs() // Delete the trace data buffer if (m_pTraceData != NULL) { - delete m_pTraceData; + delete[] m_pTraceData; m_pTraceData = NULL; } } @@ -3124,7 +3125,7 @@ void VTCpuRegs::draw(void) make_current(); #ifdef WIN32 - Fl_Double_Window::draw(); + Fl_Window::draw(); #else Fl_Window::draw(); #endif diff --git a/src/cpuregs.h b/src/cpuregs.h index 63508dc..fb76e5d 100644 --- a/src/cpuregs.h +++ b/src/cpuregs.h @@ -109,10 +109,8 @@ class VTCpuRegs : public Fl_Window virtual int handle(int event); Fl_Menu_Bar* m_pMenu; - Fl_Check_Button* m_pEnable; Fl_Input* m_pRegA; - Fl_Input* m_pRegF; Fl_Input* m_pRegB; Fl_Input* m_pRegC; Fl_Input* m_pRegD; @@ -175,8 +173,6 @@ class VTCpuRegs : public Fl_Window Fl_Round_Button* m_pHLDec; Fl_Round_Button* m_pMHex; Fl_Round_Button* m_pMDec; - Fl_Round_Button* m_pBreakHex; - Fl_Round_Button* m_pBreakDec; Fl_Box* m_pTraceBox; Fl_Box* m_pStackBox; @@ -241,6 +237,8 @@ class VTCpuRegs : public Fl_Window int m_selStart; int m_selEnd; int m_haveMouse; + + char m_pad[4096]; }; #endif diff --git a/src/disassemble.cpp b/src/disassemble.cpp index b39fe02..caf5594 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -33,15 +33,21 @@ #include #include #include -#include #include +#include +#include +#include "My_Text_Editor.h" +#include "multieditwin.h" #include #include #include +#include "FLU/Flu_File_Chooser.h" + #include "VirtualT.h" #include "m100emu.h" #include "disassemble.h" +#include "file.h" #include "io.h" #include "cpu.h" #include "periph.h" @@ -51,21 +57,35 @@ #include "memory.h" #include "fileview.h" -void cb_Ide(Fl_Widget* w, void*) ; - -Fl_Window *gpDis; +// Define extern variables +extern Fl_Preferences virtualt_prefs; -// Callback routine for the close box of the Disassembler window -static void close_cb(Fl_Widget* w, void*) +extern "C" { - if (gpDis != NULL) - { - gpDis->hide(); - delete gpDis; - gpDis = 0; - } +extern uchar gMsplanROM[32768]; /* MSPLAN ROM T200 Only */ } +// Declare extern functions +void cb_Ide(Fl_Widget* w, void*) ; +void set_text_size(int t); +void get_hilight_color_prefs(void); + +// Our globalton object +VTDis *gpDis; + +// List of opcodes that dictate a label is needed for a given address +const unsigned char gLabelOpcodes[] = { + 0xC3, 0xCD, 0xC2, 0xC4, 0xCA, 0xCC, 0xD2, 0xD4, 0xDA, 0xDC, + 0xE2, 0xE4, 0xEA, 0xEC, 0xF2, 0xF4, 0xFA, 0xFC +}; + +#define INST_LXI_B 0x01 +#define INST_LXI_D 0x11 +#define INST_LXI_H 0x21 +#define INST_RET 0xC9 +#define INST_JMP 0xC3 +#define INST_PCHL 0xE9 + // Table of OPCODE const char * gStrTable[256] = { "NOP", "LXI B,", "STAX B", "INX B", "INR B", "DCR B", "MVI B,", "RLC", @@ -153,20 +173,91 @@ unsigned char gLenTable[256] = { 0,0,2,0,2,2,1,0 }; +static Std_ROM_Table_t gEmpty_Tables[] = { + { 0x0003, 5, TABLE_TYPE_STRING }, + { 0x0004, 4, TABLE_TYPE_STRING }, + { -1, 0, 0} +}; +static Std_ROM_Addresses_t gEmpty_Vars[] = { + { -1, -1 } +}; +static Std_ROM_Addresses_t gEmpty_Funs[] = { + { 0x0000, R_RESET_VECTOR }, + { 0x0008, R_RST_1 }, + { 0x0010, R_RST_2 }, + { 0x0018, R_RST_3 }, + { 0x0020, R_RST_4 }, + { 0x0028, R_RST_5 }, + { 0x002C, R_RST_5_5 }, + { 0x0030, R_RST_6 }, + { 0x0034, R_RST_6_5 }, + { 0x0038, R_RST_7 }, + { 0x003C, R_RST_7_5 }, + { -1, -1 } +}; + +static RomDescription_t gEmpty_Desc = { + 0, /* Signature */ + 0, /* Signature address */ + 0, /* StdRom */ + + gEmpty_Tables, /* Known tables */ + gEmpty_Vars, /* Known variables */ + gEmpty_Funs, /* Known functions */ + + 0, /* Address of unsaved BASIC prgm */ + 0, /* Address of next DO file */ + 0, /* Start of DO file area */ + 0, /* Start of CO file area */ + 0, /* Start of Variable space */ + 0, /* Start of Array data */ + 0, /* Pointer to unused memory */ + 0, /* Address where HIMEM is stored */ + 0, /* End of RAM for file storage */ + 0, /* Lowest RAM used by system */ + 0, /* Start of RAM directory */ + 0, /* BASIC string buffer pointer */ + 0, /* BASIC Size */ + 0, /* Keyscan array */ + 0, /* Character generator array */ + 0, /* Location of Year storage */ + 0, /* LCD Buffer storage area */ + 0, /* Label line enable flag (not defined) */ + + 0, /* Number of directory entries */ + 0, /* Index of first Dir entry */ + 0 /* Address of MS Copyright string */ +}; + +// Callback routine the disassembler +static void close_cb(Fl_Widget* w, void*); +static void cb_dis_what(Fl_Widget* w, void*); +static void cb_setup(Fl_Widget* w, void*); +static void cb_dis_find(Fl_Widget* w, void*); +static void cb_find_next(Fl_Widget* w, void* pOpaque); +static void cb_open_file(Fl_Widget* w, void* pOpaque); +static void cb_save_file(Fl_Widget* w, void* pOpaque); + // Menu items for the disassembler Fl_Menu_Item gDis_menuitems[] = { { "&File", 0, 0, 0, FL_SUBMENU }, - { "Open...", 0, 0, 0 }, - { "Save...", 0, 0, 0, FL_MENU_DIVIDER }, + { "Open...", FL_CTRL + 'o', cb_open_file, 0 }, + { "Save...", FL_CTRL + 's', cb_save_file, 0 }, + { "Disassemble...", FL_CTRL + 'd', cb_dis_what, 0, FL_MENU_DIVIDER }, + { "Setup...", 0, cb_setup, 0, FL_MENU_DIVIDER }, { "Close", FL_CTRL + 'q', close_cb, 0 }, { 0 }, - { "&Tools", 0, 0, 0, FL_SUBMENU }, + { "&Edit", 0, 0, 0, FL_SUBMENU }, + { "Find...", FL_CTRL + 'f', cb_dis_find, 0 }, + { "Find Next", FL_F + 3, cb_find_next, 0, 0 }, + { 0 }, + + { "&Tools", 0, 0, 0, FL_SUBMENU }, { "CPU Registers", 0, cb_CpuRegs }, { "Assembler / IDE", 0, cb_Ide }, { "Memory Editor", 0, cb_MemoryEditor }, { "Peripheral Devices", 0, cb_PeripheralDevices }, -// { "Simulation Log Viewer", 0, 0 }, { "Model T File Viewer", 0, cb_FileView }, { 0 }, @@ -174,25 +265,461 @@ Fl_Menu_Item gDis_menuitems[] = { }; /* -======================================================= +============================================================================ +Closes the disassembler +============================================================================ +*/ +static void close_cb(Fl_Widget* w, void*) +{ + if (gpDis != NULL) + { + // Save the window preferences + gpDis->SavePrefs(); + + // Collapse the window + collapse_window(gpDis); + + // Now delete the window + delete gpDis; + gpDis = 0; + } +} + +/* +============================================================================ +Class to manage Disassemble What dialog +============================================================================ +*/ +class VTDisWhat : public Fl_Window +{ +public: + VTDisWhat(int x, int y, const char *title); + + static void CbRadioROM(Fl_Widget *w, void *pOpaque); + static void CbRadioTargetCO(Fl_Widget *w, void *pOpaque); + static void CbRadioHostFile(Fl_Widget *w, void *pOpaque); + static void CbHostFileBrowse(Fl_Widget *w, void *pOpaque); + static void CbCancel(Fl_Widget *w, void *pOpaque); + static void CbOkay(Fl_Widget *w, void *pOpaque); + void CbOkay(void); + void PopulateTargetFiles(void); + + Fl_Round_Button* m_pDisRom; + Fl_Round_Button* m_pDisTargetCo; + Fl_Round_Button* m_pDisHostFile; + Fl_Choice* m_whichRom; + Fl_Choice* m_whichCO; + Fl_Input* m_pHostFilename; + Fl_Button* m_pHostFileBrowse; + model_t_files_t m_tFiles[100]; + int m_tCount; + char m_sHostFile[512]; +}; + +/* +============================================================================ +Class constructor for VTDisWhat +============================================================================ +*/ +VTDisWhat::VTDisWhat(int x, int y, const char *title) : + Fl_Window(x, y, title) +{ + // Create items on the dialog + m_pDisRom = new Fl_Round_Button(20, 20, 60, 20, "ROM"); + m_pDisRom->type(FL_RADIO_BUTTON); + m_pDisRom->callback(CbRadioROM, this); + m_pDisRom->value(1); + + // Create a selection box for the ROM to disassemble + m_whichRom = new Fl_Choice(140, 20, 130, 20, ""); + m_whichRom->add("Main ROM"); + + // Add other ROMs based on the current model + if (gModel == MODEL_T200) + m_whichRom->add("MS Plan"); + else if (gModel == MODEL_PC8300) + { + m_whichRom->add("ROM B"); + m_whichRom->add("ROM C"); + } + + m_whichRom->add("OptROM"); + m_whichRom->value(0); + + // Create a radio button to select in-memory Model T files + m_pDisTargetCo = new Fl_Round_Button(20, 50, 100, 20, "Target .CO"); + m_pDisTargetCo->type(FL_RADIO_BUTTON); + m_pDisTargetCo->callback(CbRadioTargetCO, this); + + // Create a selection box for target .CO files + m_whichCO = new Fl_Choice(140, 50, 130, 20, ""); + m_whichCO->deactivate(); + PopulateTargetFiles(); + + // Create a radio button to select external host file + m_pDisHostFile = new Fl_Round_Button(20, 80, 100, 20, "Host file"); + m_pDisHostFile->type(FL_RADIO_BUTTON); + m_pDisHostFile->callback(CbRadioHostFile, this); + + // Create an edit field and browse button for the host filename + m_sHostFile[0] = '\0'; + m_pHostFilename = new Fl_Input(140, 80, 220, 20, ""); + m_pHostFilename->deactivate(); + m_pHostFileBrowse = new Fl_Button(160, 105, 80, 20, "Browse"); + m_pHostFileBrowse->callback(CbHostFileBrowse, this); + m_pHostFileBrowse->deactivate(); + + // Create a Cancel button + Fl_Button* o = new Fl_Button(100, 160, 60, 30, "Cancel"); + o->callback(CbCancel, this); + + // OK button + Fl_Return_Button* ro = new Fl_Return_Button(200, 160, 60, 30, "OK"); + ro->callback(CbOkay, this); +} + +/* +============================================================================ +Populates m_whichCO with target .CO files from the emulation +============================================================================ +*/ +/* +============================================================================ +Populates m_whichCO with target .CO files from the emulation +============================================================================ +*/ +void VTDisWhat::PopulateTargetFiles(void) +{ + unsigned short addr1; + int dir_index; + unsigned char file_type; + int c, x; + char mt_file[10]; + + // Add Model T files to the browser + addr1 = gStdRomDesc->sDirectory; + dir_index = 0; + m_tCount = 0; + while (dir_index < gStdRomDesc->sDirCount) + { + // Get the filetype of this file + file_type = get_memory8(addr1); + if (file_type != TYPE_CO) + { + // Skip files that aren't .CO + dir_index++; + addr1 += 11; + continue; + } + + c = 0; + for (x = 0; x < 6; x++) + { + if (get_memory8(addr1+3+x) != ' ') + mt_file[c++] = get_memory8(addr1+3+x); + } + + mt_file[c++] = '.'; + mt_file[c++] = get_memory8(addr1+3+x++); + mt_file[c++] = get_memory8(addr1+3+x); + mt_file[c] = '\0'; + + // Add filename to tFiles structure + strcpy(m_tFiles[m_tCount].name, mt_file); + + // Get address of file + m_tFiles[m_tCount].address = get_memory16(addr1+1); + m_tFiles[m_tCount].dir_address = addr1; + + m_whichCO->add(m_tFiles[m_tCount++].name); + + dir_index++; + addr1 += 11; + } +} + +/* +============================================================================ +Callback for the ROM radio button +============================================================================ +*/ +void VTDisWhat::CbRadioROM(Fl_Widget* w, void* pOpaque) +{ + VTDisWhat* pWin = (VTDisWhat *) pOpaque; + + // Enable the ROM selection + pWin->m_whichRom->activate(); + + // Disable other controls + pWin->m_whichCO->deactivate(); + pWin->m_pHostFilename->deactivate(); + pWin->m_pHostFileBrowse->deactivate(); +} + +/* +============================================================================ +Callback for the Target CO radio button +============================================================================ +*/ +void VTDisWhat::CbRadioTargetCO(Fl_Widget* w, void* pOpaque) +{ + VTDisWhat* pWin = (VTDisWhat *) pOpaque; + + // Enable the ROM selection + pWin->m_whichCO->activate(); + + // Disable other controls + pWin->m_whichRom->deactivate(); + pWin->m_pHostFilename->deactivate(); + pWin->m_pHostFileBrowse->deactivate(); +} + +/* +============================================================================ +Callback for the host File radio button +============================================================================ +*/ +void VTDisWhat::CbRadioHostFile(Fl_Widget* w, void* pOpaque) +{ + VTDisWhat* pWin = (VTDisWhat *) pOpaque; + + // Enable the ROM selection + pWin->m_pHostFilename->activate(); + pWin->m_pHostFileBrowse->activate(); + + // Disable other controls + pWin->m_whichCO->deactivate(); + pWin->m_whichRom->deactivate(); +} + +/* +============================================================================ +Callback for the Host file browse button +============================================================================ +*/ +void VTDisWhat::CbHostFileBrowse(Fl_Widget* w, void* pOpaque) +{ + VTDisWhat* pWin = (VTDisWhat *) pOpaque; + Flu_File_Chooser * fc; + FILE* fd; + + // Create a file browser + fl_cursor(FL_CURSOR_WAIT); +#ifdef __APPLE__ + fc = new Flu_File_Chooser(pWin->m_sHostFile,"*.*",Fl_File_Chooser::CREATE,"File to disassemble"); +#else + fc = new Flu_File_Chooser(pWin->m_sHostFile,"*.*",Fl_File_Chooser::CREATE,"File to disassemble"); +#endif + fl_cursor(FL_CURSOR_DEFAULT); + fc->preview(0); + fc->show(); + + // Show the file browser and wait for it to go away + while (fc->visible()) + Fl::wait(); + + // Check if a file was selected + if (fc->value() == 0) + { + delete fc; + return; + } + if (strlen(fc->value()) == 0) + { + delete fc; + return; + } + + // Try to open the input file + fd = fopen(fc->value(), "rb"); + if (fd == NULL) + { + // Error! File must exist + fl_alert("Error opening file %s", fl_filename_name(fc->value())); + delete fc; + return; + } + + // Save the filename + strcpy(pWin->m_sHostFile, fc->value()); + pWin->m_pHostFilename->value(fl_filename_name(pWin->m_sHostFile)); +} + +/* +============================================================================ +Callback for the DisWhat Cancel button +============================================================================ +*/ +void VTDisWhat::CbCancel(Fl_Widget* w, void* pOpaque) +{ + VTDisWhat* pWin = (VTDisWhat *) pOpaque; + + // Just hide the window. + pWin->hide(); +} + +/* +============================================================================ +Callback for the DisWhat Okay button +============================================================================ +*/ +void VTDisWhat::CbOkay(Fl_Widget* w, void* pOpaque) +{ + VTDisWhat* pWin = (VTDisWhat *) pOpaque; + + // Call the Okay handler for this window + pWin->CbOkay(); + + // Now hide the window + pWin->hide(); + + // Change the text in the disasembler to show we are disassembling + gpDis->ShowDisassemblyMessage(); + + Fl::wait(0.5); + + gpDis->Disassemble(); +} + +/* +============================================================================ +Callback for the DisWhat Okay button +============================================================================ +*/ +void VTDisWhat::CbOkay(void) +{ + // Determine what should be disassembled + if (m_pDisRom->value()) + { + // Now set the disassembly range + gpDis->m_StartAddress = 0; + gpDis->m_EndAddress = ROMSIZE-1; + + // Disassembling a ROM + if (strcmp(m_whichRom->text(), "Main ROM") == 0) + { + // Copy the standard ROM into memory + gpDis->CopyIntoMem(gSysROM, ROMSIZE); + } + else if (strcmp(m_whichRom->text(), "MS Plan") == 0) + { + // Copy ROM bank B into memory + gpDis->CopyIntoMem(gMsplanROM, ROMSIZE); + gpDis->m_EndAddress = 32767; + } + else if (strcmp(m_whichRom->text(), "ROM B") == 0) + { + // Copy ROM bank B into memory + gpDis->CopyIntoMem(&gSysROM[32768], ROMSIZE); + } + else if (strcmp(m_whichRom->text(), "ROM C") == 0) + { + // Copy ROM bank C into memory + gpDis->CopyIntoMem(&gSysROM[2*32768], ROMSIZE); + } + else if (strcmp(m_whichRom->text(), "OptROM") == 0) + { + gpDis->CopyIntoMem(gOptROM, 32768); + gpDis->m_EndAddress = 32767; + } + } + + else if (m_pDisTargetCo->value()) + { + // Disassembling a target CO file + unsigned char* pBuf = new unsigned char[32768]; + int x, idx, addr, size; + + // Get index of file to disassemble + idx = m_whichCO->value(); + addr = get_memory16(m_tFiles[idx].address); + size = get_memory16(m_tFiles[idx].address+2); + for (x = 0; x < size; x++) + pBuf[x] = get_memory8(m_tFiles[idx].address + 6 + x); + gpDis->CopyIntoMem(pBuf, size, addr); + gpDis->m_StartAddress = addr; + gpDis->m_EndAddress = addr+size-1; + delete pBuf; + + // Now copy the standard ROM into the lower memory space + gpDis->CopyIntoMem(gSysROM, ROMSIZE); + } + + else if (m_pDisHostFile->value()) + { + // Copy the standard ROM into the lower memory space + + // Disassembling a host file. Load the host file into memory + } +} + +/* +============================================================================ +Chooses what to actually disassemble +============================================================================ +*/ +static void cb_dis_what(Fl_Widget* w, void*) +{ + VTDisWhat* pWin; + + /* Create a new window for the trace configuration */ + pWin = new VTDisWhat(400, 200, "Disassemble What"); + + // Show the window + pWin->show(); + pWin->set_modal(); + + // Now wait until OK or Cancel pressed + while (pWin->visible()) + Fl::wait(); + + // Delete the window + delete pWin; +} + +/* +============================================================================ Menu Item Callbacks -======================================================= +============================================================================ */ -void disassembler_cb(Fl_Widget* w, void*) { +void disassembler_cb(Fl_Widget* w, void*) +{ + const int wx = 50; + const int wy = 50; if (gpDis == NULL) { - // Create a new window for the disassembler - gpDis = new Fl_Window(600, 400 , "Disassembler"); + // Create a Disassembler + gpDis = new VTDis(wx, wy , "Disassembler"); gpDis->callback(close_cb); + // Load user preferences + gpDis->LoadPrefs(); + + // Get the hilight color preferences + get_hilight_color_prefs(); + // Create a menu for the new window. - Fl_Menu_Bar *m = new Fl_Menu_Bar(0, 0, 600, MENU_HEIGHT-2); -// gpDisp = new T100_Disp(0, MENU_HEIGHT, 240*MultFact + 90*DisplayMode, 64*MultFact + 50*DisplayMode); + Fl_Menu_Bar *m = new Fl_Menu_Bar(0, 0, wx, MENU_HEIGHT-2); m->menu(gDis_menuitems); // Create a Text Editor to show/edit the disassembled text - Fl_Text_Editor* td = new Fl_Text_Editor(0, MENU_HEIGHT, 600, 400-MENU_HEIGHT); + My_Text_Editor* td = new Fl_Multi_Edit_Window(0, MENU_HEIGHT, wx, wy-MENU_HEIGHT); + gpDis->SetTextEditor(td); + + // Set the background if black background enabled + if (gpDis->m_blackBackground) + { + td->textcolor(FL_WHITE); + td->color(FL_BLACK); + td->selection_color(FL_DARK_BLUE); + td->textfont(FL_COURIER); + } + else + td->textfont(FL_COURIER_BOLD); + + // Set the font size preference + set_text_size(gpDis->m_fontSize); // Create a Text Buffer for the Text Editor to work with Fl_Text_Buffer* tb = new Fl_Text_Buffer(); @@ -200,63 +727,119 @@ void disassembler_cb(Fl_Widget* w, void*) { // Show the Disassembling text to indicate activity tb->append("\n\n\n Disassembling..."); - td->textfont(FL_COURIER); - - // Create a Disassembler - VTDis *pDisassembler = new VTDis(); - - // Assign the RomDescription table for the model being emulated - pDisassembler->m_pRom = gStdRomDesc; // Give the disassembler the text editor to dump it's data into - pDisassembler->SetTextViewer(td); + gpDis->SetTextViewer(td); // Give the disassembler something to disassemble - pDisassembler->CopyIntoMem(gSysROM, ROMSIZE); -// pDisassembler->CopyIntoMem((unsigned char*) gBaseMemory, 65536); + gpDis->CopyIntoMem(gSysROM, ROMSIZE); gpDis->resizable(m); gpDis->resizable(td); + // End and show the window gpDis->end(); gpDis->show(); + gpDis->CreateFindDlg(); + + // Now expand the window to the user prefrence size + expand_window(gpDis, gpDis->m_x, gpDis->m_y, + gpDis->m_w, gpDis->m_h); // Show the new window - Fl::wait(); + Fl::check(); // Disassemble the code (this should be moved later when dissasembly // of .CO programs is supported) - pDisassembler->Disassemble(); + gpDis->Disassemble(); } else { + // Show the window so it appears on top + gpDis->show(); } } /* -======================================================= +============================================================================ Disassembler Class Definition -======================================================= +============================================================================ +*/ +VTDis::VTDis(int x, int y, const char *title) : + Fl_Double_Window(x, y, title) +{ + m_StartAddress = 0; + m_EndAddress = ROMSIZE-1; + m_BaseAddress = 0; + m_WantComments = 0; + m_pFindDlg = NULL; +} + +/* +============================================================================ +Disassembler Class Definition - empty constructor +============================================================================ */ -VTDis::VTDis() +VTDis::VTDis() : + Fl_Double_Window(0, 0, "") { m_StartAddress = 0; m_EndAddress = ROMSIZE-1; m_BaseAddress = 0; m_WantComments = 0; + m_pFindDlg = NULL; +} + +/* +============================================================================ +Creates a find dialog for the disassembler window +============================================================================ +*/ +void VTDis::CreateFindDlg(void) +{ + m_pFindDlg = new VTDisFindDlg(this); +} + +/* +============================================================================ +Disassembler Class Definition - empty constructor +============================================================================ +*/ +VTDis::~VTDis() +{ + // Delete the find dialog + if (m_pFindDlg != NULL) + delete m_pFindDlg; } -void VTDis::SetTextViewer(Fl_Text_Editor *pTextViewer) +/* +============================================================================ +Sets the text viewer object for the disassembler +============================================================================ +*/ +void VTDis::SetTextViewer(My_Text_Editor *pTextViewer) { m_pTextViewer = pTextViewer; } -void VTDis::AppendComments(char* line, int opcode, int address) +/* +============================================================================ +Appends comments from the current StdRom description +to the given line. +============================================================================ +*/ +void VTDis::AppendComments(char* line, int opcode, int address, int oldSchool) { int i, x, len, op_len; + int margin; + + if (oldSchool) + margin = 28; + else + margin = 39; // Calculate # spaces to add for fixed line len (make comments line up) - len = 28 - strlen(line); + len = margin - strlen(line); // Determine length of this opcode op_len = gLenTable[opcode] & 0x03; @@ -351,157 +934,204 @@ void VTDis::AppendComments(char* line, int opcode, int address) } } +/* +============================================================================ +This is the actual disassembler code. It disassembles whatever has been +copied into m_memory +============================================================================ +*/ void VTDis::Disassemble() { - int c; - int x; - int table; + int c, x, table; char line[200]; char arg[60]; - int addr; + int addr, generate; int rst7 = 0; int rst1 = 0; + int oldSchool = m_oldSchool; // Indicates Old school style disassembly + int tricked_out; + int sig_addr; + unsigned long sig; unsigned char opcode; unsigned char op_len; Fl_Text_Buffer* tb; + // Assign the RomDescription table for the model being emulated + gpDis->m_pRom = gStdRomDesc; - tb = new Fl_Text_Buffer; - for (c = m_StartAddress; c <= m_EndAddress; c++) + // Allocate a disassembly type array + m_pDisType = new DisType_t[65536]; + + // Validate we are disassembling a std ROM. If not, the point to an empty ROM description + sig_addr = gpDis->m_pRom->sSignatureAddr; + sig = (unsigned char) m_memory[sig_addr] + + ((unsigned char) m_memory[sig_addr+1] << 8) + + ((unsigned char) m_memory[sig_addr+2] << 16) + + ((unsigned char) m_memory[sig_addr+3] << 24); + if (sig != gpDis->m_pRom->dwSignature) + gpDis->m_pRom = &gEmpty_Desc; + + // Mark all lines as needing no label + for (x = 0; x < 65536; x++) { - // Search for C in the function table - x = 0; - while (m_pRom->pFuns[x].addr != -1) - { - if (m_pRom->pFuns[x].addr == c) - { - strcpy(line, "\n; ======================================================\n; "); - strcat(line, gDisStrings[m_pRom->pFuns[x].strnum].desc); - strcat(line, "\n; ======================================================\n"); - // Add line to Edit Buffer - tb->append(line); - break; - } + m_pDisType[x].dis_type = DIS_TYPE_UNKNOWN; + m_pDisType[x].pLabel = NULL; + } - x++; - } + // Assign labels we know we need + x = 0; + while (m_pRom->pFuns[x].addr != -1) + { + m_pDisType[m_pRom->pFuns[x].addr].dis_type |= DIS_TYPE_LABEL | DIS_TYPE_TABLE | DIS_TYPE_CODE; + m_pDisType[m_pRom->pFuns[x].addr].pLabel = + gDisStrings[m_pRom->pFuns[x].strnum].desc; + m_pDisType[m_pRom->pFuns[x].addr].idx = m_pRom->pFuns[x].strnum; - // Check if address is a table instead of code - x = 0; - table = 0; + // Increment to next function + x++; + } - // Check if last instruction was RST7 (that means this byte is a DB) - if (rst7 == 1) - { - sprintf(line, "%04XH DB %02XH\n", c, m_memory[c]); - tb->append(line); - rst7 = 0; - continue; - } + // We make two passes. The 1st pass we throw away as we are just + // identifying the addresses that need labels + for (generate = 0; generate < 2; generate++) + { + // Create a new text buffer + tb = new Fl_Text_Buffer; - // Check if last instruction was RST1 (that means this byte is a DB) - if (rst1 == 1) + for (c = m_StartAddress; c <= m_EndAddress; c++) { - sprintf(line, "%04XH DB %02XH\n", c, m_memory[c]); + // Test if we need to print a label for this line + if (m_pDisType[c].dis_type & DIS_TYPE_LABEL) + { + // Add a label to the disassembly + DisassembleAddLabel(tb, c); + } + +#if 0 + if (m_pDisType[c].dis_type & DIS_TYPE_CODE) + strcpy(line, "C "); + else if (m_pDisType[c].dis_type & DIS_TYPE_STRING) + strcpy(line, "S "); + else strcpy(line, " "); tb->append(line); - rst1 = 0; - continue; - } +#endif - // Loop though the array of table definitions for the current address - while (m_pRom->pTables[x].addr != -1) - { - // Current address found? - if (m_pRom->pTables[x].addr == c) + // Check if address is a table instead of code + x = 0; + table = 0; + + // Check if last instruction was RST7 (that means this byte is a DB) + if (rst7 == 1) { - table = 1 ; - // Modified strings are those that start with a 0x80 and ends - // when the next string is found (the next 0x80). All the - // BASIC keywords are stored this way - if (m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING) - { - int next; - int last = c + m_pRom->pTables[x].size; - int str_active = 0; - for (next = c; next < last; next++) - { - if ((m_memory[next] & 0x80) && (str_active)) - { - if ((m_memory[next-1] & 0x80) == 0) - strcat(line, "\""); - strcat(line, "\n"); - tb->append(line); - line[0]=0; - str_active = 0; - } - if (!str_active) - { - sprintf(line, "%04XH DB 80H or '%c'", next, m_memory[next] & 0x7F); - str_active = 1; - if ((m_memory[next+1] & 0x80) == 0) - strcat(line, ",\""); - } - else - { - sprintf(arg, "%c", m_memory[next]); - strcat(line, arg); - } + if (oldSchool) + sprintf(line, "%04XH DB %02XH\n", c, m_memory[c]); + else + sprintf(line, " DB %02XH\n", m_memory[c]); + tb->append(line); + rst7 = 0; + continue; + } - if (next + 1 == last) - { - if ((m_memory[next-1] & 0x80) == 0) - strcat(line, "\""); - strcat(line, "\n\n"); - tb->append(line); - line[0] = 0; - } - } - } - // Modified strings are those that start with a 0x80 and ends - // when the next string is found (the next 0x80). All the - // BASIC keywords are stored this way - else if ((m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING2) - || (m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING3)) + // Check if last instruction was RST1 (that means this byte is a DB) + if (rst1 == 1) + { + if (oldSchool) + sprintf(line, "%04XH DB %02XH\n", c, m_memory[c]); + else + sprintf(line, " DB %02XH\n", m_memory[c]); + tb->append(line); + rst1 = 0; + continue; + } + + // Loop though the array of table definitions for the current address + while (m_pRom->pTables[x].addr != -1) + { + // Current address found? + if (m_pRom->pTables[x].addr == c) { - int next; - int last = c + m_pRom->pTables[x].size; - int str_active = 0; - for (next = c; next < last; next++) + // Mark this address as a table address + table = 1; + + // Mark all address covered by the table entry as covered + int j, k; + k = m_pRom->pTables[x].addr + m_pRom->pTables[x].size; + for (j = m_pRom->pTables[x].addr; j < k; j++) + m_pDisType[j].dis_type |= DIS_TYPE_TABLE; + m_pDisType[m_pRom->pTables[x].addr].dis_type |= DIS_TYPE_LABEL; + + // Modified strings are those that start with a 0x80 and ends + // when the next string is found (the next 0x80). All the + // BASIC keywords are stored this way + if (m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING) { - if (m_memory[next] == 0) + int next; + int last = c + m_pRom->pTables[x].size; + int str_active = 0; + for (next = c; next < last; next++) { - sprintf(line, "%04XH DB 00H\n", next); - tb->append(line); - line[0] = 0; - continue; - } - if ((m_memory[next] & 0x80) && (str_active)) - { - sprintf(arg, "\",'%c' or 80H", m_memory[next] & 0x7F); - strcat(line, arg); - if (m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING2) - { - sprintf(arg, ", %02XH\n", m_memory[next+1]); - next++; + if ((m_memory[next] & 0x80) && (str_active)) + { + if ((m_memory[next-1] & 0x80) == 0) + strcat(line, "\""); + strcat(line, "\n"); + tb->append(line); + line[0]=0; + str_active = 0; + } + if (!str_active) + { + if (oldSchool) + sprintf(line, "%04XH DB 80H or '%c'", next, m_memory[next] & 0x7F); + else + sprintf(line, " DB 80H or '%c'", m_memory[next] & 0x7F); + str_active = 1; + if ((m_memory[next+1] & 0x80) == 0) + strcat(line, ",\""); } else - strcpy(arg, "\n"); - strcat(line, arg); -// if ((m_memory[next-1] & 0x80) == 0) -// strcat(line, "\""); -// strcat(line, "\n"); - tb->append(line); - line[0]=0; - str_active = 0; - continue; + { + sprintf(arg, "%c", m_memory[next]); + strcat(line, arg); + } + + if (next + 1 == last) + { + if ((m_memory[next-1] & 0x80) == 0) + strcat(line, "\""); + strcat(line, "\n\n"); + tb->append(line); + line[0] = 0; + } } - if (!str_active) + } + // Modified strings are those that start with a 0x80 and ends + // when the next string is found (the next 0x80). All the + // BASIC keywords are stored this way + else if ((m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING2) + || (m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING3)) + { + int next; + int last = c + m_pRom->pTables[x].size; + int str_active = 0; + for (next = c; next < last; next++) { - if (m_memory[next] & 0x80) + if (m_memory[next] == 0) + { + if (oldSchool) + sprintf(line, "%04XH DB 00H\n", next); + else + sprintf(line, " DB 00H\n"); + tb->append(line); + line[0] = 0; + continue; + } + if ((m_memory[next] & 0x80) && (str_active)) { - sprintf(line, "%04XH DB '%c' OR 80H", next, m_memory[next] & 0x7F); + sprintf(arg, "\",'%c' or 80H", m_memory[next] & 0x7F); + strcat(line, arg); if (m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING2) - { + { sprintf(arg, ", %02XH\n", m_memory[next+1]); next++; } @@ -513,376 +1143,865 @@ void VTDis::Disassemble() str_active = 0; continue; } + if (!str_active) + { + if (m_memory[next] & 0x80) + { + if (oldSchool) + sprintf(line, "%04XH DB '%c' OR 80H", next, m_memory[next] & 0x7F); + else + sprintf(line, " DB '%c' OR 80H", m_memory[next] & 0x7F); + if (m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING2) + { + sprintf(arg, ", %02XH\n", m_memory[next+1]); + next++; + } + else + strcpy(arg, "\n"); + strcat(line, arg); + tb->append(line); + line[0]=0; + str_active = 0; + continue; + } + else + { + if (oldSchool) + sprintf(line, "%04XH DB \"%c", next, m_memory[next]); + else + sprintf(line, " DB \"%c", m_memory[next]); + str_active = 1; + } + } else { - sprintf(line, "%04XH DB \"%c", next, m_memory[next]); - str_active = 1; + sprintf(arg, "%c", m_memory[next]); + strcat(line, arg); } - } - else - { - sprintf(arg, "%c", m_memory[next]); - strcat(line, arg); - } - if (next + 1 == last) - { - if ((m_memory[next-1] & 0x80) == 0) - strcat(line, "\""); - strcat(line, "\n\n"); - tb->append(line); - line[0] = 0; + if (next + 1 == last) + { + if ((m_memory[next-1] & 0x80) == 0) + strcat(line, "\""); + strcat(line, "\n\n"); + tb->append(line); + line[0] = 0; + } } } - } - // A string is one that ends with NULL (0x00) - else if (m_pRom->pTables[x].type == TABLE_TYPE_STRING) - { - int next; - int last = c + m_pRom->pTables[x].size; - int str_active = 0; - int quote_active = 0; - for (next = c; next < last; next++) + // A string is one that ends with NULL (0x00) + else if (m_pRom->pTables[x].type == TABLE_TYPE_STRING) { - if ((m_memory[next] == 0) && (str_active)) - { - if (quote_active) - strcat(line, "\""); - strcat(line, ",00H\n"); - tb->append(line); - line[0]=0; - str_active = 0; - quote_active = 0; - } - else if (!str_active) + // Disassemble this block of code as a string + DisassembleAsString(tb, c, m_pRom->pTables[x].size); + } + + // CTRL_DELIM tables are string that have a non-ASCII byte + // between them + else if (m_pRom->pTables[x].type == TABLE_TYPE_CTRL_DELIM) + { + int next; + int last = c + m_pRom->pTables[x].size; + int str_active = 0; + for (next = c; next < last; next++) { - if (m_memory[next] == 0) + if ((m_memory[next] > 0x7E) && (str_active)) { - sprintf(line, "%04XH DB 00H\n", next); + sprintf(arg, "\",%02XH\n", m_memory[next]); + strcat(line, arg); tb->append(line); line[0]=0; + str_active = 0; + continue; + } + if (!str_active) + { + if (m_memory[next] > 0x7E) + { + if (oldSchool) + sprintf(line, "%04XH DB %02XH\n", next, m_memory[next]); + else + sprintf(line, " DB %02XH\n", m_memory[next]); + tb->append(line); + } + else + { + if (oldSchool) + sprintf(line, "%04XH DB \"%c", next, m_memory[next]); + else + sprintf(line, " DB \"%c", m_memory[next]); + str_active = 1; + } } else { - sprintf(line, "%04XH DB \"%c", next, m_memory[next]); - quote_active = 1; - str_active = 1; + sprintf(arg, "%c", m_memory[next]); + strcat(line, arg); } } - else + } + // A JUMP table is one that contains 16 bit address in a table + else if (m_pRom->pTables[x].type == TABLE_TYPE_JUMP) + { + int next; + int last = c + m_pRom->pTables[x].size; + int count = 0, itemsPerLine; + + // Determine number of items per line + itemsPerLine = 3; + if (!oldSchool) + itemsPerLine = 2; + + for (next = c; next < last; next += 2) { - if (iscntrl(m_memory[next])) + if (count == 0) { - if (quote_active) - { - strcat(line, "\""); - quote_active = 0; - } - sprintf(arg, ",%02XH", m_memory[next]); + if (oldSchool) + sprintf(line, "%04XH DW ", next); + else + sprintf(line, " DW "); } + + addr = m_memory[next] | (m_memory[next+1] << 8); + if (oldSchool) + sprintf(arg, "%04XH", addr); else { - if (!quote_active) - sprintf(arg, ",\"%c", m_memory[next]); - else if (m_memory[next] == '"') - sprintf(arg, "\\%c", m_memory[next]); + // Display the label + if (m_pDisType[addr].pLabel) + { + // Append the defined label + strcpy(arg, gDisStrings[m_pDisType[addr].idx].pLabel); + if (arg[strlen(arg)-1] == ':') + arg[strlen(arg)-1] = '\0'; + } else - sprintf(arg, "%c", m_memory[next]); - quote_active = 1; + { + // Append the generated label + sprintf(arg, "L_%04XH", addr); + m_pDisType[addr].dis_type |= DIS_TYPE_LABEL; + } } + + // Append the argument to the line strcat(line, arg); + + // Append a comma if more items on this line + if ((next+2 != last) && (count != itemsPerLine)) + strcat(line, ", "); + else + { + strcat(line, "\n"); + if (next+2 == last) + strcat(line, "\n"); + } + + // Test if we need to start a new line + if ((count == itemsPerLine) || (next+2 == last)) + { + tb->append(line); + count = 0; + } + else + count++; } - if ((next+1 == last) && (m_memory[next] != 0)) + } + // A 2BYTE table is one with entries that are exactly 2 bytes + // This is used for the BASIC error message text + else if (m_pRom->pTables[x].type == TABLE_TYPE_2BYTE) + { + int next; + int last = c + m_pRom->pTables[x].size; + for (next = c; next < last; next += 2) { - if (quote_active) - strcat(line, "\""); - strcat(line, "\n"); + if (oldSchool) + sprintf(line, "%04XH DB \"%c%c\"\n", next, m_memory[next], m_memory[next+1]); + else + sprintf(line, " DB \"%c%c\"\n", m_memory[next], m_memory[next+1]); tb->append(line); - line[0]=0; - str_active = 0; - quote_active = 0; } } - } - // CTRL_DELIM tables are string that have a non-ASCII byte - // between them - else if (m_pRom->pTables[x].type == TABLE_TYPE_CTRL_DELIM) - { - int next; - int last = c + m_pRom->pTables[x].size; - int str_active = 0; - for (next = c; next < last; next++) + // A 3BYTE table is one with entries that are exactly 3 bytes + // This is used for the Day of week and Month text (Mon, Tue, Jan, Feb) + else if (m_pRom->pTables[x].type == TABLE_TYPE_3BYTE) { - if ((m_memory[next] > 0x7E) && (str_active)) + int next; + int last = c + m_pRom->pTables[x].size; + for (next = c; next < last; next += 3) { - sprintf(arg, "\",%02XH\n", m_memory[next]); - strcat(line, arg); + if (oldSchool) + sprintf(line, "%04XH DB \"%c%c%c\"\n", next, m_memory[next], m_memory[next+1], + m_memory[next+2]); + else + sprintf(line, " DB \"%c%c%c\"\n", m_memory[next], m_memory[next+1], + m_memory[next+2]); tb->append(line); - line[0]=0; - str_active = 0; - continue; } - if (!str_active) + } + // A BYTE_LOOKUP is a table that has a single "search" byte with a + // 2 byte address following it + else if (m_pRom->pTables[x].type == TABLE_TYPE_BYTE_LOOKUP) + { + int next; + int last = c + m_pRom->pTables[x].size; + for (next = c; next < last; next += 3) { - if (m_memory[next] > 0x7E) + if (iscntrl(m_memory[next])) { - sprintf(line, "%04XH DB %02XH\n", next, m_memory[next]); - tb->append(line); + if (oldSchool) + sprintf(line, "%04XH DB %02XH\n%04XH DW %04XH\n", next, m_memory[next], + next+1, m_memory[next+1] | (m_memory[next+2] << 8)); + else + sprintf(line, " DB %02XH\n%04XH DW %04XH\n", m_memory[next], + next+1, m_memory[next+1] | (m_memory[next+2] << 8)); } - else + else { - sprintf(line, "%04XH DB \"%c", next, m_memory[next]); - str_active = 1; + if (oldSchool) + sprintf(line, "%04XH DB '%c'\n%04XH DW %04XH\n", next, m_memory[next], + next+1, m_memory[next+1] | (m_memory[next+2] << 8)); + else + sprintf(line, " DB '%c'\n%04XH DW %04XH\n", m_memory[next], + next+1, m_memory[next+1] | (m_memory[next+2] << 8)); } + tb->append(line); } - else + } + // A 4BYTE_CMD table has 4 ASCII bytes (the command) followed by a + // 2 byte address + else if (m_pRom->pTables[x].type == TABLE_TYPE_4BYTE_CMD) + { + int next; + int last = c + m_pRom->pTables[x].size; + for (next = c; next < last; next += 6) { - sprintf(arg, "%c", m_memory[next]); - strcat(line, arg); + if (oldSchool) + sprintf(line, "%04XH DB \"%c%c%c%c\"\n", next, m_memory[next], + m_memory[next+1], m_memory[next+2], m_memory[next+3]); + else + sprintf(line, " DB \"%c%c%c%c\"\n", m_memory[next], + m_memory[next+1], m_memory[next+2], m_memory[next+3]); + tb->append(line); + if (oldSchool) + sprintf(line, "%04XH DW %04XH\n", next+4, m_memory[next+4] | + (m_memory[next+5] << 8)); + else + sprintf(line, " DW %04XH\n", m_memory[next+4] | + (m_memory[next+5] << 8)); + tb->append(line); } } - } - // A JUMP table is one that contains 16 bit address in a table - else if (m_pRom->pTables[x].type == TABLE_TYPE_JUMP) - { - int next; - int last = c + m_pRom->pTables[x].size; - int count = 0; - for (next = c; next < last; next += 2) + // A catalog table is just that. One that contains ROM catalog entries + else if (m_pRom->pTables[x].type == TABLE_TYPE_CATALOG) { - if (count == 0) - sprintf(line, "%04XH DW ", next); - - sprintf(arg, "%04XH", m_memory[next] | (m_memory[next+1] << 8)); - strcat(line, arg); - if ((next+2 != last) && (count != 3)) - strcat(line, ","); - else + int next; + int last = c + m_pRom->pTables[x].size; + for (next = c; next < last; next += 11) { - strcat(line, "\n"); - if (next+2 == last) - strcat(line, "\n"); - } + if (oldSchool) + sprintf(line, "%04XH DB %02XH\n", next, m_memory[next]); + else + sprintf(line, " DB %02XH\n", m_memory[next]); + tb->append(line); + if (oldSchool) + sprintf(line, "%04XH DW %04XH\n", next+1, m_memory[next+1] | + (m_memory[next+2] << 8)); + else + sprintf(line, " DW %04XH\n", m_memory[next+1] | + (m_memory[next+2] << 8)); + tb->append(line); - if ((count == 3) || (next+2 == last)) - { + if (m_memory[next+3] == 0) + { + if (oldSchool) + sprintf(line, "%04XH DB %02XH,\"%c%c%c%c%c%c\",%02XH\n", next+3, m_memory[next+3], + m_memory[next+4], m_memory[next+5], m_memory[next+6], m_memory[next+7], + m_memory[next+8], m_memory[next+9], m_memory[next+10]); + else + sprintf(line, " DB %02XH,\"%c%c%c%c%c%c\",%02XH\n", m_memory[next+3], + m_memory[next+4], m_memory[next+5], m_memory[next+6], m_memory[next+7], + m_memory[next+8], m_memory[next+9], m_memory[next+10]); + } + else + { + if (oldSchool) + sprintf(line, "%04XH DB \"%c%c%c%c%c%c%c\",%02XH\n", next+3, m_memory[next+3], + m_memory[next+4], m_memory[next+5], m_memory[next+6], m_memory[next+7], + m_memory[next+8], m_memory[next+9], m_memory[next+10]); + else + sprintf(line, " DB \"%c%c%c%c%c%c%c\",%02XH\n", m_memory[next+3], + m_memory[next+4], m_memory[next+5], m_memory[next+6], m_memory[next+7], + m_memory[next+8], m_memory[next+9], m_memory[next+10]); + } tb->append(line); - count = 0; } - else - count++; } - } - // A 2BYTE table is one with entries that are exactly 2 bytes - // This is used for the BASIC error message text - else if (m_pRom->pTables[x].type == TABLE_TYPE_2BYTE) - { - int next; - int last = c + m_pRom->pTables[x].size; - for (next = c; next < last; next += 2) + // A CODE table is one where bytes are simply represented with + // a DB directive. Bytes are split into lines with 8 bytes per line + else if (m_pRom->pTables[x].type == TABLE_TYPE_CODE) { - sprintf(line, "%04XH DB \"%c%c\"\n", next, m_memory[next], m_memory[next+1]); - tb->append(line); + int next; + int last = c + m_pRom->pTables[x].size; + int count = 0; + for (next = c; next < last; next++) + { + if (count == 0) + { + if (oldSchool) + sprintf(line, "%04XH DB ", next); + else + sprintf(line, " DB "); + } + + sprintf(arg, "%02XH", m_memory[next]); + strcat(line, arg); + if ((next+1 != last) && (count != 7)) + strcat(line, ","); + else + { + strcat(line, "\n"); + if (next+1 == last) + { + strcat(line, "\n"); + tb->append(line); + line[0] = 0; + } + } + + if (count == 7) + { + tb->append(line); + line[0] = 0; + count = 0; + } + else + count++; + } } + // Add line to Edit Buffer + c += m_pRom->pTables[x].size-1; + break; } - // A 3BYTE table is one with entries that are exactly 3 bytes - // This is used for the Day of week and Month text (Mon, Tue, Jan, Feb) - else if (m_pRom->pTables[x].type == TABLE_TYPE_3BYTE) + + x++; + } + + // Was this address identified as a table? If so, don't disassemble it! + if (table) + continue; + + // Test if the disassembly type for this address has been calculated by inference + if (m_pDisType[c].dis_type & DIS_TYPE_STRING) + { + DisassembleAsString(tb, c, m_pDisType[c].idx); + c += m_pDisType[c].idx - 1; + continue; + } + + // Get opcode from memory + opcode = m_memory[c]; + + // Test if this opcode refers to an address which will need a label + int j; + for (j = 0; j < sizeof(gLabelOpcodes); j++) + { + // Test for label reference + if (opcode == gLabelOpcodes[j]) { - int next; - int last = c + m_pRom->pTables[x].size; - for (next = c; next < last; next += 3) - { - sprintf(line, "%04XH DB \"%c%c%c\"\n", next, m_memory[next], m_memory[next+1], - m_memory[next+2]); - tb->append(line); - } + int addr = m_memory[c+1] | (m_memory[c+2] << 8); + + if (opcode < 0x80 && addr < 0x200) + break; + + // This address will need a label + m_pDisType[addr].dis_type |= DIS_TYPE_LABEL | DIS_TYPE_CODE; + break; } - // A BYTE_LOOKUP is a table that has a single "search" byte with a - // 2 byte address following it - else if (m_pRom->pTables[x].type == TABLE_TYPE_BYTE_LOOKUP) + } + + // Determine length of this opcode + op_len = gLenTable[opcode] & 0x03; + tricked_out = FALSE; + + // Print the address and opcode value to the temporary line buffer + if (oldSchool) + { + sprintf(line, "%04XH (%02XH) ", c, opcode); + strcat(line, gStrTable[opcode]); + } + else + { + strcpy(line, " "); + + // Print the opcode text to the temp line buffer + const char* ptr = gStrTable[opcode]; + + // Test if this opcode has been tricked out with the next + // opcode to produce a mutli-entry routine (ORI AFH / XRA A) + if (op_len > 0) { - int next; - int last = c + m_pRom->pTables[x].size; - for (next = c; next < last; next += 3) + // Opcode len is not zero. Test if next address needs a label too + if (m_pDisType[c+1].dis_type & DIS_TYPE_LABEL) { - if (iscntrl(m_memory[next])) - sprintf(line, "%04XH DB %02XH\n%04XH DW %04XH\n", next, m_memory[next], - next+1, m_memory[next+1] | (m_memory[next+2] << 8)); - else - sprintf(line, "%04XH DB '%c'\n%04XH DW %04XH\n", next, m_memory[next], - next+1, m_memory[next+1] | (m_memory[next+2] << 8)); - tb->append(line); + // This opcode is tricked out. + tricked_out = TRUE; + + // Disassemble it as a DB instead + sprintf(line, " DB %02XH", opcode); + strcat(line, " ; Tricked out "); } } - // A 4BYTE_CMD table has 4 ASCII bytes (the command) followed by a - // 2 byte address - else if (m_pRom->pTables[x].type == TABLE_TYPE_4BYTE_CMD) + + // Copy opcode to line + int y = strlen(line); + while (*ptr != ' ' && *ptr != '\0') { - int next; - int last = c + m_pRom->pTables[x].size; - for (next = c; next < last; next += 6) - { - sprintf(line, "%04XH DB \"%c%c%c%c\"\n", next, m_memory[next], - m_memory[next+1], m_memory[next+2], m_memory[next+3]); - tb->append(line); - sprintf(line, "%04XH DW %04XH\n", next+4, m_memory[next+4] | - (m_memory[next+5] << 8)); - tb->append(line); - } + if (m_opcodesLowercase) + line[y++] = tolower(*ptr++); + else + line[y++] = *ptr++; } - // A catalog table is just that. One that contains ROM catalog entries - else if (m_pRom->pTables[x].type == TABLE_TYPE_CATALOG) + while (y < 11) + line[y++] = ' '; + while (*ptr != '\0') + line[y++] = *ptr++; + line[y] = '\0'; + } + + // Check if this opcode has a single byte argument + if (op_len == 1) + { + // Single byte argument + sprintf(arg, "%02XH", m_memory[c+1]); + strcat(line, arg); + } + + // Check if this opcode as a 2 byte argument + else if (op_len == 2) + { + // Double byte argument + addr = m_memory[c+1] | (m_memory[c+2] << 8); + if ((m_pDisType[addr].dis_type & DIS_TYPE_LABEL) && !oldSchool && !tricked_out) { - int next; - int last = c + m_pRom->pTables[x].size; - for (next = c; next < last; next += 11) - { - sprintf(line, "%04XH DB %02XH\n", next, m_memory[next]); - tb->append(line); - sprintf(line, "%04XH DW %04XH\n", next+1, m_memory[next+1] | - (m_memory[next+2] << 8)); - tb->append(line); - - if (m_memory[next+3] == 0) - sprintf(line, "%04XH DB %02XH,\"%c%c%c%c%c%c\",%02XH\n", next+3, m_memory[next+3], - m_memory[next+4], m_memory[next+5], m_memory[next+6], m_memory[next+7], - m_memory[next+8], m_memory[next+9], m_memory[next+10]); - else - sprintf(line, "%04XH DB \"%c%c%c%c%c%c%c\",%02XH\n", next+3, m_memory[next+3], - m_memory[next+4], m_memory[next+5], m_memory[next+6], m_memory[next+7], - m_memory[next+8], m_memory[next+9], m_memory[next+10]); - tb->append(line); - } + // Test if we need to build a label or use a ROM label + if (m_pDisType[addr].pLabel != NULL) + strcpy(arg, gDisStrings[m_pDisType[addr].idx].pLabel); + else + sprintf(arg, "L_%04XH", addr); } - // A CODE table is one where bytes are simply represented with - // a DB directive. Bytes are split into lines with 8 bytes per line - else if (m_pRom->pTables[x].type == TABLE_TYPE_CODE) - { - int next; - int last = c + m_pRom->pTables[x].size; - int count = 0; - for (next = c; next < last; next++) - { - if (count == 0) - sprintf(line, "%04XH DB ", next); - - sprintf(arg, "%02XH", m_memory[next]); - strcat(line, arg); - if ((next+1 != last) && (count != 7)) - strcat(line, ","); - else - { - strcat(line, "\n"); - if (next+1 == last) - { - strcat(line, "\n"); - tb->append(line); - line[0] = 0; - } - } + else + sprintf(arg, "%04XH", addr); + strcat(line, arg); + } - if (count == 7) - { - tb->append(line); - line[0] = 0; - count = 0; - } - else - count++; - } - } - // Add line to Edit Buffer -// tb->append(line); - c += m_pRom->pTables[x].size-1; - break; + if (!tricked_out) + AppendComments(line, opcode, addr, oldSchool); + + // Finish off the line + strcat(line, "\n"); + + // Test for LXI opcodes and check the target memory if it is a + // string or other special disassembly format + if (opcode == INST_LXI_B || opcode == INST_LXI_D || opcode == INST_LXI_H) + { + // Get the LXI target address + addr = m_memory[c+1] | (m_memory[c+2] << 8); + TestForStringArg(addr); } - x++; + // Increment memory counter by opcode length + if (!tricked_out) + c += op_len; + + // Add a blank line for JMP, CALL, and RET to provide routine separation + if (opcode == 195 || opcode == 201 || opcode == 0xE9) + { + strcat(line, "\n"); + } + + // Check if opcode is a rst7 + if (opcode == 0xFF) + rst7 = 1; + + // Check if opcode is a rst1 + if (opcode == 0xCF) + rst1 = 1; + + // Add line to Edit Buffer + tb->append(line); } - // Was this address identified as a table? If so, don't disassemble it! - if (table) - continue; + // If we aren't on the generate phase, then throw this buffer away + if (!generate) + { + // Delete the text buffer + delete tb; + + // Now scan through all disassembled addresses and determine which have actual code + ScanForCodeBlocks(); + + // Now scan non-code blocks for strings + ScanForStrings(); + } + } + + // Display the text buffer in the text editor + Fl_Text_Buffer* old_tb = m_pTextViewer->buffer(); + m_pTextViewer->buffer(tb); - // Get opcode from memory - opcode = m_memory[c]; + ResetHilight(); - // Determine length of this opcode - op_len = gLenTable[opcode] & 0x03; + // Change the title of the window in case there was an opened file + label("Disassembler"); - // Print the address and opcode value to the temporary line buffer - sprintf(line, "%04XH (%02XH) ", c, opcode); + delete old_tb; - // Print the opcode text to the temp line buffer - strcat(line, gStrTable[opcode]); + // Delete the disassembly type array + delete[] m_pDisType; +} - // Check if this opcode has a single byte argument - if (op_len == 1) +/* +============================================================================ +Resets the hilight buffer +============================================================================ +*/ +void VTDis::ResetHilight(void) +{ + // Test if color syntax hilighting enabled + ((Fl_Multi_Edit_Window *) m_pTextViewer)->DisableHl(); + if (m_colorHilight) + { + ((Fl_Multi_Edit_Window *) m_pTextViewer)->EnableHl(); + } + else + { + // Set the background if black background enabled + if (gpDis->m_blackBackground) { - // Single byte argument - sprintf(arg, "%02XH", m_memory[c+1]); - strcat(line, arg); + m_pTd->textcolor(FL_WHITE); + m_pTd->color(FL_BLACK); + m_pTd->selection_color(FL_DARK_BLUE); + m_pTd->textfont(FL_COURIER); } + else + m_pTd->textfont(FL_COURIER_BOLD); + + m_pTd->textsize(m_fontSize); + } +} - // Check if this opcode as a 2 byte argument - else if (op_len == 2) +/* +============================================================================ +Scans all disassembled addresses and fills in actual code blocks +============================================================================ +*/ +void VTDis::ScanForCodeBlocks(void) +{ + int disType = DIS_TYPE_UNKNOWN; + int c, j, len; + + // Loop for all disassembled code + for (c = m_StartAddress; c <= m_EndAddress; c++) + { + // Test if the type of disassembly for this address is known + if ((m_pDisType[c].dis_type & DIS_TYPE_CODE) || (disType == DIS_TYPE_CODE)) { - // Double byte argument - addr = m_memory[c+1] | (m_memory[c+2] << 8); - sprintf(arg, "%04XH", addr); - strcat(line, arg); - } + disType = DIS_TYPE_CODE; - AppendComments(line, opcode, addr); + // We are processing a code block. Fill in this entry + m_pDisType[c].dis_type |= disType; + m_pDisType[c].dis_type &= ~DIS_TYPE_STRING; - // Finish off the line - strcat(line, "\n"); + // Mark operand bytes as code + len = gLenTable[m_memory[c]] & 0x03; + for (j = 1; j <= len; j++) + { + m_pDisType[c+j].dis_type |= disType; + m_pDisType[c+j].dis_type &= ~DIS_TYPE_STRING; + } - // Increment memory counter by opcode length - c += op_len; + // Now test this opcode for end of code block + if (m_memory[c] == INST_JMP || m_memory[c] == INST_RET || + m_memory[c] == INST_PCHL) + { + // Change to unknown disassembly type + disType = DIS_TYPE_UNKNOWN; + } - // Add a blank line for JMP, CALL, and RET to provide routine separation - if (opcode == 195 || opcode == 201 || opcode == 0xE9) + // Skip over operand length + c += len; + } + else if (m_pDisType[c].dis_type & (DIS_TYPE_STRING | DIS_TYPE_JUMP)) { - strcat(line, "\n"); + // Skip over this string region + c += m_pDisType[c].idx - 1; } + } +} - // Check if opcode is a rst7 - if (opcode == 0xFF) - rst7 = 1; +/* +============================================================================ +Scans all disassembled addresses for unknown type and tests for strings +============================================================================ +*/ +void VTDis::ScanForStrings(void) +{ + int c; - // Check if opcode is a rst1 - if (opcode == 0xCF) - rst1 = 1; + // Loop for all disassembled code + for (c = m_StartAddress; c <= m_EndAddress; c++) + { + if (m_pDisType[c].dis_type == DIS_TYPE_UNKNOWN) + { + // Test this block for strings + TestForStringArg(c); + } + } +} +/* +============================================================================ +Adds a label to the disassembly +============================================================================ +*/ +void VTDis::DisassembleAddLabel(Fl_Text_Buffer* tb, int addr) +{ + char line[200]; + char arg[60]; + // Test if a comment block needed + if (m_pDisType[addr].pLabel != NULL) + { + strcpy(line, "\n; ======================================================\n; "); + strcat(line, gDisStrings[m_pDisType[addr].idx].desc); + strcat(line, "\n; ======================================================\n"); // Add line to Edit Buffer tb->append(line); + if (!m_oldSchool) + { + sprintf(arg, "%s:", gDisStrings[m_pDisType[addr].idx].pLabel); + sprintf(line, "%-39s; %04XH\n", arg, addr); + tb->append(line); + } + } + else if (!m_oldSchool) + { + // Generate a label based on the address + sprintf(line, "L_%04XH:\n", addr); + tb->append(line); } +} - // Display the text buffer in the text editor - Fl_Text_Buffer* old_tb = m_pTextViewer->buffer(); - m_pTextViewer->buffer(tb); - delete old_tb; +/* +============================================================================ +Disassembles the specified memory memory region as a string +============================================================================ +*/ +void VTDis::DisassembleAsString(Fl_Text_Buffer* tb, int startAddr, int len) +{ + int next; + int last = startAddr + len; + int str_active = 0; + int quote_active = 0; + char line[200]; + char arg[60]; + + for (next = startAddr; next < last; next++) + { + // Test if we need to print a label + if ((m_pDisType[next].dis_type & DIS_TYPE_LABEL) && + (next != startAddr)) + { + // Add a label for this string + DisassembleAddLabel(tb, next); + } + + if ((m_memory[next] == 0) && (str_active)) + { + if (quote_active) + strcat(line, "\""); + strcat(line, ",00H\n"); + tb->append(line); + line[0]=0; + str_active = 0; + quote_active = 0; + } + else if (!str_active) + { + if (m_memory[next] == 0) + { + if (m_oldSchool) + sprintf(line, "%04XH DB 00H\n", next); + else + sprintf(line, " DB 00H\n"); + tb->append(line); + line[0]=0; + } + else + { + if (iscntrl(m_memory[next]) || m_memory[next] > '~') + { + if (m_oldSchool) + sprintf(line, "%04XH DB %02XH", next, m_memory[next]); + else + sprintf(line, " DB %02XH", m_memory[next]); + } + else + { + if (m_oldSchool) + sprintf(line, "%04XH DB \"%c", next, m_memory[next]); + else + sprintf(line, " DB \"%c", m_memory[next]); + quote_active = 1; + } + str_active = 1; + } + } + else + { + if (iscntrl(m_memory[next]) || m_memory[next] > '~') + { + if (quote_active) + { + strcat(line, "\""); + quote_active = 0; + } + sprintf(arg, ",%02XH", m_memory[next]); + } + else + { + if (!quote_active) + sprintf(arg, ",\"%c", m_memory[next]); + else if (m_memory[next] == '"') + sprintf(arg, "\\%c", m_memory[next]); + else + sprintf(arg, "%c", m_memory[next]); + quote_active = 1; + } + strcat(line, arg); + } + + // Test if we need to terminate the string + if (((next+1 == last) && (m_memory[next] != 0)) || + (strlen(line) > 100) || (m_memory[next] < ' ' && m_memory[next+1] >= ' ' && + m_memory[next] != '\0' && strlen(line) > 16) || + (m_pDisType[next+1].dis_type & DIS_TYPE_LABEL)) + { + if (quote_active) + strcat(line, "\""); + strcat(line, "\n"); + tb->append(line); + line[0]=0; + str_active = 0; + quote_active = 0; + } + } } +/* +============================================================================ +Tests if the memory at address is a string and marks the m_pDisType as +DIS_TYPE_STRING if it is. +============================================================================ +*/ +void VTDis::TestForStringArg(int addr) +{ + int len, lastLen; + int c; + + // Test if this address already covered by another disassembly type + if (m_pDisType[addr].dis_type != DIS_TYPE_UNKNOWN) + return; + + // Validate the code prior to this is either marked as non-code or is a JMP, RET, PCHL + if (m_memory[addr-1] != INST_RET && m_memory[addr-3] != INST_JMP && + m_pDisType[addr-1].dis_type == DIS_TYPE_UNKNOWN) + return; + + // Keep track of string length. If less than 3, we don't count it as a + // string unless it is NULL terminated + len = lastLen = 0; + for (c = addr; c <= m_EndAddress; c++) + { + // Test if this byte is a string byte or not + if (m_memory[c] != '\x0D' && m_memory[c] != '\x0A' && + m_memory[c] != '\x09' && m_memory[c] != '\0' && + m_memory[c] != '\x0C' && + (m_memory[c] < ' ' || m_memory[c] >= '~')) + { + // End of possible string found + break; + } + + // Test if this address already has a disassembly type + if (m_pDisType[c].dis_type != DIS_TYPE_UNKNOWN) + break; + + // Increment the length + len++; + lastLen++; + + // Test if we need to reset the lastLen value + if (m_memory[c] == '\0') + lastLen = 0; + } + + // Test if length is greater than 3 (or 2 with a NULL) + if (len > 3 || (len == 2 && m_memory[c] == '\0')) + { + // Test the length of the last string seen + if (lastLen <= 2) + len -= lastLen; + + // Delcare it as a string + for (c = addr; c < addr + len; c++) + { + // Mark this entry as a string disassembly type + m_pDisType[c].dis_type |= DIS_TYPE_STRING; + m_pDisType[c].pLabel = NULL; + m_pDisType[c].idx = len; + } + } + + // Test if this LXI address is a string. If so, mark it as a label also + if (m_pDisType[addr].dis_type & DIS_TYPE_STRING) + m_pDisType[addr].dis_type |= DIS_TYPE_LABEL; -void VTDis::CopyIntoMem(unsigned char *ptr, int len) +} + +/* +============================================================================ +This copies the code to be disassembled into memory from the given pointer. +============================================================================ +*/ +void VTDis::CopyIntoMem(unsigned char *ptr, int len, int startAddr) { int c; for (c = 0; c < len; c++) { - m_memory[c] = ptr[c]; + if (c + startAddr < sizeof(m_memory)) + m_memory[c + startAddr] = ptr[c]; } } +/* +============================================================================ +This sets the base address of the disassembly when disassembling individual +lines of code. It is used by the remote debugger. +============================================================================ +*/ void VTDis::SetBaseAddress(int address) { m_BaseAddress = address; } +/* +============================================================================ +Disassembles a single line of code from system memory at the given address +using the current memory configuration. +============================================================================ +*/ int VTDis::DisassembleLine(int address, char* line) { char arg[60]; @@ -927,6 +2046,13 @@ int VTDis::DisassembleLine(int address, char* line) return 1+op_len; } +/* +============================================================================ +Disassembles the given address / opcode / operand data with comments from +the current StdRom description. This is used by the CPU Registers trace +window to disassemble the trace history. +============================================================================ +*/ int VTDis::DisassembleLine(int address, unsigned char opcode, unsigned short operand, char* line) { char arg[60]; @@ -964,3 +2090,500 @@ int VTDis::DisassembleLine(int address, unsigned char opcode, unsigned short ope return 1+op_len; } + +/* +============================================================================ +Sets the editor color and font +============================================================================ +*/ +void VTDis::SetEditorStyle(int blackBackground, int colorHilight, int fontSize) +{ + // Save the values + m_fontSize = fontSize; + m_blackBackground = blackBackground; + m_colorHilight = colorHilight; + + // Now update the text editor + if (m_pTd != NULL) + { + // Set the text color + if (blackBackground) + { + m_pTd->textcolor(FL_WHITE); + m_pTd->color(FL_BLACK); + m_pTd->textfont(FL_COURIER); + } + else + { + m_pTd->textcolor(FL_BLACK); + m_pTd->color(FL_WHITE); + m_pTd->textfont(FL_COURIER_BOLD); + } + + m_pTd->textsize(fontSize); + } +} + +/* +============================================================================ +Load the user preferences +============================================================================ +*/ +void VTDis::LoadPrefs(void) +{ + Fl_Preferences g(virtualt_prefs, "Disassembler"); + + // Get the window location + g.get("x", m_x, 50); + g.get("y", m_y, 50); + g.get("w", m_w, 600); + g.get("h", m_h, 400); + + // Validate the x/y coordinates + if (m_x < 10) + m_x = 50; + if (m_y < 10) + m_y = 50; + + // Get display style preferences + g.get("FontSize", m_fontSize, 14); + g.get("OldSchool", m_oldSchool, 0); + g.get("BlackBackground", m_blackBackground, 1); + g.get("ColorHilight", m_colorHilight, 1); + g.get("DisDepth", m_disassemblyDepth, 1000); + g.get("OpcodesLowercase", m_opcodesLowercase, 0); +} + +/* +============================================================================ +Save the user preferences +============================================================================ +*/ +void VTDis::SavePrefs(void) +{ + Fl_Preferences g(virtualt_prefs, "Disassembler"); + + // Get the window location + g.set("x", x()); + g.set("y", y()); + g.set("w", w()); + g.set("h", h()); + + // Get display style preferences + g.set("FontSize", m_fontSize); + g.set("OldSchool", m_oldSchool); + g.set("BlackBackground", m_blackBackground); + g.set("ColorHilight", m_colorHilight); + g.set("DisDepth", m_disassemblyDepth); + g.set("OpcodesLowercase", m_opcodesLowercase); +} + +/* +============================================================================ +Changes the text in the disassembler to indicate an active disassembly +============================================================================ +*/ +void VTDis::ShowDisassemblyMessage(void) +{ + ((Fl_Multi_Edit_Window *) m_pTextViewer)->DisableHl(); + m_pTd->buffer()->replace(0, 99999999, "\n\nDisassembling..."); +} + +/* +============================================================================ +FindDlg routine to show the Disassembler's Find Dialog +============================================================================ +*/ +void VTDis::FindDlg(void) +{ + // Validate the pointer isn't NULL + if (m_pFindDlg != NULL) + m_pFindDlg->m_pFindDlg->show(); +} + +/* +============================================================================ +FindNext routine finds the next item specified by the FindDlg +============================================================================ +*/ +void VTDis::FindNext(void) +{ + const char * pFind; + + // Determine what to find and how to find it + if (m_pFindDlg != NULL) + { + // Ensure there is a search string + pFind = m_pFindDlg->m_pFind->value(); + if (pFind[0] == '\0') + { + m_pFindDlg->m_pFindDlg->show(); + m_pFindDlg->m_pFind->take_focus(); + return; + } + + // Find the text +// m_Search = pFind; + Fl_Multi_Edit_Window* mw = (Fl_Multi_Edit_Window *) m_pTd; + + if (!mw->ForwardSearch(pFind, m_pFindDlg->m_pMatchCase->value())) + { + // Save the current position and search from beginning of file + int pos = mw->insert_position(); + mw->insert_position(0); + if (!mw->ForwardSearch(pFind, m_pFindDlg->m_pMatchCase->value())) + { + // If still not found, report not found + mw->insert_position(pos); + fl_alert("Search string %s not found", pFind); + m_pFindDlg->m_pFind->take_focus(); + } + } + + // Hide the dialog box + mw->take_focus(); + m_pFindDlg->m_pFindDlg->hide(); + show(); + } +} + +/* +============================================================= +OpenFile routine handles the File->Save File menu item. +This routine opens an existing file and creates an edit +window for the newly opened file. +============================================================= +*/ +void VTDis::OpenFile(void) +{ + Flu_File_Chooser* fc; + int count; + MString filename; + + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser((const char *) m_LastDir, + "Assembly Files (*.asm,*.a85,*.txt)", + 1, "Open File"); + fl_cursor(FL_CURSOR_DEFAULT); + fc->preview(0); + fc->show(); + + // Wait for user to select a file or escape + while (fc->visible()) + Fl::wait(); + + // Determine if a file was selected or not + count = fc->count(); + if (count == 0) + { + delete fc; + return; + } + + // Get the filename from the file chooser + filename = fc->value(); + filename.Replace('\\', '/'); + + // Delete the file chooser + m_LastDir = fc->get_current_directory(); + if (m_LastDir[m_LastDir.GetLength() - 1] == '/') + m_LastDir = m_LastDir.Left(m_LastDir.GetLength() - 1); + delete fc; + + // Try to load the file + if (!m_pTd->buffer()->loadfile((const char *) filename)) + { + MString title; + title.Format("Disassembler - %s", fl_filename_name((const char *) filename)); + label((const char *) title); + + // Reset the color hilighting + ResetHilight(); + } +} + +/* +============================================================= +SaveAs routine handles the File->Save As File menu item. +This routine determines the active edit window and calls +its SaveAs function. +============================================================= +*/ +void VTDis::SaveFile(void) +{ + Fl_Multi_Edit_Window* mw; + MString rootpath; + MString title; + + // First get a pointer to the active (topmost) window + mw = (Fl_Multi_Edit_Window*) m_pTd; + if (mw == NULL) + return; + + // Validate this is truly a Multi_Edit_Window + if (strcmp(mw->GetClass()->m_ClassName, "Fl_Multi_Edit_Window") != 0) + return; + + // Determine root path + rootpath = path; + + if (mw->Filename() == "") + mw->SaveAs(rootpath); + else + mw->SaveFile(rootpath); +} + +/* +============================================================================ +Define a local struct for the setup parameters. +============================================================================ +*/ +typedef struct dis_setup_params +{ + Fl_Input* pDepth; + Fl_Input* pFontSize; + Fl_Check_Button* pInverseHilight; + Fl_Check_Button* pOldSchool; + Fl_Check_Button* pColorHilight; + Fl_Check_Button* pOpcodeLowercase; + char sDepth[20]; + char sFontSize[20]; +} dis_setup_params_t; + +/* +============================================================================ +Callback for Trace Setup Ok button +============================================================================ +*/ +static void cb_setupdlg_OK(Fl_Widget* w, void* pOpaque) +{ + dis_setup_params_t* p = (dis_setup_params_t *) pOpaque; + int fontSize, blackBackground, hilight; + + // Save values + if (strlen(p->pFontSize->value()) > 0) + { + // update the font size + fontSize = atoi(p->pFontSize->value()); + if (fontSize < 6) + fontSize = 6; + } + + // Get Inverse Highlight selection + blackBackground = p->pInverseHilight->value(); + + // Get show as 16-bit selection + gpDis->m_oldSchool = p->pOldSchool->value(); + + // Get hilighting option + hilight = p->pColorHilight->value(); + + // Get lowercase setting + gpDis->m_opcodesLowercase = p->pOpcodeLowercase->value(); + + // Set the editor style + gpDis->SetEditorStyle(blackBackground, hilight, fontSize); + set_text_size(fontSize); + + // Get the updated trace depth +// gpDis->m_disassemblyDepth = atoi(p->pDepth->value()); + + // Now hide the parent dialog + w->parent()->hide(); + + Fl::check(); + + // Re-disassemble + gpDis->Disassemble(); + +} + +/* +============================================================================ +Callback for Trace Setup Cancel button +============================================================================ +*/ +static void cb_setupdlg_cancel(Fl_Widget* w, void* pOpaque) +{ + // Hide the parent dialog so we cancel out + w->parent()->hide(); +} + +/* +============================================================================ +Menu callback for disassembly setup +============================================================================ +*/ +void cb_setup(Fl_Widget* w, void* pOpaque) +{ + Fl_Box* b; + Fl_Window* pWin; + dis_setup_params_t p; + + /* Create a new window for the trace configuration */ + pWin = new Fl_Window(300, 200, "Disassembler Setup"); + + /* Create input field for trace depth */ +// b = new Fl_Box(20, 20, 100, 20, "Disassembly Depth"); +// b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); +// p.pDepth = new Fl_Input(160, 20, 80, 20, ""); +// p.pDepth->align(FL_ALIGN_LEFT); +// sprintf(p.sDepth, "%d", gpDis->m_disassemblyDepth); +// p.pDepth->value(p.sDepth); + + /* Create input field for font size */ + b = new Fl_Box(20, 20, 100, 20, "Font Size"); + b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + p.pFontSize = new Fl_Input(120, 20, 60, 20, ""); + p.pFontSize->align(FL_ALIGN_LEFT); + sprintf(p.sFontSize, "%d", gpDis->m_fontSize); + p.pFontSize->value(p.sFontSize); + + /* Create checkbox for hilight style */ + p.pInverseHilight = new Fl_Check_Button(20, 60, 190, 20, "Black background"); + p.pInverseHilight->value(gpDis->m_blackBackground); + + /* Create checkbox for 16-bit register style */ + p.pColorHilight = new Fl_Check_Button(20, 80, 200, 20, "Color syntax hilighting"); + p.pColorHilight->value(gpDis->m_colorHilight); + + /* Create checkbox for 16-bit register style */ + p.pOldSchool = new Fl_Check_Button(20, 100, 200, 20, "Old-school disassembly"); + p.pOldSchool->value(gpDis->m_oldSchool); + + /* Create a checkbox to make opcodes lowercase */ + p.pOpcodeLowercase = new Fl_Check_Button(20, 120, 200, 20, "Make opcode lowercase"); + p.pOpcodeLowercase->value(gpDis->m_opcodesLowercase); + + // Cancel button + { Fl_Button* o = new Fl_Button(80, 160, 60, 30, "Cancel"); + o->callback((Fl_Callback*) cb_setupdlg_cancel); + } + + // OK button + { Fl_Return_Button* o = new Fl_Return_Button(160, 160, 60, 30, "OK"); + o->callback((Fl_Callback*) cb_setupdlg_OK, &p); + } + + // Loop until user presses OK or Cancel + pWin->show(); + while (pWin->visible()) + Fl::wait(); + + // Delete the window + delete pWin; +} + +/* +======================================================= +Callback routine for opening files +======================================================= +*/ +static void cb_open_file(Fl_Widget* w, void*) +{ + if (gpDis != NULL) + gpDis->OpenFile(); +} + +/* +======================================================= +Callback routine for saving files +======================================================= +*/ +static void cb_save_file(Fl_Widget* w, void*) +{ + if (gpDis != NULL) + gpDis->SaveFile(); +} + +/* +================================================================================ +VTDisFindDlg pops up the Find Dlg for the disassembly window +================================================================================ +*/ +static void cb_dis_find(Fl_Widget* w, void* pOpaque) +{ + if (gpDis != NULL) + gpDis->FindDlg(); +} + +/* +================================================================================ +Callback for find next button +================================================================================ +*/ +static void cb_find_next(Fl_Widget* w, void* pOpaque) +{ + VTDis* pWin = (VTDis *) pOpaque; + + if (pWin == NULL) + pWin = gpDis; + + pWin->FindNext(); +} + +/* +================================================================================ +Callback for find close button +================================================================================ +*/ +static void cb_find_close(Fl_Widget* w, void* pOpaque) +{ + VTDisFindDlg* pWin = (VTDisFindDlg *) pOpaque; + + pWin->m_pFindDlg->hide(); +} + +/* +================================================================================ +VT_FindDlg routines below. +================================================================================ +*/ +VTDisFindDlg::VTDisFindDlg(class VTDis* pParent) +{ + // Create Find What combo list + m_pFindDlg = new Fl_Window(400, 300, "Find"); + Fl_Box *o = new Fl_Box(20, 10, 100, 25, "Find what:"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pFind = new Flu_Combo_List(20, 35, 360, 25, ""); + m_pFind->align(FL_ALIGN_LEFT); + m_pFind->input_callback(cb_find_next, pParent); + m_pFindDlg->resizable(m_pFind); + m_pFindDlg->callback(cb_find_close, this); + + // Create Find In choice box + o = new Fl_Box(20, 70, 100, 20, "Find in:"); + o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pFindIn = new Fl_Choice(20, 95, 360, 25, ""); + m_pFindIn->add("Current Window"); + m_pFindIn->add("Current Selection"); + m_pFindIn->value(0); + m_pFindDlg->resizable(m_pFindIn); + + o = new Fl_Box(20, 135, 360, 110, "Find options"); + o->box(FL_ENGRAVED_BOX); + o->labeltype(FL_ENGRAVED_LABEL); + o->align(FL_ALIGN_TOP_LEFT | FL_ALIGN_INSIDE); + m_pFindDlg->resizable(o); + + m_pBackward = new Fl_Check_Button(40, 160, 120, 25, "Search backward"); + m_pMatchCase = new Fl_Check_Button(40, 185, 100, 25, "Match case"); + m_pWholeWord = new Fl_Check_Button(40, 210, 140, 25, "Match whole word"); + + o = new Fl_Box(20, 250, 50, 45, ""); + m_pFindDlg->resizable(o); + + m_pNext = new Flu_Return_Button(160, 255, 100, 25, "Find Next"); + m_pNext->callback(cb_find_next, pParent); + + m_pCancel = new Flu_Button(280, 255, 100, 25, "Close"); + m_pCancel->callback(cb_find_close, this); + o = new Fl_Box(20, 295, 360, 2, ""); + m_pFindDlg->resizable(o); + + m_pFindDlg->end(); + m_pFindDlg->set_non_modal(); + m_pFindDlg->hide(); + + m_pParent = pParent; +} diff --git a/src/disassemble.h b/src/disassemble.h index c617615..319c9a9 100644 --- a/src/disassemble.h +++ b/src/disassemble.h @@ -31,34 +31,109 @@ #ifndef _DISASSEMBLE_H_ #define _DISASSEMBLE_H_ +#include +#include +#include +#include +#include "FLU/Flu_Combo_List.h" +#include "FLU/Flu_Button.h" + #include "display.h" +#include "MString.h" void disassembler_cb(Fl_Widget* w, void*); -class VTDis +// Structure to keep track of which addresses need labels printed +typedef struct DisType +{ + int dis_type; // Disassembly type for this address + const char *pLabel; // Pointer to the description + int idx; // Index into Disassembly String table +} DisType_t; + +#define DIS_TYPE_UNKNOWN 0x00 +#define DIS_TYPE_LABEL 0x01 +#define DIS_TYPE_STRING 0x02 +#define DIS_TYPE_JUMP 0x04 +#define DIS_TYPE_CODE 0x08 +#define DIS_TYPE_TABLE 0x10 + +class VTDis; + +class VTDisFindDlg +{ +public: + VTDisFindDlg(class VTDis* pParent); + + Fl_Window* m_pFindDlg; + Flu_Combo_List* m_pFind; + Fl_Choice* m_pFindIn; + Fl_Check_Button* m_pBackward; + Fl_Check_Button* m_pMatchCase; + Fl_Check_Button* m_pWholeWord; + Flu_Button* m_pNext; + Flu_Button* m_pCancel; + + class VTDis* m_pParent; + + char search[256]; +}; + + +class VTDis : public Fl_Double_Window { public: - VTDis(); - - int m_StartAddress; - int m_EndAddress; - unsigned char m_memory[65536]; - class Fl_Text_Editor* m_pTextViewer; - RomDescription_t *m_pRom; - int m_WantComments; - - void Disassemble(); - void SetTextViewer(class Fl_Text_Editor* pTextViewer); - void CopyIntoMem(unsigned char * ptr, int len); - int DisassembleLine(int address, char* line); - int DisassembleLine(int address, unsigned char opcode, unsigned short operand, char* line); - void SetBaseAddress(int address); - void AppendComments(char* line, int opcode, int address); + VTDis(int x, int y, const char* title); + VTDis(void); + ~VTDis(); + + int m_StartAddress; // Starting address of the disassembly + int m_EndAddress; // Ending address of the disassembly + unsigned char m_memory[65536]; // Our local memory to disassemble from + class My_Text_Editor* m_pTextViewer; + RomDescription_t *m_pRom; // The ROM description table we are using + int m_WantComments; // Indicates if comments should be appended + int m_x, m_y, m_w, m_h; // User preference window location + int m_fontSize; // Font size + int m_oldSchool; // Set true to generate legacy style disassembly + int m_blackBackground; // Set true for black background + int m_colorHilight; // Set TRUE for color hilighting + int m_disassemblyDepth; // Depth (in instructions) to simulate for disassembly + int m_opcodesLowercase; // Creates disassembly with lower-case opcodes + + void Disassemble(); + void SetTextViewer(class My_Text_Editor* pTextViewer); + void CopyIntoMem(unsigned char * ptr, int len, int startAddr = 0); + int DisassembleLine(int address, char* line); + int DisassembleLine(int address, unsigned char opcode, unsigned short operand, char* line); + void SetBaseAddress(int address); + void AppendComments(char* line, int opcode, int address, int oldSchool = 1); + void LoadPrefs(void); + void SavePrefs(void); + void SetTextEditor(My_Text_Editor* pTd) { m_pTd = pTd; } + void SetEditorStyle(int blackBackground, int colorHilight, int fontSize); + void ResetHilight(void); + void ShowDisassemblyMessage(void); + void CreateFindDlg(void); + void FindDlg(void); + void FindNext(void); + void OpenFile(void); + void SaveFile(void); protected: - char* m_StrTable[256]; - unsigned char m_LenTable[256]; - int m_BaseAddress; + void DisassembleAddLabel(Fl_Text_Buffer* tb, int addr); + void DisassembleAsString(Fl_Text_Buffer* tb, int addr, int size); + void TestForStringArg(int address); + void ScanForCodeBlocks(void); + void ScanForStrings(void); + + char* m_StrTable[256]; + unsigned char m_LenTable[256]; + int m_BaseAddress; + DisType_t* m_pDisType; + My_Text_Editor* m_pTd; + VTDisFindDlg* m_pFindDlg; + MString m_LastDir; }; diff --git a/src/display.cpp b/src/display.cpp index 0f07526..cfc2824 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -228,6 +228,66 @@ const char *gSpKeyText[] = { "DOWN" }; +/* +======================================================= +Collapse window: Causes the given window to appear to +"collapse" into the main window by resizing it smaller +and smaller in steps. +======================================================= +*/ +void collapse_window(Fl_Window* pWin) +{ + int newx, newy, neww, newh; + int dx, dy, dw, dh; + int steps = 10, c; + + // Shrink the window to nothingness... + newx = MainWin->x() + MainWin->w()/4; + newy = MainWin->y() + MainWin->h()/4; + neww = 50; + newh = 50; + + dx = (newx - pWin->x()) / steps; + dy = (newy - pWin->y()) / steps; + dw = (neww - pWin->w()) / steps; + dh = (newh - pWin->h()) / steps; + for (c = 0; c < steps-1; c++) + { + pWin->resize(pWin->x()+dx, pWin->y()+dy, pWin->w()+dw, pWin->h()+dh); + Fl::check(); + } + + // Finally, hide the window altogether + pWin->hide(); +} +/* +======================================================= +Expande window: Causes the given window to appear to +"expand" to it's final size and location by resizing it +larger and larger in steps. +======================================================= +*/ +void expand_window(Fl_Window* pWin, int newx, int newy, int neww, int newh) +{ + int dx, dy, dw, dh; + int c, steps = 9; + + pWin->hide(); + pWin->resize(MainWin->x(), MainWin->y(), 50, 150); + pWin->show(); + + dx = (newx - pWin->x()) / steps; + dy = (newy - pWin->y()) / steps; + dw = (neww - pWin->w()) / steps; + dh = (newh - pWin->h()) / steps; + for (c = 0; c < steps-1; c++) + { + pWin->resize(pWin->x()+dx, pWin->y()+dy, pWin->w()+dw, pWin->h()+dh); + Fl::check(); + } + + pWin->resize(newx, newy, neww, newh); +} /* ======================================================= External Menu Item Callbacks @@ -1246,9 +1306,9 @@ Fl_Menu_Item menuitems[] = { { "M102", 0, cb_M102, (void *) 2, FL_MENU_RADIO }, { "T200", 0, cb_M200, (void *) 3, FL_MENU_RADIO }, { "PC-8201", 0, cb_PC8201, (void *) 4, FL_MENU_RADIO }, -// { "PC-8300", 0, cb_PC8300, (void *) 5, FL_MENU_RADIO }, { "M10", 0, cb_M10, (void *) 5, FL_MENU_RADIO }, { "KC85", 0, cb_KC85, (void *) 6, FL_MENU_RADIO }, + { "PC-8300", 0, cb_PC8300, (void *) 7, FL_MENU_RADIO }, { 0 }, { "Speed", 0, 0, 0, FL_SUBMENU }, { "2.4 MHz", 0, rspeed, (void *) 1, FL_MENU_RADIO | FL_MENU_VALUE }, @@ -2149,13 +2209,9 @@ void init_display(void) for(i=MODEL_M100;i<=MODEL_PC8300;i++) { if(i==gModel) - if(i==MODEL_PC8300) - menuitems[i+mIndex].flags=FL_MENU_RADIO | FL_MENU_VALUE | FL_MENU_DIVIDER; - else menuitems[i+mIndex].flags=FL_MENU_RADIO | FL_MENU_VALUE; + menuitems[i+mIndex].flags=FL_MENU_RADIO | FL_MENU_VALUE; else - if(i==MODEL_PC8300) - menuitems[i+mIndex].flags=FL_MENU_RADIO | FL_MENU_DIVIDER; - else menuitems[i+mIndex].flags=FL_MENU_RADIO; + menuitems[i+mIndex].flags=FL_MENU_RADIO; } //================================================== @@ -3389,6 +3445,9 @@ int T100_Disp::handle(int event) case FL_LEAVE: return 1; + case FL_MOVE: + return 1; + case FL_DRAG: if (m_HaveMouse) { @@ -3646,7 +3705,7 @@ int T100_Disp::handle(int event) ========================================= ========================================= */ - if (gModel == MODEL_PC8201) + if (gModel == MODEL_PC8201 || gModel == MODEL_PC8300) { // Handle the '^' key (Shift 6) if (key == '6') @@ -4066,7 +4125,7 @@ int T100_Disp::handle(int event) { gSpecialKeys &= ~MT_SPACE; } - if (gModel == MODEL_PC8201) + if (gModel == MODEL_PC8201 || gModel == MODEL_PC8300) { // Deal with special keys for the PC-8201 diff --git a/src/display.h b/src/display.h index 2a48901..eb4fe6d 100644 --- a/src/display.h +++ b/src/display.h @@ -54,6 +54,10 @@ void handle_simkey(void); void switch_model(int); void init_other_windows(void); void enable_tpdd_log_menu(int bEnabled); +#ifdef __cplusplus +void collapse_window(Fl_Window* pWin); +void expand_window(Fl_Window* pWin, int newx, int newy, int neww, int newh); +#endif typedef int (*get_key_t)(int); typedef int (*event_key_t)(void); diff --git a/src/file.cpp b/src/file.cpp index 0e08e5b..f1dc92c 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -1099,6 +1099,20 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) } } + // Determine file location + if (file_type == TYPE_BA) + { + addr1 = get_memory16(gStdRomDesc->sFilePtrBA); + } + else if ((file_type == TYPE_CO) || (file_type == TYPE_HEX)) + { + addr1 = get_memory16(gStdRomDesc->sBeginVar); + } + else if (file_type == TYPE_DO) + { + addr1 = get_memory16(gStdRomDesc->sFilePtrDO); + } + // Determine if file will fit in memory addr3 = get_memory16(gStdRomDesc->sBasicStrings); addr2 = get_memory16(gStdRomDesc->sBeginVar); @@ -1234,14 +1248,6 @@ int remote_load_from_host(const char *filename) Routines to save Model T files to the host ======================================================================= */ - -typedef struct model_t_files { - char name[10]; - unsigned short address; - unsigned short dir_address; - unsigned short size; -} model_t_files_t; - Fl_Window *gSaveToHost; int gSave; diff --git a/src/file.h b/src/file.h index b2679ea..9d30aad 100644 --- a/src/file.h +++ b/src/file.h @@ -47,6 +47,13 @@ void cb_SaveToHost(Fl_Widget* w, void*); int load_optrom_file(const char* filename); int delete_file(const char* filename, unsigned short addr = 0); +typedef struct model_t_files { + char name[10]; + unsigned short address; + unsigned short dir_address; + unsigned short size; +} model_t_files_t; + #define FILE_ERROR_INVALID_HEX 1 #define FILE_ERROR_FILE_NOT_FOUND 2 diff --git a/src/highlight.cpp b/src/highlight.cpp index 0fcfe28..dfcda5f 100644 --- a/src/highlight.cpp +++ b/src/highlight.cpp @@ -112,6 +112,7 @@ const char *asm_code_keywords[] = { "cmp", "cnc", "cnz", + "cp", "cpe", "cpi", "cpo", @@ -365,7 +366,7 @@ void style_parse(const char *text, char *style, int length) // !(isalnum(*(text-1)) || *(text-1)=='_')) { // Might be a keyword... - for (temp = text, bufptr = buf; (isalnum(*temp) || *temp=='_') && + for (temp = text, bufptr = buf; ((*temp > 0) && (isalnum(*temp) || *temp=='_')) && bufptr < (buf + sizeof(buf) - 1); *bufptr++ = tolower(*temp++)); { //if (!islower(*temp)) @@ -503,7 +504,7 @@ void style_parse(const char *text, char *style, int length) } else *style++ = current; - last = isalnum(*text) || *text == '_'; + last = (*text > 0) && (isalnum(*text) || *text == '_'); if (*text != 0x0a) col++; diff --git a/src/ide.cpp b/src/ide.cpp index d311c01..920d78b 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -235,6 +235,37 @@ Fl_Menu_Item gRootMenu[] = { Fl_Pixmap gTextDoc( textdoc_xpm ), gComputer( computer_xpm ); +/* +======================================================= +Save the user's preferences for IDE window size. +======================================================= +*/ +void get_hilight_color_prefs(void) +{ + int pc; + + virtualt_prefs.get("Ide_ColorText", pc, FL_BLACK); + hl_plain = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorLineComment", pc, 95); + hl_linecomment = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorBlockComment", pc, 93); + hl_blockcomment = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorString", pc, 219); + hl_string = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorDirective", pc, 219); + hl_directive = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorKeyword", pc, 74); + hl_type = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorInstruction", pc, 220); + hl_keyword = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorCharacter", pc, 75); + hl_character = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorLabel", pc, 116); + hl_label = (Fl_Color) pc; + virtualt_prefs.get("Ide_ColorBackground", pc, FL_BLACK); + background_color = (Fl_Color) pc; +} + /* ======================================================= Save the user's preferences for IDE window size. @@ -927,7 +958,7 @@ Routine to load the IDE preferences */ void VT_Ide::LoadPrefs(void) { - int pc, c; + int c; char sRecentFile[32]; // Get the initial window size from the user preferences @@ -962,26 +993,8 @@ void VT_Ide::LoadPrefs(void) } } - virtualt_prefs.get("Ide_ColorText", pc, FL_BLACK); - hl_plain = (Fl_Color) pc; - virtualt_prefs.get("Ide_ColorLineComment", pc, 95); - hl_linecomment = (Fl_Color) pc; - virtualt_prefs.get("Ide_ColorBlockComment", pc, 93); - hl_blockcomment = (Fl_Color) pc; - virtualt_prefs.get("Ide_ColorString", pc, 219); - hl_string = (Fl_Color) pc; - virtualt_prefs.get("Ide_ColorDirective", pc, 219); - hl_directive = (Fl_Color) pc; - virtualt_prefs.get("Ide_ColorKeyword", pc, 74); - hl_type = (Fl_Color) pc; - virtualt_prefs.get("Ide_ColorInstruction", pc, 220); - hl_keyword = (Fl_Color) pc; - virtualt_prefs.get("Ide_ColorCharacter", pc, 75); - hl_character = (Fl_Color) pc; - virtualt_prefs.get("Ide_ColorLabel", pc, 116); - hl_label = (Fl_Color) pc; - virtualt_prefs.get("Ide_ColorBackground", pc, FL_BLACK); - background_color = (Fl_Color) pc; + get_hilight_color_prefs(); + virtualt_prefs.get("Ide_SmartIndent", gSmartIndent, 1); virtualt_prefs.get("Ide_ReloadProject", gReloadProject, 1); virtualt_prefs.get("Ide_AutoBrace", auto_brace_mode, 1); @@ -3683,6 +3696,7 @@ void VT_Ide::BuildProject(void) linker.SetObjDirs(m_ActivePrj->m_LinkPath); linker.SetProjectType(m_ActivePrj->m_ProjectType); linker.SetOutputFile(m_ActivePrj->m_OutputName); + linker.SetTargetModel(m_ActivePrj->m_TargetModel); if (linkerScriptFound) linker.SetLinkerScript(linkerScript); else diff --git a/src/io.c b/src/io.c index 1bd6597..f160634 100644 --- a/src/io.c +++ b/src/io.c @@ -56,6 +56,7 @@ uchar io21; /* Real-time milisecond countdown */ double gPort21Time; /* Starting time for io21 from previous out */ uchar io90; uchar ioA1; +static uchar ioA3; uchar ioBA; uchar ioB9; uchar ioE8; @@ -218,7 +219,7 @@ void update_keys(void) (gKeyStates['5'] << 4) | (gKeyStates['6'] << 5) | (gKeyStates['7'] << 6) | (gKeyStates['8'] << 7)); - if (gModel != MODEL_PC8201) + if (gModel != MODEL_PC8201 && gModel != MODEL_PC8300) { keyscan[3] = ~(gKeyStates['o'] | (gKeyStates['p'] << 1) | (gKeyStates['['] << 2) | (gKeyStates[';'] << 3) | @@ -416,7 +417,7 @@ void out(uchar port, uchar val) 6 & 7 - Active Serial Port */ case 0x90: /* T200 Clock/Timer chip */ - if (gModel == MODEL_PC8201) + if (gModel == MODEL_PC8201 || gModel == MODEL_PC8300) { if ((val & 0x10) && !(io90 & 0x10)) { @@ -487,6 +488,11 @@ void out(uchar port, uchar val) ioA1 = val & 0x0F; break; + case 0xA3: /* PC-8300 ROM Bank #0 Select */ + ioA3 = val & 0x03; + set_rom0_bank(ioA3); + break; + case 0xB0: /* PIO Command/Status Register */ case 0xB8: /* @@ -955,6 +961,9 @@ int inport(uchar port) case 0xA1: /* Bank control port on NEC laptops */ return ioA1; + case 0xA3: /* ROM #0 Bank select for PC-8300 */ + return ioA3; + case 0xB0: /* PIO Command/Status Register */ case 0xB8: /* diff --git a/src/linker.cpp b/src/linker.cpp index e0fd4b9..0b71852 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -17,6 +17,7 @@ Written: 11/13/09 Kenneth D. Pettit #include #include #include +#include extern "C" { @@ -25,17 +26,23 @@ char path[512]; } static const char *gLoaderCode[] = { - "89GOTO96\n", - "90V=VARPTR(A$):P=PEEK(V+1)+PEEK(V+2)*M\n", - "91C=PEEK(P):IFC=34THENRETURN\n", - "92V=0:FORX=0TO4:T=PEEK(P):V=V*85+T-35:K=K+T:P=P+1:NEXT\n", - "93H=INT(V/M/M):L=V-H*M*M:POKES,H/M:POKES+1,H-INT(H/M)*M:POKES+2,L/M:POKES+3,L-INT(L/M)*M:S=S+4\n", - "94L=D:D=D+I:IFD>184THEND=184\n", - "95FORX=L+1TOD:PSET(X,27):NEXT:PSET(D,27):PSET(D-1,26):PSET(D-2,25):PSET(D-1,28):PSET(D-2,29):PRESET(L-1,26):PRESET(L-2,25):PRESET(L-1,28):PRESET(L-2,29):GOTO 91\n", - "96CLS:PRINT@56,\"Loading\":PRINT@129,CHR$(245);:PRINT@151,CHR$(245);:D=59:I=%.3f:S=%d:M=256:FORJ%=1TO%d:READA$:GOSUB90:NEXT\n", - "97IFK<>%dTHEN99ELSE PRINT@200,\"Success! Issue command: clear 256,%d\"\n", - "98SAVEM\"%s\",%d,%d,%d:END\n", - "99PRINT@200,\"Chksum error! Need %d, got\";S:END\n" + "89GOTO96\r\n", + "90P=1\x0D\x0A", + "91C$=MID$(A$,P,5):IFC$=\"\"THENRETURN\x0D\x0A", + "92V=0:FORX=1TO5:T=ASC(MID$(C$,X,1)):V=V*85+T-35:K=K+T:NEXT:P=P+5\x0D\x0A", + "93H=INT(V/M/M):L=V-H*M*M:POKES,H/M:POKES+1,H-INT(H/M)*M:POKES+2,L/M:POKES+3,L-INT(L/M)*M:S=S+4\x0D\x0A", + "94L=D:D=D+I:IFD>184THEND=184\x0D\x0A", + "95FORX=L+1TOD:PSET(X,27):NEXT:PSET(D,27):PSET(D-1,26):PSET(D-2,25):PSET(D-1,28):PSET(D-2,29):PRESET(L-1,26):PRESET(L-2,25):PRESET(L-1,28):PRESET(L-2,29):GOTO 91\x0D\x0A", + "96CLS:DEFDBLV:PRINT@50,\"Creating %s\":PRINT@129,CHR$(245);:PRINT@151,CHR$(245);:D=59:I=%.3f:S=%d:M=256:FORJ%%=1TO%d:READA$:GOSUB90:NEXT\x0D\x0A", + "97IFK<>%dTHEN99ELSE PRINT@200,\"Success! Issue command: clear 256,%d\"\x0D\x0A", + "98SAVEM\"%s\",%d,%d,%d:END\x0D\x0A", + "99PRINT@200,\"Chksum error! Need %d, got\";K:END\x0D\x0A", + + // These are used for PC-8201 and PC-8300 links + "96CLS:DEFDBLV:LOCATE10,1:PRINT\"Creating %s\":LOCATE9,3:PRINT\"|\"SPACE$(21)\"|\";:D=59:I=%.3f:S=%d:M=256:FORJ%%=1TO%d:READA$:GOSUB90:NEXT\x0D\x0A", + "97IFK<>%dTHEN99ELSE LOCATE0,5:PRINT\"Success! Issue command: clear 256,%d\"\x0D\x0A", + "98BSAVE\"%s\",%d,%d,%d:END\x0D\x0A", + "99LOCATE0,5:PRINT\"Chksum error! Need %d, got\";K:END\x0D\x0A" }; static const char *gsEdl = "Error during linking: "; @@ -2433,7 +2440,7 @@ int VTLinker::CreateQuintuple(FILE* fd, unsigned long& ascii85, int& lineNo, if (lineCount >= MAX_LOADER_LINE_LEN) { // Terminate the current data statement - fprintf(fd, "\"\n"); + fprintf(fd, "\"\x0D\x0A"); lineCount = 0; // Start a new data line. First grab the file position @@ -2490,7 +2497,6 @@ int VTLinker::GenerateLoaderFile(int startAddr, int endAddr, int entryAddr) { // Munge next byte into ascii85 calculation ascii85 = ascii85 * 256 + (unsigned char) pSect->m_pProgBytes[x]; - printf("%02X\t", (unsigned char) pSect->m_pProgBytes[x]); // Check if time to output a quintuple from our quadtuple if (++quadtuple == 4) @@ -2544,7 +2550,7 @@ int VTLinker::GenerateLoaderFile(int startAddr, int endAddr, int entryAddr) else { // Terminate the last DATA statement - fprintf(fd, "\"\n"); + fputs("\"\x0D\x0A", fd); } // Now write the rest of the program to the file @@ -2557,16 +2563,38 @@ int VTLinker::GenerateLoaderFile(int startAddr, int endAddr, int entryAddr) inc = (double) 128 / (double) quintupleCount; // Print next line with increment, start address, and data count - fprintf(fd, gLoaderCode[7], (float) inc, ((int) startAddr)-65536, dataCount); + char coname[32]; + m_LoaderFilename.MakeUpper(); + strcpy(coname, (const char *) m_LoaderFilename); + fl_filename_setext(coname, sizeof(coname), ".CO"); - // Print line with checksum validation and CLEAR statement - fprintf(fd, gLoaderCode[8], checksum, startAddr); + // The PC-8201 and PC-8300 use LOCATE and BSAVE instead of PRINT@ and SAVEM + if (m_TargetModel == MODEL_PC8201 || m_TargetModel == MODEL_PC8300) + { + fprintf(fd, gLoaderCode[7+4], (const char *) coname, (float) inc, ((int) startAddr)-65536, dataCount); + + // Print line with checksum validation and CLEAR statement + fprintf(fd, gLoaderCode[8+4], checksum, startAddr); - // Print the line with the SAVEM filename command - fprintf(fd, gLoaderCode[9], (const char *) m_LoaderFilename, startAddr, endAddr, entryAddr); + // Print the line with the SAVEM filename command + fprintf(fd, gLoaderCode[9+4], (const char *) coname, startAddr, endAddr-startAddr+1, entryAddr); - // Finally print the line reporting the checksum error - fprintf(fd, gLoaderCode[10], checksum); + // Finally print the line reporting the checksum error + fprintf(fd, gLoaderCode[10+4], checksum); + } + else + { + fprintf(fd, gLoaderCode[7], (const char *) coname, (float) inc, ((int) startAddr)-65536, dataCount); + + // Print line with checksum validation and CLEAR statement + fprintf(fd, gLoaderCode[8], checksum, startAddr); + + // Print the line with the SAVEM filename command + fprintf(fd, gLoaderCode[9], (const char *) coname, startAddr, endAddr, entryAddr); + + // Finally print the line reporting the checksum error + fprintf(fd, gLoaderCode[10], checksum); + } // Now close the file and we're all done fclose(fd); diff --git a/src/linker.h b/src/linker.h index 80ba0e9..62edfeb 100644 --- a/src/linker.h +++ b/src/linker.h @@ -220,6 +220,7 @@ class VTLinker : public VTObject int m_Command; // Script command during file parsing int m_TotalCodeSpace; // Total space used by code int m_TotalDataSpace; // Total space used for data + int m_TargetModel; // Target model we are linking for unsigned short m_StartAddress; // Start address of generated code unsigned short m_EntryAddress; // Entry address of generated code MString m_OutputName; // Name of output file @@ -295,6 +296,7 @@ class VTLinker : public VTObject void SetLoaderFilename(const MString& loaderFilename); void SetProjectType(int type); void SetStdoutFunction(void *pContext, stdOutFunc_t pFunc); + void SetTargetModel(int targetModel) { m_TargetModel = targetModel; } const MStringArray& GetErrors() { return m_Errors; }; void SetOutputFile(const MString& outFile ); int TotalCodeSpace(void) { return m_TotalCodeSpace; } diff --git a/src/m100emu.c b/src/m100emu.c index 786993e..781db97 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -768,7 +768,7 @@ void init_cpu(void) horrible kludge, but it fixes the problem. */ #ifdef WIN32 - if (gModel == MODEL_PC8201) + if (gModel == MODEL_PC8201 || gModel == MODEL_PC8300) { lock_remote(); debug_set_monitor_callback(model_8201_bug_workaround); @@ -823,7 +823,7 @@ void resetcpu(void) horrible kludge, but it fixes the problem. */ #ifdef WIN32 - if (gModel == MODEL_PC8201) + if (gModel == MODEL_PC8201 || gModel == MODEL_PC8300) { lock_remote(); debug_set_monitor_callback(model_8201_bug_workaround); diff --git a/src/m100rom.c b/src/m100rom.c index 1952eb8..2008852 100644 --- a/src/m100rom.c +++ b/src/m100rom.c @@ -231,6 +231,7 @@ Std_ROM_Addresses_t gM100_Vars[] = { { 0xFABE, R_SP_SAVE_BUF }, { 0xFAC0, R_LOWEST_RAM }, { 0xFAC9, R_RST_38H_OFFSET }, + { 0xFACE, R_CUR_PROG_LOAD_ADDR }, { 0xFAD0, R_LAST_PGRM_LEN }, { 0xFADA, R_RST_38H_VCTR_TBL }, { 0xFAE2, R_LCD_OUTPUT_HOOK }, @@ -538,18 +539,23 @@ Std_ROM_Addresses_t gM100_Funs[] = { { 0x1FBE, R_KILL_TEXT_FILE }, { 0x2037, R_NAME_STMT }, { 0x20FE, R_NEW_STMT }, + { 0x2146, R_UPDATE_SYS_PTRS }, { 0x21FA, R_STRLEN }, { 0x2206, R_GET_FIND_DO_FILE }, { 0x220F, R_OPEN_TEXT_FILE }, + { 0x2239, R_SAVE_TO_CATALOG }, { 0x2280, R_CSAVE_STMT }, { 0x22B9, R_CAS_WRITE_BUF }, { 0x22CC, R_SAVEM_STMT }, - { 0x22DD, R_CSAVEM_STMT }, + { 0x22DD, R_CSAVEM_STMT }, + { 0x2346, R_PROC_SAVEM_ARGS }, { 0x2377, R_CLOAD_STMT }, - { 0x2413, R_CAS_READ_REC }, + { 0x2413, R_CAS_READ_REC }, + { 0x2426, R_CLOAD_ONERR }, { 0x2478, R_GEN_VERIFY_FAIL_ERR }, { 0x2491, R_LOADM_STMT }, { 0x24A7, R_CLOADM_STMT }, + { 0x253D, R_LOAD_CO_HEADER }, { 0x2542, R_MOVE_B_BYTES }, { 0x254B, R_EXEC_CO_FILE }, { 0x260B, R_CAS_OPEN_OUT_BA }, @@ -559,7 +565,8 @@ Std_ROM_Addresses_t gM100_Funs[] = { { 0x2653, R_CAS_OPEN_IN_DO }, { 0x2656, R_CAS_OPEN_IN_CO }, { 0x273A, R_STR_FUN }, - { 0x27B1, R_PRINT_STRING }, + { 0x27B1, R_PRINT_STRING }, + { 0x2904, R_MEMCPY_CALL_ARGS }, { 0x290F, R_MOVE_L_BYTES }, { 0x2943, R_LEN_FUN }, { 0x294F, R_ASC_FUN }, diff --git a/src/memedit.cpp b/src/memedit.cpp index 00f4928..f04122a 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -194,10 +194,12 @@ Callback routine for the memory editor window */ void cb_memeditwin (Fl_Widget* w, void*) { - gmew->hide(); mem_clear_monitor_callback(memory_monitor_cb); MemoryEditor_SavePrefs(); + // Colapse the window + collapse_window(gmew); + delete gmew; gmew = NULL; } @@ -1029,7 +1031,7 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) neww = memedit_ctrl.pMemEdit->m_w; newh = memedit_ctrl.pMemEdit->m_h; - gmew->resize(newx, newy, neww, newh); + expand_window(gmew, newx, newy, neww, newh); } // Show the window @@ -1243,7 +1245,7 @@ void T100_MemEditor::SetRegionOptions(void) { if (gRex) { - if (gModel == MODEL_T200 || gModel == MODEL_PC8201) + if (gModel == MODEL_T200 || gModel == MODEL_PC8201 || gModel == MODEL_PC8300) { memedit_ctrl.pRegion->add("RAM 1"); memedit_ctrl.pRegion->add("RAM 2"); @@ -1256,6 +1258,12 @@ void T100_MemEditor::SetRegionOptions(void) memedit_ctrl.pRegion->add("ROM"); if (gModel == MODEL_T200) memedit_ctrl.pRegion->add("ROM 2"); + if (gModel == MODEL_PC8300) + { + memedit_ctrl.pRegion->add("ROM 2"); + memedit_ctrl.pRegion->add("ROM 3"); + memedit_ctrl.pRegion->add("ROM 4"); + } memedit_ctrl.pRegion->add("Flash"); if (gRex == REX2) memedit_ctrl.pRegion->add("128K SRAM"); @@ -1301,6 +1309,18 @@ void T100_MemEditor::SetRegionOptions(void) memedit_ctrl.pRegion->add("Opt ROM"); memedit_ctrl.pRegion->value(0); break; + + case MODEL_PC8300: + memedit_ctrl.pRegion->add("RAM 1"); + memedit_ctrl.pRegion->add("RAM 2"); + memedit_ctrl.pRegion->add("RAM 3"); + memedit_ctrl.pRegion->add("ROM A"); + memedit_ctrl.pRegion->add("ROM B"); + memedit_ctrl.pRegion->add("ROM C"); + memedit_ctrl.pRegion->add("ROM D"); + memedit_ctrl.pRegion->add("Opt ROM"); + memedit_ctrl.pRegion->value(0); + break; } } if (gRampac) @@ -1325,7 +1345,7 @@ void T100_MemEditor::SetScrollSize(void) if (gRex) { region = memedit_ctrl.pRegion->value(); - if (gModel == MODEL_T200 || gModel == MODEL_PC8201) + if (gModel == MODEL_T200 || gModel == MODEL_PC8201 || gModel == MODEL_PC8300) { switch (region) { @@ -1349,6 +1369,9 @@ void T100_MemEditor::SetScrollSize(void) case 6: m_Max = 128 * 1024 / 16; break; + default: + m_Max = ROMSIZE / 16; + break; } } else @@ -1380,6 +1403,7 @@ void T100_MemEditor::SetScrollSize(void) case MODEL_M10: case MODEL_M102: case MODEL_PC8201: + case MODEL_PC8300: if (region == 0) m_Max = RAMSIZE / 16; else @@ -1452,6 +1476,10 @@ int T100_MemEditor::GetRegionEnum(void) if (strcmp(reg_text, "ROM") == 0) m_Region = REGION_ROM; + // Test if ROM region is selected + if (strcmp(reg_text, "ROM A") == 0) + m_Region = REGION_ROM; + // Test if OptROM region is selected if (strcmp(reg_text, "Opt ROM") == 0) m_Region = REGION_OPTROM; @@ -1460,6 +1488,18 @@ int T100_MemEditor::GetRegionEnum(void) if (strcmp(reg_text, "ROM 2") == 0) m_Region = REGION_ROM2; + // Test if ROM2 region is selected + if (strcmp(reg_text, "ROM B") == 0) + m_Region = REGION_ROM2; + + // Test if ROM2 region is selected + if (strcmp(reg_text, "ROM C") == 0) + m_Region = REGION_ROM3; + + // Test if ROM2 region is selected + if (strcmp(reg_text, "ROM D") == 0) + m_Region = REGION_ROM4; + // Test if RAMPAC region is selected if (strcmp(reg_text, "RamPac") == 0) m_Region = REGION_RAMPAC; diff --git a/src/memory.c b/src/memory.c index abe1605..83231e5 100644 --- a/src/memory.c +++ b/src/memory.c @@ -28,7 +28,7 @@ memory.c uchar *gMemory[64]; /* CPU Memory space */ int gRamBottom = 0x8000;/* Defines the amount of RAM installed */ uchar gBaseMemory[65536]; /* System Memory */ -uchar gSysROM[65536]; /* System ROM */ +uchar gSysROM[4*32768]; /* System ROM */ uchar gOptROM[32768]; /* Option ROM */ uchar gMsplanROM[32768]; /* MSPLAN ROM T200 Only */ //extern char path[255]; @@ -38,6 +38,7 @@ int gOptRomRW = 0; /* Flag to make OptROM R/W */ unsigned char rambanks[3*32768]; /* Model T200 & NEC RAM banks */ uchar gRamBank = 0; /* Currently enabled bank */ int gRomBank = 0; /* Current ROM Bank selection */ +static int gRom0Bank = 0; /* Current ROM #0 Bank for PC-8300 */ int gRomSize = 32768; /* Current ROM Size for R/O calculation */ uchar gReMem = 0; /* Flag indicating if ReMem emulation enabled */ @@ -83,6 +84,7 @@ int gIndex[65536]; extern RomDescription_t gM100_Desc; extern RomDescription_t gM200_Desc; extern RomDescription_t gN8201_Desc; +extern RomDescription_t gN8300_Desc; extern RomDescription_t gM10_Desc; //JV extern RomDescription_t gKC85_Desc; @@ -188,8 +190,18 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) case REGION_ROM2: addr = address; - for (c = 0; c < count; c++) - data[c] = gMsplanROM[addr++]; + if (gModel == MODEL_T200) + { + // Copy from the MsPlan ROM + for (c = 0; c < count; c++) + data[c] = gMsplanROM[addr++]; + } + else if (gModel = MODEL_PC8300) + { + // Copy from ROM Bank B + for (c = 0; c < count; c++) + data[c] = gSysROM[32768 + addr++]; + } break; case REGION_OPTROM: @@ -334,6 +346,26 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) for (;(cp_ptr < count); cp_ptr++) data[cp_ptr] = ptr[addr++]; break; + + case REGION_ROM3: + addr = address; + if (gModel = MODEL_PC8300) + { + // Copy from ROM Bank B + for (c = 0; c < count; c++) + data[c] = gSysROM[2*32768 + addr++]; + } + break; + + case REGION_ROM4: + addr = address; + if (gModel = MODEL_PC8300) + { + // Copy from ROM Bank B + for (c = 0; c < count; c++) + data[c] = gSysROM[3*32768 + addr++]; + } + break; } } @@ -1534,7 +1566,7 @@ void patch_vt_version(char* pMem, int size) /* Test if VirtulalT version should replace (C) Micro***t text */ if (gShowVersion) { - if (gModel == MODEL_PC8201) + if (gModel == MODEL_PC8201 || gModel == MODEL_PC8300) { sprintf(newString, " VirtualT %s ", VERSION); newString[14] = 0; @@ -1610,8 +1642,8 @@ void load_sys_rom(void) gStdRomDesc = &gM10_Desc; else if (gModel == MODEL_KC85) gStdRomDesc = &gKC85_Desc; -// else if (gModel == MODEL_PC8300) -// gStdRomDesc = &gN8300_Desc; + else if (gModel == MODEL_PC8300) + gStdRomDesc = &gN8300_Desc; else gStdRomDesc = &gM100_Desc; @@ -1638,12 +1670,18 @@ void load_sys_rom(void) /* If Model = T200 then read the 2nd ROM (MSPLAN) */ if (gModel == MODEL_T200) readlen = fread(gMsplanROM, 1, 32768, fd); + + /* If Model is PC-8300, then read the rest of the 128K ROM */ + if (gModel == MODEL_PC8300) + readlen = fread(&gSysROM[32768], 1, 3 * 32768, fd); /* Close the ROM file */ fclose(fd); /* Patch the ROM with VirtualT version if requested */ patch_vt_version((char *) gSysROM, ROMSIZE); + if (gModel == MODEL_PC8300) + patch_vt_version((char *) &gSysROM[2*32768], ROMSIZE); /* Copy ROM into system memory */ memcpy(gBaseMemory, gSysROM, ROMSIZE); @@ -1787,6 +1825,22 @@ unsigned char get_rom_bank(void) return gRomBank; } +/* +============================================================================= +set_rom0_bank: This function sets the current ROM #0 bank for the PC-8300s. + The 8300 has a 128K rom with 4 selectable banks. +============================================================================= +*/ +void set_rom0_bank(unsigned char bank) +{ + // Save the bank + gRom0Bank = bank; + + // Now update the bank if needed + if (gRomBank == 0) + set_rom_bank(gRomBank); +} + /* ============================================================================= set_rom_bank: This function sets the current ROM bank for all models. It @@ -1864,7 +1918,10 @@ void set_rom_bank(unsigned char bank) switch (bank) { case 0: /* System ROM bank */ - memcpy(gBaseMemory,gSysROM,ROMSIZE); + if (gModel == MODEL_PC8201) + memcpy(gBaseMemory, gSysROM, ROMSIZE); + else + memcpy(gBaseMemory, &gSysROM[gRom0Bank*32768], ROMSIZE); break; case 1: /* Option ROM bank */ diff --git a/src/memory.h b/src/memory.h index 6f9acff..76c0206 100644 --- a/src/memory.h +++ b/src/memory.h @@ -107,7 +107,9 @@ extern "C" { #define REGION_RAMPAC 10 #define REGION_REX_FLASH 11 #define REGION_REX2_RAM 12 -#define REGION_MAX 13 +#define REGION_ROM3 13 +#define REGION_ROM4 14 +#define REGION_MAX 15 #define REX 1 #define REX2 2 @@ -136,7 +138,7 @@ typedef struct { #define AMD_FLASH_TYPE_REX 2 extern unsigned char *gMemory[64]; -extern unsigned char gSysROM[65536]; +extern unsigned char gSysROM[4*32768]; extern unsigned char gOptROM[32768]; extern unsigned char gBaseMemory[65536]; extern unsigned char gReMem; @@ -188,6 +190,7 @@ void load_sys_rom(void); void load_opt_rom(void); void set_ram_bank(unsigned char page); void set_rom_bank(unsigned char bank); +void set_rom0_bank(unsigned char bank); unsigned char get_ram_bank(void); unsigned char get_rom_bank(void); diff --git a/src/multieditwin.cpp b/src/multieditwin.cpp index eab1bdf..0c7d0b7 100644 --- a/src/multieditwin.cpp +++ b/src/multieditwin.cpp @@ -115,10 +115,23 @@ void cb_multieditwin(Fl_Widget* w, void *args) // delete mw; } +void Fl_Multi_Edit_Window::buffer(Fl_Text_Buffer* buf) +{ + DisableHl(); + if (m_pHlCtrl != NULL) + m_pHlCtrl->textbuf = buf; + My_Text_Editor::buffer(buf); + m_tb = buf; + if (!gDisableHl && m_pHlCtrl != NULL) + EnableHl(); +} + Fl_Multi_Edit_Window::Fl_Multi_Edit_Window(int x, int y, int w, int h, const char* title) : My_Text_Editor(x, y, w, h, title) { /* Create window */ + m_pHlCtrl = NULL; + m_tb = new Fl_Text_Buffer(); buffer(m_tb); m_tb->add_modify_callback(multiEditModCB, this); @@ -285,6 +298,10 @@ void Fl_Multi_Edit_Window::SaveAs(const MString& rootpath) m_FileName = fc->value(); m_tb->savefile((const char *) m_FileName); + MString title = fl_filename_name((const char *) m_FileName); + title = "Disassembler - " + title; + label((const char *) title); + delete fc; m_Modified = 0; } diff --git a/src/multieditwin.h b/src/multieditwin.h index dde71c7..2083aa4 100644 --- a/src/multieditwin.h +++ b/src/multieditwin.h @@ -35,6 +35,10 @@ #include "My_Text_Editor.h" #include "highlight.h" +#ifndef TRUE +#define TRUE 1 +#endif + //class Fl_Multi_Edit_Window : public Fl_Multi_Window class Fl_Multi_Edit_Window : public My_Text_Editor, public VTObject { @@ -62,6 +66,8 @@ class Fl_Multi_Edit_Window : public My_Text_Editor, public VTObject void EnableHl(void); int ForwardSearch(const char *pFind, int caseSensitive = TRUE); virtual void show(void); + virtual void buffer(Fl_Text_Buffer* buf); + Fl_Text_Buffer* buffer() { return My_Text_Display::buffer(); } // Fl_Text_Editor* m_te; protected: diff --git a/src/n8300rom.c b/src/n8300rom.c new file mode 100644 index 0000000..4a304b9 --- /dev/null +++ b/src/n8300rom.c @@ -0,0 +1,941 @@ +/* n8300rom.c */ + +/* $Id$ */ + +/* + * Copyright 2013 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "roms.h" +#include "romstrings.h" + + +Std_ROM_Table_t gN8300_Tables[] = { + { 0x0003, 5, TABLE_TYPE_STRING }, + { 0x0040, 266, TABLE_TYPE_JUMP }, + { 0x014A, 26*2,TABLE_TYPE_JUMP }, + { 0x017E, 542, TABLE_TYPE_MODIFIED_STRING2 }, + { 0x039C, 20, TABLE_TYPE_JUMP }, + { 0x03BD, 40, TABLE_TYPE_JUMP }, + { 0x03E5, 70, TABLE_TYPE_2BYTE }, + { 0x042B, 225, TABLE_TYPE_CODE }, + { 0x050C, 23, TABLE_TYPE_STRING }, + { 0x0F5D, 19, TABLE_TYPE_STRING }, + { 0x1057, 17, TABLE_TYPE_STRING }, + { 0x1712, 16, TABLE_TYPE_STRING }, + { 0x1942, 6, TABLE_TYPE_JUMP }, + + { 0x1962, 10, TABLE_TYPE_JUMP }, + { 0x1974, 10, TABLE_TYPE_JUMP }, + { 0x1AF7, 10, TABLE_TYPE_JUMP }, + { 0x1BCC, 6, TABLE_TYPE_JUMP }, + { 0x1BDA, 10, TABLE_TYPE_JUMP }, + { 0x1CEC, 10, TABLE_TYPE_JUMP }, + { 0x287B, 6, TABLE_TYPE_STRING }, + { 0x2ABF, 12, TABLE_TYPE_STRING }, + { 0x2FDA, 1, TABLE_TYPE_CODE }, + { 0x2FDB, 4*8, TABLE_TYPE_CODE }, +// { 0x2FEB, 4*4, TABLE_TYPE_CODE }, + { 0x3CCA, 131, TABLE_TYPE_CODE }, + { 0x3DFD, 1, TABLE_TYPE_CODE }, + { 0x3DFE, 7*4, TABLE_TYPE_CODE }, + { 0x3F49, 1, TABLE_TYPE_CODE }, + { 0x3F4A, 5*4, TABLE_TYPE_CODE }, + { 0x3F98, 1, TABLE_TYPE_CODE }, + { 0x3F99, 9*4, TABLE_TYPE_CODE }, + { 0x43EF, 36, TABLE_TYPE_BYTE_LOOKUP }, + { 0x4429, 72, TABLE_TYPE_BYTE_LOOKUP }, + { 0x47FC, 8*3, TABLE_TYPE_BYTE_LOOKUP }, + { 0x528D, 29, TABLE_TYPE_CTRL_DELIM }, + { 0x52AA, 1, TABLE_TYPE_CODE }, + { 0x52AB, 16, TABLE_TYPE_JUMP }, +// { 0x5318, 9, TABLE_TYPE_STRING }, +// { 0x5321, 18, TABLE_TYPE_4BYTE_CMD }, +// { 0x5333, 1, TABLE_TYPE_CODE }, + { 0x5371, 23, TABLE_TYPE_STRING }, +// { 0x536B, 29, TABLE_TYPE_STRING }, + { 0x5445, 20, TABLE_TYPE_JUMP }, + { 0x54AD, 17, TABLE_TYPE_STRING }, + { 0x54BE, 7, TABLE_TYPE_STRING }, + { 0x560A, 53, TABLE_TYPE_STRING }, + { 0x5E61, 5, TABLE_TYPE_CODE }, + { 0x5E66, 4, TABLE_TYPE_STRING }, + { 0x5E6A, 2, TABLE_TYPE_CODE }, + { 0x5E6C, 4, TABLE_TYPE_STRING }, + { 0x5E70, 2, TABLE_TYPE_CODE }, + { 0x5E72, 4, TABLE_TYPE_STRING }, + { 0x5E76, 2, TABLE_TYPE_CODE }, + { 0x5E78, 1, TABLE_TYPE_CODE }, + { 0x5E79, 57, TABLE_TYPE_STRING }, + { 0x5EB2, 150, TABLE_TYPE_STRING }, + { 0x5FEB, 13, TABLE_TYPE_STRING }, + { 0x5FF8, 10, TABLE_TYPE_CODE }, + { 0x6002, 46, TABLE_TYPE_STRING }, +// { 0x551D, 1, TABLE_TYPE_CODE }, + { 0x6105, 17, TABLE_TYPE_STRING }, + { 0x61EF, 64, TABLE_TYPE_JUMP }, + { 0x627F, 13, TABLE_TYPE_STRING }, + { 0x67B3, 17, TABLE_TYPE_STRING }, + { 0x6845, 21, TABLE_TYPE_BYTE_LOOKUP }, + { 0x6C8E, 66, TABLE_TYPE_CATALOG }, + { 0x6F40, 18, TABLE_TYPE_JUMP }, + { 0x75DA, 240, TABLE_TYPE_CODE }, + { 0x76CC, 20, TABLE_TYPE_CODE }, + { 0x78B7, 96*5, TABLE_TYPE_CODE }, + { 0x7A97, 85*6-1, TABLE_TYPE_CODE }, +/* { 0x7BF1, 322, TABLE_TYPE_CODE }, +*/ { 0x7EA1, 14, TABLE_TYPE_CODE }, + { 0x7F89, 12, TABLE_TYPE_STRING }, + { 0x7F95, 12, TABLE_TYPE_STRING }, + { 0x7FA1, 14, TABLE_TYPE_STRING }, + { 0x7FAF, 15, TABLE_TYPE_STRING }, + { -1, 0, 0 } +}; + +Std_ROM_Addresses_t gN8300_Vars[] = { + { 0x0040, R_FUN_VCTR_TBL }, + { 0x0080, R_BASIC_TBL }, + { 0x02EE, R_MATH_VCTR_TBL }, + { 0x03E5, R_BASIC_ERR_TXT }, + { 0x042B, R_INIT_IMAGE }, + { 0x036F, R_XROM_DET_IMAGE }, + { 0x050C, R_BASIC_STRINGS }, +// { 0x1F24, R_CAS_FREQ_CNT }, +// { 0x4349, R_CAS_FREQ_CNT }, + { 0xF3C2, R_TERM_FKEY_VCTR_TBL }, + { 0x5E61, R_DIR_DISP_ORDER_TBL }, + { 0x5FF7, R_TEXT_FKEY_VCTR_TBL }, + { 0x5C8E, R_ROM_CAT_ENTRIES }, + { 0x7266, R_INT_EXIT_FUN }, + { 0x7267, R_INT_EXIT_FUN }, + { 0x75DA, R_8155_PIO_PAT1 }, + { 0x76CC, R_8155_PIO_PAT2 }, + { 0x7EA1, R_INIT_CLK_VALUES }, + { 0x7F89, R_MENU_STRINGS }, + { 0x7F95, R_MODEL_NUM_STRING }, + { 0xF380, R_ACTIVE_SIGNATURE }, + { 0xF384, R_HIMEM }, + { 0xF386, R_RST0_HOOK }, + { 0xF389, R_RST_5_5_VCTR }, + { 0xF38C, R_RST_6_5_VCTR }, + { 0xF38F, R_RST_7_5_VCTR }, + { 0xF392, R_TRAP_VCTR }, + { 0xF3B9, R_EXEC_2ND_ROM }, + { 0xF3C0, R_TELCOM_FKEY_VCTR }, + { 0xF3BF, R_OPTION_ROM_FLAG }, + { 0xF3C0, R_FKEY_STAT_TBL }, + { 0xF3E8, R_NEW_CONSOLE_FLAG }, + { 0xF3E5, R_CURSOR_ROW }, + { 0xF3E6, R_CURSOR_COL }, + { 0xF3E7, R_ACTIVE_ROW_CNT }, + { 0xF3E8, R_ACTIVE_COL_CNT }, + { 0xF3E9, R_LABEL_LINE_PROT }, + { 0xF3EA, R_SCROLL_DISABLE }, + { 0xF3EB, R_CURSOR_STAT }, + { 0xF3EC, R_CURSOR_ROW2 }, + { 0xF3ED, R_CURSOR_COL2 }, + { 0xF3F2, R_ESC_MODE_FLAG }, + { 0xF3F4, R_REV_VID_SWITCH }, + { 0xF3FA, R_LAST_PLOT_X }, + { 0xF3FB, R_LAST_PLOT_Y }, + { 0xF401, R_PWR_OFF_STAT }, + { 0xF403, R_DUPLEX_SWITCH }, + { 0xF404, R_RS232_LF_SWITCH }, + { 0xF406, R_RS232_PARAM_TBL }, + { 0xF40C, R_ADDRESS_LAST_CALLED }, + { 0xF413, R_OUT_STMT_HOOK }, + { 0xF44B, R_INP_STMT_HOOK }, + { 0xF453, R_LAST_ERROR_CODE }, + { 0xF455, R_LPT_HEAD_POS }, + { 0xF456, R_OUTPUT_DEVICE }, + { 0xF459, R_BASIC_STR_BUF_PTR }, + { 0xF45B, R_CUR_BASIC_LINE_NUM }, + { 0xF45D, R_START_BASIC_PGM_PTR }, + { 0xF461, R_END_OF_STMT_MARKER }, + { 0xF590, R_CUR_MENU_DIR_LOC }, + { 0xF591, R_MAX_MENU_DIR_LOC }, + { 0xF5A1, R_KEYBOARD_BUF }, + { 0xF6A4, R_CURSOR_H_POS }, + { 0xF6A5, R_FKEY_DEF_BUF }, + { 0xF746, R_BASIC_FKEY_DEF_BUF }, + { 0xF462, R_FILE_RAM_END }, + { 0xF832, R_SEC_ONES }, + { 0xF833, R_SEC_TENS }, + { 0xF834, R_MIN_ONES }, + { 0xF835, R_MIN_TENS }, + { 0xF836, R_HR_ONES }, + { 0xF837, R_HR_TENS }, + { 0xF838, R_DATE_ONES }, + { 0xF839, R_DATE_TENS }, + { 0xF83A, R_DAY_CODE }, + { 0xF83B, R_MONTH }, + { 0xF83C, R_YEAR_ONES }, + { 0xF83D, R_YEAR_TENS }, + { 0xF840, R_ONTIME_TIME }, +// { 0xF841, R_ONCOM_FLAG }, +// { 0xF945, R_ONCOM_ADDRESS }, + { 0xF841, R_ONTIME_FLAG }, +// { 0xF948, R_ONTIME_ADDRESS }, +// { 0xF94A, R_FKEY_VCTR_TBL }, + { 0xF84F, R_DIR_RAM_START }, + { 0xF979, R_UNSAVED_BASIC_PTR }, + { 0xF87C, R_PASTE_RAM_START }, +// { 0xFAAD, R_LABEL_ENABLE_FLAG }, + { 0xF9BC, R_BASIC_LIST_START }, + { 0xF9AE, R_SP_SAVE_BUF }, + { 0xF9B0, R_LOWEST_RAM }, +// { 0xFAC9, R_RST_38H_OFFSET }, + { 0xF9C0, R_CUR_PROG_LOAD_ADDR }, + { 0xF9C2, R_LAST_PGRM_LEN }, + { 0xF9CC, R_RST_38H_VCTR_TBL }, + { 0xFA8A, R_VAR_CREATE_LOC_FLAG }, + { 0xFA8B, R_LAST_VAR_TYPE }, + { 0xFA9A, R_FILE_BUF_PTR }, + { 0xFAC7, R_DATA_STMT_LINE_NUM }, + { 0xFAC9, R_FOR_NEXT_ACTIVE_FLAG }, + { 0xFACB, R_LAST_VAR_ASSIGNED_ADDR }, + { 0xFACE, R_RUNNING_LINE_NUM_ADDR }, + { 0xFAD0, R_BASIC_SP_BUF }, + { 0xFAD2, R_LAST_ERR_LINE_NUM }, + { 0xFAD4, R_LAST_ENTERED_LINE_NUM }, + { 0xFAD6, R_ERR_PTR }, + { 0xFAD8, R_ONERROR_ADDRESS }, + { 0xFADA, R_BASIC_RUNNING }, + { 0xFADD, R_BREAK_LINE_NUM }, + { 0xFADF, R_BREAK_ADDRESS }, + { 0xFAE1, R_DO_FILES_PTR }, + { 0xFAE3, R_CO_FILES_PTR }, + { 0xFAE5, R_VAR_PTR }, + { 0xFAE7, R_ARRAY_TBL_PTR }, + { 0xFAE9, R_UNUSED_MEM_PTR }, + { 0xFAEB, R_DATA_SEARCH_ADDR }, + { 0xFAED, R_DEF_TBL }, +// { 0xFBE7, R_FP_TEMP1 }, + { 0xFB28, R_FP_FAC1 }, + { 0xFB24, R_INT_FAC1 }, +// { 0xFC60, R_FP_TEMP2 }, + { 0xFB2E, R_FP_FAC2 }, + { 0xFB62, R_MAXFILES }, + { 0xFB63, R_FILE_NUM_TBL_PTR }, + { 0xFB78, R_BASIC_FILENAME }, + { 0xFB81, R_LAST_LOAD_FILENAME }, + { 0xFBC0, R_ALT_LCD_CHAR_BUF }, + { 0xFD00, R_LCD_CHAR_BUF }, + { 0xFE40, R_XON_XOFF_CTRL }, + { 0xFE41, R_XON_XOFF_CTRL }, + { 0xFE42, R_XON_XOFF_ENABLE }, + { 0xFE43, R_RS232_INIT_STAT }, + { 0xFE44, R_PORT_90H }, + { 0xFEC4, R_RS232_CHAR_BUF }, + { 0xFE45, R_RS232_BUF_CNT }, + { 0xFE46, R_RS232_BUF_OUT }, + { 0xFE47, R_RS232_BUF_IN }, + { 0xFE49, R_CTRL_S_STAT }, + { 0xFE4A, R_UART_BAUD_TIMER_VAL }, + { 0xFE4C, R_RS232_PARITY_CTRL }, + { 0xFE57, R_KEY_SCAN_STORAGE1 }, + { 0xFE60, R_KEY_SCAN_STORAGE2 }, + { 0xFE62, R_KEY_REPT_START }, + { 0xFE66, R_2ND_KEY_BUF_PTR }, + { 0xFE68, R_KEY_BUF_CNT }, + { 0xFE69, R_KEY_TYPEAHEAD_BUF }, + { 0xFEAB, R_CURSOR_BIT_PAT_BUF }, + { -1, -1 } +}; + +Std_ROM_Addresses_t gN8300_Funs[] = { + { 0x0000, R_RESET_VECTOR }, + { 0x0008, R_COMP_BYTE_M }, + { 0x0010, R_GET_NONWHITE }, + { 0x0018, R_COMP_DE_HL }, + { 0x001E, R_PRINT_SPACE }, + { 0x0020, R_PRINT_CHAR }, + { 0x0024, R_PWR_DOWN_TRAP }, + { 0x0028, R_DET_LAST_VAR_TYPE }, + { 0x002C, R_RST_5_5 }, + { 0x0030, R_GET_FAC1_SIGN }, + { 0x0034, R_RST_6_5 }, + { 0x0038, R_RAM_VCTR_TBL_DRIVER }, + { 0x003C, R_RST_7_5 }, + { 0x0040, R_FUN_VCTR_TBL }, + { 0x017E, R_BASIC_KEYWORD_TBL }, +// { 0x018F, R_FUN_KEYWORD_TBL1 }, +// { 0x01F0, R_FUN_KEYWORD_TBL2 }, +// { 0x0262, R_BASIC_VECTOR_TBL }, +// { 0x02E2, R_MATH_PRIORITY_TBL }, + { 0x03BD, R_MATH_VCTR_TBL }, + { 0x03E5, R_BASIC_ERR_MSG_TXT }, + { 0x042B, R_FUN_INIT_IMAGE }, + { 0x050C, R_FUN_BASIC_STRINGS }, + { 0x0523, R_POP_FOR_NEXT }, + { 0x0544, R_INIT_AND_READY }, + { 0x0568, R_GEN_SN_ERROR }, + { 0x056B, R_GEN_d0_ERROR }, + { 0x056E, R_GEN_NF_ERROR }, + { 0x0571, R_GEN_DD_ERROR }, + { 0x0574, R_GEN_RW_ERROR }, + { 0x0577, R_GEN_OV_ERROR }, + { 0x057A, R_GEN_MO_ERROR }, + { 0x057D, R_GEN_TM_ERROR }, + { 0x0585, R_GEN_ERR_IN_E }, + { 0x05B5, R_RESTORE_JMP_BC }, + { 0x05ED, R_PRINT_BASIC_ERR }, + { 0x0501, R_POP_GO_BASIC_RDY }, + { 0x062D, R_GO_BASIC_RDY_OK }, + { 0x063C, R_GO_BASIC_RDY }, + { 0x064E, R_PERFORM_M_GO_RDY }, + { 0x0714, R_UPDATE_LINE_ADDR }, + { 0x073A, R_EVAL_LIST_ARGS }, + { 0x075D, R_FIND_LINE_IN_DE }, + { 0x0760, R_FIND_LINE_DE_AT_HL }, + { 0x077B, R_TOKEN_COMPRESS }, + { 0x097B, R_FOR_STMT }, + { 0x09C0, R_TO_STMT }, + { 0x09D8, R_STEP_STMT }, + { 0x0A1D, R_RUN_BASIC_PGRM }, + { 0x0A4F, R_RUN_BASIC_AT_HL }, + { 0x0A55, R_EXEC_INST_IN_A }, + { 0x0A77, R_RST_10H_INC_HL }, + { 0x0B4B, R_DEFDBL_STMT }, + { 0x0B45, R_DEFINT_STMT }, + { 0x0B48, R_DEFSNG_STMT }, + { 0x0B42, R_DEFSTR_STMT }, + { 0x0B4D, R_DECL_VAR_TYPE_E }, + { 0x0B87, R_GEN_FC_ERROR }, + { 0x0B8C, R_EVAL_LINE_NUM }, + { 0x0BAC, R_ASCII_TO_BIN_PREINC }, + { 0x0BD0, R_RUN_STMT }, + { 0x0BE6, R_GOSUB_STMT }, + { 0x0C19, R_GOTO_STMT }, + { 0x0C4E, R_GEN_UL_ERROR }, + { 0x0C53, R_RETURN_STMT }, + { 0x0C8C, R_DATA_STMT }, + { 0x0C8D, R_REM_STMT }, + { 0x0CB6, R_LET_STMT }, + { 0x0D22, R_ON_STMT }, + { 0x0D27, R_ON_ERROR_STMT }, + { 0x0D4E, R_ON_KEY_STMT }, + { 0x0D87, R_ON_TIME_STMT }, + { 0x0DA3, R_RESUME_STMT }, + { 0x0DF5, R_ERROR_STMT }, + { 0x0E00, R_IF_STMT }, + { 0x0E3D, R_LPRINT_STMT }, + { 0x0E45, R_PRINT_STMT }, + { 0x0EEB, R_TAB_STMT }, + { 0x0F32, R_LINE_STMT }, + { 0x0F82, R_INPUT_NO_STMT }, + { 0x0F8C, R_INPUT_STMT }, + { 0x0FBA, R_READ_STMT }, + { 0x1091, R_EVAL_BASIC_INST }, + { 0x120B, R_INT16_DIV }, + { 0x121A, R_EVAL_FUN }, + { 0x124D, R_ERR_FUN }, + { 0x125C, R_ERL_FUN }, + { 0x12A7, R_EVAL_VAR }, + { 0x12B5, R_CONV_M_TOUPPER }, + { 0x12B6, R_CONV_A_TOUPPER }, + { 0x1306, R_ASCII_NUM_CONV }, + { 0x1323, R_NOT_FUN }, + { 0x1338, R_RST_28H }, + { 0x1366, R_OR_FUN }, + { 0x1371, R_AND_FUN }, + { 0x137C, R_XOR_FUN }, + { 0x1384, R_IMP_FUN }, + { 0x1397, R_LPOS_FUN }, + { 0x139D, R_POS_FUN }, + { 0x13A0, R_LD_FAC1_INT }, +// { 0x10E6, R_CHK_RUNNING_PGRM }, +// { 0x10EF, R_GEN_ID_ERROR }, + { 0x13B5, R_INP_FUN }, + { 0x13C1, R_OUT_STMT }, + { 0x13C7, R_EVAL_EXPR }, + { 0x13C8, R_EVAL_EXPR_PREDEC }, + { 0x13E2, R_EVAL_EXPR }, + { 0x13E3, R_EVAL_EXPR_PREDEC }, + { 0x13F0, R_LLIST_STMT }, + { 0x13F5, R_LIST_STMT }, + { 0x1462, R_BUF_TO_LCD }, + { 0x15E0, R_PEEK_FUN }, + { 0x15E7, R_POKE_FUN }, + { 0x15F3, R_EVAL_EXPR }, + { 0x1617, R_RENUM_STMT }, + { 0x174D, R_WAIT_KEY }, +// { 0x13A5, R_TOGGLE_LABEL }, + { 0x183D, R_CHK_KEY_QUEUE }, + { 0x187B, R_POWER_STMT }, + { 0x1895, R_LOW_PWR_TRAP }, + { 0x18A9, R_POWER_DOWN }, + { 0x18C6, R_POWER_CONT_STMT }, + { 0x18CE, R_POWER_ON_STMT }, + { 0x18DD, R_OUT_CH_TO_LPT }, + { 0x18EF, R_LOAD_CAS_HDR }, + { 0x18FC, R_GEN_IO_ERROR }, + { 0x1901, R_DET_CAS_SYNC_HDR }, + { 0x1913, R_CAS_MOTOR_ON }, + { 0x1915, R_CAS_MOTOR_OFF }, + { 0x191B, R_CAS_READ_BYTE }, + { 0x192F, R_CAS_WRITE_BYTE }, + { 0x1942, R_LCD_DCB }, + { 0x1948, R_LCD_OPEN }, + { 0x1955, R_LCD_OUT }, + { 0x195D, R_POP_ALL_REGS }, + { 0x1962, R_CRT_DCB }, + { 0x1974, R_RAM_DCB }, + { 0x197E, R_RAM_OPEN }, + { 0x1A05, R_RAM_CLOSE }, + { 0x1A24, R_RAM_OUT }, + { 0x1A3C, R_RAM_IN }, + { 0x1A93, R_RAM_IO }, + { 0x1AF7, R_CAS_DCB }, + { 0x1B01, R_CAS_OPEN }, + { 0x1B25, R_CAS_CLOSE }, + { 0x1B3F, R_CAS_OUT }, + { 0x1B4A, R_CAS_IN }, + { 0x1BCC, R_LPT_DCB }, + { 0x1BD2, R_LPT_OUT }, + { 0x1BDA, R_COM_DCB }, +// { 0x1BE4, R_MDM_OPEN }, + { 0x1BE4, R_COM_OPEN }, + { 0x1C01, R_COM_CLOSE }, + { 0x1C1D, R_COM_OUT }, + { 0x1C28, R_COM_IN }, + { 0x1C47, R_COM_IO }, +// { 0x1C4E, R_MDM_DCB }, +// { 0x17DB, R_MDM_CLOSE }, + { 0x1C4E, R_SET_RS232_PARAMS }, + { 0x1CEC, R_BCR_DCB }, + { 0x1CFE, R_EOF_FUN }, + { 0x1D74, R_TIME_FUN }, + { 0x1D7F, R_READ_TIME }, + { 0x1D9F, R_DATE_FUN }, + { 0x1DEE, R_UPDATE_CLK_VALUES }, + { 0x1DF9, R_TIME_STMT }, +// { 0x1DF9, R_UPDATE_CLK_CHIP }, + { 0x1E07, R_DATE_STMT }, + { 0x1E5B, R_GET_TIME_STRING }, + { 0x1E91, R_COM_MDM_STMT }, + { 0x1E9E, R_DET_TIME_ARG }, + { 0x1EB0, R_TEST_COM_TOKEN }, +// { 0x1AB2, R_KEY_FUN }, +// { 0x1AC3, R_KEY_ON_OFF_STMT }, +// { 0x1AFC, R_DET_DEVICE_ARG }, +// { 0x1B0F, R_ONTIME_STMT }, +// { 0x1B22, R_ONCOM_STMT }, + { 0x1EBE, R_RST7_5_ISR }, + { 0x1EF4, R_KICK_PWR_OFF_WDT }, +// { 0x1BB8, R_KEY_STMT }, +// { 0x1BBD, R_KEY_LIST_STMT }, + { 0x1EFB, R_SEND_CHARS_TO_LCD }, + { 0x1F11, R_KEY_STMT }, + { 0x1F5E, R_PSET_STMT }, + { 0x1F6D, R_PRESET_STMT }, +// { 0x1F74, R_LINE_STMT }, +// { 0x1CA6, R_DRAW_FBOX }, +// { 0x1CBC, R_DRAW_BOX }, + { 0x1F74, R_TOKENIZE_XY }, + { 0x1FD4, R_CSRLIN_FUN }, +// { 0x1D9B, R_MAX_FUN }, +// { 0x1DA7, R_MAXRAM_FUN }, +// { 0x1DB2, R_MAXFILES_FUN }, +// { 0x1DB9, R_HIMEM_FUN }, + { 0x1FDF, R_WIDTH_STMT }, + { 0x1FE1, R_CMD_STMT }, + { 0x1FE3, R_COLOR_STMT }, + { 0x1FE5, R_PRINT_STMT }, + { 0x1FE7, R_SOUND_STMT }, +// { 0x1DE5, R_SOUND_OFF_STMT }, +// { 0x1DE6, R_SOUND_ON_STMT }, + { 0x1FFD, R_MOTOR_STMT }, + { 0x2003, R_EXEC_STMT }, + { 0x201A, R_SCREEN_STMT }, + { 0x211D, R_FILES_STMT }, + { 0x2127, R_DISPLAY_CAT }, + { 0x217B, R_KILL_STMT }, + { 0x219B, R_KILL_TEXT_FILE }, + { 0x2220, R_NAME_STMT }, + { 0x22ED, R_NEW_STMT }, + { 0x233A, R_UPDATE_SYS_PTRS }, + { 0x23F6, R_STRLEN }, + { 0x2402, R_GET_FIND_DO_FILE }, + { 0x240B, R_OPEN_TEXT_FILE }, + { 0x2435, R_SAVE_TO_CATALOG }, + { 0x25D2, R_CSAVE_STMT }, + { 0x264D, R_BSAVE_STMT }, + { 0x26D2, R_PROC_SAVEM_ARGS }, + { 0x2703, R_BLOAD_STMT }, + { 0x27E4, R_CLOAD_ONERR }, + { 0x27D1, R_CAS_READ_REC }, + { 0x2872, R_GEN_VERIFY_FAIL_ERR }, + { 0x2881, R_CLOADM_STMT }, + { 0x28F8, R_LOAD_CO_HEADER }, +/* { 0x22CC, R_SAVEM_STMT }, + { 0x22DD, R_CSAVEM_STMT }, + { 0x2377, R_CLOAD_STMT }, + { 0x2413, R_CAS_READ_REC }, + { 0x2478, R_GEN_VERIFY_FAIL_ERR }, +*/ { 0x28FD, R_MOVE_B_BYTES }, + { 0x2906, R_EXEC_CO_FILE }, +/* { 0x260B, R_CAS_OPEN_OUT_BA }, + { 0x260E, R_CAS_OPEN_OUT_DO }, + { 0x2611, R_CAS_OPEN_OUT_CO }, + { 0x2650, R_CAS_OPEN_IN_BA }, + { 0x2653, R_CAS_OPEN_IN_DO }, + { 0x2656, R_CAS_OPEN_IN_CO }, +*/ + { 0x2A0C, R_CAS_OPEN_IN_BA }, + { 0x2AFB, R_STR_FUN }, + { 0x2B72, R_PRINT_STRING }, + { 0x2CC5, R_MEMCPY_CALL_ARGS }, + { 0x2CD0, R_MOVE_L_BYTES }, + { 0x2D04, R_LEN_FUN }, + { 0x2D10, R_ASC_FUN }, + { 0x2D20, R_CHR_FUN }, + { 0x2D2E, R_STRING_FUN }, + { 0x2D48, R_SPACE_FUN }, + { 0x2D6C, R_LEFT_FUN }, + { 0x2D9D, R_RIGHT_FUN }, + { 0x2DA7, R_MID_FUN }, + { 0x2DD3, R_VAL_FUN }, + { 0x2E03, R_INSTR_FUN }, + { 0x2E8E, R_FRE_FUN }, + { 0x34F1, R_DBL_SUB }, + { 0x34FA, R_DBL_ADD }, + { 0x2C4F, R_BCD_ADD }, + { 0x3639, R_DBL_MULT }, + { 0x3691, R_DBL_DIV }, + { 0x3EBD, R_COS_FUN }, + { 0x3EC3, R_SIN_FUN }, + { 0x3F5E, R_TAN_FUN }, + { 0x3F73, R_ATN_FUN }, + { 0x2FFC, R_LOG_FUN }, + { 0x3D4D, R_SQR_FUN }, + { 0x3DAD, R_EXP_FUN }, + { 0x3E4A, R_RND_FUN }, +/* { 0x3182, R_INIT_TEMP3 }, + { 0x31A0, R_DBL_SQR }, + { 0x31A3, R_MULT_M_FAC2 }, + { 0x31B5, R_FAC2_EQ_FAC1 }, + { 0x31B8, R_FAC2_EQ_FP }, + { 0x31C1, R_FAC1_EQ_FAC2 }, + { 0x31C4, R_FAC1_EQ_FP }, + { 0x31CA, R_M_EQ_FAC1 }, + { 0x31CA, R_MULT_FAC1_SQR_FAC1 }, + { 0x31CA, R_SWAP_FAC1_FAC2 }, + { 0x31EB, R_SQR_FAC1_MULT_TBL }, +*/ { 0x3E29, R_TBL_BASED_MATH }, +/* { 0x322E, R_PUSH_FAC2 }, + { 0x3234, R_PUSH_FAC1 }, + { 0x3245, R_POP_FAC2 }, + { 0x324B, R_POP_FAC1 }, + { 0x325C, R_FP_NUMBERS }, + { 0x327C, R_FP_SHARED_NUMBERS }, + { 0x327E, R_FP_NUMBERS }, +*/ { 0x3DFD, R_EXP_MATH_TBL }, + { 0x32F7, R_EXP_MATH_TBL }, + { 0x2FDA, R_LOG_MATH_TBL }, + { 0x2FEB, R_LOG_MATH_TBL }, + { 0x3F49, R_SIN_MATH_TBL }, + { 0x3F98, R_ATN_MATH_TBL }, + { 0x3173, R_RST_30H_FUN }, + { 0x3195, R_ABS_FUN }, + { 0x31A8, R_SGN_FUN }, + { 0x31C3, R_PUSH_SNGL_FAC1 }, + { 0x31D0, R_SNGL_FAC1_EQ_M }, + { 0x31D3, R_SNGL_FAC1_EQ_BCDE }, + { 0x31DE, R_SNGL_BCDE_EQ_FAC1 }, + { 0x31E1, R_SNGL_BCDE_EQ_M }, + { 0x31E1, R_SNGL_DECB_EQ_M }, + { 0x31EA, R_SNGL_M_EQ_FAC1 }, + { 0x31F2, R_LOAD_FAC2_FROM_M }, + { 0x31F7, R_MOVE_B_BYTES_INC }, +/* { 0x3472, R_MOVE_B_BYTES_DEC }, +*/ { 0x322E, R_SNGL_CMP_BCDE_FAC1 }, + { 0x3246, R_SNGL_CMP_BCDE_M }, + { 0x3259, R_SINT_CMP }, + { 0x3297, R_CMP_FAC1_FAC2 }, + { 0x329E, R_CINT_FUN }, + { 0x32BA, R_FAC1_EQ_SINT_HL }, + { 0x32D2, R_CSNG_FUN }, + { 0x32ED, R_CONV_SINT_SNGL }, + { 0x32F0, R_CONV_SINT_HL_SNGL }, + { 0x32FC, R_CDBL_FUN }, +/* { 0x35F8, R_SINT_SUB }, +*/ { 0x3345, R_FIX_FUN }, + { 0x3354, R_INT_FUN }, + { 0x3403, R_SINT_ADD }, + { 0x3423, R_SINT_MULT }, + { 0x347A, R_SINT_DIV }, + { 0x2EBB, R_SNGL_ADD_BCDE }, +/* { 0x37F7, R_SNGL_ADD_FAC2 }, +*/ { 0x2EC1, R_SNGL_SUB }, +/* { 0x3803, R_SNGL_MULT_BCDE }, + { 0x3806, R_SNGL_MULT_FAC2 }, + { 0x380E, R_SNGL_DIV }, + { 0x3827, R_SNGL_LOAD }, +*/ { 0x371F, R_ASCII_TO_DBL }, + { 0x374E, R_ASCII_FND_e }, + { 0x3776, R_ASCII_FND_E }, + { 0x37C1, R_ASCII_FND_DOT }, + { 0x37CC, R_ASCII_FND_PERC }, + { 0x37D7, R_ASCII_FND_LB }, + { 0x37DF, R_ASCII_CONV_HELPER }, + { 0x380D, R_ASCII_CONV_HELPER2 }, + { 0x3890, R_PRNT_BASIC_ERR_TERM }, + { 0x3898, R_PRINT_HL_ON_LCD }, + { 0x38A7, R_PRINT_FAC1 }, + { 0x38AB, R_PRINT_FAC1_FORMAT }, +/* { 0x3D11, R_FAC1_EQ_ZERO }, + { 0x3D7F, R_SNGL_EXP }, + { 0x3D8E, R_DBL_EXP }, + { 0x3DF7, R_INT_EXP }, + { 0x3F28, R_INIT_BASIC_VARS }, +*/ { 0x406A, R_TIME_ON_STMT }, + { 0x4073, R_TIME_OFF_STMT }, + { 0x4078, R_TIME_STOP_STMT }, +/* { 0x3FD2, R_TRIG_INTR }, + { 0x3FF1, R_CLEAR_INTR }, +*/ { 0x408D, R_CLEAR_COM_INT_DEF }, + { 0x40CF, R_RESTORE_STMT }, + { 0x40EA, R_STOP_STMT }, + { 0x40EF, R_END_STMT }, + { 0x412A, R_CONT_STMT }, + { 0x4141, R_ISALPHA_M }, + { 0x4142, R_ISALPHA_A }, + { 0x4149, R_CLEAR_STMT }, + { 0x41CA, R_NEXT_STMT }, + { 0x4251, R_SEND_CRLF }, + { 0x4254, R_SEND_LF }, + { 0x4258, R_BEEP_STMT }, + { 0x425C, R_HOME_CURSOR }, + { 0x4260, R_CLS_STMT }, + { 0x4264, R_PROTECT_LABEL }, + { 0x4269, R_UNPROT_LABEL }, + { 0x426E, R_STOP_AUTO_SCROLL }, + { 0x4273, R_RESUME_AUTO_SCROLL }, + { 0x4278, R_TURN_CURSOR_ON }, + { 0x427D, R_TURN_CURSOR_OFF }, + { 0x4282, R_DEL_CUR_LINE }, + { 0x4287, R_INSERT_LINE }, + { 0x428C, R_ERASE_TO_EOL }, + { 0x4291, R_SEND_ESC_X }, + { 0x42A2, R_INV_CHAR_ENABLE }, + { 0x42A7, R_INV_CHAR_DISABLE }, + { 0x42A9, R_END_ESC_SEQ }, + { 0x42B0, R_CURSOR_TO_LOW_LEFT }, + { 0x42B5, R_SET_CURSOR_POS }, + { 0x42C3, R_ERASE_FKEY_DISP }, + { 0x42E1, R_SET_DISP_FKEY }, + { 0x42E4, R_DISP_FKEY_LINE }, + { 0x4363, R_PRINT_A_TO_LCD }, +// { 0x44AA, R_CHAR_PLOT_3 }, + { 0x4380, R_CHAR_PLOT_4 }, + { 0x4395, R_CHAR_PLOT_5 }, + { 0x43D2, R_LCD_OUT_DRIVER }, + { 0x43EF, R_RST_20H_LKUP_TBL }, + { 0x4420, R_ESC_Y }, +// { 0x4429, R_LCD_OUT_ESC_FUN }, + { 0x4429, R_LCD_ESC_LKUP_TBL }, + { 0x4471, R_ESC_SEQ_DRIVER }, + { 0x44AA, R_ESC_p_FUN }, + { 0x44AB, R_ESC_q_FUN }, + { 0x44B0, R_ESC_U_FUN }, + { 0x44B2, R_ESC_T_FUN }, + { 0x44B3, R_ESC_X_FUN }, + { 0x44BE, R_ESC_V_FUN }, + { 0x44BF, R_ESC_W_FUN }, + { 0x44D2, R_ESC_C_FUN }, + { 0x44DB, R_ESC_D_FUN }, + { 0x44E0, R_BKSPACE_FUN }, + { 0x44E8, R_ESC_A_FUN }, + { 0x44ED, R_ESC_B_FUN }, + { 0x4505, R_TAB_FUN }, +/* { 0x4494, R_LF_FUN }, +*/ { 0x451B, R_ESC_H_FUN }, + { 0x451D, R_CR_FUN }, +/* { 0x44AF, R_ESC_P_FUN }, + { 0x44BA, R_ESC_Q_FUN }, +*/ { 0x4530, R_ESC_M_FUN }, + { 0x4550, R_LCD_SCROLL }, + { 0x44EA, R_ESC_L_FUN }, + { 0x4568, R_GET_LCD_CHAR }, + { 0x45B9, R_ESC_l_FUN }, + { 0x45BB, R_ESC_K_FUN }, + { 0x45CC, R_CLS_FUN }, + { 0x45D2, R_ESC_J_FUN }, + { 0x45E4, R_CHAR_PLOT_6 }, + { 0x47A4, R_INP_DISP_LINE }, + { 0x4798, R_INP_DISP_LINE_NO_Q }, + { 0x485D, R_INP_CTRL_C_HANDLER }, + { 0x4814, R_INP_ENTER_HANDLER }, + { 0x4909, R_INP_BKSP_HANDLER }, + { 0x4952, R_INP_CTRL_U_HANDLER }, +/* { 0x46CA, R_INP_TAB_HANDLER }, +*/ { 0x49AA, R_DIM_STMT }, + { 0x4BA0, R_FIND_VAR_ADDR }, + { 0x4BA1, R_USING_FUN }, + { 0x4CFA, R_SEND_A_LCD_LPT }, + { 0x4D0B, R_PRINT_A_EXPAND }, + { 0x4D3B, R_SET_OUT_DEV_LCD }, + { 0x4D54, R_LCD_CHAR_OUT_FUN }, + { 0x4D61, R_LCD_NEW_LINE }, + { 0x4D93, R_INKEY_FUN }, + { 0x4E30, R_GET_FILE_DESC }, + { 0x4E77, R_OPEN_STMT }, + { 0x4F05, R_LCD_CLOSE_FUN }, + { 0x4F1A, R_RUN_STMT }, + { 0x4F1C, R_LOAD_STMT }, + { 0x4F1D, R_MERGE_STMT }, + { 0x4F74, R_SAVE_STMT }, + { 0x4FC5, R_CLOSE_STMT }, + { 0x5029, R_INPUT_STMT }, + { 0x50A0, R_CLEAR_MEM }, + { 0x50A1, R_LOAD_MEM }, + { 0x50C4, R_PRINT_LB_INIT_FUN }, + { 0x50F1, R_LINE_INPUT_STMT }, + { 0x51E4, R_GEN_NM_ERR_FUN }, + { 0x51E7, R_GEN_AO_ERR_FUN }, + { 0x51EA, R_GEN_DS_ERR_FUN }, + { 0x51ED, R_GEN_FF_ERR_FUN }, + { 0x51F0, R_GEN_CF_ERR_FUN }, + { 0x51F3, R_GEN_BN_ERR_FUN }, + { 0x51F6, R_GEN_IE_ERR_FUN }, + { 0x51F9, R_GEN_EF_ERR_FUN }, + { 0x51FC, R_GEN_FL_ERR_FUN }, + { 0x5201, R_LOF_FUN }, + { 0x5203, R_LOC_FUN }, + { 0x5205, R_LFILES_FUN }, + { 0x5207, R_DSKO_FUN }, + { 0x5209, R_DSKI_FUN }, + { 0x520B, R_DSKF_FUN }, + { 0x520F, R_FORMAT_FUN }, + { 0x528D, R_DEV_NAME_TBL }, + { 0x52AB, R_DCB_VCTR_TBL }, + { 0x52DC, R_TELCOM_ENTRY }, + { 0x52F5, R_TELCOM_RE_ENTRY }, +// { 0x5321, R_TELCOM_INST_VCTR_TBL }, + { 0x534D, R_TELCOM_STAT_FUN }, + { 0x5353, R_PRINT_TELCOM_STAT }, + { 0x5371, R_TELCOM_LABEL_TXT }, +/* { 0x51ED, R_SET_TELCOM_STAT }, + { 0x522F, R_TELCOM_CALL_FUN }, + { 0x524D, R_TELCOM_FIND_FUN }, + { 0x52B4, R_GO_OFFHOOK }, + { 0x52BB, R_DISCONNECT_PHONE }, + { 0x52D0, R_CONNECT_PHONE }, + { 0x52E4, R_GO_OFFHOOK_WAIT }, + { 0x5310, R_TELCOM_PAUSE }, + { 0x532D, R_EXEC_LOGON_SEQ }, + { 0x5359, R_DIALING_FUN }, + { 0x539E, R_AUTO_LOGIN_SEQ }, + { 0x540A, R_DIAL_DIGIT }, +*/ { 0x5388, R_TELCOM_TERM_FUN }, + { 0x5434, R_TELCOM_DISPATCH }, + { 0x5445, R_TERM_FKEY_VCTR_TBL }, + { 0x5459, R_TELCOM_PREV_FUN }, + { 0x5474, R_TELCOM_FULL_FUN }, + { 0x5486, R_TELCOM_ECHO_FUN }, + { 0x54C5, R_TELCOM_UP_FUN }, + { 0x5550, R_TELCOM_DOWN_FUN }, + { 0x55F0, R_TELCOM_BYE_FUN }, + { 0x563F, R_PRINT_STRING }, + { 0x5645, R_MENU_ENTRY }, +/* { 0x57F8, R_DISP_DIR }, + { 0x5837, R_MENU_CTRL_U_HANDLER }, + { 0x585A, R_MENU_CMD_LOOP }, + { 0x588E, R_MENU_BKSP_HANDLER }, +*/ { 0x5822, R_MENU_ENTER_HANDLER }, + { 0x5888, R_EXEC_ROM_FILE }, + { 0x5D08, R_DISP_DIR_TYPE_C }, + { 0x5D3F, R_CONV_FILENAME }, + { 0x5D67, R_NEXT_DIR_ENTRY }, + { 0x5D83, R_CLS_PRINT_TIME_DAY }, + { 0x5D86, R_PRINT_TIME_DAY }, + { 0x5DA2, R_PRINT_STRING2 }, + { 0x5DAC, R_COPY_MEM_DE_M }, + { 0x5DCD, R_CMP_MEM_DE_M }, +// { 0x5A79, R_CLEAR_FKEY_TBL }, + { 0x5DDC, R_SET_FKEYS }, + { 0x5DFB, R_DISP_FKEYS }, + { 0x5E5B, R_GET_FILE_ADDR }, + { 0x5E61, R_DIR_DISP_ORDER_TBL }, + { 0x5F48, R_FIND_TEXT_IN_FILE }, + { 0x5F76, R_CHECK_FOR_CRLF }, + { 0x5FA0, R_GET_KEY_CONV_TOUPPER }, + { 0x5FA6, R_PRINT_TIME_LOOP }, + { 0x5FC4, R_TEXT_ENTRY }, + { 0x5FF8, R_TEXT_FKEY_TBL }, + { 0x6030, R_EDIT_STMT }, + { 0x612A, R_EDIT_DO_FILE_FUN }, + { 0x61B6, R_TEXT_EDIT_LOOP }, + { 0x61EF, R_TEXT_CTRL_VCTR_TBL }, + { 0x622F, R_TEXT_ESC_FUN }, + { 0x6258, R_TEXT_CTRL_I_FUN }, + { 0x628C, R_TEXT_CTRL_M_FUN }, + { 0x62AC, R_TEXT_CTRL_D_FUN }, + { 0x62B0, R_TEXT_CTRL_X_FUN }, + { 0x62D9, R_TEXT_CTRL_H_FUN }, + { 0x631F, R_TEXT_CTRL_S_FUN }, + { 0x6323, R_TEXT_CTRL_E_FUN }, + { 0x6348, R_TEXT_CTRL_F_FUN }, + { 0x635A, R_TEXT_CTRL_A_FUN }, + { 0x6390, R_TEXT_CTRL_T_FUN }, + { 0x63A5, R_TEXT_CTRL_B_FUN }, + { 0x63CB, R_TEXT_CTRL_R_FUN }, + { 0x63D9, R_TEXT_CTRL_Q_FUN }, + { 0x63DE, R_TEXT_CTRL_W_FUN }, + { 0x63EA, R_TEXT_CTRL_Z_FUN }, + { 0x6410, R_TEXT_CTRL_L_FUN }, + { 0x645D, R_TEXT_CTRL_C_FUN }, + { 0x65BF, R_TEXT_GET_NEXT_BYTE }, + { 0x6606, R_TEXT_CTRL_O_FUN }, + { 0x661A, R_TEXT_CTRL_U_FUN }, + { 0x6736, R_TEXT_CTRL_N_FUN }, + { 0x67A8, R_COPY_NULL_STRING }, + { 0x6BFE, R_INSERT_A_INTO_FILE }, + { 0x6C0A, R_INSERT_SPACES }, + { 0x6C3C, R_DELETE_CHARS }, + { 0x6C78, R_MOVE_BC_BYTES_INC }, + { 0x6C83, R_MOVE_BC_BYTES_DEC }, + { 0x6C8E, R_ROM_CAT_ENTRIES }, + { 0x6CD0, R_BASIC_ENTRY }, + { 0x6CF7, R_LOAD_BASIC_FKEYS }, + { 0x6D00, R_LOAD_BASIC_FKEYS }, + { 0x6D3A, R_RE_INIT_SYSTEM }, + { 0x6D44, R_WARM_RESET }, + { 0x6D92, R_SEND_A_TO_LPT }, + { 0x6DC2, R_CHECK_RS232_QUEUE }, + { 0x6DD3, R_READ_RS232_QUEUE }, + { 0x6E00, R_RST_6_5_FUN }, + { 0x6E84, R_INC_RS232_QUEUE_IN }, + { 0x6E97, R_SEND_XON }, + { 0x6EAA, R_DISABLE_XON_XOFF }, + { 0x6EBE, R_SEND_A_USING_XON }, + { 0x6EDC, R_SEND_C_TO_RS232 }, + { 0x6EF9, R_XON_XOFF_HANDLER }, + { 0x6F21, R_SET_RS232_BAUD_RATE }, + { 0x6F40, R_RS232_BAUD_TIMER_VALS }, + { 0x6F52, R_INIT_RS232_MDM }, + { 0x6FA8, R_UNINIT_RS232_MDM }, +// { 0x6EE5, R_CLICK_SND_PORT }, +// { 0x6EEF, R_CHECK_CD }, + { 0x6F8D, R_ENABLE_XON_XOFF }, + { 0x6F95, R_INIT_SER_BUF_PARAMS }, + { 0x6FD9, R_CAS_MOTOR_ON }, + { 0x7047, R_CAS_WRITE_HEADER }, + { 0x6FEB, R_CAS_WRITE_NO_CHKSUM }, + { 0x6FF8, R_CAS_WRITE_BIT }, + { 0x7059, R_CAS_READ_HEADER }, + { 0x70AF, R_CAS_READ_BIT }, +// { 0x7023, R_CAS_COUNT_BITS }, + { 0x708E, R_CAS_READ_NO_CHKSUM }, + { 0x70CD, R_KEYSCAN_MGT_FUN }, + { 0x70D8, R_KEY_DETECTION }, + { 0x713C, R_KEY_REPEAT_DET }, + { 0x7195, R_KEY_DECODE }, + { 0x7230, R_KEY_FIRST_IN_BUF }, + { 0x7253, R_KEY_ADD_TO_BUF }, + { 0x7266, R_ISR_EXIT_FUN }, +/* { 0x720A, R_UNSHIFTED_KEY }, + { 0x7222, R_ARROW_KEY }, + { 0x722C, R_CAPS_LOCK_KEY }, + { 0x7233, R_NUM_KEY }, +*/ { 0x7279, R_SCAN_KEYBOARD }, + { 0x72A0, R_ENABLE_INTERRUPTS }, + { 0x72A6, R_CHK_PENDING_KEYS }, + { 0x72B9, R_CHK_BREAK }, + { 0x72DF, R_CHK_SHIFT_BREAK }, +// { 0x72B1, R_SCAN_SPECIAL_KEYS }, + { 0x730D, R_GEN_TONE }, + { 0x7359, R_GET_CLK_CHIP_REGS }, + { 0x735A, R_PUT_CLK_CHIP_REGS }, + { 0x7382, R_READ_CLK_CHIP_BIT }, + { 0x73B3, R_SET_CLK_CHIP_MODE }, + { 0x7409, R_BLINK_CURSOR }, + { 0x744D, R_CHAR_PLOT_7 }, + { 0x74D0, R_PLOT_POINT }, + { 0x74D1, R_CLEAR_POINT }, + { 0x7526, R_LCD_BYTE_PLOT }, + { 0x75BC, R_ENABLE_LCD_DRIVER }, + { 0x75D1, R_WAIT_LCD_DRIVER }, + { 0x75DA, R_LCD_BIT_PATTERNS }, + { 0x76CC, R_LCD_BIT_PATTERNS }, + { 0x76E0, R_DELAY_FUN }, + { 0x76E5, R_SET_INTR_1DH }, + { 0x76EB, R_BEEP_FUN }, + { 0x76FF, R_CLICK_SOUND_PORT }, +// { 0x7682, R_CHK_XTRNL_CNTRLER }, +// { 0x768F, R_XTRNL_CNTRLER_DRIVER }, + { 0x78B7, R_LCD_CHAR_SHAPE_TBL1 }, + { 0x7A97, R_LCD_CHAR_SHAPE_TBL2 }, +/* { 0x7BF1, R_KEYBOARD_CONV_MATRIX }, +*/ { 0x7C94, R_BOOT_ROUTINE }, + { 0x7D83, R_COLD_BOOT }, + { 0x7E3E, R_DISP_MODEL }, + { 0x7E52, R_DISP_FREE_BYTES }, + { 0x7E66, R_INIT_RST_38H_TBL }, + { 0x7E81, R_CALC_FREE_RAM }, + { 0x7EA1, R_INIT_CLK_CHIP_REGS }, + { 0x7F98, R_MENU_TEXT_STRINGS }, + { 0x7FBE, R_RST_38H_DRIVER }, +/* { 0xF5F9, R_RST_5_5_VECTOR }, + { 0xF5FC, R_RST_6_5_VECTOR }, + { 0xF5FF, R_RST_7_5_VECTOR }, + { 0xF602, R_TRAP_VECTOR }, + { 0xF605, R_DETECT_OPTION_ROM }, +*/ { -1, -1 } +}; + +RomDescription_t gN8300_Desc = { + 0x31303238, /* Signature */ + 0x7F9C, /* Signature address */ + 1, /* StdRom */ + + gN8300_Tables, /* Known tables */ + gN8300_Vars, /* Known variables */ + gN8300_Funs, /* Known functions */ + + 0xF979, /* Address of unsaved BASIC prgm */ + 0xF87C, /* Address of next DO file */ + 0xFAE1, /* Start of DO file area */ + 0xFAE3, /* Start of CO file area */ + 0xFAE5, /* Start of Variable space */ + 0xFAE7, /* Start of Array data */ + 0xFAE9, /* Pointer to unused memory */ + 0xF384, /* Address where HIMEM is stored */ + 0xF462, /* End of RAM for file storage */ + 0xF9B0, /* Lowest RAM used by system */ + 0xF84F, /* Start of RAM directory */ + 0xF459, /* BASIC string buffer pointer */ + 0xF9CA, /* BASIC Size */ + 0xFE58, /* Keyscan array */ + 0x78B7, /* Character generator array */ + 0xF83C, /* Location of Year storage */ + 0xFD00, /* LCD Buffer storage area */ + 0xF3E9, /* Label line enable flag (not defined) */ + + 24, /* Number of directory entries */ + 8, /* Index of first Dir entry */ + 0x7FAE /* Address of MS Copyright string */ +}; + diff --git a/src/remote.cpp b/src/remote.cpp index 3723f28..de7d41e 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -56,13 +56,13 @@ using namespace std; #include "socket.h" #include "serversocket.h" #include "socketexception.h" -#include "cpu.h" #include "memory.h" #include "io.h" #include "roms.h" #include "romstrings.h" #include "disassemble.h" #include "file.h" +#include "cpu.h" #ifdef WIN32 HANDLE gRemoteThread; // The remote control thread diff --git a/src/roms.h b/src/roms.h index 75d8114..a88d23e 100644 --- a/src/roms.h +++ b/src/roms.h @@ -48,10 +48,13 @@ typedef struct Std_ROM_Table { /* Define structure for storing addresses and descriptions for */ /* known subroutine calls and variable locations within the ROM */ typedef struct Std_ROM_Strings { + const char* pLabel; int addr; char* desc; } Std_ROM_Strings_t; +#define MTRM(x) #x, x + /* Define a structure to contain all information regarding a ROM */ typedef struct RomDescription { unsigned long dwSignature; /* Unique 32bit value in ROM */ diff --git a/src/romstrings.c b/src/romstrings.c index 2ad4b69..dab07b3 100644 --- a/src/romstrings.c +++ b/src/romstrings.c @@ -5,25 +5,25 @@ /* * Copyright 2004 Stephen Hurd and Ken Pettit * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions + * Redistribution and use in source and binary forms), with or without + * modification), are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice), this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the + * notice), this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * ANY EXPRESS OR IMPLIED WARRANTIES), INCLUDING), BUT NOT LIMITED TO), THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * FOR ANY DIRECT), INDIRECT), INCIDENTAL), SPECIAL), EXEMPLARY), OR CONSEQUENTIAL + * DAMAGES (INCLUDING), BUT NOT LIMITED TO), PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE), DATA), OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY), WHETHER IN CONTRACT), STRICT + * LIABILITY), OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE), EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ @@ -31,846 +31,860 @@ #include "romstrings.h" Std_ROM_Strings_t gDisStrings[] = { - { R_FUN_VCTR_TBL, "Function vector table for SGN to MID$" }, - { R_BASIC_TBL, "BASIC statement keyword table END to NEW" }, - { R_FUN_TBL_TAB, "Function keyword table TAB to <" }, - { R_FUN_TBL_SGN, "Function keyword table SGN to MID$" }, - { R_BASIC_VCTR_TBL, "BASIC statement vector table for END to NEW" }, - { R_MATH_VCTR_TBL, "Vector table for math operations" }, - { R_BASIC_ERR_TXT, "BASIC error message text" }, - { R_INIT_IMAGE, "Initialization image loaded to F5F0H" }, - { R_XROM_DET_IMAGE, "External ROM detect image loaded at F605H" }, - { R_BASIC_STRINGS, "BASIC message strings" }, - { R_CAS_FREQ_CNT, "Cassette frequency cycle count" }, - { R_TERM_FKEY_VCTR_TBL, "TERM Mode function key vector table" }, - { R_DIR_DISP_ORDER_TBL, "Directory file-type display order table" }, - { R_TEXT_FKEY_VCTR_TBL, "TEXT Function key table - empty" }, - { R_ROM_CAT_ENTRIES, "ROM programs catalog entries" }, - { R_INT_EXIT_FUN, "Interrupt exit routine (pop all regs & RET)" }, - { R_8155_PIO_PAT1, "8155 PIO chip bit patterns for Upper LCD drivers" }, - { R_8155_PIO_PAT2, "8155 PIO chip bit patterns for Lower LCD drivers" }, - { R_INIT_CLK_VALUES, "Initial clock chip register values" }, - { R_MENU_STRINGS, "MENU Text Strings" }, - { R_MODEL_NUM_STRING, "TRS-80 model number string" }, - { R_ACTIVE_SIGNATURE, "Active system signature -- Warm vs Cold boot" }, - { R_HIMEM, "HIMEM" }, - { R_RST_5_5_VCTR, "RST 5.5 RAM Vector" }, - { R_RST_6_5_VCTR, "RST 6.5 RAM Vector" }, - { R_RST_7_5_VCTR, "RST 7.5 RAM Vector" }, - { R_TRAP_VCTR, "RAM vector for TRAP interrupt" }, - { R_OPTION_ROM_FLAG, "Option ROM flag" }, - { R_DIAL_SPEED, "Dial speed (1=10pps, 2=20pps" }, - { R_FKEY_STAT_TBL, "Function key status table (1 = on)" }, - { R_NEW_CONSOLE_FLAG, "New Console device flag" }, - { R_CURSOR_ROW, "Cursor row (1-8)" }, - { R_CURSOR_COL, "Cursor column (1-40)" }, - { R_ACTIVE_ROW_CNT, "Active rows count (1-8)" }, - { R_ACTIVE_COL_CNT, "Active columns count (1-40)" }, - { R_LABEL_LINE_PROT, "Label line protect status" }, - { R_SCROLL_DISABLE, "Scroll disable flag" }, - { R_CURSOR_STAT, "Cursor status (0 = off)" }, - { R_CURSOR_ROW2, "Cursor row (1-8)" }, - { R_CURSOR_COL2, "Cursor column (1-40)" }, - { R_ESC_MODE_FLAG, "ESC mode flag for RST 20H" }, - { R_REV_VID_SWITCH, "Reverse video switch" }, - { R_LAST_PLOT_X, "X coord of last point plotted" }, - { R_LAST_PLOT_Y, "Y coord of last point plotted" }, - { R_PWR_OFF_STAT, "Power off exit condition switch" }, - { R_DUPLEX_SWITCH, "Full/Half duplex switch" }, - { R_RS232_LF_SWITCH, "RS232 auto linefeed switch" }, - { R_RS232_PARAM_TBL, "RS232 parameter setting table" }, - { R_ADDRESS_LAST_CALLED, "Address last called" }, - { R_OUT_STMT_HOOK, "OUT statement hook" }, - { R_INP_STMT_HOOK, "INP function hook" }, - { R_LAST_ERROR_CODE, "Last Error code" }, - { R_LPT_HEAD_POS, "Line printer head position" }, - { R_OUTPUT_DEVICE, "Output device for RST 20H (0=screen)" }, - { R_BASIC_STR_BUF_PTR, "BASIC string buffer pointer" }, - { R_CUR_BASIC_LINE_NUM, "Current executing line number" }, - { R_START_BASIC_PGM_PTR, "Start of BASIC program pointer" }, - { R_END_OF_STMT_MARKER, "End of statement marker" }, - { R_KEYBOARD_BUF, "Keyboard buffer" }, - { R_CURSOR_H_POS, "Horiz. position of cursor (0-39)" }, - { R_FKEY_DEF_BUF, "Function key definition area" }, - { R_BASIC_FKEY_DEF_BUF, "Function key definition area (BASIC)" }, - { R_FILE_RAM_END, "End of RAM for file storage" }, - { R_SEC_ONES, "Seconds (ones)" }, - { R_SEC_TENS, "Seconds (tens)" }, - { R_MIN_ONES, "Minutes (ones)" }, - { R_MIN_TENS, "Minutes (tens)" }, - { R_HR_ONES, "Hours (ones)" }, - { R_HR_TENS, "Hours (tens)" }, - { R_DATE_ONES, "Date (ones)" }, - { R_DATE_TENS, "Date (tens)" }, - { R_DAY_CODE, "Day code (0=Sun, 1=Mon, etc.)" }, - { R_MONTH, "Month (1-12)" }, - { R_YEAR_ONES, "Year (ones)" }, - { R_YEAR_TENS, "Year (tens)" }, - { R_SEC_ONES2, "Seconds (ones)" }, - { R_SEC_TENS2, "Seconds (tens)" }, - { R_MIN_ONES2, "Minutes (ones)" }, - { R_MIN_TENS2, "Minutes (tens)" }, - { R_HR_ONES2, "Hours (ones)" }, - { R_HR_TENS2, "Hours (tens)" }, - { R_DATE_ONES2, "Date (ones)" }, - { R_DATE_TENS2, "Date (tens)" }, - { R_DAY_CODE2, "Day code (0=Sun, 1=Mon, etc.)" }, - { R_ONTIME_TIME, "Time for ON TIME interrupt (SSHHMM)" }, - { R_ONCOM_FLAG, "On Com flag" }, - { R_ONCOM_ADDRESS, "On Com routine address" }, - { R_ONTIME_FLAG, "On Time flag" }, - { R_ONTIME_ADDRESS, "On Time routine address" }, - { R_FKEY_VCTR_TBL, "Function key vector table" }, - { R_DIR_RAM_START, "Start of RAM directory" }, - { R_UNSAVED_BASIC_PTR, "BASIC program not saved pointer" }, - { R_PASTE_RAM_START, "Start of Paste Buffer" }, - { R_LAST_CHAR_PRINTED, "Last char sent to printer" }, - { R_LABEL_ENABLE_FLAG, "Label line enable flag" }, - { R_PORT_A8H, "Contents of port A8H" }, - { R_IPL_FILENAME_START, "Start of IPL filename" }, - { R_BASIC_LIST_START, "Address where last BASIC list started" }, - { R_SP_SAVE_BUF, "SP save area for power up/down" }, - { R_LOWEST_RAM, "Lowest RAM address used by system" }, - { R_RST_38H_OFFSET, "Offset of last RST 38H call" }, - { R_LAST_PGRM_LEN, "Length of last program loaded/saved to tape" }, - { R_RST_38H_VCTR_TBL, "Start of RST 38H vector table" }, - { R_LCD_OUTPUT_HOOK, "LCD character output hook" }, - { R_LPT_OUTPUT_HOOK, "Printer character output hook" }, - { R_EOF_FUN_HOOK, "EOF function hook" }, - { R_TERM_F6_HOOK, "Term F6 hook" }, - { R_TERM_F7_HOOK, "Term F7 hook" }, - { R_WIDTH_STMT_HOOK, "WIDTH statement hook" }, - { R_CRT_OPEN_HOOK, "CRT open routine hook" }, - { R_CRT_OUTPUT_HOOK, "CRT output file routine hook" }, - { R_WAND_OPEN_HOOK, "WAND Open routine hook" }, - { R_WAND_CLOSE_HOOK, "WAND Close routine hook" }, - { R_WAND_GET_HOOK, "WAND Get routine hook" }, - { R_WAND_IO_HOOK, "WAND Special I/O routine hook" }, - { R_LOF_HOOK, "LOF function hook" }, - { R_LOC_HOOK, "LOC function hook" }, - { R_LFILES_HOOK, "LFILES statement hook" }, - { R_DSKI_HOOK, "DSKI$ routine hook" }, - { R_DSKO_HOOK, "DSKO$ routine hook" }, - { R_VAR_CREATE_LOC_FLAG, "Variable Create/Locate switch" }, - { R_LAST_VAR_TYPE, "Type of last variable used" }, - { R_FILE_BUF_PTR, "File buffer area pointer" }, - { R_DATA_STMT_LINE_NUM, "Line number of current data statement" }, - { R_FOR_NEXT_ACTIVE_FLAG, "FOR/NEXT loop active flag" }, - { R_LAST_VAR_ASSIGNED_ADDR, "Address of last variable assigned" }, - { R_RUNNING_LINE_NUM_ADDR, "Most recent or currenly running line pointer" }, - { R_BASIC_SP_BUF, "SP used by BASIC to reinitialize the stack" }, - { R_LAST_ERR_LINE_NUM, "Line number of last error" }, - { R_LAST_ENTERED_LINE_NUM, "Most recent used or entered line number" }, - { R_ERR_PTR, "Pointer to occurance of error" }, - { R_ONERROR_ADDRESS, "Address of ON ERROR routine" }, - { R_BREAK_LINE_NUM, "Line where break, END, or STOP occurred" }, - { R_BREAK_ADDRESS, "Address where program stopped on last break, END, or STOP" }, - { R_DO_FILES_PTR, "Start of DO files pointer" }, - { R_CO_FILES_PTR, "Start of CO files pointer" }, - { R_VAR_PTR, "Start of variable data pointer" }, - { R_ARRAY_TBL_PTR, "Start of array table pointer" }, - { R_UNUSED_MEM_PTR, "Unused memory pointer" }, - { R_DATA_SEARCH_ADDR, "Address where DATA search will begin next" }, - { R_DEF_TBL, "DEF definition table" }, - { R_FP_TEMP1, "Floating Point Temp 1" }, - { R_FP_TEMP2, "Floating Point Temp 2" }, - { R_FP_TEMP3, "Floating Point Temp 3" }, - { R_FP_FAC1, "Start of FAC1 for single and double precision" }, - { R_INT_FAC1, "Start of FAC1 for integers" }, - { R_FP_FAC2, "Start of FAC2 for single and double precision" }, - { R_INT_FAC2, "Start of FAC2 for integers" }, - { R_MAXFILES, "Maxfiles" }, - { R_FILE_NUM_TBL_PTR, "File number description table pointer" }, - { R_BASIC_FILENAME, "Filename of current BASIC program" }, - { R_LAST_LOAD_FILENAME, "Filename of last program loaded from tape" }, - { R_ALT_LCD_CHAR_BUF, "Start of Alt LCD character buffer" }, - { R_MENU_TO_RAM_MAP, "Map of MENU entry positions to RAM directory positions" }, - { R_MENU_OR_CMD_FLAG, "Flag to indicate MENU entry location or command entry" }, - { R_CUR_MENU_DIR_LOC, "Current MENU directory location" }, - { R_MAX_MENU_DIR_LOC, "Maximum MENU directory location" }, - { R_LCD_CHAR_BUF, "Start of LCD character buffer" }, - { R_XON_XOFF_CTRL, "XON/XOFF protocol control" }, - { R_XON_XOFF_ENABLE, "XON/XOFF enable flag" }, - { R_RS232_INIT_STAT, "RS232 initialization status" }, - { R_SOUND_FLAG, "Sound flag" }, - { R_PORT_E8H, "Contents of port E8H" }, - { R_RS232_CHAR_BUF, "RS232 Character buffer" }, - { R_RS232_BUF_CNT, "RS232 buffer count" }, - { R_RS232_BUF_OUT, "RS232 buffer output position" }, - { R_RS232_BUF_IN, "RS232 buffer input pointer" }, - { R_CTRL_S_STAT, "Control-S status" }, - { R_UART_BAUD_TIMER_VAL, "UART baud rate timer value" }, - { R_RS232_PARITY_CTRL, "RS232 Parity Control byte" }, - { R_CAS_PULSE_CTRL, "Cassette port pulse control" }, - { R_SPEC_KEY_STAT, "Special key status storage" }, - { R_FKEY_STAT, "Function key status storage" }, - { R_KEY_SCAN_STORAGE1, "Keyboard scan column storage #1" }, - { R_KEY_SCAN_STORAGE2, "Keyboard scan column storage @2" }, - { R_SHIFT_KEY_STAT, "Shift key status storage" }, - { R_KEY_REPT_START, "Key repeat start delay counter" }, - { R_KEY_POSITION, "Key position storage" }, - { R_2ND_KEY_BUF_PTR, "Pointer to entry in 2nd Storage Buffer for key" }, - { R_KEY_BUF_CNT, "Keyboard buffer count" }, - { R_KEY_TYPEAHEAD_BUF, "Keyboard typeahead buffer" }, - { R_CURSOR_BIT_PAT_BUF, "Cursor bit pattern storage" }, + { MTRM(R_FUN_VCTR_TBL), "Function vector table for SGN to MID$" }, + { MTRM(R_BASIC_TBL), "BASIC statement keyword table END to NEW" }, + { MTRM(R_FUN_TBL_TAB), "Function keyword table TAB to <" }, + { MTRM(R_FUN_TBL_SGN), "Function keyword table SGN to MID$" }, + { MTRM(R_BASIC_VCTR_TBL), "BASIC statement vector table for END to NEW" }, + { MTRM(R_MATH_VCTR_TBL), "Vector table for math operations" }, + { MTRM(R_BASIC_ERR_TXT), "BASIC error message text" }, + { MTRM(R_INIT_IMAGE), "Initialization image loaded to F5F0H" }, + { MTRM(R_XROM_DET_IMAGE), "External ROM detect image loaded at F605H" }, + { MTRM(R_BASIC_STRINGS), "BASIC message strings" }, + { MTRM(R_CAS_FREQ_CNT), "Cassette frequency cycle count" }, + { MTRM(R_TERM_FKEY_VCTR_TBL), "TERM Mode function key vector table" }, + { MTRM(R_DIR_DISP_ORDER_TBL), "Directory file-type display order table" }, + { MTRM(R_TEXT_FKEY_VCTR_TBL), "TEXT Function key table - empty" }, + { MTRM(R_ROM_CAT_ENTRIES), "ROM programs catalog entries" }, + { MTRM(R_INT_EXIT_FUN), "Interrupt exit routine (pop all regs & RET)" }, + { MTRM(R_8155_PIO_PAT1), "8155 PIO chip bit patterns for Upper LCD drivers" }, + { MTRM(R_8155_PIO_PAT2), "8155 PIO chip bit patterns for Lower LCD drivers" }, + { MTRM(R_INIT_CLK_VALUES), "Initial clock chip register values" }, + { MTRM(R_MENU_STRINGS), "MENU Text Strings" }, + { MTRM(R_MODEL_NUM_STRING), "TRS-80 model number string" }, + { MTRM(R_ACTIVE_SIGNATURE), "Active system signature -- Warm vs Cold boot" }, + { MTRM(R_HIMEM), "HIMEM" }, + { MTRM(R_RST_5_5_VCTR), "RST 5.5 RAM Vector" }, + { MTRM(R_RST_6_5_VCTR), "RST 6.5 RAM Vector" }, + { MTRM(R_RST_7_5_VCTR), "RST 7.5 RAM Vector" }, + { MTRM(R_TRAP_VCTR), "RAM vector for TRAP interrupt" }, + { MTRM(R_OPTION_ROM_FLAG), "Option ROM flag" }, + { MTRM(R_DIAL_SPEED), "Dial speed (1=10pps), 2=20pps" }, + { MTRM(R_FKEY_STAT_TBL), "Function key status table (1 = on)" }, + { MTRM(R_NEW_CONSOLE_FLAG), "New Console device flag" }, + { MTRM(R_CURSOR_ROW), "Cursor row (1-8)" }, + { MTRM(R_CURSOR_COL), "Cursor column (1-40)" }, + { MTRM(R_ACTIVE_ROW_CNT), "Active rows count (1-8)" }, + { MTRM(R_ACTIVE_COL_CNT), "Active columns count (1-40)" }, + { MTRM(R_LABEL_LINE_PROT), "Label line protect status" }, + { MTRM(R_SCROLL_DISABLE), "Scroll disable flag" }, + { MTRM(R_CURSOR_STAT), "Cursor status (0 = off)" }, + { MTRM(R_CURSOR_ROW2), "Cursor row (1-8)" }, + { MTRM(R_CURSOR_COL2), "Cursor column (1-40)" }, + { MTRM(R_ESC_MODE_FLAG), "ESC mode flag for RST 20H" }, + { MTRM(R_REV_VID_SWITCH), "Reverse video switch" }, + { MTRM(R_LAST_PLOT_X), "X coord of last point plotted" }, + { MTRM(R_LAST_PLOT_Y), "Y coord of last point plotted" }, + { MTRM(R_PWR_OFF_STAT), "Power off exit condition switch" }, + { MTRM(R_DUPLEX_SWITCH), "Full/Half duplex switch" }, + { MTRM(R_RS232_LF_SWITCH), "RS232 auto linefeed switch" }, + { MTRM(R_RS232_PARAM_TBL), "RS232 parameter setting table" }, + { MTRM(R_ADDRESS_LAST_CALLED), "Address last called" }, + { MTRM(R_OUT_STMT_HOOK), "OUT statement hook" }, + { MTRM(R_INP_STMT_HOOK), "INP function hook" }, + { MTRM(R_LAST_ERROR_CODE), "Last Error code" }, + { MTRM(R_LPT_HEAD_POS), "Line printer head position" }, + { MTRM(R_OUTPUT_DEVICE), "Output device for RST 20H (0=screen)" }, + { MTRM(R_BASIC_STR_BUF_PTR), "BASIC string buffer pointer" }, + { MTRM(R_CUR_BASIC_LINE_NUM), "Current executing line number" }, + { MTRM(R_START_BASIC_PGM_PTR), "Start of BASIC program pointer" }, + { MTRM(R_END_OF_STMT_MARKER), "End of statement marker" }, + { MTRM(R_KEYBOARD_BUF), "Keyboard buffer" }, + { MTRM(R_CURSOR_H_POS), "Horiz. position of cursor (0-39)" }, + { MTRM(R_FKEY_DEF_BUF), "Function key definition area" }, + { MTRM(R_BASIC_FKEY_DEF_BUF), "Function key definition area (BASIC)" }, + { MTRM(R_FILE_RAM_END), "End of RAM for file storage" }, + { MTRM(R_SEC_ONES), "Seconds (ones)" }, + { MTRM(R_SEC_TENS), "Seconds (tens)" }, + { MTRM(R_MIN_ONES), "Minutes (ones)" }, + { MTRM(R_MIN_TENS), "Minutes (tens)" }, + { MTRM(R_HR_ONES), "Hours (ones)" }, + { MTRM(R_HR_TENS), "Hours (tens)" }, + { MTRM(R_DATE_ONES), "Date (ones)" }, + { MTRM(R_DATE_TENS), "Date (tens)" }, + { MTRM(R_DAY_CODE), "Day code (0=Sun), 1=Mon), etc.)" }, + { MTRM(R_MONTH), "Month (1-12)" }, + { MTRM(R_YEAR_ONES), "Year (ones)" }, + { MTRM(R_YEAR_TENS), "Year (tens)" }, + { MTRM(R_SEC_ONES2), "Seconds (ones)" }, + { MTRM(R_SEC_TENS2), "Seconds (tens)" }, + { MTRM(R_MIN_ONES2), "Minutes (ones)" }, + { MTRM(R_MIN_TENS2), "Minutes (tens)" }, + { MTRM(R_HR_ONES2), "Hours (ones)" }, + { MTRM(R_HR_TENS2), "Hours (tens)" }, + { MTRM(R_DATE_ONES2), "Date (ones)" }, + { MTRM(R_DATE_TENS2), "Date (tens)" }, + { MTRM(R_DAY_CODE2), "Day code (0=Sun), 1=Mon), etc.)" }, + { MTRM(R_ONTIME_TIME), "Time for ON TIME interrupt (SSHHMM)" }, + { MTRM(R_ONCOM_FLAG), "On Com flag" }, + { MTRM(R_ONCOM_ADDRESS), "On Com routine address" }, + { MTRM(R_ONTIME_FLAG), "On Time flag" }, + { MTRM(R_ONTIME_ADDRESS), "On Time routine address" }, + { MTRM(R_FKEY_VCTR_TBL), "Function key vector table" }, + { MTRM(R_DIR_RAM_START), "Start of RAM directory" }, + { MTRM(R_UNSAVED_BASIC_PTR), "BASIC program not saved pointer" }, + { MTRM(R_PASTE_RAM_START), "Start of Paste Buffer" }, + { MTRM(R_LAST_CHAR_PRINTED), "Last char sent to printer" }, + { MTRM(R_LABEL_ENABLE_FLAG), "Label line enable flag" }, + { MTRM(R_PORT_A8H), "Contents of port A8H" }, + { MTRM(R_IPL_FILENAME_START), "Start of IPL filename" }, + { MTRM(R_BASIC_LIST_START), "Address where last BASIC list started" }, + { MTRM(R_SP_SAVE_BUF), "SP save area for power up/down" }, + { MTRM(R_LOWEST_RAM), "Lowest RAM address used by system" }, + { MTRM(R_RST_38H_OFFSET), "Offset of last RST 38H call" }, + { MTRM(R_LAST_PGRM_LEN), "Length of last program loaded/saved to tape" }, + { MTRM(R_RST_38H_VCTR_TBL), "Start of RST 38H vector table" }, + { MTRM(R_LCD_OUTPUT_HOOK), "LCD character output hook" }, + { MTRM(R_LPT_OUTPUT_HOOK), "Printer character output hook" }, + { MTRM(R_EOF_FUN_HOOK), "EOF function hook" }, + { MTRM(R_TERM_F6_HOOK), "Term F6 hook" }, + { MTRM(R_TERM_F7_HOOK), "Term F7 hook" }, + { MTRM(R_WIDTH_STMT_HOOK), "WIDTH statement hook" }, + { MTRM(R_CRT_OPEN_HOOK), "CRT open routine hook" }, + { MTRM(R_CRT_OUTPUT_HOOK), "CRT output file routine hook" }, + { MTRM(R_WAND_OPEN_HOOK), "WAND Open routine hook" }, + { MTRM(R_WAND_CLOSE_HOOK), "WAND Close routine hook" }, + { MTRM(R_WAND_GET_HOOK), "WAND Get routine hook" }, + { MTRM(R_WAND_IO_HOOK), "WAND Special I/O routine hook" }, + { MTRM(R_LOF_HOOK), "LOF function hook" }, + { MTRM(R_LOC_HOOK), "LOC function hook" }, + { MTRM(R_LFILES_HOOK), "LFILES statement hook" }, + { MTRM(R_DSKI_HOOK), "DSKI$ routine hook" }, + { MTRM(R_DSKO_HOOK), "DSKO$ routine hook" }, + { MTRM(R_VAR_CREATE_LOC_FLAG), "Variable Create/Locate switch" }, + { MTRM(R_LAST_VAR_TYPE), "Type of last variable used" }, + { MTRM(R_FILE_BUF_PTR), "File buffer area pointer" }, + { MTRM(R_DATA_STMT_LINE_NUM), "Line number of current data statement" }, + { MTRM(R_FOR_NEXT_ACTIVE_FLAG), "FOR/NEXT loop active flag" }, + { MTRM(R_LAST_VAR_ASSIGNED_ADDR), "Address of last variable assigned" }, + { MTRM(R_RUNNING_LINE_NUM_ADDR), "Most recent or currenly running line pointer" }, + { MTRM(R_BASIC_SP_BUF), "SP used by BASIC to reinitialize the stack" }, + { MTRM(R_LAST_ERR_LINE_NUM), "Line number of last error" }, + { MTRM(R_LAST_ENTERED_LINE_NUM), "Most recent used or entered line number" }, + { MTRM(R_ERR_PTR), "Pointer to occurance of error" }, + { MTRM(R_ONERROR_ADDRESS), "Address of ON ERROR routine" }, + { MTRM(R_BREAK_LINE_NUM), "Line where break), END), or STOP occurred" }, + { MTRM(R_BREAK_ADDRESS), "Address where program stopped on last break), END), or STOP" }, + { MTRM(R_DO_FILES_PTR), "Start of DO files pointer" }, + { MTRM(R_CO_FILES_PTR), "Start of CO files pointer" }, + { MTRM(R_VAR_PTR), "Start of variable data pointer" }, + { MTRM(R_ARRAY_TBL_PTR), "Start of array table pointer" }, + { MTRM(R_UNUSED_MEM_PTR), "Unused memory pointer" }, + { MTRM(R_DATA_SEARCH_ADDR), "Address where DATA search will begin next" }, + { MTRM(R_DEF_TBL), "DEF definition table" }, + { MTRM(R_FP_TEMP1), "Floating Point Temp 1" }, + { MTRM(R_FP_TEMP2), "Floating Point Temp 2" }, + { MTRM(R_FP_TEMP3), "Floating Point Temp 3" }, + { MTRM(R_FP_FAC1), "Start of FAC1 for single and double precision" }, + { MTRM(R_INT_FAC1), "Start of FAC1 for integers" }, + { MTRM(R_FP_FAC2), "Start of FAC2 for single and double precision" }, + { MTRM(R_INT_FAC2), "Start of FAC2 for integers" }, + { MTRM(R_MAXFILES), "Maxfiles" }, + { MTRM(R_FILE_NUM_TBL_PTR), "File number description table pointer" }, + { MTRM(R_BASIC_FILENAME), "Filename of current BASIC program" }, + { MTRM(R_LAST_LOAD_FILENAME), "Filename of last program loaded from tape" }, + { MTRM(R_ALT_LCD_CHAR_BUF), "Start of Alt LCD character buffer" }, + { MTRM(R_MENU_TO_RAM_MAP), "Map of MENU entry positions to RAM directory positions" }, + { MTRM(R_MENU_OR_CMD_FLAG), "Flag to indicate MENU entry location or command entry" }, + { MTRM(R_CUR_MENU_DIR_LOC), "Current MENU directory location" }, + { MTRM(R_MAX_MENU_DIR_LOC), "Maximum MENU directory location" }, + { MTRM(R_LCD_CHAR_BUF), "Start of LCD character buffer" }, + { MTRM(R_XON_XOFF_CTRL), "XON/XOFF protocol control" }, + { MTRM(R_XON_XOFF_ENABLE), "XON/XOFF enable flag" }, + { MTRM(R_RS232_INIT_STAT), "RS232 initialization status" }, + { MTRM(R_SOUND_FLAG), "Sound flag" }, + { MTRM(R_PORT_E8H), "Contents of port E8H" }, + { MTRM(R_RS232_CHAR_BUF), "RS232 Character buffer" }, + { MTRM(R_RS232_BUF_CNT), "RS232 buffer count" }, + { MTRM(R_RS232_BUF_OUT), "RS232 buffer output position" }, + { MTRM(R_RS232_BUF_IN), "RS232 buffer input pointer" }, + { MTRM(R_CTRL_S_STAT), "Control-S status" }, + { MTRM(R_UART_BAUD_TIMER_VAL), "UART baud rate timer value" }, + { MTRM(R_RS232_PARITY_CTRL), "RS232 Parity Control byte" }, + { MTRM(R_CAS_PULSE_CTRL), "Cassette port pulse control" }, + { MTRM(R_SPEC_KEY_STAT), "Special key status storage" }, + { MTRM(R_FKEY_STAT), "Function key status storage" }, + { MTRM(R_KEY_SCAN_STORAGE1), "Keyboard scan column storage #1" }, + { MTRM(R_KEY_SCAN_STORAGE2), "Keyboard scan column storage @2" }, + { MTRM(R_SHIFT_KEY_STAT), "Shift key status storage" }, + { MTRM(R_KEY_REPT_START), "Key repeat start delay counter" }, + { MTRM(R_KEY_POSITION), "Key position storage" }, + { MTRM(R_2ND_KEY_BUF_PTR), "Pointer to entry in 2nd Storage Buffer for key" }, + { MTRM(R_KEY_BUF_CNT), "Keyboard buffer count" }, + { MTRM(R_KEY_TYPEAHEAD_BUF), "Keyboard typeahead buffer" }, + { MTRM(R_CURSOR_BIT_PAT_BUF), "Cursor bit pattern storage" }, + { MTRM(R_CUR_PROG_LOAD_ADDR), "'Load address' of current program" }, /* ROM Functions */ - { R_RESET_VECTOR, "Reset Vector" }, - { R_COMP_BYTE_M, "Compare next byte with M" }, - { R_GET_NONWHITE, "Get next non-white char from M" }, - { R_COMP_DE_HL, "Compare DE and HL" }, - { R_PRINT_SPACE, "Send a space to screen/printer" }, - { R_PRINT_CHAR, "Send character in A to screen/printer" }, - { R_PWR_DOWN_TRAP, "Power down TRAP" }, - { R_DET_LAST_VAR_TYPE, "Determine type of last var used" }, - { R_RST_5_5, "RST 5.5 -- Bar Code Reader" }, - { R_GET_FAC1_SIGN, "Get sign of FAC1" }, - { R_RST_6_5, "RST 6.5 -- RS232 character pending" }, - { R_RAM_VCTR_TBL_DRIVER, "RAM vector table driver" }, - { R_RST_7_5, "RST 7.5 -- Timer background task" }, - { R_BASIC_KEYWORD_TBL, "BASIC statement keyword table END to NEW" }, - { R_FUN_KEYWORD_TBL1, "Function keyword table TAB to <" }, - { R_FUN_KEYWORD_TBL2, "Function keyword table SGN to MID$" }, - { R_BASIC_VECTOR_TBL, "BASIC statement vector table for END to NEW" }, - { R_MATH_PRIORITY_TBL, "Math operator priority table" }, - { R_BASIC_ERR_MSG_TXT, "BASIC error message text" }, - { R_FUN_INIT_IMAGE, "Initialization image loaded to F5F0H" }, - { R_FUN_XROM_IMAGE, "External ROM detect image loaded at F605H" }, - { R_FUN_BASIC_STRINGS, "BASIC message strings" }, - { R_POP_FOR_NEXT, "Pop return address for NEXT or RETURN" }, - { R_INIT_AND_READY, "Initialize system and go to BASIC ready" }, - { R_GEN_SN_ERROR, "Generate Syntax error" }, - { R_GEN_d0_ERROR, "Generate /0 error" }, - { R_GEN_NF_ERROR, "Generate NF error" }, - { R_GEN_DD_ERROR, "Generate DD error" }, - { R_GEN_RW_ERROR, "Generate RW error" }, - { R_GEN_OV_ERROR, "Generate OV error" }, - { R_GEN_MO_ERROR, "Generate MO error" }, - { R_GEN_TM_ERROR, "Generate TM error" }, - { R_GEN_ERR_IN_E, "Generate error in E" }, - { R_RESTORE_JMP_BC, "Restore stack & runtime and jump to BC" }, - { R_PRINT_BASIC_ERR, "Print BASIC error message - XX error in XXX" }, - { R_POP_GO_BASIC_RDY, "Pop stack and vector to BASIC ready" }, - { R_GO_BASIC_RDY_OK, "Vector to BASIC ready - print Ok" }, - { R_GO_BASIC_RDY, "Silent vector to BASIC ready" }, - { R_PERFORM_M_GO_RDY, "Perform operation at M and return to ready" }, - { R_UPDATE_LINE_ADDR, "Update line addresses for current BASIC program" }, - { R_EVAL_LIST_ARGS, "Evaluate LIST statement arguments" }, - { R_FIND_LINE_IN_DE, "Find line number in DE" }, - { R_FIND_LINE_DE_AT_HL, "Find line number in DE starting at HL" }, - { R_TOKEN_COMPRESS, "Perform Token compression" }, - { R_FOR_STMT, "FOR statement" }, - { R_TO_STMT, "TO statement" }, - { R_STEP_STMT, "STEP statement" }, - { R_RUN_BASIC_PGRM, "Execute BASIC program" }, - { R_RUN_BASIC_AT_HL, "Start executing BASIC program at HL" }, - { R_EXEC_INST_IN_A, "Execute instruction in A, HL points to args" }, - { R_RST_10H_INC_HL, "RST 10H routine with pre-increment of HL" }, - { R_RST_10H, "RST 10H routine" }, - { R_DEF_STMT, "DEF statement" }, - { R_DEFDBL_STMT, "DEFDBL statement" }, - { R_DEFINT_STMT, "DEFINT statement" }, - { R_DEFSNG_STMT, "DEFSNG statement" }, - { R_DEFSTR_STMT, "DEFSTR statement" }, - { R_DECL_VAR_TYPE_E, "Declare variable at M to be type E" }, - { R_GEN_FC_ERROR, "Generate FC error" }, - { R_EVAL_LINE_NUM, "Evaluate line number text at M" }, - { R_ASCII_TO_BIN, "Convert ASCII number at M to binary" }, - { R_ASCII_TO_BIN_PREINC, "Convert ASCII number at M+1 to binary" }, - { R_RUN_STMT, "RUN statement" }, - { R_GOSUB_STMT, "GOSUB statement" }, - { R_GOTO_STMT, "GOTO statement" }, - { R_GEN_UL_ERROR, "Generate UL error" }, - { R_RETURN_STMT, "RETURN statement" }, - { R_DATA_STMT, "DATA statement" }, - { R_REM_STMT, "REM statement" }, - { R_LET_STMT, "LET statement" }, - { R_ON_STMT, "ON statement" }, - { R_ON_ERROR_STMT, "ON ERROR statement" }, - { R_ON_KEY_STMT, "ON KEY/TIME/COM/MDM GOSUB routine" }, - { R_ON_TIME_STMT, "ON TIME$ handler" }, - { R_RESUME_STMT, "RESUME statement" }, - { R_ERROR_STMT, "ERROR statement" }, - { R_IF_STMT, "IF statement" }, - { R_LPRINT_STMT, "LPRINT statement" }, - { R_PRINT_STMT, "PRINT statement" }, - { R_TAB_STMT, "TAB statement" }, - { R_LINE_STMT, "LINE statement" }, - { R_INPUT_NO_STMT, "INPUT # statement" }, - { R_INPUT_STMT, "INPUT statement" }, - { R_READ_STMT, "READ statement" }, - { R_EVAL_BASIC_INST, "Main BASIC evaluation routine" }, - { R_INT16_DIV, "Integer Divide FAC1=DE/HL" }, - { R_EVAL_FUN, "Evaluate function at M" }, - { R_ERR_FUN, "ERR function" }, - { R_ERL_FUN, "ERL function" }, - { R_VARPTR_FUN, "VARPTR function" }, - { R_VARPTR_BUF_FUN, "VARPTR(#buffer) function" }, - { R_VARPTR_VAR_FUN, "VARPTR(variable) function" }, - { R_EVAL_VAR, "Evaluate variable" }, - { R_CONV_M_TOUPPER, "Get char at M and convert to uppercase" }, - { R_CONV_A_TOUPPER, "Convert A to uppercase" }, - { R_ASCII_NUM_CONV, "ASCII num conversion - find ASCII or tokenized '+' or '-' in A" }, - { R_NOT_FUN, "NOT function" }, - { R_RST_28H, "RST 28H routine" }, - { R_OR_FUN, "OR function" }, - { R_AND_FUN, "AND function" }, - { R_XOR_FUN, "XOR function" }, - { R_EQV_FUN, "EQV function" }, - { R_IMP_FUN, "IMP function" }, - { R_LPOS_FUN, "LPOS function" }, - { R_POS_FUN, "POS function" }, - { R_LD_FAC1_INT, "Load integer in A into FAC1" }, - { R_CHK_RUNNING_PGRM, "Check for running program" }, - { R_GEN_ID_ERROR, "Generate ID error" }, - { R_INP_FUN, "INP function" }, - { R_OUT_STMT, "OUT statement" }, - { R_EVAL_EXPR, "Evaluate expression at M" }, - { R_EVAL_EXPR_PREDEC, "Evaluate expression at M-1" }, - { R_LLIST_STMT, "LLIST statement" }, - { R_LIST_STMT, "LIST statement" }, - { R_BUF_TO_LCD, "Send buffer at M to screen" }, - { R_PEEK_FUN, "PEEK function" }, - { R_POKE_FUN, "POKE function" }, - { R_WAIT_KEY, "Wait for key from keyboard" }, - { R_TOGGLE_LABEL, "Toggle function key label line" }, - { R_CHK_KEY_QUEUE, "Check keyboard queue for pending characters" }, - { R_POWER_STMT, "POWER statement" }, - { R_LOW_PWR_TRAP, "Normal TRAP (low power) interrupt routine" }, - { R_POWER_DOWN, "Turn off computer" }, - { R_POWER_CONT_STMT, "POWER CONT statement" }, - { R_POWER_ON_STMT, "POWER ON statement" }, - { R_OUT_CH_TO_LPT, "Output character to printer" }, - { R_LOAD_CAS_HDR, "Start tape and load tape header" }, - { R_GEN_IO_ERROR, "Generate I/O error" }, - { R_DET_CAS_SYNC_HDR, "Turn cassette motor on and detect sync header" }, - { R_CAS_MOTOR_ON, "Turn cassette motor on" }, - { R_CAS_MOTOR_OFF, "Turn cassette motor off" }, - { R_CAS_READ_BYTE, "Read byte from tape & update checksum" }, - { R_CAS_WRITE_BYTE, "Write byte to tape & update checksum" }, - { R_LCD_DCB, "LCD Device control block" }, - { R_LCD_OPEN, "LCD and PRT file open routine" }, - { R_LCD_OUT, "Output to LCD file" }, - { R_POP_ALL_REGS, "Pop AF, BC, DE, HL from stack" }, - { R_CRT_DCB, "CRT device control block" }, - { R_RAM_DCB, "RAM device control block" }, - { R_RAM_OPEN, "Open RAM file" }, - { R_RAM_CLOSE, "Close RAM file" }, - { R_RAM_OUT, "Output to RAM file" }, - { R_RAM_IN, "Input from RAM file" }, - { R_RAM_IO, "Special RAM file I/O" }, - { R_CAS_DCB, "CAS device control block" }, - { R_CAS_OPEN, "Open CAS file" }, - { R_CAS_CLOSE, "Close CAS file" }, - { R_CAS_OUT, "Output to CAS file" }, - { R_CAS_IN, "Input from CAS file" }, - { R_LPT_DCB, "LPT device control block" }, - { R_LPT_OUT, "Output to LPT file" }, - { R_COM_DCB, "COM device control block" }, - { R_MDM_OPEN, "Open MDM file" }, - { R_COM_OPEN, "Open COM file" }, - { R_COM_CLOSE, "Close COM file" }, - { R_COM_OUT, "Output to COM/MDM file" }, - { R_COM_IN, "Input from COM/MDM file" }, - { R_COM_IO, "Special COM/MDM file I/O" }, - { R_MDM_DCB, "MDM Device control block" }, - { R_MDM_CLOSE, "Close MDM file" }, - { R_SET_RS232_PARAMS, "Set RS232 parameters from string at M" }, - { R_BCR_DCB, "Wand device control block" }, - { R_EOF_FUN, "EOF function" }, - { R_TIME_FUN, "TIME$ function" }, - { R_READ_TIME, "Read time and store it at M" }, - { R_DATE_FUN, "DATE$ function" }, - { R_DAY_FUN, "DAY function" }, - { R_READ_DAY, "Read day and store at M" }, - { R_UPDATE_CLK_VALUES, "Update in-memory (F923H) clock values" }, - { R_TIME_STMT, "TIME$ statement" }, - { R_UPDATE_CLK_CHIP, "Update clock chip from memory F923H" }, - { R_DATE_STMT, "DATE$ statement" }, - { R_DAY_STMT, "DAY$ statement" }, - { R_GET_TIME_STRING, "Get time string from command line" }, - { R_IPL_STMT, "IPL statement" }, - { R_ERASE_IPL_PRGM, "Erase current IPL program" }, - { R_COM_MDM_STMT, "COM and MDM statements" }, - { R_KEY_FUN, "KEY() statement" }, - { R_KEY_ON_OFF_STMT, "KEY STOP/ON/OFF statements" }, - { R_DET_TIME_ARG, "Determine argument (ON/OFF/STOP) for TIME$ statement" }, - { R_DET_DEVICE_ARG, "Determine device (KEY/TIME/COM/MDM) for ON GOSUB" }, - { R_ONTIME_STMT, "ON TIME$ statement" }, - { R_ONCOM_STMT, "ON COM handler" }, - { R_RST7_5_ISR, "RST 7.5 interrupt routine" }, - { R_KICK_PWR_OFF_WDT, "Renew automatic power-off counter" }, - { R_KEY_STMT, "KEY statement" }, - { R_KEY_LIST_STMT, "KEY LIST statement" }, - { R_SEND_CHARS_TO_LCD, "Send B characters from M to the screen" }, - { R_PSET_STMT, "PSET statement" }, - { R_PRESET_STMT, "PRESET statement" }, - { R_DRAW_FBOX, "Draw a filled box on LCD. Coords are on stack" }, - { R_DRAW_BOX, "Draw an unfilled box on LCD. Coords are on stack" }, - { R_TOKENIZE_XY, "Get (X,Y) coordinate from tokenized string at M" }, - { R_CSRLIN_FUN, "CSRLIN function" }, - { R_MAX_FUN, "MAX function" }, - { R_MAXRAM_FUN, "MAXRAM function" }, - { R_MAXFILES_FUN, "MAXFILES function" }, - { R_HIMEM_FUN, "HIMEM function" }, - { R_WIDTH_STMT, "WIDTH statement" }, - { R_SOUND_STMT, "SOUND statement" }, - { R_SOUND_OFF_STMT, "SOUND OFF statement" }, - { R_SOUND_ON_STMT, "SOUND ON statement" }, - { R_MOTOR_STMT, "MOTOR statement" }, - { R_MOTOR_ON_STMT, "MOTOR ON statement" }, - { R_MOTOR_OFF_STMT, "MOTOR OFF statement" }, - { R_CALL_STMT, "CALL statement" }, - { R_SCREEN_STMT, "SCREEN statement" }, - { R_LCOPY_STMT, "LCOPY statement" }, - { R_FILES_STMT, "FILES statement" }, - { R_DISPLAY_CAT, "Display Catalog" }, - { R_KILL_STMT, "KILL statement" }, - { R_KILL_TEXT_FILE, "Kill a text file" }, - { R_NAME_STMT, "NAME statement" }, - { R_NEW_STMT, "NEW statement" }, - { R_STRLEN, "Count length of string at M" }, - { R_GET_FIND_DO_FILE, "Get .DO filename and locate in RAM directory" }, - { R_OPEN_TEXT_FILE, "Open a text file at (FC93H)" }, - { R_CSAVE_STMT, "CSAVE statement" }, - { R_CAS_WRITE_BUF, "Save buffer at M to tape" }, - { R_SAVEM_STMT, "SAVEM statement" }, - { R_CSAVEM_STMT, "CSAVEM statement" }, - { R_CLOAD_STMT, "CLOAD statement" }, - { R_CAS_READ_REC, "Load record from tape and store at M" }, - { R_GEN_VERIFY_FAIL_ERR, "Generate Verify Failed error" }, - { R_LOADM_STMT, "LOADM and RUNM statement" }, - { R_CLOADM_STMT, "CLOADM statement" }, - { R_MOVE_B_BYTES, "Move B bytes from M to (DE)" }, - { R_EXEC_CO_FILE, "Launch .CO files from MENU" }, - { R_CAS_OPEN_OUT_BA, "Open CAS for output of BASIC files" }, - { R_CAS_OPEN_OUT_DO, "Open CAS for output of TEXT files" }, - { R_CAS_OPEN_OUT_CO, "Open CAS for output of CO files" }, - { R_CAS_OPEN_IN_BA, "Open CAS for input of BASIC files" }, - { R_CAS_OPEN_IN_DO, "Open CAS for input of TEXT files" }, - { R_CAS_OPEN_IN_CO, "Open CAS for input of CO files" }, - { R_STR_FUN, "STR$ function" }, - { R_PRINT_STRING, "Print buffer at M until NULL or '\"'" }, - { R_MOVE_L_BYTES, "Move L bytes from (BC) to (DE)" }, - { R_LEN_FUN, "LEN function" }, - { R_ASC_FUN, "ASC function" }, - { R_CHR_FUN, "CHR$ function" }, - { R_STRING_FUN, "STRING$ function" }, - { R_SPACE_FUN, "SPACE$ function" }, - { R_LEFT_FUN, "LEFT$ function" }, - { R_RIGHT_FUN, "RIGHT$ function" }, - { R_MID_FUN, "MID$ function" }, - { R_VAL_FUN, "VAL function" }, - { R_INSTR_FUN, "INSTR function" }, - { R_FRE_FUN, "FRE function" }, - { R_DBL_SUB, "Double precision subtract (FAC1=FAC1-FAC2)" }, - { R_DBL_ADD, "Double precision addition (FAC1=FAC1+FAC2)" }, - { R_BCD_ADD, "Add the BCD num in M to the one in (DE)" }, - { R_DBL_MULT, "Double precision multiply (FAC1=FAC1*FAC2)" }, - { R_DBL_DIV, "Double precision divide (FAC1=FAC1/FAC2)" }, - { R_MOVE_C_BYTES, "Move C bytes from M to (DE)" }, - { R_COS_FUN, "COS function" }, - { R_SIN_FUN, "SIN function" }, - { R_TAN_FUN, "TAN function" }, - { R_ATN_FUN, "ATN function" }, - { R_LOG_FUN, "LOG function" }, - { R_SQR_FUN, "SQR function" }, - { R_EXP_FUN, "EXP function" }, - { R_RND_FUN, "RND function" }, - { R_DBL_SQR, "Double precision Square (FAC1=SQR(FAC1))" }, - { R_MULT_M_FAC2, "Double precision math (FAC1=M * FAC2))" }, - { R_FAC2_EQ_FAC1, "Move FAC1 to FAC2" }, - { R_FAC2_EQ_FP, "Move floating point number M to FAC2" }, - { R_FAC1_EQ_FAC2, "Move FAC2 to FAC1" }, - { R_FAC1_EQ_FP, "Move floating point number M to FAC1" }, - { R_M_EQ_FAC1, "Move FAC1 to M" }, - { R_MULT_FAC1_SQR_FAC1, "Double precision math (FAC1=FAC1*SQR(FAC1))" }, - { R_SWAP_FAC1_FAC2, "Swap FAC1 and FAC2" }, - { R_SQR_FAC1_MULT_TBL, "Square FAC1 & do table based math" }, - { R_TBL_BASED_MATH, "Table based math (FAC1=(((FAC1*M)+(M+1))*(M+2)+(M+3)..." }, - { R_PUSH_FAC2, "Push FAC2 on stack" }, - { R_PUSH_FAC1, "Push FAC1 on stack" }, - { R_POP_FAC2, "Pop FAC2 from stack" }, - { R_POP_FAC1, "Pop FAC1 from stack" }, - { R_FP_NUMBERS, "Floating point numbers for math operations " }, - { R_FP_SHARED_NUMBERS, "Floating point num-shares 6 bytes from next number" }, - { R_EXP_MATH_TBL, "Count of Floating point numbers to follow for EXP" }, - { R_LOG_MATH_TBL, "Count of Floating point numbers to follow for LOG" }, - { R_SIN_MATH_TBL, "Count of Floating point numbers to follow for SIN" }, - { R_ATN_MATH_TBL, "Count of Floating point numbers to follow for ATN" }, - { R_RST_30H_FUN, "RST 30H routine" }, - { R_ABS_FUN, "ABS function" }, - { R_SGN_FUN, "SGN function" }, - { R_PUSH_SNGL_FAC1, "Push single precision FAC1 on stack" }, - { R_SNGL_FAC1_EQ_M, "Load single precision at M to FAC1" }, - { R_SNGL_FAC1_EQ_BCDE, "Load single precision in BCDE to FAC1" }, - { R_SNGL_BCDE_EQ_FAC1, "Load single precision FAC1 to BCDE" }, - { R_SNGL_BCDE_EQ_M, "Load single precision at M to BCDE" }, - { R_SNGL_DECB_EQ_M, "Reverse load single precision at M to DEBC" }, - { R_SNGL_M_EQ_FAC1, "Move single precision FAC1 to M" }, - { R_LOAD_FAC2_FROM_M, "Move M to FAC2 using precision at (FB65H)" }, - { R_MOVE_B_BYTES_INC, "Move B bytes from (DE) to M with increment" }, - { R_MOVE_B_BYTES_DEC, "Move B bytes from (DE) to M with decrement" }, - { R_SNGL_CMP_BCDE_FAC1, "Compare single precision in BCDE with FAC1" }, - { R_SNGL_CMP_BCDE_M, "Compare single precision in BCDE with M" }, - { R_SINT_CMP, "Compare signed integer in DE with that in HL" }, - { R_CMP_FAC1_FAC2, "Compare double precision FAC1 with FAC2" }, - { R_CINT_FUN, "CINT function" }, - { R_FAC1_EQ_SINT_HL, "Load signed integer in HL to FAC1" }, - { R_CSNG_FUN, "CSNG function" }, - { R_CONV_SINT_SNGL, "Convert signed integer in FAC1 to single precision" }, - { R_CONV_SINT_HL_SNGL, "Convert signed integer HL to single precision FAC1" }, - { R_CDBL_FUN, "CDBL function" }, - { R_FIX_FUN, "FIX function" }, - { R_INT_FUN, "INT function" }, - { R_SINT_SUB, "Signed integer subtract (FAC1=HL-DE)" }, - { R_SINT_ADD, "Signed integer addition (FAC1=HL+DE)" }, - { R_SINT_MULT, "Signed integer muliply (FAC1=HL*DE)" }, - { R_SINT_DIV, "Signed integer divide (FAC1=DE/HL)" }, - { R_SNGL_ADD_BCDE, "Single precision addition (FAC1=FAC1+BCDE)" }, - { R_SNGL_ADD_FAC2, "Single precision addition (FAC1=FAC1+FAC2)" }, - { R_SNGL_SUB, "Single precision subtract (FAC1=FAC1-BCDE)" }, - { R_SNGL_MULT_BCDE, "Single precision multiply (FAC1=FAC1*BCDE)" }, - { R_SNGL_MULT_FAC2, "Single precision multiply (FAC1=FAC2*FAC2)" }, - { R_SNGL_DIV, "Single precision divide (FAC1=BCDE/FAC1)" }, - { R_SNGL_LOAD, "Single precision load (FAC2=BCDE)" }, - { R_ASCII_TO_DBL, "Convert ASCII number at M to double precision in FAC1" }, - { R_ASCII_FND_e, "Found 'e' in ASCII number" }, - { R_ASCII_FND_E, "Found 'E' in ASCII number" }, - { R_ASCII_FND_DOT, "Found '.' in ASCII number" }, - { R_ASCII_FND_PERC, "Found '%' in ASCII number" }, - { R_ASCII_FND_LB, "Found '#' in ASCII number" }, - { R_ASCII_CONV_HELPER, "Deal with single & double precision ASCII conversions" }, - { R_ASCII_CONV_HELPER2, "Convert ASCII number that starts with a Digit" }, - { R_PRNT_BASIC_ERR_TERM, "Finish printing BASIC ERROR message \" in \" line #" }, - { R_PRINT_HL_ON_LCD, "Print binary number in HL at current position" }, - { R_PRINT_FAC1, "Convert binary number in FAC1 to ASCII at M" }, - { R_PRINT_FAC1_FORMAT, "Convert binary number in FAC1 to ASCII at M with format" }, - { R_FAC1_EQ_ZERO, "Initialize FAC1 with 0.0 if it has no value" }, - { R_SNGL_EXP, "Single precision exponential function" }, - { R_DBL_EXP, "Double precision exponential function" }, - { R_INT_EXP, "Integer exponential function" }, - { R_TIME_ON_STMT, "TIME$ ON statement" }, - { R_TRIG_INTR, "Trigger interrupt. HL points to interrupt table" }, - { R_CLEAR_INTR, "Clear interrupt. HL points to interrupt table" }, - { R_TIME_OFF_STMT, "TIME$ OFF statement" }, - { R_TIME_STOP_STMT, "TIME$ STOP statement" }, - { R_CLEAR_COM_INT_DEF, "Clear all COM, TIME, and KEY interrupt definitions" }, - { R_RESTORE_STMT, "RESTORE statement" }, - { R_STOP_STMT, "STOP statement" }, - { R_END_STMT, "END statement" }, - { R_CONT_STMT, "CONT sttement" }, - { R_ISALPHA_M, "Check if M is alpha character" }, - { R_ISALPHA_A, "Check if A is alpha character" }, - { R_CLEAR_STMT, "CLEAR statement" }, - { R_NEXT_STMT, "NEXT statement" }, - { R_SEND_CRLF, "Send CRLF to screen or printer" }, - { R_SEND_LF, "Send LF to screen or printer" }, - { R_BEEP_STMT, "BEEP statement" }, - { R_HOME_CURSOR, "Home cursor" }, - { R_CLS_STMT, "CLS statement" }, - { R_PROTECT_LABEL, "Protect line 8. An ESC T is printed" }, - { R_UNPROT_LABEL, "Unprotect line 8. An ESC U is printed" }, - { R_STOP_AUTO_SCROLL, "Stop automatic scrolling" }, - { R_RESUME_AUTO_SCROLL, "Resume automatic scrolling" }, - { R_TURN_CURSOR_ON, "Turn the cursor on" }, - { R_TURN_CURSOR_OFF, "Turn the cursor off" }, - { R_DEL_CUR_LINE, "Delete current line on screen" }, - { R_INSERT_LINE, "Insert line a current line" }, - { R_ERASE_TO_EOL, "Erase from cursor to end of line" }, - { R_SEND_ESC_X, "Send ESC X" }, - { R_INV_CHAR_ENABLE, "Start inverse character mode" }, - { R_INV_CHAR_DISABLE, "Cancel inverse character mode" }, - { R_END_ESC_SEQ, "End escape sequence" }, - { R_CURSOR_TO_LOW_LEFT, "Send cursor to lower left of CRT" }, - { R_SET_CURSOR_POS, "Set the current cursor position (H=Row,L=Col)" }, - { R_ERASE_FKEY_DISP, "Erase function key display" }, - { R_SET_DISP_FKEY, "Set and display function keys (M has key table)" }, - { R_DISP_FKEY_LINE, "Display function key line" }, - { R_PRINT_A_TO_LCD, "Print A to the screen" }, - { R_CHAR_PLOT_3, "Character plotting level 3. Check new device console flag & call level 4)" }, - { R_CHAR_PLOT_4, "Character plotting level 4. Turn off background task & call level 5" }, - { R_CHAR_PLOT_5, "Character plotting level 5. Handle ESC sequences & call level 6" }, - { R_LCD_OUT_DRIVER, "LCD output driver" }, - { R_RST_20H_LKUP_TBL, "RST 20H lookup table" }, - { R_ESC_Y, "ESC Y routine (Set cursor position)" }, - { R_LCD_OUT_ESC_FUN, "LCD output Escape routine" }, - { R_LCD_ESC_LKUP_TBL, "LCD Escape sequence lookup table" }, - { R_ESC_SEQ_DRIVER, "ESCape sequence driver" }, - { R_ESC_p_FUN, "ESC p routine (start inverse video)" }, - { R_ESC_q_FUN, "ESC q routine (cancel inverse video)" }, - { R_ESC_U_FUN, "ESC U routine (unprotect line 8)" }, - { R_ESC_T_FUN, "ESC T routine (protect line 8)" }, - { R_ESC_V_FUN, "ESC V routine (stop automatic scrolling)" }, - { R_ESC_W_FUN, "ESC W routine (resume automatic scrolling)" }, - { R_ESC_X_FUN, "ESC X routine" }, - { R_ESC_C_FUN, "ESC C routine (move cursor right)" }, - { R_ESC_D_FUN, "ESC D routine (move cursor left)" }, - { R_BKSPACE_FUN, "Backspace routine" }, - { R_ESC_A_FUN, "ESC A routine (move cursor up)" }, - { R_ESC_B_FUN, "ESC B routine (move cursor down)" }, - { R_TAB_FUN, "Tab routine" }, - { R_LF_FUN, "Linefeed routine" }, - { R_ESC_H_FUN, "Verticle tab and ESC H routine (home cursor)" }, - { R_CR_FUN, "CR routine" }, - { R_ESC_P_FUN, "ESC P routine (turn cursor on)" }, - { R_ESC_Q_FUN, "ESC Q routine (turn cursor off)" }, - { R_ESC_M_FUN, "ESC M routine" }, - { R_LCD_SCROLL, "Scroll LCD screen A times at line number in L" }, - { R_ESC_L_FUN, "ESC L routine (insert line)" }, - { R_GET_LCD_CHAR, "Get character at (H,L) from LCD RAM)" }, - { R_ESC_l_FUN, "ESC l routine (erase current line)" }, - { R_ESC_K_FUN, "ESC K routine (erase to EOL)" }, - { R_CLS_FUN, "Form Feed (0CH), CLS, ESC E, and ESC J routine" }, - { R_CHAR_PLOT_6, "Character plotting level 6. Save character in C to LCD RAM & call level 7" }, - { R_ESC_J_FUN, "ESC J routine" }, - { R_INP_DISP_LINE, "Input and display line and store" }, - { R_INP_DISP_LINE_NO_Q, "Input and display (no \"?\") line and store" }, - { R_INP_CTRL_C_HANDLER, "Input routine Control-C handler" }, - { R_INP_ENTER_HANDLER, "Input routine ENTER handler" }, - { R_INP_BKSP_HANDLER, "Input routine backspace, left arrow, CTRL-H handler" }, - { R_INP_CTRL_U_HANDLER, "Input routine CTRL-U & X handler" }, - { R_INP_TAB_HANDLER, "Input routine Tab handler" }, - { R_DIM_STMT, "DIM statement" }, - { R_FIND_VAR_ADDR, "Find address of variable at M" }, - { R_USING_FUN, "USING function" }, - { R_SEND_A_LCD_LPT, "Send A to screen or printer" }, - { R_PRINT_A_EXPAND, "Print A to printer, expanding tabs if necessary" }, - { R_SET_OUT_DEV_LCD, "Reinitialize output back to LCD" }, - { R_LCD_CHAR_OUT_FUN, "LCD character output routine" }, - { R_LCD_NEW_LINE, "Move LCD to blank line (send CRLF if needed)" }, - { R_INKEY_FUN, "INKEY$ function" }, - { R_GET_FILE_DESC, "Get file descriptor for file in A" }, - { R_OPEN_STMT, "OPEN statement" }, - { R_LCD_CLOSE_FUN, "LCD, CRT, and LPT file close routine" }, - { R_RUN_STMT_PARAM, "RUN statement (with parameters)" }, - { R_LOAD_STMT, "LOAD statement" }, - { R_MERGE_STMT, "MERGE statement" }, - { R_SAVE_STMT, "SAVE statement" }, - { R_CLOSE_STMT, "CLOSE statement" }, - { R_INPUT_FUN, "INPUT$ function" }, - { R_CLEAR_MEM, "Zero B bytes at M" }, - { R_LOAD_MEM, "Load B bytes at M with A" }, - { R_PRINT_LB_INIT_FUN, "PRINT # initialization routine" }, - { R_LINE_INPUT_STMT, "LINE INPUT # statement" }, - { R_GEN_NM_ERR_FUN, "Generate NM error" }, - { R_GEN_AO_ERR_FUN, "Generate AO error" }, - { R_GEN_DS_ERR_FUN, "Generate DS error" }, - { R_GEN_FF_ERR_FUN, "Generate FF error" }, - { R_GEN_CF_ERR_FUN, "Generate CF error" }, - { R_GEN_BN_ERR_FUN, "Generate BN error" }, - { R_GEN_IE_ERR_FUN, "Generate IE error" }, - { R_GEN_EF_ERR_FUN, "Generate EF error" }, - { R_GEN_FL_ERR_FUN, "Generate FL error" }, - { R_LOF_FUN, "LOF function" }, - { R_LOC_FUN, "LOC function" }, - { R_LFILES_FUN, "LFILES function" }, - { R_DSKO_FUN, "DSKO$ function" }, - { R_DSKI_FUN, "DSKI$ function" }, - { R_DEV_NAME_TBL, "Device name table" }, - { R_DCB_VCTR_TBL, "Device control block vector addresses table" }, - { R_TELCOM_ENTRY, "TELCOM Entry point" }, - { R_TELCOM_RE_ENTRY, "Re-entry point for TELCOM commands" }, - { R_TELCOM_INST_VCTR_TBL, "TELCOM instruction vector table" }, - { R_TELCOM_LABEL_TXT, "TELCOM label line text table" }, - { R_TELCOM_STAT_FUN, "TELCOM STAT instruction routine" }, - { R_PRINT_TELCOM_STAT, "Print current STAT settings" }, - { R_SET_TELCOM_STAT, "Set STAT and return to TELCOM ready" }, - { R_TELCOM_CALL_FUN, "TELCOM CALL instruction routine" }, - { R_TELCOM_FIND_FUN, "TELCOM FIND instruction routine" }, - { R_GO_OFFHOOK, "Go off-hook" }, - { R_DISCONNECT_PHONE, "Disconnect phone line and disable modem carrier" }, - { R_CONNECT_PHONE, "Connect phone line and enable modem carrier" }, - { R_GO_OFFHOOK_WAIT, "Go off-hook and wait for carrier" }, - { R_TELCOM_PAUSE, "Pause for about 2 seconds" }, - { R_EXEC_LOGON_SEQ, "Execute logon sequence at M" }, - { R_DIALING_FUN, "Dialing routine" }, - { R_AUTO_LOGIN_SEQ, "Auto logon sequence" }, - { R_DIAL_DIGIT, "Dial the digit in A & print on LCD" }, - { R_TELCOM_TERM_FUN, "TELCOM TERM instruction routine" }, - { R_TELCOM_DISPATCH, "TELCOM \"dispatcher\" routine" }, - { R_TELCOM_PREV_FUN, "TELCOM PREV function routine" }, - { R_TELCOM_FULL_FUN, "TELCOM FULL/HALF function routine" }, - { R_TELCOM_ECHO_FUN, "TELCOM ECHO function routine" }, - { R_TELCOM_UP_FUN, "TELCOM UP function routine" }, - { R_TELCOM_DOWN_FUN, "TELCOM DOWN function routine" }, - { R_TELCOM_BYE_FUN, "TELCOM BYE function routine" }, - { R_MENU_ENTRY, "MENU Program" }, - { R_DISP_DIR, "Display directory entries" }, - { R_MENU_CTRL_U_HANDLER, "Handle CTRL-U key from MENU command loop" }, - { R_MENU_CMD_LOOP, "MENU Program command loop" }, - { R_MENU_BKSP_HANDLER, "Handle Backspace key from MENU command loop" }, - { R_MENU_ENTER_HANDLER, "Handle ENTER key from MENU command loop" }, - { R_EXEC_ROM_FILE, "Launch ROM command file from MENU program" }, - { R_DISP_DIR_TYPE_C, "Display directory entries of type in register C" }, - { R_CONV_FILENAME, "Convert filename from space padded to '.ext' format" }, - { R_NEXT_DIR_ENTRY, "Position cursor for next directory entry" }, - { R_CLS_PRINT_TIME_DAY, "Print time, day and date on first line of screen" }, - { R_PRINT_TIME_DAY, "Print time,day,date on first line w/o CLS" }, - { R_PRINT_STRING2, "Print NULL terminated string at M" }, - { R_COPY_MEM_DE_M, "Copy A bytes from (DE) to M" }, - { R_CMP_MEM_DE_M, "Compare string at DE with that at M (max C bytes)" }, - { R_CLEAR_FKEY_TBL, "Clear function key definition table" }, - { R_SET_FKEYS, "Set new function key table" }, - { R_DISP_FKEYS, "Display function keys on 8th line" }, - { R_SEARCH_DIR, "Search directory for filename" }, - { R_GET_FILE_ADDR, "Get start address of file at M" }, - { R_ADDRSS_ENTRY, "ADDRSS Entry point" }, - { R_ADDRSS_ENTRY_W_FILE, "ADDRSS entry with (DE) pointing to filename" }, - { R_SCHEDL_ENTRY, "SCHEDL Entry point" }, - { R_SCHEDL_ENTRY_W_FILE, "SCHEDL entry with (DE) pointing to filename" }, - { R_ADDRSS_FIND_FUN, "FIND instruction for ADDRSS/SCHEDL" }, - { R_ADDRSS_LFND_FUN, "LFND instruction for ADDRSS/SCHEDL" }, - { R_FIND_TEXT_IN_FILE, "Find text at M in the file at (DE)" }, - { R_FIND_NEXT_LINE_IN_FILE, "Increment DE past next CRLF in text file at (DE)" }, - { R_CHECK_FOR_CRLF, "Check next byte(s) at (DE) for CRLF" }, - { R_ADDRSS_INST_VCTR_TBL, "ADDRSS/SCHEDL instruction vector table" }, - { R_GET_KEY_CONV_TOUPPER, "Wait for char from keyboard & convert to uppercase" }, - { R_SEND_CURSOR_HOME, "Home cursor" }, - { R_PRINT_TIME_LOOP, "Print time on top line until key pressed" }, - { R_TEXT_ENTRY, "TEXT Entry point" }, - { R_TEXT_FKEY_TBL, "TEXT Function key table - empty" }, - { R_EDIT_STMT, "EDIT statement" }, - { R_WAIT_FOR_SPACE_KEY, "Wait for a space to be entered on keyboard" }, - { R_EDIT_DO_FILE_FUN, "Edit .DO files" }, - { R_TEXT_EDIT_LOOP, "Main TEXT edit loop" }, - { R_TEXT_CTRL_VCTR_TBL, "TEXT control character vector table" }, - { R_TEXT_ESC_FUN, "TEXT ESCape routine" }, - { R_TEXT_CTRL_P_FUN, "TEXT control P routine" }, - { R_TEXT_CTRL_I_FUN, "TEXT control I routine" }, - { R_TEXT_CTRL_M_FUN, "TEXT control M routine" }, - { R_TEXT_CTRL_D_FUN, "TEXT right arrow and control D routine" }, - { R_TEXT_CTRL_X_FUN, "TEXT down arrow and control X routine" }, - { R_TEXT_CTRL_H_FUN, "TEXT control H routine" }, - { R_TEXT_CTRL_S_FUN, "TEXT left arrow and control S routine" }, - { R_TEXT_CTRL_E_FUN, "TEXT up arrow and control E routine" }, - { R_TEXT_CTRL_F_FUN, "TEXT control F routine" }, - { R_TEXT_CTRL_A_FUN, "TEXT control A routine" }, - { R_TEXT_CTRL_T_FUN, "TEXT control T routine" }, - { R_TEXT_CTRL_B_FUN, "TEXT control B routine" }, - { R_TEXT_CTRL_R_FUN, "TEXT control R routine" }, - { R_TEXT_CTRL_Q_FUN, "TEXT control Q routine" }, - { R_TEXT_CTRL_W_FUN, "TEXT control W routine" }, - { R_TEXT_CTRL_Z_FUN, "TEXT control Z routine" }, - { R_TEXT_CTRL_L_FUN, "TEXT control L routine" }, - { R_TEXT_CTRL_C_FUN, "TEXT control C routine" }, - { R_TEXT_GET_NEXT_BYTE, "Get next byte for TEXT Program entry" }, - { R_TEXT_CTRL_O_FUN, "TEXT control O routine" }, - { R_TEXT_CTRL_U_FUN, "TEXT control U routine" }, - { R_TEXT_CTRL_N_FUN, "TEXT control N routine" }, - { R_COPY_NULL_STRING, "Copy NULL terminated string at M to (DE)" }, - { R_TEXT_CTRL_Y_FUN, "TEXT control Y routine" }, - { R_TEXT_CTRL_G_FUN, "TEXT control G routine" }, - { R_TEXT_CTRL_V_FUN, "TEXT control V routine" }, - { R_INSERT_A_INTO_FILE, "Insert A into text file at M" }, - { R_INSERT_SPACES, "Insert BC spaces at M" }, - { R_DELETE_CHARS, "Delete BC characters at M" }, - { R_MOVE_BC_BYTES_INC, "Move BC bytes from M to (DE) with increment" }, - { R_MOVE_BC_BYTES_DEC, "Move BC bytes from M to (DE) with decrement" }, - { R_BASIC_ENTRY, "BASIC Entry point" }, - { R_LOAD_BASIC_FKEYS, "Copy BASIC Function key table to key definition area" }, - { R_RE_INIT_SYSTEM, "Re-initialize system without destroying files" }, - { R_WARM_RESET, "Warm start reset entry" }, - { R_SEND_A_TO_LPT, "Send character in A to the printer" }, - { R_CHECK_RS232_QUEUE, "Check RS232 queue for pending characters" }, - { R_READ_RS232_QUEUE, "Get a character from RS232 receive queue" }, - { R_RST_6_5_FUN, "RST 6.5 routine (RS232 receive interrupt)" }, - { R_INC_RS232_QUEUE_IN, "Calculate address to save next RS232 character" }, - { R_SEND_XON, "Send XON (CTRL-Q) out RS232" }, - { R_DISABLE_XON_XOFF, "Turn off XON/XOFF protocol" }, - { R_SEND_A_USING_XON, "Send character in A to serial port using XON/XOFF" }, - { R_SEND_C_TO_RS232, "Send character in C to serial port" }, - { R_XON_XOFF_HANDLER, "Handle XON/XOFF protocol" }, - { R_SET_RS232_BAUD_RATE, "Set RS232 baud rate stored in H" }, - { R_RS232_BAUD_TIMER_VALS, "RS232 baud rate timer values" }, - { R_INIT_RS232_MDM, "Initialize RS232 or modem" }, - { R_UNINIT_RS232_MDM, "Deactivate RS232 or modem" }, - { R_CLICK_SND_PORT, "Click sound port if sound enabled" }, - { R_CHECK_CD, "Check for carrier detect" }, - { R_ENABLE_XON_XOFF, "Enable XON/OFF when CTRL-S / CTRL-Q sent" }, - { R_INIT_SER_BUF_PARAMS, "Initialize serial buffer parameters" }, - { R_CAS_WRITE_HEADER, "Write cassette header and sync byte" }, - { R_CAS_WRITE_NO_CHKSUM, "Write char in A to cassette w/o checksum" }, - { R_CAS_WRITE_NO_SYNC, "Write char in A to cassette w/o checksum or sync bit" }, - { R_CAS_WRITE_BIT, "Write bit 0 of A to cassette" }, - { R_CAS_READ_HEADER, "Read cassette header and sync byte" }, - { R_CAS_READ_BIT, "Read Cassette port data bit" }, - { R_CAS_COUNT_BITS, "Count and pack cassette input bits" }, - { R_CAS_READ_NO_CHKSUM, "Read character from cassette w/o checksum" }, - { R_CAS_REMOTE_FUN, "Cassette REMOTE routine - turn motor on or off" }, - { R_KEYSCAN_MGT_FUN, "Keyboard scanning management routine" }, - { R_KEY_DETECTION, "Key detection -- Determine which keys are pressed" }, - { R_KEY_REPEAT_DET, "Key repeat detection" }, - { R_GET_KEY_MATRIX, "Calculate key matrix position and save buffer pointer at FFA8H" }, - { R_INIT_KEY_RPT_CNT, "Key detected - initialize repeat counter and decode" }, - { R_KEY_DECODE, "Key decoding" }, - { R_KEY_FIRST_IN_BUF, "Keyboard buffer management - place key in new buffer" }, - { R_KEY_ADD_TO_BUF, "Keyboard buffer management - place subsequent key in buffer" }, - { R_ISR_EXIT_FUN, "Interrupt exit routine (pop all regs & RET)" }, - { R_UNSHIFTED_KEY, "Handle unshifted & non-CTRL key during key decoding" }, - { R_ARROW_KEY, "Handle Arrow keys during key decoding" }, - { R_CAPS_LOCK_KEY, "Handle CAPS LOCK key during key decoding" }, - { R_NUM_KEY, "Handle NUM key during key decoding" }, - { R_SCAN_KEYBOARD, "Scan keyboard for character (CTRL-BREAK ==> CTRL-C)" }, - { R_ENABLE_INTERRUPTS, "Enable interrupts as normal" }, - { R_CHK_PENDING_KEYS, "Check keyboard queue for pending characters" }, - { R_CHK_BREAK, "Check for break or wait (CTRL-S)" }, - { R_CHK_SHIFT_BREAK, "Check if SHIFT-BREAK is being pressed" }, - { R_SCAN_SPECIAL_KEYS, "Scan BREAK,CAPS,NUM,CODE,GRAPH,CTRL,SHIFT & set bits in A" }, - { R_GEN_TONE, "Produce a tone of DE freq and B duration" }, - { R_GET_CLK_CHIP_REGS, "Copy clock chip regs to M" }, - { R_PUT_CLK_CHIP_REGS, "Update clock chip regs from M" }, - { R_READ_CLK_CHIP_BIT, "Read next bit from Clock Chip" }, - { R_SET_CLK_CHIP_MODE, "Set clock chip mode" }, - { R_BLINK_CURSOR, "Blink the cursor" }, - { R_PLOT_POINT, "Plot (set) point (D,E) on the LCD" }, - { R_CHAR_PLOT_7, "Character plotting level 7. Plot character in C on LCD at (H,L)" }, - { R_CLEAR_POINT, "Clear (reset) point (D,E) on the LCD" }, - { R_LCD_BYTE_PLOT, "Byte Plot - Send bit pattern to LCD for character" }, - { R_ENABLE_LCD_DRIVER, "Enable LCD drivers after short delay" }, - { R_WAIT_LCD_DRIVER, "Wait for LCD driver to be available" }, - { R_LCD_BIT_PATTERNS, "8155 PIO chip bit patterns for LCD drivers" }, - { R_DELAY_FUN, "Delay routine - decrement C until zero" }, - { R_SET_INTR_1DH, "Set interrupt to 1DH" }, - { R_BEEP_FUN, "Beep routine" }, - { R_CLICK_SOUND_PORT, "Click sound port" }, - { R_CHK_XTRNL_CNTRLER, "Check for optional external controller" }, - { R_XTRNL_CNTRLER_DRIVER, "Optional external controller driver" }, - { R_LCD_CHAR_SHAPE_TBL1, "LCD char generator shape table (20H-7FH" }, - { R_LCD_CHAR_SHAPE_TBL2, "LCD char generator shape table (80H-FFH)" }, - { R_KEYBOARD_CONV_MATRIX, "Keyboard conversion matrix" }, - { R_BOOT_ROUTINE, "Boot routine" }, - { R_COLD_BOOT, "Cold boot routine" }, - { R_DISP_MODEL, "Display TRS-80 Model number & Free bytes on LCD" }, - { R_DISP_FREE_BYTES, "Display number of free bytes on LCD" }, - { R_INIT_RST_38H_TBL, "Initialize RST 38H RAM vector table" }, - { R_CALC_FREE_RAM, "Calculate physical RAM available" }, - { R_INIT_CLK_CHIP_REGS, "Initial clock chip register values" }, - { R_MENU_TEXT_STRINGS, "MENU Text Strings" }, - { R_RST_38H_DRIVER, "RST 38H RAM vector driver routine" }, - { R_RST_5_5_VECTOR, "RST 5.5 RAM Vector" }, - { R_RST_6_5_VECTOR, "RST 6.5 RAM Vector" }, - { R_RST_7_5_VECTOR, "RST 7.5 RAM Vector" }, - { R_TRAP_VECTOR, "RAM vector for TRAP interrupt" }, - { R_DETECT_OPTION_ROM, "Detect Option ROM" }, - { R_BASIC_RUNNING, "BASIC Program Running Flag" }, - { R_INIT_BASIC_VARS, "Initialize BASIC Variables for new execution" }, - { R_INIT_TEMP3, "Initialize FP_TEMP3 for new program" }, - { R_RENUM_STMT, "RENUM Statement" }, - { R_TEST_COM_TOKEN, "Test for COM token (ON COM Statement)" }, - { R_CMD_STMT, "CMD Statement" }, - { R_LOCATE_STMT, "LOCATE Statement" }, - { R_COLOR_STMT, "COLOR Statement" }, - { R_EXEC_STMT, "EXEC Statement" }, - { R_BSAVE_STMT, "BSAVE Statement" }, - { R_BLOAD_STMT, "BLOAD Statement" }, - { R_DSKF_FUN, "DSKF Function" }, - { R_FORMAT_FUN, "FORMAT Function" }, - { R_PORT_90H, "Current value of OUT port 90H" }, - { R_RST0_HOOK, "RST 0 Hook" }, - { R_EXEC_2ND_ROM, "Hook to execute Option ROM" }, - { R_TELCOM_FKEY_VCTR, "Main TELCOM Funciton Key Vector Table" }, - { R_UNUSED, "Unused Space" }, - { -1, "" }, + { MTRM(R_RESET_VECTOR), "Reset Vector" }, + { MTRM(R_COMP_BYTE_M), "Compare next byte with M" }, + { MTRM(R_GET_NONWHITE), "Get next non-white char from M" }, + { MTRM(R_COMP_DE_HL), "Compare DE and HL" }, + { MTRM(R_PRINT_SPACE), "Send a space to screen/printer" }, + { MTRM(R_PRINT_CHAR), "Send character in A to screen/printer" }, + { MTRM(R_PWR_DOWN_TRAP), "Power down TRAP" }, + { MTRM(R_DET_LAST_VAR_TYPE), "Determine type of last var used" }, + { MTRM(R_RST_5_5), "RST 5.5 -- Bar Code Reader" }, + { MTRM(R_GET_FAC1_SIGN), "Get sign of FAC1" }, + { MTRM(R_RST_6_5), "RST 6.5 -- RS232 character pending" }, + { MTRM(R_RAM_VCTR_TBL_DRIVER), "RAM vector table driver" }, + { MTRM(R_RST_7_5), "RST 7.5 -- Timer background task" }, + { MTRM(R_BASIC_KEYWORD_TBL), "BASIC statement keyword table END to NEW" }, + { MTRM(R_FUN_KEYWORD_TBL1), "Function keyword table TAB to <" }, + { MTRM(R_FUN_KEYWORD_TBL2), "Function keyword table SGN to MID$" }, + { MTRM(R_BASIC_VECTOR_TBL), "BASIC statement vector table for END to NEW" }, + { MTRM(R_MATH_PRIORITY_TBL), "Math operator priority table" }, + { MTRM(R_BASIC_ERR_MSG_TXT), "BASIC error message text" }, + { MTRM(R_FUN_INIT_IMAGE), "Initialization image loaded to F5F0H" }, + { MTRM(R_FUN_XROM_IMAGE), "External ROM detect image loaded at F605H" }, + { MTRM(R_FUN_BASIC_STRINGS), "BASIC message strings" }, + { MTRM(R_POP_FOR_NEXT), "Pop return address for NEXT or RETURN" }, + { MTRM(R_INIT_AND_READY), "Initialize system and go to BASIC ready" }, + { MTRM(R_GEN_SN_ERROR), "Generate Syntax error" }, + { MTRM(R_GEN_d0_ERROR), "Generate /0 error" }, + { MTRM(R_GEN_NF_ERROR), "Generate NF error" }, + { MTRM(R_GEN_DD_ERROR), "Generate DD error" }, + { MTRM(R_GEN_RW_ERROR), "Generate RW error" }, + { MTRM(R_GEN_OV_ERROR), "Generate OV error" }, + { MTRM(R_GEN_MO_ERROR), "Generate MO error" }, + { MTRM(R_GEN_TM_ERROR), "Generate TM error" }, + { MTRM(R_GEN_ERR_IN_E), "Generate error in E" }, + { MTRM(R_RESTORE_JMP_BC), "Restore stack & runtime and jump to BC" }, + { MTRM(R_PRINT_BASIC_ERR), "Print BASIC error message - XX error in XXX" }, + { MTRM(R_POP_GO_BASIC_RDY), "Pop stack and vector to BASIC ready" }, + { MTRM(R_GO_BASIC_RDY_OK), "Vector to BASIC ready - print Ok" }, + { MTRM(R_GO_BASIC_RDY), "Silent vector to BASIC ready" }, + { MTRM(R_PERFORM_M_GO_RDY), "Perform operation at M and return to ready" }, + { MTRM(R_UPDATE_LINE_ADDR), "Update line addresses for current BASIC program" }, + { MTRM(R_EVAL_LIST_ARGS), "Evaluate LIST statement arguments" }, + { MTRM(R_FIND_LINE_IN_DE), "Find line number in DE" }, + { MTRM(R_FIND_LINE_DE_AT_HL), "Find line number in DE starting at HL" }, + { MTRM(R_TOKEN_COMPRESS), "Perform Token compression" }, + { MTRM(R_FOR_STMT), "FOR statement" }, + { MTRM(R_TO_STMT), "TO statement" }, + { MTRM(R_STEP_STMT), "STEP statement" }, + { MTRM(R_RUN_BASIC_PGRM), "Execute BASIC program" }, + { MTRM(R_RUN_BASIC_AT_HL), "Start executing BASIC program at HL" }, + { MTRM(R_EXEC_INST_IN_A), "Execute instruction in A), HL points to args" }, + { MTRM(R_RST_10H_INC_HL), "RST 10H routine with pre-increment of HL" }, + { MTRM(R_RST_10H), "RST 10H routine" }, + { MTRM(R_DEF_STMT), "DEF statement" }, + { MTRM(R_DEFDBL_STMT), "DEFDBL statement" }, + { MTRM(R_DEFINT_STMT), "DEFINT statement" }, + { MTRM(R_DEFSNG_STMT), "DEFSNG statement" }, + { MTRM(R_DEFSTR_STMT), "DEFSTR statement" }, + { MTRM(R_DECL_VAR_TYPE_E), "Declare variable at M to be type E" }, + { MTRM(R_GEN_FC_ERROR), "Generate FC error" }, + { MTRM(R_EVAL_LINE_NUM), "Evaluate line number text at M" }, + { MTRM(R_ASCII_TO_BIN), "Convert ASCII number at M to binary" }, + { MTRM(R_ASCII_TO_BIN_PREINC), "Convert ASCII number at M+1 to binary" }, + { MTRM(R_RUN_STMT), "RUN statement" }, + { MTRM(R_GOSUB_STMT), "GOSUB statement" }, + { MTRM(R_GOTO_STMT), "GOTO statement" }, + { MTRM(R_GEN_UL_ERROR), "Generate UL error" }, + { MTRM(R_RETURN_STMT), "RETURN statement" }, + { MTRM(R_DATA_STMT), "DATA statement" }, + { MTRM(R_REM_STMT), "REM statement" }, + { MTRM(R_LET_STMT), "LET statement" }, + { MTRM(R_ON_STMT), "ON statement" }, + { MTRM(R_ON_ERROR_STMT), "ON ERROR statement" }, + { MTRM(R_ON_KEY_STMT), "ON KEY/TIME/COM/MDM GOSUB routine" }, + { MTRM(R_ON_TIME_STMT), "ON TIME$ handler" }, + { MTRM(R_RESUME_STMT), "RESUME statement" }, + { MTRM(R_ERROR_STMT), "ERROR statement" }, + { MTRM(R_IF_STMT), "IF statement" }, + { MTRM(R_LPRINT_STMT), "LPRINT statement" }, + { MTRM(R_PRINT_STMT), "PRINT statement" }, + { MTRM(R_TAB_STMT), "TAB statement" }, + { MTRM(R_LINE_STMT), "LINE statement" }, + { MTRM(R_INPUT_NO_STMT), "INPUT # statement" }, + { MTRM(R_INPUT_STMT), "INPUT statement" }, + { MTRM(R_READ_STMT), "READ statement" }, + { MTRM(R_EVAL_BASIC_INST), "Main BASIC evaluation routine" }, + { MTRM(R_INT16_DIV), "Integer Divide FAC1=DE/HL" }, + { MTRM(R_EVAL_FUN), "Evaluate function at M" }, + { MTRM(R_ERR_FUN), "ERR function" }, + { MTRM(R_ERL_FUN), "ERL function" }, + { MTRM(R_VARPTR_FUN), "VARPTR function" }, + { MTRM(R_VARPTR_BUF_FUN), "VARPTR(#buffer) function" }, + { MTRM(R_VARPTR_VAR_FUN), "VARPTR(variable) function" }, + { MTRM(R_EVAL_VAR), "Evaluate variable" }, + { MTRM(R_CONV_M_TOUPPER), "Get char at M and convert to uppercase" }, + { MTRM(R_CONV_A_TOUPPER), "Convert A to uppercase" }, + { MTRM(R_ASCII_NUM_CONV), "ASCII num conversion - find ASCII or tokenized '+' or '-' in A" }, + { MTRM(R_NOT_FUN), "NOT function" }, + { MTRM(R_RST_28H), "RST 28H routine" }, + { MTRM(R_OR_FUN), "OR function" }, + { MTRM(R_AND_FUN), "AND function" }, + { MTRM(R_XOR_FUN), "XOR function" }, + { MTRM(R_EQV_FUN), "EQV function" }, + { MTRM(R_IMP_FUN), "IMP function" }, + { MTRM(R_LPOS_FUN), "LPOS function" }, + { MTRM(R_POS_FUN), "POS function" }, + { MTRM(R_LD_FAC1_INT), "Load integer in A into FAC1" }, + { MTRM(R_CHK_RUNNING_PGRM), "Check for running program" }, + { MTRM(R_GEN_ID_ERROR), "Generate ID error" }, + { MTRM(R_INP_FUN), "INP function" }, + { MTRM(R_OUT_STMT), "OUT statement" }, + { MTRM(R_EVAL_EXPR), "Evaluate expression at M" }, + { MTRM(R_EVAL_EXPR_PREDEC), "Evaluate expression at M-1" }, + { MTRM(R_LLIST_STMT), "LLIST statement" }, + { MTRM(R_LIST_STMT), "LIST statement" }, + { MTRM(R_BUF_TO_LCD), "Send buffer at M to screen" }, + { MTRM(R_PEEK_FUN), "PEEK function" }, + { MTRM(R_POKE_FUN), "POKE function" }, + { MTRM(R_WAIT_KEY), "Wait for key from keyboard" }, + { MTRM(R_TOGGLE_LABEL), "Toggle function key label line" }, + { MTRM(R_CHK_KEY_QUEUE), "Check keyboard queue for pending characters" }, + { MTRM(R_POWER_STMT), "POWER statement" }, + { MTRM(R_LOW_PWR_TRAP), "Normal TRAP (low power) interrupt routine" }, + { MTRM(R_POWER_DOWN), "Turn off computer" }, + { MTRM(R_POWER_CONT_STMT), "POWER CONT statement" }, + { MTRM(R_POWER_ON_STMT), "POWER ON statement" }, + { MTRM(R_OUT_CH_TO_LPT), "Output character to printer" }, + { MTRM(R_LOAD_CAS_HDR), "Start tape and load tape header" }, + { MTRM(R_GEN_IO_ERROR), "Generate I/O error" }, + { MTRM(R_DET_CAS_SYNC_HDR), "Turn cassette motor on and detect sync header" }, + { MTRM(R_CAS_MOTOR_ON), "Turn cassette motor on" }, + { MTRM(R_CAS_MOTOR_OFF), "Turn cassette motor off" }, + { MTRM(R_CAS_READ_BYTE), "Read byte from tape & update checksum" }, + { MTRM(R_CAS_WRITE_BYTE), "Write byte to tape & update checksum" }, + { MTRM(R_LCD_DCB), "LCD Device control block" }, + { MTRM(R_LCD_OPEN), "LCD and PRT file open routine" }, + { MTRM(R_LCD_OUT), "Output to LCD file" }, + { MTRM(R_POP_ALL_REGS), "Pop AF), BC), DE), HL from stack" }, + { MTRM(R_CRT_DCB), "CRT device control block" }, + { MTRM(R_RAM_DCB), "RAM device control block" }, + { MTRM(R_RAM_OPEN), "Open RAM file" }, + { MTRM(R_RAM_CLOSE), "Close RAM file" }, + { MTRM(R_RAM_OUT), "Output to RAM file" }, + { MTRM(R_RAM_IN), "Input from RAM file" }, + { MTRM(R_RAM_IO), "Special RAM file I/O" }, + { MTRM(R_CAS_DCB), "CAS device control block" }, + { MTRM(R_CAS_OPEN), "Open CAS file" }, + { MTRM(R_CAS_CLOSE), "Close CAS file" }, + { MTRM(R_CAS_OUT), "Output to CAS file" }, + { MTRM(R_CAS_IN), "Input from CAS file" }, + { MTRM(R_LPT_DCB), "LPT device control block" }, + { MTRM(R_LPT_OUT), "Output to LPT file" }, + { MTRM(R_COM_DCB), "COM device control block" }, + { MTRM(R_MDM_OPEN), "Open MDM file" }, + { MTRM(R_COM_OPEN), "Open COM file" }, + { MTRM(R_COM_CLOSE), "Close COM file" }, + { MTRM(R_COM_OUT), "Output to COM/MDM file" }, + { MTRM(R_COM_IN), "Input from COM/MDM file" }, + { MTRM(R_COM_IO), "Special COM/MDM file I/O" }, + { MTRM(R_MDM_DCB), "MDM Device control block" }, + { MTRM(R_MDM_CLOSE), "Close MDM file" }, + { MTRM(R_SET_RS232_PARAMS), "Set RS232 parameters from string at M" }, + { MTRM(R_BCR_DCB), "Wand device control block" }, + { MTRM(R_EOF_FUN), "EOF function" }, + { MTRM(R_TIME_FUN), "TIME$ function" }, + { MTRM(R_READ_TIME), "Read time and store it at M" }, + { MTRM(R_DATE_FUN), "DATE$ function" }, + { MTRM(R_DAY_FUN), "DAY function" }, + { MTRM(R_READ_DAY), "Read day and store at M" }, + { MTRM(R_UPDATE_CLK_VALUES), "Update in-memory (F923H) clock values" }, + { MTRM(R_TIME_STMT), "TIME$ statement" }, + { MTRM(R_UPDATE_CLK_CHIP), "Update clock chip from memory F923H" }, + { MTRM(R_DATE_STMT), "DATE$ statement" }, + { MTRM(R_DAY_STMT), "DAY$ statement" }, + { MTRM(R_GET_TIME_STRING), "Get time string from command line" }, + { MTRM(R_IPL_STMT), "IPL statement" }, + { MTRM(R_ERASE_IPL_PRGM), "Erase current IPL program" }, + { MTRM(R_COM_MDM_STMT), "COM and MDM statements" }, + { MTRM(R_KEY_FUN), "KEY() statement" }, + { MTRM(R_KEY_ON_OFF_STMT), "KEY STOP/ON/OFF statements" }, + { MTRM(R_DET_TIME_ARG), "Determine argument (ON/OFF/STOP) for TIME$ statement" }, + { MTRM(R_DET_DEVICE_ARG), "Determine device (KEY/TIME/COM/MDM) for ON GOSUB" }, + { MTRM(R_ONTIME_STMT), "ON TIME$ statement" }, + { MTRM(R_ONCOM_STMT), "ON COM handler" }, + { MTRM(R_RST7_5_ISR), "RST 7.5 interrupt routine" }, + { MTRM(R_KICK_PWR_OFF_WDT), "Renew automatic power-off counter" }, + { MTRM(R_KEY_STMT), "KEY statement" }, + { MTRM(R_KEY_LIST_STMT), "KEY LIST statement" }, + { MTRM(R_SEND_CHARS_TO_LCD), "Send B characters from M to the screen" }, + { MTRM(R_PSET_STMT), "PSET statement" }, + { MTRM(R_PRESET_STMT), "PRESET statement" }, + { MTRM(R_DRAW_FBOX), "Draw a filled box on LCD. Coords are on stack" }, + { MTRM(R_DRAW_BOX), "Draw an unfilled box on LCD. Coords are on stack" }, + { MTRM(R_TOKENIZE_XY), "Get (X),Y) coordinate from tokenized string at M" }, + { MTRM(R_CSRLIN_FUN), "CSRLIN function" }, + { MTRM(R_MAX_FUN), "MAX function" }, + { MTRM(R_MAXRAM_FUN), "MAXRAM function" }, + { MTRM(R_MAXFILES_FUN), "MAXFILES function" }, + { MTRM(R_HIMEM_FUN), "HIMEM function" }, + { MTRM(R_WIDTH_STMT), "WIDTH statement" }, + { MTRM(R_SOUND_STMT), "SOUND statement" }, + { MTRM(R_SOUND_OFF_STMT), "SOUND OFF statement" }, + { MTRM(R_SOUND_ON_STMT), "SOUND ON statement" }, + { MTRM(R_MOTOR_STMT), "MOTOR statement" }, + { MTRM(R_MOTOR_ON_STMT), "MOTOR ON statement" }, + { MTRM(R_MOTOR_OFF_STMT), "MOTOR OFF statement" }, + { MTRM(R_CALL_STMT), "CALL statement" }, + { MTRM(R_SCREEN_STMT), "SCREEN statement" }, + { MTRM(R_LCOPY_STMT), "LCOPY statement" }, + { MTRM(R_FILES_STMT), "FILES statement" }, + { MTRM(R_DISPLAY_CAT), "Display Catalog" }, + { MTRM(R_KILL_STMT), "KILL statement" }, + { MTRM(R_KILL_TEXT_FILE), "Kill a text file" }, + { MTRM(R_NAME_STMT), "NAME statement" }, + { MTRM(R_NEW_STMT), "NEW statement" }, + { MTRM(R_STRLEN), "Count length of string at M" }, + { MTRM(R_GET_FIND_DO_FILE), "Get .DO filename and locate in RAM directory" }, + { MTRM(R_OPEN_TEXT_FILE), "Open a text file at (FC93H)" }, + { MTRM(R_CSAVE_STMT), "CSAVE statement" }, + { MTRM(R_CAS_WRITE_BUF), "Save buffer at M to tape" }, + { MTRM(R_SAVEM_STMT), "SAVEM statement" }, + { MTRM(R_CSAVEM_STMT), "CSAVEM statement" }, + { MTRM(R_CLOAD_STMT), "CLOAD statement" }, + { MTRM(R_CAS_READ_REC), "Load record from tape and store at M" }, + { MTRM(R_GEN_VERIFY_FAIL_ERR), "Generate Verify Failed error" }, + { MTRM(R_LOADM_STMT), "LOADM and RUNM statement" }, + { MTRM(R_CLOADM_STMT), "CLOADM statement" }, + { MTRM(R_MOVE_B_BYTES), "Move B bytes from M to (DE)" }, + { MTRM(R_EXEC_CO_FILE), "Launch .CO files from MENU" }, + { MTRM(R_CAS_OPEN_OUT_BA), "Open CAS for output of BASIC files" }, + { MTRM(R_CAS_OPEN_OUT_DO), "Open CAS for output of TEXT files" }, + { MTRM(R_CAS_OPEN_OUT_CO), "Open CAS for output of CO files" }, + { MTRM(R_CAS_OPEN_IN_BA), "Open CAS for input of BASIC files" }, + { MTRM(R_CAS_OPEN_IN_DO), "Open CAS for input of TEXT files" }, + { MTRM(R_CAS_OPEN_IN_CO), "Open CAS for input of CO files" }, + { MTRM(R_STR_FUN), "STR$ function" }, + { MTRM(R_PRINT_STRING), "Print buffer at M until NULL or '\"'" }, + { MTRM(R_MOVE_L_BYTES), "Move L bytes from (BC) to (DE)" }, + { MTRM(R_LEN_FUN), "LEN function" }, + { MTRM(R_ASC_FUN), "ASC function" }, + { MTRM(R_CHR_FUN), "CHR$ function" }, + { MTRM(R_STRING_FUN), "STRING$ function" }, + { MTRM(R_SPACE_FUN), "SPACE$ function" }, + { MTRM(R_LEFT_FUN), "LEFT$ function" }, + { MTRM(R_RIGHT_FUN), "RIGHT$ function" }, + { MTRM(R_MID_FUN), "MID$ function" }, + { MTRM(R_VAL_FUN), "VAL function" }, + { MTRM(R_INSTR_FUN), "INSTR function" }, + { MTRM(R_FRE_FUN), "FRE function" }, + { MTRM(R_DBL_SUB), "Double precision subtract (FAC1=FAC1-FAC2)" }, + { MTRM(R_DBL_ADD), "Double precision addition (FAC1=FAC1+FAC2)" }, + { MTRM(R_BCD_ADD), "Add the BCD num in M to the one in (DE)" }, + { MTRM(R_DBL_MULT), "Double precision multiply (FAC1=FAC1*FAC2)" }, + { MTRM(R_DBL_DIV), "Double precision divide (FAC1=FAC1/FAC2)" }, + { MTRM(R_MOVE_C_BYTES), "Move C bytes from M to (DE)" }, + { MTRM(R_COS_FUN), "COS function" }, + { MTRM(R_SIN_FUN), "SIN function" }, + { MTRM(R_TAN_FUN), "TAN function" }, + { MTRM(R_ATN_FUN), "ATN function" }, + { MTRM(R_LOG_FUN), "LOG function" }, + { MTRM(R_SQR_FUN), "SQR function" }, + { MTRM(R_EXP_FUN), "EXP function" }, + { MTRM(R_RND_FUN), "RND function" }, + { MTRM(R_DBL_SQR), "Double precision Square (FAC1=SQR(FAC1))" }, + { MTRM(R_MULT_M_FAC2), "Double precision math (FAC1=M * FAC2))" }, + { MTRM(R_FAC2_EQ_FAC1), "Move FAC1 to FAC2" }, + { MTRM(R_FAC2_EQ_FP), "Move floating point number M to FAC2" }, + { MTRM(R_FAC1_EQ_FAC2), "Move FAC2 to FAC1" }, + { MTRM(R_FAC1_EQ_FP), "Move floating point number M to FAC1" }, + { MTRM(R_M_EQ_FAC1), "Move FAC1 to M" }, + { MTRM(R_MULT_FAC1_SQR_FAC1), "Double precision math (FAC1=FAC1*SQR(FAC1))" }, + { MTRM(R_SWAP_FAC1_FAC2), "Swap FAC1 and FAC2" }, + { MTRM(R_SQR_FAC1_MULT_TBL), "Square FAC1 & do table based math" }, + { MTRM(R_TBL_BASED_MATH), "Table based math (FAC1=(((FAC1*M)+(M+1))*(M+2)+(M+3)..." }, + { MTRM(R_PUSH_FAC2), "Push FAC2 on stack" }, + { MTRM(R_PUSH_FAC1), "Push FAC1 on stack" }, + { MTRM(R_POP_FAC2), "Pop FAC2 from stack" }, + { MTRM(R_POP_FAC1), "Pop FAC1 from stack" }, + { MTRM(R_FP_NUMBERS), "Floating point numbers for math operations " }, + { MTRM(R_FP_SHARED_NUMBERS), "Floating point num-shares 6 bytes from next number" }, + { MTRM(R_EXP_MATH_TBL), "Count of Floating point numbers to follow for EXP" }, + { MTRM(R_LOG_MATH_TBL), "Count of Floating point numbers to follow for LOG" }, + { MTRM(R_SIN_MATH_TBL), "Count of Floating point numbers to follow for SIN" }, + { MTRM(R_ATN_MATH_TBL), "Count of Floating point numbers to follow for ATN" }, + { MTRM(R_RST_30H_FUN), "RST 30H routine" }, + { MTRM(R_ABS_FUN), "ABS function" }, + { MTRM(R_SGN_FUN), "SGN function" }, + { MTRM(R_PUSH_SNGL_FAC1), "Push single precision FAC1 on stack" }, + { MTRM(R_SNGL_FAC1_EQ_M), "Load single precision at M to FAC1" }, + { MTRM(R_SNGL_FAC1_EQ_BCDE), "Load single precision in BCDE to FAC1" }, + { MTRM(R_SNGL_BCDE_EQ_FAC1), "Load single precision FAC1 to BCDE" }, + { MTRM(R_SNGL_BCDE_EQ_M), "Load single precision at M to BCDE" }, + { MTRM(R_SNGL_DECB_EQ_M), "Reverse load single precision at M to DEBC" }, + { MTRM(R_SNGL_M_EQ_FAC1), "Move single precision FAC1 to M" }, + { MTRM(R_LOAD_FAC2_FROM_M), "Move M to FAC2 using precision at (FB65H)" }, + { MTRM(R_MOVE_B_BYTES_INC), "Move B bytes from (DE) to M with increment" }, + { MTRM(R_MOVE_B_BYTES_DEC), "Move B bytes from (DE) to M with decrement" }, + { MTRM(R_SNGL_CMP_BCDE_FAC1), "Compare single precision in BCDE with FAC1" }, + { MTRM(R_SNGL_CMP_BCDE_M), "Compare single precision in BCDE with M" }, + { MTRM(R_SINT_CMP), "Compare signed integer in DE with that in HL" }, + { MTRM(R_CMP_FAC1_FAC2), "Compare double precision FAC1 with FAC2" }, + { MTRM(R_CINT_FUN), "CINT function" }, + { MTRM(R_FAC1_EQ_SINT_HL), "Load signed integer in HL to FAC1" }, + { MTRM(R_CSNG_FUN), "CSNG function" }, + { MTRM(R_CONV_SINT_SNGL), "Convert signed integer in FAC1 to single precision" }, + { MTRM(R_CONV_SINT_HL_SNGL), "Convert signed integer HL to single precision FAC1" }, + { MTRM(R_CDBL_FUN), "CDBL function" }, + { MTRM(R_FIX_FUN), "FIX function" }, + { MTRM(R_INT_FUN), "INT function" }, + { MTRM(R_SINT_SUB), "Signed integer subtract (FAC1=HL-DE)" }, + { MTRM(R_SINT_ADD), "Signed integer addition (FAC1=HL+DE)" }, + { MTRM(R_SINT_MULT), "Signed integer muliply (FAC1=HL*DE)" }, + { MTRM(R_SINT_DIV), "Signed integer divide (FAC1=DE/HL)" }, + { MTRM(R_SNGL_ADD_BCDE), "Single precision addition (FAC1=FAC1+BCDE)" }, + { MTRM(R_SNGL_ADD_FAC2), "Single precision addition (FAC1=FAC1+FAC2)" }, + { MTRM(R_SNGL_SUB), "Single precision subtract (FAC1=FAC1-BCDE)" }, + { MTRM(R_SNGL_MULT_BCDE), "Single precision multiply (FAC1=FAC1*BCDE)" }, + { MTRM(R_SNGL_MULT_FAC2), "Single precision multiply (FAC1=FAC2*FAC2)" }, + { MTRM(R_SNGL_DIV), "Single precision divide (FAC1=BCDE/FAC1)" }, + { MTRM(R_SNGL_LOAD), "Single precision load (FAC2=BCDE)" }, + { MTRM(R_ASCII_TO_DBL), "Convert ASCII number at M to double precision in FAC1" }, + { MTRM(R_ASCII_FND_e), "Found 'e' in ASCII number" }, + { MTRM(R_ASCII_FND_E), "Found 'E' in ASCII number" }, + { MTRM(R_ASCII_FND_DOT), "Found '.' in ASCII number" }, + { MTRM(R_ASCII_FND_PERC), "Found '%' in ASCII number" }, + { MTRM(R_ASCII_FND_LB), "Found '#' in ASCII number" }, + { MTRM(R_ASCII_CONV_HELPER), "Deal with single & double precision ASCII conversions" }, + { MTRM(R_ASCII_CONV_HELPER2), "Convert ASCII number that starts with a Digit" }, + { MTRM(R_PRNT_BASIC_ERR_TERM), "Finish printing BASIC ERROR message \" in \" line #" }, + { MTRM(R_PRINT_HL_ON_LCD), "Print binary number in HL at current position" }, + { MTRM(R_PRINT_FAC1), "Convert binary number in FAC1 to ASCII at M" }, + { MTRM(R_PRINT_FAC1_FORMAT), "Convert binary number in FAC1 to ASCII at M with format" }, + { MTRM(R_FAC1_EQ_ZERO), "Initialize FAC1 with 0.0 if it has no value" }, + { MTRM(R_SNGL_EXP), "Single precision exponential function" }, + { MTRM(R_DBL_EXP), "Double precision exponential function" }, + { MTRM(R_INT_EXP), "Integer exponential function" }, + { MTRM(R_TIME_ON_STMT), "TIME$ ON statement" }, + { MTRM(R_TRIG_INTR), "Trigger interrupt. HL points to interrupt table" }, + { MTRM(R_CLEAR_INTR), "Clear interrupt. HL points to interrupt table" }, + { MTRM(R_TIME_OFF_STMT), "TIME$ OFF statement" }, + { MTRM(R_TIME_STOP_STMT), "TIME$ STOP statement" }, + { MTRM(R_CLEAR_COM_INT_DEF), "Clear all COM), TIME), and KEY interrupt definitions" }, + { MTRM(R_RESTORE_STMT), "RESTORE statement" }, + { MTRM(R_STOP_STMT), "STOP statement" }, + { MTRM(R_END_STMT), "END statement" }, + { MTRM(R_CONT_STMT), "CONT sttement" }, + { MTRM(R_ISALPHA_M), "Check if M is alpha character" }, + { MTRM(R_ISALPHA_A), "Check if A is alpha character" }, + { MTRM(R_CLEAR_STMT), "CLEAR statement" }, + { MTRM(R_NEXT_STMT), "NEXT statement" }, + { MTRM(R_SEND_CRLF), "Send CRLF to screen or printer" }, + { MTRM(R_SEND_LF), "Send LF to screen or printer" }, + { MTRM(R_BEEP_STMT), "BEEP statement" }, + { MTRM(R_HOME_CURSOR), "Home cursor" }, + { MTRM(R_CLS_STMT), "CLS statement" }, + { MTRM(R_PROTECT_LABEL), "Protect line 8. An ESC T is printed" }, + { MTRM(R_UNPROT_LABEL), "Unprotect line 8. An ESC U is printed" }, + { MTRM(R_STOP_AUTO_SCROLL), "Stop automatic scrolling" }, + { MTRM(R_RESUME_AUTO_SCROLL), "Resume automatic scrolling" }, + { MTRM(R_TURN_CURSOR_ON), "Turn the cursor on" }, + { MTRM(R_TURN_CURSOR_OFF), "Turn the cursor off" }, + { MTRM(R_DEL_CUR_LINE), "Delete current line on screen" }, + { MTRM(R_INSERT_LINE), "Insert line a current line" }, + { MTRM(R_ERASE_TO_EOL), "Erase from cursor to end of line" }, + { MTRM(R_SEND_ESC_X), "Send ESC X" }, + { MTRM(R_INV_CHAR_ENABLE), "Start inverse character mode" }, + { MTRM(R_INV_CHAR_DISABLE), "Cancel inverse character mode" }, + { MTRM(R_END_ESC_SEQ), "End escape sequence" }, + { MTRM(R_CURSOR_TO_LOW_LEFT), "Send cursor to lower left of CRT" }, + { MTRM(R_SET_CURSOR_POS), "Set the current cursor position (H=Row),L=Col)" }, + { MTRM(R_ERASE_FKEY_DISP), "Erase function key display" }, + { MTRM(R_SET_DISP_FKEY), "Set and display function keys (M has key table)" }, + { MTRM(R_DISP_FKEY_LINE), "Display function key line" }, + { MTRM(R_PRINT_A_TO_LCD), "Print A to the screen" }, + { MTRM(R_CHAR_PLOT_3), "Character plotting level 3. Check new device console flag & call level 4)" }, + { MTRM(R_CHAR_PLOT_4), "Character plotting level 4. Turn off background task & call level 5" }, + { MTRM(R_CHAR_PLOT_5), "Character plotting level 5. Handle ESC sequences & call level 6" }, + { MTRM(R_LCD_OUT_DRIVER), "LCD output driver" }, + { MTRM(R_RST_20H_LKUP_TBL), "RST 20H lookup table" }, + { MTRM(R_ESC_Y), "ESC Y routine (Set cursor position)" }, + { MTRM(R_LCD_OUT_ESC_FUN), "LCD output Escape routine" }, + { MTRM(R_LCD_ESC_LKUP_TBL), "LCD Escape sequence lookup table" }, + { MTRM(R_ESC_SEQ_DRIVER), "ESCape sequence driver" }, + { MTRM(R_ESC_p_FUN), "ESC p routine (start inverse video)" }, + { MTRM(R_ESC_q_FUN), "ESC q routine (cancel inverse video)" }, + { MTRM(R_ESC_U_FUN), "ESC U routine (unprotect line 8)" }, + { MTRM(R_ESC_T_FUN), "ESC T routine (protect line 8)" }, + { MTRM(R_ESC_V_FUN), "ESC V routine (stop automatic scrolling)" }, + { MTRM(R_ESC_W_FUN), "ESC W routine (resume automatic scrolling)" }, + { MTRM(R_ESC_X_FUN), "ESC X routine" }, + { MTRM(R_ESC_C_FUN), "ESC C routine (move cursor right)" }, + { MTRM(R_ESC_D_FUN), "ESC D routine (move cursor left)" }, + { MTRM(R_BKSPACE_FUN), "Backspace routine" }, + { MTRM(R_ESC_A_FUN), "ESC A routine (move cursor up)" }, + { MTRM(R_ESC_B_FUN), "ESC B routine (move cursor down)" }, + { MTRM(R_TAB_FUN), "Tab routine" }, + { MTRM(R_LF_FUN), "Linefeed routine" }, + { MTRM(R_ESC_H_FUN), "Verticle tab and ESC H routine (home cursor)" }, + { MTRM(R_CR_FUN), "CR routine" }, + { MTRM(R_ESC_P_FUN), "ESC P routine (turn cursor on)" }, + { MTRM(R_ESC_Q_FUN), "ESC Q routine (turn cursor off)" }, + { MTRM(R_ESC_M_FUN), "ESC M routine" }, + { MTRM(R_LCD_SCROLL), "Scroll LCD screen A times at line number in L" }, + { MTRM(R_ESC_L_FUN), "ESC L routine (insert line)" }, + { MTRM(R_GET_LCD_CHAR), "Get character at (H),L) from LCD RAM)" }, + { MTRM(R_ESC_l_FUN), "ESC l routine (erase current line)" }, + { MTRM(R_ESC_K_FUN), "ESC K routine (erase to EOL)" }, + { MTRM(R_CLS_FUN), "Form Feed (0CH)), CLS), ESC E), and ESC J routine" }, + { MTRM(R_CHAR_PLOT_6), "Character plotting level 6. Save character in C to LCD RAM & call level 7" }, + { MTRM(R_ESC_J_FUN), "ESC J routine" }, + { MTRM(R_INP_DISP_LINE), "Input and display line and store" }, + { MTRM(R_INP_DISP_LINE_NO_Q), "Input and display (no \"?\") line and store" }, + { MTRM(R_INP_CTRL_C_HANDLER), "Input routine Control-C handler" }, + { MTRM(R_INP_ENTER_HANDLER), "Input routine ENTER handler" }, + { MTRM(R_INP_BKSP_HANDLER), "Input routine backspace), left arrow), CTRL-H handler" }, + { MTRM(R_INP_CTRL_U_HANDLER), "Input routine CTRL-U & X handler" }, + { MTRM(R_INP_TAB_HANDLER), "Input routine Tab handler" }, + { MTRM(R_DIM_STMT), "DIM statement" }, + { MTRM(R_FIND_VAR_ADDR), "Find address of variable at M" }, + { MTRM(R_USING_FUN), "USING function" }, + { MTRM(R_SEND_A_LCD_LPT), "Send A to screen or printer" }, + { MTRM(R_PRINT_A_EXPAND), "Print A to printer), expanding tabs if necessary" }, + { MTRM(R_SET_OUT_DEV_LCD), "Reinitialize output back to LCD" }, + { MTRM(R_LCD_CHAR_OUT_FUN), "LCD character output routine" }, + { MTRM(R_LCD_NEW_LINE), "Move LCD to blank line (send CRLF if needed)" }, + { MTRM(R_INKEY_FUN), "INKEY$ function" }, + { MTRM(R_GET_FILE_DESC), "Get file descriptor for file in A" }, + { MTRM(R_OPEN_STMT), "OPEN statement" }, + { MTRM(R_LCD_CLOSE_FUN), "LCD), CRT), and LPT file close routine" }, + { MTRM(R_RUN_STMT_PARAM), "RUN statement (with parameters)" }, + { MTRM(R_LOAD_STMT), "LOAD statement" }, + { MTRM(R_MERGE_STMT), "MERGE statement" }, + { MTRM(R_SAVE_STMT), "SAVE statement" }, + { MTRM(R_CLOSE_STMT), "CLOSE statement" }, + { MTRM(R_INPUT_FUN), "INPUT$ function" }, + { MTRM(R_CLEAR_MEM), "Zero B bytes at M" }, + { MTRM(R_LOAD_MEM), "Load B bytes at M with A" }, + { MTRM(R_PRINT_LB_INIT_FUN), "PRINT # initialization routine" }, + { MTRM(R_LINE_INPUT_STMT), "LINE INPUT # statement" }, + { MTRM(R_GEN_NM_ERR_FUN), "Generate NM error" }, + { MTRM(R_GEN_AO_ERR_FUN), "Generate AO error" }, + { MTRM(R_GEN_DS_ERR_FUN), "Generate DS error" }, + { MTRM(R_GEN_FF_ERR_FUN), "Generate FF error" }, + { MTRM(R_GEN_CF_ERR_FUN), "Generate CF error" }, + { MTRM(R_GEN_BN_ERR_FUN), "Generate BN error" }, + { MTRM(R_GEN_IE_ERR_FUN), "Generate IE error" }, + { MTRM(R_GEN_EF_ERR_FUN), "Generate EF error" }, + { MTRM(R_GEN_FL_ERR_FUN), "Generate FL error" }, + { MTRM(R_LOF_FUN), "LOF function" }, + { MTRM(R_LOC_FUN), "LOC function" }, + { MTRM(R_LFILES_FUN), "LFILES function" }, + { MTRM(R_DSKO_FUN), "DSKO$ function" }, + { MTRM(R_DSKI_FUN), "DSKI$ function" }, + { MTRM(R_DEV_NAME_TBL), "Device name table" }, + { MTRM(R_DCB_VCTR_TBL), "Device control block vector addresses table" }, + { MTRM(R_TELCOM_ENTRY), "TELCOM Entry point" }, + { MTRM(R_TELCOM_RE_ENTRY), "Re-entry point for TELCOM commands" }, + { MTRM(R_TELCOM_INST_VCTR_TBL), "TELCOM instruction vector table" }, + { MTRM(R_TELCOM_LABEL_TXT), "TELCOM label line text table" }, + { MTRM(R_TELCOM_STAT_FUN), "TELCOM STAT instruction routine" }, + { MTRM(R_PRINT_TELCOM_STAT), "Print current STAT settings" }, + { MTRM(R_SET_TELCOM_STAT), "Set STAT and return to TELCOM ready" }, + { MTRM(R_TELCOM_CALL_FUN), "TELCOM CALL instruction routine" }, + { MTRM(R_TELCOM_FIND_FUN), "TELCOM FIND instruction routine" }, + { MTRM(R_GO_OFFHOOK), "Go off-hook" }, + { MTRM(R_DISCONNECT_PHONE), "Disconnect phone line and disable modem carrier" }, + { MTRM(R_CONNECT_PHONE), "Connect phone line and enable modem carrier" }, + { MTRM(R_GO_OFFHOOK_WAIT), "Go off-hook and wait for carrier" }, + { MTRM(R_TELCOM_PAUSE), "Pause for about 2 seconds" }, + { MTRM(R_EXEC_LOGON_SEQ), "Execute logon sequence at M" }, + { MTRM(R_DIALING_FUN), "Dialing routine" }, + { MTRM(R_AUTO_LOGIN_SEQ), "Auto logon sequence" }, + { MTRM(R_DIAL_DIGIT), "Dial the digit in A & print on LCD" }, + { MTRM(R_TELCOM_TERM_FUN), "TELCOM TERM instruction routine" }, + { MTRM(R_TELCOM_DISPATCH), "TELCOM \"dispatcher\" routine" }, + { MTRM(R_TELCOM_PREV_FUN), "TELCOM PREV function routine" }, + { MTRM(R_TELCOM_FULL_FUN), "TELCOM FULL/HALF function routine" }, + { MTRM(R_TELCOM_ECHO_FUN), "TELCOM ECHO function routine" }, + { MTRM(R_TELCOM_UP_FUN), "TELCOM UP function routine" }, + { MTRM(R_TELCOM_DOWN_FUN), "TELCOM DOWN function routine" }, + { MTRM(R_TELCOM_BYE_FUN), "TELCOM BYE function routine" }, + { MTRM(R_MENU_ENTRY), "MENU Program" }, + { MTRM(R_DISP_DIR), "Display directory entries" }, + { MTRM(R_MENU_CTRL_U_HANDLER), "Handle CTRL-U key from MENU command loop" }, + { MTRM(R_MENU_CMD_LOOP), "MENU Program command loop" }, + { MTRM(R_MENU_BKSP_HANDLER), "Handle Backspace key from MENU command loop" }, + { MTRM(R_MENU_ENTER_HANDLER), "Handle ENTER key from MENU command loop" }, + { MTRM(R_EXEC_ROM_FILE), "Launch ROM command file from MENU program" }, + { MTRM(R_DISP_DIR_TYPE_C), "Display directory entries of type in register C" }, + { MTRM(R_CONV_FILENAME), "Convert filename from space padded to '.ext' format" }, + { MTRM(R_NEXT_DIR_ENTRY), "Position cursor for next directory entry" }, + { MTRM(R_CLS_PRINT_TIME_DAY), "Print time), day and date on first line of screen" }, + { MTRM(R_PRINT_TIME_DAY), "Print time),day),date on first line w/o CLS" }, + { MTRM(R_PRINT_STRING2), "Print NULL terminated string at M" }, + { MTRM(R_COPY_MEM_DE_M), "Copy A bytes from (DE) to M" }, + { MTRM(R_CMP_MEM_DE_M), "Compare string at DE with that at M (max C bytes)" }, + { MTRM(R_CLEAR_FKEY_TBL), "Clear function key definition table" }, + { MTRM(R_SET_FKEYS), "Set new function key table" }, + { MTRM(R_DISP_FKEYS), "Display function keys on 8th line" }, + { MTRM(R_SEARCH_DIR), "Search directory for filename" }, + { MTRM(R_GET_FILE_ADDR), "Get start address of file at M" }, + { MTRM(R_ADDRSS_ENTRY), "ADDRSS Entry point" }, + { MTRM(R_ADDRSS_ENTRY_W_FILE), "ADDRSS entry with (DE) pointing to filename" }, + { MTRM(R_SCHEDL_ENTRY), "SCHEDL Entry point" }, + { MTRM(R_SCHEDL_ENTRY_W_FILE), "SCHEDL entry with (DE) pointing to filename" }, + { MTRM(R_ADDRSS_FIND_FUN), "FIND instruction for ADDRSS/SCHEDL" }, + { MTRM(R_ADDRSS_LFND_FUN), "LFND instruction for ADDRSS/SCHEDL" }, + { MTRM(R_FIND_TEXT_IN_FILE), "Find text at M in the file at (DE)" }, + { MTRM(R_FIND_NEXT_LINE_IN_FILE), "Increment DE past next CRLF in text file at (DE)" }, + { MTRM(R_CHECK_FOR_CRLF), "Check next byte(s) at (DE) for CRLF" }, + { MTRM(R_ADDRSS_INST_VCTR_TBL), "ADDRSS/SCHEDL instruction vector table" }, + { MTRM(R_GET_KEY_CONV_TOUPPER), "Wait for char from keyboard & convert to uppercase" }, + { MTRM(R_SEND_CURSOR_HOME), "Home cursor" }, + { MTRM(R_PRINT_TIME_LOOP), "Print time on top line until key pressed" }, + { MTRM(R_TEXT_ENTRY), "TEXT Entry point" }, + { MTRM(R_TEXT_FKEY_TBL), "TEXT Function key table - empty" }, + { MTRM(R_EDIT_STMT), "EDIT statement" }, + { MTRM(R_WAIT_FOR_SPACE_KEY), "Wait for a space to be entered on keyboard" }, + { MTRM(R_EDIT_DO_FILE_FUN), "Edit .DO files" }, + { MTRM(R_TEXT_EDIT_LOOP), "Main TEXT edit loop" }, + { MTRM(R_TEXT_CTRL_VCTR_TBL), "TEXT control character vector table" }, + { MTRM(R_TEXT_ESC_FUN), "TEXT ESCape routine" }, + { MTRM(R_TEXT_CTRL_P_FUN), "TEXT control P routine" }, + { MTRM(R_TEXT_CTRL_I_FUN), "TEXT control I routine" }, + { MTRM(R_TEXT_CTRL_M_FUN), "TEXT control M routine" }, + { MTRM(R_TEXT_CTRL_D_FUN), "TEXT right arrow and control D routine" }, + { MTRM(R_TEXT_CTRL_X_FUN), "TEXT down arrow and control X routine" }, + { MTRM(R_TEXT_CTRL_H_FUN), "TEXT control H routine" }, + { MTRM(R_TEXT_CTRL_S_FUN), "TEXT left arrow and control S routine" }, + { MTRM(R_TEXT_CTRL_E_FUN), "TEXT up arrow and control E routine" }, + { MTRM(R_TEXT_CTRL_F_FUN), "TEXT control F routine" }, + { MTRM(R_TEXT_CTRL_A_FUN), "TEXT control A routine" }, + { MTRM(R_TEXT_CTRL_T_FUN), "TEXT control T routine" }, + { MTRM(R_TEXT_CTRL_B_FUN), "TEXT control B routine" }, + { MTRM(R_TEXT_CTRL_R_FUN), "TEXT control R routine" }, + { MTRM(R_TEXT_CTRL_Q_FUN), "TEXT control Q routine" }, + { MTRM(R_TEXT_CTRL_W_FUN), "TEXT control W routine" }, + { MTRM(R_TEXT_CTRL_Z_FUN), "TEXT control Z routine" }, + { MTRM(R_TEXT_CTRL_L_FUN), "TEXT control L routine" }, + { MTRM(R_TEXT_CTRL_C_FUN), "TEXT control C routine" }, + { MTRM(R_TEXT_GET_NEXT_BYTE), "Get next byte for TEXT Program entry" }, + { MTRM(R_TEXT_CTRL_O_FUN), "TEXT control O routine" }, + { MTRM(R_TEXT_CTRL_U_FUN), "TEXT control U routine" }, + { MTRM(R_TEXT_CTRL_N_FUN), "TEXT control N routine" }, + { MTRM(R_COPY_NULL_STRING), "Copy NULL terminated string at M to (DE)" }, + { MTRM(R_TEXT_CTRL_Y_FUN), "TEXT control Y routine" }, + { MTRM(R_TEXT_CTRL_G_FUN), "TEXT control G routine" }, + { MTRM(R_TEXT_CTRL_V_FUN), "TEXT control V routine" }, + { MTRM(R_INSERT_A_INTO_FILE), "Insert A into text file at M" }, + { MTRM(R_INSERT_SPACES), "Insert BC spaces at M" }, + { MTRM(R_DELETE_CHARS), "Delete BC characters at M" }, + { MTRM(R_MOVE_BC_BYTES_INC), "Move BC bytes from M to (DE) with increment" }, + { MTRM(R_MOVE_BC_BYTES_DEC), "Move BC bytes from M to (DE) with decrement" }, + { MTRM(R_BASIC_ENTRY), "BASIC Entry point" }, + { MTRM(R_LOAD_BASIC_FKEYS), "Copy BASIC Function key table to key definition area" }, + { MTRM(R_RE_INIT_SYSTEM), "Re-initialize system without destroying files" }, + { MTRM(R_WARM_RESET), "Warm start reset entry" }, + { MTRM(R_SEND_A_TO_LPT), "Send character in A to the printer" }, + { MTRM(R_CHECK_RS232_QUEUE), "Check RS232 queue for pending characters" }, + { MTRM(R_READ_RS232_QUEUE), "Get a character from RS232 receive queue" }, + { MTRM(R_RST_6_5_FUN), "RST 6.5 routine (RS232 receive interrupt)" }, + { MTRM(R_INC_RS232_QUEUE_IN), "Calculate address to save next RS232 character" }, + { MTRM(R_SEND_XON), "Send XON (CTRL-Q) out RS232" }, + { MTRM(R_DISABLE_XON_XOFF), "Turn off XON/XOFF protocol" }, + { MTRM(R_SEND_A_USING_XON), "Send character in A to serial port using XON/XOFF" }, + { MTRM(R_SEND_C_TO_RS232), "Send character in C to serial port" }, + { MTRM(R_XON_XOFF_HANDLER), "Handle XON/XOFF protocol" }, + { MTRM(R_SET_RS232_BAUD_RATE), "Set RS232 baud rate stored in H" }, + { MTRM(R_RS232_BAUD_TIMER_VALS), "RS232 baud rate timer values" }, + { MTRM(R_INIT_RS232_MDM), "Initialize RS232 or modem" }, + { MTRM(R_UNINIT_RS232_MDM), "Deactivate RS232 or modem" }, + { MTRM(R_CLICK_SND_PORT), "Click sound port if sound enabled" }, + { MTRM(R_CHECK_CD), "Check for carrier detect" }, + { MTRM(R_ENABLE_XON_XOFF), "Enable XON/OFF when CTRL-S / CTRL-Q sent" }, + { MTRM(R_INIT_SER_BUF_PARAMS), "Initialize serial buffer parameters" }, + { MTRM(R_CAS_WRITE_HEADER), "Write cassette header and sync byte" }, + { MTRM(R_CAS_WRITE_NO_CHKSUM), "Write char in A to cassette w/o checksum" }, + { MTRM(R_CAS_WRITE_NO_SYNC), "Write char in A to cassette w/o checksum or sync bit" }, + { MTRM(R_CAS_WRITE_BIT), "Write bit 0 of A to cassette" }, + { MTRM(R_CAS_READ_HEADER), "Read cassette header and sync byte" }, + { MTRM(R_CAS_READ_BIT), "Read Cassette port data bit" }, + { MTRM(R_CAS_COUNT_BITS), "Count and pack cassette input bits" }, + { MTRM(R_CAS_READ_NO_CHKSUM), "Read character from cassette w/o checksum" }, + { MTRM(R_CAS_REMOTE_FUN), "Cassette REMOTE routine - turn motor on or off" }, + { MTRM(R_KEYSCAN_MGT_FUN), "Keyboard scanning management routine" }, + { MTRM(R_KEY_DETECTION), "Key detection -- Determine which keys are pressed" }, + { MTRM(R_KEY_REPEAT_DET), "Key repeat detection" }, + { MTRM(R_GET_KEY_MATRIX), "Calculate key matrix position and save buffer pointer at FFA8H" }, + { MTRM(R_INIT_KEY_RPT_CNT), "Key detected - initialize repeat counter and decode" }, + { MTRM(R_KEY_DECODE), "Key decoding" }, + { MTRM(R_KEY_FIRST_IN_BUF), "Keyboard buffer management - place key in new buffer" }, + { MTRM(R_KEY_ADD_TO_BUF), "Keyboard buffer management - place subsequent key in buffer" }, + { MTRM(R_ISR_EXIT_FUN), "Interrupt exit routine (pop all regs & RET)" }, + { MTRM(R_UNSHIFTED_KEY), "Handle unshifted & non-CTRL key during key decoding" }, + { MTRM(R_ARROW_KEY), "Handle Arrow keys during key decoding" }, + { MTRM(R_CAPS_LOCK_KEY), "Handle CAPS LOCK key during key decoding" }, + { MTRM(R_NUM_KEY), "Handle NUM key during key decoding" }, + { MTRM(R_SCAN_KEYBOARD), "Scan keyboard for character (CTRL-BREAK ==> CTRL-C)" }, + { MTRM(R_ENABLE_INTERRUPTS), "Enable interrupts as normal" }, + { MTRM(R_CHK_PENDING_KEYS), "Check keyboard queue for pending characters" }, + { MTRM(R_CHK_BREAK), "Check for break or wait (CTRL-S)" }, + { MTRM(R_CHK_SHIFT_BREAK), "Check if SHIFT-BREAK is being pressed" }, + { MTRM(R_SCAN_SPECIAL_KEYS), "Scan BREAK),CAPS),NUM),CODE),GRAPH),CTRL),SHIFT & set bits in A" }, + { MTRM(R_GEN_TONE), "Produce a tone of DE freq and B duration" }, + { MTRM(R_GET_CLK_CHIP_REGS), "Copy clock chip regs to M" }, + { MTRM(R_PUT_CLK_CHIP_REGS), "Update clock chip regs from M" }, + { MTRM(R_READ_CLK_CHIP_BIT), "Read next bit from Clock Chip" }, + { MTRM(R_SET_CLK_CHIP_MODE), "Set clock chip mode" }, + { MTRM(R_BLINK_CURSOR), "Blink the cursor" }, + { MTRM(R_PLOT_POINT), "Plot (set) point (D),E) on the LCD" }, + { MTRM(R_CHAR_PLOT_7), "Character plotting level 7. Plot character in C on LCD at (H),L)" }, + { MTRM(R_CLEAR_POINT), "Clear (reset) point (D),E) on the LCD" }, + { MTRM(R_LCD_BYTE_PLOT), "Byte Plot - Send bit pattern to LCD for character" }, + { MTRM(R_ENABLE_LCD_DRIVER), "Enable LCD drivers after short delay" }, + { MTRM(R_WAIT_LCD_DRIVER), "Wait for LCD driver to be available" }, + { MTRM(R_LCD_BIT_PATTERNS), "8155 PIO chip bit patterns for LCD drivers" }, + { MTRM(R_DELAY_FUN), "Delay routine - decrement C until zero" }, + { MTRM(R_SET_INTR_1DH), "Set interrupt to 1DH" }, + { MTRM(R_BEEP_FUN), "Beep routine" }, + { MTRM(R_CLICK_SOUND_PORT), "Click sound port" }, + { MTRM(R_CHK_XTRNL_CNTRLER), "Check for optional external controller" }, + { MTRM(R_XTRNL_CNTRLER_DRIVER), "Optional external controller driver" }, + { MTRM(R_LCD_CHAR_SHAPE_TBL1), "LCD char generator shape table (20H-7FH" }, + { MTRM(R_LCD_CHAR_SHAPE_TBL2), "LCD char generator shape table (80H-FFH)" }, + { MTRM(R_KEYBOARD_CONV_MATRIX), "Keyboard conversion matrix" }, + { MTRM(R_BOOT_ROUTINE), "Boot routine" }, + { MTRM(R_COLD_BOOT), "Cold boot routine" }, + { MTRM(R_DISP_MODEL), "Display TRS-80 Model number & Free bytes on LCD" }, + { MTRM(R_DISP_FREE_BYTES), "Display number of free bytes on LCD" }, + { MTRM(R_INIT_RST_38H_TBL), "Initialize RST 38H RAM vector table" }, + { MTRM(R_CALC_FREE_RAM), "Calculate physical RAM available" }, + { MTRM(R_INIT_CLK_CHIP_REGS), "Initial clock chip register values" }, + { MTRM(R_MENU_TEXT_STRINGS), "MENU Text Strings" }, + { MTRM(R_RST_38H_DRIVER), "RST 38H RAM vector driver routine" }, + { MTRM(R_RST_5_5_VECTOR), "RST 5.5 RAM Vector" }, + { MTRM(R_RST_6_5_VECTOR), "RST 6.5 RAM Vector" }, + { MTRM(R_RST_7_5_VECTOR), "RST 7.5 RAM Vector" }, + { MTRM(R_TRAP_VECTOR), "RAM vector for TRAP interrupt" }, + { MTRM(R_DETECT_OPTION_ROM), "Detect Option ROM" }, + { MTRM(R_BASIC_RUNNING), "BASIC Program Running Flag" }, + { MTRM(R_INIT_BASIC_VARS), "Initialize BASIC Variables for new execution" }, + { MTRM(R_INIT_TEMP3), "Initialize FP_TEMP3 for new program" }, + { MTRM(R_RENUM_STMT), "RENUM Statement" }, + { MTRM(R_TEST_COM_TOKEN), "Test for COM token (ON COM Statement)" }, + { MTRM(R_CMD_STMT), "CMD Statement" }, + { MTRM(R_LOCATE_STMT), "LOCATE Statement" }, + { MTRM(R_COLOR_STMT), "COLOR Statement" }, + { MTRM(R_EXEC_STMT), "EXEC Statement" }, + { MTRM(R_BSAVE_STMT), "BSAVE Statement" }, + { MTRM(R_BLOAD_STMT), "BLOAD Statement" }, + { MTRM(R_DSKF_FUN), "DSKF Function" }, + { MTRM(R_FORMAT_FUN), "FORMAT Function" }, + { MTRM(R_PORT_90H), "Current value of OUT port 90H" }, + { MTRM(R_RST0_HOOK), "RST 0 Hook" }, + { MTRM(R_EXEC_2ND_ROM), "Hook to execute Option ROM" }, + { MTRM(R_TELCOM_FKEY_VCTR), "Main TELCOM Funciton Key Vector Table" }, + { MTRM(R_UNUSED), "Unused Space" }, + { MTRM(R_UPDATE_SYS_PTRS), "Update system pointers for .DO), .CO), vars), etc." }, + { MTRM(R_SAVE_TO_CATALOG), "Save new entry to Catalog" }, + { MTRM(R_PROC_SAVEM_ARGS), "Process SAVEM Arguments" }, + { MTRM(R_CLOAD_ONERR), "On-error return handler for CLOAD statement" }, + { MTRM(R_LOAD_CO_HEADER), "Copy .CO 6-byte header to Current Program Area" }, + { MTRM(R_MEMCPY_CALL_ARGS), "Memory copy using args following the CALL statement" }, + { MTRM(R_RST_1), "RST 1 Vector" }, + { MTRM(R_RST_2), "RST 2 Vector" }, + { MTRM(R_RST_3), "RST 3 Vector" }, + { MTRM(R_RST_4), "RST 4 Vector" }, + { MTRM(R_RST_5), "RST 5 Vector" }, + { MTRM(R_RST_6), "RST 6 Vector" }, + { MTRM(R_RST_7), "RST 7 Vector" }, + { (void *) 0, -1, "" }, }; diff --git a/src/romstrings.h b/src/romstrings.h index 01a3818..c385b9f 100644 --- a/src/romstrings.h +++ b/src/romstrings.h @@ -211,6 +211,7 @@ enum { R_KEY_BUF_CNT, R_KEY_TYPEAHEAD_BUF, R_CURSOR_BIT_PAT_BUF, + R_CUR_PROG_LOAD_ADDR, /* ROM Functions */ @@ -869,7 +870,20 @@ enum { R_RST0_HOOK, R_EXEC_2ND_ROM, R_TELCOM_FKEY_VCTR, - R_UNUSED + R_UNUSED, + R_UPDATE_SYS_PTRS, + R_SAVE_TO_CATALOG, + R_PROC_SAVEM_ARGS, + R_CLOAD_ONERR, + R_LOAD_CO_HEADER, + R_MEMCPY_CALL_ARGS, + R_RST_1, + R_RST_2, + R_RST_3, + R_RST_4, + R_RST_5, + R_RST_6, + R_RST_7 }; #ifdef __cplusplus diff --git a/src/sound.c b/src/sound.c index 8a0962a..5d04248 100644 --- a/src/sound.c +++ b/src/sound.c @@ -482,6 +482,8 @@ void sound_play_tone(int tone, int toneFreq) DWORD WINAPI EquProc(LPVOID lpParam) { + int stopCount = 0; + // Loop forever, or til time to quit. This is the audio driver thread. while (1) { @@ -503,10 +505,11 @@ DWORD WINAPI EquProc(LPVOID lpParam) if (gReqOut >= 16) gReqOut = 0; + // Start, stop or continue playing based on new frequency and current state if ((newFreq == 0))// && (gPlayTone == TONE_PLAYING)) { /* Stop the currently playing tone */ - if (gReqIn == gReqOut) + if (gReqIn == gReqOut && waveFreeBlockCount < (BLOCK_COUNT >> 1)) { gPlayTone = TONE_STOP; } diff --git a/src/tpddserverlog.cpp b/src/tpddserverlog.cpp index 51b7700..971633f 100644 --- a/src/tpddserverlog.cpp +++ b/src/tpddserverlog.cpp @@ -96,13 +96,14 @@ void cb_server_log (Fl_Widget* w, void* pOpaque) { VTTpddServerLog* pLog = (VTTpddServerLog *) pOpaque; - // Hide the window - pLog->hide(); - // If we are closing the root window, then save preferences if (pLog == gpLog) pLog->SavePreferences(); + // Hide the window + collapse_window(pLog); + pLog->hide(); + // Delete the window and set to NULL delete pLog; @@ -885,7 +886,7 @@ Called to resize the window and position to user preference settings void VTTpddServerLog::ResizeToPref(void) { if (m_x != -1 && m_y != -1 && m_w != -1 && m_h != -1) - resize(m_x, m_y, m_w, m_h); + expand_window(this, m_x, m_y, m_w, m_h); } /* From 9c17e2cf4c97b6b656d84035969cf726e5c5496d Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 5 Mar 2013 20:48:26 +0000 Subject: [PATCH 240/327] Modifications to fix compile errors and warnings under Linux with new changes posted from Windows for Disassembler mods. --- src/disassemble.cpp | 2 +- src/multieditwin.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/disassemble.cpp b/src/disassemble.cpp index caf5594..23a588d 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -1521,7 +1521,7 @@ void VTDis::Disassemble() // Determine length of this opcode op_len = gLenTable[opcode] & 0x03; - tricked_out = FALSE; + tricked_out = 0; // Print the address and opcode value to the temporary line buffer if (oldSchool) diff --git a/src/multieditwin.cpp b/src/multieditwin.cpp index 0c7d0b7..0b5e5d8 100644 --- a/src/multieditwin.cpp +++ b/src/multieditwin.cpp @@ -299,7 +299,7 @@ void Fl_Multi_Edit_Window::SaveAs(const MString& rootpath) m_tb->savefile((const char *) m_FileName); MString title = fl_filename_name((const char *) m_FileName); - title = "Disassembler - " + title; + title = (char *) "Disassembler - " + title; label((const char *) title); delete fc; From 7d85e984c5f029018c385dbe119fc7c19fa7fe95 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Thu, 7 Mar 2013 19:35:22 +0000 Subject: [PATCH 241/327] Updates to memory.c to fix reset and cold boot when in banks 2 / 3 for T200 and NEC --- VirtualT.vcproj | 5 +++-- src/disassemble.cpp | 3 +++ src/memory.c | 2 +- src/tpddserver.cpp | 2 ++ 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/VirtualT.vcproj b/VirtualT.vcproj index aadaf8f..3ee9c28 100644 --- a/VirtualT.vcproj +++ b/VirtualT.vcproj @@ -119,7 +119,8 @@ ConfigurationType="1" InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops" UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="false" + UseOfATL="1" + ATLMinimizesCRunTimeLibraryUsage="true" CharacterSet="2" > m_pRom = gStdRomDesc; + printf("sizeof VTObject = %d\n", sizeof(VTObject)); + // Allocate a disassembly type array m_pDisType = new DisType_t[65536]; diff --git a/src/memory.c b/src/memory.c index 83231e5..6b47be7 100644 --- a/src/memory.c +++ b/src/memory.c @@ -878,7 +878,7 @@ void reinit_mem(void) // for (x = ROMSIZE; x < 65536; x++) // set_memory8(x, 0); - gRamBank = 0; +// gRamBank = 0; gRomBank = 0; } diff --git a/src/tpddserver.cpp b/src/tpddserver.cpp index fc77ca1..319be8e 100644 --- a/src/tpddserver.cpp +++ b/src/tpddserver.cpp @@ -632,6 +632,8 @@ int VTTpddServer::SerGetFlags(unsigned char *flags) else *flags &= ~SER_FLAG_TX_EMPTY; + *flags |= SER_FLAG_CTS | SER_FLAG_DSR; + return SER_NO_ERROR; } From e0b4536fe03b50c05a1461c769623ec6639cdf39 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Thu, 7 Mar 2013 19:39:01 +0000 Subject: [PATCH 242/327] Fixed bug in Memory Editor save window that caused a segmentation fault, removed a debug printf, added images for TS-DOS and REX. --- src/disassemble.cpp | 2 - src/memedit.cpp | 11 + src/reximages.c | 4104 ++++++++++++++++++++++ src/tsdosimages.c | 8017 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 12132 insertions(+), 2 deletions(-) create mode 100644 src/reximages.c create mode 100644 src/tsdosimages.c diff --git a/src/disassemble.cpp b/src/disassemble.cpp index 1cf6f11..bf9ca0f 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -960,8 +960,6 @@ void VTDis::Disassemble() // Assign the RomDescription table for the model being emulated gpDis->m_pRom = gStdRomDesc; - printf("sizeof VTObject = %d\n", sizeof(VTObject)); - // Allocate a disassembly type array m_pDisType = new DisType_t[65536]; diff --git a/src/memedit.cpp b/src/memedit.cpp index f04122a..364ed6c 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -317,6 +317,10 @@ void update_length_field(const char *filename) char buffer[65536]; unsigned short start_addr; + // If the pBytes control is not created, just return + if (gDialog.pBytes == NULL) + return; + // Check for hex file len = strlen(filename); if (((filename[len-1] | 0x20) == 'x') && @@ -329,6 +333,7 @@ void update_length_field(const char *filename) if (len == 0) { strcpy(gDialog.sBytes, "Error in HEX"); + gDialog.pBytes->label(gDialog.sBytes); gDialog.pBytes->redraw_label(); return; } @@ -336,6 +341,7 @@ void update_length_field(const char *filename) { // Update Length field and End address fields sprintf(gDialog.sBytes, "%d", len); + gDialog.pBytes->label(gDialog.sBytes); gDialog.pBytes->redraw_label(); } } @@ -346,6 +352,7 @@ void update_length_field(const char *filename) if ((fd = fopen(filename, "r")) == NULL) { strcpy(gDialog.sBytes, "Error opening file"); + gDialog.pBytes->label(gDialog.sBytes); gDialog.pBytes->redraw_label(); } else @@ -355,6 +362,7 @@ void update_length_field(const char *filename) len = ftell(fd); fclose(fd); sprintf(gDialog.sBytes, "%d", len); + gDialog.pBytes->label(gDialog.sBytes); gDialog.pBytes->redraw_label(); } @@ -781,6 +789,9 @@ void cb_save_memory(Fl_Widget* w, void*) o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); gDialog.pSaveLen = new Fl_Input(120, 150, 90, 20, ""); + // We aren't using pBytes for save + gDialog.pBytes = NULL; + // Create OK and Cancel buttons rb = new Fl_Return_Button(90, 190, 75, 25, "OK"); rb->callback(load_okButton_cb); diff --git a/src/reximages.c b/src/reximages.c new file mode 100644 index 0000000..48b7976 --- /dev/null +++ b/src/reximages.c @@ -0,0 +1,4104 @@ +/* Image data for REX 4.8, M100 version */ +const unsigned char gRex148Image[] = { +0xF3, 0xC3, 0x97, 0x00, 0x52, 0x45, 0x58, 0x21, +0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xC9, 0x00, 0x00, 0x00, 0xF3, 0xCD, 0x5F, 0x00, +0xC9, 0x00, 0x00, 0x00, 0xF3, 0xCD, 0x5F, 0x00, +0xC3, 0x48, 0x00, 0x00, 0xF3, 0xCD, 0x5F, 0x00, +0xC9, 0x00, 0x00, 0x00, 0xF3, 0xCD, 0x5F, 0x00, +0x00, 0x00, 0x00, 0x52, 0x45, 0x58, 0x04, 0x08, +0xE3, 0x23, 0x23, 0xE3, 0xE5, 0x21, 0xEA, 0xFC, +0xE3, 0xE5, 0xD5, 0x38, 0x06, 0xED, 0x2B, 0x2B, +0xEB, 0xED, 0xD1, 0xE3, 0xC3, 0x81, 0x00, 0xE5, +0xD5, 0x38, 0x04, 0xED, 0x2B, 0x2B, 0x2B, 0x2B, +0xE5, 0x21, 0xEA, 0xFC, 0xD9, 0xE1, 0xD1, 0xE3, +0xC3, 0x81, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xF5, 0xE5, 0x21, 0xC8, 0x26, 0xE3, 0x3A, +0x45, 0xFF, 0xE6, 0xFE, 0xD3, 0xE8, 0xC9, 0xE5, +0x21, 0x00, 0x00, 0xE3, 0xC3, 0x81, 0x00, 0xAF, +0x32, 0xC0, 0xFC, 0xC3, 0xB3, 0x03, 0x21, 0xFE, +0x3F, 0x01, 0xFE, 0x43, 0x23, 0x23, 0x7C, 0xA8, +0xB5, 0xA9, 0xCA, 0xB7, 0x00, 0x23, 0x7E, 0x2B, +0xB6, 0xCA, 0xA4, 0x00, 0xF6, 0x01, 0xC9, 0xAF, +0xC9, 0xCD, 0x9E, 0x00, 0x7E, 0xE6, 0x3F, 0x32, +0xCC, 0xFC, 0x7E, 0xE6, 0x40, 0x32, 0xC1, 0xFC, +0x23, 0x7E, 0x32, 0xCD, 0xFC, 0xF6, 0x01, 0xC9, +0xCD, 0xAF, 0x1B, 0xCD, 0x9E, 0x00, 0xCA, 0xD0, +0x00, 0xCD, 0x6F, 0x1B, 0x23, 0xCD, 0x6F, 0x1B, +0x23, 0xC5, 0x3A, 0xCC, 0xFC, 0xE6, 0x3F, 0x47, +0x3A, 0xC1, 0xFC, 0xE6, 0x40, 0xB0, 0xC1, 0xCD, +0x5B, 0x1C, 0x23, 0x3A, 0xCD, 0xFC, 0xE6, 0x3F, +0xCD, 0x5B, 0x1C, 0xC9, 0x21, 0x62, 0xF9, 0x01, +0x0B, 0x00, 0x16, 0x1B, 0x09, 0x15, 0x7E, 0xFE, +0x48, 0xC2, 0x04, 0x01, 0x09, 0x7E, 0xFE, 0xF0, +0xC2, 0x15, 0x01, 0x36, 0x00, 0x15, 0xC2, 0x0C, +0x01, 0xCD, 0xD1, 0x1F, 0xCD, 0x59, 0x18, 0xCD, +0x46, 0xFD, 0xAF, 0x32, 0xEE, 0xFD, 0x32, 0xAA, +0xFF, 0xC9, 0x3E, 0x01, 0x21, 0x25, 0xF6, 0xC9, +0xCD, 0x44, 0x1A, 0x3A, 0xCB, 0xFC, 0xCD, 0xFA, +0x19, 0x21, 0xB1, 0x01, 0xCD, 0x30, 0x02, 0x3E, +0x00, 0x32, 0xFF, 0xFD, 0xCD, 0x9C, 0x18, 0xCD, +0x46, 0xFD, 0xCD, 0x91, 0x17, 0x3A, 0xCB, 0xFC, +0x4F, 0xCD, 0x46, 0xFD, 0xC9, 0x32, 0xD1, 0xFC, +0xCD, 0x44, 0x1A, 0x2A, 0x2D, 0xF9, 0xE5, 0xCD, +0x70, 0x17, 0x21, 0xFF, 0x7D, 0x3A, 0xCE, 0xFC, +0x4F, 0xCD, 0x46, 0xFD, 0xFE, 0x00, 0xCA, 0x77, +0x01, 0x21, 0xE7, 0x01, 0xC3, 0xED, 0x1A, 0x21, +0xC1, 0x7A, 0x3A, 0xCE, 0xFC, 0x4F, 0xCD, 0x46, +0xFD, 0xE6, 0xE0, 0x5F, 0x3A, 0xC1, 0xFA, 0xE6, +0xE0, 0xBB, 0xCA, 0x93, 0x01, 0x21, 0x07, 0x02, +0xC3, 0xED, 0x1A, 0x21, 0xCC, 0x01, 0xCD, 0x30, +0x02, 0xCD, 0x9C, 0x18, 0xCD, 0x46, 0xFD, 0xCD, +0xC9, 0x17, 0x3A, 0xD1, 0xFC, 0x4F, 0xCD, 0x46, +0xFD, 0xE1, 0x22, 0x2D, 0xF9, 0xCD, 0xC9, 0x14, +0xC9, 0x43, 0x6F, 0x70, 0x79, 0x69, 0x6E, 0x67, +0x20, 0x52, 0x41, 0x4D, 0x20, 0x74, 0x6F, 0x20, +0x49, 0x6D, 0x61, 0x67, 0x65, 0x2E, 0x2E, 0x2E, +0x2E, 0x2E, 0x2E, 0x00, 0x43, 0x6F, 0x70, 0x79, +0x69, 0x6E, 0x67, 0x20, 0x49, 0x6D, 0x61, 0x67, +0x65, 0x20, 0x74, 0x6F, 0x20, 0x52, 0x41, 0x4D, +0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x00, 0x4D, +0x6F, 0x64, 0x65, 0x6C, 0x20, 0x6D, 0x69, 0x73, +0x6D, 0x61, 0x74, 0x63, 0x68, 0x2E, 0x2E, 0x63, +0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x69, 0x6E, +0x73, 0x74, 0x61, 0x6C, 0x6C, 0x21, 0x00, 0x52, +0x41, 0x4D, 0x20, 0x73, 0x69, 0x7A, 0x65, 0x20, +0x6D, 0x69, 0x73, 0x6D, 0x61, 0x74, 0x63, 0x68, +0x2E, 0x2E, 0x2E, 0x63, 0x61, 0x6E, 0x6E, 0x6F, +0x74, 0x20, 0x69, 0x6E, 0x73, 0x74, 0x61, 0x6C, +0x6C, 0x21, 0x00, 0x3E, 0x01, 0xC3, 0x32, 0x02, +0x3E, 0x04, 0xF5, 0xE5, 0xCD, 0x3C, 0x03, 0x11, +0x08, 0x01, 0xE1, 0xC3, 0x54, 0x02, 0x3E, 0x01, +0xC3, 0x5D, 0x02, 0x3E, 0x02, 0xC3, 0x5D, 0x02, +0x3E, 0x04, 0xC3, 0x5D, 0x02, 0x3E, 0x06, 0xC3, +0x5D, 0x02, 0xAF, 0xF5, 0xEB, 0xF7, 0x7C, 0x42, +0xEB, 0xC3, 0x5E, 0x02, 0xAF, 0xF5, 0x7E, 0x23, +0xA7, 0xCA, 0x6A, 0x02, 0xF7, 0x13, 0x43, 0xC3, +0x5E, 0x02, 0xF1, 0xB7, 0xC8, 0xFE, 0x01, 0xCA, +0x8B, 0x02, 0xFE, 0x02, 0xCA, 0x7F, 0x02, 0xFE, +0x04, 0xCA, 0x42, 0x03, 0xCD, 0x42, 0x03, 0xE5, +0x21, 0x88, 0x02, 0xCD, 0x5C, 0x02, 0xE1, 0xC9, +0x0D, 0x0A, 0x00, 0x21, 0x94, 0x02, 0xCD, 0x5C, +0x02, 0xC3, 0xE5, 0x02, 0x20, 0x28, 0x59, 0x2F, +0x4E, 0x29, 0x3F, 0x20, 0x00, 0xF5, 0xF7, 0x7C, +0x42, 0xF1, 0x26, 0x00, 0x6F, 0xF7, 0xD4, 0x39, +0xC9, 0x7E, 0xF7, 0x13, 0x43, 0x23, 0x15, 0xC2, +0xA9, 0x02, 0xC9, 0xD1, 0xED, 0xE5, 0x13, 0x13, +0xED, 0x13, 0x13, 0x1A, 0x13, 0xEB, 0xE3, 0x4F, +0xEB, 0x1A, 0x77, 0x23, 0x13, 0x0D, 0xC2, 0xC1, +0x02, 0xC9, 0x06, 0xC0, 0x11, 0x81, 0xF6, 0xC3, +0x03, 0x1B, 0x3E, 0x70, 0xC3, 0xD9, 0x02, 0x3E, +0x71, 0xF7, 0x70, 0x42, 0xC9, 0x36, 0x20, 0x23, +0x05, 0xC2, 0xDD, 0x02, 0xC9, 0xCD, 0x19, 0x1B, +0xF7, 0xE9, 0x0F, 0xFE, 0x59, 0xC8, 0xFE, 0x4E, +0xCA, 0xF6, 0x02, 0xC3, 0xE5, 0x02, 0xB7, 0xC9, +0xCD, 0x46, 0xFD, 0x7A, 0xCD, 0x00, 0x03, 0x7B, +0xF5, 0x0F, 0x0F, 0x0F, 0x0F, 0xCD, 0x09, 0x03, +0xF1, 0xE6, 0x0F, 0xC6, 0x30, 0xFE, 0x3A, 0xFA, +0x14, 0x03, 0xC6, 0x07, 0xF7, 0x13, 0x43, 0xC9, +0x21, 0x07, 0x1A, 0xC3, 0x3F, 0x03, 0x21, 0x07, +0x01, 0xF7, 0x7C, 0x42, 0x21, 0x8D, 0x0E, 0xC3, +0x5C, 0x02, 0x21, 0x02, 0x01, 0xC3, 0x3F, 0x03, +0x21, 0x08, 0x20, 0xC3, 0x3F, 0x03, 0x21, 0x07, +0x01, 0xC3, 0x3F, 0x03, 0x21, 0x08, 0x01, 0xF7, +0x7C, 0x42, 0x3E, 0x4B, 0xC3, 0xD9, 0x02, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xF3, 0x3E, 0x01, 0x32, 0xC0, +0xFC, 0xC3, 0xB3, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xC3, 0x8F, 0x00, 0xF3, 0xF3, +0xCD, 0xC9, 0x14, 0xCD, 0xB9, 0x00, 0xC2, 0xA6, +0x03, 0x3E, 0x08, 0x32, 0xCC, 0xFC, 0xCD, 0xCA, +0x02, 0xF3, 0xCD, 0x25, 0x05, 0xCD, 0xC9, 0x15, +0xC3, 0x46, 0xFD, 0xF3, 0xCD, 0xC9, 0x14, 0xCD, +0x06, 0x06, 0x32, 0xC4, 0xFC, 0x21, 0x00, 0x00, +0x39, 0x22, 0xDB, 0xFC, 0xCD, 0xDC, 0x07, 0x7C, +0xFE, 0x03, 0xFA, 0x33, 0x04, 0xCD, 0x3B, 0x05, +0xF3, 0x11, 0x00, 0x00, 0x21, 0x16, 0x1F, 0xCD, +0x3D, 0x07, 0xC2, 0x81, 0x07, 0x11, 0x00, 0x80, +0x21, 0x97, 0x1F, 0xCD, 0x3D, 0x07, 0xC2, 0x81, +0x07, 0x3A, 0xC4, 0xFC, 0xB7, 0xCA, 0xF6, 0x03, +0xCD, 0x45, 0x06, 0xF7, 0xC6, 0x7E, 0xFB, 0x3A, +0xC0, 0xFC, 0xFE, 0xFF, 0xCA, 0x4E, 0x05, 0xFE, +0x01, 0xCA, 0xE6, 0x07, 0x21, 0x18, 0x04, 0xCD, +0x3E, 0x02, 0xF5, 0xF7, 0x13, 0x43, 0xCD, 0x7F, +0x02, 0xF1, 0xCA, 0xE6, 0x07, 0xC3, 0x4E, 0x05, +0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x52, 0x45, +0x58, 0x20, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, +0x72, 0x00, 0x21, 0xA0, 0x04, 0xCD, 0x43, 0x02, +0xC3, 0x42, 0x04, 0x21, 0x59, 0x04, 0xCD, 0x43, +0x02, 0xC3, 0x42, 0x04, 0x21, 0x7E, 0x04, 0xCD, +0x43, 0x02, 0xF7, 0x29, 0x42, 0xE1, 0xCD, 0x18, +0x05, 0xF3, 0xF7, 0xC6, 0x7E, 0x21, 0xC5, 0x04, +0xCD, 0x5C, 0x02, 0xCD, 0x22, 0x1B, 0xC3, 0x8F, +0x00, 0x4E, 0x6F, 0x74, 0x20, 0x65, 0x6E, 0x6F, +0x75, 0x67, 0x68, 0x20, 0x66, 0x72, 0x65, 0x65, +0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x20, +0x74, 0x6F, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, +0x20, 0x52, 0x45, 0x58, 0x2E, 0x00, 0x52, 0x45, +0x58, 0x20, 0x66, 0x69, 0x6C, 0x65, 0x73, 0x20, +0x63, 0x6F, 0x75, 0x6C, 0x64, 0x20, 0x6E, 0x6F, +0x74, 0x20, 0x62, 0x65, 0x20, 0x69, 0x6E, 0x73, +0x74, 0x61, 0x6C, 0x6C, 0x65, 0x64, 0x2E, 0x00, +0x54, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, +0x73, 0x20, 0x61, 0x20, 0x70, 0x72, 0x6F, 0x62, +0x6C, 0x65, 0x6D, 0x20, 0x72, 0x65, 0x73, 0x74, +0x6F, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x68, 0x6F, +0x6F, 0x6B, 0x73, 0x2E, 0x00, 0x50, 0x72, 0x6F, +0x62, 0x6C, 0x65, 0x6D, 0x20, 0x65, 0x6E, 0x63, +0x6F, 0x75, 0x6E, 0x74, 0x65, 0x72, 0x65, 0x64, +0x2E, 0x0D, 0x0A, 0x52, 0x45, 0x58, 0x20, 0x68, +0x61, 0x73, 0x20, 0x62, 0x65, 0x65, 0x6E, 0x20, +0x75, 0x6E, 0x69, 0x6E, 0x73, 0x74, 0x61, 0x6C, +0x6C, 0x65, 0x64, 0x2E, 0x0D, 0x0A, 0x41, 0x64, +0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x69, 0x73, +0x73, 0x75, 0x65, 0x2C, 0x20, 0x61, 0x6E, 0x64, +0x20, 0x72, 0x65, 0x2D, 0x6C, 0x61, 0x75, 0x6E, +0x63, 0x68, 0x20, 0x52, 0x45, 0x58, 0x2E, 0x00, +0x21, 0x97, 0x1F, 0xCD, 0xA7, 0x1E, 0x21, 0x16, +0x1F, 0xCD, 0xA7, 0x1E, 0xC9, 0x11, 0x48, 0x05, +0x21, 0xFF, 0xF5, 0xF3, 0x1A, 0x77, 0x13, 0x23, +0xE5, 0xED, 0xEB, 0x2A, 0xC0, 0xFA, 0x23, 0x19, +0xD1, 0xD9, 0xC9, 0xF3, 0x21, 0xFF, 0xF5, 0x36, +0xC9, 0x23, 0x11, 0x00, 0x00, 0xEB, 0xD9, 0xC9, +0xC3, 0x04, 0x00, 0xF7, 0x31, 0x42, 0xF3, 0x3A, +0xC4, 0xFC, 0xB7, 0xC4, 0xAD, 0x06, 0xC2, 0x2A, +0x04, 0xAF, 0x32, 0xC0, 0xFC, 0x32, 0xC4, 0xFC, +0xC3, 0x97, 0x03, 0xF7, 0x31, 0x42, 0xCD, 0x18, +0x05, 0x21, 0x78, 0x05, 0xCD, 0x5C, 0x02, 0xF7, +0x42, 0x72, 0xCA, 0x6F, 0x05, 0xC3, 0x8F, 0x00, +0x41, 0x6C, 0x6C, 0x20, 0x52, 0x45, 0x58, 0x20, +0x73, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, +0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x6D, 0x6F, +0x76, 0x65, 0x64, 0x2E, 0x0D, 0x0A, 0x0A, 0x50, +0x6F, 0x77, 0x65, 0x72, 0x20, 0x6F, 0x66, 0x66, +0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, 0x65, 0x6D, +0x6F, 0x76, 0x65, 0x20, 0x52, 0x45, 0x58, 0x20, +0x66, 0x72, 0x6F, 0x6D, 0x20, 0x6C, 0x61, 0x70, +0x74, 0x6F, 0x70, 0x2C, 0x0D, 0x0A, 0x6F, 0x72, +0x20, 0x66, 0x6F, 0x6C, 0x6C, 0x6F, 0x77, 0x20, +0x72, 0x65, 0x2D, 0x69, 0x6E, 0x73, 0x74, 0x61, +0x6C, 0x6C, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, +0x70, 0x72, 0x6F, 0x63, 0x65, 0x64, 0x75, 0x72, +0x65, 0x2E, 0x0D, 0x0A, 0x0A, 0x50, 0x72, 0x65, +0x73, 0x73, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, +0x65, 0x79, 0x20, 0x74, 0x6F, 0x20, 0x72, 0x65, +0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x6C, 0x61, +0x70, 0x74, 0x6F, 0x70, 0x2E, 0x00, 0x21, 0xF3, +0x7F, 0x22, 0xCF, 0xFC, 0x21, 0xDA, 0xFA, 0x22, +0xD3, 0xFC, 0x16, 0x1D, 0x1E, 0x02, 0x2A, 0xD3, +0xFC, 0x4E, 0x23, 0x46, 0x2A, 0xCF, 0xFC, 0x08, +0xC2, 0x42, 0x06, 0x2A, 0xD3, 0xFC, 0x23, 0x23, +0x22, 0xD3, 0xFC, 0x15, 0xC2, 0x16, 0x06, 0x1D, +0xCA, 0x40, 0x06, 0xE5, 0x21, 0xDB, 0x08, 0x22, +0xCF, 0xFC, 0xE1, 0x16, 0x13, 0xC3, 0x16, 0x06, +0xAF, 0xC9, 0x3E, 0x01, 0xC9, 0x21, 0xF3, 0x7F, +0x22, 0xCF, 0xFC, 0x2A, 0xB6, 0xFB, 0x22, 0xD1, +0xFC, 0x21, 0xDA, 0xFA, 0x22, 0xD3, 0xFC, 0x16, +0x1D, 0x1E, 0x02, 0x2A, 0xD3, 0xFC, 0x4E, 0x23, +0x46, 0x2A, 0xCF, 0xFC, 0x08, 0xCA, 0x87, 0x06, +0xD5, 0x2A, 0xD1, 0xFC, 0xEB, 0x2A, 0xD3, 0xFC, +0xD9, 0xD5, 0xEB, 0xED, 0xD1, 0x13, 0x13, 0xD9, +0x13, 0x13, 0xEB, 0x22, 0xD1, 0xFC, 0x2A, 0xD3, +0xFC, 0xEB, 0x2A, 0xCF, 0xFC, 0xD9, 0xD1, 0x2A, +0xD3, 0xFC, 0x23, 0x23, 0x22, 0xD3, 0xFC, 0x15, +0xC2, 0x5B, 0x06, 0x1D, 0xCA, 0xA4, 0x06, 0xE5, +0x21, 0xDB, 0x08, 0x22, 0xCF, 0xFC, 0xE1, 0x16, +0x13, 0xC3, 0x5B, 0x06, 0x2A, 0xD1, 0xFC, 0xEB, +0x21, 0xFF, 0xFF, 0xD9, 0xC9, 0x2A, 0xB6, 0xFB, +0xEB, 0x3E, 0x1D, 0xC6, 0x13, 0x47, 0x78, 0xB7, +0xFA, 0xF2, 0x06, 0xED, 0x23, 0x7C, 0xB5, 0xC8, +0x2B, 0x22, 0xCF, 0xFC, 0xC5, 0x01, 0xDA, 0xFA, +0x2A, 0xCF, 0xFC, 0x08, 0xC1, 0x7C, 0xB7, 0xC2, +0xF2, 0x06, 0x7D, 0xE6, 0xFE, 0xBD, 0xC2, 0xF2, +0x06, 0x7D, 0x0F, 0xE6, 0x7F, 0xB8, 0xF2, 0xF2, +0x06, 0x13, 0x13, 0xD5, 0xED, 0xEB, 0x2A, 0xCF, +0xFC, 0xEB, 0xD9, 0xD1, 0x13, 0x13, 0x05, 0xC3, +0xB6, 0x06, 0x3E, 0x01, 0xB7, 0xC9, 0xF7, 0x31, +0x42, 0xC3, 0xFF, 0x06, 0xCD, 0x3C, 0x03, 0x06, +0x06, 0xC5, 0xCD, 0x14, 0x07, 0xCD, 0xD2, 0x02, +0xCD, 0x14, 0x07, 0xCD, 0xD7, 0x02, 0xC1, 0x05, +0xC2, 0x01, 0x07, 0xC9, 0x11, 0x08, 0x05, 0x21, +0x1E, 0x07, 0xCD, 0x52, 0x02, 0xC9, 0x2A, 0x2A, +0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x20, +0x68, 0x6F, 0x6F, 0x6B, 0x73, 0x20, 0x69, 0x6E, +0x69, 0x74, 0x69, 0x61, 0x6C, 0x69, 0x7A, 0x65, +0x64, 0x20, 0x2A, 0x2A, 0x00, 0xD5, 0xE5, 0xCD, +0xBA, 0x1E, 0x2A, 0xCF, 0xFC, 0x7C, 0xB5, 0xCA, +0x7C, 0x07, 0xEB, 0x13, 0xED, 0x01, 0x04, 0x00, +0x09, 0xEB, 0xE1, 0x01, 0x0B, 0x00, 0x09, 0x7E, +0xD6, 0x04, 0x01, 0x06, 0x00, 0x09, 0x4F, 0x06, +0x00, 0x1A, 0x80, 0x96, 0x47, 0x23, 0x13, 0x0D, +0xC2, 0x61, 0x07, 0xE1, 0x7C, 0xB5, 0x78, 0xCA, +0x7A, 0x07, 0x85, 0x84, 0x11, 0xC0, 0xFA, 0xED, +0x94, 0x95, 0xB7, 0xC9, 0xC1, 0xC1, 0xF6, 0x01, +0xC9, 0x21, 0xA5, 0x07, 0xCD, 0x43, 0x02, 0xCD, +0x18, 0x05, 0x21, 0x16, 0x1F, 0xCD, 0xBD, 0x1D, +0xC2, 0x3C, 0x04, 0x21, 0x97, 0x1F, 0xCD, 0xBD, +0x1D, 0xC2, 0x3C, 0x04, 0x01, 0x0F, 0x00, 0xCD, +0xC5, 0x07, 0xC3, 0xE9, 0x03, 0x49, 0x6E, 0x73, +0x74, 0x61, 0x6C, 0x6C, 0x69, 0x6E, 0x67, 0x20, +0x52, 0x45, 0x58, 0x20, 0x66, 0x69, 0x6C, 0x65, +0x73, 0x20, 0x69, 0x6E, 0x20, 0x52, 0x41, 0x4D, +0x2E, 0x2E, 0x2E, 0x2E, 0x00, 0x2A, 0xC0, 0xFA, +0x23, 0xE5, 0xE5, 0x09, 0xEB, 0xED, 0xC5, 0x01, +0x01, 0x80, 0x08, 0xC1, 0xD1, 0x19, 0xEB, 0xE1, +0x09, 0xEB, 0xD9, 0xC9, 0x2A, 0xB6, 0xFB, 0x44, +0x4D, 0x2A, 0xDB, 0xFC, 0x08, 0xC9, 0xF3, 0xCD, +0xC9, 0x14, 0xCD, 0x34, 0x15, 0xCD, 0x46, 0xFD, +0xFB, 0xAF, 0x32, 0xC0, 0xFC, 0x32, 0xD9, 0xFC, +0xCD, 0x08, 0x10, 0x3E, 0x07, 0x32, 0xDF, 0xFC, +0xCD, 0xAB, 0x11, 0xCD, 0x3D, 0x13, 0xC3, 0x0C, +0x08, 0xCD, 0xB3, 0x34, 0xAF, 0x32, 0xC9, 0xFC, +0x32, 0xC8, 0xFC, 0x21, 0x09, 0x08, 0x22, 0xC2, +0xFC, 0xCD, 0xB9, 0x00, 0xCD, 0xC5, 0x11, 0xCD, +0x44, 0x34, 0xCD, 0x05, 0x09, 0xCD, 0xAF, 0x0C, +0xCD, 0x44, 0x34, 0xCD, 0xE0, 0x0D, 0xCD, 0x91, +0x0D, 0xCD, 0x7F, 0x37, 0xCD, 0x05, 0x0E, 0xAF, +0xCD, 0xA6, 0x13, 0x3E, 0xFF, 0x32, 0xC6, 0xFC, +0xCD, 0xA6, 0x12, 0xCD, 0xCC, 0x13, 0xCD, 0xB6, +0x13, 0xCD, 0xAB, 0x0D, 0xCD, 0xFF, 0x13, 0x3A, +0xC5, 0xFC, 0x32, 0xC6, 0xFC, 0xCD, 0x89, 0x13, +0x3A, 0xC9, 0xFC, 0x32, 0xC8, 0xFC, 0xF7, 0x42, +0x72, 0xCA, 0x5E, 0x08, 0xDA, 0x1D, 0x09, 0xF7, +0xE9, 0x0F, 0xFE, 0x53, 0xCA, 0x51, 0x13, 0xFE, +0x42, 0xCC, 0x5C, 0x13, 0xFE, 0x45, 0xCC, 0x71, +0x13, 0xFE, 0x49, 0xCA, 0x10, 0x11, 0xFE, 0x43, +0xCA, 0x7F, 0x0A, 0xFE, 0x09, 0xCA, 0xF9, 0x08, +0xFE, 0x0D, 0xCA, 0xA5, 0x0A, 0xCD, 0x93, 0x08, +0xC3, 0x40, 0x08, 0x21, 0xCA, 0xFC, 0x4E, 0xF5, +0x3A, 0xD9, 0xFC, 0xFE, 0x03, 0xC2, 0xA1, 0x08, +0x0D, 0x3A, 0xC9, 0xFC, 0x67, 0xF1, 0xFE, 0x1F, +0xCA, 0xC0, 0x08, 0xFE, 0x1E, 0xCA, 0xCF, 0x08, +0xFE, 0x1D, 0xCA, 0xE8, 0x08, 0xFE, 0x1C, 0xCA, +0xD8, 0x08, 0xFE, 0x20, 0xCA, 0xD8, 0x08, 0xC9, +0x7C, 0xC6, 0x03, 0xB9, 0xF0, 0xD6, 0x03, 0xFE, +0x0C, 0xF0, 0xC6, 0x04, 0xC3, 0xF5, 0x08, 0x7C, +0xFE, 0x04, 0xF8, 0xD6, 0x04, 0xC3, 0xF5, 0x08, +0x7C, 0xFE, 0x0F, 0xF2, 0xE2, 0x08, 0xB9, 0xFA, +0xE4, 0x08, 0x3E, 0xFF, 0x3C, 0xC3, 0xF5, 0x08, +0x7C, 0xFE, 0x01, 0xF2, 0xF4, 0x08, 0x79, 0xFE, +0x10, 0xFA, 0xF5, 0x08, 0x3D, 0x32, 0xC9, 0xFC, +0xC9, 0x3A, 0xD9, 0xFC, 0x3C, 0xE6, 0x03, 0x32, +0xD9, 0xFC, 0xC3, 0x0C, 0x08, 0x3A, 0xC0, 0xFC, +0xE6, 0xFD, 0x32, 0xC0, 0xFC, 0x3E, 0x1E, 0x90, +0x5F, 0x32, 0xDD, 0xFC, 0xF5, 0xCC, 0x5E, 0x0D, +0xF1, 0xFC, 0x5E, 0x0D, 0xC9, 0xB7, 0xCA, 0x6F, +0x20, 0xF5, 0x3A, 0xC5, 0xFC, 0xE6, 0x03, 0xFE, +0x03, 0xCA, 0x3F, 0x09, 0x3A, 0xC5, 0xFC, 0xE6, +0x04, 0xCA, 0x4B, 0x09, 0xF1, 0x3D, 0xCA, 0x66, +0x2F, 0x3D, 0x3D, 0x3D, 0xC3, 0x74, 0x09, 0xF1, +0x3D, 0xCA, 0x68, 0x12, 0x3D, 0xCA, 0xF1, 0x11, +0xC3, 0x3A, 0x09, 0xF1, 0x3D, 0xCA, 0xDC, 0x30, +0x3D, 0xCA, 0x9F, 0x09, 0x47, 0xCD, 0x90, 0x0C, +0x78, 0xCA, 0x61, 0x09, 0x3D, 0xCA, 0xF8, 0x09, +0x3C, 0x3D, 0x3D, 0xCA, 0x16, 0x0A, 0x47, 0x3A, +0xD9, 0xFC, 0xB7, 0x78, 0xC2, 0x74, 0x09, 0x3D, +0xCA, 0x8E, 0x38, 0x3C, 0x3D, 0x3D, 0xCA, 0x63, +0x05, 0x3D, 0xCA, 0x4B, 0x05, 0xC3, 0x55, 0x08, +0x3A, 0xDF, 0xFC, 0xFE, 0x0F, 0x79, 0xCA, 0x7C, +0x3B, 0x79, 0xE6, 0x0C, 0x0F, 0x0F, 0xC6, 0x03, +0x6F, 0x79, 0xE6, 0x03, 0x67, 0x3E, 0xF9, 0xC6, +0x0A, 0x25, 0xF2, 0x97, 0x09, 0x67, 0xC9, 0xCD, +0x44, 0x1A, 0xCD, 0x53, 0x1A, 0x3A, 0xCB, 0xFC, +0xCD, 0xFA, 0x19, 0xCD, 0x5F, 0x1A, 0x21, 0x26, +0x0C, 0xCD, 0x30, 0x02, 0x3A, 0xCE, 0xFC, 0x47, +0x3A, 0xCB, 0xFC, 0x4F, 0xF6, 0x01, 0xCD, 0xC4, +0x09, 0xC3, 0x09, 0x08, 0xF5, 0xC5, 0xCD, 0xE1, +0x09, 0xCD, 0x32, 0x1B, 0xCC, 0xAF, 0x1B, 0xC1, +0x78, 0xCD, 0x73, 0x1B, 0xE5, 0xCD, 0x60, 0x1B, +0xE1, 0x23, 0xF1, 0xCA, 0x81, 0x1C, 0xC3, 0x71, +0x1C, 0xC5, 0xCD, 0x30, 0x03, 0xCD, 0x9C, 0x18, +0xCD, 0x46, 0xFD, 0xCD, 0x76, 0x16, 0xC1, 0xD5, +0x11, 0x00, 0x80, 0xCD, 0x46, 0xFD, 0xD1, 0xC9, +0x21, 0x0A, 0x0C, 0xCD, 0x2B, 0x02, 0xC2, 0x3B, +0x08, 0xCD, 0x44, 0x1A, 0x21, 0x51, 0x0C, 0xCD, +0x30, 0x02, 0x3A, 0xCE, 0xFC, 0xCD, 0x73, 0x1B, +0xCD, 0x69, 0x1B, 0xC3, 0x09, 0x08, 0xCD, 0x72, +0x0A, 0xCA, 0x3B, 0x08, 0xCD, 0x44, 0x1A, 0x3A, +0xCE, 0xFC, 0xCD, 0x73, 0x1B, 0xE5, 0x11, 0x07, +0x00, 0x19, 0x7E, 0x32, 0xDA, 0xFC, 0xE1, 0xE5, +0xCD, 0x6F, 0x1B, 0xCD, 0x32, 0x1B, 0xCC, 0xAF, +0x1B, 0x3E, 0xFF, 0xCD, 0x7B, 0x1B, 0xE5, 0x3A, +0xCE, 0xFC, 0xCD, 0x51, 0x1B, 0x21, 0x85, 0xF6, +0xEB, 0xE1, 0xE5, 0xCD, 0x3F, 0x1B, 0xE1, 0xE5, +0xCD, 0x56, 0x1B, 0xE1, 0xD1, 0x01, 0x08, 0x00, +0x09, 0xEB, 0x09, 0xEB, 0x06, 0x04, 0x1A, 0xC5, +0xD5, 0xCD, 0x5B, 0x1C, 0xD1, 0xC1, 0x23, 0x13, +0x05, 0xC2, 0x5E, 0x0A, 0xCD, 0xCA, 0x02, 0xC3, +0x09, 0x08, 0x21, 0x62, 0x0C, 0xCD, 0x30, 0x02, +0x21, 0x08, 0x0C, 0xCD, 0x57, 0x19, 0xC9, 0x3A, +0xCE, 0xFC, 0xFE, 0xFF, 0xCA, 0x40, 0x08, 0x21, +0x6E, 0x0C, 0xCD, 0x30, 0x02, 0xCD, 0x4A, 0x15, +0x3A, 0xCE, 0xFC, 0x11, 0x00, 0x80, 0xCD, 0xF8, +0x02, 0x21, 0x81, 0x0C, 0xCD, 0x5C, 0x02, 0xCD, +0x19, 0x1B, 0xC3, 0x3B, 0x08, 0x3A, 0xD9, 0xFC, +0xFE, 0x00, 0xCA, 0x0A, 0x0B, 0xFE, 0x03, 0xCA, +0x3B, 0x08, 0x3A, 0xCE, 0xFC, 0xFE, 0xFF, 0xCA, +0x40, 0x08, 0x3A, 0xCE, 0xFC, 0x47, 0x3A, 0xCC, +0xFC, 0xB8, 0xCA, 0xE7, 0x0A, 0x21, 0xFE, 0x0B, +0xCD, 0x2B, 0x02, 0xC2, 0x3B, 0x08, 0xF7, 0x13, +0x43, 0x3A, 0xCE, 0xFC, 0x32, 0xCC, 0xFC, 0xCD, +0xD3, 0x00, 0x3A, 0xC4, 0xFC, 0xB7, 0xC4, 0xF6, +0x06, 0xCD, 0xFC, 0x00, 0xC3, 0xEF, 0x0A, 0xF3, +0x3A, 0xC4, 0xFC, 0xB7, 0xC4, 0xAD, 0x06, 0xAF, +0x32, 0xC0, 0xFC, 0x32, 0xC4, 0xFC, 0xCD, 0xCA, +0x02, 0xCD, 0x2A, 0x01, 0xE5, 0xF5, 0xF3, 0xCD, +0x25, 0x05, 0xCD, 0xEC, 0x15, 0xF1, 0xE1, 0xC3, +0x46, 0xFD, 0x3A, 0xCE, 0xFC, 0xFE, 0xFF, 0xCA, +0x8A, 0x0B, 0x47, 0x3A, 0xCD, 0xFC, 0xB8, 0xCA, +0x5A, 0x0B, 0x21, 0xCD, 0x0B, 0xCD, 0x2B, 0x02, +0xC2, 0x3B, 0x08, 0xF7, 0x13, 0x43, 0xCD, 0xBD, +0x0B, 0x3A, 0xCB, 0xFC, 0x32, 0xCD, 0xFC, 0xCD, +0xD3, 0x00, 0x3A, 0xCE, 0xFC, 0xCD, 0x55, 0x01, +0x3A, 0xCE, 0xFC, 0x32, 0xCD, 0xFC, 0xCD, 0xD3, +0x00, 0x3A, 0xC4, 0xFC, 0xB7, 0xC4, 0xFC, 0x06, +0xCD, 0xFC, 0x00, 0xAF, 0x32, 0xC4, 0xFC, 0x3E, +0xFF, 0x32, 0xC0, 0xFC, 0xF7, 0x31, 0x42, 0xC3, +0xD0, 0x03, 0x21, 0xDD, 0x0B, 0xCD, 0x2B, 0x02, +0xC2, 0x75, 0x0B, 0xF7, 0x13, 0x43, 0xCD, 0xBD, +0x0B, 0x3A, 0xCB, 0xFC, 0x32, 0xCD, 0xFC, 0xCD, +0xD3, 0x00, 0xC3, 0x09, 0x08, 0x21, 0x15, 0x0C, +0xCD, 0x2B, 0x02, 0xC2, 0x3B, 0x08, 0xF7, 0x13, +0x43, 0x3A, 0xCE, 0xFC, 0xCD, 0x55, 0x01, 0xC3, +0x41, 0x0B, 0xCD, 0x53, 0x1A, 0x21, 0xEC, 0x0B, +0xCD, 0x2B, 0x02, 0xC2, 0x3B, 0x08, 0xF7, 0x13, +0x43, 0x21, 0x62, 0x0C, 0xCD, 0x30, 0x02, 0x21, +0x08, 0x0C, 0xCD, 0x57, 0x19, 0xCA, 0x3B, 0x08, +0x21, 0x85, 0xF6, 0xCD, 0xA2, 0x0C, 0x3A, 0xCB, +0xFC, 0x32, 0xCD, 0xFC, 0xCD, 0xD3, 0x00, 0xCD, +0xCA, 0x02, 0xC3, 0x09, 0x08, 0x3A, 0xCD, 0xFC, +0xCD, 0x73, 0x1B, 0xE5, 0x23, 0xCD, 0xA2, 0x0C, +0xE1, 0xCD, 0x69, 0x1B, 0xC9, 0x53, 0x77, 0x69, +0x74, 0x63, 0x68, 0x20, 0x61, 0x6E, 0x64, 0x20, +0x65, 0x78, 0x69, 0x74, 0x00, 0x52, 0x65, 0x66, +0x72, 0x65, 0x73, 0x68, 0x20, 0x62, 0x61, 0x63, +0x6B, 0x75, 0x70, 0x00, 0x43, 0x72, 0x65, 0x61, +0x74, 0x65, 0x20, 0x6E, 0x65, 0x77, 0x20, 0x62, +0x61, 0x63, 0x6B, 0x75, 0x70, 0x00, 0x49, 0x6E, +0x73, 0x74, 0x61, 0x6C, 0x6C, 0x20, 0x52, 0x4F, +0x4D, 0x00, 0x4B, 0x69, 0x6C, 0x6C, 0x20, 0x69, +0x6D, 0x61, 0x67, 0x65, 0x00, 0x52, 0x65, 0x76, +0x65, 0x72, 0x74, 0x20, 0x74, 0x6F, 0x20, 0x62, +0x61, 0x63, 0x6B, 0x75, 0x70, 0x00, 0x43, 0x6F, +0x70, 0x79, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x6D, +0x61, 0x67, 0x65, 0x2E, 0x2E, 0x2E, 0x00, 0x52, +0x65, 0x62, 0x75, 0x69, 0x6C, 0x64, 0x69, 0x6E, +0x67, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, +0x6F, 0x72, 0x69, 0x65, 0x73, 0x2E, 0x2E, 0x2E, +0x00, 0x4B, 0x69, 0x6C, 0x6C, 0x69, 0x6E, 0x67, +0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x2E, 0x2E, +0x2E, 0x00, 0x4E, 0x65, 0x77, 0x20, 0x4E, 0x61, +0x6D, 0x65, 0x20, 0x3F, 0x20, 0x00, 0x31, 0x36, +0x20, 0x62, 0x69, 0x74, 0x20, 0x63, 0x68, 0x65, +0x63, 0x6B, 0x73, 0x75, 0x6D, 0x20, 0x3D, 0x20, +0x00, 0x20, 0x20, 0x3C, 0x61, 0x6E, 0x79, 0x20, +0x6B, 0x65, 0x79, 0x3E, 0x2E, 0x2E, 0x2E, 0x00, +0x3A, 0xCE, 0xFC, 0xC5, 0x47, 0x3A, 0xCC, 0xFC, +0xB8, 0xCA, 0xA0, 0x0C, 0x3A, 0xCD, 0xFC, 0xB8, +0xC1, 0xC9, 0xE5, 0xCD, 0x30, 0x01, 0xE1, 0xAF, +0x32, 0xDA, 0xFC, 0xCD, 0x71, 0x1C, 0xC9, 0x3E, +0xFF, 0x32, 0xCB, 0xFC, 0x11, 0x00, 0x00, 0xCD, +0x23, 0x38, 0xC2, 0xC4, 0x0C, 0x79, 0xE6, 0xFE, +0x32, 0xCB, 0xFC, 0xC9, 0x11, 0x40, 0x40, 0xCD, +0x23, 0x38, 0xC2, 0xD0, 0x0C, 0xC3, 0xD9, 0x0C, +0x11, 0x40, 0x00, 0xCD, 0x23, 0x38, 0xC2, 0xE0, +0x0C, 0x79, 0xCD, 0x3B, 0x0D, 0xC3, 0x35, 0x0D, +0x11, 0x00, 0xC0, 0xCD, 0x23, 0x38, 0xC2, 0x4F, +0x0D, 0x79, 0x32, 0xCB, 0xFC, 0x11, 0xC0, 0x40, +0xCD, 0x23, 0x38, 0xCA, 0xFF, 0x0C, 0x11, 0xC0, +0x00, 0xCD, 0x23, 0x38, 0xC2, 0x4F, 0x0D, 0xF5, +0xC5, 0x41, 0x3A, 0xCB, 0xFC, 0x4F, 0xAF, 0xCD, +0xC4, 0x09, 0xC1, 0xC5, 0x79, 0xCD, 0x3B, 0x0D, +0xC1, 0xF1, 0x3A, 0xCD, 0xFC, 0xB9, 0xC2, 0x25, +0x0D, 0x3A, 0xCB, 0xFC, 0x32, 0xCD, 0xFC, 0xCD, +0xD3, 0x00, 0xC3, 0x35, 0x0D, 0x3A, 0xCC, 0xFC, +0xB9, 0xC2, 0x35, 0x0D, 0x3A, 0xCB, 0xFC, 0x32, +0xCC, 0xFC, 0xCD, 0xD3, 0x00, 0xCD, 0x44, 0x34, +0xC3, 0xAF, 0x0C, 0xF5, 0xCD, 0x76, 0x37, 0xF1, +0xF5, 0xCD, 0x47, 0x0D, 0xF1, 0xEE, 0x01, 0xCD, +0x7B, 0x1B, 0xC0, 0xCD, 0x6F, 0x1B, 0xC9, 0x21, +0x77, 0x0D, 0xC3, 0x58, 0x0D, 0x21, 0x67, 0x0D, +0xCD, 0x30, 0x02, 0xCD, 0x22, 0x1B, 0x3A, 0xC0, +0xFC, 0xF6, 0x02, 0x32, 0xC0, 0xFC, 0xC9, 0x4E, +0x6F, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20, 0x62, +0x6C, 0x6F, 0x63, 0x6B, 0x73, 0x21, 0x00, 0x43, +0x61, 0x6E, 0x27, 0x74, 0x20, 0x66, 0x69, 0x6E, +0x64, 0x20, 0x61, 0x20, 0x62, 0x6C, 0x61, 0x6E, +0x6B, 0x20, 0x73, 0x65, 0x63, 0x74, 0x6F, 0x72, +0x21, 0x11, 0x01, 0x21, 0x21, 0xA5, 0x0D, 0xCD, +0x52, 0x02, 0x3A, 0xDD, 0xFC, 0xB7, 0xF8, 0xCD, +0xD2, 0x0D, 0xC3, 0x42, 0x03, 0x46, 0x72, 0x65, +0x65, 0x3A, 0x00, 0x3A, 0xC0, 0xFC, 0xE6, 0x04, +0xC8, 0x11, 0x07, 0x01, 0x21, 0xD9, 0x0D, 0xCD, +0x52, 0x02, 0x3A, 0xCB, 0xFC, 0xCD, 0xD2, 0x0D, +0x21, 0xDC, 0x0D, 0xCD, 0x5C, 0x02, 0x3A, 0xCE, +0xFC, 0xCD, 0xD2, 0x0D, 0x21, 0x95, 0x0E, 0xC3, +0x5C, 0x02, 0x6F, 0x26, 0x00, 0xF7, 0xD4, 0x39, +0xC9, 0x46, 0x3A, 0x00, 0x20, 0x43, 0x3A, 0x00, +0x11, 0x01, 0x0D, 0x21, 0xF9, 0x0D, 0xCD, 0x52, +0x02, 0x21, 0x2D, 0x13, 0x3A, 0xD9, 0xFC, 0x07, +0x07, 0x16, 0x00, 0x5F, 0x19, 0xCD, 0x5C, 0x02, +0xC9, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x3C, 0x54, +0x41, 0x42, 0x3E, 0x3A, 0x00, 0x0E, 0xFF, 0x0C, +0x3A, 0xCA, 0xFC, 0xB9, 0xCA, 0x4C, 0x0E, 0x21, +0xA6, 0xFD, 0xC5, 0x06, 0x00, 0x09, 0x7E, 0xC1, +0x21, 0x66, 0xFD, 0xC5, 0x87, 0x4F, 0x06, 0x00, +0x09, 0xC1, 0xEB, 0xED, 0x7E, 0xE6, 0x3F, 0xF5, +0x23, 0xC5, 0xE5, 0xCD, 0x89, 0x09, 0xF7, 0x7C, +0x42, 0xE1, 0xC1, 0x16, 0x06, 0xCD, 0xA9, 0x02, +0xF1, 0xCD, 0x93, 0x0C, 0xCA, 0x44, 0x0E, 0x3E, +0x20, 0xC3, 0x46, 0x0E, 0x3E, 0x2A, 0xF7, 0x13, +0x43, 0xC3, 0x07, 0x0E, 0x3A, 0xD9, 0xFC, 0xFE, +0x03, 0x3A, 0xCA, 0xFC, 0xCA, 0x6E, 0x0E, 0xFE, +0x10, 0xF0, 0x4F, 0xCD, 0x89, 0x09, 0xF7, 0x7C, +0x42, 0x21, 0x99, 0x0E, 0xCD, 0x5C, 0x02, 0x3A, +0xCA, 0xFC, 0xFE, 0x0F, 0xF0, 0x3C, 0x4F, 0x3E, +0x10, 0x91, 0x47, 0x78, 0xB7, 0xC8, 0xC5, 0xCD, +0x89, 0x09, 0xF7, 0x7C, 0x42, 0x21, 0x91, 0x0E, +0xCD, 0x5C, 0x02, 0xC1, 0x05, 0x0C, 0xC3, 0x73, +0x0E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x00, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x20, +0x00, 0x11, 0x02, 0x01, 0x3A, 0xD9, 0xFC, 0xFE, +0x03, 0xCA, 0x04, 0x0F, 0x3A, 0xC0, 0xFC, 0xE6, +0x10, 0xC2, 0xBF, 0x0E, 0x3A, 0xC6, 0xFC, 0xE6, +0x03, 0xFE, 0x03, 0xCA, 0x2A, 0x03, 0xC9, 0x3A, +0xD9, 0xFC, 0xB7, 0xCA, 0xDF, 0x0E, 0x3A, 0xCE, +0xFC, 0x3C, 0xCA, 0x2A, 0x03, 0xCD, 0xFE, 0x0E, +0xCD, 0x90, 0x0C, 0x21, 0xB6, 0x0F, 0xCA, 0xF8, +0x0E, 0x21, 0xA2, 0x0F, 0xC3, 0xF8, 0x0E, 0xCD, +0xFE, 0x0E, 0x3A, 0xCE, 0xFC, 0x3C, 0x21, 0xED, +0x0F, 0xCA, 0xF8, 0x0E, 0xCD, 0x90, 0x0C, 0x21, +0xDB, 0x0F, 0xCA, 0xF8, 0x0E, 0x21, 0xC8, 0x0F, +0xCD, 0x5C, 0x02, 0xC3, 0x42, 0x03, 0x21, 0xFF, +0x0F, 0xC3, 0x52, 0x02, 0x3A, 0xCE, 0xFC, 0xCD, +0x10, 0x0F, 0xCD, 0x52, 0x02, 0xC3, 0x42, 0x03, +0x21, 0x24, 0x0F, 0x3D, 0x3D, 0xC8, 0x21, 0x3F, +0x0F, 0x3D, 0xC8, 0x21, 0x61, 0x0F, 0x3D, 0xC8, +0x21, 0x7E, 0x0F, 0xC9, 0x50, 0x72, 0x69, 0x6D, +0x61, 0x72, 0x79, 0x20, 0x4D, 0x61, 0x69, 0x6E, +0x20, 0x52, 0x4F, 0x4D, 0x20, 0x30, 0x30, 0x30, +0x30, 0x2D, 0x37, 0x46, 0x46, 0x46, 0x00, 0x50, +0x72, 0x69, 0x6D, 0x61, 0x72, 0x79, 0x20, 0x4D, +0x61, 0x69, 0x6E, 0x20, 0x52, 0x4F, 0x4D, 0x20, +0x38, 0x30, 0x30, 0x30, 0x2D, 0x39, 0x46, 0x46, +0x46, 0x20, 0x28, 0x54, 0x32, 0x30, 0x30, 0x29, +0x00, 0x53, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x61, +0x72, 0x79, 0x20, 0x4D, 0x61, 0x69, 0x6E, 0x20, +0x52, 0x4F, 0x4D, 0x20, 0x30, 0x30, 0x30, 0x30, +0x2D, 0x37, 0x46, 0x46, 0x46, 0x00, 0x53, 0x65, +0x63, 0x6F, 0x6E, 0x64, 0x61, 0x72, 0x79, 0x20, +0x4D, 0x61, 0x69, 0x6E, 0x20, 0x52, 0x4F, 0x4D, +0x20, 0x38, 0x30, 0x30, 0x30, 0x2D, 0x39, 0x46, +0x46, 0x46, 0x20, 0x28, 0x54, 0x32, 0x30, 0x30, +0x29, 0x00, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, +0x20, 0x4F, 0x50, 0x54, 0x52, 0x4F, 0x4D, 0x20, +0x69, 0x6D, 0x61, 0x67, 0x65, 0x00, 0x52, 0x65, +0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, +0x20, 0x4F, 0x50, 0x54, 0x52, 0x4F, 0x4D, 0x00, +0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x20, +0x61, 0x6E, 0x64, 0x20, 0x73, 0x77, 0x69, 0x74, +0x63, 0x68, 0x00, 0x52, 0x65, 0x66, 0x72, 0x65, +0x73, 0x68, 0x20, 0x6F, 0x72, 0x20, 0x72, 0x65, +0x76, 0x65, 0x72, 0x74, 0x00, 0x43, 0x72, 0x65, +0x61, 0x74, 0x65, 0x20, 0x6E, 0x65, 0x77, 0x20, +0x62, 0x61, 0x63, 0x6B, 0x75, 0x70, 0x00, 0x3C, +0x45, 0x4E, 0x54, 0x45, 0x52, 0x3E, 0x3A, 0x00, +0xCD, 0x4A, 0x15, 0xAF, 0x11, 0x40, 0x60, 0xD5, +0xCD, 0x46, 0xFD, 0xEB, 0xE3, 0x3E, 0x01, 0xEB, +0xCD, 0x46, 0xFD, 0xE1, 0xF7, 0x18, 0x00, 0xC8, +0x21, 0x8E, 0x10, 0xCD, 0x43, 0x02, 0x21, 0xA9, +0x10, 0xCD, 0x3E, 0x02, 0x47, 0xC5, 0xF7, 0x13, +0x43, 0xCD, 0x7F, 0x02, 0x21, 0xC7, 0x10, 0xCD, +0x3E, 0x02, 0xF5, 0xF7, 0x13, 0x43, 0xCD, 0x7F, +0x02, 0xF1, 0xC1, 0x78, 0xC2, 0x26, 0x10, 0xFE, +0x59, 0xCA, 0x6E, 0x10, 0x21, 0xCC, 0x10, 0xCD, +0x43, 0x02, 0x21, 0x00, 0x40, 0xAF, 0xCD, 0x0D, +0x1B, 0xCD, 0x9C, 0x18, 0xCD, 0x46, 0xFD, 0xCD, +0x76, 0x16, 0x11, 0x40, 0x60, 0x01, 0x00, 0x01, +0xCD, 0x46, 0xFD, 0xC3, 0x74, 0x10, 0x21, 0xEE, +0x10, 0xCD, 0x48, 0x02, 0x3E, 0x01, 0x32, 0xCB, +0xFC, 0xCD, 0x0B, 0x1B, 0xCD, 0x9C, 0x18, 0xCD, +0x46, 0xFD, 0xCD, 0x76, 0x16, 0x01, 0x01, 0x00, +0x11, 0x00, 0x80, 0xC3, 0x46, 0xFD, 0x44, 0x69, +0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x69, 0x65, +0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x64, 0x69, +0x66, 0x66, 0x65, 0x72, 0x65, 0x6E, 0x74, 0x2E, +0x00, 0x4B, 0x65, 0x65, 0x70, 0x20, 0x6D, 0x61, +0x69, 0x6E, 0x20, 0x28, 0x62, 0x6C, 0x6F, 0x63, +0x6B, 0x20, 0x30, 0x29, 0x20, 0x64, 0x69, 0x72, +0x65, 0x63, 0x74, 0x6F, 0x72, 0x79, 0x00, 0x53, +0x55, 0x52, 0x45, 0x00, 0x43, 0x6F, 0x70, 0x79, +0x20, 0x62, 0x61, 0x63, 0x6B, 0x75, 0x70, 0x20, +0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, +0x79, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x69, +0x6E, 0x2E, 0x2E, 0x2E, 0x2E, 0x00, 0x43, 0x6F, +0x70, 0x79, 0x20, 0x6D, 0x61, 0x69, 0x6E, 0x20, +0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, +0x79, 0x20, 0x74, 0x6F, 0x20, 0x62, 0x61, 0x63, +0x6B, 0x75, 0x70, 0x2E, 0x2E, 0x2E, 0x2E, 0x00, +0xF7, 0x31, 0x42, 0xCD, 0x13, 0x16, 0xCD, 0x46, +0xFD, 0xC5, 0x11, 0x02, 0x02, 0x21, 0x82, 0x11, +0xCD, 0x52, 0x02, 0xCD, 0x4A, 0x15, 0xAF, 0x11, +0x00, 0x40, 0xCD, 0xF8, 0x02, 0x11, 0x03, 0x02, +0x21, 0x95, 0x11, 0xCD, 0x52, 0x02, 0xC1, 0xC5, +0x79, 0xE6, 0xC0, 0xCA, 0x44, 0x11, 0x21, 0xE8, +0x1A, 0xC3, 0x47, 0x11, 0x21, 0xE4, 0x1A, 0xCD, +0x5C, 0x02, 0x11, 0x04, 0x02, 0x21, 0xA0, 0x11, +0xCD, 0x52, 0x02, 0xC1, 0xC5, 0x79, 0xE6, 0x3C, +0x0F, 0x0F, 0x26, 0x00, 0x6F, 0xF7, 0xD4, 0x39, +0x3E, 0x28, 0xF7, 0x13, 0x43, 0xC1, 0xC5, 0x79, +0xE6, 0x03, 0x26, 0x00, 0x6F, 0xF7, 0xD4, 0x39, +0x3E, 0x29, 0xF7, 0x13, 0x43, 0xC1, 0x21, 0x81, +0x0C, 0xCD, 0x30, 0x02, 0xCD, 0x19, 0x1B, 0xC3, +0x63, 0x20, 0x53, 0x6F, 0x66, 0x74, 0x77, 0x61, +0x72, 0x65, 0x20, 0x3A, 0x34, 0x2E, 0x38, 0x2C, +0x20, 0x43, 0x53, 0x3D, 0x00, 0x4D, 0x6F, 0x64, +0x65, 0x6C, 0x20, 0x20, 0x20, 0x20, 0x3A, 0x00, +0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, +0x20, 0x3A, 0x00, 0xCD, 0xB8, 0x18, 0xCD, 0x46, +0xFD, 0xC2, 0xBC, 0x11, 0x3A, 0xC0, 0xFC, 0xF6, +0x20, 0xC3, 0xC1, 0x11, 0x3A, 0xC0, 0xFC, 0xE6, +0xDF, 0x32, 0xC0, 0xFC, 0xC9, 0x21, 0x01, 0x09, +0xF7, 0x7C, 0x42, 0xCD, 0xD2, 0x02, 0x3A, 0xC0, +0xFC, 0xE6, 0x20, 0xC2, 0xDB, 0x11, 0x3E, 0x4D, +0xC3, 0xEA, 0x11, 0x3A, 0xC1, 0xFC, 0xE6, 0x40, +0xCA, 0xE8, 0x11, 0x3E, 0x53, 0xC3, 0xEA, 0x11, +0x3E, 0x50, 0xF7, 0x13, 0x43, 0xCD, 0xD7, 0x02, +0xC9, 0xCD, 0x36, 0x03, 0x3A, 0xCE, 0xFC, 0xFE, +0x02, 0xCA, 0x01, 0x12, 0xFE, 0x04, 0xC2, 0x3B, +0x08, 0xCD, 0xCA, 0x12, 0xCA, 0x3B, 0x08, 0xCD, +0xFE, 0x12, 0xCA, 0x3B, 0x08, 0x21, 0x42, 0x12, +0xCD, 0x30, 0x02, 0x3A, 0xCE, 0xFC, 0xFE, 0x02, +0xCA, 0x21, 0x12, 0x21, 0x50, 0x12, 0xC3, 0x24, +0x12, 0x21, 0x5D, 0x12, 0xCD, 0x5C, 0x02, 0x21, +0xC7, 0x10, 0xCD, 0x3E, 0x02, 0xC2, 0x3B, 0x08, +0x3A, 0xCE, 0xFC, 0x0F, 0x3D, 0xE6, 0x01, 0x0F, +0x0F, 0x32, 0xC1, 0xFC, 0xCD, 0xD3, 0x00, 0xC3, +0x09, 0x08, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, +0x69, 0x6E, 0x67, 0x20, 0x74, 0x6F, 0x20, 0x00, +0x53, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x61, 0x72, +0x79, 0x2E, 0x2E, 0x2E, 0x00, 0x50, 0x72, 0x69, +0x6D, 0x61, 0x72, 0x79, 0x2E, 0x2E, 0x2E, 0x00, +0x3A, 0xC0, 0xFC, 0xE6, 0x20, 0xCA, 0x69, 0x2F, +0x3A, 0xCE, 0xFC, 0xE6, 0x02, 0xCA, 0x69, 0x2F, +0x21, 0x81, 0x12, 0xCD, 0x14, 0x13, 0xCA, 0x3B, +0x08, 0x52, 0x45, 0x58, 0x20, 0x4D, 0x61, 0x6E, +0x61, 0x67, 0x65, 0x72, 0x20, 0x75, 0x73, 0x65, +0x73, 0x20, 0x50, 0x72, 0x69, 0x6D, 0x61, 0x72, +0x79, 0x20, 0x61, 0x73, 0x20, 0x64, 0x65, 0x66, +0x61, 0x75, 0x6C, 0x74, 0x2E, 0x00, 0x3A, 0xC9, +0xFC, 0x4F, 0x3A, 0xCA, 0xFC, 0xB9, 0xCA, 0xC4, +0x12, 0x06, 0x00, 0x21, 0xA6, 0xFD, 0x09, 0x7E, +0x32, 0xCE, 0xFC, 0x07, 0x4F, 0x21, 0x66, 0xFD, +0x09, 0xEB, 0xED, 0xC9, 0x3E, 0xFF, 0x32, 0xCE, +0xFC, 0xC9, 0x3A, 0xC0, 0xFC, 0xE6, 0x20, 0xC0, +0x21, 0xD6, 0x12, 0xC3, 0x14, 0x13, 0x52, 0x45, +0x58, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x63, 0x6F, +0x6E, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x64, +0x20, 0x74, 0x6F, 0x20, 0x70, 0x72, 0x6F, 0x76, +0x69, 0x64, 0x65, 0x20, 0x6D, 0x61, 0x69, 0x6E, +0x20, 0x72, 0x6F, 0x6D, 0x2E, 0x00, 0x3A, 0xCE, +0xFC, 0xE6, 0x06, 0x0F, 0x3D, 0x0F, 0x0F, 0xF5, +0x3A, 0xC1, 0xFC, 0xE6, 0x40, 0x47, 0xF1, 0xB8, +0xC0, 0x21, 0x1C, 0x13, 0xCD, 0x30, 0x02, 0xCD, +0x22, 0x1B, 0xAF, 0xC9, 0x4D, 0x61, 0x69, 0x6E, +0x20, 0x52, 0x4F, 0x4D, 0x20, 0x69, 0x6E, 0x20, +0x75, 0x73, 0x65, 0x21, 0x00, 0x52, 0x41, 0x4D, +0x00, 0x52, 0x4F, 0x4D, 0x00, 0x4F, 0x53, 0x20, +0x00, 0x53, 0x59, 0x53, 0x00, 0xF7, 0x31, 0x42, +0x11, 0x01, 0x01, 0x21, 0x4A, 0x13, 0xCD, 0x52, +0x02, 0xC9, 0x52, 0x45, 0x58, 0x34, 0x2E, 0x38, +0x00, 0x3A, 0xC0, 0xFC, 0xEE, 0x08, 0x32, 0xC0, +0xFC, 0xC3, 0x0C, 0x08, 0xF5, 0x3A, 0xC0, 0xFC, +0xEE, 0x04, 0x32, 0xC0, 0xFC, 0xE6, 0x04, 0xF5, +0xCC, 0x1E, 0x03, 0xF1, 0xC4, 0xAB, 0x0D, 0xF1, +0xC9, 0xF5, 0x3A, 0xC0, 0xFC, 0xEE, 0x10, 0x32, +0xC0, 0xFC, 0xE6, 0x10, 0xCC, 0x2A, 0x03, 0x3A, +0xC5, 0xFC, 0xEE, 0x20, 0x32, 0xC5, 0xFC, 0xF1, +0xC9, 0xC5, 0xF5, 0xE5, 0xD5, 0x3A, 0xC8, 0xFC, +0x4F, 0x3A, 0xC9, 0xFC, 0xB9, 0xCA, 0xA1, 0x13, +0xC5, 0xCD, 0xA6, 0x13, 0xC1, 0x79, 0xCD, 0xA6, +0x13, 0xD1, 0xE1, 0xF1, 0xC1, 0xC9, 0x4F, 0xCD, +0x80, 0x09, 0x24, 0x22, 0x39, 0xF6, 0x3A, 0xDF, +0xFC, 0x47, 0xF7, 0xED, 0x59, 0xC9, 0x3A, 0xC5, +0xFC, 0xE6, 0x04, 0xC2, 0x18, 0x03, 0xE5, 0xCD, +0x8F, 0x1D, 0xCD, 0x34, 0x1D, 0xE1, 0xCD, 0x88, +0x1D, 0xC3, 0x1C, 0x1D, 0x3A, 0xC5, 0xFC, 0xE6, +0x30, 0x4F, 0x3A, 0xD9, 0xFC, 0xF5, 0xE6, 0x03, +0xB1, 0x4F, 0x3A, 0xCE, 0xFC, 0xFE, 0xFF, 0x79, +0xC2, 0xE5, 0x13, 0xF6, 0x04, 0x4F, 0xCD, 0x90, +0x0C, 0x79, 0xC2, 0xEF, 0x13, 0xF6, 0x08, 0x4F, +0xF1, 0xFE, 0x03, 0x79, 0xC2, 0xFB, 0x13, 0xEE, +0x10, 0xF6, 0x04, 0x32, 0xC5, 0xFC, 0xC9, 0x2A, +0xC5, 0xFC, 0x7D, 0xBC, 0xC8, 0xCD, 0xA1, 0x0E, +0xC3, 0x0B, 0x14, 0x21, 0x08, 0x01, 0xF7, 0x7C, +0x42, 0x21, 0x8A, 0x14, 0xCD, 0x5C, 0x02, 0x3A, +0xC5, 0xFC, 0xE6, 0x04, 0xCA, 0x53, 0x14, 0x21, +0x90, 0x14, 0xCD, 0x5C, 0x02, 0x3A, 0xC5, 0xFC, +0xE6, 0x03, 0xFE, 0x03, 0xCA, 0x4A, 0x14, 0x21, +0x93, 0x0E, 0xCD, 0x5C, 0x02, 0x21, 0x93, 0x0E, +0xCD, 0x5C, 0x02, 0x21, 0x93, 0x0E, 0xCD, 0x5C, +0x02, 0x21, 0x93, 0x0E, 0xCD, 0x5C, 0x02, 0xC3, +0x83, 0x14, 0x21, 0x96, 0x14, 0xCD, 0x5C, 0x02, +0xC3, 0x35, 0x14, 0x21, 0x9C, 0x14, 0xCD, 0x5C, +0x02, 0x3A, 0xC5, 0xFC, 0xE6, 0x08, 0xC2, 0x6A, +0x14, 0x21, 0xA7, 0x14, 0xCD, 0x5C, 0x02, 0xC3, +0x70, 0x14, 0x21, 0x93, 0x0E, 0xCD, 0x5C, 0x02, +0x21, 0xAD, 0x14, 0xCD, 0x5C, 0x02, 0x3A, 0xD9, +0xFC, 0xB7, 0xC2, 0x41, 0x14, 0x21, 0xB3, 0x14, +0xCD, 0x5C, 0x02, 0x21, 0xB9, 0x14, 0xCD, 0x5C, +0x02, 0xC9, 0x48, 0x65, 0x6C, 0x70, 0x20, 0x00, +0x4C, 0x6F, 0x61, 0x64, 0x20, 0x00, 0x55, 0x73, +0x65, 0x20, 0x20, 0x00, 0x53, 0x61, 0x76, 0x65, +0x20, 0x43, 0x6F, 0x70, 0x79, 0x20, 0x00, 0x4B, +0x69, 0x6C, 0x6C, 0x20, 0x00, 0x4E, 0x61, 0x6D, +0x65, 0x20, 0x00, 0x46, 0x69, 0x6C, 0x65, 0x20, +0x00, 0x44, 0x65, 0x49, 0x6E, 0x20, 0x45, 0x78, +0x69, 0x74, 0x00, 0x53, 0x69, 0x7A, 0x65, 0x20, +0x00, 0xCD, 0xB3, 0x02, 0xD2, 0x14, 0xE4, 0xFC, +0x62, 0xC9, 0x39, 0x38, 0x4E, 0x31, 0x44, 0x00, +0xF5, 0x3A, 0x45, 0xFF, 0xF6, 0x01, 0xD3, 0xE8, +0xF1, 0xC9, 0xF5, 0x3A, 0x45, 0xFF, 0xE6, 0xFE, +0xD3, 0xE8, 0xF1, 0xC9, 0xE5, 0xF5, 0x21, 0x00, +0x00, 0x7E, 0x7E, 0x7E, 0xF1, 0x2E, 0xB8, 0x6E, +0x2E, 0xF2, 0x6E, 0x2E, 0x34, 0x6E, 0x2E, 0xB0, +0x6E, 0x2E, 0x31, 0x6E, 0x2E, 0xBF, 0x6E, 0xE1, +0xC9, 0xE5, 0x21, 0x01, 0x00, 0x6E, 0x6F, 0x7E, +0xE1, 0xC9, 0x21, 0xAA, 0x0A, 0x7E, 0x7E, 0x21, +0x55, 0x05, 0x7E, 0x7E, 0x3A, 0xAA, 0x0A, 0x3A, +0xA0, 0x0A, 0x3A, 0x06, 0x00, 0x62, 0x6B, 0x7E, +0x68, 0x7E, 0x21, 0x03, 0x00, 0x7E, 0x17, 0x7E, +0xD2, 0x3F, 0xFD, 0xC9, 0xCD, 0xB3, 0x02, 0x3D, +0x15, 0x46, 0xFD, 0x0D, 0xC9, 0xF3, 0xCD, 0xFE, +0xFC, 0xAF, 0xCD, 0x1B, 0xFD, 0x3A, 0x00, 0x00, +0xFB, 0xC9, 0xCD, 0xB3, 0x02, 0x53, 0x15, 0x46, +0xFD, 0x34, 0xC9, 0xF3, 0xCD, 0xFE, 0xFC, 0xCD, +0x1B, 0xFD, 0x21, 0x00, 0x00, 0x7E, 0x39, 0x22, +0xD7, 0xFC, 0x63, 0x2E, 0x00, 0xF9, 0x7A, 0x06, +0x00, 0xD1, 0x4A, 0x09, 0x4B, 0x09, 0x38, 0x00, +0xBA, 0xC2, 0x5C, 0xFD, 0xEB, 0x2A, 0xD7, 0xFC, +0xF9, 0xD5, 0xCD, 0xFE, 0xFC, 0xAF, 0xCD, 0x1B, +0xFD, 0x3A, 0x00, 0x00, 0xD1, 0xFB, 0xC9, 0xCD, +0xB3, 0x02, 0x90, 0x15, 0x46, 0xFD, 0x39, 0xC9, +0xF3, 0xCD, 0xFE, 0xFC, 0xCD, 0x1B, 0xFD, 0x21, +0x00, 0x00, 0x7E, 0x39, 0x22, 0xD7, 0xFC, 0x21, +0x00, 0x00, 0xF9, 0x01, 0x01, 0x00, 0x11, 0x00, +0xC0, 0xAF, 0xE1, 0x09, 0xD2, 0x6C, 0xFD, 0x13, +0xBA, 0xC2, 0x60, 0xFD, 0x3E, 0xFF, 0x2A, 0xD7, +0xFC, 0xF9, 0x3C, 0xF5, 0xCD, 0xFE, 0xFC, 0xAF, +0xCD, 0x1B, 0xFD, 0x3A, 0x00, 0x00, 0xF1, 0xFB, +0xC9, 0xCD, 0xB3, 0x02, 0xD2, 0x15, 0x46, 0xFD, +0x1A, 0xC9, 0xF3, 0xCD, 0xFE, 0xFC, 0x3A, 0xCC, +0xFC, 0xE6, 0x3F, 0x47, 0x3A, 0xC1, 0xFC, 0xE6, +0x40, 0xB0, 0xCD, 0x1B, 0xFD, 0x3A, 0x00, 0x00, +0xCD, 0xF4, 0xFC, 0xC7, 0xCD, 0xB3, 0x02, 0xF5, +0x15, 0x46, 0xFD, 0x1E, 0xC9, 0xF3, 0xE5, 0xF5, +0xCD, 0xFE, 0xFC, 0x3A, 0xCC, 0xFC, 0xE6, 0x3F, +0x47, 0x3A, 0xC1, 0xFC, 0xE6, 0x40, 0xB0, 0xCD, +0x1B, 0xFD, 0x3A, 0x00, 0x00, 0xCD, 0xF4, 0xFC, +0xF1, 0xE1, 0xE9, 0xCD, 0xB3, 0x02, 0x1C, 0x16, +0x46, 0xFD, 0x15, 0xC9, 0xF3, 0xF5, 0xCD, 0xFE, +0xFC, 0x21, 0x03, 0x00, 0x46, 0x7E, 0x21, 0x07, +0x00, 0x4E, 0x7E, 0x3A, 0x00, 0x00, 0xF1, 0xFB, +0xC9, 0xCD, 0xB3, 0x02, 0x3A, 0x16, 0x46, 0xFD, +0x3C, 0xC9, 0xF3, 0xCD, 0xFE, 0xFC, 0xCD, 0x1B, +0xFD, 0xE5, 0x21, 0xAA, 0x0A, 0x7E, 0x7E, 0x21, +0x55, 0x05, 0x7E, 0x7E, 0x3A, 0xAA, 0x00, 0x3A, +0x80, 0x0A, 0x21, 0xAA, 0x0A, 0x7E, 0x7E, 0x21, +0x55, 0x05, 0x7E, 0x7E, 0x3A, 0x06, 0x00, 0xE1, +0x7E, 0x2E, 0x30, 0x7E, 0x3E, 0x13, 0x3D, 0xC2, +0x72, 0xFD, 0xCD, 0x3C, 0xFD, 0xAF, 0xCD, 0x1B, +0xFD, 0x3A, 0x00, 0x00, 0xFB, 0xC9, 0xCD, 0xB3, +0x02, 0x7F, 0x16, 0x46, 0xFD, 0x7D, 0xC9, 0xF3, +0x63, 0x2E, 0x00, 0x22, 0xCF, 0xFC, 0x7A, 0x32, +0xB2, 0xFD, 0x78, 0x32, 0x63, 0xFD, 0x79, 0x32, +0x87, 0xFD, 0x26, 0x00, 0x39, 0x22, 0xD7, 0xFC, +0xCD, 0xFE, 0xFC, 0x3E, 0x00, 0xCD, 0x1B, 0xFD, +0x3A, 0x00, 0x00, 0x21, 0x37, 0xF7, 0xF9, 0x2A, +0xCF, 0xFC, 0xEB, 0xED, 0xE5, 0x13, 0x13, 0x7B, +0xE6, 0x7F, 0xC2, 0x72, 0xFD, 0xEB, 0x22, 0xCF, +0xFC, 0x22, 0xD1, 0xFC, 0xCD, 0xFE, 0xFC, 0x3E, +0x00, 0xCD, 0x1B, 0xFD, 0x2A, 0xCF, 0xFC, 0xEB, +0xC1, 0x1B, 0xCD, 0x24, 0xFD, 0x41, 0x1B, 0xCD, +0x24, 0xFD, 0x7B, 0xE6, 0x7F, 0xC2, 0x8F, 0xFD, +0x2A, 0xD1, 0xFC, 0x22, 0xCF, 0xFC, 0x7C, 0xE6, +0x03, 0xB5, 0xC2, 0xB0, 0xFD, 0x3E, 0xFF, 0xD3, +0xFF, 0x7C, 0xFE, 0x80, 0xC2, 0x62, 0xFD, 0x2A, +0xD7, 0xFC, 0xF9, 0xAF, 0xCD, 0x1B, 0xFD, 0x3A, +0x00, 0x00, 0xFB, 0xC9, 0xCD, 0xB3, 0x02, 0x05, +0x17, 0x46, 0xFD, 0x20, 0xC9, 0xF3, 0xCD, 0xFE, +0xFC, 0x79, 0xCD, 0x1B, 0xFD, 0x0E, 0x80, 0xEB, +0x46, 0xE5, 0xCD, 0x24, 0xFD, 0xE1, 0x23, 0x13, +0x0D, 0xC2, 0x51, 0xFD, 0xAF, 0xCD, 0x1B, 0xFD, +0x3A, 0x00, 0x00, 0xEB, 0xC9, 0xCD, 0xB3, 0x02, +0x2E, 0x17, 0x46, 0xFD, 0x20, 0xC9, 0xF3, 0x06, +0x80, 0xCD, 0xFE, 0xFC, 0x79, 0xCD, 0x1B, 0xFD, +0x3A, 0x00, 0x00, 0x7E, 0x12, 0x23, 0x13, 0x05, +0xC2, 0x53, 0xFD, 0xCD, 0xFE, 0xFC, 0xAF, 0xCD, +0x1B, 0xFD, 0x3A, 0x00, 0x00, 0xC9, 0xCD, 0xB3, +0x02, 0x57, 0x17, 0x46, 0xFD, 0x19, 0xC9, 0xF3, +0xF5, 0xE5, 0xCD, 0xFE, 0xFC, 0x79, 0xCD, 0x1B, +0xFD, 0xD1, 0xF1, 0x47, 0xCD, 0x24, 0xFD, 0xAF, +0xCD, 0x1B, 0xFD, 0x3A, 0x00, 0x00, 0xFB, 0xC9, +0xCD, 0xB3, 0x02, 0x79, 0x17, 0x46, 0xFD, 0x18, +0xC9, 0xF3, 0xCD, 0xFE, 0xFC, 0x79, 0xCD, 0x1B, +0xFD, 0x3A, 0x04, 0x00, 0x7E, 0xF5, 0x7E, 0xAF, +0xCD, 0x1B, 0xFD, 0x3A, 0x00, 0x00, 0xF1, 0xFB, +0xC9, 0xCD, 0xB3, 0x02, 0x9A, 0x17, 0x46, 0xFD, +0x2F, 0xC9, 0xF3, 0xCD, 0xFE, 0xFC, 0x79, 0xCD, +0x1B, 0xFD, 0x11, 0x00, 0x00, 0x21, 0x00, 0x80, +0x46, 0xE5, 0xCD, 0x24, 0xFD, 0xE1, 0x13, 0x23, +0x7C, 0xE6, 0x03, 0xB5, 0xC2, 0x67, 0xFD, 0x3E, +0xFF, 0xD3, 0xFF, 0x7D, 0xB4, 0xC2, 0x54, 0xFD, +0xAF, 0xCD, 0x1B, 0xFD, 0x3A, 0x00, 0x00, 0xFB, +0xC9, 0xCD, 0xB3, 0x02, 0xD2, 0x17, 0x46, 0xFD, +0x87, 0xC9, 0xF3, 0xCD, 0xFE, 0xFC, 0x79, 0xCD, +0x1B, 0xFD, 0x3A, 0x00, 0x00, 0x38, 0x00, 0x42, +0x4B, 0x2A, 0xDB, 0xFC, 0xE5, 0x08, 0x44, 0x4D, +0x22, 0xD7, 0xFC, 0xE1, 0x11, 0xFE, 0xFD, 0x0C, +0x2B, 0x0D, 0xCA, 0x70, 0xFD, 0x7E, 0x12, 0x2B, +0x1B, 0xC3, 0x65, 0xFD, 0x2E, 0x00, 0x1E, 0x00, +0x3A, 0xC1, 0xFA, 0xE6, 0xE0, 0x67, 0xE6, 0x60, +0x57, 0x01, 0xC0, 0xFC, 0x1A, 0x77, 0x13, 0x23, +0x7C, 0xE6, 0x03, 0xB5, 0xC2, 0x8F, 0xFD, 0x3E, +0xFF, 0xD3, 0xFF, 0x7D, 0xB4, 0xCA, 0xA7, 0xFD, +0x7C, 0xB8, 0xC2, 0x80, 0xFD, 0x7D, 0xB9, 0xC2, +0x80, 0xFD, 0x21, 0x40, 0xFF, 0x11, 0x40, 0x7F, +0xC3, 0x80, 0xFD, 0x2A, 0xD7, 0xFC, 0x44, 0x4D, +0x2A, 0xDB, 0x7C, 0x11, 0xFE, 0xFD, 0x0C, 0x2B, +0x0D, 0xCA, 0xBF, 0xFD, 0x1A, 0x77, 0x2B, 0x1B, +0xC3, 0xB4, 0xFD, 0x23, 0xF9, 0xCD, 0xFE, 0xFC, +0xAF, 0xCD, 0x1B, 0xFD, 0x3A, 0x00, 0x00, 0xFB, +0xC9, 0xCD, 0xB3, 0x02, 0x62, 0x18, 0x46, 0xFD, +0x3A, 0xC9, 0xF3, 0xCD, 0xFE, 0xFC, 0x3A, 0xCC, +0xFC, 0xCD, 0x1B, 0xFD, 0x3A, 0x00, 0x00, 0x21, +0x40, 0x00, 0x11, 0xA4, 0xFA, 0x06, 0x08, 0x7E, +0x12, 0x23, 0x13, 0x05, 0xC2, 0x5B, 0xFD, 0xCD, +0xF4, 0xFC, 0x21, 0x05, 0xF6, 0x11, 0x6F, 0x03, +0x06, 0x24, 0xCD, 0x69, 0x34, 0xCD, 0xEA, 0xFC, +0xCD, 0xFE, 0xFC, 0xAF, 0xCD, 0x1B, 0xFD, 0x3A, +0x00, 0x00, 0xFB, 0xC9, 0xCD, 0xB3, 0x02, 0xA5, +0x18, 0x46, 0xFD, 0x13, 0xC9, 0xF3, 0xF5, 0xAF, +0xD3, 0xB9, 0xDB, 0xBA, 0xE6, 0xFC, 0xF6, 0x02, +0xD3, 0xBA, 0x3E, 0xC0, 0xD3, 0xFE, 0xF1, 0xC9, +0xCD, 0xB3, 0x02, 0xC1, 0x18, 0x46, 0xFD, 0x1F, +0xC9, 0xF3, 0xCD, 0xF4, 0xFC, 0x11, 0x04, 0x00, +0x1A, 0xFE, 0x65, 0xC2, 0x5E, 0xFD, 0x13, 0x1A, +0xFE, 0x6E, 0xC2, 0x5E, 0xFD, 0x13, 0x1A, 0xFE, +0x75, 0xF5, 0xCD, 0xEA, 0xFC, 0xF1, 0xFB, 0xC9, +0xCD, 0xB3, 0x02, 0xE9, 0x18, 0x46, 0xFD, 0x1E, +0xC9, 0xF3, 0xE6, 0x01, 0x07, 0x07, 0xF5, 0xCD, +0xFE, 0xFC, 0x21, 0x03, 0x00, 0x7E, 0x66, 0xE6, +0x3F, 0x67, 0xF1, 0xB4, 0x21, 0x01, 0x00, 0x6E, +0x6F, 0x7E, 0x3A, 0x00, 0x00, 0xFB, 0xC9, 0xCD, +0xB3, 0x02, 0x10, 0x19, 0x46, 0xFD, 0x1E, 0xC9, +0xF3, 0x11, 0x00, 0x00, 0xCD, 0xFE, 0xFC, 0xCD, +0x1B, 0xFD, 0x1A, 0x2B, 0x23, 0x03, 0x7E, 0xFE, +0x1A, 0xC2, 0x52, 0xFD, 0xCD, 0xFE, 0xFC, 0xAF, +0xCD, 0x1B, 0xFD, 0x1A, 0xFB, 0xC9, 0xCD, 0xB3, +0x02, 0x37, 0x19, 0x46, 0xFD, 0x20, 0xC9, 0xF3, +0xCD, 0xFE, 0xFC, 0xCD, 0x1B, 0xFD, 0x3A, 0x00, +0x00, 0x7E, 0x12, 0x23, 0x13, 0x0B, 0x78, 0xB1, +0xC2, 0x50, 0xFD, 0xCD, 0xFE, 0xFC, 0xAF, 0xCD, +0x1B, 0xFD, 0x3A, 0x00, 0x00, 0xFB, 0xC9, 0x22, +0xD3, 0xFC, 0x21, 0x85, 0xF6, 0x22, 0xD5, 0xFC, +0x06, 0x08, 0xCD, 0xDD, 0x02, 0x06, 0x06, 0xC5, +0x2A, 0xD3, 0xFC, 0xF7, 0x7C, 0x42, 0xF7, 0xCB, +0x12, 0xF7, 0xE9, 0x0F, 0xFE, 0x1B, 0xCA, 0xED, +0x19, 0xFE, 0x0D, 0xCA, 0xF0, 0x19, 0xFE, 0x08, +0xCA, 0xB1, 0x19, 0xC1, 0xC5, 0x4F, 0x78, 0xB7, +0xCA, 0x68, 0x19, 0x79, 0xFE, 0x20, 0xFA, 0x68, +0x19, 0xFE, 0x7F, 0xF2, 0x68, 0x19, 0x2A, 0xD5, +0xFC, 0x77, 0xCD, 0xDF, 0x19, 0x2A, 0xD3, 0xFC, +0x24, 0x22, 0xD3, 0xFC, 0x2A, 0xD5, 0xFC, 0x23, +0x22, 0xD5, 0xFC, 0xC1, 0x05, 0xC5, 0xC3, 0x68, +0x19, 0xC1, 0xC5, 0x78, 0xFE, 0x06, 0xCA, 0x68, +0x19, 0xC1, 0x04, 0xC5, 0x3E, 0x20, 0x2A, 0xD5, +0xFC, 0x77, 0xCD, 0xDF, 0x19, 0x2A, 0xD3, 0xFC, +0x25, 0x22, 0xD3, 0xFC, 0x2A, 0xD5, 0xFC, 0x2B, +0x22, 0xD5, 0xFC, 0x3E, 0x20, 0x2A, 0xD5, 0xFC, +0x77, 0xCD, 0xDF, 0x19, 0xC3, 0x68, 0x19, 0x2A, +0xD3, 0xFC, 0xF7, 0x7C, 0x42, 0x2A, 0xD5, 0xFC, +0x7E, 0xF7, 0x13, 0x43, 0xC9, 0xC1, 0xAF, 0xC9, +0xC1, 0x78, 0xFE, 0x06, 0xCA, 0x57, 0x19, 0xF6, +0xFF, 0xC9, 0xF5, 0xCD, 0x87, 0x15, 0xF1, 0x47, +0xC5, 0xCD, 0x46, 0xFD, 0xC1, 0x78, 0xC8, 0x32, +0xCE, 0xFC, 0x3A, 0xD9, 0xFC, 0x32, 0xDA, 0xFC, +0xCD, 0x32, 0x1B, 0xCC, 0xAF, 0x1B, 0x3E, 0xFF, +0xCD, 0x7B, 0x1B, 0xE5, 0x3A, 0xCE, 0xFC, 0xCD, +0x51, 0x1B, 0x11, 0xD7, 0x1A, 0xE1, 0xE5, 0xCD, +0x3F, 0x1B, 0xE1, 0xE5, 0xCD, 0x56, 0x1B, 0xCD, +0xB8, 0x1C, 0xE1, 0xE5, 0xCD, 0x9F, 0x1D, 0xCD, +0xD2, 0x1C, 0xE1, 0xCD, 0xA7, 0x1D, 0x21, 0xB2, +0x1A, 0xC3, 0x68, 0x1A, 0xCD, 0x13, 0x16, 0xCD, +0x46, 0xFD, 0x78, 0xA7, 0xF8, 0x21, 0x76, 0x1A, +0xC3, 0x68, 0x1A, 0x3A, 0xC0, 0xFC, 0xE6, 0x02, +0xC8, 0x21, 0x8F, 0x1A, 0xC3, 0x68, 0x1A, 0x3A, +0xCA, 0xFC, 0xFE, 0x10, 0xF8, 0x21, 0x9C, 0x1A, +0xCD, 0x30, 0x02, 0xCD, 0x22, 0x1B, 0x2A, 0xDB, +0xFC, 0xF9, 0x2A, 0xC2, 0xFC, 0xE9, 0x45, 0x72, +0x72, 0x6F, 0x72, 0x20, 0x2D, 0x20, 0x66, 0x6C, +0x61, 0x73, 0x68, 0x20, 0x6E, 0x6F, 0x74, 0x20, +0x72, 0x65, 0x61, 0x64, 0x79, 0x21, 0x00, 0x52, +0x45, 0x58, 0x20, 0x69, 0x73, 0x20, 0x66, 0x75, +0x6C, 0x6C, 0x21, 0x00, 0x54, 0x6F, 0x6F, 0x20, +0x6D, 0x61, 0x6E, 0x79, 0x20, 0x6F, 0x66, 0x20, +0x6F, 0x6E, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, +0x21, 0x00, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x20, +0x75, 0x6E, 0x6D, 0x61, 0x72, 0x6B, 0x65, 0x64, +0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x2E, 0x2E, +0x2E, 0x72, 0x65, 0x63, 0x6F, 0x76, 0x65, 0x72, +0x69, 0x6E, 0x67, 0x2E, 0x2E, 0x2E, 0x00, 0x52, +0x45, 0x43, 0x4F, 0x56, 0x52, 0x20, 0x4F, 0x4B, +0x21, 0x0D, 0x0A, 0x00, 0x52, 0x45, 0x58, 0x00, +0x52, 0x45, 0x58, 0x32, 0x00, 0xCD, 0x30, 0x02, +0xF7, 0x29, 0x42, 0xCD, 0x22, 0x1B, 0x2A, 0xDB, +0xFC, 0xF9, 0x2A, 0xC2, 0xFC, 0xE9, 0x11, 0x46, +0xFD, 0x06, 0x60, 0xAF, 0x12, 0x13, 0x05, 0xC2, +0x04, 0x1B, 0xC9, 0x26, 0x00, 0x2E, 0x00, 0xE5, +0xF5, 0xCD, 0x31, 0x16, 0xF1, 0xE1, 0xC3, 0x46, +0xFD, 0xF7, 0x42, 0x72, 0xCA, 0x19, 0x1B, 0xFE, +0x1B, 0xC9, 0x06, 0x02, 0x21, 0xFF, 0xFF, 0x2B, +0x7C, 0xB5, 0xC2, 0x27, 0x1B, 0x05, 0xC2, 0x24, +0x1B, 0xC9, 0x3A, 0xF0, 0x4F, 0xFE, 0xFF, 0xCA, +0x3C, 0x1B, 0xAF, 0xC9, 0xF6, 0x01, 0xC9, 0x23, +0x06, 0x06, 0x1A, 0xD5, 0xC5, 0xCD, 0x5B, 0x1C, +0xC1, 0xD1, 0x23, 0x13, 0x05, 0xC2, 0x42, 0x1B, +0xC9, 0xF6, 0xC0, 0xC3, 0x5B, 0x1C, 0x11, 0x07, +0x00, 0x19, 0x3A, 0xDA, 0xFC, 0xC3, 0x5B, 0x1C, +0x11, 0x07, 0x00, 0x19, 0x7E, 0x32, 0xDA, 0xFC, +0xC9, 0x7E, 0xE6, 0x7F, 0xC3, 0x5B, 0x1C, 0xAF, +0xC3, 0x5B, 0x1C, 0xF6, 0xC0, 0xF5, 0x06, 0xFF, +0xC3, 0x80, 0x1B, 0xF6, 0x40, 0xF5, 0x06, 0x7F, +0x21, 0x00, 0x44, 0x11, 0x00, 0x50, 0xF7, 0x18, +0x00, 0xCA, 0xA1, 0x1B, 0x3E, 0xFF, 0xBE, 0xCA, +0xA1, 0x1B, 0x7E, 0xA0, 0x4F, 0xF1, 0xF5, 0xB9, +0xCA, 0xA5, 0x1B, 0xCD, 0xA8, 0x1B, 0xC3, 0x86, +0x1B, 0xF1, 0xF6, 0x01, 0xC9, 0xF1, 0xAF, 0xC9, +0xD5, 0x11, 0x10, 0x00, 0x19, 0xD1, 0xC9, 0x21, +0x37, 0x0C, 0xCD, 0x30, 0x02, 0x21, 0x00, 0x40, +0xE5, 0xAF, 0xCD, 0x0D, 0x1B, 0xCD, 0x4E, 0x17, +0x0E, 0x00, 0xE1, 0xE5, 0x3A, 0xCC, 0xFC, 0xCD, +0x46, 0xFD, 0x0E, 0x00, 0xE1, 0x23, 0x3A, 0xCD, +0xFC, 0xCD, 0x46, 0xFD, 0x21, 0x00, 0x44, 0x22, +0xCF, 0xFC, 0x22, 0xD1, 0xFC, 0x2A, 0xD1, 0xFC, +0x11, 0x00, 0x50, 0xF7, 0x18, 0x00, 0xCA, 0x0A, +0x1C, 0xCD, 0x70, 0x17, 0x0E, 0x01, 0x2A, 0xD1, +0xFC, 0xCD, 0x46, 0xFD, 0xFE, 0xFF, 0xCA, 0x0A, +0x1C, 0xE6, 0x40, 0xC4, 0x21, 0x1C, 0x2A, 0xD1, +0xFC, 0xCD, 0xA8, 0x1B, 0x22, 0xD1, 0xFC, 0xC3, +0xDD, 0x1B, 0x3E, 0x01, 0xCD, 0x0B, 0x1B, 0xCD, +0x9C, 0x18, 0xCD, 0x46, 0xFD, 0xCD, 0x76, 0x16, +0x01, 0x01, 0x00, 0x11, 0x00, 0x80, 0xC3, 0x46, +0xFD, 0x01, 0x10, 0x00, 0x2A, 0xD1, 0xFC, 0xEB, +0x2A, 0xCF, 0xFC, 0xC5, 0xE5, 0xD5, 0xCD, 0x70, +0x17, 0x0E, 0x01, 0xE1, 0xE5, 0xCD, 0x46, 0xFD, +0xD1, 0xE1, 0xD5, 0xE5, 0xF5, 0xCD, 0x4E, 0x17, +0x0E, 0x00, 0xF1, 0xE1, 0xE5, 0xCD, 0x46, 0xFD, +0xE1, 0xD1, 0x23, 0x13, 0xC1, 0x0D, 0xC2, 0x2B, +0x1C, 0x2A, 0xCF, 0xFC, 0xCD, 0xA8, 0x1B, 0x22, +0xCF, 0xFC, 0xC9, 0xE5, 0xF5, 0xCD, 0x4E, 0x17, +0xF1, 0xE1, 0x0E, 0x00, 0xCD, 0x69, 0x1C, 0x0E, +0x01, 0xE5, 0xF5, 0xCD, 0x46, 0xFD, 0xF1, 0xE1, +0xC9, 0xCD, 0x96, 0x1C, 0xCD, 0xB8, 0x1C, 0xCD, +0x9F, 0x1D, 0xCD, 0xD2, 0x1C, 0xCD, 0xA7, 0x1D, +0xC9, 0xCD, 0x96, 0x1C, 0x1B, 0xEB, 0xCD, 0x88, +0x1D, 0xEB, 0xCD, 0x9F, 0x1D, 0xEB, 0xCD, 0x8F, +0x1D, 0xEB, 0xCD, 0xA7, 0x1D, 0xC9, 0xE5, 0xCD, +0x32, 0x1B, 0xCC, 0xAF, 0x1B, 0x3E, 0xFF, 0xCD, +0x7B, 0x1B, 0xE5, 0x3A, 0xCB, 0xFC, 0xCD, 0x51, +0x1B, 0xE1, 0xE5, 0xCD, 0x56, 0x1B, 0xE1, 0xD1, +0xD5, 0xE5, 0xCD, 0x3F, 0x1B, 0xE1, 0xD1, 0xC9, +0xE5, 0x21, 0x46, 0xFD, 0xE5, 0xF7, 0x0F, 0x19, +0xD1, 0xCD, 0x06, 0x1D, 0x32, 0xD5, 0xFC, 0x13, +0x13, 0x13, 0xCD, 0x06, 0x1D, 0x32, 0xD6, 0xFC, +0xE1, 0xC9, 0xE5, 0x21, 0x46, 0xFD, 0xE5, 0xF7, +0x2F, 0x19, 0xD1, 0xCD, 0x06, 0x1D, 0xE6, 0x0F, +0x0F, 0x0F, 0x0F, 0x47, 0xE6, 0xE0, 0x4F, 0x78, +0xE6, 0x01, 0x47, 0x13, 0x13, 0x13, 0xCD, 0x06, +0x1D, 0xE6, 0x1F, 0xB1, 0x32, 0xD6, 0xFC, 0x13, +0x13, 0x13, 0xCD, 0x06, 0x1D, 0xE6, 0x7F, 0x07, +0xB0, 0x32, 0xD5, 0xFC, 0xE1, 0xC9, 0xED, 0x7C, +0xD6, 0x30, 0x67, 0x7D, 0xD6, 0x30, 0x6F, 0xB7, +0xCA, 0x1A, 0x1D, 0xAF, 0xC6, 0x0A, 0x2D, 0xC2, +0x14, 0x1D, 0x84, 0xC9, 0x21, 0x07, 0x24, 0xF7, +0x7C, 0x42, 0x3A, 0xD5, 0xFC, 0xCD, 0x69, 0x1D, +0x3E, 0x3A, 0xCD, 0x84, 0x1D, 0x3A, 0xD6, 0xFC, +0xCD, 0x69, 0x1D, 0xC9, 0x21, 0x07, 0x1B, 0xF7, +0x7C, 0x42, 0x3A, 0xD5, 0xFC, 0xF5, 0xE6, 0xFE, +0x0F, 0xCD, 0x69, 0x1D, 0x3E, 0x2F, 0xCD, 0x84, +0x1D, 0xF1, 0xE6, 0x01, 0x07, 0x07, 0x07, 0x47, +0x3A, 0xD6, 0xFC, 0xF5, 0xE6, 0xE0, 0x07, 0x07, +0x07, 0xB0, 0xCD, 0x69, 0x1D, 0x3E, 0x2F, 0xCD, +0x84, 0x1D, 0xF1, 0xE6, 0x1F, 0xCD, 0x69, 0x1D, +0xC9, 0xE6, 0x3F, 0xF5, 0xFE, 0x0A, 0xF2, 0x7A, +0x1D, 0x3E, 0x30, 0xF7, 0x13, 0x43, 0xF1, 0xC3, +0x82, 0x1D, 0xF1, 0x26, 0x00, 0x6F, 0xF7, 0xD4, +0x39, 0xC9, 0xC6, 0x30, 0xF7, 0x13, 0x43, 0xC9, +0xE5, 0x01, 0x0A, 0x00, 0xC3, 0x93, 0x1D, 0xE5, +0x01, 0x08, 0x00, 0x09, 0x7E, 0x32, 0xD5, 0xFC, +0x23, 0x7E, 0x32, 0xD6, 0xFC, 0xE1, 0xC9, 0xE5, +0xD5, 0x01, 0x0A, 0x00, 0xC3, 0xAC, 0x1D, 0xE5, +0xD5, 0x01, 0x08, 0x00, 0x09, 0x3A, 0xD5, 0xFC, +0xCD, 0x5B, 0x1C, 0x23, 0x3A, 0xD6, 0xFC, 0xCD, +0x5B, 0x1C, 0xD1, 0xE1, 0xC9, 0xE5, 0xCD, 0xBA, +0x1E, 0x2A, 0xCF, 0xFC, 0x7C, 0xB5, 0xE1, 0xCA, +0xD4, 0x1D, 0x21, 0x01, 0x1E, 0xCD, 0x43, 0x02, +0x3E, 0x01, 0xB7, 0xC9, 0xE5, 0x2A, 0xD1, 0xFC, +0x7C, 0xB5, 0xE1, 0xC2, 0x16, 0x1E, 0x21, 0xE8, +0x1D, 0xCD, 0x43, 0x02, 0x3E, 0x01, 0xB7, 0xC9, +0x4E, 0x4F, 0x20, 0x46, 0x52, 0x45, 0x45, 0x20, +0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x4F, 0x52, +0x59, 0x20, 0x45, 0x4E, 0x54, 0x52, 0x59, 0x21, +0x00, 0x44, 0x55, 0x50, 0x4C, 0x49, 0x43, 0x41, +0x54, 0x45, 0x20, 0x46, 0x49, 0x4C, 0x45, 0x20, +0x4E, 0x41, 0x4D, 0x45, 0x21, 0x00, 0xE5, 0x21, +0x6D, 0xF9, 0x01, 0x0B, 0x00, 0x09, 0x7E, 0xFE, +0xFF, 0xCA, 0x3F, 0x1E, 0xE5, 0x23, 0x3A, 0xC0, +0xFA, 0x3C, 0xBE, 0xE1, 0xC2, 0x1A, 0x1E, 0xE5, +0x23, 0x23, 0x3A, 0xC1, 0xFA, 0xBE, 0xE1, 0xC2, +0x1A, 0x1E, 0x23, 0x7E, 0x3C, 0x3C, 0x77, 0xE1, +0xEB, 0x2A, 0xD1, 0xFC, 0x0E, 0x0B, 0xCD, 0xC1, +0x02, 0xED, 0x44, 0x4D, 0xC5, 0x2A, 0xAE, 0xFB, +0x09, 0x22, 0xAE, 0xFB, 0x13, 0x13, 0xD5, 0x2A, +0xC0, 0xFA, 0x23, 0xE5, 0xF7, 0x6D, 0x6B, 0xDA, +0x77, 0x1E, 0xE1, 0xD1, 0xC1, 0xCD, 0xC1, 0x02, +0x2A, 0xD1, 0xFC, 0x23, 0xEB, 0x2A, 0xC0, 0xFA, +0x23, 0xD9, 0xF7, 0x46, 0x21, 0xAF, 0xC9, 0x21, +0x8F, 0x1E, 0xCD, 0x4D, 0x02, 0xF7, 0x9F, 0x6B, +0xE1, 0xE1, 0xE1, 0x2A, 0xD1, 0xFC, 0xAF, 0x77, +0xF7, 0x46, 0x21, 0x3E, 0x01, 0xB7, 0xC9, 0x4E, +0x4F, 0x54, 0x20, 0x45, 0x4E, 0x4F, 0x55, 0x47, +0x48, 0x20, 0x46, 0x52, 0x45, 0x45, 0x20, 0x4D, +0x45, 0x4D, 0x4F, 0x52, 0x59, 0x21, 0x00, 0xCD, +0xBA, 0x1E, 0x2A, 0xCF, 0xFC, 0x7C, 0xB5, 0xC8, +0xE5, 0xF7, 0xE3, 0x5A, 0xEB, 0xE1, 0xF7, 0x17, +0x20, 0xC9, 0x22, 0xD3, 0xFC, 0x21, 0x00, 0x00, +0x22, 0xD1, 0xFC, 0x22, 0xCF, 0xFC, 0x21, 0xAF, +0xF9, 0x01, 0x0B, 0x00, 0x09, 0x7E, 0x3C, 0xC8, +0xE5, 0x3D, 0xEB, 0x2A, 0xD3, 0xFC, 0xBE, 0xEB, +0xCC, 0xEF, 0x1E, 0xB7, 0xCC, 0xE3, 0x1E, 0xE1, +0xC3, 0xC9, 0x1E, 0xEB, 0x2A, 0xD1, 0xFC, 0x7C, +0xB5, 0xEB, 0xC0, 0x22, 0xD1, 0xFC, 0xC9, 0xEB, +0x2A, 0xCF, 0xFC, 0x7C, 0xB5, 0xEB, 0xC0, 0xE5, +0x23, 0x23, 0x23, 0xEB, 0x2A, 0xD3, 0xFC, 0x23, +0x23, 0x23, 0x06, 0x08, 0x1A, 0xBE, 0xC2, 0x14, +0x1F, 0x23, 0x13, 0x05, 0xC2, 0x04, 0x1F, 0xE1, +0x22, 0xCF, 0xFC, 0xC9, 0xE1, 0xC9, 0x80, 0x00, +0x00, 0x52, 0x45, 0x58, 0x4D, 0x47, 0x52, 0x42, +0x41, 0x74, 0x00, 0x73, 0x80, 0x01, 0x00, 0x41, +0x24, 0xDD, 0x22, 0xF3, 0xAF, 0x3C, 0xD3, 0xE8, +0xAF, 0x67, 0x6F, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, +0x2E, 0xB8, 0x6E, 0x2E, 0xF2, 0x6E, 0x2E, 0x34, +0x6E, 0x2E, 0xB0, 0x6E, 0x2E, 0x31, 0x6E, 0x2E, +0xBF, 0x6E, 0xAF, 0x67, 0x6F, 0x2C, 0x6E, 0xAF, +0x6F, 0x7E, 0x7E, 0xAF, 0x3C, 0x3C, 0x3C, 0x67, +0x2E, 0x83, 0xE9, 0x22, 0x3A, 0x42, 0xDD, 0xC3, +0x28, 0x41, 0x24, 0x29, 0x3A, 0x43, 0xDD, 0xEE, +0x28, 0x42, 0xD0, 0x31, 0x29, 0xD0, 0x32, 0x35, +0x36, 0xD2, 0x28, 0xEE, 0x28, 0x42, 0xD0, 0x32, +0x29, 0x29, 0x3A, 0xB9, 0x43, 0x3A, 0x8E, 0x56, +0x45, 0x52, 0x53, 0x49, 0x4F, 0x4E, 0x20, 0x34, +0x2E, 0x38, 0x20, 0x4D, 0x31, 0x30, 0x30, 0x2F, +0x54, 0x31, 0x30, 0x32, 0x00, 0x00, 0x00, 0x88, +0x00, 0x00, 0x52, 0x58, 0x48, 0x4F, 0x4F, 0x4B, +0x00, 0x00, 0x2D, 0x00, 0x2C, 0x80, 0x01, 0x00, +0xF3, 0xF5, 0xE5, 0xAF, 0x67, 0x2E, 0x03, 0x7E, +0xFE, 0x4D, 0xC2, 0x27, 0x80, 0x3A, 0x45, 0xFF, +0xF6, 0x01, 0xD3, 0xE8, 0x23, 0x7E, 0xFE, 0x52, +0xCA, 0x96, 0x03, 0x3A, 0x45, 0xFF, 0xE6, 0xFE, +0xD3, 0xE8, 0xE1, 0xF1, 0xFB, 0xC9, 0x00, 0x00, +0x00, 0x21, 0xE4, 0x1F, 0xE5, 0xCD, 0xA7, 0x1E, +0xE1, 0x11, 0x0B, 0x00, 0x19, 0x7E, 0xFE, 0xFF, +0xC2, 0xD4, 0x1F, 0xC9, 0x80, 0x00, 0x00, 0x54, +0x53, 0x2D, 0x44, 0x4F, 0x53, 0x20, 0x20, 0x80, +0x00, 0x00, 0x55, 0x52, 0x2D, 0x32, 0x20, 0x20, +0x20, 0x20, 0x80, 0x00, 0x00, 0x54, 0x57, 0x4F, +0x52, 0x44, 0x2B, 0x20, 0x20, 0x80, 0x00, 0x00, +0x52, 0x41, 0x4E, 0x44, 0x4F, 0x4D, 0x20, 0x20, +0xFF, 0x51, 0x1E, 0x00, 0x2A, 0xC0, 0xFA, 0x01, +0x00, 0xA0, 0xC5, 0x08, 0xF7, 0x18, 0x00, 0xCA, +0x5B, 0x20, 0xF5, 0xD2, 0x27, 0x20, 0xEB, 0x42, +0x4B, 0x08, 0x44, 0x4D, 0xF1, 0xE1, 0xC5, 0xD2, +0x39, 0x20, 0xF7, 0x6D, 0x6B, 0xC1, 0xC3, 0x43, +0x20, 0xF7, 0x9F, 0x6B, 0xC1, 0x21, 0x00, 0x00, +0x08, 0x44, 0x4D, 0x2A, 0xAE, 0xFB, 0x09, 0x22, +0xAE, 0xFB, 0x2A, 0xC0, 0xFA, 0x09, 0x22, 0xC0, +0xFA, 0x7C, 0xD6, 0xA0, 0x32, 0x00, 0xA0, 0xF7, +0x62, 0x2C, 0xC9, 0xC1, 0xC9, 0x21, 0xC9, 0x2E, +0xC3, 0x7A, 0x20, 0x21, 0x0B, 0x2E, 0xC3, 0x7A, +0x20, 0x21, 0x5E, 0x27, 0xC3, 0x7A, 0x20, 0x3A, +0xD9, 0xFC, 0xFE, 0x03, 0xCA, 0x69, 0x20, 0x21, +0xE9, 0x20, 0xE5, 0xCD, 0x36, 0x03, 0x21, 0x01, +0x01, 0xF7, 0x7C, 0x42, 0xE1, 0xCD, 0x4D, 0x02, +0x7E, 0xFE, 0xFE, 0xCA, 0x96, 0x20, 0xFE, 0xFF, +0xCA, 0xA8, 0x20, 0xC3, 0x85, 0x20, 0x23, 0xE5, +0x21, 0xBB, 0x20, 0xCD, 0x30, 0x02, 0xCD, 0x19, +0x1B, 0xE1, 0xCA, 0xB1, 0x20, 0xC3, 0x7A, 0x20, +0x21, 0xD5, 0x20, 0xCD, 0x30, 0x02, 0xCD, 0x19, +0x1B, 0xCD, 0x3D, 0x13, 0xCD, 0x3C, 0x03, 0x2A, +0xC2, 0xFC, 0xE9, 0x3C, 0x45, 0x53, 0x43, 0x3E, +0x20, 0x65, 0x78, 0x69, 0x74, 0x20, 0x3C, 0x61, +0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x3E, 0x20, +0x6D, 0x6F, 0x72, 0x65, 0x00, 0x3C, 0x61, 0x6E, +0x79, 0x20, 0x6B, 0x65, 0x79, 0x3E, 0x20, 0x74, +0x6F, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, +0x00, 0x4B, 0x65, 0x79, 0x62, 0x6F, 0x61, 0x72, +0x64, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x61, 0x6E, +0x64, 0x73, 0x00, 0x3C, 0x62, 0x3E, 0x20, 0x42, +0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6E, 0x75, 0x6D, +0x62, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x66, 0x6F, +0x72, 0x6D, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, +0x3C, 0x65, 0x3E, 0x20, 0x48, 0x69, 0x6E, 0x74, +0x73, 0x20, 0x6F, 0x6E, 0x20, 0x3C, 0x45, 0x4E, +0x54, 0x45, 0x52, 0x3E, 0x20, 0x6B, 0x65, 0x79, +0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, +0x6E, 0x73, 0x00, 0x3C, 0x69, 0x3E, 0x20, 0x49, +0x6E, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x69, +0x6F, 0x6E, 0x20, 0x6F, 0x6E, 0x20, 0x52, 0x45, +0x58, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6D, +0x00, 0x3C, 0x63, 0x3E, 0x20, 0x43, 0x68, 0x65, +0x63, 0x6B, 0x73, 0x75, 0x6D, 0x20, 0x6F, 0x66, +0x20, 0x6D, 0x65, 0x6E, 0x75, 0x20, 0x65, 0x6E, +0x74, 0x72, 0x79, 0x20, 0x69, 0x6D, 0x61, 0x67, +0x65, 0x00, 0x3C, 0x73, 0x3E, 0x20, 0x54, 0x6F, +0x67, 0x67, 0x6C, 0x65, 0x20, 0x64, 0x69, 0x72, +0x65, 0x63, 0x74, 0x6F, 0x72, 0x79, 0x20, 0x73, +0x6F, 0x72, 0x74, 0x20, 0x6F, 0x72, 0x64, 0x65, +0x72, 0x00, 0xFE, 0x4B, 0x65, 0x79, 0x62, 0x6F, +0x61, 0x72, 0x64, 0x20, 0x43, 0x6F, 0x6D, 0x6D, +0x61, 0x6E, 0x64, 0x73, 0x00, 0x3C, 0x65, 0x6E, +0x74, 0x3E, 0x20, 0x54, 0x61, 0x6B, 0x65, 0x20, +0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, +0x6F, 0x72, 0x20, 0x73, 0x65, 0x6C, 0x65, 0x63, +0x74, 0x69, 0x6F, 0x6E, 0x00, 0x3C, 0x74, 0x61, +0x62, 0x3E, 0x20, 0x53, 0x68, 0x6F, 0x77, 0x20, +0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, +0x79, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x6E, 0x65, +0x78, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x00, +0x3C, 0x65, 0x73, 0x63, 0x3E, 0x20, 0x72, 0x65, +0x74, 0x75, 0x72, 0x6E, 0x20, 0x74, 0x6F, 0x20, +0x6D, 0x65, 0x6E, 0x75, 0x00, 0x00, 0x00, 0xFE, +0x46, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, +0x20, 0x4B, 0x65, 0x79, 0x73, 0x00, 0x3C, 0x46, +0x31, 0x3E, 0x20, 0x44, 0x69, 0x73, 0x70, 0x6C, +0x61, 0x79, 0x20, 0x68, 0x65, 0x6C, 0x70, 0x20, +0x73, 0x63, 0x72, 0x65, 0x65, 0x6E, 0x73, 0x00, +0x3C, 0x46, 0x32, 0x3E, 0x20, 0x4C, 0x6F, 0x61, +0x64, 0x2F, 0x53, 0x61, 0x76, 0x65, 0x20, 0x69, +0x6D, 0x61, 0x67, 0x65, 0x20, 0x66, 0x72, 0x6F, +0x6D, 0x2F, 0x74, 0x6F, 0x20, 0x54, 0x50, 0x44, +0x44, 0x00, 0x3C, 0x46, 0x33, 0x3E, 0x20, 0x43, +0x6F, 0x70, 0x79, 0x20, 0x69, 0x6D, 0x61, 0x67, +0x65, 0x20, 0x74, 0x6F, 0x20, 0x52, 0x45, 0x58, +0x00, 0x3C, 0x46, 0x34, 0x3E, 0x20, 0x44, 0x65, +0x6C, 0x65, 0x74, 0x65, 0x20, 0x69, 0x6D, 0x61, +0x67, 0x65, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, +0x52, 0x45, 0x58, 0x00, 0x3C, 0x46, 0x35, 0x3E, +0x20, 0x52, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x20, +0x74, 0x68, 0x65, 0x20, 0x69, 0x6D, 0x61, 0x67, +0x65, 0x00, 0xFE, 0x46, 0x75, 0x6E, 0x63, 0x74, +0x69, 0x6F, 0x6E, 0x20, 0x4B, 0x65, 0x79, 0x73, +0x00, 0x3C, 0x46, 0x36, 0x3E, 0x20, 0x46, 0x69, +0x6C, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, +0x66, 0x65, 0x72, 0x20, 0x66, 0x72, 0x6F, 0x6D, +0x20, 0x73, 0x74, 0x6F, 0x72, 0x65, 0x64, 0x20, +0x69, 0x6D, 0x61, 0x67, 0x65, 0x00, 0x3C, 0x46, +0x37, 0x3E, 0x20, 0x44, 0x65, 0x69, 0x6E, 0x73, +0x74, 0x61, 0x6C, 0x6C, 0x20, 0x52, 0x45, 0x58, +0x20, 0x73, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72, +0x65, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x6C, +0x61, 0x70, 0x74, 0x6F, 0x70, 0x00, 0x3C, 0x46, +0x38, 0x3E, 0x20, 0x45, 0x78, 0x69, 0x74, 0x20, +0x52, 0x45, 0x58, 0x20, 0x4D, 0x61, 0x6E, 0x61, +0x67, 0x65, 0x72, 0x00, 0x00, 0x00, 0xFE, 0x4D, +0x61, 0x69, 0x6E, 0x20, 0x4D, 0x65, 0x6E, 0x75, +0x20, 0x48, 0x65, 0x6C, 0x70, 0x00, 0x3D, 0x3D, +0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, +0x3D, 0x3D, 0x3D, 0x3D, 0x00, 0x52, 0x45, 0x58, +0x20, 0x69, 0x73, 0x20, 0x61, 0x6E, 0x20, 0x6F, +0x70, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x4F, +0x4D, 0x20, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, +0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x00, +0x61, 0x6C, 0x73, 0x6F, 0x20, 0x69, 0x6E, 0x63, +0x6C, 0x75, 0x64, 0x65, 0x73, 0x20, 0x52, 0x41, +0x4D, 0x20, 0x62, 0x61, 0x63, 0x6B, 0x75, 0x70, +0x20, 0x61, 0x6E, 0x64, 0x20, 0x73, 0x77, 0x69, +0x74, 0x63, 0x68, 0x69, 0x6E, 0x67, 0x00, 0x66, +0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, +0x2E, 0x20, 0x20, 0x52, 0x45, 0x58, 0x20, 0x6D, +0x61, 0x6E, 0x61, 0x67, 0x65, 0x73, 0x20, 0x52, +0x41, 0x4D, 0x20, 0x6F, 0x72, 0x20, 0x52, 0x4F, +0x4D, 0x20, 0x64, 0x61, 0x74, 0x61, 0x00, 0x69, +0x6E, 0x20, 0x33, 0x32, 0x6B, 0x20, 0x62, 0x6C, +0x6F, 0x63, 0x6B, 0x73, 0x2C, 0x20, 0x72, 0x65, +0x66, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6F, +0x20, 0x61, 0x73, 0x20, 0x69, 0x6D, 0x61, 0x67, +0x65, 0x73, 0x2E, 0x00, 0xFE, 0x4F, 0x70, 0x74, +0x69, 0x6F, 0x6E, 0x20, 0x52, 0x4F, 0x4D, 0x73, +0x20, 0x6D, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, +0x6C, 0x6F, 0x61, 0x64, 0x65, 0x64, 0x20, 0x69, +0x6E, 0x74, 0x6F, 0x20, 0x52, 0x45, 0x58, 0x00, +0x69, 0x6D, 0x61, 0x67, 0x65, 0x73, 0x20, 0x61, +0x6E, 0x64, 0x20, 0x73, 0x65, 0x6C, 0x65, 0x63, +0x74, 0x65, 0x64, 0x20, 0x66, 0x6F, 0x72, 0x20, +0x75, 0x73, 0x65, 0x2C, 0x20, 0x61, 0x6E, 0x64, +0x20, 0x79, 0x6F, 0x75, 0x72, 0x00, 0x73, 0x79, +0x73, 0x74, 0x65, 0x6D, 0x20, 0x52, 0x41, 0x4D, +0x20, 0x6D, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, +0x63, 0x6F, 0x70, 0x69, 0x65, 0x64, 0x20, 0x74, +0x6F, 0x20, 0x6F, 0x72, 0x20, 0x72, 0x65, 0x73, +0x74, 0x6F, 0x72, 0x65, 0x64, 0x00, 0x66, 0x72, +0x6F, 0x6D, 0x20, 0x52, 0x45, 0x58, 0x20, 0x69, +0x6D, 0x61, 0x67, 0x65, 0x73, 0x2E, 0x00, 0x49, +0x6D, 0x61, 0x67, 0x65, 0x73, 0x20, 0x61, 0x72, +0x65, 0x20, 0x67, 0x72, 0x6F, 0x75, 0x70, 0x65, +0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x79, 0x70, +0x65, 0x20, 0x52, 0x41, 0x4D, 0x2F, 0x52, 0x4F, +0x4D, 0x2F, 0x4F, 0x53, 0x2E, 0x00, 0x53, 0x59, +0x53, 0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x73, +0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x65, 0x73, +0x65, 0x72, 0x76, 0x65, 0x64, 0x20, 0x66, 0x6F, +0x72, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6D, +0x20, 0x75, 0x73, 0x65, 0x2E, 0x00, 0xFE, 0x49, +0x6D, 0x61, 0x67, 0x65, 0x73, 0x20, 0x6D, 0x61, +0x79, 0x20, 0x62, 0x65, 0x20, 0x27, 0x4C, 0x6F, +0x61, 0x64, 0x27, 0x65, 0x64, 0x20, 0x6F, 0x72, +0x20, 0x27, 0x53, 0x61, 0x76, 0x65, 0x27, 0x64, +0x00, 0x74, 0x6F, 0x2F, 0x66, 0x72, 0x6F, 0x6D, +0x20, 0x54, 0x50, 0x44, 0x44, 0x2E, 0x20, 0x20, +0x46, 0x69, 0x6C, 0x65, 0x6E, 0x61, 0x6D, 0x65, +0x20, 0x65, 0x78, 0x74, 0x65, 0x6E, 0x73, 0x69, +0x6F, 0x6E, 0x73, 0x20, 0x61, 0x72, 0x65, 0x00, +0x2E, 0x42, 0x58, 0x20, 0x69, 0x73, 0x20, 0x75, +0x73, 0x65, 0x64, 0x20, 0x66, 0x6F, 0x72, 0x20, +0x4F, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, +0x4F, 0x4D, 0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, +0x73, 0x00, 0x2E, 0x42, 0x59, 0x20, 0x69, 0x73, +0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x66, 0x6F, +0x72, 0x20, 0x52, 0x41, 0x4D, 0x20, 0x69, 0x6D, +0x61, 0x67, 0x65, 0x73, 0x00, 0x2E, 0x42, 0x5A, +0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, +0x20, 0x66, 0x6F, 0x72, 0x20, 0x4F, 0x53, 0x20, +0x69, 0x6D, 0x61, 0x67, 0x65, 0x73, 0x00, 0x2E, +0x42, 0x52, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, +0x65, 0x64, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x52, +0x45, 0x58, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, +0x6D, 0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x73, +0x00, 0xFE, 0x49, 0x6D, 0x61, 0x67, 0x65, 0x73, +0x20, 0x6D, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, +0x27, 0x4E, 0x61, 0x6D, 0x65, 0x27, 0x64, 0x2C, +0x20, 0x27, 0x43, 0x6F, 0x70, 0x79, 0x27, 0x64, +0x20, 0x6F, 0x72, 0x00, 0x27, 0x4B, 0x69, 0x6C, +0x6C, 0x27, 0x65, 0x64, 0x2E, 0x20, 0x55, 0x70, +0x20, 0x74, 0x6F, 0x20, 0x31, 0x36, 0x20, 0x69, +0x6D, 0x61, 0x67, 0x65, 0x73, 0x20, 0x6F, 0x66, +0x20, 0x61, 0x6E, 0x79, 0x20, 0x6F, 0x6E, 0x65, +0x00, 0x74, 0x79, 0x70, 0x65, 0x20, 0x61, 0x72, +0x65, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, +0x64, 0x2C, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, +0x32, 0x34, 0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, +0x73, 0x20, 0x69, 0x6E, 0x00, 0x74, 0x6F, 0x74, +0x61, 0x6C, 0x2E, 0x20, 0x41, 0x6E, 0x20, 0x49, +0x6D, 0x61, 0x67, 0x65, 0x20, 0x69, 0x73, 0x20, +0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x20, 0x77, +0x68, 0x65, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x75, +0x73, 0x65, 0x00, 0x62, 0x79, 0x20, 0x52, 0x45, +0x58, 0x2C, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x69, +0x73, 0x20, 0x6D, 0x61, 0x72, 0x6B, 0x65, 0x64, +0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, +0x2A, 0x2E, 0x20, 0x20, 0x54, 0x68, 0x65, 0x72, +0x65, 0x00, 0x6D, 0x75, 0x73, 0x74, 0x20, 0x61, +0x6C, 0x77, 0x61, 0x79, 0x73, 0x20, 0x62, 0x65, +0x20, 0x6F, 0x6E, 0x65, 0x20, 0x61, 0x63, 0x74, +0x69, 0x76, 0x65, 0x20, 0x52, 0x41, 0x4D, 0x20, +0x61, 0x6E, 0x64, 0x20, 0x6F, 0x6E, 0x65, 0x00, +0xFE, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, +0x52, 0x4F, 0x4D, 0x20, 0x6F, 0x72, 0x20, 0x4F, +0x53, 0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x2E, +0x00, 0x59, 0x6F, 0x75, 0x20, 0x63, 0x61, 0x6E, +0x6E, 0x6F, 0x74, 0x20, 0x6B, 0x69, 0x6C, 0x6C, +0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, +0x76, 0x65, 0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, +0x2E, 0x00, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, +0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, +0x69, 0x73, 0x20, 0x63, 0x68, 0x61, 0x6E, 0x67, +0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x65, +0x6C, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x00, +0x6F, 0x66, 0x20, 0x61, 0x20, 0x6E, 0x65, 0x77, +0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x20, 0x75, +0x73, 0x69, 0x6E, 0x67, 0x20, 0x74, 0x68, 0x65, +0x20, 0x3C, 0x65, 0x6E, 0x74, 0x3E, 0x20, 0x6B, +0x65, 0x79, 0x2E, 0x00, 0x4F, 0x53, 0x20, 0x69, +0x6D, 0x61, 0x67, 0x65, 0x73, 0x20, 0x61, 0x72, +0x65, 0x20, 0x6F, 0x70, 0x74, 0x69, 0x6F, 0x6E, +0x20, 0x52, 0x4F, 0x4D, 0x73, 0x20, 0x74, 0x68, +0x61, 0x74, 0x20, 0x61, 0x63, 0x74, 0x20, 0x61, +0x73, 0x00, 0x69, 0x6E, 0x64, 0x65, 0x70, 0x65, +0x6E, 0x64, 0x61, 0x6E, 0x74, 0x20, 0x6F, 0x70, +0x65, 0x72, 0x61, 0x74, 0x69, 0x6E, 0x67, 0x20, +0x73, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x2E, +0x00, 0xFE, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, +0x74, 0x20, 0x42, 0x69, 0x74, 0x63, 0x68, 0x69, +0x6E, 0x31, 0x30, 0x30, 0x20, 0x52, 0x45, 0x58, +0x20, 0x57, 0x69, 0x6B, 0x69, 0x20, 0x66, 0x6F, +0x72, 0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, +0x72, 0x00, 0x69, 0x6E, 0x66, 0x6F, 0x72, 0x6D, +0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x00, 0x00, +0x45, 0x6E, 0x6A, 0x6F, 0x79, 0x20, 0x79, 0x6F, +0x75, 0x72, 0x20, 0x52, 0x45, 0x58, 0x21, 0x00, +0x00, 0x53, 0x74, 0x65, 0x70, 0x68, 0x65, 0x6E, +0x20, 0x41, 0x64, 0x6F, 0x6C, 0x70, 0x68, 0x20, +0x32, 0x30, 0x31, 0x31, 0x00, 0xFF, 0x4B, 0x65, +0x79, 0x62, 0x6F, 0x61, 0x72, 0x64, 0x20, 0x43, +0x6F, 0x6D, 0x6D, 0x61, 0x6E, 0x64, 0x73, 0x00, +0x3C, 0x62, 0x3E, 0x20, 0x42, 0x6C, 0x6F, 0x63, +0x6B, 0x20, 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, +0x20, 0x69, 0x6E, 0x66, 0x6F, 0x72, 0x6D, 0x61, +0x74, 0x69, 0x6F, 0x6E, 0x00, 0x3C, 0x69, 0x3E, +0x20, 0x49, 0x6E, 0x66, 0x6F, 0x72, 0x6D, 0x61, +0x74, 0x69, 0x6F, 0x6E, 0x20, 0x6F, 0x6E, 0x20, +0x52, 0x45, 0x58, 0x20, 0x73, 0x79, 0x73, 0x74, +0x65, 0x6D, 0x00, 0x3C, 0x63, 0x3E, 0x20, 0x43, +0x68, 0x65, 0x63, 0x6B, 0x73, 0x75, 0x6D, 0x20, +0x6F, 0x66, 0x20, 0x6D, 0x65, 0x6E, 0x75, 0x20, +0x65, 0x6E, 0x74, 0x72, 0x79, 0x20, 0x69, 0x6D, +0x61, 0x67, 0x65, 0x00, 0x3C, 0x74, 0x61, 0x62, +0x3E, 0x20, 0x53, 0x68, 0x6F, 0x77, 0x20, 0x64, +0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x79, +0x20, 0x66, 0x6F, 0x72, 0x20, 0x6E, 0x65, 0x78, +0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x00, 0x3C, +0x65, 0x73, 0x63, 0x3E, 0x20, 0x72, 0x65, 0x74, +0x75, 0x72, 0x6E, 0x20, 0x74, 0x6F, 0x20, 0x6D, +0x65, 0x6E, 0x75, 0x00, 0xFE, 0x46, 0x75, 0x6E, +0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x4B, 0x65, +0x79, 0x73, 0x00, 0x3C, 0x46, 0x31, 0x3E, 0x20, +0x44, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x20, +0x68, 0x65, 0x6C, 0x70, 0x20, 0x73, 0x63, 0x72, +0x65, 0x65, 0x6E, 0x73, 0x00, 0x3C, 0x46, 0x32, +0x3E, 0x20, 0x4C, 0x6F, 0x61, 0x64, 0x20, 0x69, +0x6D, 0x61, 0x67, 0x65, 0x20, 0x66, 0x72, 0x6F, +0x6D, 0x20, 0x54, 0x50, 0x44, 0x44, 0x00, 0x3C, +0x46, 0x33, 0x3E, 0x20, 0x53, 0x65, 0x6C, 0x65, +0x63, 0x74, 0x20, 0x52, 0x4F, 0x4D, 0x20, 0x69, +0x6D, 0x61, 0x67, 0x65, 0x20, 0x66, 0x6F, 0x72, +0x20, 0x75, 0x73, 0x65, 0x00, 0x3C, 0x46, 0x37, +0x3E, 0x20, 0x44, 0x65, 0x69, 0x6E, 0x73, 0x74, +0x61, 0x6C, 0x6C, 0x20, 0x52, 0x45, 0x58, 0x20, +0x73, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, +0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x6C, 0x61, +0x70, 0x74, 0x6F, 0x70, 0x00, 0x3C, 0x46, 0x38, +0x3E, 0x20, 0x45, 0x78, 0x69, 0x74, 0x20, 0x52, +0x45, 0x58, 0x20, 0x4D, 0x61, 0x6E, 0x61, 0x67, +0x65, 0x72, 0x00, 0xFE, 0x53, 0x59, 0x53, 0x20, +0x4D, 0x65, 0x6E, 0x75, 0x20, 0x48, 0x65, 0x6C, +0x70, 0x00, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, +0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x00, +0x54, 0x68, 0x69, 0x73, 0x20, 0x6D, 0x65, 0x6E, +0x75, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, +0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6E, +0x61, 0x67, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, +0x65, 0x6D, 0x00, 0x72, 0x65, 0x6C, 0x61, 0x74, +0x65, 0x64, 0x20, 0x74, 0x61, 0x73, 0x6B, 0x73, +0x2C, 0x20, 0x70, 0x72, 0x69, 0x6D, 0x61, 0x72, +0x69, 0x6C, 0x79, 0x20, 0x6D, 0x61, 0x6E, 0x61, +0x67, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x6F, +0x66, 0x00, 0x74, 0x68, 0x65, 0x20, 0x6C, 0x6F, +0x61, 0x64, 0x65, 0x64, 0x20, 0x6D, 0x61, 0x69, +0x6E, 0x20, 0x52, 0x4F, 0x4D, 0x20, 0x69, 0x6D, +0x61, 0x67, 0x65, 0x73, 0x20, 0x75, 0x73, 0x65, +0x64, 0x20, 0x77, 0x68, 0x65, 0x6E, 0x00, 0x52, +0x45, 0x58, 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, +0x70, 0x6C, 0x61, 0x63, 0x69, 0x6E, 0x67, 0x20, +0x74, 0x68, 0x65, 0x20, 0x69, 0x6E, 0x74, 0x65, +0x72, 0x6E, 0x61, 0x6C, 0x20, 0x52, 0x4F, 0x4D, +0x73, 0x2E, 0x00, 0xFE, 0x53, 0x65, 0x65, 0x20, +0x74, 0x68, 0x65, 0x20, 0x57, 0x69, 0x6B, 0x69, +0x20, 0x66, 0x6F, 0x72, 0x20, 0x74, 0x68, 0x65, +0x20, 0x73, 0x74, 0x65, 0x70, 0x73, 0x20, 0x72, +0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x00, +0x74, 0x6F, 0x20, 0x63, 0x6F, 0x6E, 0x66, 0x69, +0x67, 0x75, 0x72, 0x65, 0x20, 0x79, 0x6F, 0x75, +0x72, 0x20, 0x6C, 0x61, 0x70, 0x74, 0x6F, 0x70, +0x20, 0x66, 0x6F, 0x72, 0x20, 0x52, 0x4F, 0x4D, +0x00, 0x52, 0x65, 0x70, 0x6C, 0x61, 0x63, 0x65, +0x6D, 0x65, 0x6E, 0x74, 0x2C, 0x20, 0x61, 0x6E, +0x64, 0x20, 0x68, 0x6F, 0x77, 0x20, 0x74, 0x6F, +0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, +0x52, 0x4F, 0x4D, 0x00, 0x69, 0x6D, 0x61, 0x67, +0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, +0x61, 0x72, 0x65, 0x20, 0x63, 0x6F, 0x6D, 0x70, +0x61, 0x74, 0x69, 0x62, 0x6C, 0x65, 0x20, 0x77, +0x69, 0x74, 0x68, 0x20, 0x52, 0x45, 0x58, 0x2E, +0x00, 0x52, 0x4F, 0x4D, 0x73, 0x20, 0x72, 0x65, +0x71, 0x75, 0x69, 0x72, 0x65, 0x20, 0x61, 0x20, +0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x20, 0x63, 0x68, +0x61, 0x6E, 0x67, 0x65, 0x20, 0x73, 0x6F, 0x20, +0x74, 0x68, 0x61, 0x74, 0x20, 0x52, 0x45, 0x58, +0x00, 0x63, 0x61, 0x6E, 0x20, 0x64, 0x65, 0x74, +0x65, 0x63, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, +0x68, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, +0x20, 0x63, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x75, +0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x00, +0xFE, 0x52, 0x45, 0x58, 0x20, 0x4D, 0x61, 0x6E, +0x61, 0x67, 0x65, 0x72, 0x20, 0x73, 0x63, 0x72, +0x65, 0x65, 0x6E, 0x73, 0x20, 0x6E, 0x6F, 0x77, +0x20, 0x69, 0x6E, 0x64, 0x69, 0x63, 0x61, 0x74, +0x65, 0x20, 0x74, 0x68, 0x65, 0x00, 0x73, 0x74, +0x61, 0x74, 0x75, 0x73, 0x20, 0x6F, 0x66, 0x20, +0x74, 0x68, 0x65, 0x20, 0x52, 0x4F, 0x4D, 0x20, +0x52, 0x65, 0x70, 0x6C, 0x61, 0x63, 0x65, 0x6D, +0x65, 0x6E, 0x74, 0x20, 0x66, 0x75, 0x6E, 0x63, +0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x00, 0x49, 0x6E, +0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6F, 0x70, +0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x63, 0x6F, +0x72, 0x6E, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, +0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, +0x00, 0x68, 0x69, 0x67, 0x68, 0x6C, 0x69, 0x67, +0x68, 0x74, 0x65, 0x64, 0x20, 0x63, 0x68, 0x61, +0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2C, 0x20, +0x6F, 0x6E, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x4D, +0x2F, 0x50, 0x2F, 0x53, 0x2E, 0x00, 0x54, 0x68, +0x69, 0x73, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, +0x63, 0x74, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x64, +0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x77, +0x68, 0x69, 0x63, 0x68, 0x20, 0x73, 0x79, 0x73, +0x74, 0x65, 0x6D, 0x00, 0x52, 0x4F, 0x4D, 0x20, +0x69, 0x73, 0x20, 0x69, 0x6E, 0x20, 0x75, 0x73, +0x65, 0x20, 0x2D, 0x20, 0x69, 0x6E, 0x74, 0x65, +0x72, 0x6E, 0x61, 0x6C, 0x20, 0x6F, 0x72, 0x20, +0x52, 0x45, 0x58, 0x20, 0x62, 0x61, 0x73, 0x65, +0x64, 0x2E, 0x00, 0xFE, 0x4D, 0x20, 0x2D, 0x20, +0x73, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64, +0x20, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x61, +0x6C, 0x20, 0x52, 0x4F, 0x4D, 0x73, 0x20, 0x69, +0x6E, 0x20, 0x75, 0x73, 0x65, 0x00, 0x50, 0x20, +0x2D, 0x20, 0x50, 0x72, 0x69, 0x6D, 0x61, 0x72, +0x79, 0x20, 0x52, 0x4F, 0x4D, 0x20, 0x28, 0x62, +0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x32, 0x29, 0x69, +0x6E, 0x20, 0x75, 0x73, 0x65, 0x00, 0x53, 0x20, +0x2D, 0x20, 0x53, 0x65, 0x63, 0x6F, 0x6E, 0x64, +0x61, 0x72, 0x79, 0x20, 0x52, 0x4F, 0x4D, 0x20, +0x28, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x34, +0x29, 0x20, 0x69, 0x6E, 0x20, 0x75, 0x73, 0x65, +0x00, 0x57, 0x68, 0x65, 0x6E, 0x20, 0x74, 0x68, +0x65, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x6E, +0x61, 0x6C, 0x20, 0x52, 0x4F, 0x4D, 0x20, 0x69, +0x73, 0x20, 0x69, 0x6E, 0x20, 0x75, 0x73, 0x65, +0x2C, 0x20, 0x52, 0x45, 0x58, 0x00, 0x63, 0x61, +0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x70, 0x72, 0x6F, +0x76, 0x69, 0x64, 0x65, 0x20, 0x52, 0x4F, 0x4D, +0x20, 0x52, 0x65, 0x70, 0x6C, 0x61, 0x63, 0x65, +0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x00, 0x50, 0x72, +0x69, 0x6D, 0x61, 0x72, 0x79, 0x20, 0x6F, 0x72, +0x20, 0x53, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x61, +0x72, 0x79, 0x20, 0x52, 0x4F, 0x4D, 0x20, 0x69, +0x6D, 0x61, 0x67, 0x65, 0x73, 0x20, 0x6D, 0x61, +0x79, 0x20, 0x62, 0x65, 0x00, 0xFE, 0x27, 0x4C, +0x6F, 0x61, 0x64, 0x27, 0x65, 0x64, 0x20, 0x76, +0x69, 0x61, 0x20, 0x73, 0x65, 0x6C, 0x65, 0x63, +0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x72, 0x6F, +0x6D, 0x20, 0x6D, 0x65, 0x6E, 0x75, 0x2E, 0x00, +0x57, 0x68, 0x65, 0x6E, 0x20, 0x74, 0x68, 0x65, +0x20, 0x6C, 0x61, 0x70, 0x74, 0x6F, 0x70, 0x20, +0x69, 0x73, 0x20, 0x63, 0x6F, 0x6E, 0x66, 0x69, +0x67, 0x75, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6F, +0x72, 0x20, 0x52, 0x4F, 0x4D, 0x73, 0x00, 0x70, +0x72, 0x6F, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, +0x62, 0x79, 0x20, 0x52, 0x45, 0x58, 0x2C, 0x20, +0x74, 0x68, 0x65, 0x20, 0x70, 0x6F, 0x77, 0x65, +0x72, 0x2D, 0x75, 0x70, 0x20, 0x64, 0x65, 0x66, +0x61, 0x75, 0x6C, 0x74, 0x20, 0x00, 0x69, 0x73, +0x20, 0x74, 0x6F, 0x20, 0x75, 0x73, 0x65, 0x20, +0x74, 0x68, 0x65, 0x20, 0x50, 0x72, 0x69, 0x6D, +0x61, 0x72, 0x79, 0x20, 0x52, 0x4F, 0x4D, 0x20, +0x69, 0x6E, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, +0x20, 0x32, 0x2E, 0x00, 0x49, 0x74, 0x20, 0x69, +0x73, 0x20, 0x61, 0x20, 0x67, 0x6F, 0x6F, 0x64, +0x20, 0x69, 0x64, 0x65, 0x61, 0x20, 0x74, 0x6F, +0x20, 0x6C, 0x65, 0x61, 0x76, 0x65, 0x20, 0x74, +0x68, 0x69, 0x73, 0x20, 0x62, 0x6C, 0x6F, 0x63, +0x6B, 0x00, 0x63, 0x6F, 0x6E, 0x66, 0x69, 0x67, +0x75, 0x72, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, +0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, +0x61, 0x6E, 0x64, 0x61, 0x72, 0x64, 0x20, 0x69, +0x6D, 0x61, 0x67, 0x65, 0x2E, 0x00, 0xFE, 0x27, +0x55, 0x73, 0x65, 0x27, 0x20, 0x63, 0x6F, 0x6D, +0x6D, 0x61, 0x6E, 0x64, 0x20, 0x61, 0x6C, 0x6C, +0x6F, 0x77, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, +0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, +0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x00, 0x65, +0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x50, 0x72, +0x69, 0x6D, 0x61, 0x72, 0x79, 0x20, 0x6F, 0x72, +0x20, 0x53, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x61, +0x72, 0x79, 0x20, 0x52, 0x4F, 0x4D, 0x73, 0x20, +0x66, 0x6F, 0x72, 0x00, 0x75, 0x73, 0x65, 0x2E, +0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, +0x65, 0x6C, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, +0x20, 0x69, 0x73, 0x20, 0x74, 0x72, 0x61, 0x63, +0x6B, 0x65, 0x64, 0x20, 0x69, 0x6E, 0x20, 0x74, +0x68, 0x65, 0x00, 0x61, 0x63, 0x74, 0x69, 0x76, +0x65, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, +0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, +0x79, 0x2C, 0x20, 0x73, 0x6F, 0x20, 0x74, 0x68, +0x61, 0x74, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, +0x6D, 0x00, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, +0x69, 0x73, 0x20, 0x61, 0x6C, 0x77, 0x61, 0x79, +0x73, 0x20, 0x72, 0x65, 0x73, 0x74, 0x6F, 0x72, +0x65, 0x64, 0x20, 0x6F, 0x6E, 0x20, 0x70, 0x6F, +0x77, 0x65, 0x72, 0x20, 0x75, 0x70, 0x2E, 0x00, +0x54, 0x69, 0x6D, 0x65, 0x73, 0x74, 0x61, 0x6D, +0x70, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, +0x65, 0x63, 0x6F, 0x72, 0x64, 0x65, 0x64, 0x20, +0x61, 0x6C, 0x73, 0x6F, 0x2E, 0x00, 0xFE, 0x4D, +0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x20, +0x61, 0x72, 0x65, 0x20, 0x73, 0x68, 0x6F, 0x77, +0x6E, 0x20, 0x61, 0x62, 0x6F, 0x76, 0x65, 0x20, +0x74, 0x68, 0x65, 0x20, 0x65, 0x6E, 0x74, 0x72, +0x69, 0x65, 0x73, 0x20, 0x74, 0x6F, 0x00, 0x67, +0x69, 0x76, 0x65, 0x20, 0x73, 0x6F, 0x6D, 0x65, +0x20, 0x69, 0x6E, 0x66, 0x6F, 0x72, 0x6D, 0x61, +0x74, 0x69, 0x6F, 0x6E, 0x20, 0x61, 0x62, 0x6F, +0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, +0x6C, 0x6F, 0x63, 0x6B, 0x00, 0x75, 0x6E, 0x64, +0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, +0x75, 0x72, 0x73, 0x6F, 0x72, 0x2E, 0x00, 0x00, +0x00, 0x00, 0xFF, 0x54, 0x68, 0x61, 0x6E, 0x6B, +0x73, 0x20, 0x74, 0x6F, 0x3A, 0x00, 0x4A, 0x6F, +0x68, 0x6E, 0x20, 0x48, 0x6F, 0x67, 0x65, 0x72, +0x68, 0x75, 0x69, 0x73, 0x3A, 0x20, 0x62, 0x72, +0x6F, 0x61, 0x64, 0x20, 0x74, 0x65, 0x63, 0x68, +0x6E, 0x69, 0x63, 0x61, 0x6C, 0x20, 0x73, 0x75, +0x70, 0x70, 0x6F, 0x72, 0x74, 0x00, 0x50, 0x68, +0x69, 0x6C, 0x69, 0x70, 0x20, 0x41, 0x76, 0x65, +0x72, 0x79, 0x3A, 0x20, 0x4D, 0x45, 0x4E, 0x55, +0x20, 0x63, 0x6F, 0x64, 0x65, 0x20, 0x63, 0x6F, +0x6E, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, +0x6F, 0x6E, 0x73, 0x00, 0x57, 0x69, 0x6C, 0x73, +0x6F, 0x6E, 0x20, 0x56, 0x61, 0x6E, 0x20, 0x41, +0x6C, 0x73, 0x74, 0x3A, 0x20, 0x62, 0x61, 0x73, +0x65, 0x20, 0x54, 0x50, 0x44, 0x44, 0x20, 0x72, +0x6F, 0x75, 0x74, 0x69, 0x6E, 0x65, 0x73, 0x00, +0x4B, 0x65, 0x6E, 0x20, 0x50, 0x65, 0x74, 0x74, +0x69, 0x74, 0x3A, 0x20, 0x66, 0x6F, 0x72, 0x20, +0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6C, 0x54, +0x21, 0x00, 0x2E, 0x2E, 0x2E, 0x61, 0x6E, 0x64, +0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x6F, 0x74, +0x68, 0x65, 0x72, 0x73, 0x20, 0x66, 0x6F, 0x72, +0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x66, +0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6B, 0x00, +0xFF, 0x41, 0x72, 0x72, 0x6F, 0x77, 0x2C, 0x20, +0x73, 0x68, 0x69, 0x66, 0x74, 0x2D, 0x61, 0x72, +0x72, 0x6F, 0x77, 0x20, 0x74, 0x6F, 0x20, 0x62, +0x72, 0x6F, 0x77, 0x73, 0x65, 0x00, 0x3C, 0x46, +0x31, 0x3E, 0x20, 0x44, 0x69, 0x73, 0x70, 0x6C, +0x61, 0x79, 0x20, 0x68, 0x65, 0x6C, 0x70, 0x20, +0x73, 0x63, 0x72, 0x65, 0x65, 0x6E, 0x73, 0x00, +0x3C, 0x46, 0x33, 0x3E, 0x20, 0x43, 0x6F, 0x70, +0x79, 0x20, 0x66, 0x69, 0x6C, 0x65, 0x20, 0x66, +0x72, 0x6F, 0x6D, 0x20, 0x52, 0x45, 0x58, 0x20, +0x69, 0x6D, 0x61, 0x67, 0x65, 0x20, 0x2D, 0x2D, +0x3E, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x00, 0x3C, +0x46, 0x34, 0x3E, 0x20, 0x4B, 0x69, 0x6C, 0x6C, +0x20, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x20, 0x66, +0x69, 0x6C, 0x65, 0x00, 0x3C, 0x46, 0x35, 0x3E, +0x20, 0x4E, 0x61, 0x6D, 0x65, 0x20, 0x6C, 0x6F, +0x63, 0x61, 0x6C, 0x20, 0x66, 0x69, 0x6C, 0x65, +0x00, 0x3C, 0x46, 0x38, 0x3E, 0x20, 0x45, 0x78, +0x69, 0x74, 0x20, 0x46, 0x69, 0x6C, 0x65, 0x20, +0x4D, 0x65, 0x6E, 0x75, 0x00, 0xFF, 0xCD, 0x53, +0x1A, 0xCD, 0x44, 0x1A, 0x3A, 0xCB, 0xFC, 0xCD, +0xFA, 0x19, 0x21, 0x86, 0x2F, 0x3A, 0xD9, 0xFC, +0xFE, 0x03, 0xC2, 0x80, 0x2F, 0x21, 0xB3, 0x2F, +0x22, 0xC2, 0xFC, 0xC3, 0x35, 0x30, 0xCD, 0x01, +0x33, 0xCA, 0xAD, 0x2F, 0xCD, 0x03, 0x30, 0xCD, +0x19, 0x33, 0xCA, 0x9E, 0x2F, 0x11, 0x85, 0xF6, +0xCD, 0x3F, 0x1B, 0xC3, 0xAD, 0x2F, 0xCD, 0x69, +0x1B, 0xCD, 0x2C, 0x30, 0x21, 0x09, 0x08, 0x22, +0xC2, 0xFC, 0xC3, 0x67, 0x32, 0xCD, 0x2C, 0x30, +0xC3, 0x09, 0x08, 0xCD, 0x01, 0x33, 0xCA, 0xAD, +0x2F, 0xCD, 0x19, 0x33, 0xCA, 0xF1, 0x2F, 0x3A, +0xCE, 0xFC, 0x47, 0x3A, 0xCB, 0xFC, 0x4F, 0x78, +0xC5, 0xCD, 0x0B, 0x1B, 0xC1, 0x78, 0x41, 0x4F, +0xC5, 0xCD, 0xE1, 0x09, 0xC1, 0x78, 0xC5, 0xCD, +0x0B, 0x1B, 0xC1, 0x79, 0x32, 0xCB, 0xFC, 0xCD, +0x73, 0x1B, 0xCD, 0x6F, 0x1B, 0xCD, 0x03, 0x30, +0x11, 0x85, 0xF6, 0xCD, 0x3F, 0x1B, 0xC3, 0xAD, +0x2F, 0x3A, 0xCB, 0xFC, 0xCD, 0x0B, 0x1B, 0xC3, +0xA1, 0x2F, 0x78, 0xEE, 0x01, 0x47, 0x79, 0xEE, +0x01, 0x4F, 0xC9, 0x3A, 0xD9, 0xFC, 0x32, 0xDA, +0xFC, 0x3E, 0xFF, 0xCD, 0x7B, 0x1B, 0xE5, 0x3A, +0xCB, 0xFC, 0xCD, 0x51, 0x1B, 0xE1, 0xE5, 0xCD, +0x56, 0x1B, 0xCD, 0xB8, 0x1C, 0xE1, 0xE5, 0xCD, +0x9F, 0x1D, 0xCD, 0xD2, 0x1C, 0xE1, 0xE5, 0xCD, +0xA7, 0x1D, 0xE1, 0xC9, 0xCD, 0x10, 0x33, 0xCD, +0xF8, 0x32, 0xC3, 0xCA, 0x02, 0xCD, 0x9A, 0x30, +0xCD, 0x9C, 0x32, 0xCA, 0xFA, 0x1A, 0xCD, 0x33, +0x33, 0xCA, 0xFA, 0x1A, 0xCD, 0x36, 0x03, 0x21, +0x67, 0x33, 0xCD, 0xA6, 0x30, 0xCD, 0xFC, 0x16, +0xCD, 0xB9, 0x30, 0x21, 0x85, 0xF6, 0x7E, 0x32, +0xD3, 0xFC, 0x3E, 0x03, 0x77, 0x21, 0x01, 0x01, +0xCD, 0x34, 0x31, 0x21, 0x85, 0xF6, 0x3A, 0xD3, +0xFC, 0x77, 0xCD, 0xEF, 0x32, 0x21, 0x03, 0x00, +0xCD, 0x34, 0x31, 0xEB, 0x3A, 0xCB, 0xFC, 0x4F, +0x2A, 0xD1, 0xFC, 0xCD, 0x46, 0xFD, 0x22, 0xD1, +0xFC, 0x7C, 0xE6, 0x03, 0xB5, 0xC2, 0x8C, 0x30, +0x3E, 0xFF, 0xD3, 0xFF, 0x2A, 0xD1, 0xFC, 0x7C, +0x17, 0xD2, 0x6D, 0x30, 0x21, 0x7C, 0x33, 0xC3, +0xCC, 0x30, 0xCD, 0x2A, 0x33, 0xCD, 0x1F, 0x33, +0xCD, 0x10, 0x33, 0xC3, 0xF8, 0x32, 0xCD, 0x30, +0x02, 0x16, 0x09, 0x21, 0x85, 0xF6, 0xCD, 0xA9, +0x02, 0xF3, 0xCD, 0x9C, 0x18, 0xCD, 0x46, 0xFD, +0xC9, 0x21, 0x00, 0x00, 0x22, 0xD1, 0xFC, 0x21, +0x07, 0x00, 0xCD, 0x34, 0x31, 0x21, 0x00, 0x1A, +0xCD, 0x34, 0x31, 0xC9, 0xFB, 0xCD, 0x30, 0x02, +0x21, 0x02, 0x00, 0xCD, 0x34, 0x31, 0xCD, 0x07, +0x33, 0xC3, 0xFA, 0x1A, 0xCD, 0x9A, 0x30, 0xCD, +0xAC, 0x32, 0xCA, 0xFA, 0x1A, 0xCD, 0x33, 0x33, +0xCA, 0xFA, 0x1A, 0x21, 0x72, 0x33, 0xCD, 0xA6, +0x30, 0xCD, 0x25, 0x17, 0xCD, 0xB9, 0x30, 0x21, +0x01, 0x01, 0x3E, 0x01, 0x32, 0x85, 0xF6, 0xCD, +0x34, 0x31, 0x2A, 0xD1, 0xFC, 0x3A, 0xCE, 0xFC, +0x4F, 0x11, 0x85, 0xF6, 0xCD, 0x46, 0xFD, 0x22, +0xD1, 0xFC, 0x21, 0x04, 0x80, 0xCD, 0x34, 0x31, +0x2A, 0xD1, 0xFC, 0x7C, 0xE6, 0x03, 0xB5, 0xC2, +0x26, 0x31, 0x3E, 0xFF, 0xD3, 0xFF, 0x2A, 0xD1, +0xFC, 0x7C, 0x17, 0xD2, 0x02, 0x31, 0x21, 0x91, +0x33, 0xCD, 0xCC, 0x30, 0xF3, 0x0E, 0x00, 0x11, +0x83, 0xF6, 0xD9, 0x24, 0x24, 0x3E, 0x5A, 0xCD, +0x85, 0x32, 0xCD, 0x85, 0x32, 0x1A, 0xCD, 0x85, +0x32, 0x81, 0x4F, 0x13, 0x25, 0xC2, 0x45, 0x31, +0xEB, 0x01, 0x20, 0x00, 0x09, 0x22, 0xCF, 0xFC, +0xEB, 0x13, 0x2F, 0xCD, 0x85, 0x32, 0x21, 0x00, +0x10, 0x22, 0xD7, 0xFC, 0x2A, 0xCF, 0xFC, 0xAF, +0x77, 0x20, 0xE6, 0x20, 0xC2, 0x84, 0x31, 0x3E, +0x20, 0x3D, 0xC2, 0x71, 0x31, 0x2A, 0xD7, 0xFC, +0x2B, 0x22, 0xD7, 0xFC, 0x7C, 0xB5, 0xCA, 0x6D, +0x32, 0xC3, 0x69, 0x31, 0x21, 0x00, 0x10, 0x22, +0xD7, 0xFC, 0xAF, 0xDB, 0xC8, 0x2A, 0xCF, 0xFC, +0x4E, 0x77, 0x81, 0x23, 0x77, 0x22, 0xCF, 0xFC, +0x1A, 0x3C, 0x3C, 0x4F, 0x06, 0x00, 0x08, 0x7C, +0xBA, 0xC2, 0x69, 0x31, 0x7D, 0xBB, 0xC2, 0x69, +0x31, 0x2A, 0xCF, 0xFC, 0x7E, 0x2B, 0x96, 0xEE, +0xFF, 0xBE, 0xC2, 0x79, 0x32, 0xEB, 0x2B, 0x46, +0x23, 0x23, 0xAF, 0x86, 0x4F, 0xC5, 0x78, 0xD6, +0x12, 0xC1, 0x79, 0xC0, 0xB7, 0xC8, 0xE6, 0xF0, +0x0F, 0x0F, 0x0F, 0x21, 0xD7, 0x31, 0x4F, 0x06, +0x00, 0x09, 0xEB, 0xED, 0xC3, 0xED, 0x1A, 0xE9, +0x31, 0xFB, 0x31, 0x0B, 0x32, 0x19, 0x32, 0x27, +0x32, 0x32, 0x32, 0x42, 0x32, 0x4C, 0x32, 0x58, +0x32, 0x55, 0x6E, 0x73, 0x70, 0x65, 0x63, 0x69, +0x66, 0x69, 0x65, 0x64, 0x20, 0x65, 0x72, 0x72, +0x6F, 0x72, 0x00, 0x46, 0x69, 0x6C, 0x65, 0x20, +0x6E, 0x61, 0x6D, 0x65, 0x20, 0x65, 0x72, 0x72, +0x6F, 0x72, 0x00, 0x55, 0x6E, 0x6B, 0x6E, 0x6F, +0x77, 0x6E, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, +0x00, 0x43, 0x6F, 0x6D, 0x6D, 0x61, 0x6E, 0x64, +0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x00, 0x52, +0x65, 0x61, 0x64, 0x20, 0x65, 0x72, 0x72, 0x6F, +0x72, 0x00, 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, +0x70, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x65, +0x64, 0x00, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x66, +0x75, 0x6C, 0x6C, 0x00, 0x49, 0x6E, 0x73, 0x65, +0x72, 0x74, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x00, +0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, +0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x00, 0x21, +0x11, 0x34, 0xC3, 0xED, 0x1A, 0x21, 0x2D, 0x34, +0xC3, 0xED, 0x1A, 0x21, 0xFA, 0x33, 0xC3, 0xED, +0x1A, 0x21, 0xC2, 0x33, 0xC3, 0xED, 0x1A, 0x21, +0xA6, 0x33, 0xC3, 0xED, 0x1A, 0xF5, 0xE5, 0x21, +0x00, 0x00, 0x2B, 0x7C, 0xB5, 0xCA, 0x73, 0x32, +0xDB, 0xD8, 0xE6, 0x10, 0xCA, 0x8A, 0x32, 0xE1, +0xF1, 0xD3, 0xC8, 0xC9, 0x21, 0x48, 0x33, 0xCD, +0x30, 0x02, 0x21, 0x08, 0x1E, 0xCD, 0x57, 0x19, +0xC8, 0xC3, 0xC9, 0x32, 0x3A, 0xCE, 0xFC, 0xCD, +0x73, 0x1B, 0x23, 0x11, 0x85, 0xF6, 0x06, 0x06, +0x7E, 0xC5, 0xE5, 0xD5, 0xF7, 0xE9, 0x0F, 0xD1, +0xE1, 0xC1, 0x12, 0x23, 0x13, 0x05, 0xC2, 0xB8, +0x32, 0x21, 0x8B, 0xF6, 0x06, 0x12, 0xCD, 0xDD, +0x02, 0x11, 0x46, 0x00, 0xEB, 0xD9, 0x21, 0x8B, +0xF6, 0x36, 0x2E, 0x23, 0xE5, 0x21, 0x40, 0x33, +0x3A, 0xD9, 0xFC, 0x07, 0x5F, 0xAF, 0x57, 0x19, +0xEB, 0xED, 0xD1, 0xD9, 0xF6, 0x01, 0xC9, 0x3A, +0xC0, 0xFC, 0xF6, 0x40, 0x32, 0xC0, 0xFC, 0xC9, +0x3A, 0xC0, 0xFC, 0xE6, 0xBF, 0x32, 0xC0, 0xFC, +0xC9, 0x3A, 0xC0, 0xFC, 0xE6, 0x40, 0xC9, 0x3A, +0xC0, 0xFC, 0xF6, 0x80, 0x32, 0xC0, 0xFC, 0xC9, +0x3A, 0xC0, 0xFC, 0xE6, 0x7F, 0x32, 0xC0, 0xFC, +0xC9, 0x3A, 0xC0, 0xFC, 0xE6, 0x80, 0xC9, 0x3E, +0xFF, 0xC6, 0x01, 0x21, 0xE4, 0xFC, 0xF7, 0xE6, +0x17, 0xC9, 0xDB, 0xBA, 0xE6, 0xBF, 0xF6, 0x80, +0xD3, 0xBA, 0xC9, 0x21, 0xDD, 0x33, 0xCD, 0x30, +0x02, 0xCD, 0x19, 0x1B, 0xCA, 0xF6, 0x1A, 0xC9, +0x42, 0x59, 0x42, 0x58, 0x42, 0x5A, 0x42, 0x52, +0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, +0x66, 0x72, 0x6F, 0x6D, 0x20, 0x69, 0x6D, 0x61, +0x67, 0x65, 0x20, 0x66, 0x69, 0x6C, 0x65, 0x20, +0x6E, 0x61, 0x6D, 0x65, 0x3A, 0x20, 0x00, 0x4C, +0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x30, +0x3A, 0x00, 0x53, 0x61, 0x76, 0x69, 0x6E, 0x67, +0x20, 0x30, 0x3A, 0x00, 0x4C, 0x6F, 0x61, 0x64, +0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x20, 0x63, +0x6F, 0x6D, 0x70, 0x6C, 0x65, 0x74, 0x65, 0x21, +0x00, 0x53, 0x61, 0x76, 0x65, 0x20, 0x69, 0x6D, +0x61, 0x67, 0x65, 0x20, 0x63, 0x6F, 0x6D, 0x70, +0x6C, 0x65, 0x74, 0x65, 0x21, 0x00, 0x45, 0x53, +0x43, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x70, 0x72, +0x65, 0x73, 0x73, 0x65, 0x64, 0x2E, 0x2E, 0x2E, +0x61, 0x62, 0x6F, 0x72, 0x74, 0x69, 0x6E, 0x67, +0x2E, 0x00, 0x43, 0x68, 0x65, 0x63, 0x6B, 0x73, +0x75, 0x6D, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, +0x2E, 0x2E, 0x2E, 0x61, 0x62, 0x6F, 0x72, 0x74, +0x69, 0x6E, 0x67, 0x2E, 0x00, 0x48, 0x69, 0x74, +0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, +0x20, 0x77, 0x68, 0x65, 0x6E, 0x20, 0x54, 0x50, +0x44, 0x44, 0x20, 0x72, 0x65, 0x61, 0x64, 0x79, +0x2E, 0x00, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x20, +0x73, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, +0x63, 0x6F, 0x6D, 0x6D, 0x61, 0x6E, 0x64, 0x21, +0x00, 0x4C, 0x6F, 0x61, 0x64, 0x20, 0x66, 0x69, +0x6C, 0x65, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, +0x54, 0x50, 0x44, 0x44, 0x20, 0x66, 0x61, 0x69, +0x6C, 0x65, 0x64, 0x21, 0x00, 0x4E, 0x6F, 0x20, +0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, +0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x54, 0x50, +0x44, 0x44, 0x21, 0x00, 0xCD, 0xFE, 0x1A, 0xAF, +0x32, 0xCA, 0xFC, 0x32, 0xD3, 0xFC, 0x21, 0xF0, +0x43, 0x11, 0x10, 0x00, 0x19, 0x7E, 0xA7, 0xCA, +0x51, 0x34, 0xFE, 0xFF, 0xCA, 0xA3, 0x34, 0xE6, +0x3F, 0x4F, 0xEB, 0x06, 0x00, 0x21, 0x46, 0xFD, +0x09, 0xEB, 0xE5, 0x01, 0x07, 0x00, 0x09, 0x4E, +0xE1, 0x7E, 0xE6, 0xC0, 0x81, 0x12, 0xE6, 0xC0, +0xFE, 0xC0, 0xC2, 0x92, 0x34, 0x3A, 0xD3, 0xFC, +0x3C, 0x32, 0xD3, 0xFC, 0x3A, 0xD9, 0xFC, 0xB9, +0xC2, 0x92, 0x34, 0x3A, 0xCA, 0xFC, 0x3C, 0x32, +0xCA, 0xFC, 0x7E, 0xE6, 0x3F, 0xEB, 0x21, 0x66, +0xFD, 0x87, 0x4F, 0x06, 0x00, 0x09, 0xEB, 0xD9, +0xC3, 0x51, 0x34, 0x3A, 0xD3, 0xFC, 0x47, 0x3A, +0xD9, 0xFC, 0xFE, 0x03, 0xC0, 0x3E, 0x02, 0x32, +0xCA, 0xFC, 0xC9, 0xCD, 0xB9, 0x00, 0x3A, 0xCD, +0xFC, 0xFE, 0x06, 0xFA, 0x1D, 0x36, 0xFE, 0x20, +0xF2, 0x1D, 0x36, 0x3A, 0xCC, 0xFC, 0xFE, 0x06, +0xFA, 0x1D, 0x36, 0xFE, 0x20, 0xF2, 0x1D, 0x36, +0xCD, 0xFE, 0x1A, 0x3E, 0xFF, 0x32, 0xD1, 0xFC, +0xAF, 0x32, 0xD3, 0xFC, 0x32, 0xCA, 0xFC, 0x21, +0xF0, 0x43, 0x22, 0xCF, 0xFC, 0x3A, 0xD1, 0xFC, +0x2F, 0x32, 0xD1, 0xFC, 0x11, 0x10, 0x00, 0x19, +0xE5, 0x01, 0x00, 0x50, 0x08, 0xE1, 0xCA, 0xA2, +0x35, 0x3A, 0xD1, 0xFC, 0xA6, 0x47, 0x3A, 0xD1, +0xFC, 0xB8, 0xC2, 0xE4, 0x35, 0x7E, 0xA7, 0xCA, +0xEC, 0x34, 0x7E, 0xFE, 0xFF, 0xCA, 0x97, 0x35, +0x7E, 0xE6, 0xC0, 0xCA, 0x3B, 0x36, 0x01, 0x07, +0x00, 0xE5, 0x09, 0x7E, 0xE1, 0x46, 0xFE, 0x03, +0xC2, 0x33, 0x35, 0x78, 0xE6, 0x3F, 0xFE, 0x06, +0xF2, 0x35, 0x36, 0xFE, 0x00, 0xFA, 0x35, 0x36, +0xC3, 0x4A, 0x35, 0xFE, 0x03, 0xF2, 0x2F, 0x36, +0xFE, 0x00, 0xFA, 0x2F, 0x36, 0x78, 0xE6, 0x3F, +0xFE, 0x06, 0xFA, 0x35, 0x36, 0xFE, 0x32, 0xF2, +0x35, 0x36, 0x7E, 0xEB, 0xF5, 0xE6, 0x3F, 0x4F, +0x06, 0x00, 0xF1, 0x21, 0x46, 0xFD, 0x09, 0xEB, +0xE5, 0x01, 0x07, 0x00, 0x09, 0x7E, 0xE1, 0x4F, +0x1A, 0xB7, 0xC2, 0xF0, 0x35, 0x7E, 0xE6, 0xC0, +0x81, 0x12, 0xE6, 0xC0, 0xFE, 0xC0, 0xC2, 0x86, +0x35, 0x3A, 0xD3, 0xFC, 0x3C, 0x32, 0xD3, 0xFC, +0x3A, 0xD9, 0xFC, 0xB9, 0xC2, 0x86, 0x35, 0x3A, +0xCA, 0xFC, 0x3C, 0x32, 0xCA, 0xFC, 0x7E, 0xE6, +0x3F, 0xEB, 0x21, 0x66, 0xFD, 0x87, 0x4F, 0x06, +0x00, 0x09, 0xEB, 0xD9, 0xC3, 0xEC, 0x34, 0x3A, +0xD1, 0xFC, 0xFE, 0xFF, 0xCA, 0xEC, 0x34, 0xC3, +0xE2, 0x34, 0x11, 0x46, 0xFD, 0x01, 0xC3, 0xC3, +0x3E, 0x03, 0xD5, 0xED, 0x08, 0xD1, 0xC2, 0x17, +0x36, 0x13, 0x13, 0x3D, 0xC2, 0xAA, 0x35, 0x3A, +0xCD, 0xFC, 0x4F, 0x06, 0x00, 0x21, 0x46, 0xFD, +0x09, 0x7E, 0xFE, 0xC0, 0xC2, 0x23, 0x36, 0x3A, +0xCC, 0xFC, 0x4F, 0x06, 0x00, 0x21, 0x46, 0xFD, +0x09, 0x7E, 0xFE, 0xC0, 0xCA, 0x29, 0x36, 0xFA, +0x29, 0x36, 0xFE, 0xC3, 0xF2, 0x29, 0x36, 0x3A, +0xD3, 0xFC, 0x47, 0xC9, 0x21, 0x5A, 0x36, 0xCD, +0x30, 0x02, 0x2A, 0xCF, 0xFC, 0xC3, 0x4A, 0x36, +0x7E, 0xE6, 0xC0, 0xFE, 0xC0, 0xC2, 0x08, 0x36, +0xEB, 0x01, 0x46, 0xFD, 0x08, 0x7D, 0x21, 0x66, +0xFD, 0x87, 0x4F, 0x06, 0x00, 0x09, 0xEB, 0xED, +0xCD, 0x6F, 0x1B, 0x21, 0xA2, 0x36, 0xCD, 0x30, +0x02, 0xCD, 0x22, 0x1B, 0xC3, 0xB3, 0x34, 0x21, +0xBF, 0x36, 0xC3, 0x53, 0x36, 0x21, 0xDA, 0x36, +0xC3, 0x53, 0x36, 0x21, 0xFF, 0x36, 0xC3, 0x53, +0x36, 0x21, 0x1C, 0x37, 0xC3, 0x53, 0x36, 0x11, +0x40, 0x37, 0xC3, 0x44, 0x36, 0x11, 0x59, 0x37, +0xC3, 0x44, 0x36, 0x11, 0x73, 0x36, 0xC3, 0x44, +0x36, 0x11, 0x8B, 0x36, 0xEB, 0xD5, 0xCD, 0x30, +0x02, 0xE1, 0xCD, 0x6F, 0x1B, 0xCD, 0x22, 0x1B, +0xC3, 0xB3, 0x34, 0xCD, 0x30, 0x02, 0xCD, 0x22, +0x1B, 0xC9, 0x46, 0x46, 0x20, 0x65, 0x6E, 0x63, +0x6F, 0x75, 0x6E, 0x74, 0x65, 0x72, 0x65, 0x64, +0x20, 0x65, 0x61, 0x72, 0x6C, 0x79, 0x20, 0x2E, +0x2E, 0x2E, 0x00, 0x42, 0x61, 0x64, 0x20, 0x64, +0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x79, +0x20, 0x65, 0x6E, 0x74, 0x72, 0x79, 0x20, 0x2E, +0x2E, 0x2E, 0x00, 0x42, 0x6C, 0x6F, 0x63, 0x6B, +0x20, 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x20, +0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x2E, 0x2E, +0x2E, 0x00, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, +0x65, 0x64, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, +0x74, 0x6F, 0x72, 0x79, 0x20, 0x65, 0x6E, 0x74, +0x72, 0x79, 0x20, 0x2E, 0x2E, 0x2E, 0x00, 0x4D, +0x69, 0x73, 0x73, 0x69, 0x6E, 0x67, 0x20, 0x73, +0x79, 0x73, 0x74, 0x65, 0x6D, 0x20, 0x65, 0x6E, +0x74, 0x72, 0x69, 0x65, 0x73, 0x20, 0x2E, 0x2E, +0x2E, 0x00, 0x42, 0x61, 0x64, 0x20, 0x6F, 0x72, +0x20, 0x6D, 0x69, 0x73, 0x73, 0x69, 0x6E, 0x67, +0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, +0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x69, 0x6E, +0x66, 0x6F, 0x20, 0x2E, 0x2E, 0x2E, 0x00, 0x41, +0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x52, 0x41, +0x4D, 0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x20, +0x6D, 0x69, 0x73, 0x73, 0x69, 0x6E, 0x67, 0x20, +0x2E, 0x2E, 0x2E, 0x00, 0x41, 0x63, 0x74, 0x69, +0x76, 0x65, 0x20, 0x4F, 0x50, 0x54, 0x49, 0x4F, +0x4E, 0x20, 0x52, 0x4F, 0x4D, 0x20, 0x69, 0x6D, +0x61, 0x67, 0x65, 0x20, 0x6D, 0x69, 0x73, 0x73, +0x69, 0x6E, 0x67, 0x20, 0x2E, 0x2E, 0x2E, 0x00, +0x49, 0x6E, 0x63, 0x6F, 0x72, 0x72, 0x65, 0x63, +0x74, 0x20, 0x65, 0x6E, 0x74, 0x72, 0x79, 0x20, +0x74, 0x79, 0x70, 0x65, 0x20, 0x2E, 0x2E, 0x2E, +0x00, 0x45, 0x6E, 0x74, 0x72, 0x79, 0x20, 0x62, +0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6F, 0x75, 0x74, +0x20, 0x6F, 0x66, 0x20, 0x72, 0x61, 0x6E, 0x67, +0x65, 0x20, 0x2E, 0x2E, 0x2E, 0x00, 0xF5, 0xCD, +0x44, 0x1A, 0xF1, 0xCD, 0x0B, 0x1B, 0xC9, 0x3A, +0xD9, 0xFC, 0xFE, 0x03, 0xCA, 0xC4, 0x37, 0xCD, +0x68, 0x38, 0x3A, 0xCA, 0xFC, 0xB7, 0xC8, 0xFE, +0x01, 0xC8, 0x0E, 0xFF, 0x06, 0x00, 0x0C, 0x3A, +0xCA, 0xFC, 0x3D, 0xB9, 0xC8, 0xCD, 0xCD, 0x37, +0xEB, 0xED, 0xE5, 0x0C, 0xCD, 0xCD, 0x37, 0x0D, +0xEB, 0xED, 0xEB, 0xE1, 0xC5, 0xCD, 0xDB, 0x37, +0xC1, 0xCA, 0x96, 0x37, 0xFA, 0x96, 0x37, 0x21, +0xA6, 0xFD, 0x09, 0xEB, 0xED, 0x7C, 0x65, 0x6F, +0xD9, 0xC3, 0x92, 0x37, 0x21, 0xA6, 0xFD, 0x36, +0x02, 0x23, 0x36, 0x04, 0xC9, 0x21, 0xA6, 0xFD, +0x09, 0x7E, 0x87, 0x21, 0x66, 0xFD, 0x16, 0x00, +0x5F, 0x19, 0xC9, 0xC5, 0xE5, 0xD5, 0x01, 0x08, +0x00, 0xCD, 0xF7, 0x37, 0xD1, 0xE1, 0xCA, 0xEF, +0x37, 0xFA, 0xF5, 0x37, 0xF2, 0xF5, 0x37, 0x01, +0x0A, 0x00, 0xCD, 0xF7, 0x37, 0xC1, 0xC9, 0x09, +0xEB, 0x09, 0x46, 0x23, 0x4E, 0xEB, 0x56, 0x23, +0x5E, 0xEB, 0x08, 0xC8, 0xF5, 0x3A, 0xC0, 0xFC, +0xE6, 0x08, 0xCA, 0x14, 0x38, 0xF1, 0xF2, 0x1B, +0x38, 0xFA, 0x1F, 0x38, 0xF1, 0xFA, 0x1B, 0x38, +0xF2, 0x1F, 0x38, 0xAF, 0xC6, 0x10, 0xC9, 0xAF, +0xD6, 0x10, 0xC9, 0xE5, 0x0E, 0x06, 0x06, 0x00, +0x79, 0xFE, 0x20, 0xCA, 0x60, 0x38, 0x3A, 0xCB, +0xFC, 0xB9, 0xCA, 0x5B, 0x38, 0xEE, 0x01, 0xB9, +0xCA, 0x5B, 0x38, 0x21, 0x46, 0xFD, 0x09, 0x7E, +0xE6, 0xC0, 0xF5, 0x23, 0x7E, 0xE6, 0xC0, 0x67, +0xF1, 0x6F, 0xF7, 0x18, 0x00, 0xCA, 0x65, 0x38, +0x7C, 0x65, 0x6F, 0x0C, 0xF7, 0x18, 0x00, 0xCA, +0x65, 0x38, 0x0D, 0x0C, 0x0C, 0xC3, 0x28, 0x38, +0xF6, 0x01, 0xC3, 0x66, 0x38, 0xAF, 0xE1, 0xC9, +0x11, 0xA6, 0xFD, 0x06, 0x20, 0xCD, 0x03, 0x1B, +0x0E, 0xFF, 0x06, 0x32, 0x11, 0xA6, 0xFD, 0x21, +0x45, 0xFD, 0x3A, 0xD9, 0xFC, 0xF6, 0xC0, 0x0C, +0x23, 0x05, 0xC8, 0xBE, 0xC2, 0x7F, 0x38, 0xEB, +0x71, 0xEB, 0x13, 0xC3, 0x7F, 0x38, 0x21, 0x9C, +0x38, 0x22, 0xC2, 0xFC, 0xF7, 0x31, 0x42, 0x3E, +0x0F, 0x32, 0xDF, 0xFC, 0xCD, 0x70, 0x17, 0x3E, +0x80, 0x32, 0xDE, 0xFC, 0x32, 0xC9, 0xFC, 0x32, +0xC8, 0xFC, 0x21, 0x01, 0x01, 0x22, 0xE0, 0xFC, +0xAF, 0x3D, 0x32, 0xC5, 0xFC, 0xCD, 0xD5, 0x3B, +0xCD, 0x8E, 0x3B, 0xCD, 0x0E, 0x3A, 0xAF, 0x32, +0xDE, 0xFC, 0xCD, 0xEF, 0x39, 0xCD, 0xF9, 0x39, +0xCD, 0xA0, 0x3A, 0x3E, 0x80, 0x32, 0xDE, 0xFC, +0xCD, 0xEF, 0x39, 0xCD, 0xF9, 0x39, 0x3E, 0xFF, +0x32, 0xC5, 0xFC, 0x3A, 0xC5, 0xFC, 0xB7, 0xCA, +0xF2, 0x38, 0xCD, 0xA0, 0x3A, 0x3A, 0xC9, 0xFC, +0xCD, 0xA6, 0x13, 0xCD, 0xF0, 0x3B, 0xAF, 0x32, +0xC5, 0xFC, 0x3A, 0xC9, 0xFC, 0xE6, 0x80, 0x6F, +0x3A, 0xC8, 0xFC, 0xE6, 0x80, 0xBD, 0xC4, 0xF0, +0x3B, 0xCD, 0x89, 0x13, 0x3A, 0xC9, 0xFC, 0x32, +0xC8, 0xFC, 0xF7, 0x42, 0x72, 0xCA, 0x0A, 0x39, +0xDA, 0x52, 0x3C, 0xF7, 0xE9, 0x0F, 0xCD, 0x1C, +0x39, 0xC3, 0xDB, 0x38, 0xF5, 0x2A, 0xC9, 0xFC, +0x3A, 0xC7, 0xFC, 0x47, 0x7D, 0xE6, 0x7F, 0x6F, +0xF1, 0xFE, 0x1D, 0xCA, 0x5C, 0x39, 0xFE, 0x1C, +0xCA, 0x5C, 0x39, 0x25, 0x24, 0xC8, 0xFE, 0x1F, +0xCA, 0x4B, 0x39, 0xFE, 0x1E, 0xCA, 0x4D, 0x39, +0xFE, 0x14, 0xCA, 0x51, 0x39, 0xFE, 0x02, 0xCA, +0x55, 0x39, 0xC9, 0x2C, 0x2C, 0x2D, 0xC3, 0x7E, +0x39, 0x78, 0xD6, 0x0C, 0x47, 0x78, 0xC6, 0x06, +0x47, 0xC3, 0x7E, 0x39, 0x3A, 0xDE, 0xFC, 0xF5, +0xB5, 0x32, 0xC8, 0xFC, 0xF1, 0xEE, 0x80, 0x32, +0xDE, 0xFC, 0xCD, 0xEF, 0x39, 0x47, 0xCD, 0xF9, +0x39, 0x67, 0x25, 0x24, 0xC2, 0x7E, 0x39, 0x06, +0x01, 0x2E, 0x00, 0xC3, 0xAA, 0x39, 0x78, 0xFE, +0x01, 0xFA, 0xD3, 0x39, 0x7D, 0xFE, 0x00, 0xFA, +0xC7, 0x39, 0xFE, 0x06, 0xF2, 0xCD, 0x39, 0xBC, +0xF2, 0xD9, 0x39, 0x7C, 0x90, 0xBD, 0xFA, 0xD5, +0x39, 0x7C, 0xD6, 0x05, 0x57, 0xFE, 0x01, 0xF2, +0xA4, 0x39, 0x16, 0x01, 0x78, 0x3D, 0xBA, 0xF2, +0xDE, 0x39, 0x3A, 0xDE, 0xFC, 0xB5, 0x6F, 0x22, +0xC9, 0xFC, 0x3A, 0xC7, 0xFC, 0xB8, 0x3E, 0x00, +0xCA, 0xBC, 0x39, 0x3D, 0x32, 0xC5, 0xFC, 0x78, +0x32, 0xC7, 0xFC, 0xCD, 0xE2, 0x39, 0xC9, 0x2E, +0x00, 0x05, 0xC3, 0x7E, 0x39, 0x2E, 0x05, 0x04, +0xC3, 0x7E, 0x39, 0x06, 0x02, 0x05, 0xC3, 0x7E, +0x39, 0x6C, 0x2D, 0xC3, 0x7E, 0x39, 0x42, 0xC3, +0x7E, 0x39, 0xE5, 0x21, 0xE0, 0xFC, 0xCD, 0x07, +0x3A, 0x3A, 0xC7, 0xFC, 0x77, 0xE1, 0xC9, 0xE5, +0x21, 0xE0, 0xFC, 0x11, 0xC7, 0xFC, 0xC3, 0x00, +0x3A, 0xE5, 0x21, 0xE2, 0xFC, 0x11, 0xCA, 0xFC, +0xCD, 0x07, 0x3A, 0x7E, 0x12, 0xE1, 0xC9, 0x3A, +0xDE, 0xFC, 0xB7, 0xC8, 0x23, 0xC9, 0x11, 0x69, +0xFD, 0x06, 0x6C, 0xC5, 0xCD, 0x03, 0x1B, 0x11, +0x85, 0xF6, 0xC1, 0xCD, 0x03, 0x1B, 0xAF, 0x32, +0xE2, 0xFC, 0x32, 0xE3, 0xFC, 0x32, 0xD3, 0xFC, +0x3A, 0xD3, 0xFC, 0x0E, 0x36, 0x06, 0x00, 0x21, +0x85, 0xF6, 0x11, 0x62, 0xF9, 0xB7, 0xCA, 0x3E, +0x3A, 0x09, 0x7A, 0xE6, 0x7F, 0x57, 0xEB, 0x0E, +0x0B, 0x06, 0x00, 0x09, 0xCD, 0x80, 0x3A, 0xFE, +0xFF, 0xCA, 0x69, 0x3A, 0xCD, 0x94, 0x3A, 0xC2, +0x43, 0x3A, 0xD9, 0x13, 0x13, 0xC5, 0xE5, 0x21, +0xE2, 0xFC, 0x06, 0x00, 0x3A, 0xD3, 0xFC, 0x4F, +0x09, 0x7E, 0x3C, 0x77, 0xE1, 0xC1, 0xC3, 0x43, +0x3A, 0x3A, 0xD3, 0xFC, 0xB7, 0xC2, 0x77, 0x3A, +0x3C, 0x32, 0xD3, 0xFC, 0xC3, 0x28, 0x3A, 0xCD, +0xB3, 0x02, 0x85, 0xF6, 0x69, 0xFD, 0x6C, 0xC9, +0x3A, 0xD3, 0xFC, 0xC3, 0xF7, 0x3C, 0xC5, 0xD5, +0xE5, 0x3A, 0xCE, 0xFC, 0x4F, 0xCD, 0x46, 0xFD, +0xE1, 0xD1, 0xC1, 0xC9, 0xFE, 0x80, 0xC8, 0xFE, +0xC0, 0xC8, 0xFE, 0xA0, 0xC8, 0xF6, 0x01, 0xC9, +0x3A, 0xC7, 0xFC, 0x47, 0xC6, 0x05, 0x4F, 0x3A, +0xCA, 0xFC, 0xB7, 0xCA, 0xD3, 0x3A, 0xB9, 0xF2, +0xB3, 0x3A, 0x4F, 0xCD, 0x02, 0x3B, 0x78, 0x3D, +0xCD, 0x0E, 0x3B, 0x16, 0x01, 0x79, 0x90, 0x3C, +0x3C, 0x5F, 0xD5, 0xE5, 0xCD, 0x14, 0x3B, 0xE1, +0xD1, 0x23, 0x23, 0x14, 0x7A, 0xFE, 0x07, 0xFA, +0xC2, 0x3A, 0xC9, 0x3A, 0xDE, 0xFC, 0xCD, 0x7C, +0x3B, 0x11, 0xE1, 0x3A, 0xEB, 0xCD, 0x52, 0x02, +0xC9, 0x4E, 0x4F, 0x20, 0x46, 0x49, 0x4C, 0x45, +0x53, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x00, 0xCD, 0x02, 0x3B, 0x3A, 0xC9, 0xFC, 0xE6, +0x7F, 0x4F, 0x3A, 0xC7, 0xFC, 0x81, 0x3D, 0xC3, +0x0E, 0x3B, 0x21, 0x69, 0xFD, 0x3A, 0xDE, 0xFC, +0xB7, 0xC8, 0x21, 0x9F, 0xFD, 0xC9, 0x87, 0x16, +0x00, 0x5F, 0x19, 0xC9, 0xD5, 0xEB, 0xED, 0x22, +0xCF, 0xFC, 0x23, 0x23, 0x23, 0x3A, 0xDE, 0xFC, +0xB7, 0xCA, 0x35, 0x3B, 0x11, 0x85, 0xF6, 0xD5, +0x06, 0x08, 0xCD, 0x86, 0x3A, 0x12, 0x23, 0x13, +0x05, 0xC2, 0x2A, 0x3B, 0xE1, 0xD1, 0xE5, 0x3A, +0xDE, 0xFC, 0xB2, 0x3D, 0xCD, 0x7C, 0x3B, 0x22, +0xD1, 0xFC, 0xF7, 0x7C, 0x42, 0xE1, 0x7A, 0xBB, +0xF2, 0x76, 0x3B, 0x16, 0x06, 0xCD, 0xA9, 0x02, +0x3E, 0x2E, 0xF7, 0x13, 0x43, 0x16, 0x02, 0xCD, +0xA9, 0x02, 0x21, 0x92, 0x0E, 0xCD, 0x5C, 0x02, +0x2A, 0xD1, 0xFC, 0x7C, 0xC6, 0x0A, 0x67, 0xF7, +0x7C, 0x42, 0x2A, 0xCF, 0xFC, 0xCD, 0x8F, 0x3C, +0x60, 0x69, 0xF7, 0xD4, 0x39, 0xC9, 0x21, 0x89, +0x0E, 0xC3, 0x5C, 0x02, 0x21, 0x02, 0x04, 0xF5, +0xE6, 0x7F, 0x85, 0x6F, 0xF1, 0xE6, 0x80, 0xB7, +0xC8, 0x3E, 0x14, 0x84, 0x67, 0xC9, 0x21, 0x01, +0x01, 0xF7, 0x7C, 0x42, 0x21, 0x2D, 0x13, 0xCD, +0x5C, 0x02, 0x3E, 0x3A, 0xF7, 0x13, 0x43, 0x3E, +0x20, 0xF7, 0x13, 0x43, 0xCD, 0xDC, 0x07, 0xF7, +0xD4, 0x39, 0x21, 0xC9, 0x3B, 0xCD, 0x48, 0x02, +0x21, 0x01, 0x15, 0xF7, 0x7C, 0x42, 0x21, 0xCF, +0x3B, 0xCD, 0x5C, 0x02, 0x3A, 0xCE, 0xFC, 0xCD, +0x73, 0x1B, 0x23, 0x16, 0x06, 0xCD, 0xA9, 0x02, +0xC9, 0x20, 0x66, 0x72, 0x65, 0x65, 0x00, 0x52, +0x45, 0x58, 0x3A, 0x20, 0x00, 0x21, 0x01, 0x14, +0xF7, 0x7C, 0x42, 0x06, 0x07, 0xC5, 0x21, 0xEA, +0x3B, 0xCD, 0x5C, 0x02, 0xC1, 0x05, 0xC2, 0xDD, +0x3B, 0xC9, 0x7C, 0x1B, 0x42, 0x1B, 0x44, 0x00, +0x21, 0x08, 0x01, 0xF7, 0x7C, 0x42, 0x21, 0x8A, +0x14, 0xCD, 0x5C, 0x02, 0x21, 0x93, 0x0E, 0xCD, +0x5C, 0x02, 0x3A, 0xCA, 0xFC, 0xB7, 0xCA, 0x49, +0x3C, 0x3A, 0xDE, 0xFC, 0xB7, 0xCA, 0x25, 0x3C, +0x21, 0xA1, 0x14, 0xCD, 0x5C, 0x02, 0x21, 0x93, +0x0E, 0xCD, 0x5C, 0x02, 0x21, 0x93, 0x0E, 0xCD, +0x5C, 0x02, 0xC3, 0x37, 0x3C, 0x21, 0x93, 0x0E, +0xCD, 0x5C, 0x02, 0x21, 0xA7, 0x14, 0xCD, 0x5C, +0x02, 0x21, 0xAD, 0x14, 0xCD, 0x5C, 0x02, 0x21, +0x93, 0x0E, 0xCD, 0x5C, 0x02, 0x21, 0x93, 0x0E, +0xCD, 0x5C, 0x02, 0x21, 0xBE, 0x14, 0xC3, 0x5C, +0x02, 0x21, 0x93, 0x0E, 0xCD, 0x5C, 0x02, 0xC3, +0x16, 0x3C, 0x57, 0x3A, 0xCA, 0xFC, 0xB7, 0xCA, +0x85, 0x3C, 0x7A, 0xB7, 0xCA, 0x5D, 0x20, 0x3D, +0xF5, 0x3A, 0xDE, 0xFC, 0xB7, 0xC2, 0x7B, 0x3C, +0xF1, 0x3D, 0x3D, 0xCA, 0x01, 0x3D, 0x3D, 0xCA, +0xAE, 0x3E, 0x3D, 0x3D, 0x3D, 0xCA, 0xFB, 0x07, +0xC3, 0xDB, 0x38, 0xF1, 0x3D, 0xCA, 0x6D, 0x3D, +0x3D, 0x3D, 0xC3, 0x72, 0x3C, 0x7A, 0xB7, 0xCA, +0x5D, 0x20, 0xFE, 0x07, 0xC3, 0x75, 0x3C, 0xCD, +0x58, 0x3D, 0x01, 0x00, 0x00, 0xFE, 0x80, 0xCA, +0xB9, 0x3C, 0xFE, 0xA0, 0xCA, 0xD9, 0x3C, 0xFE, +0xC0, 0xCA, 0xA5, 0x3C, 0xC9, 0xE5, 0xCD, 0x07, +0x19, 0xE1, 0x01, 0x00, 0x00, 0x3A, 0xCE, 0xFC, +0xCD, 0x46, 0xFD, 0xC5, 0xCD, 0x70, 0x17, 0xC1, +0xC9, 0xD5, 0x44, 0x4D, 0xCD, 0xF4, 0x3C, 0x5F, +0x23, 0xCD, 0xF4, 0x3C, 0x57, 0xB2, 0xCA, 0xD1, +0x3C, 0x62, 0x6B, 0xCD, 0xEC, 0x3C, 0xC3, 0xBC, +0x3C, 0x23, 0xE5, 0x08, 0x44, 0x4D, 0xE1, 0xD1, +0xC9, 0x23, 0x23, 0xCD, 0xF4, 0x3C, 0x5F, 0x23, +0xCD, 0xF4, 0x3C, 0x57, 0xEB, 0x11, 0x06, 0x00, +0x19, 0x44, 0x4D, 0xC9, 0x3A, 0xDE, 0xFC, 0xEE, +0xFF, 0xA4, 0x67, 0xC9, 0x3A, 0xDE, 0xFC, 0xB7, +0xCA, 0xFF, 0x3C, 0xCD, 0x86, 0x3A, 0xC9, 0x7E, +0xC9, 0x21, 0xC7, 0x10, 0xCD, 0x2B, 0x02, 0xF5, +0xF7, 0x13, 0x43, 0xF1, 0xC2, 0xD6, 0x38, 0x2A, +0xB6, 0xFB, 0x22, 0xD7, 0xFC, 0xCD, 0xF1, 0x3A, +0xEB, 0xED, 0xE5, 0xCD, 0x58, 0x3D, 0xEB, 0xE1, +0x7E, 0xFE, 0x80, 0xCA, 0x42, 0x3D, 0xFE, 0xA0, +0xCA, 0x39, 0x3D, 0xFE, 0xC0, 0xCA, 0x33, 0x3D, +0xC3, 0xD6, 0x38, 0xF7, 0xBF, 0x1F, 0xC3, 0x3C, +0x3D, 0xF7, 0xD9, 0x1F, 0xF7, 0x46, 0x21, 0xC3, +0x45, 0x3D, 0xF7, 0x17, 0x20, 0xCD, 0x3F, 0x3E, +0xCA, 0x9C, 0x38, 0x2A, 0xB6, 0xFB, 0xEB, 0x2A, +0xD7, 0xFC, 0xF7, 0xDB, 0x6B, 0xC3, 0x9C, 0x38, +0xCD, 0xF4, 0x3C, 0xF5, 0x23, 0xCD, 0xF4, 0x3C, +0xF5, 0x23, 0xCD, 0xF4, 0x3C, 0x67, 0xF1, 0x6F, +0xCD, 0xEC, 0x3C, 0xF1, 0xC9, 0x3A, 0xCA, 0xFC, +0xB7, 0xCA, 0xDB, 0x38, 0xCD, 0xF1, 0x3A, 0xEB, +0xED, 0xE5, 0xCD, 0x8F, 0x3C, 0x60, 0x69, 0x22, +0xD5, 0xFC, 0xE1, 0x11, 0x85, 0xF6, 0xD5, 0x01, +0x0B, 0x00, 0xCD, 0x95, 0x3E, 0xE1, 0xE5, 0xCD, +0xBA, 0x1E, 0x2A, 0xCF, 0xFC, 0x7C, 0xB5, 0xC2, +0x80, 0x3E, 0x2A, 0xD1, 0xFC, 0x7C, 0xB5, 0xCA, +0x80, 0x3E, 0xD1, 0x1A, 0x77, 0xF5, 0x23, 0x23, +0x23, 0x13, 0x13, 0x13, 0x0E, 0x08, 0xCD, 0xC1, +0x02, 0xF1, 0xFE, 0x80, 0xCA, 0xC4, 0x3D, 0xFE, +0xA0, 0xCA, 0xE2, 0x3D, 0xFE, 0xC0, 0xCA, 0x01, +0x3E, 0xC3, 0x80, 0x3E, 0x2A, 0x9A, 0xF9, 0x22, +0xD3, 0xFC, 0x2B, 0x22, 0xCF, 0xFC, 0xCD, 0x14, +0x3E, 0x2A, 0xD5, 0xFC, 0xEB, 0x2A, 0xAE, 0xFB, +0x19, 0x22, 0xAE, 0xFB, 0xCD, 0x61, 0x3E, 0xC3, +0x9C, 0x38, 0x2A, 0xB0, 0xFB, 0xE5, 0x2A, 0xB2, +0xFB, 0x22, 0xD3, 0xFC, 0x22, 0xCF, 0xFC, 0xCD, +0x14, 0x3E, 0xE1, 0xE5, 0x22, 0xB0, 0xFB, 0xCD, +0x61, 0x3E, 0xE1, 0x22, 0xB0, 0xFB, 0xC3, 0x9C, +0x38, 0x2A, 0xB0, 0xFB, 0x22, 0xD3, 0xFC, 0x2B, +0x22, 0xCF, 0xFC, 0xCD, 0x14, 0x3E, 0xCD, 0x61, +0x3E, 0xC3, 0x9C, 0x38, 0x2A, 0xD5, 0xFC, 0xE5, +0x2A, 0xB6, 0xFB, 0x22, 0xD7, 0xFC, 0xCD, 0x3F, +0x3E, 0xCA, 0x34, 0x3E, 0xD1, 0xD5, 0x2A, 0xB6, +0xFB, 0xE5, 0x19, 0x09, 0x2B, 0xD1, 0xEB, 0x09, +0x2B, 0xF7, 0xE6, 0x6B, 0xC1, 0x2A, 0xD3, 0xFC, +0xF7, 0x6D, 0x6B, 0xDA, 0x80, 0x3E, 0xC9, 0x3A, +0xC4, 0xFC, 0xB7, 0xC8, 0xE5, 0xD5, 0x2A, 0xD7, +0xFC, 0xEB, 0xAF, 0x4F, 0x47, 0xED, 0x23, 0x7C, +0xB5, 0xCA, 0x5A, 0x3E, 0x13, 0x13, 0x0C, 0xC3, +0x4D, 0x3E, 0x0C, 0x79, 0x07, 0x4F, 0xD1, 0xE1, +0xC9, 0x2A, 0xD5, 0xFC, 0x44, 0x4D, 0x2A, 0xD3, +0xFC, 0xEB, 0x2A, 0x86, 0xF6, 0xCD, 0xEC, 0x3C, +0xCD, 0x95, 0x3E, 0x2A, 0xD1, 0xFC, 0x23, 0xEB, +0x2A, 0xCF, 0xFC, 0xD9, 0xF7, 0x46, 0x21, 0xC9, +0x21, 0x86, 0x3E, 0xC3, 0xED, 0x1A, 0x43, 0x6F, +0x70, 0x79, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, +0x2E, 0x2E, 0x2E, 0x2E, 0x00, 0xE5, 0xC5, 0xD5, +0xCD, 0x2E, 0x19, 0xD1, 0xC1, 0xE1, 0xE5, 0xC5, +0xD5, 0x3A, 0xCE, 0xFC, 0xCD, 0x46, 0xFD, 0xCD, +0x70, 0x17, 0xD1, 0xC1, 0xE1, 0xC9, 0xCD, 0x72, +0x0A, 0xCA, 0xD6, 0x38, 0xCD, 0xF1, 0x3A, 0xEB, +0xED, 0x23, 0x23, 0x23, 0x11, 0x85, 0xF6, 0x0E, +0x06, 0xCD, 0xC1, 0x02, 0xC3, 0x9C, 0x38, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +/* Image for REX 4.8, T200 version */ +const unsigned char gRex248Image[] = { +0xF3, 0xC3, 0x97, 0x00, 0x52, 0x45, 0x58, 0x21, +0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xC9, 0x00, 0x00, 0x00, 0xF3, 0xCD, 0x5F, 0x00, +0xC9, 0x00, 0x00, 0x00, 0xF3, 0xCD, 0x5F, 0x00, +0xC3, 0x48, 0x00, 0x00, 0xF3, 0xCD, 0x5F, 0x00, +0xC9, 0x00, 0x00, 0x00, 0xF3, 0xCD, 0x5F, 0x00, +0x00, 0x00, 0x00, 0x52, 0x45, 0x58, 0x04, 0x08, +0xE3, 0x23, 0x23, 0xE3, 0xE5, 0x21, 0xDC, 0xF7, +0xE3, 0xE5, 0xD5, 0x38, 0x06, 0xED, 0x2B, 0x2B, +0xEB, 0xED, 0xD1, 0xE3, 0xC3, 0x82, 0x00, 0xE5, +0xD5, 0x38, 0x04, 0xED, 0x2B, 0x2B, 0x2B, 0x2B, +0xE5, 0x21, 0xDC, 0xF7, 0xD9, 0xE1, 0xD1, 0xE3, +0xC3, 0x82, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xF5, 0xE5, 0x21, 0xE9, 0x14, 0xE3, +0xDB, 0xD8, 0xE6, 0x0C, 0xD3, 0xD8, 0xC9, 0xE5, +0x21, 0x00, 0x00, 0xE3, 0xC3, 0x82, 0x00, 0xDB, +0xD8, 0xE6, 0x03, 0xD3, 0xD8, 0x4F, 0x3A, 0xF5, +0xEE, 0xE6, 0x0C, 0xB1, 0xD3, 0xD8, 0xAF, 0x32, +0xB0, 0xF7, 0xC3, 0xBC, 0x03, 0x21, 0xFE, 0x3F, +0x01, 0xFE, 0x43, 0x23, 0x23, 0x7C, 0xA8, 0xB5, +0xA9, 0xCA, 0xC6, 0x00, 0x23, 0x7E, 0x2B, 0xB6, +0xCA, 0xB3, 0x00, 0xF6, 0x01, 0xC9, 0xAF, 0xC9, +0xCD, 0xAD, 0x00, 0x7E, 0xE6, 0x3F, 0x32, 0xBC, +0xF7, 0x7E, 0xE6, 0x40, 0x32, 0xB1, 0xF7, 0x23, +0x7E, 0x32, 0xBD, 0xF7, 0xF6, 0x01, 0xC9, 0xCD, +0x17, 0x1C, 0xCD, 0xAD, 0x00, 0xCA, 0xDF, 0x00, +0xCD, 0xD7, 0x1B, 0x23, 0xCD, 0xD7, 0x1B, 0x23, +0xC5, 0x3A, 0xBC, 0xF7, 0xE6, 0x3F, 0x47, 0x3A, +0xB1, 0xF7, 0xE6, 0x40, 0xB0, 0xC1, 0xCD, 0xBD, +0x1C, 0x23, 0x3A, 0xBD, 0xF7, 0xE6, 0x3F, 0xCD, +0xBD, 0x1C, 0xC9, 0x21, 0x52, 0xF2, 0x01, 0x0B, +0x00, 0x16, 0x37, 0x09, 0x15, 0x7E, 0xFE, 0x48, +0xC2, 0x13, 0x01, 0x09, 0x7E, 0xFE, 0xF0, 0xC2, +0x24, 0x01, 0x36, 0x00, 0x15, 0xC2, 0x1B, 0x01, +0xCD, 0x3A, 0x20, 0xCD, 0xBA, 0x18, 0xCD, 0x83, +0xF8, 0xAF, 0x32, 0x48, 0xF8, 0x32, 0x1E, 0xFD, +0xC9, 0xCD, 0xD3, 0x17, 0x06, 0x05, 0x11, 0x67, +0x01, 0x21, 0x4D, 0x00, 0x3A, 0xBC, 0xF7, 0x4F, +0xCD, 0x83, 0xF8, 0x4F, 0x1A, 0xB9, 0xC2, 0x61, +0x01, 0x23, 0x13, 0x05, 0xC2, 0x44, 0x01, 0x21, +0xEF, 0xEE, 0xDB, 0xD8, 0xE6, 0x0C, 0xF6, 0x02, +0xC9, 0x21, 0xEF, 0xEE, 0x3E, 0x02, 0xC9, 0x53, +0x75, 0x70, 0x65, 0x72, 0xCD, 0xAC, 0x1A, 0x3A, +0xBB, 0xF7, 0xCD, 0x62, 0x1A, 0x21, 0xE5, 0x01, +0xCD, 0x64, 0x02, 0x3E, 0x01, 0x32, 0x2F, 0xFA, +0xCD, 0xFD, 0x18, 0xCD, 0x83, 0xF8, 0xCD, 0xF4, +0x17, 0x3A, 0xBB, 0xF7, 0x4F, 0xCD, 0x83, 0xF8, +0xC9, 0x32, 0xC1, 0xF7, 0xCD, 0xAC, 0x1A, 0xCD, +0xD3, 0x17, 0x21, 0x2F, 0x7A, 0x3A, 0xBE, 0xF7, +0x4F, 0xCD, 0x83, 0xF8, 0xFE, 0x01, 0xCA, 0xAF, +0x01, 0x21, 0x1B, 0x02, 0xC3, 0x55, 0x1B, 0x21, +0xEF, 0x74, 0x3A, 0xBE, 0xF7, 0x4F, 0xCD, 0x83, +0xF8, 0xE6, 0xE0, 0x5F, 0x3A, 0xEF, 0xF4, 0xE6, +0xE0, 0xBB, 0xCA, 0xCB, 0x01, 0x21, 0x3B, 0x02, +0xC3, 0x55, 0x1B, 0x21, 0x00, 0x02, 0xCD, 0x64, +0x02, 0xCD, 0xFD, 0x18, 0xCD, 0x83, 0xF8, 0xCD, +0x2B, 0x18, 0x3A, 0xC1, 0xF7, 0x4F, 0xCD, 0x83, +0xF8, 0xCD, 0xE0, 0x14, 0xC9, 0x43, 0x6F, 0x70, +0x79, 0x69, 0x6E, 0x67, 0x20, 0x52, 0x41, 0x4D, +0x20, 0x74, 0x6F, 0x20, 0x49, 0x6D, 0x61, 0x67, +0x65, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x00, +0x43, 0x6F, 0x70, 0x79, 0x69, 0x6E, 0x67, 0x20, +0x49, 0x6D, 0x61, 0x67, 0x65, 0x20, 0x74, 0x6F, +0x20, 0x52, 0x41, 0x4D, 0x2E, 0x2E, 0x2E, 0x2E, +0x2E, 0x2E, 0x00, 0x4D, 0x6F, 0x64, 0x65, 0x6C, +0x20, 0x6D, 0x69, 0x73, 0x6D, 0x61, 0x74, 0x63, +0x68, 0x2E, 0x2E, 0x63, 0x61, 0x6E, 0x6E, 0x6F, +0x74, 0x20, 0x69, 0x6E, 0x73, 0x74, 0x61, 0x6C, +0x6C, 0x21, 0x00, 0x52, 0x41, 0x4D, 0x20, 0x73, +0x69, 0x7A, 0x65, 0x20, 0x6D, 0x69, 0x73, 0x6D, +0x61, 0x74, 0x63, 0x68, 0x2E, 0x2E, 0x2E, 0x63, +0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x69, 0x6E, +0x73, 0x74, 0x61, 0x6C, 0x6C, 0x21, 0x00, 0x3E, +0x01, 0xC3, 0x66, 0x02, 0x3E, 0x04, 0xF5, 0xE5, +0xCD, 0x70, 0x03, 0x11, 0x0C, 0x01, 0xE1, 0xC3, +0x88, 0x02, 0x3E, 0x01, 0xC3, 0x91, 0x02, 0x3E, +0x02, 0xC3, 0x91, 0x02, 0x3E, 0x04, 0xC3, 0x91, +0x02, 0x3E, 0x06, 0xC3, 0x91, 0x02, 0xAF, 0xF5, +0xEB, 0xF7, 0x9B, 0x4F, 0xEB, 0xC3, 0x92, 0x02, +0xAF, 0xF5, 0x7E, 0x23, 0xA7, 0xCA, 0x9E, 0x02, +0xF7, 0x30, 0x50, 0xC3, 0x92, 0x02, 0xF1, 0xB7, +0xC8, 0xFE, 0x01, 0xCA, 0xBF, 0x02, 0xFE, 0x02, +0xCA, 0xB3, 0x02, 0xFE, 0x04, 0xCA, 0x76, 0x03, +0xCD, 0x76, 0x03, 0xE5, 0x21, 0xBC, 0x02, 0xCD, +0x90, 0x02, 0xE1, 0xC9, 0x0D, 0x0A, 0x00, 0x21, +0xC8, 0x02, 0xCD, 0x90, 0x02, 0xC3, 0x19, 0x03, +0x20, 0x28, 0x59, 0x2F, 0x4E, 0x29, 0x3F, 0x20, +0x00, 0xF5, 0xF7, 0x9B, 0x4F, 0xF1, 0x26, 0x00, +0x6F, 0xF7, 0x0B, 0x47, 0xC9, 0x7E, 0xF7, 0x30, +0x50, 0x23, 0x15, 0xC2, 0xDD, 0x02, 0xC9, 0xD1, +0xED, 0xE5, 0x13, 0x13, 0xED, 0x13, 0x13, 0x1A, +0x13, 0xEB, 0xE3, 0x4F, 0xEB, 0x1A, 0x77, 0x23, +0x13, 0x0D, 0xC2, 0xF5, 0x02, 0xC9, 0x06, 0xC0, +0x11, 0x6C, 0xEF, 0xC3, 0x6B, 0x1B, 0x3E, 0x70, +0xC3, 0x0D, 0x03, 0x3E, 0x71, 0xF7, 0x8F, 0x4F, +0xC9, 0x36, 0x20, 0x23, 0x05, 0xC2, 0x11, 0x03, +0xC9, 0xCD, 0x81, 0x1B, 0xF7, 0x14, 0x10, 0xFE, +0x59, 0xC8, 0xFE, 0x4E, 0xCA, 0x2A, 0x03, 0xC3, +0x19, 0x03, 0xB7, 0xC9, 0xCD, 0x83, 0xF8, 0x7A, +0xCD, 0x34, 0x03, 0x7B, 0xF5, 0x0F, 0x0F, 0x0F, +0x0F, 0xCD, 0x3D, 0x03, 0xF1, 0xE6, 0x0F, 0xC6, +0x30, 0xFE, 0x3A, 0xFA, 0x48, 0x03, 0xC6, 0x07, +0xF7, 0x30, 0x50, 0xC9, 0x21, 0x0B, 0x1A, 0xC3, +0x73, 0x03, 0x21, 0x0B, 0x01, 0xF7, 0x9B, 0x4F, +0x21, 0xA4, 0x0E, 0xC3, 0x90, 0x02, 0x21, 0x06, +0x01, 0xC3, 0x73, 0x03, 0x21, 0x0C, 0x20, 0xC3, +0x73, 0x03, 0x21, 0x0B, 0x01, 0xC3, 0x73, 0x03, +0x21, 0x0C, 0x01, 0xF7, 0x9B, 0x4F, 0x3E, 0x4B, +0xC3, 0x0D, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xF3, 0x3E, 0x01, 0x32, 0xB0, +0xF7, 0xC3, 0xBC, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x8F, 0x00, 0xF3, +0xF3, 0xCD, 0xE0, 0x14, 0xCD, 0xC8, 0x00, 0xC2, +0xAF, 0x03, 0x3E, 0x08, 0x32, 0xBC, 0xF7, 0xCD, +0xFE, 0x02, 0xF3, 0xCD, 0x2E, 0x05, 0xCD, 0x2D, +0x16, 0xC3, 0x83, 0xF8, 0xF3, 0xCD, 0xE0, 0x14, +0xCD, 0x09, 0x06, 0x32, 0xB4, 0xF7, 0x21, 0x00, +0x00, 0x39, 0x22, 0xCB, 0xF7, 0xCD, 0xEE, 0x07, +0x7C, 0xFE, 0x03, 0xFA, 0x3C, 0x04, 0xCD, 0x3E, +0x05, 0xF3, 0x11, 0x00, 0x00, 0x21, 0x78, 0x1F, +0xCD, 0x4C, 0x07, 0xC2, 0x90, 0x07, 0x11, 0x00, +0x00, 0x21, 0x00, 0x20, 0xCD, 0x40, 0x07, 0xC2, +0x90, 0x07, 0x3A, 0xB4, 0xF7, 0xB7, 0xCA, 0xFF, +0x03, 0xCD, 0x48, 0x06, 0xF7, 0x17, 0x9B, 0xFB, +0x3A, 0xB0, 0xF7, 0xFE, 0xFF, 0xCA, 0x51, 0x05, +0xFE, 0x01, 0xCA, 0xF8, 0x07, 0x21, 0x21, 0x04, +0xCD, 0x72, 0x02, 0xF5, 0xF7, 0x30, 0x50, 0xCD, +0xB3, 0x02, 0xF1, 0xCA, 0xF8, 0x07, 0xC3, 0x51, +0x05, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x52, +0x45, 0x58, 0x20, 0x4D, 0x61, 0x6E, 0x61, 0x67, +0x65, 0x72, 0x00, 0x21, 0xA9, 0x04, 0xCD, 0x77, +0x02, 0xC3, 0x4B, 0x04, 0x21, 0x62, 0x04, 0xCD, +0x77, 0x02, 0xC3, 0x4B, 0x04, 0x21, 0x87, 0x04, +0xCD, 0x77, 0x02, 0xF7, 0x45, 0x4F, 0xE1, 0xCD, +0x21, 0x05, 0xF3, 0xF7, 0x17, 0x9B, 0x21, 0xCE, +0x04, 0xCD, 0x90, 0x02, 0xCD, 0x8A, 0x1B, 0xC3, +0x8F, 0x00, 0x4E, 0x6F, 0x74, 0x20, 0x65, 0x6E, +0x6F, 0x75, 0x67, 0x68, 0x20, 0x66, 0x72, 0x65, +0x65, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, +0x20, 0x74, 0x6F, 0x20, 0x73, 0x74, 0x61, 0x72, +0x74, 0x20, 0x52, 0x45, 0x58, 0x2E, 0x00, 0x52, +0x45, 0x58, 0x20, 0x66, 0x69, 0x6C, 0x65, 0x73, +0x20, 0x63, 0x6F, 0x75, 0x6C, 0x64, 0x20, 0x6E, +0x6F, 0x74, 0x20, 0x62, 0x65, 0x20, 0x69, 0x6E, +0x73, 0x74, 0x61, 0x6C, 0x6C, 0x65, 0x64, 0x2E, +0x00, 0x54, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, +0x61, 0x73, 0x20, 0x61, 0x20, 0x70, 0x72, 0x6F, +0x62, 0x6C, 0x65, 0x6D, 0x20, 0x72, 0x65, 0x73, +0x74, 0x6F, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x68, +0x6F, 0x6F, 0x6B, 0x73, 0x2E, 0x00, 0x50, 0x72, +0x6F, 0x62, 0x6C, 0x65, 0x6D, 0x20, 0x65, 0x6E, +0x63, 0x6F, 0x75, 0x6E, 0x74, 0x65, 0x72, 0x65, +0x64, 0x2E, 0x0D, 0x0A, 0x52, 0x45, 0x58, 0x20, +0x68, 0x61, 0x73, 0x20, 0x62, 0x65, 0x65, 0x6E, +0x20, 0x75, 0x6E, 0x69, 0x6E, 0x73, 0x74, 0x61, +0x6C, 0x6C, 0x65, 0x64, 0x2E, 0x0D, 0x0A, 0x41, +0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x69, +0x73, 0x73, 0x75, 0x65, 0x2C, 0x20, 0x61, 0x6E, +0x64, 0x20, 0x72, 0x65, 0x2D, 0x6C, 0x61, 0x75, +0x6E, 0x63, 0x68, 0x20, 0x52, 0x45, 0x58, 0x2E, +0x00, 0x01, 0x00, 0x00, 0xCD, 0x7A, 0x20, 0x21, +0x78, 0x1F, 0xCD, 0x09, 0x1F, 0xC9, 0x11, 0x4B, +0x05, 0x21, 0xC2, 0xEE, 0xF3, 0x1A, 0x77, 0x13, +0x23, 0xE5, 0xED, 0xD1, 0xD9, 0xC9, 0xF3, 0x21, +0xC2, 0xEE, 0x36, 0xC9, 0x23, 0x11, 0x00, 0x00, +0xEB, 0xD9, 0xC9, 0xC3, 0x01, 0xA0, 0xF7, 0x4D, +0x4F, 0xF3, 0x3A, 0xB4, 0xF7, 0xB7, 0xC4, 0xB0, +0x06, 0xC2, 0x33, 0x04, 0xAF, 0x32, 0xB0, 0xF7, +0x32, 0xB4, 0xF7, 0xC3, 0xA0, 0x03, 0xF7, 0x4D, +0x4F, 0xCD, 0x21, 0x05, 0x21, 0x7B, 0x05, 0xCD, +0x90, 0x02, 0xF7, 0x03, 0x8B, 0xCA, 0x72, 0x05, +0xC3, 0x8F, 0x00, 0x41, 0x6C, 0x6C, 0x20, 0x52, +0x45, 0x58, 0x20, 0x73, 0x6F, 0x66, 0x74, 0x77, +0x61, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x72, +0x65, 0x6D, 0x6F, 0x76, 0x65, 0x64, 0x2E, 0x0D, +0x0A, 0x0A, 0x50, 0x6F, 0x77, 0x65, 0x72, 0x20, +0x6F, 0x66, 0x66, 0x20, 0x61, 0x6E, 0x64, 0x20, +0x72, 0x65, 0x6D, 0x6F, 0x76, 0x65, 0x20, 0x52, +0x45, 0x58, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, +0x6C, 0x61, 0x70, 0x74, 0x6F, 0x70, 0x2C, 0x0D, +0x0A, 0x6F, 0x72, 0x20, 0x66, 0x6F, 0x6C, 0x6C, +0x6F, 0x77, 0x20, 0x72, 0x65, 0x2D, 0x69, 0x6E, +0x73, 0x74, 0x61, 0x6C, 0x6C, 0x61, 0x74, 0x69, +0x6F, 0x6E, 0x20, 0x70, 0x72, 0x6F, 0x63, 0x65, +0x64, 0x75, 0x72, 0x65, 0x2E, 0x0D, 0x0A, 0x0A, +0x50, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6E, +0x79, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x74, 0x6F, +0x20, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, +0x20, 0x6C, 0x61, 0x70, 0x74, 0x6F, 0x70, 0x2E, +0x00, 0x21, 0xA8, 0x9C, 0x22, 0xBF, 0xF7, 0x21, +0x07, 0xF5, 0x22, 0xC3, 0xF7, 0x16, 0x20, 0x1E, +0x02, 0x2A, 0xC3, 0xF7, 0x4E, 0x23, 0x46, 0x2A, +0xBF, 0xF7, 0x08, 0xC2, 0x45, 0x06, 0x2A, 0xC3, +0xF7, 0x23, 0x23, 0x22, 0xC3, 0xF7, 0x15, 0xC2, +0x19, 0x06, 0x1D, 0xCA, 0x43, 0x06, 0xE5, 0x21, +0x06, 0x09, 0x22, 0xBF, 0xF7, 0xE1, 0x16, 0x12, +0xC3, 0x19, 0x06, 0xAF, 0xC9, 0x3E, 0x01, 0xC9, +0x21, 0xA8, 0x9C, 0x22, 0xBF, 0xF7, 0x2A, 0x69, +0xF6, 0x22, 0xC1, 0xF7, 0x21, 0x07, 0xF5, 0x22, +0xC3, 0xF7, 0x16, 0x20, 0x1E, 0x02, 0x2A, 0xC3, +0xF7, 0x4E, 0x23, 0x46, 0x2A, 0xBF, 0xF7, 0x08, +0xCA, 0x8A, 0x06, 0xD5, 0x2A, 0xC1, 0xF7, 0xEB, +0x2A, 0xC3, 0xF7, 0xD9, 0xD5, 0xEB, 0xED, 0xD1, +0x13, 0x13, 0xD9, 0x13, 0x13, 0xEB, 0x22, 0xC1, +0xF7, 0x2A, 0xC3, 0xF7, 0xEB, 0x2A, 0xBF, 0xF7, +0xD9, 0xD1, 0x2A, 0xC3, 0xF7, 0x23, 0x23, 0x22, +0xC3, 0xF7, 0x15, 0xC2, 0x5E, 0x06, 0x1D, 0xCA, +0xA7, 0x06, 0xE5, 0x21, 0x06, 0x09, 0x22, 0xBF, +0xF7, 0xE1, 0x16, 0x12, 0xC3, 0x5E, 0x06, 0x2A, +0xC1, 0xF7, 0xEB, 0x21, 0xFF, 0xFF, 0xD9, 0xC9, +0x2A, 0x69, 0xF6, 0xEB, 0x3E, 0x20, 0xC6, 0x12, +0x47, 0x78, 0xB7, 0xFA, 0xF5, 0x06, 0xED, 0x23, +0x7C, 0xB5, 0xC8, 0x2B, 0x22, 0xBF, 0xF7, 0xC5, +0x01, 0x07, 0xF5, 0x2A, 0xBF, 0xF7, 0x08, 0xC1, +0x7C, 0xB7, 0xC2, 0xF5, 0x06, 0x7D, 0xE6, 0xFE, +0xBD, 0xC2, 0xF5, 0x06, 0x7D, 0x0F, 0xE6, 0x7F, +0xB8, 0xF2, 0xF5, 0x06, 0x13, 0x13, 0xD5, 0xED, +0xEB, 0x2A, 0xBF, 0xF7, 0xEB, 0xD9, 0xD1, 0x13, +0x13, 0x05, 0xC3, 0xB9, 0x06, 0x3E, 0x01, 0xB7, +0xC9, 0xF7, 0x4D, 0x4F, 0xC3, 0x02, 0x07, 0xCD, +0x70, 0x03, 0x06, 0x06, 0xC5, 0xCD, 0x17, 0x07, +0xCD, 0x06, 0x03, 0xCD, 0x17, 0x07, 0xCD, 0x0B, +0x03, 0xC1, 0x05, 0xC2, 0x04, 0x07, 0xC9, 0x11, +0x0C, 0x05, 0x21, 0x21, 0x07, 0xCD, 0x86, 0x02, +0xC9, 0x2A, 0x2A, 0x20, 0x53, 0x79, 0x73, 0x74, +0x65, 0x6D, 0x20, 0x68, 0x6F, 0x6F, 0x6B, 0x73, +0x20, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, +0x69, 0x7A, 0x65, 0x64, 0x20, 0x2A, 0x2A, 0x00, +0xD5, 0x3E, 0x26, 0x11, 0x01, 0xA0, 0x21, 0x11, +0x20, 0xC3, 0x6D, 0x07, 0xD5, 0xE5, 0xCD, 0x1C, +0x1F, 0x2A, 0xBF, 0xF7, 0x7C, 0xB5, 0xCA, 0x8B, +0x07, 0xEB, 0x13, 0xED, 0x01, 0x04, 0x00, 0x09, +0xEB, 0xE1, 0x01, 0x0B, 0x00, 0x09, 0x7E, 0xD6, +0x04, 0x01, 0x06, 0x00, 0x09, 0x4F, 0x06, 0x00, +0x1A, 0x80, 0x96, 0x47, 0x23, 0x13, 0x0D, 0xC2, +0x70, 0x07, 0xE1, 0x7C, 0xB5, 0x78, 0xCA, 0x89, +0x07, 0x85, 0x84, 0x11, 0xEE, 0xF4, 0xED, 0x94, +0x95, 0xB7, 0xC9, 0xC1, 0xC1, 0xF6, 0x01, 0xC9, +0x21, 0xB7, 0x07, 0xCD, 0x77, 0x02, 0xCD, 0x21, +0x05, 0x21, 0x78, 0x1F, 0xCD, 0x1F, 0x1E, 0xC2, +0x45, 0x04, 0x0E, 0x01, 0xCD, 0x7A, 0x20, 0x0E, +0x26, 0x06, 0x00, 0x21, 0x01, 0xA0, 0x11, 0x11, +0x20, 0xCD, 0xF5, 0x02, 0xC3, 0xF2, 0x03, 0x49, +0x6E, 0x73, 0x74, 0x61, 0x6C, 0x6C, 0x69, 0x6E, +0x67, 0x20, 0x52, 0x45, 0x58, 0x20, 0x66, 0x69, +0x6C, 0x65, 0x73, 0x20, 0x69, 0x6E, 0x20, 0x52, +0x41, 0x4D, 0x2E, 0x2E, 0x2E, 0x2E, 0x00, 0x2A, +0xEE, 0xF4, 0x23, 0xE5, 0xE5, 0x09, 0xEB, 0xED, +0xC5, 0x01, 0x01, 0xA0, 0x08, 0xC1, 0xD1, 0x19, +0xEB, 0xE1, 0x09, 0xEB, 0xD9, 0xC9, 0x2A, 0x69, +0xF6, 0x44, 0x4D, 0x2A, 0xCB, 0xF7, 0x08, 0xC9, +0xF3, 0xCD, 0xE0, 0x14, 0xCD, 0x98, 0x15, 0xCD, +0x83, 0xF8, 0xFB, 0xAF, 0x32, 0xB0, 0xF7, 0x32, +0xC9, 0xF7, 0xCD, 0x1F, 0x10, 0x3E, 0x07, 0x32, +0xCF, 0xF7, 0xCD, 0xC2, 0x11, 0xCD, 0x54, 0x13, +0xC3, 0x1E, 0x08, 0xCD, 0x2C, 0x35, 0xAF, 0x32, +0xB9, 0xF7, 0x32, 0xB8, 0xF7, 0x21, 0x1B, 0x08, +0x22, 0xB2, 0xF7, 0xCD, 0xC8, 0x00, 0xCD, 0xDC, +0x11, 0xCD, 0xBD, 0x34, 0xCD, 0x17, 0x09, 0xCD, +0xC6, 0x0C, 0xCD, 0xBD, 0x34, 0xCD, 0xF7, 0x0D, +0xCD, 0xA8, 0x0D, 0xCD, 0xF8, 0x37, 0xCD, 0x1C, +0x0E, 0xAF, 0xCD, 0xBD, 0x13, 0x3E, 0xFF, 0x32, +0xB6, 0xF7, 0xCD, 0xBD, 0x12, 0xCD, 0xE3, 0x13, +0xCD, 0xCD, 0x13, 0xCD, 0xC2, 0x0D, 0xCD, 0x16, +0x14, 0x3A, 0xB5, 0xF7, 0x32, 0xB6, 0xF7, 0xCD, +0xA0, 0x13, 0x3A, 0xB9, 0xF7, 0x32, 0xB8, 0xF7, +0xF7, 0x03, 0x8B, 0xCA, 0x70, 0x08, 0xDA, 0x2F, +0x09, 0xF7, 0x14, 0x10, 0xFE, 0x53, 0xCA, 0x68, +0x13, 0xFE, 0x42, 0xCC, 0x73, 0x13, 0xFE, 0x45, +0xCC, 0x88, 0x13, 0xFE, 0x49, 0xCA, 0x27, 0x11, +0xFE, 0x43, 0xCA, 0x91, 0x0A, 0xFE, 0x09, 0xCA, +0x0B, 0x09, 0xFE, 0x0D, 0xCA, 0xB7, 0x0A, 0xCD, +0xA5, 0x08, 0xC3, 0x52, 0x08, 0x21, 0xBA, 0xF7, +0x4E, 0xF5, 0x3A, 0xC9, 0xF7, 0xFE, 0x03, 0xC2, +0xB3, 0x08, 0x0D, 0x3A, 0xB9, 0xF7, 0x67, 0xF1, +0xFE, 0x1F, 0xCA, 0xD2, 0x08, 0xFE, 0x1E, 0xCA, +0xE1, 0x08, 0xFE, 0x1D, 0xCA, 0xFA, 0x08, 0xFE, +0x1C, 0xCA, 0xEA, 0x08, 0xFE, 0x20, 0xCA, 0xEA, +0x08, 0xC9, 0x7C, 0xC6, 0x03, 0xB9, 0xF0, 0xD6, +0x03, 0xFE, 0x0C, 0xF0, 0xC6, 0x04, 0xC3, 0x07, +0x09, 0x7C, 0xFE, 0x04, 0xF8, 0xD6, 0x04, 0xC3, +0x07, 0x09, 0x7C, 0xFE, 0x0F, 0xF2, 0xF4, 0x08, +0xB9, 0xFA, 0xF6, 0x08, 0x3E, 0xFF, 0x3C, 0xC3, +0x07, 0x09, 0x7C, 0xFE, 0x01, 0xF2, 0x06, 0x09, +0x79, 0xFE, 0x10, 0xFA, 0x07, 0x09, 0x3D, 0x32, +0xB9, 0xF7, 0xC9, 0x3A, 0xC9, 0xF7, 0x3C, 0xE6, +0x03, 0x32, 0xC9, 0xF7, 0xC3, 0x1E, 0x08, 0x3A, +0xB0, 0xF7, 0xE6, 0xFD, 0x32, 0xB0, 0xF7, 0x3E, +0x1E, 0x90, 0x5F, 0x32, 0xCD, 0xF7, 0xF5, 0xCC, +0x75, 0x0D, 0xF1, 0xFC, 0x75, 0x0D, 0xC9, 0xB7, +0xCA, 0xD8, 0x20, 0xF5, 0x3A, 0xB5, 0xF7, 0xE6, +0x03, 0xFE, 0x03, 0xCA, 0x51, 0x09, 0x3A, 0xB5, +0xF7, 0xE6, 0x04, 0xCA, 0x5D, 0x09, 0xF1, 0x3D, +0xCA, 0xCF, 0x2F, 0x3D, 0x3D, 0x3D, 0xC3, 0x86, +0x09, 0xF1, 0x3D, 0xCA, 0x7F, 0x12, 0x3D, 0xCA, +0x08, 0x12, 0xC3, 0x4C, 0x09, 0xF1, 0x3D, 0xCA, +0x54, 0x31, 0x3D, 0xCA, 0xB1, 0x09, 0x47, 0xCD, +0xA7, 0x0C, 0x78, 0xCA, 0x73, 0x09, 0x3D, 0xCA, +0x0A, 0x0A, 0x3C, 0x3D, 0x3D, 0xCA, 0x28, 0x0A, +0x47, 0x3A, 0xC9, 0xF7, 0xB7, 0x78, 0xC2, 0x86, +0x09, 0x3D, 0xCA, 0x0D, 0x39, 0x3C, 0x3D, 0x3D, +0xCA, 0x66, 0x05, 0x3D, 0xCA, 0x4E, 0x05, 0xC3, +0x67, 0x08, 0x3A, 0xCF, 0xF7, 0xFE, 0x0F, 0x79, +0xCA, 0xFB, 0x3B, 0x79, 0xE6, 0x0C, 0x0F, 0x0F, +0xC6, 0x07, 0x6F, 0x79, 0xE6, 0x03, 0x67, 0x3E, +0xF9, 0xC6, 0x0A, 0x25, 0xF2, 0xA9, 0x09, 0x67, +0xC9, 0xCD, 0xAC, 0x1A, 0xCD, 0xBB, 0x1A, 0x3A, +0xBB, 0xF7, 0xCD, 0x62, 0x1A, 0xCD, 0xC7, 0x1A, +0x21, 0x3D, 0x0C, 0xCD, 0x64, 0x02, 0x3A, 0xBE, +0xF7, 0x47, 0x3A, 0xBB, 0xF7, 0x4F, 0xF6, 0x01, +0xCD, 0xD6, 0x09, 0xC3, 0x1B, 0x08, 0xF5, 0xC5, +0xCD, 0xF3, 0x09, 0xCD, 0x9A, 0x1B, 0xCC, 0x17, +0x1C, 0xC1, 0x78, 0xCD, 0xDB, 0x1B, 0xE5, 0xCD, +0xC8, 0x1B, 0xE1, 0x23, 0xF1, 0xCA, 0xE3, 0x1C, +0xC3, 0xD3, 0x1C, 0xC5, 0xCD, 0x64, 0x03, 0xCD, +0xFD, 0x18, 0xCD, 0x83, 0xF8, 0xCD, 0xDA, 0x16, +0xC1, 0xD5, 0x11, 0x00, 0x80, 0xCD, 0x83, 0xF8, +0xD1, 0xC9, 0x21, 0x21, 0x0C, 0xCD, 0x5F, 0x02, +0xC2, 0x4D, 0x08, 0xCD, 0xAC, 0x1A, 0x21, 0x68, +0x0C, 0xCD, 0x64, 0x02, 0x3A, 0xBE, 0xF7, 0xCD, +0xDB, 0x1B, 0xCD, 0xD1, 0x1B, 0xC3, 0x1B, 0x08, +0xCD, 0x84, 0x0A, 0xCA, 0x4D, 0x08, 0xCD, 0xAC, +0x1A, 0x3A, 0xBE, 0xF7, 0xCD, 0xDB, 0x1B, 0xE5, +0x11, 0x07, 0x00, 0x19, 0x7E, 0x32, 0xCA, 0xF7, +0xE1, 0xE5, 0xCD, 0xD7, 0x1B, 0xCD, 0x9A, 0x1B, +0xCC, 0x17, 0x1C, 0x3E, 0xFF, 0xCD, 0xE3, 0x1B, +0xE5, 0x3A, 0xBE, 0xF7, 0xCD, 0xB9, 0x1B, 0x21, +0x70, 0xEF, 0xEB, 0xE1, 0xE5, 0xCD, 0xA7, 0x1B, +0xE1, 0xE5, 0xCD, 0xBE, 0x1B, 0xE1, 0xD1, 0x01, +0x08, 0x00, 0x09, 0xEB, 0x09, 0xEB, 0x06, 0x04, +0x1A, 0xC5, 0xD5, 0xCD, 0xBD, 0x1C, 0xD1, 0xC1, +0x23, 0x13, 0x05, 0xC2, 0x70, 0x0A, 0xCD, 0xFE, +0x02, 0xC3, 0x1B, 0x08, 0x21, 0x79, 0x0C, 0xCD, +0x64, 0x02, 0x21, 0x0C, 0x0C, 0xCD, 0xBF, 0x19, +0xC9, 0x3A, 0xBE, 0xF7, 0xFE, 0xFF, 0xCA, 0x52, +0x08, 0x21, 0x85, 0x0C, 0xCD, 0x64, 0x02, 0xCD, +0xAE, 0x15, 0x3A, 0xBE, 0xF7, 0x11, 0x00, 0x80, +0xCD, 0x2C, 0x03, 0x21, 0x98, 0x0C, 0xCD, 0x90, +0x02, 0xCD, 0x81, 0x1B, 0xC3, 0x4D, 0x08, 0x3A, +0xC9, 0xF7, 0xFE, 0x00, 0xCA, 0x1C, 0x0B, 0xFE, +0x03, 0xCA, 0x4D, 0x08, 0x3A, 0xBE, 0xF7, 0xFE, +0xFF, 0xCA, 0x52, 0x08, 0x3A, 0xBE, 0xF7, 0x47, +0x3A, 0xBC, 0xF7, 0xB8, 0xCA, 0xF9, 0x0A, 0x21, +0x15, 0x0C, 0xCD, 0x5F, 0x02, 0xC2, 0x4D, 0x08, +0xF7, 0x30, 0x50, 0x3A, 0xBE, 0xF7, 0x32, 0xBC, +0xF7, 0xCD, 0xE2, 0x00, 0x3A, 0xB4, 0xF7, 0xB7, +0xC4, 0xF9, 0x06, 0xCD, 0x0B, 0x01, 0xC3, 0x01, +0x0B, 0xF3, 0x3A, 0xB4, 0xF7, 0xB7, 0xC4, 0xB0, +0x06, 0xAF, 0x32, 0xB0, 0xF7, 0x32, 0xB4, 0xF7, +0xCD, 0xFE, 0x02, 0xCD, 0x39, 0x01, 0xE5, 0xF5, +0xF3, 0xCD, 0x2E, 0x05, 0xCD, 0x50, 0x16, 0xF1, +0xE1, 0xC3, 0x83, 0xF8, 0x3A, 0xBE, 0xF7, 0xFE, +0xFF, 0xCA, 0xA1, 0x0B, 0x47, 0x3A, 0xBD, 0xF7, +0xB8, 0xCA, 0x71, 0x0B, 0x21, 0xE4, 0x0B, 0xCD, +0x5F, 0x02, 0xC2, 0x4D, 0x08, 0xF7, 0x30, 0x50, +0xCD, 0xD4, 0x0B, 0x3A, 0xBB, 0xF7, 0x32, 0xBD, +0xF7, 0xCD, 0xE2, 0x00, 0x3A, 0xBE, 0xF7, 0xCD, +0x91, 0x01, 0x3A, 0xBE, 0xF7, 0x32, 0xBD, 0xF7, +0xCD, 0xE2, 0x00, 0x21, 0xF5, 0xEE, 0x36, 0x00, +0x3A, 0xB4, 0xF7, 0xB7, 0xC4, 0xFF, 0x06, 0xCD, +0x0B, 0x01, 0xAF, 0x32, 0xB4, 0xF7, 0x3E, 0xFF, +0x32, 0xB0, 0xF7, 0xF7, 0x4D, 0x4F, 0xC3, 0xD9, +0x03, 0x21, 0xF4, 0x0B, 0xCD, 0x5F, 0x02, 0xC2, +0x8C, 0x0B, 0xF7, 0x30, 0x50, 0xCD, 0xD4, 0x0B, +0x3A, 0xBB, 0xF7, 0x32, 0xBD, 0xF7, 0xCD, 0xE2, +0x00, 0xC3, 0x1B, 0x08, 0x21, 0x2C, 0x0C, 0xCD, +0x5F, 0x02, 0xC2, 0x4D, 0x08, 0xF7, 0x30, 0x50, +0x3A, 0xBE, 0xF7, 0xCD, 0x91, 0x01, 0xC3, 0x53, +0x0B, 0xCD, 0xBB, 0x1A, 0x21, 0x03, 0x0C, 0xCD, +0x5F, 0x02, 0xC2, 0x4D, 0x08, 0xF7, 0x30, 0x50, +0x21, 0x79, 0x0C, 0xCD, 0x64, 0x02, 0x21, 0x0C, +0x0C, 0xCD, 0xBF, 0x19, 0xCA, 0x4D, 0x08, 0x21, +0x70, 0xEF, 0xCD, 0xB9, 0x0C, 0x3A, 0xBB, 0xF7, +0x32, 0xBD, 0xF7, 0xCD, 0xE2, 0x00, 0xCD, 0xFE, +0x02, 0xC3, 0x1B, 0x08, 0x3A, 0xBD, 0xF7, 0xCD, +0xDB, 0x1B, 0xE5, 0x23, 0xCD, 0xB9, 0x0C, 0xE1, +0xCD, 0xD1, 0x1B, 0xC9, 0x53, 0x77, 0x69, 0x74, +0x63, 0x68, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x65, +0x78, 0x69, 0x74, 0x00, 0x52, 0x65, 0x66, 0x72, +0x65, 0x73, 0x68, 0x20, 0x62, 0x61, 0x63, 0x6B, +0x75, 0x70, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, +0x65, 0x20, 0x6E, 0x65, 0x77, 0x20, 0x62, 0x61, +0x63, 0x6B, 0x75, 0x70, 0x00, 0x49, 0x6E, 0x73, +0x74, 0x61, 0x6C, 0x6C, 0x20, 0x52, 0x4F, 0x4D, +0x00, 0x4B, 0x69, 0x6C, 0x6C, 0x20, 0x69, 0x6D, +0x61, 0x67, 0x65, 0x00, 0x52, 0x65, 0x76, 0x65, +0x72, 0x74, 0x20, 0x74, 0x6F, 0x20, 0x62, 0x61, +0x63, 0x6B, 0x75, 0x70, 0x00, 0x43, 0x6F, 0x70, +0x79, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x6D, 0x61, +0x67, 0x65, 0x2E, 0x2E, 0x2E, 0x00, 0x52, 0x65, +0x62, 0x75, 0x69, 0x6C, 0x64, 0x69, 0x6E, 0x67, +0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, +0x72, 0x69, 0x65, 0x73, 0x2E, 0x2E, 0x2E, 0x00, +0x4B, 0x69, 0x6C, 0x6C, 0x69, 0x6E, 0x67, 0x20, +0x69, 0x6D, 0x61, 0x67, 0x65, 0x2E, 0x2E, 0x2E, +0x00, 0x4E, 0x65, 0x77, 0x20, 0x4E, 0x61, 0x6D, +0x65, 0x20, 0x3F, 0x20, 0x00, 0x31, 0x36, 0x20, +0x62, 0x69, 0x74, 0x20, 0x63, 0x68, 0x65, 0x63, +0x6B, 0x73, 0x75, 0x6D, 0x20, 0x3D, 0x20, 0x00, +0x20, 0x20, 0x3C, 0x61, 0x6E, 0x79, 0x20, 0x6B, +0x65, 0x79, 0x3E, 0x2E, 0x2E, 0x2E, 0x00, 0x3A, +0xBE, 0xF7, 0xC5, 0x47, 0x3A, 0xBC, 0xF7, 0xB8, +0xCA, 0xB7, 0x0C, 0x3A, 0xBD, 0xF7, 0xB8, 0xC1, +0xC9, 0xE5, 0xCD, 0x6C, 0x01, 0xE1, 0xAF, 0x32, +0xCA, 0xF7, 0xCD, 0xD3, 0x1C, 0xC9, 0x3E, 0xFF, +0x32, 0xBB, 0xF7, 0x11, 0x00, 0x00, 0xCD, 0xA2, +0x38, 0xC2, 0xDB, 0x0C, 0x79, 0xE6, 0xFE, 0x32, +0xBB, 0xF7, 0xC9, 0x11, 0x40, 0x40, 0xCD, 0xA2, +0x38, 0xC2, 0xE7, 0x0C, 0xC3, 0xF0, 0x0C, 0x11, +0x40, 0x00, 0xCD, 0xA2, 0x38, 0xC2, 0xF7, 0x0C, +0x79, 0xCD, 0x52, 0x0D, 0xC3, 0x4C, 0x0D, 0x11, +0x00, 0xC0, 0xCD, 0xA2, 0x38, 0xC2, 0x66, 0x0D, +0x79, 0x32, 0xBB, 0xF7, 0x11, 0xC0, 0x40, 0xCD, +0xA2, 0x38, 0xCA, 0x16, 0x0D, 0x11, 0xC0, 0x00, +0xCD, 0xA2, 0x38, 0xC2, 0x66, 0x0D, 0xF5, 0xC5, +0x41, 0x3A, 0xBB, 0xF7, 0x4F, 0xAF, 0xCD, 0xD6, +0x09, 0xC1, 0xC5, 0x79, 0xCD, 0x52, 0x0D, 0xC1, +0xF1, 0x3A, 0xBD, 0xF7, 0xB9, 0xC2, 0x3C, 0x0D, +0x3A, 0xBB, 0xF7, 0x32, 0xBD, 0xF7, 0xCD, 0xE2, +0x00, 0xC3, 0x4C, 0x0D, 0x3A, 0xBC, 0xF7, 0xB9, +0xC2, 0x4C, 0x0D, 0x3A, 0xBB, 0xF7, 0x32, 0xBC, +0xF7, 0xCD, 0xE2, 0x00, 0xCD, 0xBD, 0x34, 0xC3, +0xC6, 0x0C, 0xF5, 0xCD, 0xEF, 0x37, 0xF1, 0xF5, +0xCD, 0x5E, 0x0D, 0xF1, 0xEE, 0x01, 0xCD, 0xE3, +0x1B, 0xC0, 0xCD, 0xD7, 0x1B, 0xC9, 0x21, 0x8E, +0x0D, 0xC3, 0x6F, 0x0D, 0x21, 0x7E, 0x0D, 0xCD, +0x64, 0x02, 0xCD, 0x8A, 0x1B, 0x3A, 0xB0, 0xF7, +0xF6, 0x02, 0x32, 0xB0, 0xF7, 0xC9, 0x4E, 0x6F, +0x20, 0x66, 0x72, 0x65, 0x65, 0x20, 0x62, 0x6C, +0x6F, 0x63, 0x6B, 0x73, 0x21, 0x00, 0x43, 0x61, +0x6E, 0x27, 0x74, 0x20, 0x66, 0x69, 0x6E, 0x64, +0x20, 0x61, 0x20, 0x62, 0x6C, 0x61, 0x6E, 0x6B, +0x20, 0x73, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x21, +0x11, 0x05, 0x21, 0x21, 0xBC, 0x0D, 0xCD, 0x86, +0x02, 0x3A, 0xCD, 0xF7, 0xB7, 0xF8, 0xCD, 0xE9, +0x0D, 0xC3, 0x76, 0x03, 0x46, 0x72, 0x65, 0x65, +0x3A, 0x00, 0x3A, 0xB0, 0xF7, 0xE6, 0x04, 0xC8, +0x11, 0x0B, 0x01, 0x21, 0xF0, 0x0D, 0xCD, 0x86, +0x02, 0x3A, 0xBB, 0xF7, 0xCD, 0xE9, 0x0D, 0x21, +0xF3, 0x0D, 0xCD, 0x90, 0x02, 0x3A, 0xBE, 0xF7, +0xCD, 0xE9, 0x0D, 0x21, 0xAC, 0x0E, 0xC3, 0x90, +0x02, 0x6F, 0x26, 0x00, 0xF7, 0x0B, 0x47, 0xC9, +0x46, 0x3A, 0x00, 0x20, 0x43, 0x3A, 0x00, 0x11, +0x05, 0x0D, 0x21, 0x10, 0x0E, 0xCD, 0x86, 0x02, +0x21, 0x44, 0x13, 0x3A, 0xC9, 0xF7, 0x07, 0x07, +0x16, 0x00, 0x5F, 0x19, 0xCD, 0x90, 0x02, 0xC9, +0x47, 0x72, 0x6F, 0x75, 0x70, 0x3C, 0x54, 0x41, +0x42, 0x3E, 0x3A, 0x00, 0x0E, 0xFF, 0x0C, 0x3A, +0xBA, 0xF7, 0xB9, 0xCA, 0x63, 0x0E, 0x21, 0xE3, +0xF8, 0xC5, 0x06, 0x00, 0x09, 0x7E, 0xC1, 0x21, +0xA3, 0xF8, 0xC5, 0x87, 0x4F, 0x06, 0x00, 0x09, +0xC1, 0xEB, 0xED, 0x7E, 0xE6, 0x3F, 0xF5, 0x23, +0xC5, 0xE5, 0xCD, 0x9B, 0x09, 0xF7, 0x9B, 0x4F, +0xE1, 0xC1, 0x16, 0x06, 0xCD, 0xDD, 0x02, 0xF1, +0xCD, 0xAA, 0x0C, 0xCA, 0x5B, 0x0E, 0x3E, 0x20, +0xC3, 0x5D, 0x0E, 0x3E, 0x2A, 0xF7, 0x30, 0x50, +0xC3, 0x1E, 0x0E, 0x3A, 0xC9, 0xF7, 0xFE, 0x03, +0x3A, 0xBA, 0xF7, 0xCA, 0x85, 0x0E, 0xFE, 0x10, +0xF0, 0x4F, 0xCD, 0x9B, 0x09, 0xF7, 0x9B, 0x4F, +0x21, 0xB0, 0x0E, 0xCD, 0x90, 0x02, 0x3A, 0xBA, +0xF7, 0xFE, 0x0F, 0xF0, 0x3C, 0x4F, 0x3E, 0x10, +0x91, 0x47, 0x78, 0xB7, 0xC8, 0xC5, 0xCD, 0x9B, +0x09, 0xF7, 0x9B, 0x4F, 0x21, 0xA8, 0x0E, 0xCD, +0x90, 0x02, 0xC1, 0x05, 0x0C, 0xC3, 0x8A, 0x0E, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, +0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x20, 0x00, +0x11, 0x06, 0x01, 0x3A, 0xC9, 0xF7, 0xFE, 0x03, +0xCA, 0x1B, 0x0F, 0x3A, 0xB0, 0xF7, 0xE6, 0x10, +0xC2, 0xD6, 0x0E, 0x3A, 0xB6, 0xF7, 0xE6, 0x03, +0xFE, 0x03, 0xCA, 0x5E, 0x03, 0xC9, 0x3A, 0xC9, +0xF7, 0xB7, 0xCA, 0xF6, 0x0E, 0x3A, 0xBE, 0xF7, +0x3C, 0xCA, 0x5E, 0x03, 0xCD, 0x15, 0x0F, 0xCD, +0xA7, 0x0C, 0x21, 0xCD, 0x0F, 0xCA, 0x0F, 0x0F, +0x21, 0xB9, 0x0F, 0xC3, 0x0F, 0x0F, 0xCD, 0x15, +0x0F, 0x3A, 0xBE, 0xF7, 0x3C, 0x21, 0x04, 0x10, +0xCA, 0x0F, 0x0F, 0xCD, 0xA7, 0x0C, 0x21, 0xF2, +0x0F, 0xCA, 0x0F, 0x0F, 0x21, 0xDF, 0x0F, 0xCD, +0x90, 0x02, 0xC3, 0x76, 0x03, 0x21, 0x16, 0x10, +0xC3, 0x86, 0x02, 0x3A, 0xBE, 0xF7, 0xCD, 0x27, +0x0F, 0xCD, 0x86, 0x02, 0xC3, 0x76, 0x03, 0x21, +0x3B, 0x0F, 0x3D, 0x3D, 0xC8, 0x21, 0x56, 0x0F, +0x3D, 0xC8, 0x21, 0x78, 0x0F, 0x3D, 0xC8, 0x21, +0x95, 0x0F, 0xC9, 0x50, 0x72, 0x69, 0x6D, 0x61, +0x72, 0x79, 0x20, 0x4D, 0x61, 0x69, 0x6E, 0x20, +0x52, 0x4F, 0x4D, 0x20, 0x30, 0x30, 0x30, 0x30, +0x2D, 0x37, 0x46, 0x46, 0x46, 0x00, 0x50, 0x72, +0x69, 0x6D, 0x61, 0x72, 0x79, 0x20, 0x4D, 0x61, +0x69, 0x6E, 0x20, 0x52, 0x4F, 0x4D, 0x20, 0x38, +0x30, 0x30, 0x30, 0x2D, 0x39, 0x46, 0x46, 0x46, +0x20, 0x28, 0x54, 0x32, 0x30, 0x30, 0x29, 0x00, +0x53, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x61, 0x72, +0x79, 0x20, 0x4D, 0x61, 0x69, 0x6E, 0x20, 0x52, +0x4F, 0x4D, 0x20, 0x30, 0x30, 0x30, 0x30, 0x2D, +0x37, 0x46, 0x46, 0x46, 0x00, 0x53, 0x65, 0x63, +0x6F, 0x6E, 0x64, 0x61, 0x72, 0x79, 0x20, 0x4D, +0x61, 0x69, 0x6E, 0x20, 0x52, 0x4F, 0x4D, 0x20, +0x38, 0x30, 0x30, 0x30, 0x2D, 0x39, 0x46, 0x46, +0x46, 0x20, 0x28, 0x54, 0x32, 0x30, 0x30, 0x29, +0x00, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20, +0x4F, 0x50, 0x54, 0x52, 0x4F, 0x4D, 0x20, 0x69, +0x6D, 0x61, 0x67, 0x65, 0x00, 0x52, 0x65, 0x61, +0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, +0x4F, 0x50, 0x54, 0x52, 0x4F, 0x4D, 0x00, 0x52, +0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x20, 0x61, +0x6E, 0x64, 0x20, 0x73, 0x77, 0x69, 0x74, 0x63, +0x68, 0x00, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, +0x68, 0x20, 0x6F, 0x72, 0x20, 0x72, 0x65, 0x76, +0x65, 0x72, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, +0x74, 0x65, 0x20, 0x6E, 0x65, 0x77, 0x20, 0x62, +0x61, 0x63, 0x6B, 0x75, 0x70, 0x00, 0x3C, 0x45, +0x4E, 0x54, 0x45, 0x52, 0x3E, 0x3A, 0x00, 0xCD, +0xAE, 0x15, 0xAF, 0x11, 0x40, 0x60, 0xD5, 0xCD, +0x83, 0xF8, 0xEB, 0xE3, 0x3E, 0x01, 0xEB, 0xCD, +0x83, 0xF8, 0xE1, 0xF7, 0x18, 0x00, 0xC8, 0x21, +0xA5, 0x10, 0xCD, 0x77, 0x02, 0x21, 0xC0, 0x10, +0xCD, 0x72, 0x02, 0x47, 0xC5, 0xF7, 0x30, 0x50, +0xCD, 0xB3, 0x02, 0x21, 0xDE, 0x10, 0xCD, 0x72, +0x02, 0xF5, 0xF7, 0x30, 0x50, 0xCD, 0xB3, 0x02, +0xF1, 0xC1, 0x78, 0xC2, 0x3D, 0x10, 0xFE, 0x59, +0xCA, 0x85, 0x10, 0x21, 0xE3, 0x10, 0xCD, 0x77, +0x02, 0x21, 0x00, 0x40, 0xAF, 0xCD, 0x75, 0x1B, +0xCD, 0xFD, 0x18, 0xCD, 0x83, 0xF8, 0xCD, 0xDA, +0x16, 0x11, 0x40, 0x60, 0x01, 0x00, 0x01, 0xCD, +0x83, 0xF8, 0xC3, 0x8B, 0x10, 0x21, 0x05, 0x11, +0xCD, 0x7C, 0x02, 0x3E, 0x01, 0x32, 0xBB, 0xF7, +0xCD, 0x73, 0x1B, 0xCD, 0xFD, 0x18, 0xCD, 0x83, +0xF8, 0xCD, 0xDA, 0x16, 0x01, 0x01, 0x00, 0x11, +0x00, 0x80, 0xC3, 0x83, 0xF8, 0x44, 0x69, 0x72, +0x65, 0x63, 0x74, 0x6F, 0x72, 0x69, 0x65, 0x73, +0x20, 0x61, 0x72, 0x65, 0x20, 0x64, 0x69, 0x66, +0x66, 0x65, 0x72, 0x65, 0x6E, 0x74, 0x2E, 0x00, +0x4B, 0x65, 0x65, 0x70, 0x20, 0x6D, 0x61, 0x69, +0x6E, 0x20, 0x28, 0x62, 0x6C, 0x6F, 0x63, 0x6B, +0x20, 0x30, 0x29, 0x20, 0x64, 0x69, 0x72, 0x65, +0x63, 0x74, 0x6F, 0x72, 0x79, 0x00, 0x53, 0x55, +0x52, 0x45, 0x00, 0x43, 0x6F, 0x70, 0x79, 0x20, +0x62, 0x61, 0x63, 0x6B, 0x75, 0x70, 0x20, 0x64, +0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x79, +0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x69, 0x6E, +0x2E, 0x2E, 0x2E, 0x2E, 0x00, 0x43, 0x6F, 0x70, +0x79, 0x20, 0x6D, 0x61, 0x69, 0x6E, 0x20, 0x64, +0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x79, +0x20, 0x74, 0x6F, 0x20, 0x62, 0x61, 0x63, 0x6B, +0x75, 0x70, 0x2E, 0x2E, 0x2E, 0x2E, 0x00, 0xF7, +0x4D, 0x4F, 0xCD, 0x77, 0x16, 0xCD, 0x83, 0xF8, +0xC5, 0x11, 0x06, 0x02, 0x21, 0x99, 0x11, 0xCD, +0x86, 0x02, 0xCD, 0xAE, 0x15, 0xAF, 0x11, 0x00, +0x40, 0xCD, 0x2C, 0x03, 0x11, 0x07, 0x02, 0x21, +0xAC, 0x11, 0xCD, 0x86, 0x02, 0xC1, 0xC5, 0x79, +0xE6, 0xC0, 0xCA, 0x5B, 0x11, 0x21, 0x50, 0x1B, +0xC3, 0x5E, 0x11, 0x21, 0x4C, 0x1B, 0xCD, 0x90, +0x02, 0x11, 0x08, 0x02, 0x21, 0xB7, 0x11, 0xCD, +0x86, 0x02, 0xC1, 0xC5, 0x79, 0xE6, 0x3C, 0x0F, +0x0F, 0x26, 0x00, 0x6F, 0xF7, 0x0B, 0x47, 0x3E, +0x28, 0xF7, 0x30, 0x50, 0xC1, 0xC5, 0x79, 0xE6, +0x03, 0x26, 0x00, 0x6F, 0xF7, 0x0B, 0x47, 0x3E, +0x29, 0xF7, 0x30, 0x50, 0xC1, 0x21, 0x98, 0x0C, +0xCD, 0x64, 0x02, 0xCD, 0x81, 0x1B, 0xC3, 0xCC, +0x20, 0x53, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72, +0x65, 0x20, 0x3A, 0x34, 0x2E, 0x38, 0x2C, 0x20, +0x43, 0x53, 0x3D, 0x00, 0x4D, 0x6F, 0x64, 0x65, +0x6C, 0x20, 0x20, 0x20, 0x20, 0x3A, 0x00, 0x46, +0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x20, +0x3A, 0x00, 0xCD, 0x20, 0x19, 0xCD, 0x83, 0xF8, +0xC2, 0xD3, 0x11, 0x3A, 0xB0, 0xF7, 0xF6, 0x20, +0xC3, 0xD8, 0x11, 0x3A, 0xB0, 0xF7, 0xE6, 0xDF, +0x32, 0xB0, 0xF7, 0xC9, 0x21, 0x05, 0x09, 0xF7, +0x9B, 0x4F, 0xCD, 0x06, 0x03, 0x3A, 0xB0, 0xF7, +0xE6, 0x20, 0xC2, 0xF2, 0x11, 0x3E, 0x4D, 0xC3, +0x01, 0x12, 0x3A, 0xB1, 0xF7, 0xE6, 0x40, 0xCA, +0xFF, 0x11, 0x3E, 0x53, 0xC3, 0x01, 0x12, 0x3E, +0x50, 0xF7, 0x30, 0x50, 0xCD, 0x0B, 0x03, 0xC9, +0xCD, 0x6A, 0x03, 0x3A, 0xBE, 0xF7, 0xFE, 0x02, +0xCA, 0x18, 0x12, 0xFE, 0x04, 0xC2, 0x4D, 0x08, +0xCD, 0xE1, 0x12, 0xCA, 0x4D, 0x08, 0xCD, 0x15, +0x13, 0xCA, 0x4D, 0x08, 0x21, 0x59, 0x12, 0xCD, +0x64, 0x02, 0x3A, 0xBE, 0xF7, 0xFE, 0x02, 0xCA, +0x38, 0x12, 0x21, 0x67, 0x12, 0xC3, 0x3B, 0x12, +0x21, 0x74, 0x12, 0xCD, 0x90, 0x02, 0x21, 0xDE, +0x10, 0xCD, 0x72, 0x02, 0xC2, 0x4D, 0x08, 0x3A, +0xBE, 0xF7, 0x0F, 0x3D, 0xE6, 0x01, 0x0F, 0x0F, +0x32, 0xB1, 0xF7, 0xCD, 0xE2, 0x00, 0xC3, 0x1B, +0x08, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x69, +0x6E, 0x67, 0x20, 0x74, 0x6F, 0x20, 0x00, 0x53, +0x65, 0x63, 0x6F, 0x6E, 0x64, 0x61, 0x72, 0x79, +0x2E, 0x2E, 0x2E, 0x00, 0x50, 0x72, 0x69, 0x6D, +0x61, 0x72, 0x79, 0x2E, 0x2E, 0x2E, 0x00, 0x3A, +0xB0, 0xF7, 0xE6, 0x20, 0xCA, 0xD2, 0x2F, 0x3A, +0xBE, 0xF7, 0xE6, 0x02, 0xCA, 0xD2, 0x2F, 0x21, +0x98, 0x12, 0xCD, 0x2B, 0x13, 0xCA, 0x4D, 0x08, +0x52, 0x45, 0x58, 0x20, 0x4D, 0x61, 0x6E, 0x61, +0x67, 0x65, 0x72, 0x20, 0x75, 0x73, 0x65, 0x73, +0x20, 0x50, 0x72, 0x69, 0x6D, 0x61, 0x72, 0x79, +0x20, 0x61, 0x73, 0x20, 0x64, 0x65, 0x66, 0x61, +0x75, 0x6C, 0x74, 0x2E, 0x00, 0x3A, 0xB9, 0xF7, +0x4F, 0x3A, 0xBA, 0xF7, 0xB9, 0xCA, 0xDB, 0x12, +0x06, 0x00, 0x21, 0xE3, 0xF8, 0x09, 0x7E, 0x32, +0xBE, 0xF7, 0x07, 0x4F, 0x21, 0xA3, 0xF8, 0x09, +0xEB, 0xED, 0xC9, 0x3E, 0xFF, 0x32, 0xBE, 0xF7, +0xC9, 0x3A, 0xB0, 0xF7, 0xE6, 0x20, 0xC0, 0x21, +0xED, 0x12, 0xC3, 0x2B, 0x13, 0x52, 0x45, 0x58, +0x20, 0x6E, 0x6F, 0x74, 0x20, 0x63, 0x6F, 0x6E, +0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x64, 0x20, +0x74, 0x6F, 0x20, 0x70, 0x72, 0x6F, 0x76, 0x69, +0x64, 0x65, 0x20, 0x6D, 0x61, 0x69, 0x6E, 0x20, +0x72, 0x6F, 0x6D, 0x2E, 0x00, 0x3A, 0xBE, 0xF7, +0xE6, 0x06, 0x0F, 0x3D, 0x0F, 0x0F, 0xF5, 0x3A, +0xB1, 0xF7, 0xE6, 0x40, 0x47, 0xF1, 0xB8, 0xC0, +0x21, 0x33, 0x13, 0xCD, 0x64, 0x02, 0xCD, 0x8A, +0x1B, 0xAF, 0xC9, 0x4D, 0x61, 0x69, 0x6E, 0x20, +0x52, 0x4F, 0x4D, 0x20, 0x69, 0x6E, 0x20, 0x75, +0x73, 0x65, 0x21, 0x00, 0x52, 0x41, 0x4D, 0x00, +0x52, 0x4F, 0x4D, 0x00, 0x4F, 0x53, 0x20, 0x00, +0x53, 0x59, 0x53, 0x00, 0xF7, 0x4D, 0x4F, 0x11, +0x05, 0x01, 0x21, 0x61, 0x13, 0xCD, 0x86, 0x02, +0xC9, 0x52, 0x45, 0x58, 0x34, 0x2E, 0x38, 0x00, +0x3A, 0xB0, 0xF7, 0xEE, 0x08, 0x32, 0xB0, 0xF7, +0xC3, 0x1E, 0x08, 0xF5, 0x3A, 0xB0, 0xF7, 0xEE, +0x04, 0x32, 0xB0, 0xF7, 0xE6, 0x04, 0xF5, 0xCC, +0x52, 0x03, 0xF1, 0xC4, 0xC2, 0x0D, 0xF1, 0xC9, +0xF5, 0x3A, 0xB0, 0xF7, 0xEE, 0x10, 0x32, 0xB0, +0xF7, 0xE6, 0x10, 0xCC, 0x5E, 0x03, 0x3A, 0xB5, +0xF7, 0xEE, 0x20, 0x32, 0xB5, 0xF7, 0xF1, 0xC9, +0xC5, 0xF5, 0xE5, 0xD5, 0x3A, 0xB8, 0xF7, 0x4F, +0x3A, 0xB9, 0xF7, 0xB9, 0xCA, 0xB8, 0x13, 0xC5, +0xCD, 0xBD, 0x13, 0xC1, 0x79, 0xCD, 0xBD, 0x13, +0xD1, 0xE1, 0xF1, 0xC1, 0xC9, 0x4F, 0xCD, 0x92, +0x09, 0x24, 0x22, 0x06, 0xEF, 0x3A, 0xCF, 0xF7, +0x47, 0xF7, 0x75, 0x6D, 0xC9, 0x3A, 0xB5, 0xF7, +0xE6, 0x04, 0xC2, 0x4C, 0x03, 0xE5, 0xCD, 0xF1, +0x1D, 0xCD, 0x96, 0x1D, 0xE1, 0xCD, 0xEA, 0x1D, +0xC3, 0x7E, 0x1D, 0x3A, 0xB5, 0xF7, 0xE6, 0x30, +0x4F, 0x3A, 0xC9, 0xF7, 0xF5, 0xE6, 0x03, 0xB1, +0x4F, 0x3A, 0xBE, 0xF7, 0xFE, 0xFF, 0x79, 0xC2, +0xFC, 0x13, 0xF6, 0x04, 0x4F, 0xCD, 0xA7, 0x0C, +0x79, 0xC2, 0x06, 0x14, 0xF6, 0x08, 0x4F, 0xF1, +0xFE, 0x03, 0x79, 0xC2, 0x12, 0x14, 0xEE, 0x10, +0xF6, 0x04, 0x32, 0xB5, 0xF7, 0xC9, 0x2A, 0xB5, +0xF7, 0x7D, 0xBC, 0xC8, 0xCD, 0xB8, 0x0E, 0xC3, +0x22, 0x14, 0x21, 0x0C, 0x01, 0xF7, 0x9B, 0x4F, +0x21, 0xA1, 0x14, 0xCD, 0x90, 0x02, 0x3A, 0xB5, +0xF7, 0xE6, 0x04, 0xCA, 0x6A, 0x14, 0x21, 0xA7, +0x14, 0xCD, 0x90, 0x02, 0x3A, 0xB5, 0xF7, 0xE6, +0x03, 0xFE, 0x03, 0xCA, 0x61, 0x14, 0x21, 0xAA, +0x0E, 0xCD, 0x90, 0x02, 0x21, 0xAA, 0x0E, 0xCD, +0x90, 0x02, 0x21, 0xAA, 0x0E, 0xCD, 0x90, 0x02, +0x21, 0xAA, 0x0E, 0xCD, 0x90, 0x02, 0xC3, 0x9A, +0x14, 0x21, 0xAD, 0x14, 0xCD, 0x90, 0x02, 0xC3, +0x4C, 0x14, 0x21, 0xB3, 0x14, 0xCD, 0x90, 0x02, +0x3A, 0xB5, 0xF7, 0xE6, 0x08, 0xC2, 0x81, 0x14, +0x21, 0xBE, 0x14, 0xCD, 0x90, 0x02, 0xC3, 0x87, +0x14, 0x21, 0xAA, 0x0E, 0xCD, 0x90, 0x02, 0x21, +0xC4, 0x14, 0xCD, 0x90, 0x02, 0x3A, 0xC9, 0xF7, +0xB7, 0xC2, 0x58, 0x14, 0x21, 0xCA, 0x14, 0xCD, +0x90, 0x02, 0x21, 0xD0, 0x14, 0xCD, 0x90, 0x02, +0xC9, 0x48, 0x65, 0x6C, 0x70, 0x20, 0x00, 0x4C, +0x6F, 0x61, 0x64, 0x20, 0x00, 0x55, 0x73, 0x65, +0x20, 0x20, 0x00, 0x53, 0x61, 0x76, 0x65, 0x20, +0x43, 0x6F, 0x70, 0x79, 0x20, 0x00, 0x4B, 0x69, +0x6C, 0x6C, 0x20, 0x00, 0x4E, 0x61, 0x6D, 0x65, +0x20, 0x00, 0x46, 0x69, 0x6C, 0x65, 0x20, 0x00, +0x44, 0x65, 0x49, 0x6E, 0x20, 0x45, 0x78, 0x69, +0x74, 0x00, 0x53, 0x69, 0x7A, 0x65, 0x20, 0x00, +0xCD, 0xE7, 0x02, 0xE9, 0x14, 0xD4, 0xF7, 0xAF, +0xC9, 0x39, 0x38, 0x4E, 0x31, 0x44, 0x4E, 0x4E, +0x00, 0xF5, 0xDB, 0xD8, 0xE6, 0x0C, 0xF6, 0x02, +0xD3, 0xD8, 0xF1, 0xC9, 0xF5, 0xDB, 0xD8, 0xE6, +0x0C, 0xD3, 0xD8, 0xF1, 0xC9, 0xE5, 0xF5, 0x21, +0x00, 0x00, 0x7E, 0x7E, 0x7E, 0xF1, 0x2E, 0xB8, +0x6E, 0x2E, 0xF2, 0x6E, 0x2E, 0x34, 0x6E, 0x2E, +0xB0, 0x6E, 0x2E, 0x31, 0x6E, 0x2E, 0xBF, 0x6E, +0xE1, 0xC9, 0xE5, 0x21, 0x01, 0x00, 0x6E, 0x6F, +0x7E, 0xE1, 0xC9, 0x21, 0xAA, 0x0A, 0x7E, 0x7E, +0x21, 0x55, 0x05, 0x7E, 0x7E, 0x3A, 0xAA, 0x0A, +0x3A, 0xA0, 0x0A, 0x3A, 0x06, 0x00, 0x62, 0x6B, +0x7E, 0x68, 0x7E, 0x21, 0x03, 0x00, 0x7E, 0x17, +0x7E, 0xD2, 0x31, 0xF8, 0xC9, 0xE5, 0xC5, 0xD5, +0x21, 0x00, 0x00, 0x06, 0x08, 0x11, 0x28, 0x00, +0x3E, 0x0A, 0xD3, 0xFF, 0x7D, 0xD3, 0xFE, 0x3E, +0x0B, 0xD3, 0xFF, 0x7C, 0xD3, 0xFE, 0x3E, 0x0C, +0xD3, 0xFF, 0x3E, 0x00, 0xD3, 0xFE, 0x19, 0x7C, +0xE6, 0x1F, 0x67, 0x05, 0xC2, 0x43, 0xF8, 0x3A, +0x56, 0xF8, 0x37, 0x17, 0x32, 0x56, 0xF8, 0xE6, +0xC0, 0xD1, 0xC1, 0xE1, 0xC8, 0xE5, 0x3E, 0x01, +0x32, 0x56, 0xF8, 0x2A, 0x3C, 0xF8, 0x23, 0x7C, +0xE6, 0x1F, 0x67, 0x22, 0x3C, 0xF8, 0xE1, 0xC9, +0xCD, 0xE7, 0x02, 0xA1, 0x15, 0x83, 0xF8, 0x0D, +0xC9, 0xF3, 0xCD, 0xF0, 0xF7, 0xAF, 0xCD, 0x0D, +0xF8, 0x3A, 0x00, 0x00, 0xFB, 0xC9, 0xCD, 0xE7, +0x02, 0xB7, 0x15, 0x83, 0xF8, 0x34, 0xC9, 0xF3, +0xCD, 0xF0, 0xF7, 0xCD, 0x0D, 0xF8, 0x21, 0x00, +0x00, 0x7E, 0x39, 0x22, 0xC7, 0xF7, 0x63, 0x2E, +0x00, 0xF9, 0x7A, 0x06, 0x00, 0xD1, 0x4A, 0x09, +0x4B, 0x09, 0x38, 0x00, 0xBA, 0xC2, 0x99, 0xF8, +0xEB, 0x2A, 0xC7, 0xF7, 0xF9, 0xD5, 0xCD, 0xF0, +0xF7, 0xAF, 0xCD, 0x0D, 0xF8, 0x3A, 0x00, 0x00, +0xD1, 0xFB, 0xC9, 0xCD, 0xE7, 0x02, 0xF4, 0x15, +0x83, 0xF8, 0x39, 0xC9, 0xF3, 0xCD, 0xF0, 0xF7, +0xCD, 0x0D, 0xF8, 0x21, 0x00, 0x00, 0x7E, 0x39, +0x22, 0xC7, 0xF7, 0x21, 0x00, 0x00, 0xF9, 0x01, +0x01, 0x00, 0x11, 0x00, 0xC0, 0xAF, 0xE1, 0x09, +0xD2, 0xA9, 0xF8, 0x13, 0xBA, 0xC2, 0x9D, 0xF8, +0x3E, 0xFF, 0x2A, 0xC7, 0xF7, 0xF9, 0x3C, 0xF5, +0xCD, 0xF0, 0xF7, 0xAF, 0xCD, 0x0D, 0xF8, 0x3A, +0x00, 0x00, 0xF1, 0xFB, 0xC9, 0xCD, 0xE7, 0x02, +0x36, 0x16, 0x83, 0xF8, 0x1A, 0xC9, 0xF3, 0xCD, +0xF0, 0xF7, 0x3A, 0xBC, 0xF7, 0xE6, 0x3F, 0x47, +0x3A, 0xB1, 0xF7, 0xE6, 0x40, 0xB0, 0xCD, 0x0D, +0xF8, 0x3A, 0x00, 0x00, 0xCD, 0xE7, 0xF7, 0xC7, +0xCD, 0xE7, 0x02, 0x59, 0x16, 0x83, 0xF8, 0x1E, +0xC9, 0xF3, 0xE5, 0xF5, 0xCD, 0xF0, 0xF7, 0x3A, +0xBC, 0xF7, 0xE6, 0x3F, 0x47, 0x3A, 0xB1, 0xF7, +0xE6, 0x40, 0xB0, 0xCD, 0x0D, 0xF8, 0x3A, 0x00, +0x00, 0xCD, 0xE7, 0xF7, 0xF1, 0xE1, 0xE9, 0xCD, +0xE7, 0x02, 0x80, 0x16, 0x83, 0xF8, 0x15, 0xC9, +0xF3, 0xF5, 0xCD, 0xF0, 0xF7, 0x21, 0x03, 0x00, +0x46, 0x7E, 0x21, 0x07, 0x00, 0x4E, 0x7E, 0x3A, +0x00, 0x00, 0xF1, 0xFB, 0xC9, 0xCD, 0xE7, 0x02, +0x9E, 0x16, 0x83, 0xF8, 0x3C, 0xC9, 0xF3, 0xCD, +0xF0, 0xF7, 0xCD, 0x0D, 0xF8, 0xE5, 0x21, 0xAA, +0x0A, 0x7E, 0x7E, 0x21, 0x55, 0x05, 0x7E, 0x7E, +0x3A, 0xAA, 0x00, 0x3A, 0x80, 0x0A, 0x21, 0xAA, +0x0A, 0x7E, 0x7E, 0x21, 0x55, 0x05, 0x7E, 0x7E, +0x3A, 0x06, 0x00, 0xE1, 0x7E, 0x2E, 0x30, 0x7E, +0x3E, 0x13, 0x3D, 0xC2, 0xAF, 0xF8, 0xCD, 0x2E, +0xF8, 0xAF, 0xCD, 0x0D, 0xF8, 0x3A, 0x00, 0x00, +0xFB, 0xC9, 0xCD, 0xE7, 0x02, 0xE3, 0x16, 0x83, +0xF8, 0x7C, 0xC9, 0xF3, 0x63, 0x2E, 0x00, 0x22, +0xBF, 0xF7, 0x7A, 0x32, 0xEE, 0xF8, 0x78, 0x32, +0xA0, 0xF8, 0x79, 0x32, 0xC4, 0xF8, 0x26, 0x00, +0x39, 0x22, 0xC7, 0xF7, 0xCD, 0xF0, 0xF7, 0x3E, +0x00, 0xCD, 0x0D, 0xF8, 0x3A, 0x00, 0x00, 0x21, +0x22, 0xF0, 0xF9, 0x2A, 0xBF, 0xF7, 0xEB, 0xED, +0xE5, 0x13, 0x13, 0x7B, 0xE6, 0x7F, 0xC2, 0xAF, +0xF8, 0xEB, 0x22, 0xBF, 0xF7, 0x22, 0xC1, 0xF7, +0xCD, 0xF0, 0xF7, 0x3E, 0x00, 0xCD, 0x0D, 0xF8, +0x2A, 0xBF, 0xF7, 0xEB, 0xC1, 0x1B, 0xCD, 0x16, +0xF8, 0x41, 0x1B, 0xCD, 0x16, 0xF8, 0x7B, 0xE6, +0x7F, 0xC2, 0xCC, 0xF8, 0x2A, 0xC1, 0xF7, 0x22, +0xBF, 0xF7, 0x7C, 0xE6, 0x03, 0xB5, 0xC2, 0xEC, +0xF8, 0xCD, 0x38, 0xF8, 0x7C, 0xFE, 0x80, 0xC2, +0x9F, 0xF8, 0x2A, 0xC7, 0xF7, 0xF9, 0xAF, 0xCD, +0x0D, 0xF8, 0x3A, 0x00, 0x00, 0xFB, 0xC9, 0xCD, +0xE7, 0x02, 0x68, 0x17, 0x83, 0xF8, 0x20, 0xC9, +0xF3, 0xCD, 0xF0, 0xF7, 0x79, 0xCD, 0x0D, 0xF8, +0x0E, 0x80, 0xEB, 0x46, 0xE5, 0xCD, 0x16, 0xF8, +0xE1, 0x23, 0x13, 0x0D, 0xC2, 0x8E, 0xF8, 0xAF, +0xCD, 0x0D, 0xF8, 0x3A, 0x00, 0x00, 0xEB, 0xC9, +0xCD, 0xE7, 0x02, 0x91, 0x17, 0x83, 0xF8, 0x20, +0xC9, 0xF3, 0x06, 0x80, 0xCD, 0xF0, 0xF7, 0x79, +0xCD, 0x0D, 0xF8, 0x3A, 0x00, 0x00, 0x7E, 0x12, +0x23, 0x13, 0x05, 0xC2, 0x90, 0xF8, 0xCD, 0xF0, +0xF7, 0xAF, 0xCD, 0x0D, 0xF8, 0x3A, 0x00, 0x00, +0xC9, 0xCD, 0xE7, 0x02, 0xBA, 0x17, 0x83, 0xF8, +0x19, 0xC9, 0xF3, 0xF5, 0xE5, 0xCD, 0xF0, 0xF7, +0x79, 0xCD, 0x0D, 0xF8, 0xD1, 0xF1, 0x47, 0xCD, +0x16, 0xF8, 0xAF, 0xCD, 0x0D, 0xF8, 0x3A, 0x00, +0x00, 0xFB, 0xC9, 0xCD, 0xE7, 0x02, 0xDC, 0x17, +0x83, 0xF8, 0x18, 0xC9, 0xF3, 0xCD, 0xF0, 0xF7, +0x79, 0xCD, 0x0D, 0xF8, 0x3A, 0x04, 0x00, 0x7E, +0xF5, 0x7E, 0xAF, 0xCD, 0x0D, 0xF8, 0x3A, 0x00, +0x00, 0xF1, 0xFB, 0xC9, 0xCD, 0xE7, 0x02, 0xFD, +0x17, 0x83, 0xF8, 0x2E, 0xC9, 0xF3, 0xCD, 0xF0, +0xF7, 0x79, 0xCD, 0x0D, 0xF8, 0x11, 0x00, 0x20, +0x21, 0x00, 0xA0, 0x46, 0xE5, 0xCD, 0x16, 0xF8, +0xE1, 0x13, 0x23, 0x7C, 0xE6, 0x03, 0xB5, 0xC2, +0xA3, 0xF8, 0xCD, 0x38, 0xF8, 0x7D, 0xB4, 0xC2, +0x91, 0xF8, 0xAF, 0xCD, 0x0D, 0xF8, 0x3A, 0x00, +0x00, 0xFB, 0xC9, 0xCD, 0xE7, 0x02, 0x34, 0x18, +0x83, 0xF8, 0x86, 0xC9, 0xF3, 0xCD, 0xF0, 0xF7, +0x79, 0xCD, 0x0D, 0xF8, 0x3A, 0x00, 0x00, 0x38, +0x00, 0x42, 0x4B, 0x2A, 0xCB, 0xF7, 0xE5, 0x08, +0x44, 0x4D, 0x22, 0xC7, 0xF7, 0xE1, 0x11, 0x2E, +0xFA, 0x0C, 0x2B, 0x0D, 0xCA, 0xAD, 0xF8, 0x7E, +0x12, 0x2B, 0x1B, 0xC3, 0xA2, 0xF8, 0x2E, 0x00, +0x1E, 0x00, 0x3A, 0xEF, 0xF4, 0xE6, 0xE0, 0x67, +0xE6, 0x60, 0x57, 0x01, 0xB0, 0xF7, 0x1A, 0x77, +0x13, 0x23, 0x7C, 0xE6, 0x03, 0xB5, 0xC2, 0xCB, +0xF8, 0xCD, 0x38, 0xF8, 0x7D, 0xB4, 0xCA, 0xE3, +0xF8, 0x7C, 0xB8, 0xC2, 0xBD, 0xF8, 0x7D, 0xB9, +0xC2, 0xBD, 0xF8, 0x21, 0xB0, 0xFC, 0x11, 0xB0, +0x7C, 0xC3, 0xBD, 0xF8, 0x2A, 0xC7, 0xF7, 0x44, +0x4D, 0x2A, 0xCB, 0x77, 0x11, 0x2E, 0xFA, 0x0C, +0x2B, 0x0D, 0xCA, 0xFB, 0xF8, 0x1A, 0x77, 0x2B, +0x1B, 0xC3, 0xF0, 0xF8, 0x23, 0xF9, 0xCD, 0xF0, +0xF7, 0xAF, 0xCD, 0x0D, 0xF8, 0x3A, 0x00, 0x00, +0xFB, 0xC9, 0xCD, 0xE7, 0x02, 0xC3, 0x18, 0x83, +0xF8, 0x3A, 0xC9, 0xF3, 0xCD, 0xF0, 0xF7, 0x3A, +0xBC, 0xF7, 0xCD, 0x0D, 0xF8, 0x3A, 0x00, 0x00, +0x21, 0x40, 0x00, 0x11, 0xD3, 0xF4, 0x06, 0x08, +0x7E, 0x12, 0x23, 0x13, 0x05, 0xC2, 0x98, 0xF8, +0xCD, 0xE7, 0xF7, 0x21, 0xC8, 0xEE, 0x11, 0x72, +0x03, 0x06, 0x2A, 0xCD, 0xBA, 0x41, 0xCD, 0xDC, +0xF7, 0xCD, 0xF0, 0xF7, 0xAF, 0xCD, 0x0D, 0xF8, +0x3A, 0x00, 0x00, 0xFB, 0xC9, 0xCD, 0xE7, 0x02, +0x06, 0x19, 0x83, 0xF8, 0x1A, 0xC9, 0xE5, 0xD5, +0xF5, 0x2A, 0xAC, 0xFE, 0x11, 0xE1, 0x0D, 0x19, +0x7C, 0xE6, 0x1F, 0x67, 0x22, 0x3C, 0xF8, 0x3E, +0x01, 0x32, 0x56, 0xF8, 0xF1, 0xD1, 0xE1, 0xC9, +0xCD, 0xE7, 0x02, 0x29, 0x19, 0x83, 0xF8, 0x1F, +0xC9, 0xF3, 0xCD, 0xE7, 0xF7, 0x11, 0x04, 0x00, +0x1A, 0xFE, 0x65, 0xC2, 0x9B, 0xF8, 0x13, 0x1A, +0xFE, 0x6E, 0xC2, 0x9B, 0xF8, 0x13, 0x1A, 0xFE, +0x75, 0xF5, 0xCD, 0xDC, 0xF7, 0xF1, 0xFB, 0xC9, +0xCD, 0xE7, 0x02, 0x51, 0x19, 0x83, 0xF8, 0x1E, +0xC9, 0xF3, 0xE6, 0x01, 0x07, 0x07, 0xF5, 0xCD, +0xF0, 0xF7, 0x21, 0x03, 0x00, 0x7E, 0x66, 0xE6, +0x3F, 0x67, 0xF1, 0xB4, 0x21, 0x01, 0x00, 0x6E, +0x6F, 0x7E, 0x3A, 0x00, 0x00, 0xFB, 0xC9, 0xCD, +0xE7, 0x02, 0x78, 0x19, 0x83, 0xF8, 0x1E, 0xC9, +0xF3, 0x11, 0x00, 0x00, 0xCD, 0xF0, 0xF7, 0xCD, +0x0D, 0xF8, 0x1A, 0x2B, 0x23, 0x03, 0x7E, 0xFE, +0x1A, 0xC2, 0x8F, 0xF8, 0xCD, 0xF0, 0xF7, 0xAF, +0xCD, 0x0D, 0xF8, 0x1A, 0xFB, 0xC9, 0xCD, 0xE7, +0x02, 0x9F, 0x19, 0x83, 0xF8, 0x20, 0xC9, 0xF3, +0xCD, 0xF0, 0xF7, 0xCD, 0x0D, 0xF8, 0x3A, 0x00, +0x00, 0x7E, 0x12, 0x23, 0x13, 0x0B, 0x78, 0xB1, +0xC2, 0x8D, 0xF8, 0xCD, 0xF0, 0xF7, 0xAF, 0xCD, +0x0D, 0xF8, 0x3A, 0x00, 0x00, 0xFB, 0xC9, 0x22, +0xC3, 0xF7, 0x21, 0x70, 0xEF, 0x22, 0xC5, 0xF7, +0x06, 0x08, 0xCD, 0x11, 0x03, 0x06, 0x06, 0xC5, +0x2A, 0xC3, 0xF7, 0xF7, 0x9B, 0x4F, 0xF7, 0xF7, +0x12, 0xF7, 0x14, 0x10, 0xFE, 0x1B, 0xCA, 0x55, +0x1A, 0xFE, 0x0D, 0xCA, 0x58, 0x1A, 0xFE, 0x08, +0xCA, 0x19, 0x1A, 0xC1, 0xC5, 0x4F, 0x78, 0xB7, +0xCA, 0xD0, 0x19, 0x79, 0xFE, 0x20, 0xFA, 0xD0, +0x19, 0xFE, 0x7F, 0xF2, 0xD0, 0x19, 0x2A, 0xC5, +0xF7, 0x77, 0xCD, 0x47, 0x1A, 0x2A, 0xC3, 0xF7, +0x24, 0x22, 0xC3, 0xF7, 0x2A, 0xC5, 0xF7, 0x23, +0x22, 0xC5, 0xF7, 0xC1, 0x05, 0xC5, 0xC3, 0xD0, +0x19, 0xC1, 0xC5, 0x78, 0xFE, 0x06, 0xCA, 0xD0, +0x19, 0xC1, 0x04, 0xC5, 0x3E, 0x20, 0x2A, 0xC5, +0xF7, 0x77, 0xCD, 0x47, 0x1A, 0x2A, 0xC3, 0xF7, +0x25, 0x22, 0xC3, 0xF7, 0x2A, 0xC5, 0xF7, 0x2B, +0x22, 0xC5, 0xF7, 0x3E, 0x20, 0x2A, 0xC5, 0xF7, +0x77, 0xCD, 0x47, 0x1A, 0xC3, 0xD0, 0x19, 0x2A, +0xC3, 0xF7, 0xF7, 0x9B, 0x4F, 0x2A, 0xC5, 0xF7, +0x7E, 0xF7, 0x30, 0x50, 0xC9, 0xC1, 0xAF, 0xC9, +0xC1, 0x78, 0xFE, 0x06, 0xCA, 0xBF, 0x19, 0xF6, +0xFF, 0xC9, 0xF5, 0xCD, 0xEB, 0x15, 0xF1, 0x47, +0xC5, 0xCD, 0x83, 0xF8, 0xC1, 0x78, 0xC8, 0x32, +0xBE, 0xF7, 0x3A, 0xC9, 0xF7, 0x32, 0xCA, 0xF7, +0xCD, 0x9A, 0x1B, 0xCC, 0x17, 0x1C, 0x3E, 0xFF, +0xCD, 0xE3, 0x1B, 0xE5, 0x3A, 0xBE, 0xF7, 0xCD, +0xB9, 0x1B, 0x11, 0x3F, 0x1B, 0xE1, 0xE5, 0xCD, +0xA7, 0x1B, 0xE1, 0xE5, 0xCD, 0xBE, 0x1B, 0xCD, +0x1A, 0x1D, 0xE1, 0xE5, 0xCD, 0x01, 0x1E, 0xCD, +0x34, 0x1D, 0xE1, 0xCD, 0x09, 0x1E, 0x21, 0x1A, +0x1B, 0xC3, 0xD0, 0x1A, 0xCD, 0x77, 0x16, 0xCD, +0x83, 0xF8, 0x78, 0xA7, 0xF8, 0x21, 0xDE, 0x1A, +0xC3, 0xD0, 0x1A, 0x3A, 0xB0, 0xF7, 0xE6, 0x02, +0xC8, 0x21, 0xF7, 0x1A, 0xC3, 0xD0, 0x1A, 0x3A, +0xBA, 0xF7, 0xFE, 0x10, 0xF8, 0x21, 0x04, 0x1B, +0xCD, 0x64, 0x02, 0xCD, 0x8A, 0x1B, 0x2A, 0xCB, +0xF7, 0xF9, 0x2A, 0xB2, 0xF7, 0xE9, 0x45, 0x72, +0x72, 0x6F, 0x72, 0x20, 0x2D, 0x20, 0x66, 0x6C, +0x61, 0x73, 0x68, 0x20, 0x6E, 0x6F, 0x74, 0x20, +0x72, 0x65, 0x61, 0x64, 0x79, 0x21, 0x00, 0x52, +0x45, 0x58, 0x20, 0x69, 0x73, 0x20, 0x66, 0x75, +0x6C, 0x6C, 0x21, 0x00, 0x54, 0x6F, 0x6F, 0x20, +0x6D, 0x61, 0x6E, 0x79, 0x20, 0x6F, 0x66, 0x20, +0x6F, 0x6E, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, +0x21, 0x00, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x20, +0x75, 0x6E, 0x6D, 0x61, 0x72, 0x6B, 0x65, 0x64, +0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x2E, 0x2E, +0x2E, 0x72, 0x65, 0x63, 0x6F, 0x76, 0x65, 0x72, +0x69, 0x6E, 0x67, 0x2E, 0x2E, 0x2E, 0x00, 0x52, +0x45, 0x43, 0x4F, 0x56, 0x52, 0x20, 0x4F, 0x4B, +0x21, 0x0D, 0x0A, 0x00, 0x52, 0x45, 0x58, 0x00, +0x52, 0x45, 0x58, 0x32, 0x00, 0xCD, 0x64, 0x02, +0xF7, 0x45, 0x4F, 0xCD, 0x8A, 0x1B, 0x2A, 0xCB, +0xF7, 0xF9, 0x2A, 0xB2, 0xF7, 0xE9, 0x11, 0x83, +0xF8, 0x06, 0x60, 0xAF, 0x12, 0x13, 0x05, 0xC2, +0x6C, 0x1B, 0xC9, 0x26, 0x00, 0x2E, 0x00, 0xE5, +0xF5, 0xCD, 0x95, 0x16, 0xF1, 0xE1, 0xC3, 0x83, +0xF8, 0xF7, 0x03, 0x8B, 0xCA, 0x81, 0x1B, 0xFE, +0x1B, 0xC9, 0x06, 0x02, 0x21, 0xFF, 0xFF, 0x2B, +0x7C, 0xB5, 0xC2, 0x8F, 0x1B, 0x05, 0xC2, 0x8C, +0x1B, 0xC9, 0x3A, 0xF0, 0x4F, 0xFE, 0xFF, 0xCA, +0xA4, 0x1B, 0xAF, 0xC9, 0xF6, 0x01, 0xC9, 0x23, +0x06, 0x06, 0x1A, 0xD5, 0xC5, 0xCD, 0xBD, 0x1C, +0xC1, 0xD1, 0x23, 0x13, 0x05, 0xC2, 0xAA, 0x1B, +0xC9, 0xF6, 0xC0, 0xC3, 0xBD, 0x1C, 0x11, 0x07, +0x00, 0x19, 0x3A, 0xCA, 0xF7, 0xC3, 0xBD, 0x1C, +0x11, 0x07, 0x00, 0x19, 0x7E, 0x32, 0xCA, 0xF7, +0xC9, 0x7E, 0xE6, 0x7F, 0xC3, 0xBD, 0x1C, 0xAF, +0xC3, 0xBD, 0x1C, 0xF6, 0xC0, 0xF5, 0x06, 0xFF, +0xC3, 0xE8, 0x1B, 0xF6, 0x40, 0xF5, 0x06, 0x7F, +0x21, 0x00, 0x44, 0x11, 0x00, 0x50, 0xF7, 0x18, +0x00, 0xCA, 0x09, 0x1C, 0x3E, 0xFF, 0xBE, 0xCA, +0x09, 0x1C, 0x7E, 0xA0, 0x4F, 0xF1, 0xF5, 0xB9, +0xCA, 0x0D, 0x1C, 0xCD, 0x10, 0x1C, 0xC3, 0xEE, +0x1B, 0xF1, 0xF6, 0x01, 0xC9, 0xF1, 0xAF, 0xC9, +0xD5, 0x11, 0x10, 0x00, 0x19, 0xD1, 0xC9, 0x21, +0x4E, 0x0C, 0xCD, 0x64, 0x02, 0x21, 0x00, 0x40, +0xE5, 0xAF, 0xCD, 0x75, 0x1B, 0xCD, 0xB1, 0x17, +0x0E, 0x00, 0xE1, 0xE5, 0x3A, 0xBC, 0xF7, 0xCD, +0x83, 0xF8, 0x0E, 0x00, 0xE1, 0x23, 0x3A, 0xBD, +0xF7, 0xCD, 0x83, 0xF8, 0x21, 0x00, 0x44, 0x22, +0xBF, 0xF7, 0x22, 0xC1, 0xF7, 0x2A, 0xC1, 0xF7, +0x11, 0x00, 0x50, 0xF7, 0x18, 0x00, 0xCA, 0x72, +0x1C, 0xCD, 0xD3, 0x17, 0x0E, 0x01, 0x2A, 0xC1, +0xF7, 0xCD, 0x83, 0xF8, 0xFE, 0xFF, 0xCA, 0x72, +0x1C, 0xE6, 0x40, 0xC4, 0x83, 0x1C, 0x2A, 0xC1, +0xF7, 0xCD, 0x10, 0x1C, 0x22, 0xC1, 0xF7, 0xC3, +0x45, 0x1C, 0x3E, 0x01, 0xCD, 0x73, 0x1B, 0xCD, +0xDA, 0x16, 0x01, 0x01, 0x00, 0x11, 0x00, 0x80, +0xC3, 0x83, 0xF8, 0x01, 0x10, 0x00, 0x2A, 0xC1, +0xF7, 0xEB, 0x2A, 0xBF, 0xF7, 0xC5, 0xE5, 0xD5, +0xCD, 0xD3, 0x17, 0x0E, 0x01, 0xE1, 0xE5, 0xCD, +0x83, 0xF8, 0xD1, 0xE1, 0xD5, 0xE5, 0xF5, 0xCD, +0xB1, 0x17, 0x0E, 0x00, 0xF1, 0xE1, 0xE5, 0xCD, +0x83, 0xF8, 0xE1, 0xD1, 0x23, 0x13, 0xC1, 0x0D, +0xC2, 0x8D, 0x1C, 0x2A, 0xBF, 0xF7, 0xCD, 0x10, +0x1C, 0x22, 0xBF, 0xF7, 0xC9, 0xE5, 0xF5, 0xCD, +0xB1, 0x17, 0xF1, 0xE1, 0x0E, 0x00, 0xCD, 0xCB, +0x1C, 0x0E, 0x01, 0xE5, 0xF5, 0xCD, 0x83, 0xF8, +0xF1, 0xE1, 0xC9, 0xCD, 0xF8, 0x1C, 0xCD, 0x1A, +0x1D, 0xCD, 0x01, 0x1E, 0xCD, 0x34, 0x1D, 0xCD, +0x09, 0x1E, 0xC9, 0xCD, 0xF8, 0x1C, 0x1B, 0xEB, +0xCD, 0xEA, 0x1D, 0xEB, 0xCD, 0x01, 0x1E, 0xEB, +0xCD, 0xF1, 0x1D, 0xEB, 0xCD, 0x09, 0x1E, 0xC9, +0xE5, 0xCD, 0x9A, 0x1B, 0xCC, 0x17, 0x1C, 0x3E, +0xFF, 0xCD, 0xE3, 0x1B, 0xE5, 0x3A, 0xBB, 0xF7, +0xCD, 0xB9, 0x1B, 0xE1, 0xE5, 0xCD, 0xBE, 0x1B, +0xE1, 0xD1, 0xD5, 0xE5, 0xCD, 0xA7, 0x1B, 0xE1, +0xD1, 0xC9, 0xE5, 0x21, 0x83, 0xF8, 0xE5, 0xF7, +0x7E, 0x1A, 0xD1, 0xCD, 0x68, 0x1D, 0x32, 0xC5, +0xF7, 0x13, 0x13, 0x13, 0xCD, 0x68, 0x1D, 0x32, +0xC6, 0xF7, 0xE1, 0xC9, 0xE5, 0x21, 0x83, 0xF8, +0xE5, 0xF7, 0x9E, 0x1A, 0xD1, 0xCD, 0x68, 0x1D, +0xE6, 0x0F, 0x0F, 0x0F, 0x0F, 0x47, 0xE6, 0xE0, +0x4F, 0x78, 0xE6, 0x01, 0x47, 0x13, 0x13, 0x13, +0xCD, 0x68, 0x1D, 0xE6, 0x1F, 0xB1, 0x32, 0xC6, +0xF7, 0x13, 0x13, 0x13, 0xCD, 0x68, 0x1D, 0xE6, +0x7F, 0x07, 0xB0, 0x32, 0xC5, 0xF7, 0xE1, 0xC9, +0xED, 0x7C, 0xD6, 0x30, 0x67, 0x7D, 0xD6, 0x30, +0x6F, 0xB7, 0xCA, 0x7C, 0x1D, 0xAF, 0xC6, 0x0A, +0x2D, 0xC2, 0x76, 0x1D, 0x84, 0xC9, 0x21, 0x0B, +0x24, 0xF7, 0x9B, 0x4F, 0x3A, 0xC5, 0xF7, 0xCD, +0xCB, 0x1D, 0x3E, 0x3A, 0xCD, 0xE6, 0x1D, 0x3A, +0xC6, 0xF7, 0xCD, 0xCB, 0x1D, 0xC9, 0x21, 0x0B, +0x1B, 0xF7, 0x9B, 0x4F, 0x3A, 0xC5, 0xF7, 0xF5, +0xE6, 0xFE, 0x0F, 0xCD, 0xCB, 0x1D, 0x3E, 0x2F, +0xCD, 0xE6, 0x1D, 0xF1, 0xE6, 0x01, 0x07, 0x07, +0x07, 0x47, 0x3A, 0xC6, 0xF7, 0xF5, 0xE6, 0xE0, +0x07, 0x07, 0x07, 0xB0, 0xCD, 0xCB, 0x1D, 0x3E, +0x2F, 0xCD, 0xE6, 0x1D, 0xF1, 0xE6, 0x1F, 0xCD, +0xCB, 0x1D, 0xC9, 0xE6, 0x3F, 0xF5, 0xFE, 0x0A, +0xF2, 0xDC, 0x1D, 0x3E, 0x30, 0xF7, 0x30, 0x50, +0xF1, 0xC3, 0xE4, 0x1D, 0xF1, 0x26, 0x00, 0x6F, +0xF7, 0x0B, 0x47, 0xC9, 0xC6, 0x30, 0xF7, 0x30, +0x50, 0xC9, 0xE5, 0x01, 0x0A, 0x00, 0xC3, 0xF5, +0x1D, 0xE5, 0x01, 0x08, 0x00, 0x09, 0x7E, 0x32, +0xC5, 0xF7, 0x23, 0x7E, 0x32, 0xC6, 0xF7, 0xE1, +0xC9, 0xE5, 0xD5, 0x01, 0x0A, 0x00, 0xC3, 0x0E, +0x1E, 0xE5, 0xD5, 0x01, 0x08, 0x00, 0x09, 0x3A, +0xC5, 0xF7, 0xCD, 0xBD, 0x1C, 0x23, 0x3A, 0xC6, +0xF7, 0xCD, 0xBD, 0x1C, 0xD1, 0xE1, 0xC9, 0xE5, +0xCD, 0x1C, 0x1F, 0x2A, 0xBF, 0xF7, 0x7C, 0xB5, +0xE1, 0xCA, 0x36, 0x1E, 0x21, 0x63, 0x1E, 0xCD, +0x77, 0x02, 0x3E, 0x01, 0xB7, 0xC9, 0xE5, 0x2A, +0xC1, 0xF7, 0x7C, 0xB5, 0xE1, 0xC2, 0x78, 0x1E, +0x21, 0x4A, 0x1E, 0xCD, 0x77, 0x02, 0x3E, 0x01, +0xB7, 0xC9, 0x4E, 0x4F, 0x20, 0x46, 0x52, 0x45, +0x45, 0x20, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, +0x4F, 0x52, 0x59, 0x20, 0x45, 0x4E, 0x54, 0x52, +0x59, 0x21, 0x00, 0x44, 0x55, 0x50, 0x4C, 0x49, +0x43, 0x41, 0x54, 0x45, 0x20, 0x46, 0x49, 0x4C, +0x45, 0x20, 0x4E, 0x41, 0x4D, 0x45, 0x21, 0x00, +0xE5, 0x21, 0x5D, 0xF2, 0x01, 0x0B, 0x00, 0x09, +0x7E, 0xFE, 0xFF, 0xCA, 0xA1, 0x1E, 0xE5, 0x23, +0x3A, 0xEE, 0xF4, 0x3C, 0xBE, 0xE1, 0xC2, 0x7C, +0x1E, 0xE5, 0x23, 0x23, 0x3A, 0xEF, 0xF4, 0xBE, +0xE1, 0xC2, 0x7C, 0x1E, 0x23, 0x7E, 0x3C, 0x3C, +0x77, 0xE1, 0xEB, 0x2A, 0xC1, 0xF7, 0x0E, 0x0B, +0xCD, 0xF5, 0x02, 0xED, 0x44, 0x4D, 0xC5, 0x2A, +0x61, 0xF6, 0x09, 0x22, 0x61, 0xF6, 0x13, 0x13, +0xD5, 0x2A, 0xEE, 0xF4, 0x23, 0xE5, 0xF7, 0xA8, +0x82, 0xDA, 0xD9, 0x1E, 0xE1, 0xD1, 0xC1, 0xCD, +0xF5, 0x02, 0x2A, 0xC1, 0xF7, 0x23, 0xEB, 0x2A, +0xEE, 0xF4, 0x23, 0xD9, 0xF7, 0x62, 0x2C, 0xAF, +0xC9, 0x21, 0xF1, 0x1E, 0xCD, 0x81, 0x02, 0xF7, +0xDA, 0x82, 0xE1, 0xE1, 0xE1, 0x2A, 0xC1, 0xF7, +0xAF, 0x77, 0xF7, 0x62, 0x2C, 0x3E, 0x01, 0xB7, +0xC9, 0x4E, 0x4F, 0x54, 0x20, 0x45, 0x4E, 0x4F, +0x55, 0x47, 0x48, 0x20, 0x46, 0x52, 0x45, 0x45, +0x20, 0x4D, 0x45, 0x4D, 0x4F, 0x52, 0x59, 0x21, +0x00, 0xCD, 0x1C, 0x1F, 0x2A, 0xBF, 0xF7, 0x7C, +0xB5, 0xC8, 0xE5, 0xF7, 0x8C, 0x6E, 0xEB, 0xE1, +0xF7, 0x0C, 0x2B, 0xC9, 0x22, 0xC3, 0xF7, 0x21, +0x00, 0x00, 0x22, 0xC1, 0xF7, 0x22, 0xBF, 0xF7, +0x21, 0xAA, 0xF2, 0x01, 0x0B, 0x00, 0x09, 0x7E, +0x3C, 0xC8, 0xE5, 0x3D, 0xEB, 0x2A, 0xC3, 0xF7, +0xBE, 0xEB, 0xCC, 0x51, 0x1F, 0xB7, 0xCC, 0x45, +0x1F, 0xE1, 0xC3, 0x2B, 0x1F, 0xEB, 0x2A, 0xC1, +0xF7, 0x7C, 0xB5, 0xEB, 0xC0, 0x22, 0xC1, 0xF7, +0xC9, 0xEB, 0x2A, 0xBF, 0xF7, 0x7C, 0xB5, 0xEB, +0xC0, 0xE5, 0x23, 0x23, 0x23, 0xEB, 0x2A, 0xC3, +0xF7, 0x23, 0x23, 0x23, 0x06, 0x08, 0x1A, 0xBE, +0xC2, 0x76, 0x1F, 0x23, 0x13, 0x05, 0xC2, 0x66, +0x1F, 0xE1, 0x22, 0xBF, 0xF7, 0xC9, 0xE1, 0xC9, +0x80, 0x00, 0x00, 0x52, 0x45, 0x58, 0x4D, 0x47, +0x52, 0x42, 0x41, 0x7B, 0x00, 0x7A, 0xA0, 0x01, +0x00, 0x41, 0x24, 0xDD, 0x22, 0xF3, 0x3E, 0x30, +0x0F, 0x0F, 0x6F, 0x3E, 0x80, 0x07, 0x07, 0x67, +0xDB, 0xD8, 0xA5, 0xB4, 0xD3, 0xD8, 0xAF, 0x67, +0x6F, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x2E, 0xB8, +0x6E, 0x2E, 0xF2, 0x6E, 0x2E, 0x34, 0x6E, 0x2E, +0xB0, 0x6E, 0x2E, 0x31, 0x6E, 0x2E, 0xBF, 0x6E, +0xAF, 0x67, 0x6F, 0x2C, 0x6E, 0xAF, 0x6F, 0x7E, +0x7E, 0xAF, 0x3C, 0x3C, 0x3C, 0x67, 0x2E, 0x83, +0xE9, 0x22, 0x3A, 0x42, 0xDD, 0xC3, 0x28, 0x41, +0x24, 0x29, 0x3A, 0x43, 0xDD, 0xEE, 0x28, 0x42, +0xD0, 0x31, 0x29, 0xD0, 0x32, 0x35, 0x36, 0xD2, +0x28, 0xEE, 0x28, 0x42, 0xD0, 0x32, 0x29, 0x29, +0x3A, 0xB9, 0x43, 0x3A, 0x8E, 0x56, 0x45, 0x52, +0x53, 0x49, 0x4F, 0x4E, 0x20, 0x34, 0x2E, 0x38, +0x20, 0x54, 0x32, 0x30, 0x30, 0x00, 0x00, 0x00, +0x88, 0x00, 0x00, 0x52, 0x58, 0x48, 0x4F, 0x4F, +0x4B, 0x00, 0x00, 0x2D, 0x00, 0x2C, 0xA0, 0x01, +0x00, 0xF3, 0xF5, 0xE5, 0xAF, 0x67, 0x2E, 0x03, +0x7E, 0xFE, 0x4D, 0xC2, 0x23, 0xA0, 0xDB, 0xD8, +0xE6, 0x0C, 0xF6, 0x02, 0xD3, 0xD8, 0x23, 0x7E, +0xFE, 0x52, 0xCA, 0x9F, 0x03, 0xDB, 0xD8, 0xE6, +0x0C, 0xD3, 0xD8, 0xE1, 0xF1, 0xFB, 0xC9, 0x00, +0x00, 0x00, 0x21, 0x4D, 0x20, 0xE5, 0xCD, 0x09, +0x1F, 0xE1, 0x11, 0x0B, 0x00, 0x19, 0x7E, 0xFE, +0xFF, 0xC2, 0x3D, 0x20, 0xC9, 0x80, 0x00, 0x00, +0x54, 0x53, 0x2D, 0x44, 0x4F, 0x53, 0x20, 0x20, +0x80, 0x00, 0x00, 0x55, 0x52, 0x2D, 0x32, 0x20, +0x20, 0x20, 0x20, 0x80, 0x00, 0x00, 0x54, 0x57, +0x4F, 0x52, 0x44, 0x2B, 0x20, 0x20, 0x80, 0x00, +0x00, 0x52, 0x41, 0x4E, 0x44, 0x4F, 0x4D, 0x20, +0x20, 0xFF, 0x51, 0x1E, 0x00, 0x2A, 0xEE, 0xF4, +0x01, 0x00, 0xA0, 0xC5, 0x08, 0xF7, 0x18, 0x00, +0xCA, 0xC4, 0x20, 0xF5, 0xD2, 0x90, 0x20, 0xEB, +0x42, 0x4B, 0x08, 0x44, 0x4D, 0xF1, 0xE1, 0xC5, +0xD2, 0xA2, 0x20, 0xF7, 0xA8, 0x82, 0xC1, 0xC3, +0xAC, 0x20, 0xF7, 0xDA, 0x82, 0xC1, 0x21, 0x00, +0x00, 0x08, 0x44, 0x4D, 0x2A, 0x61, 0xF6, 0x09, +0x22, 0x61, 0xF6, 0x2A, 0xEE, 0xF4, 0x09, 0x22, +0xEE, 0xF4, 0x7C, 0xD6, 0xA0, 0x32, 0x00, 0xA0, +0xF7, 0x62, 0x2C, 0xC9, 0xC1, 0xC9, 0x21, 0x32, +0x2F, 0xC3, 0xE3, 0x20, 0x21, 0x74, 0x2E, 0xC3, +0xE3, 0x20, 0x21, 0xC7, 0x27, 0xC3, 0xE3, 0x20, +0x3A, 0xC9, 0xF7, 0xFE, 0x03, 0xCA, 0xD2, 0x20, +0x21, 0x52, 0x21, 0xE5, 0xCD, 0x6A, 0x03, 0x21, +0x05, 0x01, 0xF7, 0x9B, 0x4F, 0xE1, 0xCD, 0x81, +0x02, 0x7E, 0xFE, 0xFE, 0xCA, 0xFF, 0x20, 0xFE, +0xFF, 0xCA, 0x11, 0x21, 0xC3, 0xEE, 0x20, 0x23, +0xE5, 0x21, 0x24, 0x21, 0xCD, 0x64, 0x02, 0xCD, +0x81, 0x1B, 0xE1, 0xCA, 0x1A, 0x21, 0xC3, 0xE3, +0x20, 0x21, 0x3E, 0x21, 0xCD, 0x64, 0x02, 0xCD, +0x81, 0x1B, 0xCD, 0x54, 0x13, 0xCD, 0x70, 0x03, +0x2A, 0xB2, 0xF7, 0xE9, 0x3C, 0x45, 0x53, 0x43, +0x3E, 0x20, 0x65, 0x78, 0x69, 0x74, 0x20, 0x3C, +0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x3E, +0x20, 0x6D, 0x6F, 0x72, 0x65, 0x00, 0x3C, 0x61, +0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x3E, 0x20, +0x74, 0x6F, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, +0x6E, 0x00, 0x4B, 0x65, 0x79, 0x62, 0x6F, 0x61, +0x72, 0x64, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x61, +0x6E, 0x64, 0x73, 0x00, 0x3C, 0x62, 0x3E, 0x20, +0x42, 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6E, 0x75, +0x6D, 0x62, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x66, +0x6F, 0x72, 0x6D, 0x61, 0x74, 0x69, 0x6F, 0x6E, +0x00, 0x3C, 0x65, 0x3E, 0x20, 0x48, 0x69, 0x6E, +0x74, 0x73, 0x20, 0x6F, 0x6E, 0x20, 0x3C, 0x45, +0x4E, 0x54, 0x45, 0x52, 0x3E, 0x20, 0x6B, 0x65, +0x79, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, +0x6F, 0x6E, 0x73, 0x00, 0x3C, 0x69, 0x3E, 0x20, +0x49, 0x6E, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, +0x69, 0x6F, 0x6E, 0x20, 0x6F, 0x6E, 0x20, 0x52, +0x45, 0x58, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, +0x6D, 0x00, 0x3C, 0x63, 0x3E, 0x20, 0x43, 0x68, +0x65, 0x63, 0x6B, 0x73, 0x75, 0x6D, 0x20, 0x6F, +0x66, 0x20, 0x6D, 0x65, 0x6E, 0x75, 0x20, 0x65, +0x6E, 0x74, 0x72, 0x79, 0x20, 0x69, 0x6D, 0x61, +0x67, 0x65, 0x00, 0x3C, 0x73, 0x3E, 0x20, 0x54, +0x6F, 0x67, 0x67, 0x6C, 0x65, 0x20, 0x64, 0x69, +0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x79, 0x20, +0x73, 0x6F, 0x72, 0x74, 0x20, 0x6F, 0x72, 0x64, +0x65, 0x72, 0x00, 0xFE, 0x4B, 0x65, 0x79, 0x62, +0x6F, 0x61, 0x72, 0x64, 0x20, 0x43, 0x6F, 0x6D, +0x6D, 0x61, 0x6E, 0x64, 0x73, 0x00, 0x3C, 0x65, +0x6E, 0x74, 0x3E, 0x20, 0x54, 0x61, 0x6B, 0x65, +0x20, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, +0x66, 0x6F, 0x72, 0x20, 0x73, 0x65, 0x6C, 0x65, +0x63, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x3C, 0x74, +0x61, 0x62, 0x3E, 0x20, 0x53, 0x68, 0x6F, 0x77, +0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, +0x72, 0x79, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x6E, +0x65, 0x78, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, +0x00, 0x3C, 0x65, 0x73, 0x63, 0x3E, 0x20, 0x72, +0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x74, 0x6F, +0x20, 0x6D, 0x65, 0x6E, 0x75, 0x00, 0x00, 0x00, +0xFE, 0x46, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, +0x6E, 0x20, 0x4B, 0x65, 0x79, 0x73, 0x00, 0x3C, +0x46, 0x31, 0x3E, 0x20, 0x44, 0x69, 0x73, 0x70, +0x6C, 0x61, 0x79, 0x20, 0x68, 0x65, 0x6C, 0x70, +0x20, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6E, 0x73, +0x00, 0x3C, 0x46, 0x32, 0x3E, 0x20, 0x4C, 0x6F, +0x61, 0x64, 0x2F, 0x53, 0x61, 0x76, 0x65, 0x20, +0x69, 0x6D, 0x61, 0x67, 0x65, 0x20, 0x66, 0x72, +0x6F, 0x6D, 0x2F, 0x74, 0x6F, 0x20, 0x54, 0x50, +0x44, 0x44, 0x00, 0x3C, 0x46, 0x33, 0x3E, 0x20, +0x43, 0x6F, 0x70, 0x79, 0x20, 0x69, 0x6D, 0x61, +0x67, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x52, 0x45, +0x58, 0x00, 0x3C, 0x46, 0x34, 0x3E, 0x20, 0x44, +0x65, 0x6C, 0x65, 0x74, 0x65, 0x20, 0x69, 0x6D, +0x61, 0x67, 0x65, 0x20, 0x66, 0x72, 0x6F, 0x6D, +0x20, 0x52, 0x45, 0x58, 0x00, 0x3C, 0x46, 0x35, +0x3E, 0x20, 0x52, 0x65, 0x6E, 0x61, 0x6D, 0x65, +0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6D, 0x61, +0x67, 0x65, 0x00, 0xFE, 0x46, 0x75, 0x6E, 0x63, +0x74, 0x69, 0x6F, 0x6E, 0x20, 0x4B, 0x65, 0x79, +0x73, 0x00, 0x3C, 0x46, 0x36, 0x3E, 0x20, 0x46, +0x69, 0x6C, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6E, +0x73, 0x66, 0x65, 0x72, 0x20, 0x66, 0x72, 0x6F, +0x6D, 0x20, 0x73, 0x74, 0x6F, 0x72, 0x65, 0x64, +0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x00, 0x3C, +0x46, 0x37, 0x3E, 0x20, 0x44, 0x65, 0x69, 0x6E, +0x73, 0x74, 0x61, 0x6C, 0x6C, 0x20, 0x52, 0x45, +0x58, 0x20, 0x73, 0x6F, 0x66, 0x74, 0x77, 0x61, +0x72, 0x65, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, +0x6C, 0x61, 0x70, 0x74, 0x6F, 0x70, 0x00, 0x3C, +0x46, 0x38, 0x3E, 0x20, 0x45, 0x78, 0x69, 0x74, +0x20, 0x52, 0x45, 0x58, 0x20, 0x4D, 0x61, 0x6E, +0x61, 0x67, 0x65, 0x72, 0x00, 0x00, 0x00, 0xFE, +0x4D, 0x61, 0x69, 0x6E, 0x20, 0x4D, 0x65, 0x6E, +0x75, 0x20, 0x48, 0x65, 0x6C, 0x70, 0x00, 0x3D, +0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, +0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x00, 0x52, 0x45, +0x58, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6E, 0x20, +0x6F, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, +0x4F, 0x4D, 0x20, 0x73, 0x77, 0x69, 0x74, 0x63, +0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, +0x00, 0x61, 0x6C, 0x73, 0x6F, 0x20, 0x69, 0x6E, +0x63, 0x6C, 0x75, 0x64, 0x65, 0x73, 0x20, 0x52, +0x41, 0x4D, 0x20, 0x62, 0x61, 0x63, 0x6B, 0x75, +0x70, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x73, 0x77, +0x69, 0x74, 0x63, 0x68, 0x69, 0x6E, 0x67, 0x00, +0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, +0x73, 0x2E, 0x20, 0x20, 0x52, 0x45, 0x58, 0x20, +0x6D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x73, 0x20, +0x52, 0x41, 0x4D, 0x20, 0x6F, 0x72, 0x20, 0x52, +0x4F, 0x4D, 0x20, 0x64, 0x61, 0x74, 0x61, 0x00, +0x69, 0x6E, 0x20, 0x33, 0x32, 0x6B, 0x20, 0x62, +0x6C, 0x6F, 0x63, 0x6B, 0x73, 0x2C, 0x20, 0x72, +0x65, 0x66, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, +0x6F, 0x20, 0x61, 0x73, 0x20, 0x69, 0x6D, 0x61, +0x67, 0x65, 0x73, 0x2E, 0x00, 0xFE, 0x4F, 0x70, +0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x4F, 0x4D, +0x73, 0x20, 0x6D, 0x61, 0x79, 0x20, 0x62, 0x65, +0x20, 0x6C, 0x6F, 0x61, 0x64, 0x65, 0x64, 0x20, +0x69, 0x6E, 0x74, 0x6F, 0x20, 0x52, 0x45, 0x58, +0x00, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x73, 0x20, +0x61, 0x6E, 0x64, 0x20, 0x73, 0x65, 0x6C, 0x65, +0x63, 0x74, 0x65, 0x64, 0x20, 0x66, 0x6F, 0x72, +0x20, 0x75, 0x73, 0x65, 0x2C, 0x20, 0x61, 0x6E, +0x64, 0x20, 0x79, 0x6F, 0x75, 0x72, 0x00, 0x73, +0x79, 0x73, 0x74, 0x65, 0x6D, 0x20, 0x52, 0x41, +0x4D, 0x20, 0x6D, 0x61, 0x79, 0x20, 0x62, 0x65, +0x20, 0x63, 0x6F, 0x70, 0x69, 0x65, 0x64, 0x20, +0x74, 0x6F, 0x20, 0x6F, 0x72, 0x20, 0x72, 0x65, +0x73, 0x74, 0x6F, 0x72, 0x65, 0x64, 0x00, 0x66, +0x72, 0x6F, 0x6D, 0x20, 0x52, 0x45, 0x58, 0x20, +0x69, 0x6D, 0x61, 0x67, 0x65, 0x73, 0x2E, 0x00, +0x49, 0x6D, 0x61, 0x67, 0x65, 0x73, 0x20, 0x61, +0x72, 0x65, 0x20, 0x67, 0x72, 0x6F, 0x75, 0x70, +0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x79, +0x70, 0x65, 0x20, 0x52, 0x41, 0x4D, 0x2F, 0x52, +0x4F, 0x4D, 0x2F, 0x4F, 0x53, 0x2E, 0x00, 0x53, +0x59, 0x53, 0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, +0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x65, +0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x20, 0x66, +0x6F, 0x72, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, +0x6D, 0x20, 0x75, 0x73, 0x65, 0x2E, 0x00, 0xFE, +0x49, 0x6D, 0x61, 0x67, 0x65, 0x73, 0x20, 0x6D, +0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x27, 0x4C, +0x6F, 0x61, 0x64, 0x27, 0x65, 0x64, 0x20, 0x6F, +0x72, 0x20, 0x27, 0x53, 0x61, 0x76, 0x65, 0x27, +0x64, 0x00, 0x74, 0x6F, 0x2F, 0x66, 0x72, 0x6F, +0x6D, 0x20, 0x54, 0x50, 0x44, 0x44, 0x2E, 0x20, +0x20, 0x46, 0x69, 0x6C, 0x65, 0x6E, 0x61, 0x6D, +0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6E, 0x73, +0x69, 0x6F, 0x6E, 0x73, 0x20, 0x61, 0x72, 0x65, +0x00, 0x2E, 0x42, 0x58, 0x20, 0x69, 0x73, 0x20, +0x75, 0x73, 0x65, 0x64, 0x20, 0x66, 0x6F, 0x72, +0x20, 0x4F, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x20, +0x52, 0x4F, 0x4D, 0x20, 0x69, 0x6D, 0x61, 0x67, +0x65, 0x73, 0x00, 0x2E, 0x42, 0x59, 0x20, 0x69, +0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x66, +0x6F, 0x72, 0x20, 0x52, 0x41, 0x4D, 0x20, 0x69, +0x6D, 0x61, 0x67, 0x65, 0x73, 0x00, 0x2E, 0x42, +0x5A, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, +0x64, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x4F, 0x53, +0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x73, 0x00, +0x2E, 0x42, 0x52, 0x20, 0x69, 0x73, 0x20, 0x75, +0x73, 0x65, 0x64, 0x20, 0x66, 0x6F, 0x72, 0x20, +0x52, 0x45, 0x58, 0x20, 0x73, 0x79, 0x73, 0x74, +0x65, 0x6D, 0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, +0x73, 0x00, 0xFE, 0x49, 0x6D, 0x61, 0x67, 0x65, +0x73, 0x20, 0x6D, 0x61, 0x79, 0x20, 0x62, 0x65, +0x20, 0x27, 0x4E, 0x61, 0x6D, 0x65, 0x27, 0x64, +0x2C, 0x20, 0x27, 0x43, 0x6F, 0x70, 0x79, 0x27, +0x64, 0x20, 0x6F, 0x72, 0x00, 0x27, 0x4B, 0x69, +0x6C, 0x6C, 0x27, 0x65, 0x64, 0x2E, 0x20, 0x55, +0x70, 0x20, 0x74, 0x6F, 0x20, 0x31, 0x36, 0x20, +0x69, 0x6D, 0x61, 0x67, 0x65, 0x73, 0x20, 0x6F, +0x66, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6F, 0x6E, +0x65, 0x00, 0x74, 0x79, 0x70, 0x65, 0x20, 0x61, +0x72, 0x65, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, +0x65, 0x64, 0x2C, 0x20, 0x77, 0x69, 0x74, 0x68, +0x20, 0x32, 0x34, 0x20, 0x69, 0x6D, 0x61, 0x67, +0x65, 0x73, 0x20, 0x69, 0x6E, 0x00, 0x74, 0x6F, +0x74, 0x61, 0x6C, 0x2E, 0x20, 0x41, 0x6E, 0x20, +0x49, 0x6D, 0x61, 0x67, 0x65, 0x20, 0x69, 0x73, +0x20, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x20, +0x77, 0x68, 0x65, 0x6E, 0x20, 0x69, 0x6E, 0x20, +0x75, 0x73, 0x65, 0x00, 0x62, 0x79, 0x20, 0x52, +0x45, 0x58, 0x2C, 0x20, 0x61, 0x6E, 0x64, 0x20, +0x69, 0x73, 0x20, 0x6D, 0x61, 0x72, 0x6B, 0x65, +0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, +0x20, 0x2A, 0x2E, 0x20, 0x20, 0x54, 0x68, 0x65, +0x72, 0x65, 0x00, 0x6D, 0x75, 0x73, 0x74, 0x20, +0x61, 0x6C, 0x77, 0x61, 0x79, 0x73, 0x20, 0x62, +0x65, 0x20, 0x6F, 0x6E, 0x65, 0x20, 0x61, 0x63, +0x74, 0x69, 0x76, 0x65, 0x20, 0x52, 0x41, 0x4D, +0x20, 0x61, 0x6E, 0x64, 0x20, 0x6F, 0x6E, 0x65, +0x00, 0xFE, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, +0x20, 0x52, 0x4F, 0x4D, 0x20, 0x6F, 0x72, 0x20, +0x4F, 0x53, 0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, +0x2E, 0x00, 0x59, 0x6F, 0x75, 0x20, 0x63, 0x61, +0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x6B, 0x69, 0x6C, +0x6C, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, +0x69, 0x76, 0x65, 0x20, 0x69, 0x6D, 0x61, 0x67, +0x65, 0x2E, 0x00, 0x41, 0x63, 0x74, 0x69, 0x76, +0x65, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, +0x20, 0x69, 0x73, 0x20, 0x63, 0x68, 0x61, 0x6E, +0x67, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, +0x65, 0x6C, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, +0x00, 0x6F, 0x66, 0x20, 0x61, 0x20, 0x6E, 0x65, +0x77, 0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x20, +0x75, 0x73, 0x69, 0x6E, 0x67, 0x20, 0x74, 0x68, +0x65, 0x20, 0x3C, 0x65, 0x6E, 0x74, 0x3E, 0x20, +0x6B, 0x65, 0x79, 0x2E, 0x00, 0x4F, 0x53, 0x20, +0x69, 0x6D, 0x61, 0x67, 0x65, 0x73, 0x20, 0x61, +0x72, 0x65, 0x20, 0x6F, 0x70, 0x74, 0x69, 0x6F, +0x6E, 0x20, 0x52, 0x4F, 0x4D, 0x73, 0x20, 0x74, +0x68, 0x61, 0x74, 0x20, 0x61, 0x63, 0x74, 0x20, +0x61, 0x73, 0x00, 0x69, 0x6E, 0x64, 0x65, 0x70, +0x65, 0x6E, 0x64, 0x61, 0x6E, 0x74, 0x20, 0x6F, +0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6E, 0x67, +0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, +0x2E, 0x00, 0xFE, 0x43, 0x6F, 0x6E, 0x73, 0x75, +0x6C, 0x74, 0x20, 0x42, 0x69, 0x74, 0x63, 0x68, +0x69, 0x6E, 0x31, 0x30, 0x30, 0x20, 0x52, 0x45, +0x58, 0x20, 0x57, 0x69, 0x6B, 0x69, 0x20, 0x66, +0x6F, 0x72, 0x20, 0x66, 0x75, 0x72, 0x74, 0x68, +0x65, 0x72, 0x00, 0x69, 0x6E, 0x66, 0x6F, 0x72, +0x6D, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x00, +0x00, 0x45, 0x6E, 0x6A, 0x6F, 0x79, 0x20, 0x79, +0x6F, 0x75, 0x72, 0x20, 0x52, 0x45, 0x58, 0x21, +0x00, 0x00, 0x53, 0x74, 0x65, 0x70, 0x68, 0x65, +0x6E, 0x20, 0x41, 0x64, 0x6F, 0x6C, 0x70, 0x68, +0x20, 0x32, 0x30, 0x31, 0x31, 0x00, 0xFF, 0x4B, +0x65, 0x79, 0x62, 0x6F, 0x61, 0x72, 0x64, 0x20, +0x43, 0x6F, 0x6D, 0x6D, 0x61, 0x6E, 0x64, 0x73, +0x00, 0x3C, 0x62, 0x3E, 0x20, 0x42, 0x6C, 0x6F, +0x63, 0x6B, 0x20, 0x6E, 0x75, 0x6D, 0x62, 0x65, +0x72, 0x20, 0x69, 0x6E, 0x66, 0x6F, 0x72, 0x6D, +0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x3C, 0x69, +0x3E, 0x20, 0x49, 0x6E, 0x66, 0x6F, 0x72, 0x6D, +0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x6F, 0x6E, +0x20, 0x52, 0x45, 0x58, 0x20, 0x73, 0x79, 0x73, +0x74, 0x65, 0x6D, 0x00, 0x3C, 0x63, 0x3E, 0x20, +0x43, 0x68, 0x65, 0x63, 0x6B, 0x73, 0x75, 0x6D, +0x20, 0x6F, 0x66, 0x20, 0x6D, 0x65, 0x6E, 0x75, +0x20, 0x65, 0x6E, 0x74, 0x72, 0x79, 0x20, 0x69, +0x6D, 0x61, 0x67, 0x65, 0x00, 0x3C, 0x74, 0x61, +0x62, 0x3E, 0x20, 0x53, 0x68, 0x6F, 0x77, 0x20, +0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, +0x79, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x6E, 0x65, +0x78, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x00, +0x3C, 0x65, 0x73, 0x63, 0x3E, 0x20, 0x72, 0x65, +0x74, 0x75, 0x72, 0x6E, 0x20, 0x74, 0x6F, 0x20, +0x6D, 0x65, 0x6E, 0x75, 0x00, 0xFE, 0x46, 0x75, +0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x4B, +0x65, 0x79, 0x73, 0x00, 0x3C, 0x46, 0x31, 0x3E, +0x20, 0x44, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, +0x20, 0x68, 0x65, 0x6C, 0x70, 0x20, 0x73, 0x63, +0x72, 0x65, 0x65, 0x6E, 0x73, 0x00, 0x3C, 0x46, +0x32, 0x3E, 0x20, 0x4C, 0x6F, 0x61, 0x64, 0x20, +0x69, 0x6D, 0x61, 0x67, 0x65, 0x20, 0x66, 0x72, +0x6F, 0x6D, 0x20, 0x54, 0x50, 0x44, 0x44, 0x00, +0x3C, 0x46, 0x33, 0x3E, 0x20, 0x53, 0x65, 0x6C, +0x65, 0x63, 0x74, 0x20, 0x52, 0x4F, 0x4D, 0x20, +0x69, 0x6D, 0x61, 0x67, 0x65, 0x20, 0x66, 0x6F, +0x72, 0x20, 0x75, 0x73, 0x65, 0x00, 0x3C, 0x46, +0x37, 0x3E, 0x20, 0x44, 0x65, 0x69, 0x6E, 0x73, +0x74, 0x61, 0x6C, 0x6C, 0x20, 0x52, 0x45, 0x58, +0x20, 0x73, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72, +0x65, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x6C, +0x61, 0x70, 0x74, 0x6F, 0x70, 0x00, 0x3C, 0x46, +0x38, 0x3E, 0x20, 0x45, 0x78, 0x69, 0x74, 0x20, +0x52, 0x45, 0x58, 0x20, 0x4D, 0x61, 0x6E, 0x61, +0x67, 0x65, 0x72, 0x00, 0xFE, 0x53, 0x59, 0x53, +0x20, 0x4D, 0x65, 0x6E, 0x75, 0x20, 0x48, 0x65, +0x6C, 0x70, 0x00, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, +0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, +0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x6D, 0x65, +0x6E, 0x75, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, +0x65, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, +0x6E, 0x61, 0x67, 0x65, 0x20, 0x73, 0x79, 0x73, +0x74, 0x65, 0x6D, 0x00, 0x72, 0x65, 0x6C, 0x61, +0x74, 0x65, 0x64, 0x20, 0x74, 0x61, 0x73, 0x6B, +0x73, 0x2C, 0x20, 0x70, 0x72, 0x69, 0x6D, 0x61, +0x72, 0x69, 0x6C, 0x79, 0x20, 0x6D, 0x61, 0x6E, +0x61, 0x67, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, +0x6F, 0x66, 0x00, 0x74, 0x68, 0x65, 0x20, 0x6C, +0x6F, 0x61, 0x64, 0x65, 0x64, 0x20, 0x6D, 0x61, +0x69, 0x6E, 0x20, 0x52, 0x4F, 0x4D, 0x20, 0x69, +0x6D, 0x61, 0x67, 0x65, 0x73, 0x20, 0x75, 0x73, +0x65, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6E, 0x00, +0x52, 0x45, 0x58, 0x20, 0x69, 0x73, 0x20, 0x72, +0x65, 0x70, 0x6C, 0x61, 0x63, 0x69, 0x6E, 0x67, +0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6E, 0x74, +0x65, 0x72, 0x6E, 0x61, 0x6C, 0x20, 0x52, 0x4F, +0x4D, 0x73, 0x2E, 0x00, 0xFE, 0x53, 0x65, 0x65, +0x20, 0x74, 0x68, 0x65, 0x20, 0x57, 0x69, 0x6B, +0x69, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x74, 0x68, +0x65, 0x20, 0x73, 0x74, 0x65, 0x70, 0x73, 0x20, +0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, +0x00, 0x74, 0x6F, 0x20, 0x63, 0x6F, 0x6E, 0x66, +0x69, 0x67, 0x75, 0x72, 0x65, 0x20, 0x79, 0x6F, +0x75, 0x72, 0x20, 0x6C, 0x61, 0x70, 0x74, 0x6F, +0x70, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x52, 0x4F, +0x4D, 0x00, 0x52, 0x65, 0x70, 0x6C, 0x61, 0x63, +0x65, 0x6D, 0x65, 0x6E, 0x74, 0x2C, 0x20, 0x61, +0x6E, 0x64, 0x20, 0x68, 0x6F, 0x77, 0x20, 0x74, +0x6F, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, +0x20, 0x52, 0x4F, 0x4D, 0x00, 0x69, 0x6D, 0x61, +0x67, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, +0x20, 0x61, 0x72, 0x65, 0x20, 0x63, 0x6F, 0x6D, +0x70, 0x61, 0x74, 0x69, 0x62, 0x6C, 0x65, 0x20, +0x77, 0x69, 0x74, 0x68, 0x20, 0x52, 0x45, 0x58, +0x2E, 0x00, 0x52, 0x4F, 0x4D, 0x73, 0x20, 0x72, +0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x20, 0x61, +0x20, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x20, 0x63, +0x68, 0x61, 0x6E, 0x67, 0x65, 0x20, 0x73, 0x6F, +0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x52, 0x45, +0x58, 0x00, 0x63, 0x61, 0x6E, 0x20, 0x64, 0x65, +0x74, 0x65, 0x63, 0x74, 0x20, 0x74, 0x68, 0x65, +0x20, 0x68, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, +0x65, 0x20, 0x63, 0x6F, 0x6E, 0x66, 0x69, 0x67, +0x75, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2E, +0x00, 0xFE, 0x52, 0x45, 0x58, 0x20, 0x4D, 0x61, +0x6E, 0x61, 0x67, 0x65, 0x72, 0x20, 0x73, 0x63, +0x72, 0x65, 0x65, 0x6E, 0x73, 0x20, 0x6E, 0x6F, +0x77, 0x20, 0x69, 0x6E, 0x64, 0x69, 0x63, 0x61, +0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x00, 0x73, +0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x6F, 0x66, +0x20, 0x74, 0x68, 0x65, 0x20, 0x52, 0x4F, 0x4D, +0x20, 0x52, 0x65, 0x70, 0x6C, 0x61, 0x63, 0x65, +0x6D, 0x65, 0x6E, 0x74, 0x20, 0x66, 0x75, 0x6E, +0x63, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x00, 0x49, +0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6F, +0x70, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x63, +0x6F, 0x72, 0x6E, 0x65, 0x72, 0x20, 0x74, 0x68, +0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, +0x20, 0x00, 0x68, 0x69, 0x67, 0x68, 0x6C, 0x69, +0x67, 0x68, 0x74, 0x65, 0x64, 0x20, 0x63, 0x68, +0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2C, +0x20, 0x6F, 0x6E, 0x65, 0x20, 0x6F, 0x66, 0x20, +0x4D, 0x2F, 0x50, 0x2F, 0x53, 0x2E, 0x00, 0x54, +0x68, 0x69, 0x73, 0x20, 0x63, 0x68, 0x61, 0x72, +0x61, 0x63, 0x74, 0x65, 0x72, 0x20, 0x69, 0x6E, +0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, +0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x73, 0x79, +0x73, 0x74, 0x65, 0x6D, 0x00, 0x52, 0x4F, 0x4D, +0x20, 0x69, 0x73, 0x20, 0x69, 0x6E, 0x20, 0x75, +0x73, 0x65, 0x20, 0x2D, 0x20, 0x69, 0x6E, 0x74, +0x65, 0x72, 0x6E, 0x61, 0x6C, 0x20, 0x6F, 0x72, +0x20, 0x52, 0x45, 0x58, 0x20, 0x62, 0x61, 0x73, +0x65, 0x64, 0x2E, 0x00, 0xFE, 0x4D, 0x20, 0x2D, +0x20, 0x73, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, +0x64, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x6E, +0x61, 0x6C, 0x20, 0x52, 0x4F, 0x4D, 0x73, 0x20, +0x69, 0x6E, 0x20, 0x75, 0x73, 0x65, 0x00, 0x50, +0x20, 0x2D, 0x20, 0x50, 0x72, 0x69, 0x6D, 0x61, +0x72, 0x79, 0x20, 0x52, 0x4F, 0x4D, 0x20, 0x28, +0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x32, 0x29, +0x69, 0x6E, 0x20, 0x75, 0x73, 0x65, 0x00, 0x53, +0x20, 0x2D, 0x20, 0x53, 0x65, 0x63, 0x6F, 0x6E, +0x64, 0x61, 0x72, 0x79, 0x20, 0x52, 0x4F, 0x4D, +0x20, 0x28, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, +0x34, 0x29, 0x20, 0x69, 0x6E, 0x20, 0x75, 0x73, +0x65, 0x00, 0x57, 0x68, 0x65, 0x6E, 0x20, 0x74, +0x68, 0x65, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x72, +0x6E, 0x61, 0x6C, 0x20, 0x52, 0x4F, 0x4D, 0x20, +0x69, 0x73, 0x20, 0x69, 0x6E, 0x20, 0x75, 0x73, +0x65, 0x2C, 0x20, 0x52, 0x45, 0x58, 0x00, 0x63, +0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x70, 0x72, +0x6F, 0x76, 0x69, 0x64, 0x65, 0x20, 0x52, 0x4F, +0x4D, 0x20, 0x52, 0x65, 0x70, 0x6C, 0x61, 0x63, +0x65, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x00, 0x50, +0x72, 0x69, 0x6D, 0x61, 0x72, 0x79, 0x20, 0x6F, +0x72, 0x20, 0x53, 0x65, 0x63, 0x6F, 0x6E, 0x64, +0x61, 0x72, 0x79, 0x20, 0x52, 0x4F, 0x4D, 0x20, +0x69, 0x6D, 0x61, 0x67, 0x65, 0x73, 0x20, 0x6D, +0x61, 0x79, 0x20, 0x62, 0x65, 0x00, 0xFE, 0x27, +0x4C, 0x6F, 0x61, 0x64, 0x27, 0x65, 0x64, 0x20, +0x76, 0x69, 0x61, 0x20, 0x73, 0x65, 0x6C, 0x65, +0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x72, +0x6F, 0x6D, 0x20, 0x6D, 0x65, 0x6E, 0x75, 0x2E, +0x00, 0x57, 0x68, 0x65, 0x6E, 0x20, 0x74, 0x68, +0x65, 0x20, 0x6C, 0x61, 0x70, 0x74, 0x6F, 0x70, +0x20, 0x69, 0x73, 0x20, 0x63, 0x6F, 0x6E, 0x66, +0x69, 0x67, 0x75, 0x72, 0x65, 0x64, 0x20, 0x66, +0x6F, 0x72, 0x20, 0x52, 0x4F, 0x4D, 0x73, 0x00, +0x70, 0x72, 0x6F, 0x76, 0x69, 0x64, 0x65, 0x64, +0x20, 0x62, 0x79, 0x20, 0x52, 0x45, 0x58, 0x2C, +0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6F, 0x77, +0x65, 0x72, 0x2D, 0x75, 0x70, 0x20, 0x64, 0x65, +0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x00, 0x69, +0x73, 0x20, 0x74, 0x6F, 0x20, 0x75, 0x73, 0x65, +0x20, 0x74, 0x68, 0x65, 0x20, 0x50, 0x72, 0x69, +0x6D, 0x61, 0x72, 0x79, 0x20, 0x52, 0x4F, 0x4D, +0x20, 0x69, 0x6E, 0x20, 0x62, 0x6C, 0x6F, 0x63, +0x6B, 0x20, 0x32, 0x2E, 0x00, 0x49, 0x74, 0x20, +0x69, 0x73, 0x20, 0x61, 0x20, 0x67, 0x6F, 0x6F, +0x64, 0x20, 0x69, 0x64, 0x65, 0x61, 0x20, 0x74, +0x6F, 0x20, 0x6C, 0x65, 0x61, 0x76, 0x65, 0x20, +0x74, 0x68, 0x69, 0x73, 0x20, 0x62, 0x6C, 0x6F, +0x63, 0x6B, 0x00, 0x63, 0x6F, 0x6E, 0x66, 0x69, +0x67, 0x75, 0x72, 0x65, 0x64, 0x20, 0x77, 0x69, +0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, +0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64, 0x20, +0x69, 0x6D, 0x61, 0x67, 0x65, 0x2E, 0x00, 0xFE, +0x27, 0x55, 0x73, 0x65, 0x27, 0x20, 0x63, 0x6F, +0x6D, 0x6D, 0x61, 0x6E, 0x64, 0x20, 0x61, 0x6C, +0x6C, 0x6F, 0x77, 0x73, 0x20, 0x74, 0x68, 0x65, +0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x6F, +0x20, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x00, +0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x50, +0x72, 0x69, 0x6D, 0x61, 0x72, 0x79, 0x20, 0x6F, +0x72, 0x20, 0x53, 0x65, 0x63, 0x6F, 0x6E, 0x64, +0x61, 0x72, 0x79, 0x20, 0x52, 0x4F, 0x4D, 0x73, +0x20, 0x66, 0x6F, 0x72, 0x00, 0x75, 0x73, 0x65, +0x2E, 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, +0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x69, 0x6F, +0x6E, 0x20, 0x69, 0x73, 0x20, 0x74, 0x72, 0x61, +0x63, 0x6B, 0x65, 0x64, 0x20, 0x69, 0x6E, 0x20, +0x74, 0x68, 0x65, 0x00, 0x61, 0x63, 0x74, 0x69, +0x76, 0x65, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, +0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, +0x72, 0x79, 0x2C, 0x20, 0x73, 0x6F, 0x20, 0x74, +0x68, 0x61, 0x74, 0x20, 0x73, 0x79, 0x73, 0x74, +0x65, 0x6D, 0x00, 0x73, 0x74, 0x61, 0x74, 0x65, +0x20, 0x69, 0x73, 0x20, 0x61, 0x6C, 0x77, 0x61, +0x79, 0x73, 0x20, 0x72, 0x65, 0x73, 0x74, 0x6F, +0x72, 0x65, 0x64, 0x20, 0x6F, 0x6E, 0x20, 0x70, +0x6F, 0x77, 0x65, 0x72, 0x20, 0x75, 0x70, 0x2E, +0x00, 0x54, 0x69, 0x6D, 0x65, 0x73, 0x74, 0x61, +0x6D, 0x70, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, +0x72, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x65, 0x64, +0x20, 0x61, 0x6C, 0x73, 0x6F, 0x2E, 0x00, 0xFE, +0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, +0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x68, 0x6F, +0x77, 0x6E, 0x20, 0x61, 0x62, 0x6F, 0x76, 0x65, +0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6E, 0x74, +0x72, 0x69, 0x65, 0x73, 0x20, 0x74, 0x6F, 0x00, +0x67, 0x69, 0x76, 0x65, 0x20, 0x73, 0x6F, 0x6D, +0x65, 0x20, 0x69, 0x6E, 0x66, 0x6F, 0x72, 0x6D, +0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x61, 0x62, +0x6F, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, +0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x00, 0x75, 0x6E, +0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, +0x63, 0x75, 0x72, 0x73, 0x6F, 0x72, 0x2E, 0x00, +0x00, 0x00, 0x00, 0xFF, 0x54, 0x68, 0x61, 0x6E, +0x6B, 0x73, 0x20, 0x74, 0x6F, 0x3A, 0x00, 0x4A, +0x6F, 0x68, 0x6E, 0x20, 0x48, 0x6F, 0x67, 0x65, +0x72, 0x68, 0x75, 0x69, 0x73, 0x3A, 0x20, 0x62, +0x72, 0x6F, 0x61, 0x64, 0x20, 0x74, 0x65, 0x63, +0x68, 0x6E, 0x69, 0x63, 0x61, 0x6C, 0x20, 0x73, +0x75, 0x70, 0x70, 0x6F, 0x72, 0x74, 0x00, 0x50, +0x68, 0x69, 0x6C, 0x69, 0x70, 0x20, 0x41, 0x76, +0x65, 0x72, 0x79, 0x3A, 0x20, 0x4D, 0x45, 0x4E, +0x55, 0x20, 0x63, 0x6F, 0x64, 0x65, 0x20, 0x63, +0x6F, 0x6E, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, +0x69, 0x6F, 0x6E, 0x73, 0x00, 0x57, 0x69, 0x6C, +0x73, 0x6F, 0x6E, 0x20, 0x56, 0x61, 0x6E, 0x20, +0x41, 0x6C, 0x73, 0x74, 0x3A, 0x20, 0x62, 0x61, +0x73, 0x65, 0x20, 0x54, 0x50, 0x44, 0x44, 0x20, +0x72, 0x6F, 0x75, 0x74, 0x69, 0x6E, 0x65, 0x73, +0x00, 0x4B, 0x65, 0x6E, 0x20, 0x50, 0x65, 0x74, +0x74, 0x69, 0x74, 0x3A, 0x20, 0x66, 0x6F, 0x72, +0x20, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6C, +0x54, 0x21, 0x00, 0x2E, 0x2E, 0x2E, 0x61, 0x6E, +0x64, 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x6F, +0x74, 0x68, 0x65, 0x72, 0x73, 0x20, 0x66, 0x6F, +0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, +0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6B, +0x00, 0xFF, 0x41, 0x72, 0x72, 0x6F, 0x77, 0x2C, +0x20, 0x73, 0x68, 0x69, 0x66, 0x74, 0x2D, 0x61, +0x72, 0x72, 0x6F, 0x77, 0x20, 0x74, 0x6F, 0x20, +0x62, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x00, 0x3C, +0x46, 0x31, 0x3E, 0x20, 0x44, 0x69, 0x73, 0x70, +0x6C, 0x61, 0x79, 0x20, 0x68, 0x65, 0x6C, 0x70, +0x20, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6E, 0x73, +0x00, 0x3C, 0x46, 0x33, 0x3E, 0x20, 0x43, 0x6F, +0x70, 0x79, 0x20, 0x66, 0x69, 0x6C, 0x65, 0x20, +0x66, 0x72, 0x6F, 0x6D, 0x20, 0x52, 0x45, 0x58, +0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x20, 0x2D, +0x2D, 0x3E, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x00, +0x3C, 0x46, 0x34, 0x3E, 0x20, 0x4B, 0x69, 0x6C, +0x6C, 0x20, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x20, +0x66, 0x69, 0x6C, 0x65, 0x00, 0x3C, 0x46, 0x35, +0x3E, 0x20, 0x4E, 0x61, 0x6D, 0x65, 0x20, 0x6C, +0x6F, 0x63, 0x61, 0x6C, 0x20, 0x66, 0x69, 0x6C, +0x65, 0x00, 0x3C, 0x46, 0x38, 0x3E, 0x20, 0x45, +0x78, 0x69, 0x74, 0x20, 0x46, 0x69, 0x6C, 0x65, +0x20, 0x4D, 0x65, 0x6E, 0x75, 0x00, 0xFF, 0xCD, +0xBB, 0x1A, 0xCD, 0xAC, 0x1A, 0x3A, 0xBB, 0xF7, +0xCD, 0x62, 0x1A, 0x21, 0xEF, 0x2F, 0x3A, 0xC9, +0xF7, 0xFE, 0x03, 0xC2, 0xE9, 0x2F, 0x21, 0x1C, +0x30, 0x22, 0xB2, 0xF7, 0xC3, 0xAE, 0x30, 0xCD, +0x78, 0x33, 0xCA, 0x16, 0x30, 0xCD, 0x7C, 0x30, +0xCD, 0x90, 0x33, 0xCA, 0x07, 0x30, 0x11, 0x70, +0xEF, 0xCD, 0xA7, 0x1B, 0xC3, 0x16, 0x30, 0xCD, +0xD1, 0x1B, 0xCD, 0xA5, 0x30, 0x21, 0x1B, 0x08, +0x22, 0xB2, 0xF7, 0xC3, 0xDE, 0x32, 0xCD, 0xA5, +0x30, 0xC3, 0x1B, 0x08, 0xCD, 0x78, 0x33, 0xCA, +0x16, 0x30, 0xCD, 0x90, 0x33, 0xCA, 0x6A, 0x30, +0x3A, 0xBE, 0xF7, 0x47, 0x3A, 0xBB, 0xF7, 0x4F, +0xC5, 0xCD, 0x73, 0x30, 0xCD, 0xF3, 0x09, 0xC1, +0x78, 0xC5, 0xCD, 0x73, 0x1B, 0xC1, 0x78, 0x41, +0x4F, 0xC5, 0xCD, 0xF3, 0x09, 0xC1, 0xC5, 0xCD, +0x73, 0x30, 0xCD, 0xF3, 0x09, 0xC1, 0x78, 0xC5, +0xCD, 0x73, 0x1B, 0xC1, 0x79, 0x32, 0xBB, 0xF7, +0xCD, 0xDB, 0x1B, 0xCD, 0xD7, 0x1B, 0xCD, 0x7C, +0x30, 0x11, 0x70, 0xEF, 0xCD, 0xA7, 0x1B, 0xC3, +0x16, 0x30, 0x3A, 0xBB, 0xF7, 0xCD, 0x73, 0x1B, +0xC3, 0x0A, 0x30, 0x78, 0xEE, 0x01, 0x47, 0x79, +0xEE, 0x01, 0x4F, 0xC9, 0x3A, 0xC9, 0xF7, 0x32, +0xCA, 0xF7, 0x3E, 0xFF, 0xCD, 0xE3, 0x1B, 0xE5, +0x3A, 0xBB, 0xF7, 0xCD, 0xB9, 0x1B, 0xE1, 0xE5, +0xCD, 0xBE, 0x1B, 0xCD, 0x1A, 0x1D, 0xE1, 0xE5, +0xCD, 0x01, 0x1E, 0xCD, 0x34, 0x1D, 0xE1, 0xE5, +0xCD, 0x09, 0x1E, 0xE1, 0xC9, 0xCD, 0x87, 0x33, +0xCD, 0x6F, 0x33, 0xC3, 0xFE, 0x02, 0xCD, 0x12, +0x31, 0xCD, 0x13, 0x33, 0xCA, 0x62, 0x1B, 0xCD, +0xAC, 0x33, 0xCA, 0x62, 0x1B, 0xCD, 0x6A, 0x03, +0x21, 0xE0, 0x33, 0xCD, 0x1E, 0x31, 0xCD, 0x5F, +0x17, 0xCD, 0x31, 0x31, 0x21, 0x70, 0xEF, 0x7E, +0x32, 0xC3, 0xF7, 0x3E, 0x03, 0x77, 0x21, 0x01, +0x01, 0xCD, 0xAB, 0x31, 0x21, 0x70, 0xEF, 0x3A, +0xC3, 0xF7, 0x77, 0xCD, 0x66, 0x33, 0x21, 0x03, +0x00, 0xCD, 0xAB, 0x31, 0xEB, 0x3A, 0xBB, 0xF7, +0x4F, 0x2A, 0xC1, 0xF7, 0xCD, 0x83, 0xF8, 0x22, +0xC1, 0xF7, 0x7C, 0xE6, 0x03, 0xB5, 0xC2, 0x04, +0x31, 0xCD, 0x38, 0xF8, 0x2A, 0xC1, 0xF7, 0x7C, +0x17, 0xD2, 0xE6, 0x30, 0x21, 0xF5, 0x33, 0xC3, +0x44, 0x31, 0xCD, 0xA1, 0x33, 0xCD, 0x96, 0x33, +0xCD, 0x87, 0x33, 0xC3, 0x6F, 0x33, 0xCD, 0x64, +0x02, 0x16, 0x09, 0x21, 0x70, 0xEF, 0xCD, 0xDD, +0x02, 0xF3, 0xCD, 0xFD, 0x18, 0xCD, 0x83, 0xF8, +0xC9, 0x21, 0x00, 0x00, 0x22, 0xC1, 0xF7, 0x21, +0x07, 0x00, 0xCD, 0xAB, 0x31, 0x21, 0x00, 0x1A, +0xCD, 0xAB, 0x31, 0xC9, 0xFB, 0xCD, 0x64, 0x02, +0x21, 0x02, 0x00, 0xCD, 0xAB, 0x31, 0xCD, 0x7E, +0x33, 0xC3, 0x62, 0x1B, 0xCD, 0x12, 0x31, 0xCD, +0x23, 0x33, 0xCA, 0x62, 0x1B, 0xCD, 0xAC, 0x33, +0xCA, 0x62, 0x1B, 0x21, 0xEB, 0x33, 0xCD, 0x1E, +0x31, 0xCD, 0x88, 0x17, 0xCD, 0x31, 0x31, 0x21, +0x01, 0x01, 0x3E, 0x01, 0x32, 0x70, 0xEF, 0xCD, +0xAB, 0x31, 0x2A, 0xC1, 0xF7, 0x3A, 0xBE, 0xF7, +0x4F, 0x11, 0x70, 0xEF, 0xCD, 0x83, 0xF8, 0x22, +0xC1, 0xF7, 0x21, 0x04, 0x80, 0xCD, 0xAB, 0x31, +0x2A, 0xC1, 0xF7, 0x7C, 0xE6, 0x03, 0xB5, 0xC2, +0x9D, 0x31, 0xCD, 0x38, 0xF8, 0x2A, 0xC1, 0xF7, +0x7C, 0x17, 0xD2, 0x7A, 0x31, 0x21, 0x0A, 0x34, +0xCD, 0x44, 0x31, 0xF3, 0x0E, 0x00, 0x11, 0x6E, +0xEF, 0xD9, 0x24, 0x24, 0x3E, 0x5A, 0xCD, 0xFC, +0x32, 0xCD, 0xFC, 0x32, 0x1A, 0xCD, 0xFC, 0x32, +0x81, 0x4F, 0x13, 0x25, 0xC2, 0xBC, 0x31, 0xEB, +0x01, 0x20, 0x00, 0x09, 0x22, 0xBF, 0xF7, 0xEB, +0x13, 0x2F, 0xCD, 0xFC, 0x32, 0x21, 0x00, 0x10, +0x22, 0xC7, 0xF7, 0x2A, 0xBF, 0xF7, 0xAF, 0x77, +0x20, 0xE6, 0x20, 0xC2, 0xFB, 0x31, 0x3E, 0x20, +0x3D, 0xC2, 0xE8, 0x31, 0x2A, 0xC7, 0xF7, 0x2B, +0x22, 0xC7, 0xF7, 0x7C, 0xB5, 0xCA, 0xE4, 0x32, +0xC3, 0xE0, 0x31, 0x21, 0x00, 0x10, 0x22, 0xC7, +0xF7, 0xAF, 0xDB, 0xCE, 0x2A, 0xBF, 0xF7, 0x4E, +0x77, 0x81, 0x23, 0x77, 0x22, 0xBF, 0xF7, 0x1A, +0x3C, 0x3C, 0x4F, 0x06, 0x00, 0x08, 0x7C, 0xBA, +0xC2, 0xE0, 0x31, 0x7D, 0xBB, 0xC2, 0xE0, 0x31, +0x2A, 0xBF, 0xF7, 0x7E, 0x2B, 0x96, 0xEE, 0xFF, +0xBE, 0xC2, 0xF0, 0x32, 0xEB, 0x2B, 0x46, 0x23, +0x23, 0xAF, 0x86, 0x4F, 0xC5, 0x78, 0xD6, 0x12, +0xC1, 0x79, 0xC0, 0xB7, 0xC8, 0xE6, 0xF0, 0x0F, +0x0F, 0x0F, 0x21, 0x4E, 0x32, 0x4F, 0x06, 0x00, +0x09, 0xEB, 0xED, 0xC3, 0x55, 0x1B, 0x60, 0x32, +0x72, 0x32, 0x82, 0x32, 0x90, 0x32, 0x9E, 0x32, +0xA9, 0x32, 0xB9, 0x32, 0xC3, 0x32, 0xCF, 0x32, +0x55, 0x6E, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, +0x69, 0x65, 0x64, 0x20, 0x65, 0x72, 0x72, 0x6F, +0x72, 0x00, 0x46, 0x69, 0x6C, 0x65, 0x20, 0x6E, +0x61, 0x6D, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6F, +0x72, 0x00, 0x55, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, +0x6E, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x00, +0x43, 0x6F, 0x6D, 0x6D, 0x61, 0x6E, 0x64, 0x20, +0x65, 0x72, 0x72, 0x6F, 0x72, 0x00, 0x52, 0x65, +0x61, 0x64, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, +0x00, 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, 0x70, +0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, +0x00, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x66, 0x75, +0x6C, 0x6C, 0x00, 0x49, 0x6E, 0x73, 0x65, 0x72, +0x74, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x00, 0x48, +0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x20, +0x65, 0x72, 0x72, 0x6F, 0x72, 0x00, 0x21, 0x8A, +0x34, 0xC3, 0x55, 0x1B, 0x21, 0xA6, 0x34, 0xC3, +0x55, 0x1B, 0x21, 0x73, 0x34, 0xC3, 0x55, 0x1B, +0x21, 0x3B, 0x34, 0xC3, 0x55, 0x1B, 0x21, 0x1F, +0x34, 0xC3, 0x55, 0x1B, 0xF5, 0xE5, 0x21, 0x00, +0x00, 0x2B, 0x7C, 0xB5, 0xCA, 0xEA, 0x32, 0xDB, +0xCF, 0xE6, 0x01, 0xCA, 0x01, 0x33, 0xE1, 0xF1, +0xD3, 0xCE, 0xC9, 0x21, 0xC1, 0x33, 0xCD, 0x64, +0x02, 0x21, 0x0C, 0x1E, 0xCD, 0xBF, 0x19, 0xC8, +0xC3, 0x40, 0x33, 0x3A, 0xBE, 0xF7, 0xCD, 0xDB, +0x1B, 0x23, 0x11, 0x70, 0xEF, 0x06, 0x06, 0x7E, +0xC5, 0xE5, 0xD5, 0xF7, 0x14, 0x10, 0xD1, 0xE1, +0xC1, 0x12, 0x23, 0x13, 0x05, 0xC2, 0x2F, 0x33, +0x21, 0x76, 0xEF, 0x06, 0x12, 0xCD, 0x11, 0x03, +0x11, 0x46, 0x00, 0xEB, 0xD9, 0x21, 0x76, 0xEF, +0x36, 0x2E, 0x23, 0xE5, 0x21, 0xB9, 0x33, 0x3A, +0xC9, 0xF7, 0x07, 0x5F, 0xAF, 0x57, 0x19, 0xEB, +0xED, 0xD1, 0xD9, 0xF6, 0x01, 0xC9, 0x3A, 0xB0, +0xF7, 0xF6, 0x40, 0x32, 0xB0, 0xF7, 0xC9, 0x3A, +0xB0, 0xF7, 0xE6, 0xBF, 0x32, 0xB0, 0xF7, 0xC9, +0x3A, 0xB0, 0xF7, 0xE6, 0x40, 0xC9, 0x3A, 0xB0, +0xF7, 0xF6, 0x80, 0x32, 0xB0, 0xF7, 0xC9, 0x3A, +0xB0, 0xF7, 0xE6, 0x7F, 0x32, 0xB0, 0xF7, 0xC9, +0x3A, 0xB0, 0xF7, 0xE6, 0x80, 0xC9, 0x3E, 0xFF, +0xC6, 0x01, 0x21, 0xD4, 0xF7, 0xF7, 0x1D, 0x19, +0xC9, 0x3A, 0xFE, 0xFC, 0xF6, 0x27, 0x32, 0xFE, +0xFC, 0xD3, 0xCF, 0xC9, 0x21, 0x56, 0x34, 0xCD, +0x64, 0x02, 0xCD, 0x81, 0x1B, 0xCA, 0x5E, 0x1B, +0xC9, 0x42, 0x59, 0x42, 0x58, 0x42, 0x5A, 0x42, +0x52, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, +0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x69, 0x6D, +0x61, 0x67, 0x65, 0x20, 0x66, 0x69, 0x6C, 0x65, +0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3A, 0x20, 0x00, +0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, +0x30, 0x3A, 0x00, 0x53, 0x61, 0x76, 0x69, 0x6E, +0x67, 0x20, 0x30, 0x3A, 0x00, 0x4C, 0x6F, 0x61, +0x64, 0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x20, +0x63, 0x6F, 0x6D, 0x70, 0x6C, 0x65, 0x74, 0x65, +0x21, 0x00, 0x53, 0x61, 0x76, 0x65, 0x20, 0x69, +0x6D, 0x61, 0x67, 0x65, 0x20, 0x63, 0x6F, 0x6D, +0x70, 0x6C, 0x65, 0x74, 0x65, 0x21, 0x00, 0x45, +0x53, 0x43, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x70, +0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2E, 0x2E, +0x2E, 0x61, 0x62, 0x6F, 0x72, 0x74, 0x69, 0x6E, +0x67, 0x2E, 0x00, 0x43, 0x68, 0x65, 0x63, 0x6B, +0x73, 0x75, 0x6D, 0x20, 0x65, 0x72, 0x72, 0x6F, +0x72, 0x2E, 0x2E, 0x2E, 0x61, 0x62, 0x6F, 0x72, +0x74, 0x69, 0x6E, 0x67, 0x2E, 0x00, 0x48, 0x69, +0x74, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, +0x79, 0x20, 0x77, 0x68, 0x65, 0x6E, 0x20, 0x54, +0x50, 0x44, 0x44, 0x20, 0x72, 0x65, 0x61, 0x64, +0x79, 0x2E, 0x00, 0x45, 0x72, 0x72, 0x6F, 0x72, +0x20, 0x73, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, +0x20, 0x63, 0x6F, 0x6D, 0x6D, 0x61, 0x6E, 0x64, +0x21, 0x00, 0x4C, 0x6F, 0x61, 0x64, 0x20, 0x66, +0x69, 0x6C, 0x65, 0x20, 0x66, 0x72, 0x6F, 0x6D, +0x20, 0x54, 0x50, 0x44, 0x44, 0x20, 0x66, 0x61, +0x69, 0x6C, 0x65, 0x64, 0x21, 0x00, 0x4E, 0x6F, +0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, +0x65, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x54, +0x50, 0x44, 0x44, 0x21, 0x00, 0xCD, 0x66, 0x1B, +0xAF, 0x32, 0xBA, 0xF7, 0x32, 0xC3, 0xF7, 0x21, +0xF0, 0x43, 0x11, 0x10, 0x00, 0x19, 0x7E, 0xA7, +0xCA, 0xCA, 0x34, 0xFE, 0xFF, 0xCA, 0x1C, 0x35, +0xE6, 0x3F, 0x4F, 0xEB, 0x06, 0x00, 0x21, 0x83, +0xF8, 0x09, 0xEB, 0xE5, 0x01, 0x07, 0x00, 0x09, +0x4E, 0xE1, 0x7E, 0xE6, 0xC0, 0x81, 0x12, 0xE6, +0xC0, 0xFE, 0xC0, 0xC2, 0x0B, 0x35, 0x3A, 0xC3, +0xF7, 0x3C, 0x32, 0xC3, 0xF7, 0x3A, 0xC9, 0xF7, +0xB9, 0xC2, 0x0B, 0x35, 0x3A, 0xBA, 0xF7, 0x3C, +0x32, 0xBA, 0xF7, 0x7E, 0xE6, 0x3F, 0xEB, 0x21, +0xA3, 0xF8, 0x87, 0x4F, 0x06, 0x00, 0x09, 0xEB, +0xD9, 0xC3, 0xCA, 0x34, 0x3A, 0xC3, 0xF7, 0x47, +0x3A, 0xC9, 0xF7, 0xFE, 0x03, 0xC0, 0x3E, 0x04, +0x32, 0xBA, 0xF7, 0xC9, 0xCD, 0xC8, 0x00, 0x3A, +0xBD, 0xF7, 0xFE, 0x06, 0xFA, 0x96, 0x36, 0xFE, +0x20, 0xF2, 0x96, 0x36, 0x3A, 0xBC, 0xF7, 0xFE, +0x06, 0xFA, 0x96, 0x36, 0xFE, 0x20, 0xF2, 0x96, +0x36, 0xCD, 0x66, 0x1B, 0x3E, 0xFF, 0x32, 0xC1, +0xF7, 0xAF, 0x32, 0xC3, 0xF7, 0x32, 0xBA, 0xF7, +0x21, 0xF0, 0x43, 0x22, 0xBF, 0xF7, 0x3A, 0xC1, +0xF7, 0x2F, 0x32, 0xC1, 0xF7, 0x11, 0x10, 0x00, +0x19, 0xE5, 0x01, 0x00, 0x50, 0x08, 0xE1, 0xCA, +0x1B, 0x36, 0x3A, 0xC1, 0xF7, 0xA6, 0x47, 0x3A, +0xC1, 0xF7, 0xB8, 0xC2, 0x5D, 0x36, 0x7E, 0xA7, +0xCA, 0x65, 0x35, 0x7E, 0xFE, 0xFF, 0xCA, 0x10, +0x36, 0x7E, 0xE6, 0xC0, 0xCA, 0xB4, 0x36, 0x01, +0x07, 0x00, 0xE5, 0x09, 0x7E, 0xE1, 0x46, 0xFE, +0x03, 0xC2, 0xAC, 0x35, 0x78, 0xE6, 0x3F, 0xFE, +0x06, 0xF2, 0xAE, 0x36, 0xFE, 0x00, 0xFA, 0xAE, +0x36, 0xC3, 0xC3, 0x35, 0xFE, 0x03, 0xF2, 0xA8, +0x36, 0xFE, 0x00, 0xFA, 0xA8, 0x36, 0x78, 0xE6, +0x3F, 0xFE, 0x06, 0xFA, 0xAE, 0x36, 0xFE, 0x32, +0xF2, 0xAE, 0x36, 0x7E, 0xEB, 0xF5, 0xE6, 0x3F, +0x4F, 0x06, 0x00, 0xF1, 0x21, 0x83, 0xF8, 0x09, +0xEB, 0xE5, 0x01, 0x07, 0x00, 0x09, 0x7E, 0xE1, +0x4F, 0x1A, 0xB7, 0xC2, 0x69, 0x36, 0x7E, 0xE6, +0xC0, 0x81, 0x12, 0xE6, 0xC0, 0xFE, 0xC0, 0xC2, +0xFF, 0x35, 0x3A, 0xC3, 0xF7, 0x3C, 0x32, 0xC3, +0xF7, 0x3A, 0xC9, 0xF7, 0xB9, 0xC2, 0xFF, 0x35, +0x3A, 0xBA, 0xF7, 0x3C, 0x32, 0xBA, 0xF7, 0x7E, +0xE6, 0x3F, 0xEB, 0x21, 0xA3, 0xF8, 0x87, 0x4F, +0x06, 0x00, 0x09, 0xEB, 0xD9, 0xC3, 0x65, 0x35, +0x3A, 0xC1, 0xF7, 0xFE, 0xFF, 0xCA, 0x65, 0x35, +0xC3, 0x5B, 0x35, 0x11, 0x83, 0xF8, 0x01, 0xC3, +0xC3, 0x3E, 0x03, 0xD5, 0xED, 0x08, 0xD1, 0xC2, +0x90, 0x36, 0x13, 0x13, 0x3D, 0xC2, 0x23, 0x36, +0x3A, 0xBD, 0xF7, 0x4F, 0x06, 0x00, 0x21, 0x83, +0xF8, 0x09, 0x7E, 0xFE, 0xC0, 0xC2, 0x9C, 0x36, +0x3A, 0xBC, 0xF7, 0x4F, 0x06, 0x00, 0x21, 0x83, +0xF8, 0x09, 0x7E, 0xFE, 0xC0, 0xCA, 0xA2, 0x36, +0xFA, 0xA2, 0x36, 0xFE, 0xC3, 0xF2, 0xA2, 0x36, +0x3A, 0xC3, 0xF7, 0x47, 0xC9, 0x21, 0xD3, 0x36, +0xCD, 0x64, 0x02, 0x2A, 0xBF, 0xF7, 0xC3, 0xC3, +0x36, 0x7E, 0xE6, 0xC0, 0xFE, 0xC0, 0xC2, 0x81, +0x36, 0xEB, 0x01, 0x83, 0xF8, 0x08, 0x7D, 0x21, +0xA3, 0xF8, 0x87, 0x4F, 0x06, 0x00, 0x09, 0xEB, +0xED, 0xCD, 0xD7, 0x1B, 0x21, 0x1B, 0x37, 0xCD, +0x64, 0x02, 0xCD, 0x8A, 0x1B, 0xC3, 0x2C, 0x35, +0x21, 0x38, 0x37, 0xC3, 0xCC, 0x36, 0x21, 0x53, +0x37, 0xC3, 0xCC, 0x36, 0x21, 0x78, 0x37, 0xC3, +0xCC, 0x36, 0x21, 0x95, 0x37, 0xC3, 0xCC, 0x36, +0x11, 0xB9, 0x37, 0xC3, 0xBD, 0x36, 0x11, 0xD2, +0x37, 0xC3, 0xBD, 0x36, 0x11, 0xEC, 0x36, 0xC3, +0xBD, 0x36, 0x11, 0x04, 0x37, 0xEB, 0xD5, 0xCD, +0x64, 0x02, 0xE1, 0xCD, 0xD7, 0x1B, 0xCD, 0x8A, +0x1B, 0xC3, 0x2C, 0x35, 0xCD, 0x64, 0x02, 0xCD, +0x8A, 0x1B, 0xC9, 0x46, 0x46, 0x20, 0x65, 0x6E, +0x63, 0x6F, 0x75, 0x6E, 0x74, 0x65, 0x72, 0x65, +0x64, 0x20, 0x65, 0x61, 0x72, 0x6C, 0x79, 0x20, +0x2E, 0x2E, 0x2E, 0x00, 0x42, 0x61, 0x64, 0x20, +0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, +0x79, 0x20, 0x65, 0x6E, 0x74, 0x72, 0x79, 0x20, +0x2E, 0x2E, 0x2E, 0x00, 0x42, 0x6C, 0x6F, 0x63, +0x6B, 0x20, 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, +0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x2E, +0x2E, 0x2E, 0x00, 0x52, 0x65, 0x70, 0x65, 0x61, +0x74, 0x65, 0x64, 0x20, 0x64, 0x69, 0x72, 0x65, +0x63, 0x74, 0x6F, 0x72, 0x79, 0x20, 0x65, 0x6E, +0x74, 0x72, 0x79, 0x20, 0x2E, 0x2E, 0x2E, 0x00, +0x4D, 0x69, 0x73, 0x73, 0x69, 0x6E, 0x67, 0x20, +0x73, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x20, 0x65, +0x6E, 0x74, 0x72, 0x69, 0x65, 0x73, 0x20, 0x2E, +0x2E, 0x2E, 0x00, 0x42, 0x61, 0x64, 0x20, 0x6F, +0x72, 0x20, 0x6D, 0x69, 0x73, 0x73, 0x69, 0x6E, +0x67, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, +0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x69, +0x6E, 0x66, 0x6F, 0x20, 0x2E, 0x2E, 0x2E, 0x00, +0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x52, +0x41, 0x4D, 0x20, 0x69, 0x6D, 0x61, 0x67, 0x65, +0x20, 0x6D, 0x69, 0x73, 0x73, 0x69, 0x6E, 0x67, +0x20, 0x2E, 0x2E, 0x2E, 0x00, 0x41, 0x63, 0x74, +0x69, 0x76, 0x65, 0x20, 0x4F, 0x50, 0x54, 0x49, +0x4F, 0x4E, 0x20, 0x52, 0x4F, 0x4D, 0x20, 0x69, +0x6D, 0x61, 0x67, 0x65, 0x20, 0x6D, 0x69, 0x73, +0x73, 0x69, 0x6E, 0x67, 0x20, 0x2E, 0x2E, 0x2E, +0x00, 0x49, 0x6E, 0x63, 0x6F, 0x72, 0x72, 0x65, +0x63, 0x74, 0x20, 0x65, 0x6E, 0x74, 0x72, 0x79, +0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x2E, 0x2E, +0x2E, 0x00, 0x45, 0x6E, 0x74, 0x72, 0x79, 0x20, +0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6F, 0x75, +0x74, 0x20, 0x6F, 0x66, 0x20, 0x72, 0x61, 0x6E, +0x67, 0x65, 0x20, 0x2E, 0x2E, 0x2E, 0x00, 0xF5, +0xCD, 0xAC, 0x1A, 0xF1, 0xCD, 0x73, 0x1B, 0xC9, +0x3A, 0xC9, 0xF7, 0xFE, 0x03, 0xCA, 0x3D, 0x38, +0xCD, 0xE7, 0x38, 0x3A, 0xBA, 0xF7, 0xB7, 0xC8, +0xFE, 0x01, 0xC8, 0x0E, 0xFF, 0x06, 0x00, 0x0C, +0x3A, 0xBA, 0xF7, 0x3D, 0xB9, 0xC8, 0xCD, 0x4C, +0x38, 0xEB, 0xED, 0xE5, 0x0C, 0xCD, 0x4C, 0x38, +0x0D, 0xEB, 0xED, 0xEB, 0xE1, 0xC5, 0xCD, 0x5A, +0x38, 0xC1, 0xCA, 0x0F, 0x38, 0xFA, 0x0F, 0x38, +0x21, 0xE3, 0xF8, 0x09, 0xEB, 0xED, 0x7C, 0x65, +0x6F, 0xD9, 0xC3, 0x0B, 0x38, 0x21, 0xE3, 0xF8, +0x36, 0x02, 0x23, 0x36, 0x03, 0x23, 0x36, 0x04, +0x23, 0x36, 0x05, 0xC9, 0x21, 0xE3, 0xF8, 0x09, +0x7E, 0x87, 0x21, 0xA3, 0xF8, 0x16, 0x00, 0x5F, +0x19, 0xC9, 0xC5, 0xE5, 0xD5, 0x01, 0x08, 0x00, +0xCD, 0x76, 0x38, 0xD1, 0xE1, 0xCA, 0x6E, 0x38, +0xFA, 0x74, 0x38, 0xF2, 0x74, 0x38, 0x01, 0x0A, +0x00, 0xCD, 0x76, 0x38, 0xC1, 0xC9, 0x09, 0xEB, +0x09, 0x46, 0x23, 0x4E, 0xEB, 0x56, 0x23, 0x5E, +0xEB, 0x08, 0xC8, 0xF5, 0x3A, 0xB0, 0xF7, 0xE6, +0x08, 0xCA, 0x93, 0x38, 0xF1, 0xF2, 0x9A, 0x38, +0xFA, 0x9E, 0x38, 0xF1, 0xFA, 0x9A, 0x38, 0xF2, +0x9E, 0x38, 0xAF, 0xC6, 0x10, 0xC9, 0xAF, 0xD6, +0x10, 0xC9, 0xE5, 0x0E, 0x06, 0x06, 0x00, 0x79, +0xFE, 0x20, 0xCA, 0xDF, 0x38, 0x3A, 0xBB, 0xF7, +0xB9, 0xCA, 0xDA, 0x38, 0xEE, 0x01, 0xB9, 0xCA, +0xDA, 0x38, 0x21, 0x83, 0xF8, 0x09, 0x7E, 0xE6, +0xC0, 0xF5, 0x23, 0x7E, 0xE6, 0xC0, 0x67, 0xF1, +0x6F, 0xF7, 0x18, 0x00, 0xCA, 0xE4, 0x38, 0x7C, +0x65, 0x6F, 0x0C, 0xF7, 0x18, 0x00, 0xCA, 0xE4, +0x38, 0x0D, 0x0C, 0x0C, 0xC3, 0xA7, 0x38, 0xF6, +0x01, 0xC3, 0xE5, 0x38, 0xAF, 0xE1, 0xC9, 0x11, +0xE3, 0xF8, 0x06, 0x20, 0xCD, 0x6B, 0x1B, 0x0E, +0xFF, 0x06, 0x32, 0x11, 0xE3, 0xF8, 0x21, 0x82, +0xF8, 0x3A, 0xC9, 0xF7, 0xF6, 0xC0, 0x0C, 0x23, +0x05, 0xC8, 0xBE, 0xC2, 0xFE, 0x38, 0xEB, 0x71, +0xEB, 0x13, 0xC3, 0xFE, 0x38, 0x21, 0x1B, 0x39, +0x22, 0xB2, 0xF7, 0xF7, 0x4D, 0x4F, 0x3E, 0x0F, +0x32, 0xCF, 0xF7, 0xCD, 0xD3, 0x17, 0x3E, 0x80, +0x32, 0xCE, 0xF7, 0x32, 0xB9, 0xF7, 0x32, 0xB8, +0xF7, 0x21, 0x01, 0x01, 0x22, 0xD0, 0xF7, 0xAF, +0x3D, 0x32, 0xB5, 0xF7, 0xCD, 0x54, 0x3C, 0xCD, +0x0D, 0x3C, 0xCD, 0x8D, 0x3A, 0xAF, 0x32, 0xCE, +0xF7, 0xCD, 0x6E, 0x3A, 0xCD, 0x78, 0x3A, 0xCD, +0x1F, 0x3B, 0x3E, 0x80, 0x32, 0xCE, 0xF7, 0xCD, +0x6E, 0x3A, 0xCD, 0x78, 0x3A, 0x3E, 0xFF, 0x32, +0xB5, 0xF7, 0x3A, 0xB5, 0xF7, 0xB7, 0xCA, 0x71, +0x39, 0xCD, 0x1F, 0x3B, 0x3A, 0xB9, 0xF7, 0xCD, +0xBD, 0x13, 0xCD, 0x6F, 0x3C, 0xAF, 0x32, 0xB5, +0xF7, 0x3A, 0xB9, 0xF7, 0xE6, 0x80, 0x6F, 0x3A, +0xB8, 0xF7, 0xE6, 0x80, 0xBD, 0xC4, 0x6F, 0x3C, +0xCD, 0xA0, 0x13, 0x3A, 0xB9, 0xF7, 0x32, 0xB8, +0xF7, 0xF7, 0x03, 0x8B, 0xCA, 0x89, 0x39, 0xDA, +0xD1, 0x3C, 0xF7, 0x14, 0x10, 0xCD, 0x9B, 0x39, +0xC3, 0x5A, 0x39, 0xF5, 0x2A, 0xB9, 0xF7, 0x3A, +0xB7, 0xF7, 0x47, 0x7D, 0xE6, 0x7F, 0x6F, 0xF1, +0xFE, 0x1D, 0xCA, 0xDB, 0x39, 0xFE, 0x1C, 0xCA, +0xDB, 0x39, 0x25, 0x24, 0xC8, 0xFE, 0x1F, 0xCA, +0xCA, 0x39, 0xFE, 0x1E, 0xCA, 0xCC, 0x39, 0xFE, +0x14, 0xCA, 0xD0, 0x39, 0xFE, 0x02, 0xCA, 0xD4, +0x39, 0xC9, 0x2C, 0x2C, 0x2D, 0xC3, 0xFD, 0x39, +0x78, 0xD6, 0x0C, 0x47, 0x78, 0xC6, 0x06, 0x47, +0xC3, 0xFD, 0x39, 0x3A, 0xCE, 0xF7, 0xF5, 0xB5, +0x32, 0xB8, 0xF7, 0xF1, 0xEE, 0x80, 0x32, 0xCE, +0xF7, 0xCD, 0x6E, 0x3A, 0x47, 0xCD, 0x78, 0x3A, +0x67, 0x25, 0x24, 0xC2, 0xFD, 0x39, 0x06, 0x01, +0x2E, 0x00, 0xC3, 0x29, 0x3A, 0x78, 0xFE, 0x01, +0xFA, 0x52, 0x3A, 0x7D, 0xFE, 0x00, 0xFA, 0x46, +0x3A, 0xFE, 0x06, 0xF2, 0x4C, 0x3A, 0xBC, 0xF2, +0x58, 0x3A, 0x7C, 0x90, 0xBD, 0xFA, 0x54, 0x3A, +0x7C, 0xD6, 0x05, 0x57, 0xFE, 0x01, 0xF2, 0x23, +0x3A, 0x16, 0x01, 0x78, 0x3D, 0xBA, 0xF2, 0x5D, +0x3A, 0x3A, 0xCE, 0xF7, 0xB5, 0x6F, 0x22, 0xB9, +0xF7, 0x3A, 0xB7, 0xF7, 0xB8, 0x3E, 0x00, 0xCA, +0x3B, 0x3A, 0x3D, 0x32, 0xB5, 0xF7, 0x78, 0x32, +0xB7, 0xF7, 0xCD, 0x61, 0x3A, 0xC9, 0x2E, 0x00, +0x05, 0xC3, 0xFD, 0x39, 0x2E, 0x05, 0x04, 0xC3, +0xFD, 0x39, 0x06, 0x02, 0x05, 0xC3, 0xFD, 0x39, +0x6C, 0x2D, 0xC3, 0xFD, 0x39, 0x42, 0xC3, 0xFD, +0x39, 0xE5, 0x21, 0xD0, 0xF7, 0xCD, 0x86, 0x3A, +0x3A, 0xB7, 0xF7, 0x77, 0xE1, 0xC9, 0xE5, 0x21, +0xD0, 0xF7, 0x11, 0xB7, 0xF7, 0xC3, 0x7F, 0x3A, +0xE5, 0x21, 0xD2, 0xF7, 0x11, 0xBA, 0xF7, 0xCD, +0x86, 0x3A, 0x7E, 0x12, 0xE1, 0xC9, 0x3A, 0xCE, +0xF7, 0xB7, 0xC8, 0x23, 0xC9, 0x11, 0xA6, 0xF8, +0x06, 0xDC, 0xC5, 0xCD, 0x6B, 0x1B, 0x11, 0x70, +0xEF, 0xC1, 0xCD, 0x6B, 0x1B, 0xAF, 0x32, 0xD2, +0xF7, 0x32, 0xD3, 0xF7, 0x32, 0xC3, 0xF7, 0x3A, +0xC3, 0xF7, 0x0E, 0x6E, 0x06, 0x00, 0x21, 0x70, +0xEF, 0x11, 0x52, 0xF2, 0xB7, 0xCA, 0xBD, 0x3A, +0x09, 0x7A, 0xE6, 0x7F, 0x57, 0xEB, 0x0E, 0x0B, +0x06, 0x00, 0x09, 0xCD, 0xFF, 0x3A, 0xFE, 0xFF, +0xCA, 0xE8, 0x3A, 0xCD, 0x13, 0x3B, 0xC2, 0xC2, +0x3A, 0xD9, 0x13, 0x13, 0xC5, 0xE5, 0x21, 0xD2, +0xF7, 0x06, 0x00, 0x3A, 0xC3, 0xF7, 0x4F, 0x09, +0x7E, 0x3C, 0x77, 0xE1, 0xC1, 0xC3, 0xC2, 0x3A, +0x3A, 0xC3, 0xF7, 0xB7, 0xC2, 0xF6, 0x3A, 0x3C, +0x32, 0xC3, 0xF7, 0xC3, 0xA7, 0x3A, 0xCD, 0xE7, +0x02, 0x70, 0xEF, 0xA6, 0xF8, 0xDC, 0xC9, 0x3A, +0xC3, 0xF7, 0xC3, 0x76, 0x3D, 0xC5, 0xD5, 0xE5, +0x3A, 0xBE, 0xF7, 0x4F, 0xCD, 0x83, 0xF8, 0xE1, +0xD1, 0xC1, 0xC9, 0xFE, 0x80, 0xC8, 0xFE, 0xC0, +0xC8, 0xFE, 0xA0, 0xC8, 0xF6, 0x01, 0xC9, 0x3A, +0xB7, 0xF7, 0x47, 0xC6, 0x05, 0x4F, 0x3A, 0xBA, +0xF7, 0xB7, 0xCA, 0x52, 0x3B, 0xB9, 0xF2, 0x32, +0x3B, 0x4F, 0xCD, 0x81, 0x3B, 0x78, 0x3D, 0xCD, +0x8D, 0x3B, 0x16, 0x01, 0x79, 0x90, 0x3C, 0x3C, +0x5F, 0xD5, 0xE5, 0xCD, 0x93, 0x3B, 0xE1, 0xD1, +0x23, 0x23, 0x14, 0x7A, 0xFE, 0x07, 0xFA, 0x41, +0x3B, 0xC9, 0x3A, 0xCE, 0xF7, 0xCD, 0xFB, 0x3B, +0x11, 0x60, 0x3B, 0xEB, 0xCD, 0x86, 0x02, 0xC9, +0x4E, 0x4F, 0x20, 0x46, 0x49, 0x4C, 0x45, 0x53, +0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, +0xCD, 0x81, 0x3B, 0x3A, 0xB9, 0xF7, 0xE6, 0x7F, +0x4F, 0x3A, 0xB7, 0xF7, 0x81, 0x3D, 0xC3, 0x8D, +0x3B, 0x21, 0xA6, 0xF8, 0x3A, 0xCE, 0xF7, 0xB7, +0xC8, 0x21, 0x14, 0xF9, 0xC9, 0x87, 0x16, 0x00, +0x5F, 0x19, 0xC9, 0xD5, 0xEB, 0xED, 0x22, 0xBF, +0xF7, 0x23, 0x23, 0x23, 0x3A, 0xCE, 0xF7, 0xB7, +0xCA, 0xB4, 0x3B, 0x11, 0x70, 0xEF, 0xD5, 0x06, +0x08, 0xCD, 0x05, 0x3B, 0x12, 0x23, 0x13, 0x05, +0xC2, 0xA9, 0x3B, 0xE1, 0xD1, 0xE5, 0x3A, 0xCE, +0xF7, 0xB2, 0x3D, 0xCD, 0xFB, 0x3B, 0x22, 0xC1, +0xF7, 0xF7, 0x9B, 0x4F, 0xE1, 0x7A, 0xBB, 0xF2, +0xF5, 0x3B, 0x16, 0x06, 0xCD, 0xDD, 0x02, 0x3E, +0x2E, 0xF7, 0x30, 0x50, 0x16, 0x02, 0xCD, 0xDD, +0x02, 0x21, 0xA9, 0x0E, 0xCD, 0x90, 0x02, 0x2A, +0xC1, 0xF7, 0x7C, 0xC6, 0x0A, 0x67, 0xF7, 0x9B, +0x4F, 0x2A, 0xBF, 0xF7, 0xCD, 0x0E, 0x3D, 0x60, +0x69, 0xF7, 0x0B, 0x47, 0xC9, 0x21, 0xA0, 0x0E, +0xC3, 0x90, 0x02, 0x21, 0x06, 0x04, 0xF5, 0xE6, +0x7F, 0x85, 0x6F, 0xF1, 0xE6, 0x80, 0xB7, 0xC8, +0x3E, 0x14, 0x84, 0x67, 0xC9, 0x21, 0x05, 0x01, +0xF7, 0x9B, 0x4F, 0x21, 0x44, 0x13, 0xCD, 0x90, +0x02, 0x3E, 0x3A, 0xF7, 0x30, 0x50, 0x3E, 0x20, +0xF7, 0x30, 0x50, 0xCD, 0xEE, 0x07, 0xF7, 0x0B, +0x47, 0x21, 0x48, 0x3C, 0xCD, 0x7C, 0x02, 0x21, +0x05, 0x15, 0xF7, 0x9B, 0x4F, 0x21, 0x4E, 0x3C, +0xCD, 0x90, 0x02, 0x3A, 0xBE, 0xF7, 0xCD, 0xDB, +0x1B, 0x23, 0x16, 0x06, 0xCD, 0xDD, 0x02, 0xC9, +0x20, 0x66, 0x72, 0x65, 0x65, 0x00, 0x52, 0x45, +0x58, 0x3A, 0x20, 0x00, 0x21, 0x05, 0x14, 0xF7, +0x9B, 0x4F, 0x06, 0x07, 0xC5, 0x21, 0x69, 0x3C, +0xCD, 0x90, 0x02, 0xC1, 0x05, 0xC2, 0x5C, 0x3C, +0xC9, 0x7C, 0x1B, 0x42, 0x1B, 0x44, 0x00, 0x21, +0x0C, 0x01, 0xF7, 0x9B, 0x4F, 0x21, 0xA1, 0x14, +0xCD, 0x90, 0x02, 0x21, 0xAA, 0x0E, 0xCD, 0x90, +0x02, 0x3A, 0xBA, 0xF7, 0xB7, 0xCA, 0xC8, 0x3C, +0x3A, 0xCE, 0xF7, 0xB7, 0xCA, 0xA4, 0x3C, 0x21, +0xB8, 0x14, 0xCD, 0x90, 0x02, 0x21, 0xAA, 0x0E, +0xCD, 0x90, 0x02, 0x21, 0xAA, 0x0E, 0xCD, 0x90, +0x02, 0xC3, 0xB6, 0x3C, 0x21, 0xAA, 0x0E, 0xCD, +0x90, 0x02, 0x21, 0xBE, 0x14, 0xCD, 0x90, 0x02, +0x21, 0xC4, 0x14, 0xCD, 0x90, 0x02, 0x21, 0xAA, +0x0E, 0xCD, 0x90, 0x02, 0x21, 0xAA, 0x0E, 0xCD, +0x90, 0x02, 0x21, 0xD5, 0x14, 0xC3, 0x90, 0x02, +0x21, 0xAA, 0x0E, 0xCD, 0x90, 0x02, 0xC3, 0x95, +0x3C, 0x57, 0x3A, 0xBA, 0xF7, 0xB7, 0xCA, 0x04, +0x3D, 0x7A, 0xB7, 0xCA, 0xC6, 0x20, 0x3D, 0xF5, +0x3A, 0xCE, 0xF7, 0xB7, 0xC2, 0xFA, 0x3C, 0xF1, +0x3D, 0x3D, 0xCA, 0x80, 0x3D, 0x3D, 0xCA, 0x2D, +0x3F, 0x3D, 0x3D, 0x3D, 0xCA, 0x0D, 0x08, 0xC3, +0x5A, 0x39, 0xF1, 0x3D, 0xCA, 0xEC, 0x3D, 0x3D, +0x3D, 0xC3, 0xF1, 0x3C, 0x7A, 0xB7, 0xCA, 0xC6, +0x20, 0xFE, 0x07, 0xC3, 0xF4, 0x3C, 0xCD, 0xD7, +0x3D, 0x01, 0x00, 0x00, 0xFE, 0x80, 0xCA, 0x38, +0x3D, 0xFE, 0xA0, 0xCA, 0x58, 0x3D, 0xFE, 0xC0, +0xCA, 0x24, 0x3D, 0xC9, 0xE5, 0xCD, 0x6F, 0x19, +0xE1, 0x01, 0x00, 0x00, 0x3A, 0xBE, 0xF7, 0xCD, +0x83, 0xF8, 0xC5, 0xCD, 0xD3, 0x17, 0xC1, 0xC9, +0xD5, 0x44, 0x4D, 0xCD, 0x73, 0x3D, 0x5F, 0x23, +0xCD, 0x73, 0x3D, 0x57, 0xB2, 0xCA, 0x50, 0x3D, +0x62, 0x6B, 0xCD, 0x6B, 0x3D, 0xC3, 0x3B, 0x3D, +0x23, 0xE5, 0x08, 0x44, 0x4D, 0xE1, 0xD1, 0xC9, +0x23, 0x23, 0xCD, 0x73, 0x3D, 0x5F, 0x23, 0xCD, +0x73, 0x3D, 0x57, 0xEB, 0x11, 0x06, 0x00, 0x19, +0x44, 0x4D, 0xC9, 0x3A, 0xCE, 0xF7, 0xEE, 0xFF, +0xA4, 0x67, 0xC9, 0x3A, 0xCE, 0xF7, 0xB7, 0xCA, +0x7E, 0x3D, 0xCD, 0x05, 0x3B, 0xC9, 0x7E, 0xC9, +0x21, 0xDE, 0x10, 0xCD, 0x5F, 0x02, 0xF5, 0xF7, +0x30, 0x50, 0xF1, 0xC2, 0x55, 0x39, 0x2A, 0x69, +0xF6, 0x22, 0xC7, 0xF7, 0xCD, 0x70, 0x3B, 0xEB, +0xED, 0xE5, 0xCD, 0xD7, 0x3D, 0xEB, 0xE1, 0x7E, +0xFE, 0x80, 0xCA, 0xC1, 0x3D, 0xFE, 0xA0, 0xCA, +0xB8, 0x3D, 0xFE, 0xC0, 0xCA, 0xB2, 0x3D, 0xC3, +0x55, 0x39, 0xF7, 0xB5, 0x2A, 0xC3, 0xBB, 0x3D, +0xF7, 0xCE, 0x2A, 0xF7, 0x62, 0x2C, 0xC3, 0xC4, +0x3D, 0xF7, 0x0C, 0x2B, 0xCD, 0xBE, 0x3E, 0xCA, +0x1B, 0x39, 0x2A, 0x69, 0xF6, 0xEB, 0x2A, 0xC7, +0xF7, 0xF7, 0x16, 0x83, 0xC3, 0x1B, 0x39, 0xCD, +0x73, 0x3D, 0xF5, 0x23, 0xCD, 0x73, 0x3D, 0xF5, +0x23, 0xCD, 0x73, 0x3D, 0x67, 0xF1, 0x6F, 0xCD, +0x6B, 0x3D, 0xF1, 0xC9, 0x3A, 0xBA, 0xF7, 0xB7, +0xCA, 0x5A, 0x39, 0xCD, 0x70, 0x3B, 0xEB, 0xED, +0xE5, 0xCD, 0x0E, 0x3D, 0x60, 0x69, 0x22, 0xC5, +0xF7, 0xE1, 0x11, 0x70, 0xEF, 0xD5, 0x01, 0x0B, +0x00, 0xCD, 0x14, 0x3F, 0xE1, 0xE5, 0xCD, 0x1C, +0x1F, 0x2A, 0xBF, 0xF7, 0x7C, 0xB5, 0xC2, 0xFF, +0x3E, 0x2A, 0xC1, 0xF7, 0x7C, 0xB5, 0xCA, 0xFF, +0x3E, 0xD1, 0x1A, 0x77, 0xF5, 0x23, 0x23, 0x23, +0x13, 0x13, 0x13, 0x0E, 0x08, 0xCD, 0xF5, 0x02, +0xF1, 0xFE, 0x80, 0xCA, 0x43, 0x3E, 0xFE, 0xA0, +0xCA, 0x61, 0x3E, 0xFE, 0xC0, 0xCA, 0x80, 0x3E, +0xC3, 0xFF, 0x3E, 0x2A, 0x95, 0xF2, 0x22, 0xC3, +0xF7, 0x2B, 0x22, 0xBF, 0xF7, 0xCD, 0x93, 0x3E, +0x2A, 0xC5, 0xF7, 0xEB, 0x2A, 0x61, 0xF6, 0x19, +0x22, 0x61, 0xF6, 0xCD, 0xE0, 0x3E, 0xC3, 0x1B, +0x39, 0x2A, 0x63, 0xF6, 0xE5, 0x2A, 0x65, 0xF6, +0x22, 0xC3, 0xF7, 0x22, 0xBF, 0xF7, 0xCD, 0x93, +0x3E, 0xE1, 0xE5, 0x22, 0x63, 0xF6, 0xCD, 0xE0, +0x3E, 0xE1, 0x22, 0x63, 0xF6, 0xC3, 0x1B, 0x39, +0x2A, 0x63, 0xF6, 0x22, 0xC3, 0xF7, 0x2B, 0x22, +0xBF, 0xF7, 0xCD, 0x93, 0x3E, 0xCD, 0xE0, 0x3E, +0xC3, 0x1B, 0x39, 0x2A, 0xC5, 0xF7, 0xE5, 0x2A, +0x69, 0xF6, 0x22, 0xC7, 0xF7, 0xCD, 0xBE, 0x3E, +0xCA, 0xB3, 0x3E, 0xD1, 0xD5, 0x2A, 0x69, 0xF6, +0xE5, 0x19, 0x09, 0x2B, 0xD1, 0xEB, 0x09, 0x2B, +0xF7, 0x21, 0x83, 0xC1, 0x2A, 0xC3, 0xF7, 0xF7, +0xA8, 0x82, 0xDA, 0xFF, 0x3E, 0xC9, 0x3A, 0xB4, +0xF7, 0xB7, 0xC8, 0xE5, 0xD5, 0x2A, 0xC7, 0xF7, +0xEB, 0xAF, 0x4F, 0x47, 0xED, 0x23, 0x7C, 0xB5, +0xCA, 0xD9, 0x3E, 0x13, 0x13, 0x0C, 0xC3, 0xCC, +0x3E, 0x0C, 0x79, 0x07, 0x4F, 0xD1, 0xE1, 0xC9, +0x2A, 0xC5, 0xF7, 0x44, 0x4D, 0x2A, 0xC3, 0xF7, +0xEB, 0x2A, 0x71, 0xEF, 0xCD, 0x6B, 0x3D, 0xCD, +0x14, 0x3F, 0x2A, 0xC1, 0xF7, 0x23, 0xEB, 0x2A, +0xBF, 0xF7, 0xD9, 0xF7, 0x62, 0x2C, 0xC9, 0x21, +0x05, 0x3F, 0xC3, 0x55, 0x1B, 0x43, 0x6F, 0x70, +0x79, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x2E, +0x2E, 0x2E, 0x2E, 0x00, 0xE5, 0xC5, 0xD5, 0xCD, +0x96, 0x19, 0xD1, 0xC1, 0xE1, 0xE5, 0xC5, 0xD5, +0x3A, 0xBE, 0xF7, 0xCD, 0x83, 0xF8, 0xCD, 0xD3, +0x17, 0xD1, 0xC1, 0xE1, 0xC9, 0xCD, 0x84, 0x0A, +0xCA, 0x55, 0x39, 0xCD, 0x70, 0x3B, 0xEB, 0xED, +0x23, 0x23, 0x23, 0x11, 0x70, 0xEF, 0x0E, 0x06, +0xCD, 0xF5, 0x02, 0xC3, 0x1B, 0x39, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + diff --git a/src/tsdosimages.c b/src/tsdosimages.c new file mode 100644 index 0000000..d6328a1 --- /dev/null +++ b/src/tsdosimages.c @@ -0,0 +1,8017 @@ +/* Image for TS-DOS, M100 version */ +const unsigned char gTsDos100Image[] = { +0xC3, 0xB2, 0x00, 0xE1, 0xD1, 0xC1, 0xF1, 0xC9, +0xC3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xCF, 0x10, 0x00, 0xC9, 0x00, 0x00, 0x00, 0x00, +0xC3, 0x6C, 0x00, 0xD3, 0xE0, 0xC9, 0x3E, 0x20, +0xCF, 0x20, 0x00, 0xC9, 0xF3, 0xCD, 0x97, 0x00, +0xE1, 0xC3, 0x03, 0x00, 0xF3, 0xCD, 0x97, 0x00, +0xF1, 0xF1, 0xC9, 0x00, 0xF3, 0xCD, 0x97, 0x00, +0xC3, 0xA6, 0x00, 0x00, 0xF3, 0xCD, 0x97, 0x00, +0xF5, 0x3A, 0x45, 0xFF, 0x3C, 0xD3, 0xE0, 0xF7, +0x11, 0x05, 0xF6, 0x3C, 0xD3, 0xE0, 0xAF, 0x2A, +0x49, 0x00, 0xD3, 0xE0, 0xDF, 0xFE, 0x01, 0xD8, +0x21, 0x1D, 0x11, 0x22, 0xE0, 0xFA, 0x22, 0xF2, +0xF5, 0xCD, 0x05, 0x29, 0x24, 0x6F, 0x03, 0xC7, +0x00, 0xCD, 0xA4, 0xFA, 0x7C, 0x92, 0xC0, 0x7D, +0x93, 0xC9, 0x01, 0x08, 0x00, 0x1A, 0x77, 0x13, +0x23, 0x0B, 0x78, 0xB1, 0xC2, 0x75, 0x00, 0xC9, +0x22, 0xB2, 0xF9, 0xE1, 0xD5, 0x5E, 0x23, 0x56, +0x23, 0xE3, 0xEB, 0xE5, 0x21, 0xA4, 0xFA, 0xE3, +0xE5, 0x2A, 0xB2, 0xF9, 0xC3, 0xA6, 0x00, 0x22, +0xB4, 0xF9, 0x21, 0xA4, 0xFA, 0xE3, 0x2B, 0x2B, +0x2B, 0x2B, 0xE5, 0x2A, 0xB4, 0xF9, 0xF5, 0xE5, +0x21, 0x88, 0x14, 0xE3, 0x3A, 0x45, 0xFF, 0xC3, +0x1B, 0x00, 0xF3, 0xFE, 0x08, 0xD2, 0x00, 0x01, +0x47, 0xC5, 0xD5, 0xE5, 0x11, 0x40, 0x00, 0x21, +0xA4, 0xFA, 0xCD, 0x72, 0x00, 0x01, 0x24, 0x00, +0x21, 0x05, 0xF6, 0xCD, 0x75, 0x00, 0xE1, 0xD1, +0xF1, 0xFB, 0xC3, 0x00, 0x01, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x7C, 0xB5, 0xCA, 0x00, 0x70, 0xE1, 0xCD, 0x17, +0x01, 0xC3, 0x35, 0x35, 0x7E, 0x12, 0x23, 0x13, +0x0B, 0x78, 0xB1, 0xC2, 0x0C, 0x01, 0xC9, 0x21, +0xE1, 0x01, 0xE5, 0x23, 0x01, 0x08, 0x00, 0x11, +0x93, 0xFC, 0xCD, 0x0C, 0x01, 0xEB, 0xED, 0x22, +0xC4, 0xFC, 0x13, 0x13, 0xEB, 0x22, 0xC8, 0xFC, +0xCD, 0xD1, 0x01, 0xCD, 0xCD, 0x01, 0xC1, 0xC0, +0x2A, 0x9A, 0xF9, 0x22, 0xC2, 0xFC, 0x0A, 0x32, +0xC6, 0xFC, 0xCD, 0x85, 0x01, 0xD8, 0xE5, 0x2A, +0xC4, 0xFC, 0x44, 0x4D, 0xC5, 0x2A, 0xC2, 0xFC, +0xCD, 0xDD, 0x01, 0xDA, 0x82, 0x01, 0x2A, 0xC2, +0xFC, 0xEB, 0x2A, 0xC8, 0xFC, 0xC1, 0xCD, 0x0C, +0x01, 0xD1, 0xD5, 0x2A, 0xAE, 0xFB, 0x2B, 0x22, +0x9A, 0xF9, 0x23, 0xEB, 0x2A, 0xC4, 0xFC, 0x19, +0x22, 0xAE, 0xFB, 0xD1, 0x2A, 0xC2, 0xFC, 0xEB, +0x3A, 0xC6, 0xFC, 0xCD, 0xD5, 0x01, 0xCD, 0xD1, +0x01, 0xC9, 0xE1, 0xE1, 0xC9, 0x21, 0xAF, 0xF9, +0x01, 0x0B, 0x00, 0x09, 0x7E, 0xFE, 0xFF, 0xCA, +0x97, 0x01, 0x87, 0xDA, 0x8B, 0x01, 0xC9, 0x37, +0xC9, 0xCF, 0xA8, 0x42, 0xC9, 0xCF, 0x8A, 0x42, +0xC9, 0xCF, 0x7C, 0x5A, 0xC9, 0xCF, 0xCB, 0x12, +0xC9, 0xCF, 0x42, 0x72, 0xC9, 0xCF, 0xB5, 0x13, +0xC9, 0xCF, 0xB1, 0x1B, 0xC9, 0xCF, 0x31, 0x42, +0xC9, 0xCF, 0x69, 0x42, 0xC9, 0xCF, 0x6E, 0x42, +0xC9, 0xCF, 0xDB, 0x13, 0xC9, 0xCF, 0x3F, 0x42, +0xC9, 0xCF, 0x00, 0x00, 0xC9, 0xCF, 0xAF, 0x20, +0xC9, 0xCF, 0x46, 0x21, 0xC9, 0xCF, 0x39, 0x22, +0xC9, 0xCF, 0x25, 0x58, 0xC9, 0xCF, 0x6D, 0x6B, +0xC9, 0x80, 0x54, 0x53, 0x2D, 0x44, 0x4F, 0x53, +0x20, 0x20, 0x0F, 0x00, 0x0E, 0x80, 0x0A, 0x00, +0xB9, 0x36, 0x33, 0x30, 0x31, 0x33, 0x2C, 0x31, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x21, 0xC0, 0xFC, +0x06, 0xB4, 0xAF, 0xCD, 0x34, 0x4A, 0x21, 0x00, +0x00, 0x39, 0x22, 0xCE, 0xFC, 0x3E, 0x01, 0xCD, +0x85, 0x4A, 0xAF, 0x32, 0xD4, 0xFC, 0x32, 0xDA, +0xFC, 0x32, 0xD9, 0xFC, 0x32, 0xCA, 0xFC, 0x3C, +0x32, 0xCD, 0xFC, 0x21, 0x64, 0x35, 0x22, 0xD0, +0xFC, 0xCD, 0x27, 0x4C, 0xCD, 0x5A, 0x4C, 0xCD, +0x11, 0x36, 0x3A, 0xD5, 0xFC, 0x32, 0xCD, 0xFC, +0xCD, 0x2F, 0x36, 0x21, 0xB5, 0x48, 0xE5, 0xF5, +0xFE, 0x02, 0xD2, 0xB9, 0x35, 0x3A, 0xCC, 0xFC, +0xA7, 0xCA, 0xB9, 0x35, 0x3A, 0xD6, 0xFC, 0x4F, +0x0C, 0x06, 0x00, 0xC5, 0x3A, 0xCD, 0xFC, 0x32, +0xD5, 0xFC, 0xCD, 0xC4, 0x3A, 0xC1, 0x04, 0x0D, +0xCA, 0xB5, 0x48, 0x78, 0x32, 0xD5, 0xFC, 0x32, +0xCD, 0xFC, 0xC5, 0xCD, 0xB2, 0x3A, 0x2A, 0xE4, +0xFC, 0x2B, 0x7E, 0xFE, 0x3E, 0xC2, 0x8C, 0x35, +0xC1, 0xF1, 0x21, 0x8C, 0x35, 0xF5, 0xC5, 0xE5, +0xF5, 0xCD, 0x56, 0x4C, 0x3A, 0xD9, 0xFC, 0xB7, +0xCA, 0xE2, 0x35, 0xF1, 0xA7, 0xCA, 0x2E, 0x3B, +0x3D, 0xCA, 0x73, 0x3D, 0x3D, 0xCA, 0x9F, 0x3D, +0x3D, 0x3D, 0xCA, 0x53, 0x3D, 0x3D, 0x3D, 0xCA, +0x00, 0x3D, 0x3D, 0xE1, 0xCA, 0xFE, 0x35, 0xC3, +0x64, 0x35, 0xF1, 0xA7, 0xCA, 0x4B, 0x3C, 0x3D, +0xCA, 0x2B, 0x3C, 0x3D, 0xCA, 0xF8, 0x3A, 0x3D, +0x3D, 0xCA, 0x5C, 0x3E, 0x3D, 0x3D, 0x3D, 0xE1, +0xCA, 0xFE, 0x35, 0xC3, 0x64, 0x35, 0xCD, 0xC4, +0x4A, 0xCD, 0xD7, 0x4B, 0xCD, 0x27, 0x4C, 0xCD, +0x5A, 0x4C, 0x21, 0x00, 0x00, 0xE5, 0xC3, 0xA6, +0x00, 0x21, 0x01, 0x01, 0x22, 0x39, 0xF6, 0x21, +0x69, 0x3E, 0xCD, 0x2C, 0x4A, 0xAF, 0x32, 0xCC, +0xFC, 0x3E, 0x01, 0x32, 0xD5, 0xFC, 0x21, 0x02, +0x02, 0x22, 0x39, 0xF6, 0xC3, 0x3B, 0x38, 0x3A, +0xCD, 0xFC, 0x32, 0xD5, 0xFC, 0xCD, 0xB2, 0x3A, +0x3A, 0xD5, 0xFC, 0x3D, 0x37, 0x3F, 0x07, 0x5F, +0x16, 0x00, 0x21, 0x85, 0xF6, 0x19, 0xEB, 0x21, +0x07, 0x23, 0x22, 0x39, 0xF6, 0xCD, 0x2B, 0x4C, +0xED, 0xCD, 0x2F, 0x4C, 0xCD, 0x3E, 0x4C, 0xCD, +0x33, 0x4C, 0xCD, 0xFE, 0x3D, 0xCD, 0xEF, 0x4B, +0xCA, 0x5A, 0x36, 0xDA, 0x0C, 0x38, 0xFE, 0x0D, +0xCA, 0x22, 0x37, 0xFE, 0x17, 0xCA, 0xAA, 0x37, +0xFE, 0x14, 0xCA, 0x98, 0x37, 0xFE, 0x5D, 0xCA, +0x98, 0x37, 0xFE, 0x3F, 0xCA, 0x77, 0x37, 0xFE, +0x02, 0xCA, 0x77, 0x37, 0xFE, 0x1E, 0xCA, 0xEE, +0x36, 0xFE, 0x1F, 0xCA, 0xFC, 0x36, 0xFE, 0x1D, +0xCA, 0xDD, 0x36, 0xFE, 0x1C, 0xCA, 0xCA, 0x36, +0xFE, 0x20, 0xCA, 0xCA, 0x36, 0xE6, 0xDF, 0xFE, +0x52, 0xCA, 0x59, 0x37, 0xFE, 0x54, 0xCA, 0xEE, +0x37, 0xFE, 0x41, 0xCA, 0x15, 0x37, 0xFE, 0x47, +0xCA, 0x15, 0x37, 0xFE, 0x55, 0xCA, 0xAE, 0x37, +0xFE, 0x44, 0xCA, 0xB9, 0x39, 0xFE, 0x4C, 0xCA, +0xC2, 0x39, 0xFE, 0x50, 0xCA, 0xC2, 0x39, 0xC3, +0x5A, 0x36, 0x3E, 0x01, 0x21, 0xD5, 0xFC, 0x86, +0x23, 0xBE, 0xDA, 0x0A, 0x37, 0xCA, 0x0A, 0x37, +0x3E, 0x01, 0xC3, 0x0A, 0x37, 0x3A, 0xD5, 0xFC, +0x3D, 0xC2, 0x0A, 0x37, 0x3A, 0xD6, 0xFC, 0xA7, +0xCA, 0x5A, 0x36, 0xC3, 0x0A, 0x37, 0x3A, 0xD5, +0xFC, 0xD6, 0x04, 0xDA, 0x5A, 0x36, 0xCA, 0x5A, +0x36, 0xC3, 0x0A, 0x37, 0x3E, 0x04, 0x21, 0xD5, +0xFC, 0x86, 0x4F, 0x23, 0x7E, 0xB9, 0xDA, 0x5A, +0x36, 0x79, 0xF5, 0xCD, 0xC4, 0x3A, 0xF1, 0x32, +0xCD, 0xFC, 0xC3, 0x2F, 0x36, 0x3E, 0x3E, 0xCD, +0xCA, 0x37, 0x3E, 0x01, 0x32, 0xCC, 0xFC, 0xC3, +0x2F, 0x36, 0x3A, 0xCB, 0xFC, 0xFE, 0x02, 0xC2, +0x5A, 0x36, 0x2A, 0xE4, 0xFC, 0x01, 0x07, 0x00, +0x09, 0x7E, 0xFE, 0x3C, 0xC2, 0x5A, 0x36, 0xCD, +0x3B, 0x4A, 0x2A, 0xE4, 0xFC, 0xCD, 0x95, 0x3D, +0xCD, 0x8A, 0x40, 0x21, 0x02, 0x00, 0xCD, 0x9B, +0x40, 0x2A, 0xE4, 0xFC, 0x11, 0xC0, 0xFC, 0x01, +0x09, 0x00, 0xCD, 0x05, 0x4A, 0xAF, 0xC3, 0x8A, +0x37, 0x3A, 0xD9, 0xFC, 0xA7, 0xC2, 0x2F, 0x36, +0x2A, 0xE4, 0xFC, 0xCD, 0x02, 0x49, 0xCD, 0x51, +0x4A, 0xFE, 0xC0, 0xCC, 0x00, 0x50, 0xCD, 0x0F, +0x4C, 0xCD, 0x11, 0x36, 0xC3, 0x2F, 0x36, 0x3A, +0xD9, 0xFC, 0xA7, 0xCA, 0x5A, 0x36, 0x3A, 0xD6, +0xFC, 0xFE, 0x14, 0xDA, 0x5A, 0x36, 0x3A, 0xD4, +0xFC, 0x3C, 0x32, 0xD4, 0xFC, 0x3E, 0x01, 0x32, +0xCD, 0xFC, 0xCD, 0x11, 0x36, 0xC3, 0x2F, 0x36, +0x3A, 0xD9, 0xFC, 0xA7, 0xCA, 0x5A, 0x36, 0x3A, +0xD4, 0xFC, 0xA7, 0xCA, 0x5A, 0x36, 0x3D, 0xC3, +0x8A, 0x37, 0xAF, 0xC3, 0x8A, 0x37, 0x3E, 0x20, +0xCD, 0xCA, 0x37, 0xAF, 0x32, 0xCC, 0xFC, 0xC3, +0x2F, 0x36, 0x3A, 0xCB, 0xFC, 0x3D, 0xC2, 0x5A, +0x36, 0x3A, 0xCA, 0xFC, 0xEE, 0x01, 0x32, 0xCA, +0xFC, 0xC9, 0x32, 0xCC, 0xFC, 0x3A, 0xD6, 0xFC, +0xA7, 0xC8, 0xAF, 0x3C, 0x32, 0xD5, 0xFC, 0xCD, +0xCD, 0x3A, 0x2A, 0xE4, 0xFC, 0x2B, 0x3A, 0xCC, +0xFC, 0xE7, 0x3A, 0xD5, 0xFC, 0x21, 0xD6, 0xFC, +0xBE, 0xDA, 0xD3, 0x37, 0xA7, 0xC9, 0xCD, 0xCD, +0x3A, 0xCD, 0x2F, 0x4C, 0x2A, 0xE4, 0xFC, 0x2B, +0x3E, 0x3E, 0xBE, 0xC2, 0x00, 0x38, 0x3E, 0x20, +0xE7, 0xCD, 0x33, 0x4C, 0x21, 0xCC, 0xFC, 0x36, +0x01, 0xC3, 0xCA, 0x36, 0xFE, 0x08, 0xD2, 0x5A, +0x36, 0xFE, 0x05, 0xCA, 0x33, 0x38, 0xFE, 0x03, +0xC0, 0x3A, 0xD9, 0xFC, 0xEE, 0x01, 0x32, 0xD9, +0xFC, 0xAF, 0x32, 0xD4, 0xFC, 0x3E, 0x01, 0x32, +0xCD, 0xFC, 0xCD, 0x27, 0x4C, 0xCD, 0x11, 0x36, +0xC3, 0x2F, 0x36, 0x3A, 0xD9, 0xFC, 0xA7, 0xC8, +0xC3, 0xAA, 0x37, 0x21, 0x85, 0xF6, 0x22, 0xDB, +0xFC, 0xAF, 0x77, 0x23, 0x77, 0x3A, 0xD9, 0xFC, +0xA7, 0xCA, 0x5D, 0x39, 0xAF, 0x32, 0xDA, 0xFC, +0xCD, 0x35, 0x47, 0xC2, 0x0F, 0x39, 0x3A, 0xD4, +0xFC, 0xA7, 0xCA, 0x71, 0x38, 0x32, 0xDA, 0xFC, +0xCD, 0x42, 0x47, 0x3A, 0xDA, 0xFC, 0x3D, 0xC2, +0x5D, 0x38, 0xAF, 0x32, 0xDA, 0xFC, 0x32, 0xD6, +0xFC, 0xCD, 0x42, 0x47, 0x3A, 0xD6, 0xFC, 0xFE, +0x14, 0xDC, 0xAA, 0x39, 0x3A, 0xCB, 0xFC, 0xA7, +0xCA, 0x9F, 0x38, 0x3D, 0xCA, 0x8D, 0x38, 0x21, +0xC0, 0xFC, 0xC3, 0xA5, 0x38, 0x21, 0x01, 0x24, +0x22, 0x39, 0xF6, 0xCD, 0x2F, 0x4C, 0x3E, 0x23, +0xE7, 0x3A, 0xCA, 0xFC, 0xC6, 0x30, 0xE7, 0xCD, +0x33, 0x4C, 0xC3, 0xB8, 0x38, 0xE5, 0x21, 0x01, +0x21, 0x22, 0x39, 0xF6, 0xCD, 0x2F, 0x4C, 0xE1, +0x0E, 0x06, 0xCD, 0xE5, 0x48, 0xCD, 0x33, 0x4C, +0x21, 0x97, 0x3E, 0x01, 0x36, 0x39, 0x3A, 0xD9, +0xFC, 0xA7, 0xC2, 0xCB, 0x38, 0x21, 0xD9, 0x3E, +0x01, 0x22, 0x39, 0xC5, 0xE5, 0x3A, 0xCD, 0xFC, +0x21, 0xD6, 0xFC, 0xBE, 0xDA, 0xDD, 0x38, 0x7E, +0xA7, 0xC2, 0xDD, 0x38, 0x3C, 0x32, 0xD5, 0xFC, +0x21, 0x07, 0x0B, 0x22, 0x39, 0xF6, 0xE1, 0xCD, +0x2C, 0x4A, 0x3A, 0xD9, 0xFC, 0xA7, 0xCA, 0x05, +0x39, 0x3A, 0xCB, 0xFC, 0xA7, 0xCA, 0x05, 0x39, +0x21, 0xE9, 0x3F, 0x3D, 0xCA, 0x02, 0x39, 0x21, +0xD8, 0x3F, 0xCD, 0x2C, 0x4A, 0xCD, 0x40, 0x39, +0x21, 0x07, 0x15, 0x22, 0x39, 0xF6, 0xC9, 0xAF, +0xCD, 0xAA, 0x39, 0x21, 0x97, 0x3E, 0x01, 0x1C, +0x39, 0xC3, 0xCB, 0x38, 0x21, 0x3C, 0x3F, 0xC3, +0x2C, 0x4A, 0x2A, 0xB2, 0xFB, 0xEB, 0x2A, 0x78, +0xF6, 0x7D, 0x93, 0x6F, 0x7C, 0x9A, 0x67, 0x01, +0xF2, 0xFF, 0x09, 0xC3, 0x3E, 0x4C, 0xCD, 0x10, +0x4A, 0xCD, 0x3E, 0x4C, 0x3E, 0x30, 0xE7, 0xC9, +0x3A, 0xD9, 0xFC, 0xA7, 0xC0, 0x3A, 0x2C, 0xFB, +0x11, 0xF2, 0x3F, 0xFE, 0xDB, 0xCA, 0x53, 0x39, +0x11, 0xF6, 0x3F, 0x21, 0x08, 0x19, 0x22, 0x39, +0xF6, 0xEB, 0xC3, 0x2C, 0x4A, 0x21, 0xBA, 0xF9, +0xAF, 0x32, 0xD6, 0xFC, 0x3E, 0x14, 0x3D, 0xF5, +0x7E, 0xEE, 0x80, 0xE6, 0x9F, 0xC2, 0x96, 0x39, +0xE5, 0x23, 0x5E, 0x23, 0x56, 0xE3, 0xE5, 0xCD, +0xD3, 0x3C, 0xEB, 0xCD, 0x91, 0x47, 0xE1, 0xE3, +0x23, 0x0E, 0x06, 0xCD, 0xE5, 0x48, 0x3E, 0x2E, +0xE7, 0x0E, 0x02, 0xCD, 0xE5, 0x48, 0x3E, 0x20, +0xE7, 0x21, 0xD6, 0xFC, 0x34, 0xE1, 0x11, 0x0B, +0x00, 0x19, 0xF1, 0x3D, 0xC2, 0x67, 0x39, 0x3A, +0xD6, 0xFC, 0xFE, 0x14, 0xDC, 0xAA, 0x39, 0xC3, +0x7C, 0x38, 0xF5, 0x21, 0xCD, 0x3F, 0xCD, 0x2C, +0x4A, 0xF1, 0x3C, 0xFE, 0x14, 0xC2, 0xAA, 0x39, +0xC9, 0xCD, 0xA8, 0x3A, 0xCD, 0x52, 0x4C, 0xC3, +0x2F, 0x36, 0x32, 0xDF, 0xFC, 0x11, 0x07, 0x00, +0x2A, 0xE4, 0xFC, 0x19, 0x7E, 0xFE, 0x44, 0xC2, +0x2F, 0x36, 0x23, 0x7E, 0xFE, 0x4F, 0xC2, 0x06, +0x3A, 0xCD, 0x49, 0x3A, 0x3A, 0xDF, 0xFC, 0xFE, +0x4C, 0xCC, 0x27, 0x4C, 0xC4, 0xA8, 0x3A, 0xCD, +0x24, 0x3A, 0xF5, 0xCD, 0x6B, 0x3A, 0xF1, 0xCA, +0xE7, 0x39, 0x3A, 0xDF, 0xFC, 0xFE, 0x4C, 0xC2, +0x00, 0x3A, 0x3E, 0x07, 0xE7, 0xCD, 0xF8, 0x3D, +0xCD, 0x27, 0x4C, 0xC3, 0xB5, 0x48, 0x3A, 0xD9, +0xFC, 0xA7, 0xC2, 0x2F, 0x36, 0x2A, 0xE4, 0xFC, +0xCD, 0x02, 0x49, 0xCD, 0x51, 0x4A, 0xFE, 0xC0, +0xCC, 0x04, 0x50, 0xCD, 0x0F, 0x4C, 0xCD, 0x11, +0x36, 0xC3, 0x2F, 0x36, 0x3A, 0xD9, 0xFC, 0xA7, +0xC2, 0xB6, 0x40, 0x2A, 0xDD, 0xFC, 0x01, 0x80, +0x00, 0x79, 0x08, 0xD2, 0x3A, 0x3A, 0x09, 0x7D, +0x6C, 0x4F, 0x22, 0xDD, 0xFC, 0x2A, 0xE0, 0xFC, +0xE5, 0x09, 0x22, 0xE0, 0xFC, 0xE1, 0xFE, 0x80, +0xC9, 0xCD, 0x3B, 0x4A, 0x2A, 0xE4, 0xFC, 0x3A, +0xD9, 0xFC, 0xA7, 0xC2, 0x65, 0x3A, 0xCD, 0x4B, +0x4A, 0xD5, 0xCD, 0xD3, 0x3C, 0x22, 0xDD, 0xFC, +0xE1, 0x22, 0xE0, 0xFC, 0xC9, 0xCD, 0x95, 0x3D, +0xC3, 0x8A, 0x40, 0xEB, 0xB7, 0xC8, 0x4F, 0x3A, +0xDF, 0xFC, 0xFE, 0x4C, 0xC2, 0x82, 0x3A, 0xCD, +0x8F, 0x3A, 0x1A, 0xE7, 0x13, 0x0D, 0xC2, 0x77, +0x3A, 0xC9, 0xCD, 0x8F, 0x3A, 0x1A, 0xCD, 0x42, +0x4C, 0x13, 0x0D, 0xC2, 0x82, 0x3A, 0xC9, 0xCD, +0x4A, 0x4C, 0xC8, 0xCD, 0xEB, 0x4B, 0xFE, 0x03, +0xCA, 0x00, 0x3A, 0xFE, 0x1B, 0xCA, 0x00, 0x3A, +0xFE, 0x20, 0xC2, 0x8F, 0x3A, 0xC3, 0xEB, 0x4B, +0xDB, 0xBB, 0xE6, 0x06, 0xEE, 0x02, 0xC2, 0x7B, +0x48, 0xC9, 0xCD, 0xCD, 0x3A, 0x22, 0xE4, 0xFC, +0xCD, 0x2F, 0x4C, 0x2B, 0x0E, 0x0A, 0xCD, 0xE5, +0x48, 0xC3, 0x33, 0x4C, 0xCD, 0x33, 0x4C, 0xCD, +0xCD, 0x3A, 0xC3, 0xBB, 0x3A, 0x3A, 0xD5, 0xFC, +0x3D, 0x6F, 0x26, 0x00, 0x11, 0x0A, 0x00, 0xCD, +0x1F, 0x4C, 0x11, 0x28, 0xFE, 0x19, 0x23, 0xE5, +0x01, 0x00, 0xFE, 0x08, 0x11, 0x28, 0x00, 0xEB, +0xCD, 0x1B, 0x4C, 0x7D, 0x3C, 0x32, 0x39, 0xF6, +0xEB, 0x10, 0x7D, 0x32, 0x3A, 0xF6, 0xE1, 0xC9, +0xCD, 0x4B, 0x4A, 0x22, 0xE0, 0xFC, 0x21, 0x4A, +0x3F, 0xCD, 0x1A, 0x3E, 0xC8, 0xCD, 0x02, 0x49, +0x2A, 0xE0, 0xFC, 0x01, 0x09, 0x00, 0x09, 0x11, +0x99, 0xFC, 0x7E, 0x12, 0x13, 0x23, 0x7E, 0x12, +0xCD, 0x51, 0x4A, 0xC2, 0x7E, 0x48, 0x2A, 0xE0, +0xFC, 0x23, 0x23, 0x23, 0x11, 0x93, 0xFC, 0x01, +0x06, 0x00, 0xEB, 0xC3, 0x05, 0x4A, 0xCD, 0x3B, +0x4A, 0x2A, 0xE4, 0xFC, 0xCD, 0x95, 0x3D, 0x3A, +0xCC, 0xFC, 0xA7, 0xC2, 0x56, 0x3B, 0x21, 0x7A, +0x3F, 0xCD, 0x1A, 0x3E, 0xCA, 0x56, 0x3B, 0xCD, +0x02, 0x49, 0x01, 0x02, 0x00, 0x21, 0xEF, 0xFC, +0x11, 0x99, 0xFC, 0xCD, 0x05, 0x4A, 0xCD, 0x51, +0x4A, 0xCA, 0x69, 0x3B, 0x21, 0xB0, 0x3F, 0xCD, +0xF4, 0x48, 0xCD, 0xEE, 0x3D, 0xC0, 0xCD, 0x38, +0x3C, 0x2A, 0x1D, 0xFD, 0x7C, 0x65, 0x6F, 0x22, +0x1D, 0xFD, 0x3A, 0xEF, 0xFC, 0xFE, 0x44, 0xC2, +0x82, 0x3B, 0x2A, 0xAE, 0xFB, 0x3E, 0xC0, 0xC3, +0xA3, 0x3B, 0xFE, 0x43, 0xC2, 0x95, 0x3B, 0x2A, +0xB0, 0xFB, 0x22, 0xD5, 0xFC, 0x2A, 0xB2, 0xFB, +0x3E, 0xA0, 0xC3, 0xA3, 0x3B, 0x2A, 0x1D, 0xFD, +0x22, 0xD5, 0xFC, 0x2A, 0x9A, 0xF9, 0x22, 0xE0, +0xFC, 0x3E, 0x80, 0x32, 0xDF, 0xFC, 0x22, 0xE2, +0xFC, 0x2A, 0x1D, 0xFD, 0x22, 0xDD, 0xFC, 0xE5, +0xC1, 0x3A, 0xDF, 0xFC, 0xFE, 0xA0, 0xCA, 0xC0, +0x3B, 0x03, 0xFE, 0x80, 0xC2, 0xC0, 0x3B, 0x03, +0xC5, 0xCD, 0x48, 0x3E, 0xDA, 0x87, 0x48, 0xC1, +0xE5, 0xC5, 0x2A, 0xE2, 0xFC, 0xCD, 0x0B, 0x4C, +0xDA, 0x8A, 0x48, 0x2A, 0xE2, 0xFC, 0xC1, 0x36, +0x00, 0x23, 0x0B, 0x79, 0xB0, 0xC2, 0xD7, 0x3B, +0x2B, 0xD1, 0x3A, 0xDF, 0xFC, 0xFE, 0xC0, 0xC2, +0xF3, 0x3B, 0x36, 0x1A, 0x2A, 0xE2, 0xFC, 0x2B, +0xC3, 0x1B, 0x3C, 0xFE, 0xA0, 0xC2, 0x04, 0x3C, +0x2A, 0xD5, 0xFC, 0x22, 0xB0, 0xFB, 0x2A, 0xE2, +0xFC, 0xC3, 0x1B, 0x3C, 0xD5, 0x2A, 0xAE, 0xFB, +0x2B, 0x22, 0x9A, 0xF9, 0x23, 0xEB, 0x2A, 0xD5, +0xFC, 0x23, 0x23, 0x19, 0x22, 0xAE, 0xFB, 0xD1, +0x2A, 0xE0, 0xFC, 0xEB, 0xCD, 0x17, 0x4C, 0xCD, +0x27, 0x41, 0xCD, 0x0F, 0x4C, 0x21, 0x02, 0x00, +0xC3, 0x9B, 0x40, 0x3A, 0xCC, 0xFC, 0xA7, 0xCC, +0xE1, 0x3D, 0x2A, 0xE4, 0xFC, 0xCD, 0x02, 0x49, +0xCD, 0x51, 0x4A, 0xFE, 0xC0, 0xCA, 0xFF, 0x4B, +0xFE, 0xA0, 0xCA, 0x07, 0x4C, 0xFE, 0x80, 0xCA, +0x03, 0x4C, 0xC9, 0xCD, 0x3B, 0x4A, 0xCD, 0x4B, +0x4A, 0xD5, 0xE5, 0x23, 0x23, 0x23, 0x11, 0xE8, +0xFC, 0x01, 0x06, 0x00, 0xCD, 0x05, 0x4A, 0x3E, +0x2E, 0x12, 0x13, 0x01, 0x02, 0x00, 0xCD, 0x05, +0x4A, 0x3A, 0xCC, 0xFC, 0xA7, 0xC2, 0x88, 0x3C, +0x21, 0x71, 0x3F, 0xCD, 0x1A, 0x3E, 0xCA, 0x88, +0x3C, 0xCD, 0x02, 0x49, 0x01, 0x06, 0x00, 0x11, +0xE8, 0xFC, 0x21, 0x93, 0xFC, 0xCD, 0x05, 0x4A, +0xE1, 0xD1, 0xD5, 0xCD, 0xD3, 0x3C, 0x7C, 0xB5, +0xCA, 0x84, 0x48, 0xE5, 0x3E, 0x01, 0x32, 0xD6, +0xFC, 0xCD, 0x43, 0x49, 0xCD, 0x72, 0x4A, 0xCA, +0xCE, 0x3C, 0x21, 0x8B, 0x3F, 0xCD, 0xF4, 0x48, +0xCD, 0xF8, 0x3D, 0xE6, 0xDF, 0xE7, 0xFE, 0x52, +0xC2, 0xBC, 0x3C, 0xCD, 0x1A, 0x43, 0xCD, 0x72, +0x4A, 0xC3, 0xCE, 0x3C, 0xE1, 0xD1, 0xFE, 0x41, +0xC0, 0x3A, 0xEF, 0xFC, 0xFE, 0x44, 0xC0, 0x3E, +0x02, 0x32, 0xD6, 0xFC, 0xD5, 0xE5, 0xE1, 0xD1, +0xC3, 0xC8, 0x40, 0x7E, 0xFE, 0xC0, 0xCA, 0xE6, +0x3C, 0xFE, 0xA0, 0xCA, 0xF5, 0x3C, 0xD5, 0xCD, +0x13, 0x4C, 0xC1, 0x08, 0x2B, 0xC9, 0xEB, 0x11, +0x00, 0x00, 0x7E, 0x23, 0x13, 0xFE, 0x1A, 0xC2, +0xEA, 0x3C, 0x1B, 0xEB, 0xC9, 0xEB, 0x23, 0x23, +0x4E, 0x23, 0x46, 0x21, 0x06, 0x00, 0x09, 0xC9, +0x3A, 0xCB, 0xFC, 0xA7, 0xC8, 0x3D, 0xCA, 0xBA, +0x37, 0xCD, 0x3B, 0x4A, 0x21, 0x61, 0x3F, 0xCD, +0x1A, 0x3E, 0xC8, 0xCD, 0x02, 0x49, 0x21, 0x93, +0xFC, 0x11, 0xE8, 0xFC, 0x01, 0x06, 0x00, 0xCD, +0x05, 0x4A, 0x21, 0x3C, 0x3E, 0x22, 0xEF, 0xFC, +0x3E, 0x2E, 0x32, 0xEE, 0xFC, 0xCD, 0x43, 0x49, +0x3A, 0xCB, 0xFC, 0xFE, 0x02, 0xC0, 0xCD, 0x72, +0x4A, 0xC2, 0x4D, 0x3D, 0x3E, 0x01, 0x32, 0xE8, +0xFC, 0x21, 0x01, 0x01, 0xCD, 0x9B, 0x40, 0x21, +0x02, 0x00, 0xC3, 0x9B, 0x40, 0xCD, 0x8A, 0x40, +0xC3, 0x47, 0x3D, 0x3A, 0xCB, 0xFC, 0xFE, 0x02, +0xC8, 0x21, 0x1B, 0x3F, 0xCD, 0xF4, 0x48, 0xCD, +0xEE, 0x3D, 0xC0, 0xCD, 0x43, 0x49, 0xCD, 0xE3, +0x49, 0x21, 0x06, 0x00, 0xCD, 0x9B, 0x40, 0x3E, +0x07, 0xE7, 0xC9, 0x3A, 0xCC, 0xFC, 0xA7, 0xCC, +0xE1, 0x3D, 0xCD, 0x3B, 0x4A, 0xCD, 0x83, 0x3D, +0xC3, 0x1A, 0x43, 0x01, 0x09, 0x00, 0x2A, 0xE4, +0xFC, 0x11, 0xE8, 0xFC, 0xCD, 0x05, 0x4A, 0xCD, +0x43, 0x49, 0xC3, 0x72, 0x4A, 0xCD, 0x02, 0x49, +0x21, 0x93, 0xFC, 0xCD, 0x57, 0x4A, 0xC9, 0xCD, +0x3B, 0x4A, 0xCD, 0x83, 0x3D, 0x21, 0xE8, 0xFC, +0x11, 0x9C, 0xFC, 0x01, 0x09, 0x00, 0xCD, 0x05, +0x4A, 0x2A, 0x1D, 0xFD, 0x4C, 0x45, 0x21, 0xC0, +0x7C, 0x08, 0x21, 0x4A, 0x3F, 0xC2, 0xD7, 0x3D, +0x01, 0x09, 0x00, 0xCD, 0x1D, 0x3E, 0xC8, 0xE5, +0xF5, 0xCD, 0x3B, 0x4A, 0xF1, 0xE1, 0x11, 0xE8, +0xFC, 0x4F, 0x06, 0x00, 0xC3, 0xB0, 0x41, 0xCD, +0x1A, 0x3E, 0xC8, 0xCD, 0x02, 0x49, 0xC3, 0xA7, +0x41, 0x21, 0x83, 0x3F, 0xCD, 0xF4, 0x48, 0xCD, +0xEE, 0x3D, 0xC2, 0xB5, 0x48, 0xC9, 0xCD, 0xF8, +0x3D, 0xE7, 0xFE, 0x59, 0xC8, 0xFE, 0x79, 0xC9, +0xCD, 0xFE, 0x3D, 0xC3, 0xEB, 0x4B, 0xAF, 0x3D, +0x32, 0x56, 0xF6, 0xCD, 0x4A, 0x4C, 0xCA, 0xFE, +0x3D, 0xAF, 0x32, 0x56, 0xF6, 0x21, 0x32, 0xF9, +0xB6, 0xCA, 0xF7, 0x4B, 0xCD, 0xF3, 0x4B, 0xC3, +0xFE, 0x3D, 0x01, 0x06, 0x00, 0xCD, 0x2F, 0x3E, +0xC8, 0xE5, 0xF5, 0xCD, 0x5E, 0x4C, 0x77, 0x23, +0xA7, 0xC2, 0x23, 0x3E, 0xF1, 0xE1, 0xC9, 0xC5, +0xCD, 0xF4, 0x48, 0xCD, 0x46, 0x4C, 0xDA, 0xB5, +0x48, 0x23, 0x78, 0x3D, 0xD1, 0xC8, 0xBB, 0xD8, +0xE5, 0x19, 0x36, 0x00, 0xE1, 0x7B, 0xB7, 0xC9, +0x21, 0xAF, 0xF9, 0x01, 0x0B, 0x00, 0x09, 0x7E, +0xFE, 0xFF, 0xCA, 0x5A, 0x3E, 0x87, 0xDA, 0x4E, +0x3E, 0xC9, 0x37, 0xC9, 0x2A, 0x2C, 0xFB, 0x01, +0xDB, 0x08, 0x08, 0xCA, 0x1F, 0x40, 0xC3, 0xFA, +0x3F, 0x1B, 0x70, 0x20, 0x54, 0x53, 0x2D, 0x44, +0x4F, 0x53, 0x20, 0x28, 0x31, 0x30, 0x30, 0x20, +0x76, 0x34, 0x2E, 0x30, 0x30, 0x29, 0x20, 0x28, +0x63, 0x29, 0x38, 0x37, 0x2C, 0x54, 0x53, 0x49, +0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x1B, 0x71, 0x20, 0x00, 0x44, +0x49, 0x53, 0x4B, 0x20, 0x46, 0x72, 0x65, 0x65, +0x3A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x46, 0x69, 0x6C, 0x65, 0x3A, 0x0D, +0x0A, 0x4C, 0x6F, 0x61, 0x64, 0x20, 0x4B, 0x69, +0x6C, 0x6C, 0x20, 0x4E, 0x61, 0x6D, 0x65, 0x20, +0x52, 0x61, 0x6D, 0x20, 0x20, 0x46, 0x72, 0x6D, +0x74, 0x20, 0x4C, 0x6F, 0x67, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x20, 0x4D, 0x65, 0x6E, 0x75, +0x00, 0x20, 0x52, 0x41, 0x4D, 0x20, 0x46, 0x72, +0x65, 0x65, 0x3A, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x20, 0x46, 0x69, 0x6C, 0x65, +0x3A, 0x0D, 0x0A, 0x53, 0x61, 0x76, 0x65, 0x20, +0x4B, 0x69, 0x6C, 0x6C, 0x20, 0x4E, 0x61, 0x6D, +0x65, 0x20, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x44, +0x4F, 0x53, 0x2D, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4D, 0x65, +0x6E, 0x75, 0x00, 0x49, 0x6E, 0x73, 0x65, 0x72, +0x74, 0x20, 0x44, 0x69, 0x73, 0x6B, 0x2C, 0x20, +0x50, 0x72, 0x65, 0x73, 0x73, 0x20, 0x22, 0x59, +0x22, 0x20, 0x74, 0x6F, 0x20, 0x62, 0x65, 0x67, +0x69, 0x6E, 0x20, 0x00, 0x4E, 0x4F, 0x54, 0x20, +0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x54, 0x45, +0x44, 0x00, 0x4E, 0x65, 0x77, 0x20, 0x4E, 0x61, +0x6D, 0x65, 0x3A, 0x00, 0x53, 0x79, 0x73, 0x74, +0x65, 0x6D, 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3A, +0x00, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, +0x72, 0x79, 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3A, +0x00, 0x53, 0x61, 0x76, 0x65, 0x20, 0x61, 0x73, +0x3A, 0x00, 0x4C, 0x6F, 0x61, 0x64, 0x20, 0x61, +0x73, 0x3A, 0x00, 0x53, 0x75, 0x72, 0x65, 0x20, +0x3F, 0x20, 0x00, 0x46, 0x69, 0x6C, 0x65, 0x20, +0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x2C, 0x20, +0x41, 0x29, 0x70, 0x70, 0x65, 0x6E, 0x64, 0x20, +0x52, 0x29, 0x65, 0x70, 0x6C, 0x61, 0x63, 0x65, +0x20, 0x51, 0x29, 0x75, 0x69, 0x74, 0x3A, 0x00, +0x46, 0x69, 0x6C, 0x65, 0x20, 0x65, 0x78, 0x69, +0x73, 0x74, 0x73, 0x2C, 0x20, 0x52, 0x65, 0x70, +0x6C, 0x61, 0x63, 0x65, 0x3F, 0x20, 0x28, 0x59, +0x2F, 0x4E, 0x29, 0x3A, 0x00, 0x2D, 0x2E, 0x2D, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, +0x1B, 0x59, 0x37, 0x34, 0x20, 0x20, 0x20, 0x20, +0x1B, 0x59, 0x37, 0x3E, 0x4D, 0x6B, 0x44, 0x72, +0x00, 0x1B, 0x59, 0x37, 0x3E, 0x42, 0x61, 0x6E, +0x6B, 0x00, 0x4F, 0x46, 0x46, 0x00, 0x4F, 0x4E, +0x20, 0x00, 0x21, 0xF3, 0x7F, 0x22, 0xE6, 0xFA, +0x22, 0x08, 0xFB, 0x22, 0x0A, 0xFB, 0x22, 0xF0, +0xFA, 0x22, 0xF4, 0xFA, 0x21, 0xDB, 0x08, 0x22, +0x2C, 0xFB, 0x22, 0x32, 0xFB, 0x22, 0x34, 0xFB, +0x22, 0x36, 0xFB, 0x22, 0x38, 0xFB, 0xC9, 0xCD, +0xFA, 0x3F, 0x21, 0x84, 0x40, 0x11, 0x3D, 0xF9, +0x01, 0x06, 0x00, 0xCD, 0x05, 0x4A, 0x21, 0x3D, +0xF9, 0x22, 0xF4, 0xFA, 0x22, 0xF0, 0xFA, 0x22, +0x38, 0xFB, 0x22, 0x36, 0xFB, 0x22, 0x08, 0xFB, +0x22, 0x0A, 0xFB, 0x22, 0x2C, 0xFB, 0x22, 0x32, +0xFB, 0x22, 0x34, 0xFB, 0xC9, 0xF5, 0x3A, 0xC9, +0xFA, 0xFE, 0x1A, 0xCA, 0x51, 0x44, 0xFE, 0x16, +0xCA, 0xE7, 0x44, 0xFE, 0x5E, 0xCA, 0xC1, 0x43, +0xFE, 0x5C, 0xCA, 0x0D, 0x44, 0xFE, 0x2E, 0xCA, +0x24, 0x43, 0xFE, 0x30, 0xCA, 0x1D, 0x45, 0xFE, +0x52, 0xCA, 0x46, 0x43, 0xFE, 0x58, 0xCA, 0x77, +0x43, 0xFE, 0x5A, 0xCA, 0x96, 0x43, 0xF1, 0x1E, +0x02, 0xC3, 0x37, 0x4C, 0xCD, 0xA4, 0xFA, 0xC3, +0x4D, 0x40, 0x21, 0x01, 0x01, 0x3E, 0x03, 0x32, +0xE8, 0xFC, 0xC3, 0x9B, 0x40, 0x67, 0x2E, 0x04, +0xC3, 0xA7, 0x40, 0xCD, 0x22, 0x48, 0xCD, 0xF0, +0x49, 0xCD, 0xCC, 0x47, 0xC3, 0xF8, 0x47, 0x22, +0x02, 0xFD, 0x21, 0x02, 0xFD, 0xCD, 0x28, 0x48, +0xCD, 0xCC, 0x47, 0xC3, 0xF8, 0x47, 0x21, 0x03, +0x00, 0xCD, 0x22, 0x48, 0xCD, 0xCC, 0x47, 0x3A, +0x03, 0xFD, 0x21, 0x04, 0xFD, 0xFE, 0x80, 0xC9, +0xD5, 0xE5, 0xCD, 0x01, 0x41, 0xE1, 0x22, 0xD5, +0xFC, 0xE1, 0x11, 0x04, 0xFD, 0x01, 0x80, 0x00, +0xCD, 0x05, 0x4A, 0xE5, 0x2A, 0xD5, 0xFC, 0x01, +0x80, 0x00, 0x08, 0xDA, 0xF4, 0x40, 0xCA, 0xF4, +0x40, 0x22, 0xD5, 0xFC, 0x3E, 0x80, 0xCD, 0x95, +0x40, 0xC3, 0xD1, 0x40, 0xE1, 0x3A, 0xD5, 0xFC, +0xCD, 0x95, 0x40, 0x21, 0x02, 0x00, 0xC3, 0x9B, +0x40, 0x11, 0x00, 0x05, 0xEB, 0xCD, 0x1B, 0x4C, +0x3A, 0x1F, 0xFD, 0x95, 0xDA, 0x81, 0x48, 0xCA, +0x81, 0x48, 0x3A, 0xD6, 0xFC, 0x32, 0xE8, 0xFC, +0x21, 0x01, 0x01, 0xC3, 0x9B, 0x40, 0x2A, 0xE2, +0xFC, 0xCD, 0x0B, 0x4C, 0xDA, 0x8A, 0x48, 0x2A, +0xE2, 0xFC, 0xE5, 0xCD, 0x8A, 0x40, 0xCD, 0xB6, +0x40, 0x4F, 0x06, 0x00, 0xD1, 0xCD, 0x05, 0x4A, +0xD5, 0x3A, 0x03, 0xFD, 0x2A, 0xDD, 0xFC, 0x4F, +0x06, 0x00, 0x08, 0x22, 0xDD, 0xFC, 0xDA, 0x4E, +0x41, 0x7D, 0xB4, 0xC2, 0x2E, 0x41, 0xD1, 0xC9, +0x3A, 0xDD, 0xFC, 0xFE, 0x01, 0xC8, 0xCD, 0x98, +0x49, 0x3E, 0x57, 0x32, 0xD3, 0xFC, 0xCD, 0xCE, +0x42, 0xCD, 0x98, 0x49, 0xCD, 0x76, 0x41, 0x2A, +0xE4, 0xFC, 0xCD, 0xD9, 0x48, 0x22, 0xE4, 0xFC, +0xCD, 0xEE, 0x42, 0xC3, 0x50, 0x41, 0x3A, 0x09, +0xFD, 0xCD, 0x91, 0x41, 0xFE, 0x35, 0xCA, 0x89, +0x41, 0x21, 0xDE, 0xFC, 0x34, 0x7E, 0xFE, 0x14, +0xC0, 0x21, 0xDD, 0xFC, 0x34, 0x23, 0x36, 0x01, +0xC9, 0x01, 0x00, 0x05, 0xFE, 0x35, 0xC8, 0x01, +0x40, 0x00, 0xC9, 0x21, 0x08, 0x00, 0xCD, 0x22, +0x48, 0xCD, 0xD3, 0x49, 0xC3, 0x98, 0x49, 0x21, +0x93, 0xFC, 0x11, 0xE8, 0xFC, 0x01, 0x06, 0x00, +0xCD, 0x05, 0x4A, 0x3A, 0xCB, 0xFC, 0xA7, 0xC2, +0x58, 0x42, 0xCD, 0x72, 0x4A, 0xC2, 0x7E, 0x48, +0x11, 0x00, 0x05, 0xCD, 0x08, 0x43, 0x21, 0x00, +0x01, 0x22, 0xDD, 0xFC, 0xCD, 0x9B, 0x41, 0xCD, +0x7E, 0x42, 0x2A, 0xB6, 0xFB, 0xE5, 0x06, 0x28, +0x11, 0x9C, 0xFC, 0xCD, 0x69, 0x42, 0xDA, 0x7B, +0x48, 0x78, 0xA7, 0xCA, 0x7B, 0x48, 0xE5, 0x11, +0xE8, 0xFC, 0xEB, 0x01, 0x09, 0x00, 0xCD, 0x05, +0x4A, 0xE1, 0xE5, 0x11, 0x20, 0xFD, 0x01, 0x1F, +0x00, 0xCD, 0x05, 0x4A, 0xD1, 0xD5, 0x21, 0x1F, +0x00, 0x19, 0xE5, 0x2A, 0xB6, 0xFB, 0x01, 0x00, +0x05, 0x09, 0xC1, 0xC5, 0x08, 0xE3, 0xC1, 0xCD, +0x05, 0x4A, 0x2A, 0xB6, 0xFB, 0x06, 0x27, 0x11, +0x20, 0xFD, 0xCD, 0x69, 0x42, 0xE5, 0x2A, 0xB6, +0xFB, 0x01, 0xFF, 0x04, 0x09, 0xE5, 0x01, 0x1F, +0x00, 0x08, 0xD1, 0xC1, 0xC5, 0xE5, 0x08, 0xE5, +0xC1, 0x03, 0xE1, 0xCD, 0x4E, 0x4C, 0x21, 0x20, +0xFD, 0xD1, 0x01, 0x1F, 0x00, 0xCD, 0x05, 0x4A, +0x21, 0x01, 0x14, 0x22, 0xDE, 0xFC, 0xE1, 0xE1, +0x22, 0xE4, 0xFC, 0x21, 0x00, 0x01, 0x22, 0xDD, +0xFC, 0xCD, 0x50, 0x41, 0xCD, 0xCD, 0x49, 0xC9, +0x21, 0x0D, 0x19, 0xCD, 0x22, 0x48, 0xCD, 0xCC, +0x47, 0x3A, 0x04, 0xFD, 0xA7, 0xC2, 0x7E, 0x48, +0xC9, 0x0E, 0x09, 0xCD, 0x1C, 0x4A, 0xC8, 0xD8, +0x7E, 0xB7, 0xC8, 0xC5, 0x01, 0x1F, 0x00, 0x09, +0xC1, 0x05, 0xC8, 0xC3, 0x69, 0x42, 0x2A, 0xE2, +0xFC, 0xCD, 0x98, 0x42, 0x3A, 0xDD, 0xFC, 0x3D, +0xC8, 0xC3, 0x81, 0x42, 0xCD, 0x7E, 0x6D, 0x77, +0x23, 0x0B, 0x79, 0xB0, 0xC2, 0x89, 0xFD, 0xC9, +0xE5, 0x3E, 0x52, 0x32, 0xD3, 0xFC, 0xCD, 0xCE, +0x42, 0xCD, 0x76, 0x41, 0xCD, 0x62, 0x48, 0xC5, +0x21, 0x8C, 0x42, 0x01, 0x0C, 0x00, 0x11, 0x89, +0xFD, 0xCD, 0x05, 0x4A, 0x3E, 0x0D, 0xCD, 0x5F, +0x48, 0xCD, 0xDB, 0x4B, 0xC1, 0xE1, 0xCF, 0x89, +0xFD, 0xC9, 0x06, 0x2F, 0xD6, 0x0A, 0x04, 0xD2, +0xC4, 0x42, 0xC6, 0x3A, 0x4F, 0xC9, 0x3A, 0xDD, +0xFC, 0xCD, 0xC2, 0x42, 0x3A, 0xD3, 0xFC, 0xCD, +0x5F, 0x48, 0xCD, 0xDB, 0x49, 0x3A, 0xDE, 0xFC, +0xCD, 0xC2, 0x42, 0x3E, 0x2C, 0xCD, 0x5F, 0x48, +0xCD, 0xDB, 0x49, 0xCD, 0xD3, 0x49, 0x21, 0x04, +0xFD, 0xE5, 0x0E, 0x08, 0xCD, 0xE5, 0x47, 0x0D, +0xC2, 0xF4, 0x42, 0xE1, 0x7E, 0xFE, 0x30, 0xC8, +0xFE, 0x42, 0xCA, 0x6D, 0x48, 0xC3, 0x67, 0x48, +0x2A, 0xB6, 0xFB, 0xE5, 0x22, 0xE2, 0xFC, 0x21, +0xC0, 0xFF, 0x39, 0xC1, 0x08, 0xDF, 0xDA, 0x8A, +0x48, 0xC9, 0xAF, 0x32, 0x01, 0xFD, 0x21, 0x05, +0x00, 0xC3, 0x9B, 0x40, 0xF1, 0xFE, 0x30, 0xDA, +0xA6, 0x00, 0xFE, 0x32, 0xD2, 0xA6, 0x00, 0xD6, +0x30, 0x32, 0xCA, 0xFC, 0x23, 0x1D, 0x7E, 0xFE, +0x3A, 0xC2, 0xA6, 0x00, 0x23, 0x1D, 0xE3, 0xE1, +0x3E, 0x09, 0xB7, 0xC3, 0xA6, 0x00, 0xF1, 0xD5, +0xE5, 0xF5, 0xAF, 0xCD, 0x85, 0x4A, 0x38, 0x02, +0xED, 0x7E, 0xA7, 0xCA, 0x6A, 0x43, 0xFE, 0x3A, +0xCA, 0x6A, 0x43, 0xCD, 0xCF, 0x4B, 0x7B, 0xFE, +0x02, 0xD2, 0x70, 0x43, 0x32, 0xCA, 0xFC, 0x38, +0x02, 0xD9, 0xCD, 0x04, 0x47, 0xCD, 0xC4, 0x4A, +0xF1, 0xE1, 0xD1, 0xC1, 0xC3, 0xA6, 0x00, 0xF1, +0xFE, 0x09, 0xC2, 0x16, 0x45, 0xD5, 0xE5, 0xF5, +0xAF, 0xCD, 0x85, 0x4A, 0x21, 0x93, 0xFC, 0xCD, +0x57, 0x4A, 0xCA, 0x7B, 0x48, 0xCD, 0x1A, 0x43, +0xCD, 0xC4, 0x4A, 0xC3, 0x70, 0x43, 0xF1, 0xFE, +0x09, 0xC2, 0x16, 0x45, 0xD5, 0xE5, 0xF5, 0xAF, +0xCD, 0x85, 0x4A, 0x21, 0x9C, 0xFC, 0xCD, 0x57, +0x4A, 0xCA, 0x7B, 0x48, 0x21, 0xE8, 0xFC, 0x11, +0x9C, 0xFC, 0x01, 0x09, 0x00, 0xCD, 0x05, 0x4A, +0xCD, 0xA7, 0x41, 0xCD, 0xC4, 0x4A, 0xC3, 0x70, +0x43, 0xF1, 0xFE, 0x09, 0xC2, 0xA6, 0x00, 0xC1, +0xE5, 0x01, 0x43, 0x4F, 0xCD, 0xBA, 0x44, 0xCA, +0x7B, 0x48, 0xCD, 0x8A, 0x40, 0x2A, 0x1D, 0xFD, +0x7D, 0x6C, 0x67, 0x22, 0xDD, 0xFC, 0xCD, 0xB6, +0x40, 0xCD, 0x6A, 0x4C, 0xE5, 0xCD, 0x6E, 0x4C, +0x2A, 0xCE, 0xFA, 0xE5, 0xE5, 0x2A, 0xF4, 0xF5, +0xE3, 0xC1, 0x08, 0xDA, 0x8A, 0x48, 0xD1, 0xE1, +0x3A, 0x03, 0xFD, 0xD6, 0x06, 0x4F, 0x06, 0x00, +0xCD, 0x35, 0x41, 0xCD, 0xC4, 0x4A, 0x21, 0x1A, +0x25, 0xE5, 0xC3, 0xA6, 0x00, 0xF1, 0xFE, 0x09, +0xC2, 0xA6, 0x00, 0xCD, 0x72, 0x4C, 0x01, 0x43, +0x4F, 0xCD, 0xBA, 0x44, 0xC2, 0x7E, 0x48, 0x3E, +0x01, 0x32, 0xD6, 0xFC, 0x2A, 0xD0, 0xFA, 0x01, +0x06, 0x00, 0xC5, 0x09, 0xE5, 0xCD, 0x01, 0x41, +0xE1, 0x22, 0xD5, 0xFC, 0xC1, 0x21, 0xCE, 0xFA, +0x11, 0x04, 0xFD, 0xCD, 0x05, 0x4A, 0x2A, 0x04, +0xFD, 0x01, 0x7A, 0x00, 0xCD, 0xD8, 0x40, 0xCD, +0xC4, 0x4A, 0x21, 0x01, 0x05, 0xE5, 0xC3, 0xA6, +0x00, 0xF1, 0xFE, 0x09, 0xC2, 0xA6, 0x00, 0xC1, +0xF1, 0xF5, 0xC5, 0xCA, 0xA6, 0x00, 0x9F, 0x32, +0x92, 0xFC, 0x01, 0x42, 0x41, 0xCD, 0xBA, 0x44, +0xCA, 0x7B, 0x48, 0x2A, 0x1D, 0xFD, 0x4C, 0x45, +0x60, 0x69, 0x22, 0xDD, 0xFC, 0xCD, 0xAB, 0x44, +0x23, 0x22, 0xE2, 0xFC, 0x2A, 0xDD, 0xFC, 0xE5, +0xE5, 0xC1, 0xCD, 0x1E, 0x41, 0xD1, 0x2A, 0xAE, +0xFB, 0x19, 0x22, 0xAE, 0xFB, 0x2A, 0xD8, 0xFA, +0x19, 0x22, 0xD8, 0xFA, 0xCD, 0xC4, 0x4A, 0xAF, +0x21, 0xF5, 0x23, 0xE5, 0xC3, 0xA6, 0x00, 0xAF, +0xD3, 0xE0, 0xCD, 0xFF, 0x20, 0xCD, 0xA4, 0xFA, +0xC3, 0x78, 0x44, 0x21, 0x9F, 0x44, 0x11, 0x89, +0xFD, 0x01, 0x0C, 0x00, 0xCD, 0x05, 0x4A, 0xC3, +0x89, 0xFD, 0xF5, 0xE5, 0xD5, 0xC5, 0x2A, 0x99, +0xFC, 0x11, 0x20, 0x20, 0xDF, 0xCA, 0xD6, 0x44, +0xD1, 0xD5, 0xDF, 0xCA, 0xD6, 0x44, 0xC1, 0xD1, +0xE1, 0xF1, 0xC1, 0xC3, 0xA6, 0x00, 0xE1, 0x22, +0x99, 0xFC, 0xD1, 0xE1, 0xF1, 0xAF, 0xCD, 0x85, +0x4A, 0x21, 0x93, 0xFC, 0xC3, 0x57, 0x4A, 0xF1, +0xFE, 0x09, 0xC2, 0xA6, 0x00, 0x01, 0x42, 0x41, +0xCD, 0xBA, 0x44, 0xC2, 0x7E, 0x48, 0xCD, 0x66, +0x4C, 0x2A, 0x7C, 0xF6, 0xEB, 0xDF, 0xCA, 0x0F, +0x45, 0xD5, 0xC1, 0x08, 0x3E, 0x01, 0x32, 0xD6, +0xFC, 0xCD, 0xC8, 0x40, 0xCD, 0xC4, 0x4A, 0x21, +0x02, 0x05, 0xE5, 0xC3, 0xA6, 0x00, 0x21, 0xDB, +0x08, 0xE5, 0xC3, 0xA6, 0x00, 0xAF, 0x32, 0xD2, +0xFC, 0xF1, 0x22, 0xCE, 0xFC, 0xD5, 0xE5, 0xF5, +0x11, 0x04, 0x00, 0x19, 0x7E, 0xFE, 0x09, 0xCA, +0x38, 0x45, 0xF1, 0xE1, 0xD1, 0xC3, 0xA6, 0x00, +0xF1, 0xF5, 0xFE, 0x00, 0xCA, 0x5C, 0x45, 0xFE, +0x02, 0xCA, 0xE8, 0x45, 0xFE, 0x04, 0xCA, 0xB0, +0x46, 0xFE, 0x06, 0xCA, 0x07, 0x46, 0xFE, 0x08, +0xC2, 0x32, 0x45, 0x38, 0x06, 0x21, 0x1B, 0x16, +0xD9, 0xC3, 0x32, 0x45, 0xAF, 0xCD, 0x85, 0x4A, +0x21, 0x99, 0xFC, 0x7E, 0xFE, 0x20, 0xCA, 0x6E, +0x45, 0xFE, 0x44, 0xC2, 0x8D, 0x48, 0x36, 0x44, +0x23, 0x36, 0x4F, 0x21, 0x93, 0xFC, 0xCD, 0x57, +0x4A, 0x4F, 0xCD, 0x5B, 0x46, 0x36, 0x00, 0xE1, +0xE1, 0xD1, 0xD5, 0xE5, 0x51, 0x7B, 0xE6, 0x07, +0x21, 0xE4, 0x4A, 0x4F, 0x06, 0x00, 0x09, 0x7E, +0x3D, 0xCA, 0xCD, 0x45, 0x3D, 0xC2, 0xE0, 0x45, +0x3A, 0x1C, 0xFD, 0xA7, 0xC2, 0xA1, 0x45, 0x23, +0x23, 0x7E, 0x32, 0xE8, 0xFC, 0x21, 0x01, 0x01, +0xCD, 0x9B, 0x40, 0x2A, 0xCE, 0xFC, 0x11, 0x07, +0x00, 0x19, 0xAF, 0x77, 0x23, 0x54, 0x5D, 0x23, +0x23, 0xD9, 0xE1, 0xD1, 0x7B, 0xFE, 0x08, 0xC2, +0xC4, 0x45, 0x1E, 0x02, 0x73, 0xE3, 0x21, 0xDE, +0x14, 0xE3, 0xC3, 0xA6, 0x00, 0x7A, 0xB7, 0xCA, +0xA1, 0x45, 0xE5, 0xCD, 0x1A, 0x43, 0x21, 0x93, +0xFC, 0xCD, 0x57, 0x4A, 0xE1, 0xC3, 0xA1, 0x45, +0x7A, 0xB7, 0xCA, 0x7B, 0x48, 0xC3, 0xA1, 0x45, +0xF1, 0xE1, 0xD1, 0xE5, 0x7E, 0x36, 0x00, 0xFE, +0x02, 0xCC, 0xDD, 0x46, 0x21, 0x02, 0x00, 0xCD, +0x9B, 0x40, 0xCD, 0xC4, 0x4A, 0xE1, 0xE3, 0xE1, +0x21, 0x59, 0x4D, 0xE5, 0xC3, 0xA6, 0x00, 0xCD, +0x5B, 0x46, 0x7E, 0x36, 0x00, 0xA7, 0xC2, 0x27, +0x46, 0x2A, 0xCE, 0xFC, 0x01, 0x07, 0x00, 0x09, +0x7E, 0x23, 0xE5, 0xA7, 0xCC, 0x63, 0x46, 0xD1, +0xED, 0x7E, 0x23, 0xD9, 0x1B, 0xEB, 0x35, 0xFE, +0x1A, 0x37, 0x3F, 0xC2, 0x33, 0x46, 0xCD, 0x5B, +0x46, 0x77, 0x37, 0xF5, 0x38, 0x10, 0xED, 0x01, +0x9A, 0x18, 0x08, 0xC2, 0x4F, 0x46, 0xCD, 0x5B, +0x46, 0xF1, 0x77, 0x4F, 0x9F, 0xCD, 0xCB, 0x4B, +0x38, 0x12, 0xEB, 0xF9, 0xC3, 0xA6, 0x00, 0xF1, +0xE1, 0xE1, 0xD1, 0xE3, 0x21, 0x8A, 0x4E, 0xE3, +0xC3, 0xA6, 0x00, 0x2A, 0xA2, 0xFA, 0x11, 0x91, +0xFA, 0x19, 0xC9, 0x21, 0x03, 0x00, 0xCD, 0x22, +0x48, 0xCD, 0xCC, 0x47, 0x3A, 0x02, 0xFD, 0xFE, +0x10, 0xC2, 0x9E, 0x46, 0x3A, 0x03, 0xFD, 0x2A, +0xCE, 0xFC, 0x11, 0x08, 0x00, 0x19, 0xE5, 0x54, +0x5D, 0x23, 0x23, 0xD9, 0x11, 0x04, 0xFD, 0xEB, +0x4F, 0x06, 0x00, 0xCD, 0x05, 0x4A, 0x3A, 0x03, +0xFD, 0xFE, 0x80, 0xCA, 0x9A, 0x46, 0xEB, 0x36, +0x1A, 0x3C, 0xE1, 0x2B, 0x77, 0xC9, 0x2A, 0xCE, +0xFC, 0x11, 0x07, 0x00, 0x19, 0x36, 0x01, 0x23, +0x54, 0x5D, 0x23, 0x23, 0xD9, 0x36, 0x1A, 0xC9, +0x2A, 0xCE, 0xFC, 0x11, 0x07, 0x00, 0x19, 0x7E, +0xFE, 0x80, 0xCC, 0xDD, 0x46, 0xF1, 0xE1, 0xD1, +0xE1, 0xF1, 0xF5, 0xFE, 0x1A, 0xCA, 0xD6, 0x46, +0x2A, 0xCE, 0xFC, 0x11, 0x07, 0x00, 0x19, 0x34, +0x23, 0xEB, 0xED, 0x77, 0x23, 0xD9, 0x21, 0xEA, +0x14, 0xE5, 0xC3, 0xA6, 0x00, 0x2A, 0xCE, 0xFC, +0x01, 0x07, 0x00, 0x09, 0x7E, 0xE5, 0x23, 0x23, +0x23, 0x11, 0x04, 0xFD, 0x4F, 0x06, 0x00, 0xF5, +0xCD, 0x05, 0x4A, 0xF1, 0xA7, 0xC4, 0x95, 0x40, +0xE1, 0x36, 0x00, 0x23, 0x54, 0x5D, 0x23, 0x23, +0xD9, 0xC9, 0xF1, 0xC9, 0x21, 0x85, 0xF6, 0x22, +0xDB, 0xFC, 0xCD, 0x35, 0x47, 0xC2, 0x6A, 0x48, +0xAF, 0x32, 0xDA, 0xFC, 0x32, 0xD4, 0xFC, 0x3D, +0x32, 0xD7, 0xFC, 0x3E, 0x01, 0x32, 0x3A, 0xF6, +0xCD, 0x47, 0x47, 0xC3, 0x23, 0x4C, 0xCD, 0x10, +0x4A, 0xCD, 0x3E, 0x4C, 0x21, 0xD1, 0x4A, 0xCD, +0x2C, 0x4A, 0xC3, 0x23, 0x4C, 0xAF, 0x32, 0xD6, +0xFC, 0xCD, 0x43, 0x49, 0x21, 0x46, 0x01, 0xC3, +0x6F, 0x47, 0x3E, 0x14, 0x32, 0xD7, 0xFC, 0x3A, +0xCB, 0xFC, 0xA7, 0xC2, 0x57, 0x47, 0x21, 0xF6, +0x02, 0xCD, 0x6F, 0x47, 0xC2, 0xF8, 0x47, 0x3A, +0x04, 0xFD, 0xA7, 0xC8, 0x3A, 0xDA, 0xFC, 0xA7, +0xCC, 0x81, 0x47, 0x21, 0xD6, 0xFC, 0x34, 0x3A, +0xD7, 0xFC, 0xBE, 0xC2, 0x4E, 0x47, 0xC9, 0x22, +0x00, 0xFD, 0x21, 0x00, 0x1A, 0xCD, 0x22, 0x48, +0xCD, 0xCC, 0x47, 0x3A, 0x02, 0xFD, 0xFE, 0x11, +0xC9, 0x0E, 0x09, 0x21, 0x04, 0xFD, 0xCD, 0xE5, +0x48, 0x3E, 0x20, 0xE7, 0x2A, 0x1D, 0xFD, 0x5C, +0x55, 0x2A, 0xDB, 0xFC, 0xEB, 0xD9, 0xEB, 0x23, +0x23, 0x22, 0xDB, 0xFC, 0xC9, 0x21, 0x02, 0xFD, +0xE5, 0xCD, 0xB2, 0xFD, 0xCD, 0xB2, 0xFD, 0x4F, +0xCD, 0xB2, 0xFD, 0x41, 0x79, 0xA7, 0xCA, 0xA4, +0xFD, 0xCD, 0xB2, 0xFD, 0x0D, 0xC2, 0x9D, 0xFD, +0xE1, 0x04, 0x04, 0xAF, 0x30, 0x86, 0x23, 0x05, +0xC2, 0xA9, 0xFD, 0x2F, 0xBE, 0xC9, 0xCD, 0x7E, +0x6D, 0x77, 0x23, 0xC9, 0x21, 0x9D, 0x47, 0x11, +0x89, 0xFD, 0x01, 0x2F, 0x00, 0xCD, 0x05, 0x4A, +0xCD, 0x62, 0x48, 0xCD, 0xDB, 0x4B, 0xCF, 0x89, +0xFD, 0xC2, 0x6A, 0x48, 0xC9, 0xCD, 0xEB, 0x47, +0x77, 0x23, 0xC9, 0xCD, 0x62, 0x48, 0xCD, 0xE7, +0x4B, 0xDA, 0x8D, 0x48, 0xC2, 0x6A, 0x48, 0xC9, +0x3A, 0x02, 0xFD, 0xFE, 0x12, 0xC2, 0x6A, 0x48, +0x3A, 0x04, 0xFD, 0xA7, 0xC8, 0xFE, 0x10, 0xCA, +0x7E, 0x48, 0xFE, 0x50, 0xCA, 0x6D, 0x48, 0xFE, +0x60, 0xCA, 0x81, 0x48, 0xDA, 0x6A, 0x48, 0xCA, +0x73, 0x48, 0xFE, 0x80, 0xDA, 0x73, 0x48, 0xC3, +0x70, 0x48, 0x22, 0xE6, 0xFC, 0x21, 0xE6, 0xFC, +0xE5, 0x3A, 0xCA, 0xFC, 0xA7, 0xCA, 0x37, 0x48, +0xE6, 0x01, 0x1F, 0x1F, 0x1F, 0xB6, 0x77, 0x7E, +0x23, 0x86, 0x47, 0x7E, 0xF5, 0x23, 0xA7, 0xCA, +0x4B, 0x48, 0x4F, 0x78, 0x86, 0x23, 0x0D, 0xC2, +0x44, 0x48, 0x47, 0x78, 0x2F, 0x57, 0x01, 0x5A, +0x5A, 0xCD, 0xDB, 0x49, 0xC1, 0x48, 0x06, 0x00, +0x03, 0x03, 0xE1, 0xCD, 0xD9, 0x48, 0x7A, 0xCD, +0xE3, 0x4B, 0xDB, 0xBB, 0xE6, 0x20, 0xC8, 0x3E, +0x01, 0x21, 0x3E, 0x02, 0x21, 0x3E, 0x03, 0x21, +0x3E, 0x04, 0x21, 0x3E, 0x05, 0x21, 0xD9, 0xFC, +0x36, 0x00, 0x21, 0x3E, 0x06, 0x21, 0x3E, 0x07, +0x21, 0x3E, 0x08, 0x21, 0x3E, 0x09, 0x21, 0x3E, +0x0A, 0x21, 0x3E, 0x0B, 0x21, 0x3E, 0x0C, 0x21, +0x3E, 0x0D, 0x21, 0x02, 0x4B, 0x4F, 0x0D, 0xCA, +0xA4, 0x48, 0x7E, 0x23, 0xFE, 0x00, 0xC2, 0x9A, +0x48, 0xC3, 0x96, 0x48, 0x3A, 0xD2, 0xFC, 0xA7, +0xCA, 0xD0, 0x48, 0x3E, 0x07, 0xE7, 0x23, 0xCD, +0xF4, 0x48, 0xCD, 0xC7, 0x48, 0x2A, 0xCE, 0xFC, +0xF9, 0x2A, 0xD0, 0xFC, 0xE5, 0xC9, 0xCD, 0x23, +0x4C, 0xCD, 0xC7, 0x48, 0xC3, 0x23, 0x4C, 0x21, +0xBB, 0x4B, 0xCD, 0x2C, 0x4A, 0xC3, 0xEB, 0x4B, +0x5E, 0x2A, 0xCE, 0xFC, 0x36, 0x00, 0xC3, 0x37, +0x4C, 0x7E, 0xCD, 0x5F, 0x48, 0x23, 0x0B, 0x79, +0xB0, 0xC2, 0xD9, 0x48, 0xC9, 0x7E, 0xFE, 0x20, +0xD2, 0xED, 0x48, 0x3E, 0x20, 0xE7, 0x23, 0x0D, +0xC2, 0xE5, 0x48, 0xC9, 0xE5, 0x21, 0x08, 0x01, +0x22, 0x39, 0xF6, 0xCD, 0x2B, 0x4C, 0xE1, 0xC3, +0x2C, 0x4A, 0xE5, 0x3E, 0x20, 0x21, 0x93, 0xFC, +0x06, 0x08, 0xCD, 0x34, 0x4A, 0xE1, 0x11, 0x93, +0xFC, 0x06, 0x06, 0x7E, 0xFE, 0x41, 0xDA, 0x90, +0x48, 0x7E, 0xFE, 0x2E, 0xCA, 0x2B, 0x49, 0xB7, +0xC8, 0x12, 0x23, 0x13, 0x05, 0xC2, 0x19, 0x49, +0xC3, 0x33, 0x49, 0x3E, 0x20, 0x12, 0x13, 0x05, +0xC2, 0x2D, 0x49, 0x06, 0x02, 0x23, 0x7E, 0xB7, +0xC8, 0x12, 0x13, 0x05, 0xC2, 0x35, 0x49, 0x3E, +0x00, 0x12, 0xC9, 0xCD, 0x94, 0x4A, 0xCD, 0xA2, +0x49, 0xCD, 0xCC, 0x47, 0xCD, 0xF8, 0x47, 0x3A, +0xCB, 0xFC, 0xA7, 0xC8, 0x21, 0x08, 0x00, 0xCD, +0x22, 0x48, 0xCD, 0xCC, 0x47, 0x3A, 0x03, 0xFD, +0xFE, 0x01, 0xCA, 0x77, 0x49, 0x3D, 0x4F, 0x3E, +0x02, 0x32, 0xCB, 0xFC, 0x06, 0x00, 0x21, 0x05, +0xFD, 0x11, 0xC0, 0xFC, 0xC3, 0x05, 0x4A, 0x21, +0x23, 0x00, 0xCD, 0x22, 0x48, 0xCD, 0xCC, 0x47, +0x21, 0xE7, 0x4A, 0xCD, 0x8F, 0x49, 0x21, 0xF0, +0x4A, 0xCD, 0x8F, 0x49, 0x21, 0xF9, 0x4A, 0x01, +0x09, 0x00, 0xCD, 0xD9, 0x48, 0xC3, 0xCC, 0x47, +0xCD, 0xDF, 0x4B, 0xC8, 0xCD, 0xEB, 0x47, 0xC3, +0x98, 0x49, 0xCD, 0x62, 0x48, 0xCD, 0xCD, 0x49, +0xCD, 0x98, 0x49, 0xCD, 0x9B, 0x41, 0xCD, 0xD3, +0x49, 0xCD, 0xDF, 0x4B, 0x3E, 0x00, 0xC2, 0xBA, +0x49, 0x3C, 0x32, 0xCB, 0xFC, 0xCD, 0x98, 0x49, +0xCD, 0xCD, 0x49, 0xCD, 0x98, 0x49, 0x21, 0x07, +0x00, 0xCD, 0x22, 0x48, 0xC9, 0x01, 0x31, 0x4D, +0xCD, 0xDB, 0x49, 0x3E, 0x0D, 0xCD, 0x5F, 0x48, +0xC3, 0xE3, 0x49, 0x78, 0xCD, 0x5F, 0x48, 0x79, +0xC3, 0x5F, 0x48, 0x26, 0x14, 0x2E, 0xFF, 0x2D, +0xC2, 0xE7, 0x49, 0x25, 0xC2, 0xE5, 0x49, 0xC9, +0x01, 0x50, 0xFF, 0xCD, 0xE3, 0x49, 0xCD, 0xDF, +0x4B, 0xC0, 0x05, 0xC2, 0xF3, 0x49, 0x0D, 0xC2, +0xF3, 0x49, 0xC3, 0x67, 0x48, 0x7E, 0x12, 0x23, +0x13, 0x0B, 0x78, 0xB1, 0xC2, 0x05, 0x4A, 0xC9, +0x3A, 0x1F, 0xFD, 0x6F, 0x26, 0x00, 0x11, 0x80, +0x00, 0xC3, 0x1F, 0x4C, 0xD5, 0xE5, 0x1A, 0x96, +0xC2, 0x29, 0x4A, 0x23, 0x13, 0x0D, 0xC2, 0x1E, +0x4A, 0xE1, 0xD1, 0xC9, 0x7E, 0xA7, 0xC8, 0xE7, +0x23, 0xC3, 0x2C, 0x4A, 0x77, 0x23, 0x05, 0xC2, +0x34, 0x4A, 0xC9, 0x3E, 0x20, 0x06, 0x18, 0x21, +0xE8, 0xFC, 0xCD, 0x34, 0x4A, 0x3E, 0x46, 0x32, +0x00, 0xFD, 0xC9, 0x2A, 0xE4, 0xFC, 0xCD, 0x02, +0x49, 0xCD, 0x0F, 0x4C, 0xC3, 0xFB, 0x4B, 0xE5, +0xCD, 0x3B, 0x4A, 0xE1, 0x11, 0xE8, 0xFC, 0x01, +0x06, 0x00, 0xCD, 0x05, 0x4A, 0x3E, 0x2E, 0x12, +0x13, 0x01, 0x02, 0x00, 0xCD, 0x05, 0x4A, 0xCD, +0x43, 0x49, 0x3E, 0x00, 0x32, 0x01, 0xFD, 0x21, +0x00, 0x1A, 0xCD, 0x22, 0x48, 0xCD, 0xCC, 0x47, +0x3A, 0x1C, 0xFD, 0xA7, 0xC9, 0x32, 0xD2, 0xFC, +0x11, 0xA8, 0xF9, 0x21, 0x5B, 0xF6, 0x01, 0x05, +0x00, 0xC3, 0x05, 0x4A, 0xCD, 0xD7, 0x4B, 0x21, +0xDE, 0x4A, 0x11, 0x5B, 0xF6, 0x01, 0x05, 0x00, +0xCD, 0x05, 0x4A, 0x21, 0x5B, 0xF6, 0x37, 0xCD, +0xD3, 0x4B, 0xCD, 0x98, 0x49, 0xCD, 0xA2, 0x49, +0xCD, 0xE3, 0x49, 0xCD, 0xDF, 0x4B, 0xC2, 0x98, +0x49, 0xCD, 0xD7, 0x4B, 0x21, 0x5B, 0xF6, 0x35, +0x37, 0xC3, 0xD3, 0x4B, 0x21, 0xA8, 0xF9, 0x7E, +0xD6, 0x3A, 0xDA, 0xD3, 0x4B, 0x23, 0xC3, 0xD3, +0x4B, 0x30, 0x20, 0x42, 0x79, 0x74, 0x65, 0x73, +0x20, 0x66, 0x72, 0x65, 0x65, 0x00, 0x39, 0x38, +0x4E, 0x31, 0x44, 0x00, 0x02, 0x03, 0x01, 0x5A, +0x5A, 0x31, 0x04, 0x01, 0x00, 0x84, 0xFF, 0x46, +0x5A, 0x5A, 0x31, 0x04, 0x01, 0x00, 0x96, 0x0F, +0x24, 0x5A, 0x5A, 0x31, 0x04, 0x01, 0x00, 0x94, +0x0F, 0x26, 0x12, 0x44, 0x72, 0x69, 0x76, 0x65, +0x20, 0x4E, 0x6F, 0x74, 0x20, 0x52, 0x65, 0x61, +0x64, 0x79, 0x00, 0x12, 0x43, 0x6F, 0x6D, 0x6D, +0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, +0x6E, 0x20, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x00, +0x12, 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, 0x50, +0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x00, 0x12, +0x44, 0x72, 0x69, 0x76, 0x65, 0x20, 0x54, 0x72, +0x6F, 0x75, 0x62, 0x6C, 0x65, 0x00, 0x12, 0x44, +0x69, 0x73, 0x6B, 0x20, 0x6E, 0x6F, 0x74, 0x20, +0x69, 0x6E, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, +0x00, 0x34, 0x50, 0x72, 0x69, 0x6E, 0x74, 0x65, +0x72, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x65, +0x61, 0x64, 0x79, 0x00, 0x05, 0x46, 0x69, 0x6C, +0x65, 0x20, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, +0x00, 0x39, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x46, +0x75, 0x6C, 0x6C, 0x00, 0x1A, 0x46, 0x69, 0x6C, +0x65, 0x20, 0x45, 0x6D, 0x70, 0x74, 0x79, 0x00, +0x39, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, +0x72, 0x79, 0x20, 0x46, 0x75, 0x6C, 0x6C, 0x00, +0x07, 0x52, 0x61, 0x6D, 0x20, 0x46, 0x75, 0x6C, +0x6C, 0x00, 0x36, 0x00, 0x37, 0x42, 0x61, 0x64, +0x20, 0x46, 0x69, 0x6C, 0x65, 0x20, 0x4E, 0x61, +0x6D, 0x65, 0x00, 0x20, 0x50, 0x72, 0x65, 0x73, +0x73, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, +0x79, 0x2E, 0x00, 0xCF, 0x0A, 0x34, 0xC9, 0xCF, +0x13, 0x11, 0xC9, 0xCF, 0xE6, 0x17, 0xC9, 0xCF, +0xCB, 0x6E, 0xC9, 0xCF, 0x5C, 0x76, 0xC9, 0xCF, +0x6D, 0x6D, 0xC9, 0xCF, 0x32, 0x6E, 0xC9, 0xCF, +0x7E, 0x6D, 0xC9, 0xCF, 0xCB, 0x12, 0xC9, 0xCF, +0x42, 0x72, 0xC9, 0xCF, 0xB5, 0x13, 0xC9, 0xCF, +0xB1, 0x1B, 0xC9, 0xCF, 0xAF, 0x20, 0xC9, 0xCF, +0xBF, 0x1F, 0xC9, 0xCF, 0x17, 0x20, 0xC9, 0xCF, +0xD9, 0x1F, 0xC9, 0xCF, 0x6D, 0x6B, 0xC9, 0xCF, +0x46, 0x21, 0xC9, 0xCF, 0xF4, 0x05, 0xC9, 0xCF, +0x39, 0x22, 0xC9, 0xCF, 0x7E, 0x37, 0xC9, 0xCF, +0x25, 0x37, 0xC9, 0xCF, 0x22, 0x42, 0xC9, 0xCF, +0x31, 0x42, 0xC9, 0xCF, 0x5D, 0x42, 0xC9, 0xCF, +0x69, 0x42, 0xC9, 0xCF, 0x6E, 0x42, 0xC9, 0x21, +0x5D, 0x04, 0xE5, 0xC3, 0xA6, 0x00, 0xCF, 0xD4, +0x39, 0xC9, 0xCF, 0x55, 0x4B, 0xC9, 0xCF, 0x44, +0x46, 0xC9, 0xCF, 0xDB, 0x13, 0xC9, 0xCF, 0xE6, +0x6B, 0xC9, 0xCF, 0x5E, 0x1E, 0xC9, 0xCF, 0x3F, +0x42, 0xC9, 0xCF, 0x44, 0x42, 0xC9, 0xCF, 0xE8, +0x0F, 0xC9, 0xCF, 0x81, 0x4C, 0xC9, 0xCF, 0xF0, +0x05, 0xC9, 0xCF, 0x3D, 0x25, 0xC9, 0xCF, 0xA4, +0x25, 0xC9, 0xCF, 0x46, 0x23, 0xC9, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xCD, 0x08, 0x50, 0xC9, 0xCD, 0x0F, 0x50, 0xC9, +0xAF, 0x32, 0x9E, 0xF6, 0xC3, 0x18, 0x50, 0x3E, +0x0C, 0x32, 0x9E, 0xF6, 0xE7, 0xCD, 0x47, 0x53, +0x22, 0x9B, 0xF6, 0x21, 0x4B, 0x53, 0x11, 0x85, +0xF6, 0x01, 0x15, 0x00, 0xCD, 0x18, 0x53, 0x3E, +0x50, 0x32, 0x9D, 0xF6, 0xAF, 0x32, 0x9F, 0xF6, +0xCD, 0x3B, 0x53, 0x2A, 0x9B, 0xF6, 0xCD, 0x33, +0x53, 0xEB, 0xD5, 0xCD, 0xAB, 0x52, 0x00, 0x2E, +0x7E, 0xC2, 0x46, 0x50, 0x2E, 0x80, 0x01, 0x00, +0x00, 0x1A, 0xBD, 0xDA, 0x4F, 0x50, 0x03, 0x13, +0xFE, 0x1A, 0xC2, 0x49, 0x50, 0xE1, 0x3A, 0x9E, +0xF6, 0xD6, 0x0C, 0xC2, 0x60, 0x50, 0x47, 0x4F, +0xCD, 0x3F, 0x53, 0xD8, 0x2B, 0xE5, 0xCD, 0xA5, +0x52, 0xC2, 0x98, 0x50, 0xCD, 0xAB, 0x52, 0xDC, +0x07, 0x53, 0xC3, 0x1A, 0x52, 0xCD, 0x23, 0x53, +0xDA, 0x75, 0x50, 0xCD, 0x37, 0x53, 0xC9, 0x4F, +0xFE, 0x3A, 0xD0, 0xFE, 0x20, 0x37, 0xC8, 0xFE, +0x2F, 0xC8, 0x3F, 0xC9, 0xD6, 0x2F, 0xD0, 0x3E, +0x0B, 0xC9, 0xFE, 0x3A, 0xC0, 0x3E, 0x20, 0xC9, +0xD5, 0x00, 0x00, 0x01, 0x00, 0x00, 0xC5, 0xE1, +0x03, 0x13, 0x1A, 0xFE, 0x5B, 0xD2, 0xA0, 0x50, +0xFE, 0x1A, 0xCA, 0xB7, 0x50, 0xFE, 0x41, 0xDA, +0xA1, 0x50, 0x00, 0x23, 0xC3, 0xA1, 0x50, 0xC5, +0xD1, 0xDF, 0xD1, 0xDA, 0xC6, 0x50, 0xCD, 0x07, +0x53, 0x3E, 0x43, 0x32, 0x9D, 0xF6, 0xAF, 0x32, +0x9F, 0xF6, 0xCD, 0x0A, 0x52, 0xCD, 0x8A, 0x51, +0xD2, 0x5E, 0x51, 0xCD, 0x7F, 0x50, 0x00, 0xD2, +0x17, 0x51, 0x13, 0x1A, 0xCD, 0x80, 0x50, 0x1B, +0x47, 0x79, 0xD2, 0x17, 0x51, 0xC2, 0xEE, 0x50, +0xB8, 0xCA, 0x36, 0x51, 0x00, 0x00, 0x13, 0x21, +0x9F, 0xF6, 0x00, 0x7E, 0xB7, 0xC2, 0xFF, 0x50, +0x3E, 0x7E, 0x77, 0xE1, 0x77, 0x23, 0xE5, 0x79, +0xCD, 0x8C, 0x50, 0x00, 0x4F, 0x78, 0xCD, 0x8C, +0x50, 0xC6, 0x0B, 0x0D, 0xC2, 0x09, 0x51, 0xC6, +0x7A, 0xE1, 0x77, 0xE5, 0xC3, 0xCA, 0x50, 0xE1, +0xFE, 0x0D, 0xC2, 0x2A, 0x51, 0x13, 0x1A, 0xFE, +0x0A, 0x1B, 0x3E, 0x0D, 0xC2, 0x2A, 0x51, 0x13, +0x3E, 0x80, 0x77, 0xE5, 0x3A, 0x9F, 0xF6, 0xB7, +0xC2, 0xC6, 0x50, 0x00, 0x00, 0x7E, 0x21, 0x84, +0xF6, 0x06, 0x07, 0x05, 0xCA, 0xCA, 0x50, 0x23, +0xBE, 0xC2, 0x3B, 0x51, 0x0E, 0x15, 0xCD, 0x8A, +0x51, 0xD2, 0x5E, 0x51, 0x21, 0x85, 0xF6, 0xBE, +0xCA, 0x7B, 0x51, 0x0D, 0xCC, 0x0A, 0x52, 0xCA, +0x84, 0x51, 0x23, 0xC3, 0x4F, 0x51, 0x32, 0x9A, +0xF6, 0xAF, 0x32, 0x9F, 0xF6, 0x78, 0xFE, 0x07, +0xD2, 0x6E, 0x51, 0xCD, 0x0A, 0x52, 0xE1, 0x36, +0xFF, 0xE5, 0x3A, 0x9A, 0xF6, 0xCD, 0x95, 0x51, +0xC3, 0xCA, 0x50, 0x79, 0xC6, 0x15, 0x05, 0xC2, +0x7C, 0x51, 0xC6, 0x6B, 0xE1, 0x77, 0xE5, 0xC3, +0xCA, 0x50, 0x13, 0x1A, 0xFE, 0x1A, 0xCA, 0xBA, +0x52, 0xFE, 0x7E, 0xC9, 0x7E, 0x4F, 0x3A, 0x9E, +0xF6, 0xB7, 0x79, 0xC1, 0xE1, 0x23, 0xC2, 0xA2, +0x51, 0x77, 0xE5, 0xC5, 0xC8, 0xE7, 0xD5, 0x6F, +0x3A, 0x3A, 0xF6, 0x2F, 0xC6, 0x2C, 0x67, 0x7D, +0xCD, 0xD7, 0x51, 0x00, 0x00, 0x3F, 0xCA, 0xC4, +0x51, 0xD2, 0xC7, 0x51, 0x13, 0x1A, 0xCD, 0xD7, +0x51, 0xC3, 0xB6, 0x51, 0xCD, 0x2F, 0x53, 0xCD, +0x75, 0x50, 0x00, 0xD1, 0xC8, 0xFE, 0x20, 0xDA, +0xBA, 0x52, 0xCC, 0x27, 0x53, 0x00, 0xC9, 0x25, +0xC8, 0xFE, 0x21, 0x3F, 0xD0, 0xFE, 0xFE, 0x3D, +0xD0, 0xD6, 0x7F, 0xCA, 0x00, 0x52, 0xD8, 0x25, +0x00, 0xC8, 0xF5, 0x3A, 0x9F, 0xF6, 0xB7, 0x01, +0x0B, 0x05, 0xC2, 0xF8, 0x51, 0x01, 0x15, 0x00, +0xF1, 0x90, 0x90, 0x00, 0xD8, 0x3C, 0xFE, 0x6A, +0x3D, 0xD0, 0x80, 0x91, 0xD8, 0xC2, 0x03, 0x52, +0x3C, 0xC9, 0xC1, 0xE1, 0x23, 0xE5, 0xC5, 0xC9, +0xAF, 0x32, 0x9F, 0xF6, 0xCD, 0x8A, 0x51, 0xC3, +0x2F, 0x52, 0xCD, 0xAB, 0x52, 0xC2, 0x10, 0x52, +0xCD, 0x8A, 0x51, 0xDA, 0x2F, 0x52, 0xC2, 0x39, +0x52, 0x32, 0x9F, 0xF6, 0xC3, 0x1A, 0x52, 0xCD, +0x95, 0x51, 0xAF, 0x32, 0x9F, 0xF6, 0xC3, 0x1A, +0x52, 0xFE, 0x80, 0xC2, 0x48, 0x52, 0x3E, 0x0D, +0xCD, 0x95, 0x51, 0x3E, 0x0A, 0xC3, 0x2F, 0x52, +0xFE, 0xFE, 0xCA, 0x81, 0x52, 0xD2, 0x10, 0x52, +0x4F, 0x3A, 0x9F, 0xF6, 0xB7, 0x79, 0xCA, 0x81, +0x52, 0xD6, 0x86, 0xDA, 0x1A, 0x52, 0x01, 0x00, +0x00, 0x0C, 0xD6, 0x0B, 0xD2, 0x61, 0x52, 0xC6, +0x3B, 0xCD, 0x92, 0x50, 0x32, 0x9A, 0xF6, 0x79, +0xC6, 0x2F, 0xCD, 0x92, 0x50, 0xCD, 0x95, 0x51, +0x3A, 0x9A, 0xF6, 0xCD, 0x95, 0x51, 0xC3, 0x1A, +0x52, 0xD6, 0x81, 0x21, 0x8B, 0xF6, 0x2B, 0xD6, +0x15, 0xD2, 0x86, 0x52, 0xC6, 0x16, 0x32, 0x9A, +0xF6, 0xCD, 0x94, 0x51, 0x3A, 0x9A, 0xF6, 0x21, +0x9A, 0xF6, 0x2B, 0x3D, 0xC2, 0x9A, 0x52, 0xCD, +0x94, 0x51, 0xC3, 0x1A, 0x52, 0x3A, 0x9E, 0xF6, +0xFE, 0x0C, 0xC8, 0x2A, 0x9B, 0xF6, 0x01, 0x0A, +0x00, 0x09, 0x7E, 0xFE, 0x50, 0xC8, 0xFE, 0x43, +0x37, 0xC9, 0x32, 0x9A, 0xF6, 0xC5, 0xCD, 0xA5, +0x52, 0xC1, 0xD1, 0xE1, 0xFE, 0x0C, 0xC2, 0xD6, +0x52, 0x3A, 0x9A, 0xF6, 0xFE, 0x1A, 0xCC, 0x27, +0x53, 0xCD, 0x2B, 0x53, 0xBF, 0xC9, 0xD6, 0x43, +0xCA, 0xE6, 0x52, 0xD6, 0x0F, 0xCA, 0xE6, 0x52, +0x78, 0xFE, 0x07, 0xD2, 0xE7, 0x52, 0x23, 0xE5, +0x2B, 0x01, 0xFF, 0xFF, 0x3E, 0x1A, 0x03, 0x23, +0xBE, 0xC2, 0xEE, 0x52, 0xE1, 0xCD, 0x43, 0x53, +0xCD, 0xAB, 0x52, 0xCA, 0x04, 0x53, 0x3A, 0x9D, +0xF6, 0x77, 0xBF, 0xC9, 0x36, 0x4F, 0xC9, 0x21, +0x86, 0xF6, 0x3E, 0x14, 0xF5, 0x7E, 0xE6, 0xDF, +0x77, 0xF1, 0x3D, 0xC8, 0x23, 0xC3, 0x0C, 0x53, +0x7E, 0x12, 0x23, 0x13, 0x0B, 0x78, 0xB1, 0xC2, +0x18, 0x53, 0xC9, 0xCF, 0x83, 0x72, 0xC9, 0xCF, +0xCB, 0x12, 0xC9, 0xCF, 0x31, 0x42, 0xC9, 0xCF, +0x22, 0x42, 0xC9, 0xCF, 0xE3, 0x5A, 0xC9, 0xCF, +0x42, 0x72, 0xC9, 0xCF, 0x46, 0x21, 0xC9, 0xCF, +0x6D, 0x6B, 0xC9, 0xCF, 0x9F, 0x6B, 0xC9, 0xCF, +0x44, 0x42, 0xC9, 0x20, 0x65, 0x74, 0x61, 0x6F, +0x69, 0x6E, 0x72, 0x73, 0x68, 0x64, 0x6C, 0x66, +0x63, 0x6D, 0x75, 0x67, 0x79, 0x70, 0x77, 0x62, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +/* TS-DOS T200 image */ +const unsigned char gTsDos200Image[] = { +0xC3, 0xAA, 0x00, 0xE1, 0xD1, 0xC1, 0xF1, 0xC9, +0xC3, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xCF, 0x10, 0x00, 0xC9, 0x00, 0x00, 0x00, 0x00, +0x7C, 0x92, 0xC0, 0x7D, 0x93, 0xC9, 0x3E, 0x20, +0xCF, 0x20, 0x00, 0xC9, 0xF3, 0xCD, 0x93, 0x00, +0xE1, 0xC3, 0x03, 0x00, 0xF3, 0xCD, 0x93, 0x00, +0xF1, 0xF1, 0xC9, 0x00, 0xF3, 0xCD, 0x93, 0x00, +0xC3, 0xA2, 0x00, 0x00, 0xF3, 0xCD, 0x93, 0x00, +0xF5, 0x3E, 0x02, 0xD3, 0xD0, 0xF1, 0xC9, 0x00, +0x11, 0xC8, 0xEE, 0xCD, 0xD3, 0xF4, 0xDB, 0xD0, +0xE6, 0x0C, 0x2A, 0x49, 0x00, 0xD3, 0xD0, 0xDF, +0xFE, 0x01, 0xD8, 0x21, 0x47, 0x11, 0x22, 0x0D, +0xF5, 0x22, 0xB2, 0xEE, 0xCD, 0x6B, 0x36, 0x26, +0x72, 0x03, 0xCD, 0xD3, 0xF4, 0xC7, 0x01, 0x08, +0x00, 0x1A, 0x77, 0x13, 0x23, 0x0B, 0x78, 0xB1, +0xC2, 0x71, 0x00, 0xC9, 0x22, 0xAD, 0xF2, 0xE1, +0xD5, 0x5E, 0x23, 0x56, 0x23, 0xE3, 0xEB, 0xE5, +0x21, 0xD3, 0xF4, 0xE3, 0xE5, 0x2A, 0xAD, 0xF2, +0xC3, 0xA2, 0x00, 0x22, 0xAF, 0xF2, 0x21, 0xD3, +0xF4, 0xE3, 0x2B, 0x2B, 0x2B, 0x2B, 0xE5, 0x2A, +0xAF, 0xF2, 0xF5, 0xDB, 0xD0, 0xE6, 0x0C, 0xC3, +0xD6, 0xF4, 0xF3, 0xFE, 0x08, 0xD2, 0x00, 0x01, +0x47, 0xD3, 0xD0, 0x3A, 0xF5, 0xEE, 0xB0, 0xD3, +0xD0, 0xC5, 0xF5, 0xD5, 0xE5, 0x11, 0x40, 0x00, +0x21, 0xD3, 0xF4, 0xCD, 0x6E, 0x00, 0x01, 0x26, +0x00, 0x21, 0xC8, 0xEE, 0xCD, 0x71, 0x00, 0xE1, +0xD1, 0xF1, 0x32, 0xD5, 0xF4, 0xF1, 0xFB, 0xC3, +0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x7C, 0xB5, 0xCA, 0x00, 0x70, 0xE1, 0xCD, 0x17, +0x01, 0xC3, 0x35, 0x35, 0x7E, 0x12, 0x23, 0x13, +0x0B, 0x78, 0xB1, 0xC2, 0x0C, 0x01, 0xC9, 0x21, +0xA5, 0x03, 0xE5, 0x23, 0x01, 0x08, 0x00, 0x11, +0x46, 0xF7, 0xCD, 0x0C, 0x01, 0xEB, 0xED, 0x22, +0xC4, 0xF7, 0x13, 0x13, 0xEB, 0x22, 0xC8, 0xF7, +0xCD, 0xD1, 0x01, 0xCD, 0xCD, 0x01, 0xC1, 0xC0, +0x2A, 0x95, 0xF2, 0x22, 0xC2, 0xF7, 0x0A, 0x32, +0xC6, 0xF7, 0xCD, 0x85, 0x01, 0xD8, 0xE5, 0x2A, +0xC4, 0xF7, 0x44, 0x4D, 0xC5, 0x2A, 0xC2, 0xF7, +0xCD, 0xD9, 0x01, 0xDA, 0x82, 0x01, 0x2A, 0xC2, +0xF7, 0xEB, 0x2A, 0xC8, 0xF7, 0xC1, 0xCD, 0x0C, +0x01, 0xD1, 0xD5, 0x2A, 0x61, 0xF6, 0x2B, 0x22, +0x95, 0xF2, 0x23, 0xEB, 0x2A, 0xC4, 0xF7, 0x19, +0x22, 0x61, 0xF6, 0xD1, 0x2A, 0xC2, 0xF7, 0xEB, +0x3A, 0xC6, 0xF7, 0xCD, 0xD5, 0x01, 0xCD, 0xD1, +0x01, 0xC9, 0xE1, 0xE1, 0xC9, 0x21, 0xAA, 0xF2, +0x01, 0x0B, 0x00, 0x09, 0x7E, 0xFE, 0xFF, 0xCA, +0x97, 0x01, 0x87, 0xDA, 0x8B, 0x01, 0xC9, 0x37, +0xC9, 0xCF, 0xC7, 0x4F, 0xC9, 0xCF, 0xA9, 0x4F, +0xC9, 0xCF, 0x20, 0x6E, 0xC9, 0xCF, 0xF7, 0x12, +0xC9, 0xCF, 0x03, 0x8B, 0xC9, 0xCF, 0xDE, 0x13, +0xC9, 0xCF, 0x97, 0x26, 0xC9, 0xCF, 0x4D, 0x4F, +0xC9, 0xCF, 0x88, 0x4F, 0xC9, 0xCF, 0x8D, 0x4F, +0xC9, 0xCF, 0x04, 0x14, 0xC9, 0xCF, 0x5E, 0x4F, +0xC9, 0xCF, 0x00, 0x00, 0xC9, 0xCF, 0xCC, 0x2B, +0xC9, 0xCF, 0x62, 0x2C, 0xC9, 0xCF, 0xAC, 0x2D, +0xC9, 0xCF, 0xA8, 0x82, 0xC9, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x3E, 0x02, 0xE1, 0x21, +0x00, 0x00, 0xC3, 0x00, 0x00, 0x80, 0x54, 0x53, +0x2D, 0x44, 0x4F, 0x53, 0x20, 0x20, 0x0F, 0x00, +0x0E, 0xA0, 0x0A, 0x00, 0xB9, 0x36, 0x31, 0x31, +0x36, 0x37, 0x2C, 0x32, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x21, 0xC0, 0xF7, +0x06, 0xB4, 0xAF, 0xCD, 0x5A, 0x4A, 0x21, 0x00, +0x00, 0x39, 0x22, 0xCE, 0xF7, 0x3E, 0x01, 0xCD, +0xAB, 0x4A, 0xAF, 0x32, 0xD4, 0xF7, 0x32, 0xDA, +0xF7, 0x32, 0xD9, 0xF7, 0x32, 0xCA, 0xF7, 0x3C, +0x32, 0xCD, 0xF7, 0x21, 0x64, 0x35, 0x22, 0xD0, +0xF7, 0xCD, 0x4F, 0x4C, 0xCD, 0x7E, 0x4C, 0xCD, +0x11, 0x36, 0x3A, 0xD5, 0xF7, 0x32, 0xCD, 0xF7, +0xCD, 0x2F, 0x36, 0x21, 0xDB, 0x48, 0xE5, 0xF5, +0xFE, 0x02, 0xD2, 0xB9, 0x35, 0x3A, 0xCC, 0xF7, +0xA7, 0xCA, 0xB9, 0x35, 0x3A, 0xD6, 0xF7, 0x4F, +0x0C, 0x06, 0x00, 0xC5, 0x3A, 0xCD, 0xF7, 0x32, +0xD5, 0xF7, 0xCD, 0xC4, 0x3A, 0xC1, 0x04, 0x0D, +0xCA, 0xDB, 0x48, 0x78, 0x32, 0xD5, 0xF7, 0x32, +0xCD, 0xF7, 0xC5, 0xCD, 0xB2, 0x3A, 0x2A, 0xE4, +0xF7, 0x2B, 0x7E, 0xFE, 0x3E, 0xC2, 0x8C, 0x35, +0xC1, 0xF1, 0x21, 0x8C, 0x35, 0xF5, 0xC5, 0xE5, +0xF5, 0xCD, 0x7A, 0x4C, 0x3A, 0xD9, 0xF7, 0xB7, +0xCA, 0xE2, 0x35, 0xF1, 0xA7, 0xCA, 0x25, 0x3B, +0x3D, 0xCA, 0x6A, 0x3D, 0x3D, 0xCA, 0x96, 0x3D, +0x3D, 0x3D, 0xCA, 0x4A, 0x3D, 0x3D, 0x3D, 0xCA, +0xF7, 0x3C, 0x3D, 0xE1, 0xCA, 0xFE, 0x35, 0xC3, +0x64, 0x35, 0xF1, 0xA7, 0xCA, 0x42, 0x3C, 0x3D, +0xCA, 0x22, 0x3C, 0x3D, 0xCA, 0xEF, 0x3A, 0x3D, +0x3D, 0xCA, 0x53, 0x3E, 0x3D, 0x3D, 0x3D, 0xE1, +0xCA, 0xFE, 0x35, 0xC3, 0x64, 0x35, 0xCD, 0xEA, +0x4A, 0xCD, 0xFB, 0x4B, 0xCD, 0x4F, 0x4C, 0xCD, +0x7E, 0x4C, 0x21, 0x00, 0x00, 0xE5, 0xC3, 0xA2, +0x00, 0x21, 0x01, 0x01, 0x22, 0x06, 0xEF, 0x21, +0x60, 0x3E, 0xCD, 0x52, 0x4A, 0xAF, 0x32, 0xCC, +0xF7, 0x3E, 0x01, 0x32, 0xD5, 0xF7, 0x21, 0x02, +0x02, 0x22, 0x06, 0xEF, 0xC3, 0x3B, 0x38, 0x3A, +0xCD, 0xF7, 0x32, 0xD5, 0xF7, 0xCD, 0xB2, 0x3A, +0x3A, 0xD5, 0xF7, 0x3D, 0x37, 0x3F, 0x07, 0x5F, +0x16, 0x00, 0x21, 0x70, 0xEF, 0x19, 0xEB, 0x21, +0x0F, 0x23, 0x22, 0x06, 0xEF, 0xCD, 0x53, 0x4C, +0xED, 0xCD, 0x57, 0x4C, 0xCD, 0x66, 0x4C, 0xCD, +0x5B, 0x4C, 0xCD, 0xF5, 0x3D, 0xCD, 0x13, 0x4C, +0xCA, 0x5A, 0x36, 0xDA, 0x0C, 0x38, 0xFE, 0x0D, +0xCA, 0x22, 0x37, 0xFE, 0x17, 0xCA, 0xAA, 0x37, +0xFE, 0x14, 0xCA, 0x98, 0x37, 0xFE, 0x5D, 0xCA, +0x98, 0x37, 0xFE, 0x3F, 0xCA, 0x77, 0x37, 0xFE, +0x02, 0xCA, 0x77, 0x37, 0xFE, 0x1E, 0xCA, 0xEE, +0x36, 0xFE, 0x1F, 0xCA, 0xFC, 0x36, 0xFE, 0x1D, +0xCA, 0xDD, 0x36, 0xFE, 0x1C, 0xCA, 0xCA, 0x36, +0xFE, 0x20, 0xCA, 0xCA, 0x36, 0xE6, 0xDF, 0xFE, +0x54, 0xCA, 0xEE, 0x37, 0xFE, 0x41, 0xCA, 0x15, +0x37, 0xFE, 0x47, 0xCA, 0x15, 0x37, 0xFE, 0x55, +0xCA, 0xAE, 0x37, 0xFE, 0x44, 0xCA, 0xB9, 0x39, +0xFE, 0x4C, 0xCA, 0xC2, 0x39, 0xFE, 0x50, 0xCA, +0xC2, 0x39, 0xFE, 0x52, 0xCA, 0x59, 0x37, 0xC3, +0x5A, 0x36, 0x3E, 0x01, 0x21, 0xD5, 0xF7, 0x86, +0x23, 0xBE, 0xDA, 0x0A, 0x37, 0xCA, 0x0A, 0x37, +0x3E, 0x01, 0xC3, 0x0A, 0x37, 0x3A, 0xD5, 0xF7, +0x3D, 0xC2, 0x0A, 0x37, 0x3A, 0xD6, 0xF7, 0xA7, +0xCA, 0x5A, 0x36, 0xC3, 0x0A, 0x37, 0x3A, 0xD5, +0xF7, 0xD6, 0x04, 0xDA, 0x5A, 0x36, 0xCA, 0x5A, +0x36, 0xC3, 0x0A, 0x37, 0x3E, 0x04, 0x21, 0xD5, +0xF7, 0x86, 0x4F, 0x23, 0x7E, 0xB9, 0xDA, 0x5A, +0x36, 0x79, 0xF5, 0xCD, 0xC4, 0x3A, 0xF1, 0x32, +0xCD, 0xF7, 0xC3, 0x2F, 0x36, 0x3E, 0x3E, 0xCD, +0xCA, 0x37, 0x3E, 0x01, 0x32, 0xCC, 0xF7, 0xC3, +0x2F, 0x36, 0x3A, 0xCB, 0xF7, 0xFE, 0x02, 0xC2, +0x5A, 0x36, 0x2A, 0xE4, 0xF7, 0x01, 0x07, 0x00, +0x09, 0x7E, 0xFE, 0x3C, 0xC2, 0x5A, 0x36, 0xCD, +0x61, 0x4A, 0x2A, 0xE4, 0xF7, 0xCD, 0x8C, 0x3D, +0xCD, 0x81, 0x40, 0x21, 0x02, 0x00, 0xCD, 0x92, +0x40, 0x2A, 0xE4, 0xF7, 0x11, 0xC0, 0xF7, 0x01, +0x09, 0x00, 0xCD, 0x2B, 0x4A, 0xAF, 0xC3, 0x8A, +0x37, 0x3A, 0xD9, 0xF7, 0xA7, 0xC2, 0x2F, 0x36, +0x2A, 0xE4, 0xF7, 0xCD, 0x28, 0x49, 0xCD, 0x77, +0x4A, 0xFE, 0xC0, 0xCC, 0x00, 0x50, 0xCD, 0x33, +0x4C, 0xCD, 0x11, 0x36, 0xC3, 0x2F, 0x36, 0x3A, +0xD9, 0xF7, 0xA7, 0xCA, 0x5A, 0x36, 0x3A, 0xD6, +0xF7, 0xFE, 0x2E, 0xDA, 0x5A, 0x36, 0x3A, 0xD4, +0xF7, 0x3C, 0x32, 0xD4, 0xF7, 0x3E, 0x01, 0x32, +0xCD, 0xF7, 0xCD, 0x11, 0x36, 0xC3, 0x2F, 0x36, +0x3A, 0xD9, 0xF7, 0xA7, 0xCA, 0x5A, 0x36, 0x3A, +0xD4, 0xF7, 0xA7, 0xCA, 0x5A, 0x36, 0x3D, 0xC3, +0x8A, 0x37, 0xAF, 0xC3, 0x8A, 0x37, 0x3E, 0x20, +0xCD, 0xCA, 0x37, 0xAF, 0x32, 0xCC, 0xF7, 0xC3, +0x2F, 0x36, 0x3A, 0xCB, 0xF7, 0x3D, 0xC2, 0x5A, +0x36, 0x3A, 0xCA, 0xF7, 0xEE, 0x01, 0x32, 0xCA, +0xF7, 0xC9, 0x32, 0xCC, 0xF7, 0x3A, 0xD6, 0xF7, +0xA7, 0xC8, 0xAF, 0x3C, 0x32, 0xD5, 0xF7, 0xCD, +0xCD, 0x3A, 0x2A, 0xE4, 0xF7, 0x2B, 0x3A, 0xCC, +0xF7, 0xE7, 0x3A, 0xD5, 0xF7, 0x21, 0xD6, 0xF7, +0xBE, 0xDA, 0xD3, 0x37, 0xA7, 0xC9, 0xCD, 0xCD, +0x3A, 0xCD, 0x57, 0x4C, 0x2A, 0xE4, 0xF7, 0x2B, +0x3E, 0x3E, 0xBE, 0xC2, 0x00, 0x38, 0x3E, 0x20, +0xE7, 0xCD, 0x5B, 0x4C, 0x21, 0xCC, 0xF7, 0x36, +0x01, 0xC3, 0xCA, 0x36, 0xFE, 0x08, 0xD2, 0x5A, +0x36, 0xFE, 0x05, 0xCA, 0x33, 0x38, 0xFE, 0x03, +0xC0, 0x3A, 0xD9, 0xF7, 0xEE, 0x01, 0x32, 0xD9, +0xF7, 0xAF, 0x32, 0xD4, 0xF7, 0x3E, 0x01, 0x32, +0xCD, 0xF7, 0xCD, 0x4F, 0x4C, 0xCD, 0x11, 0x36, +0xC3, 0x2F, 0x36, 0x3A, 0xD9, 0xF7, 0xA7, 0xC8, +0xC3, 0xAA, 0x37, 0x21, 0x70, 0xEF, 0x22, 0xDB, +0xF7, 0xAF, 0x77, 0x23, 0x77, 0x3A, 0xD9, 0xF7, +0xA7, 0xCA, 0x5D, 0x39, 0xAF, 0x32, 0xDA, 0xF7, +0xCD, 0x5B, 0x47, 0xC2, 0x0F, 0x39, 0x3A, 0xD4, +0xF7, 0xA7, 0xCA, 0x71, 0x38, 0x32, 0xDA, 0xF7, +0xCD, 0x68, 0x47, 0x3A, 0xDA, 0xF7, 0x3D, 0xC2, +0x5D, 0x38, 0xAF, 0x32, 0xDA, 0xF7, 0x32, 0xD6, +0xF7, 0xCD, 0x68, 0x47, 0x3A, 0xD6, 0xF7, 0xFE, +0x2E, 0xDC, 0xAA, 0x39, 0x3A, 0xCB, 0xF7, 0xA7, +0xCA, 0x9F, 0x38, 0x3D, 0xCA, 0x8D, 0x38, 0x21, +0xC0, 0xF7, 0xC3, 0xA5, 0x38, 0x21, 0x01, 0x24, +0x22, 0x06, 0xEF, 0xCD, 0x57, 0x4C, 0x3E, 0x23, +0xE7, 0x3A, 0xCA, 0xF7, 0xC6, 0x30, 0xE7, 0xCD, +0x5B, 0x4C, 0xC3, 0xB8, 0x38, 0xE5, 0x21, 0x01, +0x21, 0x22, 0x06, 0xEF, 0xCD, 0x57, 0x4C, 0xE1, +0x0E, 0x06, 0xCD, 0x0B, 0x49, 0xCD, 0x5B, 0x4C, +0x21, 0x8E, 0x3E, 0x01, 0x36, 0x39, 0x3A, 0xD9, +0xF7, 0xA7, 0xC2, 0xCB, 0x38, 0x21, 0xD0, 0x3E, +0x01, 0x22, 0x39, 0xC5, 0xE5, 0x3A, 0xCD, 0xF7, +0x21, 0xD6, 0xF7, 0xBE, 0xDA, 0xDD, 0x38, 0x7E, +0xA7, 0xC2, 0xDD, 0x38, 0x3C, 0x32, 0xD5, 0xF7, +0x21, 0x0F, 0x0B, 0x22, 0x06, 0xEF, 0xE1, 0xCD, +0x52, 0x4A, 0x3A, 0xD9, 0xF7, 0xA7, 0xCA, 0x05, +0x39, 0x3A, 0xCB, 0xF7, 0xA7, 0xCA, 0x05, 0x39, +0x21, 0xE0, 0x3F, 0x3D, 0xCA, 0x02, 0x39, 0x21, +0xCF, 0x3F, 0xCD, 0x52, 0x4A, 0xCD, 0x40, 0x39, +0x21, 0x0F, 0x15, 0x22, 0x06, 0xEF, 0xC9, 0xAF, +0xCD, 0xAA, 0x39, 0x21, 0x8E, 0x3E, 0x01, 0x1C, +0x39, 0xC3, 0xCB, 0x38, 0x21, 0x33, 0x3F, 0xC3, +0x52, 0x4A, 0x2A, 0x65, 0xF6, 0xEB, 0x2A, 0x63, +0xEF, 0x7D, 0x93, 0x6F, 0x7C, 0x9A, 0x67, 0x01, +0xF2, 0xFF, 0x09, 0xC3, 0x66, 0x4C, 0xCD, 0x36, +0x4A, 0xCD, 0x66, 0x4C, 0x3E, 0x30, 0xE7, 0xC9, +0x3A, 0xD9, 0xF7, 0xA7, 0xC0, 0x3A, 0x5D, 0xF5, +0x11, 0xE9, 0x3F, 0xFE, 0x06, 0xCA, 0x53, 0x39, +0x11, 0xED, 0x3F, 0x21, 0x10, 0x19, 0x22, 0x06, +0xEF, 0xEB, 0xC3, 0x52, 0x4A, 0x21, 0xB5, 0xF2, +0xAF, 0x32, 0xD6, 0xF7, 0x3E, 0x2E, 0x3D, 0xF5, +0x7E, 0xEE, 0x80, 0xE6, 0x9F, 0xC2, 0x96, 0x39, +0xE5, 0x23, 0x5E, 0x23, 0x56, 0xE3, 0xE5, 0xCD, +0xCA, 0x3C, 0xEB, 0xCD, 0xB7, 0x47, 0xE1, 0xE3, +0x23, 0x0E, 0x06, 0xCD, 0x0B, 0x49, 0x3E, 0x2E, +0xE7, 0x0E, 0x02, 0xCD, 0x0B, 0x49, 0x3E, 0x20, +0xE7, 0x21, 0xD6, 0xF7, 0x34, 0xE1, 0x11, 0x0B, +0x00, 0x19, 0xF1, 0x3D, 0xC2, 0x67, 0x39, 0x3A, +0xD6, 0xF7, 0xFE, 0x2E, 0xDC, 0xAA, 0x39, 0xC3, +0x7C, 0x38, 0xF5, 0x21, 0xC4, 0x3F, 0xCD, 0x52, +0x4A, 0xF1, 0x3C, 0xFE, 0x2E, 0xC2, 0xAA, 0x39, +0xC9, 0xCD, 0xA8, 0x3A, 0xCD, 0x76, 0x4C, 0xC3, +0x2F, 0x36, 0x32, 0xDF, 0xF7, 0x11, 0x07, 0x00, +0x2A, 0xE4, 0xF7, 0x19, 0x7E, 0xFE, 0x44, 0xC2, +0x2F, 0x36, 0x23, 0x7E, 0xFE, 0x4F, 0xC2, 0x06, +0x3A, 0xCD, 0x49, 0x3A, 0x3A, 0xDF, 0xF7, 0xFE, +0x4C, 0xCC, 0x4F, 0x4C, 0xC4, 0xA8, 0x3A, 0xCD, +0x24, 0x3A, 0xF5, 0xCD, 0x6B, 0x3A, 0xF1, 0xCA, +0xE7, 0x39, 0x3A, 0xDF, 0xF7, 0xFE, 0x4C, 0xC2, +0x00, 0x3A, 0x3E, 0x07, 0xE7, 0xCD, 0xEF, 0x3D, +0xCD, 0x4F, 0x4C, 0xC3, 0xDB, 0x48, 0x3A, 0xD9, +0xF7, 0xA7, 0xC2, 0x2F, 0x36, 0x2A, 0xE4, 0xF7, +0xCD, 0x28, 0x49, 0xCD, 0x77, 0x4A, 0xFE, 0xC0, +0xCC, 0x04, 0x50, 0xCD, 0x33, 0x4C, 0xCD, 0x11, +0x36, 0xC3, 0x2F, 0x36, 0x3A, 0xD9, 0xF7, 0xA7, +0xC2, 0xAD, 0x40, 0x2A, 0xDD, 0xF7, 0x01, 0x80, +0x00, 0x79, 0x08, 0xD2, 0x3A, 0x3A, 0x09, 0x7D, +0x6C, 0x4F, 0x22, 0xDD, 0xF7, 0x2A, 0xE0, 0xF7, +0xE5, 0x09, 0x22, 0xE0, 0xF7, 0xE1, 0xFE, 0x80, +0xC9, 0xCD, 0x61, 0x4A, 0x2A, 0xE4, 0xF7, 0x3A, +0xD9, 0xF7, 0xA7, 0xC2, 0x65, 0x3A, 0xCD, 0x71, +0x4A, 0xD5, 0xCD, 0xCA, 0x3C, 0x22, 0xDD, 0xF7, +0xE1, 0x22, 0xE0, 0xF7, 0xC9, 0xCD, 0x8C, 0x3D, +0xC3, 0x81, 0x40, 0xEB, 0xB7, 0xC8, 0x4F, 0x3A, +0xDF, 0xF7, 0xFE, 0x4C, 0xC2, 0x82, 0x3A, 0xCD, +0x8F, 0x3A, 0x1A, 0xE7, 0x13, 0x0D, 0xC2, 0x77, +0x3A, 0xC9, 0xCD, 0x8F, 0x3A, 0x1A, 0xCD, 0x6A, +0x4C, 0x13, 0x0D, 0xC2, 0x82, 0x3A, 0xC9, 0xCD, +0x72, 0x4C, 0xC8, 0xCD, 0x0F, 0x4C, 0xFE, 0x03, +0xCA, 0x00, 0x3A, 0xFE, 0x1B, 0xCA, 0x00, 0x3A, +0xFE, 0x20, 0xC2, 0x8F, 0x3A, 0xC3, 0x0F, 0x4C, +0xDB, 0xBB, 0xE6, 0x06, 0xEE, 0x02, 0xC2, 0xA1, +0x48, 0xC9, 0xCD, 0xCD, 0x3A, 0x22, 0xE4, 0xF7, +0xCD, 0x57, 0x4C, 0x2B, 0x0E, 0x0A, 0xCD, 0x0B, +0x49, 0xC3, 0x5B, 0x4C, 0xCD, 0x5B, 0x4C, 0xCD, +0xCD, 0x3A, 0xC3, 0xBB, 0x3A, 0x3A, 0xD5, 0xF7, +0x3D, 0x5F, 0x16, 0x00, 0x21, 0x04, 0x00, 0xCD, +0x3F, 0x4C, 0x23, 0x23, 0xE5, 0x21, 0x05, 0x00, +0xCD, 0x43, 0x4C, 0xD1, 0x55, 0xEB, 0x24, 0x22, +0x06, 0xEF, 0xCD, 0x47, 0x4C, 0x23, 0xC9, 0xCD, +0x71, 0x4A, 0x22, 0xE0, 0xF7, 0x21, 0x41, 0x3F, +0xCD, 0x11, 0x3E, 0xC8, 0xCD, 0x28, 0x49, 0x2A, +0xE0, 0xF7, 0x01, 0x09, 0x00, 0x09, 0x11, 0x4C, +0xF7, 0x7E, 0x12, 0x13, 0x23, 0x7E, 0x12, 0xCD, +0x77, 0x4A, 0xC2, 0xA4, 0x48, 0x2A, 0xE0, 0xF7, +0x23, 0x23, 0x23, 0x11, 0x46, 0xF7, 0x01, 0x06, +0x00, 0xEB, 0xC3, 0x2B, 0x4A, 0xCD, 0x61, 0x4A, +0x2A, 0xE4, 0xF7, 0xCD, 0x8C, 0x3D, 0x3A, 0xCC, +0xF7, 0xA7, 0xC2, 0x4D, 0x3B, 0x21, 0x71, 0x3F, +0xCD, 0x11, 0x3E, 0xCA, 0x4D, 0x3B, 0xCD, 0x28, +0x49, 0x01, 0x02, 0x00, 0x21, 0xEF, 0xF7, 0x11, +0x4C, 0xF7, 0xCD, 0x2B, 0x4A, 0xCD, 0x77, 0x4A, +0xCA, 0x60, 0x3B, 0x21, 0xA7, 0x3F, 0xCD, 0x1A, +0x49, 0xCD, 0xE5, 0x3D, 0xC0, 0xCD, 0x2F, 0x3C, +0x2A, 0x1D, 0xF8, 0x7C, 0x65, 0x6F, 0x22, 0x1D, +0xF8, 0x3A, 0xEF, 0xF7, 0xFE, 0x44, 0xC2, 0x79, +0x3B, 0x2A, 0x61, 0xF6, 0x3E, 0xC0, 0xC3, 0x9A, +0x3B, 0xFE, 0x43, 0xC2, 0x8C, 0x3B, 0x2A, 0x63, +0xF6, 0x22, 0xD5, 0xF7, 0x2A, 0x65, 0xF6, 0x3E, +0xA0, 0xC3, 0x9A, 0x3B, 0x2A, 0x1D, 0xF8, 0x22, +0xD5, 0xF7, 0x2A, 0x95, 0xF2, 0x22, 0xE0, 0xF7, +0x3E, 0x80, 0x32, 0xDF, 0xF7, 0x22, 0xE2, 0xF7, +0x2A, 0x1D, 0xF8, 0x22, 0xDD, 0xF7, 0xE5, 0xC1, +0x3A, 0xDF, 0xF7, 0xFE, 0xA0, 0xCA, 0xB7, 0x3B, +0x03, 0xFE, 0x80, 0xC2, 0xB7, 0x3B, 0x03, 0xC5, +0xCD, 0x3F, 0x3E, 0xDA, 0xAD, 0x48, 0xC1, 0xE5, +0xC5, 0x2A, 0xE2, 0xF7, 0xCD, 0x2F, 0x4C, 0xDA, +0xB0, 0x48, 0x2A, 0xE2, 0xF7, 0xC1, 0x36, 0x00, +0x23, 0x0B, 0x79, 0xB0, 0xC2, 0xCE, 0x3B, 0x2B, +0xD1, 0x3A, 0xDF, 0xF7, 0xFE, 0xC0, 0xC2, 0xEA, +0x3B, 0x36, 0x1A, 0x2A, 0xE2, 0xF7, 0x2B, 0xC3, +0x12, 0x3C, 0xFE, 0xA0, 0xC2, 0xFB, 0x3B, 0x2A, +0xD5, 0xF7, 0x22, 0x63, 0xF6, 0x2A, 0xE2, 0xF7, +0xC3, 0x12, 0x3C, 0xD5, 0x2A, 0x61, 0xF6, 0x2B, +0x22, 0x95, 0xF2, 0x23, 0xEB, 0x2A, 0xD5, 0xF7, +0x23, 0x23, 0x19, 0x22, 0x61, 0xF6, 0xD1, 0x2A, +0xE0, 0xF7, 0xEB, 0xCD, 0x3B, 0x4C, 0xCD, 0x1E, +0x41, 0xCD, 0x33, 0x4C, 0x21, 0x02, 0x00, 0xC3, +0x92, 0x40, 0x3A, 0xCC, 0xF7, 0xA7, 0xCC, 0xD8, +0x3D, 0x2A, 0xE4, 0xF7, 0xCD, 0x28, 0x49, 0xCD, +0x77, 0x4A, 0xFE, 0xC0, 0xCA, 0x23, 0x4C, 0xFE, +0xA0, 0xCA, 0x2B, 0x4C, 0xFE, 0x80, 0xCA, 0x27, +0x4C, 0xC9, 0xCD, 0x61, 0x4A, 0xCD, 0x71, 0x4A, +0xD5, 0xE5, 0x23, 0x23, 0x23, 0x11, 0xE8, 0xF7, +0x01, 0x06, 0x00, 0xCD, 0x2B, 0x4A, 0x3E, 0x2E, +0x12, 0x13, 0x01, 0x02, 0x00, 0xCD, 0x2B, 0x4A, +0x3A, 0xCC, 0xF7, 0xA7, 0xC2, 0x7F, 0x3C, 0x21, +0x68, 0x3F, 0xCD, 0x11, 0x3E, 0xCA, 0x7F, 0x3C, +0xCD, 0x28, 0x49, 0x01, 0x06, 0x00, 0x11, 0xE8, +0xF7, 0x21, 0x46, 0xF7, 0xCD, 0x2B, 0x4A, 0xE1, +0xD1, 0xD5, 0xCD, 0xCA, 0x3C, 0x7C, 0xB5, 0xCA, +0xAA, 0x48, 0xE5, 0x3E, 0x01, 0x32, 0xD6, 0xF7, +0xCD, 0x69, 0x49, 0xCD, 0x98, 0x4A, 0xCA, 0xC5, +0x3C, 0x21, 0x82, 0x3F, 0xCD, 0x1A, 0x49, 0xCD, +0xEF, 0x3D, 0xE6, 0xDF, 0xE7, 0xFE, 0x52, 0xC2, +0xB3, 0x3C, 0xCD, 0x40, 0x43, 0xCD, 0x98, 0x4A, +0xC3, 0xC5, 0x3C, 0xE1, 0xD1, 0xFE, 0x41, 0xC0, +0x3A, 0xEF, 0xF7, 0xFE, 0x44, 0xC0, 0x3E, 0x02, +0x32, 0xD6, 0xF7, 0xD5, 0xE5, 0xE1, 0xD1, 0xC3, +0xBF, 0x40, 0x7E, 0xFE, 0xC0, 0xCA, 0xDD, 0x3C, +0xFE, 0xA0, 0xCA, 0xEC, 0x3C, 0xD5, 0xCD, 0x37, +0x4C, 0xC1, 0x08, 0x2B, 0xC9, 0xEB, 0x11, 0x00, +0x00, 0x7E, 0x23, 0x13, 0xFE, 0x1A, 0xC2, 0xE1, +0x3C, 0x1B, 0xEB, 0xC9, 0xEB, 0x23, 0x23, 0x4E, +0x23, 0x46, 0x21, 0x06, 0x00, 0x09, 0xC9, 0x3A, +0xCB, 0xF7, 0xA7, 0xC8, 0x3D, 0xCA, 0xBA, 0x37, +0xCD, 0x61, 0x4A, 0x21, 0x58, 0x3F, 0xCD, 0x11, +0x3E, 0xC8, 0xCD, 0x28, 0x49, 0x21, 0x46, 0xF7, +0x11, 0xE8, 0xF7, 0x01, 0x06, 0x00, 0xCD, 0x2B, +0x4A, 0x21, 0x3C, 0x3E, 0x22, 0xEF, 0xF7, 0x3E, +0x2E, 0x32, 0xEE, 0xF7, 0xCD, 0x69, 0x49, 0x3A, +0xCB, 0xF7, 0xFE, 0x02, 0xC0, 0xCD, 0x98, 0x4A, +0xC2, 0x44, 0x3D, 0x3E, 0x01, 0x32, 0xE8, 0xF7, +0x21, 0x01, 0x01, 0xCD, 0x92, 0x40, 0x21, 0x02, +0x00, 0xC3, 0x92, 0x40, 0xCD, 0x81, 0x40, 0xC3, +0x3E, 0x3D, 0x3A, 0xCB, 0xF7, 0xFE, 0x02, 0xC8, +0x21, 0x12, 0x3F, 0xCD, 0x1A, 0x49, 0xCD, 0xE5, +0x3D, 0xC0, 0xCD, 0x69, 0x49, 0xCD, 0x09, 0x4A, +0x21, 0x06, 0x00, 0xCD, 0x92, 0x40, 0x3E, 0x07, +0xE7, 0xC9, 0x3A, 0xCC, 0xF7, 0xA7, 0xCC, 0xD8, +0x3D, 0xCD, 0x61, 0x4A, 0xCD, 0x7A, 0x3D, 0xC3, +0x40, 0x43, 0x01, 0x09, 0x00, 0x2A, 0xE4, 0xF7, +0x11, 0xE8, 0xF7, 0xCD, 0x2B, 0x4A, 0xCD, 0x69, +0x49, 0xC3, 0x98, 0x4A, 0xCD, 0x28, 0x49, 0x21, +0x46, 0xF7, 0xCD, 0x7D, 0x4A, 0xC9, 0xCD, 0x61, +0x4A, 0xCD, 0x7A, 0x3D, 0x21, 0xE8, 0xF7, 0x11, +0x4F, 0xF7, 0x01, 0x09, 0x00, 0xCD, 0x2B, 0x4A, +0x2A, 0x1D, 0xF8, 0x4C, 0x45, 0x21, 0xB0, 0x77, +0x08, 0x21, 0x41, 0x3F, 0xC2, 0xCE, 0x3D, 0x01, +0x09, 0x00, 0xCD, 0x14, 0x3E, 0xC8, 0xE5, 0xF5, +0xCD, 0x61, 0x4A, 0xF1, 0xE1, 0x11, 0xE8, 0xF7, +0x4F, 0x06, 0x00, 0xC3, 0xA7, 0x41, 0xCD, 0x11, +0x3E, 0xC8, 0xCD, 0x28, 0x49, 0xC3, 0x9E, 0x41, +0x21, 0x7A, 0x3F, 0xCD, 0x1A, 0x49, 0xCD, 0xE5, +0x3D, 0xC2, 0xDB, 0x48, 0xC9, 0xCD, 0xEF, 0x3D, +0xE7, 0xFE, 0x59, 0xC8, 0xFE, 0x79, 0xC9, 0xCD, +0xF5, 0x3D, 0xC3, 0x0F, 0x4C, 0xAF, 0x3D, 0x32, +0x37, 0xEF, 0xCD, 0x72, 0x4C, 0xCA, 0xF5, 0x3D, +0xAF, 0x32, 0x37, 0xEF, 0x21, 0x22, 0xF2, 0xB6, +0xCA, 0x1B, 0x4C, 0xCD, 0x17, 0x4C, 0xC3, 0xF5, +0x3D, 0x01, 0x06, 0x00, 0xCD, 0x26, 0x3E, 0xC8, +0xE5, 0xF5, 0xCD, 0x82, 0x4C, 0x77, 0x23, 0xA7, +0xC2, 0x1A, 0x3E, 0xF1, 0xE1, 0xC9, 0xC5, 0xCD, +0x1A, 0x49, 0xCD, 0x6E, 0x4C, 0xDA, 0xDB, 0x48, +0x23, 0x78, 0x3D, 0xD1, 0xC8, 0xBB, 0xD8, 0xE5, +0x19, 0x36, 0x00, 0xE1, 0x7B, 0xB7, 0xC9, 0x21, +0xAA, 0xF2, 0x01, 0x0B, 0x00, 0x09, 0x7E, 0xFE, +0xFF, 0xCA, 0x51, 0x3E, 0x87, 0xDA, 0x45, 0x3E, +0xC9, 0x37, 0xC9, 0x2A, 0x5D, 0xF5, 0x01, 0x06, +0x09, 0x08, 0xCA, 0x16, 0x40, 0xC3, 0xF1, 0x3F, +0x1B, 0x70, 0x20, 0x54, 0x53, 0x2D, 0x44, 0x4F, +0x53, 0x20, 0x28, 0x32, 0x30, 0x30, 0x20, 0x76, +0x34, 0x2E, 0x30, 0x30, 0x29, 0x20, 0x28, 0x63, +0x29, 0x38, 0x37, 0x2C, 0x54, 0x53, 0x49, 0x2E, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x1B, 0x71, 0x20, 0x00, 0x44, 0x49, +0x53, 0x4B, 0x20, 0x46, 0x72, 0x65, 0x65, 0x3A, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x46, 0x69, 0x6C, 0x65, 0x3A, 0x0D, 0x0A, +0x4C, 0x6F, 0x61, 0x64, 0x20, 0x4B, 0x69, 0x6C, +0x6C, 0x20, 0x4E, 0x61, 0x6D, 0x65, 0x20, 0x52, +0x61, 0x6D, 0x20, 0x20, 0x46, 0x72, 0x6D, 0x74, +0x20, 0x4C, 0x6F, 0x67, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x4D, 0x65, 0x6E, 0x75, 0x00, +0x20, 0x52, 0x41, 0x4D, 0x20, 0x46, 0x72, 0x65, +0x65, 0x3A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x46, 0x69, 0x6C, 0x65, 0x3A, +0x0D, 0x0A, 0x53, 0x61, 0x76, 0x65, 0x20, 0x4B, +0x69, 0x6C, 0x6C, 0x20, 0x4E, 0x61, 0x6D, 0x65, +0x20, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x44, 0x4F, +0x53, 0x2D, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x20, 0x20, 0x4D, 0x65, 0x6E, +0x75, 0x00, 0x49, 0x6E, 0x73, 0x65, 0x72, 0x74, +0x20, 0x44, 0x69, 0x73, 0x6B, 0x2C, 0x20, 0x50, +0x72, 0x65, 0x73, 0x73, 0x20, 0x22, 0x59, 0x22, +0x20, 0x74, 0x6F, 0x20, 0x62, 0x65, 0x67, 0x69, +0x6E, 0x20, 0x00, 0x4E, 0x4F, 0x54, 0x20, 0x46, +0x4F, 0x52, 0x4D, 0x41, 0x54, 0x54, 0x45, 0x44, +0x00, 0x4E, 0x65, 0x77, 0x20, 0x4E, 0x61, 0x6D, +0x65, 0x3A, 0x00, 0x53, 0x79, 0x73, 0x74, 0x65, +0x6D, 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3A, 0x00, +0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, +0x79, 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3A, 0x00, +0x53, 0x61, 0x76, 0x65, 0x20, 0x61, 0x73, 0x3A, +0x00, 0x4C, 0x6F, 0x61, 0x64, 0x20, 0x61, 0x73, +0x3A, 0x00, 0x53, 0x75, 0x72, 0x65, 0x20, 0x3F, +0x20, 0x00, 0x46, 0x69, 0x6C, 0x65, 0x20, 0x65, +0x78, 0x69, 0x73, 0x74, 0x73, 0x2C, 0x20, 0x41, +0x29, 0x70, 0x70, 0x65, 0x6E, 0x64, 0x20, 0x52, +0x29, 0x65, 0x70, 0x6C, 0x61, 0x63, 0x65, 0x20, +0x51, 0x29, 0x75, 0x69, 0x74, 0x3A, 0x00, 0x46, +0x69, 0x6C, 0x65, 0x20, 0x65, 0x78, 0x69, 0x73, +0x74, 0x73, 0x2C, 0x20, 0x52, 0x65, 0x70, 0x6C, +0x61, 0x63, 0x65, 0x3F, 0x20, 0x28, 0x59, 0x2F, +0x4E, 0x29, 0x3A, 0x00, 0x2D, 0x2E, 0x2D, 0x20, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x1B, +0x59, 0x3F, 0x34, 0x20, 0x20, 0x20, 0x20, 0x1B, +0x59, 0x3F, 0x3E, 0x4D, 0x6B, 0x44, 0x72, 0x00, +0x1B, 0x59, 0x3F, 0x3E, 0x42, 0x61, 0x6E, 0x6B, +0x00, 0x4F, 0x46, 0x46, 0x00, 0x4F, 0x4E, 0x20, +0x00, 0x21, 0xA8, 0x9C, 0x22, 0x15, 0xF5, 0x22, +0x37, 0xF5, 0x22, 0x39, 0xF5, 0x22, 0x1F, 0xF5, +0x22, 0x23, 0xF5, 0x21, 0x06, 0x09, 0x22, 0x5D, +0xF5, 0x22, 0x63, 0xF5, 0x22, 0x65, 0xF5, 0x22, +0x67, 0xF5, 0x22, 0x69, 0xF5, 0xC9, 0xCD, 0xF1, +0x3F, 0x21, 0x7B, 0x40, 0x11, 0x2D, 0xF2, 0x01, +0x06, 0x00, 0xCD, 0x2B, 0x4A, 0x21, 0x2D, 0xF2, +0x22, 0x23, 0xF5, 0x22, 0x1F, 0xF5, 0x22, 0x69, +0xF5, 0x22, 0x67, 0xF5, 0x22, 0x37, 0xF5, 0x22, +0x39, 0xF5, 0x22, 0x5D, 0xF5, 0x22, 0x63, 0xF5, +0x22, 0x65, 0xF5, 0xC9, 0xF5, 0x3A, 0xF7, 0xF4, +0xFE, 0x1C, 0xCA, 0x77, 0x44, 0xFE, 0x18, 0xCA, +0x0D, 0x45, 0xFE, 0x62, 0xCA, 0xE7, 0x43, 0xFE, +0x60, 0xCA, 0x33, 0x44, 0xFE, 0x30, 0xCA, 0x4A, +0x43, 0xFE, 0x32, 0xCA, 0x43, 0x45, 0xFE, 0x56, +0xCA, 0x6C, 0x43, 0xFE, 0x5C, 0xCA, 0x9D, 0x43, +0xFE, 0x5E, 0xCA, 0xBC, 0x43, 0xF1, 0x1E, 0x02, +0xC3, 0x5F, 0x4C, 0xCD, 0xD3, 0xF4, 0xC3, 0x44, +0x40, 0x21, 0x01, 0x01, 0x3E, 0x03, 0x32, 0xE8, +0xF7, 0xC3, 0x92, 0x40, 0x67, 0x2E, 0x04, 0xC3, +0x9E, 0x40, 0xCD, 0x48, 0x48, 0xCD, 0x16, 0x4A, +0xCD, 0xF2, 0x47, 0xC3, 0x1E, 0x48, 0x22, 0x02, +0xF8, 0x21, 0x02, 0xF8, 0xCD, 0x4E, 0x48, 0xCD, +0xF2, 0x47, 0xC3, 0x1E, 0x48, 0x21, 0x03, 0x00, +0xCD, 0x48, 0x48, 0xCD, 0xF2, 0x47, 0x3A, 0x03, +0xF8, 0x21, 0x04, 0xF8, 0xFE, 0x80, 0xC9, 0xD5, +0xE5, 0xCD, 0xF8, 0x40, 0xE1, 0x22, 0xD5, 0xF7, +0xE1, 0x11, 0x04, 0xF8, 0x01, 0x80, 0x00, 0xCD, +0x2B, 0x4A, 0xE5, 0x2A, 0xD5, 0xF7, 0x01, 0x80, +0x00, 0x08, 0xDA, 0xEB, 0x40, 0xCA, 0xEB, 0x40, +0x22, 0xD5, 0xF7, 0x3E, 0x80, 0xCD, 0x8C, 0x40, +0xC3, 0xC8, 0x40, 0xE1, 0x3A, 0xD5, 0xF7, 0xCD, +0x8C, 0x40, 0x21, 0x02, 0x00, 0xC3, 0x92, 0x40, +0x11, 0x00, 0x05, 0xEB, 0xCD, 0x3F, 0x4C, 0x3A, +0x1F, 0xF8, 0x95, 0xDA, 0xA7, 0x48, 0xCA, 0xA7, +0x48, 0x3A, 0xD6, 0xF7, 0x32, 0xE8, 0xF7, 0x21, +0x01, 0x01, 0xC3, 0x92, 0x40, 0x2A, 0xE2, 0xF7, +0xCD, 0x2F, 0x4C, 0xDA, 0xB0, 0x48, 0x2A, 0xE2, +0xF7, 0xE5, 0xCD, 0x81, 0x40, 0xCD, 0xAD, 0x40, +0x4F, 0x06, 0x00, 0xD1, 0xCD, 0x2B, 0x4A, 0xD5, +0x3A, 0x03, 0xF8, 0x2A, 0xDD, 0xF7, 0x4F, 0x06, +0x00, 0x08, 0x22, 0xDD, 0xF7, 0xDA, 0x45, 0x41, +0x7D, 0xB4, 0xC2, 0x25, 0x41, 0xD1, 0xC9, 0x3A, +0xDD, 0xF7, 0xFE, 0x01, 0xC8, 0xCD, 0xBE, 0x49, +0x3E, 0x57, 0x32, 0xD3, 0xF7, 0xCD, 0xF4, 0x42, +0xCD, 0xBE, 0x49, 0xCD, 0x6D, 0x41, 0x2A, 0xE4, +0xF7, 0xCD, 0xFF, 0x48, 0x22, 0xE4, 0xF7, 0xCD, +0x14, 0x43, 0xC3, 0x47, 0x41, 0x3A, 0x09, 0xF8, +0xCD, 0x88, 0x41, 0xFE, 0x35, 0xCA, 0x80, 0x41, +0x21, 0xDE, 0xF7, 0x34, 0x7E, 0xFE, 0x14, 0xC0, +0x21, 0xDD, 0xF7, 0x34, 0x23, 0x36, 0x01, 0xC9, +0x01, 0x00, 0x05, 0xFE, 0x35, 0xC8, 0x01, 0x40, +0x00, 0xC9, 0x21, 0x08, 0x00, 0xCD, 0x48, 0x48, +0xCD, 0xF9, 0x49, 0xC3, 0xBE, 0x49, 0x21, 0x46, +0xF7, 0x11, 0xE8, 0xF7, 0x01, 0x06, 0x00, 0xCD, +0x2B, 0x4A, 0x3A, 0xCB, 0xF7, 0xA7, 0xC2, 0x5A, +0x42, 0xCD, 0x98, 0x4A, 0xC2, 0xA4, 0x48, 0x11, +0x00, 0x05, 0xCD, 0x2E, 0x43, 0x21, 0x00, 0x01, +0x22, 0xDD, 0xF7, 0xCD, 0x92, 0x41, 0xCD, 0x80, +0x42, 0x2A, 0x69, 0xF6, 0xE5, 0x06, 0x28, 0x11, +0x4F, 0xF7, 0xCD, 0x6B, 0x42, 0xDA, 0xA1, 0x48, +0x78, 0xA7, 0xCA, 0xA1, 0x48, 0xE5, 0x11, 0xE8, +0xF7, 0xEB, 0x01, 0x09, 0x00, 0xCD, 0x2B, 0x4A, +0xE1, 0xE5, 0x11, 0x20, 0xF8, 0x01, 0x1F, 0x00, +0xCD, 0x2B, 0x4A, 0xD1, 0xD5, 0x21, 0x1F, 0x00, +0x19, 0xE5, 0x2A, 0x69, 0xF6, 0x01, 0x00, 0x05, +0x09, 0xC1, 0xC5, 0x08, 0xE3, 0xC1, 0xCD, 0x2B, +0x4A, 0x2A, 0x69, 0xF6, 0x06, 0x27, 0x11, 0x20, +0xF8, 0xCD, 0x6B, 0x42, 0xE5, 0x2A, 0x69, 0xF6, +0x01, 0xFF, 0x04, 0x09, 0xE5, 0x01, 0x1F, 0x00, +0x08, 0xD1, 0xC1, 0xC5, 0xE5, 0x08, 0xE5, 0xC1, +0x03, 0xE1, 0xCD, 0x4F, 0x42, 0x21, 0x20, 0xF8, +0xD1, 0x01, 0x1F, 0x00, 0xCD, 0x2B, 0x4A, 0x21, +0x01, 0x14, 0x22, 0xDE, 0xF7, 0xE1, 0xE1, 0x22, +0xE4, 0xF7, 0x21, 0x00, 0x01, 0x22, 0xDD, 0xF7, +0xCD, 0x47, 0x41, 0xCD, 0xF3, 0x49, 0xC9, 0x7E, +0x12, 0x2B, 0x1B, 0x0B, 0x78, 0xB1, 0xC2, 0x4F, +0x42, 0xC9, 0x21, 0x0D, 0x19, 0xCD, 0x48, 0x48, +0xCD, 0xF2, 0x47, 0x3A, 0x04, 0xF8, 0xA7, 0xC2, +0xA4, 0x48, 0xC9, 0x0E, 0x09, 0xCD, 0x42, 0x4A, +0xC8, 0xD8, 0x7E, 0xB7, 0xC8, 0xC5, 0x01, 0x1F, +0x00, 0x09, 0xC1, 0x05, 0xC8, 0xC3, 0x6B, 0x42, +0x2A, 0xE2, 0xF7, 0xCD, 0x8E, 0x42, 0x3A, 0xDD, +0xF7, 0x3D, 0xC8, 0xC3, 0x83, 0x42, 0xE5, 0x3E, +0x52, 0x32, 0xD3, 0xF7, 0xCD, 0xF4, 0x42, 0xCD, +0x6D, 0x41, 0xC5, 0x3E, 0x0D, 0xCD, 0x85, 0x48, +0xC1, 0xE1, 0xF3, 0xCD, 0xB1, 0x42, 0xDA, 0x90, +0x48, 0x0B, 0x79, 0xB0, 0xC2, 0xA3, 0x42, 0xFB, +0xC9, 0xAF, 0xE5, 0x32, 0xD8, 0xF7, 0xCD, 0x88, +0x48, 0xDB, 0xCF, 0x6F, 0xE6, 0x02, 0xC2, 0xD0, +0x42, 0xAF, 0x21, 0xD8, 0xF7, 0xB6, 0xCA, 0xB6, +0x42, 0x34, 0xC2, 0xB6, 0x42, 0xE1, 0x37, 0xC9, +0xDB, 0xCE, 0x67, 0x7D, 0xE6, 0x38, 0xC2, 0xDE, +0x42, 0x7C, 0xE1, 0x77, 0x23, 0xC9, 0x3A, 0xFE, +0xFC, 0xF6, 0x10, 0xD3, 0xCF, 0xC3, 0xCD, 0x42, +0x06, 0x2F, 0xD6, 0x0A, 0x04, 0xD2, 0xEA, 0x42, +0xC6, 0x3A, 0x4F, 0xC9, 0x3A, 0xDD, 0xF7, 0xCD, +0xE8, 0x42, 0x3A, 0xD3, 0xF7, 0xCD, 0x85, 0x48, +0xCD, 0x01, 0x4A, 0x3A, 0xDE, 0xF7, 0xCD, 0xE8, +0x42, 0x3E, 0x2C, 0xCD, 0x85, 0x48, 0xCD, 0x01, +0x4A, 0xCD, 0xF9, 0x49, 0x21, 0x04, 0xF8, 0xE5, +0x0E, 0x08, 0xCD, 0x0B, 0x48, 0x0D, 0xC2, 0x1A, +0x43, 0xE1, 0x7E, 0xFE, 0x30, 0xC8, 0xFE, 0x42, +0xCA, 0x93, 0x48, 0xC3, 0x8D, 0x48, 0x2A, 0x69, +0xF6, 0xE5, 0x22, 0xE2, 0xF7, 0x21, 0xC0, 0xFF, +0x39, 0xC1, 0x08, 0xDF, 0xDA, 0xB0, 0x48, 0xC9, +0xAF, 0x32, 0x01, 0xF8, 0x21, 0x05, 0x00, 0xC3, +0x92, 0x40, 0xF1, 0xFE, 0x30, 0xDA, 0xA2, 0x00, +0xFE, 0x32, 0xD2, 0xA2, 0x00, 0xD6, 0x30, 0x32, +0xCA, 0xF7, 0x23, 0x1D, 0x7E, 0xFE, 0x3A, 0xC2, +0xA2, 0x00, 0x23, 0x1D, 0xE3, 0xE1, 0x3E, 0x09, +0xB7, 0xC3, 0xA2, 0x00, 0xF1, 0xD5, 0xE5, 0xF5, +0xAF, 0xCD, 0xAB, 0x4A, 0x38, 0x02, 0xED, 0x7E, +0xA7, 0xCA, 0x90, 0x43, 0xFE, 0x3A, 0xCA, 0x90, +0x43, 0xCD, 0x96, 0x4C, 0x7B, 0xFE, 0x02, 0xD2, +0x96, 0x43, 0x32, 0xCA, 0xF7, 0x38, 0x02, 0xD9, +0xCD, 0x2A, 0x47, 0xCD, 0xEA, 0x4A, 0xF1, 0xE1, +0xD1, 0xC1, 0xC3, 0xA2, 0x00, 0xF1, 0xFE, 0x09, +0xC2, 0x3C, 0x45, 0xD5, 0xE5, 0xF5, 0xAF, 0xCD, +0xAB, 0x4A, 0x21, 0x46, 0xF7, 0xCD, 0x7D, 0x4A, +0xCA, 0xA1, 0x48, 0xCD, 0x40, 0x43, 0xCD, 0xEA, +0x4A, 0xC3, 0x96, 0x43, 0xF1, 0xFE, 0x09, 0xC2, +0x3C, 0x45, 0xD5, 0xE5, 0xF5, 0xAF, 0xCD, 0xAB, +0x4A, 0x21, 0x4F, 0xF7, 0xCD, 0x7D, 0x4A, 0xCA, +0xA1, 0x48, 0x21, 0xE8, 0xF7, 0x11, 0x4F, 0xF7, +0x01, 0x09, 0x00, 0xCD, 0x2B, 0x4A, 0xCD, 0x9E, +0x41, 0xCD, 0xEA, 0x4A, 0xC3, 0x96, 0x43, 0xF1, +0xFE, 0x09, 0xC2, 0xA2, 0x00, 0xC1, 0xE5, 0x01, +0x43, 0x4F, 0xCD, 0xE0, 0x44, 0xCA, 0xA1, 0x48, +0xCD, 0x81, 0x40, 0x2A, 0x1D, 0xF8, 0x7D, 0x6C, +0x67, 0x22, 0xDD, 0xF7, 0xCD, 0xAD, 0x40, 0xCD, +0x8E, 0x4C, 0xE5, 0xCD, 0x92, 0x4C, 0x2A, 0xFB, +0xF4, 0xE5, 0xE5, 0x2A, 0xB4, 0xEE, 0xE3, 0xC1, +0x08, 0xDA, 0xB0, 0x48, 0xD1, 0xE1, 0x3A, 0x03, +0xF8, 0xD6, 0x06, 0x4F, 0x06, 0x00, 0xCD, 0x2C, +0x41, 0xCD, 0xEA, 0x4A, 0x21, 0x8A, 0x32, 0xE5, +0xC3, 0xA2, 0x00, 0xF1, 0xFE, 0x09, 0xC2, 0xA2, +0x00, 0xCD, 0x9A, 0x4C, 0x01, 0x43, 0x4F, 0xCD, +0xE0, 0x44, 0xC2, 0xA4, 0x48, 0x3E, 0x01, 0x32, +0xD6, 0xF7, 0x2A, 0xFD, 0xF4, 0x01, 0x06, 0x00, +0xC5, 0x09, 0xE5, 0xCD, 0xF8, 0x40, 0xE1, 0x22, +0xD5, 0xF7, 0xC1, 0x21, 0xFB, 0xF4, 0x11, 0x04, +0xF8, 0xCD, 0x2B, 0x4A, 0x2A, 0x04, 0xF8, 0x01, +0x7A, 0x00, 0xCD, 0xCF, 0x40, 0xCD, 0xEA, 0x4A, +0x21, 0x2C, 0x05, 0xE5, 0xC3, 0xA2, 0x00, 0xF1, +0xFE, 0x09, 0xC2, 0xA2, 0x00, 0xC1, 0xF1, 0xF5, +0xC5, 0xCA, 0xA2, 0x00, 0x9F, 0x32, 0x45, 0xF7, +0x01, 0x42, 0x41, 0xCD, 0xE0, 0x44, 0xCA, 0xA1, +0x48, 0x2A, 0x1D, 0xF8, 0x4C, 0x45, 0x60, 0x69, +0x22, 0xDD, 0xF7, 0xCD, 0xD1, 0x44, 0x23, 0x22, +0xE2, 0xF7, 0x2A, 0xDD, 0xF7, 0xE5, 0xE5, 0xC1, +0xCD, 0x15, 0x41, 0xD1, 0x2A, 0x61, 0xF6, 0x19, +0x22, 0x61, 0xF6, 0x2A, 0x05, 0xF5, 0x19, 0x22, +0x05, 0xF5, 0xCD, 0xEA, 0x4A, 0xAF, 0x21, 0x65, +0x31, 0xE5, 0xC3, 0xA2, 0x00, 0xAF, 0xD3, 0xD0, +0xCD, 0x1C, 0x2C, 0xCD, 0xD3, 0xF4, 0xC3, 0x9E, +0x44, 0x21, 0xC5, 0x44, 0x11, 0x89, 0xF8, 0x01, +0x0C, 0x00, 0xCD, 0x2B, 0x4A, 0xC3, 0x89, 0xF8, +0xF5, 0xE5, 0xD5, 0xC5, 0x2A, 0x4C, 0xF7, 0x11, +0x20, 0x20, 0xDF, 0xCA, 0xFC, 0x44, 0xD1, 0xD5, +0xDF, 0xCA, 0xFC, 0x44, 0xC1, 0xD1, 0xE1, 0xF1, +0xC1, 0xC3, 0xA2, 0x00, 0xE1, 0x22, 0x4C, 0xF7, +0xD1, 0xE1, 0xF1, 0xAF, 0xCD, 0xAB, 0x4A, 0x21, +0x46, 0xF7, 0xC3, 0x7D, 0x4A, 0xF1, 0xFE, 0x09, +0xC2, 0xA2, 0x00, 0x01, 0x42, 0x41, 0xCD, 0xE0, +0x44, 0xC2, 0xA4, 0x48, 0xCD, 0x8A, 0x4C, 0x2A, +0x67, 0xEF, 0xEB, 0xDF, 0xCA, 0x35, 0x45, 0xD5, +0xC1, 0x08, 0x3E, 0x01, 0x32, 0xD6, 0xF7, 0xCD, +0xBF, 0x40, 0xCD, 0xEA, 0x4A, 0x21, 0x2D, 0x05, +0xE5, 0xC3, 0xA2, 0x00, 0x21, 0x06, 0x09, 0xE5, +0xC3, 0xA2, 0x00, 0xAF, 0x32, 0xD2, 0xF7, 0xF1, +0x22, 0xCE, 0xF7, 0xD5, 0xE5, 0xF5, 0x11, 0x04, +0x00, 0x19, 0x7E, 0xFE, 0x09, 0xCA, 0x5E, 0x45, +0xF1, 0xE1, 0xD1, 0xC3, 0xA2, 0x00, 0xF1, 0xF5, +0xFE, 0x00, 0xCA, 0x82, 0x45, 0xFE, 0x02, 0xCA, +0x0E, 0x46, 0xFE, 0x04, 0xCA, 0xD6, 0x46, 0xFE, +0x06, 0xCA, 0x2D, 0x46, 0xFE, 0x08, 0xC2, 0x58, +0x45, 0x38, 0x06, 0x21, 0x49, 0x17, 0xD9, 0xC3, +0x58, 0x45, 0xAF, 0xCD, 0xAB, 0x4A, 0x21, 0x4C, +0xF7, 0x7E, 0xFE, 0x20, 0xCA, 0x94, 0x45, 0xFE, +0x44, 0xC2, 0xB3, 0x48, 0x36, 0x44, 0x23, 0x36, +0x4F, 0x21, 0x46, 0xF7, 0xCD, 0x7D, 0x4A, 0x4F, +0xCD, 0x81, 0x46, 0x36, 0x00, 0xE1, 0xE1, 0xD1, +0xD5, 0xE5, 0x51, 0x7B, 0xE6, 0x07, 0x21, 0x0C, +0x4B, 0x4F, 0x06, 0x00, 0x09, 0x7E, 0x3D, 0xCA, +0xF3, 0x45, 0x3D, 0xC2, 0x06, 0x46, 0x3A, 0x1C, +0xF8, 0xA7, 0xC2, 0xC7, 0x45, 0x23, 0x23, 0x7E, +0x32, 0xE8, 0xF7, 0x21, 0x01, 0x01, 0xCD, 0x92, +0x40, 0x2A, 0xCE, 0xF7, 0x11, 0x07, 0x00, 0x19, +0xAF, 0x77, 0x23, 0x54, 0x5D, 0x23, 0x23, 0xD9, +0xE1, 0xD1, 0x7B, 0xFE, 0x08, 0xC2, 0xEA, 0x45, +0x1E, 0x02, 0x73, 0xE3, 0x21, 0xF5, 0x15, 0xE3, +0xC3, 0xA2, 0x00, 0x7A, 0xB7, 0xCA, 0xC7, 0x45, +0xE5, 0xCD, 0x40, 0x43, 0x21, 0x46, 0xF7, 0xCD, +0x7D, 0x4A, 0xE1, 0xC3, 0xC7, 0x45, 0x7A, 0xB7, +0xCA, 0xA1, 0x48, 0xC3, 0xC7, 0x45, 0xF1, 0xE1, +0xD1, 0xE5, 0x7E, 0x36, 0x00, 0xFE, 0x02, 0xCC, +0x03, 0x47, 0x21, 0x02, 0x00, 0xCD, 0x92, 0x40, +0xCD, 0xEA, 0x4A, 0xE1, 0xE3, 0xE1, 0x21, 0x18, +0x5C, 0xE5, 0xC3, 0xA2, 0x00, 0xCD, 0x81, 0x46, +0x7E, 0x36, 0x00, 0xA7, 0xC2, 0x4D, 0x46, 0x2A, +0xCE, 0xF7, 0x01, 0x07, 0x00, 0x09, 0x7E, 0x23, +0xE5, 0xA7, 0xCC, 0x89, 0x46, 0xD1, 0xED, 0x7E, +0x23, 0xD9, 0x1B, 0xEB, 0x35, 0xFE, 0x1A, 0x37, +0x3F, 0xC2, 0x59, 0x46, 0xCD, 0x81, 0x46, 0x77, +0x37, 0xF5, 0x38, 0x10, 0xED, 0x01, 0x09, 0x1A, +0x08, 0xC2, 0x75, 0x46, 0xCD, 0x81, 0x46, 0xF1, +0x77, 0x4F, 0x9F, 0xCD, 0xF3, 0x4B, 0x38, 0x12, +0xEB, 0xF9, 0xC3, 0xA2, 0x00, 0xF1, 0xE1, 0xE1, +0xD1, 0xE3, 0x21, 0x46, 0x5D, 0xE3, 0xC3, 0xA2, +0x00, 0x2A, 0xD1, 0xF4, 0x11, 0xC0, 0xF4, 0x19, +0xC9, 0x21, 0x03, 0x00, 0xCD, 0x48, 0x48, 0xCD, +0xF2, 0x47, 0x3A, 0x02, 0xF8, 0xFE, 0x10, 0xC2, +0xC4, 0x46, 0x3A, 0x03, 0xF8, 0x2A, 0xCE, 0xF7, +0x11, 0x08, 0x00, 0x19, 0xE5, 0x54, 0x5D, 0x23, +0x23, 0xD9, 0x11, 0x04, 0xF8, 0xEB, 0x4F, 0x06, +0x00, 0xCD, 0x2B, 0x4A, 0x3A, 0x03, 0xF8, 0xFE, +0x80, 0xCA, 0xC0, 0x46, 0xEB, 0x36, 0x1A, 0x3C, +0xE1, 0x2B, 0x77, 0xC9, 0x2A, 0xCE, 0xF7, 0x11, +0x07, 0x00, 0x19, 0x36, 0x01, 0x23, 0x54, 0x5D, +0x23, 0x23, 0xD9, 0x36, 0x1A, 0xC9, 0x2A, 0xCE, +0xF7, 0x11, 0x07, 0x00, 0x19, 0x7E, 0xFE, 0x80, +0xCC, 0x03, 0x47, 0xF1, 0xE1, 0xD1, 0xE1, 0xF1, +0xF5, 0xFE, 0x1A, 0xCA, 0xFC, 0x46, 0x2A, 0xCE, +0xF7, 0x11, 0x07, 0x00, 0x19, 0x34, 0x23, 0xEB, +0xED, 0x77, 0x23, 0xD9, 0x21, 0x01, 0x16, 0xE5, +0xC3, 0xA2, 0x00, 0x2A, 0xCE, 0xF7, 0x01, 0x07, +0x00, 0x09, 0x7E, 0xE5, 0x23, 0x23, 0x23, 0x11, +0x04, 0xF8, 0x4F, 0x06, 0x00, 0xF5, 0xCD, 0x2B, +0x4A, 0xF1, 0xA7, 0xC4, 0x8C, 0x40, 0xE1, 0x36, +0x00, 0x23, 0x54, 0x5D, 0x23, 0x23, 0xD9, 0xC9, +0xF1, 0xC9, 0x21, 0x70, 0xEF, 0x22, 0xDB, 0xF7, +0xCD, 0x5B, 0x47, 0xC2, 0x90, 0x48, 0xAF, 0x32, +0xDA, 0xF7, 0x32, 0xD4, 0xF7, 0x3D, 0x32, 0xD7, +0xF7, 0x3E, 0x01, 0x32, 0x07, 0xEF, 0xCD, 0x6D, +0x47, 0xC3, 0x4B, 0x4C, 0xCD, 0x36, 0x4A, 0xCD, +0x66, 0x4C, 0x21, 0xF7, 0x4A, 0xCD, 0x52, 0x4A, +0xC3, 0x4B, 0x4C, 0xAF, 0x32, 0xD6, 0xF7, 0xCD, +0x69, 0x49, 0x21, 0x46, 0x01, 0xC3, 0x95, 0x47, +0x3E, 0x2E, 0x32, 0xD7, 0xF7, 0x3A, 0xCB, 0xF7, +0xA7, 0xC2, 0x7D, 0x47, 0x21, 0xF6, 0x02, 0xCD, +0x95, 0x47, 0xC2, 0x1E, 0x48, 0x3A, 0x04, 0xF8, +0xA7, 0xC8, 0x3A, 0xDA, 0xF7, 0xA7, 0xCC, 0xA7, +0x47, 0x21, 0xD6, 0xF7, 0x34, 0x3A, 0xD7, 0xF7, +0xBE, 0xC2, 0x74, 0x47, 0xC9, 0x22, 0x00, 0xF8, +0x21, 0x00, 0x1A, 0xCD, 0x48, 0x48, 0xCD, 0xF2, +0x47, 0x3A, 0x02, 0xF8, 0xFE, 0x11, 0xC9, 0x0E, +0x09, 0x21, 0x04, 0xF8, 0xCD, 0x0B, 0x49, 0x3E, +0x20, 0xE7, 0x2A, 0x1D, 0xF8, 0x5C, 0x55, 0x2A, +0xDB, 0xF7, 0xEB, 0xD9, 0xEB, 0x23, 0x23, 0x22, +0xDB, 0xF7, 0xC9, 0x21, 0x02, 0xF8, 0xE5, 0xCD, +0xB2, 0xF8, 0xCD, 0xB2, 0xF8, 0x4F, 0xCD, 0xB2, +0xF8, 0x41, 0x79, 0xA7, 0xCA, 0xA4, 0xF8, 0xCD, +0xB2, 0xF8, 0x0D, 0xC2, 0x9D, 0xF8, 0xE1, 0x04, +0x04, 0xAF, 0x30, 0x86, 0x23, 0x05, 0xC2, 0xA9, +0xF8, 0x2F, 0xBE, 0xC9, 0xCD, 0x19, 0x85, 0x77, +0x23, 0xC9, 0x21, 0xC3, 0x47, 0x11, 0x89, 0xF8, +0x01, 0x2F, 0x00, 0xCD, 0x2B, 0x4A, 0xCD, 0x88, +0x48, 0xCD, 0x03, 0x4C, 0xCF, 0x89, 0xF8, 0xC2, +0x90, 0x48, 0xC9, 0xCD, 0x11, 0x48, 0x77, 0x23, +0xC9, 0xCD, 0x88, 0x48, 0xCD, 0x0B, 0x4C, 0xDA, +0xB3, 0x48, 0xC2, 0x90, 0x48, 0xC9, 0x3A, 0x02, +0xF8, 0xFE, 0x12, 0xC2, 0x90, 0x48, 0x3A, 0x04, +0xF8, 0xA7, 0xC8, 0xFE, 0x10, 0xCA, 0xA4, 0x48, +0xFE, 0x50, 0xCA, 0x93, 0x48, 0xFE, 0x60, 0xCA, +0xA7, 0x48, 0xDA, 0x90, 0x48, 0xCA, 0x99, 0x48, +0xFE, 0x80, 0xDA, 0x99, 0x48, 0xC3, 0x96, 0x48, +0x22, 0xE6, 0xF7, 0x21, 0xE6, 0xF7, 0xE5, 0x3A, +0xCA, 0xF7, 0xA7, 0xCA, 0x5D, 0x48, 0xE6, 0x01, +0x1F, 0x1F, 0x1F, 0xB6, 0x77, 0x7E, 0x23, 0x86, +0x47, 0x7E, 0xF5, 0x23, 0xA7, 0xCA, 0x71, 0x48, +0x4F, 0x78, 0x86, 0x23, 0x0D, 0xC2, 0x6A, 0x48, +0x47, 0x78, 0x2F, 0x57, 0x01, 0x5A, 0x5A, 0xCD, +0x01, 0x4A, 0xC1, 0x48, 0x06, 0x00, 0x03, 0x03, +0xE1, 0xCD, 0xFF, 0x48, 0x7A, 0xCD, 0x07, 0x4C, +0xDB, 0xCF, 0xE6, 0x80, 0xC0, 0x3E, 0x01, 0x21, +0x3E, 0x02, 0x21, 0x3E, 0x03, 0x21, 0x3E, 0x04, +0x21, 0x3E, 0x05, 0x21, 0xD9, 0xF7, 0x36, 0x00, +0x21, 0x3E, 0x06, 0x21, 0x3E, 0x07, 0x21, 0x3E, +0x08, 0x21, 0x3E, 0x09, 0x21, 0x3E, 0x0A, 0x21, +0x3E, 0x0B, 0x21, 0x3E, 0x0C, 0x21, 0x3E, 0x0D, +0x21, 0x2A, 0x4B, 0x4F, 0x0D, 0xCA, 0xCA, 0x48, +0x7E, 0x23, 0xFE, 0x00, 0xC2, 0xC0, 0x48, 0xC3, +0xBC, 0x48, 0x3A, 0xD2, 0xF7, 0xA7, 0xCA, 0xF6, +0x48, 0x3E, 0x07, 0xE7, 0x23, 0xCD, 0x1A, 0x49, +0xCD, 0xED, 0x48, 0x2A, 0xCE, 0xF7, 0xF9, 0x2A, +0xD0, 0xF7, 0xE5, 0xC9, 0xCD, 0x4B, 0x4C, 0xCD, +0xED, 0x48, 0xC3, 0x4B, 0x4C, 0x21, 0xE3, 0x4B, +0xCD, 0x52, 0x4A, 0xC3, 0x0F, 0x4C, 0x5E, 0x2A, +0xCE, 0xF7, 0x36, 0x00, 0xC3, 0x5F, 0x4C, 0x7E, +0xCD, 0x85, 0x48, 0x23, 0x0B, 0x79, 0xB0, 0xC2, +0xFF, 0x48, 0xC9, 0x7E, 0xFE, 0x20, 0xD2, 0x13, +0x49, 0x3E, 0x20, 0xE7, 0x23, 0x0D, 0xC2, 0x0B, +0x49, 0xC9, 0xE5, 0x21, 0x10, 0x01, 0x22, 0x06, +0xEF, 0xCD, 0x53, 0x4C, 0xE1, 0xC3, 0x52, 0x4A, +0xE5, 0x3E, 0x20, 0x21, 0x46, 0xF7, 0x06, 0x08, +0xCD, 0x5A, 0x4A, 0xE1, 0x11, 0x46, 0xF7, 0x06, +0x06, 0x7E, 0xFE, 0x41, 0xDA, 0xB6, 0x48, 0x7E, +0xFE, 0x2E, 0xCA, 0x51, 0x49, 0xB7, 0xC8, 0x12, +0x23, 0x13, 0x05, 0xC2, 0x3F, 0x49, 0xC3, 0x59, +0x49, 0x3E, 0x20, 0x12, 0x13, 0x05, 0xC2, 0x53, +0x49, 0x06, 0x02, 0x23, 0x7E, 0xB7, 0xC8, 0x12, +0x13, 0x05, 0xC2, 0x5B, 0x49, 0x3E, 0x00, 0x12, +0xC9, 0xCD, 0xBA, 0x4A, 0xCD, 0xC8, 0x49, 0xCD, +0xF2, 0x47, 0xCD, 0x1E, 0x48, 0x3A, 0xCB, 0xF7, +0xA7, 0xC8, 0x21, 0x08, 0x00, 0xCD, 0x48, 0x48, +0xCD, 0xF2, 0x47, 0x3A, 0x03, 0xF8, 0xFE, 0x01, +0xCA, 0x9D, 0x49, 0x3D, 0x4F, 0x3E, 0x02, 0x32, +0xCB, 0xF7, 0x06, 0x00, 0x21, 0x05, 0xF8, 0x11, +0xC0, 0xF7, 0xC3, 0x2B, 0x4A, 0x21, 0x23, 0x00, +0xCD, 0x48, 0x48, 0xCD, 0xF2, 0x47, 0x21, 0x0F, +0x4B, 0xCD, 0xB5, 0x49, 0x21, 0x18, 0x4B, 0xCD, +0xB5, 0x49, 0x21, 0x21, 0x4B, 0x01, 0x09, 0x00, +0xCD, 0xFF, 0x48, 0xC3, 0xF2, 0x47, 0xCD, 0xFF, +0x4B, 0xC8, 0xCD, 0x11, 0x48, 0xC3, 0xBE, 0x49, +0xCD, 0x88, 0x48, 0xCD, 0xF3, 0x49, 0xCD, 0xBE, +0x49, 0xCD, 0x92, 0x41, 0xCD, 0xF9, 0x49, 0xCD, +0xFF, 0x4B, 0x3E, 0x00, 0xC2, 0xE0, 0x49, 0x3C, +0x32, 0xCB, 0xF7, 0xCD, 0xBE, 0x49, 0xCD, 0xF3, +0x49, 0xCD, 0xBE, 0x49, 0x21, 0x07, 0x00, 0xCD, +0x48, 0x48, 0xC9, 0x01, 0x31, 0x4D, 0xCD, 0x01, +0x4A, 0x3E, 0x0D, 0xCD, 0x85, 0x48, 0xC3, 0x09, +0x4A, 0x78, 0xCD, 0x85, 0x48, 0x79, 0xC3, 0x85, +0x48, 0x26, 0x14, 0x2E, 0xFF, 0x2D, 0xC2, 0x0D, +0x4A, 0x25, 0xC2, 0x0B, 0x4A, 0xC9, 0x01, 0x50, +0xFF, 0xCD, 0x09, 0x4A, 0xCD, 0xFF, 0x4B, 0xC0, +0x05, 0xC2, 0x19, 0x4A, 0x0D, 0xC2, 0x19, 0x4A, +0xC3, 0x8D, 0x48, 0x7E, 0x12, 0x23, 0x13, 0x0B, +0x78, 0xB1, 0xC2, 0x2B, 0x4A, 0xC9, 0x3A, 0x1F, +0xF8, 0x6F, 0x26, 0x00, 0x11, 0x80, 0x00, 0xC3, +0x43, 0x4C, 0xD5, 0xE5, 0x1A, 0x96, 0xC2, 0x4F, +0x4A, 0x23, 0x13, 0x0D, 0xC2, 0x44, 0x4A, 0xE1, +0xD1, 0xC9, 0x7E, 0xA7, 0xC8, 0xE7, 0x23, 0xC3, +0x52, 0x4A, 0x77, 0x23, 0x05, 0xC2, 0x5A, 0x4A, +0xC9, 0x3E, 0x20, 0x06, 0x18, 0x21, 0xE8, 0xF7, +0xCD, 0x5A, 0x4A, 0x3E, 0x46, 0x32, 0x00, 0xF8, +0xC9, 0x2A, 0xE4, 0xF7, 0xCD, 0x28, 0x49, 0xCD, +0x33, 0x4C, 0xC3, 0x1F, 0x4C, 0xE5, 0xCD, 0x61, +0x4A, 0xE1, 0x11, 0xE8, 0xF7, 0x01, 0x06, 0x00, +0xCD, 0x2B, 0x4A, 0x3E, 0x2E, 0x12, 0x13, 0x01, +0x02, 0x00, 0xCD, 0x2B, 0x4A, 0xCD, 0x69, 0x49, +0x3E, 0x00, 0x32, 0x01, 0xF8, 0x21, 0x00, 0x1A, +0xCD, 0x48, 0x48, 0xCD, 0xF2, 0x47, 0x3A, 0x1C, +0xF8, 0xA7, 0xC9, 0x32, 0xD2, 0xF7, 0x11, 0xA3, +0xF2, 0x21, 0x3C, 0xEF, 0x01, 0x07, 0x00, 0xC3, +0x2B, 0x4A, 0xCD, 0xFB, 0x4B, 0x21, 0x04, 0x4B, +0x11, 0x3C, 0xEF, 0x01, 0x07, 0x00, 0xCD, 0x2B, +0x4A, 0x21, 0x3C, 0xEF, 0x37, 0xCD, 0xF7, 0x4B, +0xCD, 0xBE, 0x49, 0xCD, 0xC8, 0x49, 0xCD, 0x09, +0x4A, 0xCD, 0xFF, 0x4B, 0xC2, 0xBE, 0x49, 0xCD, +0xFB, 0x4B, 0x21, 0x3C, 0xEF, 0x35, 0x37, 0xC3, +0xF7, 0x4B, 0x21, 0xA3, 0xF2, 0x7E, 0xD6, 0x3A, +0xDA, 0xF7, 0x4B, 0x23, 0xC3, 0xF7, 0x4B, 0x30, +0x20, 0x42, 0x79, 0x74, 0x65, 0x73, 0x20, 0x66, +0x72, 0x65, 0x65, 0x00, 0x39, 0x38, 0x4E, 0x31, +0x44, 0x4E, 0x4E, 0x00, 0x02, 0x03, 0x01, 0x5A, +0x5A, 0x31, 0x04, 0x01, 0x00, 0x84, 0xFF, 0x46, +0x5A, 0x5A, 0x31, 0x04, 0x01, 0x00, 0x96, 0x0F, +0x24, 0x5A, 0x5A, 0x31, 0x04, 0x01, 0x00, 0x94, +0x0F, 0x26, 0x12, 0x44, 0x72, 0x69, 0x76, 0x65, +0x20, 0x4E, 0x6F, 0x74, 0x20, 0x52, 0x65, 0x61, +0x64, 0x79, 0x00, 0x12, 0x43, 0x6F, 0x6D, 0x6D, +0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, +0x6E, 0x20, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x00, +0x12, 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, 0x50, +0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x00, 0x12, +0x44, 0x72, 0x69, 0x76, 0x65, 0x20, 0x54, 0x72, +0x6F, 0x75, 0x62, 0x6C, 0x65, 0x00, 0x12, 0x44, +0x69, 0x73, 0x6B, 0x20, 0x6E, 0x6F, 0x74, 0x20, +0x69, 0x6E, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, +0x00, 0x34, 0x50, 0x72, 0x69, 0x6E, 0x74, 0x65, +0x72, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x65, +0x61, 0x64, 0x79, 0x00, 0x05, 0x46, 0x69, 0x6C, +0x65, 0x20, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, +0x00, 0x39, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x46, +0x75, 0x6C, 0x6C, 0x00, 0x1A, 0x46, 0x69, 0x6C, +0x65, 0x20, 0x45, 0x6D, 0x70, 0x74, 0x79, 0x00, +0x39, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, +0x72, 0x79, 0x20, 0x46, 0x75, 0x6C, 0x6C, 0x00, +0x07, 0x52, 0x61, 0x6D, 0x20, 0x46, 0x75, 0x6C, +0x6C, 0x00, 0x36, 0x00, 0x37, 0x42, 0x61, 0x64, +0x20, 0x46, 0x69, 0x6C, 0x65, 0x20, 0x4E, 0x61, +0x6D, 0x65, 0x00, 0x20, 0x50, 0x72, 0x65, 0x73, +0x73, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, +0x79, 0x2E, 0x00, 0xCF, 0x5B, 0x41, 0xC9, 0xCF, +0x1D, 0x19, 0xC9, 0xCF, 0xB5, 0x87, 0xC9, 0xCF, +0x08, 0x85, 0xC9, 0xCF, 0xA0, 0x8F, 0xC9, 0xCF, +0x43, 0x86, 0xC9, 0xCF, 0x19, 0x85, 0xC9, 0xCF, +0xF7, 0x12, 0xC9, 0xCF, 0x03, 0x8B, 0xC9, 0xCF, +0xDE, 0x13, 0xC9, 0xCF, 0x97, 0x26, 0xC9, 0xCF, +0xCC, 0x2B, 0xC9, 0xCF, 0xB5, 0x2A, 0xC9, 0xCF, +0x0C, 0x2B, 0xC9, 0xCF, 0xCE, 0x2A, 0xC9, 0xCF, +0xA8, 0x82, 0xC9, 0xCF, 0x62, 0x2C, 0xC9, 0xCF, +0x1F, 0x06, 0xC9, 0xCF, 0xAC, 0x2D, 0xC9, 0xCF, +0xD2, 0x44, 0xC9, 0xCF, 0x79, 0x44, 0xC9, 0xCF, +0x8A, 0x53, 0xC9, 0xCF, 0x3E, 0x4F, 0xC9, 0xCF, +0x4D, 0x4F, 0xC9, 0xCF, 0x7C, 0x4F, 0xC9, 0xCF, +0x88, 0x4F, 0xC9, 0xCF, 0x8D, 0x4F, 0xC9, 0x21, +0x88, 0x04, 0xE5, 0xC3, 0xA2, 0x00, 0xCF, 0x0B, +0x47, 0xC9, 0xCF, 0x14, 0x5A, 0xC9, 0xCF, 0xF6, +0x54, 0xC9, 0xCF, 0x04, 0x14, 0xC9, 0xCF, 0x46, +0x29, 0xC9, 0xCF, 0x5E, 0x4F, 0xC9, 0xCF, 0x63, +0x4F, 0xC9, 0xCF, 0x13, 0x10, 0xC9, 0xCF, 0x40, +0x5B, 0xC9, 0xCF, 0x1B, 0x06, 0xC9, 0xCF, 0xA2, +0x32, 0xC9, 0xCF, 0x09, 0x33, 0xC9, 0xCF, 0x3D, +0x11, 0xC9, 0xCF, 0xB3, 0x30, 0xC9, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xCD, 0x08, 0x50, 0xC9, 0xCD, 0x0F, 0x50, 0xC9, +0xAF, 0x32, 0x49, 0xF8, 0xC3, 0x18, 0x50, 0x3E, +0x0C, 0x32, 0x49, 0xF8, 0xE7, 0xCD, 0x47, 0x53, +0x22, 0x46, 0xF8, 0x21, 0x4B, 0x53, 0x11, 0x30, +0xF8, 0x01, 0x15, 0x00, 0xCD, 0x18, 0x53, 0x3E, +0x50, 0x32, 0x48, 0xF8, 0xAF, 0x32, 0x4A, 0xF8, +0xCD, 0x3B, 0x53, 0x2A, 0x46, 0xF8, 0xCD, 0x33, +0x53, 0xEB, 0xD5, 0xCD, 0xAB, 0x52, 0x00, 0x2E, +0x7E, 0xC2, 0x46, 0x50, 0x2E, 0x80, 0x01, 0x00, +0x00, 0x1A, 0xBD, 0xDA, 0x4F, 0x50, 0x03, 0x13, +0xFE, 0x1A, 0xC2, 0x49, 0x50, 0xE1, 0x3A, 0x49, +0xF8, 0xD6, 0x0C, 0xC2, 0x60, 0x50, 0x47, 0x4F, +0xCD, 0x3F, 0x53, 0xD8, 0x2B, 0xE5, 0xCD, 0xA5, +0x52, 0xC2, 0x98, 0x50, 0xCD, 0xAB, 0x52, 0xDC, +0x07, 0x53, 0xC3, 0x1A, 0x52, 0xCD, 0x23, 0x53, +0xDA, 0x75, 0x50, 0xCD, 0x37, 0x53, 0xC9, 0x4F, +0xFE, 0x3A, 0xD0, 0xFE, 0x20, 0x37, 0xC8, 0xFE, +0x2F, 0xC8, 0x3F, 0xC9, 0xD6, 0x2F, 0xD0, 0x3E, +0x0B, 0xC9, 0xFE, 0x3A, 0xC0, 0x3E, 0x20, 0xC9, +0xD5, 0x00, 0x00, 0x01, 0x00, 0x00, 0xC5, 0xE1, +0x03, 0x13, 0x1A, 0xFE, 0x5B, 0xD2, 0xA0, 0x50, +0xFE, 0x1A, 0xCA, 0xB7, 0x50, 0xFE, 0x41, 0xDA, +0xA1, 0x50, 0x00, 0x23, 0xC3, 0xA1, 0x50, 0xC5, +0xD1, 0xDF, 0xD1, 0xDA, 0xC6, 0x50, 0xCD, 0x07, +0x53, 0x3E, 0x43, 0x32, 0x48, 0xF8, 0xAF, 0x32, +0x4A, 0xF8, 0xCD, 0x0A, 0x52, 0xCD, 0x8A, 0x51, +0xD2, 0x5E, 0x51, 0xCD, 0x7F, 0x50, 0x00, 0xD2, +0x17, 0x51, 0x13, 0x1A, 0xCD, 0x80, 0x50, 0x1B, +0x47, 0x79, 0xD2, 0x17, 0x51, 0xC2, 0xEE, 0x50, +0xB8, 0xCA, 0x36, 0x51, 0x00, 0x00, 0x13, 0x21, +0x4A, 0xF8, 0x00, 0x7E, 0xB7, 0xC2, 0xFF, 0x50, +0x3E, 0x7E, 0x77, 0xE1, 0x77, 0x23, 0xE5, 0x79, +0xCD, 0x8C, 0x50, 0x00, 0x4F, 0x78, 0xCD, 0x8C, +0x50, 0xC6, 0x0B, 0x0D, 0xC2, 0x09, 0x51, 0xC6, +0x7A, 0xE1, 0x77, 0xE5, 0xC3, 0xCA, 0x50, 0xE1, +0xFE, 0x0D, 0xC2, 0x2A, 0x51, 0x13, 0x1A, 0xFE, +0x0A, 0x1B, 0x3E, 0x0D, 0xC2, 0x2A, 0x51, 0x13, +0x3E, 0x80, 0x77, 0xE5, 0x3A, 0x4A, 0xF8, 0xB7, +0xC2, 0xC6, 0x50, 0x00, 0x00, 0x7E, 0x21, 0x2F, +0xF8, 0x06, 0x07, 0x05, 0xCA, 0xCA, 0x50, 0x23, +0xBE, 0xC2, 0x3B, 0x51, 0x0E, 0x15, 0xCD, 0x8A, +0x51, 0xD2, 0x5E, 0x51, 0x21, 0x30, 0xF8, 0xBE, +0xCA, 0x7B, 0x51, 0x0D, 0xCC, 0x0A, 0x52, 0xCA, +0x84, 0x51, 0x23, 0xC3, 0x4F, 0x51, 0x32, 0x45, +0xF8, 0xAF, 0x32, 0x4A, 0xF8, 0x78, 0xFE, 0x07, +0xD2, 0x6E, 0x51, 0xCD, 0x0A, 0x52, 0xE1, 0x36, +0xFF, 0xE5, 0x3A, 0x45, 0xF8, 0xCD, 0x95, 0x51, +0xC3, 0xCA, 0x50, 0x79, 0xC6, 0x15, 0x05, 0xC2, +0x7C, 0x51, 0xC6, 0x6B, 0xE1, 0x77, 0xE5, 0xC3, +0xCA, 0x50, 0x13, 0x1A, 0xFE, 0x1A, 0xCA, 0xBA, +0x52, 0xFE, 0x7E, 0xC9, 0x7E, 0x4F, 0x3A, 0x49, +0xF8, 0xB7, 0x79, 0xC1, 0xE1, 0x23, 0xC2, 0xA2, +0x51, 0x77, 0xE5, 0xC5, 0xC8, 0xE7, 0xD5, 0x6F, +0x3A, 0x06, 0xEF, 0x2F, 0xC6, 0x2C, 0x67, 0x7D, +0xCD, 0xD7, 0x51, 0x00, 0x00, 0x3F, 0xCA, 0xC4, +0x51, 0xD2, 0xC7, 0x51, 0x13, 0x1A, 0xCD, 0xD7, +0x51, 0xC3, 0xB6, 0x51, 0xCD, 0x2F, 0x53, 0xCD, +0x75, 0x50, 0x00, 0xD1, 0xC8, 0xFE, 0x20, 0xDA, +0xBA, 0x52, 0xCC, 0x27, 0x53, 0x00, 0xC9, 0x25, +0xC8, 0xFE, 0x21, 0x3F, 0xD0, 0xFE, 0xFE, 0x3D, +0xD0, 0xD6, 0x7F, 0xCA, 0x00, 0x52, 0xD8, 0x25, +0x00, 0xC8, 0xF5, 0x3A, 0x4A, 0xF8, 0xB7, 0x01, +0x0B, 0x05, 0xC2, 0xF8, 0x51, 0x01, 0x15, 0x00, +0xF1, 0x90, 0x90, 0x00, 0xD8, 0x3C, 0xFE, 0x6A, +0x3D, 0xD0, 0x80, 0x91, 0xD8, 0xC2, 0x03, 0x52, +0x3C, 0xC9, 0xC1, 0xE1, 0x23, 0xE5, 0xC5, 0xC9, +0xAF, 0x32, 0x4A, 0xF8, 0xCD, 0x8A, 0x51, 0xC3, +0x2F, 0x52, 0xCD, 0xAB, 0x52, 0xC2, 0x10, 0x52, +0xCD, 0x8A, 0x51, 0xDA, 0x2F, 0x52, 0xC2, 0x39, +0x52, 0x32, 0x4A, 0xF8, 0xC3, 0x1A, 0x52, 0xCD, +0x95, 0x51, 0xAF, 0x32, 0x4A, 0xF8, 0xC3, 0x1A, +0x52, 0xFE, 0x80, 0xC2, 0x48, 0x52, 0x3E, 0x0D, +0xCD, 0x95, 0x51, 0x3E, 0x0A, 0xC3, 0x2F, 0x52, +0xFE, 0xFE, 0xCA, 0x81, 0x52, 0xD2, 0x10, 0x52, +0x4F, 0x3A, 0x4A, 0xF8, 0xB7, 0x79, 0xCA, 0x81, +0x52, 0xD6, 0x86, 0xDA, 0x1A, 0x52, 0x01, 0x00, +0x00, 0x0C, 0xD6, 0x0B, 0xD2, 0x61, 0x52, 0xC6, +0x3B, 0xCD, 0x92, 0x50, 0x32, 0x45, 0xF8, 0x79, +0xC6, 0x2F, 0xCD, 0x92, 0x50, 0xCD, 0x95, 0x51, +0x3A, 0x45, 0xF8, 0xCD, 0x95, 0x51, 0xC3, 0x1A, +0x52, 0xD6, 0x81, 0x21, 0x36, 0xF8, 0x2B, 0xD6, +0x15, 0xD2, 0x86, 0x52, 0xC6, 0x16, 0x32, 0x45, +0xF8, 0xCD, 0x94, 0x51, 0x3A, 0x45, 0xF8, 0x21, +0x45, 0xF8, 0x2B, 0x3D, 0xC2, 0x9A, 0x52, 0xCD, +0x94, 0x51, 0xC3, 0x1A, 0x52, 0x3A, 0x49, 0xF8, +0xFE, 0x0C, 0xC8, 0x2A, 0x46, 0xF8, 0x01, 0x0A, +0x00, 0x09, 0x7E, 0xFE, 0x50, 0xC8, 0xFE, 0x43, +0x37, 0xC9, 0x32, 0x45, 0xF8, 0xC5, 0xCD, 0xA5, +0x52, 0xC1, 0xD1, 0xE1, 0xFE, 0x0C, 0xC2, 0xD6, +0x52, 0x3A, 0x45, 0xF8, 0xFE, 0x1A, 0xCC, 0x27, +0x53, 0xCD, 0x2B, 0x53, 0xBF, 0xC9, 0xD6, 0x43, +0xCA, 0xE6, 0x52, 0xD6, 0x0F, 0xCA, 0xE6, 0x52, +0x78, 0xFE, 0x07, 0xD2, 0xE7, 0x52, 0x23, 0xE5, +0x2B, 0x01, 0xFF, 0xFF, 0x3E, 0x1A, 0x03, 0x23, +0xBE, 0xC2, 0xEE, 0x52, 0xE1, 0xCD, 0x43, 0x53, +0xCD, 0xAB, 0x52, 0xCA, 0x04, 0x53, 0x3A, 0x48, +0xF8, 0x77, 0xBF, 0xC9, 0x36, 0x4F, 0xC9, 0x21, +0x31, 0xF8, 0x3E, 0x14, 0xF5, 0x7E, 0xE6, 0xDF, +0x77, 0xF1, 0x3D, 0xC8, 0x23, 0xC3, 0x0C, 0x53, +0x7E, 0x12, 0x23, 0x13, 0x0B, 0x78, 0xB1, 0xC2, +0x18, 0x53, 0xC9, 0xCF, 0x4D, 0x8B, 0xC9, 0xCF, +0xF7, 0x12, 0xC9, 0xCF, 0x4D, 0x4F, 0xC9, 0xCF, +0x3E, 0x4F, 0xC9, 0xCF, 0x8C, 0x6E, 0xC9, 0xCF, +0x03, 0x8B, 0xC9, 0xCF, 0x62, 0x2C, 0xC9, 0xCF, +0xA8, 0x82, 0xC9, 0xCF, 0xDA, 0x82, 0xC9, 0xCF, +0x63, 0x4F, 0xC9, 0x20, 0x65, 0x74, 0x61, 0x6F, +0x69, 0x6E, 0x72, 0x73, 0x68, 0x64, 0x6C, 0x66, +0x63, 0x6D, 0x75, 0x67, 0x79, 0x70, 0x77, 0x62 +}; + +/* TS-DOS NEC Image */ +const unsigned char gTsDosNecImage[] = { +0xC3, 0xAD, 0x00, 0xE1, 0xD1, 0xC1, 0xF1, 0xC9, +0xC3, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xCF, 0x10, 0x00, 0xC8, 0xFE, 0x20, 0xC9, 0x00, +0x7C, 0x92, 0xC0, 0x7D, 0x93, 0xC9, 0x3E, 0x20, +0xCF, 0x20, 0x00, 0xC9, 0xF3, 0xCD, 0x96, 0x00, +0xE1, 0xC3, 0x03, 0x00, 0xF3, 0xCD, 0x96, 0x00, +0xF1, 0xF1, 0xC9, 0x00, 0xF3, 0xCD, 0x96, 0x00, +0xC3, 0xA5, 0x00, 0x00, 0xF3, 0xCD, 0x96, 0x00, +0xF5, 0x3E, 0x01, 0xD3, 0xA1, 0xF1, 0xC9, 0x00, +0x11, 0x95, 0xF3, 0xCD, 0x91, 0xF9, 0xDB, 0xA0, +0xE6, 0x0C, 0x2A, 0x49, 0x00, 0xD3, 0xA1, 0xDF, +0xFE, 0x01, 0xD8, 0x21, 0xD2, 0x13, 0x22, 0xD2, +0xF9, 0x22, 0x82, 0xF3, 0xCD, 0xC6, 0x2C, 0x29, +0x40, 0x04, 0x00, 0x00, 0xC7, 0x00, 0xCD, 0x91, +0xF9, 0x01, 0x08, 0x00, 0x1A, 0x77, 0x13, 0x23, +0x0B, 0x78, 0xB1, 0xC2, 0x74, 0x00, 0xC9, 0x22, +0x89, 0xF8, 0xE1, 0xD5, 0x5E, 0x23, 0x56, 0x23, +0xE3, 0xEB, 0xE5, 0x21, 0x91, 0xF9, 0xE3, 0xE5, +0x2A, 0x89, 0xF8, 0xC3, 0xA5, 0x00, 0x22, 0x8B, +0xF8, 0x21, 0x91, 0xF9, 0xE3, 0x2B, 0x2B, 0x2B, +0x2B, 0xE5, 0x2A, 0x8B, 0xF8, 0xF5, 0xDB, 0xA0, +0xE6, 0x0C, 0xC3, 0x94, 0xF9, 0xF3, 0xFE, 0x08, +0xD2, 0x00, 0x01, 0x47, 0xD3, 0xA1, 0x3A, 0xDB, +0xF3, 0xB0, 0xD3, 0xA1, 0xC5, 0xF5, 0xD5, 0xE5, +0x11, 0x40, 0x00, 0x21, 0x91, 0xF9, 0xCD, 0x71, +0x00, 0x01, 0x29, 0x00, 0x21, 0x95, 0xF3, 0xCD, +0x74, 0x00, 0xE1, 0xD1, 0xF1, 0x32, 0x93, 0xF9, +0xF1, 0xFB, 0xC3, 0x00, 0x01, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xE1, 0x7C, 0xB5, 0xCA, 0x00, 0x70, 0xCD, 0x1E, +0x01, 0xC3, 0x35, 0x35, 0x77, 0x23, 0x05, 0xC2, +0x0C, 0x01, 0xC9, 0x7E, 0x12, 0x23, 0x13, 0x0B, +0x78, 0xB1, 0xC2, 0x13, 0x01, 0xC9, 0x21, 0xE8, +0x01, 0xE5, 0x23, 0x01, 0x08, 0x00, 0x11, 0x78, +0xFB, 0xCD, 0x13, 0x01, 0xEB, 0xED, 0x22, 0xC4, +0xFB, 0x13, 0x13, 0xEB, 0x22, 0xC8, 0xFB, 0xCD, +0xD8, 0x01, 0xCD, 0xD4, 0x01, 0xC1, 0xC0, 0x2A, +0x71, 0xF8, 0x22, 0xC2, 0xFB, 0x0A, 0x32, 0xC6, +0xFB, 0xCD, 0x8C, 0x01, 0xD8, 0xE5, 0x2A, 0xC4, +0xFB, 0x44, 0x4D, 0xC5, 0x2A, 0xC2, 0xFB, 0xCD, +0xE4, 0x01, 0xDA, 0x89, 0x01, 0x2A, 0xC2, 0xFB, +0xEB, 0x2A, 0xC8, 0xFB, 0xC1, 0xCD, 0x13, 0x01, +0xD1, 0xD5, 0x2A, 0xE1, 0xFA, 0x2B, 0x22, 0x71, +0xF8, 0x23, 0xEB, 0x2A, 0xC4, 0xFB, 0x19, 0x22, +0xE1, 0xFA, 0xD1, 0x2A, 0xC2, 0xFB, 0xEB, 0x3A, +0xC6, 0xFB, 0xCD, 0xDC, 0x01, 0xCD, 0xD8, 0x01, +0xC9, 0xE1, 0xE1, 0xC9, 0x21, 0x86, 0xF8, 0x01, +0x0B, 0x00, 0x09, 0x7E, 0xFE, 0xFF, 0xCA, 0x9E, +0x01, 0x87, 0xDA, 0x92, 0x01, 0xC9, 0x37, 0xC9, +0xCF, 0xE4, 0x42, 0xC9, 0xCF, 0xC3, 0x42, 0xC9, +0xCF, 0xDC, 0x5D, 0xC9, 0xCF, 0x4D, 0x17, 0xC9, +0xCF, 0x79, 0x72, 0xC9, 0xCF, 0x17, 0x18, 0xC9, +0xCF, 0xF4, 0x1E, 0xC9, 0xCF, 0x60, 0x42, 0xC9, +0xCF, 0xA2, 0x42, 0xC9, 0xCF, 0xA7, 0x42, 0xC9, +0xCF, 0x3D, 0x18, 0xC9, 0xCF, 0x6E, 0x42, 0xC9, +0xCF, 0x00, 0x00, 0xC9, 0xCF, 0x9B, 0x22, 0xC9, +0xCF, 0x3A, 0x23, 0xC9, 0xCF, 0x35, 0x24, 0xC9, +0xCF, 0x21, 0x59, 0xC9, 0xCF, 0x0A, 0x6C, 0xC9, +0x80, 0x54, 0x53, 0x2D, 0x44, 0x4F, 0x53, 0x20, +0x20, 0x16, 0x00, 0x15, 0x80, 0x0A, 0x00, 0x98, +0x1D, 0x00, 0xA7, 0x79, 0x90, 0x2C, 0x12, 0x3A, +0xBC, 0x1D, 0x00, 0xBA, 0x73, 0x90, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3E, 0x01, 0xE1, 0x21, 0x00, 0x00, +0xE5, 0xC3, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x21, 0xC1, 0xFB, +0x06, 0xB4, 0xAF, 0xCD, 0x8B, 0x4A, 0x21, 0x00, +0x00, 0x39, 0x22, 0xCF, 0xFB, 0x3E, 0x01, 0xCD, +0xDC, 0x4A, 0xAF, 0x32, 0xD5, 0xFB, 0x32, 0xDB, +0xFB, 0x32, 0xDA, 0xFB, 0x32, 0xCB, 0xFB, 0x3C, +0x32, 0xCE, 0xFB, 0x21, 0x64, 0x35, 0x22, 0xD1, +0xFB, 0xCD, 0x7F, 0x4C, 0xCD, 0xAE, 0x4C, 0xCD, +0x15, 0x36, 0x3A, 0xD6, 0xFB, 0x32, 0xCE, 0xFB, +0xCD, 0x33, 0x36, 0x21, 0x09, 0x49, 0xE5, 0xF5, +0xFE, 0x02, 0xD2, 0xB9, 0x35, 0x3A, 0xCD, 0xFB, +0xA7, 0xCA, 0xB9, 0x35, 0x3A, 0xD7, 0xFB, 0x4F, +0x0C, 0x06, 0x00, 0xC5, 0x3A, 0xCE, 0xFB, 0x32, +0xD6, 0xFB, 0xCD, 0x27, 0x3B, 0xC1, 0x04, 0x0D, +0xCA, 0x09, 0x49, 0x78, 0x32, 0xD6, 0xFB, 0x32, +0xCE, 0xFB, 0xC5, 0xCD, 0x15, 0x3B, 0x2A, 0xE5, +0xFB, 0x2B, 0x7E, 0xFE, 0x3E, 0xC2, 0x8C, 0x35, +0xC1, 0xF1, 0x21, 0x8C, 0x35, 0xF5, 0xC5, 0xE5, +0xF5, 0xCD, 0xAA, 0x4C, 0x3A, 0xDA, 0xFB, 0xB7, +0xCA, 0xE4, 0x35, 0xF1, 0xA7, 0xCA, 0x91, 0x3B, +0x3D, 0xCA, 0xD6, 0x3D, 0x3D, 0xCA, 0x02, 0x3E, +0x3D, 0x3D, 0xCA, 0xB6, 0x3D, 0x3D, 0x3D, 0xCA, +0x63, 0x3D, 0x3D, 0x3D, 0x3D, 0xE1, 0xCA, 0x02, +0x36, 0xC3, 0x64, 0x35, 0xF1, 0xA7, 0xCA, 0xAE, +0x3C, 0x3D, 0xCA, 0x8E, 0x3C, 0x3D, 0xCA, 0x5B, +0x3B, 0x3D, 0x3D, 0xCA, 0xB3, 0x3E, 0x3D, 0x3D, +0x3D, 0x3D, 0x3D, 0xE1, 0xCA, 0x02, 0x36, 0xC3, +0x64, 0x35, 0xCD, 0x1B, 0x4B, 0xCD, 0x2F, 0x4C, +0xCD, 0x7F, 0x4C, 0xCD, 0xAE, 0x4C, 0x21, 0x00, +0x00, 0xE5, 0xC3, 0xA5, 0x00, 0x21, 0x01, 0x01, +0x22, 0xE5, 0xF3, 0x21, 0xC0, 0x3E, 0xCD, 0x83, +0x4A, 0xAF, 0x32, 0xCD, 0xFB, 0x3E, 0x01, 0x32, +0xD6, 0xFB, 0x21, 0x02, 0x02, 0x22, 0xE5, 0xF3, +0xC3, 0x45, 0x38, 0x3A, 0xCE, 0xFB, 0x32, 0xD6, +0xFB, 0xCD, 0x15, 0x3B, 0x3A, 0xD6, 0xFB, 0x3D, +0x37, 0x3F, 0x07, 0x5F, 0x16, 0x00, 0x21, 0xA1, +0xF5, 0x19, 0xEB, 0x21, 0x07, 0x23, 0x22, 0xE5, +0xF3, 0xCD, 0x83, 0x4C, 0xED, 0xCD, 0x87, 0x4C, +0xCD, 0x96, 0x4C, 0xCD, 0x8B, 0x4C, 0xCD, 0x61, +0x3E, 0xCD, 0x47, 0x4C, 0xCA, 0x5E, 0x36, 0xDA, +0x16, 0x38, 0xFE, 0x0D, 0xCA, 0x26, 0x37, 0xFE, +0x17, 0xCA, 0xB4, 0x37, 0xFE, 0x14, 0xCA, 0xA2, +0x37, 0xFE, 0x5D, 0xCA, 0xA2, 0x37, 0xFE, 0x3F, +0xCA, 0x81, 0x37, 0xFE, 0x02, 0xCA, 0x81, 0x37, +0xFE, 0x1E, 0xCA, 0xF2, 0x36, 0xFE, 0x1F, 0xCA, +0x00, 0x37, 0xFE, 0x1D, 0xCA, 0xE1, 0x36, 0xFE, +0x1C, 0xCA, 0xCE, 0x36, 0xFE, 0x20, 0xCA, 0xCE, +0x36, 0xE6, 0xDF, 0xFE, 0x54, 0xCA, 0xF8, 0x37, +0xFE, 0x41, 0xCA, 0x19, 0x37, 0xFE, 0x47, 0xCA, +0x19, 0x37, 0xFE, 0x55, 0xCA, 0xB8, 0x37, 0xFE, +0x44, 0xCA, 0xF6, 0x39, 0xFE, 0x4C, 0xCA, 0x1F, +0x3A, 0xFE, 0x50, 0xCA, 0x1F, 0x3A, 0xFE, 0x52, +0xCA, 0x5D, 0x37, 0xC3, 0x5E, 0x36, 0x3E, 0x01, +0x21, 0xD6, 0xFB, 0x86, 0x23, 0xBE, 0xDA, 0x0E, +0x37, 0xCA, 0x0E, 0x37, 0x3E, 0x01, 0xC3, 0x0E, +0x37, 0x3A, 0xD6, 0xFB, 0x3D, 0xC2, 0x0E, 0x37, +0x3A, 0xD7, 0xFB, 0xA7, 0xCA, 0x5E, 0x36, 0xC3, +0x0E, 0x37, 0x3A, 0xD6, 0xFB, 0xD6, 0x04, 0xDA, +0x5E, 0x36, 0xCA, 0x5E, 0x36, 0xC3, 0x0E, 0x37, +0x3E, 0x04, 0x21, 0xD6, 0xFB, 0x86, 0x4F, 0x23, +0x7E, 0xB9, 0xDA, 0x5E, 0x36, 0x79, 0xF5, 0xCD, +0x27, 0x3B, 0xF1, 0x32, 0xCE, 0xFB, 0xC3, 0x33, +0x36, 0x3E, 0x3E, 0xCD, 0xD4, 0x37, 0x3E, 0x01, +0x32, 0xCD, 0xFB, 0xC3, 0x33, 0x36, 0x3A, 0xCC, +0xFB, 0xFE, 0x02, 0xC2, 0x5E, 0x36, 0x2A, 0xE5, +0xFB, 0x01, 0x07, 0x00, 0x09, 0x7E, 0xFE, 0x3C, +0xC2, 0x5E, 0x36, 0xCD, 0x92, 0x4A, 0x2A, 0xE5, +0xFB, 0xCD, 0xF8, 0x3D, 0xCD, 0xE1, 0x40, 0x21, +0x02, 0x00, 0xCD, 0xF2, 0x40, 0x2A, 0xE5, 0xFB, +0x11, 0xC1, 0xFB, 0x01, 0x09, 0x00, 0xCD, 0x5C, +0x4A, 0xAF, 0xC3, 0x94, 0x37, 0x3A, 0xDA, 0xFB, +0xA7, 0xC2, 0x33, 0x36, 0xCD, 0xC6, 0x4C, 0x2A, +0xE5, 0xFB, 0xCD, 0x59, 0x49, 0xCD, 0xA8, 0x4A, +0xFE, 0xC0, 0xCC, 0x00, 0x50, 0xCD, 0x67, 0x4C, +0xCD, 0xC2, 0x4C, 0xCD, 0x15, 0x36, 0xC3, 0x33, +0x36, 0x3A, 0xDA, 0xFB, 0xA7, 0xCA, 0x5E, 0x36, +0x3A, 0xD7, 0xFB, 0xFE, 0x15, 0xDA, 0x5E, 0x36, +0x3A, 0xD5, 0xFB, 0x3C, 0x32, 0xD5, 0xFB, 0x3E, +0x01, 0x32, 0xCE, 0xFB, 0xCD, 0x15, 0x36, 0xC3, +0x33, 0x36, 0x3A, 0xDA, 0xFB, 0xA7, 0xCA, 0x5E, +0x36, 0x3A, 0xD5, 0xFB, 0xA7, 0xCA, 0x5E, 0x36, +0x3D, 0xC3, 0x94, 0x37, 0xAF, 0xC3, 0x94, 0x37, +0x3E, 0x20, 0xCD, 0xD4, 0x37, 0xAF, 0x32, 0xCD, +0xFB, 0xC3, 0x33, 0x36, 0x3A, 0xCC, 0xFB, 0x3D, +0xC2, 0x5E, 0x36, 0x3A, 0xCB, 0xFB, 0xEE, 0x01, +0x32, 0xCB, 0xFB, 0xC9, 0x32, 0xCD, 0xFB, 0x3A, +0xD7, 0xFB, 0xA7, 0xC8, 0xAF, 0x3C, 0x32, 0xD6, +0xFB, 0xCD, 0x30, 0x3B, 0x2A, 0xE5, 0xFB, 0x2B, +0x3A, 0xCD, 0xFB, 0xE7, 0x3A, 0xD6, 0xFB, 0x21, +0xD7, 0xFB, 0xBE, 0xDA, 0xDD, 0x37, 0xA7, 0xC9, +0xCD, 0x30, 0x3B, 0xCD, 0x87, 0x4C, 0x2A, 0xE5, +0xFB, 0x2B, 0x3E, 0x3E, 0xBE, 0xC2, 0x0A, 0x38, +0x3E, 0x20, 0xE7, 0xCD, 0x8B, 0x4C, 0x21, 0xCD, +0xFB, 0x36, 0x01, 0xC3, 0xCE, 0x36, 0xFE, 0x0A, +0xD2, 0x5E, 0x36, 0xFE, 0x05, 0xCA, 0x3D, 0x38, +0xFE, 0x03, 0xC0, 0x3A, 0xDA, 0xFB, 0xEE, 0x01, +0x32, 0xDA, 0xFB, 0xAF, 0x32, 0xD5, 0xFB, 0x3E, +0x01, 0x32, 0xCE, 0xFB, 0xCD, 0x7F, 0x4C, 0xCD, +0x15, 0x36, 0xC3, 0x33, 0x36, 0x3A, 0xDA, 0xFB, +0xA7, 0xC8, 0xC3, 0xB4, 0x37, 0x21, 0xA1, 0xF5, +0x22, 0xDC, 0xFB, 0xAF, 0x77, 0x23, 0x77, 0x3A, +0xDA, 0xFB, 0xA7, 0xCA, 0x9A, 0x39, 0xAF, 0x32, +0xDB, 0xFB, 0xCD, 0x89, 0x47, 0xC2, 0x27, 0x39, +0x3A, 0xD5, 0xFB, 0xA7, 0xCA, 0x7B, 0x38, 0x32, +0xDB, 0xFB, 0xCD, 0x96, 0x47, 0x3A, 0xDB, 0xFB, +0x3D, 0xC2, 0x67, 0x38, 0xAF, 0x32, 0xDB, 0xFB, +0x32, 0xD7, 0xFB, 0xCD, 0x96, 0x47, 0x3A, 0xD7, +0xFB, 0xFE, 0x15, 0xDC, 0xE7, 0x39, 0x3A, 0xCC, +0xFB, 0xA7, 0xCA, 0xA9, 0x38, 0x3D, 0xCA, 0x97, +0x38, 0x21, 0xC1, 0xFB, 0xC3, 0xAF, 0x38, 0x21, +0x01, 0x24, 0x22, 0xE5, 0xF3, 0xCD, 0x87, 0x4C, +0x3E, 0x23, 0xE7, 0x3A, 0xCB, 0xFB, 0xC6, 0x30, +0xE7, 0xCD, 0x8B, 0x4C, 0xC3, 0xC2, 0x38, 0xE5, +0x21, 0x01, 0x21, 0x22, 0xE5, 0xF3, 0xCD, 0x87, +0x4C, 0xE1, 0x0E, 0x06, 0xCD, 0x39, 0x49, 0xCD, +0x8B, 0x4C, 0x21, 0xEE, 0x3E, 0x01, 0x4E, 0x39, +0x3A, 0xDA, 0xFB, 0xA7, 0xC2, 0xD5, 0x38, 0x21, +0x38, 0x3F, 0x01, 0x3A, 0x39, 0xC5, 0xE5, 0x3A, +0xCE, 0xFB, 0x21, 0xD7, 0xFB, 0xBE, 0xDA, 0xE7, +0x38, 0x7E, 0xA7, 0xC2, 0xE7, 0x38, 0x3C, 0x32, +0xD6, 0xFB, 0xE1, 0x11, 0xA5, 0xF6, 0xD5, 0x0E, +0xA0, 0xAF, 0x12, 0x13, 0x0D, 0xC2, 0xF2, 0x38, +0xD1, 0x06, 0x0A, 0xEB, 0x0E, 0x05, 0x1A, 0x77, +0x13, 0x23, 0x0D, 0xC2, 0xFE, 0x38, 0xC5, 0x01, +0x0B, 0x00, 0x09, 0xC1, 0x05, 0xC2, 0xFC, 0x38, +0x21, 0x07, 0x0C, 0x22, 0xE5, 0xF3, 0xEB, 0xCD, +0x83, 0x4A, 0xCD, 0x58, 0x39, 0xCD, 0xC2, 0x4C, +0x21, 0x07, 0x16, 0x22, 0xE5, 0xF3, 0xC9, 0xAF, +0xCD, 0xE7, 0x39, 0x21, 0xEE, 0x3E, 0x01, 0x34, +0x39, 0xC3, 0xD5, 0x38, 0x21, 0xA3, 0x3F, 0xC3, +0x83, 0x4A, 0x2A, 0xE5, 0xFA, 0xEB, 0x2A, 0x59, +0xF4, 0x7D, 0x93, 0x6F, 0x7C, 0x9A, 0x67, 0x01, +0xF2, 0xFF, 0x09, 0xC3, 0x96, 0x4C, 0xCD, 0x67, +0x4A, 0xCD, 0x96, 0x4C, 0x3E, 0x30, 0xE7, 0xC9, +0x3A, 0xDA, 0xFB, 0xA7, 0xC2, 0x79, 0x39, 0x21, +0xE9, 0xF6, 0x3A, 0x44, 0xFA, 0x11, 0x49, 0x40, +0xFE, 0x87, 0xCA, 0x70, 0x39, 0x11, 0x4D, 0x40, +0x1A, 0x77, 0x23, 0x13, 0xA7, 0xC2, 0x70, 0x39, +0xC9, 0x3A, 0xCC, 0xFB, 0xA7, 0xC8, 0x21, 0x05, +0xF7, 0x11, 0x44, 0x40, 0x3D, 0xCA, 0x70, 0x39, +0x21, 0xE5, 0xF6, 0xAF, 0x06, 0x10, 0xCD, 0x8B, +0x4A, 0x21, 0x05, 0xF7, 0x11, 0x3F, 0x40, 0xC3, +0x70, 0x39, 0x21, 0x91, 0xF8, 0xAF, 0x32, 0xD7, +0xFB, 0x3E, 0x15, 0x3D, 0xF5, 0x7E, 0xEE, 0x80, +0xE6, 0x9F, 0xC2, 0xD3, 0x39, 0xE5, 0x23, 0x5E, +0x23, 0x56, 0xE3, 0xE5, 0xCD, 0x36, 0x3D, 0xEB, +0xCD, 0xE5, 0x47, 0xE1, 0xE3, 0x23, 0x0E, 0x06, +0xCD, 0x39, 0x49, 0x3E, 0x2E, 0xE7, 0x0E, 0x02, +0xCD, 0x39, 0x49, 0x3E, 0x20, 0xE7, 0x21, 0xD7, +0xFB, 0x34, 0xE1, 0x11, 0x0B, 0x00, 0x19, 0xF1, +0x3D, 0xC2, 0xA4, 0x39, 0x3A, 0xD7, 0xFB, 0xFE, +0x15, 0xDC, 0xE7, 0x39, 0xC3, 0x86, 0x38, 0xF5, +0x21, 0x34, 0x40, 0xCD, 0x83, 0x4A, 0xF1, 0x3C, +0xFE, 0x15, 0xC2, 0xE7, 0x39, 0xC9, 0xCD, 0x0B, +0x3B, 0xCD, 0xFF, 0x39, 0xC3, 0x33, 0x36, 0xE5, +0xCD, 0x0B, 0x3B, 0xCD, 0xCA, 0x4C, 0x21, 0x00, +0xFD, 0x1E, 0x08, 0x16, 0x28, 0x7E, 0xCD, 0x9A, +0x4C, 0x23, 0x15, 0xC2, 0x0D, 0x3A, 0xCD, 0xCA, +0x4C, 0x1D, 0xC2, 0x0B, 0x3A, 0xE1, 0xC9, 0x32, +0xE0, 0xFB, 0x11, 0x07, 0x00, 0x2A, 0xE5, 0xFB, +0x19, 0x7E, 0xFE, 0x44, 0xC2, 0x33, 0x36, 0x23, +0x7E, 0xFE, 0x4F, 0xC2, 0x69, 0x3A, 0xCD, 0xAC, +0x3A, 0x3A, 0xE0, 0xFB, 0xFE, 0x4C, 0xCC, 0x7F, +0x4C, 0xCC, 0xAE, 0x4C, 0xCC, 0xC6, 0x4C, 0xC4, +0x0B, 0x3B, 0xCD, 0x87, 0x3A, 0xF5, 0xCD, 0xCE, +0x3A, 0xF1, 0xCA, 0x4A, 0x3A, 0x3A, 0xE0, 0xFB, +0xFE, 0x4C, 0xC2, 0x63, 0x3A, 0x3E, 0x07, 0xE7, +0xCD, 0x5B, 0x3E, 0xCD, 0x7F, 0x4C, 0xC3, 0x09, +0x49, 0x3A, 0xDA, 0xFB, 0xA7, 0xC2, 0x33, 0x36, +0x2A, 0xE5, 0xFB, 0xCD, 0x59, 0x49, 0xCD, 0xA8, +0x4A, 0xFE, 0xC0, 0xCC, 0x04, 0x50, 0xCD, 0x67, +0x4C, 0xCD, 0x15, 0x36, 0xC3, 0x33, 0x36, 0x3A, +0xDA, 0xFB, 0xA7, 0xC2, 0x0D, 0x41, 0x2A, 0xDE, +0xFB, 0x01, 0x80, 0x00, 0x79, 0x08, 0xD2, 0x9D, +0x3A, 0x09, 0x7D, 0x6C, 0x4F, 0x22, 0xDE, 0xFB, +0x2A, 0xE1, 0xFB, 0xE5, 0x09, 0x22, 0xE1, 0xFB, +0xE1, 0xFE, 0x80, 0xC9, 0xCD, 0x92, 0x4A, 0x2A, +0xE5, 0xFB, 0x3A, 0xDA, 0xFB, 0xA7, 0xC2, 0xC8, +0x3A, 0xCD, 0xA2, 0x4A, 0xD5, 0xCD, 0x36, 0x3D, +0x22, 0xDE, 0xFB, 0xE1, 0x22, 0xE1, 0xFB, 0xC9, +0xCD, 0xF8, 0x3D, 0xC3, 0xE1, 0x40, 0xEB, 0xB7, +0xC8, 0x4F, 0x3A, 0xE0, 0xFB, 0xFE, 0x4C, 0xC2, +0xE5, 0x3A, 0xCD, 0xF2, 0x3A, 0x1A, 0xE7, 0x13, +0x0D, 0xC2, 0xDA, 0x3A, 0xC9, 0xCD, 0xF2, 0x3A, +0x1A, 0xCD, 0x9A, 0x4C, 0x13, 0x0D, 0xC2, 0xE5, +0x3A, 0xC9, 0xCD, 0xA2, 0x4C, 0xC8, 0xCD, 0x43, +0x4C, 0xFE, 0x03, 0xCA, 0x63, 0x3A, 0xFE, 0x1B, +0xCA, 0x63, 0x3A, 0xFE, 0x20, 0xC2, 0xF2, 0x3A, +0xC3, 0x43, 0x4C, 0xDB, 0xBB, 0xE6, 0x06, 0xEE, +0x02, 0xC2, 0xCF, 0x48, 0xC9, 0xCD, 0x30, 0x3B, +0x22, 0xE5, 0xFB, 0xCD, 0x87, 0x4C, 0x2B, 0x0E, +0x0A, 0xCD, 0x39, 0x49, 0xC3, 0x8B, 0x4C, 0xCD, +0x8B, 0x4C, 0xCD, 0x30, 0x3B, 0xC3, 0x1E, 0x3B, +0x3A, 0xD6, 0xFB, 0x3D, 0x6F, 0x26, 0x00, 0x11, +0x0A, 0x00, 0xCD, 0x77, 0x4C, 0x11, 0x28, 0xFD, +0x19, 0x23, 0xE5, 0x01, 0x00, 0xFD, 0x08, 0x11, +0x28, 0x00, 0xEB, 0xCD, 0x73, 0x4C, 0x7D, 0x3C, +0x32, 0xE5, 0xF3, 0xEB, 0x10, 0x7D, 0x32, 0xE6, +0xF3, 0xE1, 0xC9, 0xCD, 0xA2, 0x4A, 0x22, 0xE1, +0xFB, 0x21, 0xB1, 0x3F, 0xCD, 0x7D, 0x3E, 0xC8, +0xCD, 0x59, 0x49, 0x2A, 0xE1, 0xFB, 0x01, 0x09, +0x00, 0x09, 0x11, 0x7E, 0xFB, 0x7E, 0x12, 0x13, +0x23, 0x7E, 0x12, 0xCD, 0xA8, 0x4A, 0xC2, 0xD2, +0x48, 0x2A, 0xE1, 0xFB, 0x23, 0x23, 0x23, 0x11, +0x78, 0xFB, 0x01, 0x06, 0x00, 0xEB, 0xC3, 0x5C, +0x4A, 0xCD, 0x92, 0x4A, 0x2A, 0xE5, 0xFB, 0xCD, +0xF8, 0x3D, 0x3A, 0xCD, 0xFB, 0xA7, 0xC2, 0xB9, +0x3B, 0x21, 0xE1, 0x3F, 0xCD, 0x7D, 0x3E, 0xCA, +0xB9, 0x3B, 0xCD, 0x59, 0x49, 0x01, 0x02, 0x00, +0x21, 0xF0, 0xFB, 0x11, 0x7E, 0xFB, 0xCD, 0x5C, +0x4A, 0xCD, 0xA8, 0x4A, 0xCA, 0xCC, 0x3B, 0x21, +0x17, 0x40, 0xCD, 0x48, 0x49, 0xCD, 0x51, 0x3E, +0xC0, 0xCD, 0x9B, 0x3C, 0x2A, 0x1E, 0xFC, 0x7C, +0x65, 0x6F, 0x22, 0x1E, 0xFC, 0x3A, 0xF0, 0xFB, +0xFE, 0x44, 0xC2, 0xE5, 0x3B, 0x2A, 0xE1, 0xFA, +0x3E, 0xC0, 0xC3, 0x06, 0x3C, 0xFE, 0x43, 0xC2, +0xF8, 0x3B, 0x2A, 0xE3, 0xFA, 0x22, 0xD6, 0xFB, +0x2A, 0xE5, 0xFA, 0x3E, 0xA0, 0xC3, 0x06, 0x3C, +0x2A, 0x1E, 0xFC, 0x22, 0xD6, 0xFB, 0x2A, 0x71, +0xF8, 0x22, 0xE1, 0xFB, 0x3E, 0x80, 0x32, 0xE0, +0xFB, 0x22, 0xE3, 0xFB, 0x2A, 0x1E, 0xFC, 0x22, +0xDE, 0xFB, 0xE5, 0xC1, 0x3A, 0xE0, 0xFB, 0xFE, +0xA0, 0xCA, 0x23, 0x3C, 0x03, 0xFE, 0x80, 0xC2, +0x23, 0x3C, 0x03, 0xC5, 0xCD, 0x9F, 0x3E, 0xDA, +0xDB, 0x48, 0xC1, 0xE5, 0xC5, 0x2A, 0xE3, 0xFB, +0xCD, 0x63, 0x4C, 0xDA, 0xDE, 0x48, 0x2A, 0xE3, +0xFB, 0xC1, 0x36, 0x00, 0x23, 0x0B, 0x79, 0xB0, +0xC2, 0x3A, 0x3C, 0x2B, 0xD1, 0x3A, 0xE0, 0xFB, +0xFE, 0xC0, 0xC2, 0x56, 0x3C, 0x36, 0x1A, 0x2A, +0xE3, 0xFB, 0x2B, 0xC3, 0x7E, 0x3C, 0xFE, 0xA0, +0xC2, 0x67, 0x3C, 0x2A, 0xD6, 0xFB, 0x22, 0xE3, +0xFA, 0x2A, 0xE3, 0xFB, 0xC3, 0x7E, 0x3C, 0xD5, +0x2A, 0xE1, 0xFA, 0x2B, 0x22, 0x71, 0xF8, 0x23, +0xEB, 0x2A, 0xD6, 0xFB, 0x23, 0x23, 0x19, 0x22, +0xE1, 0xFA, 0xD1, 0x2A, 0xE1, 0xFB, 0xEB, 0xCD, +0x6F, 0x4C, 0xCD, 0x7E, 0x41, 0xCD, 0x67, 0x4C, +0x21, 0x02, 0x00, 0xC3, 0xF2, 0x40, 0x3A, 0xCD, +0xFB, 0xA7, 0xCC, 0x44, 0x3E, 0x2A, 0xE5, 0xFB, +0xCD, 0x59, 0x49, 0xCD, 0xA8, 0x4A, 0xFE, 0xC0, +0xCA, 0x57, 0x4C, 0xFE, 0xA0, 0xCA, 0x5F, 0x4C, +0xFE, 0x80, 0xCA, 0x5B, 0x4C, 0xC9, 0xCD, 0x92, +0x4A, 0xCD, 0xA2, 0x4A, 0xD5, 0xE5, 0x23, 0x23, +0x23, 0x11, 0xE9, 0xFB, 0x01, 0x06, 0x00, 0xCD, +0x5C, 0x4A, 0x3E, 0x2E, 0x12, 0x13, 0x01, 0x02, +0x00, 0xCD, 0x5C, 0x4A, 0x3A, 0xCD, 0xFB, 0xA7, +0xC2, 0xEB, 0x3C, 0x21, 0xD8, 0x3F, 0xCD, 0x7D, +0x3E, 0xCA, 0xEB, 0x3C, 0xCD, 0x59, 0x49, 0x01, +0x06, 0x00, 0x11, 0xE9, 0xFB, 0x21, 0x78, 0xFB, +0xCD, 0x5C, 0x4A, 0xE1, 0xD1, 0xD5, 0xCD, 0x36, +0x3D, 0x7C, 0xB5, 0xCA, 0xD8, 0x48, 0xE5, 0x3E, +0x01, 0x32, 0xD7, 0xFB, 0xCD, 0x9A, 0x49, 0xCD, +0xC9, 0x4A, 0xCA, 0x31, 0x3D, 0x21, 0xF2, 0x3F, +0xCD, 0x48, 0x49, 0xCD, 0x5B, 0x3E, 0xE6, 0xDF, +0xE7, 0xFE, 0x52, 0xC2, 0x1F, 0x3D, 0xCD, 0x71, +0x43, 0xCD, 0xC9, 0x4A, 0xC3, 0x31, 0x3D, 0xE1, +0xD1, 0xFE, 0x41, 0xC0, 0x3A, 0xF0, 0xFB, 0xFE, +0x44, 0xC0, 0x3E, 0x02, 0x32, 0xD7, 0xFB, 0xD5, +0xE5, 0xE1, 0xD1, 0xC3, 0x1F, 0x41, 0x7E, 0xFE, +0xC0, 0xCA, 0x49, 0x3D, 0xFE, 0xA0, 0xCA, 0x58, +0x3D, 0xD5, 0xCD, 0x6B, 0x4C, 0xC1, 0x08, 0x2B, +0xC9, 0xEB, 0x11, 0x00, 0x00, 0x7E, 0x23, 0x13, +0xFE, 0x1A, 0xC2, 0x4D, 0x3D, 0x1B, 0xEB, 0xC9, +0xEB, 0x23, 0x23, 0x4E, 0x23, 0x46, 0x21, 0x06, +0x00, 0x09, 0xC9, 0x3A, 0xCC, 0xFB, 0xA7, 0xC8, +0x3D, 0xCA, 0xC4, 0x37, 0xCD, 0x92, 0x4A, 0x21, +0xC8, 0x3F, 0xCD, 0x7D, 0x3E, 0xC8, 0xCD, 0x59, +0x49, 0x21, 0x78, 0xFB, 0x11, 0xE9, 0xFB, 0x01, +0x06, 0x00, 0xCD, 0x5C, 0x4A, 0x21, 0x3C, 0x3E, +0x22, 0xF0, 0xFB, 0x3E, 0x2E, 0x32, 0xEF, 0xFB, +0xCD, 0x9A, 0x49, 0x3A, 0xCC, 0xFB, 0xFE, 0x02, +0xC0, 0xCD, 0xC9, 0x4A, 0xC2, 0xB0, 0x3D, 0x3E, +0x01, 0x32, 0xE9, 0xFB, 0x21, 0x01, 0x01, 0xCD, +0xF2, 0x40, 0x21, 0x02, 0x00, 0xC3, 0xF2, 0x40, +0xCD, 0xE1, 0x40, 0xC3, 0xAA, 0x3D, 0x3A, 0xCC, +0xFB, 0xFE, 0x02, 0xC8, 0x21, 0x82, 0x3F, 0xCD, +0x48, 0x49, 0xCD, 0x51, 0x3E, 0xC0, 0xCD, 0x9A, +0x49, 0xCD, 0x3A, 0x4A, 0x21, 0x06, 0x00, 0xCD, +0xF2, 0x40, 0x3E, 0x07, 0xE7, 0xC9, 0x3A, 0xCD, +0xFB, 0xA7, 0xCC, 0x44, 0x3E, 0xCD, 0x92, 0x4A, +0xCD, 0xE6, 0x3D, 0xC3, 0x71, 0x43, 0x01, 0x09, +0x00, 0x2A, 0xE5, 0xFB, 0x11, 0xE9, 0xFB, 0xCD, +0x5C, 0x4A, 0xCD, 0x9A, 0x49, 0xC3, 0xC9, 0x4A, +0xCD, 0x59, 0x49, 0x21, 0x78, 0xFB, 0xCD, 0xAE, +0x4A, 0xC9, 0xCD, 0x92, 0x4A, 0xCD, 0xE6, 0x3D, +0x21, 0xE9, 0xFB, 0x11, 0x81, 0xFB, 0x01, 0x09, +0x00, 0xCD, 0x5C, 0x4A, 0x2A, 0x1E, 0xFC, 0x4C, +0x45, 0x21, 0xC0, 0x7B, 0x08, 0x21, 0xB1, 0x3F, +0xC2, 0x3A, 0x3E, 0x01, 0x09, 0x00, 0xCD, 0x7F, +0x3E, 0xC8, 0xE5, 0xF5, 0xCD, 0x92, 0x4A, 0xF1, +0xE1, 0x11, 0xE9, 0xFB, 0x4F, 0x06, 0x00, 0xC3, +0x07, 0x42, 0xCD, 0x7D, 0x3E, 0xC8, 0xCD, 0x59, +0x49, 0xC3, 0xFE, 0x41, 0x21, 0xEA, 0x3F, 0xCD, +0x48, 0x49, 0xCD, 0x51, 0x3E, 0xC2, 0x09, 0x49, +0xC9, 0xCD, 0x5B, 0x3E, 0xE7, 0xFE, 0x59, 0xC8, +0xFE, 0x79, 0xC9, 0xCD, 0x61, 0x3E, 0xC3, 0x43, +0x4C, 0xAF, 0x3D, 0x32, 0x03, 0xF4, 0xCD, 0xA2, +0x4C, 0xCA, 0x61, 0x3E, 0xAF, 0x32, 0x03, 0xF4, +0x21, 0x41, 0xF8, 0xB6, 0xCA, 0x4F, 0x4C, 0xCD, +0x4B, 0x4C, 0xC3, 0x61, 0x3E, 0x0E, 0x06, 0xC5, +0xCD, 0x48, 0x49, 0xCD, 0x9E, 0x4C, 0xDA, 0x09, +0x49, 0x23, 0xC1, 0x06, 0x00, 0xE5, 0x7E, 0xA7, +0xCA, 0x99, 0x3E, 0x23, 0x04, 0x0D, 0xC2, 0x8E, +0x3E, 0x36, 0x00, 0x78, 0xE1, 0xA7, 0xC9, 0x21, +0x86, 0xF8, 0x01, 0x0B, 0x00, 0x09, 0x7E, 0xFE, +0xFF, 0xCA, 0xB1, 0x3E, 0x87, 0xDA, 0xA5, 0x3E, +0xC9, 0x37, 0xC9, 0x2A, 0x44, 0xFA, 0x01, 0x87, +0x0B, 0x08, 0xCA, 0x76, 0x40, 0xC3, 0x51, 0x40, +0x1B, 0x70, 0x20, 0x54, 0x53, 0x2D, 0x44, 0x4F, +0x53, 0x20, 0x28, 0x4E, 0x45, 0x43, 0x20, 0x76, +0x34, 0x2E, 0x30, 0x30, 0x29, 0x20, 0x28, 0x63, +0x29, 0x38, 0x37, 0x2C, 0x54, 0x53, 0x49, 0x2E, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x1B, 0x71, 0x20, 0x00, 0x4C, 0x6F, +0x61, 0x64, 0x20, 0x4B, 0x69, 0x6C, 0x6C, 0x20, +0x4E, 0x61, 0x6D, 0x65, 0x20, 0x52, 0x61, 0x6D, +0x20, 0x20, 0x46, 0x72, 0x6D, 0x74, 0x20, 0x4C, +0x6F, 0x67, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x4D, 0x65, 0x6E, 0x75, 0x20, +0x44, 0x49, 0x53, 0x4B, 0x20, 0x46, 0x72, 0x65, +0x65, 0x3A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x46, 0x69, 0x6C, 0x65, 0x3A, 0x00, +0x53, 0x61, 0x76, 0x65, 0x20, 0x4B, 0x69, 0x6C, +0x6C, 0x20, 0x4E, 0x61, 0x6D, 0x65, 0x20, 0x44, +0x69, 0x73, 0x6B, 0x20, 0x44, 0x4F, 0x53, 0x2D, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x20, 0x20, 0x4D, 0x65, 0x6E, +0x75, 0x20, 0x20, 0x52, 0x41, 0x4D, 0x20, 0x46, +0x72, 0x65, 0x65, 0x3A, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x20, 0x46, 0x69, 0x6C, 0x65, +0x3A, 0x00, 0x49, 0x6E, 0x73, 0x65, 0x72, 0x74, +0x20, 0x44, 0x69, 0x73, 0x6B, 0x2C, 0x20, 0x50, +0x72, 0x65, 0x73, 0x73, 0x20, 0x22, 0x59, 0x22, +0x20, 0x74, 0x6F, 0x20, 0x62, 0x65, 0x67, 0x69, +0x6E, 0x20, 0x00, 0x4E, 0x4F, 0x54, 0x20, 0x46, +0x4F, 0x52, 0x4D, 0x41, 0x54, 0x54, 0x45, 0x44, +0x00, 0x4E, 0x65, 0x77, 0x20, 0x4E, 0x61, 0x6D, +0x65, 0x3A, 0x00, 0x53, 0x79, 0x73, 0x74, 0x65, +0x6D, 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3A, 0x00, +0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, +0x79, 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3A, 0x00, +0x53, 0x61, 0x76, 0x65, 0x20, 0x61, 0x73, 0x3A, +0x00, 0x4C, 0x6F, 0x61, 0x64, 0x20, 0x61, 0x73, +0x3A, 0x00, 0x53, 0x75, 0x72, 0x65, 0x20, 0x3F, +0x20, 0x00, 0x46, 0x69, 0x6C, 0x65, 0x20, 0x65, +0x78, 0x69, 0x73, 0x74, 0x73, 0x2C, 0x20, 0x41, +0x29, 0x70, 0x70, 0x65, 0x6E, 0x64, 0x20, 0x52, +0x29, 0x65, 0x70, 0x6C, 0x61, 0x63, 0x65, 0x20, +0x51, 0x29, 0x75, 0x69, 0x74, 0x3A, 0x00, 0x46, +0x69, 0x6C, 0x65, 0x20, 0x65, 0x78, 0x69, 0x73, +0x74, 0x73, 0x2C, 0x20, 0x52, 0x65, 0x70, 0x6C, +0x61, 0x63, 0x65, 0x3F, 0x20, 0x28, 0x59, 0x2F, +0x4E, 0x29, 0x3A, 0x00, 0x2D, 0x2E, 0x2D, 0x20, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x4D, +0x6B, 0x44, 0x72, 0x00, 0x42, 0x61, 0x6E, 0x6B, +0x00, 0x4F, 0x46, 0x46, 0x00, 0x4F, 0x4E, 0x20, +0x00, 0x21, 0xDB, 0x7F, 0x22, 0xDA, 0xF9, 0x22, +0xFC, 0xF9, 0x22, 0xFE, 0xF9, 0x22, 0xE4, 0xF9, +0x22, 0xE8, 0xF9, 0x21, 0x87, 0x0B, 0x22, 0x44, +0xFA, 0x22, 0x4A, 0xFA, 0x22, 0x4C, 0xFA, 0x22, +0x4E, 0xFA, 0x22, 0x50, 0xFA, 0xC9, 0xCD, 0x51, +0x40, 0x21, 0xDB, 0x40, 0x11, 0x42, 0xF8, 0x01, +0x06, 0x00, 0xCD, 0x5C, 0x4A, 0x21, 0x42, 0xF8, +0x22, 0xE8, 0xF9, 0x22, 0xE4, 0xF9, 0x22, 0x50, +0xFA, 0x22, 0x4E, 0xFA, 0x22, 0xFC, 0xF9, 0x22, +0xFE, 0xF9, 0x22, 0x44, 0xFA, 0x22, 0x4A, 0xFA, +0x22, 0x4C, 0xFA, 0xC9, 0xF5, 0x3A, 0xBC, 0xF9, +0xFE, 0x1C, 0xCA, 0xA5, 0x44, 0xFE, 0x18, 0xCA, +0x3B, 0x45, 0xFE, 0x84, 0xCA, 0x18, 0x44, 0xFE, +0x82, 0xCA, 0x61, 0x44, 0xFE, 0x30, 0xCA, 0x7B, +0x43, 0xFE, 0x32, 0xCA, 0x71, 0x45, 0xFE, 0x78, +0xCA, 0x9D, 0x43, 0xFE, 0x7E, 0xCA, 0xCE, 0x43, +0xFE, 0x80, 0xCA, 0xED, 0x43, 0xF1, 0x1E, 0x02, +0xC3, 0x8F, 0x4C, 0xCD, 0x91, 0xF9, 0xC3, 0xA4, +0x40, 0x21, 0x01, 0x01, 0x3E, 0x03, 0x32, 0xE9, +0xFB, 0xC3, 0xF2, 0x40, 0x67, 0x2E, 0x04, 0xC3, +0xFE, 0x40, 0xCD, 0x76, 0x48, 0xCD, 0x47, 0x4A, +0xCD, 0x20, 0x48, 0xC3, 0x4C, 0x48, 0x22, 0x03, +0xFC, 0x21, 0x03, 0xFC, 0xCD, 0x7C, 0x48, 0xCD, +0x20, 0x48, 0xC3, 0x4C, 0x48, 0x21, 0x03, 0x00, +0xCD, 0x76, 0x48, 0xCD, 0x20, 0x48, 0x3A, 0x04, +0xFC, 0x21, 0x05, 0xFC, 0xFE, 0x80, 0xC9, 0xD5, +0xE5, 0xCD, 0x58, 0x41, 0xE1, 0x22, 0xD6, 0xFB, +0xE1, 0x11, 0x05, 0xFC, 0x01, 0x80, 0x00, 0xCD, +0x5C, 0x4A, 0xE5, 0x2A, 0xD6, 0xFB, 0x01, 0x80, +0x00, 0x08, 0xDA, 0x4B, 0x41, 0xCA, 0x4B, 0x41, +0x22, 0xD6, 0xFB, 0x3E, 0x80, 0xCD, 0xEC, 0x40, +0xC3, 0x28, 0x41, 0xE1, 0x3A, 0xD6, 0xFB, 0xCD, +0xEC, 0x40, 0x21, 0x02, 0x00, 0xC3, 0xF2, 0x40, +0x11, 0x00, 0x05, 0xEB, 0xCD, 0x73, 0x4C, 0x3A, +0x20, 0xFC, 0x95, 0xDA, 0xD5, 0x48, 0xCA, 0xD5, +0x48, 0x3A, 0xD7, 0xFB, 0x32, 0xE9, 0xFB, 0x21, +0x01, 0x01, 0xC3, 0xF2, 0x40, 0x2A, 0xE3, 0xFB, +0xCD, 0x63, 0x4C, 0xDA, 0xDE, 0x48, 0x2A, 0xE3, +0xFB, 0xE5, 0xCD, 0xE1, 0x40, 0xCD, 0x0D, 0x41, +0x4F, 0x06, 0x00, 0xD1, 0xCD, 0x5C, 0x4A, 0xD5, +0x3A, 0x04, 0xFC, 0x2A, 0xDE, 0xFB, 0x4F, 0x06, +0x00, 0x08, 0x22, 0xDE, 0xFB, 0xDA, 0xA5, 0x41, +0x7D, 0xB4, 0xC2, 0x85, 0x41, 0xD1, 0xC9, 0x3A, +0xDE, 0xFB, 0xFE, 0x01, 0xC8, 0xCD, 0xEF, 0x49, +0x3E, 0x57, 0x32, 0xD4, 0xFB, 0xCD, 0x25, 0x43, +0xCD, 0xEF, 0x49, 0xCD, 0xCD, 0x41, 0x2A, 0xE5, +0xFB, 0xCD, 0x2D, 0x49, 0x22, 0xE5, 0xFB, 0xCD, +0x45, 0x43, 0xC3, 0xA7, 0x41, 0x3A, 0x0A, 0xFC, +0xCD, 0xE8, 0x41, 0xFE, 0x35, 0xCA, 0xE0, 0x41, +0x21, 0xDF, 0xFB, 0x34, 0x7E, 0xFE, 0x14, 0xC0, +0x21, 0xDE, 0xFB, 0x34, 0x23, 0x36, 0x01, 0xC9, +0x01, 0x00, 0x05, 0xFE, 0x35, 0xC8, 0x01, 0x40, +0x00, 0xC9, 0x21, 0x08, 0x00, 0xCD, 0x76, 0x48, +0xCD, 0x2A, 0x4A, 0xC3, 0xEF, 0x49, 0x21, 0x78, +0xFB, 0x11, 0xE9, 0xFB, 0x01, 0x06, 0x00, 0xCD, +0x5C, 0x4A, 0x3A, 0xCC, 0xFB, 0xA7, 0xC2, 0xAF, +0x42, 0xCD, 0xC9, 0x4A, 0xC2, 0xD2, 0x48, 0x11, +0x00, 0x05, 0xCD, 0x5F, 0x43, 0x21, 0x00, 0x01, +0x22, 0xDE, 0xFB, 0xCD, 0xF2, 0x41, 0xCD, 0xD5, +0x42, 0x2A, 0xE9, 0xFA, 0xE5, 0x06, 0x28, 0x11, +0x81, 0xFB, 0xCD, 0xC0, 0x42, 0xDA, 0xCF, 0x48, +0x78, 0xA7, 0xCA, 0xCF, 0x48, 0xE5, 0x11, 0xE9, +0xFB, 0xEB, 0x01, 0x09, 0x00, 0xCD, 0x5C, 0x4A, +0xE1, 0xE5, 0x11, 0x21, 0xFC, 0x01, 0x1F, 0x00, +0xCD, 0x5C, 0x4A, 0xD1, 0xD5, 0x21, 0x1F, 0x00, +0x19, 0xE5, 0x2A, 0xE9, 0xFA, 0x01, 0x00, 0x05, +0x09, 0xC1, 0xC5, 0x08, 0xE3, 0xC1, 0xCD, 0x5C, +0x4A, 0x2A, 0xE9, 0xFA, 0x06, 0x27, 0x11, 0x21, +0xFC, 0xCD, 0xC0, 0x42, 0xE5, 0x2A, 0xE9, 0xFA, +0x01, 0xFF, 0x04, 0x09, 0xE5, 0x01, 0x1F, 0x00, +0x08, 0xD1, 0xC1, 0xC5, 0xE5, 0x08, 0xE5, 0xC1, +0x03, 0xE1, 0xCD, 0xA6, 0x4C, 0x21, 0x21, 0xFC, +0xD1, 0x01, 0x1F, 0x00, 0xCD, 0x5C, 0x4A, 0x21, +0x01, 0x14, 0x22, 0xDF, 0xFB, 0xE1, 0xE1, 0x22, +0xE5, 0xFB, 0x21, 0x00, 0x01, 0x22, 0xDE, 0xFB, +0xCD, 0xA7, 0x41, 0xCD, 0x24, 0x4A, 0xC9, 0x21, +0x0D, 0x19, 0xCD, 0x76, 0x48, 0xCD, 0x20, 0x48, +0x3A, 0x05, 0xFC, 0xA7, 0xC2, 0xD2, 0x48, 0xC9, +0x0E, 0x09, 0xCD, 0x73, 0x4A, 0xC8, 0xD8, 0x7E, +0xB7, 0xC8, 0xC5, 0x01, 0x1F, 0x00, 0x09, 0xC1, +0x05, 0xC8, 0xC3, 0xC0, 0x42, 0x2A, 0xE3, 0xFB, +0xCD, 0xEF, 0x42, 0x3A, 0xDE, 0xFB, 0x3D, 0xC8, +0xC3, 0xD8, 0x42, 0xCD, 0xD3, 0x6D, 0x77, 0x23, +0x0B, 0x79, 0xB0, 0xC2, 0x8A, 0xFC, 0xC9, 0xE5, +0x3E, 0x52, 0x32, 0xD4, 0xFB, 0xCD, 0x25, 0x43, +0xCD, 0xCD, 0x41, 0xCD, 0xB6, 0x48, 0xC5, 0x21, +0xE3, 0x42, 0x01, 0x0C, 0x00, 0x11, 0x8A, 0xFC, +0xCD, 0x5C, 0x4A, 0x3E, 0x0D, 0xCD, 0xB3, 0x48, +0xCD, 0x33, 0x4C, 0xC1, 0xE1, 0xCF, 0x8A, 0xFC, +0xC9, 0x06, 0x2F, 0xD6, 0x0A, 0x04, 0xD2, 0x1B, +0x43, 0xC6, 0x3A, 0x4F, 0xC9, 0x3A, 0xDE, 0xFB, +0xCD, 0x19, 0x43, 0x3A, 0xD4, 0xFB, 0xCD, 0xB3, +0x48, 0xCD, 0x32, 0x4A, 0x3A, 0xDF, 0xFB, 0xCD, +0x19, 0x43, 0x3E, 0x2C, 0xCD, 0xB3, 0x48, 0xCD, +0x32, 0x4A, 0xCD, 0x2A, 0x4A, 0x21, 0x05, 0xFC, +0xE5, 0x0E, 0x08, 0xCD, 0x39, 0x48, 0x0D, 0xC2, +0x4B, 0x43, 0xE1, 0x7E, 0xFE, 0x30, 0xC8, 0xFE, +0x42, 0xCA, 0xC1, 0x48, 0xC3, 0xBB, 0x48, 0x2A, +0xE9, 0xFA, 0xE5, 0x22, 0xE3, 0xFB, 0x21, 0xC0, +0xFF, 0x39, 0xC1, 0x08, 0xDF, 0xDA, 0xDE, 0x48, +0xC9, 0xAF, 0x32, 0x02, 0xFC, 0x21, 0x05, 0x00, +0xC3, 0xF2, 0x40, 0xF1, 0xFE, 0x30, 0xDA, 0xA5, +0x00, 0xFE, 0x32, 0xD2, 0xA5, 0x00, 0xD6, 0x30, +0x32, 0xCB, 0xFB, 0x23, 0x1D, 0x7E, 0xFE, 0x3A, +0xC2, 0xA5, 0x00, 0x23, 0x1D, 0xE3, 0xE1, 0x3E, +0x09, 0xB7, 0xC3, 0xA5, 0x00, 0xF1, 0xD5, 0xE5, +0xF5, 0xAF, 0xCD, 0xDC, 0x4A, 0x38, 0x02, 0xED, +0x7E, 0xA7, 0xCA, 0xC1, 0x43, 0xFE, 0x3A, 0xCA, +0xC1, 0x43, 0xCD, 0x27, 0x4C, 0x7B, 0xFE, 0x02, +0xD2, 0xC7, 0x43, 0x32, 0xCB, 0xFB, 0x38, 0x02, +0xD9, 0xCD, 0x58, 0x47, 0xCD, 0x1B, 0x4B, 0xF1, +0xE1, 0xD1, 0xC1, 0xC3, 0xA5, 0x00, 0xF1, 0xFE, +0x09, 0xC2, 0x6A, 0x45, 0xD5, 0xE5, 0xF5, 0xAF, +0xCD, 0xDC, 0x4A, 0x21, 0x78, 0xFB, 0xCD, 0xAE, +0x4A, 0xCA, 0xCF, 0x48, 0xCD, 0x71, 0x43, 0xCD, +0x1B, 0x4B, 0xC3, 0xC7, 0x43, 0xF1, 0xFE, 0x09, +0xC2, 0x6A, 0x45, 0xD5, 0xE5, 0xF5, 0xAF, 0xCD, +0xDC, 0x4A, 0x21, 0x81, 0xFB, 0xCD, 0xAE, 0x4A, +0xCA, 0xCF, 0x48, 0x21, 0xE9, 0xFB, 0x11, 0x81, +0xFB, 0x01, 0x09, 0x00, 0xCD, 0x5C, 0x4A, 0xCD, +0xFE, 0x41, 0xCD, 0x1B, 0x4B, 0xC3, 0xC7, 0x43, +0xF1, 0xFE, 0x09, 0xC2, 0xA5, 0x00, 0xC1, 0xE5, +0x01, 0x43, 0x4F, 0xCD, 0x0E, 0x45, 0xCA, 0xCF, +0x48, 0xCD, 0xE1, 0x40, 0x2A, 0x1E, 0xFC, 0x7D, +0x6C, 0x67, 0x22, 0xDE, 0xFB, 0xCD, 0x0D, 0x41, +0xCD, 0xBA, 0x4C, 0xE5, 0x2A, 0xC0, 0xF9, 0xE5, +0xE5, 0x2A, 0x84, 0xF3, 0xE3, 0xC1, 0x08, 0xDA, +0xDE, 0x48, 0xD1, 0xE1, 0x3A, 0x04, 0xFC, 0xD6, +0x06, 0x4F, 0x06, 0x00, 0xCD, 0x8C, 0x41, 0xCD, +0x1B, 0x4B, 0x21, 0xDD, 0x28, 0xE5, 0xC3, 0xA5, +0x00, 0xF1, 0xFE, 0x09, 0xC2, 0xA5, 0x00, 0xCD, +0xBE, 0x4C, 0x01, 0x43, 0x4F, 0xCD, 0x0E, 0x45, +0xC2, 0xD2, 0x48, 0x3E, 0x01, 0x32, 0xD7, 0xFB, +0x2A, 0xC2, 0xF9, 0x01, 0x06, 0x00, 0xC5, 0x09, +0xE5, 0xCD, 0x58, 0x41, 0xE1, 0x22, 0xD6, 0xFB, +0xC1, 0x21, 0xC0, 0xF9, 0x11, 0x05, 0xFC, 0xCD, +0x5C, 0x4A, 0x2A, 0x05, 0xFC, 0x01, 0x7A, 0x00, +0xCD, 0x2F, 0x41, 0xCD, 0x1B, 0x4B, 0x21, 0x2C, +0x06, 0xE5, 0xC3, 0xA5, 0x00, 0xF1, 0xFE, 0x09, +0xC2, 0xA5, 0x00, 0xC1, 0xF1, 0xF5, 0xC5, 0xCA, +0xA5, 0x00, 0x9F, 0x32, 0x72, 0xFB, 0x01, 0x42, +0x41, 0xCD, 0x0E, 0x45, 0xCA, 0xCF, 0x48, 0x2A, +0x1E, 0xFC, 0x4C, 0x45, 0x60, 0x69, 0x22, 0xDE, +0xFB, 0xCD, 0xFF, 0x44, 0x23, 0x22, 0xE3, 0xFB, +0x2A, 0xDE, 0xFB, 0xE5, 0xE5, 0xC1, 0xCD, 0x75, +0x41, 0xD1, 0x2A, 0xE1, 0xFA, 0x19, 0x22, 0xE1, +0xFA, 0x2A, 0xCA, 0xF9, 0x19, 0x22, 0xCA, 0xF9, +0xCD, 0x1B, 0x4B, 0xAF, 0x21, 0xB8, 0x27, 0xE5, +0xC3, 0xA5, 0x00, 0xAF, 0xD3, 0xA1, 0xCD, 0xEE, +0x22, 0xCD, 0x91, 0xF9, 0xC3, 0xCC, 0x44, 0x21, +0xF3, 0x44, 0x11, 0x8A, 0xFC, 0x01, 0x0C, 0x00, +0xCD, 0x5C, 0x4A, 0xC3, 0x8A, 0xFC, 0xF5, 0xE5, +0xD5, 0xC5, 0x2A, 0x7E, 0xFB, 0x11, 0x20, 0x20, +0xDF, 0xCA, 0x2A, 0x45, 0xD1, 0xD5, 0xDF, 0xCA, +0x2A, 0x45, 0xC1, 0xD1, 0xE1, 0xF1, 0xC1, 0xC3, +0xA5, 0x00, 0xE1, 0x22, 0x7E, 0xFB, 0xD1, 0xE1, +0xF1, 0xAF, 0xCD, 0xDC, 0x4A, 0x21, 0x78, 0xFB, +0xC3, 0xAE, 0x4A, 0xF1, 0xFE, 0x09, 0xC2, 0xA5, +0x00, 0x01, 0x42, 0x41, 0xCD, 0x0E, 0x45, 0xC2, +0xD2, 0x48, 0xCD, 0xB6, 0x4C, 0x2A, 0x5D, 0xF4, +0xEB, 0xDF, 0xCA, 0x63, 0x45, 0xD5, 0xC1, 0x08, +0x3E, 0x01, 0x32, 0xD7, 0xFB, 0xCD, 0x1F, 0x41, +0xCD, 0x1B, 0x4B, 0x21, 0x2D, 0x06, 0xE5, 0xC3, +0xA5, 0x00, 0x21, 0x87, 0x0B, 0xE5, 0xC3, 0xA5, +0x00, 0xAF, 0x32, 0xD3, 0xFB, 0xF1, 0x22, 0xCF, +0xFB, 0xD5, 0xE5, 0xF5, 0x11, 0x04, 0x00, 0x19, +0x7E, 0xFE, 0x09, 0xCA, 0x8C, 0x45, 0xF1, 0xE1, +0xD1, 0xC3, 0xA5, 0x00, 0xF1, 0xF5, 0xFE, 0x00, +0xCA, 0xB0, 0x45, 0xFE, 0x02, 0xCA, 0x3C, 0x46, +0xFE, 0x04, 0xCA, 0x04, 0x47, 0xFE, 0x06, 0xCA, +0x5B, 0x46, 0xFE, 0x08, 0xC2, 0x86, 0x45, 0x38, +0x06, 0x21, 0x93, 0x1A, 0xD9, 0xC3, 0x86, 0x45, +0xAF, 0xCD, 0xDC, 0x4A, 0x21, 0x7E, 0xFB, 0x7E, +0xFE, 0x20, 0xCA, 0xC2, 0x45, 0xFE, 0x44, 0xC2, +0xE1, 0x48, 0x36, 0x44, 0x23, 0x36, 0x4F, 0x21, +0x78, 0xFB, 0xCD, 0xAE, 0x4A, 0x4F, 0xCD, 0xAF, +0x46, 0x36, 0x00, 0xE1, 0xE1, 0xD1, 0xD5, 0xE5, +0x51, 0x7B, 0xE6, 0x07, 0x21, 0x3C, 0x4B, 0x4F, +0x06, 0x00, 0x09, 0x7E, 0x3D, 0xCA, 0x21, 0x46, +0x3D, 0xC2, 0x34, 0x46, 0x3A, 0x1D, 0xFC, 0xA7, +0xC2, 0xF5, 0x45, 0x23, 0x23, 0x7E, 0x32, 0xE9, +0xFB, 0x21, 0x01, 0x01, 0xCD, 0xF2, 0x40, 0x2A, +0xCF, 0xFB, 0x11, 0x07, 0x00, 0x19, 0xAF, 0x77, +0x23, 0x54, 0x5D, 0x23, 0x23, 0xD9, 0xE1, 0xD1, +0x7B, 0xFE, 0x08, 0xC2, 0x18, 0x46, 0x1E, 0x02, +0x73, 0xE3, 0x21, 0x4E, 0x19, 0xE3, 0xC3, 0xA5, +0x00, 0x7A, 0xB7, 0xCA, 0xF5, 0x45, 0xE5, 0xCD, +0x71, 0x43, 0x21, 0x78, 0xFB, 0xCD, 0xAE, 0x4A, +0xE1, 0xC3, 0xF5, 0x45, 0x7A, 0xB7, 0xCA, 0xCF, +0x48, 0xC3, 0xF5, 0x45, 0xF1, 0xE1, 0xD1, 0xE5, +0x7E, 0x36, 0x00, 0xFE, 0x02, 0xCC, 0x31, 0x47, +0x21, 0x02, 0x00, 0xCD, 0xF2, 0x40, 0xCD, 0x1B, +0x4B, 0xE1, 0xE3, 0xE1, 0x21, 0x05, 0x4F, 0xE5, +0xC3, 0xA5, 0x00, 0xCD, 0xAF, 0x46, 0x7E, 0x36, +0x00, 0xA7, 0xC2, 0x7B, 0x46, 0x2A, 0xCF, 0xFB, +0x01, 0x07, 0x00, 0x09, 0x7E, 0x23, 0xE5, 0xA7, +0xCC, 0xB7, 0x46, 0xD1, 0xED, 0x7E, 0x23, 0xD9, +0x1B, 0xEB, 0x35, 0xFE, 0x1A, 0x37, 0x3F, 0xC2, +0x87, 0x46, 0xCD, 0xAF, 0x46, 0x77, 0x37, 0xF5, +0x38, 0x10, 0xED, 0x01, 0x0F, 0x1D, 0x08, 0xC2, +0xA3, 0x46, 0xCD, 0xAF, 0x46, 0xF1, 0x77, 0x4F, +0x9F, 0xCD, 0x23, 0x4C, 0x38, 0x12, 0xEB, 0xF9, +0xC3, 0xA5, 0x00, 0xF1, 0xE1, 0xE1, 0xD1, 0xE3, +0x21, 0x25, 0x50, 0xE3, 0xC3, 0xA5, 0x00, 0x2A, +0x8F, 0xF9, 0x11, 0x7E, 0xF9, 0x19, 0xC9, 0x21, +0x03, 0x00, 0xCD, 0x76, 0x48, 0xCD, 0x20, 0x48, +0x3A, 0x03, 0xFC, 0xFE, 0x10, 0xC2, 0xF2, 0x46, +0x3A, 0x04, 0xFC, 0x2A, 0xCF, 0xFB, 0x11, 0x08, +0x00, 0x19, 0xE5, 0x54, 0x5D, 0x23, 0x23, 0xD9, +0x11, 0x05, 0xFC, 0xEB, 0x4F, 0x06, 0x00, 0xCD, +0x5C, 0x4A, 0x3A, 0x04, 0xFC, 0xFE, 0x80, 0xCA, +0xEE, 0x46, 0xEB, 0x36, 0x1A, 0x3C, 0xE1, 0x2B, +0x77, 0xC9, 0x2A, 0xCF, 0xFB, 0x11, 0x07, 0x00, +0x19, 0x36, 0x01, 0x23, 0x54, 0x5D, 0x23, 0x23, +0xD9, 0x36, 0x1A, 0xC9, 0x2A, 0xCF, 0xFB, 0x11, +0x07, 0x00, 0x19, 0x7E, 0xFE, 0x80, 0xCC, 0x31, +0x47, 0xF1, 0xE1, 0xD1, 0xE1, 0xF1, 0xF5, 0xFE, +0x1A, 0xCA, 0x2A, 0x47, 0x2A, 0xCF, 0xFB, 0x11, +0x07, 0x00, 0x19, 0x34, 0x23, 0xEB, 0xED, 0x77, +0x23, 0xD9, 0x21, 0x5A, 0x19, 0xE5, 0xC3, 0xA5, +0x00, 0x2A, 0xCF, 0xFB, 0x01, 0x07, 0x00, 0x09, +0x7E, 0xE5, 0x23, 0x23, 0x23, 0x11, 0x05, 0xFC, +0x4F, 0x06, 0x00, 0xF5, 0xCD, 0x5C, 0x4A, 0xF1, +0xA7, 0xC4, 0xEC, 0x40, 0xE1, 0x36, 0x00, 0x23, +0x54, 0x5D, 0x23, 0x23, 0xD9, 0xC9, 0xF1, 0xC9, +0x21, 0xA1, 0xF5, 0x22, 0xDC, 0xFB, 0xCD, 0x89, +0x47, 0xC2, 0xBE, 0x48, 0xAF, 0x32, 0xDB, 0xFB, +0x32, 0xD5, 0xFB, 0x3D, 0x32, 0xD8, 0xFB, 0x3E, +0x01, 0x32, 0xE6, 0xF3, 0xCD, 0x9B, 0x47, 0xC3, +0x7B, 0x4C, 0xCD, 0x67, 0x4A, 0xCD, 0x96, 0x4C, +0x21, 0x28, 0x4B, 0xCD, 0x83, 0x4A, 0xC3, 0x7B, +0x4C, 0xAF, 0x32, 0xD7, 0xFB, 0xCD, 0x9A, 0x49, +0x21, 0x46, 0x01, 0xC3, 0xC3, 0x47, 0x3E, 0x15, +0x32, 0xD8, 0xFB, 0x3A, 0xCC, 0xFB, 0xA7, 0xC2, +0xAB, 0x47, 0x21, 0xF6, 0x02, 0xCD, 0xC3, 0x47, +0xC2, 0x4C, 0x48, 0x3A, 0x05, 0xFC, 0xA7, 0xC8, +0x3A, 0xDB, 0xFB, 0xA7, 0xCC, 0xD5, 0x47, 0x21, +0xD7, 0xFB, 0x34, 0x3A, 0xD8, 0xFB, 0xBE, 0xC2, +0xA2, 0x47, 0xC9, 0x22, 0x01, 0xFC, 0x21, 0x00, +0x1A, 0xCD, 0x76, 0x48, 0xCD, 0x20, 0x48, 0x3A, +0x03, 0xFC, 0xFE, 0x11, 0xC9, 0x0E, 0x09, 0x21, +0x05, 0xFC, 0xCD, 0x39, 0x49, 0x3E, 0x20, 0xE7, +0x2A, 0x1E, 0xFC, 0x5C, 0x55, 0x2A, 0xDC, 0xFB, +0xEB, 0xD9, 0xEB, 0x23, 0x23, 0x22, 0xDC, 0xFB, +0xC9, 0x21, 0x03, 0xFC, 0xE5, 0xCD, 0xB3, 0xFC, +0xCD, 0xB3, 0xFC, 0x4F, 0xCD, 0xB3, 0xFC, 0x41, +0x79, 0xA7, 0xCA, 0xA5, 0xFC, 0xCD, 0xB3, 0xFC, +0x0D, 0xC2, 0x9E, 0xFC, 0xE1, 0x04, 0x04, 0xAF, +0x30, 0x86, 0x23, 0x05, 0xC2, 0xAA, 0xFC, 0x2F, +0xBE, 0xC9, 0xCD, 0xD3, 0x6D, 0x77, 0x23, 0xC9, +0x21, 0xF1, 0x47, 0x11, 0x8A, 0xFC, 0x01, 0x2F, +0x00, 0xCD, 0x5C, 0x4A, 0xCD, 0xB6, 0x48, 0xCD, +0x33, 0x4C, 0xCF, 0x8A, 0xFC, 0xC2, 0xBE, 0x48, +0xC9, 0xCD, 0x3F, 0x48, 0x77, 0x23, 0xC9, 0xCD, +0xB6, 0x48, 0xCD, 0x3F, 0x4C, 0xDA, 0xE1, 0x48, +0xC2, 0xBE, 0x48, 0xC9, 0x3A, 0x03, 0xFC, 0xFE, +0x12, 0xC2, 0xBE, 0x48, 0x3A, 0x05, 0xFC, 0xA7, +0xC8, 0xFE, 0x10, 0xCA, 0xD2, 0x48, 0xFE, 0x50, +0xCA, 0xC1, 0x48, 0xFE, 0x60, 0xCA, 0xD5, 0x48, +0xDA, 0xBE, 0x48, 0xCA, 0xC7, 0x48, 0xFE, 0x80, +0xDA, 0xC7, 0x48, 0xC3, 0xC4, 0x48, 0x22, 0xE7, +0xFB, 0x21, 0xE7, 0xFB, 0xE5, 0x3A, 0xCB, 0xFB, +0xA7, 0xCA, 0x8B, 0x48, 0xE6, 0x01, 0x1F, 0x1F, +0x1F, 0xB6, 0x77, 0x7E, 0x23, 0x86, 0x47, 0x7E, +0xF5, 0x23, 0xA7, 0xCA, 0x9F, 0x48, 0x4F, 0x78, +0x86, 0x23, 0x0D, 0xC2, 0x98, 0x48, 0x47, 0x78, +0x2F, 0x57, 0x01, 0x5A, 0x5A, 0xCD, 0x32, 0x4A, +0xC1, 0x48, 0x06, 0x00, 0x03, 0x03, 0xE1, 0xCD, +0x2D, 0x49, 0x7A, 0xCD, 0x3B, 0x4C, 0xDB, 0xBB, +0xE6, 0x20, 0xC8, 0x3E, 0x01, 0x21, 0x3E, 0x02, +0x21, 0x3E, 0x03, 0x21, 0x3E, 0x04, 0x21, 0x3E, +0x05, 0x21, 0xDA, 0xFB, 0x36, 0x00, 0x21, 0x3E, +0x06, 0x21, 0x3E, 0x07, 0x21, 0x3E, 0x08, 0x21, +0x3E, 0x09, 0x21, 0x3E, 0x0A, 0x21, 0x3E, 0x0B, +0x21, 0x3E, 0x0C, 0x21, 0x3E, 0x0D, 0x21, 0x5A, +0x4B, 0x4F, 0x0D, 0xCA, 0xF8, 0x48, 0x7E, 0x23, +0xFE, 0x00, 0xC2, 0xEE, 0x48, 0xC3, 0xEA, 0x48, +0x3A, 0xD3, 0xFB, 0xA7, 0xCA, 0x24, 0x49, 0x3E, +0x07, 0xE7, 0x23, 0xCD, 0x48, 0x49, 0xCD, 0x1B, +0x49, 0x2A, 0xCF, 0xFB, 0xF9, 0x2A, 0xD1, 0xFB, +0xE5, 0xC9, 0xCD, 0x7B, 0x4C, 0xCD, 0x1B, 0x49, +0xC3, 0x7B, 0x4C, 0x21, 0x13, 0x4C, 0xCD, 0x83, +0x4A, 0xC3, 0x43, 0x4C, 0x5E, 0x2A, 0xCF, 0xFB, +0x36, 0x00, 0xC3, 0x8F, 0x4C, 0x7E, 0xCD, 0xB3, +0x48, 0x23, 0x0B, 0x79, 0xB0, 0xC2, 0x2D, 0x49, +0xC9, 0x7E, 0xFE, 0x20, 0xD2, 0x41, 0x49, 0x3E, +0x20, 0xE7, 0x23, 0x0D, 0xC2, 0x39, 0x49, 0xC9, +0xE5, 0xCD, 0xC6, 0x4C, 0x21, 0x08, 0x01, 0x22, +0xE5, 0xF3, 0xCD, 0x83, 0x4C, 0xE1, 0xC3, 0x83, +0x4A, 0xE5, 0x3E, 0x20, 0x21, 0x78, 0xFB, 0x06, +0x08, 0xCD, 0x8B, 0x4A, 0xE1, 0x11, 0x78, 0xFB, +0x06, 0x06, 0x7E, 0xFE, 0x41, 0xDA, 0xE4, 0x48, +0x7E, 0xFE, 0x2E, 0xCA, 0x82, 0x49, 0xB7, 0xC8, +0x12, 0x23, 0x13, 0x05, 0xC2, 0x70, 0x49, 0xC3, +0x8A, 0x49, 0x3E, 0x20, 0x12, 0x13, 0x05, 0xC2, +0x84, 0x49, 0x06, 0x02, 0x23, 0x7E, 0xB7, 0xC8, +0x12, 0x13, 0x05, 0xC2, 0x8C, 0x49, 0x3E, 0x00, +0x12, 0xC9, 0xCD, 0xEB, 0x4A, 0xCD, 0xF9, 0x49, +0xCD, 0x20, 0x48, 0xCD, 0x4C, 0x48, 0x3A, 0xCC, +0xFB, 0xA7, 0xC8, 0x21, 0x08, 0x00, 0xCD, 0x76, +0x48, 0xCD, 0x20, 0x48, 0x3A, 0x04, 0xFC, 0xFE, +0x01, 0xCA, 0xCE, 0x49, 0x3D, 0x4F, 0x3E, 0x02, +0x32, 0xCC, 0xFB, 0x06, 0x00, 0x21, 0x06, 0xFC, +0x11, 0xC1, 0xFB, 0xC3, 0x5C, 0x4A, 0x21, 0x23, +0x00, 0xCD, 0x76, 0x48, 0xCD, 0x20, 0x48, 0x21, +0x3F, 0x4B, 0xCD, 0xE6, 0x49, 0x21, 0x48, 0x4B, +0xCD, 0xE6, 0x49, 0x21, 0x51, 0x4B, 0x01, 0x09, +0x00, 0xCD, 0x2D, 0x49, 0xC3, 0x20, 0x48, 0xCD, +0x37, 0x4C, 0xC8, 0xCD, 0x3F, 0x48, 0xC3, 0xEF, +0x49, 0xCD, 0xB6, 0x48, 0xCD, 0x24, 0x4A, 0xCD, +0xEF, 0x49, 0xCD, 0xF2, 0x41, 0xCD, 0x2A, 0x4A, +0xCD, 0x37, 0x4C, 0x3E, 0x00, 0xC2, 0x11, 0x4A, +0x3C, 0x32, 0xCC, 0xFB, 0xCD, 0xEF, 0x49, 0xCD, +0x24, 0x4A, 0xCD, 0xEF, 0x49, 0x21, 0x07, 0x00, +0xCD, 0x76, 0x48, 0xC9, 0x01, 0x31, 0x4D, 0xCD, +0x32, 0x4A, 0x3E, 0x0D, 0xCD, 0xB3, 0x48, 0xC3, +0x3A, 0x4A, 0x78, 0xCD, 0xB3, 0x48, 0x79, 0xC3, +0xB3, 0x48, 0x26, 0x14, 0x2E, 0xFF, 0x2D, 0xC2, +0x3E, 0x4A, 0x25, 0xC2, 0x3C, 0x4A, 0xC9, 0x01, +0x50, 0xFF, 0xCD, 0x3A, 0x4A, 0xCD, 0x37, 0x4C, +0xC0, 0x05, 0xC2, 0x4A, 0x4A, 0x0D, 0xC2, 0x4A, +0x4A, 0xC3, 0xBB, 0x48, 0x7E, 0x12, 0x23, 0x13, +0x0B, 0x78, 0xB1, 0xC2, 0x5C, 0x4A, 0xC9, 0x3A, +0x20, 0xFC, 0x6F, 0x26, 0x00, 0x11, 0x80, 0x00, +0xC3, 0x77, 0x4C, 0xD5, 0xE5, 0x1A, 0x96, 0xC2, +0x80, 0x4A, 0x23, 0x13, 0x0D, 0xC2, 0x75, 0x4A, +0xE1, 0xD1, 0xC9, 0x7E, 0xA7, 0xC8, 0xE7, 0x23, +0xC3, 0x83, 0x4A, 0x77, 0x23, 0x05, 0xC2, 0x8B, +0x4A, 0xC9, 0x3E, 0x20, 0x06, 0x18, 0x21, 0xE9, +0xFB, 0xCD, 0x8B, 0x4A, 0x3E, 0x46, 0x32, 0x01, +0xFC, 0xC9, 0x2A, 0xE5, 0xFB, 0xCD, 0x59, 0x49, +0xCD, 0x67, 0x4C, 0xC3, 0x53, 0x4C, 0xE5, 0xCD, +0x92, 0x4A, 0xE1, 0x11, 0xE9, 0xFB, 0x01, 0x06, +0x00, 0xCD, 0x5C, 0x4A, 0x3E, 0x2E, 0x12, 0x13, +0x01, 0x02, 0x00, 0xCD, 0x5C, 0x4A, 0xCD, 0x9A, +0x49, 0x3E, 0x00, 0x32, 0x02, 0xFC, 0x21, 0x00, +0x1A, 0xCD, 0x76, 0x48, 0xCD, 0x20, 0x48, 0x3A, +0x1D, 0xFC, 0xA7, 0xC9, 0x32, 0xD3, 0xFB, 0x11, +0x7F, 0xF8, 0x21, 0x06, 0xF4, 0x01, 0x06, 0x00, +0xC3, 0x5C, 0x4A, 0xCD, 0x2F, 0x4C, 0x21, 0x35, +0x4B, 0x11, 0x06, 0xF4, 0x01, 0x06, 0x00, 0xCD, +0x5C, 0x4A, 0x21, 0x06, 0xF4, 0x37, 0xCD, 0x2B, +0x4C, 0xCD, 0xEF, 0x49, 0xCD, 0xF9, 0x49, 0xCD, +0x3A, 0x4A, 0xCD, 0x37, 0x4C, 0xC2, 0xEF, 0x49, +0xCD, 0x2F, 0x4C, 0x21, 0x06, 0xF4, 0x35, 0x37, +0xC3, 0x2B, 0x4C, 0x21, 0x7F, 0xF8, 0x7E, 0xD6, +0x3A, 0xDA, 0x2B, 0x4C, 0x23, 0xC3, 0x2B, 0x4C, +0x30, 0x20, 0x42, 0x79, 0x74, 0x65, 0x73, 0x20, +0x66, 0x72, 0x65, 0x65, 0x00, 0x39, 0x4E, 0x38, +0x31, 0x4E, 0x4E, 0x00, 0x02, 0x03, 0x01, 0x5A, +0x5A, 0x31, 0x04, 0x01, 0x00, 0x84, 0xFF, 0x46, +0x5A, 0x5A, 0x31, 0x04, 0x01, 0x00, 0x96, 0x0F, +0x24, 0x5A, 0x5A, 0x31, 0x04, 0x01, 0x00, 0x94, +0x0F, 0x26, 0x12, 0x44, 0x72, 0x69, 0x76, 0x65, +0x20, 0x4E, 0x6F, 0x74, 0x20, 0x52, 0x65, 0x61, +0x64, 0x79, 0x00, 0x12, 0x43, 0x6F, 0x6D, 0x6D, +0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, +0x6E, 0x20, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x00, +0x12, 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, 0x50, +0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x00, 0x12, +0x44, 0x72, 0x69, 0x76, 0x65, 0x20, 0x54, 0x72, +0x6F, 0x75, 0x62, 0x6C, 0x65, 0x00, 0x12, 0x44, +0x69, 0x73, 0x6B, 0x20, 0x6E, 0x6F, 0x74, 0x20, +0x69, 0x6E, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, +0x00, 0x34, 0x50, 0x72, 0x69, 0x6E, 0x74, 0x65, +0x72, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x65, +0x61, 0x64, 0x79, 0x00, 0x05, 0x46, 0x69, 0x6C, +0x65, 0x20, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, +0x00, 0x39, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x46, +0x75, 0x6C, 0x6C, 0x00, 0x1A, 0x46, 0x69, 0x6C, +0x65, 0x20, 0x45, 0x6D, 0x70, 0x74, 0x79, 0x00, +0x39, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, +0x72, 0x79, 0x20, 0x46, 0x75, 0x6C, 0x6C, 0x00, +0x07, 0x52, 0x61, 0x6D, 0x20, 0x46, 0x75, 0x6C, +0x6C, 0x00, 0x36, 0x00, 0x37, 0x42, 0x61, 0x64, +0x20, 0x46, 0x69, 0x6C, 0x65, 0x20, 0x4E, 0x61, +0x6D, 0x65, 0x00, 0x20, 0x50, 0x72, 0x65, 0x73, +0x73, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, +0x79, 0x2E, 0x00, 0xCF, 0xAB, 0x31, 0xC9, 0xCF, +0xC8, 0x13, 0xC9, 0xCF, 0x4E, 0x1C, 0xC9, 0xCF, +0xA8, 0x6F, 0xC9, 0xCF, 0xE5, 0x76, 0xC9, 0xCF, +0xC2, 0x6D, 0xC9, 0xCF, 0xBE, 0x6E, 0xC9, 0xCF, +0xD3, 0x6D, 0xC9, 0xCF, 0x4D, 0x17, 0xC9, 0xCF, +0x79, 0x72, 0xC9, 0xCF, 0x17, 0x18, 0xC9, 0xCF, +0xF4, 0x1E, 0xC9, 0xCF, 0x9B, 0x22, 0xC9, 0xCF, +0xA8, 0x21, 0xC9, 0xCF, 0x00, 0x22, 0xC9, 0xCF, +0xC2, 0x21, 0xC9, 0xCF, 0x0A, 0x6C, 0xC9, 0xCF, +0x3A, 0x23, 0xC9, 0xCF, 0x18, 0x07, 0xC9, 0xCF, +0x35, 0x24, 0xC9, 0xCF, 0x7A, 0x34, 0xC9, 0xCF, +0x23, 0x34, 0xC9, 0xCF, 0x51, 0x42, 0xC9, 0xCF, +0x60, 0x42, 0xC9, 0xCF, 0x8C, 0x42, 0xC9, 0xCF, +0xA2, 0x42, 0xC9, 0xCF, 0xA7, 0x42, 0xC9, 0x21, +0x85, 0x05, 0xE5, 0xC3, 0xA5, 0x00, 0xCF, 0x98, +0x38, 0xC9, 0xCF, 0x0B, 0x4D, 0xC9, 0xCF, 0xAA, +0x47, 0xC9, 0xCF, 0x3D, 0x18, 0xC9, 0xCF, 0x83, +0x6C, 0xC9, 0xCF, 0x6E, 0x42, 0xC9, 0xCF, 0x73, +0x42, 0xC9, 0xCF, 0x2D, 0x4E, 0xC9, 0xCF, 0x14, +0x07, 0xC9, 0xCF, 0xF8, 0x28, 0xC9, 0xCF, 0xD2, +0x26, 0xC9, 0xCF, 0xE4, 0x42, 0xC9, 0xCF, 0xC3, +0x42, 0xC9, 0xCF, 0x44, 0x4D, 0xC9, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xCD, 0x08, 0x50, 0xC9, 0xCD, 0x0F, 0x50, 0xC9, +0xAF, 0x32, 0xBA, 0xF5, 0xC3, 0x18, 0x50, 0x3E, +0x0C, 0x32, 0xBA, 0xF5, 0xE7, 0xCD, 0x46, 0x53, +0x22, 0xB7, 0xF5, 0x21, 0x4A, 0x53, 0x11, 0xA1, +0xF5, 0x01, 0x15, 0x00, 0xCD, 0x17, 0x53, 0x3E, +0x50, 0x32, 0xB9, 0xF5, 0xAF, 0x32, 0xBB, 0xF5, +0xCD, 0x3A, 0x53, 0x2A, 0xB7, 0xF5, 0xCD, 0x32, +0x53, 0xD5, 0xCD, 0xAA, 0x52, 0x00, 0x2E, 0x7E, +0xC2, 0x45, 0x50, 0x2E, 0x80, 0x01, 0x00, 0x00, +0x1A, 0xBD, 0xDA, 0x4E, 0x50, 0x03, 0x13, 0xFE, +0x1A, 0xC2, 0x48, 0x50, 0xE1, 0x3A, 0xBA, 0xF5, +0xD6, 0x0C, 0xC2, 0x5F, 0x50, 0x47, 0x4F, 0xCD, +0x3E, 0x53, 0xD8, 0x2B, 0xE5, 0xCD, 0xA4, 0x52, +0xC2, 0x97, 0x50, 0xCD, 0xAA, 0x52, 0xDC, 0x06, +0x53, 0xC3, 0x19, 0x52, 0xCD, 0x22, 0x53, 0xDA, +0x74, 0x50, 0xCD, 0x36, 0x53, 0xC9, 0x4F, 0xFE, +0x3A, 0xD0, 0xFE, 0x20, 0x37, 0xC8, 0xFE, 0x2F, +0xC8, 0x3F, 0xC9, 0xD6, 0x2F, 0xD0, 0x3E, 0x0B, +0xC9, 0xFE, 0x3A, 0xC0, 0x3E, 0x20, 0xC9, 0xD5, +0x00, 0x00, 0x01, 0x00, 0x00, 0xC5, 0xE1, 0x03, +0x13, 0x1A, 0xFE, 0x5B, 0xD2, 0x9F, 0x50, 0xFE, +0x1A, 0xCA, 0xB6, 0x50, 0xFE, 0x41, 0xDA, 0xA0, +0x50, 0x00, 0x23, 0xC3, 0xA0, 0x50, 0xC5, 0xD1, +0xDF, 0xD1, 0xDA, 0xC5, 0x50, 0xCD, 0x06, 0x53, +0x3E, 0x43, 0x32, 0xB9, 0xF5, 0xAF, 0x32, 0xBB, +0xF5, 0xCD, 0x09, 0x52, 0xCD, 0x89, 0x51, 0xD2, +0x5D, 0x51, 0xCD, 0x7E, 0x50, 0x00, 0xD2, 0x16, +0x51, 0x13, 0x1A, 0xCD, 0x7F, 0x50, 0x1B, 0x47, +0x79, 0xD2, 0x16, 0x51, 0xC2, 0xED, 0x50, 0xB8, +0xCA, 0x35, 0x51, 0x00, 0x00, 0x13, 0x21, 0xBB, +0xF5, 0x00, 0x7E, 0xB7, 0xC2, 0xFE, 0x50, 0x3E, +0x7E, 0x77, 0xE1, 0x77, 0x23, 0xE5, 0x79, 0xCD, +0x8B, 0x50, 0x00, 0x4F, 0x78, 0xCD, 0x8B, 0x50, +0xC6, 0x0B, 0x0D, 0xC2, 0x08, 0x51, 0xC6, 0x7A, +0xE1, 0x77, 0xE5, 0xC3, 0xC9, 0x50, 0xE1, 0xFE, +0x0D, 0xC2, 0x29, 0x51, 0x13, 0x1A, 0xFE, 0x0A, +0x1B, 0x3E, 0x0D, 0xC2, 0x29, 0x51, 0x13, 0x3E, +0x80, 0x77, 0xE5, 0x3A, 0xBB, 0xF5, 0xB7, 0xC2, +0xC5, 0x50, 0x00, 0x00, 0x7E, 0x21, 0xA0, 0xF5, +0x06, 0x07, 0x05, 0xCA, 0xC9, 0x50, 0x23, 0xBE, +0xC2, 0x3A, 0x51, 0x0E, 0x15, 0xCD, 0x89, 0x51, +0xD2, 0x5D, 0x51, 0x21, 0xA1, 0xF5, 0xBE, 0xCA, +0x7A, 0x51, 0x0D, 0xCC, 0x09, 0x52, 0xCA, 0x83, +0x51, 0x23, 0xC3, 0x4E, 0x51, 0x32, 0xB6, 0xF5, +0xAF, 0x32, 0xBB, 0xF5, 0x78, 0xFE, 0x07, 0xD2, +0x6D, 0x51, 0xCD, 0x09, 0x52, 0xE1, 0x36, 0xFF, +0xE5, 0x3A, 0xB6, 0xF5, 0xCD, 0x94, 0x51, 0xC3, +0xC9, 0x50, 0x79, 0xC6, 0x15, 0x05, 0xC2, 0x7B, +0x51, 0xC6, 0x6B, 0xE1, 0x77, 0xE5, 0xC3, 0xC9, +0x50, 0x13, 0x1A, 0xFE, 0x1A, 0xCA, 0xB9, 0x52, +0xFE, 0x7E, 0xC9, 0x7E, 0x4F, 0x3A, 0xBA, 0xF5, +0xB7, 0x79, 0xC1, 0xE1, 0x23, 0xC2, 0xA1, 0x51, +0x77, 0xE5, 0xC5, 0xC8, 0xE7, 0xD5, 0x6F, 0x3A, +0xE6, 0xF3, 0x2F, 0xC6, 0x2C, 0x67, 0x7D, 0xCD, +0xD6, 0x51, 0x00, 0x00, 0x3F, 0xCA, 0xC3, 0x51, +0xD2, 0xC6, 0x51, 0x13, 0x1A, 0xCD, 0xD6, 0x51, +0xC3, 0xB5, 0x51, 0xCD, 0x2E, 0x53, 0xCD, 0x74, +0x50, 0x00, 0xD1, 0xC8, 0xFE, 0x20, 0xDA, 0xB9, +0x52, 0xCC, 0x26, 0x53, 0x00, 0xC9, 0x25, 0xC8, +0xFE, 0x21, 0x3F, 0xD0, 0xFE, 0xFE, 0x3D, 0xD0, +0xD6, 0x7F, 0xCA, 0xFF, 0x51, 0xD8, 0x25, 0x00, +0xC8, 0xF5, 0x3A, 0xBB, 0xF5, 0xB7, 0x01, 0x0B, +0x05, 0xC2, 0xF7, 0x51, 0x01, 0x15, 0x00, 0xF1, +0x90, 0x90, 0x00, 0xD8, 0x3C, 0xFE, 0x6A, 0x3D, +0xD0, 0x80, 0x91, 0xD8, 0xC2, 0x02, 0x52, 0x3C, +0xC9, 0xC1, 0xE1, 0x23, 0xE5, 0xC5, 0xC9, 0xAF, +0x32, 0xBB, 0xF5, 0xCD, 0x89, 0x51, 0xC3, 0x2E, +0x52, 0xCD, 0xAA, 0x52, 0xC2, 0x0F, 0x52, 0xCD, +0x89, 0x51, 0xDA, 0x2E, 0x52, 0xC2, 0x38, 0x52, +0x32, 0xBB, 0xF5, 0xC3, 0x19, 0x52, 0xCD, 0x94, +0x51, 0xAF, 0x32, 0xBB, 0xF5, 0xC3, 0x19, 0x52, +0xFE, 0x80, 0xC2, 0x47, 0x52, 0x3E, 0x0D, 0xCD, +0x94, 0x51, 0x3E, 0x0A, 0xC3, 0x2E, 0x52, 0xFE, +0xFE, 0xCA, 0x80, 0x52, 0xD2, 0x0F, 0x52, 0x4F, +0x3A, 0xBB, 0xF5, 0xB7, 0x79, 0xCA, 0x80, 0x52, +0xD6, 0x86, 0xDA, 0x19, 0x52, 0x01, 0x00, 0x00, +0x0C, 0xD6, 0x0B, 0xD2, 0x60, 0x52, 0xC6, 0x3B, +0xCD, 0x91, 0x50, 0x32, 0xB6, 0xF5, 0x79, 0xC6, +0x2F, 0xCD, 0x91, 0x50, 0xCD, 0x94, 0x51, 0x3A, +0xB6, 0xF5, 0xCD, 0x94, 0x51, 0xC3, 0x19, 0x52, +0xD6, 0x81, 0x21, 0xA7, 0xF5, 0x2B, 0xD6, 0x15, +0xD2, 0x85, 0x52, 0xC6, 0x16, 0x32, 0xB6, 0xF5, +0xCD, 0x93, 0x51, 0x3A, 0xB6, 0xF5, 0x21, 0xB6, +0xF5, 0x2B, 0x3D, 0xC2, 0x99, 0x52, 0xCD, 0x93, +0x51, 0xC3, 0x19, 0x52, 0x3A, 0xBA, 0xF5, 0xFE, +0x0C, 0xC8, 0x2A, 0xB7, 0xF5, 0x01, 0x0A, 0x00, +0x09, 0x7E, 0xFE, 0x50, 0xC8, 0xFE, 0x43, 0x37, +0xC9, 0x32, 0xB6, 0xF5, 0xC5, 0xCD, 0xA4, 0x52, +0xC1, 0xD1, 0xE1, 0xFE, 0x0C, 0xC2, 0xD5, 0x52, +0x3A, 0xB6, 0xF5, 0xFE, 0x1A, 0xCC, 0x26, 0x53, +0xCD, 0x2A, 0x53, 0xBF, 0xC9, 0xD6, 0x43, 0xCA, +0xE5, 0x52, 0xD6, 0x0F, 0xCA, 0xE5, 0x52, 0x78, +0xFE, 0x07, 0xD2, 0xE6, 0x52, 0x23, 0xE5, 0x2B, +0x01, 0xFF, 0xFF, 0x3E, 0x1A, 0x03, 0x23, 0xBE, +0xC2, 0xED, 0x52, 0xE1, 0xCD, 0x42, 0x53, 0xCD, +0xAA, 0x52, 0xCA, 0x03, 0x53, 0x3A, 0xB9, 0xF5, +0x77, 0xBF, 0xC9, 0x36, 0x4F, 0xC9, 0x21, 0xA2, +0xF5, 0x3E, 0x14, 0xF5, 0x7E, 0xE6, 0xDF, 0x77, +0xF1, 0x3D, 0xC8, 0x23, 0xC3, 0x0B, 0x53, 0x7E, +0x12, 0x23, 0x13, 0x0B, 0x78, 0xB1, 0xC2, 0x17, +0x53, 0xC9, 0xCF, 0xDF, 0x72, 0xC9, 0xCF, 0x4D, +0x17, 0xC9, 0xCF, 0x60, 0x42, 0xC9, 0xCF, 0x51, +0x42, 0xC9, 0xCF, 0xBC, 0x22, 0xC9, 0xCF, 0x79, +0x72, 0xC9, 0xCF, 0x3A, 0x23, 0xC9, 0xCF, 0x0A, +0x6C, 0xC9, 0xCF, 0x3C, 0x6C, 0xC9, 0xCF, 0x73, +0x42, 0xC9, 0x20, 0x65, 0x74, 0x61, 0x6F, 0x69, +0x6E, 0x72, 0x73, 0x68, 0x64, 0x6C, 0x66, 0x63, +0x6D, 0x75, 0x67, 0x79, 0x70, 0x77, 0x62, 0xFF +}; + From c11eb2f771d054565c57a1f001602da9cc168789 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Thu, 7 Mar 2013 19:42:51 +0000 Subject: [PATCH 243/327] Added default REX directory image to resimages.c --- src/reximages.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/reximages.c b/src/reximages.c index 48b7976..b349ec7 100644 --- a/src/reximages.c +++ b/src/reximages.c @@ -4102,3 +4102,23 @@ const unsigned char gRex248Image[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +/* Rex default directories image */ +const unsigned char gRexDirectories[] = { +0xC0, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4D, 0x03, +0x10, 0x81, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, +0xC1, 0x53, 0x59, 0x53, 0x42, 0x41, 0x4B, 0x03, +0x10, 0x81, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, +0xC2, 0x4D, 0x41, 0x49, 0x4E, 0x31, 0x50, 0x03, +0x10, 0x81, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, +0xC3, 0x4D, 0x41, 0x49, 0x4E, 0x32, 0x50, 0x03, +0x10, 0x81, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, +0xC4, 0x4D, 0x41, 0x49, 0x4E, 0x31, 0x53, 0x03, +0x10, 0x81, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, +0xC5, 0x4D, 0x41, 0x49, 0x4E, 0x32, 0x53, 0x03, +0x10, 0x81, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, +0xC8, 0x54, 0x53, 0x2D, 0x44, 0x4F, 0x53, 0x01, +0x10, 0x81, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, +0xC6, 0x62, 0x61, 0x63, 0x6B, 0x75, 0x70, 0x00, +0x10, 0x81, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF +}; + From c797ebc962d44c669baa941c7e9fd73e5fdc0a2b Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 8 Mar 2013 00:33:37 +0000 Subject: [PATCH 244/327] Added button to Memory Options to create a default REX Flash file and fixed CTS / DSR flag issue with simulated NADSBox in M100 mode (the fix for T200 shouldn't have applied in M100 mode). --- VirtualT.vcproj | 8 ++++ src/reximages.c | 6 +-- src/setup.cpp | 107 +++++++++++++++++++++++++++++++++++++++++---- src/tpddserver.cpp | 3 +- src/tsdosimages.c | 6 +-- 5 files changed, 114 insertions(+), 16 deletions(-) diff --git a/VirtualT.vcproj b/VirtualT.vcproj index 3ee9c28..eaaafb3 100644 --- a/VirtualT.vcproj +++ b/VirtualT.vcproj @@ -582,6 +582,10 @@ RelativePath=".\src\remote.cpp" > + + @@ -698,6 +702,10 @@ RelativePath=".\src\tpddserverlog.cpp" > + + diff --git a/src/reximages.c b/src/reximages.c index b349ec7..ed9f6d2 100644 --- a/src/reximages.c +++ b/src/reximages.c @@ -1,5 +1,5 @@ /* Image data for REX 4.8, M100 version */ -const unsigned char gRex148Image[] = { +const unsigned char gRex148Image[16384] = { 0xF3, 0xC3, 0x97, 0x00, 0x52, 0x45, 0x58, 0x21, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -2051,7 +2051,7 @@ const unsigned char gRex148Image[] = { }; /* Image for REX 4.8, T200 version */ -const unsigned char gRex248Image[] = { +const unsigned char gRex248Image[16384] = { 0xF3, 0xC3, 0x97, 0x00, 0x52, 0x45, 0x58, 0x21, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -4103,7 +4103,7 @@ const unsigned char gRex248Image[] = { }; /* Rex default directories image */ -const unsigned char gRexDirectories[] = { +const unsigned char gRexDirectories[16 * 8] = { 0xC0, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4D, 0x03, 0x10, 0x81, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x53, 0x59, 0x53, 0x42, 0x41, 0x4B, 0x03, diff --git a/src/setup.cpp b/src/setup.cpp index 2cdaaa5..040d1e2 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -60,6 +60,14 @@ extern "C" void enable_tpdd_log_menu(int bEnabled); void sound_set_tone_control(double tone); double sound_get_tone_control(void); + +extern const unsigned char gRex148Image[16384]; +extern const unsigned char gRex248Image[16384]; +extern const unsigned char gRexDirectories[16*8]; + +extern const unsigned char gTsDos100Image[21352]; +extern const unsigned char gTsDos200Image[21346]; +extern const unsigned char gTsDosNecImage[21344]; } typedef struct setup_ctrl_struct @@ -126,6 +134,7 @@ typedef struct memory_ctrl_struct Fl_Input* pRampacFile; Fl_Input* pRexFlashFile; Fl_Input* pRex2RamFile; + Fl_Button* pRexCreateFlash; Fl_Button* pReMemBrowse; Fl_Button* pRampacBrowse; Fl_Button* pRexFlashBrowse; @@ -1264,6 +1273,7 @@ void cb_radio_base_memory (Fl_Widget* w, void*) mem_ctrl.pRexFlashBrowse->deactivate(); mem_ctrl.pRex2RamFile->deactivate(); mem_ctrl.pRex2RamBrowse->deactivate(); + mem_ctrl.pRexCreateFlash->deactivate(); } void cb_radio_remem (Fl_Widget* w, void*) @@ -1278,6 +1288,7 @@ void cb_radio_remem (Fl_Widget* w, void*) mem_ctrl.pRexFlashBrowse->deactivate(); mem_ctrl.pRex2RamFile->deactivate(); mem_ctrl.pRex2RamBrowse->deactivate(); + mem_ctrl.pRexCreateFlash->deactivate(); } void cb_radio_rampac (Fl_Widget* w, void*) @@ -1292,6 +1303,7 @@ void cb_radio_rampac (Fl_Widget* w, void*) mem_ctrl.pRexFlashBrowse->deactivate(); mem_ctrl.pRex2RamFile->deactivate(); mem_ctrl.pRex2RamBrowse->deactivate(); + mem_ctrl.pRexCreateFlash->deactivate(); } void cb_radio_remem_and_rampac (Fl_Widget* w, void*) @@ -1306,6 +1318,7 @@ void cb_radio_remem_and_rampac (Fl_Widget* w, void*) mem_ctrl.pRexFlashBrowse->deactivate(); mem_ctrl.pRex2RamFile->deactivate(); mem_ctrl.pRex2RamBrowse->deactivate(); + mem_ctrl.pRexCreateFlash->deactivate(); } void cb_radio_rex (Fl_Widget* w, void*) @@ -1320,6 +1333,7 @@ void cb_radio_rex (Fl_Widget* w, void*) mem_ctrl.pRexFlashBrowse->activate(); mem_ctrl.pRex2RamFile->deactivate(); mem_ctrl.pRex2RamBrowse->deactivate(); + mem_ctrl.pRexCreateFlash->activate(); } void cb_radio_rex2 (Fl_Widget* w, void*) @@ -1334,6 +1348,7 @@ void cb_radio_rex2 (Fl_Widget* w, void*) mem_ctrl.pRexFlashBrowse->activate(); mem_ctrl.pRex2RamFile->activate(); mem_ctrl.pRex2RamBrowse->activate(); + mem_ctrl.pRexCreateFlash->activate(); } void cb_memory_cancel (Fl_Widget* w, void*) @@ -1401,6 +1416,75 @@ void cb_rampac_browse (Fl_Widget* w, void*) delete fc; } +/* +============================================================================ +Callback routine to create default REX Flash +============================================================================ +*/ +void cb_create_flash (Fl_Widget* w, void*) +{ + unsigned char *pData; + FILE* fd; + int x; + + // Allocate a 1M buffer + pData = new unsigned char[1024 * 1024]; + if (pData == NULL) + { + // Report error + fl_alert("Unable to allocate a 1M buffer!"); + return; + } + + // Validate the file can be opened for write mode + if ((fd = fopen(mem_ctrl.pRexFlashFile->value(), "wb")) == NULL) + { + // Report failure ot open file + fl_alert("Unable to open file %s", mem_ctrl.pRexFlashFile->value()); + delete[] pData; + return; + } + + // Fill the buffer with 0xFF + for (x = 0; x < 1024 * 1024; x++) + pData[x] = 0xFF; + + // Now copy in the data + if (gModel == MODEL_T200) + { + // Copy in REX MGR + memcpy(pData, gRex248Image, sizeof(gRex248Image)); + memcpy(&pData[0x4400], gRexDirectories, sizeof(gRexDirectories)); + memcpy(&pData[0x8000], gRex248Image, sizeof(gRex248Image)); + memcpy(&pData[0xC400], gRexDirectories, sizeof(gRexDirectories)); + + // Copy in TS-DOS + memcpy(&pData[0x040000], gTsDos200Image, sizeof(gTsDos200Image)); + } + else if (gModel == MODEL_M100 || gModel == MODEL_M102) + { + // Copy in REX MGR + memcpy(pData, gRex148Image, sizeof(gRex148Image)); + memcpy(&pData[0x4400], gRexDirectories, sizeof(gRexDirectories)); + memcpy(&pData[0x8000], gRex148Image, sizeof(gRex148Image)); + memcpy(&pData[0xC400], gRexDirectories, sizeof(gRexDirectories)); + + // Copy in TS-DOS + memcpy(&pData[0x040000], gTsDos100Image, sizeof(gTsDos100Image)); + } + + // Write data to the file + fwrite(pData, 1, 1024 * 1024, fd); + fclose(fd); + + // Read the new flash + if ((mem_setup.mem_mode == SETUP_MEM_REX) || (mem_setup.mem_mode == SETUP_MEM_REX2)) + load_rex_flash(); + + // Free the buffer + delete[] pData; +} + /* ============================================================================ Routine to create the PeripheralSetup Window and tabs @@ -1409,7 +1493,7 @@ Routine to create the PeripheralSetup Window and tabs void cb_MemorySetup (Fl_Widget* w, void*) { // Create Peripheral Setup window - gmsw = new Fl_Window(420, 415, "Memory Emulation Options"); + gmsw = new Fl_Window(520, 415, "Memory Emulation Options"); gmsw->callback(cb_memorywin); // Create items on the Tab @@ -1470,10 +1554,10 @@ void cb_MemorySetup (Fl_Widget* w, void*) // =============================================== // Setup Rampac File Edit field and Browser button // =============================================== - mem_ctrl.pRampacFile = new Fl_Input(105, 130, 210, 20, "RamPac File"); + mem_ctrl.pRampacFile = new Fl_Input(105, 130, 310, 20, "RamPac File"); mem_ctrl.pRampacFile->value(mem_setup.rampac_file); - mem_ctrl.pRampacBrowse = new Fl_Button(330, 125, 60, 30, "Browse"); + mem_ctrl.pRampacBrowse = new Fl_Button(430, 125, 60, 30, "Browse"); mem_ctrl.pRampacBrowse->callback((Fl_Callback*)cb_rampac_browse); if ((mem_setup.mem_mode != SETUP_MEM_RAMPAC) && (mem_setup.mem_mode != SETUP_MEM_REMEM_RAMPAC)) @@ -1485,12 +1569,12 @@ void cb_MemorySetup (Fl_Widget* w, void*) // =============================================== // Setup ReMem File edit field and Browser button // =============================================== - mem_ctrl.pReMemFile = new Fl_Input(105, 170, 210, 20, "ReMem File"); + mem_ctrl.pReMemFile = new Fl_Input(105, 170, 310, 20, "ReMem File"); mem_ctrl.pReMemFile->value(mem_setup.remem_file); mem_ctrl.pReMemText = new Fl_Box(45, 190, 325, 20, "(Use Memory Editor to load FLASH)"); mem_ctrl.pReMemText->labelsize(12); - mem_ctrl.pReMemBrowse = new Fl_Button(330, 165, 60, 30, "Browse"); + mem_ctrl.pReMemBrowse = new Fl_Button(430, 165, 60, 30, "Browse"); mem_ctrl.pReMemBrowse->callback((Fl_Callback*)cb_remem_browse); if ((mem_setup.mem_mode != SETUP_MEM_REMEM) && (mem_setup.mem_mode != SETUP_MEM_REMEM_RAMPAC)) @@ -1514,12 +1598,17 @@ void cb_MemorySetup (Fl_Widget* w, void*) if (mem_setup.mem_mode == SETUP_MEM_REX2) mem_ctrl.pRex2->value(1); + mem_ctrl.pRexCreateFlash = new Fl_Button(300, 220, 170, 20, "Create Default Flash"); + if (mem_setup.mem_mode != SETUP_MEM_REX && mem_setup.mem_mode != SETUP_MEM_REX2) + mem_ctrl.pRexCreateFlash->deactivate(); + mem_ctrl.pRexCreateFlash->callback(cb_create_flash, &mem_ctrl); + // =============================================== // Setup Rex Flash File edit field and Browser button // =============================================== - mem_ctrl.pRexFlashFile = new Fl_Input(105, 260, 210, 20, "Flash File"); + mem_ctrl.pRexFlashFile = new Fl_Input(105, 260, 310, 20, "Flash File"); mem_ctrl.pRexFlashFile->value(mem_setup.rex_flash_file); - mem_ctrl.pRexFlashBrowse = new Fl_Button(330, 257, 60, 30, "Browse"); + mem_ctrl.pRexFlashBrowse = new Fl_Button(430, 257, 60, 30, "Browse"); mem_ctrl.pRexFlashBrowse->callback((Fl_Callback*)cb_rex_browse); if ((mem_setup.mem_mode != SETUP_MEM_REX) && (mem_setup.mem_mode != SETUP_MEM_REX2)) @@ -1531,9 +1620,9 @@ void cb_MemorySetup (Fl_Widget* w, void*) // =============================================== // Setup Rex Flash File edit field and Browser button // =============================================== - mem_ctrl.pRex2RamFile = new Fl_Input(105, 295, 210, 20, "RAM File"); + mem_ctrl.pRex2RamFile = new Fl_Input(105, 295, 310, 20, "RAM File"); mem_ctrl.pRex2RamFile->value(mem_setup.rex2_ram_file); - mem_ctrl.pRex2RamBrowse = new Fl_Button(330, 292, 60, 30, "Browse"); + mem_ctrl.pRex2RamBrowse = new Fl_Button(430, 292, 60, 30, "Browse"); mem_ctrl.pRex2RamBrowse->callback((Fl_Callback*)cb_rex2_browse); if (mem_setup.mem_mode != SETUP_MEM_REX2) diff --git a/src/tpddserver.cpp b/src/tpddserver.cpp index 319be8e..b24d773 100644 --- a/src/tpddserver.cpp +++ b/src/tpddserver.cpp @@ -632,7 +632,8 @@ int VTTpddServer::SerGetFlags(unsigned char *flags) else *flags &= ~SER_FLAG_TX_EMPTY; - *flags |= SER_FLAG_CTS | SER_FLAG_DSR; + if (gModel == MODEL_T200) + *flags |= SER_FLAG_CTS | SER_FLAG_DSR; return SER_NO_ERROR; } diff --git a/src/tsdosimages.c b/src/tsdosimages.c index d6328a1..a85d877 100644 --- a/src/tsdosimages.c +++ b/src/tsdosimages.c @@ -1,5 +1,5 @@ /* Image for TS-DOS, M100 version */ -const unsigned char gTsDos100Image[] = { +const unsigned char gTsDos100Image[21352] = { 0xC3, 0xB2, 0x00, 0xE1, 0xD1, 0xC1, 0xF1, 0xC9, 0xC3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCF, 0x10, 0x00, 0xC9, 0x00, 0x00, 0x00, 0x00, @@ -2672,7 +2672,7 @@ const unsigned char gTsDos100Image[] = { }; /* TS-DOS T200 image */ -const unsigned char gTsDos200Image[] = { +const unsigned char gTsDos200Image[21346] = { 0xC3, 0xAA, 0x00, 0xE1, 0xD1, 0xC1, 0xF1, 0xC9, 0xC3, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCF, 0x10, 0x00, 0xC9, 0x00, 0x00, 0x00, 0x00, @@ -5344,7 +5344,7 @@ const unsigned char gTsDos200Image[] = { }; /* TS-DOS NEC Image */ -const unsigned char gTsDosNecImage[] = { +const unsigned char gTsDosNecImage[21344] = { 0xC3, 0xAD, 0x00, 0xE1, 0xD1, 0xC1, 0xF1, 0xC9, 0xC3, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCF, 0x10, 0x00, 0xC8, 0xFE, 0x20, 0xC9, 0x00, From 168714fba6e337f01517527cf2640c4fa2de2f17 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 8 Mar 2013 00:35:53 +0000 Subject: [PATCH 245/327] Modified save_file for .DO files so it doesn't append the 1Ah to the host file. --- src/file.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/file.cpp b/src/file.cpp index f1dc92c..037d1d1 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -1430,7 +1430,7 @@ void save_file(model_t_files_t *pFile) } // Write end of file marker (0x1a) to file - fwrite(&ch, 1, 1, fd); + //fwrite(&ch, 1, 1, fd); break; case TYPE_CO: From f1228b8bd855870e3be4345eda6ae029f30d7a88 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 8 Mar 2013 00:39:44 +0000 Subject: [PATCH 246/327] Added PC-8300 ROM image --- ROMs/PC8300rom.bin | Bin 0 -> 131072 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ROMs/PC8300rom.bin diff --git a/ROMs/PC8300rom.bin b/ROMs/PC8300rom.bin new file mode 100644 index 0000000000000000000000000000000000000000..48d82b464a6f4c7ac5d80c9706f661ab5597d360 GIT binary patch literal 131072 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

    svaMPH0@Phy2e>#q*g5Mjliz;< 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 a5D^d&5D^d&5D^d&5D^d&5D^d&aQ+WB9>hfe literal 0 HcmV?d00001 From 98fa2ed91333d41233487de0bbc9cb8f4e4f6795 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 8 Mar 2013 00:41:16 +0000 Subject: [PATCH 247/327] Added detection of missing PC-8300 emulation directory and creation of same. --- src/m100emu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m100emu.c b/src/m100emu.c index 781db97..689fbae 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -640,7 +640,7 @@ void check_installation(void) errors[0] = 0; /* Check each model */ - for (model = MODEL_M100; model < MODEL_PC8300; model++) + for (model = MODEL_M100; model <= MODEL_PC8300; model++) { /* Check if ROM file exists for this model */ if (check_model_support(model)) From 8e08d1ad7904bfbdba8c8a991dccb7dd46e36c5a Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 8 Mar 2013 01:24:33 +0000 Subject: [PATCH 248/327] Fixed bug with REX enabled in models other than M100 causing VT to crash randomly. --- src/memory.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/memory.c b/src/memory.c index 6b47be7..958d814 100644 --- a/src/memory.c +++ b/src/memory.c @@ -732,6 +732,10 @@ void init_mem(void) { gRexModel = REX | gRex; gReMem = 1; + gRexState = 7; + gRexFlash.iFlashState = FLASH_STATE_RO; + gRexSector = 0; + gRexKeyState = 0; } gRampacEmulation = 0; gRampacSectPtr = NULL; @@ -3087,9 +3091,9 @@ unsigned char rex_read(unsigned short address) case 1: /* Set Sector state */ /* Test if RAM mode is enabled and set sector based on result */ - if (gModel && REX2_RAM_MODE) - gRexSector = (address & 0x3F) << 15; - else +// if (gModel && REX2_RAM_MODE) +// gRexSector = (address & 0x3F) << 15; +// else gRexSector = (address & 0x1F) << 15; /* Save Flash Select bit */ From 19e8f6e8dedf78cad1ff1872150b4b3ae573b51f Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 8 Mar 2013 02:32:58 +0000 Subject: [PATCH 249/327] Updated REX default flash generation to include active block and ask to overwrite existing file. --- src/reximages.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++- src/setup.cpp | 20 ++++++-- 2 files changed, 144 insertions(+), 6 deletions(-) diff --git a/src/reximages.c b/src/reximages.c index ed9f6d2..dcc40a5 100644 --- a/src/reximages.c +++ b/src/reximages.c @@ -4103,7 +4103,135 @@ const unsigned char gRex248Image[16384] = { }; /* Rex default directories image */ -const unsigned char gRexDirectories[16 * 8] = { +const unsigned char gRexDirectories[1152] = { +0x08, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4D, 0x03, 0x10, 0x81, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x53, 0x59, 0x53, 0x42, 0x41, 0x4B, 0x03, diff --git a/src/setup.cpp b/src/setup.cpp index 040d1e2..66c6481 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -63,7 +63,7 @@ double sound_get_tone_control(void); extern const unsigned char gRex148Image[16384]; extern const unsigned char gRex248Image[16384]; -extern const unsigned char gRexDirectories[16*8]; +extern const unsigned char gRexDirectories[1152]; extern const unsigned char gTsDos100Image[21352]; extern const unsigned char gTsDos200Image[21346]; @@ -1436,6 +1436,16 @@ void cb_create_flash (Fl_Widget* w, void*) return; } + // Check if the file already exists + if ((fd = fopen(mem_ctrl.pRexFlashFile->value(), "r")) != NULL) + { + // Close the file + fclose(fd); + int ret = fl_choice("Overwrite existing file?", "Yes", "No", NULL); + if (ret == 1) + return; + } + // Validate the file can be opened for write mode if ((fd = fopen(mem_ctrl.pRexFlashFile->value(), "wb")) == NULL) { @@ -1454,9 +1464,9 @@ void cb_create_flash (Fl_Widget* w, void*) { // Copy in REX MGR memcpy(pData, gRex248Image, sizeof(gRex248Image)); - memcpy(&pData[0x4400], gRexDirectories, sizeof(gRexDirectories)); + memcpy(&pData[0x4000], gRexDirectories, sizeof(gRexDirectories)); memcpy(&pData[0x8000], gRex248Image, sizeof(gRex248Image)); - memcpy(&pData[0xC400], gRexDirectories, sizeof(gRexDirectories)); + memcpy(&pData[0xC000], gRexDirectories, sizeof(gRexDirectories)); // Copy in TS-DOS memcpy(&pData[0x040000], gTsDos200Image, sizeof(gTsDos200Image)); @@ -1465,9 +1475,9 @@ void cb_create_flash (Fl_Widget* w, void*) { // Copy in REX MGR memcpy(pData, gRex148Image, sizeof(gRex148Image)); - memcpy(&pData[0x4400], gRexDirectories, sizeof(gRexDirectories)); + memcpy(&pData[0x4000], gRexDirectories, sizeof(gRexDirectories)); memcpy(&pData[0x8000], gRex148Image, sizeof(gRex148Image)); - memcpy(&pData[0xC400], gRexDirectories, sizeof(gRexDirectories)); + memcpy(&pData[0xC000], gRexDirectories, sizeof(gRexDirectories)); // Copy in TS-DOS memcpy(&pData[0x040000], gTsDos100Image, sizeof(gTsDos100Image)); From fd2dfdd78ed31017b8bd438217fac194b6ac87ac Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 15 Mar 2013 00:30:37 +0000 Subject: [PATCH 250/327] Added option to display opcode values in new disassembly format. --- src/disassemble.cpp | 120 ++++++++++++++++++++++++++++++++------------ src/disassemble.h | 2 + 2 files changed, 89 insertions(+), 33 deletions(-) diff --git a/src/disassemble.cpp b/src/disassemble.cpp index bf9ca0f..127f806 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -715,9 +715,13 @@ void disassembler_cb(Fl_Widget* w, void*) td->color(FL_BLACK); td->selection_color(FL_DARK_BLUE); td->textfont(FL_COURIER); + td->utility_margin_color(5, FL_BLACK); } else + { + td->utility_margin_color(5, FL_WHITE); td->textfont(FL_COURIER_BOLD); + } // Set the font size preference set_text_size(gpDis->m_fontSize); @@ -837,7 +841,7 @@ void VTDis::AppendComments(char* line, int opcode, int address, int oldSchool) if (oldSchool) margin = 28; else - margin = 39; + margin = 39 + (m_includeOpcodes ? 6 : 0); // Calculate # spaces to add for fixed line len (make comments line up) len = margin - strlen(line); @@ -952,6 +956,7 @@ void VTDis::Disassemble() int oldSchool = m_oldSchool; // Indicates Old school style disassembly int tricked_out; int sig_addr; + const char* pSpaces; unsigned long sig; unsigned char opcode; unsigned char op_len; @@ -979,6 +984,12 @@ void VTDis::Disassemble() m_pDisType[x].pLabel = NULL; } + // Insert either 5 spaces or zero based on if opcodes are included + if (m_includeOpcodes) + pSpaces = " "; + else + pSpaces = ""; + // Assign labels we know we need x = 0; while (m_pRom->pFuns[x].addr != -1) @@ -1027,7 +1038,7 @@ void VTDis::Disassemble() if (oldSchool) sprintf(line, "%04XH DB %02XH\n", c, m_memory[c]); else - sprintf(line, " DB %02XH\n", m_memory[c]); + sprintf(line, " %sDB %02XH\n", pSpaces, m_memory[c]); tb->append(line); rst7 = 0; continue; @@ -1039,7 +1050,7 @@ void VTDis::Disassemble() if (oldSchool) sprintf(line, "%04XH DB %02XH\n", c, m_memory[c]); else - sprintf(line, " DB %02XH\n", m_memory[c]); + sprintf(line, " %sDB %02XH\n", pSpaces, m_memory[c]); tb->append(line); rst1 = 0; continue; @@ -1085,7 +1096,7 @@ void VTDis::Disassemble() if (oldSchool) sprintf(line, "%04XH DB 80H or '%c'", next, m_memory[next] & 0x7F); else - sprintf(line, " DB 80H or '%c'", m_memory[next] & 0x7F); + sprintf(line, " %sDB 80H or '%c'", pSpaces, m_memory[next] & 0x7F); str_active = 1; if ((m_memory[next+1] & 0x80) == 0) strcat(line, ",\""); @@ -1122,7 +1133,7 @@ void VTDis::Disassemble() if (oldSchool) sprintf(line, "%04XH DB 00H\n", next); else - sprintf(line, " DB 00H\n"); + sprintf(line, " %sDB 00H\n", pSpaces); tb->append(line); line[0] = 0; continue; @@ -1151,7 +1162,7 @@ void VTDis::Disassemble() if (oldSchool) sprintf(line, "%04XH DB '%c' OR 80H", next, m_memory[next] & 0x7F); else - sprintf(line, " DB '%c' OR 80H", m_memory[next] & 0x7F); + sprintf(line, " %sDB '%c' OR 80H", pSpaces, m_memory[next] & 0x7F); if (m_pRom->pTables[x].type == TABLE_TYPE_MODIFIED_STRING2) { sprintf(arg, ", %02XH\n", m_memory[next+1]); @@ -1170,7 +1181,7 @@ void VTDis::Disassemble() if (oldSchool) sprintf(line, "%04XH DB \"%c", next, m_memory[next]); else - sprintf(line, " DB \"%c", m_memory[next]); + sprintf(line, " %sDB \"%c", pSpaces, m_memory[next]); str_active = 1; } } @@ -1222,7 +1233,7 @@ void VTDis::Disassemble() if (oldSchool) sprintf(line, "%04XH DB %02XH\n", next, m_memory[next]); else - sprintf(line, " DB %02XH\n", m_memory[next]); + sprintf(line, " %sDB %02XH\n", pSpaces, m_memory[next]); tb->append(line); } else @@ -1230,7 +1241,7 @@ void VTDis::Disassemble() if (oldSchool) sprintf(line, "%04XH DB \"%c", next, m_memory[next]); else - sprintf(line, " DB \"%c", m_memory[next]); + sprintf(line, " %sDB \"%c", pSpaces, m_memory[next]); str_active = 1; } } @@ -1260,7 +1271,7 @@ void VTDis::Disassemble() if (oldSchool) sprintf(line, "%04XH DW ", next); else - sprintf(line, " DW "); + sprintf(line, " %sDW ", pSpaces); } addr = m_memory[next] | (m_memory[next+1] << 8); @@ -1318,7 +1329,7 @@ void VTDis::Disassemble() if (oldSchool) sprintf(line, "%04XH DB \"%c%c\"\n", next, m_memory[next], m_memory[next+1]); else - sprintf(line, " DB \"%c%c\"\n", m_memory[next], m_memory[next+1]); + sprintf(line, " %sDB \"%c%c\"\n", pSpaces, m_memory[next], m_memory[next+1]); tb->append(line); } } @@ -1334,7 +1345,7 @@ void VTDis::Disassemble() sprintf(line, "%04XH DB \"%c%c%c\"\n", next, m_memory[next], m_memory[next+1], m_memory[next+2]); else - sprintf(line, " DB \"%c%c%c\"\n", m_memory[next], m_memory[next+1], + sprintf(line, " %sDB \"%c%c%c\"\n", pSpaces, m_memory[next], m_memory[next+1], m_memory[next+2]); tb->append(line); } @@ -1353,8 +1364,8 @@ void VTDis::Disassemble() sprintf(line, "%04XH DB %02XH\n%04XH DW %04XH\n", next, m_memory[next], next+1, m_memory[next+1] | (m_memory[next+2] << 8)); else - sprintf(line, " DB %02XH\n%04XH DW %04XH\n", m_memory[next], - next+1, m_memory[next+1] | (m_memory[next+2] << 8)); + sprintf(line, " %sDB %02XH\n%04XH %sDW %04XH\n", pSpaces, m_memory[next], + next+1, pSpaces, m_memory[next+1] | (m_memory[next+2] << 8)); } else { @@ -1362,8 +1373,8 @@ void VTDis::Disassemble() sprintf(line, "%04XH DB '%c'\n%04XH DW %04XH\n", next, m_memory[next], next+1, m_memory[next+1] | (m_memory[next+2] << 8)); else - sprintf(line, " DB '%c'\n%04XH DW %04XH\n", m_memory[next], - next+1, m_memory[next+1] | (m_memory[next+2] << 8)); + sprintf(line, " %sDB '%c'\n%04XH %sDW %04XH\n", pSpaces, m_memory[next], + next+1, pSpaces, m_memory[next+1] | (m_memory[next+2] << 8)); } tb->append(line); } @@ -1380,14 +1391,14 @@ void VTDis::Disassemble() sprintf(line, "%04XH DB \"%c%c%c%c\"\n", next, m_memory[next], m_memory[next+1], m_memory[next+2], m_memory[next+3]); else - sprintf(line, " DB \"%c%c%c%c\"\n", m_memory[next], + sprintf(line, " %sDB \"%c%c%c%c\"\n", pSpaces, m_memory[next], m_memory[next+1], m_memory[next+2], m_memory[next+3]); tb->append(line); if (oldSchool) sprintf(line, "%04XH DW %04XH\n", next+4, m_memory[next+4] | (m_memory[next+5] << 8)); else - sprintf(line, " DW %04XH\n", m_memory[next+4] | + sprintf(line, " %sDW %04XH\n", pSpaces, m_memory[next+4] | (m_memory[next+5] << 8)); tb->append(line); } @@ -1402,13 +1413,13 @@ void VTDis::Disassemble() if (oldSchool) sprintf(line, "%04XH DB %02XH\n", next, m_memory[next]); else - sprintf(line, " DB %02XH\n", m_memory[next]); + sprintf(line, " %sDB %02XH\n", pSpaces, m_memory[next]); tb->append(line); if (oldSchool) sprintf(line, "%04XH DW %04XH\n", next+1, m_memory[next+1] | (m_memory[next+2] << 8)); else - sprintf(line, " DW %04XH\n", m_memory[next+1] | + sprintf(line, " %sDW %04XH\n", pSpaces, m_memory[next+1] | (m_memory[next+2] << 8)); tb->append(line); @@ -1419,7 +1430,7 @@ void VTDis::Disassemble() m_memory[next+4], m_memory[next+5], m_memory[next+6], m_memory[next+7], m_memory[next+8], m_memory[next+9], m_memory[next+10]); else - sprintf(line, " DB %02XH,\"%c%c%c%c%c%c\",%02XH\n", m_memory[next+3], + sprintf(line, " %sDB %02XH,\"%c%c%c%c%c%c\",%02XH\n", pSpaces, m_memory[next+3], m_memory[next+4], m_memory[next+5], m_memory[next+6], m_memory[next+7], m_memory[next+8], m_memory[next+9], m_memory[next+10]); } @@ -1430,7 +1441,7 @@ void VTDis::Disassemble() m_memory[next+4], m_memory[next+5], m_memory[next+6], m_memory[next+7], m_memory[next+8], m_memory[next+9], m_memory[next+10]); else - sprintf(line, " DB \"%c%c%c%c%c%c%c\",%02XH\n", m_memory[next+3], + sprintf(line, " %sDB \"%c%c%c%c%c%c%c\",%02XH\n", pSpaces, m_memory[next+3], m_memory[next+4], m_memory[next+5], m_memory[next+6], m_memory[next+7], m_memory[next+8], m_memory[next+9], m_memory[next+10]); } @@ -1451,7 +1462,7 @@ void VTDis::Disassemble() if (oldSchool) sprintf(line, "%04XH DB ", next); else - sprintf(line, " DB "); + sprintf(line, " %sDB ", pSpaces); } sprintf(arg, "%02XH", m_memory[next]); @@ -1532,7 +1543,10 @@ void VTDis::Disassemble() } else { - strcpy(line, " "); + if (m_includeOpcodes) + sprintf(line, " (%02XH) ", opcode); + else + strcpy(line, " "); // Print the opcode text to the temp line buffer const char* ptr = gStrTable[opcode]; @@ -1548,7 +1562,7 @@ void VTDis::Disassemble() tricked_out = TRUE; // Disassemble it as a DB instead - sprintf(line, " DB %02XH", opcode); + sprintf(line, " %sDB %02XH", pSpaces, opcode); strcat(line, " ; Tricked out "); } } @@ -1562,7 +1576,7 @@ void VTDis::Disassemble() else line[y++] = *ptr++; } - while (y < 11) + while (y < 11 + (m_includeOpcodes ? 6 : 0)) line[y++] = ' '; while (*ptr != '\0') line[y++] = *ptr++; @@ -1683,9 +1697,13 @@ void VTDis::ResetHilight(void) m_pTd->color(FL_BLACK); m_pTd->selection_color(FL_DARK_BLUE); m_pTd->textfont(FL_COURIER); + m_pTd->utility_margin_color(5, FL_BLACK); } else + { + m_pTd->utility_margin_color(5, FL_WHITE); m_pTd->textfont(FL_COURIER_BOLD); + } m_pTd->textsize(m_fontSize); } @@ -1781,7 +1799,7 @@ void VTDis::DisassembleAddLabel(Fl_Text_Buffer* tb, int addr) if (!m_oldSchool) { sprintf(arg, "%s:", gDisStrings[m_pDisType[addr].idx].pLabel); - sprintf(line, "%-39s; %04XH\n", arg, addr); + sprintf(line, "%-39s%s; %04XH\n", arg, m_includeOpcodes ? " " : "", addr); tb->append(line); } } @@ -1806,6 +1824,12 @@ void VTDis::DisassembleAsString(Fl_Text_Buffer* tb, int startAddr, int len) int quote_active = 0; char line[200]; char arg[60]; + const char* pSpaces; + + if (m_includeOpcodes) + pSpaces = " "; + else + pSpaces = ""; for (next = startAddr; next < last; next++) { @@ -1834,7 +1858,7 @@ void VTDis::DisassembleAsString(Fl_Text_Buffer* tb, int startAddr, int len) if (m_oldSchool) sprintf(line, "%04XH DB 00H\n", next); else - sprintf(line, " DB 00H\n"); + sprintf(line, " %sDB 00H\n", pSpaces); tb->append(line); line[0]=0; } @@ -1845,14 +1869,14 @@ void VTDis::DisassembleAsString(Fl_Text_Buffer* tb, int startAddr, int len) if (m_oldSchool) sprintf(line, "%04XH DB %02XH", next, m_memory[next]); else - sprintf(line, " DB %02XH", m_memory[next]); + sprintf(line, " %sDB %02XH", pSpaces, m_memory[next]); } else { if (m_oldSchool) sprintf(line, "%04XH DB \"%c", next, m_memory[next]); else - sprintf(line, " DB \"%c", m_memory[next]); + sprintf(line, " %sDB \"%c", pSpaces, m_memory[next]); quote_active = 1; } str_active = 1; @@ -2113,12 +2137,14 @@ void VTDis::SetEditorStyle(int blackBackground, int colorHilight, int fontSize) m_pTd->textcolor(FL_WHITE); m_pTd->color(FL_BLACK); m_pTd->textfont(FL_COURIER); + m_pTd->utility_margin_color(5, FL_BLACK); } else { m_pTd->textcolor(FL_BLACK); m_pTd->color(FL_WHITE); m_pTd->textfont(FL_COURIER_BOLD); + m_pTd->utility_margin_color(5, FL_WHITE); } m_pTd->textsize(fontSize); @@ -2153,6 +2179,7 @@ void VTDis::LoadPrefs(void) g.get("ColorHilight", m_colorHilight, 1); g.get("DisDepth", m_disassemblyDepth, 1000); g.get("OpcodesLowercase", m_opcodesLowercase, 0); + g.get("ShowOpcodes", m_includeOpcodes, 0); } /* @@ -2177,6 +2204,7 @@ void VTDis::SavePrefs(void) g.set("ColorHilight", m_colorHilight); g.set("DisDepth", m_disassemblyDepth); g.set("OpcodesLowercase", m_opcodesLowercase); + g.set("ShowOpcodes", m_includeOpcodes); } /* @@ -2334,6 +2362,24 @@ void VTDis::SaveFile(void) mw->SaveFile(rootpath); } +/* +============================================================= +draw draws the display +============================================================= +*/ +void VTDis::draw(void) +{ +#if 0 + if (m_blackBackground) + fl_color(FL_BLACK); + else + fl_color(FL_WHITE); + + fl_rectf(0, 0, w(), h()); +#endif + Fl_Double_Window::draw(); +} + /* ============================================================================ Define a local struct for the setup parameters. @@ -2347,6 +2393,7 @@ typedef struct dis_setup_params Fl_Check_Button* pOldSchool; Fl_Check_Button* pColorHilight; Fl_Check_Button* pOpcodeLowercase; + Fl_Check_Button* pIncludeOpcodes; char sDepth[20]; char sFontSize[20]; } dis_setup_params_t; @@ -2382,6 +2429,9 @@ static void cb_setupdlg_OK(Fl_Widget* w, void* pOpaque) // Get lowercase setting gpDis->m_opcodesLowercase = p->pOpcodeLowercase->value(); + // Get show opcodes setting + gpDis->m_includeOpcodes = p->pIncludeOpcodes->value(); + // Set the editor style gpDis->SetEditorStyle(blackBackground, hilight, fontSize); set_text_size(fontSize); @@ -2422,7 +2472,7 @@ void cb_setup(Fl_Widget* w, void* pOpaque) dis_setup_params_t p; /* Create a new window for the trace configuration */ - pWin = new Fl_Window(300, 200, "Disassembler Setup"); + pWin = new Fl_Window(300, 230, "Disassembler Setup"); /* Create input field for trace depth */ // b = new Fl_Box(20, 20, 100, 20, "Disassembly Depth"); @@ -2456,13 +2506,17 @@ void cb_setup(Fl_Widget* w, void* pOpaque) p.pOpcodeLowercase = new Fl_Check_Button(20, 120, 200, 20, "Make opcode lowercase"); p.pOpcodeLowercase->value(gpDis->m_opcodesLowercase); + /* Create a checkbox to include opcodes */ + p.pIncludeOpcodes = new Fl_Check_Button(20, 140, 200, 20, "Show opcode values"); + p.pIncludeOpcodes->value(gpDis->m_includeOpcodes); + // Cancel button - { Fl_Button* o = new Fl_Button(80, 160, 60, 30, "Cancel"); + { Fl_Button* o = new Fl_Button(80, 190, 60, 30, "Cancel"); o->callback((Fl_Callback*) cb_setupdlg_cancel); } // OK button - { Fl_Return_Button* o = new Fl_Return_Button(160, 160, 60, 30, "OK"); + { Fl_Return_Button* o = new Fl_Return_Button(160, 190, 60, 30, "OK"); o->callback((Fl_Callback*) cb_setupdlg_OK, &p); } diff --git a/src/disassemble.h b/src/disassemble.h index 319c9a9..2d0ee0e 100644 --- a/src/disassemble.h +++ b/src/disassemble.h @@ -100,6 +100,7 @@ class VTDis : public Fl_Double_Window int m_colorHilight; // Set TRUE for color hilighting int m_disassemblyDepth; // Depth (in instructions) to simulate for disassembly int m_opcodesLowercase; // Creates disassembly with lower-case opcodes + int m_includeOpcodes; // Include opcode values in disassembly void Disassemble(); void SetTextViewer(class My_Text_Editor* pTextViewer); @@ -126,6 +127,7 @@ class VTDis : public Fl_Double_Window void TestForStringArg(int address); void ScanForCodeBlocks(void); void ScanForStrings(void); + virtual void draw(void); char* m_StrTable[256]; unsigned char m_LenTable[256]; From 55d7c0000712c2f647c085bd01bfa2440a94da4f Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 15 Mar 2013 00:35:54 +0000 Subject: [PATCH 251/327] Fixed divide by zero error in CPU Regs winndow associated with wwindow resize. --- src/cpuregs.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index 5fd3467..35bbc46 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -3142,6 +3142,8 @@ void VTCpuRegs::draw(void) int current_val = m_pScroll->value(); int size = (int) (m_pScroll->h() / m_fontHeight); + if (size == 0) + size = 1; if (current_val + size + 4 > m_traceAvail) current_val = m_traceAvail - size + 4; int max_size = m_traceAvail-size+4; From 760e2efd4ae2662ed572af234e7f383e64ede584 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 27 Mar 2013 04:24:53 +0000 Subject: [PATCH 252/327] Updated Makefile with -fsigned-char. --- GNUmakefile | 2 +- src/cpuregs.cpp | 18 ++++++++++-------- src/watchtable.cpp | 3 +++ 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 620642f..89882a2 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -24,7 +24,7 @@ ifeq ($(DEBUG),) OPTIMIZE = -O2 endif -CFLAGS += -I $(SRCDIR)/FLU $(OPTIMIZE) $(DEBUG) +CFLAGS += -I $(SRCDIR)/FLU $(OPTIMIZE) $(DEBUG) -fsigned-char CPPFLAGS += -I $(SRCDIR) $(OPTIMIZE) $(DEBUG) VIRTUALT = virtualt CLIENT = vt_client diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index 35bbc46..a968f14 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -421,19 +421,21 @@ void VTCpuRegs::get_reg_edits(void) // Finally get updates to the flags flags = 0; if (m_pSFlag->value()) - flags |= 0x80; + flags |= SF_BIT; if (m_pZFlag->value()) - flags |= 0x40; - if (m_pTSFlag->value()) - flags |= 0x20; + flags |= ZF_BIT; + if (m_pXFlag->value()) + flags |= XF_BIT; if (m_pACFlag->value()) - flags |= 0x10; + flags |= AC_BIT; + if (m_pTSFlag->value()) + flags |= TS_BIT; if (m_pPFlag->value()) - flags |= 0x04; + flags |= PF_BIT; if (m_pOVFlag->value()) - flags |= 0x02; + flags |= OV_BIT; if (m_pCFlag->value()) - flags |= 0x01; + flags |= CF_BIT; F = flags; diff --git a/src/watchtable.cpp b/src/watchtable.cpp index 1aac377..f9e7e8f 100644 --- a/src/watchtable.cpp +++ b/src/watchtable.cpp @@ -1131,6 +1131,9 @@ void VT_Watch_Table::resize(int x, int y, int w, int h) remaining -= m_ColWidth[c]; } + if (remaining < 10) + return; + // Now adjust cols 0 & 1 based on their percentage and remaining pixels m_ColWidth[1] = (int) (m_WidthPercentage[1] * (double) remaining); m_ColStart[1] = m_ColStart[2] - m_ColWidth[1]; From 0e554413c71e9a2e95b23efd86ee9c82286aaca2 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Thu, 24 Apr 2014 23:30:14 +0000 Subject: [PATCH 253/327] Updates to remove OSX build warnings and errors for Version 1.6 release. --- src/My_Text_Display.cpp | 1 + src/doins.c | 2 +- src/doins.h | 2 +- src/file.h | 2 +- src/memory.c | 14 +++++++------- src/setup.cpp | 1 + 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/My_Text_Display.cpp b/src/My_Text_Display.cpp index 8829382..e90a2fd 100644 --- a/src/My_Text_Display.cpp +++ b/src/My_Text_Display.cpp @@ -33,6 +33,7 @@ #include #include "My_Text_Display.h" #include +//#include #include #undef min diff --git a/src/doins.c b/src/doins.c index 67c455d..f28ead7 100644 --- a/src/doins.c +++ b/src/doins.c @@ -54,7 +54,7 @@ static char paritybits[256]={ 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, }; -#if defined(WIN32) +#if defined(WIN32) || defined(__APPLE__) void setflags(int regval, int sign, int zero, int auxcarry, int parity, int carry, int ov) #else __inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry, char ov) diff --git a/src/doins.h b/src/doins.h index bf5d694..e7cd4a0 100644 --- a/src/doins.h +++ b/src/doins.h @@ -31,7 +31,7 @@ #ifndef _DOINS_H_ #define _DOINS_H_ -#if defined(WIN32) +#if defined(WIN32) || defined(__APPLE__) void setflags(int regval, int sign, int zero, int auxcarry, int parity, int carry, int ov); #else __inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry, char ov); diff --git a/src/file.h b/src/file.h index 9d30aad..620572e 100644 --- a/src/file.h +++ b/src/file.h @@ -67,7 +67,7 @@ const char* ChooseWorkDir(); #ifdef __cplusplus extern "C" { #endif -extern char path[255]; +extern char path[512]; #ifdef __cplusplus } #endif diff --git a/src/memory.c b/src/memory.c index 958d814..295894f 100644 --- a/src/memory.c +++ b/src/memory.c @@ -196,7 +196,7 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) for (c = 0; c < count; c++) data[c] = gMsplanROM[addr++]; } - else if (gModel = MODEL_PC8300) + else if (gModel == MODEL_PC8300) { // Copy from ROM Bank B for (c = 0; c < count; c++) @@ -349,7 +349,7 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) case REGION_ROM3: addr = address; - if (gModel = MODEL_PC8300) + if (gModel == MODEL_PC8300) { // Copy from ROM Bank B for (c = 0; c < count; c++) @@ -359,7 +359,7 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) case REGION_ROM4: addr = address; - if (gModel = MODEL_PC8300) + if (gModel == MODEL_PC8300) { // Copy from ROM Bank B for (c = 0; c < count; c++) @@ -1088,7 +1088,7 @@ void save_rex2_ram(void) /* Check if file opened successfully */ if (fd != 0) { - size = 1024 * 128; /* Copy 256K of RAM + size = 1024 * 128; /* Copy 256K of RAM */ /* Write ReMem RAM first */ fwrite(gRex2Ram, 1, size, fd); @@ -1124,7 +1124,7 @@ void save_rex_flash(void) /* Check if file opened successfully */ if (fd != 0) { - size = 1024 * 1024; /* Copy 1 Meg of flash + size = 1024 * 1024; /* Copy 1 Meg of flash */ /* Write ReMem RAM first */ fwrite(gRexFlash.pFlash, 1, size, fd); @@ -1373,7 +1373,7 @@ void load_rex_flash(void) /* Check if file opened successfully */ if ((fd != 0) && (gRexFlash.pFlash != NULL)) { - size = 1024 * 1024; /* Copy 1 meg of FLASH + size = 1024 * 1024; /* Copy 1 meg of FLASH */ /* Read Rex Flash first */ readlen = fread(gRexFlash.pFlash, 1, size, fd); @@ -1413,7 +1413,7 @@ void load_rex2_ram(void) /* Check if file opened successfully */ if (fd != 0) { - size = 1024 * 128; /* Copy 128K of RAM + size = 1024 * 128; /* Copy 128K of RAM */ /* Read Rex2 RAM */ readlen = fread(gRex2Ram, 1, size, fd); diff --git a/src/setup.cpp b/src/setup.cpp index 66c6481..83f114a 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -51,6 +51,7 @@ #include "clock.h" #include "cpu.h" #include "tpddserver.h" +#include "file.h" extern Fl_Preferences virtualt_prefs; void init_menus(void); From 0f994635a1379dece6c8070f88d490d753b2a26d Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 25 Apr 2014 00:48:31 +0000 Subject: [PATCH 254/327] Updated Visual Studio project with new source files and fixed bug with FX-80 printer Character Generator that caused app to crash. --- VirtualT.suo | Bin 336896 -> 337408 bytes src/chargen.cpp | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/VirtualT.suo b/VirtualT.suo index 6ebd76867fa96ddbde8f7a76defcbe6c0d5baf3d..25e1c086173a92c27af2a2a83af3d36c0ad5787d 100644 GIT binary patch delta 92708 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 aGj2_Eb<0=Dz}V_l`r=pmFEzScwf_%J;#27W delta 86296 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 }s4XN{QStq^XByCcO3riJ4@;E<|8LDW$aTDr zP{;duUBde{9q;_aIl8XS?zkgT+FbiN9sHo?U_tbG=JhG-w=d20%JZ(0k1BjStwE>nn$eIiDYrd(PJslfvqCtAkm={&(sy9n!m`q<;(PjfU?wmo8hi z6nR35-B9V1QsgBmTtDf{Qsi$^xUSMIE;HVy-+gEFaJk=0k)NfQ?jij}iu^8xqY2w4 zMUo=mh)xP1p>q%HCDkZ?Bn^ziZ$raP{q(!3BAba!%WZB4X+-xBZYOt7<0c7Xr~lD9 z7~B!knE(l$ao|WPQ}Phs-|j8!``cHTT{rs2^lgz_jU;jYXdK;8AbP)X4;UvZ@tklc zxz8Ji34Kx3#)&tK+gtcA9FV*xH`gAF&`TTb(wjZAOSkMkI~!(d{rK)YEHEsRa{H;I zyG!Bnq&=i$1=0|XB5fL=ZkAl=-K z7lLVwIX28+dfy{AE8fxmmJb#d@&U(P8PI1i66k#k!{-}rSMwly@>A{j(oLeHt_L$( zYA%gndI@0G&$zV4k5XkWeXQz*XT`r*Q}o@kV{_Avir$xTA5vd((PP>o^0-ua_KC1( z(S3!vj*35U&2g#e#Z0?8mL^Nm-euknnngW;p>{@MHddJK(KLs>}<0r4?p(wsF|;c!=Ev##IPkXm&jE8BAO)fZg@RQEA+u zQM)>mk}Wcn5e$hJKoQQ1f5b#sTElwt-; zf7#9@@g)o8ay}Z<#l|rq1CA2Ol27DN<2X;1Fkzfx-0s3G14ULFS0U_-yWF_G;;u}l zYIa8HIx(?OL+bk{{-6;;=9O#4?QboWd3-&>>J%+-NKPB%3qy~vZZKij)+(;{rm$5w z`@=RrM(<9hc9XSwOOdqGU!Rg|Ee71V>n&C{8%Iz7kH+0;99Mat@b2074lb$LtF!p; zc5-nI&eaBryEgJH;4O`&ins=w!X|kiebx7qsO4iv{3sqB zvpPcFtPv}{(P$$Fh>sqvBOwjEF*yq1aSN`!lzJH9BpJ5cPG08x!+G6M{^T`lw8FPwo|zxo75uMJ2Qr@W|e~-a?kN zX`YU5?Ls2PaWXdXLcnnRrjQ^$p4bnLn3`D)Jk$8NO%=v(sdSpOCZlKjJlrb$^D9GN zahrZjH7+^U3`4nRN*N3|E8;3#FeEj&HCOq>S5-gBi9)1Mkm-k>+?bda1yejR+S7KrO0@R0 zbvw^UX_nd<+RXEb6{((id?Dpn_uCot97X1Dkk7x>@Vq`IwM*BtY8y>Q{fg5~}FjA-+Kq922wYV9QV&h1Z2FA4v zUDeTgt^3#!Vbx$fQpb%l{WaF&?osKp+BU2^wO7kq`K zrMQB`yE6Q1O_Jz5d79JUemf^MK0Bg)&-}OK;bzqsQTm;mYs53!O)UDxS#+AHlIm;c z9BA<%ZbOAh#R}u7AoegjzZDXNcd~Kpsp79|zA&X>p>gHHdkZ7ia)B7q$X^#u|NH%s z>;1$2$nNk)L6fk{w)HPZFE*JDzN_pBCT_C8NX47&41bE9;LpbSjY-q8V`nAgZL_1A ze#f}4jH4F&MwmOFRGQkA6(zpjMNW@0e?4mlRDzCCSvo#y55mJAdvNweH?^uwN4<{J zx=|OTrWd`dO9%_JINh)p^C~2I`&4*u}tD2 z9i!Wy696^9V9UCGhnQaCigi7R-$%7lxT$e1?OM5hc8fvEVq8b#_%s3Mz>d!o&`VDA ziIFv(Zd&R29F{DX;*Gx2QBve&DI8A+Q804vH;z2=fE0OMiXE-k8&bqSV0BCD2ZL8g zsazmYrAs_lZYOtk%dn)MP}C#F-QCPO3HQccQf1sIVc)Sl%jP@v2#Yd&bpaU^yV45d zM#MNa>R0zHG2S?C1)rCrRi0v;U}B~)4;BZ>^))m}`p^AOb}Nq1hScec$Q-Z9?4_Cv zP>^^_dFaO4R@N^{l^4Au3j#&xW)vi*DUVcHb(+o+%15&KCLYRYnKTaF@!8Z^dKPu& z>oShabtc@~z=hs@Fe4BJa*OOZKJ&vDO@1Ep{sqz6fnqotlZCSr1vmf$$? zX~xmi!jVDFGVZ)4Mq+rrkzdp#pk~D7xoeLO8}gk3&39@{e974agkP>1=_7?3ASGMk z_Lstuegma&JpaPsZ>V&Lv_c9;N2gMX43olfdj zJ;M6=+yb?yFD}v-E*|Te)WhH6Fx_ONSyC|YO#vS5R-LcS${(H_78d(HRaf!Wr&`iE zRn&T>*~{5Ae_)nzon6VeWJ#2_<{1^$71_!Un=Qn{e#Vj>L>nQ>KKk5Tgc}RTjXGG0 z947U4hewQNIvPj+=>#|N*Pz*<9N~Ur%56Gbig3T-+DXrrB0oqeOVJPe6UyB#Rg;CX0 zv_M)YttG83ts^axVpCUcJ!yR@OPn+~qp~S&ENvofDrKD$>zi6gTS`l$t)#7`ZKQ3b zX=$mnowQ6^E^RMm*WZrPPEvOM?JVsg?JDgi?Jn&h<-2#iq?z6Ir?<3^w6By{_Ln2T=?DSk)Ey;(X&I#xPP3O_;aMCl~yWa$*?)LNP_ z%eKSkNZo|XQ};9?xph)YXt2g0-q35ky`f`U9}K?sc8^u8SJPqDx`=n_FU9~5mQs@RO4i# zq6L3~6wjQPvP6~V%M!KF8`28tTT<-WNw-LcN#B#grKRsnhf6<_!nKxuBBlEKRO;M%KcJGh5wClT*aZQ z+$JSF3V)#UC(=>|kO?p)7tch7zTP;wc`+_un99D;ILf!)$3-sdURMjODCmD48G5n$|#a^&Am)69Ql5Yad#R=NOu{x&NzNn8~3Vl zgiX@sNqusH85mYZ$|N4Ks1=CZDqK(Q@5ZHsixdKvTr5{~l=EJbi|``--&^UZn?az1 zr2oQF$LMDMM^-wL8UFR9j=4xvF8|$?j?wgle|f2+PW&HQ={PJ(es00PveZ%LH7gyf zx35j5iZcJps~w|wQ*qg1$ISooYDdi$ubV5mxy6pkNYvy1YpWe~uD@ICm{GYMCh~u4 zwIf-ED)k`h3rXe}0Z8OnVO0%@6OE%ke3BVnY#g31G43+sL?zY;z1 z3E6K?OqH)*A9ms+ONYCPKj?!z`W{ujt8=)%T&OSo6uZnG$#$;K6G7K$Pu0ow9-fg) z=rq#L3L_sG2mhmRk=&n*p}Lu)Y#mvWS_;4woxne zp!a`&?hSVSCkpi1WcAkjQ)9z|;A4fjBkpIe{G1WkIUi=ctwCyc_tV3v$@yQ%_N%yU zW7$6DZ68tmK9R+@af_j{xK$^6B$c19&m{fbC&2!XA+D)crCNkrR{Zfvx3W%NtIPxi zMsEW-SL##pJYh28O5=D?TO~yaisGp!VH34VBA3ABZQG`j-!*A+Z7+)Pd23GSmQo>D_K%{gZbq!Qv*rq zYUAi|+~^L?v)L1WGg@r4Q7(u5Bt5v#b)2sFmoYmg=XDhKLyTiSUa7dP#>q(p>iSj4 zP01y#;aH(gOp8-m`Tq*6h;iMj0Y>qaFE^T&&^#Y#jR) z!<9>!I*HtG9FGA^okX6EanBj|hH>26H;waDm_#7WVU6|)UFNe`)?-sm@Q5fyD0 zjLVvQ?08OTDU7r=PES{fv^&4RZjhg(NGa%UrtI^JcW%rmZlj_WC6}u8;kEDP6~;)USt3OL;qtoNR_|h0hU&KF_$cFmI0WbH2Hy!mBWnTo&Va zV~p^w7JCZA{ld-UK44sP$|mdnN$^LFtS@|nF!Ho|-z*^(aN zixED+LySApxH27IX51;p5#XuDtu?M(+_lE>0)+73*s&h*FFxSz3Zs63(#H&Gn>PxR zoA`DFo=K}`g^>@88!!B!ao-w8#{AB>oyL(7qUJ$P0~H0r<3jvLkXvSq6qhKWtVo#c zf+3!Hm4NUSHh(318aLFq_B!sz-1m*y%`v;G7`MW>(~Zm2mFF{zDR{jX|Uui?IrCBz6y&oIGT)&`nw@V;*N5ujTQ~MTE6-OVk)~hND$^ z(d@o5j+*joVPuDKgtybUPPKD>J0)D3{z2{13j0k-s}x3-8ApS;+}*i4l^ZT!V{}*1 zmz(L+#?k3|#<7MJ@1S?(#aqd4RqRk)mh-2AXGN%%;Ndrp`t^%dh&VlDn6z(MMB;z=KmM{h8T;nb2;^HM z@%+6R?$~9hjBR$IHGUL;e0S)YWJ%qQMpcOF6uQoRk}WgLogmI6(w^L8$tdH%qlG!` zIOFyd9&dJwj3XZ|Htr9`kuIz|L44B7h*#(`H0~BV0QLpi`;Eu zIshj=BIfx-VG5-0-f%oCZm3*mc5v4T^VoJ%jJr#i#^T->_nh!BaT{XXcYHCI+u(a3 zqlJ%@0ph>$3T9tIPS!xKzsIeF%f->_@Z4x&!kcB>aAA5a$Ueq__Z23*xxSmjJ)ZCG zJS0`pmv3(o9&Pz?!W2dS*;oAVEeslwbIp!Q?^t)z#$-wHGe%7j^<1{j6(t$}O$%z! z&vg{pZdTwO!UP(s+4C3CMtF?4wlS`UFemk$j|$;DaY!Gt1Je;9JlouQW>k$2F+)DV z#YvFyW;oS2Jn^|$+Omblk&;!yl(-ef4Hll}Y8{*^i>hw=Gh}l1w)XMATDY$`->)I) zYH_q&>`(3O*dBj^xHpU&Cw!hTLSM#5^&?@z_|iCVK(~T;CDo?+0NKKp`kifT;Ye>f zK*QuVG;W0OS9X$8<3vT9X%ldJ<2nd;5JtKf$F+Agt{2Nf{fP&Oq&gmKh6Ge8jE7;y zQTW&u7a4CHc!DtYlZ^w@@gg;R$BXuz9la6X@k+Sc*9CPlY?4bfFkws)S!f)1kuX8- zXB@Td{$_Vzj629U`fY@V94?IC<;GDkj~2$gDaUn>hWU=t59C%eObh?fxZ7gf?a{ue z#rGQ3MP}>Vp@*x`J#JJVQBRo9PmL3m_)M6nd|_Of@Rx4z-Kmnyk4BLVe-cKRp5U*7 zX$pAtJFb$enQcJsV3q-PaLgQlW5NI&SII;HYF8!;z@g)X$z{CY*Y8YZI9)#~M9wfn z0^CoS9I$_kJ4%?7oE76%3y%`#j3Zf?E`eNS9QbNsF636@ILBSJlnn`RU5tEO818A~ zxDuu`a3#+h$CbP#OtS^Q z7`IJ$sJI=*jTinv7)h!JPh=1tBS_UcF|MaD7v8ImRYN54c#-7H2{FS%g=qy3GcGM0 z3L|{@*q>y%Fi*5c8%L|g2a%DiairkI#{Fhobp2b6+%DI@bkRF|E3@BO0qr91-&+CQ zY8=7;Zg$&^8zXLqFj6;`4VhO&T2gq4HgDY9)FK~An5N^eh3PsNGDQatytgoolHX5x zZ{cz7x>TyHdfR)cuK9WA%HV!J?^4qBM!}1vmq;m`6wFJdmr3uFUM{^t`moe3|1?z| zJ^;Gn(^RL-T|#$D?~&dsrCe4^ACfXn=u_Qb+z0jhDdQfIyI%UJ^fBX}ko%!p3{9n#z(dDtbEDC&^<&|IeB$RYci26thQVRk_YRujE;ut;=(a2kYX>*FmmUuf z&sKFg(rtP?47KKM#X-S9*CQ{lVfMUrg+Yg!omhjJ*;NPkcZyO&_opYrLbtwCa!9b! z9r{dosC(j-aGsm=OxTXyZ~H`Fr>Rr3SzLSf(70f%_88Y*X=Uqn=u;ZgNr~5W8K)}0 zjg|77cQxY-Pms%=6YQ7Cb`wWSWwLXSu6?TE?GQ0>3sPEwv_MB)m5>{8YuMb~lL|-d z+SPkq7!I#p5d5GMe_r!Suy!J=`|%2?>b94JW$v1~VYJ^(t+k>~Q+URw>xJd{-|44b zfJW;9HIK9)8qrB=R&Kp8nw6X1SRSsbU%jsT$t^- ztX5(44%hwIDxAy&Vz<0?IJqGBQvSBq_^bY*b=V>-3U%TC6tNIF=$x77XGF5GYAETP%beWd$J=Sb&D=Sk;F z7f2UM7fBaO_ml1~{e$!X=@RJU6_6@=_<7dFg0UkCQnLcCtV(QZY4INLS+J!q=(b*%oW$$hH-z-Z-3@l^dH0ZXOR zT(|F1&DxV478y-1{X}V{^d#fxS}kS*Yf0Zzjl%b7QshD@AtEcK1ecY<(Jj6>``yY$ znX833vR29wPIRx7)@hv-uCw%7DY9M)hde69?~_tE@N-hSSI-O6JBP%%cV3hlMz$ zax0A^4F_^iGAqZGL_cQh2Oj2_VJG3anrl!iXjy-SaUI2-BJ5tcBxv66d}GIp^~+5C z6j4zuDUCv8d4~Q+Qw0B%``~T#(Dsz^oRxArN-k4Kv4vw5c00Lm8x;{W*XO1csvIr`x?isnq%A|9sojHCN0QS84SskcTW8#ZX4g*K zL&iOxv>s?$IVjFVY{59>m|V;pzpZxE6njngF9 z>K#48t+n%hf5p5@Vu>2J^R_% zuvx3@_kZdW+>qNRQy&U!o~^p3B3sp6pHO`vEaH2HU9*Q=-X^b`!qK*=lajOD`WM5d zQRimDi`us1?*YLAlLz!`+c73C_gK^Z4orDoT z=uX^ul}_%De^Pg-+3}{Fb0CbM>ol2Yw|hwX-%HJKdCbu7e9urhc4WU}&CU<6i;7;q z6Yo>Zj+=X`*)jC){hn>y%7{BSHxXi$kl^@M6 zsXO2kI3-MY`NmO{3&LoUh~`zq3|WeaVH@L!cU#vW)XoDu!weCP_;>qY-tFUMU-L3d zc&^zUW*l~hn;oO?#A~?pD6=~wW_PC9oogJe(fND}74f6#VBYC-V!x=7;(wbs)nb@g`BMRqg8-Hl{0ySEwsvr%`y?v6+>!d@zuQFS6i z!!|P8>+G^TLOIl(`?Ee1bb}ql10&;1K>ACJdtR8P{6*u)myD((-x>$z-9BObY8;qX z`0eB-)oCUIaExh>k!#34*JNjLo2MCiXD`MO@VInxuIBKw7 z!U$i8_Te2NOn80-9efV2-x~{@Z-$UJ3KQT>G46h08psEXqk27F81duk;Ah1V#!F@g z{z15d+#h4yR$(fIZ5bo!5xgRd_~CXi!{`LUGG(8HY2h~Fw1#mPH%6F9kBxEr3Nv0b z$2d~1o-lHNaT%^^iIImHnHG11aeOS26VsVJ&Nx5ZK0(~6#$9N3q7o~GiM0Q~BvmJ4 z@W_>BS0Q{=ft7J45pWX7JIwGQ;|S;lVUF<)TkIHIdf4nBrDa3%jzfCQKDROM;;W-BF zxlJ8CM;*t&dqcVG0P78z@z6yagZFUlrMx*n{49u0!lR9wW_BFs^K?YYZ}LT3&1m^B zxks4YIAJ#a;`|9_K5!C*;dDGRlnzJ!U`7OTQq1mTv#T!Vr`)2ob%6crfy zP!ks1llsF&KV_W!WD;NM2Y201s-rrjg`OqXx6t~TpfM&Td}GWBYl|Bpm*xDNguvHg zENN^Un8|n8vz#BhVbZq3(Yzp9Wk{sl3_BV}zU|~byF6La$G625qI_G-ygcuf_3)g- z&(R~U`j};P^K-&6LFw!|8iJATE1e^qE1f5uFI^zrQN7~aFq3o*_enK(L*EMX-HRJF z`1j-4$pP;8jT&Hkgv|N8kW0Fo3z(|M!Wp?XKSGJ@F9u! zRIB*AsW>F2)T@c)RAC}H!#G;BnZn5FawC7)Z#wn}3fKJ~MoTYp9}KfA4CyZ+(SFV>F$U|T6MxWt2@6<-sBrE4Qtoa1OM*P zFjBAGd-v(v&;4<8I7r_UJ7Q%*Iq4Qd|Us(-jX zd^MRYu3?H3yhWr%LR?kbypC*^)YMgV&{r<*Oy=$5Zr>aZaA$^j*J^v4mYit1IxdY8 zmyqsWT+yvzr&`Q*=iz&0b>*$$Bf+Yw(A}{)>>sqrMKs-8dymi998M$pGu(nV!n2(| zpwKW1Gj~bbvTNH;j8Y+6b#S5EYjZd=I&kmZd5wcyOfG*jytX>HE8JP^zF(m2&UN{n z!mIB1YPDN%bh1_SUCF6#Mg4H7yJKat`5ss3vdHe_psS?3yt`WJxf_LPVs0{y(sQL$ ziShEXu=`N#$Z=0XNnVq}spRb1+Jg1PaOKj8010au^xtJ34Og_}fSG46L^VzNEPu}q<(xKOUn8}%9zwe+J@ zWStxtrCUSc3UQ5NTx((C-o`kd!oE}Bh@Zj_?ylp|ea()#W1ukhdm6`7m3}GifMk-9 z;K{;xW&nbe=_Q?(%Fel{WoCb)=nMZr7&+27@G@b%9%tNc!pECkCT3SSFV{as6 zbj)sy*)dO#bC4_({8Kzb2L8me%+L=X&_2!)hxnlaGTUdn2WoFS^k_DT_duGTsj8)rWeCRK7`48a0o*Vc)rCrOse&VUd(+lj@1H`(@n zj4<*LrF0AZVEBPRrWi?nm{#D@k895F{>E{9nK1T88Aq}+LO=<-#JIu2e-K74H4c24 zFkxu)VArj?QJB1abBw!NnCI_%a$F|z^t^r)i`*D9{6d%~AwOzB$A#&E$ggGx{!N$@ zGgIB?nI^(Sx@nASEzGDQD{rwQ;meqjH%x#L0LT&2Kp5$39Jrq_CmCp52Vn*S5Ejzn zmz1e6ZlrPeVHO^>I5YHo1ZN0iKeNb4ZizlVerKwz5eiM zpTOP^AYivNJ8)x3#;=#4HudWz{73;DBLxVf13t7f5TNruR zxU}#i#yytfG6_gOQt*@+ib^~!Oq8EBu8Z(pbM-!QvvF}v+%x6`;X z0%D3A!m1E|b$P;^m?;KuSp&9C#;_ zia2q-+BGLB5gsY7O^n-3nD<l3y2bQ^f2y^zL^ETHH z=52A}FN{nJf8{n_q~0I&@1iO8Os&HY9Ls)&%57-ec;R1Uhcq<~%<>-+u3d~9EzGrz zF^)uBEF5LMnBBQ78KMHk1CED;e%lOUJ#wUoJ^QUiwxHQiZZwXnGVlZ5+)- zso4!M4!;A98!WdvxFgu9PeHvC2I-6sXowCF(6E@N;pXW`xw(>%J24w2)TiJ|ddT%* z^b{tH{>GIE^V$uW8nc^bc3RAmTc$=0Iok}?8{QS*ax>(087CpY6U@$ccsq)_#<+*g zPE_I%VIuRSam|FEGCTi@O;wNXnHjzoGko0)-#3l`*;p|gNHaQh z3;fHn6Jmxe<0YQ{ja(byQ^X;c$Ly{!yK9Z3Ak+ICC^u={846HJIBF@3(tyTX+M}=`bL02*#A6XkSyw(hFjv3w}jBJkCv6Pnp z|7sj<^xI}PKGyb55XNpV<4B#8g)8J%WsIaJGhGx7j$3v;LO=-!P6__NLiw zkJ;@oyHJ^%lcM#7=^!;SE<=IO*AJw(kwm7Cas7>Be0YFydm4wILBd3)!Z_;cO0yed z9L?)k<0cs=Dlxg(I;+!-eT8X{`x(dG*i)FyKG-;_ zlOe`c7#HmgIZ8ihkH>gYc!KaSxf6{WFWg!fInX#T9SS0IM9hv31+v<>&ce>PD~;Yd5z9R+#G@J6kMurGDi&3(H!+L+X~!;ZGC MW$Rk6+QRn#1HapTR{#J2 diff --git a/src/chargen.cpp b/src/chargen.cpp index efac274..4f30b58 100644 --- a/src/chargen.cpp +++ b/src/chargen.cpp @@ -78,7 +78,7 @@ void cb_CloseCharGen(Fl_Widget* w, void *) // Okay to close gpCharGen->hide(); - delete gpCharGen; +// delete gpCharGen; gpCharGen = NULL; } From 31e130737fba01d6f0df5bc91f0fa97fd484473e Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 25 Apr 2014 00:53:38 +0000 Subject: [PATCH 255/327] Added FX-80 Emulation character ROMs for Model 100 and Model 200. Also added a modified 9-pin version with smoother output on some of the characters. --- ROMs/m100-9.fcr | Bin 0 -> 3072 bytes ROMs/m100t.fcr | Bin 0 -> 3072 bytes ROMs/m200-9.fcr | Bin 0 -> 3072 bytes ROMs/m200t.fcr | Bin 0 -> 3072 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 ROMs/m100-9.fcr create mode 100644 ROMs/m100t.fcr create mode 100644 ROMs/m200-9.fcr create mode 100644 ROMs/m200t.fcr diff --git a/ROMs/m100-9.fcr b/ROMs/m100-9.fcr new file mode 100644 index 0000000000000000000000000000000000000000..8edb3631b08f5a8e8d3001c9592af6e81ae644d7 GIT binary patch literal 3072 zcmd6o!E01k6vmH_rw$<`PmwZ|Fnxq9f=CHjWf8{LFfG%PMGdyAVy7Y^!9{jT3F+w| z5=5*GwuMq?8f+2&f>Ok~@~`M36zQS`$uh_=_V=Cp#$?e|SKiBc@0;(PbM86ko_ojb zVE6&F*BKuQ^Rk}hL*&9#?JHWymjF_+g&ScW~>7queQpqZf;{> zY|1A*7;d&;9qZS)4_*k|sXbzAC38QX`gFu5Y+N81eJkUa!3OV^<&C1O9NHH;eZ2QO zc;)vJv1QWsth#BpY|Ac!JG?cof}5<{MXLdRW;@I+yA58nmC#`YckAby#kLmktHCDQ zUc&ixt-zQ~FFms}33~xs=W8Fnnu<-i&r&b*il5)xc7=&AqibpZm>-J>3o_XeDo_{{#8}}}Xzf{M$40cu=A`TwZD-FQAMI+a? z?t=G0O=KVZG-@_$Pr*(&6KUhUpKEt_Dzd><)P$wv7$sZ(O4%U>PsbEiq*M+2C=I}-hH@x62{dbw~TRZ%u4rWhdJgVOc z;c>#O)v!~gLY5z8lg2ucEruBVp$zoi?2CZP$Fx=4_tT=55Z~ zwhCH}nm-0Tw?C1gYpLJ$U^Mb(k1!OZ&vIfH?26-`IG@@>qM*m9k$3-E7rzuhbUA%^P|M|2ssL#r)s|&M$X+-*nq?cBs#*eX+8NRCtjixt~VJ z-J0~;45B!b?TzTGj3sria$funwfPIV1D?Wi72A>ilI5X41*dw#Gpbt5Pud1vT!d%# zk$rT)^jbY;CZJk86IM z4wP5zIX)6VD3q$iLYM`xH+Me4Yre@|ogK z`#VQRzDL}1!S~54i(KSidy#zJ!snQL9v;4DnlU`R64N4D^~J#mrq-Wi?;3&-*(7 literal 0 HcmV?d00001 diff --git a/ROMs/m100t.fcr b/ROMs/m100t.fcr new file mode 100644 index 0000000000000000000000000000000000000000..2c995a811118a7a82558d261710a817d0412de86 GIT binary patch literal 3072 zcmdUw&udgy6vw|EMhz0;C{kR6bUKKLxEO+qS%mR53~7)oG+0++QxPd4i|mvV!fg-< zBG!hKmQrj9whjITrHGYMq<=&gL1-y0NR}eu+0XafH_a?6bkjxeo%7!Jeeb#Fo*(z# zN!o2`7wW&p155oY_$q$}C%;PPf5pGZ5#jR|$f9&yrLrg;)p@?oYa0G1{j7$LX$pK% z8=BRy4uhqpid;f)M?I~C9r5n*O-sGXVvmm|{dqh+^qNMnLrV>;=k8Cz2Cuq?;Jt>@ zl5S~@wU@vxP2yXPt~3Sjk;~v7Z}$c85!RhXYY6<5c^g{SDtH3#t-}iGF}~l^S9%Oy z2sY213%suDc7}F5zj)SkGGl!1u+Ec+_^kR}X$5Y9u?98^?BCK|&4FjIc@J&--^H_4 zqzhib$G*=?jJuPo;HxaAtg*(3z;~l3u=PFnV(>YGCD{2dtqmT==N0XkWNw34qDo-r zFXymSp*G^VCEhm3j&a`~``ll5&U`J^R%^Ro#CC3r*+8tzcg?sBS%YvseK)8A&nfYV~`# zQL$py`REhqm+a&geU!=G!S2*MjRt!-tad8>Q}E96G8H(Bep_eg<5ANx_H`4#y;e() zSeuq=?DIGIGWKrtYR0)np~L(_6CnaOLH^$L$0uo-)u!ofa33v$`}$4rsmjl3>^G^o z4zK_{0vsF@OJDA{ro3}a>n7E{RQ$uO9i31 zHif@-Te_-eu{)mWYC5g=^rx=rH2NhK&y^Q3|DxNvA9cTm?=R^sT}y2u9%r?2wK+TU zp!qmEk3i4#6e*LJ`k`8{L3jy2Akzs>Y)9{F6YR73058~MWYXuzPv0jky+B%E@0umQ zqBY6I^FZUe6f-X2MVC9ovuD*!K2K$2PiYT+Jw*0kXPm5kha3WrQuQz5p4m>qmxl-~ zO%m%SV<*(3UIi6%=0qlkz`py$cN3k(;O)(3FiIW$p__>JMw8vRig@l;V-;^!8(Y}# z5Z@gHon);d$Cc`2VV+gJR~I>7w_~=_F(UCzS%>$p2#a~&4sl|Kf-i`qkXylBv54@M zY~N>q#@+j?zSg&#ZO>iNH>^=s_h3k#9TB4zd4Tmx$c46!4Dy1VZficON_V!_PeTM(nE^ zEBan#|ED|T<~PKCjxuwexsJ>Fld6aQD4g>NPb(@>I>f16i#+-sct@Wg2beojVgCnN z|I?V`yLuLV|GRpvNml5EpY}W<&ET{Dd96eaF#%t%eCvWuT&VbAcA%}==7efk%`vt) z;b*9eb9IUMe4{zWNxZb5AA$X!Wq)pi_o2Op>;u11`F{{Bozs^HjkwO~W5jhC(_8uw zArY7vX= zyB68zEo|<$&B4ZhkbAV0Uzr)hTknhA7EGmofZ82M@r?P~6+bvP>-*k%nT@3U3MOSf z^sBjp{Gk0oKF_k9E<50#IyH~xu}UYIc*z-~SJ+J66x$W=(S9B>_Op@v?E9Z_=6ARY lx4E4kW2UCP)On2cx+%eIG4h;qybLqO$X?ab1NKQJe*rb7`Sbt) literal 0 HcmV?d00001 diff --git a/ROMs/m200-9.fcr b/ROMs/m200-9.fcr new file mode 100644 index 0000000000000000000000000000000000000000..1a5300e2c11d0ae08825b05ed7d4d2b63d661dd0 GIT binary patch literal 3072 zcmd6p!E01k6vj^;PZ=b{L9)nV7#_hz2vQ`gSq$SNOkoNxilkkMOhrV3i|mvVriX_} z5Rni<7e!Zp6i3>%e`W6klQ&h zKE)dzG&k#5->Mo{;7;Iv9T8tE=*RKYr#V}&d4XW`t%$!2Hh8xzZ#0Y2p}o_uh+g%H z%HQi~%Vh0Y`OqHOp4|lZd8^+AFEQ@`s|NTFJD~5`V{q55g$*;fTb1uL$C|+J2Ah0` z3Fr4U18pU}^vo_L>`mBuz4qnDE^S)-3i&cG`SS-Gm$>*x3$9Xhe!K#y(hJ{3Y!z#jm|`2uk~IJzR8?TypjfaYu- z)P>7}Jcn=KMjm*oN1E$-hw|OdJo9s&e>>$H`!~hks&!rkJ2Rdz96YIKnt%_Rja=J$ z2tEcaF^<7+BWEl27VOAbNE`1}uH8K-Sq-5gCrqWl7!fM4DQm18zOa&yWz^D~O?$|w zS)(R4qIa=Bu|->^w{TVkt1C_`*u{w2N%ln!Z{%>~P2RHqoc@LNB2KDc_B7h7`Yj2s z6K1Z4Ef$ijI9g3=+bHYCFzQ1q(BG$ebdtV{dP}D&>0E(3wO1saS#_P+!X{afp_q2x za(Y9xr=4!ZsRC~aF}A>|W>wR&KNEcv{8b{}67Nk;mNHFqJ>Ka77I&At2$#+v6{Y?< zZGIbT)#^LD?N{s@`^WCt73@#gah(>Ov9A5b8GWwX$nTN=5ABU$Y)@`^>KFnV&(|E5;e{8d>|9aRJ<-#-7^P-q?|w z-NELLLV7vQo^!$VALXfTC+vH{hbDV9VJM@d(q5oKywto1hWpU|wucPWM#25F!;sCe zxr3UW=8*VH#lW7}pjZOSs!Z$hoGfhGs!^-HWjop9@HWp^DVlM{_b_xEqFpi7PX}6j zIZjs^$c88y$_&0B4~5Zusr=FCnda4r{fQfzS`YjS`4|3+)m=jA6Yz_<_Y~r1Wo74s zFYIgXP4nR{ru8+lPcD0mefTz67%-&2YwJ$ed5QZ_w;gp(em?Gt6(tf2y;vh_UuDR* z#jnCLqXq8bm)V1;tGSV9yV>qd{YE??H-9puvxVm-zFL>;*DVkG7M$`4Ph*xC<`-@QHQ ziJzwe^^2#qbS)!lTBDp^>j8g*_3ctWT4SHs()J8|9W~PP6x=I!*o?i1I#?{bY{ft2!S_P_Dqf1YPs~NdoNaz&>d`#C64ORG+GkoYwf%XcdpyJc zsOD#VlfCY(4=IYLS1_LVu&;e*`PulheDYG9o{IQCdM`~9Uuqi{^?@@+udx{A)=-~# zJ*Rm{_>`aO7c-4B;VwMlc78*c%+8Y6Hkx|wFo%3O=GGd)wE1$@GJk1bu^Tb|1;APY Aga7~l literal 0 HcmV?d00001 diff --git a/ROMs/m200t.fcr b/ROMs/m200t.fcr new file mode 100644 index 0000000000000000000000000000000000000000..36dbd6d75c4949a7cb15ce96973f63a8916eb9e4 GIT binary patch literal 3072 zcmdUw&r4ia6vt18Nsu7vRHR55hS#BlAX$iXF$MHr6v-da#gIiQEyye-$g`jCxo>b5rTg5=dGGtqJ-_d{_XWEd z;Rf3Kf=5DrZ({!6+P;e!A=3wmEZn!uB3by%miSt-7X07sjg{=4&4ZuVfi2p&O@hr5 zOJg~}HEUYe?HKPS-;B`AEjIZ`n3w+4QUNP*h#zPC9?w^bHilpMu+XuWwu|o$xM~ez zD=;n0!`I4F_q7Y!wKjMPzb&N3z;Dqzus!R6=ZIc1_ztJUzHdL-DY)(2sJr5L&o*N? zSQ?IkJ%})r$ggeZp7A3aP77UlZPrTIOtJscc5DT_fX#iR6@Q(`dQcsljri@bu1T%n zM=bfFOxN)a7I(0$nsi!B^E`!|7qQC0_QvfrWX+)1}u%jG|ZuNrSr|3}Er*q6*%-_tDb;0iK^?g_pbp&m@7tbahoF7$w}>bKDrPDxFBlj`ecgl9D2(X)~BANIW+`o3=v`!%y_8)1fwXW5Bao8j!Nf!6%&oPaLu zEu>CUj}OM4<5OL+$rm$Bb7E`utsUV@XY-gC=rL-fe%4d>N!8v#Rj|6IqnD3_T3kAs zwPn{>CW<+_%)~2n= zex+of${Cd$1MBWHz7u5Dov&z)oMWM8f7=U4y^+w3JxIF!QjchQr9Sqjl9p{-E13eb zgmr&~B2`$!E4}JHKcB~ck4$t^7F|9dAIBCPRW$NbGKniGcf~ryS5Oo>1B~$4e)jnZ zSSR)u&Ty9F->ARvUu5?HzuVwr&-P>L|Aq4t``Uhlze0_*vy$JVmUUAVEpSGw)!bLw-mFDW*Z4M7IwJ`JJE-E+v9Ipi%n(tYlIr4Be`K8C+dW&eZ} zXBo{kbcgZ{E4q9cp6VIvj2C(0@sZyYJ6@lnYp!|BtC;UUV-C3OMfDroh9nMWV#P4oZdH({3-@TC)_FYkUh{|&|~oqslnIXNrz%jHe)@j z;JciIRd)9-Soh}^x(vUERTb4F#^1%a{%aF(3s!V~m%IwjujhLaZSG-nQZ`2i{~%2t zA-*D~Lgd6gGMtmke`w6$PuCyh{88N~uY2n{S_$#xoDlggpX-kDN9~XDqn7N{IbZ)Z zsihCCt`+>%Lx9s~ V<&tx}1*gKwZ7YOh`- Date: Fri, 25 Apr 2014 01:15:57 +0000 Subject: [PATCH 256/327] Remapped lower serial.c baud rates to 57600, 115200. Modified default IDE plain text color to WHITE. --- release.txt | 2 ++ src/ide.cpp | 2 +- src/serial.c | 30 +++++++++++++++++++-- src/tpddserver.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+), 3 deletions(-) diff --git a/release.txt b/release.txt index fc6d5ff..ff8a603 100644 --- a/release.txt +++ b/release.txt @@ -66,6 +66,8 @@ v1.6 20. Added color syntax hilighting, Load and Save, and Find operations to Disassembler window. +21. Modified serial.c to map 75 baud = 57600 and 110 baud = 115200. + ==================== v1.5 July 9th, 2011 ==================== diff --git a/src/ide.cpp b/src/ide.cpp index 920d78b..65213ed 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -244,7 +244,7 @@ void get_hilight_color_prefs(void) { int pc; - virtualt_prefs.get("Ide_ColorText", pc, FL_BLACK); + virtualt_prefs.get("Ide_ColorText", pc, FL_WHITE); hl_plain = (Fl_Color) pc; virtualt_prefs.get("Ide_ColorLineComment", pc, 95); hl_linecomment = (Fl_Color) pc; diff --git a/src/serial.c b/src/serial.c index 1e12f1d..e9f5074 100644 --- a/src/serial.c +++ b/src/serial.c @@ -43,6 +43,7 @@ #include #include #include /* Error number definitions */ +#include #endif @@ -785,8 +786,9 @@ int ser_set_baud(int baud) unsigned baud_flag; switch (sp.baud_rate) { - case 75 : baud_flag = B75 ; break; - case 110 : baud_flag = B110 ; break; + /* Steal 75 baud to make it 57600 and 110 to make it 115200 */ + case 75 : baud_flag = B57600 ; break; + case 110 : baud_flag = B115200 ; break; case 150 : baud_flag = B150 ; break; case 200 : baud_flag = B200 ; break; case 300 : baud_flag = B300 ; break; @@ -797,6 +799,8 @@ int ser_set_baud(int baud) case 4800 : baud_flag = B4800 ; break; case 9600 : baud_flag = B9600 ; break; case 19200: baud_flag = B19200; break; + case 38400: baud_flag = B38400; break; + case 76800: baud_flag = B38400; break; default: return SER_IO_ERROR; } @@ -805,6 +809,28 @@ int ser_set_baud(int baud) cfsetospeed (&options, baud_flag); options.c_cflag |= (CLOCAL | CREAD); tcsetattr(sp.fd, TCSANOW, &options); + + /* For 76800 Baud, we have to try to use ioctl and + and TIOCGSERIAL / TIOCSSERIAL to set a custom baud + rate divisor and hope it's an FTDI USB device */ + if (sp.baud_rate == 76800) { + struct serial_struct ser; + + /* Get current structure values */ + if (ioctl(sp.fd, TIOCGSERIAL, &ser) < 0) { + printf("Error calling TIOCGSERIAL\n"); + } + else + { + // Calculate custom_divisor based on baud_base + ser.custom_divisor = ser.baud_base / 76800; + ser.flags |= ASYNC_SPD_CUST; + printf("Baud base = %d, Custom divisor = %d\n", ser.baud_base, ser.custom_divisor); + if (ioctl(sp.fd, TIOCSSERIAL, &ser) < 0) + printf("Error setting custom baud rate\n"); + } + } + } #endif diff --git a/src/tpddserver.cpp b/src/tpddserver.cpp index b24d773..82321d4 100644 --- a/src/tpddserver.cpp +++ b/src/tpddserver.cpp @@ -2602,15 +2602,82 @@ Handles the SetExtended opcode */ void VTTpddServer::OpcodeSetExtended(void) { + SendNormalReturn(TPDD_ERR_NONE); } /* =========================================================================== Handles the QueryExtended opcode + +The QueryExtended opcode parameter will be a NULL terminated string with +a space seperated list of extended options being queried, such as: + + NM BR CL Which is requesting Name (of server), Baud Rate and + Condensed List support + +The proper response is a RET_QUERY_EXTENDED packet that looks like: + + 0: 0x14 + 1: Length byte + 2-n: NM=NADSBox BR=9600,19200,38400,57600,76800,115200,230400 CL:Y \0 + N+1: Checksum + =========================================================================== */ void VTTpddServer::OpcodeQueryExtended(void) { + MString resp; + const char *ptr; + int len, c; + + // TPDD_RET_QUERY_EXTENDED + ptr = strtok(&m_rxBuffer[TPDD_PKT_DATA_INDEX], " "); + + // Loop for all entries in in opcode parameter list + while (ptr != NULL) + { + // Add this extended parameter to the response + resp += ptr; + + if (strcmp(ptr, "NM") == 0) + // Provide the our Server Name + resp += (char *) "=VTNADS"; + else if (strcmp(ptr, "BR") == 0) + // Provide list of virtual baud rates we support + resp += (char *) "=38400,57600,76800,115200,230400"; + else if (strcmp(ptr, "CL") == 0) + // Indicate Condensed List API supported + resp += (char *) ":Y"; + else + // Anything else we don't support so respond "N"ot supported + resp += (char *) ":N"; + + // Get pointer to next extended parameter in list + ptr = strtok(NULL, " "); + + // Add a space separator if there are more parameters in the list + if (ptr != NULL) + resp += (char *) " "; + } + + // Okay now send out the response + m_txChecksum = 0; + len = resp.GetLength() + 1; + + // Send API code + TpddSendByte(TPDD_RET_QUERY_EXTENDED); + TpddSendByte(len); + + // Send out the response dat + ptr = (const char *) resp; + for (c = 0; c < len; c++) + { + // Send to host and calc checksum + TpddSendByte(*ptr++); + } + + // Now send the checksum + TpddSendChecksum(); } /* From c3a777c6dd54fcf6e71c9505499ac4478f5303e2 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 25 Apr 2014 01:25:42 +0000 Subject: [PATCH 257/327] Updates to release notes. Fixed header error in serial.c with OSX. --- release.txt | 2 +- src/serial.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/release.txt b/release.txt index ff8a603..c11a641 100644 --- a/release.txt +++ b/release.txt @@ -6,7 +6,7 @@ VirtualT Release.txt This file lists the changes and additions for each of the versions of VirtualT since v0.3 ==================== -v1.6 +v1.6 April 24, 2014 ==================== 1. Fixed issue with remote interface simulated keystokes where the keys wouldn't diff --git a/src/serial.c b/src/serial.c index e9f5074..f1e7630 100644 --- a/src/serial.c +++ b/src/serial.c @@ -43,7 +43,9 @@ #include #include #include /* Error number definitions */ +#if !defined(__APPLE__) #include +#endif #endif From 0e13d32484363cc9f816d53d69861fcc7731aa9c Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 25 Apr 2014 01:37:02 +0000 Subject: [PATCH 258/327] Made special serial logic to enable 76,800 baud compile for Linux only (not OSX). --- src/serial.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/serial.c b/src/serial.c index f1e7630..c86bed6 100644 --- a/src/serial.c +++ b/src/serial.c @@ -815,6 +815,7 @@ int ser_set_baud(int baud) /* For 76800 Baud, we have to try to use ioctl and and TIOCGSERIAL / TIOCSSERIAL to set a custom baud rate divisor and hope it's an FTDI USB device */ +#if __linux if (sp.baud_rate == 76800) { struct serial_struct ser; @@ -832,6 +833,7 @@ int ser_set_baud(int baud) printf("Error setting custom baud rate\n"); } } +#endif } From 82a9abaf6bf6adfcb1a41ded22134b8f8bfe8242 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 25 Apr 2014 01:44:57 +0000 Subject: [PATCH 259/327] Removed window open / close animation for OSX for now since it is so slow. --- src/display.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/display.cpp b/src/display.cpp index cfc2824..2d84976 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -241,6 +241,7 @@ void collapse_window(Fl_Window* pWin) int dx, dy, dw, dh; int steps = 10, c; +#if !defined(__APPLE__) // Shrink the window to nothingness... newx = MainWin->x() + MainWin->w()/4; newy = MainWin->y() + MainWin->h()/4; @@ -256,6 +257,7 @@ void collapse_window(Fl_Window* pWin) pWin->resize(pWin->x()+dx, pWin->y()+dy, pWin->w()+dw, pWin->h()+dh); Fl::check(); } +#endif // Finally, hide the window altogether pWin->hide(); @@ -272,10 +274,13 @@ void expand_window(Fl_Window* pWin, int newx, int newy, int neww, int newh) int dx, dy, dw, dh; int c, steps = 9; +#if !defined(__APPLE__) pWin->hide(); pWin->resize(MainWin->x(), MainWin->y(), 50, 150); +#endif pWin->show(); +#if !defined(__APPLE__) dx = (newx - pWin->x()) / steps; dy = (newy - pWin->y()) / steps; dw = (neww - pWin->w()) / steps; @@ -287,6 +292,7 @@ void expand_window(Fl_Window* pWin, int newx, int newy, int neww, int newh) } pWin->resize(newx, newy, neww, newh); +#endif } /* ======================================================= From 27fec8b3647baeecaf166debe81b158ded1e1a66 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 25 Apr 2014 01:48:04 +0000 Subject: [PATCH 260/327] Updated OSX expand_window so it does a resize to place window in last known location. --- src/display.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/display.cpp b/src/display.cpp index 2d84976..1e3aa90 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -290,9 +290,9 @@ void expand_window(Fl_Window* pWin, int newx, int newy, int neww, int newh) pWin->resize(pWin->x()+dx, pWin->y()+dy, pWin->w()+dw, pWin->h()+dh); Fl::check(); } +#endif pWin->resize(newx, newy, neww, newh); -#endif } /* ======================================================= From 2ac357790ee442496601aad7b0e8e36135da2bdc Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 9 May 2014 18:27:43 +0000 Subject: [PATCH 261/327] Modifications to mitrate VirtualT to FLTK 1.3.2 and also to get the IDE working on OSX. --- GNUmakefile | 4 +- src/FLU/Flu_Tree_Browser.h | 4 + src/My_Text_Display.cpp | 158 +++++++++++++++++++------------------ src/My_Text_Display.h | 21 ++--- src/disassemble.cpp | 14 ++-- src/disassemble.h | 5 +- src/display.cpp | 4 +- src/highlight.cpp | 4 +- src/highlight.h | 6 +- src/ide.cpp | 87 +++++++++++++------- src/ide.h | 9 ++- src/idetabs.cpp | 138 ++++++++++++++++++++------------ src/idetabs.h | 4 +- src/m100emu.c | 13 ++- src/multieditwin.cpp | 7 +- src/multieditwin.h | 11 ++- src/watchtable.cpp | 2 +- 17 files changed, 296 insertions(+), 195 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 89882a2..74c841d 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -52,8 +52,8 @@ endif # ================================ # Define our linker flags and libs # ================================ -LDFLAGS += -L/usr/X11R6/lib -LIBFILES = -lstdc++ -lfltk_images -lfltk_jpeg -lfltk_png -lfltk_z -lfltk -lm -lc -lX11 -lpthread +LDFLAGS += $(shell $(FLTKCONFIG) --ldflags) -L/usr/X11R6/lib +LIBFILES = -lstdc++ -lfltk_images -lfltk_jpeg -lfltk_png -lfltk_z -lfltk -lm -lc -ldl -lX11 -lpthread -lXft -lXinerama -lfontconfig -lXext # ============================= # Defines for MacOSX builds diff --git a/src/FLU/Flu_Tree_Browser.h b/src/FLU/Flu_Tree_Browser.h index 616dc08..d6a8958 100644 --- a/src/FLU/Flu_Tree_Browser.h +++ b/src/FLU/Flu_Tree_Browser.h @@ -487,6 +487,10 @@ class FLU_EXPORT Flu_Tree_Browser : public Fl_Double_Window inline void shaded_entry_colors( Fl_Color even, Fl_Color odd ) { rdata.shadedColors[0] = even; rdata.shadedColors[1] = odd; } + //! Override show to ensure Fl_Widget::show is called + void show(void) + { Fl_Double_Window::show(); Fl_Widget::show(); } + //! Set whether branch entries are visible. Default is \c true inline void show_branches( bool b ) { rdata.showBranches = b; rdata.forceResize = true; } diff --git a/src/My_Text_Display.cpp b/src/My_Text_Display.cpp index e90a2fd..5f9183f 100644 --- a/src/My_Text_Display.cpp +++ b/src/My_Text_Display.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +//#include #include "My_Text_Display.h" #include //#include @@ -92,7 +92,7 @@ void My_Text_Display::blink_cursor(void) } My_Text_Display::My_Text_Display(int X, int Y, int W, int H, const char* l) - : Fl_Double_Window(X, Y, W, H, l) { +: Fl_Double_Window(X, Y, W, H, l) { int i; border(0); @@ -211,7 +211,7 @@ int My_Text_Display::get_line_pos(int line) /* ** Attach a text buffer to display, replacing the current buffer (if any) */ -void My_Text_Display::buffer( Fl_Text_Buffer *buf ) { +void My_Text_Display::buffer( My_Text_Buffer *buf ) { /* If the text display is already displaying a buffer, clear it off of the display and remove our callback from it */ if ( mBuffer != 0 ) { @@ -244,13 +244,13 @@ void My_Text_Display::buffer( Fl_Text_Buffer *buf ) { ** character - 'A') into fonts and colors; and a callback mechanism for ** as-needed highlighting, triggered by a style buffer entry of ** "unfinishedStyle". Style buffer can trigger additional redisplay during -** a normal buffer modification if the buffer contains a primary Fl_Text_Selection +** a normal buffer modification if the buffer contains a primary My_Text_Selection ** (see extendRangeForStyleMods for more information on this protocol). ** ** Style buffers, tables and their associated memory are managed by the caller. */ void -My_Text_Display::highlight_data(Fl_Text_Buffer *styleBuffer, +My_Text_Display::highlight_data(My_Text_Buffer *styleBuffer, const Style_Table_Entry *styleTable, int nStyles, char unfinishedStyle, Unfinished_Style_Cb unfinishedHighlightCB, @@ -471,7 +471,7 @@ void My_Text_Display::resize(int X, int Y, int W, int H) } else { text_area.x = X+LEFT_MARGIN+mLeftMargin; text_area.w = W-scrollbar_width()-LEFT_MARGIN-RIGHT_MARGIN*2-mLeftMargin-2; - mVScrollBar->resize(X+W-1-scrollbar_width(), text_area.y-TOP_MARGIN, + mVScrollBar->resize(X+W+2-scrollbar_width(), text_area.y-TOP_MARGIN, scrollbar_width(), text_area.h+TOP_MARGIN+BOTTOM_MARGIN); } } @@ -508,12 +508,12 @@ void My_Text_Display::resize(int X, int Y, int W, int H) text_area.y = Y + scrollbar_width()+TOP_MARGIN; text_area.h = H - scrollbar_width()-TOP_MARGIN-BOTTOM_MARGIN; mHScrollBar->resize(text_area.x-LEFT_MARGIN-mLeftMargin, Y, - text_area.w+LEFT_MARGIN+RIGHT_MARGIN*2+mLeftMargin, scrollbar_width()); + text_area.w+LEFT_MARGIN+RIGHT_MARGIN*4+mLeftMargin, scrollbar_width()); } else { text_area.y = Y+TOP_MARGIN; text_area.h = H - scrollbar_width()-TOP_MARGIN-BOTTOM_MARGIN; mHScrollBar->resize(text_area.x-LEFT_MARGIN-mLeftMargin, Y+H-scrollbar_width(), - text_area.w+LEFT_MARGIN+RIGHT_MARGIN*2+mLeftMargin, scrollbar_width()); + text_area.w+LEFT_MARGIN+RIGHT_MARGIN*4+mLeftMargin, scrollbar_width()); } } } @@ -567,8 +567,6 @@ void My_Text_Display::draw_text( int left, int top, int width, int height ) { lastLine = ( top + height - text_area.y ) / fontHeight + 1; fl_push_clip( left, top, width, height ); - Fl_Region r = XRectangleRegion(left, top, width, height); - fl_clip_region(r); /* draw the lines */ for ( line = firstLine; line <= lastLine; line++ ) @@ -754,7 +752,7 @@ void My_Text_Display::insert(const char* text) */ void My_Text_Display::overstrike(const char* text) { int startPos = mCursorPos; - Fl_Text_Buffer *buf = mBuffer; + My_Text_Buffer *buf = mBuffer; int lineStart = buf->line_start( startPos ); int textLen = strlen( text ); int i, p, endPos, indent, startIndent, endIndent; @@ -765,7 +763,7 @@ void My_Text_Display::overstrike(const char* text) { startIndent = mBuffer->count_displayed_characters( lineStart, startPos ); indent = startIndent; for ( c = text; *c != '\0'; c++ ) - indent += Fl_Text_Buffer::character_width( *c, indent, buf->tab_distance(), buf->null_substitution_character() ); + indent += My_Text_Buffer::character_width( *c, indent, buf->tab_distance(), buf->null_substitution_character() ); endIndent = indent; /* find which characters to remove, and if necessary generate additional @@ -777,14 +775,14 @@ void My_Text_Display::overstrike(const char* text) { ch = buf->character( p ); if ( ch == '\n' ) break; - indent += Fl_Text_Buffer::character_width( ch, indent, buf->tab_distance(), buf->null_substitution_character() ); + indent += My_Text_Buffer::character_width( ch, indent, buf->tab_distance(), buf->null_substitution_character() ); if ( indent == endIndent ) { p++; break; } else if ( indent > endIndent ) { if ( ch != '\t' ) { p++; - paddedText = new char [ textLen + FL_TEXT_MAX_EXP_CHAR_LEN + 1 ]; + paddedText = new char [ textLen + MY_TEXT_MAX_EXP_CHAR_LEN + 1 ]; strcpy( paddedText, text ); for ( i = 0; i < indent - endIndent; i++ ) paddedText[ textLen + i ] = ' '; @@ -813,7 +811,7 @@ void My_Text_Display::overstrike(const char* text) { int My_Text_Display::position_to_xy( int pos, int* X, int* Y ) { int charIndex, lineStartPos, fontHeight, lineLen; int visLineNum, charLen, outIndex, xStep, charStyle; - char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ]; + char expandedChar[ MY_TEXT_MAX_EXP_CHAR_LEN ]; const char *lineStr; /* If position is not displayed, return false */ @@ -849,7 +847,7 @@ int My_Text_Display::position_to_xy( int pos, int* X, int* Y ) { xStep = text_area.x - mHorizOffset; outIndex = 0; for ( charIndex = 0; charIndex < lineLen && charIndex < pos - lineStartPos; charIndex++ ) { - charLen = Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar, + charLen = My_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar, mBuffer->tab_distance(), mBuffer->null_substitution_character() ); charStyle = position_style( lineStartPos, lineLen, charIndex, outIndex ); @@ -895,15 +893,16 @@ int My_Text_Display::position_to_linecol( int pos, int* lineNum, int* column ) { } /* -** Return 1 if position (X, Y) is inside of the primary Fl_Text_Selection +** Return 1 if position (X, Y) is inside of the primary My_Text_Selection */ int My_Text_Display::in_selection( int X, int Y ) { int row, column, pos = xy_to_position( X, Y, CHARACTER_POS ); - Fl_Text_Buffer *buf = mBuffer; + My_Text_Buffer *buf = mBuffer; xy_to_rowcol( X, Y, &row, &column, CHARACTER_POS ); if (range_touches_selection(buf->primary_selection(), mFirstChar, mLastChar)) column = wrapped_column(row, column); +// return buf->primary_selection()->includes(pos, buf->line_start( pos ), column); return buf->primary_selection()->includes(pos, buf->line_start( pos ), column); } @@ -1165,7 +1164,7 @@ int My_Text_Display::line_start(int pos) { ** wrapping is turned on. */ int My_Text_Display::rewind_lines(int startPos, int nLines) { - Fl_Text_Buffer *buf = buffer(); + My_Text_Buffer *buf = buffer(); int pos, lineStart, retLines, retPos, retLineStart, retLineEnd; /* If we're not wrapping, use the more efficient BufCountBackwardNLines */ @@ -1246,7 +1245,7 @@ void My_Text_Display::buffer_modified_cb( int pos, int nInserted, int nDeleted, int nRestyled, const char *deletedText, void *cbArg ) { int linesInserted, linesDeleted, startDispPos, endDispPos; My_Text_Display *textD = ( My_Text_Display * ) cbArg; - Fl_Text_Buffer *buf = textD->mBuffer; + My_Text_Buffer *buf = textD->mBuffer; int oldFirstChar = textD->mFirstChar; int scrolled, origCursorPos = textD->mCursorPos; int wrapModStart, wrapModEnd; @@ -1461,12 +1460,12 @@ int My_Text_Display::position_to_line( int pos, int *lineNum ) { */ void My_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip, int leftCharIndex, int rightCharIndex) { - Fl_Text_Buffer * buf = mBuffer; + My_Text_Buffer * buf = mBuffer; int i, X, Y, startX, charIndex, lineStartPos, lineLen, fontHeight; int stdCharWidth, charWidth, startIndex, charStyle, style; int charLen, outStartIndex, outIndex; int dispIndexOffset; - char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ], outStr[ MAX_DISP_LINE_LEN ]; + char expandedChar[ MY_TEXT_MAX_EXP_CHAR_LEN ], outStr[ MAX_DISP_LINE_LEN ]; char *outPtr; const char *lineStr; @@ -1491,7 +1490,7 @@ void My_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip, /* Space beyond the end of the line is still counted in units of characters of a standardized character width (this is done mostly because style changes based on character position can still occur in this region due - to rectangular Fl_Text_Selections). stdCharWidth must be non-zero to + to rectangular My_Text_Selections). stdCharWidth must be non-zero to prevent a potential infinite loop if X does not advance */ stdCharWidth = TMPFONTWIDTH; //mFontStruct->max_bounds.width; if ( stdCharWidth <= 0 ) { @@ -1504,11 +1503,11 @@ void My_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip, leftClip = max( text_area.x, leftClip ); rightClip = min( rightClip, text_area.x + text_area.w ); - /* Rectangular Fl_Text_Selections are based on "real" line starts (after + /* Rectangular My_Text_Selections are based on "real" line starts (after a newline or start of buffer). Calculate the difference between the last newline position and the line start we're using. Since scanning back to find a newline is expensive, only do so if there's actually a - rectangular Fl_Text_Selection which needs it */ + rectangular My_Text_Selection which needs it */ if (mContinuousWrap && (range_touches_selection(buf->primary_selection(), lineStartPos, lineStartPos + lineLen) || range_touches_selection( buf->secondary_selection(), lineStartPos, lineStartPos + lineLen) || @@ -1527,7 +1526,7 @@ void My_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip, outIndex = 0; for ( charIndex = 0; ; charIndex++ ) { charLen = charIndex >= lineLen ? 1 : - Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, + My_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar, buf->tab_distance(), buf->null_substitution_character() ); style = position_style( lineStartPos, lineLen, charIndex, outIndex + dispIndexOffset ); @@ -1552,7 +1551,7 @@ void My_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip, X = startX; for ( charIndex = startIndex; charIndex < rightCharIndex; charIndex++ ) { charLen = charIndex >= lineLen ? 1 : - Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar, + My_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar, buf->tab_distance(), buf->null_substitution_character() ); charStyle = position_style( lineStartPos, lineLen, charIndex, outIndex + dispIndexOffset ); @@ -1576,7 +1575,7 @@ void My_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip, X += charWidth; outIndex++; } - if ( outPtr - outStr + FL_TEXT_MAX_EXP_CHAR_LEN >= MAX_DISP_LINE_LEN || X >= rightClip ) + if ( outPtr - outStr + MY_TEXT_MAX_EXP_CHAR_LEN >= MAX_DISP_LINE_LEN || X >= rightClip ) break; } @@ -1627,7 +1626,7 @@ void My_Text_Display::draw_string( int style, int X, int Y, int toX, } /* Set font, color, and gc depending on style. For normal text, GCs - for normal drawing, or drawing within a Fl_Text_Selection or highlight are + for normal drawing, or drawing within a My_Text_Selection or highlight are pre-allocated and pre-configured. For syntax highlighting, GCs are configured here, on the fly. */ @@ -1685,7 +1684,7 @@ void My_Text_Display::draw_string( int style, int X, int Y, int toX, clear_rect( style, X, Y + mAscent + fs->descent, toX - x, mDescent - fs->descent); */ - /* Underline if style is secondary Fl_Text_Selection */ + /* Underline if style is secondary My_Text_Selection */ /* if (style & SECONDARY_MASK) @@ -1797,7 +1796,7 @@ void My_Text_Display::draw_cursor( int X, int Y ) { ** ** Why not just: position_style(pos)? Because style applies to blank areas ** of the window beyond the text boundaries, and because this routine must also -** decide whether a position is inside of a rectangular Fl_Text_Selection, and do +** decide whether a position is inside of a rectangular My_Text_Selection, and do ** so efficiently, without re-counting character positions from the start of the ** line. ** @@ -1806,8 +1805,8 @@ void My_Text_Display::draw_cursor( int X, int Y ) { */ int My_Text_Display::position_style( int lineStartPos, int lineLen, int lineIndex, int dispIndex ) { - Fl_Text_Buffer * buf = mBuffer; - Fl_Text_Buffer *styleBuf = mStyleBuffer; + My_Text_Buffer * buf = mBuffer; + My_Text_Buffer *styleBuf = mStyleBuffer; int pos, style = 0; if ( lineStartPos == -1 || buf == NULL ) @@ -1867,7 +1866,7 @@ int My_Text_Display::string_width( const char *string, int length, int style ) { int My_Text_Display::xy_to_position( int X, int Y, int posType ) { int charIndex, lineStart, lineLen, fontHeight; int charWidth, charLen, charStyle, visLineNum, xStep, outIndex; - char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ]; + char expandedChar[ MY_TEXT_MAX_EXP_CHAR_LEN ]; const char *lineStr; /* Find the visible line number corresponding to the Y coordinate */ @@ -1894,7 +1893,7 @@ int My_Text_Display::xy_to_position( int X, int Y, int posType ) { xStep = text_area.x - mHorizOffset; outIndex = 0; for ( charIndex = 0; charIndex < lineLen; charIndex++ ) { - charLen = Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar, + charLen = My_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar, mBuffer->tab_distance(), mBuffer->null_substitution_character() ); charStyle = position_style( lineStart, lineLen, charIndex, outIndex ); charWidth = string_width( expandedChar, charLen, charStyle ); @@ -1948,7 +1947,7 @@ void My_Text_Display::offset_line_starts( int newTopLineNum ) { int nVisLines = mNVisibleLines; int *lineStarts = mLineStarts; int i, lastLineNum; - Fl_Text_Buffer *buf = mBuffer; + My_Text_Buffer *buf = mBuffer; /* If there was no offset, nothing needs to be changed */ if ( lineDelta == 0 ) @@ -2314,7 +2313,7 @@ static int countlines( const char *string ) { int My_Text_Display::measure_vline( int visLineNum ) { int i, width = 0, len, style, lineLen = vline_length( visLineNum ); int charCount = 0, lineStartPos = mLineStarts[ visLineNum ]; - char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ]; + char expandedChar[ MY_TEXT_MAX_EXP_CHAR_LEN ]; if (lineStartPos < 0 || lineLen == 0) return 0; if ( mStyleBuffer == NULL ) { @@ -2393,7 +2392,7 @@ void My_Text_Display::find_wrap_range(const char *deletedText, int pos, int nInserted, int nDeleted, int *modRangeStart, int *modRangeEnd, int *linesInserted, int *linesDeleted) { int length, retPos, retLines, retLineStart, retLineEnd; - Fl_Text_Buffer *deletedTextBuf, *buf = buffer(); + My_Text_Buffer *deletedTextBuf, *buf = buffer(); int nVisLines = mNVisibleLines; int *lineStarts = mLineStarts; int countFrom, countTo, lineStart, adjLineStart, i; @@ -2515,7 +2514,7 @@ void My_Text_Display::find_wrap_range(const char *deletedText, int pos, } length = (pos-countFrom) + nDeleted +(countTo-(pos+nInserted)); - deletedTextBuf = new Fl_Text_Buffer(length); + deletedTextBuf = new My_Text_Buffer(length); deletedTextBuf->copy(buffer(), countFrom, pos, 0); if (nDeleted != 0) deletedTextBuf->insert(pos-countFrom, deletedText); @@ -2544,7 +2543,7 @@ void My_Text_Display::find_wrap_range(const char *deletedText, int pos, */ void My_Text_Display::measure_deleted_lines(int pos, int nDeleted) { int retPos, retLines, retLineStart, retLineEnd; - Fl_Text_Buffer *buf = buffer(); + My_Text_Buffer *buf = buffer(); int nVisLines = mNVisibleLines; int *lineStarts = mLineStarts; int countFrom, lineStart; @@ -2623,7 +2622,7 @@ void My_Text_Display::measure_deleted_lines(int pos, int nDeleted) { ** retLineStart: Start of the line where counting ended ** retLineEnd: End position of the last line traversed */ -void My_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos, +void My_Text_Display::wrapped_line_counter(My_Text_Buffer *buf, int startPos, int maxPos, int maxLines, bool startPosIsLineStart, int styleBufOffset, int *retPos, int *retLines, int *retLineStart, int *retLineEnd, bool countLastLineMissingNewLine) { @@ -2687,7 +2686,7 @@ void My_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos, colNum = 0; width = 0; } else { - colNum += Fl_Text_Buffer::character_width(c, colNum, tabDist, nullSubsChar); + colNum += My_Text_Buffer::character_width(c, colNum, tabDist, nullSubsChar); if (countPixels) width += measure_proportional_character(c, colNum, p+styleBufOffset); } @@ -2717,7 +2716,7 @@ void My_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos, } if (!foundBreak) { /* no whitespace, just break at margin */ newLineStart = max(p, lineStart+1); - colNum = Fl_Text_Buffer::character_width(c, colNum, tabDist, nullSubsChar); + colNum = My_Text_Buffer::character_width(c, colNum, tabDist, nullSubsChar); if (countPixels) width = measure_proportional_character(c, colNum, p+styleBufOffset); } @@ -2766,10 +2765,10 @@ void My_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos, */ int My_Text_Display::measure_proportional_character(char c, int colNum, int pos) { int charLen, style; - char expChar[ FL_TEXT_MAX_EXP_CHAR_LEN ]; - Fl_Text_Buffer *styleBuf = mStyleBuffer; + char expChar[ MY_TEXT_MAX_EXP_CHAR_LEN ]; + My_Text_Buffer *styleBuf = mStyleBuffer; - charLen = Fl_Text_Buffer::expand_character(c, colNum, expChar, + charLen = My_Text_Buffer::expand_character(c, colNum, expChar, buffer()->tab_distance(), buffer()->null_substitution_character()); if (styleBuf == 0) { style = 0; @@ -2843,7 +2842,7 @@ int My_Text_Display::wrap_uses_character(int lineEndPos) { ** Return true if the selection "sel" is rectangular, and touches a ** buffer position withing "rangeStart" to "rangeEnd" */ -int My_Text_Display::range_touches_selection(Fl_Text_Selection *sel, +int My_Text_Display::range_touches_selection(My_Text_Selection *sel, int rangeStart, int rangeEnd) { return sel->selected() && sel->rectangular() && sel->end() >= rangeStart && sel->start() <= rangeEnd; @@ -2855,11 +2854,11 @@ int My_Text_Display::range_touches_selection(Fl_Text_Selection *sel, ** contains auxiliary information for coloring or styling text). */ void My_Text_Display::extend_range_for_styles( int *startpos, int *endpos ) { - Fl_Text_Selection * sel = mStyleBuffer->primary_selection(); + My_Text_Selection * sel = mStyleBuffer->primary_selection(); int extended = 0; /* The peculiar protocol used here is that modifications to the style - buffer are marked by selecting them with the buffer's primary Fl_Text_Selection. + buffer are marked by selecting them with the buffer's primary My_Text_Selection. The style buffer is usually modified in response to a modify callback on the text buffer BEFORE My_Text_Display.c's modify callback, so that it can keep the style buffer in step with the text buffer. The style-update @@ -2879,7 +2878,7 @@ void My_Text_Display::extend_range_for_styles( int *startpos, int *endpos ) { } } - /* If the Fl_Text_Selection was extended due to a style change, and some of the + /* If the My_Text_Selection was extended due to a style change, and some of the fonts don't match in spacing, extend redraw area to end of line to redraw characters exposed by possible font size changes */ if ( mFixedFontWidth == -1 && extended ) @@ -2889,8 +2888,12 @@ void My_Text_Display::extend_range_for_styles( int *startpos, int *endpos ) { // The draw() method. It tries to minimize what is draw as much as possible. void My_Text_Display::draw(void) { // don't even try if there is no associated text buffer! - if (!buffer()) { draw_box(); return; } + if (!buffer()) { /*draw_box();*/ return; } +// fl_push_clip(0, 0, w(), h()); +// fl_rectf(0, 0, w(), h(), color()); +// fl_pop_clip(); + // draw the non-text, non-scrollbar areas. if (damage() & FL_DAMAGE_ALL) { // Fl_Region r = XRectangleRegion(0, 0, w(), h()); @@ -2906,21 +2909,22 @@ void My_Text_Display::draw(void) { H -= scrollbar_width(); draw_box(box(), x(), y(), w(), h(), color()); + // left margin if (bHasUtilityMargin) { - fl_rectf(text_area.x-mLeftMargin - LEFT_MARGIN-1, text_area.y-TOP_MARGIN-1, - mLeftMargin, text_area.h+TOP_MARGIN+BOTTOM_MARGIN, mUtilityMarginColor); - fl_rectf(text_area.x - LEFT_MARGIN, text_area.y-1, - LEFT_MARGIN, text_area.h+2, color()); + fl_rectf(1 /*text_area.x-mLeftMargin - LEFT_MARGIN*/, text_area.y-TOP_MARGIN-2, + mLeftMargin, text_area.h+TOP_MARGIN-BOTTOM_MARGIN+4, mUtilityMarginColor); + fl_rectf(text_area.x - LEFT_MARGIN-1, text_area.y-1, + LEFT_MARGIN+1, text_area.h+2, color()); } else fl_rectf(text_area.x-mLeftMargin, text_area.y-TOP_MARGIN, - mLeftMargin, text_area.h+TOP_MARGIN+BOTTOM_MARGIN, color()); - + mLeftMargin, text_area.h+TOP_MARGIN-BOTTOM_MARGIN, color()); + // right margin fl_rectf(text_area.x+text_area.w, text_area.y-TOP_MARGIN, - RIGHT_MARGIN + scrollbar_width(), text_area.h+TOP_MARGIN+BOTTOM_MARGIN, + RIGHT_MARGIN + scrollbar_width(), text_area.h+TOP_MARGIN+BOTTOM_MARGIN, color()); // top margin @@ -2937,27 +2941,30 @@ void My_Text_Display::draw(void) { mVScrollBar->w(), mHScrollBar->h(), FL_GRAY); - // blank the previous cursor protrusions + // blank the previous cursor protrusions fl_pop_clip(); } else if (damage() & (FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE)) { // CET - FIXME - save old cursor position instead and just draw side needed? fl_push_clip(0, 0, w(), text_area.h + scrollbar_width()); - Fl_Region r = XRectangleRegion(0, 0, w(), text_area.h + scrollbar_width()); - fl_clip_region(r); +// Fl_Region r = XRectangleRegion(0, 0, w(), text_area.h + scrollbar_width()); +// fl_clip_region(r); + + // Top margin fl_rectf(text_area.x, text_area.y-TOP_MARGIN, w(), TOP_MARGIN, color()); + if (bHasUtilityMargin) { - fl_rectf(0, text_area.y-TOP_MARGIN-1, - mLeftMargin, text_area.h+TOP_MARGIN+BOTTOM_MARGIN, mUtilityMarginColor); - fl_rectf(text_area.x - LEFT_MARGIN, text_area.y-1, - LEFT_MARGIN, text_area.h+2, color()); + fl_rectf(1 /*text_area.x-mLeftMargin - LEFT_MARGIN*/, text_area.y-TOP_MARGIN, + mLeftMargin, text_area.h+TOP_MARGIN-BOTTOM_MARGIN+2, mUtilityMarginColor); + fl_rectf(text_area.x - LEFT_MARGIN-1, text_area.y-1, + LEFT_MARGIN+1, text_area.h+2, color()); } else fl_rectf(text_area.x-mLeftMargin, text_area.y-TOP_MARGIN, - mLeftMargin, text_area.h+TOP_MARGIN+BOTTOM_MARGIN, color()); + mLeftMargin, text_area.h+TOP_MARGIN-BOTTOM_MARGIN, color()); fl_rectf(text_area.x+text_area.w, text_area.y, RIGHT_MARGIN, text_area.h, color()); fl_pop_clip(); @@ -2971,6 +2978,7 @@ void My_Text_Display::draw(void) { update_child(*mVScrollBar); update_child(*mHScrollBar); +#if 1 // draw all of the text if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_EXPOSE)) { int X, Y, W, H; @@ -2988,9 +2996,9 @@ void My_Text_Display::draw(void) { // draw some lines of text fl_push_clip(text_area.x, text_area.y, text_area.w, text_area.h); - Fl_Region r = XRectangleRegion(text_area.x, text_area.y, - text_area.w, text_area.h); - fl_clip_region(r); +// Fl_Region r = XRectangleRegion(text_area.x, text_area.y, +// text_area.w, text_area.h); +// fl_clip_region(r); draw_range(damage_range1_start, damage_range1_end); if (damage_range2_end != -1) { draw_range(damage_range2_start, damage_range2_end); @@ -2999,7 +3007,7 @@ void My_Text_Display::draw(void) { damage_range2_start = damage_range2_end = -1; fl_pop_clip(); } - +#endif // draw the text cursor if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE) && !buffer()->primary_selection()->selected() && @@ -3008,20 +3016,20 @@ void My_Text_Display::draw(void) { text_area.y, text_area.w+LEFT_MARGIN+RIGHT_MARGIN, text_area.h); - Fl_Region r = XRectangleRegion(0, 0, - w(), h()); - fl_clip_region(r); +// Fl_Region r = XRectangleRegion(0, 0, +// w(), h()); +// fl_clip_region(r); int X, Y; if (position_to_xy(mCursorPos, &X, &Y)) draw_cursor(X, Y); mCursorOldY = Y; fl_pop_clip(); - } + } } // this processes drag events due to mouse for My_Text_Display and // also drags due to cursor movement with shift held down for -// Fl_Text_Editor +// My_Text_Editor void fl_text_drag_me(int pos, My_Text_Display* d) { if (d->dragType == My_Text_Display::DRAG_CHAR) { if (pos >= d->dragPos) { diff --git a/src/My_Text_Display.h b/src/My_Text_Display.h index c8e502a..d84276d 100644 --- a/src/My_Text_Display.h +++ b/src/My_Text_Display.h @@ -33,8 +33,10 @@ #include #include #include +//#include -#include +#include "My_Text_Buffer.H" +class My_Text_Buffer; typedef void (*MyTextDisplay_ReportError_t)(int lineNo, char* file, void* opaque); @@ -77,9 +79,9 @@ class FL_EXPORT My_Text_Display: public Fl_Double_Window { ~My_Text_Display(); virtual int handle(int e); - virtual void buffer(Fl_Text_Buffer* buf); - void buffer(Fl_Text_Buffer& buf) { buffer(&buf); } - Fl_Text_Buffer* buffer() { return mBuffer; } + virtual void buffer(My_Text_Buffer* buf); + void buffer(My_Text_Buffer& buf) { buffer(&buf); } + My_Text_Buffer* buffer() { return mBuffer; } void redisplay_range(int start, int end); void scroll(int topLineNum, int horizOffset); void insert(const char* text); @@ -112,7 +114,7 @@ class FL_EXPORT My_Text_Display: public Fl_Double_Window { void register_error_report(MyTextDisplay_ReportError_t pFunc, void* pOpaque) { m_pErrorFunc = pFunc, m_pErrorOpaque = pOpaque; } - void highlight_data(Fl_Text_Buffer *styleBuffer, + void highlight_data(My_Text_Buffer *styleBuffer, const Style_Table_Entry *styleTable, int nStyles, char unfinishedStyle, Unfinished_Style_Cb unfinishedHighlightCB, @@ -143,7 +145,6 @@ class FL_EXPORT My_Text_Display: public Fl_Double_Window { void utility_margin_color(int margin_size, Fl_Color c) { bHasUtilityMargin = 1; mLeftMargin = margin_size, mUtilityMarginColor = c; resize(x(), y(), w(), h()); } - //text_area.x += margin_size; text_area.w -= margin_size; } Fl_Color mCursor_color; @@ -214,7 +215,7 @@ class FL_EXPORT My_Text_Display: public Fl_Double_Window { int nDeleted, int *modRangeStart, int *modRangeEnd, int *linesInserted, int *linesDeleted); void measure_deleted_lines(int pos, int nDeleted); - void wrapped_line_counter(Fl_Text_Buffer *buf, int startPos, int maxPos, + void wrapped_line_counter(My_Text_Buffer *buf, int startPos, int maxPos, int maxLines, bool startPosIsLineStart, int styleBufOffset, int *retPos, int *retLines, int *retLineStart, int *retLineEnd, @@ -223,7 +224,7 @@ class FL_EXPORT My_Text_Display: public Fl_Double_Window { int *nextLineStart); int measure_proportional_character(char c, int colNum, int pos); int wrap_uses_character(int lineEndPos); - int range_touches_selection(Fl_Text_Selection *sel, int rangeStart, + int range_touches_selection(My_Text_Selection *sel, int rangeStart, int rangeEnd); int damage_range1_start, damage_range1_end; @@ -242,8 +243,8 @@ class FL_EXPORT My_Text_Display: public Fl_Double_Window { int mCursorPreferredCol; /* Column for vert. cursor movement */ int mNVisibleLines; /* # of visible (displayed) lines */ int mNBufferLines; /* # of newlines in the buffer */ - Fl_Text_Buffer* mBuffer; /* Contains text to be displayed */ - Fl_Text_Buffer* mStyleBuffer; /* Optional parallel buffer containing + My_Text_Buffer* mBuffer; /* Contains text to be displayed */ + My_Text_Buffer* mStyleBuffer; /* Optional parallel buffer containing color and font information */ int mFirstChar, mLastChar; /* Buffer positions of first and last displayed character (lastChar points diff --git a/src/disassemble.cpp b/src/disassemble.cpp index 127f806..520ee5a 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -49,9 +49,9 @@ #include "disassemble.h" #include "file.h" #include "io.h" -#include "cpu.h" #include "periph.h" #include "memedit.h" +#include "cpu.h" #include "romstrings.h" #include "cpuregs.h" #include "memory.h" @@ -727,7 +727,7 @@ void disassembler_cb(Fl_Widget* w, void*) set_text_size(gpDis->m_fontSize); // Create a Text Buffer for the Text Editor to work with - Fl_Text_Buffer* tb = new Fl_Text_Buffer(); + My_Text_Buffer* tb = new My_Text_Buffer(); td->buffer(tb); // Show the Disassembling text to indicate activity @@ -960,7 +960,7 @@ void VTDis::Disassemble() unsigned long sig; unsigned char opcode; unsigned char op_len; - Fl_Text_Buffer* tb; + My_Text_Buffer* tb; // Assign the RomDescription table for the model being emulated gpDis->m_pRom = gStdRomDesc; @@ -1008,7 +1008,7 @@ void VTDis::Disassemble() for (generate = 0; generate < 2; generate++) { // Create a new text buffer - tb = new Fl_Text_Buffer; + tb = new My_Text_Buffer; for (c = m_StartAddress; c <= m_EndAddress; c++) { @@ -1661,7 +1661,7 @@ void VTDis::Disassemble() } // Display the text buffer in the text editor - Fl_Text_Buffer* old_tb = m_pTextViewer->buffer(); + My_Text_Buffer* old_tb = m_pTextViewer->buffer(); m_pTextViewer->buffer(tb); ResetHilight(); @@ -1783,7 +1783,7 @@ void VTDis::ScanForStrings(void) Adds a label to the disassembly ============================================================================ */ -void VTDis::DisassembleAddLabel(Fl_Text_Buffer* tb, int addr) +void VTDis::DisassembleAddLabel(My_Text_Buffer* tb, int addr) { char line[200]; char arg[60]; @@ -1816,7 +1816,7 @@ void VTDis::DisassembleAddLabel(Fl_Text_Buffer* tb, int addr) Disassembles the specified memory memory region as a string ============================================================================ */ -void VTDis::DisassembleAsString(Fl_Text_Buffer* tb, int startAddr, int len) +void VTDis::DisassembleAsString(My_Text_Buffer* tb, int startAddr, int len) { int next; int last = startAddr + len; diff --git a/src/disassemble.h b/src/disassemble.h index 2d0ee0e..bb577a2 100644 --- a/src/disassemble.h +++ b/src/disassemble.h @@ -40,6 +40,7 @@ #include "display.h" #include "MString.h" +#include "My_Text_Buffer.H" void disassembler_cb(Fl_Widget* w, void*); @@ -122,8 +123,8 @@ class VTDis : public Fl_Double_Window void SaveFile(void); protected: - void DisassembleAddLabel(Fl_Text_Buffer* tb, int addr); - void DisassembleAsString(Fl_Text_Buffer* tb, int addr, int size); + void DisassembleAddLabel(My_Text_Buffer* tb, int addr); + void DisassembleAsString(My_Text_Buffer* tb, int addr, int size); void TestForStringArg(int address); void ScanForCodeBlocks(void); void ScanForStrings(void); diff --git a/src/display.cpp b/src/display.cpp index 1e3aa90..c5a3be4 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -408,7 +408,7 @@ resize_window: This function resizes the main window and repositions gModel, MultFact, DisplayMode ===================================================================== */ -void resize_window() +extern "C" void resize_window() { #ifdef WIN32 int hiddenTaskBarAdjust = 0; @@ -2340,6 +2340,8 @@ void init_display(void) /* End the Window and show it */ MainWin->end(); + resize_window(); + if (!gNoGUI) MainWin->show(); diff --git a/src/highlight.cpp b/src/highlight.cpp index dfcda5f..c892d93 100644 --- a/src/highlight.cpp +++ b/src/highlight.cpp @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include "highlight.h" - +#include "multieditwin.h" //Editor colors #if 0 @@ -538,7 +538,7 @@ void style_init(HighlightCtrl_t *pHlCtrl) style[pHlCtrl->textbuf->length()] = '\0'; if (!pHlCtrl->stylebuf) - pHlCtrl->stylebuf = new Fl_Text_Buffer(pHlCtrl->textbuf->length()); + pHlCtrl->stylebuf = new My_Text_Buffer(pHlCtrl->textbuf->length()); if (pHlCtrl->cppfile) style_parse(text, style, pHlCtrl->textbuf->length()); diff --git a/src/highlight.h b/src/highlight.h index 6983033..d8686c6 100644 --- a/src/highlight.h +++ b/src/highlight.h @@ -25,9 +25,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. typedef struct _HighlightCtrl { - Fl_Text_Buffer *textbuf; - Fl_Text_Buffer *stylebuf; - Fl_Text_Buffer *op_stylebuf; + My_Text_Buffer *textbuf; + My_Text_Buffer *stylebuf; + My_Text_Buffer *op_stylebuf; My_Text_Editor *te; int cppfile; } HighlightCtrl_t; diff --git a/src/ide.cpp b/src/ide.cpp index 65213ed..3072032 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +//#include #include "FLU/Flu_Tree_Browser.h" #include "FLU/flu_pixmaps.h" #include "FLU/Flu_File_Chooser.h" @@ -549,6 +549,7 @@ void VT_Ide::SetColors(int fg, int bg) { // Set all editor background colors int children = m_EditTabs->children(); + m_TabNoBlinkBox->color(background_color); for (int c = 0; c < children; c++) { Fl_Multi_Edit_Window* te = (Fl_Multi_Edit_Window *) m_EditTabs->child(c); @@ -565,6 +566,7 @@ void VT_Ide::SetColors(int fg, int bg) } // Set Browser Tree colors + m_ProjWindow->color(background_color); m_ProjTree->connector_style(hl_plain, FL_SOLID); m_ProjTree->leaf_text(hl_plain, m_ProjTree->leaf_font(), m_ProjTree->leaf_size()); m_ProjTree->branch_text(hl_plain, m_ProjTree->branch_font(), m_ProjTree->branch_size()); @@ -797,7 +799,10 @@ void cb_lcd_display(Fl_Widget* w, void*) TAB_HEIGHT); gpIde->m_EditTabs->insert(*gpLcd, gpIde->m_EditTabs->children()); if (gpIde->m_EditTabs->children() == 1) + { gpIde->m_EditTabs->show(); + m_TabNoBlinkBox->show(); + } gpLcd->show(); gpLcd->show(); gpLcd->take_focus(); @@ -1271,10 +1276,10 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) Create region for Project tree ============================================ */ - m_ProjWindow = new Fl_Window(2,MENU_HEIGHT-2,ideTreeWidth,h-75,""); + m_ProjWindow = new Fl_Double_Window(0,MENU_HEIGHT-2,ideTreeWidth,h-75,""); m_ProjWindow->box(FL_DOWN_BOX); m_ProjWindow->color(background_color); - + // Create Tree control m_ProjTree = new Flu_Tree_Browser( 0, 0, ideTreeWidth, h-75 ); m_ProjTree->box( FL_DOWN_FRAME ); @@ -1283,6 +1288,8 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) m_ProjTree->animate(TRUE); m_ProjTree->leaf_text(hl_plain, m_ProjTree->leaf_font(), text_size); m_ProjTree->branch_text(hl_plain, m_ProjTree->branch_font(), text_size); + m_ProjTree->end(); + Fl_Window* b = new Fl_Window(40, 20, 10, 10, ""); b->hide(); gPopup = new Fl_Menu_Button(0,0,100,400,"Popup"); @@ -1292,7 +1299,8 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) gPopup->color(fl_rgb_color(240,239,228)); gPopup->hide(); b->end(); - m_ProjTree->hide(); + + m_ProjTree->hide(); m_ProjWindow->resizable(m_ProjTree); m_ProjWindow->end(); @@ -1302,16 +1310,24 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) Create region and Child Window for editing files ================================================= */ - m_EditWindow = new Fl_Window(ideTreeWidth+2,MENU_HEIGHT-2,w-(ideTreeWidth+2),h - 75,"Edit"); + m_EditWindow = new Fl_Double_Window(ideTreeWidth,MENU_HEIGHT-2,w-(ideTreeWidth),h - 75,"Edit"); m_EditWindow->box(FL_DOWN_BOX); - m_EditTabs = new Fl_Ide_Tabs(0, 0, m_EditWindow->w(), m_EditWindow->h()-1); + m_TabNoBlinkBox = new Fl_Box(20, TAB_HEIGHT, m_EditWindow->w()-22, m_EditWindow->h() - TAB_HEIGHT-1); + m_TabNoBlinkBox->box(FL_FLAT_BOX); + m_TabNoBlinkBox->color(background_color); + m_TabNoBlinkBox->hide(); + m_EditWindow->resizable(m_TabNoBlinkBox); + + m_EditTabs = new Fl_Ide_Tabs(0, 0, m_EditWindow->w(), m_EditWindow->h()); m_EditTabs->hide(); m_EditTabs->selection_color(fl_rgb_color(253, 252, 251)); m_EditTabs->has_close_button(TRUE); + m_EditTabs->color(FL_LIGHT1); + m_EditTabs->box(FL_FLAT_BOX); m_EditTabs->end(); m_EditWindow->resizable(m_EditTabs); - m_EditWindow->end(); - + m_EditWindow->end(); + /* ================================================= Create region for Debug and output tabs @@ -1321,7 +1337,6 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) m_TabWindow->box(FL_DOWN_BOX); // Create a tab control -// m_Tabs = new Fl_Tabs(0, 1, w, 75-MENU_HEIGHT); m_Tabs = new Fl_Ide_Tabs(0, 1, w, 75-MENU_HEIGHT+3); m_Tabs->selection_color(fl_rgb_color(253, 252, 251)); @@ -1344,7 +1359,7 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) m_BuildTextDisp->blink_enable(0); // Create a Text Buffer for the Text Editor to work with - m_BuildTextBuf = new Fl_Text_Buffer(); + m_BuildTextBuf = new My_Text_Buffer(); m_BuildTextDisp->buffer(m_BuildTextBuf); // Setup a callback for the text display to report errors @@ -1378,7 +1393,7 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) md->blink_enable(0); // Create a Text Buffer for the Text Editor to work with - Fl_Text_Buffer *tb = new Fl_Text_Buffer(); + My_Text_Buffer *tb = new My_Text_Buffer(); md->buffer(tb); // Show the Disassembling text to indicate activity @@ -1406,17 +1421,22 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) Fl_Tile* tile2 = new Fl_Tile(2, 0,w,75-MENU_HEIGHT-22); Fl_Box* box0 = new Fl_Box(2, 0,w/2-2,75-MENU_HEIGHT-22,"1"); + box0->box(FL_DOWN_BOX); + box0->color(background_color); + box0->labelcolor(hl_plain); + box0->labelsize(36); + box0->align(FL_ALIGN_CLIP); // Create a text display for this pane + md = new My_Text_Display(0, 0, w-3, 75-MENU_HEIGHT-22); md->box(FL_DOWN_BOX); md->textcolor(hl_plain); md->color(background_color); md->selection_color(FL_DARK_BLUE); md->blink_enable(0); - // Create a Text Buffer for the Text Editor to work with - tb = new Fl_Text_Buffer(); + tb = new My_Text_Buffer(); md->buffer(tb); // Show the Disassembling text to indicate activity @@ -1426,6 +1446,7 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) md->textsize(text_size); md->end(); + Fl_Box* box1 = new Fl_Box(w/2, 0,w/2,75-MENU_HEIGHT-22,"2"); box1->box(FL_DOWN_BOX); box1->color(background_color); @@ -1441,7 +1462,7 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) md->blink_enable(0); // Create a Text Buffer for the Text Editor to work with - tb = new Fl_Text_Buffer(); + tb = new My_Text_Buffer(); md->buffer(tb); // Show the Disassembling text to indicate activity @@ -1463,6 +1484,7 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) m_Tabs->end(); m_TabWindow->resizable(m_Tabs); + m_Tabs->value(m_BuildTab); // Create a line display box Fl_Group* g = new Fl_Group(0, 0, m_TabWindow->w(), m_TabWindow->h()); @@ -1483,7 +1505,7 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) tile->end(); resizable(m); resizable(tile); - + int ideTabHeight; virtualt_prefs.get("IdeTabheight", ideTabHeight, 75); @@ -3480,7 +3502,7 @@ Fl_Multi_Edit_Window* VT_Ide::NewEditWindow(const MString& title, const MString& int x, y, w, h; int c; Fl_Multi_Edit_Window* mw; - + // Test if this file already opened in a tab for (c = m_EditTabs->children()-1; c >= 0; c--) { @@ -3493,14 +3515,14 @@ Fl_Multi_Edit_Window* VT_Ide::NewEditWindow(const MString& title, const MString& } /* Calculate location of next window */ - x = 1; + x = 0; y = TAB_HEIGHT; - h = m_EditTabs->h() - TAB_HEIGHT; - w = m_EditTabs->w()-1; - - /* Create a group tab */ -// Fl_Group* g = new Fl_Group(x, y, w, h, (const char *) title); - + h = m_EditTabs->h() - TAB_HEIGHT+1; + w = m_EditTabs->w()-2; + + /* Create the MultiEditWin as a child of the main EditWindow */ +// m_EditTabs->begin(); + /* Now Create window */ mw = new Fl_Multi_Edit_Window(x, y, w, h, (const char *) title); @@ -3514,20 +3536,28 @@ Fl_Multi_Edit_Window* VT_Ide::NewEditWindow(const MString& title, const MString& mw->end(); // Insert new window in EditWindow - m_EditTabs->insert(*mw, m_EditTabs->children()); - m_EditTabs->resizable(m_EditTabs->child(m_EditWindow->children()-1)); + m_EditTabs->insert(*mw, m_EditTabs->children()); + m_EditTabs->resizable(mw); mw->add_status_bar(&m_StatusBar); mw->color(background_color); mw->mCursor_color = hl_plain; mw->textsize(text_size); mw->textcolor(hl_plain); + mw->box(FL_DOWN_FRAME); mw->selection_color(fl_color_average(FL_DARK_BLUE, FL_WHITE, .85f)); - mw->utility_margin_color(20, fl_rgb_color(253, 252, 251)); - mw->show(); + mw->utility_margin_color(20, fl_rgb_color(253, 252, 251)); + mw->show(); +// m_EditTabs->value(mw); + m_EditTabs->value(m_EditTabs->child(m_EditTabs->children()-1)); if (m_EditTabs->children() == 1) + { m_EditTabs->show(); - + m_TabNoBlinkBox->show(); + } + m_EditWindow->redraw(); +// m_EditTabs->redraw(); + // Call show again to bring window to front mw->take_focus(); @@ -4058,3 +4088,4 @@ VT_FindDlg::VT_FindDlg(class VT_Ide* pParent) m_pParent = pParent; } + diff --git a/src/ide.h b/src/ide.h index 79f0492..b86e816 100644 --- a/src/ide.h +++ b/src/ide.h @@ -33,6 +33,8 @@ #include #include +#include +#include #include "FLU/Flu_Combo_List.h" #include "FLU/Flu_Return_Button.h" #include "FLU/Flu_Button.h" @@ -172,8 +174,9 @@ class VT_Ide : public Fl_Window int SpliterHeight(void) { return m_ProjWindow->h(); } int SpliterWidth(void) { return m_ProjWindow->w(); } - Fl_Window* m_EditWindow; + Fl_Double_Window* m_EditWindow; Fl_Ide_Tabs* m_EditTabs; + Fl_Box* m_TabNoBlinkBox; VT_ReplaceDlg* m_pReplaceDlg; VT_FindDlg* m_pFindDlg; @@ -183,14 +186,14 @@ class VT_Ide : public Fl_Window class Fl_Multi_Edit_Window* NewEditWindow(const MString& title, const MString& file, int addToRecentFiles = TRUE); - Fl_Window* m_ProjWindow; + Fl_Double_Window* m_ProjWindow; Flu_Tree_Browser* m_ProjTree; Fl_Window* m_TabWindow; Fl_Ide_Tabs* m_Tabs; // Fl_Tabs* m_Tabs; Fl_Group* m_BuildTab; My_Text_Display* m_BuildTextDisp; - Fl_Text_Buffer* m_BuildTextBuf; + My_Text_Buffer* m_BuildTextBuf; Fl_Group* m_DebugTab; Fl_Group* m_WatchTab; Flu_Tree_Browser::Node* m_Node; diff --git a/src/idetabs.cpp b/src/idetabs.cpp index ebf51c7..3460937 100644 --- a/src/idetabs.cpp +++ b/src/idetabs.cpp @@ -43,6 +43,7 @@ #include "m100emu.h" #include "multiwin_icons.h" #include "idetabs.h" +#include "multieditwin.h" #define BORDER 3 #define EXTRASPACE 16 @@ -57,19 +58,40 @@ IMPLEMENT_DYNCREATE(Fl_Ide_Tabs, VTObject) void cb_idetabs(Fl_Widget* w, void *args) { Fl_Ide_Tabs* pTabs; + int x, count, newvalue; // Test for closure event if (args == (void *) FL_IDE_TABS_CLOSE) { // Find the widget being closed and remove it from the group pTabs = (Fl_Ide_Tabs *) w->parent(); - if (pTabs->children() == 1) - pTabs->hide(); - + count = pTabs->children(); + if (count == 1) + { + // Hide the tab control if no more tabs left +// pTabs->hide(); + + // Hide the no-blink box in the parent window also + for (x = 0; x < pTabs->parent()->children(); x++) + pTabs->parent()->child(x)->hide(); + } + + // Find the index of this entry + for (x = 0; x < count; x++) + if (w == pTabs->child(x)) + { + newvalue = x; + if (newvalue == count - 1) + newvalue--; + break; + } + pTabs->remove(w); + pTabs->last_visible_ = 0; Fl::delete_widget(w); if (pTabs->children() != 0) { + pTabs->value(pTabs->child(newvalue)); pTabs->parent()->redraw(); pTabs->redraw(); int count = pTabs->children(); @@ -87,6 +109,7 @@ Fl_Ide_Tabs::Fl_Ide_Tabs(int x, int y, int w, int h, const char* title) m_hasCloseButton = FALSE; box(FL_THIN_UP_BOX); push_ = 0; + last_visible_ = 0; callback(cb_idetabs); } @@ -104,12 +127,11 @@ void Fl_Ide_Tabs::draw() { Fl_Widget *v = value(); int H = tab_height(); -#if 0 if (damage() & FL_DAMAGE_ALL) { // redraw the entire thing: Fl_Color c = v ? v->color() : color(); - + +#if 0 draw_box(box(), x(), y()+(H>=0?H:0), w(), h()-(H>=0?H:-H), c); - if (selection_color() != c) { // Draw the top 5 lines of the tab pane in the selection color so // that the user knows which tab is selected... @@ -121,18 +143,20 @@ void Fl_Ide_Tabs::draw() { fl_pop_clip(); } +#endif if (v) draw_child(*v); } else { // redraw the child if (v) update_child(*v); } -#endif int H2 = H < 0 ? -H : H; +#if 0 // Draw the background rectangle - fl_clip(x(), y(), w(), h()+2); + fl_push_clip(x(), y(), w(), h()+2); draw_box(box(), x(), y(), w(), h()+2, fl_rgb_color(228,226,213)); - fl_pop_clip(); + fl_pop_clip(); +#endif // Draw the close box if (m_hasCloseButton) @@ -142,36 +166,33 @@ void Fl_Ide_Tabs::draw() { else m_closeRect = VT_Rect(x() + w() - H2, y() + h() - H2, H2, H2); draw_box(box(), x() + w() - H2, 0, H2, H2, selection_color()); + // Draw the 'X' in the close box + fl_color(FL_BLACK); + + int rx1 = m_closeRect.x() + 8; + int ry1 = m_closeRect.y(); + int rx2 = m_closeRect.x1() - 8; + int ry2 = m_closeRect.y1(); + + fl_line(rx1, ry1 + 7, rx2, ry2 - 9); + fl_line(rx1, ry1 + 8, rx2, ry2 - 8); + fl_line(rx1, ry1 + 9, rx2, ry2 - 7); + fl_line(rx1, ry2 - 7, rx2, ry1 + 9); + fl_line(rx1, ry2 - 8, rx2, ry1 + 8); + fl_line(rx1, ry2 - 9, rx2, ry1 + 7); } // Draw the bottom border line for the "TAB" if (H >= 0) - draw_box(box(), x()+1, H2-3, w(), H2, selection_color()); + draw_box(box(), x()+1, H2-5, w(), 7, selection_color()); else draw_box(box(), x()+1, h()-H2-4, w(), 5, selection_color()); fl_color(fl_rgb_color(127,157,184)); if (H<0) fl_line(x()+1, h()-H2, w(), h()-H2); else - fl_line(x()+1, H-4, w()-H-1, H-4); - - // Draw the 'X' in the close box - if (m_hasCloseButton) - { - fl_color(FL_BLACK); - - int rx1 = m_closeRect.x() + 8; - int ry1 = m_closeRect.y(); - int rx2 = m_closeRect.x1() - 8; - int ry2 = m_closeRect.y1(); - - fl_line(rx1, ry1 + 7, rx2, ry2 - 9); - fl_line(rx1, ry1 + 8, rx2, ry2 - 8); - fl_line(rx1, ry1 + 9, rx2, ry2 - 7); - fl_line(rx1, ry2 - 7, rx2, ry1 + 9); - fl_line(rx1, ry2 - 8, rx2, ry1 + 8); - fl_line(rx1, ry2 - 9, rx2, ry1 + 7); - } + fl_line(x()+1, H-6, w()-H-1, H-6); + // Draw the tabs if (damage() & (FL_DAMAGE_SCROLL|FL_DAMAGE_ALL)) { @@ -322,7 +343,7 @@ void Fl_Ide_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) Fl_Color oc = o->labelcolor(); fl_pop_clip(); - fl_clip(x1-H-10, y()-2, W+H+5, H+2); + fl_push_clip(x1-H-10, y()-2, W+H+5, H+2); // Draw TAB left curved portion fl_color(c); @@ -351,7 +372,6 @@ void Fl_Ide_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) o->labelcolor(oc); // Draw TAB Border -// fl_color(FL_BLACK); if (sel) fl_color(fl_rgb_color(127,157,184)); else @@ -376,7 +396,7 @@ void Fl_Ide_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) // Save the previous label color Fl_Color c = sel ? fl_lighter(selection_color()) : selection_color(); Fl_Color oc = o->labelcolor(); - fl_clip(x(), y(), w()+5, h()); + fl_push_clip(x(), y(), w()+5, h()); // Draw TAB left curved portion fl_color(c); @@ -575,12 +595,12 @@ int Fl_Ide_Tabs::orig_handle(int event) { case FL_RELEASE: o = which(Fl::event_x(), Fl::event_y()); if (event == FL_RELEASE) { - push(0); + //push(0); if (o && Fl::visible_focus() && Fl::focus()!=this) { Fl::focus(this); redraw_tabs(); } - if (o && value(o)) { + if (o) {// && value(o)) { set_changed(); do_callback(); } @@ -588,7 +608,8 @@ int Fl_Ide_Tabs::orig_handle(int event) { Fl::focus(o); Fl_Tooltip::current(o); } else { - push(o); + if (o) + push(o); } return 1; case FL_MOVE: { @@ -664,16 +685,21 @@ int Fl_Ide_Tabs::orig_handle(int event) { } int Fl_Ide_Tabs::push(Fl_Widget *o) { - if (push_ == o) return 0; - if (push_ && !push_->visible() || o && !o->visible()) + + if (last_visible_ == o) return 0; +// if ((push_ && push_->visible()) || (o && !o->visible())) { - if (push_) - push_->hide(); - if (o) - o->show(); + if (o) + { + o->show(); + } + if (last_visible_) + { + last_visible_->hide(); + } redraw_tabs(); } - push_ = o; + last_visible_ = o; return 1; } @@ -685,11 +711,24 @@ Fl_Widget* Fl_Ide_Tabs::value() { Fl_Widget* v = 0; Fl_Widget*const* a = array(); for (int i=children(); i--;) { - Fl_Widget* o = *a++; - if (v) o->hide(); - else if (o->visible()) v = o; - else if (!i) {o->show(); v = o;} - } + Fl_Widget* o = *a++; + if (v) + { + o->hide(); + } + else if (o->visible()) + { + v = o; + } +#if 0 + else if (!i) + { + o->show(); + last_visible_ = o; + v = o; + } +#endif + } return v; } @@ -702,9 +741,10 @@ int Fl_Ide_Tabs::value(Fl_Widget *newvalue) { Fl_Widget* o = *a++; if (o == newvalue) { if (!o->visible()) ret = 1; - o->show(); + o->show(); + last_visible_ = o; } else { - o->hide(); + o->hide(); } } return ret; diff --git a/src/idetabs.h b/src/idetabs.h index cae4b75..44ee4b3 100644 --- a/src/idetabs.h +++ b/src/idetabs.h @@ -31,6 +31,7 @@ #define _IDETABS_H_ #include +#include #include "vtobj.h" #define FL_IDE_TABS_CLOSE (0xDEADD00D) @@ -45,10 +46,11 @@ class Fl_Ide_Tabs : public Fl_Group, public VTObject Fl_Widget *value(); int value(Fl_Widget *); - Fl_Widget *push() const {return push_;} + Fl_Widget *push() {return last_visible_;} int push(Fl_Widget *); Fl_Widget *which(int event_x, int event_y); void has_close_button(int bHasCloseButton) { m_hasCloseButton = bHasCloseButton; } + Fl_Widget *last_visible_; protected: VT_Rect m_closeRect; diff --git a/src/m100emu.c b/src/m100emu.c index 689fbae..64b1b22 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -45,6 +45,10 @@ #include #endif +#ifdef __APPLE__ +#include +#endif + #include "VirtualT.h" #include "io.h" #include "cpu.h" @@ -322,6 +326,7 @@ count. This is used for 2.4 Mhz emulation speed. */ void throttle(int cy) { + int sleepUs = 1000 / gThrottlePeriod * 1000; /* Update cycles counter */ cycles+=cy; @@ -338,6 +343,10 @@ void throttle(int cy) #else while (cycles >= gThrottleCycles) { + if(fullspeed != 3) + usleep(sleepUs); + else + usleep(sleepUs * 2); sem_wait(&gThrottleEvent); } #if 0 @@ -1367,7 +1376,7 @@ void setup_working_path(char **argv) found = FALSE; /* Search for the /VirtualT.app/Contents directory */ - pContents = strstr(argv[0], "/VirtualT.app/Contents"); + pContents = strstr(argv[0], "/Contents/MacOS"); // First search for "/VT Emulation" folder in the same directory as the VirtualT.app if (pContents != NULL) @@ -1379,7 +1388,7 @@ void setup_working_path(char **argv) /* Save a copy of the bundle path */ strcpy(gOsxBundlePath, path); - strcat(gOsxBundlePath, "/VirtualT.app/Contents"); + strcat(gOsxBundlePath, "/Contents"); strcat(path, "/VT Emulation"); if (stat(path, &romStat) == 0) diff --git a/src/multieditwin.cpp b/src/multieditwin.cpp index 0b5e5d8..cc2583c 100644 --- a/src/multieditwin.cpp +++ b/src/multieditwin.cpp @@ -79,7 +79,6 @@ My_Text_Display::Style_Table_Entry IMPLEMENT_DYNCREATE(Fl_Multi_Edit_Window, VTObject) -//IMPLEMENT_DYNCREATE(Fl_Multi_Edit_Window, Fl_Multi_Window) void multiEditModCB(int pos, int nInserted, int nDeleted, int nRestyled, const char* deletedText, void* cbArg) @@ -115,7 +114,7 @@ void cb_multieditwin(Fl_Widget* w, void *args) // delete mw; } -void Fl_Multi_Edit_Window::buffer(Fl_Text_Buffer* buf) +void Fl_Multi_Edit_Window::buffer(My_Text_Buffer* buf) { DisableHl(); if (m_pHlCtrl != NULL) @@ -132,7 +131,7 @@ Fl_Multi_Edit_Window::Fl_Multi_Edit_Window(int x, int y, int w, int h, const cha /* Create window */ m_pHlCtrl = NULL; - m_tb = new Fl_Text_Buffer(); + m_tb = new My_Text_Buffer(); buffer(m_tb); m_tb->add_modify_callback(multiEditModCB, this); @@ -452,8 +451,10 @@ int Fl_Multi_Edit_Window::ForwardSearch(const char *pFind, int caseSensitive) return TRUE; } +#if 0 void Fl_Multi_Edit_Window::show(void) { My_Text_Display::show(); redraw(); } +#endif diff --git a/src/multieditwin.h b/src/multieditwin.h index 2083aa4..8d35fc4 100644 --- a/src/multieditwin.h +++ b/src/multieditwin.h @@ -39,7 +39,6 @@ #define TRUE 1 #endif -//class Fl_Multi_Edit_Window : public Fl_Multi_Window class Fl_Multi_Edit_Window : public My_Text_Editor, public VTObject { public: @@ -65,13 +64,13 @@ class Fl_Multi_Edit_Window : public My_Text_Editor, public VTObject void DisableHl(void); void EnableHl(void); int ForwardSearch(const char *pFind, int caseSensitive = TRUE); - virtual void show(void); - virtual void buffer(Fl_Text_Buffer* buf); - Fl_Text_Buffer* buffer() { return My_Text_Display::buffer(); } + virtual void show(void) { My_Text_Editor::show(); Fl_Widget::show(); } + virtual void buffer(My_Text_Buffer* buf); + My_Text_Buffer* buffer() { return My_Text_Display::buffer(); } -// Fl_Text_Editor* m_te; + My_Text_Editor* m_te; protected: - Fl_Text_Buffer* m_tb; + My_Text_Buffer* m_tb; HighlightCtrl_t *m_pHlCtrl; MString m_FileName; MString m_Title; diff --git a/src/watchtable.cpp b/src/watchtable.cpp index f9e7e8f..42c847c 100644 --- a/src/watchtable.cpp +++ b/src/watchtable.cpp @@ -47,8 +47,8 @@ #include "VirtualT.h" #include "memory.h" -#include "cpu.h" #include "watchtable.h" +#include "cpu.h" int str_to_i(const char *pStr); From 60e562cf83da455af984f3b4a787c5aa76881722 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 9 May 2014 19:04:52 +0000 Subject: [PATCH 262/327] Adding missing files for FLTK 1.3.2 conversion. --- src/My_Text_Buffer.H | 261 +++++ src/My_Text_Buffer.cpp | 2539 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2800 insertions(+) create mode 100644 src/My_Text_Buffer.H create mode 100644 src/My_Text_Buffer.cpp diff --git a/src/My_Text_Buffer.H b/src/My_Text_Buffer.H new file mode 100644 index 0000000..a2c4dd9 --- /dev/null +++ b/src/My_Text_Buffer.H @@ -0,0 +1,261 @@ +// +// "$Id$" +// +// Header file for My_Text_Buffer class. +// +// Copyright 2001-2005 by Bill Spitzak and others. +// Original code Copyright Mark Edel. Permission to distribute under +// the LGPL for the FLTK library granted by Mark Edel. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef MY_TEXT_BUFFER_H +#define MY_TEXT_BUFFER_H + +/* Maximum length in characters of a tab or control character expansion + of a single buffer character */ +#define MY_TEXT_MAX_EXP_CHAR_LEN 20 + +class My_Text_Selection { + friend class My_Text_Buffer; + + public: + void set(int start, int end); + void set_rectangular(int start, int end, int rectStart, int rectEnd); + void update(int pos, int nDeleted, int nInserted); + char rectangular() { return mRectangular; } + int start() { return mStart; } + int end() { return mEnd; } + int rect_start() { return mRectStart; } + int rect_end() { return mRectEnd; } + char selected() { return mSelected; } + void selected(char b) { mSelected = b; } + int includes(int pos, int lineStartPos, int dispIndex); + int position(int* start, int* end); + int position(int* start, int* end, int* isRect, int* rectStart, int* rectEnd); + + + protected: + char mSelected; + char mRectangular; + int mStart; + int mEnd; + int mRectStart; + int mRectEnd; +}; + +typedef void (*My_Text_Modify_Cb)(int pos, int nInserted, int nDeleted, + int nRestyled, const char* deletedText, + void* cbArg); +typedef void (*My_Text_Predelete_Cb)(int pos, int nDeleted, void* cbArg); + +class My_Text_Buffer { + public: + My_Text_Buffer(int requestedSize = 0); + ~My_Text_Buffer(); + + int length() { return mLength; } + char* text(); + void text(const char* text); + char* text_range(int start, int end); + char character(int pos); + char* text_in_rectangle(int start, int end, int rectStart, int rectEnd); + void insert(int pos, const char* text); + void append(const char* t) { insert(length(), t); } + void remove(int start, int end); + void replace(int start, int end, const char *text); + void copy(My_Text_Buffer* fromBuf, int fromStart, int fromEnd, int toPos); + int undo(int *cp=0); + void canUndo(char flag=1); + int insertfile(const char *file, int pos, int buflen = 128*1024); + int appendfile(const char *file, int buflen = 128*1024) + { return insertfile(file, length(), buflen); } + int loadfile(const char *file, int buflen = 128*1024) + { select(0, length()); remove_selection(); return appendfile(file, buflen); } + int outputfile(const char *file, int start, int end, int buflen = 128*1024); + int savefile(const char *file, int buflen = 128*1024) + { return outputfile(file, 0, length(), buflen); } + + void insert_column(int column, int startPos, const char* text, + int* charsInserted, int* charsDeleted); + + void replace_rectangular(int start, int end, int rectStart, int rectEnd, + const char* text); + + void overlay_rectangular(int startPos, int rectStart, int rectEnd, + const char* text, int* charsInserted, + int* charsDeleted); + + void remove_rectangular(int start, int end, int rectStart, int rectEnd); + void clear_rectangular(int start, int end, int rectStart, int rectEnd); + int tab_distance() { return mTabDist; } + void tab_distance(int tabDist); + void select(int start, int end); + int selected() { return mPrimary.selected(); } + void unselect(); + void select_rectangular(int start, int end, int rectStart, int rectEnd); + int selection_position(int* start, int* end); + + int selection_position(int* start, int* end, int* isRect, int* rectStart, + int* rectEnd); + + char* selection_text(); + void remove_selection(); + void replace_selection(const char* text); + void secondary_select(int start, int end); + int secondary_selected() { return mSecondary.selected(); } + void secondary_unselect(); + + void secondary_select_rectangular(int start, int end, int rectStart, + int rectEnd); + + int secondary_selection_position(int* start, int* end); + int secondary_selection_position(int* start, int* end, int* isRect, + int* rectStart, int* rectEnd); + + char* secondary_selection_text(); + void remove_secondary_selection(); + void replace_secondary_selection(const char* text); + void highlight(int start, int end); + int highlight() { return mHighlight.selected(); } + void unhighlight(); + void highlight_rectangular(int start, int end, int rectStart, int rectEnd); + + int highlight_position(int* start, int* end); + int highlight_position(int* start, int* end, int* isRect, int* rectStart, + int* rectEnd); + + char* highlight_text(); + void add_modify_callback(My_Text_Modify_Cb bufModifiedCB, void* cbArg); + void remove_modify_callback(My_Text_Modify_Cb bufModifiedCB, void* cbArg); + + void call_modify_callbacks() { call_modify_callbacks(0, 0, 0, 0, 0); } + + void add_predelete_callback(My_Text_Predelete_Cb bufPredelCB, void* cbArg); + void remove_predelete_callback(My_Text_Predelete_Cb predelCB, void* cbArg); + + void call_predelete_callbacks() { call_predelete_callbacks(0, 0); } + + char* line_text(int pos); + int line_start(int pos); + int line_end(int pos); + int word_start(int pos); + int word_end(int pos); + int expand_character(int pos, int indent, char *outStr); + + static int expand_character(char c, int indent, char* outStr, int tabDist, + char nullSubsChar); + + static int character_width(char c, int indent, int tabDist, char nullSubsChar); + int count_displayed_characters(int lineStartPos, int targetPos); + int skip_displayed_characters(int lineStartPos, int nChars); + int count_lines(int startPos, int endPos); + int skip_lines(int startPos, int nLines); + int rewind_lines(int startPos, int nLines); + int findchar_forward(int startPos, char searchChar, int* foundPos); + int findchar_backward(int startPos, char searchChar, int* foundPos); + int findchars_forward(int startPos, const char* searchChars, int* foundPos); + int findchars_backward(int startPos, const char* searchChars, int* foundPos); + + int search_forward(int startPos, const char* searchString, int* foundPos, + int matchCase = 0); + + int search_backward(int startPos, const char* searchString, int* foundPos, + int matchCase = 0); + + int substitute_null_characters(char* string, int length); + void unsubstitute_null_characters(char* string); + char null_substitution_character() { return mNullSubsChar; } + My_Text_Selection* primary_selection() { return &mPrimary; } + My_Text_Selection* secondary_selection() { return &mSecondary; } + My_Text_Selection* highlight_selection() { return &mHighlight; } + + protected: + void call_modify_callbacks(int pos, int nDeleted, int nInserted, + int nRestyled, const char* deletedText); + void call_predelete_callbacks(int pos, int nDeleted); + + int insert_(int pos, const char* text); + void remove_(int start, int end); + + void remove_rectangular_(int start, int end, int rectStart, int rectEnd, + int* replaceLen, int* endPos); + + void insert_column_(int column, int startPos, const char* insText, + int* nDeleted, int* nInserted, int* endPos); + + void overlay_rectangular_(int startPos, int rectStart, int rectEnd, + const char* insText, int* nDeleted, + int* nInserted, int* endPos); + + void redisplay_selection(My_Text_Selection* oldSelection, + My_Text_Selection* newSelection); + + void move_gap(int pos); + void reallocate_with_gap(int newGapStart, int newGapLen); + char* selection_text_(My_Text_Selection* sel); + void remove_selection_(My_Text_Selection* sel); + void replace_selection_(My_Text_Selection* sel, const char* text); + + void rectangular_selection_boundaries(int lineStartPos, int rectStart, + int rectEnd, int* selStart, + int* selEnd); + + void update_selections(int pos, int nDeleted, int nInserted); + + My_Text_Selection mPrimary; /* highlighted areas */ + My_Text_Selection mSecondary; + My_Text_Selection mHighlight; + int mLength; /* length of the text in the buffer (the length + of the buffer itself must be calculated: + gapEnd - gapStart + length) */ + char* mBuf; /* allocated memory where the text is stored */ + int mGapStart; /* points to the first character of the gap */ + int mGapEnd; /* points to the first char after the gap */ + // The hardware tab distance used by all displays for this buffer, + // and used in computing offsets for rectangular selection operations. + int mTabDist; /* equiv. number of characters in a tab */ + int mUseTabs; /* True if buffer routines are allowed to use + tabs for padding in rectangular operations */ + int mNModifyProcs; /* number of modify-redisplay procs attached */ + My_Text_Modify_Cb* /* procedures to call when buffer is */ + mNodifyProcs; /* modified to redisplay contents */ + void** mCbArgs; /* caller arguments for modifyProcs above */ + int mNPredeleteProcs; /* number of pre-delete procs attached */ + My_Text_Predelete_Cb* /* procedure to call before text is deleted */ + mPredeleteProcs; /* from the buffer; at most one is supported. */ + void **mPredeleteCbArgs; /* caller argument for pre-delete proc above */ + int mCursorPosHint; /* hint for reasonable cursor position after + a buffer modification operation */ + char mNullSubsChar; /* NEdit is based on C null-terminated strings, + so ascii-nul characters must be substituted + with something else. This is the else, but + of course, things get quite messy when you + use it */ + char mCanUndo; /* if this buffer is used for attributes, it must + not do any undo calls */ +}; + +#endif + +// +// End of "$Id$". +// diff --git a/src/My_Text_Buffer.cpp b/src/My_Text_Buffer.cpp new file mode 100644 index 0000000..5c53a91 --- /dev/null +++ b/src/My_Text_Buffer.cpp @@ -0,0 +1,2539 @@ +// +// "$Id$" +// +// Copyright 2001-2005 by Bill Spitzak and others. +// Original code Copyright Mark Edel. Permission to distribute under +// the LGPL for the FLTK library granted by Mark Edel. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include +#include +#include +//#include "flstring.h" +#include +#include +#include "My_Text_Buffer.H" + + +#define PREFERRED_GAP_SIZE 1024 +/* Initial size for the buffer gap (empty space +in the buffer where text might be inserted +if the user is typing sequential chars ) */ + +static void histogramCharacters( const char *string, int length, char hist[ 256 ], + int init ); +static void subsChars( char *string, int length, char fromChar, char toChar ); +static char chooseNullSubsChar( char hist[ 256 ] ); +static void insertColInLine( const char *line, char *insLine, int column, int insWidth, + int tabDist, int useTabs, char nullSubsChar, char *outStr, int *outLen, + int *endOffset ); +static void deleteRectFromLine( const char *line, int rectStart, int rectEnd, + int tabDist, int useTabs, char nullSubsChar, char *outStr, int *outLen, + int *endOffset ); +static void overlayRectInLine( const char *line, char *insLine, int rectStart, + int rectEnd, int tabDist, int useTabs, char nullSubsChar, char *outStr, + int *outLen, int *endOffset ); + +static void addPadding( char *string, int startIndent, int toIndent, + int tabDist, int useTabs, char nullSubsChar, int *charsAdded ); +static char *copyLine( const char* text, int *lineLen ); +static int countLines( const char *string ); +static int textWidth( const char *text, int tabDist, char nullSubsChar ); +static char *realignTabs( const char *text, int origIndent, int newIndent, + int tabDist, int useTabs, char nullSubsChar, int *newLength ); +static char *expandTabs( const char *text, int startIndent, int tabDist, + char nullSubsChar, int *newLen ); +static char *unexpandTabs( char *text, int startIndent, int tabDist, + char nullSubsChar, int *newLen ); +static int max( int i1, int i2 ); +static int min( int i1, int i2 ); + +static const char *ControlCodeTable[ 32 ] = { + "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", + "bs", "ht", "nl", "vt", "np", "cr", "so", "si", + "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", + "can", "em", "sub", "esc", "fs", "gs", "rs", "us"}; + +static char* undobuffer; +static int undobufferlength; +static My_Text_Buffer* undowidget; +static int undoat; // points after insertion +static int undocut; // number of characters deleted there +static int undoinsert; // number of characters inserted +static int undoyankcut; // length of valid contents of buffer, even if undocut=0 + +static void undobuffersize(int n) { + if (n > undobufferlength) { + if (undobuffer) { + do {undobufferlength *= 2;} while (undobufferlength < n); + undobuffer = (char*)realloc(undobuffer, undobufferlength); + } else { + undobufferlength = n+9; + undobuffer = (char*)malloc(undobufferlength); + } + } +} + +/* +** Create an empty text buffer of a pre-determined size (use this to +** avoid unnecessary re-allocation if you know exactly how much the buffer +** will need to hold +*/ +My_Text_Buffer::My_Text_Buffer( int requestedSize ) { + mLength = 0; + mBuf = (char *)malloc( requestedSize + PREFERRED_GAP_SIZE ); + mGapStart = 0; + mGapEnd = PREFERRED_GAP_SIZE; + mTabDist = 8; + mUseTabs = 1; + mPrimary.mSelected = 0; + mPrimary.mRectangular = 0; + mPrimary.mStart = mPrimary.mEnd = 0; + mSecondary.mSelected = 0; + mSecondary.mStart = mSecondary.mEnd = 0; + mSecondary.mRectangular = 0; + mHighlight.mSelected = 0; + mHighlight.mStart = mHighlight.mEnd = 0; + mHighlight.mRectangular = 0; + mNodifyProcs = NULL; + mCbArgs = NULL; + mNModifyProcs = 0; + mNPredeleteProcs = 0; + mPredeleteProcs = NULL; + mPredeleteCbArgs = NULL; + mCursorPosHint = 0; + mNullSubsChar = '\0'; + mCanUndo = 1; +#ifdef PURIFY +{ int i; for (i = mGapStart; i < mGapEnd; i++) mBuf[ i ] = '.'; } +#endif +} + +/* +** Free a text buffer +*/ +My_Text_Buffer::~My_Text_Buffer() { + free( mBuf ); + if ( mNModifyProcs != 0 ) { + delete[] mNodifyProcs; + delete[] mCbArgs; + } + if ( mNPredeleteProcs != 0 ) { + delete[] mPredeleteProcs; + delete[] mPredeleteCbArgs; + } +} + +/* +** Get the entire contents of a text buffer. Memory is allocated to contain +** the returned string, which the caller must free. +*/ +char * My_Text_Buffer::text() { + char *t; + + t = (char *)malloc( mLength + 1 ); + memcpy( t, mBuf, mGapStart ); + memcpy( &t[ mGapStart ], &mBuf[ mGapEnd ], + mLength - mGapStart ); + t[ mLength ] = '\0'; + return t; +} + +/* +** Replace the entire contents of the text buffer +*/ +void My_Text_Buffer::text( const char *t ) { + int insertedLength, deletedLength; + const char *deletedText; + + call_predelete_callbacks(0, length()); + + /* Save information for redisplay, and get rid of the old buffer */ + deletedText = text(); + deletedLength = mLength; + free( (void *)mBuf ); + + /* Start a new buffer with a gap of PREFERRED_GAP_SIZE in the center */ + insertedLength = strlen( t ); + mBuf = (char *)malloc( insertedLength + PREFERRED_GAP_SIZE ); + mLength = insertedLength; + mGapStart = insertedLength / 2; + mGapEnd = mGapStart + PREFERRED_GAP_SIZE; + memcpy( mBuf, t, mGapStart ); + memcpy( &mBuf[ mGapEnd ], &t[ mGapStart ], insertedLength - mGapStart ); +#ifdef PURIFY +{ int i; for ( i = mGapStart; i < mGapEnd; i++ ) mBuf[ i ] = '.'; } +#endif + + /* Zero all of the existing selections */ + update_selections( 0, deletedLength, 0 ); + + /* Call the saved display routine(s) to update the screen */ + call_modify_callbacks( 0, deletedLength, insertedLength, 0, deletedText ); + free( (void *)deletedText ); +} + +/* +** Return a copy of the text between "start" and "end" character positions +** from text buffer "buf". Positions start at 0, and the range does not +** include the character pointed to by "end" +*/ +char * My_Text_Buffer::text_range( int start, int end ) { + char * s; + int copiedLength, part1Length; + + /* Make sure start and end are ok, and allocate memory for returned string. + If start is bad, return "", if end is bad, adjust it. */ + if ( start < 0 || start > mLength ) { + s = (char *)malloc( 1 ); + s[ 0 ] = '\0'; + return s; + } + if ( end < start ) { + int temp = start; + start = end; + end = temp; + } + if ( end > mLength ) + end = mLength; + copiedLength = end - start; + s = (char *)malloc( copiedLength + 1 ); + + /* Copy the text from the buffer to the returned string */ + if ( end <= mGapStart ) { + memcpy( s, &mBuf[ start ], copiedLength ); + } else if ( start >= mGapStart ) { + memcpy( s, &mBuf[ start + ( mGapEnd - mGapStart ) ], copiedLength ); + } else { + part1Length = mGapStart - start; + memcpy( s, &mBuf[ start ], part1Length ); + memcpy( &s[ part1Length ], &mBuf[ mGapEnd ], copiedLength - part1Length ); + } + s[ copiedLength ] = '\0'; + return s; +} + +/* +** Return the character at buffer position "pos". Positions start at 0. +*/ +char My_Text_Buffer::character( int pos ) { + if ( pos < 0 || pos >= mLength ) + return '\0'; + if ( pos < mGapStart ) + return mBuf[ pos ]; + else + return mBuf[ pos + mGapEnd - mGapStart ]; +} + +/* +** Insert null-terminated string "text" at position "pos" in "buf" +*/ +void My_Text_Buffer::insert( int pos, const char *s ) { + int nInserted; + + /* if pos is not contiguous to existing text, make it */ + if ( pos > mLength ) pos = mLength; + if ( pos < 0 ) pos = 0; + + /* Even if nothing is deleted, we must call these callbacks */ + call_predelete_callbacks( pos, 0 ); + + /* insert and redisplay */ + nInserted = insert_( pos, s ); + mCursorPosHint = pos + nInserted; + call_modify_callbacks( pos, 0, nInserted, 0, NULL ); +} + +/* +** Delete the characters between "start" and "end", and insert the +** null-terminated string "text" in their place in in "buf" +*/ +void My_Text_Buffer::replace( int start, int end, const char *s ) { + const char * deletedText; + int nInserted; + + // Range check... + if (!s) return; + if (start < 0) start = 0; + if (end > mLength) end = mLength; + + call_predelete_callbacks( start, end-start ); + deletedText = text_range( start, end ); + remove_( start, end ); + //undoyankcut = undocut; + nInserted = insert_( start, s ); + mCursorPosHint = start + nInserted; + call_modify_callbacks( start, end - start, nInserted, 0, deletedText ); + free( (void *)deletedText ); +} + +void My_Text_Buffer::remove( int start, int end ) { + const char * deletedText; + + /* Make sure the arguments make sense */ + if ( start > end ) { + int temp = start; + start = end; + end = temp; + } + if ( start > mLength ) start = mLength; + if ( start < 0 ) start = 0; + if ( end > mLength ) end = mLength; + if ( end < 0 ) end = 0; + + if (start == end) return; + + call_predelete_callbacks( start, end-start ); + /* Remove and redisplay */ + deletedText = text_range( start, end ); + remove_( start, end ); + mCursorPosHint = start; + call_modify_callbacks( start, end - start, 0, 0, deletedText ); + free( (void *)deletedText ); +} + +void My_Text_Buffer::copy( My_Text_Buffer *fromBuf, int fromStart, + int fromEnd, int toPos ) { + int copiedLength = fromEnd - fromStart; + int part1Length; + + /* Prepare the buffer to receive the new text. If the new text fits in + the current buffer, just move the gap (if necessary) to where + the text should be inserted. If the new text is too large, reallocate + the buffer with a gap large enough to accomodate the new text and a + gap of PREFERRED_GAP_SIZE */ + if ( copiedLength > mGapEnd - mGapStart ) + reallocate_with_gap( toPos, copiedLength + PREFERRED_GAP_SIZE ); + else if ( toPos != mGapStart ) + move_gap( toPos ); + + /* Insert the new text (toPos now corresponds to the start of the gap) */ + if ( fromEnd <= fromBuf->mGapStart ) { + memcpy( &mBuf[ toPos ], &fromBuf->mBuf[ fromStart ], copiedLength ); + } else if ( fromStart >= fromBuf->mGapStart ) { + memcpy( &mBuf[ toPos ], + &fromBuf->mBuf[ fromStart + ( fromBuf->mGapEnd - fromBuf->mGapStart ) ], + copiedLength ); + } else { + part1Length = fromBuf->mGapStart - fromStart; + memcpy( &mBuf[ toPos ], &fromBuf->mBuf[ fromStart ], part1Length ); + memcpy( &mBuf[ toPos + part1Length ], &fromBuf->mBuf[ fromBuf->mGapEnd ], + copiedLength - part1Length ); + } + mGapStart += copiedLength; + mLength += copiedLength; + update_selections( toPos, 0, copiedLength ); +} + +/* +** remove text according to the undo variables or insert text +** from the undo buffer +*/ +int My_Text_Buffer::undo(int *cursorPos) { + if (undowidget != this || !undocut && !undoinsert &&!mCanUndo) return 0; + + int ilen = undocut; + int xlen = undoinsert; + int b = undoat-xlen; + + if (xlen && undoyankcut && !ilen) { + ilen = undoyankcut; + } + + if (xlen && ilen) { + undobuffersize(ilen+1); + undobuffer[ilen] = 0; + char *tmp = strdup(undobuffer); + replace(b, undoat, tmp); + if (cursorPos) *cursorPos = mCursorPosHint; + free(tmp); + } + else if (xlen) { + remove(b, undoat); + if (cursorPos) *cursorPos = mCursorPosHint; + } + else if (ilen) { + undobuffersize(ilen+1); + undobuffer[ilen] = 0; + insert(undoat, undobuffer); + if (cursorPos) *cursorPos = mCursorPosHint; + undoyankcut = 0; + } + + return 1; +} + +/* +** let the undo system know if we can undo changes +*/ +void My_Text_Buffer::canUndo(char flag) { + mCanUndo = flag; +} + +/* +** Insert "text" columnwise into buffer starting at displayed character +** position "column" on the line beginning at "startPos". Opens a rectangular +** space the width and height of "text", by moving all text to the right of +** "column" right. If charsInserted and charsDeleted are not NULL, the +** number of characters inserted and deleted in the operation (beginning +** at startPos) are returned in these arguments +*/ +void My_Text_Buffer::insert_column( int column, int startPos, const char *s, + int *charsInserted, int *charsDeleted ) { + int nLines, lineStartPos, nDeleted, insertDeleted, nInserted; + const char *deletedText; + + nLines = countLines( s ); + lineStartPos = line_start( startPos ); + nDeleted = line_end( skip_lines( startPos, nLines ) ) - + lineStartPos; + call_predelete_callbacks( lineStartPos, nDeleted ); + deletedText = text_range( lineStartPos, lineStartPos + nDeleted ); + insert_column_( column, lineStartPos, s, &insertDeleted, &nInserted, + &mCursorPosHint ); + if ( nDeleted != insertDeleted ) + Fl::error("My_Text_Buffer::insert_column(): internal consistency check ins1 failed"); + call_modify_callbacks( lineStartPos, nDeleted, nInserted, 0, deletedText ); + free( (void *) deletedText ); + if ( charsInserted != NULL ) + * charsInserted = nInserted; + if ( charsDeleted != NULL ) + * charsDeleted = nDeleted; +} + +/* +** Overlay "text" between displayed character positions "rectStart" and +** "rectEnd" on the line beginning at "startPos". If charsInserted and +** charsDeleted are not NULL, the number of characters inserted and deleted +** in the operation (beginning at startPos) are returned in these arguments. +*/ +void My_Text_Buffer::overlay_rectangular( int startPos, int rectStart, + int rectEnd, const char *s, int *charsInserted, int *charsDeleted ) { + int nLines, lineStartPos, nDeleted, insertDeleted, nInserted; + const char *deletedText; + + nLines = countLines( s ); + lineStartPos = line_start( startPos ); + nDeleted = line_end( skip_lines( startPos, nLines ) ) - + lineStartPos; + call_predelete_callbacks( lineStartPos, nDeleted ); + deletedText = text_range( lineStartPos, lineStartPos + nDeleted ); + overlay_rectangular_( lineStartPos, rectStart, rectEnd, s, &insertDeleted, + &nInserted, &mCursorPosHint ); + if ( nDeleted != insertDeleted ) + Fl::error("My_Text_Buffer::overlay_rectangle(): internal consistency check ovly1 failed"); + call_modify_callbacks( lineStartPos, nDeleted, nInserted, 0, deletedText ); + free( (void *) deletedText ); + if ( charsInserted != NULL ) + * charsInserted = nInserted; + if ( charsDeleted != NULL ) + * charsDeleted = nDeleted; +} + +/* +** Replace a rectangular area in buf, given by "start", "end", "rectStart", +** and "rectEnd", with "text". If "text" is vertically longer than the +** rectangle, add extra lines to make room for it. +*/ +void My_Text_Buffer::replace_rectangular( int start, int end, int rectStart, + int rectEnd, const char *s ) { + char *insPtr; + const char *deletedText; + char *insText = (char *)""; + int i, nInsertedLines, nDeletedLines, insLen, hint; + int insertDeleted, insertInserted, deleteInserted; + int linesPadded = 0; + + /* Make sure start and end refer to complete lines, since the + columnar delete and insert operations will replace whole lines */ + start = line_start( start ); + end = line_end( end ); + + call_predelete_callbacks( start, end-start ); + + /* If more lines will be deleted than inserted, pad the inserted text + with newlines to make it as long as the number of deleted lines. This + will indent all of the text to the right of the rectangle to the same + column. If more lines will be inserted than deleted, insert extra + lines in the buffer at the end of the rectangle to make room for the + additional lines in "text" */ + nInsertedLines = countLines( s ); + nDeletedLines = count_lines( start, end ); + if ( nInsertedLines < nDeletedLines ) { + insLen = strlen( s ); + insText = (char *)malloc( insLen + nDeletedLines - nInsertedLines + 1 ); + strcpy( insText, s ); + insPtr = insText + insLen; + for ( i = 0; i < nDeletedLines - nInsertedLines; i++ ) + *insPtr++ = '\n'; + *insPtr = '\0'; + } else if ( nDeletedLines < nInsertedLines ) { + linesPadded = nInsertedLines - nDeletedLines; + for ( i = 0; i < linesPadded; i++ ) + insert_( end, "\n" ); + } /* else nDeletedLines == nInsertedLines; */ + + /* Save a copy of the text which will be modified for the modify CBs */ + deletedText = text_range( start, end ); + + /* Delete then insert */ + remove_rectangular_( start, end, rectStart, rectEnd, &deleteInserted, &hint ); + insert_column_( rectStart, start, insText, &insertDeleted, &insertInserted, + &mCursorPosHint ); + + /* Figure out how many chars were inserted and call modify callbacks */ + if ( insertDeleted != deleteInserted + linesPadded ) + Fl::error("My_Text_Buffer::replace_rectangular(): internal consistency check repl1 failed"); + call_modify_callbacks( start, end - start, insertInserted, 0, deletedText ); + free( (void *) deletedText ); + if ( nInsertedLines < nDeletedLines ) + free( (void *) insText ); +} + +/* +** Remove a rectangular swath of characters between character positions start +** and end and horizontal displayed-character offsets rectStart and rectEnd. +*/ +void My_Text_Buffer::remove_rectangular( int start, int end, int rectStart, + int rectEnd ) { + const char * deletedText; + int nInserted; + + start = line_start( start ); + end = line_end( end ); + call_predelete_callbacks( start, end-start ); + deletedText = text_range( start, end ); + remove_rectangular_( start, end, rectStart, rectEnd, &nInserted, + &mCursorPosHint ); + call_modify_callbacks( start, end - start, nInserted, 0, deletedText ); + free( (void *) deletedText ); +} + +/* +** Clear a rectangular "hole" out of the buffer between character positions +** start and end and horizontal displayed-character offsets rectStart and +** rectEnd. +*/ +void My_Text_Buffer::clear_rectangular( int start, int end, int rectStart, + int rectEnd ) { + int i, nLines; + char *newlineString; + + nLines = count_lines( start, end ); + newlineString = (char *)malloc( nLines + 1 ); + for ( i = 0; i < nLines; i++ ) + newlineString[ i ] = '\n'; + newlineString[ i ] = '\0'; + overlay_rectangular( start, rectStart, rectEnd, newlineString, + NULL, NULL ); + free( (void *) newlineString ); +} + +char * My_Text_Buffer::text_in_rectangle( int start, int end, + int rectStart, int rectEnd ) { + int lineStart, selLeft, selRight, len; + char *textOut, *outPtr, *retabbedStr; + const char *textIn; + + start = line_start( start ); + end = line_end( end ); + textOut = (char *)malloc( ( end - start ) + 1 ); + lineStart = start; + outPtr = textOut; + while ( lineStart <= end ) { + rectangular_selection_boundaries( lineStart, rectStart, rectEnd, + &selLeft, &selRight ); + textIn = text_range( selLeft, selRight ); + len = selRight - selLeft; + memcpy( outPtr, textIn, len ); + free( (void *) textIn ); + outPtr += len; + lineStart = line_end( selRight ) + 1; + *outPtr++ = '\n'; + } + if ( outPtr != textOut ) + outPtr--; /* don't leave trailing newline */ + *outPtr = '\0'; + + /* If necessary, realign the tabs in the selection as if the text were + positioned at the left margin */ + retabbedStr = realignTabs( textOut, rectStart, 0, mTabDist, + mUseTabs, mNullSubsChar, &len ); + free( (void *) textOut ); + return retabbedStr; +} + +/* +** Set the hardware tab distance used by all displays for this buffer, +** and used in computing offsets for rectangular selection operations. +*/ +void My_Text_Buffer::tab_distance( int tabDist ) { + const char * deletedText; + + /* First call the pre-delete callbacks with the previous tab setting + still active. */ + call_predelete_callbacks( 0, mLength ); + + /* Change the tab setting */ + mTabDist = tabDist; + + /* Force any display routines to redisplay everything (unfortunately, + this means copying the whole buffer contents to provide "deletedText" */ + deletedText = text(); + call_modify_callbacks( 0, mLength, mLength, 0, deletedText ); + free( (void *) deletedText ); +} + +void My_Text_Buffer::select( int start, int end ) { + My_Text_Selection oldSelection = mPrimary; + + mPrimary.set( start, end ); + redisplay_selection( &oldSelection, &mPrimary ); +} + +void My_Text_Buffer::unselect() { + My_Text_Selection oldSelection = mPrimary; + + mPrimary.mSelected = 0; + redisplay_selection( &oldSelection, &mPrimary ); +} + +void My_Text_Buffer::select_rectangular( int start, int end, int rectStart, + int rectEnd ) { + My_Text_Selection oldSelection = mPrimary; + + mPrimary.set_rectangular( start, end, rectStart, rectEnd ); + redisplay_selection( &oldSelection, &mPrimary ); +} + +int My_Text_Buffer::selection_position( int *start, int *end + ) { + return mPrimary.position( start, end ); +} + +int My_Text_Buffer::selection_position( int *start, int *end, + int *isRect, int *rectStart, int *rectEnd ) { + return mPrimary.position( start, end, isRect, rectStart, + rectEnd ); +} + +char * My_Text_Buffer::selection_text() { + return selection_text_( &mPrimary ); +} + +void My_Text_Buffer::remove_selection() { + remove_selection_( &mPrimary ); +} + +void My_Text_Buffer::replace_selection( const char *s ) { + replace_selection_( &mPrimary, s ); +} + +void My_Text_Buffer::secondary_select( int start, int end ) { + My_Text_Selection oldSelection = mSecondary; + + mSecondary.set( start, end ); + redisplay_selection( &oldSelection, &mSecondary ); +} + +void My_Text_Buffer::secondary_unselect() { + My_Text_Selection oldSelection = mSecondary; + + mSecondary.mSelected = 0; + redisplay_selection( &oldSelection, &mSecondary ); +} + +void My_Text_Buffer::secondary_select_rectangular( int start, int end, + int rectStart, int rectEnd ) { + My_Text_Selection oldSelection = mSecondary; + + mSecondary.set_rectangular( start, end, rectStart, rectEnd ); + redisplay_selection( &oldSelection, &mSecondary ); +} + +int My_Text_Buffer::secondary_selection_position( int *start, int *end + ) { + return mSecondary.position( start, end ); +} + +int My_Text_Buffer::secondary_selection_position( int *start, int *end, + int *isRect, int *rectStart, int *rectEnd ) { + return mSecondary.position( start, end, isRect, rectStart, + rectEnd ); +} + +char * My_Text_Buffer::secondary_selection_text() { + return selection_text_( &mSecondary ); +} + +void My_Text_Buffer::remove_secondary_selection() { + remove_selection_( &mSecondary ); +} + +void My_Text_Buffer::replace_secondary_selection( const char *s ) { + replace_selection_( &mSecondary, s ); +} + +void My_Text_Buffer::highlight( int start, int end ) { + My_Text_Selection oldSelection = mHighlight; + + mHighlight.set( start, end ); + redisplay_selection( &oldSelection, &mHighlight ); +} + +void My_Text_Buffer::unhighlight() { + My_Text_Selection oldSelection = mHighlight; + + mHighlight.mSelected = 0; + redisplay_selection( &oldSelection, &mHighlight ); +} + +void My_Text_Buffer::highlight_rectangular( int start, int end, + int rectStart, int rectEnd ) { + My_Text_Selection oldSelection = mHighlight; + + mHighlight.set_rectangular( start, end, rectStart, rectEnd ); + redisplay_selection( &oldSelection, &mHighlight ); +} + +int My_Text_Buffer::highlight_position( int *start, int *end + ) { + return mHighlight.position( start, end ); +} + +int My_Text_Buffer::highlight_position( int *start, int *end, + int *isRect, int *rectStart, int *rectEnd ) { + return mHighlight.position( start, end, isRect, rectStart, + rectEnd ); +} + +char * My_Text_Buffer::highlight_text() { + return selection_text_( &mHighlight ); +} + +/* +** Add a callback routine to be called when the buffer is modified +*/ +void My_Text_Buffer::add_modify_callback( My_Text_Modify_Cb bufModifiedCB, + void *cbArg ) { + My_Text_Modify_Cb * newModifyProcs; + void **newCBArgs; + int i; + + newModifyProcs = new My_Text_Modify_Cb [ mNModifyProcs + 1 ]; + newCBArgs = new void * [ mNModifyProcs + 1 ]; + for ( i = 0; i < mNModifyProcs; i++ ) { + newModifyProcs[ i + 1 ] = mNodifyProcs[ i ]; + newCBArgs[ i + 1 ] = mCbArgs[ i ]; + } + if ( mNModifyProcs != 0 ) { + delete [] mNodifyProcs; + delete [] mCbArgs; + } + newModifyProcs[ 0 ] = bufModifiedCB; + newCBArgs[ 0 ] = cbArg; + mNModifyProcs++; + mNodifyProcs = newModifyProcs; + mCbArgs = newCBArgs; +} + +void My_Text_Buffer::remove_modify_callback( My_Text_Modify_Cb bufModifiedCB, + void *cbArg ) { + int i, toRemove = -1; + My_Text_Modify_Cb *newModifyProcs; + void **newCBArgs; + + /* find the matching callback to remove */ + for ( i = 0; i < mNModifyProcs; i++ ) { + if ( mNodifyProcs[ i ] == bufModifiedCB && mCbArgs[ i ] == cbArg ) { + toRemove = i; + break; + } + } + if ( toRemove == -1 ) { + Fl::error("My_Text_Buffer::remove_modify_callback(): Can't find modify CB to remove"); + return; + } + + /* Allocate new lists for remaining callback procs and args (if + any are left) */ + mNModifyProcs--; + if ( mNModifyProcs == 0 ) { + mNModifyProcs = 0; + delete[] mNodifyProcs; + mNodifyProcs = NULL; + delete[] mCbArgs; + mCbArgs = NULL; + return; + } + newModifyProcs = new My_Text_Modify_Cb [ mNModifyProcs ]; + newCBArgs = new void * [ mNModifyProcs ]; + + /* copy out the remaining members and free the old lists */ + for ( i = 0; i < toRemove; i++ ) { + newModifyProcs[ i ] = mNodifyProcs[ i ]; + newCBArgs[ i ] = mCbArgs[ i ]; + } + for ( ; i < mNModifyProcs; i++ ) { + newModifyProcs[ i ] = mNodifyProcs[ i + 1 ]; + newCBArgs[ i ] = mCbArgs[ i + 1 ]; + } + delete[] mNodifyProcs; + delete[] mCbArgs; + mNodifyProcs = newModifyProcs; + mCbArgs = newCBArgs; +} + +/* +** Add a callback routine to be called before text is deleted from the buffer. +*/ +void My_Text_Buffer::add_predelete_callback(My_Text_Predelete_Cb bufPreDeleteCB, + void *cbArg) { + My_Text_Predelete_Cb *newPreDeleteProcs; + void **newCBArgs; + int i; + + newPreDeleteProcs = new My_Text_Predelete_Cb[ mNPredeleteProcs + 1 ]; + newCBArgs = new void * [ mNPredeleteProcs + 1 ]; + for ( i = 0; i < mNPredeleteProcs; i++ ) { + newPreDeleteProcs[i + 1] = mPredeleteProcs[i]; + newCBArgs[i + 1] = mPredeleteCbArgs[i]; + } + if (! mNPredeleteProcs != 0) { + delete [] mPredeleteProcs; + delete [] mPredeleteCbArgs; + } + newPreDeleteProcs[0] = bufPreDeleteCB; + newCBArgs[0] = cbArg; + mNPredeleteProcs++; + mPredeleteProcs = newPreDeleteProcs; + mPredeleteCbArgs = newCBArgs; +} + +void My_Text_Buffer::remove_predelete_callback( + My_Text_Predelete_Cb bufPreDeleteCB, void *cbArg) { + int i, toRemove = -1; + My_Text_Predelete_Cb *newPreDeleteProcs; + void **newCBArgs; + + /* find the matching callback to remove */ + for ( i = 0; i < mNPredeleteProcs; i++) { + if (mPredeleteProcs[i] == bufPreDeleteCB && + mPredeleteCbArgs[i] == cbArg) { + toRemove = i; + break; + } + } + if (toRemove == -1) { + Fl::error("My_Text_Buffer::remove_predelete_callback(): Can't find pre-delete CB to remove"); + return; + } + + /* Allocate new lists for remaining callback procs and args (if + any are left) */ + mNPredeleteProcs--; + if (mNPredeleteProcs == 0) { + mNPredeleteProcs = 0; + delete[] mPredeleteProcs; + mPredeleteProcs = NULL; + delete[] mPredeleteCbArgs; + mPredeleteCbArgs = NULL; + return; + } + newPreDeleteProcs = new My_Text_Predelete_Cb [ mNPredeleteProcs ]; + newCBArgs = new void * [ mNPredeleteProcs ]; + + /* copy out the remaining members and free the old lists */ + for ( i = 0; i < toRemove; i++) { + newPreDeleteProcs[i] = mPredeleteProcs[i]; + newCBArgs[i] = mPredeleteCbArgs[i]; + } + for ( ; i < mNPredeleteProcs; i++) { + newPreDeleteProcs[i] = mPredeleteProcs[i+1]; + newCBArgs[i] = mPredeleteCbArgs[i+1]; + } + delete[] mPredeleteProcs; + delete[] mPredeleteCbArgs; + mPredeleteProcs = newPreDeleteProcs; + mPredeleteCbArgs = newCBArgs; +} + +/* +** Return the text from the entire line containing position "pos" +*/ +char * My_Text_Buffer::line_text( int pos ) { + return text_range( line_start( pos ), line_end( pos ) ); +} + +/* +** Find the position of the start of the line containing position "pos" +*/ +int My_Text_Buffer::line_start( int pos ) { + if ( !findchar_backward( pos, '\n', &pos ) ) + return 0; + return pos + 1; +} + +/* +** Find the position of the end of the line containing position "pos" +** (which is either a pointer to the newline character ending the line, +** or a pointer to one character beyond the end of the buffer) +*/ +int My_Text_Buffer::line_end( int pos ) { + if ( !findchar_forward( pos, '\n', &pos ) ) + pos = mLength; + return pos; +} + +int My_Text_Buffer::word_start( int pos ) { + while ( pos && ( isalnum( character( pos ) ) || character( pos ) == '_' ) ) { + pos--; + } + if ( !( isalnum( character( pos ) ) || character( pos ) == '_' ) ) pos++; + return pos; +} + +int My_Text_Buffer::word_end( int pos ) { + while (pos < length() && (isalnum(character(pos)) || character(pos) == '_' )) { + pos++; + } + return pos; +} + +/* +** Get a character from the text buffer expanded into it's screen +** representation (which may be several characters for a tab or a +** control code). Returns the number of characters written to "outStr". +** "indent" is the number of characters from the start of the line +** for figuring tabs. Output string is guranteed to be shorter or +** equal in length to MY_TEXT_MAX_EXP_CHAR_LEN +*/ +int My_Text_Buffer::expand_character( int pos, int indent, char *outStr ) { + return expand_character( character( pos ), indent, outStr, + mTabDist, mNullSubsChar ); +} + +/* +** Expand a single character from the text buffer into it's screen +** representation (which may be several characters for a tab or a +** control code). Returns the number of characters added to "outStr". +** "indent" is the number of characters from the start of the line +** for figuring tabs. Output string is guranteed to be shorter or +** equal in length to MY_TEXT_MAX_EXP_CHAR_LEN +*/ +int My_Text_Buffer::expand_character( char c, int indent, char *outStr, int tabDist, + char nullSubsChar ) { + int i, nSpaces; + + /* Convert tabs to spaces */ + if ( c == '\t' ) { + nSpaces = tabDist - ( indent % tabDist ); + for ( i = 0; i < nSpaces; i++ ) + outStr[ i ] = ' '; + return nSpaces; + } + + /* Convert control codes to readable character sequences */ + /*... is this safe with international character sets? */ + if ( ( ( unsigned char ) c ) <= 31 ) { + sprintf( outStr, "<%s>", ControlCodeTable[ ( unsigned char ) c ] ); + return strlen( outStr ); + } else if ( c == 127 ) { + sprintf( outStr, "" ); + return 5; + } else if ( c == nullSubsChar ) { + sprintf( outStr, "" ); + return 5; + } + + /* Otherwise, just return the character */ + *outStr = c; + return 1; +} + +/* +** Return the length in displayed characters of character "c" expanded +** for display (as discussed above in BufGetExpandedChar). If the +** buffer for which the character width is being measured is doing null +** substitution, nullSubsChar should be passed as that character (or nul +** to ignore). +*/ +int My_Text_Buffer::character_width( char c, int indent, int tabDist, char nullSubsChar ) { + /* Note, this code must parallel that in My_Text_Buffer::ExpandCharacter */ + if ( c == '\t' ) + return tabDist - ( indent % tabDist ); + else if ( ( ( unsigned char ) c ) <= 31 ) + return strlen( ControlCodeTable[ ( unsigned char ) c ] ) + 2; + else if ( c == 127 ) + return 5; + else if ( c == nullSubsChar ) + return 5; + return 1; +} + +/* +** Count the number of displayed characters between buffer position +** "lineStartPos" and "targetPos". (displayed characters are the characters +** shown on the screen to represent characters in the buffer, where tabs and +** control characters are expanded) +*/ +int My_Text_Buffer::count_displayed_characters( int lineStartPos, int targetPos ) { + int pos, charCount = 0; + char expandedChar[ MY_TEXT_MAX_EXP_CHAR_LEN ]; + + pos = lineStartPos; + while ( pos < targetPos ) + charCount += expand_character( pos++, charCount, expandedChar ); + return charCount; +} + +/* +** Count forward from buffer position "startPos" in displayed characters +** (displayed characters are the characters shown on the screen to represent +** characters in the buffer, where tabs and control characters are expanded) +*/ +int My_Text_Buffer::skip_displayed_characters( int lineStartPos, int nChars ) { + int pos, charCount = 0; + char c; + + pos = lineStartPos; + while ( charCount < nChars && pos < mLength ) { + c = character( pos ); + if ( c == '\n' ) + return pos; + charCount += character_width( c, charCount, mTabDist, mNullSubsChar ); + pos++; + } + return pos; +} + +/* +** Count the number of newlines between startPos and endPos in buffer "buf". +** The character at position "endPos" is not counted. +*/ +int My_Text_Buffer::count_lines( int startPos, int endPos ) { + int pos, gapLen = mGapEnd - mGapStart; + int lineCount = 0; + + pos = startPos; + while ( pos < mGapStart ) { + if ( pos == endPos ) + return lineCount; + if ( mBuf[ pos++ ] == '\n' ) + lineCount++; + } + while ( pos < mLength ) { + if ( pos == endPos ) + return lineCount; + if ( mBuf[ pos++ + gapLen ] == '\n' ) + lineCount++; + } + return lineCount; +} + +/* +** Find the first character of the line "nLines" forward from "startPos" +** in "buf" and return its position +*/ +int My_Text_Buffer::skip_lines( int startPos, int nLines ) { + int pos, gapLen = mGapEnd - mGapStart; + int lineCount = 0; + + if ( nLines == 0 ) + return startPos; + + pos = startPos; + while ( pos < mGapStart ) { + if ( mBuf[ pos++ ] == '\n' ) { + lineCount++; + if ( lineCount == nLines ) + return pos; + } + } + while ( pos < mLength ) { + if ( mBuf[ pos++ + gapLen ] == '\n' ) { + lineCount++; + if ( lineCount >= nLines ) + return pos; + } + } + return pos; +} + +/* +** Find the position of the first character of the line "nLines" backwards +** from "startPos" (not counting the character pointed to by "startpos" if +** that is a newline) in "buf". nLines == 0 means find the beginning of +** the line +*/ +int My_Text_Buffer::rewind_lines( int startPos, int nLines ) { + int pos, gapLen = mGapEnd - mGapStart; + int lineCount = -1; + + pos = startPos - 1; + if ( pos <= 0 ) + return 0; + + while ( pos >= mGapStart ) { + if ( mBuf[ pos + gapLen ] == '\n' ) { + if ( ++lineCount >= nLines ) + return pos + 1; + } + pos--; + } + while ( pos >= 0 ) { + if ( mBuf[ pos ] == '\n' ) { + if ( ++lineCount >= nLines ) + return pos + 1; + } + pos--; + } + return 0; +} + +/* +** Search forwards in buffer for string "searchString", starting with the +** character "startPos", and returning the result in "foundPos" +** returns 1 if found, 0 if not. +*/ +int My_Text_Buffer::search_forward( int startPos, const char *searchString, + int *foundPos, int matchCase ) +{ + if (!searchString) return 0; + int bp; + const char* sp; + while (startPos < length()) { + bp = startPos; + sp = searchString; + do { + if (!*sp) { *foundPos = startPos; return 1; } + } while ((matchCase ? character(bp++) == *sp++ : + toupper(character(bp++)) == toupper(*sp++)) + && bp < length()); + startPos++; + } + return 0; +} + +/* +** Search backwards in buffer for string "searchString", starting with the +** character BEFORE "startPos", returning the result in "foundPos" +** returns 1 if found, 0 if not. +*/ +int My_Text_Buffer::search_backward( int startPos, const char *searchString, + int *foundPos, int matchCase ) +{ + if (!searchString) return 0; + int bp; + const char* sp; + while (startPos > 0) { + bp = startPos-1; + sp = searchString+strlen(searchString)-1; + do { + if (sp < searchString) { *foundPos = bp+1; return 1; } + } while ((matchCase ? character(bp--) == *sp-- : + toupper(character(bp--)) == toupper(*sp--)) + && bp >= 0); + startPos--; + } + return 0; +} + +/* +** Search forwards in buffer for characters in "searchChars", starting +** with the character "startPos", and returning the result in "foundPos" +** returns 1 if found, 0 if not. +*/ +int My_Text_Buffer::findchars_forward( int startPos, const char *searchChars, + int *foundPos ) { + int pos, gapLen = mGapEnd - mGapStart; + const char *c; + + pos = startPos; + while ( pos < mGapStart ) { + for ( c = searchChars; *c != '\0'; c++ ) { + if ( mBuf[ pos ] == *c ) { + *foundPos = pos; + return 1; + } + } + pos++; + } + while ( pos < mLength ) { + for ( c = searchChars; *c != '\0'; c++ ) { + if ( mBuf[ pos + gapLen ] == *c ) { + *foundPos = pos; + return 1; + } + } + pos++; + } + *foundPos = mLength; + return 0; +} + +/* +** Search backwards in buffer for characters in "searchChars", starting +** with the character BEFORE "startPos", returning the result in "foundPos" +** returns 1 if found, 0 if not. +*/ +int My_Text_Buffer::findchars_backward( int startPos, const char *searchChars, + int *foundPos ) { + int pos, gapLen = mGapEnd - mGapStart; + const char *c; + + if ( startPos == 0 ) { + *foundPos = 0; + return 0; + } + pos = startPos == 0 ? 0 : startPos - 1; + while ( pos >= mGapStart ) { + for ( c = searchChars; *c != '\0'; c++ ) { + if ( mBuf[ pos + gapLen ] == *c ) { + *foundPos = pos; + return 1; + } + } + pos--; + } + while ( pos >= 0 ) { + for ( c = searchChars; *c != '\0'; c++ ) { + if ( mBuf[ pos ] == *c ) { + *foundPos = pos; + return 1; + } + } + pos--; + } + *foundPos = 0; + return 0; +} + +/* +** A horrible design flaw in NEdit (from the very start, before we knew that +** NEdit would become so popular), is that it uses C NULL terminated strings +** to hold text. This means editing text containing NUL characters is not +** possible without special consideration. Here is the special consideration. +** The routines below maintain a special substitution-character which stands +** in for a null, and translates strings an buffers back and forth from/to +** the substituted form, figure out what to substitute, and figure out +** when we're in over our heads and no translation is possible. +*/ + +/* +** The primary routine for integrating new text into a text buffer with +** substitution of another character for ascii nuls. This substitutes null +** characters in the string in preparation for being copied or replaced +** into the buffer, and if neccessary, adjusts the buffer as well, in the +** event that the string contains the character it is currently using for +** substitution. Returns 0, if substitution is no longer possible +** because all non-printable characters are already in use. +*/ +int My_Text_Buffer::substitute_null_characters( char *string, int len ) { + char histogram[ 256 ]; + + /* Find out what characters the string contains */ + histogramCharacters( string, len, histogram, 1 ); + + /* Does the string contain the null-substitute character? If so, re- + histogram the buffer text to find a character which is ok in both the + string and the buffer, and change the buffer's null-substitution + character. If none can be found, give up and return 0 */ + if ( histogram[ ( unsigned char ) mNullSubsChar ] != 0 ) { + char * bufString; + char newSubsChar; + bufString = (char*)text(); + histogramCharacters( bufString, mLength, histogram, 0 ); + newSubsChar = chooseNullSubsChar( histogram ); + if ( newSubsChar == '\0' ) + return 0; + subsChars( bufString, mLength, mNullSubsChar, newSubsChar ); + remove_( 0, mLength ); + insert_( 0, bufString ); + free( (void *) bufString ); + mNullSubsChar = newSubsChar; + } + + /* If the string contains null characters, substitute them with the + buffer's null substitution character */ + if ( histogram[ 0 ] != 0 ) + subsChars( string, len, '\0', mNullSubsChar ); + return 1; +} + +/* +** Convert strings obtained from buffers which contain null characters, which +** have been substituted for by a special substitution character, back to +** a null-containing string. There is no time penalty for calling this +** routine if no substitution has been done. +*/ +void My_Text_Buffer::unsubstitute_null_characters( char *string ) { + register char * c, subsChar = mNullSubsChar; + + if ( subsChar == '\0' ) + return; + for ( c = string; *c != '\0'; c++ ) + if ( *c == subsChar ) + * c = '\0'; +} + +/* +** Create a pseudo-histogram of the characters in a string (don't actually +** count, because we don't want overflow, just mark the character's presence +** with a 1). If init is true, initialize the histogram before acumulating. +** if not, add the new data to an existing histogram. +*/ +static void histogramCharacters( const char *string, int length, char hist[ 256 ], + int init ) { + int i; + const char *c; + + if ( init ) + for ( i = 0; i < 256; i++ ) + hist[ i ] = 0; + for ( c = string; c < &string[ length ]; c++ ) + hist[ *( ( unsigned char * ) c ) ] |= 1; +} + +/* +** Substitute fromChar with toChar in string. +*/ +static void subsChars( char *string, int length, char fromChar, char toChar ) { + char * c; + + for ( c = string; c < &string[ length ]; c++ ) + if ( *c == fromChar ) * c = toChar; +} + +/* +** Search through ascii control characters in histogram in order of least +** likelihood of use, find an unused character to use as a stand-in for a +** null. If the character set is full (no available characters outside of +** the printable set, return the null character. +*/ +static char chooseNullSubsChar( char hist[ 256 ] ) { +#define N_REPLACEMENTS 25 + static char replacements[ N_REPLACEMENTS ] = {1, 2, 3, 4, 5, 6, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 28, 29, 30, 31, 11, 7}; + int i; + for ( i = 0; i < N_REPLACEMENTS; i++ ) + if ( hist[ replacements[ i ] ] == 0 ) + return replacements[ i ]; + return '\0'; +} + +/* +** Internal (non-redisplaying) version of BufInsert. Returns the length of +** text inserted (this is just strlen(text), however this calculation can be +** expensive and the length will be required by any caller who will continue +** on to call redisplay). pos must be contiguous with the existing text in +** the buffer (i.e. not past the end). +*/ +int My_Text_Buffer::insert_( int pos, const char *s ) { + int insertedLength = strlen( s ); + + /* Prepare the buffer to receive the new text. If the new text fits in + the current buffer, just move the gap (if necessary) to where + the text should be inserted. If the new text is too large, reallocate + the buffer with a gap large enough to accomodate the new text and a + gap of PREFERRED_GAP_SIZE */ + if ( insertedLength > mGapEnd - mGapStart ) + reallocate_with_gap( pos, insertedLength + PREFERRED_GAP_SIZE ); + else if ( pos != mGapStart ) + move_gap( pos ); + + /* Insert the new text (pos now corresponds to the start of the gap) */ + memcpy( &mBuf[ pos ], s, insertedLength ); + mGapStart += insertedLength; + mLength += insertedLength; + update_selections( pos, 0, insertedLength ); + + if (mCanUndo) { + if ( undowidget==this && undoat==pos && undoinsert ) { + undoinsert += insertedLength; + } + else { + undoinsert = insertedLength; + undoyankcut = (undoat==pos) ? undocut : 0 ; + } + undoat = pos+insertedLength; + undocut = 0; + undowidget = this; + } + + return insertedLength; +} + +/* +** Internal (non-redisplaying) version of BufRemove. Removes the contents +** of the buffer between start and end (and moves the gap to the site of +** the delete). +*/ +void My_Text_Buffer::remove_( int start, int end ) { + /* if the gap is not contiguous to the area to remove, move it there */ + + if (mCanUndo) { + if ( undowidget==this && undoat==end && undocut ) { + undobuffersize( undocut+end-start+1 ); + memmove( undobuffer+end-start, undobuffer, undocut ); + undocut += end-start; + } + else { + undocut = end-start; + undobuffersize(undocut); + } + undoat = start; + undoinsert = 0; + undoyankcut = 0; + undowidget = this; + } + + if ( start > mGapStart ) { + if (mCanUndo) + memcpy( undobuffer, mBuf+(mGapEnd-mGapStart)+start, end-start ); + move_gap( start ); + } + else if ( end < mGapStart ) { + if (mCanUndo) + memcpy( undobuffer, mBuf+start, end-start ); + move_gap( end ); + } + else { + int prelen = mGapStart - start; + if (mCanUndo) { + memcpy( undobuffer, mBuf+start, prelen ); + memcpy( undobuffer+prelen, mBuf+mGapEnd, end-start-prelen); + } + } + + /* expand the gap to encompass the deleted characters */ + mGapEnd += end - mGapStart; + mGapStart -= mGapStart - start; + + /* update the length */ + mLength -= end - start; + + /* fix up any selections which might be affected by the change */ + update_selections( start, end - start, 0 ); +} + +/* +** Insert a column of text without calling the modify callbacks. Note that +** in some pathological cases, inserting can actually decrease the size of +** the buffer because of spaces being coalesced into tabs. "nDeleted" and +** "nInserted" return the number of characters deleted and inserted beginning +** at the start of the line containing "startPos". "endPos" returns buffer +** position of the lower left edge of the inserted column (as a hint for +** routines which need to set a cursor position). +*/ +void My_Text_Buffer::insert_column_( int column, int startPos, const char *insText, + int *nDeleted, int *nInserted, int *endPos ) { + int nLines, start, end, insWidth, lineStart, lineEnd; + int expReplLen, expInsLen, len, endOffset; + char *c, *outStr, *outPtr, *expText, *insLine; + const char *line; + const char *replText; + const char *insPtr; + + if ( column < 0 ) + column = 0; + + /* Allocate a buffer for the replacement string large enough to hold + possibly expanded tabs in both the inserted text and the replaced + area, as well as per line: 1) an additional 2*MY_TEXT_MAX_EXP_CHAR_LEN + characters for padding where tabs and control characters cross the + column of the selection, 2) up to "column" additional spaces per + line for padding out to the position of "column", 3) padding up + to the width of the inserted text if that must be padded to align + the text beyond the inserted column. (Space for additional + newlines if the inserted text extends beyond the end of the buffer + is counted with the length of insText) */ + start = line_start( startPos ); + nLines = countLines( insText ) + 1; + insWidth = textWidth( insText, mTabDist, mNullSubsChar ); + end = line_end( skip_lines( start, nLines - 1 ) ); + replText = text_range( start, end ); + expText = expandTabs( replText, 0, mTabDist, mNullSubsChar, + &expReplLen ); + free( (void *) replText ); + free( (void *) expText ); + expText = expandTabs( insText, 0, mTabDist, mNullSubsChar, + &expInsLen ); + free( (void *) expText ); + outStr = (char *)malloc( expReplLen + expInsLen + + nLines * ( column + insWidth + MY_TEXT_MAX_EXP_CHAR_LEN ) + 1 ); + + /* Loop over all lines in the buffer between start and end removing the + text between rectStart and rectEnd and padding appropriately. Trim + trailing space from line (whitespace at the ends of lines otherwise + tends to multiply, since additional padding is added to maintain it */ + outPtr = outStr; + lineStart = start; + insPtr = insText; + for (;;) { + lineEnd = line_end( lineStart ); + line = text_range( lineStart, lineEnd ); + insLine = copyLine( insPtr, &len ); + insPtr += len; + insertColInLine( line, insLine, column, insWidth, mTabDist, + mUseTabs, mNullSubsChar, outPtr, &len, &endOffset ); + free( (void *) line ); + free( (void *) insLine ); + for ( c = outPtr + len - 1; c > outPtr && isspace( *c ); c-- ) + len--; + outPtr += len; + *outPtr++ = '\n'; + lineStart = lineEnd < mLength ? lineEnd + 1 : mLength; + if ( *insPtr == '\0' ) + break; + insPtr++; + } + if ( outPtr != outStr ) + outPtr--; /* trim back off extra newline */ + *outPtr = '\0'; + + /* replace the text between start and end with the new stuff */ + remove_( start, end ); + insert_( start, outStr ); + *nInserted = outPtr - outStr; + *nDeleted = end - start; + *endPos = start + ( outPtr - outStr ) - len + endOffset; + free( (void *) outStr ); +} + +/* +** Delete a rectangle of text without calling the modify callbacks. Returns +** the number of characters replacing those between start and end. Note that +** in some pathological cases, deleting can actually increase the size of +** the buffer because of tab expansions. "endPos" returns the buffer position +** of the point in the last line where the text was removed (as a hint for +** routines which need to position the cursor after a delete operation) +*/ +void My_Text_Buffer::remove_rectangular_( int start, int end, int rectStart, + int rectEnd, int *replaceLen, int *endPos ) { + int nLines, lineStart, lineEnd, len, endOffset; + char *outStr, *outPtr, *expText; + const char *s, *line; + + /* allocate a buffer for the replacement string large enough to hold + possibly expanded tabs as well as an additional MY_TEXT_MAX_EXP_CHAR_LEN * 2 + characters per line for padding where tabs and control characters cross + the edges of the selection */ + start = line_start( start ); + end = line_end( end ); + nLines = count_lines( start, end ) + 1; + s = text_range( start, end ); + expText = expandTabs( s, 0, mTabDist, mNullSubsChar, &len ); + free( (void *) s ); + free( (void *) expText ); + outStr = (char *)malloc( len + nLines * MY_TEXT_MAX_EXP_CHAR_LEN * 2 + 1 ); + + /* loop over all lines in the buffer between start and end removing + the text between rectStart and rectEnd and padding appropriately */ + lineStart = start; + outPtr = outStr; + endOffset = 0; + while ( lineStart <= mLength && lineStart <= end ) { + lineEnd = line_end( lineStart ); + line = text_range( lineStart, lineEnd ); + deleteRectFromLine( line, rectStart, rectEnd, mTabDist, + mUseTabs, mNullSubsChar, outPtr, &len, &endOffset ); + free( (void *) line ); + outPtr += len; + *outPtr++ = '\n'; + lineStart = lineEnd + 1; + } + if ( outPtr != outStr ) + outPtr--; /* trim back off extra newline */ + *outPtr = '\0'; + + /* replace the text between start and end with the newly created string */ + remove_( start, end ); + insert_( start, outStr ); + *replaceLen = outPtr - outStr; + *endPos = start + ( outPtr - outStr ) - len + endOffset; + free( (void *) outStr ); +} + +/* +** Overlay a rectangular area of text without calling the modify callbacks. +** "nDeleted" and "nInserted" return the number of characters deleted and +** inserted beginning at the start of the line containing "startPos". +** "endPos" returns buffer position of the lower left edge of the inserted +** column (as a hint for routines which need to set a cursor position). +*/ +void My_Text_Buffer::overlay_rectangular_(int startPos, int rectStart, + int rectEnd, const char *insText, + int *nDeleted, int *nInserted, + int *endPos ) { + int nLines, start, end, lineStart, lineEnd; + int expInsLen, len, endOffset; + char *c, *outStr, *outPtr, *expText, *insLine; + const char *line; + const char *insPtr; + + /* Allocate a buffer for the replacement string large enough to hold + possibly expanded tabs in the inserted text, as well as per line: 1) + an additional 2*MY_TEXT_MAX_EXP_CHAR_LEN characters for padding where tabs + and control characters cross the column of the selection, 2) up to + "column" additional spaces per line for padding out to the position + of "column", 3) padding up to the width of the inserted text if that + must be padded to align the text beyond the inserted column. (Space + for additional newlines if the inserted text extends beyond the end + of the buffer is counted with the length of insText) */ + start = line_start( startPos ); + nLines = countLines( insText ) + 1; + end = line_end( skip_lines( start, nLines - 1 ) ); + expText = expandTabs( insText, 0, mTabDist, mNullSubsChar, + &expInsLen ); + free( (void *) expText ); + outStr = (char *)malloc( end - start + expInsLen + + nLines * ( rectEnd + MY_TEXT_MAX_EXP_CHAR_LEN ) + 1 ); + + /* Loop over all lines in the buffer between start and end overlaying the + text between rectStart and rectEnd and padding appropriately. Trim + trailing space from line (whitespace at the ends of lines otherwise + tends to multiply, since additional padding is added to maintain it */ + outPtr = outStr; + lineStart = start; + insPtr = insText; + for (;;) { + lineEnd = line_end( lineStart ); + line = text_range( lineStart, lineEnd ); + insLine = copyLine( insPtr, &len ); + insPtr += len; + overlayRectInLine( line, insLine, rectStart, rectEnd, mTabDist, + mUseTabs, mNullSubsChar, outPtr, &len, &endOffset ); + free( (void *) line ); + free( (void *) insLine ); + for ( c = outPtr + len - 1; c > outPtr && isspace( *c ); c-- ) + len--; + outPtr += len; + *outPtr++ = '\n'; + lineStart = lineEnd < mLength ? lineEnd + 1 : mLength; + if ( *insPtr == '\0' ) + break; + insPtr++; + } + if ( outPtr != outStr ) + outPtr--; /* trim back off extra newline */ + *outPtr = '\0'; + + /* replace the text between start and end with the new stuff */ + remove_( start, end ); + insert_( start, outStr ); + *nInserted = outPtr - outStr; + *nDeleted = end - start; + *endPos = start + ( outPtr - outStr ) - len + endOffset; + free( (void *) outStr ); +} + +/* +** Insert characters from single-line string "insLine" in single-line string +** "line" at "column", leaving "insWidth" space before continuing line. +** "outLen" returns the number of characters written to "outStr", "endOffset" +** returns the number of characters from the beginning of the string to +** the right edge of the inserted text (as a hint for routines which need +** to position the cursor). +*/ +static void insertColInLine( const char *line, char *insLine, int column, int insWidth, + int tabDist, int useTabs, char nullSubsChar, char *outStr, int *outLen, + int *endOffset ) { + char * c, *outPtr, *retabbedStr; + const char *linePtr; + int indent, toIndent, len, postColIndent; + + /* copy the line up to "column" */ + outPtr = outStr; + indent = 0; + for ( linePtr = line; *linePtr != '\0'; linePtr++ ) { + len = My_Text_Buffer::character_width( *linePtr, indent, tabDist, nullSubsChar ); + if ( indent + len > column ) + break; + indent += len; + *outPtr++ = *linePtr; + } + + /* If "column" falls in the middle of a character, and the character is a + tab, leave it off and leave the indent short and it will get padded + later. If it's a control character, insert it and adjust indent + accordingly. */ + if ( indent < column && *linePtr != '\0' ) { + postColIndent = indent + len; + if ( *linePtr == '\t' ) + linePtr++; + else { + *outPtr++ = *linePtr++; + indent += len; + } + } else + postColIndent = indent; + + /* If there's no text after the column and no text to insert, that's all */ + if ( *insLine == '\0' && *linePtr == '\0' ) { + *outLen = *endOffset = outPtr - outStr; + return; + } + + /* pad out to column if text is too short */ + if ( indent < column ) { + addPadding( outPtr, indent, column, tabDist, useTabs, nullSubsChar, &len ); + outPtr += len; + indent = column; + } + + /* Copy the text from "insLine" (if any), recalculating the tabs as if + the inserted string began at column 0 to its new column destination */ + if ( *insLine != '\0' ) { + retabbedStr = realignTabs( insLine, 0, indent, tabDist, useTabs, + nullSubsChar, &len ); + for ( c = retabbedStr; *c != '\0'; c++ ) { + *outPtr++ = *c; + len = My_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar ); + indent += len; + } + free( (void *) retabbedStr ); + } + + /* If the original line did not extend past "column", that's all */ + if ( *linePtr == '\0' ) { + *outLen = *endOffset = outPtr - outStr; + return; + } + + /* Pad out to column + width of inserted text + (additional original + offset due to non-breaking character at column) */ + toIndent = column + insWidth + postColIndent - column; + addPadding( outPtr, indent, toIndent, tabDist, useTabs, nullSubsChar, &len ); + outPtr += len; + indent = toIndent; + + /* realign tabs for text beyond "column" and write it out */ + retabbedStr = realignTabs( linePtr, postColIndent, indent, tabDist, + useTabs, nullSubsChar, &len ); + strcpy( outPtr, retabbedStr ); + free( (void *) retabbedStr ); + *endOffset = outPtr - outStr; + *outLen = ( outPtr - outStr ) + len; +} + +/* +** Remove characters in single-line string "line" between displayed positions +** "rectStart" and "rectEnd", and write the result to "outStr", which is +** assumed to be large enough to hold the returned string. Note that in +** certain cases, it is possible for the string to get longer due to +** expansion of tabs. "endOffset" returns the number of characters from +** the beginning of the string to the point where the characters were +** deleted (as a hint for routines which need to position the cursor). +*/ +static void deleteRectFromLine( const char *line, int rectStart, int rectEnd, + int tabDist, int useTabs, char nullSubsChar, char *outStr, int *outLen, + int *endOffset ) { + int indent, preRectIndent, postRectIndent, len; + const char *c; + char *retabbedStr, *outPtr; + + /* copy the line up to rectStart */ + outPtr = outStr; + indent = 0; + for ( c = line; *c != '\0'; c++ ) { + if ( indent > rectStart ) + break; + len = My_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar ); + if ( indent + len > rectStart && ( indent == rectStart || *c == '\t' ) ) + break; + indent += len; + *outPtr++ = *c; + } + preRectIndent = indent; + + /* skip the characters between rectStart and rectEnd */ + for ( ; *c != '\0' && indent < rectEnd; c++ ) + indent += My_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar ); + postRectIndent = indent; + + /* If the line ended before rectEnd, there's nothing more to do */ + if ( *c == '\0' ) { + *outPtr = '\0'; + *outLen = *endOffset = outPtr - outStr; + return; + } + + /* fill in any space left by removed tabs or control characters + which straddled the boundaries */ + indent = max( rectStart + postRectIndent - rectEnd, preRectIndent ); + addPadding( outPtr, preRectIndent, indent, tabDist, useTabs, nullSubsChar, + &len ); + outPtr += len; + + /* Copy the rest of the line. If the indentation has changed, preserve + the position of non-whitespace characters by converting tabs to + spaces, then back to tabs with the correct offset */ + retabbedStr = realignTabs( c, postRectIndent, indent, tabDist, useTabs, + nullSubsChar, &len ); + strcpy( outPtr, retabbedStr ); + free( (void *) retabbedStr ); + *endOffset = outPtr - outStr; + *outLen = ( outPtr - outStr ) + len; +} + +/* +** Overlay characters from single-line string "insLine" on single-line string +** "line" between displayed character offsets "rectStart" and "rectEnd". +** "outLen" returns the number of characters written to "outStr", "endOffset" +** returns the number of characters from the beginning of the string to +** the right edge of the inserted text (as a hint for routines which need +** to position the cursor). +*/ +static void overlayRectInLine( const char *line, char *insLine, int rectStart, + int rectEnd, int tabDist, int useTabs, char nullSubsChar, char *outStr, + int *outLen, int *endOffset ) { + char * c, *outPtr, *retabbedStr; + int inIndent, outIndent, len, postRectIndent; + const char *linePtr; + + /* copy the line up to "rectStart" */ + outPtr = outStr; + inIndent = outIndent = 0; + for ( linePtr = line; *linePtr != '\0'; linePtr++ ) { + len = My_Text_Buffer::character_width( *linePtr, inIndent, tabDist, nullSubsChar ); + if ( inIndent + len > rectStart ) + break; + inIndent += len; + outIndent += len; + *outPtr++ = *linePtr; + } + + /* If "rectStart" falls in the middle of a character, and the character + is a tab, leave it off and leave the outIndent short and it will get + padded later. If it's a control character, insert it and adjust + outIndent accordingly. */ + if ( inIndent < rectStart && *linePtr != '\0' ) { + if ( *linePtr == '\t' ) { + linePtr++; + inIndent += len; + } else { + *outPtr++ = *linePtr++; + outIndent += len; + inIndent += len; + } + } + + /* skip the characters between rectStart and rectEnd */ + postRectIndent = rectEnd; + for ( ; *linePtr != '\0'; linePtr++ ) { + inIndent += My_Text_Buffer::character_width( *linePtr, inIndent, tabDist, nullSubsChar ); + if ( inIndent >= rectEnd ) { + linePtr++; + postRectIndent = inIndent; + break; + } + } + + /* If there's no text after rectStart and no text to insert, that's all */ + if ( *insLine == '\0' && *linePtr == '\0' ) { + *outLen = *endOffset = outPtr - outStr; + return; + } + + /* pad out to rectStart if text is too short */ + if ( outIndent < rectStart ) { + addPadding( outPtr, outIndent, rectStart, tabDist, useTabs, nullSubsChar, + &len ); + outPtr += len; + } + outIndent = rectStart; + + /* Copy the text from "insLine" (if any), recalculating the tabs as if + the inserted string began at column 0 to its new column destination */ + if ( *insLine != '\0' ) { + retabbedStr = realignTabs( insLine, 0, rectStart, tabDist, useTabs, + nullSubsChar, &len ); + for ( c = retabbedStr; *c != '\0'; c++ ) { + *outPtr++ = *c; + len = My_Text_Buffer::character_width( *c, outIndent, tabDist, nullSubsChar ); + outIndent += len; + } + free( (void *) retabbedStr ); + } + + /* If the original line did not extend past "rectStart", that's all */ + if ( *linePtr == '\0' ) { + *outLen = *endOffset = outPtr - outStr; + return; + } + + /* Pad out to rectEnd + (additional original offset + due to non-breaking character at right boundary) */ + addPadding( outPtr, outIndent, postRectIndent, tabDist, useTabs, + nullSubsChar, &len ); + outPtr += len; + outIndent = postRectIndent; + + /* copy the text beyond "rectEnd" */ + strcpy( outPtr, linePtr ); + *endOffset = outPtr - outStr; + *outLen = ( outPtr - outStr ) + strlen( linePtr ); +} + +void My_Text_Selection::set( int startpos, int endpos ) { + mSelected = startpos != endpos; + mRectangular = 0; + mStart = min( startpos, endpos ); + mEnd = max( startpos, endpos ); +} + +void My_Text_Selection::set_rectangular( int startpos, int endpos, + int rectStart, int rectEnd ) { + mSelected = rectStart < rectEnd; + mRectangular = 1; + mStart = startpos; + mEnd = endpos; + mRectStart = rectStart; + mRectEnd = rectEnd; +} + +int My_Text_Selection::position( int *startpos, int *endpos ) { + if ( !mSelected ) + return 0; + *startpos = mStart; + *endpos = mEnd; + + return 1; +} + +int My_Text_Selection::position( int *startpos, int *endpos, + int *isRect, int *rectStart, int *rectEnd ) { + if ( !mSelected ) + return 0; + *isRect = mRectangular; + *startpos = mStart; + *endpos = mEnd; + if ( mRectangular ) { + *rectStart = mRectStart; + *rectEnd = mRectEnd; + } + return 1; +} + +/* +** Return true if position "pos" with indentation "dispIndex" is in +** the My_Text_Selection. +*/ +int My_Text_Selection::includes(int pos, int lineStartPos, int dispIndex) { + return selected() && + ( (!rectangular() && pos >= start() && pos < end()) || + (rectangular() && pos >= start() && lineStartPos <= end() && + dispIndex >= rect_start() && dispIndex < rect_end()) + ); +} + + + +char * My_Text_Buffer::selection_text_( My_Text_Selection *sel ) { + int start, end, isRect, rectStart, rectEnd; + char *s; + + /* If there's no selection, return an allocated empty string */ + if ( !sel->position( &start, &end, &isRect, &rectStart, &rectEnd ) ) { + s = (char *)malloc( 1 ); + *s = '\0'; + return s; + } + + /* If the selection is not rectangular, return the selected range */ + if ( isRect ) + return text_in_rectangle( start, end, rectStart, rectEnd ); + else + return text_range( start, end ); +} + +void My_Text_Buffer::remove_selection_( My_Text_Selection *sel ) { + int start, end; + int isRect, rectStart, rectEnd; + + if ( !sel->position( &start, &end, &isRect, &rectStart, &rectEnd ) ) + return; + if ( isRect ) + remove_rectangular( start, end, rectStart, rectEnd ); + else { + remove( start, end ); + //undoyankcut = undocut; + } +} + +void My_Text_Buffer::replace_selection_( My_Text_Selection *sel, const char *s ) { + int start, end, isRect, rectStart, rectEnd; + My_Text_Selection oldSelection = *sel; + + /* If there's no selection, return */ + if ( !sel->position( &start, &end, &isRect, &rectStart, &rectEnd ) ) + return; + + /* Do the appropriate type of replace */ + if ( isRect ) + replace_rectangular( start, end, rectStart, rectEnd, s ); + else + replace( start, end, s ); + + /* Unselect (happens automatically in BufReplace, but BufReplaceRect + can't detect when the contents of a selection goes away) */ + sel->mSelected = 0; + redisplay_selection( &oldSelection, sel ); +} + +static void addPadding( char *string, int startIndent, int toIndent, + int tabDist, int useTabs, char nullSubsChar, int *charsAdded ) { + char * outPtr; + int len, indent; + + indent = startIndent; + outPtr = string; + if ( useTabs ) { + while ( indent < toIndent ) { + len = My_Text_Buffer::character_width( '\t', indent, tabDist, nullSubsChar ); + if ( len > 1 && indent + len <= toIndent ) { + *outPtr++ = '\t'; + indent += len; + } else { + *outPtr++ = ' '; + indent++; + } + } + } else { + while ( indent < toIndent ) { + *outPtr++ = ' '; + indent++; + } + } + *charsAdded = outPtr - string; +} + +/* +** Call the stored modify callback procedure(s) for this buffer to update the +** changed area(s) on the screen and any other listeners. +*/ +void My_Text_Buffer::call_modify_callbacks( int pos, int nDeleted, + int nInserted, int nRestyled, const char *deletedText ) { + int i; + + for ( i = 0; i < mNModifyProcs; i++ ) + ( *mNodifyProcs[ i ] ) ( pos, nInserted, nDeleted, nRestyled, + deletedText, mCbArgs[ i ] ); +} + +/* +** Call the stored pre-delete callback procedure(s) for this buffer to update +** the changed area(s) on the screen and any other listeners. +*/ +void My_Text_Buffer::call_predelete_callbacks(int pos, int nDeleted) { + int i; + + for (i=0; imStart; + newStart = newSelection->mStart; + oldEnd = oldSelection->mEnd; + newEnd = newSelection->mEnd; + if ( oldSelection->mRectangular ) + oldEnd++; + if ( newSelection->mRectangular ) + newEnd++; + + /* If the old or new selection is unselected, just redisplay the + single area that is (was) selected and return */ + if ( !oldSelection->mSelected && !newSelection->mSelected ) + return; + if ( !oldSelection->mSelected ) { + call_modify_callbacks( newStart, 0, 0, newEnd - newStart, NULL ); + return; + } + if ( !newSelection->mSelected ) { + call_modify_callbacks( oldStart, 0, 0, oldEnd - oldStart, NULL ); + return; + } + + /* If the selection changed from normal to rectangular or visa versa, or + if a rectangular selection changed boundaries, redisplay everything */ + if ( ( oldSelection->mRectangular && !newSelection->mRectangular ) || + ( !oldSelection->mRectangular && newSelection->mRectangular ) || + ( oldSelection->mRectangular && ( + ( oldSelection->mRectStart != newSelection->mRectStart ) || + ( oldSelection->mRectEnd != newSelection->mRectEnd ) ) ) ) { + call_modify_callbacks( min( oldStart, newStart ), 0, 0, + max( oldEnd, newEnd ) - min( oldStart, newStart ), NULL ); + return; + } + + /* If the selections are non-contiguous, do two separate updates + and return */ + if ( oldEnd < newStart || newEnd < oldStart ) { + call_modify_callbacks( oldStart, 0, 0, oldEnd - oldStart, NULL ); + call_modify_callbacks( newStart, 0, 0, newEnd - newStart, NULL ); + return; + } + + /* Otherwise, separate into 3 separate regions: ch1, and ch2 (the two + changed areas), and the unchanged area of their intersection, + and update only the changed area(s) */ + ch1Start = min( oldStart, newStart ); + ch2End = max( oldEnd, newEnd ); + ch1End = max( oldStart, newStart ); + ch2Start = min( oldEnd, newEnd ); + if ( ch1Start != ch1End ) + call_modify_callbacks( ch1Start, 0, 0, ch1End - ch1Start, NULL ); + if ( ch2Start != ch2End ) + call_modify_callbacks( ch2Start, 0, 0, ch2End - ch2Start, NULL ); +} + +void My_Text_Buffer::move_gap( int pos ) { + int gapLen = mGapEnd - mGapStart; + + if ( pos > mGapStart ) + memmove( &mBuf[ mGapStart ], &mBuf[ mGapEnd ], + pos - mGapStart ); + else + memmove( &mBuf[ pos + gapLen ], &mBuf[ pos ], mGapStart - pos ); + mGapEnd += pos - mGapStart; + mGapStart += pos - mGapStart; +} + +/* +** reallocate the text storage in "buf" to have a gap starting at "newGapStart" +** and a gap size of "newGapLen", preserving the buffer's current contents. +*/ +void My_Text_Buffer::reallocate_with_gap( int newGapStart, int newGapLen ) { + char * newBuf; + int newGapEnd; + + newBuf = (char *)malloc( mLength + newGapLen ); + newGapEnd = newGapStart + newGapLen; + if ( newGapStart <= mGapStart ) { + memcpy( newBuf, mBuf, newGapStart ); + memcpy( &newBuf[ newGapEnd ], &mBuf[ newGapStart ], + mGapStart - newGapStart ); + memcpy( &newBuf[ newGapEnd + mGapStart - newGapStart ], + &mBuf[ mGapEnd ], mLength - mGapStart ); + } else { /* newGapStart > mGapStart */ + memcpy( newBuf, mBuf, mGapStart ); + memcpy( &newBuf[ mGapStart ], &mBuf[ mGapEnd ], + newGapStart - mGapStart ); + memcpy( &newBuf[ newGapEnd ], + &mBuf[ mGapEnd + newGapStart - mGapStart ], + mLength - newGapStart ); + } + free( (void *) mBuf ); + mBuf = newBuf; + mGapStart = newGapStart; + mGapEnd = newGapEnd; +#ifdef PURIFY +{int i; for ( i = mGapStart; i < mGapEnd; i++ ) mBuf[ i ] = '.'; } +#endif +} + +/* +** Update all of the selections in "buf" for changes in the buffer's text +*/ +void My_Text_Buffer::update_selections( int pos, int nDeleted, + int nInserted ) { + mPrimary.update( pos, nDeleted, nInserted ); + mSecondary.update( pos, nDeleted, nInserted ); + mHighlight.update( pos, nDeleted, nInserted ); +} + +/* +** Update an individual selection for changes in the corresponding text +*/ +void My_Text_Selection::update( int pos, int nDeleted, + int nInserted ) { + if ( !mSelected || pos > mEnd ) + return; + if ( pos + nDeleted <= mStart ) { + mStart += nInserted - nDeleted; + mEnd += nInserted - nDeleted; + } else if ( pos <= mStart && pos + nDeleted >= mEnd ) { + mStart = pos; + mEnd = pos; + mSelected = 0; + } else if ( pos <= mStart && pos + nDeleted < mEnd ) { + mStart = pos; + mEnd = nInserted + mEnd - nDeleted; + } else if ( pos < mEnd ) { + mEnd += nInserted - nDeleted; + if ( mEnd <= mStart ) + mSelected = 0; + } +} + +/* +** Search forwards in buffer "buf" for character "searchChar", starting +** with the character "startPos", and returning the result in "foundPos" +** returns 1 if found, 0 if not. (The difference between this and +** BufSearchForward is that it's optimized for single characters. The +** overall performance of the text widget is dependent on its ability to +** count lines quickly, hence searching for a single character: newline) +*/ +int My_Text_Buffer::findchar_forward( int startPos, char searchChar, + int *foundPos ) { + int pos, gapLen = mGapEnd - mGapStart; + + if (startPos < 0 || startPos >= mLength) { + *foundPos = mLength; + return 0; + } + + pos = startPos; + while ( pos < mGapStart ) { + if ( mBuf[ pos ] == searchChar ) { + *foundPos = pos; + return 1; + } + pos++; + } + while ( pos < mLength ) { + if ( mBuf[ pos + gapLen ] == searchChar ) { + *foundPos = pos; + return 1; + } + pos++; + } + *foundPos = mLength; + return 0; +} + +/* +** Search backwards in buffer "buf" for character "searchChar", starting +** with the character BEFORE "startPos", returning the result in "foundPos" +** returns 1 if found, 0 if not. (The difference between this and +** BufSearchBackward is that it's optimized for single characters. The +** overall performance of the text widget is dependent on its ability to +** count lines quickly, hence searching for a single character: newline) +*/ +int My_Text_Buffer::findchar_backward( int startPos, char searchChar, + int *foundPos ) { + int pos, gapLen = mGapEnd - mGapStart; + + if ( startPos <= 0 || startPos > mLength ) { + *foundPos = 0; + return 0; + } + pos = startPos - 1; + while ( pos >= mGapStart ) { + if ( mBuf[ pos + gapLen ] == searchChar ) { + *foundPos = pos; + return 1; + } + pos--; + } + while ( pos >= 0 ) { + if ( mBuf[ pos ] == searchChar ) { + *foundPos = pos; + return 1; + } + pos--; + } + *foundPos = 0; + return 0; +} + +/* +** Copy from "text" to end up to but not including newline (or end of "text") +** and return the copy as the function value, and the length of the line in +** "lineLen" +*/ +static char *copyLine( const char *text, int *lineLen ) { + int len = 0; + const char *c; + char *outStr; + + for ( c = text; *c != '\0' && *c != '\n'; c++ ) + len++; + outStr = (char *)malloc( len + 1 ); +#ifdef __APPLE__ + strlcpy( outStr, text, len + 1); +#else + strncpy( outStr, text, len + 1); +#endif + *lineLen = len; + return outStr; +} + +/* +** Count the number of newlines in a null-terminated text string; +*/ +static int countLines( const char *string ) { + const char * c; + int lineCount = 0; + + for ( c = string; *c != '\0'; c++ ) + if ( *c == '\n' ) lineCount++; + return lineCount; +} + +/* +** Measure the width in displayed characters of string "text" +*/ +static int textWidth( const char *text, int tabDist, char nullSubsChar ) { + int width = 0, maxWidth = 0; + const char *c; + + for ( c = text; *c != '\0'; c++ ) { + if ( *c == '\n' ) { + if ( width > maxWidth ) + maxWidth = width; + width = 0; + } else + width += My_Text_Buffer::character_width( *c, width, tabDist, nullSubsChar ); + } + if ( width > maxWidth ) + return width; + return maxWidth; +} + +/* +** Find the first and last character position in a line within a rectangular +** selection (for copying). Includes tabs which cross rectStart, but not +** control characters which do so. Leaves off tabs which cross rectEnd. +** +** Technically, the calling routine should convert tab characters which +** cross the right boundary of the selection to spaces which line up with +** the edge of the selection. Unfortunately, the additional memory +** management required in the parent routine to allow for the changes +** in string size is not worth all the extra work just for a couple of +** shifted characters, so if a tab protrudes, just lop it off and hope +** that there are other characters in the selection to establish the right +** margin for subsequent columnar pastes of this data. +*/ +void My_Text_Buffer::rectangular_selection_boundaries( int lineStartPos, + int rectStart, int rectEnd, int *selStart, int *selEnd ) { + int pos, width, indent = 0; + char c; + + /* find the start of the selection */ + for ( pos = lineStartPos; pos < mLength; pos++ ) { + c = character( pos ); + if ( c == '\n' ) + break; + width = My_Text_Buffer::character_width( c, indent, mTabDist, mNullSubsChar ); + if ( indent + width > rectStart ) { + if ( indent != rectStart && c != '\t' ) { + pos++; + indent += width; + } + break; + } + indent += width; + } + *selStart = pos; + + /* find the end */ + for ( ; pos < mLength; pos++ ) { + c = character( pos ); + if ( c == '\n' ) + break; + width = My_Text_Buffer::character_width( c, indent, mTabDist, mNullSubsChar ); + indent += width; + if ( indent > rectEnd ) { + if ( indent - width != rectEnd && c != '\t' ) + pos++; + break; + } + } + *selEnd = pos; +} + +/* +** Adjust the space and tab characters from string "text" so that non-white +** characters remain stationary when the text is shifted from starting at +** "origIndent" to starting at "newIndent". Returns an allocated string +** which must be freed by the caller with XtFree. +*/ +static char *realignTabs( const char *text, int origIndent, int newIndent, + int tabDist, int useTabs, char nullSubsChar, int *newLength ) { + char * expStr, *outStr; + int len; + + /* If the tabs settings are the same, retain original tabs */ + if ( origIndent % tabDist == newIndent % tabDist ) { + len = strlen( text ); + outStr = (char *)malloc( len + 1 ); + strcpy( outStr, text ); + *newLength = len; + return outStr; + } + + /* If the tab settings are not the same, brutally convert tabs to + spaces, then back to tabs in the new position */ + expStr = expandTabs( text, origIndent, tabDist, nullSubsChar, &len ); + if ( !useTabs ) { + *newLength = len; + return expStr; + } + outStr = unexpandTabs( expStr, newIndent, tabDist, nullSubsChar, newLength ); + free( (void *) expStr ); + return outStr; +} + +/* +** Expand tabs to spaces for a block of text. The additional parameter +** "startIndent" if nonzero, indicates that the text is a rectangular selection +** beginning at column "startIndent" +*/ +static char *expandTabs( const char *text, int startIndent, int tabDist, + char nullSubsChar, int *newLen ) { + char * outStr, *outPtr; + const char *c; + int indent, len, outLen = 0; + + /* rehearse the expansion to figure out length for output string */ + indent = startIndent; + for ( c = text; *c != '\0'; c++ ) { + if ( *c == '\t' ) { + len = My_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar ); + outLen += len; + indent += len; + } else if ( *c == '\n' ) { + indent = startIndent; + outLen++; + } else { + indent += My_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar ); + outLen++; + } + } + + /* do the expansion */ + outStr = (char *)malloc( outLen + 1 ); + outPtr = outStr; + indent = startIndent; + for ( c = text; *c != '\0'; c++ ) { + if ( *c == '\t' ) { + len = My_Text_Buffer::expand_character( *c, indent, outPtr, tabDist, nullSubsChar ); + outPtr += len; + indent += len; + } else if ( *c == '\n' ) { + indent = startIndent; + *outPtr++ = *c; + } else { + indent += My_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar ); + *outPtr++ = *c; + } + } + outStr[ outLen ] = '\0'; + *newLen = outLen; + return outStr; +} + +/* +** Convert sequences of spaces into tabs. The threshold for conversion is +** when 3 or more spaces can be converted into a single tab, this avoids +** converting double spaces after a period withing a block of text. +*/ +static char *unexpandTabs( char *text, int startIndent, int tabDist, + char nullSubsChar, int *newLen ) { + char * outStr, *outPtr, *c, expandedChar[ MY_TEXT_MAX_EXP_CHAR_LEN ]; + int indent, len; + + outStr = (char *)malloc( strlen( text ) + 1 ); + outPtr = outStr; + indent = startIndent; + for ( c = text; *c != '\0'; ) { + if ( *c == ' ' ) { + len = My_Text_Buffer::expand_character( '\t', indent, expandedChar, tabDist, + nullSubsChar ); + if ( len >= 3 && !strncmp( c, expandedChar, len ) ) { + c += len; + *outPtr++ = '\t'; + indent += len; + } else { + *outPtr++ = *c++; + indent++; + } + } else if ( *c == '\n' ) { + indent = startIndent; + *outPtr++ = *c++; + } else { + *outPtr++ = *c++; + indent++; + } + } + *outPtr = '\0'; + *newLen = outPtr - outStr; + return outStr; +} + +static int max( int i1, int i2 ) { + return i1 >= i2 ? i1 : i2; +} + +static int min( int i1, int i2 ) { + return i1 <= i2 ? i1 : i2; +} + +int +My_Text_Buffer::insertfile(const char *file, int pos, int buflen) { + FILE *fp; int r; + if (!(fp = fopen(file, "r"))) return 1; + char *buffer = new char[buflen]; + for (; (r = fread(buffer, 1, buflen - 1, fp)) > 0; pos += r) { + buffer[r] = (char)0; + insert(pos, buffer); + } + + int e = ferror(fp) ? 2 : 0; + fclose(fp); + delete[] buffer; + return e; +} + +int +My_Text_Buffer::outputfile(const char *file, int start, int end, int buflen) { + FILE *fp; + if (!(fp = fopen(file, "w"))) return 1; + for (int n; (n = min(end - start, buflen)); start += n) { + const char *p = text_range(start, start + n); + int r = fwrite(p, 1, n, fp); + free((void *)p); + if (r != n) break; + } + + int e = ferror(fp) ? 2 : 0; + fclose(fp); + return e; +} + + +// +// End of "$Id$". +// From 63584ee4d9dadce297c3e87f41030aca6f1af689 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Wed, 26 Nov 2014 07:18:27 +0000 Subject: [PATCH 263/327] Fix opcode 9C in disassembly... should be SBB H, but was SUB H Reported by: Darren Clark Thanks! --- src/disassemble.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/disassemble.cpp b/src/disassemble.cpp index 520ee5a..89d214f 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -117,7 +117,7 @@ const char * gStrTable[256] = { "ADC B", "ADC C", "ADC D", "ADC E", "ADC H", "ADC L", "ADC M", "ADC A", "SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB M", "SUB A", - "SBB B", "SBB C", "SBB D", "SBB E", "SUB H", "SBB L", "SBB M", "SBB A", + "SBB B", "SBB C", "SBB D", "SBB E", "SBB H", "SBB L", "SBB M", "SBB A", "ANA B", "ANA C", "ANA D", "ANA E", "ANA H", "ANA L", "ANA M", "ANA A", "XRA B", "XRA C", "XRA D", "XRA E", "XRA H", "XRA L", "XRA M", "XRA A", From c0a2e092007821448d718bdf842df1307e915053 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Tue, 13 Jan 2015 05:34:24 +0000 Subject: [PATCH 264/327] Fix multiple-include header guard define. --- src/multiwin_icons.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/multiwin_icons.h b/src/multiwin_icons.h index 105a763..4e21fe1 100644 --- a/src/multiwin_icons.h +++ b/src/multiwin_icons.h @@ -29,7 +29,7 @@ #ifndef MULTIWIN_ICONS_H -#define MULTIIWN_ICONS_H +#define MULTIWIN_ICONS_H #include #include From 5cedc90b676c7c09e82f34f179f375345730f2ad Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Tue, 13 Jan 2015 05:51:09 +0000 Subject: [PATCH 265/327] Fix Issue#5 For ctrl tables, ensure all decoded stuff is written even if the ending isn't > x7F. --- src/disassemble.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/disassemble.cpp b/src/disassemble.cpp index 89d214f..88639dd 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -1251,6 +1251,11 @@ void VTDis::Disassemble() strcat(line, arg); } } + if (line[0]) { + if (str_active) + strcat(line, "\""); + tb->append(line); + } } // A JUMP table is one that contains 16 bit address in a table else if (m_pRom->pTables[x].type == TABLE_TYPE_JUMP) From 6b2886ab79df95d1d6b2f89781b27084004267f6 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Tue, 13 Jan 2015 05:51:45 +0000 Subject: [PATCH 266/327] Fix FreeBSD build with clang. Remove non-standard __inline usage in favour of C99 inline. --- GNUmakefile | 40 ++++++++++++++++++++++++---------------- src/display.cpp | 2 +- src/display.h | 2 +- src/doins.c | 43 +------------------------------------------ src/doins.h | 43 ++++++++++++++++++++++++++++++++++++++----- src/genwrap.c | 2 +- src/io.c | 2 +- src/serial.c | 2 +- 8 files changed, 68 insertions(+), 68 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 74c841d..2dd3dde 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -28,18 +28,24 @@ CFLAGS += -I $(SRCDIR)/FLU $(OPTIMIZE) $(DEBUG) -fsigned-char CPPFLAGS += -I $(SRCDIR) $(OPTIMIZE) $(DEBUG) VIRTUALT = virtualt CLIENT = vt_client -CC = $(CROSS_COMPILE)gcc +ifndef CC + CC = $(CROSS_COMPILE)gcc +else + ifdef CROSS_COMPILE + CC = $(CROSS_COMPILE)gcc + endif +endif # ============================= # Find the FLTK libs # ============================= FLTKCONFIG = $(shell which fltk-config) ifneq ($(FLTKCONFIG),) -FLTKLIB = $(shell $(FLTKCONFIG) --libs) -CFLAGS += $(shell $(FLTKCONFIG) --cflags) -CPPFLAGS += $(shell $(FLTKCONFIG) --cxxflags) +FLTKLIB = $(shell $(FLTKCONFIG) --use-images --libs) +CFLAGS += $(shell $(FLTKCONFIG) --use-images --cflags) +CPPFLAGS += $(shell $(FLTKCONFIG) --use-images --cxxflags) endif -POSTBUILD = $(FLTKCONFIG) --post +POSTBUILD = $(FLTKCONFIG) --use-images --post ifeq ($(FLTKLIB),) ifneq ($(FLTKDIR),) @@ -52,14 +58,14 @@ endif # ================================ # Define our linker flags and libs # ================================ -LDFLAGS += $(shell $(FLTKCONFIG) --ldflags) -L/usr/X11R6/lib -LIBFILES = -lstdc++ -lfltk_images -lfltk_jpeg -lfltk_png -lfltk_z -lfltk -lm -lc -ldl -lX11 -lpthread -lXft -lXinerama -lfontconfig -lXext +LDFLAGS += $(shell $(FLTKCONFIG) --use-images --ldflags) -L/usr/X11R6/lib +LIBFILES = -lstdc++ $(FLTKLIB) -lm -lc -lX11 -lpthread -lXft -lXinerama -lfontconfig -lXext # ============================= # Defines for MacOSX builds # ============================= -MACLDFLAGS = $(shell $(FLTKCONFIG) --ldflags) -arch i386 -arch ppc -MACLIBFILES = -lstdc++ `$(FLTKCONFIG) --ldstaticflags --use-images` --lm -lpthread +MACLDFLAGS = $(shell $(FLTKCONFIG) --use-images --ldflags) -arch i386 -arch ppc +MACLIBFILES = -lstdc++ `$(FLTKCONFIG) --use-images --ldstaticflags --use-images` --lm -lpthread # ==================================== # Define all source files for VirtualT @@ -113,10 +119,12 @@ ifndef FLTKLIB exit 1 else # Test if FLTK libraries built - if ! test -f $(FLTKLIB); then \ - echo "Please ensure the FLTK, JPEG, PNG and ZLIB libraries and run make again"; \ - exit 1; \ - fi; + for ONE_FLTKLIB in $(FLTKLIB); do \ + if ! test -f $(ONE_FLTKLIB); then \ + echo "Please ensure the FLTK, JPEG, PNG and ZLIB libraries and run make again"; \ + exit 1; \ + fi; \ + done @echo "Linking" $(VIRTUALT) if test -f /Developer/Tools/Rez; then \ g++ $(MACLDFLAGS) $(OBJECTS) $(MACLIBFILES) -o $@ ; \ @@ -182,10 +190,10 @@ endif clean: @echo "=== cleaning ==="; @echo "Objects..." - @rm -rf $(OBJDIR) $(DEPDIR) + @-rm -rf $(OBJDIR) $(DEPDIR) @echo "Executables..." - rm -f virtualt - rm -f vt_client + -rm -f virtualt + -rm -rf vt_client # ================================================ # Provide info for building FLTK, Tiger, Leopard versions diff --git a/src/display.cpp b/src/display.cpp index c5a3be4..1ac7458 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -1723,7 +1723,7 @@ drawpixel: This routine is called by the system to draw a single ================================================================= */ // Draw the black pixels on the LCD -__inline void T100_Disp::drawpixel(int x, int y, int color) +inline void T100_Disp::drawpixel(int x, int y, int color) { #ifdef ZIPIT_Z2 if (color) diff --git a/src/display.h b/src/display.h index eb4fe6d..c5a78e1 100644 --- a/src/display.h +++ b/src/display.h @@ -145,7 +145,7 @@ class T100_Disp : public Fl_Widget virtual void draw(); static int sim_get_key(int key); static int sim_event_key(void); - __inline void drawpixel(int x, int y, int color); + inline void drawpixel(int x, int y, int color); virtual void draw_static(); static int m_simKeys[32]; static int m_simEventKey; diff --git a/src/doins.c b/src/doins.c index f28ead7..1bdd198 100644 --- a/src/doins.c +++ b/src/doins.c @@ -35,7 +35,7 @@ #include "io.h" #include "m100emu.h" -static char paritybits[256]={ +char paritybits[256]={ 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00, 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00, @@ -54,47 +54,6 @@ static char paritybits[256]={ 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, }; -#if defined(WIN32) || defined(__APPLE__) -void setflags(int regval, int sign, int zero, int auxcarry, int parity, int carry, int ov) -#else -__inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry, char ov) -#endif -{ - if (sign!=-2) - { - if(sign>=0) - F=(F&~SF_BIT)|(sign?SF_BIT:0); - else - F=(F&~SF_BIT)|(regval&SF_BIT); - } - - if (zero != -2) - { - if(zero>=0) - F=(F&~ZF_BIT)|(zero?ZF_BIT:0); - else - F=(F&~ZF_BIT)|(regval?0:ZF_BIT); - } - - if(auxcarry>=0) - F=(F&~AC_BIT)|(auxcarry?AC_BIT:0); - - if (parity != -2) - { - if(parity>=0) - F=(F&~PF_BIT)|paritybits[parity & 0xFF]; - else - /* Table Lookup */ - F=(F&~PF_BIT)|paritybits[regval & 0xFF]; - } - - if(carry>=0) - F=(F&~CF_BIT)|(carry?CF_BIT:0); - - if (ov >= 0) - F=(F&~OV_BIT)|(ov?OV_BIT:0); -} - /* inline void do_instruct(void) #include "do_instruct.h" */ diff --git a/src/doins.h b/src/doins.h index e7cd4a0..f8d75a8 100644 --- a/src/doins.h +++ b/src/doins.h @@ -31,10 +31,43 @@ #ifndef _DOINS_H_ #define _DOINS_H_ -#if defined(WIN32) || defined(__APPLE__) -void setflags(int regval, int sign, int zero, int auxcarry, int parity, int carry, int ov); -#else -__inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry, char ov); -#endif +extern char paritybits[256]; + +static inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry, char ov) +{ + if (sign!=-2) + { + if(sign>=0) + F=(F&~SF_BIT)|(sign?SF_BIT:0); + else + F=(F&~SF_BIT)|(regval&SF_BIT); + } + + if (zero != -2) + { + if(zero>=0) + F=(F&~ZF_BIT)|(zero?ZF_BIT:0); + else + F=(F&~ZF_BIT)|(regval?0:ZF_BIT); + } + + if(auxcarry>=0) + F=(F&~AC_BIT)|(auxcarry?AC_BIT:0); + + if (parity != -2) + { + if(parity>=0) + F=(F&~PF_BIT)|paritybits[parity & 0xFF]; + else + /* Table Lookup */ + F=(F&~PF_BIT)|paritybits[regval & 0xFF]; + } + + if(carry>=0) + F=(F&~CF_BIT)|(carry?CF_BIT:0); + + if (ov >= 0) + F=(F&~OV_BIT)|(ov?OV_BIT:0); +} #endif diff --git a/src/genwrap.c b/src/genwrap.c index 177397a..8cb1e22 100644 --- a/src/genwrap.c +++ b/src/genwrap.c @@ -58,7 +58,7 @@ #if defined(__OpenBSD__) || defined(__NetBSD__) #include #elif defined(__FreeBSD__) - #include + #include #endif #endif /* __unix__ */ diff --git a/src/io.c b/src/io.c index f160634..c83ce61 100644 --- a/src/io.c +++ b/src/io.c @@ -104,7 +104,7 @@ double hirestimer(void) return (double)pcount.QuadPart / (double)pcfreq.QuadPart; } #else -__inline double hirestimer(void) +inline double hirestimer(void) { struct timeval tv; gettimeofday(&tv, NULL); diff --git a/src/serial.c b/src/serial.c index c86bed6..be4cc9b 100644 --- a/src/serial.c +++ b/src/serial.c @@ -43,7 +43,7 @@ #include #include #include /* Error number definitions */ -#if !defined(__APPLE__) +#ifdef __linux__ #include #endif From c885f706dced96b954e4bccfda3fd7ef5f4b8c06 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Tue, 13 Jan 2015 18:48:19 +0000 Subject: [PATCH 267/327] Add missing newline to fragments at the end of TABLE_TYPE_CTRL_DELIM Characters below 0x20 are CTRL chars as well, not just above 0x7E --- src/disassemble.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/disassemble.cpp b/src/disassemble.cpp index 88639dd..bd461b5 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -1217,7 +1217,7 @@ void VTDis::Disassemble() int str_active = 0; for (next = c; next < last; next++) { - if ((m_memory[next] > 0x7E) && (str_active)) + if ((m_memory[next] > 0x7E || m_memory[next] < 0x20) && (str_active)) { sprintf(arg, "\",%02XH\n", m_memory[next]); strcat(line, arg); @@ -1228,7 +1228,7 @@ void VTDis::Disassemble() } if (!str_active) { - if (m_memory[next] > 0x7E) + if (m_memory[next] > 0x7E || m_memory[next] < 0x20) { if (oldSchool) sprintf(line, "%04XH DB %02XH\n", next, m_memory[next]); @@ -1254,6 +1254,7 @@ void VTDis::Disassemble() if (line[0]) { if (str_active) strcat(line, "\""); + strcat(line, "\n"); tb->append(line); } } From a91406a2fe10da158bb83582b196b5f42c8799fc Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 24 Feb 2015 20:19:17 +0000 Subject: [PATCH 268/327] Bug fixes for deleting .CO files, IDE undo and added TDock and TDock video emulation. --- GNUmakefile | 2 +- doc/help.html | 1 - doc/ide.html | 37 ++ doc/ide.jpg | Bin 0 -> 141743 bytes release.txt | 20 + src/My_Text_Buffer.H | 11 + src/My_Text_Buffer.cpp | 37 +- src/VirtualT.h | 2 +- src/colors.h | 145 ++++++ src/display.cpp | 2 + src/display.h | 2 +- src/file.cpp | 4 +- src/highlight.cpp | 6 + src/ide.cpp | 21 +- src/io.c | 79 ++- src/linker.cpp | 19 +- src/multieditwin.cpp | 16 +- src/tdock.cpp | 173 +++++++ src/tdock.h | 73 +++ src/tdockvid.cpp | 1093 ++++++++++++++++++++++++++++++++++++++++ src/tdockvid.h | 144 ++++++ src/tpddserver.h | 4 +- 22 files changed, 1852 insertions(+), 39 deletions(-) create mode 100644 doc/ide.jpg create mode 100644 src/colors.h create mode 100644 src/tdock.cpp create mode 100644 src/tdock.h create mode 100644 src/tdockvid.cpp create mode 100644 src/tdockvid.h diff --git a/GNUmakefile b/GNUmakefile index 2dd3dde..83a178a 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -59,7 +59,7 @@ endif # Define our linker flags and libs # ================================ LDFLAGS += $(shell $(FLTKCONFIG) --use-images --ldflags) -L/usr/X11R6/lib -LIBFILES = -lstdc++ $(FLTKLIB) -lm -lc -lX11 -lpthread -lXft -lXinerama -lfontconfig -lXext +LIBFILES = -lstdc++ $(FLTKLIB) -lm -lc -lX11 -lpthread -ldl -ljpeg -lpng -lXft -lXinerama -lfontconfig -lXext # ============================= # Defines for MacOSX builds diff --git a/doc/help.html b/doc/help.html index 2ba826d..ec7e2e9 100644 --- a/doc/help.html +++ b/doc/help.html @@ -77,7 +77,6 @@

    A Model 100/102/200 Emulator

  • Project Settings
  • 8085 Assembler
  • Linking Projects
  • -
  • Managing Code
  • 9 - About Hardware Emulation
    diff --git a/doc/ide.html b/doc/ide.html index 340e250..2535a00 100644 --- a/doc/ide.html +++ b/doc/ide.html @@ -19,5 +19,42 @@
    +

    The IDE provides an editing and programming environment for 8085 assembly language +programs. It has three panes for presenting information used during a programming session. +These consist of a Project Tree control pane, an Editor / open file tab pane, and a message +window pane. These are demonstrated in the image below. + +

    + +

    The assembler in VirtualT is a relocating / linking assembler. As such, it builds (or can build) programs +from more than just a single source file, each of which is assembled individually into .obj files and then +linked together later. This means that unlike some assemblers, simply providing an assembly file (.asm) isn't +enough information to build the final binary. + +

    The IDE therefore uses Project files (.prj) which specify all the informaiton required during botht the +assembly step and the link step including which files to assemble, project defines and a linker script (*.lkr) +that defines where assembled code should be located. + +

    Project Files

    +

    A project file stores all information needed to build an application, be it a .CO file +or an OptROM. All files added to a project file will appear in the tree control in the +left-hand project pane. Other project settings are configured using the Projects -> Settings +item in the Project menu of the IDE window. + +

    Creating a new project

    +

    New projects are created using File -> New Project menu item. By default, VirtualT +tries to create projects within their own directory under the "Projects" directory from +the main VT Emulation directory. When the project is created, a project name and type +must be supplied. The project type can be changed later, however the name cannot +(at least not without hand editing and renaming the project file). + + + +

    Settings

    + +

    Assembler

    + +

    Linker

    + diff --git a/doc/ide.jpg b/doc/ide.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2e21dcf54fda2363a293a487fdd7b9beba23c907 GIT binary patch literal 141743 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≪n4GiTp!tEF+ylX5K57a=hp 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 f`EAy5@*ib>kn%W<;EC&a)=Th>o&>r(e@y*?S literal 0 HcmV?d00001 diff --git a/release.txt b/release.txt index c11a641..9dea394 100644 --- a/release.txt +++ b/release.txt @@ -5,6 +5,26 @@ VirtualT Release.txt This file lists the changes and additions for each of the versions of VirtualT since v0.3 +===================== +v1.7 Not released yet +===================== + +1. Fixed bug with deleting a .CO file where the deletion length wasn't including + the 6-byte CO header, causing memory corruption. + +2. Fixed the IDE Editor's undo function. + +3. Made the IDE's undo local to each file vs. being a global entity. This allows + undo to be specific to the file being edited. + +4. Fixed a bug in the linker to detect link addresses that are out of range. + +5. Added TDock Video emulation support (and TDock I/O general processing). + +6. Started adding documentation for the IDE / Assembler / Linker. + +7. Updated the GNUMakefile to include libjpeg and libpng. + ==================== v1.6 April 24, 2014 ==================== diff --git a/src/My_Text_Buffer.H b/src/My_Text_Buffer.H index a2c4dd9..e2224d4 100644 --- a/src/My_Text_Buffer.H +++ b/src/My_Text_Buffer.H @@ -252,6 +252,17 @@ class My_Text_Buffer { use it */ char mCanUndo; /* if this buffer is used for attributes, it must not do any undo calls */ + + /* KDP: 2/23/2015. Undo variables moved within Buffer class so they + are not global and apply only to this buffer. */ + + void undobuffersize(int n); + char* undobuffer; + int undobufferlength; + int undoat; // points after insertion + int undocut; // number of characters deleted there + int undoinsert; // number of characters inserted + int undoyankcut; // length of valid contents of buffer, even if undocut=0 }; #endif diff --git a/src/My_Text_Buffer.cpp b/src/My_Text_Buffer.cpp index 5c53a91..40e1d13 100644 --- a/src/My_Text_Buffer.cpp +++ b/src/My_Text_Buffer.cpp @@ -1,6 +1,5 @@ // -// "$Id$" -// +// "$Id$"// // Copyright 2001-2005 by Bill Spitzak and others. // Original code Copyright Mark Edel. Permission to distribute under // the LGPL for the FLTK library granted by Mark Edel. @@ -73,15 +72,16 @@ static const char *ControlCodeTable[ 32 ] = { "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", "can", "em", "sub", "esc", "fs", "gs", "rs", "us"}; -static char* undobuffer; -static int undobufferlength; -static My_Text_Buffer* undowidget; -static int undoat; // points after insertion -static int undocut; // number of characters deleted there -static int undoinsert; // number of characters inserted -static int undoyankcut; // length of valid contents of buffer, even if undocut=0 +//static char* undobuffer; +//static int undobufferlength; +//static My_Text_Buffer* undowidget; +//static int undoat; // points after insertion +//static int undocut; // number of characters deleted there +//static int undoinsert; // number of characters inserted +//static int undoyankcut; // length of valid contents of buffer, even if undocut=0 -static void undobuffersize(int n) { +void My_Text_Buffer::undobuffersize(int n) +{ if (n > undobufferlength) { if (undobuffer) { do {undobufferlength *= 2;} while (undobufferlength < n); @@ -99,6 +99,10 @@ static void undobuffersize(int n) { ** will need to hold */ My_Text_Buffer::My_Text_Buffer( int requestedSize ) { + undobuffer = NULL; + undocut = 0; + undoinsert = 0; + undobufferlength = 0; mLength = 0; mBuf = (char *)malloc( requestedSize + PREFERRED_GAP_SIZE ); mGapStart = 0; @@ -349,7 +353,8 @@ void My_Text_Buffer::copy( My_Text_Buffer *fromBuf, int fromStart, ** from the undo buffer */ int My_Text_Buffer::undo(int *cursorPos) { - if (undowidget != this || !undocut && !undoinsert &&!mCanUndo) return 0; + //if (undowidget != this || !undocut && !undoinsert &&!mCanUndo) return 0; + if (!undocut && !undoinsert &&!mCanUndo) return 0; int ilen = undocut; int xlen = undoinsert; @@ -1368,7 +1373,8 @@ int My_Text_Buffer::insert_( int pos, const char *s ) { update_selections( pos, 0, insertedLength ); if (mCanUndo) { - if ( undowidget==this && undoat==pos && undoinsert ) { + //if ( undowidget==this && undoat==pos && undoinsert ) { + if ( undoat==pos && undoinsert ) { undoinsert += insertedLength; } else { @@ -1377,7 +1383,7 @@ int My_Text_Buffer::insert_( int pos, const char *s ) { } undoat = pos+insertedLength; undocut = 0; - undowidget = this; + //undowidget = this; } return insertedLength; @@ -1392,7 +1398,8 @@ void My_Text_Buffer::remove_( int start, int end ) { /* if the gap is not contiguous to the area to remove, move it there */ if (mCanUndo) { - if ( undowidget==this && undoat==end && undocut ) { + //if ( undowidget==this && undoat==end && undocut ) { + if ( undoat==end && undocut ) { undobuffersize( undocut+end-start+1 ); memmove( undobuffer+end-start, undobuffer, undocut ); undocut += end-start; @@ -1404,7 +1411,7 @@ void My_Text_Buffer::remove_( int start, int end ) { undoat = start; undoinsert = 0; undoyankcut = 0; - undowidget = this; + //undowidget = this; } if ( start > mGapStart ) { diff --git a/src/VirtualT.h b/src/VirtualT.h index a687c1b..0e510eb 100644 --- a/src/VirtualT.h +++ b/src/VirtualT.h @@ -31,7 +31,7 @@ #ifndef _VIRTUALT_H_ #define _VIRTUALT_H_ -#define VERSION "1.6" +#define VERSION "1.7" enum { MODEL_M100 diff --git a/src/colors.h b/src/colors.h new file mode 100644 index 0000000..440358f --- /dev/null +++ b/src/colors.h @@ -0,0 +1,145 @@ + { "Aqua" , 51, 0, 255, 255 }, + { "Aquamarine" , 122, 127, 255, 212 }, + { "Medium Aquamarine" , 115, 102, 205, 170 }, + { "Azure" , 231, 240, 255, 255 }, + { "Beige" , 230, 245, 245, 220 }, + { "Bisque" , 224, 255, 228, 196 }, + { "Black" , 16, 0, 0, 0 }, + { "Blanched Almond" , 230, 255, 235, 205 }, + { "Blue" , 21, 0, 0, 255 }, + { "Dark Blue" , 19, 0, 0, 139 }, + { "Light Blue" , 153, 173, 216, 230 }, + { "Medium Blue" , 20, 0, 0, 205 }, + { "Alice Blue" , 231, 240, 248, 255 }, + { "Cadet Blue" , 109, 95, 158, 160 }, + { "Dodger Blue" , 75, 30, 144, 255 }, + { "Midnight Blue" , 18, 25, 25, 112 }, + { "Navy Blue" , 19, 0, 0, 128 }, + { "Powder Blue" , 153, 176, 224, 230 }, + { "Royal Blue" , 68, 65, 105, 225 }, + { "Sky Blue" , 153, 135, 206, 235 }, + { "Deep Sky Blue" , 45, 0, 191, 255 }, + { "Light Sky Blue" , 153, 135, 206, 250 }, + { "Slate Blue" , 104, 106, 90, 205 }, + { "Dark Slate Blue" , 61, 72, 61, 139 }, + { "Medium Slate Blue" , 105, 123, 104, 238 }, + { "Steel Blue" , 74, 70, 130, 180 }, + { "Light Steel Blue" , 152, 176, 196, 222 }, + { "Brown" , 131, 165, 42, 42 }, + { "Rosy Brown" , 181, 188, 143, 143 }, + { "Saddle Brown" , 130, 139, 69, 19 }, + { "Sandy Brown" , 216, 244, 164, 96 }, + { "Burlywood" , 187, 222, 184, 135 }, + { "Chartreuse" , 118, 127, 255, 0 }, + { "Chocolate" , 173, 210, 105, 30 }, + { "Coral" , 210, 255, 127, 80 }, + { "Light Coral" , 217, 240, 128, 128 }, + { "Cornflower" , 111, 100, 149, 237 }, + { "Cornsilk" , 230, 255, 248, 220 }, + { "Crimson" , 161, 220, 20, 60 }, + { "Cyan" , 51, 0, 255, 255 }, + { "Dark Cyan" , 37, 0, 139, 139 }, + { "Light Cyan" , 195, 224, 255, 255 }, + { "Firebrick" , 131, 178, 34, 34 }, + { "Fuchsia" , 201, 255, 0, 255 }, + { "Gainsboro" , 188, 220, 220, 220 }, + { "Gold" , 220, 255, 215, 0 }, + { "Goldenrod" , 179, 218, 165, 32 }, + { "Dark Goldenrod" , 178, 184, 134, 11 }, + { "Light Goldenrod" , 230, 250, 250, 210 }, + { "Pale Goldenrod" , 229, 238, 232, 170 }, + { "Gray" , 188, 190, 190, 190 }, + { "Dark Gray" , 145, 169, 169, 169 }, + { "Dim Gray" , 102, 105, 105, 105 }, + { "Light Gray" , 188, 211, 211, 211 }, + { "Slate Gray" , 109, 112, 128, 144 }, + { "Light Slate Gray" , 109, 119, 136, 153 }, + { "Web Gray" , 145, 128, 128, 128 }, + { "Green" , 46, 0, 255, 0 }, + { "Dark Green" , 28, 0, 100, 0 }, + { "Light Green" , 157, 144, 238, 144 }, + { "Pale Green" , 157, 152, 251, 152 }, + { "Dark Olive Green" , 101, 85, 107, 47 }, + { "Yellow Green" , 149, 154, 205, 50 }, + { "Forest Green" , 71, 34, 139, 34 }, + { "Lawn Green" , 118, 124, 252, 0 }, + { "Lime Green" , 77, 50, 205, 50 }, + { "Sea Green" , 72, 46, 139, 87 }, + { "Dark Sea Green" , 151, 143, 188, 143 }, + { "Light Sea Green" , 73, 32, 178, 170 }, + { "Medium Sea Green" , 78, 60, 179, 113 }, + { "Spring Green" , 48, 0, 255, 127 }, + { "Medium Spring Green" , 49, 0, 250, 154 }, + { "Web Green" , 34, 0, 128, 0 }, + { "Honeydew" , 231, 240, 255, 240 }, + { "Indian Red" , 174, 205, 92, 92 }, + { "Indigo" , 55, 75, 0, 130 }, + { "Ivory" , 231, 255, 255, 240 }, + { "Khaki" , 229, 240, 230, 140 }, + { "Dark Khaki" , 186, 189, 183, 107 }, + { "Lavender" , 231, 230, 230, 250 }, + { "Lavender Blush" , 231, 255, 240, 245 }, + { "Lemon Chiffon" , 230, 255, 250, 205 }, + { "Lime" , 46, 0, 255, 0 }, + { "Linen" , 231, 250, 240, 230 }, + { "Magenta" , 201, 255, 0, 255 }, + { "Dark Magenta" , 127, 139, 0, 139 }, + { "Maroon" , 132, 176, 48, 96 }, + { "Web Maroon" , 88, 127, 0, 0 }, + { "Mint Cream" , 231, 245, 255, 250 }, + { "Misty Rose" , 224, 255, 228, 225 }, + { "Moccasin" , 224, 255, 228, 181 }, + { "Old Lace" , 231, 253, 245, 230 }, + { "Olive" , 142, 128, 128, 0 }, + { "Olive Drab" , 107, 107, 142, 35 }, + { "Orange" , 214, 255, 165, 0 }, + { "Dark Orange" , 214, 255, 140, 0 }, + { "Orchid" , 176, 218, 112, 214 }, + { "Dark Orchid" , 134, 153, 50, 204 }, + { "Medium Orchid" , 176, 186, 85, 211 }, + { "Papaya Whip" , 230, 255, 239, 213 }, + { "Peach Puff" , 224, 255, 218, 185 }, + { "Peru" , 179, 205, 133, 63 }, + { "Pink" , 224, 255, 192, 203 }, + { "Deep Pink" , 199, 255, 20, 147 }, + { "Light Pink" , 224, 255, 182, 193 }, + { "Hot Pink" , 212, 255, 105, 180 }, + { "Plum" , 182, 221, 160, 221 }, + { "Purple" , 135, 160, 32, 240 }, + { "Medium Purple" , 140, 147, 112, 219 }, + { "Rebecca Purple" , 97, 102, 51, 153 }, + { "Web Purple" , 90, 127, 0, 127 }, + { "Red" , 196, 255, 0, 0 }, + { "Dark Red" , 124, 139, 0, 0 }, + { "Orange Red" , 202, 255, 69, 0 }, + { "Medium Violet Red" , 163, 199, 21, 133 }, + { "Pale Violet Red" , 175, 219, 112, 147 }, + { "Salmon" , 216, 250, 128, 114 }, + { "Dark Salmon" , 216, 233, 150, 122 }, + { "Light Salmon" , 216, 255, 160, 122 }, + { "Seashell" , 231, 255, 245, 238 }, + { "Sienna" , 137, 160, 82, 45 }, + { "Silver" , 188, 192, 192, 192 }, + { "Dark Slate Gray" , 66, 47, 79, 79 }, + { "Snow" , 231, 255, 250, 250 }, + { "Tan" , 187, 210, 180, 140 }, + { "Teal" , 37, 0, 128, 128 }, + { "Thistle" , 188, 216, 191, 216 }, + { "Tomato" , 209, 255, 99, 71 }, + { "Turquoise" , 80, 64, 224, 208 }, + { "Dark Turquoise" , 44, 0, 206, 209 }, + { "Medium Turquoise" , 80, 72, 209, 204 }, + { "Pale Turquoise" , 159, 175, 238, 238 }, + { "Violet" , 219, 238, 130, 238 }, + { "Dark Violet" , 128, 148, 0, 211 }, + { "Blue Violet" , 134, 138, 43, 226 }, + { "Wheat" , 224, 245, 222, 179 }, + { "White" , 231, 255, 255, 255 }, + { "Antique White" , 230, 250, 235, 215 }, + { "Floral White" , 231, 255, 250, 240 }, + { "Ghost White" , 231, 248, 248, 255 }, + { "Navajo White" , 223, 255, 222, 173 }, + { "White Smoke" , 231, 245, 245, 245 }, + { "Yellow" , 226, 255, 255, 0 }, + { "Light Yellow" , 230, 255, 255, 224 }, + { "Green Yellow" , 155, 173, 255, 47 } diff --git a/src/display.cpp b/src/display.cpp index 1ac7458..2c9da6f 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -4779,6 +4779,8 @@ void T200_Disp::draw() fl_color(m_PixelColor); + window()->make_current(); + /* Check if the driver is in "graphics" mode */ if (m_mcr & 0x02) { diff --git a/src/display.h b/src/display.h index c5a78e1..d648761 100644 --- a/src/display.h +++ b/src/display.h @@ -140,8 +140,8 @@ class T100_Disp : public Fl_Widget const virtual T100_Disp& operator=(const T100_Disp& srcDisp); -protected: virtual int handle(int event); +protected: virtual void draw(); static int sim_get_key(int key); static int sim_event_key(void); diff --git a/src/file.cpp b/src/file.cpp index 037d1d1..035f743 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -696,7 +696,7 @@ int delete_file(const char* filename, unsigned short dir_addr) file_type = TYPE_CO; // Deleting a binary file - len = get_memory16(file_addr + 2); + len = get_memory16(file_addr + 2) + 6; } else { @@ -1095,7 +1095,7 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) if (fc != NULL) delete fc; gLoadError = 1; - return; + return; } } diff --git a/src/highlight.cpp b/src/highlight.cpp index c892d93..1d016c6 100644 --- a/src/highlight.cpp +++ b/src/highlight.cpp @@ -280,6 +280,7 @@ const char *asm_code_types[] = { // List of known C/C++asm types... "if", "include", "link", + "list", "lsfirst", "maclib", "module", @@ -544,6 +545,7 @@ void style_init(HighlightCtrl_t *pHlCtrl) style_parse(text, style, pHlCtrl->textbuf->length()); pHlCtrl->stylebuf->text(style); + pHlCtrl->stylebuf->canUndo(0); delete[] style; free(text); } @@ -682,6 +684,10 @@ style_update( int pos, // I - Position of update pHlCtrl = (HighlightCtrl_t *) cbArg; + /* Test if highlight disabled for this buffer */ + if (pHlCtrl->stylebuf == NULL) + return; + // If this is just a selection change, just unselect the style buffer... if (nInserted == 0 && nDeleted == 0) { diff --git a/src/ide.cpp b/src/ide.cpp index 3072032..c220048 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -326,7 +326,8 @@ void close_ide_cb(Fl_Widget* w, void*) ======================================================= Callback for opening recent files ======================================================= -*/void recent_file_cb(Fl_Widget* w, void*) +*/ +void recent_file_cb(Fl_Widget* w, void*) { // if (!check_save()) return; Fl_Menu_* mw = (Fl_Menu_*)w; @@ -351,7 +352,8 @@ Callback for opening recent files ======================================================= Routine to update the recent files menu items ======================================================= -*/void add_recent_file_to_menu(const char *filename) +*/ +void add_recent_file_to_menu(const char *filename) { int c; @@ -402,7 +404,8 @@ Routine to update the recent files menu items ======================================================= Callback for opening recent projects ======================================================= -*/void recent_project_cb(Fl_Widget* w, void*) +*/ +void recent_project_cb(Fl_Widget* w, void*) { // if (!check_save()) return; Fl_Menu_* mw = (Fl_Menu_*)w; @@ -1611,6 +1614,7 @@ void VT_Ide::NewFile(void) { int seq; // Next sequence number MString title; // Tile of new file + MString titlemod; // Tile of new file int children, child; Fl_Widget* pWidget; @@ -1627,6 +1631,9 @@ void VT_Ide::NewFile(void) pWidget = (Fl_Widget*) m_EditTabs->child(child); if (strcmp((const char *) title, pWidget->label()) == 0) break; + titlemod = title + (char *) "*"; + if (strcmp((const char *) titlemod, pWidget->label()) == 0) + break; } // Check if title already exists @@ -1755,7 +1762,7 @@ void VT_Ide::OpenFile(void) void VT_Ide::OpenFile(const char *file) { - MString title; + MString title, titlemod; MString rootpath; if (m_ActivePrj == NULL) @@ -1770,7 +1777,9 @@ void VT_Ide::OpenFile(const char *file) for (int c = 0; c < children; c++) { Fl_Widget* pWidget = (Fl_Widget*) m_EditTabs->child(c); - if (strcmp((const char *) title, pWidget->label()) == 0) + titlemod = title + (char *) "*"; + if ((strcmp((const char *) title, pWidget->label()) == 0) || + (strcmp((const char *) titlemod, pWidget->label()) == 0)) { // File already open...bring file to foreground m_EditTabs->value((Fl_Group *) pWidget); @@ -3788,6 +3797,8 @@ void VT_Ide::BuildProject(void) break; case VT_PROJ_TYPE_ROM: + /* Re-load the OPT ROM */ + load_opt_rom(); break; case VT_PROJ_TYPE_LIB: diff --git a/src/io.c b/src/io.c index c83ce61..29ca677 100644 --- a/src/io.c +++ b/src/io.c @@ -47,6 +47,7 @@ #include "sound.h" #include "lpt.h" #include "clock.h" +#include "tdock.h" uchar lcd[10][256]; uchar lcdpointers[10]={0,0,0,0,0,0,0,0,0,0}; @@ -60,6 +61,8 @@ static uchar ioA3; uchar ioBA; uchar ioB9; uchar ioE8; +uchar gSTROBE; +uchar gCLK; uchar ioBC; /* Low byte of 14-bit timer */ uchar ioBD; /* High byte of 14-bit timer */ uchar ioD0; /* D0-DF io for T200 */ @@ -70,6 +73,11 @@ int gInMsPlanROM = FALSE; uchar keyscan[9] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; char keyin[9]; extern int sound_enable; +extern int fullspeed; +extern volatile UINT64 cycles; +extern volatile int cycle_delta; +volatile UINT64 lcdCycles[10] = {0,}; +double lcdTime[10] = {0.0, }; uint lcdbits=0; unsigned long gSpecialKeys = 0; @@ -78,6 +86,7 @@ int gDelayUpdateKeys = 0; int gDelayCount = 0; extern uchar clock_serial_out; extern int gRomBank; +int gTDock = 1; extern RomDescription_t *gStdRomDesc; void handle_wheel_keys(void); @@ -332,6 +341,8 @@ void init_io(void) ioBC = 0; /* Low byte of 14-bit timer */ ioBD = 0; /* High byte of 14-bit timer */ ioD0 = 0; /* D0-DF io for T200 */ + gSTROBE = 0; + gCLK = 0; } @@ -531,6 +542,21 @@ void out(uchar port, uchar val) /* Call routine to process the CLK pulse */ pd1990ac_clk_pulse(val); } + + /* Check for a CLK condiiton if Video Dock enabled */ + if (gTDock && gSTROBE) + { + /* Test for low to high transition on bit 7 */ + //if ((val & 0x80) && !(ioB9 & 0x80)) + { + gCLK = 1; + } + + /* Test for a high to low transition on bit 7 */ + if (!(val & 0x80) && (ioB9 & 0x80)) + tdock_write((ioB9 >> 1) & 0x3F, (ioB9 & 1 ? 0x80 : 0) | val); + } + ioB9 = val; return; @@ -788,15 +814,32 @@ void out(uchar port, uchar val) pd1990ac_chip_cmd(ioB9); } + if ((val & 0x02) && !(ioE8 & 0x02)) + gSTROBE = 1; + /* Check for data to the printer */ - if ((val & 0x02) && !(ioE8 & 0x02)) - send_to_lpt(ioB9); + if (!(val & 0x02) && (ioE8 & 0x02)) + { + if (!gCLK) + send_to_lpt(ioB9); + gCLK = 0; + gSTROBE = 0; + } } else { // T200 Printer port STROBE is on Bit 0, not Bit 1 - if ((val & 0x01) && !(ioE8 & 0x01)) - send_to_lpt(ioB9); + if ((val & 0x01) && !(ioE8 & 0x01)) + gSTROBE = 1; + + /* Check for data to the printer */ + if (!(val & 0x01) && (ioE8 & 0x01)) + { + if (!gCLK) + send_to_lpt(ioB9); + gCLK = 0; + gSTROBE = 0; + } } ioE8 = val; @@ -816,6 +859,9 @@ void out(uchar port, uchar val) { if (lcdbits & (1 << c)) { + lcdCycles[c] = cycles; + lcdTime[c] = hirestimer(); + /* Save page and column info for later use */ lcdpointers[c]=A; @@ -848,6 +894,8 @@ void out(uchar port, uchar val) if (lcdbits & (1 << c)) { int maxPixels = 50; + lcdCycles[c] = cycles; + lcdTime[c] = hirestimer(); if ((c == 4) || (c == 9)) maxPixels = 40; @@ -855,6 +903,10 @@ void out(uchar port, uchar val) { /* Save Byte in LCD memory */ lcd[c][lcdpointers[c]]=A; +#if 0 + if ((c == 4 || c==9) && lcdpointers[c] >= 40 && lcdpointers[c] < 50) + printf("%d=%02X\n", lcdpointers[c], A); +#endif /* Draw the byte on the display */ if ((lcdpointers[c]&0x3f) < maxPixels) @@ -906,7 +958,7 @@ int inport(uchar port) timeLeft = timeNow - gPort21Time; /* Convert timeLeft (in ms) to int */ - c = (char) (timeLeft * 1000.0); + c = (uchar) (timeLeft * 1000.0); /* Test if time has expired and clear io21 if it has */ if (c >= io21) @@ -1008,7 +1060,10 @@ int inport(uchar port) flags |= clock_serial_out; // OR the Printer Not Busy bit - return flags | 0x02; + if (!gSTROBE) + return flags | 0x02; + else + return flags | tdock_read(); case 0xB4: /* 8155 Timer register. LSB of timer counter */ case 0xBC: @@ -1194,7 +1249,13 @@ int inport(uchar port) if (gModel == MODEL_T200) return t200_readport(0xFE); else - return(64); + { + if (fullspeed == 0 && (lcdTime[c]+.000014 > hirestimer())) + //if (fullspeed == 0 && (lcdCycles[c]+3*2454 > cycles + cycle_delta)) + return (0x80); + else + return(64); + } case 0xFF: /* Loop through all LCD driver modules */ for (c = 0; c < 10; c++) @@ -1204,6 +1265,10 @@ int inport(uchar port) { /* Get the return data from the LCD memory */ int ret = lcd[c][lcdpointers[c]]; +#if 0 + if ((c == 4 || c == 9) && lcdpointers[c] >= 40 && lcdpointers[c] < 50) + printf("Read %d: %02X\n", lcdpointers[c], ret); +#endif /* Update the pointer only if it isn't fresh */ if (!lcd_fresh_ptr[c]) diff --git a/src/linker.cpp b/src/linker.cpp index 0b71852..eadae20 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -474,7 +474,16 @@ void VTLinker::ProcScriptField3(char *pStr, int lineNo, int& startAddr, } } else + { startAddr = EvaluateScriptAddress(pStr + 6, lineNo); + if (startAddr > 65535) + { + err.Format("Error in line %d(%s): START address too large", lineNo, + (const char *) m_LinkerScript); + m_Errors.Add(err); + m_Command = LKR_CMD_ERROR; + } + } } else { @@ -532,7 +541,15 @@ void VTLinker::ProcScriptField4(const char *pStr, int lineNo, int& endAddr) if (strncmp(pStr, "END=", 4) == 0) { endAddr = EvaluateScriptAddress(pStr + 4, lineNo); - m_Command |= LKR_CMD_CD_DONE; + if (endAddr > 65535) + { + err.Format("Error in line %d(%s): END address too large", lineNo, + (const char *) m_LinkerScript); + m_Errors.Add(err); + m_Command = LKR_CMD_ERROR; + } + else + m_Command |= LKR_CMD_CD_DONE; } else { diff --git a/src/multieditwin.cpp b/src/multieditwin.cpp index cc2583c..f397ac2 100644 --- a/src/multieditwin.cpp +++ b/src/multieditwin.cpp @@ -216,19 +216,27 @@ Routine to draw the border and title bar of the window */ void Fl_Multi_Edit_Window::OpenFile(const MString& filename) { + MString ext; // Show the Disassembling text to indicate activity if (filename != "") { + m_tb->canUndo(0); m_tb->loadfile((const char *) filename); + m_tb->canUndo(1); m_FileName = filename; + ext = filename.Right(4); + ext.MakeLower(); + if (ext != ".asm" && ext != ".inc" && ext != ".lkr") + DisableHl(); } if (m_Title.Right(1) == '*') m_Title = m_Title.Left(m_Title.GetLength()-1); label((const char *) m_Title); - redraw(); + if (parent() != NULL) + parent()->redraw(); m_Modified = 0; } @@ -257,7 +265,8 @@ void Fl_Multi_Edit_Window::SaveFile(const MString& rootpath) { m_Title = m_Title.Left(m_Title.GetLength()-1); label((const char *) m_Title); - redraw(); + if (parent() != NULL) + parent()->redraw(); } m_Modified = 0; @@ -326,7 +335,8 @@ void Fl_Multi_Edit_Window::ModifedCB(int pos, int nInserted, int nDeleted, m_Title += '*'; label((const char *) m_Title); - redraw(); + if (parent() != NULL) + parent()->redraw(); m_Modified = 1; } diff --git a/src/tdock.cpp b/src/tdock.cpp new file mode 100644 index 0000000..7fe0af5 --- /dev/null +++ b/src/tdock.cpp @@ -0,0 +1,173 @@ +/* tdock.cpp */ + +/* $Id$ */ + +/* + * Copyright 2015 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#ifdef _WIN32 +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "FLU/Flu_File_Chooser.h" + +#include "VirtualT.h" +#include "m100emu.h" +#include "tdock.h" +#include "tdockvid.h" + +// =============================================== +// Extern "C" linkage items +// =============================================== +extern "C" +{ +extern volatile UINT64 cycles; +extern volatile DWORD rst7cycles; + +#ifdef WIN32 +int strcasecmp(const char* s1, const char* s2); +#endif +} + +extern int MultFact; +static VTTDockVid* gpDisp = NULL; +static Fl_Window* gpExtWin = NULL; +static Fl_Menu_Bar* gpExtMenu = NULL; + +static Fl_Menu_Item menuitems[] = { + { "&File", 0, 0, 0, FL_SUBMENU }, + { "&Open", 0, 0, 0 }, + { 0 }, + { "&Emulation", 0, 0, 0, FL_SUBMENU }, + { "&Some Option", 0, 0, 0 }, + { 0 }, + { "&Tools", 0, 0, 0, FL_SUBMENU }, + { "&Assembler", 0, 0, 0, 0 }, + { 0 }, + { "&Help", 0, 0, 0, FL_SUBMENU}, // | FL_MENU_DIVIDER}, + { "&About", 0, 0, 0, 0 }, + { 0 }, + { 0 } +}; + + +/* +============================================================================ +TDock C init routine +============================================================================ +*/ +void tdock_init (void) +{ + gpExtWin = new Fl_Window((480)*MultFact+10, 200*MultFact+MENU_HEIGHT+10, "VirtualT's TDock VGA Emulation"); + + /* Create a Menu bar in the window */ + gpExtMenu = new Fl_Menu_Bar(0, 0, gpExtWin->w(), MENU_HEIGHT-2); + gpExtMenu->menu(menuitems); + + /* Crate a TDock Video window */ + gpDisp = new VTTDockVid(0, MENU_HEIGHT, gpExtWin->w(), gpExtWin->h() - MENU_HEIGHT); + + gpExtWin->end(); + gpExtWin->show(); +} + +/* +============================================================================ +TDock C write hook +============================================================================ +*/ +void tdock_write(unsigned char device, unsigned char data) +{ + if (gpDisp == NULL) + tdock_init(); + + if (device == 1 && gpDisp) + gpDisp->WriteData(data); + else + printf("TDock write: Device=%d, val=%02X\n", device, data); +} + +/* +============================================================================ +TDock C read hook +============================================================================ +*/ +unsigned char tdock_read(void) +{ + return 0xFF; +} + +/* +=========================================================================== +VTTpddServer class function implementaion follows. This is the constructor +=========================================================================== +*/ +VTTDock::VTTDock(void) +{ +} + +/* +=========================================================================== +Class destructor +=========================================================================== +*/ +VTTDock::~VTTDock(void) +{ +} + +/* +=========================================================================== +Writes data to the TDock +=========================================================================== +*/ +void VTTDock::Write(unsigned char data) +{ +} + +/* +=========================================================================== +Reads data from the TDock +=========================================================================== +*/ +unsigned char VTTDock::Read(void) +{ + return 0xFF; +} + diff --git a/src/tdock.h b/src/tdock.h new file mode 100644 index 0000000..79618d2 --- /dev/null +++ b/src/tdock.h @@ -0,0 +1,73 @@ +/* tdock.h */ + +/* $Id$ */ + +/* +* Copyright 2015 Ken Pettit +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +*/ + +#ifndef VDOCK_H +#define VDOCK_H + +/* +============================================================================ +Define call routines to hook to serial port functionality. +============================================================================ +*/ +#ifdef __cplusplus + +extern "C" +{ +#endif /* __cplusplus */ + +// Now define the function prototypes +void tdock_init(void); +unsigned char tdock_read(void); +void tdock_write(unsigned char device, unsigned char data); +#ifdef __cplusplus +} + +class VTTDock; + +/* +===================================================================== +Define the TDock class. This will be passed around in C land +as a void* context. +===================================================================== +*/ +class VTTDock +{ +public: + VTTDock(); + ~VTTDock(); + + void Init(void); + void Write(unsigned char data); + unsigned char Read(void); +}; + +#endif /* __cplusplus */ + +#endif /* VDOCK_H */ + diff --git a/src/tdockvid.cpp b/src/tdockvid.cpp new file mode 100644 index 0000000..81eb014 --- /dev/null +++ b/src/tdockvid.cpp @@ -0,0 +1,1093 @@ +/* tdockvid.cpp */ + +/* $Id$ */ + +/* + * Copyright 2015 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include + +#include + +#include "FLU/Flu_Button.h" +#include "FLU/Flu_Return_Button.h" +#include "FLU/flu_pixmaps.h" + +#include +#include +#include +#ifndef WIN32 +#include +#include +#endif + +#include "VirtualT.h" +#include "display.h" +#include "tdockvid.h" +#include "m100emu.h" +#include "io.h" +#include "file.h" +#include "setup.h" +#include "periph.h" +#include "memory.h" +#include "memedit.h" +#include "cpuregs.h" +#include "rememcfg.h" +#include "lpt.h" +#include "fl_action_icon.h" +#include "clock.h" +#include "fileview.h" +#include "romstrings.h" +#include "remote.h" +#include "tpddserverlog.h" + + +extern "C" { +extern RomDescription_t gM100_Desc; +extern RomDescription_t gM200_Desc; +extern RomDescription_t gN8201_Desc; +extern RomDescription_t gM10_Desc; +//JV +//extern RomDescription_t gN8300_Desc; +extern RomDescription_t gKC85_Desc; + +extern RomDescription_t *gStdRomDesc; +extern int gRomSize; +extern int gMaintCount; +extern int gOsDelay; +} + + +extern int MultFact; +extern int DisplayMode; +extern int Fullscreen; +extern int SolidChars; +extern int DispHeight; +extern int gRectsize; +extern int gXoffset; +extern int gYoffset; +extern int gSimKey; +extern int gFrameColor; +extern int gDetailColor; +extern int gBackgroundColor; +extern int gPixelColor; +extern int gLabelColor; +extern int gConsoleDebug; + +#ifndef WIN32 +#define min(a,b) ((a)<(b) ? (a):(b)) +#endif + +extern T100_Disp* gpDisp; + +typedef struct namedColors +{ + const char * pName; + unsigned char cid; + unsigned char red; + unsigned char green; + unsigned char blue; +} namedColors_t; + +static namedColors_t gNamedColors[] = { +#include "colors.h" +}; +static int gColorCount = sizeof(gNamedColors) / sizeof(namedColors_t); + +/* +======================================================= +T100:Disp: This is the class construcor +======================================================= +*/ +VTTDockVid::VTTDockVid(int x, int y, int w, int h) : + Fl_Widget(x, y, w, h) +{ + int c, red, green, blue; + + m_FrameColor = gFrameColor; + m_DetailColor = gDetailColor; + m_BackgroundColor = gBackgroundColor; + m_PixelColor = gPixelColor; + m_LabelColor = gLabelColor; + m_HaveMouse = FALSE; + + memset(pixdata, 0, 200*480); + + m_MyFocus = 0; + m_CurX = 0; + m_CurY = 0; + m_EscSeq = 0; + m_Reverse = 0; + m_Locked = 0; + m_Width = 40; + m_Color = 255; + + m_Colors[1] = FL_DARK_RED; + m_Colors[2] = FL_DARK_GREEN; + m_Colors[3] = FL_DARK_YELLOW; + m_Colors[4] = FL_DARK_BLUE; + m_Colors[5] = FL_DARK_MAGENTA; + m_Colors[6] = FL_DARK_CYAN; + m_Colors[7] = FL_LIGHT1; + + m_Colors[8] = FL_DARK2; + m_Colors[9] = FL_RED; + m_Colors[10] = FL_GREEN; + m_Colors[11] = FL_YELLOW; + m_Colors[12] = FL_BLUE; + m_Colors[13] = FL_MAGENTA; + m_Colors[14] = FL_CYAN; + m_Colors[15] = FL_WHITE; + + /* 6x6x6 Color Cube */ + c = 16; + for (red = 0; red <=255; red += 51) + for (green = 0; green <=255; green += 51) + for (blue = 0; blue <=255; blue += 51) + { + m_Colors[c++] = fl_rgb_color(red , green, blue); + } + + /* Gray scale */ + red = 255; + for (c = 254; c >= 232; c--) + { + m_Colors[c] = fl_rgb_color(red, red, red); + red -= 11; + } + + m_Colors[0] = gBackgroundColor; + m_Colors[255] = gPixelColor; + + MultFact = 2; + DisplayMode = 1; + SolidChars = 0; + DispHeight = 64; + gRectsize = 2; + + m_BezelTop = m_BezelLeft = m_BezelBottom = m_BezelRight = 0; + m_BezelTopH = m_BezelLeftW = m_BezelBottomH = m_BezelRightW = 0; + + CalcScreenCoords(); +} + +VTTDockVid::~VTTDockVid() +{ +} + +/* +================================================================= +Clear: This routine clears the "LCD" +================================================================= +*/ +void VTTDockVid::Clear(void) +{ + int x,y; + + memset(pixdata, 0, 200*480); + + m_CurX = m_CurY = 0; + redraw(); + Fl::check(); +} + +/* +================================================================= +drawpixel: This routine is called by the system to draw a single + black pixel on the "LCD". +================================================================= +*/ +// Draw the black pixels on the LCD +__inline void VTTDockVid::drawpixel(int x, int y, int color) +{ + // Check if the pixel color is black and draw if it is + if (color) + { + fl_rectf(x*MultFact + gXoffset,y*MultFact + gYoffset, + gRectsize, gRectsize); + } +} + +/* +======================================================= +Calculate the xoffset, yoffset, border locations, etc. +======================================================= +*/ +void VTTDockVid::CalcScreenCoords(void) +{ + // Calculatet the pixel rectangle size + ::gRectsize = MultFact; + if (::gRectsize == 0) + ::gRectsize = 1; + + // Calculate xoffset and yoffset + if (Fullscreen) + { + ::gXoffset = parent()->w() / 2 - 240 * MultFact; + ::gYoffset = (parent()->h() - MENU_HEIGHT - 20 - 200 * MultFact) / 3 + MENU_HEIGHT+1; + } + else + { + ::gXoffset = 5; + ::gYoffset = MENU_HEIGHT+5; + } + + gRectsize = ::gRectsize; + gXoffset = ::gXoffset; + gYoffset = ::gYoffset; + + // If the display is framed, then calculate the frame coords + + if (DisplayMode && 0) + { + // Calculate the Bezel location + int wantedH = 20; + int wantedW = 40; +// int topH, bottomH, leftW, rightW; + int bottomSpace; + int rightSpace; + + // Calculate the top height of the Bezel + m_HasTopChassis = TRUE; + if (gYoffset-1 - MENU_HEIGHT-1 >= wantedH + 5) + m_BezelTopH = wantedH; + else + { + // Test if there's room for both Bezel and chassis detail + if (gYoffset > 6) + m_BezelTopH = gYoffset - MENU_HEIGHT - 1 - 6; + else + { + m_BezelTopH = gYoffset - MENU_HEIGHT - 1 - 1; + m_HasTopChassis = FALSE; + } + } + m_BezelTop = gYoffset - m_BezelTopH - 1; + + // Calculate the bottom height of the Bezel + m_BezelBottom = gYoffset + 200 * MultFact + 1; + bottomSpace = parent()->h() - m_BezelBottom - 20; + m_HasBottomChassis = TRUE; + if (bottomSpace >= wantedH + 5) + m_BezelBottomH = wantedH; + else + { + m_BezelBottomH = bottomSpace; + m_HasBottomChassis = FALSE; + } + + // Calculate the left Bezel border width + m_HasLeftChassis = TRUE; + if (gXoffset-1 >= wantedW + 5) + m_BezelLeftW = wantedW; + else + { + // Test if there's room for Bezel plus chassis + if (gXoffset > 6) + m_BezelLeftW = gXoffset - 6; + else + { + m_BezelLeftW = gXoffset - 1; + m_HasLeftChassis = FALSE; + } + } + m_BezelLeft = gXoffset - m_BezelLeftW - 1; + + // Calculate the Bezel right width + m_BezelRight = gXoffset + 240 * MultFact + 1; + rightSpace = w() - m_BezelRight; + m_HasRightChassis = TRUE; + if (rightSpace >= wantedW + 5) + m_BezelRightW = wantedW; + else + { + // Test if there's room for Bezel plus chassis + if (rightSpace > 5) + m_BezelRightW = rightSpace - 5; + else + { + m_BezelRightW = rightSpace; + m_HasRightChassis = FALSE; + } + } + } +} + +/* +================================================================= +draw_static: This routine draws the static portions of the LCD, + such as erasing the background, drawing function + key labls, etc. +================================================================= +*/ +void VTTDockVid::draw_static() +{ + int c; + int width; + int x_pos, inc, start, y_pos; + int xl_start, xl_end, xr_start, xr_end; + int num_labels; + + // Draw gray "screen" + fl_color(m_BackgroundColor); + fl_rectf(x(),y(),w(),h()); + + return; + + /* Check if the user wants the display "framed" */ + if (DisplayMode == 1) + { + // Color for outer border + fl_color(m_DetailColor); + + // Draw border along the top + if (m_HasTopChassis) + fl_rectf(x(),y(),w(),m_BezelTop - MENU_HEIGHT - 1); + + // Draw border along the bottom + if (m_HasBottomChassis) + fl_rectf(x(),m_BezelBottom + m_BezelBottomH,w(),parent()->h() - m_BezelBottom - m_BezelBottomH - 20); + + // Draw border along the left + if (m_HasLeftChassis) + fl_rectf(x(),y(),m_BezelLeft,h()); + + // Draw border along the right + if (m_HasRightChassis) + fl_rectf(m_BezelRight + m_BezelRightW,y(),w()-m_BezelRight,h()); + + + // Color for inner border + fl_color(m_FrameColor); + + // Draw border along the top + if (m_BezelTopH > 0) + fl_rectf(m_BezelLeft,m_BezelTop,m_BezelRight - m_BezelLeft + m_BezelRightW,m_BezelTopH); + + // Draw border along the bottom + if (m_BezelBottomH > 0) + fl_rectf(m_BezelLeft,m_BezelBottom,m_BezelRight - m_BezelLeft + m_BezelRightW,m_BezelBottomH); + + // Draw border along the left + if (m_BezelLeftW > 0) + fl_rectf(m_BezelLeft, m_BezelTop, m_BezelLeftW, m_BezelBottom - m_BezelTop + m_BezelBottomH); + + // Draw border along the right + if (m_BezelRightW > 0) + fl_rectf(m_BezelRight,m_BezelTop, m_BezelRightW, m_BezelBottom - m_BezelTop + m_BezelBottomH); + + +#ifdef ZIPIT_Z2 + width = 320; +#else + width = 240 * MultFact; +#endif + num_labels = gModel == MODEL_PC8201 ? 5 : 8; + inc = width / num_labels; + start = gXoffset + width/16 - 2 * (5- (MultFact > 5? 5 : MultFact)); + fl_color(m_LabelColor); + fl_font(FL_COURIER,12); + char text[3] = "F1"; +// y_pos = h()+20; + y_pos = m_BezelBottom + 13; //y()+DispHeight*MultFact+40; + xl_start = 2*MultFact; + xl_end = 7*MultFact; + + xr_start = 12 + 2*MultFact; + xr_end = 12 + 7*MultFact; + + // Draw function key labels + for (c = 0; c < num_labels; c++) + { + // Draw text + x_pos = start + inc*c; + text[1] = c + '1'; + fl_draw(text, x_pos, y_pos); + + if (MultFact != 1) + { + // Draw lines to left + fl_line(x_pos - xl_start, y_pos-2, x_pos - xl_end, y_pos-2); + fl_line(x_pos - xl_start, y_pos-7, x_pos - xl_end, y_pos-7); + fl_line(x_pos - xl_end, y_pos-2, x_pos - xl_end, y_pos-7); + + // Draw lines to right + fl_line(x_pos + xr_start, y_pos-2, x_pos + xr_end, y_pos-2); + fl_line(x_pos + xr_start, y_pos-7, x_pos + xr_end, y_pos-7); + fl_line(x_pos + xr_end, y_pos-2, x_pos + xr_end, y_pos-7); + } + } + } +} + +/* +================================================================= +draw: This routine draws the entire LCD. This is a member + function of Fl_Window. +================================================================= +*/ +void VTTDockVid::draw() +{ + /* Draw static background stuff */ + draw_static(); + + /* Draw the pixels */ + draw_pixels(); +} + +/* +================================================================= +draw_pixels: This routine draws the pixels on the display. +================================================================= +*/ +void VTTDockVid::draw_pixels() +{ + int x=0; + int y=0; + int line, col; + uchar value; + int lastColor = -1; + int color; + + window()->make_current(); + + for (line = 0; line < 200; line++) + { + for (x = 0; x < 480; x++) + { + value = pixdata[line][x]; + //y = line << 3; + + // Erase line so it is grey, then fill in with black where needed + if ((line & 0x07) == 0) + { + fl_color(m_BackgroundColor); + fl_rectf(x*MultFact + gXoffset,line*MultFact + + gYoffset,gRectsize,8*MultFact); + } + if (value == 0) + continue; + + // Draw the black pixels + //if (value) + { + color = m_Colors[value]; + //if (color != lastColor) + { + fl_color(color); + lastColor = color; + } + drawpixel(x,line,1); + } + } + } +} + +/* +================================================================================ +SetByte: Updates the LCD with a byte of data as written from the I/O + interface from the 8085. +================================================================================ +*/ +void VTTDockVid::SetByte(int line, int col, uchar value) +{ + int y; + + if (line > 24 || col > 479) + return; + if (line < 0 || col < 0) + return; + + // Check if LCD already has the value being requested + //if (pixdata[line][col] == value) + // return; + + // Load new value into lcd "RAM" + y = line << 3; + //pixdata[line][col] = value; + + pixdata[y++][col] = value&0x01 ? m_Color : 0; + pixdata[y++][col] = value&0x02 ? m_Color : 0; + pixdata[y++][col] = value&0x04 ? m_Color : 0; + pixdata[y++][col] = value&0x08 ? m_Color : 0; + pixdata[y++][col] = value&0x10 ? m_Color : 0; + pixdata[y++][col] = value&0x20 ? m_Color : 0; + pixdata[y++][col] = value&0x40 ? m_Color : 0; + pixdata[y++][col] = value&0x80 ? m_Color : 0; + + // Calcluate y position of byte + y = line << 3; + + // Set the display + window()->make_current(); + + fl_color(m_BackgroundColor); + fl_rectf(col*MultFact + gXoffset, y*MultFact + + gYoffset, gRectsize,MultFact<<3); + + if (value == 0) + return; + + fl_color(m_Colors[m_Color]); + + for (y = line << 3; y < (line+1) << 3; y++) + drawpixel(col,y,pixdata[y][col]); +} + +/* +================================================================================ +WriteData: Routine that receives data from the VDock interface when the + Model T sends data / commands to our device ID. +================================================================================ +*/ +void VTTDockVid::WriteData(uchar data) +{ + int line, col, y; + int color; + +#if 0 + if (m_EscSeq) + { + printf("%c(%02x), X=%d, Y=%d\n", data, data, m_CurX, m_CurY); + } + else if (data == 0x1B) + printf("ESC "); +#if 1 + else if (data <= ' ') + printf("%02X, X=%d, Y=%d\n", data, m_CurX, m_CurY); + else + printf("%c, X=%d, Y=%d\n", data, m_CurX, m_CurY); +#endif +#endif + + window()->make_current(); + + /* Test if we are processing an ESC Sequence */ + if (m_EscSeq) + { + /* Add the byte to the escape sequence */ + m_EscData[m_EscSeq++ - 1] = data; + + /* Test if time to process the ESC sequence */ + if (m_EscData[0] == 'Y') + { + //printf("ESCY:%d\n", m_EscSeq); + if (m_EscSeq == 4) + { + /* Process the cursor position sequence */ + m_CurX = (m_EscData[2] - 0x20) * 6; + if (m_Width == 40) + m_CurX <<= 1; + m_CurY = (m_EscData[1] - 0x20) * 8; + if (m_CurX < 0) + m_CurX = 0; + if (m_CurY < 0) + m_CurY = 0; + if (m_CurX > 474) + m_CurX = 474; + if (m_CurY > 192) + m_CurY = 192; + m_EscSeq = 0; + } + } + else if (m_EscData[0] == ESC_SET_COLOR) + { + if (m_EscSeq == 3) + { + m_Color = (unsigned char) m_EscData[1]; + m_EscSeq = 0; + } + } + else if ((m_EscData[0] == ESC_SET_COLOR_NAME) || m_EscData[0] == ESC_SET_BG_NAME) + { + if (data == 0x0A) + { + /* Do a color name lookup */ + /* First remove the 0D and 0A */ + m_EscSeq -= 2; + while (m_EscData[m_EscSeq] == 0x0D || m_EscData[m_EscSeq] == 0x0A) + { + m_EscData[m_EscSeq--] = 0; + } + + color = FindColorByName(&m_EscData[1]); + if (color != -1) + { + if (m_EscData[0] == ESC_SET_COLOR_NAME) + m_Color = gNamedColors[color].cid; + else + { + m_BackgroundColor = fl_rgb_color(gNamedColors[color].red, + gNamedColors[color].green, gNamedColors[color].blue); + m_Colors[0] = m_BackgroundColor; + redraw(); + Fl::check(); + } + } + m_EscSeq = 0; + } + } + else + { + /* Process the escape code */ + switch (m_EscData[0]) + { + /* Turn Cursor ON */ + case ESC_CURSOR_ON: + if (m_Cursor == 1) + break; + + /* Turn cursor on */ + m_Cursor = 1; + if (m_CurY >= 200) + Scroll(); + XorCursor(); + break; + + /* Turn Cursor OFF */ + case ESC_CURSOR_OFF: + if (m_Cursor == 0) + break; + + /* Turn cursor off */ + m_Cursor = 0; + XorCursor(); + break; + + /* Test for Home Cursor */ + case ESC_CURSOR_HOME: + m_CurX = m_CurY = 0; + break; + + /* Test for Erase to EOL */ + case ESC_ERASE_EOL: + case ESC_CLEAR_EOL: + line = m_CurY >> 3; + for (col = m_CurX; col < 480; col++) + SetByte(line, col, 0); + break; + + case ESC_ERASE_SCREEN: + Clear(); + break; + + case ESC_ERASE_LINE: + line = m_CurY >> 3; + for (col = 0; col < 480; col++) + SetByte(line, col, 0); + break; + + case ESC_INS_LINE: + for (y = 199; y > m_CurY+8; y--) + //for (line = 24; line > (m_CurY >> 3); line--) + { + for (col = 0; col < 480; col++) + { + //SetByte(line, col, pixdata[line-1][col]); + pixdata[y][col] = pixdata[y-8][col]; + fl_color(m_Colors[pixdata[y][col]]); + drawpixel(col, y, 1); + } + } + line = m_CurY >> 3; + for (col = 0; col < 480; col++) + SetByte(line, col, 0); + break; + + case ESC_DEL_LINE: + for (y = m_CurY; y < 200-8; y++) + //for (line = m_CurY >> 3; line < 24; line++) + { + for (col = 0; col < 480; col++) + { + //SetByte(line, col, pixdata[line+1][col]); + pixdata[y][col] = pixdata[y+8][col]; + fl_color(m_Colors[pixdata[y][col]]); + drawpixel(col, y, 1); + } + } + + for (col = 0; col < 480; col++) + SetByte(24, col, 0); + break; + + case ESC_CURSOR_UP: + m_CurY -= 8; + break; + + case ESC_CURSOR_DOWN: + m_CurY += 8; + break; + + case ESC_CURSOR_LEFT: + if (m_Width == 40) + m_CurX -= 12; + else + m_CurX -= 6; + break; + + case ESC_CURSOR_RIGHT: + if (m_Width == 40) + m_CurX += 12; + else + m_CurX += 6; + break; + + case ESC_START_REVERSE: + m_Reverse = 1; + break; + + case ESC_END_REVERSE: + m_Reverse = 0; + break; + + case ESC_LOCK_DISPLAY: + /* Not sure we need this */ + m_Locked = 1; + break; + + case ESC_UNLOCK_DISPLAY: + m_Locked = 0; + break; + + case ESC_WIDTH_40: + Clear(); + m_Width = 40; + break; + + case ESC_WIDTH_80: + Clear(); + m_Width = 80; + break; + + case ESC_HELP: + m_EscSeq = 0; + Help(); + break; + + /* Not sure what this ESC does exactly */ + case 0x58: + break; + + default: + printf("ESC %02x\n", m_EscData[0]); + break; + } + + m_EscSeq = 0; + } + } + else if (data == 0x1B) + { + m_EscSeq = 1; + } + + /* Test for CLS */ + else if (data == 0x0C) + { + Clear(); + } + + /* Test for TAB */ + else if (data == 0x09) + { + } + + /* Test for BKSP */ + else if (data == 0x08) + { + if (m_CurX > 0) + { + if (m_Width == 40) + m_CurX -= 12; + else + m_CurX -= 6; + } + else + { + if (m_Width == 40) + m_CurX = 240-12; + else + m_CurX = 240-6; + m_CurY -= 8; + } + } + + /* Test for DEL. Nothing to do really */ + else if (data == 0x7F) + { + } + + /* Test for CR */ + else if (data == 0x0D) + { + /* Go to start of line */ + m_CurX = 0; + } + + /* Test for "HOME" cursor */ + else if (data == 0x0B) + { + m_CurX = m_CurY = 0; + } + + /* Test for End of Document */ + else if (data == 0x1A) + { + } + + /* Test for LF */ + else if (data == 0x0A) + { + /* Go to next line */ + m_CurY += 8; + } + + else if (data < ' ') + { + printf("Unhandled %0X\n", data); + } + + /* Draw the received byte */ + else //if (data >= ' '); + { + int addr, line, y, c, mem_index, column, color, lastcolor = -1; + + if (m_CurY >= 200) + Scroll(); + + addr = gStdRomDesc->sCharTable; + if (data > 127) + mem_index = addr + (128 - ' ') * 5 + (data - 128)*6; + else + mem_index = addr + (data - ' ') * 5; + + column = m_CurX; + line = m_CurY / 8; + + /* Draw the byte */ + for (c = 0; c < 5; c++) + { + if (m_Reverse) + { + if (m_Width == 40) + { + SetByte(line, column, ~gSysROM[mem_index]); + column++; + } + SetByte(line, column, ~gSysROM[mem_index++]); + } + else + { + if (m_Width == 40) + { + SetByte(line, column, gSysROM[mem_index]); + column++; + } + SetByte(line, column, gSysROM[mem_index++]); + } + column++; + } + + /* Now draw space between chars if needed */ + if (data > 127) + { + if (m_Reverse) + { + if (m_Width == 40) + { + SetByte(line, column, ~gSysROM[mem_index]); + } + SetByte(line, column, ~gSysROM[mem_index++]); + } + else + { + if (m_Width == 40) + { + SetByte(line, column, gSysROM[mem_index]); + } + SetByte(line, column, gSysROM[mem_index++]); + } + } + else + { + if (m_Reverse) + { + if (m_Width == 40) + SetByte(line, column, 0xFF); + SetByte(line, column, 0xFF); + } + else + { + if (m_Width == 40) + SetByte(line, column, 0x0); + SetByte(line, column, 0); + } + } + + /* Advance to the next character */ + if (m_Width == 40) + m_CurX += 12; + else + m_CurX += 6; + + if (m_CurX >= 480) + { + m_CurX = 0; + m_CurY += 8; + } + + /* Draw cursor if it is on */ + if (m_Cursor) + { + XorCursor(); + } + } +} + +void VTTDockVid::XorCursor(void) +{ + int line = m_CurY >> 3; + int col = m_CurX; + int num, x,y; + + if (m_CurY > 192) + return; + + if (m_Width == 40) + num = 12; + else + num = 6; + + window()->make_current(); + + for (x = 0; x < num; x++) + { + for (y = m_CurY; y < m_CurY + 8; y++) + { + pixdata[y][col] = ~pixdata[y][col]; + fl_color(m_Colors[pixdata[y][col]]); + drawpixel(col,y,1); + } + col++; + } +} + +void VTTDockVid::Scroll(void) +{ + int y, col, color, lastcolor; + + /* Test if at bottom of display */ + if (m_CurY >= 200) + { + /* We need to perform a scroll */ + for (y = 8; y < 200; y++) + //for (line = 1; line < 25; line++) + { + for (col = 0; col < 480; col++) + { + color = pixdata[y][col]; + if (color != 0 || pixdata[y-8][col] != 0) + { + pixdata[y-8][col] = color; + if (lastcolor != color) + { + fl_color(m_Colors[color]); + lastcolor = color; + } + drawpixel(col,y-8,1); + } + //if (pixdata[line][col] != 0 || pixdata[line-1][col] != 0) + // SetByte(line-1, col, pixdata[line][col]); + } + } + + /* Now zero out the bottom line */ + for (col = 0; col < 480; col++) + { + SetByte(24,col,0); + } + + m_CurY -= 8; + + Fl::check(); + } +} + +int VTTDockVid::handle(int event) +{ + int key; + + return gpDisp->handle(event); +} + +int VTTDockVid::FindColorByName(char *pName) +{ + int x; + + /* Search all named colors for a match */ + for (x = 0; x < gColorCount; x++) + { + if (strcasecmp(gNamedColors[x].pName, pName) == 0) + { + return x; + } + } + + return -1; +} + +void VTTDockVid::Help(void) +{ + int x, c, len; + + Clear(); + + /* Display all named colors */ + for (x = 0; x < gColorCount; x++) + { + len = strlen(gNamedColors[x].pName); + if (m_CurX + len*6 > 480) + { + WriteData(0x0D); + WriteData(0x0A); + } + + for (c = 0; c < len; c++) + WriteData(gNamedColors[x].pName[c]); + if (x+1 != gColorCount) + { + if (m_CurX != 0) + WriteData(','); + if (m_CurX != 0) + WriteData(' '); + } + } +} + diff --git a/src/tdockvid.h b/src/tdockvid.h new file mode 100644 index 0000000..e20e1f5 --- /dev/null +++ b/src/tdockvid.h @@ -0,0 +1,144 @@ +/* tdockvid.h */ + +/* $Id$ */ + +/* + * Copyright 2015 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef _TDOCKVID_H_ +#define _TDOCKVID_H_ + +#ifndef MENU_HEIGHT +#define MENU_HEIGHT 32 +#endif + +#ifndef TAB_HEIGHT +#define TAB_HEIGHT 24 +#endif + +#ifdef __cplusplus + +#define ESC_ERASE_SCREEN 0x6A /* j */ +#define ESC_ERASE_EOL 0x4B /* K */ +#define ESC_CLEAR_EOL 0x4A /* J */ +#define ESC_ERASE_LINE 0x6C /* l */ +#define ESC_INS_LINE 0x4C /* L */ +#define ESC_DEL_LINE 0x4D /* M */ +#define ESC_CURS_POS 0x59 /* Y */ +#define ESC_CURSOR_UP 0x41 /* A */ +#define ESC_CURSOR_DOWN 0x42 /* B */ +#define ESC_CURSOR_RIGHT 0x43 /* C */ +#define ESC_CURSOR_LEFT 0x44 /* D */ +#define ESC_CURSOR_HOME 0x48 /* H */ +#define ESC_START_REVERSE 0x70 /* p */ +#define ESC_END_REVERSE 0x71 /* q */ +#define ESC_CURSOR_ON 0x50 /* P */ +#define ESC_CURSOR_OFF 0x51 /* Q */ +#define ESC_SET_SYS_LINE 0x54 /* T */ +#define ESC_RESET_SYS_LINE 0x55 /* U */ +#define ESC_LOCK_DISPLAY 0x56 /* V */ +#define ESC_UNLOCK_DISPLAY 0x57 /* W */ +#define ESC_WIDTH_40 0x63 /* c */ +#define ESC_WIDTH_80 0x64 /* d */ +#define ESC_SET_COLOR 0x65 /* e */ +#define ESC_SET_COLOR_NAME 0x66 /* f */ +#define ESC_SET_BG_NAME 0x67 /* g */ +#define ESC_HELP 0x68 /* h */ + +//#include +//#include + +class VTTDockVid : public Fl_Widget +{ +public: + VTTDockVid(int x, int y, int w, int h); + ~VTTDockVid(); + + virtual void WriteData(unsigned char data); + + virtual void Clear(void); + + int MultFact; + int DisplayMode; + int SolidChars; + int DispHeight; + + int gRectsize; + int gXoffset; + int gYoffset; + int m_BezelTop; + int m_BezelLeft; + int m_BezelBottom; + int m_BezelRight; + int m_BezelTopH; + int m_BezelBottomH; + int m_BezelLeftW; + int m_BezelRightW; + int m_HasTopChassis; + int m_HasBottomChassis; + int m_HasLeftChassis; + int m_HasRightChassis; + + int m_FrameColor; + int m_DetailColor; + int m_BackgroundColor; + int m_PixelColor; + int m_LabelColor; + + char m_HaveMouse; + +protected: + virtual void draw(); + void draw_pixels(); + void SetByte(int line, int col, uchar value); + void CalcScreenCoords(void); + int FindColorByName(char *pName); + void XorCursor(void); + void Help(void); + void Scroll(void); + __inline void drawpixel(int x, int y, int color); + virtual void draw_static(); + virtual int handle(int event); + + int m_MyFocus; + uchar pixdata[200][480]; + + int m_CurX, m_CurY; + int m_Cursor; + int m_Reverse; + int m_Locked; + int m_Width; + int m_Colors[256]; + unsigned int m_Color; + + int m_EscSeq; /* Non zero for ESC sequence. # Bytes RX otherwise */ + char m_EscData[256]; /* Chars RX after the ESC */ + +}; + +#endif + +#endif diff --git a/src/tpddserver.h b/src/tpddserver.h index 9c884a1..2ce4291 100644 --- a/src/tpddserver.h +++ b/src/tpddserver.h @@ -110,7 +110,7 @@ typedef struct VT_NADSCmd #define TPDD_REQ_SET_EXTENDED 0x0B #define TPDD_REQ_QUERY_EXTENDED 0x0E #define TPDD_REQ_CONDENSED_LIST 0x0F -#define TPDD_REQ_LAST_OPCODE 0x0F +#define TPDD_REQ_LAST_OPCODE 0x0D #define TPDD_REQ_TSDOS_MYSTERY23 0x23 #define TPDD_REQ_TSDOS_MYSTERY31 0x31 @@ -121,7 +121,7 @@ typedef struct VT_NADSCmd #define TPDD_REQ_SET_EXTENDED 0x0B #define TPDD_REQ_QUERY_EXTENDED 0x0E #define TPDD_REQ_CONDENSED_LIST 0x0F -#define TPDD_REQ_LAST_OPCODE 0x0F +//#define TPDD_REQ_LAST_OPCODE 0x0F // Define OPEN mode constants here #define TPDD_OPEN_MODE_WRITE 0x01 From 49056dbdf45d76f30e4f549347fa8aae2a6eed51 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 24 Feb 2015 23:41:16 +0000 Subject: [PATCH 269/327] Added support for Steve Adolph's QUAD 128K Banked RAM module for M100. --- release.txt | 4 ++ src/display.cpp | 43 +++++++++++++++-- src/display.h | 1 + src/io.c | 12 +++++ src/memedit.cpp | 51 +++++++++++++-------- src/memory.c | 119 ++++++++++++++++++++++++++++++++++++++++++++---- src/memory.h | 2 + src/setup.cpp | 97 +++++++++++++++++++++++++++++++-------- src/setup.h | 4 +- 9 files changed, 284 insertions(+), 49 deletions(-) diff --git a/release.txt b/release.txt index 9dea394..7a29905 100644 --- a/release.txt +++ b/release.txt @@ -25,6 +25,10 @@ v1.7 Not released yet 7. Updated the GNUMakefile to include libjpeg and libpng. +8. Added support for Steve Adolph's QUAD Model 100 128K Banked RAM module. + +9. Added right-click menu support to easily change QUAD bank when enabled. + ==================== v1.6 April 24, 2014 ==================== diff --git a/src/display.cpp b/src/display.cpp index 2c9da6f..ffc3444 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -85,6 +85,7 @@ extern int gMaintCount; extern int gOsDelay; extern int gInMsPlanROM; extern int gDelayUpdateKeys; +extern unsigned char gQuad; void set_target_frequency(int freq); void memory_monitor_cb(void); } @@ -1275,6 +1276,14 @@ void cb_menu_fkey (Fl_Widget* w, void* key) } } +void cb_menu_bank (Fl_Widget* w, void* key) +{ + int bank = atoi((char *) key); + + set_ram_bank(bank); + resetcpu(); +} + Fl_Menu_Item gCopyCutMenu[] = { { " Copy ", 0, cb_select_copy, 0, 0 }, { " Cut ", 0, cb_select_cut, 0, FL_MENU_DIVIDER }, @@ -1290,6 +1299,18 @@ Fl_Menu_Item gLeftClickMenu[] = { { 0 } }; +Fl_Menu_Item gLeftClickQuadMenu[] = { + { " Paste ", 0, cb_menu_fkey, (void *) (FL_F + 11), FL_MENU_DIVIDER }, + { " Label ", 0, cb_menu_fkey, (void *) (FL_F + 9), 0 }, + { " Print ", 0, cb_menu_fkey, (void *) (FL_F + 10), 0 }, + { " Pause ", 0, cb_menu_fkey, (void *) (FL_F + 12), FL_MENU_DIVIDER }, + { " Bank 1 ", 0, cb_menu_bank, (void *) "0", 0 }, + { " Bank 2 ", 0, cb_menu_bank, (void *) "1", 0 }, + { " Bank 3 ", 0, cb_menu_bank, (void *) "2", 0 }, + { " Bank 4 ", 0, cb_menu_bank, (void *) "3", 0 }, + { 0 } +}; + Fl_Menu_Item menuitems[] = { { "&File", 0, 0, 0, FL_SUBMENU }, { "Load file from HD", 0, cb_LoadFromHost, 0 }, @@ -1631,11 +1652,18 @@ T100_Disp::T100_Disp(int x, int y, int w, int h) : m_LeftClick->type(0); m_LeftClick->callback(cb_leftclick_cancel); m_LeftClick->hide(); + + m_LeftClickQuad = new Fl_Menu_Button(x, y, w, h, "Action"); + m_LeftClickQuad->menu(gLeftClickQuadMenu); + m_LeftClickQuad->type(0); + m_LeftClickQuad->callback(cb_leftclick_cancel); + m_LeftClickQuad->hide(); } T100_Disp::~T100_Disp() { delete m_LeftClick; + delete m_LeftClickQuad; delete m_CopyCut; } @@ -3487,9 +3515,18 @@ int T100_Disp::handle(int event) m_HaveMouse = TRUE; if (Fl::event_button3()) { - m_LeftClick->type(Fl_Menu_Button::POPUP123); - m_LeftClick->popup(); - m_LeftClick->type(0); + if (gModel == MODEL_M100 && gQuad) + { + m_LeftClickQuad->type(Fl_Menu_Button::POPUP123); + m_LeftClickQuad->popup(); + m_LeftClickQuad->type(0); + } + else + { + m_LeftClick->type(Fl_Menu_Button::POPUP123); + m_LeftClick->popup(); + m_LeftClick->type(0); + } take_focus(); return 1; } diff --git a/src/display.h b/src/display.h index d648761..6525596 100644 --- a/src/display.h +++ b/src/display.h @@ -127,6 +127,7 @@ class T100_Disp : public Fl_Widget int m_WheelKeyDown; class Fl_Menu_Button* m_CopyCut; class Fl_Menu_Button* m_LeftClick; + class Fl_Menu_Button* m_LeftClickQuad; char m_SimulatedCtrl; char m_SelectComplete; char m_HaveMouse; diff --git a/src/io.c b/src/io.c index 29ca677..1885ab5 100644 --- a/src/io.c +++ b/src/io.c @@ -86,6 +86,7 @@ int gDelayUpdateKeys = 0; int gDelayCount = 0; extern uchar clock_serial_out; extern int gRomBank; +extern uchar gQuad; int gTDock = 1; extern RomDescription_t *gStdRomDesc; void handle_wheel_keys(void); @@ -371,6 +372,9 @@ void show_remem_mode(void) } /* Not in ReMem emulation mode */ + if (gQuad) + return; + display_map_mode(""); } @@ -401,6 +405,14 @@ void out(uchar port, uchar val) case 0x23: break; + case QUAD_BANK_PORT: + if (gModel == MODEL_M100 && gQuad) + { + /* Set the QUAD RAM bank */ + set_ram_bank(val & 0x03); + } + break; + case REMEM_MODE_PORT: /* ReMem Mode port */ case REMEM_SECTOR_PORT: /* ReMem Sector access port */ case REMEM_DATA_PORT: /* ReMem Data Port */ diff --git a/src/memedit.cpp b/src/memedit.cpp index 364ed6c..075a0cd 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -54,6 +54,7 @@ extern "C" #include "intelhex.h" extern int gRamBottom; +extern uchar gQuad; } void cb_Ide(Fl_Widget* w, void*); @@ -378,7 +379,7 @@ void load_file_to_mem(const char *filename, int address) // Adjust address if writing to RAM region region = memedit_ctrl.pMemEdit->GetRegionEnum(); if ((region == REGION_RAM) || (region == REGION_RAM1) || (region == REGION_RAM2) || - (region == REGION_RAM3)) + (region == REGION_RAM3) || (region == REGION_RAM4)) address -= RAMSTART; // Check for hex file @@ -445,7 +446,7 @@ void save_mem_to_file(const char *filename, int address, int count, int save_as_ // Adjust address if writing from RAM region = memedit_ctrl.pMemEdit->GetRegionEnum(); if ((region == REGION_RAM) || (region == REGION_RAM1) || (region == REGION_RAM2) || - (region == REGION_RAM3)) + (region == REGION_RAM3) || (region == REGION_RAM4)) address -= RAMSTART; // Check for hex file @@ -1296,7 +1297,15 @@ void T100_MemEditor::SetRegionOptions(void) case MODEL_KC85: case MODEL_M102: case MODEL_M10: - memedit_ctrl.pRegion->add("RAM"); + if (gQuad) + { + memedit_ctrl.pRegion->add("RAM 1"); + memedit_ctrl.pRegion->add("RAM 2"); + memedit_ctrl.pRegion->add("RAM 3"); + memedit_ctrl.pRegion->add("RAM 4"); + } + else + memedit_ctrl.pRegion->add("RAM"); memedit_ctrl.pRegion->add("ROM"); memedit_ctrl.pRegion->add("Opt ROM"); memedit_ctrl.pRegion->value(0); @@ -1483,6 +1492,10 @@ int T100_MemEditor::GetRegionEnum(void) if (strcmp(reg_text, "RAM 3") == 0) m_Region = REGION_RAM3; + // Test if RAM 4 region is selecte + if (strcmp(reg_text, "RAM 4") == 0) + m_Region = REGION_RAM4; + // Test if ROM region is selected if (strcmp(reg_text, "ROM") == 0) m_Region = REGION_ROM; @@ -1557,7 +1570,7 @@ void T100_MemEditor::UpdateDispMem(void) get_memory8_ext(m_Region, m_FirstAddress, count, mem); addrBase = 0; if ((m_Region == REGION_RAM) || (m_Region == REGION_RAM2) || - (m_Region == REGION_RAM3) || m_Region == REGION_RAM1) + (m_Region == REGION_RAM3) || m_Region == REGION_RAM1 || (m_Region == REGION_RAM4)) addrBase = ROMSIZE; // Set the display @@ -1747,7 +1760,7 @@ void T100_MemEditor::draw() break; fl_color(m_colors.addr); if ((region == REGION_RAM) || (region == REGION_RAM2) || - (region == REGION_RAM3) || region == REGION_RAM1) + (region == REGION_RAM3) || region == REGION_RAM1 || (region == REGION_RAM4)) { sprintf(string, "%06X ", addr + RAMSTART); actualAddr += RAMSTART; @@ -2203,7 +2216,7 @@ int T100_MemEditor::handle(int event) // Set or clear the Undo based on availablilty int count = sizeof(gDeleteMarkerMenu) / sizeof(Fl_Menu_Item); int region = m_Region; - if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3 || (region == REGION_RAM4)) region = REGION_RAM; if (m_pUndoDeleteMarkers[region] == NULL) { @@ -2739,7 +2752,7 @@ int T100_MemEditor::handle(int event) actualAddr = address; if ((m_Region == REGION_RAM) || (m_Region == REGION_RAM2) || - (m_Region == REGION_RAM3) || m_Region == REGION_RAM1) + (m_Region == REGION_RAM3) || m_Region == REGION_RAM1 || (m_Region == REGION_RAM4)) actualAddr += ROMSIZE; // Determine if this is the first keystroke at this address @@ -2909,7 +2922,7 @@ int T100_MemEditor::handle(int event) address += m_CursorRow * 16; actualAddr = address; if ((m_Region == REGION_RAM) || (m_Region == REGION_RAM2) || - (m_Region == REGION_RAM3) || m_Region == REGION_RAM1) + (m_Region == REGION_RAM3) || m_Region == REGION_RAM1 || (m_Region == REGION_RAM4)) actualAddr += ROMSIZE; address += col; @@ -3130,7 +3143,7 @@ void T100_MemEditor::MoveTo(int address) the ROM size from the address so we jump to the right location in the scroll bar */ if ((m_Region == REGION_RAM) || (m_Region == REGION_RAM2) || - (m_Region == REGION_RAM3) || m_Region == REGION_RAM1) + (m_Region == REGION_RAM3) || m_Region == REGION_RAM1 || (m_Region == REGION_RAM4)) address -= ROMSIZE; /* Calculate line value */ @@ -3226,7 +3239,7 @@ int T100_MemEditor::HasMarker(int address) // we use the REGION_RAM marker so they all have the same // set of markers region = m_Region; - if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3 || (region == REGION_RAM4)) region = REGION_RAM; // Get pointer to start of marker list @@ -3379,7 +3392,7 @@ void T100_MemEditor::UpdateAddressText() region = GetRegionEnum(); if ((region == REGION_RAM) || (region == REGION_RAM2) || - (region == REGION_RAM3) || region == REGION_RAM1) + (region == REGION_RAM3) || region == REGION_RAM1 || (region == REGION_RAM4)) { if (gReMem) sprintf(string, "0x%06X", (unsigned int) (address + RAMSTART)); @@ -4121,7 +4134,7 @@ void T100_MemEditor::AddMarker(int region) if (region == -1) { region = m_Region; - if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3 || (region == REGION_RAM4)) region = REGION_RAM; } @@ -4253,7 +4266,7 @@ void T100_MemEditor::FindNextMarker(void) // we use the REGION_RAM marker so they all have the same // set of markers region = m_Region; - if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3 || (region == REGION_RAM4)) region = REGION_RAM; // Get pointer to start of marker list @@ -4308,7 +4321,7 @@ void T100_MemEditor::FindPrevMarker(void) // we use the REGION_RAM marker so they all have the same // set of markers region = m_Region; - if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3 || (region == REGION_RAM4)) region = REGION_RAM; // Get pointer to start of marker list @@ -4363,7 +4376,7 @@ memedit_marker_t* T100_MemEditor::GetMarker(int address) // we use the REGION_RAM marker so they all have the same // set of markers region = m_Region; - if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3 || (region == REGION_RAM4)) region = REGION_RAM; // Get pointer to start of marker list @@ -4399,7 +4412,7 @@ int T100_MemEditor::IsSelected(int address) // we use the REGION_RAM marker so they all have the same // set of markers region = m_Region; - if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3 || (region == REGION_RAM4)) region = REGION_RAM; // Get pointer to start of marker list @@ -4441,7 +4454,7 @@ void T100_MemEditor::DeleteMarker(void) // we use the REGION_RAM marker so they all have the same // set of markers region = m_Region; - if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3 || (region == REGION_RAM4)) region = REGION_RAM; // Get pointer to start of marker list @@ -4496,7 +4509,7 @@ void T100_MemEditor::DeleteAllMarkers(void) // we use the REGION_RAM marker so they all have the same // set of markers region = m_Region; - if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3 || (region == REGION_RAM4)) region = REGION_RAM; // First test if we have an existing undo delete all markers list @@ -4538,7 +4551,7 @@ void T100_MemEditor::UndoDeleteAllMarkers(void) // we use the REGION_RAM marker so they all have the same // set of markers region = m_Region; - if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3) + if (region == REGION_RAM1 || region == REGION_RAM2 || region == REGION_RAM3 || (region == REGION_RAM4)) region = REGION_RAM; // Check if we have an undo buffer for this region diff --git a/src/memory.c b/src/memory.c index 295894f..4ddb656 100644 --- a/src/memory.c +++ b/src/memory.c @@ -35,11 +35,12 @@ uchar gMsplanROM[32768]; /* MSPLAN ROM T200 Only */ extern char file[255]; int gOptRomRW = 0; /* Flag to make OptROM R/W */ -unsigned char rambanks[3*32768]; /* Model T200 & NEC RAM banks */ +unsigned char rambanks[4*32768]; /* Model T200 & NEC RAM banks */ uchar gRamBank = 0; /* Currently enabled bank */ int gRomBank = 0; /* Current ROM Bank selection */ static int gRom0Bank = 0; /* Current ROM #0 Bank for PC-8300 */ int gRomSize = 32768; /* Current ROM Size for R/O calculation */ +unsigned char gQuad = 0; /* QUAD (128K RAM bank on M100) enabled */ uchar gReMem = 0; /* Flag indicating if ReMem emulation enabled */ uchar gReMemBoot = 0; /* ALT boot flag */ @@ -258,7 +259,7 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) break; case REGION_RAM3: - // Check if RAM Bank 2 is active & copy from system memory if it is + // Check if RAM Bank 3 is active & copy from system memory if it is if (gRamBank == 2) { addr = address + RAMSTART; @@ -282,6 +283,31 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) } break; + case REGION_RAM4: + // Check if RAM Bank 4 is active & copy from system memory if it is + if (gRamBank == 3) + { + addr = address + RAMSTART; + for (c = 0; c < count; c++) + { + if (gReMem && !gRex) + data[c] = gMemory[addr>>10][addr&0x3FF]; + else + data[c] = gBaseMemory[addr]; + addr++; + } + } + else + { + if (gModel == MODEL_T200) + addr = 24576*3 + address; + else + addr = 32768*3 + address; + for (c = 0; c < count; c++) + data[c] = rambanks[addr++]; + } + break; + case REGION_RAMPAC: // Check if RamPack memory is valid if (gRampacRam == NULL) @@ -470,7 +496,7 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) break; case REGION_RAM3: - // Check if RAM Bank 2 is active & copy from system memory if it is + // Check if RAM Bank 3 is active & copy from system memory if it is if (gRamBank == 2) { addr = address + RAMSTART; @@ -494,6 +520,31 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) } break; + case REGION_RAM4: + // Check if RAM Bank 4 is active & copy from system memory if it is + if (gRamBank == 3) + { + addr = address + RAMSTART; + for (c = 0; c < count; c++) + { + if (gReMem && !gRex) + gMemory[addr>>10][addr&0x3FF] = data[c]; + else + gBaseMemory[addr] = data[c]; + addr++; + } + } + else + { + if (gModel == MODEL_T200) + addr = 24576*3 + address; + else + addr = 32768*3 + address; + for (c = 0; c < count; c++) + rambanks[addr++] = data[c]; + } + break; + case REGION_RAMPAC: // Check if RamPack memory is valid if (gRampacRam == NULL) @@ -727,7 +778,10 @@ void init_mem(void) /* Set gReMem and gRampac based on preferences */ gReMem = (mem_setup.mem_mode == SETUP_MEM_REMEM) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC); gRampac = (mem_setup.mem_mode == SETUP_MEM_RAMPAC) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC); - gRex = (mem_setup.mem_mode == SETUP_MEM_REX) ? REX : (mem_setup.mem_mode == SETUP_MEM_REX2) ? REX2 : 0; + gRex = (mem_setup.mem_mode == SETUP_MEM_REX || mem_setup.mem_mode == SETUP_MEM_REX_QUAD) ? REX : + (mem_setup.mem_mode == SETUP_MEM_REX2) ? REX2 : 0; + gQuad = (mem_setup.mem_mode == SETUP_MEM_QUAD || mem_setup.mem_mode == SETUP_MEM_REX_QUAD) ? 1 : 0; + if (gRex) { gRexModel = REX | gRex; @@ -742,12 +796,22 @@ void init_mem(void) gRamBank = 0; gRomBank = 0; + if (gQuad) + set_ram_bank(0); + // Initialize ROM size base on current model gRomSize = gModel == MODEL_T200 ? 40960 : 32768; for (c = 0; c < 65536; c++) gIndex[c] = c >> 10; + /* Zero out QUAD memory */ + if (gQuad) + { + for (c = 0; c < 65536*2; c++) + rambanks[c] = 0; + } + /* Test if ReMem emulation enabled */ if (gReMem) { @@ -1163,7 +1227,10 @@ void save_ram(void) get_emulation_path(file, gModel); /* Append the RAM filename for Base Memory emulation */ - strcat(file, "RAM.bin"); + if (gModel == MODEL_M100 && gQuad) + strcat(file, "QUAD.bin"); + else + strcat(file, "RAM.bin"); /* Open the RAM file */ fd=fopen(file, "wb+"); @@ -1176,7 +1243,13 @@ void save_ram(void) case MODEL_M10: /* M100 & M102 have single bank */ case MODEL_KC85: // JV case MODEL_M102: - fwrite(gBaseMemory+RAMSTART, 1, RAMSIZE, fd); + if (gQuad) + { + set_ram_bank(gRamBank); + fwrite(rambanks, 1, 4*RAMSIZE, fd); + } + else + fwrite(gBaseMemory+RAMSTART, 1, RAMSIZE, fd); break; case MODEL_T200: @@ -1439,6 +1512,7 @@ load_ram: This routine loads the contens of the RAM in preparation void load_ram(void) { char file[256]; + char sbank[10]; FILE *fd; int x; int readlen; @@ -1452,6 +1526,7 @@ void load_ram(void) } else { + /* Zero the base memory */ for (x = 0; x < 64; x++) gMemory[x] = 0; @@ -1459,7 +1534,13 @@ void load_ram(void) get_emulation_path(file, gModel); /* Append the RAM filename */ - strcat(file, "RAM.bin"); + if (gModel == MODEL_M100 && gQuad) + strcat(file, "QUAD.bin"); + else + { + strcat(file, "RAM.bin"); + display_map_mode(""); + } /* Open the RAM file */ fd = fopen(file, "rb+"); @@ -1473,7 +1554,16 @@ void load_ram(void) case MODEL_M10: /* M100 & M102 have single bank */ case MODEL_KC85: case MODEL_M102: - readlen = fread(gBaseMemory+RAMSTART, 1, RAMSIZE, fd); + if (gQuad) + { + gRamBank = 0; + readlen = fread(rambanks, 1, RAMSIZE*4, fd); + memcpy(&gBaseMemory[RAMSTART], &rambanks[gRamBank*32768], RAMSIZE); + sprintf(sbank, "Bank %d", gRamBank+1); + display_map_mode(sbank); + } + else + readlen = fread(gBaseMemory+RAMSTART, 1, RAMSIZE, fd); break; case MODEL_T200: @@ -1768,6 +1858,7 @@ set_ram_bank: This function sets the current RAM bank for Model T200 and */ void set_ram_bank(unsigned char bank) { + char sbank[10]; int block; if (!(gReMem && !gRex)) @@ -1775,12 +1866,24 @@ void set_ram_bank(unsigned char bank) /* Deal with Non-Remem Banks */ switch (gModel) { + case MODEL_M100: /* Moel 100 QUAD support */ + if (gQuad) + { + memcpy(&rambanks[gRamBank*RAMSIZE], &gBaseMemory[RAMSTART], RAMSIZE); + gRamBank = bank; + memcpy(&gBaseMemory[RAMSTART], &rambanks[gRamBank*RAMSIZE], RAMSIZE); + sprintf(sbank, "Bank %d", bank+1); + display_map_mode(sbank); + } + break; + case MODEL_T200: /* Model T200 RAM banks */ case MODEL_PC8201: /* NEC Laptop banks */ case MODEL_PC8300: memcpy(&rambanks[gRamBank*RAMSIZE], &gBaseMemory[RAMSTART], RAMSIZE); gRamBank = bank; memcpy(&gBaseMemory[RAMSTART], &rambanks[gRamBank*RAMSIZE], RAMSIZE); + break; } } else diff --git a/src/memory.h b/src/memory.h index 76c0206..037b845 100644 --- a/src/memory.h +++ b/src/memory.h @@ -43,6 +43,7 @@ extern "C" { #define REMEM_FLASH1_555_PORT 0x75 #define REMEM_FLASH2_AAA_PORT 0x76 #define REMEM_FLASH2_555_PORT 0x77 +#define QUAD_BANK_PORT 0x80 #define RAMPAC_SECTOR_PORT 0x81 #define RAMPAC_DATA_PORT 0x83 @@ -110,6 +111,7 @@ extern "C" { #define REGION_ROM3 13 #define REGION_ROM4 14 #define REGION_MAX 15 +#define REGION_RAM4 16 #define REX 1 #define REX2 2 diff --git a/src/setup.cpp b/src/setup.cpp index 83f114a..1bf3a78 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -131,6 +131,8 @@ typedef struct memory_ctrl_struct Fl_Round_Button* pRex; Fl_Round_Button* pRex2; Fl_Check_Button* pReMemOverride; + Fl_Round_Button* pQuad; + Fl_Round_Button* pRexQuad; Fl_Input* pReMemFile; Fl_Input* pRampacFile; Fl_Input* pRexFlashFile; @@ -875,7 +877,8 @@ void cb_memory_OK(Fl_Widget* w, void*) =================================================== */ if ((mem_setup.mem_mode == SETUP_MEM_RAMPAC) || (mem_setup.mem_mode == SETUP_MEM_BASE) || - (mem_setup.mem_mode == SETUP_MEM_REX)) + (mem_setup.mem_mode == SETUP_MEM_REX) || (mem_setup.mem_mode == SETUP_MEM_QUAD) || + (mem_setup.mem_mode == SETUP_MEM_REX_QUAD)) save_ram(); /* @@ -944,6 +947,10 @@ void cb_memory_OK(Fl_Widget* w, void*) mem_setup.mem_mode = SETUP_MEM_REX; else if (mem_ctrl.pRex2->value() == 1) mem_setup.mem_mode = SETUP_MEM_REX2; + else if (mem_ctrl.pQuad->value() == 1) + mem_setup.mem_mode = SETUP_MEM_QUAD; + else if (mem_ctrl.pRexQuad->value() == 1) + mem_setup.mem_mode = SETUP_MEM_REX_QUAD; // Get Memory installed selection mem_setup.mem_installed = mem_ctrl.pMemInstalled->value(); @@ -967,7 +974,8 @@ void cb_memory_OK(Fl_Widget* w, void*) =================================================== */ if ((mem_setup.mem_mode == SETUP_MEM_RAMPAC) || (mem_setup.mem_mode == SETUP_MEM_BASE) || - (mem_setup.mem_mode == SETUP_MEM_REX)) + (mem_setup.mem_mode == SETUP_MEM_REX) || (mem_setup.mem_mode == SETUP_MEM_QUAD) || + (mem_setup.mem_mode == SETUP_MEM_REX_QUAD)) load_ram(); // If we are in ReMem or ReMem_Rampac mode, check if ReMem filename changed @@ -1078,7 +1086,7 @@ void cb_memory_OK(Fl_Widget* w, void*) resetcpu(); gExitLoop = 1; - show_remem_mode(); + show_remem_mode(); // Destroy the window gmsw->hide(); @@ -1352,6 +1360,36 @@ void cb_radio_rex2 (Fl_Widget* w, void*) mem_ctrl.pRexCreateFlash->activate(); } +void cb_radio_quad (Fl_Widget* w, void*) +{ + mem_ctrl.pRampacFile->deactivate(); + mem_ctrl.pRampacBrowse->deactivate(); + mem_ctrl.pReMemOverride->deactivate(); + mem_ctrl.pReMemFile->deactivate(); + mem_ctrl.pReMemBrowse->deactivate(); + mem_ctrl.pReMemText->hide(); + mem_ctrl.pRexFlashFile->deactivate(); + mem_ctrl.pRexFlashBrowse->deactivate(); + mem_ctrl.pRex2RamFile->deactivate(); + mem_ctrl.pRex2RamBrowse->deactivate(); + mem_ctrl.pRexCreateFlash->deactivate(); +} + +void cb_radio_rex_quad (Fl_Widget* w, void*) +{ + mem_ctrl.pRampacFile->deactivate(); + mem_ctrl.pRampacBrowse->deactivate(); + mem_ctrl.pReMemOverride->deactivate(); + mem_ctrl.pReMemFile->deactivate(); + mem_ctrl.pReMemBrowse->deactivate(); + mem_ctrl.pReMemText->hide(); + mem_ctrl.pRexFlashFile->activate(); + mem_ctrl.pRexFlashBrowse->activate(); + mem_ctrl.pRex2RamFile->deactivate(); + mem_ctrl.pRex2RamBrowse->deactivate(); + mem_ctrl.pRexCreateFlash->activate(); +} + void cb_memory_cancel (Fl_Widget* w, void*) { gmsw->hide(); @@ -1504,7 +1542,7 @@ Routine to create the PeripheralSetup Window and tabs void cb_MemorySetup (Fl_Widget* w, void*) { // Create Peripheral Setup window - gmsw = new Fl_Window(520, 415, "Memory Emulation Options"); + gmsw = new Fl_Window(520, 465, "Memory Emulation Options"); gmsw->callback(cb_memorywin); // Create items on the Tab @@ -1595,34 +1633,57 @@ void cb_MemorySetup (Fl_Widget* w, void*) mem_ctrl.pReMemText->hide(); } + + // Add radio button for QUAD + mem_ctrl.pQuad = new Fl_Round_Button(20, 210, 270, 20, "QUAD (128K Banked RAM)"); + mem_ctrl.pQuad->type(FL_RADIO_BUTTON); + mem_ctrl.pQuad->callback(cb_radio_quad); + if (mem_setup.mem_mode == SETUP_MEM_QUAD) + mem_ctrl.pQuad->value(1); + + // Add radio button for REX+QUAD + mem_ctrl.pRexQuad = new Fl_Round_Button(20, 235, 270, 20, "QUAD + REX"); + mem_ctrl.pRexQuad->type(FL_RADIO_BUTTON); + mem_ctrl.pRexQuad->callback(cb_radio_rex_quad); + if (mem_setup.mem_mode == SETUP_MEM_REX_QUAD) + mem_ctrl.pRexQuad->value(1); + + if (gModel != MODEL_M100) + { + mem_ctrl.pQuad->deactivate(); + mem_ctrl.pRexQuad->deactivate(); + } + // Create Rex radio button - mem_ctrl.pRex = new Fl_Round_Button(20, 210, 270, 20, "Rex (1M Flash Option ROM)"); + mem_ctrl.pRex = new Fl_Round_Button(20, 260, 270, 20, "Rex (1M Flash Option ROM)"); mem_ctrl.pRex->type(FL_RADIO_BUTTON); mem_ctrl.pRex->callback(cb_radio_rex); if (mem_setup.mem_mode == SETUP_MEM_REX) mem_ctrl.pRex->value(1); // Create Rex radio button - mem_ctrl.pRex2 = new Fl_Round_Button(20, 235, 270, 20, "Rex2 (1M Opt ROM + 128K SRAM)"); + mem_ctrl.pRex2 = new Fl_Round_Button(20, 285, 270, 20, "Rex2 (1M Opt ROM + 128K SRAM)"); mem_ctrl.pRex2->type(FL_RADIO_BUTTON); mem_ctrl.pRex2->callback(cb_radio_rex2); if (mem_setup.mem_mode == SETUP_MEM_REX2) mem_ctrl.pRex2->value(1); - mem_ctrl.pRexCreateFlash = new Fl_Button(300, 220, 170, 20, "Create Default Flash"); - if (mem_setup.mem_mode != SETUP_MEM_REX && mem_setup.mem_mode != SETUP_MEM_REX2) - mem_ctrl.pRexCreateFlash->deactivate(); + mem_ctrl.pRexCreateFlash = new Fl_Button(300, 270, 170, 20, "Create Default Flash"); + if (mem_setup.mem_mode != SETUP_MEM_REX && mem_setup.mem_mode != SETUP_MEM_REX2 && + mem_setup.mem_mode != SETUP_MEM_REX_QUAD) + mem_ctrl.pRexCreateFlash->deactivate(); mem_ctrl.pRexCreateFlash->callback(cb_create_flash, &mem_ctrl); // =============================================== // Setup Rex Flash File edit field and Browser button // =============================================== - mem_ctrl.pRexFlashFile = new Fl_Input(105, 260, 310, 20, "Flash File"); + mem_ctrl.pRexFlashFile = new Fl_Input(105, 310, 310, 20, "Flash File"); mem_ctrl.pRexFlashFile->value(mem_setup.rex_flash_file); - mem_ctrl.pRexFlashBrowse = new Fl_Button(430, 257, 60, 30, "Browse"); + mem_ctrl.pRexFlashBrowse = new Fl_Button(430, 307, 60, 30, "Browse"); mem_ctrl.pRexFlashBrowse->callback((Fl_Callback*)cb_rex_browse); - if ((mem_setup.mem_mode != SETUP_MEM_REX) && (mem_setup.mem_mode != SETUP_MEM_REX2)) + if ((mem_setup.mem_mode != SETUP_MEM_REX) && (mem_setup.mem_mode != SETUP_MEM_REX2) && + (mem_setup.mem_mode != SETUP_MEM_REX_QUAD)) { mem_ctrl.pRexFlashFile->deactivate(); mem_ctrl.pRexFlashBrowse->deactivate(); @@ -1631,9 +1692,9 @@ void cb_MemorySetup (Fl_Widget* w, void*) // =============================================== // Setup Rex Flash File edit field and Browser button // =============================================== - mem_ctrl.pRex2RamFile = new Fl_Input(105, 295, 310, 20, "RAM File"); + mem_ctrl.pRex2RamFile = new Fl_Input(105, 345, 310, 20, "RAM File"); mem_ctrl.pRex2RamFile->value(mem_setup.rex2_ram_file); - mem_ctrl.pRex2RamBrowse = new Fl_Button(430, 292, 60, 30, "Browse"); + mem_ctrl.pRex2RamBrowse = new Fl_Button(430, 342, 60, 30, "Browse"); mem_ctrl.pRex2RamBrowse->callback((Fl_Callback*)cb_rex2_browse); if (mem_setup.mem_mode != SETUP_MEM_REX2) @@ -1644,18 +1705,18 @@ void cb_MemorySetup (Fl_Widget* w, void*) // Option ROM RW Enable - mem_ctrl.pOptRomRW = new Fl_Check_Button(20, 320, 210, 20, "Make Option ROM R/W"); + mem_ctrl.pOptRomRW = new Fl_Check_Button(20, 370, 210, 20, "Make Option ROM R/W"); mem_ctrl.pOptRomRW->value(gOptRomRW); // Show Version Checkbox - mem_ctrl.pShowVersion = new Fl_Check_Button(20, 345, 210, 20, "Patch ROM on load to show VirtualT version"); + mem_ctrl.pShowVersion = new Fl_Check_Button(20, 395, 210, 20, "Patch ROM on load to show VirtualT version"); mem_ctrl.pShowVersion->value(gShowVersion); // OK button - { Fl_Button* o = new Fl_Button(140, 375, 60, 30, "Cancel"); + { Fl_Button* o = new Fl_Button(140, 425, 60, 30, "Cancel"); o->callback((Fl_Callback*)cb_memory_cancel); } - { Fl_Return_Button* o = new Fl_Return_Button(220, 375, 60, 30, "OK"); + { Fl_Return_Button* o = new Fl_Return_Button(220, 425, 60, 30, "OK"); o->callback((Fl_Callback*)cb_memory_OK); } diff --git a/src/setup.h b/src/setup.h index fa7b1de..c863df0 100644 --- a/src/setup.h +++ b/src/setup.h @@ -95,7 +95,9 @@ enum { SETUP_MEM_REMEM, SETUP_MEM_REMEM_RAMPAC, SETUP_MEM_REX, - SETUP_MEM_REX2 + SETUP_MEM_REX2, + SETUP_MEM_QUAD, + SETUP_MEM_REX_QUAD }; #ifdef __cplusplus From b39cb6801401e70e02ff9183a001f800a8f1ece5 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 25 Feb 2015 00:36:00 +0000 Subject: [PATCH 270/327] Changes to get QUAD changes working on Windows build. --- VirtualT.suo | Bin 337408 -> 335360 bytes VirtualT.vcproj | 24 ++++++++++++++++++++++++ src/doins.h | 4 ++++ src/io.c | 15 ++++++++++++--- src/memedit.cpp | 10 +++++++++- src/tdockvid.cpp | 16 +++++++++------- 6 files changed, 58 insertions(+), 11 deletions(-) diff --git a/VirtualT.suo b/VirtualT.suo index 25e1c086173a92c27af2a2a83af3d36c0ad5787d..224d49945b28dad79c2074d4e2a479a58f04986c 100644 GIT binary patch delta 25609 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 Kf80h+?0*7&J}{*K diff --git a/VirtualT.vcproj b/VirtualT.vcproj index eaaafb3..852d097 100644 --- a/VirtualT.vcproj +++ b/VirtualT.vcproj @@ -690,6 +690,14 @@ RelativePath=".\src\strcase.c" > + + + + @@ -1059,6 +1067,10 @@ /> + + @@ -1133,6 +1145,10 @@ RelativePath=".\src\clock.h" > + + @@ -1237,6 +1253,14 @@ RelativePath="src\sound.h" > + + + + diff --git a/src/doins.h b/src/doins.h index f8d75a8..8222230 100644 --- a/src/doins.h +++ b/src/doins.h @@ -33,7 +33,11 @@ extern char paritybits[256]; +#ifdef WIN32 +void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry, char ov) +#else static inline void setflags(unsigned char regval, char sign, char zero, char auxcarry, char parity, char carry, char ov) +#endif { if (sign!=-2) { diff --git a/src/io.c b/src/io.c index 1885ab5..91f5ccb 100644 --- a/src/io.c +++ b/src/io.c @@ -1262,9 +1262,18 @@ int inport(uchar port) return t200_readport(0xFE); else { - if (fullspeed == 0 && (lcdTime[c]+.000014 > hirestimer())) - //if (fullspeed == 0 && (lcdCycles[c]+3*2454 > cycles + cycle_delta)) - return (0x80); + if (fullspeed == 0) + { + /* Loop through all LCD driver modules */ + for (c = 0; c < 10; c++) + { + /* Check if this driver is enabled */ + if (lcdbits & (1 << c)) + if (lcdTime[c]+.000014 > hirestimer()) + return (0x80); + } + return 64; + } else return(64); } diff --git a/src/memedit.cpp b/src/memedit.cpp index 075a0cd..fc78333 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -1265,7 +1265,15 @@ void T100_MemEditor::SetRegionOptions(void) } else { - memedit_ctrl.pRegion->add("RAM"); + if (gQuad) + { + memedit_ctrl.pRegion->add("RAM 1"); + memedit_ctrl.pRegion->add("RAM 2"); + memedit_ctrl.pRegion->add("RAM 3"); + memedit_ctrl.pRegion->add("RAM 4"); + } + else + memedit_ctrl.pRegion->add("RAM"); } memedit_ctrl.pRegion->add("ROM"); if (gModel == MODEL_T200) diff --git a/src/tdockvid.cpp b/src/tdockvid.cpp index 81eb014..dce9364 100644 --- a/src/tdockvid.cpp +++ b/src/tdockvid.cpp @@ -103,6 +103,12 @@ extern int gConsoleDebug; #ifndef WIN32 #define min(a,b) ((a)<(b) ? (a):(b)) #endif +#ifdef WIN32 +extern "C" +{ +int strcasecmp(const char* s1, const char* s2); +} +#endif extern T100_Disp* gpDisp; @@ -208,8 +214,6 @@ Clear: This routine clears the "LCD" */ void VTTDockVid::Clear(void) { - int x,y; - memset(pixdata, 0, 200*480); m_CurX = m_CurY = 0; @@ -470,7 +474,7 @@ void VTTDockVid::draw_pixels() { int x=0; int y=0; - int line, col; + int line; uchar value; int lastColor = -1; int color; @@ -877,7 +881,7 @@ void VTTDockVid::WriteData(uchar data) /* Draw the received byte */ else //if (data >= ' '); { - int addr, line, y, c, mem_index, column, color, lastcolor = -1; + int addr, line, c, mem_index, column, lastcolor = -1; if (m_CurY >= 200) Scroll(); @@ -1001,7 +1005,7 @@ void VTTDockVid::XorCursor(void) void VTTDockVid::Scroll(void) { - int y, col, color, lastcolor; + int y, col, color, lastcolor = -1; /* Test if at bottom of display */ if (m_CurY >= 200) @@ -1042,8 +1046,6 @@ void VTTDockVid::Scroll(void) int VTTDockVid::handle(int event) { - int key; - return gpDisp->handle(event); } From a813265225093e5b4b3bec1f829adfe0f50d13bf Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 25 Feb 2015 02:12:08 +0000 Subject: [PATCH 271/327] Re-checkin of ide.jpg, attempting to fix display issue on Windows. --- doc/ide.jpg | Bin 141743 -> 176120 bytes src/assemble.cpp | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ide.jpg b/doc/ide.jpg index 2e21dcf54fda2363a293a487fdd7b9beba23c907..8e69176df2dc2e21285dbdee7257d4dbf94ebca5 100644 GIT binary patch literal 176120 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
    vOf2&>x1MU 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˿q8h^+9| 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ú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≤kzaw8`_8&effujpD<$(!f(6iV{Mq&@W6IaM3)x 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�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 literal 141743 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≪n4GiTp!tEF+ylX5K57a=hp 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 f`EAy5@*ib>kn%W<;EC&a)=Th>o&>r(e@y*?S diff --git a/src/assemble.cpp b/src/assemble.cpp index 5074538..d3df2c7 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -3526,7 +3526,7 @@ int VTAssembler::Assemble() } } else - { + { // Equation does not evaluate. Check if it is an extern if (EquationIsExtern((CRpnEquation *) pInst->m_Group, size)) { From 42cd30e2cfcaefbaf579c6ed44c70b3ca25157c7 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 3 Mar 2015 01:51:44 +0000 Subject: [PATCH 272/327] *** empty log message *** --- src/MString.cpp | 44 +- src/MString.h | 8 +- src/assemble.cpp | 753 +++++++++++++++++++----------- src/assemble.h | 25 +- src/elf.h | 27 +- src/ide.cpp | 209 ++++++--- src/ide.h | 8 + src/linker.cpp | 1060 +++++++++++++++++++++++++++++++++++++++--- src/linker.h | 35 +- src/memedit.cpp | 28 +- src/multieditwin.cpp | 2 +- src/project.cpp | 97 +++- src/project.h | 23 +- src/rpn_eqn.h | 1 + 14 files changed, 1861 insertions(+), 459 deletions(-) diff --git a/src/MString.cpp b/src/MString.cpp index 0921426..0887126 100644 --- a/src/MString.cpp +++ b/src/MString.cpp @@ -20,6 +20,9 @@ ----- $Log$ + Revision 1.4 2015/03/03 01:51:44 kpettit1 + *** empty log message *** + Revision 1.3 2013/02/20 20:47:46 kpettit1 Added TPDD Server (NADSBox emulation). Currently only tested under Windows build and only minimal implementation, though functional. @@ -163,7 +166,7 @@ void MString::deallocate(MNode* p) } } -static int string_length(char* string) +static int string_length(const char* string) { int count = 0; if (string == NULL) @@ -1608,9 +1611,11 @@ char* MString::ToChar(int nStart,int nCount) { } -int MString::ToInt(int nStart) { +int MString::ToInt(int nStart) const { MNode* tmp; + int base = 10; + if( nStart != 0 ) { if ((nStart < 0) || (nStart > GetLength())) @@ -1628,12 +1633,26 @@ int MString::ToInt(int nStart) { tmpInt = 0, tmpMul = 1; + // Skip spaces + while ((tmp) && (tmp->MInfo == ' ')) + tmp = tmp->MLink_Forward; + if( (tmp) && (tmp->MInfo == '-') ) { tmpMul = -1; tmp = tmp->MLink_Forward; } + // Test for "0x" + if ( (tmp) && (tmp->MInfo == '0')) + { + if ( (tmp->MLink_Forward) && (tmp->MLink_Forward->MInfo == 'x')) + { + base = 16; + tmp = tmp->MLink_Forward->MLink_Forward; + } + } + while((tmp) && (tmp->MInfo >= '0') && (tmp->MInfo <='9')) { tmpStr+= tmp->MInfo; tmp = tmp->MLink_Forward; @@ -1645,7 +1664,7 @@ int MString::ToInt(int nStart) { while(tmp) { tmpInt = tmpInt + ((tmp->MInfo - '0') * power); - power = power * 10; + power = power * base; tmp = tmp->MLink_Forward; } return tmpInt * tmpMul; @@ -2052,7 +2071,7 @@ int MString::Find(char ch, int nStart) const { return -1; } -int MString::Find(char* string, int nStart) const { +int MString::Find(const char* string, int nStart) const { //Idea from CString int strLength = string_length(string); @@ -2291,7 +2310,7 @@ void _splitpath(char *path, char* pDrive, char* pDir, char* pFname, char* pExt) pDrive[0] = '\0'; // Get the filename - fname_ptr = strrchr(path, '\\'); + fname_ptr = strrchr(path, '/'); if (fname_ptr == NULL) fname_ptr = path; else @@ -2347,6 +2366,7 @@ MString CFileString::Filename() m_String.ReleaseBuffer(); filename = fname; + filename += (char *) "."; filename += ext; return filename; } @@ -2468,5 +2488,19 @@ MString CFileString::NextSubDir() return subDir; } +void CFileString::NewExt(MString newext) +{ + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR*2]; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + + _splitpath( m_String.GetBuffer(m_String.GetLength() + 1), drive, dir, fname, ext ); + m_String = drive; + m_String += dir; + m_String += fname; + m_String += newext; +} + //End Buffer Access --------------------------------------- diff --git a/src/MString.h b/src/MString.h index 2f8e96a..84ea49e 100644 --- a/src/MString.h +++ b/src/MString.h @@ -274,7 +274,7 @@ class MString { // POST: returns a pointer to a new null-terminated character array // that is a copy of the infomation in the MString. - int ToInt(int nStart = 0); + int ToInt(int nStart = 0) const; // PRE: nStart is > 0 and < GetLength(). // POST: returns an integer created from the numbers starting at nStart // Other: ToInt does not check to see if the string of numbers contained @@ -327,7 +327,7 @@ class MString { //Begin Searching ----------------------------------------- int Find(char ch, int nStart = 0) const; //Idea from CString - int Find(char* string, int nStart = 0) const; //Idea from CString + int Find(const char* string, int nStart = 0) const; //Idea from CString int ReverseFind(char ch) const; //Idea from CString @@ -395,8 +395,10 @@ class CFileString MString Ext(); // C:\DATA\SUBDIR\FILE.TXT -> .TXT MString FirstSubDir(); // C:\DATA\SUBDIR\FILE.TXT -> DATA MString NextSubDir(); // C:\DATA\SUBDIR\FILE.TXT -> SUBDIR ... + void NewExt(MString ext); - MString& operator->() { return m_String; }; + MString& GetString(void) { return m_String; }; + MString& operator->*(MString&) { return m_String; }; CFileString& operator=(const MString& string) { m_String = string; return *this; }; protected: diff --git a/src/assemble.cpp b/src/assemble.cpp index d3df2c7..5c6ce42 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -397,8 +397,6 @@ int VTAssembler::PerformSubstitution(CMacro* pMacro, const char *pLoc) *pNew++ = *ptr++; *pNew = '\0'; - //printf("New line = %s", pNewLine); - // Delete the old m_pInLine and replace with the new one delete[] m_pInLine; m_pInLine = pNewLine; @@ -514,8 +512,8 @@ int VTAssembler::preprocessor(void) if (m_pInPtr) { // filter out cr characters - if (*m_pInPtr == 13) - m_pInPtr++; + while (*m_pInPtr == 13 || (unsigned char) *m_pInPtr > 127) + m_pInPtr++; // If not at end of line, return the next char if (*m_pInPtr != '\0') @@ -543,8 +541,14 @@ int VTAssembler::preprocessor(void) m_pInPtr = m_pInLine; // filter out cr characters + while (*m_pInPtr == 13 || (unsigned char) *m_pInPtr > 127) + m_pInPtr++; +#if 0 if (*m_pInPtr == 13) m_pInPtr++; + else if (*m_pInPtr > 127) + m_pInPtr++; +#endif return *m_pInPtr++; } @@ -615,6 +619,15 @@ void VTAssembler::ResetContent(void) // Delete all undefined symbols m_UndefSymbols.RemoveAll(); + // Remove all linker equations + count = m_Equations.GetSize(); + for (c = 0; c < count; c++) + { + CLinkerEquation* pEq = (CLinkerEquation *) m_Equations[c]; + delete pEq; + } + m_Equations.RemoveAll(); + // Delete all errors m_Errors.RemoveAll(); m_IncludeDirs.RemoveAll(); @@ -1076,9 +1089,7 @@ int VTAssembler::GetValue(MString & string, int & value) } else if (string[0] == '$' && string.GetLength() > 1) { - printf("Found %s\n", (const char *) string); myStr = string.Right(string.GetLength()-1); - printf("New string %s\n", (const char *) myStr); } // Lookup the symbol in all modules @@ -1236,7 +1247,7 @@ void VTAssembler::opcode_arg_1reg_equ8(int opcode) if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) { reg_cnt--; // Pop unused reg operand from stack - delete gEq; // Delete the unused equaiton + delete gEq; // Delete the unused equation gEq = new CRpnEquation; // Allocate new equation for parser return; } @@ -1271,7 +1282,7 @@ void VTAssembler::opcode_arg_1reg_2byte(int opcode) if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) { reg_cnt--; // Pop unused reg operand from stack - delete gEq; // Delete the unused equaiton + delete gEq; // Delete the unused equation gEq = new CRpnEquation; // Allocate new equation for parser return; } @@ -1302,7 +1313,7 @@ void VTAssembler::opcode_arg_1reg_equ16(int opcode) if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) { reg_cnt--; // Pop unused reg operand from stack - delete gEq; // Delete the unused equaiton + delete gEq; // Delete the unused equation gEq = new CRpnEquation; // Allocate new equation for parser return; } @@ -1335,7 +1346,7 @@ void VTAssembler::opcode_arg_equ8(int opcode) // Determine if conditional assembly enabled if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) { - delete gEq; // Delete the unused equaiton + delete gEq; // Delete the unused equation gEq = new CRpnEquation; // Allocate new equation for parser return; } @@ -1367,7 +1378,7 @@ void VTAssembler::opcode_arg_equ16(int opcode) // Determine if conditional assembly enabled if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) { - delete gEq; // Delete the unused equaiton + delete gEq; // Delete the unused equation gEq = new CRpnEquation; // Allocate new equation for parser return; } @@ -1398,7 +1409,7 @@ void VTAssembler::opcode_arg_equ24(int opcode) // Determine if conditional assembly enabled if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) { - delete gEq; // Delete the unused equaiton + delete gEq; // Delete the unused equation gEq = new CRpnEquation; // Allocate new equation for parser return; } @@ -1523,7 +1534,7 @@ void VTAssembler::equate(const char *name) // Determine if conditional assembly enabled if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) { - delete gEq; // Delete the unused equaiton + delete gEq; // Delete the unused equation gEq = new CRpnEquation; // Allocate new equation for parser return; } @@ -1547,7 +1558,6 @@ void VTAssembler::equate(const char *name) pSymbol->m_SymType = SYM_EQUATE; pSymbol->m_pRange = m_ActiveAddr; - // Try to evaluate the equation. Note that we may not be able to // successfully evaluate it at this point because it may contain // a forward reference, so don't report any errors yet. @@ -1555,13 +1565,11 @@ void VTAssembler::equate(const char *name) { pSymbol->m_Value = (long) value; pSymbol->m_SymType |= SYM_HASVALUE; - //printf("EQU: %s = %d\n", (const char *) pSymbol->m_Name, (int) value); } else { // Symbol did not evaluate, save as an equation pSymbol->m_SymType |= SYM_ISEQ; - //printf("EQU: %s = equation\n", (const char *) pSymbol->m_Name); } // Save equation @@ -1646,6 +1654,12 @@ void VTAssembler::label(const char *label, int address) pSymbol->m_Value = address; pSymbol->m_FileIndex = m_FileIndex; // Save index of the current file pSymbol->m_SymType = SYM_LABEL | SYM_HASVALUE; + + // Check for auto Auto Extern and make all lables auto PUBLIC + if (m_AsmOptions.Find((char *) "-e") != -1 && !local) + { + pSymbol->m_SymType |= SYM_PUBLIC; + } pSymbol->m_pRange = m_ActiveAddr; pSymbol->m_Segment = m_ActiveSeg; if (m_ActiveSeg->m_Type == CSEG) @@ -1683,6 +1697,7 @@ void VTAssembler::label(const char *label, int address) m_LastLabelSym= pSymbol; CInstruction* pInst = new CInstruction; pInst->m_ID = INST_LABEL; + pInst->m_Line = m_Line; pInst->m_Operand1 = new MString; *pInst->m_Operand1 = m_LastLabel; m_Instructions->Add(pInst); // Save instruction @@ -1705,7 +1720,7 @@ void VTAssembler::directive_set(const char *name) // Determine if conditional assembly enabled if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) { - delete gEq; // Delete the unused equaiton + delete gEq; // Delete the unused equation gEq = new CRpnEquation; // Allocate new equation for parser return; } @@ -1826,7 +1841,7 @@ void VTAssembler::directive_org() // Determine if conditional assembly enabled if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) { - delete gEq; // Delete the unused equaiton + delete gEq; // Delete the unused equation gEq = new CRpnEquation; // Allocate new equation for parser return; } @@ -1944,7 +1959,7 @@ void VTAssembler::directive_printf(const char *string, int hasEquation) // Determine if conditional assembly enabled if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) { - delete gEq; // Delete the unused equaiton + delete gEq; // Delete the unused equation gEq = new CRpnEquation; // Allocate new equation for parser return; } @@ -1985,7 +2000,7 @@ void VTAssembler::directive_printf(const char *string, int hasEquation) strcat(str, ptr + 2 + fmtDigits); } - delete gEq; // Delete the unused equaiton + delete gEq; // Delete the unused equation gEq = new CRpnEquation; // Allocate new equation for parser if (m_pStdoutFunc != NULL) @@ -2012,7 +2027,7 @@ void VTAssembler::directive_echo() // Determine if conditional assembly enabled if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) { - delete gEq; // Delete the unused equaiton + delete gEq; // Delete the unused equation gEq = new CRpnEquation; // Allocate new equation for parser return; } @@ -2040,7 +2055,7 @@ void VTAssembler::directive_echo() m_pStdoutFunc(m_pStdoutContext, "#UNDEFINED"); } - delete gEq; // Delete the unused equaiton + delete gEq; // Delete the unused equation gEq = new CRpnEquation; // Allocate new equation for parser } @@ -2242,6 +2257,7 @@ void VTAssembler::directive_cdseg(int segType, int page) } // Add segment to our list of segments + pSeg->m_Line = m_Line; // Save line number where segment starts m_Segments[name] = pSeg; } @@ -2261,7 +2277,7 @@ void VTAssembler::directive_ds() // Determine if conditional assembly enabled if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) { - delete gEq; // Delete the unused equaiton + delete gEq; // Delete the unused equation gEq = new CRpnEquation; // Allocate new equation for parser return; } @@ -2989,6 +3005,10 @@ void VTAssembler::preproc_define() { int count, c; + // Determine if conditional assembly enabled + if (m_IfStat[m_IfDepth] != IF_STAT_ASSEMBLE) + return; + // Update line number m_Line = (PCB).line; @@ -2997,7 +3017,8 @@ void VTAssembler::preproc_define() if (pInst != NULL) { pInst->m_ID = INST_DEFINE; - pInst->m_Line = m_Line; + //pInst->m_Line = m_Line; + pInst->m_Line = -1; // KDP pInst->m_Group = gMacro; // Save the macro pInst->m_Operand1 = new MString; *pInst->m_Operand1 = gMacro->m_Name; // Save name of define @@ -3071,7 +3092,7 @@ void VTAssembler::preproc_undef(const char *name) /* ============================================================================ This is the preprocessor function to handle macros found in the code that -is acrually a statement vs. a parameter / equation +is actually a statement vs. a parameter / equation ============================================================================ */ int VTAssembler::preproc_macro() @@ -3178,127 +3199,116 @@ void VTAssembler::directive_if(int inst) // Update line number m_Line = (PCB).line - 1; - -// CInstruction* pInst = new CInstruction; -// if (pInst != NULL) -// { -// pInst->m_ID = inst; // If or elif -// pInst->m_Line = m_Line; -// pInst->m_Group = gCond; -// pInst->m_FileIndex = m_FileIndex; // Save index of the current file - m_LastIfElseLine = m_Line; - m_LastIfElseIsIf = 1; - - // First push results from previous IF/ELSE/ENDIF operation so - // we generate "nested if" conditions. Initialize condition to - // EVAL_ERROR in case the condition does not evaluate - if (inst == INST_IF) - { - // Process if instrution - if ((m_IfStat[m_IfDepth] == IF_STAT_DONT_ASSEMBLE) || - (m_IfStat[m_IfDepth] == IF_STAT_NESTED_DONT_ASSEMBLE) || - (m_IfStat[m_IfDepth] == IF_STAT_EVAL_ERROR)) - { - m_IfStat[++m_IfDepth] = IF_STAT_NESTED_DONT_ASSEMBLE; - } - else - m_IfStat[++m_IfDepth] = IF_STAT_EVAL_ERROR; + m_LastIfElseLine = m_Line; + m_LastIfElseIsIf = 1; - if (m_IfDepth >= sizeof(m_IfStat)) - { - m_IfDepth--; - err.Format("Error in line %d(%s): Too many nested ifs", m_Line, - (const char *) m_Filenames[m_FileIndex].Filename()); - m_Errors.Add(err); - gCond = new CCondition; -// m_Instructions->Add(pInst); - } + // First push results from previous IF/ELSE/ENDIF operation so + // we generate "nested if" conditions. Initialize condition to + // EVAL_ERROR in case the condition does not evaluate + if (inst == INST_IF) + { + // Process if instrution + if ((m_IfStat[m_IfDepth] == IF_STAT_DONT_ASSEMBLE) || + (m_IfStat[m_IfDepth] == IF_STAT_NESTED_DONT_ASSEMBLE) || + (m_IfStat[m_IfDepth] == IF_STAT_EVAL_ERROR)) + { + m_IfStat[++m_IfDepth] = IF_STAT_NESTED_DONT_ASSEMBLE; } else - { - // Process elif instruction - if (m_IfDepth == 0) - { - err.Format("Error in line %d(%s): ELSE without a matching IF", m_Line, - (const char *) m_Filenames[m_FileIndex].Filename()); - m_Errors.Add(err); - return; - } + m_IfStat[++m_IfDepth] = IF_STAT_EVAL_ERROR; - if (m_IfStat[m_IfDepth] == IF_STAT_ASSEMBLE) - m_IfStat[m_IfDepth] = IF_STAT_NESTED_DONT_ASSEMBLE; - else - if (m_IfStat[m_IfDepth] == IF_STAT_DONT_ASSEMBLE) - m_IfStat[m_IfDepth] = IF_STAT_EVAL_ERROR; + if (m_IfDepth >= sizeof(m_IfStat)) + { + m_IfDepth--; + err.Format("Error in line %d(%s): Too many nested ifs", m_Line, + (const char *) m_Filenames[m_FileIndex].Filename()); + m_Errors.Add(err); + gCond = new CCondition; } + } + else + { + // Process elif instruction + if (m_IfDepth == 0) + { + err.Format("Error in line %d(%s): ELSE without a matching IF", m_Line, + (const char *) m_Filenames[m_FileIndex].Filename()); + m_Errors.Add(err); + return; + } + + if (m_IfStat[m_IfDepth] == IF_STAT_ASSEMBLE) + m_IfStat[m_IfDepth] = IF_STAT_NESTED_DONT_ASSEMBLE; + else + if (m_IfStat[m_IfDepth] == IF_STAT_DONT_ASSEMBLE) + m_IfStat[m_IfDepth] = IF_STAT_EVAL_ERROR; + } - // Determine if both equations can be evaluated - if (m_IfStat[m_IfDepth] == IF_STAT_EVAL_ERROR) + // Determine if both equations can be evaluated + if (m_IfStat[m_IfDepth] == IF_STAT_EVAL_ERROR) + { + if (Evaluate(gCond->m_EqLeft, &valuel, 0, errVar)) { - if (Evaluate(gCond->m_EqLeft, &valuel, 0, errVar)) + // Check if condition contains 2 equations or not + if (gCond->m_EqRight != 0) { - // Check if condition contains 2 equations or not - if (gCond->m_EqRight != 0) + if (Evaluate(gCond->m_EqRight, &valuer, 0, errVar)) { - if (Evaluate(gCond->m_EqRight, &valuer, 0, errVar)) - { - m_IfStat[m_IfDepth] = IF_STAT_DONT_ASSEMBLE; + m_IfStat[m_IfDepth] = IF_STAT_DONT_ASSEMBLE; - // Both equations evaluate, check condition - switch (gCond->m_Condition) - { - case COND_EQ: - if (valuel == valuer) - m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; - break; + // Both equations evaluate, check condition + switch (gCond->m_Condition) + { + case COND_EQ: + if (valuel == valuer) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + break; - case COND_NE: - if (valuel != valuer) - m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; - break; + case COND_NE: + if (valuel != valuer) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + break; - case COND_GE: - if (valuel >= valuer) - m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; - break; + case COND_GE: + if (valuel >= valuer) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + break; - case COND_LE: - if (valuel <= valuer) - m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; - break; + case COND_LE: + if (valuel <= valuer) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + break; - case COND_GT: - if (valuel > valuer) - m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; - break; + case COND_GT: + if (valuel > valuer) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + break; - case COND_LT: - if (valuel < valuer) - m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; - break; - } + case COND_LT: + if (valuel < valuer) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + break; } } + } + else + { + // Check bit 0 of the evaluated expression from equation 1 + if (((int) valuel) & 0x01) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; else - { - // Check bit 0 of the evaluated expression from equation 1 - if (((int) valuel) & 0x01) - m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; - else - m_IfStat[m_IfDepth] = IF_STAT_DONT_ASSEMBLE; - } + m_IfStat[m_IfDepth] = IF_STAT_DONT_ASSEMBLE; } - } - if (m_IfStat[m_IfDepth] == IF_STAT_EVAL_ERROR || errVar != "") - { - err.Format("Error in line %d(%s): Symbol %s undefined", m_Line, - (const char *) m_Filenames[m_FileIndex].Filename(), (const char *) errVar); - m_Errors.Add(err); } + } + if (m_IfStat[m_IfDepth] == IF_STAT_EVAL_ERROR || errVar != "") + { + err.Format("Error in line %d(%s): Symbol %s undefined", m_Line, + (const char *) m_Filenames[m_FileIndex].Filename(), (const char *) errVar); + m_Errors.Add(err); + } - gCond = new CCondition; -// m_Instructions->Add(pInst); -// } + gCond = new CCondition; } /* @@ -3313,33 +3323,25 @@ void VTAssembler::directive_else() // Update line number m_Line = (PCB).line - 1; -// CInstruction* pInst = new CInstruction; -// if (pInst != NULL) -// { -// pInst->m_ID = INST_ELSE; -// pInst->m_Line = m_Line; -// pInst->m_FileIndex = m_FileIndex; // Save index of the current file - m_LastIfElseLine = m_Line; - m_LastIfElseIsIf = 0; -// m_Instructions->Add(pInst); - - // Process ELSE statement during parsing. First insure else has a matching if - if (m_IfDepth == 0) - { - err.Format("Error in line %d(%s): ELSE without a matching IF", m_Line, - (const char *) m_Filenames[m_FileIndex].Filename()); - m_Errors.Add(err); - return; - } - - // Now check if the active IF statement is not a NESTED_DONT_ASSEMBLE. - // If it isn't then change the state of the assembly - if (m_IfStat[m_IfDepth] == IF_STAT_ASSEMBLE) - m_IfStat[m_IfDepth] = IF_STAT_DONT_ASSEMBLE; - else - if (m_IfStat[m_IfDepth] == IF_STAT_DONT_ASSEMBLE) - m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; -// } + m_LastIfElseLine = m_Line; + m_LastIfElseIsIf = 0; + + // Process ELSE statement during parsing. First insure else has a matching if + if (m_IfDepth == 0) + { + err.Format("Error in line %d(%s): ELSE without a matching IF", m_Line, + (const char *) m_Filenames[m_FileIndex].Filename()); + m_Errors.Add(err); + return; + } + + // Now check if the active IF statement is not a NESTED_DONT_ASSEMBLE. + // If it isn't then change the state of the assembly + if (m_IfStat[m_IfDepth] == IF_STAT_ASSEMBLE) + m_IfStat[m_IfDepth] = IF_STAT_DONT_ASSEMBLE; + else + if (m_IfStat[m_IfDepth] == IF_STAT_DONT_ASSEMBLE) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; } /* @@ -3354,26 +3356,17 @@ void VTAssembler::directive_endif() // Update line number m_Line = (PCB).line - 1; -// CInstruction* pInst = new CInstruction; -// if (pInst != NULL) -// { -// pInst->m_ID = INST_ENDIF; -// pInst->m_Line = m_Line; -// pInst->m_FileIndex = m_FileIndex; // Save index of the current file -// m_Instructions->Add(pInst); - - // Process ENDIF statement during parsing. First insure else has a matching if - if (m_IfDepth == 0) - { - err.Format("Error in line %d(%s): ENDIF without a matching IF", m_Line, - (const char *) m_Filenames[m_FileIndex].Filename()); - m_Errors.Add(err); - return; - } + // Process ENDIF statement during parsing. First insure else has a matching if + if (m_IfDepth == 0) + { + err.Format("Error in line %d(%s): ENDIF without a matching IF", m_Line, + (const char *) m_Filenames[m_FileIndex].Filename()); + m_Errors.Add(err); + return; + } - // Pop If from stack - m_IfDepth--; -// } + // Pop If from stack + m_IfDepth--; } /* @@ -3403,7 +3396,7 @@ int VTAssembler::Assemble() unsigned int address; double value; char rel_mask; - int valid, extern_label; + int valid, extern_label, equation; POSITION pos; MString key, errSymbol; CSegment* relSeg; @@ -3441,8 +3434,11 @@ int VTAssembler::Assemble() { pInst = (CInstruction*) (*m_Instructions)[c]; m_Line = pInst->m_Line; + if (m_Line != -1) + m_ActiveSeg->m_LastLine = m_Line; m_FileIndex = pInst->m_FileIndex; rel_mask = 0; + equation = 0; address = m_Address; /* @@ -3498,6 +3494,8 @@ int VTAssembler::Assemble() (type == OPCODE_REG_IMM) || (type == OPCODE_REG_EQU16) || (type == OPCODE_PGI)) { + CRpnEquation* pEq = (CRpnEquation *) pInst->m_Group; + if ((type == OPCODE_EQU8) || (type == OPCODE_REG_IMM)) size = 1; else if (type == OPCODE_EQU24) @@ -3506,14 +3504,19 @@ int VTAssembler::Assemble() size = 2; // Try to get value of the equation - if (Evaluate((CRpnEquation *) pInst->m_Group, &value, 1, errSymbol)) + if (Evaluate(pEq, &value, 1, errSymbol)) { // Equation evaluated to a value. Check if it is // relative to a relocatable segment - if (InvalidRelocation((CRpnEquation *) pInst->m_Group, rel_mask, + if (InvalidRelocation(pEq, rel_mask, relSeg)) { valid = 0; + equation = 1; + op1 = 0; + op2 = 0; + op3 = 0; + value = 0.0; } if (type == OPCODE_PGI) @@ -3528,7 +3531,7 @@ int VTAssembler::Assemble() else { // Equation does not evaluate. Check if it is an extern - if (EquationIsExtern((CRpnEquation *) pInst->m_Group, size)) + if (EquationIsExtern(pEq, size)) { // Add a dummy value (0) with relocation op1 = 0; @@ -3539,11 +3542,13 @@ int VTAssembler::Assemble() } else { - err.Format("Error in line %d(%s): Invalid relocation relative to symbol %s", - pInst->m_Line, (const char *) m_Filenames[m_FileIndex].Filename(), - (const char *) errSymbol); - m_Errors.Add(err); - valid = 0; + // We need to save the equation in the ELF file and let the linker + // to the evaluation after the segments have been located. + equation = 1; + op1 = 0; + op2 = 0; + op3 = 0; + value = 0.0; } } } @@ -3556,6 +3561,12 @@ int VTAssembler::Assemble() pRel->m_Address = m_Address + 1; pRel->m_pSourceRange = m_ActiveAddr; pRel->m_Segment = relSeg; + if (type == OPCODE_EQU16 || type == OPCODE_REG_EQU16) + pRel->m_Size = 2; + else if (type == OPCODE_EQU24) + pRel->m_Size = 3; + else + pRel->m_Size = 1; pRange = m_ActiveSeg->m_UsedAddr; if (relSeg != NULL) pRange = relSeg->m_UsedAddr; @@ -3584,6 +3595,24 @@ int VTAssembler::Assemble() pExt->m_pRange = m_ActiveAddr; m_Externs.Add(pExt); } + + // Add equation to the array of equations to be added to the ELF file + else if (equation) + { + // Add a linker equation for relocation + CLinkerEquation *pLinkEq = new CLinkerEquation; + pLinkEq->m_Address = m_Address + 1; + if (m_ActiveSeg->m_Type == ASEG) + pLinkEq->m_Address -= m_ActiveAddr->address; + pLinkEq->m_Segment = m_ActiveSeg->m_Type; + pLinkEq->m_Size = size; + pLinkEq->m_pRange = m_ActiveAddr; + pLinkEq->m_pRpnEq = ((CRpnEquation *) pInst->m_Group); + pLinkEq->m_Line = m_Line; + pInst->m_Group = NULL; + m_Equations.Add(pLinkEq); + } + // Test for relative branch instruction else if ((pInst->m_ID >= OPCODE_BR) && (pInst->m_ID <= OPCODE_RCALL)) { @@ -3777,44 +3806,10 @@ int VTAssembler::Assemble() /* ==================================================================== - Deal with DB directive by adding bytes to the output stream - ==================================================================== - */ - else if (pInst->m_ID == INST_DB) - { - // Get count of expression in list - pExpList = (VTObArray *) pInst->m_Group; - len = pExpList->GetSize(); - - // Update address based on number of items in expression list - for (x = 0; x < len; x++) - { - // Get next expression from expression list - pExp = (CExpression *) (*pExpList)[x]; - - // If expression has an equation, try to evaluate it - if (pExp->m_Equation != NULL) - { - if (Evaluate(pExp->m_Equation, &value, 1)) - m_ActiveSeg->m_AsmBytes[m_Address++] = (unsigned char) value; - } - else - { - // Add bytes from the string - int y, str_len; - str_len = pExp->m_Literal.GetLength(); - for (y = 0; y < str_len; y++) - m_ActiveSeg->m_AsmBytes[m_Address++] = pExp->m_Literal[y]; - } - } - } - - /* - ==================================================================== - Deal with DW directive by adding bytes to the output stream + Deal with DB and DW directive by adding bytes to the output stream ==================================================================== */ - else if (pInst->m_ID == INST_DW) + else if (pInst->m_ID == INST_DW || pInst->m_ID == INST_DB) { // Get count of expression in list pExpList = (VTObArray *) pInst->m_Group; @@ -3839,22 +3834,40 @@ int VTAssembler::Assemble() if (InvalidRelocation(pExp->m_Equation, rel_mask, relSeg)) { valid = 0; + equation = 1; + op1 = 0; + op2 = 0; + op3 = 0; + value = 0.0; } // Test operand1 to check if MSFIRST is on or not - if (*pInst->m_Operand1 == "1") + if (pInst->m_ID == INST_DW) { - m_ActiveSeg->m_AsmBytes[m_Address++] = ((unsigned short) value) >> 8; - m_ActiveSeg->m_AsmBytes[m_Address++] = ((unsigned short) value) & 0xFF; + if (*pInst->m_Operand1 == "1") + { + m_ActiveSeg->m_AsmBytes[m_Address++] = ((unsigned short) value) >> 8; + m_ActiveSeg->m_AsmBytes[m_Address++] = ((unsigned short) value) & 0xFF; + } + else + { + m_ActiveSeg->m_AsmBytes[m_Address++] = ((unsigned short) value) & 0xFF; + m_ActiveSeg->m_AsmBytes[m_Address++] = ((unsigned short) value) >> 8; + } } else { m_ActiveSeg->m_AsmBytes[m_Address++] = ((unsigned short) value) & 0xFF; - m_ActiveSeg->m_AsmBytes[m_Address++] = ((unsigned short) value) >> 8; } } else { + // Set size based on instruction + if (pInst->m_ID == INST_DW) + size = 2; + else + size = 1; + // Equation does not evaluate. Check if it is an extern if (EquationIsExtern(pExp->m_Equation, size)) { @@ -3867,11 +3880,19 @@ int VTAssembler::Assemble() } else { - err.Format("Error in line %d(%s): Equation cannot be evaluated", - pInst->m_Line, (const char *) m_Filenames[m_FileIndex].Filename()); - m_Errors.Add(err); - valid = 0; + // We need to save the equation in the ELF file and let the linker + // to the evaluation after the segments have been located. + op1 = 0; + op2 = 0; + op3 = 0; + value = 0.0; + equation = 1; } + + // Add zero bytes to the output + m_ActiveSeg->m_AsmBytes[m_Address++] = 0; + if (size == 2) + m_ActiveSeg->m_AsmBytes[m_Address++] = 0; } // Check if DW is relative to a relocatable section @@ -3882,6 +3903,7 @@ int VTAssembler::Assemble() pRel->m_Address = m_Address-2; pRel->m_pSourceRange = m_ActiveAddr; pRel->m_Segment = relSeg; + pRel->m_Size = size; pRange = m_ActiveSeg->m_UsedAddr; if (relSeg != NULL) pRange = relSeg->m_UsedAddr; @@ -3909,16 +3931,43 @@ int VTAssembler::Assemble() pExt->m_pRange = m_ActiveAddr; m_Externs.Add(pExt); } + + // Add equation to the array of relocatable equations to add to the ELF file + else if (equation) + { + // Add a linker equation for relocation + CLinkerEquation *pLinkEq = new CLinkerEquation; + pLinkEq->m_Address = m_Address - 2; + if (m_ActiveSeg->m_Type == ASEG) + pLinkEq->m_Address -= m_ActiveAddr->address; + pLinkEq->m_Segment = m_ActiveSeg->m_Type; + pLinkEq->m_Size = size; + pLinkEq->m_pRange = m_ActiveAddr; + pLinkEq->m_pRpnEq = pExp->m_Equation; + pLinkEq->m_Line = m_Line; + pExp->m_Equation = NULL; + m_Equations.Add(pLinkEq); + } } else { // Add bytes from the string int y, str_len; - str_len = pExt->m_Name.GetLength(); - for (y = 0; y < str_len; y++) - m_ActiveSeg->m_AsmBytes[m_Address++] = pExt->m_Name[y]; - if (str_len & 1) - m_ActiveSeg->m_AsmBytes[m_Address++] = 0; + if (pInst->m_ID == INST_DW) + { + str_len = pExt->m_Name.GetLength(); + for (y = 0; y < str_len; y++) + m_ActiveSeg->m_AsmBytes[m_Address++] = pExt->m_Name[y]; + if (str_len & 1) + m_ActiveSeg->m_AsmBytes[m_Address++] = 0; + } + else + { + // Add bytes from the string + str_len = pExp->m_Literal.GetLength(); + for (y = 0; y < str_len; y++) + m_ActiveSeg->m_AsmBytes[m_Address++] = pExp->m_Literal[y]; + } } } } @@ -4015,16 +4064,21 @@ int VTAssembler::Assemble() This routine creates the ELF object file. ======================================================================== */ -int VTAssembler::CreateObjFile(const char *filename) +int VTAssembler::CreateObjFile(const char *filename, const char *sourcefile) { Elf32_Ehdr ehdr; - Elf32_Shdr strhdr, str2hdr, symhdr, *aseg_hdr, *cseg_hdr, *dseg_hdr; + Elf32_Shdr strhdr, str2hdr, symhdr, eqhdr, *aseg_hdr, *cseg_hdr, *dseg_hdr; Elf32_Shdr *rel_hdrs, null_hdr; Elf32_Sym sym; + Elf32_LinkEq eqent; Elf32_Rel rel; - int c, idx; + Elf32_Half namelen; + int c, idx, count, x, opcount, eqIdx; int aseg_sections, cseg_sections, dseg_sections; + Elf32_Word seglineinfo; FILE* fd; + char* eqTemp; + char sval[20]; CSymbol* pSymbol; CSegment* pSegment; CRelocation* pReloc; @@ -4036,16 +4090,20 @@ int VTAssembler::CreateObjFile(const char *filename) const char relString[] = ".relcseg\0.reldseg\0"; const char debugString[] = ".debug\0"; const char symString[] = ".symtab\0"; + const char equString[] = ".equtab\0"; int symtab_off, symtab_idx; const int debugStrSize = 7; + const int eqStrSize = 8; const int shstrtab_off = 1; const int strtab_off = 11; const int aseg_off = 19; const int cseg_off = 25; const int dseg_off = 31; + int eqtab_off; int len, strtab_start; int first_aseg_idx, first_cseg_idx, first_dseg_idx; int shidx, type, bind; + int symtype; const char * pStr; // Now try to open the object file @@ -4128,6 +4186,12 @@ int VTAssembler::CreateObjFile(const char *filename) fwrite(sectString, sizeof(sectString), 1, fd); fwrite(relString, sizeof(relString), 1, fd); strhdr.sh_size = sizeof(sectString) + sizeof(relString); + if (m_Equations.GetSize() > 0) + { + fwrite(equString, eqStrSize, 1, fd); + eqtab_off = strhdr.sh_size; + strhdr.sh_size += eqStrSize; + } if (m_DebugInfo) { fwrite(debugString, debugStrSize, 1, fd); @@ -4194,7 +4258,8 @@ int VTAssembler::CreateObjFile(const char *filename) { // Get next symbol m_ActiveMod->m_Symbols->GetNextAssoc(pos, key, (VTObject *&) pSymbol); - if ((pSymbol->m_SymType & SYM_PUBLIC) || (pSymbol->m_SymType & SYM_EXTERN)) + symtype = pSymbol->m_SymType & 0xFF; + if ((pSymbol->m_SymType & SYM_PUBLIC) || (symtype == SYM_EXTERN)) { // Don't add global defines to Object file if ((pSymbol->m_SymType & 0xFF) == SYM_DEFINE) @@ -4250,7 +4315,9 @@ int VTAssembler::CreateObjFile(const char *filename) aseg_hdr[idx].sh_size = pRange->length; // Get size from AddrRange aseg_hdr[idx].sh_link = 0; // Set link data to zero aseg_hdr[idx].sh_info = pRange->line;// Set info byte to lineNo where range starts - aseg_hdr[idx].sh_addralign = 0; // Set allignment data to zero + seglineinfo = (m_ActiveSeg->m_Line & 0xFFFF) | + ((m_ActiveSeg->m_LastLine & 0xFFFF) << 16); + aseg_hdr[idx].sh_addralign = seglineinfo; // Set allignment data to zero aseg_hdr[idx].sh_entsize = 0; // Symbol table has equal size items // Save the index of this ASEG Section Header for relocation reference @@ -4326,7 +4393,9 @@ int VTAssembler::CreateObjFile(const char *filename) cseg_hdr[idx].sh_size = pRange->length; // Get size from AddrRange cseg_hdr[idx].sh_link = 0; // Set link data to zero cseg_hdr[idx].sh_info = pRange->line;// Set info byte to lineNo where range starts - cseg_hdr[idx].sh_addralign = 0; // Set allignment data to zero + seglineinfo = (m_ActiveSeg->m_Line & 0xFFFF) | + ((m_ActiveSeg->m_LastLine & 0xFFFF) << 16); + cseg_hdr[idx].sh_addralign = seglineinfo;// Use alignment for line # cseg_hdr[idx].sh_entsize = 0; // Symbol table has equal size items // Save the index of this CSEG Section Header for relocation reference @@ -4397,7 +4466,9 @@ int VTAssembler::CreateObjFile(const char *filename) dseg_hdr[idx].sh_size = pRange->length; // Get size from AddrRange dseg_hdr[idx].sh_link = 0; // Set link data to zero dseg_hdr[idx].sh_info = pRange->line;// Set info byte to lineNo where range starts - dseg_hdr[idx].sh_addralign = 0; // Set allignment data to zero + seglineinfo = (m_ActiveSeg->m_Line & 0xFFFF) | + ((m_ActiveSeg->m_LastLine & 0xFFFF) << 16); + dseg_hdr[idx].sh_addralign = seglineinfo;// Use alignment for line # dseg_hdr[idx].sh_entsize = 0; // Symbol table has equal size items // Save the index of this CSEG Section Header for relocation reference @@ -4444,6 +4515,8 @@ int VTAssembler::CreateObjFile(const char *filename) { // Get next symbol m_ActiveMod->m_Symbols->GetNextAssoc(pos, key, (VTObject *&) pSymbol); + symtype = pSymbol->m_SymType & 0xFF; + //if ((pSymbol->m_SymType & SYM_PUBLIC) || (symtype == SYM_EXTERN)) if ((pSymbol->m_SymType & SYM_PUBLIC) || (pSymbol->m_SymType & SYM_EXTERN)) { // Don't add global defines to Object file @@ -4461,6 +4534,8 @@ int VTAssembler::CreateObjFile(const char *filename) bind = STB_EXTERN; if ((pSymbol->m_SymType & 0xFF) == SYM_LABEL) type = STT_FUNC; + else if ((pSymbol->m_SymType & 0xFF) == SYM_EQUATE) + type = STT_EQUATE; else type = STT_OBJECT; @@ -4550,6 +4625,12 @@ int VTAssembler::CreateObjFile(const char *filename) { // Check if this relocation relative to current section pReloc = (CRelocation *) m_ActiveSeg->m_Reloc[c]; + if (pReloc->m_Size == 2) + type = SR_ADDR_XLATE; + else if (pReloc->m_Size == 1) + type = SR_8BIT; + else + type = SR_24BIT; if (pReloc->m_pTargetRange == pRange) { if (pReloc->m_pSourceRange->shidx >= first_dseg_idx) @@ -4557,21 +4638,21 @@ int VTAssembler::CreateObjFile(const char *filename) shidx = pReloc->m_pSourceRange->shidx - first_dseg_idx; rel.r_offset = pReloc->m_Address - dseg_hdr[shidx].sh_addr + dseg_hdr[shidx].sh_offset; - rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); + rel.r_info = ELF32_R_INFO(0, type); } else if (pReloc->m_pSourceRange->shidx >= first_cseg_idx) { shidx = pReloc->m_pSourceRange->shidx - first_cseg_idx; rel.r_offset = pReloc->m_Address - cseg_hdr[shidx].sh_addr + cseg_hdr[shidx].sh_offset; - rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); + rel.r_info = ELF32_R_INFO(0, type); } else { shidx = pReloc->m_pSourceRange->shidx - first_aseg_idx; rel.r_offset = pReloc->m_Address - aseg_hdr[shidx].sh_addr + aseg_hdr[shidx].sh_offset; - rel.r_info = ELF32_R_INFO(0, SR_ADDR_XLATE); + rel.r_info = ELF32_R_INFO(0, type); } // Update size of header @@ -4595,7 +4676,10 @@ int VTAssembler::CreateObjFile(const char *filename) { // Set address for this relocation rel.r_offset = pExt->m_Address - pExt->m_pRange->address; - rel.r_info = ELF32_R_INFO(pExt->m_SymIdx, SR_EXTERN); + if (pExt->m_Size == 1) + rel.r_info = ELF32_R_INFO(pExt->m_SymIdx, SR_EXTERN8); + else + rel.r_info = ELF32_R_INFO(pExt->m_SymIdx, SR_EXTERN); // Update size of header rel_hdrs[idx].sh_size += sizeof(Elf32_Rel); @@ -4636,6 +4720,121 @@ int VTAssembler::CreateObjFile(const char *filename) } } + /* + ========================================================= + Create section for relocatable linker equations if needed + + Equations are store in the ELF file with a 16-bit length + followed by the equation data. Equation data is storeed + in binary + NULL terminated variable name format. Each + RPN operation is added as a single byte. For RPN entries + that are values or variables, a NULL terminated string + representing the value / variable will follow the + RPN operation code. + ========================================================= + */ + count = m_Equations.GetSize(); + if (count > 0) + { + // Create section header + eqhdr.sh_name = eqtab_off; // Put ".strtab" as first entry in table + eqhdr.sh_type = SHT_LINK_EQ; // Make section a linker equation section + eqhdr.sh_flags = SHF_OS_NONCONFORMING; // This section is custom + eqhdr.sh_addr = 0; // No address data for string table + eqhdr.sh_offset = ftell(fd); + eqhdr.sh_size = 0; // Initialize size to zero -- fill in later + eqhdr.sh_link = 0; // Set link data to point to the .shstrtab section + eqhdr.sh_info = 0; // Set info byte to zero + eqhdr.sh_addralign = 0; // Set allignment data to zero + eqhdr.sh_entsize = 0; // String table does not have equal size entries + ehdr.e_shnum++; // Increment Section Header count + + /* Add the source filename to the ELF file */ + namelen = strlen(sourcefile)+1; + fwrite(&namelen, 1, sizeof(namelen), fd); + fwrite(sourcefile, 1, namelen, fd); + + /* Loop through all Linker Equations and add them to this section */ + eqTemp = new char[2048]; + for (c = 0; c < count; c++) + { + // Get pointer to next LinkerEquation + CLinkerEquation *pLinkEq = (CLinkerEquation *) m_Equations[c]; + opcount = pLinkEq->m_pRpnEq->m_OperationArray.GetSize(); + eqIdx = 0; + + for (x = 0; x < opcount; x++) + { + CRpnOperation& op = pLinkEq->m_pRpnEq->m_OperationArray[x]; + + // Add the operation code to the equation data + eqTemp[eqIdx++] = op.m_Operation; + + // Check if a value or variable needs to be added + switch (op.m_Operation) + { + case RPN_VARIABLE: + // Try to evaluate the variable. If we can evaluate it, then + // we will add the value to the equation instead of the variable name + { + int int_val; + + if (!GetValue(op.m_Variable, int_val)) + { + // Add the variable to the eqTemp data + if (op.m_Variable.GetLength() > 0) + { + strcpy(&eqTemp[eqIdx], (const char *) op.m_Variable); + eqIdx += op.m_Variable.GetLength()+1; + } + break; + } + else + { + // Change the RPN_VARIABLE in the output array to a value + eqTemp[eqIdx-1] = RPN_VALUE; + op.m_Value = int_val; + + // Fallthrough to add RPN_VALUE to ELF file + } + } + + case RPN_VALUE: + // Add the operation code + sprintf(sval, "%f", op.m_Value); + len = strlen(sval); + while (sval[len-1] == '0') + sval[--len] = '\0'; + if (sval[len-1] == '.') + sval[--len] = '\0'; + strcpy(&eqTemp[eqIdx], sval); + eqIdx += strlen(sval)+1; + break; + + default: + break; + } + } + + // Write this equation out to the file + eqent.st_addr = pLinkEq->m_Address; + eqent.st_size = pLinkEq->m_Size; + eqent.st_num = opcount; + eqent.st_len = sizeof(eqent) + eqIdx; + eqent.st_info = pLinkEq->m_pRange->shidx; // Index of the segment this is relative to + eqent.st_line = pLinkEq->m_Line; + fwrite(&eqent, 1, sizeof(eqent), fd); + fwrite(eqTemp, 1, eqIdx, fd); + + // Update the section size + eqhdr.sh_size += eqent.st_len; + + } + + // delete the temporary equation storage + delete[] eqTemp; + } + /* ======================================= Add debug sections to .OBJ file @@ -4696,6 +4895,12 @@ int VTAssembler::CreateObjFile(const char *filename) fwrite(&rel_hdrs[c], sizeof(Elf32_Shdr), 1, fd); } + // Write Linker Equation header if needed + if (m_Equations.GetSize() > 0) + { + fwrite(&eqhdr, sizeof(eqhdr), 1, fd); + } + // Write Debug section headers // Seek to beginning and update Elf Header @@ -4723,7 +4928,7 @@ more than one segment. int VTAssembler::InvalidRelocation(CRpnEquation *pEq, char &rel_mask, CSegment *&pSeg) { - int c, count, invalid; + int c, count, invalid, sameseg; char rel[3]; CSymbol *pSym; @@ -4736,6 +4941,10 @@ int VTAssembler::InvalidRelocation(CRpnEquation *pEq, char &rel_mask, rel[c] = 0; pSeg = NULL; + if (count > 1) + sameseg = TRUE; + else + sameseg = FALSE; for (c = 0; c < count; c++) { // Check if operation type is a variable @@ -4775,15 +4984,25 @@ int VTAssembler::InvalidRelocation(CRpnEquation *pEq, char &rel_mask, else { if (pSeg != pSym->m_Segment) + { invalid = TRUE; + sameseg = FALSE; + } } } } + else + sameseg = FALSE; } + else if (pEq->m_OperationArray[c].m_Operation == RPN_VALUE) + sameseg = FALSE; } // Update rel_mask based on which types of segments referenced - rel_mask = rel[0] | (rel[1] << 1) | (rel[2] << 2); + rel_mask = rel[0] | (rel[1] << 1) | (rel[2] << 2); + if (sameseg && (rel_mask == 1 || rel_mask == 2 || rel_mask == 4)) + rel_mask = 0; + return invalid; } @@ -4834,7 +5053,7 @@ output files for .obj, .lst, .hex, etc. void VTAssembler::ParseExternalDefines(void) { int startIndex, endIndex; - MString def; + MString def, sval; int valIdx, len; int value = -1; @@ -4857,12 +5076,16 @@ void VTAssembler::ParseExternalDefines(void) // Extract the define from the string def = m_ExtDefines.Mid(startIndex, endIndex - startIndex); + sval = ""; + // Test if the define has an embedded '=' if ((valIdx = def.Find('=')) != -1) { MString name = def.Left(valIdx); - MString val = def.Mid(valIdx+1, endIndex - (valIdx+1)); + sval = def.Mid(valIdx+1, endIndex - (valIdx+1)); + //MString val = def.Mid(valIdx+1, endIndex - (valIdx+1)); +#if 0 if (!GetValue(val, value)) { MString errMsg; @@ -4871,11 +5094,21 @@ void VTAssembler::ParseExternalDefines(void) (const char *) name); m_Errors.Add(errMsg); } +#endif // The value was valid. Replace the def name def = name; } + CMacro *pMacro = new CMacro; + if (pMacro != NULL) + { + pMacro->m_Name = def; + pMacro->m_DefString = sval; + m_Defines.Add(pMacro); + } + +#if 0 // Now assign this define CSymbol* pSymbol = new CSymbol; if (pSymbol != NULL) @@ -4893,6 +5126,7 @@ void VTAssembler::ParseExternalDefines(void) const char *pStr = (const char *) pSymbol->m_Name; (*m_Symbols)[pStr] = pSymbol; } +#endif // Update startIndex startIndex = endIndex + 1; @@ -4925,10 +5159,6 @@ void VTAssembler::Parse(MString filename) MString outfile, errMsg; MString temp; - - // Clean up the assembler files from previous assembler - ResetContent(); - // Assign the file's directory for searching include files lastDirMark = filename.ReverseFind('/'); if (lastDirMark == -1) @@ -4971,23 +5201,19 @@ void VTAssembler::Parse(MString filename) // Append .obj to filename temp = outfile; - outfile += (char *) ".obj"; - - // Generate the object file - CreateObjFile(outfile); // Generate a listing file if requested outfile = temp + (char *) ".lst"; CreateList(outfile, filename); + // Generate the object file + outfile = temp + (char *) ".obj"; + CreateObjFile(outfile, filename); + // Generate a hex file if requested outfile = temp + (char *) ".hex"; CreateHex(outfile); - // Generate a .CO file if needed - outfile = temp + (char *) ".co"; - CreateCO(outfile); - // Generate a verilog file if requested outfile = temp + (char *) ".dat"; CreateVerilog(outfile); @@ -5002,10 +5228,10 @@ This function creates a listing file if one was requested. */ void VTAssembler::CreateList(MString& filename, MString& asmFilename) { - MString outfile; FILE* fd; FILE* inFd; int lineNo = 1; + int outLine = 1; int c; // Segment this line was found in char * pRead; char lineBuf[256]; @@ -5052,10 +5278,11 @@ void VTAssembler::CreateList(MString& filename, MString& asmFilename) pSegLines = (CSegLines *) m_SegLines[0]; pSeg = pSegLines->pSegment; + // Get the first instruction / line with output bytes if (pSeg->m_Count != 0) { pInst = (CInstruction*) (*pSeg->m_Instructions)[0]; - while ((pInst != NULL) && (pInst->m_ID == INST_LABEL)) + while ((pInst != NULL) && (pInst->m_ID == INST_LABEL || pInst->m_Line == -1)) { if (++pSeg->m_Index < pSeg->m_Count) pInst = (CInstruction *) (*pSeg->m_Instructions)[pSeg->m_Index]; @@ -5120,6 +5347,7 @@ void VTAssembler::CreateList(MString& filename, MString& asmFilename) fprintf(fd, " "); } fprintf(fd, LINE_ENDING); + outLine++; } // Print any remaining bytes (dw or db statement) @@ -5132,6 +5360,7 @@ void VTAssembler::CreateList(MString& filename, MString& asmFilename) if (pInst->m_Bytes > 12) { fprintf(fd, "...%s", LINE_ENDING); + outLine++; continue; } } @@ -5152,6 +5381,7 @@ void VTAssembler::CreateList(MString& filename, MString& asmFilename) fprintf(fd, " "); } fprintf(fd, LINE_ENDING); + outLine++; } firstInst = FALSE; @@ -5187,11 +5417,11 @@ void VTAssembler::CreateList(MString& filename, MString& asmFilename) fputs(lineBuf, fd); } - // Append .lst to filename - outfile += (char *) ".lst"; + pSeg->m_LastLine = outLine; // Increment the line number lineNo++; + outLine++; // Test if the new lineNo causes us to change to a new segment if ((pSegLines->lastLine != -1) && (lineNo > pSegLines->lastLine)) @@ -5209,6 +5439,8 @@ void VTAssembler::CreateList(MString& filename, MString& asmFilename) // Update pSegLines and pSeg plus pInst structures pSegLines = (CSegLines *) m_SegLines[segLines]; pSeg = pSegLines->pSegment; + pSeg->m_Line = outLine - 1; + pInst = (CInstruction*) (*pSeg->m_Instructions)[0]; // Get the pInst for this module if (pSeg->m_Index < pSeg->m_Count) @@ -5605,6 +5837,7 @@ CSegment::CSegment(const char *name, int type, CModule* initialMod) m_InitialMod = initialMod; m_LastMod = initialMod; m_InstIndex = 0; + m_Line = 0; m_Instructions = new VTObArray; m_Address = 0; m_UsedAddr = new AddrRange; diff --git a/src/assemble.h b/src/assemble.h index f079f85..b61ee03 100644 --- a/src/assemble.h +++ b/src/assemble.h @@ -151,6 +151,7 @@ #define SYM_SET 3 #define SYM_EXTERN 4 #define SYM_DEFINE 5 +#define SYM_EXTERN8 6 #define SYM_CSEG 0x0100 #define SYM_DSEG 0x0200 #define SYM_8BIT 0x0400 @@ -265,6 +266,8 @@ class CSegment : public VTObject int m_Index; // Current index for listing int m_Count; // Instruction count for listing int m_sh_offset; // Offset in .obj file of segment name + int m_Line; // Line numbrer in source of the seg directive + int m_LastLine; // Line numbrer in source of last line VTObArray* m_Instructions; // Array of Instructions for each segment unsigned int m_Address; // Address counter for each segment VTObArray m_Reloc; @@ -309,6 +312,22 @@ class CExtern : public VTObject unsigned char m_Size; }; +class CLinkerEquation : public VTObject +{ +public: + CLinkerEquation() { m_Address = 0; m_pRange = 0; m_pRpnEq = 0; }; + ~CLinkerEquation() { if (m_pRpnEq) delete m_pRpnEq; } + + unsigned int m_Address; + unsigned int m_Line; + unsigned short m_Segment; + unsigned short m_SegIdx; + AddrRange* m_pRange; + CRpnEquation* m_pRpnEq; + MString m_Sourcefile; + unsigned char m_Size; +}; + class CCondition : public VTObject { public: @@ -328,6 +347,7 @@ class CRelocation : public VTObject CRelocation() { m_Address = 0; m_Segment = 0; m_pSourceRange = 0; m_pTargetRange = 0; }; unsigned int m_Address; + int m_Size; CSegment* m_Segment; AddrRange* m_pSourceRange; AddrRange* m_pTargetRange; @@ -477,7 +497,8 @@ class VTAssembler : public VTObject stdOutFunc_t m_pStdoutFunc; // Standard out message routine void* m_pStdoutContext; // Opaque context for stdout MStringArray m_Errors; // Array of error messages during parsing - VTObArray m_Externs; + VTObArray m_Externs; // Array of externs to add to ELF file + VTObArray m_Equations; // Array of equations to add to ELF file VTMapStringToOb m_UndefSymbols; int m_List; // Create a list file? int m_Hex; // Create a HEX file? @@ -518,7 +539,7 @@ class VTAssembler : public VTObject int LookupMacro(MString& name, CMacro *& macro); CSymbol* LookupSymOtherModules(MString& name, CSegment** pSeg = NULL); void ResetContent(void); - int CreateObjFile(const char *filename); + int CreateObjFile(const char *filename, const char *sourcefile); int InvalidRelocation(CRpnEquation* pEq, char &rel_mask, CSegment *&pSeg); int EquationIsExtern(CRpnEquation* pEq, int size); void MakeBinary(int val, int length, MString& binary); diff --git a/src/elf.h b/src/elf.h index 952a23f..3110b6a 100644 --- a/src/elf.h +++ b/src/elf.h @@ -31,11 +31,13 @@ #ifndef ELF_H #define ELF_H -typedef unsigned long Elf32_Addr; -typedef unsigned short Elf32_Half; -typedef unsigned long Elf32_Off; -typedef signed long Elf32_Sword; -typedef unsigned long Elf32_Word; +#include + +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; typedef unsigned char Elf32_Char; #define EI_NIDENT 16 @@ -204,6 +206,7 @@ typedef struct { #define SHT_PREINIT_ARRAY 16 #define SHT_GROUP 17 #define SHT_SYMTAB_SHNDX 18 +#define SHT_LINK_EQ 19 #define SHT_LOOS 0x6000000 #define SHT_HIOS 0x6ffffff #define SHT_LOPROC 0x7000000 @@ -255,6 +258,7 @@ typedef struct { #define STT_FUNC 2 #define STT_SECTION 3 #define STT_FILE 4 +#define STT_EQUATE 5 // Absoute value (EQU) in a relocatable segment #define STT_LOPROC 13 #define STT_HIPROC 15 @@ -278,6 +282,9 @@ typedef struct { #define SR_ADDR_XLATE 1 #define SR_EXTERN 2 #define SR_PUBLIC 3 +#define SR_8BIT 4 +#define SR_24BIT 5 +#define SR_EXTERN8 6 #define SR_ADDR_PROCESSED 0x81 // Define program header information @@ -304,5 +311,15 @@ typedef struct { #define PT_HIPROC 0x7fffffff +// Define Linker Equation entry +typedef struct { + Elf32_Half st_addr; // Address of the relocation + Elf32_Half st_size; // Symbol size + Elf32_Half st_len; // Length of equation entry, counting this struct + Elf32_Half st_num; // Number of entries in the RPN equation + Elf32_Half st_line; // Line number where equation occurrs + Elf32_Half st_info; // Index of the section this is relative to +} Elf32_LinkEq; + #endif diff --git a/src/ide.cpp b/src/ide.cpp index c220048..d3a908e 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -1905,6 +1905,8 @@ void VT_Ide::FindNext(void) if (mw == NULL) return; + m_pFindDlg->m_pErrorMsg->hide(); + // Ensure there is a search string pFind = m_pFindDlg->m_pFind->value(); if (pFind[0] == '\0') @@ -1924,15 +1926,22 @@ void VT_Ide::FindNext(void) if (!mw->ForwardSearch(pFind, m_pFindDlg->m_pMatchCase->value())) { // If still not found, report not found - mw->insert_position(pos); - fl_alert("Search string %s not found", pFind); - m_pFindDlg->m_pFind->take_focus(); + m_pFindDlg->m_ErrMsg.Format("Search string %s not found", pFind); + m_pFindDlg->m_pErrorMsg->label((const char *) m_pFindDlg->m_ErrMsg); + m_pFindDlg->m_pErrorMsg->show(); + + //fl_alert("Search string %s not found", pFind); + m_pFindDlg->m_pFindDlg->show(); + m_pFindDlg->m_pFind->take_focus(); + m_pFindDlg->m_pFind->selectall(); + return; + //mw->insert_position(pos); } } // Hide the dialog box - mw->take_focus(); m_pFindDlg->m_pFindDlg->hide(); + mw->take_focus(); } /* @@ -3600,6 +3609,111 @@ void VT_Ide::Stdout(const char *msg) Fl::check(); } +/* +============================================================================= +BuildProjet: This routine is the reason for all this mess! Try to assemble + each file in the project and then link if no errors. +============================================================================= +*/ +void VT_Ide::AssembleSourcesInGroup(VTAssembler& assembler, VT_IdeGroup* pGroup, int& totalErrors, + int& linkerScriptFound, MString& linkerScript, MString& linkerFiles) +{ + int groups, sources; + int c, x, err; + int index; + VT_IdeGroup* pSubGroup; + VT_IdeSource* pSource; + int errorCount; + MString text, temp; + int assemblyNeeded; + MStringArray errors; + MString filename; + + // Loop through each source in group + sources = pGroup->m_Objects.GetSize(); + for (x = 0; x < sources; x++) + { + // Test if this entry is a group or a source + if (strcmp(pGroup->m_Objects[x]->GetClass()->m_ClassName, "VT_IdeGroup") == 0) + { + // Sub group found. Assemble all source files in this group + + pSubGroup = (VT_IdeGroup *) pGroup->m_Objects[x]; + AssembleSourcesInGroup(assembler, pSubGroup, totalErrors, linkerScriptFound, + linkerScript, linkerFiles); + continue; + } + + // Configure the assembler + assembler.ResetContent(); + assembler.SetRootPath(m_ActivePrj->m_RootPath); + assembler.SetAsmOptions(m_ActivePrj->m_AsmOptions); + assembler.SetIncludeDirs(m_ActivePrj->m_IncludePath); + assembler.SetDefines(m_ActivePrj->m_Defines); + assembler.SetProjectType(m_ActivePrj->m_ProjectType); + assembler.SetStdoutFunction(this, ideStdoutProc); + + // Get next source from group + pSource = (VT_IdeSource*) pGroup->m_Objects[x]; + + // Get extension of this source + + // Test if source is .asm or .a85 + assemblyNeeded = FALSE; + temp = pSource->m_Name.Right(4); + temp.MakeLower(); + if ((temp == ".asm") || (temp == ".a85")) + { + // Check source dependencies + + assemblyNeeded = TRUE; + + // Delete old .obj file + + // Add this file to the list of files to be linked + temp = pSource->m_Name.Left(pSource->m_Name.GetLength() - 4) + (char *) ".obj"; + linkerFiles += temp + (char *) ","; + } + + // Try to assemble the file + if (assemblyNeeded) + { + // Display build indication + index = pSource->m_Name.ReverseFind('/'); + temp = pSource->m_Name.Right(pSource->m_Name.GetLength()-index-1); + text.Format("%s\n", (const char *) temp); + m_BuildTextBuf->append((const char *) text); + Fl::check(); + + // Try to assemble this file + filename = MakePathAbsolute(pSource->m_Name, m_ActivePrj->m_RootPath); + assembler.Parse(filename); + + // Check if any errors occurred & report them + errors = assembler.GetErrors(); + errorCount = errors.GetSize(); + totalErrors += errorCount; + for (err = 0; err < errorCount; err++) + { + m_BuildTextBuf->append((const char *) errors[err]); + m_BuildTextBuf->append("\n"); + } + } + + // Look for linker scripts while we are looping through the tree + if (temp == ".lkr") + { + if (pSource->m_Name[0] == '/' || pSource->m_Name[1] == ':') + linkerScript = pSource->m_Name; + else + { + linkerScript = m_ActivePrj->m_RootPath + (char *) "/"+ pSource->m_Name; + } + linkerScriptFound = true; + } + } +} + /* ============================================================================= BuildProjet: This routine is the reason for all this mess! Try to assemble @@ -3633,12 +3747,14 @@ void VT_Ide::BuildProject(void) Fl::check(); // Configure the assembler +#if 0 assembler.SetRootPath(m_ActivePrj->m_RootPath); assembler.SetAsmOptions(m_ActivePrj->m_AsmOptions); assembler.SetIncludeDirs(m_ActivePrj->m_IncludePath); assembler.SetDefines(m_ActivePrj->m_Defines); assembler.SetProjectType(m_ActivePrj->m_ProjectType); assembler.SetStdoutFunction(this, ideStdoutProc); +#endif m_BuildTextBuf->append("Assembling...\n"); Fl::check(); @@ -3651,70 +3767,7 @@ void VT_Ide::BuildProject(void) // Get group pGroup = (VT_IdeGroup*) m_ActivePrj->m_Groups[c]; - // Loop through each source in group - sources = pGroup->m_Objects.GetSize(); - for (x = 0; x < sources; x++) - { - // Get next source from group - pSource = (VT_IdeSource*) pGroup->m_Objects[x]; - - // Get extension of this source - - // Test if source is .asm or .a85 - assemblyNeeded = FALSE; - temp = pSource->m_Name.Right(4); - temp.MakeLower(); - if ((temp == ".asm") || (temp == ".a85")) - { - // Check source dependencies - - assemblyNeeded = TRUE; - - // Delete old .obj file - - // Add this file to the list of files to be linked - temp = pSource->m_Name.Left(pSource->m_Name.GetLength() - 4) + (char *) ".obj"; - linkerFiles += temp + (char *) ","; - } - - // Try to assemble the file - if (assemblyNeeded) - { - // Display build indication - index = pSource->m_Name.ReverseFind('/'); - temp = pSource->m_Name.Right(pSource->m_Name.GetLength()-index-1); - text.Format("%s\n", (const char *) temp); - m_BuildTextBuf->append((const char *) text); - Fl::check(); - - // Try to assemble this file - filename = MakePathAbsolute(pSource->m_Name, m_ActivePrj->m_RootPath); - assembler.ResetContent(); - assembler.Parse(filename); - - // Check if any errors occurred & report them - errors = assembler.GetErrors(); - errorCount = errors.GetSize(); - totalErrors += errorCount; - for (err = 0; err < errorCount; err++) - { - m_BuildTextBuf->append((const char *) errors[err]); - m_BuildTextBuf->append("\n"); - } - } - - // Look for linker scripts while we are looping through the tree - if (temp == ".lkr") - { - if (pSource->m_Name[0] == '/' || pSource->m_Name[1] == ':') - linkerScript = pSource->m_Name; - else - { - linkerScript = m_ActivePrj->m_RootPath + (char *) "/"+ pSource->m_Name; - } - linkerScriptFound = true; - } - } + AssembleSourcesInGroup(assembler, pGroup, totalErrors, linkerScriptFound, linkerScript, linkerFiles); } // Check if there were any erros during assembly and if not, @@ -3970,15 +4023,19 @@ MString VT_Ide::MakePathAbsolute(const MString& path, const MString& relTo) { index = newRel.ReverseFind('/'); if (index != -1) - newRel = newRel.Left(index - 1); + { + newRel = newRel.Left(index); + } else { index = newRel.ReverseFind('\\'); if (index != -1) - newRel = newRel.Left(index - 1); + newRel = newRel.Left(index); else break; } + + temp = temp.Right(temp.GetLength()-3); } temp = newRel + '/' + temp; @@ -4055,7 +4112,7 @@ VT_FindDlg routines below. VT_FindDlg::VT_FindDlg(class VT_Ide* pParent) { // Create Find What combo list - m_pFindDlg = new Fl_Window(400, 300, "Find"); + m_pFindDlg = new Fl_Window(400, 340, "Find"); Fl_Box *o = new Fl_Box(20, 10, 100, 25, "Find what:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); m_pFind = new Flu_Combo_List(20, 35, 360, 25, ""); @@ -4082,13 +4139,17 @@ VT_FindDlg::VT_FindDlg(class VT_Ide* pParent) m_pMatchCase = new Fl_Check_Button(40, 185, 100, 25, "Match case"); m_pWholeWord = new Fl_Check_Button(40, 210, 140, 25, "Match whole word"); - o = new Fl_Box(20, 250, 50, 45, ""); + m_pErrorMsg = new Fl_Box(40, 250, 300, 25); + m_pErrorMsg->labelfont(m_pErrorMsg->labelfont()+1); + m_pErrorMsg->hide(); + + o = new Fl_Box(20, 300, 50, 45, ""); m_pFindDlg->resizable(o); - m_pNext = new Flu_Return_Button(160, 255, 100, 25, "Find Next"); + m_pNext = new Flu_Return_Button(160, 295, 100, 25, "Find Next"); m_pNext->callback(cb_find_next, this); - m_pCancel = new Flu_Button(280, 255, 100, 25, "Close"); + m_pCancel = new Flu_Button(280, 295, 100, 25, "Close"); m_pCancel->callback(cb_replace_cancel, this); o = new Fl_Box(20, 295, 360, 2, ""); m_pFindDlg->resizable(o); diff --git a/src/ide.h b/src/ide.h index b86e816..72441bd 100644 --- a/src/ide.h +++ b/src/ide.h @@ -55,6 +55,8 @@ void cb_Ide(Fl_Widget* w, void*) ; #define MENU_HEIGHT 32 #endif +class VTAssembler; + class VT_IdeSource : public VTObject { DECLARE_DYNCREATE(VT_IdeSource); @@ -111,6 +113,9 @@ class VT_FindDlg Fl_Check_Button* m_pWholeWord; Flu_Button* m_pNext; Flu_Button* m_pCancel; + Fl_Box* m_pErrorMsg; + + MString m_ErrMsg; class VT_Ide* m_pParent; @@ -158,6 +163,9 @@ class VT_Ide : public Fl_Window void OpenTreeFile(Flu_Tree_Browser::Node* n); void AssembleTreeFile(Flu_Tree_Browser::Node* n); void TreeFileProperties(Flu_Tree_Browser::Node* n); + void AssembleSourcesInGroup(VTAssembler& assembler, VT_IdeGroup* pGroup, + int& totalErrors, int& linkerScriptFound, MString& linkerScript, + MString& linkerFiles); void BuildProject(void); void CleanProject(void); void SetColors(int fg, int bg); diff --git a/src/linker.cpp b/src/linker.cpp index eadae20..28f5980 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -10,6 +10,7 @@ Written: 11/13/09 Kenneth D. Pettit #include "VirtualT.h" #include "linker.h" +#include "assemble.h" #include "elf.h" #include "project.h" #include @@ -37,8 +38,7 @@ static const char *gLoaderCode[] = { "97IFK<>%dTHEN99ELSE PRINT@200,\"Success! Issue command: clear 256,%d\"\x0D\x0A", "98SAVEM\"%s\",%d,%d,%d:END\x0D\x0A", "99PRINT@200,\"Chksum error! Need %d, got\";K:END\x0D\x0A", - - // These are used for PC-8201 and PC-8300 links +// These are used for PC-8201 and PC-8300 links "96CLS:DEFDBLV:LOCATE10,1:PRINT\"Creating %s\":LOCATE9,3:PRINT\"|\"SPACE$(21)\"|\";:D=59:I=%.3f:S=%d:M=256:FORJ%%=1TO%d:READA$:GOSUB90:NEXT\x0D\x0A", "97IFK<>%dTHEN99ELSE LOCATE0,5:PRINT\"Success! Issue command: clear 256,%d\"\x0D\x0A", "98BSAVE\"%s\",%d,%d,%d:END\x0D\x0A", @@ -63,6 +63,7 @@ VTLinker::VTLinker() m_TotalDataSpace = 0; m_EntryAddress = 0; m_StartAddress = 0; + m_LinkDone = FALSE; // Clear out the Segment assignement map for (x = 0; x < sizeof(m_SegMap) / sizeof(CObjSegment *); x++) @@ -109,6 +110,7 @@ void VTLinker::ResetContent(void) MStringArray* pStrArray; CObjSymFile* pObjSymFile; POSITION pos; + int x; // Loop through each segment pos = m_ObjFiles.GetStartPosition(); @@ -179,6 +181,10 @@ void VTLinker::ResetContent(void) m_FileIndex = -1; m_ObjDirs.RemoveAll(); + // Reset the AddrLines array + for (x = 0; x < 65536; x++) + m_AddrLines.a[x].pObjFile = NULL; + // Assign active assembly pointers m_Hex = FALSE; m_DebugInfo = FALSE; @@ -252,6 +258,13 @@ void VTLinker::ProcessArgs(MString &str, const char *pDelim) // Set the linker script filename m_LinkerScript = pTok + 1; } + + // Test for OptROM Bytes + else if (*pTok == 'b') + { + // Get pointer to next token + pTok = strtok(NULL, pDelim); + } } else { @@ -320,6 +333,14 @@ int VTLinker::MapScriptCommand(const char *pStr, int lineNo) else if (strcmp(pStr, "DEFINE") == 0) command = LKR_CMD_DEFINE; + // Test for PRELINK specification + else if (strcmp(pStr, "PRELINK") == 0) + command = LKR_CMD_PRELINK; + + // Test for POSTLINK specification + else if (strcmp(pStr, "POSTLINK") == 0) + command = LKR_CMD_POSTLINK; + else { // Syntax error @@ -398,37 +419,201 @@ void VTLinker::ProcScriptField2(const char *pStr, int lineNo, MString &segname) ============================================================================ This routine evaluates the string provided and returns it's value. The string can be decimal, hex, etc. and can contain simple math. + +END=Preamble_start + (1 + COUNT*4+a)*2 + ============================================================================ */ -int VTLinker::EvaluateScriptAddress(const char *pStr, int lineNo) +typedef struct { - int len = strlen(pStr); - int hex = 0; - int address; + char op; + char* val; +} SimpleEqOperator_t; + +#define SIMPLE_EQ_PAREN 0 +#define SIMPLE_EQ_ADD 1 +#define SIMPLE_EQ_SUB 2 +#define SIMPLE_EQ_MULT 3 +#define SIMPLE_EQ_DIV 4 +#define SIMPLE_EQ_VALUE 6 +#define SIMPLE_EQ_NOADD 10 + +int VTLinker::EvaluateScriptAddress(const char *pEq, int lineNo) +{ + int len = strlen(pEq); + int hex = 0; + int stack[10]; + int slevel = 0; + int address, x; + char op, unwindto; + char *token, *pStr; + SimpleEqOperator_t eq[20]; + SimpleEqOperator_t build[20]; + char temp[256]; + int eqsize = 0; + int buildidx = 0; + int value; + + strncpy(temp, pEq, sizeof(temp)); + pStr = temp; + token = pStr; + for (x = 0; x < len; ) + { + // Find end of next token + while (*pStr != '+' && *pStr != '-' && *pStr != '*' && *pStr != '/' && *pStr != 0 && + *pStr != '(' && *pStr != ')') + { + pStr++; + x++; + } + op = *pStr; + *pStr = 0; + + if (strlen(token) > 0) + { + // Push the value to the equation + eq[eqsize].op = SIMPLE_EQ_VALUE; + eq[eqsize++].val = token; + } + + switch (op) + { + case '+': + op= SIMPLE_EQ_ADD; + unwindto = SIMPLE_EQ_ADD; + break; - // Test for Hex conversion - if (*pStr == '$') - { - hex = 1; // Indicate HEX conversion - pStr++; // Skip the '$' hex delimiter + case '-': + op = SIMPLE_EQ_SUB; + unwindto = SIMPLE_EQ_ADD; + break; + + case '*': + op = SIMPLE_EQ_MULT; + unwindto = SIMPLE_EQ_ADD; + break; + case '/': + op = SIMPLE_EQ_DIV; + unwindto = SIMPLE_EQ_ADD; + break; + + case '(': + build[buildidx++].op = SIMPLE_EQ_PAREN; + unwindto = 99; + break; + + case ')': + op = SIMPLE_EQ_NOADD; + unwindto = SIMPLE_EQ_PAREN; + break; + default: + op = SIMPLE_EQ_NOADD; + break; + } + + // Unwind the build stack + while (buildidx > 0 && build[buildidx-1].op >= unwindto) + { + if (build[buildidx-1].op != SIMPLE_EQ_PAREN) + eq[eqsize++].op = build[buildidx-1].op; + buildidx--; + } + + if (op != SIMPLE_EQ_NOADD) + build[buildidx++].op = op; + + x++; + token = ++pStr; } - else if ((*pStr == '0') && (*(pStr + 1) == 'x')) + while (buildidx > 0) { - hex = 1; - pStr += 2; // Skip the "0x" hex delimiter + eq[eqsize++].op = build[buildidx-1].op; + buildidx--; } - else if ((pStr[len-1] == 'h') || (pStr[len-1] == 'H')) + + // Evaluate equation + for (x = 0; x < eqsize; x++) { - hex = 1; - } + if (eq[x].op == SIMPLE_EQ_VALUE) + { + token = eq[x].val; - // Perform the conversion - if (hex) - sscanf(pStr, "%x", &address); - else - sscanf(pStr, "%d", &address); + // Lookup symbol in active module + CObjSymFile* pSymFile; + if (m_Symbols.Lookup(token, (VTObject *&) pSymFile)) + { + // If symbol was found, try to evaluate it + if (pSymFile != (CObjSymFile*) NULL) + { + // First get a pointer to the section referenced by the symbol + CObjFileSection* pSymSect = (CObjFileSection *) pSymFile->m_pObjFile->m_FileSections[pSymFile->m_pSym->st_shndx]; + + // Get the symbol value + value = (unsigned short) pSymFile->m_pSym->st_value; + if (pSymSect->m_Type == ASEG || m_LinkDone) + { + stack[slevel++] = value; + } + else + stack[slevel++] = 0; + } + else + stack[slevel++] = 0; + } + else + { + // Test for Hex conversion + if (*token == '$') + { + hex = 1; // Indicate HEX conversion + token++; // Skip the '$' hex delimiter + } + else if ((*token == '0') && (*(token + 1) == 'x')) + { + hex = 1; + token += 2; // Skip the "0x" hex delimiter + } + else if ((token[len-1] == 'h') || (token[len-1] == 'H')) + { + hex = 1; + } + + // Perform the conversion + if (hex) + sscanf(token, "%x", &address); + else + sscanf(token, "%d", &address); - return address; + stack[slevel++] = address; + } + } + else if (eq[x].op == SIMPLE_EQ_ADD) + { + // Add the 2 top stack items and save in stack + value = stack[--slevel]; + stack[slevel-1] += value; + } + else if (eq[x].op == SIMPLE_EQ_SUB) + { + // Subtract top stack item from next one down + value = stack[--slevel]; + stack[slevel-1] -= value; + } + else if (eq[x].op == SIMPLE_EQ_MULT) + { + // Subtract top stack item from next one down + value = stack[--slevel]; + stack[slevel-1] *= value; + } + else if (eq[x].op == SIMPLE_EQ_DIV) + { + // Subtract top stack item from next one down + value = stack[--slevel]; + stack[slevel-1] /= value; + } + } + + return stack[slevel - 1]; } /* @@ -783,6 +968,9 @@ void VTLinker::NewLinkRegion(int type, int lineNo, int startAddr, err.Format("Error in line %d(%s): Linker script address ranges cannot overlap", lineNo, (const char *) m_LinkerScript); m_Errors.Add(err); + err.Format(" Range %X-%X and %X-%X\n", pThisRange->startAddr, pThisRange->endAddr, + startAddr, endAddr); + m_Errors.Add(err); m_Command = LKR_CMD_ERROR; return; } @@ -1164,12 +1352,16 @@ CObjFile object provided. int VTLinker::ReadSectionData(FILE* fd, CObjFile* pObjFile, CObjFileSection* pFileSection) { - int bytes = 0, count, c; - MString err; - Elf32_Shdr* pHdr = &pFileSection->m_ElfHeader; - Elf32_Sym* pSym; - Elf32_Rel* pRel; - CObjSymFile* pSymFile; + int bytes = 0, count, c, size, idx; + MString err, sourcefile; + Elf32_Shdr* pHdr = &pFileSection->m_ElfHeader; + Elf32_Sym* pSym; + Elf32_Rel* pRel; + Elf32_LinkEq eqent; + Elf32_Half namelen; + CObjSymFile* pSymFile; + CLinkerEquation* pEq; + char eqdata[2048]; if (pHdr->sh_offset != 0) fseek(fd, pHdr->sh_offset, SEEK_SET); @@ -1279,6 +1471,8 @@ int VTLinker::ReadSectionData(FILE* fd, CObjFile* pObjFile, // Allocate space for bytes and read from file pFileSection->m_pProgBytes = new char[pHdr->sh_size]; pFileSection->m_Size = pHdr->sh_size; + pFileSection->m_Line = pHdr->sh_addralign & 0xFFFF; + pFileSection->m_LastLine = pHdr->sh_addralign >> 16; if (pFileSection->m_pProgBytes != NULL) bytes = fread(pFileSection->m_pProgBytes, 1, pHdr->sh_size, fd); @@ -1324,7 +1518,7 @@ int VTLinker::ReadSectionData(FILE* fd, CObjFile* pObjFile, // Allocate new symbol and read data from the file pRel = new Elf32_Rel; if (pRel != NULL) - bytes = fread(pRel, 1, sizeof(Elf32_Rel), fd); + bytes = fread(pRel, 1, sizeof(Elf32_Rel), fd); // Test for error during read or allocate if (bytes != sizeof(Elf32_Rel)) @@ -1341,6 +1535,85 @@ int VTLinker::ReadSectionData(FILE* fd, CObjFile* pObjFile, pFileSection->m_Reloc.Add((VTObject *) pRel); } break; + + /* Read in the Linker Equations */ + case SHT_LINK_EQ: + size = pHdr->sh_size; + + // Read the source file name + bytes = fread(&namelen, 1, sizeof(namelen), fd); + bytes = fread(eqdata, 1, namelen, fd); + if (bytes != namelen) + { + err.Format("%sUnable to read equation data for %s", + gsEdl, (const char *) pObjFile->m_Name); + m_Errors.Add(err); + return FALSE; + } + sourcefile = eqdata; + + while (size) + { + pEq = new CLinkerEquation; + pEq->m_pRpnEq = new CRpnEquation; + + // Read equation header + bytes = fread(&eqent, 1, sizeof(eqent), fd); + + // Read equation data from the file + bytes = fread(eqdata, 1, eqent.st_len - sizeof(eqent), fd); + if (bytes != eqent.st_len - sizeof(eqent)) + { + err.Format("%sUnable to read equation data for %s", + gsEdl, (const char *) pObjFile->m_Name); + m_Errors.Add(err); + if (pEq != NULL) + delete pEq; + return FALSE; + } + + // Save the index of the relative segment + pEq->m_Segment = eqent.st_info; + pEq->m_Address = eqent.st_addr; + pEq->m_Size = eqent.st_size; + pEq->m_Line = eqent.st_line; + pEq->m_Sourcefile = sourcefile; + + // Build the equation from the data + count = eqent.st_num; + idx = 0; + for (c = 0; c < count; c++) + { + int operation = eqdata[idx]; + idx++; + + switch (operation) + { + case RPN_VALUE: + pEq->m_pRpnEq->Add(atof(&eqdata[idx])); + idx += strlen(&eqdata[idx])+1; + break; + + case RPN_VARIABLE: + pEq->m_pRpnEq->Add(RPN_VARIABLE, (const char *) &eqdata[idx]); + idx += strlen(&eqdata[idx])+1; + break; + + default: + pEq->m_pRpnEq->Add(operation); + break; + } + + } + + // Subtract equation size from total section size + size -= eqent.st_len; + + // Add the equation to the array + pFileSection->m_Equations.Add((VTObject *) pEq); + } + break; + } return TRUE; @@ -1589,9 +1862,9 @@ int VTLinker::LocateSegmentIntoRegion(MString& region, CObjFileSection* pFileSec // Validate the range was found if ((pAddrRange == NULL) || (pAddrRange->startAddr > locateAddr) || - (locateAddr + segSize > pAddrRange->endAddr)) + (locateAddr + segSize-1 > pAddrRange->endAddr)) { - err.Format("%sNo Link Range found for ASEG %s (addr=%d, size=%d)", gsEdl, + err.Format("%sNo link range found for ASEG %s (addr=%d, size=%d)", gsEdl, (const char *) segment, locateAddr, segSize); m_Errors.Add(err); return FALSE; @@ -1980,13 +2253,13 @@ int VTLinker::LocateSegments() /* ============================================================================ -Now that all segments have been located, this function assigns physical -addresses to local values, such as data, jump and call addresses, etc. +This routine finds the file section referenced by the relocation object +pRel in th especified object file. ============================================================================ */ CObjFileSection* VTLinker::FindRelSection(CObjFile* pObjFile, Elf32_Rel* pRel) { - int sectCount, sect; + int sectCount, sect, type; CObjFileSection* pFileSect; CObjFileSection* pRelSect; @@ -1999,7 +2272,8 @@ CObjFileSection* VTLinker::FindRelSection(CObjFile* pObjFile, Elf32_Rel* pRel) if (pFileSect->m_ElfHeader.sh_offset < pRel->r_offset) { // Validate the section type - if ((ELF32_R_TYPE(pRel->r_info) == SR_ADDR_XLATE) && + type = ELF32_R_TYPE(pRel->r_info); + if ((type == SR_ADDR_XLATE || type == SR_8BIT || type == SR_24BIT) && (pFileSect->m_ElfHeader.sh_type != SHT_PROGBITS)) continue; @@ -2029,7 +2303,7 @@ int VTLinker::ResolveLocals() CObjFile* pObjFile; CObjFileSection* pFileSect; CObjFileSection* pRelSect; - int sect, sectCount, rel, relCount; + int sect, sectCount, rel, relCount, type; MString err, filename; // Exit if error has occurred @@ -2054,7 +2328,8 @@ int VTLinker::ResolveLocals() { // Process this relocation item Elf32_Rel* pRel = (Elf32_Rel *) pFileSect->m_Reloc[rel]; - if (ELF32_R_TYPE(pRel->r_info) == SR_ADDR_XLATE) + type = ELF32_R_TYPE(pRel->r_info); + if (type == SR_ADDR_XLATE || type == SR_8BIT || type == SR_24BIT) { CObjFileSection* pRefSect = (CObjFileSection *) pObjFile->m_FileSections[pFileSect->m_ElfHeader.sh_info]; pRelSect = FindRelSection(pObjFile, pRel); @@ -2067,15 +2342,30 @@ int VTLinker::ResolveLocals() unsigned short addr = (((unsigned short) pRelSect->m_pProgBytes[offset]) & 0xFF) | (pRelSect->m_pProgBytes[offset+1] << 8); // Update the address based on the segments locate address -// addr += pRelSect->m_LocateAddr; addr += pRefSect->m_LocateAddr; // Update the translated address in the ProgBits pRelSect->m_pProgBytes[offset] = addr & 0xFF; - pRelSect->m_pProgBytes[offset + 1] = addr >> 8; + if (type != SR_8BIT) + pRelSect->m_pProgBytes[offset + 1] = addr >> 8; + + // Save the relative update info for listing back annotation + offset += pRelSect->m_LocateAddr; + m_AddrLines.a[offset].pObjFile = pObjFile; + m_AddrLines.a[offset].line = 0; + m_AddrLines.a[offset].fdPos = -1; + m_AddrLines.a[offset].value = addr & 0xFF; + if (type != SR_8BIT) + { + m_AddrLines.a[offset+1].pObjFile = pObjFile; + m_AddrLines.a[offset+1].line = 0; + m_AddrLines.a[offset+1].fdPos = -1; + m_AddrLines.a[offset+1].value = addr >> 8; + } // Change the relocation type so we know we have translated this item pRel->r_info = ELF32_R_INFO(0, SR_ADDR_PROCESSED); + pRel->r_offset = offset; } else { @@ -2094,14 +2384,14 @@ int VTLinker::ResolveLocals() ============================================================================ Now resolved all extern symbols. ============================================================================ -*/ -int VTLinker::ResolveExterns() +*/ int VTLinker::ResolveExterns() { POSITION pos; CObjFile* pObjFile; CObjFileSection* pFileSect; - int sect, sectCount, rel, relCount; + int sect, sectCount, rel, relCount, type; MString err, filename; + VTObject* dummy; // Exit if error has occurred if (m_Errors.GetSize() != 0) @@ -2130,9 +2420,10 @@ int VTLinker::ResolveExterns() { // Process this relocation item Elf32_Rel* pRel = (Elf32_Rel *) pFileSect->m_Reloc[rel]; + type = ELF32_R_TYPE(pRel->r_info); // Test if this is an EXTERN relocation type - if (ELF32_R_TYPE(pRel->r_info) == SR_EXTERN) + if (type == SR_EXTERN || type == SR_EXTERN8) { // Get the EXTERN symbol name if (pObjFile->m_pStrTab != NULL) @@ -2152,18 +2443,22 @@ int VTLinker::ResolveExterns() { // PUBLIC symbol found! Now perform the link // First get a pointer to the section referenced by the symbol - CObjFileSection* pSymSect = (CObjFileSection *) pSymFile->m_pObjFile->m_FileSections[pSymFile->m_pSym->st_shndx]; + CObjFileSection* pSymSect = (CObjFileSection *) + pSymFile->m_pObjFile->m_FileSections[pSymFile->m_pSym->st_shndx]; // Calculate the value of the EXTERN symbol unsigned short value = (unsigned short) pSymFile->m_pSym->st_value; - if (pSymSect->m_Type != ASEG) + if (pSymSect->m_Type != ASEG && ((pSymFile->m_pSym->st_info & 0x0F) + != STT_EQUATE)) value +=(unsigned short) pSymSect->m_LocateAddr; // Calculate the address where we update with the symbol's value if (pRel->r_offset + 1 >= (unsigned short) pObjSect->m_Size) { - err.Format("Invalid relocation offset for section %s, symbol = %s, offset = %d, size = %d\n", - (const char *) pObjSect->m_Name, (const char *) pSymName, pRel->r_offset, pObjSect->m_Size); + err.Format("Invalid relocation offset for section %s, symbol = %s, " + "offset = %d, size = %d\n", + (const char *) pObjSect->m_Name, (const char *) pSymName, + pRel->r_offset, pObjSect->m_Size); m_Errors.Add(err); } else @@ -2172,15 +2467,39 @@ int VTLinker::ResolveExterns() // Update the code *pAddr++ = value & 0xFF; - *pAddr = value >> 8; + if (type != SR_EXTERN8) + *pAddr = value >> 8; + + int offset = pRel->r_offset + pObjSect->m_LocateAddr; + + // Save the relative update info for listing back annotation + m_AddrLines.a[offset].pObjFile = pObjFile; + m_AddrLines.a[offset].line = 0; + m_AddrLines.a[offset].fdPos = -1; + m_AddrLines.a[offset].value = value & 0xFF; + if (type != SR_EXTERN8) + { + m_AddrLines.a[offset+1].pObjFile = pObjFile; + m_AddrLines.a[offset+1].line = 0; + m_AddrLines.a[offset+1].fdPos = -1; + m_AddrLines.a[offset+1].value = value >> 8; + } + + // Update the relocation information + pRel->r_info = ELF32_R_INFO(0, SR_ADDR_PROCESSED); + pRel->r_offset += pObjSect->m_LocateAddr; } } else { - MString title = MakeTitle(pObjFile->m_Name); - err.Format("%sUnresolved EXTERN symbol %s referenced in file %s", gsEdl, - pSymName, (const char *) title); - m_Errors.Add(err); + if (!m_UndefSymbols.Lookup(pObjFile->m_Name, dummy)) + { + MString title = MakeTitle(pObjFile->m_Name); + err.Format("%sUnresolved symbol \"%s\" referenced in %s", + gsEdl, pSymName, (const char *) title); + m_Errors.Add(err); + m_UndefSymbols[pObjFile->m_Name] = 0; + } } } else @@ -2197,6 +2516,340 @@ int VTLinker::ResolveExterns() return TRUE; } +/* +============================================================================ +This function evaluates equations and attempts to determine a numeric value +for the equation. If a numeric value can be achieved, it updates the value +parameter and returns TRUE. If it cannot achieve a numeric value, the +function returns FALSE, and creates an error report in design if the +reportError flag is TRUE. +============================================================================ +*/ +int VTLinker::Evaluate(class CRpnEquation* eq, double* value, + int reportError, MString& errVariable, MString& filename) +{ + double s1, s2; + CSymbol* symbol; + MString errMsg, temp; + double stack[200]; + int stk = 0; + int int_value; + const char* pStr; + int c, local; + VTObject* dummy; + + // Get count of number of operations in equation and initalize stack + int count = eq->m_OperationArray.GetSize(); + + for (c = 0; c < count; c++) + { + CRpnOperation& op = eq->m_OperationArray[c]; + switch (op.m_Operation) + { + case RPN_VALUE: + stack[stk++] = op.m_Value; + break; + + case RPN_VARIABLE: + // Try to find variable in equate array + temp = op.m_Variable; + local = 0; + + // Lookup symbol in active module + pStr = (const char *) temp; + CObjSymFile* pSymFile; + if (!m_Symbols.Lookup(pStr, (VTObject *&) pSymFile)) + pSymFile = NULL; + + // If symbol was found, try to evaluate it + if (pSymFile != (CObjSymFile*) NULL) + { + // First get a pointer to the section referenced by the symbol + CObjFileSection* pSymSect = (CObjFileSection *) pSymFile->m_pObjFile->m_FileSections[pSymFile->m_pSym->st_shndx]; + + // Get the symbol value + unsigned short value = (unsigned short) pSymFile->m_pSym->st_value; + if (pSymSect->m_Type != ASEG && ELF32_ST_TYPE(pSymFile->m_pSym->st_info) + != STT_EQUATE) + value +=(unsigned short) pSymSect->m_LocateAddr; + + // Add the value to the stack + stack[stk++] = value; + break; + } + else + { + if (reportError) + { + // Check if thie symbol has already been declared undefined + if (!m_UndefSymbols.Lookup(op.m_Variable, dummy)) + { + errMsg.Format("%sin line %d(%s): Unresolved symbol %s", gsEdl, eq->m_Line, + (const char *) filename, pStr); + m_Errors.Add(errMsg); + m_UndefSymbols[op.m_Variable] = 0; + } + } + else + errVariable = op.m_Variable; + return 0; + } + break; + + case RPN_MACRO: + // Need to add code here to process macros + break; + + case RPN_MULTIPLY: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = s2 * s1; + break; + + case RPN_DIVIDE: + s2 = stack[--stk]; + s1 = stack[--stk]; + if (s2 == 0.0) + { + // Divide by zero error + if (reportError) + { + errMsg.Format("Error in line %d(%s): Divide by zero!", + eq->m_Line, (const char *) filename); + m_Errors.Add(errMsg); + } + return 0; + } + stack[stk++] = s1 / s2; + break; + + case RPN_ADD: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = s1 + s2; + break; + + case RPN_SUBTRACT: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = s1 - s2; + break; + + case RPN_EXPONENT: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = pow(s1, s2); + break; + + case RPN_MODULUS: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = (double) ((int) s1 % (int) s2); + break; + + case RPN_BITOR: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = (double) ((int) s2 | (int) s1); + break; + + case RPN_BITAND: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = (double) ((int) s2 & (int) s1); + break; + + case RPN_NEGATE: + s1 = stack[--stk]; + stack[stk++] = -s1; + break; + + case RPN_BITXOR: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = (double) ((int) s1 ^ (int) s2); + break; + + case RPN_LEFTSHIFT: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = (double) ((int) s1 << (int) s2); + break; + + case RPN_RIGHTSHIFT: + s2 = stack[--stk]; + s1 = stack[--stk]; + stack[stk++] = (double) ((int) s1 >> (int) s2); + break; + + case RPN_FLOOR: + s1 = stack[--stk]; + stack[stk++] = floor(s1); + break; + + case RPN_CEIL: + s1 = stack[--stk]; + stack[stk++] = ceil(s1); + break; + + case RPN_IP: + s1 = stack[--stk]; + stack[stk++] = floor(s1); + break; + + case RPN_FP: + s1 = stack[--stk]; + stack[stk++] = s1 - floor(s1); + break; + + case RPN_LN: + s1 = stack[--stk]; + stack[stk++] = log(s1); + break; + + case RPN_PAGE: + s1 = stack[--stk]; + stack[stk++] = ((unsigned int) s1 >> 16) & 0xFF; + break; + + case RPN_HIGH: + s1 = stack[--stk]; + stack[stk++] = ((unsigned int) s1 >> 8) & 0xFF; + break; + + case RPN_LOW: + s1 = stack[--stk]; + stack[stk++] = (unsigned int) s1 & 0xFF; + break; + + case RPN_LOG: + s1 = stack[--stk]; + stack[stk++] = log10(s1); + break; + + case RPN_SQRT: + s1 = stack[--stk]; + stack[stk++] = sqrt(s1); + break; + +#if 0 + case RPN_DEFINED: + if (LookupSymbol(op.m_Variable, symbol)) + stack[stk++] = 1.0; + else + stack[stk++] = 0.0; + break; +#endif + + case RPN_NOT: + s1 = stack[--stk]; + if (s1 == 0.0) + stack[stk++] = 1.0; + else + stack[stk++] = 0.0; + break; + + case RPN_BITNOT: + s1 = stack[--stk]; + stack[stk++] = (double) (~((int) s1)); + break; + + } + errVariable = ""; + } + + // Get the result from the equation and return to calling function + *value = stack[--stk]; + + return 1; +} + +/* +============================================================================ +Now resolved all equations. +============================================================================ +*/ +int VTLinker::ResolveEquations() +{ + POSITION pos; + CObjFile* pObjFile; + CObjFileSection* pFileSect; + int sect, sectCount, c, relCount, eqCount; + MString err, errVar, filename; + double value; + + // Exit if error has occurred + if (m_Errors.GetSize() != 0) + return FALSE; + + // Loop for all object files loaded + pos = m_ObjFiles.GetStartPosition(); + while (pos != NULL) + { + // Get pointer to this object file's data + m_ObjFiles.GetNextAssoc(pos, filename, (VTObject *&) pObjFile); + + // Loop through all segments and look for equation info + sectCount = pObjFile->m_FileSections.GetSize(); + for (sect = 0; sect < sectCount; sect++) + { + // Loop through equation segments + pFileSect = (CObjFileSection *) pObjFile->m_FileSections[sect]; + + if (pFileSect->m_Type != SHT_LINK_EQ) + continue; + + eqCount = pFileSect->m_Equations.GetSize(); + for (c = 0; c < eqCount; c++) + { + // Process this equation item + CLinkerEquation* pEq = (CLinkerEquation *) pFileSect->m_Equations[c]; + CObjFileSection* pObjSect = (CObjFileSection *) pObjFile->m_FileSections[pEq->m_Segment]; + + // Try to evaluate the equation + if (Evaluate(pEq->m_pRpnEq, &value, 0, errVar, pObjSect->m_Name)) + { + // Calculate the address where we update with the symbol's value + if (pEq->m_Address + 1 >= (unsigned short) pObjSect->m_Size) + { + err.Format("Invalid relocation offset for section %s, offset = %d, size = %d\n", + (const char *) pObjSect->m_Name, pEq->m_Address, pObjSect->m_Size); + m_Errors.Add(err); + } + else + { + char * pAddr = pObjSect->m_pProgBytes + pEq->m_Address; + + // Update the code + *pAddr++ = (unsigned int) value & 0xFF; + *pAddr = (unsigned int) value >> 8; + + int offset = pObjSect->m_LocateAddr + pEq->m_Address; + + // Save the relative update info for listing back annotation + m_AddrLines.a[offset].pObjFile = pObjFile; + m_AddrLines.a[offset].line = 0; + m_AddrLines.a[offset].fdPos = -1; + m_AddrLines.a[offset].value = (int) value & 0xFF; + m_AddrLines.a[offset+1].pObjFile = pObjFile; + m_AddrLines.a[offset+1].line = 0; + m_AddrLines.a[offset+1].fdPos = -1; + m_AddrLines.a[offset+1].value = (int) value >> 8; + } + } + else + { + MString title = MakeTitle(pObjFile->m_Name); + err.Format("Error in line %d(%s): Unresolved symbol %s", pEq->m_Line, + (const char *) pEq->m_Sourcefile, (const char *) errVar); + m_Errors.Add(err); + } + } + } + } + + return TRUE; +} /* ============================================================================ Generate the output file(s). For .CO projects, this will be the .CO file, @@ -2206,7 +2859,7 @@ for library files, a .lib, and for ROM projects, it will be a HEX file. int VTLinker::GenerateOutputFile() { int startAddr, endAddr, entryAddr; - int c; + int c, size, index; unsigned char temp; const int addrSize = sizeof(m_SegMap) / sizeof(void *); MString err; @@ -2358,20 +3011,30 @@ int VTLinker::GenerateOutputFile() // Allocate a 32K memory region to hold the ROM contents char * pRom = new char[32768]; + char fillchar = 0; + + if (m_LinkOptions.Find((char *) "-f") != -1) + fillchar = 0xFF; // Fill contents with zero for (c = 0; c < 32768; c++) - pRom[c] = 0; + pRom[c] = fillchar; + + size = 32768; + if ((index = m_LinkOptions.Find((char *) "-b")) != -1) + { + size = m_LinkOptions.ToInt(index+2); + } // Copy the output data to the ROM storage - for (c = 0; c < 32768; ) + for (c = 0; c < size; ) { // Skip empty space in the link map - while (m_SegMap[c] == NULL && c < 32768) + while (m_SegMap[c] == NULL && c < size) c++; // Write the next block of bytes - if (c < 32768) + if (c < size) { CObjFileSection *pSect = m_SegMap[c]; if (pSect != NULL) @@ -2385,7 +3048,7 @@ int VTLinker::GenerateOutputFile() } // Write the ROM data to the HEX file. File is closed by the routine - save_hex_file_buf(pRom, 0, 32767, 0, fd); + save_hex_file_buf(pRom, 0, size-1, 0, fd); // Write the data out as a REX .BX file also... int dot = m_OutputName.ReverseFind('.'); @@ -2409,7 +3072,7 @@ int VTLinker::GenerateOutputFile() } // The REX BX file is a simple binary dump of the ROM contents - fwrite(pRom, 1, 32768, fd); + fwrite(pRom, 1, size, fd); fclose(fd); // Delete the ROM memory @@ -2420,6 +3083,8 @@ int VTLinker::GenerateOutputFile() else if (m_ProjectType == VT_PROJ_TYPE_LIB) { } + + m_LinkDone = TRUE; return TRUE; } @@ -2629,7 +3294,7 @@ int VTLinker::GenerateMapFile(void) { MString err, filename; FILE* fd; - int c, count; + int c, count, addr; int codeSize = 0, dataSize = 0; VTObArray m_Sorted; @@ -2752,15 +3417,21 @@ int VTLinker::GenerateMapFile(void) count = m_Sorted.GetSize(); for (c = 0; c < count; c++) { + CFileString fstr; + pObjSymFile = (CObjSymFile *) m_Sorted[c]; CObjFileSection* pSymSect = (CObjFileSection *) pObjSymFile->m_pObjFile->m_FileSections[ pObjSymFile->m_pSym->st_shndx]; - fprintf(fd, "%25s 0x%04x %9s %s\n", pObjSymFile->m_pName, - (int) (pObjSymFile->m_pSym->st_value + pSymSect->m_LocateAddr), + addr = (int) pObjSymFile->m_pSym->st_value; + if (pSymSect->m_Type != ASEG && ELF32_ST_TYPE(pObjSymFile->m_pSym->st_info) != STT_EQUATE) + addr += (int) pSymSect->m_LocateAddr; + + fstr = pObjSymFile->m_pObjFile->m_Name; + fprintf(fd, "%35s 0x%04x %9s %s\n", pObjSymFile->m_pName, addr, ELF32_ST_TYPE(pObjSymFile->m_pSym->st_info) == STT_OBJECT ? (char *) "data" : (char *) "function", - (const char *) pObjSymFile->m_pObjFile->m_Name); + (const char *) fstr.Filename()); } // Remove all items from the sort array and re-sort by address @@ -2796,14 +3467,20 @@ int VTLinker::GenerateMapFile(void) count = m_Sorted.GetSize(); for (c = 0; c < count; c++) { + CFileString fstr; + pObjSymFile = (CObjSymFile *) m_Sorted[c]; CObjFileSection* pSymSect = (CObjFileSection *) pObjSymFile->m_pObjFile->m_FileSections[ pObjSymFile->m_pSym->st_shndx]; - fprintf(fd, "%25s 0x%04x %9s %s\n", pObjSymFile->m_pName, - (int) (pObjSymFile->m_pSym->st_value + pSymSect->m_LocateAddr), + addr = (int) pObjSymFile->m_pSym->st_value; + if (pSymSect->m_Type != ASEG && ELF32_ST_TYPE(pObjSymFile->m_pSym->st_info) != STT_EQUATE) + addr += (int) pSymSect->m_LocateAddr; + + fstr = pObjSymFile->m_pObjFile->m_Name; + fprintf(fd, "%35s 0x%04x %9s %s\n", pObjSymFile->m_pName, addr, ELF32_ST_TYPE(pObjSymFile->m_pSym->st_info) == STT_OBJECT ? (char *) "data" : (char *) "function", - (const char *) pObjSymFile->m_pObjFile->m_Name); + (const char *) fstr.Filename()); } // Remove all entries from the Sorted array @@ -2826,30 +3503,257 @@ int VTLinker::BackAnnotateListingFiles(void) { POSITION pos; CObjFile* pObjFile; -// CObjFileSection* pFileSect; + CObjFile* pOpenFile; + CObjFileSection* pFileSection; MString err, filename; + FILE* fd; + char* pRead; + char lineBuf[512]; + char str[6]; + int fdpos, fdpos2, c, x, eq, count, line; + int addr, rel, relCount; // Exit if error has occurred if (m_Errors.GetSize() != 0) return FALSE; // Test if list file generation requested - if (m_LinkOptions.Find((char *) "-t") == -1) - return FALSE; + //if (m_LinkOptions.Find((char *) "-t") == -1) + // return FALSE; - // Loop for all object files loaded and locate any that have not been located yet + // Loop for all object files loaded and update the address of all CSEG and DSEG + // segments + pos = m_ObjFiles.GetStartPosition(); while (pos != NULL) + { + // Get pointer to this object file's data + m_ObjFiles.GetNextAssoc(pos, filename, (VTObject *&) pObjFile); + + // Get the path of the source file for this object file + CFileString lstFile(pObjFile->m_Name); + lstFile.NewExt(".lst"); + + // Try to open the listing file. If no file, just move on + if ((fd = fopen((const char *) lstFile.GetString(), "r+")) == NULL) + continue; + + // Now loop through all ObjFileSections for this file and update the + // address for any CSEG or DSEG segments + count = pObjFile->m_FileSections.GetSize(); + for (c = 0; c < count; c++) + { + // Get a pointer to the next file section + pFileSection = (CObjFileSection *) pObjFile->m_FileSections[c]; + if (pFileSection->m_Type != CSEG && pFileSection->m_Type != DSEG && + pFileSection->m_Type != ASEG) + continue; + + // Start at beginning of list file and search for the starting line + fseek(fd, 0, SEEK_SET); + line = 1; + fdpos = 0; + while (line != 0 && line < pFileSection->m_Line) + { + // Read next line from listing file + pRead = fgets(lineBuf, sizeof(lineBuf), fd); + if (pRead == NULL || feof(fd)) + break; + + // Keep track of the file position + line++; + } + + // Test if end of file encoundered + if (feof(fd)) + continue; + + // Now loop for all lines in this section and update addresses + for (; line < pFileSection->m_LastLine; line++) + { + // Save the file position so we can rewind for saving new address + fdpos = ftell(fd); + + // Read in the next line + pRead = fgets(lineBuf, sizeof(lineBuf), fd); + if (pRead == NULL || feof(fd)) + break; + + // Check if this line has an address at col 1 + if (lineBuf[0] == ' ') + continue; + + // Okay, we need to add our segment start address to the address + // (offset) reported in the listing file + sscanf(lineBuf, "%X", &addr); + if (pFileSection->m_Type != ASEG) + { + addr += pFileSection->m_LocateAddr; + sprintf(lineBuf, "%04X", addr); + + // Seek back, write the new addr and then restore + fdpos2 = ftell(fd); + fseek(fd, fdpos, SEEK_SET); + fwrite(lineBuf, 1, 4, fd); + fseek(fd, fdpos2, SEEK_SET); + } + + // Add this address to our AddrLines array + m_AddrLines.a[addr].line = line; + m_AddrLines.a[addr].fdPos = fdpos+6; + + // Check if this line has multiple bytes on it and add all AddrLines + for (x = 1; x < 4; x++) + { + if (lineBuf[6+x*3] != ' ') + { + m_AddrLines.a[addr+x].line = line; + m_AddrLines.a[addr+x].fdPos = fdpos+6+x*3; + } + else + break; + } + } + } + + // Close the listing file + fclose(fd); + } + + // Now loop through all relocate items and replace the offsets with actual addresses + // Loop for all object files loaded pos = m_ObjFiles.GetStartPosition(); + pOpenFile = NULL; while (pos != NULL) { // Get pointer to this object file's data m_ObjFiles.GetNextAssoc(pos, filename, (VTObject *&) pObjFile); - // Get the path of the source file for this object file + // Loop through all segments and look for relocation info + count = pObjFile->m_FileSections.GetSize(); + for (c = 0; c < count; c++) + { + // Loop through relocation segments + pFileSection = (CObjFileSection *) pObjFile->m_FileSections[c]; + relCount = pFileSection->m_Reloc.GetSize(); + for (rel = 0; rel < relCount; rel++) + { + // Process this relocation item + Elf32_Rel* pRel = (Elf32_Rel *) pFileSection->m_Reloc[rel]; + if (ELF32_R_TYPE(pRel->r_info) == SR_ADDR_PROCESSED) + { + // Lookup this address in the AddrLines array + if (pRel->r_offset > 0 && pRel->r_offset < 65536) + { + if (m_AddrLines.a[pRel->r_offset].pObjFile != NULL) + { + // Found! Now go update the data + if (pOpenFile != NULL && pOpenFile != pObjFile) + { + // Close the file so we can open a new one + fclose(fd); + pOpenFile = NULL; + } + + // Get the path of the source file for this object file + CFileString lstFile(m_AddrLines.a[pRel->r_offset].pObjFile->m_Name); + lstFile.NewExt(".lst"); + + // Try to open the listing file. If no file, just move on + if (pOpenFile == NULL) + { + if ((fd = fopen((const char *) lstFile.GetString(), "r+")) == NULL) + continue; + + // Mark the file as opened + pOpenFile = pObjFile; + } + + // Seek to the location in the lst file for LSB + fseek(fd, m_AddrLines.a[pRel->r_offset].fdPos, SEEK_SET); + sprintf(str, "%02X", m_AddrLines.a[pRel->r_offset].value); + fwrite(str, 1, 2, fd); + + if (m_AddrLines.a[pRel->r_offset+1].pObjFile != NULL) + { + // Seek to the location in the lst file for MSB + fseek(fd, m_AddrLines.a[pRel->r_offset+1].fdPos, SEEK_SET); + sprintf(str, "%02X", m_AddrLines.a[pRel->r_offset+1].value); + fwrite(str, 1, 2, fd); + } + } + } + } + } + + // Now loop for all equations in this section + if (pFileSection->m_Type != SHT_LINK_EQ) + continue; + + int eqCount = pFileSection->m_Equations.GetSize(); + for (eq = 0; eq < eqCount; eq++) + { + // Process this equation item + CLinkerEquation* pEq = (CLinkerEquation *) pFileSection->m_Equations[eq]; + CObjFileSection* pObjSect = (CObjFileSection *) pObjFile->m_FileSections[pEq->m_Segment]; + + int offset = pObjSect->m_LocateAddr + pEq->m_Address; + if (m_AddrLines.a[offset].pObjFile != NULL) + { + // Found! Now go update the data + if (pOpenFile != NULL && pOpenFile != pObjFile) + { + // Close the file so we can open a new one + fclose(fd); + pOpenFile = NULL; + } + + // Get the path of the source file for this object file + CFileString lstFile(m_AddrLines.a[offset].pObjFile->m_Name); + lstFile.NewExt(".lst"); + + // Try to open the listing file. If no file, just move on + if (pOpenFile == NULL) + { + if ((fd = fopen((const char *) lstFile.GetString(), "r+")) == NULL) + continue; + + // Mark the file as opened + pOpenFile = pObjFile; + } + + // Seek to the location in the lst file for LSB + fseek(fd, m_AddrLines.a[offset].fdPos, SEEK_SET); + sprintf(str, "%02X", m_AddrLines.a[offset].value); + fwrite(str, 1, 2, fd); + + if (m_AddrLines.a[offset+1].pObjFile != NULL) + { + // Seek to the location in the lst file for MSB + fseek(fd, m_AddrLines.a[offset+1].fdPos, SEEK_SET); + sprintf(str, "%02X", m_AddrLines.a[offset+1].value); + fwrite(str, 1, 2, fd); + } + } + } + } } + if (pOpenFile != NULL) + fclose(fd); + return TRUE; } +/* +============================================================================ +Process any POSTLINK commands from the Linker Script. +============================================================================ +*/ +void VTLinker::ProcessPostlink(void) +{ + if (!m_LinkDone || m_Errors.GetSize() > 0) + return; +} + /* ============================================================================ The parser calls this function to perform the link operation after all @@ -2867,12 +3771,12 @@ int VTLinker::Link() // Process the input filename list from the IDE ProcessArgs(m_ObjFileList, ",;"); - // Read the linker script - ReadLinkerScript(); - // Load all files to be linked ReadObjFiles(); + // Read the linker script + ReadLinkerScript(); + // Locate segments based on commands in the Linker Script LocateSegments(); @@ -2882,6 +3786,9 @@ int VTLinker::Link() // Resolve segment extern symbols ResolveExterns(); + // Resolve reloatable equations + ResolveEquations(); + // Generate output file GenerateOutputFile(); @@ -2893,6 +3800,9 @@ int VTLinker::Link() // Back annotate Listing files with actual addresses BackAnnotateListingFiles(); + // Process Linker Script POSTLINK commands + ProcessPostlink(); + return m_Errors.GetSize() == 0; } diff --git a/src/linker.h b/src/linker.h index 62edfeb..b8716e7 100644 --- a/src/linker.h +++ b/src/linker.h @@ -31,6 +31,9 @@ #define LKR_CMD_ENTRY 8 #define LKR_CMD_DEFINE 9 #define LKR_CMD_MIXED 10 +#define LKR_CMD_PRELINK 11 +#define LKR_CMD_POSTLINK 12 +#define LKR_CMD_ECHO 13 #define LKR_CMD_CD_DONE 0x80 #define LKR_CMD_ERROR 98 #define LKR_CMD_COMPLETE 99 @@ -56,6 +59,8 @@ #endif // Support classes for VTAssembler objects... +class CObjFile; + typedef struct sLinkAddrRange { int startAddr; int endAddr; @@ -65,6 +70,23 @@ typedef struct sLinkAddrRange { struct sLinkAddrRange* pPrev; } LinkAddrRange; +// Define a local struct to support back annotating listing files +// We will allocate an array of 65536 of these, initialize them to +// NULL pointers and then populate them as we learn of the +// fd offset for each address. +typedef struct ListAddrLines +{ + CObjFile* pObjFile; + int line; + int fdPos; + unsigned char value; +} ListAddrLines_t; + +typedef struct +{ + ListAddrLines a[65536]; +} ListAddrLinesAry_t; + class CObjSegment : public VTObject { public: @@ -125,7 +147,8 @@ class CObjFileSection : public VTObject { public: CObjFileSection() { m_pStrTab = NULL; m_pObjSegment = NULL; m_pProgBytes = NULL; m_Located = false; - m_LocateAddr = -1; m_Size = 0; m_Index = -1; }; + m_LocateAddr = -1; m_Size = 0; m_Index = -1; + m_Line = 0; m_LastLine = 0; }; ~CObjFileSection(); Elf32_Shdr m_ElfHeader; // The ELF header as read from the file @@ -133,6 +156,7 @@ class CObjFileSection : public VTObject CObjSegment* m_pObjSegment; // Pointer to the Segment data VTObArray m_Symbols; // Symbols from the symbol table VTObArray m_Reloc; // Relocation entries + VTObArray m_Equations; // Linker Equations char* m_pProgBytes; // Pointer to program bytes int m_Size; // Size of the ProgBytes int m_Index; // Index of this section in the object file @@ -140,6 +164,8 @@ class CObjFileSection : public VTObject int m_LocateAddr; // Address where the segment was located by linker MString m_Name; // Name of the section int m_Type; // Segment type for segment sections + int m_Line; // Starting line in source for segment + int m_LastLine; // Ending line in source for segment }; class CLinkRgn : public VTObject @@ -221,6 +247,7 @@ class VTLinker : public VTObject int m_TotalCodeSpace; // Total space used by code int m_TotalDataSpace; // Total space used for data int m_TargetModel; // Target model we are linking for + int m_LinkDone; // TRUE if link complete unsigned short m_StartAddress; // Start address of generated code unsigned short m_EntryAddress; // Entry address of generated code MString m_OutputName; // Name of output file @@ -233,7 +260,7 @@ class VTLinker : public VTObject MString m_EntryLabel; // Label or address of program entry MStringArray m_ObjDirs; // Array of '/' terminated object dirs CObjFileSection* m_SegMap[65536]; // Map of Segment assignements - + ListAddrLinesAry_t m_AddrLines; // Array of relative address / line mappings // Operations int GetValue(MString & string, int & value); int LookupSymbol(MString& name, CObjSymbol *& symbol); @@ -275,6 +302,7 @@ class VTLinker : public VTObject CObjFileSection* FindRelSection(CObjFile* pObjFile, Elf32_Rel* pRel); int ResolveLocals(); int ResolveExterns(); + int ResolveEquations(); MString MakeTitle(const MString& path); int GenerateOutputFile(void); int GenerateMapFile(void); @@ -282,6 +310,8 @@ class VTLinker : public VTObject int CreateQuintuple(FILE* fd, unsigned long& ascii85, int& lineNo, int& dataCount, int& lastDataFilePos, int& lineCount, int& checksum); int GenerateLoaderFile(int startAddr, int endAddr, int entryAddr); + int Evaluate(class CRpnEquation* eq, double* value, + int reportError, MString& errVariable, MString& filename); public: // Public Access functions @@ -301,6 +331,7 @@ class VTLinker : public VTObject void SetOutputFile(const MString& outFile ); int TotalCodeSpace(void) { return m_TotalCodeSpace; } int TotalDataSpace(void) { return m_TotalDataSpace; } + void ProcessPostlink(void); }; #endif diff --git a/src/memedit.cpp b/src/memedit.cpp index fc78333..730be3f 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -1404,14 +1404,26 @@ void T100_MemEditor::SetScrollSize(void) } else { - if (region == 0) - m_Max = RAMSIZE / 16; - else if (region == 1) - m_Max = ROMSIZE / 16; - else if (region == 2) - m_Max = 1024 * 1024 / 16; - else if (region == 3) - m_Max = 128 * 1024 / 16; + if (gQuad) + { + if (region < 4) + m_Max = RAMSIZE / 16; + else if (region == 4) + m_Max = ROMSIZE / 16; + else + m_Max = 1024 * 1024 / 16; + } + else + { + if (region == 0) + m_Max = RAMSIZE / 16; + else if (region == 1) + m_Max = ROMSIZE / 16; + else if (region == 2) + m_Max = 1024 * 1024 / 16; + else if (region == 3) + m_Max = 128 * 1024 / 16; + } } } else diff --git a/src/multieditwin.cpp b/src/multieditwin.cpp index f397ac2..4a48231 100644 --- a/src/multieditwin.cpp +++ b/src/multieditwin.cpp @@ -227,7 +227,7 @@ void Fl_Multi_Edit_Window::OpenFile(const MString& filename) m_FileName = filename; ext = filename.Right(4); ext.MakeLower(); - if (ext != ".asm" && ext != ".inc" && ext != ".lkr") + if (ext != ".asm" && ext != ".inc" && ext != ".lkr" && ext != ".lst") DisableHl(); } diff --git a/src/project.cpp b/src/project.cpp index bb3904f..aec0ff5 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -394,11 +394,12 @@ void cb_settings_ok(Fl_Widget* w, void*) // Update the Linker Options pProject->LinkDebugInfo(pProj->getLinkDebugInfo()); pProject->MapFile(pProj->getMapFile()); - pProject->IgnoreStdLibs(pProj->getIgnoreStdLibs()); + pProject->Flash(pProj->getFlash()); pProject->m_LinkPath = pProj->getLinkPath(); pProject->m_LinkLibs = pProj->getLinkObjs(); pProject->m_LinkScript = pProj->getLinkScript(); pProject->m_OutputName = pProj->getOutputName(); + pProject->CustomRomSize(pProj->getCustomRomSize(), pProj->getRomBytes()); // Hide the window to end the session pProj->m_pProject->m_Dirty = 1; @@ -532,8 +533,8 @@ VT_ProjectSettings::VT_ProjectSettings(VT_Project *pProj) m_pLinkDebugInfo->value(m_pProject->LinkDebugInfo()); m_pMapFile = new Fl_Check_Button(20, 75, 170, 20, "Generate Map File"); m_pMapFile->value(m_pProject->MapFile()); - m_pIgnoreStdLibs = new Fl_Check_Button(200, 50, 165, 20, "Ingore Std Libraries"); - m_pIgnoreStdLibs->value(m_pProject->IgnoreStdLibs()); + m_pFlash = new Fl_Check_Button(200, 50, 165, 20, "FLASH (0xFF fill)"); + m_pFlash->value(m_pProject->Flash()); // Add edit fields for Code and Data segment addresses o = new Fl_Box(20, 95, 100, 20, "Linker Script"); @@ -561,6 +562,12 @@ VT_ProjectSettings::VT_ProjectSettings(VT_Project *pProj) m_pObjPath = new Fl_Input(20, 240, 320, 20, ""); m_pObjPath->value(m_pProject->m_LinkPath); + // Create Edit field for Link Dirs + m_pCustomRomSize = new Fl_Check_Button(20, 265, 100, 20, "Custom OptROM Size"); + m_pCustomRomSize->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pCustomRomSize->value(m_pProject->CustomRomSize()); + m_pRomBytes = new Fl_Input(20, 285, 320, 20, ""); + m_pRomBytes->value(m_pProject->m_RomBytes); // End the Linker tab g->end(); @@ -748,12 +755,20 @@ int VT_ProjectSettings::getMapFile(void) return m_pMapFile->value(); } -int VT_ProjectSettings::getIgnoreStdLibs(void) +int VT_ProjectSettings::getFlash(void) { - if (m_pIgnoreStdLibs == NULL) + if (m_pFlash == NULL) return 0; - return m_pIgnoreStdLibs->value(); + return m_pFlash->value(); +} + +int VT_ProjectSettings::getCustomRomSize(void) +{ + if (m_pCustomRomSize == NULL) + return 0; + + return m_pCustomRomSize->value(); } MString VT_ProjectSettings::getLinkPath(void) @@ -764,6 +779,14 @@ MString VT_ProjectSettings::getLinkPath(void) return m_pObjPath->value(); } +MString VT_ProjectSettings::getRomBytes(void) +{ + if (m_pRomBytes == NULL) + return ""; + + return m_pRomBytes->value(); +} + MString VT_ProjectSettings::getLinkObjs(void) { if (m_pLinkObjs == NULL) @@ -890,7 +913,7 @@ void VT_Project::RemoveAsmOption(char* pOpt) m_AsmOptions = temp; } -void VT_Project::AddLinkOption(char* pOpt) +void VT_Project::AddLinkOption(const char* pOpt) { int index; @@ -903,9 +926,9 @@ void VT_Project::AddLinkOption(char* pOpt) m_LinkOptions = m_LinkOptions + (char *) " " + pOpt; } -void VT_Project::RemoveLinkOption(char* pOpt) +void VT_Project::RemoveLinkOption(char* pOpt, int param) { - int index; + int index, len = 2, size; MString temp; // Determin if option already exists in m_AsmOptions @@ -913,11 +936,21 @@ void VT_Project::RemoveLinkOption(char* pOpt) if (index == -1) return; + // Test if we need to trim an option parameter also + size = m_LinkOptions.GetLength(); + if (param) + { + while (size > index + len && m_LinkOptions[index+len] == ' ') + len++; + while (size > index + len && m_LinkOptions[index+len] != ' ') + len++; + } + // Need to remove option from the m_AsmOptons string temp = m_LinkOptions.Left(index); temp.Trim(); - if (m_LinkOptions.GetLength() > index + 2) - temp += m_LinkOptions.Right(m_LinkOptions.GetLength() - (index + 2)); + if (size > index + len) + temp += m_LinkOptions.Right(m_LinkOptions.GetLength() - (index + len)); // Assign new m_AsmOptions m_LinkOptions = temp; @@ -949,17 +982,49 @@ int VT_Project::MapFile(void) const return m_LinkOptions.Find((char *) "-m", 0) != -1; } -void VT_Project::IgnoreStdLibs(int enable) +void VT_Project::Flash(int enable) { if (enable) - AddLinkOption((char *) "-i"); + AddLinkOption((char *) "-f"); else - RemoveLinkOption((char *) "-i"); + RemoveLinkOption((char *) "-f"); } -int VT_Project::IgnoreStdLibs(void) const +int VT_Project::Flash(void) const { - return m_LinkOptions.Find((char *) "-i", 0) != -1; + return m_LinkOptions.Find((char *) "-f", 0) != -1; +} + +void VT_Project::CustomRomSize(int enable, MString bytes) +{ + MString str; + + if (enable) + { + str = "-b "; + str += bytes; + AddLinkOption((const char *) str); + } + else + RemoveLinkOption((char *) "-b", 1); +} + +int VT_Project::CustomRomSize(void) +{ + int index; + + if ((index = m_LinkOptions.Find((char *) "-b", 0)) == -1) + return 0; + + m_RomBytes = ""; + index += 2; + while (index < m_LinkOptions.GetLength() && m_LinkOptions[index] == ' ') + index++; + + while (index < m_LinkOptions.GetLength() && m_LinkOptions[index] != ' ') + m_RomBytes += m_LinkOptions[index++]; + + return 1; } /* diff --git a/src/project.h b/src/project.h index d0344a9..25a2471 100644 --- a/src/project.h +++ b/src/project.h @@ -76,11 +76,13 @@ class VT_Project int LinkDebugInfo(void) const; void MapFile(int enable); int MapFile(void) const; - void IgnoreStdLibs(int enable); - int IgnoreStdLibs(void) const; + void Flash(int enable); + int Flash(void) const; + void CustomRomSize(int enable, MString bytes); + int CustomRomSize(void); - void AddLinkOption(char *pOpt); - void RemoveLinkOption(char *pOpt); + void AddLinkOption(const char *pOpt); + void RemoveLinkOption(char *pOpt, int param = 0); void SaveProject(void); void LoadProject(void); @@ -99,6 +101,7 @@ class VT_Project MString m_LinkOptions; MString m_LinkScript; MString m_OutputName; + MString m_RomBytes; VTObArray m_Groups; int m_Dirty; // Set true when project settings change int m_ProjectType; // Type of project @@ -106,9 +109,9 @@ class VT_Project int m_AutoLoad; // Load to emulator after assemble? int m_UpdateHIMEM; // Auto update HIMEM variable? int m_CreateLoader; // Create BASIC loader for .CO program? + int m_CustomRomSize; // Set TRUE to select custom ROM size MString m_LoaderFilename; // BASIC loader filename -}; - +}; class VT_NewProject { public: @@ -171,11 +174,13 @@ class VT_ProjectSettings int getLinkDebugInfo(void); int getMapFile(void); - int getIgnoreStdLibs(void); + int getFlash(void); + int getCustomRomSize(void); MString getLinkPath(void); MString getOutputName(void); MString getLinkObjs(void); MString getLinkScript(void); + MString getRomBytes(void); void ProjTypeChanged(void); void EnableUpdateHIMEM(int enable); @@ -207,13 +212,15 @@ class VT_ProjectSettings Fl_Input* m_pDefines; // Define Link tab items - Fl_Button* m_pIgnoreStdLibs; + Fl_Button* m_pFlash; Fl_Button* m_pMapFile; Fl_Button* m_pLinkDebugInfo; + Fl_Check_Button* m_pCustomRomSize; Fl_Input* m_pObjPath; Fl_Input* m_pOutputName; Fl_Input* m_pLinkObjs; Fl_Input* m_pLinkScript; + Fl_Input* m_pRomBytes; Fl_Button* m_pOk; Fl_Button* m_pCancel; diff --git a/src/rpn_eqn.h b/src/rpn_eqn.h index 6c127fe..4efbc9f 100644 --- a/src/rpn_eqn.h +++ b/src/rpn_eqn.h @@ -80,6 +80,7 @@ class CRpnEquation : public VTObject // Attributes CRpnOpArray m_OperationArray; + int m_Line; int m_EqPtr; }; From 6d1e9172874ca259aa2e233fb39135fc3ea148a6 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 3 Mar 2015 01:59:47 +0000 Subject: [PATCH 273/327] Updated the release.txt file with modifications made for v1.7. --- release.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/release.txt b/release.txt index 7a29905..dce0f30 100644 --- a/release.txt +++ b/release.txt @@ -29,6 +29,24 @@ v1.7 Not released yet 9. Added right-click menu support to easily change QUAD bank when enabled. +10. Updated linker so it back annotates listing files with actual addresses + determined during the link step. + +11. Made updates to the assembler to push unresolved equations into the object + file and added an equation evaluation function to the linker. This allows + the linker to resolve addresses that consist of a relocatable address + location (i.e. label) embedded in an equation, such as Label+12h. + +12. Added support in Linker Script for segment addresses based on known symbol + values (e.g. from an absolute address in an ASEG) and also using simple + equations involving basic math (+ - / *). + +13. Modified the IDE's Find Dialog so that when it doesn't find the requested + text, it displays the error message in the Find Dialog instead of using + the FLTK fl_alert routine. Using the fl_alert causes the main VirtualT + emulation window to come into focus instead of the IDE window, plus showing + the error in the Find Dialog box provides opportunity to modify the search. + ==================== v1.6 April 24, 2014 ==================== From bc298fe4d2f6714d04696e43e45ac7745bb5eae2 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 4 Mar 2015 02:27:51 +0000 Subject: [PATCH 274/327] Made updates to IDE tab control to deal with more tabs than can be displayed. --- release.txt | 7 + src/My_Text_Display.cpp | 34 ++-- src/ide.cpp | 9 +- src/idetabs.cpp | 349 ++++++++++++++++++++++++++++++---------- src/idetabs.h | 9 +- wish_list.txt | 52 ++++++ 6 files changed, 354 insertions(+), 106 deletions(-) create mode 100644 wish_list.txt diff --git a/release.txt b/release.txt index dce0f30..21306cf 100644 --- a/release.txt +++ b/release.txt @@ -47,6 +47,13 @@ v1.7 Not released yet emulation window to come into focus instead of the IDE window, plus showing the error in the Find Dialog box provides opportunity to modify the search. +14. Modified the non-T200 LCD emulation routines when in 2.4Mhz emulaiton mode + to more closely reflect the actual delay introduced by the LCD hardware. + +15. Updated IDE Tab control to deal with more tabs than can fit on the window. + Tabs are now clipped and a "More Files" icon is displayed to allow selection + of off-screen open file windows. + ==================== v1.6 April 24, 2014 ==================== diff --git a/src/My_Text_Display.cpp b/src/My_Text_Display.cpp index 5f9183f..4299204 100644 --- a/src/My_Text_Display.cpp +++ b/src/My_Text_Display.cpp @@ -466,13 +466,13 @@ void My_Text_Display::resize(int X, int Y, int W, int H) if (scrollbar_align() & FL_ALIGN_LEFT) { text_area.x = X+scrollbar_width()+LEFT_MARGIN+mLeftMargin; text_area.w = W-scrollbar_width()-LEFT_MARGIN-RIGHT_MARGIN*2-mLeftMargin; - mVScrollBar->resize(X, text_area.y-TOP_MARGIN, scrollbar_width(), - text_area.h+TOP_MARGIN+BOTTOM_MARGIN); + mVScrollBar->resize(X, text_area.y-TOP_MARGIN-2, scrollbar_width(), + text_area.h+TOP_MARGIN+BOTTOM_MARGIN+2); } else { text_area.x = X+LEFT_MARGIN+mLeftMargin; text_area.w = W-scrollbar_width()-LEFT_MARGIN-RIGHT_MARGIN*2-mLeftMargin-2; - mVScrollBar->resize(X+W+2-scrollbar_width(), text_area.y-TOP_MARGIN, - scrollbar_width(), text_area.h+TOP_MARGIN+BOTTOM_MARGIN); + mVScrollBar->resize(X+W+2-scrollbar_width(), text_area.y-4,//-TOP_MARGIN-4, + scrollbar_width(), text_area.h+TOP_MARGIN+BOTTOM_MARGIN+2); } } @@ -2896,9 +2896,7 @@ void My_Text_Display::draw(void) { // draw the non-text, non-scrollbar areas. if (damage() & FL_DAMAGE_ALL) { -// Fl_Region r = XRectangleRegion(0, 0, w(), h()); - fl_push_clip(0, 0, w(), h()); - // fl_clip_region(r); + fl_push_clip(0, 0, w(), h()); // fl_clip_region(r); // draw the box() int W = w(), H = h(); @@ -2915,8 +2913,12 @@ void My_Text_Display::draw(void) { { fl_rectf(1 /*text_area.x-mLeftMargin - LEFT_MARGIN*/, text_area.y-TOP_MARGIN-2, mLeftMargin, text_area.h+TOP_MARGIN-BOTTOM_MARGIN+4, mUtilityMarginColor); - fl_rectf(text_area.x - LEFT_MARGIN-1, text_area.y-1, - LEFT_MARGIN+1, text_area.h+2, color()); + fl_color(FL_DARK1); + fl_line(0, text_area.y-TOP_MARGIN-2, 0, text_area.h+TOP_MARGIN-BOTTOM_MARGIN+4); + fl_color(FL_BLACK); + fl_line(1, text_area.y-TOP_MARGIN-2, 1, text_area.h+TOP_MARGIN-BOTTOM_MARGIN+4); + //fl_rectf(text_area.x - LEFT_MARGIN-1, text_area.y-1, + //LEFT_MARGIN+1, text_area.h+2, color()); } else fl_rectf(text_area.x-mLeftMargin, text_area.y-TOP_MARGIN, @@ -2948,8 +2950,6 @@ void My_Text_Display::draw(void) { else if (damage() & (FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE)) { // CET - FIXME - save old cursor position instead and just draw side needed? fl_push_clip(0, 0, w(), text_area.h + scrollbar_width()); -// Fl_Region r = XRectangleRegion(0, 0, w(), text_area.h + scrollbar_width()); -// fl_clip_region(r); // Top margin fl_rectf(text_area.x, text_area.y-TOP_MARGIN, @@ -2957,8 +2957,12 @@ void My_Text_Display::draw(void) { if (bHasUtilityMargin) { - fl_rectf(1 /*text_area.x-mLeftMargin - LEFT_MARGIN*/, text_area.y-TOP_MARGIN, + fl_rectf(2 /*text_area.x-mLeftMargin - LEFT_MARGIN*/, text_area.y-TOP_MARGIN, mLeftMargin, text_area.h+TOP_MARGIN-BOTTOM_MARGIN+2, mUtilityMarginColor); + fl_color(FL_DARK1); + fl_line(0, text_area.y-TOP_MARGIN-2, 0, text_area.h+TOP_MARGIN-BOTTOM_MARGIN+4); + fl_color(FL_BLACK); + fl_line(1, text_area.y-TOP_MARGIN-2, 1, text_area.h+TOP_MARGIN-BOTTOM_MARGIN+4); fl_rectf(text_area.x - LEFT_MARGIN-1, text_area.y-1, LEFT_MARGIN+1, text_area.h+2, color()); } @@ -2996,9 +3000,6 @@ void My_Text_Display::draw(void) { // draw some lines of text fl_push_clip(text_area.x, text_area.y, text_area.w, text_area.h); -// Fl_Region r = XRectangleRegion(text_area.x, text_area.y, -// text_area.w, text_area.h); -// fl_clip_region(r); draw_range(damage_range1_start, damage_range1_end); if (damage_range2_end != -1) { draw_range(damage_range2_start, damage_range2_end); @@ -3016,9 +3017,6 @@ void My_Text_Display::draw(void) { text_area.y, text_area.w+LEFT_MARGIN+RIGHT_MARGIN, text_area.h); -// Fl_Region r = XRectangleRegion(0, 0, -// w(), h()); -// fl_clip_region(r); int X, Y; if (position_to_xy(mCursorPos, &X, &Y)) draw_cursor(X, Y); diff --git a/src/ide.cpp b/src/ide.cpp index d3a908e..c698c9d 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -804,7 +804,7 @@ void cb_lcd_display(Fl_Widget* w, void*) if (gpIde->m_EditTabs->children() == 1) { gpIde->m_EditTabs->show(); - m_TabNoBlinkBox->show(); + //m_TabNoBlinkBox->show(); } gpLcd->show(); gpLcd->show(); @@ -3499,6 +3499,7 @@ void VT_Ide::OpenTreeFile(Flu_Tree_Browser::Node* n) // File already open...bring file to foreground m_EditTabs->value(pWidget); pWidget->take_focus(); + m_EditTabs->redraw(); return; } } @@ -3534,8 +3535,8 @@ Fl_Multi_Edit_Window* VT_Ide::NewEditWindow(const MString& title, const MString& /* Calculate location of next window */ x = 0; - y = TAB_HEIGHT; - h = m_EditTabs->h() - TAB_HEIGHT+1; + y = TAB_HEIGHT-1; + h = m_EditTabs->h() - TAB_HEIGHT+3; w = m_EditTabs->w()-2; /* Create the MultiEditWin as a child of the main EditWindow */ @@ -3574,7 +3575,7 @@ Fl_Multi_Edit_Window* VT_Ide::NewEditWindow(const MString& title, const MString& m_TabNoBlinkBox->show(); } m_EditWindow->redraw(); -// m_EditTabs->redraw(); + m_EditTabs->redraw(); // Call show again to bring window to front mw->take_focus(); diff --git a/src/idetabs.cpp b/src/idetabs.cpp index 3460937..95b48c3 100644 --- a/src/idetabs.cpp +++ b/src/idetabs.cpp @@ -1,4 +1,4 @@ -/* multiwin.cpp */ +/* idetabs.cpp */ /* $Id$ */ @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -55,6 +56,13 @@ enum {LEFT, RIGHT, SELECTED}; IMPLEMENT_DYNCREATE(Fl_Ide_Tabs, VTObject) +static void cb_tab_file_sel(Fl_Widget* w, void* sel) +{ + Fl_Ide_Tabs* pTabs = (Fl_Ide_Tabs *) w->parent(); + + pTabs->SelectTab((Fl_Widget *) sel); +} + void cb_idetabs(Fl_Widget* w, void *args) { Fl_Ide_Tabs* pTabs; @@ -68,9 +76,6 @@ void cb_idetabs(Fl_Widget* w, void *args) count = pTabs->children(); if (count == 1) { - // Hide the tab control if no more tabs left -// pTabs->hide(); - // Hide the no-blink box in the parent window also for (x = 0; x < pTabs->parent()->children(); x++) pTabs->parent()->child(x)->hide(); @@ -106,7 +111,10 @@ Fl_Ide_Tabs::Fl_Ide_Tabs(int x, int y, int w, int h, const char* title) { m_prevInRect = FALSE; m_pushInRect = FALSE; - m_hasCloseButton = FALSE; + m_hasCloseButton = 0; + m_hasMoreButton = 0; + m_MorePopup = NULL; + memset((char *) &m_PopupMenuItems, 0, sizeof(m_PopupMenuItems)); box(FL_THIN_UP_BOX); push_ = 0; last_visible_ = 0; @@ -123,49 +131,73 @@ Fl_Ide_Tabs::~Fl_Ide_Tabs() Redraw routine =============================================================== */ -void Fl_Ide_Tabs::draw() { - Fl_Widget *v = value(); - int H = tab_height(); +void Fl_Ide_Tabs::draw() +{ + Fl_Widget *v = value(); + int H = tab_height(); + int tabLeftX; + int rightX = 0; + int i, maxw; + int p[128]; int wp[128]; - if (damage() & FL_DAMAGE_ALL) { // redraw the entire thing: - Fl_Color c = v ? v->color() : color(); - -#if 0 - draw_box(box(), x(), y()+(H>=0?H:0), w(), h()-(H>=0?H:-H), c); - if (selection_color() != c) { - // Draw the top 5 lines of the tab pane in the selection color so - // that the user knows which tab is selected... - if (H >= 0) fl_push_clip(x(), y() + H, w(), 5); - else fl_push_clip(x(), y() + h() - H - 4, w(), 5); + int selected = tab_positions(p,wp); - draw_box(box(), x(), y()+(H>=0?H:0), w(), h()-(H>=0?H:-H), - selection_color()); + if (m_MorePopup == NULL) + { - fl_pop_clip(); - } -#endif - if (v) draw_child(*v); - } else { // redraw the child - if (v) update_child(*v); - } + m_MorePopup = new Fl_Menu_Button(0,0,100,400,"Popup"); + m_MorePopup->type(Fl_Menu_Button::POPUP3); + m_MorePopup->selection_color(fl_rgb_color(80,80,255)); + m_MorePopup->color(fl_rgb_color(240,239,228)); + m_MorePopup->parent(this); + m_MorePopup->hide(); + } + + if (damage() & FL_DAMAGE_ALL) + { + // redraw the entire thing: + Fl_Color c = v ? v->color() : color(); + + if (v) + draw_child(*v); + } + else + { + // redraw the child + if (v) + update_child(*v); + } int H2 = H < 0 ? -H : H; -#if 0 - // Draw the background rectangle - fl_push_clip(x(), y(), w(), h()+2); - draw_box(box(), x(), y(), w(), h()+2, fl_rgb_color(228,226,213)); - fl_pop_clip(); -#endif + // Draw the bottom border line for the "TAB" + tabLeftX = w()-1; + if (m_hasCloseButton) + tabLeftX -= H2+1; + if (m_hasMoreButton) + tabLeftX -= H2+1; + + if (H >= 0) + //draw_box(box(), x()+2, H2-5, tabLeftX, 10, selection_color()); + fl_rectf(x()+2, H2-5, tabLeftX, 10, selection_color()); + else + draw_box(box(), x()+2, h()-H2-4, tabLeftX, 5, selection_color()); + fl_color(fl_rgb_color(127,157,184)); + if (H<0) + fl_line(x()+2, h()-H2, tabLeftX, h()-H2); + else + fl_line(x()+2, H-6, tabLeftX, H-6); + // Draw the close box if (m_hasCloseButton) { if (H >= 0) - m_closeRect = VT_Rect(x() + w() - H2, 0, H2, H2); + m_closeRect = VT_Rect(x() + w() - H2-1, 0, H2, H2); else - m_closeRect = VT_Rect(x() + w() - H2, y() + h() - H2, H2, H2); - draw_box(box(), x() + w() - H2, 0, H2, H2, selection_color()); + m_closeRect = VT_Rect(x() + w() - H2-1, y() + h() - H2, H2, H2); + draw_box(box(), m_closeRect.x(), 0, H2, H2-2, selection_color()); + // Draw the 'X' in the close box fl_color(FL_BLACK); @@ -180,35 +212,101 @@ void Fl_Ide_Tabs::draw() { fl_line(rx1, ry2 - 7, rx2, ry1 + 9); fl_line(rx1, ry2 - 8, rx2, ry1 + 8); fl_line(rx1, ry2 - 9, rx2, ry1 + 7); + fl_color(fl_rgb_color(127,157,184)); + fl_line(m_closeRect.x1(), m_closeRect.y()-2, m_closeRect.x1(), m_closeRect.y1()-2); + if (!m_hasMoreButton) + fl_line(m_closeRect.x(), m_closeRect.y()-2, m_closeRect.x(), m_closeRect.y1()-2); + fl_line(m_closeRect.x(), m_closeRect.y1()-1, m_closeRect.x1(), m_closeRect.y1()-1); } - // Draw the bottom border line for the "TAB" - if (H >= 0) - draw_box(box(), x()+1, H2-5, w(), 7, selection_color()); - else - draw_box(box(), x()+1, h()-H2-4, w(), 5, selection_color()); - fl_color(fl_rgb_color(127,157,184)); - if (H<0) - fl_line(x()+1, h()-H2, w(), h()-H2); - else - fl_line(x()+1, H-6, w()-H-1, H-6); - // Draw the tabs if (damage() & (FL_DAMAGE_SCROLL|FL_DAMAGE_ALL)) { - int p[128]; int wp[128]; - int selected = tab_positions(p,wp); - int i; Fl_Widget*const* a = array(); + Fl_Widget* pSel; + + // Test if the selected tab is beyond the right edge of the + // window. If it is, then we will move it's position in the + // list of children such that it is the right most tab that is + // fully visible. + maxw = w() - (H2+1) * (m_hasCloseButton + m_hasMoreButton); + if (p[selected] + wp[selected] >= maxw) + { + // Okay, the selected tab doesn't fit on the window. Let's + // move it so it does fit. + i = selected-1; + while (i > 0 && p[i] > maxw - wp[selected]) + i--; + + // Now move the selected tab such that is is at index i + pSel = child(selected); + remove(selected); + insert(*pSel, i); + value(pSel); + selected = tab_positions(p,wp); + } + for (i=children()-1; i > selected; i--) - draw_tab(x()+H2+p[i], x()+H2/2+3+p[i+1], wp[i], H, a[i], RIGHT); + { + if (p[i] >= w() - (H2+1) * (m_hasCloseButton + m_hasMoreButton)) + continue; + if (x()+H2+p[i]+wp[i] > rightX) + rightX = x()+H2+p[i]+wp[i]; + draw_tab(x()+H2+p[i], x()+H2/2+3+p[i+1], wp[i], H, a[i], RIGHT); + } for (i=selected - 1; i>=0; i--) - draw_tab(x()+H2+p[i], x()+H2/2+3+p[i+1], wp[i], H, a[i], LEFT); - if (v) { - i = selected; - draw_tab(x()+H2+p[i], x()+H2/2+3+p[i+1], wp[i], H, a[i], SELECTED); + { + if (p[i] >= w() - (H2+1) * (m_hasCloseButton + m_hasMoreButton)) + break; + draw_tab(x()+H2+p[i], x()+H2/2+3+p[i+1], wp[i], H, a[i], LEFT); + } + if (v) + { + i = selected; + if (x()+H2+p[i]+wp[i] > rightX) + rightX = x()+H2+p[i]+wp[i]; + draw_tab(x()+H2+p[i], x()+H2/2+3+p[i+1], wp[i], H, a[i], SELECTED); } } + + fl_rectf(rightX+1, 2, x()+2+maxw-rightX-EXTRASPACE, TAB_HEIGHT-BORDER-5, parent()->color()); + + // Draw the "More tabs" box + if (m_hasMoreButton) + { + if (H >= 0) + m_moveRect = VT_Rect(x() + w() - H2*(1+m_hasCloseButton)-2, 0, H2, H2); + else + m_moveRect = VT_Rect(x() + w() - H2*(1+m_hasCloseButton)-2, y() + h() - + H2*(1+m_hasCloseButton), H2, H2); + + draw_box(box(), m_moveRect.x(), 0, H2, H2, selection_color()); + + // Draw the down arrow in the close box + fl_color(FL_BLACK); + + int rx1 = m_moveRect.x() + H2/2-1; + int ry1 = m_moveRect.y() + 7; + int ry2 = m_moveRect.y1() - 8; + + fl_line(rx1, ry1, rx1, ry2); + fl_line(rx1+1, ry1, rx1+1, ry2+1); + fl_line(rx1+2, ry1, rx1+2, ry2); + fl_line(rx1-1, ry2-1, rx1+3, ry2-1); + fl_line(rx1-2, ry2-2, rx1+4, ry2-2); + fl_line(rx1-3, ry2-3, rx1+5, ry2-3); + + // Draw left border + fl_color(fl_rgb_color(127,157,184)); + fl_line(m_moveRect.x(), m_moveRect.y(), m_moveRect.x(), m_moveRect.y1()); + + // Draw right border + if (m_hasCloseButton) + fl_line(m_moveRect.x1(), m_moveRect.y(), m_moveRect.x1(), m_moveRect.y1()); + } + else + m_moveRect = VT_Rect(-1, -1, 1, 1); + } /* @@ -217,7 +315,8 @@ Calculates the position of all tabs based on the children in the tab group. =============================================================== */ -int Fl_Ide_Tabs::tab_positions(int* p, int* wp) { +int Fl_Ide_Tabs::tab_positions(int* p, int* wp) +{ int selected = 0; Fl_Widget*const* a = array(); int i; @@ -249,8 +348,19 @@ int Fl_Ide_Tabs::tab_positions(int* p, int* wp) { fl_draw_shortcut = prev_draw_shortcut; int r = w() - m_closeRect.w(); - if (p[i] <= r) return selected; - // uh oh, they are too big: + if (p[i] <= r) + { + m_hasMoreButton = FALSE; + return selected; + } + + // uh oh, they are too big + // Set the m_hasMoreButton so we have a way to display tabs that are + // off screen + + m_hasMoreButton = TRUE; + return selected; + // pack them against right edge: p[i] = r; for (i = children(); i--;) @@ -322,7 +432,7 @@ void Fl_Ide_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) int sel = (what == SELECTED); int dh = Fl::box_dh(box()); int dy = Fl::box_dy(box()); - int i; + int i, clipw; char prev_draw_shortcut = fl_draw_shortcut; fl_draw_shortcut = 1; @@ -343,7 +453,10 @@ void Fl_Ide_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) Fl_Color oc = o->labelcolor(); fl_pop_clip(); - fl_push_clip(x1-H-10, y()-2, W+H+5, H+2); + clipw = W+H+5; + if (x1-H-10 + clipw >= w()-(TAB_HEIGHT+1)*(m_hasCloseButton + m_hasMoreButton)-10) + clipw = w()-(TAB_HEIGHT+1)*(m_hasCloseButton + m_hasMoreButton) - (x1-H-10); + fl_push_clip(x1-H-10, y()-2, clipw/*W+H+5*/, H+2); // Draw TAB left curved portion fl_color(c); @@ -453,9 +566,8 @@ Handle events */ int Fl_Ide_Tabs::handle(int e) { - int drawbox = FALSE; - int ret; - Fl_Widget* w; + int ret, i, n; + Fl_Widget* pW; switch (e) { @@ -464,7 +576,6 @@ int Fl_Ide_Tabs::handle(int e) if (m_pushInRect) return 1; - // Test if mouse is in our close rect if (m_closeRect.PointInRect(Fl::event_x(), Fl::event_y())) { @@ -474,53 +585,78 @@ int Fl_Ide_Tabs::handle(int e) window()->make_current(); // Draw the activity box fl_color(FL_BLACK); - drawbox = TRUE; m_prevInRect = TRUE; + fl_rect(m_closeRect.x()+4, m_closeRect.y()+4, m_closeRect.w() - 7, m_closeRect.h() - 7); } else { - if (!m_prevInRect) - return orig_handle(e); - window()->make_current(); - fl_color(selection_color()); - drawbox = TRUE; - m_prevInRect = FALSE; + if (m_prevInRect) + { + window()->make_current(); + fl_color(selection_color()); + m_prevInRect = FALSE; + fl_rect(m_closeRect.x()+4, m_closeRect.y()+4, m_closeRect.w() - 7, m_closeRect.h() - 7); + } } - if (drawbox) + // Test if mouse is in our close rect + if (m_moveRect.PointInRect(Fl::event_x(), Fl::event_y())) { - int rx1 = m_closeRect.x() + x(); - int ry1 = m_closeRect.y() + y(); + if (m_prevInMoveRect) + return 0; + window()->make_current(); - fl_rect(rx1 + 4, ry1 + 4, m_closeRect.w() - 8, m_closeRect.h() - 8); + // Draw the activity box + fl_color(FL_BLACK); + m_prevInMoveRect = TRUE; + fl_rect(m_moveRect.x()+4, m_moveRect.y()+4, m_moveRect.w() - 7, m_moveRect.h() - 7); } + else + { + if (!m_prevInMoveRect) + return orig_handle(e); + window()->make_current(); + fl_color(selection_color()); + m_prevInMoveRect = FALSE; + fl_rect(m_moveRect.x()+4, m_moveRect.y()+4, m_moveRect.w() - 7, m_moveRect.h() - 7); + } + break; case FL_LEAVE: + window()->make_current(); if (m_prevInRect && !m_pushInRect) { fl_color(selection_color()); m_prevInRect = FALSE; int rx1 = m_closeRect.x() + x(); int ry1 = m_closeRect.y() + y(); - fl_rect(rx1 + 4, ry1 + 4, m_closeRect.w() - 8, m_closeRect.h() - 8); + fl_rect(rx1 + 4, ry1 + 4, m_closeRect.w() - 7, m_closeRect.h() - 7); + } + if (m_prevInMoveRect && !m_pushInRect) + { + fl_color(selection_color()); + m_prevInMoveRect = FALSE; + int rx1 = m_moveRect.x() + x(); + int ry1 = m_moveRect.y() + y(); + fl_rect(rx1 + 4, ry1 + 4, m_moveRect.w() - 7, m_moveRect.h() - 7); } break; case FL_PUSH: // If the mouse is in the close rect, indicate a push in rect event - if (m_prevInRect) + if (m_prevInRect || m_prevInMoveRect) { m_pushInRect = TRUE; return 1; } break; - w = value(); + pW = value(); ret = orig_handle(e); - if (w != value()) + if (pW != value()) { - if (w != NULL) - w->hide(); + if (pW != NULL) + pW->hide(); if (value() != NULL) value()->show(); } @@ -529,7 +665,7 @@ int Fl_Ide_Tabs::handle(int e) case FL_RELEASE: // If the mouse was previously pushed in the close box, then test for closure - if (m_pushInRect) + if (m_pushInRect || m_prevInMoveRect) { window()->make_current(); @@ -537,8 +673,44 @@ int Fl_Ide_Tabs::handle(int e) if (m_closeRect.PointInRect(Fl::event_x(), Fl::event_y())) { value()->do_callback(value(), FL_IDE_TABS_CLOSE); + m_pushInRect = FALSE; } - m_pushInRect = FALSE; + else if (m_moveRect.PointInRect(Fl::event_x(), Fl::event_y())) + { + // Deal with More Tabs push button + + m_pushInRect = FALSE; + + Fl_Widget*const* a = array(); + int maxx = w()-(TAB_HEIGHT+1)*(1+m_hasCloseButton)-2; + int p[128], wp[128]; + tab_positions(p, wp); + for (i=0; i < children(); i++, a++) + { + if (p[i]+wp[i] >= maxx) + break; + } + + n = 0; + while (i < children()) + { + // Add this tab to the list + m_PopupMenuItems[n].text = (*a)->label(); + m_PopupMenuItems[n].user_data_ = *a; + m_PopupMenuItems[n].flags = 0; + m_PopupMenuItems[n].callback_ = cb_tab_file_sel; + i++; + a++; + n++; + } + + m_PopupMenuItems[n].text = NULL; + m_MorePopup->menu(m_PopupMenuItems); + m_MorePopup->label("More Files"); + m_MorePopup->type(Fl_Menu_Button::POPUP123); + window()->make_current(); + m_MorePopup->popup(); + } } break; @@ -750,3 +922,14 @@ int Fl_Ide_Tabs::value(Fl_Widget *newvalue) { return ret; } +/* +=============================================================== +Select the specified tab +=============================================================== +*/ +void Fl_Ide_Tabs::SelectTab(Fl_Widget *pTab) +{ + value(pTab); + redraw(); +} + diff --git a/src/idetabs.h b/src/idetabs.h index 44ee4b3..ad05d33 100644 --- a/src/idetabs.h +++ b/src/idetabs.h @@ -32,6 +32,7 @@ #include #include +#include #include "vtobj.h" #define FL_IDE_TABS_CLOSE (0xDEADD00D) @@ -49,16 +50,22 @@ class Fl_Ide_Tabs : public Fl_Group, public VTObject Fl_Widget *push() {return last_visible_;} int push(Fl_Widget *); Fl_Widget *which(int event_x, int event_y); - void has_close_button(int bHasCloseButton) { m_hasCloseButton = bHasCloseButton; } + void has_close_button(int bHasCloseButton) { m_hasCloseButton = bHasCloseButton?1:0; } Fl_Widget *last_visible_; + void SelectTab(Fl_Widget *pTab); protected: VT_Rect m_closeRect; + VT_Rect m_moveRect; int m_prevInRect; + int m_prevInMoveRect; int m_pushInRect; int m_hasCloseButton; + int m_hasMoreButton; Fl_Widget *value_; Fl_Widget *push_; + Fl_Menu_Item m_PopupMenuItems[100]; + Fl_Menu_Button* m_MorePopup; virtual int handle(int e); virtual int orig_handle(int e); diff --git a/wish_list.txt b/wish_list.txt new file mode 100644 index 0000000..80bd93f --- /dev/null +++ b/wish_list.txt @@ -0,0 +1,52 @@ +This is a list of things that I still want to add / improve in VirtualT +in no specfic order. + +- Update Disassembler to allow disassembly from REX FLASH regions. + +- Add debug information generation to Assembler and Linker. + +- Add interface to IDE to set and track breakpoints in assembly source files. + +- Add interface to IDE to do source level single stepping using added debug info. + +- Update IDE Find Dialog to save searches to the drop list. + +- Update IDE FInd Dialog to perform Find In Files feature. + +- Add multi level Undo / Redo to IDE Editor windows. + +- Add interface to IDE to set and display variables in debug mode. + +- Modifiy IDE / Project settings window so it is resizable and uses a list on the + left with control window panes on the right. + +- Add Linker Script command processing. + +- Add IDE Project Profiles to allow setting environment variables for M100, T200, etc. + +- Update TDock VGA so that it pulls in the M100 ROM and doesn't depen on the M100 + ROM being active. + +- Update TDock VGA so it has selectable resolution mode (480x200 and 640x350). + +- Add a Font Editor for TDock VGA. + +- Add "Install TDock Tools" menu item to automatically install the TDock CO files. + +- Update REX memory model to pull in REX 4.9 instead of REX 4.8. + +- Add ability from IDE / Editor to specify Tab spacing. + +- Add ability to create multiple Memory Editor windows. + +- Add ability to support more than one active emulation. + +- Fix issue on Mac where File Browsing sometime doesn't work. + +- Fix issue on Mac where IDE doesn't work properly. + +- Add file modification tracking to IDE to auto-reload files that have been modified + outside the IDE / Editor window. + +- Add IDE icon bar. + From f7c6c87aa5b361667c77918e56ae2092f0afa6e4 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Thu, 5 Mar 2015 23:48:25 +0000 Subject: [PATCH 275/327] Added Linker script command processing and IDE Tab management when too many tabs open. --- release.txt | 6 + src/assemble.cpp | 20 - src/ide.cpp | 9 +- src/idetabs.cpp | 2 +- src/linker.cpp | 1330 +++++++++++++++++++++++++++++++++--------- src/linker.h | 130 ++++- src/memedit.cpp | 1 + src/multieditwin.cpp | 32 +- src/multieditwin.h | 2 + src/pref_form.cpp | 10 +- src/pref_form.h | 3 + wish_list.txt | 4 - 12 files changed, 1222 insertions(+), 327 deletions(-) diff --git a/release.txt b/release.txt index 21306cf..5bf892d 100644 --- a/release.txt +++ b/release.txt @@ -54,6 +54,12 @@ v1.7 Not released yet Tabs are now clipped and a "More Files" icon is displayed to allow selection of off-screen open file windows. +16. Added linker script PRELINK and POSTLINK processing to allow defining symbols + based on #if / #else / #endif C preprocessor style statements. Also added + ability to display link messages using "echo" for displaying things like + program sizes and addresses, etc. + + ==================== v1.6 April 24, 2014 ==================== diff --git a/src/assemble.cpp b/src/assemble.cpp index 5c6ce42..732aaf8 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -5108,26 +5108,6 @@ void VTAssembler::ParseExternalDefines(void) m_Defines.Add(pMacro); } -#if 0 - // Now assign this define - CSymbol* pSymbol = new CSymbol; - if (pSymbol != NULL) - { - pSymbol->m_Name = def; - pSymbol->m_Line = -1; - pSymbol->m_SymType = SYM_DEFINE; - pSymbol->m_pRange = NULL; - pSymbol->m_FileIndex = -1; - pSymbol->m_Value = value; - if (value != -1) - pSymbol->m_SymType |= SYM_HASVALUE; - - // Assign symbol to active segment - const char *pStr = (const char *) pSymbol->m_Name; - (*m_Symbols)[pStr] = pSymbol; - } -#endif - // Update startIndex startIndex = endIndex + 1; if (startIndex >= len) diff --git a/src/ide.cpp b/src/ide.cpp index c698c9d..b795af8 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -75,6 +75,7 @@ Fl_Multi_Window* gpLcd; MString gRootpath; char usrdocdir[256]; int gIdeX, gIdeY, gIdeW, gIdeH; +int tab_size = 4; char gRecentFile[VT_NUM_RECENT_FILES][256]; char gRecentProject[VT_NUM_RECENT_PROJECTS][256]; int gDisableHl, gSmartIndent, gReloadProject; @@ -562,6 +563,7 @@ void VT_Ide::SetColors(int fg, int bg) te->mCursor_color = hl_plain; te->smart_indent = gSmartIndent; te->textsize(text_size); + te->tab_distance(tab_size); if (gDisableHl) te->DisableHl(); else @@ -607,6 +609,8 @@ dialog box. void cb_prefs(Fl_Widget* w, void*) { text_size_choice->value((text_size - 6)/2); + sprintf(stab, "%d", tab_size); + tab_size_choice->value(stab); save_wsoe_check->value(save_window_size); hide_output_check->value(auto_hide); @@ -973,6 +977,7 @@ void VT_Ide::LoadPrefs(void) virtualt_prefs.get("Ide_SaveWindowSize", save_window_size, 1); virtualt_prefs.get("Ide_AutoHide", auto_hide, 0); virtualt_prefs.get("Ide_TextSize", text_size, 12); + virtualt_prefs.get("Ide_TabSize", tab_size, 4); for (c = 0; c < VT_NUM_RECENT_FILES; c++) { sprintf(sRecentFile, "Ide_RecentFile%d", c + 1); @@ -1031,6 +1036,7 @@ void VT_Ide::SavePrefs(void) virtualt_prefs.set("Ide_SaveWindowSize", save_window_size); virtualt_prefs.set("Ide_AutoHide", auto_hide); virtualt_prefs.set("Ide_TextSize", text_size); + virtualt_prefs.set("Ide_TabSize", tab_size); for (int c = 0; c < VT_NUM_RECENT_FILES; c++) { sprintf(sRecentFile, "Ide_RecentFile%d", c + 1); @@ -3545,7 +3551,7 @@ Fl_Multi_Edit_Window* VT_Ide::NewEditWindow(const MString& title, const MString& /* Now Create window */ mw = new Fl_Multi_Edit_Window(x, y, w, h, (const char *) title); - mw->buffer()->tab_distance(4); + mw->buffer()->tab_distance(tab_size); if (file != "") { mw->OpenFile((const char *) file); @@ -3790,6 +3796,7 @@ void VT_Ide::BuildProject(void) linker.SetProjectType(m_ActivePrj->m_ProjectType); linker.SetOutputFile(m_ActivePrj->m_OutputName); linker.SetTargetModel(m_ActivePrj->m_TargetModel); + linker.SetDefines(m_ActivePrj->m_Defines); if (linkerScriptFound) linker.SetLinkerScript(linkerScript); else diff --git a/src/idetabs.cpp b/src/idetabs.cpp index 95b48c3..ed8ca7e 100644 --- a/src/idetabs.cpp +++ b/src/idetabs.cpp @@ -47,7 +47,7 @@ #include "multieditwin.h" #define BORDER 3 -#define EXTRASPACE 16 +#define EXTRASPACE 32 #ifndef TAB_HEIGHT #define TAB_HEIGHT 24 #endif diff --git a/src/linker.cpp b/src/linker.cpp index 28f5980..0098614 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -18,6 +18,7 @@ Written: 11/13/09 Kenneth D. Pettit #include #include #include +#include #include extern "C" @@ -64,6 +65,7 @@ VTLinker::VTLinker() m_EntryAddress = 0; m_StartAddress = 0; m_LinkDone = FALSE; + m_LinkScriptRaw = FALSE; // Clear out the Segment assignement map for (x = 0; x < sizeof(m_SegMap) / sizeof(CObjSegment *); x++) @@ -75,6 +77,89 @@ VTLinker::~VTLinker() ResetContent(); } +/* +============================================================================ +Constructor for the CLinkRgn object. This object is used to keep track of +regions defined in the linker script. +============================================================================ +*/ +CLinkRgn::CLinkRgn(int type, MString& name, int startAddr, int endAddr, int prot, + const char* pAtEndName, int atend) +{ + m_Type = type; + m_Name = name; + if (pAtEndName != NULL) + m_AtEndRgn = pAtEndName; + m_Protected = prot; + m_AtEnd = atend; + m_LocateComplete = FALSE; + m_pFirstAddrRange = new LinkAddrRange; + m_pLastAddrRange = m_pFirstAddrRange; + m_pFirstAddrRange->startAddr = startAddr; + m_pFirstAddrRange->endAddr = endAddr; + m_pFirstAddrRange->pNext = NULL; + m_pFirstAddrRange->pPrev = NULL; + m_pFirstAddrRange->nextLocateAddr = startAddr; + m_pFirstAddrRange->endLocateAddr = endAddr; + m_NextLocateAddr = startAddr; + m_EndLocateAddr = endAddr; +} + +CLinkRgn::~CLinkRgn() +{ + LinkAddrRange *pRange; + LinkAddrRange *pNextRange; + + pRange = m_pFirstAddrRange; + while (pRange != NULL) + { + pNextRange = pRange->pNext; + delete pRange; + pRange = pNextRange; + } +} + +CObjFile::~CObjFile() +{ + int count, c; + + count = m_FileSections.GetSize(); + for (c = 0; c < count; c++) + { + delete (CObjFileSection *) m_FileSections[c]; + } + m_FileSections.RemoveAll(); +} + +CObjFileSection::~CObjFileSection() +{ + int count, c; + + if (m_pStrTab != NULL) + delete m_pStrTab; + + if (m_pObjSegment != NULL) + delete m_pObjSegment; + + count = m_Symbols.GetSize(); + for (c = 0; c < count; c++) + { + delete (Elf32_Sym *) m_Symbols[c]; + } + m_Symbols.RemoveAll(); + + count = m_Reloc.GetSize(); + for (c = 0; c < count; c++) + { + delete (Elf32_Rel *) m_Reloc[c]; + } + m_Symbols.RemoveAll(); + + // Delete program bytes pointer if not NULL + if (m_pProgBytes != NULL) + delete m_pProgBytes; +} + /* ============================================================================ Sets the standard output "printf" function to write error messages to @@ -96,6 +181,26 @@ void VTLinker::SetOutputFile(const MString& outFile) m_OutputName = outFile; } +/* +============================================================================ +Returns the Start address (lowest address) of the generated code. +============================================================================ +*/ +unsigned short VTLinker::GetStartAddress(void) +{ + return m_StartAddress; +} + +/* +============================================================================ +Returns the Entry address (lowest address) of the generated code. +============================================================================ +*/ +unsigned short VTLinker::GetEntryAddress(void) +{ + return m_EntryAddress; +} + /* ============================================================================ This routine free's all memory and initializes all variables for a new @@ -181,6 +286,34 @@ void VTLinker::ResetContent(void) m_FileIndex = -1; m_ObjDirs.RemoveAll(); + // Delete all entries in the Prelink script + for (x = 0; x < m_PrelinkScript.m_Script.GetSize(); x++) + { + CScriptCmd *pCmd = (CScriptCmd *) m_PrelinkScript.m_Script[x]; + delete pCmd; + } + m_PrelinkScript.m_Script.RemoveAll(); + + // Delete all entries in the Postlink script + for (x = 0; x < m_PostlinkScript.m_Script.GetSize(); x++) + { + CScriptCmd *pCmd = (CScriptCmd *) m_PostlinkScript.m_Script[x]; + delete pCmd; + } + m_PostlinkScript.m_Script.RemoveAll(); + + // Delete all entries in the m_Defines map + pos = m_Defines.GetStartPosition(); + CDefine* pDefine; + while (pos != NULL) + { + m_Defines.GetNextAssoc(pos, key, (VTObject *&) pDefine); + delete pDefine; + } + m_Defines.RemoveAll(); + + m_ProgSections.RemoveAll(); + // Reset the AddrLines array for (x = 0; x < 65536; x++) m_AddrLines.a[x].pObjFile = NULL; @@ -193,6 +326,77 @@ void VTLinker::ResetContent(void) m_StartAddress = 0; } +/* +============================================================================ +Parses the comma delimeted object filename list and splits it into an array +of filenames to be linked. +============================================================================ +*/ +void VTLinker::CalcObjDirs(void) +{ + char* pStr; + char* pToken; + MString temp; + + m_ObjDirs.RemoveAll(); + + // Add the root directory to the ObjDirs + m_ObjDirs.Add(m_RootPath+(char *) "/"); + + // Check if there is an include path + if (m_ObjPath.GetLength() == 0) + return; + + // Copy path to a char array so we can tokenize + pStr = new char[m_ObjPath.GetLength() + 1]; + strcpy(pStr, (const char *) m_ObjPath); + + pToken = strtok(pStr, ",;"); + while (pToken != NULL) + { + // Preprocess the directory by searching for $VT_ROOT and $VT_PROJ + temp = PreprocessDirectory(pToken); + + // Now add it to the array + m_ObjDirs.Add(temp); + + // Get next token + pToken = strtok(NULL, ",;"); + } + + delete pStr; +} + +/* +============================================================================ +Parses the provided directory name and substitutes {$VT_ROOT} and {$VT_PROJ} +with actual path's. Returns the resultant string. +============================================================================ +*/ +MString VTLinker::PreprocessDirectory(const char *pDir) +{ + MString temp; + + if (strncmp(pDir, "{$VT_ROOT}", 10) == 0) + { + // Substitute the VirtualT path + temp = path; + temp += pDir[10]; + } + else if (strncmp(pDir, "{$VT_PROJ}", 10) == 0) + { + // Generate a projet relative path + temp = pDir[10]; + temp.Trim(); + temp += (char *) "/"; + temp = m_RootPath + (char *) "/" + temp; + } + else + temp = pDir; + + return temp; +} + /* ============================================================================ This function processes the argument list that was passed in @@ -413,55 +617,74 @@ void VTLinker::ProcScriptField2(const char *pStr, int lineNo, MString &segname) else if (m_Command == LKR_CMD_DEFINE) { } + + // Test if command is PRELINK or POSTLINK + else if ((m_Command == LKR_CMD_PRELINK) || (m_Command == LKR_CMD_POSTLINK)) + { + if (strcmp(pStr, "{") != 0) + { + err.Format("Error in line %d(%s): Expected open brace", lineNo, + (const char *) m_LinkerScript); + m_Errors.Add(err); + m_Command = LKR_CMD_ERROR; + } + else + m_LinkScriptRaw = TRUE; + } } /* ============================================================================ This routine evaluates the string provided and returns it's value. The -string can be decimal, hex, etc. and can contain simple math. +string can be decimal, hex, etc. and can contain simple math or comparisons +such as: -END=Preamble_start + (1 + COUNT*4+a)*2 + Preamble_start + (1 + COUNT*4+a)*2 + modeltype=2 + COUNT > 4 + count+1 > 3 || modeltype * 2 < 4 ============================================================================ */ -typedef struct -{ - char op; - char* val; -} SimpleEqOperator_t; - -#define SIMPLE_EQ_PAREN 0 -#define SIMPLE_EQ_ADD 1 -#define SIMPLE_EQ_SUB 2 -#define SIMPLE_EQ_MULT 3 -#define SIMPLE_EQ_DIV 4 -#define SIMPLE_EQ_VALUE 6 -#define SIMPLE_EQ_NOADD 10 - -int VTLinker::EvaluateScriptAddress(const char *pEq, int lineNo) +int VTLinker::EvaluateStringEquation(const char *pEq, int lineNo, int* asHex) { int len = strlen(pEq); int hex = 0; int stack[10]; - int slevel = 0; - int address, x; + int slevel = 1; + int address, x, i; char op, unwindto; char *token, *pStr; SimpleEqOperator_t eq[20]; SimpleEqOperator_t build[20]; + CLinkRgn *pLinkRgn; + CDefine *pDefine; + MString err; char temp[256]; int eqsize = 0; int buildidx = 0; - int value; + int value, found; strncpy(temp, pEq, sizeof(temp)); pStr = temp; token = pStr; + + while (*pStr == ' ') + pStr++; + if (asHex) + { + if (*pStr == '$') + *asHex = 1; + else + *asHex = 0; + } + for (x = 0; x < len; ) { // Find end of next token while (*pStr != '+' && *pStr != '-' && *pStr != '*' && *pStr != '/' && *pStr != 0 && - *pStr != '(' && *pStr != ')') + *pStr != '(' && *pStr != ')' && *pStr != '=' && *pStr != '>' && *pStr != '<' && + *pStr != '|' && *pStr != '&' && *pStr != '!' && *pStr != ' ') { pStr++; x++; @@ -471,13 +694,26 @@ int VTLinker::EvaluateScriptAddress(const char *pEq, int lineNo) if (strlen(token) > 0) { - // Push the value to the equation - eq[eqsize].op = SIMPLE_EQ_VALUE; - eq[eqsize++].val = token; + if (strcmp(token, "sizeof") == 0 && op == '(') + { + // Push SIMPLE_EQ_SIZEOF to build stack + build[buildidx++].op = SIMPLE_EQ_SIZEOF; + } + else + { + // Push the value to the equation + eq[eqsize].op = SIMPLE_EQ_VALUE; + eq[eqsize++].val = token; + } } switch (op) { + case ' ': + op = SIMPLE_EQ_NOADD; + unwindto = SIMPLE_EQ_NOADD; + break; + case '+': op= SIMPLE_EQ_ADD; unwindto = SIMPLE_EQ_ADD; @@ -498,6 +734,7 @@ int VTLinker::EvaluateScriptAddress(const char *pEq, int lineNo) break; case '(': + op = SIMPLE_EQ_PAREN; build[buildidx++].op = SIMPLE_EQ_PAREN; unwindto = 99; break; @@ -506,6 +743,82 @@ int VTLinker::EvaluateScriptAddress(const char *pEq, int lineNo) op = SIMPLE_EQ_NOADD; unwindto = SIMPLE_EQ_PAREN; break; + + case '|': + if (*(pStr+1) != '|') + { + err.Format("Error in line %d(%s): Bitwise OR not supported", lineNo, + (const char *) m_LinkerScript); + m_Errors.Add(err); + return 0; + } + pStr++; + op = SIMPLE_EQ_LOGOR; + unwindto = SIMPLE_EQ_LOGOR; + break; + + case '&': + if (*(pStr+1) != '&') + { + err.Format("Error in line %d(%s): Bitwise AND not supported", lineNo, + (const char *) m_LinkerScript); + m_Errors.Add(err); + return 0; + } + pStr++; + op = SIMPLE_EQ_LOGAND; + unwindto = SIMPLE_EQ_LOGOR; + break; + + case '=': + if (*(pStr+1) == '=') + { + // Skip the 2nd = so "==" and "=" are the same + pStr++; + } + op = SIMPLE_EQ_EQUAL; + unwindto = SIMPLE_EQ_EQUAL; + break; + + case '<': + if (*(pStr+1) == '=') + { + // Skip the '<' + pStr++; + op = SIMPLE_EQ_LTE; + } + else + op = SIMPLE_EQ_LT; + break; + unwindto = SIMPLE_EQ_LT; + + case '>': + if (*(pStr+1) == '=') + { + // Skip the '>' + pStr++; + op = SIMPLE_EQ_GTE; + } + else + op = SIMPLE_EQ_GT; + break; + unwindto = SIMPLE_EQ_LT; + + case '!': + if (*(pStr+1) == '=') + { + // Skip the '=' + pStr++; + op = SIMPLE_EQ_NOTEQUAL; + unwindto = SIMPLE_EQ_EQUAL; + } + else + { + op = SIMPLE_EQ_LOGNOT; + unwindto = SIMPLE_EQ_NOADD; + } + break; + default: op = SIMPLE_EQ_NOADD; break; @@ -515,12 +828,35 @@ int VTLinker::EvaluateScriptAddress(const char *pEq, int lineNo) while (buildidx > 0 && build[buildidx-1].op >= unwindto) { if (build[buildidx-1].op != SIMPLE_EQ_PAREN) + { + // Test for special processing of "sizeof(SECTION)" syntax + if (build[buildidx-1].op == SIMPLE_EQ_SIZEOF) + { + // Pop the sizeof from the build stack + buildidx--; + if (eqsize == 0 || eq[eqsize-1].op != SIMPLE_EQ_VALUE) + { + // Error condition ... nothing else on the stack. Must + // be something like sizeof() + // Error condition in equation! Something like "/3" was specified + err.Format("Error in line %d(%s): Malformed sizeof", lineNo, + (const char *) m_LinkerScript); + m_Errors.Add(err); + return 0; + } + + eq[eqsize-1].op = SIMPLE_EQ_SIZEOF; + continue; + } eq[eqsize++].op = build[buildidx-1].op; + } buildidx--; } if (op != SIMPLE_EQ_NOADD) + { build[buildidx++].op = op; + } x++; token = ++pStr; @@ -534,8 +870,9 @@ int VTLinker::EvaluateScriptAddress(const char *pEq, int lineNo) // Evaluate equation for (x = 0; x < eqsize; x++) { - if (eq[x].op == SIMPLE_EQ_VALUE) + switch (eq[x].op) { + case SIMPLE_EQ_VALUE: token = eq[x].val; // Lookup symbol in active module @@ -550,6 +887,13 @@ int VTLinker::EvaluateScriptAddress(const char *pEq, int lineNo) // Get the symbol value value = (unsigned short) pSymFile->m_pSym->st_value; + if (pSymSect->m_Type != ASEG && ELF32_ST_TYPE(pSymFile->m_pSym->st_info) + != STT_EQUATE) + { + value +=(unsigned short) pSymSect->m_LocateAddr; + } + + // Symbol is only valid if it is ASEG or has been located if (pSymSect->m_Type == ASEG || m_LinkDone) { stack[slevel++] = value; @@ -560,9 +904,16 @@ int VTLinker::EvaluateScriptAddress(const char *pEq, int lineNo) else stack[slevel++] = 0; } + else if (m_Defines.Lookup(token, (VTObject *&) pDefine)) + { + // It is a define, evaluate it + value = EvaluateStringEquation((const char *) pDefine->m_Value, lineNo); + stack[slevel++] = value; + } else { // Test for Hex conversion + int tokenlen = strlen(token); if (*token == '$') { hex = 1; // Indicate HEX conversion @@ -573,9 +924,27 @@ int VTLinker::EvaluateScriptAddress(const char *pEq, int lineNo) hex = 1; token += 2; // Skip the "0x" hex delimiter } - else if ((token[len-1] == 'h') || (token[len-1] == 'H')) + else if ((token[tokenlen-1] == 'h') || (token[tokenlen-1] == 'H')) { hex = 1; + token[--tokenlen] = '\0'; + } + + // Validate it is a value + tokenlen = strlen(token); + for (i = 0; i < tokenlen; i++) + { + if (token[i] < '0' || token[i] > '9') + { + if (!hex || !isxdigit(token[i])) + { + MString err; + err.Format("Error in line %d(%s): Unknown symbol %s", lineNo, + (const char *) m_LinkerScript, token); + m_Errors.Add(err); + return 0; + } + } } // Perform the conversion @@ -586,30 +955,138 @@ int VTLinker::EvaluateScriptAddress(const char *pEq, int lineNo) stack[slevel++] = address; } - } - else if (eq[x].op == SIMPLE_EQ_ADD) - { + break; + + case SIMPLE_EQ_ADD: // Add the 2 top stack items and save in stack value = stack[--slevel]; stack[slevel-1] += value; - } - else if (eq[x].op == SIMPLE_EQ_SUB) - { + break; + + case SIMPLE_EQ_SUB: // Subtract top stack item from next one down value = stack[--slevel]; stack[slevel-1] -= value; - } - else if (eq[x].op == SIMPLE_EQ_MULT) - { + break; + + case SIMPLE_EQ_MULT: // Subtract top stack item from next one down value = stack[--slevel]; stack[slevel-1] *= value; - } - else if (eq[x].op == SIMPLE_EQ_DIV) - { + break; + + case SIMPLE_EQ_DIV: // Subtract top stack item from next one down value = stack[--slevel]; stack[slevel-1] /= value; + break; + + case SIMPLE_EQ_LOGNOT: + stack[slevel] = !stack[slevel]; + break; + + case SIMPLE_EQ_EQUAL: + value = stack[--slevel]; + stack[slevel-1] = value == stack[slevel-1]; + break; + + case SIMPLE_EQ_NOTEQUAL: + value = stack[--slevel]; + stack[slevel-1] = value != stack[slevel-1]; + break; + + case SIMPLE_EQ_LT: + value = stack[--slevel]; + stack[slevel-1] = value < stack[slevel-1]; + break; + + case SIMPLE_EQ_LTE: + value = stack[--slevel]; + stack[slevel-1] = value <= stack[slevel-1]; + break; + + case SIMPLE_EQ_GT: + value = stack[--slevel]; + stack[slevel-1] = value > stack[slevel-1]; + break; + + case SIMPLE_EQ_GTE: + value = stack[--slevel]; + stack[slevel-1] = value >= stack[slevel-1]; + break; + + case SIMPLE_EQ_LOGOR: + value = stack[--slevel]; + stack[slevel-1] = value || stack[slevel-1]; + break; + + case SIMPLE_EQ_LOGAND: + value = stack[--slevel]; + stack[slevel-1] = value && stack[slevel-1]; + break; + + case SIMPLE_EQ_SIZEOF: + token = eq[x].val; + value = 0; + found = FALSE; + + // Search for token in the Progbits section array + for (i = 0; i < m_ProgSections.GetSize(); i++) + { + // Test if this section name matches. + if (((CObjFileSection *) m_ProgSections[i])->m_Name == token) + { + // Add all sizes of sections that match + value += ((CObjFileSection *) m_ProgSections[i])->m_Size; + found = TRUE; + } + } + if (found) + { + // Add the value to the stack + stack[slevel++] = value; + break; + } + + // Maybe it's a Linker Region? + else if (m_LinkRegions.Lookup(token, (VTObject *&) pLinkRgn)) + { + // Search for Progbits sections located in this region + for (i = 0; i < m_ProgSections.GetSize(); i++) + { + // Test if this section name matches. + if (((CObjFileSection *) m_ProgSections[i])->m_pLinkRgn == pLinkRgn) + { + // Add all sizes of sections that match + value += ((CObjFileSection *) m_ProgSections[i])->m_Size; + } + } + + // Add the size to the stack + stack[slevel++] = value; + break; + } + else + { + MString err; + // Error condition in equation! Something like "/3" was specified + err.Format("Error in line %d(%s): Unknown symbol '%s'", lineNo, + (const char *) m_LinkerScript, token); + m_Errors.Add(err); + return 0; + } + + break; + } + + if (slevel <= 1) + { + MString err; + // Error condition in equation! Something like "/3" was specified + err.Format("Error in line %d(%s): Malformed equation", lineNo, + (const char *) m_LinkerScript); + m_Errors.Add(err); + return 0; } } @@ -660,7 +1137,7 @@ void VTLinker::ProcScriptField3(char *pStr, int lineNo, int& startAddr, } else { - startAddr = EvaluateScriptAddress(pStr + 6, lineNo); + startAddr = EvaluateStringEquation(pStr + 6, lineNo); if (startAddr > 65535) { err.Format("Error in line %d(%s): START address too large", lineNo, @@ -725,7 +1202,7 @@ void VTLinker::ProcScriptField4(const char *pStr, int lineNo, int& endAddr) { if (strncmp(pStr, "END=", 4) == 0) { - endAddr = EvaluateScriptAddress(pStr + 4, lineNo); + endAddr = EvaluateStringEquation(pStr + 4, lineNo); if (endAddr > 65535) { err.Format("Error in line %d(%s): END address too large", lineNo, @@ -1063,6 +1540,344 @@ void VTLinker::NewLinkRegion(int type, int lineNo, int startAddr, m_Command = LKR_CMD_COMPLETE; } +/* +============================================================================ +Process a Linker Sub Script +============================================================================ +*/ +void VTLinker::ProcessScript(CLinkScript *pScript, int singleStep) +{ + MString msg; + int x, count, value, index; + CScriptCmd *pCmd; + CDefine *pDefine; + MString name, val; + + count = pScript->m_Script.GetSize(); + for (x = singleStep ? pScript->m_executeIdx++ : 0; x < count; x++) + { + pCmd = (CScriptCmd *) pScript->m_Script[x]; + + switch (pCmd->m_ID) + { + case SCR_CMD_IF: + if (pScript->m_execute == FALSE) + { + // Even if we can't execute, we still have to keep + // track of the nested if condition so we know which + // else and endif belongs to us + pScript->m_ifStack[pScript->m_ifdepth].m_CanExecute = FALSE; + pScript->m_ifStack[pScript->m_ifdepth++].m_StartLine = pCmd->m_Line; + continue; + } + + // Evaluate the if condition + value = EvaluateStringEquation((const char *) pCmd->m_CmdArg, + pCmd->m_Line); + if (m_Errors.GetSize() > 0) + return; + + pScript->m_ifStack[pScript->m_ifdepth].m_StartLine = pCmd->m_Line; + pScript->m_ifStack[pScript->m_ifdepth].m_CanExecute = pScript->m_execute; + pScript->m_ifStack[pScript->m_ifdepth].m_Executed = value; + pScript->m_execute = value; + pScript->m_ifdepth++; + break; + + case SCR_CMD_IFDEF: + case SCR_CMD_IFNDEF: + if (pScript->m_execute == FALSE) + { + // Even if we can't execute, we still have to keep + // track of the nested if condition so we know which + // else and endif belongs to us + pScript->m_ifStack[pScript->m_ifdepth].m_CanExecute = FALSE; + pScript->m_ifStack[pScript->m_ifdepth++].m_StartLine = pCmd->m_Line; + continue; + } + + // Lookup symbol in active module + CObjSymFile* pSymFile; + value = m_Symbols.Lookup((const char *) pCmd->m_CmdArg, (VTObject *&) pSymFile); + + pScript->m_ifStack[pScript->m_ifdepth].m_StartLine = pCmd->m_Line; + pScript->m_ifStack[pScript->m_ifdepth].m_CanExecute = pScript->m_execute; + if (pCmd->m_ID == SCR_CMD_IFDEF) + { + pScript->m_ifStack[pScript->m_ifdepth].m_Executed = value; + pScript->m_execute = value; + } + else + { + pScript->m_ifStack[pScript->m_ifdepth].m_Executed = !value; + pScript->m_execute = !value; + } + pScript->m_ifdepth++; + break; + + case SCR_CMD_ENDIF: + if (!pScript->m_ifdepth) + { + msg.Format("Error in line %d(%s): #endif with no matching #if statement", pCmd->m_Line, + (const char *) m_LinkerScript); + m_Errors.Add(msg); + return; + } + + // Pop the ifStack and restore the execute flag + pScript->m_execute = pScript->m_ifStack[--pScript->m_ifdepth].m_CanExecute; + break; + + case SCR_CMD_ELSE: + if (!pScript->m_ifdepth) + { + msg.Format("Error in line %d(%s): #else with no matching #if statement", pCmd->m_Line, + (const char *) m_LinkerScript); + m_Errors.Add(msg); + return; + } + + // Check if we can execute at this level + if (pScript->m_ifStack[pScript->m_ifdepth-1].m_CanExecute) + { + // If we haven't executed this if, then execute the else + pScript->m_execute = !pScript->m_ifStack[pScript->m_ifdepth-1].m_Executed; + pScript->m_ifStack[pScript->m_ifdepth-1].m_Executed = 1; + } + break; + + case SCR_CMD_ELSIF: + if (!pScript->m_ifdepth) + { + msg.Format("Error in line %d(%s): #elsif with no matching #if statement", pCmd->m_Line, + (const char *) m_LinkerScript); + m_Errors.Add(msg); + return; + } + + // Check if we can execute at this level + if (pScript->m_ifStack[pScript->m_ifdepth-1].m_CanExecute && !pScript->m_ifStack[pScript->m_ifdepth-1].m_Executed) + { + // We haven't executed yet. Evaluate and test if we should execute + // Evaluate the if condition + value = EvaluateStringEquation((const char *) pCmd->m_CmdArg, + pCmd->m_Line); + if (m_Errors.GetSize() > 0) + return; + + pScript->m_ifStack[pScript->m_ifdepth-1].m_StartLine = pCmd->m_Line; + pScript->m_ifStack[pScript->m_ifdepth-1].m_CanExecute = pScript->m_execute; + if (value) + { + pScript->m_ifStack[pScript->m_ifdepth-1].m_Executed = TRUE; + } + else + { + pScript->m_execute = FALSE; + } + break; + } + break; + + case SCR_CMD_DEFINE: + // Test if we are in a non-execute mode (#if) + if (pScript->m_execute == FALSE) + continue; + + // Split the CmdArg into name and value + pCmd->m_CmdArg.Replace('\t', ' '); + index = pCmd->m_CmdArg.Find(' '); + name = pCmd->m_CmdArg.Left(index); + val = pCmd->m_CmdArg.Right(pCmd->m_CmdArg.GetLength()-index-1); + val.TrimLeft(); + val.Trim(); + + // Add a symbol to the m_Defines map. + if (m_Defines.Lookup((const char *) name, (VTObject *&) pDefine)) + { + msg.Format("Error in line %d(%s): symbol %s already defined", pCmd->m_Line, + (const char *) m_LinkerScript, (const char *) name); + m_Errors.Add(msg); + return; + break; + } + if (pDefine != NULL) + { + pDefine = new CDefine; + pDefine->m_Name = name; + pDefine->m_Value = val; + m_Defines[name] = pDefine; + } + + break; + + case SCR_CMD_ECHO: + // Test if we are in a non-execute mode (#if) + if (pScript->m_execute == FALSE) + continue; + + // Echo data to the build window + if (pCmd->m_CmdArg[0] == '"') + { + // Data is a simple string + msg = pCmd->m_CmdArg.Right(pCmd->m_CmdArg.GetLength()-1); + msg = msg.Left(msg.GetLength()-1); + msg.Replace((char *) "\\n", (char *) "\n"); + m_pStdoutFunc(m_pStdoutContext, (const char *) msg); + } + else + { + // Data is an equation + int asHex; + value = EvaluateStringEquation((const char *) pCmd->m_CmdArg, + pCmd->m_Line, &asHex); + if (asHex) + msg.Format("%X", value); + else + msg.Format("%d", value); + m_pStdoutFunc(m_pStdoutContext, (const char *) msg); + } + break; + + } + + // Test for single step and return if set + if (singleStep) + return; + } +} + +/* +============================================================================ +This routine parses lines from the Linker Script that occur between the +open brace and close brace of PRELINK and POSTLINK commands in the script. +============================================================================ +*/ +void VTLinker::ParseSubScript(char *pStr, int lineNo, CLinkScript* pScript) +{ + char* token; + char* arg; + MString cmd, sArg, err; + CScriptCmd *pCmd; + + // Test for close brace + if (pStr[0] == '}') + { + // Turn off RAW linker script processing + m_LinkScriptRaw = FALSE; + + // Indicate sub-script parsing complete + m_Command = LKR_CMD_COMPLETE; + return; + } + + while (*pStr == ' ' || *pStr == '\t') + pStr++; + if (*pStr == ';') + return; + + // Parse command from the rest of the line + token = strtok(pStr, " \t\n"); + arg = strtok(NULL,"\n;"); + + if (token == NULL) + return; + + cmd = token; + cmd.MakeLower(); + if (arg == NULL) + { + if (cmd != "#else" && cmd != "#endif") + { + err.Format("Error in line %d(%s): Expecting argument to %s", lineNo, + (const char *) m_LinkerScript, token); + m_Errors.Add(err); + return; + } + } + else + while (*arg == ' ' || *arg == '\t') + arg++; + sArg = arg; + sArg.Trim(); + + // Test for #ifdef or #ifndef + pCmd = new CScriptCmd; + if (cmd == "#ifdef" || cmd == "#ifndef") + { + if (cmd == "#ifdef") + pCmd->m_ID = SCR_CMD_IFDEF; + else + pCmd->m_ID = SCR_CMD_IFNDEF; + } + + // Test for "#if" + else if (cmd == "#if") + { + pCmd->m_ID = SCR_CMD_IF; + } + + // Test for "#else" + else if (cmd == "#else") + { + pCmd->m_ID = SCR_CMD_ELSE; + } + + // Test for "#elsif" + else if (cmd == "#elseif" || cmd == "#elsif") + { + pCmd->m_ID = SCR_CMD_ELSIF; + } + + // Test for "#endif" + else if (cmd == "#endif") + { + pCmd->m_ID = SCR_CMD_ENDIF; + } + + // Test for #define + else if (cmd == "#define") + { + // Validate there is an identifier and an argument + while (*arg != ' ' && *arg != '\t' && *arg != '\0') + arg++; + token = arg; + while (*token == ' ' || *token == '\t') + token++; + if ((*arg != ' ' && *arg != '\t') || *token == '\0') + { + // Error, only 1 argument given + err.Format("Error in line %d(%s): Expecting argument to %s", lineNo, + (const char *) m_LinkerScript, (const char *) sArg); + m_Errors.Add(err); + delete pCmd; + return; + } + pCmd->m_ID = SCR_CMD_DEFINE; + } + + // Test for echo + else if (cmd == "echo" || cmd == ".echo") + { + pCmd->m_ID = SCR_CMD_ECHO; + } + + // Unknown linker script command! + else + { + err.Format("Error in line %d(%s): Unkown linker script command %s", lineNo, + (const char *) m_LinkerScript, token); + m_Errors.Add(err); + delete pCmd; + return; + } + + // Add the command to the script + pCmd->m_CmdArg = sArg; + pCmd->m_Line= lineNo; + pScript->m_Script.Add(pCmd); +} + /* ============================================================================ This routine attempts to open and parse the linker script to be used during @@ -1080,6 +1895,7 @@ int VTLinker::ReadLinkerScript() char *pRead, *pTok; int field, startAddr, endAddr, prot, atend; char *pSectName; + CLinkScript readScript; // Test if linker script was supplied if (m_LinkerScript.GetLength() == 0) @@ -1130,81 +1946,110 @@ int VTLinker::ReadLinkerScript() if (lineBuf[0] == ';') continue; - // Separate the line into tokens - pTok = strtok(lineBuf, " ,\t\n\r"); - if ((m_Command == LKR_CMD_ERROR) || (m_Command == LKR_CMD_COMPLETE)) - { - field = 0; - m_Command = LKR_CMD_NONE; - startAddr = endAddr = prot = 0; - } + if (lineBuf[0] == '#') + { + // Process #if / #else / #endif directives at the root level + ParseSubScript(lineBuf, lineNo, &readScript); + ProcessScript(&readScript, TRUE); + continue; + } - // Loop for all fields on the line - while (pTok != NULL) + if (readScript.m_execute == FALSE) + continue; + + // If we are not in RAW mode, then tokenized. RAW mode is used + // by the PRELINK and POSTLINK commands. + if (!m_LinkScriptRaw) { - // Test for comment in the line - if (*pTok == ';') + // Separate the line into tokens + pTok = strtok(lineBuf, " ,\t\n\r"); + if ((m_Command == LKR_CMD_ERROR) || (m_Command == LKR_CMD_COMPLETE)) { - // Comment only allowd on line if all args processed - if ((m_Command != LKR_CMD_NONE) && (m_Command != LKR_CMD_COMPLETE) && - !(m_Command & LKR_CMD_CD_DONE)) - { - err.Format("Error in line %d(%s): Incomplete linker script command", lineNo, - (const char *) m_LinkerScript); - m_Errors.Add(err); - } - break; + field = 0; + m_Command = LKR_CMD_NONE; + startAddr = endAddr = prot = 0; } - // Parse based on field number - switch (field) + // Loop for all fields on the line + while (pTok != NULL) { - case 0: - m_Command = MapScriptCommand(pTok, lineNo); - break; + // Test for comment in the line + if (*pTok == ';') + { + // Comment only allowd on line if all args processed + if ((m_Command != LKR_CMD_NONE) && (m_Command != LKR_CMD_COMPLETE) && + !(m_Command & LKR_CMD_CD_DONE)) + { + err.Format("Error in line %d(%s): Incomplete linker script command", lineNo, + (const char *) m_LinkerScript); + m_Errors.Add(err); + } + break; + } - case 1: - ProcScriptField2(pTok, lineNo, segname); - m_SegName = segname; - break; + // Parse based on field number + switch (field) + { + case 0: + m_Command = MapScriptCommand(pTok, lineNo); + break; - case 2: - ProcScriptField3(pTok, lineNo, startAddr, pSectName); - break; + case 1: + ProcScriptField2(pTok, lineNo, segname); + m_SegName = segname; + break; - case 3: - ProcScriptField4(pTok, lineNo, endAddr); - break; + case 2: + ProcScriptField3(pTok, lineNo, startAddr, pSectName); + break; - case 4: - ProcScriptField5(pTok, lineNo, prot, atend); - break; + case 3: + ProcScriptField4(pTok, lineNo, endAddr); + break; - default: - // Keep processing arguments to the ORDER command - if (m_Command == LKR_CMD_ORDER) - AddOrderedSegment(pTok, lineNo); - else if (m_Command == LKR_CMD_CONTAINS) - AddContainsSegment(pTok, lineNo); - else if (m_Command == LKR_CMD_ENDSWITH) - AddEndsWithSegment(pTok, lineNo); - break; + case 4: + ProcScriptField5(pTok, lineNo, prot, atend); + break; + + default: + // Keep processing arguments to the ORDER command + if (m_Command == LKR_CMD_ORDER) + AddOrderedSegment(pTok, lineNo); + else if (m_Command == LKR_CMD_CONTAINS) + AddContainsSegment(pTok, lineNo); + else if (m_Command == LKR_CMD_ENDSWITH) + AddEndsWithSegment(pTok, lineNo); + break; + } + + // Increment the field number + field++; + if ((m_Command == LKR_CMD_NONE) || (m_Command == LKR_CMD_ERROR)) + break; + pTok = strtok(NULL, " ,\t\n\r"); } - // Increment the field number - field++; - if ((m_Command == LKR_CMD_NONE) || (m_Command == LKR_CMD_ERROR)) - break; - pTok = strtok(NULL, " ,\t\n\r"); + // If this was a DATA or CODE command that completed, process the + // information + if (m_Command & LKR_CMD_CD_DONE) + { + // Clear the CMD_CD_DONE bit + m_Command &= ~LKR_CMD_CD_DONE; + NewLinkRegion(m_Command, lineNo, startAddr, endAddr, prot, pSectName, atend); + } } - - // If this was a DATA or CODE command that completed, process the - // information - if (m_Command & LKR_CMD_CD_DONE) + else { - // Clear the CMD_CD_DONE bit - m_Command &= ~LKR_CMD_CD_DONE; - NewLinkRegion(m_Command, lineNo, startAddr, endAddr, prot, pSectName, atend); + // Must be a PRELINK or POSTLINK command. Send RAW strings + // to the ParseScript routine. + if (m_Command == LKR_CMD_PRELINK) + { + ParseSubScript(lineBuf, lineNo, &m_PrelinkScript); + if (m_Command == LKR_CMD_COMPLETE) + ProcessScript(&m_PrelinkScript); + } + else + ParseSubScript(lineBuf, lineNo, &m_PostlinkScript); } } @@ -1659,6 +2504,9 @@ int VTLinker::AssignSectionNames() // Finally, assign the name to the segment if (*pName != '\0') pFileSection->m_Name = pName; + + if (pFileSection->m_ElfHeader.sh_type == SHT_PROGBITS) + m_ProgSections.Add(pFileSection); } } @@ -1947,6 +2795,7 @@ int VTLinker::LocateSegmentIntoRegion(MString& region, CObjFileSection* pFileSec // Mark the segment as located pFileSection->m_LocateAddr = locateAddr; pFileSection->m_Located = true; + pFileSection->m_pLinkRgn = pLinkRgn; if (pFileSection->m_Type == DSEG) m_TotalDataSpace += segSize; @@ -3295,6 +4144,7 @@ int VTLinker::GenerateMapFile(void) MString err, filename; FILE* fd; int c, count, addr; + int x; int codeSize = 0, dataSize = 0; VTObArray m_Sorted; @@ -3403,6 +4253,20 @@ int VTLinker::GenerateMapFile(void) m_Symbols.GetNextAssoc(pos, key, (VTObject *&) pObjSymFile); CObjSymFile* pComp; + int sectionname = FALSE; + for (x = 0; x < m_ProgSections.GetSize(); x++) + { + if (((CObjFileSection *) m_ProgSections[x])->m_Name == pObjSymFile->m_pName) + { + sectionname = TRUE; + break; + } + } + if (sectionname) + continue; + + // Test if this symbol is a section name + count = m_Sorted.GetSize(); for (c = 0; c < count; c++) { @@ -3450,6 +4314,18 @@ int VTLinker::GenerateMapFile(void) pObjSymFile->m_pSym->st_shndx]; CObjSymFile* pComp; + int sectionname = FALSE; + for (x = 0; x < m_ProgSections.GetSize(); x++) + { + if (((CObjFileSection *) m_ProgSections[x])->m_Name == pObjSymFile->m_pName) + { + sectionname = TRUE; + break; + } + } + if (sectionname) + continue; + count = m_Sorted.GetSize(); for (c = 0; c < count; c++) { @@ -3743,6 +4619,77 @@ int VTLinker::BackAnnotateListingFiles(void) return TRUE; } +/* +============================================================================ +This function is called to parse an input file. If there are no errors +during parsing, the routine calls the routines to assemlbe and generate +output files for .obj, .lst, .hex, etc. +============================================================================ +*/ +void VTLinker::ParseExternalDefines(void) +{ + int startIndex, endIndex; + MString def, sval; + int valIdx, len; + int value = -1; + + // If zero length then we're done + if ((len = m_ExtDefines.GetLength()) == 0) + return; + + // Convert any commas to semicolons to make searches easy + m_ExtDefines.Replace(',', ';'); + + // Loop for all items in the string and assign labels + startIndex = 0; + while (startIndex >= 0) + { + // Find end of next define + endIndex = m_ExtDefines.Find(';', startIndex); + if (endIndex < 0) + endIndex = len; + + // Extract the define from the string + def = m_ExtDefines.Mid(startIndex, endIndex - startIndex); + + sval = ""; + + // Test if the define has an embedded '=' + if ((valIdx = def.Find('=')) != -1) + { + MString name = def.Left(valIdx); + sval = def.Mid(valIdx+1, endIndex - (valIdx+1)); + + // The value was valid. Replace the def name + def = name; + } + + // Add this define / string value pair + CDefine *pDefine = new CDefine; + if (pDefine != NULL) + { + pDefine->m_Name = def; + pDefine->m_Value = sval; + m_Defines[def] = pDefine; + } + + // Update startIndex + startIndex = endIndex + 1; + if (startIndex >= len) + startIndex = -1; + while (startIndex > 0) + { + if (m_ExtDefines[startIndex] == ' ') + { + if (++startIndex >= len) + startIndex = -1; + } + else + break; + } + } +} + /* ============================================================================ Process any POSTLINK commands from the Linker Script. @@ -3750,13 +4697,17 @@ Process any POSTLINK commands from the Linker Script. */ void VTLinker::ProcessPostlink(void) { + // Validate link done and no errors if (!m_LinkDone || m_Errors.GetSize() > 0) return; + + // Process the postlink script from the linker script file + ProcessScript(&m_PostlinkScript); } /* ============================================================================ -The parser calls this function to perform the link operation after all +The IDE calls this function to perform the link operation after all files have been assembled. ============================================================================ */ @@ -3771,6 +4722,9 @@ int VTLinker::Link() // Process the input filename list from the IDE ProcessArgs(m_ObjFileList, ",;"); + // Add any external defines from the IDE + ParseExternalDefines(); + // Load all files to be linked ReadObjFiles(); @@ -3816,7 +4770,7 @@ void VTLinker::SetLinkOptions(const MString& options) // Set the options string in case we need it later m_LinkOptions = options; - // Parse the options later during assembly + // Parse the options later during linking } /* @@ -3829,7 +4783,7 @@ void VTLinker::SetLinkerScript(const MString& script) // Set the linker script filename for processing later m_LinkerScript = script; - // Parse the options later during assembly + // Parse the options later during linking } /* @@ -3895,174 +4849,12 @@ void VTLinker::SetProjectType(int type) /* ============================================================================ -Parses the comma delimeted object filename list and splits it into an array -of filenames to be linked. -============================================================================ -*/ -void VTLinker::CalcObjDirs(void) -{ - char* pStr; - char* pToken; - MString temp; - - m_ObjDirs.RemoveAll(); - - // Add the root directory to the ObjDirs - m_ObjDirs.Add(m_RootPath+(char *) "/"); - - // Check if there is an include path - if (m_ObjPath.GetLength() == 0) - return; - - // Copy path to a char array so we can tokenize - pStr = new char[m_ObjPath.GetLength() + 1]; - strcpy(pStr, (const char *) m_ObjPath); - - pToken = strtok(pStr, ",;"); - while (pToken != NULL) - { - // Preprocess the directory by searching for $VT_ROOT and $VT_PROJ - temp = PreprocessDirectory(pToken); - - // Now add it to the array - m_ObjDirs.Add(temp); - - // Get next token - pToken = strtok(NULL, ",;"); - } - - delete pStr; -} - -/* -============================================================================ -Parses the provided directory name and substitutes {$VT_ROOT} and {$VT_PROJ} -with actual path's. Returns the resultant string. -============================================================================ -*/ -MString VTLinker::PreprocessDirectory(const char *pDir) -{ - MString temp; - - if (strncmp(pDir, "{$VT_ROOT}", 10) == 0) - { - // Substitute the VirtualT path - temp = path; - temp += pDir[10]; - } - else if (strncmp(pDir, "{$VT_PROJ}", 10) == 0) - { - // Generate a projet relative path - temp = pDir[10]; - temp.Trim(); - temp += (char *) "/"; - temp = m_RootPath + (char *) "/" + temp; - } - else - temp = pDir; - - return temp; -} - -/* -============================================================================ -Returns the Start address (lowest address) of the generated code. -============================================================================ -*/ -unsigned short VTLinker::GetStartAddress(void) -{ - return m_StartAddress; -} - -/* -============================================================================ -Returns the Entry address (lowest address) of the generated code. -============================================================================ -*/ -unsigned short VTLinker::GetEntryAddress(void) -{ - return m_EntryAddress; -} - -/* -============================================================================ -Constructor for the CLinkRgn object. This object is used to keep track of -regions defined in the linker script. +Sets the Linker external defines ============================================================================ */ -CLinkRgn::CLinkRgn(int type, MString& name, int startAddr, int endAddr, int prot, - const char* pAtEndName, int atend) -{ - m_Type = type; - m_Name = name; - if (pAtEndName != NULL) - m_AtEndRgn = pAtEndName; - m_Protected = prot; - m_AtEnd = atend; - m_LocateComplete = FALSE; - m_pFirstAddrRange = new LinkAddrRange; - m_pLastAddrRange = m_pFirstAddrRange; - m_pFirstAddrRange->startAddr = startAddr; - m_pFirstAddrRange->endAddr = endAddr; - m_pFirstAddrRange->pNext = NULL; - m_pFirstAddrRange->pPrev = NULL; - m_pFirstAddrRange->nextLocateAddr = startAddr; - m_pFirstAddrRange->endLocateAddr = endAddr; - m_NextLocateAddr = startAddr; - m_EndLocateAddr = endAddr; -} - -CLinkRgn::~CLinkRgn() -{ - LinkAddrRange *pRange; - LinkAddrRange *pNextRange; - - pRange = m_pFirstAddrRange; - while (pRange != NULL) - { - pNextRange = pRange->pNext; - delete pRange; - pRange = pNextRange; - } -} - -CObjFile::~CObjFile() +void VTLinker::SetDefines(const MString& defines) { - int count, c; - - count = m_FileSections.GetSize(); - for (c = 0; c < count; c++) - { - delete (CObjFileSection *) m_FileSections[c]; - } - m_FileSections.RemoveAll(); + // Save the project type + m_ExtDefines = defines; } -CObjFileSection::~CObjFileSection() -{ - int count, c; - - if (m_pStrTab != NULL) - delete m_pStrTab; - - if (m_pObjSegment != NULL) - delete m_pObjSegment; - - count = m_Symbols.GetSize(); - for (c = 0; c < count; c++) - { - delete (Elf32_Sym *) m_Symbols[c]; - } - m_Symbols.RemoveAll(); - - count = m_Reloc.GetSize(); - for (c = 0; c < count; c++) - { - delete (Elf32_Rel *) m_Reloc[c]; - } - m_Symbols.RemoveAll(); - - // Delete program bytes pointer if not NULL - if (m_pProgBytes != NULL) - delete m_pProgBytes; -} diff --git a/src/linker.h b/src/linker.h index b8716e7..edf27ff 100644 --- a/src/linker.h +++ b/src/linker.h @@ -38,6 +38,15 @@ #define LKR_CMD_ERROR 98 #define LKR_CMD_COMPLETE 99 +#define SCR_CMD_IF 1 +#define SCR_CMD_IFDEF 2 +#define SCR_CMD_IFNDEF 3 +#define SCR_CMD_ELSE 4 +#define SCR_CMD_ELSIF 5 +#define SCR_CMD_ENDIF 6 +#define SCR_CMD_DEFINE 7 +#define SCR_CMD_ECHO 8 + #define START_ADDR_CODEEND -2 #define START_ADDR_DATAEND -3 @@ -50,6 +59,32 @@ #define MAX_LOADER_LINE_LEN 220 +typedef struct +{ + char op; + char* val; +} SimpleEqOperator_t; + +// These are in order of precedence! +#define SIMPLE_EQ_PAREN 0 +#define SIMPLE_EQ_LOGOR 1 +#define SIMPLE_EQ_LOGAND 2 +#define SIMPLE_EQ_EQUAL 3 +#define SIMPLE_EQ_NOTEQUAL 4 +#define SIMPLE_EQ_LT 5 +#define SIMPLE_EQ_LTE 6 +#define SIMPLE_EQ_GT 7 +#define SIMPLE_EQ_GTE 8 +#define SIMPLE_EQ_ADD 9 +#define SIMPLE_EQ_SUB 10 +#define SIMPLE_EQ_MULT 11 +#define SIMPLE_EQ_DIV 12 +#define SIMPLE_EQ_LOGNOT 13 +#define SIMPLE_EQ_HEX 14 +#define SIMPLE_EQ_VALUE 15 +#define SIMPLE_EQ_NOADD 127 +#define SIMPLE_EQ_SIZEOF 100 + #define VT_ISDIGIT(x) (((x) >= '0') && ((x) <= '9')) #ifdef WIN32 @@ -143,17 +178,37 @@ class CObjSymbol : public VTObject unsigned long m_Off16; }; +class CLinkRgn : public VTObject +{ +public: + CLinkRgn(int type, MString& name, int startAddr, int endAddr, int prot, const char* pAtEndName, int atend); + ~CLinkRgn(); + +// Attributes + MString m_Name; + LinkAddrRange* m_pFirstAddrRange; + LinkAddrRange* m_pLastAddrRange; + MString m_AtEndRgn; + int m_Type; + int m_Protected; + int m_AtEnd; + int m_NextLocateAddr; + int m_EndLocateAddr; + int m_LocateComplete; +}; + class CObjFileSection : public VTObject { public: CObjFileSection() { m_pStrTab = NULL; m_pObjSegment = NULL; m_pProgBytes = NULL; m_Located = false; m_LocateAddr = -1; m_Size = 0; m_Index = -1; - m_Line = 0; m_LastLine = 0; }; + m_Line = 0; m_LastLine = 0; m_pLinkRgn = NULL; } ~CObjFileSection(); Elf32_Shdr m_ElfHeader; // The ELF header as read from the file char* m_pStrTab; // Pointer to the string table, if any CObjSegment* m_pObjSegment; // Pointer to the Segment data + CLinkRgn* m_pLinkRgn; // Region where segment is located VTObArray m_Symbols; // Symbols from the symbol table VTObArray m_Reloc; // Relocation entries VTObArray m_Equations; // Linker Equations @@ -168,25 +223,6 @@ class CObjFileSection : public VTObject int m_LastLine; // Ending line in source for segment }; -class CLinkRgn : public VTObject -{ -public: - CLinkRgn(int type, MString& name, int startAddr, int endAddr, int prot, const char* pAtEndName, int atend); - ~CLinkRgn(); - -// Attributes - MString m_Name; - LinkAddrRange* m_pFirstAddrRange; - LinkAddrRange* m_pLastAddrRange; - MString m_AtEndRgn; - int m_Type; - int m_Protected; - int m_AtEnd; - int m_NextLocateAddr; - int m_EndLocateAddr; - int m_LocateComplete; -}; - typedef void (*stdOutFunc_t)(void *pContext, const char *msg); class CObjFile : public VTObject @@ -217,6 +253,46 @@ class CObjSymFile : public VTObject const char * m_pName; // Pointer to the name string }; +class CScriptCmd : public VTObject +{ +public: + CScriptCmd() { m_ID = 0; } + + int m_ID; // ID of the command + int m_Line; // Line number from linker script + MString m_CmdArg; // Argument line after the command +}; + +class CSimpleIf : public VTObject +{ +public: + CSimpleIf() { m_Executed = FALSE; m_StartLine = 0; m_CanExecute = TRUE; } + + int m_Executed; // TRUE if this if / else has already executed + int m_CanExecute; // FALSE if #if was in an non-execute block + int m_StartLine; +}; + +class CLinkScript : public VTObject +{ +public: + CLinkScript() { m_ifdepth = 0; m_execute = TRUE; m_executeIdx = 0; } + + int m_ifdepth; + int m_execute; + int m_executeIdx; + CSimpleIf m_ifStack[20]; + VTObArray m_Script; +}; + +class CDefine : public VTObject +{ +public: + CDefine() {} + MString m_Name; + MString m_Value; +}; + class VTLinker : public VTObject { public: @@ -229,12 +305,16 @@ class VTLinker : public VTObject VTMapStringToOb m_Symbols; // Map of Symbols VTMapStringToOb m_ObjFiles; // Array of CObjFile objects VTMapStringToOb m_LinkRegions; // Map of CLinkRgn objects where we can link to + VTMapStringToOb m_Defines; // Map of CDefine objects defined MStringArray m_LinkFiles; // Array of filenames to be linked MStringArray m_Errors; // Array of error messages during parsing MStringArray* m_ActiveLinkOrder; // Array of error messages during parsing VTMapStringToOb m_LinkOrderList; // List of link order arrays per segment VTMapStringToOb m_LinkContainsList; // List of link order arrays per segment VTMapStringToOb m_LinkEndsWithList; // List of link order arrays per segment + CLinkScript m_PrelinkScript; // Pre-link script to run + CLinkScript m_PostlinkScript; // Post-link script to run + VTObArray m_ProgSections; // Array of Progbits sections MString m_SegName; // Active segment name stdOutFunc_t m_pStdoutFunc; // Standard out message routine void* m_pStdoutContext; // Opaque context for stdout @@ -248,6 +328,7 @@ class VTLinker : public VTObject int m_TotalDataSpace; // Total space used for data int m_TargetModel; // Target model we are linking for int m_LinkDone; // TRUE if link complete + int m_LinkScriptRaw; // TRUE to pass raw strings vs tokenized unsigned short m_StartAddress; // Start address of generated code unsigned short m_EntryAddress; // Entry address of generated code MString m_OutputName; // Name of output file @@ -258,6 +339,7 @@ class VTLinker : public VTObject MString m_LoaderFilename; // Filename of loader to be generated, if any MString m_LinkerScript; // Name of the linker script MString m_EntryLabel; // Label or address of program entry + MString m_ExtDefines; // Externally set (by IDE) defines MStringArray m_ObjDirs; // Array of '/' terminated object dirs CObjFileSection* m_SegMap[65536]; // Map of Segment assignements ListAddrLinesAry_t m_AddrLines; // Array of relative address / line mappings @@ -282,7 +364,7 @@ class VTLinker : public VTObject void AddEndsWithSegment(const char *pStr, int lineNo); void NewLinkRegion(int type, int lineNo, int startAddr, int endAddr, int prot, const char* pAtEndName, int atend); - int EvaluateScriptAddress(const char *pStr, int lineNo); + int EvaluateStringEquation(const char *pStr, int lineNo, int* asHex = NULL); void ProcessArgs(MString &str, const char *pDelim); int ReadLinkerScript(void); int ReadObjFiles(void); @@ -303,6 +385,7 @@ class VTLinker : public VTObject int ResolveLocals(); int ResolveExterns(); int ResolveEquations(); + void ParseExternalDefines(void); MString MakeTitle(const MString& path); int GenerateOutputFile(void); int GenerateMapFile(void); @@ -312,6 +395,9 @@ class VTLinker : public VTObject int GenerateLoaderFile(int startAddr, int endAddr, int entryAddr); int Evaluate(class CRpnEquation* eq, double* value, int reportError, MString& errVariable, MString& filename); + void ProcessPostlink(void); + void ParseSubScript(char *lineBuf, int lineNo, CLinkScript *pScript); + void ProcessScript(CLinkScript *pScript, int singleStep = FALSE); public: // Public Access functions @@ -321,6 +407,7 @@ class VTLinker : public VTObject void SetLinkOptions(const MString& options); void SetObjFiles(const MString& options); void SetLinkerScript(const MString& script); + void SetDefines(const MString& defines); void SetObjDirs(const MString& dirs); void SetRootPath(const MString& rootPath); void SetLoaderFilename(const MString& loaderFilename); @@ -331,7 +418,6 @@ class VTLinker : public VTObject void SetOutputFile(const MString& outFile ); int TotalCodeSpace(void) { return m_TotalCodeSpace; } int TotalDataSpace(void) { return m_TotalDataSpace; } - void ProcessPostlink(void); }; #endif diff --git a/src/memedit.cpp b/src/memedit.cpp index 730be3f..575004f 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -3073,6 +3073,7 @@ int T100_MemEditor::handle(int event) break; } + redraw(); break; case FL_MOUSEWHEEL: diff --git a/src/multieditwin.cpp b/src/multieditwin.cpp index 4a48231..f5bf249 100644 --- a/src/multieditwin.cpp +++ b/src/multieditwin.cpp @@ -162,6 +162,7 @@ Fl_Multi_Edit_Window::Fl_Multi_Edit_Window(int x, int y, int w, int h, const cha textsize(14); #endif m_Modified = 0; + m_TabChange = 0; m_Title = title; this->label((const char *) m_Title); } @@ -314,6 +315,18 @@ void Fl_Multi_Edit_Window::SaveAs(const MString& rootpath) m_Modified = 0; } +/* +=============================================================== +Routine to handle modifications to the text buffer +=============================================================== +*/ +void Fl_Multi_Edit_Window::tab_distance(int size) +{ + m_TabChange = 1; + buffer()->tab_distance(size); + m_TabChange = 0; +} + /* =============================================================== Routine to handle modifications to the text buffer @@ -326,19 +339,20 @@ void Fl_Multi_Edit_Window::ModifedCB(int pos, int nInserted, int nDeleted, return; // Check if buffer had already been modified before - if (m_Modified) - return; + if (!m_TabChange) + { + // Update the window title to append a '*' + if (m_Title.Right(1) != '*') + { + m_Title += '*'; + label((const char *) m_Title); - // Update the window title to append a '*' - if (m_Title.Right(1) == '*') - return; + m_Modified = 1; + } + } - m_Title += '*'; - label((const char *) m_Title); if (parent() != NULL) parent()->redraw(); - - m_Modified = 1; } /* diff --git a/src/multieditwin.h b/src/multieditwin.h index 8d35fc4..45c5a11 100644 --- a/src/multieditwin.h +++ b/src/multieditwin.h @@ -66,6 +66,7 @@ class Fl_Multi_Edit_Window : public My_Text_Editor, public VTObject int ForwardSearch(const char *pFind, int caseSensitive = TRUE); virtual void show(void) { My_Text_Editor::show(); Fl_Widget::show(); } virtual void buffer(My_Text_Buffer* buf); + void tab_distance(int); My_Text_Buffer* buffer() { return My_Text_Display::buffer(); } My_Text_Editor* m_te; @@ -75,6 +76,7 @@ class Fl_Multi_Edit_Window : public My_Text_Editor, public VTObject MString m_FileName; MString m_Title; int m_Modified; + int m_TabChange; int virtual OkToClose(void); }; diff --git a/src/pref_form.cpp b/src/pref_form.cpp index 47d2996..fcc2e16 100644 --- a/src/pref_form.cpp +++ b/src/pref_form.cpp @@ -15,10 +15,14 @@ extern int gReloadProject; Fl_Double_Window *pref_window=(Fl_Double_Window *)0; Fl_Button *pref_ok_btn=(Fl_Button *)0; +Fl_Input *tab_size_choice=(Fl_Input *)0; +char stab[10]; + static void cb_pref_ok_btn(Fl_Button*, void*) { text_size = text_size_choice->value() * 2 + 6; + tab_size = atoi(tab_size_choice->value()); auto_brace_mode = auto_brace_check->value(); save_window_size = save_wsoe_check->value(); auto_hide = hide_output_check->value(); @@ -173,11 +177,15 @@ Fl_Double_Window* make_pref_form() { o->labeltype(FL_ENGRAVED_LABEL); o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE); } - { Fl_Choice* o = text_size_choice = new Fl_Choice(130, 45, 60, 25, "Text Size"); + { Fl_Choice* o = text_size_choice = new Fl_Choice(90, 45, 60, 25, "Text Size"); o->down_box(FL_BORDER_BOX); text_size_choice->add("6");text_size_choice->add("8");text_size_choice->add("10");text_size_choice->add("12");text_size_choice->add("14");text_size_choice->add("16");text_size_choice->add("18");text_size_choice->add("20"); text_size_choice->value(3); } + { Fl_Input* i = tab_size_choice = new Fl_Input(240, 45, 40, 25, "Tab Size"); + sprintf(stab, "%d", tab_size); + tab_size_choice->value(stab); + } { Fl_Check_Button* o = smart_indent_check = new Fl_Check_Button(30, 95, 180, 25, "Use Auto-Indent Option"); o->down_box(FL_DOWN_BOX); } diff --git a/src/pref_form.h b/src/pref_form.h index 8f49f41..6d01bfc 100644 --- a/src/pref_form.h +++ b/src/pref_form.h @@ -8,6 +8,7 @@ #include extern void load_lang_cb(char *file); extern int text_size; +extern int tab_size; extern Fl_Color hl_plain; extern Fl_Color hl_linecomment; extern Fl_Color hl_blockcomment; @@ -36,6 +37,8 @@ extern Fl_Group *ed_group; #include #include extern Fl_Choice *text_size_choice; +extern Fl_Input *tab_size_choice; +extern char stab[10]; #include extern Fl_Check_Button *smart_indent_check; extern Fl_Check_Button *save_wsoe_check; diff --git a/wish_list.txt b/wish_list.txt index 80bd93f..a062094 100644 --- a/wish_list.txt +++ b/wish_list.txt @@ -20,8 +20,6 @@ in no specfic order. - Modifiy IDE / Project settings window so it is resizable and uses a list on the left with control window panes on the right. -- Add Linker Script command processing. - - Add IDE Project Profiles to allow setting environment variables for M100, T200, etc. - Update TDock VGA so that it pulls in the M100 ROM and doesn't depen on the M100 @@ -35,8 +33,6 @@ in no specfic order. - Update REX memory model to pull in REX 4.9 instead of REX 4.8. -- Add ability from IDE / Editor to specify Tab spacing. - - Add ability to create multiple Memory Editor windows. - Add ability to support more than one active emulation. From f83d41e1ccf4883ad1ef76c8e2a48dffe6b58069 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 6 Mar 2015 01:41:10 +0000 Subject: [PATCH 276/327] Updates to compile under Windows --- VirtualT.suo | Bin 335360 -> 343552 bytes doc/ide.jpg | Bin 176120 -> 22 bytes src/elf.h | 6 ++++++ src/ide.cpp | 56 ++++++++++++++++++++++++++---------------------- src/idetabs.cpp | 2 +- src/linker.cpp | 8 +++---- 6 files changed, 40 insertions(+), 32 deletions(-) diff --git a/VirtualT.suo b/VirtualT.suo index 224d49945b28dad79c2074d4e2a479a58f04986c..4cdf102897eae8d1f8b1df42ad816c4b10d0037e 100644 GIT binary patch delta 30257 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 delta 25727 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
    m5XEK^Wp;Nnqry60h3M=$DXnRFh@2G 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 diff --git a/doc/ide.jpg b/doc/ide.jpg index 8e69176df2dc2e21285dbdee7257d4dbf94ebca5..8491803946245522ebdcb739096e7c7b9becc5df 100644 GIT binary patch delta 6 NcmexypG$0l7yt{=0-gW> literal 176120 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
    vOf2&>x1MU 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˿q8h^+9| zdPA%_Z9P=H+Mr@}zDjf6CBwb2$yez1_wDMFN-TA*ngM;efb?)Q)E#|#{UPlcU`K&k zQgKnc!0xdXi3|Az*L~1o!8`1(-8Y@KlzOth)2=*>YsdFCq!`UpCk*KXDTgMZG{g~P z&9F2Cmm_qXj^alb+uGZzWD|#3DpIsd2yTf7ut!W{JRy!U!OIHS8Q621^5Shx$#%^m zHqK8sH+w!#WhLvc>2JZbrD)s`(#veHVd4jhh_DS|t{xa8>Utqk_byx}FpM`%%}?&6 z+?vJ@=bPH%Nk1;;x3n^pW-Nh>voL{w7|2p2Bdfj~?ixUIVV(UVVHVbtZ--pe9jVwI z8q@moq-I5+!(~v>@9rH`G_k;cYFro?v6aLJLo3N9B zq+#w&Xv|X|9TQ1dVpX6ei z5zqQv`jCB;Jwd<$+XoIzz;++froeg^b^&#fihZr|^lRmP0eWQRD$lBH*ozAP&&rv% z`1t*^c0%DR&@e1t8@Onv`6&S#V4?tG8n+)q9o|@_)_%kAex;m=B-(vIT%rs|?di>R zTUlnL<;p)VZcVn>Vg1E9`c*KBrF97l)}s{5tr!RkT{r|(@BG@JUG>fj8QnI4MtfFP zcnP_KaoeN%@|m%3epl}dq)25j_wk9Qo~hGf0znx&|KZmHCgEOM5E|ccPD(GGsU~zx zo7zUdkhHh1Dti0foREF2O=XJ5*BrZm-~qm5H^wpS!W%p;4kHMz7Yed~xUkl;oXHap zC#@Tjg<#m}yynO*e8b-LGQL6C(yX}cPjBa&6M@SrU2H-7-@%%vn07OrB!f)porJJw zpancQG-^F~Z`iGR*Z+Q@6X}c1^hu*cjSKg_xaRA4`bautnyzpRDtA2K3UMOLMhcEp z|BSVugr?-#JARjvS-38>n)pg_CH5TXPo5#diY z?^-9u-?L6rMc38MKVeyRQ#ccCzRWcw{k9c}!?K{|~aL2T?s2qHmM{4L<` zkr4pxrn6CT-F9v$71AJ^uU@WktAn}TgvR?E>lF*{mFXdu@7Acn3!+&H>(l!w?=3QdF#xZl8)hCqy zB7go76Xr%(iom-8U9Hq3V|0gIB-shQ=xGN=I1!GNyGR7#iZKF^(PuEZI3e1cZ7tYj zvlkHUVm32g_dM_QKvD+-Na+au@()9Qc1Rca`SpuIr-+GTlrGG{Etg^?)30?7r9n~X z!M=vou5`zmM5w8|*-93X92Bfm9vYf!q`Xh6sJC`UR&4Rx_UJrP=!Qi`@#Ha}Mz4JTvuXZb~|?Rw(&I>VMQ4|2{eIe(HQPW+1CS9qJy+dOax4uHS~{s4#6 zCcbUE>I!n7!eOWU6*!R>zaO5Bt%tGcdsnX3)NR{~&p(}&z1e@UrdDUH>ypuzv&^UY zD;`*=v9G5hU`@DNs*xogfsMUD8&YbS6(D#m*+@Q z*uPaVuCqQD*mgVJ<@QR=eUkd|iN8MxqrDFQ$>;U-&iAM6DIo)puYGUnGAQojkDfGG zUVUFIMh)fEJZ8J=Xs_GYxzFOnjel-)3VyVnnZ9%K?}x|}uTNQl^ZVLiaxp1)`hesb zM|&_Sz#jh$h%cD`<9MZ-DsDdPS!p|OB(xKq!IbyWeu&kKNi2!)#@-rx-aNQ#SkqAR z8h}kDGN21`ewUAa-mL{RjEKMaU`$^0Yh9wLVQQL-NgYq%7+E{nXj+cdQ#7eD9k6+( zI(ahgnl=B?yW(>_JJTVX@p@GOZC{$2wWKL z7R8E415H}`x^h9HM{FOK1EY?&UCWUk_fk5x{59i#m{XbWc5Q@s z$8D z(eU{AVO~vRk}Mk%^xXM-m3$yiaAb04r~k9UwSE=HqGbJEX7g6KZP}d3{G-5RPk4Tr z{?U+pHt(=WItgWQbPr%O0!%^jL7x^6#eWx!DSy za2{TC9J%YM(DM&NeZU(HRnpd(KRFupRIhsXPx7f>=3sVqZRx&+Op-@}QIfOqqM}R; zQYB(B+r_?OY46fpRK>HB;a>n=YP#KVHbxO?-iKu?Y)tGHVVkI^&sMFx%-OZlA^kn` z*YVQ8YaJb(KwZ)G1kDny)qaqDo=9*(FN!Z z5KvesQR{oH#eq@>@8rE>G|2$CJJ`e1cvyH~TYmLLi$h*hL{MXWyt4Rt)CVWA$Nas% zBXBGO)O9%8612YT12?)b$ay6>ZaM?f?8tH~M9cvhvk5~gObwBwPw~>PALsc&q6w@t!G+uiutlcl@l>Cnl&j>=JKU8?@kvJr?@jy^ z=k)yhupD_?*?$;z1j61O4>W9!ZUc=e*wFh_n_Ru!t z=TnVi4*0?1xtXsYpVp&z`-<6lIX)vj$jw}!F zDO1-Jo}aPrjE!>vW4Zoe0MQdLfD-DFIAh*TzkFQkH+0V)KoiM~-8ouRqxAivVf^N& zhMJ~qb8--E<=t$1)BI1H{=czas?|rvG*!T}0^Omh1;&vAK?^Lf2#ge!H(n{1{hq6H z`TQEkdWLgq#rxdn?;Q;<*(3)QaPhS@&4~Yne-m*hR?R?6f#6cwqfDaiTN*D>-6U2- zSc|8l{Wt-|Z0S0QFA>hf`!_?yv7M`oTrrA9AXfW8gkpR6-sBK$$0 z+N|8%EmLph&0%xctP0;)G>iXzRjpRso7C7|49b zS@_H<>Ac7fxbyCxr+=3x+>Ge^sLczt#wNMxnc0rNyu*{m~>{V6X{ju%BjTFHg^&kp+CCN@?c1_K1;wl)3p6UpHkC} zo1S-G|J>~3MlTc+syD+aP&zYrAx-i4gIGfEI&7>BDmvzg*z_XrR+yO9h3YgkHZ|XG zMh4i6i9Lvw?`L?-&i#!hd5rZZM8FvR&}5erz%hIHbG`l2*cRHFUXV@qk8fiIHE zhfel*3z_TC?>~6boPdlKm5{j!S_w`p<|d#U=K8>T?gILmJ6$u~zLt9GZtq-AYQ<1- z%D%UdSzCOy)-VVD$24P#V>oN$Et`7#M}-se2GP3NO)5xflcYx1fx;CTsUg1<Jnlv-KeFOO9kFFg*>L zB#f~|?ZQWnIQ)jxhu(OD*Pbcew zQ+j9Wi8hnq1@=h#nTg7!oOLrai=Ct0=PGZ-9H(J5`#EFAO}TDITUy^z1tA{YXk2=9 zo5oD3dK)4E@Dk^KmM#nl40hpNV~I7bk+4MLy6>UWb6%JqYuqtj%17VnvOBg!pK>Es zEpx+Z_q($L)RuZxbCX)f9j~89?%oE4b|qWbzq6FJL-YMWkcu*lSJ(%Y<|RnRuCX-; zH|pvlmet1Eh;{p;Lb;Mfd)<-1J?wxiLag@EfY<5H&5p|$c$NQgG2aKexBh)08VY{{~Rs=ZR-} z8(r<`S8lmAcT?I}+L4aWgf@6ZQn35*VcyZ0=Yr$}vv;TwiU?A;UsVH4i&yKxxLLxR5V2W^9GOV9 z+K;{GEPcyc7VZ@E+$Ngg!X^Jc$~L^|_!D;F6COO)5qPvd&{u#||2EG6gnwQqP*Mg< z0Z%2yaOM{zo@ubJ$bS79$4=n}uA6 zKlVKgi6aJsb9%U(^YX{Gpi`6Ug67J%syB{m$0bF_Ia&gQKltcj1kaNYO_X{ZlTb#gM^n0d_8?|2J_B6zw<5>dG>Ojln}dK==`DfUm|hV z`l|!*;AdY2!7d&e5A|mw(epgy{A!LA^=#zlmWhR$HyW)-g6F`D@zX>PF{4v)CoA=P zP_@LYJstBRRqdf3gFWY~O}!bWsI@{{gYqwfsRsC-?RsS9(JMRXpwY3qHM#BPks?j{ z_@mZYlp#=0jn#+6z0yjjUS1~_hbk6Ld>-4KvmqD2qxTG(H|Cs?VQd~^de3eTsfwrC zE}$2Ru_rVj6v$#gSYn6f<@GK#s|3{9Prv};{H$aDE4pA4w$7%ohRg5>XCZ#$qgHSY z16*p~=NMZ*Jbkb*vDHO}eFJaf5HUb)(H_P*i;!DXQvQ__7TmWP zm=Ax{$_`z1Nv?|iGN<&T>gV5Q8KI$%=zL9hW3w7B6CKjr*R0hhTN&8e;YTQY8&@z@ zp$`v<)VL99WY{ebCg7Q$6R$Wb>jvE_<~|HM3a~|S9v5R2LZ)8aq0rZUE-t7Aj3f$|X^Nj6gn_EyU ztKpS4wrk$~5?LVAqNZC?Z%#Pn)m2fo6}}yXkckSn%XMcYvc_LuuJI5UFc*ppa>Nw-D z(NufOvRK=my`#5;YoEMj1B{p3pjAq(n-k%)sP=(4FkiKphU9XFaeEvl5_#t9{HW;g zBY!5TJdd~pZHkAs-fOOtwf7Q54F{Bk2;Q~>06(N0%Bm(c3uVE(3Gh%KVdY7%$njPc z?xabrWB?qy9K+Yff7N&?=rp-a@YahU0r#9wkAuo}D87fd-5DTeruP0#%q-bL*=_#U zn0fHO#!P48-E4gRijmQV+Mt=^o1r%aqJ~rA2C1E5I;kIvM4ev*hv-||Y;CQ6KY&rJ z4^x^hkZ^QnIZ~V*RmZ_)7IVg$CRa;sD{`}5EZ)LX6$1vH8Z1Q`-@wjw`HW$((AOrn z-z3NW1Z?49B#RbkrA|D6mx{le|p;06C{=w<-r+U=at5KpIF6n1bzS#{VnK^&kEE-&T*}^M7g(ti|y+wA_&wPrDV?kS7ik zY7RpPs3bsK>+^2XX}#G#MHVB#B=)jye{qU@_`DmB;?sr0+48d?7E%Y-R#hybP_DRR zP%0tE@ba)-Roe2xMIAP#m+1&{4U#-?-(v&l05=4-GlL_5L*qP-yGAqQ?Fwtzc;o|* z`8PVw10uXvMq^@Svv0n6!jl}mBt(DO$}bnuN7}7`C%XCgmfx#3&r>cke3xO{ePzeT zJlGX!*VXhO{&R&T;w)?DS+C5+7kl|x!F~&;z1@m5tdt~HayLpx2L@nF2obVH(#~oe z;4AFX&O23*GpR=5^&7v|>itGlJ727Y5p5mb207bwW6p9D+Jfh*Dv{3Mn97t86XnW@ zVP51gtr9vX7oQAuS>Cs32gjl+WmaP(nGOwP+J#g zL|ebVvbgEXDI>FP2@^`0Y2aQxv{7Qxev(~Uqr>1tLWgODjGKO`Td@%=TW$0ZKpi$u zJ8gD$FVFZcLU`cJc2xgjVZb7S+x#oWDcUG)KjBSUWs~D`exX<<6SGL~`0!;b1)vZV&o8*WQ2-E3GDo0;0A;_vX6wM4}2*?9?-xyrqR)q@5&#T0r0Ch|o1pk|`yc8b!=v1ZaBU zUe%l2aD5O{S7@QT9Cez(>*0t3dnixsR&GPZaps_avIhRz$JbOqZQ>Huhk4jjE9fd? z00E7P%9bCX)IHsuoI1T6%fY7SsoH9Lj3!m}c=h>>?sDlTf7ji;0%-64XMY;~3C-GF zTGb<%Qke(Cn290$@~l%B;W?q*OM6Tlevv(KS05X3SmOtahn_%k(auwWfyF8>BKyLi z+O=N{OsHqo2KSz5#CVkHdpX*?OB8zkUG>(56z70H?ujuFKYCxU({Db_>fJQi;91y{ zJL#>b;at#@;VG0E*r4~_!EeT4sd(R%&NO&%o~C;E5h?m(`WSh$!}uJPyOVxpOmL{$ zhFRtW%5&1Tl+3~SDcSdQ#{H0^*g5%C=p4L}=v&;GA zNg{{u=qG97)Sz;=eaKoNSqI4foV%}gnI1{MMYn*zRpgj6@znWa>y<=wgif4pV({@f z@fgKLKLX#JJzL=7LY`@{mm--h=5XVs?vGc8Bq-Xv0_5jhw4|F7wY5S$fijjSPOI)P zU*nQH+c)T{fch{Jykb0S2QeBctDZ8MyO*MS$z|Bf3*Z4^6US`oFMsj!DZQC;!Vgl{ zjENbZO>aX_?4y8;!c`68pyqW+VO%R|dgN(znR};AbV~R7T@(Db2~9~1?2;R$M3!sd zj74h_>%*%&r9MFr*W4E`m&Cm@4fT!mC6awwgah7gZb}q#O=COd3fC340L{$sdh%%3 zS{_+{fN+z#wMoDv5lM2ls*+eCQRU-$*D8+K+P$KcbukYvu4LdIUWNY1?2^_a>A;PT^qQk>3DW0My_-^(sgZD>^Q54A(0)l6D z;i@39*tA2(y4tNN z;h_XipS{~;_0;LCBDdk@vZ;a*sWX%+K~DI5!V^dT`}c|%!cHmVkX8wpX!=!nKhXGP z@?(K@Xj~eZNEe8U+?y0r73ei(& z$0#An@m)+l#C3Hh7FV^fxt=r!G#0TGpdPA(DA2U2gAOd?Ei(-8@s6}{?n1*@Pd?2CT%t`5IKy)^C*kQ! zorBi!#mQ|4{&Dp=xM#cO;42Jtg-t(4GoU{Qea*^VkWHe zJOT6NrwAc%*n&IP#%jh!I{10KWZFJbd_J3t)R{AfVqeC~JS$xqQLwXLk&uwEwD7Bw z`%Dl_U<`0}VhGOI=cb>A0(oW=LNb~GQz5s)JI6HC;@TVd)5n#@0z}4`FWj7_ue4G+ zK$)U%E@t1ycpN!_~w{E|%n|b)^G+clICIAnFY^OE_{_e(-&_KQUw! zzSfj!o^s8{)3mSAmDVoU6TiW**tm&*ahC*eAzYx}GCKvh$k;OCCZikgK%C#9PCNDz zNxgZhtzqTEjINiw+r~od($a|VB_TB1{fbU+sKRS+jmy~~227ES1>9Hqd=v|nvg%uVU} zWy!RW;L@A-BJqnh;jl;Pb#am&+!+U_u1QXsYe^;ku`f7>TQ36ydeFxa4+^N7opey+ zXpI!x)>zLeh!b$ScOB}J`?M0BPMWSxi?@6ts^uJ?wZe2qqLgX~Ea?Pw6!^P_Dh2K^ zK8+A01KP35?!0OZiD+a)AUcO8Ugi3#d98d#c&u>2OFZwI%~7kkkEfKYjHHXyxFzRF zA7gscQUa1x>n!Y3^jSTX6}TvR^?KSy=lu$3y_lWsrNyWYnW*5TR&Wefkc5uI4jh&d zLQR%*o416vFK@3exaNQR#+UA+c=n{$jak$Y4;(wf;A|Xe5&!^emfChnR#+~l`PhB$ zN!A|f>E&>@e3qyz^pLUV{g=l_6wvQilz2OH)Tc3O;}(G?^23I5=_xJ`4dkvZyh_m% zO)>mEBRTF$n$97DH0ovQY-ZaNQ{$LLM?SMGb24b{_#}O@BXQHPCNOZKg&6ImE zIú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≤kzaw8`_8&effujpD<$(!f(6iV{Mq&@W6IaM3)x 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�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 diff --git a/src/elf.h b/src/elf.h index 3110b6a..bb23496 100644 --- a/src/elf.h +++ b/src/elf.h @@ -31,7 +31,13 @@ #ifndef ELF_H #define ELF_H +#ifdef WIN32 +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int16 uint16_t; +#else #include +#endif typedef uint32_t Elf32_Addr; typedef uint16_t Elf32_Half; diff --git a/src/ide.cpp b/src/ide.cpp index b795af8..96a7502 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -3625,8 +3625,8 @@ BuildProjet: This routine is the reason for all this mess! Try to assemble void VT_Ide::AssembleSourcesInGroup(VTAssembler& assembler, VT_IdeGroup* pGroup, int& totalErrors, int& linkerScriptFound, MString& linkerScript, MString& linkerFiles) { - int groups, sources; - int c, x, err; + int x, sources; + int err; int index; VT_IdeGroup* pSubGroup; VT_IdeSource* pSource; @@ -3729,19 +3729,16 @@ BuildProjet: This routine is the reason for all this mess! Try to assemble */ void VT_Ide::BuildProject(void) { - int groups, sources; - int c, x, err; - int index; + int groups; + int c, err; VT_IdeGroup* pGroup; - VT_IdeSource* pSource; int errorCount, totalErrors=0; MString text, temp; - VTAssembler assembler; - int assemblyNeeded; + VTAssembler* assembler; MStringArray errors; MString filename; MString linkerFiles; - VTLinker linker; + VTLinker* linker; MString linkerScript; int linkerScriptFound = false; @@ -3766,6 +3763,9 @@ void VT_Ide::BuildProject(void) m_BuildTextBuf->append("Assembling...\n"); Fl::check(); + assembler = new VTAssembler; + linker = new VTLinker; + // Loop through each group and look for files to assemble errorCount = 0; groups = m_ActivePrj->m_Groups.GetSize(); @@ -3774,7 +3774,7 @@ void VT_Ide::BuildProject(void) // Get group pGroup = (VT_IdeGroup*) m_ActivePrj->m_Groups[c]; - AssembleSourcesInGroup(assembler, pGroup, totalErrors, linkerScriptFound, linkerScript, linkerFiles); + AssembleSourcesInGroup(*assembler, pGroup, totalErrors, linkerScriptFound, linkerScript, linkerFiles); } // Check if there were any erros during assembly and if not, @@ -3790,29 +3790,29 @@ void VT_Ide::BuildProject(void) Fl::check(); // Setup the linker - linker.SetRootPath(m_ActivePrj->m_RootPath); - linker.SetLinkOptions(m_ActivePrj->m_LinkOptions); - linker.SetObjDirs(m_ActivePrj->m_LinkPath); - linker.SetProjectType(m_ActivePrj->m_ProjectType); - linker.SetOutputFile(m_ActivePrj->m_OutputName); - linker.SetTargetModel(m_ActivePrj->m_TargetModel); - linker.SetDefines(m_ActivePrj->m_Defines); + linker->SetRootPath(m_ActivePrj->m_RootPath); + linker->SetLinkOptions(m_ActivePrj->m_LinkOptions); + linker->SetObjDirs(m_ActivePrj->m_LinkPath); + linker->SetProjectType(m_ActivePrj->m_ProjectType); + linker->SetOutputFile(m_ActivePrj->m_OutputName); + linker->SetTargetModel(m_ActivePrj->m_TargetModel); + linker->SetDefines(m_ActivePrj->m_Defines); if (linkerScriptFound) - linker.SetLinkerScript(linkerScript); + linker->SetLinkerScript(linkerScript); else - linker.SetLinkerScript(m_ActivePrj->m_LinkScript); + linker->SetLinkerScript(m_ActivePrj->m_LinkScript); linkerFiles = linkerFiles + (char *) "," + m_ActivePrj->m_LinkLibs; - linker.SetObjFiles(linkerFiles); - linker.SetStdoutFunction(this, ideStdoutProc); + linker->SetObjFiles(linkerFiles); + linker->SetStdoutFunction(this, ideStdoutProc); if (m_ActivePrj->m_CreateLoader) { - linker.SetLoaderFilename(m_ActivePrj->m_LoaderFilename); + linker->SetLoaderFilename(m_ActivePrj->m_LoaderFilename); } // Now finally perform the link operation - linker.Link(); + linker->Link(); - errors = linker.GetErrors(); + errors = linker->GetErrors(); errorCount = errors.GetSize(); totalErrors += errorCount; for (err = 0; err < errorCount; err++) @@ -3826,7 +3826,7 @@ void VT_Ide::BuildProject(void) { // Print the message temp.Format("Success, code size=%d, data size=%d\n", - linker.TotalCodeSpace(), linker.TotalDataSpace()); + linker->TotalCodeSpace(), linker->TotalDataSpace()); m_BuildTextBuf->append((const char *) temp); // Check if we generated a MAP file and the MAP file is opened @@ -3842,7 +3842,7 @@ void VT_Ide::BuildProject(void) if (m_ActivePrj->m_UpdateHIMEM) { // Set Himem - set_memory16(gStdRomDesc->sHimem, linker.GetStartAddress()); + set_memory16(gStdRomDesc->sHimem, linker->GetStartAddress()); // May need to change some other parameters?? } @@ -3874,6 +3874,10 @@ void VT_Ide::BuildProject(void) } } } + + // Delete the linker and assembler + delete linker; + delete assembler; } void VT_Ide::CleanProject(void) diff --git a/src/idetabs.cpp b/src/idetabs.cpp index ed8ca7e..4e12427 100644 --- a/src/idetabs.cpp +++ b/src/idetabs.cpp @@ -240,7 +240,7 @@ void Fl_Ide_Tabs::draw() // Now move the selected tab such that is is at index i pSel = child(selected); - remove(selected); + remove(pSel); insert(*pSel, i); value(pSel); selected = tab_positions(p,wp); diff --git a/src/linker.cpp b/src/linker.cpp index 0098614..1b90c71 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -2420,7 +2420,7 @@ int VTLinker::ReadSectionData(FILE* fd, CObjFile* pObjFile, // Save the index of the relative segment pEq->m_Segment = eqent.st_info; pEq->m_Address = eqent.st_addr; - pEq->m_Size = eqent.st_size; + pEq->m_Size = (unsigned char) eqent.st_size; pEq->m_Line = eqent.st_line; pEq->m_Sourcefile = sourcefile; @@ -3378,11 +3378,9 @@ int VTLinker::Evaluate(class CRpnEquation* eq, double* value, int reportError, MString& errVariable, MString& filename) { double s1, s2; - CSymbol* symbol; MString errMsg, temp; double stack[200]; int stk = 0; - int int_value; const char* pStr; int c, local; VTObject* dummy; @@ -3623,7 +3621,7 @@ int VTLinker::ResolveEquations() POSITION pos; CObjFile* pObjFile; CObjFileSection* pFileSect; - int sect, sectCount, c, relCount, eqCount; + int sect, sectCount, c, eqCount; MString err, errVar, filename; double value; @@ -3860,7 +3858,7 @@ int VTLinker::GenerateOutputFile() // Allocate a 32K memory region to hold the ROM contents char * pRom = new char[32768]; - char fillchar = 0; + unsigned char fillchar = 0; if (m_LinkOptions.Find((char *) "-f") != -1) fillchar = 0xFF; From 6672a3243bb9ad9291138c42831c599b4c40fd2c Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 6 Mar 2015 01:54:49 +0000 Subject: [PATCH 277/327] Modified the assembler's macro expansion so it doesn't expand empty defines. --- src/assemble.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/assemble.cpp b/src/assemble.cpp index 732aaf8..c78e3de 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -424,6 +424,12 @@ int VTAssembler::MacroSubstitution(void) pMacro = (CMacro *) m_Defines[c]; len = pMacro->m_Name.GetLength(); + if (pMacro->m_ParamList == NULL && pMacro->m_DefList == NULL && + pMacro->m_DefString.GetLength() == 0) + { + // Skip this macro ... it is an empty define + continue; + } // Test if this macro name found in the current line if ((pStr = strstr(m_pInLine, (const char *) pMacro->m_Name)) != NULL) { From 28d4c6c232cce845322ab57325289609ba880e37 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 6 Mar 2015 02:11:08 +0000 Subject: [PATCH 278/327] Changes to fix #if defined assembly processing. --- VirtualT.suo | Bin 343552 -> 343040 bytes src/assemble.cpp | 17 ++++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/VirtualT.suo b/VirtualT.suo index 4cdf102897eae8d1f8b1df42ad816c4b10d0037e..99c38cc110c1d2000f08db61009e05c1dc35b642 100644 GIT binary patch delta 11910 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 delta 9116 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 == op.m_Variable) + { + stack[stk++] = 1.0; + break; + } + } + + if (def == m_Defines.GetSize()) + stack[stk++] = 0.0; + } + break; case RPN_NOT: From 89b63ebc5f8e2962c36f22e70de4da99fc0dcd57 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 6 Mar 2015 18:21:48 +0000 Subject: [PATCH 279/327] Updated fopen mode for back annotating listing files to us binary mode to match the assembler's open mode. If the line endings are different, then non binary causes issues with position offsets. --- VirtualT.suo | Bin 343040 -> 343040 bytes src/linker.cpp | 21 +++++++-------------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/VirtualT.suo b/VirtualT.suo index 99c38cc110c1d2000f08db61009e05c1dc35b642..ede8f3129833ad43f5f0e301bce85cc24c2b837f 100644 GIT binary patch delta 7533 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 delta 7540 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 I*X-TxpKDi+sQ>@~ diff --git a/src/linker.cpp b/src/linker.cpp index 1b90c71..f69f5c9 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -1666,15 +1666,8 @@ void VTLinker::ProcessScript(CLinkScript *pScript, int singleStep) return; pScript->m_ifStack[pScript->m_ifdepth-1].m_StartLine = pCmd->m_Line; - pScript->m_ifStack[pScript->m_ifdepth-1].m_CanExecute = pScript->m_execute; - if (value) - { - pScript->m_ifStack[pScript->m_ifdepth-1].m_Executed = TRUE; - } - else - { - pScript->m_execute = FALSE; - } + pScript->m_ifStack[pScript->m_ifdepth-1].m_Executed = value; + pScript->m_execute = value; break; } break; @@ -1777,8 +1770,8 @@ void VTLinker::ParseSubScript(char *pStr, int lineNo, CLinkScript* pScript) return; // Parse command from the rest of the line - token = strtok(pStr, " \t\n"); - arg = strtok(NULL,"\n;"); + token = strtok(pStr, " \t\n\r"); + arg = strtok(NULL,"\n\r;"); if (token == NULL) return; @@ -4407,7 +4400,7 @@ int VTLinker::BackAnnotateListingFiles(void) lstFile.NewExt(".lst"); // Try to open the listing file. If no file, just move on - if ((fd = fopen((const char *) lstFile.GetString(), "r+")) == NULL) + if ((fd = fopen((const char *) lstFile.GetString(), "rb+")) == NULL) continue; // Now loop through all ObjFileSections for this file and update the @@ -4534,7 +4527,7 @@ int VTLinker::BackAnnotateListingFiles(void) // Try to open the listing file. If no file, just move on if (pOpenFile == NULL) { - if ((fd = fopen((const char *) lstFile.GetString(), "r+")) == NULL) + if ((fd = fopen((const char *) lstFile.GetString(), "rb+")) == NULL) continue; // Mark the file as opened @@ -4587,7 +4580,7 @@ int VTLinker::BackAnnotateListingFiles(void) // Try to open the listing file. If no file, just move on if (pOpenFile == NULL) { - if ((fd = fopen((const char *) lstFile.GetString(), "r+")) == NULL) + if ((fd = fopen((const char *) lstFile.GetString(), "rb+")) == NULL) continue; // Mark the file as opened From 6fb980b752be348a2c11e2f79ea2264cd56fa649 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sun, 8 Mar 2015 15:03:38 +0000 Subject: [PATCH 280/327] Fixed issue with #elsif processing in Linker Script and removed "" from edit files on Linux when dealing with DOS line ending files. --- src/My_Text_Buffer.cpp | 6 ++++++ src/linker.cpp | 31 +++++++++++++++++++------------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/My_Text_Buffer.cpp b/src/My_Text_Buffer.cpp index 40e1d13..29f68fd 100644 --- a/src/My_Text_Buffer.cpp +++ b/src/My_Text_Buffer.cpp @@ -957,6 +957,12 @@ int My_Text_Buffer::expand_character( char c, int indent, char *outStr, int tabD return nSpaces; } + if ( c == '\r' ) + { + outStr[0] = '\0'; + return 0; + } + /* Convert control codes to readable character sequences */ /*... is this safe with international character sets? */ if ( ( ( unsigned char ) c ) <= 31 ) { diff --git a/src/linker.cpp b/src/linker.cpp index f69f5c9..55e9e67 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -1656,19 +1656,26 @@ void VTLinker::ProcessScript(CLinkScript *pScript, int singleStep) } // Check if we can execute at this level - if (pScript->m_ifStack[pScript->m_ifdepth-1].m_CanExecute && !pScript->m_ifStack[pScript->m_ifdepth-1].m_Executed) + if (pScript->m_ifStack[pScript->m_ifdepth-1].m_CanExecute) { - // We haven't executed yet. Evaluate and test if we should execute - // Evaluate the if condition - value = EvaluateStringEquation((const char *) pCmd->m_CmdArg, - pCmd->m_Line); - if (m_Errors.GetSize() > 0) - return; - - pScript->m_ifStack[pScript->m_ifdepth-1].m_StartLine = pCmd->m_Line; - pScript->m_ifStack[pScript->m_ifdepth-1].m_Executed = value; - pScript->m_execute = value; - break; + if (!pScript->m_ifStack[pScript->m_ifdepth-1].m_Executed) + { + // We haven't executed yet. Evaluate and test if we should execute + // Evaluate the if condition + value = EvaluateStringEquation((const char *) pCmd->m_CmdArg, + pCmd->m_Line); + if (m_Errors.GetSize() > 0) + return; + + pScript->m_ifStack[pScript->m_ifdepth-1].m_StartLine = pCmd->m_Line; + pScript->m_ifStack[pScript->m_ifdepth-1].m_Executed = value; + pScript->m_execute = value; + break; + } + else + { + pScript->m_execute = FALSE; + } } break; From 0ac49cf612edb5ddcfd7453d4a1be15d7e96f8b1 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Thu, 12 Mar 2015 18:49:21 +0000 Subject: [PATCH 281/327] Modified assembler parser syntax to properly handle '$' curent PC in equations. Added toolbar icons. --- VirtualT.suo | Bin 343040 -> 352256 bytes src/FLU/flu_pixmaps.h | 22 + src/a85parse.cpp | 9094 ++++++++++++++++++++--------------------- src/a85parse.h | 30 +- src/a85parse.syn | 9 +- src/assemble.cpp | 35 +- src/assemble.h | 3 +- src/disassemble.cpp | 2 + src/flu_pixmaps.cpp | 1635 ++++++++ src/ide.cpp | 294 +- src/ide.h | 49 + src/linker.cpp | 12 +- src/multieditwin.cpp | 17 + src/multieditwin.h | 1 + 14 files changed, 6576 insertions(+), 4627 deletions(-) diff --git a/VirtualT.suo b/VirtualT.suo index ede8f3129833ad43f5f0e301bce85cc24c2b837f..7073294b2a8c7411bdd97e3fe3ff10e07815e150 100644 GIT binary patch delta 30979 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
    es7E4 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 cvR~-Qk-kyN86B7MABVV!Z diff --git a/src/FLU/flu_pixmaps.h b/src/FLU/flu_pixmaps.h index ad15fbe..9b97788 100644 --- a/src/FLU/flu_pixmaps.h +++ b/src/FLU/flu_pixmaps.h @@ -51,4 +51,26 @@ FLU_EXPORT extern const char* trash_xpm[]; FLU_EXPORT extern const char* home_xpm[]; FLU_EXPORT extern const char* reload_xpm[]; +FLU_EXPORT extern const char* arrow_execute_xpm[]; + +FLU_EXPORT extern const char* edit_undo_xpm[]; +FLU_EXPORT extern const char* edit_paste_xpm[]; +FLU_EXPORT extern const char* edit_find_xpm[]; +FLU_EXPORT extern const char* edit_cut_xpm[]; +FLU_EXPORT extern const char* edit_copy_xpm[]; +FLU_EXPORT extern const char* check_xpm[]; +FLU_EXPORT extern const char* document_open_xpm[]; +FLU_EXPORT extern const char* document_save_xpm[]; +FLU_EXPORT extern const char* document_new_xpm[]; +FLU_EXPORT extern const char* toolbar_handle_xpm[]; +FLU_EXPORT extern const char* configure_xpm[]; +FLU_EXPORT extern const char* wizard_xpm[]; +FLU_EXPORT extern const char* printer_xpm[]; +FLU_EXPORT extern const char* log_viewer_xpm[]; +FLU_EXPORT extern const char* brick_add_xpm[]; +FLU_EXPORT extern const char* computer_xpm[]; +FLU_EXPORT extern const char* chip_xpm[]; +FLU_EXPORT extern const char* dollar_xpm[]; +FLU_EXPORT extern const char* checkmark_xpm[]; + #endif diff --git a/src/a85parse.cpp b/src/a85parse.cpp index 6b25138..8f20c25 100644 --- a/src/a85parse.cpp +++ b/src/a85parse.cpp @@ -17,11 +17,11 @@ */ -#ifndef A85PARSE_H_1359819567 +#ifndef A85PARSE_H_1425877737 #include "a85parse.h" #endif -#ifndef A85PARSE_H_1359819567 +#ifndef A85PARSE_H_1425877737 #error Mismatched header file #endif @@ -39,7 +39,7 @@ a85parse_pcb_type a85parse_pcb; #define PCB a85parse_pcb -/* Line 706, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 707, C:/Projects/VirtualT/src/a85parse.syn */ // Embedded C #include "MString.h" // Include MString header @@ -675,180 +675,175 @@ static void ag_rp_36(void) { #define ag_rp_84() (gNameList->Add(ss[ss_idx--])) static void ag_rp_85(void) { -/* Line 253, C:/Projects/VirtualT/src/a85parse.syn */ - strcpy(ss[++ss_idx], "$"); ss_len = 1; -} - -static void ag_rp_86(void) { /* Line 254, C:/Projects/VirtualT/src/a85parse.syn */ strcpy(ss[++ss_idx], "&"); ss_len = 1; } -static void ag_rp_87(int c) { +static void ag_rp_86(int c) { /* Line 257, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; \ if (PCB.column == 2) ss_addr = gAsm->m_ActiveSeg->m_Address; } -static void ag_rp_88(int c) { +static void ag_rp_87(int c) { /* Line 259, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_89(int c) { +static void ag_rp_88(int c) { /* Line 260, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_90(int c) { +static void ag_rp_89(int c) { /* Line 263, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = c; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_91(int c) { +static void ag_rp_90(int c) { /* Line 264, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_92(int ch1, int ch2) { +static void ag_rp_91(int ch1, int ch2) { /* Line 270, C:/Projects/VirtualT/src/a85parse.syn */ ss_idx++; ss_len = 2; sprintf(ss[ss_idx], "%c%c", ch1, ch2); } -static void ag_rp_93(int c) { +static void ag_rp_92(int c) { /* Line 271, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_94(void) { +static void ag_rp_93(void) { /* Line 278, C:/Projects/VirtualT/src/a85parse.syn */ ss_idx++; ss_len = 0; } -static void ag_rp_95(int c) { +static void ag_rp_94(int c) { /* Line 279, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -#define ag_rp_96(n) (n) +#define ag_rp_95(n) (n) -#define ag_rp_97() ('\\') +#define ag_rp_96() ('\\') -#define ag_rp_98() ('\n') +#define ag_rp_97() ('\n') -#define ag_rp_99() ('\t') +#define ag_rp_98() ('\t') -#define ag_rp_100() ('\r') +#define ag_rp_99() ('\r') -#define ag_rp_101() ('\0') +#define ag_rp_100() ('\0') -#define ag_rp_102() ('"') +#define ag_rp_101() ('"') -#define ag_rp_103() (0x08) +#define ag_rp_102() (0x08) -#define ag_rp_104() (0x0C) +#define ag_rp_103() (0x0C) -#define ag_rp_105(n1, n2, n3) ((n1-'0') * 64 + (n2-'0') * 8 + n3-'0') +#define ag_rp_104(n1, n2, n3) ((n1-'0') * 64 + (n2-'0') * 8 + n3-'0') -#define ag_rp_106(n1, n2) (chtoh(n1) * 16 + chtoh(n2)) +#define ag_rp_105(n1, n2) (chtoh(n1) * 16 + chtoh(n2)) -#define ag_rp_107(n1) (chtoh(n1)) +#define ag_rp_106(n1) (chtoh(n1)) -static void ag_rp_108(void) { +static void ag_rp_107(void) { /* Line 299, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '>'; ss[ss_idx][ss_len] = 0; } -static void ag_rp_109(void) { +static void ag_rp_108(void) { /* Line 302, C:/Projects/VirtualT/src/a85parse.syn */ ss[++ss_idx][0] = '<'; ss[ss_idx][1] = 0; ss_len = 1; } -static void ag_rp_110(int c) { +static void ag_rp_109(int c) { /* Line 303, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } -static void ag_rp_111(int c) { +static void ag_rp_110(int c) { /* Line 304, C:/Projects/VirtualT/src/a85parse.syn */ ss[ss_idx][ss_len++] = '\\'; ss[ss_idx][ss_len++] = c; ss[ss_idx][ss_len] = 0; } +#define ag_rp_111() (gAsm->label(ss[ss_idx--])) + #define ag_rp_112() (gAsm->label(ss[ss_idx--])) -#define ag_rp_113() (gAsm->label(ss[ss_idx--])) +#define ag_rp_113() (gAsm->label(".bss")) -#define ag_rp_114() (gAsm->label(".bss")) +#define ag_rp_114() (gAsm->label(".text")) -#define ag_rp_115() (gAsm->label(".text")) +#define ag_rp_115() (gAsm->label(".data")) -#define ag_rp_116() (gAsm->label(".data")) +#define ag_rp_116() (PAGE) -#define ag_rp_117() (PAGE) +#define ag_rp_117() (INPAGE) -#define ag_rp_118() (INPAGE) +#define ag_rp_118() (condition(-1)) -#define ag_rp_119() (condition(-1)) +#define ag_rp_119() (condition(COND_NOCMP)) -#define ag_rp_120() (condition(COND_NOCMP)) +#define ag_rp_120() (condition(COND_EQ)) -#define ag_rp_121() (condition(COND_EQ)) +#define ag_rp_121() (condition(COND_NE)) -#define ag_rp_122() (condition(COND_NE)) +#define ag_rp_122() (condition(COND_GE)) -#define ag_rp_123() (condition(COND_GE)) +#define ag_rp_123() (condition(COND_LE)) -#define ag_rp_124() (condition(COND_LE)) +#define ag_rp_124() (condition(COND_GT)) -#define ag_rp_125() (condition(COND_GT)) +#define ag_rp_125() (condition(COND_LT)) -#define ag_rp_126() (condition(COND_LT)) +#define ag_rp_126() (gEq->Add(RPN_BITOR)) #define ag_rp_127() (gEq->Add(RPN_BITOR)) -#define ag_rp_128() (gEq->Add(RPN_BITOR)) +#define ag_rp_128() (gEq->Add(RPN_BITXOR)) #define ag_rp_129() (gEq->Add(RPN_BITXOR)) -#define ag_rp_130() (gEq->Add(RPN_BITXOR)) +#define ag_rp_130() (gEq->Add(RPN_BITAND)) #define ag_rp_131() (gEq->Add(RPN_BITAND)) -#define ag_rp_132() (gEq->Add(RPN_BITAND)) +#define ag_rp_132() (gEq->Add(RPN_LEFTSHIFT)) #define ag_rp_133() (gEq->Add(RPN_LEFTSHIFT)) -#define ag_rp_134() (gEq->Add(RPN_LEFTSHIFT)) +#define ag_rp_134() (gEq->Add(RPN_RIGHTSHIFT)) #define ag_rp_135() (gEq->Add(RPN_RIGHTSHIFT)) -#define ag_rp_136() (gEq->Add(RPN_RIGHTSHIFT)) +#define ag_rp_136() (gEq->Add(RPN_ADD)) -#define ag_rp_137() (gEq->Add(RPN_ADD)) +#define ag_rp_137() (gEq->Add(RPN_SUBTRACT)) -#define ag_rp_138() (gEq->Add(RPN_SUBTRACT)) +#define ag_rp_138() (gEq->Add(RPN_MULTIPLY)) -#define ag_rp_139() (gEq->Add(RPN_MULTIPLY)) +#define ag_rp_139() (gEq->Add(RPN_DIVIDE)) -#define ag_rp_140() (gEq->Add(RPN_DIVIDE)) +#define ag_rp_140() (gEq->Add(RPN_MODULUS)) #define ag_rp_141() (gEq->Add(RPN_MODULUS)) -#define ag_rp_142() (gEq->Add(RPN_MODULUS)) +#define ag_rp_142() (gEq->Add(RPN_EXPONENT)) -#define ag_rp_143() (gEq->Add(RPN_EXPONENT)) +#define ag_rp_143() (gEq->Add(RPN_NOT)) #define ag_rp_144() (gEq->Add(RPN_NOT)) -#define ag_rp_145() (gEq->Add(RPN_NOT)) +#define ag_rp_145() (gEq->Add(RPN_BITNOT)) -#define ag_rp_146() (gEq->Add(RPN_BITNOT)) +#define ag_rp_146() (gEq->Add(RPN_NEGATE)) -#define ag_rp_147() (gEq->Add(RPN_NEGATE)) +#define ag_rp_147(n) (gEq->Add((double) n)) -#define ag_rp_148(n) (gEq->Add((double) n)) - -static void ag_rp_149(void) { +static void ag_rp_148(void) { /* Line 395, C:/Projects/VirtualT/src/a85parse.syn */ delete gMacro; gMacro = gMacroStack[ms_idx-1]; \ gMacroStack[ms_idx--] = 0; if (gMacro->m_ParamList == 0) \ @@ -859,6 +854,8 @@ static void ag_rp_149(void) { } } +#define ag_rp_149() (gEq->Add("$")) + #define ag_rp_150() (gEq->Add(RPN_FLOOR)) #define ag_rp_151() (gEq->Add(RPN_CEIL)) @@ -906,67 +903,67 @@ static void ag_rp_149(void) { #define ag_rp_172() (conv_to_dec()) static void ag_rp_173(int n) { -/* Line 442, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 443, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } static void ag_rp_174(int n) { -/* Line 443, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 444, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 2; integer[0] = '-', integer[1] = n; integer[2] = 0; } static void ag_rp_175(int n) { -/* Line 444, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 445, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } static void ag_rp_176(int n) { -/* Line 445, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 446, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } static void ag_rp_177(int n) { -/* Line 450, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 451, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } static void ag_rp_178(int n) { -/* Line 451, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 452, C:/Projects/VirtualT/src/a85parse.syn */ int_len = 1; integer[0] = n; integer[1] = 0; } static void ag_rp_179(int n) { -/* Line 452, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 453, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } static void ag_rp_180(int n) { -/* Line 455, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 456, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } static void ag_rp_181(int n) { -/* Line 456, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 457, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } static void ag_rp_182(int n) { -/* Line 459, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 460, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } static void ag_rp_183(int n) { -/* Line 460, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 461, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } static void ag_rp_184(int n) { -/* Line 463, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 464, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } static void ag_rp_185(int n) { -/* Line 464, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 465, C:/Projects/VirtualT/src/a85parse.syn */ integer[int_len++] = n; integer[int_len] = 0; } @@ -993,17 +990,17 @@ static void ag_rp_185(int n) { #define ag_rp_196() ('\'') static double ag_rp_197(void) { -/* Line 485, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 486, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor = 1.0; return (double) conv_to_dec(); } static double ag_rp_198(int d) { -/* Line 486, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 487, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor = 10.0; return ((double) (d - '0') / gDivisor); } static double ag_rp_199(double r, int d) { -/* Line 487, C:/Projects/VirtualT/src/a85parse.syn */ +/* Line 488, C:/Projects/VirtualT/src/a85parse.syn */ gDivisor *= 10.0; return (r + (double) (d - '0') / gDivisor); } @@ -1323,26 +1320,26 @@ static const unsigned short ag_rpx[] = { 0, 37, 0, 38, 39, 40, 41, 42, 0, 0, 0, 43, 44, 0, 0, 45, 0, 0, 0, 46, 0, 0, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 0, 0, 85, 86, 87, 88, 89, 90, 91, 0, 92, - 93, 0, 94, 95, 0, 96, 97, 98, 99,100,101,102,103,104,105, 0, 0,106, - 107,108,109,110,111, 0,112,113,114,115,116,117,118,119,120, 0, 0, 0, - 121, 0, 0,122, 0, 0,123, 0, 0,124, 0, 0,125, 0, 0,126, 0, 0, - 127,128, 0,129,130, 0,131,132, 0,133,134,135,136, 0,137,138, 0,139, - 140,141,142,143, 0,144,145,146,147,148,149, 0, 0,150,151,152,153,154, + 78, 79, 80, 81, 82, 83, 84, 0, 0, 85, 86, 87, 88, 89, 90, 0, 91, 92, + 0, 93, 94, 0, 95, 96, 97, 98, 99,100,101,102,103,104, 0, 0,105,106, + 107,108,109,110, 0,111,112,113,114,115,116,117,118,119, 0, 0, 0,120, + 0, 0,121, 0, 0,122, 0, 0,123, 0, 0,124, 0, 0,125, 0, 0,126, + 127, 0,128,129, 0,130,131, 0,132,133,134,135, 0,136,137, 0,138,139, + 140,141,142, 0,143,144,145,146,147,148,149, 0, 0,150,151,152,153,154, 155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170, 0, 0, - 171,172,173,174,175,176, 0, 0,177,178,179,180,181,182,183,184,185,186, - 187,188,189,190,191,192,193,194,195,196, 0,197,198,199,200,201,202,203, - 204,205, 0, 0,206,207, 0, 0,208, 0, 0,209, 0, 0,210,211,212,213, - 214,215,216,217,218,219,220,221,222,223,224, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,225,226,227,228,229, 0, 0,230,231, - 232, 0, 0, 0,233,234,235,236,237,238,239,240,241, 0, 0,242,243,244, - 245,246,247,248,249,250,251, 0, 0, 0,252,253,254,255,256,257,258,259, - 260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277, - 278,279,280, 0,281, 0,282, 0,283,284,285,286,287,288,289,290,291,292, - 293,294,295,296,297,298,299, 0, 0, 0, 0, 0,300,301,302,303, 0, 0, - 0, 0, 0,304,305,306,307,308,309,310, 0, 0, 0,311, 0, 0, 0,312, - 313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330, - 331,332,333,334,335,336 + 171,172,173,174,175,176, 0,177,178,179,180,181,182,183,184,185,186,187, + 188,189,190,191,192,193,194,195,196, 0,197,198,199,200,201,202,203,204, + 205, 0, 0,206,207, 0, 0,208, 0, 0,209, 0, 0,210,211,212,213,214, + 215,216,217,218,219,220,221,222,223,224, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,225,226,227,228,229, 0, 0,230,231,232, + 0, 0, 0,233,234,235,236,237,238,239,240,241, 0, 0,242,243,244,245, + 246,247,248,249,250,251, 0, 0, 0,252,253,254,255,256,257,258,259,260, + 261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278, + 279,280, 0,281, 0,282, 0,283,284,285,286,287,288,289,290,291,292,293, + 294,295,296,297,298,299, 0, 0, 0, 0, 0,300,301,302,303, 0, 0, 0, + 0, 0,304,305,306,307,308,309,310, 0, 0, 0,311, 0, 0, 0,312,313, + 314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331, + 332,333,334,335,336 }; static const unsigned char ag_key_itt[] = { @@ -1361,602 +1358,605 @@ static const unsigned char ag_key_itt[] = { }; static const unsigned short ag_key_pt[] = { - 1,430, 1,431, 1,433, 1,434, 1,440, 1,439, 1,441, 1,443, - 1,444, 1,445, 1,446, 1,447, 1,448, 1,449, 1,450, 1,451, - 1,452, 1,453, 1,454, 1,456, 1,457, 1,458, 1,462, 1,463, - 1,464, 1,467, 1,468, 1,469, 1,470, 1,471, 1,472, 1,473, - 1,474, 1,475, 1,476, 1,477, 1,478, 1,479, 1,480, 1,481, - 1,482, 1,483, 1,484, 1,486, 1,487, 1,488, 1,489, 1,490, - 1,491, 1,134, 1,494, 1,495, 1,497, 1,499, 1,501, 1,503, - 1,505, 1,508, 1,510, 1,512, 1,514, 1,516, 1,522, 1,525, - 1,527, 1,528, 1,529, 1,530, 1,531, 1,532, 1,533, 1,534, - 1,535, 1,537, 1,221, 1,222, 1,234, 1,235, 1,236, 1,237, - 1,238, 1,239, 1,240, 1,540, 1,668, 1,246, 1,248, 1,543, - 1,539, 1,541, 1,542, 1,544, 1,545, 1,546, 1,547, 1,548, - 1,549, 1,550, 1,551, 1,552, 1,553, 1,554, 1,555, 1,556, - 1,557, 1,558, 1,559, 1,560, 1,561, 1,562, 1,563, 1,564, - 1,565, 1,566, 1,567, 1,568, 1,569, 1,570, 1,571, 1,572, - 1,573, 1,574, 1,575, 1,576, 1,577, 1,578, 1,579, 1,580, - 1,581, 1,582, 1,583, 1,584, 1,585, 1,586, 1,587, 1,588, - 1,589, 1,590, 1,591, 1,592, 1,593, 1,595, 1,596, 1,597, - 1,598, 1,599, 1,600, 1,601, 1,602, 1,603, 1,604, 1,605, - 1,606, 1,607, 1,609, 1,610, 1,611, 1,612, 1,613, 1,614, - 1,615, 1,616, 1,617, 1,618, 1,619, 1,620, 1,621, 1,622, - 1,623, 1,624, 1,625, 1,626, 1,627, 1,628, 1,629, 1,630, - 1,631, 1,632, 1,633, 1,634, 1,635, 1,636, 1,637, 1,638, - 1,639, 1,640, 1,641, 1,642, 1,643, 1,644, 1,645, 1,646, - 1,647, 1,648, 1,649, 1,650, 1,651, 1,652, 1,653, 1,654, - 1,655, 1,656, 1,657, 1,658, 1,659, 1,660, 1,661, 1,662, - 1,663, 1,664, 1,665, 1,666, 1,667, 1,669, 1,670, 1,671, - 1,672, 1,673, 1,674, 1,675, 1,676, 1,677, 1,678, 1,679, -0 + 1,429, 1,430, 1,432, 1,433, 1,439, 1,438, 1,440, 1,442, + 1,443, 1,444, 1,445, 1,446, 1,447, 1,448, 1,449, 1,450, + 1,451, 1,452, 1,453, 1,455, 1,456, 1,457, 1,461, 1,462, + 1,463, 1,466, 1,467, 1,468, 1,469, 1,470, 1,471, 1,472, + 1,473, 1,474, 1,475, 1,476, 1,477, 1,478, 1,479, 1,480, + 1,481, 1,482, 1,483, 1,485, 1,486, 1,487, 1,488, 1,489, + 1,490, 1,493, 1,494, 1,496, 1,498, 1,500, 1,502, 1,504, + 1,507, 1,509, 1,511, 1,513, 1,515, 1,521, 1,524, 1,527, + 1,528, 1,529, 1,530, 1,531, 1,532, 1,533, 1,534, 1,535, + 1,537, 1,220, 1,221, 1,233, 1,234, 1,235, 1,236, 1,237, + 1,238, 1,239, 1,540, 1,668, 1,245, 1,247, 1,543, 1,539, + 1,541, 1,542, 1,544, 1,545, 1,546, 1,547, 1,548, 1,549, + 1,550, 1,551, 1,552, 1,553, 1,554, 1,555, 1,556, 1,557, + 1,558, 1,559, 1,560, 1,561, 1,562, 1,563, 1,564, 1,565, + 1,566, 1,567, 1,568, 1,569, 1,570, 1,571, 1,572, 1,573, + 1,574, 1,575, 1,576, 1,577, 1,578, 1,579, 1,580, 1,581, + 1,582, 1,583, 1,584, 1,585, 1,586, 1,587, 1,588, 1,589, + 1,590, 1,591, 1,592, 1,593, 1,595, 1,596, 1,597, 1,598, + 1,599, 1,600, 1,601, 1,602, 1,603, 1,604, 1,605, 1,606, + 1,607, 1,609, 1,610, 1,611, 1,612, 1,613, 1,614, 1,615, + 1,616, 1,617, 1,618, 1,619, 1,620, 1,621, 1,622, 1,623, + 1,624, 1,625, 1,626, 1,627, 1,628, 1,629, 1,630, 1,631, + 1,632, 1,633, 1,634, 1,635, 1,636, 1,637, 1,638, 1,639, + 1,640, 1,641, 1,642, 1,643, 1,644, 1,645, 1,646, 1,647, + 1,648, 1,649, 1,650, 1,651, 1,652, 1,653, 1,654, 1,655, + 1,656, 1,657, 1,658, 1,659, 1,660, 1,661, 1,662, 1,663, + 1,664, 1,665, 1,666, 1,667, 1,669, 1,670, 1,671, 1,672, + 1,673, 1,674, 1,675, 1,676, 1,677, 1,678, 1,679,0 }; static const unsigned char ag_key_ch[] = { - 0, 66, 68, 84,255, 42, 47,255, 85,255, 76,255, 67,255, 78,255, 35, 36, - 38, 46, 47, 73,255, 61,255, 61,255, 42, 47, 61,255, 66, 68, 84,255, 42, - 47,255, 60, 61,255, 61,255, 61, 62,255, 67, 68, 73,255, 65, 68, 73,255, + 0, 66, 68, 84,255, 42, 47,255, 85,255, 76,255, 67,255, 78,255, 35, 38, + 46, 47, 73,255, 61,255, 42, 47, 61,255, 66, 68, 84,255, 42, 47,255, 60, + 61,255, 61,255, 61, 62,255, 67, 68, 73,255, 65, 68, 73,255, 69, 72,255, + 67, 68, 78, 82, 83,255, 67, 90,255, 69,255, 65,255, 67, 76, 77, 78, 80, + 82, 89, 90,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 69, + 77, 78, 80, 83, 90,255, 65, 68,255, 82, 88,255, 68,255, 69,255, 78,255, + 73,255, 70, 72, 83,255, 69, 85,255, 65, 66, 67, 69, 73, 83, 87, 88,255, + 73, 83,255, 73,255, 68, 84,255, 85,255, 78, 82,255, 69, 82,255, 84,255, + 67, 73, 76, 78, 81, 82, 88,255, 73, 76, 80,255, 69, 84,255, 77, 84,255, + 69, 73, 76,255, 68, 78,255, 85,255, 76,255, 67, 80, 82, 88,255, 70, 78, + 80,255, 80,255, 53,255, 67, 68, 75, 88, 90,255, 69, 79,255, 77, 80,255, + 53,255, 67, 68, 75, 77, 78, 80, 84, 88, 90,255, 88,255, 72, 83,255, 65, + 69, 72, 83,255, 69,255, 68, 73, 88,255, 76,255, 78, 83,255, 71, 87,255, + 79, 85,255, 67, 68, 69, 72, 73, 74, 78, 79, 80, 82, 83, 84, 88,255, 85, + 255, 68, 86,255, 65, 79, 83, 86,255, 65,255, 80, 84,255, 65, 69, 79,255, + 65, 71, 73,255, 82, 85,255, 72,255, 70,255, 84,255, 78,255, 65, 73,255, + 66, 83,255, 65, 67, 79, 82, 83, 85,255, 76, 82,255, 65,255, 67, 68,255, + 67, 90,255, 69, 71, 79,255, 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, + 73, 76, 77, 78, 80, 82, 83, 90,255, 67, 90,255, 66, 67, 73, 78, 90,255, + 69,255, 68, 73, 82, 88,255, 76, 82,255, 71, 72, 73,255, 88,255, 65, 67, + 75,255, 66, 73,255, 66, 69, 72, 73, 80, 81, 84, 85, 89,255, 69, 73,255, + 65, 73,255, 67, 79, 82, 84,255, 33, 35, 36, 38, 39, 40, 42, 44, 46, 47, + 60, 61, 62, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, + 82, 83, 84, 85, 86, 87, 88, 92,255, 66, 68, 84,255, 42, 47,255, 35, 38, + 46, 47,255, 73, 83,255, 67, 76, 78, 82,255, 68, 78,255, 70, 78,255, 70, + 255, 84,255, 78,255, 65, 73,255, 82,255, 68, 69, 73, 80, 85,255, 42, 47, + 255, 36, 38, 42, 47, 58, 61,255, 42, 47,255, 67, 68, 73,255, 65, 73,255, 69, 72,255, 67, 68, 78, 82, 83,255, 67, 90,255, 69,255, 65,255, 67, 76, 77, 78, 80, 82, 89, 90,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, - 65, 67, 69, 77, 78, 80, 83, 90,255, 65, 68,255, 82, 88,255, 68,255, 69, - 255, 78,255, 73,255, 70, 72, 83,255, 69, 85,255, 65, 66, 67, 69, 73, 83, - 87, 88,255, 73, 83,255, 73,255, 68, 84,255, 85,255, 78, 82,255, 69, 82, - 255, 84,255, 67, 73, 76, 78, 81, 82, 88,255, 73, 76, 80,255, 69, 84,255, - 77, 84,255, 69, 73, 76,255, 68, 78,255, 85,255, 76,255, 67, 80, 82, 88, - 255, 70, 78, 80,255, 80,255, 53,255, 67, 68, 75, 88, 90,255, 69, 79,255, - 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, 88, 90,255, 88,255, 72, - 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, 88,255, 76,255, 78, 83,255, - 71, 87,255, 79, 85,255, 67, 68, 69, 72, 73, 74, 78, 79, 80, 82, 83, 84, - 88,255, 85,255, 68, 86,255, 65, 79, 83, 86,255, 65,255, 80, 84,255, 65, - 69, 79,255, 65, 71, 73,255, 82, 85,255, 72,255, 70,255, 84,255, 78,255, - 65, 73,255, 66, 83,255, 65, 67, 79, 82, 83, 85,255, 76, 82,255, 65,255, - 67, 68,255, 67, 90,255, 69, 71, 79,255, 67, 72,255, 86,255, 84,255, 65, - 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 67, 90,255, 66, 67, 73, - 78, 90,255, 69,255, 68, 73, 82, 88,255, 76, 82,255, 71, 72, 73,255, 88, - 255, 65, 67, 75,255, 66, 73,255, 66, 69, 72, 73, 80, 81, 84, 85, 89,255, - 69, 73,255, 65, 73,255, 67, 79, 82, 84,255, 33, 35, 36, 38, 39, 40, 42, - 44, 46, 47, 60, 61, 62, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, - 78, 79, 80, 82, 83, 84, 85, 86, 87, 88, 92,255, 66, 68, 84,255, 42, 47, - 255, 35, 36, 38, 46, 47,255, 73, 83,255, 67, 76, 78, 82,255, 68, 78,255, - 70, 78,255, 70,255, 84,255, 78,255, 65, 73,255, 82,255, 68, 69, 73, 80, - 85,255, 42, 47,255, 38, 42, 47, 58, 61,255, 61,255, 42, 47,255, 67, 68, - 73,255, 65, 73,255, 69, 72,255, 67, 68, 78, 82, 83,255, 67, 90,255, 69, - 255, 65,255, 67, 76, 77, 78, 80, 82, 89, 90,255, 65, 67, 80,255, 67, 90, - 255, 69, 73, 79,255, 65, 67, 77, 78, 80, 83, 90,255, 65, 68,255, 82, 88, - 255, 72, 83,255, 69, 85,255, 65, 66, 67, 69, 73, 83, 87,255, 73,255, 68, - 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 73, 76, 78, 81, 88,255, 77, - 84,255, 69, 76,255, 82, 88,255, 70, 78,255, 80,255, 53,255, 67, 68, 75, - 88, 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, - 88, 90,255, 88,255, 72, 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, 88, - 255, 76,255, 78, 83,255, 79, 85,255, 67, 68, 72, 73, 74, 80, 82, 83, 88, - 255, 68, 86,255, 65, 79, 83, 86,255, 65,255, 80,255, 65, 79,255, 65, 71, - 73,255, 82, 85,255, 70,255, 84,255, 78,255, 73,255, 66, 83,255, 65, 67, - 79, 82, 85,255, 76, 82,255, 65,255, 67, 68,255, 67, 90,255, 69, 71, 79, - 255, 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, - 83, 90,255, 67, 90,255, 66, 67, 73, 78, 90,255, 69,255, 68, 73, 82, 88, - 255, 76,255, 71, 72, 73,255, 88,255, 65, 67, 75,255, 66, 73,255, 66, 69, - 72, 73, 80, 84, 85, 89,255, 69, 73,255, 65, 73,255, 67, 82, 84,255, 36, - 38, 42, 47, 61, 65, 66, 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 80, - 82, 83, 84, 86, 87, 88,255, 42, 47,255, 85,255, 76,255, 67,255, 78,255, - 47, 73,255, 61,255, 42, 47,255, 67, 68, 73,255, 65, 73,255, 69, 72,255, - 67, 68, 78, 82, 83,255, 67, 90,255, 69,255, 65,255, 67, 76, 77, 78, 80, - 82, 89, 90,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, - 78, 80, 83, 90,255, 65, 68,255, 82, 88,255, 72, 83,255, 69, 85,255, 65, - 66, 67, 69, 73, 83, 87,255, 73,255, 68, 84,255, 78, 82,255, 69, 82,255, - 84,255, 67, 73, 76, 78, 88,255, 77, 84,255, 69, 76,255, 85,255, 76,255, - 67, 82, 88,255, 70, 78,255, 80,255, 53,255, 67, 68, 75, 88, 90,255, 69, - 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, 88, 90,255, 88, - 255, 72, 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, 88,255, 76,255, 78, - 83,255, 79, 85,255, 67, 68, 72, 73, 74, 80, 82, 83, 88,255, 68, 86,255, - 65, 79, 83, 86,255, 65,255, 80,255, 65, 79,255, 65, 71, 73,255, 82, 85, - 255, 70,255, 84,255, 78,255, 73,255, 66, 83,255, 65, 67, 79, 82, 85,255, - 76, 82,255, 65,255, 67, 68,255, 67, 90,255, 69, 71, 79,255, 67, 72,255, - 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 67, - 90,255, 66, 67, 73, 78, 90,255, 69,255, 68, 73, 82, 88,255, 76,255, 71, - 72, 73,255, 88,255, 65, 67, 75,255, 66, 73,255, 66, 72, 73, 80, 84, 85, - 89,255, 69, 73,255, 65, 73,255, 67, 82, 84,255, 36, 38, 42, 47, 65, 66, - 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, 86, 87, 88, - 255, 36, 38,255, 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, 67, 68, - 70, 72, 73, 76, 78, 80, 83,255, 42, 47,255, 47,255, 78, 88,255, 69, 72, - 76, 86,255, 66, 68, 84,255, 42, 47,255, 85,255, 76,255, 67,255, 78,255, - 35, 36, 38, 42, 46, 47, 73,255, 47, 61,255, 42, 47,255, 76, 89,255, 69, - 255, 66, 83, 87,255, 68, 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 78, - 81, 88,255, 85,255, 76,255, 67,255, 78,255, 78, 83,255, 73, 83,255, 65, - 79, 83,255, 65, 79,255, 70,255, 84,255, 78,255, 73,255, 65, 82, 85,255, - 69, 84, 89,255, 69, 73,255, 36, 42, 47, 65, 66, 67, 68, 69, 70, 72, 73, - 76, 77, 78, 79, 80, 83, 84, 86, 87, 92,255, 85,255, 76,255, 67,255, 78, - 255, 73,255, 42, 47,255, 42, 47,255, 42, 47, 92,255, 42, 47,255, 47, 73, - 80,255, 42, 47,255, 33, 47,255, 67,255, 69, 88,255, 76,255, 66, 68, 72, - 80, 83,255, 40, 65, 66, 67, 68, 69, 72, 76, 77,255, 67,255, 69,255, 76, - 255, 66, 68, 72, 83,255, 67,255, 69,255, 76,255, 65, 66, 68, 72, 80,255, - 67,255, 69,255, 66, 68,255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, - 62,255, 33, 42, 44, 47, 60, 61, 62,255, 61,255, 42, 47,255, 60, 61,255, - 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 42, - 44, 47, 60, 61, 62, 65, 69, 71, 76, 77, 78, 79, 83, 88,255, 76, 89,255, - 69,255, 66, 83, 87,255, 68, 84,255, 78, 82,255, 69, 82,255, 84,255, 67, - 78, 88,255, 78, 83,255, 73, 83,255, 65, 79, 83,255, 65, 79,255, 70,255, - 84,255, 78,255, 73,255, 65, 82, 85,255, 84, 89,255, 69, 73,255, 36, 42, - 65, 66, 67, 68, 69, 70, 72, 76, 77, 78, 79, 80, 83, 84, 86, 87,255, 42, - 47,255, 44, 47,255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, - 69, 84,255, 69, 84,255, 82,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, - 61, 62, 65, 69, 71, 76, 77, 78, 79, 81, 83, 88,255, 39,255, 61,255, 42, - 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 82,255, - 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 71, 76, 77, 78, 79, 81, - 83, 88,255, 42, 47,255, 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, - 42, 47, 67, 68, 70, 72, 73, 76, 78, 80, 83, 92,255, 76, 80,255, 71, 87, - 255, 78, 79,255, 36, 38, 39, 67, 68, 70, 72, 73, 76, 80, 83,255, 42, 47, - 255, 76, 80,255, 71, 87,255, 78, 79,255, 36, 38, 39, 42, 47, 67, 68, 70, - 72, 73, 76, 80, 83, 92,255, 61,255, 60, 61,255, 61,255, 61, 62,255, 69, - 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 42, 44, 60, 61, 62, 65, 69, - 71, 76, 77, 78, 79, 83, 88,255, 61,255, 42, 47,255, 60, 61,255, 61,255, - 61, 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, 33, 44, 47, 60, - 61, 62, 65, 69, 71, 76, 78, 79, 83, 88,255, 61,255, 42, 47,255, 61,255, - 61,255, 61,255, 69, 84,255, 69, 84,255, 33, 44, 47, 60, 61, 62, 65, 69, - 71, 76, 78, 79, 88,255, 61,255, 42, 47,255, 61,255, 61,255, 61,255, 69, - 84,255, 69, 84,255, 33, 44, 47, 60, 61, 62, 69, 71, 76, 78, 79, 88,255, - 61,255, 42, 47,255, 61,255, 61,255, 61,255, 69, 84,255, 69, 84,255, 33, - 44, 47, 60, 61, 62, 69, 71, 76, 78, 79,255, 42, 47,255, 61,255, 61,255, - 61,255, 69, 84,255, 69, 84,255, 33, 47, 60, 61, 62, 69, 71, 76, 78,255, - 61,255, 42, 47,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84, - 255, 69, 84,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 65, 69, - 71, 76, 77, 78, 79, 83, 88, 92,255, 76, 89,255, 69,255, 66, 83, 87,255, - 68, 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 78, 81, 88,255, 78, 83, - 255, 73, 83,255, 65, 79, 83,255, 65, 79,255, 70,255, 84,255, 78,255, 73, - 255, 65, 82, 85,255, 69, 84, 89,255, 69, 73,255, 36, 42, 65, 66, 67, 68, - 69, 70, 72, 76, 77, 78, 79, 80, 83, 84, 86, 87,255, 39,255, 67, 68, 73, - 255, 65, 73,255, 67, 68, 78, 82, 83,255, 67, 90,255, 69,255, 65,255, 67, - 77, 78, 80, 82, 90,255, 65, 67, 80,255, 67, 90,255, 69, 73, 79,255, 65, - 67, 77, 78, 80, 90,255, 65, 68,255, 82, 88,255, 72, 83,255, 65, 67, 69, - 73, 83,255, 77, 84,255, 76,255, 82, 88,255, 78,255, 80,255, 53,255, 67, - 68, 75, 88, 90,255, 69, 79,255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, - 80, 84, 88, 90,255, 88,255, 72, 83,255, 65, 69, 72, 83,255, 69,255, 68, - 73, 88,255, 76,255, 79, 85,255, 67, 68, 72, 74, 80, 82, 88,255, 79, 86, - 255, 65, 73,255, 82, 85,255, 67, 79, 85,255, 76, 82,255, 65,255, 67, 68, + 65, 67, 77, 78, 80, 83, 90,255, 65, 68,255, 82, 88,255, 72, 83,255, 69, + 85,255, 65, 66, 67, 69, 73, 83, 87,255, 73,255, 68, 84,255, 78, 82,255, + 69, 82,255, 84,255, 67, 73, 76, 78, 81, 88,255, 77, 84,255, 69, 76,255, + 82, 88,255, 70, 78,255, 80,255, 53,255, 67, 68, 75, 88, 90,255, 69, 79, + 255, 77, 80,255, 53,255, 67, 68, 75, 77, 78, 80, 84, 88, 90,255, 88,255, + 72, 83,255, 65, 69, 72, 83,255, 69,255, 68, 73, 88,255, 76,255, 78, 83, + 255, 79, 85,255, 67, 68, 72, 73, 74, 80, 82, 83, 88,255, 68, 86,255, 65, + 79, 83, 86,255, 65,255, 80,255, 65, 79,255, 65, 71, 73,255, 82, 85,255, + 70,255, 84,255, 78,255, 73,255, 66, 83,255, 65, 67, 79, 82, 85,255, 76, + 82,255, 65,255, 67, 68,255, 67, 90,255, 69, 71, 79,255, 67, 72,255, 86, + 255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 67, 90, + 255, 66, 67, 73, 78, 90,255, 69,255, 68, 73, 82, 88,255, 76,255, 71, 72, + 73,255, 88,255, 65, 67, 75,255, 66, 73,255, 66, 69, 72, 73, 80, 84, 85, + 89,255, 69, 73,255, 65, 73,255, 67, 82, 84,255, 36, 38, 42, 47, 61, 65, + 66, 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 84, 86, 87, + 88,255, 42, 47,255, 85,255, 76,255, 67,255, 78,255, 47, 73,255, 42, 47, + 255, 67, 68, 73,255, 65, 73,255, 69, 72,255, 67, 68, 78, 82, 83,255, 67, + 90,255, 69,255, 65,255, 67, 76, 77, 78, 80, 82, 89, 90,255, 65, 67, 80, + 255, 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 83, 90,255, 65, 68, + 255, 82, 88,255, 72, 83,255, 69, 85,255, 65, 66, 67, 69, 73, 83, 87,255, + 73,255, 68, 84,255, 78, 82,255, 69, 82,255, 84,255, 67, 73, 76, 78, 88, + 255, 77, 84,255, 69, 76,255, 85,255, 76,255, 67, 82, 88,255, 70, 78,255, + 80,255, 53,255, 67, 68, 75, 88, 90,255, 69, 79,255, 77, 80,255, 53,255, + 67, 68, 75, 77, 78, 80, 84, 88, 90,255, 88,255, 72, 83,255, 65, 69, 72, + 83,255, 69,255, 68, 73, 88,255, 76,255, 78, 83,255, 79, 85,255, 67, 68, + 72, 73, 74, 80, 82, 83, 88,255, 68, 86,255, 65, 79, 83, 86,255, 65,255, + 80,255, 65, 79,255, 65, 71, 73,255, 82, 85,255, 70,255, 84,255, 78,255, + 73,255, 66, 83,255, 65, 67, 79, 82, 85,255, 76, 82,255, 65,255, 67, 68, 255, 67, 90,255, 69, 71, 79,255, 67, 72,255, 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, 67, 90,255, 66, 67, 73, 78, 90, 255, 69,255, 68, 73, 82, 88,255, 76,255, 71, 72, 73,255, 88,255, 65, 67, - 255, 66, 73,255, 66, 72, 73, 80, 84, 85,255, 65, 73,255, 67, 82, 84,255, - 65, 66, 67, 68, 69, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 88,255, 42, - 47,255, 36, 38, 47,255, 42, 47,255, 33, 44, 47,255, 44,255, 42, 47,255, - 47, 79, 81,255, 92,255, 69,255, 69,255, 76, 80,255, 73,255, 71, 87,255, - 78, 79,255, 36, 38, 39, 40, 65, 66, 67, 68, 69, 70, 72, 73, 76, 77, 78, - 80, 83,255, 33,255, 42, 47,255, 47, 92,255 + 75,255, 66, 73,255, 66, 72, 73, 80, 84, 85, 89,255, 69, 73,255, 65, 73, + 255, 67, 82, 84,255, 36, 38, 42, 47, 65, 66, 67, 68, 69, 70, 72, 73, 74, + 76, 77, 78, 79, 80, 82, 83, 84, 86, 87, 88,255, 38,255, 76, 80,255, 71, + 87,255, 78, 79,255, 38, 39, 67, 68, 70, 72, 73, 76, 78, 80, 83,255, 42, + 47,255, 47,255, 78, 88,255, 69, 72, 76, 86,255, 66, 68, 84,255, 42, 47, + 255, 85,255, 76,255, 67,255, 78,255, 35, 38, 42, 46, 47, 73,255, 47, 61, + 255, 42, 47,255, 76, 89,255, 69,255, 66, 83, 87,255, 68, 84,255, 78, 82, + 255, 69, 82,255, 84,255, 67, 78, 81, 88,255, 85,255, 76,255, 67,255, 78, + 255, 78, 83,255, 73, 83,255, 65, 79, 83,255, 65, 79,255, 70,255, 84,255, + 78,255, 73,255, 65, 82, 85,255, 69, 84, 89,255, 69, 73,255, 36, 42, 47, + 65, 66, 67, 68, 69, 70, 72, 73, 76, 77, 78, 79, 80, 83, 84, 86, 87, 92, + 255, 85,255, 76,255, 67,255, 78,255, 73,255, 42, 47,255, 42, 47,255, 42, + 47, 92,255, 42, 47,255, 47, 73, 80,255, 42, 47,255, 33, 47,255, 67,255, + 69, 88,255, 76,255, 66, 68, 72, 80, 83,255, 40, 65, 66, 67, 68, 69, 72, + 76, 77,255, 67,255, 69,255, 76,255, 66, 68, 72, 83,255, 67,255, 69,255, + 76,255, 65, 66, 68, 72, 80,255, 67,255, 69,255, 66, 68,255, 61,255, 42, + 47,255, 60, 61,255, 61,255, 61, 62,255, 33, 42, 44, 47, 60, 61, 62,255, + 61,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84, + 255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 65, 69, 71, 76, 77, + 78, 79, 83, 88,255, 76, 89,255, 69,255, 66, 83, 87,255, 68, 84,255, 78, + 82,255, 69, 82,255, 84,255, 67, 78, 88,255, 78, 83,255, 73, 83,255, 65, + 79, 83,255, 65, 79,255, 70,255, 84,255, 78,255, 73,255, 65, 82, 85,255, + 84, 89,255, 69, 73,255, 36, 42, 65, 66, 67, 68, 69, 70, 72, 76, 77, 78, + 79, 80, 83, 84, 86, 87,255, 42, 47,255, 44, 47,255, 61,255, 42, 47,255, + 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 82,255, 76, 82, + 255, 72,255, 33, 42, 44, 47, 60, 61, 62, 65, 69, 71, 76, 77, 78, 79, 81, + 83, 88,255, 39,255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, + 69, 84,255, 69, 84,255, 82,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, + 61, 62, 71, 76, 77, 78, 79, 81, 83, 88,255, 42, 47,255, 76, 80,255, 71, + 87,255, 78, 79,255, 38, 39, 42, 47, 67, 68, 70, 72, 73, 76, 78, 80, 83, + 92,255, 61,255, 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, + 69, 84,255, 76, 82,255, 72,255, 33, 42, 44, 47, 60, 61, 62, 71, 76, 77, + 78, 79, 83, 88,255, 76, 80,255, 71, 87,255, 78, 79,255, 38, 39, 67, 68, + 70, 72, 73, 76, 80, 83,255, 42, 47,255, 76, 80,255, 71, 87,255, 78, 79, + 255, 38, 39, 42, 47, 67, 68, 70, 72, 73, 76, 80, 83, 92,255, 61,255, 60, + 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, + 33, 42, 44, 60, 61, 62, 65, 69, 71, 76, 77, 78, 79, 83, 88,255, 61,255, + 42, 47,255, 60, 61,255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 76, + 82,255, 72,255, 33, 44, 47, 60, 61, 62, 65, 69, 71, 76, 78, 79, 83, 88, + 255, 61,255, 42, 47,255, 61,255, 61,255, 61,255, 69, 84,255, 69, 84,255, + 33, 44, 47, 60, 61, 62, 65, 69, 71, 76, 78, 79, 88,255, 61,255, 42, 47, + 255, 61,255, 61,255, 61,255, 69, 84,255, 69, 84,255, 33, 44, 47, 60, 61, + 62, 69, 71, 76, 78, 79, 88,255, 61,255, 42, 47,255, 61,255, 61,255, 61, + 255, 69, 84,255, 69, 84,255, 33, 44, 47, 60, 61, 62, 69, 71, 76, 78, 79, + 255, 42, 47,255, 61,255, 61,255, 61,255, 69, 84,255, 69, 84,255, 33, 47, + 60, 61, 62, 69, 71, 76, 78,255, 61,255, 42, 47,255, 42, 47,255, 60, 61, + 255, 61,255, 61, 62,255, 69, 84,255, 69, 84,255, 76, 82,255, 72,255, 33, + 42, 44, 47, 60, 61, 62, 65, 69, 71, 76, 77, 78, 79, 83, 88, 92,255, 76, + 89,255, 69,255, 66, 83, 87,255, 68, 84,255, 78, 82,255, 69, 82,255, 84, + 255, 67, 78, 81, 88,255, 78, 83,255, 73, 83,255, 65, 79, 83,255, 65, 79, + 255, 70,255, 84,255, 78,255, 73,255, 65, 82, 85,255, 69, 84, 89,255, 69, + 73,255, 36, 42, 65, 66, 67, 68, 69, 70, 72, 76, 77, 78, 79, 80, 83, 84, + 86, 87,255, 39,255, 67, 68, 73,255, 65, 73,255, 67, 68, 78, 82, 83,255, + 67, 90,255, 69,255, 65,255, 67, 77, 78, 80, 82, 90,255, 65, 67, 80,255, + 67, 90,255, 69, 73, 79,255, 65, 67, 77, 78, 80, 90,255, 65, 68,255, 82, + 88,255, 72, 83,255, 65, 67, 69, 73, 83,255, 77, 84,255, 76,255, 82, 88, + 255, 78,255, 80,255, 53,255, 67, 68, 75, 88, 90,255, 69, 79,255, 77, 80, + 255, 53,255, 67, 68, 75, 77, 78, 80, 84, 88, 90,255, 88,255, 72, 83,255, + 65, 69, 72, 83,255, 69,255, 68, 73, 88,255, 76,255, 79, 85,255, 67, 68, + 72, 74, 80, 82, 88,255, 79, 86,255, 65, 73,255, 82, 85,255, 67, 79, 85, + 255, 76, 82,255, 65,255, 67, 68,255, 67, 90,255, 69, 71, 79,255, 67, 72, + 255, 86,255, 84,255, 65, 67, 68, 69, 73, 76, 77, 78, 80, 82, 83, 90,255, + 67, 90,255, 66, 67, 73, 78, 90,255, 69,255, 68, 73, 82, 88,255, 76,255, + 71, 72, 73,255, 88,255, 65, 67,255, 66, 73,255, 66, 72, 73, 80, 84, 85, + 255, 65, 73,255, 67, 82, 84,255, 65, 66, 67, 68, 69, 72, 73, 74, 76, 77, + 78, 79, 80, 82, 83, 88,255, 42, 47,255, 38, 47,255, 42, 47,255, 33, 44, + 47,255, 44,255, 42, 47,255, 47, 79, 81,255, 92,255, 69,255, 69,255, 76, + 80,255, 73,255, 71, 87,255, 78, 79,255, 38, 39, 40, 65, 66, 67, 68, 69, + 70, 72, 73, 76, 77, 78, 80, 83,255, 33,255, 42, 47,255, 47, 92,255 }; static const unsigned char ag_key_act[] = { - 0,3,3,3,4,0,0,4,7,4,6,4,2,4,2,4,0,5,0,2,2,2,4,0,4,0,4,0,0,0,4,3,3,3,4, - 0,0,4,0,0,4,0,4,0,0,4,5,5,5,4,5,5,5,4,7,7,4,7,2,2,7,2,4,5,5,4,5,4,5,4, - 5,7,5,2,6,6,7,5,4,5,5,5,4,5,5,4,5,5,5,4,7,5,7,6,2,6,7,5,4,5,5,4,5,5,4, - 5,4,6,4,2,4,2,4,2,7,7,4,7,7,4,2,5,2,6,5,6,5,5,4,7,7,4,7,4,6,7,4,5,4,7, - 7,4,2,7,4,2,4,7,5,2,2,6,7,2,4,7,7,5,4,5,5,4,7,5,4,7,7,6,4,7,7,4,7,4,6, - 4,2,7,5,5,4,6,6,5,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2, - 6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4,2,4,7,7,4,5,5,4,7,7,4,7,2,5,2,2, - 7,5,2,2,7,7,5,7,4,7,4,6,5,4,7,2,7,7,4,7,4,6,5,4,7,5,2,4,5,5,5,4,6,7,4, - 7,4,5,4,6,4,2,4,7,2,4,7,7,4,7,6,7,2,7,2,4,5,5,4,7,4,5,7,4,5,5,4,5,5,5, - 4,5,7,4,5,4,6,4,2,6,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5,5, - 5,4,6,5,4,5,7,5,4,5,4,6,5,7,4,5,5,4,2,7,2,7,6,7,2,2,7,4,7,7,4,5,5,4,7, - 7,2,7,4,6,0,6,0,3,3,2,0,2,2,1,1,1,6,6,6,6,6,2,2,6,2,2,6,6,2,2,2,2,2,2, - 7,7,7,2,3,4,3,3,3,4,0,0,4,0,5,0,2,2,4,7,7,4,7,2,7,7,4,7,7,4,6,7,4,5,4, - 6,4,2,4,7,2,4,2,4,7,2,2,2,7,4,0,0,4,0,3,2,0,0,4,0,4,0,0,4,5,5,5,4,5,5, - 4,7,7,4,7,2,2,7,2,4,5,5,4,5,4,5,4,5,7,5,2,6,6,7,5,4,5,5,5,4,5,5,4,5,5, - 5,4,7,5,6,2,6,7,5,4,5,5,4,5,5,4,7,7,4,7,7,4,2,5,2,2,5,6,5,4,7,4,6,7,4, - 7,7,4,2,7,4,2,4,7,5,7,2,7,2,4,7,5,4,7,2,4,5,5,4,5,6,4,5,4,5,4,5,5,5,6, - 5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5, - 4,2,4,7,7,4,7,7,4,7,2,2,2,7,2,7,7,7,4,7,5,4,7,2,7,7,4,7,4,6,4,7,2,4,5, - 5,5,4,2,7,4,5,4,6,4,2,4,2,4,7,7,4,7,7,7,2,2,4,5,5,4,7,4,5,7,4,5,5,4,5, - 5,5,4,5,7,4,5,4,6,4,2,6,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6, - 5,5,5,4,2,4,5,7,5,4,5,4,6,5,7,4,5,5,4,2,7,2,7,2,2,2,7,4,7,7,4,5,5,4,7, - 2,7,4,6,0,3,2,0,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,7,7,2,4,0,0,4,7,4,6, - 4,2,4,2,4,2,2,4,0,4,0,0,4,5,5,5,4,5,5,4,7,7,4,7,2,2,7,2,4,5,5,4,5,4,5, - 4,5,7,5,2,6,6,7,5,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5,4,5,5,4,5,5,4, - 7,7,4,7,7,4,2,5,2,2,5,6,5,4,7,4,6,7,4,7,7,4,2,7,4,2,4,7,5,7,2,2,4,7,5, - 4,7,2,4,7,4,6,4,2,5,5,4,5,6,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5, - 5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4,2,4,7,7,4,7,7,4,7,2,2, - 2,7,2,7,7,7,4,7,5,4,7,2,7,7,4,7,4,6,4,7,2,4,5,5,5,4,2,7,4,5,4,6,4,2,4, - 2,4,7,7,4,7,7,7,2,2,4,5,5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4,6,4,2,6, - 7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5,5,5,4,2,4,5,7,5,4,5,4, - 6,5,7,4,5,5,4,2,2,7,2,2,2,7,4,7,7,4,5,5,4,7,2,7,4,6,0,3,2,2,2,2,2,2,7, - 2,2,2,2,2,2,2,2,2,2,2,7,7,2,4,5,0,4,7,5,4,5,5,4,5,2,4,5,0,3,7,7,2,7,7, - 2,7,7,7,4,0,0,4,2,4,7,7,4,2,7,7,7,4,3,3,3,4,0,0,4,7,4,6,4,2,4,2,4,0,5, - 0,3,2,2,2,4,0,0,4,0,0,4,7,7,4,7,4,5,6,5,4,5,7,4,7,7,4,2,7,4,2,4,7,2,7, - 2,4,7,4,6,4,2,4,2,4,7,7,4,2,7,4,7,7,7,4,7,7,4,5,4,6,4,2,4,2,4,7,2,7,4, - 7,7,7,4,7,7,4,3,2,2,7,2,7,2,2,7,7,2,2,2,2,7,2,2,2,7,7,3,4,7,4,6,4,2,4, - 2,4,2,4,3,3,4,0,0,4,3,2,3,4,0,0,4,2,7,7,4,0,0,4,5,2,4,5,4,5,5,4,5,4,6, - 6,6,7,7,4,3,5,5,5,5,5,5,5,5,4,5,4,5,4,5,4,6,6,6,7,4,5,4,5,4,5,4,5,6,6, - 6,7,4,5,4,5,4,6,6,4,0,4,0,0,4,0,0,4,0,4,0,0,4,6,3,0,2,1,1,1,4,0,4,0,0, - 4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,3,0,2,1,1,1,7,7,2,2,7,7,7,2, - 7,4,7,7,4,7,4,5,6,5,4,5,7,4,7,7,4,2,7,4,2,4,7,2,2,4,7,7,4,2,7,4,7,7,7, - 4,7,7,4,5,4,6,4,2,4,2,4,7,2,7,4,7,7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2,2,7, - 2,2,2,7,7,4,0,0,4,0,2,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,4,5,5, - 4,2,4,6,3,0,2,1,1,1,7,7,2,2,7,7,6,5,2,7,4,3,4,0,4,0,0,4,0,0,4,0,4,0,0, - 4,5,5,4,5,5,4,5,4,5,5,4,2,4,6,3,0,2,1,1,1,2,2,7,7,6,5,2,7,4,0,0,4,7,5, - 4,5,5,4,5,2,4,5,0,3,3,2,7,7,2,7,7,2,7,7,7,3,4,7,5,4,5,5,4,5,2,4,5,0,3, - 7,7,2,7,7,2,7,7,4,0,0,4,7,5,4,5,5,4,5,2,4,5,0,3,3,2,7,7,2,7,7,2,7,7,3, - 4,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,3,0,1,1,1,7,7,2,2,7,7,7, - 2,7,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,0,2,1,1,1,7,7, - 2,2,7,7,2,7,4,0,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,6,0,2,1,1,1,7,7,2,2,7, - 7,7,4,0,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,6,0,2,1,1,1,7,2,2,7,7,7,4,0,4, - 0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,6,0,2,1,1,1,7,2,2,7,7,4,0,0,4,0,4,0,4,0, - 4,5,5,4,5,5,4,3,2,1,1,1,7,2,2,7,4,0,4,0,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5, - 4,5,5,4,5,5,4,2,4,6,2,0,2,1,1,1,7,7,2,2,7,7,7,2,7,3,4,7,7,4,7,4,5,6,5, - 4,5,7,4,7,7,4,2,7,4,2,4,7,2,7,2,4,7,7,4,2,7,4,7,7,7,4,7,7,4,5,4,6,4,2, - 4,2,4,7,2,7,4,7,7,7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2,2,7,2,2,2,7,7,4,3,4, - 5,5,5,4,5,5,4,7,2,2,7,7,4,5,5,4,5,4,5,4,5,5,2,6,6,5,4,5,5,5,4,5,5,4,5, - 5,5,4,7,5,6,2,6,5,4,5,5,4,5,5,4,7,7,4,2,2,2,5,7,4,7,5,4,2,4,5,5,4,6,4, - 5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2, - 7,7,4,5,4,6,5,5,4,2,4,7,7,4,7,2,2,7,2,7,7,4,7,7,4,5,5,4,2,7,4,7,7,7,4, - 5,5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4,6,4,2,6,7,7,7,2,5,2,6,2,2,5,4, - 5,5,4,5,5,5,2,5,4,5,4,6,5,5,5,4,2,4,5,7,5,4,5,4,6,5,4,5,5,4,2,2,7,2,2, - 2,4,5,5,4,7,2,7,4,2,2,2,2,7,2,2,2,2,2,7,2,2,2,2,2,4,0,0,4,5,0,2,4,0,0, - 4,5,0,2,4,0,4,0,0,4,2,5,5,4,3,4,7,4,7,4,7,5,4,7,4,5,5,4,5,2,4,5,0,3,3, - 5,5,6,6,5,2,6,7,6,5,7,7,7,4,5,4,0,0,4,2,3,4 + 0,3,3,3,4,0,0,4,7,4,6,4,2,4,2,4,0,0,2,2,2,4,0,4,0,0,0,4,3,3,3,4,0,0,4, + 0,0,4,0,4,0,0,4,5,5,5,4,5,5,5,4,7,7,4,7,2,2,7,2,4,5,5,4,5,4,5,4,5,7,5, + 2,6,6,7,5,4,5,5,5,4,5,5,4,5,5,5,4,7,5,7,6,2,6,7,5,4,5,5,4,5,5,4,5,4,6, + 4,2,4,2,4,2,7,7,4,7,7,4,2,5,2,6,5,6,5,5,4,7,7,4,7,4,6,7,4,5,4,7,7,4,2, + 7,4,2,4,7,5,2,2,6,7,2,4,7,7,5,4,5,5,4,7,5,4,7,7,6,4,7,7,4,7,4,6,4,2,7, + 5,5,4,6,6,5,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5,4, + 5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4,2,4,7,7,4,5,5,4,7,7,4,7,2,5,2,2,7,5,2, + 2,7,7,5,7,4,7,4,6,5,4,7,2,7,7,4,7,4,6,5,4,7,5,2,4,5,5,5,4,6,7,4,7,4,5, + 4,6,4,2,4,7,2,4,7,7,4,7,6,7,2,7,2,4,5,5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7, + 4,5,4,6,4,2,6,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5,5,5,4,6, + 5,4,5,7,5,4,5,4,6,5,7,4,5,5,4,2,7,2,7,6,7,2,2,7,4,7,7,4,5,5,4,7,7,2,7, + 4,6,0,3,0,3,3,2,0,2,2,1,1,1,6,6,6,6,6,2,2,6,2,2,6,6,2,2,2,2,2,2,7,7,7, + 2,3,4,3,3,3,4,0,0,4,0,0,2,2,4,7,7,4,7,2,7,7,4,7,7,4,6,7,4,5,4,6,4,2,4, + 7,2,4,2,4,7,2,2,2,7,4,0,0,4,3,0,3,2,0,0,4,0,0,4,5,5,5,4,5,5,4,7,7,4,7, + 2,2,7,2,4,5,5,4,5,4,5,4,5,7,5,2,6,6,7,5,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6, + 2,6,7,5,4,5,5,4,5,5,4,7,7,4,7,7,4,2,5,2,2,5,6,5,4,7,4,6,7,4,7,7,4,2,7, + 4,2,4,7,5,7,2,7,2,4,7,5,4,7,2,4,5,5,4,5,6,4,5,4,5,4,5,5,5,6,5,4,5,5,4, + 5,5,4,5,4,5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4,2,4,7,7, + 4,7,7,4,7,2,2,2,7,2,7,7,7,4,7,5,4,7,2,7,7,4,7,4,6,4,7,2,4,5,5,5,4,2,7, + 4,5,4,6,4,2,4,2,4,7,7,4,7,7,7,2,2,4,5,5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7, + 4,5,4,6,4,2,6,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5,5,5,4,2, + 4,5,7,5,4,5,4,6,5,7,4,5,5,4,2,7,2,7,2,2,2,7,4,7,7,4,5,5,4,7,2,7,4,3,0, + 3,2,0,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,7,7,2,4,0,0,4,7,4,6,4,2,4,2,4, + 2,2,4,0,0,4,5,5,5,4,5,5,4,7,7,4,7,2,2,7,2,4,5,5,4,5,4,5,4,5,7,5,2,6,6, + 7,5,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,7,5,4,5,5,4,5,5,4,7,7,4,7,7,4,2, + 5,2,2,5,6,5,4,7,4,6,7,4,7,7,4,2,7,4,2,4,7,5,7,2,2,4,7,5,4,7,2,4,7,4,6, + 4,2,5,5,4,5,6,4,5,4,5,4,5,5,5,6,5,4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5, + 4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4,2,4,7,7,4,7,7,4,7,2,2,2,7,2,7,7,7,4, + 7,5,4,7,2,7,7,4,7,4,6,4,7,2,4,5,5,5,4,2,7,4,5,4,6,4,2,4,2,4,7,7,4,7,7, + 7,2,2,4,5,5,4,7,4,5,7,4,5,5,4,5,5,5,4,5,7,4,5,4,6,4,2,6,7,7,7,2,5,2,6, + 2,2,5,4,5,5,4,5,5,5,2,5,4,5,4,6,5,5,5,4,2,4,5,7,5,4,5,4,6,5,7,4,5,5,4, + 2,2,7,2,2,2,7,4,7,7,4,5,5,4,7,2,7,4,3,0,3,2,2,2,2,2,2,7,2,2,2,2,2,2,2, + 2,2,2,2,7,7,2,4,0,4,7,5,4,5,5,4,5,2,4,0,3,7,7,2,7,7,2,7,7,7,4,0,0,4,2, + 4,7,7,4,2,7,7,7,4,3,3,3,4,0,0,4,7,4,6,4,2,4,2,4,0,0,3,2,2,2,4,0,0,4,0, + 0,4,7,7,4,7,4,5,6,5,4,5,7,4,7,7,4,2,7,4,2,4,7,2,7,2,4,7,4,6,4,2,4,2,4, + 7,7,4,2,7,4,7,7,7,4,7,7,4,5,4,6,4,2,4,2,4,7,2,7,4,7,7,7,4,7,7,4,3,2,2, + 7,2,7,2,2,7,7,2,2,2,2,7,2,2,2,7,7,3,4,7,4,6,4,2,4,2,4,2,4,3,3,4,0,0,4, + 3,2,3,4,0,0,4,2,7,7,4,0,0,4,5,2,4,5,4,5,5,4,5,4,6,6,6,7,7,4,3,5,5,5,5, + 5,5,5,5,4,5,4,5,4,5,4,6,6,6,7,4,5,4,5,4,5,4,5,6,6,6,7,4,5,4,5,4,6,6,4, + 0,4,0,0,4,0,0,4,0,4,0,0,4,6,3,0,2,1,1,1,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5, + 5,4,5,5,4,5,5,4,2,4,6,3,0,2,1,1,1,7,7,2,2,7,7,7,2,7,4,7,7,4,7,4,5,6,5, + 4,5,7,4,7,7,4,2,7,4,2,4,7,2,2,4,7,7,4,2,7,4,7,7,7,4,7,7,4,5,4,6,4,2,4, + 2,4,7,2,7,4,7,7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2,2,7,2,2,2,7,7,4,0,0,4,0, + 2,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,4,5,5,4,2,4,6,3,0,2,1,1,1, + 7,7,2,2,7,7,6,5,2,7,4,3,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,4,5, + 5,4,2,4,6,3,0,2,1,1,1,2,2,7,7,6,5,2,7,4,0,0,4,7,5,4,5,5,4,5,2,4,0,3,3, + 2,7,7,2,7,7,2,7,7,7,3,4,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2, + 4,6,3,0,2,1,1,1,2,2,7,7,7,2,7,4,7,5,4,5,5,4,5,2,4,0,3,7,7,2,7,7,2,7,7, + 4,0,0,4,7,5,4,5,5,4,5,2,4,0,3,3,2,7,7,2,7,7,2,7,7,3,4,0,4,0,0,4,0,4,0, + 0,4,5,5,4,5,5,4,5,5,4,2,4,6,3,0,1,1,1,7,7,2,2,7,7,7,2,7,4,0,4,0,0,4,0, + 0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4,6,0,2,1,1,1,7,7,2,2,7,7,2,7,4,0,4, + 0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,6,0,2,1,1,1,7,7,2,2,7,7,7,4,0,4,0,0,4,0, + 4,0,4,0,4,5,5,4,5,5,4,6,0,2,1,1,1,7,2,2,7,7,7,4,0,4,0,0,4,0,4,0,4,0,4, + 5,5,4,5,5,4,6,0,2,1,1,1,7,2,2,7,7,4,0,0,4,0,4,0,4,0,4,5,5,4,5,5,4,3,2, + 1,1,1,7,2,2,7,4,0,4,0,0,4,0,0,4,0,0,4,0,4,0,0,4,5,5,4,5,5,4,5,5,4,2,4, + 6,2,0,2,1,1,1,7,7,2,2,7,7,7,2,7,3,4,7,7,4,7,4,5,6,5,4,5,7,4,7,7,4,2,7, + 4,2,4,7,2,7,2,4,7,7,4,2,7,4,7,7,7,4,7,7,4,5,4,6,4,2,4,2,4,7,2,7,4,7,7, + 7,4,7,7,4,3,3,7,2,7,2,2,7,7,2,2,2,7,2,2,2,7,7,4,3,4,5,5,5,4,5,5,4,7,2, + 2,7,7,4,5,5,4,5,4,5,4,5,5,2,6,6,5,4,5,5,5,4,5,5,4,5,5,5,4,7,5,6,2,6,5, + 4,5,5,4,5,5,4,7,7,4,2,2,2,5,7,4,7,5,4,2,4,5,5,4,6,4,5,4,5,4,5,5,5,6,5, + 4,5,5,4,5,5,4,5,4,5,5,5,6,2,6,2,6,5,4,5,4,5,5,4,6,2,7,7,4,5,4,6,5,5,4, + 2,4,7,7,4,7,2,2,7,2,7,7,4,7,7,4,5,5,4,2,7,4,7,7,7,4,5,5,4,7,4,5,7,4,5, + 5,4,5,5,5,4,5,7,4,5,4,6,4,2,6,7,7,7,2,5,2,6,2,2,5,4,5,5,4,5,5,5,2,5,4, + 5,4,6,5,5,5,4,2,4,5,7,5,4,5,4,6,5,4,5,5,4,2,2,7,2,2,2,4,5,5,4,7,2,7,4, + 2,2,2,2,7,2,2,2,2,2,7,2,2,2,2,2,4,0,0,4,0,2,4,0,0,4,5,0,2,4,0,4,0,0,4, + 2,5,5,4,3,4,7,4,7,4,7,5,4,7,4,5,5,4,5,2,4,0,3,3,5,5,6,6,5,2,6,7,6,5,7, + 7,7,4,5,4,0,0,4,2,3,4 }; static const unsigned short ag_key_parm[] = { - 0,162,164,163, 0,427,424, 0, 4, 0, 6, 0, 0, 0, 0, 0,438, 98, - 135, 0, 0, 0, 0,498, 0,465, 0,523,426,466, 0,162,164,163, 0,427, - 424, 0,513,502, 0,496, 0,500,515, 0,282,284,324, 0,286,118,326, 0, - 50,184, 0,322, 0, 0,188, 0, 0,426,424, 0,432, 0,420, 0,168, 54, - 428, 0,430,418, 58,422, 0,192,194,288, 0,334,336, 0,340,342,344, 0, - 328,330,130,332, 0,338, 44,346, 0,196,308, 0,290,310, 0,146, 0, 42, - 0, 0, 0, 0, 0, 0,392,398, 0, 46,200, 0, 0, 56, 0,170,198, 52, - 62,178, 0, 24, 28, 0, 30, 0, 80, 14, 0, 0, 0, 18, 70, 0, 0, 68, - 0, 0, 0, 34,204, 0, 0,102, 32, 0, 0, 78,128,140, 0,106,110, 0, - 202,206, 0, 12,142,172, 0, 20, 26, 0, 4, 0, 6, 0, 0,100,292,312, - 0, 22,348,138, 0,364, 0,370, 0,366,376,374,368,378, 0,382,384, 0, - 356,372, 0,354, 0,350,360,358,362, 0,380, 0,352,386, 0,272, 0,390, - 396, 0,388, 0,394,400, 0,212, 0,402,210,208, 0, 0, 0, 92, 10, 0, - 134,144, 0,278,280, 0,444, 0,108, 0, 0,446,132, 0, 0,268, 84,112, - 314, 0, 72, 0,124,294, 0, 94, 0, 82,316, 0, 88, 0,214,126, 0, 74, - 104, 0, 0,296, 48,404, 0,114,406, 0,216, 0, 38, 0, 36, 0, 0, 0, - 8, 0, 0, 66,276, 0, 96,180,274, 0,176, 0, 0,218,220, 0,434, 0, - 228,230, 0,236,238, 0,242,306,244, 0,246,190, 0,248, 0,320, 0, 0, - 222,232,224,226, 0,234, 0,240, 0, 0,250, 0,442,438, 0,298,440,408, - 0,436, 0,256, 0,410,254,186,252, 0,120,122, 0,304,260,318, 0,270, - 0,412,262, 76, 0,300,414, 0, 0, 2, 0,258,174,136, 0, 0, 90, 0, - 60, 86, 0,302,416, 0,264,116, 0,266, 0,182,438, 98,135,231,241, 0, - 493, 0, 0,506,432,504,166,152,154,156,158, 0, 0,160, 0, 0,162,164, - 0, 0, 0, 0, 0, 0, 40, 16, 64, 0,461, 0,162,164,163, 0,427,424, - 0,438, 98,135, 0, 0, 0, 24, 28, 0, 34, 0, 30, 32, 0, 20, 26, 0, - 22, 4, 0, 38, 0, 36, 0, 0, 0, 8, 0, 0, 0, 0, 42, 0, 0, 0, - 40, 0,427,424, 0,135,466, 0,161,432, 0,465, 0,427,424, 0,282,284, - 324, 0,286,326, 0, 50,184, 0,322, 0, 0,188, 0, 0,426,424, 0,432, - 0,420, 0,168, 54,428, 0,430,418, 58,422, 0,192,194,288, 0,334,336, - 0,340,342,344, 0,328,330,332, 0,338, 44,346, 0,196,308, 0,290,310, - 0,392,398, 0, 46,200, 0, 0, 56, 0, 0,198, 52, 62, 0, 30, 0, 80, - 14, 0, 18, 70, 0, 0, 68, 0, 0, 0, 34,204, 28, 0, 0, 0, 0,202, - 206, 0, 12, 0, 0,292,312, 0, 22,348, 0,364, 0,370, 0,366,376,374, - 368,378, 0,382,384, 0,356,372, 0,354, 0,350,360,358,362, 0,380, 0, - 352,386, 0,272, 0,390,396, 0,388, 0,394,400, 0,212, 0,402,210,208, - 0, 0, 0, 92, 10, 0,278,280, 0,444, 0, 0, 0,446, 0,268, 84,314, - 0, 72,294, 0, 94, 0, 82,316, 0, 88, 0,214, 0, 74, 0, 0,296, 48, - 404, 0, 0,406, 0, 38, 0, 36, 0, 0, 0, 0, 0, 66,276, 0, 96,216, - 274, 0, 0, 0,218,220, 0,434, 0,228,230, 0,236,238, 0,242,306,244, - 0,246,190, 0,248, 0,320, 0, 0,222,232,224,226, 0,234, 0,240, 0, - 0,250, 0,442,438, 0,298,440,408, 0,436, 0,256, 0,410,254,186,252, - 0, 0, 0,304,260,318, 0,270, 0,412,262, 76, 0,300,414, 0, 0, 2, - 0,258, 0, 0, 0, 90, 0, 60, 86, 0,302,416, 0,264, 0,266, 0, 98, - 135,466, 0,432, 0, 0, 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 16, 64, 0, 0,427,424, 0, 4, 0, 6, 0, 0, 0, 0, 0, - 0, 0, 0,465, 0,427,424, 0,282,284,324, 0,286,326, 0, 50,184, 0, - 322, 0, 0,188, 0, 0,426,424, 0,432, 0,420, 0,168, 54,428, 0,430, - 418, 58,422, 0,192,194,288, 0,334,336, 0,340,342,344, 0,328,330,332, - 0,338, 44,346, 0,196,308, 0,290,310, 0,392,398, 0, 46,200, 0, 0, - 56, 0, 0,198, 52, 62, 0, 30, 0, 80, 14, 0, 18, 70, 0, 0, 68, 0, - 0, 0, 34,204, 28, 0, 0, 0,202,206, 0, 12, 0, 0, 4, 0, 6, 0, - 0,292,312, 0, 22,348, 0,364, 0,370, 0,366,376,374,368,378, 0,382, - 384, 0,356,372, 0,354, 0,350,360,358,362, 0,380, 0,352,386, 0,272, - 0,390,396, 0,388, 0,394,400, 0,212, 0,402,210,208, 0, 0, 0, 92, - 10, 0,278,280, 0,444, 0, 0, 0,446, 0,268, 84,314, 0, 72,294, 0, - 94, 0, 82,316, 0, 88, 0,214, 0, 74, 0, 0,296, 48,404, 0, 0,406, - 0, 38, 0, 36, 0, 0, 0, 0, 0, 66,276, 0, 96,216,274, 0, 0, 0, - 218,220, 0,434, 0,228,230, 0,236,238, 0,242,306,244, 0,246,190, 0, - 248, 0,320, 0, 0,222,232,224,226, 0,234, 0,240, 0, 0,250, 0,442, - 438, 0,298,440,408, 0,436, 0,256, 0,410,254,186,252, 0, 0, 0,304, - 260,318, 0,270, 0,412,262, 76, 0,300,414, 0, 0, 0,258, 0, 0, 0, - 90, 0, 60, 86, 0,302,416, 0,264, 0,266, 0, 98,135,466, 0, 0, 0, - 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 64, 0, - 0, 98,135, 0,128,140, 0,134,144, 0,132, 0, 0, 98,135,231,130,146, - 0,142,138, 0,126, 96,136, 0,427,424, 0, 0, 0, 14, 18, 0, 0, 12, - 10, 16, 0,162,164,163, 0,427,424, 0, 4, 0, 6, 0, 0, 0, 0, 0, - 438, 98,135,426, 0, 0, 0, 0,426,466, 0,427,424, 0, 54, 58, 0, 46, - 0, 56, 52, 62, 0, 80, 14, 0, 18, 70, 0, 0, 68, 0, 0, 0, 34, 0, - 0, 0, 0, 4, 0, 6, 0, 0, 0, 0, 0, 92, 10, 0, 0, 84, 0, 94, + 0,161,163,162, 0,426,423, 0, 4, 0, 6, 0, 0, 0, 0, 0,437,134, + 0, 0, 0, 0,497, 0,522,425,465, 0,161,163,162, 0,426,423, 0,512, + 501, 0,495, 0,499,514, 0,280,282,322, 0,284,116,324, 0, 50,182, 0, + 320, 0, 0,186, 0, 0,424,422, 0,430, 0,418, 0,166, 54,426, 0,428, + 416, 58,420, 0,190,192,286, 0,332,334, 0,338,340,342, 0,326,328,128, + 330, 0,336, 44,344, 0,194,306, 0,288,308, 0,144, 0, 42, 0, 0, 0, + 0, 0, 0,390,396, 0, 46,198, 0, 0, 56, 0,168,196, 52, 62,176, 0, + 24, 28, 0, 30, 0, 80, 14, 0, 0, 0, 18, 70, 0, 0, 68, 0, 0, 0, + 34,202, 0, 0,100, 32, 0, 0, 78,126,138, 0,104,108, 0,200,204, 0, + 12,140,170, 0, 20, 26, 0, 4, 0, 6, 0, 0, 98,290,310, 0, 22,346, + 136, 0,362, 0,368, 0,364,374,372,366,376, 0,380,382, 0,354,370, 0, + 352, 0,348,358,356,360, 0,378, 0,350,384, 0,270, 0,388,394, 0,386, + 0,392,398, 0,210, 0,400,208,206, 0, 0, 0, 92, 10, 0,132,142, 0, + 276,278, 0,442, 0,106, 0, 0,444,130, 0, 0,266, 84,110,312, 0, 72, + 0,122,292, 0, 94, 0, 82,314, 0, 88, 0,212,124, 0, 74,102, 0, 0, + 294, 48,402, 0,112,404, 0,214, 0, 38, 0, 36, 0, 0, 0, 8, 0, 0, + 66,274, 0, 96,178,272, 0,174, 0, 0,216,218, 0,432, 0,226,228, 0, + 234,236, 0,240,304,242, 0,244,188, 0,246, 0,318, 0, 0,220,230,222, + 224, 0,232, 0,238, 0, 0,248, 0,440,436, 0,296,438,406, 0,434, 0, + 254, 0,408,252,184,250, 0,118,120, 0,302,258,316, 0,268, 0,410,260, + 76, 0,298,412, 0, 0, 2, 0,256,172,134, 0, 0, 90, 0, 60, 86, 0, + 300,414, 0,262,114, 0,264, 0,180,437,464,134,230,240, 0,492, 0, 0, + 505,431,503,164,150,152,154,156, 0, 0,158, 0, 0,160,162, 0, 0, 0, + 0, 0, 0, 40, 16, 64, 0,460, 0,161,163,162, 0,426,423, 0,437,134, + 0, 0, 0, 24, 28, 0, 34, 0, 30, 32, 0, 20, 26, 0, 22, 4, 0, 38, + 0, 36, 0, 0, 0, 8, 0, 0, 0, 0, 42, 0, 0, 0, 40, 0,426,423, + 0,464,134,465, 0,160,431, 0,426,423, 0,280,282,322, 0,284,324, 0, + 50,182, 0,320, 0, 0,186, 0, 0,424,422, 0,430, 0,418, 0,166, 54, + 426, 0,428,416, 58,420, 0,190,192,286, 0,332,334, 0,338,340,342, 0, + 326,328,330, 0,336, 44,344, 0,194,306, 0,288,308, 0,390,396, 0, 46, + 198, 0, 0, 56, 0, 0,196, 52, 62, 0, 30, 0, 80, 14, 0, 18, 70, 0, + 0, 68, 0, 0, 0, 34,202, 28, 0, 0, 0, 0,200,204, 0, 12, 0, 0, + 290,310, 0, 22,346, 0,362, 0,368, 0,364,374,372,366,376, 0,380,382, + 0,354,370, 0,352, 0,348,358,356,360, 0,378, 0,350,384, 0,270, 0, + 388,394, 0,386, 0,392,398, 0,210, 0,400,208,206, 0, 0, 0, 92, 10, + 0,276,278, 0,442, 0, 0, 0,444, 0,266, 84,312, 0, 72,292, 0, 94, + 0, 82,314, 0, 88, 0,212, 0, 74, 0, 0,294, 48,402, 0, 0,404, 0, + 38, 0, 36, 0, 0, 0, 0, 0, 66,274, 0, 96,214,272, 0, 0, 0,216, + 218, 0,432, 0,226,228, 0,234,236, 0,240,304,242, 0,244,188, 0,246, + 0,318, 0, 0,220,230,222,224, 0,232, 0,238, 0, 0,248, 0,440,436, + 0,296,438,406, 0,434, 0,254, 0,408,252,184,250, 0, 0, 0,302,258, + 316, 0,268, 0,410,260, 76, 0,298,412, 0, 0, 2, 0,256, 0, 0, 0, + 90, 0, 60, 86, 0,300,414, 0,262, 0,264, 0,464,134,465, 0,431, 0, + 0, 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 64, + 0, 0,426,423, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0,426,423, + 0,280,282,322, 0,284,324, 0, 50,182, 0,320, 0, 0,186, 0, 0,424, + 422, 0,430, 0,418, 0,166, 54,426, 0,428,416, 58,420, 0,190,192,286, + 0,332,334, 0,338,340,342, 0,326,328,330, 0,336, 44,344, 0,194,306, + 0,288,308, 0,390,396, 0, 46,198, 0, 0, 56, 0, 0,196, 52, 62, 0, + 30, 0, 80, 14, 0, 18, 70, 0, 0, 68, 0, 0, 0, 34,202, 28, 0, 0, + 0,200,204, 0, 12, 0, 0, 4, 0, 6, 0, 0,290,310, 0, 22,346, 0, + 362, 0,368, 0,364,374,372,366,376, 0,380,382, 0,354,370, 0,352, 0, + 348,358,356,360, 0,378, 0,350,384, 0,270, 0,388,394, 0,386, 0,392, + 398, 0,210, 0,400,208,206, 0, 0, 0, 92, 10, 0,276,278, 0,442, 0, + 0, 0,444, 0,266, 84,312, 0, 72,292, 0, 94, 0, 82,314, 0, 88, 0, + 212, 0, 74, 0, 0,294, 48,402, 0, 0,404, 0, 38, 0, 36, 0, 0, 0, + 0, 0, 66,274, 0, 96,214,272, 0, 0, 0,216,218, 0,432, 0,226,228, + 0,234,236, 0,240,304,242, 0,244,188, 0,246, 0,318, 0, 0,220,230, + 222,224, 0,232, 0,238, 0, 0,248, 0,440,436, 0,296,438,406, 0,434, + 0,254, 0,408,252,184,250, 0, 0, 0,302,258,316, 0,268, 0,410,260, + 76, 0,298,412, 0, 0, 0,256, 0, 0, 0, 90, 0, 60, 86, 0,300,414, + 0,262, 0,264, 0,464,134,465, 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 16, 64, 0, 0,134, 0,126,138, 0,132, + 142, 0,130, 0, 0,134,230,128,144, 0,140,136, 0,124, 96,134, 0,426, + 423, 0, 0, 0, 14, 18, 0, 0, 12, 10, 16, 0,161,163,162, 0,426,423, + 0, 4, 0, 6, 0, 0, 0, 0, 0,437,134,425, 0, 0, 0, 0,425,465, + 0,426,423, 0, 54, 58, 0, 46, 0, 56, 52, 62, 0, 80, 14, 0, 18, 70, + 0, 0, 68, 0, 0, 0, 34, 0, 0, 0, 0, 4, 0, 6, 0, 0, 0, 0, + 0, 92, 10, 0, 0, 84, 0, 94, 72, 82, 0, 74, 88, 0, 38, 0, 36, 0, + 0, 0, 0, 0, 96, 0, 66, 0, 2, 76, 90, 0, 60, 86, 0,464, 0, 0, + 50, 0, 44, 0, 0, 78, 12, 0, 0, 0, 0, 48, 0, 0, 0, 16, 64,460, + 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0,425,426, 0,426,423, 0,425, + 0,460, 0,426,423, 0, 0, 98, 96, 0,426,423, 0,180, 0, 0,166, 0, + 168,176, 0,170, 0,150,154,158,178,172, 0,240,164,150,152,154,156,158, + 160,162, 0,166, 0,168, 0,170, 0,150,154,158,172, 0,166, 0,168, 0, + 170, 0,164,150,154,158,174, 0,166, 0,168, 0,150,154, 0,497, 0,426, + 423, 0,512,501, 0,495, 0,499,514, 0,180,522,492, 0,505,431,503, 0, + 497, 0,426,423, 0,512,501, 0,495, 0,499,514, 0,104,108, 0,106,110, + 0,118,120, 0, 0, 0,180,522,492, 0,505,431,503,116,100, 0, 0,122, + 102,112, 0,114, 0, 54, 58, 0, 46, 0, 56, 52, 62, 0, 80, 14, 0, 18, + 70, 0, 0, 68, 0, 0, 0, 34, 0, 0, 0, 92, 10, 0, 0, 84, 0, 94, 72, 82, 0, 74, 88, 0, 38, 0, 36, 0, 0, 0, 0, 0, 96, 0, 66, 0, - 2, 76, 90, 0, 60, 86, 0,465, 0, 0, 50, 0, 44, 0, 0, 78, 12, 0, - 0, 0, 0, 48, 0, 0, 0, 16, 64,461, 0, 4, 0, 6, 0, 0, 0, 0, - 0, 0, 0,426,427, 0,427,424, 0,426, 0,461, 0,427,424, 0, 0,100, - 96, 0,427,424, 0,182, 0, 0,168, 0,170,178, 0,172, 0,152,156,160, - 180,174, 0,241,166,152,154,156,158,160,162,164, 0,168, 0,170, 0,172, - 0,152,156,160,174, 0,168, 0,170, 0,172, 0,166,152,156,160,176, 0, - 168, 0,170, 0,152,156, 0,498, 0,427,424, 0,513,502, 0,496, 0,500, - 515, 0,182,523,493, 0,506,432,504, 0,498, 0,427,424, 0,513,502, 0, - 496, 0,500,515, 0,106,110, 0,108,112, 0,120,122, 0, 0, 0,182,523, - 493, 0,506,432,504,118,102, 0, 0,124,104,114, 0,116, 0, 54, 58, 0, - 46, 0, 56, 52, 62, 0, 80, 14, 0, 18, 70, 0, 0, 68, 0, 0, 0, 34, - 0, 0, 0, 92, 10, 0, 0, 84, 0, 94, 72, 82, 0, 74, 88, 0, 38, 0, - 36, 0, 0, 0, 0, 0, 96, 0, 66, 0, 76, 90, 0, 60, 86, 0,465,466, - 50, 0, 44, 0, 0, 78, 12, 0, 0, 0, 48, 0, 0, 0, 16, 64, 0,427, - 424, 0,493, 0, 0,498, 0,427,424, 0,513,502, 0,496, 0,500,515, 0, - 106,110, 0,108,112, 0,114, 0,120,122, 0, 0, 0,182,523,493, 0,506, - 432,504,118,102, 0, 0,124,104,150,148, 0,116, 0,233, 0,498, 0,427, - 424, 0,513,502, 0,496, 0,500,515, 0,106,110, 0,108,112, 0,114, 0, - 120,122, 0, 0, 0,182,523,493, 0,506,432,504, 0, 0,124,104,150,148, - 0,116, 0,427,424, 0,128,140, 0,134,144, 0,132, 0, 0, 98,135,231, - 426, 0,130,146, 0,142,138, 0,126, 96,136,461, 0,128,140, 0,134,144, - 0,132, 0, 0, 98,135,231,130,146, 0,142,138, 0, 96,136, 0,427,424, - 0,128,140, 0,134,144, 0,132, 0, 0, 98,135,231,426, 0,130,146, 0, - 142,138, 0, 96,136,461, 0,498, 0,513,502, 0,496, 0,500,515, 0,106, - 110, 0,108,112, 0,120,122, 0, 0, 0,182,523,493,506,432,504,118,102, - 0, 0,124,104,114, 0,116, 0,498, 0,427,424, 0,513,502, 0,496, 0, - 500,515, 0,106,110, 0,108,112, 0,120,122, 0, 0, 0,182,493, 0,506, - 432,504,118,102, 0, 0,104,114, 0,116, 0,498, 0,427,424, 0,502, 0, - 496, 0,500, 0,106,110, 0,108,112, 0,182,493, 0,506,432,504,118,102, - 0, 0,104,114,116, 0,498, 0,427,424, 0,502, 0,496, 0,500, 0,106, - 110, 0,108,112, 0,182,493, 0,506,432,504,102, 0, 0,104,114,116, 0, - 498, 0,427,424, 0,502, 0,496, 0,500, 0,106,110, 0,108,112, 0,182, - 493, 0,506,432,504,102, 0, 0,104,114, 0,427,424, 0,502, 0,496, 0, - 500, 0,106,110, 0,108,112, 0,498, 0,506,432,504,102, 0, 0,104, 0, - 498, 0,523,426, 0,427,424, 0,513,502, 0,496, 0,500,515, 0,106,110, - 0,108,112, 0,120,122, 0, 0, 0,182, 0,493, 0,506,432,504,118,102, - 0, 0,124,104,114, 0,116,461, 0, 54, 58, 0, 46, 0, 56, 52, 62, 0, - 80, 14, 0, 18, 70, 0, 0, 68, 0, 0, 0, 34, 0, 0, 0, 0, 92, 10, - 0, 0, 84, 0, 94, 72, 82, 0, 74, 88, 0, 38, 0, 36, 0, 0, 0, 0, - 0, 96, 0, 66, 0, 2, 76, 90, 0, 60, 86, 0,465,466, 50, 0, 44, 0, - 0, 78, 12, 0, 0, 0, 48, 0, 0, 0, 16, 64, 0,231, 0,282,284,324, - 0,286,326, 0,322, 0, 0,188,184, 0,426,424, 0,432, 0,420, 0,168, - 428, 0,430,418,422, 0,192,194,288, 0,334,336, 0,340,342,344, 0,328, - 330,332, 0,338,346, 0,196,308, 0,290,310, 0,392,398, 0, 0, 0, 0, - 198,200, 0,202,206, 0, 0, 0,292,312, 0,348, 0,364, 0,370, 0,366, - 376,374,368,378, 0,382,384, 0,356,372, 0,354, 0,350,360,358,362, 0, - 380, 0,352,386, 0,272, 0,390,396, 0,388, 0,394,400, 0,212, 0,402, - 210,208, 0, 0, 0,278,280, 0,444, 0, 0,446, 0,268,314, 0,294,316, - 0,296,404, 0, 0,406, 0,216,274,276, 0,218,220, 0,434, 0,228,230, - 0,236,238, 0,242,306,244, 0,246,190, 0,248, 0,320, 0, 0,222,232, - 224,226, 0,234, 0,240, 0, 0,250, 0,442,438, 0,298,440,408, 0,436, - 0,256, 0,410,254,186,252, 0, 0, 0,304,260,318, 0,270, 0,412,262, - 0,300,414, 0, 0, 0,258, 0, 0, 0, 0,302,416, 0,264, 0,266, 0, - 0, 0, 0, 0,204, 0, 0, 0, 0, 0,214, 0, 0, 0, 0, 0, 0,427, - 424, 0, 98,135, 0, 0,427,424, 0,182,493, 0, 0,493, 0,427,424, 0, - 0,150,148, 0,461, 0,130, 0,146, 0,128,140, 0,142, 0,134,144, 0, - 132, 0, 0, 98,135,231,241,166,152,154,156,158, 0,160,138,162,164,126, - 96,136, 0,182, 0,427,424, 0, 0,461, 0 + 76, 90, 0, 60, 86, 0,464,465, 50, 0, 44, 0, 0, 78, 12, 0, 0, 0, + 48, 0, 0, 0, 16, 64, 0,426,423, 0,492, 0, 0,497, 0,426,423, 0, + 512,501, 0,495, 0,499,514, 0,104,108, 0,106,110, 0,112, 0,118,120, + 0, 0, 0,180,522,492, 0,505,431,503,116,100, 0, 0,122,102,148,146, + 0,114, 0,232, 0,497, 0,426,423, 0,512,501, 0,495, 0,499,514, 0, + 104,108, 0,106,110, 0,112, 0,118,120, 0, 0, 0,180,522,492, 0,505, + 431,503, 0, 0,122,102,148,146, 0,114, 0,426,423, 0,126,138, 0,132, + 142, 0,130, 0, 0,134,230,425, 0,128,144, 0,140,136, 0,124, 96,134, + 460, 0,497, 0,426,423, 0,512,501, 0,495, 0,499,514, 0,104,108, 0, + 106,110, 0,118,120, 0, 0, 0,180,522,492, 0,505,431,503, 0, 0,122, + 102,112, 0,114, 0,126,138, 0,132,142, 0,130, 0, 0,134,230,128,144, + 0,140,136, 0, 96,134, 0,426,423, 0,126,138, 0,132,142, 0,130, 0, + 0,134,230,425, 0,128,144, 0,140,136, 0, 96,134,460, 0,497, 0,512, + 501, 0,495, 0,499,514, 0,104,108, 0,106,110, 0,118,120, 0, 0, 0, + 180,522,492,505,431,503,116,100, 0, 0,122,102,112, 0,114, 0,497, 0, + 426,423, 0,512,501, 0,495, 0,499,514, 0,104,108, 0,106,110, 0,118, + 120, 0, 0, 0,180,492, 0,505,431,503,116,100, 0, 0,102,112, 0,114, + 0,497, 0,426,423, 0,501, 0,495, 0,499, 0,104,108, 0,106,110, 0, + 180,492, 0,505,431,503,116,100, 0, 0,102,112,114, 0,497, 0,426,423, + 0,501, 0,495, 0,499, 0,104,108, 0,106,110, 0,180,492, 0,505,431, + 503,100, 0, 0,102,112,114, 0,497, 0,426,423, 0,501, 0,495, 0,499, + 0,104,108, 0,106,110, 0,180,492, 0,505,431,503,100, 0, 0,102,112, + 0,426,423, 0,501, 0,495, 0,499, 0,104,108, 0,106,110, 0,497, 0, + 505,431,503,100, 0, 0,102, 0,497, 0,522,425, 0,426,423, 0,512,501, + 0,495, 0,499,514, 0,104,108, 0,106,110, 0,118,120, 0, 0, 0,180, + 0,492, 0,505,431,503,116,100, 0, 0,122,102,112, 0,114,460, 0, 54, + 58, 0, 46, 0, 56, 52, 62, 0, 80, 14, 0, 18, 70, 0, 0, 68, 0, 0, + 0, 34, 0, 0, 0, 0, 92, 10, 0, 0, 84, 0, 94, 72, 82, 0, 74, 88, + 0, 38, 0, 36, 0, 0, 0, 0, 0, 96, 0, 66, 0, 2, 76, 90, 0, 60, + 86, 0,464,465, 50, 0, 44, 0, 0, 78, 12, 0, 0, 0, 48, 0, 0, 0, + 16, 64, 0,230, 0,280,282,322, 0,284,324, 0,320, 0, 0,186,182, 0, + 424,422, 0,430, 0,418, 0,166,426, 0,428,416,420, 0,190,192,286, 0, + 332,334, 0,338,340,342, 0,326,328,330, 0,336,344, 0,194,306, 0,288, + 308, 0,390,396, 0, 0, 0, 0,196,198, 0,200,204, 0, 0, 0,290,310, + 0,346, 0,362, 0,368, 0,364,374,372,366,376, 0,380,382, 0,354,370, + 0,352, 0,348,358,356,360, 0,378, 0,350,384, 0,270, 0,388,394, 0, + 386, 0,392,398, 0,210, 0,400,208,206, 0, 0, 0,276,278, 0,442, 0, + 0,444, 0,266,312, 0,292,314, 0,294,402, 0, 0,404, 0,214,272,274, + 0,216,218, 0,432, 0,226,228, 0,234,236, 0,240,304,242, 0,244,188, + 0,246, 0,318, 0, 0,220,230,222,224, 0,232, 0,238, 0, 0,248, 0, + 440,436, 0,296,438,406, 0,434, 0,254, 0,408,252,184,250, 0, 0, 0, + 302,258,316, 0,268, 0,410,260, 0,298,412, 0, 0, 0,256, 0, 0, 0, + 0,300,414, 0,262, 0,264, 0, 0, 0, 0, 0,202, 0, 0, 0, 0, 0, + 212, 0, 0, 0, 0, 0, 0,426,423, 0,134, 0, 0,426,423, 0,180,492, + 0, 0,492, 0,426,423, 0, 0,148,146, 0,460, 0,128, 0,144, 0,126, + 138, 0,140, 0,132,142, 0,130, 0, 0,134,230,240,164,150,152,154,156, + 0,158,136,160,162,124, 96,134, 0,180, 0,426,423, 0, 0,460, 0 }; static const unsigned short ag_key_jmp[] = { 0, 0, 3, 7, 0, 0, 0, 0, 11, 0, 8, 0, 10, 0, 12, 0, 0, 0, - 0, 1, 5, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 24, 28, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 37, 39, 0, 32, 46, 50, 34, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, - 0, 63, 66, 68, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 48, 0, 51, 79, 83, 86, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, - 0,107, 0,109, 0,111, 57, 59, 0, 61, 63, 0, 99, 0,102,113, 0,117, - 0, 0, 0, 68, 70, 0, 72, 0,132, 74, 0, 0, 0, 81, 85, 0,139, 87, - 0,142, 0, 65, 0,129,134,137, 77,145, 0, 89, 92, 0, 0, 0, 0, 0, - 101, 0, 0, 96, 98,162, 0,104,107, 0,111, 0,172, 0,174,114, 0, 0, - 0,169,176, 0, 0, 0, 0, 0, 0, 0, 0, 0,187, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,185,189,195,198,201, 0, 0, 0, 0, 0, - 0, 0,213,215,122,124, 0, 0, 0,223, 0, 0, 0,225, 0,126,128, 0, - 0, 0, 0,133,135, 0,118,218, 0,229,231,130, 0,234,237,138,141, 0, - 147, 0,154, 0,254, 0, 0,149,256,157,163, 0,168, 0,264, 0, 0,165, - 0,266, 0, 0, 0, 0, 0,273,171, 0,176, 0, 0, 0,282, 0,284, 0, - 180,286, 0,186,190, 0,173,280,178,288,184,291, 0, 0, 0, 0,192, 0, - 0,202, 0, 0, 0, 0, 0, 0, 0, 0, 0,204, 0, 0, 0,319, 0,301, - 304,195,198,200,306, 0,309,312,316,321, 0, 0, 0, 0, 0, 0, 0, 0, - 336, 0, 0, 0, 0,345, 0, 0, 0, 0,347, 0, 0, 0,210, 0, 0, 0, - 0,359, 0,215, 0, 0, 0, 0,339,206,352,208,355,212,361,365,218, 0, - 220,223, 0, 0, 0, 0,243,246,381,248, 0, 23, 0, 25, 0, 14, 17, 27, - 0, 31, 35, 38, 41, 43, 57, 70, 90,120,147,155,159,165,181,203,240,259, - 269,277,294,323,368,378,227,232,239,384,251, 0,253,256,260, 0, 0, 0, - 0, 0, 0, 0,426,430, 0,273,275, 0,270,439,277,281, 0,285,288, 0, - 447,292, 0, 0, 0,453, 0,455, 0,298,457, 0,459, 0,264,442,450,462, - 302, 0, 0, 0, 0, 0,307,470, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,316,318, 0,311,484,488,313,491, 0, 0, 0, 0, 0, - 0, 0, 0, 0,320, 0,500,503,505,324, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,327, 0,516,520,523,330, 0, 0, 0, 0, 0, 0, 0, - 0,333,335, 0,337,339, 0,535, 0,538,541, 0,544, 0, 0,347, 0,555, - 349, 0,354,358, 0,560,360, 0,563, 0,341, 0,344,557,352,566, 0,368, - 0, 0,366,575, 0, 0, 0, 0, 0,581, 0, 0, 0, 0, 0, 0, 0, 0, - 589, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,587,591,597,600, - 603, 0, 0, 0, 0, 0, 0, 0,615,617,375,377, 0, 0, 0,625, 0, 0, - 0,627, 0,379,381, 0,386,388, 0,371,620,631,633,383,636,391,394,400, - 0,407, 0, 0,402,649,411,417, 0,422, 0,657, 0,419,659, 0, 0, 0, - 0, 0,664,425, 0, 0, 0,671, 0,673, 0,675, 0,435,439, 0,427,430, - 433,677,679, 0, 0, 0, 0,441, 0, 0,451, 0, 0, 0, 0, 0, 0, 0, - 0, 0,453, 0, 0, 0,706, 0,688,691,444,447,449,693, 0,696,699,703, - 708, 0, 0, 0, 0, 0, 0, 0, 0,723, 0, 0, 0, 0,732, 0, 0, 0, - 0,734, 0, 0,459, 0, 0, 0, 0,745, 0,461, 0, 0, 0, 0,726,455, - 739,457,741,747,751,464, 0,466,469, 0, 0, 0, 0,484,766,487, 0,479, - 0,309,481, 0,494,507,527,547,568,362,578,584,605,639,652,661,668,682, - 710,754,763,473,480,769, 0, 0, 0, 0,490, 0,802, 0,804, 0,806, 0, - 799,808, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,500,502, 0, - 495,818,822,497,825, 0, 0, 0, 0, 0, 0, 0, 0, 0,504, 0,834,837, - 839,508, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,511, 0,850, - 854,857,514, 0, 0, 0, 0, 0, 0, 0, 0,517,519, 0,521,523, 0,869, - 0,872,875, 0,878, 0, 0,531, 0,889,533, 0,536,540, 0,894,542, 0, - 897, 0,525, 0,528,891,900, 0,550, 0, 0,548,908, 0,553, 0,914, 0, - 916, 0, 0, 0, 0,918, 0, 0, 0, 0, 0, 0, 0, 0,927, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,925,929,935,938,941, 0, 0, 0, - 0, 0, 0, 0,953,955,560,562, 0, 0, 0,963, 0, 0, 0,965, 0,564, - 566, 0,571,573, 0,556,958,969,971,568,974,576,579,585, 0,592, 0, 0, - 587,987,596,602, 0,607, 0,995, 0,604,997, 0, 0, 0, 0, 0,1002,610, - 0, 0, 0,1009, 0,1011, 0,1013, 0,620,624, 0,612,615,618,1015,1017, - 0, 0, 0, 0,626, 0, 0,636, 0, 0, 0, 0, 0, 0, 0, 0, 0,638, - 0, 0, 0,1044, 0,1026,1029,629,632,634,1031, 0,1034,1037,1041,1046, - 0, 0, 0, 0, 0, 0, 0, 0,1061, 0, 0, 0, 0,1070, 0, 0, 0, - 0,1072, 0, 0,642, 0, 0, 0, 0,1083, 0,644, 0, 0, 0, 0,1064, - 1077,640,1079,1085,1089,647, 0,649,652, 0, 0, 0, 0,667,1103,670, 0, - 813, 0,493,815,828,841,861,881,902,544,911,922,943,977,990,999,1006,1020, - 1048,1092,1100,656,663,1106, 0, 0, 0, 0,687, 0, 0, 0, 0, 0, 0, - 1141, 0, 0, 0,673,676,680,1138,691,695,1144,697,700,704, 0, 0, 0, - 0,1160, 0,708,712, 0,1165,719,722,726, 0,735,738,742, 0, 0, 0, - 0,746, 0,1180, 0,1182, 0,1184, 0, 0, 0, 0,733,1173,1177,1186, - 0, 0, 0, 0, 0, 0, 0,755,759, 0,766, 0, 0,1205, 0, 0, 0,771, - 0,776,780, 0,1214,782, 0,1217, 0,768,1211,774,1220, 0,791, 0,1227, - 0,1229, 0,1231, 0,794,796, 0,1235,798, 0,804,809,814, 0,820,823, - 0, 0, 0,1248, 0,1250, 0,1252, 0,831,1254,834, 0,839,841,845, 0, - 847,850, 0,749,1196,1199,751,1202,762,1207,1222,784,788,1233,1238,1241, - 1245,828,1256,1260,1264,854,861,865, 0,867, 0,1289, 0,1291, 0,1293, - 0,1295, 0,870,872, 0, 0, 0, 0,874,1302,876, 0, 0, 0, 0,1309, - 878,884, 0, 0, 0, 0, 0,1316, 0, 0, 0, 0, 0, 0, 0, 0,1322, - 1324,1327,888,890, 0,892, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,1345,1347,1349,896, 0, 0, 0, 0, 0, 0, 0, 0,1356, - 1358,1360,898, 0, 0, 0, 0, 0,1368,1370, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,1375,901, 0,1377,1380,1383,1385, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,1415, 0,1396,903, 0,1398,1401,1404,1406,905,908,1409,1412,910, - 913,915,1418,917, 0,928,932, 0,939, 0, 0,1440, 0, 0, 0,944, 0, - 947,951, 0,1449,953, 0,1452, 0,941,1446,1455, 0,962,964, 0,1461,966, - 0,972,977,982, 0,988,991, 0, 0, 0,1474, 0,1476, 0,1478, 0,999, - 1480,1002, 0,1007,1011, 0,1013,1016, 0,920,922,924,1437,935,1442,1457, - 955,959,1464,1467,1471,996,1482,1486,1489,1020,1027, 0, 0, 0, 0, 0, - 1511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1538, 0,1517,1031, 0,1519,1522,1525, - 1527,1033,1036,1530,1533,1038,1041,1536, 0,1541,1043, 0,1046, 0, 0, + 1, 5, 14, 0, 0, 0, 0, 0, 0, 0, 23, 26, 30, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 41, 0, + 34, 43, 47, 36, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 0, 60, 63, + 65, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, 53, + 76, 80, 83, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102, 0,104, 0, + 106, 0,108, 59, 61, 0, 63, 65, 0, 96, 0, 99,110, 0,114, 0, 0, 0, + 70, 72, 0, 74, 0,129, 76, 0, 0, 0, 83, 87, 0,136, 89, 0,139, 0, + 67, 0,126,131,134, 79,142, 0, 91, 94, 0, 0, 0, 0, 0,103, 0, 0, + 98,100,159, 0,106,109, 0,113, 0,169, 0,171,116, 0, 0, 0,166,173, + 0, 0, 0, 0, 0, 0, 0, 0, 0,184, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,182,186,192,195,198, 0, 0, 0, 0, 0, 0, 0,210, + 212,124,126, 0, 0, 0,220, 0, 0, 0,222, 0,128,130, 0, 0, 0, 0, + 135,137, 0,120,215, 0,226,228,132, 0,231,234,140,143, 0,149, 0,156, + 0,251, 0, 0,151,253,159,165, 0,170, 0,261, 0, 0,167, 0,263, 0, + 0, 0, 0, 0,270,173, 0,178, 0, 0, 0,279, 0,281, 0,182,283, 0, + 188,192, 0,175,277,180,285,186,288, 0, 0, 0, 0,194, 0, 0,204, 0, + 0, 0, 0, 0, 0, 0, 0, 0,206, 0, 0, 0,316, 0,298,301,197,200, + 202,303, 0,306,309,313,318, 0, 0, 0, 0, 0, 0, 0, 0,333, 0, 0, + 0, 0,342, 0, 0, 0, 0,344, 0, 0, 0,212, 0, 0, 0, 0,356, 0, + 217, 0, 0, 0, 0,336,208,349,210,352,214,358,362,220, 0,222,225, 0, + 0, 0, 0,245,248,378,250, 0, 22, 0, 14, 0, 16, 19, 24, 0, 28, 32, + 35, 38, 40, 54, 67, 87,117,144,152,156,162,178,200,237,256,266,274,291, + 320,365,375,229,234,241,381,253, 0,255,258,262, 0, 0, 0, 0, 0, 0, + 423,427, 0,275,277, 0,272,435,279,283, 0,287,290, 0,443,294, 0, 0, + 0,449, 0,451, 0,300,453, 0,455, 0,266,438,446,458,304, 0, 0, 0, + 0,309, 0,311,466, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 322,324, 0,317,479,483,319,486, 0, 0, 0, 0, 0, 0, 0, 0, 0,326, + 0,495,498,500,330, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 333, 0,511,515,518,336, 0, 0, 0, 0, 0, 0, 0, 0,339,341, 0,343, + 345, 0,530, 0,533,536, 0,539, 0, 0,353, 0,550,355, 0,360,364, 0, + 555,366, 0,558, 0,347, 0,350,552,358,561, 0,374, 0, 0,372,570, 0, + 0, 0, 0, 0,576, 0, 0, 0, 0, 0, 0, 0, 0,584, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,582,586,592,595,598, 0, 0, 0, 0, + 0, 0, 0,610,612,381,383, 0, 0, 0,620, 0, 0, 0,622, 0,385,387, + 0,392,394, 0,377,615,626,628,389,631,397,400,406, 0,413, 0, 0,408, + 644,417,423, 0,428, 0,652, 0,425,654, 0, 0, 0, 0, 0,659,431, 0, + 0, 0,666, 0,668, 0,670, 0,441,445, 0,433,436,439,672,674, 0, 0, + 0, 0,447, 0, 0,457, 0, 0, 0, 0, 0, 0, 0, 0, 0,459, 0, 0, + 0,701, 0,683,686,450,453,455,688, 0,691,694,698,703, 0, 0, 0, 0, + 0, 0, 0, 0,718, 0, 0, 0, 0,727, 0, 0, 0, 0,729, 0, 0,465, + 0, 0, 0, 0,740, 0,467, 0, 0, 0, 0,721,461,734,463,736,742,746, + 470, 0,472,475, 0, 0, 0, 0,490,761,493, 0,313, 0,315,476, 0,489, + 502,522,542,563,368,573,579,600,634,647,656,663,677,705,749,758,479,486, + 764, 0, 0, 0, 0,496, 0,797, 0,799, 0,801, 0,794,803, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,508,510, 0,503,811,815,505,818, 0, 0, + 0, 0, 0, 0, 0, 0, 0,512, 0,827,830,832,516, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,519, 0,843,847,850,522, 0, 0, 0, 0, + 0, 0, 0, 0,525,527, 0,529,531, 0,862, 0,865,868, 0,871, 0, 0, + 539, 0,882,541, 0,544,548, 0,887,550, 0,890, 0,533, 0,536,884,893, + 0,558, 0, 0,556,901, 0,561, 0,907, 0,909, 0, 0, 0, 0,911, 0, + 0, 0, 0, 0, 0, 0, 0,920, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,918,922,928,931,934, 0, 0, 0, 0, 0, 0, 0,946,948,568, + 570, 0, 0, 0,956, 0, 0, 0,958, 0,572,574, 0,579,581, 0,564,951, + 962,964,576,967,584,587,593, 0,600, 0, 0,595,980,604,610, 0,615, 0, + 988, 0,612,990, 0, 0, 0, 0, 0,995,618, 0, 0, 0,1002, 0,1004, + 0,1006, 0,628,632, 0,620,623,626,1008,1010, 0, 0, 0, 0,634, 0, + 0,644, 0, 0, 0, 0, 0, 0, 0, 0, 0,646, 0, 0, 0,1037, 0,1019, + 1022,637,640,642,1024, 0,1027,1030,1034,1039, 0, 0, 0, 0, 0, 0, + 0, 0,1054, 0, 0, 0, 0,1063, 0, 0, 0, 0,1065, 0, 0,650, 0, + 0, 0, 0,1076, 0,652, 0, 0, 0, 0,1057,1070,648,1072,1078,1082, + 655, 0,657,660, 0, 0, 0, 0,675,1096,678, 0,499, 0,501,808,821,834, + 854,874,895,552,904,915,936,970,983,992,999,1013,1041,1085,1093,664,671, + 1099, 0, 0, 0,695, 0, 0, 0, 0, 0, 0,1133, 0, 0,681,684,688, + 1130,699,703,1136,705,708,712, 0, 0, 0, 0,1151, 0,716,720, 0,1156, + 727,730,734, 0,743,746,750, 0, 0, 0, 0,754, 0,1171, 0,1173, 0, + 1175, 0, 0, 0,741,1164,1168,1177, 0, 0, 0, 0, 0, 0, 0,763,767, + 0,774, 0, 0,1195, 0, 0, 0,779, 0,784,788, 0,1204,790, 0,1207, + 0,776,1201,782,1210, 0,799, 0,1217, 0,1219, 0,1221, 0,802,804, 0, + 1225,806, 0,812,817,822, 0,828,831, 0, 0, 0,1238, 0,1240, 0,1242, + 0,839,1244,842, 0,847,849,853, 0,855,858, 0,757,1186,1189,759,1192, + 770,1197,1212,792,796,1223,1228,1231,1235,836,1246,1250,1254,862,869,873, + 0,875, 0,1279, 0,1281, 0,1283, 0,1285, 0,878,880, 0, 0, 0, 0, + 882,1292,884, 0, 0, 0, 0,1299,886,892, 0, 0, 0, 0, 0,1306, 0, + 0, 0, 0, 0, 0, 0, 0,1312,1314,1317,896,898, 0,900, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1335,1337,1339,904, 0, + 0, 0, 0, 0, 0, 0, 0,1346,1348,1350,906, 0, 0, 0, 0, 0,1358, + 1360, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1365,909, + 0,1367,1370,1373,1375, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1405, 0,1386,911, 0,1388, + 1391,1394,1396,913,916,1399,1402,918,921,923,1408,925, 0,936,940, 0, + 947, 0, 0,1430, 0, 0, 0,952, 0,955,959, 0,1439,961, 0,1442, 0, + 949,1436,1445, 0,970,972, 0,1451,974, 0,980,985,990, 0,996,999, 0, + 0, 0,1464, 0,1466, 0,1468, 0,1007,1470,1010, 0,1015,1019, 0,1021, + 1024, 0,928,930,932,1427,943,1432,1447,963,967,1454,1457,1461,1004,1472, + 1476,1479,1028,1035, 0, 0, 0, 0, 0,1501, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,1584, 0,1563,1048, 0,1565,1568,1571,1573,1576,1579, - 1050,1053,1582, 0,1587,1055, 0, 0, 0, 0,1074, 0, 0, 0, 0, 0, - 0,1611, 0, 0, 0,1058,1061,1605,1063,1067,1608,1078,1082,1614,1084, - 1087,1091,1095, 0,1111, 0, 0, 0, 0, 0, 0,1636, 0, 0, 0,1097, - 1100,1104,1633,1115,1119,1639,1121,1125, 0, 0, 0, 0,1145, 0, 0, 0, - 0, 0, 0,1660, 0, 0, 0,1129,1132,1654,1134,1138,1657,1149,1153,1663, - 1155,1159,1163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1697, 0,1681,1165, 0,1683,1686,1688,1167,1170, - 1691,1694,1172,1175,1177,1700,1179, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1737, 0,1718, - 0,1720,1723,1726,1728,1182,1185,1731,1734,1187,1189,1740,1191, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1757, 0, - 1759,1762,1764,1766,1194,1197,1768,1771,1199,1201,1203, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1788, 0,1790, - 1793,1795,1797,1206,1799,1802,1208,1210,1212, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1818, 0,1820,1823,1825,1827, - 1215,1829,1832,1217,1219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,1221,1847,1850,1852,1854,1223,1856,1859,1225, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,1894, 0,1872,1874, 0,1877,1880,1883,1885,1227,1230, - 1888,1891,1232,1235,1237,1897,1239,1242, 0,1252,1256, 0,1263, 0, 0, - 1920, 0, 0, 0,1268, 0,1273,1277, 0,1929,1279, 0,1932, 0,1265,1926, - 1271,1935, 0,1288,1290, 0,1942,1292, 0,1298,1303,1308, 0,1314,1317, - 0, 0, 0,1955, 0,1957, 0,1959, 0,1325,1961,1328, 0,1333,1335,1339, - 0,1341,1344, 0,1244,1246,1248,1917,1259,1922,1937,1281,1285,1945,1948, - 1952,1322,1963,1967,1971,1348,1355, 0,1359, 0, 0, 0, 0, 0, 0, 0, - 0,1362,1995,1999,1364,1367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2008, - 2011,2013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1370, 0, - 2022,2026,2029, 0, 0, 0, 0, 0, 0, 0, 0,1373,1375, 0,2040,2043, - 2046, 0,1377, 0,1382, 0, 0,2055, 0, 0, 0, 0,2060, 0, 0, 0, 0, - 0, 0, 0, 0,2067, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2065,2069,2075,2078,2081, 0, 0, 0, 0, 0, 0, 0,2093,2095,1389,1391, - 0, 0, 0,2103, 0, 0, 0,2105, 0,1396,1398, 0,1385,2098,2109,1393, - 2111,1401,1404, 0,1406,1408, 0, 0, 0, 0,2125,1413, 0,1415,1418,1420, - 0, 0, 0, 0,1423, 0, 0,1433, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1435, 0, 0, 0,2153, 0,2135,2138,1426,1429,1431,2140, 0,2143,2146, - 2150,2155, 0, 0, 0, 0, 0, 0, 0, 0,2170, 0, 0, 0, 0,2179, 0, - 0, 0, 0,2181, 0, 0,1439, 0, 0, 0, 0,2192, 0, 0, 0, 0, 0, - 2173,2186,1437,2188,2194,2197, 0, 0, 0, 0,1441,2207,1444, 0,2002, - 2015,2033,2049,1380,2058,2063,2083,2114,2122,1410,2128,2131,2157,2200, - 2210, 0, 0, 0, 0, 0, 0,2231, 0, 0, 0, 0, 0, 0,2238, 0, 0, - 0, 0, 0, 0,2247, 0, 0, 0,1447, 0,1456, 0,1459, 0,1465, 0, 0, - 1469, 0, 0, 0, 0, 0,2265, 0, 0, 0,1449,1452, 0, 0,2256,2258, - 0,2260,2263,1472,2268, 0,1474,1477,1481, 0, 0, 0, 0, 0, 0,2291, - 1485, 0 + 1528, 0,1507,1039, 0,1509,1512,1515,1517,1041,1044,1520,1523,1046,1049, + 1526, 0,1531,1051, 0,1054, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1574, 0,1553, + 1056, 0,1555,1558,1561,1563,1566,1569,1058,1061,1572, 0,1577,1063, 0, + 0, 0, 0,1082, 0, 0, 0, 0, 0, 0,1601, 0, 0,1066,1069,1595,1071, + 1075,1598,1086,1090,1604,1092,1095,1099,1103, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1641, 0, + 1622,1105, 0,1624,1627,1630,1632,1635,1638,1107,1110,1112,1644,1114, 0, + 1131, 0, 0, 0, 0, 0, 0,1664, 0, 0,1117,1120,1124,1661,1135,1139, + 1667,1141,1145, 0, 0, 0, 0,1165, 0, 0, 0, 0, 0, 0,1687, 0, 0, + 1149,1152,1681,1154,1158,1684,1169,1173,1690,1175,1179,1183, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1723, + 0,1707,1185, 0,1709,1712,1714,1187,1190,1717,1720,1192,1195,1197,1726, + 1199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1763, 0,1744, 0,1746,1749,1752,1754,1202,1205, + 1757,1760,1207,1209,1766,1211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1783, 0,1785,1788,1790,1792,1214,1217, + 1794,1797,1219,1221,1223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1814, 0,1816,1819,1821,1823,1226,1825,1828,1228, + 1230,1232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1844, 0,1846,1849,1851,1853,1235,1855,1858,1237,1239, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1241,1873, + 1876,1878,1880,1243,1882,1885,1245, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1920, + 0,1898,1900, 0,1903,1906,1909,1911,1247,1250,1914,1917,1252,1255,1257, + 1923,1259,1262, 0,1272,1276, 0,1283, 0, 0,1946, 0, 0, 0,1288, 0, + 1293,1297, 0,1955,1299, 0,1958, 0,1285,1952,1291,1961, 0,1308,1310, + 0,1968,1312, 0,1318,1323,1328, 0,1334,1337, 0, 0, 0,1981, 0,1983, + 0,1985, 0,1345,1987,1348, 0,1353,1355,1359, 0,1361,1364, 0,1264, + 1266,1268,1943,1279,1948,1963,1301,1305,1971,1974,1978,1342,1989,1993, + 1997,1368,1375, 0,1379, 0, 0, 0, 0, 0, 0, 0, 0,1382,2021,2025, + 1384,1387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2034,2037,2039, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1390, 0,2048,2052,2055, 0, + 0, 0, 0, 0, 0, 0, 0,1393,1395, 0,2066,2069,2072, 0,1397, 0, + 1402, 0, 0,2081, 0, 0, 0, 0,2086, 0, 0, 0, 0, 0, 0, 0, 0, + 2093, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,2091,2095,2101, + 2104,2107, 0, 0, 0, 0, 0, 0, 0,2119,2121,1409,1411, 0, 0, 0, + 2129, 0, 0, 0,2131, 0,1416,1418, 0,1405,2124,2135,1413,2137,1421, + 1424, 0,1426,1428, 0, 0, 0, 0,2151,1433, 0,1435,1438,1440, 0, 0, + 0, 0,1443, 0, 0,1453, 0, 0, 0, 0, 0, 0, 0, 0, 0,1455, 0, + 0, 0,2179, 0,2161,2164,1446,1449,1451,2166, 0,2169,2172,2176,2181, + 0, 0, 0, 0, 0, 0, 0, 0,2196, 0, 0, 0, 0,2205, 0, 0, 0, + 0,2207, 0, 0,1459, 0, 0, 0, 0,2218, 0, 0, 0, 0, 0,2199,2212, + 1457,2214,2220,2223, 0, 0, 0, 0,1461,2233,1464, 0,2028,2041,2059, + 2075,1400,2084,2089,2109,2140,2148,1430,2154,2157,2183,2226,2236, 0, 0, + 0, 0, 0,2257, 0, 0, 0, 0, 0, 0,2263, 0, 0, 0, 0, 0, 0, + 2272, 0, 0, 0,1467, 0,1476, 0,1479, 0,1485, 0, 0,1489, 0, 0, + 0, 0, 0,2290, 0, 0,1469,1472, 0, 0,2281,2283, 0,2285,2288,1492, + 2293, 0,1494,1497,1501, 0, 0, 0, 0, 0, 0,2315,1505, 0 }; static const unsigned short ag_key_index[] = { - 16,389,433,464,473,464,773, 0,810,773,1110,433,1135,1135, 0, 0,1147, - 0,1163,1163,1135,1147,1147,1135,1168, 0,1135,1135, 0, 0,1147, 0, - 1163,1163,1135,1147,1147,1135,1168, 0,1188,1267,1297,1299,1305, 0,1299, - 0, 0,773,1312,1319,1319,1319,1319,1319,1319,1319,1319,1319,1319,1319, - 1319,1319,1319,1329,1335,1351,1147,1147,1147,1147,1147,1147,1147,1147, - 1147,1147,1147,1147,1147,1147,1147,1147,1319,1319,1319,1319,1319,1319, - 1319,1319,1319,1319,1319,1319,1319,1319,1319,1319,1319,1319,1319,1319, - 1319,1319,1319,1319,1319,1319,1319,1319,1319, 0,1329,1335,1351,1147,1147, - 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, - 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, - 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, - 1147,1147,1147,1147,1362,1362,1362,1362,1372,1372,1351,1351,1351,1329, - 1329,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335, 0, 0, 0, - 0,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, - 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, - 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, - 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1362,1362,1362,1362, - 1372,1372,1351,1351,1351,1329,1329,1335,1335,1335,1335,1335,1335,1335, - 1335,1335,1335,1335,1388,1319,1420,1163,1319,1147,1492,1163, 0,1163, 0, - 0,1147, 0,1514,1163,1163,1163,1163, 0, 0, 0,1420,1543, 0,1561,1420, - 0,1420,1420,1420,1589, 0,1163, 0, 0, 0, 0, 0, 0, 0, 0, 0,1420, - 1420,1617, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1642,1666,1642,1666, - 1147,1642,1642,1642,1642,1420,1702,1742,1742,1774,1805,1835,1862,1147, - 1163,1163,1163,1163,1163,1163,1163,1135,1135,1163,1163,1163,1163, 0,1163, - 1163,1163, 0, 0,1305,1617,1305,1617,1299,1305,1305,1305,1305,1305,1305, - 1305,1305,1305,1305,1305,1305,1305,1305,1305,1305,1305,1305,1305,1666, - 1617,1617,1617,1666,1899,1305,1617,1666,1305,1305,1305,1188, 0, 0, 0, - 1147,1147,1974,1163,1312,1329,1335,1351, 0, 0, 0, 0,1147,1147,1147, - 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, - 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, - 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, - 1147,1147,1147,1147,1147,1147,1147,1362,1362,1362,1362,1372,1372,1351, - 1351,1351,1329,1329,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335, - 1335,1147,1993,2214,2214,1135,1135, 0, 0,1163,1163, 0, 0,1163,1163, - 2234,2234, 0, 0,1147,1147,1147,1147,1147,1135,1135,1135,1135,1135,1135, - 1135,1135,1135,1135,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, - 1163,1147,1147,1147,1147,1135,1312,1312,1163, 0,1163, 0,1163,1163,1163, - 0,1163,1163, 0, 0,1561,1420,1420, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,1147, 0,1642,1642,1642,1642,1642,1642,1642,1147,1147,1147,1147, - 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, - 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1163, - 1163,1163,1163,1163,1135,1163,1163, 0,1163,1163, 0,1163,1163,1163,1163, - 1147,1147,1147,1147,1163,1163,1163,1319,1319,1319,2241,1319,1147,1147, - 1147,1319,1319,2245,1561,1561,1514,2245, 0,2250,2214,1561, 0,1147,1147, - 1514,1514,1514,1514,1514,2254,1147,1163,1163,1163, 0, 0, 0, 0,1135, - 1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, 0,1642,1642,1642,1642, - 1642,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1163, - 1163,1163,1163,1163,1163,1163,1163,1147,1147,1147,2245,1561,2271,1147, - 2289,1319,1561,1147,1514,1135,2294,2294,1163,1147, 0, 0,1135, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1702,1702,1742,1742,1742,1742,1742, - 1742,1774,1774,1805,1805,1163,1163,1163,1335,1561,1147,1147,1135,1163, - 0, 0, 0,1335,1163, 0 + 16,386,430,460,469,460,768, 0,805,768,1103,430,1128,1128, 0, 0,1139, + 0,1154,1154,1128,1139,1139,1128,1159, 0,1128,1128, 0, 0,1139, 0, + 1154,1154,1128,1139,1139,1128,1159, 0,1179,1257,1287,1289,1295, 0,1289, + 0, 0,768,1302,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309, + 1309,1309,1309,1319,1325,1341,1139,1139,1139,1139,1139,1139,1139,1139, + 1139,1139,1139,1139,1139,1139,1139,1139,1309,1309,1309,1309,1309,1309, + 1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309, + 1309,1309,1309,1309,1309,1309,1309,1309,1309, 0,1319,1325,1341,1139,1139, + 1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139, + 1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139, + 1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139, + 1139,1139,1139,1139,1352,1352,1352,1352,1362,1362,1341,1341,1341,1319, + 1319,1325,1325,1325,1325,1325,1325,1325,1325,1325,1325,1325, 0, 0, 0, + 0,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139, + 1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139, + 1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139, + 1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1352,1352,1352,1352, + 1362,1362,1341,1341,1341,1319,1319,1325,1325,1325,1325,1325,1325,1325, + 1325,1325,1325,1325,1378,1309,1410,1154,1309,1139,1482,1154, 0,1154, 0, + 0,1139, 0,1504,1154,1154,1154,1154, 0, 0, 0,1533, 0,1551,1410, 0, + 1410,1410,1410,1579, 0,1154, 0, 0, 0, 0, 0, 0, 0, 0, 0,1410, + 1410,1607, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1646,1670,1693,1670, + 1693,1139,1670,1670,1670,1670,1410,1728,1768,1768,1800,1831,1861,1888, + 1139,1154,1154,1154,1154,1154,1154,1154,1128,1128,1154,1154,1154,1154, + 0,1154,1154,1154, 0, 0,1295,1607,1295,1607,1289,1295,1295,1295,1295, + 1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,1295, + 1295,1693,1607,1607,1607,1693,1925,1295,1607,1693,1295,1295,1295,1179, + 0, 0, 0,1139,1139,2000,1154,1302,1319,1325,1341, 0, 0, 0, 0,1139, + 1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139, + 1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139, + 1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139, + 1139,1139,1139,1139,1139,1139,1139,1139,1139,1352,1352,1352,1352,1362, + 1362,1341,1341,1341,1319,1319,1325,1325,1325,1325,1325,1325,1325,1325, + 1325,1325,1325,1139,2019,2240,2240,1128,1128, 0, 0,1154,1154, 0, 0, + 1154,1154,2260,2260, 0, 0,1139,1139,1139,1139,1139,1128,1128,1128,1128, + 1128,1128,1128,1128,1128,1128,1139,1139,1139,1139,1139,1139,1139,1139, + 1139,1139,1154,1139,1139,1139,1139,1128,1302,1302,1154, 0,1154, 0,1154, + 1154,1154, 0,1154,1154, 0, 0,1551,1410,1410, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,1139, 0,1670,1670,1670,1670,1670,1670,1670,1139,1139, + 1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139, + 1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139, + 1139,1154,1154,1154,1154,1154,1128,1154,1154, 0,1154,1154, 0,1154,1154, + 1154,1154,1139,1139,1139,1139,1154,1154,1154,1309,1309,1309,2266,1309, + 1139,1139,1139,1309,1309,2270,1551,1551,1504,2270, 0,2275,2240,1551, 0, + 1139,1139,1504,1504,1504,1504,1504,2279,1139,1154,1154,1154, 0, 0, 0, + 0,1128,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139, 0,1670,1670, + 1670,1670,1670,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139,1139, + 1139,1154,1154,1154,1154,1154,1154,1154,1154,1139,1139,1139,2270,1551, + 2296,1139,2313,1309,1551,1139,1504,1128,2318,2318,1154,1139, 0, 0,1128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1728,1728,1768,1768,1768,1768, + 1768,1768,1800,1800,1831,1831,1154,1154,1154,1325,1551,1139,1139,1128, + 1154, 0, 0, 0,1325,1154, 0 }; static const unsigned char ag_key_ends[] = { -83,83,0, 65,84,65,0, 69,88,84,0, 68,69,0, 92,39,0, 72,76,41,0, -83,83,0, 65,84,65,0, 69,88,84,0, 73,0, 72,76,0, 71,0, 82,0, -79,67,75,0, 84,69,0, 76,76,0, 73,76,0, 69,71,0, 76,0, 80,0, -71,0, 66,0, 72,79,0, 70,0, 69,0, 70,0, 82,89,0, 82,79,82,0, -68,69,68,0, 78,0, 78,0, 76,76,0, 79,79,82,0, 88,0, 71,72,0, -66,67,0, 69,70,0, 68,69,70,0, 68,69,0, 65,71,69,0, 65,76,76,0, -73,0, 73,0, 75,0, 84,0, 77,80,0, 80,0, 83,72,0, 69,84,0, -70,73,82,83,84,0, 73,0, 67,76,73,66,0, 76,69,0, 70,73,82,83,84,0, -73,0, 77,69,0, 71,69,0, 84,0, 71,69,0, 76,0, 80,0, 71,77,65,0, -87,0, 76,73,67,0, 72,0, 76,76,0, 69,76,0, 84,0, 77,0, 69,0, -76,0, 84,0, 77,0, 76,0, 82,84,0, 76,78,0, 77,0, 88,84,0, -84,76,69,0, 78,68,69,70,0, 69,82,73,76,79,71,0, 79,82,68,0, -72,71,0, 82,0, 72,76,0, 10,0, 83,83,0, 65,84,65,0, 69,88,84,0, -69,70,73,78,69,0, 72,79,0, 70,0, 69,0, 68,73,70,0, 82,79,82,0, -69,70,0, 68,69,70,0, 67,76,85,68,69,0, 71,77,65,0, 78,68,69,70,0, -61,0, 61,0, 73,0, 72,76,0, 71,0, 82,0, 79,67,75,0, 84,69,0, -76,76,0, 69,71,0, 76,0, 80,0, 71,0, 66,0, 72,79,0, 83,69,0, -70,0, 82,89,0, 85,0, 68,69,68,0, 78,0, 78,0, 73,76,76,0, 88,0, -66,67,0, 65,76,76,0, 73,0, 73,0, 75,0, 84,0, 77,80,0, 80,0, -83,72,0, 69,84,0, 70,73,82,83,84,0, 73,0, 67,76,73,66,0, -85,76,69,0, 70,73,82,83,84,0, 73,0, 77,69,0, 71,69,0, 84,0, -71,69,0, 72,76,0, 80,0, 76,73,67,0, 72,0, 76,76,0, 69,76,0, -84,0, 77,0, 69,0, 76,0, 84,0, 77,0, 76,0, 76,78,0, 77,0, -88,84,0, 84,76,69,0, 69,82,73,76,79,71,0, 79,82,68,0, 72,71,0, -72,76,0, 68,69,0, 61,0, 73,0, 72,76,0, 71,0, 82,0, 79,67,75,0, -84,69,0, 76,76,0, 69,71,0, 76,0, 80,0, 71,0, 66,0, 72,79,0, -83,69,0, 70,0, 82,89,0, 68,69,68,0, 78,0, 78,0, 73,76,76,0, -88,0, 66,67,0, 68,69,0, 65,76,76,0, 73,0, 73,0, 75,0, 84,0, -77,80,0, 80,0, 83,72,0, 69,84,0, 70,73,82,83,84,0, 73,0, +83,83,0, 65,84,65,0, 69,88,84,0, 68,69,0, 61,0, 92,39,0, +72,76,41,0, 83,83,0, 65,84,65,0, 69,88,84,0, 73,0, 72,76,0, +71,0, 82,0, 79,67,75,0, 84,69,0, 76,76,0, 73,76,0, 69,71,0, +76,0, 80,0, 71,0, 66,0, 72,79,0, 70,0, 69,0, 70,0, 82,89,0, +82,79,82,0, 68,69,68,0, 78,0, 78,0, 76,76,0, 79,79,82,0, 88,0, +71,72,0, 66,67,0, 69,70,0, 68,69,70,0, 68,69,0, 65,71,69,0, +65,76,76,0, 73,0, 73,0, 75,0, 84,0, 77,80,0, 80,0, 83,72,0, +69,84,0, 70,73,82,83,84,0, 73,0, 67,76,73,66,0, 76,69,0, +70,73,82,83,84,0, 73,0, 77,69,0, 71,69,0, 84,0, 71,69,0, 76,0, +80,0, 71,77,65,0, 87,0, 76,73,67,0, 72,0, 76,76,0, 69,76,0, +84,0, 77,0, 69,0, 76,0, 84,0, 77,0, 76,0, 82,84,0, 76,78,0, +77,0, 88,84,0, 84,76,69,0, 78,68,69,70,0, 69,82,73,76,79,71,0, +79,82,68,0, 72,71,0, 82,0, 72,76,0, 10,0, 83,83,0, 65,84,65,0, +69,88,84,0, 69,70,73,78,69,0, 72,79,0, 70,0, 69,0, 68,73,70,0, +82,79,82,0, 69,70,0, 68,69,70,0, 67,76,85,68,69,0, 71,77,65,0, +78,68,69,70,0, 61,0, 61,0, 61,0, 61,0, 73,0, 72,76,0, 71,0, +82,0, 79,67,75,0, 84,69,0, 76,76,0, 69,71,0, 76,0, 80,0, 71,0, +66,0, 72,79,0, 83,69,0, 70,0, 82,89,0, 85,0, 68,69,68,0, 78,0, +78,0, 73,76,76,0, 88,0, 66,67,0, 65,76,76,0, 73,0, 73,0, 75,0, +84,0, 77,80,0, 80,0, 83,72,0, 69,84,0, 70,73,82,83,84,0, 73,0, 67,76,73,66,0, 85,76,69,0, 70,73,82,83,84,0, 73,0, 77,69,0, 71,69,0, 84,0, 71,69,0, 72,76,0, 80,0, 76,73,67,0, 72,0, -76,76,0, 69,76,0, 84,0, 77,0, 69,0, 76,0, 77,0, 76,0, +76,76,0, 69,76,0, 84,0, 77,0, 69,0, 76,0, 84,0, 77,0, 76,0, 76,78,0, 77,0, 88,84,0, 84,76,69,0, 69,82,73,76,79,71,0, -79,82,68,0, 72,71,0, 72,76,0, 92,39,0, 69,73,76,0, -69,70,73,78,69,68,0, 79,79,82,0, 73,71,72,0, 80,0, 79,84,0, -65,71,69,0, 81,82,84,0, 84,82,89,0, 84,69,78,68,69,68,0, 69,88,0, -73,83,84,0, 69,82,73,76,79,71,0, 47,0, 83,83,0, 65,84,65,0, -69,88,84,0, 68,69,0, 61,0, 83,69,71,0, 79,67,75,0, 84,69,0, -83,69,71,0, 71,0, 72,79,0, 82,89,0, 85,0, 68,69,68,0, 78,0, -78,0, 73,76,76,0, 69,88,0, 68,69,0, 75,0, 84,0, +79,82,68,0, 72,71,0, 72,76,0, 68,69,0, 61,0, 61,0, 73,0, +72,76,0, 71,0, 82,0, 79,67,75,0, 84,69,0, 76,76,0, 69,71,0, +76,0, 80,0, 71,0, 66,0, 72,79,0, 83,69,0, 70,0, 82,89,0, +68,69,68,0, 78,0, 78,0, 73,76,76,0, 88,0, 66,67,0, 68,69,0, +65,76,76,0, 73,0, 73,0, 75,0, 84,0, 77,80,0, 80,0, 83,72,0, +69,84,0, 70,73,82,83,84,0, 73,0, 67,76,73,66,0, 85,76,69,0, +70,73,82,83,84,0, 73,0, 77,69,0, 71,69,0, 84,0, 71,69,0, +72,76,0, 80,0, 76,73,67,0, 72,0, 76,76,0, 69,76,0, 84,0, 77,0, +69,0, 76,0, 77,0, 76,0, 76,78,0, 77,0, 88,84,0, 84,76,69,0, +69,82,73,76,79,71,0, 79,82,68,0, 72,71,0, 72,76,0, 92,39,0, +69,73,76,0, 69,70,73,78,69,68,0, 79,79,82,0, 73,71,72,0, 80,0, +79,84,0, 65,71,69,0, 81,82,84,0, 84,82,89,0, 84,69,78,68,69,68,0, +69,88,0, 73,83,84,0, 69,82,73,76,79,71,0, 47,0, 83,83,0, +65,84,65,0, 69,88,84,0, 68,69,0, 61,0, 83,69,71,0, 79,67,75,0, +84,69,0, 83,69,71,0, 71,0, 72,79,0, 82,89,0, 85,0, 68,69,68,0, +78,0, 78,0, 73,76,76,0, 69,88,0, 68,69,0, 75,0, 84,0, 70,73,82,83,84,0, 67,76,73,66,0, 68,85,76,69,0, 70,73,82,83,84,0, 77,69,0, 80,65,71,69,0, 82,71,0, 71,69,0, 66,76,73,67,0, 84,0, 75,76,78,0, 77,0, 88,84,0, 84,76,69,0, 69,82,73,76,79,71,0, @@ -1972,19 +1972,19 @@ static const unsigned char ag_key_ends[] = { 42,0, 78,68,0, 81,0, 79,68,0, 69,0, 79,82,0, 39,0, 42,0, 79,68,0, 69,0, 79,82,0, 92,39,0, 47,0, 69,73,76,0, 69,70,73,78,69,68,0, 79,79,82,0, 73,71,72,0, 80,0, 79,84,0, -65,71,69,0, 81,82,84,0, 10,0, 92,39,0, 69,73,76,0, -69,70,73,78,69,68,0, 79,79,82,0, 73,71,72,0, 80,0, 65,71,69,0, -81,82,84,0, 92,39,0, 47,0, 69,73,76,0, 69,70,73,78,69,68,0, -79,79,82,0, 73,71,72,0, 80,0, 65,71,69,0, 81,82,84,0, 10,0, -42,0, 78,68,0, 81,0, 79,68,0, 69,0, 82,0, 79,82,0, 78,68,0, -81,0, 69,0, 82,0, 79,82,0, 78,68,0, 81,0, 69,0, 82,0, -79,82,0, 81,0, 69,0, 82,0, 79,82,0, 81,0, 69,0, 82,0, 61,0, -81,0, 69,0, 78,68,0, 81,0, 79,68,0, 69,0, 82,0, 79,82,0, -10,0, 61,0, 61,0, 83,69,71,0, 79,67,75,0, 84,69,0, 83,69,71,0, -71,0, 72,79,0, 82,89,0, 85,0, 68,69,68,0, 78,0, 78,0, -73,76,76,0, 69,88,0, 75,0, 84,0, 70,73,82,83,84,0, -67,76,73,66,0, 68,85,76,69,0, 70,73,82,83,84,0, 77,69,0, -80,65,71,69,0, 82,71,0, 71,69,0, 66,76,73,67,0, 84,0, +65,71,69,0, 81,82,84,0, 10,0, 42,0, 79,68,0, 69,0, 82,0, +79,82,0, 92,39,0, 69,73,76,0, 69,70,73,78,69,68,0, 79,79,82,0, +73,71,72,0, 80,0, 65,71,69,0, 81,82,84,0, 92,39,0, 47,0, +69,73,76,0, 69,70,73,78,69,68,0, 79,79,82,0, 73,71,72,0, 80,0, +65,71,69,0, 81,82,84,0, 10,0, 42,0, 78,68,0, 81,0, 79,68,0, +69,0, 82,0, 79,82,0, 78,68,0, 81,0, 69,0, 82,0, 79,82,0, +78,68,0, 81,0, 69,0, 82,0, 79,82,0, 81,0, 69,0, 82,0, +79,82,0, 81,0, 69,0, 82,0, 61,0, 81,0, 69,0, 78,68,0, 81,0, +79,68,0, 69,0, 82,0, 79,82,0, 10,0, 61,0, 61,0, 83,69,71,0, +79,67,75,0, 84,69,0, 83,69,71,0, 71,0, 72,79,0, 82,89,0, 85,0, +68,69,68,0, 78,0, 78,0, 73,76,76,0, 69,88,0, 75,0, 84,0, +70,73,82,83,84,0, 67,76,73,66,0, 68,85,76,69,0, 70,73,82,83,84,0, +77,69,0, 80,65,71,69,0, 82,71,0, 71,69,0, 66,76,73,67,0, 84,0, 75,76,78,0, 77,0, 88,84,0, 84,76,69,0, 69,82,73,76,79,71,0, 79,82,68,0, 92,39,0, 73,0, 72,76,0, 72,82,0, 76,76,0, 76,0, 80,0, 85,66,0, 73,0, 66,67,0, 65,76,76,0, 73,0, 73,0, 77,80,0, @@ -1997,21 +1997,21 @@ static const unsigned char ag_key_ends[] = { #define AG_TCV(x) (((int)(x) >= -1 && (int)(x) <= 255) ? ag_tcv[(x) + 1] : 0) static const unsigned short ag_tcv[] = { - 38, 38,680,680,680,680,680,680,680,680, 1,423,680,680,680,680,680,680, - 680,680,680,680,680,680,680,680,680,680,680,680,680,680,680, 1,524,681, - 680,682,521,511,683,460,459,519,517,455,518,429,520,684,685,686,686,687, - 687,687,687,688,688,680,425,689,680,690,691,692,693,694,693,695,693,696, - 697,698,697,697,697,697,697,699,697,697,697,700,697,701,697,697,697,702, - 697,697,680,703,680,509,704,692,693,694,693,695,693,696,697,698,697,697, - 697,697,697,699,697,697,697,700,697,701,697,697,697,702,697,697,691,507, - 691,526,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, - 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, - 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, - 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, - 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, - 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, - 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, - 705,705,705,705,705 + 38, 38,680,680,680,680,680,680,680,680, 1,422,680,680,680,680,680,680, + 680,680,680,680,680,680,680,680,680,680,680,680,680,680,680, 1,523,681, + 680,526,520,510,682,459,458,518,516,454,517,428,519,683,684,685,685,686, + 686,686,686,687,687,680,424,688,680,689,690,691,692,693,692,694,692,695, + 696,697,696,696,696,696,696,698,696,696,696,699,696,700,696,696,696,701, + 696,696,680,702,680,508,703,691,692,693,692,694,692,695,696,697,696,696, + 696,696,696,698,696,696,696,699,696,700,696,696,696,701,696,696,690,506, + 690,525,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704, + 704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704, + 704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704, + 704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704, + 704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704, + 704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704, + 704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704, + 704,704,704,704,704 }; #ifndef SYNTAX_ERROR @@ -2198,1234 +2198,1231 @@ static void ag_undo(void) { static const unsigned short ag_tstt[] = { -704,702,701,700,699,698,697,696,695,694,693,691,682,438,434,433,429,427,425, - 424,423,164,163,162,135,134,38,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,437,433,432,428,426,424,423, + 422,163,162,161,134,38,1,0,51,52, 1,0, -704,702,701,700,699,698,697,696,695,694,693,691,682,438,429,427,425,424,423, - 164,163,162,135,134,64,38,1,0,11,34,35,36,37,51,52,53,65,66,133,428,442, -458,457,456,454,453,452,451,450,449,448,447,446,440,433,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,466, - 432,429,427,425,424,423,161,135,38,1,0,138, -458,457,456,454,453,452,451,450,449,448,447,446,440,433,0,60,67,68,74,76,78, +703,701,700,699,698,697,696,695,694,693,692,690,437,428,426,424,423,422,163, + 162,161,134,64,38,1,0,11,34,35,36,37,51,52,53,65,66,133,427,441, +457,456,455,453,452,451,450,449,448,447,446,445,439,432,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,687,686,685,684,683,465,464, + 431,428,426,424,423,422,160,134,38,1,0,137, +457,456,455,453,452,451,450,449,448,447,446,445,439,432,0,60,67,68,74,76,78, 79,80,81,82,83,84,85,87,88, -704,702,701,700,699,698,697,696,695,694,693,691,682,679,678,677,676,675,674, - 673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656, - 655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638, - 637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620, - 619,618,617,616,615,614,613,612,611,610,609,607,606,605,604,603,602,601, - 600,599,598,597,596,595,593,592,591,590,589,588,587,586,585,584,583,582, - 581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564, - 563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546, - 545,491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474, - 473,472,471,470,469,468,467,466,465,464,463,462,456,454,453,451,450,447, - 445,444,443,441,439,432,431,430,429,427,425,424,423,135,134,38,1,0,51, - 52, -423,0,45, -434,433,429,427,425,424,423,38,0,39,40,41,45,46,47,49,54,55, -704,702,701,700,699,698,697,696,695,694,693,691,682,679,678,677,676,675,674, - 673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656, - 655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638, - 637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620, - 619,618,617,616,615,614,613,612,611,610,609,607,606,605,604,603,602,601, - 600,599,598,597,596,595,593,592,591,590,589,588,587,586,585,584,583,582, - 581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564, - 563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546, - 545,491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474, - 473,472,471,470,469,468,467,466,465,464,463,462,456,454,453,451,450,447, - 445,444,443,441,439,432,431,430,429,427,425,424,423,135,134,38,1,0,51, - 52, -704,702,701,700,699,698,697,696,695,694,693,691,682,679,678,677,676,675,674, - 673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656, - 655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638, - 637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620, - 619,618,617,616,615,614,613,612,611,610,609,607,606,605,604,603,602,601, - 600,599,598,597,596,595,593,592,591,590,589,588,587,586,585,584,583,582, - 581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564, - 563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546, - 545,491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474, - 473,472,471,470,469,468,467,466,465,464,463,462,456,454,453,451,450,447, - 445,444,443,441,439,434,433,429,427,425,424,423,135,134,38,1,0,21,30,31, - 32,33,45,54,55,63,76,80,81,89,97,133,244,257,258,259,260,261,262,263, - 264,265,266,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282, - 283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300, - 301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318, - 319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336, - 337,338,339,340,341,342,343,344,346,347,348,349,350,351,352,353,354,355, - 356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373, - 374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391, - 392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409, - 410,411,412,442, -704,702,701,700,699,698,697,696,695,694,693,691,682,438,429,427,425,424,423, - 164,163,162,135,134,64,38,1,0,11,35,36,51,52,53,65,66,133,428,442, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,679,678,677,676,675,674,673, + 672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656,655, + 654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638,637, + 636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620,619, + 618,617,616,615,614,613,612,611,610,609,607,606,605,604,603,602,601,600, + 599,598,597,596,595,593,592,591,590,589,588,587,586,585,584,583,582,581, + 580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564,563, + 562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546,545, + 490,489,488,487,486,485,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,455,453,452,450,449,446,444, + 443,442,440,438,431,430,429,428,426,424,423,422,134,38,1,0,51,52, +422,0,45, +433,432,428,426,424,423,422,38,0,39,40,41,45,46,47,49,54,55, +703,701,700,699,698,697,696,695,694,693,692,690,679,678,677,676,675,674,673, + 672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656,655, + 654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638,637, + 636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620,619, + 618,617,616,615,614,613,612,611,610,609,607,606,605,604,603,602,601,600, + 599,598,597,596,595,593,592,591,590,589,588,587,586,585,584,583,582,581, + 580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564,563, + 562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546,545, + 490,489,488,487,486,485,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,455,453,452,450,449,446,444, + 443,442,440,438,431,430,429,428,426,424,423,422,134,38,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,679,678,677,676,675,674,673, + 672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656,655, + 654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638,637, + 636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620,619, + 618,617,616,615,614,613,612,611,610,609,607,606,605,604,603,602,601,600, + 599,598,597,596,595,593,592,591,590,589,588,587,586,585,584,583,582,581, + 580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564,563, + 562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546,545, + 490,489,488,487,486,485,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,455,453,452,450,449,446,444, + 443,442,440,438,433,432,428,426,424,423,422,134,38,1,0,21,30,31,32,33, + 45,54,55,63,76,80,81,89,97,133,243,256,257,258,259,260,261,262,263,264, + 265,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283, + 284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301, + 302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319, + 320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337, + 338,339,340,341,342,343,345,346,347,348,349,350,351,352,353,354,355,356, + 357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374, + 375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392, + 393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410, + 411,441, +703,701,700,699,698,697,696,695,694,693,692,690,437,428,426,424,423,422,163, + 162,161,134,64,38,1,0,11,35,36,51,52,53,65,66,133,427,441, +703,701,700,699,698,697,696,695,694,693,692,690,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,134,1,0,51,52, 681,1,0,51,52, 681,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,1,0,51,52, 681,1,0,51,52, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -445,444,443,441,439,1,0,51,52, -704,703,702,701,700,699,698,697,696,695,694,693,689,688,687,686,685,684,681, - 520,429,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,89,133,442, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,134,1,0,51,52, +444,443,442,440,438,1,0,51,52, +703,702,701,700,699,698,697,696,695,694,693,692,688,687,686,685,684,683,681, + 519,428,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,134,0,21,89,133,441, +703,701,700,699,698,697,696,695,694,693,692,690,134,0,21,133,441, 681,1,0,51,52, 681,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,1,0,51,52, -681,0,10,12,435, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,77,89, - 91,131,133,166,196,198,203,204,205,206,207,208,209,210,211,212,213,214, - 215,216,217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,77,89, - 91,131,133,166,196,198,203,204,205,206,207,208,209,210,211,212,213,214, - 215,216,217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, -445,444,443,441,439,0,69,70,71,72,73, -689,681,0,10,12,13,14,435,436, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,455,438,434,433,429,427,426,425,424,423,164,163,162,135,134,38,1,0, - 51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,491, - 490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,461,460,459,456,455,454,453,445, - 444,443,441,439,434,433,431,430,429,427,426,425,424,423,38,1,0,51,52, -434,433,0,60,61,62, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,455,429,427,426,425,423,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,455,429,425,423,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,455,429,427,426,425,423,1,0,40,45,46,47,48,49,54,86,91,93,140,141, - 143,145,146,147,148,149,150,154,157,158,185,187,189,195,196,197,199,200, - 203,205,220,224,225,229,413,414,415,416,417,418,419,420,421,422, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,455,429,425,423,1,0,43,44,46,54,86,91,93,140,141,143,145,146,147, - 148,149,150,154,157,158,185,187,189,195,196,197,199,200,203,205,220,224, - 225,229,413,414,415,416,417,418,419,420,421,422, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,455,429,425,423,1,0,43,44,46,54,86,91,93,140,141,143,145,146,147, - 148,149,150,154,157,158,185,187,189,195,196,197,199,200,203,205,220,224, - 225,229,413,414,415,416,417,418,419,420,421,422, -704,702,701,700,699,698,697,696,695,694,693,691,682,679,678,677,676,675,674, - 673,672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656, - 655,654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638, - 637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620, - 619,618,617,616,615,614,613,612,611,610,609,607,606,605,604,603,602,601, - 600,599,598,597,596,595,593,592,591,590,589,588,587,586,585,584,583,582, - 581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564, - 563,562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546, - 545,491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474, - 473,472,471,470,469,468,467,466,465,464,463,462,456,454,453,451,450,447, - 445,444,443,441,439,432,431,430,429,427,425,424,423,135,134,38,0,21,30, - 31,32,33,39,40,41,45,46,47,49,54,55,59,63,76,80,81,89,97,133,244,257, - 258,259,260,261,262,263,264,265,266,268,269,270,271,272,273,274,275,276, - 277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294, - 295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312, - 313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330, - 331,332,333,334,335,336,337,338,339,340,341,342,343,344,346,347,348,349, - 350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367, - 368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385, - 386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403, - 404,405,406,407,408,409,410,411,412,442, -494,491,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -668,543,542,541,248,246,238,236,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -668,543,248,246,238,236,234,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -687,686,685,684,1,0,51,52, -668,543,542,541,248,246,238,236,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -668,543,248,246,238,236,234,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -668,540,539,248,246,238,236,234,1,0,51,52, -668,540,539,248,246,238,236,234,1,0,51,52, -668,540,539,248,246,238,236,234,1,0,51,52, -668,540,539,248,246,238,236,234,1,0,51,52, -668,246,236,234,1,0,51,52, -668,246,236,234,1,0,51,52, -668,543,248,246,238,236,234,1,0,51,52, -668,543,248,246,238,236,234,1,0,51,52, -668,543,248,246,238,236,234,1,0,51,52, -668,543,542,541,248,246,238,236,234,1,0,51,52, -668,543,542,541,248,246,238,236,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -687,686,685,684,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -455,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -668,540,539,248,246,238,236,234,1,0,51,52, -668,540,539,248,246,238,236,234,1,0,51,52, -668,540,539,248,246,238,236,234,1,0,51,52, -668,540,539,248,246,238,236,234,1,0,51,52, -668,246,236,234,1,0,51,52, -668,246,236,234,1,0,51,52, -668,543,248,246,238,236,234,1,0,51,52, -668,543,248,246,238,236,234,1,0,51,52, -668,543,248,246,238,236,234,1,0,51,52, -668,543,542,541,248,246,238,236,234,1,0,51,52, -668,543,542,541,248,246,238,236,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -540,241,240,239,238,237,236,235,234,1,0,51,52, -705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,544,526,524,523,521,520,519,518,517,515,513,511, - 509,507,506,504,502,500,498,496,493,460,459,455,432,429,427,425,424,423, - 38,1,0,51,52,138, -544,427,425,424,423,38,1,0,51,52, -705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,544,526,524,523,522,521,520,519,518,517,516,515, - 514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, - 496,495,493,460,459,455,432,429,427,425,424,423,38,1,0,91, -427,425,424,423,38,1,0,51, -544,0,267, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,77,89, - 91,131,133,166,196,198,203,204,205,206,207,208,209,210,211,212,213,214, - 215,216,217,218,219,442,492,538, -491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,456,454,453,445,444,443,441,439, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,1,0,51,52, +681,0,10,12,434, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,134,0,21,133,441, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,77,89,91, + 131,133,153,165,195,197,202,203,204,205,206,207,208,209,210,211,212,213, + 214,215,216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,77,89,91, + 131,133,153,165,195,197,202,203,204,205,206,207,208,209,210,211,212,213, + 214,215,216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,690,134,0,21,133,441, +444,443,442,440,438,0,69,70,71,72,73, +688,681,0,10,12,13,14,434,435, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459, + 458,454,437,433,432,428,426,425,424,423,422,163,162,161,134,38,1,0,51, + 52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,490, + 489,488,487,486,485,483,482,481,480,479,478,477,476,475,474,473,472,471, + 470,469,468,467,466,465,464,463,462,461,460,459,458,455,454,453,452,444, + 443,442,440,438,433,432,430,429,428,426,425,424,423,422,38,1,0,51,52, +433,432,0,60,61,62, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459, + 458,454,428,426,425,424,422,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459, + 458,454,428,424,422,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459, + 458,454,428,426,425,424,422,1,0,40,45,46,47,48,49,54,86,91,93,139,140, + 142,144,145,146,147,148,149,153,156,157,184,186,188,194,195,196,198,199, + 202,204,219,223,224,228,412,413,414,415,416,417,418,419,420,421, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459, + 458,454,428,424,422,1,0,43,44,46,54,86,91,93,139,140,142,144,145,146, + 147,148,149,153,156,157,184,186,188,194,195,196,198,199,202,204,219,223, + 224,228,412,413,414,415,416,417,418,419,420,421, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459, + 458,454,428,424,422,1,0,43,44,46,54,86,91,93,139,140,142,144,145,146, + 147,148,149,153,156,157,184,186,188,194,195,196,198,199,202,204,219,223, + 224,228,412,413,414,415,416,417,418,419,420,421, +703,701,700,699,698,697,696,695,694,693,692,690,679,678,677,676,675,674,673, + 672,671,670,669,668,667,666,665,664,663,662,661,660,659,658,657,656,655, + 654,653,652,651,650,649,648,647,646,645,644,643,642,641,640,639,638,637, + 636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620,619, + 618,617,616,615,614,613,612,611,610,609,607,606,605,604,603,602,601,600, + 599,598,597,596,595,593,592,591,590,589,588,587,586,585,584,583,582,581, + 580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564,563, + 562,561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546,545, + 490,489,488,487,486,485,483,482,481,480,479,478,477,476,475,474,473,472, + 471,470,469,468,467,466,465,464,463,462,461,455,453,452,450,449,446,444, + 443,442,440,438,431,430,429,428,426,424,423,422,134,38,0,21,30,31,32,33, + 39,40,41,45,46,47,49,54,55,59,63,76,80,81,89,97,133,243,256,257,258,259, + 260,261,262,263,264,265,267,268,269,270,271,272,273,274,275,276,277,278, + 279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296, + 297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314, + 315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332, + 333,334,335,336,337,338,339,340,341,342,343,345,346,347,348,349,350,351, + 352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369, + 370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387, + 388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405, + 406,407,408,409,410,411,441, +493,490,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +668,543,542,541,247,245,237,235,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +668,543,247,245,237,235,233,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +686,685,684,683,1,0,51,52, +668,543,542,541,247,245,237,235,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +668,543,247,245,237,235,233,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +668,540,539,247,245,237,235,233,1,0,51,52, +668,540,539,247,245,237,235,233,1,0,51,52, +668,540,539,247,245,237,235,233,1,0,51,52, +668,540,539,247,245,237,235,233,1,0,51,52, +668,245,235,233,1,0,51,52, +668,245,235,233,1,0,51,52, +668,543,247,245,237,235,233,1,0,51,52, +668,543,247,245,237,235,233,1,0,51,52, +668,543,247,245,237,235,233,1,0,51,52, +668,543,542,541,247,245,237,235,233,1,0,51,52, +668,543,542,541,247,245,237,235,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +686,685,684,683,1,0,51,52, +454,1,0,51,52, +454,1,0,51,52, +454,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +668,540,539,247,245,237,235,233,1,0,51,52, +668,540,539,247,245,237,235,233,1,0,51,52, +668,540,539,247,245,237,235,233,1,0,51,52, +668,540,539,247,245,237,235,233,1,0,51,52, +668,245,235,233,1,0,51,52, +668,245,235,233,1,0,51,52, +668,543,247,245,237,235,233,1,0,51,52, +668,543,247,245,237,235,233,1,0,51,52, +668,543,247,245,237,235,233,1,0,51,52, +668,543,542,541,247,245,237,235,233,1,0,51,52, +668,543,542,541,247,245,237,235,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +540,240,239,238,237,236,235,234,233,1,0,51,52, +704,703,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,682,681,680,544,526,525,523,522,520,519,518,517,516,514,512,510, + 508,506,505,503,501,499,497,495,492,459,458,454,431,428,426,424,423,422, + 38,1,0,51,52,137, +544,426,424,423,422,38,1,0,51,52, +704,703,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,682,681,680,544,526,525,523,522,521,520,519,518,517,516,515,514, + 513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496, + 495,494,492,459,458,454,431,428,426,424,423,422,38,1,0,91, +426,424,423,422,38,1,0,51, +544,0,266, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,77,89,91, + 131,133,153,165,195,197,202,203,204,205,206,207,208,209,210,211,212,213, + 214,215,216,217,218,441,491,538, +490,489,488,487,486,485,483,482,481,480,479,478,477,476,475,474,473,472,471, + 470,469,468,467,466,465,464,463,462,461,455,453,452,444,443,442,440,438, 0,69,70,71,72,73,83,84,85,98,99,100,101,102,103,104,105,106,107,108,109, 110,111,112,113,114,115,117,118,119,120,121,122,123,124,125,126,127,128, 129,130,131, -427,425,424,423,38,1,0,51,52, -705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, - 455,429,425,1,0,51,52, -427,425,424,423,38,1,0,51,52, -681,0,10,12,435, -681,0,10,12,435, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28,29, - 57,89,91,131,133,196,198,203,204,205,206,207,208,209,210,211,212,213, - 214,215,216,217,218,219,435,442,492,538, -704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, - 455,429,425,423,1,0,142, -493,459,455,427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,1,0,51,52, -688,687,686,685,684,0, -687,686,685,684,0, -685,684,0, -704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,544, - 523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, - 505,504,503,502,501,500,499,498,497,496,495,493,460,459,432,429,427,425, - 424,423,38,1,0, -704,702,698,696,695,694,693,688,687,686,685,684,682,544,523,522,521,520,519, - 518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,496,495,493,459,432,429,427,425,424,423,222,221,38,1,0, -688,687,686,685,684,0, -704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459,455, - 429,425,423,233,1,0,16, -688,687,686,685,684,0, -698,696,695,694,693,688,687,686,685,684,0, -687,686,685,684,544,523,522,521,520,519,518,517,516,515,514,513,512,511,510, - 509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,493,459,432, - 427,425,424,423,38,1,0, -685,684,544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, - 507,506,505,504,503,502,501,500,499,498,497,496,495,493,459,432,427,425, - 424,423,38,1,0, -696,695,694,693,688,687,686,685,684,544,523,522,521,520,519,518,517,516,515, - 514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, - 496,495,493,459,432,427,425,424,423,38,1,0, -704,698,696,695,694,693,688,687,686,685,684,682,544,523,522,521,520,519,518, - 517,516,515,514,513,511,510,509,508,507,506,505,504,503,502,501,500,499, - 498,497,496,493,459,432,429,427,425,424,423,222,221,38,1,0,223, -460,1,0,51,52, -460,427,425,424,423,38,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, - 505,504,503,502,501,500,499,498,497,496,495,493,459,432,427,425,424,423, +426,424,423,422,38,1,0,51,52, +704,703,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459,458, + 454,428,424,1,0,51,52, +426,424,423,422,38,1,0,51,52, +681,0,10,12,434, +681,0,10,12,434, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28,29,57, + 89,91,131,133,153,195,197,202,203,204,205,206,207,208,209,210,211,212, + 213,214,215,216,217,218,434,441,491,538, +703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459,458, + 454,428,424,422,1,0,141, +492,458,454,426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,1,0,51,52, +687,686,685,684,683,0, +686,685,684,683,0, +684,683,0, +703,701,697,695,694,693,692,687,686,685,684,683,544,522,521,520,519,518,517, + 516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499, + 498,497,496,495,494,492,458,431,428,426,424,423,422,221,220,38,1,0, +687,686,685,684,683,0, +703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,681,680,526,525,523,520,519,518,517,516,510,508,506,459,458,454, + 428,424,422,232,1,0,16, +687,686,685,684,683,0, +697,695,694,693,692,687,686,685,684,683,0, +686,685,684,683,544,522,521,520,519,518,517,516,515,514,513,512,511,510,509, + 508,507,506,505,504,503,502,501,500,499,498,497,496,495,494,492,458,431, + 426,424,423,422,38,1,0, +684,683,544,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507, + 506,505,504,503,502,501,500,499,498,497,496,495,494,492,458,431,426,424, + 423,422,38,1,0, +695,694,693,692,687,686,685,684,683,544,522,521,520,519,518,517,516,515,514, + 513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496, + 495,494,492,458,431,426,424,423,422,38,1,0, +703,697,695,694,693,692,687,686,685,684,683,544,522,521,520,519,518,517,516, + 515,514,513,512,510,509,508,507,506,505,504,503,502,501,500,499,498,497, + 496,495,492,458,431,428,426,424,423,422,221,220,38,1,0,222, +459,1,0,51,52, +459,426,424,423,422,38,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +544,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, + 504,503,502,501,500,499,498,497,496,495,494,492,458,431,426,424,423,422, 38,1,0,51,52, -544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, - 505,504,503,502,501,500,499,498,497,496,495,493,459,432,427,425,424,423, +544,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, + 504,503,502,501,500,499,498,497,496,495,494,492,458,431,426,424,423,422, 38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 525,524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426, - 425,424,423,231,135,134,38,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -460,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426,425, - 424,423,231,135,134,38,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426,425, - 424,423,231,135,134,38,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, - 212,213,214,215,216,217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, - 212,213,214,215,216,217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, - 212,213,214,215,216,217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, - 212,213,214,215,216,217,218,219,442,492,538, -544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, - 505,504,503,502,501,500,499,498,497,496,495,493,459,432,427,425,424,423, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526,525, + 524,523,520,519,518,517,516,510,508,506,490,460,459,458,454,428,426,425, + 424,423,422,230,134,38,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +459,1,0,51,52, +695,694,693,692,687,686,685,684,683,544,522,521,520,519,518,517,516,515,514, + 513,512,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495, + 492,458,431,426,424,423,422,38,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526,525, + 523,520,519,518,517,516,510,508,506,490,460,459,458,454,428,426,425,424, + 423,422,230,134,38,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526,525, + 523,520,519,518,517,516,510,508,506,490,460,459,458,454,428,426,425,424, + 423,422,230,134,38,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,0,2,6,7,8,9,15,17,21,89,91,131,133,153,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,0,2,6,7,8,9,15,17,21,89,91,131,133,153,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,0,2,6,7,8,9,15,17,21,89,91,131,133,153,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,0,2,6,7,8,9,15,17,21,89,91,131,133,153,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,491,538, +544,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, + 504,503,502,501,500,499,498,497,496,495,494,492,458,431,426,424,423,422, 38,1,0,51,52, -544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, - 505,504,503,502,501,500,499,498,497,496,495,493,459,432,425,423,38,1,0, - 51,52,197,199,200,201,202, -544,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,496,495,493,459,432,427,425,424,423,38,1,0,51,52,195, - 196, -544,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499, - 498,497,496,495,493,459,432,427,425,424,423,38,1,0,51,52,191,192,193, - 194, -544,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495, - 493,459,432,427,425,424,423,38,1,0,51,52,189,190, -544,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,493,459, - 432,427,425,424,423,38,1,0,51,52,187,188, -508,507,0,185,186, -506,505,504,503,502,501,500,499,498,497,496,495,432,427,425,424,423,38,1,0, - 59,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183, - 184, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,75, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,680,526,524,521,520,519,518,517,511,509,507,460,459, - 455,429,425,1,0, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -704,703,702,701,700,699,698,697,696,695,694,693,689,688,687,686,685,684,681, - 520,429,1,0,51,52, -704,703,702,701,700,699,698,697,696,695,694,693,689,688,687,686,685,684,681, - 520,429,0,10,12,13,14,19,435,436,437, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 525,524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426, - 425,424,423,231,135,134,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 525,524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426, - 425,424,423,231,135,134,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,455,429,427,426,425,423,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426,425, - 424,423,231,135,134,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 525,524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426, - 425,424,423,231,135,134,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 525,524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426, - 425,424,423,231,135,134,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 525,524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426, - 425,424,423,231,135,134,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426,425, - 424,423,231,135,134,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,544,526,524,523,522,521,520,519,518,517,516, - 515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, - 497,496,495,493,461,460,459,455,432,429,427,426,425,424,423,38,1,0,51, +544,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, + 504,503,502,501,500,499,498,497,496,495,494,492,458,431,424,422,38,1,0, + 51,52,196,198,199,200,201, +544,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, + 499,498,497,496,495,494,492,458,431,426,424,423,422,38,1,0,51,52,194, + 195, +544,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, + 497,496,495,494,492,458,431,426,424,423,422,38,1,0,51,52,190,191,192, + 193, +544,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494, + 492,458,431,426,424,423,422,38,1,0,51,52,188,189, +544,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494,492,458, + 431,426,424,423,422,38,1,0,51,52,186,187, +507,506,0,184,185, +505,504,503,502,501,500,499,498,497,496,495,494,431,426,424,423,422,38,1,0, + 59,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182, + 183, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,75, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,134,1,0,51,52, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,680,526,525,523,520,519,518,517,516,510,508,506,459,458, + 454,428,424,1,0, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +703,702,701,700,699,698,697,696,695,694,693,692,688,687,686,685,684,683,681, + 519,428,1,0,51,52, +703,702,701,700,699,698,697,696,695,694,693,692,688,687,686,685,684,683,681, + 519,428,0,10,12,13,14,19,434,435,436, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526,525, + 524,523,520,519,518,517,516,510,508,506,490,460,459,458,454,428,426,425, + 424,423,422,230,134,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526,525, + 524,523,520,519,518,517,516,510,508,506,490,460,459,458,454,428,426,425, + 424,423,422,230,134,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459, + 458,454,428,426,425,424,422,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526,525, + 523,520,519,518,517,516,510,508,506,490,460,459,458,454,428,426,425,424, + 423,422,230,134,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526,525, + 524,523,520,519,518,517,516,510,508,506,490,460,459,458,454,428,426,425, + 424,423,422,230,134,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526,525, + 524,523,520,519,518,517,516,510,508,506,490,460,459,458,454,428,426,425, + 424,423,422,230,134,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526,525, + 524,523,520,519,518,517,516,510,508,506,490,460,459,458,454,428,426,425, + 424,423,422,230,134,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526,525, + 523,520,519,518,517,516,510,508,506,490,460,459,458,454,428,426,425,424, + 423,422,230,134,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,544,526,525,523,522,521,520,519,518,517,516,515, + 514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, + 496,495,494,492,460,459,458,454,431,428,426,425,424,423,422,38,1,0,51, 52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 525,524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426, - 425,424,423,231,135,134,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526, - 524,521,520,519,518,517,511,509,507,491,461,460,459,455,429,427,426,425, - 424,423,231,135,134,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461, - 460,459,455,429,427,426,425,424,423,38,1,0,51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,455,438,434,433,429,427,426,425,424,423,164,163,162,135,134,38,1,0, - 51,52, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,455,429,425,1,0,46,54,86,91,93,140,141,143,145,146,147,148,149,150, - 154,157,158,185,187,189,195,196,197,199,200,203,205,220,224,225,229,413, - 414,415,416,417,418,419,420,421,422, -423,0,45, -423,0,45, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -491,490,489,488,487,486,484,483,482,481,480,479,478,477,476,475,474,473,472, - 471,470,469,468,467,466,465,464,463,462,456,454,453,445,444,443,441,439, - 431,430,0,56,58,69,70,71,72,73,83,84,85,98,99,100,101,102,103,104,105, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526,525, + 524,523,520,519,518,517,516,510,508,506,490,460,459,458,454,428,426,425, + 424,423,422,230,134,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,537,535,534,533,532,531,530,529,528,527,526,525, + 523,520,519,518,517,516,510,508,506,490,460,459,458,454,428,426,425,424, + 423,422,230,134,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460, + 459,458,454,428,426,425,424,423,422,38,1,0,51,52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459, + 458,454,437,433,432,428,426,425,424,423,422,163,162,161,134,38,1,0,51, + 52, +704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459, + 458,454,428,424,1,0,46,54,86,91,93,139,140,142,144,145,146,147,148,149, + 153,156,157,184,186,188,194,195,196,198,199,202,204,219,223,224,228,412, + 413,414,415,416,417,418,419,420,421, +422,0,45, +422,0,45, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +490,489,488,487,486,485,483,482,481,480,479,478,477,476,475,474,473,472,471, + 470,469,468,467,466,465,464,463,462,461,455,453,452,444,443,442,440,438, + 430,429,0,56,58,69,70,71,72,73,83,84,85,98,99,100,101,102,103,104,105, 106,107,108,109,110,111,112,113,114,115,117,118,119,120,121,122,123,124, 125,126,127,128,129,130,131, -427,425,424,423,38,1,0,51,52, -494,491,427,425,424,423,38,0,22,39,40,41,45,46,47,49,131,165, -668,543,542,541,248,246,238,236,234,0,245,247,249,250,254,255,256, -540,241,240,239,238,237,236,235,234,0,4,242,594, -668,543,248,246,238,236,234,0,5,245,247,249,608, -687,686,685,684,0,345, -455,0,86, -455,0,86, -455,0,86, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -668,540,539,248,246,238,236,234,0,243,245,247,249,251,252, -668,540,539,248,246,238,236,234,0,243,245,247,249,251,252, -668,540,539,248,246,238,236,234,0,243,245,247,249,251,252, -668,540,539,248,246,238,236,234,0,243,245,247,249,251,252, -668,246,236,234,0,245,247,253, -668,246,236,234,0,245,247,253, -668,543,248,246,238,236,234,0,5,245,247,249,608, -668,543,248,246,238,236,234,0,5,245,247,249,608, -668,543,248,246,238,236,234,0,5,245,247,249,608, -668,543,542,541,248,246,238,236,234,0,245,247,249,250,254,255,256, -668,543,542,541,248,246,238,236,234,0,245,247,249,250,254,255,256, -540,241,240,239,238,237,236,235,234,0,4,242,594, -540,241,240,239,238,237,236,235,234,0,4,242,594, -540,241,240,239,238,237,236,235,234,0,4,242,594, -540,241,240,239,238,237,236,235,234,0,4,242,594, -540,241,240,239,238,237,236,235,234,0,4,242,594, -540,241,240,239,238,237,236,235,234,0,4,242,594, -540,241,240,239,238,237,236,235,234,0,4,242,594, -540,241,240,239,238,237,236,235,234,0,4,242,594, -540,241,240,239,238,237,236,235,234,0,4,242,594, -540,241,240,239,238,237,236,235,234,0,4,242,594, -540,241,240,239,238,237,236,235,234,0,4,242,594, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,89,91,92,131,133,196,198,203,204,205,206,207,208,209,210,211, - 212,213,214,215,216,217,218,219,435,442,485,492,538, -692,688,687,686,685,684,683,682,521,518,517,231,1,0,2,6,7,15,17,218,219,492, +426,424,423,422,38,1,0,51,52, +493,490,426,424,423,422,38,0,22,39,40,41,45,46,47,49,131,164, +668,543,542,541,247,245,237,235,233,0,244,246,248,249,253,254,255, +540,240,239,238,237,236,235,234,233,0,4,241,594, +668,543,247,245,237,235,233,0,5,244,246,248,608, +686,685,684,683,0,344, +454,0,86, +454,0,86, +454,0,86, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +668,540,539,247,245,237,235,233,0,242,244,246,248,250,251, +668,540,539,247,245,237,235,233,0,242,244,246,248,250,251, +668,540,539,247,245,237,235,233,0,242,244,246,248,250,251, +668,540,539,247,245,237,235,233,0,242,244,246,248,250,251, +668,245,235,233,0,244,246,252, +668,245,235,233,0,244,246,252, +668,543,247,245,237,235,233,0,5,244,246,248,608, +668,543,247,245,237,235,233,0,5,244,246,248,608, +668,543,247,245,237,235,233,0,5,244,246,248,608, +668,543,542,541,247,245,237,235,233,0,244,246,248,249,253,254,255, +668,543,542,541,247,245,237,235,233,0,244,246,248,249,253,254,255, +540,240,239,238,237,236,235,234,233,0,4,241,594, +540,240,239,238,237,236,235,234,233,0,4,241,594, +540,240,239,238,237,236,235,234,233,0,4,241,594, +540,240,239,238,237,236,235,234,233,0,4,241,594, +540,240,239,238,237,236,235,234,233,0,4,241,594, +540,240,239,238,237,236,235,234,233,0,4,241,594, +540,240,239,238,237,236,235,234,233,0,4,241,594, +540,240,239,238,237,236,235,234,233,0,4,241,594, +540,240,239,238,237,236,235,234,233,0,4,241,594, +540,240,239,238,237,236,235,234,233,0,4,241,594, +540,240,239,238,237,236,235,234,233,0,4,241,594, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27,28, + 29,57,89,91,92,131,133,153,195,197,202,203,204,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,434,441,484,491,538, +691,687,686,685,684,683,682,526,520,517,516,230,1,0,2,6,7,15,17,217,218,491, 679,678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663,662,661, 660,659,658,657,656,655,654,653,652,651,650,649,648,647,646,645,644,643, 642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627,626,625, @@ -3442,332 +3439,329 @@ static const unsigned short ag_tstt[] = { 586,585,584,583,582,581,580,579,578,577,576,575,574,573,572,571,570,569, 568,567,566,565,564,563,562,561,560,559,558,557,556,555,554,553,552,551, 550,549,548,547,546,545,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, -704,703,702,701,700,699,698,697,696,695,694,693,688,687,686,685,684,520,429, +703,701,700,699,698,697,696,695,694,693,692,690,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,134,0,21,133,441, +703,702,701,700,699,698,697,696,695,694,693,692,687,686,685,684,683,519,428, 1,0,51,52, -704,703,702,701,700,699,698,697,696,695,694,693,688,687,686,685,684,520,429, - 0,19,437, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -683,681,1,0,51,52, -683,681,0,10,12,18,20,435,485, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,427,425,424,423,135,134, - 38,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,427,425,424,423,135,134, - 38,1,0,21,133,442, -681,0,10,12,435, -681,0,10,12,435, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,1,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28, - 29,51,52,57,89,91,131,133,196,198,203,204,205,206,207,208,209,210,211, - 212,213,214,215,216,217,218,219,435,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,116,133, - 442, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,116,133, - 442, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,116,133, - 442, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,89,91,92,131,133,196,198,203,204,205,206,207,208,209,210,211, - 212,213,214,215,216,217,218,219,435,442,485,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,89,91,92,131,133,196,198,203,204,205,206,207,208,209,210,211, - 212,213,214,215,216,217,218,219,435,442,485,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -427,425,424,423,38,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, -494,491,427,425,424,423,38,1,0,51,52, -494,491,427,425,424,423,38,1,0,51,52, -427,425,424,423,38,0,39,40,41,45,46,47,49, -705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, - 455,429,425,0,46,54,86,90,91,93,140,141,145,146,147,148,149,150,154,157, - 158,185,187,189,195,196,197,199,200,203,205,220,224,225,229,413,414,415, - 416,417,418,419,420,421,422, -427,425,424,423,38,0,39,40,41,45,46,47,49, -455,0,86, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -703,702,701,700,699,696,694,686,685,684,682,681,423,0,155, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,0,39,40,41,45,46,47,49, -696,695,694,693,688,687,686,685,684,0, -703,701,700,699,684,683,0, -704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, - 455,429,425,423,233,1,0,16, -698,696,695,694,693,688,687,686,685,684,544,523,522,521,520,519,518,517,516, - 515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, - 497,496,495,493,459,432,427,425,424,423,38,1,0, -698,696,695,694,693,688,687,686,685,684,544,523,522,521,520,519,518,517,516, - 515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, - 497,496,495,493,459,432,427,425,424,423,38,1,0, -460,0,91, -460,0,91, -460,0,91, -460,0,91, -460,0,91, -460,0,91, -460,0,91, -460,0,91, -460,0,91, -460,0,91, -460,0,91, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -688,687,686,685,684,0, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,0,39,40,41,45,46,47,49, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,0,39,40,41,45,46,47,49, -705,704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687, - 686,685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460, - 459,455,429,425,423,1,0, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,0,39,40,41,45,46,47,49, -704,703,702,701,700,699,698,697,696,695,694,693,688,687,686,685,684,520,429, - 425,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -544,455,427,425,424,423,38,1,0,51,52, -544,455,427,425,424,423,38,1,0,51,52, -544,455,427,425,424,423,38,1,0,51,52, -544,493,455,427,425,424,423,38,1,0,51,52, -544,455,427,425,424,423,38,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -544,427,425,424,423,38,1,0,51,52, -493,1,0,51,52, -704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459,455, - 429,425,423,233,1,0,16, +703,702,701,700,699,698,697,696,695,694,693,692,687,686,685,684,683,519,428, + 0,19,436, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +682,681,1,0,51,52, +682,681,0,10,12,18,20,434,484, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,426,424,423,422,134,38,1,0, + 51,52, +703,701,700,699,698,697,696,695,694,693,692,690,426,424,423,422,134,38,1,0, + 21,133,441, +681,0,10,12,434, +681,0,10,12,434, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,1,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28,29, + 51,52,57,89,91,131,133,153,195,197,202,203,204,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,434,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,690,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,134,0,21,133,441, +703,701,700,699,698,697,696,695,694,693,692,690,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,134,0,21,133,441, +703,701,700,699,698,697,696,695,694,693,692,690,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,134,0,21,116,133,441, +703,701,700,699,698,697,696,695,694,693,692,690,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,134,0,21,116,133,441, +703,701,700,699,698,697,696,695,694,693,692,690,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,134,0,21,116,133,441, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27,28, + 29,57,89,91,92,131,133,153,195,197,202,203,204,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,434,441,484,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27,28, + 29,57,89,91,92,131,133,153,195,197,202,203,204,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,434,441,484,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +426,424,423,422,38,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,690,134,0,21,133,441, +493,490,426,424,423,422,38,1,0,51,52, +493,490,426,424,423,422,38,1,0,51,52, +426,424,423,422,38,0,39,40,41,45,46,47,49, +704,703,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459,458, + 454,428,424,0,46,54,86,90,91,93,139,140,144,145,146,147,148,149,153,156, + 157,184,186,188,194,195,196,198,199,202,204,219,223,224,228,412,413,414, + 415,416,417,418,419,420,421, +426,424,423,422,38,0,39,40,41,45,46,47,49, +454,0,86, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +702,701,700,699,698,695,693,685,684,683,681,526,422,0,154, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,0,39,40,41,45,46,47,49, +695,694,693,692,687,686,685,684,683,0, +702,700,699,698,683,682,0, +703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459,458, + 454,428,424,422,232,1,0,16, +697,695,694,693,692,687,686,685,684,683,544,522,521,520,519,518,517,516,515, + 514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, + 496,495,494,492,458,431,426,424,423,422,38,1,0, +697,695,694,693,692,687,686,685,684,683,544,522,521,520,519,518,517,516,515, + 514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497, + 496,495,494,492,458,431,426,424,423,422,38,1,0, +459,0,91, +459,0,91, +459,0,91, +459,0,91, +459,0,91, +459,0,91, +459,0,91, +459,0,91, +459,0,91, +459,0,91, +459,0,91, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +687,686,685,684,683,0, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,0,39,40,41,45,46,47,49, +703,701,700,699,698,697,696,695,694,693,692,690,134,0,21,133,441, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,0,39,40,41,45,46,47,49, 704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, - 455,429,425,423,233,1,0,16, -493,459,427,425,424,423,38,1,0,51,52, -493,459,0,93,132, -696,695,694,693,688,687,686,685,684,0, -704,698,696,695,694,693,688,687,686,685,684,682,427,425,424,423,222,221,38, - 1,0,223, + 685,684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459, + 458,454,428,424,422,1,0, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,0,39,40,41,45,46,47,49, +703,702,701,700,699,698,697,696,695,694,693,692,687,686,685,684,683,519,428, + 424,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +544,454,426,424,423,422,38,1,0,51,52, +544,454,426,424,423,422,38,1,0,51,52, +544,454,426,424,423,422,38,1,0,51,52, +544,492,454,426,424,423,422,38,1,0,51,52, +544,454,426,424,423,422,38,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +544,426,424,423,422,38,1,0,51,52, +492,1,0,51,52, +703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,681,680,526,525,523,520,519,518,517,516,510,508,506,459,458,454, + 428,424,422,232,1,0,16, +703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459,458, + 454,428,424,422,232,1,0,16, +492,458,426,424,423,422,38,1,0,51,52, +492,458,0,93,132, +695,694,693,692,687,686,685,684,683,0, +703,697,695,694,693,692,687,686,685,684,683,426,424,423,422,221,220,38,1,0, + 222, 679,678,677,676,675,674,673,672,671,670,669,668,667,666,665,664,663,662,661, 660,659,658,657,656,655,654,653,652,651,650,649,648,647,646,645,644,643, 642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627,626,625, @@ -3775,635 +3769,622 @@ static const unsigned short ag_tstt[] = { 605,604,603,602,601,600,599,598,597,596,595,593,592,591,590,589,588,587, 586,585,584,583,582,581,580,579,578,577,576,575,574,573,572,571,570,569, 568,567,566,565,564,563,562,561,560,559,558,557,556,555,554,553,552,551, - 550,549,548,547,546,545,0,31,32,244,257,258,259,260,261,262,263,264,265, - 266,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284, - 285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302, - 303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320, - 321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338, - 339,340,341,342,343,344,346,347,348,349,350,351,352,353,354,355,356,357, - 358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375, - 376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393, - 394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411, - 412, -704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459,455, - 429,425,423,233,1,0,16, -455,0,86, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,89,91,92,131,133,196,198,203,204,205,206,207,208,209,210,211, - 212,213,214,215,216,217,218,219,435,442,485,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28,29, - 57,89,91,131,133,196,198,203,204,205,206,207,208,209,210,211,212,213, - 214,215,216,217,218,219,435,442,492,538, -493,427,425,424,423,38,1,0,132, -493,427,425,424,423,38,1,0,132, -493,427,425,424,423,38,1,0,132, -493,427,425,424,423,38,1,0,132, -493,427,425,424,423,38,1,0,132, -705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461,460, - 459,455,429,425,423,38,1,0,46,51,52,54,86,91,93,96,140,141,145,146,147, - 148,149,150,154,157,158,185,187,189,195,196,197,199,200,203,205,220,224, - 225,229,413,414,415,416,417,418,419,420,421,422, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,0,39,40,41,45,46,47,49, -696,695,694,693,688,687,686,685,684,0, -688,687,686,685,684,0, -704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, - 455,429,425,423,1,0, -683,0, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -459,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, - 212,213,214,215,216,217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, - 212,213,214,215,216,217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, - 212,213,214,215,216,217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, - 212,213,214,215,216,217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,521,518,517,491,460,429,231, - 135,134,0,2,6,7,8,9,15,17,21,89,91,131,133,198,206,207,208,209,210,211, - 212,213,214,215,216,217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,25,29,89,91,131,133,196,198, - 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, - 492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,25,29,89,91,131,133,196,198, - 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, - 492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,25,27,29,89,91,131,133,196,198, - 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, - 492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,25,27,29,89,91,131,133,196,198, - 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, - 492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,25,27,29,89,91,131,133,196,198, - 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, - 492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,25,27,29,89,91,131,133,196,198, - 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,442, - 492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,24,25,27,29,89,91,131,133,196, - 198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219, - 442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,24,25,27,29,89,91,131,133,196, - 198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219, - 442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,29,89,91,131,133, - 196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, - 219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,29,89,91,131,133, - 196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, - 219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,89,91,131, - 133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,89,91,131, - 133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, - 218,219,442,492,538, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,1,0,51,52, -427,425,424,423,38,0,39,40,41,45,46,47,49, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -493,0,132, -704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, - 455,429,425,423,233,1,0,16, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,540,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518, - 517,491,460,429,241,240,239,238,237,236,235,234,231,135,134,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,1,0,51,52, -544,0,267, -544,427,425,424,423,38,1,0,51,52, -704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459,455, - 429,425,423,233,1,0,16, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,1,0,51,52, -493,427,425,424,423,38,1,0,132, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,1,0,51,52, -705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461,460, - 459,455,429,427,425,424,423,38,1,0,51,52, -705,704,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,461,460, - 459,455,429,427,425,424,423,38,1,0, -427,425,424,423,38,0,39,40,41,45,46,47,49, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, - 455,429,425,423,1,0, -688,687,686,685,684,0, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,3,133,442,536, -459,0,93, -459,0,93, -459,0,93, -459,0,93, -459,0,93, -459,0,93, -459,0,93, -459,0,93, -459,0,93, -459,0,93, -459,0,93, -544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, - 505,504,503,502,501,500,499,498,497,496,495,493,459,432,425,423,38,1,0, - 197,199,200,201,202, -544,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506, - 505,504,503,502,501,500,499,498,497,496,495,493,459,432,425,423,38,1,0, - 197,199,200,201,202, -544,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,496,495,493,459,432,427,425,424,423,38,1,0,195,196, -544,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,496,495,493,459,432,427,425,424,423,38,1,0,195,196, -544,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,496,495,493,459,432,427,425,424,423,38,1,0,195,196, -544,518,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501, - 500,499,498,497,496,495,493,459,432,427,425,424,423,38,1,0,195,196, -544,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499, - 498,497,496,495,493,459,432,427,425,424,423,38,1,0,191,192,193,194, -544,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499, - 498,497,496,495,493,459,432,427,425,424,423,38,1,0,191,192,193,194, -544,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495, - 493,459,432,427,425,424,423,38,1,0,189,190, -544,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495, - 493,459,432,427,425,424,423,38,1,0,189,190, -544,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,493,459, - 432,427,425,424,423,38,1,0,187,188, -544,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,493,459, - 432,427,425,424,423,38,1,0,187,188, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,0,39,40,41,45,46,47,49, -427,425,424,423,38,0,39,40,41,45,46,47,49, -540,241,240,239,238,237,236,235,234,1,0,51,52, -704,703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686, - 685,684,683,682,681,680,526,524,521,520,519,518,517,511,509,507,460,459, - 455,429,425,423,233,1,0, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,681,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517, - 491,460,429,231,135,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27, - 28,29,57,89,91,131,133,196,198,203,204,205,206,207,208,209,210,211,212, - 213,214,215,216,217,218,219,435,442,485,492,538, -704,702,701,700,699,698,697,696,695,694,693,692,691,688,687,686,685,684,683, - 682,537,535,534,533,532,531,530,529,528,527,526,525,524,521,518,517,491, - 460,429,231,135,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91, - 131,133,196,198,203,204,205,206,207,208,209,210,211,212,213,214,215,216, - 217,218,219,442,492,538, -704,702,701,700,699,698,697,696,695,694,693,691,682,135,134,0,21,133,442, -427,425,424,423,38,1,0,51,52, -704,702,701,700,699,698,697,696,695,694,693,691,688,687,686,685,684,682,459, - 429,1,0,51,52,138, -459,1,0,51,52, -459,1,0,51,52, -540,241,240,239,238,237,236,235,234,0,4,242,594, -427,425,424,423,38,0,39,40,41,45,46,47,49, -459,0,93, + 550,549,548,547,546,545,0,31,32,243,256,257,258,259,260,261,262,263,264, + 265,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283, + 284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301, + 302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319, + 320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337, + 338,339,340,341,342,343,345,346,347,348,349,350,351,352,353,354,355,356, + 357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374, + 375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392, + 393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410, + 411, +703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,681,680,526,525,523,520,519,518,517,516,510,508,506,459,458,454, + 428,424,422,232,1,0,16, +454,0,86, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27,28, + 29,57,89,91,92,131,133,153,195,197,202,203,204,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,434,441,484,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,0,2,6,7,8,9,10,12,15,17,21,23,24,25,26,27,28,29,57, + 89,91,131,133,153,195,197,202,203,204,205,206,207,208,209,210,211,212, + 213,214,215,216,217,218,434,441,491,538, +492,426,424,423,422,38,1,0,132, +492,426,424,423,422,38,1,0,132, +492,426,424,423,422,38,1,0,132, +492,426,424,423,422,38,1,0,132, +492,426,424,423,422,38,1,0,132, +704,703,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460,459, + 458,454,428,424,422,38,1,0,46,51,52,54,86,91,93,96,139,140,144,145,146, + 147,148,149,153,156,157,184,186,188,194,195,196,198,199,202,204,219,223, + 224,228,412,413,414,415,416,417,418,419,420,421, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,0,39,40,41,45,46,47,49, +695,694,693,692,687,686,685,684,683,0, +687,686,685,684,683,0, +703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459,458, + 454,428,424,422,1,0, +682,0, +703,701,700,699,698,697,696,695,694,693,692,690,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +458,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,0,2,6,7,8,9,15,17,21,89,91,131,133,153,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,0,2,6,7,8,9,15,17,21,89,91,131,133,153,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,0,2,6,7,8,9,15,17,21,89,91,131,133,153,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,0,2,6,7,8,9,15,17,21,89,91,131,133,153,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,520,517,516,490,459,428,230, + 134,0,2,6,7,8,9,15,17,21,89,91,131,133,153,197,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,25,29,89,91,131,133,153,195,197, + 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, + 491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,25,29,89,91,131,133,153,195,197, + 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, + 491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,25,27,29,89,91,131,133,153,195,197, + 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, + 491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,25,27,29,89,91,131,133,153,195,197, + 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, + 491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,25,27,29,89,91,131,133,153,195,197, + 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, + 491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,25,27,29,89,91,131,133,153,195,197, + 202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,441, + 491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,24,25,27,29,89,91,131,133,153,195, + 197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, + 441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,24,25,27,29,89,91,131,133,153,195, + 197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, + 441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,27,29,89,91,131,133,153, + 195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,27,29,89,91,131,133,153, + 195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,89,91,131,133, + 153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,27,28,29,89,91,131,133, + 153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216, + 217,218,441,491,538, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,1,0,51,52, +426,424,423,422,38,0,39,40,41,45,46,47,49, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +492,0,132, +703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459,458, + 454,428,424,422,232,1,0,16, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,540,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517, + 516,490,459,428,240,239,238,237,236,235,234,233,230,134,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,1,0,51,52, +544,0,266, +544,426,424,423,422,38,1,0,51,52, +703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,681,680,526,525,523,520,519,518,517,516,510,508,506,459,458,454, + 428,424,422,232,1,0,16, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,1,0,51,52, +492,426,424,423,422,38,1,0,132, +703,701,700,699,698,697,696,695,694,693,692,690,134,1,0,51,52, +704,703,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460,459, + 458,454,428,426,424,423,422,38,1,0,51,52, +704,703,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,460,459, + 458,454,428,426,424,423,422,38,1,0, +426,424,423,422,38,0,39,40,41,45,46,47,49, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459,458, + 454,428,424,422,1,0, +687,686,685,684,683,0, +703,701,700,699,698,697,696,695,694,693,692,690,134,0,3,133,441,536, +458,0,93, +458,0,93, +458,0,93, +458,0,93, +458,0,93, +458,0,93, +458,0,93, +458,0,93, +458,0,93, +458,0,93, +458,0,93, +544,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, + 504,503,502,501,500,499,498,497,496,495,494,492,458,431,424,422,38,1,0, + 196,198,199,200,201, +544,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508,507,506,505, + 504,503,502,501,500,499,498,497,496,495,494,492,458,431,424,422,38,1,0, + 196,198,199,200,201, +544,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, + 499,498,497,496,495,494,492,458,431,426,424,423,422,38,1,0,194,195, +544,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, + 499,498,497,496,495,494,492,458,431,426,424,423,422,38,1,0,194,195, +544,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, + 499,498,497,496,495,494,492,458,431,426,424,423,422,38,1,0,194,195, +544,517,516,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500, + 499,498,497,496,495,494,492,458,431,426,424,423,422,38,1,0,194,195, +544,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, + 497,496,495,494,492,458,431,426,424,423,422,38,1,0,190,191,192,193, +544,515,514,513,512,511,510,509,508,507,506,505,504,503,502,501,500,499,498, + 497,496,495,494,492,458,431,426,424,423,422,38,1,0,190,191,192,193, +544,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494, + 492,458,431,426,424,423,422,38,1,0,188,189, +544,511,510,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494, + 492,458,431,426,424,423,422,38,1,0,188,189, +544,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494,492,458, + 431,426,424,423,422,38,1,0,186,187, +544,509,508,507,506,505,504,503,502,501,500,499,498,497,496,495,494,492,458, + 431,426,424,423,422,38,1,0,186,187, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,0,39,40,41,45,46,47,49, +426,424,423,422,38,0,39,40,41,45,46,47,49, +540,240,239,238,237,236,235,234,233,1,0,51,52, +703,702,701,700,699,698,697,696,695,694,693,692,691,690,689,688,687,686,685, + 684,683,682,681,680,526,525,523,520,519,518,517,516,510,508,506,459,458, + 454,428,424,422,232,1,0, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 681,537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516, + 490,459,428,230,134,0,2,6,7,8,9,10,12,15,17,18,20,21,23,24,25,26,27,28, + 29,57,89,91,131,133,153,195,197,202,203,204,205,206,207,208,209,210,211, + 212,213,214,215,216,217,218,434,441,484,491,538, +703,701,700,699,698,697,696,695,694,693,692,691,690,687,686,685,684,683,682, + 537,535,534,533,532,531,530,529,528,527,526,525,524,523,520,517,516,490, + 459,428,230,134,0,2,6,7,8,9,15,17,21,23,24,25,26,27,28,29,57,89,91,131, + 133,153,195,197,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,441,491,538, +703,701,700,699,698,697,696,695,694,693,692,690,134,0,21,133,441, +426,424,423,422,38,1,0,51,52, +703,701,700,699,698,697,696,695,694,693,692,690,687,686,685,684,683,458,428, + 1,0,51,52,137, +458,1,0,51,52, +458,1,0,51,52, +540,240,239,238,237,236,235,234,233,0,4,241,594, +426,424,423,422,38,0,39,40,41,45,46,47,49, +458,0,93, }; -static unsigned const char ag_astt[28270] = { - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,7,1,1,9,5,2,2,2,2, - 2,2,2,2,2,2,2,2,2,1,8,8,8,8,8,2,2,2,2,2,1,8,1,7,1,0,1,1,1,1,1,1,1,1,1,1,1, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4, - 4,2,4,4,4,4,2,4,4,4,7,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,3,1,1,1,1,1,1,1,1, - 1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +static unsigned const char ag_astt[27983] = { + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,7,1,1,9,5,2,2,2,2,2,2, + 2,2,2,2,2,2,1,8,8,8,8,8,2,2,2,2,1,8,1,7,1,0,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,2,4,4, + 4,4,2,4,4,4,7,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,3,1,1,1,1,1,1,1,1,1,1,1,1, + 1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,7,2,8,8,1,1,1,1,1,3,7,3,3,1,3, - 1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,7,2,8,8,1,1,1,1,1,3,7,3,3,1,3,1,1,1,1,1,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,5,5,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1, + 5,5,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,1,1,8,8,8,8,8,5,5,1,5,5,5,1,2,2,5,9,7,1,1,1, - 1,1,3,1,1,2,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,1,1,1,8,8,8,8,8,5,5,1,5,5,5,1,2,5,9,7,1,1,1,1,1,3,1,1,2,1,2,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,8,8,8, - 8,8,2,2,2,2,2,1,3,1,7,1,3,3,1,1,3,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,7,1,3,5,1,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,7,1,1,1,8,1,7,1,1,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,7,1,1,1,8,8, - 8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,2,2, - 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1, - 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,7,1,1,1,1,1,1,1,1,7,1,1,1,1,1,2,2,7,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5, + 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,1,8,8,8,8,8,2,2,2,2,1,3,1,7,1, + 3,3,1,1,3,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5, + 5,5,5,1,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,1,7,1,3,5,5,5,5,5,5, + 7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,1,7,1,3,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1, + 1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,8,1,7,1,1,8,1,7,1,1,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, + 1,1,2,7,1,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2, + 2,7,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1, + 1,1,1,2,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,1,7,1,1,1,1,1,2,2,7,1,1,1,1,1,1,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,7,1,1,1,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,1,1,1,1, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,7,1,1, + 1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,9,7,3,3,3,1,3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,9,7,3,3,3,1,3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,1,1,8,8,8, - 8,8,1,8,8,1,1,1,1,1,2,2,3,7,1,1,1,1,1,3,3,1,3,1,1,1,1,1,1,2,1,2,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,1,1, + 8,8,8,8,8,1,8,8,1,1,1,1,1,2,3,7,1,1,1,1,1,3,3,1,3,1,1,1,1,1,1,2,1,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1, - 3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, - 5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5, - 5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3, - 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5, - 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, + 7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1, + 3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5, - 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7, + 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7, 1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, 5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5, 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1, 3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, 5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5, 5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3, - 5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, - 8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, + 7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,8,8,8,8,8,8, + 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, - 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, - 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, + 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, - 5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, - 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5, - 5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1, - 3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5, - 7,1,3,8,8,8,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, + 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5,5,5,5,7,1,3,5,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, + 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, + 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1, + 1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, + 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1, 7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, - 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, - 1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, + 1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1, - 8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1, - 7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8, - 8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1, - 1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1, - 7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8, - 8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, - 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,5,2,2,2,2,2,2,2,2,2,2,2,5,2,5,5,2, - 2,2,2,2,5,2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,2,5,5,5, - 5,5,1,7,1,3,2,5,5,5,5,5,5,1,7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,1,4,4,4,4,4,4,4,4,4,4,7,1,4,4,4,4,4,1,7,1,1,5,1,2,2,2,2,2,2,2,2,2,2,2,1, - 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, - 1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,7,2,2,1,2,2,1,1,1,2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 1,2,2,1,1,2,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,2,7,1,1,1,2, - 7,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,5,5,7,1, - 3,8,8,8,8,8,1,7,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,8, - 8,8,8,8,1,7,1,1,2,2,2,2,2,7,2,2,2,2,7,2,2,7,4,4,4,4,4,4,4,2,2,2,2,4,2,2,2, - 2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,7,4,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,7,2,1,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,7,1,10,10,10,10,10,5,2,10,10,10,10,10,10,10,10,10,7,10,10,10,10,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,10, - 10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,7,10,10,10,10,10,10,10,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,9,2,2,1,1,2,10,10,10,10,10,9,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4,2,2,4,4, - 7,2,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3, - 5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,1,7,1,1,8,1,7,1,1, - 8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1, - 7,1,1,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,2,2,2,2,2,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, + 1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, + 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1,8,8,8,8,1,7,1,1, + 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8, + 8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, + 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1, + 8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7, + 1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8, + 1,7,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,5,2,2,2,2,2,2,2,2,2,2,2,5,2,5,5,2,2,2,2, + 2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,2,5,5,5,5,5,1, + 7,1,3,2,5,5,5,5,5,5,1,7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,4, + 4,4,4,4,4,4,4,4,4,7,1,4,4,4,4,4,1,7,1,1,5,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1, + 1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2, + 2,1,2,2,1,1,1,2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,2,2, + 1,1,2,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,2,7,1,1,1,2,7,1,1, + 1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,7,2,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,5,5,7,1,3,8,8, + 8,8,8,1,7,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,8,8,8,8, + 8,1,7,1,1,2,2,2,2,2,7,2,2,2,2,7,2,2,7,4,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7, + 2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,7,1,10,10,10,10,10,5,2,10,10,10,10,10,10,10,10,10,7, + 10,10,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,7,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,10,10,10,10,10,10,10,10,10,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,9,2,2,1,1,2, + 10,10,10,10,10,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,2,4,4,4,4,2,2,4,4,7,2,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3, + 5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5,7,1,3,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, - 1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, - 5,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, - 7,1,3,1,1,1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,1,7,1,3,1,1,5,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,1,7,1,3,1,1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,1,7,1,3,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, - 1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1, - 1,8,8,8,8,8,1,7,1,5,5,5,5,5,5,7,1,3,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,8, - 8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,8, - 8,8,8,8,1,7,1,1,10,10,1,10,10,10,10,10,10,10,10,10,10,10,10,2,10,10,10,10, - 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,7,5,5,5,5,5, - 5,7,1,3,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1, - 1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8, + 1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,8,1,7, + 1,1,8,1,7,1,1,8,1,7,1,1,8,1,7,1,1,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,2,2,2,2,2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2, + 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1, + 2,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1, + 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,5,1,1,1,1,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,5,1,1,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,5,1,1,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4, + 4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1, + 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1, + 1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8, + 8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,5,5,5,5,5,5,7,1,3,8,8,8, + 8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,7,1,3,8,8,8,8,8,1,7, + 1,1,5,5,5,5,5,5,7,1,3,8,8,8,8,8,1,7,1,1,10,10,1,10,10,10,10,10,10,10,10,10, + 10,10,10,2,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,7,5,5,5,5,5,5,7,1,3,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,7,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, @@ -4424,440 +4405,445 @@ static unsigned const char ag_astt[28270] = { 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,7,3,1,7,3,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,7,3,1,7,3,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, - 7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1, + 1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,2,2,1,2,2,1,1,1,2,2,1,1,1,1,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,1,1,2,8,8,8,8,8,1,7,1,1,1,1,1,1,1, - 1,3,7,1,3,3,1,3,1,1,1,2,2,2,1,1,1,2,2,2,2,2,7,2,2,2,2,3,2,2,2,2,2,2,2,2,2, - 2,2,7,3,2,1,2,2,2,2,2,2,2,7,3,2,2,2,1,2,2,2,2,7,2,1,7,1,1,7,1,1,7,1,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,2,2,1,2,2,1,1,1,2,2,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,1,1,2,8,8,8,8,8,1,7,1,1,1,1,1,1, + 1,1,3,7,1,3,3,1,3,1,1,1,2,2,2,1,1,1,2,2,2,2,2,7,2,2,2,2,3,2,2,2,2,2,2,2,2, + 2,2,2,7,3,2,1,2,2,2,2,2,2,2,7,3,2,2,2,1,2,2,2,2,7,2,1,7,1,1,7,1,1,7,1,2,2, + 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1, + 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1, + 1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2, + 1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2, + 2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, + 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1, + 2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1, + 2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1, + 1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, + 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1, 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1, - 1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, - 2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2, - 1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, + 1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, + 2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1, + 1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1, + 1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2, - 2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, - 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, - 2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2, + 1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, + 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2, + 1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1, + 1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2, 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, - 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, - 1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1, + 1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, + 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1, 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, - 1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, - 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1, - 1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1, + 1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1, + 2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1, + 1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2, - 1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, - 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, - 1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1, + 1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, + 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1, + 1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, 2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1, + 1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1, 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2, - 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1, - 1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, - 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1, + 1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7, + 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1, 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1, - 1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, - 2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, - 2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, + 2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, + 2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2, + 1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1, - 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2, - 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, - 1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1, + 1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2, + 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1, + 1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, + 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1, 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, - 1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, - 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, - 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1, + 1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2, + 1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2, + 1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, - 2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, - 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2, - 1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2, + 2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, + 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1, + 2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1, + 1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1, - 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, - 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, - 1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1, + 2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1, + 1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, + 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1, 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1, - 1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, - 2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2, - 1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, + 1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, + 2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1, + 1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2, - 2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, - 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1, - 2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1, - 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, - 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, - 1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, - 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1, - 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, - 1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, - 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1, - 1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,1,1,2,2,2,2,2, - 7,2,2,2,2,2,2,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2, - 2,2,2,2,7,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2,1,2,2,2,2,2,2,2,7, - 2,2,2,2,1,2,2,2,2,2,2,2,7,2,2,2,2,1,2,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,1, - 1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2, - 7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2, - 2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2, - 2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2, - 2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2, - 2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,1,1,1, - 1,1,1,2,9,7,2,1,1,2,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,1,1,2,2,2,2, + 2,7,2,2,2,2,2,2,2,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,1,1,2,2,2,2,2,7,2,2,2,2,2, + 2,2,2,2,2,7,2,2,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,7,2,2,2,2,1,2,2,2,2,2,2,2, + 7,2,2,2,2,1,2,2,2,2,2,2,2,7,2,2,2,2,1,2,1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2, + 1,1,1,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2, + 2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2, + 2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2, + 2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,7,2,2,1,2,2, + 2,2,2,2,2,2,2,7,2,2,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2, + 2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,1,1, + 1,1,1,1,2,9,7,2,1,1,2,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2, - 1,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,1,7,1,3,1,2,7,2,1,1,2,1,1,5,5,5, - 5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, - 1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2,2,4,4,7,2,1,1,2,7,1,1,1,2,7,2,1,1, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5, + 5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,5,5, + 5,5,5,5,7,1,3,5,5,5,5,5,5,7,1,3,5,5,1,7,1,3,1,2,7,2,1,1,2,1,1,5,5,5,5,5,5, + 7,1,3,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,2,2,2, + 2,2,2,2,2,2,2,2,2,4,4,4,4,2,4,4,7,2,1,1,2,7,1,1,1,2,7,2,1,1,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, + 1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,7,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1, + 2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3, + 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2, + 2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2, + 2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2, + 1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1, + 1,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,7,2,1,1,2,1,2,1,2,1, - 1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1, - 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, - 7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,1,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7, - 1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1, - 1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5, + 5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1, + 1,1,1,1,1,2,2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2, - 2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2, - 1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2, + 1,2,2,2,2,2,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1, + 2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2, - 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, - 1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5, + 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1, + 1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5, 5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2, - 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,7,1, - 3,5,5,5,5,5,5,5,5,7,1,3,1,1,1,1,3,7,3,3,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,2,2,1,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1, - 2,7,2,2,1,2,1,1,1,1,7,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7, - 1,1,2,1,2,2,2,2,2,1,1,1,1,2,3,7,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2, - 2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2, + 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2, + 1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, + 5,5,5,5,7,1,3,1,1,1,1,3,7,3,3,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,2,2,1,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2,7,2,2,1, + 2,1,1,1,1,7,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,2,1,2, + 2,2,2,2,1,1,1,2,1,3,7,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1, + 1,2,2,2,2,2,2,2,2,2,7,2,2,2,2,2,2,7,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,4,4,4,4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,7,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7, - 1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, - 1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,7,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7, - 1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8, + 4,7,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1,7,1,1, + 7,1,1,7,1,1,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,7,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, - 1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8, + 1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5, + 8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1, + 3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1, - 7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1, - 1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1, - 1,1,1,2,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,2,7, - 2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,7,1,1,1,1,2,7,2,2,1,2, - 1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,10,10,10,10,10,10,10,10,10,10,10,10,10,10, - 10,10,10,10,10,5,5,5,5,7,1,3,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8, - 1,7,1,1,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, - 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, - 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,7,3,3,1,3,1,1,1,5,5,5,5,5,5,7,1, - 3,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5, - 5,5,5,7,1,3,5,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1, - 1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7, - 1,3,8,1,7,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,5,7,1,3,1,1,7,2, - 1,2,2,2,2,2,2,2,2,2,7,9,2,2,1,1,2,10,10,10,10,10,9,4,4,4,4,2,2,4,4,7,2,1,1, + 5,5,5,1,7,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1, + 2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2, + 2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1, + 1,1,1,2,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,7,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2, + 7,2,2,1,2,1,1,1,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,5, + 5,5,5,7,1,3,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8, + 8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1, + 1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,7,1,3,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7, + 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,3,7,3,3,1,3,1,1,1,5,5,5,5,5,5,7,1,3,8,8,8,8,8,1,7,1,1, + 5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,5,5,5,5, + 5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,1,7,1,1,5,5,5,5,5,5,5,7,1,3,5,5,5,5,5,5,5,7,1,3,8,1,7,1,1,2,1,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7, + 1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,7,2,5,5,5,5,5,5,5,5,7,1,3,1,1,7,2,1,2,2,2,2,2,2,2,2,2,7,9,2, + 2,1,1,2,10,10,10,10,10,4,4,4,4,2,2,4,4,7,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1, - 1,7,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, - 2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,2, - 1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,4,4,4,4,4,4,7,1,1,4,4,4,4,4,4,7,1,1,4,4,4,4,4,4,7,1,1,4,4,4,4,4,4,7,1,1, - 4,4,4,4,4,4,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,8,8,1,7,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,1,1,1,1,2,7, - 2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,7,1,1,1,1,1,7,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7, - 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1, - 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2, - 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, - 1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, - 1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, - 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7, - 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, - 1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, - 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2, - 1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,2,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, - 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, - 2,1,2,1,1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, - 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1, - 1,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, - 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, - 1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, - 2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1, - 2,1,2,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,7,1,2,2,2,2,2,2,2,2,2,2,2, + 1,2,2,2,2,2,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1, + 2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2, + 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,7,1,1,4,4,4,4, + 4,4,7,1,1,4,4,4,4,4,4,7,1,1,4,4,4,4,4,4,7,1,1,4,4,4,4,4,4,7,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8, + 1,7,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2, + 1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,1,1,1,7,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,7,2,7,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1, + 1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, - 2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1, + 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1, + 1,1,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, + 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1, + 2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,1,1, - 1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1, - 1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, - 2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2, - 1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, - 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1, + 1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, + 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1, + 1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, + 2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1, + 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2, + 1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,2, + 1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,2,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,2, 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2, - 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1, - 1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,1, - 7,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2, - 1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,1, - 1,1,1,2,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1, - 1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2, - 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1, - 1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, + 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1, + 1,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, + 2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2, + 1,2,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2, 2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2, - 2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,7,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1, - 3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,1,7,1,1,1,7,1,5,5,5,5,5,5,1,7,1,3,2,1,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1, - 7,1,1,1,4,4,4,4,4,4,7,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,7,1,1,1,1,2,7,2,2,1,2,1,1,1,2,2,2,2,2,2,2,2, - 2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1, - 1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,4,4,4,4,4,4,4,4,2,2,2,2,4,4,4,4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,7,2,2,2,2,2,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,1,1,1,1,1,7, - 2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,3,4,1,1,1,1,1, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1, - 4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 7,1,1,1,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,7,1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,7,1,1,1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,7,1,1,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1, - 4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1, - 2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,8,8,8,8,8,8,8,8,8,1,7,1,1,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7, - 2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1, - 1,1,2,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,7,2,1,1,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,5,2,1,7,1,3,2,5,5,7,1,3,8,1,7,1,1,2,2,2,2,2,2,2,2,2,7,2,2,1,1,1,1,1,2,7, - 2,2,1,2,1,1,1,1,7,2 + 2,7,2,1,1,2,1,2,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1, + 1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1, + 2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1, + 1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2, + 2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2, + 7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,2,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,8,8,1,7,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1, + 1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1, + 1,8,8,8,8,8,1,7,1,1,8,8,8,8,8,1,7,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,2,2,2,2,2, + 2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7, + 2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1, + 2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,2,1,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 7,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,1,7,1,5,5,5,5,5, + 5,1,7,1,3,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,7,2,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,1,7,1,1,1,4,4,4,4,4,4,7,1,8,8,8,8,8,8,8,8, + 8,8,8,8,8,1,7,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,7,1,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,7,1,1,1,1,2,7, + 2,2,1,2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,4,4,2,2,2,2,4,4,4,4,2,2,2, + 2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,7,2,2,2,2,2,2,2, + 2,2,2,2,2,2,7,1,1,1,1,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7,2,1,7, + 2,1,7,2,1,7,3,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,7,1,1,1,1,1,4,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,4,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,7,1,1,4,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,4, + 1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,1,1,1,1,1,1,2,7,2,2,1, + 2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,1,1,1,2,7,2,2,1,2,1,1,1,8,8,8,8,8,8,8, + 8,8,1,7,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,7,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,1,2,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2,1,1,2,1,2,1,2,1,1,2,1,1,1,1,1,1,1, + 1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,7,2, + 1,1,2,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,7,2,1,1,8,8,8,8,8,1,7,1,1,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,5,2,1,7,1,3,2,5,5,7,1,3,8,1,7,1,1,2,2,2,2,2,2,2,2,2, + 7,2,2,1,1,1,1,1,2,7,2,2,1,2,1,1,1,1,7,2 }; static const unsigned short ag_pstt[] = { -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,1,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,1,2, 19,21, -137,137,137,137,137,137,137,137,137,137,137,137,137,3,8,8,8,8,8,172,171,170, - 136,135,7,8,10,2,9,0,11,11,11,10,8,11,5,5,4,6,4, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,3,1,893, -138,138,138,138,138,138,138,138,138,138,138,138,139,139,139,139,139,138,169, - 169,138,169,169,169,169,168,169,169,169,4,139, +136,136,136,136,136,136,136,136,136,136,136,136,3,8,8,8,8,8,171,170,169,135, + 7,8,10,2,9,0,11,11,11,10,8,11,5,5,4,6,4, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,3,1,890, +137,137,137,137,137,137,137,137,137,137,137,137,138,138,138,138,138,168,168, + 168,137,168,168,168,168,167,168,168,168,4,138, 12,13,14,15,16,17,18,19,20,21,22,23,24,25,5,39,42,38,37,36,35,34,33,32,31, 30,29,28,27,26, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, @@ -4868,7 +4854,7 @@ static const unsigned short ag_pstt[] = { 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,1,6,1,883, + 20,20,1,6,1,880, 40,7,39, 42,42,41,43,44,45,40,25,8,25,25,48,25,47,46,46,42,42, 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, @@ -4878,483 +4864,482 @@ static const unsigned short ag_pstt[] = { 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49, - 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,20,20,49,49,49,49, - 49,49,49,49,1,9,1,49, -137,137,137,137,137,137,137,137,137,137,137,137,137,117,118,119,120,121,122, - 123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140, - 68,69,70,71,72,73,141,142,143,144,145,146,74,75,76,77,78,147,148,149,79, - 80,81,82,83,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164, + 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,20,20,49,49,49,49,49, + 49,49,1,9,1,49, +136,136,136,136,136,136,136,136,136,136,136,136,117,118,119,120,121,122,123, + 124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,68, + 69,70,71,72,73,141,142,143,144,145,146,74,75,76,77,78,147,148,149,79,80, + 81,82,83,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164, 113,65,66,67,171,172,173,174,175,176,177,178,179,180,181,182,183,184, 185,186,165,166,167,168,169,170,84,85,86,87,88,89,51,52,53,90,91,92,93, 94,95,96,97,98,54,55,99,100,101,102,103,104,105,106,56,57,58,107,108,59, 60,109,110,111,112,61,62,63,64,271,271,271,271,271,271,271,271,271,271, 271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, - 271,271,271,271,18,19,22,271,271,271,271,271,21,21,41,21,21,21,40,136, - 135,21,19,10,267,268,269,266,272,40,271,271,37,270,111,112,272,50,265, - 202,266,266,266,266,266,266,266,266,266,266,333,333,333,333,333,334,335, - 336,337,340,340,340,341,342,346,346,346,346,347,348,349,350,351,352,353, - 354,357,357,357,358,359,360,361,362,363,364,365,366,370,370,370,370,371, - 372,373,374,375,376,248,247,246,245,244,243,264,263,262,261,260,259,258, - 257,256,255,254,253,252,251,250,249,190,116,189,115,188,114,187,242,241, - 240,239,238,237,236,235,234,233,232,231,230,229,228,227,227,227,227,227, - 227,226,225,224,223,223,223,223,223,223,222,221,220,219,218,217,216,216, - 216,216,215,215,215,215,214,213,212,211,210,209,208,207,206,205,204,203, - 201,200,199,198,197,196,195,194,193,192,191,265, -137,137,137,137,137,137,137,137,137,137,137,137,137,3,8,8,8,8,8,172,171,170, - 136,135,7,4,10,11,9,3,3,10,8,3,5,5,4,6,4, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,12,1,913, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,13,1,912, -20,20,14,1,911, -20,20,15,1,909, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,16,1,908, -20,1,17,1,907, -20,20,20,20,20,20,18,1,906, -20,20,20,20,20,20,19,1,905, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,20,1,904, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,21,1,903, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,22,1,902, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,23,1,901, -20,20,20,20,20,1,24,1,895, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,25,1,888, -137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,26,267,273,265, - 265, -137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,27,274,265,265, + 271,271,271,271,18,19,22,271,271,271,271,271,21,21,41,21,21,21,40,135, + 21,19,10,267,268,269,266,272,40,271,271,37,270,111,112,272,50,265,202, + 266,266,266,266,266,266,266,266,266,266,332,332,332,332,332,333,334,335, + 336,339,339,339,340,341,345,345,345,345,346,347,348,349,350,351,352,353, + 356,356,356,357,358,359,360,361,362,363,364,365,369,369,369,369,370,371, + 372,373,374,375,248,247,246,245,244,243,264,263,262,261,260,259,258,257, + 256,255,254,253,252,251,250,249,190,116,189,115,188,114,187,242,241,240, + 239,238,237,236,235,234,233,232,231,230,229,228,227,227,227,227,227,227, + 226,225,224,223,223,223,223,223,223,222,221,220,219,218,217,216,216,216, + 216,215,215,215,215,214,213,212,211,210,209,208,207,206,205,204,203,201, + 200,199,198,197,196,195,194,193,192,191,265, +136,136,136,136,136,136,136,136,136,136,136,136,3,8,8,8,8,8,171,170,169,135, + 7,4,10,11,9,3,3,10,8,3,5,5,4,6,4, +20,20,20,20,20,20,20,20,20,20,20,20,20,1,12,1,910, +20,20,20,20,20,20,20,20,20,20,20,20,20,1,13,1,909, +20,20,14,1,908, +20,20,15,1,906, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,16,1,905, +20,1,17,1,904, +20,20,20,20,20,20,18,1,903, +20,20,20,20,20,20,19,1,902, +20,20,20,20,20,20,20,20,20,20,20,20,20,1,20,1,901, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,21,1,900, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,22,1,899, +20,20,20,20,20,20,20,20,20,20,20,20,20,1,23,1,898, +20,20,20,20,20,1,24,1,892, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,25,1,885, +136,136,136,136,136,136,136,136,136,136,136,136,135,26,267,273,265,265, +136,136,136,136,136,136,136,136,136,136,136,136,135,27,274,265,265, 275,1,28,1,275, 276,1,29,1,276, 277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277, 277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277, - 277,277,277,277,277,277,1,30,1,277, -146,31,280,278,279, + 277,277,277,277,277,1,30,1,277, +145,31,280,278,279, 281,281,281,281,281,1,32,1,281, 282,282,282,282,282,1,33,1,282, -137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,34,283,265,265, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,35,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,338,340,226,326,312,265,339,327,331,330,329,328,225,331,321, - 320,319,318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,36,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,338,341,226,326,312,265,339,327,331,330,329,328,225,331,321, - 320,319,318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,37,342,265,265, +136,136,136,136,136,136,136,136,136,136,136,136,135,34,283,265,265, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,35,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,338,340,225,326,311,265,226,339,327,331,330,329,328,224,331,320, + 319,318,317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,36,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,338,341,225,326,311,265,226,339,327,331,330,329,328,224,331,320, + 319,318,317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,136,135,37,342,265,265, 343,345,347,349,351,38,352,350,348,346,344, -164,146,39,356,278,355,353,279,354, +163,145,39,356,278,355,353,279,354, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,40,1,878, + 20,20,20,20,20,40,1,875, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,41,1,884, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,41,1,881, 357,25,42,358,358,358, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,43,1,882, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,43,1,879, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,44, - 1,880, + 1,877, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,45,1,879, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,45,1,876, 359,361,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379, - 380,381,382,389,392,393,394,323,325,391,383,387,384,386,390,362,360,310, + 380,381,382,389,393,394,392,323,325,391,383,387,384,386,390,362,360,309, 388,385,41,43,395,44,40,16,46,17,16,16,46,14,46,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16, 359,361,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379, - 380,381,382,389,392,393,394,323,325,391,383,387,384,386,390,362,360,310, + 380,381,382,389,393,394,392,323,325,391,383,387,384,386,390,362,360,309, 388,385,41,44,397,396,47,396,397,396,396,396,396,396,396,396,396,396, 396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396, 396,396,396,396,396,396,396,396,396,396,396,396,396,396, 359,361,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379, - 380,381,382,389,392,393,394,323,325,391,383,387,384,386,390,362,360,310, + 380,381,382,389,393,394,392,323,325,391,383,387,384,386,390,362,360,309, 388,385,41,44,398,396,48,396,398,396,396,396,396,396,396,396,396,396, 396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396, 396,396,396,396,396,396,396,396,396,396,396,396,396,396, -137,137,137,137,137,137,137,137,137,137,137,137,137,117,118,119,120,121,122, - 123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140, - 68,69,70,71,72,73,141,142,143,144,145,146,74,75,76,77,78,147,148,149,79, - 80,81,82,83,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164, +136,136,136,136,136,136,136,136,136,136,136,136,117,118,119,120,121,122,123, + 124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,68, + 69,70,71,72,73,141,142,143,144,145,146,74,75,76,77,78,147,148,149,79,80, + 81,82,83,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164, 113,65,66,67,171,172,173,174,175,176,177,178,179,180,181,182,183,184, 185,186,165,166,167,168,169,170,84,85,86,87,88,89,51,52,53,90,91,92,93, 94,95,96,97,98,54,55,99,100,101,102,103,104,105,106,56,57,58,107,108,59, 60,109,110,111,112,61,62,63,64,401,401,401,401,401,401,401,401,401,401, 401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, 401,401,401,401,18,19,22,401,401,401,401,401,399,401,401,41,43,44,45,40, - 136,135,24,49,267,268,269,266,402,24,24,48,24,47,46,46,401,401,400,38, - 270,111,112,402,50,265,202,266,266,266,266,266,266,266,266,266,266,333, - 333,333,333,333,334,335,336,337,340,340,340,341,342,346,346,346,346,347, - 348,349,350,351,352,353,354,357,357,357,358,359,360,361,362,363,364,365, - 366,370,370,370,370,371,372,373,374,375,376,248,247,246,245,244,243,264, - 263,262,261,260,259,258,257,256,255,254,253,252,251,250,249,190,116,189, - 115,188,114,187,242,241,240,239,238,237,236,235,234,233,232,231,230,229, - 228,227,227,227,227,227,227,226,225,224,223,223,223,223,223,223,222,221, - 220,219,218,217,216,216,216,216,215,215,215,215,214,213,212,211,210,209, - 208,207,206,205,204,203,201,200,199,198,197,196,195,194,193,192,191,265, + 135,24,49,267,268,269,266,402,24,24,48,24,47,46,46,401,401,400,38,270, + 111,112,402,50,265,202,266,266,266,266,266,266,266,266,266,266,332,332, + 332,332,332,333,334,335,336,339,339,339,340,341,345,345,345,345,346,347, + 348,349,350,351,352,353,356,356,356,357,358,359,360,361,362,363,364,365, + 369,369,369,369,370,371,372,373,374,375,248,247,246,245,244,243,264,263, + 262,261,260,259,258,257,256,255,254,253,252,251,250,249,190,116,189,115, + 188,114,187,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228, + 227,227,227,227,227,227,226,225,224,223,223,223,223,223,223,222,221,220, + 219,218,217,216,216,216,216,215,215,215,215,214,213,212,211,210,209,208, + 207,206,205,204,203,201,200,199,198,197,196,195,194,193,192,191,265, 403,403,403,403,403,403,403,1,50,1,403, -20,20,20,20,20,20,20,51,1,1036, -20,20,20,20,20,20,20,52,1,1035, -20,20,20,20,20,20,20,53,1,1034, -20,20,20,20,20,20,20,54,1,1024, -20,20,20,20,20,20,20,55,1,1023, -20,20,20,20,20,20,20,56,1,1014, -20,20,20,20,20,20,20,57,1,1013, -20,20,20,20,20,20,20,58,1,1012, -20,20,20,20,20,20,20,59,1,1009, -20,20,20,20,20,20,20,60,1,1008, -20,20,20,20,20,20,20,61,1,1003, -20,20,20,20,20,20,20,62,1,1002, -20,20,20,20,20,20,20,63,1,1001, -20,20,20,20,20,20,20,64,1,1000, -20,20,20,20,20,20,20,20,20,20,65,1,1069, -20,20,20,20,20,20,20,20,20,20,66,1,1068, -20,20,20,20,20,20,20,20,67,1,1067, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,68,1,1110, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,69,1,1109, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,70,1,1108, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,71,1,1107, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,72,1,1106, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,73,1,1105, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,74,1,1098, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,75,1,1097, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,76,1,1096, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,77,1,1095, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,78,1,1094, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,79,1,1090, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,80,1,1089, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,81,1,1088, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,82,1,1087, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,83,1,1086, -20,20,20,20,20,20,20,84,1,1042, -20,20,20,20,20,20,20,85,1,1041, -20,20,20,20,20,20,20,86,1,1040, -20,20,20,20,20,20,20,87,1,1039, -20,20,20,20,20,20,20,88,1,1038, -20,20,20,20,20,20,20,89,1,1037, -20,20,20,20,20,20,20,90,1,1033, -20,20,20,20,20,20,20,91,1,1032, -20,20,20,20,20,20,20,92,1,1031, -20,20,20,20,20,20,20,93,1,1030, -20,20,20,20,20,20,20,94,1,1029, -20,20,20,20,20,20,20,95,1,1028, -20,20,20,20,20,20,20,96,1,1027, -20,20,20,20,20,20,20,97,1,1026, -20,20,20,20,20,20,20,98,1,1025, -20,20,20,20,20,20,20,99,1,1022, -20,20,20,20,20,20,20,100,1,1021, -20,20,20,20,20,20,20,101,1,1020, -20,20,20,20,20,20,20,102,1,1019, -20,20,20,20,20,20,20,103,1,1018, -20,20,20,20,20,20,20,104,1,1017, -20,20,20,20,20,20,20,105,1,1016, -20,20,20,20,20,20,20,106,1,1015, -20,20,20,20,20,20,20,107,1,1011, -20,20,20,20,20,20,20,108,1,1010, -20,20,20,20,20,20,20,109,1,1007, -20,20,20,20,20,20,20,110,1,1006, -20,20,20,20,20,20,20,111,1,1005, -20,20,20,20,20,20,20,112,1,1004, -20,20,20,20,20,113,1,1070, +20,20,20,20,20,20,20,51,1,1034, +20,20,20,20,20,20,20,52,1,1033, +20,20,20,20,20,20,20,53,1,1032, +20,20,20,20,20,20,20,54,1,1022, +20,20,20,20,20,20,20,55,1,1021, +20,20,20,20,20,20,20,56,1,1012, +20,20,20,20,20,20,20,57,1,1011, +20,20,20,20,20,20,20,58,1,1010, +20,20,20,20,20,20,20,59,1,1007, +20,20,20,20,20,20,20,60,1,1006, +20,20,20,20,20,20,20,61,1,1001, +20,20,20,20,20,20,20,62,1,1000, +20,20,20,20,20,20,20,63,1,999, +20,20,20,20,20,20,20,64,1,998, +20,20,20,20,20,20,20,20,20,20,65,1,1067, +20,20,20,20,20,20,20,20,20,20,66,1,1066, +20,20,20,20,20,20,20,20,67,1,1065, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,68,1,1108, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,69,1,1107, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,70,1,1106, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,71,1,1105, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,72,1,1104, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,73,1,1103, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,74,1,1096, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,75,1,1095, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,76,1,1094, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,77,1,1093, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,78,1,1092, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,79,1,1088, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,80,1,1087, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,81,1,1086, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,82,1,1085, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,83,1,1084, +20,20,20,20,20,20,20,84,1,1040, +20,20,20,20,20,20,20,85,1,1039, +20,20,20,20,20,20,20,86,1,1038, +20,20,20,20,20,20,20,87,1,1037, +20,20,20,20,20,20,20,88,1,1036, +20,20,20,20,20,20,20,89,1,1035, +20,20,20,20,20,20,20,90,1,1031, +20,20,20,20,20,20,20,91,1,1030, +20,20,20,20,20,20,20,92,1,1029, +20,20,20,20,20,20,20,93,1,1028, +20,20,20,20,20,20,20,94,1,1027, +20,20,20,20,20,20,20,95,1,1026, +20,20,20,20,20,20,20,96,1,1025, +20,20,20,20,20,20,20,97,1,1024, +20,20,20,20,20,20,20,98,1,1023, +20,20,20,20,20,20,20,99,1,1020, +20,20,20,20,20,20,20,100,1,1019, +20,20,20,20,20,20,20,101,1,1018, +20,20,20,20,20,20,20,102,1,1017, +20,20,20,20,20,20,20,103,1,1016, +20,20,20,20,20,20,20,104,1,1015, +20,20,20,20,20,20,20,105,1,1014, +20,20,20,20,20,20,20,106,1,1013, +20,20,20,20,20,20,20,107,1,1009, +20,20,20,20,20,20,20,108,1,1008, +20,20,20,20,20,20,20,109,1,1005, +20,20,20,20,20,20,20,110,1,1004, +20,20,20,20,20,20,20,111,1,1003, +20,20,20,20,20,20,20,112,1,1002, +20,20,20,20,20,113,1,1068, 404,404,404,404,404,404,404,404,404,1,114,1,404, 405,405,405,405,405,405,405,405,405,1,115,1,405, 406,406,406,406,406,406,406,1,116,1,406, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,117,1,1134, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,117,1,1132, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,118,1,1133, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,118,1,1131, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,119,1,1132, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,119,1,1130, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,120,1,1131, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,120,1,1129, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,121,1,1130, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,121,1,1128, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,122,1,1129, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,122,1,1127, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,123,1,1128, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,123,1,1126, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,124,1,1127, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,124,1,1125, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,125,1,1126, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,125,1,1124, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,126,1,1125, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,126,1,1123, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,127,1,1124, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,127,1,1122, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,128,1,1123, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,128,1,1121, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,129,1,1122, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,129,1,1120, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,130,1,1121, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,130,1,1119, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,131,1,1120, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,131,1,1118, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,132,1,1119, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,132,1,1117, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,133,1,1118, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,133,1,1116, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,134,1,1117, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,134,1,1115, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,135,1,1116, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,135,1,1114, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,136,1,1115, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,136,1,1113, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,137,1,1114, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,137,1,1112, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,138,1,1113, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,138,1,1111, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,139,1,1112, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,139,1,1110, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,140,1,1111, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,140,1,1109, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,141,1,1104, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,141,1,1102, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,142,1,1103, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,142,1,1101, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,143,1,1102, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,143,1,1100, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,144,1,1101, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,144,1,1099, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,145,1,1100, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,145,1,1098, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,146,1,1099, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,146,1,1097, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,147,1,1093, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,147,1,1091, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,148,1,1092, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,148,1,1090, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,149,1,1091, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,149,1,1089, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,150,1,1085, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,150,1,1083, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,151,1,1084, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,151,1,1082, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,152,1,1083, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,152,1,1081, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,153,1,1082, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,153,1,1080, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,154,1,1081, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,154,1,1079, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,155,1,1080, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,155,1,1078, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,156,1,1079, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,156,1,1077, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,157,1,1078, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,157,1,1076, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,158,1,1077, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,158,1,1075, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,159,1,1076, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,159,1,1074, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,160,1,1075, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,160,1,1073, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,161,1,1074, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,161,1,1072, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,162,1,1073, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,162,1,1071, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,163,1,1072, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,163,1,1070, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,164,1,1071, -20,20,20,20,20,20,20,20,20,165,1,1048, -20,20,20,20,20,20,20,20,20,166,1,1047, -20,20,20,20,20,20,20,20,20,167,1,1046, -20,20,20,20,20,20,20,20,20,168,1,1045, -20,20,20,20,20,169,1,1044, -20,20,20,20,20,170,1,1043, -20,20,20,20,20,20,20,20,171,1,1066, -20,20,20,20,20,20,20,20,172,1,1065, -20,20,20,20,20,20,20,20,173,1,1064, -20,20,20,20,20,20,20,20,20,20,174,1,1062, -20,20,20,20,20,20,20,20,20,20,175,1,1061, -20,20,20,20,20,20,20,20,20,20,176,1,1060, -20,20,20,20,20,20,20,20,20,20,177,1,1059, -20,20,20,20,20,20,20,20,20,20,178,1,1058, -20,20,20,20,20,20,20,20,20,20,179,1,1057, -20,20,20,20,20,20,20,20,20,20,180,1,1056, -20,20,20,20,20,20,20,20,20,20,181,1,1055, -20,20,20,20,20,20,20,20,20,20,182,1,1054, -20,20,20,20,20,20,20,20,20,20,183,1,1053, -20,20,20,20,20,20,20,20,20,20,184,1,1052, -20,20,20,20,20,20,20,20,20,20,185,1,1051, -20,20,20,20,20,20,20,20,20,20,186,1,1050, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,164,1,1069, +20,20,20,20,20,20,20,20,20,165,1,1046, +20,20,20,20,20,20,20,20,20,166,1,1045, +20,20,20,20,20,20,20,20,20,167,1,1044, +20,20,20,20,20,20,20,20,20,168,1,1043, +20,20,20,20,20,169,1,1042, +20,20,20,20,20,170,1,1041, +20,20,20,20,20,20,20,20,171,1,1064, +20,20,20,20,20,20,20,20,172,1,1063, +20,20,20,20,20,20,20,20,173,1,1062, +20,20,20,20,20,20,20,20,20,20,174,1,1060, +20,20,20,20,20,20,20,20,20,20,175,1,1059, +20,20,20,20,20,20,20,20,20,20,176,1,1058, +20,20,20,20,20,20,20,20,20,20,177,1,1057, +20,20,20,20,20,20,20,20,20,20,178,1,1056, +20,20,20,20,20,20,20,20,20,20,179,1,1055, +20,20,20,20,20,20,20,20,20,20,180,1,1054, +20,20,20,20,20,20,20,20,20,20,181,1,1053, +20,20,20,20,20,20,20,20,20,20,182,1,1052, +20,20,20,20,20,20,20,20,20,20,183,1,1051, +20,20,20,20,20,20,20,20,20,20,184,1,1050, +20,20,20,20,20,20,20,20,20,20,185,1,1049, +20,20,20,20,20,20,20,20,20,20,186,1,1048, 407,407,407,407,1,187,1,407, 408,1,188,1,408, 409,1,189,1,409, 410,1,190,1,410, 411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411, 411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411, - 411,411,411,411,411,1,191,1,411, + 411,411,411,411,1,191,1,411, 412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412, 412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412, - 412,412,412,412,412,1,192,1,412, + 412,412,412,412,1,192,1,412, 413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, 413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, - 413,413,413,413,413,1,193,1,413, + 413,413,413,413,1,193,1,413, 414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, 414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, - 414,414,414,414,414,1,194,1,414, + 414,414,414,414,1,194,1,414, 415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, 415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, - 415,415,415,415,415,1,195,1,415, + 415,415,415,415,1,195,1,415, 416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, 416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, - 416,416,416,416,416,1,196,1,416, + 416,416,416,416,1,196,1,416, 417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417, 417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417, - 417,417,417,417,417,1,197,1,417, + 417,417,417,417,1,197,1,417, 418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, 418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, - 418,418,418,418,418,1,198,1,418, + 418,418,418,418,1,198,1,418, 419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419, 419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419, - 419,419,419,419,419,1,199,1,419, + 419,419,419,419,1,199,1,419, 420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420, 420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420, - 420,420,420,420,420,1,200,1,420, + 420,420,420,420,1,200,1,420, 421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421, 421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421, - 421,421,421,421,421,1,201,1,421, + 421,421,421,421,1,201,1,421, 422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, 422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, - 422,422,422,422,422,1,202,1,422, + 422,422,422,422,1,202,1,422, 423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423, 423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423, - 423,423,423,423,423,1,203,1,423, + 423,423,423,423,1,203,1,423, 424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424, 424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424, - 424,424,424,424,424,1,204,1,424, + 424,424,424,424,1,204,1,424, 425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425, 425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425, - 425,425,425,425,425,1,205,1,425, + 425,425,425,425,1,205,1,425, 426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, 426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, - 426,426,426,426,426,1,206,1,426, + 426,426,426,426,1,206,1,426, 427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427, 427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427, - 427,427,427,427,427,1,207,1,427, + 427,427,427,427,1,207,1,427, 428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, 428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, - 428,428,428,428,428,1,208,1,428, + 428,428,428,428,1,208,1,428, 429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, 429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, - 429,429,429,429,429,1,209,1,429, + 429,429,429,429,1,209,1,429, 430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430, 430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430, - 430,430,430,430,430,1,210,1,430, + 430,430,430,430,1,210,1,430, 431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431, 431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431, - 431,431,431,431,431,1,211,1,431, + 431,431,431,431,1,211,1,431, 432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432, 432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432, - 432,432,432,432,432,1,212,1,432, + 432,432,432,432,1,212,1,432, 433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433, 433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433, - 433,433,433,433,433,1,213,1,433, + 433,433,433,433,1,213,1,433, 434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434, 434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434, - 434,434,434,434,434,1,214,1,434, + 434,434,434,434,1,214,1,434, 435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435, 435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435, - 435,435,435,435,435,1,215,1,435, + 435,435,435,435,1,215,1,435, 436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, 436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, - 436,436,436,436,436,1,216,1,436, + 436,436,436,436,1,216,1,436, 437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, 437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, - 437,437,437,437,437,1,217,1,437, + 437,437,437,437,1,217,1,437, 438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, 438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, - 438,438,438,438,438,1,218,1,438, + 438,438,438,438,1,218,1,438, 439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, 439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, - 439,439,439,439,439,1,219,1,439, + 439,439,439,439,1,219,1,439, 440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, 440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, - 440,440,440,440,440,1,220,1,440, + 440,440,440,440,1,220,1,440, 441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441, 441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441, - 441,441,441,441,441,1,221,1,441, + 441,441,441,441,1,221,1,441, 442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442, 442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442, - 442,442,442,442,442,1,222,1,442, + 442,442,442,442,1,222,1,442, 443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443, 443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443, - 443,443,443,443,443,1,223,1,443, + 443,443,443,443,1,223,1,443, 444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444, 444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444, - 444,444,444,444,444,1,224,1,444, + 444,444,444,444,1,224,1,444, 445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445, 445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445, - 445,445,445,445,445,1,225,1,445, + 445,445,445,445,1,225,1,445, 446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446, 446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446, - 446,446,446,446,446,1,226,1,446, + 446,446,446,446,1,226,1,446, 447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447, 447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447, - 447,447,447,447,447,1,227,1,447, + 447,447,447,447,1,227,1,447, 448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448, 448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448, - 448,448,448,448,448,1,228,1,448, + 448,448,448,448,1,228,1,448, 449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, 449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, - 449,449,449,449,449,1,229,1,449, + 449,449,449,449,1,229,1,449, 450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, 450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, - 450,450,450,450,450,1,230,1,450, + 450,450,450,450,1,230,1,450, 451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, 451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, - 451,451,451,451,451,1,231,1,451, + 451,451,451,451,1,231,1,451, 452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452, 452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452, - 452,452,452,452,452,1,232,1,452, + 452,452,452,452,1,232,1,452, 453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453, 453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453, - 453,453,453,453,453,1,233,1,453, + 453,453,453,453,1,233,1,453, 454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454, 454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454, - 454,454,454,454,454,1,234,1,454, + 454,454,454,454,1,234,1,454, 455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455, 455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455, - 455,455,455,455,455,1,235,1,455, + 455,455,455,455,1,235,1,455, 456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456, 456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456, - 456,456,456,456,456,1,236,1,456, + 456,456,456,456,1,236,1,456, 457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457, 457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457, - 457,457,457,457,457,1,237,1,457, + 457,457,457,457,1,237,1,457, 458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458, 458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458, - 458,458,458,458,458,1,238,1,458, + 458,458,458,458,1,238,1,458, 459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459, 459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459, - 459,459,459,459,459,1,239,1,459, + 459,459,459,459,1,239,1,459, 460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460, 460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460, - 460,460,460,460,460,1,240,1,460, + 460,460,460,460,1,240,1,460, 461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, 461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, - 461,461,461,461,461,1,241,1,461, + 461,461,461,461,1,241,1,461, 462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462, 462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462, - 462,462,462,462,462,1,242,1,462, + 462,462,462,462,1,242,1,462, 463,463,463,463,463,463,463,463,1,243,1,463, 464,464,464,464,464,464,464,464,1,244,1,464, 465,465,465,465,465,465,465,465,1,245,1,465, @@ -5377,21 +5362,21 @@ static const unsigned short ag_pstt[] = { 482,482,482,482,482,482,482,482,482,1,262,1,482, 483,483,483,483,483,483,483,483,483,1,263,1,483, 484,484,484,484,484,484,484,484,484,1,264,1,484, -20,138,138,138,138,138,138,138,138,138,138,138,20,138,20,20,139,139,139,139, - 139,20,138,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,138,20,20,20,20,20,1,265,1,897,139, -20,20,20,20,20,20,1,266,1,317, +20,137,137,137,137,137,137,137,137,137,137,137,20,137,20,20,138,138,138,138, + 138,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,137,20,20,20,20,20,1,265,1,894,138, +20,20,20,20,20,20,1,266,1,316, 66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66, 66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66, - 66,66,66,66,66,66,66,66,66,310,66,66,66,66,66,66,66,66,66,66,267,485, + 66,66,66,66,66,66,66,66,66,309,66,66,66,66,66,66,66,66,66,66,267,485, 122,122,122,122,122,486,268,486, 487,121,488, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,270,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,338,110,226,326,312,265,339,327,331,330,329,328,225,331,321, - 320,319,318,317,316,315,314,313,311,294,293,265,309,308, -298,489,491,493,494,495,497,498,499,503,506,508,510,512,514,516,518,519,521, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,270,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,338,110,225,326,311,265,226,339,327,331,330,329,328,224,331,320, + 319,318,317,316,315,314,313,312,310,293,292,265,308,307, +297,489,491,493,494,495,497,498,499,503,506,508,510,512,514,516,518,519,521, 522,523,525,526,528,529,530,531,534,535,14,15,16,343,345,347,349,351, 271,75,76,533,77,79,505,502,501,70,71,532,532,532,532,84,527,527,527, 524,524,524,524,520,520,520,517,515,513,511,509,507,504,500,113,114,496, @@ -5401,585 +5386,583 @@ static const unsigned short ag_pstt[] = { 537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, 537,537,537,1,273,1,537, 538,538,538,538,538,1,274,1,538, -146,275,539,278,279, -146,276,540,278,279, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,146,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289, - 298,310,284,271,136,135,277,240,295,296,241,291,542,278,242,292,267,335, - 334,332,337,333,336,331,541,226,326,312,265,327,331,330,329,328,225,331, - 321,320,319,318,317,316,315,314,313,311,294,293,279,265,309,308, -149,543,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, - 149,149,149,149,145,149,149,149,149,149,149,149,149,149,149,149,149,149, - 149,149,149,149,149,278,147, -20,20,20,20,20,20,20,20,20,279,1,890, +145,275,539,278,279, +145,276,540,278,279, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 145,296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288, + 297,309,284,270,135,277,240,294,295,241,290,542,278,242,291,267,335,334, + 332,337,333,336,331,541,225,326,311,265,226,327,331,330,329,328,224,331, + 320,319,318,317,316,315,314,313,312,310,293,292,279,265,308,307, +148,543,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, + 148,148,148,144,148,148,148,148,148,148,148,148,148,148,148,148,148,148, + 148,148,148,148,148,278,146, +20,20,20,20,20,20,20,20,20,279,1,887, 544,544,544,544,544,1,280,1,544, 43,44,45,40,57,281,57,57,48,57,47,46,46, 43,44,45,40,56,282,56,56,48,56,47,46,46, 545,545,545,545,545,1,283,1,545, -282,282,282,282,282,284, -267,267,267,267,285, -265,265,286, -137,137,137,137,137,137,137,261,261,261,261,137,261,261,261,261,261,137,137, - 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, - 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, - 137,137,137,137,287, +281,281,281,281,281,284, +266,266,266,266,285, +264,264,286, 256,546,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256, 256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256, - 256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256, - 288, -254,254,254,254,254,289, -272,547,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, - 272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, - 272,272,272,278,272,290,548, -283,283,283,283,283,280, -247,264,264,264,264,264,264,264,264,264,292, -268,268,268,268,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, + 256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,287, +254,254,254,254,254,288, +271,547,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, + 271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, + 271,271,271,277,271,289,548, +282,282,282,282,282,279, +247,263,263,263,263,263,263,263,263,263,291, +267,267,267,267,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, 246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, - 246,246,246,246,246,246,293, -266,266,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, + 246,246,246,246,246,246,292, +265,265,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, - 245,245,245,245,294, -262,262,262,262,262,262,262,262,262,244,244,244,244,244,244,244,244,244,244, + 245,245,245,245,293, +261,261,261,261,261,261,261,261,261,244,244,244,244,244,244,244,244,244,244, 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, - 244,244,244,244,244,244,244,244,244,244,244,295, -258,248,263,549,550,263,257,257,257,257,257,259,243,243,243,243,243,243,243, + 244,244,244,244,244,244,244,244,244,244,244,294, +258,248,262,549,550,262,257,257,257,257,257,243,243,243,243,243,243,243,243, 243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243, - 243,243,243,243,243,243,281,243,243,243,243,252,252,243,243,296,252, -20,20,297,1,992, -20,20,20,20,20,20,20,298,1,946, -20,20,299,1,990, -20,20,300,1,989, -20,20,301,1,988, -20,20,302,1,987, -20,20,303,1,986, -20,20,304,1,985, -20,20,305,1,984, -20,20,306,1,983, -20,20,307,1,982, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,308,1,993, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,1,309,1,947, + 243,243,243,243,243,280,243,243,243,243,252,252,243,243,295,252, +20,20,296,1,990, +20,20,20,20,20,20,20,297,1,943, +20,20,298,1,988, +20,20,299,1,987, +20,20,300,1,986, +20,20,301,1,985, +20,20,302,1,984, +20,20,303,1,983, +20,20,304,1,982, +20,20,305,1,981, +20,20,306,1,980, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,307,1,991, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,1,308,1,944, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,310,1,915, -551,1,311,1,551, -552,1,312,1,552, -553,1,313,1,553, -554,1,314,1,554, -555,1,315,1,555, -556,1,316,1,556, -557,1,317,1,557, -558,1,318,1,558, -559,1,319,1,559, -560,1,320,1,560, -561,1,321,1,561, + 20,20,20,20,20,20,20,20,20,20,20,20,20,309,1,912, +551,1,310,1,551, +552,1,311,1,552, +553,1,312,1,553, +554,1,313,1,554, +555,1,314,1,555, +556,1,315,1,556, +557,1,316,1,557, +558,1,317,1,558, +559,1,318,1,559, +560,1,319,1,560, +561,1,320,1,561, +260,260,260,260,260,260,260,260,260,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 321,1,979, 20,20,20,20,20,20,20,20,20,20,20,20,20,255,255,255,255,255,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,322,1,973, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,322,1,970, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,323,1,981, + 20,20,20,20,20,20,20,20,20,20,20,20,323,1,978, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,324,1,980, + 20,20,20,20,20,20,20,20,20,20,20,20,20,1,324,1,977, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,325,1,979, + 20,20,20,20,20,20,20,20,20,20,20,20,325,1,976, 562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562, 562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562, - 562,562,562,562,562,1,326,1,562, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, - 136,135,327,240,295,296,241,291,242,292,267,226,326,312,265,224,225,224, - 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, - 136,135,328,240,295,296,241,291,242,292,267,226,326,312,265,223,225,223, - 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, - 136,135,329,240,295,296,241,291,242,292,267,226,326,312,265,222,225,222, - 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, - 136,135,330,240,295,296,241,291,242,292,267,226,326,312,265,221,225,221, - 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,1,331,1,214, + 562,562,562,562,1,326,1,562, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,286,563,288,297,309,284,270, + 135,327,240,294,295,241,290,242,291,267,225,326,311,265,226,223,224,223, + 320,319,318,317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,286,563,288,297,309,284,270, + 135,328,240,294,295,241,290,242,291,267,225,326,311,265,226,222,224,222, + 320,319,318,317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,286,563,288,297,309,284,270, + 135,329,240,294,295,241,290,242,291,267,225,326,311,265,226,221,224,221, + 320,319,318,317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,286,563,288,297,309,284,270, + 135,330,240,294,295,241,290,242,291,267,225,326,311,265,226,220,224,220, + 320,319,318,317,316,315,314,313,312,310,293,292,265,308,307, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,1,331,1,213, 20,564,566,391,383,387,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,1,332,1,211,570,569,568,567,565, + 20,20,20,20,20,20,20,20,20,20,20,20,20,1,332,1,210,570,569,568,567,565, 20,384,386,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,1,333,1,206,572,571, + 20,20,20,20,20,20,20,20,20,1,333,1,205,572,571, 20,573,575,577,579,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,1,334,1,203,580,578,576,574, + 20,20,20,20,20,20,20,1,334,1,202,580,578,576,574, 20,581,390,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,1,335,1,200,583,582, + 20,20,20,1,335,1,199,583,582, 20,584,362,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,1,336,1,197,586,585, -587,360,196,589,588, -590,591,592,593,594,595,596,597,598,599,600,601,399,176,176,176,176,176,176, - 338,180,180,180,180,183,183,183,186,186,186,189,189,189,192,192,192,195, - 195,195, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,339,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,175,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, + 20,1,336,1,196,586,585, +587,360,195,589,588, +590,591,592,593,594,595,596,597,598,599,600,601,399,175,175,175,175,175,175, + 338,179,179,179,179,182,182,182,185,185,185,188,188,188,191,191,191,194, + 194,194, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,339,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,174,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, 602,602,602,602,602,1,340,1,602, 603,603,603,603,603,1,341,1,603, 604,604,604,604,604,604,342,604, -20,20,20,20,20,20,343,1,900, +20,20,20,20,20,20,343,1,897, 605,605,605,605,605,1,344,1,605, -20,20,20,20,20,20,345,1,899, +20,20,20,20,20,20,345,1,896, 606,606,606,606,606,1,346,1,606, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,347,1,898, -607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,1,348,1,607, -20,20,20,20,20,20,349,1,896, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,347,1,895, +607,607,607,607,607,607,607,607,607,607,607,607,607,1,348,1,607, +20,20,20,20,20,20,349,1,893, 608,608,608,608,608,1,350,1,608, -20,20,20,20,20,20,351,1,894, +20,20,20,20,20,20,351,1,891, 609,609,609,609,609,1,352,1,609, -165,165,610,165,165,165,165,165,165,165,165,165,165,165,165,163,165,165,165, - 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, - 165,165,165,165,353, -20,20,20,20,20,20,354,1,891, +164,164,610,164,164,164,164,164,164,164,164,164,164,164,164,162,164,164,164, + 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164, + 164,164,164,164,353, +20,20,20,20,20,20,354,1,888, 611,611,611,611,611,1,355,1,611, 612,612,612,612,612,1,356,1,612, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,357,1,889, -140,140,140,140,140,140,140,140,140,140,140,140,164,140,140,140,140,140,146, - 140,140,358,616,278,615,353,614,279,354,613, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,357,1,886, +139,139,139,139,139,139,139,139,139,139,139,139,163,139,139,139,139,139,145, + 139,139,358,616,278,615,353,614,279,354,613, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 359,1,1160, + 359,1,1157, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,360,1,962, + 20,20,20,20,20,20,20,20,20,20,20,20,20,360,1,959, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 361,1,1159, + 361,1,1156, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,362,1,964, + 20,20,20,20,20,20,20,20,20,20,20,20,20,362,1,961, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,363,1,1158, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,363,1,1155, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 364,1,1157, + 364,1,1154, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 365,1,1156, + 365,1,1153, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 366,1,1155, + 366,1,1152, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 367,1,1154, + 367,1,1151, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 368,1,1153, + 368,1,1150, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 369,1,1152, + 369,1,1149, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 370,1,1151, + 370,1,1148, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 371,1,1150, + 371,1,1147, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 372,1,1149, + 372,1,1146, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 373,1,1148, + 373,1,1145, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 374,1,1147, + 374,1,1144, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 375,1,1146, + 375,1,1143, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 376,1,1145, + 376,1,1142, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 377,1,1144, + 377,1,1141, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 378,1,1143, + 378,1,1140, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 379,1,1142, + 379,1,1139, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 380,1,1141, + 380,1,1138, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 381,1,1140, + 381,1,1137, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 382,1,1139, + 382,1,1136, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,383,1,975, + 20,20,20,20,20,20,20,20,20,20,20,20,383,1,972, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,384,1,973, + 20,20,20,20,20,20,20,20,20,20,20,20,20,384,1,970, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,385,1,910, + 20,20,20,20,20,20,20,20,20,20,20,20,20,385,1,907, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,386,1,972, + 20,20,20,20,20,20,20,20,20,20,20,20,20,386,1,969, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,387,1,974, + 20,20,20,20,20,20,20,20,20,20,20,20,387,1,971, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 388,1,914, + 388,1,911, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 389,1,1138, + 389,1,1135, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,390,1,966, + 20,20,20,20,20,20,20,20,20,20,20,20,20,390,1,963, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,391,1,976, + 20,20,20,20,20,20,20,20,20,20,20,20,391,1,973, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 392,1,1137, + 392,1,979, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 393,1,1136, + 393,1,1134, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 394,1,1135, + 394,1,1133, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,395,1,881, + 20,20,20,20,20,395,1,878, 359,361,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379, - 380,381,382,389,392,393,394,323,325,391,383,387,384,386,390,362,360,310, + 380,381,382,389,393,394,392,323,325,391,383,387,384,386,390,362,360,309, 388,385,41,44,7,9,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7, 40,397,11, 40,398,10, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,399,1,887, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,400,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,617,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -298,489,491,493,494,495,497,498,499,503,506,508,510,512,514,516,518,519,521, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,399,1,884, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,400,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,617,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +297,489,491,493,494,495,497,498,499,503,506,508,510,512,514,516,518,519,521, 522,523,525,526,528,529,530,531,534,535,14,15,16,343,345,347,349,351, 618,620,401,621,619,75,76,533,77,79,505,502,501,70,71,532,532,532,532, 84,527,527,527,524,524,524,524,520,520,520,517,515,513,511,509,507,504, 500,113,114,496,117,118,492,490,123, 622,622,622,622,622,1,402,1,622, -623,298,43,44,45,40,72,403,624,72,72,48,72,47,46,46,173,174, -311,625,626,627,313,312,313,312,311,404,311,312,313,316,403,314,315, -293,292,292,289,288,287,286,285,284,405,401,292,628, -296,303,302,299,302,299,296,406,399,296,299,302,629, -405,405,405,405,407,405, +623,297,43,44,45,40,72,403,624,72,72,48,72,47,46,46,172,173, +310,625,626,627,312,311,312,311,310,404,310,311,312,315,402,313,314, +292,291,291,288,287,286,285,284,283,405,400,291,628, +295,302,301,298,301,298,295,406,398,295,298,301,629, +404,404,404,404,407,404, 385,408,630, 385,409,631, 385,410,632, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,411,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,473,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,412,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,472,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,413,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,471,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,414,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,470,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,415,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,469,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,416,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,468,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,417,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,467,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,418,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,466,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,419,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,465,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,420,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,464,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,421,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,463,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,422,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,462,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,423,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,461,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,424,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,460,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,425,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,459,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,426,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,458,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,427,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,457,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,428,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,456,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,429,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,455,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,430,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,454,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,431,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,453,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,432,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,452,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,433,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,451,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,434,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,450,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,435,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,449,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,436,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,445,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,437,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,441,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,438,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,440,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,439,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,439,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,440,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,438,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,441,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,437,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,442,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,436,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,443,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,435,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,444,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,429,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,445,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,428,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,446,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,427,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,447,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,426,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,448,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,420,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,449,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,419,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,450,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,418,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,451,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,417,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,452,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,416,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,453,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,415,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,454,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,414,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,455,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,413,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,456,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,412,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,457,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,411,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,458,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,410,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,459,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,409,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,460,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,408,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,461,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,407,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,462,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,406,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -304,633,634,306,305,306,305,304,463,308,304,305,306,382,307, -304,633,634,306,305,306,305,304,464,308,304,305,306,381,307, -304,633,634,306,305,306,305,304,465,308,304,305,306,380,307, -304,633,634,306,305,306,305,304,466,308,304,305,306,379,307, -309,310,310,309,467,309,310,378, -309,310,310,309,468,309,310,377, -296,303,302,299,302,299,296,469,398,296,299,302,629, -296,303,302,299,302,299,296,470,397,296,299,302,629, -296,303,302,299,302,299,296,471,396,296,299,302,629, -311,625,626,627,313,312,313,312,311,472,311,312,313,316,395,314,315, -311,625,626,627,313,312,313,312,311,473,311,312,313,316,394,314,315, -293,292,292,289,288,287,286,285,284,474,393,292,628, -293,292,292,289,288,287,286,285,284,475,392,292,628, -293,292,292,289,288,287,286,285,284,476,391,292,628, -293,292,292,289,288,287,286,285,284,477,390,292,628, -293,292,292,289,288,287,286,285,284,478,635,292,628, -293,292,292,289,288,287,286,285,284,479,388,292,628, -293,292,292,289,288,287,286,285,284,480,387,292,628, -293,292,292,289,288,287,286,285,284,481,386,292,628, -293,292,292,289,288,287,286,285,284,482,385,292,628, -293,292,292,289,288,287,286,285,284,483,384,292,628, -293,292,292,289,288,287,286,285,284,484,383,292,628, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,636, - 287,146,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289, - 298,310,284,271,136,135,485,240,295,296,241,291,125,278,242,292,637,126, - 267,335,334,332,337,333,336,331,127,226,326,639,312,265,327,331,330,329, - 328,225,331,321,320,319,318,317,316,315,314,313,311,294,293,279,265,638, - 309,308, -285,256,256,256,256,288,290,640,286,563,289,271,19,486,124,295,641,242,292, - 294,293,309, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,411,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,472,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,412,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,471,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,413,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,470,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,414,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,469,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,415,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,468,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,416,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,467,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,417,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,466,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,418,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,465,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,419,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,464,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,420,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,463,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,421,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,462,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,422,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,461,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,423,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,460,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,424,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,459,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,425,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,458,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,426,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,457,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,427,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,456,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,428,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,455,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,429,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,454,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,430,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,453,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,431,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,452,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,432,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,451,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,433,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,450,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,434,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,449,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,435,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,448,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,436,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,444,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,437,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,440,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,438,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,439,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,439,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,438,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,440,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,437,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,441,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,436,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,442,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,435,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,443,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,434,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,444,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,428,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,445,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,427,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,446,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,426,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,447,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,425,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,448,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,419,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,449,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,418,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,450,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,417,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,451,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,416,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,452,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,415,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,453,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,414,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,454,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,413,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,455,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,412,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,456,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,411,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,457,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,410,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,458,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,409,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,459,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,408,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,460,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,407,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,461,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,406,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,462,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,405,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +303,633,634,305,304,305,304,303,463,307,303,304,305,381,306, +303,633,634,305,304,305,304,303,464,307,303,304,305,380,306, +303,633,634,305,304,305,304,303,465,307,303,304,305,379,306, +303,633,634,305,304,305,304,303,466,307,303,304,305,378,306, +308,309,309,308,467,308,309,377, +308,309,309,308,468,308,309,376, +295,302,301,298,301,298,295,469,397,295,298,301,629, +295,302,301,298,301,298,295,470,396,295,298,301,629, +295,302,301,298,301,298,295,471,395,295,298,301,629, +310,625,626,627,312,311,312,311,310,472,310,311,312,315,394,313,314, +310,625,626,627,312,311,312,311,310,473,310,311,312,315,393,313,314, +292,291,291,288,287,286,285,284,283,474,392,291,628, +292,291,291,288,287,286,285,284,283,475,391,291,628, +292,291,291,288,287,286,285,284,283,476,390,291,628, +292,291,291,288,287,286,285,284,283,477,389,291,628, +292,291,291,288,287,286,285,284,283,478,635,291,628, +292,291,291,288,287,286,285,284,283,479,387,291,628, +292,291,291,288,287,286,285,284,283,480,386,291,628, +292,291,291,288,287,286,285,284,283,481,385,291,628, +292,291,291,288,287,286,285,284,283,482,384,291,628, +292,291,291,288,287,286,285,284,283,483,383,291,628, +292,291,291,288,287,286,285,284,283,484,382,291,628, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,636, + 145,296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288, + 297,309,284,270,135,485,240,294,295,241,290,125,278,242,291,637,126,267, + 335,334,332,337,333,336,331,127,225,326,639,311,265,226,327,331,330,329, + 328,224,331,320,319,318,317,316,315,314,313,312,310,293,292,279,265,638, + 308,307, +285,256,256,256,256,287,289,640,286,563,288,270,19,486,124,294,641,242,291, + 293,292,308, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,487,1,999, + 20,20,20,20,20,20,20,20,20,20,20,20,20,487,1,997, 642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, 642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, 642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, @@ -5988,102 +5971,99 @@ static const unsigned short ag_pstt[] = { 642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, 642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, 642,642,642,642,642,642,1,488,1,642, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,489,1,945, -137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,490,120,265,265, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,491,1,944, -140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +20,20,20,20,20,20,20,20,20,20,20,20,20,1,489,1,942, +136,136,136,136,136,136,136,136,136,136,136,136,135,490,120,265,265, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,491,1,941, +139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, 492,119,613, -20,20,20,20,20,20,493,1,943, -20,20,20,20,20,20,494,1,942, -20,20,1,495,1,941, -643,146,496,116,278,637,115,279,638, -20,20,20,20,20,20,497,1,939, -20,20,20,20,20,20,498,1,938, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,499,1,937, -137,137,137,137,137,137,137,137,137,137,137,137,137,108,108,108,108,136,135, - 108,108,500,109,265,265, -146,501,644,278,279, -146,502,106,278,279, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,503,1,936, +20,20,20,20,20,20,493,1,940, +20,20,20,20,20,20,494,1,939, +20,20,1,495,1,938, +643,145,496,116,278,637,115,279,638, +20,20,20,20,20,20,497,1,936, +20,20,20,20,20,20,498,1,935, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,499,1,934, +136,136,136,136,136,136,136,136,136,136,136,136,108,108,108,108,135,108,108, + 500,109,265,265, +145,501,644,278,279, +145,502,106,278,279, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,503,1,933, 645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645, 645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645, - 645,645,645,645,645,645,1,504,1,645, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,146,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289, - 298,310,284,271,136,135,1,505,240,295,296,241,291,102,278,242,292,267, - 335,334,332,337,333,336,331,1,646,101,226,326,312,265,327,331,330,329, - 328,225,331,321,320,319,318,317,316,315,314,313,311,294,293,279,265,309, - 308, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,506,1,935, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,507,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,100,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,508,1,934, -137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,509,99,265,265, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,510,1,933, -137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,511,98,265,265, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,512,1,932, -137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,513,131,647,265, - 265, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,514,1,931, -137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,515,131,648,265, - 265, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,516,1,930, -137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,517,131,649,265, - 265, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,518,1,929, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,519,1,928, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,636, - 287,146,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289, - 298,310,284,271,136,135,520,240,295,296,241,291,125,278,242,292,637,126, - 267,335,334,332,337,333,336,331,127,226,326,650,312,265,327,331,330,329, - 328,225,331,321,320,319,318,317,316,315,314,313,311,294,293,279,265,638, - 309,308, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,521,1,927, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,522,1,926, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,523,1,925, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,636, - 287,146,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289, - 298,310,284,271,136,135,524,240,295,296,241,291,125,278,242,292,637,126, - 267,335,334,332,337,333,336,331,127,226,326,651,312,265,327,331,330,329, - 328,225,331,321,320,319,318,317,316,315,314,313,311,294,293,279,265,638, - 309,308, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,525,1,924, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,526,1,923, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,527,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,87,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -20,20,20,20,20,20,528,1,922, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,529,1,921, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,530,1,920, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,531,1,919, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,532,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,83,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,533,78,265,265, -20,20,20,20,20,20,20,20,534,1,918, -20,20,20,20,20,20,20,20,535,1,917, + 645,645,645,645,645,1,504,1,645, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 145,296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288, + 297,309,284,270,135,1,505,240,294,295,241,290,102,278,242,291,267,335, + 334,332,337,333,336,331,1,646,101,225,326,311,265,226,327,331,330,329, + 328,224,331,320,319,318,317,316,315,314,313,312,310,293,292,279,265,308, + 307, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,506,1,932, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,507,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,100,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +20,20,20,20,20,20,20,20,20,20,20,20,20,1,508,1,931, +136,136,136,136,136,136,136,136,136,136,136,136,135,509,99,265,265, +20,20,20,20,20,20,20,20,20,20,20,20,20,1,510,1,930, +136,136,136,136,136,136,136,136,136,136,136,136,135,511,98,265,265, +20,20,20,20,20,20,20,20,20,20,20,20,20,1,512,1,929, +136,136,136,136,136,136,136,136,136,136,136,136,135,513,131,647,265,265, +20,20,20,20,20,20,20,20,20,20,20,20,20,1,514,1,928, +136,136,136,136,136,136,136,136,136,136,136,136,135,515,131,648,265,265, +20,20,20,20,20,20,20,20,20,20,20,20,20,1,516,1,927, +136,136,136,136,136,136,136,136,136,136,136,136,135,517,131,649,265,265, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,518,1,926, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,519,1,925, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,636, + 145,296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288, + 297,309,284,270,135,520,240,294,295,241,290,125,278,242,291,637,126,267, + 335,334,332,337,333,336,331,127,225,326,650,311,265,226,327,331,330,329, + 328,224,331,320,319,318,317,316,315,314,313,312,310,293,292,279,265,638, + 308,307, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,521,1,924, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,522,1,923, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,523,1,922, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,636, + 145,296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288, + 297,309,284,270,135,524,240,294,295,241,290,125,278,242,291,637,126,267, + 335,334,332,337,333,336,331,127,225,326,651,311,265,226,327,331,330,329, + 328,224,331,320,319,318,317,316,315,314,313,312,310,293,292,279,265,638, + 308,307, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,525,1,921, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,526,1,920, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,527,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,87,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +20,20,20,20,20,20,528,1,919, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,529,1,918, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,530,1,917, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,531,1,916, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,532,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,83,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,136,135,533,78,265,265, +20,20,20,20,20,20,20,20,534,1,915, +20,20,20,20,20,20,20,20,535,1,914, 43,44,45,40,22,536,22,22,48,22,47,46,46, 359,361,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380, - 381,382,389,392,393,394,323,325,391,383,387,384,386,390,362,360,310,388, + 381,382,389,393,394,392,323,325,391,383,387,384,386,390,362,360,309,388, 385,41,44,537,67,67,67,652,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, 43,44,45,40,63,538,63,63,48,63,47,46,46, @@ -6091,194 +6071,194 @@ static const unsigned short ag_pstt[] = { 654,654,654,654,654,1,540,1,654, 655,655,655,655,655,1,541,1,655, 656,656,656,656,656,1,542,1,656, -150,657,152,153,151,157,156,658,658,659,657,155,148,543,657, +149,657,151,152,150,156,155,658,658,659,154,657,147,543,657, 43,44,45,40,58,544,58,58,48,58,47,46,46, 43,44,45,40,55,545,55,55,48,55,47,46,46, -260,260,260,260,260,260,260,260,260,546, -273,275,276,274,277,279,547, -272,547,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, - 272,272,269,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, - 272,272,272,272,278,272,548,660, -263,263,263,263,263,263,263,263,263,263,253,253,253,253,253,253,253,253,253, +259,259,259,259,259,259,259,259,259,546, +272,274,275,273,276,278,547, +271,547,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, + 271,271,268,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, + 271,271,271,271,277,271,548,660, +262,262,262,262,262,262,262,262,262,262,253,253,253,253,253,253,253,253,253, 253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, 253,253,253,253,253,253,253,253,253,253,253,253,549, -263,263,263,263,263,263,263,263,263,263,249,249,249,249,249,249,249,249,249, +262,262,262,262,262,262,262,262,262,262,249,249,249,249,249,249,249,249,249, 249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, 249,249,249,249,249,249,249,249,249,249,249,249,550, -310,551,661, -310,552,662, -310,553,663, -310,554,664, -310,555,665, -310,556,666, -310,557,667, -310,558,668, -310,559,669, -310,560,670, -310,561,671, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,562,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,672,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, +309,551,661, +309,552,662, +309,553,663, +309,554,664, +309,555,665, +309,556,666, +309,557,667, +309,558,668, +309,559,669, +309,560,670, +309,561,671, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,562,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,672,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, 255,255,255,255,255,563, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,564,1,978, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,564,1,975, 673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, 673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, - 673,673,1,565,1,673, + 673,1,565,1,673, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,566,1,977, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,566,1,974, 674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674, 674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674, - 674,674,1,567,1,674, + 674,1,567,1,674, 675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675, 675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675, - 675,675,1,568,1,675, + 675,1,568,1,675, 676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676, 676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676, - 676,676,1,569,1,676, + 676,1,569,1,676, 677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677, 677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677, - 677,677,1,570,1,677, + 677,1,570,1,677, 678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678, 678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678, - 678,678,678,678,678,1,571,1,678, + 678,678,678,678,1,571,1,678, 679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, 679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, - 679,679,679,679,679,1,572,1,679, + 679,679,679,679,1,572,1,679, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,573,1,971, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,573,1,968, 680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680, 680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680, - 680,680,680,680,680,1,574,1,680, + 680,680,680,680,1,574,1,680, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,575,1,970, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,575,1,967, 681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681, 681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681, - 681,681,681,681,681,1,576,1,681, + 681,681,681,681,1,576,1,681, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,577,1,969, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,577,1,966, 682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682, 682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682, - 682,682,682,682,682,1,578,1,682, + 682,682,682,682,1,578,1,682, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,579,1,968, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,579,1,965, 683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683, 683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683, - 683,683,683,683,683,1,580,1,683, + 683,683,683,683,1,580,1,683, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,581,1,967, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,581,1,964, 684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684, 684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684, - 684,684,684,684,684,1,582,1,684, + 684,684,684,684,1,582,1,684, 685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685, 685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685, - 685,685,685,685,685,1,583,1,685, + 685,685,685,685,1,583,1,685, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,584,1,965, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,584,1,962, 686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686, 686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686, - 686,686,686,686,686,1,585,1,686, + 686,686,686,686,1,585,1,686, 687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687, 687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687, - 687,687,687,687,687,1,586,1,687, + 687,687,687,687,1,586,1,687, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,587,1,963, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,587,1,960, 688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688, 688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688, - 688,688,688,688,688,1,588,1,688, + 688,688,688,688,1,588,1,688, 689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689, 689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689, - 689,689,689,689,689,1,589,1,689, + 689,689,689,689,1,589,1,689, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,590,1,961, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,590,1,958, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,591,1,960, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,591,1,957, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,592,1,959, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,592,1,956, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,593,1,958, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,593,1,955, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,594,1,957, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,594,1,954, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,595,1,956, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,595,1,953, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,596,1,955, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,596,1,952, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,597,1,954, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,597,1,951, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,598,1,953, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,598,1,950, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,599,1,952, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,599,1,949, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,600,1,951, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,600,1,948, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,601,1,950, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,601,1,947, 43,44,45,40,54,602,54,54,48,54,47,46,46, 43,44,45,40,53,603,53,53,48,53,47,46,46, 43,44,45,40,52,604,52,52,48,52,47,46,46, 43,44,45,40,49,605,49,49,48,49,47,46,46, 43,44,45,40,48,606,48,48,48,48,47,46,46, -137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,607,690,265,265, +136,136,136,136,136,136,136,136,136,136,136,136,135,607,690,265,265, 43,44,45,40,46,608,46,46,48,46,47,46,46, 43,44,45,40,45,609,45,45,48,45,47,46,46, -166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, - 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, - 166,166,166,166,167,166,610, +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, + 165,165,165,165,166,165,610, 43,44,45,40,44,611,44,44,48,44,47,46,46, 43,44,45,40,43,612,43,43,48,43,47,46,46, -141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, - 20,20,20,20,613,1,892, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, + 20,20,20,20,613,1,889, 691,691,691,691,691,1,614,1,691, 692,692,692,692,692,1,615,1,692, 693,693,693,693,693,1,616,1,693, 694,694,694,694,694,1,617,1,694, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,618,1,886, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,619,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,695,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,620,1,885, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,621,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,696,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,618,1,883, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,619,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,695,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,620,1,882, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,621,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,696,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, 43,44,45,40,23,622,23,23,48,23,47,46,46, -20,20,20,20,20,20,623,1,949, +20,20,20,20,20,20,623,1,946, 697,697,697,697,697,1,624,1,697, -20,20,20,20,20,20,20,20,625,1,998, -20,20,20,20,20,20,20,20,626,1,997, -20,20,20,20,20,20,20,20,627,1,996, -20,20,20,20,20,20,20,20,20,628,1,1049, -20,20,20,20,20,20,20,20,629,1,1063, +20,20,20,20,20,20,20,20,625,1,996, +20,20,20,20,20,20,20,20,626,1,995, +20,20,20,20,20,20,20,20,627,1,994, +20,20,20,20,20,20,20,20,20,628,1,1047, +20,20,20,20,20,20,20,20,629,1,1061, 698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698, 698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698, - 698,698,698,698,698,1,630,1,698, + 698,698,698,698,1,630,1,698, 699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699, 699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699, - 699,699,699,699,699,1,631,1,699, + 699,699,699,699,1,631,1,699, 700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700, 700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700, - 700,700,700,700,700,1,632,1,700, -20,20,20,20,20,20,20,633,1,995, -20,20,20,20,20,20,20,634,1,994, + 700,700,700,700,1,632,1,700, +20,20,20,20,20,20,20,633,1,993, +20,20,20,20,20,20,20,634,1,992, 701,1,635,1,701, -272,547,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, - 272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, - 272,272,272,278,272,636,702, -272,547,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, - 272,272,142,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, - 272,272,272,272,278,272,637,144, -20,20,20,20,20,20,20,20,638,1,940, +271,547,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, + 271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, + 271,271,271,277,271,636,702, +271,547,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, + 271,271,141,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, + 271,271,271,271,277,271,637,143, +20,20,20,20,20,20,20,20,638,1,937, 703,388,639,65,704, -261,261,261,261,261,261,261,261,261,640, -258,248,263,549,550,263,257,257,257,257,257,259,243,243,243,243,252,252,243, - 243,641,252, +260,260,260,260,260,260,260,260,260,640, +258,248,262,549,550,262,257,257,257,257,257,243,243,243,243,252,252,243,243, + 641,252, 117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135, 136,137,138,139,140,68,69,70,71,72,73,141,142,143,144,145,146,74,75,76, 77,78,147,148,149,79,80,81,82,83,150,151,152,153,154,155,156,157,158, @@ -6286,184 +6266,184 @@ static const unsigned short ag_pstt[] = { 179,180,181,182,183,184,185,186,165,166,167,168,169,170,84,85,86,87,88, 89,51,52,53,90,91,92,93,94,95,96,97,98,54,55,99,100,101,102,103,104,105, 106,56,57,58,107,108,59,60,109,110,111,112,61,62,63,64,642,705,706,202, - 706,706,706,706,706,706,706,706,706,706,333,333,333,333,333,334,335,336, - 337,340,340,340,341,342,346,346,346,346,347,348,349,350,351,352,353,354, - 357,357,357,358,359,360,361,362,363,364,365,366,370,370,370,370,371,372, - 373,374,375,376,248,247,246,245,244,243,264,263,262,261,260,259,258,257, + 706,706,706,706,706,706,706,706,706,706,332,332,332,332,332,333,334,335, + 336,339,339,339,340,341,345,345,345,345,346,347,348,349,350,351,352,353, + 356,356,356,357,358,359,360,361,362,363,364,365,369,369,369,369,370,371, + 372,373,374,375,248,247,246,245,244,243,264,263,262,261,260,259,258,257, 256,255,254,253,252,251,250,249,190,116,189,115,188,114,187,242,241,240, 239,238,237,236,235,234,233,232,231,230,229,228,227,227,227,227,227,227, 226,225,224,223,223,223,223,223,223,222,221,220,219,218,217,216,216,216, 216,215,215,215,215,214,213,212,211,210,209,208,207,206,205,204,203,201, 200,199,198,197,196,195,194,193,192,191, -272,547,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, - 272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, - 272,272,272,278,272,643,707, +271,547,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, + 271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, + 271,271,271,277,271,643,707, 385,644,708, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,636, - 287,146,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289, - 298,310,284,271,136,135,645,240,295,296,241,291,125,278,242,292,637,126, - 267,335,334,332,337,333,336,331,127,226,326,709,312,265,327,331,330,329, - 328,225,331,321,320,319,318,317,316,315,314,313,311,294,293,279,265,638, - 309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,146,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289, - 298,310,284,271,136,135,646,240,295,296,241,291,104,278,242,292,267,335, - 334,332,337,333,336,331,105,226,326,312,265,327,331,330,329,328,225,331, - 321,320,319,318,317,316,315,314,313,311,294,293,279,265,309,308, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,636, + 145,296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288, + 297,309,284,270,135,645,240,294,295,241,290,125,278,242,291,637,126,267, + 335,334,332,337,333,336,331,127,225,326,709,311,265,226,327,331,330,329, + 328,224,331,320,319,318,317,316,315,314,313,312,310,293,292,279,265,638, + 308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 145,296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288, + 297,309,284,270,135,646,240,294,295,241,290,104,278,242,291,267,335,334, + 332,337,333,336,331,105,225,326,311,265,226,327,331,330,329,328,224,331, + 320,319,318,317,316,315,314,313,312,310,293,292,279,265,308,307, 703,97,97,97,97,97,97,647,710, 703,96,96,96,96,96,96,648,710, 703,95,95,95,95,95,95,649,710, 703,94,94,94,94,94,94,650,704, 703,91,91,91,91,91,91,651,704, 359,361,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380, - 381,382,389,392,393,394,323,325,391,383,387,384,386,390,362,360,711,310, + 381,382,389,393,394,392,323,325,391,383,387,384,386,390,362,360,711,309, 388,385,41,44,713,713,712,652,68,1,713,68,68,68,68,69,68,68,68,68,68,68, 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68, 68,68,68,68,68, 714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714, 714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714, - 714,714,714,714,714,1,653,1,714, + 714,714,714,714,1,653,1,714, 43,44,45,40,61,654,61,61,48,61,47,46,46, 43,44,45,40,60,655,60,60,48,60,47,46,46, 43,44,45,40,59,656,59,59,48,59,47,46,46, 715,715,715,715,715,715,715,715,715,657, 716,716,716,716,716,658, -154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,716,716,716, - 716,716,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, - 154,154,154,154,154,659, -270,660, -717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,1,661,1,717, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,662,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,718,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,663,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,719,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,664,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,720,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,665,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,721,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,666,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,722,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,667,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,723,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,668,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,724,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,669,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,725,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,670,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,726,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,671,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,727,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,716,716,716, + 716,716,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, + 153,153,153,153,153,659, +269,660, +717,717,717,717,717,717,717,717,717,717,717,717,717,1,661,1,717, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,662,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,718,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,663,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,719,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,664,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,720,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,665,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,721,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,666,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,722,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,667,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,723,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,668,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,724,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,669,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,725,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,670,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,726,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,671,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,727,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, 728,1,672,1,728, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, - 136,135,673,240,295,296,241,291,242,292,267,226,326,312,265,219,225,219, - 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, - 136,135,674,240,295,296,241,291,242,292,267,226,326,312,265,218,225,218, - 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, - 136,135,675,240,295,296,241,291,242,292,267,226,326,312,265,217,225,217, - 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, - 136,135,676,240,295,296,241,291,242,292,267,226,326,312,265,216,225,216, - 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,286,563,289,298,310,284,271, - 136,135,677,240,295,296,241,291,242,292,267,226,326,312,265,215,225,215, - 321,320,319,318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,678,240,295,296,241,291,242,292,267,729,331,226,326, - 312,265,327,331,330,329,328,225,331,321,320,319,318,317,316,315,314,313, - 311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,679,240,295,296,241,291,242,292,267,730,331,226,326, - 312,265,327,331,330,329,328,225,331,321,320,319,318,317,316,315,314,313, - 311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,680,240,295,296,241,291,242,292,267,332,731,331,226, - 326,312,265,327,331,330,329,328,225,331,321,320,319,318,317,316,315,314, - 313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,681,240,295,296,241,291,242,292,267,332,732,331,226, - 326,312,265,327,331,330,329,328,225,331,321,320,319,318,317,316,315,314, - 313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,682,240,295,296,241,291,242,292,267,332,733,331,226, - 326,312,265,327,331,330,329,328,225,331,321,320,319,318,317,316,315,314, - 313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,683,240,295,296,241,291,242,292,267,332,734,331,226, - 326,312,265,327,331,330,329,328,225,331,321,320,319,318,317,316,315,314, - 313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,684,240,295,296,241,291,242,292,267,735,332,333,331, - 226,326,312,265,327,331,330,329,328,225,331,321,320,319,318,317,316,315, - 314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,685,240,295,296,241,291,242,292,267,736,332,333,331, - 226,326,312,265,327,331,330,329,328,225,331,321,320,319,318,317,316,315, - 314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,686,240,295,296,241,291,242,292,267,737,334,332,333, - 331,226,326,312,265,327,331,330,329,328,225,331,321,320,319,318,317,316, - 315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,687,240,295,296,241,291,242,292,267,738,334,332,333, - 331,226,326,312,265,327,331,330,329,328,225,331,321,320,319,318,317,316, - 315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,688,240,295,296,241,291,242,292,267,335,334,332,333, - 739,331,226,326,312,265,327,331,330,329,328,225,331,321,320,319,318,317, - 316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,689,240,295,296,241,291,242,292,267,335,334,332,333, - 740,331,226,326,312,265,327,331,330,329,328,225,331,321,320,319,318,317, - 316,315,314,313,311,294,293,265,309,308, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,286,563,288,297,309,284,270, + 135,673,240,294,295,241,290,242,291,267,225,326,311,265,226,218,224,218, + 320,319,318,317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,286,563,288,297,309,284,270, + 135,674,240,294,295,241,290,242,291,267,225,326,311,265,226,217,224,217, + 320,319,318,317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,286,563,288,297,309,284,270, + 135,675,240,294,295,241,290,242,291,267,225,326,311,265,226,216,224,216, + 320,319,318,317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,286,563,288,297,309,284,270, + 135,676,240,294,295,241,290,242,291,267,225,326,311,265,226,215,224,215, + 320,319,318,317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,286,563,288,297,309,284,270, + 135,677,240,294,295,241,290,242,291,267,225,326,311,265,226,214,224,214, + 320,319,318,317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,678,240,294,295,241,290,242,291,267,729,331,225,326,311, + 265,226,327,331,330,329,328,224,331,320,319,318,317,316,315,314,313,312, + 310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,679,240,294,295,241,290,242,291,267,730,331,225,326,311, + 265,226,327,331,330,329,328,224,331,320,319,318,317,316,315,314,313,312, + 310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,680,240,294,295,241,290,242,291,267,332,731,331,225,326, + 311,265,226,327,331,330,329,328,224,331,320,319,318,317,316,315,314,313, + 312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,681,240,294,295,241,290,242,291,267,332,732,331,225,326, + 311,265,226,327,331,330,329,328,224,331,320,319,318,317,316,315,314,313, + 312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,682,240,294,295,241,290,242,291,267,332,733,331,225,326, + 311,265,226,327,331,330,329,328,224,331,320,319,318,317,316,315,314,313, + 312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,683,240,294,295,241,290,242,291,267,332,734,331,225,326, + 311,265,226,327,331,330,329,328,224,331,320,319,318,317,316,315,314,313, + 312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,684,240,294,295,241,290,242,291,267,735,332,333,331,225, + 326,311,265,226,327,331,330,329,328,224,331,320,319,318,317,316,315,314, + 313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,685,240,294,295,241,290,242,291,267,736,332,333,331,225, + 326,311,265,226,327,331,330,329,328,224,331,320,319,318,317,316,315,314, + 313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,686,240,294,295,241,290,242,291,267,737,334,332,333,331, + 225,326,311,265,226,327,331,330,329,328,224,331,320,319,318,317,316,315, + 314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,687,240,294,295,241,290,242,291,267,738,334,332,333,331, + 225,326,311,265,226,327,331,330,329,328,224,331,320,319,318,317,316,315, + 314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,688,240,294,295,241,290,242,291,267,335,334,332,333,739, + 331,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318,317,316, + 315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,689,240,294,295,241,290,242,291,267,335,334,332,333,740, + 331,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318,317,316, + 315,314,313,312,310,293,292,265,308,307, 741,741,741,741,741,1,690,1,741, 43,44,45,40,36,691,36,36,48,36,47,46,46, 43,44,45,40,35,692,35,35,48,35,47,46,46, @@ -6472,58 +6452,57 @@ static const unsigned short ag_pstt[] = { 742,742,742,742,742,1,695,1,742, 743,743,743,743,743,1,696,1,743, 43,44,45,40,73,697,73,73,48,73,47,46,46, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,698,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,404,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,699,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,402,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,700,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,400,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,698,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,403,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,699,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,401,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,700,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,399,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, 703,701,744, -272,547,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, - 272,272,269,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, - 272,272,272,272,278,272,702,745, +271,547,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, + 271,271,268,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, + 271,271,271,271,277,271,702,745, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 20,20,20,20,703,1,948, + 20,20,20,703,1,945, 746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746, 746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746, - 746,746,746,746,746,746,1,704,1,746, + 746,746,746,746,746,1,704,1,746, 487,705,488, -20,328,328,328,328,328,1,706,1,317, -272,547,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, - 272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272, - 272,272,272,278,272,707,143, +20,327,327,327,327,327,1,706,1,316, +271,547,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, + 271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, + 271,271,271,277,271,707,142, 747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747, 747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747, - 747,747,747,747,747,1,708,1,747, + 747,747,747,747,1,708,1,747, 703,103,103,103,103,103,103,709,704, -748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,1,710,1,748, +748,748,748,748,748,748,748,748,748,748,748,748,748,1,710,1,748, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,711,1, - 916, + 913, 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68, 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,18,18,18,18,18,18,712, 43,44,45,40,64,713,64,64,48,64,47,46,46, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,714,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,749,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -162,162,162,162,162,162,162,162,161,161,161,161,162,162,162,162,161,161,161, - 161,161,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162, - 162,162,162,162,162,715, -158,158,158,158,158,716, -137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,717,752,750,750, - 751, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,714,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,749,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +161,161,161,161,161,161,161,161,160,160,160,160,161,161,161,161,160,160,160, + 160,160,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, + 161,161,161,161,161,715, +157,157,157,157,157,716, +136,136,136,136,136,136,136,136,136,136,136,136,135,717,752,750,750,751, 388,718,238, 388,719,237, 388,720,236, @@ -6535,57 +6514,57 @@ static const unsigned short ag_pstt[] = { 388,726,230, 388,727,229, 388,728,228, -213,564,566,391,383,387,213,213,213,213,213,213,213,213,213,213,213,213,213, - 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213, - 729,570,569,568,567,565, 212,564,566,391,383,387,212,212,212,212,212,212,212,212,212,212,212,212,212, 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, + 729,570,569,568,567,565, +211,564,566,391,383,387,211,211,211,211,211,211,211,211,211,211,211,211,211, + 211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, 730,570,569,568,567,565, -210,384,386,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, - 210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,731,572,571, 209,384,386,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209, - 209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,732,572,571, + 209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,731,572,571, 208,384,386,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, - 208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,733,572,571, + 208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,732,572,571, 207,384,386,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, - 207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,734,572,571, -205,573,575,577,579,205,205,205,205,205,205,205,205,205,205,205,205,205,205, - 205,205,205,205,205,205,205,205,205,205,205,205,205,735,580,578,576,574, + 207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,733,572,571, +206,384,386,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, + 206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,734,572,571, 204,573,575,577,579,204,204,204,204,204,204,204,204,204,204,204,204,204,204, - 204,204,204,204,204,204,204,204,204,204,204,204,204,736,580,578,576,574, -202,581,390,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, - 202,202,202,202,202,202,202,202,202,737,583,582, + 204,204,204,204,204,204,204,204,204,204,204,204,204,735,580,578,576,574, +203,573,575,577,579,203,203,203,203,203,203,203,203,203,203,203,203,203,203, + 203,203,203,203,203,203,203,203,203,203,203,203,203,736,580,578,576,574, 201,581,390,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201, - 201,201,201,201,201,201,201,201,201,738,583,582, -199,584,362,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, - 199,199,199,199,199,199,199,739,586,585, + 201,201,201,201,201,201,201,201,201,737,583,582, +200,581,390,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, + 200,200,200,200,200,200,200,200,200,738,583,582, 198,584,362,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, - 198,198,198,198,198,198,198,740,586,585, + 198,198,198,198,198,198,198,739,586,585, +197,584,362,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197, + 197,197,197,197,197,197,197,740,586,585, 43,44,45,40,47,741,47,47,48,47,47,46,46, 43,44,45,40,30,742,30,30,48,30,47,46,46, 43,44,45,40,29,743,29,29,48,29,47,46,46, 753,753,753,753,753,753,753,753,753,1,744,1,753, -143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, - 143,143,270,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, - 143,143,143,143,143,143,745, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,636, - 287,146,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289, - 298,310,284,271,136,135,746,240,295,296,241,291,129,278,242,292,637,130, - 267,335,334,332,337,333,336,331,128,226,326,312,265,327,331,330,329,328, - 225,331,321,320,319,318,317,316,315,314,313,311,294,293,279,265,638,309, - 308, -137,137,137,137,137,137,137,137,137,137,137,285,137,256,256,256,256,288,290, - 287,297,299,300,301,302,303,304,305,306,307,323,324,325,286,322,289,298, - 310,284,271,136,135,747,240,295,296,241,291,242,292,267,335,334,332,337, - 333,336,331,107,226,326,312,265,327,331,330,329,328,225,331,321,320,319, - 318,317,316,315,314,313,311,294,293,265,309,308, -137,137,137,137,137,137,137,137,137,137,137,137,137,136,135,748,132,265,265, +142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, + 142,142,269,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, + 142,142,142,142,142,142,745, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,636, + 145,296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288, + 297,309,284,270,135,746,240,294,295,241,290,129,278,242,291,637,130,267, + 335,334,332,337,333,336,331,128,225,326,311,265,226,327,331,330,329,328, + 224,331,320,319,318,317,316,315,314,313,312,310,293,292,279,265,638,308, + 307, +136,136,136,136,136,136,136,136,136,136,136,285,136,256,256,256,256,287,289, + 296,298,299,300,301,302,303,304,305,306,321,323,324,325,286,322,288,297, + 309,284,270,135,747,240,294,295,241,290,242,291,267,335,334,332,337,333, + 336,331,107,225,326,311,265,226,327,331,330,329,328,224,331,320,319,318, + 317,316,315,314,313,312,310,293,292,265,308,307, +136,136,136,136,136,136,136,136,136,136,136,136,135,748,132,265,265, 754,754,754,754,754,1,749,1,754, -138,138,138,138,138,138,138,138,138,138,138,138,139,139,139,139,139,138,20, - 138,1,750,1,133,139, -20,20,751,1,991, +137,137,137,137,137,137,137,137,137,137,137,137,138,138,138,138,138,20,137, + 1,750,1,133,138, +20,20,751,1,989, 755,1,752,1,755, -293,292,292,289,288,287,286,285,284,753,389,292,628, +292,291,291,288,287,286,285,284,283,753,388,291,628, 43,44,45,40,62,754,62,62,48,62,47,46,46, 388,755,239, @@ -6593,130 +6572,130 @@ static const unsigned short ag_pstt[] = { static const unsigned short ag_sbt[] = { - 0, 31, 33, 74, 92, 123, 153, 354, 357, 375, 576, 945, 984,1003, - 1022,1027,1032,1079,1084,1093,1102,1121,1167,1213,1232,1241,1266,1286, - 1305,1310,1315,1362,1367,1376,1385,1404,1491,1578,1597,1608,1617,1675, - 1767,1773,1821,1872,1918,2010,2097,2184,2560,2571,2581,2591,2601,2611, - 2621,2631,2641,2651,2661,2671,2681,2691,2701,2711,2724,2737,2748,2794, - 2840,2886,2932,2978,3024,3070,3116,3162,3208,3254,3300,3346,3392,3438, - 3484,3494,3504,3514,3524,3534,3544,3554,3564,3574,3584,3594,3604,3614, - 3624,3634,3644,3654,3664,3674,3684,3694,3704,3714,3724,3734,3744,3754, - 3764,3774,3782,3795,3808,3819,3865,3911,3957,4003,4049,4095,4141,4187, - 4233,4279,4325,4371,4417,4463,4509,4555,4601,4647,4693,4739,4785,4831, - 4877,4923,4969,5015,5061,5107,5153,5199,5245,5291,5337,5383,5429,5475, - 5521,5567,5613,5659,5705,5751,5797,5843,5889,5935,5981,6027,6039,6051, - 6063,6075,6083,6091,6102,6113,6124,6137,6150,6163,6176,6189,6202,6215, - 6228,6241,6254,6267,6280,6293,6301,6306,6311,6316,6362,6408,6454,6500, - 6546,6592,6638,6684,6730,6776,6822,6868,6914,6960,7006,7052,7098,7144, - 7190,7236,7282,7328,7374,7420,7466,7512,7558,7604,7650,7696,7742,7788, - 7834,7880,7926,7972,8018,8064,8110,8156,8202,8248,8294,8340,8386,8432, - 8478,8524,8570,8616,8662,8708,8720,8732,8744,8756,8764,8772,8783,8794, - 8805,8818,8831,8844,8857,8870,8883,8896,8909,8922,8935,8948,8961,8974, - 9035,9045,9116,9124,9127,9214,9293,9302,9346,9355,9360,9365,9454,9498, - 9510,9519,9532,9545,9554,9560,9565,9568,9628,9684,9690,9734,9740,9751, - 9795,9837,9886,9940,9945,9955,9960,9965,9970,9975,9980,9985,9990,9995, - 10000,10042,10084,10150,10155,10160,10165,10170,10175,10180,10185,10190, - 10195,10200,10205,10248,10313,10356,10421,10467,10537,10607,10677,10747, - 10789,10834,10873,10912,10945,10976,10981,11020,11105,11114,11123,11131, - 11140,11149,11158,11167,11186,11205,11214,11223,11232,11241,11283,11292, - 11301,11310,11335,11365,11416,11482,11533,11599,11647,11698,11749,11800, - 11851,11902,11953,12004,12055,12106,12157,12208,12259,12310,12361,12412, - 12463,12514,12565,12616,12681,12747,12813,12879,12944,13019,13070,13136, - 13201,13252,13303,13354,13412,13496,13499,13502,13548,13633,13716,13725, - 13743,13760,13773,13786,13792,13795,13798,13801,13886,13971,14056,14141, - 14226,14311,14396,14481,14566,14651,14736,14821,14906,14991,15076,15161, - 15246,15331,15416,15501,15586,15671,15756,15841,15926,16011,16096,16181, - 16266,16351,16436,16521,16606,16691,16776,16861,16946,17031,17116,17201, - 17286,17371,17456,17541,17626,17711,17796,17881,17966,18051,18136,18221, - 18236,18251,18266,18281,18289,18297,18310,18323,18336,18353,18370,18383, - 18396,18409,18422,18435,18448,18461,18474,18487,18500,18513,18606,18628, - 18765,18902,18921,18940,18963,18985,18994,19003,19009,19018,19027,19036, - 19060,19085,19090,19095,19142,19189,19281,19327,19412,19431,19450,19469, - 19488,19507,19527,19546,19566,19585,19605,19652,19699,19792,19839,19886, - 19933,20026,20072,20118,20203,20212,20258,20304,20350,20435,20454,20465, - 20476,20489,20571,20584,20587,20596,20605,20614,20629,20642,20655,20665, - 20672,20717,20767,20817,20820,20823,20826,20829,20832,20835,20838,20841, - 20844,20847,20850,20935,20941,20984,21027,21070,21113,21156,21199,21242, - 21288,21334,21380,21426,21472,21518,21564,21610,21656,21702,21748,21794, - 21840,21886,21932,21978,22024,22070,22116,22162,22208,22254,22300,22346, - 22392,22438,22484,22530,22576,22622,22668,22681,22694,22707,22720,22733, - 22752,22765,22778,22822,22835,22848,22874,22883,22892,22901,22910,22956, - 23041,23087,23172,23185,23194,23203,23214,23225,23236,23248,23259,23305, - 23351,23397,23407,23417,23422,23466,23511,23522,23527,23537,23559,23850, - 23894,23897,23990,24079,24088,24097,24106,24115,24124,24212,24258,24271, - 24284,24297,24307,24313,24356,24358,24377,24462,24547,24632,24717,24802, - 24887,24972,25057,25142,25227,25232,25302,25372,25442,25512,25582,25661, - 25740,25820,25900,25980,26060,26141,26222,26304,26386,26469,26552,26561, - 26574,26587,26600,26613,26622,26631,26644,26729,26814,26899,26902,26947, - 27003,27050,27053,27063,27107,27153,27162,27181,27230,27277,27290,27375, - 27418,27424,27444,27447,27450,27453,27456,27459,27462,27465,27468,27471, - 27474,27477,27520,27563,27600,27637,27674,27711,27748,27785,27816,27847, - 27876,27905,27918,27931,27944,27957,28001,28093,28178,28197,28206,28231, - 28236,28241,28254,28267,28270 + 0, 29, 31, 70, 88, 119, 149, 348, 351, 369, 568, 935, 972, 989, + 1006,1011,1016,1062,1067,1076,1085,1102,1147,1192,1209,1218,1243,1261, + 1278,1283,1288,1334,1339,1348,1357,1374,1461,1548,1565,1576,1585,1642, + 1734,1740,1788,1839,1885,1977,2064,2151,2525,2536,2546,2556,2566,2576, + 2586,2596,2606,2616,2626,2636,2646,2656,2666,2676,2689,2702,2713,2758, + 2803,2848,2893,2938,2983,3028,3073,3118,3163,3208,3253,3298,3343,3388, + 3433,3443,3453,3463,3473,3483,3493,3503,3513,3523,3533,3543,3553,3563, + 3573,3583,3593,3603,3613,3623,3633,3643,3653,3663,3673,3683,3693,3703, + 3713,3723,3731,3744,3757,3768,3813,3858,3903,3948,3993,4038,4083,4128, + 4173,4218,4263,4308,4353,4398,4443,4488,4533,4578,4623,4668,4713,4758, + 4803,4848,4893,4938,4983,5028,5073,5118,5163,5208,5253,5298,5343,5388, + 5433,5478,5523,5568,5613,5658,5703,5748,5793,5838,5883,5928,5940,5952, + 5964,5976,5984,5992,6003,6014,6025,6038,6051,6064,6077,6090,6103,6116, + 6129,6142,6155,6168,6181,6194,6202,6207,6212,6217,6262,6307,6352,6397, + 6442,6487,6532,6577,6622,6667,6712,6757,6802,6847,6892,6937,6982,7027, + 7072,7117,7162,7207,7252,7297,7342,7387,7432,7477,7522,7567,7612,7657, + 7702,7747,7792,7837,7882,7927,7972,8017,8062,8107,8152,8197,8242,8287, + 8332,8377,8422,8467,8512,8557,8569,8581,8593,8605,8613,8621,8632,8643, + 8654,8667,8680,8693,8706,8719,8732,8745,8758,8771,8784,8797,8810,8823, + 8884,8894,8965,8973,8976,9063,9142,9151,9195,9204,9209,9214,9303,9347, + 9359,9368,9381,9394,9403,9409,9414,9417,9472,9478,9522,9528,9539,9583, + 9625,9674,9727,9732,9742,9747,9752,9757,9762,9767,9772,9777,9782,9787, + 9829,9871,9936,9941,9946,9951,9956,9961,9966,9971,9976,9981,9986,9991, + 10040,10082,10146,10188,10252,10297,10367,10437,10507,10577,10619,10664, + 10703,10742,10775,10806,10811,10850,10935,10944,10953,10961,10970,10979, + 10988,10997,11014,11031,11040,11049,11058,11067,11109,11118,11127,11136, + 11161,11191,11242,11307,11358,11423,11471,11522,11573,11624,11675,11726, + 11777,11828,11879,11930,11981,12032,12083,12134,12185,12236,12287,12338, + 12389,12440,12504,12569,12634,12699,12763,12838,12889,12954,13018,13069, + 13120,13171,13228,13312,13315,13318,13363,13448,13531,13540,13558,13575, + 13588,13601,13607,13610,13613,13616,13701,13786,13871,13956,14041,14126, + 14211,14296,14381,14466,14551,14636,14721,14806,14891,14976,15061,15146, + 15231,15316,15401,15486,15571,15656,15741,15826,15911,15996,16081,16166, + 16251,16336,16421,16506,16591,16676,16761,16846,16931,17016,17101,17186, + 17271,17356,17441,17526,17611,17696,17781,17866,17951,18036,18051,18066, + 18081,18096,18104,18112,18125,18138,18151,18168,18185,18198,18211,18224, + 18237,18250,18263,18276,18289,18302,18315,18328,18421,18443,18580,18717, + 18734,18751,18774,18796,18805,18814,18820,18829,18838,18847,18869,18892, + 18897,18902,18948,18994,19086,19131,19216,19233,19250,19267,19284,19301, + 19319,19336,19354,19371,19389,19435,19481,19574,19620,19666,19712,19805, + 19850,19895,19980,19989,20034,20079,20124,20209,20226,20237,20248,20261, + 20343,20356,20359,20368,20377,20386,20401,20414,20427,20437,20444,20489, + 20539,20589,20592,20595,20598,20601,20604,20607,20610,20613,20616,20619, + 20622,20707,20713,20755,20797,20839,20881,20923,20965,21007,21052,21097, + 21142,21187,21232,21277,21322,21367,21412,21457,21502,21547,21592,21637, + 21682,21727,21772,21817,21862,21907,21952,21997,22042,22087,22132,22177, + 22222,22267,22312,22357,22402,22415,22428,22441,22454,22467,22484,22497, + 22510,22554,22567,22580,22606,22615,22624,22633,22642,22687,22772,22817, + 22902,22915,22924,22933,22944,22955,22966,22978,22989,23034,23079,23124, + 23134,23144,23149,23193,23238,23249,23254,23264,23285,23576,23620,23623, + 23716,23805,23814,23823,23832,23841,23850,23938,23983,23996,24009,24022, + 24032,24038,24081,24083,24100,24185,24270,24355,24440,24525,24610,24695, + 24780,24865,24950,24955,25025,25095,25165,25235,25305,25384,25463,25543, + 25623,25703,25783,25864,25945,26027,26109,26192,26275,26284,26297,26310, + 26323,26336,26345,26354,26367,26452,26537,26622,26625,26670,26725,26771, + 26774,26784,26828,26873,26882,26899,26948,26995,27008,27093,27136,27142, + 27160,27163,27166,27169,27172,27175,27178,27181,27184,27187,27190,27193, + 27236,27279,27316,27353,27390,27427,27464,27501,27532,27563,27592,27621, + 27634,27647,27660,27673,27717,27809,27894,27911,27920,27944,27949,27954, + 27967,27980,27983 }; static const unsigned short ag_sbe[] = { - 28, 32, 60, 89, 121, 137, 351, 355, 365, 573, 773, 972,1000,1019, - 1024,1029,1076,1081,1090,1099,1118,1164,1210,1229,1238,1263,1281,1301, - 1307,1312,1359,1363,1373,1382,1400,1446,1533,1593,1602,1610,1672,1764, - 1769,1818,1869,1915,1963,2053,2140,2381,2568,2578,2588,2598,2608,2618, - 2628,2638,2648,2658,2668,2678,2688,2698,2708,2721,2734,2745,2791,2837, - 2883,2929,2975,3021,3067,3113,3159,3205,3251,3297,3343,3389,3435,3481, - 3491,3501,3511,3521,3531,3541,3551,3561,3571,3581,3591,3601,3611,3621, - 3631,3641,3651,3661,3671,3681,3691,3701,3711,3721,3731,3741,3751,3761, - 3771,3779,3792,3805,3816,3862,3908,3954,4000,4046,4092,4138,4184,4230, - 4276,4322,4368,4414,4460,4506,4552,4598,4644,4690,4736,4782,4828,4874, - 4920,4966,5012,5058,5104,5150,5196,5242,5288,5334,5380,5426,5472,5518, - 5564,5610,5656,5702,5748,5794,5840,5886,5932,5978,6024,6036,6048,6060, - 6072,6080,6088,6099,6110,6121,6134,6147,6160,6173,6186,6199,6212,6225, - 6238,6251,6264,6277,6290,6298,6303,6308,6313,6359,6405,6451,6497,6543, - 6589,6635,6681,6727,6773,6819,6865,6911,6957,7003,7049,7095,7141,7187, - 7233,7279,7325,7371,7417,7463,7509,7555,7601,7647,7693,7739,7785,7831, - 7877,7923,7969,8015,8061,8107,8153,8199,8245,8291,8337,8383,8429,8475, - 8521,8567,8613,8659,8705,8717,8729,8741,8753,8761,8769,8780,8791,8802, - 8815,8828,8841,8854,8867,8880,8893,8906,8919,8932,8945,8958,8971,9031, - 9042,9114,9122,9125,9169,9251,9299,9343,9352,9356,9361,9408,9496,9507, - 9516,9524,9537,9551,9559,9564,9567,9627,9683,9689,9732,9739,9750,9794, - 9836,9885,9938,9942,9952,9957,9962,9967,9972,9977,9982,9987,9992,9997, - 10039,10081,10147,10152,10157,10162,10167,10172,10177,10182,10187,10192, - 10197,10202,10245,10310,10353,10418,10464,10506,10576,10646,10716,10786, - 10826,10868,10905,10940,10971,10978,11000,11062,11111,11120,11129,11137, - 11146,11155,11164,11183,11202,11211,11220,11229,11238,11282,11289,11298, - 11307,11332,11356,11413,11479,11530,11596,11644,11695,11746,11797,11848, - 11899,11950,12001,12052,12103,12154,12205,12256,12307,12358,12409,12460, - 12511,12562,12613,12678,12744,12810,12876,12941,13016,13067,13133,13198, - 13249,13300,13351,13409,13454,13497,13500,13545,13590,13672,13722,13732, - 13752,13769,13780,13790,13793,13796,13799,13843,13928,14013,14098,14183, - 14268,14353,14438,14523,14608,14693,14778,14863,14948,15033,15118,15203, - 15288,15373,15458,15543,15628,15713,15798,15883,15968,16053,16138,16223, - 16308,16393,16478,16563,16648,16733,16818,16903,16988,17073,17158,17243, - 17328,17413,17498,17583,17668,17753,17838,17923,18008,18093,18178,18229, - 18244,18259,18274,18285,18293,18304,18317,18330,18345,18362,18379,18392, - 18405,18418,18431,18444,18457,18470,18483,18496,18509,18556,18619,18762, - 18899,18918,18936,18960,18982,18991,19000,19006,19011,19024,19033,19057, - 19081,19086,19091,19139,19186,19233,19324,19369,19428,19446,19466,19484, - 19504,19522,19543,19561,19582,19600,19649,19696,19742,19836,19883,19930, - 19976,20069,20115,20160,20209,20255,20301,20347,20392,20450,20462,20473, - 20481,20529,20576,20585,20593,20602,20611,20627,20634,20647,20664,20671, - 20715,20766,20816,20818,20821,20824,20827,20830,20833,20836,20839,20842, - 20845,20848,20892,20940,20981,21024,21067,21110,21153,21196,21239,21285, - 21331,21377,21423,21469,21515,21561,21607,21653,21699,21745,21791,21837, - 21883,21929,21975,22021,22067,22113,22159,22205,22251,22297,22343,22389, - 22435,22481,22527,22573,22619,22665,22673,22686,22699,22712,22725,22748, - 22757,22770,22821,22827,22840,22871,22880,22889,22898,22907,22953,22998, - 23084,23129,23177,23191,23200,23211,23222,23233,23245,23256,23302,23348, - 23394,23404,23414,23419,23464,23509,23519,23524,23536,23557,23692,23892, - 23895,23940,24033,24086,24095,24104,24113,24122,24168,24255,24263,24276, - 24289,24306,24312,24355,24357,24374,24419,24504,24589,24674,24759,24844, - 24929,25014,25099,25184,25229,25271,25341,25411,25481,25551,25624,25703, - 25782,25862,25942,26022,26102,26183,26264,26346,26428,26511,26558,26566, - 26579,26592,26605,26619,26628,26636,26686,26771,26856,26900,26945,27000, - 27047,27051,27060,27105,27150,27160,27178,27227,27276,27282,27332,27417, - 27423,27439,27445,27448,27451,27454,27457,27460,27463,27466,27469,27472, - 27475,27514,27557,27597,27634,27671,27708,27743,27780,27813,27844,27873, - 27902,27910,27923,27936,27954,28000,28044,28135,28193,28203,28227,28233, - 28238,28250,28259,28268,28270 + 26, 30, 56, 85, 117, 133, 345, 349, 359, 565, 763, 960, 986,1003, + 1008,1013,1059,1064,1073,1082,1099,1144,1189,1206,1215,1240,1256,1274, + 1280,1285,1331,1335,1345,1354,1370,1415,1502,1561,1570,1578,1639,1731, + 1736,1785,1836,1882,1930,2020,2107,2346,2533,2543,2553,2563,2573,2583, + 2593,2603,2613,2623,2633,2643,2653,2663,2673,2686,2699,2710,2755,2800, + 2845,2890,2935,2980,3025,3070,3115,3160,3205,3250,3295,3340,3385,3430, + 3440,3450,3460,3470,3480,3490,3500,3510,3520,3530,3540,3550,3560,3570, + 3580,3590,3600,3610,3620,3630,3640,3650,3660,3670,3680,3690,3700,3710, + 3720,3728,3741,3754,3765,3810,3855,3900,3945,3990,4035,4080,4125,4170, + 4215,4260,4305,4350,4395,4440,4485,4530,4575,4620,4665,4710,4755,4800, + 4845,4890,4935,4980,5025,5070,5115,5160,5205,5250,5295,5340,5385,5430, + 5475,5520,5565,5610,5655,5700,5745,5790,5835,5880,5925,5937,5949,5961, + 5973,5981,5989,6000,6011,6022,6035,6048,6061,6074,6087,6100,6113,6126, + 6139,6152,6165,6178,6191,6199,6204,6209,6214,6259,6304,6349,6394,6439, + 6484,6529,6574,6619,6664,6709,6754,6799,6844,6889,6934,6979,7024,7069, + 7114,7159,7204,7249,7294,7339,7384,7429,7474,7519,7564,7609,7654,7699, + 7744,7789,7834,7879,7924,7969,8014,8059,8104,8149,8194,8239,8284,8329, + 8374,8419,8464,8509,8554,8566,8578,8590,8602,8610,8618,8629,8640,8651, + 8664,8677,8690,8703,8716,8729,8742,8755,8768,8781,8794,8807,8820,8880, + 8891,8963,8971,8974,9017,9100,9148,9192,9201,9205,9210,9256,9345,9356, + 9365,9373,9386,9400,9408,9413,9416,9471,9477,9520,9527,9538,9582,9624, + 9673,9725,9729,9739,9744,9749,9754,9759,9764,9769,9774,9779,9784,9826, + 9868,9933,9938,9943,9948,9953,9958,9963,9968,9973,9978,9983,9988,10037, + 10079,10143,10185,10249,10294,10335,10405,10475,10545,10616,10656,10698, + 10735,10770,10801,10808,10830,10891,10941,10950,10959,10967,10976,10985, + 10994,11011,11028,11037,11046,11055,11064,11108,11115,11124,11133,11158, + 11182,11239,11304,11355,11420,11468,11519,11570,11621,11672,11723,11774, + 11825,11876,11927,11978,12029,12080,12131,12182,12233,12284,12335,12386, + 12437,12501,12566,12631,12696,12760,12835,12886,12951,13015,13066,13117, + 13168,13225,13270,13313,13316,13360,13404,13487,13537,13547,13567,13584, + 13595,13605,13608,13611,13614,13657,13742,13827,13912,13997,14082,14167, + 14252,14337,14422,14507,14592,14677,14762,14847,14932,15017,15102,15187, + 15272,15357,15442,15527,15612,15697,15782,15867,15952,16037,16122,16207, + 16292,16377,16462,16547,16632,16717,16802,16887,16972,17057,17142,17227, + 17312,17397,17482,17567,17652,17737,17822,17907,17992,18044,18059,18074, + 18089,18100,18108,18119,18132,18145,18160,18177,18194,18207,18220,18233, + 18246,18259,18272,18285,18298,18311,18324,18370,18434,18577,18714,18731, + 18747,18771,18793,18802,18811,18817,18822,18835,18844,18866,18888,18893, + 18898,18945,18991,19037,19128,19172,19230,19246,19264,19280,19298,19314, + 19333,19349,19368,19384,19432,19478,19523,19617,19663,19709,19754,19847, + 19892,19936,19986,20031,20076,20121,20165,20222,20234,20245,20253,20301, + 20348,20357,20365,20374,20383,20399,20406,20419,20436,20443,20487,20538, + 20588,20590,20593,20596,20599,20602,20605,20608,20611,20614,20617,20620, + 20663,20712,20752,20794,20836,20878,20920,20962,21004,21049,21094,21139, + 21184,21229,21274,21319,21364,21409,21454,21499,21544,21589,21634,21679, + 21724,21769,21814,21859,21904,21949,21994,22039,22084,22129,22174,22219, + 22264,22309,22354,22399,22407,22420,22433,22446,22459,22480,22489,22502, + 22553,22559,22572,22603,22612,22621,22630,22639,22684,22728,22814,22858, + 22907,22921,22930,22941,22952,22963,22975,22986,23031,23076,23121,23131, + 23141,23146,23191,23236,23246,23251,23263,23283,23418,23618,23621,23665, + 23758,23812,23821,23830,23839,23848,23894,23980,23988,24001,24014,24031, + 24037,24080,24082,24097,24141,24226,24311,24396,24481,24566,24651,24736, + 24821,24906,24952,24993,25063,25133,25203,25273,25346,25425,25504,25584, + 25664,25744,25824,25905,25986,26068,26150,26233,26281,26289,26302,26315, + 26328,26342,26351,26359,26408,26493,26578,26623,26668,26722,26768,26772, + 26781,26826,26870,26880,26896,26945,26994,27000,27049,27135,27141,27155, + 27161,27164,27167,27170,27173,27176,27179,27182,27185,27188,27191,27230, + 27273,27313,27350,27387,27424,27459,27496,27529,27560,27589,27618,27626, + 27639,27652,27670,27716,27759,27850,27907,27917,27940,27946,27951,27963, + 27972,27981,27983 }; @@ -6724,17 +6703,17 @@ static const unsigned char ag_fl[] = { 2,1,1,2,2,1,1,2,0,1,3,3,1,1,2,1,2,2,1,2,0,1,4,5,3,2,1,0,1,7,7,6,1,1,6, 6,6,2,3,2,2,1,2,4,4,4,4,6,4,4,0,1,4,4,4,4,3,3,4,5,5,5,8,4,6,4,1,1,2,2, 2,2,3,5,1,2,2,2,3,2,1,1,1,3,2,1,1,3,1,1,1,3,1,1,3,3,3,3,3,3,3,3,3,4,4, - 4,3,6,2,3,2,1,1,2,2,3,3,2,2,3,3,1,1,2,3,1,1,1,4,4,4,1,4,2,1,1,1,1,2,2, - 1,2,2,3,2,2,1,2,3,1,2,2,2,2,2,2,2,2,4,1,1,4,3,2,1,2,3,3,2,1,1,1,1,1,1, - 2,1,1,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,2,4,4,2,4,4,2,4,4,2,4,4,4, - 4,2,4,4,2,4,4,4,4,4,1,2,2,2,2,1,1,1,5,5,5,5,5,5,5,5,5,5,5,7,1,1,1,1,1, - 1,1,2,2,2,1,1,2,2,2,2,1,2,2,2,3,2,2,2,2,2,2,2,2,3,4,1,1,2,2,2,2,2,1,2, - 1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3, - 3,3,3,3,7,3,3,3,3,3,3,3,3,3,3,5,3,5,3,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 3,1,1,1,1,1,3,3,3,3,1,1,1,1,1,3,3,3,3,3,3,3,1,1,1,3,1,1,1,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 4,3,6,2,3,2,1,1,2,2,3,3,2,2,3,3,1,1,2,3,1,1,1,4,4,4,1,4,2,1,1,1,2,2,1, + 2,2,3,2,2,1,2,3,1,2,2,2,2,2,2,2,2,4,1,1,4,3,2,1,2,3,3,2,1,1,1,1,1,1,2, + 1,1,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,2,4,4,2,4,4,2,4,4,2,4,4,4,4, + 2,4,4,2,4,4,4,4,4,1,2,2,2,2,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,7,1,1,1,1,1, + 1,1,2,2,2,1,1,2,2,2,2,1,2,2,3,2,2,2,2,2,2,2,2,3,4,1,1,2,2,2,2,2,1,2,1, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3, + 3,3,3,7,3,3,3,3,3,3,3,3,3,3,5,3,5,3,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 1,1,1,1,1,3,3,3,3,1,1,1,1,1,3,3,3,3,3,3,3,1,1,1,3,1,1,1,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -6746,7 +6725,6 @@ static const unsigned char ag_fl[] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, @@ -6754,7 +6732,8 @@ static const unsigned char ag_fl[] = { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2 + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2 }; static const unsigned short ag_ptt[] = { @@ -6765,64 +6744,64 @@ static const unsigned short ag_ptt[] = { 63, 63, 33, 33, 33, 33, 33, 33,103,103,103, 33, 33,107,107, 33,111,111, 111, 33,114,114, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 30, 30, 92, - 92, 92, 92, 92, 92,116,116,536,442,442,442,133,133,133,437,437,485, 18, - 18,435, 12, 12, 12,142,142,142,142,142,142,142,142,142,142,155,155,142, - 142,436, 14, 14, 14, 14,428,428,428,428,428, 22, 22, 77, 77,169,169,169, - 166,172,172,166,175,175,166,178,178,166,181,181,166,184,184,166, 57, 26, - 26, 26, 28, 28, 28, 23, 23, 23, 24, 24, 24, 24, 24, 27, 27, 27, 25, 25, - 25, 25, 25, 25, 29, 29, 29, 29, 29,198,198,198,198,207,207,207,207,207, - 207,207,207,207,207,207,206,206,492,492,492,492,492,492,492,492,223,223, - 492,492, 7, 7, 7, 7, 7, 7, 6, 6, 6, 17, 17,218,218,219,219, 15, - 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,538, 9, 9, 9,594,594,594,594, - 594,594,242,242,594,594,245,245,608,247,247,608,249,249,608,608,251,251, - 251,251,251,253,253,254,254,254,254,254,254, 31, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32,272,272,272,272,266,266,266,266,266,279,279,266,266, - 266,285,285,285,266,266,266,266,266,266,266,266,266,296,296,266,266,266, - 266,266,266,266,266,266,266,309,309,309,266,266,266,266,266,266,266,259, - 259,260,260,260,260,257,257,257,257,257,257,257,257,257,257,257,257,257, - 258,258,258,338,262,340,263,342,264,265,261,261,261,261,261,261,261,261, - 261,261,261,261,261,261,261,366,366,366,366,366,261,261,261,261,375,375, - 375,375,375,261,261,261,261,261,261,261,385,385,385,261,389,389,389,261, - 261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, - 261,261,261,261,261,261,138,345,153,226, 42, 42, 42, 42, 42, 42, 42, 42, + 92, 92, 92, 92, 92,116,116,536,441,441,133,133,133,436,436,484, 18, 18, + 434, 12, 12, 12,141,141,141,141,141,141,141,141,141,141,154,154,141,141, + 435, 14, 14, 14, 14,427,427,427,427,427, 22, 22, 77, 77,168,168,168,165, + 171,171,165,174,174,165,177,177,165,180,180,165,183,183,165, 57, 26, 26, + 26, 28, 28, 28, 23, 23, 23, 24, 24, 24, 24, 24, 27, 27, 27, 25, 25, 25, + 25, 25, 25, 29, 29, 29, 29, 29,197,197,197,197,197,206,206,206,206,206, + 206,206,206,206,206,206,205,205,491,491,491,491,491,491,491,491,222,222, + 491,491, 7, 7, 7, 7, 7, 6, 6, 6, 17, 17,217,217,218,218, 15, 15, + 15, 16, 16, 16, 16, 16, 16, 16, 16,538, 9, 9, 9,594,594,594,594,594, + 594,241,241,594,594,244,244,608,246,246,608,248,248,608,608,250,250,250, + 250,250,252,252,253,253,253,253,253,253, 31, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32,271,271,271,271,265,265,265,265,265,278,278,265,265,265, + 284,284,284,265,265,265,265,265,265,265,265,265,295,295,265,265,265,265, + 265,265,265,265,265,265,308,308,308,265,265,265,265,265,265,265,258,258, + 259,259,259,259,256,256,256,256,256,256,256,256,256,256,256,256,256,257, + 257,257,337,261,339,262,341,263,264,260,260,260,260,260,260,260,260,260, + 260,260,260,260,260,260,365,365,365,365,365,260,260,260,260,374,374,374, + 374,374,260,260,260,260,260,260,260,384,384,384,260,388,388,388,260,260, + 260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260, + 260,260,260,260,260,137,344,152,225, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 50, 50, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 50, 50, 50, 50, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,136,136,136,136, - 136,136,136,136,136,136,136,136,136,137,137,137,137,137,137,137,137,137, - 137,137,137,137,137,139,139,139,139,139,139,139,139,139,139,139,139,139, - 139,139,139,139,139,139,144,144,144,144,144,144,144,144,144,144,144,144, - 144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, - 144,144,144,144,144,144,144,144,144,144,151,151,151,152,152,152,152,152, - 156,156,156,156,156,156,156,156,156,159,159,159,159,159,159,159,159,159, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,135,135,135,135,135, + 135,135,135,135,135,135,135,136,136,136,136,136,136,136,136,136,136,136, + 136,136,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, + 138,138,138,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, + 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, + 143,143,143,143,143,143,143,150,150,150,151,151,151,151,151,155,155,155, + 155,155,155,155,155,155,158,158,158,158,158,158,158,158,158,158,158,158, + 158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, + 158,158,158,158,158,158,158,158,158,159,159,159,159,159,159,159,159,159, 159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159, - 159,159,159,159,159,159,159,159,159,159,159,159,160,160,160,160,160,160, - 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, - 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, - 227,227,227,227,228,228,230,230,230,230,232,232,232,232,232,232,232,232, - 232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, - 232,232,232,232,232,232,232,232,232,232,232,232,232,232, 45, 41, 46, 48, - 49, 11, 54, 56, 58, 59, 60, 61, 10, 13, 19, 66, 69, 68, 70, 21, 71, 72, - 73, 74, 76, 78, 79, 80, 81, 82, 83, 84, 86, 85, 87, 88, 93, 91, 96, 98, - 99,100,101,102,104,105,106,108,109,110,112,113,115,117,118,119,120,121, - 122,123,124,125, 20,126,127,128,129,130,131, 2,132,165,167,168,170,171, - 173,174,176,177,179,180,182,183,185,186,187,188,189,190,191,192,193,194, - 195,196,197,199,200,201,202,203,204,205,208,209,210,211,212,213,214,215, - 216, 3,217, 8,252,243,255,256,250,267,268,269,270,271,273,274,275,276, - 277,278,280,281,282,283,284,286,287,288,289,290,291,292,293,294,295,297, - 298,299,300,301,302,303,304,305,306,307,308,310,311,312,313,314,315,316, - 317,318,319,320,321, 4,322,323,324,325,326,327,328,329,330,331,332,333, - 334, 5,335,336,337,339,341,343,344,346,347,348,349,350,351,352,353,354, - 355,356,357,358,359,360,361,362,363,364,365,367,368,369,370,371,372,373, - 374,376,377,378,379,380,381,382,383,384,386,387,388,390,391,392,393,394, - 395,396,397,398,399,400,401,244,402,403,404,405,406,407,408,409,410,411, - 412,414,141,154,140,148,415,416,417,418,158,157,419,229,420,149,224,150, - 421,220,145,147,146,413,143,225,422 + 159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,226,226,226, + 226,227,227,229,229,229,229,231,231,231,231,231,231,231,231,231,231,231, + 231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, + 231,231,231,231,231,231,231,231,231,231,231, 45, 41, 46, 48, 49, 11, 54, + 56, 58, 59, 60, 61, 10, 13, 19, 66, 69, 68, 70, 21, 71, 72, 73, 74, 76, + 78, 79, 80, 81, 82, 83, 84, 86, 85, 87, 88, 93, 91, 96, 98, 99,100,101, + 102,104,105,106,108,109,110,112,113,115,117,118,119,120,121,122,123,124, + 125, 20,126,127,128,129,130,131, 2,132,164,166,167,169,170,172,173,175, + 176,178,179,181,182,184,185,186,187,188,189,190,191,192,193,194,195,196, + 198,199,200,201,202,203,204,153,207,208,209,210,211,212,213,214,215, 3, + 216, 8,251,242,254,255,249,266,267,268,269,270,272,273,274,275,276,277, + 279,280,281,282,283,285,286,287,288,289,290,291,292,293,294,296,297,298, + 299,300,301,302,303,304,305,306,307,309,310,311,312,313,314,315,316,317, + 318,319,320, 4,321,322,323,324,325,326,327,328,329,330,331,332,333, 5, + 334,335,336,338,340,342,343,345,346,347,348,349,350,351,352,353,354,355, + 356,357,358,359,360,361,362,363,364,366,367,368,369,370,371,372,373,375, + 376,377,378,379,380,381,382,383,385,386,387,389,390,391,392,393,394,395, + 396,397,398,399,400,243,401,402,403,404,405,406,407,408,409,410,411,413, + 140,139,147,414,415,416,417,157,156,418,228,419,148,223,149,420,219,144, + 146,145,412,142,224,421 }; @@ -6914,17 +6893,17 @@ static void ag_ra(void) case 83: ag_rp_83(); break; case 84: ag_rp_84(); break; case 85: ag_rp_85(); break; - case 86: ag_rp_86(); break; - case 87: ag_rp_87(V(0,int)); break; + case 86: ag_rp_86(V(0,int)); break; + case 87: ag_rp_87(V(1,int)); break; case 88: ag_rp_88(V(1,int)); break; - case 89: ag_rp_89(V(1,int)); break; - case 90: ag_rp_90(V(0,int)); break; - case 91: ag_rp_91(V(1,int)); break; - case 92: ag_rp_92(V(1,int), V(2,int)); break; - case 93: ag_rp_93(V(1,int)); break; - case 94: ag_rp_94(); break; - case 95: ag_rp_95(V(1,int)); break; - case 96: V(0,int) = ag_rp_96(V(0,int)); break; + case 89: ag_rp_89(V(0,int)); break; + case 90: ag_rp_90(V(1,int)); break; + case 91: ag_rp_91(V(1,int), V(2,int)); break; + case 92: ag_rp_92(V(1,int)); break; + case 93: ag_rp_93(); break; + case 94: ag_rp_94(V(1,int)); break; + case 95: V(0,int) = ag_rp_95(V(0,int)); break; + case 96: V(0,int) = ag_rp_96(); break; case 97: V(0,int) = ag_rp_97(); break; case 98: V(0,int) = ag_rp_98(); break; case 99: V(0,int) = ag_rp_99(); break; @@ -6932,21 +6911,21 @@ static void ag_ra(void) case 101: V(0,int) = ag_rp_101(); break; case 102: V(0,int) = ag_rp_102(); break; case 103: V(0,int) = ag_rp_103(); break; - case 104: V(0,int) = ag_rp_104(); break; - case 105: V(0,int) = ag_rp_105(V(1,int), V(2,int), V(3,int)); break; - case 106: V(0,int) = ag_rp_106(V(2,int), V(3,int)); break; - case 107: V(0,int) = ag_rp_107(V(2,int)); break; + case 104: V(0,int) = ag_rp_104(V(1,int), V(2,int), V(3,int)); break; + case 105: V(0,int) = ag_rp_105(V(2,int), V(3,int)); break; + case 106: V(0,int) = ag_rp_106(V(2,int)); break; + case 107: ag_rp_107(); break; case 108: ag_rp_108(); break; - case 109: ag_rp_109(); break; - case 110: ag_rp_110(V(1,int)); break; - case 111: ag_rp_111(V(2,int)); break; + case 109: ag_rp_109(V(1,int)); break; + case 110: ag_rp_110(V(2,int)); break; + case 111: ag_rp_111(); break; case 112: ag_rp_112(); break; case 113: ag_rp_113(); break; case 114: ag_rp_114(); break; case 115: ag_rp_115(); break; - case 116: ag_rp_116(); break; + case 116: V(0,int) = ag_rp_116(); break; case 117: V(0,int) = ag_rp_117(); break; - case 118: V(0,int) = ag_rp_118(); break; + case 118: ag_rp_118(); break; case 119: ag_rp_119(); break; case 120: ag_rp_120(); break; case 121: ag_rp_121(); break; @@ -6975,8 +6954,8 @@ static void ag_ra(void) case 144: ag_rp_144(); break; case 145: ag_rp_145(); break; case 146: ag_rp_146(); break; - case 147: ag_rp_147(); break; - case 148: ag_rp_148(V(0,double)); break; + case 147: ag_rp_147(V(0,double)); break; + case 148: ag_rp_148(); break; case 149: ag_rp_149(); break; case 150: ag_rp_150(); break; case 151: ag_rp_151(); break; @@ -7169,7 +7148,7 @@ static void ag_ra(void) } #define TOKEN_NAMES a85parse_token_names -const char *const a85parse_token_names[706] = { +const char *const a85parse_token_names[705] = { "a85parse", "WS", "integer", @@ -7304,7 +7283,6 @@ const char *const a85parse_token_names[706] = { "\"PAGE\"", "\",\"", "literal alpha", - "\"$\"", "\"&\"", "", "", @@ -7697,6 +7675,7 @@ const char *const a85parse_token_names[706] = { "'!'", "\"NOT\"", "'~'", + "'$'", "\"FLOOR\"", "\"CEIL\"", "\"LN\"", @@ -7852,7 +7831,6 @@ const char *const a85parse_token_names[706] = { "\"LJMP\"", "", "'\\\"'", - "'$'", "'\\''", "'0'", "", @@ -7881,69 +7859,69 @@ const char *const a85parse_token_names[706] = { static const unsigned short ag_ctn[] = { - 0,0, 0,0, 0,0, 65,1,428,1, 53,1, 35,1, 35,1, 35,1, 35,1, 35,1, 0,0, + 0,0, 0,0, 0,0, 65,1,427,1, 53,1, 35,1, 35,1, 35,1, 35,1, 35,1, 0,0, 67,1, 67,1, 0,0, 0,0, 0,0, 67,1, 0,0, 0,0, 67,1, 67,1, 0,0, 67,1, 67,1, 0,0, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 67,1, 0,0, 0,0, 35,2, 47,1, 0,0, 39,1, 40,1, 39,1, - 39,1, 35,2, 63,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1, - 266,1,266,1,266,1,266,1,266,1,342,1,340,1,338,1,261,1,261,1,261,1,261,1, - 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, - 266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1, - 266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1,266,1, - 266,1,266,1,266,1,266,1,266,1,265,1,342,1,340,1,338,1,261,1,261,1,261,1, - 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, - 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, - 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, - 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,260,1,260,1,260,1, - 260,1,259,1,259,1,258,1,258,1,258,1,257,1,257,1,257,1,257,1,257,1,257,1, - 257,1,257,1,257,1,257,1,257,1,257,1,257,1,265,1,264,1,263,1,262,1,261,1, - 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, - 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, - 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, - 261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1,261,1, - 261,1,261,1,261,1,260,1,260,1,260,1,260,1,259,1,259,1,258,1,258,1,258,1, - 257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1,257,1, - 257,1, 0,0, 32,1, 89,1, 30,1, 32,1, 33,1, 33,1, 35,2, 67,2, 67,2, 67,2, - 67,2, 67,2,435,1, 0,0, 67,2, 67,2, 67,2, 67,2,538,1,219,1,218,1, 6,1, - 6,1, 7,1, 15,1,538,1,492,1,219,1,218,1, 6,1,206,1,207,1, 0,0,207,1, - 207,1,207,1,207,1,207,1,207,1,207,1,207,1,207,1,206,1, 0,0, 0,0,207,1, - 207,1,207,1,207,1,207,1,207,1,207,1,207,1,207,1,207,1,207,1, 29,1, 0,0, - 29,1, 0,0,198,1, 29,1, 29,1, 29,1, 29,1, 25,1, 27,1, 24,1, 23,1, 28,1, + 39,1, 35,2, 63,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1, + 265,1,265,1,265,1,265,1,265,1,341,1,339,1,337,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1, + 265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1,265,1, + 265,1,265,1,265,1,265,1,265,1,264,1,341,1,339,1,337,1,260,1,260,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,259,1,259,1,259,1, + 259,1,258,1,258,1,257,1,257,1,257,1,256,1,256,1,256,1,256,1,256,1,256,1, + 256,1,256,1,256,1,256,1,256,1,256,1,256,1,264,1,263,1,262,1,261,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1,260,1, + 260,1,260,1,260,1,259,1,259,1,259,1,259,1,258,1,258,1,257,1,257,1,257,1, + 256,1,256,1,256,1,256,1,256,1,256,1,256,1,256,1,256,1,256,1,256,1,256,1, + 256,1, 0,0, 32,1, 89,1, 30,1, 32,1, 33,1, 33,1, 35,2, 67,2, 67,2, 67,2, + 67,2, 67,2,434,1, 0,0, 67,2, 67,2, 67,2, 67,2,538,1,218,1,217,1, 6,1, + 7,1, 15,1,538,1,491,1,218,1,217,1, 6,1,205,1,206,1, 0,0,206,1,206,1, + 206,1,206,1,206,1,206,1,206,1,206,1,206,1,205,1, 0,0, 0,0,206,1,206,1, + 206,1,206,1,206,1,206,1,206,1,206,1,206,1,206,1,206,1,197,1, 29,1, 0,0, + 29,1, 0,0,197,1, 29,1, 29,1, 29,1, 29,1, 25,1, 27,1, 24,1, 23,1, 28,1, 26,1, 26,1, 77,1, 77,1, 67,2, 67,2, 67,2, 0,0, 67,2, 0,0, 67,2, 0,0, - 67,2, 0,0, 67,2, 0,0, 67,2,436,1, 0,0, 67,2, 67,2, 0,0, 35,3, 0,0, + 67,2, 0,0, 67,2, 0,0, 67,2,435,1, 0,0, 67,2, 67,2, 0,0, 35,3, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, - 0,0, 39,2, 39,2, 0,0, 35,3, 33,1, 35,3, 63,2,342,2,340,2,338,2,265,2, - 264,2,263,2,262,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2, - 261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2, - 261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2, - 261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2,261,2, - 261,2,261,2,261,2,261,2,261,2,261,2,261,2,260,2,260,2,260,2,260,2,259,2, - 259,2,258,2,258,2,258,2,257,2,257,2,257,2,257,2,257,2,257,2,257,2,257,2, - 257,2,257,2,257,2,257,2,257,2, 89,2, 0,0, 0,0, 32,2, 0,0, 33,2, 0,0, + 0,0, 39,2, 39,2, 0,0, 35,3, 33,1, 35,3, 63,2,341,2,339,2,337,2,264,2, + 263,2,262,2,261,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2, + 260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2, + 260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2, + 260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2,260,2, + 260,2,260,2,260,2,260,2,260,2,260,2,260,2,259,2,259,2,259,2,259,2,258,2, + 258,2,257,2,257,2,257,2,256,2,256,2,256,2,256,2,256,2,256,2,256,2,256,2, + 256,2,256,2,256,2,256,2,256,2, 89,2, 0,0, 0,0, 32,2, 0,0, 33,2, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 33,2, 33,2, 0,0, 33,2, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 33,2, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 33,2, 0,0, 0,0, 33,2, 0,0, 0,0, 0,0, 0,0, 33,2, 33,2, 0,0, 0,0, 35,3, 67,3, 67,3, 67,3, - 67,3, 67,3, 67,3, 0,0, 67,3, 67,3, 6,2, 16,1, 15,2, 0,0, 0,0,207,2, - 207,2,207,2,207,2,207,2,207,2,207,2,207,2,207,2,207,2,207,2,198,2, 7,1, + 67,3, 67,3, 67,3, 0,0, 67,3, 67,3, 6,2, 16,1, 15,2, 0,0, 0,0,206,2, + 206,2,206,2,206,2,206,2,206,2,206,2,206,2,206,2,206,2,206,2,197,2, 7,1, 0,0, 25,2, 0,0, 25,2, 25,2, 25,2, 25,2, 27,2, 27,2, 0,0, 24,2, 0,0, 24,2, 0,0, 24,2, 0,0, 24,2, 0,0, 23,2, 23,2, 0,0, 28,2, 28,2, 0,0, 26,2, 26,2, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, - 0,0, 0,0, 67,3, 67,3, 67,3, 67,3, 67,3, 67,3, 67,3, 67,3,436,2, 67,3, + 0,0, 0,0, 67,3, 67,3, 67,3, 67,3, 67,3, 67,3, 67,3, 67,3,435,2, 67,3, 67,3, 0,0, 35,4, 35,4, 35,4, 35,4, 0,0, 35,4, 0,0, 35,4, 35,4, 22,1, - 63,3,254,1,254,1,254,1, 0,0, 0,0,264,3,263,3,262,3,251,1,251,1,257,3, - 0,0,485,1, 0,0, 0,0, 6,1,492,1, 32,3,485,1, 33,3, 33,3, 33,3,116,1, + 63,3,253,1,253,1,253,1, 0,0, 0,0,263,3,262,3,261,3,250,1,250,1,256,3, + 0,0,484,1, 0,0, 0,0, 6,1,491,1, 32,3,484,1, 33,3, 33,3, 33,3,116,1, 116,1,116,1, 0,0, 0,0, 90,1, 67,4, 67,4, 67,4, 67,4, 0,0, 0,0, 0,0, - 15,3,207,3,207,3,207,3,207,3,207,3,207,3,207,3,207,3,207,3,207,3,207,3, - 198,3, 25,3, 25,3, 25,3, 25,3, 25,3, 27,3, 27,3, 24,3, 24,3, 24,3, 24,3, + 15,3,206,3,206,3,206,3,206,3,206,3,206,3,206,3,206,3,206,3,206,3,206,3, + 197,3, 25,3, 25,3, 25,3, 25,3, 25,3, 27,3, 27,3, 24,3, 24,3, 24,3, 24,3, 23,3, 23,3, 28,3, 28,3, 26,3, 26,3, 67,4, 35,5, 35,5, 35,5, 35,5, 35,5, - 35,5, 63,4,264,4,263,4,262,4,257,4, 0,0, 0,0, 0,0, 32,1, 32,1,485,2, - 33,4, 0,0,116,2, 0,0, 0,0, 67,5, 67,5, 0,0, 0,0,207,4,207,4,207,4, - 207,4,207,4,207,4,207,4,207,4,207,4,207,4,207,4,198,4, 25,1, 25,1, 27,1, + 35,5, 63,4,263,4,262,4,261,4,256,4, 0,0, 0,0, 0,0, 32,1, 32,1,484,2, + 33,4, 0,0,116,2, 0,0, 0,0, 67,5, 67,5, 0,0, 0,0,206,4,206,4,206,4, + 206,4,206,4,206,4,206,4,206,4,206,4,206,4,206,4,197,4, 25,1, 25,1, 27,1, 27,1, 27,1, 27,1, 24,1, 24,1, 23,1, 23,1, 28,1, 28,1, 67,5, 35,6, 35,6, - 257,5, 15,3, 0,0, 33,5,116,3, 67,6,536,1, 0,0,207,5,257,6, 67,7,207,6 + 256,5, 15,3, 0,0, 33,5,116,3, 67,6,536,1, 0,0,206,5,256,6, 67,7,206,6 }; #ifndef MISSING_FORMAT diff --git a/src/a85parse.h b/src/a85parse.h index 91d43d4..3285823 100644 --- a/src/a85parse.h +++ b/src/a85parse.h @@ -1,5 +1,5 @@ -#ifndef A85PARSE_H_1359819567 -#define A85PARSE_H_1359819567 +#ifndef A85PARSE_H_1425877737 +#define A85PARSE_H_1425877737 typedef union { long alignment; @@ -29,24 +29,24 @@ typedef enum { a85parse_macro_token = 89, a85parse_macro_expansion_token, a85parse_expression_list_token = 92, a85parse_define_chars_token = 95, a85parse_cdseg_statement_start_token = 97, a85parse_name_list_token = 116, - a85parse_literal_alpha_token = 133, a85parse_digit_token = 138, - a85parse_asm_incl_char_token, a85parse_str_escape_char_token = 142, - a85parse_hex_digit_token = 156, a85parse_condition_start_token = 166, - a85parse_primary_exp_token = 198, a85parse_value_token = 206, - a85parse_function_token, a85parse_binary_integer_token = 218, - a85parse_octal_integer_token, a85parse_stack_register_token = 251, - a85parse_bd_register_token = 253, a85parse_page_register_token, - a85parse_eight_bit_reg_inst_token = 257, + a85parse_literal_alpha_token = 133, a85parse_digit_token = 137, + a85parse_asm_incl_char_token, a85parse_str_escape_char_token = 141, + a85parse_hex_digit_token = 155, a85parse_condition_start_token = 165, + a85parse_primary_exp_token = 197, a85parse_value_token = 205, + a85parse_function_token, a85parse_binary_integer_token = 217, + a85parse_octal_integer_token, a85parse_stack_register_token = 250, + a85parse_bd_register_token = 252, a85parse_page_register_token, + a85parse_eight_bit_reg_inst_token = 256, a85parse_sixteen_bit_reg_inst_token, a85parse_bd_reg_inst_token, a85parse_stack_reg_inst_token, a85parse_immediate_operand_inst_token, a85parse_lxi_inst_token, a85parse_mvi_inst_token, a85parse_spi_inst_token, a85parse_rst_inst_token, a85parse_no_arg_inst_token, - a85parse_lxi_inst_start_token = 338, a85parse_mvi_inst_start_token = 340, - a85parse_spi_inst_start_token = 342, a85parse_rst_arg_token = 345, - a85parse_label_token = 428, a85parse_literal_string_token = 435, + a85parse_lxi_inst_start_token = 337, a85parse_mvi_inst_start_token = 339, + a85parse_spi_inst_start_token = 341, a85parse_rst_arg_token = 344, + a85parse_label_token = 427, a85parse_literal_string_token = 434, a85parse_include_string_token, a85parse_asm_include_token, - a85parse_literal_name_nows_token = 442, - a85parse_singlequote_string_token = 485, a85parse_integer_token = 492, + a85parse_literal_name_nows_token = 441, + a85parse_singlequote_string_token = 484, a85parse_integer_token = 491, a85parse_literal_name_token = 536, a85parse_real_token = 538, a85parse_register_8_bit_token = 594, a85parse_register_16_bit_token = 608 } a85parse_token_type; diff --git a/src/a85parse.syn b/src/a85parse.syn index 766fa33..75a8d3a 100644 --- a/src/a85parse.syn +++ b/src/a85parse.syn @@ -37,7 +37,7 @@ eof = -1 + 0 hex digit = '0-9' + 'A-F' + 'a-f' newline = '\n' letter = 'a-z' + 'A-Z' + '_' -label char = '$' + '?' + '{' + '}' +label char = '?' + '{' + '}' string char = ~eof - ('"' + '\\' + '\n') rst arg = '0-7' asm incl char = 'a-z' + 'A-Z' + '0-9' + '_' + '.' + '\\' + '/' @@ -242,7 +242,7 @@ expression list */ name list - -> literal name nows = gNameList->Add(ss[ss_idx--]); + -> literal name nows = gNameList->Add(ss[ss_idx--]); -> name list, ",", WS?..., literal name nows = gNameList->Add(ss[ss_idx--]); literal name @@ -250,7 +250,7 @@ literal name literal name nows -> literal alpha - -> "$" = { strcpy(ss[++ss_idx], "$"); ss_len = 1; } +// -> "$" = { strcpy(ss[++ss_idx], "$"); ss_len = 1; printf("Added '$'\n"); } -> "&" = { strcpy(ss[++ss_idx], "&"); ss_len = 1; } literal alpha @@ -399,6 +399,7 @@ primary exp else { \ gEq->Add((VTObject *) gMacro); gMacro = new CMacro; \ } } + -> '$' = gEq->Add("$"); -> function -> '(', WS?..., equation, WS?..., ')' @@ -444,7 +445,7 @@ decimal integer -> '0-9':n = { int_len = 1; integer[0] = n; integer[1] = 0; } -> decimal integer, '0-9':n = { integer[int_len++] = n; integer[int_len] = 0; } -> decimal integer, '_' - -> decimal integer, '$' +// -> decimal integer, '$' hex integer -> '0', 'x' + 'X', hex digit:n = { int_len = 1; integer[0] = n; integer[1] = 0; } diff --git a/src/assemble.cpp b/src/assemble.cpp index dd72826..959efbd 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -850,7 +850,7 @@ int VTAssembler::Evaluate(class CRpnEquation* eq, double* value, } } else if (temp == "$") - stack[stk++] = m_Address; + stack[stk++] = m_ActiveSeg->m_Address; else // Genereate error indication { if (reportError) @@ -3416,7 +3416,7 @@ int VTAssembler::Assemble() unsigned char type; unsigned int address; double value; - char rel_mask; + char rel_mask, pcRel; int valid, extern_label, equation; POSITION pos; MString key, errSymbol; @@ -3444,6 +3444,7 @@ int VTAssembler::Assemble() m_Instructions = m_ActiveSeg->m_Instructions; m_ActiveAddr = m_ActiveSeg->m_UsedAddr; m_Address = 0; + m_ActiveSeg->m_Address = 0; // Get the initial module that was active during segment creation m_ActiveMod = m_ActiveSeg->m_InitialMod; @@ -3530,7 +3531,7 @@ int VTAssembler::Assemble() // Equation evaluated to a value. Check if it is // relative to a relocatable segment if (InvalidRelocation(pEq, rel_mask, - relSeg)) + relSeg, pcRel)) { valid = 0; equation = 1; @@ -3591,6 +3592,8 @@ int VTAssembler::Assemble() pRange = m_ActiveSeg->m_UsedAddr; if (relSeg != NULL) pRange = relSeg->m_UsedAddr; + if (pcRel) + pRel->m_pTargetRange = pRange; while ((pRange != 0) && (pRel->m_pTargetRange == 0)) { if ((pRange->address <= (unsigned int) value) && @@ -3852,7 +3855,7 @@ int VTAssembler::Assemble() { // Equation evaluated to a value. Check if it is // relative to a relocatable segment - if (InvalidRelocation(pExp->m_Equation, rel_mask, relSeg)) + if (InvalidRelocation(pExp->m_Equation, rel_mask, relSeg, pcRel)) { valid = 0; equation = 1; @@ -3928,6 +3931,8 @@ int VTAssembler::Assemble() pRange = m_ActiveSeg->m_UsedAddr; if (relSeg != NULL) pRange = relSeg->m_UsedAddr; + if (pcRel) + pRel->m_pTargetRange = pRange; while ((pRange != 0) && (pRel->m_pTargetRange == 0)) { if ((pRange->address <= (unsigned int) value) && @@ -4068,9 +4073,9 @@ int VTAssembler::Assemble() // increased m_Address if (pInst->m_Bytes != -1) pInst->m_Bytes = m_Address - address; - } - // Here we should check if m_Address == m_ActiveSeg->m_Address as validation + m_ActiveSeg->m_Address = m_Address; + } } // Check for errors during assembly @@ -4947,7 +4952,7 @@ more than one segment. ======================================================================== */ int VTAssembler::InvalidRelocation(CRpnEquation *pEq, char &rel_mask, - CSegment *&pSeg) + CSegment *&pSeg, char &pcRel) { int c, count, invalid, sameseg; char rel[3]; @@ -4957,6 +4962,7 @@ int VTAssembler::InvalidRelocation(CRpnEquation *pEq, char &rel_mask, // in more than just one segment, we will mark the equation invalid // for relocation. invalid = FALSE; + pcRel = FALSE; count = pEq->m_OperationArray.GetSize(); for (c = 0; c < 3; c++) rel[c] = 0; @@ -5012,6 +5018,21 @@ int VTAssembler::InvalidRelocation(CRpnEquation *pEq, char &rel_mask, } } } + else if (temp == "$") + { + rel[m_ActiveSeg->m_Type] = 1; + pcRel = TRUE; + if (pSeg == NULL) + pSeg = m_ActiveSeg; + else + { + if (pSeg != m_ActiveSeg) + { + invalid = TRUE; + sameseg = FALSE; + } + } + } else sameseg = FALSE; } diff --git a/src/assemble.h b/src/assemble.h index b61ee03..bf66624 100644 --- a/src/assemble.h +++ b/src/assemble.h @@ -540,7 +540,8 @@ class VTAssembler : public VTObject CSymbol* LookupSymOtherModules(MString& name, CSegment** pSeg = NULL); void ResetContent(void); int CreateObjFile(const char *filename, const char *sourcefile); - int InvalidRelocation(CRpnEquation* pEq, char &rel_mask, CSegment *&pSeg); + int InvalidRelocation(CRpnEquation* pEq, char &rel_mask, CSegment *&pSeg, + char &pcRel); int EquationIsExtern(CRpnEquation* pEq, int size); void MakeBinary(int val, int length, MString& binary); void CreateHex(MString& filename); diff --git a/src/disassemble.cpp b/src/disassemble.cpp index bd461b5..6bb1a1c 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -812,6 +812,8 @@ Disassembler Class Definition - empty constructor */ VTDis::~VTDis() { + delete m_pTd; + // Delete the find dialog if (m_pFindDlg != NULL) delete m_pFindDlg; diff --git a/src/flu_pixmaps.cpp b/src/flu_pixmaps.cpp index 2f568a6..4bb57c5 100644 --- a/src/flu_pixmaps.cpp +++ b/src/flu_pixmaps.cpp @@ -1627,3 +1627,1638 @@ const char * big_folder_up_xpm[] = { " .................. ", " ", " "}; + +const char * arrow_execute_xpm[] = { +"15 15 8 1", +" c None", +". c #000060", +"a c #000080", +"b c #0000A0", +"c c #0000C0", +"d c #2020E0", +"+ c #4040FF", +"s c #b0b0b0", +" ", +" ", +" ", +" ++ ", +" ++dd ", +" dddccc ", +" cccccccb ", +" cccccbbbb ", +" bbbbbbbass ", +" bbaaa.sss ", +" aaa.sss ", +" ..sss ", +" ss ", +" ", +" "}; + +/* XPM */ +const char * edit_undo_xpm[] = { +"16 16 90 1", +" c None", +". c #C5A101", +"+ c #C6A303", +"@ c #C7A404", +"# c #F2E279", +"$ c #C6A306", +"% c #CCAA12", +"& c #F8EEA2", +"* c #FDF9D8", +"= c #C5A307", +"- c #C6A202", +"; c #C7A403", +"> c #C8A504", +", c #D4B931", +"' c #FBF4BF", +") c #FAEF8F", +"! c #FDF8CA", +"~ c #FCF4B6", +"{ c #FBF3B5", +"] c #F0E079", +"^ c #DAC03F", +"/ c #DFC857", +"( c #FCF6C5", +"_ c #F8E865", +": c #F6E133", +"< c #F7E449", +"[ c #F7E445", +"} c #F7E341", +"| c #F7E54F", +"1 c #F8E969", +"2 c #FAEF92", +"3 c #F5E788", +"4 c #CFB022", +"5 c #D1B224", +"6 c #F9F0AB", +"7 c #F9EC7E", +"8 c #F5E030", +"9 c #F6E44C", +"0 c #F8E862", +"a c #F7E75A", +"b c #F6E340", +"c c #F5E02F", +"d c #F7E656", +"e c #F6E988", +"f c #CAA90F", +"g c #C9A80D", +"h c #F3E684", +"i c #F9EE8C", +"j c #FAF19F", +"k c #F5E888", +"l c #EDDB64", +"m c #EEDD69", +"n c #F6EA89", +"o c #F8E96F", +"p c #F4E02E", +"q c #F7E65A", +"r c #E6D155", +"s c #EDDA59", +"t c #F9EE97", +"u c #C4A000", +"v c #C7A402", +"w c #C7A405", +"x c #E0C949", +"y c #F6E66B", +"z c #F5DF33", +"A c #F1DF65", +"B c #C6A201", +"C c #E3CB32", +"D c #C5A100", +"E c #E1C948", +"F c #F5E244", +"G c #F5E463", +"H c #C5A102", +"I c #C6A301", +"J c #CBAB14", +"K c #F5E452", +"L c #EDDA4C", +"M c #CFAE0E", +"N c #F4E24B", +"O c #E3CA2F", +"P c #D8BC1B", +"Q c #F1DD39", +"R c #CAA809", +"S c #CEAD06", +"T c #EBD52B", +"U c #D5B711", +"V c #C6A300", +"W c #D6B603", +"X c #E0C305", +"Y c #CBA906", +" . ", +" +. ", +" @#$ ", +" %&*=-;> ", +" ,')!~{&]^- ", +" /(_:<[}|1234 ", +" 5678890abcdef ", +" ghijklmnopqr ", +" +stu vwxyzAv ", +" BCD EFGH ", +" ID JKLv ", +" u MNO ", +" PQR ", +" ISTU ", +" VWXY ", +" VD "}; + +/* XPM */ +const char * edit_paste_xpm[] = { +"16 16 71 1", +" c None", +". c #2E3436", +"+ c #8F5902", +"@ c #2D261A", +"# c #DBDBDB", +"$ c #E3E3E3", +"% c #D8D8D8", +"& c #3B2D17", +"* c #EFE0C7", +"= c #7B7970", +"- c #2C2D2C", +"; c #D9D8D7", +"> c #BFBCB3", +", c #DADAD8", +"' c #A29B8D", +") c #E9B96E", +"! c #EBE8DC", +"~ c #D6D3C8", +"{ c #CFCCC1", +"] c #CECBC1", +"^ c #EBE8DD", +"/ c #8B7652", +"( c #9C937F", +"_ c #888A85", +": c #FFFFFF", +"< c #CECFCA", +"[ c #CFD1CD", +"} c #D2D4CF", +"| c #D4D6D2", +"1 c #D7D9D5", +"2 c #D9DAD7", +"3 c #DBDDD9", +"4 c #D1D3CE", +"5 c #A0A29E", +"6 c #A1A4A0", +"7 c #A3A5A1", +"8 c #A5A6A3", +"9 c #A6A8A4", +"0 c #DFE1DE", +"a c #D5D7D2", +"b c #DADBD8", +"c c #DCDEDA", +"d c #DEDFDC", +"e c #E1E2DF", +"f c #E3E4E2", +"g c #A7A8A5", +"h c #A8A9A6", +"i c #A9ABA7", +"j c #ABACA9", +"k c #E7E8E6", +"l c #DDDEDB", +"m c #DFE1DD", +"n c #E2E3DF", +"o c #E4E5E2", +"p c #E6E7E5", +"q c #E9E9E7", +"r c #EBEBE9", +"s c #E0E2DE", +"t c #AAABA8", +"u c #ABACAA", +"v c #ADAEAB", +"w c #EAEBE8", +"x c #ECEDEB", +"y c #EFEFED", +"z c #E7E8E5", +"A c #E8EAE8", +"B c #EBECEA", +"C c #EEEFED", +"D c #F0F1EF", +"E c #F3F3F1", +"F c #888373", +" ... ", +" +++@#$%&+++ ", +"+**=-;>,-'**+ ", +"+*).!~{]^.)*+ ", +"+*)/...../)*+ ", +"+*)))(__________", +"+*)))_:::::::::_", +"+*)))_:<[}|123:_", +"+*)))_:4567890:_", +"+*)))_:a1bcdef:_", +"+*)))_:28ghijk:_", +"+*)))_:lmnopqr:_", +"+*)))_:stuvwxy:_", +"+*)))_:ozABCDE:_", +"+****_:::::::::_", +" ++++F__________"}; + +/* XPM */ +const char * edit_find_xpm[] = { +"16 16 81 1", +" c None", +". c #343A3C", +"+ c #2E3436", +"@ c #303638", +"# c #7F807C", +"$ c #575955", +"% c #33383B", +"& c #2F3537", +"* c #313839", +"= c #4B4F50", +"- c #999B98", +"; c #838482", +"> c #5C5F5E", +", c #787C7B", +"' c #CDCFCA", +") c #B3B5B1", +"! c #464B4C", +"~ c #363D3F", +"{ c #999C99", +"] c #7D7F7C", +"^ c #555753", +"/ c #585C5B", +"( c #4F5352", +"_ c #B8BBB4", +": c #9FA29C", +"< c #808280", +"[ c #32383A", +"} c #313739", +"| c #ABADAA", +"1 c #CCCEC9", +"2 c #A6A8A4", +"3 c #6F716D", +"4 c #888A85", +"5 c #747671", +"6 c #949791", +"7 c #828480", +"8 c #787A77", +"9 c #717371", +"0 c #959792", +"a c #6E706C", +"b c #6D706B", +"c c #727370", +"d c #B0B2AE", +"e c #5E6260", +"f c #535755", +"g c #6D6F6B", +"h c #303538", +"i c #A7A9A6", +"j c #C8CAC4", +"k c #A9ABA7", +"l c #868885", +"m c #4E5251", +"n c #303537", +"o c #727675", +"p c #A9ABA6", +"q c #868884", +"r c #666764", +"s c #2F3436", +"t c #525556", +"u c #999A96", +"v c #686A66", +"w c #555653", +"x c #313636", +"y c #34393C", +"z c #9C9F9C", +"A c #B7BAB4", +"B c #848782", +"C c #636562", +"D c #4D504E", +"E c #303637", +"F c #33393A", +"G c #DBDCDB", +"H c #CDCFCB", +"I c #A8ABA7", +"J c #80827F", +"K c #6F706D", +"L c #BEBFBD", +"M c #BFC0BC", +"N c #969895", +"O c #676966", +"P c #545653", +" ", +" .++@ .++@ ", +" +#$+ +#$+ ", +" %&++ @++* ", +" =-;>+&,')! ", +" @~{]^+/(+_:<[& ", +"}|123^+45+_6789&", +"+)_0a^+45+_6b^c+", +"+d_0a^+ef+_6b^g+", +"hijklgm&nojpqgrs", +" &+++++@ ++++++ ", +" tuvwx tuvwx ", +"yzABCDE yzABCDE", +"FGHIJKn FGHIJKn", +"[LMNOP@ [LMNOP@", +"+[}@&++ +[}@&++"}; + +/* XPM */ +const char * edit_cut_xpm[] = { +"16 16 78 1", +" c None", +". c #787878", +"+ c #F2F2F2", +"@ c #979797", +"# c #DFDFDF", +"$ c #E4E4E4", +"% c #9A9A9A", +"& c #FEFEFE", +"* c #969696", +"= c #E1E1E1", +"- c #DEDEDE", +"; c #646464", +"> c #858686", +", c #B1B1B1", +"' c #7F7F7F", +") c #A9A9A9", +"! c #636363", +"~ c #983939", +"{ c #963535", +"] c #C6C8C8", +"^ c #E8E9E9", +"/ c #8E8E8E", +"( c #8A8A8A", +"_ c #B2B2B2", +": c #C7C7C7", +"< c #D0D0D0", +"[ c #8C8C8C", +"} c #B34B4B", +"| c #943131", +"1 c #D41F1F", +"2 c #892121", +"3 c #9C5C5C", +"4 c #B8BDBD", +"5 c #ADAEAE", +"6 c #8E8D8D", +"7 c #BCBCBC", +"8 c #B8B8B8", +"9 c #989898", +"0 c #595959", +"a c #A75050", +"b c #BA5353", +"c c #7B0909", +"d c #F71616", +"e c #CE2727", +"f c #C29090", +"g c #B4CCCC", +"h c #878989", +"i c #737373", +"j c #737474", +"k c #B95454", +"l c #D86B6B", +"m c #BA1E1E", +"n c #DF0606", +"o c #7A6666", +"p c #F5ACAC", +"q c #745E5E", +"r c #D75757", +"s c #F04E4E", +"t c #B92222", +"u c #CE5050", +"v c #A62424", +"w c #D06969", +"x c #FF6868", +"y c #B01E1E", +"z c #B96363", +"A c #CE5F5F", +"B c #7B2828", +"C c #DD2525", +"D c #A60F0F", +"E c #F47E7E", +"F c #9C2424", +"G c #B51010", +"H c #DA5E5E", +"I c #E43F3F", +"J c #B81313", +"K c #C90F0F", +"L c #BC2727", +"M c #BC0C0C", +" . ", +" +@ ", +" #$ ", +" %&* ", +" =-; ", +" >+, ')!", +" ~{ ]^/(_:<[ ", +" }|12 34567890 ", +"ab cdefghij ", +"kl mn opq ", +" rst uv ", +" wxy ", +" zABCD ", +" E FG ", +" HIJK ", +" LM "}; + +/* XPM */ +const char * edit_copy_xpm[] = { +"16 16 6 1", +" c None", +". c #888A85", +"+ c #FFFFFF", +"@ c #BABDB6", +"# c #EEEEEC", +"$ c #BBBCB8", +".......... ", +".++++++++. ", +".+@@@@@@+. ", +".+######+. ", +".+@@@@@@+. ", +".+###$......... ", +".+@@@.++++++++. ", +".+###.+@@@@@@+. ", +".+@@@.+######+. ", +".++++.+@@@@@@+. ", +"......+######+. ", +" .+@@@@@@+. ", +" .+######+. ", +" .+@@@@##+. ", +" .++++++++. ", +" .......... "}; + + +/* XPM */ +const char * check_xpm[] = { +"16 16 79 1", +" c None", +". c #187612", +"+ c #115D0F", +"@ c #177810", +"# c #BDD7BA", +"$ c #5D9E56", +"% c #024D00", +"& c #177710", +"* c #B9D7B6", +"= c #5A9F52", +"- c #41993A", +"; c #519349", +"> c #014501", +", c #14770E", +"' c #B7DCB4", +") c #5AB251", +"! c #149E06", +"~ c #17950B", +"{ c #125310", +"] c #3A8F34", +"^ c #44923F", +"/ c #197F11", +"( c #B7E3B3", +"_ c #60C455", +": c #25B715", +"< c #20A313", +"[ c #054A02", +"} c #498F44", +"| c #BADDB5", +"1 c #AEDAA9", +"2 c #358F2F", +"3 c #1E8517", +"4 c #AAE2A5", +"5 c #6AD060", +"6 c #37C928", +"7 c #2FB022", +"8 c #054C03", +"9 c #075205", +"0 c #66B45D", +"a c #79D16F", +"b c #A3DF9D", +"c c #9FDF98", +"d c #288323", +"e c #257D20", +"f c #A0E599", +"g c #74DB69", +"h c #49D839", +"i c #3DC231", +"j c #065703", +"k c #084F07", +"l c #30A124", +"m c #5FD753", +"n c #91E488", +"o c #96E58E", +"p c #A5EA9F", +"q c #7CE771", +"r c #59E74A", +"s c #4CD63F", +"t c #0B6208", +"u c #024F01", +"v c #30B124", +"w c #5EE94F", +"x c #84EF78", +"y c #84F279", +"z c #67F558", +"A c #56E74A", +"B c #106C0D", +"C c #045401", +"D c #40BF36", +"E c #6FFE60", +"F c #78FF69", +"G c #65F058", +"H c #167212", +"I c #075804", +"J c #57CB4E", +"K c #81EE77", +"L c #227420", +"M c #0D5F0A", +"N c #23801F", +" ", +" ", +" .+ ", +" @#$% ", +" &*=-;>", +" ,')!~{ ", +" ]^ /(_:<[ ", +" }|12 345678 ", +"90abcdefghij ", +" klmnopqrst ", +" uvwxyzAB ", +" CDEFGH ", +" IJKL ", +" MN ", +" ", +" "}; + +/* XPM */ +const char * document_open_xpm[] = { +"16 16 107 2", +" c None", +". c #586B74", +"+ c #6E7E86", +"@ c #6D7D85", +"# c #6A7A82", +"$ c #64747C", +"% c #5D6D75", +"& c #586971", +"* c #A07002", +"= c #9C6C00", +"- c #7A7B66", +"; c #E2E2E2", +"> c #DFDFDF", +", c #DCDCDC", +"' c #D5D5D5", +") c #C2C2C2", +"! c #8B9397", +"~ c #738289", +"{ c #9B6C00", +"] c #E9AD1B", +"^ c #908D6E", +"/ c #E5E5E5", +"( c #A1AAAF", +"_ c #8A969C", +": c #89959B", +"< c #869298", +"[ c #6F7E86", +"} c #D8DBDC", +"| c #717D7F", +"1 c #8C680F", +"2 c #9C6D00", +"3 c #9F7001", +"4 c #E6AA1A", +"5 c #8F8C6E", +"6 c #E8E8E8", +"7 c #B9BEC1", +"8 c #97A0A5", +"9 c #8C969B", +"0 c #656E62", +"a c #DAA016", +"b c #9D6E01", +"c c #DDA318", +"d c #8E8B6F", +"e c #ECECEC", +"f c #A5AEB3", +"g c #8E9AA0", +"h c #8C989E", +"i c #8B979D", +"j c #A4ACAF", +"k c #C6C6C6", +"l c #7F7B5D", +"m c #DCA118", +"n c #D59C16", +"o c #8C896E", +"p c #EFEFEF", +"q c #E9E9E9", +"r c #E6E6E6", +"s c #E3E3E3", +"t c #E0E0E0", +"u c #DDDDDD", +"v c #DADADA", +"w c #827F62", +"x c #D39A15", +"y c #CD9413", +"z c #8B896F", +"A c #F2F2F2", +"B c #A9B2B7", +"C c #919DA3", +"D c #8F9BA1", +"E c #A8B0B3", +"F c #858266", +"G c #CB9313", +"H c #B07D09", +"I c #9A7927", +"J c #B4903C", +"K c #AE862C", +"L c #A87E1D", +"M c #A27610", +"N c #9D6F04", +"O c #9D6E03", +"P c #A0720A", +"Q c #A27611", +"R c #9D720E", +"S c #A57508", +"T c #9E6F03", +"U c #C09328", +"V c #CCA035", +"W c #D2A73C", +"X c #D7AC41", +"Y c #DCB146", +"Z c #E1B74C", +"` c #E6BC51", +" . c #E4B94E", +".. c #E1B64B", +"+. c #DEB348", +"@. c #D9AE43", +"#. c #9C6D01", +"$. c #E1B443", +"%. c #E0B342", +"&. c #DAAA34", +"*. c #DAAA33", +"=. c #D9A932", +"-. c #D5A122", +";. c #9E6E01", +">. c #C08A0A", +",. c #D2990F", +"'. c #C7900C", +" ", +" . + @ # $ % & ", +" * = - ; > , ' ) ! ~ ", +" { ] ^ / ( _ : < [ } | 1 2 3 ", +" { 4 5 6 / ; > , 7 8 9 0 a b ", +" { c d e f g h i : j k l m { ", +" { n o p e q r s t u v w x { ", +" { y z A B C D g h E u F G { ", +" { H I J K L M N O P Q R S T ", +" { U V W X Y Z ` ` ...+.@.#. ", +" { $.$.$.$.$.$.$.$.$.$.$.%.#. ", +" { &.&.&.&.&.&.&.&.&.&.*.=.{ ", +" { -.-.-.-.-.-.-.-.-.-.-.-.{ ", +" ;.>.,.,.,.,.,.,.,.,.,.,.'.b ", +" { 2 { { { { { { { { { { 2 2 ", +" "}; + +/* XPM */ +const char * document_save_xpm[] = { +"16 16 112 2", +" c None", +". c #4C4B4B", +"+ c #444344", +"@ c #B3B4B9", +"# c #B4B6B9", +"$ c #B4B6BB", +"% c #B6B8BC", +"& c #B7B9BC", +"* c #B8B9BC", +"= c #B9B9BC", +"- c #424041", +"; c #5A5959", +"> c #F1F4FA", +", c #F0F4FA", +"' c #F2F5FA", +") c #F3F6FB", +"! c #F5F8FC", +"~ c #F7F9FC", +"{ c #F9FBFD", +"] c #656364", +"^ c #403E3F", +"/ c #626061", +"( c #F9FAFD", +"_ c #9CB6CF", +": c #9DB6CF", +"< c #9DB7CF", +"[ c #9EB7D0", +"} c #9FB8D0", +"| c #FDFDFE", +"1 c #3D3C3D", +"2 c #5E5C5D", +"3 c #FBFCFD", +"4 c #F8F9FB", +"5 c #F9F9FB", +"6 c #F7F8FA", +"7 c #F5F7FA", +"8 c #F4F6F9", +"9 c #F2F4F8", +"0 c #F2F6F9", +"a c #3B3A3B", +"b c #5B595A", +"c c #EEF3F7", +"d c #EFF3F7", +"e c #EEF2F6", +"f c #EDF1F6", +"g c #EBF0F5", +"h c #E9EFF4", +"i c #E7EDF3", +"j c #393738", +"k c #575556", +"l c #E2EAF1", +"m c #8BA2B8", +"n c #8AA1B7", +"o c #8AA0B7", +"p c #89A0B6", +"q c #DCE5ED", +"r c #373536", +"s c #545253", +"t c #D4DEE8", +"u c #D0DDE8", +"v c #D0DCE7", +"w c #CFDCE7", +"x c #CFDBE7", +"y c #CEDBE6", +"z c #CDDAE6", +"A c #CFDAE6", +"B c #353333", +"C c #514E4F", +"D c #323031", +"E c #4D4A4B", +"F c #302D2E", +"G c #494546", +"H c #CDCDCD", +"I c #D6D6D6", +"J c #D6D5D5", +"K c #D5D5D5", +"L c #D3D3D3", +"M c #292627", +"N c #262324", +"O c #2B292A", +"P c #423F40", +"Q c #A7A7A7", +"R c #3F3C3D", +"S c #AEAEAE", +"T c #282727", +"U c #464344", +"V c #262425", +"W c #3B3839", +"X c #999999", +"Y c #343132", +"Z c #282526", +"` c #9F9F9F", +" . c #413E3F", +".. c #5A5758", +"+. c #242222", +"@. c #2D2A2A", +"#. c #353132", +"$. c #8B8A8B", +"%. c #2B2829", +"&. c #211F20", +"*. c #909090", +"=. c #363334", +"-. c #514D4E", +";. c #232021", +">. c #1F1D1D", +",. c #1E1B1C", +"'. c #757575", +"). c #787878", +"!. c #1B191A", +"~. c #1B1919", +"{. c #1F1C1D", +"]. c #211F1F", +" ", +" . + @ @ @ @ # $ % & * = + . ", +" - ; > , , , > ' ) ! ~ { ] - ", +" ^ / ( _ _ _ _ : < [ } | / ^ ", +" 1 2 3 4 5 4 4 6 7 8 9 0 2 1 ", +" a b c d d d c e f g h i b a ", +" j k l m m m m n n o p q k j ", +" r s t u u u v w x y z A s r ", +" B C C C C C C C C C C C C B ", +" D E E E E E E E E E E E E D ", +" F G G H I J K I I L M N G F ", +" O P P Q R B S S S S - T U O ", +" V W W X Y Z ` ` ` ` .V ..V ", +" +.@.#.$.%.&.*.*.*.*.=.&.-.;. ", +" >.,.'.).).).).).).!.~.{.]. ", +" "}; + +/* XPM */ +const char * toolbar_handle_xpm[] = { +"8 15 3 1", +" c None", +". c #FFFFFF", +"+ c #000000", +" ", +" ", +" ++++++ ", +" ", +" ++++++ ", +" ", +" ++++++ ", +" ", +" ++++++ ", +" ", +" ++++++ ", +" ", +" ++++++ ", +" ", +" "}; + +/* XPM */ +const char * document_new_xpm[] = { +"16 16 107 2", +" c None", +". c #DEDEDE", +"+ c #DDDDDD", +"@ c #E8E8E8", +"# c #FAFAFA", +"$ c #F2F2F2", +"% c #DEDFDF", +"& c #E7E7E7", +"* c #F9F9F9", +"= c #F9F8F8", +"- c #F4F4F4", +"; c #EAEAEA", +"> c #E2E2E2", +", c #E5E4E4", +"' c #F7F6F6", +") c #F6F6F6", +"! c #F3F2F2", +"~ c #E1E1E1", +"{ c #E6E6E6", +"] c #D1D1D1", +"^ c #E3E2E2", +"/ c #F5F4F4", +"( c #F4F3F3", +"_ c #E4E3E3", +": c #C5C5C5", +"< c #B6B6B6", +"[ c #B0B0B0", +"} c #E0DFDF", +"| c #F2F1F1", +"1 c #F1F0F0", +"2 c #F0F0F0", +"3 c #E6E5E6", +"4 c #DBDBDB", +"5 c #D3D2D2", +"6 c #DDDCDC", +"7 c #EEEDED", +"8 c #EDECEC", +"9 c #D9D9D9", +"0 c #EAE9E9", +"a c #E9E8E8", +"b c #EAE9EA", +"c c #EAE8EA", +"d c #EBE9EA", +"e c #DAD9D9", +"f c #D6D5D5", +"g c #E6E5E5", +"h c #DFE0DE", +"i c #A8BE9F", +"j c #9CB98F", +"k c #A6BD9D", +"l c #CDCFCC", +"m c #E2E1E1", +"n c #E1E0E0", +"o c #E4E2E3", +"p c #D5D8D5", +"q c #7EAE62", +"r c #74B441", +"s c #79AC5A", +"t c #C0C5C0", +"u c #CFCECE", +"v c #DEDDDD", +"w c #D8D9D7", +"x c #ACBFA5", +"y c #7DB955", +"z c #7BC63E", +"A c #77B54C", +"B c #88AA78", +"C c #CCCBCB", +"D c #CDD0CC", +"E c #7FAD64", +"F c #7DBF49", +"G c #80CF41", +"H c #7BD334", +"I c #6EC32A", +"J c #5EAC22", +"K c #509227", +"L c #C8C8C7", +"M c #D6D5D4", +"N c #CACDC9", +"O c #7AAA5E", +"P c #6DB833", +"Q c #68C61D", +"R c #63CC0F", +"S c #5CBD0F", +"T c #52A610", +"U c #498E1E", +"V c #C5C4C4", +"W c #D2D1D1", +"X c #D2D1D0", +"Y c #CDCDCB", +"Z c #A1B599", +"` c #8FAF7F", +" . c #62AE2D", +".. c #55B806", +"+. c #62AC2D", +"@. c #7FA36E", +"#. c #BBBAB9", +"$. c #C7C6C5", +"%. c #C9C7C8", +"&. c #BDBFBC", +"*. c #639E3D", +"=. c #4CA00A", +"-. c #629E3B", +";. c #ABB0AA", +">. c #457C30", +",. c #418520", +"'. c #457D2F", +" . + + + + + ", +" @ # # # # # # $ % ", +" & * = = = = * - ; > ", +" , ' ) ) ) ) ' ! ~ { ] ", +" ^ / ( ( ( ( ( ! _ : < [ ", +" } | 1 1 1 1 1 1 2 3 4 5 ", +" 6 7 8 8 8 8 8 8 8 8 7 6 ", +" 9 0 a a a a a a b c d e ", +" f g g g g g g h i j k l ", +" 5 m m m n m o p q r s t ", +" u v v v v w x j y z A B ", +" C e e e e D E F G H I J K ", +" L f M M f N O P Q R S T U ", +" V W X X X Y Z ` ...+.@. ", +" #.$.$.$.$.$.%.&.*.=.-.;. ", +" >.,.'. "}; + +/* XPM */ +const char * configure_xpm[] = { +"16 16 90 1", +" c None", +". c #707078", +"+ c #828289", +"@ c #727279", +"# c #B7B7C5", +"$ c #DDDDEF", +"% c #CBCBDE", +"& c #B7B7C4", +"* c #606064", +"= c #B0B0C0", +"- c #CCCCDE", +"; c #DADAE8", +"> c #C1C1CE", +", c #707077", +"' c #BABAC8", +") c #B4B4C0", +"! c #DCDCE8", +"~ c #E7E7F0", +"{ c #7D7D85", +"] c #7C7C85", +"^ c #DCDCEF", +"/ c #B2B2C0", +"( c #9999A2", +"_ c #EBEBF4", +": c #F1F1F8", +"< c #8E8E96", +"[ c #6A6A70", +"} c #C9C9DC", +"| c #CDCDDD", +"1 c #AFAFBD", +"2 c #95959F", +"3 c #D4D4DF", +"4 c #EFEFF3", +"5 c #F6F6FB", +"6 c #898992", +"7 c #AFAFBC", +"8 c #DADAE9", +"9 c #DDDDE9", +"0 c #EAEAF4", +"a c #EEEEF3", +"b c #F4F4F6", +"c c #E7E7EE", +"d c #DFDFE6", +"e c #6B6B6F", +"f c #4D4D52", +"g c #B8B8C7", +"h c #E5E5F1", +"i c #F1F1F9", +"j c #F4F4FB", +"k c #E5E5EC", +"l c #FFFFFF", +"m c #EDEDF2", +"n c #65656A", +"o c #6A6A72", +"p c #81818A", +"q c #7E7E87", +"r c #D6D6E0", +"s c #EBEBEF", +"t c #636367", +"u c #5B5B61", +"v c #E8E8EE", +"w c #EEEEF1", +"x c #606066", +"y c #54545A", +"z c #E6E6EB", +"A c #F6F6F8", +"B c #F6F6FA", +"C c #EFEFF2", +"D c #626266", +"E c #55555B", +"F c #E4E4EB", +"G c #EDEDF5", +"H c #E2E2EA", +"I c #F8F8FB", +"J c #5A5A5F", +"K c #4E4E54", +"L c #DCDCE9", +"M c #D8D8E1", +"N c #D9D9E4", +"O c #F7F7FC", +"P c #575759", +"Q c #525258", +"R c #DFDFEA", +"S c #E2E2EC", +"T c #D9D9E6", +"U c #D5D5DC", +"V c #3E3E41", +"W c #E7E7F2", +"X c #D0D0DA", +"Y c #47474C", +" .+@ ", +" #$%&* ", +" =-;> ", +",' )!~{ ", +"]^/ (_:< ", +"[}|123456 ", +" 7890abcde ", +" fghijkklmn ", +" opqrlllst ", +" uvlllwx ", +" yzlABCD ", +" EFGHIbJ ", +" KLGMNOP", +" QRSTUV", +" fWX ", +" Y "}; + +/* XPM */ +const char * wizard_xpm[] = { +"16 16 145 2", +" c None", +". c #C1C1C1", +"+ c #A09E9E", +"@ c #989697", +"# c #959394", +"$ c #999697", +"% c #999898", +"& c #858484", +"* c #4E4C4D", +"= c #959798", +"- c #B2B3B3", +"; c #939292", +"> c #817F7F", +", c #6F6C6C", +"' c #6B6A6A", +") c #686767", +"! c #666565", +"~ c #5F5E5E", +"{ c #636262", +"] c #8B8A8A", +"^ c #939293", +"/ c #5C5E5E", +"( c #4A4A4A", +"_ c #747272", +": c #5E5B5D", +"< c #595A5A", +"[ c #4E4F4E", +"} c #474846", +"| c #505151", +"1 c #828282", +"2 c #838484", +"3 c #626363", +"4 c #393A39", +"5 c #3A3B3A", +"6 c #4F4B4C", +"7 c #4E4B4C", +"8 c #656263", +"9 c #5E5B5C", +"0 c #807E7F", +"a c #5E5A5C", +"b c #4A4949", +"c c #343434", +"d c #454745", +"e c #7E7F7F", +"f c #797979", +"g c #454645", +"h c #2C2C2C", +"i c #2C2D2C", +"j c #313332", +"k c #3F3F3F", +"l c #4B494A", +"m c #514E4F", +"n c #464444", +"o c #343233", +"p c #585757", +"q c #6B6A6B", +"r c #E0E0E0", +"s c #AFAFAF", +"t c #333232", +"u c #302F2F", +"v c #323131", +"w c #353333", +"x c #3E3C3D", +"y c #524F50", +"z c #585758", +"A c #444343", +"B c #494647", +"C c #5B5B5A", +"D c #676565", +"E c #444142", +"F c #4A4647", +"G c #494645", +"H c #525051", +"I c #646263", +"J c #767374", +"K c #777778", +"L c #868788", +"M c #525252", +"N c #707070", +"O c #A8AAA9", +"P c #BEBEBE", +"Q c #C7C8C7", +"R c #C8C8C8", +"S c #D2D3D4", +"T c #C1C1C2", +"U c #797B7C", +"V c #333434", +"W c #313030", +"X c #2D2C2C", +"Y c #5B5A59", +"Z c #8A898A", +"` c #A1A3A4", +" . c #A0A0A1", +".. c #828183", +"+. c #403F40", +"@. c #2A2A2A", +"#. c #232323", +"$. c #313131", +"%. c #353535", +"&. c #535151", +"*. c #757475", +"=. c #939497", +"-. c #858587", +";. c #686567", +">. c #454445", +",. c #373737", +"'. c #2D2D2D", +"). c #303030", +"!. c #575555", +"~. c #7B797A", +"{. c #96989A", +"]. c #8A8A8C", +"^. c #6E6D6D", +"/. c #444444", +"(. c #2E2E2E", +"_. c #363636", +":. c #252525", +"<. c #343333", +"[. c #565454", +"}. c #7A797A", +"|. c #96979A", +"1. c #6D6C6C", +"2. c #464545", +"3. c #2B2B2B", +"4. c #282828", +"5. c #5A5A5A", +"6. c #222222", +"7. c #5D5B5B", +"8. c #7F7D7D", +"9. c #98999C", +"0. c #8C8C90", +"a. c #727172", +"b. c #504F4F", +"c. c #8B8B8B", +"d. c #444443", +"e. c #444242", +"f. c #5E5D5E", +"g. c #77787C", +"h. c #6B6C70", +"i. c #545253", +"j. c #403F3F", +"k. c #606060", +"l. c #BDBDBD", +"m. c #BDBDBE", +"n. c #BCBDBD", +" ", +" . ", +" + @ # $ % & * = - ", +" ; > , ' ) ! ~ { ] ^ / ( ", +" _ : < [ } | 1 2 3 4 5 6 7 8 9 ", +"0 a b c d e f g h i j k l m n o ", +"p 9 q r s t u v w x y z A ", +" B C D E F G H I J K L ", +" M N O P Q R S T U V ", +" W X Y Z ` ...+.@.#. ", +" $.%.&.*.=.-.;.>.,.'. ", +" ).).!.~.{.].^./.(._. ", +" ,.:.<.[.}.|.].1.2.3.4. ", +" 5.6.,.7.8.9.0.a.b.4.X ", +" c.d.e.f.g.h.i.j.k. ", +" l.m.n.. "}; + +/* XPM */ +const char * printer_xpm[] = { +"16 16 61 1", +" c None", +". c #888A85", +"+ c #FFFFFF", +"@ c #E7E8E5", +"# c #ECEDEB", +"$ c #8E908B", +"% c #F2F3F2", +"& c #B7B9B5", +"* c #F8F8F8", +"= c #606462", +"- c #454947", +"; c #8E8F8B", +"> c #F3F3F1", +", c #3C4140", +"' c #939796", +") c #8F9392", +"! c #939695", +"~ c #E5E6E2", +"{ c #33383A", +"] c #727676", +"^ c #5A5F5F", +"/ c #515656", +"( c #505555", +"_ c #535858", +": c #575C5C", +"< c #DDDFDA", +"[ c #454B4C", +"} c #2E3436", +"| c #D5D9D1", +"1 c #ACBF88", +"2 c #F5F6F5", +"3 c #B2B4B0", +"4 c #747875", +"5 c #6C706D", +"6 c #747775", +"7 c #4E514E", +"8 c #4B4E4B", +"9 c #5C615E", +"0 c #EBECEB", +"a c #F5F5F4", +"b c #F4F4F2", +"c c #F2F3F1", +"d c #F1F2F0", +"e c #F1F1EF", +"f c #F0F0EE", +"g c #EFF0ED", +"h c #EEEFEC", +"i c #E4E6E3", +"j c #3B4040", +"k c #494D4D", +"l c #EFEFED", +"m c #EDEEEB", +"n c #EBECE9", +"o c #E9EAE8", +"p c #E8E9E6", +"q c #E7E8E4", +"r c #E5E7E2", +"s c #E3E5E1", +"t c #E2E4DF", +"u c #E0E3DE", +"v c #363C3D", +" ", +" ...... ", +" .++++++. ", +" .+@@@@+. ", +" .+####+. ", +" $..+%%%%+..$ ", +" &*=--------=*& ", +";*>,'''))!'',>*;", +".+~{]^/(((_:{~+.", +".+<[}}}}}}}}[<+.", +".+|||||||||||1+.", +".23455555555632.", +"7890abcdefghi987", +" jklmnopqrstukj ", +" vvvvvvvvvvvv ", +" "}; + +/* XPM */ +const char * log_viewer_xpm[] = { +"16 16 106 2", +" c None", +". c #8C8E88", +"+ c #888A85", +"@ c #898B86", +"# c #8B8D87", +"$ c #8F908C", +"% c #B8BCB5", +"& c #F0F2EF", +"* c #FFFFFF", +"= c #FFFFFE", +"- c #D8DAD6", +"; c #8E908B", +"> c #D5D9D2", +", c #DBDFD9", +"' c #E2E3E2", +") c #9C9F9B", +"! c #C1C5BF", +"~ c #9FA39D", +"{ c #E1E2E1", +"] c #8F918C", +"^ c #FDFDFD", +"/ c #D9DDD6", +"( c #DBDFD8", +"_ c #FCFDFC", +": c #8A8C87", +"< c #92948F", +"[ c #E3E3E3", +"} c #A0A39E", +"| c #898989", +"1 c #2E3436", +"2 c #C6C9C3", +"3 c #A2A49F", +"4 c #E3E3E2", +"5 c #92938F", +"6 c #FBFBFA", +"7 c #888888", +"8 c #6C6C6C", +"9 c #DEE1DB", +"0 c #E0E3DD", +"a c #FAFBFA", +"b c #91938E", +"c c #D2D2D2", +"d c #E7E7E7", +"e c #CACCC8", +"f c #A5A6A3", +"g c #E0E1E0", +"h c #E3E5E0", +"i c #E4E6E2", +"j c #F8F9F8", +"k c #CFCFCF", +"l c #6F6F6F", +"m c #6B6B6B", +"n c #666666", +"o c #838383", +"p c #CED0CC", +"q c #A7A9A6", +"r c #DEDFDE", +"s c #CDCDCD", +"t c #818586", +"u c #5B5B5B", +"v c #848484", +"w c #E7E9E5", +"x c #E8EAE6", +"y c #F7F7F6", +"z c #C5C5C5", +"A c #D3D3D1", +"B c #ABACAA", +"C c #DDDEDD", +"D c #8A8D87", +"E c #CBCBCB", +"F c #EAEBE8", +"G c #E8E9E6", +"H c #E8E9E5", +"I c #E7E8E5", +"J c #F1F1F0", +"K c #8D8F88", +"L c #33383A", +"M c #CACACA", +"N c #BEC0BD", +"O c #AEB1AA", +"P c #AAADA7", +"Q c #A7AAA3", +"R c #A3A6A0", +"S c #A0A29C", +"T c #9C9F99", +"U c #999B96", +"V c #959892", +"W c #8B8D88", +"X c #F7F8F7", +"Y c #E7EAE6", +"Z c #F2F2F1", +"` c #F1F1F1", +" . c #F0F0F0", +".. c #E2E2E1", +"+. c #91938D", +"@. c #D6D8D5", +"#. c #C3C5C1", +"$. c #A7AAA4", +"%. c #D1D4CC", +"&. c #D0D4CC", +"*. c #D0D3CC", +"=. c #D0D3CB", +"-. c #AFB2AC", +";. c #8E8F8A", +">. c #8F908D", +",. c #8C8E89", +" . + + + @ # # @ + + + . ", +"$ % & * * * * * * * * = - ; ", +"@ > , ' ) ! ! ! ! ! ! ~ { # ", +"+ + ] ^ / / / / / / / ( _ : ", +" < [ } | 1 1 | 2 2 3 4 : ", +" 5 6 7 8 * * 8 7 9 0 a : ", +" b c 1 * d d * 1 e f g : ", +" b c 1 * d d * 1 h i j : ", +" b k l m * * n o p q r : ", +" s 1 t u 1 1 v w w x y : ", +" z 1 t 1 s A A A A A B C D ", +" 1 t 1 E F G G H w I G J K ", +" L 1 M N O P Q R S T U V < ; W ", +" : X Y R Z ` ` ` J . . ...: ", +" +.@.#.$.%.&.*.*.*.*.*.=.-.;.", +" >.,.+ + + + + + + + + W "}; + +/* XPM */ +const char * brick_add_xpm[] = { +"16 16 84 1", +" c None", +". c #D17676", +"+ c #C95E5E", +"@ c #CC6767", +"# c #F4E1E1", +"$ c #D07373", +"% c #E2A8A8", +"& c #F3DCDC", +"* c #E0A2A2", +"= c #E6B5B5", +"- c #CE6D6D", +"; c #DFA0A0", +"> c #CE6C6C", +", c #CF6F6F", +"' c #E1A6A6", +") c #DB9393", +"! c #D27979", +"~ c #CA6060", +"{ c #F3DBDB", +"] c #E2A9A9", +"^ c #DD9A9A", +"/ c #DE9C9C", +"( c #DD9898", +"_ c #D88A8A", +": c #D68585", +"< c #C65454", +"[ c #EFCFCF", +"} c #EAC1C1", +"| c #E4AFAF", +"1 c #E5B2B2", +"2 c #D88B8B", +"3 c #E3ACAC", +"4 c #D98C8C", +"5 c #D48181", +"6 c #DE9D9D", +"7 c #CD6A6A", +"8 c #EECDCD", +"9 c #EDC8C8", +"0 c #D78888", +"a c #C55252", +"b c #EECCCC", +"c c #ECC5C5", +"d c #E8BBBB", +"e c #D98E8E", +"f c #C44F4F", +"g c #CB6262", +"h c #F0D3D3", +"i c #EAC0C0", +"j c #E6B4B4", +"k c #E3AEAE", +"l c #B88075", +"m c #7F8758", +"n c #678C4F", +"o c #6B7943", +"p c #AF7364", +"q c #C34C4C", +"r c #E8BABA", +"s c #B47B6F", +"t c #81AB61", +"u c #B4D495", +"v c #D0E6BA", +"w c #8FBB6A", +"x c #578F2D", +"y c #814F3B", +"z c #EBC3C3", +"A c #6D7B45", +"B c #B1D390", +"C c #B1D692", +"D c #FFFFFF", +"E c #8CBC65", +"F c #8FBC67", +"G c #435F1C", +"H c #C75858", +"I c #4D7A31", +"J c #B6D49C", +"K c #B2D295", +"L c #386A19", +"M c #486221", +"N c #8BBA62", +"O c #87BA60", +"P c #87B960", +"Q c #C34E4E", +"R c #538C28", +"S c #8DBA64", +" .++. ", +" @####@ ", +" .++$%&&*$++. ", +" @###=-;;>=###@ ", +" ,'&&)!~~!)&{*, ", +"-]^/;-####-;(_:<", +">[}|123&&34%556<", +"7[89=)(;;($500/a", +"@[bc}d3]e5:240(f", +"gh[idjk%02lmnopq", +" :r8i|3%:stuvwxy", +" +_iz1%5ABCDEFG", +" Hezi(IJDDDKL", +" <^:MNODPFG", +" Q RSKSR ", +" GLG "}; + +/* XPM */ +const char * dollar_xpm[] = { +"16 16 69 1", +" c None", +". c #B1E47A", +"+ c #C5EE94", +"@ c #C8EE96", +"# c #AAE070", +"$ c #C5ED95", +"% c #C7EF97", +"& c #AEE276", +"* c #77E02A", +"= c #BBE886", +"- c #C2EB91", +"; c #C1EB8F", +"> c #C3ED91", +", c #B9E886", +"' c #AFE278", +") c #6BE11D", +"! c #C3EC92", +"~ c #BBEA88", +"{ c #A1DD67", +"] c #91D852", +"^ c #A4DF6B", +"/ c #B6E781", +"( c #B4E67E", +"_ c #90D94F", +": c #B7E783", +"< c #C6EE96", +"[ c #B0E478", +"} c #62DC18", +"| c #6DE11F", +"1 c #B3E57D", +"2 c #C4ED93", +"3 c #6CE21E", +"4 c #B6E682", +"5 c #C0EB8D", +"6 c #B5E77F", +"7 c #AFE377", +"8 c #A5DF6D", +"9 c #88DB45", +"0 c #87DB43", +"a c #A6DF6F", +"b c #ACE173", +"c c #A6E06E", +"d c #5BD113", +"e c #8ADA4A", +"f c #ACE377", +"g c #B0E379", +"h c #A1DC68", +"i c #B1E67E", +"j c #8AD94B", +"k c #93D757", +"l c #73E02A", +"m c #78DF2D", +"n c #A9E173", +"o c #A8E171", +"p c #61DA18", +"q c #7ADE30", +"r c #AEE47A", +"s c #A0DD69", +"t c #A9E276", +"u c #9ADA62", +"v c #83DB43", +"w c #B0E57D", +"x c #9FDD67", +"y c #69E022", +"z c #68E21E", +"A c #AAE175", +"B c #ABE276", +"C c #6BE123", +"D c #4BC60E", +" .. ", +" +@ ", +" #$%&* ", +" =-$;>,') ", +" '!~{]^/(_ ", +" :<[ }| ", +" 12:3 ", +" _456789 ", +" 0ab[:1c ", +" defg| ", +" ) hij ", +" k[bl mnop ", +" qoir8stnu ", +" v8(wxy ", +" zABC ", +" 9vD "}; diff --git a/src/ide.cpp b/src/ide.cpp index 96a7502..4a84b80 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -120,6 +120,7 @@ void cb_cut(Fl_Widget* w, void*); void cb_paste(Fl_Widget* w, void*); void cb_find(Fl_Widget* w, void*); void cb_find_next(Fl_Widget* w, void*); +void cb_find_prev(Fl_Widget* w, void*); void cb_replace(Fl_Widget* w, void*); void cb_prefs(Fl_Widget* w, void*); // Define project management routines @@ -129,6 +130,7 @@ void cb_clean_project(Fl_Widget* w, void*); void cb_project_settings(Fl_Widget* w, void*); void add_recent_file_to_menu(const char *filename); void add_recent_project_to_menu(const char *filename); +void cb_toolbar_find(Fl_Widget* w, void*); IMPLEMENT_DYNCREATE(VT_IdeGroup, VTObject); IMPLEMENT_DYNCREATE(VT_IdeSource, VTObject); @@ -173,6 +175,7 @@ Fl_Menu_Item gIde_menuitems[] = { { "&Paste", 'p', cb_paste, 0, FL_MENU_DIVIDER}, { "Find...", FL_CTRL + 'f', cb_find, 0, 0 }, { "Find Next", FL_F + 3, cb_find_next, 0, 0 }, + { "Find Prev", FL_SHIFT + FL_F + 3, cb_find_prev, 0, 0 }, { "Replace", FL_CTRL + 'r', cb_replace, 0, FL_MENU_DIVIDER }, { "Preferences", 0, cb_prefs, 0, 0 }, { 0 }, @@ -235,6 +238,9 @@ Fl_Menu_Item gRootMenu[] = { }; Fl_Pixmap gTextDoc( textdoc_xpm ), gComputer( computer_xpm ); +Fl_Pixmap gExecute( arrow_execute_xpm); +Fl_Pixmap gDollar ( dollar_xpm ); +Fl_Pixmap gAssemble( brick_add_xpm); /* ======================================================= @@ -758,6 +764,52 @@ void cb_find_next(Fl_Widget* w, void*) gpIde->FindNext(); } +/* +======================================================= +Callback routine for finding next text +======================================================= +*/ +void cb_find_prev(Fl_Widget* w, void*) +{ + if (gpIde != NULL) + gpIde->FindPrev(); +} + +/* +======================================================= +Callback routine for toolbar find item +======================================================= +*/ +void cb_toolbar_find(Fl_Widget* w, void*obj) +{ + int count, x; + Flu_Combo_List *pList = (Flu_Combo_List *) w; + const char* text = pList->value(); + + count = pList->list.size(); + for (x = 1; x <= count; x++) + { + const char *pItem = pList->list.text(x); + if (strcmp(text, pItem) == 0) + { + pList->list.move(1, x); + break; + } + } + if (x == count+1) + { + if (pList->list.size() >= 18) + pList->list.remove(18); + pList->list.add(text); + } + + if (gpIde != NULL) + { + gpIde->m_LastFind = LAST_FIND_TOOLBAR; + gpIde->ToolbarFind(pList); + } +} + /* ======================================================= Callback routine for replacing text @@ -1186,7 +1238,6 @@ void projtree_callback( Fl_Widget* w, void* ) break; case FLU_WIDGET_CALLBACK: - printf("Flu WIDGET callback\n"); break; break; @@ -1262,6 +1313,7 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) : Fl_Window(x, y, w, h, title) { int ideTreeWidth; + int h2; // Parent window has no box, only child regions box(FL_NO_BOX); @@ -1275,8 +1327,48 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) m->menu(gIde_menuitems); m->color(fl_rgb_color(240,239,228)); + Fl_Box* tbbox = new Fl_Box(0, MENU_HEIGHT-2, w, 28); + int dark = 30; + Fl_Color color = fl_rgb_color(220-dark,219-dark,208-dark); + tbbox->box(FL_FLAT_BOX); + tbbox->color(color); + + IDE_Toolbar * pToolbar = new IDE_Toolbar(0, MENU_HEIGHT-2, w, 28); + Fl_Pixmap* toolbar_handle = new Fl_Pixmap(toolbar_handle_xpm); + Fl_Pixmap* new_file = new Fl_Pixmap(document_new_xpm); + Fl_Pixmap* open_file = new Fl_Pixmap(document_open_xpm); + Fl_Pixmap* save_file = new Fl_Pixmap(document_save_xpm); + Fl_Pixmap* print_file = new Fl_Pixmap(printer_xpm); + + Fl_Pixmap* cut_icon = new Fl_Pixmap(edit_cut_xpm); + Fl_Pixmap* copy_icon = new Fl_Pixmap(edit_copy_xpm); + Fl_Pixmap* paste_icon = new Fl_Pixmap(edit_paste_xpm); + Fl_Pixmap* undo_icon = new Fl_Pixmap(edit_undo_xpm); + Fl_Pixmap* find_icon = new Fl_Pixmap(edit_find_xpm); + Fl_Pixmap* configure_icon = new Fl_Pixmap(configure_xpm); + Fl_Pixmap* wizard_icon = new Fl_Pixmap(wizard_xpm); + Fl_Pixmap* log_viewer_icon = new Fl_Pixmap(log_viewer_xpm); + + pToolbar->AddHandle(toolbar_handle, NULL, NULL); + pToolbar->AddButton("New", new_file, cb_new_file, NULL); + pToolbar->AddButton("Open", open_file, cb_open_file, NULL); + pToolbar->AddButton("Save", save_file, cb_save_file, NULL); + pToolbar->AddButton("Cut", cut_icon, cb_cut, NULL); + pToolbar->AddButton("Copy", copy_icon, cb_copy, NULL); + pToolbar->AddButton("Paste", paste_icon, cb_paste, NULL); + pToolbar->AddButton("Undo", undo_icon, cb_undo, NULL); + pToolbar->AddButton("Find", find_icon, cb_find, NULL); + pToolbar->AddComboList(m_pToolbarFind, 140); + m_pToolbarFind->callback(cb_toolbar_find, this); + //TODO: populate find list with recent searches + pToolbar->AddButton("New Project Wizard", wizard_icon, cb_new_project, NULL); + pToolbar->AddButton("Project Settings", configure_icon, cb_project_settings, NULL); + pToolbar->AddButton("Build", &gAssemble, cb_build_project, NULL); + // Create a tiled window to support Project, Edit, and debug regions - Fl_Tile* tile = new Fl_Tile(0,MENU_HEIGHT-2,w,h-MENU_HEIGHT-2); +// Fl_Tile* tile = new Fl_Tile(0,MENU_HEIGHT-2,w,h-MENU_HEIGHT-2); + Fl_Tile* tile = new Fl_Tile(0, MENU_HEIGHT-2+28, w, h - (MENU_HEIGHT-2+28)); +// h -= 28; virtualt_prefs.get("IdeTreeWidth", ideTreeWidth, 198); @@ -1285,12 +1377,13 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) Create region for Project tree ============================================ */ - m_ProjWindow = new Fl_Double_Window(0,MENU_HEIGHT-2,ideTreeWidth,h-75,""); + h2 = tile->h(); + m_ProjWindow = new Fl_Double_Window(0,MENU_HEIGHT-2+28,ideTreeWidth, h2-75,""); m_ProjWindow->box(FL_DOWN_BOX); m_ProjWindow->color(background_color); // Create Tree control - m_ProjTree = new Flu_Tree_Browser( 0, 0, ideTreeWidth, h-75 ); + m_ProjTree = new Flu_Tree_Browser( 0, 0, ideTreeWidth, m_ProjWindow->h() /*h-75*/ ); m_ProjTree->box( FL_DOWN_FRAME ); m_ProjTree->callback( projtree_callback ); m_ProjTree->selection_mode( FLU_SINGLE_SELECT ); @@ -1319,7 +1412,7 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) Create region and Child Window for editing files ================================================= */ - m_EditWindow = new Fl_Double_Window(ideTreeWidth,MENU_HEIGHT-2,w-(ideTreeWidth),h - 75,"Edit"); + m_EditWindow = new Fl_Double_Window(ideTreeWidth,MENU_HEIGHT-2+28,w-(ideTreeWidth),h2 - 75,"Edit"); m_EditWindow->box(FL_DOWN_BOX); m_TabNoBlinkBox = new Fl_Box(20, TAB_HEIGHT, m_EditWindow->w()-22, m_EditWindow->h() - TAB_HEIGHT-1); m_TabNoBlinkBox->box(FL_FLAT_BOX); @@ -1342,11 +1435,13 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) Create region for Debug and output tabs ================================================= */ - m_TabWindow = new Fl_Window(0,MENU_HEIGHT-2+h-75,w,75-MENU_HEIGHT+2,"Tab"); +// m_TabWindow = new Fl_Window(0,MENU_HEIGHT-2+h-75+28,w,75-MENU_HEIGHT+2,"Tab"); + m_TabWindow = new Fl_Window(0,h-75,w,75,"Tab"); m_TabWindow->box(FL_DOWN_BOX); // Create a tab control - m_Tabs = new Fl_Ide_Tabs(0, 1, w, 75-MENU_HEIGHT+3); +// m_Tabs = new Fl_Ide_Tabs(0, 1, w, 75-MENU_HEIGHT+3); + m_Tabs = new Fl_Ide_Tabs(0, 1, w, 75); m_Tabs->selection_color(fl_rgb_color(253, 252, 251)); /* @@ -1354,13 +1449,14 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) Create build tab ==================== */ - m_BuildTab = new Fl_Group(2, 0, w-3, 75-MENU_HEIGHT-22, " Build "); +// m_BuildTab = new Fl_Group(2, 0, w-3, 75-MENU_HEIGHT-22, " Build "); + m_BuildTab = new Fl_Group(2, 0, w-3, 75-22, " Build "); m_BuildTab->box(FL_DOWN_BOX); m_BuildTab->selection_color(FL_LIGHT2); m_BuildTab->color(background_color); // Create a Text Editor to show the disassembled text - m_BuildTextDisp = new My_Text_Display(0, 0, w-3, 75-MENU_HEIGHT-22); + m_BuildTextDisp = new My_Text_Display(0, 0, w-3, 75-22); m_BuildTextDisp->box(FL_DOWN_BOX); m_BuildTextDisp->textcolor(hl_plain); m_BuildTextDisp->color(background_color); @@ -1389,12 +1485,12 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) Create Debug tab ==================== */ - m_DebugTab = new Fl_Group(2, 0, w-3, 75-MENU_HEIGHT-22, " Debug "); + m_DebugTab = new Fl_Group(2, 0, w-3, 75-22, " Debug "); m_DebugTab->box(FL_DOWN_BOX); m_DebugTab->selection_color(FL_LIGHT2); m_DebugTab->color(background_color); - My_Text_Display* md = new My_Text_Display(0, 0, w-3, 75-MENU_HEIGHT-22); + My_Text_Display* md = new My_Text_Display(0, 0, w-3, 75-22); md->box(FL_DOWN_BOX); md->textcolor(hl_plain); md->color(background_color); @@ -1421,15 +1517,15 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) Create watch tab ==================== */ - m_WatchTab = new Fl_Group(2, 0, w-3, 75-MENU_HEIGHT-22, " Watch "); + m_WatchTab = new Fl_Group(2, 0, w-3, 75-22, " Watch "); m_WatchTab->box(FL_NO_BOX); m_WatchTab->selection_color(FL_LIGHT2); m_WatchTab->color(background_color); // Create tiled window for auto and watch variables - Fl_Tile* tile2 = new Fl_Tile(2, 0,w,75-MENU_HEIGHT-22); + Fl_Tile* tile2 = new Fl_Tile(2, 0,w,75-22); - Fl_Box* box0 = new Fl_Box(2, 0,w/2-2,75-MENU_HEIGHT-22,"1"); + Fl_Box* box0 = new Fl_Box(2, 0,w/2-2,75-22,"1"); box0->box(FL_DOWN_BOX); box0->color(background_color); box0->labelcolor(hl_plain); @@ -1438,7 +1534,7 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) // Create a text display for this pane - md = new My_Text_Display(0, 0, w-3, 75-MENU_HEIGHT-22); + md = new My_Text_Display(0, 0, w-3, 75-22); md->box(FL_DOWN_BOX); md->textcolor(hl_plain); md->color(background_color); @@ -1456,14 +1552,14 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) md->end(); - Fl_Box* box1 = new Fl_Box(w/2, 0,w/2,75-MENU_HEIGHT-22,"2"); + Fl_Box* box1 = new Fl_Box(w/2, 0,w/2,75-22,"2"); box1->box(FL_DOWN_BOX); box1->color(background_color); box1->labelcolor(hl_plain); box1->labelsize(36); box1->align(FL_ALIGN_CLIP); // Create a text display for this pane - md = new My_Text_Display(0, 0, w-3, 75-MENU_HEIGHT-22); + md = new My_Text_Display(0, 0, w-3, 75-22); md->box(FL_DOWN_BOX); md->textcolor(hl_plain); md->color(background_color); @@ -1483,7 +1579,7 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) box0->show(); box1->show(); - Fl_Box* r2 = new Fl_Box(0,0,w,75-MENU_HEIGHT-22); + Fl_Box* r2 = new Fl_Box(0,0,w,75-22); tile2->resizable(r2); tile2->end(); m_WatchTab->resizable(tile2); @@ -1519,7 +1615,7 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) virtualt_prefs.get("IdeTabheight", ideTabHeight, 75); // Reposition the tile separators to be a little bigger than the minimum - tile->position(ideTreeWidth,MENU_HEIGHT-2+h-75, ideTreeWidth,MENU_HEIGHT-2+h-(ideTabHeight)); + tile->position(ideTreeWidth,MENU_HEIGHT-2+h-75+28, ideTreeWidth,MENU_HEIGHT-2+h-(ideTabHeight)+28); SetColors(hl_plain, background_color); @@ -1892,6 +1988,7 @@ void VT_Ide::Find(void) m_pFindDlg->m_pFindDlg->show(); m_pFindDlg->m_pFind->take_focus(); m_pFindDlg->m_pFind->selectall(); + m_LastFind = LAST_FIND_DLG; } /* @@ -1913,12 +2010,147 @@ void VT_Ide::FindNext(void) m_pFindDlg->m_pErrorMsg->hide(); + if (m_LastFind == LAST_FIND_TOOLBAR) + { + } + else + { + // Ensure there is a search string + pFind = m_pFindDlg->m_pFind->value(); + if (pFind[0] == '\0' && m_Search == NULL) + { + m_pFindDlg->m_pFindDlg->show(); + m_pFindDlg->m_pFind->take_focus(); + return; + } + + // Find the text + m_Search = pFind; + } + + if (!mw->ForwardSearch(m_Search, m_pFindDlg->m_pMatchCase->value())) + { + // Save the current position and search from beginning of file + int pos = mw->insert_position(); + mw->insert_position(0); + if (!mw->ForwardSearch(m_Search, m_pFindDlg->m_pMatchCase->value())) + { + if (m_LastFind != LAST_FIND_TOOLBAR) + { + // If still not found, report not found + m_pFindDlg->m_ErrMsg.Format("Search string %s not found", pFind); + m_pFindDlg->m_pErrorMsg->label((const char *) m_pFindDlg->m_ErrMsg); + m_pFindDlg->m_pErrorMsg->show(); + + //fl_alert("Search string %s not found", pFind); + m_pFindDlg->m_pFindDlg->show(); + m_pFindDlg->m_pFind->take_focus(); + m_pFindDlg->m_pFind->selectall(); + return; + //mw->insert_position(pos); + } + } + } + + // Hide the dialog box + m_pFindDlg->m_pFindDlg->hide(); + Fl::check(); + if (m_LastFind == LAST_FIND_TOOLBAR) + m_pToolbarFind->take_focus(); + else + mw->take_focus(); +} + +/* +============================================================= +FindAgain routine handles the Edit->Find Next menu item. +The routine identifies the active window and calls the Fl +cut routine. +============================================================= +*/ +void VT_Ide::FindPrev(void) +{ + Fl_Multi_Edit_Window* mw; + const char * pFind; + + // First get a pointer to the active (topmost) window + mw = (Fl_Multi_Edit_Window*) m_EditTabs->value(); + if (mw == NULL) + return; + + m_pFindDlg->m_pErrorMsg->hide(); + + if (m_LastFind == LAST_FIND_TOOLBAR) + { + } + else + { + // Ensure there is a search string + pFind = m_pFindDlg->m_pFind->value(); + if (pFind[0] == '\0' && m_Search == NULL) + { + m_pFindDlg->m_pFindDlg->show(); + m_pFindDlg->m_pFind->take_focus(); + return; + } + + // Find the text + m_Search = pFind; + } + + if (!mw->BackwardSearch(m_Search, m_pFindDlg->m_pMatchCase->value())) + { + // Save the current position and search from beginning of file + int pos = mw->insert_position(); + mw->insert_position(99999999); + if (!mw->BackwardSearch(m_Search, m_pFindDlg->m_pMatchCase->value())) + { + if (m_LastFind != LAST_FIND_TOOLBAR) + { + // If still not found, report not found + m_pFindDlg->m_ErrMsg.Format("Search string %s not found", pFind); + m_pFindDlg->m_pErrorMsg->label((const char *) m_pFindDlg->m_ErrMsg); + m_pFindDlg->m_pErrorMsg->show(); + + //fl_alert("Search string %s not found", pFind); + m_pFindDlg->m_pFindDlg->show(); + m_pFindDlg->m_pFind->take_focus(); + m_pFindDlg->m_pFind->selectall(); + return; + //mw->insert_position(pos); + } + } + } + + // Hide the dialog box + m_pFindDlg->m_pFindDlg->hide(); + if (m_LastFind == LAST_FIND_TOOLBAR) + m_pToolbarFind->take_focus(); + else + mw->take_focus(); +} + +/* +============================================================= +FindAgain routine handles the Edit->Find Next menu item. +The routine identifies the active window and calls the Fl +cut routine. +============================================================= +*/ +void VT_Ide::ToolbarFind(Flu_Combo_List *pList) +{ + Fl_Multi_Edit_Window* mw; + const char * pFind; + + // First get a pointer to the active (topmost) window + mw = (Fl_Multi_Edit_Window*) m_EditTabs->value(); + if (mw == NULL) + return; + // Ensure there is a search string - pFind = m_pFindDlg->m_pFind->value(); + pFind = pList->value(); if (pFind[0] == '\0') { - m_pFindDlg->m_pFindDlg->show(); - m_pFindDlg->m_pFind->take_focus(); return; } @@ -1931,23 +2163,12 @@ void VT_Ide::FindNext(void) mw->insert_position(0); if (!mw->ForwardSearch(pFind, m_pFindDlg->m_pMatchCase->value())) { - // If still not found, report not found - m_pFindDlg->m_ErrMsg.Format("Search string %s not found", pFind); - m_pFindDlg->m_pErrorMsg->label((const char *) m_pFindDlg->m_ErrMsg); - m_pFindDlg->m_pErrorMsg->show(); - - //fl_alert("Search string %s not found", pFind); - m_pFindDlg->m_pFindDlg->show(); - m_pFindDlg->m_pFind->take_focus(); - m_pFindDlg->m_pFind->selectall(); return; - //mw->insert_position(pos); } } // Hide the dialog box - m_pFindDlg->m_pFindDlg->hide(); - mw->take_focus(); + m_pToolbarFind->take_focus(); } /* @@ -4111,11 +4332,6 @@ VT_ReplaceDlg::VT_ReplaceDlg(class VT_Ide* pParent) m_pParent = pParent; } -void cb_find_edit(Fl_Widget* w, void *opaque) -{ - printf("Edit callback\n"); -} - /* ================================================================================ VT_FindDlg routines below. diff --git a/src/ide.h b/src/ide.h index 72441bd..1d52a68 100644 --- a/src/ide.h +++ b/src/ide.h @@ -55,6 +55,9 @@ void cb_Ide(Fl_Widget* w, void*) ; #define MENU_HEIGHT 32 #endif +#define LAST_FIND_DLG 1 +#define LAST_FIND_TOOLBAR 2 + class VTAssembler; class VT_IdeSource : public VTObject @@ -122,6 +125,48 @@ class VT_FindDlg char search[256]; }; +class IDE_Toolbar : public Fl_Pack { +public: + // CTOR + IDE_Toolbar(int X,int Y,int W,int H):Fl_Pack(X,Y,W,H) + { + type(Fl_Pack::HORIZONTAL); // horizontal packing of buttons + box(FL_UP_FRAME); + spacing(4); // spacing between buttons + end(); + } + // ADD A TOOLBAR BUTTON TO THE PACK + void AddButton(const char *name, Fl_Pixmap *img=0, Fl_Callback *cb=0, void *data=0) + { + begin(); + Fl_Button *b = new Fl_Button(0,0,24,24); + b->box(FL_FLAT_BOX); // buttons won't have 'edges' + b->clear_visible_focus(); + if ( name ) b->tooltip(name); + if ( img ) b->image(img); + if ( cb ) b->callback(cb,data); + end(); + } + // ADD A TOOLBAR BUTTON TO THE PACK + void AddHandle(Fl_Pixmap *img=0, Fl_Callback *cb=0, void *data=0) + { + begin(); + Fl_Button *b = new Fl_Button(0,0,8,8); + b->box(FL_FLAT_BOX); // buttons won't have 'edges' + b->clear_visible_focus(); + if ( img ) b->image(img); + if ( cb ) b->callback(cb,data); + end(); + } + void AddComboList(Flu_Combo_List *&box, int width, Fl_Callback *cb=0, void *data=0) { + begin(); + box = new Flu_Combo_List(0, 2, width, 20); + box->clear_visible_focus(); + if ( cb ) box->callback(cb,data); + end(); + } +}; + class VT_Ide : public Fl_Window { public: @@ -154,6 +199,8 @@ class VT_Ide : public Fl_Window void Undo(void); void Find(void); void FindNext(void); + void FindPrev(void); + void ToolbarFind(Flu_Combo_List *pList); void Replace(void); void ReplaceAll(void); void ReplaceNext(void); @@ -187,6 +234,8 @@ class VT_Ide : public Fl_Window Fl_Box* m_TabNoBlinkBox; VT_ReplaceDlg* m_pReplaceDlg; VT_FindDlg* m_pFindDlg; + int m_LastFind; + Flu_Combo_List *m_pToolbarFind; protected: virtual void draw(); diff --git a/src/linker.cpp b/src/linker.cpp index 55e9e67..76b0f26 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -121,12 +121,14 @@ CLinkRgn::~CLinkRgn() CObjFile::~CObjFile() { - int count, c; + int count, c; + CObjFileSection *pSect; count = m_FileSections.GetSize(); for (c = 0; c < count; c++) { - delete (CObjFileSection *) m_FileSections[c]; + pSect = (CObjFileSection *) m_FileSections[c]; + delete pSect; } m_FileSections.RemoveAll(); } @@ -158,6 +160,7 @@ CObjFileSection::~CObjFileSection() // Delete program bytes pointer if not NULL if (m_pProgBytes != NULL) delete m_pProgBytes; + m_pProgBytes = NULL; } /* @@ -3118,7 +3121,7 @@ CObjFileSection* VTLinker::FindRelSection(CObjFile* pObjFile, Elf32_Rel* pRel) { // Loop through relocation segments pFileSect = (CObjFileSection *) pObjFile->m_FileSections[sect]; - if (pFileSect->m_ElfHeader.sh_offset < pRel->r_offset) + if (pFileSect->m_ElfHeader.sh_offset <= pRel->r_offset) { // Validate the section type type = ELF32_R_TYPE(pRel->r_info); @@ -3126,6 +3129,9 @@ CObjFileSection* VTLinker::FindRelSection(CObjFile* pObjFile, Elf32_Rel* pRel) (pFileSect->m_ElfHeader.sh_type != SHT_PROGBITS)) continue; + if (pFileSect->m_ElfHeader.sh_offset + pFileSect->m_ElfHeader.sh_size <= pRel->r_offset) + continue; + // If no rel section assigned yet, just assign it if (pRelSect == NULL) pRelSect = pFileSect; diff --git a/src/multieditwin.cpp b/src/multieditwin.cpp index f5bf249..da6157e 100644 --- a/src/multieditwin.cpp +++ b/src/multieditwin.cpp @@ -463,6 +463,23 @@ int Fl_Multi_Edit_Window::ForwardSearch(const char *pFind, int caseSensitive) int pos = insert_position(); int found = m_tb->search_forward(pos, pFind, &pos, caseSensitive); if (found) + { + take_focus(); + insert_position(pos+strlen(pFind)); + show_insert_position(); + m_tb->select(pos, pos+strlen(pFind)); + } + else + return FALSE; + + return TRUE; +} + +int Fl_Multi_Edit_Window::BackwardSearch(const char *pFind, int caseSensitive) +{ + int pos = insert_position()-1; + int found = m_tb->search_backward(pos, pFind, &pos, caseSensitive); + if (found) { insert_position(pos+strlen(pFind)); show_insert_position(); diff --git a/src/multieditwin.h b/src/multieditwin.h index 45c5a11..760ac93 100644 --- a/src/multieditwin.h +++ b/src/multieditwin.h @@ -64,6 +64,7 @@ class Fl_Multi_Edit_Window : public My_Text_Editor, public VTObject void DisableHl(void); void EnableHl(void); int ForwardSearch(const char *pFind, int caseSensitive = TRUE); + int BackwardSearch(const char *pFind, int caseSensitive = TRUE); virtual void show(void) { My_Text_Editor::show(); Fl_Widget::show(); } virtual void buffer(My_Text_Buffer* buf); void tab_distance(int); From 1effe012cfda4b5c9088b34c1ab3d00a24c77e8b Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Mon, 6 Apr 2015 21:15:05 +0000 Subject: [PATCH 282/327] Updates for Toolabar quick find and #ifdef processing. --- src/MString.cpp | 11 +++++++---- src/My_Text_Display.cpp | 7 ++++--- src/assemble.cpp | 19 ++++++++++++++++--- src/disassemble.cpp | 6 ++++++ src/ide.cpp | 7 ++----- src/idetabs.cpp | 1 + 6 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/MString.cpp b/src/MString.cpp index 0887126..8d73242 100644 --- a/src/MString.cpp +++ b/src/MString.cpp @@ -20,6 +20,9 @@ ----- $Log$ + Revision 1.5 2015/04/06 21:15:05 kpettit1 + Updates for Toolabar quick find and #ifdef processing. + Revision 1.4 2015/03/03 01:51:44 kpettit1 *** empty log message *** @@ -159,7 +162,7 @@ void MString::deallocate(MNode* p) tmp = NULL; } if (pcStr) { - delete pcStr; + delete[] pcStr; pcStr = NULL; bModified = true; // iBufferInUse = 0; @@ -265,7 +268,7 @@ MString::~MString() { tailMNode = NULL; if (pcStr) { - delete pcStr; + delete[] pcStr; pcStr = NULL; } } @@ -1945,7 +1948,7 @@ void MString::Format( const char * sFormat, ...) vsnprintf(s, 2000, sFormat, arglist); va_end(arglist); *this = s; - delete s; + delete[] s; s = NULL; } // End additions by Bruce Riggins 11/14/00 @@ -2189,7 +2192,7 @@ char * MString::GetBuffer(int nMinBufLength) { { if (pcStr) { // if buffer is in existence already, simply delete it and start over - delete pcStr; + delete[] pcStr; pcStr = NULL; } diff --git a/src/My_Text_Display.cpp b/src/My_Text_Display.cpp index 4299204..b16a903 100644 --- a/src/My_Text_Display.cpp +++ b/src/My_Text_Display.cpp @@ -855,7 +855,7 @@ int My_Text_Display::position_to_xy( int pos, int* X, int* Y ) { outIndex += charLen; } *X = xStep; - delete [] (char *)lineStr; + free((void *) lineStr); return 1; } @@ -1546,6 +1546,7 @@ void My_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip, draw parts whenever the style changes (also note if the cursor is on this line, and where it should be drawn to take advantage of the x position which we've gone to so much trouble to calculate) */ + outStr[0] = '\0'; outPtr = outStr; outIndex = outStartIndex; X = startX; @@ -1898,7 +1899,7 @@ int My_Text_Display::xy_to_position( int X, int Y, int posType ) { charStyle = position_style( lineStart, lineLen, charIndex, outIndex ); charWidth = string_width( expandedChar, charLen, charStyle ); if ( X < xStep + ( posType == CURSOR_POS ? charWidth / 2 : charWidth ) ) { - delete [] (char *)lineStr; + free((char *)lineStr); return lineStart + charIndex; } xStep += charWidth; @@ -1907,7 +1908,7 @@ int My_Text_Display::xy_to_position( int X, int Y, int posType ) { /* If the X position was beyond the end of the line, return the position of the newline at the end of the line */ - delete [] (char *)lineStr; + free((char *)lineStr); return lineStart + lineLen; } diff --git a/src/assemble.cpp b/src/assemble.cpp index 959efbd..fe6bacb 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -2115,10 +2115,13 @@ This function searches for the specified symbol in the active module */ int VTAssembler::LookupSymbol(MString& name, CSymbol *&symbol) { + CMacro pMacro; // Test if the specified label / define exists if (m_ActiveMod->m_Symbols->Lookup(name, (VTObject*&) symbol)) + { return TRUE; + } // Symbol not found in active module. Check other modules if (name.GetLength() > 1) @@ -2929,6 +2932,7 @@ void VTAssembler::preproc_ifdef(const char* name, int negate) { MString err, strName; CSymbol* dummy; + CMacro* pMacro; int defined; // Update line number @@ -2961,9 +2965,18 @@ void VTAssembler::preproc_ifdef(const char* name, int negate) { m_IfStat[m_IfDepth] = IF_STAT_DONT_ASSEMBLE; strName = name; - defined = LookupSymbol(strName, dummy); - if ((defined && !negate) || (!defined && negate)) - m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + // Test if it is a CMacro + if (LookupMacro(strName, pMacro)) + { + if (!negate) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + } + else + { + defined = LookupSymbol(strName, dummy); + if ((defined && !negate) || (!defined && negate)) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + } } } diff --git a/src/disassemble.cpp b/src/disassemble.cpp index 6bb1a1c..b3f17e9 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -814,6 +814,12 @@ VTDis::~VTDis() { delete m_pTd; + if (m_pTextViewer != NULL) + { + delete m_pTextViewer->buffer(); + delete m_pTextViewer; + } + // Delete the find dialog if (m_pFindDlg != NULL) delete m_pFindDlg; diff --git a/src/ide.cpp b/src/ide.cpp index 4a84b80..fd2b248 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -2008,6 +2008,7 @@ void VT_Ide::FindNext(void) if (mw == NULL) return; + Fl::focus(mw); m_pFindDlg->m_pErrorMsg->hide(); if (m_LastFind == LAST_FIND_TOOLBAR) @@ -2054,11 +2055,7 @@ void VT_Ide::FindNext(void) // Hide the dialog box m_pFindDlg->m_pFindDlg->hide(); - Fl::check(); - if (m_LastFind == LAST_FIND_TOOLBAR) - m_pToolbarFind->take_focus(); - else - mw->take_focus(); + //mw->take_focus(); } /* diff --git a/src/idetabs.cpp b/src/idetabs.cpp index 4e12427..6563436 100644 --- a/src/idetabs.cpp +++ b/src/idetabs.cpp @@ -109,6 +109,7 @@ void cb_idetabs(Fl_Widget* w, void *args) Fl_Ide_Tabs::Fl_Ide_Tabs(int x, int y, int w, int h, const char* title) : Fl_Group(x, y, w, h, title) { + m_prevInMoveRect = FALSE; m_prevInRect = FALSE; m_pushInRect = FALSE; m_hasCloseButton = 0; From 865fb355aa09e27fdd622c2a7e971c968856d2ed Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 7 Apr 2015 20:37:50 +0000 Subject: [PATCH 283/327] Added support for NUM lock. --- src/display.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/display.cpp b/src/display.cpp index ffc3444..da2b105 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -196,7 +196,7 @@ const char *gSpKeyText[] = { "CTRL", "GRAPH", "CODE", - "", + "NUM", "CAPS", "", "PAUSE", @@ -3738,6 +3738,9 @@ int T100_Disp::handle(int event) case FL_F+11: gSpecialKeys |= MT_PASTE; break; + case FL_Num_Lock: + gSpecialKeys |= MT_NUM; + break; default: key &= 0x7F; // key=(unsigned int)Fl::event_text(); @@ -4163,6 +4166,9 @@ int T100_Disp::handle(int event) case FL_F+11: gSpecialKeys &= ~MT_PASTE; break; + case FL_Num_Lock: + gSpecialKeys &= ~MT_NUM; + break; default: key &= 0x7F; gKeyStates[key] = 1; From 4ae9db7c9e3fc23cdf68b597fc4fc50c2f138f33 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 7 Apr 2015 20:38:51 +0000 Subject: [PATCH 284/327] Updated release notes. --- release.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/release.txt b/release.txt index 5bf892d..d5aafb6 100644 --- a/release.txt +++ b/release.txt @@ -6,7 +6,7 @@ VirtualT Release.txt This file lists the changes and additions for each of the versions of VirtualT since v0.3 ===================== -v1.7 Not released yet +v1.7 4/7/2014 ===================== 1. Fixed bug with deleting a .CO file where the deletion length wasn't including @@ -59,6 +59,7 @@ v1.7 Not released yet ability to display link messages using "echo" for displaying things like program sizes and addresses, etc. +17. Added support for NUM lock key so T200 Calculator will work. ==================== v1.6 April 24, 2014 From 715da5af8fd72104465394b47cd658b799554160 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Fri, 13 Mar 2020 05:43:34 -0400 Subject: [PATCH 285/327] gettimeofday() is declared in sys/time.h --- src/io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io.c b/src/io.c index 91f5ccb..aa91ba6 100644 --- a/src/io.c +++ b/src/io.c @@ -29,7 +29,7 @@ #include -#ifdef __APPLE__ +#ifndef _WIN32 #include #endif #include From 8b9bb5e4a7da53133e6ca93571256593fcc76e17 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Fri, 13 Mar 2020 05:44:04 -0400 Subject: [PATCH 286/327] Silence Clang warning --- src/intelhex.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/intelhex.c b/src/intelhex.c index f8476bd..d4661fe 100644 --- a/src/intelhex.c +++ b/src/intelhex.c @@ -155,7 +155,8 @@ int load_hex_file(char *filename, char *buffer, unsigned short *start_addr) *start_addr = minaddr; return n; } - if (status == 2) ; /* begin of file */ + if (status == 2) + ; /* begin of file */ } else { fclose(fin); return 0; From f1e049fb95a4128da8ab7fbcb2935de0b56aa2ff Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Fri, 13 Mar 2020 05:45:33 -0400 Subject: [PATCH 287/327] Fix pointer initialization. --- src/Flu_DND.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Flu_DND.cpp b/src/Flu_DND.cpp index 316f53f..34b5cf2 100644 --- a/src/Flu_DND.cpp +++ b/src/Flu_DND.cpp @@ -37,7 +37,7 @@ Flu_DND_Event :: ~Flu_DND_Event() void Flu_DND_Event :: clear() { // reset everything - objUnderMouse = false; + objUnderMouse = NULL; dragging = false; exit = false; if(_text) free(_text); _text = 0; From 738f3bfba8d1fa51cbae2534d564c0fce4e45dc2 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Fri, 13 Mar 2020 05:47:16 -0400 Subject: [PATCH 288/327] Add space required by C++11 --- src/display.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/display.cpp b/src/display.cpp index da2b105..150cb03 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -1200,7 +1200,7 @@ void cb_about (Fl_Widget* w, void*) o->labelfont(8); o->labelsize(18); } - { Fl_Box* o = new Fl_Box(95, 265, 195, 25, "V "VERSION); + { Fl_Box* o = new Fl_Box(95, 265, 195, 25, "V " VERSION); o->labelfont(8); o->labelsize(18); } From 3d6883ea5506d161dd46ed5f71a17884896e88fe Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Fri, 13 Mar 2020 05:48:48 -0400 Subject: [PATCH 289/327] Fix obviously incorrect comparison. --- src/highlight.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/highlight.cpp b/src/highlight.cpp index 1d016c6..a6e6bae 100644 --- a/src/highlight.cpp +++ b/src/highlight.cpp @@ -363,7 +363,7 @@ void style_parse(const char *text, char *style, int length) current = 'H'; } - else if (!last && /*islower(*text) && */ text > 0)// && + else if (!last && /*islower(*text) && */ *text > 0)// && // !(isalnum(*(text-1)) || *(text-1)=='_')) { // Might be a keyword... From 662af68ef04f6f0d6f5e10a519a983ccbe3fb949 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Fri, 13 Mar 2020 05:52:46 -0400 Subject: [PATCH 290/327] Use delete[] for new char[x] allocations. --- src/My_Text_Editor.cpp | 4 ++-- src/disassemble.cpp | 2 +- src/linker.cpp | 2 +- src/project.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/My_Text_Editor.cpp b/src/My_Text_Editor.cpp index 774d8df..9831a2b 100644 --- a/src/My_Text_Editor.cpp +++ b/src/My_Text_Editor.cpp @@ -456,7 +456,7 @@ int My_Text_Editor::handle_key() { insert_position(inspos); insert("\t"); } - delete line; + delete[] line; autobrace = false; return 1; } @@ -469,7 +469,7 @@ int My_Text_Editor::handle_key() { for(unsigned int i = 0; i < strlen(line); i++) { if(line[i]!=' ' && line[i]!='\t') { pos = i; break; } } - delete line; + delete[] line; int old = insert_position(); insert_position(buffer()->line_start(insert_position()) + pos); if(state == FL_SHIFT) diff --git a/src/disassemble.cpp b/src/disassemble.cpp index b3f17e9..36f3923 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -640,7 +640,7 @@ void VTDisWhat::CbOkay(void) gpDis->CopyIntoMem(pBuf, size, addr); gpDis->m_StartAddress = addr; gpDis->m_EndAddress = addr+size-1; - delete pBuf; + delete[] pBuf; // Now copy the standard ROM into the lower memory space gpDis->CopyIntoMem(gSysROM, ROMSIZE); diff --git a/src/linker.cpp b/src/linker.cpp index 76b0f26..8b04327 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -3929,7 +3929,7 @@ int VTLinker::GenerateOutputFile() fclose(fd); // Delete the ROM memory - delete pRom; + delete[] pRom; } // We don't support Library output yet, but soon... diff --git a/src/project.cpp b/src/project.cpp index aec0ff5..f6e8f66 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -615,7 +615,7 @@ void VT_ProjectSettings::ProjTypeChanged(void) *pOldExt = '\0'; m_pProject->m_OutputName = pNewName + newExt; m_pOutputName->value(m_pProject->m_OutputName); - delete pNewName; + delete[] pNewName; } void VT_ProjectSettings::show(void) From b65e009cf51abd7dc3b4cfe90120131b4e4611a7 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Fri, 13 Mar 2020 05:56:27 -0400 Subject: [PATCH 291/327] Silence warnings when if (x = y()) --- src/assemble.cpp | 4 ++-- src/display.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/assemble.cpp b/src/assemble.cpp index fe6bacb..ec6fc5e 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -5207,7 +5207,7 @@ void VTAssembler::Parse(MString filename) ParseExternalDefines(); // Try to assemble the file - if (success = ParseASMFile(filename, this)) + if ((success = ParseASMFile(filename, this))) { // Test if #ifdef stack is zero (mis-matched if / else / end if (m_IfDepth != 0) @@ -5222,7 +5222,7 @@ void VTAssembler::Parse(MString filename) } // No parse errors! Try to assemble - else if (success = Assemble()) + else if ((success = Assemble())) { // Get Output filename temp = filename.Right(4); diff --git a/src/display.cpp b/src/display.cpp index 150cb03..0f09640 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -3551,7 +3551,7 @@ int T100_Disp::handle(int event) } } // Test if we are in the menu - if (whichMenu = IsInMenu()) + if ((whichMenu = IsInMenu())) { m_Select = FALSE; // Test if mouse is in FKey area From 1583268bbff5390d657533cd323d95b5b5f72157 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Fri, 13 Mar 2020 06:00:03 -0400 Subject: [PATCH 292/327] Remove usage of obsolete register storage class. --- src/My_Text_Buffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/My_Text_Buffer.cpp b/src/My_Text_Buffer.cpp index 29f68fd..352a9b0 100644 --- a/src/My_Text_Buffer.cpp +++ b/src/My_Text_Buffer.cpp @@ -1298,7 +1298,7 @@ int My_Text_Buffer::substitute_null_characters( char *string, int len ) { ** routine if no substitution has been done. */ void My_Text_Buffer::unsubstitute_null_characters( char *string ) { - register char * c, subsChar = mNullSubsChar; + char * c, subsChar = mNullSubsChar; if ( subsChar == '\0' ) return; From 85753e52d54bee0d339ce28eaa494bee6bc56b8e Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Fri, 13 Mar 2020 06:06:53 -0400 Subject: [PATCH 293/327] Fix some more harmless warnings. Scary warnings are left in as an excercise for someone who actually digs in and tests changes. --- src/highlight.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/highlight.cpp b/src/highlight.cpp index a6e6bae..39d78e1 100644 --- a/src/highlight.cpp +++ b/src/highlight.cpp @@ -340,7 +340,7 @@ void style_parse(const char *text, char *style, int length) { current = 'C'; *style++ = current; - *style--; + style--; } else if (strncmp(text, "\\\"", 2) == 0) @@ -483,11 +483,6 @@ void style_parse(const char *text, char *style, int length) // Copy style info... if (current == 'A' && (*text == '{' || *text == '}')) *style++ = 'G'; - /*else if(current == 'E' && strncmp(text, "/*", 2) == 0) { - *style++ = 'C'; - *style++ = 'C'; - //*style--; - }*/ else if(current == 'E' && strncmp(text, "/*", 2) == 0) { *style++ = 'C'; From 2e2f6af879313deff4450ffd6c49fe11bebbe9c0 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 13 Mar 2020 18:03:10 -0700 Subject: [PATCH 294/327] Shortened the LCD response time in io.c to more closely match the real HW. Needs additional profiling. --- src/io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io.c b/src/io.c index aa91ba6..16ca0ef 100644 --- a/src/io.c +++ b/src/io.c @@ -1269,7 +1269,7 @@ int inport(uchar port) { /* Check if this driver is enabled */ if (lcdbits & (1 << c)) - if (lcdTime[c]+.000014 > hirestimer()) + if (lcdTime[c]+.000003 > hirestimer()) return (0x80); } return 64; From 0ab31028c2a40f2eac0edd5d101f0a732f6f401b Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 13 Mar 2020 20:38:25 -0700 Subject: [PATCH 295/327] Updated CPU regs trace bug where L register was showing E values. --- src/cpuregs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index a968f14..cee0e74 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -661,7 +661,7 @@ int build_trace_line(int line, char* lineStr) else sprintf(str, "A:%02X %s B:%02X C:%02X D:%02X E:%02X H:%02X L:%02X SP:%02X", pTrace->af >> 8, flags, pTrace->bc >> 8, pTrace->bc & 0xFF, pTrace->de >> 8, - pTrace->de & 0xFF, pTrace->hl >> 8, pTrace->de & 0xFF, pTrace->sp); + pTrace->de & 0xFF, pTrace->hl >> 8, pTrace->hl & 0xFF, pTrace->sp); strcat(lineStr, str); return last_pc; From 28d21e2ed3a520e1c9930b48d34c00d7d7c65b20 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Fri, 13 Mar 2020 20:39:39 -0700 Subject: [PATCH 296/327] Changed assembler.cpp LookupSymbol / Define logic. --- src/assemble.cpp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/assemble.cpp b/src/assemble.cpp index ec6fc5e..74c107e 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -2966,14 +2966,28 @@ void VTAssembler::preproc_ifdef(const char* name, int negate) m_IfStat[m_IfDepth] = IF_STAT_DONT_ASSEMBLE; strName = name; // Test if it is a CMacro - if (LookupMacro(strName, pMacro)) - { - if (!negate) - m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; - } - else + // if (LookupMacro(strName, pMacro)) + // { + // if (!negate) + // m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; + // } + // else { defined = LookupSymbol(strName, dummy); + if (!defined) + { + int def; + + for (def = 0; def < m_Defines.GetSize(); def++) + { + if (((CMacro *) m_Defines[def])->m_Name == strName) + { + defined = 1; + break; + } + } + } + if ((defined && !negate) || (!defined && negate)) m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; } From dda89818112cb85c43cb63897932b361e062b098 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Sat, 14 Mar 2020 00:45:25 -0400 Subject: [PATCH 297/327] Fix harmless warnings. --- src/My_Text_Buffer.cpp | 2 +- src/My_Text_Editor.cpp | 2 +- src/assemble.cpp | 8 ++++---- src/linker.cpp | 4 ++-- src/periph.cpp | 2 +- src/tpddserver.cpp | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/My_Text_Buffer.cpp b/src/My_Text_Buffer.cpp index 352a9b0..03172a4 100644 --- a/src/My_Text_Buffer.cpp +++ b/src/My_Text_Buffer.cpp @@ -823,7 +823,7 @@ void My_Text_Buffer::add_predelete_callback(My_Text_Predelete_Cb bufPreDeleteCB, newPreDeleteProcs[i + 1] = mPredeleteProcs[i]; newCBArgs[i + 1] = mPredeleteCbArgs[i]; } - if (! mNPredeleteProcs != 0) { + if (mNPredeleteProcs == 0) { delete [] mPredeleteProcs; delete [] mPredeleteCbArgs; } diff --git a/src/My_Text_Editor.cpp b/src/My_Text_Editor.cpp index 9831a2b..df25fcb 100644 --- a/src/My_Text_Editor.cpp +++ b/src/My_Text_Editor.cpp @@ -443,7 +443,7 @@ int My_Text_Editor::handle_key() { char *line = new char[strlen(buffer()->line_text(insert_position()))+1]; strcpy(line, buffer()->line_text(insert_position())); for(unsigned int i = 0; i < strlen(line); i++) { - if(line[i]!=' ' && line[i]!='\t' || i >= (unsigned int) max) line[i]='\0'; + if((line[i]!=' ' && line[i]!='\t') || i >= (unsigned int) max) line[i]='\0'; } kf_enter(c,this); insert(line); diff --git a/src/assemble.cpp b/src/assemble.cpp index 74c107e..b787fcb 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -1088,7 +1088,7 @@ int VTAssembler::GetValue(MString & string, int & value) // First check if string is a numeric value for (c = 0; c < len; c++) - if ((string[c] > '9') || (string[c] < '0') && string[c] != '-') + if ((string[c] > '9') || ((string[c] < '0') && string[c] != '-')) { numericVal = 0; break; @@ -3208,13 +3208,13 @@ int VTAssembler::preproc_macro() if (pos != 0) { char ch = replace[pos-1]; // Get char before the find - if ((ch >= 'A') && (ch <= 'z') || (ch == '_') || (ch == '$') || (ch == '&')) + if (((ch >= 'A') && (ch <= 'z')) || (ch == '_') || (ch == '$') || (ch == '&')) wholeMatch = FALSE; } if (pos + len != replace.GetLength()-1) { char ch = replace[pos + len +1 ]; - if ((ch >= 'A') && (ch <= 'z') || (ch == '_') || (ch == '$') || (ch == '&')) + if (((ch >= 'A') && (ch <= 'z')) || (ch == '_') || (ch == '$') || (ch == '&')) wholeMatch = FALSE; } @@ -3667,7 +3667,7 @@ int VTAssembler::Assemble() // Test for relative branch instruction else if ((pInst->m_ID >= OPCODE_BR) && (pInst->m_ID <= OPCODE_RCALL)) { - if ((pInst->m_ID >= OPCODE_BRA) && (pInst->m_ID <= OPCODE_BPE) || + if (((pInst->m_ID >= OPCODE_BRA) && (pInst->m_ID <= OPCODE_BPE)) || (pInst->m_ID == OPCODE_RCALL)) size = 3; diff --git a/src/linker.cpp b/src/linker.cpp index 8b04327..d46c398 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -1436,8 +1436,8 @@ void VTLinker::NewLinkRegion(int type, int lineNo, int startAddr, while (pThisRange != NULL) { // Test if this region overlaps with new region - if (((startAddr >= pThisRange->startAddr) && ( - (startAddr <= pThisRange->endAddr)) || + if ((((startAddr >= pThisRange->startAddr) && ( + (startAddr <= pThisRange->endAddr))) || ((endAddr >= pThisRange->startAddr) && (endAddr <= pThisRange->endAddr)) || ((startAddr <= pThisRange->startAddr) && diff --git a/src/periph.cpp b/src/periph.cpp index f34f268..ef7b667 100644 --- a/src/periph.cpp +++ b/src/periph.cpp @@ -1675,7 +1675,7 @@ void T100_ComMon::SaveLog(void) cle = &clb->entries[index]; // Test if this entry's rx/tx marker is different from current packet - if ((rxtx != 0) && ((cle->flags & 0x80) && (rxtx == CLE_RX) || (!(cle->flags & 0x80) && (rxtx == CLE_TX)))) + if ((rxtx != 0) && (((cle->flags & 0x80) && (rxtx == CLE_RX)) || (!(cle->flags & 0x80) && (rxtx == CLE_TX)))) { // This byte doesn't match the current line! Terminate the current line and start a new one fill = 0; diff --git a/src/tpddserver.cpp b/src/tpddserver.cpp index 82321d4..bea2889 100644 --- a/src/tpddserver.cpp +++ b/src/tpddserver.cpp @@ -1610,7 +1610,7 @@ int VTTpddServer::SerWriteByte(char data) } // Test for command line characters - if (data >= 'a' && data <= 'z' || m_backgroundCmd) + if ((data >= 'a' && data <= 'z') || m_backgroundCmd) { // Add the byte to our RX buffer m_rxBuffer[m_rxIn++] = data; From 8a11dd3c83a2428a4a40c746bc27788d1434cd32 Mon Sep 17 00:00:00 2001 From: Stephen Hurd Date: Sat, 14 Mar 2020 00:46:44 -0400 Subject: [PATCH 298/327] Fix copy pasta. --- src/vtpaper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vtpaper.cpp b/src/vtpaper.cpp index ecab919..1f31418 100644 --- a/src/vtpaper.cpp +++ b/src/vtpaper.cpp @@ -1119,7 +1119,7 @@ void VTPSPaper::WriteHeader(void) fprintf(m_pFd, "%%!PS-Adobe-3.0\n"); fprintf(m_pFd, "%%%%Pages: (atend)\n"); fprintf(m_pFd, "%%%%Creator: VirtualT %s\n", VERSION); - fprintf(m_pFd, "%%%%Title: FX-80 Emulation Print\n", VERSION); + fprintf(m_pFd, "%%%%Title: FX-80 Emulation Print\n"); fprintf(m_pFd, "%%%%DocumentData: Clean7Bit\n"); fprintf(m_pFd, "%%%%LanguageLevel: 2\n"); fprintf(m_pFd, "%%%%EndComments\n"); From 6c8bd22360f529e475e3b80882407d8694c8b082 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 14 Mar 2020 06:19:57 -0700 Subject: [PATCH 299/327] Checking in missing code added to IDE / Linker to automatically load assembled code to REX memory during REX emulation. --- src/ide.cpp | 116 +++++++++++++++++++++++++++++++++++++++++++++++-- src/ide.h | 2 + src/linker.cpp | 30 +++++++++++++ src/linker.h | 1 + 4 files changed, 146 insertions(+), 3 deletions(-) diff --git a/src/ide.cpp b/src/ide.cpp index fd2b248..ce502dd 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -3836,7 +3836,7 @@ void VT_Ide::Stdout(const char *msg) /* ============================================================================= -BuildProjet: This routine is the reason for all this mess! Try to assemble +BuildProject: This routine is the reason for all this mess! Try to assemble each file in the project and then link if no errors. ============================================================================= */ @@ -3939,6 +3939,105 @@ void VT_Ide::AssembleSourcesInGroup(VTAssembler& assembler, VT_IdeGroup* pGroup, } } +/* +============================================================================= +LoadRomToRex: This routine load the built OptROM data to the REX flash + in the active ROM image area. +============================================================================= +*/ +void VT_Ide::LoadRomToRex(VTLinker *pLinker) +{ + long address, blockaddr; + unsigned char sEntry[7]; + int x, actblk = 0; + unsigned char status; + MString temp; + unsigned char buf[32768]; + + // First find the location of the directory + address = 0xC400; + get_memory8_ext(REGION_REX_FLASH, address+1, 6, sEntry); + sEntry[6] = '\0'; + + // Test for "SYSTEM" + if (strcmp((char *) sEntry, (char *) "SYSTEM") != 0) + { + // Not found. Try 0xE000 + address = 0xE400; + get_memory8_ext(REGION_REX_FLASH, address+1, 6, sEntry); + if (strcmp((char *) sEntry, (char *) "SYSTEM") != 0) + { + // Don't know where REX is! + return; + } + } + +#if 0 + // Address found. Determine active block + for (x = 0; x < 0x3FF; x++) + { + get_memory8_ext(REGION_REX_FLASH, address-0x400+x, 1, &status); + if ((status & 0xE0) == 0x40) + { + actblk = status & 0x1F; + break; + } + } + + // Validate active block found + if (actblk == 0) + return; + + // Find the active block in the directory + for (x = 0; x < 0x3ff; x++) + { + get_memory8_ext(REGION_REX_FLASH, address+x*16, 1, &status); + if (status == (0xC0 | actblk)) + { + break; + } + } + + // Test if block found above + if (x == 0x3ff) + { + // Active block not found! + return; + } + + // Block found. Get the image name + get_memory8_ext(REGION_REX_FLASH, address+x*16+1, 6, sEntry); +#endif + + temp = m_ActivePrj->m_Name; + temp.MakeUpper(); + + // Find the project name in the dir list + for (x = 0; x < 0x3FF; x++) + { + unsigned char dent[7]; + + get_memory8_ext(REGION_REX_FLASH, address+x*16+1, 6, dent); + dent[6] = '\0'; + + // Validate the block name + if (strncmp((char *) dent, (const char *) temp, 6) == 0) + { + unsigned char blk; + get_memory8_ext(REGION_REX_FLASH, address+x*16, 1, &blk); + + // Match! Copy data to this block location + blk &= 0x1F; + address = (long) (blk) << 15; + + // Do the memcpy + pLinker->CreateByteArray(buf, sizeof(buf)); + set_memory8_ext(REGION_REX_FLASH, address, 32768, buf); + } + } + +} + /* ============================================================================= BuildProjet: This routine is the reason for all this mess! Try to assemble @@ -4076,8 +4175,19 @@ void VT_Ide::BuildProject(void) break; case VT_PROJ_TYPE_ROM: - /* Re-load the OPT ROM */ - load_opt_rom(); + /* Test if REX is enabled. If it is, then we must copy the + new ROM image into the active image area, validating the + name in the process. + */ + if (gRex) + { + LoadRomToRex(linker); + } + else + { + /* Re-load the OPT ROM */ + load_opt_rom(); + } break; case VT_PROJ_TYPE_LIB: diff --git a/src/ide.h b/src/ide.h index 1d52a68..96f8567 100644 --- a/src/ide.h +++ b/src/ide.h @@ -47,6 +47,7 @@ #include "project.h" #include "My_Text_Editor.h" #include "idetabs.h" +#include "linker.h" void cb_Ide(Fl_Widget* w, void*) ; @@ -214,6 +215,7 @@ class VT_Ide : public Fl_Window int& totalErrors, int& linkerScriptFound, MString& linkerScript, MString& linkerFiles); void BuildProject(void); + void LoadRomToRex(VTLinker* plinker); void CleanProject(void); void SetColors(int fg, int bg); void ShowProjectSettings(void); diff --git a/src/linker.cpp b/src/linker.cpp index d46c398..f0d965c 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -4137,6 +4137,36 @@ int VTLinker::GenerateLoaderFile(int startAddr, int endAddr, int entryAddr) return 1; } +/* +============================================================================ +Generates a linear byte array of program bytes. +============================================================================ +*/ +int VTLinker::CreateByteArray(unsigned char *buf, int size) +{ + int c, x; + + // Loop for all data + for (c = 0; c < size; ) + { + // Write the next block of bytes + CObjFileSection *pSect = m_SegMap[c]; + for (x = 0; x < pSect->m_Size; x++) + { + buf[c++] = pSect->m_pProgBytes[x]; + } + + while ((m_SegMap[c] == NULL || m_SegMap[c]->m_Name == ".bss") && + c <= size) + { + buf[c] = 0; + c++; + } + } + + return 1; +} + /* ============================================================================ Generates a map file if one was requested and no errors exist during the diff --git a/src/linker.h b/src/linker.h index edf27ff..ad5398f 100644 --- a/src/linker.h +++ b/src/linker.h @@ -402,6 +402,7 @@ class VTLinker : public VTObject public: // Public Access functions int Link(); + int CreateByteArray(unsigned char *buf, int count); unsigned short GetEntryAddress(void); unsigned short GetStartAddress(void); void SetLinkOptions(const MString& options); From 5b34e52c9711acab9af896a8f2df409cb88f029b Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 14 Mar 2020 07:07:39 -0700 Subject: [PATCH 300/327] Updates to tdock sources to add support for locking the label line. --- src/tdock.cpp | 26 ++- src/tdock.h | 2 +- src/tdockvid.cpp | 464 +++++++++++++++++++++++++---------------------- src/tdockvid.h | 86 ++++----- 4 files changed, 321 insertions(+), 257 deletions(-) diff --git a/src/tdock.cpp b/src/tdock.cpp index 7fe0af5..f7f272f 100644 --- a/src/tdock.cpp +++ b/src/tdock.cpp @@ -1,6 +1,6 @@ /* tdock.cpp */ -/* $Id$ */ +/* $Id: tdock.cpp,v 1.1 2015/02/24 20:19:17 kpettit1 Exp $ */ /* * Copyright 2015 Ken Pettit @@ -88,6 +88,19 @@ static Fl_Menu_Item menuitems[] = { }; +void close_tdock_cb(Fl_Widget* w, void*) +{ + /* Save the window preferences here! */ + + /* Delete the window */ + delete gpExtWin; + + /* NULL out the pointers so we know we have no window */ + gpExtWin = NULL; + gpDisp = NULL; + gpExtMenu = NULL; +} + /* ============================================================================ TDock C init routine @@ -95,7 +108,14 @@ TDock C init routine */ void tdock_init (void) { - gpExtWin = new Fl_Window((480)*MultFact+10, 200*MultFact+MENU_HEIGHT+10, "VirtualT's TDock VGA Emulation"); + int multfact; + + /* Limit display size */ + multfact = MultFact; + if (multfact > 3) + multfact = 3; + + gpExtWin = new Fl_Window((480)*multfact+10, 200*multfact+MENU_HEIGHT+10, "VirtualT's TDock VGA Emulation"); /* Create a Menu bar in the window */ gpExtMenu = new Fl_Menu_Bar(0, 0, gpExtWin->w(), MENU_HEIGHT-2); @@ -103,6 +123,8 @@ void tdock_init (void) /* Crate a TDock Video window */ gpDisp = new VTTDockVid(0, MENU_HEIGHT, gpExtWin->w(), gpExtWin->h() - MENU_HEIGHT); + gpDisp->SetMultFact(multfact); + gpExtWin->callback(close_tdock_cb); gpExtWin->end(); gpExtWin->show(); diff --git a/src/tdock.h b/src/tdock.h index 79618d2..6b5ad1c 100644 --- a/src/tdock.h +++ b/src/tdock.h @@ -1,6 +1,6 @@ /* tdock.h */ -/* $Id$ */ +/* $Id: tdock.h,v 1.1 2015/02/24 20:19:17 kpettit1 Exp $ */ /* * Copyright 2015 Ken Pettit diff --git a/src/tdockvid.cpp b/src/tdockvid.cpp index dce9364..03b2662 100644 --- a/src/tdockvid.cpp +++ b/src/tdockvid.cpp @@ -134,18 +134,19 @@ T100:Disp: This is the class construcor VTTDockVid::VTTDockVid(int x, int y, int w, int h) : Fl_Widget(x, y, w, h) { - int c, red, green, blue; + int c, red, green, blue; - m_FrameColor = gFrameColor; - m_DetailColor = gDetailColor; - m_BackgroundColor = gBackgroundColor; - m_PixelColor = gPixelColor; - m_LabelColor = gLabelColor; - m_HaveMouse = FALSE; + m_FrameColor = gFrameColor; + m_DetailColor = gDetailColor; + m_BackgroundColor = gBackgroundColor; + m_PixelColor = gPixelColor; + m_LabelColor = gLabelColor; + m_HaveMouse = FALSE; + m_LabelLocked = FALSE; memset(pixdata, 0, 200*480); - m_MyFocus = 0; + m_MyFocus = 0; m_CurX = 0; m_CurY = 0; m_EscSeq = 0; @@ -191,14 +192,14 @@ VTTDockVid::VTTDockVid(int x, int y, int w, int h) : m_Colors[0] = gBackgroundColor; m_Colors[255] = gPixelColor; - MultFact = 2; - DisplayMode = 1; - SolidChars = 0; - DispHeight = 64; - gRectsize = 2; + MultFact = 2; + DisplayMode = 1; + SolidChars = 0; + DispHeight = 64; + gRectsize = 2; - m_BezelTop = m_BezelLeft = m_BezelBottom = m_BezelRight = 0; - m_BezelTopH = m_BezelLeftW = m_BezelBottomH = m_BezelRightW = 0; + m_BezelTop = m_BezelLeft = m_BezelBottom = m_BezelRight = 0; + m_BezelTopH = m_BezelLeftW = m_BezelBottomH = m_BezelRightW = 0; CalcScreenCoords(); } @@ -214,11 +215,17 @@ Clear: This routine clears the "LCD" */ void VTTDockVid::Clear(void) { - memset(pixdata, 0, 200*480); + int bottom; - m_CurX = m_CurY = 0; - redraw(); - Fl::check(); + if (m_LabelLocked) + bottom = 200-8; + else + bottom = 200; + memset(pixdata, 0, bottom*480); + + m_CurX = m_CurY = 0; + redraw(); + Fl::check(); } /* @@ -230,14 +237,26 @@ drawpixel: This routine is called by the system to draw a single // Draw the black pixels on the LCD __inline void VTTDockVid::drawpixel(int x, int y, int color) { - // Check if the pixel color is black and draw if it is - if (color) + // Check if the pixel color is black and draw if it is + if (color) { - fl_rectf(x*MultFact + gXoffset,y*MultFact + gYoffset, - gRectsize, gRectsize); + fl_rectf(x*MultFact + gXoffset,y*MultFact + gYoffset, + gRectsize, gRectsize); } } +/* +======================================================= +Set the screen size multiplication factor +======================================================= +*/ +void VTTDockVid::SetMultFact(int multfact) +{ + MultFact = multfact; + ::MultFact = multfact; + gRectsize = multfact; +} + /* ======================================================= Calculate the xoffset, yoffset, border locations, etc. @@ -245,102 +264,101 @@ Calculate the xoffset, yoffset, border locations, etc. */ void VTTDockVid::CalcScreenCoords(void) { - // Calculatet the pixel rectangle size - ::gRectsize = MultFact; - if (::gRectsize == 0) - ::gRectsize = 1; - - // Calculate xoffset and yoffset - if (Fullscreen) - { - ::gXoffset = parent()->w() / 2 - 240 * MultFact; - ::gYoffset = (parent()->h() - MENU_HEIGHT - 20 - 200 * MultFact) / 3 + MENU_HEIGHT+1; - } - else - { - ::gXoffset = 5; - ::gYoffset = MENU_HEIGHT+5; - } + // Calculatet the pixel rectangle size + ::gRectsize = MultFact; + if (::gRectsize == 0) + ::gRectsize = 1; - gRectsize = ::gRectsize; - gXoffset = ::gXoffset; - gYoffset = ::gYoffset; - - // If the display is framed, then calculate the frame coords - - if (DisplayMode && 0) - { - // Calculate the Bezel location - int wantedH = 20; - int wantedW = 40; -// int topH, bottomH, leftW, rightW; - int bottomSpace; - int rightSpace; - - // Calculate the top height of the Bezel - m_HasTopChassis = TRUE; - if (gYoffset-1 - MENU_HEIGHT-1 >= wantedH + 5) - m_BezelTopH = wantedH; - else - { - // Test if there's room for both Bezel and chassis detail - if (gYoffset > 6) - m_BezelTopH = gYoffset - MENU_HEIGHT - 1 - 6; - else - { - m_BezelTopH = gYoffset - MENU_HEIGHT - 1 - 1; - m_HasTopChassis = FALSE; - } - } - m_BezelTop = gYoffset - m_BezelTopH - 1; - - // Calculate the bottom height of the Bezel - m_BezelBottom = gYoffset + 200 * MultFact + 1; - bottomSpace = parent()->h() - m_BezelBottom - 20; - m_HasBottomChassis = TRUE; - if (bottomSpace >= wantedH + 5) - m_BezelBottomH = wantedH; - else - { - m_BezelBottomH = bottomSpace; - m_HasBottomChassis = FALSE; - } - - // Calculate the left Bezel border width - m_HasLeftChassis = TRUE; - if (gXoffset-1 >= wantedW + 5) - m_BezelLeftW = wantedW; - else - { - // Test if there's room for Bezel plus chassis - if (gXoffset > 6) - m_BezelLeftW = gXoffset - 6; - else - { - m_BezelLeftW = gXoffset - 1; - m_HasLeftChassis = FALSE; - } - } - m_BezelLeft = gXoffset - m_BezelLeftW - 1; - - // Calculate the Bezel right width - m_BezelRight = gXoffset + 240 * MultFact + 1; - rightSpace = w() - m_BezelRight; - m_HasRightChassis = TRUE; - if (rightSpace >= wantedW + 5) - m_BezelRightW = wantedW; - else - { - // Test if there's room for Bezel plus chassis - if (rightSpace > 5) - m_BezelRightW = rightSpace - 5; - else - { - m_BezelRightW = rightSpace; - m_HasRightChassis = FALSE; - } - } - } + // Calculate xoffset and yoffset + if (Fullscreen) + { + ::gXoffset = parent()->w() / 2 - 240 * MultFact; + ::gYoffset = (parent()->h() - MENU_HEIGHT - 20 - 200 * MultFact) / 3 + MENU_HEIGHT+1; + } + else + { + ::gXoffset = 5; + ::gYoffset = MENU_HEIGHT+5; + } + + gRectsize = ::gRectsize; + gXoffset = ::gXoffset; + gYoffset = ::gYoffset; + + // If the display is framed, then calculate the frame coords + if (DisplayMode && 0) + { + // Calculate the Bezel location + int wantedH = 20; + int wantedW = 40; + // int topH, bottomH, leftW, rightW; + int bottomSpace; + int rightSpace; + + // Calculate the top height of the Bezel + m_HasTopChassis = TRUE; + if (gYoffset-1 - MENU_HEIGHT-1 >= wantedH + 5) + m_BezelTopH = wantedH; + else + { + // Test if there's room for both Bezel and chassis detail + if (gYoffset > 6) + m_BezelTopH = gYoffset - MENU_HEIGHT - 1 - 6; + else + { + m_BezelTopH = gYoffset - MENU_HEIGHT - 1 - 1; + m_HasTopChassis = FALSE; + } + } + m_BezelTop = gYoffset - m_BezelTopH - 1; + + // Calculate the bottom height of the Bezel + m_BezelBottom = gYoffset + 200 * MultFact + 1; + bottomSpace = parent()->h() - m_BezelBottom - 20; + m_HasBottomChassis = TRUE; + if (bottomSpace >= wantedH + 5) + m_BezelBottomH = wantedH; + else + { + m_BezelBottomH = bottomSpace; + m_HasBottomChassis = FALSE; + } + + // Calculate the left Bezel border width + m_HasLeftChassis = TRUE; + if (gXoffset-1 >= wantedW + 5) + m_BezelLeftW = wantedW; + else + { + // Test if there's room for Bezel plus chassis + if (gXoffset > 6) + m_BezelLeftW = gXoffset - 6; + else + { + m_BezelLeftW = gXoffset - 1; + m_HasLeftChassis = FALSE; + } + } + m_BezelLeft = gXoffset - m_BezelLeftW - 1; + + // Calculate the Bezel right width + m_BezelRight = gXoffset + 240 * MultFact + 1; + rightSpace = w() - m_BezelRight; + m_HasRightChassis = TRUE; + if (rightSpace >= wantedW + 5) + m_BezelRightW = wantedW; + else + { + // Test if there's room for Bezel plus chassis + if (rightSpace > 5) + m_BezelRightW = rightSpace - 5; + else + { + m_BezelRightW = rightSpace; + m_HasRightChassis = FALSE; + } + } + } } /* @@ -352,102 +370,101 @@ draw_static: This routine draws the static portions of the LCD, */ void VTTDockVid::draw_static() { - int c; - int width; - int x_pos, inc, start, y_pos; - int xl_start, xl_end, xr_start, xr_end; - int num_labels; + int c; + int width; + int x_pos, inc, start, y_pos; + int xl_start, xl_end, xr_start, xr_end; + int num_labels; - // Draw gray "screen" + // Draw gray "screen" fl_color(m_BackgroundColor); fl_rectf(x(),y(),w(),h()); return; - /* Check if the user wants the display "framed" */ - if (DisplayMode == 1) - { - // Color for outer border - fl_color(m_DetailColor); - - // Draw border along the top - if (m_HasTopChassis) - fl_rectf(x(),y(),w(),m_BezelTop - MENU_HEIGHT - 1); + /* Check if the user wants the display "framed" */ + if (DisplayMode == 1) + { + // Color for outer border + fl_color(m_DetailColor); - // Draw border along the bottom - if (m_HasBottomChassis) - fl_rectf(x(),m_BezelBottom + m_BezelBottomH,w(),parent()->h() - m_BezelBottom - m_BezelBottomH - 20); + // Draw border along the top + if (m_HasTopChassis) + fl_rectf(x(),y(),w(),m_BezelTop - MENU_HEIGHT - 1); - // Draw border along the left - if (m_HasLeftChassis) - fl_rectf(x(),y(),m_BezelLeft,h()); + // Draw border along the bottom + if (m_HasBottomChassis) + fl_rectf(x(),m_BezelBottom + m_BezelBottomH,w(),parent()->h() - m_BezelBottom - m_BezelBottomH - 20); - // Draw border along the right - if (m_HasRightChassis) - fl_rectf(m_BezelRight + m_BezelRightW,y(),w()-m_BezelRight,h()); + // Draw border along the left + if (m_HasLeftChassis) + fl_rectf(x(),y(),m_BezelLeft,h()); + // Draw border along the right + if (m_HasRightChassis) + fl_rectf(m_BezelRight + m_BezelRightW,y(),w()-m_BezelRight,h()); - // Color for inner border - fl_color(m_FrameColor); - - // Draw border along the top - if (m_BezelTopH > 0) - fl_rectf(m_BezelLeft,m_BezelTop,m_BezelRight - m_BezelLeft + m_BezelRightW,m_BezelTopH); + // Color for inner border + fl_color(m_FrameColor); + + // Draw border along the top + if (m_BezelTopH > 0) + fl_rectf(m_BezelLeft,m_BezelTop,m_BezelRight - m_BezelLeft + m_BezelRightW,m_BezelTopH); - // Draw border along the bottom - if (m_BezelBottomH > 0) - fl_rectf(m_BezelLeft,m_BezelBottom,m_BezelRight - m_BezelLeft + m_BezelRightW,m_BezelBottomH); + // Draw border along the bottom + if (m_BezelBottomH > 0) + fl_rectf(m_BezelLeft,m_BezelBottom,m_BezelRight - m_BezelLeft + m_BezelRightW,m_BezelBottomH); - // Draw border along the left - if (m_BezelLeftW > 0) - fl_rectf(m_BezelLeft, m_BezelTop, m_BezelLeftW, m_BezelBottom - m_BezelTop + m_BezelBottomH); + // Draw border along the left + if (m_BezelLeftW > 0) + fl_rectf(m_BezelLeft, m_BezelTop, m_BezelLeftW, m_BezelBottom - m_BezelTop + m_BezelBottomH); - // Draw border along the right - if (m_BezelRightW > 0) - fl_rectf(m_BezelRight,m_BezelTop, m_BezelRightW, m_BezelBottom - m_BezelTop + m_BezelBottomH); + // Draw border along the right + if (m_BezelRightW > 0) + fl_rectf(m_BezelRight,m_BezelTop, m_BezelRightW, m_BezelBottom - m_BezelTop + m_BezelBottomH); #ifdef ZIPIT_Z2 - width = 320; + width = 320; #else - width = 240 * MultFact; + width = 240 * MultFact; #endif - num_labels = gModel == MODEL_PC8201 ? 5 : 8; - inc = width / num_labels; - start = gXoffset + width/16 - 2 * (5- (MultFact > 5? 5 : MultFact)); - fl_color(m_LabelColor); - fl_font(FL_COURIER,12); - char text[3] = "F1"; -// y_pos = h()+20; - y_pos = m_BezelBottom + 13; //y()+DispHeight*MultFact+40; - xl_start = 2*MultFact; - xl_end = 7*MultFact; - - xr_start = 12 + 2*MultFact; - xr_end = 12 + 7*MultFact; - - // Draw function key labels - for (c = 0; c < num_labels; c++) - { - // Draw text - x_pos = start + inc*c; - text[1] = c + '1'; - fl_draw(text, x_pos, y_pos); - - if (MultFact != 1) - { - // Draw lines to left - fl_line(x_pos - xl_start, y_pos-2, x_pos - xl_end, y_pos-2); - fl_line(x_pos - xl_start, y_pos-7, x_pos - xl_end, y_pos-7); - fl_line(x_pos - xl_end, y_pos-2, x_pos - xl_end, y_pos-7); - - // Draw lines to right - fl_line(x_pos + xr_start, y_pos-2, x_pos + xr_end, y_pos-2); - fl_line(x_pos + xr_start, y_pos-7, x_pos + xr_end, y_pos-7); - fl_line(x_pos + xr_end, y_pos-2, x_pos + xr_end, y_pos-7); - } - } - } + num_labels = gModel == MODEL_PC8201 ? 5 : 8; + inc = width / num_labels; + start = gXoffset + width/16 - 2 * (5- (MultFact > 5? 5 : MultFact)); + fl_color(m_LabelColor); + fl_font(FL_COURIER,12); + char text[3] = "F1"; + //y_pos = h()+20; + y_pos = m_BezelBottom + 13; //y()+DispHeight*MultFact+40; + xl_start = 2*MultFact; + xl_end = 7*MultFact; + + xr_start = 12 + 2*MultFact; + xr_end = 12 + 7*MultFact; + + // Draw function key labels + for (c = 0; c < num_labels; c++) + { + // Draw text + x_pos = start + inc*c; + text[1] = c + '1'; + fl_draw(text, x_pos, y_pos); + + if (MultFact != 1) + { + // Draw lines to left + fl_line(x_pos - xl_start, y_pos-2, x_pos - xl_end, y_pos-2); + fl_line(x_pos - xl_start, y_pos-7, x_pos - xl_end, y_pos-7); + fl_line(x_pos - xl_end, y_pos-2, x_pos - xl_end, y_pos-7); + + // Draw lines to right + fl_line(x_pos + xr_start, y_pos-2, x_pos + xr_end, y_pos-2); + fl_line(x_pos + xr_start, y_pos-7, x_pos + xr_end, y_pos-7); + fl_line(x_pos + xr_end, y_pos-2, x_pos + xr_end, y_pos-7); + } + } + } } /* @@ -458,8 +475,8 @@ draw: This routine draws the entire LCD. This is a member */ void VTTDockVid::draw() { - /* Draw static background stuff */ - draw_static(); + /* Draw static background stuff */ + draw_static(); /* Draw the pixels */ draw_pixels(); @@ -472,17 +489,17 @@ draw_pixels: This routine draws the pixels on the display. */ void VTTDockVid::draw_pixels() { - int x=0; - int y=0; - int line; - uchar value; + int x=0; + int y=0; + int line; + uchar value; int lastColor = -1; int color; window()->make_current(); - for (line = 0; line < 200; line++) - { + for (line = 0; line < 200; line++) + { for (x = 0; x < 480; x++) { value = pixdata[line][x]; @@ -521,7 +538,7 @@ SetByte: Updates the LCD with a byte of data as written from the I/O */ void VTTDockVid::SetByte(int line, int col, uchar value) { - int y; + int y; if (line > 24 || col > 479) return; @@ -573,7 +590,7 @@ WriteData: Routine that receives data from the VDock interface when the void VTTDockVid::WriteData(uchar data) { int line, col, y; - int color; + int color, bottom; #if 0 if (m_EscSeq) @@ -592,6 +609,12 @@ void VTTDockVid::WriteData(uchar data) window()->make_current(); + /* Calculate bottom pixel value based on m_LabelLocked */ + if (m_LabelLocked) + bottom = 200-8; + else + bottom = 200; + /* Test if we are processing an ESC Sequence */ if (m_EscSeq) { @@ -669,7 +692,7 @@ void VTTDockVid::WriteData(uchar data) /* Turn cursor on */ m_Cursor = 1; - if (m_CurY >= 200) + if (m_CurY >= bottom) Scroll(); XorCursor(); break; @@ -707,6 +730,14 @@ void VTTDockVid::WriteData(uchar data) SetByte(line, col, 0); break; + case ESC_LOCK_SYS_LINE: + m_LabelLocked = TRUE; + break; + + case ESC_UNLOCK_SYS_LINE: + m_LabelLocked = FALSE; + break; + case ESC_INS_LINE: for (y = 199; y > m_CurY+8; y--) //for (line = 24; line > (m_CurY >> 3); line--) @@ -725,7 +756,7 @@ void VTTDockVid::WriteData(uchar data) break; case ESC_DEL_LINE: - for (y = m_CurY; y < 200-8; y++) + for (y = m_CurY; y < bottom-8; y++) //for (line = m_CurY >> 3; line < 24; line++) { for (col = 0; col < 480; col++) @@ -800,7 +831,7 @@ void VTTDockVid::WriteData(uchar data) break; default: - printf("ESC %02x\n", m_EscData[0]); + printf("ESC 0x%02x\n", m_EscData[0]); break; } @@ -883,7 +914,7 @@ void VTTDockVid::WriteData(uchar data) { int addr, line, c, mem_index, column, lastcolor = -1; - if (m_CurY >= 200) + if (m_CurY >= bottom) Scroll(); addr = gStdRomDesc->sCharTable; @@ -1006,12 +1037,18 @@ void VTTDockVid::XorCursor(void) void VTTDockVid::Scroll(void) { int y, col, color, lastcolor = -1; + int bottom; + + if (m_LabelLocked) + bottom = 200 - 8; + else + bottom = 200; /* Test if at bottom of display */ - if (m_CurY >= 200) + if (m_CurY >= bottom) { /* We need to perform a scroll */ - for (y = 8; y < 200; y++) + for (y = 8; y < bottom; y++) //for (line = 1; line < 25; line++) { for (col = 0; col < 480; col++) @@ -1035,7 +1072,10 @@ void VTTDockVid::Scroll(void) /* Now zero out the bottom line */ for (col = 0; col < 480; col++) { - SetByte(24,col,0); + if (m_LabelLocked) + SetByte(23,col,0); + else + SetByte(24,col,0); } m_CurY -= 8; diff --git a/src/tdockvid.h b/src/tdockvid.h index e20e1f5..a07e239 100644 --- a/src/tdockvid.h +++ b/src/tdockvid.h @@ -57,8 +57,8 @@ #define ESC_END_REVERSE 0x71 /* q */ #define ESC_CURSOR_ON 0x50 /* P */ #define ESC_CURSOR_OFF 0x51 /* Q */ -#define ESC_SET_SYS_LINE 0x54 /* T */ -#define ESC_RESET_SYS_LINE 0x55 /* U */ +#define ESC_LOCK_SYS_LINE 0x54 /* T */ +#define ESC_UNLOCK_SYS_LINE 0x55 /* U */ #define ESC_LOCK_DISPLAY 0x56 /* V */ #define ESC_UNLOCK_DISPLAY 0x57 /* W */ #define ESC_WIDTH_40 0x63 /* c */ @@ -74,44 +74,46 @@ class VTTDockVid : public Fl_Widget { public: - VTTDockVid(int x, int y, int w, int h); - ~VTTDockVid(); - - virtual void WriteData(unsigned char data); - - virtual void Clear(void); - - int MultFact; - int DisplayMode; - int SolidChars; - int DispHeight; - - int gRectsize; - int gXoffset; - int gYoffset; - int m_BezelTop; - int m_BezelLeft; - int m_BezelBottom; - int m_BezelRight; - int m_BezelTopH; - int m_BezelBottomH; - int m_BezelLeftW; - int m_BezelRightW; - int m_HasTopChassis; - int m_HasBottomChassis; - int m_HasLeftChassis; - int m_HasRightChassis; - - int m_FrameColor; - int m_DetailColor; - int m_BackgroundColor; - int m_PixelColor; - int m_LabelColor; - - char m_HaveMouse; + VTTDockVid(int x, int y, int w, int h); + ~VTTDockVid(); + + virtual void WriteData(unsigned char data); + + virtual void Clear(void); + virtual void SetMultFact(int multfact); + + int MultFact; + int DisplayMode; + int SolidChars; + int DispHeight; + + int gRectsize; + int gXoffset; + int gYoffset; + int m_BezelTop; + int m_BezelLeft; + int m_BezelBottom; + int m_BezelRight; + int m_BezelTopH; + int m_BezelBottomH; + int m_BezelLeftW; + int m_BezelRightW; + int m_HasTopChassis; + int m_HasBottomChassis; + int m_HasLeftChassis; + int m_HasRightChassis; + int m_LabelLocked; + + int m_FrameColor; + int m_DetailColor; + int m_BackgroundColor; + int m_PixelColor; + int m_LabelColor; + + char m_HaveMouse; protected: - virtual void draw(); + virtual void draw(); void draw_pixels(); void SetByte(int line, int col, uchar value); void CalcScreenCoords(void); @@ -119,12 +121,12 @@ class VTTDockVid : public Fl_Widget void XorCursor(void); void Help(void); void Scroll(void); - __inline void drawpixel(int x, int y, int color); - virtual void draw_static(); + __inline void drawpixel(int x, int y, int color); + virtual void draw_static(); virtual int handle(int event); - int m_MyFocus; - uchar pixdata[200][480]; + int m_MyFocus; + uchar pixdata[200][480]; int m_CurX, m_CurY; int m_Cursor; From 1578a8165d6b2e41ba726494465af11e5cb4dbfc Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 14 Mar 2020 07:16:19 -0700 Subject: [PATCH 301/327] Fixed warning in display.cpp with fl_choice call for Cold Boot. --- src/display.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/display.cpp b/src/display.cpp index 0f09640..706b31c 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -755,7 +755,8 @@ void cb_coldBoot (Fl_Widget* w, void*) if (gReMem) { if (w != NULL) - a = fl_choice("Cold Boot. Reload System ROM too?", "Cancel", "Yes", "No", NULL); + //a = fl_choice("Cold Boot. Reload System ROM too?", "Cancel", "Yes", "No", NULL); + a = fl_choice("Cold Boot. Reload System ROM too?", "Cancel", "Yes", "No"); else a = 2; if (a == 1) From 34e04db0b6397d4f9384f7e58577962795426340 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 14 Mar 2020 07:32:58 -0700 Subject: [PATCH 302/327] Updated tpddserver class to derive from new VTServer base class. This is in preparation for adding a Cassette server (which will also derive from VTServer). --- src/tpddserver.h | 6 ++-- src/tpddserverlog.h | 11 +++--- src/vtserver.h | 88 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 src/vtserver.h diff --git a/src/tpddserver.h b/src/tpddserver.h index 2ce4291..97e4e6d 100644 --- a/src/tpddserver.h +++ b/src/tpddserver.h @@ -30,6 +30,8 @@ #ifndef TPDDSERVER_H #define TPDDSERVER_H +#include "vtserver.h" + /* ============================================================================ Define call routines to hook to serial port functionality. @@ -184,7 +186,7 @@ Define the TPDD Server class. This will be passed around in C land as a void* context. ===================================================================== */ -class VTTpddServer +class VTTpddServer : public VTServer { public: VTTpddServer(); @@ -212,7 +214,7 @@ class VTTpddServer m_logEnabled = TRUE; } void UnregisterServerLog(VTTpddServerLog* pServerLog) { m_logEnabled = FALSE; m_pServerLog = NULL; } - int IsCmdlineState(void); + virtual int IsCmdlineState(void); private: void StateCmdline(char data);// Process data while in Cmdline state diff --git a/src/tpddserverlog.h b/src/tpddserverlog.h index 85dd1b6..c19e1ca 100644 --- a/src/tpddserverlog.h +++ b/src/tpddserverlog.h @@ -64,6 +64,8 @@ class VTTpddLogEntry : public VTObject char* m_pData; // Pointer to the data }; +class VTServer; + /* ===================================================================== Define the TPDD Server Log class. @@ -80,8 +82,9 @@ class VTTpddServerLog : public Fl_Double_Window int handle(int event); void resize(int x, int y, int w, int h); - void Server(VTTpddServer* pServer) { m_pServer = pServer; } + void Server(VTServer* pServer) { m_pServer = pServer; } void LogData(char data, int rxTx); + void LogBreak() { m_lastWasRx = !m_lastWasRx; } void ResetContent(void); void DisableCallback(void); void AutoscrollCallback(void); @@ -101,15 +104,15 @@ class VTTpddServerLog : public Fl_Double_Window void SetScrollSizes(void); // TPDD Server interface - VTTpddServer* m_pServer; // Pointer to the TpddServer we are logging + VTServer* m_pServer; // Pointer to the TpddServer we are logging int m_enabled; // Indicates if the log is enabled // RX and TX buffer control int m_lastWasRx; // Indicates if last logged data was RX int m_rxCount; // Count of data in rx buffer int m_txCount; // Count of data in tx buffer - char m_rxBuffer[256]; // RX accumulation buffer - char m_txBuffer[256]; // TX accumulation buffer + char m_rxBuffer[32768]; // RX accumulation buffer + char m_txBuffer[32768]; // TX accumulation buffer // The actual log VTObArray m_log; // Array of log entries diff --git a/src/vtserver.h b/src/vtserver.h new file mode 100644 index 0000000..79b4e9a --- /dev/null +++ b/src/vtserver.h @@ -0,0 +1,88 @@ +/* vtserver.h */ + +/* $Id: vtserver.h,v 1.3 2015/02/24 20:19:17 kpettit1 Exp $ */ + +/* +* Copyright 2016 Ken Pettit +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +*/ + +#ifndef VTSERVER_H +#define VTSERVER_H + +/* +============================================================================ +Define call routines to hook to serial port functionality. +============================================================================ +*/ +// If compiled in cpp file, make declarations extern "C" +#ifdef __cplusplus + +#include +#include "MString.h" +#include "MStringArray.h" + +class VTTpddServerLog; + +extern "C" +{ +#endif /* __cplusplus */ + +// Close the extern "C" block if compiling a cpp file +#ifdef __cplusplus +} + +// Logging defines +#define SERVER_LOG_RX 0 +#define SERVER_LOG_TX 1 + +/* +===================================================================== +Define the TPDD Server class. This will be passed around in C land +as a void* context. +===================================================================== +*/ +class VTServer +{ +public: + VTServer() { m_pServerLog = NULL; m_logEnabled = TRUE; } + ~VTServer() {} + + // Methods + virtual void RegisterServerLog(VTTpddServerLog* pServerLog) { m_pServerLog = pServerLog; + m_logEnabled = TRUE; } + virtual void UnregisterServerLog(VTTpddServerLog* pServerLog) { m_logEnabled = FALSE; + m_pServerLog = NULL; } + virtual int IsCmdlineState(void) = 0; + +protected: + virtual void LogData(char data, int rxTx) = 0; + + VTTpddServerLog* m_pServerLog; // Server log object for logging data + int m_logEnabled; +}; + +#endif /* __cplusplus */ + +#endif /* VTSERVER_H */ + From 3993572632ff9d1be339bfea4f943c028ce9db83 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 25 Mar 2020 07:22:30 -0700 Subject: [PATCH 303/327] Fixed Save To Host ASCII mode bug where ASCII values > 127 in quotes were being incorrectly detokenized into BASIC keywords. --- src/file.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/file.cpp b/src/file.cpp index 035f743..efccdac 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -1378,8 +1378,27 @@ void save_file(model_t_files_t *pFile) // Get next byte ch = get_memory8(addr1++); + if (ch == '"') + { + // Write the quote + fwrite(&ch, 1, 1, fd); + ch = get_memory8(addr1); + + // Loop to end of the quote, writing bytes directly + while (ch != '"') + { + fwrite(&ch, 1, 1, fd); + addr1++; + ch = get_memory8(addr1); + } + + // Write the final ending quote + fwrite(&ch, 1, 1, fd); + addr1++; + } + // Check if byte is ':' - if (ch == ':') + else if (ch == ':') { // Get next character ch = get_memory8(addr1); @@ -1403,6 +1422,8 @@ void save_file(model_t_files_t *pFile) ch = ':'; fwrite(&ch, 1, 1, fd); } + + // Check for keyword expansion else if (ch > 0x7F) { fprintf(fd, "%s", gKeywordTable[ch & 0x7F]); From 88966bc344b4ccd489e6d9cda2afe7b46265c95d Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Wed, 25 Mar 2020 08:15:26 -0700 Subject: [PATCH 304/327] Added -ldflags to FLTK env variables in GNUMakefile. --- GNUmakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index 83a178a..c197d7b 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -41,7 +41,7 @@ endif # ============================= FLTKCONFIG = $(shell which fltk-config) ifneq ($(FLTKCONFIG),) -FLTKLIB = $(shell $(FLTKCONFIG) --use-images --libs) +FLTKLIB = $(shell $(FLTKCONFIG) --use-images --ldflags --libs) CFLAGS += $(shell $(FLTKCONFIG) --use-images --cflags) CPPFLAGS += $(shell $(FLTKCONFIG) --use-images --cxxflags) endif From 50c71e646d58782613d6c4eec5b0c2e6b2c5853c Mon Sep 17 00:00:00 2001 From: bkw777 Date: Fri, 27 Mar 2020 00:00:22 -0400 Subject: [PATCH 305/327] remove no-longer-working build targets from osx --- Darwin.mk | 4 ++-- GNUmakefile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Darwin.mk b/Darwin.mk index 9bde65e..9a16194 100644 --- a/Darwin.mk +++ b/Darwin.mk @@ -1,5 +1,5 @@ -CFLAGS += -D__unix__ -I/usr/include/malloc/ -arch i386 -arch ppc -CPPFLAGS += -D__unix__ -I/usr/include/malloc/ -arch i386 -arch ppc +CFLAGS += -D__unix__ -I/usr/include/malloc/ +CPPFLAGS += -D__unix__ -I/usr/include/malloc/ FLTKDIR ?= /usr/local/bin #post: diff --git a/GNUmakefile b/GNUmakefile index c197d7b..fba6cee 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -64,7 +64,7 @@ LIBFILES = -lstdc++ $(FLTKLIB) -lm -lc -lX11 -lpthread -ldl -ljpeg -lpng -lXft - # ============================= # Defines for MacOSX builds # ============================= -MACLDFLAGS = $(shell $(FLTKCONFIG) --use-images --ldflags) -arch i386 -arch ppc +MACLDFLAGS = $(shell $(FLTKCONFIG) --use-images --ldflags) MACLIBFILES = -lstdc++ `$(FLTKCONFIG) --use-images --ldstaticflags --use-images` --lm -lpthread # ==================================== @@ -129,7 +129,7 @@ else if test -f /Developer/Tools/Rez; then \ g++ $(MACLDFLAGS) $(OBJECTS) $(MACLIBFILES) -o $@ ; \ else \ - $(CC) $(LDFLAGS) $(OBJECTS) $(LIBFILES) -o $@ ; \ + $(CC) $(OBJECTS) $(LDFLAGS) $(LIBFILES) -o $@ ; \ fi; cd .. From 9054238c5c682d22fe898a84e6b421f022ecfbf9 Mon Sep 17 00:00:00 2001 From: bkw777 Date: Fri, 27 Mar 2020 00:01:37 -0400 Subject: [PATCH 306/327] gitignore build results --- .gitignore | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..516f097 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# build results +.dep/ +obj/ +virtualt +vt_client From d28673196e7c0b54b4a527dd145229722762a8f7 Mon Sep 17 00:00:00 2001 From: bkw777 Date: Fri, 27 Mar 2020 00:04:16 -0400 Subject: [PATCH 307/327] array sizes --- src/autofile.cpp | 2 +- src/fileprint.cpp | 2 +- src/m100emu.c | 10 +++++----- src/memory.c | 16 ++++++++-------- src/watchtable.h | 4 ++-- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/autofile.cpp b/src/autofile.cpp index 6e3debd..74bfd2a 100644 --- a/src/autofile.cpp +++ b/src/autofile.cpp @@ -70,7 +70,7 @@ MString VTAutoFile::GenFilename() int len, c; int seq = 0; int seqFound = FALSE; - char page[10]; + char page[11]; FILE* fd; const char* formatCode; diff --git a/src/fileprint.cpp b/src/fileprint.cpp index 3cab243..5b1026e 100644 --- a/src/fileprint.cpp +++ b/src/fileprint.cpp @@ -386,7 +386,7 @@ MString VTFilePrint::GenFilename() int len, c; int seq = 0; int seqFound = FALSE; - char page[10]; + char page[11]; FILE* fd; // Build the filename by parsing the format & looking for % modifiers diff --git a/src/m100emu.c b/src/m100emu.c index 64b1b22..78015a7 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -634,9 +634,9 @@ check_installation: This routine checks that VirtualT is properly installed void check_installation(void) { int model, len; - char localpath[256]; - char roms_path[512]; - char errors[256]; + char localpath[257]; + char roms_path[513]; + char errors[1025]; FILE *fd, *fd2; /* Test if Mac OSX and no path specified */ @@ -720,8 +720,8 @@ void check_installation(void) if (strlen(errors) > 0) { - sprintf(localpath, "No ROM file for %s", errors); - show_error(localpath); + sprintf(errors, "No ROM file for %s", localpath); + show_error(errors); } } diff --git a/src/memory.c b/src/memory.c index 4ddb656..9b1f5fd 100644 --- a/src/memory.c +++ b/src/memory.c @@ -1064,7 +1064,7 @@ void save_remem_ram(void) /* Print error if unable to open the file */ if (fd == NULL) { - char msg[100]; + char msg[513]; sprintf(msg, "Could not save Remem file %s", mem_setup.remem_file); show_error(msg); return; @@ -1104,7 +1104,7 @@ void save_rampac_ram(void) /* Print error if unable to open the file */ if (fd == NULL) { - char msg[100]; + char msg[513]; sprintf(msg, "Could not save Rampac file %s", mem_setup.rampac_file); show_error(msg); return; @@ -1143,7 +1143,7 @@ void save_rex2_ram(void) /* Print error if unable to open the file */ if (fd == NULL) { - char msg[100]; + char msg[513]; sprintf(msg, "Could not save REX2 RAM file %s", mem_setup.rex2_ram_file); show_error(msg); return; @@ -1179,7 +1179,7 @@ void save_rex_flash(void) /* Print error if unable to open the file */ if (fd == NULL) { - char msg[100]; + char msg[513]; sprintf(msg, "Could not save REX file %s", mem_setup.rex_flash_file); show_error(msg); return; @@ -1325,7 +1325,7 @@ void load_remem_ram(void) /* Print error if unable to open the file */ if (fd == NULL) { - char msg[100]; + char msg[513]; sprintf(msg, "Could not open Remem file %s", mem_setup.remem_file); show_error(msg); return; @@ -1400,7 +1400,7 @@ void load_rampac_ram(void) /* Print error if unable to open the file */ if (fd == NULL) { - char msg[100]; + char msg[513]; sprintf(msg, "Could not open Rampac file %s", mem_setup.rampac_file); show_error(msg); return; @@ -1437,7 +1437,7 @@ void load_rex_flash(void) /* Print error if unable to open the file */ if (fd == NULL) { - char msg[100]; + char msg[513]; sprintf(msg, "Could not open REX file %s", mem_setup.rex_flash_file); show_error(msg); return; @@ -1477,7 +1477,7 @@ void load_rex2_ram(void) /* Print error if unable to open the file */ if (fd == NULL) { - char msg[100]; + char msg[513]; sprintf(msg, "Could not open REX2 RAM file %s", mem_setup.rex2_ram_file); show_error(msg); return; diff --git a/src/watchtable.h b/src/watchtable.h index e3ff249..397b0ba 100644 --- a/src/watchtable.h +++ b/src/watchtable.h @@ -173,8 +173,8 @@ class VT_Watch_Table : public Fl_Widget watchtable_color_t m_colors; int m_FontSize; - int m_ColStart[VT_WATCH_TABLE_COL_COUNT]; - int m_ColWidth[VT_WATCH_TABLE_COL_COUNT]; + int m_ColStart[VT_WATCH_TABLE_COL_COUNT+1]; + int m_ColWidth[VT_WATCH_TABLE_COL_COUNT+1]; double m_WidthPercentage[VT_WATCH_TABLE_COL_COUNT]; int m_SelLine; int m_DblclkX, m_DblclkY; From e999a071f420cc13b447e944897b93cfb7c4fb9a Mon Sep 17 00:00:00 2001 From: bkw777 Date: Fri, 27 Mar 2020 00:05:14 -0400 Subject: [PATCH 308/327] replace fl_wait() with Fl::wait() --- src/remote.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/remote.cpp b/src/remote.cpp index de7d41e..4b59833 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -144,7 +144,6 @@ void remote_set_speed(int speed); int str_to_i(const char *pStr); void remote_switch_model(int model); extern int fullspeed; -extern int fl_wait(double); extern void simulate_keydown(int key); extern void simulate_keyup(int key); extern Fl_Preferences virtualt_prefs; @@ -741,7 +740,7 @@ std::string cmd_step(ServerSocket& sock, std::string& args) unlock_remote(); while (gSingleStep) - fl_wait(0.001); + Fl::wait(0.001); } return gOk; @@ -825,7 +824,7 @@ std::string cmd_step_over(ServerSocket& sock, std::string& args) // Wait for the processor to stop again while (!gStopped) - fl_wait(0.001); + Fl::wait(0.001); // gRemoteBreak[addr] = saveBrk; gStepOverBreak = 0; @@ -839,7 +838,7 @@ std::string cmd_step_over(ServerSocket& sock, std::string& args) // Wait for single step to complete while (gSingleStep) - fl_wait(0.001); + Fl::wait(0.001); } } @@ -1635,13 +1634,13 @@ std::string cmd_list_break(ServerSocket& sock, std::string& args) void key_delay(void) { - //fl_wait(0.01); + //Fl::wait(0.01); while (gSimKey != 0) - fl_wait(0.001); + Fl::wait(0.001); while (gDelayUpdateKeys) - fl_wait(0.001); - //fl_wait(0.01); + Fl::wait(0.001); + //Fl::wait(0.01); } /* ======================================================= @@ -1997,7 +1996,7 @@ std::string cmd_model(ServerSocket& sock, std::string& args) else return gParamError; - fl_wait(0.25); + Fl::wait(0.25); return gOk; } From ef24513593b3a27fcd9a0ac1ba1d6c3f5fb2cae8 Mon Sep 17 00:00:00 2001 From: bkw777 Date: Fri, 27 Mar 2020 03:50:19 -0400 Subject: [PATCH 309/327] don't overwrite errors in check_installation() --- src/m100emu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/m100emu.c b/src/m100emu.c index 78015a7..d916990 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -720,7 +720,8 @@ void check_installation(void) if (strlen(errors) > 0) { - sprintf(errors, "No ROM file for %s", localpath); + strcat(errors, "\nNo ROM file for "); + strcat(errors, localpath); show_error(errors); } } From 065b3f254e4079caf91c293584a7848869b688a4 Mon Sep 17 00:00:00 2001 From: bkw777 Date: Fri, 27 Mar 2020 13:44:15 -0400 Subject: [PATCH 310/327] revert check_installation(), except declare large localpath[] --- src/m100emu.c | 7 +++---- src/remote.cpp | 2 -- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/m100emu.c b/src/m100emu.c index d916990..ca15bca 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -634,7 +634,7 @@ check_installation: This routine checks that VirtualT is properly installed void check_installation(void) { int model, len; - char localpath[257]; + char localpath[2049]; char roms_path[513]; char errors[1025]; FILE *fd, *fd2; @@ -720,9 +720,8 @@ void check_installation(void) if (strlen(errors) > 0) { - strcat(errors, "\nNo ROM file for "); - strcat(errors, localpath); - show_error(errors); + sprintf(localpath, "No ROM file for %s", errors); + show_error(localpath); } } diff --git a/src/remote.cpp b/src/remote.cpp index 4b59833..a9b8318 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -1634,13 +1634,11 @@ std::string cmd_list_break(ServerSocket& sock, std::string& args) void key_delay(void) { - //Fl::wait(0.01); while (gSimKey != 0) Fl::wait(0.001); while (gDelayUpdateKeys) Fl::wait(0.001); - //Fl::wait(0.01); } /* ======================================================= From 0cc2c4b80055df47398692509b43218105410de4 Mon Sep 17 00:00:00 2001 From: bkw777 Date: Fri, 27 Mar 2020 14:03:32 -0400 Subject: [PATCH 311/327] yet another redo of error msg in check_installation(), per SJH suggestion --- src/m100emu.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/m100emu.c b/src/m100emu.c index ca15bca..8a7d4cb 100644 --- a/src/m100emu.c +++ b/src/m100emu.c @@ -634,7 +634,7 @@ check_installation: This routine checks that VirtualT is properly installed void check_installation(void) { int model, len; - char localpath[2049]; + char localpath[257]; char roms_path[513]; char errors[1025]; FILE *fd, *fd2; @@ -720,8 +720,9 @@ void check_installation(void) if (strlen(errors) > 0) { - sprintf(localpath, "No ROM file for %s", errors); - show_error(localpath); + char errmsg[1048]; + sprintf(errmsg, "No ROM file for %s", errors); + show_error(errmsg); } } From 30587f01f095c75e3179b4dd1c694e95d78bec45 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Thu, 26 Mar 2020 19:20:45 -0700 Subject: [PATCH 312/327] Fixing compiler warnings in src/chargen.cpp. --- src/chargen.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/chargen.cpp b/src/chargen.cpp index 4f30b58..9ede039 100644 --- a/src/chargen.cpp +++ b/src/chargen.cpp @@ -726,7 +726,8 @@ void VTCharacterGen::Load(void) data[0] = 0x80; else data[0] = 0; */ - m_pCharTable->PutCharData(index, data); + if (readlen > 0) + m_pCharTable->PutCharData(index, data); } // Close the file @@ -742,7 +743,7 @@ Save data to a file */ void VTCharacterGen::Save(int format) { - Flu_File_Chooser* fc; + Flu_File_Chooser* fc = NULL; unsigned char data[12]; int index, len, c; char ch; @@ -781,7 +782,7 @@ void VTCharacterGen::Save(int format) } // Loop until a file selected or cancel - while (TRUE) + while (fc) { // Show the file dialog fc->show(); @@ -826,6 +827,7 @@ void VTCharacterGen::Save(int format) // Test if filename has an extension filename = fc->value(); len = filename.GetLength(); + ch = 0; for (c = len - 1; c >= 0; c--) { ch = filename[c]; @@ -925,7 +927,7 @@ void VTCharacterGen::UpdatePicaView(void) char byte; // Clear the pixelData map - for (c = 0; c < sizeof(m_PicaPixelData); c++) + for (c = 0; c < (int) sizeof(m_PicaPixelData); c++) m_PicaPixelData[c] = 0; // Fill in pixel @@ -954,7 +956,7 @@ void VTCharacterGen::UpdateExpandView(void) char byte; // Clear the pixelData map - for (c = 0; c < sizeof(m_ExpandPixelData); c++) + for (c = 0; c < (int) sizeof(m_ExpandPixelData); c++) m_ExpandPixelData[c] = 0; // Fill in pixel @@ -983,7 +985,7 @@ void VTCharacterGen::UpdateEnhanceView(void) char byte; // Clear the pixelData map - for (c = 0; c < sizeof(m_EnhancePixelData); c++) + for (c = 0; c < (int) sizeof(m_EnhancePixelData); c++) m_EnhancePixelData[c] = 0; // Fill in pixel @@ -1018,7 +1020,7 @@ void VTCharacterGen::UpdateDblStrikeView(void) char byte; // Clear the pixelData map - for (c = 0; c < sizeof(m_DblStrikePixelData); c++) + for (c = 0; c < (int) sizeof(m_DblStrikePixelData); c++) m_DblStrikePixelData[c] = 0; // Fill in pixel @@ -1048,7 +1050,7 @@ void VTCharacterGen::UpdateDblEnhanceView(void) char byte; // Clear the pixelData map - for (c = 0; c < sizeof(m_DblEnhancePixelData); c++) + for (c = 0; c < (int) sizeof(m_DblEnhancePixelData); c++) m_DblEnhancePixelData[c] = 0; // Fill in pixel @@ -1097,9 +1099,7 @@ VTCharTable::VTCharTable(int x, int y, int w, int h, const char *title) : Fl_Box(FL_FRAME_BOX, x, y, w, h, title) { int c, i; - int j; - j = 0; for (c = 0; c < 256; c++) for (i = 0; i < 12; i++) m_Data[c][i] = 0; From 46db8588ba67ed74e89d37afcac5b37cbd8dd574 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Thu, 26 Mar 2020 19:21:28 -0700 Subject: [PATCH 313/327] Fixing compiler warnings in Linux in src/sound.c. --- src/sound.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/sound.c b/src/sound.c index 5d04248..438e989 100644 --- a/src/sound.c +++ b/src/sound.c @@ -51,7 +51,9 @@ #include "sound.h" #include "m100emu.h" +#ifdef _WIN32 #pragma comment(lib, "winmm.lib") +#endif #define BLOCK_SIZE 1024 #define BLOCK_COUNT 10 @@ -84,17 +86,21 @@ static int gReqOut = 0; unsigned short gToneBuf[BLOCK_SIZE >> 1] ; /* input buffer */ unsigned short gpOneHertz[SAMPLING_RATE]; + +#ifdef _WIN32 static int gPlayTone = TONE_STOPPED; static int gToneFreq = 0; +static int gOneHzPtr = 0; +static double gDecayLevel = DECAY_MAX_LEVEL; +static int gLastToneFreq = 0; +static UINT64 gPlayCycle = 0; +#endif + static int gExit = 0; static int gBeepOn = 0; -static int gOneHzPtr = 0; static double gToneDivisor = 1.0; -static double gDecayLevel = DECAY_MAX_LEVEL; static double gDecayStep = 0.008; -static int gLastToneFreq = 0; static UINT64 spkr_cycle = 0; -static UINT64 gPlayCycle = 0; int sound_enable = 1; #ifdef _WIN32 From 1690ce06ab6c9356e6129095f69c24f6cf42707b Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 28 Mar 2020 06:21:59 -0700 Subject: [PATCH 314/327] Changes to assembler and parser to fix warnings with -Wall. --- src/a85parse.cpp | 7 ++--- src/assemble.cpp | 74 +++++++++++++++++++++++------------------------- 2 files changed, 37 insertions(+), 44 deletions(-) diff --git a/src/a85parse.cpp b/src/a85parse.cpp index 8f20c25..c73b50d 100644 --- a/src/a85parse.cpp +++ b/src/a85parse.cpp @@ -67,7 +67,7 @@ char ss[32][256]; // String Stack; CMacro* gMacroStack[32]; // Macro Stack; int ms_idx = 0; // Macro Stack Index char integer[64]; // Integer storage space -char int_len = 0; // Integer string length +unsigned char int_len = 0; // Integer string length int ss_idx = 0; // String Stack Index int ss_len = 0; // SS string length int ss_addr = 0; // Address at start of literal name @@ -318,9 +318,6 @@ void syntax_error(const char *token_name) #define GET_INPUT {(PCB).input_code = (gAsm->m_fd != 0 && !gAbort) ? \ gAsm->preprocessor() : 0; } -// fgetc(gAsm->m_fd) : 0; if ((PCB).input_code == 13) (PCB).input_code = fgetc(gAsm->m_fd);\ -// } - #define SYNTAX_ERROR { syntax_error(TOKEN_NAMES[(PCB).error_frame_token]); } /* @@ -2061,7 +2058,7 @@ static int ag_look_ahead(void) { static void ag_get_key_word(int ag_k) { int save_index = (PCB).rx; const unsigned char *sp; - int ag_ch; + int ag_ch=0; while (1) { switch (ag_key_act[ag_k]) { case ag_cf_end_key: diff --git a/src/assemble.cpp b/src/assemble.cpp index b787fcb..77ccc93 100644 --- a/src/assemble.cpp +++ b/src/assemble.cpp @@ -208,6 +208,7 @@ int VTAssembler::PerformSubstitution(CMacro* pMacro, const char *pLoc) // Find all arguments in the macro invocation. First skip white space len = paren = quote = 0; ptr = pEndName; + quoteChar = 0; while (*ptr == ' ' || *ptr == '\t') ptr++; if (*ptr == '(') @@ -2932,7 +2933,6 @@ void VTAssembler::preproc_ifdef(const char* name, int negate) { MString err, strName; CSymbol* dummy; - CMacro* pMacro; int defined; // Update line number @@ -2954,7 +2954,7 @@ void VTAssembler::preproc_ifdef(const char* name, int negate) m_IfStat[++m_IfDepth] = IF_STAT_EVAL_ERROR; // Ensure our #ifdef stack depth hasn't overflowed - if (m_IfDepth >= sizeof(m_IfStat)) + if (m_IfDepth >= (int) sizeof(m_IfStat)) { m_IfDepth--; err.Format("Error in line %d(%s): Too many nested ifs", m_Line, @@ -2965,32 +2965,23 @@ void VTAssembler::preproc_ifdef(const char* name, int negate) { m_IfStat[m_IfDepth] = IF_STAT_DONT_ASSEMBLE; strName = name; - // Test if it is a CMacro - // if (LookupMacro(strName, pMacro)) - // { - // if (!negate) - // m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; - // } - // else - { - defined = LookupSymbol(strName, dummy); - if (!defined) - { - int def; - - for (def = 0; def < m_Defines.GetSize(); def++) - { - if (((CMacro *) m_Defines[def])->m_Name == strName) - { - defined = 1; - break; - } - } - } - - if ((defined && !negate) || (!defined && negate)) - m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; - } + defined = LookupSymbol(strName, dummy); + if (!defined) + { + int def; + + for (def = 0; def < m_Defines.GetSize(); def++) + { + if (((CMacro *) m_Defines[def])->m_Name == strName) + { + defined = 1; + break; + } + } + } + + if ((defined && !negate) || (!defined && negate)) + m_IfStat[m_IfDepth] = IF_STAT_ASSEMBLE; } } @@ -3223,6 +3214,7 @@ int VTAssembler::preproc_macro() replace.Insert(pos, (char *) (const char *) arg); pos += arg.GetLength(); } + (void) wholeMatch; } } } @@ -3265,7 +3257,7 @@ void VTAssembler::directive_if(int inst) else m_IfStat[++m_IfDepth] = IF_STAT_EVAL_ERROR; - if (m_IfDepth >= sizeof(m_IfStat)) + if (m_IfDepth >= (int) sizeof(m_IfStat)) { m_IfDepth--; err.Format("Error in line %d(%s): Too many nested ifs", m_Line, @@ -3429,10 +3421,10 @@ int VTAssembler::Assemble() { MString err; int c, count, len, x; - int size; + int size = 0; CInstruction* pInst; CRelocation* pRel; - CExtern * pExt; + CExtern * pExt = NULL; CExpression* pExp; VTObArray* pExpList; MStringArray* pNameList; @@ -3878,6 +3870,7 @@ int VTAssembler::Assemble() valid = 1; rel_mask = 0; extern_label = 0; + size = 0; if (Evaluate(pExp->m_Equation, &value, 1)) { // Equation evaluated to a value. Check if it is @@ -4008,11 +4001,14 @@ int VTAssembler::Assemble() int y, str_len; if (pInst->m_ID == INST_DW) { - str_len = pExt->m_Name.GetLength(); - for (y = 0; y < str_len; y++) - m_ActiveSeg->m_AsmBytes[m_Address++] = pExt->m_Name[y]; - if (str_len & 1) - m_ActiveSeg->m_AsmBytes[m_Address++] = 0; + if (pExt) + { + str_len = pExt->m_Name.GetLength(); + for (y = 0; y < str_len; y++) + m_ActiveSeg->m_AsmBytes[m_Address++] = pExt->m_Name[y]; + if (str_len & 1) + m_ActiveSeg->m_AsmBytes[m_Address++] = 0; + } } else { @@ -4152,7 +4148,7 @@ int VTAssembler::CreateObjFile(const char *filename, const char *sourcefile) const int aseg_off = 19; const int cseg_off = 25; const int dseg_off = 31; - int eqtab_off; + int eqtab_off = 0; int len, strtab_start; int first_aseg_idx, first_cseg_idx, first_dseg_idx; int shidx, type, bind; @@ -5124,7 +5120,7 @@ void VTAssembler::ParseExternalDefines(void) int startIndex, endIndex; MString def, sval; int valIdx, len; - int value = -1; + //int value = -1; // If zero length then we're done if ((len = m_ExtDefines.GetLength()) == 0) @@ -5896,7 +5892,7 @@ CSegment::CSegment(const char *name, int type, CModule* initialMod) m_UsedAddr->pNext = NULL; m_Index = m_Count = 0; - for (x = 0; x < sizeof(m_AsmBytes); x++) + for (x = 0; x < (int) sizeof(m_AsmBytes); x++) m_AsmBytes[x] = 0; // Initialize the active Addr range to the first in the list From b401e8d9077b5bac808b342b2cbe84394e2f60a2 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 28 Mar 2020 06:24:06 -0700 Subject: [PATCH 315/327] Minor fixes to src/fileview.cpp to fix warnings with -Wall. --- src/fileview.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/fileview.cpp b/src/fileview.cpp index 9a32ca0..ea5a949 100644 --- a/src/fileview.cpp +++ b/src/fileview.cpp @@ -145,6 +145,7 @@ void display_file(int index) case TYPE_BA: // Get first BASIC line pointer addr1 = pfile->address; + addr2 = addr1; // Calculate the maximum linenumber length while (get_memory16(addr1) != 0) @@ -373,7 +374,7 @@ Callback routine when a file is selected */ void cb_FileSelect(Fl_Widget* w, void*) { - int index, x, usage, lowram; + int index, x, usage = 0, lowram; file_view_files_t *pfile; lowram = get_memory16(gStdRomDesc->sLowRam); @@ -395,6 +396,8 @@ void cb_FileSelect(Fl_Widget* w, void*) case TYPE_CO: usage = FV_CO_FILE_COLOR; break; + default: + return; } gFvCtrl.pRAM->AddUsageEvent(pfile->address - lowram, pfile->address + pfile->size - lowram, usage); From 22a40e2488bb8fa1792dfb49b0e46eadca803a09 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 28 Mar 2020 06:26:44 -0700 Subject: [PATCH 316/327] Minor updates to src/disassemble.cpp to fix warnings with -Wall. --- src/disassemble.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/disassemble.cpp b/src/disassemble.cpp index 36f3923..f012e85 100644 --- a/src/disassemble.cpp +++ b/src/disassemble.cpp @@ -958,7 +958,7 @@ void VTDis::Disassemble() int c, x, table; char line[200]; char arg[60]; - int addr, generate; + int addr = 0, generate; int rst7 = 0; int rst1 = 0; int oldSchool = m_oldSchool; // Indicates Old school style disassembly @@ -1529,7 +1529,7 @@ void VTDis::Disassemble() // Test if this opcode refers to an address which will need a label int j; - for (j = 0; j < sizeof(gLabelOpcodes); j++) + for (j = 0; j < (int) sizeof(gLabelOpcodes); j++) { // Test for label reference if (opcode == gLabelOpcodes[j]) @@ -2019,7 +2019,7 @@ void VTDis::CopyIntoMem(unsigned char *ptr, int len, int startAddr) for (c = 0; c < len; c++) { - if (c + startAddr < sizeof(m_memory)) + if (c + startAddr < (int) sizeof(m_memory)) m_memory[c + startAddr] = ptr[c]; } } @@ -2430,6 +2430,8 @@ static void cb_setupdlg_OK(Fl_Widget* w, void* pOpaque) if (fontSize < 6) fontSize = 6; } + else + fontSize = 12; // Get Inverse Highlight selection blackBackground = p->pInverseHilight->value(); From a245b8e03b337394a05c6cb0df00abe766d0557d Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 28 Mar 2020 06:32:54 -0700 Subject: [PATCH 317/327] Minor changes to fix unused var warnings with -Wall. --- src/tpddserverlog.cpp | 35 +++++++++-------------------------- src/watchtable.cpp | 7 ++----- 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/src/tpddserverlog.cpp b/src/tpddserverlog.cpp index 971633f..1189cd5 100644 --- a/src/tpddserverlog.cpp +++ b/src/tpddserverlog.cpp @@ -61,7 +61,6 @@ VTTpddServerLog* gpLog = NULL; static void cb_load_log(Fl_Widget* w, void* pOpaque); static void cb_save_log(Fl_Widget* w, void* pOpaque); -static void cb_setup_log(Fl_Widget* w, void* pOpaque); void cb_CpuRegs(Fl_Widget* w, void* pOpaque); void cb_Ide(Fl_Widget* w, void* pOpaque); @@ -73,7 +72,6 @@ static Fl_Menu_Item gServerLog_menuitems[] = { { "&File", 0, 0, 0, FL_SUBMENU }, { "Load from File...", 0, cb_load_log, 0 }, { "Save to File...", 0, cb_save_log, 0, 0 /*FL_MENU_DIVIDER*/ }, -// { "Setup...", 0, cb_setup_log, 0}, { 0 }, { "&Tools", 0, 0, 0, FL_SUBMENU }, @@ -199,15 +197,6 @@ static void cb_load_log(Fl_Widget* w, void* pOpaque) delete fc; } -/* -============================================================================ -Callback for setup dialog -============================================================================ -*/ -static void cb_setup_log(Fl_Widget* w, void* pOpaque) -{ -} - /* ============================================================================ Callback for redrawing the window @@ -645,20 +634,17 @@ void VTTpddServerLog::LogData(char data, int rxTx) AddNewEntry(TPDD_LOG_TX, m_txCount, m_txBuffer); m_txCount = 0; m_rxCount = 0; - //printf("\nRX: "); } m_lastWasRx = TRUE; m_rxBuffer[m_rxCount++] = data; // Test if the rxBuffer is full - if (m_rxCount == sizeof(m_rxBuffer)) + if (m_rxCount == (int) sizeof(m_rxBuffer)) { // Need to dump this packet and start a new one AddNewEntry(TPDD_LOG_RX, m_rxCount, m_rxBuffer); m_rxCount = 0; } - - //printf("%02X ", (unsigned char) data); } else { @@ -672,7 +658,6 @@ void VTTpddServerLog::LogData(char data, int rxTx) if (m_txCount > 0) AddNewEntry(TPDD_LOG_TX, m_txCount, m_txBuffer); m_txCount = m_rxCount = 0; - //printf("\nTX: "); } m_lastWasRx = FALSE; @@ -680,7 +665,7 @@ void VTTpddServerLog::LogData(char data, int rxTx) m_txBuffer[m_txCount++] = data; // Test if the TX buffer is full - if (m_txCount == sizeof(m_txBuffer)) + if (m_txCount == (int) sizeof(m_txBuffer)) { // Need to dump this packet and start a new one AddNewEntry(TPDD_LOG_TX, m_txCount, m_txBuffer); @@ -988,9 +973,7 @@ Loads the log data from a file. int VTTpddServerLog::LoadFile(MString filename) { FILE* fd; - int c, lineNo, rxTx; - //VTTpddLogEntry* pEntry; - //MString fmt, hexFmt; + int c, lineNo, rxTx = 0; char line[256]; char *ptr; @@ -1026,7 +1009,7 @@ int VTTpddServerLog::LoadFile(MString filename) // Loop for all data in the file lineNo = 0; - while (fgets(line, sizeof(line), fd) != NULL) + while (fgets(line, (int) sizeof(line), fd) != NULL) { // Start at beginning of line ptr = line; @@ -1061,7 +1044,7 @@ int VTTpddServerLog::LoadFile(MString filename) m_rxCount = 0; // Skip past the reference and find the ':' - while (*ptr != ':' && c < sizeof(line)) + while (*ptr != ':' && c < (int) sizeof(line)) { // Increment pointer and index ptr++; @@ -1069,7 +1052,7 @@ int VTTpddServerLog::LoadFile(MString filename) } // Test if ':' found - if (c >= sizeof(line) || *ptr != ':') + if (c >= (int) sizeof(line) || *ptr != ':') { // Not a trace file!! fl_message("This does not appear to be a valid file on line %d", lineNo); @@ -1099,7 +1082,7 @@ int VTTpddServerLog::LoadFile(MString filename) // Now we are pointing at the HEX data. Read all data from this line into // either the m_rxBuffer or m_txBuffer - while (*ptr != ' ' && *ptr != '\0' && c < sizeof(line)) + while (*ptr != ' ' && *ptr != '\0' && c < (int) sizeof(line)) { unsigned char val; @@ -1113,7 +1096,7 @@ int VTTpddServerLog::LoadFile(MString filename) if (rxTx) { m_txBuffer[m_txCount++] = val; - if (m_txCount >= sizeof(m_txBuffer)) + if (m_txCount >= (int) sizeof(m_txBuffer)) { AddNewEntry(TPDD_LOG_TX, m_txCount, m_txBuffer); m_txCount = 0; @@ -1122,7 +1105,7 @@ int VTTpddServerLog::LoadFile(MString filename) else { m_rxBuffer[m_rxCount++] = val; - if (m_rxCount >= sizeof(m_rxBuffer)) + if (m_rxCount >= (int) sizeof(m_rxBuffer)) { AddNewEntry(TPDD_LOG_RX, m_rxCount, m_rxBuffer); m_rxCount = 0; diff --git a/src/watchtable.cpp b/src/watchtable.cpp index 42c847c..42689d4 100644 --- a/src/watchtable.cpp +++ b/src/watchtable.cpp @@ -490,15 +490,13 @@ Draw the specified watch variable on the specified line */ void VT_Watch_Table::DrawWatch(CWatchDef* pVar, int line) { - int wx, wy, ww, wh; + int wy, wh; int xOffset, yOffset; int fontHeight, lines, topLine; char str[256]; // Get our dimensions - wx = m_pVarWindow->x(); wy = m_pVarWindow->y(); - ww = m_pVarWindow->w(); wh = m_pVarWindow->h(); fontHeight = fl_height(); lines = wh / fontHeight; @@ -1209,7 +1207,6 @@ Adds a new watch to the widget. int VT_Watch_Table::AddWatch(MString& name, MString& addr, int type, int region, int need_redraw) { - int index; CWatchDef* pWatch; // Create a new watch definition @@ -1224,7 +1221,7 @@ int VT_Watch_Table::AddWatch(MString& name, MString& addr, int type, pWatch->m_Region = region; // Add the watch to the list - index = m_WatchVars.Add(pWatch); + m_WatchVars.Add(pWatch); // Now draw the new item if needed SetScrollSizes(); From 4b419ba4d54d68ecd0bd31c7c974bea3a693f513 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 28 Mar 2020 06:37:18 -0700 Subject: [PATCH 318/327] Minor update to src/fl_action_icon.cpp to fix warnings with -Wall and to draw label using labelcolor() instead of FL_BLACK. --- src/fl_action_icon.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/fl_action_icon.cpp b/src/fl_action_icon.cpp index 25417c3..e722ee9 100644 --- a/src/fl_action_icon.cpp +++ b/src/fl_action_icon.cpp @@ -79,7 +79,7 @@ Handles the events sent to the action_icon */ int Fl_Action_Icon::handle(int event) { - int button, xp, yp; + int button; switch (event) { @@ -89,9 +89,6 @@ int Fl_Action_Icon::handle(int event) { case FL_LEFT_MOUSE: // Create a pop-up menu - xp = Fl::event_x(); - yp = Fl::event_y(); - m_pPopup->menu(m_pMenu); m_pPopup->popup(); } @@ -126,7 +123,7 @@ void Fl_Action_Icon::draw(void) // Draw the label window()->make_current(); - fl_color(FL_BLACK); + fl_color(labelcolor()); fl_draw(label(),tx, ty ); fl_pop_clip(); } From dbe4cc6e48efd7fd49a540a19168f5296eb3db78 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 28 Mar 2020 06:53:44 -0700 Subject: [PATCH 319/327] Fixed warnings with -Wall and code cleanup in src/highlight.cpp. --- src/highlight.cpp | 265 ++++++++++------------------------------- src/vt_client_main.cpp | 175 ++++++++++++++------------- 2 files changed, 153 insertions(+), 287 deletions(-) diff --git a/src/highlight.cpp b/src/highlight.cpp index 39d78e1..03af992 100644 --- a/src/highlight.cpp +++ b/src/highlight.cpp @@ -22,19 +22,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "multieditwin.h" //Editor colors -#if 0 -Fl_Color hl_plain = FL_BLACK; -Fl_Color hl_linecomment = FL_DARK_GREEN; -Fl_Color hl_blockcomment = FL_DARK_GREEN; -Fl_Color hl_string = FL_BLUE; -Fl_Color hl_directive = FL_DARK_MAGENTA; -Fl_Color hl_type = FL_DARK_RED; -Fl_Color hl_keyword = FL_BLUE; -Fl_Color hl_character = FL_DARK_RED; -Fl_Color hl_label = FL_DARK_BLUE; -Fl_Color background_color = FL_WHITE; -#endif - Fl_Color hl_plain = FL_WHITE; Fl_Color hl_linecomment = (Fl_Color) 95; Fl_Color hl_blockcomment = (Fl_Color) 93; @@ -315,12 +302,9 @@ void style_parse(const char *text, char *style, int length) for (current = *style, last = 0; length > 0; length --, text ++) { - //if ((current != 'C') && (current != 'D') && (current != 'E')) current = 'A'; - //if ((current == 'B')) current = 'A'; - if (current == 'A') { - // Check for directives, comments, strings, and keywords... + // Check for directives, comments, strings, and keywords... if (*text == '#') { // Set style to directive @@ -353,7 +337,7 @@ void style_parse(const char *text, char *style, int length) continue; } - else if (*text == '\"' /*| *text == '\''*/) + else if (*text == '\"') { current = 'D'; } @@ -363,48 +347,44 @@ void style_parse(const char *text, char *style, int length) current = 'H'; } - else if (!last && /*islower(*text) && */ *text > 0)// && -// !(isalnum(*(text-1)) || *(text-1)=='_')) + else if (!last && *text > 0) { // Might be a keyword... for (temp = text, bufptr = buf; ((*temp > 0) && (isalnum(*temp) || *temp=='_')) && bufptr < (buf + sizeof(buf) - 1); *bufptr++ = tolower(*temp++)); { - //if (!islower(*temp)) - { - *bufptr = '\0'; - bufptr = buf; + *bufptr = '\0'; + bufptr = buf; - if (bsearch(&bufptr, asm_code_types, sizeof(asm_code_types) / - sizeof(asm_code_types[0]), sizeof(asm_code_types[0]), compare_keywords)) + if (bsearch(&bufptr, asm_code_types, sizeof(asm_code_types) / + sizeof(asm_code_types[0]), sizeof(asm_code_types[0]), compare_keywords)) + { + while (text < temp) { - while (text < temp) - { - *style++ = 'F'; - text ++; - length --; - } - text --; - length ++; - last = 1; - continue; - - } - else if (bsearch(&bufptr, asm_code_keywords, sizeof(asm_code_keywords) / - sizeof(asm_code_keywords[0]), sizeof(asm_code_keywords[0]), compare_keywords)) + *style++ = 'F'; + text ++; + length --; + } + text --; + length ++; + last = 1; + continue; + + } + else if (bsearch(&bufptr, asm_code_keywords, sizeof(asm_code_keywords) / + sizeof(asm_code_keywords[0]), sizeof(asm_code_keywords[0]), compare_keywords)) + { + while (text < temp) { - while (text < temp) - { - *style++ = 'G'; - text ++; - length --; - } - - text --; - length ++; - last = 1; - continue; - } + *style++ = 'G'; + text ++; + length --; + } + + text --; + length ++; + last = 1; + continue; } } @@ -414,8 +394,6 @@ void style_parse(const char *text, char *style, int length) current = 'I'; } } - - } else if (current == 'C' && strncmp(text, "*/", 2) == 0) { @@ -450,14 +428,17 @@ void style_parse(const char *text, char *style, int length) else if (current == 'H') { // Continuing in char... - if (strncmp(text, "\\\'", 2) == 0) { + if (strncmp(text, "\\\'", 2) == 0) + { // Quoted end quote... *style++ = current; *style++ = current; text ++; length --; continue; - } else if (*text == '\'') { + } + else if (*text == '\'') + { // End quote... *style++ = current; current = 'A'; @@ -480,9 +461,9 @@ void style_parse(const char *text, char *style, int length) continue; } - // Copy style info... - if (current == 'A' && (*text == '{' || *text == '}')) *style++ = 'G'; + if (current == 'A' && (*text == '{' || *text == '}')) + *style++ = 'G'; else if(current == 'E' && strncmp(text, "/*", 2) == 0) { *style++ = 'C'; @@ -507,7 +488,8 @@ void style_parse(const char *text, char *style, int length) if (*text == '\n') { // Reset column and possibly reset the style - if (current != 'D' && current != 'C') current = 'A'; + if (current != 'D' && current != 'C') + current = 'A'; col = 0; } } //for @@ -556,107 +538,11 @@ void style_unfinished_cb(int, void*) } -// -// 'style_update()' - Update the style buffer... -// - -void -old_style_update( int pos, // I - Position of update - int nInserted, // I - Number of inserted chars - int nDeleted, // I - Number of deleted chars - int /*nRestyled*/, // I - Number of restyled chars - const char * /*deletedText*/,// I - Text that was deleted - void *cbArg) { // I - Callback data -/* int start, // Start of text - end; // End of text - char last, // Last style on line - stringdeleted=0; - char *style, // Style data - *text; // Text data -*/ /* - // If this is just a selection change, just unselect the style buffer... - if (nInserted == 0 && nDeleted == 0) { - stylebuf->unselect(); - return; - } - - // Track changes in the text buffer... - if (nInserted > 0) { - // Insert characters into the style buffer... - style = (char*)malloc(nInserted + 1); - memset(style, 'A', nInserted); - style[nInserted] = '\0'; - - stylebuf->replace(pos, pos + nDeleted, style); - free(style); - } else { - // Just delete characters in the style buffer... - if((stylebuf->character(pos) == 'D') || (stylebuf->character(pos) == 'C')) stringdeleted = 1; - - stylebuf->remove(pos, pos + nDeleted); - if(pos < 2) style_init(); - } - - - - // Select the area that was just updated to avoid unnecessary - // callbacks... - stylebuf->select(pos, pos + nInserted - nDeleted); - - // Re-parse the changed region; we do this by parsing from the - // beginning of the line of the changed region to the end of - // the line of the changed region... Then we check the last - // style character and keep updating if we have a multi-line - // comment character... - start = textbuf->line_start(pos); - end = textbuf->line_end(pos + nInserted); - text = textbuf->text_range(start, end); - style = stylebuf->text_range(start, end); - last = style[end - start - 1]; - - - style_parse(text, style, end - start); - - - stylebuf->replace(start, end, style); - ((Fl_Text_Editor_ext *)cbArg)->redisplay_range(start, end); - - if ((last != style[end - start - 1]) || nDeleted || style[end - start - 1] == 'D') - if (last == 'C' || last == 'D') - //if(update_count > 10) - { - // The last character on the line changed styles, so reparse the - // remainder of the buffer... - free(text); - free(style); - - start = 0; - end = textbuf->length(); - text = textbuf->text_range(start, end); - style = stylebuf->text_range(start, end); - - style_parse(text, style, end - start); - - //if(update_count > 10) - { - update_count = 0; - if(browser_nav_grp->visible()) navigator_update(text,style,end - start); - } - - stylebuf->replace(start, end, style); - //((Fl_Text_Editor *)cbArg)->redisplay_range(start, end); - - te->redraw(); - } - update_count+= nInserted > nDeleted ? nInserted : nDeleted; - - free(text); - free(style); +========================================================================== +style_update() - Update the style buffer... +========================================================================== */ -} - - void style_update( int pos, // I - Position of update int nInserted, // I - Number of inserted chars @@ -667,8 +553,6 @@ style_update( int pos, // I - Position of update { int start, // Start of text end; // End of text - char last, // Last style on line - stringdeleted=0; char *style, // Style data *text; // Text data @@ -704,36 +588,30 @@ style_update( int pos, // I - Position of update else { // Just delete characters in the style buffer... - if((pHlCtrl->stylebuf->character(pos) == 'D') || (pHlCtrl->stylebuf->character(pos) == 'C')) stringdeleted = 1; - pHlCtrl->stylebuf->remove(pos, pos + nDeleted); if(pos < 2) style_init(pHlCtrl); } - // Select the area that was just updated to avoid unnecessary - // callbacks... - pHlCtrl->stylebuf->select(pos, pos + nInserted - nDeleted); - - // Re-parse the changed region; we do this by parsing from the - // beginning of the line of the changed region to the end of - // the line of the changed region... Then we check the last - // style character and keep updating if we have a multi-line - // comment character... - start = pHlCtrl->textbuf->line_start(pos); - end = pHlCtrl->textbuf->line_end(pos + nInserted); - text = pHlCtrl->textbuf->text_range(start, end); - style = pHlCtrl->stylebuf->text_range(start, end); - last = style[end - start - 1]; - - style_parse(text, style, end - start); - - pHlCtrl->stylebuf->replace(start, end, style); - pHlCtrl->te->redisplay_range(start, end); - - //if ((last != style[end - start - 1]) || nDeleted || style[end - start - 1] == 'D') - //if(update_count > 10) - { + // Select the area that was just updated to avoid unnecessary + // callbacks... + pHlCtrl->stylebuf->select(pos, pos + nInserted - nDeleted); + + // Re-parse the changed region; we do this by parsing from the + // beginning of the line of the changed region to the end of + // the line of the changed region... Then we check the last + // style character and keep updating if we have a multi-line + // comment character... + start = pHlCtrl->textbuf->line_start(pos); + end = pHlCtrl->textbuf->line_end(pos + nInserted); + text = pHlCtrl->textbuf->text_range(start, end); + style = pHlCtrl->stylebuf->text_range(start, end); + + style_parse(text, style, end - start); + + pHlCtrl->stylebuf->replace(start, end, style); + pHlCtrl->te->redisplay_range(start, end); + // The last character on the line changed styles, so reparse the // remainder of the buffer... free(text); @@ -746,24 +624,13 @@ style_update( int pos, // I - Position of update style_parse(text, style, end - start); -// add_nav_timeout_handler(); - //if(update_count > 10) - { - //update_count = 0; - //if(browser_nav_grp->visible()) navigator_update(text,style,end - start); - } - pHlCtrl->stylebuf->replace(start, end, style); - //((Fl_Text_Editor *)cbArg)->redisplay_range(start, end); pHlCtrl->te->redraw(); - } - //update_count+= nInserted > nDeleted ? nInserted : nDeleted; - free(text); - free(style); + free(text); + free(style); } - - +// vim: noet sw=4 ts=4 diff --git a/src/vt_client_main.cpp b/src/vt_client_main.cpp index 7bf20f0..c4e3e3c 100644 --- a/src/vt_client_main.cpp +++ b/src/vt_client_main.cpp @@ -98,117 +98,116 @@ int main ( int argc, char* argv[] ) std::cout << "Return data reported according to specified radix\n"; std::cout << "Type 'help' or 'quit' to exit\n"; - try - { - if (hostArg == NULL) - hostArg = (char *) "localhost"; - - ClientSocket client_socket ( hostArg , atoi(portArg) ); + try + { + if (hostArg == NULL) + hostArg = (char *) "localhost"; - std::string reply; - std::string cmd; - std::string outfile; - size_t pos,c; - std::cout << "Ok> "; + ClientSocket client_socket ( hostArg , atoi(portArg) ); - while (true) - { - getline(std::cin, cmd); + std::string reply; + std::string cmd; + std::string outfile; + size_t pos,c; + std::cout << "Ok> "; - outfile = "stdout"; - // Search for '>' in the command - if ((pos = cmd.find('>')) != -1) + while (true) { - for (c = pos+1; c < cmd.length(); c++) + getline(std::cin, cmd); + + outfile = "stdout"; + // Search for '>' in the command + if ((pos = cmd.find('>')) != string::npos) { - if (cmd[c] != ' ') - break; - } + for (c = pos+1; c < cmd.length(); c++) + { + if (cmd[c] != ' ') + break; + } - outfile = cmd.substr(c, cmd.length()-c); - cmd = cmd.substr(0, pos); - while (cmd[cmd.length()-1] == ' ') - cmd = cmd.substr(0, cmd.length()-1); - } + outfile = cmd.substr(c, cmd.length()-c); + cmd = cmd.substr(0, pos); + while (cmd[cmd.length()-1] == ' ') + cmd = cmd.substr(0, cmd.length()-1); + } - if (cmd == "quit") - break; - if (cmd == "") - { - std::cout << "Ok> "; - continue; - } - - try - { - client_socket << cmd; - } - catch ( SocketException& ) - {} - - // Get response(s) - if (outfile != "stdout") - filestr.open(outfile.c_str(), fstream::out); - reply = ""; - int retry = 0; // Only wait so long for "Ok" - while (reply != "Ok") - { - // Get response - try + if (cmd == "quit") + break; + if (cmd == "") { - client_socket >> reply; + std::cout << "Ok> "; + continue; } - catch ( SocketException& e) + + try { - std::cout << "Exception - " << e.description() << "\n"; + client_socket << cmd; } + catch ( SocketException& ) + {} + + // Get response(s) + if (outfile != "stdout") + filestr.open(outfile.c_str(), fstream::out); + reply = ""; - // Check if response is "Ok" or contains "Ok" at the end - size_t len = reply.length(); - if ((reply[len-1] == 'k') && (reply[len-2] == 'O')) + while (reply != "Ok") { - // Check if output goes to a file - if (outfile == "stdout") - std::cout << reply << "> "; - else + // Get response + try { - reply = reply.substr(0, reply.length()-2); - filestr << reply; - std::cout << "Ok> "; + client_socket >> reply; + } + catch ( SocketException& e) + { + std::cout << "Exception - " << e.description() << "\n"; + } + + // Check if response is "Ok" or contains "Ok" at the end + size_t len = reply.length(); + if ((reply[len-1] == 'k') && (reply[len-2] == 'O')) + { + // Check if output goes to a file + if (outfile == "stdout") + std::cout << reply << "> "; + else + { + reply = reply.substr(0, reply.length()-2); + filestr << reply; + std::cout << "Ok> "; + } + reply = "Ok"; } - reply = "Ok"; - } - else - { - if (outfile == "stdout") - std::cout << reply; else { - filestr << reply; + if (outfile == "stdout") + std::cout << reply; + else + { + filestr << reply; + } } - } - // Check if response is "Syntax error" - if (reply == "Syntax error") - { - reply = "Ok"; - std::cout << "\nOk> "; + // Check if response is "Syntax error" + if (reply == "Syntax error") + { + reply = "Ok"; + std::cout << "\nOk> "; + } } - } - if (outfile != "stdout") - filestr.close(); + if (outfile != "stdout") + filestr.close(); - if (cmd == "terminate") - break; - } - - } - catch ( SocketException& e ) - { - std::cout << "Exception was caught:" << e.description() << "\n"; + if (cmd == "terminate") + break; + } } + catch ( SocketException& e ) + { + std::cout << "Exception was caught:" << e.description() << "\n"; + } std::cout << "\n"; - return 0; + return 0; } From de71fe7ca01f786379f2351711bab0d8a082d6c3 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 28 Mar 2020 07:15:41 -0700 Subject: [PATCH 320/327] Minor changes to fix warnings with -Wall in ide.cpp and idetabs.cpp. --- src/ide.cpp | 27 ++++++++++++--------------- src/idetabs.cpp | 9 +++------ 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/ide.cpp b/src/ide.cpp index ce502dd..2105388 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -1338,7 +1338,6 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) Fl_Pixmap* new_file = new Fl_Pixmap(document_new_xpm); Fl_Pixmap* open_file = new Fl_Pixmap(document_open_xpm); Fl_Pixmap* save_file = new Fl_Pixmap(document_save_xpm); - Fl_Pixmap* print_file = new Fl_Pixmap(printer_xpm); Fl_Pixmap* cut_icon = new Fl_Pixmap(edit_cut_xpm); Fl_Pixmap* copy_icon = new Fl_Pixmap(edit_copy_xpm); @@ -1347,7 +1346,6 @@ VT_Ide::VT_Ide(int x, int y, int w, int h, const char *title) Fl_Pixmap* find_icon = new Fl_Pixmap(edit_find_xpm); Fl_Pixmap* configure_icon = new Fl_Pixmap(configure_xpm); Fl_Pixmap* wizard_icon = new Fl_Pixmap(wizard_xpm); - Fl_Pixmap* log_viewer_icon = new Fl_Pixmap(log_viewer_xpm); pToolbar->AddHandle(toolbar_handle, NULL, NULL); pToolbar->AddButton("New", new_file, cb_new_file, NULL); @@ -2001,7 +1999,7 @@ cut routine. void VT_Ide::FindNext(void) { Fl_Multi_Edit_Window* mw; - const char * pFind; + const char * pFind = ""; // First get a pointer to the active (topmost) window mw = (Fl_Multi_Edit_Window*) m_EditTabs->value(); @@ -2032,7 +2030,6 @@ void VT_Ide::FindNext(void) if (!mw->ForwardSearch(m_Search, m_pFindDlg->m_pMatchCase->value())) { // Save the current position and search from beginning of file - int pos = mw->insert_position(); mw->insert_position(0); if (!mw->ForwardSearch(m_Search, m_pFindDlg->m_pMatchCase->value())) { @@ -2048,7 +2045,6 @@ void VT_Ide::FindNext(void) m_pFindDlg->m_pFind->take_focus(); m_pFindDlg->m_pFind->selectall(); return; - //mw->insert_position(pos); } } } @@ -2068,7 +2064,7 @@ cut routine. void VT_Ide::FindPrev(void) { Fl_Multi_Edit_Window* mw; - const char * pFind; + const char * pFind = ""; // First get a pointer to the active (topmost) window mw = (Fl_Multi_Edit_Window*) m_EditTabs->value(); @@ -2098,7 +2094,6 @@ void VT_Ide::FindPrev(void) if (!mw->BackwardSearch(m_Search, m_pFindDlg->m_pMatchCase->value())) { // Save the current position and search from beginning of file - int pos = mw->insert_position(); mw->insert_position(99999999); if (!mw->BackwardSearch(m_Search, m_pFindDlg->m_pMatchCase->value())) { @@ -2114,7 +2109,6 @@ void VT_Ide::FindPrev(void) m_pFindDlg->m_pFind->take_focus(); m_pFindDlg->m_pFind->selectall(); return; - //mw->insert_position(pos); } } } @@ -2156,7 +2150,6 @@ void VT_Ide::ToolbarFind(Flu_Combo_List *pList) if (!mw->ForwardSearch(pFind, m_pFindDlg->m_pMatchCase->value())) { // Save the current position and search from beginning of file - int pos = mw->insert_position(); mw->insert_position(0); if (!mw->ForwardSearch(pFind, m_pFindDlg->m_pMatchCase->value())) { @@ -3444,10 +3437,10 @@ project and to the tree control. void VT_Ide::NewFolder(Flu_Tree_Browser::Node* n) { MString name, filespec; - VT_IdeGroup* pGroup; + VT_IdeGroup* pGroup = NULL; VT_IdeGroup* pNewGrp; int len, c, root; - Flu_Tree_Browser::Node* i; + Flu_Tree_Browser::Node* i = NULL; Flu_Tree_Browser::Node* newNode; const char* pName; @@ -3540,7 +3533,7 @@ void VT_Ide::NewFolder(Flu_Tree_Browser::Node* n) else m_ActivePrj->m_Groups.InsertAt(c, pNewGrp); } - else + else if (pGroup != NULL) { if (c == len) pGroup->m_Objects.Add(pNewGrp); @@ -3947,10 +3940,9 @@ LoadRomToRex: This routine load the built OptROM data to the REX flash */ void VT_Ide::LoadRomToRex(VTLinker *pLinker) { - long address, blockaddr; + long address; unsigned char sEntry[7]; - int x, actblk = 0; - unsigned char status; + int x; MString temp; unsigned char buf[32768]; @@ -3973,6 +3965,9 @@ void VT_Ide::LoadRomToRex(VTLinker *pLinker) } #if 0 + int actblk = 0; + unsigned char status; + // Address found. Determine active block for (x = 0; x < 0x3FF; x++) { @@ -4496,3 +4491,5 @@ VT_FindDlg::VT_FindDlg(class VT_Ide* pParent) m_pParent = pParent; } +// vim: noet ts=4 sw=4 + diff --git a/src/idetabs.cpp b/src/idetabs.cpp index 6563436..44a6eac 100644 --- a/src/idetabs.cpp +++ b/src/idetabs.cpp @@ -157,8 +157,6 @@ void Fl_Ide_Tabs::draw() if (damage() & FL_DAMAGE_ALL) { // redraw the entire thing: - Fl_Color c = v ? v->color() : color(); - if (v) draw_child(*v); } @@ -221,6 +219,7 @@ void Fl_Ide_Tabs::draw() } // Draw the tabs + maxw = w() - (H2+1) * (m_hasCloseButton + m_hasMoreButton); if (damage() & (FL_DAMAGE_SCROLL|FL_DAMAGE_ALL)) { Fl_Widget*const* a = array(); @@ -230,7 +229,6 @@ void Fl_Ide_Tabs::draw() // window. If it is, then we will move it's position in the // list of children such that it is the right most tab that is // fully visible. - maxw = w() - (H2+1) * (m_hasCloseButton + m_hasMoreButton); if (p[selected] + wp[selected] >= maxw) { // Okay, the selected tab doesn't fit on the window. Let's @@ -321,7 +319,6 @@ int Fl_Ide_Tabs::tab_positions(int* p, int* wp) int selected = 0; Fl_Widget*const* a = array(); int i; - int H = tab_height(); char prev_draw_shortcut = fl_draw_shortcut; fl_draw_shortcut = 1; @@ -437,8 +434,6 @@ void Fl_Ide_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) char prev_draw_shortcut = fl_draw_shortcut; fl_draw_shortcut = 1; - Fl_Boxtype bt = (o==push() &&!sel) ? fl_down(box()) : box(); - // compute offsets to make selected tab look bigger int yofs = sel ? BORDER + 1 : BORDER; @@ -934,3 +929,5 @@ void Fl_Ide_Tabs::SelectTab(Fl_Widget *pTab) redraw(); } +// vim: noet sw=4 ts=4 + From 24be7bf1a56b4e2ec0d99931f251c7a71be42669 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 28 Mar 2020 07:49:32 -0700 Subject: [PATCH 321/327] Minor updates to fix unused variable warnings with -Wall. --- src/MString.cpp | 4 ++-- src/linker.cpp | 32 +++++++++++++++++--------------- src/lpt.cpp | 2 +- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/MString.cpp b/src/MString.cpp index 8d73242..cecbacf 100644 --- a/src/MString.cpp +++ b/src/MString.cpp @@ -2444,7 +2444,7 @@ MString CFileString::FirstSubDir() m_SubDirIndex = 0; char* ptr = dir.GetBuffer(dir.GetLength() + 1); - char* token; + char* token = NULL; // Now find the m_SubDirIndex'th item in the path for (int c = 0; c <= m_SubDirIndex; c++) @@ -2470,7 +2470,7 @@ MString CFileString::NextSubDir() MString dir = Directory(); char* ptr = dir.GetBuffer(dir.GetLength() + 1); - char* token; + char* token = NULL; // Now find the m_SubDirIndex'th item in the path for (int c = 0; c <= m_SubDirIndex; c++) diff --git a/src/linker.cpp b/src/linker.cpp index f0d965c..8cb047d 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -55,7 +55,7 @@ Construtor / destructor for the linker */ VTLinker::VTLinker() { - int x; + unsigned int x; m_Hex = 0; m_FileIndex = -1; @@ -1352,7 +1352,7 @@ void VTLinker::ProcScriptField5(const char *pStr, int lineNo, int& prot, int& at { MString err; const char *pToken, *ptr; - int tokLen; + unsigned int tokLen; // Initialize startAddr in case error or ORDER command prot = FALSE; @@ -2200,7 +2200,8 @@ CObjFile object provided. int VTLinker::ReadSectionData(FILE* fd, CObjFile* pObjFile, CObjFileSection* pFileSection) { - int bytes = 0, count, c, size, idx; + unsigned int bytes = 0; + int count, c, size, idx; MString err, sourcefile; Elf32_Shdr* pHdr = &pFileSection->m_ElfHeader; Elf32_Sym* pSym; @@ -2244,7 +2245,7 @@ int VTLinker::ReadSectionData(FILE* fd, CObjFile* pObjFile, } // Test if the section link points to itself - if (pFileSection->m_Index == pHdr->sh_link) + if (pFileSection->m_Index == (int) pHdr->sh_link) { if (strcmp(&pFileSection->m_pStrTab[pHdr->sh_name], ".shstrtab") == 0) if (pObjFile->m_pShStrTab == NULL) @@ -2479,7 +2480,6 @@ int VTLinker::AssignSectionNames() CObjFile* pObjFile; int count, c; CObjFileSection* pFileSection; - bool segmentFound = false; char * pName; POSITION pos; MString fileName; @@ -2637,7 +2637,6 @@ int VTLinker::LocateSegmentIntoRegion(MString& region, CObjFileSection* pFileSec CLinkRgn* pLinkRgn; MString err; int c, locateAddr, segSize; - bool segmentFound = false; MString fileName; LinkAddrRange* pAddrRange; static const char* sSegType[] = { "ASEG", "CSEG", "DSEG" }; @@ -2973,7 +2972,8 @@ int VTLinker::LocateNondependantSegments() if (m_LinkRegions.Lookup((const char *) pFileSect->m_Name, (VTObject *&) pLinkRgn)) { // Locate the segment into the region with the same name - LocateSegmentIntoRegion(pLinkRgn->m_Name, pFileSect); + if (!LocateSegmentIntoRegion(pLinkRgn->m_Name, pFileSect)) + success = FALSE; } // Test if segment is ASEG @@ -2981,7 +2981,8 @@ int VTLinker::LocateNondependantSegments() (pFileSect->m_ElfHeader.sh_type == SHT_PROGBITS)) { // Locate ASEGs into the .aseg linker region - LocateSegmentIntoRegion(aseg, pFileSect); + if (!LocateSegmentIntoRegion(aseg, pFileSect)) + success = FALSE; } // Test if segment is CSEG @@ -2989,7 +2990,8 @@ int VTLinker::LocateNondependantSegments() SHF_WRITE)) == (SHF_ALLOC | SHF_EXECINSTR)) { // Locate CSEGs into the .text linker region - LocateSegmentIntoRegion(text, pFileSect); + if (!LocateSegmentIntoRegion(text, pFileSect)) + success = FALSE; } // Test if segment is DSEG @@ -2997,7 +2999,8 @@ int VTLinker::LocateNondependantSegments() SHF_WRITE)) == SHF_WRITE) { // Locate DSEGs into the .data linker region - LocateSegmentIntoRegion(data, pFileSect); + if (!LocateSegmentIntoRegion(data, pFileSect)) + success = FALSE; } // Unknown segment type @@ -3010,7 +3013,7 @@ int VTLinker::LocateNondependantSegments() } } - return TRUE; + return success; } /* @@ -3388,7 +3391,7 @@ int VTLinker::Evaluate(class CRpnEquation* eq, double* value, double stack[200]; int stk = 0; const char* pStr; - int c, local; + int c; VTObject* dummy; // Get count of number of operations in equation and initalize stack @@ -3406,7 +3409,6 @@ int VTLinker::Evaluate(class CRpnEquation* eq, double* value, case RPN_VARIABLE: // Try to find variable in equate array temp = op.m_Variable; - local = 0; // Lookup symbol in active module pStr = (const char *) temp; @@ -4416,7 +4418,7 @@ int VTLinker::BackAnnotateListingFiles(void) CObjFile* pOpenFile; CObjFileSection* pFileSection; MString err, filename; - FILE* fd; + FILE* fd = NULL; char* pRead; char lineBuf[512]; char str[6]; @@ -4665,7 +4667,6 @@ void VTLinker::ParseExternalDefines(void) int startIndex, endIndex; MString def, sval; int valIdx, len; - int value = -1; // If zero length then we're done if ((len = m_ExtDefines.GetLength()) == 0) @@ -4892,3 +4893,4 @@ void VTLinker::SetDefines(const MString& defines) m_ExtDefines = defines; } +// vim: noet sw=4 ts=4 diff --git a/src/lpt.cpp b/src/lpt.cpp index 91ff7cc..8106f5a 100644 --- a/src/lpt.cpp +++ b/src/lpt.cpp @@ -1011,7 +1011,7 @@ void VTLpt::HandleTimeouts(unsigned long time) } } // Check if we need to cancel activity animation - if ((m_PortStatus == LPT_STATUS_ACTIVITY) && (m_PortActivity + 1 <= time)) + if ((m_PortStatus == LPT_STATUS_ACTIVITY) && (m_PortActivity + 1 <= (time_t) time)) { // Change the port status to READY. Animation will stop automatically m_PortStatus = LPT_STATUS_READY; From 1193b87a58b2f6b7134294509967e4586a12b352 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 28 Mar 2020 08:39:34 -0700 Subject: [PATCH 322/327] Minor updates to fix unused and possible uninitialized vars with -Wall. --- src/My_Text_Buffer.cpp | 2 +- src/My_Text_Display.cpp | 36 +++++++++++------------------------- src/pref_form.cpp | 2 +- src/rememcfg.cpp | 2 +- src/tdockvid.cpp | 26 ++++++-------------------- 5 files changed, 20 insertions(+), 48 deletions(-) diff --git a/src/My_Text_Buffer.cpp b/src/My_Text_Buffer.cpp index 03172a4..ffdffe9 100644 --- a/src/My_Text_Buffer.cpp +++ b/src/My_Text_Buffer.cpp @@ -1343,7 +1343,7 @@ static void subsChars( char *string, int length, char fromChar, char toChar ) { */ static char chooseNullSubsChar( char hist[ 256 ] ) { #define N_REPLACEMENTS 25 - static char replacements[ N_REPLACEMENTS ] = {1, 2, 3, 4, 5, 6, 14, 15, 16, 17, 18, 19, + static unsigned char replacements[ N_REPLACEMENTS ] = {1, 2, 3, 4, 5, 6, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 29, 30, 31, 11, 7}; int i; for ( i = 0; i < N_REPLACEMENTS; i++ ) diff --git a/src/My_Text_Display.cpp b/src/My_Text_Display.cpp index b16a903..6e5f200 100644 --- a/src/My_Text_Display.cpp +++ b/src/My_Text_Display.cpp @@ -25,15 +25,12 @@ #include #include -//#include #include #include #include #include -//#include #include "My_Text_Display.h" #include -//#include #include #undef min @@ -424,8 +421,8 @@ void My_Text_Display::resize(int X, int Y, int W, int H) mMaxsize = max(mMaxsize, fl_height(mStyleTable[i].font, mStyleTable[i].size)); // did we have scrollbars initially? - int hscrollbarvisible = mHScrollBar->visible(); - int vscrollbarvisible = mVScrollBar->visible(); + unsigned int hscrollbarvisible = mHScrollBar->visible(); + unsigned int vscrollbarvisible = mVScrollBar->visible(); // try without scrollbars first mVScrollBar->clear_visible(); @@ -545,7 +542,7 @@ void My_Text_Display::resize(int X, int Y, int W, int H) display_insert_position_hint = 0; if (mContinuousWrap || - hscrollbarvisible != mHScrollBar->visible() || + hscrollbarvisible != mHScrollBar->visible() || vscrollbarvisible != mVScrollBar->visible()) redraw(); @@ -902,7 +899,6 @@ int My_Text_Display::in_selection( int X, int Y ) { xy_to_rowcol( X, Y, &row, &column, CHARACTER_POS ); if (range_touches_selection(buf->primary_selection(), mFirstChar, mLastChar)) column = wrapped_column(row, column); -// return buf->primary_selection()->includes(pos, buf->line_start( pos ), column); return buf->primary_selection()->includes(pos, buf->line_start( pos ), column); } @@ -2548,7 +2544,7 @@ void My_Text_Display::measure_deleted_lines(int pos, int nDeleted) { int nVisLines = mNVisibleLines; int *lineStarts = mLineStarts; int countFrom, lineStart; - int visLineNum = 0, nLines = 0, i; + int nLines = 0, i; /* ** Determine where to begin searching: either the previous newline, or ** if possible, limit to the start of the (original) previous displayed @@ -2560,7 +2556,6 @@ void My_Text_Display::measure_deleted_lines(int pos, int nDeleted) { break; if (i > 0) { countFrom = lineStarts[i-1]; - visLineNum = i-1; } else countFrom = buf->line_start(pos); } else @@ -3060,7 +3055,7 @@ void fl_text_drag_me(int pos, My_Text_Display* d) { int My_Text_Display::handle(int event) { - int line, ret; + int line; if (!buffer()) return 0; @@ -3068,7 +3063,7 @@ int My_Text_Display::handle(int event) if (!Fl::event_inside(text_area.x, text_area.y, text_area.w, text_area.h) && !dragging && event != FL_LEAVE && event != FL_ENTER && event != FL_MOVE) { - ret = Fl_Group::handle(event); + Fl_Group::handle(event); position_to_linecol(insert_position(), &line, &mCurrentCol); } @@ -3134,8 +3129,10 @@ int My_Text_Display::handle(int event) int errLine = atoi(buffer()->text_range(errNumPos, errNumEndPos)); int fileNameStart = errNumEndPos + 1; int foundPos; - int fileNameEnd = buffer()->search_forward(fileNameStart, ")", &foundPos, 0); - char *pFile = buffer()->text_range(fileNameStart, foundPos); + char *pFile; + + buffer()->search_forward(fileNameStart, ")", &foundPos, 0); + pFile = buffer()->text_range(fileNameStart, foundPos); // Now call the IDE with the filename and line number instructing it to display the errored line if (m_pErrorFunc != NULL) @@ -3197,18 +3194,6 @@ int My_Text_Display::handle(int event) case FL_MOUSEWHEEL: return mVScrollBar->handle(event); - -/* case FL_FOCUS: - if (buffer()->primary_selection()->start() != - buffer()->primary_selection()->end()) redraw(); // Redraw selections... - color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR); - - break; - case FL_UNFOCUS: - if (buffer()->primary_selection()->start() != - buffer()->primary_selection()->end()) redraw(); // Redraw selections... - color(FL_INACTIVE_COLOR, FL_BLACK); - break; */ } return Fl_Double_Window::handle(event); @@ -3218,3 +3203,4 @@ int My_Text_Display::handle(int event) // // End of "$Id$". // +// vim: noet sw=4 ts=4 diff --git a/src/pref_form.cpp b/src/pref_form.cpp index fcc2e16..851a515 100644 --- a/src/pref_form.cpp +++ b/src/pref_form.cpp @@ -182,7 +182,7 @@ Fl_Double_Window* make_pref_form() { text_size_choice->add("6");text_size_choice->add("8");text_size_choice->add("10");text_size_choice->add("12");text_size_choice->add("14");text_size_choice->add("16");text_size_choice->add("18");text_size_choice->add("20"); text_size_choice->value(3); } - { Fl_Input* i = tab_size_choice = new Fl_Input(240, 45, 40, 25, "Tab Size"); + { tab_size_choice = new Fl_Input(240, 45, 40, 25, "Tab Size"); sprintf(stab, "%d", tab_size); tab_size_choice->value(stab); } diff --git a/src/rememcfg.cpp b/src/rememcfg.cpp index f6fe58e..faa298d 100644 --- a/src/rememcfg.cpp +++ b/src/rememcfg.cpp @@ -549,7 +549,7 @@ void cb_revert_map (Fl_Widget* w, void*) void create_default_map(int map) { - int c, mapdata; + unsigned int c, mapdata; // First zero all map memory for (c = 0; c < sizeof(gMapData); c++) diff --git a/src/tdockvid.cpp b/src/tdockvid.cpp index 03b2662..c15ac3c 100644 --- a/src/tdockvid.cpp +++ b/src/tdockvid.cpp @@ -490,10 +490,8 @@ draw_pixels: This routine draws the pixels on the display. void VTTDockVid::draw_pixels() { int x=0; - int y=0; int line; uchar value; - int lastColor = -1; int color; window()->make_current(); @@ -503,7 +501,6 @@ void VTTDockVid::draw_pixels() for (x = 0; x < 480; x++) { value = pixdata[line][x]; - //y = line << 3; // Erase line so it is grey, then fill in with black where needed if ((line & 0x07) == 0) @@ -515,19 +512,12 @@ void VTTDockVid::draw_pixels() if (value == 0) continue; - // Draw the black pixels - //if (value) - { - color = m_Colors[value]; - //if (color != lastColor) - { - fl_color(color); - lastColor = color; - } - drawpixel(x,line,1); - } + // Draw the pixels + color = m_Colors[value]; + fl_color(color); + drawpixel(x,line,1); } - } + } } /* @@ -912,7 +902,7 @@ void VTTDockVid::WriteData(uchar data) /* Draw the received byte */ else //if (data >= ' '); { - int addr, line, c, mem_index, column, lastcolor = -1; + int addr, line, c, mem_index, column; if (m_CurY >= bottom) Scroll(); @@ -1008,7 +998,6 @@ void VTTDockVid::WriteData(uchar data) void VTTDockVid::XorCursor(void) { - int line = m_CurY >> 3; int col = m_CurX; int num, x,y; @@ -1049,7 +1038,6 @@ void VTTDockVid::Scroll(void) { /* We need to perform a scroll */ for (y = 8; y < bottom; y++) - //for (line = 1; line < 25; line++) { for (col = 0; col < 480; col++) { @@ -1064,8 +1052,6 @@ void VTTDockVid::Scroll(void) } drawpixel(col,y-8,1); } - //if (pixdata[line][col] != 0 || pixdata[line-1][col] != 0) - // SetByte(line-1, col, pixdata[line][col]); } } From 60415604d978968a2cc5dc281fd6c5089e50e64b Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 28 Mar 2020 09:18:50 -0700 Subject: [PATCH 323/327] Minor updates to tpddserver to fix warnings with -Wall. --- src/tpddserver.cpp | 16 +++++++--------- src/tpddserver.h | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/tpddserver.cpp b/src/tpddserver.cpp index bea2889..8a4644e 100644 --- a/src/tpddserver.cpp +++ b/src/tpddserver.cpp @@ -627,7 +627,7 @@ Sets the simulated port flags int VTTpddServer::SerGetFlags(unsigned char *flags) { // Test if we can receive more data - if (m_rxCount + 1 < sizeof(m_rxBuffer)) + if (m_rxCount + 1 < (int) sizeof(m_rxBuffer)) *flags = SER_FLAG_TX_EMPTY; else *flags &= ~SER_FLAG_TX_EMPTY; @@ -673,7 +673,7 @@ int VTTpddServer::SerReadByte(char *data) // "Read" the next byte from the TX buffer *data = m_txBuffer[m_txOut++]; - if (m_txOut >= sizeof(m_txBuffer)) + if (m_txOut >= (int) sizeof(m_txBuffer)) m_txOut = 0; LogData(*data, TPDD_LOG_TX); @@ -734,7 +734,7 @@ Sends a single character to the host void VTTpddServer::SendToHost(char data) { // Validate the TX buffer isn't full - if (m_txCount + 1 >= sizeof(m_txBuffer)) + if (m_txCount + 1 >= (int) sizeof(m_txBuffer)) { m_txOverflow = TRUE; return; @@ -742,7 +742,7 @@ void VTTpddServer::SendToHost(char data) // Add the byte m_txBuffer[m_txIn++] = data; - if (m_txIn >= sizeof(m_txBuffer)) + if (m_txIn >= (int) sizeof(m_txBuffer)) m_txIn = 0; m_txCount++; } @@ -807,7 +807,7 @@ void VTTpddServer::StateCmdline(char data) // We have received part of a command line and we are looking for a CR, // but must look for a 'Z' or 'M' after a timeout also - if (m_rxCount + 1 >= sizeof(m_rxBuffer)) + if (m_rxCount + 1 >= (int) sizeof(m_rxBuffer)) { // Buffer overflow!!! Go to idle state m_rxIn = m_rxCount = 0; @@ -954,7 +954,6 @@ int VTTpddServer::CmdlineDir(int background) { int i, printed, col; MString file_path; - int wide = FALSE; MString fmt; int len, isDir; @@ -1898,7 +1897,7 @@ void VTTpddServer::DirFindFile(const char* pFilename) // read the directory dirent** e; char* name; - int i, num, len, dir_search = FALSE, dir_entry; + int i, num, len, dir_entry; MString file_path; char find_name[16]; @@ -1930,7 +1929,6 @@ void VTTpddServer::DirFindFile(const char* pFilename) if (len > 3 && pFilename[len-1] == '>' && pFilename[len-2] == '<') { // Indicate we are doing a directory search - dir_search = TRUE; m_refIsDirectory = TRUE; // Terminate the filename at the '.' @@ -2805,7 +2803,6 @@ Change directory to the directory specified int VTTpddServer::ChangeDirectory(MString& sDir) { MString dirName; - int idx = 0; int len = sDir.GetLength(); // Strip any trailing ".<>" @@ -2920,3 +2917,4 @@ int VTTpddServer::IsCmdlineState(void) return m_state == TPDD_STATE_CMDLINE; } +// vim: noet ts=4 sw=4 diff --git a/src/tpddserver.h b/src/tpddserver.h index 97e4e6d..d0271f7 100644 --- a/src/tpddserver.h +++ b/src/tpddserver.h @@ -190,7 +190,7 @@ class VTTpddServer : public VTServer { public: VTTpddServer(); - ~VTTpddServer(); + virtual ~VTTpddServer(); // Methods int SerOpenPort(void); From 37b6b19149f696d567b9dcefd8bee8a3360a0ceb Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 22 May 2021 18:38:27 -0700 Subject: [PATCH 324/327] Added midnight theme with all black dialog boxes and menus, added RexC memory support, fixed pc8201a host file load. --- GNUmakefile | 4 +- src/FLU/Flu_Combo_Box.h | 4 + src/FLU/Flu_Combo_List.h | 3 + src/FLU/Flu_Combo_Tree.h | 2 + src/FLU/Flu_Tree_Browser.h | 3 + src/Flu_Combo_Box.cpp | 12 +- src/Flu_Combo_List.cpp | 9 + src/Flu_Combo_Tree.cpp | 8 + src/Flu_File_Chooser.cpp | 142 ++++- src/Flu_Tree_Browser.cpp | 12 + src/VirtualT.h | 2 +- src/chargen.cpp | 56 +- src/clock.cpp | 12 + src/cpu.h | 28 +- src/cpuregs.cpp | 7 +- src/display.cpp | 167 +++++- src/display.h | 1 + src/file.cpp | 74 ++- src/fileprint.cpp | 20 +- src/fx80print.cpp | 122 +++- src/fx80print.h | 8 +- src/hostprint.cpp | 16 + src/io.c | 20 +- src/lpt.cpp | 31 +- src/memedit.cpp | 219 ++++++- src/memory.c | 1152 +++++++++++++++++++++++++++--------- src/memory.h | 23 +- src/n8201rom.c | 3 +- src/periph.cpp | 135 ++++- src/remote.cpp | 77 ++- src/setup.cpp | 437 ++++++++++++-- src/setup.h | 4 + src/tpddserver.cpp | 20 + src/vtpaper.cpp | 27 + 34 files changed, 2379 insertions(+), 481 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index fba6cee..6c97bc7 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -24,8 +24,8 @@ ifeq ($(DEBUG),) OPTIMIZE = -O2 endif -CFLAGS += -I $(SRCDIR)/FLU $(OPTIMIZE) $(DEBUG) -fsigned-char -CPPFLAGS += -I $(SRCDIR) $(OPTIMIZE) $(DEBUG) +CFLAGS += -I $(SRCDIR)/FLU $(OPTIMIZE) $(DEBUG) -fsigned-char -Wall +CPPFLAGS += -I $(SRCDIR) $(OPTIMIZE) $(DEBUG) -Wall VIRTUALT = virtualt CLIENT = vt_client ifndef CC diff --git a/src/FLU/Flu_Combo_Box.h b/src/FLU/Flu_Combo_Box.h index 87ebdce..3153249 100644 --- a/src/FLU/Flu_Combo_Box.h +++ b/src/FLU/Flu_Combo_Box.h @@ -69,6 +69,9 @@ class FLU_EXPORT Flu_Combo_Box : public Fl_Group inline void input_callback( void (*cb)(Fl_Widget*,void*), void* cbd = NULL ) { _inputCB = cb; _inputCBD = cbd; } + //! Set the string in the input field and the value of the popup box. + void set_colors( Fl_Color fgcolor, Fl_Color textcolor); + //! Publicly exposed input widget Fl_Input input; @@ -91,6 +94,7 @@ class FLU_EXPORT Flu_Combo_Box : public Fl_Group bool _pushed, _popped; Fl_Widget *_cbox; int popHeight; + Fl_Color _arrowColor; static void input_cb( Fl_Widget*, void* v ); diff --git a/src/FLU/Flu_Combo_List.h b/src/FLU/Flu_Combo_List.h index b6e6e0f..31c824b 100644 --- a/src/FLU/Flu_Combo_List.h +++ b/src/FLU/Flu_Combo_List.h @@ -35,6 +35,9 @@ class FLU_EXPORT Flu_Combo_List : public Flu_Combo_Box //! Publicly exposed list widget (instance of Fl_Hold_Browser) Fl_Hold_Browser list; + //! Set the widget colors + void set_colors( Fl_Color bgcolor, Fl_Color textcolor ); + protected: bool _value( const char *v ); diff --git a/src/FLU/Flu_Combo_Tree.h b/src/FLU/Flu_Combo_Tree.h index a0370b9..dbd6275 100644 --- a/src/FLU/Flu_Combo_Tree.h +++ b/src/FLU/Flu_Combo_Tree.h @@ -34,6 +34,8 @@ class FLU_EXPORT Flu_Combo_Tree : public Flu_Combo_Box //! Publicly exposed tree widget (instance of Flu_Tree_Browser) Flu_Tree_Browser tree; + void set_colors( Fl_Color fgcolor, Fl_Color textcolor ); + protected: bool _value( const char *v ); diff --git a/src/FLU/Flu_Tree_Browser.h b/src/FLU/Flu_Tree_Browser.h index d6a8958..9a8bae1 100644 --- a/src/FLU/Flu_Tree_Browser.h +++ b/src/FLU/Flu_Tree_Browser.h @@ -63,6 +63,9 @@ class FLU_EXPORT Flu_Tree_Browser : public Fl_Double_Window //! Default destructor virtual ~Flu_Tree_Browser(); + //! Set the widget's colors + void set_colors( Fl_Color bgcolor, Fl_Color textcolor); + //! Add the entry specified by \b fullpath to the tree. If \b w is not \c NULL then that widget is the entry and its label is visible depending on the value of \b showLabel. Note that the widget is destroyed by the tree/node on clear() or the destructor /*! If \b fullpath ends in a slash ("/"), then the entry is added as a branch, else it is added as a leaf \return a pointer to the Node of the added entry or NULL if the add failed */ diff --git a/src/Flu_Combo_Box.cpp b/src/Flu_Combo_Box.cpp index f70be13..2336c52 100644 --- a/src/Flu_Combo_Box.cpp +++ b/src/Flu_Combo_Box.cpp @@ -31,6 +31,7 @@ Flu_Combo_Box :: Flu_Combo_Box( int X, int Y, int W, int H, const char* l ) _cbox = NULL; _valbox = FL_UP_BOX; + _arrowColor = FL_BLACK; input_callback( NULL ); input.box( FL_FLAT_BOX ); @@ -50,6 +51,14 @@ Flu_Combo_Box::~Flu_Combo_Box() { } +void Flu_Combo_Box :: set_colors( Fl_Color fgcolor, Fl_Color textcolor ) +{ + color(fgcolor); + _arrowColor = textcolor; + input.color(fgcolor); + input.textcolor(textcolor); +} + void Flu_Combo_Box :: set_combo_widget( Fl_Widget *w ) { _cbox = w; @@ -93,7 +102,8 @@ void Flu_Combo_Box :: draw() // draw the arrow button fl_draw_box( (Fl_Boxtype)_valbox, X, Y, W, H, color() ); - fl_color( active_r() ? FL_FOREGROUND_COLOR : fl_inactive(FL_FOREGROUND_COLOR) ); + //fl_color( active_r() ? FL_FOREGROUND_COLOR : fl_inactive(FL_FOREGROUND_COLOR) ); + fl_color( active_r() ? _arrowColor : fl_inactive(_arrowColor) ); fl_polygon( X+W/2-4, Y+H/2-2, X+W/2+4, Y+H/2-2, X+W/2, Y+H/2+2 ); draw_child( input ); diff --git a/src/Flu_Combo_List.cpp b/src/Flu_Combo_List.cpp index 8bbfa24..d841071 100644 --- a/src/Flu_Combo_List.cpp +++ b/src/Flu_Combo_List.cpp @@ -34,6 +34,15 @@ Flu_Combo_List :: ~Flu_Combo_List() { } +void Flu_Combo_List :: set_colors( Fl_Color bgcolor, Fl_Color textcolor ) +{ + color(bgcolor); + labelcolor(textcolor); + Flu_Combo_Box::set_colors(bgcolor, textcolor); + list.color(bgcolor); + list.textcolor(textcolor); +} + void Flu_Combo_List :: cb() { if( list.value() == 0 ) diff --git a/src/Flu_Combo_Tree.cpp b/src/Flu_Combo_Tree.cpp index 76ee728..1823b4b 100644 --- a/src/Flu_Combo_Tree.cpp +++ b/src/Flu_Combo_Tree.cpp @@ -35,6 +35,14 @@ Flu_Combo_Tree :: ~Flu_Combo_Tree() { } +void Flu_Combo_Tree :: set_colors( Fl_Color bgcolor, Fl_Color textcolor ) +{ + tree.color(bgcolor); + tree.labelcolor(textcolor); + tree.set_colors(bgcolor, textcolor); + Flu_Combo_Box::set_colors(bgcolor, textcolor); +} + void Flu_Combo_Tree :: cb() { //if( tree.callback_reason() == FLU_UNSELECTED ) diff --git a/src/Flu_File_Chooser.cpp b/src/Flu_File_Chooser.cpp index 88e72be..a794a89 100644 --- a/src/Flu_File_Chooser.cpp +++ b/src/Flu_File_Chooser.cpp @@ -58,6 +58,8 @@ #define DEFAULT_ENTRY_WIDTH 235 +extern int gMidnight; + Fl_Pixmap up_folder_img( big_folder_up_xpm ), trash( trash_xpm ), new_folder( big_folder_new_xpm ), reload( reload_xpm ), preview_img( monalisa_xpm ), file_list_img( filelist_xpm ), file_listwide_img( filelistwide_xpm ), fileDetails( filedetails_xpm ), add_to_favorite_folder( folder_favorite_xpm ), @@ -293,12 +295,20 @@ Flu_File_Chooser :: Flu_File_Chooser( const char *pathname, const char *pat, int Fl_Group *quickIcons = new Fl_Group( 5, 5, 100, h()-10-60 ); quickIcons->box( FL_DOWN_BOX ); quickIcons->color( FL_DARK3 ); + if (gMidnight) + { + color(fl_rgb_color(0x1e, 0x27, 0x28)); + //color(FL_BLACK); + quickIcons->color( FL_BLACK ); + } Flu_Button *desktopBtn = new Flu_Button( 30, 18, 50, 48 ); desktopBtn->box( FL_FLAT_BOX ); desktopBtn->image( desktop ); desktopBtn->enter_box( FL_THIN_UP_BOX ); desktopBtn->color( FL_DARK3 ); + if (gMidnight) + desktopBtn->color( FL_BLACK ); desktopBtn->callback( _desktopCB, this ); { Flu_Label *l = new Flu_Label( 5, 62, 100, 20, "Desktop" ); @@ -310,6 +320,8 @@ Flu_File_Chooser :: Flu_File_Chooser( const char *pathname, const char *pat, int homeBtn->box( FL_FLAT_BOX ); homeBtn->enter_box( FL_THIN_UP_BOX ); homeBtn->color( FL_DARK3 ); + if (gMidnight) + homeBtn->color( FL_BLACK ); homeBtn->callback( _homeCB, this ); { #ifdef WIN32 @@ -328,6 +340,8 @@ Flu_File_Chooser :: Flu_File_Chooser( const char *pathname, const char *pat, int documentsBtn->enter_box( FL_THIN_UP_BOX ); documentsBtn->labelcolor( FL_WHITE ); documentsBtn->color( FL_DARK3 ); + if (gMidnight) + documentsBtn->color( FL_BLACK ); documentsBtn->callback( _documentsCB, this ); { #ifdef WIN32 @@ -346,6 +360,8 @@ Flu_File_Chooser :: Flu_File_Chooser( const char *pathname, const char *pat, int favoritesBtn->image( favorites ); favoritesBtn->enter_box( FL_THIN_UP_BOX ); favoritesBtn->color( FL_DARK3 ); + if (gMidnight) + favoritesBtn->color( FL_BLACK ); favoritesBtn->callback( _favoritesCB, this ); { Flu_Label *l = new Flu_Label( 5, 302, 100, 20, "Favorites" ); @@ -370,6 +386,11 @@ Flu_File_Chooser :: Flu_File_Chooser( const char *pathname, const char *pat, int filesystems->tree.horizontal_gap( -10 ); filesystems->tree.show_leaves( false ); filesystems->callback( _filesystemsCB, this ); + if (gMidnight) + { + filesystems->set_colors(FL_BLACK, FL_WHITE); + filesystems->labelcolor(FL_WHITE); + } //////////////////////////////////////////////////////////////// @@ -467,6 +488,8 @@ Flu_File_Chooser :: Flu_File_Chooser( const char *pathname, const char *pat, int hiddenFiles = new Fl_Check_Button( 110, 33, 130, 25, "Show Hidden Files" ); hiddenFiles->callback( reloadCB, this ); + if (gMidnight) + hiddenFiles->labelcolor(FL_WHITE); #ifdef WIN32 hiddenFiles->hide(); #endif @@ -486,6 +509,8 @@ Flu_File_Chooser :: Flu_File_Chooser( const char *pathname, const char *pat, int filelist = new FileList( fileGroup->x()+2, fileGroup->y()+2, fileGroup->w()-4, fileGroup->h()-4, this ); filelist->box( FL_FLAT_BOX ); filelist->color( FL_WHITE ); + if (gMidnight) + filelist->color(FL_BLACK); filelist->type( FL_HORIZONTAL ); filelist->spacing( 4, 1 ); filelist->scrollbar.linesize( DEFAULT_ENTRY_WIDTH+4 ); @@ -493,13 +518,29 @@ Flu_File_Chooser :: Flu_File_Chooser( const char *pathname, const char *pat, int filecolumns = new FileColumns( fileGroup->x()+2, fileGroup->y()+2, fileGroup->w()-4, 20, this ); filecolumns->hide(); + if (gMidnight) + { + filecolumns->color(FL_BLACK); + filecolumns->labelcolor(FL_WHITE); + } + filecolumns->end(); filescroll = new Fl_Scroll( fileGroup->x()+2, fileGroup->y()+22, fileGroup->w()-4, fileGroup->h()-20-4 ); filescroll->color( FL_WHITE ); + if (gMidnight) + { + filescroll->color(FL_BLACK); + filescroll->labelcolor(FL_WHITE); + } filescroll->scrollbar.linesize( 20 ); filescroll->box( FL_FLAT_BOX ); filescroll->type( Fl_Scroll::VERTICAL ); { filedetails = new FileDetails( fileGroup->x()+2, fileGroup->y()+22, fileGroup->w()-4, fileGroup->h()-20-4, this ); + if (gMidnight) + { + filedetails->color(FL_BLACK); + filedetails->labelcolor(FL_WHITE); + } filedetails->end(); } filescroll->end(); @@ -527,6 +568,18 @@ Flu_File_Chooser :: Flu_File_Chooser( const char *pathname, const char *pat, int ok.callback( _okCB, this ); cancel.callback( _cancelCB, this ); + if (gMidnight) + { + ok.color(FL_BLACK); + ok.labelcolor(FL_WHITE); + cancel.color(FL_BLACK); + cancel.labelcolor(FL_WHITE); + filename.color(FL_BLACK); + filename.labelcolor(FL_WHITE); + filename.textcolor(FL_WHITE); + filename.cursor_color(FL_WHITE); + filePattern->set_colors(FL_BLACK, FL_WHITE); + } { g = new Fl_Group( 0, h()-60, w(), 30 ); @@ -577,7 +630,8 @@ Flu_File_Chooser :: Flu_File_Chooser( const char *pathname, const char *pat, int //printf( "load: %s %X\n", buf, f ); if( f ) { - int scanLen = fscanf(f, "%d, %d\n", &neww, &newh); + int dummy = fscanf(f, "%d, %d\n", &neww, &newh); + (void) dummy; buf[0] = '\0'; while( !feof(f) ) { @@ -828,6 +882,12 @@ void Flu_File_Chooser :: newFolderCB() // create a new entry with the name of the new folder. add to either the list or the details Entry *entry = new Entry( newName.c_str(), ENTRY_DIR, fileDetailsBtn->value(), this ); + if (gMidnight) + { + entry->color(FL_BLACK); + entry->textcolor(FL_WHITE); + entry->cursor_color(FL_WHITE); + } if( !fileDetailsBtn->value() ) filelist->add( *entry ); else @@ -1440,6 +1500,11 @@ Flu_File_Chooser :: FileColumns :: FileColumns( int x, int y, int w, int h, Flu_ c->detailNameBtn = new Flu_Button( x, y, W1, h, "Name" ); c->detailNameBtn->align( FL_ALIGN_CLIP ); c->detailNameBtn->callback( Flu_File_Chooser::_sortCB, c ); + if (gMidnight) + { + c->detailNameBtn->color(fl_rgb_color(0x0e, 0x17, 0x18)); + c->detailNameBtn->labelcolor(FL_WHITE); + } { CBTile *tile = new CBTile( x+W1, y, W2+W3+W4, h, c ); Fl_Box *box = new Fl_Box( tile->x()+50, tile->y(), tile->w()-150, tile->h() ); @@ -1447,6 +1512,11 @@ Flu_File_Chooser :: FileColumns :: FileColumns( int x, int y, int w, int h, Flu_ c->detailTypeBtn = new Flu_Button( x+W1, y, W2, h, "Type" ); c->detailTypeBtn->align( FL_ALIGN_CLIP ); c->detailTypeBtn->callback( Flu_File_Chooser::_sortCB, c ); + if (gMidnight) + { + c->detailTypeBtn->color(fl_rgb_color(0x0e, 0x17, 0x18)); + c->detailTypeBtn->labelcolor(FL_WHITE); + } { CBTile *tile = new CBTile( x+W1+W2, y, W3+W4, h, c ); Fl_Box *box = new Fl_Box( tile->x()+50, tile->y(), tile->w()-100, tile->h() ); @@ -1457,6 +1527,13 @@ Flu_File_Chooser :: FileColumns :: FileColumns( int x, int y, int w, int h, Flu_ c->detailDateBtn = new Flu_Button( x+W1+W2+W3, y, W4, h, "Date" ); c->detailDateBtn->align( FL_ALIGN_CLIP ); c->detailDateBtn->callback( Flu_File_Chooser::_sortCB, c ); + if (gMidnight) + { + c->detailSizeBtn->color(fl_rgb_color(0x0e, 0x17, 0x18)); + c->detailSizeBtn->labelcolor(FL_WHITE); + c->detailDateBtn->color(fl_rgb_color(0x0e, 0x17, 0x18)); + c->detailDateBtn->labelcolor(FL_WHITE); + } tile->end(); } tile->end(); @@ -1917,11 +1994,10 @@ void Flu_File_Chooser :: Entry :: updateSize() nameW = w(); // how big is the icon? - int iW = 0, iH = 0; + int iW = 0; if( icon ) { iW = icon->w()+2; - iH = icon->h(); } fl_font( labelfont(), labelsize() ); @@ -2354,12 +2430,26 @@ int Flu_File_Chooser :: popupContextMenu( Entry *entry ) void Flu_File_Chooser :: Entry :: draw() { + int white; + int black; + + if (gMidnight) + { + white = FL_BLACK; + black = FL_WHITE; + } + else + { + white = FL_WHITE; + black = FL_BLACK; + } + if( editMode ) { if( editMode == 2 ) { editMode--; - fl_draw_box( FL_FLAT_BOX, x(), y(), w(), h(), FL_WHITE ); + fl_draw_box( FL_FLAT_BOX, x(), y(), w(), h(), white ); redraw(); } Fl_Input::draw(); @@ -2369,12 +2459,15 @@ void Flu_File_Chooser :: Entry :: draw() if( selected ) { fl_draw_box( FL_FLAT_BOX, x(), y(), w(), h(), FL_SELECTION_COLOR ); - fl_color( FL_WHITE ); + if (gMidnight) + fl_color( black ); + else + fl_color( white ); } else { - fl_draw_box( FL_FLAT_BOX, x(), y(), w(), h(), FL_WHITE ); - fl_color( FL_BLACK ); + fl_draw_box( FL_FLAT_BOX, x(), y(), w(), h(), white ); + fl_color( black ); } int X = x()+4; @@ -2943,7 +3036,7 @@ void Flu_File_Chooser :: cd( const char *localpath ) previewGroup->redraw(); filelist->scroll_to_beginning(); - filescroll->position( 0, 0 ); + //KDP filescroll->position( 0, 0 ); bool listMode = !fileDetailsBtn->value() || streq( localpath, FAVORITES_UNIQUE_STRING ); @@ -2975,13 +3068,14 @@ void Flu_File_Chooser :: cd( const char *localpath ) { filelist->hide(); filecolumns->show(); + //filescroll->position( filecolumns->x(), filecolumns->y()+20); filescroll->show(); filescroll->parent()->resizable( filescroll ); updateEntrySizes(); } FluSimpleString currentFile = filename.value(); - filescroll->position( 0, 0 ); + // KDP filescroll->position( 0, 0 ); Fl::focus( &filename ); upDirBtn->activate(); ok.activate(); @@ -3008,6 +3102,12 @@ void Flu_File_Chooser :: cd( const char *localpath ) for( int i = 1; i <= favoritesList->size(); i++ ) { entry = new Entry( favoritesList->text(i), ENTRY_FAVORITE, false/*fileDetailsBtn->value()*/, this ); + if (gMidnight) + { + entry->color(FL_BLACK); + entry->textcolor(FL_WHITE); + entry->cursor_color(FL_WHITE); + } entry->updateSize(); entry->updateIcon(); } @@ -3115,6 +3215,12 @@ void Flu_File_Chooser :: cd( const char *localpath ) char drive[] = "A:/"; drive[0] = 'A' + i; entry = new Entry( drive, ENTRY_DRIVE, fileDetailsBtn->value(), this ); + if (gMidnight) + { + entry->color(FL_BLACK); + entry->textcolor(FL_WHITE); + entry->cursor_color(FL_WHITE); + } switch( driveTypes[i] ) { case DRIVE_REMOVABLE: entry->description = "Floppy Disk"; break; @@ -3144,9 +3250,21 @@ void Flu_File_Chooser :: cd( const char *localpath ) else filedetails->begin(); entry = new Entry( "My Documents", ENTRY_MYDOCUMENTS, fileDetailsBtn->value(), this ); + if (gMidnight) + { + entry->color(FL_BLACK); + entry->textcolor(FL_WHITE); + entry->cursor_color(FL_WHITE); + } entry->updateSize(); entry->updateIcon(); entry = new Entry( "My Computer", ENTRY_MYCOMPUTER, fileDetailsBtn->value(), this ); + if (gMidnight) + { + entry->color(FL_BLACK); + entry->textcolor(FL_WHITE); + entry->cursor_color(FL_WHITE); + } entry->updateSize(); entry->updateIcon(); if( listMode ) @@ -3355,6 +3473,12 @@ void Flu_File_Chooser :: cd( const char *localpath ) // add directories at the beginning, and files at the end entry = new Entry( name, isDir?ENTRY_DIR:ENTRY_FILE, fileDetailsBtn->value(), this ); + if (gMidnight) + { + entry->color(FL_BLACK); + entry->textcolor(FL_WHITE); + entry->cursor_color(FL_WHITE); + } if( isDir ) { if( listMode ) diff --git a/src/Flu_Tree_Browser.cpp b/src/Flu_Tree_Browser.cpp index 4c4b6b1..43168b7 100644 --- a/src/Flu_Tree_Browser.cpp +++ b/src/Flu_Tree_Browser.cpp @@ -3398,6 +3398,7 @@ Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: insert_at( Node* p, Node* i, rdata.visibilityChanged = true; free( nodeName ); + (void) remainingPath; return retNode; } @@ -3478,3 +3479,14 @@ void Flu_Tree_Browser :: Node :: leaf_icon( Fl_Image *icon ) tree->rdata.forceResize = true; } } + +void Flu_Tree_Browser :: set_colors ( Fl_Color bgcolor, Fl_Color textcolor ) +{ + _box->color(bgcolor); + color(bgcolor); + branch_text( textcolor, FL_HELVETICA_BOLD, 12 ); + leaf_text( textcolor, FL_HELVETICA, 12 ); + shaded_entry_colors( bgcolor, bgcolor ); + connector_style( textcolor, FL_DOT ); +} + diff --git a/src/VirtualT.h b/src/VirtualT.h index 0e510eb..78a5962 100644 --- a/src/VirtualT.h +++ b/src/VirtualT.h @@ -31,7 +31,7 @@ #ifndef _VIRTUALT_H_ #define _VIRTUALT_H_ -#define VERSION "1.7" +#define VERSION "1.8" enum { MODEL_M100 diff --git a/src/chargen.cpp b/src/chargen.cpp index 9ede039..36042be 100644 --- a/src/chargen.cpp +++ b/src/chargen.cpp @@ -57,6 +57,11 @@ #define EDIT_FIELD_X 200 #define EDIT_FIELD_Y 10 +#define COLOR_BG (gMidnight ? FL_BLACK : fl_rgb_color(192, 192, 192)) +#define COLOR_BG_INPUT (gMidnight ? FL_BLACK : FL_WHITE) +#define COLOR_FG (gMidnight ? FL_WHITE : FL_BLACK) + +extern int gMidnight; VTCharacterGen* gpCharGen; /* @@ -135,25 +140,37 @@ VTCharacterGen::VTCharacterGen(int w, int h, const char* title) : Fl_Box* o; Fl_Button* b; + // Set the window background color + color(COLOR_BG); + // Create Text field with char value o = new Fl_Box(FL_NO_BOX, 20, 10, 100, 20, "Character:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); m_pCharText = new Fl_Box(FL_NO_BOX, 120, 10, 60, 20, ""); m_pCharText->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pCharText->labelcolor(COLOR_FG); // Create Clear, Copy, Paste buttons b = new Fl_Button(20, 45, 60, 25, "Copy"); b->callback(cb_Copy); + b->color(COLOR_BG); + b->labelcolor(COLOR_FG); b = new Fl_Button(100, 45, 60, 25, "Paste"); b->callback(cb_Paste); + b->color(COLOR_BG); + b->labelcolor(COLOR_FG); b = new Fl_Button(20, 80, 60, 25, "Clear"); b->callback(cb_Clear); + b->color(COLOR_BG); + b->labelcolor(COLOR_FG); for (c = 0; c < 6; c++) for (r = 0; r < 9; r++) { - m_pBoxes[c][r] = new Fl_Box(FL_BORDER_BOX, EDIT_FIELD_X + c*GRID_SIZE, + m_pBoxes[c][r] = new Fl_Box(FL_BORDER_FRAME, EDIT_FIELD_X + c*GRID_SIZE, EDIT_FIELD_Y + r*GRID_SIZE, GRID_SIZE+1, GRID_SIZE+1, ""); + m_pBoxes[c][r]->color(COLOR_FG); } // Generate the dots for (c = 0; c < 11; c++) @@ -161,7 +178,7 @@ VTCharacterGen::VTCharacterGen(int w, int h, const char* title) : { m_pDots[c][r] = new Fl_Box(FL_OVAL_BOX, EDIT_FIELD_X + c*GRID_SIZE/2+5, EDIT_FIELD_Y +r*GRID_SIZE+5, GRID_SIZE-10, GRID_SIZE-10, ""); - m_pDots[c][r]->color(FL_BLACK); + m_pDots[c][r]->color(COLOR_FG); m_pDots[c][r]->hide(); m_Dots[c][r] = 0; } @@ -169,59 +186,77 @@ VTCharacterGen::VTCharacterGen(int w, int h, const char* title) : // Create text for the sample output displays o = new Fl_Box(EDIT_FIELD_X + GRID_SIZE * 7, 10, 80, 20, "Pica:"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); m_pExPica = new Fl_Box(FL_NO_BOX, EDIT_FIELD_X + GRID_SIZE * 7 + 100, 10, 35, 35, ""); + m_pExPica->color(COLOR_FG); + m_pExPica->labelcolor(COLOR_FG); o = new Fl_Box(EDIT_FIELD_X + GRID_SIZE * 7, 50, 80, 20, "Expanded:"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); - m_pExPica = new Fl_Box(FL_NO_BOX, EDIT_FIELD_X + GRID_SIZE * 7 + 100, 10, 35, 35, ""); + o->labelcolor(COLOR_FG); + //m_pExPica = new Fl_Box(FL_NO_BOX, EDIT_FIELD_X + GRID_SIZE * 7 + 100, 10, 35, 35, ""); m_pExExpand = new Fl_Box(FL_NO_BOX, EDIT_FIELD_X + GRID_SIZE * 7 + 100, 50, 35, 35, ""); o = new Fl_Box(EDIT_FIELD_X + GRID_SIZE * 7, 90, 80, 20, "Enhanced:"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); - m_pExPica = new Fl_Box(FL_NO_BOX, EDIT_FIELD_X + GRID_SIZE * 7 + 100, 10, 35, 35, ""); + o->labelcolor(COLOR_FG); + //m_pExPica = new Fl_Box(FL_NO_BOX, EDIT_FIELD_X + GRID_SIZE * 7 + 100, 10, 35, 35, ""); m_pExEnhance = new Fl_Box(FL_NO_BOX, EDIT_FIELD_X + GRID_SIZE * 7 + 100, 90, 35, 35, ""); o = new Fl_Box(EDIT_FIELD_X + GRID_SIZE * 7, 130, 80, 20, "Dbl-Strike:"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); - m_pExPica = new Fl_Box(FL_NO_BOX, EDIT_FIELD_X + GRID_SIZE * 7 + 100, 10, 35, 35, ""); + o->labelcolor(COLOR_FG); + //m_pExPica = new Fl_Box(FL_NO_BOX, EDIT_FIELD_X + GRID_SIZE * 7 + 100, 10, 35, 35, ""); m_pExDblStrike = new Fl_Box(FL_NO_BOX, EDIT_FIELD_X + GRID_SIZE * 7 + 100, 130, 35, 35, ""); o = new Fl_Box(EDIT_FIELD_X + GRID_SIZE * 7, 170, 80, 20, "Dbl-Enhance:"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); - m_pExPica = new Fl_Box(FL_NO_BOX, EDIT_FIELD_X + GRID_SIZE * 7 + 100, 10, 35, 35, ""); + o->labelcolor(COLOR_FG); + //m_pExPica = new Fl_Box(FL_NO_BOX, EDIT_FIELD_X + GRID_SIZE * 7 + 100, 10, 35, 35, ""); m_pExDblEnhance = new Fl_Box(FL_NO_BOX, EDIT_FIELD_X + GRID_SIZE * 7 + 100, 170, 35, 35, ""); // Create a character table m_pCharTable = new VTCharTable(40, EDIT_FIELD_Y + GRID_SIZE * 11, 15*32, 22*8,""); m_pCharTable->callback(cb_CloseCharGen); + m_pCharTable->color(COLOR_BG); // Text for the Char Table o = new Fl_Box(FL_NO_BOX, 10, EDIT_FIELD_Y+GRID_SIZE*11+5, 25, 15,"00h"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o->labelsize(10); o = new Fl_Box(FL_NO_BOX, 10, EDIT_FIELD_Y+GRID_SIZE*11+5+1*22, 25, 15,"20h"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o->labelsize(10); o = new Fl_Box(FL_NO_BOX, 10, EDIT_FIELD_Y+GRID_SIZE*11+5+2*22, 25, 15,"40h"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); o->labelsize(10); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 10, EDIT_FIELD_Y+GRID_SIZE*11+5+3*22, 25, 15,"60h"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); o->labelsize(10); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 10, EDIT_FIELD_Y+GRID_SIZE*11+5+4*22, 25, 15,"80h"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); o->labelsize(10); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 10, EDIT_FIELD_Y+GRID_SIZE*11+5+5*22, 25, 15,"A0h"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); o->labelsize(10); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 10, EDIT_FIELD_Y+GRID_SIZE*11+5+6*22, 25, 15,"C0h"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); o->labelsize(10); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 10, EDIT_FIELD_Y+GRID_SIZE*11+5+7*22, 25, 15,"E0h"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); o->labelsize(10); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 40, EDIT_FIELD_Y+GRID_SIZE*11-15, 25, 15,"00h"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); o->labelsize(10); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 40+15*32-22, EDIT_FIELD_Y+GRID_SIZE*11-15, 25, 15,"1Fh"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); o->labelsize(10); + o->labelcolor(COLOR_FG); // Create load button b = new Fl_Button(40, 460, 70, 30, "Load"); @@ -1120,7 +1155,7 @@ void VTCharTable::DrawChar(int index) if (index == m_ActiveChar) bk_color = fl_rgb_color(255, 255, 0); else - bk_color = FL_GRAY; + bk_color = COLOR_BG; for (j = 1; j < 12; j++) { @@ -1139,7 +1174,12 @@ void VTCharTable::DrawChar(int index) for (i = 7; i >= 0; i--) { if (m_Data[index][j] & (0x01 << i)) - fl_color(FL_BLACK); + { + if (index == m_ActiveChar) + fl_color(FL_BLACK); + else + fl_color(COLOR_FG); + } else fl_color(bk_color); diff --git a/src/clock.cpp b/src/clock.cpp index cb77e0c..ac034fd 100644 --- a/src/clock.cpp +++ b/src/clock.cpp @@ -48,6 +48,13 @@ #include "memory.h" #include "clock.h" +#define COLOR_BG (gMidnight ? FL_BLACK : fl_rgb_color(192, 192, 192)) +#define COLOR_BG_INPUT (gMidnight ? FL_BLACK : FL_WHITE) +#define COLOR_FG (gMidnight ? FL_WHITE : FL_BLACK) +#define COLOR_TAB_INACTIVE_BG (gMidnight ? fl_rgb_color(32,32,32) : fl_rgb_color(192,192,192)) +#define COLOR_TAB_INACTIVE_FG (gMidnight ? fl_rgb_color(192,192,192) : FL_BLACK) + +extern int gMidnight; uchar gClockMode = 255; uchar gRp5c01_mode; uchar gRp5c01_data[4][13]; @@ -556,24 +563,29 @@ void build_clock_setup_tab(void) { Fl_Box* pText = new Fl_Box(20, 10, 60, 80, "Clock operation upon power-up"); pText->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + pText->labelcolor(COLOR_FG); // Create Radio button for "Host Time" gClockCtrl.pSysTime = new Fl_Round_Button(20, 70, 200, 20, "Reset to Host Time"); gClockCtrl.pSysTime->type(FL_RADIO_BUTTON); gClockCtrl.pSysTime->callback(cb_clock_radio_sys); + gClockCtrl.pSysTime->labelcolor(COLOR_FG); gClockCtrl.pReload = new Fl_Check_Button(45, 95, 250, 20, "Reset time when changing models"); gClockCtrl.pReload->value(gReload); + gClockCtrl.pReload->labelcolor(COLOR_FG); if (gClockTimingMode != CLOCK_MODE_SYS) gClockCtrl.pReload->deactivate(); // Create Radio button for Model Clock Time gClockCtrl.pEmulTime = new Fl_Round_Button(20, 130, 200, 20, "Restore Emulated Time"); gClockCtrl.pEmulTime->type(FL_RADIO_BUTTON); + gClockCtrl.pEmulTime->labelcolor(COLOR_FG); gClockCtrl.pEmulTime->callback(cb_clock_radio_emul); gClockCtrl.pTimeElapse = new Fl_Check_Button(45, 155, 270, 20, "Time elapses while emulation stopped"); gClockCtrl.pTimeElapse->value(gTimeElapse); + gClockCtrl.pTimeElapse->labelcolor(COLOR_FG); if (gClockTimingMode != CLOCK_MODE_EMUL) gClockCtrl.pTimeElapse->deactivate(); diff --git a/src/cpu.h b/src/cpu.h index 09997c6..2b588c7 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -171,27 +171,15 @@ the settings for ReMem support. #else -#define SETPCINS16 {int pc=PC; PCL=get_memory8((unsigned short) pc++); PCH=get_memory8((unsigned short) pc);} -#define M (get_memory8(HL)) -#define INS (get_memory8(PC)) -#define INS_INC (get_memory8(PC); INCPC;) -#define NXTINS (get_memory8((unsigned short) (PC+1))) -#define INS16 (((int)get_memory8((unsigned short) (PC)))|(((int)get_memory8((unsigned short) (PC+1)))<<8)) -#define MEM(x) (get_memory8(x)) +#define SETPCINS16 {int pc=PC; PCL=get_memory8_counter((unsigned short) pc++); PCH=get_memory8_counter((unsigned short) pc);} +#define M (get_memory8_counter(HL)) +#define INS (get_memory8_counter(PC)) +#define INS_INC (get_memory8_counter(PC); INCPC;) +#define NXTINS (get_memory8_counter((unsigned short) (PC+1))) +#define INS16 (((int)get_memory8_counter((unsigned short) (PC)))|(((int)get_memory8_counter((unsigned short) (PC+1)))<<8)) +#define MEM(x) (get_memory8_counter(x)) #define MEM16(x) (((ushort)MEM(x))|((ushort)MEM(x+1))<<8) -#define MEMSET(a,v) {gRex?rex_set8((unsigned short)(a),v):remem_set8((unsigned short) (a), v); } - - -//#define SETPCINS16 {int pc=PC; PCL=get_memory8((unsigned short) pc++); PCH=get_memory8((unsigned short) pc);} -//#define M (gMemory[gIndex[HL]][HL & 0x3FF]) -//#define INS (gMemory[gIndex[PC]][PC & 0x3FF]) -//#define INS_INC (gMemory[gIndex[PC]][PC & 0x3FF]); INCPC; -//#define NXTINS (get_memory8((unsigned short) (PC+1))) -//#define INS16 (((int)get_memory8((unsigned short) (PC)))|(((int)get_memory8((unsigned short) (PC+1)))<<8)) -//#define MEM(x) (gMemory[gIndex[x]][x & 0x3FF]) -//#define MEM16(x) (((ushort)MEM(x))|((ushort)MEM(x+1))<<8) -//#define MEMSET(a,v) {remem_set8((unsigned short) (a), v); } - +#define MEMSET(a,v) (set_memory8((unsigned short)(a),v)) #endif diff --git a/src/cpuregs.cpp b/src/cpuregs.cpp index cee0e74..b00321f 100644 --- a/src/cpuregs.cpp +++ b/src/cpuregs.cpp @@ -677,7 +677,7 @@ void redraw_trace(Fl_Widget* w, void* pOpaque) int x, draw, lines, last_pc, last_sp; char lineStr[120], str[100]; int trace_top = gcpuw->m_pTraceBox->y() + gcpuw->m_fontHeight - 4; - int lookahead = 0, bold; + int lookahead = 0, bold = 0; int selStart, selEnd; // Clear rectangle @@ -985,7 +985,8 @@ unsigned char get_m() if (gReMem & !gRex) return (gMemory[gIndex[HL]][HL & 0x3FF]); else - return gBaseMemory[HL]; + return get_memory8(HL); + //return gBaseMemory[HL]; } /* @@ -2524,7 +2525,7 @@ VTCpuRegs::VTCpuRegs(int x, int y, const char *title) : /* Load the user preferences for window size, etc. */ LoadPrefs(); SetTraceColors(); - for (c = 0; c < sizeof(m_pad); c++) + for (c = 0; c < (int) sizeof(m_pad); c++) m_pad[c] = '1'; // Allocate the trace buffer diff --git a/src/display.cpp b/src/display.cpp index 706b31c..d4f2387 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -97,6 +97,7 @@ void cb_TpddServerLog(Fl_Widget* w, void*); Fl_Window *MainWin = NULL; T100_Disp *gpDisp; T100_Disp *gpDebugMonitor; +int gDefaultColor; Fl_Box *gpCode, *gpGraph, *gpKey, *gpSpeed, *gpCaps, *gpKeyInfo; Fl_Action_Icon *gpPrint; Fl_Box *gpMap = NULL; @@ -119,6 +120,7 @@ int gBackgroundColor = FL_GRAY; int gPixelColor = FL_BLACK; int gLabelColor = FL_WHITE; int gConsoleDebug = FALSE; +int gMidnight = 1; Fl_Double_Window* gDisplayColors; Fl_Button* gLcdBkButton; @@ -509,6 +511,57 @@ extern "C" void resize_window() } #endif /* ZIPIT_Z2 */ + if (gMidnight) + { + Menu->color(FL_BLACK); + Menu->textcolor(FL_WHITE); + Menu->selection_color(FL_BLUE); + MainWin->color(FL_BLACK); + MainWin->labelcolor(FL_WHITE); + + gpGraph->color(FL_BLACK); + gpGraph->labelcolor(FL_WHITE); + gpCode->color(FL_BLACK); + gpCode->labelcolor(FL_WHITE); + gpCaps->color(FL_BLACK); + gpCaps->labelcolor(FL_WHITE); + gpKey->color(FL_BLACK); + gpKey->labelcolor(FL_WHITE); + gpSpeed->color(FL_BLACK); + gpSpeed->labelcolor(FL_WHITE); + gpMap->color(FL_BLACK); + gpMap->labelcolor(FL_WHITE); + gpPrint->color(FL_BLACK); + gpPrint->labelcolor(FL_WHITE); + gpPrint->box(FL_DOWN_BOX); + gpKeyInfo->color(FL_BLACK); + gpKeyInfo->labelcolor(FL_WHITE); + } + else + { + Menu->color(gDefaultColor); + Menu->textcolor(FL_BLACK); + MainWin->color(gDefaultColor); + MainWin->labelcolor(FL_BLACK); + + gpGraph->color(gDefaultColor); + gpGraph->labelcolor(FL_BLACK); + gpCode->color(gDefaultColor); + gpCode->labelcolor(FL_BLACK); + gpCaps->color(gDefaultColor); + gpCaps->labelcolor(FL_BLACK); + gpKey->color(gDefaultColor); + gpKey->labelcolor(FL_BLACK); + gpSpeed->color(gDefaultColor); + gpSpeed->labelcolor(FL_BLACK); + gpMap->color(gDefaultColor); + gpMap->labelcolor(FL_BLACK); + gpPrint->color(gDefaultColor); + gpPrint->labelcolor(FL_BLACK); + gpPrint->box(FL_DOWN_BOX); + gpKeyInfo->color(gDefaultColor); + gpKeyInfo->labelcolor(FL_BLACK); + } gpDisp->CalcScreenCoords(); Fl::check(); @@ -721,6 +774,13 @@ void cb_save_co(Fl_Widget* w, void*) COSaveMode ^= 1; virtualt_prefs.set("COSaveMode",COSaveMode); } +void cb_midnight (Fl_Widget* w, void*) +{ + gMidnight ^= 1; + + virtualt_prefs.set("Midnight",gMidnight); + resize_window(); +} void cb_reset (Fl_Widget* w, void*) { @@ -755,7 +815,6 @@ void cb_coldBoot (Fl_Widget* w, void*) if (gReMem) { if (w != NULL) - //a = fl_choice("Cold Boot. Reload System ROM too?", "Cancel", "Yes", "No", NULL); a = fl_choice("Cold Boot. Reload System ROM too?", "Cancel", "Yes", "No"); else a = 2; @@ -1171,52 +1230,82 @@ cb_about: This callback routine displays the about box void cb_about (Fl_Widget* w, void*) { - Fl_Window* o = new Fl_Window(420, 340); + Fl_Window* o = new Fl_Window(520, 440); + if (gMidnight) + o->color(FL_BLACK); + + Fl_Window* o2 = new Fl_Window(50, 50, 420, 340); + if (gMidnight) + o2->color(FL_BLACK); - { Fl_Box* o = new Fl_Box(20, 0, 345, 95, "Virtual T"); + { Fl_Box* o = new Fl_Box(20, 0, 345, 85, "Virtual T"); o->labelfont(11); o->labelsize(80); + if (gMidnight) + o->labelcolor(FL_WHITE); } { Fl_Box* o = new Fl_Box(50, 105, 305, 40, "A Tandy Model 100/102/200 Emulator"); o->labelfont(8); - o->labelsize(24); + o->labelsize(20); + if (gMidnight) + o->labelcolor(FL_WHITE); } { Fl_Box* o = new Fl_Box(30, 150, 335, 35, "written by: "); o->labelfont(8); o->labelsize(18); + if (gMidnight) + o->labelcolor(FL_WHITE); } { Fl_Box* o = new Fl_Box(30, 170, 335, 35, "Ken Pettit"); o->labelfont(8); o->labelsize(18); + if (gMidnight) + o->labelcolor(FL_WHITE); } { Fl_Box* o = new Fl_Box(25, 190, 340, 35, "Stephen Hurd"); o->labelfont(8); o->labelsize(18); + if (gMidnight) + o->labelcolor(FL_WHITE); } { Fl_Box* o = new Fl_Box(25, 210, 340, 35, "Jerome Vernet"); o->labelfont(8); o->labelsize(18); + if (gMidnight) + o->labelcolor(FL_WHITE); } { Fl_Box* o = new Fl_Box(25, 230, 340, 35, "John Hogerhuis"); o->labelfont(8); o->labelsize(18); + if (gMidnight) + o->labelcolor(FL_WHITE); } { Fl_Box* o = new Fl_Box(95, 265, 195, 25, "V " VERSION); o->labelfont(8); o->labelsize(18); + if (gMidnight) + o->labelcolor(FL_WHITE); } { Fl_Box* o = new Fl_Box(35, 295, 320, 25, "This program may be distributed freely "); o->labelfont(8); o->labelsize(16); + if (gMidnight) + o->labelcolor(FL_WHITE); } { Fl_Box* o = new Fl_Box(35, 315, 320, 25, "under the terms of the BSD license"); o->labelfont(8); o->labelsize(16); + if (gMidnight) + o->labelcolor(FL_WHITE); } { Fl_Box* o = new Fl_Box(20, 75, 320, 20, "in FLTK"); o->labelfont(8); o->labelsize(18); + if (gMidnight) + o->labelcolor(FL_WHITE); } + o2->end(); + o2->show(); o->end(); o->show(); } @@ -1353,6 +1442,7 @@ Fl_Menu_Item menuitems[] = { { "Framed", 0, cb_framed, (void *) 1, FL_MENU_TOGGLE|FL_MENU_VALUE }, { "Solid Chars", 0, cb_solidchars, (void *) 1, FL_MENU_TOGGLE | FL_MENU_DIVIDER}, { "Display Colors", 0, cb_display_colors, 0, 0 }, + { "Midnight", 0, cb_midnight, (void *) 0, FL_MENU_TOGGLE}, { 0 }, { "Peripheral Setup...", 0, cb_PeripheralSetup, 0, 0 }, #ifdef __APPLE__ @@ -1376,6 +1466,7 @@ Fl_Menu_Item menuitems[] = { { "Enable Console Debug", 0, cb_ConsoleDebug }, #endif { "ReMem Configuration", 0, cb_RememCfg, 0, 0 }, +// { "Rex Monitor", 0, cb_RexMon, 0, 0 }, { "Peripheral Devices", 0, cb_PeripheralDevices }, { "Model T File Viewer", 0, cb_FileView }, { "TPDD Server Log", 0, cb_TpddServerLog, 0, FL_MENU_INVISIBLE }, @@ -1459,18 +1550,29 @@ void remote_set_speed(int speed) void init_menus(void) { int remem_menu_flag = FL_MENU_INVISIBLE; + //int rexmon_menu_flag = FL_MENU_INVISIBLE; int mIndex; if (gReMem) { remem_menu_flag = 0; } + //if (gRex) // added SA + //{ + //rexmon_menu_flag = 0; + //} // Locate the ReMem Configuration menu item mIndex = 0; while (menuitems[mIndex].callback_ != cb_RememCfg) mIndex++; menuitems[mIndex].flags= remem_menu_flag; + +// // Locate the ReMem Configuration menu item //added SA +// mIndex = 0; +// while (menuitems[mIndex].callback_ != cb_RexMon) +// mIndex++; +// menuitems[mIndex].flags= rexmon_menu_flag; } /* @@ -2003,6 +2105,7 @@ void init_pref(void) virtualt_prefs.get("MultFact",MultFact,3); virtualt_prefs.get("DisplayMode",DisplayMode,1); virtualt_prefs.get("SolidChars",SolidChars,0); + virtualt_prefs.get("Midnight",gMidnight,0); virtualt_prefs.get("BasicSaveMode",BasicSaveMode,0); virtualt_prefs.get("COSaveMode",COSaveMode,0); virtualt_prefs.get("Model",gModel, MODEL_M100); @@ -2154,6 +2257,15 @@ void init_display(void) #endif /* ZIPIT_Z2 */ Menu = new Fl_Menu_Bar(0, 0, MainWin->w(), MENU_HEIGHT-2); + gDefaultColor = Menu->color(); + if (gMidnight) + { + Menu->color(FL_BLACK); + Menu->textcolor(FL_WHITE); + Menu->selection_color(FL_BLUE); + MainWin->color(FL_BLACK); + MainWin->labelcolor(FL_WHITE); + } if (gModel == MODEL_T200) gpDisp = new T200_Disp(0, MENU_HEIGHT, MainWin->w(), MainWin->h() - MENU_HEIGHT - 20); else @@ -2273,6 +2385,19 @@ void init_display(void) menuitems[mIndex].flags=FL_MENU_TOGGLE|FL_MENU_VALUE|FL_MENU_DIVIDER; } + /* + ================================================== + Update Midnight menu item + ================================================== + */ + if(gMidnight==1) + { + mIndex = 0; + while (menuitems[mIndex].callback_ != cb_midnight) + mIndex++; + menuitems[mIndex].flags=FL_MENU_TOGGLE|FL_MENU_VALUE; + } + /* ================================================== Update BasicSaveMode parameter @@ -2366,6 +2491,27 @@ void init_display(void) gpDisp->CalcScreenCoords(); } + if (gMidnight) + { + gpGraph->color(FL_BLACK); + gpGraph->labelcolor(FL_WHITE); + gpCode->color(FL_BLACK); + gpCode->labelcolor(FL_WHITE); + gpCaps->color(FL_BLACK); + gpCaps->labelcolor(FL_WHITE); + gpKey->color(FL_BLACK); + gpKey->labelcolor(FL_WHITE); + gpSpeed->color(FL_BLACK); + gpSpeed->labelcolor(FL_WHITE); + gpMap->color(FL_BLACK); + gpMap->labelcolor(FL_WHITE); + gpPrint->color(FL_BLACK); + gpPrint->labelcolor(FL_WHITE); + gpPrint->box(FL_DOWN_BOX); + gpKeyInfo->color(FL_BLACK); + gpKeyInfo->labelcolor(FL_WHITE); + } + /* End the Window and show it */ MainWin->end(); @@ -3352,7 +3498,8 @@ drag selection and word drag selection. */ int T100_Disp::MouseMoveInText(int mx, int my) { - int cursorRow, cursorCol; + //int cursorRow + int cursorCol; int newCol, newRow, pos; // Calculate new row and col @@ -3365,7 +3512,7 @@ int T100_Disp::MouseMoveInText(int mx, int my) pos = newRow * 40 + newCol; // Find address of cursor row and col - cursorRow = find_stdrom_addr(R_CURSOR_ROW); + //cursorRow = find_stdrom_addr(R_CURSOR_ROW); cursorCol = find_stdrom_addr(R_CURSOR_COL); // Test if the cursor changed positions @@ -3409,7 +3556,7 @@ char keylabel[128]; int T100_Disp::handle(int event) { char keystr[10]; - char isSpecialKey = 1; + //char isSpecialKey = 1; int c; int simulated; get_key_t get_key; @@ -4041,7 +4188,7 @@ int T100_Disp::handle(int event) } } - isSpecialKey = 0; + //isSpecialKey = 0; break; } update_keys(); @@ -4489,7 +4636,7 @@ int T100_Disp::handle(int event) } } } - isSpecialKey = 0; + //isSpecialKey = 0; break; } update_keys(); @@ -5020,3 +5167,5 @@ void init_other_windows(void) MainWin->show(); } +// vim: noet sw=4 ts=4 + diff --git a/src/display.h b/src/display.h index 6525596..452a3fb 100644 --- a/src/display.h +++ b/src/display.h @@ -119,6 +119,7 @@ class T100_Disp : public Fl_Widget int m_BackgroundColor; int m_PixelColor; int m_LabelColor; + int m_DefaultColor; int m_DebugMonitor; int m_WheelKeys[32]; diff --git a/src/file.cpp b/src/file.cpp index efccdac..7bba3a9 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -45,18 +45,24 @@ extern "C" { +#include "VirtualT.h" #include "memory.h" #include "roms.h" #include "intelhex.h" #include "m100emu.h" extern RomDescription_t *gStdRomDesc; +extern int gMidnight; void jump_to_zero(void); } #include "file.h" #include "fileview.h" +#define COLOR_BG (gMidnight ? FL_BLACK : fl_rgb_color(192, 192, 192)) +#define COLOR_BG_INPUT (gMidnight ? FL_BLACK : FL_WHITE) +#define COLOR_FG (gMidnight ? FL_WHITE : FL_BLACK) + int BasicSaveMode = 0; int COSaveMode = 0; int gLoadError; // Indicates load error (for remote interface) @@ -257,7 +263,7 @@ int relocate(unsigned char* in, unsigned char* out, unsigned short addr) if (in[c] + (in[c+1] << 8) <= line_number) { - fl_message("%s", gIllformedBasic); + fl_message("1: %s", gIllformedBasic); return 0; } @@ -271,11 +277,52 @@ int relocate(unsigned char* in, unsigned char* out, unsigned short addr) line_len++; // Copy tokenized line - while (in[c] != 0) + if (gModel == MODEL_PC8201 || gModel == MODEL_PC8300) + { + // For MODEL_PC8201 or PC8300, the line can have embedded + // zeros. This is because integer numbers are encoded as 3 + // bytes: 0x0E LSB MSB + // So for a value of say, 256, the LSB would be zero. + while (in[c] != 0) + { + // Test for 0x0E encoding + if (in[c] == 0x0E || in[c] == 0x1C || in[c] == 0x1D) + { + int encoding = in[c]; + + // Copy this byte and the next directly + out[c] = in[c]; + c++; + out[c] = in[c]; + c++; + line_len += 2; + + // The 0x1D encoding is 4 bytes + if (encoding == 0x1D) + { + // Copy this byte and the next directly + out[c] = in[c]; + c++; + out[c] = in[c]; + c++; + line_len += 2; + } + } + + out[c] = in[c]; + c++; + line_len++; + } + } + else { - out[c] = in[c]; - c++; - line_len++; + // Each line is terminated with a zero + while (in[c] != 0) + { + out[c] = in[c]; + c++; + line_len++; + } } out[c] = in[c]; // Copy terminating zero @@ -292,7 +339,7 @@ int relocate(unsigned char* in, unsigned char* out, unsigned short addr) addr1 = in[this_line] + (in[this_line+1] << 8); if (addr1 != base + line_len) { - fl_message("%s", gIllformedBasic); + fl_message("2: %s", gIllformedBasic); return 0; } } @@ -369,7 +416,7 @@ int tokenize(unsigned char* in, unsigned char* out, unsigned short addr) // Check for characters with no line number else if (line_num_len == 0) { - fl_message("%s", gIllformedBasic); + fl_message("3: %s", gIllformedBasic); return 0; } @@ -972,6 +1019,9 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) // Close the file fclose(fd); + if (readlen == 0) + return; + // Determine file location if (file_type == TYPE_BA) { @@ -985,6 +1035,8 @@ void cb_LoadFromHost(Fl_Widget* w, void* host_filename) { addr1 = get_memory16(gStdRomDesc->sFilePtrDO); } + else + return; // Determine length of data and expand LF to CRLF if (file_type == TYPE_DO) @@ -1492,11 +1544,19 @@ void cb_SaveToHost(Fl_Widget* w, void*) // Create the windows gSaveToHost = new Fl_Window(220,320,"Select file to save to Host"); + gSaveToHost->color(COLOR_BG); fsb = new Fl_Hold_Browser(0, 0, 220,280); + fsb->color(COLOR_BG); + fsb->labelcolor(COLOR_FG); + fsb->textcolor(COLOR_FG); fsave = new Fl_Button(20,288,80,25,"Save"); + fsave->color(COLOR_BG); + fsave->labelcolor(COLOR_FG); fsave->callback(cb_save); fcancel = new Fl_Button(130, 288, 80, 25, "Cancel"); fcancel->callback(cb_cancel); + fcancel->color(COLOR_BG); + fcancel->labelcolor(COLOR_FG); // Add Model T files to the browser addr1 = gStdRomDesc->sDirectory; diff --git a/src/fileprint.cpp b/src/fileprint.cpp index 5b1026e..8ae98b6 100644 --- a/src/fileprint.cpp +++ b/src/fileprint.cpp @@ -56,6 +56,12 @@ extern "C" struct tm* mytime; +extern int gMidnight; + +#define COLOR_BG (gMidnight ? FL_BLACK : fl_rgb_color(192, 192, 192)) +#define COLOR_BG_INPUT (gMidnight ? FL_BLACK : FL_WHITE) +#define COLOR_FG (gMidnight ? FL_WHITE : FL_BLACK) + /* ================================================================================ VTFilePrint: This is the class constructor for the FilePrint Printer. @@ -305,38 +311,50 @@ void VTFilePrint::BuildPropertyDialog(Fl_Window* pParent) { // Create controls for File Output emulaiton mode Fl_Box* o = new Fl_Box(20, 20, 360, 20, "File Output Printer"); + o->labelcolor(COLOR_FG); // File Directory Name o = new Fl_Box(20, 50, 300, 20, "File Output Directory"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); m_pDirName = new Fl_Input(50, 75, 300, 20, ""); m_pDirName->value(m_DirName); + m_pDirName->color(COLOR_BG); + m_pDirName->textcolor(COLOR_FG); + m_pDirName->cursor_color(COLOR_FG); // Prompt for filename m_pPrompt = new Fl_Check_Button(20, 110, 200, 20, "Prompt for filename"); m_pPrompt->value(m_Prompt); + m_pPrompt->labelcolor(COLOR_FG); // Pages in separate files m_pSeparateFiles = new Fl_Check_Button(20, 135, 200, 20, "Print pages to separate files"); m_pSeparateFiles->value(m_SeparateFiles); m_pSeparateFiles->callback(cb_SeparateFiles, this); + m_pSeparateFiles->labelcolor(COLOR_FG); // Auto formatted filenames m_pAutoFormat = new Fl_Check_Button(20, 160, 200, 20, "Automatically generate filenames"); m_pAutoFormat->value(m_AutoFormat); + m_pAutoFormat->labelcolor(COLOR_FG); // Filename format string o = new Fl_Box(50, 185, 50, 20, "Format"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); m_pFormatCode = new Fl_Input(110, 185, 180, 20, ""); m_pFormatCode->value(m_FormatCode); + m_pFormatCode->color(COLOR_BG); + m_pFormatCode->textcolor(COLOR_FG); + m_pFormatCode->cursor_color(COLOR_FG); o = new Fl_Box(110, 210, 50, 20, "%d=Date %s=Seq# %p=Page#"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); // Control code filtering m_pFilterCodes = new Fl_Check_Button(20, 235, 200, 20, "Filter control codes"); m_pFilterCodes->value(m_FilterCodes); - + m_pFilterCodes->labelcolor(COLOR_FG); } /* diff --git a/src/fx80print.cpp b/src/fx80print.cpp index 51c5842..2ef34e9 100644 --- a/src/fx80print.cpp +++ b/src/fx80print.cpp @@ -51,6 +51,12 @@ #include "vtpaper.h" #include "chargen.h" +extern int gMidnight; + +#define COLOR_BG (gMidnight ? FL_BLACK : fl_rgb_color(192, 192, 192)) +#define COLOR_BG_INPUT (gMidnight ? FL_BLACK : FL_WHITE) +#define COLOR_FG (gMidnight ? FL_WHITE : FL_BLACK) + extern unsigned char gFX80CharRom[256][12]; unsigned char gIntlTable[9][12] = { @@ -355,23 +361,31 @@ void VTFX80Print::BuildPropertyDialog(Fl_Window* pParent) // Resize the parent pParent->resize(pParent->x(), pParent->y(), pParent->w()+300, pParent->h()); + pParent->color(COLOR_BG); o = new Fl_Box(20, 15, 660, 20, "Emulated Epson FX-80 Printer"); + o->labelcolor(COLOR_FG); // Create checkbox for use of external ROM file m_pUseRomFile = new Fl_Check_Button(20, 50, 230, 20, "Use External Character ROM"); m_pUseRomFile->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); m_pUseRomFile->value(m_useRomFile); m_pUseRomFile->callback(cb_UseRomCheck, this); + m_pUseRomFile->labelcolor(COLOR_FG); // Create edit field for External ROM file m_pRomFile = new Fl_Input(40, 78, 260, 20, ""); strcpy(m_romFileStr, (const char *) m_sRomFile); m_pRomFile->value(m_romFileStr); + m_pRomFile->color(COLOR_BG); + m_pRomFile->textcolor(COLOR_FG); + m_pRomFile->cursor_color(COLOR_FG); // Create Browse button m_pRomBrowse = new Fl_Button(315, 73, 60, 30, "Browse"); m_pRomBrowse->callback(cb_CharRomBrowse, this); + m_pRomBrowse->color(COLOR_BG); + m_pRomBrowse->labelcolor(COLOR_FG); // Deactivate controls if check not selected if (!m_useRomFile) @@ -385,15 +399,21 @@ void VTFX80Print::BuildPropertyDialog(Fl_Window* pParent) m_pUseRamFile->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); m_pUseRamFile->value(m_useRamFile); m_pUseRamFile->callback(cb_UseRomCheck, this); + m_pUseRamFile->labelcolor(COLOR_FG); // Create edit field for External RAM file m_pRamFile = new Fl_Input(40, 128, 260, 20, ""); strcpy(m_ramFileStr, (const char *) m_sRamFile); m_pRamFile->value(m_ramFileStr); + m_pRamFile->color(COLOR_BG); + m_pRamFile->textcolor(COLOR_FG); + m_pRamFile->cursor_color(COLOR_FG); // Create Browse button m_pRamBrowse = new Fl_Button(315, 123, 60, 30, "Browse"); m_pRamBrowse->callback(cb_CharRomBrowse, this); + m_pRamBrowse->color(COLOR_BG); + m_pRamBrowse->labelcolor(COLOR_FG); // Deactivate controls if check not selected if (!m_useRamFile) @@ -421,6 +441,9 @@ void VTFX80Print::BuildPropertyDialog(Fl_Window* pParent) } } m_pPaperChoice->callback(cb_PaperSelect, this); + m_pPaperChoice->color(COLOR_BG); + m_pPaperChoice->textcolor(COLOR_FG); + m_pPaperChoice->labelcolor(COLOR_FG); // Ensure a paper is selected if (m_pPaperChoice->value() == -1) @@ -437,24 +460,30 @@ void VTFX80Print::BuildPropertyDialog(Fl_Window* pParent) // Create controls for setting DIP switch default settings o = new Fl_Box(470, 50, 280, 20, "DIP Switch Settings"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_BORDER_BOX, 510, 75, 50, 170, ""); // Create buttons for International Char Set o = new Fl_Box(440, 85, 60, 20, "Intl Char"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(440, 107, 60, 20, "Set"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); g = new Fl_Group(510,78, 60, 25); + g->color(COLOR_FG); m_pIntlChar4off = new Fl_Round_Button(515, 80, 20, 20, ""); m_pIntlChar4off->type(102); m_pIntlChar4off->callback(cb_IntlCharDip, this); + m_pIntlChar4off->labelcolor(COLOR_FG); if (!(m_defCharSet & 0x04)) m_pIntlChar4off->value(1); m_pIntlChar4on = new Fl_Round_Button(538, 80, 20, 20, ""); m_pIntlChar4on->type(102); m_pIntlChar4on->callback(cb_IntlCharDip, this); + m_pIntlChar4on->labelcolor(COLOR_FG); if (m_defCharSet & 0x04) m_pIntlChar4on->value(1); g->end(); @@ -462,11 +491,13 @@ void VTFX80Print::BuildPropertyDialog(Fl_Window* pParent) m_pIntlChar2off = new Fl_Round_Button(515, 100, 20, 20, ""); m_pIntlChar2off->type(102); m_pIntlChar2off->callback(cb_IntlCharDip, this); + m_pIntlChar2off->labelcolor(COLOR_FG); if (!(m_defCharSet & 0x02)) m_pIntlChar2off->value(1); m_pIntlChar2on = new Fl_Round_Button(538, 100, 20, 20, ""); m_pIntlChar2on->type(102); m_pIntlChar2on->callback(cb_IntlCharDip, this); + m_pIntlChar2on->labelcolor(COLOR_FG); if (m_defCharSet & 0x02) m_pIntlChar2on->value(1); g->end(); @@ -474,16 +505,19 @@ void VTFX80Print::BuildPropertyDialog(Fl_Window* pParent) m_pIntlChar1off = new Fl_Round_Button(515, 120, 20, 20, ""); m_pIntlChar1off->type(102); m_pIntlChar1off->callback(cb_IntlCharDip, this); + m_pIntlChar1off->labelcolor(COLOR_FG); if (!(m_defCharSet & 0x01)) m_pIntlChar1off->value(1); m_pIntlChar1on = new Fl_Round_Button(538, 120, 20, 20, ""); m_pIntlChar1on->type(102); m_pIntlChar1on->callback(cb_IntlCharDip, this); + m_pIntlChar1on->labelcolor(COLOR_FG); if (m_defCharSet & 0x01) m_pIntlChar1on->value(1); g->end(); m_pIntlCharText = new Fl_Box(580, 95, 80, 20, ""); m_pIntlCharText->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pIntlCharText->labelcolor(COLOR_FG); // Set the international character set text SetIntlDipText(m_defCharSet); @@ -491,17 +525,21 @@ void VTFX80Print::BuildPropertyDialog(Fl_Window* pParent) // Create switch for Print Weight o = new Fl_Box(440, 140, 60, 20, "Emphasized"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(570, 140, 60, 20, "Single Strike"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); // Create switches for Print Weight g = new Fl_Group(510,140, 60, 25); m_pPrintWeightOff = new Fl_Round_Button(515, 140, 20, 20, ""); m_pPrintWeightOff->type(102); + m_pPrintWeightOff->labelcolor(COLOR_FG); if (m_defEnhance) m_pPrintWeightOff->value(1); m_pPrintWeightOn = new Fl_Round_Button(538, 140, 20, 20, ""); m_pPrintWeightOn->type(102); + m_pPrintWeightOn->labelcolor(COLOR_FG); if (!m_defEnhance) m_pPrintWeightOn->value(1); g->end(); @@ -509,17 +547,21 @@ void VTFX80Print::BuildPropertyDialog(Fl_Window* pParent) // Create switch for Zero slash o = new Fl_Box(440, 160, 60, 20, "Zero Slashed"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(570, 160, 60, 20, "Zero Normal"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); // Create switches for Print Weight g = new Fl_Group(510,160, 60, 25); m_pZeroSlashOff = new Fl_Round_Button(515, 160, 20, 20, ""); m_pZeroSlashOff->type(102); + m_pZeroSlashOff->labelcolor(COLOR_FG); if (m_zeroSlashed) m_pZeroSlashOff->value(1); m_pZeroSlashOn = new Fl_Round_Button(538, 160, 20, 20, ""); m_pZeroSlashOn->type(102); + m_pZeroSlashOn->labelcolor(COLOR_FG); if (!m_zeroSlashed) m_pZeroSlashOn->value(1); g->end(); @@ -527,17 +569,21 @@ void VTFX80Print::BuildPropertyDialog(Fl_Window* pParent) // Create switch for Print Pitch o = new Fl_Box(440, 180, 60, 20, "Compressed"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(570, 180, 60, 20, "Pica"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); // Create switches for Print Pitch g = new Fl_Group(510,180, 60, 25); m_pPitchOff = new Fl_Round_Button(515, 180, 20, 20, ""); m_pPitchOff->type(102); + m_pPitchOff->labelcolor(COLOR_FG); if (m_defCompressed) m_pPitchOff->value(1); m_pPitchOn = new Fl_Round_Button(538, 180, 20, 20, ""); m_pPitchOn->type(102); + m_pPitchOn->labelcolor(COLOR_FG); if (!m_defCompressed) m_pPitchOn->value(1); g->end(); @@ -545,17 +591,21 @@ void VTFX80Print::BuildPropertyDialog(Fl_Window* pParent) // Create switch for Auto CR o = new Fl_Box(440, 200, 60, 20, "CR + LF"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(570, 200, 60, 20, "CR Only"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); // Create switches for Auto CR g = new Fl_Group(510,200, 60, 25); m_pAutoCROff = new Fl_Round_Button(515, 200, 20, 20, ""); m_pAutoCROff->type(102); + m_pAutoCROff->labelcolor(COLOR_FG); if (m_autoCR) m_pAutoCROff->value(1); m_pAutoCROn = new Fl_Round_Button(538, 200, 20, 20, ""); m_pAutoCROn->type(102); + m_pAutoCROn->labelcolor(COLOR_FG); if (!m_autoCR) m_pAutoCROn->value(1); g->end(); @@ -563,18 +613,22 @@ void VTFX80Print::BuildPropertyDialog(Fl_Window* pParent) // Create switch for Skip Perforation o = new Fl_Box(440, 220, 60, 20, "Skip Perforation"); o->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(570, 220, 60, 20, "No Skip"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); // Create switches for Skip Perforation g = new Fl_Group(510,220, 60, 25); m_pSkipPerfOff = new Fl_Round_Button(515, 220, 20, 20, ""); m_pSkipPerfOff->type(102); + m_pSkipPerfOff->labelcolor(COLOR_FG); m_pSkipPerfOff->callback(cb_SkipPerf, this); if (m_defSkipPerf) m_pSkipPerfOff->value(1); m_pSkipPerfOn = new Fl_Round_Button(538, 220, 20, 20, ""); m_pSkipPerfOn->type(102); + m_pSkipPerfOn->labelcolor(COLOR_FG); m_pSkipPerfOn->callback(cb_SkipPerf, this); if (!m_defSkipPerf) m_pSkipPerfOn->value(1); @@ -583,19 +637,27 @@ void VTFX80Print::BuildPropertyDialog(Fl_Window* pParent) // Create control for setting the Top of Form o = new Fl_Box(400, 250, 60, 20, "Top of Form"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); m_pTopOfForm = new Fl_Input(510, 250, 60, 20, ""); m_pTopOfForm->value(m_topOfFormStr); + m_pTopOfForm->color(COLOR_BG); + m_pTopOfForm->textcolor(COLOR_FG); + m_pTopOfForm->cursor_color(COLOR_FG); o = new Fl_Box(575, 250, 60, 20, "inches from top"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); // Create checkbox for auto-word wrap (not a feature of original FX-80) m_pAutoWrap = new Fl_Check_Button(400, 280, 230, 20, "Auto wrap (CR/LF at end of line)"); m_pAutoWrap->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); m_pAutoWrap->value(m_autoWrap); + m_pAutoWrap->labelcolor(COLOR_FG); // Button for Character Generator b = new Fl_Button(360, 310, 120, 30, "Char Generator"); b->callback(cb_CreateNewCharGen); + b->color(COLOR_BG); + b->labelcolor(COLOR_FG); } /* @@ -631,7 +693,7 @@ void VTFX80Print::SetIntlDipText(char intlCode) if (intlCode > 8) return; - m_pIntlCharText->label(gIntlCharDesc[intlCode]); + m_pIntlCharText->label(gIntlCharDesc[(int) intlCode]); } /* @@ -1066,7 +1128,8 @@ void VTFX80Print::ResetPrinter(void) fclose(fd); // Indicate ROM loaded - fileLoaded = TRUE; + if (readlen == sizeof(m_charRom)) + fileLoaded = TRUE; } } } @@ -1576,7 +1639,7 @@ int VTFX80Print::ProcessAsCmd(unsigned char byte) // On first byte, copy ROM to RAM if (m_escParamsRcvd == 0) { - for (c = 0; c < sizeof(m_charRam); c++) + for (c = 0; c < (int) sizeof(m_charRam); c++) ((char*)m_charRam)[c] = ((char*)m_charRom)[c]; m_escParamsRcvd++; } @@ -2028,7 +2091,7 @@ int VTFX80Print::SetVertChannelTabs(unsigned char byte) return TRUE; } else if ((byte == 0) || ((m_escParamsRcvd > 1) && - (byte < m_vertTabs[m_escTabChannel][m_escParamsRcvd-2]))) + (byte < m_vertTabs[(int) m_escTabChannel][(int) m_escParamsRcvd-2]))) { m_escCmd = m_escParamsRcvd = 0; return TRUE; @@ -2039,7 +2102,7 @@ int VTFX80Print::SetVertChannelTabs(unsigned char byte) { if (m_escTabChannel < 8) { - m_vertTabs[m_escTabChannel][m_escParamsRcvd++] = + m_vertTabs[(int) m_escTabChannel][m_escParamsRcvd++] = (int) (m_vertDpi * (double) byte * m_lineSpacing); } else @@ -2315,7 +2378,7 @@ Processes a Set Form Height argument */ int VTFX80Print::FormHeightCmd(unsigned char byte) { - double newHeight; + double newHeight = m_formHeight; // Check if using inches mode. If inches, need to wait for next byte if (byte == 0) @@ -2511,100 +2574,143 @@ void VTFX80Print::BuildMonTab(void) o = new Fl_Box(20, 45+MENU_HEIGHT, 100, 20, "Print Pitch:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(20, 70+MENU_HEIGHT, 100, 20, "Print Weight:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(20, 95+MENU_HEIGHT, 100, 20, "Italic Mode:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(20, 120+MENU_HEIGHT, 100, 20, "Script Mode:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(20, 145+MENU_HEIGHT, 100, 20, "Underline:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(20, 170+MENU_HEIGHT, 100, 20, "Line Spacing:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(20, 195+MENU_HEIGHT, 100, 20, "Form Length:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(20, 220+MENU_HEIGHT, 100, 20, "Left Margin:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(20, 245+MENU_HEIGHT, 100, 20, "Head Position:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(20, 270+MENU_HEIGHT, 100, 20, "Perforation Skip:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(20, 295+MENU_HEIGHT, 100, 20, "Paper Type:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(20, 320+MENU_HEIGHT, 100, 20, "Paper Status:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); // 2nd Column of status items o = new Fl_Box(280, 45+MENU_HEIGHT, 100, 20, "ESC Mode:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(280, 70+MENU_HEIGHT, 100, 20, "ESC Params:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(280, 95+MENU_HEIGHT, 100, 20, "Graphics Mode:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(280, 120+MENU_HEIGHT, 100, 20, "Graphics Res:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(280, 145+MENU_HEIGHT, 100, 20, "Graphics Rcvd:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(280, 170+MENU_HEIGHT, 100, 20, "Update Char:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(280, 195+MENU_HEIGHT, 100, 20, "Last Char:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(280, 220+MENU_HEIGHT, 100, 20, "Update Bytes:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(280, 245+MENU_HEIGHT, 100, 20, "Font Source:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(280, 270+MENU_HEIGHT, 100, 20, "Intl Char Set:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); // Create controls for displaying the current status m_pStatPrintPitch = new Fl_Box(150, 45+MENU_HEIGHT, 100, 20, ""); m_pStatPrintPitch->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatPrintPitch->labelcolor(COLOR_FG); m_pStatPrintWeight = new Fl_Box(150, 70+MENU_HEIGHT, 100, 20, ""); m_pStatPrintWeight->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatPrintWeight->labelcolor(COLOR_FG); m_pStatItalic = new Fl_Box(150, 95+MENU_HEIGHT, 100, 20, ""); m_pStatItalic->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatItalic->labelcolor(COLOR_FG); m_pStatScriptMode = new Fl_Box(150, 120+MENU_HEIGHT, 100, 20, ""); m_pStatScriptMode->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatScriptMode->labelcolor(COLOR_FG); m_pStatUnderline = new Fl_Box(150, 145+MENU_HEIGHT, 100, 20, ""); m_pStatUnderline->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatUnderline->labelcolor(COLOR_FG); m_pStatLineSpacing = new Fl_Box(150, 170+MENU_HEIGHT, 100, 20, ""); m_pStatLineSpacing->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatLineSpacing->labelcolor(COLOR_FG); m_pStatFormLength = new Fl_Box(150, 195+MENU_HEIGHT, 100, 20, ""); m_pStatFormLength->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatFormLength->labelcolor(COLOR_FG); m_pStatLeftMargin = new Fl_Box(150, 220+MENU_HEIGHT, 100, 20, ""); m_pStatLeftMargin->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatLeftMargin->labelcolor(COLOR_FG); m_pStatPos = new Fl_Box(150, 245+MENU_HEIGHT, 100, 20, ""); m_pStatPos->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatPos->labelcolor(COLOR_FG); m_pStatPerfSkip = new Fl_Box(150, 270+MENU_HEIGHT, 100, 20, ""); m_pStatPerfSkip->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatPerfSkip->labelcolor(COLOR_FG); m_pStatPaperType = new Fl_Box(150, 295+MENU_HEIGHT, 250, 20, ""); m_pStatPaperType->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatPaperType->labelcolor(COLOR_FG); m_pStatPaperStatus = new Fl_Box(150, 320+MENU_HEIGHT, 250, 20, ""); m_pStatPaperStatus->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatPaperStatus->labelcolor(COLOR_FG); m_pStatEscMode = new Fl_Box(390, 45+MENU_HEIGHT, 100, 20, ""); m_pStatEscMode->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatEscMode->labelcolor(COLOR_FG); m_pStatEscParams = new Fl_Box(390, 70+MENU_HEIGHT, 130, 20, ""); m_pStatEscParams->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatEscParams->labelcolor(COLOR_FG); m_pStatGraphicsMode = new Fl_Box(390, 95+MENU_HEIGHT, 130, 20, ""); m_pStatGraphicsMode->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatGraphicsMode->labelcolor(COLOR_FG); m_pStatGraphicsRes = new Fl_Box(390, 120+MENU_HEIGHT, 130, 20, ""); m_pStatGraphicsRes->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatGraphicsRes->labelcolor(COLOR_FG); m_pStatGraphicsRcvd = new Fl_Box(390, 145+MENU_HEIGHT, 130, 20, ""); m_pStatGraphicsRcvd->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatGraphicsRcvd->labelcolor(COLOR_FG); m_pStatUpdateChar = new Fl_Box(390, 170+MENU_HEIGHT, 130, 20, ""); m_pStatUpdateChar->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatUpdateChar->labelcolor(COLOR_FG); m_pStatLastChar = new Fl_Box(390, 195+MENU_HEIGHT, 130, 20, ""); m_pStatLastChar->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatLastChar->labelcolor(COLOR_FG); m_pStatUpdateBytes = new Fl_Box(390, 220+MENU_HEIGHT, 130, 20, ""); m_pStatUpdateBytes->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatUpdateBytes->labelcolor(COLOR_FG); m_pStatFontSource = new Fl_Box(390, 245+MENU_HEIGHT, 130, 20, ""); m_pStatFontSource->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatFontSource->labelcolor(COLOR_FG); m_pStatIntlCharSet = new Fl_Box(390, 270+MENU_HEIGHT, 130, 20, ""); m_pStatIntlCharSet->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatIntlCharSet->labelcolor(COLOR_FG); UpdateMonTab(TRUE); - } /* @@ -2854,3 +2960,5 @@ void VTFX80Print::UpdateMonTab(int forceUpdate) } } +// vim: noet sw=4 ts=4 + diff --git a/src/fx80print.h b/src/fx80print.h index ad9aaa2..9df009f 100644 --- a/src/fx80print.h +++ b/src/fx80print.h @@ -268,10 +268,10 @@ class VTFX80Print : public VTPrinter int m_graphicsRcvd; // Number of bytes received int m_graphicsStartX; // Start X location - preserves precision double m_graphicsDpi; // DPI of graphics mode - char m_escKmode; // Graphics mode for ESC K - char m_escLmode; // Graphics mode for ESC L - char m_escYmode; // Graphics mode for ESC Y - char m_escZmode; // Graphics mode for ESC Z + unsigned char m_escKmode; // Graphics mode for ESC K + unsigned char m_escLmode; // Graphics mode for ESC L + unsigned char m_escYmode; // Graphics mode for ESC Y + unsigned char m_escZmode; // Graphics mode for ESC Z char m_graphicsReassign; // Graphics command being reassigned unsigned char m_charRom[256][12]; // Character ROM diff --git a/src/hostprint.cpp b/src/hostprint.cpp index aa2230b..82b3e96 100644 --- a/src/hostprint.cpp +++ b/src/hostprint.cpp @@ -51,6 +51,12 @@ #include "VirtualT.h" #include "hostprint.h" +extern int gMidnight; + +#define COLOR_BG (gMidnight ? FL_BLACK : fl_rgb_color(192, 192, 192)) +#define COLOR_BG_INPUT (gMidnight ? FL_BLACK : FL_WHITE) +#define COLOR_FG (gMidnight ? FL_WHITE : FL_BLACK) + /* ================================================================================ VTHostPrint: This is the class construcor for the HostPrint Device emulation. @@ -112,18 +118,24 @@ void VTHostPrint::BuildPropertyDialog(Fl_Window* pParent) { // Create controls for Host Port emulation mode Fl_Box* o = new Fl_Box(20, 20, 360, 20, "Host Port / Device Printer"); + o->labelcolor(COLOR_FG); // Host port name control o = new Fl_Box(20, 50, 300, 20, "Host Port Name"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); m_pHostPort = new Fl_Input(50, 75, 300, 20, ""); m_pHostPort->value(m_HostPort); + m_pHostPort->color(COLOR_BG); + m_pHostPort->textcolor(COLOR_FG); + m_pHostPort->cursor_color(COLOR_FG); m_pClosePort = new Fl_Check_Button(20, 115, 215, 20, "Close port between sessions"); m_pClosePort->value(m_ClosePort); + m_pClosePort->labelcolor(COLOR_FG); m_pReadBusy = new Fl_Check_Button(20, 140, 205, 20, "Read BUSY status from port"); m_pReadBusy->value(m_ReadBusy); + m_pReadBusy->labelcolor(COLOR_FG); } /* @@ -306,13 +318,17 @@ void VTHostPrint::BuildMonTab(void) o = new Fl_Box(20, 45+MENU_HEIGHT, 100, 20, "Host Port:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(20, 70+MENU_HEIGHT, 100, 20, "Port Status:"); o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); m_pStatHostPort = new Fl_Box(150, 45+MENU_HEIGHT, 300, 20, ""); m_pStatHostPort->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatHostPort->labelcolor(COLOR_FG); m_pStatPortStatus = new Fl_Box(150, 70+MENU_HEIGHT, 300, 20, ""); m_pStatPortStatus->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pStatPortStatus->labelcolor(COLOR_FG); UpdateMonTab(); } diff --git a/src/io.c b/src/io.c index 16ca0ef..a655ebe 100644 --- a/src/io.c +++ b/src/io.c @@ -275,7 +275,7 @@ void update_keys(void) } } - if (((gSpecialKeys & (MT_GRAPH | MT_CODE | MT_SHIFT)) == 0) && !gCapture) + if (((gSpecialKeys & (MT_PASTE | MT_CTRL | MT_SHIFT)) == 0) && !gCapture) { FILE* fd; int d, col, row; @@ -296,7 +296,9 @@ void update_keys(void) fprintf(fd, "%x 0 %02x\n", d, row<<6); for(col = 0; col < 50; col++) { - fprintf(fd, "%x 1 %02x\n", d, lcd[d][(row<<2) + col]); + if ((row == 4 || row == 9) && col == 40) + break; + fprintf(fd, "%x 1 %02x\n", d, lcd[d][(row<<6) + col]); } } } @@ -1261,22 +1263,24 @@ int inport(uchar port) if (gModel == MODEL_T200) return t200_readport(0xFE); else - { - if (fullspeed == 0) + { + if (fullspeed == 0) { +#if 0 /* Loop through all LCD driver modules */ for (c = 0; c < 10; c++) { /* Check if this driver is enabled */ if (lcdbits & (1 << c)) if (lcdTime[c]+.000003 > hirestimer()) - return (0x80); + return (0x80); } +#endif return 64; } - else - return(64); - } + else + return(64); + } case 0xFF: /* Loop through all LCD driver modules */ for (c = 0; c < 10; c++) diff --git a/src/lpt.cpp b/src/lpt.cpp index 8106f5a..a90ed6e 100644 --- a/src/lpt.cpp +++ b/src/lpt.cpp @@ -57,6 +57,13 @@ #include "fx80print.h" #include "fl_action_icon.h" +#define COLOR_BG (gMidnight ? FL_BLACK : fl_rgb_color(192, 192, 192)) +#define COLOR_BG_INPUT (gMidnight ? FL_BLACK : FL_WHITE) +#define COLOR_FG (gMidnight ? FL_WHITE : FL_BLACK) +#define COLOR_TAB_INACTIVE_BG (gMidnight ? fl_rgb_color(32,32,32) : fl_rgb_color(192,192,192)) +#define COLOR_TAB_INACTIVE_FG (gMidnight ? fl_rgb_color(192,192,192) : FL_BLACK) + +extern int gMidnight; extern Fl_Preferences virtualt_prefs; extern Fl_Action_Icon* gpPrint; typedef struct @@ -607,50 +614,63 @@ void build_lpt_setup_tab(void) gLptCtrl.pNone = new Fl_Round_Button(20, 40, 110, 20, "No emulation"); gLptCtrl.pNone->type(FL_RADIO_BUTTON); gLptCtrl.pNone->callback(cb_lpt_radio_none); + gLptCtrl.pNone->labelcolor(COLOR_FG); // Create Radio button for LPT emulation gLptCtrl.pEmul = new Fl_Round_Button(20, 65, 160, 20, "Connect LPT to:"); gLptCtrl.pEmul->type(FL_RADIO_BUTTON); gLptCtrl.pEmul->callback(cb_lpt_radio_emul); + gLptCtrl.pEmul->labelcolor(COLOR_FG); // Create control to choose the printer emulation mode gLptCtrl.pEmulPrint = new Fl_Choice(50, 90, 220, 20, ""); + gLptCtrl.pEmulPrint->color(COLOR_BG); + gLptCtrl.pEmulPrint->textcolor(COLOR_FG); + gLptCtrl.pEmulPrint->labelcolor(COLOR_FG); if (gLptPrefs.lpt_mode != LPT_MODE_EMUL) gLptCtrl.pEmulPrint->deactivate(); gLptCtrl.pCRtoLF = new Fl_Check_Button(20, 120, 200, 20, "Convert lonely CR to LF"); gLptCtrl.pCRtoLF->value(gLptPrefs.lpt_cr2lf); + gLptCtrl.pCRtoLF->labelcolor(COLOR_FG); if (gLptPrefs.lpt_mode != LPT_MODE_EMUL) gLptCtrl.pCRtoLF->deactivate(); gLptCtrl.pAutoFF = new Fl_Check_Button(20, 145, 240, 20, "Auto FormFeed after timeout (sec):"); gLptCtrl.pAutoFF->value(gLptPrefs.lpt_auto_ff); + gLptCtrl.pAutoFF->labelcolor(COLOR_FG); if (gLptPrefs.lpt_mode != LPT_MODE_EMUL) gLptCtrl.pAutoFF->deactivate(); gLptCtrl.pAFFtimeout = new Fl_Input(280, 145, 40, 20, ""); sprintf(value, "%d", gLptPrefs.lpt_aff_timeout); gLptCtrl.pAFFtimeout->value(value); + gLptCtrl.pAFFtimeout->color(COLOR_BG); + gLptCtrl.pAFFtimeout->textcolor(COLOR_FG); + gLptCtrl.pAFFtimeout->cursor_color(COLOR_FG); if (gLptPrefs.lpt_mode != LPT_MODE_EMUL) gLptCtrl.pAFFtimeout->deactivate(); gLptCtrl.pAutoClose = new Fl_Check_Button(20, 170, 240, 20, "Close Session after timeout (sec):"); gLptCtrl.pAutoClose->value(gLptPrefs.lpt_auto_close); + gLptCtrl.pAutoClose->labelcolor(COLOR_FG); if (gLptPrefs.lpt_mode != LPT_MODE_EMUL) gLptCtrl.pAutoClose->deactivate(); gLptCtrl.pCloseTimeout = new Fl_Input(280, 170, 40, 20, ""); sprintf(value, "%d", gLptPrefs.lpt_close_timeout); gLptCtrl.pCloseTimeout->value(value); + gLptCtrl.pCloseTimeout->color(COLOR_BG); + gLptCtrl.pCloseTimeout->textcolor(COLOR_FG); + gLptCtrl.pCloseTimeout->cursor_color(COLOR_FG); if (gLptPrefs.lpt_mode != LPT_MODE_EMUL) gLptCtrl.pCloseTimeout->deactivate(); - // Add help text for setting up printer preferences Fl_Button* b = new Fl_Button(20, 210, 120, 30, "Printer Setup"); b->callback(cb_printer_properties); - //Fl_Box* o = new Fl_Box(20, 220, 300, 20, "Setup Printer Preferences from File menu"); - //o->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + b->color(COLOR_BG); + b->labelcolor(COLOR_FG); // Add items to the EmulPrint choice box count = gLpt->GetPrinterCount(); @@ -1108,6 +1128,7 @@ void VTLpt::PrinterProperties(int useActivePrinter) // Create a dialog box first m_pProp = new Fl_Window(400, 350, "Printer Properties"); + m_pProp->color(COLOR_BG); // Create property page from selected printer count = GetPrinterCount(); @@ -1142,9 +1163,13 @@ void VTLpt::PrinterProperties(int useActivePrinter) // Create Ok and Cancel button m_pCancel = new Fl_Button(m_pProp->w() - 165, m_pProp->h()-40, 60, 30, "Cancel"); m_pCancel->callback(cb_PrintProp_Cancel); + m_pCancel->color(COLOR_BG); + m_pCancel->labelcolor(COLOR_FG); m_pOk = new Fl_Return_Button(m_pProp->w()-90, m_pProp->h()-40, 60, 30, "Ok"); m_pOk->callback(cb_PrintProp_Ok, pPrint); + m_pOk->color(COLOR_BG); + m_pOk->labelcolor(COLOR_FG); // Show the dialog box m_pProp->end(); diff --git a/src/memedit.cpp b/src/memedit.cpp index 575004f..b2ad89b 100644 --- a/src/memedit.cpp +++ b/src/memedit.cpp @@ -57,6 +57,8 @@ extern int gRamBottom; extern uchar gQuad; } +extern int gMidnight; + void cb_Ide(Fl_Widget* w, void*); void cb_menu_run(Fl_Widget* w, void*); void cb_menu_stop(Fl_Widget* w, void*); @@ -619,6 +621,8 @@ void cb_load(Fl_Widget* w, void*) // Create edit field for filename o = new Fl_Box(FL_NO_BOX, 10, 10, 50, 15, "Filename"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + if (gMidnight) + o->labelcolor(FL_WHITE); gDialog.pFilename = new Fl_Input(10, 30, 300, 20, ""); gDialog.pFilename->callback(load_filename_cb); @@ -626,10 +630,11 @@ void cb_load(Fl_Widget* w, void*) gDialog.pBrowse = new Fl_Button(320, 30, 70, 20, "Browse"); gDialog.pBrowse->callback(load_browseButton_cb); - // Create report field for # bytes being loaded o = new Fl_Box(FL_NO_BOX, 25, 55, 100, 15, "Filesize (bytes):"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + if (gMidnight) + o->labelcolor(FL_WHITE); gDialog.sBytes[0] = 0; gDialog.pBytes = new Fl_Box(FL_NO_BOX, 135, 55, 150, 15, gDialog.sBytes); gDialog.pBytes->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); @@ -637,11 +642,15 @@ void cb_load(Fl_Widget* w, void*) // Create Edit fields for memory range o = new Fl_Box(FL_NO_BOX, 10, 90, 110, 15, "Start Address"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + if (gMidnight) + o->labelcolor(FL_WHITE); gDialog.pStartAddr = new Fl_Input(120, 90, 90, 20, ""); gDialog.pStartAddr->value(memedit_ctrl.pMemRange->value()); o = new Fl_Box(FL_NO_BOX, 10, 120, 110, 15, "End Address"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + if (gMidnight) + o->labelcolor(FL_WHITE); gDialog.pEndAddr = new Fl_Box(FL_NO_BOX, 120, 120, 90, 15, ""); gDialog.pEndAddr->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); @@ -656,6 +665,33 @@ void cb_load(Fl_Widget* w, void*) b = new Fl_Button(210, 160, 75, 25, "Cancel"); b->callback(load_cancelButton_cb); + if (gMidnight) + { + gDialog.pWin->color(FL_BLACK); + + gDialog.pBrowse->color(FL_BLACK); + gDialog.pBrowse->labelcolor(FL_WHITE); + + gDialog.pFilename->color(FL_BLACK); + gDialog.pFilename->textcolor(FL_WHITE); + gDialog.pFilename->cursor_color(FL_WHITE); + + gDialog.pBytes->color(FL_BLACK); + gDialog.pBytes->labelcolor(FL_WHITE); + + gDialog.pStartAddr->color(FL_BLACK); + gDialog.pStartAddr->textcolor(FL_WHITE); + gDialog.pStartAddr->cursor_color(FL_WHITE); + + gDialog.pEndAddr->color(FL_BLACK); + gDialog.pEndAddr->labelcolor(FL_WHITE); + + rb->color(FL_BLACK); + rb->labelcolor(FL_WHITE); + b->color(FL_BLACK); + b->labelcolor(FL_WHITE); + } + gDialog.pWin->set_modal(); // Show the dialog box @@ -768,6 +804,8 @@ void cb_save_memory(Fl_Widget* w, void*) // Create edit field for filename o = new Fl_Box(FL_NO_BOX, 10, 40, 50, 15, "Filename"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + if (gMidnight) + o->labelcolor(FL_WHITE); gDialog.pFilename = new Fl_Input(10, 60, 300, 20, ""); gDialog.pFilename->callback(load_filename_cb); @@ -778,16 +816,22 @@ void cb_save_memory(Fl_Widget* w, void*) // Create Edit fields for memory range o = new Fl_Box(FL_NO_BOX, 10, 90, 110, 15, "Start Address"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + if (gMidnight) + o->labelcolor(FL_WHITE); gDialog.pStartAddr = new Fl_Input(120, 90, 90, 20, ""); gDialog.pStartAddr->value(memedit_ctrl.pMemRange->value()); o = new Fl_Box(FL_NO_BOX, 10, 120, 110, 15, "End Address"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + if (gMidnight) + o->labelcolor(FL_WHITE); gDialog.pEndSaveAddr = new Fl_Input(120, 120, 90, 20, ""); // Create edit field for length o = new Fl_Box(FL_NO_BOX, 10, 150, 110, 15, "Length"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + if (gMidnight) + o->labelcolor(FL_WHITE); gDialog.pSaveLen = new Fl_Input(120, 150, 90, 20, ""); // We aren't using pBytes for save @@ -800,6 +844,38 @@ void cb_save_memory(Fl_Widget* w, void*) b = new Fl_Button(210, 190, 75, 25, "Cancel"); b->callback(load_cancelButton_cb); + if (gMidnight) + { + gDialog.pWin->color(FL_BLACK); + + gDialog.pHex->labelcolor(FL_WHITE); + gDialog.pBin->labelcolor(FL_WHITE); + + gDialog.pBrowse->color(FL_BLACK); + gDialog.pBrowse->labelcolor(FL_WHITE); + + gDialog.pFilename->color(FL_BLACK); + gDialog.pFilename->textcolor(FL_WHITE); + gDialog.pFilename->cursor_color(FL_WHITE); + + gDialog.pStartAddr->color(FL_BLACK); + gDialog.pStartAddr->textcolor(FL_WHITE); + gDialog.pStartAddr->cursor_color(FL_WHITE); + + gDialog.pEndSaveAddr->color(FL_BLACK); + gDialog.pEndSaveAddr->labelcolor(FL_WHITE); + gDialog.pEndSaveAddr->cursor_color(FL_WHITE); + + gDialog.pSaveLen->color(FL_BLACK); + gDialog.pSaveLen->labelcolor(FL_WHITE); + gDialog.pSaveLen->cursor_color(FL_WHITE); + + rb->color(FL_BLACK); + rb->labelcolor(FL_WHITE); + b->color(FL_BLACK); + b->labelcolor(FL_WHITE); + } + gDialog.pWin->set_modal(); // Show the dialog box @@ -938,7 +1014,6 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) // Create a menu for the new window. memedit_ctrl.pMenu = new Fl_Menu_Bar(0, 0, w, MENU_HEIGHT-2); - gmew->callback(cb_memeditwin); memedit_ctrl.pMenu->menu(gMemEdit_menuitems); @@ -954,8 +1029,12 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) // Create static text boxes o = new Fl_Box(FL_NO_BOX, 10, 10, 50, 15, "Region"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + if (gMidnight) + o->labelcolor(FL_WHITE); o = new Fl_Box(FL_NO_BOX, 175, 10, 50, 15, "Address"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + if (gMidnight) + o->labelcolor(FL_WHITE); // Create Region choice box memedit_ctrl.pRegion = new Fl_Choice(70, 8, 100, 20, ""); @@ -966,6 +1045,20 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) memedit_ctrl.pMemRange->callback(cb_memory_range); memedit_ctrl.pMemRange->when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED); + if (gMidnight) + { + gmew->color(FL_BLACK); + memedit_ctrl.pMenu->color(FL_BLACK); + memedit_ctrl.pMenu->textcolor(FL_WHITE); + memedit_ctrl.pTile->color(FL_BLACK); + memedit_ctrl.pTopPane->color(FL_BLACK); + memedit_ctrl.pRegion->color(FL_BLACK); + memedit_ctrl.pRegion->textcolor(FL_WHITE); + memedit_ctrl.pMemRange->color(FL_BLACK); + memedit_ctrl.pMemRange->textcolor(FL_WHITE); + memedit_ctrl.pMemRange->cursor_color(FL_WHITE); + } + // Create a resize box for the group and end the group. This resizing box within // the group causes the region and address edit fields to maintain size / position // while allowing the editor region to resize with the group. @@ -975,6 +1068,12 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) g->end(); // Create the memory editor widget and scrollbar + if (gMidnight) + { + o = new Fl_Box(7, 37, w-20-2, 350-MENU_HEIGHT+15); + o->box(FL_THIN_DOWN_BOX); + o->color(FL_WHITE); + } memedit_ctrl.pMemEdit = new T100_MemEditor(10, 40, w-20-15/*545*/, 350-MENU_HEIGHT+10); memedit_ctrl.pScroll = new Fl_Scrollbar(w-10-15/*555*/, 40, 15, 350-MENU_HEIGHT+10, ""); @@ -994,6 +1093,15 @@ void cb_MemoryEditor (Fl_Widget* pW, void*) // Create a group to hold the framing box and the actual watch table widget g = new Fl_Group(0, 0, w, wh, ""); + + if (gMidnight) + { + memedit_ctrl.pBottomPane->color(FL_BLACK); + o = new Fl_Box(7, 0, w-20-2, 350-MENU_HEIGHT+15); + o->box(FL_THIN_DOWN_BOX); + o->color(FL_WHITE); + } + Fl_Box* b = new Fl_Box(FL_DOWN_FRAME, 9, 2, w-17/*22*/, wh-5, ""); // Create the Watch Table widget @@ -1255,7 +1363,7 @@ void T100_MemEditor::SetRegionOptions(void) // Update the Regions control with appropriate options if (gReMem) { - if (gRex) + if ((gRex && (gRex != REXC))) { if (gModel == MODEL_T200 || gModel == MODEL_PC8201 || gModel == MODEL_PC8300) { @@ -1289,6 +1397,15 @@ void T100_MemEditor::SetRegionOptions(void) memedit_ctrl.pRegion->add("128K SRAM"); memedit_ctrl.pRegion->value(0); } + + else if (gRex && (gRex == REXC)) // added SA + { + memedit_ctrl.pRegion->add("RAM"); + memedit_ctrl.pRegion->add("ROM"); + memedit_ctrl.pRegion->add("Opt ROM"); + memedit_ctrl.pRegion->add("4MB SRAM"); + memedit_ctrl.pRegion->value(0); + } else { memedit_ctrl.pRegion->add("RAM"); @@ -1395,7 +1512,7 @@ void T100_MemEditor::SetScrollSize(void) m_Max = 1024 * 1024 / 16; break; case 6: - m_Max = 128 * 1024 / 16; + m_Max = 128 * 1024 / 16; break; default: m_Max = ROMSIZE / 16; @@ -1411,7 +1528,7 @@ void T100_MemEditor::SetScrollSize(void) else if (region == 4) m_Max = ROMSIZE / 16; else - m_Max = 1024 * 1024 / 16; + m_Max = 1024 * 1024 / 16; } else { @@ -1420,9 +1537,20 @@ void T100_MemEditor::SetScrollSize(void) else if (region == 1) m_Max = ROMSIZE / 16; else if (region == 2) - m_Max = 1024 * 1024 / 16; + { + if (gRex == REXC) + m_Max = ROMSIZE / 16; // added SA + else + m_Max = 1024 * 1024 / 16; + } else if (region == 3) - m_Max = 128 * 1024 / 16; + { + if (gRex == REXC) + m_Max = 4 * 1024 * 1024 / 16; // added SA + else + m_Max = 128 * 1024 / 16; + } + } } } @@ -1564,6 +1692,10 @@ int T100_MemEditor::GetRegionEnum(void) if (strcmp(reg_text, "128K SRAM") == 0) m_Region = REGION_REX2_RAM; + // Test if REXCPM RAM region is selected + if (strcmp(reg_text, "4MB SRAM") == 0) + m_Region = REGION_REXC_RAM; + return m_Region; } @@ -1921,10 +2053,9 @@ Handle mouse events, key events, focus events, etc. */ int T100_MemEditor::handle(int event) { - int c, xp, yp, shift; - int line_click, col_click, cnt; - int col, line; - int lineIndex; + int c, xp = 0, yp = 0, shift = 0; + int line_click = 0, col_click = 0; + int col; int height, size; int value; unsigned int key; @@ -1936,7 +2067,6 @@ int T100_MemEditor::handle(int event) if (event == 0) return 0; - //printf("Event %d\n", event); // Do some common processing before the switch if (event == FL_PUSH || event == FL_MOVE || event == FL_DRAG) { @@ -2087,13 +2217,7 @@ int T100_MemEditor::handle(int event) m_HaveMouse = TRUE; m_DragX = xp; m_DragY = yp; - - // Get LineStart index - lineIndex = (m_FirstLine + line_click) >> 1; - - cnt = 0; col = 0; - line = lineIndex << 1; // Select 12 point Courier font fl_font(m_Font, m_FontSize); @@ -3383,7 +3507,7 @@ Update the Address edit box base on the position of the cursor */ void T100_MemEditor::UpdateAddressText() { - char string[10]; + char string[20]; long address; int col, region; @@ -3416,14 +3540,14 @@ void T100_MemEditor::UpdateAddressText() (region == REGION_RAM3) || region == REGION_RAM1 || (region == REGION_RAM4)) { if (gReMem) - sprintf(string, "0x%06X", (unsigned int) (address + RAMSTART)); + sprintf(string, "0x%06X", (unsigned int) ((address + RAMSTART) & 0xFFFFFF)); else sprintf(string, "0x%04X", (unsigned int) (address + RAMSTART)); } else { if (gReMem) - sprintf(string, "0x%06X", (unsigned int) address); + sprintf(string, "0x%06X", (unsigned int) (address & 0xFFFFFF)); else sprintf(string, "0x%04X", (unsigned int) address); } @@ -4085,40 +4209,71 @@ void cb_setup_memedit(Fl_Widget* w, void* pOpaque) /* Create a button for the marker foreground color */ p.pMarkerForeground = new Fl_Button(22, 110, 15, 15, "Marker Forground Color"); - p.pMarkerForeground->callback((Fl_Callback*) cb_marker_foreground, &p); + p.pMarkerForeground->callback((Fl_Callback*) cb_marker_foreground, &p); p.pMarkerForeground->align(FL_ALIGN_RIGHT); p.pMarkerForeground->color(memedit_ctrl.pMemEdit->GetMarkerForegroundColor()); /* Create a button for the marker background color */ p.pMarkerBackground = new Fl_Button(22, 130, 15, 15, "Marker Background Color"); - p.pMarkerBackground->callback((Fl_Callback*) cb_marker_background, &p); + p.pMarkerBackground->callback((Fl_Callback*) cb_marker_background, &p); p.pMarkerBackground->align(FL_ALIGN_RIGHT); p.pMarkerBackground->color(memedit_ctrl.pMemEdit->GetMarkerBackgroundColor()); /* Create a button for the marker foreground color */ p.pSelectedForeground = new Fl_Button(22, 150, 15, 15, "Selected Marker Forground"); - p.pSelectedForeground->callback((Fl_Callback*) cb_selected_foreground, &p); + p.pSelectedForeground->callback((Fl_Callback*) cb_selected_foreground, &p); p.pSelectedForeground->align(FL_ALIGN_RIGHT); p.pSelectedForeground->color(memedit_ctrl.pMemEdit->GetSelectedForegroundColor()); /* Create a button for the marker background color */ p.pSelectedBackground = new Fl_Button(22, 170, 15, 15, "Selected Marker Background"); - p.pSelectedBackground->callback((Fl_Callback*) cb_selected_background, &p); + p.pSelectedBackground->callback((Fl_Callback*) cb_selected_background, &p); p.pSelectedBackground->align(FL_ALIGN_RIGHT); p.pSelectedBackground->color(memedit_ctrl.pMemEdit->GetSelectedBackgroundColor()); p.pDefaults = new Fl_Button(240, 135, 70, 30, "Defaults"); p.pDefaults->callback((Fl_Callback *) cb_default_colors, &p); + if (gMidnight) + { + pWin->color(FL_BLACK); + b->labelcolor(FL_WHITE); + p.pFontSize->color(FL_BLACK); + p.pFontSize->textcolor(FL_WHITE); + p.pFontSize->cursor_color(FL_WHITE); + p.pBold->color(FL_BLACK); + p.pBold->labelcolor(FL_WHITE); + p.pBlackBackground->color(FL_BLACK); + p.pBlackBackground->labelcolor(FL_WHITE); + p.pColorHilight->color(FL_BLACK); + p.pColorHilight->labelcolor(FL_WHITE); + p.pMarkerForeground->labelcolor(FL_WHITE); + p.pMarkerBackground->labelcolor(FL_WHITE); + p.pSelectedForeground->labelcolor(FL_WHITE); + p.pSelectedBackground->labelcolor(FL_WHITE); + p.pDefaults->color(FL_BLACK); + p.pDefaults->labelcolor(FL_WHITE); + } + // Cancel button - { Fl_Button* o = new Fl_Button(80, 200, 60, 30, "Cancel"); - o->callback((Fl_Callback*) cb_setupdlg_cancel, &p); - } + { Fl_Button* o = new Fl_Button(80, 200, 60, 30, "Cancel"); + o->callback((Fl_Callback*) cb_setupdlg_cancel, &p); + if (gMidnight) + { + o->color(FL_BLACK); + o->labelcolor(FL_WHITE); + } + } // OK button - { Fl_Return_Button* o = new Fl_Return_Button(160, 200, 60, 30, "OK"); - o->callback((Fl_Callback*) cb_setupdlg_OK, &p); - } + { Fl_Return_Button* o = new Fl_Return_Button(160, 200, 60, 30, "OK"); + o->callback((Fl_Callback*) cb_setupdlg_OK, &p); + if (gMidnight) + { + o->color(FL_BLACK); + o->labelcolor(FL_WHITE); + } + } // Loop until user presses OK or Cancel pWin->show(); @@ -4692,3 +4847,5 @@ void cb_show_hide_watch(Fl_Widget* w, void*) gMemEdit_menuitems[3].text = "Show Watch Window"; } } + +// vim: noet sw=4 ts=4 diff --git a/src/memory.c b/src/memory.c index 9b1f5fd..2923150 100644 --- a/src/memory.c +++ b/src/memory.c @@ -70,17 +70,36 @@ int gRampacEmulation = 0;/* ReMem's Rampac emulation active? */ int gRex = 0; /* Rex Emulation Enable flag */ unsigned char *gRex2Ram = NULL; /* Rex2 RAM pointer */ int gRexSector = 0; /* Active sector */ + int gRexState = 7; /* Rex Command State */ +int gRexCState = 15; /* REXCPM Command State */ // added SA unsigned char gRexReturn = 0; /* Return value for Status & HW reads */ unsigned char gRexModel = 0; /* Rex model */ unsigned char gRexFlashSel = 1; /* Rex Flash enable signal */ int gRexKeyState = 0; /* Rex Key State */ +int gRexCKeyState = 15; /* REXCPM Key State */ int gRexFlashPA = 0; /* REX Flash Address Line during programing */ unsigned char gRex3Data = 0; /* REX3 data to write for commands 2,5 and 6 */ unsigned char gRex3Cmd = 0; /* REX3 command saved for state 6 */ amd_flash_t gRexFlash = { FLASH_STATE_RO, 0, FALSE, 0 }; unsigned char gRexKeyTable[6] = { 184, 242, 52, 176, 49, 191 }; +unsigned char gRexCKeyTable[6] = { 184, 242, 196, 237, 161, 152 }; // added SA +int gRexCKey; +int gRexCKeyAddr; +unsigned char gRexCOSector = 1; /* OPTROM 32k sector */ // added SA +unsigned char gRexCRLSector = 0; /* lower 16k RAM sector */ // added SA +unsigned char gRexCRUSector = 1; /* upper 16k RAM sector */ // added SA +int gRexCWP = 1; /* write protect */ // added SA +unsigned char *gRexCRam = NULL; /* Pointer to REXC RAM space */ // added SA +int readcounter = 1; // read counter for REXC state machine, added SA +int lastreadcounter = 0; // read counter for REXC state machine, added SA +int readcounterclear = 1; // clear signal for REXC read counter, added SA +int optromcounter = 0; // REX Optrom read counter, added SA + +int gRexCModel = 0xE8; // model # info for REXC, added SA int gIndex[65536]; +int temp; + extern RomDescription_t gM100_Desc; extern RomDescription_t gM200_Desc; @@ -101,13 +120,43 @@ uchar gFlashCFIData[] = { 0x50, 0x52, 0x49, 0x31, 0x30, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 }; + +unsigned char get_memory8_counter(unsigned short address) +{ // added so that actual memory reads during emulation can be counted, for REXCPM state machine + if (readcounterclear == 1) + { + readcounter = 1; + lastreadcounter = 0; + optromcounter = 0; + } + else + readcounter = ((readcounter + 1) & 0xFF); + + return get_memory8(address); +} + + + unsigned char get_memory8(unsigned short address) { if (gReMem) { - if (gRex) - return rex_read(address); - else + if (gRex && (gRex == REXC)) // modified SA + { + unsigned char ret; + ret = rexC_read(address); + lastreadcounter = readcounter; + return ret; + } + else if (gRex && (gRex != REXC)) + // REX, REX3, REXS, REX2, REX3 + { + unsigned char ret; + ret = rex_read(address); + lastreadcounter = readcounter; + return ret; + } + else // REMEM { if (gReMemFlashReady) return gMemory[address >> 10][address & 0x3FF]; @@ -123,9 +172,15 @@ unsigned short get_memory16(unsigned short address) { if (gReMem) { - if (gRex) + if (gRex && (gRex == REXC)) // modified SA + // REXC + return rexC_read(address) | (rexC_read(address+1) << 8); + else if (gRex && (gRex != REXC)) + // REX, REX3, REXS, REX2, REX3 return rex_read(address) | (rex_read(address+1) << 8); - return gMemory[address>>10][address&0x3FF] + (gMemory[(address+1)>>10][(address+1)&0x3FF] << 8); + else + // REMEM + return gMemory[address>>10][address&0x3FF] + (gMemory[(address+1)>>10][(address+1)&0x3FF] << 8); } else return (address>ROMSIZE&&address> 8)); } @@ -171,8 +230,15 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) { if (gReMem && !gRex) data[c] = gMemory[addr>>10][addr&0x3FF]; + else if (gRex == REXC) + { + if ( (addr&0xC000) == 0xC000 ) + data[c]= gRexCRam[ gRexCRUSector<<14 | (addr&0x3FFF)]; //upper ram + else + data[c]= gRexCRam[ gRexCRLSector<<14 | (addr&0x3FFF)]; // lower ram + } else - data[c] = gBaseMemory[addr]; + data[c] = gBaseMemory[addr]; addr++; } break; @@ -208,7 +274,13 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) case REGION_OPTROM: addr = address; for (c = 0; c < count; c++) - data[c] = gOptROM[addr++]; + { + if (gRex && (gRex == REXC)) + data[c] = gRexCRam[(gRexCOSector <<15) | (0x07FFF & addr)]; + else + data[c] = gOptROM[addr]; + addr++; + } break; case REGION_RAM1: @@ -373,6 +445,25 @@ void get_memory8_ext(int region, long address, int count, unsigned char *data) data[cp_ptr] = ptr[addr++]; break; + + // added SA + case REGION_REXC_RAM: + // First check that the REXC RAM has been allocated + if (gRexCRam== NULL) + break; + + // Indicate zero bytes copied so far + cp_ptr = 0; + + // Determine which location to copy memory from + ptr = (uchar *) gRexCRam; + + // Block is not mapped -- copy from 4Meg Region (RAM) + addr = address; + for (;(cp_ptr < count); cp_ptr++) + data[cp_ptr] = ptr[addr++]; + break; + case REGION_ROM3: addr = address; if (gModel == MODEL_PC8300) @@ -405,7 +496,6 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) { int addr; int c; - unsigned short map; int cp_ptr; unsigned char *ptr; int map_changed = 0; @@ -418,12 +508,19 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) { if (gReMem && !gRex) gMemory[addr>>10][addr&0x3FF] = data[c]; + else if (gRex == REXC) + { + if ((addr&0xC000) == 0xC000 ) + gRexCRam[ gRexCRUSector<<14 | (addr&0x3FFF)] = data[c]; // upper ram + else + gRexCRam[ gRexCRLSector<<14 | (addr&0x3FFF)] = data[c]; // lower ram + } else gBaseMemory[addr] = data[c]; addr++; } break; - + case REGION_ROM: addr = address; for (c = 0; c < count; c++) @@ -445,7 +542,13 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) case REGION_OPTROM: addr = address; for (c = 0; c < count; c++) - gOptROM[addr++] = data[c]; + { + if (gRex == REXC) + gRexCRam[(gRexCOSector<<15) | (0x7FFF & addr)] = data[c]; + else + gOptROM[addr] = data[c]; + addr++; + } break; case REGION_RAM1: @@ -582,7 +685,6 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) addr = address; // Calculate ReMemMap value to search for to test if - map = REMEM_VCTR_FLASH1_CS | REMEM_VCTR_FLASH2_CS; ptr = gReMemRam; /* Loop for each byte and copy to RAM. If byte is in MMU space */ @@ -644,6 +746,30 @@ void set_memory8_ext(int region, long address, int count, unsigned char *data) ptr[addr++] = data[cp_ptr]; break; + + + + /* + ================================================================ + The following deals with REXC RAM + ================================================================ + */ + case REGION_REXC_RAM: + // First check that the ReMem RAM has been allocated + if (gRexCRam == NULL) + break; + + /* Get pointer to the REXCPM RAM */ + ptr = (uchar *) gRexCRam; + + /* Setup to copy */ + addr = address; + + // Copy bytes up to the limit to allocation + for (cp_ptr = 0; cp_ptr < count; cp_ptr++) + ptr[addr++] = data[cp_ptr]; + + break; } } @@ -779,10 +905,12 @@ void init_mem(void) gReMem = (mem_setup.mem_mode == SETUP_MEM_REMEM) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC); gRampac = (mem_setup.mem_mode == SETUP_MEM_RAMPAC) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC); gRex = (mem_setup.mem_mode == SETUP_MEM_REX || mem_setup.mem_mode == SETUP_MEM_REX_QUAD) ? REX : - (mem_setup.mem_mode == SETUP_MEM_REX2) ? REX2 : 0; + (mem_setup.mem_mode == SETUP_MEM_REX2) ? REX2 : + (mem_setup.mem_mode == SETUP_MEM_REXS) ? REXS : + (mem_setup.mem_mode == SETUP_MEM_REXC) ? REXC : 0; gQuad = (mem_setup.mem_mode == SETUP_MEM_QUAD || mem_setup.mem_mode == SETUP_MEM_REX_QUAD) ? 1 : 0; - if (gRex) + if (gRex && (gRex != REXC)) { gRexModel = REX | gRex; gReMem = 1; @@ -791,6 +919,19 @@ void init_mem(void) gRexSector = 0; gRexKeyState = 0; } + + if (gRex == REXC) + { + gRexModel = REXC | gRex; // added SA + gReMem = 1; + gRexCState = 15; + gRexCKeyState = 0; + gRexCOSector = 1; + gRexCRLSector = 0; + gRexCRUSector = 1; + gRexCWP = 1; + } + gRampacEmulation = 0; gRampacSectPtr = NULL; gRamBank = 0; @@ -812,8 +953,52 @@ void init_mem(void) rambanks[c] = 0; } + + /* Test if Rex emulation enabled */ + if (gRex) + { + /* Allocate memory only if not already allocated */ //only when not REXCPM // added SA + if ((gRex != REXC) && (gRexFlash.pFlash == 0) ) + { + /* Size of allocation for RAM and FLASH */ + size = 1024 * 1024; + + /* Allocate space for Rex FLASH */ + amd_flash_init(&gRexFlash, size, AMD_FLASH_TYPE_REX); + } + // test if REXCPM is enabled + if ((gRex == REXC) && (gRexCRam == 0)) // added SA, allocate if not already allocated + { + /* Size of allocation for REXCPM RAM */ + size = 4 * 1024 * 1024; + + /* Allocate space for RexCPM RAM */ + gRexCRam = malloc(size); + + /* Initialize memory to zero */ + for (c = 0; c < size; c++) + gRexCRam[c] = 0; + } + + + /* Test if Rex2 enabled and allocate RAM */ + if ((gRex == REX2) && (gRex2Ram == 0)) + { + /* Size of allocation for RAM and FLASH */ + size = 1024 * 128; + + /* Allocate space for Rex2 RAM */ + gRex2Ram = malloc(size); + + /* Initialize memory to zero */ + for (c = 0; c < size; c++) + gRex2Ram[c] = 0; + } + } + + /* Test if ReMem emulation enabled */ - if (gReMem) + if (gReMem && !gRex) // do this if ReMem { /* Allocate memory only if not already allocated */ if (gReMemRam == 0) @@ -833,7 +1018,7 @@ void init_mem(void) amd_flash_init(&gReMemFlash1, size, AMD_FLASH_TYPE_REMEM); amd_flash_init(&gReMemFlash2, size, AMD_FLASH_TYPE_REMEM); } - + remem_copy_normal_to_system(); /* Initialize Rampac I/O mode access variables */ @@ -843,7 +1028,8 @@ void init_mem(void) gReMemCounter = 0; gReMemSectPtr = (unsigned char *) (gReMemRam + REMEM_MAP_OFFSET); } - else + + else // REX and non REX, not ReMem { /* Reset Rom Size back to original */ if (gModel == MODEL_T200) @@ -854,36 +1040,14 @@ void init_mem(void) /* Copy Memory */ for (c = 0; c < ROMSIZE/1024; c++) gMemory[c] = &gSysROM[c*1024]; - - for (; c < 64; c++) - gMemory[c] = &gBaseMemory[next++ * 1024]; - } - - /* Test if Rex emulation enabled */ - if (gRex) - { - /* Allocate memory only if not already allocated */ - if (gRexFlash.pFlash == 0) - { - /* Size of allocation for RAM and FLASH */ - size = 1024 * 1024; - - /* Allocate space for Rex FLASH */ - amd_flash_init(&gRexFlash, size, AMD_FLASH_TYPE_REX); + + if (gRex == REXC) // added SA - + { } - - /* Test if Rex2 enabled and allocate RAM */ - if ((gRex == REX2) && (gRex2Ram == 0)) + else // normal RAM assignment { - /* Size of allocation for RAM and FLASH */ - size = 1024 * 128; - - /* Allocate space for Rex2 RAM */ - gRex2Ram = malloc(size); - - /* Initialize memory to zero */ - for (c = 0; c < size; c++) - gRex2Ram[c] = 0; + for (; c < 64; c++) + gMemory[c] = &gBaseMemory[next++ * 1024]; } } @@ -917,7 +1081,8 @@ void reinit_mem(void) gRomSize = gModel == MODEL_T200 ? 40960 : 32768; /* Check if ReMem emulation on */ - if (gReMem) +// if (gReMem) SA + if (gReMem && !gRex) { gReMemMode = REMEM_MODE_FLASH1_RDY | REMEM_MODE_FLASH2_RDY; gReMemFlashReady = TRUE; @@ -933,7 +1098,7 @@ void reinit_mem(void) } /* Test if Rex needs to be reinitialized */ - if (gRex) + if ((gRex) && (gRex != REXC)) { /* Initialize Rex state varialbles */ gRexState = 7; @@ -942,6 +1107,18 @@ void reinit_mem(void) gRexKeyState = 0; } + /* Test if RexCPM needs to be reinitialized */ + if ((gRex) && (gRex == REXC)) + { + /* Initialize RexCPM state varialbles */ + gRexCState = 15; + gRexCOSector = 1; + gRexCRLSector = 0; + gRexCRUSector = 1; + gRexCWP = 1; + gRexCKeyState = 0; + } + // Clear the RAM // for (x = ROMSIZE; x < 65536; x++) // set_memory8(x, 0); @@ -964,9 +1141,17 @@ void cold_boot_mem(void) load_sys_rom(); // Now zero out the RAM - if (gReMem && (gRex == 0)) + if (gReMem && !gRex) { } + else if (gRex == REXC) + { + for (x = 0; x < 0x04000; x++) // init first 2 16k blocks of REXCPM RAM as pointed to by registers + { + gRexCRam[gRexCRUSector<<14 | x] = 0; + gRexCRam[gRexCRLSector<<14 | x] = 0; + } + } else { for (x = ROMSIZE; x < 65536; x++) @@ -1025,6 +1210,24 @@ void free_rex_mem(void) /* Set memory pointers to NULL */ gRexFlash.pFlash = 0; + +} + +/* +======================================================================== +free_rexc_mem: This routine frees the memory used by the RexCPM + emulation and resets the pointers to zero. +======================================================================== +*/ +void free_rexc_mem(void) +{ + /* Delete memory allocated for RAM*/ + if (gRexCRam != NULL) + free(gRexCRam); + + /* Set memory pointers to NULL */ + gRexCRam = 0; + } /* @@ -1043,8 +1246,11 @@ void free_mem(void) if (gRampacRam != 0) free_rampac_mem(); - if (gRex != 0) + if (gRex && (gRex != REXC)) free_rex_mem(); + + if (gRex == REXC) + free_rexc_mem(); } /* @@ -1162,6 +1368,44 @@ void save_rex2_ram(void) } } +/* +======================================================================== +save_rexc_ram: This routine saves the Rexc emulation RAM to the RexC + RAM file. + added SA +======================================================================== +*/ +void save_rexc_ram(void) +{ + FILE *fd; + int size; + + /* Open RexC RAM file */ + fd = fopen(mem_setup.rexc_ram_file, "wb+"); + + /* Print error if unable to open the file */ + if (fd == NULL) + { + char msg[100]; + sprintf(msg, "Could not save REXCPM RAM file %s", mem_setup.rexc_ram_file); + show_error(msg); + return; + } + + /* Check if file opened successfully */ + if (fd != 0) + { + size = 4 * 1024 * 1024; /* Copy 4MB of RAM */ + + /* Write RexC RAM first */ + fwrite(gRexCRam, 1, size, fd); + + /* Close the file */ + fclose(fd); + } +} + + /* ======================================================================== save_rex_flash: This routine saves the Rex emulation flash to the Rex @@ -1221,7 +1465,7 @@ void save_ram(void) { save_remem_ram(); /* Save ReMem data to file */ } - else + else if (gRex != REXC) // modified SA { /* Base memory -- First get the emulation path */ get_emulation_path(file, gModel); @@ -1299,11 +1543,22 @@ void save_ram(void) Save Rex Flash & RAM if enabled =========================================== */ - if (gRex) + if (gRex && (gRex != REXC)) { save_rex_flash(); /* Save the flash */ save_rex2_ram(); /* Save Rex2 RAM to file */ } + + + /* + =========================================== + Save RexC RAM if enabled added SA + =========================================== + */ + if (gRex == REXC) + { + save_rexc_ram(); /* Save RexCPM RAM to file */ + } } /* @@ -1372,14 +1627,17 @@ void load_remem_ram(void) if (gModel == MODEL_T200) for (x = 0; x < sizeof(gMsplanROM); x++) gReMemFlash1.pFlash[0x10000 + x] = gMsplanROM[x]; + (void) (readlen); } void reload_sys_rom(void) { int x; - - for (x = 0; x < ROMSIZE; x++) - gReMemFlash1.pFlash[x] = gSysROM[x]; + if (gReMem && !gRex) + { + for (x = 0; x < ROMSIZE; x++) + gReMemFlash1.pFlash[x] = gSysROM[x]; + } } /* @@ -1417,6 +1675,7 @@ void load_rampac_ram(void) /* Close the file */ fclose(fd); } + (void) (readlen); } /* @@ -1457,6 +1716,7 @@ void load_rex_flash(void) /* Now update the VirtualT version if needed */ patch_vt_version(gRexFlash.pFlash, ROMSIZE); } + (void) (readlen); } /* @@ -1494,8 +1754,49 @@ void load_rex2_ram(void) /* Close the file */ fclose(fd); } + (void) (readlen); +} + +/* +======================================================================== +load_rexc_ram: This routine loads the RexC emulation RAM from the + RexC RAM file. + added SA +======================================================================== +*/ +void load_rexc_ram(void) +{ + FILE *fd; + int size; + int readlen; + + /* Open RexC RAM file */ + fd = fopen(mem_setup.rexc_ram_file, "rb+"); + + /* Print error if unable to open the file */ + if (fd == NULL) + { + char msg[100]; + sprintf(msg, "Could not open REXCPM RAM file %s", mem_setup.rexc_ram_file); + show_error(msg); + return; + } + + /* Check if file opened successfully */ + if (fd != 0) + { + size = 4 * 1024 * 1024; /* Copy 4MB of RAM */ + + /* Read RexC RAM */ + readlen = fread(gRexCRam, 1, size, fd); + + /* Close the file */ + fclose(fd); + } + (void) (readlen); } + /* ======================================================================== load_ram: This routine loads the contens of the RAM in preparation @@ -1518,13 +1819,14 @@ void load_ram(void) int readlen; /* Check if ReMem emulation enabled or Base Memory emulation */ - if (gReMem & !gRex) + if (gReMem & !gRex ) { /* In ReMem mode - load RAM */ load_remem_ram(); /* Call routine to load ReMem */ remem_copy_normal_to_system(); } - else + + else if (gRex != REXC) { /* Zero the base memory */ for (x = 0; x < 64; x++) @@ -1628,13 +1930,26 @@ void load_ram(void) Load Rex Flash and RAM if enabled =========================================== */ - if (gRex) + if (gRex & (gRex != REXC)) { /* Load Rex Flash and RAM if needed */ load_rex_flash(); if (gRex == REX2) load_rex2_ram(); } + + /* + =========================================== + Load REXCPM RAM if enabled // added SA + =========================================== + */ + if (gRex && (gRex == REXC)) + { + /* Load RexCPM RAM if needed */ + load_rexc_ram(); + + } + (void) (readlen); } /* @@ -1718,7 +2033,7 @@ void patch_vt_version(char* pMem, int size) /* ============================================================================= -load_opt_rom: This function loads option ROMS as specified by user settings. +load_sys_rom: This function loads option ROMS as specified by user settings. ============================================================================= */ void load_sys_rom(void) @@ -1779,6 +2094,7 @@ void load_sys_rom(void) /* Copy ROM into system memory */ memcpy(gBaseMemory, gSysROM, ROMSIZE); + (void) (readlen); } /* ============================================================================= @@ -1816,7 +2132,7 @@ void load_opt_rom(void) for (c = 0; c < len; c++) gOptROM[c] = buf[c]; - if (gReMem) + if (gReMem && !gRex) //changed SA) { if (gModel == MODEL_T200) for (c = 0; c < len; c++) @@ -1825,7 +2141,11 @@ void load_opt_rom(void) for (c = 0; c < len; c++) gReMemFlash1.pFlash[0x8000 + c] = buf[c]; } - + else if (gRex == REXC) + { + for (c = 0; c < 32768; c++) + gRexCRam [0x8000 + c] = gOptROM[c]; + } } else { @@ -1837,7 +2157,7 @@ void load_opt_rom(void) fclose(fd); } - if (gReMem) + if (gReMem && !gRex) //changed SA { if (gModel == MODEL_T200) for (c = 0; c < OPTROMSIZE; c++) @@ -1846,7 +2166,13 @@ void load_opt_rom(void) for (c = 0; c < OPTROMSIZE; c++) gReMemFlash1.pFlash[0x8000 + c] = gOptROM[c]; } + else if (gRex == REXC) + { + for (c = 0; c < 32768; c++) + gRexCRam [0x8000 + c] = gOptROM[c]; + } } + (void) (readlen); } /* @@ -1861,9 +2187,10 @@ void set_ram_bank(unsigned char bank) char sbank[10]; int block; - if (!(gReMem && !gRex)) +// if (!(gReMem && !gRex)) + if (!gReMem || (gRex && (gRex != REXC))) { - /* Deal with Non-Remem Banks */ + /* Deal with Non-Remem Banks , excluding case where REXC is installed */ switch (gModel) { case MODEL_M100: /* Moel 100 QUAD support */ @@ -1886,7 +2213,7 @@ void set_ram_bank(unsigned char bank) break; } } - else + else if (gReMem) { /* Deal with ReMem emulation mode */ if (gModel == MODEL_T200) @@ -1957,91 +2284,119 @@ set_rom_bank: This function sets the current ROM bank for all models. It */ void set_rom_bank(unsigned char bank) { - int block, blocks; + int block, blocks, x; if (!(gReMem && !gRex)) { - /* Deal with non-ReMem emulation */ - switch (gModel) + if (gRex == REXC) { - case MODEL_M100: /* Model 100 / 102 emulation */ - case MODEL_M102: - case MODEL_KC85: - // Default ROM size - gRomSize = 32768; - - // Save any writes to OptROM space - if ((gOptRomRW) && (gRomBank == 1)) - memcpy(gOptROM, gBaseMemory, ROMSIZE); - - // Update ROM bank - gRomBank = bank; - if (bank & 0x01) - { - memcpy(gBaseMemory,gOptROM,ROMSIZE); - gRomSize = gOptRomRW ? 0 : 32768; - } - else - memcpy(gBaseMemory,gSysROM,ROMSIZE); - break; - - case MODEL_T200: /* Model 200 emulation */ - // Default ROM size - gRomSize = 40960; - - // Save any writes to OptROM space - if ((gOptRomRW) && (gRomBank == 2)) - memcpy(gOptROM, gBaseMemory, OPTROMSIZE); - - // Save ROM bank - gRomBank = bank; - - switch (bank) { - case 0: - memcpy(gBaseMemory,gSysROM,ROMSIZE); - break; - case 1: - memcpy(gBaseMemory, gMsplanROM, sizeof(gMsplanROM)); - break; - case 2: - memcpy(gBaseMemory,gOptROM,sizeof(gOptROM)); - gRomSize = gOptRomRW ? 0 : 40960; - break; - } - break; - - case MODEL_PC8201: /* NEC laptops */ - case MODEL_PC8300: - // Default ROM size - gRomSize = 32768; - - // Save any writes to OptROM space - if ((gOptRomRW) && (gRomBank == 2)) - memcpy(gOptROM, gBaseMemory, ROMSIZE); - - // Save ROM bank - gRomBank = bank; /* Update global ROM bank var */ - - switch (bank) + // Default ROM size + gRomSize = 32768; + + // Save any writes to OptROM space + if ((gOptRomRW) && (gRomBank == 1)) + for (x = 0; x < 0x08000; x++) // copy 32k + gRexCRam[gRexCOSector<<15 | x] = gBaseMemory[x]; + + // Update ROM bank + gRomBank = bank; + if (bank & 0x01) + { + memcpy(gBaseMemory,gOptROM,ROMSIZE); + for (x = 0; x < 0x08000; x++) // copy 32k + { + gBaseMemory[x] = gRexCRam[gRexCOSector<<15 | x]; + } + gRomSize = gOptRomRW ? 0 : 32768; + } + else + memcpy(gBaseMemory,gSysROM,ROMSIZE); + + } + else + { + /* Deal with non-ReMem emulation */ + switch (gModel) { - case 0: /* System ROM bank */ - if (gModel == MODEL_PC8201) - memcpy(gBaseMemory, gSysROM, ROMSIZE); - else - memcpy(gBaseMemory, &gSysROM[gRom0Bank*32768], ROMSIZE); + case MODEL_M100: /* Model 100 / 102 emulation */ + case MODEL_M102: + case MODEL_KC85: + // Default ROM size + gRomSize = 32768; + + // Save any writes to OptROM space + if ((gOptRomRW) && (gRomBank == 1)) + memcpy(gOptROM, gBaseMemory, ROMSIZE); + + // Update ROM bank + gRomBank = bank; + if (bank & 0x01) + { + memcpy(gBaseMemory,gOptROM,ROMSIZE); + gRomSize = gOptRomRW ? 0 : 32768; + } + else + memcpy(gBaseMemory,gSysROM,ROMSIZE); break; - - case 1: /* Option ROM bank */ - memcpy(gBaseMemory,gOptROM,ROMSIZE); - gRomSize = gOptRomRW ? 0 : 32768; + + case MODEL_T200: /* Model 200 emulation */ + // Default ROM size + gRomSize = 40960; + + // Save any writes to OptROM space + if ((gOptRomRW) && (gRomBank == 2)) + memcpy(gOptROM, gBaseMemory, OPTROMSIZE); + + // Save ROM bank + gRomBank = bank; + + switch (bank) { + case 0: + memcpy(gBaseMemory,gSysROM,ROMSIZE); + break; + case 1: + memcpy(gBaseMemory, gMsplanROM, sizeof(gMsplanROM)); + break; + case 2: + memcpy(gBaseMemory,gOptROM,sizeof(gOptROM)); + gRomSize = gOptRomRW ? 0 : 40960; + break; + } break; - - case 2: /* RAM banks */ - case 3: - memcpy(gBaseMemory,&rambanks[(bank-1)*RAMSIZE],RAMSIZE); + + case MODEL_PC8201: /* NEC laptops */ + case MODEL_PC8300: + // Default ROM size + gRomSize = 32768; + + // Save any writes to OptROM space + if ((gOptRomRW) && (gRomBank == 2)) + memcpy(gOptROM, gBaseMemory, ROMSIZE); + + // Save ROM bank + gRomBank = bank; /* Update global ROM bank var */ + + switch (bank) + { + case 0: /* System ROM bank */ + if (gModel == MODEL_PC8201) + memcpy(gBaseMemory, gSysROM, ROMSIZE); + else + memcpy(gBaseMemory, &gSysROM[gRom0Bank*32768], ROMSIZE); + break; + + case 1: /* Option ROM bank */ + memcpy(gBaseMemory,gOptROM,ROMSIZE); + gRomSize = gOptRomRW ? 0 : 32768; + break; + + case 2: /* RAM banks */ + case 3: + memcpy(gBaseMemory,&rambanks[(bank-1)*RAMSIZE],RAMSIZE); + break; + } break; } - break; } } else @@ -3109,6 +3464,8 @@ void remem_flash_proc_timer(void) gReMemFlashReady = TRUE; } + + /* ============================================================================= rex_read: This routine processes reads during REX emulation mode. @@ -3126,185 +3483,450 @@ unsigned char rex_read(unsigned short address) if (address & 0x8000) return (address>ROMSIZE&&address 0) amd_flash_proc_timer(&gRexFlash); + // Process read as a REX State machine read switch (gRexState) { case 7: /* Read State */ - if ((address & 0xFF) == gRexKeyTable[gRexKeyState]) + if ( (readcounter != lastreadcounter)) + // proceeed only if valid read { - if (++gRexKeyState == 6) + optromcounter = ((optromcounter +1) & 0xFF); // a valid optrom read occured + + if ( ((address & 0xFF) == gRexKeyTable[gRexKeyState]) && (optromcounter == (gRexKeyState+1) ) ) + { // advance only if valid sequential optrom read occured + readcounterclear = 0; + + if (++gRexKeyState == 6) + { + /* Key sequence detected - switch to state zero */ + gRexState = 0; + gRexKeyState = 0; /* ensure key state is set to 0 here SA*/ + } + } + else { - /* Key sequence detected - switch to state zero */ - gRexState = 0; + /* Key state not detected - clear keystate */ + gRexKeyState = 0; + readcounterclear = 1; + } + } - else - /* Key state not detected - clear keystate */ - gRexKeyState = 0; return gRexFlash.pFlash[gRexSector | address]; case 0: /* Command mode */ - switch (address & 0x07) + if (readcounter != lastreadcounter) // process in state machine only if valid read { - case 3: /* Read Status CMD */ - gRexReturn =(gRexFlash.iFlashBusy ? 0 : 0x80) | - (gRexFlashSel ? 0x40 : 0) | - (gRexSector >> 15); - gRexState = address & 0x07; - return gRexReturn; - - case 2: /* Send AAA,AA CMD */ - case 5: /* Send 555,55 CMD */ - case 6: /* Send PA, PD */ - /* For REX2 (PC8201), the state machine had to change because of no ALE. - In this case, we transition to state 2 to await the data, then to state - 6 to await the address. */ - if (gModel == MODEL_PC8201) + switch (address & 0x07) { - // Go to state 2 - gRexState = 2; - gRex3Cmd = address & 0x07; + case 3: /* Read Status CMD */ + gRexReturn =(gRexFlash.iFlashBusy ? 0 : 0x80) | + (gRexFlashSel ? 0x40 : 0) | + (gRexSector >> 15); + gRexState = address & 0x07; + return gRexReturn; + + case 2: /* Send AAA,AA CMD */ + case 5: /* Send 555,55 CMD */ + case 6: /* Send PA, PD */ + /* For REXS or REX3 (PC8201), the state machine had to change because of no ALE. + In this case, we transition to state 2 to await the data, then to state + 6 to await the address. */ + if ( (gModel == MODEL_PC8201) || (gRex == REXS) ) + { + // Go to state 2 + gRexState = 2; + gRex3Cmd = address & 0x07; + break; + } + + // Fall through + + case 1: /* Set Sector CMD */ + case 4: /* Read from flash */ + gRexState = address & 0x07; + gRexFlashPA = address & 0xFF; break; - } - - // Fall through - - case 1: /* Set Sector CMD */ - case 4: /* Read from flash */ - gRexState = address & 0x07; - gRexFlashPA = address & 0xFF; - break; - - case 7: /* Read FW/HW ID */ - gRexReturn = (gRex == REX2 ? 0x40 : 0) | - (0x10) | gRexModel; - gRexState = 3; - return gRexReturn; + + case 7: /* Read FW/HW ID */ + gRexReturn = (gRex == REX2 ? 0x40 : 0) | + (0x10) | gRexModel; + gRexState = 3; + return gRexReturn; + + default: + readcounterclear = 1; + gRexState = 7; - default: - gRexState = 7; - break; + break; + } } break; case 1: /* Set Sector state */ - /* Test if RAM mode is enabled and set sector based on result */ -// if (gModel && REX2_RAM_MODE) -// gRexSector = (address & 0x3F) << 15; -// else - gRexSector = (address & 0x1F) << 15; - - /* Save Flash Select bit */ - gRexFlashSel = address & 0x40 ? 0 : 1; - - /* Back to state 0 for next command */ - gRexState = 0; + if (readcounter != lastreadcounter) // process in state machine only if valid read + { + /* Test if RAM mode is enabled and set sector based on result */ + // if (gModel && REX2_RAM_MODE) + // gRexSector = (address & 0x3F) << 15; + // else + gRexSector = (address & 0x1F) << 15; + + /* Save Flash Select bit when NOT REXS */ + // if (gRex <> REXS) + gRexFlashSel = address & 0x40 ? 0 : 1; + + /* Back to state 0 for next command */ + gRexState = 0; + } break; case 2: /* Send AAA, AD to Flash */ - if (gModel == MODEL_PC8201) + if (readcounter != lastreadcounter) // process in state machine only if valid read { - /* For REX3 (PC8201), we save the write data during state 2, then go to - state 6 to await the address */ - gRex3Data = address & 0xFF; - gRexState = 6; + if ( (gModel == MODEL_PC8201) || (gRex == REXS) ) + { + /* For REXS or REX3 (PC8201), we save the write data during state 2, then go to + state 6 to await the address */ + gRex3Data = address & 0xFF; + gRexState = 6; + + } + else + { + /* Write to the REX Flash object. LSB of address is actually data */ + amd_flash_write(&gRexFlash, gRexSector | gRexFlashPA, address & 0xFF); + + /* Back to state 0 for next command */ + gRexState = 0; + } } - else - { - /* Write to the REX Flash object. LSB of address is actually data */ - amd_flash_write(&gRexFlash, gRexSector | gRexFlashPA, address & 0xFF); + break; - /* Back to state 0 for next command */ + case 3: + if (readcounter != lastreadcounter) // process in state machine only if valid read + { + /* Switch back to state 0 */ gRexState = 0; + return gRexReturn; } break; - case 3: - /* Switch back to state 0 */ - gRexState = 0; - return gRexReturn; - case 4: /* Read from flash */ - /* Test if reading from RAM sector */ - gRexState = 8; /* Holding state */ - - /* Read from either RAM for Flash */ - if (gRexSector & 0x100000) + if (readcounter != lastreadcounter) // process in state machine only if valid read { - /* Read from RAM if REX2 */ - if (gRex == REX2) - gRexReturn = gRex2Ram[(gRexSector & 0x18000) | (address & 0x7FFF)]; - else - gRexReturn = 0xFF; - } - else - { - /* Read from Flash if enabled */ - if (gRexFlashSel) - gRexReturn = gRexFlash.pFlash[gRexSector | (address & 0x7FFF)]; + /* Test if reading from RAM sector */ + gRexState = 8; /* Holding state */ + + /* Read from either RAM for Flash */ + if (gRexSector & 0x100000) + { + /* Read from RAM if REX2 */ + if (gRex == REX2) + gRexReturn = gRex2Ram[(gRexSector & 0x18000) | (address & 0x7FFF)]; + else + gRexReturn = 0xFF; + } else - gRexReturn = 0xFF; + { + /* Read from Flash if enabled */ + if (gRexFlashSel) + gRexReturn = gRexFlash.pFlash[gRexSector | (address & 0x7FFF)]; + else + gRexReturn = 0xFF; + } + return gRexReturn; } - return gRexReturn; + break; case 8: /* Temp holding state for state 4 */ - gRexState = 0; /* Back to state 0 */ - return gRexReturn; + if (readcounter != lastreadcounter) // process in state machine only if valid read + { + gRexState = 0; /* Back to state 0 */ + return gRexReturn; + } + break; case 5: /* Send 555,data to flash */ - gRexState = 0; /* Back to state 0 */ - - /* Send 555,data to flash */ - amd_flash_write(&gRexFlash, 0x55, 0x55); - + if (readcounter != lastreadcounter) // process in state machine only if valid read + { + gRexState = 0; /* Back to state 0 */ + + /* Send 555,data to flash */ + amd_flash_write(&gRexFlash, 0x55, 0x55); + } break; case 6: /* Send PA,PD to flash, first we receive PA */ - /* Test for REX3 (PC8201) */ - if (gModel == MODEL_PC8201) - { - /* For REX3, we perform the write during state 6 */ - switch (gRex3Cmd) + if (readcounter != lastreadcounter) // process in state machine only if valid read + { + /* Test for REXS or REX3 (PC8201) */ + if ( (gModel == MODEL_PC8201) || (gRex == REXS) ) + { + // gRexFlashPA = gRexSector | (address & 0x7FFF); + /* For REXS or REX3, we perform the write during state 6 */ + switch (gRex3Cmd) + { + case 2: + gRexFlashPA = gRexSector | (address & 0xFF); + break; + case 5: + gRexFlashPA = gRexSector | (address & 0xFF); // SA + // gRexFlashPA = address & 0xFF; + break; + case 6: + gRexFlashPA = gRexSector | (address & 0x7FFF); + break; + default: + gRexFlashPA = 0; + break; + } + /* Write to the REX Flash object. LSB of address is actually data */ + amd_flash_write(&gRexFlash, gRexFlashPA, gRex3Data); + + /* Back to state 0 for next command */ + gRexState = 0; + } + else { - case 2: - gRexFlashPA = gRexSector | (address & 0xFF); - break; - case 5: - gRexFlashPA = address & 0xFF; - break; - case 6: - gRexFlashPA = gRexSector | (address & 0x7FFF); - break; - default: - gRexFlashPA = 0; - break; + /* Save the address from this read as our Flash PA */ + gRexFlashPA = address & 0x7FFF; + + /* Go to State 2 to await the data */ + gRexState = 2; } + } + break; + } + return (unsigned char) (0xFF); //(address & 0xFF); +} - /* Write to the REX Flash object. LSB of address is actually data */ - amd_flash_write(&gRexFlash, gRexFlashPA, gRex3Data); - /* Back to state 0 for next command */ - gRexState = 0; - } + +/* +============================================================================= +rexC_read: This routine processes reads during REXC emulation mode. +S. Adolph +============================================================================= +*/ +unsigned char rexC_read(unsigned short address) +{ + gRexCKey = gRexCKeyTable[gRexCKeyState]; + gRexCKeyAddr = (address>>8)&0xFF ; + + /* Reads from primary ROM are processed as usual */ + if (address < 0x8000) + { + if ((gRomBank == 0)) + // return main ROM memory contents + return gBaseMemory[address]; else + return gRexCRam[ gRexCOSector <<15 | (address&0x7FFF)]; // OPTROM + } + else + { + // otherwise REXCPM is returning a RAM value based on register contents and state machine + // Process the read as a REXC State machine read + switch (gRexCState) { - /* Save the address from this read as our Flash PA */ - gRexFlashPA = address & 0x7FFF; + case 15: /* Default power up, Read State.. counter should be static at 1 */ + if (readcounter == ((lastreadcounter+1) & 0xFF) ) // process in state machine only if valid read + { + if (((address>>8) & 0xFF) == gRexCKeyTable[gRexCKeyState]) + { + gRexCState = 14; + gRexCKeyState = 1; + readcounterclear = 0; + } + else + { + gRexCState = 15; + gRexCKeyState = 0; + readcounterclear = 1; + } + } + if ( (address&0xC000) == 0xC000 ) + return gRexCRam[ gRexCRUSector<<14 | (address&0x3FFF)]; // Upper RAM + else + return gRexCRam[ gRexCRLSector<<14 | (address&0x3FFF)]; // Lower RAM + break; + case 14: + case 13: + case 12: + case 11: + case 10: /* Read State */ + if (readcounter == ((lastreadcounter+1) & 0xFF) ) // process in state machine only if valid read + { + if (readcounter < ( (gRexCKeyState*4) +1 ) ) + { + } + else if (readcounter > ( (gRexCKeyState*4) +1 ) ) + { + gRexCState = 15; + gRexCKeyState = 0; + readcounterclear = 1; + } + else // check for key + { + if (((address>>8) & 0xFF) == gRexCKeyTable[gRexCKeyState]) + { + if (gRexCState == 10) + gRexCState = 0; + else + --gRexCState; + ++gRexCKeyState; + } + else + { + gRexCState = 15; + gRexCKeyState = 0; + readcounterclear = 1; + } + } + } + if ( (address&0xC000) == 0xC000 ) + return gRexCRam[ gRexCRUSector<<14 | (address&0x3FFF)]; // Upper RAM + else + return gRexCRam[ gRexCRLSector<<14 | (address&0x3FFF)]; // Lower RAM + break; + case 0: /* Command state, read registers or write register content */ + /* enter on readcount = 21, execute on readcount = 23 */ + readcounterclear = 0; + gRexCKeyState = 0; + if (readcounter == ((lastreadcounter+1) & 0xFF) ) // process in state machine only if valid read + { + if (readcounter < 23) + { + } + else if (readcounter > 24) + gRexCState = 15; // jump out and search for keys again + else // (readcounter == 23) + { + gRexCState = 1; + if (((address & 0x07000)>>12) == 1) + gRexCOSector = ((address & 0x0F00)>>5); // set upper 4 bits of OPTROM register + else if (((address & 0x07000)>>12) == 2) + gRexCRLSector = ((address & 0x0F00)>>4); // set upper 4 bits of lower RAM register + else if (((address & 0x07000)>>12) == 3) + gRexCRUSector = ((address & 0x0F00)>>4); // set upper 4 bits of upper RAM register + } + } + if ( (address&0xC000) == 0xC000 ) + return gRexCRam[ gRexCRUSector<<14 | (address&0x3FFF)]; // Upper RAM + else + return gRexCRam[ gRexCRLSector<<14 | (address&0x3FFF)]; // Lower RAM + break; + + case 1: /* Command state, read registers or write register content */ + /* enter on readcount = 23, execute on readcount = 26 */ - /* Go to State 2 to await the data */ - gRexState = 2; + if (readcounter != ((lastreadcounter+1) & 0xFF) ) // return these returns if not valid read + { + if ( (address&0xC000) == 0xC000 ) + return gRexCRam[ gRexCRUSector<<14 | (address&0x3FFF)]; // Upper RAM + else + return gRexCRam[ gRexCRLSector<<14 | (address&0x3FFF)]; // Lower RAM + } + readcounterclear = 0; + gRexCKeyState = 0; + if (readcounter < 26) + { + if ( (address&0xC000) == 0xC000 ) + return gRexCRam[ gRexCRUSector<<14 | (address&0x3FFF)]; // Upper RAM + else + return gRexCRam[ gRexCRLSector<<14 | (address&0x3FFF)]; // Lower RAM + } + else if (readcounter > 26) + { + gRexCState = 15; + if ( (address&0xC000) == 0xC000 ) + return gRexCRam[ gRexCRUSector<<14 | (address&0x3FFF)]; // Upper RAM + else + return gRexCRam[ gRexCRLSector<<14 | (address&0x3FFF)]; // Lower RAM + } + else // (readcounter == 26) + { + gRexCState = 15; + if (((address & 0x07000)>>12) == 0) + { // gRexCState = 8; + gRexCWP = ((address & 0x0100)>>8); + return gRexCWP; + } + else if (((address & 0x07000)>>12) == 1) + { // set lower 3 bits of OPTROM register RexCState = 5; + gRexCOSector = gRexCOSector + ((address & 0x0E00)>>9); + return (gRexCOSector<<1); + } + else if (((address & 0x07000)>>12) == 2) + { // set lower 4 bits of lower RAM register gRexCState = 6; + gRexCRLSector = gRexCRLSector + ((address & 0x0F00)>>8);; + return gRexCRLSector; + } + else if (((address & 0x07000)>>12) == 3) + { // set lower 4 bits of upper RAM register gRexCState = 7; + gRexCRUSector = gRexCRUSector + ((address & 0x0F00)>>8); + return gRexCRUSector; + } + else if (((address & 0x07000)>>12) == 4) // gRexCState = 4; + return gRexCModel; + else if (((address & 0x07000)>>12) == 5) // gRexCState = 5; + return (gRexCOSector<<1); + else if (((address & 0x07000)>>12) == 6) // gRexCState = 6; + return gRexCRLSector; + else if (((address & 0x07000)>>12) == 7) // gRexCState = 7; + return gRexCRUSector; + else + return gRexCModel; + } + break; } + } +} - break; +/* +============================================================================= +rexC_set8: This routine processes writes during REXC emulation mode. +S. Adolph +============================================================================= +*/ +void rexC_set8(unsigned short address, unsigned char val) +{ + /* writes are allowed to OPTROM and RAM in M100 and T102 */ + /* write protection can be enabled for 16kblocks 8 and above, and block 1 (32k) */ + /* range for gRexCOSector is 0 to 127 (4MB) */ + /* range for gRexCRUSector is 0 to 255 (4MB) */ + + if ((address < 32768) && (gRomBank == 1)) + { + if ( ( (gRexCWP) && ((gRexCOSector < 4) && (gRexCOSector != 1))) || (!gRexCWP) ) // 32k basis + { + gRexCRam[ gRexCOSector<<15 | (address&0x7FFF)] = val; // OPTROM + } + } + else if ((address >= 49152)) + { + if ( ( (gRexCWP) && ((gRexCRUSector < 8) && (gRexCRUSector != 2) && (gRexCRUSector != 3))) || (!gRexCWP) ) + { + gRexCRam[ gRexCRUSector<<14 | (address&0x3FFF)] = val; // Upper RAM // 16k basis + } + } + else if ((address >= 32768) && (address < 49152)) + { + if ( ( (gRexCWP) && ((gRexCRLSector < 8) && (gRexCRLSector != 2)&& (gRexCRLSector != 3))) || (!gRexCWP) ) + { + gRexCRam[ gRexCRLSector<<14 | (address&0x3FFF)] = val; // Lower RAM // 16k basis + } } - return (unsigned char) (address & 0xFF); } +// if ( (gRexCWP!=1) || ( (gRexCWP==1) && ((gRexCRLSector==0) || (gRexCRLSector==1) || (gRexCRLSector==4) || (gRexCRLSector==5) || (gRexCRLSector==6) ||(gRexCRLSector== 7) ))) +// if ( (gRexCWP!=1) || ( (gRexCWP==1) && ((gRexCRUSector==0) || (gRexCRUSector==1) || (gRexCRUSector==4) || (gRexCRUSector==5) || (gRexCRUSector ==6) || (gRexCRUSector== 7) )) ) /* ============================================================================= rex_set8: This routine processes writes during REX emulation mode. @@ -3327,3 +3949,5 @@ void rex_set8(unsigned short address, unsigned char val) } } +// vim: noet sw=4 ts=4 + diff --git a/src/memory.h b/src/memory.h index 037b845..b1f2244 100644 --- a/src/memory.h +++ b/src/memory.h @@ -112,9 +112,13 @@ extern "C" { #define REGION_ROM4 14 #define REGION_MAX 15 #define REGION_RAM4 16 +#define REGION_REXC_RAM 17 // added SA #define REX 1 #define REX2 2 +#define REXS 3 // added SA +#define REXC 4 // added SA + #define REX_ROM_REPLACEMENT 0x01 #define REX2_RAM_MODE 0x02 @@ -146,6 +150,18 @@ extern unsigned char gBaseMemory[65536]; extern unsigned char gReMem; extern int gRex; +extern int gRexState; // added SA to support remote.cpp functions +extern int gRexSector; +extern int gRexCState; +extern unsigned char gRexCOSector; +extern unsigned char gRexCRLSector; +extern unsigned char gRexCRUSector; +extern int gRexCWP; +extern int readcounter; + +extern int gRexCKey; +extern int gRexCKeyAddr; + void init_mem(void); void reinit_mem(void); void cold_boot_mem(void); @@ -153,8 +169,10 @@ void free_mem(void); void free_remem_mem(void); void free_rampac_mem(void); void load_rampac_ram(void); +void load_rexc_ram(void); // added SA void load_remem_ram(void); void save_rampac_ram(void); +void save_rexc_ram(void); // added SA void save_remem_ram(void); void reload_sys_rom(void); void save_rex2_ram(void); @@ -163,6 +181,7 @@ void load_rex2_ram(void); void load_rex_flash(void); unsigned char get_memory8(unsigned short address); +unsigned char get_memory8_counter(unsigned short address); // added to facilitate read counting in REXCPM unsigned short get_memory16(unsigned short address); void set_memory8(unsigned short address, unsigned char data); void set_memory16(unsigned short address, unsigned short data); @@ -184,7 +203,9 @@ unsigned char remem_flash_sm_read(unsigned short address); void remem_flash_proc_timer(void); void patch_vt_version(char* pMem, int size); unsigned char rex_read(unsigned short address); -void rex_set8(unsigned short address, unsigned char val); +unsigned char rexC_read(unsigned short address); // added SA +void rex_set8(unsigned short address, unsigned char val); +void rexC_set8(unsigned short address, unsigned char val); // added SA void save_ram(void); void load_ram(void); diff --git a/src/n8201rom.c b/src/n8201rom.c index f4eb81a..cb64548 100644 --- a/src/n8201rom.c +++ b/src/n8201rom.c @@ -898,7 +898,8 @@ RomDescription_t gN8201_Desc = { gN8201_Vars, /* Known variables */ gN8201_Funs, /* Known functions */ - 0xF979, /* Address of unsaved BASIC prgm */ + 0xF45D, /* Address of unsaved BASIC prgm */ + //0xF979, /* Address of unsaved BASIC prgm */ 0xF87C, /* Address of next DO file */ 0xFAE1, /* Start of DO file area */ 0xFAE3, /* Start of CO file area */ diff --git a/src/periph.cpp b/src/periph.cpp index ef7b667..b6844e3 100644 --- a/src/periph.cpp +++ b/src/periph.cpp @@ -59,6 +59,16 @@ #include "lpt.h" #include "fileview.h" +extern int gMidnight; + +#define COLOR_BG (gMidnight ? FL_BLACK : fl_rgb_color(192, 192, 192)) +#define COLOR_BG_INPUT (gMidnight ? FL_BLACK : FL_WHITE) +#define COLOR_FG (gMidnight ? FL_WHITE : FL_BLACK) +#define COLOR_TAB_INACTIVE_BG (gMidnight ? fl_rgb_color(32,32,32) : fl_rgb_color(192,192,192)) +#define COLOR_TAB_INACTIVE_FG (gMidnight ? fl_rgb_color(192,192,192) : FL_BLACK) +#define FL_LIGHT_RED fl_rgb_color(255, 195, 195) +#define FL_LIGHT_BLUE fl_rgb_color(195, 195, 255) + void cb_Ide(Fl_Widget* w, void*) ; typedef struct periph_ctrl_struct @@ -565,91 +575,122 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) // Create Peripheral Setup window gpdw = new Fl_Window(550, 400, "Peripheral Devices"); gpdw->callback(cb_peripheralwin); + gpdw->color(COLOR_BG); // Create Peripheral Tabs { // Create a menu for the new window. periph_ctrl.pMenu = new Fl_Menu_Bar(0, 0, 550, MENU_HEIGHT-2); periph_ctrl.pMenu->menu(gPeriph_menuitems); + periph_ctrl.pMenu->color(COLOR_BG); + periph_ctrl.pMenu->textcolor(COLOR_FG); periph_ctrl.pTabs = new Fl_Tabs(10, MENU_HEIGHT+10, 530, 380-MENU_HEIGHT); + periph_ctrl.pTabs->color(COLOR_BG); + periph_ctrl.pTabs->selection_color(COLOR_BG); + periph_ctrl.pTabs->labelcolor(COLOR_FG); // COM port Tab { periph_ctrl.com.g = new Fl_Group(10, 30+MENU_HEIGHT, 540, 380-MENU_HEIGHT, " COM "); + periph_ctrl.com.g->color(COLOR_BG); + periph_ctrl.com.g->selection_color(COLOR_TAB_INACTIVE_BG); + periph_ctrl.com.g->labelcolor(COLOR_TAB_INACTIVE_FG); // Create static text boxes o = new Fl_Box(FL_NO_BOX, 20, 45+MENU_HEIGHT, 50, 15, "Port Name:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 20, 70+MENU_HEIGHT, 50, 15, "Port Status:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 20, 95+MENU_HEIGHT, 50, 15, "Baud Rate:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 20, 120+MENU_HEIGHT, 50, 15, "Start Char:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 180, 70+MENU_HEIGHT, 50, 15, "Word Size:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 180, 95+MENU_HEIGHT, 50, 15, "Parity:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 180, 120+MENU_HEIGHT, 50, 15, "End Char:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 320, 70+MENU_HEIGHT, 50, 15, "Stop Bits:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 450, 45+MENU_HEIGHT, 50, 15, "RTS:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 450, 70+MENU_HEIGHT, 50, 15, "DTR:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 450, 95+MENU_HEIGHT, 50, 15, "CTS:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 450, 120+MENU_HEIGHT, 50, 15, "DSR:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); periph_ctrl.com.pPortName = new Fl_Box(FL_NO_BOX, 100, 45+MENU_HEIGHT, 400, 15, periph_ctrl.com.sPortName); periph_ctrl.com.pPortName->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + periph_ctrl.com.pPortName->labelcolor(COLOR_FG); periph_ctrl.com.pPortStatus = new Fl_Box(FL_NO_BOX, 100, 70+MENU_HEIGHT, 50, 15, periph_ctrl.com.sPortStatus); periph_ctrl.com.pPortStatus->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + periph_ctrl.com.pPortStatus->labelcolor(COLOR_FG); periph_ctrl.com.pBaud = new Fl_Box(FL_NO_BOX, 100, 95+MENU_HEIGHT, 50, 15, periph_ctrl.com.sBaud); periph_ctrl.com.pBaud->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + periph_ctrl.com.pBaud->labelcolor(COLOR_FG); periph_ctrl.com.pStartChar = new Fl_Box(FL_NO_BOX, 100, 120+MENU_HEIGHT, 60, 15, periph_ctrl.com.sStartChar); periph_ctrl.com.pStartChar->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + periph_ctrl.com.pStartChar->labelcolor(COLOR_FG); strcpy(periph_ctrl.com.sStartChar, "(Click)"); periph_ctrl.com.pWordSize = new Fl_Box(FL_NO_BOX, 260, 70+MENU_HEIGHT, 50, 15, periph_ctrl.com.sWordSize); periph_ctrl.com.pWordSize->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + periph_ctrl.com.pWordSize->labelcolor(COLOR_FG); periph_ctrl.com.pParity = new Fl_Box(FL_NO_BOX, 260, 95+MENU_HEIGHT, 50, 15, periph_ctrl.com.sParity); periph_ctrl.com.pParity->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + periph_ctrl.com.pParity->labelcolor(COLOR_FG); periph_ctrl.com.pStopChar = new Fl_Box(FL_NO_BOX, 260, 120+MENU_HEIGHT, 120, 15, periph_ctrl.com.sStopChar); periph_ctrl.com.pStopChar->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + periph_ctrl.com.pStopChar->labelcolor(COLOR_FG); strcpy(periph_ctrl.com.sStopChar, "(Shift/Right Click)"); periph_ctrl.com.pStopBits = new Fl_Box(FL_NO_BOX, 380, 70+MENU_HEIGHT, 50, 15, periph_ctrl.com.sStopBits); periph_ctrl.com.pStopBits->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + periph_ctrl.com.pStopBits->labelcolor(COLOR_FG); periph_ctrl.com.pDeltaTime = new Fl_Box(FL_NO_BOX, 20, 145+MENU_HEIGHT, 190, 15, periph_ctrl.com.sDeltaTime); periph_ctrl.com.pDeltaTime->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + periph_ctrl.com.pDeltaTime->labelcolor(COLOR_FG); strcpy(periph_ctrl.com.sDeltaTime, ""); ser_get_signals(&periph_ctrl.com.cSignal); periph_ctrl.com.pRTS = new Fl_Box(FL_OVAL_BOX, 490, 47+MENU_HEIGHT, 12, 12, ""); periph_ctrl.com.pRTS->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + periph_ctrl.com.pRTS->labelcolor(COLOR_FG); if (periph_ctrl.com.cSignal & SER_SIGNAL_RTS) periph_ctrl.com.pRTS->color(FL_YELLOW); else @@ -657,6 +698,7 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) periph_ctrl.com.pDTR = new Fl_Box(FL_OVAL_BOX, 490, 72+MENU_HEIGHT, 12, 12, ""); periph_ctrl.com.pDTR->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + periph_ctrl.com.pDTR->labelcolor(COLOR_FG); if (periph_ctrl.com.cSignal & SER_SIGNAL_DTR) periph_ctrl.com.pDTR->color(FL_YELLOW); else @@ -664,6 +706,7 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) periph_ctrl.com.pCTS = new Fl_Box(FL_OVAL_BOX, 490, 97+MENU_HEIGHT, 12, 12, ""); periph_ctrl.com.pCTS->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + periph_ctrl.com.pCTS->labelcolor(COLOR_FG); if (periph_ctrl.com.cSignal & SER_SIGNAL_CTS) periph_ctrl.com.pCTS->color(FL_YELLOW); else @@ -671,12 +714,16 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) periph_ctrl.com.pDSR = new Fl_Box(FL_OVAL_BOX, 490, 122+MENU_HEIGHT, 12, 12, ""); periph_ctrl.com.pDSR->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + periph_ctrl.com.pDSR->labelcolor(COLOR_FG); if (periph_ctrl.com.cSignal & SER_SIGNAL_DSR) periph_ctrl.com.pDSR->color(FL_YELLOW); else periph_ctrl.com.pDSR->color(FL_BLACK); periph_ctrl.com.pLog = new T100_ComMon(20, 200, 495, 190-MENU_HEIGHT); + periph_ctrl.com.pLog->color(COLOR_BG); + periph_ctrl.com.pLog->labelcolor(COLOR_FG); + periph_ctrl.com.pLog->box(FL_UP_FRAME); periph_ctrl.com.g->resizable(periph_ctrl.com.pLog); // periph_ctrl.com.pLog->color(FL_WHITE); @@ -690,14 +737,19 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) // Create items on the Tab periph_ctrl.com.pEnable = new Fl_Check_Button(20, 362, 130, 20, "Enable Capture"); periph_ctrl.com.pEnable->callback(cb_com_enable_box); + periph_ctrl.com.pEnable->color(COLOR_BG); + periph_ctrl.com.pEnable->labelcolor(COLOR_FG); // Create items on the Tab periph_ctrl.com.pHex = new Fl_Check_Button(160, 362, 50, 20, "HEX"); periph_ctrl.com.pHex->callback(cb_com_hex_box); + periph_ctrl.com.pHex->labelcolor(COLOR_FG); // Create items on the Tab periph_ctrl.com.pClear = new Fl_Button(330, 360, 80, 25, "Clear Log"); periph_ctrl.com.pClear->callback(cb_com_clear); + periph_ctrl.com.pClear->color(COLOR_BG); + periph_ctrl.com.pClear->labelcolor(COLOR_FG); periph_ctrl.com.pFont = new Fl_Choice(250, 362, 60, 20, "Size"); periph_ctrl.com.pFont->callback(cb_com_font_size); @@ -705,9 +757,14 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) periph_ctrl.com.pFont->add("14"); periph_ctrl.com.pFont->add("16"); periph_ctrl.com.pFont->value(0); + periph_ctrl.com.pFont->color(COLOR_BG); + periph_ctrl.com.pFont->labelcolor(COLOR_FG); + periph_ctrl.com.pFont->textcolor(COLOR_FG); Fl_Button *but = new Fl_Button(430, 360, 80, 25, "Save Log"); but->callback(cb_save_serial_log); + but->color(COLOR_BG); + but->labelcolor(COLOR_FG); periph_ctrl.com.g->end(); @@ -720,42 +777,58 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) { // Create the Group item (the "Tab") periph_ctrl.lpt.g = new Fl_Group(10, MENU_HEIGHT+30, 500, 380-MENU_HEIGHT, " LPT "); + periph_ctrl.lpt.g->color(COLOR_BG); + periph_ctrl.lpt.g->selection_color(COLOR_TAB_INACTIVE_BG); + periph_ctrl.lpt.g->labelcolor(COLOR_TAB_INACTIVE_FG); // Create static text boxes o = new Fl_Box(FL_NO_BOX, 20, 45+MENU_HEIGHT, 70, 15, "Emulation Mode:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); o = new Fl_Box(FL_NO_BOX, 20, 70+MENU_HEIGHT, 50, 15, "Port Status:"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); // Create control for reporting emulaiton mode periph_ctrl.lpt.pPortMode = new Fl_Box(150, 45+MENU_HEIGHT, 200, 15, "Unknown"); periph_ctrl.lpt.pPortMode->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + periph_ctrl.lpt.pPortMode->labelcolor(COLOR_FG); // Create control for reporting port status periph_ctrl.lpt.pPortStatus = new Fl_Box(150, 70+MENU_HEIGHT, 200, 15, "Unknown"); periph_ctrl.lpt.pPortStatus->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + periph_ctrl.lpt.pPortStatus->labelcolor(COLOR_FG); // Create control for hex log o = new Fl_Box(FL_NO_BOX, 20, 105+MENU_HEIGHT, 70, 15, "Hex Log"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); periph_ctrl.lpt.pHexLogBuffer = new Fl_Text_Buffer(); periph_ctrl.lpt.pHexLogDisplay = new Fl_Text_Display(20, 130+MENU_HEIGHT, 480, 180, ""); periph_ctrl.lpt.pHexLogDisplay->buffer(periph_ctrl.lpt.pHexLogBuffer); periph_ctrl.lpt.pHexLogDisplay->wrap_mode(1, 48); periph_ctrl.lpt.pHexLogDisplay->textfont(FL_COURIER); + periph_ctrl.lpt.pHexLogDisplay->color(COLOR_BG); + periph_ctrl.lpt.pHexLogDisplay->textcolor(COLOR_FG); + periph_ctrl.lpt.pHexLogDisplay->cursor_color(COLOR_FG); periph_ctrl.lpt.g->resizable(periph_ctrl.lpt.pHexLogDisplay); // Create control for enabling capture periph_ctrl.lpt.pEnable = new Fl_Check_Button(20, 357, 130, 20, "Enable Hex Log"); periph_ctrl.lpt.pEnable->callback(cb_lpt_enable_box); + periph_ctrl.lpt.pEnable->labelcolor(COLOR_FG); // Create control for Saving the log periph_ctrl.lpt.pSave = new Fl_Button(240, 355, 80, 25, "Save Log"); periph_ctrl.lpt.pSave->callback(cb_lpt_save); + periph_ctrl.lpt.pSave->color(COLOR_BG); + periph_ctrl.lpt.pSave->labelcolor(COLOR_FG); // Create control for Clearing the log periph_ctrl.lpt.pClear = new Fl_Button(340, 355, 80, 25, "Clear Log"); periph_ctrl.lpt.pClear->callback(cb_lpt_clear); + periph_ctrl.lpt.pClear->color(COLOR_BG); + periph_ctrl.lpt.pClear->labelcolor(COLOR_FG); // Populate controls with current status if (gLpt != NULL) @@ -776,10 +849,14 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) // Create the Group item (the "Tab") periph_ctrl.mdm.g = new Fl_Group(10, MENU_HEIGHT+30, 500, 380-MENU_HEIGHT, " MDM "); + periph_ctrl.mdm.g->color(COLOR_BG); + periph_ctrl.mdm.g->selection_color(COLOR_TAB_INACTIVE_BG); + periph_ctrl.mdm.g->labelcolor(COLOR_TAB_INACTIVE_FG); // Create controls periph_ctrl.mdm.pText = new Fl_Box(120, MENU_HEIGHT+60, 60, 80, "Modem Port not supported yet"); + periph_ctrl.mdm.pText->labelcolor(COLOR_FG); // End of control for this tab periph_ctrl.mdm.g->end(); @@ -790,10 +867,14 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) { // Create the Group item (the "Tab") periph_ctrl.cas.g = new Fl_Group(10, MENU_HEIGHT+30, 500, 380-MENU_HEIGHT, " CAS "); + periph_ctrl.cas.g->color(COLOR_BG); + periph_ctrl.cas.g->selection_color(COLOR_TAB_INACTIVE_BG); + periph_ctrl.cas.g->labelcolor(COLOR_TAB_INACTIVE_FG); // Create controls periph_ctrl.cas.pText = new Fl_Box(120, MENU_HEIGHT+60, 60, 80, "Cassette Port not supported yet"); + periph_ctrl.cas.pText->labelcolor(COLOR_FG); // End of control for this tab periph_ctrl.cas.g->end(); @@ -804,10 +885,14 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) { // Create the Group item (the "Tab") periph_ctrl.bcr.g = new Fl_Group(10, MENU_HEIGHT+30, 500, 380-MENU_HEIGHT, " BCR "); + periph_ctrl.bcr.g->color(COLOR_BG); + periph_ctrl.bcr.g->selection_color(COLOR_TAB_INACTIVE_BG); + periph_ctrl.bcr.g->labelcolor(COLOR_TAB_INACTIVE_FG); // Create controls periph_ctrl.bcr.pText = new Fl_Box(120, MENU_HEIGHT+60, 60, 80, "BCR Port not supported yet"); + periph_ctrl.bcr.pText->labelcolor(COLOR_FG); // End of control for this tab periph_ctrl.bcr.g->end(); @@ -834,6 +919,9 @@ void cb_PeripheralDevices (Fl_Widget* w, void*) // Create a Tab for this printer pDev->pTab = new Fl_Group(10, MENU_HEIGHT+30, 500, 380-MENU_HEIGHT, pDev->pName); + pDev->pTab->color(COLOR_BG); + pDev->pTab->selection_color(COLOR_TAB_INACTIVE_BG); + pDev->pTab->labelcolor(COLOR_TAB_INACTIVE_FG); // Build th controls for this tab gLpt->BuildPrinterMonTab(c); @@ -981,20 +1069,20 @@ void T100_ComMon::AddByte(int rx_tx, char byte, char flags) fl_font(FL_COURIER_BOLD,gFontSize); // Determine xoffset of text - xpos = (int) (x() + m_LastCol * m_Width); + xpos = (int) (x() + m_LastCol * m_Width) + 5; // Determine color & yoffset of text if (b->entries[b->used].flags & 0x80) { // Byte is a TX byte - fl_color(FL_RED); + fl_color(gMidnight ? FL_LIGHT_RED : FL_RED); ypos = (int) (y() + (m_LastLine-m_FirstLine+1) * m_Height); } else { // Byte is an RX byte - fl_color(FL_BLUE); + fl_color(gMidnight ? FL_LIGHT_BLUE : FL_BLUE); ypos = (int) (y() + (m_LastLine-m_FirstLine+2) * m_Height); } @@ -1133,8 +1221,9 @@ void T100_ComMon::draw() } // Draw white background - fl_color(FL_WHITE); - fl_rectf(x(),y(),w(),h()); + fl_color(color()); + fl_rectf(x(),y(),w(),h()); + draw_box(); // Draw GRAY lines between every other line fl_color(FL_GRAY); @@ -1179,20 +1268,20 @@ void T100_ComMon::draw() } // Determine xoffset of text - xpos = (int) (x() + col * m_Width); + xpos = (int) (x() + col * m_Width)+5; // Determine color & yoffset of text if (clb->entries[index].flags & 0x80) { // Byte is a TX byte - fl_color(FL_RED); + fl_color(gMidnight ? FL_LIGHT_RED : FL_RED); ypos = (int) (y() + (line+1) * m_Height); } else { // Byte is an RX byte - fl_color(FL_BLUE); + fl_color(gMidnight ? FL_LIGHT_BLUE : FL_BLUE); ypos = (int) (y() + (line+2) * m_Height); } @@ -1221,12 +1310,12 @@ void T100_ComMon::draw() if (m_pStartTime == m_pStopTime) fl_color(FL_YELLOW); else - fl_color(FL_RED); + fl_color(gMidnight ? FL_LIGHT_RED : FL_RED); fl_rectf(xpos, ypos-(int)m_Height+3, (int) (adder * m_Width), (int) m_Height-1); if (m_pStartTime == m_pStopTime) - fl_color(FL_BLACK); + fl_color(labelcolor()); else - fl_color(FL_WHITE); + fl_color(color()); m_StopTimeLine = line + m_FirstLine; if ((clb->entries[index].flags & 0x80) == 0) m_StopTimeLine++; @@ -1296,7 +1385,7 @@ int T100_ComMon::handle(int event) if ((c == FL_LEFT_MOUSE) || (c == FL_RIGHT_MOUSE)) { // Get X,Y position of button press - xp = Fl::event_x(); + xp = Fl::event_x()-5; yp = Fl::event_y(); // Check if Shift was depressed during the Mouse Button event @@ -1417,7 +1506,7 @@ int T100_ComMon::handle(int event) if ((m_StopTimeLine >= m_FirstLine) && (m_StopTimeLine < m_FirstLine + m_Lines)) { - xpos = (int) (x() + m_StopTimeCol * m_Width); + xpos = (int) (x() + m_StopTimeCol * m_Width) + 5; ypos = (int) (y() + (m_StopTimeLine - m_FirstLine) * m_Height); prev_cle = m_pStopTime; line = m_StopTimeLine; @@ -1433,7 +1522,7 @@ int T100_ComMon::handle(int event) if ((m_StartTimeLine >= m_FirstLine) && (m_StartTimeLine < m_FirstLine + m_Lines)) { - xpos = (int) (x() + m_StartTimeCol * m_Width); + xpos = (int) (x() + m_StartTimeCol * m_Width) + 5; ypos = (int) (y() + (m_StartTimeLine - m_FirstLine) * m_Height); prev_cle = m_pStartTime; line = m_StartTimeLine; @@ -1448,13 +1537,13 @@ int T100_ComMon::handle(int event) if (prev_cle != NULL) { // Draw background - fl_color(FL_WHITE); + fl_color(color()); fl_rectf(xpos, ypos+3, (int) (adder * m_Width), (int) m_Height-1); if (line & 0x01) - fl_color(FL_BLUE); + fl_color(gMidnight ? FL_LIGHT_BLUE : FL_BLUE); else - fl_color(FL_RED); + fl_color(gMidnight ? FL_LIGHT_RED : FL_RED); // Draw the text if (gHexOn) @@ -1479,7 +1568,7 @@ int T100_ComMon::handle(int event) m_pStopTime = cle_sel; m_StopTimeLine = line_click + m_FirstLine; m_StopTimeCol = col; - fl_color(FL_RED); + fl_color(gMidnight ? FL_LIGHT_RED : FL_RED); } else { @@ -1496,7 +1585,7 @@ int T100_ComMon::handle(int event) { // Draw the Start selecton box fl_color(FL_GREEN); - xpos = (int) (x() + m_StartTimeCol * m_Width); + xpos = (int) (x() + m_StartTimeCol * m_Width) + 5; ypos = (int) (y() + (m_StartTimeLine - m_FirstLine) * m_Height); fl_rectf(xpos, ypos+3, (int) (adder * m_Width), (int) m_Height-1); @@ -1516,16 +1605,16 @@ int T100_ComMon::handle(int event) if (m_pStartTime == m_pStopTime) fl_color(FL_YELLOW); else - fl_color(FL_RED); - xpos = (int) (x() + m_StopTimeCol * m_Width); + fl_color(gMidnight ? FL_LIGHT_RED : FL_RED); + xpos = (int) (x() + m_StopTimeCol * m_Width) + 5; ypos = (int) (y() + (m_StopTimeLine - m_FirstLine) * m_Height); fl_rectf(xpos, ypos+3, (int) (adder * m_Width), (int) m_Height-1); // Draw the StartTime text if (m_pStartTime == m_pStopTime) - fl_color(FL_BLACK); + fl_color(labelcolor()); else - fl_color(FL_WHITE); + fl_color(color()); if (gHexOn) sprintf(string, "%02X", m_pStopTime->byte); else diff --git a/src/remote.cpp b/src/remote.cpp index a9b8318..1a6ee69 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -188,6 +188,7 @@ std::string cmd_help(ServerSocket& sock) sock << " radix [10 or 16]" << gLineTerm; sock << " read_mem(rm) address [count]" << gLineTerm; sock << " read_reg(rr) [all A B h m DE ...]" << gLineTerm; + sock << " read_rex" << gLineTerm; sock << " reset" << gLineTerm; sock << " run" << gLineTerm; sock << " screen_dump(sd)" << gLineTerm; @@ -1082,6 +1083,45 @@ std::string cmd_read_reg(ServerSocket& sock, std::string& args) return gOk; } +/* +======================================================= +Read rex command: Reads REX state and register contents +// added SA +======================================================= +*/ +std::string cmd_read_rex(ServerSocket& sock) +{ + std::string ret=""; + char rex1_str[300]; + char rex2_str[300]; + char rex3_str[300]; + + // Lock the global access object so the registers are stable + lock_remote(); + + if (gRadix == 10) + { + sprintf(rex1_str, "REX state=%d REX OPTROM register=%d", gRexState, gRexSector); + + sprintf(rex2_str, "REXC state=%d REXC OPTROM register=%d REXC LowRam register=%d REXC UpRam register=%d REXC WP= %d", + gRexCState, gRexCOSector, gRexCRLSector, gRexCRUSector, gRexCWP); + } + else + { + sprintf(rex1_str, "REX state=%02X REX OPTROM register=%02X", gRexState, gRexSector); + + sprintf(rex2_str, "REXC state=%02X REXC OPTROM register=%02X REXC LowRam register=%02X REXC UpRam register=%02X REXC WP= %02X", + gRexCState, gRexCOSector, gRexCRLSector, gRexCRUSector, gRexCWP); + } + + sprintf(rex3_str, "gReMem=%02X gRex=%02X readcounter=%02X keyvalue=%02X keyaddr=%02X ", + gReMem, gRex, readcounter, gRexCKey, gRexCKeyAddr); + + unlock_remote(); + + return rex1_str+ gLineTerm + rex2_str+ gLineTerm + rex3_str+ gLineTerm + gOk ; +} + /* ======================================================= Write reg command: Writes registers @@ -2133,7 +2173,7 @@ get_lcd_coords: Extracts row and column values from */ int get_lcd_coords(std::string& str, int& row, int& col) { - int pos, c; + unsigned int pos, c; // Ensure there is a '(' if (str[0] != '(') @@ -2141,11 +2181,11 @@ int get_lcd_coords(std::string& str, int& row, int& col) // Find the ',' pos = str.find(","); - if (pos == -1) + if (pos == std::string::npos) return 1; // Find the position of the col value - for (c = pos+1; c < (int) str.length(); c++) + for (c = pos+1; c < str.length(); c++) { if (str[c] != ' ') break; @@ -2834,13 +2874,13 @@ int telnet_command_ready(ServerSocket& sock, std::string &cmd, char* sockData, i /* Test for 0x0a command line terminaor */ if (ch == gTelnetCR) { - char temp[2]; cmd_term = TRUE; cmd = gTelnetCmd; gTelnetCmd = ""; +#ifdef WIN32 + char temp[2]; temp[0] = ch; temp[1] = 0; -#ifdef WIN32 sock << temp; temp[0] = 0x0A; sock << temp; @@ -2850,11 +2890,10 @@ int telnet_command_ready(ServerSocket& sock, std::string &cmd, char* sockData, i /* Test for 0x0D and ignore it */ if (ch == 0x0D) { +#ifdef WIN32 char temp[2]; temp[0] = ch; temp[1] = 0; - temp[1] = 0; -#ifdef WIN32 sock << temp; #endif continue; @@ -2996,6 +3035,9 @@ std::string process_command(ServerSocket& sock, char *sockdata, int len, else if ((cmd_word == "read_reg") || (cmd_word == "rr")) ret = cmd_read_reg(sock, args); + else if ((cmd_word == "read_rex") || (cmd_word == "rx")) + ret = cmd_read_rex(sock); + else if (cmd_word == "regs") { args = "all"; @@ -3121,7 +3163,7 @@ std::string process_command(ServerSocket& sock, char *sockdata, int len, gLastCmdDis = TRUE; return ret; } - else if (cmd_word.find('=') != -1) + else if (cmd_word.find('=') != std::string::npos) ret = cmd_write_reg(sock, cmd); gLastCmdDis = FALSE; @@ -3249,10 +3291,10 @@ Handles user input at the console */ void* console_control(void* pArg) { - static char cmdLine[256]; - static int cmdLen = 0; - static int cmdReady = 0; - std::string ret; + static char cmdLine[256]; + static unsigned int cmdLen = 0; + static int cmdReady = 0; + std::string ret; // Check if no-GUI mode enabled send_telnet_greeting(gConsole, TRUE); @@ -3717,10 +3759,10 @@ Handles user input at the console */ void remote_process_console_input(void) { - int ch; - static char cmdLine[256]; - static char cmdLen = 0; - std::string ret; + int ch; + static char cmdLine[256]; + static unsigned int cmdLen = 0; + std::string ret; // Get the character from the console while (1) @@ -3775,7 +3817,8 @@ void remote_process_console_input(void) cmdLen = 0; return; } - } } +// vim: noet sw=4 ts=4 + diff --git a/src/setup.cpp b/src/setup.cpp index 1bf3a78..1348fb9 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -25,9 +25,21 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * changes by S. Adolph to enable REX#, REXCPM + * new items: + * mem_ctrl.pRexS, cb_radio_rexs, SETUP_MEM_REXS + * mem_ctrl.pRexC, cb_radio_rexc, SETUP_MEM_REXC + * mem_ctrl.pRexCRamFile, mem_setup.rexc_ram_file + * mem_ctrl.pRexCRamBrowse, cb_rexc_browse + * + * issues: + * - how to set up REXCPM memory? load_rex_flash() load_rexc_ram(); save_rexc_ram(); + * - might want to make a callback for create default REX# flash + * fix call to load_rexc and save_rexc + * - memory options not filtering correctly with different model types */ - #include #include #include @@ -54,8 +66,15 @@ #include "file.h" extern Fl_Preferences virtualt_prefs; +extern int gMidnight; void init_menus(void); +#define COLOR_BG (gMidnight ? FL_BLACK : fl_rgb_color(192, 192, 192)) +#define COLOR_BG_INPUT (gMidnight ? FL_BLACK : FL_WHITE) +#define COLOR_FG (gMidnight ? FL_WHITE : FL_BLACK) +#define COLOR_TAB_INACTIVE_BG (gMidnight ? fl_rgb_color(32,32,32) : fl_rgb_color(192,192,192)) +#define COLOR_TAB_INACTIVE_FG (gMidnight ? fl_rgb_color(192,192,192) : FL_BLACK) + extern "C" { void enable_tpdd_log_menu(int bEnabled); @@ -130,6 +149,8 @@ typedef struct memory_ctrl_struct Fl_Round_Button* pReMem_Rampac; Fl_Round_Button* pRex; Fl_Round_Button* pRex2; + Fl_Round_Button* pRexS; // added SA + Fl_Round_Button* pRexC; // added SA Fl_Check_Button* pReMemOverride; Fl_Round_Button* pQuad; Fl_Round_Button* pRexQuad; @@ -137,11 +158,13 @@ typedef struct memory_ctrl_struct Fl_Input* pRampacFile; Fl_Input* pRexFlashFile; Fl_Input* pRex2RamFile; + Fl_Input* pRexCRamFile; // added SA Fl_Button* pRexCreateFlash; Fl_Button* pReMemBrowse; Fl_Button* pRampacBrowse; Fl_Button* pRexFlashBrowse; Fl_Button* pRex2RamBrowse; + Fl_Button* pRexCRamBrowse; // added SA Fl_Box* pReMemText; Fl_Check_Button* pOptRomRW; Fl_Check_Button* pShowVersion; @@ -507,63 +530,72 @@ void cb_PeripheralSetup (Fl_Widget* w, void*) // Create Peripheral Setup window gpsw = new Fl_Window(350, 300, "Peripheral Setup"); gpsw->callback(cb_setupwin); + gpsw->color(COLOR_BG); // Create Peripheral Tabs { setup_ctrl.pTabs = new Fl_Tabs(10, 10, 330, 240); + setup_ctrl.pTabs->color(COLOR_BG); + setup_ctrl.pTabs->selection_color(COLOR_BG); + setup_ctrl.pTabs->labelcolor(COLOR_FG); // COM port Tab { setup_ctrl.com.g = new Fl_Group(10, 30, 350, 260, " COM "); + setup_ctrl.com.g->color(COLOR_BG); + setup_ctrl.com.g->selection_color(COLOR_TAB_INACTIVE_BG); + setup_ctrl.com.g->labelcolor(COLOR_TAB_INACTIVE_FG); // Create items on the Tab setup_ctrl.com.pNone = new Fl_Round_Button(20, 40, 180, 20, "No emulation"); setup_ctrl.com.pNone->type(FL_RADIO_BUTTON); setup_ctrl.com.pNone->callback(cb_com_radio_none); + setup_ctrl.com.pNone->labelcolor(COLOR_FG); // Create controls to select simulated TPDD client connection setup_ctrl.com.pSim = new Fl_Round_Button(20, 65, 220, 20, "Connect to simulated NADSBox"); setup_ctrl.com.pSim->type(FL_RADIO_BUTTON); setup_ctrl.com.pSim->callback(cb_com_radio_sim_tpdd); + setup_ctrl.com.pSim->labelcolor(COLOR_FG); setup_ctrl.com.pTpddConfig = new Fl_Button(50, 90, 80, 20, "Configure"); if (setup.com_mode != SETUP_COM_SIM_TPDD) setup_ctrl.com.pTpddConfig->deactivate(); setup_ctrl.com.pTpddConfig->callback(cb_com_sim_tpdd_config); + setup_ctrl.com.pTpddConfig->color(COLOR_BG); + setup_ctrl.com.pTpddConfig->labelcolor(COLOR_FG); setup_ctrl.com.pCmd = NULL; -#if 0 - // Old simulation file controls... - setup_ctrl.com.pSim = new Fl_Round_Button(20, 65, 180, 20, "Use Simulated Port (not supported yet)"); - setup_ctrl.com.pSim->type(FL_RADIO_BUTTON); - setup_ctrl.com.pSim->callback(cb_com_radio_sim); - - setup_ctrl.com.pCmd = new Fl_Input(105, 90, 200, 20, "Cmd File:"); - if (setup.com_mode != SETUP_COM_SIMULATED) - setup_ctrl.com.pCmd->deactivate(); - setup_ctrl.com.pCmd->value(setup.com_cmd); -#endif setup_ctrl.com.pHost = new Fl_Round_Button(20, 115, 180, 20, "Use Host Port"); setup_ctrl.com.pHost->type(FL_RADIO_BUTTON); setup_ctrl.com.pHost->callback(cb_com_radio_host); + setup_ctrl.com.pHost->labelcolor(COLOR_FG); setup_ctrl.com.pPort = new Fl_Choice(50, 137, 240, 20, ""); + setup_ctrl.com.pPort->color(COLOR_BG); + setup_ctrl.com.pPort->labelcolor(COLOR_FG); + setup_ctrl.com.pPort->textcolor(COLOR_FG); if (setup.com_mode != SETUP_COM_HOST) setup_ctrl.com.pPort->deactivate(); setup_ctrl.com.pOther = new Fl_Round_Button(20, 165, 180, 20, "Other Host Port"); setup_ctrl.com.pOther->type(FL_RADIO_BUTTON); setup_ctrl.com.pOther->callback(cb_com_radio_other); + setup_ctrl.com.pOther->labelcolor(COLOR_FG); setup_ctrl.com.pOtherName = new Fl_Input(50, 185, 240, 20, ""); if (setup.com_mode != SETUP_COM_OTHER) setup_ctrl.com.pOtherName->deactivate(); setup_ctrl.com.pOtherName->value(setup.com_other); + setup_ctrl.com.pOtherName->color(COLOR_BG); + setup_ctrl.com.pOtherName->textcolor(COLOR_FG); + setup_ctrl.com.pOtherName->cursor_color(COLOR_FG); + setup_ctrl.com.pOtherName->labelcolor(COLOR_FG); setup_ctrl.com.pIgnoreFlow = new Fl_Check_Button(20, 210, 180, 20, "Ignore Flow Control"); setup_ctrl.com.pIgnoreFlow->value(setup.com_ignore_flow); - + setup_ctrl.com.pIgnoreFlow->labelcolor(COLOR_FG); // Get list of COM ports on the host ser_get_port_list(com_port_list, 256, &count); @@ -597,9 +629,11 @@ void cb_PeripheralSetup (Fl_Widget* w, void*) { // Create the Group item (the "Tab") setup_ctrl.lpt.g = new Fl_Group(10, 30, 350, 260, " LPT "); + setup_ctrl.lpt.g->color(COLOR_BG); + setup_ctrl.lpt.g->selection_color(COLOR_TAB_INACTIVE_BG); + setup_ctrl.lpt.g->labelcolor(COLOR_TAB_INACTIVE_FG); // Create controls -// setup_ctrl.lpt.pText = new Fl_Box(120, 60, 60, 80, "Parallel Port not supported yet"); build_lpt_setup_tab(); // End of control for this tab @@ -610,9 +644,13 @@ void cb_PeripheralSetup (Fl_Widget* w, void*) { // Create the Group item (the "Tab") setup_ctrl.mdm.g = new Fl_Group(10, 30, 350, 260, " MDM "); + setup_ctrl.mdm.g->color(COLOR_BG); + setup_ctrl.mdm.g->selection_color(COLOR_TAB_INACTIVE_BG); + setup_ctrl.mdm.g->labelcolor(COLOR_TAB_INACTIVE_FG); // Create controls setup_ctrl.mdm.pText = new Fl_Box(120, 60, 60, 80, "Modem Port not supported yet"); + setup_ctrl.mdm.pText->labelcolor(COLOR_FG); // End of control for this tab setup_ctrl.mdm.g->end(); @@ -622,34 +660,30 @@ void cb_PeripheralSetup (Fl_Widget* w, void*) { // Create the Group item (the "Tab") setup_ctrl.cas.g = new Fl_Group(10, 30, 300, 260, " CAS "); + setup_ctrl.cas.g->color(COLOR_BG); + setup_ctrl.cas.g->selection_color(COLOR_TAB_INACTIVE_BG); + setup_ctrl.cas.g->labelcolor(COLOR_TAB_INACTIVE_FG); // Create controls setup_ctrl.cas.pText = new Fl_Box(120, 60, 60, 80, "Cassette Port not supported yet"); + setup_ctrl.cas.pText->labelcolor(COLOR_FG); // End of control for this tab setup_ctrl.cas.g->end(); } - // BCR Port Tab - { - // Create the Group item (the "Tab") -// setup_ctrl.bcr.g = new Fl_Group(10, 30, 300, 260, " BCR "); - - // Create controls -// setup_ctrl.bcr.pText = new Fl_Box(120, 60, 60, 80, "BCR Port not supported yet"); - - // End of control for this tab -// setup_ctrl.bcr.g->end(); - } - // Sound Port Tab { // Create the Group item (the "Tab") setup_ctrl.sound.g = new Fl_Group(10, 30, 300, 260, " Sound "); + setup_ctrl.sound.g->color(COLOR_BG); + setup_ctrl.sound.g->selection_color(COLOR_TAB_INACTIVE_BG); + setup_ctrl.sound.g->labelcolor(COLOR_TAB_INACTIVE_FG); // Create controls setup_ctrl.sound.pEnable = new Fl_Check_Button(20, 40, 180, 20, "Enable Sound"); setup_ctrl.sound.pEnable->value(setup.sound_enable); + setup_ctrl.sound.pEnable->labelcolor(COLOR_FG); // Create a tone control slider //Fl_Box* b = new Fl_Box(20, 80, 100, 20, "Tone Control"); @@ -662,11 +696,6 @@ void cb_PeripheralSetup (Fl_Widget* w, void*) double tone = sound_get_tone_control(); setup_ctrl.sound.pTone->value(tone); setup_ctrl.sound.pTone->hide(); -// setup_ctrl.sound.pTone->step(1); - - // Create text to describe tone control - //b = new Fl_Box(130, 100, 50, 20, "Agressive"); - //b = new Fl_Box(280, 100, 50, 20, "Soft"); // End of control for this tab setup_ctrl.sound.g->end(); @@ -676,6 +705,9 @@ void cb_PeripheralSetup (Fl_Widget* w, void*) { // Create the Group item (the "Tab") setup_ctrl.clock.g = new Fl_Group(10, 30, 350, 260, " Clock "); + setup_ctrl.clock.g->color(COLOR_BG); + setup_ctrl.clock.g->selection_color(COLOR_TAB_INACTIVE_BG); + setup_ctrl.clock.g->labelcolor(COLOR_TAB_INACTIVE_FG); // Create controls build_clock_setup_tab(); @@ -692,9 +724,13 @@ void cb_PeripheralSetup (Fl_Widget* w, void*) // OK button { Fl_Button* o = new Fl_Button(180, 260, 60, 30, "Cancel"); o->callback((Fl_Callback*)cb_setup_cancel); + o->color(COLOR_BG); + o->labelcolor(COLOR_FG); } { Fl_Return_Button* o = new Fl_Return_Button(250, 260, 60, 30, "OK"); o->callback((Fl_Callback*)cb_setup_OK); + o->color(COLOR_BG); + o->labelcolor(COLOR_FG); } gpsw->show(); @@ -772,6 +808,11 @@ void save_memory_preferences(void) strcat(pref, "_Rex2RamFile"); virtualt_prefs.set(pref, mem_setup.rex2_ram_file); + // new, added by SA + strcpy(pref, str); + strcat(pref, "_RexCRamFile"); + virtualt_prefs.set(pref, mem_setup.rexc_ram_file); + strcpy(pref, str); strcat(pref, "_OptRomRW"); virtualt_prefs.set(pref, gOptRomRW); @@ -848,6 +889,16 @@ void load_memory_preferences(void) if (strlen(mem_setup.rex2_ram_file) == 0) strcpy(mem_setup.rex2_ram_file, path); +// // Load REXCPM Ram filename based on Model +// // new added by SA + strcpy(pref, str); + strcat(pref, "_RexCRamFile"); + get_emulation_path(path, gModel); + strcat(path, "rexcpm_ram_4M.bin"); + virtualt_prefs.get(pref, mem_setup.rexc_ram_file, path, 256); + if (strlen(mem_setup.rexc_ram_file) == 0) + strcpy(mem_setup.rexc_ram_file, path); + // Load OptRom R/W or R/O option strcpy(pref, str); strcat(pref, "_OptRomRW"); @@ -910,9 +961,10 @@ void cb_memory_OK(Fl_Widget* w, void*) /* =================================================== Check if Rex Flash needs to be saved / deallocated + --> modified to include REX# =================================================== */ - if ((mem_setup.mem_mode == SETUP_MEM_REX) || (mem_setup.mem_mode == SETUP_MEM_REX2)) + if ((mem_setup.mem_mode == SETUP_MEM_REX) || (mem_setup.mem_mode == SETUP_MEM_REX2) || (mem_setup.mem_mode == SETUP_MEM_REXS)) { // Save Rex Flash save_rex_flash(); // Write Rex flash memory to file @@ -929,11 +981,23 @@ void cb_memory_OK(Fl_Widget* w, void*) save_rex2_ram(); // Write Rex RAM memory to file } + /* + =================================================== + Check if REXCPM RAM needs to be saved / deallocated + =================================================== + */ + if (mem_setup.mem_mode == SETUP_MEM_REXC) + { + // Save REXCPM RAM + save_rexc_ram(); // Write REXCPM RAM memory to file + } + // Save old mem_mode so we know when to load data from file old_mode = mem_setup.mem_mode; // =========================== // Get memory options + // --> modified by SA to support REX# and REXCPM // =========================== if (mem_ctrl.pNone->value() == 1) mem_setup.mem_mode = SETUP_MEM_BASE; @@ -947,6 +1011,10 @@ void cb_memory_OK(Fl_Widget* w, void*) mem_setup.mem_mode = SETUP_MEM_REX; else if (mem_ctrl.pRex2->value() == 1) mem_setup.mem_mode = SETUP_MEM_REX2; + else if (mem_ctrl.pRexS->value() == 1) + mem_setup.mem_mode = SETUP_MEM_REXS; // new SA + else if (mem_ctrl.pRexC->value() == 1) + mem_setup.mem_mode = SETUP_MEM_REXC; // new SA else if (mem_ctrl.pQuad->value() == 1) mem_setup.mem_mode = SETUP_MEM_QUAD; else if (mem_ctrl.pRexQuad->value() == 1) @@ -971,12 +1039,16 @@ void cb_memory_OK(Fl_Widget* w, void*) /* =================================================== Load Base memory if needed + --> modified to support REX# and REXCPM =================================================== */ if ((mem_setup.mem_mode == SETUP_MEM_RAMPAC) || (mem_setup.mem_mode == SETUP_MEM_BASE) || (mem_setup.mem_mode == SETUP_MEM_REX) || (mem_setup.mem_mode == SETUP_MEM_QUAD) || - (mem_setup.mem_mode == SETUP_MEM_REX_QUAD)) - load_ram(); + (mem_setup.mem_mode == SETUP_MEM_REX_QUAD) || (mem_setup.mem_mode == SETUP_MEM_REXC) || + (mem_setup.mem_mode == SETUP_MEM_REXS) ) + { + load_ram(); + } // If we are in ReMem or ReMem_Rampac mode, check if ReMem filename changed if ((mem_setup.mem_mode == SETUP_MEM_REMEM) || (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC)) @@ -1023,7 +1095,8 @@ void cb_memory_OK(Fl_Widget* w, void*) } // If we are in Rex or Rex2 mode, check if Rex Flash filename changed - if ((mem_setup.mem_mode == SETUP_MEM_REX) || (mem_setup.mem_mode == SETUP_MEM_REX2)) + // extended to REX# + if ((mem_setup.mem_mode == SETUP_MEM_REX) || (mem_setup.mem_mode == SETUP_MEM_REX2) || (mem_setup.mem_mode == SETUP_MEM_REXS)) { // Check if we are changing Rampac filename if (strcmp(mem_ctrl.pRexFlashFile->value(), mem_setup.rex_flash_file) != 0) @@ -1037,14 +1110,14 @@ void cb_memory_OK(Fl_Widget* w, void*) // Load Rampac data from new file load_rex_flash(); } - else if ((old_mode != SETUP_MEM_REX) && (old_mode != SETUP_MEM_REX2)) + else if ((old_mode != SETUP_MEM_REX) && (old_mode != SETUP_MEM_REX2) && (old_mode != SETUP_MEM_REXS) ) { // Load Rampac data from file load_rex_flash(); } } - // If we are in Rex or Rex2 mode, check if Rex Flash filename changed + // If we are in Rex2 mode, check if Rex2 ram filename changed if (mem_setup.mem_mode == SETUP_MEM_REX2) { // Check if we are changing Rampac filename @@ -1066,11 +1139,36 @@ void cb_memory_OK(Fl_Widget* w, void*) } } + // If we are in REXCPM mode, check if REXCPM ram filename changed + // added by SA + if (mem_setup.mem_mode == SETUP_MEM_REXC) + { + // Check if we are changing RAM filename + if (strcmp(mem_ctrl.pRexCRamFile->value(), mem_setup.rexc_ram_file) != 0) + { + // Save memory to old file + save_rexc_ram(); + + // Copy new filename to preferences + strcpy(mem_setup.rexc_ram_file, mem_ctrl.pRexCRamFile->value()); + + // Load REXC RAM data from new file + load_rexc_ram(); + } + else if (old_mode != SETUP_MEM_REXC) + { + // Load Rampac data from file + load_rexc_ram(); + } + } + // Copy new ReMem filename and Rampac filename to preferences strcpy(mem_setup.remem_file, mem_ctrl.pReMemFile->value()); strcpy(mem_setup.rampac_file, mem_ctrl.pRampacFile->value()); strcpy(mem_setup.rex_flash_file, mem_ctrl.pRexFlashFile->value()); strcpy(mem_setup.rex2_ram_file, mem_ctrl.pRex2RamFile->value()); + // added SA + strcpy(mem_setup.rexc_ram_file, mem_ctrl.pRexCRamFile->value()); // Save memory preferences to file save_memory_preferences(); @@ -1099,7 +1197,6 @@ void cb_remem_browse(Fl_Widget* w, void*) Flu_File_Chooser *fc; const char *filename; const char *filename_name; - int len; char mstr[16]; char mstr_upper[16]; char path[256]; @@ -1131,7 +1228,6 @@ void cb_remem_browse(Fl_Widget* w, void*) delete fc; return; } - len = strlen(filename); // Copy filename to edit field filename_name = fl_filename_name(filename); @@ -1158,7 +1254,6 @@ void cb_rex_browse(Fl_Widget* w, void*) Flu_File_Chooser *fc; const char *filename; const char *filename_name; - int len; char mstr[16]; char mstr_upper[16]; char path[256]; @@ -1190,7 +1285,6 @@ void cb_rex_browse(Fl_Widget* w, void*) delete fc; return; } - len = strlen(filename); // Copy filename to edit field filename_name = fl_filename_name(filename); @@ -1217,7 +1311,6 @@ void cb_rex2_browse(Fl_Widget* w, void*) Flu_File_Chooser *fc; const char *filename; const char *filename_name; - int len; char mstr[16]; char mstr_upper[16]; char path[256]; @@ -1249,7 +1342,6 @@ void cb_rex2_browse(Fl_Widget* w, void*) delete fc; return; } - len = strlen(filename); // Copy filename to edit field filename_name = fl_filename_name(filename); @@ -1270,6 +1362,66 @@ void cb_rex2_browse(Fl_Widget* w, void*) delete fc; } + +// added to support REXCPM + +void cb_rexc_browse(Fl_Widget* w, void*) +{ + int count; + Flu_File_Chooser *fc; + const char *filename; + const char *filename_name; + char mstr[16]; + char mstr_upper[16]; + char path[256]; + int c; + + // Create chooser window to pick file + strcpy(path, mem_ctrl.pRexCRamFile->value()); + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser(path,"Binary Files (*.bin)",2,"Choose REXCPM RAM File"); + fl_cursor(FL_CURSOR_DEFAULT); + fc->preview(0); + fc->show(); + + // Show Chooser window + while (fc->visible()) + Fl::wait(); + + count = fc->count(); + if (count == 0) + { + delete fc; + return; + } + + // Get Filename + filename = fc->value(1); + if (filename == 0) + { + delete fc; + return; + } + + // Copy filename to edit field + filename_name = fl_filename_name(filename); + + get_model_string(mstr, gModel); + strcpy(mstr_upper, mstr); + for (c = strlen(mstr_upper)-1; c >= 0; c--) + mstr_upper[c] = toupper(mstr_upper[c]); + if (strstr(filename, mstr) || strstr(filename, mstr_upper)) + { + get_emulation_path(path, gModel); + strcat(path, filename_name); + mem_ctrl.pRexCRamFile->value(path); + } + else + mem_ctrl.pRexCRamFile->value(filename); + + delete fc; +} + void cb_radio_base_memory (Fl_Widget* w, void*) { mem_ctrl.pRampacFile->deactivate(); @@ -1283,6 +1435,8 @@ void cb_radio_base_memory (Fl_Widget* w, void*) mem_ctrl.pRex2RamFile->deactivate(); mem_ctrl.pRex2RamBrowse->deactivate(); mem_ctrl.pRexCreateFlash->deactivate(); + mem_ctrl.pRexCRamFile->deactivate(); //added SA + mem_ctrl.pRexCRamBrowse->deactivate(); //added SA } void cb_radio_remem (Fl_Widget* w, void*) @@ -1298,6 +1452,8 @@ void cb_radio_remem (Fl_Widget* w, void*) mem_ctrl.pRex2RamFile->deactivate(); mem_ctrl.pRex2RamBrowse->deactivate(); mem_ctrl.pRexCreateFlash->deactivate(); + mem_ctrl.pRexCRamFile->deactivate(); //added SA + mem_ctrl.pRexCRamBrowse->deactivate(); //added SA } void cb_radio_rampac (Fl_Widget* w, void*) @@ -1313,6 +1469,8 @@ void cb_radio_rampac (Fl_Widget* w, void*) mem_ctrl.pRex2RamFile->deactivate(); mem_ctrl.pRex2RamBrowse->deactivate(); mem_ctrl.pRexCreateFlash->deactivate(); + mem_ctrl.pRexCRamFile->deactivate(); //added SA + mem_ctrl.pRexCRamBrowse->deactivate(); //added SA } void cb_radio_remem_and_rampac (Fl_Widget* w, void*) @@ -1328,6 +1486,8 @@ void cb_radio_remem_and_rampac (Fl_Widget* w, void*) mem_ctrl.pRex2RamFile->deactivate(); mem_ctrl.pRex2RamBrowse->deactivate(); mem_ctrl.pRexCreateFlash->deactivate(); + mem_ctrl.pRexCRamFile->deactivate(); //added SA + mem_ctrl.pRexCRamBrowse->deactivate(); //added SA } void cb_radio_rex (Fl_Widget* w, void*) @@ -1343,6 +1503,8 @@ void cb_radio_rex (Fl_Widget* w, void*) mem_ctrl.pRex2RamFile->deactivate(); mem_ctrl.pRex2RamBrowse->deactivate(); mem_ctrl.pRexCreateFlash->activate(); + mem_ctrl.pRexCRamFile->deactivate(); //added SA + mem_ctrl.pRexCRamBrowse->deactivate(); //added SA } void cb_radio_rex2 (Fl_Widget* w, void*) @@ -1358,6 +1520,44 @@ void cb_radio_rex2 (Fl_Widget* w, void*) mem_ctrl.pRex2RamFile->activate(); mem_ctrl.pRex2RamBrowse->activate(); mem_ctrl.pRexCreateFlash->activate(); + mem_ctrl.pRexCRamFile->deactivate(); //added SA + mem_ctrl.pRexCRamBrowse->deactivate(); //added SA +} + +// new entry added by SA for REX# +void cb_radio_rexs (Fl_Widget* w, void*) +{ + mem_ctrl.pRampacFile->deactivate(); + mem_ctrl.pRampacBrowse->deactivate(); + mem_ctrl.pReMemOverride->deactivate(); + mem_ctrl.pReMemFile->deactivate(); + mem_ctrl.pReMemBrowse->deactivate(); + mem_ctrl.pReMemText->hide(); + mem_ctrl.pRexFlashFile->activate(); + mem_ctrl.pRexFlashBrowse->activate(); + mem_ctrl.pRex2RamFile->deactivate(); + mem_ctrl.pRex2RamBrowse->deactivate(); + mem_ctrl.pRexCreateFlash->deactivate(); + mem_ctrl.pRexCRamFile->deactivate(); //added SA + mem_ctrl.pRexCRamBrowse->deactivate(); //added SA +} + +// new entry added by SA for REXCPM +void cb_radio_rexc (Fl_Widget* w, void*) +{ + mem_ctrl.pRampacFile->deactivate(); + mem_ctrl.pRampacBrowse->deactivate(); + mem_ctrl.pReMemOverride->deactivate(); + mem_ctrl.pReMemFile->deactivate(); + mem_ctrl.pReMemBrowse->deactivate(); + mem_ctrl.pReMemText->hide(); + mem_ctrl.pRexFlashFile->deactivate(); + mem_ctrl.pRexFlashBrowse->deactivate(); + mem_ctrl.pRex2RamFile->deactivate(); + mem_ctrl.pRex2RamBrowse->deactivate(); + mem_ctrl.pRexCreateFlash->deactivate(); + mem_ctrl.pRexCRamFile->activate(); //added SA + mem_ctrl.pRexCRamBrowse->activate(); //added SA } void cb_radio_quad (Fl_Widget* w, void*) @@ -1373,6 +1573,8 @@ void cb_radio_quad (Fl_Widget* w, void*) mem_ctrl.pRex2RamFile->deactivate(); mem_ctrl.pRex2RamBrowse->deactivate(); mem_ctrl.pRexCreateFlash->deactivate(); + mem_ctrl.pRexCRamFile->deactivate(); //added SA + mem_ctrl.pRexCRamBrowse->deactivate(); //added SA } void cb_radio_rex_quad (Fl_Widget* w, void*) @@ -1388,6 +1590,8 @@ void cb_radio_rex_quad (Fl_Widget* w, void*) mem_ctrl.pRex2RamFile->deactivate(); mem_ctrl.pRex2RamBrowse->deactivate(); mem_ctrl.pRexCreateFlash->activate(); + mem_ctrl.pRexCRamFile->deactivate(); //added SA + mem_ctrl.pRexCRamBrowse->deactivate(); //added SA } void cb_memory_cancel (Fl_Widget* w, void*) @@ -1399,10 +1603,9 @@ void cb_memory_cancel (Fl_Widget* w, void*) void cb_rampac_browse (Fl_Widget* w, void*) { int count; - Flu_File_Chooser *fc; + Flu_File_Chooser *fc; const char *filename; const char *filename_name; - int len; char mstr[16]; char mstr_upper[16]; char path[256]; @@ -1434,7 +1637,6 @@ void cb_rampac_browse (Fl_Widget* w, void*) delete fc; return; } - len = strlen(filename); // Copy filename to edit field filename_name = fl_filename_name(filename); @@ -1542,19 +1744,23 @@ Routine to create the PeripheralSetup Window and tabs void cb_MemorySetup (Fl_Widget* w, void*) { // Create Peripheral Setup window - gmsw = new Fl_Window(520, 465, "Memory Emulation Options"); + //gmsw = new Fl_Window(560, 560, "Memory Emulation Options"); + gmsw = new Fl_Window(520, 560, "Memory Emulation Options"); gmsw->callback(cb_memorywin); + gmsw->color(COLOR_BG); // Create items on the Tab mem_ctrl.pNone = new Fl_Round_Button(20, 20, 120, 20, "Base Memory"); mem_ctrl.pNone->type(FL_RADIO_BUTTON); mem_ctrl.pNone->callback(cb_radio_base_memory); + mem_ctrl.pNone->labelcolor(COLOR_FG); if (mem_setup.mem_mode == SETUP_MEM_BASE) mem_ctrl.pNone->value(1); // Create list box for the amount of installed memory mem_ctrl.pMemInstalled = new Fl_Choice(280, 20, 60, 20, "Memory Installed:"); mem_ctrl.pMemInstalled->align(FL_ALIGN_LEFT); + mem_ctrl.pMemInstalled->labelcolor(COLOR_FG); if (gModel == MODEL_T200) { mem_ctrl.pMemInstalled->add("72K"); @@ -1579,22 +1785,26 @@ void cb_MemorySetup (Fl_Widget* w, void*) mem_ctrl.pRampac = new Fl_Round_Button(20, 45, 180, 20, "RamPac (256K RAM)"); mem_ctrl.pRampac->type(FL_RADIO_BUTTON); mem_ctrl.pRampac->callback(cb_radio_rampac); + mem_ctrl.pRampac->labelcolor(COLOR_FG); if (mem_setup.mem_mode == SETUP_MEM_RAMPAC) mem_ctrl.pRampac->value(1); mem_ctrl.pReMem = new Fl_Round_Button(20, 70, 220, 20, "ReMem (2M RAM, 4M FLASH)"); mem_ctrl.pReMem->type(FL_RADIO_BUTTON); mem_ctrl.pReMem->callback(cb_radio_remem); + mem_ctrl.pReMem->labelcolor(COLOR_FG); if (mem_setup.mem_mode == SETUP_MEM_REMEM) mem_ctrl.pReMem->value(1); mem_ctrl.pReMem_Rampac = new Fl_Round_Button(20, 95, 180, 20, "ReMem + RamPac"); mem_ctrl.pReMem_Rampac->type(FL_RADIO_BUTTON); mem_ctrl.pReMem_Rampac->callback(cb_radio_remem_and_rampac); + mem_ctrl.pReMem_Rampac->labelcolor(COLOR_FG); if (mem_setup.mem_mode == SETUP_MEM_REMEM_RAMPAC) mem_ctrl.pReMem_Rampac->value(1); mem_ctrl.pReMemOverride = new Fl_Check_Button(210, 95, 210, 20, "ReMem overrides Rampac"); + mem_ctrl.pReMemOverride->labelcolor(COLOR_FG); if (mem_setup.remem_override) mem_ctrl.pReMemOverride->value(1); if (mem_setup.mem_mode != SETUP_MEM_REMEM_RAMPAC) @@ -1605,9 +1815,15 @@ void cb_MemorySetup (Fl_Widget* w, void*) // =============================================== mem_ctrl.pRampacFile = new Fl_Input(105, 130, 310, 20, "RamPac File"); mem_ctrl.pRampacFile->value(mem_setup.rampac_file); + mem_ctrl.pRampacFile->color(COLOR_BG_INPUT); + mem_ctrl.pRampacFile->labelcolor(COLOR_FG); + mem_ctrl.pRampacFile->textcolor(COLOR_FG); + mem_ctrl.pRampacFile->cursor_color(COLOR_FG); mem_ctrl.pRampacBrowse = new Fl_Button(430, 125, 60, 30, "Browse"); mem_ctrl.pRampacBrowse->callback((Fl_Callback*)cb_rampac_browse); + mem_ctrl.pRampacBrowse->color(COLOR_BG); + mem_ctrl.pRampacBrowse->labelcolor(COLOR_FG); if ((mem_setup.mem_mode != SETUP_MEM_RAMPAC) && (mem_setup.mem_mode != SETUP_MEM_REMEM_RAMPAC)) { @@ -1620,11 +1836,18 @@ void cb_MemorySetup (Fl_Widget* w, void*) // =============================================== mem_ctrl.pReMemFile = new Fl_Input(105, 170, 310, 20, "ReMem File"); mem_ctrl.pReMemFile->value(mem_setup.remem_file); + mem_ctrl.pReMemFile->color(COLOR_BG_INPUT); + mem_ctrl.pReMemFile->labelcolor(COLOR_FG); + mem_ctrl.pReMemFile->textcolor(COLOR_FG); + mem_ctrl.pReMemFile->cursor_color(COLOR_FG); mem_ctrl.pReMemText = new Fl_Box(45, 190, 325, 20, "(Use Memory Editor to load FLASH)"); mem_ctrl.pReMemText->labelsize(12); + mem_ctrl.pReMemText->labelcolor(COLOR_FG); mem_ctrl.pReMemBrowse = new Fl_Button(430, 165, 60, 30, "Browse"); mem_ctrl.pReMemBrowse->callback((Fl_Callback*)cb_remem_browse); + mem_ctrl.pReMemBrowse->color(COLOR_BG); + mem_ctrl.pReMemBrowse->labelcolor(COLOR_FG); if ((mem_setup.mem_mode != SETUP_MEM_REMEM) && (mem_setup.mem_mode != SETUP_MEM_REMEM_RAMPAC)) { @@ -1633,11 +1856,11 @@ void cb_MemorySetup (Fl_Widget* w, void*) mem_ctrl.pReMemText->hide(); } - // Add radio button for QUAD mem_ctrl.pQuad = new Fl_Round_Button(20, 210, 270, 20, "QUAD (128K Banked RAM)"); mem_ctrl.pQuad->type(FL_RADIO_BUTTON); mem_ctrl.pQuad->callback(cb_radio_quad); + mem_ctrl.pQuad->labelcolor(COLOR_FG); if (mem_setup.mem_mode == SETUP_MEM_QUAD) mem_ctrl.pQuad->value(1); @@ -1645,45 +1868,85 @@ void cb_MemorySetup (Fl_Widget* w, void*) mem_ctrl.pRexQuad = new Fl_Round_Button(20, 235, 270, 20, "QUAD + REX"); mem_ctrl.pRexQuad->type(FL_RADIO_BUTTON); mem_ctrl.pRexQuad->callback(cb_radio_rex_quad); + mem_ctrl.pRexQuad->labelcolor(COLOR_FG); if (mem_setup.mem_mode == SETUP_MEM_REX_QUAD) mem_ctrl.pRexQuad->value(1); + // QUAD filter if (gModel != MODEL_M100) { mem_ctrl.pQuad->deactivate(); mem_ctrl.pRexQuad->deactivate(); } - + + // added SA, REXCPM filter + if ((gModel != MODEL_M100) && (gModel != MODEL_M102) ) + { + if (mem_ctrl.pRexC) + mem_ctrl.pRexC->deactivate(); + } + + // added SA, REX# filter + if ( (gModel != MODEL_M100) && (gModel != MODEL_M102) && (gModel != MODEL_T200) ) + { + if (mem_ctrl.pRexS) + mem_ctrl.pRexS->deactivate(); + } + // Create Rex radio button - mem_ctrl.pRex = new Fl_Round_Button(20, 260, 270, 20, "Rex (1M Flash Option ROM)"); + mem_ctrl.pRex = new Fl_Round_Button(20, 260, 270, 20, "REX (1M Flash Option ROM)"); mem_ctrl.pRex->type(FL_RADIO_BUTTON); mem_ctrl.pRex->callback(cb_radio_rex); + mem_ctrl.pRex->labelcolor(COLOR_FG); if (mem_setup.mem_mode == SETUP_MEM_REX) mem_ctrl.pRex->value(1); - // Create Rex radio button - mem_ctrl.pRex2 = new Fl_Round_Button(20, 285, 270, 20, "Rex2 (1M Opt ROM + 128K SRAM)"); + // Create Rex2 radio button + mem_ctrl.pRex2 = new Fl_Round_Button(20, 285, 270, 20, "REX2 (1M Opt ROM + 128K SRAM)"); mem_ctrl.pRex2->type(FL_RADIO_BUTTON); mem_ctrl.pRex2->callback(cb_radio_rex2); + mem_ctrl.pRex2->labelcolor(COLOR_FG); if (mem_setup.mem_mode == SETUP_MEM_REX2) mem_ctrl.pRex2->value(1); + // added SA + // Create Rex# radio button NEW + mem_ctrl.pRexS = new Fl_Round_Button(20, 310, 270, 20, "REX# (1M Opt ROM)"); + mem_ctrl.pRexS->type(FL_RADIO_BUTTON); + mem_ctrl.pRexS->callback(cb_radio_rexs); + mem_ctrl.pRexS->labelcolor(COLOR_FG); + if (mem_setup.mem_mode == SETUP_MEM_REXS) + mem_ctrl.pRexS->value(1); + // end new + + // location is fine but don't enable for REX# mem_ctrl.pRexCreateFlash = new Fl_Button(300, 270, 170, 20, "Create Default Flash"); if (mem_setup.mem_mode != SETUP_MEM_REX && mem_setup.mem_mode != SETUP_MEM_REX2 && mem_setup.mem_mode != SETUP_MEM_REX_QUAD) mem_ctrl.pRexCreateFlash->deactivate(); mem_ctrl.pRexCreateFlash->callback(cb_create_flash, &mem_ctrl); + mem_ctrl.pRexCreateFlash->color(COLOR_BG); + mem_ctrl.pRexCreateFlash->labelcolor(COLOR_FG); // =============================================== // Setup Rex Flash File edit field and Browser button // =============================================== - mem_ctrl.pRexFlashFile = new Fl_Input(105, 310, 310, 20, "Flash File"); + // modify location + mem_ctrl.pRexFlashFile = new Fl_Input(105, 335, 310, 20, "Flash File"); mem_ctrl.pRexFlashFile->value(mem_setup.rex_flash_file); - mem_ctrl.pRexFlashBrowse = new Fl_Button(430, 307, 60, 30, "Browse"); + mem_ctrl.pRexFlashFile->color(COLOR_BG_INPUT); + mem_ctrl.pRexFlashFile->labelcolor(COLOR_FG); + mem_ctrl.pRexFlashFile->textcolor(COLOR_FG); + mem_ctrl.pRexFlashFile->cursor_color(COLOR_FG); + mem_ctrl.pRexFlashBrowse = new Fl_Button(430, 332, 60, 30, "Browse"); mem_ctrl.pRexFlashBrowse->callback((Fl_Callback*)cb_rex_browse); + mem_ctrl.pRexFlashBrowse->color(COLOR_BG); + mem_ctrl.pRexFlashBrowse->labelcolor(COLOR_FG); + // added SA + // allow for REX# if ((mem_setup.mem_mode != SETUP_MEM_REX) && (mem_setup.mem_mode != SETUP_MEM_REX2) && - (mem_setup.mem_mode != SETUP_MEM_REX_QUAD)) + (mem_setup.mem_mode != SETUP_MEM_REX_QUAD) && (mem_setup.mem_mode != SETUP_MEM_REXS)) { mem_ctrl.pRexFlashFile->deactivate(); mem_ctrl.pRexFlashBrowse->deactivate(); @@ -1692,10 +1955,17 @@ void cb_MemorySetup (Fl_Widget* w, void*) // =============================================== // Setup Rex Flash File edit field and Browser button // =============================================== - mem_ctrl.pRex2RamFile = new Fl_Input(105, 345, 310, 20, "RAM File"); + // modify location + mem_ctrl.pRex2RamFile = new Fl_Input(105, 370, 310, 20, "REX2 RAM File"); mem_ctrl.pRex2RamFile->value(mem_setup.rex2_ram_file); - mem_ctrl.pRex2RamBrowse = new Fl_Button(430, 342, 60, 30, "Browse"); + mem_ctrl.pRex2RamFile->color(COLOR_BG_INPUT); + mem_ctrl.pRex2RamFile->labelcolor(COLOR_FG); + mem_ctrl.pRex2RamFile->textcolor(COLOR_FG); + mem_ctrl.pRex2RamFile->cursor_color(COLOR_FG); + mem_ctrl.pRex2RamBrowse = new Fl_Button(430, 367, 60, 30, "Browse"); mem_ctrl.pRex2RamBrowse->callback((Fl_Callback*)cb_rex2_browse); + mem_ctrl.pRex2RamBrowse->color(COLOR_BG); + mem_ctrl.pRex2RamBrowse->labelcolor(COLOR_FG); if (mem_setup.mem_mode != SETUP_MEM_REX2) { @@ -1703,22 +1973,67 @@ void cb_MemorySetup (Fl_Widget* w, void*) mem_ctrl.pRex2RamBrowse->deactivate(); } + // =============================================== + // Setup REXCPM RAM File edit field and Browser button + // =============================================== + // added SA + mem_ctrl.pRexC = new Fl_Round_Button(20, 395, 270, 20, "REXCPM (4M SRAM)"); + mem_ctrl.pRexC->type(FL_RADIO_BUTTON); + mem_ctrl.pRexC->callback(cb_radio_rexc); + mem_ctrl.pRexC->labelcolor(COLOR_FG); + if (mem_setup.mem_mode == SETUP_MEM_REXC) + mem_ctrl.pRexC->value(1); + // end new + + // =============================================== + // Setup REXCPM Flash File edit field and Browser button + // =============================================== + // modify location + // added SA + mem_ctrl.pRexCRamFile = new Fl_Input(105, 420, 310, 20, "REXCPM File"); + mem_ctrl.pRexCRamFile->value(mem_setup.rexc_ram_file); + mem_ctrl.pRexCRamFile->color(COLOR_BG_INPUT); + mem_ctrl.pRexCRamFile->labelcolor(COLOR_FG); + mem_ctrl.pRexCRamFile->textcolor(COLOR_FG); + mem_ctrl.pRexCRamFile->cursor_color(COLOR_FG); + mem_ctrl.pRexCRamBrowse = new Fl_Button(430, 417, 60, 30, "Browse"); + mem_ctrl.pRexCRamBrowse->callback((Fl_Callback*)cb_rexc_browse); + mem_ctrl.pRexCRamBrowse->color(COLOR_BG); + mem_ctrl.pRexCRamBrowse->labelcolor(COLOR_FG); + + if (mem_setup.mem_mode != SETUP_MEM_REXC) + { + mem_ctrl.pRexCRamFile->deactivate(); + mem_ctrl.pRexCRamBrowse->deactivate(); + } // Option ROM RW Enable - mem_ctrl.pOptRomRW = new Fl_Check_Button(20, 370, 210, 20, "Make Option ROM R/W"); + // new location + mem_ctrl.pOptRomRW = new Fl_Check_Button(20, 445, 210, 20, "Make Option ROM R/W"); mem_ctrl.pOptRomRW->value(gOptRomRW); + mem_ctrl.pOptRomRW->labelcolor(COLOR_FG); // Show Version Checkbox - mem_ctrl.pShowVersion = new Fl_Check_Button(20, 395, 210, 20, "Patch ROM on load to show VirtualT version"); + // new location + mem_ctrl.pShowVersion = new Fl_Check_Button(20, 470, 210, 20, "Patch ROM on load to show VirtualT version"); mem_ctrl.pShowVersion->value(gShowVersion); + mem_ctrl.pShowVersion->labelcolor(COLOR_FG); // OK button - { Fl_Button* o = new Fl_Button(140, 425, 60, 30, "Cancel"); + // new location + { Fl_Button* o = new Fl_Button(190, 515, 60, 30, "Cancel"); o->callback((Fl_Callback*)cb_memory_cancel); + o->color(COLOR_BG); + o->labelcolor(COLOR_FG); } - { Fl_Return_Button* o = new Fl_Return_Button(220, 425, 60, 30, "OK"); + { Fl_Return_Button* o = new Fl_Return_Button(270, 515, 60, 30, "OK"); o->callback((Fl_Callback*)cb_memory_OK); + o->color(COLOR_BG); + o->labelcolor(COLOR_FG); } gmsw->show(); } + +// vim: ts=4 sw=4 noet + diff --git a/src/setup.h b/src/setup.h index c863df0..69836e6 100644 --- a/src/setup.h +++ b/src/setup.h @@ -77,6 +77,8 @@ typedef struct memory_setup char rampac_file[256]; // Filename for RamPac storage char rex_flash_file[256]; // Rex flash file char rex2_ram_file[256]; // Rex2 RAM file + char rexc_ram_file[256]; // REXCPM RAM file added SA + } memory_setup_t; extern memory_setup_t mem_setup; @@ -96,6 +98,8 @@ enum { SETUP_MEM_REMEM_RAMPAC, SETUP_MEM_REX, SETUP_MEM_REX2, + SETUP_MEM_REXC, // added SA + SETUP_MEM_REXS, // added SA SETUP_MEM_QUAD, SETUP_MEM_REX_QUAD }; diff --git a/src/tpddserver.cpp b/src/tpddserver.cpp index 8a4644e..a350181 100644 --- a/src/tpddserver.cpp +++ b/src/tpddserver.cpp @@ -59,6 +59,12 @@ #include "memedit.h" #include "fileview.h" +#define COLOR_BG (gMidnight ? FL_BLACK : fl_rgb_color(192, 192, 192)) +#define COLOR_BG_INPUT (gMidnight ? FL_BLACK : FL_WHITE) +#define COLOR_FG (gMidnight ? FL_WHITE : FL_BLACK) +#define COLOR_TAB_INACTIVE_BG (gMidnight ? fl_rgb_color(32,32,32) : fl_rgb_color(192,192,192)) +#define COLOR_TAB_INACTIVE_FG (gMidnight ? fl_rgb_color(192,192,192) : FL_BLACK) + enum { TPDD_STATE_IDLE = 0, TPDD_STATE_Z, @@ -85,6 +91,7 @@ extern volatile DWORD rst7cycles; int strcasecmp(const char* s1, const char* s2); #endif } +extern int gMidnight; /* ====================================================== @@ -271,29 +278,40 @@ void tpdd_server_config(void) // Create TPDD Server configuration window gtcw = new Fl_Double_Window(480, 150, "TPDD / NADSBox Server"); gtcw->callback(cb_tcwin); + gtcw->color(COLOR_BG); o = new Fl_Box(20, 20, 80, 20, "Root Directory"); o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); // Create an input field to edit / show the root directory gTsCtrl.pRootDir = new Fl_Input(35, 40, 325, 20, ""); VTTpddServer* pServer = (VTTpddServer *) ser_get_tpdd_context(); strcpy(gTsCtrl.sRootDir, pServer->RootDir()); gTsCtrl.pRootDir->value(gTsCtrl.sRootDir); + gTsCtrl.pRootDir->color(COLOR_BG); + gTsCtrl.pRootDir->textcolor(COLOR_FG); + gTsCtrl.pRootDir->cursor_color(COLOR_FG); // Create a browse button for the root directory gTsCtrl.pTpddDir = new Fl_Button(380, 40, 80, 20, "Browse"); gTsCtrl.pTpddDir->callback(cb_TpddDir); + gTsCtrl.pTpddDir->color(COLOR_BG); + gTsCtrl.pTpddDir->labelcolor(COLOR_FG); // Create a Cancel button b = new Fl_Button(200, 120, 80, 20, "Cancel"); b->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE); b->callback(cb_tpdd_cancel); + b->color(COLOR_BG); + b->labelcolor(COLOR_FG); // Create an OK button b = new Fl_Return_Button(300, 120, 80, 20, "OK"); b->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE); b->callback(cb_tpdd_ok); + b->color(COLOR_BG); + b->labelcolor(COLOR_FG); gtcw->show(); } @@ -2224,7 +2242,9 @@ void VTTpddServer::OpcodeClose(void) { // Test if last "open" was a directory open if (m_lastOpenWasDir) + { SendNormalReturn(TPDD_ERR_NONE); + } // Test if the active FD is open else if (m_refFd[m_activeFd] == NULL) diff --git a/src/vtpaper.cpp b/src/vtpaper.cpp index 1f31418..ca4f12c 100644 --- a/src/vtpaper.cpp +++ b/src/vtpaper.cpp @@ -48,6 +48,12 @@ #include "VirtualT.h" #include "vtpaper.h" +extern int gMidnight; + +#define COLOR_BG (gMidnight ? FL_BLACK : fl_rgb_color(192, 192, 192)) +#define COLOR_BG_INPUT (gMidnight ? FL_BLACK : FL_WHITE) +#define COLOR_FG (gMidnight ? FL_WHITE : FL_BLACK) + void cb_VTPaperScroll(Fl_Widget *w, void * ptr) { if (ptr != NULL) @@ -690,22 +696,28 @@ void VTPSPaper::BuildControls() m_pPrompt = new Fl_Check_Button(45, 210, 155, 20, "Prompt for Filename"); m_pPrompt->hide(); m_pPrompt->value(m_prompt); + m_pPrompt->labelcolor(COLOR_FG); // Control to enable auto file generation m_pAutoFilename = new Fl_Check_Button(45, 235, 210, 20, "Generate Automatic filename"); m_pAutoFilename->hide(); m_pAutoFilename->value(m_autoFilename); + m_pAutoFilename->labelcolor(COLOR_FG); // Control to edit the output file generator format m_pFileFormat = new Fl_Input(65, 260, 240, 20, ""); m_pFileFormat->hide(); m_pFileFormat->value((const char *) m_fileFormat); + m_pFileFormat->color(COLOR_BG); + m_pFileFormat->textcolor(COLOR_FG); + m_pFileFormat->cursor_color(COLOR_FG); if (!m_autoFilename) m_pFileFormat->deactivate(); // Control to show the format specifiers m_pFormatText = new Fl_Box(75, 280, 230, 20, "%d = Date %s = Seq"); m_pFormatText->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + m_pFormatText->labelcolor(COLOR_FG); m_pFormatText->hide(); // Create control for ink darkness @@ -716,13 +728,17 @@ void VTPSPaper::BuildControls() m_pDarkness->range(20, 60); m_pDarkness->value(m_darkness); m_pDarkness->hide(); + m_pDarkness->color(COLOR_BG); + m_pDarkness->labelcolor(COLOR_FG); m_pLight = new Fl_Box(45, 305, 40, 20, "Light"); m_pLight->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); m_pLight->hide(); + m_pLight->labelcolor(COLOR_FG); m_pDark = new Fl_Box(240, 305, 40, 20, "Dark"); m_pDark->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); m_pDark->hide(); + m_pDark->labelcolor(COLOR_FG); // Set callback for checkbox m_pAutoFilename->callback(cb_PSAutoFilenameCheck, m_pFileFormat); @@ -1415,16 +1431,23 @@ void VTlprPaper::BuildControls() m_pFileFormat = new Fl_Input(65, 215, 240, 20, "Format"); m_pFileFormat->hide(); m_pFileFormat->value((const char *) m_fileFormat); + m_pFileFormat->color(COLOR_BG); + m_pFileFormat->textcolor(COLOR_FG); + m_pFileFormat->cursor_color(COLOR_FG); // Control to edit the output file generator format m_pCmdLine = new Fl_Input(65, 245, 240, 20, "Cmd"); m_pCmdLine->hide(); m_pCmdLine->value((const char *) m_cmdLine); + m_pCmdLine->color(COLOR_BG); + m_pCmdLine->textcolor(COLOR_FG); + m_pCmdLine->cursor_color(COLOR_FG); // Control to show the format specifiers m_pFormatText = new Fl_Box(75, 270, 230, 20, "%d = Date %s = Seq %f = File"); m_pFormatText->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); m_pFormatText->hide(); + m_pFormatText->labelcolor(COLOR_FG); // Create control for ink darkness m_pDarkness = new Fl_Slider(90, 305, 140, 20, "Ink Density"); @@ -1434,13 +1457,17 @@ void VTlprPaper::BuildControls() m_pDarkness->range(20, 60); m_pDarkness->value(m_darkness); m_pDarkness->hide(); + m_pDarkness->color(COLOR_BG); + m_pDarkness->labelcolor(COLOR_FG); m_pLight = new Fl_Box(45, 305, 40, 20, "Light"); m_pLight->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); m_pLight->hide(); + m_pLight->labelcolor(COLOR_FG); m_pDark = new Fl_Box(240, 305, 40, 20, "Dark"); m_pDark->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); m_pDark->hide(); + m_pDark->labelcolor(COLOR_FG); } From 9b814d95231d076c595949df0751c57508dd7c3f Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Sat, 22 May 2021 22:36:07 -0700 Subject: [PATCH 325/327] Updates to get VirtualT 1.8 compiling under Windows using FLTK-1.3.5. --- VirtualT.dsp | 794 +++--- VirtualT.dsw | 58 +- VirtualT.sln | 46 +- VirtualT.suo | Bin 352256 -> 350208 bytes VirtualT.vcproj | 2905 +++++++++++----------- src/file.cpp | 4 +- src/memory.c | 1 + src/tdockvid.cpp | 2247 ++++++++--------- src/tpddserver.cpp | 5886 ++++++++++++++++++++++---------------------- 9 files changed, 5957 insertions(+), 5984 deletions(-) mode change 100644 => 100755 VirtualT.dsp mode change 100644 => 100755 VirtualT.suo mode change 100644 => 100755 src/file.cpp mode change 100644 => 100755 src/memory.c mode change 100644 => 100755 src/tdockvid.cpp mode change 100644 => 100755 src/tpddserver.cpp diff --git a/VirtualT.dsp b/VirtualT.dsp old mode 100644 new mode 100755 index 31bd04b..dca1f4f --- a/VirtualT.dsp +++ b/VirtualT.dsp @@ -1,397 +1,397 @@ -# Microsoft Developer Studio Project File - Name="VirtualT" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Application" 0x0101 - -CFG=VirtualT - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "VirtualT.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "VirtualT.mak" CFG="VirtualT - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "VirtualT - Win32 Release" (based on "Win32 (x86) Application") -!MESSAGE "VirtualT - Win32 Debug" (based on "Win32 (x86) Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "VirtualT - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /Od /I "$(FLTKDIR)" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 -# ADD LINK32 $(FLTKDIR)/lib/fltk.lib $(FLTKDIR)/lib/fltkimages.lib wsock32.lib comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib:"libc" /libpath:"..\lib" -# SUBTRACT LINK32 /pdb:none /incremental:yes /nodefaultlib - -!ELSEIF "$(CFG)" == "VirtualT - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "$(FLTKDIR)" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept -# ADD LINK32 $(FLTKDIR)/lib/fltkd.lib $(FLTKDIR)/lib/fltkimagesd.lib wsock32.lib comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib:"libcd" /libpath:"..\lib" -# SUBTRACT LINK32 /pdb:none /incremental:no /debug /pdbtype: - -!ENDIF - -# Begin Target - -# Name "VirtualT - Win32 Release" -# Name "VirtualT - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Group "asm" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\a85parse.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\assemble.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\MString.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\MStringArray.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\rpn_eqn.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\vtobj.cpp -# End Source File -# End Group -# Begin Group "ide" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\Flu_DND.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\flu_pixmaps.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\Flu_Tree_Browser.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\FluSimpleString.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\ide.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\multiwin.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\multiwin_icons.cpp -# End Source File -# End Group -# Begin Source File - -SOURCE=.\src\cpuregs.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\disassemble.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\display.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\doins.c -# End Source File -# Begin Source File - -SOURCE=.\src\file.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\genwrap.c -# End Source File -# Begin Source File - -SOURCE=.\src\intelhex.c -# End Source File -# Begin Source File - -SOURCE=.\src\io.c -# End Source File -# Begin Source File - -SOURCE=.\src\m100emu.c -# End Source File -# Begin Source File - -SOURCE=.\src\m100rom.c -# End Source File -# Begin Source File - -SOURCE=.\src\m200rom.c -# End Source File -# Begin Source File - -SOURCE=.\src\memedit.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\memory.c -# End Source File -# Begin Source File - -SOURCE=.\src\n8201rom.c -# End Source File -# Begin Source File - -SOURCE=.\src\periph.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\romstrings.c -# End Source File -# Begin Source File - -SOURCE=.\src\serial.c -# End Source File -# Begin Source File - -SOURCE=.\src\setup.cpp -# End Source File -# Begin Source File - -SOURCE=.\src\sound.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Group "asm.h" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\a85parse.h -# End Source File -# Begin Source File - -SOURCE=.\src\assemble.h -# End Source File -# Begin Source File - -SOURCE=.\src\elf.h -# End Source File -# Begin Source File - -SOURCE=.\src\MString.h -# End Source File -# Begin Source File - -SOURCE=.\src\MStringArray.h -# End Source File -# Begin Source File - -SOURCE=.\src\rpn_eqn.h -# End Source File -# Begin Source File - -SOURCE=.\src\vtobj.h -# End Source File -# End Group -# Begin Group "ide.h" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\FLU\Flu_DND.h -# End Source File -# Begin Source File - -SOURCE=.\src\FLU\Flu_Enumerations.h -# End Source File -# Begin Source File - -SOURCE=.\src\FLU\flu_export.h -# End Source File -# Begin Source File - -SOURCE=.\src\FLU\flu_pixmaps.h -# End Source File -# Begin Source File - -SOURCE=.\src\FLU\Flu_Tree_Browser.h -# End Source File -# Begin Source File - -SOURCE=.\src\FLU\FluSimpleString.h -# End Source File -# Begin Source File - -SOURCE=.\src\ide.h -# End Source File -# Begin Source File - -SOURCE=.\src\multiwin.h -# End Source File -# Begin Source File - -SOURCE=.\src\multiwin_icons.h -# End Source File -# End Group -# Begin Source File - -SOURCE=.\src\cpu.h -# End Source File -# Begin Source File - -SOURCE=.\src\cpuregs.h -# End Source File -# Begin Source File - -SOURCE=.\src\disassemble.h -# End Source File -# Begin Source File - -SOURCE=.\src\display.h -# End Source File -# Begin Source File - -SOURCE=.\src\do_instruct.h -# End Source File -# Begin Source File - -SOURCE=.\src\doins.h -# End Source File -# Begin Source File - -SOURCE=.\src\gen_defs.h -# End Source File -# Begin Source File - -SOURCE=.\src\genwrap.h -# End Source File -# Begin Source File - -SOURCE=.\src\intelhex.h -# End Source File -# Begin Source File - -SOURCE=.\src\io.h -# End Source File -# Begin Source File - -SOURCE=.\src\m100emu.h -# End Source File -# Begin Source File - -SOURCE=.\src\memedit.h -# End Source File -# Begin Source File - -SOURCE=.\src\memory.h -# End Source File -# Begin Source File - -SOURCE=.\src\periph.h -# End Source File -# Begin Source File - -SOURCE=.\src\roms.h -# End Source File -# Begin Source File - -SOURCE=.\src\romstrings.h -# End Source File -# Begin Source File - -SOURCE=.\src\serial.h -# End Source File -# Begin Source File - -SOURCE=.\src\setup.h -# End Source File -# Begin Source File - -SOURCE=.\src\sound.h -# End Source File -# Begin Source File - -SOURCE=.\src\VirtualT.h -# End Source File -# Begin Source File - -SOURCE=.\src\wrapdll.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project +# Microsoft Developer Studio Project File - Name="VirtualT" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=VirtualT - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "VirtualT.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "VirtualT.mak" CFG="VirtualT - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "VirtualT - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "VirtualT - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "VirtualT - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /Od /I "$(FLTKDIR)" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 $(FLTKDIR)/lib/fltk.lib $(FLTKDIR)/lib/fltkimages.lib wsock32.lib comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib:"libc" /libpath:"..\lib" +# SUBTRACT LINK32 /pdb:none /incremental:yes /nodefaultlib + +!ELSEIF "$(CFG)" == "VirtualT - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "$(FLTKDIR)" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 $(FLTKDIR)/lib/fltkd.lib $(FLTKDIR)/lib/fltkimagesd.lib wsock32.lib comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib:"libcd" /libpath:"..\lib" +# SUBTRACT LINK32 /pdb:none /incremental:no /debug /pdbtype: + +!ENDIF + +# Begin Target + +# Name "VirtualT - Win32 Release" +# Name "VirtualT - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "asm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\a85parse.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\assemble.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\MString.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\MStringArray.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\rpn_eqn.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\vtobj.cpp +# End Source File +# End Group +# Begin Group "ide" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\Flu_DND.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\flu_pixmaps.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\Flu_Tree_Browser.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\FluSimpleString.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\ide.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\multiwin.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\multiwin_icons.cpp +# End Source File +# End Group +# Begin Source File + +SOURCE=.\src\cpuregs.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\disassemble.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\display.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\doins.c +# End Source File +# Begin Source File + +SOURCE=.\src\file.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\genwrap.c +# End Source File +# Begin Source File + +SOURCE=.\src\intelhex.c +# End Source File +# Begin Source File + +SOURCE=.\src\io.c +# End Source File +# Begin Source File + +SOURCE=.\src\m100emu.c +# End Source File +# Begin Source File + +SOURCE=.\src\m100rom.c +# End Source File +# Begin Source File + +SOURCE=.\src\m200rom.c +# End Source File +# Begin Source File + +SOURCE=.\src\memedit.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\memory.c +# End Source File +# Begin Source File + +SOURCE=.\src\n8201rom.c +# End Source File +# Begin Source File + +SOURCE=.\src\periph.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\romstrings.c +# End Source File +# Begin Source File + +SOURCE=.\src\serial.c +# End Source File +# Begin Source File + +SOURCE=.\src\setup.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sound.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Group "asm.h" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\a85parse.h +# End Source File +# Begin Source File + +SOURCE=.\src\assemble.h +# End Source File +# Begin Source File + +SOURCE=.\src\elf.h +# End Source File +# Begin Source File + +SOURCE=.\src\MString.h +# End Source File +# Begin Source File + +SOURCE=.\src\MStringArray.h +# End Source File +# Begin Source File + +SOURCE=.\src\rpn_eqn.h +# End Source File +# Begin Source File + +SOURCE=.\src\vtobj.h +# End Source File +# End Group +# Begin Group "ide.h" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\FLU\Flu_DND.h +# End Source File +# Begin Source File + +SOURCE=.\src\FLU\Flu_Enumerations.h +# End Source File +# Begin Source File + +SOURCE=.\src\FLU\flu_export.h +# End Source File +# Begin Source File + +SOURCE=.\src\FLU\flu_pixmaps.h +# End Source File +# Begin Source File + +SOURCE=.\src\FLU\Flu_Tree_Browser.h +# End Source File +# Begin Source File + +SOURCE=.\src\FLU\FluSimpleString.h +# End Source File +# Begin Source File + +SOURCE=.\src\ide.h +# End Source File +# Begin Source File + +SOURCE=.\src\multiwin.h +# End Source File +# Begin Source File + +SOURCE=.\src\multiwin_icons.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\src\cpu.h +# End Source File +# Begin Source File + +SOURCE=.\src\cpuregs.h +# End Source File +# Begin Source File + +SOURCE=.\src\disassemble.h +# End Source File +# Begin Source File + +SOURCE=.\src\display.h +# End Source File +# Begin Source File + +SOURCE=.\src\do_instruct.h +# End Source File +# Begin Source File + +SOURCE=.\src\doins.h +# End Source File +# Begin Source File + +SOURCE=.\src\gen_defs.h +# End Source File +# Begin Source File + +SOURCE=.\src\genwrap.h +# End Source File +# Begin Source File + +SOURCE=.\src\intelhex.h +# End Source File +# Begin Source File + +SOURCE=.\src\io.h +# End Source File +# Begin Source File + +SOURCE=.\src\m100emu.h +# End Source File +# Begin Source File + +SOURCE=.\src\memedit.h +# End Source File +# Begin Source File + +SOURCE=.\src\memory.h +# End Source File +# Begin Source File + +SOURCE=.\src\periph.h +# End Source File +# Begin Source File + +SOURCE=.\src\roms.h +# End Source File +# Begin Source File + +SOURCE=.\src\romstrings.h +# End Source File +# Begin Source File + +SOURCE=.\src\serial.h +# End Source File +# Begin Source File + +SOURCE=.\src\setup.h +# End Source File +# Begin Source File + +SOURCE=.\src\sound.h +# End Source File +# Begin Source File + +SOURCE=.\src\VirtualT.h +# End Source File +# Begin Source File + +SOURCE=.\src\wrapdll.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/VirtualT.dsw b/VirtualT.dsw index e643330..2eca512 100644 --- a/VirtualT.dsw +++ b/VirtualT.dsw @@ -1,29 +1,29 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "VirtualT"=.\VirtualT.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "VirtualT"=.\VirtualT.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/VirtualT.sln b/VirtualT.sln index 8f3c390..2eff8d5 100644 --- a/VirtualT.sln +++ b/VirtualT.sln @@ -1,26 +1,20 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VirtualT", "VirtualT.vcproj", "{4B62EF01-B8D4-4C99-BC7B-661B97684568}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vt_client", "vt_client_src\vt_client.vcproj", "{2EE29331-FFC1-46AF-96AB-AA0643DF918E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4B62EF01-B8D4-4C99-BC7B-661B97684568}.Debug|Win32.ActiveCfg = Debug|Win32 - {4B62EF01-B8D4-4C99-BC7B-661B97684568}.Debug|Win32.Build.0 = Debug|Win32 - {4B62EF01-B8D4-4C99-BC7B-661B97684568}.Release|Win32.ActiveCfg = Release|Win32 - {4B62EF01-B8D4-4C99-BC7B-661B97684568}.Release|Win32.Build.0 = Release|Win32 - {2EE29331-FFC1-46AF-96AB-AA0643DF918E}.Debug|Win32.ActiveCfg = Debug|Win32 - {2EE29331-FFC1-46AF-96AB-AA0643DF918E}.Debug|Win32.Build.0 = Debug|Win32 - {2EE29331-FFC1-46AF-96AB-AA0643DF918E}.Release|Win32.ActiveCfg = Release|Win32 - {2EE29331-FFC1-46AF-96AB-AA0643DF918E}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VirtualT", "VirtualT.vcproj", "{7E618E02-9E81-408D-AC2F-0BEB162025BC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7E618E02-9E81-408D-AC2F-0BEB162025BC}.Debug|Win32.ActiveCfg = Debug|Win32 + {7E618E02-9E81-408D-AC2F-0BEB162025BC}.Debug|Win32.Build.0 = Debug|Win32 + {7E618E02-9E81-408D-AC2F-0BEB162025BC}.Release|Win32.ActiveCfg = Release|Win32 + {7E618E02-9E81-408D-AC2F-0BEB162025BC}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/VirtualT.suo b/VirtualT.suo old mode 100644 new mode 100755 index 7073294b2a8c7411bdd97e3fe3ff10e07815e150..7555ec6ae106c3e51d8afef34dfe46ac5379aba1 GIT binary patch delta 9142 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 EUjX`|+W-In delta 9296 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 H5~BVA@j)rx diff --git a/VirtualT.vcproj b/VirtualT.vcproj index 852d097..f4fa45e 100644 --- a/VirtualT.vcproj +++ b/VirtualT.vcproj @@ -1,1469 +1,1436 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/file.cpp b/src/file.cpp old mode 100644 new mode 100755 index 7bba3a9..cda44b8 --- a/src/file.cpp +++ b/src/file.cpp @@ -52,13 +52,13 @@ extern "C" #include "m100emu.h" extern RomDescription_t *gStdRomDesc; -extern int gMidnight; void jump_to_zero(void); } - #include "file.h" #include "fileview.h" +extern int gMidnight; + #define COLOR_BG (gMidnight ? FL_BLACK : fl_rgb_color(192, 192, 192)) #define COLOR_BG_INPUT (gMidnight ? FL_BLACK : FL_WHITE) #define COLOR_FG (gMidnight ? FL_WHITE : FL_BLACK) diff --git a/src/memory.c b/src/memory.c old mode 100644 new mode 100755 index 2923150..432d7a3 --- a/src/memory.c +++ b/src/memory.c @@ -3887,6 +3887,7 @@ unsigned char rexC_read(unsigned short address) break; } } + return 0; } /* diff --git a/src/tdockvid.cpp b/src/tdockvid.cpp old mode 100644 new mode 100755 index c15ac3c..5590369 --- a/src/tdockvid.cpp +++ b/src/tdockvid.cpp @@ -1,1121 +1,1126 @@ -/* tdockvid.cpp */ - -/* $Id$ */ - -/* - * Copyright 2015 Ken Pettit - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - -#include -#include -#include -#include - -#include - -#include "FLU/Flu_Button.h" -#include "FLU/Flu_Return_Button.h" -#include "FLU/flu_pixmaps.h" - -#include -#include -#include -#ifndef WIN32 -#include -#include -#endif - -#include "VirtualT.h" -#include "display.h" -#include "tdockvid.h" -#include "m100emu.h" -#include "io.h" -#include "file.h" -#include "setup.h" -#include "periph.h" -#include "memory.h" -#include "memedit.h" -#include "cpuregs.h" -#include "rememcfg.h" -#include "lpt.h" -#include "fl_action_icon.h" -#include "clock.h" -#include "fileview.h" -#include "romstrings.h" -#include "remote.h" -#include "tpddserverlog.h" - - -extern "C" { -extern RomDescription_t gM100_Desc; -extern RomDescription_t gM200_Desc; -extern RomDescription_t gN8201_Desc; -extern RomDescription_t gM10_Desc; -//JV -//extern RomDescription_t gN8300_Desc; -extern RomDescription_t gKC85_Desc; - -extern RomDescription_t *gStdRomDesc; -extern int gRomSize; -extern int gMaintCount; -extern int gOsDelay; -} - - -extern int MultFact; -extern int DisplayMode; -extern int Fullscreen; -extern int SolidChars; -extern int DispHeight; -extern int gRectsize; -extern int gXoffset; -extern int gYoffset; -extern int gSimKey; -extern int gFrameColor; -extern int gDetailColor; -extern int gBackgroundColor; -extern int gPixelColor; -extern int gLabelColor; -extern int gConsoleDebug; - -#ifndef WIN32 -#define min(a,b) ((a)<(b) ? (a):(b)) -#endif -#ifdef WIN32 -extern "C" -{ -int strcasecmp(const char* s1, const char* s2); -} -#endif - -extern T100_Disp* gpDisp; - -typedef struct namedColors -{ - const char * pName; - unsigned char cid; - unsigned char red; - unsigned char green; - unsigned char blue; -} namedColors_t; - -static namedColors_t gNamedColors[] = { -#include "colors.h" -}; -static int gColorCount = sizeof(gNamedColors) / sizeof(namedColors_t); - -/* -======================================================= -T100:Disp: This is the class construcor -======================================================= -*/ -VTTDockVid::VTTDockVid(int x, int y, int w, int h) : - Fl_Widget(x, y, w, h) -{ - int c, red, green, blue; - - m_FrameColor = gFrameColor; - m_DetailColor = gDetailColor; - m_BackgroundColor = gBackgroundColor; - m_PixelColor = gPixelColor; - m_LabelColor = gLabelColor; - m_HaveMouse = FALSE; - m_LabelLocked = FALSE; - - memset(pixdata, 0, 200*480); - - m_MyFocus = 0; - m_CurX = 0; - m_CurY = 0; - m_EscSeq = 0; - m_Reverse = 0; - m_Locked = 0; - m_Width = 40; - m_Color = 255; - - m_Colors[1] = FL_DARK_RED; - m_Colors[2] = FL_DARK_GREEN; - m_Colors[3] = FL_DARK_YELLOW; - m_Colors[4] = FL_DARK_BLUE; - m_Colors[5] = FL_DARK_MAGENTA; - m_Colors[6] = FL_DARK_CYAN; - m_Colors[7] = FL_LIGHT1; - - m_Colors[8] = FL_DARK2; - m_Colors[9] = FL_RED; - m_Colors[10] = FL_GREEN; - m_Colors[11] = FL_YELLOW; - m_Colors[12] = FL_BLUE; - m_Colors[13] = FL_MAGENTA; - m_Colors[14] = FL_CYAN; - m_Colors[15] = FL_WHITE; - - /* 6x6x6 Color Cube */ - c = 16; - for (red = 0; red <=255; red += 51) - for (green = 0; green <=255; green += 51) - for (blue = 0; blue <=255; blue += 51) - { - m_Colors[c++] = fl_rgb_color(red , green, blue); - } - - /* Gray scale */ - red = 255; - for (c = 254; c >= 232; c--) - { - m_Colors[c] = fl_rgb_color(red, red, red); - red -= 11; - } - - m_Colors[0] = gBackgroundColor; - m_Colors[255] = gPixelColor; - - MultFact = 2; - DisplayMode = 1; - SolidChars = 0; - DispHeight = 64; - gRectsize = 2; - - m_BezelTop = m_BezelLeft = m_BezelBottom = m_BezelRight = 0; - m_BezelTopH = m_BezelLeftW = m_BezelBottomH = m_BezelRightW = 0; - - CalcScreenCoords(); -} - -VTTDockVid::~VTTDockVid() -{ -} - -/* -================================================================= -Clear: This routine clears the "LCD" -================================================================= -*/ -void VTTDockVid::Clear(void) -{ - int bottom; - - if (m_LabelLocked) - bottom = 200-8; - else - bottom = 200; - memset(pixdata, 0, bottom*480); - - m_CurX = m_CurY = 0; - redraw(); - Fl::check(); -} - -/* -================================================================= -drawpixel: This routine is called by the system to draw a single - black pixel on the "LCD". -================================================================= -*/ -// Draw the black pixels on the LCD -__inline void VTTDockVid::drawpixel(int x, int y, int color) -{ - // Check if the pixel color is black and draw if it is - if (color) - { - fl_rectf(x*MultFact + gXoffset,y*MultFact + gYoffset, - gRectsize, gRectsize); - } -} - -/* -======================================================= -Set the screen size multiplication factor -======================================================= -*/ -void VTTDockVid::SetMultFact(int multfact) -{ - MultFact = multfact; - ::MultFact = multfact; - gRectsize = multfact; -} - -/* -======================================================= -Calculate the xoffset, yoffset, border locations, etc. -======================================================= -*/ -void VTTDockVid::CalcScreenCoords(void) -{ - // Calculatet the pixel rectangle size - ::gRectsize = MultFact; - if (::gRectsize == 0) - ::gRectsize = 1; - - // Calculate xoffset and yoffset - if (Fullscreen) - { - ::gXoffset = parent()->w() / 2 - 240 * MultFact; - ::gYoffset = (parent()->h() - MENU_HEIGHT - 20 - 200 * MultFact) / 3 + MENU_HEIGHT+1; - } - else - { - ::gXoffset = 5; - ::gYoffset = MENU_HEIGHT+5; - } - - gRectsize = ::gRectsize; - gXoffset = ::gXoffset; - gYoffset = ::gYoffset; - - // If the display is framed, then calculate the frame coords - if (DisplayMode && 0) - { - // Calculate the Bezel location - int wantedH = 20; - int wantedW = 40; - // int topH, bottomH, leftW, rightW; - int bottomSpace; - int rightSpace; - - // Calculate the top height of the Bezel - m_HasTopChassis = TRUE; - if (gYoffset-1 - MENU_HEIGHT-1 >= wantedH + 5) - m_BezelTopH = wantedH; - else - { - // Test if there's room for both Bezel and chassis detail - if (gYoffset > 6) - m_BezelTopH = gYoffset - MENU_HEIGHT - 1 - 6; - else - { - m_BezelTopH = gYoffset - MENU_HEIGHT - 1 - 1; - m_HasTopChassis = FALSE; - } - } - m_BezelTop = gYoffset - m_BezelTopH - 1; - - // Calculate the bottom height of the Bezel - m_BezelBottom = gYoffset + 200 * MultFact + 1; - bottomSpace = parent()->h() - m_BezelBottom - 20; - m_HasBottomChassis = TRUE; - if (bottomSpace >= wantedH + 5) - m_BezelBottomH = wantedH; - else - { - m_BezelBottomH = bottomSpace; - m_HasBottomChassis = FALSE; - } - - // Calculate the left Bezel border width - m_HasLeftChassis = TRUE; - if (gXoffset-1 >= wantedW + 5) - m_BezelLeftW = wantedW; - else - { - // Test if there's room for Bezel plus chassis - if (gXoffset > 6) - m_BezelLeftW = gXoffset - 6; - else - { - m_BezelLeftW = gXoffset - 1; - m_HasLeftChassis = FALSE; - } - } - m_BezelLeft = gXoffset - m_BezelLeftW - 1; - - // Calculate the Bezel right width - m_BezelRight = gXoffset + 240 * MultFact + 1; - rightSpace = w() - m_BezelRight; - m_HasRightChassis = TRUE; - if (rightSpace >= wantedW + 5) - m_BezelRightW = wantedW; - else - { - // Test if there's room for Bezel plus chassis - if (rightSpace > 5) - m_BezelRightW = rightSpace - 5; - else - { - m_BezelRightW = rightSpace; - m_HasRightChassis = FALSE; - } - } - } -} - -/* -================================================================= -draw_static: This routine draws the static portions of the LCD, - such as erasing the background, drawing function - key labls, etc. -================================================================= -*/ -void VTTDockVid::draw_static() -{ - int c; - int width; - int x_pos, inc, start, y_pos; - int xl_start, xl_end, xr_start, xr_end; - int num_labels; - - // Draw gray "screen" - fl_color(m_BackgroundColor); - fl_rectf(x(),y(),w(),h()); - - return; - - /* Check if the user wants the display "framed" */ - if (DisplayMode == 1) - { - // Color for outer border - fl_color(m_DetailColor); - - // Draw border along the top - if (m_HasTopChassis) - fl_rectf(x(),y(),w(),m_BezelTop - MENU_HEIGHT - 1); - - // Draw border along the bottom - if (m_HasBottomChassis) - fl_rectf(x(),m_BezelBottom + m_BezelBottomH,w(),parent()->h() - m_BezelBottom - m_BezelBottomH - 20); - - // Draw border along the left - if (m_HasLeftChassis) - fl_rectf(x(),y(),m_BezelLeft,h()); - - // Draw border along the right - if (m_HasRightChassis) - fl_rectf(m_BezelRight + m_BezelRightW,y(),w()-m_BezelRight,h()); - - // Color for inner border - fl_color(m_FrameColor); - - // Draw border along the top - if (m_BezelTopH > 0) - fl_rectf(m_BezelLeft,m_BezelTop,m_BezelRight - m_BezelLeft + m_BezelRightW,m_BezelTopH); - - // Draw border along the bottom - if (m_BezelBottomH > 0) - fl_rectf(m_BezelLeft,m_BezelBottom,m_BezelRight - m_BezelLeft + m_BezelRightW,m_BezelBottomH); - - // Draw border along the left - if (m_BezelLeftW > 0) - fl_rectf(m_BezelLeft, m_BezelTop, m_BezelLeftW, m_BezelBottom - m_BezelTop + m_BezelBottomH); - - // Draw border along the right - if (m_BezelRightW > 0) - fl_rectf(m_BezelRight,m_BezelTop, m_BezelRightW, m_BezelBottom - m_BezelTop + m_BezelBottomH); - - -#ifdef ZIPIT_Z2 - width = 320; -#else - width = 240 * MultFact; -#endif - num_labels = gModel == MODEL_PC8201 ? 5 : 8; - inc = width / num_labels; - start = gXoffset + width/16 - 2 * (5- (MultFact > 5? 5 : MultFact)); - fl_color(m_LabelColor); - fl_font(FL_COURIER,12); - char text[3] = "F1"; - //y_pos = h()+20; - y_pos = m_BezelBottom + 13; //y()+DispHeight*MultFact+40; - xl_start = 2*MultFact; - xl_end = 7*MultFact; - - xr_start = 12 + 2*MultFact; - xr_end = 12 + 7*MultFact; - - // Draw function key labels - for (c = 0; c < num_labels; c++) - { - // Draw text - x_pos = start + inc*c; - text[1] = c + '1'; - fl_draw(text, x_pos, y_pos); - - if (MultFact != 1) - { - // Draw lines to left - fl_line(x_pos - xl_start, y_pos-2, x_pos - xl_end, y_pos-2); - fl_line(x_pos - xl_start, y_pos-7, x_pos - xl_end, y_pos-7); - fl_line(x_pos - xl_end, y_pos-2, x_pos - xl_end, y_pos-7); - - // Draw lines to right - fl_line(x_pos + xr_start, y_pos-2, x_pos + xr_end, y_pos-2); - fl_line(x_pos + xr_start, y_pos-7, x_pos + xr_end, y_pos-7); - fl_line(x_pos + xr_end, y_pos-2, x_pos + xr_end, y_pos-7); - } - } - } -} - -/* -================================================================= -draw: This routine draws the entire LCD. This is a member - function of Fl_Window. -================================================================= -*/ -void VTTDockVid::draw() -{ - /* Draw static background stuff */ - draw_static(); - - /* Draw the pixels */ - draw_pixels(); -} - -/* -================================================================= -draw_pixels: This routine draws the pixels on the display. -================================================================= -*/ -void VTTDockVid::draw_pixels() -{ - int x=0; - int line; - uchar value; - int color; - - window()->make_current(); - - for (line = 0; line < 200; line++) - { - for (x = 0; x < 480; x++) - { - value = pixdata[line][x]; - - // Erase line so it is grey, then fill in with black where needed - if ((line & 0x07) == 0) - { - fl_color(m_BackgroundColor); - fl_rectf(x*MultFact + gXoffset,line*MultFact + - gYoffset,gRectsize,8*MultFact); - } - if (value == 0) - continue; - - // Draw the pixels - color = m_Colors[value]; - fl_color(color); - drawpixel(x,line,1); - } - } -} - -/* -================================================================================ -SetByte: Updates the LCD with a byte of data as written from the I/O - interface from the 8085. -================================================================================ -*/ -void VTTDockVid::SetByte(int line, int col, uchar value) -{ - int y; - - if (line > 24 || col > 479) - return; - if (line < 0 || col < 0) - return; - - // Check if LCD already has the value being requested - //if (pixdata[line][col] == value) - // return; - - // Load new value into lcd "RAM" - y = line << 3; - //pixdata[line][col] = value; - - pixdata[y++][col] = value&0x01 ? m_Color : 0; - pixdata[y++][col] = value&0x02 ? m_Color : 0; - pixdata[y++][col] = value&0x04 ? m_Color : 0; - pixdata[y++][col] = value&0x08 ? m_Color : 0; - pixdata[y++][col] = value&0x10 ? m_Color : 0; - pixdata[y++][col] = value&0x20 ? m_Color : 0; - pixdata[y++][col] = value&0x40 ? m_Color : 0; - pixdata[y++][col] = value&0x80 ? m_Color : 0; - - // Calcluate y position of byte - y = line << 3; - - // Set the display - window()->make_current(); - - fl_color(m_BackgroundColor); - fl_rectf(col*MultFact + gXoffset, y*MultFact + - gYoffset, gRectsize,MultFact<<3); - - if (value == 0) - return; - - fl_color(m_Colors[m_Color]); - - for (y = line << 3; y < (line+1) << 3; y++) - drawpixel(col,y,pixdata[y][col]); -} - -/* -================================================================================ -WriteData: Routine that receives data from the VDock interface when the - Model T sends data / commands to our device ID. -================================================================================ -*/ -void VTTDockVid::WriteData(uchar data) -{ - int line, col, y; - int color, bottom; - -#if 0 - if (m_EscSeq) - { - printf("%c(%02x), X=%d, Y=%d\n", data, data, m_CurX, m_CurY); - } - else if (data == 0x1B) - printf("ESC "); -#if 1 - else if (data <= ' ') - printf("%02X, X=%d, Y=%d\n", data, m_CurX, m_CurY); - else - printf("%c, X=%d, Y=%d\n", data, m_CurX, m_CurY); -#endif -#endif - - window()->make_current(); - - /* Calculate bottom pixel value based on m_LabelLocked */ - if (m_LabelLocked) - bottom = 200-8; - else - bottom = 200; - - /* Test if we are processing an ESC Sequence */ - if (m_EscSeq) - { - /* Add the byte to the escape sequence */ - m_EscData[m_EscSeq++ - 1] = data; - - /* Test if time to process the ESC sequence */ - if (m_EscData[0] == 'Y') - { - //printf("ESCY:%d\n", m_EscSeq); - if (m_EscSeq == 4) - { - /* Process the cursor position sequence */ - m_CurX = (m_EscData[2] - 0x20) * 6; - if (m_Width == 40) - m_CurX <<= 1; - m_CurY = (m_EscData[1] - 0x20) * 8; - if (m_CurX < 0) - m_CurX = 0; - if (m_CurY < 0) - m_CurY = 0; - if (m_CurX > 474) - m_CurX = 474; - if (m_CurY > 192) - m_CurY = 192; - m_EscSeq = 0; - } - } - else if (m_EscData[0] == ESC_SET_COLOR) - { - if (m_EscSeq == 3) - { - m_Color = (unsigned char) m_EscData[1]; - m_EscSeq = 0; - } - } - else if ((m_EscData[0] == ESC_SET_COLOR_NAME) || m_EscData[0] == ESC_SET_BG_NAME) - { - if (data == 0x0A) - { - /* Do a color name lookup */ - /* First remove the 0D and 0A */ - m_EscSeq -= 2; - while (m_EscData[m_EscSeq] == 0x0D || m_EscData[m_EscSeq] == 0x0A) - { - m_EscData[m_EscSeq--] = 0; - } - - color = FindColorByName(&m_EscData[1]); - if (color != -1) - { - if (m_EscData[0] == ESC_SET_COLOR_NAME) - m_Color = gNamedColors[color].cid; - else - { - m_BackgroundColor = fl_rgb_color(gNamedColors[color].red, - gNamedColors[color].green, gNamedColors[color].blue); - m_Colors[0] = m_BackgroundColor; - redraw(); - Fl::check(); - } - } - m_EscSeq = 0; - } - } - else - { - /* Process the escape code */ - switch (m_EscData[0]) - { - /* Turn Cursor ON */ - case ESC_CURSOR_ON: - if (m_Cursor == 1) - break; - - /* Turn cursor on */ - m_Cursor = 1; - if (m_CurY >= bottom) - Scroll(); - XorCursor(); - break; - - /* Turn Cursor OFF */ - case ESC_CURSOR_OFF: - if (m_Cursor == 0) - break; - - /* Turn cursor off */ - m_Cursor = 0; - XorCursor(); - break; - - /* Test for Home Cursor */ - case ESC_CURSOR_HOME: - m_CurX = m_CurY = 0; - break; - - /* Test for Erase to EOL */ - case ESC_ERASE_EOL: - case ESC_CLEAR_EOL: - line = m_CurY >> 3; - for (col = m_CurX; col < 480; col++) - SetByte(line, col, 0); - break; - - case ESC_ERASE_SCREEN: - Clear(); - break; - - case ESC_ERASE_LINE: - line = m_CurY >> 3; - for (col = 0; col < 480; col++) - SetByte(line, col, 0); - break; - - case ESC_LOCK_SYS_LINE: - m_LabelLocked = TRUE; - break; - - case ESC_UNLOCK_SYS_LINE: - m_LabelLocked = FALSE; - break; - - case ESC_INS_LINE: - for (y = 199; y > m_CurY+8; y--) - //for (line = 24; line > (m_CurY >> 3); line--) - { - for (col = 0; col < 480; col++) - { - //SetByte(line, col, pixdata[line-1][col]); - pixdata[y][col] = pixdata[y-8][col]; - fl_color(m_Colors[pixdata[y][col]]); - drawpixel(col, y, 1); - } - } - line = m_CurY >> 3; - for (col = 0; col < 480; col++) - SetByte(line, col, 0); - break; - - case ESC_DEL_LINE: - for (y = m_CurY; y < bottom-8; y++) - //for (line = m_CurY >> 3; line < 24; line++) - { - for (col = 0; col < 480; col++) - { - //SetByte(line, col, pixdata[line+1][col]); - pixdata[y][col] = pixdata[y+8][col]; - fl_color(m_Colors[pixdata[y][col]]); - drawpixel(col, y, 1); - } - } - - for (col = 0; col < 480; col++) - SetByte(24, col, 0); - break; - - case ESC_CURSOR_UP: - m_CurY -= 8; - break; - - case ESC_CURSOR_DOWN: - m_CurY += 8; - break; - - case ESC_CURSOR_LEFT: - if (m_Width == 40) - m_CurX -= 12; - else - m_CurX -= 6; - break; - - case ESC_CURSOR_RIGHT: - if (m_Width == 40) - m_CurX += 12; - else - m_CurX += 6; - break; - - case ESC_START_REVERSE: - m_Reverse = 1; - break; - - case ESC_END_REVERSE: - m_Reverse = 0; - break; - - case ESC_LOCK_DISPLAY: - /* Not sure we need this */ - m_Locked = 1; - break; - - case ESC_UNLOCK_DISPLAY: - m_Locked = 0; - break; - - case ESC_WIDTH_40: - Clear(); - m_Width = 40; - break; - - case ESC_WIDTH_80: - Clear(); - m_Width = 80; - break; - - case ESC_HELP: - m_EscSeq = 0; - Help(); - break; - - /* Not sure what this ESC does exactly */ - case 0x58: - break; - - default: - printf("ESC 0x%02x\n", m_EscData[0]); - break; - } - - m_EscSeq = 0; - } - } - else if (data == 0x1B) - { - m_EscSeq = 1; - } - - /* Test for CLS */ - else if (data == 0x0C) - { - Clear(); - } - - /* Test for TAB */ - else if (data == 0x09) - { - } - - /* Test for BKSP */ - else if (data == 0x08) - { - if (m_CurX > 0) - { - if (m_Width == 40) - m_CurX -= 12; - else - m_CurX -= 6; - } - else - { - if (m_Width == 40) - m_CurX = 240-12; - else - m_CurX = 240-6; - m_CurY -= 8; - } - } - - /* Test for DEL. Nothing to do really */ - else if (data == 0x7F) - { - } - - /* Test for CR */ - else if (data == 0x0D) - { - /* Go to start of line */ - m_CurX = 0; - } - - /* Test for "HOME" cursor */ - else if (data == 0x0B) - { - m_CurX = m_CurY = 0; - } - - /* Test for End of Document */ - else if (data == 0x1A) - { - } - - /* Test for LF */ - else if (data == 0x0A) - { - /* Go to next line */ - m_CurY += 8; - } - - else if (data < ' ') - { - printf("Unhandled %0X\n", data); - } - - /* Draw the received byte */ - else //if (data >= ' '); - { - int addr, line, c, mem_index, column; - - if (m_CurY >= bottom) - Scroll(); - - addr = gStdRomDesc->sCharTable; - if (data > 127) - mem_index = addr + (128 - ' ') * 5 + (data - 128)*6; - else - mem_index = addr + (data - ' ') * 5; - - column = m_CurX; - line = m_CurY / 8; - - /* Draw the byte */ - for (c = 0; c < 5; c++) - { - if (m_Reverse) - { - if (m_Width == 40) - { - SetByte(line, column, ~gSysROM[mem_index]); - column++; - } - SetByte(line, column, ~gSysROM[mem_index++]); - } - else - { - if (m_Width == 40) - { - SetByte(line, column, gSysROM[mem_index]); - column++; - } - SetByte(line, column, gSysROM[mem_index++]); - } - column++; - } - - /* Now draw space between chars if needed */ - if (data > 127) - { - if (m_Reverse) - { - if (m_Width == 40) - { - SetByte(line, column, ~gSysROM[mem_index]); - } - SetByte(line, column, ~gSysROM[mem_index++]); - } - else - { - if (m_Width == 40) - { - SetByte(line, column, gSysROM[mem_index]); - } - SetByte(line, column, gSysROM[mem_index++]); - } - } - else - { - if (m_Reverse) - { - if (m_Width == 40) - SetByte(line, column, 0xFF); - SetByte(line, column, 0xFF); - } - else - { - if (m_Width == 40) - SetByte(line, column, 0x0); - SetByte(line, column, 0); - } - } - - /* Advance to the next character */ - if (m_Width == 40) - m_CurX += 12; - else - m_CurX += 6; - - if (m_CurX >= 480) - { - m_CurX = 0; - m_CurY += 8; - } - - /* Draw cursor if it is on */ - if (m_Cursor) - { - XorCursor(); - } - } -} - -void VTTDockVid::XorCursor(void) -{ - int col = m_CurX; - int num, x,y; - - if (m_CurY > 192) - return; - - if (m_Width == 40) - num = 12; - else - num = 6; - - window()->make_current(); - - for (x = 0; x < num; x++) - { - for (y = m_CurY; y < m_CurY + 8; y++) - { - pixdata[y][col] = ~pixdata[y][col]; - fl_color(m_Colors[pixdata[y][col]]); - drawpixel(col,y,1); - } - col++; - } -} - -void VTTDockVid::Scroll(void) -{ - int y, col, color, lastcolor = -1; - int bottom; - - if (m_LabelLocked) - bottom = 200 - 8; - else - bottom = 200; - - /* Test if at bottom of display */ - if (m_CurY >= bottom) - { - /* We need to perform a scroll */ - for (y = 8; y < bottom; y++) - { - for (col = 0; col < 480; col++) - { - color = pixdata[y][col]; - if (color != 0 || pixdata[y-8][col] != 0) - { - pixdata[y-8][col] = color; - if (lastcolor != color) - { - fl_color(m_Colors[color]); - lastcolor = color; - } - drawpixel(col,y-8,1); - } - } - } - - /* Now zero out the bottom line */ - for (col = 0; col < 480; col++) - { - if (m_LabelLocked) - SetByte(23,col,0); - else - SetByte(24,col,0); - } - - m_CurY -= 8; - - Fl::check(); - } -} - -int VTTDockVid::handle(int event) -{ - return gpDisp->handle(event); -} - -int VTTDockVid::FindColorByName(char *pName) -{ - int x; - - /* Search all named colors for a match */ - for (x = 0; x < gColorCount; x++) - { - if (strcasecmp(gNamedColors[x].pName, pName) == 0) - { - return x; - } - } - - return -1; -} - -void VTTDockVid::Help(void) -{ - int x, c, len; - - Clear(); - - /* Display all named colors */ - for (x = 0; x < gColorCount; x++) - { - len = strlen(gNamedColors[x].pName); - if (m_CurX + len*6 > 480) - { - WriteData(0x0D); - WriteData(0x0A); - } - - for (c = 0; c < len; c++) - WriteData(gNamedColors[x].pName[c]); - if (x+1 != gColorCount) - { - if (m_CurX != 0) - WriteData(','); - if (m_CurX != 0) - WriteData(' '); - } - } -} - +/* tdockvid.cpp */ + +/* $Id$ */ + +/* + * Copyright 2015 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include + +#include + +#include "FLU/Flu_Button.h" +#include "FLU/Flu_Return_Button.h" +#include "FLU/flu_pixmaps.h" + +#include +#include +#include +#ifndef WIN32 +#include +#include +#endif + +#include "VirtualT.h" +#include "display.h" +#include "tdockvid.h" +#include "m100emu.h" +#include "io.h" +#include "file.h" +#include "setup.h" +#include "periph.h" +#include "memory.h" +#include "memedit.h" +#include "cpuregs.h" +#include "rememcfg.h" +#include "lpt.h" +#include "fl_action_icon.h" +#include "clock.h" +#include "fileview.h" +#include "romstrings.h" +#include "remote.h" +#include "tpddserverlog.h" + + +extern "C" { +extern RomDescription_t gM100_Desc; +extern RomDescription_t gM200_Desc; +extern RomDescription_t gN8201_Desc; +extern RomDescription_t gM10_Desc; +//JV +//extern RomDescription_t gN8300_Desc; +extern RomDescription_t gKC85_Desc; + +extern RomDescription_t *gStdRomDesc; +extern int gRomSize; +extern int gMaintCount; +extern int gOsDelay; +} + +#ifdef _MSC_VER +//not #if defined(_WIN32) || defined(_WIN64) because we have strncasecmp in mingw +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#endif + +extern int MultFact; +extern int DisplayMode; +extern int Fullscreen; +extern int SolidChars; +extern int DispHeight; +extern int gRectsize; +extern int gXoffset; +extern int gYoffset; +extern int gSimKey; +extern int gFrameColor; +extern int gDetailColor; +extern int gBackgroundColor; +extern int gPixelColor; +extern int gLabelColor; +extern int gConsoleDebug; + +#ifndef WIN32 +#define min(a,b) ((a)<(b) ? (a):(b)) +#endif +#ifdef WIN32 +extern "C" +{ +int strcasecmp(const char* s1, const char* s2); +} +#endif + +extern T100_Disp* gpDisp; + +typedef struct namedColors +{ + const char * pName; + unsigned char cid; + unsigned char red; + unsigned char green; + unsigned char blue; +} namedColors_t; + +static namedColors_t gNamedColors[] = { +#include "colors.h" +}; +static int gColorCount = sizeof(gNamedColors) / sizeof(namedColors_t); + +/* +======================================================= +T100:Disp: This is the class construcor +======================================================= +*/ +VTTDockVid::VTTDockVid(int x, int y, int w, int h) : + Fl_Widget(x, y, w, h) +{ + int c, red, green, blue; + + m_FrameColor = gFrameColor; + m_DetailColor = gDetailColor; + m_BackgroundColor = gBackgroundColor; + m_PixelColor = gPixelColor; + m_LabelColor = gLabelColor; + m_HaveMouse = FALSE; + m_LabelLocked = FALSE; + + memset(pixdata, 0, 200*480); + + m_MyFocus = 0; + m_CurX = 0; + m_CurY = 0; + m_EscSeq = 0; + m_Reverse = 0; + m_Locked = 0; + m_Width = 40; + m_Color = 255; + + m_Colors[1] = FL_DARK_RED; + m_Colors[2] = FL_DARK_GREEN; + m_Colors[3] = FL_DARK_YELLOW; + m_Colors[4] = FL_DARK_BLUE; + m_Colors[5] = FL_DARK_MAGENTA; + m_Colors[6] = FL_DARK_CYAN; + m_Colors[7] = FL_LIGHT1; + + m_Colors[8] = FL_DARK2; + m_Colors[9] = FL_RED; + m_Colors[10] = FL_GREEN; + m_Colors[11] = FL_YELLOW; + m_Colors[12] = FL_BLUE; + m_Colors[13] = FL_MAGENTA; + m_Colors[14] = FL_CYAN; + m_Colors[15] = FL_WHITE; + + /* 6x6x6 Color Cube */ + c = 16; + for (red = 0; red <=255; red += 51) + for (green = 0; green <=255; green += 51) + for (blue = 0; blue <=255; blue += 51) + { + m_Colors[c++] = fl_rgb_color(red , green, blue); + } + + /* Gray scale */ + red = 255; + for (c = 254; c >= 232; c--) + { + m_Colors[c] = fl_rgb_color(red, red, red); + red -= 11; + } + + m_Colors[0] = gBackgroundColor; + m_Colors[255] = gPixelColor; + + MultFact = 2; + DisplayMode = 1; + SolidChars = 0; + DispHeight = 64; + gRectsize = 2; + + m_BezelTop = m_BezelLeft = m_BezelBottom = m_BezelRight = 0; + m_BezelTopH = m_BezelLeftW = m_BezelBottomH = m_BezelRightW = 0; + + CalcScreenCoords(); +} + +VTTDockVid::~VTTDockVid() +{ +} + +/* +================================================================= +Clear: This routine clears the "LCD" +================================================================= +*/ +void VTTDockVid::Clear(void) +{ + int bottom; + + if (m_LabelLocked) + bottom = 200-8; + else + bottom = 200; + memset(pixdata, 0, bottom*480); + + m_CurX = m_CurY = 0; + redraw(); + Fl::check(); +} + +/* +================================================================= +drawpixel: This routine is called by the system to draw a single + black pixel on the "LCD". +================================================================= +*/ +// Draw the black pixels on the LCD +__inline void VTTDockVid::drawpixel(int x, int y, int color) +{ + // Check if the pixel color is black and draw if it is + if (color) + { + fl_rectf(x*MultFact + gXoffset,y*MultFact + gYoffset, + gRectsize, gRectsize); + } +} + +/* +======================================================= +Set the screen size multiplication factor +======================================================= +*/ +void VTTDockVid::SetMultFact(int multfact) +{ + MultFact = multfact; + ::MultFact = multfact; + gRectsize = multfact; +} + +/* +======================================================= +Calculate the xoffset, yoffset, border locations, etc. +======================================================= +*/ +void VTTDockVid::CalcScreenCoords(void) +{ + // Calculatet the pixel rectangle size + ::gRectsize = MultFact; + if (::gRectsize == 0) + ::gRectsize = 1; + + // Calculate xoffset and yoffset + if (Fullscreen) + { + ::gXoffset = parent()->w() / 2 - 240 * MultFact; + ::gYoffset = (parent()->h() - MENU_HEIGHT - 20 - 200 * MultFact) / 3 + MENU_HEIGHT+1; + } + else + { + ::gXoffset = 5; + ::gYoffset = MENU_HEIGHT+5; + } + + gRectsize = ::gRectsize; + gXoffset = ::gXoffset; + gYoffset = ::gYoffset; + + // If the display is framed, then calculate the frame coords + if (DisplayMode && 0) + { + // Calculate the Bezel location + int wantedH = 20; + int wantedW = 40; + // int topH, bottomH, leftW, rightW; + int bottomSpace; + int rightSpace; + + // Calculate the top height of the Bezel + m_HasTopChassis = TRUE; + if (gYoffset-1 - MENU_HEIGHT-1 >= wantedH + 5) + m_BezelTopH = wantedH; + else + { + // Test if there's room for both Bezel and chassis detail + if (gYoffset > 6) + m_BezelTopH = gYoffset - MENU_HEIGHT - 1 - 6; + else + { + m_BezelTopH = gYoffset - MENU_HEIGHT - 1 - 1; + m_HasTopChassis = FALSE; + } + } + m_BezelTop = gYoffset - m_BezelTopH - 1; + + // Calculate the bottom height of the Bezel + m_BezelBottom = gYoffset + 200 * MultFact + 1; + bottomSpace = parent()->h() - m_BezelBottom - 20; + m_HasBottomChassis = TRUE; + if (bottomSpace >= wantedH + 5) + m_BezelBottomH = wantedH; + else + { + m_BezelBottomH = bottomSpace; + m_HasBottomChassis = FALSE; + } + + // Calculate the left Bezel border width + m_HasLeftChassis = TRUE; + if (gXoffset-1 >= wantedW + 5) + m_BezelLeftW = wantedW; + else + { + // Test if there's room for Bezel plus chassis + if (gXoffset > 6) + m_BezelLeftW = gXoffset - 6; + else + { + m_BezelLeftW = gXoffset - 1; + m_HasLeftChassis = FALSE; + } + } + m_BezelLeft = gXoffset - m_BezelLeftW - 1; + + // Calculate the Bezel right width + m_BezelRight = gXoffset + 240 * MultFact + 1; + rightSpace = w() - m_BezelRight; + m_HasRightChassis = TRUE; + if (rightSpace >= wantedW + 5) + m_BezelRightW = wantedW; + else + { + // Test if there's room for Bezel plus chassis + if (rightSpace > 5) + m_BezelRightW = rightSpace - 5; + else + { + m_BezelRightW = rightSpace; + m_HasRightChassis = FALSE; + } + } + } +} + +/* +================================================================= +draw_static: This routine draws the static portions of the LCD, + such as erasing the background, drawing function + key labls, etc. +================================================================= +*/ +void VTTDockVid::draw_static() +{ + int c; + int width; + int x_pos, inc, start, y_pos; + int xl_start, xl_end, xr_start, xr_end; + int num_labels; + + // Draw gray "screen" + fl_color(m_BackgroundColor); + fl_rectf(x(),y(),w(),h()); + + return; + + /* Check if the user wants the display "framed" */ + if (DisplayMode == 1) + { + // Color for outer border + fl_color(m_DetailColor); + + // Draw border along the top + if (m_HasTopChassis) + fl_rectf(x(),y(),w(),m_BezelTop - MENU_HEIGHT - 1); + + // Draw border along the bottom + if (m_HasBottomChassis) + fl_rectf(x(),m_BezelBottom + m_BezelBottomH,w(),parent()->h() - m_BezelBottom - m_BezelBottomH - 20); + + // Draw border along the left + if (m_HasLeftChassis) + fl_rectf(x(),y(),m_BezelLeft,h()); + + // Draw border along the right + if (m_HasRightChassis) + fl_rectf(m_BezelRight + m_BezelRightW,y(),w()-m_BezelRight,h()); + + // Color for inner border + fl_color(m_FrameColor); + + // Draw border along the top + if (m_BezelTopH > 0) + fl_rectf(m_BezelLeft,m_BezelTop,m_BezelRight - m_BezelLeft + m_BezelRightW,m_BezelTopH); + + // Draw border along the bottom + if (m_BezelBottomH > 0) + fl_rectf(m_BezelLeft,m_BezelBottom,m_BezelRight - m_BezelLeft + m_BezelRightW,m_BezelBottomH); + + // Draw border along the left + if (m_BezelLeftW > 0) + fl_rectf(m_BezelLeft, m_BezelTop, m_BezelLeftW, m_BezelBottom - m_BezelTop + m_BezelBottomH); + + // Draw border along the right + if (m_BezelRightW > 0) + fl_rectf(m_BezelRight,m_BezelTop, m_BezelRightW, m_BezelBottom - m_BezelTop + m_BezelBottomH); + + +#ifdef ZIPIT_Z2 + width = 320; +#else + width = 240 * MultFact; +#endif + num_labels = gModel == MODEL_PC8201 ? 5 : 8; + inc = width / num_labels; + start = gXoffset + width/16 - 2 * (5- (MultFact > 5? 5 : MultFact)); + fl_color(m_LabelColor); + fl_font(FL_COURIER,12); + char text[3] = "F1"; + //y_pos = h()+20; + y_pos = m_BezelBottom + 13; //y()+DispHeight*MultFact+40; + xl_start = 2*MultFact; + xl_end = 7*MultFact; + + xr_start = 12 + 2*MultFact; + xr_end = 12 + 7*MultFact; + + // Draw function key labels + for (c = 0; c < num_labels; c++) + { + // Draw text + x_pos = start + inc*c; + text[1] = c + '1'; + fl_draw(text, x_pos, y_pos); + + if (MultFact != 1) + { + // Draw lines to left + fl_line(x_pos - xl_start, y_pos-2, x_pos - xl_end, y_pos-2); + fl_line(x_pos - xl_start, y_pos-7, x_pos - xl_end, y_pos-7); + fl_line(x_pos - xl_end, y_pos-2, x_pos - xl_end, y_pos-7); + + // Draw lines to right + fl_line(x_pos + xr_start, y_pos-2, x_pos + xr_end, y_pos-2); + fl_line(x_pos + xr_start, y_pos-7, x_pos + xr_end, y_pos-7); + fl_line(x_pos + xr_end, y_pos-2, x_pos + xr_end, y_pos-7); + } + } + } +} + +/* +================================================================= +draw: This routine draws the entire LCD. This is a member + function of Fl_Window. +================================================================= +*/ +void VTTDockVid::draw() +{ + /* Draw static background stuff */ + draw_static(); + + /* Draw the pixels */ + draw_pixels(); +} + +/* +================================================================= +draw_pixels: This routine draws the pixels on the display. +================================================================= +*/ +void VTTDockVid::draw_pixels() +{ + int x=0; + int line; + uchar value; + int color; + + window()->make_current(); + + for (line = 0; line < 200; line++) + { + for (x = 0; x < 480; x++) + { + value = pixdata[line][x]; + + // Erase line so it is grey, then fill in with black where needed + if ((line & 0x07) == 0) + { + fl_color(m_BackgroundColor); + fl_rectf(x*MultFact + gXoffset,line*MultFact + + gYoffset,gRectsize,8*MultFact); + } + if (value == 0) + continue; + + // Draw the pixels + color = m_Colors[value]; + fl_color(color); + drawpixel(x,line,1); + } + } +} + +/* +================================================================================ +SetByte: Updates the LCD with a byte of data as written from the I/O + interface from the 8085. +================================================================================ +*/ +void VTTDockVid::SetByte(int line, int col, uchar value) +{ + int y; + + if (line > 24 || col > 479) + return; + if (line < 0 || col < 0) + return; + + // Check if LCD already has the value being requested + //if (pixdata[line][col] == value) + // return; + + // Load new value into lcd "RAM" + y = line << 3; + //pixdata[line][col] = value; + + pixdata[y++][col] = value&0x01 ? m_Color : 0; + pixdata[y++][col] = value&0x02 ? m_Color : 0; + pixdata[y++][col] = value&0x04 ? m_Color : 0; + pixdata[y++][col] = value&0x08 ? m_Color : 0; + pixdata[y++][col] = value&0x10 ? m_Color : 0; + pixdata[y++][col] = value&0x20 ? m_Color : 0; + pixdata[y++][col] = value&0x40 ? m_Color : 0; + pixdata[y++][col] = value&0x80 ? m_Color : 0; + + // Calcluate y position of byte + y = line << 3; + + // Set the display + window()->make_current(); + + fl_color(m_BackgroundColor); + fl_rectf(col*MultFact + gXoffset, y*MultFact + + gYoffset, gRectsize,MultFact<<3); + + if (value == 0) + return; + + fl_color(m_Colors[m_Color]); + + for (y = line << 3; y < (line+1) << 3; y++) + drawpixel(col,y,pixdata[y][col]); +} + +/* +================================================================================ +WriteData: Routine that receives data from the VDock interface when the + Model T sends data / commands to our device ID. +================================================================================ +*/ +void VTTDockVid::WriteData(uchar data) +{ + int line, col, y; + int color, bottom; + +#if 0 + if (m_EscSeq) + { + printf("%c(%02x), X=%d, Y=%d\n", data, data, m_CurX, m_CurY); + } + else if (data == 0x1B) + printf("ESC "); +#if 1 + else if (data <= ' ') + printf("%02X, X=%d, Y=%d\n", data, m_CurX, m_CurY); + else + printf("%c, X=%d, Y=%d\n", data, m_CurX, m_CurY); +#endif +#endif + + window()->make_current(); + + /* Calculate bottom pixel value based on m_LabelLocked */ + if (m_LabelLocked) + bottom = 200-8; + else + bottom = 200; + + /* Test if we are processing an ESC Sequence */ + if (m_EscSeq) + { + /* Add the byte to the escape sequence */ + m_EscData[m_EscSeq++ - 1] = data; + + /* Test if time to process the ESC sequence */ + if (m_EscData[0] == 'Y') + { + //printf("ESCY:%d\n", m_EscSeq); + if (m_EscSeq == 4) + { + /* Process the cursor position sequence */ + m_CurX = (m_EscData[2] - 0x20) * 6; + if (m_Width == 40) + m_CurX <<= 1; + m_CurY = (m_EscData[1] - 0x20) * 8; + if (m_CurX < 0) + m_CurX = 0; + if (m_CurY < 0) + m_CurY = 0; + if (m_CurX > 474) + m_CurX = 474; + if (m_CurY > 192) + m_CurY = 192; + m_EscSeq = 0; + } + } + else if (m_EscData[0] == ESC_SET_COLOR) + { + if (m_EscSeq == 3) + { + m_Color = (unsigned char) m_EscData[1]; + m_EscSeq = 0; + } + } + else if ((m_EscData[0] == ESC_SET_COLOR_NAME) || m_EscData[0] == ESC_SET_BG_NAME) + { + if (data == 0x0A) + { + /* Do a color name lookup */ + /* First remove the 0D and 0A */ + m_EscSeq -= 2; + while (m_EscData[m_EscSeq] == 0x0D || m_EscData[m_EscSeq] == 0x0A) + { + m_EscData[m_EscSeq--] = 0; + } + + color = FindColorByName(&m_EscData[1]); + if (color != -1) + { + if (m_EscData[0] == ESC_SET_COLOR_NAME) + m_Color = gNamedColors[color].cid; + else + { + m_BackgroundColor = fl_rgb_color(gNamedColors[color].red, + gNamedColors[color].green, gNamedColors[color].blue); + m_Colors[0] = m_BackgroundColor; + redraw(); + Fl::check(); + } + } + m_EscSeq = 0; + } + } + else + { + /* Process the escape code */ + switch (m_EscData[0]) + { + /* Turn Cursor ON */ + case ESC_CURSOR_ON: + if (m_Cursor == 1) + break; + + /* Turn cursor on */ + m_Cursor = 1; + if (m_CurY >= bottom) + Scroll(); + XorCursor(); + break; + + /* Turn Cursor OFF */ + case ESC_CURSOR_OFF: + if (m_Cursor == 0) + break; + + /* Turn cursor off */ + m_Cursor = 0; + XorCursor(); + break; + + /* Test for Home Cursor */ + case ESC_CURSOR_HOME: + m_CurX = m_CurY = 0; + break; + + /* Test for Erase to EOL */ + case ESC_ERASE_EOL: + case ESC_CLEAR_EOL: + line = m_CurY >> 3; + for (col = m_CurX; col < 480; col++) + SetByte(line, col, 0); + break; + + case ESC_ERASE_SCREEN: + Clear(); + break; + + case ESC_ERASE_LINE: + line = m_CurY >> 3; + for (col = 0; col < 480; col++) + SetByte(line, col, 0); + break; + + case ESC_LOCK_SYS_LINE: + m_LabelLocked = TRUE; + break; + + case ESC_UNLOCK_SYS_LINE: + m_LabelLocked = FALSE; + break; + + case ESC_INS_LINE: + for (y = 199; y > m_CurY+8; y--) + //for (line = 24; line > (m_CurY >> 3); line--) + { + for (col = 0; col < 480; col++) + { + //SetByte(line, col, pixdata[line-1][col]); + pixdata[y][col] = pixdata[y-8][col]; + fl_color(m_Colors[pixdata[y][col]]); + drawpixel(col, y, 1); + } + } + line = m_CurY >> 3; + for (col = 0; col < 480; col++) + SetByte(line, col, 0); + break; + + case ESC_DEL_LINE: + for (y = m_CurY; y < bottom-8; y++) + //for (line = m_CurY >> 3; line < 24; line++) + { + for (col = 0; col < 480; col++) + { + //SetByte(line, col, pixdata[line+1][col]); + pixdata[y][col] = pixdata[y+8][col]; + fl_color(m_Colors[pixdata[y][col]]); + drawpixel(col, y, 1); + } + } + + for (col = 0; col < 480; col++) + SetByte(24, col, 0); + break; + + case ESC_CURSOR_UP: + m_CurY -= 8; + break; + + case ESC_CURSOR_DOWN: + m_CurY += 8; + break; + + case ESC_CURSOR_LEFT: + if (m_Width == 40) + m_CurX -= 12; + else + m_CurX -= 6; + break; + + case ESC_CURSOR_RIGHT: + if (m_Width == 40) + m_CurX += 12; + else + m_CurX += 6; + break; + + case ESC_START_REVERSE: + m_Reverse = 1; + break; + + case ESC_END_REVERSE: + m_Reverse = 0; + break; + + case ESC_LOCK_DISPLAY: + /* Not sure we need this */ + m_Locked = 1; + break; + + case ESC_UNLOCK_DISPLAY: + m_Locked = 0; + break; + + case ESC_WIDTH_40: + Clear(); + m_Width = 40; + break; + + case ESC_WIDTH_80: + Clear(); + m_Width = 80; + break; + + case ESC_HELP: + m_EscSeq = 0; + Help(); + break; + + /* Not sure what this ESC does exactly */ + case 0x58: + break; + + default: + printf("ESC 0x%02x\n", m_EscData[0]); + break; + } + + m_EscSeq = 0; + } + } + else if (data == 0x1B) + { + m_EscSeq = 1; + } + + /* Test for CLS */ + else if (data == 0x0C) + { + Clear(); + } + + /* Test for TAB */ + else if (data == 0x09) + { + } + + /* Test for BKSP */ + else if (data == 0x08) + { + if (m_CurX > 0) + { + if (m_Width == 40) + m_CurX -= 12; + else + m_CurX -= 6; + } + else + { + if (m_Width == 40) + m_CurX = 240-12; + else + m_CurX = 240-6; + m_CurY -= 8; + } + } + + /* Test for DEL. Nothing to do really */ + else if (data == 0x7F) + { + } + + /* Test for CR */ + else if (data == 0x0D) + { + /* Go to start of line */ + m_CurX = 0; + } + + /* Test for "HOME" cursor */ + else if (data == 0x0B) + { + m_CurX = m_CurY = 0; + } + + /* Test for End of Document */ + else if (data == 0x1A) + { + } + + /* Test for LF */ + else if (data == 0x0A) + { + /* Go to next line */ + m_CurY += 8; + } + + else if (data < ' ') + { + printf("Unhandled %0X\n", data); + } + + /* Draw the received byte */ + else //if (data >= ' '); + { + int addr, line, c, mem_index, column; + + if (m_CurY >= bottom) + Scroll(); + + addr = gStdRomDesc->sCharTable; + if (data > 127) + mem_index = addr + (128 - ' ') * 5 + (data - 128)*6; + else + mem_index = addr + (data - ' ') * 5; + + column = m_CurX; + line = m_CurY / 8; + + /* Draw the byte */ + for (c = 0; c < 5; c++) + { + if (m_Reverse) + { + if (m_Width == 40) + { + SetByte(line, column, ~gSysROM[mem_index]); + column++; + } + SetByte(line, column, ~gSysROM[mem_index++]); + } + else + { + if (m_Width == 40) + { + SetByte(line, column, gSysROM[mem_index]); + column++; + } + SetByte(line, column, gSysROM[mem_index++]); + } + column++; + } + + /* Now draw space between chars if needed */ + if (data > 127) + { + if (m_Reverse) + { + if (m_Width == 40) + { + SetByte(line, column, ~gSysROM[mem_index]); + } + SetByte(line, column, ~gSysROM[mem_index++]); + } + else + { + if (m_Width == 40) + { + SetByte(line, column, gSysROM[mem_index]); + } + SetByte(line, column, gSysROM[mem_index++]); + } + } + else + { + if (m_Reverse) + { + if (m_Width == 40) + SetByte(line, column, 0xFF); + SetByte(line, column, 0xFF); + } + else + { + if (m_Width == 40) + SetByte(line, column, 0x0); + SetByte(line, column, 0); + } + } + + /* Advance to the next character */ + if (m_Width == 40) + m_CurX += 12; + else + m_CurX += 6; + + if (m_CurX >= 480) + { + m_CurX = 0; + m_CurY += 8; + } + + /* Draw cursor if it is on */ + if (m_Cursor) + { + XorCursor(); + } + } +} + +void VTTDockVid::XorCursor(void) +{ + int col = m_CurX; + int num, x,y; + + if (m_CurY > 192) + return; + + if (m_Width == 40) + num = 12; + else + num = 6; + + window()->make_current(); + + for (x = 0; x < num; x++) + { + for (y = m_CurY; y < m_CurY + 8; y++) + { + pixdata[y][col] = ~pixdata[y][col]; + fl_color(m_Colors[pixdata[y][col]]); + drawpixel(col,y,1); + } + col++; + } +} + +void VTTDockVid::Scroll(void) +{ + int y, col, color, lastcolor = -1; + int bottom; + + if (m_LabelLocked) + bottom = 200 - 8; + else + bottom = 200; + + /* Test if at bottom of display */ + if (m_CurY >= bottom) + { + /* We need to perform a scroll */ + for (y = 8; y < bottom; y++) + { + for (col = 0; col < 480; col++) + { + color = pixdata[y][col]; + if (color != 0 || pixdata[y-8][col] != 0) + { + pixdata[y-8][col] = color; + if (lastcolor != color) + { + fl_color(m_Colors[color]); + lastcolor = color; + } + drawpixel(col,y-8,1); + } + } + } + + /* Now zero out the bottom line */ + for (col = 0; col < 480; col++) + { + if (m_LabelLocked) + SetByte(23,col,0); + else + SetByte(24,col,0); + } + + m_CurY -= 8; + + Fl::check(); + } +} + +int VTTDockVid::handle(int event) +{ + return gpDisp->handle(event); +} + +int VTTDockVid::FindColorByName(char *pName) +{ + int x; + + /* Search all named colors for a match */ + for (x = 0; x < gColorCount; x++) + { + if (strcasecmp(gNamedColors[x].pName, pName) == 0) + { + return x; + } + } + + return -1; +} + +void VTTDockVid::Help(void) +{ + int x, c, len; + + Clear(); + + /* Display all named colors */ + for (x = 0; x < gColorCount; x++) + { + len = strlen(gNamedColors[x].pName); + if (m_CurX + len*6 > 480) + { + WriteData(0x0D); + WriteData(0x0A); + } + + for (c = 0; c < len; c++) + WriteData(gNamedColors[x].pName[c]); + if (x+1 != gColorCount) + { + if (m_CurX != 0) + WriteData(','); + if (m_CurX != 0) + WriteData(' '); + } + } +} + diff --git a/src/tpddserver.cpp b/src/tpddserver.cpp old mode 100644 new mode 100755 index a350181..eb7c1d8 --- a/src/tpddserver.cpp +++ b/src/tpddserver.cpp @@ -1,2940 +1,2946 @@ -/* tpddserver.cpp */ - -/* $Id$ */ - -/* - * Copyright 2013 Ken Pettit - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -//#include -#include -#include -#ifdef _WIN32 -#include -#include -#else -#include -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include "FLU/Flu_File_Chooser.h" - -#include "VirtualT.h" -#include "m100emu.h" -#include "tpddserver.h" -#include "tpddserverlog.h" -#include "serial.h" -#include "display.h" -#include "cpuregs.h" -#include "periph.h" -#include "memedit.h" -#include "fileview.h" - -#define COLOR_BG (gMidnight ? FL_BLACK : fl_rgb_color(192, 192, 192)) -#define COLOR_BG_INPUT (gMidnight ? FL_BLACK : FL_WHITE) -#define COLOR_FG (gMidnight ? FL_WHITE : FL_BLACK) -#define COLOR_TAB_INACTIVE_BG (gMidnight ? fl_rgb_color(32,32,32) : fl_rgb_color(192,192,192)) -#define COLOR_TAB_INACTIVE_FG (gMidnight ? fl_rgb_color(192,192,192) : FL_BLACK) - -enum { - TPDD_STATE_IDLE = 0, - TPDD_STATE_Z, - TPDD_STATE_OPCODE, - TPDD_STATE_LEN, - TPDD_STATE_READ_BYTES, - TPDD_STATE_READ_CHECKSUM, - TPDD_STATE_M, - TPDD_STATE_M1, - TPDD_STATE_R, - TPDD_STATE_CMDLINE, - TPDD_STATE_EXEC -}; - -// =============================================== -// Extern "C" linkage items -// =============================================== -extern "C" -{ -extern volatile UINT64 cycles; -extern volatile DWORD rst7cycles; - -#ifdef WIN32 -int strcasecmp(const char* s1, const char* s2); -#endif -} -extern int gMidnight; - -/* -====================================================== -Structure for the setup GUI controls. -====================================================== -*/ -typedef struct tpddserver_ctrl_struct -{ - Fl_Input* pRootDir; // Pointer to root dir input - char sRootDir[512]; - Fl_Button* pTpddDir; // Create TPDD directory listing -} tpddserver_ctrl_t; - -// =============================================== -// Extern and global variables -// =============================================== -extern Fl_Preferences virtualt_prefs; -static Fl_Window* gtcw = NULL; -tpddserver_ctrl_t gTsCtrl; - -// Define the array of NADSBox commands -VT_NADSCmd_t VTTpddServer::m_Cmds[] = { - { "cd", &VTTpddServer::CmdlineCd, "cd path - Change Directory" }, -// { "copy", &VTTpddServer::CmdlineCopy }, -// { "date", &VTTpddServer::CmdlineDate }, -// { "del", &VTTpddServer::CmdlineDel }, - { "dir", &VTTpddServer::CmdlineDir, "dir [-dw] [file] - Directory" }, - { "help", &VTTpddServer::CmdlineHelp, "help [command] - Display help" }, -// { "info", &VTTpddServer::CmdlineInfo }, -// { "mkdir", &VTTpddServer::CmdlineMkdir }, - { "pwd", &VTTpddServer::CmdlinePwd, "pwd - Show working directory" }, -// { "ren", &VTTpddServer::CmdlineRen }, -// { "rmdir", &VTTpddServer::CmdlineRmdir }, -// { "time", &VTTpddServer::CmdlineTime }, -// { "trace", &VTTpddServer::CmdlineTrace }, -// { "type", &VTTpddServer::CmdlineType }, - { "ver", &VTTpddServer::CmdlineVer, "ver - Show emulation version" }, -}; -int VTTpddServer::m_cmdCount = sizeof(VTTpddServer::m_Cmds) / sizeof(VT_NADSCmd_t); - -// Define the array of Linux alias commands -VT_NADSCmd_t VTTpddServer::m_LinuxCmds[] = { - { "cat", &VTTpddServer::CmdlineType, "cat - Alias for 'type'" }, - { "cp", &VTTpddServer::CmdlineCopy, "cp - Alias for 'copy'" }, - { "ls", &VTTpddServer::CmdlineDir, "ls - Alias for 'dir -w'" }, - { "ll", &VTTpddServer::CmdlineDir, "ll - Alias for 'dir'" }, - { "more", &VTTpddServer::CmdlineType, "more - Alias for 'type'" }, - { "mv", &VTTpddServer::CmdlineRen, "mv - Alias for 'ren'" }, - { "rm", &VTTpddServer::CmdlineDel, "rm - Alias for 'del'" }, -}; -int VTTpddServer::m_linuxCmdCount = sizeof(VTTpddServer::m_LinuxCmds) / sizeof(VT_NADSCmd_t); - -// Define the array of Linux alias commands -VTTpddOpcodeFunc VTTpddServer::m_tpddOpcodeHandlers[] = { - &VTTpddServer::OpcodeDir, // 0x00 - &VTTpddServer::OpcodeOpen, // 0x01 - &VTTpddServer::OpcodeClose, // 0x02 - &VTTpddServer::OpcodeRead, // 0x03 - &VTTpddServer::OpcodeWrite, // 0x04 - &VTTpddServer::OpcodeDelete, // 0x05 - &VTTpddServer::OpcodeFormat, // 0x06 - &VTTpddServer::OpcodeDriveStatus, // 0x07 - &VTTpddServer::OpcodeId, // 0x08 - &VTTpddServer::OpcodeSeek, // 0x09 - &VTTpddServer::OpcodeTell, // 0x0A - &VTTpddServer::OpcodeSetExtended, // 0x0B - &VTTpddServer::OpcodeDriveCond, // 0x0C - &VTTpddServer::OpcodeRename, // 0x0D - &VTTpddServer::OpcodeQueryExtended, // 0x0E - &VTTpddServer::OpcodeCondensedList, // 0x0F -}; - -int VTTpddServer::m_tpddOpcodeCount = sizeof(VTTpddServer::m_tpddOpcodeHandlers) / sizeof(VTNADSCmdlineFunc); - -/* -============================================================================ -Callback routine for the File Viewer window -============================================================================ -*/ -void cb_tcwin (Fl_Widget* w, void*) -{ - // Hide the window - gtcw->hide(); - - // Delete the window and set to NULL - delete gtcw; - gtcw = NULL; -} - -/* -============================================================================ -Callback routine to read TPDD / NADSBox directory -============================================================================ -*/ -static void cb_TpddDir(Fl_Widget* w, void*) -{ - Flu_File_Chooser* fc; - char fc_path[256]; - int count; - const char *filename; - - // Create chooser window to pick file - strncpy(fc_path, gTsCtrl.pRootDir->value(), sizeof(fc_path)); - fl_cursor(FL_CURSOR_WAIT); - fc = new Flu_File_Chooser(fc_path, "", Flu_File_Chooser::DIRECTORY, "Choose Root Directory"); - fl_cursor(FL_CURSOR_DEFAULT); - fc->preview(0); - fc->show(); - - // Show Chooser window - while (fc->visible()) - Fl::wait(); - - count = fc->count(); - if (count == 0) - { - delete fc; - return; - } - - // Get Filename - filename = fc->value(); - if (filename == 0) - { - delete fc; - return; - } - - // Copy the new root - strncpy(gTsCtrl.sRootDir, filename, sizeof(gTsCtrl.sRootDir)); - gTsCtrl.pRootDir->value(gTsCtrl.sRootDir); - - delete fc; -} - -/* -============================================================================ -Callback routine for the cancel button -============================================================================ -*/ -static void cb_tpdd_cancel(Fl_Widget* w, void*) -{ - // Hide and delete the window - gtcw->hide(); - delete gtcw; - gtcw = NULL; -} - -/* -============================================================================ -Callback routine for the Ok button -============================================================================ -*/ -static void cb_tpdd_ok(Fl_Widget* w, void* pOpaque) -{ - // hide the window - gtcw->hide(); - - // Get the updated root directory - const char *pDir = gTsCtrl.pRootDir->value(); - - VTTpddServer* pServer = (VTTpddServer *) ser_get_tpdd_context(); - strcpy(gTsCtrl.sRootDir, pDir); - pServer->RootDir(pDir); - - // Delete the window - delete gtcw; - gtcw = NULL; -} - -/* -============================================================================ -Routine to create the TPDD Server configuration window -============================================================================ -*/ -void tpdd_server_config(void) -{ - Fl_Box* o; - Fl_Button* b; - - if (gtcw != NULL) - return; - - // Create TPDD Server configuration window - gtcw = new Fl_Double_Window(480, 150, "TPDD / NADSBox Server"); - gtcw->callback(cb_tcwin); - gtcw->color(COLOR_BG); - - o = new Fl_Box(20, 20, 80, 20, "Root Directory"); - o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - o->labelcolor(COLOR_FG); - - // Create an input field to edit / show the root directory - gTsCtrl.pRootDir = new Fl_Input(35, 40, 325, 20, ""); - VTTpddServer* pServer = (VTTpddServer *) ser_get_tpdd_context(); - strcpy(gTsCtrl.sRootDir, pServer->RootDir()); - gTsCtrl.pRootDir->value(gTsCtrl.sRootDir); - gTsCtrl.pRootDir->color(COLOR_BG); - gTsCtrl.pRootDir->textcolor(COLOR_FG); - gTsCtrl.pRootDir->cursor_color(COLOR_FG); - - // Create a browse button for the root directory - gTsCtrl.pTpddDir = new Fl_Button(380, 40, 80, 20, "Browse"); - gTsCtrl.pTpddDir->callback(cb_TpddDir); - gTsCtrl.pTpddDir->color(COLOR_BG); - gTsCtrl.pTpddDir->labelcolor(COLOR_FG); - - // Create a Cancel button - b = new Fl_Button(200, 120, 80, 20, "Cancel"); - b->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE); - b->callback(cb_tpdd_cancel); - b->color(COLOR_BG); - b->labelcolor(COLOR_FG); - - // Create an OK button - b = new Fl_Return_Button(300, 120, 80, 20, "OK"); - b->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE); - b->callback(cb_tpdd_ok); - b->color(COLOR_BG); - b->labelcolor(COLOR_FG); - - gtcw->show(); -} - -/* -=========================================================================== -Define Serial port interface "C" routines below -=========================================================================== -*/ -extern "C" -{ - -/* -=========================================================================== -tpdd_alloc_context: Allocates a context to define and control the TPDD - server routines. -=========================================================================== -*/ -void* tpdd_alloc_context(void) -{ - return (void *) new VTTpddServer; -} - -/* -=========================================================================== -tpdd_free_context: Frees the given context. -=========================================================================== -*/ -void tpdd_free_context(void* pContext) -{ - // Validate the context is not null - if (pContext != NULL) - { - VTTpddServer* pTpdd = (VTTpddServer *) pContext; - delete pTpdd; - } -} - -/* -=========================================================================== -tpdd_load_prefs: Loads the tpdd server preferences from the user file. -=========================================================================== -*/ -void tpdd_load_prefs(void* pContext) -{ - char rootDir[512]; - VTTpddServer* pServer; - - virtualt_prefs.get("TpddServer_RootDir", rootDir, path, sizeof(rootDir)); - pServer = (VTTpddServer *) pContext; - pServer->RootDir(rootDir); -} - -/* -=========================================================================== -tpdd_save_prefs: Saves the tpdd server preferences to the user file. -=========================================================================== -*/ -void tpdd_save_prefs(void* pContext) -{ - VTTpddServer* pServer = (VTTpddServer *) pContext; - - virtualt_prefs.set("TpddServer_RootDir", pServer->RootDir()); -} - -/* -=========================================================================== -tpdd_close_serial: Closes the simulated TPDD serial session. -=========================================================================== -*/ -int tpdd_close_serial(void* pContext) -{ - VTTpddServer* pTpdd = (VTTpddServer *) pContext; - - // Let the TPDD Server class handle it - return pTpdd->SerClosePort(); -} - -/* -=========================================================================== -tpdd_open_serial: Opens the simulated TPDD serial session. -=========================================================================== -*/ -int tpdd_open_serial(void* pContext) -{ - VTTpddServer* pTpdd = (VTTpddServer *) pContext; - - // Let the TPDD Server class handle it - return pTpdd->SerOpenPort(); -} - -/* -=========================================================================== -tpdd_ser_set_baud: Sets the simulated baudrate for the TPDD server. -=========================================================================== -*/ -int tpdd_ser_set_baud(void* pContext, int baud_rate) -{ - VTTpddServer* pTpdd = (VTTpddServer *) pContext; - - // Let the TPDD Server class handle it - return pTpdd->SerSetBaud(baud_rate); -} - -/* -=========================================================================== -tpdd_ser_get_flags: Returns the port flags for the TPDD server -=========================================================================== -*/ -int tpdd_ser_get_flags(void* pContext, unsigned char *flags) -{ - VTTpddServer* pTpdd = (VTTpddServer *) pContext; - - // Let the TPDD Server class handle it - return pTpdd->SerGetFlags(flags); -} - -/* -=========================================================================== -tpdd_ser_set_signals: Sets the simulated port signals for the TPDD server -=========================================================================== -*/ -int tpdd_ser_set_signals(void* pContext, unsigned char signals) -{ - VTTpddServer* pTpdd = (VTTpddServer *) pContext; - - // Let the TPDD Server class handle it - return pTpdd->SerSetSignals(signals); -} - -/* -=========================================================================== -tpdd_ser_get_signals: Sets the simulated port signals for the TPDD server -=========================================================================== -*/ -int tpdd_ser_get_signals(void* pContext, unsigned char *signals) -{ - VTTpddServer* pTpdd = (VTTpddServer *) pContext; - - // Let the TPDD Server class handle it - return pTpdd->SerGetSignals(signals); -} - -/* -=========================================================================== -tpdd_ser_read_byte: Reads a byte from the TPDD server -=========================================================================== -*/ -int tpdd_ser_read_byte(void* pContext, char* data) -{ - VTTpddServer* pTpdd = (VTTpddServer *) pContext; - - // Let the TPDD Server class handle it - return pTpdd->SerReadByte(data); -} - -/* -=========================================================================== -tpdd_ser_write_byte: Writes a byte to the TPDD server -=========================================================================== -*/ -int tpdd_ser_write_byte(void* pContext, char data) -{ - VTTpddServer* pTpdd = (VTTpddServer *) pContext; - - // Let the TPDD Server class handle it - return pTpdd->SerWriteByte(data); -} - -/* -=========================================================================== -tpdd_get_port_name: Returns a printer to the name of this tpdd port -=========================================================================== -*/ -const char* tpdd_get_port_name(void* pContext) -{ - VTTpddServer* pTpdd = (VTTpddServer *) pContext; - - // Let the TPDD Server class handle it - return pTpdd->SerGetPortName(); -} - -/* -=========================================================================== -tpdd_ser_poll: Poll the TPDD Server to test if it has data available -=========================================================================== -*/ -int tpdd_ser_poll(void* pContext) -{ - VTTpddServer* pTpdd = (VTTpddServer *) pContext; - - // Let the TPDD Server class handle it - return pTpdd->SerPoll(); -} - -} /* End of extern "C" block */ - -/* -=========================================================================== -VTTpddServer class function implementaion follows. This is the constructor -=========================================================================== -*/ -VTTpddServer::VTTpddServer(void) -{ - int c; - - // Clear out the rx and tx buffers - m_rxCount = m_txCount = 0; - m_rxIn = 0; - m_txIn = m_txOut = 0; - for (c = 0; c < TPDD_MAX_FDS; c++) - { - m_refFd[c] = NULL; - m_mode[c] = 0; - } - m_lastWasRx = FALSE; - m_lastOpenWasDir = FALSE; - m_refIsDirectory = FALSE; - m_activeFd = 0; - m_backgroundCmd = NULL; - m_activeDir = NULL; - m_dirDir = NULL; - m_logEnabled = FALSE; - m_dirCount = m_dirNext = 0; - m_tsdosDmeReq = m_tsdosDmeStart = FALSE; - - // Reset the TPDD to idle state - m_state = TPDD_STATE_IDLE; - - // Initialze the working dir and rootpath - m_curDir = "/"; - m_sRootDir = path; -} - -/* -=========================================================================== -Class destructor -=========================================================================== -*/ -VTTpddServer::~VTTpddServer(void) -{ - int c; - - // Close any open file - for (c = 0; c < TPDD_MAX_FDS; c++) - { - if (m_refFd[c] != NULL) - fclose(m_refFd[c]); - m_refFd[c] = NULL; - } - - // Test if any active dirent list - ResetDirent(); -} - -/* -=========================================================================== -Set the root emulation directory -=========================================================================== -*/ -void VTTpddServer::RootDir(const char *pDir) -{ - int len; - - // Update the root directory - len = strlen(pDir); - m_sRootDir = pDir; - - // Remove trailing '/' or '\' - if (pDir[len-1] == '/' || pDir[len-1] == '\\') - m_sRootDir = m_sRootDir.Left(len - 1); - - // If there are any open files, then they have to be marked to send - // a TPDD_ERR_DISK_CHANGE_ERR error - // TODO: Do this!! -} - -/* -=========================================================================== -Opens the TpddServer port -=========================================================================== -*/ -int VTTpddServer::SerOpenPort(void) -{ - // Clear out the rx and tx buffers - m_txOverflow = m_rxOverflow = FALSE; - m_cycleDelay = 100000; - m_lastReadCycles = cycles; - - return SER_NO_ERROR; -} - -/* -=========================================================================== -Closes the TpddServer port -=========================================================================== -*/ -int VTTpddServer::SerClosePort(void) -{ - return SER_NO_ERROR; -} - -/* -=========================================================================== -Returns the name of the simulated port -=========================================================================== -*/ -const char* VTTpddServer::SerGetPortName(void) -{ - return (const char *) "TPDD"; -} - -/* -=========================================================================== -Sets the baud rate of the simulated TPDD server -=========================================================================== -*/ -int VTTpddServer::SerSetBaud(int baud_rate) -{ - // Save the simulated baud rate - m_baudRate = baud_rate; - - return SER_NO_ERROR; -} - -/* -=========================================================================== -Sets the simulated port flags -=========================================================================== -*/ -int VTTpddServer::SerGetFlags(unsigned char *flags) -{ - // Test if we can receive more data - if (m_rxCount + 1 < (int) sizeof(m_rxBuffer)) - *flags = SER_FLAG_TX_EMPTY; - else - *flags &= ~SER_FLAG_TX_EMPTY; - - if (gModel == MODEL_T200) - *flags |= SER_FLAG_CTS | SER_FLAG_DSR; - - return SER_NO_ERROR; -} - -/* -=========================================================================== -Sets the simulated port signals -=========================================================================== -*/ -int VTTpddServer::SerSetSignals(unsigned char signals) -{ - return SER_NO_ERROR; -} - -/* -=========================================================================== -Gets the simulated port signals -=========================================================================== -*/ -int VTTpddServer::SerGetSignals(unsigned char *signals) -{ - *signals = SER_SIGNAL_CTS | SER_SIGNAL_DSR | SER_SIGNAL_DTR | SER_SIGNAL_RTS; - - return SER_NO_ERROR; -} - -/* -=========================================================================== -Reads a byte from the TPDD Server -=========================================================================== -*/ -int VTTpddServer::SerReadByte(char *data) -{ - // Test if any data available - if (m_txCount == 0) - return SER_NO_DATA; - - // "Read" the next byte from the TX buffer - *data = m_txBuffer[m_txOut++]; - if (m_txOut >= (int) sizeof(m_txBuffer)) - m_txOut = 0; - - LogData(*data, TPDD_LOG_TX); - - // Decrement the count - m_txCount--; - - // "Kick" transmission of the next block of data from background command - if (m_backgroundCmd != NULL) - { - // Continue execution of the command in the background - if ((this->*m_backgroundCmd)(TRUE) == 0) - { - // Background command terminated - m_backgroundCmd = NULL; - SendToHost("> "); - - // Clear out the RX path - m_rxIn = m_rxCount = 0; - m_state = TPDD_STATE_IDLE; - } - } - - // If the count reached zero, then we need to indicate that to the - // serial routines so it will clear the interrupt - if (m_txCount == 0) - return SER_LAST_BYTE; - - // Update the time (cycles) of the last read - m_lastReadCycles = cycles; - - return SER_NO_ERROR; -} - -/* -=========================================================================== -Test if any bytes available to read and return appropriate status code -=========================================================================== -*/ -int VTTpddServer::SerPoll(void) -{ - // Test if any data in the TX buffer - if (m_txCount == 0) - return SER_NO_DATA; - - // Test if enough "time" (i.e. cycles) have elapsed - if (cycles > (UINT64) (m_lastReadCycles + m_cycleDelay)) - return SER_NO_ERROR; - - return SER_NO_DATA; -} - -/* -=========================================================================== -Sends a single character to the host -=========================================================================== -*/ -void VTTpddServer::SendToHost(char data) -{ - // Validate the TX buffer isn't full - if (m_txCount + 1 >= (int) sizeof(m_txBuffer)) - { - m_txOverflow = TRUE; - return; - } - - // Add the byte - m_txBuffer[m_txIn++] = data; - if (m_txIn >= (int) sizeof(m_txBuffer)) - m_txIn = 0; - m_txCount++; -} - -/* -=========================================================================== -Sends a string of characters to the host -=========================================================================== -*/ -void VTTpddServer::SendToHost(const char* data) -{ - while (*data != '\0') - SendToHost(*data++); -} - -/* -=========================================================================== -Processes received bytes while in the command line state -=========================================================================== -*/ -void VTTpddServer::StateCmdline(char data) -{ - // Test for CR - if (data == '\r') - { - // Echo CRLF to host - if (data != 0x1B) - SendToHost("\r\n"); - - // If there's no background command active... - if (m_backgroundCmd == NULL) - { - // Terminate the command and execute it - m_rxBuffer[m_rxIn] = '\0'; - m_cycleDelay = 400000; - ExecuteCmdline(); - } - - // Now reset the rxBuffer and go to idle - m_rxIn = m_rxCount = 0; - m_state = TPDD_STATE_IDLE; - return; - } - // Test for BKSP - else if (data == 0x08) - { - // Process the backspace - if (m_rxCount > 0) - { - // Erase the line from the host - SendToHost("\x08 \x08"); - m_rxCount--; - m_rxIn--; - - // If we backspaced to zero, then go to IDLE state - if (m_rxCount == 0) - m_state = TPDD_STATE_IDLE; - } - - return; - } - - // We have received part of a command line and we are looking for a CR, - // but must look for a 'Z' or 'M' after a timeout also - if (m_rxCount + 1 >= (int) sizeof(m_rxBuffer)) - { - // Buffer overflow!!! Go to idle state - m_rxIn = m_rxCount = 0; - m_state = TPDD_STATE_IDLE; - m_rxOverflow = TRUE; - return; - } - - else - { - // Add the byte to our rx buffer - m_rxBuffer[m_rxIn++] = data; - m_rxCount++; - - // Echo the byte back to the host - if (data != 0x1B) - SendToHost(data); - } -} - -/* -=========================================================================== -Handles the "cd" command -=========================================================================== -*/ -int VTTpddServer::CmdlineCd(int background) -{ - MString dirSave; - MString temp; - MString subDir; - int len, i; - - if (!background) - { - // Test if an arguemnt given - if (m_args.GetSize() == 0) - { - SendToHost("no argument given\r\n"); - return FALSE; - } - - // We could have multiple directories in the arg, such as "../M100" - // Process them one at a time. First save the current directory - // in case of error. - temp = m_args[0]; - len = temp.GetLength(); - dirSave = m_curDir; - - // Test if directory starts with '/' - i = 0; - if (temp[0] == '/') - { - i++; - m_curDir = '/'; - } - - // Get the first subdir specification - while (i < len && temp[i] != '/') - subDir += (char) temp[i++]; - - // Skip the '/' - if (i < len) - i++; - - while (subDir != "") - { - // Try to change to this directory - if (!ChangeDirectory(subDir)) - { - MString fmt; - fmt.Format("Dir '%s' does not exist\r\n", (const char *) subDir); - SendToHost((const char *) fmt); - m_curDir = dirSave; - return FALSE; - } - - // Get next level of subdir - subDir = ""; - - // Get the next subdir spec - while (i < len && temp[i] != '/') - subDir += (char) temp[i++]; - - // Skip the '/' - if (i < len) - i++; - } - } - - // Don't need to execute in the background - return FALSE; -} - -/* -=========================================================================== -Parses command line option arguments and creates a bitfield based on the -given option string. -=========================================================================== -*/ -int VTTpddServer::ParseOptions(MString& arg, const char* pOptions, int& flags) -{ - int c, x; - int len; - - // Initialize flags to zero - flags = 0; - - // Validate the 1st byte of arg is '-' - if (arg.GetLength() < 2 || arg[0] != '-') - return -1; - - // Start at byte just past '-' - x = 1; - len = strlen(pOptions); - while (x < arg.GetLength()) - { - // Loop through all options - for (c = 0; c < len; c++) - { - if (arg[x] == pOptions[c]) - { - flags |= 1 << c; - break; - } - } - - // Test if an invalid option was given - if (c == len) - return x; - - // Advance to next supplied option - x++; - } - - return -1; -} - -/* -=========================================================================== -Handles the "dir" command -=========================================================================== -*/ -int VTTpddServer::CmdlineDir(int background) -{ - int i, printed, col; - MString file_path; - MString fmt; - int len, isDir; - - m_cycleDelay = rst7cycles * 70 ; - if (m_cycleDelay > 1000000) - m_cycleDelay = 1000000; - - // Test if running in background or not - if (background) - { - // Wait for a key from the user before continuing - if (m_rxCount == 0) - return TRUE; - - // Key pressed. Test for ESC or CTRL-C - for (i = 0; i < m_rxCount; i++) - { - // Test if this character is CTRL-C or ESC - if (m_rxBuffer[i] == 0x03 || m_rxBuffer[i] == 0x1B || m_rxBuffer[i] == 'q') - { - // Yep, the user terminated the listing - for( i = 0; i < m_dirDirCount; i++ ) - free((void*) (m_dirDir[i])); - free((void*) m_dirDir); - m_dirDir = NULL; - SendToHost("\r\n"); - return FALSE; - } - } - - // Terminate the message line - m_rxIn = m_rxCount = 0; - SendToHost("\r \r"); - } - else - { - // Get a listing of the current directory - if (m_dirDir != NULL) - { - // Free the directory listing - for( i = 0; i < m_dirDirCount; i++ ) - free((void*) (m_dirDir[i])); - free((void*) m_dirDir); - } - - // Test if any args given - m_backgroundFlags = 0; - int options = 0; - int errOption; - if (m_args.GetSize() > 0) - { - // Test if 1st arg is options - if (m_args[0][0] == '-') - { - // Parse the options - if ((errOption = ParseOptions(m_args[0], "wd", m_backgroundFlags)) != -1) - { - // Unknown option given - MString fmt; - fmt.Format("unknown option '%c'\r\n", m_args[0][errOption]); - SendToHost((const char *) fmt); - m_rxIn = m_rxCount = 0; - return FALSE; - } - - // Indicate we used arg0 - options = 1; - } - } - - // Test if this is the 'ls' command and automatically select wide - if (m_cmd == "ls") - m_backgroundFlags |= CMD_DIR_FLAG_WIDE; - - // Test if argument other than options given - if (m_args.GetSize() - options == 0) - { - Fl_File_Sort_F *sort = fl_casealphasort; - - // Get a listing of files in the current directory - file_path = m_sRootDir + m_curDir; - m_dirDirCount = fl_filename_list((const char *) file_path, &m_dirDir, sort); - } - else - { - SendToHost("arguments not supported yet\r\n"); - m_rxIn = m_rxCount = 0; - return FALSE; - } - - // Start at beginning of list - m_dirDirNext = 0; - } - - // Display a page of entries - printed = 0; - col = 0; - - // Loop for all directory entries and send the next screen to client - for (i = m_dirDirNext; i < m_dirDirCount; i++) - { - const char* name = m_dirDir[i]->d_name; - MString printName; - - // ignore the "." and ".." names - if ( strcmp( name, "." ) == 0 || strcmp( name, ".." ) == 0 || - strcmp( name, "./" ) == 0 || strcmp( name, "../" ) == 0 || - strcmp( name, ".\\" ) == 0 || strcmp( name, "..\\" ) == 0 ) - { - continue; - } - - // Test if this is a directory - isDir = FALSE; - if (name[strlen(name)-1] == '/') - isDir = TRUE; - - // Test if only directories requested - if ((m_backgroundFlags & CMD_DIR_FLAG_DIR) && !isDir) - continue; - - // Get length of file - if (!isDir) - { - // Open the file and seek to the end - MString temp = m_sRootDir + m_curDir + name; - FILE* fd = fopen((const char *) temp, "r"); - len = 0; - - // Seek and tell only if file opened - if (fd != NULL) - { - fseek(fd, 0, SEEK_END); - len = ftell(fd); - fclose(fd); - } - } - - // Print this entry - if ((m_backgroundFlags & CMD_DIR_FLAG_WIDE) == 0) - { - // Not in wide display format - if (!isDir) - { - fmt.Format("%-20s%8d\r\n", name, len); - fmt.MakeUpper(); - } - else - { - MString temp = name; - temp = temp.Left(temp.GetLength()-1); - temp.MakeUpper(); - fmt.Format("%-17s\r\n", (const char *) temp); - } - SendToHost((const char *) fmt); - printed++; - } - else - { - // Printing in wide format... 2 entries per line - - if (!isDir) - { - // Truncate name to 12 places - char temp[13]; - strncpy(temp, name, 12); - temp[12] = '\0'; - if (strlen(name) < 12) - temp[strlen(name)] = '\0'; - - // Max display size is 99999 - if (len < 100000) - fmt.Format("%-13s%6d", temp, len); - else - fmt.Format("%-13>99999", temp); - fmt.MakeUpper(); - } - else - { - MString temp = name; - temp = temp.Left(temp.GetLength()-1); - temp.MakeUpper(); - fmt.Format("%-13s ", (const char *) temp); - } - - SendToHost((const char *) fmt); - if (col++ == 1) - { - col = 0; - printed++; - } - else - SendToHost(" "); - } - - // Test if a page printed - if (gModel == MODEL_T200) - { - if (printed == 15) - { - i++; - break; - } - } - else if (printed == 7) - { - i++; - break; - } - } - - // Test if we ended on col 1 in a wide format - if ((m_backgroundFlags & CMD_DIR_FLAG_WIDE) && col == 1) - SendToHost("\r\n"); - - // Save index for next listing - m_dirDirNext = i; - - // Test if all entries printed - if (i == m_dirDirCount) - { - // Free the directory listing - for( i = 0; i < m_dirDirCount; i++ ) - free((void*) (m_dirDir[i])); - free((void*) m_dirDir); - m_dirDir = NULL; - - // Don't need to execute in the background - return FALSE; - } - - // We have more to display. Present a message - SendToHost("Any key to continue, 'q' to stop..."); - - // Need to execute in the background - return TRUE; -} - -/* -=========================================================================== -Handles the "rmdir" command -=========================================================================== -*/ -int VTTpddServer::CmdlineRmdir(int background) -{ - // Don't need to execute in the background - return FALSE; -} - -/* -=========================================================================== -Handles the "Mkdir" command -=========================================================================== -*/ -int VTTpddServer::CmdlineMkdir(int background) -{ - // Don't need to execute in the background - return FALSE; -} - -/* -=========================================================================== -Handles the "del" command -=========================================================================== -*/ -int VTTpddServer::CmdlineDel(int background) -{ - // Don't need to execute in the background - return FALSE; -} - -/* -=========================================================================== -Handles the "copy" command -=========================================================================== -*/ -int VTTpddServer::CmdlineCopy(int background) -{ - // Don't need to execute in the background - return FALSE; -} - -/* -=========================================================================== -Handles the "ren" command -=========================================================================== -*/ -int VTTpddServer::CmdlineRen(int background) -{ - // Don't need to execute in the background - return FALSE; -} - -/* -=========================================================================== -Handles the "trace" command -=========================================================================== -*/ -int VTTpddServer::CmdlineTrace(int background) -{ - // Don't need to execute in the background - return FALSE; -} - -/* -=========================================================================== -Handles the "type" command -=========================================================================== -*/ -int VTTpddServer::CmdlineType(int background) -{ - // Don't need to execute in the background - return FALSE; -} - -/* -=========================================================================== -Handles the "date" command -=========================================================================== -*/ -int VTTpddServer::CmdlineDate(int background) -{ - // Don't need to execute in the background - return FALSE; -} - -/* -=========================================================================== -Handles the "time" command -=========================================================================== -*/ -int VTTpddServer::CmdlineTime(int background) -{ - // Don't need to execute in the background - return FALSE; -} - -/* -=========================================================================== -Handles the "info" command -=========================================================================== -*/ -int VTTpddServer::CmdlineInfo(int background) -{ - // Don't need to execute in the background - return FALSE; -} - -/* -=========================================================================== -Handles the "help" command -=========================================================================== -*/ -int VTTpddServer::CmdlineHelp(int background) -{ - int c, cmdsThisLine; - - // Counts the number of commands printed on this line - cmdsThisLine = 0; - - m_cycleDelay = rst7cycles * 70 ; - if (m_cycleDelay > 1000000) - m_cycleDelay = 1000000; - - if (!background) - { - // Test if an argument given - if (m_args.GetSize() == 0) - { - // Loop for all commands - for (c = 0; c < m_cmdCount; c++) - { - SendToHost(m_Cmds[c].pCmd); - if (++cmdsThisLine == 4) - { - // Terminate this line - cmdsThisLine = 0; - SendToHost("\r\n"); - } - else - { - // Send a tab between commands - SendToHost("\t"); - } - } - - // Test if we need a final CRLF - if (cmdsThisLine != 0) - SendToHost("\r\n"); - } - else - { - // Show help for a specific command - for (c = 0; c < m_cmdCount; c++) - { - // Test if this item matches - if (m_args[0] == m_Cmds[c].pCmd) - { - // Display help for this command - SendToHost(m_Cmds[c].pHelp); - SendToHost("\r\n"); - return FALSE; - } - else if (c < m_linuxCmdCount) - { - if (m_args[0] == m_LinuxCmds[c].pCmd) - { - // Display help for this command - SendToHost(m_LinuxCmds[c].pHelp); - SendToHost("\r\n"); - return FALSE; - } - } - - // Test if all commands requested - if (m_args[0] == "all") - { - // Display help for this command - SendToHost(m_Cmds[c].pHelp); - SendToHost("\r\n"); - } - } - - // If all commands requested, then return - if (m_args[0] == "all") - return FALSE; - - // Command not found - MString fmt; - fmt.Format("unknown command '%s'\r\n", (const char *) m_args[0]); - SendToHost((const char *) fmt); - } - } - - // Don't need to execute in the background - return FALSE; -} - -/* -=========================================================================== -Handles the "pwd" command -=========================================================================== -*/ -int VTTpddServer::CmdlinePwd(int background) -{ - MString temp = m_curDir; - - if (!background) - { - temp.MakeUpper(); - if (temp.GetLength() > 1) - if (temp[temp.GetLength()-1] == '/') - temp = temp.Left(temp.GetLength()-1); - SendToHost((const char *) temp); - SendToHost("\r\n"); - } - - // Don't need to execute in the background - return FALSE; -} - -/* -=========================================================================== -Handles the "ver" command -=========================================================================== -*/ -int VTTpddServer::CmdlineVer(int background) -{ - // Send our Version information to the host - if (!background) - { - SendToHost("VirtualT's emulated NADSBox\r\n"); - SendToHost("Firmware v1.14 equivalent\r\n"); - SendToHost("Copyright 2013, Kenneth D. Pettit\r\n"); - } - - // Don't need to execute in the background - return FALSE; -} - -/* -=========================================================================== -Executes the command line command in the m_rxBuffer -=========================================================================== -*/ -void VTTpddServer::ExecuteCmdline(void) -{ - int c; - char* ptr; - MString cmd, arg; - - // Split the m_rxBuffer into command and args - ptr = m_rxBuffer; - - // Remove previous arguments - m_args.RemoveAll(); - - // Get the command - while (*ptr != '\0' && *ptr != ' ') - cmd += *ptr++; - - // Now get the args - while (*ptr == ' ') - ptr++; - while (*ptr != '\0') - { - // Clear out the argument - arg = ""; - while (*ptr != ' ' && *ptr != '\0') - arg += *ptr++; - - // Add to the args array - m_args.Add(arg); - - // Skip whitespace - while (*ptr == ' ') - ptr++; - } - - // Loop through all registered commands and see if we have a match - for (c = 0; c < m_cmdCount; c++) - { - // Test if this command matches - if (strcmp(m_Cmds[c].pCmd, (const char *) cmd) == 0) - { - // This command matches the rxBuffer. Call the command handler - m_cmd = m_Cmds[c].pCmd; - if ((this->*m_Cmds[c].pFunc)(FALSE)) - m_backgroundCmd = m_Cmds[c].pFunc; - break; - } - } - - // Test if command not foune - if (c == m_cmdCount) - { - // Search the Linux equivalent commands - for (c = 0; c < m_linuxCmdCount; c++) - { - // Test if this command matches - if (strcmp(m_LinuxCmds[c].pCmd, (const char *) cmd) == 0) - { - // This command matches the rxBuffer. Call the command handler - m_cmd = m_LinuxCmds[c].pCmd; - if ((this->*m_LinuxCmds[c].pFunc)(FALSE)) - m_backgroundCmd = m_LinuxCmds[c].pFunc; - break; - } - } - - // Test if command not found in Linux alias list either - if (c == m_linuxCmdCount) - { - // Test for "flash" command - if (strcmp("flash", (const char *) cmd) == 0) - SendToHost("'flash' not supported in emulation\r\n"); - else if (strcmp("stats", (const char *) cmd) == 0) - SendToHost("'stats' not supported in emulation\r\n"); - else - SendToHost("Unknown command\r\n"); - } - } - - // Send an new prompt - if (m_backgroundCmd == NULL) - SendToHost("> "); -} - -/* -=========================================================================== -Executes the TPDD opcode in the m_rxBuffer -=========================================================================== -*/ -void VTTpddServer::ExecuteTpddOpcode(void) -{ - // Test opcode for mystery31 or mystery23 - if (m_opcode == TPDD_REQ_TSDOS_MYSTERY23) - OpcodeMystery23(); - else if (m_opcode == TPDD_REQ_TSDOS_MYSTERY31) - OpcodeMystery31(); - - // Normal TPDD protocol opcodes - else if (m_opcode <= TPDD_REQ_LAST_OPCODE) - { - // Call the handler routine for this opcode - (this->*m_tpddOpcodeHandlers[m_opcode])(); - } - - // Unknown opcode - else - { - // Send an error condition - SendNormalReturn(TPDD_ERR_PARAM_ERR); - } - - // Reset RX path and go to IDLE state - m_rxIn = m_rxCount = 0; - m_state = TPDD_STATE_IDLE; -} - -/* -=========================================================================== -Logs data to the packet log, either RX or TX data -=========================================================================== -*/ -void VTTpddServer::LogData(char data, int rxTx) -{ - // Log data only if the log is enabled - if (m_logEnabled && m_pServerLog != NULL) - { - m_pServerLog->LogData(data, rxTx); - } -} - -/* -=========================================================================== -Writes a byte to the TPDD Server -=========================================================================== -*/ -int VTTpddServer::SerWriteByte(char data) -{ - int c; - - // Record the time of this byte so we can perform timeout - // operations in the state machine - - // Log the byte - LogData(data, TPDD_LOG_RX); - - // Switch based on state. This is the main state machine - switch (m_state) - { - case TPDD_STATE_IDLE: - // We are in idle state. Search for 'Z', 'M', or 'R'. Any lower case - // chars or CR will take us to command line state - if (m_tsdosDmeReq && (data == 0x0D)) - { - // Reset the rx path - m_rxIn = m_rxCount = 0; - m_tsdosDmeStart = FALSE; - if (m_tsdosDmeReq++ == 2) - { - // Clear the DME request flag after the 2nd 0x0D - m_tsdosDmeReq = 0; - } - break; - } - if (m_tsdosDmeReq) - { - // Byte received that wasn't 0x0D. Clear out the DME - m_tsdosDmeReq = m_tsdosDmeStart = 0; - m_rxIn = m_rxCount = 0; - } - - // Test for command line characters - if ((data >= 'a' && data <= 'z') || m_backgroundCmd) - { - // Add the byte to our RX buffer - m_rxBuffer[m_rxIn++] = data; - m_rxCount = 1; - - // Add the byte to our TX buffer so we echo it - if (data != 0x1B) - SendToHost(data); - - // Clear out any acive TS-DOS DME activity - m_tsdosDmeStart = FALSE; - - // Goto cmdline state - m_state = TPDD_STATE_CMDLINE; - } - - // Test for empty-line CR - else if (data == '\n' || data == '\r') - { - // Send a prompt to the host - SendToHost("\r\n> "); - } - - // Search for 'Z' - else if (data == 'Z') - { - // Add the byte to our RX buffer - m_rxBuffer[m_rxIn++] = data; - m_rxCount = 1; - m_state = TPDD_STATE_Z; // Goto Z state - } - else if (data == 'M') - { - // Add the byte to our RX buffer - m_rxBuffer[m_rxIn++] = data; - m_rxCount = 1; - m_state = TPDD_STATE_M; // Goto M state - } - else if (data == 'R') - { - // Add the byte to our RX buffer - m_rxBuffer[m_rxIn++] = data; - m_rxCount = 1; - m_state = TPDD_STATE_R; // Goto R state - } - break; - - case TPDD_STATE_Z: - // We expect to see another 'Z', but look for timeout too - if (data == 'Z') - { - // Add the byte to our RX buffer - m_rxBuffer[m_rxIn++] = data; - m_rxCount++; - - // Go to the opcode state, we got the 2nd 'Z' - m_state = TPDD_STATE_OPCODE; - } - else - { - // Goto the IDLE state and reprocess the byte - m_state = TPDD_STATE_IDLE; - m_rxCount = m_rxIn = 0; // Reset the Rx buffer - SerWriteByte(data); - } - break; - - case TPDD_STATE_OPCODE: - // We have received 'ZZ', now we are waiting for the opcode byte - m_opcode = data; - - // Add the byte to our RX buffer - m_rxBuffer[m_rxIn++] = data; - m_rxCount++; - - // Go wait for the LEN byte - m_state = TPDD_STATE_LEN; - break; - - case TPDD_STATE_LEN: - // We have received the opcode, now waiting for the length byte - m_length = (unsigned char) data; - m_bytesRead = 0; - - // Add the byte to our RX buffer - m_rxBuffer[m_rxIn++] = data; - m_rxCount++; - - // Go wait for bytes - if (m_length == 0) - m_state = TPDD_STATE_READ_CHECKSUM; - else - m_state = TPDD_STATE_READ_BYTES; - break; - - case TPDD_STATE_READ_BYTES: - // Add the byte to our RX buffer - m_rxBuffer[m_rxIn++] = data; - - // Test if all bytes read - m_rxCount++; - if (++m_bytesRead == m_length) - { - // Goto state to read the checksum - m_state = TPDD_STATE_READ_CHECKSUM; - } - break; - - case TPDD_STATE_READ_CHECKSUM: - // All bytes read, now read the checksum - m_rxChecksum = data; - - // Now compute the checksum of received data - m_calcChecksum = 0; - for (c = TPDD_PKT_OPCODE_INDEX; c < m_length+4; c++) - { - // Calculate checksum across opcode, length and all data - m_calcChecksum += (unsigned char) m_rxBuffer[c]; - } - - // Compare the checksum - if ((m_calcChecksum ^ 0xFF) != m_rxChecksum) - { - // Error in checksum. Send error packet - SendNormalReturn(TPDD_ERR_ID_CRC_CHK_ERR); - } - else - { - // Execute the TPDD opcode - m_cycleDelay = 100000; - ExecuteTpddOpcode(); - } - - // Now reset RX and go to idle - m_rxIn = m_rxCount = 0; - m_state = TPDD_STATE_IDLE; - break; - - case TPDD_STATE_M: - // We have received 'M' and are waiting for '1' (the 'M1' sequence) - if (data == '1') - { - // Now wait for the 0Dh - m_rxBuffer[m_rxIn++] = data; - m_rxCount = 1; - m_state = TPDD_STATE_M1; - } - else - { - // Reset RX path and goto idle - m_rxIn = m_rxCount = 0; - m_state = TPDD_STATE_IDLE; - } - break; - - case TPDD_STATE_M1: - // We have received 'M1'. This is used for Directory Management Extension - if (data == 0x0D) - { - // TS-DOS DME request initiated. Save the event - m_tsdosDmeStart = TRUE; - } - - // Clear the RX path and goto idle - m_rxIn = m_rxCount = 0; - m_state = TPDD_STATE_IDLE; - break; - - case TPDD_STATE_CMDLINE: - // Process in the cmdline routine - StateCmdline(data); - break; - - default: - // Unknown state. Go to idle. - m_state = TPDD_STATE_IDLE; - - // Reset the RX buffer - m_rxIn = m_rxCount = 0; - break; - } - return SER_NO_ERROR; -} - -/* -=========================================================================== -Sends the specified file entry to the server -=========================================================================== -*/ -void VTTpddServer::SendDirEntReturn(dirent* e, int dir_entry) -{ - int c, idx; - int send_spaces; - - // Clear the TX checksum - m_txChecksum = 0; - TpddSendByte(TPDD_RET_DIR_REF); // Return code - TpddSendByte(28); // Dir Entry pkt length - - // Now send 24 bytes of filename, space padded - idx = 0; - send_spaces = FALSE; - for (c = 0; c < 24; c++) - { - // Test if we are sending spaces - if (send_spaces) - TpddSendByte(' '); - else if (e == NULL) - { - TpddSendByte(0); - continue; - } - else if ((e->d_name[idx] == '.' || e->d_name[idx] == '/') && c < 6) - { - TpddSendByte(' '); - } - else if ((e->d_name[idx] == '.' && dir_entry) || e->d_name[idx] == '/') - { - // Send the '.' followed by "<>", then send spaces - TpddSendByte('.'); - TpddSendByte('<'); - TpddSendByte('>'); - c += 2; - send_spaces = true; - - // Skip idx ahead to the NULL - while (e->d_name[idx] != '\0') - idx++; - } - else if (e->d_name[idx] == '\0') - { - TpddSendByte(' '); - send_spaces = TRUE; - } - else if (e->d_name[idx] == '.' && c < 6) - TpddSendByte(' '); - else - TpddSendByte(toupper(e->d_name[idx++])); - } - - // Send the Attribute byte 'F' - if (e == NULL) - TpddSendByte(0); - else - TpddSendByte('F'); - - // Send 2-byte length - int file_len = 0; - if (!dir_entry && e) - { - // Open the file to calculate the length - MString file_path = m_sRootDir + m_curDir + e->d_name; - FILE* fd = fopen((const char *) file_path, "r"); - if (fd != NULL) - { - // Seek to end of file - fseek(fd, 0, SEEK_END); - file_len = ftell(fd); - fclose(fd); - - // Truncate file length at 64K - if (file_len > 65535) - file_len = 65535; - } - } - - // Send 2 bytes of length - TpddSendByte((file_len >> 8) & 0xFF); - TpddSendByte(file_len & 0xFF); - - // Send the number of free sectors (255) - TpddSendByte((char) 0x9D); - - // Now send the checksum - TpddSendChecksum(); -} - -/* -=========================================================================== -Finds the specified file and sends the DIR_REF retrun packet to the server. -=========================================================================== -*/ -void VTTpddServer::DirFindFile(const char* pFilename) -{ - // read the directory - dirent** e; - char* name; - int i, num, len, dir_entry; - MString file_path; - char find_name[16]; - - // Test if accessing the "PARENT.<>" file - if (strcmp(pFilename, "PARENT.<>") == 0) - { - // Just save the reference and exit - m_dirRef = pFilename; -#ifdef WIN32 - dirent* pParent = (dirent *) "PARENT.<>"; -#else - dirent parent; - dirent* pParent = &parent; - strcpy(parent.d_name, "PARENT.<>"); -#endif - SendDirEntReturn(pParent, TRUE); - return; - } - - // Construct the path using the current working directory and the root - file_path = m_sRootDir + m_curDir; - num = fl_filename_list((const char *) file_path, &e ); - m_refIsDirectory = FALSE; - - // Test if the given filename is a diretory search. If it is, then - // the filename will look like "DIRNAM.<>" - strcpy(find_name, pFilename); - len = strlen(pFilename); - if (len > 3 && pFilename[len-1] == '>' && pFilename[len-2] == '<') - { - // Indicate we are doing a directory search - m_refIsDirectory = TRUE; - - // Terminate the filename at the '.' - find_name[len-3] = '\0'; - } - - // If any files found - if (num > 0) - { - // Loop through all files in the list and perform a - // case insensitive compare - for ( i = 0; i < num; i++ ) - { - name = e[i]->d_name; - - // ignore the "." and ".." names - if ( strcmp( name, "." ) == 0 || strcmp( name, ".." ) == 0 || - strcmp( name, "./" ) == 0 || strcmp( name, "../" ) == 0 || - strcmp( name, ".\\" ) == 0 || strcmp( name, "..\\" ) == 0 ) - { - continue; - } - - // if 'name' ends in '/', remove it - dir_entry = FALSE; - if ( name[strlen(name)-1] == '/' ) - { - dir_entry = TRUE; - name[strlen(name)-1] = '\0'; - } - - // Compare this file with the requested filename - if (strcasecmp(name, find_name) == 0) - { - // Entry found! Send the DIR_ENT return - SendDirEntReturn(e[i], dir_entry); - - // Test if another file was already opened - if (m_refFd[m_activeFd] != NULL) - { - // Close the previously referenced file - fclose(m_refFd[m_activeFd]); - m_refFd[m_activeFd] = NULL; - } - - // Save this reference for future open, delete, etc. - m_dirRef = name; - m_refIsDirectory = dir_entry; - - // Now free the list memory - for( i = 0; i < num; i++ ) - free((void*)(e[i])); - free((void*)e); - - return; - } - } - - // File not found. Create a new dirent and send the reference - SendDirEntReturn(NULL, FALSE); - m_dirRef = pFilename; - - // Now free the list memory - for( i = 0; i < num; i++ ) - free((void*)(e[i])); - free((void*)e); - } - else - { - // Return error - SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); - } -} - -/* -=========================================================================== -Finds the first entry in the current directory and sends a DirEnt packet -to the server. -=========================================================================== -*/ -void VTTpddServer::DirFindFirst(void) -{ - // read the directory - MString file_path; - - // Construct the path using the current working directory and the root - file_path = m_sRootDir + m_curDir; - if (m_activeDir != NULL) - ResetDirent(); - m_dirCount = fl_filename_list((const char *) file_path, &m_activeDir ); - m_dirNext = 0; - - // Test if we are at the ROOT directory or not. If not at root, then - // the first entry is always "PARENT.<>" - if (m_curDir != "/") - { - // Send the "PARENT.<>" directory entry -#ifdef WIN32 - dirent* pParent = (dirent *) "PARENT.<>"; -#else - dirent parent; - dirent* pParent = &parent; - strcpy(parent.d_name, "PARENT.<>"); -#endif - SendDirEntReturn(pParent, TRUE); - } - else - { - // Call the routine to send the next directory entry - DirFindNext(); - } -} - -/* -=========================================================================== -Finds the next entry in the current directory and sends a DirEnt packet -to the server. -=========================================================================== -*/ -void VTTpddServer::DirFindNext(void) -{ - // Don't count the '.' and '..' entries in the count - while (m_dirNext < m_dirCount) - { - const char* name = m_activeDir[m_dirNext]->d_name; - if ( strcmp( name, "." ) == 0 || strcmp( name, ".." ) == 0 || - strcmp( name, "./" ) == 0 || strcmp( name, "../" ) == 0 || - strcmp( name, ".\\" ) == 0 || strcmp( name, "..\\" ) == 0 ) - { - // Subtract this entry f - m_dirNext++; - continue; - } - - // Send first directory entry - SendDirEntReturn(m_activeDir[m_dirNext], FALSE); - m_dirNext++; - break; - } - - // Send the next directory entry or all blank - if (m_dirNext >= m_dirCount) - { - // Send a blank entry - SendDirEntReturn(NULL, FALSE); - } -} - -/* -=========================================================================== -Handles the Dir opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeDir(void) -{ - char* pFilename; - char fat_filename[16]; - int idx, c; - - // Validate the length byte - if (m_length != 26) - { - SendNormalReturn(TPDD_ERR_PARAM_ERR); - return; - } - - // Convert filename from Model T 6.2 format to FAT 8.3 format - pFilename = &m_rxBuffer[TPDD_PKT_DATA_INDEX]; - idx = 0; - for (c = 0; c < 6; c++) - if ((fat_filename[idx] = *pFilename++) != ' ') - idx++; - fat_filename[idx++] = '.'; - if (*pFilename == '.') - pFilename++; - if ((fat_filename[idx] = *pFilename++) != ' ') - idx++; - if ((fat_filename[idx] = *pFilename++) != ' ') - idx++; - fat_filename[idx] = '\0'; - - // Now process the request based on the search type - switch (m_rxBuffer[TPDD_PKT_DATA_INDEX + 25]) - { - case 0: // Dir find file - DirFindFile(fat_filename); - break; - - case 1: // Find first entry - DirFindFirst(); - break; - - case 2: // Find next entry - DirFindNext(); - break; - - default: - // Unknown - SendNormalReturn(TPDD_ERR_PARAM_ERR); - break; - } -} - -/* -=========================================================================== -Handles the Open opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeOpen(void) -{ - MString open_path; - unsigned char open_mode; - - // Try to open the referenced file - open_path = m_sRootDir + m_curDir + m_dirRef; - open_mode = m_rxBuffer[TPDD_PKT_DATA_INDEX]; - - // Check if the referenced file is a directory - if (m_refIsDirectory) - { - // Mark last open as a directory change - m_lastOpenWasDir = TRUE; - - // Test the open_mode. If read mod, then CD - if (open_mode == TPDD_OPEN_MODE_READ) - { - // Perform a "Change directory" operation - if (m_dirRef == "PARENT.<>") - { - // Change to parent directory - ChangeDirectory(".."); - SendNormalReturn(TPDD_ERR_NONE); - } - else - { - // Change to m_dirRef - ChangeDirectory(m_dirRef); - SendNormalReturn(TPDD_ERR_NONE); - } - } - else if (open_mode == TPDD_OPEN_MODE_WRITE) - { - MString temp; - // Test if we need to remove the ".<>" (likely) - if (m_dirRef.Right(3) == ".<>") - temp = m_dirRef.Left(m_dirRef.GetLength()-3); - else - temp = m_dirRef; - - // MKDIR operation - temp.MakeUpper(); - MString dirToMake = m_sRootDir + m_curDir + temp; -#ifdef WIN32 - _mkdir((const char *) dirToMake); -#else - mkdir((const char *) dirToMake, 0755); -#endif - - // Send a normal return code - SendNormalReturn(TPDD_ERR_NONE); - } - } - else - { - // Open the file based on mode - if (open_mode == TPDD_OPEN_MODE_WRITE) - m_refFd[m_activeFd] = fopen((const char *) open_path, "wb"); - else if (open_mode == TPDD_OPEN_MODE_APPEND) - m_refFd[m_activeFd] = fopen((const char *) open_path, "ab"); - else if (open_mode == TPDD_OPEN_MODE_READ) - m_refFd[m_activeFd] = fopen((const char *) open_path, "rb"); - else if (open_mode == TPDD_OPEN_MODE_READ_WRITE) - m_refFd[m_activeFd] = fopen((const char *) open_path, "rb+"); - - // Test if the file was opened successfully - if (m_refFd[m_activeFd] == NULL) - SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); - else - { - // Save the open mode - m_mode[m_activeFd] = open_mode; - SendNormalReturn(TPDD_ERR_NONE); - } - } -} - -/* -=========================================================================== -Handles the Close opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeClose(void) -{ - // Test if last "open" was a directory open - if (m_lastOpenWasDir) - { - SendNormalReturn(TPDD_ERR_NONE); - } - - // Test if the active FD is open - else if (m_refFd[m_activeFd] == NULL) - SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); - else - { - // Close the file and mark it closed - fclose(m_refFd[m_activeFd]); - m_refFd[m_activeFd] = NULL; - - // Send normal return - SendNormalReturn(TPDD_ERR_NONE); - } -} - -/* -=========================================================================== -Handles the Read opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeRead(void) -{ - char fileData[128]; - int read_len, c; - - // Validate the file is opened and in the right mode - if (m_refFd[m_activeFd] == NULL) - SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); - else if (m_mode[m_activeFd] != TPDD_OPEN_MODE_READ && - m_mode[m_activeFd] != TPDD_OPEN_MODE_READ_WRITE) - SendNormalReturn(TPDD_ERR_OPEN_FMT_MISMATCH); - else - { - // File is open and in the correct mode. Read up to 128 bytes - read_len = fread(fileData, 1, sizeof(fileData), m_refFd[m_activeFd]); - - // Test for end-of-file - if (read_len == 0) - SendNormalReturn(TPDD_ERR_END_OF_FILE); - else - { - // Send the read file packet - m_txChecksum = 0; - TpddSendByte(TPDD_RET_READ_FILE); - TpddSendByte((unsigned char) read_len); - - // Loop for all data to be sent - for (c = 0; c < read_len; c++) - TpddSendByte(fileData[c]); - - // Send the checksum - TpddSendChecksum(); - } - } -} - -/* -=========================================================================== -Handles the Write opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeWrite(void) -{ - int write_len; - - write_len = m_length; - - // Validate the file is opened and in the right mode - if (m_refFd[m_activeFd] == NULL) - SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); - else if (m_mode[m_activeFd] == TPDD_OPEN_MODE_READ) - SendNormalReturn(TPDD_ERR_OPEN_FMT_MISMATCH); - else - { - // File is open and in the correct mode. Read up to 128 bytes - write_len = fwrite(&m_rxBuffer[TPDD_PKT_DATA_INDEX], 1, m_length, m_refFd[m_activeFd]); - - // Test for end-of-file - if (write_len == 0) - SendNormalReturn(TPDD_ERR_DISK_FULL); - else - SendNormalReturn(TPDD_ERR_NONE); - } -} - -/* -=========================================================================== -Handles the Delete opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeDelete(void) -{ - MString delFile; - int ret; - - // Test if last reference was a directory - if (m_refIsDirectory) - { - // Request to remove a directory. Test if "PARENT.<>" - if (m_dirRef == "PARENT.<>") - { - // Just send normal return - SendNormalReturn(TPDD_ERR_NONE); - return; - } - - // Construct the path of the file to delete - delFile = m_sRootDir + m_curDir + m_dirRef; - -#ifdef WIN32 -#else - ret = rmdir((const char *) delFile); - if (ret == 0) - SendNormalReturn(TPDD_ERR_NONE); - else - { - // Send error based on errno - } -#endif - } - else - { - // Request to delete a file. Construct the path of the file to delete - delFile = m_sRootDir + m_curDir + m_dirRef; -#ifdef WIN32 - ret = DeleteFile((const char *) delFile); - if (ret) - SendNormalReturn(TPDD_ERR_NONE); - else - { - // Send error based on GetLastError() - if (GetLastError() == ERROR_FILE_NOT_FOUND) - SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); - else - SendNormalReturn(TPDD_ERR_DISK_WRITE_PROT); - } -#else - ret = unlink((const char *) delFile); - if (ret == 0) - SendNormalReturn(TPDD_ERR_NONE); - else - { - // Send error based on errno - if (errno == ENOENT) - SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); - else - SendNormalReturn(TPDD_ERR_DISK_WRITE_PROT); - } -#endif - } -} - -/* -=========================================================================== -Handles the Format opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeFormat(void) -{ - // Just send a normal return with no error - SendNormalReturn(TPDD_ERR_NONE); -} - -/* -=========================================================================== -Handles the Drive Status opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeDriveStatus(void) -{ - // Just send a normal return with no error - SendNormalReturn(TPDD_ERR_NONE); -} - -/* -=========================================================================== -Handles the Id opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeId(void) -{ - // Test if a TS-DOS DME request was received previously - if (m_tsdosDmeStart) - { - // Send a DME Response and flag to expect a coule of 0x0D - m_tsdosDmeReq = 1; - SendDmeResponse(); - } - else - { - // Send the drive ID - SendToHost("NADSBox"); - } -} - -/* -=========================================================================== -Handles the Rename opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeRename(void) -{ - MString old_filename, new_filename; - MString temp; - int ret, idx; - - // Test if last reference was a directory - if (m_refIsDirectory) - { - // Request to rename a directory. Test if "PARENT.<>" - if (m_dirRef == "PARENT.<>") - { - // Just send normal return - SendNormalReturn(TPDD_ERR_NONE); - return; - } - } - - // Validate the length - if (m_length != 25) - { - SendNormalReturn(TPDD_ERR_PARAM_ERR); - return; - } - - // Get the new filename - new_filename = m_sRootDir + m_curDir; - idx = TPDD_PKT_DATA_INDEX; - const int end = TPDD_PKT_DATA_INDEX + 24; // Max filename len - while (m_rxBuffer[idx] != ' ' && m_rxBuffer[idx] != '\0' && idx < end) - new_filename += (char) m_rxBuffer[idx++]; - - // Skip spaces - while (m_rxBuffer[idx] == ' ' && idx < end) - idx++; - - // Now append the extension if not a directory - if (idx < end && m_rxBuffer[idx] == '.') - { - // Test if this is a directory reference or not - if (m_rxBuffer[idx+1] != '<') - { - // Not a directory reference. Append the file extension - new_filename += (char) m_rxBuffer[idx++]; - while (idx != ' ' && idx != '\0' && idx < end) - new_filename += (char) m_rxBuffer[idx++]; - } - } - - // Construct the path of the old filename - old_filename = m_sRootDir + m_curDir + m_dirRef; - -#ifdef WIN32 - ret = rename((const char *) old_filename, (const char *) new_filename); - if (ret == 0) - SendNormalReturn(TPDD_ERR_NONE); - else - { - // Send error based on GetLastError() - if (GetLastError() == ERROR_FILE_NOT_FOUND) - SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); - else - SendNormalReturn(TPDD_ERR_DISK_WRITE_PROT); - } -#else - ret = rename((const char *) old_filename, (const char *) new_filename); - if (ret == 0) - SendNormalReturn(TPDD_ERR_NONE); - else - { - // Send error based on errno - if (errno == ENOENT) - SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); - else - SendNormalReturn(TPDD_ERR_DISK_WRITE_PROT); - } -#endif -} - -/* -=========================================================================== -Handles the Drive Condition opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeDriveCond(void) -{ - // Clear the TX checksum - m_txChecksum = 0; - TpddSendByte(TPDD_RET_CONDITION); - TpddSendByte(1); // Length is 1 - TpddSendByte(0); // Condition - all ok - TpddSendChecksum(); -} - -/* -=========================================================================== -Handles the Seek opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeSeek(void) -{ - int seek_mode, seek_offset; - - // Validate the length and seek mode - if (m_length != 5 || m_rxBuffer[TPDD_PKT_DATA_INDEX] > TPDD_SEEK_END) - { - // Send error condition - SendNormalReturn(TPDD_ERR_PARAM_ERR); - return; - } - - // Validate the file is open and in the right mode - if (m_refFd[m_activeFd] == NULL) - { - // Send error code - SendNormalReturn(TPDD_ERR_OPEN_FMT_MISMATCH); - return; - } - - // Get the seek mode and length - switch (m_rxBuffer[TPDD_PKT_DATA_INDEX]) - { - case TPDD_SEEK_SET: seek_mode = SEEK_SET; break; - case TPDD_SEEK_CUR: seek_mode = SEEK_CUR; break; - case TPDD_SEEK_END: seek_mode = SEEK_END; break; - default: seek_mode = SEEK_SET; break; - } - seek_offset = ((unsigned char) m_rxBuffer[TPDD_PKT_DATA_INDEX+1]) | - ((unsigned char) m_rxBuffer[TPDD_PKT_DATA_INDEX+2] << 8) | - ((unsigned char) m_rxBuffer[TPDD_PKT_DATA_INDEX+3] << 16) | - ((unsigned char) m_rxBuffer[TPDD_PKT_DATA_INDEX+4] << 24); - - // Perform the seek - fseek(m_refFd[m_activeFd], seek_mode, seek_offset); - SendNormalReturn(TPDD_ERR_NONE); -} - -/* -=========================================================================== -Handles the Tell opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeTell(void) -{ - int pos; - - // Validate the file is open and in the right mode - if (m_refFd[m_activeFd] == NULL) - { - // Send error code - SendNormalReturn(TPDD_ERR_OPEN_FMT_MISMATCH); - return; - } - - // Get the current file position - pos = ftell(m_refFd[m_activeFd]); - - // Clear the txChecksum and start the packet - m_txChecksum = 0; - TpddSendByte(TPDD_RET_TELL); - TpddSendByte(4); // Length is 4 bytes offset data - TpddSendByte(pos & 0xFF); // Send LSB - TpddSendByte((pos >> 8) & 0xFF); - TpddSendByte((pos >> 16) & 0xFF); - TpddSendByte((pos >> 24) & 0xFF); // Send MSB - TpddSendChecksum(); -} - -/* -=========================================================================== -Handles the SetExtended opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeSetExtended(void) -{ - SendNormalReturn(TPDD_ERR_NONE); -} - -/* -=========================================================================== -Handles the QueryExtended opcode - -The QueryExtended opcode parameter will be a NULL terminated string with -a space seperated list of extended options being queried, such as: - - NM BR CL Which is requesting Name (of server), Baud Rate and - Condensed List support - -The proper response is a RET_QUERY_EXTENDED packet that looks like: - - 0: 0x14 - 1: Length byte - 2-n: NM=NADSBox BR=9600,19200,38400,57600,76800,115200,230400 CL:Y \0 - N+1: Checksum - -=========================================================================== -*/ -void VTTpddServer::OpcodeQueryExtended(void) -{ - MString resp; - const char *ptr; - int len, c; - - // TPDD_RET_QUERY_EXTENDED - ptr = strtok(&m_rxBuffer[TPDD_PKT_DATA_INDEX], " "); - - // Loop for all entries in in opcode parameter list - while (ptr != NULL) - { - // Add this extended parameter to the response - resp += ptr; - - if (strcmp(ptr, "NM") == 0) - // Provide the our Server Name - resp += (char *) "=VTNADS"; - else if (strcmp(ptr, "BR") == 0) - // Provide list of virtual baud rates we support - resp += (char *) "=38400,57600,76800,115200,230400"; - else if (strcmp(ptr, "CL") == 0) - // Indicate Condensed List API supported - resp += (char *) ":Y"; - else - // Anything else we don't support so respond "N"ot supported - resp += (char *) ":N"; - - // Get pointer to next extended parameter in list - ptr = strtok(NULL, " "); - - // Add a space separator if there are more parameters in the list - if (ptr != NULL) - resp += (char *) " "; - } - - // Okay now send out the response - m_txChecksum = 0; - len = resp.GetLength() + 1; - - // Send API code - TpddSendByte(TPDD_RET_QUERY_EXTENDED); - TpddSendByte(len); - - // Send out the response dat - ptr = (const char *) resp; - for (c = 0; c < len; c++) - { - // Send to host and calc checksum - TpddSendByte(*ptr++); - } - - // Now send the checksum - TpddSendChecksum(); -} - -/* -=========================================================================== -Handles the CondensedList opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeCondensedList(void) -{ -} - -/* -=========================================================================== -Handles the Mystery 0x23 opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeMystery23(void) -{ - const char op23Table[] = "\x14\x0F\x41\x10\x01\x00\x50\x05\x00\x02\x00\x28\x00\xE1\x00\x00\x00"; - const char op23Len = sizeof(op23Table)-1; - int c; - - // Send bytes from the table - m_txChecksum = 0; - for (c = 0; c < op23Len; c++) - { - // Send to host and calc checksum - TpddSendByte(op23Table[c]); - } - - // Now send the checksum - TpddSendChecksum(); -} - -/* -=========================================================================== -Handles the Mystery 0x31 opcode -=========================================================================== -*/ -void VTTpddServer::OpcodeMystery31(void) -{ - // Send mystery 31 response - m_txChecksum = 0; - TpddSendByte(0x38); - TpddSendByte(1); - TpddSendByte(0); - - // Now send the checksum - TpddSendChecksum(); -} - -/* -=========================================================================== -Sends a Normal Return packet. This is a packet with 4 bytes and an ID -of 12, length 1 with an error code and checksum. -=========================================================================== -*/ -void VTTpddServer::SendNormalReturn(unsigned char errCode) -{ - // Send a Normal Return - m_txChecksum = 0; - TpddSendByte(TPDD_RET_NORMAL); - TpddSendByte(1); - TpddSendByte(errCode); - - // Now send the checksum - TpddSendChecksum(); -} - -/* -=========================================================================== -Sends the DME response packet to the server -=========================================================================== -*/ -void VTTpddServer::SendDmeResponse(void) -{ - MString dir; - int c, len; - - // Send the start of the DME Resp packet - m_txChecksum = 0; - TpddSendByte(0x12); // Opcode - TpddSendByte(0x0B); // Length - TpddSendByte(0x00); // RESVD - - // Now send the 6-byte directory name - if (m_curDir == "/") - dir = "ROOT "; - else - { - // Find last '/' in the current directory - len = m_curDir.GetLength(); - if (m_curDir[len-1] == '/') - len--; - for (c = len-1; c >= 0; c--) - if (m_curDir[c] == '/') - break; - c++; - - // Now copy up to 6 bytes of the dir name - while (dir.GetLength() < 6 && c < len) - dir += (char) toupper(m_curDir[c++]); - // Space pad to 6 characters - while (dir.GetLength() < 6) - dir += ' '; - } - - // Add the ".<>" extension - dir += (char *) ".<> "; - - // Now send the filename - len = dir.GetLength(); - for (c = 0; c < len; c++) - TpddSendByte(dir[c]); - - // Now send the checksum - TpddSendChecksum(); -} - -/* -=========================================================================== -Change directory to the directory specified -=========================================================================== -*/ -int VTTpddServer::ChangeDirectory(MString& sDir) -{ - MString dirName; - int len = sDir.GetLength(); - - // Strip any trailing ".<>" - if (sDir.Right(3) == ".<>") - dirName = sDir.Left(len - 3); - else - dirName = sDir; - dirName.Trim(); - - // Now change directory - return ChangeDirectory((const char *) dirName); -} - -/* -=========================================================================== -Change directory to the directory specified -=========================================================================== -*/ -int VTTpddServer::ChangeDirectory(const char *pDir) -{ - int ret = 0; - MString find_name; - - // Test if changing to parent directory - if (strcmp(pDir, "..") == 0) - { - // Ensure we aren't at root already - if (m_curDir != "/") - { - // Search backward for the last '/' - int idx = m_curDir.GetLength() - 2; - while (idx >= 0 && m_curDir[idx] != '/') - idx--; - idx++; - m_curDir = m_curDir.Left(idx); - ret = 1; - } - else - ret = 0; - } - else if (strcmp(pDir, ".") == 0) - return 1; - else - { - MString file_path = m_sRootDir + m_curDir; - dirent** e; - int num = fl_filename_list((const char *) file_path, &e ); - int i; - - // For directories, append the '/' for the search - find_name = pDir; - find_name += '/'; - - // If any files found - if (num > 0) - { - // Loop through all files in the list and perform a - // case insensitive compare - for ( i = 0; i < num; i++ ) - { - const char* name = e[i]->d_name; - - // Compare this file with the requested filename - if (strcasecmp(name, find_name) == 0) - { - // Directory found! Append directory to current directory - m_curDir += name; - ret = 1; - break; - } - } - } - - // Free the directory entries - for (i = 0; i < num; i++) - free((void*) (e[i])); - free((void*) e); - } - - // Delete existing dirent structure - ResetDirent(); - - return ret; -} - -/* -=========================================================================== -Delete all entries in m_activeDir -=========================================================================== -*/ -void VTTpddServer::ResetDirent(void) -{ - int i; - - // Now free the list memory - for( i = 0; i < m_dirCount; i++ ) - free((void*) (m_activeDir[i])); - free((void*) m_activeDir); - - // Clear out the dirent - m_activeDir = NULL; - m_dirCount = 0; -} - -/* -=========================================================================== -Delete all entries in m_activeDir -=========================================================================== -*/ -int VTTpddServer::IsCmdlineState(void) -{ - return m_state == TPDD_STATE_CMDLINE; -} - -// vim: noet ts=4 sw=4 +/* tpddserver.cpp */ + +/* $Id$ */ + +/* + * Copyright 2013 Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +//#include +#include +#include +#ifdef _WIN32 +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "FLU/Flu_File_Chooser.h" + +#include "VirtualT.h" +#include "m100emu.h" +#include "tpddserver.h" +#include "tpddserverlog.h" +#include "serial.h" +#include "display.h" +#include "cpuregs.h" +#include "periph.h" +#include "memedit.h" +#include "fileview.h" + +#ifdef _MSC_VER +//not #if defined(_WIN32) || defined(_WIN64) because we have strncasecmp in mingw +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#endif + +#define COLOR_BG (gMidnight ? FL_BLACK : fl_rgb_color(192, 192, 192)) +#define COLOR_BG_INPUT (gMidnight ? FL_BLACK : FL_WHITE) +#define COLOR_FG (gMidnight ? FL_WHITE : FL_BLACK) +#define COLOR_TAB_INACTIVE_BG (gMidnight ? fl_rgb_color(32,32,32) : fl_rgb_color(192,192,192)) +#define COLOR_TAB_INACTIVE_FG (gMidnight ? fl_rgb_color(192,192,192) : FL_BLACK) + +enum { + TPDD_STATE_IDLE = 0, + TPDD_STATE_Z, + TPDD_STATE_OPCODE, + TPDD_STATE_LEN, + TPDD_STATE_READ_BYTES, + TPDD_STATE_READ_CHECKSUM, + TPDD_STATE_M, + TPDD_STATE_M1, + TPDD_STATE_R, + TPDD_STATE_CMDLINE, + TPDD_STATE_EXEC +}; + +// =============================================== +// Extern "C" linkage items +// =============================================== +extern "C" +{ +extern volatile UINT64 cycles; +extern volatile DWORD rst7cycles; + +#ifdef WIN32 +int strcasecmp(const char* s1, const char* s2); +#endif +} +extern int gMidnight; + +/* +====================================================== +Structure for the setup GUI controls. +====================================================== +*/ +typedef struct tpddserver_ctrl_struct +{ + Fl_Input* pRootDir; // Pointer to root dir input + char sRootDir[512]; + Fl_Button* pTpddDir; // Create TPDD directory listing +} tpddserver_ctrl_t; + +// =============================================== +// Extern and global variables +// =============================================== +extern Fl_Preferences virtualt_prefs; +static Fl_Window* gtcw = NULL; +tpddserver_ctrl_t gTsCtrl; + +// Define the array of NADSBox commands +VT_NADSCmd_t VTTpddServer::m_Cmds[] = { + { "cd", &VTTpddServer::CmdlineCd, "cd path - Change Directory" }, +// { "copy", &VTTpddServer::CmdlineCopy }, +// { "date", &VTTpddServer::CmdlineDate }, +// { "del", &VTTpddServer::CmdlineDel }, + { "dir", &VTTpddServer::CmdlineDir, "dir [-dw] [file] - Directory" }, + { "help", &VTTpddServer::CmdlineHelp, "help [command] - Display help" }, +// { "info", &VTTpddServer::CmdlineInfo }, +// { "mkdir", &VTTpddServer::CmdlineMkdir }, + { "pwd", &VTTpddServer::CmdlinePwd, "pwd - Show working directory" }, +// { "ren", &VTTpddServer::CmdlineRen }, +// { "rmdir", &VTTpddServer::CmdlineRmdir }, +// { "time", &VTTpddServer::CmdlineTime }, +// { "trace", &VTTpddServer::CmdlineTrace }, +// { "type", &VTTpddServer::CmdlineType }, + { "ver", &VTTpddServer::CmdlineVer, "ver - Show emulation version" }, +}; +int VTTpddServer::m_cmdCount = sizeof(VTTpddServer::m_Cmds) / sizeof(VT_NADSCmd_t); + +// Define the array of Linux alias commands +VT_NADSCmd_t VTTpddServer::m_LinuxCmds[] = { + { "cat", &VTTpddServer::CmdlineType, "cat - Alias for 'type'" }, + { "cp", &VTTpddServer::CmdlineCopy, "cp - Alias for 'copy'" }, + { "ls", &VTTpddServer::CmdlineDir, "ls - Alias for 'dir -w'" }, + { "ll", &VTTpddServer::CmdlineDir, "ll - Alias for 'dir'" }, + { "more", &VTTpddServer::CmdlineType, "more - Alias for 'type'" }, + { "mv", &VTTpddServer::CmdlineRen, "mv - Alias for 'ren'" }, + { "rm", &VTTpddServer::CmdlineDel, "rm - Alias for 'del'" }, +}; +int VTTpddServer::m_linuxCmdCount = sizeof(VTTpddServer::m_LinuxCmds) / sizeof(VT_NADSCmd_t); + +// Define the array of Linux alias commands +VTTpddOpcodeFunc VTTpddServer::m_tpddOpcodeHandlers[] = { + &VTTpddServer::OpcodeDir, // 0x00 + &VTTpddServer::OpcodeOpen, // 0x01 + &VTTpddServer::OpcodeClose, // 0x02 + &VTTpddServer::OpcodeRead, // 0x03 + &VTTpddServer::OpcodeWrite, // 0x04 + &VTTpddServer::OpcodeDelete, // 0x05 + &VTTpddServer::OpcodeFormat, // 0x06 + &VTTpddServer::OpcodeDriveStatus, // 0x07 + &VTTpddServer::OpcodeId, // 0x08 + &VTTpddServer::OpcodeSeek, // 0x09 + &VTTpddServer::OpcodeTell, // 0x0A + &VTTpddServer::OpcodeSetExtended, // 0x0B + &VTTpddServer::OpcodeDriveCond, // 0x0C + &VTTpddServer::OpcodeRename, // 0x0D + &VTTpddServer::OpcodeQueryExtended, // 0x0E + &VTTpddServer::OpcodeCondensedList, // 0x0F +}; + +int VTTpddServer::m_tpddOpcodeCount = sizeof(VTTpddServer::m_tpddOpcodeHandlers) / sizeof(VTNADSCmdlineFunc); + +/* +============================================================================ +Callback routine for the File Viewer window +============================================================================ +*/ +void cb_tcwin (Fl_Widget* w, void*) +{ + // Hide the window + gtcw->hide(); + + // Delete the window and set to NULL + delete gtcw; + gtcw = NULL; +} + +/* +============================================================================ +Callback routine to read TPDD / NADSBox directory +============================================================================ +*/ +static void cb_TpddDir(Fl_Widget* w, void*) +{ + Flu_File_Chooser* fc; + char fc_path[256]; + int count; + const char *filename; + + // Create chooser window to pick file + strncpy(fc_path, gTsCtrl.pRootDir->value(), sizeof(fc_path)); + fl_cursor(FL_CURSOR_WAIT); + fc = new Flu_File_Chooser(fc_path, "", Flu_File_Chooser::DIRECTORY, "Choose Root Directory"); + fl_cursor(FL_CURSOR_DEFAULT); + fc->preview(0); + fc->show(); + + // Show Chooser window + while (fc->visible()) + Fl::wait(); + + count = fc->count(); + if (count == 0) + { + delete fc; + return; + } + + // Get Filename + filename = fc->value(); + if (filename == 0) + { + delete fc; + return; + } + + // Copy the new root + strncpy(gTsCtrl.sRootDir, filename, sizeof(gTsCtrl.sRootDir)); + gTsCtrl.pRootDir->value(gTsCtrl.sRootDir); + + delete fc; +} + +/* +============================================================================ +Callback routine for the cancel button +============================================================================ +*/ +static void cb_tpdd_cancel(Fl_Widget* w, void*) +{ + // Hide and delete the window + gtcw->hide(); + delete gtcw; + gtcw = NULL; +} + +/* +============================================================================ +Callback routine for the Ok button +============================================================================ +*/ +static void cb_tpdd_ok(Fl_Widget* w, void* pOpaque) +{ + // hide the window + gtcw->hide(); + + // Get the updated root directory + const char *pDir = gTsCtrl.pRootDir->value(); + + VTTpddServer* pServer = (VTTpddServer *) ser_get_tpdd_context(); + strcpy(gTsCtrl.sRootDir, pDir); + pServer->RootDir(pDir); + + // Delete the window + delete gtcw; + gtcw = NULL; +} + +/* +============================================================================ +Routine to create the TPDD Server configuration window +============================================================================ +*/ +void tpdd_server_config(void) +{ + Fl_Box* o; + Fl_Button* b; + + if (gtcw != NULL) + return; + + // Create TPDD Server configuration window + gtcw = new Fl_Double_Window(480, 150, "TPDD / NADSBox Server"); + gtcw->callback(cb_tcwin); + gtcw->color(COLOR_BG); + + o = new Fl_Box(20, 20, 80, 20, "Root Directory"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + o->labelcolor(COLOR_FG); + + // Create an input field to edit / show the root directory + gTsCtrl.pRootDir = new Fl_Input(35, 40, 325, 20, ""); + VTTpddServer* pServer = (VTTpddServer *) ser_get_tpdd_context(); + strcpy(gTsCtrl.sRootDir, pServer->RootDir()); + gTsCtrl.pRootDir->value(gTsCtrl.sRootDir); + gTsCtrl.pRootDir->color(COLOR_BG); + gTsCtrl.pRootDir->textcolor(COLOR_FG); + gTsCtrl.pRootDir->cursor_color(COLOR_FG); + + // Create a browse button for the root directory + gTsCtrl.pTpddDir = new Fl_Button(380, 40, 80, 20, "Browse"); + gTsCtrl.pTpddDir->callback(cb_TpddDir); + gTsCtrl.pTpddDir->color(COLOR_BG); + gTsCtrl.pTpddDir->labelcolor(COLOR_FG); + + // Create a Cancel button + b = new Fl_Button(200, 120, 80, 20, "Cancel"); + b->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE); + b->callback(cb_tpdd_cancel); + b->color(COLOR_BG); + b->labelcolor(COLOR_FG); + + // Create an OK button + b = new Fl_Return_Button(300, 120, 80, 20, "OK"); + b->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE); + b->callback(cb_tpdd_ok); + b->color(COLOR_BG); + b->labelcolor(COLOR_FG); + + gtcw->show(); +} + +/* +=========================================================================== +Define Serial port interface "C" routines below +=========================================================================== +*/ +extern "C" +{ + +/* +=========================================================================== +tpdd_alloc_context: Allocates a context to define and control the TPDD + server routines. +=========================================================================== +*/ +void* tpdd_alloc_context(void) +{ + return (void *) new VTTpddServer; +} + +/* +=========================================================================== +tpdd_free_context: Frees the given context. +=========================================================================== +*/ +void tpdd_free_context(void* pContext) +{ + // Validate the context is not null + if (pContext != NULL) + { + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + delete pTpdd; + } +} + +/* +=========================================================================== +tpdd_load_prefs: Loads the tpdd server preferences from the user file. +=========================================================================== +*/ +void tpdd_load_prefs(void* pContext) +{ + char rootDir[512]; + VTTpddServer* pServer; + + virtualt_prefs.get("TpddServer_RootDir", rootDir, path, sizeof(rootDir)); + pServer = (VTTpddServer *) pContext; + pServer->RootDir(rootDir); +} + +/* +=========================================================================== +tpdd_save_prefs: Saves the tpdd server preferences to the user file. +=========================================================================== +*/ +void tpdd_save_prefs(void* pContext) +{ + VTTpddServer* pServer = (VTTpddServer *) pContext; + + virtualt_prefs.set("TpddServer_RootDir", pServer->RootDir()); +} + +/* +=========================================================================== +tpdd_close_serial: Closes the simulated TPDD serial session. +=========================================================================== +*/ +int tpdd_close_serial(void* pContext) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerClosePort(); +} + +/* +=========================================================================== +tpdd_open_serial: Opens the simulated TPDD serial session. +=========================================================================== +*/ +int tpdd_open_serial(void* pContext) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerOpenPort(); +} + +/* +=========================================================================== +tpdd_ser_set_baud: Sets the simulated baudrate for the TPDD server. +=========================================================================== +*/ +int tpdd_ser_set_baud(void* pContext, int baud_rate) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerSetBaud(baud_rate); +} + +/* +=========================================================================== +tpdd_ser_get_flags: Returns the port flags for the TPDD server +=========================================================================== +*/ +int tpdd_ser_get_flags(void* pContext, unsigned char *flags) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerGetFlags(flags); +} + +/* +=========================================================================== +tpdd_ser_set_signals: Sets the simulated port signals for the TPDD server +=========================================================================== +*/ +int tpdd_ser_set_signals(void* pContext, unsigned char signals) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerSetSignals(signals); +} + +/* +=========================================================================== +tpdd_ser_get_signals: Sets the simulated port signals for the TPDD server +=========================================================================== +*/ +int tpdd_ser_get_signals(void* pContext, unsigned char *signals) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerGetSignals(signals); +} + +/* +=========================================================================== +tpdd_ser_read_byte: Reads a byte from the TPDD server +=========================================================================== +*/ +int tpdd_ser_read_byte(void* pContext, char* data) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerReadByte(data); +} + +/* +=========================================================================== +tpdd_ser_write_byte: Writes a byte to the TPDD server +=========================================================================== +*/ +int tpdd_ser_write_byte(void* pContext, char data) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerWriteByte(data); +} + +/* +=========================================================================== +tpdd_get_port_name: Returns a printer to the name of this tpdd port +=========================================================================== +*/ +const char* tpdd_get_port_name(void* pContext) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerGetPortName(); +} + +/* +=========================================================================== +tpdd_ser_poll: Poll the TPDD Server to test if it has data available +=========================================================================== +*/ +int tpdd_ser_poll(void* pContext) +{ + VTTpddServer* pTpdd = (VTTpddServer *) pContext; + + // Let the TPDD Server class handle it + return pTpdd->SerPoll(); +} + +} /* End of extern "C" block */ + +/* +=========================================================================== +VTTpddServer class function implementaion follows. This is the constructor +=========================================================================== +*/ +VTTpddServer::VTTpddServer(void) +{ + int c; + + // Clear out the rx and tx buffers + m_rxCount = m_txCount = 0; + m_rxIn = 0; + m_txIn = m_txOut = 0; + for (c = 0; c < TPDD_MAX_FDS; c++) + { + m_refFd[c] = NULL; + m_mode[c] = 0; + } + m_lastWasRx = FALSE; + m_lastOpenWasDir = FALSE; + m_refIsDirectory = FALSE; + m_activeFd = 0; + m_backgroundCmd = NULL; + m_activeDir = NULL; + m_dirDir = NULL; + m_logEnabled = FALSE; + m_dirCount = m_dirNext = 0; + m_tsdosDmeReq = m_tsdosDmeStart = FALSE; + + // Reset the TPDD to idle state + m_state = TPDD_STATE_IDLE; + + // Initialze the working dir and rootpath + m_curDir = "/"; + m_sRootDir = path; +} + +/* +=========================================================================== +Class destructor +=========================================================================== +*/ +VTTpddServer::~VTTpddServer(void) +{ + int c; + + // Close any open file + for (c = 0; c < TPDD_MAX_FDS; c++) + { + if (m_refFd[c] != NULL) + fclose(m_refFd[c]); + m_refFd[c] = NULL; + } + + // Test if any active dirent list + ResetDirent(); +} + +/* +=========================================================================== +Set the root emulation directory +=========================================================================== +*/ +void VTTpddServer::RootDir(const char *pDir) +{ + int len; + + // Update the root directory + len = strlen(pDir); + m_sRootDir = pDir; + + // Remove trailing '/' or '\' + if (pDir[len-1] == '/' || pDir[len-1] == '\\') + m_sRootDir = m_sRootDir.Left(len - 1); + + // If there are any open files, then they have to be marked to send + // a TPDD_ERR_DISK_CHANGE_ERR error + // TODO: Do this!! +} + +/* +=========================================================================== +Opens the TpddServer port +=========================================================================== +*/ +int VTTpddServer::SerOpenPort(void) +{ + // Clear out the rx and tx buffers + m_txOverflow = m_rxOverflow = FALSE; + m_cycleDelay = 100000; + m_lastReadCycles = cycles; + + return SER_NO_ERROR; +} + +/* +=========================================================================== +Closes the TpddServer port +=========================================================================== +*/ +int VTTpddServer::SerClosePort(void) +{ + return SER_NO_ERROR; +} + +/* +=========================================================================== +Returns the name of the simulated port +=========================================================================== +*/ +const char* VTTpddServer::SerGetPortName(void) +{ + return (const char *) "TPDD"; +} + +/* +=========================================================================== +Sets the baud rate of the simulated TPDD server +=========================================================================== +*/ +int VTTpddServer::SerSetBaud(int baud_rate) +{ + // Save the simulated baud rate + m_baudRate = baud_rate; + + return SER_NO_ERROR; +} + +/* +=========================================================================== +Sets the simulated port flags +=========================================================================== +*/ +int VTTpddServer::SerGetFlags(unsigned char *flags) +{ + // Test if we can receive more data + if (m_rxCount + 1 < (int) sizeof(m_rxBuffer)) + *flags = SER_FLAG_TX_EMPTY; + else + *flags &= ~SER_FLAG_TX_EMPTY; + + if (gModel == MODEL_T200) + *flags |= SER_FLAG_CTS | SER_FLAG_DSR; + + return SER_NO_ERROR; +} + +/* +=========================================================================== +Sets the simulated port signals +=========================================================================== +*/ +int VTTpddServer::SerSetSignals(unsigned char signals) +{ + return SER_NO_ERROR; +} + +/* +=========================================================================== +Gets the simulated port signals +=========================================================================== +*/ +int VTTpddServer::SerGetSignals(unsigned char *signals) +{ + *signals = SER_SIGNAL_CTS | SER_SIGNAL_DSR | SER_SIGNAL_DTR | SER_SIGNAL_RTS; + + return SER_NO_ERROR; +} + +/* +=========================================================================== +Reads a byte from the TPDD Server +=========================================================================== +*/ +int VTTpddServer::SerReadByte(char *data) +{ + // Test if any data available + if (m_txCount == 0) + return SER_NO_DATA; + + // "Read" the next byte from the TX buffer + *data = m_txBuffer[m_txOut++]; + if (m_txOut >= (int) sizeof(m_txBuffer)) + m_txOut = 0; + + LogData(*data, TPDD_LOG_TX); + + // Decrement the count + m_txCount--; + + // "Kick" transmission of the next block of data from background command + if (m_backgroundCmd != NULL) + { + // Continue execution of the command in the background + if ((this->*m_backgroundCmd)(TRUE) == 0) + { + // Background command terminated + m_backgroundCmd = NULL; + SendToHost("> "); + + // Clear out the RX path + m_rxIn = m_rxCount = 0; + m_state = TPDD_STATE_IDLE; + } + } + + // If the count reached zero, then we need to indicate that to the + // serial routines so it will clear the interrupt + if (m_txCount == 0) + return SER_LAST_BYTE; + + // Update the time (cycles) of the last read + m_lastReadCycles = cycles; + + return SER_NO_ERROR; +} + +/* +=========================================================================== +Test if any bytes available to read and return appropriate status code +=========================================================================== +*/ +int VTTpddServer::SerPoll(void) +{ + // Test if any data in the TX buffer + if (m_txCount == 0) + return SER_NO_DATA; + + // Test if enough "time" (i.e. cycles) have elapsed + if (cycles > (UINT64) (m_lastReadCycles + m_cycleDelay)) + return SER_NO_ERROR; + + return SER_NO_DATA; +} + +/* +=========================================================================== +Sends a single character to the host +=========================================================================== +*/ +void VTTpddServer::SendToHost(char data) +{ + // Validate the TX buffer isn't full + if (m_txCount + 1 >= (int) sizeof(m_txBuffer)) + { + m_txOverflow = TRUE; + return; + } + + // Add the byte + m_txBuffer[m_txIn++] = data; + if (m_txIn >= (int) sizeof(m_txBuffer)) + m_txIn = 0; + m_txCount++; +} + +/* +=========================================================================== +Sends a string of characters to the host +=========================================================================== +*/ +void VTTpddServer::SendToHost(const char* data) +{ + while (*data != '\0') + SendToHost(*data++); +} + +/* +=========================================================================== +Processes received bytes while in the command line state +=========================================================================== +*/ +void VTTpddServer::StateCmdline(char data) +{ + // Test for CR + if (data == '\r') + { + // Echo CRLF to host + if (data != 0x1B) + SendToHost("\r\n"); + + // If there's no background command active... + if (m_backgroundCmd == NULL) + { + // Terminate the command and execute it + m_rxBuffer[m_rxIn] = '\0'; + m_cycleDelay = 400000; + ExecuteCmdline(); + } + + // Now reset the rxBuffer and go to idle + m_rxIn = m_rxCount = 0; + m_state = TPDD_STATE_IDLE; + return; + } + // Test for BKSP + else if (data == 0x08) + { + // Process the backspace + if (m_rxCount > 0) + { + // Erase the line from the host + SendToHost("\x08 \x08"); + m_rxCount--; + m_rxIn--; + + // If we backspaced to zero, then go to IDLE state + if (m_rxCount == 0) + m_state = TPDD_STATE_IDLE; + } + + return; + } + + // We have received part of a command line and we are looking for a CR, + // but must look for a 'Z' or 'M' after a timeout also + if (m_rxCount + 1 >= (int) sizeof(m_rxBuffer)) + { + // Buffer overflow!!! Go to idle state + m_rxIn = m_rxCount = 0; + m_state = TPDD_STATE_IDLE; + m_rxOverflow = TRUE; + return; + } + + else + { + // Add the byte to our rx buffer + m_rxBuffer[m_rxIn++] = data; + m_rxCount++; + + // Echo the byte back to the host + if (data != 0x1B) + SendToHost(data); + } +} + +/* +=========================================================================== +Handles the "cd" command +=========================================================================== +*/ +int VTTpddServer::CmdlineCd(int background) +{ + MString dirSave; + MString temp; + MString subDir; + int len, i; + + if (!background) + { + // Test if an arguemnt given + if (m_args.GetSize() == 0) + { + SendToHost("no argument given\r\n"); + return FALSE; + } + + // We could have multiple directories in the arg, such as "../M100" + // Process them one at a time. First save the current directory + // in case of error. + temp = m_args[0]; + len = temp.GetLength(); + dirSave = m_curDir; + + // Test if directory starts with '/' + i = 0; + if (temp[0] == '/') + { + i++; + m_curDir = '/'; + } + + // Get the first subdir specification + while (i < len && temp[i] != '/') + subDir += (char) temp[i++]; + + // Skip the '/' + if (i < len) + i++; + + while (subDir != "") + { + // Try to change to this directory + if (!ChangeDirectory(subDir)) + { + MString fmt; + fmt.Format("Dir '%s' does not exist\r\n", (const char *) subDir); + SendToHost((const char *) fmt); + m_curDir = dirSave; + return FALSE; + } + + // Get next level of subdir + subDir = ""; + + // Get the next subdir spec + while (i < len && temp[i] != '/') + subDir += (char) temp[i++]; + + // Skip the '/' + if (i < len) + i++; + } + } + + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Parses command line option arguments and creates a bitfield based on the +given option string. +=========================================================================== +*/ +int VTTpddServer::ParseOptions(MString& arg, const char* pOptions, int& flags) +{ + int c, x; + int len; + + // Initialize flags to zero + flags = 0; + + // Validate the 1st byte of arg is '-' + if (arg.GetLength() < 2 || arg[0] != '-') + return -1; + + // Start at byte just past '-' + x = 1; + len = strlen(pOptions); + while (x < arg.GetLength()) + { + // Loop through all options + for (c = 0; c < len; c++) + { + if (arg[x] == pOptions[c]) + { + flags |= 1 << c; + break; + } + } + + // Test if an invalid option was given + if (c == len) + return x; + + // Advance to next supplied option + x++; + } + + return -1; +} + +/* +=========================================================================== +Handles the "dir" command +=========================================================================== +*/ +int VTTpddServer::CmdlineDir(int background) +{ + int i, printed, col; + MString file_path; + MString fmt; + int len, isDir; + + m_cycleDelay = rst7cycles * 70 ; + if (m_cycleDelay > 1000000) + m_cycleDelay = 1000000; + + // Test if running in background or not + if (background) + { + // Wait for a key from the user before continuing + if (m_rxCount == 0) + return TRUE; + + // Key pressed. Test for ESC or CTRL-C + for (i = 0; i < m_rxCount; i++) + { + // Test if this character is CTRL-C or ESC + if (m_rxBuffer[i] == 0x03 || m_rxBuffer[i] == 0x1B || m_rxBuffer[i] == 'q') + { + // Yep, the user terminated the listing + for( i = 0; i < m_dirDirCount; i++ ) + free((void*) (m_dirDir[i])); + free((void*) m_dirDir); + m_dirDir = NULL; + SendToHost("\r\n"); + return FALSE; + } + } + + // Terminate the message line + m_rxIn = m_rxCount = 0; + SendToHost("\r \r"); + } + else + { + // Get a listing of the current directory + if (m_dirDir != NULL) + { + // Free the directory listing + for( i = 0; i < m_dirDirCount; i++ ) + free((void*) (m_dirDir[i])); + free((void*) m_dirDir); + } + + // Test if any args given + m_backgroundFlags = 0; + int options = 0; + int errOption; + if (m_args.GetSize() > 0) + { + // Test if 1st arg is options + if (m_args[0][0] == '-') + { + // Parse the options + if ((errOption = ParseOptions(m_args[0], "wd", m_backgroundFlags)) != -1) + { + // Unknown option given + MString fmt; + fmt.Format("unknown option '%c'\r\n", m_args[0][errOption]); + SendToHost((const char *) fmt); + m_rxIn = m_rxCount = 0; + return FALSE; + } + + // Indicate we used arg0 + options = 1; + } + } + + // Test if this is the 'ls' command and automatically select wide + if (m_cmd == "ls") + m_backgroundFlags |= CMD_DIR_FLAG_WIDE; + + // Test if argument other than options given + if (m_args.GetSize() - options == 0) + { + Fl_File_Sort_F *sort = fl_casealphasort; + + // Get a listing of files in the current directory + file_path = m_sRootDir + m_curDir; + m_dirDirCount = fl_filename_list((const char *) file_path, &m_dirDir, sort); + } + else + { + SendToHost("arguments not supported yet\r\n"); + m_rxIn = m_rxCount = 0; + return FALSE; + } + + // Start at beginning of list + m_dirDirNext = 0; + } + + // Display a page of entries + printed = 0; + col = 0; + + // Loop for all directory entries and send the next screen to client + for (i = m_dirDirNext; i < m_dirDirCount; i++) + { + const char* name = m_dirDir[i]->d_name; + MString printName; + + // ignore the "." and ".." names + if ( strcmp( name, "." ) == 0 || strcmp( name, ".." ) == 0 || + strcmp( name, "./" ) == 0 || strcmp( name, "../" ) == 0 || + strcmp( name, ".\\" ) == 0 || strcmp( name, "..\\" ) == 0 ) + { + continue; + } + + // Test if this is a directory + isDir = FALSE; + if (name[strlen(name)-1] == '/') + isDir = TRUE; + + // Test if only directories requested + if ((m_backgroundFlags & CMD_DIR_FLAG_DIR) && !isDir) + continue; + + // Get length of file + if (!isDir) + { + // Open the file and seek to the end + MString temp = m_sRootDir + m_curDir + name; + FILE* fd = fopen((const char *) temp, "r"); + len = 0; + + // Seek and tell only if file opened + if (fd != NULL) + { + fseek(fd, 0, SEEK_END); + len = ftell(fd); + fclose(fd); + } + } + + // Print this entry + if ((m_backgroundFlags & CMD_DIR_FLAG_WIDE) == 0) + { + // Not in wide display format + if (!isDir) + { + fmt.Format("%-20s%8d\r\n", name, len); + fmt.MakeUpper(); + } + else + { + MString temp = name; + temp = temp.Left(temp.GetLength()-1); + temp.MakeUpper(); + fmt.Format("%-17s\r\n", (const char *) temp); + } + SendToHost((const char *) fmt); + printed++; + } + else + { + // Printing in wide format... 2 entries per line + + if (!isDir) + { + // Truncate name to 12 places + char temp[13]; + strncpy(temp, name, 12); + temp[12] = '\0'; + if (strlen(name) < 12) + temp[strlen(name)] = '\0'; + + // Max display size is 99999 + if (len < 100000) + fmt.Format("%-13s%6d", temp, len); + else + fmt.Format("%-13>99999", temp); + fmt.MakeUpper(); + } + else + { + MString temp = name; + temp = temp.Left(temp.GetLength()-1); + temp.MakeUpper(); + fmt.Format("%-13s ", (const char *) temp); + } + + SendToHost((const char *) fmt); + if (col++ == 1) + { + col = 0; + printed++; + } + else + SendToHost(" "); + } + + // Test if a page printed + if (gModel == MODEL_T200) + { + if (printed == 15) + { + i++; + break; + } + } + else if (printed == 7) + { + i++; + break; + } + } + + // Test if we ended on col 1 in a wide format + if ((m_backgroundFlags & CMD_DIR_FLAG_WIDE) && col == 1) + SendToHost("\r\n"); + + // Save index for next listing + m_dirDirNext = i; + + // Test if all entries printed + if (i == m_dirDirCount) + { + // Free the directory listing + for( i = 0; i < m_dirDirCount; i++ ) + free((void*) (m_dirDir[i])); + free((void*) m_dirDir); + m_dirDir = NULL; + + // Don't need to execute in the background + return FALSE; + } + + // We have more to display. Present a message + SendToHost("Any key to continue, 'q' to stop..."); + + // Need to execute in the background + return TRUE; +} + +/* +=========================================================================== +Handles the "rmdir" command +=========================================================================== +*/ +int VTTpddServer::CmdlineRmdir(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "Mkdir" command +=========================================================================== +*/ +int VTTpddServer::CmdlineMkdir(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "del" command +=========================================================================== +*/ +int VTTpddServer::CmdlineDel(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "copy" command +=========================================================================== +*/ +int VTTpddServer::CmdlineCopy(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "ren" command +=========================================================================== +*/ +int VTTpddServer::CmdlineRen(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "trace" command +=========================================================================== +*/ +int VTTpddServer::CmdlineTrace(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "type" command +=========================================================================== +*/ +int VTTpddServer::CmdlineType(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "date" command +=========================================================================== +*/ +int VTTpddServer::CmdlineDate(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "time" command +=========================================================================== +*/ +int VTTpddServer::CmdlineTime(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "info" command +=========================================================================== +*/ +int VTTpddServer::CmdlineInfo(int background) +{ + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "help" command +=========================================================================== +*/ +int VTTpddServer::CmdlineHelp(int background) +{ + int c, cmdsThisLine; + + // Counts the number of commands printed on this line + cmdsThisLine = 0; + + m_cycleDelay = rst7cycles * 70 ; + if (m_cycleDelay > 1000000) + m_cycleDelay = 1000000; + + if (!background) + { + // Test if an argument given + if (m_args.GetSize() == 0) + { + // Loop for all commands + for (c = 0; c < m_cmdCount; c++) + { + SendToHost(m_Cmds[c].pCmd); + if (++cmdsThisLine == 4) + { + // Terminate this line + cmdsThisLine = 0; + SendToHost("\r\n"); + } + else + { + // Send a tab between commands + SendToHost("\t"); + } + } + + // Test if we need a final CRLF + if (cmdsThisLine != 0) + SendToHost("\r\n"); + } + else + { + // Show help for a specific command + for (c = 0; c < m_cmdCount; c++) + { + // Test if this item matches + if (m_args[0] == m_Cmds[c].pCmd) + { + // Display help for this command + SendToHost(m_Cmds[c].pHelp); + SendToHost("\r\n"); + return FALSE; + } + else if (c < m_linuxCmdCount) + { + if (m_args[0] == m_LinuxCmds[c].pCmd) + { + // Display help for this command + SendToHost(m_LinuxCmds[c].pHelp); + SendToHost("\r\n"); + return FALSE; + } + } + + // Test if all commands requested + if (m_args[0] == "all") + { + // Display help for this command + SendToHost(m_Cmds[c].pHelp); + SendToHost("\r\n"); + } + } + + // If all commands requested, then return + if (m_args[0] == "all") + return FALSE; + + // Command not found + MString fmt; + fmt.Format("unknown command '%s'\r\n", (const char *) m_args[0]); + SendToHost((const char *) fmt); + } + } + + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "pwd" command +=========================================================================== +*/ +int VTTpddServer::CmdlinePwd(int background) +{ + MString temp = m_curDir; + + if (!background) + { + temp.MakeUpper(); + if (temp.GetLength() > 1) + if (temp[temp.GetLength()-1] == '/') + temp = temp.Left(temp.GetLength()-1); + SendToHost((const char *) temp); + SendToHost("\r\n"); + } + + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Handles the "ver" command +=========================================================================== +*/ +int VTTpddServer::CmdlineVer(int background) +{ + // Send our Version information to the host + if (!background) + { + SendToHost("VirtualT's emulated NADSBox\r\n"); + SendToHost("Firmware v1.14 equivalent\r\n"); + SendToHost("Copyright 2013, Kenneth D. Pettit\r\n"); + } + + // Don't need to execute in the background + return FALSE; +} + +/* +=========================================================================== +Executes the command line command in the m_rxBuffer +=========================================================================== +*/ +void VTTpddServer::ExecuteCmdline(void) +{ + int c; + char* ptr; + MString cmd, arg; + + // Split the m_rxBuffer into command and args + ptr = m_rxBuffer; + + // Remove previous arguments + m_args.RemoveAll(); + + // Get the command + while (*ptr != '\0' && *ptr != ' ') + cmd += *ptr++; + + // Now get the args + while (*ptr == ' ') + ptr++; + while (*ptr != '\0') + { + // Clear out the argument + arg = ""; + while (*ptr != ' ' && *ptr != '\0') + arg += *ptr++; + + // Add to the args array + m_args.Add(arg); + + // Skip whitespace + while (*ptr == ' ') + ptr++; + } + + // Loop through all registered commands and see if we have a match + for (c = 0; c < m_cmdCount; c++) + { + // Test if this command matches + if (strcmp(m_Cmds[c].pCmd, (const char *) cmd) == 0) + { + // This command matches the rxBuffer. Call the command handler + m_cmd = m_Cmds[c].pCmd; + if ((this->*m_Cmds[c].pFunc)(FALSE)) + m_backgroundCmd = m_Cmds[c].pFunc; + break; + } + } + + // Test if command not foune + if (c == m_cmdCount) + { + // Search the Linux equivalent commands + for (c = 0; c < m_linuxCmdCount; c++) + { + // Test if this command matches + if (strcmp(m_LinuxCmds[c].pCmd, (const char *) cmd) == 0) + { + // This command matches the rxBuffer. Call the command handler + m_cmd = m_LinuxCmds[c].pCmd; + if ((this->*m_LinuxCmds[c].pFunc)(FALSE)) + m_backgroundCmd = m_LinuxCmds[c].pFunc; + break; + } + } + + // Test if command not found in Linux alias list either + if (c == m_linuxCmdCount) + { + // Test for "flash" command + if (strcmp("flash", (const char *) cmd) == 0) + SendToHost("'flash' not supported in emulation\r\n"); + else if (strcmp("stats", (const char *) cmd) == 0) + SendToHost("'stats' not supported in emulation\r\n"); + else + SendToHost("Unknown command\r\n"); + } + } + + // Send an new prompt + if (m_backgroundCmd == NULL) + SendToHost("> "); +} + +/* +=========================================================================== +Executes the TPDD opcode in the m_rxBuffer +=========================================================================== +*/ +void VTTpddServer::ExecuteTpddOpcode(void) +{ + // Test opcode for mystery31 or mystery23 + if (m_opcode == TPDD_REQ_TSDOS_MYSTERY23) + OpcodeMystery23(); + else if (m_opcode == TPDD_REQ_TSDOS_MYSTERY31) + OpcodeMystery31(); + + // Normal TPDD protocol opcodes + else if (m_opcode <= TPDD_REQ_LAST_OPCODE) + { + // Call the handler routine for this opcode + (this->*m_tpddOpcodeHandlers[m_opcode])(); + } + + // Unknown opcode + else + { + // Send an error condition + SendNormalReturn(TPDD_ERR_PARAM_ERR); + } + + // Reset RX path and go to IDLE state + m_rxIn = m_rxCount = 0; + m_state = TPDD_STATE_IDLE; +} + +/* +=========================================================================== +Logs data to the packet log, either RX or TX data +=========================================================================== +*/ +void VTTpddServer::LogData(char data, int rxTx) +{ + // Log data only if the log is enabled + if (m_logEnabled && m_pServerLog != NULL) + { + m_pServerLog->LogData(data, rxTx); + } +} + +/* +=========================================================================== +Writes a byte to the TPDD Server +=========================================================================== +*/ +int VTTpddServer::SerWriteByte(char data) +{ + int c; + + // Record the time of this byte so we can perform timeout + // operations in the state machine + + // Log the byte + LogData(data, TPDD_LOG_RX); + + // Switch based on state. This is the main state machine + switch (m_state) + { + case TPDD_STATE_IDLE: + // We are in idle state. Search for 'Z', 'M', or 'R'. Any lower case + // chars or CR will take us to command line state + if (m_tsdosDmeReq && (data == 0x0D)) + { + // Reset the rx path + m_rxIn = m_rxCount = 0; + m_tsdosDmeStart = FALSE; + if (m_tsdosDmeReq++ == 2) + { + // Clear the DME request flag after the 2nd 0x0D + m_tsdosDmeReq = 0; + } + break; + } + if (m_tsdosDmeReq) + { + // Byte received that wasn't 0x0D. Clear out the DME + m_tsdosDmeReq = m_tsdosDmeStart = 0; + m_rxIn = m_rxCount = 0; + } + + // Test for command line characters + if ((data >= 'a' && data <= 'z') || m_backgroundCmd) + { + // Add the byte to our RX buffer + m_rxBuffer[m_rxIn++] = data; + m_rxCount = 1; + + // Add the byte to our TX buffer so we echo it + if (data != 0x1B) + SendToHost(data); + + // Clear out any acive TS-DOS DME activity + m_tsdosDmeStart = FALSE; + + // Goto cmdline state + m_state = TPDD_STATE_CMDLINE; + } + + // Test for empty-line CR + else if (data == '\n' || data == '\r') + { + // Send a prompt to the host + SendToHost("\r\n> "); + } + + // Search for 'Z' + else if (data == 'Z') + { + // Add the byte to our RX buffer + m_rxBuffer[m_rxIn++] = data; + m_rxCount = 1; + m_state = TPDD_STATE_Z; // Goto Z state + } + else if (data == 'M') + { + // Add the byte to our RX buffer + m_rxBuffer[m_rxIn++] = data; + m_rxCount = 1; + m_state = TPDD_STATE_M; // Goto M state + } + else if (data == 'R') + { + // Add the byte to our RX buffer + m_rxBuffer[m_rxIn++] = data; + m_rxCount = 1; + m_state = TPDD_STATE_R; // Goto R state + } + break; + + case TPDD_STATE_Z: + // We expect to see another 'Z', but look for timeout too + if (data == 'Z') + { + // Add the byte to our RX buffer + m_rxBuffer[m_rxIn++] = data; + m_rxCount++; + + // Go to the opcode state, we got the 2nd 'Z' + m_state = TPDD_STATE_OPCODE; + } + else + { + // Goto the IDLE state and reprocess the byte + m_state = TPDD_STATE_IDLE; + m_rxCount = m_rxIn = 0; // Reset the Rx buffer + SerWriteByte(data); + } + break; + + case TPDD_STATE_OPCODE: + // We have received 'ZZ', now we are waiting for the opcode byte + m_opcode = data; + + // Add the byte to our RX buffer + m_rxBuffer[m_rxIn++] = data; + m_rxCount++; + + // Go wait for the LEN byte + m_state = TPDD_STATE_LEN; + break; + + case TPDD_STATE_LEN: + // We have received the opcode, now waiting for the length byte + m_length = (unsigned char) data; + m_bytesRead = 0; + + // Add the byte to our RX buffer + m_rxBuffer[m_rxIn++] = data; + m_rxCount++; + + // Go wait for bytes + if (m_length == 0) + m_state = TPDD_STATE_READ_CHECKSUM; + else + m_state = TPDD_STATE_READ_BYTES; + break; + + case TPDD_STATE_READ_BYTES: + // Add the byte to our RX buffer + m_rxBuffer[m_rxIn++] = data; + + // Test if all bytes read + m_rxCount++; + if (++m_bytesRead == m_length) + { + // Goto state to read the checksum + m_state = TPDD_STATE_READ_CHECKSUM; + } + break; + + case TPDD_STATE_READ_CHECKSUM: + // All bytes read, now read the checksum + m_rxChecksum = data; + + // Now compute the checksum of received data + m_calcChecksum = 0; + for (c = TPDD_PKT_OPCODE_INDEX; c < m_length+4; c++) + { + // Calculate checksum across opcode, length and all data + m_calcChecksum += (unsigned char) m_rxBuffer[c]; + } + + // Compare the checksum + if ((m_calcChecksum ^ 0xFF) != m_rxChecksum) + { + // Error in checksum. Send error packet + SendNormalReturn(TPDD_ERR_ID_CRC_CHK_ERR); + } + else + { + // Execute the TPDD opcode + m_cycleDelay = 100000; + ExecuteTpddOpcode(); + } + + // Now reset RX and go to idle + m_rxIn = m_rxCount = 0; + m_state = TPDD_STATE_IDLE; + break; + + case TPDD_STATE_M: + // We have received 'M' and are waiting for '1' (the 'M1' sequence) + if (data == '1') + { + // Now wait for the 0Dh + m_rxBuffer[m_rxIn++] = data; + m_rxCount = 1; + m_state = TPDD_STATE_M1; + } + else + { + // Reset RX path and goto idle + m_rxIn = m_rxCount = 0; + m_state = TPDD_STATE_IDLE; + } + break; + + case TPDD_STATE_M1: + // We have received 'M1'. This is used for Directory Management Extension + if (data == 0x0D) + { + // TS-DOS DME request initiated. Save the event + m_tsdosDmeStart = TRUE; + } + + // Clear the RX path and goto idle + m_rxIn = m_rxCount = 0; + m_state = TPDD_STATE_IDLE; + break; + + case TPDD_STATE_CMDLINE: + // Process in the cmdline routine + StateCmdline(data); + break; + + default: + // Unknown state. Go to idle. + m_state = TPDD_STATE_IDLE; + + // Reset the RX buffer + m_rxIn = m_rxCount = 0; + break; + } + return SER_NO_ERROR; +} + +/* +=========================================================================== +Sends the specified file entry to the server +=========================================================================== +*/ +void VTTpddServer::SendDirEntReturn(dirent* e, int dir_entry) +{ + int c, idx; + int send_spaces; + + // Clear the TX checksum + m_txChecksum = 0; + TpddSendByte(TPDD_RET_DIR_REF); // Return code + TpddSendByte(28); // Dir Entry pkt length + + // Now send 24 bytes of filename, space padded + idx = 0; + send_spaces = FALSE; + for (c = 0; c < 24; c++) + { + // Test if we are sending spaces + if (send_spaces) + TpddSendByte(' '); + else if (e == NULL) + { + TpddSendByte(0); + continue; + } + else if ((e->d_name[idx] == '.' || e->d_name[idx] == '/') && c < 6) + { + TpddSendByte(' '); + } + else if ((e->d_name[idx] == '.' && dir_entry) || e->d_name[idx] == '/') + { + // Send the '.' followed by "<>", then send spaces + TpddSendByte('.'); + TpddSendByte('<'); + TpddSendByte('>'); + c += 2; + send_spaces = true; + + // Skip idx ahead to the NULL + while (e->d_name[idx] != '\0') + idx++; + } + else if (e->d_name[idx] == '\0') + { + TpddSendByte(' '); + send_spaces = TRUE; + } + else if (e->d_name[idx] == '.' && c < 6) + TpddSendByte(' '); + else + TpddSendByte(toupper(e->d_name[idx++])); + } + + // Send the Attribute byte 'F' + if (e == NULL) + TpddSendByte(0); + else + TpddSendByte('F'); + + // Send 2-byte length + int file_len = 0; + if (!dir_entry && e) + { + // Open the file to calculate the length + MString file_path = m_sRootDir + m_curDir + e->d_name; + FILE* fd = fopen((const char *) file_path, "r"); + if (fd != NULL) + { + // Seek to end of file + fseek(fd, 0, SEEK_END); + file_len = ftell(fd); + fclose(fd); + + // Truncate file length at 64K + if (file_len > 65535) + file_len = 65535; + } + } + + // Send 2 bytes of length + TpddSendByte((file_len >> 8) & 0xFF); + TpddSendByte(file_len & 0xFF); + + // Send the number of free sectors (255) + TpddSendByte((char) 0x9D); + + // Now send the checksum + TpddSendChecksum(); +} + +/* +=========================================================================== +Finds the specified file and sends the DIR_REF retrun packet to the server. +=========================================================================== +*/ +void VTTpddServer::DirFindFile(const char* pFilename) +{ + // read the directory + dirent** e; + char* name; + int i, num, len, dir_entry; + MString file_path; + char find_name[16]; + + // Test if accessing the "PARENT.<>" file + if (strcmp(pFilename, "PARENT.<>") == 0) + { + // Just save the reference and exit + m_dirRef = pFilename; +#ifdef WIN32 + dirent* pParent = (dirent *) "PARENT.<>"; +#else + dirent parent; + dirent* pParent = &parent; + strcpy(parent.d_name, "PARENT.<>"); +#endif + SendDirEntReturn(pParent, TRUE); + return; + } + + // Construct the path using the current working directory and the root + file_path = m_sRootDir + m_curDir; + num = fl_filename_list((const char *) file_path, &e ); + m_refIsDirectory = FALSE; + + // Test if the given filename is a diretory search. If it is, then + // the filename will look like "DIRNAM.<>" + strcpy(find_name, pFilename); + len = strlen(pFilename); + if (len > 3 && pFilename[len-1] == '>' && pFilename[len-2] == '<') + { + // Indicate we are doing a directory search + m_refIsDirectory = TRUE; + + // Terminate the filename at the '.' + find_name[len-3] = '\0'; + } + + // If any files found + if (num > 0) + { + // Loop through all files in the list and perform a + // case insensitive compare + for ( i = 0; i < num; i++ ) + { + name = e[i]->d_name; + + // ignore the "." and ".." names + if ( strcmp( name, "." ) == 0 || strcmp( name, ".." ) == 0 || + strcmp( name, "./" ) == 0 || strcmp( name, "../" ) == 0 || + strcmp( name, ".\\" ) == 0 || strcmp( name, "..\\" ) == 0 ) + { + continue; + } + + // if 'name' ends in '/', remove it + dir_entry = FALSE; + if ( name[strlen(name)-1] == '/' ) + { + dir_entry = TRUE; + name[strlen(name)-1] = '\0'; + } + + // Compare this file with the requested filename + if (strcasecmp(name, find_name) == 0) + { + // Entry found! Send the DIR_ENT return + SendDirEntReturn(e[i], dir_entry); + + // Test if another file was already opened + if (m_refFd[m_activeFd] != NULL) + { + // Close the previously referenced file + fclose(m_refFd[m_activeFd]); + m_refFd[m_activeFd] = NULL; + } + + // Save this reference for future open, delete, etc. + m_dirRef = name; + m_refIsDirectory = dir_entry; + + // Now free the list memory + for( i = 0; i < num; i++ ) + free((void*)(e[i])); + free((void*)e); + + return; + } + } + + // File not found. Create a new dirent and send the reference + SendDirEntReturn(NULL, FALSE); + m_dirRef = pFilename; + + // Now free the list memory + for( i = 0; i < num; i++ ) + free((void*)(e[i])); + free((void*)e); + } + else + { + // Return error + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + } +} + +/* +=========================================================================== +Finds the first entry in the current directory and sends a DirEnt packet +to the server. +=========================================================================== +*/ +void VTTpddServer::DirFindFirst(void) +{ + // read the directory + MString file_path; + + // Construct the path using the current working directory and the root + file_path = m_sRootDir + m_curDir; + if (m_activeDir != NULL) + ResetDirent(); + m_dirCount = fl_filename_list((const char *) file_path, &m_activeDir ); + m_dirNext = 0; + + // Test if we are at the ROOT directory or not. If not at root, then + // the first entry is always "PARENT.<>" + if (m_curDir != "/") + { + // Send the "PARENT.<>" directory entry +#ifdef WIN32 + dirent* pParent = (dirent *) "PARENT.<>"; +#else + dirent parent; + dirent* pParent = &parent; + strcpy(parent.d_name, "PARENT.<>"); +#endif + SendDirEntReturn(pParent, TRUE); + } + else + { + // Call the routine to send the next directory entry + DirFindNext(); + } +} + +/* +=========================================================================== +Finds the next entry in the current directory and sends a DirEnt packet +to the server. +=========================================================================== +*/ +void VTTpddServer::DirFindNext(void) +{ + // Don't count the '.' and '..' entries in the count + while (m_dirNext < m_dirCount) + { + const char* name = m_activeDir[m_dirNext]->d_name; + if ( strcmp( name, "." ) == 0 || strcmp( name, ".." ) == 0 || + strcmp( name, "./" ) == 0 || strcmp( name, "../" ) == 0 || + strcmp( name, ".\\" ) == 0 || strcmp( name, "..\\" ) == 0 ) + { + // Subtract this entry f + m_dirNext++; + continue; + } + + // Send first directory entry + SendDirEntReturn(m_activeDir[m_dirNext], FALSE); + m_dirNext++; + break; + } + + // Send the next directory entry or all blank + if (m_dirNext >= m_dirCount) + { + // Send a blank entry + SendDirEntReturn(NULL, FALSE); + } +} + +/* +=========================================================================== +Handles the Dir opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeDir(void) +{ + char* pFilename; + char fat_filename[16]; + int idx, c; + + // Validate the length byte + if (m_length != 26) + { + SendNormalReturn(TPDD_ERR_PARAM_ERR); + return; + } + + // Convert filename from Model T 6.2 format to FAT 8.3 format + pFilename = &m_rxBuffer[TPDD_PKT_DATA_INDEX]; + idx = 0; + for (c = 0; c < 6; c++) + if ((fat_filename[idx] = *pFilename++) != ' ') + idx++; + fat_filename[idx++] = '.'; + if (*pFilename == '.') + pFilename++; + if ((fat_filename[idx] = *pFilename++) != ' ') + idx++; + if ((fat_filename[idx] = *pFilename++) != ' ') + idx++; + fat_filename[idx] = '\0'; + + // Now process the request based on the search type + switch (m_rxBuffer[TPDD_PKT_DATA_INDEX + 25]) + { + case 0: // Dir find file + DirFindFile(fat_filename); + break; + + case 1: // Find first entry + DirFindFirst(); + break; + + case 2: // Find next entry + DirFindNext(); + break; + + default: + // Unknown + SendNormalReturn(TPDD_ERR_PARAM_ERR); + break; + } +} + +/* +=========================================================================== +Handles the Open opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeOpen(void) +{ + MString open_path; + unsigned char open_mode; + + // Try to open the referenced file + open_path = m_sRootDir + m_curDir + m_dirRef; + open_mode = m_rxBuffer[TPDD_PKT_DATA_INDEX]; + + // Check if the referenced file is a directory + if (m_refIsDirectory) + { + // Mark last open as a directory change + m_lastOpenWasDir = TRUE; + + // Test the open_mode. If read mod, then CD + if (open_mode == TPDD_OPEN_MODE_READ) + { + // Perform a "Change directory" operation + if (m_dirRef == "PARENT.<>") + { + // Change to parent directory + ChangeDirectory(".."); + SendNormalReturn(TPDD_ERR_NONE); + } + else + { + // Change to m_dirRef + ChangeDirectory(m_dirRef); + SendNormalReturn(TPDD_ERR_NONE); + } + } + else if (open_mode == TPDD_OPEN_MODE_WRITE) + { + MString temp; + // Test if we need to remove the ".<>" (likely) + if (m_dirRef.Right(3) == ".<>") + temp = m_dirRef.Left(m_dirRef.GetLength()-3); + else + temp = m_dirRef; + + // MKDIR operation + temp.MakeUpper(); + MString dirToMake = m_sRootDir + m_curDir + temp; +#ifdef WIN32 + _mkdir((const char *) dirToMake); +#else + mkdir((const char *) dirToMake, 0755); +#endif + + // Send a normal return code + SendNormalReturn(TPDD_ERR_NONE); + } + } + else + { + // Open the file based on mode + if (open_mode == TPDD_OPEN_MODE_WRITE) + m_refFd[m_activeFd] = fopen((const char *) open_path, "wb"); + else if (open_mode == TPDD_OPEN_MODE_APPEND) + m_refFd[m_activeFd] = fopen((const char *) open_path, "ab"); + else if (open_mode == TPDD_OPEN_MODE_READ) + m_refFd[m_activeFd] = fopen((const char *) open_path, "rb"); + else if (open_mode == TPDD_OPEN_MODE_READ_WRITE) + m_refFd[m_activeFd] = fopen((const char *) open_path, "rb+"); + + // Test if the file was opened successfully + if (m_refFd[m_activeFd] == NULL) + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + else + { + // Save the open mode + m_mode[m_activeFd] = open_mode; + SendNormalReturn(TPDD_ERR_NONE); + } + } +} + +/* +=========================================================================== +Handles the Close opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeClose(void) +{ + // Test if last "open" was a directory open + if (m_lastOpenWasDir) + { + SendNormalReturn(TPDD_ERR_NONE); + } + + // Test if the active FD is open + else if (m_refFd[m_activeFd] == NULL) + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + else + { + // Close the file and mark it closed + fclose(m_refFd[m_activeFd]); + m_refFd[m_activeFd] = NULL; + + // Send normal return + SendNormalReturn(TPDD_ERR_NONE); + } +} + +/* +=========================================================================== +Handles the Read opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeRead(void) +{ + char fileData[128]; + int read_len, c; + + // Validate the file is opened and in the right mode + if (m_refFd[m_activeFd] == NULL) + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + else if (m_mode[m_activeFd] != TPDD_OPEN_MODE_READ && + m_mode[m_activeFd] != TPDD_OPEN_MODE_READ_WRITE) + SendNormalReturn(TPDD_ERR_OPEN_FMT_MISMATCH); + else + { + // File is open and in the correct mode. Read up to 128 bytes + read_len = fread(fileData, 1, sizeof(fileData), m_refFd[m_activeFd]); + + // Test for end-of-file + if (read_len == 0) + SendNormalReturn(TPDD_ERR_END_OF_FILE); + else + { + // Send the read file packet + m_txChecksum = 0; + TpddSendByte(TPDD_RET_READ_FILE); + TpddSendByte((unsigned char) read_len); + + // Loop for all data to be sent + for (c = 0; c < read_len; c++) + TpddSendByte(fileData[c]); + + // Send the checksum + TpddSendChecksum(); + } + } +} + +/* +=========================================================================== +Handles the Write opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeWrite(void) +{ + int write_len; + + write_len = m_length; + + // Validate the file is opened and in the right mode + if (m_refFd[m_activeFd] == NULL) + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + else if (m_mode[m_activeFd] == TPDD_OPEN_MODE_READ) + SendNormalReturn(TPDD_ERR_OPEN_FMT_MISMATCH); + else + { + // File is open and in the correct mode. Read up to 128 bytes + write_len = fwrite(&m_rxBuffer[TPDD_PKT_DATA_INDEX], 1, m_length, m_refFd[m_activeFd]); + + // Test for end-of-file + if (write_len == 0) + SendNormalReturn(TPDD_ERR_DISK_FULL); + else + SendNormalReturn(TPDD_ERR_NONE); + } +} + +/* +=========================================================================== +Handles the Delete opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeDelete(void) +{ + MString delFile; + int ret; + + // Test if last reference was a directory + if (m_refIsDirectory) + { + // Request to remove a directory. Test if "PARENT.<>" + if (m_dirRef == "PARENT.<>") + { + // Just send normal return + SendNormalReturn(TPDD_ERR_NONE); + return; + } + + // Construct the path of the file to delete + delFile = m_sRootDir + m_curDir + m_dirRef; + +#ifdef WIN32 +#else + ret = rmdir((const char *) delFile); + if (ret == 0) + SendNormalReturn(TPDD_ERR_NONE); + else + { + // Send error based on errno + } +#endif + } + else + { + // Request to delete a file. Construct the path of the file to delete + delFile = m_sRootDir + m_curDir + m_dirRef; +#ifdef WIN32 + ret = DeleteFile((const char *) delFile); + if (ret) + SendNormalReturn(TPDD_ERR_NONE); + else + { + // Send error based on GetLastError() + if (GetLastError() == ERROR_FILE_NOT_FOUND) + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + else + SendNormalReturn(TPDD_ERR_DISK_WRITE_PROT); + } +#else + ret = unlink((const char *) delFile); + if (ret == 0) + SendNormalReturn(TPDD_ERR_NONE); + else + { + // Send error based on errno + if (errno == ENOENT) + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + else + SendNormalReturn(TPDD_ERR_DISK_WRITE_PROT); + } +#endif + } +} + +/* +=========================================================================== +Handles the Format opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeFormat(void) +{ + // Just send a normal return with no error + SendNormalReturn(TPDD_ERR_NONE); +} + +/* +=========================================================================== +Handles the Drive Status opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeDriveStatus(void) +{ + // Just send a normal return with no error + SendNormalReturn(TPDD_ERR_NONE); +} + +/* +=========================================================================== +Handles the Id opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeId(void) +{ + // Test if a TS-DOS DME request was received previously + if (m_tsdosDmeStart) + { + // Send a DME Response and flag to expect a coule of 0x0D + m_tsdosDmeReq = 1; + SendDmeResponse(); + } + else + { + // Send the drive ID + SendToHost("NADSBox"); + } +} + +/* +=========================================================================== +Handles the Rename opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeRename(void) +{ + MString old_filename, new_filename; + MString temp; + int ret, idx; + + // Test if last reference was a directory + if (m_refIsDirectory) + { + // Request to rename a directory. Test if "PARENT.<>" + if (m_dirRef == "PARENT.<>") + { + // Just send normal return + SendNormalReturn(TPDD_ERR_NONE); + return; + } + } + + // Validate the length + if (m_length != 25) + { + SendNormalReturn(TPDD_ERR_PARAM_ERR); + return; + } + + // Get the new filename + new_filename = m_sRootDir + m_curDir; + idx = TPDD_PKT_DATA_INDEX; + const int end = TPDD_PKT_DATA_INDEX + 24; // Max filename len + while (m_rxBuffer[idx] != ' ' && m_rxBuffer[idx] != '\0' && idx < end) + new_filename += (char) m_rxBuffer[idx++]; + + // Skip spaces + while (m_rxBuffer[idx] == ' ' && idx < end) + idx++; + + // Now append the extension if not a directory + if (idx < end && m_rxBuffer[idx] == '.') + { + // Test if this is a directory reference or not + if (m_rxBuffer[idx+1] != '<') + { + // Not a directory reference. Append the file extension + new_filename += (char) m_rxBuffer[idx++]; + while (idx != ' ' && idx != '\0' && idx < end) + new_filename += (char) m_rxBuffer[idx++]; + } + } + + // Construct the path of the old filename + old_filename = m_sRootDir + m_curDir + m_dirRef; + +#ifdef WIN32 + ret = rename((const char *) old_filename, (const char *) new_filename); + if (ret == 0) + SendNormalReturn(TPDD_ERR_NONE); + else + { + // Send error based on GetLastError() + if (GetLastError() == ERROR_FILE_NOT_FOUND) + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + else + SendNormalReturn(TPDD_ERR_DISK_WRITE_PROT); + } +#else + ret = rename((const char *) old_filename, (const char *) new_filename); + if (ret == 0) + SendNormalReturn(TPDD_ERR_NONE); + else + { + // Send error based on errno + if (errno == ENOENT) + SendNormalReturn(TPDD_ERR_NONEXISTANT_FILE); + else + SendNormalReturn(TPDD_ERR_DISK_WRITE_PROT); + } +#endif +} + +/* +=========================================================================== +Handles the Drive Condition opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeDriveCond(void) +{ + // Clear the TX checksum + m_txChecksum = 0; + TpddSendByte(TPDD_RET_CONDITION); + TpddSendByte(1); // Length is 1 + TpddSendByte(0); // Condition - all ok + TpddSendChecksum(); +} + +/* +=========================================================================== +Handles the Seek opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeSeek(void) +{ + int seek_mode, seek_offset; + + // Validate the length and seek mode + if (m_length != 5 || m_rxBuffer[TPDD_PKT_DATA_INDEX] > TPDD_SEEK_END) + { + // Send error condition + SendNormalReturn(TPDD_ERR_PARAM_ERR); + return; + } + + // Validate the file is open and in the right mode + if (m_refFd[m_activeFd] == NULL) + { + // Send error code + SendNormalReturn(TPDD_ERR_OPEN_FMT_MISMATCH); + return; + } + + // Get the seek mode and length + switch (m_rxBuffer[TPDD_PKT_DATA_INDEX]) + { + case TPDD_SEEK_SET: seek_mode = SEEK_SET; break; + case TPDD_SEEK_CUR: seek_mode = SEEK_CUR; break; + case TPDD_SEEK_END: seek_mode = SEEK_END; break; + default: seek_mode = SEEK_SET; break; + } + seek_offset = ((unsigned char) m_rxBuffer[TPDD_PKT_DATA_INDEX+1]) | + ((unsigned char) m_rxBuffer[TPDD_PKT_DATA_INDEX+2] << 8) | + ((unsigned char) m_rxBuffer[TPDD_PKT_DATA_INDEX+3] << 16) | + ((unsigned char) m_rxBuffer[TPDD_PKT_DATA_INDEX+4] << 24); + + // Perform the seek + fseek(m_refFd[m_activeFd], seek_mode, seek_offset); + SendNormalReturn(TPDD_ERR_NONE); +} + +/* +=========================================================================== +Handles the Tell opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeTell(void) +{ + int pos; + + // Validate the file is open and in the right mode + if (m_refFd[m_activeFd] == NULL) + { + // Send error code + SendNormalReturn(TPDD_ERR_OPEN_FMT_MISMATCH); + return; + } + + // Get the current file position + pos = ftell(m_refFd[m_activeFd]); + + // Clear the txChecksum and start the packet + m_txChecksum = 0; + TpddSendByte(TPDD_RET_TELL); + TpddSendByte(4); // Length is 4 bytes offset data + TpddSendByte(pos & 0xFF); // Send LSB + TpddSendByte((pos >> 8) & 0xFF); + TpddSendByte((pos >> 16) & 0xFF); + TpddSendByte((pos >> 24) & 0xFF); // Send MSB + TpddSendChecksum(); +} + +/* +=========================================================================== +Handles the SetExtended opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeSetExtended(void) +{ + SendNormalReturn(TPDD_ERR_NONE); +} + +/* +=========================================================================== +Handles the QueryExtended opcode + +The QueryExtended opcode parameter will be a NULL terminated string with +a space seperated list of extended options being queried, such as: + + NM BR CL Which is requesting Name (of server), Baud Rate and + Condensed List support + +The proper response is a RET_QUERY_EXTENDED packet that looks like: + + 0: 0x14 + 1: Length byte + 2-n: NM=NADSBox BR=9600,19200,38400,57600,76800,115200,230400 CL:Y \0 + N+1: Checksum + +=========================================================================== +*/ +void VTTpddServer::OpcodeQueryExtended(void) +{ + MString resp; + const char *ptr; + int len, c; + + // TPDD_RET_QUERY_EXTENDED + ptr = strtok(&m_rxBuffer[TPDD_PKT_DATA_INDEX], " "); + + // Loop for all entries in in opcode parameter list + while (ptr != NULL) + { + // Add this extended parameter to the response + resp += ptr; + + if (strcmp(ptr, "NM") == 0) + // Provide the our Server Name + resp += (char *) "=VTNADS"; + else if (strcmp(ptr, "BR") == 0) + // Provide list of virtual baud rates we support + resp += (char *) "=38400,57600,76800,115200,230400"; + else if (strcmp(ptr, "CL") == 0) + // Indicate Condensed List API supported + resp += (char *) ":Y"; + else + // Anything else we don't support so respond "N"ot supported + resp += (char *) ":N"; + + // Get pointer to next extended parameter in list + ptr = strtok(NULL, " "); + + // Add a space separator if there are more parameters in the list + if (ptr != NULL) + resp += (char *) " "; + } + + // Okay now send out the response + m_txChecksum = 0; + len = resp.GetLength() + 1; + + // Send API code + TpddSendByte(TPDD_RET_QUERY_EXTENDED); + TpddSendByte(len); + + // Send out the response dat + ptr = (const char *) resp; + for (c = 0; c < len; c++) + { + // Send to host and calc checksum + TpddSendByte(*ptr++); + } + + // Now send the checksum + TpddSendChecksum(); +} + +/* +=========================================================================== +Handles the CondensedList opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeCondensedList(void) +{ +} + +/* +=========================================================================== +Handles the Mystery 0x23 opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeMystery23(void) +{ + const char op23Table[] = "\x14\x0F\x41\x10\x01\x00\x50\x05\x00\x02\x00\x28\x00\xE1\x00\x00\x00"; + const char op23Len = sizeof(op23Table)-1; + int c; + + // Send bytes from the table + m_txChecksum = 0; + for (c = 0; c < op23Len; c++) + { + // Send to host and calc checksum + TpddSendByte(op23Table[c]); + } + + // Now send the checksum + TpddSendChecksum(); +} + +/* +=========================================================================== +Handles the Mystery 0x31 opcode +=========================================================================== +*/ +void VTTpddServer::OpcodeMystery31(void) +{ + // Send mystery 31 response + m_txChecksum = 0; + TpddSendByte(0x38); + TpddSendByte(1); + TpddSendByte(0); + + // Now send the checksum + TpddSendChecksum(); +} + +/* +=========================================================================== +Sends a Normal Return packet. This is a packet with 4 bytes and an ID +of 12, length 1 with an error code and checksum. +=========================================================================== +*/ +void VTTpddServer::SendNormalReturn(unsigned char errCode) +{ + // Send a Normal Return + m_txChecksum = 0; + TpddSendByte(TPDD_RET_NORMAL); + TpddSendByte(1); + TpddSendByte(errCode); + + // Now send the checksum + TpddSendChecksum(); +} + +/* +=========================================================================== +Sends the DME response packet to the server +=========================================================================== +*/ +void VTTpddServer::SendDmeResponse(void) +{ + MString dir; + int c, len; + + // Send the start of the DME Resp packet + m_txChecksum = 0; + TpddSendByte(0x12); // Opcode + TpddSendByte(0x0B); // Length + TpddSendByte(0x00); // RESVD + + // Now send the 6-byte directory name + if (m_curDir == "/") + dir = "ROOT "; + else + { + // Find last '/' in the current directory + len = m_curDir.GetLength(); + if (m_curDir[len-1] == '/') + len--; + for (c = len-1; c >= 0; c--) + if (m_curDir[c] == '/') + break; + c++; + + // Now copy up to 6 bytes of the dir name + while (dir.GetLength() < 6 && c < len) + dir += (char) toupper(m_curDir[c++]); + // Space pad to 6 characters + while (dir.GetLength() < 6) + dir += ' '; + } + + // Add the ".<>" extension + dir += (char *) ".<> "; + + // Now send the filename + len = dir.GetLength(); + for (c = 0; c < len; c++) + TpddSendByte(dir[c]); + + // Now send the checksum + TpddSendChecksum(); +} + +/* +=========================================================================== +Change directory to the directory specified +=========================================================================== +*/ +int VTTpddServer::ChangeDirectory(MString& sDir) +{ + MString dirName; + int len = sDir.GetLength(); + + // Strip any trailing ".<>" + if (sDir.Right(3) == ".<>") + dirName = sDir.Left(len - 3); + else + dirName = sDir; + dirName.Trim(); + + // Now change directory + return ChangeDirectory((const char *) dirName); +} + +/* +=========================================================================== +Change directory to the directory specified +=========================================================================== +*/ +int VTTpddServer::ChangeDirectory(const char *pDir) +{ + int ret = 0; + MString find_name; + + // Test if changing to parent directory + if (strcmp(pDir, "..") == 0) + { + // Ensure we aren't at root already + if (m_curDir != "/") + { + // Search backward for the last '/' + int idx = m_curDir.GetLength() - 2; + while (idx >= 0 && m_curDir[idx] != '/') + idx--; + idx++; + m_curDir = m_curDir.Left(idx); + ret = 1; + } + else + ret = 0; + } + else if (strcmp(pDir, ".") == 0) + return 1; + else + { + MString file_path = m_sRootDir + m_curDir; + dirent** e; + int num = fl_filename_list((const char *) file_path, &e ); + int i; + + // For directories, append the '/' for the search + find_name = pDir; + find_name += '/'; + + // If any files found + if (num > 0) + { + // Loop through all files in the list and perform a + // case insensitive compare + for ( i = 0; i < num; i++ ) + { + const char* name = e[i]->d_name; + + // Compare this file with the requested filename + if (strcasecmp(name, find_name) == 0) + { + // Directory found! Append directory to current directory + m_curDir += name; + ret = 1; + break; + } + } + } + + // Free the directory entries + for (i = 0; i < num; i++) + free((void*) (e[i])); + free((void*) e); + } + + // Delete existing dirent structure + ResetDirent(); + + return ret; +} + +/* +=========================================================================== +Delete all entries in m_activeDir +=========================================================================== +*/ +void VTTpddServer::ResetDirent(void) +{ + int i; + + // Now free the list memory + for( i = 0; i < m_dirCount; i++ ) + free((void*) (m_activeDir[i])); + free((void*) m_activeDir); + + // Clear out the dirent + m_activeDir = NULL; + m_dirCount = 0; +} + +/* +=========================================================================== +Delete all entries in m_activeDir +=========================================================================== +*/ +int VTTpddServer::IsCmdlineState(void) +{ + return m_state == TPDD_STATE_CMDLINE; +} + +// vim: noet ts=4 sw=4 From 4c8afebd2ec6ca86060595511142ecef40f746c7 Mon Sep 17 00:00:00 2001 From: pettitkd Date: Tue, 6 Aug 2024 04:57:33 -0700 Subject: [PATCH 326/327] Fixed latent bug in Model 200 Display code where clearing a dot on the screen clears multiple dots. --- src/display.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/display.cpp b/src/display.cpp index d4f2387..1f55d5b 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -4913,7 +4913,8 @@ void T200_Disp::Command(int instruction, uchar data) case RAM_BIT_CLR: /* Clear the bit specified by data at cursaddr */ /* First calculate the AND mask */ - mask = 0xFE << data; + //mask = 0xFE << data; + mask = ~(0x01 << data); /* Draw new data on the LCD */ SetByte(cursaddr, 0, m_ram[cursaddr] & mask); From 1cfe51c1f88f221312c634bcf708c8344358a01c Mon Sep 17 00:00:00 2001 From: "Curt J. Sampson" Date: Sun, 10 Nov 2024 01:48:53 +0900 Subject: [PATCH 327/327] src/linker.cpp: Fix conflicting `path` definition This applies the patch from but report [9] to fix the conflicting `path` global between m100emu.cpp and linker.cpp. This is a fairly old bug; the patch was submitted 2022-11-08. It's not clear why this hasn't been applied, but the code seems to be seeing minimal maintenance. (There's been only one commit since 2021-05-22. [9]: https://sourceforge.net/p/virtualt/bugs/9/ --- src/linker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/linker.cpp b/src/linker.cpp index 8cb047d..e4eb1d9 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -24,7 +24,7 @@ Written: 11/13/09 Kenneth D. Pettit extern "C" { #include "intelhex.h" -char path[512]; +static char linkpath[512]; } static const char *gLoaderCode[] = { @@ -383,7 +383,7 @@ MString VTLinker::PreprocessDirectory(const char *pDir) if (strncmp(pDir, "{$VT_ROOT}", 10) == 0) { // Substitute the VirtualT path - temp = path; + temp = linkpath; temp += pDir[10]; } else if (strncmp(pDir, "{$VT_PROJ}", 10) == 0)